diff options
author | ccrs <ccrs@users.noreply.github.com> | 2017-04-07 21:35:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-07 21:35:23 +0200 |
commit | 21b8c4997a260b5e2dc24ab07df17d3daa6b8b5d (patch) | |
tree | f702e10246c1385acf7928fec24e192778d111f6 /src | |
parent | 5cb1555de6db43db03d6202b7edaa9c6835ecfab (diff) |
[3.3.5] Core/Movement: MotionMaster & MovementGenerators cleaning (#19361)
Diffstat (limited to 'src')
20 files changed, 813 insertions, 736 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<T>(); (static_cast<D*>(this))->DoInitialize(static_cast<T*>(u)); } void Finalize(Unit* u) override { - //u->AssertIsType<T>(); (static_cast<D*>(this))->DoFinalize(static_cast<T*>(u)); } void Reset(Unit* u) override { - //u->AssertIsType<T>(); (static_cast<D*>(this))->DoReset(static_cast<T*>(u)); } bool Update(Unit* u, uint32 time_diff) override { - //u->AssertIsType<T>(); return (static_cast<D*>(this))->DoUpdate(static_cast<T*>(u), time_diff); } }; struct SelectableMovement : public FactoryHolder<MovementGenerator, MovementGeneratorType> { - SelectableMovement(MovementGeneratorType mgt) : FactoryHolder<MovementGenerator, MovementGeneratorType>(mgt) { } + SelectableMovement(MovementGeneratorType movementGeneratorType) : FactoryHolder<MovementGenerator, MovementGeneratorType>(movementGeneratorType) { } }; -template<class REAL_MOVEMENT> +template<class Movement> struct MovementGeneratorFactory : public SelectableMovement { - MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) { } + MovementGeneratorFactory(MovementGeneratorType movementGeneratorType) : SelectableMovement(movementGeneratorType) { } MovementGenerator* Create(void *) const override; }; typedef FactoryHolder<MovementGenerator, MovementGeneratorType> MovementGeneratorCreator; typedef FactoryHolder<MovementGenerator, MovementGeneratorType>::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<class MOVEMENT_GEN> -inline MovementGenerator* -MovementGeneratorFactory<MOVEMENT_GEN>::Create(void * /*data*/) const +template<class Movement> +inline MovementGenerator* MovementGeneratorFactory<Movement>::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<class T> -void ConfusedMovementGenerator<T>::DoInitialize(T* unit) +ConfusedMovementGenerator<T>::~ConfusedMovementGenerator() { - unit->AddUnitState(UNIT_STATE_CONFUSED); - unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit->GetPosition(i_x, i_y, i_z); + delete _path; +} - if (!unit->IsAlive() || unit->IsStopped()) +template<class T> +void ConfusedMovementGenerator<T>::DoInitialize(T* owner) +{ + if (!owner || !owner->IsAlive()) return; - unit->StopMoving(); - unit->AddUnitState(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<class T> -void ConfusedMovementGenerator<T>::DoReset(T* unit) +void ConfusedMovementGenerator<T>::DoReset(T* owner) { - i_nextMoveTime.Reset(0); - - if (!unit->IsAlive() || unit->IsStopped()) - return; - - unit->StopMoving(); - unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + DoInitialize(owner); } template<class T> -bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff) +bool ConfusedMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) { - if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) - return true; + if (!owner || !owner->IsAlive()) + return false; - if (i_nextMoveTime.Passed()) + 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<class T> +void ConfusedMovementGenerator<T>::DoFinalize(T*) { } + template<> void ConfusedMovementGenerator<Player>::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<Creature>::DoFinalize(Creature* unit) unit->SetTarget(unit->EnsureVictim()->GetGUID()); } +template ConfusedMovementGenerator<Player>::~ConfusedMovementGenerator(); +template ConfusedMovementGenerator<Creature>::~ConfusedMovementGenerator(); template void ConfusedMovementGenerator<Player>::DoInitialize(Player*); template void ConfusedMovementGenerator<Creature>::DoInitialize(Creature*); template void ConfusedMovementGenerator<Player>::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 T> class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> > { 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,178 +16,202 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#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<class T> -void FleeingMovementGenerator<T>::_setTargetLocation(T* owner) +FleeingMovementGenerator<T>::~FleeingMovementGenerator() +{ + delete _path; +} + +template<class T> +void FleeingMovementGenerator<T>::DoInitialize(T* owner) { if (!owner) return; - if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->AddUnitState(UNIT_STATE_FLEEING); + SetTargetLocation(owner); +} + +template<class T> +void FleeingMovementGenerator<T>::DoFinalize(T *) +{ +} + +template<> +void FleeingMovementGenerator<Player>::DoFinalize(Player* owner) +{ + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING); + owner->StopMoving(); +} + +template<> +void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner) +{ + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); + if (owner->GetVictim()) + owner->SetTarget(owner->EnsureVictim()->GetGUID()); +} + +template<class T> +void FleeingMovementGenerator<T>::DoReset(T* owner) +{ + DoInitialize(owner); +} + +template<class T> +bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) +{ + if (!owner || !owner->IsAlive()) + return false; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || 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; +} + +template<class T> +void FleeingMovementGenerator<T>::SetTargetLocation(T* owner) +{ + if (!owner) return; - if (owner->IsMovementPreventedByCasting()) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - owner->CastStop(); + _interrupt = true; + owner->StopMoving(); return; } owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); - float x, y, z; - _getPoint(owner, x, y, z); + Position destination = owner->GetPosition(); + GetPoint(owner, destination); // 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) + 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)) { - i_nextCheckTime.Reset(200); + _timer.Reset(200); return; } - PathGenerator path(owner); - path.SetPathLengthLimit(30.0f); - bool result = path.CalculatePath(x, y, z); - if (!result || (path.GetPathType() & PATHFIND_NOPATH)) + 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)) { - i_nextCheckTime.Reset(100); + _timer.Reset(100); return; } Movement::MoveSplineInit init(owner); - init.MovebyPath(path.GetPath()); + init.MovebyPath(_path->GetPath()); init.SetWalk(false); int32 traveltime = init.Launch(); - i_nextCheckTime.Reset(traveltime + urand(800, 1500)); + _timer.Reset(traveltime + urand(800, 1500)); } template<class T> -void FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float &z) +void FleeingMovementGenerator<T>::GetPoint(T* owner, Position &position) { - float dist_from_caster, angle_to_caster; - if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID)) + float casterDistance, casterAngle; + if (Unit* fleeTarget = ObjectAccessor::GetUnit(*owner, _fleeTargetGUID)) { - dist_from_caster = fright->GetDistance(owner); - if (dist_from_caster > 0.2f) - angle_to_caster = fright->GetAngle(owner); + casterDistance = fleeTarget->GetDistance(owner); + if (casterDistance > 0.2f) + casterAngle = fleeTarget->GetAngle(owner); else - angle_to_caster = frand(0, 2 * static_cast<float>(M_PI)); + casterAngle = frand(0.0f, 2.0f * float(M_PI)); } else { - dist_from_caster = 0.0f; - angle_to_caster = frand(0, 2 * static_cast<float>(M_PI)); + casterDistance = 0.0f; + casterAngle = frand(0.0f, 2.0f * float(M_PI)); } - float dist, angle; - if (dist_from_caster < MIN_QUIET_DISTANCE) + float distance, angle; + if (casterDistance < MIN_QUIET_DISTANCE) { - dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster); - angle = angle_to_caster + frand(-static_cast<float>(M_PI)/8, static_cast<float>(M_PI)/8); + 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 (dist_from_caster > MAX_QUIET_DISTANCE) + else if (casterDistance > MAX_QUIET_DISTANCE) { - dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = -angle_to_caster + frand(-static_cast<float>(M_PI)/4, static_cast<float>(M_PI)/4); + 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 { - dist = frand(0.6f, 1.2f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = frand(0, 2*static_cast<float>(M_PI)); + distance = frand(0.6f, 1.2f) * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = frand(0.0f, 2.0f * float(M_PI)); } - Position pos = owner->GetFirstCollisionPosition(dist, angle); - x = pos.m_positionX; - y = pos.m_positionY; - z = pos.m_positionZ; -} - -template<class T> -void FleeingMovementGenerator<T>::DoInitialize(T* owner) -{ - if (!owner) - return; - - owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->AddUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); - _setTargetLocation(owner); + owner->MovePositionToFirstCollision(position, distance, angle); } -template<> -void FleeingMovementGenerator<Player>::DoFinalize(Player* owner) -{ - owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); - owner->StopMoving(); -} - -template<> -void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner) -{ - owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - if (owner->GetVictim()) - owner->SetTarget(owner->EnsureVictim()->GetGUID()); -} +template FleeingMovementGenerator<Player>::~FleeingMovementGenerator(); +template FleeingMovementGenerator<Creature>::~FleeingMovementGenerator(); +template void FleeingMovementGenerator<Player>::DoInitialize(Player*); +template void FleeingMovementGenerator<Creature>::DoInitialize(Creature*); +template void FleeingMovementGenerator<Player>::DoReset(Player*); +template void FleeingMovementGenerator<Creature>::DoReset(Creature*); +template bool FleeingMovementGenerator<Player>::DoUpdate(Player*, uint32); +template bool FleeingMovementGenerator<Creature>::DoUpdate(Creature*, uint32); +template void FleeingMovementGenerator<Player>::SetTargetLocation(Player*); +template void FleeingMovementGenerator<Creature>::SetTargetLocation(Creature*); +template void FleeingMovementGenerator<Player>::GetPoint(Player*, Position &); +template void FleeingMovementGenerator<Creature>::GetPoint(Creature*, Position &); -template<class T> -void FleeingMovementGenerator<T>::DoReset(T* owner) -{ - DoInitialize(owner); -} +//---- TimedFleeingMovementGenerator -template<class T> -bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff) +bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff) { - if (!owner || !owner->IsAlive()) + if (!owner->IsAlive()) return false; - if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) - { - owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); - return true; - } - - i_nextCheckTime.Update(time_diff); - if (i_nextCheckTime.Passed() && owner->movespline->Finalized()) - _setTargetLocation(owner); + _totalFleeTime.Update(time_diff); + if (_totalFleeTime.Passed()) + return false; - return true; + // 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<Creature> >::Update(owner, time_diff); } -template void FleeingMovementGenerator<Player>::DoInitialize(Player*); -template void FleeingMovementGenerator<Creature>::DoInitialize(Creature*); -template void FleeingMovementGenerator<Player>::_getPoint(Player*, float&, float&, float&); -template void FleeingMovementGenerator<Creature>::_getPoint(Creature*, float&, float&, float&); -template void FleeingMovementGenerator<Player>::_setTargetLocation(Player*); -template void FleeingMovementGenerator<Creature>::_setTargetLocation(Creature*); -template void FleeingMovementGenerator<Player>::DoReset(Player*); -template void FleeingMovementGenerator<Creature>::DoReset(Creature*); -template bool FleeingMovementGenerator<Player>::DoUpdate(Player*, uint32); -template bool FleeingMovementGenerator<Creature>::DoUpdate(Creature*, uint32); - 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<Creature> >::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 T> class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> > { 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<Creature> { public: - TimedFleeingMovementGenerator(ObjectGuid fright, uint32 time) : - FleeingMovementGenerator<Creature>(fright), - i_totalFleeTime(time) { } + explicit TimedFleeingMovementGenerator(ObjectGuid fleeTargetGUID, uint32 time) : FleeingMovementGenerator<Creature>(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 <http://www.gnu.org/licenses/>. */ -#include "HomeMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" #include "MoveSplineInit.h" #include "MoveSpline.h" +#include "HomeMovementGenerator.h" -void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner) -{ - _setTargetLocation(owner); -} +template<class T> +HomeMovementGenerator<T>::~HomeMovementGenerator() { } -void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner) +template<> +HomeMovementGenerator<Creature>::~HomeMovementGenerator() { - if (arrived) - { - owner->ClearUnitState(UNIT_STATE_EVADE); - owner->SetWalk(true); - owner->LoadCreaturesAddon(); - owner->AI()->JustReachedHome(); - owner->SetSpawnHealth(); - } + delete _path; } -void HomeMovementGenerator<Creature>::DoReset(Creature*) { } +template<class T> +void HomeMovementGenerator<T>::SetTargetLocation(T*) { } -void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner) +template<> +void HomeMovementGenerator<Creature>::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<Creature>::_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<Creature>::DoUpdate(Creature* owner, const uint32 /*time_diff*/) +template<class T> +void HomeMovementGenerator<T>::DoInitialize(T*) { } + +template<> +void HomeMovementGenerator<Creature>::DoInitialize(Creature* owner) +{ + SetTargetLocation(owner); +} + +template<class T> +void HomeMovementGenerator<T>::DoFinalize(T*) { } + +template<> +void HomeMovementGenerator<Creature>::DoFinalize(Creature* owner) +{ + if (_arrived) + { + owner->ClearUnitState(UNIT_STATE_EVADE); + owner->SetWalk(true); + owner->LoadCreaturesAddon(); + owner->AI()->JustReachedHome(); + owner->SetSpawnHealth(); + } +} + +template<class T> +void HomeMovementGenerator<T>::DoReset(T*) { } + +template<> +void HomeMovementGenerator<Creature>::DoReset(Creature* owner) +{ + DoInitialize(owner); +} + +template<class T> +bool HomeMovementGenerator<T>::DoUpdate(T*, uint32) +{ + return false; +} + +template<> +bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 /*diff*/) { - arrived = skipToHome || owner->movespline->Finalized(); - return !arrived; + _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<Creature> : public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> > +template <class T> +class HomeMovementGenerator : public MovementGeneratorMedium< T, HomeMovementGenerator<T> > { 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<float>(M_PI * 2) / m_maxDuration; - while (angle >= static_cast<float>(M_PI * 2)) angle -= static_cast<float>(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<float>(M_PI * 2) / m_maxDuration; - while (angle < 0) angle += static_cast<float>(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 <http://www.gnu.org/licenses/>. */ -#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<class T> -void PointMovementGenerator<T>::DoInitialize(T* unit) +void PointMovementGenerator<T>::DoInitialize(T* owner) { - if (!unit->IsStopped()) - unit->StopMoving(); + if (_movementId == EVENT_CHARGE_PREPATH) + { + owner->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); + return; + } - unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + owner->AddUnitState(UNIT_STATE_ROAMING); - if (id == EVENT_CHARGE_PREPATH) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) + { + _interrupt = true; + owner->StopMoving(); return; + } + + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - Movement::MoveSplineInit init(unit); - init.MoveTo(i_x, i_y, i_z, m_generatePath); - if (speed > 0.0f) - init.SetVelocity(speed); + 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<class T> -bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/) +bool PointMovementGenerator<T>::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<class T> -void PointMovementGenerator<T>::DoFinalize(T* unit) +void PointMovementGenerator<T>::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<class T> -void PointMovementGenerator<T>::DoReset(T* unit) +void PointMovementGenerator<T>::DoReset(T* owner) { - if (!unit->IsStopped()) - unit->StopMoving(); - - unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + owner->StopMoving(); + DoInitialize(owner); } template<class T> -void PointMovementGenerator<T>::MovementInform(T* /*unit*/) { } +void PointMovementGenerator<T>::MovementInform(T*) { } -template <> void PointMovementGenerator<Creature>::MovementInform(Creature* unit) +template <> +void PointMovementGenerator<Creature>::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<Player>::DoInitialize(Player*); @@ -119,31 +132,33 @@ template void PointMovementGenerator<Creature>::DoReset(Creature*); template bool PointMovementGenerator<Player>::DoUpdate(Player*, uint32); template bool PointMovementGenerator<Creature>::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); - } + MovementInform(owner); +} - if (unit->ToCreature()->AI()) - unit->ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id); +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 T> class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator<T> > { 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 MovementInform(T*); - - void unitSpeedChanged() override { i_recalculateSpeed = true; } - - MovementGeneratorType GetMovementGeneratorType() const override { return POINT_MOTION_TYPE; } + void UnitSpeedChanged() override { _recalculateSpeed = true; } - 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; + void MovementInform(T*); + + uint32 _movementId; + G3D::Vector3 _destination; + float _speed; + bool _generatePath; + bool _recalculateSpeed; + bool _interrupt; }; class AssistanceMovementGenerator : public PointMovementGenerator<Creature> { public: - AssistanceMovementGenerator(float _x, float _y, float _z) : - PointMovementGenerator<Creature>(0, _x, _y, _z, true) { } + explicit AssistanceMovementGenerator(float _x, float _y, float _z) : PointMovementGenerator<Creature>(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<class T> +RandomMovementGenerator<T>::~RandomMovementGenerator() { } template<> -void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature) +RandomMovementGenerator<Creature>::~RandomMovementGenerator() { - if (creature->IsMovementPreventedByCasting()) - { - creature->CastStop(); + delete _path; +} + +template<class T> +void RandomMovementGenerator<T>::DoInitialize(T*) { } + +template<> +void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner) +{ + if (!owner || !owner->IsAlive()) 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); + owner->GetPosition(_reference.x, _reference.y, _reference.z); + owner->StopMoving(); + + if (!_wanderDistance) + _wanderDistance = owner->GetRespawnRadius(); - // 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(); + _timer.Reset(0); +} - const float angle = float(rand_norm()) * static_cast<float>(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); +template<class T> +void RandomMovementGenerator<T>::DoFinalize(T*) { } - destX = respX + distanceX; - destY = respY + distanceY; +template<> +void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner) +{ + owner->ClearUnitState(UNIT_STATE_ROAMING); + owner->StopMoving(); + owner->SetWalk(false); +} - // prevent invalid coordinates generation - Trinity::NormalizeMapCoord(destX); - Trinity::NormalizeMapCoord(destY); +template<class T> +void RandomMovementGenerator<T>::DoReset(T*) { } - travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below +template<> +void RandomMovementGenerator<Creature>::DoReset(Creature* owner) +{ + DoInitialize(owner); +} - if (is_air_ok) // 3D system above ground and above water (flying mode) - { - // 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; - } - } - } +template<class T> +void RandomMovementGenerator<T>::SetRandomLocation(T*) { } - if (is_air_ok) - i_nextMoveTime.Reset(0); - else +template<> +void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) +{ + if (!owner) + return; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - if (roll_chance_i(50)) - i_nextMoveTime.Reset(urand(5000, 10000)); - else - i_nextMoveTime.Reset(urand(50, 400)); + _interrupt = true; + owner->StopMoving(); + return; } - creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - Movement::MoveSplineInit init(creature); - init.MoveTo(destX, destY, destZ); - init.SetWalk(true); - init.Launch(); + 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); - //Call for creature group update - if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(destX, destY, destZ); -} + uint32 resetTimer = roll_chance_i(50) ? urand(5000, 10000) : urand(1000, 2000); -template<> -void RandomMovementGenerator<Creature>::DoInitialize(Creature* creature) -{ - if (!creature->IsAlive()) + if (!_path) + _path = new PathGenerator(owner); + + _path->SetPathLengthLimit(30.0f); + bool result = _path->CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) + { + _timer.Reset(100); return; + } - if (!wander_distance) - wander_distance = creature->GetRespawnRadius(); + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); + init.SetWalk(true); + int32 traveltime = init.Launch(); + _timer.Reset(traveltime + resetTimer); - creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - _setRandomLocation(creature); + // 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<> -void RandomMovementGenerator<Creature>::DoReset(Creature* creature) +template<class T> +bool RandomMovementGenerator<T>::DoUpdate(T*, uint32) { - DoInitialize(creature); + return false; } template<> -void RandomMovementGenerator<Creature>::DoFinalize(Creature* creature) +bool RandomMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff) { - creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - creature->SetWalk(false); -} - -template<> -bool RandomMovementGenerator<Creature>::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<Creature>::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 T> class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator<T> > { 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; } + bool DoUpdate(T*, uint32); + private: - TimeTrackerSmall i_nextMoveTime; + void SetRandomLocation(T*); - float wander_distance; + 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 <http://www.gnu.org/licenses/>. */ -#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<class T, typename D> -void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool updateDestination) +TargetedMovementGenerator<T, D>::~TargetedMovementGenerator() { - if (!i_target.isValid() || !i_target->IsInWorld()) - return; + delete _path; +} + +template<class T, typename D> +bool TargetedMovementGenerator<T, D>::DoUpdate(T* owner, uint32 diff) +{ + if (!IsTargetValid() || !GetTarget()->IsInWorld()) + return false; + + if (!owner || !owner->IsAlive()) + return false; + + 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 true; + } + + if (_interrupt || _recalculateTravel) + { + _interrupt = false; + SetTargetLocation(owner, true); + return true; + } + + bool targetMoved = false; + _timer.Update(diff); + if (!_interrupt && _timer.Passed()) + { + _timer.Reset(100); + + float distance = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); + if (owner->IsPet() && (owner->GetCharmerOrOwnerGUID() == GetTarget()->GetGUID())) + distance = 1.f; // pet following owner + + G3D::Vector3 destination = owner->movespline->FinalDestination(); + if (owner->movespline->onTransport) + if (TransportBase* transport = owner->GetDirectTransport()) + transport->CalculatePassengerPosition(destination.x, destination.y, destination.z); + + // First check distance + if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly()) + targetMoved = !GetTarget()->IsWithinDist3d(destination.x, destination.y, destination.z, distance); + else + targetMoved = !GetTarget()->IsWithinDist2d(destination.x, destination.y, distance); - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) + // then, if the target is in range, check also Line of Sight. + if (!targetMoved) + targetMoved = !GetTarget()->IsWithinLOSInMap(owner); + } + + if (targetMoved) + SetTargetLocation(owner, targetMoved); + + if (!_targetReached && owner->movespline->Finalized()) + { + MovementInform(owner); + if (_angle == 0.f && !owner->HasInArc(0.01f, GetTarget())) + owner->SetInFront(GetTarget()); + + if (!_targetReached) + { + _targetReached = true; + ReachTarget(owner); + } + } + + return true; +} + +template<class T, typename D> +void TargetedMovementGenerator<T, D>::SetTargetLocation(T* owner, bool updateDestination) +{ + if (!IsTargetValid() || !GetTarget()->IsInWorld()) return; - if (owner->IsMovementPreventedByCasting()) + if (!owner || !owner->IsAlive()) return; - if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature())) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting() || HasLostTarget(owner) + || (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true))) { - owner->ToCreature()->SetCannotReachTarget(true); + _interrupt = true; + owner->StopMoving(); return; } - if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true)) + if (owner->GetTypeId() == TYPEID_UNIT && !GetTarget()->isInAccessiblePlaceFor(owner->ToCreature())) + { + owner->ToCreature()->SetCannotReachTarget(true); return; + } float x, y, z; - - if (updateDestination || !i_path) + if (updateDestination || !_path) { - if (!i_offset) + if (!_offset) { - if (i_target->IsWithinDistInMap(owner, CONTACT_DISTANCE)) + if (GetTarget()->IsWithinDistInMap(owner, CONTACT_DISTANCE)) return; - // to nearest contact position - i_target->GetContactPoint(owner, x, y, z); + GetTarget()->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 + float distance = _offset + 1.0f; + float size = owner->GetCombatReach(); + + if (owner->IsPet() && GetTarget()->GetTypeId() == TYPEID_PLAYER) { - dist = i_offset + 1.0f; - size = owner->GetCombatReach(); + distance = 1.0f; + size = 1.0f; } - if (i_target->IsWithinDistInMap(owner, dist)) + if (GetTarget()->IsWithinDistInMap(owner, distance)) 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); + 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 = i_path->GetEndPosition(); + G3D::Vector3 end = _path->GetEndPosition(); x = end.x; y = end.y; z = end.z; } - if (!i_path) - i_path = new PathGenerator(owner); + 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 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)) + bool result = _path->CalculatePath(x, y, z, forceDest); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) { // can't reach target - i_recalculateTravel = true; + _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); + _targetReached = false; + _recalculateTravel = false; + + AddUnitStateMove(owner); + if (owner->GetTypeId() == TYPEID_UNIT) owner->ToCreature()->SetCannotReachTarget(false); Movement::MoveSplineInit init(owner); - init.MovebyPath(i_path->GetPath()); - init.SetWalk(((D*)this)->EnableWalking()); + 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 (i_angle == 0.f) - init.SetFacing(i_target.getTarget()); + if (_angle == 0.f) + init.SetFacing(GetTarget()); init.Launch(); } template<class T, typename D> -bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff) +bool TargetedMovementGenerator<T, D>::IsReachable() const { - if (!i_target.isValid() || !i_target->IsInWorld()) - return false; - - if (!owner || !owner->IsAlive()) - return false; - - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) - { - D::_clearUnitStateMove(owner); - return true; - } - - // prevent movement while casting spells with cast time or channel time - if (owner->IsMovementPreventedByCasting()) - { - if (!owner->IsStopped()) - owner->StopMoving(); - return true; - } - - // prevent crash after creature killed pet - if (static_cast<D*>(this)->_lostTarget(owner)) - { - D::_clearUnitStateMove(owner); - return true; - } - - bool targetMoved = false; - i_recheckDistance.Update(time_diff); - if (i_recheckDistance.Passed()) - { - i_recheckDistance.Reset(100); - - //More distance let have better performance, less distance let have more sensitive reaction at target move. - float allowed_dist = 0.0f; - - 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(); - if (owner->movespline->onTransport) - if (TransportBase* transport = owner->GetDirectTransport()) - transport->CalculatePassengerPosition(dest.x, dest.y, dest.z); - - // First check distance - if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly()) - targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); - else - targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); - - // then, if the target is in range, check also Line of Sight. - if (!targetMoved) - targetMoved = !i_target->IsWithinLOSInMap(owner); - } - - if (i_recalculateTravel || targetMoved) - _setTargetLocation(owner, targetMoved); - - if (owner->movespline->Finalized()) - { - static_cast<D*>(this)->MovementInform(owner); - if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget())) - owner->SetInFront(i_target.getTarget()); - - if (!i_targetReached) - { - i_targetReached = true; - static_cast<D*>(this)->_reachTarget(owner); - } - } - - return true; + return (_path) ? (_path->GetPathType() & PATHFIND_NORMAL) : true; } -//-----------------------------------------------// +//---- ChaseMovementGenerator + template<class T> -void ChaseMovementGenerator<T>::_reachTarget(T* owner) -{ - _clearUnitStateMove(owner); - if (owner->IsWithinMeleeRange(this->i_target.getTarget())) - owner->Attack(this->i_target.getTarget(), true); - if (owner->GetTypeId() == TYPEID_UNIT) - owner->ToCreature()->SetCannotReachTarget(false); -} +void ChaseMovementGenerator<T>::DoInitialize(T*) { } template<> void ChaseMovementGenerator<Player>::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<Creature>::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<class T> @@ -251,41 +233,60 @@ void ChaseMovementGenerator<T>::DoReset(T* owner) } template<class T> -void ChaseMovementGenerator<T>::MovementInform(T* /*unit*/) { } +void ChaseMovementGenerator<T>::ClearUnitStateMove(T* owner) +{ + owner->ClearUnitState(UNIT_STATE_CHASE_MOVE); +} -template<> -void ChaseMovementGenerator<Creature>::MovementInform(Creature* unit) +template<class T> +void ChaseMovementGenerator<T>::AddUnitStateMove(T* 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()); + owner->AddUnitState(UNIT_STATE_CHASE_MOVE); } -//-----------------------------------------------// -template<> -bool FollowMovementGenerator<Creature>::EnableWalking() const +template<class T> +bool ChaseMovementGenerator<T>::HasLostTarget(T* owner) const { - return i_target.isValid() && i_target->IsWalking(); + return owner->GetVictim() != TargetedMovementGeneratorBase::GetTarget(); } -template<> -bool FollowMovementGenerator<Player>::EnableWalking() const +template<class T> +void ChaseMovementGenerator<T>::ReachTarget(T* owner) { - return false; + ClearUnitStateMove(owner); + + if (owner->IsWithinMeleeRange(TargetedMovementGeneratorBase::GetTarget())) + owner->Attack(TargetedMovementGeneratorBase::GetTarget(), true); + + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetCannotReachTarget(false); } +template<class T> +void ChaseMovementGenerator<T>::MovementInform(T*) { } + template<> -void FollowMovementGenerator<Player>::_updateSpeed(Player* /*owner*/) +void ChaseMovementGenerator<Creature>::MovementInform(Creature* owner) { - // nothing to do for Player + // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle + if (owner->AI()) + owner->AI()->MovementInform(CHASE_MOTION_TYPE, GetTarget()->GetGUID().GetCounter()); } +//---- FollowMovementGenerator + +template<class T> +void FollowMovementGenerator<T>::UpdateSpeed(T*) { } + +template<> +void FollowMovementGenerator<Player>::UpdateSpeed(Player* /*owner*/) { } + template<> -void FollowMovementGenerator<Creature>::_updateSpeed(Creature* owner) +void FollowMovementGenerator<Creature>::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<Creature>::_updateSpeed(Creature* owner) owner->UpdateSpeed(MOVE_SWIM); } -template<> -void FollowMovementGenerator<Player>::DoInitialize(Player* owner) -{ - owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - _updateSpeed(owner); - _setTargetLocation(owner, true); -} - -template<> -void FollowMovementGenerator<Creature>::DoInitialize(Creature* owner) +template<class T> +void FollowMovementGenerator<T>::DoInitialize(T* owner) { - owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - _updateSpeed(owner); - _setTargetLocation(owner, true); + owner->AddUnitState(UNIT_STATE_FOLLOW); + UpdateSpeed(owner); + TargetedMovementGenerator<T, FollowMovementGenerator<T>>::SetTargetLocation(owner, true); } template<class T> void FollowMovementGenerator<T>::DoFinalize(T* owner) { owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); - _updateSpeed(owner); + UpdateSpeed(owner); } template<class T> @@ -323,36 +316,85 @@ void FollowMovementGenerator<T>::DoReset(T* owner) } template<class T> -void FollowMovementGenerator<T>::MovementInform(T* /*unit*/) { } +void FollowMovementGenerator<T>::ClearUnitStateMove(T* owner) +{ + owner->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); +} + +template<class T> +void FollowMovementGenerator<T>::AddUnitStateMove(T* owner) +{ + owner->AddUnitState(UNIT_STATE_FOLLOW_MOVE); +} + +template<class T> +void FollowMovementGenerator<T>::ReachTarget(T* owner) +{ + ClearUnitStateMove(owner); +} + +template<> +bool FollowMovementGenerator<Creature>::EnableWalking() const +{ + return IsTargetValid() && GetTarget()->IsWalking(); +} + +template<> +bool FollowMovementGenerator<Player>::EnableWalking() const +{ + return false; +} + +template<class T> +void FollowMovementGenerator<T>::MovementInform(T*) { } template<> void FollowMovementGenerator<Creature>::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<Player, ChaseMovementGenerator<Player> >::_setTargetLocation(Player*, bool); -template void TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::_setTargetLocation(Player*, bool); -template void TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool); -template void TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool); -template bool TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::DoUpdate(Player*, uint32); -template bool TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::DoUpdate(Player*, uint32); -template bool TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::DoUpdate(Creature*, uint32); -template bool TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::DoUpdate(Creature*, uint32); - -template void ChaseMovementGenerator<Player>::_reachTarget(Player*); -template void ChaseMovementGenerator<Creature>::_reachTarget(Creature*); + +template TargetedMovementGenerator<Player, ChaseMovementGenerator<Player> >::~TargetedMovementGenerator(); +template TargetedMovementGenerator<Player, FollowMovementGenerator<Player> >::~TargetedMovementGenerator(); +template TargetedMovementGenerator<Creature, ChaseMovementGenerator<Creature> >::~TargetedMovementGenerator(); +template TargetedMovementGenerator<Creature, FollowMovementGenerator<Creature> >::~TargetedMovementGenerator(); +template bool TargetedMovementGenerator<Player, ChaseMovementGenerator<Player> >::DoUpdate(Player*, uint32); +template bool TargetedMovementGenerator<Player, FollowMovementGenerator<Player> >::DoUpdate(Player*, uint32); +template bool TargetedMovementGenerator<Creature, ChaseMovementGenerator<Creature> >::DoUpdate(Creature*, uint32); +template bool TargetedMovementGenerator<Creature, FollowMovementGenerator<Creature> >::DoUpdate(Creature*, uint32); +template void TargetedMovementGenerator<Player, ChaseMovementGenerator<Player> >::SetTargetLocation(Player*, bool); +template void TargetedMovementGenerator<Player, FollowMovementGenerator<Player> >::SetTargetLocation(Player*, bool); +template void TargetedMovementGenerator<Creature, ChaseMovementGenerator<Creature> >::SetTargetLocation(Creature*, bool); +template void TargetedMovementGenerator<Creature, FollowMovementGenerator<Creature> >::SetTargetLocation(Creature*, bool); + template void ChaseMovementGenerator<Player>::DoFinalize(Player*); template void ChaseMovementGenerator<Creature>::DoFinalize(Creature*); template void ChaseMovementGenerator<Player>::DoReset(Player*); template void ChaseMovementGenerator<Creature>::DoReset(Creature*); +template void ChaseMovementGenerator<Player>::ClearUnitStateMove(Player*); +template void ChaseMovementGenerator<Creature>::ClearUnitStateMove(Creature*); +template void ChaseMovementGenerator<Player>::AddUnitStateMove(Player*); +template void ChaseMovementGenerator<Creature>::AddUnitStateMove(Creature*); +template bool ChaseMovementGenerator<Player>::HasLostTarget(Player*) const; +template bool ChaseMovementGenerator<Creature>::HasLostTarget(Creature*) const; +template void ChaseMovementGenerator<Player>::ReachTarget(Player*); +template void ChaseMovementGenerator<Creature>::ReachTarget(Creature*); template void ChaseMovementGenerator<Player>::MovementInform(Player*); +template void FollowMovementGenerator<Player>::DoInitialize(Player*); +template void FollowMovementGenerator<Creature>::DoInitialize(Creature*); template void FollowMovementGenerator<Player>::DoFinalize(Player*); template void FollowMovementGenerator<Creature>::DoFinalize(Creature*); template void FollowMovementGenerator<Player>::DoReset(Player*); template void FollowMovementGenerator<Creature>::DoReset(Creature*); +template void FollowMovementGenerator<Player>::ClearUnitStateMove(Player*); +template void FollowMovementGenerator<Creature>::ClearUnitStateMove(Creature*); +template void FollowMovementGenerator<Player>::AddUnitStateMove(Player*); +template void FollowMovementGenerator<Creature>::AddUnitStateMove(Creature*); +template void FollowMovementGenerator<Player>::ReachTarget(Player*); +template void FollowMovementGenerator<Creature>::ReachTarget(Creature*); template void FollowMovementGenerator<Player>::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 T, typename D> -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); - - PathGenerator* i_path; - TimeTrackerSmall i_recheckDistance; - float i_offset; - float i_angle; - bool i_recalculateTravel : 1; - bool i_targetReached : 1; + + void UnitSpeedChanged() override { _recalculateTravel = true; } + + 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 T> -class ChaseMovementGenerator : public TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> > +class ChaseMovementGenerator : public TargetedMovementGenerator<T, ChaseMovementGenerator<T> > { public: - ChaseMovementGenerator(Unit* target) - : TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target) { } - ChaseMovementGenerator(Unit* target, float offset, float angle) - : TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target, offset, angle) { } - ~ChaseMovementGenerator() { } + explicit ChaseMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGenerator<T, ChaseMovementGenerator<T> >(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 T> -class FollowMovementGenerator : public TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> > +class FollowMovementGenerator : public TargetedMovementGenerator<T, FollowMovementGenerator<T> > { public: - FollowMovementGenerator(Unit* target) - : TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target){ } - FollowMovementGenerator(Unit* target, float offset, float angle) - : TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target, offset, angle) { } - ~FollowMovementGenerator() { } + explicit FollowMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGenerator<T, FollowMovementGenerator<T> >(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 |