mirror of
https://github.com/mangosfour/server.git
synced 2025-12-17 07:37:03 +00:00
[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:
parent
7dffae89da
commit
6e65999d86
3 changed files with 119 additions and 9 deletions
|
|
@ -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() ) )
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "Common.h"
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
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<MovementGenerator *>
|
||||
{
|
||||
private:
|
||||
typedef std::stack<MovementGenerator *> Impl;
|
||||
typedef std::vector<MovementGenerator *> 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<MovementGenerator *>
|
|||
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<MovementGenerator *>
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "7236"
|
||||
#define REVISION_NR "7237"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue