diff options
author | megamage <none@none> | 2009-02-08 21:43:46 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-02-08 21:43:46 -0600 |
commit | a908f8d0024fafc3238201e4c9fa872446b07c04 (patch) | |
tree | f8c2b081b9782a939966102ed1943a4ddacc3fe4 /src/game/MotionMaster.cpp | |
parent | 62a6911dc70b71125d40d036dd49e0be867b7c0e (diff) |
[7237] Fixed crash when MotionMaster's Clean or ExpireMovement called from MovementGenerator update.
Implemented delayed movement generators removed in case cleanup is triggered
from movement generator update. For this purpose is in runtime allocated vector
for temporary store of all deleted movement generators. After delayed delete
this vector is deleted.
Signed-off-by: ApoC <apoc@nymfe.net>
(With adaptation)
--HG--
branch : trunk
Diffstat (limited to 'src/game/MotionMaster.cpp')
-rw-r--r-- | src/game/MotionMaster.cpp | 148 |
1 files changed, 90 insertions, 58 deletions
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 96072014fa8..d74602844a5 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -47,11 +47,7 @@ MotionMaster::Initialize() { MovementGenerator *curr = top(); pop(); - if(!curr) - continue; - curr->Finalize(*i_owner); - if( !isStatic( curr ) ) - delete curr; + if(curr) DirectDelete(curr); } // set new default movement generator @@ -72,82 +68,103 @@ MotionMaster::~MotionMaster() { MovementGenerator *curr = top(); pop(); - if(!curr) - continue; - curr->Finalize(*i_owner); - if( !isStatic( curr ) ) - delete curr; + if(curr) DirectDelete(curr); } } 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]; + DirectDelete(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 ) { MovementGenerator *curr = top(); pop(); - if(!curr) - continue; - curr->Finalize(*i_owner); - if( !isStatic( curr ) ) - delete curr; + if(curr) DirectDelete(curr); } - if (reset) - { - assert( !empty() ); + if(reset) top()->Reset(*i_owner); - } } void -MotionMaster::MoveRandom(float spawndist) +MotionMaster::DelayedClean() { - if(i_owner->GetTypeId()==TYPEID_UNIT) + while( !empty() && size() > 1 ) { - DEBUG_LOG("Creature (GUID: %u) start moving random", i_owner->GetGUIDLow() ); - Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE); + MovementGenerator *curr = top(); + pop(); + if(curr) DelayedDelete(curr); } } void -MotionMaster::MovementExpired(bool reset) +MotionMaster::DirectExpire(bool reset) { if( empty() || size() == 1 ) return; MovementGenerator *curr = top(); - curr->Finalize(*i_owner); pop(); + DirectDelete(curr); - if( !isStatic(curr) ) - delete curr; - - assert( !empty() ); while(!top()) --i_top; - /*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(); - delete curr; - }*/ - if( empty() ) + + if(empty()) Initialize(); - if (reset) top()->Reset(*i_owner); + if(reset) + top()->Reset(*i_owner); +} + +void +MotionMaster::DelayedExpire() +{ + if( empty() || size() == 1 ) + return; + + MovementGenerator *curr = top(); + pop(); + DelayedDelete(curr); + + while(!top()) + --i_top; } void MotionMaster::MoveIdle(MovementSlot slot) @@ -159,6 +176,16 @@ void MotionMaster::MoveIdle(MovementSlot slot) } void +MotionMaster::MoveRandom(float spawndist) +{ + if(i_owner->GetTypeId()==TYPEID_UNIT) + { + DEBUG_LOG("Creature (GUID: %u) start moving random", i_owner->GetGUIDLow() ); + Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE); + } +} + +void MotionMaster::MoveTargetedHome() { //if(i_owner->hasUnitState(UNIT_STAT_FLEEING)) @@ -360,9 +387,10 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) { if(MovementGenerator *curr = Impl[slot]) { - curr->Finalize(*i_owner); - if( !isStatic( curr ) ) - delete curr; + if(i_top == slot && (m_cleanFlag & MMCF_UPDATE)) + DelayedDelete(curr); + else + DirectDelete(curr); } else if(i_top < slot) { @@ -370,20 +398,6 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) } m->Initialize(*i_owner); Impl[slot] = m; - - /*if (!empty()) - { - switch(top()->GetMovementGeneratorType()) - { - // HomeMovement is not that important, delete it if meanwhile a new comes - case HOME_MOTION_TYPE: - // DistractMovement interrupted by any other movement - case DISTRACT_MOTION_TYPE: - MovementExpired(false); - } - } - m->Initialize(*i_owner); - push(m);*/ } void MotionMaster::MovePath(uint32 path_id, bool repeatable) @@ -432,6 +446,24 @@ MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const return top()->GetMovementGeneratorType(); } +void MotionMaster::DirectDelete(_Ty curr) +{ + if(isStatic(curr)) + return; + curr->Finalize(*i_owner); + delete curr; +} + +void MotionMaster::DelayedDelete(_Ty curr) +{ + sLog.outError("CRASH ALARM! Unit (Entry %u) is trying to delete its updating MG (Type %u)!", i_owner->GetEntry(), curr->GetMovementGeneratorType()); + if(isStatic(curr)) + return; + if(!m_expList) + m_expList = new ExpireList(); + m_expList->push_back(curr); +} + bool MotionMaster::GetDestination(float &x, float &y, float &z) { if(empty()) |