diff options
author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2021-12-27 13:33:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-27 13:33:37 +0100 |
commit | 19e99db821ba5975e88ec160df3f4ff78ed562b0 (patch) | |
tree | 00d21b3b614c385f56858b81005616c29c0d2f37 /src | |
parent | a9c80e4402a8b6b3a8a2fb478b700c16fc5ddbb4 (diff) |
Core/AI: Fix crashes caused by charmed Creatures having null AI for 1 map update tick (#27434)
Implement using ScheduledChangeAI instead of nullptr to signal a required AI change
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/AI/CoreAI/ScheduledChangeAI.cpp | 21 | ||||
-rw-r--r-- | src/server/game/AI/CoreAI/ScheduledChangeAI.h | 40 | ||||
-rw-r--r-- | src/server/game/AI/CreatureAIRegistry.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 |
5 files changed, 86 insertions, 4 deletions
diff --git a/src/server/game/AI/CoreAI/ScheduledChangeAI.cpp b/src/server/game/AI/CoreAI/ScheduledChangeAI.cpp new file mode 100644 index 00000000000..c4f513fcfa6 --- /dev/null +++ b/src/server/game/AI/CoreAI/ScheduledChangeAI.cpp @@ -0,0 +1,21 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ScheduledChangeAI.h" + +ScheduledChangeAI::ScheduledChangeAI(Creature* creature): CreatureAI(creature) +{ } diff --git a/src/server/game/AI/CoreAI/ScheduledChangeAI.h b/src/server/game/AI/CoreAI/ScheduledChangeAI.h new file mode 100644 index 00000000000..79b8344eab0 --- /dev/null +++ b/src/server/game/AI/CoreAI/ScheduledChangeAI.h @@ -0,0 +1,40 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_SCHEDULEDCHANGEAI_H +#define TRINITY_SCHEDULEDCHANGEAI_H + +#include "CreatureAI.h" + +class TC_GAME_API ScheduledChangeAI final : public CreatureAI +{ + public: + explicit ScheduledChangeAI(Creature* creature); + + void MoveInLineOfSight(Unit*) override { } + void AttackStart(Unit*) override { } + void JustStartedThreateningMe(Unit*) override { } + void JustEnteredCombat(Unit*) override { } + void UpdateAI(uint32) override { } + void JustAppeared() override { } + void EnterEvadeMode(EvadeReason /*why*/) override { } + void OnCharmed(bool /*isNew*/) override { } + + static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; } +}; + +#endif diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp index 2ae35369966..50b9c5b34c8 100644 --- a/src/server/game/AI/CreatureAIRegistry.cpp +++ b/src/server/game/AI/CreatureAIRegistry.cpp @@ -23,6 +23,7 @@ #include "PassiveAI.h" #include "PetAI.h" #include "ReactorAI.h" +#include "ScheduledChangeAI.h" #include "SmartAI.h" #include "TotemAI.h" @@ -46,6 +47,7 @@ namespace AIRegistry (new CreatureAIFactory<TurretAI>("TurretAI"))->RegisterSelf(); (new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf(); (new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf(); + (new CreatureAIFactory<ScheduledChangeAI, false>("ScheduledChangeAI"))->RegisterSelf(); (new GameObjectAIFactory<NullGameObjectAI>("NullGameObjectAI"))->RegisterSelf(); (new GameObjectAIFactory<GameObjectAI>("GameObjectAI"))->RegisterSelf(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index eda7b604fe6..278087e4890 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -60,6 +60,7 @@ #include "PlayerAI.h" #include "QuestDef.h" #include "ReputationMgr.h" +#include "ScheduledChangeAI.h" #include "SpellAuraEffects.h" #include "SpellAuras.h" #include "Spell.h" @@ -491,7 +492,7 @@ void Unit::Update(uint32 p_time) // All position info based actions have been executed, reset info _positionUpdateInfo.Reset(); - if (!GetAI() && (GetTypeId() != TYPEID_PLAYER || (IsCharmed() && GetCharmerGUID().IsCreature()))) + if (HasScheduledAIChange() && (GetTypeId() != TYPEID_PLAYER || (IsCharmed() && GetCharmerGUID().IsCreature()))) UpdateCharmAI(); RefreshAI(); } @@ -9524,11 +9525,11 @@ void Unit::ScheduleAIChange() bool const charmed = IsCharmed(); if (charmed) - PushAI(nullptr); + PushAI(GetScheduledChangeAI()); else { RestoreDisabledAI(); - PushAI(nullptr); //This could actually be PopAI() to get the previous AI but it's required atm to trigger UpdateCharmAI() + PushAI(GetScheduledChangeAI()); //This could actually be PopAI() to get the previous AI but it's required atm to trigger UpdateCharmAI() } } @@ -9536,10 +9537,26 @@ void Unit::RestoreDisabledAI() { // Keep popping the stack until we either reach the bottom or find a valid AI while (PopAI()) - if (GetTopAI()) + if (GetTopAI() && dynamic_cast<ScheduledChangeAI*>(GetTopAI()) == nullptr) return; } +UnitAI* Unit::GetScheduledChangeAI() +{ + if (Creature* creature = ToCreature()) + return new ScheduledChangeAI(creature); + else + return nullptr; +} + +bool Unit::HasScheduledAIChange() const +{ + if (UnitAI* ai = GetAI()) + return dynamic_cast<ScheduledChangeAI*>(ai) != nullptr; + else + return true; +} + void Unit::AddToWorld() { if (IsInWorld()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index ea63c22ea3a..07f46b6a7c7 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -804,6 +804,8 @@ class TC_GAME_API Unit : public WorldObject void SetAI(UnitAI* newAI); UnitAI* GetTopAI() const { return i_AIs.empty() ? nullptr : i_AIs.top().get(); } void RefreshAI(); + UnitAI* GetScheduledChangeAI(); + bool HasScheduledAIChange() const; public: void AddToWorld() override; |