diff --git a/Source/Game/Movement/Generators/GenericMovementGenerator.cs b/Source/Game/Movement/Generators/GenericMovementGenerator.cs index 3743aa8bc..9af4215ca 100644 --- a/Source/Game/Movement/Generators/GenericMovementGenerator.cs +++ b/Source/Game/Movement/Generators/GenericMovementGenerator.cs @@ -13,23 +13,31 @@ namespace Game.Movement MovementGeneratorType _type; uint _pointId; TimeTracker _duration; + bool _durationTracksSpline; uint _arrivalSpellId; ObjectGuid _arrivalSpellTargetGuid; - public GenericMovementGenerator(Action initializer, MovementGeneratorType type, uint id, uint arrivalSpellId = 0, ObjectGuid arrivalSpellTargetGuid = default) + public GenericMovementGenerator(Action initializer, MovementGeneratorType type, uint id, GenericMovementGeneratorArgs args = default) { _splineInit = initializer; _type = type; _pointId = id; - _duration = new(); - _arrivalSpellId = arrivalSpellId; - _arrivalSpellTargetGuid = arrivalSpellTargetGuid; + _durationTracksSpline = true; Mode = MovementGeneratorMode.Default; Priority = MovementGeneratorPriority.Normal; Flags = MovementGeneratorFlags.InitializationPending; BaseUnitState = UnitState.Roaming; + if (args.ArrivalSpellId.HasValue) + _arrivalSpellId = args.ArrivalSpellId.Value; + if (args.ArrivalSpellTarget.HasValue) + _arrivalSpellTargetGuid = args.ArrivalSpellTarget.Value; + if (args.Duration.HasValue) + { + _duration = new(args.Duration.Value); + _durationTracksSpline = false; + } } public override void Initialize(Unit owner) @@ -46,7 +54,9 @@ namespace Game.Movement MoveSplineInit init = new(owner); _splineInit(init); - _duration.Reset((uint)init.Launch()); + int duration = init.Launch(); + if (_durationTracksSpline) + _duration = new((uint)duration); } public override void Reset(Unit owner) @@ -60,10 +70,9 @@ namespace Game.Movement return false; // Cyclic splines never expire, so update the duration only if it's not cyclic - if (!owner.MoveSpline.IsCyclic()) - _duration.Update(diff); + _duration?.Update(diff); - if (_duration.Passed() || owner.MoveSpline.Finalized()) + if ((_duration != null && _duration.Passed()) || owner.MoveSpline.Finalized()) { AddFlag(MovementGeneratorFlags.InformEnabled); return false; @@ -97,4 +106,11 @@ namespace Game.Movement public override MovementGeneratorType GetMovementGeneratorType() { return _type; } } + + struct GenericMovementGeneratorArgs + { + public uint? ArrivalSpellId; + public ObjectGuid? ArrivalSpellTarget; + public TimeSpan? Duration; + } } diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 83c497787..5e90127ca 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -795,7 +795,7 @@ namespace Game.Movement arrivalSpellTargetGuid = arrivalCast.Target; } - GenericMovementGenerator movement = new(initializer, MovementGeneratorType.Effect, id, arrivalSpellId, arrivalSpellTargetGuid); + GenericMovementGenerator movement = new(initializer, MovementGeneratorType.Effect, id, new GenericMovementGeneratorArgs() { ArrivalSpellId = arrivalSpellId, ArrivalSpellTarget = arrivalSpellTargetGuid }); movement.Priority = MovementGeneratorPriority.Highest; movement.BaseUnitState = UnitState.Jumping; Add(movement); @@ -828,14 +828,14 @@ namespace Game.Movement arrivalSpellTargetGuid = arrivalCast.Target; } - GenericMovementGenerator movement = new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, id, arrivalSpellId, arrivalSpellTargetGuid); + GenericMovementGenerator movement = new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, id, new GenericMovementGeneratorArgs() { ArrivalSpellId = arrivalSpellId, ArrivalSpellTarget = arrivalSpellTargetGuid }); movement.Priority = MovementGeneratorPriority.Highest; movement.BaseUnitState = UnitState.Jumping; movement.AddFlag(MovementGeneratorFlags.PersistOnDeath); Add(movement); } - public void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, byte stepCount) + public void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, byte stepCount, TimeSpan? duration = null, float? speed = null, MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode.Default) { var initializer = (MoveSplineInit init) => { @@ -851,7 +851,7 @@ namespace Game.Movement Vector3 point = new(); point.X = (float)(x + radius * Math.Cos(angle)); point.Y = (float)(y + radius * Math.Sin(angle)); - + if (_owner.IsFlying()) point.Z = z; else @@ -859,21 +859,34 @@ namespace Game.Movement init.Path().Add(point); } - + + init.SetCyclic(); if (_owner.IsFlying()) { init.SetFly(); - init.SetCyclic(); init.SetAnimation(AnimTier.Hover); } else - { init.SetWalk(true); - init.SetCyclic(); + + switch (speedSelectionMode) + { + case MovementWalkRunSpeedSelectionMode.ForceRun: + init.SetWalk(false); + break; + case MovementWalkRunSpeedSelectionMode.ForceWalk: + init.SetWalk(true); + break; + case MovementWalkRunSpeedSelectionMode.Default: + default: + break; } + + if (speed.HasValue) + init.SetVelocity(speed.Value); }; - Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, 0)); + Add(new GenericMovementGenerator(initializer, MovementGeneratorType.Effect, 0, new GenericMovementGeneratorArgs() { Duration = duration })); } public void MoveSmoothPath(uint pointId, Vector3[] pathPoints, int pathSize, bool walk = false, bool fly = false)