feat(Core/SmartAI): add SMART_ACTION_INC_DATA (242) (#25922)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-05-22 07:58:23 -03:00
committed by GitHub
parent 027306fa0a
commit 2d92b338d7
6 changed files with 48 additions and 2 deletions

View File

@@ -1369,6 +1369,7 @@ void SmartGameObjectAI::UpdateAI(uint32 diff)
void SmartGameObjectAI::InitializeAI()
{
GetScript()->OnInitialize(me);
aiDataSet.clear();
// Xinef: do not call respawn event if go is not spawned
if (me->isSpawned())
@@ -1437,9 +1438,19 @@ void SmartGameObjectAI::SetData(uint32 id, uint32 value, WorldObject* invoker)
gob = invoker->ToGameObject();
}
aiDataSet[id] = value;
GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, unit, id, value, false, nullptr, gob);
}
uint32 SmartGameObjectAI::GetData(uint32 id) const
{
std::unordered_map<uint32, uint32>::const_iterator itr = aiDataSet.find(id);
if (itr != aiDataSet.end())
return itr->second;
return 0;
}
void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker)
{
if (invoker)

View File

@@ -304,6 +304,7 @@ public:
void Destroyed(Player* player, uint32 eventId) override;
void SetData(uint32 id, uint32 value) override { SetData(id, value, nullptr); }
void SetData(uint32 id, uint32 value, WorldObject* invoker);
uint32 GetData(uint32 id) const override;
void SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker);
void OnGameEvent(bool start, uint16 eventId) override;
void OnStateChanged(uint32 state, Unit* unit) override;
@@ -324,6 +325,7 @@ public:
protected:
SmartScript mScript;
std::unordered_map<uint32, uint32> aiDataSet;
};
/// Registers scripts required by the SAI scripting system

View File

@@ -1463,6 +1463,35 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
break;
}
case SMART_ACTION_INC_DATA:
{
WorldObject* invoker = me ? static_cast<WorldObject*>(me) : static_cast<WorldObject*>(go);
for (WorldObject* target : targets)
{
if (Creature* cTarget = target->ToCreature())
{
if (SmartAI* smartAI = CAST_AI(SmartAI, cTarget->AI()))
{
uint32 const newValue = smartAI->GetData(e.action.setData.field) + e.action.setData.data;
smartAI->SetData(e.action.setData.field, newValue, invoker);
}
else
LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_INC_DATA is not using SmartAI, skipping");
}
else if (GameObject* oTarget = target->ToGameObject())
{
if (SmartGameObjectAI* smartGOAI = CAST_AI(SmartGameObjectAI, oTarget->AI()))
{
uint32 const newValue = smartGOAI->GetData(e.action.setData.field) + e.action.setData.data;
smartGOAI->SetData(e.action.setData.field, newValue, invoker);
}
else
LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_INC_DATA is not using SmartGameObjectAI, skipping");
}
}
break;
}
case SMART_ACTION_MOVE_FORWARD:
{
if (!me)

View File

@@ -759,6 +759,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL: return sizeof(SmartAction::morphOrMount);
case SMART_ACTION_SET_INGAME_PHASE_MASK: return sizeof(SmartAction::ingamePhaseMask);
case SMART_ACTION_SET_DATA: return sizeof(SmartAction::setData);
case SMART_ACTION_INC_DATA: return sizeof(SmartAction::setData);
case SMART_ACTION_MOVE_FORWARD: return sizeof(SmartAction::moveRandom);
case SMART_ACTION_ATTACK_STOP: return NO_PARAMS;
case SMART_ACTION_SET_VISIBILITY: return sizeof(SmartAction::visibility);
@@ -1975,6 +1976,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_THREAT_SINGLE_PCT:
case SMART_ACTION_SET_INST_DATA64:
case SMART_ACTION_SET_DATA:
case SMART_ACTION_INC_DATA:
case SMART_ACTION_MOVE_FORWARD:
case SMART_ACTION_ESCORT_PAUSE:
case SMART_ACTION_SET_FLY:

View File

@@ -726,8 +726,9 @@ enum SMART_ACTION
SMART_ACTION_SET_ANIM_TIER = 239, // animtier
SMART_ACTION_SET_GOSSIP_MENU = 240, // gossipMenuId
SMART_ACTION_SUMMON_GAMEOBJECT_GROUP = 241, // group
SMART_ACTION_INC_DATA = 242, // field, increment (uses aiDataSet, wipe-safe across evade)
SMART_ACTION_AC_END = 242, // placeholder
SMART_ACTION_AC_END = 243, // placeholder
};
enum class SmartActionSummonCreatureFlags

View File

@@ -110,7 +110,8 @@ TEST_F(GameObjectSummonGroupTest, DifferentGroupsAreIndependent)
TEST_F(GameObjectSummonGroupTest, SmartActionEnumValue)
{
EXPECT_EQ(SMART_ACTION_SUMMON_GAMEOBJECT_GROUP, 241);
EXPECT_EQ(SMART_ACTION_AC_END, 242);
EXPECT_EQ(SMART_ACTION_INC_DATA, 242);
EXPECT_EQ(SMART_ACTION_AC_END, 243);
}
TEST_F(GameObjectSummonGroupTest, SmartActionUnionSize)