diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 865415f59..2f9bba321 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -23,6 +23,17 @@ #include "Unit.h" #include +#define CAST_AI(a, b) (dynamic_cast(b)) +#define ENSURE_AI(a,b) (EnsureAI(b)) + +template +T* EnsureAI(U* ai) +{ + T* cast_ai = dynamic_cast(ai); + ASSERT(cast_ai); + return cast_ai; +} + class Player; class Quest; class Unit; diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index be04450d0..f6ed31486 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -25,8 +25,6 @@ #include "InstanceScript.h" #include "TaskScheduler.h" -#define CAST_AI(a, b) (dynamic_cast(b)) - typedef std::list ObjectList; class InstanceScript; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index d126a9cfc..d3ec5eb51 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -962,9 +962,9 @@ uint32 SmartAI::GetData(uint32 /*id*/) const return 0; } -void SmartAI::SetData(uint32 id, uint32 value) +void SmartAI::SetData(uint32 id, uint32 value, Unit* invoker) { - GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, nullptr, id, value); + GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value); } void SmartAI::SetGUID(ObjectGuid /*guid*/, int32 /*id*/) @@ -1232,9 +1232,9 @@ void SmartGameObjectAI::Destroyed(Player* player, uint32 eventId) GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, player, eventId, 0, false, nullptr, me); } -void SmartGameObjectAI::SetData(uint32 id, uint32 value) +void SmartGameObjectAI::SetData(uint32 id, uint32 value, Unit* invoker) { - GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, nullptr, id, value); + GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value); } void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker) diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index acb52d904..0311590fe 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -159,7 +159,8 @@ public: uint32 GetData(uint32 id = 0) const override; // Used in scripts to share variables - void SetData(uint32 id, uint32 value) override; + void SetData(uint32 id, uint32 value) override { SetData(id, value, nullptr); } + void SetData(uint32 id, uint32 value, Unit* invoker); // Used in scripts to share variables void SetGUID(ObjectGuid guid, int32 id = 0) override; @@ -272,7 +273,8 @@ public: bool QuestAccept(Player* player, Quest const* quest) override; bool QuestReward(Player* player, Quest const* quest, uint32 opt) override; void Destroyed(Player* player, uint32 eventId) override; - void SetData(uint32 id, uint32 value) override; + void SetData(uint32 id, uint32 value) override { SetData(id, value, nullptr); } + void SetData(uint32 id, uint32 value, Unit* invoker); void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); void OnGameEvent(bool start, uint16 eventId) override; void OnStateChanged(uint32 state, Unit* unit) override; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 3102b37bf..7930317bf 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -63,7 +63,46 @@ SmartScript::SmartScript() SmartScript::~SmartScript() { +} +bool SmartScript::IsSmart(Creature* c, bool silent) const +{ + if (!c) + return false; + + bool smart = true; + if (!dynamic_cast(c->AI())) + smart = false; + + if (!smart && !silent) + LOG_ERROR("sql.sql", "SmartScript: Action target Creature(entry: {}) is not using SmartAI, action skipped to prevent crash.", c ? c->GetEntry() : (me ? me->GetEntry() : 0)); + + return smart; +} + +bool SmartScript::IsSmart(GameObject* g, bool silent) const +{ + if (!g) + return false; + + bool smart = true; + if (!dynamic_cast(g->AI())) + smart = false; + + if (!smart && !silent) + LOG_ERROR("sql.sql", "SmartScript: Action target GameObject(entry: {}) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetEntry() : (go ? go->GetEntry() : 0)); + + return smart; +} + +bool SmartScript::IsSmart(bool silent) const +{ + if (me) + return IsSmart(me, silent); + if (go) + return IsSmart(go, silent); + + return false; } void SmartScript::OnReset() @@ -1355,10 +1394,22 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { for (WorldObject* target : targets) { - if (IsCreature(target)) - target->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data); - else if (IsGameObject(target)) - target->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data); + if (Creature* cTarget = target->ToCreature()) + { + CreatureAI* ai = cTarget->AI(); + if (IsSmart(cTarget)) + ENSURE_AI(SmartAI, ai)->SetData(e.action.setData.field, e.action.setData.data, me); + else + ai->SetData(e.action.setData.field, e.action.setData.data); + } + else if (GameObject* oTarget = target->ToGameObject()) + { + GameObjectAI* ai = oTarget->AI(); + if (IsSmart(oTarget)) + ENSURE_AI(SmartGameObjectAI, ai)->SetData(e.action.setData.field, e.action.setData.data, me); + else + ai->SetData(e.action.setData.field, e.action.setData.data); + } } break; } @@ -1974,7 +2025,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else if (GameObject* go = target->ToGameObject()) { - if (IsSmartGO(go)) + if (IsSmart(go)) CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); } } @@ -2061,7 +2112,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else if (GameObject* go = target->ToGameObject()) { - if (IsSmartGO(go)) + if (IsSmart(go)) CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } } @@ -2085,7 +2136,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else if (GameObject* go = target->ToGameObject()) { - if (IsSmartGO(go)) + if (IsSmart(go)) CAST_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index b9ab57327..82ac3700d 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -76,6 +76,10 @@ public: void DoFindFriendlyMissingBuff(std::vector& creatures, float range, uint32 spellid) const; Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly) const; + bool IsSmart(Creature* c, bool silent = false) const; + bool IsSmart(GameObject* g, bool silent = false) const; + bool IsSmart(bool silent = false) const; + void StoreTargetList(ObjectVector const& targets, uint32 id) { // insert or replace @@ -83,35 +87,6 @@ public: _storedTargets.emplace(id, ObjectGuidVector(targets)); } - bool IsSmart(Creature* c = nullptr) - { - bool smart = true; - if (c && c->GetAIName() != "SmartAI") - smart = false; - - if (!me || me->GetAIName() != "SmartAI") - smart = false; - - if (!smart) - LOG_ERROR("sql.sql", "SmartScript: Action target Creature(entry: {}) is not using SmartAI, action skipped to prevent crash.", c ? c->GetEntry() : (me ? me->GetEntry() : 0)); - - return smart; - } - - bool IsSmartGO(GameObject* g = nullptr) - { - bool smart = true; - if (g && g->GetAIName() != "SmartGameObjectAI") - smart = false; - - if (!go || go->GetAIName() != "SmartGameObjectAI") - smart = false; - if (!smart) - LOG_ERROR("sql.sql", "SmartScript: Action target GameObject(entry: {}) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetEntry() : (go ? go->GetEntry() : 0)); - - return smart; - } - ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const { auto itr = _storedTargets.find(id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 1f2c3ae9b..a3d759a6d 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -346,6 +346,7 @@ void SmartAIMgr::LoadSmartAIFromDB() case SMART_EVENT_TRANSPORT_ADDCREATURE: case SMART_EVENT_NEAR_PLAYERS: case SMART_EVENT_SUMMONED_UNIT_EVADE: + case SMART_EVENT_DATA_SET: return true; default: return false;