diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs deleted file mode 100644 index 3bfdb7286..000000000 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network -{ - public class ArrowPacketTests - { - [Fact] - public void TestCancelArrow() - { - var data = new CancelArrow().Compile(); - - Span expectedData = stackalloc byte[6]; - var pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID - expectedData.Write(ref pos, (byte)0); // Command - expectedData.Write(ref pos, 0xFFFFFFFF); // X, Y - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(100, 10)] - [InlineData(100000, 100000)] - public void TestSetArrow(int x, int y) - { - var data = new SetArrow(x, y).Compile(); - - Span expectedData = stackalloc byte[6]; - var pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID - expectedData.Write(ref pos, (byte)0x01); // Command - expectedData.Write(ref pos, (ushort)x); - expectedData.Write(ref pos, (ushort)y); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(100, 10)] - [InlineData(100000, 100000)] - public void TestCancelArrowHS(int x, int y) - { - Serial serial = 0x01; - var data = new CancelArrowHS(x, y, serial).Compile(); - - Span expectedData = stackalloc byte[10]; - var pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Command -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)x); - expectedData.Write(ref pos, (ushort)y); - expectedData.Write(ref pos, serial); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(100, 10)] - [InlineData(100000, 100000)] - public void TestSetArrowHS(int x, int y) - { - Serial serial = 0x01; - var data = new SetArrowHS(x, y, serial).Compile(); - - Span expectedData = stackalloc byte[10]; - var pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID - expectedData.Write(ref pos, (byte)0x01); // Command - expectedData.Write(ref pos, (ushort)x); - expectedData.Write(ref pos, (ushort)y); - expectedData.Write(ref pos, serial); - - AssertThat.Equal(data, expectedData); - } - } -} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs index a34be403a..685a6b761 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs @@ -13,22 +13,13 @@ namespace Server.Tests.Network Serial attacker = 0x1000; Serial defender = 0x2000; - var data = new Swing(attacker, defender).Compile(); + var expected = new Swing(attacker, defender).Compile(); - Span expectedData = stackalloc byte[10]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendSwing(attacker, defender); - expectedData.Write(ref pos, (byte)0x2F); // Packet ID -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, attacker); - expectedData.Write(ref pos, defender); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Theory] @@ -36,45 +27,27 @@ namespace Server.Tests.Network [InlineData(false)] public void TestSetWarMode(bool warmode) { - var data = new SetWarMode(warmode).Compile(); + var expected = new SetWarMode(warmode).Compile(); - Span expectedData = stackalloc byte[5]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendSetWarMode(warmode); - expectedData.Write(ref pos, (byte)0x72); // Packet ID - expectedData.Write(ref pos, warmode); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, (byte)0x32); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] public void TestChangeCombatant() { - Serial combatant = 0x1000; + Serial serial = 0x1024; - var data = new ChangeCombatant(combatant).Compile(); + var expected = new ChangeCombatant(serial).Compile(); - Span expectedData = stackalloc byte[5]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendChangeCombatant(serial); - expectedData.Write(ref pos, (byte)0xAA); // Packet ID - expectedData.Write(ref pos, combatant); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } } } diff --git a/Projects/Server/Network/Packets/CombatPackets.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPackets.cs similarity index 87% rename from Projects/Server/Network/Packets/CombatPackets.cs rename to Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPackets.cs index c42eab6bb..9d082bb04 100644 --- a/Projects/Server/Network/Packets/CombatPackets.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPackets.cs @@ -27,9 +27,6 @@ namespace Server.Network public sealed class SetWarMode : Packet { - public static readonly Packet InWarMode = SetStatic(new SetWarMode(true)); - public static readonly Packet InPeaceMode = SetStatic(new SetWarMode(false)); - public SetWarMode(bool mode) : base(0x72, 5) { Stream.Write(mode); @@ -37,8 +34,6 @@ namespace Server.Network Stream.Write((byte)0x32); Stream.Write((byte)0x00); } - - public static Packet Instantiate(bool mode) => mode ? InWarMode : InPeaceMode; } public sealed class ChangeCombatant : Packet diff --git a/Projects/Server.Tests/AssertExtensions.cs b/Projects/Server.Tests/Utility/AssertExtensions.cs similarity index 100% rename from Projects/Server.Tests/AssertExtensions.cs rename to Projects/Server.Tests/Utility/AssertExtensions.cs diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index 5ac033b25..a0684b99a 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -562,8 +562,6 @@ namespace Server private Poison m_Poison; private Prompt m_Prompt; private ObjectPropertyList m_PropertyList; - - private QuestArrow m_QuestArrow; private Race m_Race; private Region m_Region; @@ -955,7 +953,7 @@ namespace Server if (m_Combatant == null) { - m_NetState?.Send(new ChangeCombatant(Serial.Zero)); + m_NetState?.SendChangeCombatant(Serial.Zero); m_ExpireCombatant?.Stop(); m_CombatTimer?.Stop(); @@ -964,7 +962,7 @@ namespace Server } else { - m_NetState?.Send(new ChangeCombatant(m_Combatant.Serial)); + m_NetState?.SendChangeCombatant(m_Combatant.Serial); m_ExpireCombatant ??= Timer.DelayCall(ExpireCombatantDelay, ExpireCombatant); m_ExpireCombatant.Start(); @@ -1450,10 +1448,7 @@ namespace Server m_Warmode = value; Delta(MobileDelta.Flags); - if (m_NetState != null) - { - Send(SetWarMode.Instantiate(value)); - } + m_NetState?.SendSetWarMode(value); if (!m_Warmode) { @@ -1505,8 +1500,6 @@ namespace Server m_Target?.Cancel(this, TargetCancelType.Disconnected); - QuestArrow = null; - m_Spell?.OnConnectionChanged(); // if (m_Spell != null) @@ -2010,20 +2003,6 @@ namespace Server [CommandProperty(AccessLevel.GameMaster)] public bool Mounted => Mount != null; - public QuestArrow QuestArrow - { - get => m_QuestArrow; - set - { - if (m_QuestArrow != value) - { - m_QuestArrow?.Stop(); - - m_QuestArrow = value; - } - } - } - public virtual bool CanTarget => true; public virtual bool ClickTitle => true; @@ -4504,8 +4483,6 @@ namespace Server } } - public void ClearQuestArrow() => m_QuestArrow = null; - public void ClearTarget() => m_Target = null; public Target BeginTarget(int range, bool allowGround, TargetFlags flags, TargetCallback callback) => diff --git a/Projects/Server/Network/Packets/IncomingAccountPackets.cs b/Projects/Server/Network/Packets/IncomingAccountPackets.cs index 82d55f793..5b4c22812 100644 --- a/Projects/Server/Network/Packets/IncomingAccountPackets.cs +++ b/Projects/Server/Network/Packets/IncomingAccountPackets.cs @@ -331,7 +331,7 @@ namespace Server.Network state.Send(new MobileIncoming(m, m)); // state.Send( new MobileAttributes( m ) ); state.Send(new MobileStatus(m, m)); - state.Send(SetWarMode.Instantiate(m.Warmode)); + state.SendSetWarMode(m.Warmode); m.SendEverything(); @@ -339,7 +339,7 @@ namespace Server.Network state.Send(new MobileUpdate(m)); // state.Send( new MobileAttributes( m ) ); state.Send(new MobileStatus(m, m)); - state.Send(SetWarMode.Instantiate(m.Warmode)); + state.SendSetWarMode(m.Warmode); state.Send(new MobileIncoming(m, m)); } else if (state.StygianAbyss) @@ -354,7 +354,7 @@ namespace Server.Network state.Send(new MobileIncomingSA(m, m)); // state.Send( new MobileAttributes( m ) ); state.Send(new MobileStatus(m, m)); - state.Send(SetWarMode.Instantiate(m.Warmode)); + state.SendSetWarMode(m.Warmode); m.SendEverything(); @@ -362,7 +362,7 @@ namespace Server.Network state.Send(new MobileUpdate(m)); // state.Send( new MobileAttributes( m ) ); state.Send(new MobileStatus(m, m)); - state.Send(SetWarMode.Instantiate(m.Warmode)); + state.SendSetWarMode(m.Warmode); state.Send(new MobileIncomingSA(m, m)); } else @@ -377,7 +377,7 @@ namespace Server.Network state.Send(new MobileIncomingOld(m, m)); // state.Send( new MobileAttributes( m ) ); state.Send(new MobileStatus(m, m)); - state.Send(SetWarMode.Instantiate(m.Warmode)); + state.SendSetWarMode(m.Warmode); m.SendEverything(); @@ -385,7 +385,7 @@ namespace Server.Network state.Send(new MobileUpdateOld(m)); // state.Send( new MobileAttributes( m ) ); state.Send(new MobileStatus(m, m)); - state.Send(SetWarMode.Instantiate(m.Warmode)); + state.SendSetWarMode(m.Warmode); state.Send(new MobileIncomingOld(m, m)); } diff --git a/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs b/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs index 003a69b3f..6c503e4cf 100644 --- a/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs +++ b/Projects/Server/Network/Packets/IncomingExtendedCommandPackets.cs @@ -42,7 +42,6 @@ namespace Server.Network RegisterExtended(0x05, false, ScreenSize); RegisterExtended(0x06, true, PartyMessage); - RegisterExtended(0x07, true, QuestArrow); RegisterExtended(0x09, true, DisarmRequest); RegisterExtended(0x0A, true, StunRequest); RegisterExtended(0x0B, false, Language); @@ -217,20 +216,6 @@ namespace Server.Network PartyCommands.Handler?.OnDecline(state.Mobile, World.FindMobile(reader.ReadUInt32())); } - public static void QuestArrow(NetState state, CircularBufferReader reader) - { - var from = state.Mobile; - - if (from == null) - { - return; - } - - var rightClick = reader.ReadBoolean(); - - from.QuestArrow?.OnClick(rightClick); - } - public static void Animate(NetState state, CircularBufferReader reader) { var from = state.Mobile; diff --git a/Projects/Server/Network/Packets/OutgoingCombatPackets.cs b/Projects/Server/Network/Packets/OutgoingCombatPackets.cs new file mode 100644 index 000000000..1e9578c8e --- /dev/null +++ b/Projects/Server/Network/Packets/OutgoingCombatPackets.cs @@ -0,0 +1,67 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: OutgoingCombatPackets.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.Buffers; + +namespace Server.Network +{ + public static class OutgoingCombatPackets + { + public static void SendSwing(this NetState ns, Serial attacker, Serial defender) + { + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0x2F); // Packet ID + writer.Write((byte)0); + writer.Write(attacker); + writer.Write(defender); + + ns.Send(ref buffer, 10); + } + + public static void SendSetWarMode(this NetState ns, bool warmode) + { + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0x72); // Packet ID + // Warmode, 0x00, 0x32, 0x00 + writer.Write(warmode ? 0x01003200 : 0x00003200); + + ns.Send(ref buffer, 5); + } + + public static void SendChangeCombatant(this NetState ns, Serial combatant) + { + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0xAA); // Packet ID + writer.Write(combatant); + + ns.Send(ref buffer, 5); + } + } +} diff --git a/Projects/UOContent.Tests/Network/Packets/ArrowPacketTests.cs b/Projects/UOContent.Tests/Network/Packets/ArrowPacketTests.cs new file mode 100644 index 000000000..0f769f6cd --- /dev/null +++ b/Projects/UOContent.Tests/Network/Packets/ArrowPacketTests.cs @@ -0,0 +1,72 @@ +using System; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network +{ + public class ArrowPacketTests + { + [Fact] + public void TestCancelArrow() + { + var expected = new CancelArrow().Compile(); + + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendCancelArrow(0, 0, Serial.Zero); + + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(100, 10)] + [InlineData(100000, 100000)] + public void TestSetArrow(int x, int y) + { + var expected = new SetArrow(x, y).Compile(); + + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendSetArrow(x, y, Serial.Zero); + + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(100, 10)] + [InlineData(100000, 100000)] + public void TestCancelArrowHS(int x, int y) + { + Serial serial = 0x1024; + + var expected = new CancelArrowHS(x, y, serial).Compile(); + + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.ProtocolChanges = ProtocolChanges.HighSeas; + ns.SendCancelArrow(x, y, serial); + + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(100, 10)] + [InlineData(100000, 100000)] + public void TestSetArrowHS(int x, int y) + { + Serial serial = 0x1024; + + var expected = new SetArrowHS(x, y, serial).Compile(); + + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.ProtocolChanges = ProtocolChanges.HighSeas; + ns.SendSetArrow(x, y, serial); + + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); + } + } +} diff --git a/Projects/Server/Network/Packets/ArrowPackets.cs b/Projects/UOContent.Tests/Network/Packets/ArrowPackets.cs similarity index 100% rename from Projects/Server/Network/Packets/ArrowPackets.cs rename to Projects/UOContent.Tests/Network/Packets/ArrowPackets.cs diff --git a/Projects/UOContent.Tests/UOContent.Tests.csproj b/Projects/UOContent.Tests/UOContent.Tests.csproj index a7a469b30..60d5cf2f3 100644 --- a/Projects/UOContent.Tests/UOContent.Tests.csproj +++ b/Projects/UOContent.Tests/UOContent.Tests.csproj @@ -8,6 +8,7 @@ + diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.cs index 1b3fc7760..3143d988e 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.cs @@ -744,10 +744,7 @@ namespace Server.Items { attacker.DisruptiveAction(); - if (attacker.NetState != null) - { - attacker.Send(new Swing(attacker.Serial, defender.Serial)); - } + attacker.NetState?.SendSwing(attacker.Serial, defender.Serial); if (attacker is BaseCreature bc) { diff --git a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs index 78c768692..ce47d2c01 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs @@ -60,8 +60,7 @@ namespace Server.Items // WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker ); // Make sure we've been standing still for .25/.5/1 second depending on Era - if (Core.TickCount - attacker.LastMoveTime >= (Core.SE ? 250 : - Core.AOS ? 500 : 1000) || + if (Core.TickCount - attacker.LastMoveTime >= (Core.SE ? 250 : Core.AOS ? 500 : 1000) || Core.AOS && WeaponAbility.GetCurrentAbility(attacker) is MovingShot) { var canSwing = true; @@ -84,7 +83,7 @@ namespace Server.Items if (canSwing && attacker.HarmfulCheck(defender)) { attacker.DisruptiveAction(); - attacker.Send(new Swing(attacker.Serial, defender.Serial)); + attacker.NetState?.SendSwing(attacker.Serial, defender.Serial); if (OnFired(attacker, defender)) { diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index 3854365b6..58b3e594d 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -196,14 +196,16 @@ namespace Server.Mobiles private bool m_NoDeltaRecursion; - private int - m_NonAutoreinsuredItems; // number of items that could not be automatically reinsured because gold in bank was not enough + // number of items that could not be automatically reinsured because gold in bank was not enough + private int m_NonAutoreinsuredItems; private DateTime m_SavagePaintExpiration; private TimeSpan m_ShortTermElapse; private DateTime[] m_StuckMenuUses; + private QuestArrow m_QuestArrow; + public PlayerMobile() { AutoStabled = new List(); @@ -794,6 +796,23 @@ namespace Server.Mobiles public HonorContext ReceivedHonorContext { get; set; } + public QuestArrow QuestArrow + { + get => m_QuestArrow; + set + { + if (m_QuestArrow != value) + { + m_QuestArrow?.Stop(); + + m_QuestArrow = value; + } + } + } + + + public void ClearQuestArrow() => m_QuestArrow = null; + public override void ToggleFlying() { if (Race != Race.Gargoyle) @@ -1627,6 +1646,7 @@ namespace Server.Mobiles pm.Quest?.StopTimer(); pm.SpeechLog = null; + pm.ClearQuestArrow(); pm.LastOnline = DateTime.UtcNow; } diff --git a/Projects/UOContent/Skills/Tracking/OutgoingArrowPackets.cs b/Projects/UOContent/Skills/Tracking/OutgoingArrowPackets.cs new file mode 100644 index 000000000..bedb1bb5e --- /dev/null +++ b/Projects/UOContent/Skills/Tracking/OutgoingArrowPackets.cs @@ -0,0 +1,61 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: OutgoingArrowPackets.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.Buffers; +using System.Runtime.CompilerServices; + +namespace Server.Network +{ + public static class OutgoingArrowPackets + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SendCancelArrow(this NetState ns, int x, int y, Serial s) => ns.SendArrow(0, x, y, s); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SendSetArrow(this NetState ns, int x, int y, Serial s) => ns.SendArrow(1, x, y, s); + + public static void SendArrow(this NetState ns, byte command, int x, int y, Serial s) + { + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0xBA); // Packet ID + writer.Write(command); + + + if (ns.HighSeas) + { + writer.Write((short)x); + writer.Write((short)y); + writer.Write(s); + } + else if (command == 1) + { + writer.Write((short)x); + writer.Write((short)y); + } + else + { + writer.Write((short)-1); + writer.Write((short)-1); + } + + ns.Send(ref buffer, writer.Position); + } + } +} diff --git a/Projects/Server/QuestArrow.cs b/Projects/UOContent/Skills/Tracking/QuestArrow.cs similarity index 54% rename from Projects/Server/QuestArrow.cs rename to Projects/UOContent/Skills/Tracking/QuestArrow.cs index 5dfee5fe7..c41bd37d3 100644 --- a/Projects/Server/QuestArrow.cs +++ b/Projects/UOContent/Skills/Tracking/QuestArrow.cs @@ -1,22 +1,23 @@ +using Server.Mobiles; using Server.Network; namespace Server { public class QuestArrow { - public QuestArrow(Mobile m, Mobile t) + public QuestArrow(PlayerMobile m, Mobile t) { Running = true; Mobile = m; Target = t; } - public QuestArrow(Mobile m, Mobile t, int x, int y) : this(m, t) + public QuestArrow(PlayerMobile m, Mobile t, int x, int y) : this(m, t) { Update(x, y); } - public Mobile Mobile { get; } + public PlayerMobile Mobile { get; } public Mobile Target { get; } @@ -34,21 +35,7 @@ namespace Server return; } - var ns = Mobile.NetState; - - if (ns == null) - { - return; - } - - if (ns.HighSeas) - { - ns.Send(new SetArrowHS(x, y, Target.Serial)); - } - else - { - ns.Send(new SetArrow(x, y)); - } + Mobile.NetState?.SendSetArrow(x, y, Target.Serial); } public void Stop() @@ -64,20 +51,7 @@ namespace Server } Mobile.ClearQuestArrow(); - - var ns = Mobile.NetState; - - if (ns != null) - { - if (ns.HighSeas) - { - ns.Send(new CancelArrowHS(x, y, Target.Serial)); - } - else - { - ns.Send(new CancelArrow()); - } - } + Mobile.NetState?.SendCancelArrow(x, y, Target.Serial); Running = false; OnStop(); diff --git a/Projects/UOContent/Skills/Tracking/TrackArrow.cs b/Projects/UOContent/Skills/Tracking/TrackArrow.cs new file mode 100644 index 000000000..382ff1ab2 --- /dev/null +++ b/Projects/UOContent/Skills/Tracking/TrackArrow.cs @@ -0,0 +1,41 @@ +using Server.Mobiles; + +namespace Server.SkillHandlers +{ + public class TrackArrow : QuestArrow + { + private readonly Timer m_Timer; + private Mobile m_From; + + public TrackArrow(PlayerMobile from, Mobile target, int range) : base(from, target) + { + m_From = from; + m_Timer = new TrackTimer(from, target, range, this); + m_Timer.Start(); + } + + public override void OnClick(bool rightClick) + { + if (rightClick) + { + Tracking.ClearTrackingInfo(m_From); + + m_From = null; + + Stop(); + } + } + + public override void OnStop() + { + m_Timer.Stop(); + + if (m_From != null) + { + Tracking.ClearTrackingInfo(m_From); + + m_From.SendLocalizedMessage(503177); // You have lost your quarry. + } + } + } +} diff --git a/Projects/UOContent/Skills/Tracking/TrackTimer.cs b/Projects/UOContent/Skills/Tracking/TrackTimer.cs new file mode 100644 index 000000000..db8cdfd55 --- /dev/null +++ b/Projects/UOContent/Skills/Tracking/TrackTimer.cs @@ -0,0 +1,50 @@ +using System; + +namespace Server.SkillHandlers +{ + public class TrackTimer : Timer + { + private readonly QuestArrow m_Arrow; + private readonly Mobile m_From; + private readonly int m_Range; + private readonly Mobile m_Target; + private int m_LastX, m_LastY; + + public TrackTimer(Mobile from, Mobile target, int range, QuestArrow arrow) : base( + TimeSpan.FromSeconds(0.25), + TimeSpan.FromSeconds(2.5) + ) + { + m_From = from; + m_Target = target; + m_Range = range; + + m_Arrow = arrow; + } + + protected override void OnTick() + { + if (!m_Arrow.Running) + { + Stop(); + return; + } + + if (m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || + !m_From.InRange(m_Target, m_Range) || m_Target.Hidden && m_Target.AccessLevel > m_From.AccessLevel) + { + m_Arrow.Stop(); + Stop(); + return; + } + + if (m_LastX != m_Target.X || m_LastY != m_Target.Y) + { + m_LastX = m_Target.X; + m_LastY = m_Target.Y; + + m_Arrow.Update(); + } + } + } +} diff --git a/Projects/UOContent/Skills/Tracking.cs b/Projects/UOContent/Skills/Tracking/Tracking.cs similarity index 78% rename from Projects/UOContent/Skills/Tracking.cs rename to Projects/UOContent/Skills/Tracking/Tracking.cs index b9fd57f03..929c67847 100644 --- a/Projects/UOContent/Skills/Tracking.cs +++ b/Projects/UOContent/Skills/Tracking/Tracking.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Server.Gumps; +using Server.Mobiles; using Server.Network; using Server.Spells; using Server.Spells.Necromancy; @@ -12,18 +13,32 @@ namespace Server.SkillHandlers { private static readonly Dictionary m_Table = new Dictionary(); - public static void Initialize() + public static void Configure() { + IncomingExtendedCommandPackets.RegisterExtended(0x07, true, QuestArrow); SkillInfo.Table[(int)SkillName.Tracking].Callback = OnUse; } + public static void QuestArrow(NetState state, CircularBufferReader reader) + { + if (state.Mobile is PlayerMobile from) + { + var rightClick = reader.ReadBoolean(); + + from.QuestArrow?.OnClick(rightClick); + } + } + public static TimeSpan OnUse(Mobile m) { - m.SendLocalizedMessage(1011350); // What do you wish to track? + if (m is PlayerMobile pm) + { + m.SendLocalizedMessage(1011350); // What do you wish to track? - m.CloseGump(); - m.CloseGump(); - m.SendGump(new TrackWhatGump(m)); + m.CloseGump(); + m.CloseGump(); + m.SendGump(new TrackWhatGump(pm)); + } return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill } @@ -73,10 +88,10 @@ namespace Server.SkillHandlers public class TrackWhatGump : Gump { - private readonly Mobile m_From; + private readonly PlayerMobile m_From; private readonly bool m_Success; - public TrackWhatGump(Mobile from) : base(20, 30) + public TrackWhatGump(PlayerMobile from) : base(20, 30) { m_From = from; m_Success = from.CheckSkill(SkillName.Tracking, 0.0, 21.1); @@ -126,12 +141,12 @@ namespace Server.SkillHandlers IsPlayer }; - private readonly Mobile m_From; + private readonly PlayerMobile m_From; private readonly List m_List; private readonly int m_Range; - private TrackWhoGump(Mobile from, List list, int range) : base(20, 30) + private TrackWhoGump(PlayerMobile from, List list, int range) : base(20, 30) { m_From = from; m_List = list; @@ -174,7 +189,7 @@ namespace Server.SkillHandlers } } - public static void DisplayTo(bool success, Mobile from, int type) + public static void DisplayTo(bool success, PlayerMobile from, int type) { if (!success) { @@ -333,87 +348,4 @@ namespace Server.SkillHandlers } } } - - public class TrackArrow : QuestArrow - { - private readonly Timer m_Timer; - private Mobile m_From; - - public TrackArrow(Mobile from, Mobile target, int range) : base(from, target) - { - m_From = from; - m_Timer = new TrackTimer(from, target, range, this); - m_Timer.Start(); - } - - public override void OnClick(bool rightClick) - { - if (rightClick) - { - Tracking.ClearTrackingInfo(m_From); - - m_From = null; - - Stop(); - } - } - - public override void OnStop() - { - m_Timer.Stop(); - - if (m_From != null) - { - Tracking.ClearTrackingInfo(m_From); - - m_From.SendLocalizedMessage(503177); // You have lost your quarry. - } - } - } - - public class TrackTimer : Timer - { - private readonly QuestArrow m_Arrow; - private readonly Mobile m_From; - private readonly int m_Range; - private readonly Mobile m_Target; - private int m_LastX, m_LastY; - - public TrackTimer(Mobile from, Mobile target, int range, QuestArrow arrow) : base( - TimeSpan.FromSeconds(0.25), - TimeSpan.FromSeconds(2.5) - ) - { - m_From = from; - m_Target = target; - m_Range = range; - - m_Arrow = arrow; - } - - protected override void OnTick() - { - if (!m_Arrow.Running) - { - Stop(); - return; - } - - if (m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || - !m_From.InRange(m_Target, m_Range) || m_Target.Hidden && m_Target.AccessLevel > m_From.AccessLevel) - { - m_Arrow.Stop(); - Stop(); - return; - } - - if (m_LastX != m_Target.X || m_LastY != m_Target.Y) - { - m_LastX = m_Target.X; - m_LastY = m_Target.Y; - - m_Arrow.Update(); - } - } - } }