[9445] Possible fix often crashes in waypoint movegen.

Thanks to DrKLO for research source of problem!
This commit is contained in:
VladimirMangos 2010-02-24 22:37:26 +03:00
parent 24f2d4658f
commit 87b08b4fa1
8 changed files with 35 additions and 8 deletions

View file

@ -117,9 +117,12 @@ bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
// currently moving, update location // currently moving, update location
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE); unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
Traveller<T> traveller(unit); Traveller<T> traveller(unit);
if( i_destinationHolder.UpdateTraveller(traveller, diff, false)) if (i_destinationHolder.UpdateTraveller(traveller, diff, false))
{ {
if( i_destinationHolder.HasArrived()) if (!IsActive(unit)) // force stop processing (movement can move out active zone with cleanup movegens list)
return true; // not expire now, but already lost
if (i_destinationHolder.HasArrived())
{ {
// arrived, stop and wait a bit // arrived, stop and wait a bit
unit.StopMoving(); unit.StopMoving();

View file

@ -59,7 +59,11 @@ bool
HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff) HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
{ {
CreatureTraveller traveller( owner); CreatureTraveller traveller( owner);
i_destinationHolder.UpdateTraveller(traveller, time_diff, false); if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
{
if (!IsActive(owner)) // force stop processing (movement can move out active zone with cleanup movegens list)
return true; // not expire now, but already lost
}
if (time_diff > i_travel_timer) if (time_diff > i_travel_timer)
{ {

View file

@ -21,3 +21,10 @@
MovementGenerator::~MovementGenerator() MovementGenerator::~MovementGenerator()
{ {
} }
bool MovementGenerator::IsActive( Unit& u )
{
// When movement generator list modified from Update movegen object erase delayed,
// so pointer still valid and be used for check
return !u.GetMotionMaster()->empty() && u.GetMotionMaster()->top() == this;
}

View file

@ -55,6 +55,10 @@ class MANGOS_DLL_SPEC MovementGenerator
// used by Evade code for select point to evade with expected restart default movement // used by Evade code for select point to evade with expected restart default movement
virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; }
// used for check from Update call is movegen still be active (top movement generator)
// after some not safe for this calls
bool IsActive(Unit& u);
}; };
template<class T, class D> template<class T, class D>

View file

@ -164,6 +164,9 @@ bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32
if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true)) if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true))
{ {
if (!IsActive(creature)) // force stop processing (movement can move out active zone with cleanup movegens list)
return true; // not expire now, but already lost
if (i_nextMoveTime.Passed()) if (i_nextMoveTime.Passed())
{ {
if (creature.canFly()) if (creature.canFly())

View file

@ -149,6 +149,9 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false)) if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
{ {
if (!IsActive(owner)) // force stop processing (movement can move out active zone with cleanup movegens list)
return true; // not expire now, but already lost
// put targeted movement generators on a higher priority // put targeted movement generators on a higher priority
if (owner.GetObjectSize()) if (owner.GetObjectSize())
i_destinationHolder.ResetUpdate(50); i_destinationHolder.ResetUpdate(50);

View file

@ -129,7 +129,11 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
CreatureTraveller traveller(creature); CreatureTraveller traveller(creature);
i_nextMoveTime.Update(diff); i_nextMoveTime.Update(diff);
i_destinationHolder.UpdateTraveller(traveller, diff, false, true); if (i_destinationHolder.UpdateTraveller(traveller, diff, false, true))
{
if (!IsActive(creature)) // force stop processing (movement can move out active zone with cleanup movegens list)
return true; // not expire now, but already lost
}
// creature has been stopped in middle of the waypoint segment // creature has been stopped in middle of the waypoint segment
if (!i_destinationHolder.HasArrived() && creature.IsStopped()) if (!i_destinationHolder.HasArrived() && creature.IsStopped())
@ -206,12 +210,11 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
i_hasDone[idx] = true; i_hasDone[idx] = true;
MovementInform(creature); MovementInform(creature);
// force stop processing (script change movegen list) if (!IsActive(creature)) // force stop processing (movement can move out active zone with cleanup movegens list)
if (creature.GetMotionMaster()->empty() || creature.GetMotionMaster()->top() != this)
return true; // not expire now, but already lost return true; // not expire now, but already lost
// prevent a crash at empty waypoint path. // prevent a crash at empty waypoint path.
if (!i_path || i_path->empty()) if (!i_path || i_path->empty() || i_currentNode >= i_path->size())
{ {
creature.clearUnitState(UNIT_STAT_ROAMING_MOVE); creature.clearUnitState(UNIT_STAT_ROAMING_MOVE);
return true; return true;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9444" #define REVISION_NR "9445"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__