diff --git a/GameServer/Geometry/Motion.cs b/GameServer/Geometry/Motion.cs index ab31fa4d7a..f3d1529602 100644 --- a/GameServer/Geometry/Motion.cs +++ b/GameServer/Geometry/Motion.cs @@ -2,77 +2,31 @@ namespace DOL.GS.Geometry; -public interface IMotion -{ - int StartTimeInMilliSeconds { get; } - Coordinate Start { get; init; } - Coordinate Destination { get; } - short Speed { get; init; } - Coordinate CurrentLocation { get; } - double FullDistance { get; } - double RemainingDistance { get; } - - Angle GetDirection(); -} - public class Motion { - public static IMotion Create(Position start, Coordinate destination, short withSpeed) - { - if (destination.Equals(Coordinate.Nowhere)) return new GoAheadMotion() { Start = start.Coordinate, Speed = withSpeed, Direction = start.Orientation }; - else if (start.Equals(destination)) return new GoAheadMotion() { Start = start.Coordinate, Speed = 0, Direction = start.Orientation }; - else return new MotionToDestination() { Start = start.Coordinate, Destination = destination, Speed = withSpeed }; - } -} + public static Motion Create(Position start, Coordinate destination, short withSpeed) + => new Motion() { Start = start, Destination = destination, Speed = withSpeed }; -public class MotionToDestination : IMotion -{ public int StartTimeInMilliSeconds { get; } = Environment.TickCount; - public Coordinate Start { get; init; } = Coordinate.Nowhere; + public Position Start { get; init; } = Position.Nowhere; public Coordinate Destination { get; init; } = Coordinate.Nowhere; public short Speed { get; init; } = 0; - public Coordinate CurrentLocation - => GetLocationAfter(Environment.TickCount - StartTimeInMilliSeconds); + public Position CurrentPosition + => GetPositonAfter(Environment.TickCount - StartTimeInMilliSeconds); public double FullDistance => Destination.DistanceTo(Start, ignoreZ: true); public double RemainingDistance => Destination.DistanceTo(CurrentPosition, ignoreZ: true); - public Coordinate GetLocationAfter(int elapsedTimeInMilliSeconds) + public Position GetPositonAfter(int elapsedTimeInMilliSeconds) { - if (Speed == 0) return Start; + if (Speed == 0 || Start.Coordinate == Destination) return Start; var distanceTravelled = Speed * elapsedTimeInMilliSeconds * 0.001; - if (distanceTravelled > FullDistance) return Destination; - - var progress = distanceTravelled / FullDistance; - if (progress > 1) return Destination; - else return Start + (Destination - Start) * progress; - } + if (Destination == Coordinate.Nowhere) return Start + Vector.Create(Start.Orientation, distanceTravelled); - public Angle GetDirection() - => Start.GetOrientationTo(Destination); -} + var movementVector = Destination - Start.Coordinate; + if (distanceTravelled > FullDistance) return Position.Create(Start.RegionID, Destination, movementVector.Orientation); -public class GoAheadMotion : IMotion -{ - public int StartTimeInMilliSeconds { get; } = Environment.TickCount; - public Coordinate Start { get; init; } = Coordinate.Nowhere; - public Coordinate Destination { get => Coordinate.Nowhere; } - public short Speed { get; init; } = 0; - public Angle Direction { get; init; } - - public Coordinate CurrentLocation - => GetLocationAfter(Environment.TickCount - StartTimeInMilliSeconds); - public double FullDistance => double.PositiveInfinity; - public double RemainingDistance => double.PositiveInfinity; - - public Coordinate GetLocationAfter(int elapsedTimeInMilliSeconds) - { - if (Speed == 0) return Start; - var timeElapsedInSeconds = elapsedTimeInMilliSeconds * 0.001; - var distanceTravelled = Speed * timeElapsedInSeconds; - return Start + Vector.Create(Direction, distanceTravelled); + return Start.With(movementVector.Orientation) + movementVector * (distanceTravelled / FullDistance); } - - public Angle GetDirection() => Direction; } \ No newline at end of file diff --git a/GameServer/Geometry/Position.cs b/GameServer/Geometry/Position.cs index 056ae2c158..7d141e886e 100644 --- a/GameServer/Geometry/Position.cs +++ b/GameServer/Geometry/Position.cs @@ -5,7 +5,7 @@ public struct Position private const ushort NO_REGION_ID = ushort.MaxValue; public ushort RegionID { get; init; } = 0; - public Coordinate Coordinate { get; init; } = Coordinate.Nowhere; + public Coordinate Coordinate { get; init; } = Coordinate.Zero; public Angle Orientation { get; init; } = Angle.Zero; public int X => Coordinate.X; diff --git a/GameServer/Geometry/Vector.cs b/GameServer/Geometry/Vector.cs index ab318d4e2d..5526ddadee 100644 --- a/GameServer/Geometry/Vector.cs +++ b/GameServer/Geometry/Vector.cs @@ -76,5 +76,5 @@ public override int GetHashCode() public static Vector operator -(Vector vecA, Vector vecB) => Create(vecA.X - vecB.X, vecA.Y - vecB.Y, vecA.Z - vecB.Z); - public static Vector Zero => Vector.Create(0, 0, 0); + public static readonly Vector Zero = Vector.Create(0, 0, 0); } \ No newline at end of file diff --git a/GameServer/gameobjects/GameLiving.cs b/GameServer/gameobjects/GameLiving.cs index 5feac02daf..227238271e 100644 --- a/GameServer/gameobjects/GameLiving.cs +++ b/GameServer/gameobjects/GameLiving.cs @@ -5744,34 +5744,34 @@ public int MovementStartTick public override Position Position { - get => Position.Create(CurrentRegionID, Motion.CurrentLocation, Motion.GetDirection()); - set { CurrentRegionID = value.RegionID; Motion = Geometry.Motion.Create(value, Motion.Destination, Motion.Speed); } + get => Motion.CurrentPosition; + set { CurrentRegionID = value.RegionID; Motion = Motion.Create(value, Motion.Destination, Motion.Speed); } } - protected virtual IMotion Motion { get; set; } = new GoAheadMotion(); + protected virtual Motion Motion { get; set; } = new Motion(); [Obsolete("Use .Position.X instead!")] public override int X { - set => Position = Position.Create(CurrentRegionID, coordinate: Motion.Start.With(x: value), Orientation); + set => Position = Motion.Start.With(x: value); } [Obsolete("Use .Position.Y instead!")] public override int Y { - set => Position = Position.Create(CurrentRegionID, coordinate: Motion.Start.With(y: value), Orientation); + set => Position = Motion.Start.With(y: value); } [Obsolete("Use .Position.Z instead!")] public override int Z { - set => Position = Position.Create(CurrentRegionID, coordinate: Motion.Start.With(z: value), Orientation); + set => Position = Motion.Start.With(z: value); } public override Angle Orientation { - get => Motion.GetDirection(); - set => Position = Position.Create(CurrentRegionID, Motion.Start, value); + get => Position.Orientation; + set => Position = Motion.Start.With(orientation: value); } public override ushort CurrentRegionID diff --git a/GameServer/gameobjects/GameNPC.cs b/GameServer/gameobjects/GameNPC.cs index ee09f1738a..ad027a0487 100644 --- a/GameServer/gameobjects/GameNPC.cs +++ b/GameServer/gameobjects/GameNPC.cs @@ -795,7 +795,7 @@ public ushort SpawnHeading public short ZSpeedFactor => (short)((Motion.Destination.Z - Motion.Start.Z) / Motion.FullDistance); - protected override IMotion Motion + protected override Motion Motion { set { diff --git a/GameServer/gameobjects/GamePlayer.cs b/GameServer/gameobjects/GamePlayer.cs index f64120fe16..a2f7d0cf89 100644 --- a/GameServer/gameobjects/GamePlayer.cs +++ b/GameServer/gameobjects/GamePlayer.cs @@ -10329,7 +10329,7 @@ public Zone LastPositionUpdateZone set { m_lastPositionUpdateZone = value; } } - public Coordinate LastUpdateLocation => Motion.Start; + public Coordinate LastUpdateLocation => Motion.Start.Coordinate; /// /// Holds the players max Z for fall damage