[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>
This commit is contained in:
ApoC 2009-01-26 00:54:27 +01:00
parent 7dffae89da
commit 6e65999d86
3 changed files with 119 additions and 9 deletions

View file

@ -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() ) )