diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index c82869fe7..41b2e022b 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -74,17 +74,45 @@ MotionMaster::~MotionMaster() } void -MotionMaster::UpdateMotion(const uint32 &diff) +MotionMaster::UpdateMotion(uint32 diff) { if( i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED) ) return; assert( !empty() ); + m_cleanFlag |= MMCF_UPDATE; if (!top()->Update(*i_owner, diff)) + { + m_cleanFlag &= ~MMCF_UPDATE; MovementExpired(); + } + else + m_cleanFlag &= ~MMCF_UPDATE; + + if (m_expList) + { + for (int i = 0; i < m_expList.size(); ++i) + { + MovementGenerator* mg = m_expList[i]; + if (!isStatic(mg)) + delete mg; + } + + delete m_expList; + m_expList = NULL; + + if (empty()) + Initialize(); + + if (m_cleanFlag & MMCF_RESET) + { + top()->Reset(*i_owner); + m_cleanFlag &= ~MMCF_RESET; + } + } } void -MotionMaster::Clear(bool reset) +MotionMaster::DirectClean(bool reset) { while( !empty() && size() > 1 ) { @@ -103,7 +131,24 @@ MotionMaster::Clear(bool reset) } void -MotionMaster::MovementExpired(bool reset) +MotionMaster::DelayedClean() +{ + if (empty() || size() == 1) + return; + + m_expList = new ExpireList(); + while( !empty() && size() > 1 ) + { + MovementGenerator *curr = top(); + curr->Finalize(*i_owner); + pop(); + if( !isStatic( curr ) ) + m_expList->push_back(curr); + } +} + +void +MotionMaster::DirectExpire(bool reset) { if( empty() || size() == 1 ) return; @@ -129,6 +174,30 @@ MotionMaster::MovementExpired(bool reset) if (reset) top()->Reset(*i_owner); } +void +MotionMaster::DelayedExpire() +{ + if( empty() || size() == 1 ) + return; + + MovementGenerator *curr = top(); + curr->Finalize(*i_owner); + pop(); + + if( !isStatic(curr) ) + m_expList->push_back(curr); + + m_expList = new ExpireList(); + while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE ) + { + // Should check if target is still valid? If not valid it will crash. + curr = top(); + curr->Finalize(*i_owner); + pop(); + m_expList->push_back(curr); + } +} + void MotionMaster::MoveIdle() { if( empty() || !isStatic( top() ) ) diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h index bccc73327..a1a4a55a3 100644 --- a/src/game/MotionMaster.h +++ b/src/game/MotionMaster.h @@ -21,6 +21,7 @@ #include "Common.h" #include +#include class MovementGenerator; class Unit; @@ -45,13 +46,21 @@ enum MovementGeneratorType DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h }; +enum MMCleanFlag +{ + MMCF_NONE = 0, + MMCF_UPDATE = 1, // Clear or Expire called from update + MMCF_RESET = 2 // Flag if need top()->Reset() +}; + class MANGOS_DLL_SPEC MotionMaster : private std::stack { private: typedef std::stack Impl; + typedef std::vector ExpireList; public: - explicit MotionMaster(Unit *unit) : i_owner(unit) {} + explicit MotionMaster(Unit *unit) : i_owner(unit), m_expList(NULL), m_cleanFlag(MMCF_NONE) {} ~MotionMaster(); void Initialize(); @@ -65,9 +74,33 @@ class MANGOS_DLL_SPEC MotionMaster : private std::stack const_iterator begin() const { return Impl::c.begin(); } const_iterator end() const { return Impl::c.end(); } - void UpdateMotion(const uint32 &diff); - void Clear(bool reset = true); - void MovementExpired(bool reset = true); + void UpdateMotion(uint32 diff); + void Clear(bool reset = true) + { + if (m_cleanFlag & MMCF_UPDATE) + { + if(reset) + m_cleanFlag |= MMCF_RESET; + else + m_cleanFlag &= ~MMCF_RESET; + DelayedClean(); + } + else + DirectClean(reset); + } + void MovementExpired(bool reset = true) + { + if (m_cleanFlag & MMCF_UPDATE) + { + if(reset) + m_cleanFlag |= MMCF_RESET; + else + m_cleanFlag &= ~MMCF_RESET; + DelayedExpire(); + } + else + DirectExpire(reset); + } void MoveIdle(); void MoveTargetedHome(); @@ -87,6 +120,14 @@ class MANGOS_DLL_SPEC MotionMaster : private std::stack private: void Mutate(MovementGenerator *m); // use Move* functions instead - Unit *i_owner; + void DirectClean(bool reset); + void DelayedClean(); + + void DirectExpire(bool reset); + void DelayedExpire(); + + Unit *i_owner; + ExpireList *m_expList; + uint8 m_cleanFlag; }; #endif diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0d4ffb5b9..ebbfefe54 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7236" + #define REVISION_NR "7237" #endif // __REVISION_NR_H__