diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index d3ec5eb51..b38464bc0 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -962,9 +962,19 @@ uint32 SmartAI::GetData(uint32 /*id*/) const return 0; } -void SmartAI::SetData(uint32 id, uint32 value, Unit* invoker) +void SmartAI::SetData(uint32 id, uint32 value, WorldObject* invoker) { - GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value); + Unit* unit = nullptr; + GameObject* gob = nullptr; + + if (invoker) + { + unit = invoker->ToUnit(); + if (!unit) + gob = invoker->ToGameObject(); + } + + GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, unit, id, value, false, nullptr, gob); } void SmartAI::SetGUID(ObjectGuid /*guid*/, int32 /*id*/) @@ -1132,7 +1142,7 @@ void SmartAI::MoveAway(float distance) } } -void SmartAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker) +void SmartAI::SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker) { if (invoker) GetScript()->mLastInvoker = invoker->GetGUID(); @@ -1232,12 +1242,22 @@ 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, Unit* invoker) +void SmartGameObjectAI::SetData(uint32 id, uint32 value, WorldObject* invoker) { - GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, invoker, id, value); + Unit* unit = nullptr; + GameObject* gob = nullptr; + + if (invoker) + { + unit = invoker->ToUnit(); + if (!unit) + gob = invoker->ToGameObject(); + } + + GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, unit, id, value, false, nullptr, gob); } -void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker) +void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker) { if (invoker) GetScript()->mLastInvoker = invoker->GetGUID(); diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 0311590fe..e5a62a859 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -70,7 +70,7 @@ public: void StopFollow(bool complete); void MoveAway(float distance); - void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); + void SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker); SmartScript* GetScript() { return &mScript; } bool IsEscortInvokerInRange(); @@ -160,7 +160,7 @@ public: // Used in scripts to share variables void SetData(uint32 id, uint32 value) override { SetData(id, value, nullptr); } - void SetData(uint32 id, uint32 value, Unit* invoker); + void SetData(uint32 id, uint32 value, WorldObject* invoker); // Used in scripts to share variables void SetGUID(ObjectGuid guid, int32 id = 0) override; @@ -274,8 +274,8 @@ public: bool QuestReward(Player* player, Quest const* quest, uint32 opt) override; void Destroyed(Player* player, uint32 eventId) 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 SetData(uint32 id, uint32 value, WorldObject* invoker); + void SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker); void OnGameEvent(bool start, uint16 eventId) override; void OnStateChanged(uint32 state, Unit* unit) override; void EventInform(uint32 eventId) override; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 37ac2ff76..efac02f80 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -167,21 +167,29 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (unit) mLastInvoker = unit->GetGUID(); + else if (gob) + mLastInvoker = gob->GetGUID(); - if (Unit* tempInvoker = GetLastInvoker()) + if (WorldObject* tempInvoker = GetLastInvoker()) LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: Invoker: {} ({})", tempInvoker->GetName(), tempInvoker->GetGUID().ToString()); bool isControlled = e.action.moveToPos.controlled > 0; ObjectVector targets; - GetTargets(targets, e, unit); + WorldObject* invoker = nullptr; + if (unit) + invoker = unit; + else if (gob) + invoker = gob; + + GetTargets(targets, e, invoker); switch (e.GetActionType()) { case SMART_ACTION_TALK: { Creature* talker = e.target.type == 0 ? me : nullptr; - Unit* talkTarget = nullptr; + WorldObject* talkTarget = nullptr; for (WorldObject* target : targets) { @@ -232,7 +240,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u sCreatureTextMgr->SendChat(target->ToCreature(), uint8(e.action.simpleTalk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); else if (IsPlayer(target) && me) { - Unit* templastInvoker = GetLastInvoker(); + WorldObject* templastInvoker = GetLastInvoker(); sCreatureTextMgr->SendChat(me, uint8(e.action.simpleTalk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_NEUTRAL, false, target->ToPlayer()); } @@ -783,7 +791,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_INVOKER_CAST: { // Can be used for area trigger cast - Unit* tempLastInvoker = GetLastInvoker(unit); + WorldObject* tempLastInvoker = GetLastInvoker(unit); if (!tempLastInvoker) break; @@ -798,11 +806,14 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!IsUnit(target)) continue; + if (!IsUnit(tempLastInvoker)) + continue; + if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell)) { if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS) { - tempLastInvoker->InterruptNonMeleeSpells(false); + tempLastInvoker->ToUnit()->InterruptNonMeleeSpells(false); } TriggerCastFlags triggerFlags = TRIGGERED_NONE; @@ -818,7 +829,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } } - tempLastInvoker->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlags); + tempLastInvoker->ToUnit()->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlags); LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker {} casts spell {} on target {} with castflags {}", tempLastInvoker->GetGUID().ToString(), e.action.cast.spell, target->GetGUID().ToString(), e.action.cast.castFlags); } @@ -1397,16 +1408,28 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u 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); + // Make sure we check that the sender is either a creature or gameobject + if (IsSmart(cTarget, true) && (me || go)) + { + if (me) + ENSURE_AI(SmartAI, ai)->SetData(e.action.setData.field, e.action.setData.data, me); + else + ENSURE_AI(SmartAI, ai)->SetData(e.action.setData.field, e.action.setData.data, go); + } 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); + // Make sure we check that the sender is either a creature or gameobject + if (IsSmart(oTarget, true) && (me || go)) + { + if (me) + ENSURE_AI(SmartGameObjectAI, ai)->SetData(e.action.setData.field, e.action.setData.data, me); + else + ENSURE_AI(SmartGameObjectAI, ai)->SetData(e.action.setData.field, e.action.setData.data, go); + } else ai->SetData(e.action.setData.field, e.action.setData.data); } @@ -2900,7 +2923,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.setGuid.invokerGUID) { - if (Unit* invoker = GetLastInvoker()) + if (WorldObject* invoker = GetLastInvoker()) { guidToSend = invoker->GetGUID(); } @@ -3318,12 +3341,12 @@ SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flag return script; } -void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker /*= nullptr*/) const +void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, WorldObject* invoker /*= nullptr*/) const { - Unit* scriptTrigger = nullptr; + WorldObject* scriptTrigger = nullptr; if (invoker) scriptTrigger = invoker; - else if (Unit* tempLastInvoker = GetLastInvoker()) + else if (WorldObject* tempLastInvoker = GetLastInvoker()) scriptTrigger = tempLastInvoker; WorldObject* baseObject = GetBaseObject(); @@ -3399,8 +3422,9 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, targets.push_back(scriptTrigger); break; case SMART_TARGET_ACTION_INVOKER_VEHICLE: - if (scriptTrigger && scriptTrigger->GetVehicle() && scriptTrigger->GetVehicle()->GetBase()) - targets.push_back(scriptTrigger->GetVehicle()->GetBase()); + if (scriptTrigger && IsUnit(scriptTrigger)) + if (scriptTrigger->ToUnit()->GetVehicle() && scriptTrigger->ToUnit()->GetVehicle()->GetBase()) + targets.push_back(scriptTrigger->ToUnit()->GetVehicle()->GetBase()); break; case SMART_TARGET_INVOKER_PARTY: if (scriptTrigger) @@ -4323,7 +4347,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (e.event.dataSet.id != var0 || e.event.dataSet.value != var1) return; RecalcTimer(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax); - ProcessAction(e, unit, var0, var1); + ProcessAction(e, unit, var0, var1, false, nullptr, gob); break; } case SMART_EVENT_PASSENGER_REMOVED: @@ -4352,11 +4376,16 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui case SMART_EVENT_EVENT_PHASE_CHANGE: { if (!IsInPhase(e.event.eventPhaseChange.phasemask)) - { return; - } - ProcessAction(e, GetLastInvoker()); + WorldObject* templastInvoker = GetLastInvoker(); + if (!templastInvoker) + return; + + if (!IsUnit(templastInvoker)) + return; + + ProcessAction(e, templastInvoker->ToUnit()); break; } case SMART_EVENT_GAME_EVENT_START: @@ -5178,14 +5207,14 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry) } } -Unit* SmartScript::GetLastInvoker(Unit* invoker) const +WorldObject* SmartScript::GetLastInvoker(WorldObject* invoker) const { // Xinef: Look for invoker only on map of base object... Prevents multithreaded crashes if (GetBaseObject()) - return ObjectAccessor::GetUnit(*GetBaseObject(), mLastInvoker); + return ObjectAccessor::GetWorldObject(*GetBaseObject(), mLastInvoker); // xinef: used for area triggers invoker cast else if (invoker) - return ObjectAccessor::GetUnit(*invoker, mLastInvoker); + return ObjectAccessor::GetWorldObject(*invoker, mLastInvoker); return nullptr; } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 82ac3700d..0f84cc2fd 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -44,7 +44,7 @@ public: static void InitTimer(SmartScriptHolder& e); void ProcessAction(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); - void GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker = nullptr) const; + void GetTargets(ObjectVector& targets, SmartScriptHolder const& e, WorldObject* invoker = nullptr) const; void GetWorldObjectsInDist(ObjectVector& objects, float dist) const; void InstallTemplate(SmartScriptHolder const& e); static SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, uint32 event_param6, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, uint32 phaseMask); @@ -186,7 +186,7 @@ public: //TIMED_ACTIONLIST (script type 9 aka script9) void SetScript9(SmartScriptHolder& e, uint32 entry); - Unit* GetLastInvoker(Unit* invoker = nullptr) const; + WorldObject* GetLastInvoker(WorldObject* invoker = nullptr) const; ObjectGuid mLastInvoker; typedef std::unordered_map CounterMap; CounterMap mCounterList;