From 21b8c4997a260b5e2dc24ab07df17d3daa6b8b5d Mon Sep 17 00:00:00 2001 From: ccrs Date: Fri, 7 Apr 2017 21:35:23 +0200 Subject: [PATCH] [3.3.5] Core/Movement: MotionMaster & MovementGenerators cleaning (#19361) --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Entities/Unit/Unit.h | 2 +- src/server/game/Movement/MotionMaster.cpp | 9 +- src/server/game/Movement/MotionMaster.h | 2 +- src/server/game/Movement/MovementGenerator.h | 17 +- .../game/Movement/MovementGeneratorImpl.h | 8 +- .../ConfusedMovementGenerator.cpp | 111 +++-- .../ConfusedMovementGenerator.h | 13 +- .../FleeingMovementGenerator.cpp | 258 +++++----- .../FleeingMovementGenerator.h | 24 +- .../HomeMovementGenerator.cpp | 81 +++- .../HomeMovementGenerator.h | 32 +- .../IdleMovementGenerator.cpp | 42 +- .../IdleMovementGenerator.h | 15 +- .../PointMovementGenerator.cpp | 151 +++--- .../PointMovementGenerator.h | 38 +- .../RandomMovementGenerator.cpp | 223 ++++----- .../RandomMovementGenerator.h | 23 +- .../TargetedMovementGenerator.cpp | 458 ++++++++++-------- .../TargetedMovementGenerator.h | 100 ++-- 20 files changed, 843 insertions(+), 766 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a5f8c98c290..87d7bd7e9c2 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9339,7 +9339,7 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate) m_speed_rate[mtype] = rate; - propagateSpeedChange(); + PropagateSpeedChange(); // Spline packets are for units controlled by AI. "Force speed change" (wrongly named opcodes) and "move set speed" packets are for units controlled by a player. static Opcodes const moveTypeToOpcode[MAX_MOVE_TYPE][3] = diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 3a5414c4db9..c6f78865dc2 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2134,7 +2134,7 @@ class TC_GAME_API Unit : public WorldObject void SendPetAIReaction(ObjectGuid guid); ///----------End of Pet responses methods---------- - void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); } + void PropagateSpeedChange() { GetMotionMaster()->PropagateSpeedChange(); } // reactive attacks void ClearAllReactives(); diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index c91fb0692df..4d5e2f9036b 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -75,7 +75,7 @@ void MotionMaster::InitDefault() if (_owner->GetTypeId() == TYPEID_UNIT) { MovementGenerator* movement = FactorySelector::selectMovementGenerator(_owner->ToCreature()); - Mutate(movement == NULL ? &si_idleMovement : movement, MOTION_SLOT_IDLE); + Mutate(movement == nullptr ? &si_idleMovement : movement, MOTION_SLOT_IDLE); } else { @@ -88,9 +88,6 @@ void MotionMaster::UpdateMotion(uint32 diff) if (!_owner) return; - if (_owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) // what about UNIT_STATE_DISTRACTED? Why is this not included? - return; - ASSERT(!empty()); _cleanFlag |= MMCF_UPDATE; @@ -173,12 +170,12 @@ MovementGenerator* MotionMaster::GetMotionSlot(int slot) const return _slot[slot]; } -void MotionMaster::propagateSpeedChange() +void MotionMaster::PropagateSpeedChange() { for (int i = 0; i <= _top; ++i) { if (_slot[i]) - _slot[i]->unitSpeedChanged(); + _slot[i]->UnitSpeedChanged(); } } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 0976076f0af..b2ea200b0b1 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -108,7 +108,7 @@ class TC_GAME_API MotionMaster MovementGeneratorType GetMotionSlotType(int slot) const; MovementGenerator* GetMotionSlot(int slot) const; - void propagateSpeedChange(); + void PropagateSpeedChange(); bool GetDestination(float &x, float &y, float &z); diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index ed8726b2ff6..8119c2d2599 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -34,14 +34,12 @@ class TC_GAME_API MovementGenerator virtual void Initialize(Unit*) = 0; virtual void Finalize(Unit*) = 0; - virtual void Reset(Unit*) = 0; - - virtual bool Update(Unit*, uint32 time_diff) = 0; + virtual bool Update(Unit*, uint32 diff) = 0; virtual MovementGeneratorType GetMovementGeneratorType() const = 0; - virtual void unitSpeedChanged() { } + virtual void UnitSpeedChanged() { } // used by Evade code for select point to evade with expected restart default movement virtual bool GetResetPosition(Unit*, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } @@ -53,42 +51,39 @@ class MovementGeneratorMedium : public MovementGenerator public: void Initialize(Unit* u) override { - //u->AssertIsType(); (static_cast(this))->DoInitialize(static_cast(u)); } void Finalize(Unit* u) override { - //u->AssertIsType(); (static_cast(this))->DoFinalize(static_cast(u)); } void Reset(Unit* u) override { - //u->AssertIsType(); (static_cast(this))->DoReset(static_cast(u)); } bool Update(Unit* u, uint32 time_diff) override { - //u->AssertIsType(); return (static_cast(this))->DoUpdate(static_cast(u), time_diff); } }; struct SelectableMovement : public FactoryHolder { - SelectableMovement(MovementGeneratorType mgt) : FactoryHolder(mgt) { } + SelectableMovement(MovementGeneratorType movementGeneratorType) : FactoryHolder(movementGeneratorType) { } }; -template +template struct MovementGeneratorFactory : public SelectableMovement { - MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) { } + MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : SelectableMovement(movementGeneratorType) { } MovementGenerator* Create(void *) const override; }; typedef FactoryHolder MovementGeneratorCreator; typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; + #endif diff --git a/src/server/game/Movement/MovementGeneratorImpl.h b/src/server/game/Movement/MovementGeneratorImpl.h index dd73055710c..3488de8534a 100644 --- a/src/server/game/Movement/MovementGeneratorImpl.h +++ b/src/server/game/Movement/MovementGeneratorImpl.h @@ -21,10 +21,10 @@ #include "MovementGenerator.h" -template -inline MovementGenerator* -MovementGeneratorFactory::Create(void * /*data*/) const +template +inline MovementGenerator* MovementGeneratorFactory::Create(void * /*data*/) const { - return (new MOVEMENT_GEN()); + return (new Movement()); } + #endif diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index b54aef633ef..48524d9c663 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -17,91 +17,94 @@ */ #include "Creature.h" -#include "ConfusedMovementGenerator.h" +#include "Player.h" #include "PathGenerator.h" #include "MoveSplineInit.h" #include "MoveSpline.h" -#include "Player.h" +#include "ConfusedMovementGenerator.h" template -void ConfusedMovementGenerator::DoInitialize(T* unit) +ConfusedMovementGenerator::~ConfusedMovementGenerator() { - unit->AddUnitState(UNIT_STATE_CONFUSED); - unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit->GetPosition(i_x, i_y, i_z); - - if (!unit->IsAlive() || unit->IsStopped()) - return; - - unit->StopMoving(); - unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); + delete _path; } template -void ConfusedMovementGenerator::DoReset(T* unit) +void ConfusedMovementGenerator::DoInitialize(T* owner) { - i_nextMoveTime.Reset(0); - - if (!unit->IsAlive() || unit->IsStopped()) + if (!owner || !owner->IsAlive()) return; - unit->StopMoving(); - unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + owner->AddUnitState(UNIT_STATE_CONFUSED); + owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + owner->StopMoving(); + + _timer.Reset(0); + owner->GetPosition(_reference.x, _reference.y, _reference.z); } template -bool ConfusedMovementGenerator::DoUpdate(T* unit, uint32 diff) +void ConfusedMovementGenerator::DoReset(T* owner) { - if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) - return true; + DoInitialize(owner); +} - if (i_nextMoveTime.Passed()) +template +bool ConfusedMovementGenerator::DoUpdate(T* owner, uint32 diff) +{ + if (!owner || !owner->IsAlive()) + return false; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - // currently moving, update location - unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); - - if (unit->movespline->Finalized()) - i_nextMoveTime.Reset(urand(800, 1500)); + _interrupt = true; + owner->StopMoving(); + return true; } else + _interrupt = false; + + // waiting for next move + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) { - // waiting for next move - i_nextMoveTime.Update(diff); - if (i_nextMoveTime.Passed()) + // start moving + owner->AddUnitState(UNIT_STATE_CONFUSED_MOVE); + + Position destination(_reference); + float distance = 4.0f * frand(0.0f, 1.0f) - 2.0f; + float angle = frand(0.0f, 1.0f) * float(M_PI) * 2.0f; + owner->MovePositionToFirstCollision(destination, distance, angle); + + if (!_path) + _path = new PathGenerator(owner); + + _path->SetPathLengthLimit(30.0f); + bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) { - // start moving - unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); - - float dest = 4.0f * (float)rand_norm() - 2.0f; - - Position pos; - pos.Relocate(i_x, i_y, i_z); - unit->MovePositionToFirstCollision(pos, dest, 0.0f); - - PathGenerator path(unit); - path.SetPathLengthLimit(30.0f); - bool result = path.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ); - if (!result || (path.GetPathType() & PATHFIND_NOPATH)) - { - i_nextMoveTime.Reset(100); - return true; - } - - Movement::MoveSplineInit init(unit); - init.MovebyPath(path.GetPath()); - init.SetWalk(true); - init.Launch(); + _timer.Reset(100); + return true; } + + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); + init.SetWalk(true); + int32 traveltime = init.Launch(); + _timer.Reset(traveltime + urand(800, 1500)); } return true; } +template +void ConfusedMovementGenerator::DoFinalize(T*) { } + template<> void ConfusedMovementGenerator::DoFinalize(Player* unit) { unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + unit->ClearUnitState(UNIT_STATE_CONFUSED); unit->StopMoving(); } @@ -114,6 +117,8 @@ void ConfusedMovementGenerator::DoFinalize(Creature* unit) unit->SetTarget(unit->EnsureVictim()->GetGUID()); } +template ConfusedMovementGenerator::~ConfusedMovementGenerator(); +template ConfusedMovementGenerator::~ConfusedMovementGenerator(); template void ConfusedMovementGenerator::DoInitialize(Player*); template void ConfusedMovementGenerator::DoInitialize(Creature*); template void ConfusedMovementGenerator::DoReset(Player*); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h index a23a18cbcfe..95ba375de27 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h @@ -26,16 +26,21 @@ template class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator > { public: - explicit ConfusedMovementGenerator() : i_nextMoveTime(0), i_x(0), i_y(0), i_z(0) { } + explicit ConfusedMovementGenerator() : _path(nullptr), _timer(0), _reference(0.f, 0.f, 0.f), _interrupt(false) { } + ~ConfusedMovementGenerator(); + + MovementGeneratorType GetMovementGeneratorType() const override { return CONFUSED_MOTION_TYPE; } void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); - MovementGeneratorType GetMovementGeneratorType() const override { return CONFUSED_MOTION_TYPE; } private: - TimeTracker i_nextMoveTime; - float i_x, i_y, i_z; + PathGenerator* _path; + TimeTracker _timer; + G3D::Vector3 _reference; + bool _interrupt; }; + #endif diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 6bf8d0affdd..600aae8f8b3 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -16,108 +16,23 @@ * with this program. If not, see . */ -#include "Creature.h" +#include "VMapFactory.h" #include "CreatureAI.h" -#include "FleeingMovementGenerator.h" -#include "PathGenerator.h" #include "ObjectAccessor.h" +#include "Creature.h" +#include "Player.h" +#include "PathGenerator.h" #include "MoveSplineInit.h" #include "MoveSpline.h" -#include "Player.h" -#include "VMapFactory.h" +#include "FleeingMovementGenerator.h" #define MIN_QUIET_DISTANCE 28.0f #define MAX_QUIET_DISTANCE 43.0f template -void FleeingMovementGenerator::_setTargetLocation(T* owner) +FleeingMovementGenerator::~FleeingMovementGenerator() { - if (!owner) - return; - - if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) - return; - - if (owner->IsMovementPreventedByCasting()) - { - owner->CastStop(); - return; - } - - owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); - - float x, y, z; - _getPoint(owner, x, y, z); - - // Add LOS check for target point - Position mypos = owner->GetPosition(); - bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(), - mypos.m_positionX, - mypos.m_positionY, - mypos.m_positionZ + 2.0f, - x, y, z + 2.0f, - VMAP::ModelIgnoreFlags::Nothing); - if (!isInLOS) - { - i_nextCheckTime.Reset(200); - return; - } - - PathGenerator path(owner); - path.SetPathLengthLimit(30.0f); - bool result = path.CalculatePath(x, y, z); - if (!result || (path.GetPathType() & PATHFIND_NOPATH)) - { - i_nextCheckTime.Reset(100); - return; - } - - Movement::MoveSplineInit init(owner); - init.MovebyPath(path.GetPath()); - init.SetWalk(false); - int32 traveltime = init.Launch(); - i_nextCheckTime.Reset(traveltime + urand(800, 1500)); -} - -template -void FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float &z) -{ - float dist_from_caster, angle_to_caster; - if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID)) - { - dist_from_caster = fright->GetDistance(owner); - if (dist_from_caster > 0.2f) - angle_to_caster = fright->GetAngle(owner); - else - angle_to_caster = frand(0, 2 * static_cast(M_PI)); - } - else - { - dist_from_caster = 0.0f; - angle_to_caster = frand(0, 2 * static_cast(M_PI)); - } - - float dist, angle; - if (dist_from_caster < MIN_QUIET_DISTANCE) - { - dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster); - angle = angle_to_caster + frand(-static_cast(M_PI)/8, static_cast(M_PI)/8); - } - else if (dist_from_caster > MAX_QUIET_DISTANCE) - { - dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = -angle_to_caster + frand(-static_cast(M_PI)/4, static_cast(M_PI)/4); - } - else // we are inside quiet range - { - dist = frand(0.6f, 1.2f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = frand(0, 2*static_cast(M_PI)); - } - - Position pos = owner->GetFirstCollisionPosition(dist, angle); - x = pos.m_positionX; - y = pos.m_positionY; - z = pos.m_positionZ; + delete _path; } template @@ -127,15 +42,20 @@ void FleeingMovementGenerator::DoInitialize(T* owner) return; owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->AddUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); - _setTargetLocation(owner); + owner->AddUnitState(UNIT_STATE_FLEEING); + SetTargetLocation(owner); +} + +template +void FleeingMovementGenerator::DoFinalize(T *) +{ } template<> void FleeingMovementGenerator::DoFinalize(Player* owner) { owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); + owner->ClearUnitState(UNIT_STATE_FLEEING); owner->StopMoving(); } @@ -143,7 +63,7 @@ template<> void FleeingMovementGenerator::DoFinalize(Creature* owner) { owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); + owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); if (owner->GetVictim()) owner->SetTarget(owner->EnsureVictim()->GetGUID()); } @@ -155,39 +75,143 @@ void FleeingMovementGenerator::DoReset(T* owner) } template -bool FleeingMovementGenerator::DoUpdate(T* owner, uint32 time_diff) +bool FleeingMovementGenerator::DoUpdate(T* owner, uint32 diff) { if (!owner || !owner->IsAlive()) return false; - if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); + _interrupt = true; + owner->StopMoving(); return true; } + else + _interrupt = false; - i_nextCheckTime.Update(time_diff); - if (i_nextCheckTime.Passed() && owner->movespline->Finalized()) - _setTargetLocation(owner); + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) + SetTargetLocation(owner); return true; } +template +void FleeingMovementGenerator::SetTargetLocation(T* owner) +{ + if (!owner) + return; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) + { + _interrupt = true; + owner->StopMoving(); + return; + } + + owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); + + Position destination = owner->GetPosition(); + GetPoint(owner, destination); + + // Add LOS check for target point + Position currentPosition = owner->GetPosition(); + if (!VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(), currentPosition.m_positionX, currentPosition.m_positionY, currentPosition.m_positionZ + 1.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 1.0f, VMAP::ModelIgnoreFlags::Nothing)) + { + _timer.Reset(200); + return; + } + + if (!_path) + _path = new PathGenerator(owner); + + _path->SetPathLengthLimit(30.0f); + bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) + { + _timer.Reset(100); + return; + } + + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); + init.SetWalk(false); + int32 traveltime = init.Launch(); + _timer.Reset(traveltime + urand(800, 1500)); +} + +template +void FleeingMovementGenerator::GetPoint(T* owner, Position &position) +{ + float casterDistance, casterAngle; + if (Unit* fleeTarget = ObjectAccessor::GetUnit(*owner, _fleeTargetGUID)) + { + casterDistance = fleeTarget->GetDistance(owner); + if (casterDistance > 0.2f) + casterAngle = fleeTarget->GetAngle(owner); + else + casterAngle = frand(0.0f, 2.0f * float(M_PI)); + } + else + { + casterDistance = 0.0f; + casterAngle = frand(0.0f, 2.0f * float(M_PI)); + } + + float distance, angle; + if (casterDistance < MIN_QUIET_DISTANCE) + { + distance = frand(0.4f, 1.3f) * (MIN_QUIET_DISTANCE - casterDistance); + angle = casterAngle + frand(-float(M_PI) / 8.0f, float(M_PI) / 8.0f); + } + else if (casterDistance > MAX_QUIET_DISTANCE) + { + distance = frand(0.4f, 1.0f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = -casterAngle + frand(-float(M_PI) / 4.0f, float(M_PI) / 4.0f); + } + else // we are inside quiet range + { + distance = frand(0.6f, 1.2f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = frand(0.0f, 2.0f * float(M_PI)); + } + + owner->MovePositionToFirstCollision(position, distance, angle); +} + +template FleeingMovementGenerator::~FleeingMovementGenerator(); +template FleeingMovementGenerator::~FleeingMovementGenerator(); template void FleeingMovementGenerator::DoInitialize(Player*); template void FleeingMovementGenerator::DoInitialize(Creature*); -template void FleeingMovementGenerator::_getPoint(Player*, float&, float&, float&); -template void FleeingMovementGenerator::_getPoint(Creature*, float&, float&, float&); -template void FleeingMovementGenerator::_setTargetLocation(Player*); -template void FleeingMovementGenerator::_setTargetLocation(Creature*); template void FleeingMovementGenerator::DoReset(Player*); template void FleeingMovementGenerator::DoReset(Creature*); template bool FleeingMovementGenerator::DoUpdate(Player*, uint32); template bool FleeingMovementGenerator::DoUpdate(Creature*, uint32); +template void FleeingMovementGenerator::SetTargetLocation(Player*); +template void FleeingMovementGenerator::SetTargetLocation(Creature*); +template void FleeingMovementGenerator::GetPoint(Player*, Position &); +template void FleeingMovementGenerator::GetPoint(Creature*, Position &); + +//---- TimedFleeingMovementGenerator + +bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff) +{ + if (!owner->IsAlive()) + return false; + + _totalFleeTime.Update(time_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 MovementGeneratorMedium< Creature, FleeingMovementGenerator >::Update(owner, time_diff); +} void TimedFleeingMovementGenerator::Finalize(Unit* owner) { owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); + owner->ClearUnitState(UNIT_STATE_FLEEING); + owner->StopMoving(); if (Unit* victim = owner->GetVictim()) { if (owner->IsAlive()) @@ -197,23 +221,3 @@ void TimedFleeingMovementGenerator::Finalize(Unit* owner) } } } - -bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff) -{ - if (!owner->IsAlive()) - return false; - - if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) - { - owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); - return true; - } - - i_totalFleeTime.Update(time_diff); - if (i_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 MovementGeneratorMedium< Creature, FleeingMovementGenerator >::Update(owner, time_diff); -} diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index 5739107b41f..e75240929db 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -20,41 +20,43 @@ #define TRINITY_FLEEINGMOVEMENTGENERATOR_H #include "MovementGenerator.h" +#include "Timer.h" template class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator > { public: - FleeingMovementGenerator(ObjectGuid fright) : i_frightGUID(fright), i_nextCheckTime(0) { } + explicit FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _path(nullptr), _fleeTargetGUID(fleeTargetGUID), _timer(0), _interrupt(false) { } + ~FleeingMovementGenerator(); + + MovementGeneratorType GetMovementGeneratorType() const override { return FLEEING_MOTION_TYPE; } void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); - MovementGeneratorType GetMovementGeneratorType() const override { return FLEEING_MOTION_TYPE; } - private: - void _setTargetLocation(T*); - void _getPoint(T*, float &x, float &y, float &z); + void SetTargetLocation(T*); + void GetPoint(T*, Position &position); - ObjectGuid i_frightGUID; - TimeTracker i_nextCheckTime; + PathGenerator* _path; + ObjectGuid _fleeTargetGUID; + TimeTracker _timer; + bool _interrupt; }; class TimedFleeingMovementGenerator : public FleeingMovementGenerator { public: - TimedFleeingMovementGenerator(ObjectGuid fright, uint32 time) : - FleeingMovementGenerator(fright), - i_totalFleeTime(time) { } + explicit TimedFleeingMovementGenerator(ObjectGuid fleeTargetGUID, uint32 time) : FleeingMovementGenerator(fleeTargetGUID), _totalFleeTime(time) { } MovementGeneratorType GetMovementGeneratorType() const override { return TIMED_FLEEING_MOTION_TYPE; } bool Update(Unit*, uint32) override; void Finalize(Unit*) override; private: - TimeTracker i_totalFleeTime; + TimeTracker _totalFleeTime; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 21fc465d0b2..6bd2ba9377b 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -16,36 +16,30 @@ * with this program. If not, see . */ -#include "HomeMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" #include "MoveSplineInit.h" #include "MoveSpline.h" +#include "HomeMovementGenerator.h" -void HomeMovementGenerator::DoInitialize(Creature* owner) +template +HomeMovementGenerator::~HomeMovementGenerator() { } + +template<> +HomeMovementGenerator::~HomeMovementGenerator() { - _setTargetLocation(owner); + delete _path; } -void HomeMovementGenerator::DoFinalize(Creature* owner) -{ - if (arrived) - { - owner->ClearUnitState(UNIT_STATE_EVADE); - owner->SetWalk(true); - owner->LoadCreaturesAddon(); - owner->AI()->JustReachedHome(); - owner->SetSpawnHealth(); - } -} +template +void HomeMovementGenerator::SetTargetLocation(T*) { } -void HomeMovementGenerator::DoReset(Creature*) { } - -void HomeMovementGenerator::_setTargetLocation(Creature* owner) +template<> +void HomeMovementGenerator::SetTargetLocation(Creature* owner) { if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_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; } @@ -61,14 +55,55 @@ void HomeMovementGenerator::_setTargetLocation(Creature* owner) init.SetWalk(false); init.Launch(); - skipToHome = false; - arrived = false; + _skipToHome = false; + _arrived = false; owner->ClearUnitState(UNIT_STATE_ALL_ERASABLE & ~UNIT_STATE_EVADE); } -bool HomeMovementGenerator::DoUpdate(Creature* owner, const uint32 /*time_diff*/) +template +void HomeMovementGenerator::DoInitialize(T*) { } + +template<> +void HomeMovementGenerator::DoInitialize(Creature* owner) { - arrived = skipToHome || owner->movespline->Finalized(); - return !arrived; + SetTargetLocation(owner); +} + +template +void HomeMovementGenerator::DoFinalize(T*) { } + +template<> +void HomeMovementGenerator::DoFinalize(Creature* owner) +{ + if (_arrived) + { + owner->ClearUnitState(UNIT_STATE_EVADE); + owner->SetWalk(true); + owner->LoadCreaturesAddon(); + owner->AI()->JustReachedHome(); + owner->SetSpawnHealth(); + } +} + +template +void HomeMovementGenerator::DoReset(T*) { } + +template<> +void HomeMovementGenerator::DoReset(Creature* owner) +{ + DoInitialize(owner); +} + +template +bool HomeMovementGenerator::DoUpdate(T*, uint32) +{ + return false; +} + +template<> +bool HomeMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/) +{ + _arrived = _skipToHome || owner->movespline->Finalized(); + return !_arrived; } diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h index e332c06df97..4674f99b3de 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h @@ -21,28 +21,26 @@ #include "MovementGenerator.h" -class Creature; - -template < class T > -class HomeMovementGenerator; - -template <> -class HomeMovementGenerator : public MovementGeneratorMedium< Creature, HomeMovementGenerator > +template +class HomeMovementGenerator : public MovementGeneratorMedium< T, HomeMovementGenerator > { public: + explicit HomeMovementGenerator() : _path(nullptr), _arrived(false), _skipToHome(false) { } + ~HomeMovementGenerator(); - HomeMovementGenerator() : arrived(false), skipToHome(false) { } - ~HomeMovementGenerator() { } - - void DoInitialize(Creature*); - void DoFinalize(Creature*); - void DoReset(Creature*); - bool DoUpdate(Creature*, const uint32); MovementGeneratorType GetMovementGeneratorType() const override { return HOME_MOTION_TYPE; } + void DoInitialize(T*); + void DoFinalize(T*); + void DoReset(T*); + bool DoUpdate(T*, uint32); + private: - void _setTargetLocation(Creature*); - bool arrived; - bool skipToHome; + void SetTargetLocation(T*); + + PathGenerator* _path; + bool _arrived; + bool _skipToHome; }; + #endif diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index 78bacc161af..97d526a47c5 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -35,6 +35,8 @@ void IdleMovementGenerator::Reset(Unit* owner) owner->StopMoving(); } +//----------------------------------------------------// + void RotateMovementGenerator::Initialize(Unit* owner) { if (!owner->IsStopped()) @@ -51,34 +53,38 @@ void RotateMovementGenerator::Initialize(Unit* owner) bool RotateMovementGenerator::Update(Unit* owner, uint32 diff) { float angle = owner->GetOrientation(); - if (m_direction == ROTATE_DIRECTION_LEFT) + if (_direction == ROTATE_DIRECTION_LEFT) { - angle += (float)diff * static_cast(M_PI * 2) / m_maxDuration; - while (angle >= static_cast(M_PI * 2)) angle -= static_cast(M_PI * 2); + angle += float(diff) * float(M_PI) * 2.f / float(_maxDuration); + while (angle >= float(M_PI) * 2.f) + angle -= float(M_PI) * 2.f; } else { - angle -= (float)diff * static_cast(M_PI * 2) / m_maxDuration; - while (angle < 0) angle += static_cast(M_PI * 2); + angle -= float(diff) * float(M_PI) * 2.f / float(_maxDuration); + while (angle < 0.f) + angle += float(M_PI) * 2.f; } owner->SetFacingTo(angle); - if (m_duration > diff) - m_duration -= diff; + if (_duration > diff) + _duration -= diff; else return false; return true; } -void RotateMovementGenerator::Finalize(Unit* unit) +void RotateMovementGenerator::Finalize(Unit* owner) { - unit->ClearUnitState(UNIT_STATE_ROTATING); - if (unit->GetTypeId() == TYPEID_UNIT) - unit->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0); + owner->ClearUnitState(UNIT_STATE_ROTATING); + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0); } +//----------------------------------------------------// + void DistractMovementGenerator::Initialize(Unit* owner) { // Distracted creatures stand up if not standing @@ -100,17 +106,19 @@ void DistractMovementGenerator::Finalize(Unit* owner) } } -bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 time_diff) +bool DistractMovementGenerator::Update(Unit* /*owner*/, uint32 diff) { - if (time_diff > m_timer) + if (diff > _timer) return false; - m_timer -= time_diff; + _timer -= diff; return true; } -void AssistanceDistractMovementGenerator::Finalize(Unit* unit) +//----------------------------------------------------// + +void AssistanceDistractMovementGenerator::Finalize(Unit* owner) { - unit->ClearUnitState(UNIT_STATE_DISTRACTED); - unit->ToCreature()->SetReactState(REACT_AGGRESSIVE); + owner->ClearUnitState(UNIT_STATE_DISTRACTED); + owner->ToCreature()->SetReactState(REACT_AGGRESSIVE); } diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index 29846f42614..68ad0d775e9 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -20,11 +20,11 @@ #define TRINITY_IDLEMOVEMENTGENERATOR_H #include "MovementGenerator.h" +#include "Timer.h" class IdleMovementGenerator : public MovementGenerator { public: - void Initialize(Unit*) override; void Finalize(Unit*) override { } void Reset(Unit*) override; @@ -37,7 +37,7 @@ TC_GAME_API extern IdleMovementGenerator si_idleMovement; class RotateMovementGenerator : public MovementGenerator { public: - explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) { } + explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : _duration(time), _maxDuration(time), _direction(direction) { } void Initialize(Unit*) override; void Finalize(Unit*) override; @@ -46,14 +46,14 @@ class RotateMovementGenerator : public MovementGenerator MovementGeneratorType GetMovementGeneratorType() const override { return ROTATE_MOTION_TYPE; } private: - uint32 m_duration, m_maxDuration; - RotateDirection m_direction; + uint32 _duration, _maxDuration; + RotateDirection _direction; }; class DistractMovementGenerator : public MovementGenerator { public: - explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) { } + explicit DistractMovementGenerator(uint32 timer) : _timer(timer) { } void Initialize(Unit*) override; void Finalize(Unit*) override; @@ -62,14 +62,13 @@ class DistractMovementGenerator : public MovementGenerator MovementGeneratorType GetMovementGeneratorType() const override { return DISTRACT_MOTION_TYPE; } private: - uint32 m_timer; + uint32 _timer; }; class AssistanceDistractMovementGenerator : public DistractMovementGenerator { public: - AssistanceDistractMovementGenerator(uint32 timer) : - DistractMovementGenerator(timer) { } + explicit AssistanceDistractMovementGenerator(uint32 timer) : DistractMovementGenerator(timer) { } MovementGeneratorType GetMovementGeneratorType() const override { return ASSISTANCE_DISTRACT_MOTION_TYPE; } void Finalize(Unit*) override; diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index bdde0222027..b3fa1c68e99 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -16,98 +16,111 @@ * with this program. If not, see . */ -#include "PointMovementGenerator.h" -#include "Errors.h" -#include "Creature.h" #include "CreatureAI.h" -#include "World.h" +#include "Creature.h" +#include "CreatureGroups.h" +#include "Player.h" #include "MoveSplineInit.h" #include "MoveSpline.h" -#include "Player.h" -#include "CreatureGroups.h" +#include "World.h" +#include "PointMovementGenerator.h" //----- Point Movement Generator + template -void PointMovementGenerator::DoInitialize(T* unit) +void PointMovementGenerator::DoInitialize(T* owner) { - if (!unit->IsStopped()) - unit->StopMoving(); - - unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - - if (id == EVENT_CHARGE_PREPATH) + if (_movementId == EVENT_CHARGE_PREPATH) + { + owner->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); return; + } - Movement::MoveSplineInit init(unit); - init.MoveTo(i_x, i_y, i_z, m_generatePath); - if (speed > 0.0f) - init.SetVelocity(speed); + owner->AddUnitState(UNIT_STATE_ROAMING); + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) + { + _interrupt = true; + owner->StopMoving(); + return; + } + + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); + + Movement::MoveSplineInit init(owner); + init.MoveTo(_destination, _generatePath); + if (_speed > 0.0f) + init.SetVelocity(_speed); init.Launch(); // Call for creature group update - if (Creature* creature = unit->ToCreature()) + if (Creature* creature = owner->ToCreature()) if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(i_x, i_y, i_z); + creature->GetFormation()->LeaderMoveTo(_destination.x, _destination.y, _destination.z); } template -bool PointMovementGenerator::DoUpdate(T* unit, uint32 /*diff*/) +bool PointMovementGenerator::DoUpdate(T* owner, uint32 /*diff*/) { - if (!unit) + if (!owner) return false; - if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + if (_movementId == EVENT_CHARGE_PREPATH) + return !owner->movespline->Finalized(); + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - unit->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + _interrupt = true; + owner->StopMoving(); return true; } - unit->AddUnitState(UNIT_STATE_ROAMING_MOVE); - - if (id != EVENT_CHARGE_PREPATH && i_recalculateSpeed && !unit->movespline->Finalized()) + if ((_interrupt && owner->movespline->Finalized()) || (_recalculateSpeed && !owner->movespline->Finalized())) { - i_recalculateSpeed = false; - Movement::MoveSplineInit init(unit); - 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); + _recalculateSpeed = false; + _interrupt = false; + + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); + + Movement::MoveSplineInit init(owner); + init.MoveTo(_destination, _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 - if (Creature* creature = unit->ToCreature()) + if (Creature* creature = owner->ToCreature()) if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(i_x, i_y, i_z); + creature->GetFormation()->LeaderMoveTo(_destination.x, _destination.y, _destination.z); } - return !unit->movespline->Finalized(); + return !owner->movespline->Finalized(); } template -void PointMovementGenerator::DoFinalize(T* unit) +void PointMovementGenerator::DoFinalize(T* owner) { - if (unit->HasUnitState(UNIT_STATE_CHARGING)) - unit->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); + owner->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - if (unit->movespline->Finalized()) - MovementInform(unit); + if (owner->movespline->Finalized()) + MovementInform(owner); } template -void PointMovementGenerator::DoReset(T* unit) +void PointMovementGenerator::DoReset(T* owner) { - if (!unit->IsStopped()) - unit->StopMoving(); - - unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + owner->StopMoving(); + DoInitialize(owner); } template -void PointMovementGenerator::MovementInform(T* /*unit*/) { } +void PointMovementGenerator::MovementInform(T*) { } -template <> void PointMovementGenerator::MovementInform(Creature* unit) +template <> +void PointMovementGenerator::MovementInform(Creature* owner) { - if (unit->AI()) - unit->AI()->MovementInform(POINT_MOTION_TYPE, id); + if (owner->AI()) + owner->AI()->MovementInform(POINT_MOTION_TYPE, _movementId); } template void PointMovementGenerator::DoInitialize(Player*); @@ -119,31 +132,33 @@ template void PointMovementGenerator::DoReset(Creature*); template bool PointMovementGenerator::DoUpdate(Player*, uint32); template bool PointMovementGenerator::DoUpdate(Creature*, uint32); -void AssistanceMovementGenerator::Finalize(Unit* unit) +//---- AssistanceMovementGenerator + +void AssistanceMovementGenerator::Finalize(Unit* owner) { - unit->ToCreature()->SetNoCallAssistance(false); - unit->ToCreature()->CallAssistance(); - if (unit->IsAlive()) - unit->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); + owner->ClearUnitState(UNIT_STATE_ROAMING); + owner->StopMoving(); + owner->ToCreature()->SetNoCallAssistance(false); + owner->ToCreature()->CallAssistance(); + if (owner->IsAlive()) + owner->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); } -bool EffectMovementGenerator::Update(Unit* unit, uint32) +//---- EffectMovementGenerator + +bool EffectMovementGenerator::Update(Unit* owner, uint32 /*diff*/) { - return !unit->movespline->Finalized(); + return !owner->movespline->Finalized(); } -void EffectMovementGenerator::Finalize(Unit* unit) +void EffectMovementGenerator::Finalize(Unit* owner) { - if (unit->GetTypeId() != TYPEID_UNIT) - return; - - // Need restore previous movement since we have no proper states system - if (unit->IsAlive() && !unit->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING)) - { - if (Unit* victim = unit->GetVictim()) - unit->GetMotionMaster()->MoveChase(victim); - } - - if (unit->ToCreature()->AI()) - unit->ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id); + MovementInform(owner); +} + +void EffectMovementGenerator::MovementInform(Unit* owner) +{ + if (Creature* creature = owner->ToCreature()) + if (creature->AI()) + creature->AI()->MovementInform(EFFECT_MOTION_TYPE, _pointId); } diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 2e5eda776ed..f68021c51c4 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -20,57 +20,57 @@ #define TRINITY_POINTMOVEMENTGENERATOR_H #include "MovementGenerator.h" -#include "FollowerReference.h" template class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator > { public: - PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f) : id(_id), - i_x(_x), i_y(_y), i_z(_z), speed(_speed), m_generatePath(_generatePath), i_recalculateSpeed(false) { } + explicit PointMovementGenerator(uint32 id, float x, float y, float z, bool generatePath, float speed = 0.0f) : _movementId(id), _destination(x, y, z), _speed(speed), _generatePath(generatePath), _recalculateSpeed(false), _interrupt(false) { } + + MovementGeneratorType GetMovementGeneratorType() const override { return POINT_MOTION_TYPE; } void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); + void UnitSpeedChanged() override { _recalculateSpeed = true; } + + private: void MovementInform(T*); - void unitSpeedChanged() override { i_recalculateSpeed = true; } - - MovementGeneratorType GetMovementGeneratorType() const override { return POINT_MOTION_TYPE; } - - void GetDestination(float& x, float& y, float& z) const { x = i_x; y = i_y; z = i_z; } - private: - uint32 id; - float i_x, i_y, i_z; - float speed; - bool m_generatePath; - bool i_recalculateSpeed; + uint32 _movementId; + G3D::Vector3 _destination; + float _speed; + bool _generatePath; + bool _recalculateSpeed; + bool _interrupt; }; class AssistanceMovementGenerator : public PointMovementGenerator { public: - AssistanceMovementGenerator(float _x, float _y, float _z) : - PointMovementGenerator(0, _x, _y, _z, true) { } + explicit AssistanceMovementGenerator(float _x, float _y, float _z) : PointMovementGenerator(0, _x, _y, _z, true) { } MovementGeneratorType GetMovementGeneratorType() const override { return ASSISTANCE_MOTION_TYPE; } void Finalize(Unit*) override; }; -// Does almost nothing - just doesn't allows previous movegen interrupt current effect. class EffectMovementGenerator : public MovementGenerator { public: - explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) { } + explicit EffectMovementGenerator(uint32 id) : _pointId(id) { } + void Initialize(Unit*) override { } void Finalize(Unit*) override; void Reset(Unit*) override { } bool Update(Unit*, uint32) override; MovementGeneratorType GetMovementGeneratorType() const override { return EFFECT_MOTION_TYPE; } + private: - uint32 m_Id; + void MovementInform(Unit*); + + uint32 _pointId; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 9b3f4c0060d..6f9738976a8 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -17,164 +17,131 @@ */ #include "Creature.h" -#include "RandomMovementGenerator.h" -#include "Map.h" -#include "Util.h" #include "CreatureGroups.h" +#include "Map.h" #include "MoveSplineInit.h" #include "MoveSpline.h" +#include "RandomMovementGenerator.h" -#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV" +template +RandomMovementGenerator::~RandomMovementGenerator() { } template<> -void RandomMovementGenerator::_setRandomLocation(Creature* creature) +RandomMovementGenerator::~RandomMovementGenerator() { - if (creature->IsMovementPreventedByCasting()) + delete _path; +} + +template +void RandomMovementGenerator::DoInitialize(T*) { } + +template<> +void RandomMovementGenerator::DoInitialize(Creature* owner) +{ + if (!owner || !owner->IsAlive()) + return; + + owner->AddUnitState(UNIT_STATE_ROAMING); + owner->GetPosition(_reference.x, _reference.y, _reference.z); + owner->StopMoving(); + + if (!_wanderDistance) + _wanderDistance = owner->GetRespawnRadius(); + + _timer.Reset(0); +} + +template +void RandomMovementGenerator::DoFinalize(T*) { } + +template<> +void RandomMovementGenerator::DoFinalize(Creature* owner) +{ + owner->ClearUnitState(UNIT_STATE_ROAMING); + owner->StopMoving(); + owner->SetWalk(false); +} + +template +void RandomMovementGenerator::DoReset(T*) { } + +template<> +void RandomMovementGenerator::DoReset(Creature* owner) +{ + DoInitialize(owner); +} + +template +void RandomMovementGenerator::SetRandomLocation(T*) { } + +template<> +void RandomMovementGenerator::SetRandomLocation(Creature* owner) +{ + if (!owner) + return; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - creature->CastStop(); + _interrupt = true; + owner->StopMoving(); return; } - float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; - creature->GetHomePosition(respX, respY, respZ, respO); - Map const* map = creature->GetBaseMap(); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - // For 2D/3D system selection - //bool is_land_ok = creature.CanWalk(); // not used? - //bool is_water_ok = creature.CanSwim(); // not used? - bool is_air_ok = creature->CanFly(); + Position position(_reference); + float distance = frand(0.f, 1.f) * _wanderDistance; + float angle = frand(0.f, 1.f) * float(M_PI) * 2.f; + owner->MovePositionToFirstCollision(position, distance, angle); - const float angle = float(rand_norm()) * static_cast(M_PI*2.0f); - const float range = float(rand_norm()) * wander_distance; - const float distanceX = range * std::cos(angle); - const float distanceY = range * std::sin(angle); + uint32 resetTimer = roll_chance_i(50) ? urand(5000, 10000) : urand(1000, 2000); - destX = respX + distanceX; - destY = respY + distanceY; + if (!_path) + _path = new PathGenerator(owner); - // prevent invalid coordinates generation - Trinity::NormalizeMapCoord(destX); - Trinity::NormalizeMapCoord(destY); - - 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) + _path->SetPathLengthLimit(30.0f); + bool result = _path->CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) { - // Limit height change - const float distanceZ = float(rand_norm()) * travelDistZ/2.0f; - destZ = respZ + distanceZ; - float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseMask(), 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 if (is_water_ok) // 3D system under water and above ground (swimming mode) - 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->GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, false); - - if (std::fabs(destZ - respZ) > travelDistZ) // Map check - { - // Vmap Horizontal or above - destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ - 2.0f, true); - - if (std::fabs(destZ - respZ) > travelDistZ) - { - // Vmap Higher - destZ = map->GetHeight(creature->GetPhaseMask(), 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 (std::fabs(destZ - respZ) > travelDistZ) - return; - } - } + _timer.Reset(100); + return; } - if (is_air_ok) - i_nextMoveTime.Reset(0); - else - { - if (roll_chance_i(50)) - i_nextMoveTime.Reset(urand(5000, 10000)); - else - i_nextMoveTime.Reset(urand(50, 400)); - } - - creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); - - Movement::MoveSplineInit init(creature); - init.MoveTo(destX, destY, destZ); + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); init.SetWalk(true); - init.Launch(); + int32 traveltime = init.Launch(); + _timer.Reset(traveltime + resetTimer); - //Call for creature group update - if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(destX, destY, destZ); + // Call for creature group update + if (owner->GetFormation() && owner->GetFormation()->getLeader() == owner) + owner->GetFormation()->LeaderMoveTo(position.m_positionX, position.m_positionY, position.m_positionZ); +} + +template +bool RandomMovementGenerator::DoUpdate(T*, uint32) +{ + return false; } template<> -void RandomMovementGenerator::DoInitialize(Creature* creature) +bool RandomMovementGenerator::DoUpdate(Creature* owner, uint32 diff) { - if (!creature->IsAlive()) - return; - - if (!wander_distance) - wander_distance = creature->GetRespawnRadius(); - - creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - _setRandomLocation(creature); -} - -template<> -void RandomMovementGenerator::DoReset(Creature* creature) -{ - DoInitialize(creature); -} - -template<> -void RandomMovementGenerator::DoFinalize(Creature* creature) -{ - creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - creature->SetWalk(false); -} - -template<> -bool RandomMovementGenerator::DoUpdate(Creature* creature, const uint32 diff) -{ - if (!creature || !creature->IsAlive()) + if (!owner || !owner->IsAlive()) return false; - if (creature->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - i_nextMoveTime.Reset(0); // Expire the timer - creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + _interrupt = true; + owner->StopMoving(); return true; } + else + _interrupt = false; - if (creature->movespline->Finalized()) - { - i_nextMoveTime.Update(diff); - if (i_nextMoveTime.Passed()) - _setRandomLocation(creature); - } - return true; -} - -template<> -bool RandomMovementGenerator::GetResetPos(Creature* creature, float& x, float& y, float& z) -{ - float radius; - creature->GetRespawnPosition(x, y, z, NULL, &radius); - - // use current if in range - if (creature->IsWithinDist2d(x, y, radius)) - creature->GetPosition(x, y, z); + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) + SetRandomLocation(owner); return true; } diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index 9a4f22f60e8..5bf0eb03f32 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -20,23 +20,30 @@ #define TRINITY_RANDOMMOTIONGENERATOR_H #include "MovementGenerator.h" +#include "Timer.h" template class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator > { public: - RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) { } + explicit RandomMovementGenerator(float distance = 0.0f) : _path(nullptr), _timer(0), _reference(0.f, 0.f, 0.f), _wanderDistance(distance), _interrupt(false) { } + ~RandomMovementGenerator(); + + MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; } - void _setRandomLocation(T*); void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); - bool DoUpdate(T*, const uint32); - bool GetResetPos(T*, float& x, float& y, float& z); - MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; } - private: - TimeTrackerSmall i_nextMoveTime; + bool DoUpdate(T*, uint32); - float wander_distance; + private: + void SetRandomLocation(T*); + + PathGenerator* _path; + TimeTracker _timer; + G3D::Vector3 _reference; + float _wanderDistance; + bool _interrupt; }; + #endif diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 48e55c9960f..1e6a01a08f4 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -16,226 +16,208 @@ * with this program. If not, see . */ -#include "ByteBuffer.h" -#include "TargetedMovementGenerator.h" -#include "Errors.h" -#include "Creature.h" #include "CreatureAI.h" -#include "World.h" -#include "MoveSplineInit.h" -#include "MoveSpline.h" +#include "Creature.h" #include "Player.h" #include "VehicleDefines.h" +#include "MoveSplineInit.h" +#include "MoveSpline.h" +#include "World.h" +#include "TargetedMovementGenerator.h" template -void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool updateDestination) +TargetedMovementGenerator::~TargetedMovementGenerator() { - if (!i_target.isValid() || !i_target->IsInWorld()) - return; - - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) - return; - - if (owner->IsMovementPreventedByCasting()) - return; - - if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature())) - { - owner->ToCreature()->SetCannotReachTarget(true); - return; - } - - if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true)) - return; - - float x, y, z; - - if (updateDestination || !i_path) - { - if (!i_offset) - { - if (i_target->IsWithinDistInMap(owner, CONTACT_DISTANCE)) - return; - - // to nearest contact position - i_target->GetContactPoint(owner, x, y, z); - } - else - { - float dist; - float size; - - // 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() && i_target->GetTypeId() == TYPEID_PLAYER) - { - dist = 1.0f; //i_target->GetCombatReach(); - size = 1.0f; //i_target->GetCombatReach() - i_target->GetCombatReach(); - } - else - { - dist = i_offset + 1.0f; - size = owner->GetCombatReach(); - } - - if (i_target->IsWithinDistInMap(owner, dist)) - return; - - // to at i_offset distance from target and i_angle from target facing - i_target->GetClosePoint(x, y, z, size, i_offset, i_angle); - } - } - else - { - // the destination has not changed, we just need to refresh the path (usually speed change) - G3D::Vector3 end = i_path->GetEndPosition(); - x = end.x; - y = end.y; - z = end.z; - } - - if (!i_path) - i_path = new PathGenerator(owner); - - // allow pets to use shortcut if no path found when following their master - bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsPet() - && owner->HasUnitState(UNIT_STATE_FOLLOW)); - - bool result = i_path->CalculatePath(x, y, z, forceDest); - if (!result || (i_path->GetPathType() & PATHFIND_NOPATH)) - { - // can't reach target - i_recalculateTravel = true; - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->SetCannotReachTarget(true); - return; - } - - D::_addUnitStateMove(owner); - i_targetReached = false; - i_recalculateTravel = false; - owner->AddUnitState(UNIT_STATE_CHASE); - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->SetCannotReachTarget(false); - - Movement::MoveSplineInit init(owner); - init.MovebyPath(i_path->GetPath()); - init.SetWalk(((D*)this)->EnableWalking()); - // Using the same condition for facing target as the one that is used for SetInFront on movement end - // - applies to ChaseMovementGenerator mostly - if (i_angle == 0.f) - init.SetFacing(i_target.getTarget()); - - init.Launch(); + delete _path; } template -bool TargetedMovementGeneratorMedium::DoUpdate(T* owner, uint32 time_diff) +bool TargetedMovementGenerator::DoUpdate(T* owner, uint32 diff) { - if (!i_target.isValid() || !i_target->IsInWorld()) + if (!IsTargetValid() || !GetTarget()->IsInWorld()) return false; if (!owner || !owner->IsAlive()) return false; - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner) + || (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true))) { - D::_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(); - return true; - } - - // prevent crash after creature killed pet - if (static_cast(this)->_lostTarget(owner)) - { - D::_clearUnitStateMove(owner); + _interrupt = false; + SetTargetLocation(owner, true); return true; } bool targetMoved = false; - i_recheckDistance.Update(time_diff); - if (i_recheckDistance.Passed()) + _timer.Update(diff); + if (!_interrupt && _timer.Passed()) { - i_recheckDistance.Reset(100); + _timer.Reset(100); - //More distance let have better performance, less distance let have more sensitive reaction at target move. - float allowed_dist = 0.0f; + float distance = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); + if (owner->IsPet() && (owner->GetCharmerOrOwnerGUID() == GetTarget()->GetGUID())) + distance = 1.f; // pet following owner - if (owner->IsPet() && (owner->GetCharmerOrOwnerGUID() == i_target->GetGUID())) - allowed_dist = 1.0f; // pet following owner - else - allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); - - G3D::Vector3 dest = owner->movespline->FinalDestination(); + G3D::Vector3 destination = owner->movespline->FinalDestination(); if (owner->movespline->onTransport) if (TransportBase* transport = owner->GetDirectTransport()) - transport->CalculatePassengerPosition(dest.x, dest.y, dest.z); + transport->CalculatePassengerPosition(destination.x, destination.y, destination.z); // First check distance if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly()) - targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); + targetMoved = !GetTarget()->IsWithinDist3d(destination.x, destination.y, destination.z, distance); else - targetMoved = !i_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 = !i_target->IsWithinLOSInMap(owner); + targetMoved = !GetTarget()->IsWithinLOSInMap(owner); } - if (i_recalculateTravel || targetMoved) - _setTargetLocation(owner, targetMoved); + if (targetMoved) + SetTargetLocation(owner, targetMoved); - if (owner->movespline->Finalized()) + if (!_targetReached && owner->movespline->Finalized()) { - static_cast(this)->MovementInform(owner); - if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget())) - owner->SetInFront(i_target.getTarget()); + MovementInform(owner); + if (_angle == 0.f && !owner->HasInArc(0.01f, GetTarget())) + owner->SetInFront(GetTarget()); - if (!i_targetReached) + if (!_targetReached) { - i_targetReached = true; - static_cast(this)->_reachTarget(owner); + _targetReached = true; + ReachTarget(owner); } } return true; } -//-----------------------------------------------// -template -void ChaseMovementGenerator::_reachTarget(T* owner) +template +void TargetedMovementGenerator::SetTargetLocation(T* owner, bool updateDestination) { - _clearUnitStateMove(owner); - if (owner->IsWithinMeleeRange(this->i_target.getTarget())) - owner->Attack(this->i_target.getTarget(), true); + if (!IsTargetValid() || !GetTarget()->IsInWorld()) + return; + + if (!owner || !owner->IsAlive()) + return; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner) + || (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true))) + { + _interrupt = true; + owner->StopMoving(); + return; + } + + if (owner->GetTypeId() == TYPEID_UNIT && !GetTarget()->isInAccessiblePlaceFor(owner->ToCreature())) + { + owner->ToCreature()->SetCannotReachTarget(true); + return; + } + + float x, y, z; + if (updateDestination || !_path) + { + if (!_offset) + { + if (GetTarget()->IsWithinDistInMap(owner, CONTACT_DISTANCE)) + return; + + GetTarget()->GetContactPoint(owner, x, y, z); + } + else + { + float distance = _offset + 1.0f; + float size = owner->GetCombatReach(); + + if (owner->IsPet() && GetTarget()->GetTypeId() == TYPEID_PLAYER) + { + distance = 1.0f; + size = 1.0f; + } + + if (GetTarget()->IsWithinDistInMap(owner, distance)) + return; + + GetTarget()->GetClosePoint(x, y, z, size, _offset, _angle); + } + } + else + { + // the destination has not changed, we just need to refresh the path (usually speed change) + G3D::Vector3 end = _path->GetEndPosition(); + x = end.x; + y = end.y; + z = end.z; + } + + if (!_path) + _path = new PathGenerator(owner); + + // allow pets to use shortcut if no path found when following their master + bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)); + + bool result = _path->CalculatePath(x, y, z, forceDest); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) + { + // can't reach target + _recalculateTravel = true; + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetCannotReachTarget(true); + return; + } + + _targetReached = false; + _recalculateTravel = false; + + AddUnitStateMove(owner); + if (owner->GetTypeId() == TYPEID_UNIT) owner->ToCreature()->SetCannotReachTarget(false); + + Movement::MoveSplineInit init(owner); + 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.f) + init.SetFacing(GetTarget()); + + init.Launch(); } +template +bool TargetedMovementGenerator::IsReachable() const +{ + return (_path) ? (_path->GetPathType() & PATHFIND_NORMAL) : true; +} + +//---- ChaseMovementGenerator + +template +void ChaseMovementGenerator::DoInitialize(T*) { } + template<> void ChaseMovementGenerator::DoInitialize(Player* owner) { - owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); - _setTargetLocation(owner, true); + owner->AddUnitState(UNIT_STATE_CHASE); + SetTargetLocation(owner, true); } template<> void ChaseMovementGenerator::DoInitialize(Creature* owner) { owner->SetWalk(false); - owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); - _setTargetLocation(owner, true); + owner->AddUnitState(UNIT_STATE_CHASE); + SetTargetLocation(owner, true); } template @@ -251,41 +233,60 @@ void ChaseMovementGenerator::DoReset(T* owner) } template -void ChaseMovementGenerator::MovementInform(T* /*unit*/) { } +void ChaseMovementGenerator::ClearUnitStateMove(T* owner) +{ + owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); +} + +template +void ChaseMovementGenerator::AddUnitStateMove(T* owner) +{ + owner->AddUnitState(UNIT_STATE_CHASE_MOVE); +} + +template +bool ChaseMovementGenerator::HasLostTarget(T* owner) const +{ + return owner->GetVictim() != TargetedMovementGeneratorBase::GetTarget(); +} + +template +void ChaseMovementGenerator::ReachTarget(T* owner) +{ + ClearUnitStateMove(owner); + + if (owner->IsWithinMeleeRange(TargetedMovementGeneratorBase::GetTarget())) + owner->Attack(TargetedMovementGeneratorBase::GetTarget(), true); + + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetCannotReachTarget(false); +} + +template +void ChaseMovementGenerator::MovementInform(T*) { } template<> -void ChaseMovementGenerator::MovementInform(Creature* unit) +void ChaseMovementGenerator::MovementInform(Creature* owner) { // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (unit->AI()) - unit->AI()->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter()); + if (owner->AI()) + owner->AI()->MovementInform(CHASE_MOTION_TYPE, GetTarget()->GetGUID().GetCounter()); } -//-----------------------------------------------// -template<> -bool FollowMovementGenerator::EnableWalking() const -{ - return i_target.isValid() && i_target->IsWalking(); -} +//---- FollowMovementGenerator + +template +void FollowMovementGenerator::UpdateSpeed(T*) { } template<> -bool FollowMovementGenerator::EnableWalking() const -{ - return false; -} +void FollowMovementGenerator::UpdateSpeed(Player* /*owner*/) { } template<> -void FollowMovementGenerator::_updateSpeed(Player* /*owner*/) +void FollowMovementGenerator::UpdateSpeed(Creature* owner) { - // nothing to do for Player -} - -template<> -void FollowMovementGenerator::_updateSpeed(Creature* owner) -{ - // pet only sync speed with owner - /// Make sure we are not in the process of a map change (IsInWorld) - if (!owner->IsPet() || !owner->IsInWorld() || !i_target.isValid() || i_target->GetGUID() != owner->GetOwnerGUID()) + // Pet only sync speed with owner + // Make sure we are not in the process of a map change (IsInWorld) + if (!owner->IsPet() || !owner->IsInWorld() || !IsTargetValid() || GetTarget()->GetGUID() != owner->GetOwnerGUID()) return; owner->UpdateSpeed(MOVE_RUN); @@ -293,27 +294,19 @@ void FollowMovementGenerator::_updateSpeed(Creature* owner) owner->UpdateSpeed(MOVE_SWIM); } -template<> -void FollowMovementGenerator::DoInitialize(Player* owner) +template +void FollowMovementGenerator::DoInitialize(T* owner) { - owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - _updateSpeed(owner); - _setTargetLocation(owner, true); -} - -template<> -void FollowMovementGenerator::DoInitialize(Creature* owner) -{ - owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - _updateSpeed(owner); - _setTargetLocation(owner, true); + owner->AddUnitState(UNIT_STATE_FOLLOW); + UpdateSpeed(owner); + TargetedMovementGenerator>::SetTargetLocation(owner, true); } template void FollowMovementGenerator::DoFinalize(T* owner) { owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - _updateSpeed(owner); + UpdateSpeed(owner); } template @@ -323,36 +316,85 @@ void FollowMovementGenerator::DoReset(T* owner) } template -void FollowMovementGenerator::MovementInform(T* /*unit*/) { } +void FollowMovementGenerator::ClearUnitStateMove(T* owner) +{ + owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); +} + +template +void FollowMovementGenerator::AddUnitStateMove(T* owner) +{ + owner->AddUnitState(UNIT_STATE_FOLLOW_MOVE); +} + +template +void FollowMovementGenerator::ReachTarget(T* owner) +{ + ClearUnitStateMove(owner); +} + +template<> +bool FollowMovementGenerator::EnableWalking() const +{ + return IsTargetValid() && GetTarget()->IsWalking(); +} + +template<> +bool FollowMovementGenerator::EnableWalking() const +{ + return false; +} + +template +void FollowMovementGenerator::MovementInform(T*) { } template<> void FollowMovementGenerator::MovementInform(Creature* unit) { // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle if (unit->AI()) - unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUID().GetCounter()); + unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, GetTarget()->GetGUID().GetCounter()); } //-----------------------------------------------// -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*, bool); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*, bool); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*, bool); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*, bool); -template bool TargetedMovementGeneratorMedium >::DoUpdate(Player*, uint32); -template bool TargetedMovementGeneratorMedium >::DoUpdate(Player*, uint32); -template bool TargetedMovementGeneratorMedium >::DoUpdate(Creature*, uint32); -template bool TargetedMovementGeneratorMedium >::DoUpdate(Creature*, uint32); -template void ChaseMovementGenerator::_reachTarget(Player*); -template void ChaseMovementGenerator::_reachTarget(Creature*); +template TargetedMovementGenerator >::~TargetedMovementGenerator(); +template TargetedMovementGenerator >::~TargetedMovementGenerator(); +template TargetedMovementGenerator >::~TargetedMovementGenerator(); +template TargetedMovementGenerator >::~TargetedMovementGenerator(); +template bool TargetedMovementGenerator >::DoUpdate(Player*, uint32); +template bool TargetedMovementGenerator >::DoUpdate(Player*, uint32); +template bool TargetedMovementGenerator >::DoUpdate(Creature*, uint32); +template bool TargetedMovementGenerator >::DoUpdate(Creature*, uint32); +template void TargetedMovementGenerator >::SetTargetLocation(Player*, bool); +template void TargetedMovementGenerator >::SetTargetLocation(Player*, bool); +template void TargetedMovementGenerator >::SetTargetLocation(Creature*, bool); +template void TargetedMovementGenerator >::SetTargetLocation(Creature*, bool); + template void ChaseMovementGenerator::DoFinalize(Player*); template void ChaseMovementGenerator::DoFinalize(Creature*); template void ChaseMovementGenerator::DoReset(Player*); template void ChaseMovementGenerator::DoReset(Creature*); +template void ChaseMovementGenerator::ClearUnitStateMove(Player*); +template void ChaseMovementGenerator::ClearUnitStateMove(Creature*); +template void ChaseMovementGenerator::AddUnitStateMove(Player*); +template void ChaseMovementGenerator::AddUnitStateMove(Creature*); +template bool ChaseMovementGenerator::HasLostTarget(Player*) const; +template bool ChaseMovementGenerator::HasLostTarget(Creature*) const; +template void ChaseMovementGenerator::ReachTarget(Player*); +template void ChaseMovementGenerator::ReachTarget(Creature*); template void ChaseMovementGenerator::MovementInform(Player*); +template void FollowMovementGenerator::DoInitialize(Player*); +template void FollowMovementGenerator::DoInitialize(Creature*); template void FollowMovementGenerator::DoFinalize(Player*); template void FollowMovementGenerator::DoFinalize(Creature*); template void FollowMovementGenerator::DoReset(Player*); template void FollowMovementGenerator::DoReset(Creature*); +template void FollowMovementGenerator::ClearUnitStateMove(Player*); +template void FollowMovementGenerator::ClearUnitStateMove(Creature*); +template void FollowMovementGenerator::AddUnitStateMove(Player*); +template void FollowMovementGenerator::AddUnitStateMove(Creature*); +template void FollowMovementGenerator::ReachTarget(Player*); +template void FollowMovementGenerator::ReachTarget(Creature*); template void FollowMovementGenerator::MovementInform(Player*); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 25029dcdfca..6bfb3bbbc28 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -22,95 +22,93 @@ #include "MovementGenerator.h" #include "FollowerReference.h" #include "Timer.h" -#include "Unit.h" -#include "PathGenerator.h" class TargetedMovementGeneratorBase { public: - TargetedMovementGeneratorBase(Unit* target) { i_target.link(target, this); } + TargetedMovementGeneratorBase(Unit* target) + { + _target.link(target, this); + } + + bool IsTargetValid() const { return _target.isValid(); } + Unit* GetTarget() const { return _target.getTarget(); } void stopFollowing() { } - protected: - FollowerReference i_target; + + private: + FollowerReference _target; }; template -class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase +class TargetedMovementGenerator : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase { - protected: - TargetedMovementGeneratorMedium(Unit* target, float offset, float angle) : - TargetedMovementGeneratorBase(target), i_path(NULL), - i_recheckDistance(0), i_offset(offset), i_angle(angle), - i_recalculateTravel(false), i_targetReached(false) - { - } - ~TargetedMovementGeneratorMedium() { delete i_path; } - public: + explicit TargetedMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGeneratorBase(target), _path(nullptr), _timer(0), _offset(offset), _angle(angle), _recalculateTravel(false), _targetReached(false), _interrupt(false) { } + ~TargetedMovementGenerator(); + bool DoUpdate(T*, uint32); - Unit* GetTarget() const { return i_target.getTarget(); } - void unitSpeedChanged() override { i_recalculateTravel = true; } - bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; } - protected: - void _setTargetLocation(T* owner, bool updateDestination); + void UnitSpeedChanged() override { _recalculateTravel = true; } - PathGenerator* i_path; - TimeTrackerSmall i_recheckDistance; - float i_offset; - float i_angle; - bool i_recalculateTravel : 1; - bool i_targetReached : 1; + virtual void ClearUnitStateMove(T*) { } + virtual void AddUnitStateMove(T*) { } + virtual bool HasLostTarget(T*) const { return false; } + virtual void ReachTarget(T*) { } + virtual bool EnableWalking() const { return false; } + virtual void MovementInform(T*) { } + + bool IsReachable() const; + void SetTargetLocation(T* owner, bool updateDestination); + + private: + PathGenerator* _path; + TimeTrackerSmall _timer; + float _offset; + float _angle; + bool _recalculateTravel; + bool _targetReached; + bool _interrupt; }; template -class ChaseMovementGenerator : public TargetedMovementGeneratorMedium > +class ChaseMovementGenerator : public TargetedMovementGenerator > { public: - ChaseMovementGenerator(Unit* target) - : TargetedMovementGeneratorMedium >(target) { } - ChaseMovementGenerator(Unit* target, float offset, float angle) - : TargetedMovementGeneratorMedium >(target, offset, angle) { } - ~ChaseMovementGenerator() { } + explicit ChaseMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGenerator >(target, offset, angle) { } MovementGeneratorType GetMovementGeneratorType() const override { return CHASE_MOTION_TYPE; } void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); - void MovementInform(T*); - static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_CHASE_MOVE); } - static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_CHASE_MOVE); } - bool EnableWalking() const { return false;} - bool _lostTarget(T* u) const { return u->GetVictim() != this->GetTarget(); } - void _reachTarget(T*); + void ClearUnitStateMove(T*) override; + void AddUnitStateMove(T*) override; + bool HasLostTarget(T*) const override; + void ReachTarget(T*) override; + void MovementInform(T*) override; }; template -class FollowMovementGenerator : public TargetedMovementGeneratorMedium > +class FollowMovementGenerator : public TargetedMovementGenerator > { public: - FollowMovementGenerator(Unit* target) - : TargetedMovementGeneratorMedium >(target){ } - FollowMovementGenerator(Unit* target, float offset, float angle) - : TargetedMovementGeneratorMedium >(target, offset, angle) { } - ~FollowMovementGenerator() { } + explicit FollowMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGenerator >(target, offset, angle) { } MovementGeneratorType GetMovementGeneratorType() const override { return FOLLOW_MOTION_TYPE; } void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); - void MovementInform(T*); - static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); } - static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); } - bool EnableWalking() const; - bool _lostTarget(T*) const { return false; } - void _reachTarget(T*) { } + void ClearUnitStateMove(T*) override; + void AddUnitStateMove(T*) override; + bool HasLostTarget(T*) const override { return false; } + void ReachTarget(T*) override; + bool EnableWalking() const override; + void MovementInform(T*) override; private: - void _updateSpeed(T* owner); + void UpdateSpeed(T* owner); }; #endif