diff options
author | Treeston <treeston.mmoc@gmail.com> | 2018-11-05 20:28:42 +0100 |
---|---|---|
committer | Treeston <treeston.mmoc@gmail.com> | 2018-11-05 20:28:42 +0100 |
commit | d8fee3c46b70fed660aec905a496e56d6a327aaf (patch) | |
tree | 70a39be1c9bf051afe089dfd0ff302dbfc507815 /src | |
parent | f2df802c500e3878ba431d1be0a57ce293983121 (diff) |
Core/AI: Add some checks to catch if the AI changes mid-update for players. Tag #22731 #22629.
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 3 |
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 7cbb2e3d2ba..88f434d0cd2 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -253,7 +253,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipient(), m_lootRecipientGroup(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(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) { @@ -791,9 +791,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) @@ -960,25 +958,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 f6424e2ec11..b3c04f1fed1 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -396,7 +396,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 7f37550b0f9..db4267c8cf9 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1056,7 +1056,7 @@ void Player::Update(uint32 p_time) UpdateAfkReport(now); - 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 58b5af0b9ef..4262ced1fbb 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -292,7 +292,7 @@ Unit::Unit(bool isWorldObject) : m_procDeep(0), m_transformSpell(0), m_removedAurasCount(0), 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), - m_comboTarget(nullptr), m_comboPoints(0), m_spellHistory(new SpellHistory(this)) + m_aiLocked(false), m_comboTarget(nullptr), m_comboPoints(0), m_spellHistory(new SpellHistory(this)) { m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; @@ -9401,24 +9401,25 @@ uint32 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) @@ -9434,9 +9435,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() @@ -9558,7 +9559,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 7d3288e092e..67b9b886b49 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(); @@ -1790,6 +1790,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; |