From c9a91fa62fdcd857402d38bca601ab1faf00f6e8 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 7 May 2020 14:16:30 -0400 Subject: [PATCH] Core/Movement: MotionMaster & MovementGenerators cleaning Port From (https://github.com/TrinityCore/TrinityCore/commit/14c6a4d8238e4f383557359436b5f73cb730d4ea) --- Source/Game/AI/CoreAI/PetAI.cs | 2 +- Source/Game/Chat/Commands/MiscCommands.cs | 8 +- Source/Game/Chat/Commands/NPCCommands.cs | 2 +- .../Movement/Generators/ConfusedGenerator.cs | 131 +++---- .../Movement/Generators/FleeingGenerator.cs | 228 +++++------ .../Game/Movement/Generators/HomeMovement.cs | 31 +- .../Game/Movement/Generators/IdleMovement.cs | 106 ++--- .../Movement/Generators/MovementGenerators.cs | 6 +- .../Game/Movement/Generators/PointMovement.cs | 182 ++++----- .../Movement/Generators/RandomMovement.cs | 235 +++++------ .../Movement/Generators/TargetMovement.cs | 364 +++++++++--------- Source/Game/Movement/MotionMaster.cs | 5 +- 12 files changed, 631 insertions(+), 669 deletions(-) diff --git a/Source/Game/AI/CoreAI/PetAI.cs b/Source/Game/AI/CoreAI/PetAI.cs index 1845feff5..000c09d00 100644 --- a/Source/Game/AI/CoreAI/PetAI.cs +++ b/Source/Game/AI/CoreAI/PetAI.cs @@ -430,7 +430,7 @@ namespace Game.AI ClearCharmInfoFlags(); me.GetCharmInfo().SetIsReturning(true); me.GetMotionMaster().Clear(); - me.GetMotionMaster().MovePoint(me.GetGUID().GetCounter(), x, y, z); + me.GetMotionMaster().MovePoint((uint)me.GetGUID().GetCounter(), x, y, z); } } else // COMMAND_FOLLOW diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index ea7d6b995..04514456d 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -1872,9 +1872,9 @@ namespace Game.Chat { Unit target; if (unit.IsTypeId(TypeId.Player)) - target = ((ChaseMovementGenerator)movementGenerator).Target; + target = ((ChaseMovementGenerator)movementGenerator).GetTarget(); else - target = ((ChaseMovementGenerator)movementGenerator).Target; + target = ((ChaseMovementGenerator)movementGenerator).GetTarget(); if (!target) handler.SendSysMessage(CypherStrings.MovegensChaseNull); @@ -1888,9 +1888,9 @@ namespace Game.Chat { Unit target; if (unit.IsTypeId(TypeId.Player)) - target = ((FollowMovementGenerator)movementGenerator).Target; + target = ((FollowMovementGenerator)movementGenerator).GetTarget(); else - target = ((FollowMovementGenerator)movementGenerator).Target; + target = ((FollowMovementGenerator)movementGenerator).GetTarget(); if (!target) handler.SendSysMessage(CypherStrings.MovegensFollowNull); diff --git a/Source/Game/Chat/Commands/NPCCommands.cs b/Source/Game/Chat/Commands/NPCCommands.cs index d533946bb..61ff6dcc7 100644 --- a/Source/Game/Chat/Commands/NPCCommands.cs +++ b/Source/Game/Chat/Commands/NPCCommands.cs @@ -506,7 +506,7 @@ namespace Game.Chat FollowMovementGenerator mgen = (FollowMovementGenerator)creature.GetMotionMaster().Top(); - if (mgen.Target != player) + if (mgen.GetTarget() != player) { handler.SendSysMessage(CypherStrings.CreatureNotFollowYou, creature.GetName()); return false; diff --git a/Source/Game/Movement/Generators/ConfusedGenerator.cs b/Source/Game/Movement/Generators/ConfusedGenerator.cs index 9cd5e96af..e09a81b95 100644 --- a/Source/Game/Movement/Generators/ConfusedGenerator.cs +++ b/Source/Game/Movement/Generators/ConfusedGenerator.cs @@ -25,20 +25,72 @@ namespace Game.Movement { public ConfusedGenerator() { - i_nextMoveTime = new TimeTracker(); + _timer = new TimeTracker(); } public override void DoInitialize(T owner) { - owner.AddUnitState(UnitState.Confused); - owner.AddUnitFlag(UnitFlags.Confused); - owner.GetPosition(out i_x, out i_y, out i_z); - - if (!owner.IsAlive() || owner.IsStopped()) + if (!owner || !owner.IsAlive()) return; + owner.AddUnitState(UnitState.Confused); + owner.AddUnitFlag(UnitFlags.Confused); owner.StopMoving(); - owner.AddUnitState(UnitState.ConfusedMove); + + _timer.Reset(0); + _reference = owner.GetPosition(); + } + + public override void DoReset(T owner) + { + DoInitialize(owner); + } + + public override bool DoUpdate(T owner, uint diff) + { + if (!owner || !owner.IsAlive()) + return false; + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return true; + } + else + _interrupt = false; + + // waiting for next move + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner.MoveSpline.Finalized()) + { + // start moving + owner.AddUnitState(UnitState.ConfusedMove); + + Position destination = _reference; + float distance = (float)(4.0f * RandomHelper.FRand(0.0f, 1.0f) - 2.0f); + float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f; + owner.MovePositionToFirstCollision(ref destination, distance, angle); + + if (_path == null) + _path = new PathGenerator(owner); + + _path.SetPathLengthLimit(30.0f); + bool result = _path.CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath)) + { + _timer.Reset(100); + return true; + } + + MoveSplineInit init = new MoveSplineInit(owner); + init.MovebyPath(_path.GetPath()); + init.SetWalk(true); + int traveltime = init.Launch(); + _timer.Reset(traveltime + RandomHelper.URand(800, 1500)); + } + + return true; } public override void DoFinalize(T owner) @@ -46,7 +98,7 @@ namespace Game.Movement if (owner.IsTypeId(TypeId.Player)) { owner.RemoveUnitFlag(UnitFlags.Confused); - owner.ClearUnitState(UnitState.Confused | UnitState.ConfusedMove); + owner.ClearUnitState(UnitState.Confused); owner.StopMoving(); } else if (owner.IsTypeId(TypeId.Unit)) @@ -58,69 +110,14 @@ namespace Game.Movement } } - public override void DoReset(T owner) - { - i_nextMoveTime.Reset(0); - - if (!owner.IsAlive() || owner.IsStopped()) - return; - - owner.StopMoving(); - owner.AddUnitState(UnitState.Confused | UnitState.ConfusedMove); - } - - public override bool DoUpdate(T owner, uint time_diff) - { - if (owner.HasUnitState(UnitState.Root | UnitState.Stunned | UnitState.Distracted)) - return true; - - if (i_nextMoveTime.Passed()) - { - // currently moving, update location - owner.AddUnitState(UnitState.ConfusedMove); - - if (owner.MoveSpline.Finalized()) - i_nextMoveTime.Reset(RandomHelper.IRand(800, 1500)); - } - else - { - // waiting for next move - i_nextMoveTime.Update(time_diff); - if (i_nextMoveTime.Passed()) - { - // start moving - owner.AddUnitState(UnitState.ConfusedMove); - - float dest = (float)(4.0f * RandomHelper.NextDouble() - 2.0f); - - Position pos = new Position(i_x, i_y, i_z); - owner.MovePositionToFirstCollision(ref pos, dest, 0.0f); - - PathGenerator path = new PathGenerator(owner); - path.SetPathLengthLimit(30.0f); - bool result = path.CalculatePath(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); - if (!result || path.GetPathType().HasAnyFlag(PathType.NoPath)) - { - i_nextMoveTime.Reset(100); - return true; - } - - MoveSplineInit init = new MoveSplineInit(owner); - init.MovebyPath(path.GetPath()); - init.SetWalk(true); - init.Launch(); - } - } - - return true; - } - public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Confused; } - TimeTracker i_nextMoveTime; - float i_x, i_y, i_z; + PathGenerator _path; + TimeTracker _timer; + Position _reference; + bool _interrupt; } } diff --git a/Source/Game/Movement/Generators/FleeingGenerator.cs b/Source/Game/Movement/Generators/FleeingGenerator.cs index 9767d342b..bef7cb434 100644 --- a/Source/Game/Movement/Generators/FleeingGenerator.cs +++ b/Source/Game/Movement/Generators/FleeingGenerator.cs @@ -28,93 +28,8 @@ namespace Game.Movement public FleeingGenerator(ObjectGuid fright) { - i_frightGUID = fright; - i_nextCheckTime = new TimeTracker(); - } - - void _setTargetLocation(T owner) - { - if (owner == null) - return; - - if (owner.HasUnitState(UnitState.Root | UnitState.Stunned)) - return; - - if (owner.IsMovementPreventedByCasting()) - { - owner.CastStop(); - return; - } - - owner.AddUnitState(UnitState.FleeingMove); - - float x, y, z; - _getPoint(owner, out x, out y, out z); - - Position mypos = owner.GetPosition(); - bool isInLOS = Global.VMapMgr.IsInLineOfSight(PhasingHandler.GetTerrainMapId(owner.GetPhaseShift(), owner.GetMap(), mypos.posX, mypos.posY), mypos.posX, mypos.posY, mypos.posZ + 2.0f, x, y, z + 2.0f, ModelIgnoreFlags.Nothing); - - if (!isInLOS) - { - i_nextCheckTime.Reset(200); - return; - } - - PathGenerator path = new PathGenerator(owner); - path.SetPathLengthLimit(30.0f); - bool result = path.CalculatePath(x, y, z); - if (!result || path.GetPathType().HasAnyFlag(PathType.NoPath)) - { - i_nextCheckTime.Reset(100); - return; - } - - MoveSplineInit init = new MoveSplineInit(owner); - init.MovebyPath(path.GetPath()); - init.SetWalk(false); - int traveltime = init.Launch(); - i_nextCheckTime.Reset(traveltime + RandomHelper.URand(800, 1500)); - } - - void _getPoint(T owner, out float x, out float y, out float z) - { - float dist_from_caster, angle_to_caster; - Unit fright = Global.ObjAccessor.GetUnit(owner, i_frightGUID); - if (fright != null) - { - dist_from_caster = fright.GetDistance(owner); - if (dist_from_caster > 0.2f) - angle_to_caster = fright.GetAngle(owner); - else - angle_to_caster = RandomHelper.FRand(0, 2 * MathFunctions.PI); - } - else - { - dist_from_caster = 0.0f; - angle_to_caster = RandomHelper.FRand(0, 2 * MathFunctions.PI); - } - - float dist, angle; - if (dist_from_caster < MIN_QUIET_DISTANCE) - { - dist = RandomHelper.FRand(0.4f, 1.3f) * (MIN_QUIET_DISTANCE - dist_from_caster); - angle = angle_to_caster + RandomHelper.FRand(-MathFunctions.PI / 8, MathFunctions.PI / 8); - } - else if (dist_from_caster > MAX_QUIET_DISTANCE) - { - dist = RandomHelper.FRand(0.4f, 1.0f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = -angle_to_caster + RandomHelper.FRand(-MathFunctions.PI / 4, MathFunctions.PI / 4); - } - else // we are inside quiet range - { - dist = RandomHelper.FRand(0.6f, 1.2f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = RandomHelper.FRand(0, 2 * MathFunctions.PI); - } - - Position pos = owner.GetFirstCollisionPosition(dist, angle); - x = pos.posX; - y = pos.posY; - z = pos.posZ; + _fleeTargetGUID = fright; + _timer = new TimeTracker(); } public override void DoInitialize(T owner) @@ -123,8 +38,34 @@ namespace Game.Movement return; owner.AddUnitFlag(UnitFlags.Fleeing); - owner.AddUnitState(UnitState.Fleeing | UnitState.FleeingMove); - _setTargetLocation(owner); + owner.AddUnitState(UnitState.Fleeing); + SetTargetLocation(owner); + } + + public override void DoReset(T owner) + { + DoInitialize(owner); + } + + public override bool DoUpdate(T owner, uint diff) + { + if (owner == null || !owner.IsAlive()) + return false; + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return true; + } + else + _interrupt = false; + + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner.MoveSpline.Finalized()) + SetTargetLocation(owner); + + return true; } public override void DoFinalize(T owner) @@ -132,7 +73,7 @@ namespace Game.Movement if (owner.IsTypeId(TypeId.Player)) { owner.RemoveUnitFlag(UnitFlags.Fleeing); - owner.ClearUnitState(UnitState.Fleeing | UnitState.FleeingMove); + owner.ClearUnitState(UnitState.Fleeing); owner.StopMoving(); } else @@ -144,27 +85,86 @@ namespace Game.Movement } } - public override void DoReset(T owner) + void SetTargetLocation(T owner) { - DoInitialize(owner); - } + if (owner == null) + return; - public override bool DoUpdate(T owner, uint time_diff) - { - if (owner == null || !owner.IsAlive()) - return false; - - if (owner.HasUnitState(UnitState.Root | UnitState.Stunned)) + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { - owner.ClearUnitState(UnitState.FleeingMove); - return true; + _interrupt = true; + owner.StopMoving(); + return; } - i_nextCheckTime.Update(time_diff); - if (i_nextCheckTime.Passed() && owner.MoveSpline.Finalized()) - _setTargetLocation(owner); + owner.AddUnitState(UnitState.FleeingMove); - return true; + Position destination = owner.GetPosition(); + GetPoint(owner, ref destination); + + // Add LOS check for target point + Position currentPosition = owner.GetPosition(); + bool isInLOS = Global.VMapMgr.IsInLineOfSight(PhasingHandler.GetTerrainMapId(owner.GetPhaseShift(), owner.GetMap(), currentPosition.posX, currentPosition.posY), currentPosition.posX, currentPosition.posY, currentPosition.posZ + 2.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 2.0f, ModelIgnoreFlags.Nothing); + if (!isInLOS) + { + _timer.Reset(200); + return; + } + + if (_path == null) + _path = new PathGenerator(owner); + + _path.SetPathLengthLimit(30.0f); + bool result = _path.CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath)) + { + _timer.Reset(100); + return; + } + + MoveSplineInit init = new MoveSplineInit(owner); + init.MovebyPath(_path.GetPath()); + init.SetWalk(false); + int traveltime = init.Launch(); + _timer.Reset(traveltime + RandomHelper.URand(800, 1500)); + } + + void GetPoint(T owner, ref Position position) + { + float casterDistance, casterAngle; + Unit fleeTarget = Global.ObjAccessor.GetUnit(owner, _fleeTargetGUID); + if (fleeTarget != null) + { + casterDistance = fleeTarget.GetDistance(owner); + if (casterDistance > 0.2f) + casterAngle = fleeTarget.GetAngle(owner); + else + casterAngle = RandomHelper.FRand(0.0f, 2.0f * MathF.PI); + } + else + { + casterDistance = 0.0f; + casterAngle = RandomHelper.FRand(0.0f, 2.0f * MathF.PI); + } + + float distance, angle; + if (casterDistance < MIN_QUIET_DISTANCE) + { + distance = RandomHelper.FRand(0.4f, 1.3f) * (MIN_QUIET_DISTANCE - casterDistance); + angle = casterAngle + RandomHelper.FRand(-MathF.PI / 8.0f, MathF.PI / 8.0f); + } + else if (casterDistance > MAX_QUIET_DISTANCE) + { + distance = RandomHelper.FRand(0.4f, 1.0f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = -casterAngle + RandomHelper.FRand(-MathF.PI / 4.0f, MathF.PI / 4.0f); + } + else // we are inside quiet range + { + distance = RandomHelper.FRand(0.6f, 1.2f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = RandomHelper.FRand(0.0f, 2.0f * MathF.PI); + } + + owner.MovePositionToFirstCollision(ref position, distance, angle); } public override MovementGeneratorType GetMovementGeneratorType() @@ -172,15 +172,17 @@ namespace Game.Movement return MovementGeneratorType.Fleeing; } - ObjectGuid i_frightGUID; - TimeTracker i_nextCheckTime; + PathGenerator _path; + ObjectGuid _fleeTargetGUID; + TimeTracker _timer; + bool _interrupt; } public class TimedFleeingGenerator : FleeingGenerator { public TimedFleeingGenerator(ObjectGuid fright, uint time) : base(fright) { - i_totalFleeTime = new TimeTracker(time); + _totalFleeTime = new TimeTracker(time); } public override void Finalize(Unit owner) @@ -198,7 +200,7 @@ namespace Game.Movement } } - public override bool Update(Unit owner, uint time_diff) + public override bool Update(Unit owner, uint diff) { if (!owner.IsAlive()) return false; @@ -209,15 +211,15 @@ namespace Game.Movement return true; } - i_totalFleeTime.Update(time_diff); - if (i_totalFleeTime.Passed()) + _totalFleeTime.Update(diff); + if (_totalFleeTime.Passed()) return false; // This calls grant-parent Update method hiden by FleeingMovementGenerator.Update(Creature &, uint32) version // This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly - return base.Update(owner, time_diff); + return base.Update(owner, diff); } - TimeTracker i_totalFleeTime; + TimeTracker _totalFleeTime; } } diff --git a/Source/Game/Movement/Generators/HomeMovement.cs b/Source/Game/Movement/Generators/HomeMovement.cs index 985a14843..1f3c284ce 100644 --- a/Source/Game/Movement/Generators/HomeMovement.cs +++ b/Source/Game/Movement/Generators/HomeMovement.cs @@ -28,9 +28,20 @@ namespace Game.AI SetTargetLocation(owner); } + public override void DoReset(T owner) + { + DoInitialize(owner); + } + + public override bool DoUpdate(T owner, uint diff) + { + _arrived = _skipToHome || owner.MoveSpline.Finalized(); + return !_arrived; + } + public override void DoFinalize(T owner) { - if (arrived) + if (_arrived) { owner.ClearUnitState(UnitState.Evade); owner.SetWalk(true); @@ -40,19 +51,11 @@ namespace Game.AI } } - public override void DoReset(T owner) { } - - public override bool DoUpdate(T owner, uint time_diff) - { - arrived = skipToHome || owner.MoveSpline.Finalized(); - return !arrived; - } - void SetTargetLocation(T owner) { if (owner.HasUnitState(UnitState.Root | UnitState.Stunned | UnitState.Distracted)) { // if we are ROOT/STUNNED/DISTRACTED even after aura clear, finalize on next update - otherwise we would get stuck in evade - skipToHome = true; + _skipToHome = true; return; } @@ -68,8 +71,8 @@ namespace Game.AI init.SetWalk(false); init.Launch(); - skipToHome = false; - arrived = false; + _skipToHome = false; + _arrived = false; owner.ClearUnitState(UnitState.AllErasable & ~UnitState.Evade); } @@ -79,7 +82,7 @@ namespace Game.AI return MovementGeneratorType.Home; } - bool arrived; - bool skipToHome; + bool _arrived; + bool _skipToHome; } } diff --git a/Source/Game/Movement/Generators/IdleMovement.cs b/Source/Game/Movement/Generators/IdleMovement.cs index 5fcca3468..2ffc05569 100644 --- a/Source/Game/Movement/Generators/IdleMovement.cs +++ b/Source/Game/Movement/Generators/IdleMovement.cs @@ -22,45 +22,41 @@ namespace Game.Movement { public class IdleMovementGenerator : IMovementGenerator { - public override MovementGeneratorType GetMovementGeneratorType() + public override void Initialize(Unit owner) { - return MovementGeneratorType.Idle; + Reset(owner); } - public bool IsActive { get; set; } - public override void Reset(Unit owner) { if (!owner.IsStopped()) owner.StopMoving(); } - public override void Initialize(Unit owner) - { - Reset(owner); - } - public override void Finalize(Unit owner) - { - } - public override bool Update(Unit owner, uint time_diff) + + public override bool Update(Unit owner, uint diff) { return true; } + + public override void Finalize(Unit owner) + { + } + + public override MovementGeneratorType GetMovementGeneratorType() + { + return MovementGeneratorType.Idle; + } + + public bool IsActive { get; set; } } public class RotateMovementGenerator : IMovementGenerator { public RotateMovementGenerator(uint time, RotateDirection direction) { - m_duration = time; - m_maxDuration = time; - m_direction = direction; - } - - public override void Finalize(Unit owner) - { - owner.ClearUnitState(UnitState.Rotating); - if (owner.IsTypeId(TypeId.Unit)) - owner.ToCreature().GetAI().MovementInform(MovementGeneratorType.Rotate, 0); + _duration = time; + _maxDuration = time; + _direction = direction; } public override void Initialize(Unit owner) @@ -75,36 +71,64 @@ namespace Game.Movement owner.AttackStop(); } - public override bool Update(Unit owner, uint time_diff) + public override void Reset(Unit owner) { } + + public override bool Update(Unit owner, uint diff) { float angle = owner.GetOrientation(); - angle += time_diff * MathFunctions.TwoPi / m_maxDuration * (m_direction == RotateDirection.Left ? 1.0f : -1.0f); + angle += diff * MathFunctions.TwoPi / _maxDuration * (_direction == RotateDirection.Left ? 1.0f : -1.0f); angle = MathFunctions.wrap(angle, 0.0f, MathFunctions.TwoPi); owner.SetOrientation(angle); // UpdateSplinePosition does not set orientation with UNIT_STATE_ROTATING owner.SetFacingTo(angle); // Send spline movement to clients - if (m_duration > time_diff) - m_duration -= time_diff; + if (_duration > diff) + _duration -= diff; else return false; return true; } - public override void Reset(Unit owner) { } + public override void Finalize(Unit owner) + { + owner.ClearUnitState(UnitState.Rotating); + if (owner.IsTypeId(TypeId.Unit)) + owner.ToCreature().GetAI().MovementInform(MovementGeneratorType.Rotate, 0); + } public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Rotate; } - uint m_duration, m_maxDuration; - RotateDirection m_direction; + uint _duration; + uint _maxDuration; + RotateDirection _direction; } public class DistractMovementGenerator : IMovementGenerator { public DistractMovementGenerator(uint timer) { - m_timer = timer; + _timer = timer; + } + + public override void Initialize(Unit owner) + { + // Distracted creatures stand up if not standing + if (!owner.IsStandState()) + owner.SetStandState(UnitStandStateType.Stand); + + owner.AddUnitState(UnitState.Distracted); + } + + public override void Reset(Unit owner) { } + + public override bool Update(Unit owner, uint diff) + { + if (diff > _timer) + return false; + + _timer -= diff; + return true; } public override void Finalize(Unit owner) @@ -119,29 +143,9 @@ namespace Game.Movement } } - public override void Initialize(Unit owner) - { - // Distracted creatures stand up if not standing - if (!owner.IsStandState()) - owner.SetStandState(UnitStandStateType.Stand); - - owner.AddUnitState(UnitState.Distracted); - } - - public override bool Update(Unit owner, uint time_diff) - { - if (time_diff > m_timer) - return false; - - m_timer -= time_diff; - return true; - } - - public override void Reset(Unit owner) { } - public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Distract; } - uint m_timer; + uint _timer; } public class AssistanceDistractMovementGenerator : DistractMovementGenerator diff --git a/Source/Game/Movement/Generators/MovementGenerators.cs b/Source/Game/Movement/Generators/MovementGenerators.cs index b6a6816cb..a241d6356 100644 --- a/Source/Game/Movement/Generators/MovementGenerators.cs +++ b/Source/Game/Movement/Generators/MovementGenerators.cs @@ -58,9 +58,9 @@ namespace Game.Movement { DoReset((T)owner); } - public override bool Update(Unit owner, uint time_diff) + public override bool Update(Unit owner, uint diff) { - return DoUpdate((T)owner, time_diff); + return DoUpdate((T)owner, diff); } public bool IsActive { get; set; } @@ -68,7 +68,7 @@ namespace Game.Movement public abstract void DoInitialize(T owner); public abstract void DoFinalize(T owner); public abstract void DoReset(T owner); - public abstract bool DoUpdate(T owner, uint time_diff); + public abstract bool DoUpdate(T owner, uint diff); } public class FollowerReference : Reference diff --git a/Source/Game/Movement/Generators/PointMovement.cs b/Source/Game/Movement/Generators/PointMovement.cs index 0bdf39732..1d0412137 100644 --- a/Source/Game/Movement/Generators/PointMovement.cs +++ b/Source/Game/Movement/Generators/PointMovement.cs @@ -22,39 +22,46 @@ namespace Game.Movement { public class PointMovementGenerator : MovementGeneratorMedium where T : Unit { - public PointMovementGenerator(ulong _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f, Unit faceTarget = null, SpellEffectExtraData spellEffectExtraData = null) + public PointMovementGenerator(uint id, float x, float y, float z, bool generatePath, float speed = 0.0f, Unit faceTarget = null, SpellEffectExtraData spellEffectExtraData = null) { - id = _id; - i_x = _x; - i_y = _y; - i_z = _z; - speed = _speed; - i_faceTarget = faceTarget; - i_spellEffectExtra = spellEffectExtraData; - m_generatePath = _generatePath; - i_recalculateSpeed = false; + _movementId = id; + _destination = new Position(x, y, z); + _speed = speed; + _faceTarget = faceTarget; + _spellEffectExtra = spellEffectExtraData; + _generatePath = generatePath; + _recalculateSpeed = false; } public override void DoInitialize(T owner) { - if (!owner.IsStopped()) - owner.StopMoving(); - - owner.AddUnitState(UnitState.Roaming | UnitState.RoamingMove); - - if (id == EventId.ChargePrepath) + if (_movementId == EventId.ChargePrepath) + { + owner.AddUnitState(UnitState.Roaming | UnitState.RoamingMove); return; + } + + owner.AddUnitState(UnitState.Roaming); + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return; + } + + owner.AddUnitState(UnitState.RoamingMove); MoveSplineInit init = new MoveSplineInit(owner); - init.MoveTo(i_x, i_y, i_z, m_generatePath); - if (speed > 0.0f) - init.SetVelocity(speed); + init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ(), _generatePath); + if (_speed > 0.0f) + init.SetVelocity(_speed); - if (i_faceTarget) - init.SetFacing(i_faceTarget); + if (_faceTarget) + init.SetFacing(_faceTarget); - if (i_spellEffectExtra != null) - init.SetSpellEffectExtraData(i_spellEffectExtra); + if (_spellEffectExtra != null) + init.SetSpellEffectExtraData(_spellEffectExtra); init.Launch(); @@ -62,36 +69,48 @@ namespace Game.Movement Creature creature = owner.ToCreature(); if (creature != null) if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) - creature.GetFormation().LeaderMoveTo(i_x, i_y, i_z); + creature.GetFormation().LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ()); } - public override bool DoUpdate(T owner, uint time_diff) + public override void DoReset(T owner) + { + owner.StopMoving(); + DoInitialize(owner); + } + + public override bool DoUpdate(T owner, uint diff) { if (owner == null) return false; - if (owner.HasUnitState(UnitState.Root | UnitState.Stunned)) + if (_movementId == EventId.ChargePrepath) + return !owner.MoveSpline.Finalized(); + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) { - owner.ClearUnitState(UnitState.RoamingMove); + _interrupt = true; + owner.StopMoving(); return true; } - owner.AddUnitState(UnitState.RoamingMove); - - if (id != EventId.ChargePrepath && i_recalculateSpeed && !owner.MoveSpline.Finalized()) + if ((_interrupt && owner.MoveSpline.Finalized()) || (_recalculateSpeed && !owner.MoveSpline.Finalized())) { - i_recalculateSpeed = false; + _recalculateSpeed = false; + _interrupt = false; + + owner.AddUnitState(UnitState.RoamingMove); + MoveSplineInit init = new MoveSplineInit(owner); - init.MoveTo(i_x, i_y, i_z, m_generatePath); - if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit - init.SetVelocity(speed); + init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ(), _generatePath); + if (_speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit + init.SetVelocity(_speed); init.Launch(); // Call for creature group update Creature creature = owner.ToCreature(); if (creature != null) if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) - creature.GetFormation().LeaderMoveTo(i_x, i_y, i_z); + creature.GetFormation().LeaderMoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ()); } return !owner.MoveSpline.Finalized(); @@ -99,33 +118,24 @@ namespace Game.Movement public override void DoFinalize(T owner) { - if (!owner.HasUnitState(UnitState.Charging)) - owner.ClearUnitState(UnitState.Roaming | UnitState.RoamingMove); + owner.ClearUnitState(UnitState.Roaming | UnitState.RoamingMove); if (owner.MoveSpline.Finalized()) MovementInform(owner); } - public override void DoReset(T owner) + public void MovementInform(T owner) { - if (!owner.IsStopped()) - owner.StopMoving(); - - owner.AddUnitState(UnitState.Roaming | UnitState.RoamingMove); - } - - public void MovementInform(T unit) - { - if (!unit.IsTypeId(TypeId.Unit)) - return; - - if (unit.ToCreature().GetAI() != null) - unit.ToCreature().GetAI().MovementInform(MovementGeneratorType.Point, (uint)id); + if (owner.IsTypeId(TypeId.Unit)) + { + if (owner.ToCreature().GetAI() != null) + owner.ToCreature().GetAI().MovementInform(MovementGeneratorType.Point, _movementId); + } } public override void UnitSpeedChanged() { - i_recalculateSpeed = true; + _recalculateSpeed = true; } public override MovementGeneratorType GetMovementGeneratorType() @@ -133,23 +143,26 @@ namespace Game.Movement return MovementGeneratorType.Point; } - ulong id; - float i_x, i_y, i_z; - float speed; - Unit i_faceTarget; - SpellEffectExtraData i_spellEffectExtra; - bool m_generatePath; - bool i_recalculateSpeed; + uint _movementId; + Position _destination; + float _speed; + Unit _faceTarget; + SpellEffectExtraData _spellEffectExtra; + bool _generatePath; + bool _recalculateSpeed; + bool _interrupt; } public class AssistanceMovementGenerator : PointMovementGenerator { - public AssistanceMovementGenerator(float _x, float _y, float _z) : base(0, _x, _y, _z, true) { } + public AssistanceMovementGenerator(float x, float y, float z) : base(0, x, y, z, true) { } public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Assistance; } public override void Finalize(Unit owner) { + owner.ClearUnitState(UnitState.Roaming); + owner.StopMoving(); owner.ToCreature().SetNoCallAssistance(false); owner.ToCreature().CallAssistance(); if (owner.IsAlive()) @@ -157,48 +170,41 @@ namespace Game.Movement } } - // Does almost nothing - just doesn't allows previous movegen interrupt current effect. public class EffectMovementGenerator : IMovementGenerator { public EffectMovementGenerator(uint Id, uint arrivalSpellId = 0, ObjectGuid arrivalSpellTargetGuid = default) { - _Id = Id; + _pointId = Id; _arrivalSpellId = arrivalSpellId; _arrivalSpellTargetGuid = arrivalSpellTargetGuid; } - public override void Finalize(Unit unit) - { - if (_arrivalSpellId != 0) - unit.CastSpell(Global.ObjAccessor.GetUnit(unit, _arrivalSpellTargetGuid), _arrivalSpellId, true); - - if (!unit.IsTypeId(TypeId.Unit)) - return; - - // Need restore previous movement since we have no proper states system - if (unit.IsAlive() && !unit.HasUnitState(UnitState.Confused | UnitState.Fleeing)) - { - Unit victim = unit.GetVictim(); - if (victim != null) - unit.GetMotionMaster().MoveChase(victim); - } - - if (unit.ToCreature().GetAI() != null) - unit.ToCreature().GetAI().MovementInform(MovementGeneratorType.Effect, _Id); - } - - public override bool Update(Unit owner, uint time_diff) - { - return !owner.MoveSpline.Finalized(); - } - public override void Initialize(Unit owner) { } public override void Reset(Unit owner) { } + public override bool Update(Unit owner, uint diff) + { + return !owner.MoveSpline.Finalized(); + } + + public override void Finalize(Unit owner) + { + MovementInform(owner); + } + + public void MovementInform(Unit owner) + { + if (_arrivalSpellId != 0) + owner.CastSpell(Global.ObjAccessor.GetUnit(owner, _arrivalSpellTargetGuid), _arrivalSpellId, true); + + if (owner.ToCreature().GetAI() != null) + owner.ToCreature().GetAI().MovementInform(MovementGeneratorType.Effect, _pointId); + } + public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Effect; } - uint _Id; + uint _pointId; uint _arrivalSpellId; ObjectGuid _arrivalSpellTargetGuid; } diff --git a/Source/Game/Movement/Generators/RandomMovement.cs b/Source/Game/Movement/Generators/RandomMovement.cs index e942653ec..bfc89261c 100644 --- a/Source/Game/Movement/Generators/RandomMovement.cs +++ b/Source/Game/Movement/Generators/RandomMovement.cs @@ -26,151 +26,110 @@ namespace Game.Movement { public RandomMovementGenerator(float spawn_dist = 0.0f) { - i_nextMoveTime = new TimeTrackerSmall(); - wander_distance = spawn_dist; + _timer = new TimeTracker(); + _wanderDistance = spawn_dist; } - TimeTrackerSmall i_nextMoveTime; - float wander_distance; + public override void DoInitialize(Creature owner) + { + if (owner == null || !owner.IsAlive()) + return; + + owner.AddUnitState(UnitState.Roaming); + _reference = owner.GetPosition(); + owner.StopMoving(); + + if (_wanderDistance == 0) + _wanderDistance = owner.GetRespawnRadius(); + + _timer.Reset(0); + } + + public override void DoReset(Creature owner) + { + DoInitialize(owner); + } + + public override bool DoUpdate(Creature owner, uint diff) + { + if (!owner || !owner.IsAlive()) + return false; + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return true; + } + else + _interrupt = false; + + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner.MoveSpline.Finalized()) + SetRandomLocation(owner); + + return true; + } + + public override void DoFinalize(Creature owner) + { + owner.ClearUnitState(UnitState.Roaming); + owner.StopMoving(); + owner.SetWalk(false); + } + + void SetRandomLocation(Creature owner) + { + if (owner == null) + return; + + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + { + _interrupt = true; + owner.StopMoving(); + return; + } + + owner.AddUnitState(UnitState.RoamingMove); + + Position position = _reference; + float distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance; + float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f; + owner.MovePositionToFirstCollision(ref position, distance, angle); + + uint resetTimer = RandomHelper.randChance(50) ? RandomHelper.URand(5000, 10000) : RandomHelper.URand(1000, 2000); + + if (_path == null) + _path = new PathGenerator(owner); + + _path.SetPathLengthLimit(30.0f); + bool result = _path.CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); + if (!result || _path.GetPathType().HasAnyFlag(PathType.NoPath)) + { + _timer.Reset(100); + return; + } + + MoveSplineInit init = new MoveSplineInit(owner); + init.MovebyPath(_path.GetPath()); + init.SetWalk(true); + int traveltime = init.Launch(); + _timer.Reset(traveltime + resetTimer); + + // Call for creature group update + if (owner.GetFormation() != null && owner.GetFormation().GetLeader() == owner) + owner.GetFormation().LeaderMoveTo(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); + } public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Random; } - public override void DoInitialize(Creature creature) - { - if (!creature.IsAlive()) - return; - - if (wander_distance == 0) - wander_distance = creature.GetRespawnRadius(); - - if (wander_distance == 0)//Temp fix - wander_distance = 50.0f; - - creature.AddUnitState(UnitState.Roaming | UnitState.RoamingMove); - _setRandomLocation(creature); - - } - public override void DoFinalize(Creature creature) - { - creature.ClearUnitState(UnitState.Roaming | UnitState.RoamingMove); - creature.SetWalk(false); - } - public override void DoReset(Creature creature) - { - DoInitialize(creature); - } - - public override bool DoUpdate(Creature creature, uint diff) - { - if (!creature || !creature.IsAlive()) - return false; - - if (creature.HasUnitState(UnitState.Root | UnitState.Stunned | UnitState.Distracted)) - { - i_nextMoveTime.Reset(0); // Expire the timer - creature.ClearUnitState(UnitState.RoamingMove); - return true; - } - - if (creature.MoveSpline.Finalized()) - { - i_nextMoveTime.Update((int)diff); - if (i_nextMoveTime.Passed()) - _setRandomLocation(creature); - } - return true; - } - - void _setRandomLocation(Creature creature) - { - if (creature.IsMovementPreventedByCasting()) - { - creature.CastStop(); - return; - } - - float respX, respY, respZ, respO, destZ; - creature.GetHomePosition(out respX, out respY, out respZ, out respO); - Map map = creature.GetMap(); - - bool is_air_ok = creature.CanFly(); - - float angle = (float)(RandomHelper.NextDouble() * MathFunctions.TwoPi); - float range = (float)(RandomHelper.NextDouble() * wander_distance); - float distanceX = (float)(range * Math.Cos(angle)); - float distanceY = (float)(range * Math.Sin(angle)); - - float destX = respX + distanceX; - float destY = respY + distanceY; - - // prevent invalid coordinates generation - GridDefines.NormalizeMapCoord(ref destX); - GridDefines.NormalizeMapCoord(ref destY); - - float travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below - - if (is_air_ok) // 3D system above ground and above water (flying mode) - { - // Limit height change - float distanceZ = (float)(RandomHelper.NextDouble() * travelDistZ / 2.0f); - destZ = respZ + distanceZ; - float levelZ = map.GetWaterOrGroundLevel(creature.GetPhaseShift(), destX, destY, destZ - 2.5f); - - // Problem here, we must fly above the ground and water, not under. Let's try on next tick - if (levelZ >= destZ) - return; - } - else // 2D only - { - // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) - travelDistZ = travelDistZ >= 10.0f ? 10.0f : travelDistZ; - - // The fastest way to get an accurate result 90% of the time. - // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. - destZ = map.GetHeight(creature.GetPhaseShift(), destX, destY, respZ + travelDistZ - 2.0f, false); - - if (Math.Abs(destZ - respZ) > travelDistZ) // Map check - { - // Vmap Horizontal or above - destZ = map.GetHeight(creature.GetPhaseShift(), destX, destY, respZ - 2.0f, true); - - if (Math.Abs(destZ - respZ) > travelDistZ) - { - // Vmap Higher - destZ = map.GetHeight(creature.GetPhaseShift(), destX, destY, respZ + travelDistZ - 2.0f, true); - - // let's forget this bad coords where a z cannot be find and retry at next tick - if (Math.Abs(destZ - respZ) > travelDistZ) - return; - } - } - } - - if (is_air_ok) - i_nextMoveTime.Reset(0); - else - { - if (RandomHelper.randChance(50)) - i_nextMoveTime.Reset(RandomHelper.IRand(5000, 10000)); - else - i_nextMoveTime.Reset(RandomHelper.IRand(50, 400)); - } - - creature.AddUnitState(UnitState.RoamingMove); - - MoveSplineInit init = new MoveSplineInit(creature); - init.MoveTo(destX, destY, destZ); - init.SetWalk(true); - init.Launch(); - - //Call for creature group update - if (creature.GetFormation() != null && creature.GetFormation().GetLeader() == creature) - creature.GetFormation().LeaderMoveTo(destX, destY, destZ); - } - - public virtual bool GetResetPosition(Creature creature, float x, float y, float z) { return false; } + PathGenerator _path; + TimeTracker _timer; + Position _reference; + float _wanderDistance; + bool _interrupt; } } diff --git a/Source/Game/Movement/Generators/TargetMovement.cs b/Source/Game/Movement/Generators/TargetMovement.cs index 720253e03..24d8b5520 100644 --- a/Source/Game/Movement/Generators/TargetMovement.cs +++ b/Source/Game/Movement/Generators/TargetMovement.cs @@ -24,270 +24,251 @@ namespace Game.Movement { public interface ITargetedMovementGeneratorBase { - FollowerReference Reftarget { get; set; } + bool IsTargetValid(); + Unit GetTarget(); void StopFollowing(); } - public abstract class TargetedMovementGeneratorMedium : MovementGeneratorMedium, ITargetedMovementGeneratorBase where T : Unit + public abstract class TargetedMovementGenerator : MovementGeneratorMedium, ITargetedMovementGeneratorBase where T : Unit { - public FollowerReference Reftarget { get; set; } - public Unit Target + protected TargetedMovementGenerator(Unit target, float offset = 0, float angle = 0) { - get { return Reftarget.GetTarget(); } + _target = new FollowerReference(); + _target.Link(target, this); + _timer = new TimeTracker(); + _offset = offset; + _angle = angle; + _recalculateTravel = false; + _targetReached = false; } - public void StopFollowing() { } - - protected TargetedMovementGeneratorMedium(Unit _target, float _offset = 0, float _angle = 0) + public override bool DoUpdate(T owner, uint diff) { - Reftarget = new FollowerReference(); - Reftarget.Link(_target, this); - recheckDistance = new TimeTrackerSmall(); - offset = _offset; - angle = _angle; - recalculateTravel = false; - targetReached = false; - } - - public override bool DoUpdate(T owner, uint time_diff) - { - if (!Reftarget.IsValid() || !Target.IsInWorld) + if (!IsTargetValid() || !GetTarget().IsInWorld) return false; if (owner == null || !owner.IsAlive()) return false; - if (owner.HasUnitState(UnitState.NotMove)) + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || HasLostTarget(owner)) { - _clearUnitStateMove(owner); + _interrupt = true; + owner.StopMoving(); return true; } - // prevent movement while casting spells with cast time or channel time - if (owner.IsMovementPreventedByCasting()) + if (_interrupt || _recalculateTravel) { - if (!owner.IsStopped()) - owner.StopMoving(); + _interrupt = false; + SetTargetLocation(owner, true); return true; } - // prevent crash after creature killed pet - if (_lostTarget(owner)) - { - _clearUnitStateMove(owner); - return true; - } bool targetMoved = false; - recheckDistance.Update((int)time_diff); - if (recheckDistance.Passed()) + _timer.Update((int)diff); + if (_timer.Passed()) { - recheckDistance.Reset(100); - //More distance let have better performance, less distance let have more sensitive reaction at target move. - float allowed_dist = 0.0f;// owner.GetCombatReach() + WorldConfig.GetFloatValue(WorldCfg.RateTargetPosRecalculationRange); + _timer.Reset(100); - if (owner.IsPet() && (owner.GetCharmerOrOwnerGUID() == Target.GetGUID())) - allowed_dist = 1.0f; // pet following owner - else - allowed_dist = owner.GetCombatReach() + WorldConfig.GetFloatValue(WorldCfg.RateTargetPosRecalculationRange); + float distance = owner.GetCombatReach() + WorldConfig.GetFloatValue(WorldCfg.RateTargetPosRecalculationRange); + if (owner.IsPet() && (owner.GetCharmerOrOwnerGUID() == GetTarget().GetGUID())) + distance = 1.0f; // pet following owner - Vector3 dest = owner.MoveSpline.FinalDestination(); + Vector3 destination = owner.MoveSpline.FinalDestination(); if (owner.MoveSpline.onTransport) { float o = 0; ITransport transport = owner.GetDirectTransport(); if (transport != null) - transport.CalculatePassengerPosition(ref dest.X, ref dest.Y, ref dest.Z, ref o); + transport.CalculatePassengerPosition(ref destination.X, ref destination.Y, ref destination.Z, ref o); } // First check distance - if (owner.IsTypeId(TypeId.Unit) && (owner.ToCreature().CanFly() || owner.ToCreature().CanSwim())) - targetMoved = !Target.IsWithinDist3d(dest.X, dest.Y, dest.Z, allowed_dist); + if (owner.IsTypeId(TypeId.Unit) && owner.ToCreature().CanFly()) + targetMoved = !GetTarget().IsWithinDist3d(destination.X, destination.Y, destination.Z, distance); else - targetMoved = !Target.IsWithinDist2d(dest.X, dest.Y, allowed_dist); + targetMoved = !GetTarget().IsWithinDist2d(destination.X, destination.Y, distance); // then, if the target is in range, check also Line of Sight. if (!targetMoved) - targetMoved = !Target.IsWithinLOSInMap(owner); + targetMoved = !GetTarget().IsWithinLOSInMap(owner); } - if (recalculateTravel || targetMoved) - _setTargetLocation(owner, targetMoved); + if (targetMoved) + SetTargetLocation(owner, targetMoved); + else if (_speedChanged) + SetTargetLocation(owner, false); - if (owner.MoveSpline.Finalized()) + if (!_targetReached && owner.MoveSpline.Finalized()) { MovementInform(owner); - if (angle == 0.0f && !owner.HasInArc(0.01f, Target)) - owner.SetInFront(Target); + if (_angle == 0.0f && !owner.HasInArc(0.01f, GetTarget())) + owner.SetInFront(GetTarget()); - if (!targetReached) + if (!_targetReached) { - targetReached = true; - _reachTarget(owner); + _targetReached = true; + ReachTarget(owner); } } return true; } - public override void UnitSpeedChanged() + public void SetTargetLocation(T owner, bool updateDestination) { - recalculateTravel = true; - } - - public void _setTargetLocation(T owner, bool updateDestination) - { - if (!Reftarget.IsValid() || !Target.IsInWorld) + if (!IsTargetValid() || !GetTarget().IsInWorld) return; - if (owner.HasUnitState(UnitState.NotMove)) + if (!owner || !owner.IsAlive()) return; - if (owner.IsMovementPreventedByCasting()) - return; - if (owner.IsTypeId(TypeId.Unit) && !Target.IsInAccessiblePlaceFor(owner.ToCreature())) + if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting() || HasLostTarget(owner)) + { + _interrupt = true; + owner.StopMoving(); + return; + } + + if (owner.IsTypeId(TypeId.Unit) && !GetTarget().IsInAccessiblePlaceFor(owner.ToCreature())) { owner.ToCreature().SetCannotReachTarget(true); return; } - if (owner.IsTypeId(TypeId.Unit) && owner.ToCreature().IsFocusing(null, true)) - return; - float x, y, z; - if (updateDestination || i_path == null) + if (updateDestination || _path == null) { - if (offset == 0) + if (_offset == 0) { - if (Target.IsWithinDistInMap(owner, SharedConst.ContactDistance)) + if (GetTarget().IsWithinDistInMap(owner, SharedConst.ContactDistance)) return; // to nearest contact position - Target.GetContactPoint(owner, out x, out y, out z); + GetTarget().GetContactPoint(owner, out x, out y, out z); } else { - float dist = 0; - float size = 0; + float distance = _offset + 1.0f; + float size = owner.GetCombatReach(); - // Pets need special handling. - // We need to subtract GetCombatReach() because it gets added back further down the chain - // and that makes pets too far away. Subtracting it allows pets to properly - // be (GetCombatReach() + i_offset) away. - // Only applies when i_target is pet's owner otherwise pets and mobs end up - // doing a "dance" while fighting - if (owner.IsPet() && Target.IsTypeId(TypeId.Player)) + if (owner.IsPet() && GetTarget().GetTypeId() == TypeId.Player) { - dist = 1.0f;// target.GetCombatReach(); - size = 1.0f;// target.GetCombatReach() - target.GetCombatReach(); - } - else - { - dist = offset + 1.0f; - size = owner.GetCombatReach(); + distance = 1.0f; + size = 1.0f; } - if (Target.IsWithinDistInMap(owner, dist)) + if (GetTarget().IsWithinDistInMap(owner, distance)) return; - // to at i_offset distance from target and i_angle from target facing - Target.GetClosePoint(out x, out y, out z, size, offset, angle); + GetTarget().GetClosePoint(out x, out y, out z, size, _offset, _angle); } } else { // the destination has not changed, we just need to refresh the path (usually speed change) - var end = i_path.GetEndPosition(); + var end = _path.GetEndPosition(); x = end.X; y = end.Y; z = end.Z; } - if (i_path == null) - i_path = new PathGenerator(owner); + if (_path == null) + _path = new PathGenerator(owner); // allow pets to use shortcut if no path found when following their master - bool forceDest = (owner.IsTypeId(TypeId.Unit) && owner.IsPet() - && owner.HasUnitState(UnitState.Follow)); + bool forceDest = owner.IsTypeId(TypeId.Unit) && owner.IsPet() && owner.HasUnitState(UnitState.Follow); - bool result = i_path.CalculatePath(x, y, z, forceDest); - if (!result && Convert.ToBoolean(i_path.GetPathType() & PathType.NoPath)) + bool result = _path.CalculatePath(x, y, z, forceDest); + if (!result && Convert.ToBoolean(_path.GetPathType() & PathType.NoPath)) { // Can't reach target - recalculateTravel = true; + _recalculateTravel = true; if (owner.IsTypeId(TypeId.Unit)) owner.ToCreature().SetCannotReachTarget(true); return; } - _addUnitStateMove(owner); - targetReached = false; - recalculateTravel = false; - owner.AddUnitState(UnitState.Chase); + _targetReached = false; + _recalculateTravel = false; + _speedChanged = false; + + AddUnitStateMove(owner); + if (owner.IsTypeId(TypeId.Unit)) owner.ToCreature().SetCannotReachTarget(false); MoveSplineInit init = new MoveSplineInit(owner); - init.MovebyPath(i_path.GetPath()); + init.MovebyPath(_path.GetPath()); init.SetWalk(EnableWalking()); // Using the same condition for facing target as the one that is used for SetInFront on movement end // - applies to ChaseMovementGenerator mostly - if (angle == 0.0f) - init.SetFacing(Target); + if (_angle == 0.0f) + init.SetFacing(GetTarget()); init.Launch(); } - public void UpdateFinalDistance(float fDistance) + bool IsReachable() { - if (typeof(T) == typeof(Player)) - return; - offset = fDistance; - recalculateTravel = true; + return _path != null ? _path.GetPathType().HasAnyFlag(PathType.Normal) : true; } - bool IsReachable() { return (i_path != null) ? Convert.ToBoolean(i_path.GetPathType() & PathType.Normal) : true; } + public override void UnitSpeedChanged() + { + _speedChanged = true; + } - public abstract void MovementInform(T unit); - public abstract bool _lostTarget(T u); - public abstract void _clearUnitStateMove(T u); - public abstract void _addUnitStateMove(T u); - public abstract void _reachTarget(T owner); - public abstract bool EnableWalking(); - public abstract void _updateSpeed(T u); + public abstract void ClearUnitStateMove(T owner); + public abstract void AddUnitStateMove(T owner); + public virtual bool HasLostTarget(T owner) { return false; } + public abstract void ReachTarget(T owner); + public virtual bool EnableWalking() { return false; } + public abstract void MovementInform(T owner); + + public void StopFollowing() { } - #region Fields - PathGenerator i_path; - TimeTrackerSmall recheckDistance; - float offset; - float angle; - public bool recalculateTravel; - bool targetReached; - #endregion + public bool IsTargetValid() { return _target.IsValid(); } + public Unit GetTarget() { return _target.GetTarget(); } + + FollowerReference _target; + PathGenerator _path; + TimeTracker _timer; + float _offset; + float _angle; + bool _recalculateTravel; + bool _speedChanged; + bool _targetReached; + bool _interrupt; } - public class ChaseMovementGenerator : TargetedMovementGeneratorMedium where T : Unit + public class ChaseMovementGenerator : TargetedMovementGenerator where T : Unit { public ChaseMovementGenerator(Unit target) : base(target) { } + public ChaseMovementGenerator(Unit target, float offset, float angle) : base(target, offset, angle) { } - public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Chase; } - public override void DoInitialize(T owner) { if (owner.IsTypeId(TypeId.Unit)) owner.SetWalk(false); - owner.AddUnitState(UnitState.Chase | UnitState.ChaseMove); - _setTargetLocation(owner, true); + owner.AddUnitState(UnitState.Chase); + SetTargetLocation(owner, true); + } + + public override void DoReset(T owner) + { + DoInitialize(owner); } public override void DoFinalize(T owner) @@ -295,102 +276,115 @@ namespace Game.Movement owner.ClearUnitState(UnitState.Chase | UnitState.ChaseMove); } - public override void DoReset(T owner) + public override void ClearUnitStateMove(T owner) { - DoInitialize(owner); + owner.ClearUnitState(UnitState.ChaseMove); } - public override bool _lostTarget(T u) + public override void AddUnitStateMove(T owner) { - return u.GetVictim() != Target; - } - public override void _clearUnitStateMove(T u) - { - u.ClearUnitState(UnitState.ChaseMove); - } - public override void _addUnitStateMove(T u) - { - u.AddUnitState(UnitState.ChaseMove); + owner.AddUnitState(UnitState.ChaseMove); } - public override bool EnableWalking() { return false; } - public override void _updateSpeed(T u) { } - public override void _reachTarget(T owner) + public override bool HasLostTarget(T owner) { - _clearUnitStateMove(owner); - if (owner.IsWithinMeleeRange(Target)) - owner.Attack(Target, true); + return owner.GetVictim() != GetTarget(); + } + + public override void ReachTarget(T owner) + { + ClearUnitStateMove(owner); + + if (owner.IsWithinMeleeRange(GetTarget())) + owner.Attack(GetTarget(), true); + if (owner.IsTypeId(TypeId.Unit)) owner.ToCreature().SetCannotReachTarget(false); } - public override void MovementInform(T unit) + + public override void MovementInform(T owner) { - if (unit.IsTypeId(TypeId.Unit)) + if (owner.IsTypeId(TypeId.Unit)) { // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (unit.ToCreature().GetAI() != null) - unit.ToCreature().GetAI().MovementInform(MovementGeneratorType.Chase, (uint)Target.GetGUID().GetCounter()); + if (owner.ToCreature().GetAI() != null) + owner.ToCreature().GetAI().MovementInform(MovementGeneratorType.Chase, (uint)GetTarget().GetGUID().GetCounter()); } } + + public override MovementGeneratorType GetMovementGeneratorType() { return MovementGeneratorType.Chase; } } - public class FollowMovementGenerator : TargetedMovementGeneratorMedium where T : Unit + public class FollowMovementGenerator : TargetedMovementGenerator where T : Unit { public FollowMovementGenerator(Unit target) : base(target) { } + public FollowMovementGenerator(Unit target, float offset, float angle) : base(target, offset, angle) { } - public override MovementGeneratorType GetMovementGeneratorType() + public override void DoInitialize(T owner) { - return MovementGeneratorType.Follow; - } - public override void _clearUnitStateMove(T u) - { - u.ClearUnitState(UnitState.FollowMove); - } - public override void _addUnitStateMove(T u) - { - u.AddUnitState(UnitState.FollowMove); + owner.AddUnitState(UnitState.Follow); + UpdateSpeed(owner); + SetTargetLocation(owner, true); } + public override void DoReset(T owner) { DoInitialize(owner); } - public override bool _lostTarget(T u) { return false; } - public override void _reachTarget(T u) { } - public override void DoInitialize(T owner) - { - owner.AddUnitState(UnitState.Follow | UnitState.FollowMove); - _updateSpeed(owner); - _setTargetLocation(owner, true); - } public override void DoFinalize(T owner) { owner.ClearUnitState(UnitState.Follow | UnitState.FollowMove); - _updateSpeed(owner); + UpdateSpeed(owner); } - public override void MovementInform(T unit) - { - if (unit.IsTypeId(TypeId.Player)) - return; - // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (unit.ToCreature().GetAI() != null) - unit.ToCreature().GetAI().MovementInform(MovementGeneratorType.Follow, (uint)Target.GetGUID().GetCounter()); + public override void ClearUnitStateMove(T owner) + { + owner.ClearUnitState(UnitState.FollowMove); } + + public override void AddUnitStateMove(T owner) + { + owner.AddUnitState(UnitState.FollowMove); + } + + public override void ReachTarget(T owner) + { + ClearUnitStateMove(owner); + } + public override bool EnableWalking() { if (typeof(T) == typeof(Player)) return false; else - return Reftarget.IsValid() && Target.IsWalking(); + return IsTargetValid() && GetTarget().IsWalking(); } - public override void _updateSpeed(T owner) + + public override void MovementInform(T owner) { if (owner.IsTypeId(TypeId.Player)) return; - if (!owner.IsPet() || !owner.IsInWorld || !Reftarget.IsValid() && Target.GetGUID() != owner.GetOwnerGUID()) + // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle + if (owner.ToCreature().GetAI() != null) + owner.ToCreature().GetAI().MovementInform(MovementGeneratorType.Follow, (uint)GetTarget().GetGUID().GetCounter()); + } + + public override bool HasLostTarget(T u) { return false; } + + public override MovementGeneratorType GetMovementGeneratorType() + { + return MovementGeneratorType.Follow; + } + + void UpdateSpeed(T owner) + { + if (owner.IsTypeId(TypeId.Player)) + return; + + if (!owner.IsPet() || !owner.IsInWorld || !IsTargetValid() && GetTarget().GetGUID() != owner.GetOwnerGUID()) return; owner.UpdateSpeed(UnitMoveType.Run); diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 98396ee76..d91c98a77 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -74,9 +74,6 @@ namespace Game.Movement if (!_owner) return; - if (_owner.HasUnitState(UnitState.Root | UnitState.Stunned)) - return; - Cypher.Assert(!Empty()); _cleanFlag |= MMCleanFlag.Update; @@ -263,7 +260,7 @@ namespace Game.Movement MovePoint(id, pos.posX, pos.posY, pos.posZ, generatePath); } - public void MovePoint(ulong id, float x, float y, float z, bool generatePath = true) + public void MovePoint(uint id, float x, float y, float z, bool generatePath = true) { if (_owner.IsTypeId(TypeId.Player)) StartMovement(new PointMovementGenerator(id, x, y, z, generatePath), MovementSlot.Active);