Skip to content

Commit 1cfb430

Browse files
committed
Core/Movement: Fix movement generator priority sorting mismatch between MovementGeneratorComparator and MotionMaster::DirectAdd
* Also changed generators container from multiset to set because uniqueness was already ensured by deactivation logic in MotionMaster::DirectAdd
1 parent 2d5430e commit 1cfb430

19 files changed

Lines changed: 55 additions & 140 deletions

src/server/game/AI/SmartScripts/SmartAI.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ void SmartAI::SetCombatMove(bool on, bool stopMoving)
807807
{
808808
if (!me->HasReactState(REACT_PASSIVE) && me->GetVictim() && !me->GetMotionMaster()->HasMovementGenerator([](MovementGenerator const* movement) -> bool
809809
{
810-
return movement->GetMovementGeneratorType() == CHASE_MOTION_TYPE && movement->Mode == MOTION_MODE_DEFAULT && movement->Priority == MOTION_PRIORITY_NORMAL;
810+
return movement->GetMovementGeneratorType() == CHASE_MOTION_TYPE && movement->Priority == MOTION_PRIORITY_NORMAL;
811811
}))
812812
{
813813
SetRun(_run);
@@ -816,7 +816,7 @@ void SmartAI::SetCombatMove(bool on, bool stopMoving)
816816
}
817817
else if (MovementGenerator* movement = me->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* a) -> bool
818818
{
819-
return a->GetMovementGeneratorType() == CHASE_MOTION_TYPE && a->Mode == MOTION_MODE_DEFAULT && a->Priority == MOTION_PRIORITY_NORMAL;
819+
return a->GetMovementGeneratorType() == CHASE_MOTION_TYPE && a->Priority == MOTION_PRIORITY_NORMAL;
820820
}))
821821
{
822822
me->GetMotionMaster()->Remove(movement);

src/server/game/Movement/MotionMaster.cpp

Lines changed: 43 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,7 @@ void MovementGeneratorDeleter::operator()(MovementGenerator* a)
7272

7373
bool MovementGeneratorComparator::operator()(MovementGenerator const* a, MovementGenerator const* b) const
7474
{
75-
if (a->Mode > b->Mode)
76-
return true;
77-
else if (a->Mode == b->Mode)
78-
return a->Priority > b->Priority;
79-
80-
return false;
75+
return a->Priority > b->Priority;
8176
}
8277

8378
MovementGeneratorInformation::MovementGeneratorInformation(MovementGeneratorType type, ObjectGuid targetGUID, std::string const& targetName) : Type(type), TargetGUID(targetGUID), TargetName(targetName) { }
@@ -88,8 +83,8 @@ MotionMaster::~MotionMaster()
8883
{
8984
_delayedActions.clear();
9085

91-
for (auto itr = _generators.begin(); itr != _generators.end(); itr = _generators.erase(itr))
92-
MovementGeneratorPointerDeleter(*itr);
86+
for (MovementGenerator* movement : _generators)
87+
MovementGeneratorPointerDeleter(movement);
9388
}
9489

9590
void MotionMaster::Initialize()
@@ -248,13 +243,12 @@ MovementGenerator* MotionMaster::GetMovementGenerator(std::function<bool(Movemen
248243
movement = _defaultGenerator.get();
249244
break;
250245
case MOTION_SLOT_ACTIVE:
251-
if (!_generators.empty())
252-
{
253-
auto itr = std::find_if(_generators.begin(), _generators.end(), std::ref(filter));
254-
if (itr != _generators.end())
255-
movement = *itr;
256-
}
246+
{
247+
auto itr = std::ranges::find_if(_generators, std::ref(filter));
248+
if (itr != _generators.end())
249+
movement = *itr;
257250
break;
251+
}
258252
default:
259253
break;
260254
}
@@ -271,15 +265,10 @@ bool MotionMaster::HasMovementGenerator(std::function<bool(MovementGenerator con
271265
switch (slot)
272266
{
273267
case MOTION_SLOT_DEFAULT:
274-
if (_defaultGenerator && filter(_defaultGenerator.get()))
275-
value = true;
268+
value = _defaultGenerator && filter(_defaultGenerator.get());
276269
break;
277270
case MOTION_SLOT_ACTIVE:
278-
if (!_generators.empty())
279-
{
280-
auto itr = std::find_if(_generators.begin(), _generators.end(), std::ref(filter));
281-
value = itr != _generators.end();
282-
}
271+
value = std::ranges::any_of(_generators, std::ref(filter));
283272
break;
284273
default:
285274
break;
@@ -346,7 +335,8 @@ void MotionMaster::Add(MovementGenerator* movement, MovementSlot slot/* = MOTION
346335

347336
if (movement->HasFlag(MOVEMENTGENERATOR_FLAG_IMMEDIATE) && movement->HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING))
348337
{
349-
if (!movement->Initialize(_owner))
338+
bool wouldBecomeTop = _generators.lower_bound(movement) == _generators.begin();
339+
if (!wouldBecomeTop || !movement->Initialize(_owner))
350340
{
351341
delete movement;
352342
return;
@@ -390,29 +380,27 @@ void MotionMaster::Remove(MovementGenerator* movement, MovementSlot slot/* = MOT
390380
DirectClearDefault();
391381
break;
392382
case MOTION_SLOT_ACTIVE:
393-
if (!_generators.empty())
394-
{
395-
auto bounds = _generators.equal_range(movement);
396-
auto itr = std::find(bounds.first, bounds.second, movement);
397-
if (itr != _generators.end())
398-
Remove(itr, GetCurrentMovementGenerator() == *itr, false);
399-
}
383+
{
384+
auto itr = _generators.find(movement);
385+
if (itr != _generators.end())
386+
Remove(itr, GetCurrentMovementGenerator() == *itr, false);
400387
break;
388+
}
401389
default:
402390
break;
403391
}
404392
}
405393

406-
void MotionMaster::Remove(MovementGeneratorType type, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/, MovementGeneratorMode mode/* = MOTION_MODE_DEFAULT*/)
394+
void MotionMaster::Remove(MovementGeneratorType type, MovementSlot slot/* = MOTION_SLOT_ACTIVE*/)
407395
{
408396
if (IsInvalidMovementGeneratorType(type) || IsInvalidMovementSlot(slot))
409397
return;
410398

411399
if (HasFlag(MOTIONMASTER_FLAG_DELAYED))
412400
{
413-
DelayedActionDefine action = [this, type, slot, mode]()
401+
DelayedActionDefine action = [this, type, slot]()
414402
{
415-
Remove(type, slot, mode);
403+
Remove(type, slot);
416404
};
417405
_delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_REMOVE_TYPE);
418406
return;
@@ -428,16 +416,14 @@ void MotionMaster::Remove(MovementGeneratorType type, MovementSlot slot/* = MOTI
428416
DirectClearDefault();
429417
break;
430418
case MOTION_SLOT_ACTIVE:
431-
if (!_generators.empty())
419+
do
432420
{
433-
auto itr = std::find_if(_generators.begin(), _generators.end(), [type, mode](MovementGenerator const* a) -> bool
434-
{
435-
return a->GetMovementGeneratorType() == type && a->Mode == mode;
436-
});
437-
438-
if (itr != _generators.end())
439-
Remove(itr, GetCurrentMovementGenerator() == *itr, false);
440-
}
421+
auto itr = std::ranges::find(_generators, type,
422+
[](MovementGenerator const* a) { return a->GetMovementGeneratorType(); });
423+
if (itr == _generators.end())
424+
break;
425+
Remove(itr, GetCurrentMovementGenerator() == *itr, false);
426+
} while (true);
441427
break;
442428
default:
443429
break;
@@ -491,28 +477,6 @@ void MotionMaster::Clear(MovementSlot slot)
491477
}
492478
}
493479

494-
void MotionMaster::Clear(MovementGeneratorMode mode)
495-
{
496-
if (HasFlag(MOTIONMASTER_FLAG_DELAYED))
497-
{
498-
DelayedActionDefine action = [this, mode]()
499-
{
500-
Clear(mode);
501-
};
502-
_delayedActions.emplace_back(std::move(action), MOTIONMASTER_DELAYED_CLEAR_MODE);
503-
return;
504-
}
505-
506-
if (Empty())
507-
return;
508-
509-
std::function<bool(MovementGenerator*)> criteria = [mode](MovementGenerator* a) -> bool
510-
{
511-
return a->Mode == mode;
512-
};
513-
DirectClear(criteria);
514-
}
515-
516480
void MotionMaster::Clear(MovementGeneratorPriority priority)
517481
{
518482
if (HasFlag(MOTIONMASTER_FLAG_DELAYED))
@@ -1106,17 +1070,18 @@ void MotionMaster::ResolveDelayedActions()
11061070
}
11071071
}
11081072

1109-
void MotionMaster::Remove(MotionMasterContainer::iterator iterator, bool active, bool movementInform)
1073+
void MotionMaster::Remove(MotionMasterContainer::iterator& iterator, bool active, bool movementInform)
11101074
{
11111075
MovementGenerator* pointer = *iterator;
1112-
_generators.erase(iterator);
1076+
iterator = _generators.erase(iterator);
11131077
Delete(pointer, active, movementInform);
11141078
}
11151079

11161080
void MotionMaster::Pop(bool active, bool movementInform)
11171081
{
1118-
if (!_generators.empty())
1119-
Remove(_generators.begin(), active, movementInform);
1082+
auto itr = _generators.begin();
1083+
if (itr != _generators.end())
1084+
Remove(itr, active, movementInform);
11201085
}
11211086

11221087
void MotionMaster::DirectInitialize()
@@ -1150,14 +1115,11 @@ void MotionMaster::DirectClearDefault()
11501115

11511116
void MotionMaster::DirectClear(std::function<bool(MovementGenerator*)> const& filter)
11521117
{
1153-
if (_generators.empty())
1154-
return;
1155-
1156-
MovementGenerator const* top = GetCurrentMovementGenerator();
11571118
for (auto itr = _generators.begin(); itr != _generators.end();)
11581119
{
11591120
if (filter(*itr))
11601121
{
1122+
MovementGenerator const* top = GetCurrentMovementGenerator(); // erase may change top, get fresh value on every removal
11611123
MovementGenerator* movement = *itr;
11621124
itr = _generators.erase(itr);
11631125
Delete(movement, movement == top, false);
@@ -1180,39 +1142,23 @@ void MotionMaster::DirectAdd(MovementGenerator* movement, MovementSlot slot/* =
11801142
AddFlag(MOTIONMASTER_FLAG_STATIC_INITIALIZATION_PENDING);
11811143
break;
11821144
case MOTION_SLOT_ACTIVE:
1145+
{
1146+
auto where = _generators.lower_bound(movement);
11831147
if (!_generators.empty())
11841148
{
1185-
if (movement->Priority >= (*_generators.begin())->Priority)
1186-
{
1187-
auto itr = _generators.begin();
1188-
MovementGenerator* currentTopMovement = *itr;
1189-
if (movement->Priority == currentTopMovement->Priority)
1190-
{
1191-
if (movement->Mode > currentTopMovement->Mode)
1192-
currentTopMovement->Deactivate(_owner);
1193-
else if (movement->Mode == currentTopMovement->Mode)
1194-
Remove(itr, true, false);
1195-
}
1196-
else
1197-
currentTopMovement->Deactivate(_owner);
1198-
}
1199-
else
1200-
{
1201-
auto itr = std::ranges::find_if(_generators, [movement](MovementGenerator const* a) -> bool
1202-
{
1203-
return a->Priority == movement->Priority && a->Mode == movement->Mode;
1204-
});
1205-
1206-
if (itr != _generators.end())
1207-
Remove(itr, false, false);
1208-
}
1149+
bool replacesExisting = where != _generators.end() && !_generators.key_comp()(movement, *where);
1150+
auto top = _generators.begin();
1151+
if (replacesExisting)
1152+
Remove(where, where == top, false);
1153+
else if (where == top)
1154+
(*top)->Deactivate(_owner);
12091155
}
12101156
else
12111157
_defaultGenerator->Deactivate(_owner);
12121158

12131159
if (!movement->HasFlag(MOVEMENTGENERATOR_FLAG_IMMEDIATE))
12141160
{
1215-
_generators.emplace(movement);
1161+
_generators.emplace_hint(where, movement);
12161162
AddBaseUnitState(movement);
12171163
}
12181164
else
@@ -1221,6 +1167,7 @@ void MotionMaster::DirectAdd(MovementGenerator* movement, MovementSlot slot/* =
12211167
delete movement;
12221168
}
12231169
break;
1170+
}
12241171
default:
12251172
break;
12261173
}

src/server/game/Movement/MotionMaster.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,12 @@ class TC_GAME_API MotionMaster
135135
void Remove(MovementGenerator* movement, MovementSlot slot = MOTION_SLOT_ACTIVE);
136136
// Removes first found movement
137137
// NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE
138-
void Remove(MovementGeneratorType type, MovementSlot slot = MOTION_SLOT_ACTIVE, MovementGeneratorMode mode = MOTION_MODE_DEFAULT);
138+
void Remove(MovementGeneratorType type, MovementSlot slot = MOTION_SLOT_ACTIVE);
139139
// NOTE: MOTION_SLOT_DEFAULT wont be affected
140140
void Clear();
141141
// Removes all movements for the given MovementSlot
142142
// NOTE: MOTION_SLOT_DEFAULT will be autofilled with IDLE_MOTION_TYPE
143143
void Clear(MovementSlot slot);
144-
// Removes all movements with the given MovementGeneratorMode
145-
// NOTE: MOTION_SLOT_DEFAULT wont be affected
146-
void Clear(MovementGeneratorMode mode);
147144
// Removes all movements with the given MovementGeneratorPriority
148145
// NOTE: MOTION_SLOT_DEFAULT wont be affected
149146
void Clear(MovementGeneratorPriority priority);
@@ -196,15 +193,15 @@ class TC_GAME_API MotionMaster
196193
void LaunchMoveSpline(std::function<void(Movement::MoveSplineInit& init)>&& initializer, uint32 id = 0, MovementGeneratorPriority priority = MOTION_PRIORITY_NORMAL, MovementGeneratorType type = EFFECT_MOTION_TYPE);
197194
private:
198195
typedef std::unique_ptr<MovementGenerator, MovementGeneratorDeleter> MovementGeneratorPointer;
199-
typedef std::multiset<MovementGenerator*, MovementGeneratorComparator> MotionMasterContainer;
196+
typedef std::set<MovementGenerator*, MovementGeneratorComparator> MotionMasterContainer;
200197
typedef std::unordered_multimap<uint32, MovementGenerator const*> MotionMasterUnitStatesContainer;
201198

202199
void AddFlag(uint8 const flag) { _flags |= flag; }
203200
bool HasFlag(uint8 const flag) const { return (_flags & flag) != 0; }
204201
void RemoveFlag(uint8 const flag) { _flags &= ~flag; }
205202

206203
void ResolveDelayedActions();
207-
void Remove(MotionMasterContainer::iterator iterator, bool active, bool movementInform);
204+
void Remove(MotionMasterContainer::iterator& iterator, bool active, bool movementInform);
208205
void Pop(bool active, bool movementInform);
209206
void DirectInitialize();
210207
void DirectClear();

src/server/game/Movement/MovementDefines.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,11 @@ constexpr bool CanStopMovementForSpellCasting(MovementGeneratorType type)
6262
return true;
6363
}
6464

65-
enum MovementGeneratorMode : uint8
66-
{
67-
MOTION_MODE_DEFAULT = 0,
68-
MOTION_MODE_OVERRIDE
69-
};
70-
7165
enum MovementGeneratorPriority : uint8
7266
{
73-
MOTION_PRIORITY_NONE = 0,
74-
MOTION_PRIORITY_NORMAL,
75-
MOTION_PRIORITY_HIGHEST
67+
MOTION_PRIORITY_NONE = 0,
68+
MOTION_PRIORITY_NORMAL = 64,
69+
MOTION_PRIORITY_HIGHEST = 128
7670
};
7771

7872
enum MovementSlot : uint8

src/server/game/Movement/MovementGenerator.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,16 @@
2121
#include "MovementDefines.h"
2222
#include "PathGenerator.h"
2323
#include "RandomMovementGenerator.h"
24+
#include "StringFormat.h"
2425
#include "UnitAI.h"
2526
#include "WaypointMovementGenerator.h"
2627

2728
MovementGenerator::~MovementGenerator() { }
2829

2930
std::string MovementGenerator::GetDebugInfo() const
3031
{
31-
std::stringstream sstr;
32-
sstr << std::boolalpha
33-
<< "Mode: " << std::to_string(Mode)
34-
<< " Priority: " << std::to_string(Priority)
35-
<< " Flags: " << Flags
36-
<< " BaseUniteState: " << BaseUnitState;
37-
return sstr.str();
32+
return Trinity::StringFormat("Priority: {} Flags: {} BaseUniteState: {}",
33+
Priority, Flags, BaseUnitState);
3834
}
3935

4036
IdleMovementFactory::IdleMovementFactory() : MovementGeneratorCreator(IDLE_MOTION_TYPE) { }

src/server/game/Movement/MovementGenerator.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ enum MovementGeneratorFlags : uint16
4848
class TC_GAME_API MovementGenerator
4949
{
5050
public:
51-
MovementGenerator() : Mode(0), Priority(0), Flags(MOVEMENTGENERATOR_FLAG_NONE), BaseUnitState(0) { }
51+
MovementGenerator() : Priority(0), Flags(MOVEMENTGENERATOR_FLAG_NONE), BaseUnitState(0) { }
5252
virtual ~MovementGenerator();
5353

5454
// on top first update
@@ -77,7 +77,6 @@ class TC_GAME_API MovementGenerator
7777

7878
virtual std::string GetDebugInfo() const;
7979

80-
uint8 Mode;
8180
uint8 Priority;
8281
uint16 Flags;
8382
uint32 BaseUnitState;

src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ static void DoMovementInform(Unit* owner, Unit* target)
6868
ChaseMovementGenerator::ChaseMovementGenerator(Unit *target, Optional<ChaseRange> range, Optional<ChaseAngle> angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range),
6969
_angle(angle), _rangeCheckTimer(RANGE_CHECK_INTERVAL)
7070
{
71-
Mode = MOTION_MODE_DEFAULT;
7271
Priority = MOTION_PRIORITY_NORMAL;
7372
Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING;
7473
BaseUnitState = UNIT_STATE_CHASE;

src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
template<class T>
2828
ConfusedMovementGenerator<T>::ConfusedMovementGenerator() : _timer(0), _x(0.f), _y(0.f), _z(0.f)
2929
{
30-
this->Mode = MOTION_MODE_DEFAULT;
3130
this->Priority = MOTION_PRIORITY_HIGHEST;
3231
this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING;
3332
this->BaseUnitState = UNIT_STATE_CONFUSED;

src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
template<class T>
3333
FleeingMovementGenerator<T>::FleeingMovementGenerator(ObjectGuid fleeTargetGUID) : _fleeTargetGUID(fleeTargetGUID), _timer(0)
3434
{
35-
this->Mode = MOTION_MODE_DEFAULT;
3635
this->Priority = MOTION_PRIORITY_HIGHEST;
3736
this->Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING;
3837
this->BaseUnitState = UNIT_STATE_FLEEING;

0 commit comments

Comments
 (0)