diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 4ad2a314111..105b4245ff3 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -20,7 +20,6 @@ #include "CreatureAISelector.h" #include "Creature.h" #include "ScriptSystem.h" - #include "ConfusedMovementGenerator.h" #include "FleeingMovementGenerator.h" #include "HomeMovementGenerator.h" @@ -33,9 +32,21 @@ #include "MoveSpline.h" #include "MoveSplineInit.h" -inline bool isStatic(MovementGenerator *mv) +inline bool IsStatic(MovementGenerator* movement) { - return (mv == &si_idleMovement); + return (movement == &si_idleMovement); +} + +MotionMaster::~MotionMaster() +{ + // clear ALL movement generators (including default) + while (!empty()) + { + MovementGenerator *curr = top(); + pop(); + if (curr && !IsStatic(curr)) + delete curr; // Skip finalizing on delete, it might launch new movement + } } void MotionMaster::Initialize() @@ -66,18 +77,6 @@ void MotionMaster::InitDefault() } } -MotionMaster::~MotionMaster() -{ - // clear ALL movement generators (including default) - while (!empty()) - { - MovementGenerator *curr = top(); - pop(); - if (curr && !isStatic(curr)) - delete curr; // Skip finalizing on delete, it might launch new movement - } -} - void MotionMaster::UpdateMotion(uint32 diff) { if (!_owner) @@ -97,20 +96,20 @@ void MotionMaster::UpdateMotion(uint32 diff) else _cleanFlag &= ~MMCF_UPDATE; - if (_expList) + if (_expireList) { - for (size_t i = 0; i < _expList->size(); ++i) + for (size_t i = 0; i < _expireList->size(); ++i) { - MovementGenerator* mg = (*_expList)[i]; + MovementGenerator* mg = (*_expireList)[i]; DirectDelete(mg); } - delete _expList; - _expList = NULL; + delete _expireList; + _expireList = nullptr; if (empty()) Initialize(); - else if (needInitTop()) + else if (NeedInitTop()) InitTop(); else if (_cleanFlag & MMCF_RESET) top()->Reset(_owner); @@ -122,84 +121,84 @@ void MotionMaster::UpdateMotion(uint32 diff) _owner->UpdateUnderwaterState(_owner->GetMap(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); } -void MotionMaster::DirectClean(bool reset) +void MotionMaster::Clear(bool reset /*= true*/) { - while (size() > 1) + if (_cleanFlag & MMCF_UPDATE) { - MovementGenerator *curr = top(); - pop(); - if (curr) DirectDelete(curr); + if (reset) + _cleanFlag |= MMCF_RESET; + else + _cleanFlag &= ~MMCF_RESET; + DelayedClean(); } + else + DirectClean(reset); +} +void MotionMaster::MovementExpired(bool reset /*= true*/) +{ + if (_cleanFlag & MMCF_UPDATE) + { + if (reset) + _cleanFlag |= MMCF_RESET; + else + _cleanFlag &= ~MMCF_RESET; + DelayedExpire(); + } + else + DirectExpire(reset); +} + +MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const +{ if (empty()) - return; + return IDLE_MOTION_TYPE; - if (needInitTop()) - InitTop(); - else if (reset) - top()->Reset(_owner); + return top()->GetMovementGeneratorType(); } -void MotionMaster::DelayedClean() +MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const { - while (size() > 1) + if (!_slot[slot]) + return NULL_MOTION_TYPE; + else + return _slot[slot]->GetMovementGeneratorType(); +} + +MovementGenerator* MotionMaster::GetMotionSlot(int slot) const +{ + ASSERT(slot >= 0); + return _slot[slot]; +} + +void MotionMaster::propagateSpeedChange() +{ + for (int i = 0; i <= _top; ++i) { - MovementGenerator *curr = top(); - pop(); - if (curr) - DelayedDelete(curr); + if (_slot[i]) + _slot[i]->unitSpeedChanged(); } } -void MotionMaster::DirectExpire(bool reset) +bool MotionMaster::GetDestination(float &x, float &y, float &z) { - if (size() > 1) - { - MovementGenerator *curr = top(); - pop(); - DirectDelete(curr); - } + if (_owner->movespline->Finalized()) + return false; - while (!empty() && !top()) - --_top; - - if (empty()) - Initialize(); - else if (needInitTop()) - InitTop(); - else if (reset) - top()->Reset(_owner); -} - -void MotionMaster::DelayedExpire() -{ - if (size() > 1) - { - MovementGenerator *curr = top(); - pop(); - DelayedDelete(curr); - } - - while (!empty() && !top()) - --_top; + G3D::Vector3 const& dest = _owner->movespline->FinalDestination(); + x = dest.x; + y = dest.y; + z = dest.z; + return true; } void MotionMaster::MoveIdle() { //! Should be preceded by MovementExpired or Clear if there's an overlying movementgenerator active - if (empty() || !isStatic(top())) + if (empty() || !IsStatic(top())) Mutate(&si_idleMovement, MOTION_SLOT_IDLE); } -void MotionMaster::MoveRandom(float spawndist) -{ - if (_owner->GetTypeId() == TYPEID_UNIT) - { - TC_LOG_DEBUG("misc", "Creature (GUID: %u) started random movement.", _owner->GetGUID().GetCounter()); - Mutate(new RandomMovementGenerator(spawndist), MOTION_SLOT_IDLE); - } -} - void MotionMaster::MoveTargetedHome() { Clear(false); @@ -225,18 +224,36 @@ void MotionMaster::MoveTargetedHome() } } -void MotionMaster::MoveConfused() +void MotionMaster::MoveRandom(float spawndist) { + if (_owner->GetTypeId() == TYPEID_UNIT) + { + TC_LOG_DEBUG("misc", "Creature (GUID: %u) started random movement.", _owner->GetGUID().GetCounter()); + Mutate(new RandomMovementGenerator(spawndist), MOTION_SLOT_IDLE); + } +} + +void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) +{ + // ignore movement request if target not exist + if (!target || target == _owner) + return; + + //_owner->AddUnitState(UNIT_STATE_FOLLOW); if (_owner->GetTypeId() == TYPEID_PLAYER) { - TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUID().GetCounter()); - Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); + TC_LOG_DEBUG("misc", "Player (GUID: %u) follows %s (GUID: %u).", _owner->GetGUID().GetCounter(), + target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); + Mutate(new FollowMovementGenerator(target, dist, angle), slot); } else { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) move confused", - _owner->GetEntry(), _owner->GetGUID().GetCounter()); - Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); + TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) follows %s (GUID: %u).", + _owner->GetEntry(), _owner->GetGUID().GetCounter(), + target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); + Mutate(new FollowMovementGenerator(target, dist, angle), slot); } } @@ -265,27 +282,44 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) } } -void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) +void MotionMaster::MoveConfused() { - // ignore movement request if target not exist - if (!target || target == _owner) - return; - - //_owner->AddUnitState(UNIT_STATE_FOLLOW); if (_owner->GetTypeId() == TYPEID_PLAYER) { - TC_LOG_DEBUG("misc", "Player (GUID: %u) follows %s (GUID: %u).", _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); - Mutate(new FollowMovementGenerator(target, dist, angle), slot); + TC_LOG_DEBUG("misc", "Player (GUID: %u) move confused", _owner->GetGUID().GetCounter()); + Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); } else { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) follows %s (GUID: %u).", + TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) move confused", + _owner->GetEntry(), _owner->GetGUID().GetCounter()); + Mutate(new ConfusedMovementGenerator(), MOTION_SLOT_CONTROLLED); + } +} + +void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) +{ + if (!enemy) + return; + + if (_owner->GetTypeId() == TYPEID_PLAYER) + { + TC_LOG_DEBUG("misc", "Player (GUID: %u) flees from %s (GUID: %u).", _owner->GetGUID().GetCounter(), + enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", + enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId()); + Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); + } + else + { + TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) flees from %s (GUID: %u)%s.", _owner->GetEntry(), _owner->GetGUID().GetCounter(), - target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - target->GetTypeId() == TYPEID_PLAYER ? target->GetGUID().GetCounter() : target->ToCreature()->GetSpawnId()); - Mutate(new FollowMovementGenerator(target, dist, angle), slot); + enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", + enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId(), + time ? " for a limited time" : ""); + if (time) + Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED); + else + Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); } } @@ -353,6 +387,37 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); } +void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/) +{ + if (_slot[MOTION_SLOT_CONTROLLED] && _slot[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) + return; + + if (_owner->GetTypeId() == TYPEID_PLAYER) + { + TC_LOG_DEBUG("misc", "Player (GUID: %u) charged point (X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), x, y, z); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); + } + else + { + TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) charged point (X: %f Y: %f Z: %f).", + _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); + } +} + +void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/) +{ + G3D::Vector3 dest = path.GetActualEndPosition(); + + MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH); + + // Charge movement is not started when using EVENT_CHARGE_PREPATH + Movement::MoveSplineInit init(_owner); + init.MovebyPath(path.GetPath()); + init.SetVelocity(speed); + init.Launch(); +} + void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ) { //this function may make players fall below map @@ -531,37 +596,6 @@ void MotionMaster::MoveFall(uint32 id /*=0*/) Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); } -void MotionMaster::MoveCharge(float x, float y, float z, float speed /*= SPEED_CHARGE*/, uint32 id /*= EVENT_CHARGE*/, bool generatePath /*= false*/) -{ - if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) - return; - - if (_owner->GetTypeId() == TYPEID_PLAYER) - { - TC_LOG_DEBUG("misc", "Player (GUID: %u) charged point (X: %f Y: %f Z: %f).", _owner->GetGUID().GetCounter(), x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) charged point (X: %f Y: %f Z: %f).", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); - } -} - -void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/) -{ - G3D::Vector3 dest = path.GetActualEndPosition(); - - MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH); - - // Charge movement is not started when using EVENT_CHARGE_PREPATH - Movement::MoveSplineInit init(_owner); - init.MovebyPath(path.GetPath()); - init.SetVelocity(speed); - init.Launch(); -} - void MotionMaster::MoveSeekAssistance(float x, float y, float z) { if (_owner->GetTypeId() == TYPEID_PLAYER) @@ -593,32 +627,6 @@ void MotionMaster::MoveSeekAssistanceDistract(uint32 time) } } -void MotionMaster::MoveFleeing(Unit* enemy, uint32 time) -{ - if (!enemy) - return; - - if (_owner->GetTypeId() == TYPEID_PLAYER) - { - TC_LOG_DEBUG("misc", "Player (GUID: %u) flees from %s (GUID: %u).", _owner->GetGUID().GetCounter(), - enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId()); - Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); - } - else - { - TC_LOG_DEBUG("misc", "Creature (Entry: %u GUID: %u) flees from %s (GUID: %u)%s.", - _owner->GetEntry(), _owner->GetGUID().GetCounter(), - enemy->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", - enemy->GetTypeId() == TYPEID_PLAYER ? enemy->GetGUID().GetCounter() : enemy->ToCreature()->GetSpawnId(), - time ? " for a limited time" : ""); - if (time) - Mutate(new TimedFleeingMovementGenerator(enemy->GetGUID(), time), MOTION_SLOT_CONTROLLED); - else - Mutate(new FleeingMovementGenerator(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); - } -} - void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) { if (_owner->GetTypeId() == TYPEID_PLAYER) @@ -645,7 +653,7 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) void MotionMaster::MoveDistract(uint32 timer) { - if (Impl[MOTION_SLOT_CONTROLLED]) + if (_slot[MOTION_SLOT_CONTROLLED]) return; if (_owner->GetTypeId() == TYPEID_PLAYER) @@ -662,48 +670,11 @@ void MotionMaster::MoveDistract(uint32 timer) Mutate(mgen, MOTION_SLOT_CONTROLLED); } -void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) -{ - if (MovementGenerator *curr = Impl[slot]) - { - Impl[slot] = NULL; // in case a new one is generated in this slot during directdelete - if (_top == slot && (_cleanFlag & MMCF_UPDATE)) - DelayedDelete(curr); - else - DirectDelete(curr); - } - else if (_top < slot) - { - _top = slot; - } - - Impl[slot] = m; - if (_top > slot) - _needInit[slot] = true; - else - { - _needInit[slot] = false; - m->Initialize(_owner); - } -} - void MotionMaster::MovePath(uint32 path_id, bool repeatable) { if (!path_id) return; - //We set waypoint movement as new default movement generator - // clear ALL movement generators (including default) - /*while (!empty()) - { - MovementGenerator *curr = top(); - curr->Finalize(*_owner); - pop(); - if (!isStatic(curr)) - delete curr; - }*/ - //_owner->GetTypeId() == TYPEID_PLAYER ? - //Mutate(new WaypointMovementGenerator(path_id, repeatable)): Mutate(new WaypointMovementGenerator(path_id, repeatable), MOTION_SLOT_IDLE); TC_LOG_DEBUG("misc", "%s (GUID: %u) starts moving over path(Id:%u, repeatable: %s).", @@ -719,68 +690,132 @@ void MotionMaster::MoveRotate(uint32 time, RotateDirection direction) Mutate(new RotateMovementGenerator(time, direction), MOTION_SLOT_ACTIVE); } -void MotionMaster::propagateSpeedChange() +/******************** Private methods ********************/ + +void MotionMaster::pop() { - /*Impl::container_type::iterator it = Impl::c.begin(); - for (; it != end(); ++it) - { - (*it)->unitSpeedChanged(); - }*/ - for (int i = 0; i <= _top; ++i) - { - if (Impl[i]) - Impl[i]->unitSpeedChanged(); - } + if (empty()) + return; + + _slot[_top] = nullptr; + while (!empty() && !top()) + --_top; } -MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const +bool MotionMaster::NeedInitTop() const { - if (empty()) - return IDLE_MOTION_TYPE; - - return top()->GetMovementGeneratorType(); -} - -MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const -{ - if (!Impl[slot]) - return NULL_MOTION_TYPE; - else - return Impl[slot]->GetMovementGeneratorType(); + if (empty()) + return false; + return _initialize[_top]; } void MotionMaster::InitTop() { top()->Initialize(_owner); - _needInit[_top] = false; + _initialize[_top] = false; } -void MotionMaster::DirectDelete(_Ty curr) +void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) { - if (isStatic(curr)) + if (MovementGenerator *curr = _slot[slot]) + { + _slot[slot] = nullptr; // in case a new one is generated in this slot during directdelete + if (_top == slot && (_cleanFlag & MMCF_UPDATE)) + DelayedDelete(curr); + else + DirectDelete(curr); + } + else if (_top < slot) + { + _top = slot; + } + + _slot[slot] = m; + if (_top > slot) + _initialize[slot] = true; + else + { + _initialize[slot] = false; + m->Initialize(_owner); + } +} + +void MotionMaster::DirectClean(bool reset) +{ + while (size() > 1) + { + MovementGenerator *curr = top(); + pop(); + if (curr) DirectDelete(curr); + } + + if (empty()) + return; + + if (NeedInitTop()) + InitTop(); + else if (reset) + top()->Reset(_owner); +} + +void MotionMaster::DelayedClean() +{ + while (size() > 1) + { + MovementGenerator *curr = top(); + pop(); + if (curr) + DelayedDelete(curr); + } +} + +void MotionMaster::DirectExpire(bool reset) +{ + if (size() > 1) + { + MovementGenerator *curr = top(); + pop(); + DirectDelete(curr); + } + + while (!empty() && !top()) + --_top; + + if (empty()) + Initialize(); + else if (NeedInitTop()) + InitTop(); + else if (reset) + top()->Reset(_owner); +} + +void MotionMaster::DelayedExpire() +{ + if (size() > 1) + { + MovementGenerator *curr = top(); + pop(); + DelayedDelete(curr); + } + + while (!empty() && !top()) + --_top; +} + +void MotionMaster::DirectDelete(MovementGenerator* curr) +{ + if (IsStatic(curr)) return; curr->Finalize(_owner); delete curr; } -void MotionMaster::DelayedDelete(_Ty curr) +void MotionMaster::DelayedDelete(MovementGenerator* curr) { TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating Movement Generator (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType()); - if (isStatic(curr)) + if (IsStatic(curr)) return; - if (!_expList) - _expList = new ExpireList(); - _expList->push_back(curr); -} - -bool MotionMaster::GetDestination(float &x, float &y, float &z) -{ - if (_owner->movespline->Finalized()) - return false; - - G3D::Vector3 const& dest = _owner->movespline->FinalDestination(); - x = dest.x; - y = dest.y; - z = dest.z; - return true; + if (!_expireList) + _expireList = new ExpireList(); + _expireList->push_back(curr); } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d376f6aa58f..0f46f42e08e 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -16,8 +16,8 @@ * with this program. If not, see . */ -#ifndef TRINITY_MOTIONMASTER_H -#define TRINITY_MOTIONMASTER_H +#ifndef MOTIONMASTER_H +#define MOTIONMASTER_H #include "Common.h" #include @@ -32,31 +32,32 @@ class PathGenerator; // Creature Entry ID used for waypoints show, visible only for GMs #define VISUAL_WAYPOINT 1 +// assume it is 25 yard per 0.6 second +#define SPEED_CHARGE 42.0f -// values 0 ... MAX_DB_MOTION_TYPE-1 used in DB enum MovementGeneratorType { - IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h - RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h - WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h - MAX_DB_MOTION_TYPE = 3, // *** this and below motion types can't be set in DB. - ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h - CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h - CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h - HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h - FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h - POINT_MOTION_TYPE = 8, // PointMovementGenerator.h - FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h - DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h - ASSISTANCE_MOTION_TYPE= 11, // PointMovementGenerator.h (first part of flee for assistance) - ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance) - TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance) - FOLLOW_MOTION_TYPE = 14, - ROTATE_MOTION_TYPE = 15, - EFFECT_MOTION_TYPE = 16, - NULL_MOTION_TYPE = 17, - SPLINE_CHAIN_MOTION_TYPE = 18, // SplineChainMovementGenerator.h - MAX_MOTION_TYPE // limit + IDLE_MOTION_TYPE = 0, // IdleMovementGenerator.h + RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h + WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h + MAX_DB_MOTION_TYPE = 3, // Below motion types can't be set in DB. + ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h + CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h + CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h + HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h + FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h + POINT_MOTION_TYPE = 8, // PointMovementGenerator.h + FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h + DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h + ASSISTANCE_MOTION_TYPE = 11, // PointMovementGenerator.h (first part of flee for assistance) + ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance) + TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance) + FOLLOW_MOTION_TYPE = 14, + ROTATE_MOTION_TYPE = 15, + EFFECT_MOTION_TYPE = 16, + NULL_MOTION_TYPE = 17, + SPLINE_CHAIN_MOTION_TYPE = 18, // SplineChainMovementGenerator.h + MAX_MOTION_TYPE // limit }; enum MovementSlot @@ -80,91 +81,41 @@ enum RotateDirection ROTATE_DIRECTION_RIGHT }; -// assume it is 25 yard per 0.6 second -#define SPEED_CHARGE 42.0f - -class TC_GAME_API MotionMaster //: private std::stack +class TC_GAME_API MotionMaster { private: - //typedef std::stack Impl; - typedef MovementGenerator* _Ty; + typedef std::vector ExpireList; - void pop() - { - if (empty()) - return; - - Impl[_top] = NULL; - while (!empty() && !top()) - --_top; - } - void push(_Ty _Val) { ++_top; Impl[_top] = _Val; } - - bool needInitTop() const - { - if (empty()) - return false; - return _needInit[_top]; - } - void InitTop(); public: - - explicit MotionMaster(Unit* unit) : _expList(NULL), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE) + explicit MotionMaster(Unit* unit) : _expireList(nullptr), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE) { for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) { - Impl[i] = NULL; - _needInit[i] = true; + _slot[i] = nullptr; + _initialize[i] = true; } } ~MotionMaster(); + bool empty() const { return (_top < 0); } + int size() const { return _top + 1; } + MovementGenerator* top() const { ASSERT(!empty()); return _slot[_top]; } + void Initialize(); void InitDefault(); - bool empty() const { return (_top < 0); } - int size() const { return _top + 1; } - _Ty top() const - { - ASSERT(!empty()); - return Impl[_top]; - } - _Ty GetMotionSlot(int slot) const - { - ASSERT(slot >= 0); - return Impl[slot]; - } - - void DirectDelete(_Ty curr); - void DelayedDelete(_Ty curr); - void UpdateMotion(uint32 diff); - void Clear(bool reset = true) - { - if (_cleanFlag & MMCF_UPDATE) - { - if (reset) - _cleanFlag |= MMCF_RESET; - else - _cleanFlag &= ~MMCF_RESET; - DelayedClean(); - } - else - DirectClean(reset); - } - void MovementExpired(bool reset = true) - { - if (_cleanFlag & MMCF_UPDATE) - { - if (reset) - _cleanFlag |= MMCF_RESET; - else - _cleanFlag &= ~MMCF_RESET; - DelayedExpire(); - } - else - DirectExpire(reset); - } + + void Clear(bool reset = true); + void MovementExpired(bool reset = true); + + MovementGeneratorType GetCurrentMovementGeneratorType() const; + MovementGeneratorType GetMotionSlotType(int slot) const; + MovementGenerator* GetMotionSlot(int slot) const; + + void propagateSpeedChange(); + + bool GetDestination(float &x, float &y, float &z); void MoveIdle(); void MoveTargetedHome(); @@ -174,7 +125,9 @@ class TC_GAME_API MotionMaster //: private std::stack void MoveConfused(); void MoveFleeing(Unit* enemy, uint32 time = 0); void MovePoint(uint32 id, Position const& pos, bool generatePath = true) - { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); } + { + MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); + } void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true); /* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. @@ -212,27 +165,27 @@ class TC_GAME_API MotionMaster //: private std::stack void MovePath(uint32 path_id, bool repeatable); void MoveRotate(uint32 time, RotateDirection direction); - MovementGeneratorType GetCurrentMovementGeneratorType() const; - MovementGeneratorType GetMotionSlotType(int slot) const; - - void propagateSpeedChange(); - - bool GetDestination(float &x, float &y, float &z); private: - void Mutate(MovementGenerator *m, MovementSlot slot); // use Move* functions instead + void pop(); + + bool NeedInitTop() const; + void InitTop(); + + void Mutate(MovementGenerator *m, MovementSlot slot); void DirectClean(bool reset); void DelayedClean(); - void DirectExpire(bool reset); void DelayedExpire(); + void DirectDelete(MovementGenerator* curr); + void DelayedDelete(MovementGenerator* curr); - typedef std::vector<_Ty> ExpireList; - ExpireList* _expList; - _Ty Impl[MAX_MOTION_SLOT]; + ExpireList* _expireList; + MovementGenerator* _slot[MAX_MOTION_SLOT]; int _top; Unit* _owner; - bool _needInit[MAX_MOTION_SLOT]; + bool _initialize[MAX_MOTION_SLOT]; uint8 _cleanFlag; }; -#endif + +#endif // MOTIONMASTER_H