aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2018-11-05 20:28:42 +0100
committerShauren <shauren.trinity@gmail.com>2021-11-15 22:20:17 +0100
commit1015f307041b25b47a9bb4bc76ac4ed78c49d735 (patch)
tree4b570b57a8df7ee008cac4dfec97bb02d6f87cee /src
parent1232f1d06e21ba0bfb0e956b8e957780cd5985c2 (diff)
Core/AI: Add some checks to catch if the AI changes mid-update for players. Tag #22731 #22629.
(cherry picked from commit d8fee3c46b70fed660aec905a496e56d6a327aaf)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp17
-rw-r--r--src/server/game/Entities/Creature/Creature.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp18
-rw-r--r--src/server/game/Entities/Unit/Unit.h3
5 files changed, 13 insertions, 28 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 92feefa27e3..1d21caa6689 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -300,7 +300,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_groupLootTimer(0), m_PlayerDamageReq(0), _pickpocketLootRestore(0),
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0),
- m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0),
+ m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0),
m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), m_focusSpell(nullptr), m_focusDelay(0), m_shouldReacquireTarget(false), m_suppressedOrientation(0.0f), _lastDamagedTime(0),
_regenerateHealth(true), _regenerateHealthLock(false)
{
@@ -846,9 +846,7 @@ void Creature::Update(uint32 diff)
// do not allow the AI to be changed during update
- m_AI_locked = true;
Unit::AIUpdateTick(diff);
- m_AI_locked = false;
// creature can be dead after UpdateAI call
// CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
@@ -1007,25 +1005,12 @@ void Creature::DoFleeToGetAssistance()
bool Creature::AIM_Destroy()
{
- if (m_AI_locked)
- {
- TC_LOG_DEBUG("scripts", "AIM_Destroy: failed to destroy, locked.");
- return false;
- }
-
SetAI(nullptr);
return true;
}
bool Creature::AIM_Create(CreatureAI* ai /*= nullptr*/)
{
- // make sure nothing can change the AI during AI update
- if (m_AI_locked)
- {
- TC_LOG_DEBUG("scripts", "AIM_Initialize: failed to init, locked.");
- return false;
- }
-
Motion_Initialize();
SetAI(ai ? ai : FactorySelector::SelectAI(this));
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index d840f0378f1..bca4874df5f 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -402,7 +402,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool m_AlreadySearchedAssistance;
bool m_cannotReachTarget;
uint32 m_cannotReachTimer;
- bool m_AI_locked;
SpellSchoolMask m_meleeDamageSchoolMask;
uint32 m_originalEntry;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 3154dbcc6e9..0381e1d7163 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -972,7 +972,7 @@ void Player::Update(uint32 p_time)
if (!aura->IsPermanent())
aura->SetDuration(aura->GetSpellInfo()->GetMaxDuration());
- AIUpdateTick(p_time);
+ Unit::AIUpdateTick(p_time);
// Update items that have just a limited lifetime
if (now > m_Last_tick)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index da0dd3eb82e..c6a300bbfb2 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -304,7 +304,7 @@ Unit::Unit(bool isWorldObject) :
m_charmer(nullptr), m_charmed(nullptr),
i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_vehicle(nullptr),
m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_combatManager(this),
- m_threatManager(this), _aiAnimKitId(0), _movementAnimKitId(0), _meleeAnimKitId(0),
+ m_threatManager(this), m_aiLocked(false), _aiAnimKitId(0), _movementAnimKitId(0), _meleeAnimKitId(0),
_spellHistory(new SpellHistory(this))
{
m_objectType |= TYPEMASK_UNIT;
@@ -9058,24 +9058,25 @@ int32 Unit::GetCreatePowers(Powers power) const
return 0;
}
-void Unit::AIUpdateTick(uint32 diff, bool /*force*/)
+void Unit::AIUpdateTick(uint32 diff)
{
- if (!diff) // some places call with diff = 0, which does nothing (for now), see PR #22296
- return;
if (UnitAI* ai = GetAI())
+ {
+ m_aiLocked = true;
ai->UpdateAI(diff);
+ m_aiLocked = false;
+ }
}
void Unit::SetAI(UnitAI* newAI)
{
- if (i_AI)
- AIUpdateTick(0, true); // old AI gets a final tick if enabled
+ ASSERT(!m_aiLocked, "Attempt to replace AI during AI update tick");
i_AI.reset(newAI);
- AIUpdateTick(0, true); // new AI gets its initial tick
}
void Unit::ScheduleAIChange()
{
+ ASSERT(!m_aiLocked, "Attempt to schedule AI change during AI update tick");
bool const charmed = IsCharmed();
// if charm is applied, we can't have disabled AI already, and vice versa
if (charmed)
@@ -9091,9 +9092,9 @@ void Unit::ScheduleAIChange()
void Unit::RestoreDisabledAI()
{
+ ASSERT(!m_aiLocked, "Attempt to restore AI during UpdateAI tick");
ASSERT((GetTypeId() == TYPEID_PLAYER) || i_disabledAI, "Attempt to restore disabled AI on creature without disabled AI");
i_AI = std::move(i_disabledAI);
- AIUpdateTick(0, true);
}
void Unit::AddToWorld()
@@ -9216,7 +9217,6 @@ void Unit::UpdateCharmAI()
ASSERT(newAI);
i_AI.reset(newAI);
newAI->OnCharmed(true);
- AIUpdateTick(0, true);
}
else
{
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 71bd838afd2..95c205cadfd 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -765,7 +765,7 @@ class TC_GAME_API Unit : public WorldObject
virtual ~Unit();
bool IsAIEnabled() const { return (i_AI != nullptr); }
- void AIUpdateTick(uint32 diff, bool force = false);
+ void AIUpdateTick(uint32 diff);
UnitAI* GetAI() const { return i_AI.get(); }
void SetAI(UnitAI* newAI);
void ScheduleAIChange();
@@ -1969,6 +1969,7 @@ class TC_GAME_API Unit : public WorldObject
void UpdateCharmAI();
void RestoreDisabledAI();
std::unique_ptr<UnitAI> i_AI, i_disabledAI;
+ bool m_aiLocked;
std::unordered_set<AbstractFollower*> m_followingMe;