aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/game/MotionMaster.cpp148
-rw-r--r--src/game/MotionMaster.h61
-rw-r--r--src/shared/revision_nr.h2
3 files changed, 139 insertions, 72 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())
diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h
index 73145665ae7..2822cdcd327 100644
--- a/src/game/MotionMaster.h
+++ b/src/game/MotionMaster.h
@@ -22,7 +22,7 @@
#define TRINITY_MOTIONMASTER_H
#include "Common.h"
-#include <stack>
+#include <vector>
class MovementGenerator;
class Unit;
@@ -55,12 +55,20 @@ enum MovementSlot
MAX_MOTION_SLOT,
};
+enum MMCleanFlag
+{
+ MMCF_NONE = 0,
+ MMCF_UPDATE = 1, // Clear or Expire called from update
+ MMCF_RESET = 2 // Flag if need top()->Reset()
+};
+
class TRINITY_DLL_SPEC MotionMaster //: private std::stack<MovementGenerator *>
{
private:
//typedef std::stack<MovementGenerator *> Impl;
typedef MovementGenerator* _Ty;
_Ty Impl[MAX_MOTION_SLOT];
+ typedef std::vector<_Ty> ExpireList;
int i_top;
bool empty() const { return i_top < 0; }
@@ -68,7 +76,7 @@ class TRINITY_DLL_SPEC MotionMaster //: private std::stack<MovementGenerator *>
void push(_Ty _Val) { ++i_top; Impl[i_top] = _Val; }
public:
- explicit MotionMaster(Unit *unit) : i_owner(unit), i_top(-1)
+ explicit MotionMaster(Unit *unit) : i_owner(unit), m_expList(NULL), m_cleanFlag(MMCF_NONE), i_top(-1)
{
for(int i = 0; i < MAX_MOTION_SLOT; ++i)
Impl[i] = NULL;
@@ -77,21 +85,40 @@ class TRINITY_DLL_SPEC MotionMaster //: private std::stack<MovementGenerator *>
void Initialize();
- //MovementGenerator* operator->(void) { return top(); }
-
int size() const { return i_top + 1; }
_Ty top() const { return Impl[i_top]; }
_Ty GetMotionSlot(int slot) { return Impl[slot]; }
- /*using Impl::top;
- using Impl::empty;
- typedef Impl::container_type::const_iterator const_iterator;
- const_iterator begin() const { return Impl::c.begin(); }
- const_iterator end() const { return Impl::c.end(); }*/
+ void DirectDelete(_Ty curr);
+ void DelayedDelete(_Ty curr);
- 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(MovementSlot slot = MOTION_SLOT_ACTIVE);
void MoveTargetedHome();
@@ -114,6 +141,14 @@ class TRINITY_DLL_SPEC MotionMaster //: private std::stack<MovementGenerator *>
private:
void Mutate(MovementGenerator *m, MovementSlot slot); // 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 0d4ffb5b9ba..f8ffeb005b6 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 "7238"
#endif // __REVISION_NR_H__