aboutsummaryrefslogtreecommitdiff
path: root/src/game/MotionMaster.cpp
diff options
context:
space:
mode:
authormegamage <none@none>2009-02-08 21:43:46 -0600
committermegamage <none@none>2009-02-08 21:43:46 -0600
commita908f8d0024fafc3238201e4c9fa872446b07c04 (patch)
treef8c2b081b9782a939966102ed1943a4ddacc3fe4 /src/game/MotionMaster.cpp
parent62a6911dc70b71125d40d036dd49e0be867b7c0e (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.cpp148
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())