aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMeji <alvaro.megias@outlook.com>2024-04-11 10:15:46 +0200
committerGitHub <noreply@github.com>2024-04-11 10:15:46 +0200
commit2ce40684595a0e49a7b2355012c2806952698ce4 (patch)
tree17cbb8202856fdb2e5c27ed596ce9daea9044fb3
parentbec5bdb61b1b78ae7f750019b9a187b489ebb496 (diff)
Core/SAI: Added support for StringIds to creature and gameobject targets (#29910)
Co-authored-by: Shauren <shauren.trinity@gmail.com>
-rw-r--r--sql/updates/world/master/2024_04_11_00_world.sql3
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp148
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h3
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp90
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h21
6 files changed, 158 insertions, 109 deletions
diff --git a/sql/updates/world/master/2024_04_11_00_world.sql b/sql/updates/world/master/2024_04_11_00_world.sql
new file mode 100644
index 00000000000..74ce05c2e0b
--- /dev/null
+++ b/sql/updates/world/master/2024_04_11_00_world.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `smart_scripts`
+ ADD `action_param_string` VARCHAR(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL AFTER `action_param7`,
+ ADD `target_param_string` VARCHAR(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL AFTER `target_param4`;
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index 9827b442464..9ddb30f8a8c 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -27,7 +27,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_LINKED_RESPAWN_MASTER, "DELETE FROM linked_respawn WHERE linkedGuid = ? AND linkType = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_REP_LINKED_RESPAWN, "REPLACE INTO linked_respawn (guid, linkedGuid, linkType) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_CREATURE_TEXT, "SELECT CreatureID, GroupID, ID, Text, Type, Language, Probability, Emote, Duration, Sound, SoundPlayType, BroadcastTextId, TextRange FROM creature_text", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, Difficulties, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, event_param5, event_param_string, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, action_param7, target_type, target_param1, target_param2, target_param3, target_param4, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, Difficulties, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, event_param5, event_param_string, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, action_param7, action_param_string, target_type, target_param1, target_param2, target_param3, target_param4, target_param_string, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_EVENT_GAMEOBJECT, "DELETE FROM game_event_gameobject WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_GRAVEYARD_ZONE, "INSERT INTO graveyard_zone (ID, GhostZone) VALUES (?, ?)", CONNECTION_ASYNC);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 63e9b123b96..3ae063fc57e 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1656,7 +1656,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
ObjectVector casters;
- GetTargets(casters, CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.crossCast.targetType, e.action.crossCast.targetParam1, e.action.crossCast.targetParam2, e.action.crossCast.targetParam3, 0, 0), unit);
+ GetTargets(casters, CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.crossCast.targetType, e.action.crossCast.targetParam1, e.action.crossCast.targetParam2, e.action.crossCast.targetParam3, e.action.crossCast.targetParam4, e.action.param_string, 0), unit);
CastSpellExtraArgs args;
if (e.action.crossCast.castFlags & SMARTCAST_TRIGGERED)
@@ -2537,7 +2537,7 @@ void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, ui
RecalcTimer(e, std::min<uint32>(min, 5000), std::min<uint32>(min, 5000));
}
-SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, uint32 action_param7, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, uint32 phaseMask)
+SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, uint32 action_param7, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, std::string_view targetParamString, uint32 phaseMask)
{
SmartScriptHolder script;
script.event.type = e;
@@ -2564,6 +2564,7 @@ SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flag
script.target.raw.param2 = target_param2;
script.target.raw.param3 = target_param3;
script.target.raw.param4 = target_param4;
+ script.target.param_string = targetParamString;
script.source_type = SMART_SCRIPT_TYPE_CREATURE;
InitTimer(script);
@@ -2686,20 +2687,13 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
break;
}
- ObjectVector units;
- GetWorldObjectsInDist(units, static_cast<float>(e.target.unitRange.maxDist));
-
- for (WorldObject* unit : units)
- {
- if (!IsCreature(unit))
- continue;
-
- if (me && me->GetGUID() == unit->GetGUID())
- continue;
+ std::vector<Creature*> creatures;
+ ref->GetCreatureListWithOptionsInGrid(creatures, static_cast<float>(e.target.unitRange.maxDist), {
+ .CreatureId = e.target.unitRange.creature ? Optional<uint32>(e.target.unitRange.creature) : Optional<uint32>(),
+ .StringId = !e.target.param_string.empty() ? Optional<std::string_view>(e.target.param_string) : Optional<std::string_view>(),
+ });
- if ((!e.target.unitRange.creature || unit->ToCreature()->GetEntry() == e.target.unitRange.creature) && ref->IsInRange(unit, float(e.target.unitRange.minDist), float(e.target.unitRange.maxDist)))
- targets.push_back(unit);
- }
+ std::ranges::copy_if(creatures, std::back_inserter(targets), [&](Creature const* target) { return !ref->IsWithinDist(target, static_cast<float>(e.target.unitRange.minDist)); });
if (e.target.unitRange.maxSize)
Trinity::Containers::RandomResize(targets, e.target.unitRange.maxSize);
@@ -2707,46 +2701,21 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
}
case SMART_TARGET_CREATURE_DISTANCE:
{
- ObjectVector units;
- GetWorldObjectsInDist(units, static_cast<float>(e.target.unitDistance.dist));
-
- for (WorldObject* unit : units)
- {
- if (!IsCreature(unit))
- continue;
+ if (!baseObject)
+ break;
- if (me && me->GetGUID() == unit->GetGUID())
- continue;
+ std::vector<Creature*> creatures;
+ baseObject->GetCreatureListWithOptionsInGrid(creatures, static_cast<float>(e.target.unitDistance.dist), {
+ .CreatureId = e.target.unitDistance.creature ? Optional<uint32>(e.target.unitDistance.creature) : Optional<uint32>(),
+ .StringId = !e.target.param_string.empty() ? Optional<std::string_view>(e.target.param_string) : Optional<std::string_view>(),
+ });
- if (!e.target.unitDistance.creature || unit->ToCreature()->GetEntry() == e.target.unitDistance.creature)
- targets.push_back(unit);
- }
+ targets = { creatures.begin(), creatures.end() };
if (e.target.unitDistance.maxSize)
Trinity::Containers::RandomResize(targets, e.target.unitDistance.maxSize);
break;
}
- case SMART_TARGET_GAMEOBJECT_DISTANCE:
- {
- ObjectVector units;
- GetWorldObjectsInDist(units, static_cast<float>(e.target.goDistance.dist));
-
- for (WorldObject* unit : units)
- {
- if (!IsGameObject(unit))
- continue;
-
- if (go && go->GetGUID() == unit->GetGUID())
- continue;
-
- if (!e.target.goDistance.entry || unit->ToGameObject()->GetEntry() == e.target.goDistance.entry)
- targets.push_back(unit);
- }
-
- if (e.target.goDistance.maxSize)
- Trinity::Containers::RandomResize(targets, e.target.goDistance.maxSize);
- break;
- }
case SMART_TARGET_GAMEOBJECT_RANGE:
{
WorldObject* ref = baseObject;
@@ -2760,25 +2729,35 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
break;
}
- ObjectVector units;
- GetWorldObjectsInDist(units, static_cast<float>(e.target.goRange.maxDist));
+ std::vector<GameObject*> gameObjects;
+ ref->GetGameObjectListWithOptionsInGrid(gameObjects, static_cast<float>(e.target.goRange.maxDist), {
+ .GameObjectId = e.target.goRange.entry ? Optional<uint32>(e.target.goRange.entry) : Optional<uint32>(),
+ .StringId = !e.target.param_string.empty() ? Optional<std::string_view>(e.target.param_string) : Optional<std::string_view>(),
+ });
- for (WorldObject* unit : units)
- {
- if (!IsGameObject(unit))
- continue;
-
- if (go && go->GetGUID() == unit->GetGUID())
- continue;
-
- if ((!e.target.goRange.entry || unit->ToGameObject()->GetEntry() == e.target.goRange.entry) && ref->IsInRange(unit, float(e.target.goRange.minDist), float(e.target.goRange.maxDist)))
- targets.push_back(unit);
- }
+ std::ranges::copy_if(gameObjects, std::back_inserter(targets), [&](GameObject const* target) { return !ref->IsWithinDist(target, static_cast<float>(e.target.goRange.minDist)); });
if (e.target.goRange.maxSize)
Trinity::Containers::RandomResize(targets, e.target.goRange.maxSize);
break;
}
+ case SMART_TARGET_GAMEOBJECT_DISTANCE:
+ {
+ if (!baseObject)
+ break;
+
+ std::vector<GameObject*> gameObjects;
+ baseObject->GetGameObjectListWithOptionsInGrid(gameObjects, static_cast<float>(e.target.goDistance.dist), {
+ .GameObjectId = e.target.goDistance.entry ? Optional<uint32>(e.target.goDistance.entry) : Optional<uint32>(),
+ .StringId = !e.target.param_string.empty() ? Optional<std::string_view>(e.target.param_string) : Optional<std::string_view>(),
+ });
+
+ targets = { gameObjects.begin(), gameObjects.end() };
+
+ if (e.target.goDistance.maxSize)
+ Trinity::Containers::RandomResize(targets, e.target.goDistance.maxSize);
+ break;
+ }
case SMART_TARGET_CREATURE_GUID:
{
if (!scriptTrigger && !baseObject)
@@ -2809,23 +2788,22 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
}
case SMART_TARGET_PLAYER_RANGE:
{
- ObjectVector units;
- GetWorldObjectsInDist(units, static_cast<float>(e.target.playerRange.maxDist));
+ if (!baseObject)
+ break;
- if (!units.empty() && baseObject)
- for (WorldObject* unit : units)
- if (IsPlayer(unit) && baseObject->IsInRange(unit, float(e.target.playerRange.minDist), float(e.target.playerRange.maxDist)))
- targets.push_back(unit);
+ std::vector<Player*> players;
+ baseObject->GetPlayerListInGrid(players, static_cast<float>(e.target.playerRange.maxDist));
+ std::ranges::copy_if(players, std::back_inserter(targets), [&](Player const* target) { return !baseObject->IsWithinDist(target, static_cast<float>(e.target.playerRange.minDist)); });
break;
}
case SMART_TARGET_PLAYER_DISTANCE:
{
- ObjectVector units;
- GetWorldObjectsInDist(units, static_cast<float>(e.target.playerDistance.dist));
+ if (!baseObject)
+ break;
- for (WorldObject* unit : units)
- if (IsPlayer(unit))
- targets.push_back(unit);
+ std::vector<Player*> players;
+ baseObject->GetPlayerListInGrid(players, static_cast<float>(e.target.playerDistance.dist));
+ targets = { players.begin(), players.end() };
break;
}
case SMART_TARGET_STORED:
@@ -2858,7 +2836,13 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
break;
}
- if (Creature* target = ref->FindNearestCreature(e.target.unitClosest.entry, float(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead))
+ Creature* target = ref->FindNearestCreatureWithOptions(float(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), {
+ .CreatureId = e.target.unitClosest.entry,
+ .StringId = !e.target.param_string.empty() ? Optional<std::string_view>(e.target.param_string) : Optional<std::string_view>(),
+ .IsAlive = !e.target.unitClosest.dead
+ });
+
+ if (target)
targets.push_back(target);
break;
}
@@ -2875,7 +2859,12 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
break;
}
- if (GameObject* target = ref->FindNearestGameObject(e.target.goClosest.entry, float(e.target.goClosest.dist ? e.target.goClosest.dist : 100)))
+ GameObject* target = ref->FindNearestGameObjectWithOptions(float(e.target.goClosest.dist ? e.target.goClosest.dist : 100), {
+ .GameObjectId = e.target.goClosest.entry,
+ .StringId = !e.target.param_string.empty() ? Optional<std::string_view>(e.target.param_string) : Optional<std::string_view>()
+ });
+
+ if (target)
targets.push_back(target);
break;
}
@@ -2983,17 +2972,6 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
}
}
-void SmartScript::GetWorldObjectsInDist(ObjectVector& targets, float dist) const
-{
- WorldObject* obj = GetBaseObject();
- if (!obj)
- return;
-
- Trinity::AllWorldObjectsInRange u_check(obj, dist);
- Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(obj, targets, u_check);
- Cell::VisitAllObjects(obj, searcher, dist);
-}
-
void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob, std::string const& varString)
{
if (!e.active && e.GetEventType() != SMART_EVENT_LINK)
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index 6e3068e5f38..3f5e11de9c5 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -51,8 +51,7 @@ class TC_GAME_API SmartScript
void ProcessAction(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
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, std::string const& varString = "");
void GetTargets(ObjectVector& targets, SmartScriptHolder const& e, WorldObject* invoker = nullptr) const;
- void GetWorldObjectsInDist(ObjectVector& objects, float dist) const;
- static SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, uint32 action_param7, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, uint32 phaseMask);
+ static SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, uint32 action_param7, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 target_param4, std::string_view targetParamString, uint32 phaseMask);
void SetPathId(uint32 id) { mPathId = id; }
uint32 GetPathId() const { return mPathId; }
WorldObject* GetBaseObject() const;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index a5e63f5ef22..4b368626203 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -298,16 +298,18 @@ void SmartAIMgr::LoadSmartAIFromDB()
temp.action.raw.param5 = fields[20].GetUInt32();
temp.action.raw.param6 = fields[21].GetUInt32();
temp.action.raw.param7 = fields[22].GetUInt32();
-
- temp.target.type = (SMARTAI_TARGETS)fields[23].GetUInt8();
- temp.target.raw.param1 = fields[24].GetUInt32();
- temp.target.raw.param2 = fields[25].GetUInt32();
- temp.target.raw.param3 = fields[26].GetUInt32();
- temp.target.raw.param4 = fields[27].GetUInt32();
- temp.target.x = fields[28].GetFloat();
- temp.target.y = fields[29].GetFloat();
- temp.target.z = fields[30].GetFloat();
- temp.target.o = fields[31].GetFloat();
+ temp.action.param_string = fields[23].GetString();
+
+ temp.target.type = (SMARTAI_TARGETS)fields[24].GetUInt8();
+ temp.target.raw.param1 = fields[25].GetUInt32();
+ temp.target.raw.param2 = fields[26].GetUInt32();
+ temp.target.raw.param3 = fields[27].GetUInt32();
+ temp.target.raw.param4 = fields[28].GetUInt32();
+ temp.target.param_string = fields[29].GetString();
+ temp.target.x = fields[30].GetFloat();
+ temp.target.y = fields[31].GetFloat();
+ temp.target.z = fields[32].GetFloat();
+ temp.target.o = fields[33].GetFloat();
//check target
if (!IsTargetValid(temp))
@@ -851,7 +853,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
}
}();
- static size_t rawCount = sizeof(SmartEvent::raw) / sizeof(uint32);
+ constexpr size_t rawCount = sizeof(SmartEvent::raw) / sizeof(uint32);
size_t paramsCount = paramsStructSize / sizeof(uint32);
for (size_t index = paramsCount; index < rawCount; index++)
@@ -864,6 +866,25 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
}
}
+ bool eventUsesStringParam = [&]
+ {
+ switch (e.GetEventType())
+ {
+ case SMART_EVENT_SCENE_TRIGGER:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }();
+
+ if (!eventUsesStringParam && !e.event.param_string.empty())
+ {
+ TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has unused event_param_string with value {}, it should be NULL.",
+ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.param_string);
+ }
+
return true;
}
@@ -1014,7 +1035,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
}
}();
- static size_t rawCount = sizeof(SmartAction::raw) / sizeof(uint32);
+ constexpr size_t rawCount = sizeof(SmartAction::raw) / sizeof(uint32);
size_t paramsCount = paramsStructSize / sizeof(uint32);
for (size_t index = paramsCount; index < rawCount; index++)
@@ -1027,6 +1048,25 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
}
}
+ bool actionUsesStringParam = [&]
+ {
+ switch (e.GetActionType())
+ {
+ case SMART_ACTION_CROSS_CAST:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }();
+
+ if (!actionUsesStringParam && !e.action.param_string.empty())
+ {
+ TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has unused action_param_string with value {}, it should be NULL.",
+ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.param_string);
+ }
+
return true;
}
@@ -1075,7 +1115,7 @@ bool SmartAIMgr::CheckUnusedTargetParams(SmartScriptHolder const& e)
}
}();
- static size_t rawCount = sizeof(SmartTarget::raw) / sizeof(uint32);
+ constexpr size_t rawCount = sizeof(SmartTarget::raw) / sizeof(uint32);
size_t paramsCount = paramsStructSize / sizeof(uint32);
for (size_t index = paramsCount; index < rawCount; index++)
@@ -1088,6 +1128,30 @@ bool SmartAIMgr::CheckUnusedTargetParams(SmartScriptHolder const& e)
}
}
+ bool targetUsesStringParam = [&]
+ {
+ switch (e.GetTargetType())
+ {
+ case SMART_TARGET_CREATURE_RANGE:
+ case SMART_TARGET_CREATURE_DISTANCE:
+ case SMART_TARGET_GAMEOBJECT_RANGE:
+ case SMART_TARGET_GAMEOBJECT_DISTANCE:
+ case SMART_TARGET_CLOSEST_CREATURE:
+ case SMART_TARGET_CLOSEST_GAMEOBJECT:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }();
+
+ if (!targetUsesStringParam && !e.target.param_string.empty())
+ {
+ TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has unused target_param_string with value {}, it should be NULL.",
+ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.target.param_string);
+ }
+
return true;
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 6108bc3144b..ff1ccf5e4a9 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -34,7 +34,7 @@ typedef uint32 SAIBool;
enum eSmartAI
{
- SMART_EVENT_PARAM_COUNT = 4,
+ SMART_EVENT_PARAM_COUNT = 5,
SMART_ACTION_PARAM_COUNT = 7,
SMART_SUMMON_COUNTER = 0xFFFFFF,
SMART_ESCORT_LAST_OOC_POINT = 0xFFFFFF,
@@ -543,7 +543,7 @@ enum SMART_ACTION
SMART_ACTION_REMOVE_NPC_FLAG = 83, // Flags
SMART_ACTION_SIMPLE_TALK = 84, // groupID, can be used to make players say groupID, Text_over event is not triggered, whisper can not be used (Target units will say the text)
SMART_ACTION_SELF_CAST = 85, // spellID, castFlags
- SMART_ACTION_CROSS_CAST = 86, // spellID, castFlags, CasterTargetType, CasterTarget param1, CasterTarget param2, CasterTarget param3, ( + the origonal target fields as Destination target), CasterTargets will cast spellID on all Targets (use with caution if targeting multiple * multiple units)
+ SMART_ACTION_CROSS_CAST = 86, // spellID, castFlags, CasterTargetType, CasterTarget param1, CasterTarget param2, CasterTarget param3, CasterTarget param4, CasterTarget ParamString ( + the original target fields as Destination target), CasterTargets will cast spellID on all Targets (use with caution if targeting multiple * multiple units)
SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST = 87, // script9 ids 1-9
SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST = 88, // script9 id min, max
SMART_ACTION_RANDOM_MOVE = 89, // maxDist
@@ -703,6 +703,7 @@ struct SmartAction
uint32 targetParam1;
uint32 targetParam2;
uint32 targetParam3;
+ uint32 targetParam4;
} crossCast;
struct
@@ -1257,6 +1258,8 @@ struct SmartAction
uint32 param7;
} raw;
};
+
+ std::string param_string;
};
enum SMARTAI_SPAWN_FLAGS
@@ -1278,18 +1281,18 @@ enum SMARTAI_TARGETS
SMART_TARGET_HOSTILE_RANDOM_NOT_TOP = 6, // Any random target except top threat, maxdist, playerOnly, powerType + 1
SMART_TARGET_ACTION_INVOKER = 7, // Unit who caused this Event to occur
SMART_TARGET_POSITION = 8, // use xyz from event params
- SMART_TARGET_CREATURE_RANGE = 9, // CreatureEntry(0any), minDist, maxDist
+ SMART_TARGET_CREATURE_RANGE = 9, // CreatureEntry(0any), minDist, maxDist, maxSize, StringId
SMART_TARGET_CREATURE_GUID = 10, // guid, entry
- SMART_TARGET_CREATURE_DISTANCE = 11, // CreatureEntry(0any), maxDist
+ SMART_TARGET_CREATURE_DISTANCE = 11, // CreatureEntry(0any), maxDist, maxSize, StringId
SMART_TARGET_STORED = 12, // id, uses pre-stored target(list)
- SMART_TARGET_GAMEOBJECT_RANGE = 13, // entry(0any), min, max
+ SMART_TARGET_GAMEOBJECT_RANGE = 13, // entry(0any), minDist, maxDist, StringId
SMART_TARGET_GAMEOBJECT_GUID = 14, // guid, entry
- SMART_TARGET_GAMEOBJECT_DISTANCE = 15, // entry(0any), maxDist
+ SMART_TARGET_GAMEOBJECT_DISTANCE = 15, // entry(0any), maxDist, StringId
SMART_TARGET_INVOKER_PARTY = 16, // invoker's party members
SMART_TARGET_PLAYER_RANGE = 17, // min, max
SMART_TARGET_PLAYER_DISTANCE = 18, // maxDist
- SMART_TARGET_CLOSEST_CREATURE = 19, // CreatureEntry(0any), maxDist, dead?
- SMART_TARGET_CLOSEST_GAMEOBJECT = 20, // entry(0any), maxDist
+ SMART_TARGET_CLOSEST_CREATURE = 19, // CreatureEntry(0any), maxDist, dead?, StringId
+ SMART_TARGET_CLOSEST_GAMEOBJECT = 20, // entry(0any), maxDist, StringId
SMART_TARGET_CLOSEST_PLAYER = 21, // maxDist
SMART_TARGET_ACTION_INVOKER_VEHICLE = 22, // Unit's vehicle who caused this Event to occur
SMART_TARGET_OWNER_OR_SUMMONER = 23, // Unit's owner or summoner, Use Owner/Charmer of this unit
@@ -1442,6 +1445,8 @@ struct SmartTarget
uint32 param4;
} raw;
};
+
+ std::string param_string;
};
enum SmartScriptType