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:
@@ -1369,6 +1369,7 @@ void SmartGameObjectAI::UpdateAI(uint32 diff)
|
|||||||
void SmartGameObjectAI::InitializeAI()
|
void SmartGameObjectAI::InitializeAI()
|
||||||
{
|
{
|
||||||
GetScript()->OnInitialize(me);
|
GetScript()->OnInitialize(me);
|
||||||
|
aiDataSet.clear();
|
||||||
|
|
||||||
// Xinef: do not call respawn event if go is not spawned
|
// Xinef: do not call respawn event if go is not spawned
|
||||||
if (me->isSpawned())
|
if (me->isSpawned())
|
||||||
@@ -1437,9 +1438,19 @@ void SmartGameObjectAI::SetData(uint32 id, uint32 value, WorldObject* invoker)
|
|||||||
gob = invoker->ToGameObject();
|
gob = invoker->ToGameObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aiDataSet[id] = value;
|
||||||
GetScript()->ProcessEventsFor(SMART_EVENT_DATA_SET, unit, id, value, false, nullptr, gob);
|
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)
|
void SmartGameObjectAI::SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker)
|
||||||
{
|
{
|
||||||
if (invoker)
|
if (invoker)
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ public:
|
|||||||
void Destroyed(Player* player, uint32 eventId) 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) override { SetData(id, value, nullptr); }
|
||||||
void SetData(uint32 id, uint32 value, WorldObject* invoker);
|
void SetData(uint32 id, uint32 value, WorldObject* invoker);
|
||||||
|
uint32 GetData(uint32 id) const override;
|
||||||
void SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker);
|
void SetScript9(SmartScriptHolder& e, uint32 entry, WorldObject* invoker);
|
||||||
void OnGameEvent(bool start, uint16 eventId) override;
|
void OnGameEvent(bool start, uint16 eventId) override;
|
||||||
void OnStateChanged(uint32 state, Unit* unit) override;
|
void OnStateChanged(uint32 state, Unit* unit) override;
|
||||||
@@ -324,6 +325,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
SmartScript mScript;
|
SmartScript mScript;
|
||||||
|
std::unordered_map<uint32, uint32> aiDataSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Registers scripts required by the SAI scripting system
|
/// Registers scripts required by the SAI scripting system
|
||||||
|
|||||||
@@ -1463,6 +1463,35 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case SMART_ACTION_MOVE_FORWARD:
|
||||||
{
|
{
|
||||||
if (!me)
|
if (!me)
|
||||||
|
|||||||
@@ -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_MOUNT_TO_ENTRY_OR_MODEL: return sizeof(SmartAction::morphOrMount);
|
||||||
case SMART_ACTION_SET_INGAME_PHASE_MASK: return sizeof(SmartAction::ingamePhaseMask);
|
case SMART_ACTION_SET_INGAME_PHASE_MASK: return sizeof(SmartAction::ingamePhaseMask);
|
||||||
case SMART_ACTION_SET_DATA: return sizeof(SmartAction::setData);
|
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_MOVE_FORWARD: return sizeof(SmartAction::moveRandom);
|
||||||
case SMART_ACTION_ATTACK_STOP: return NO_PARAMS;
|
case SMART_ACTION_ATTACK_STOP: return NO_PARAMS;
|
||||||
case SMART_ACTION_SET_VISIBILITY: return sizeof(SmartAction::visibility);
|
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_THREAT_SINGLE_PCT:
|
||||||
case SMART_ACTION_SET_INST_DATA64:
|
case SMART_ACTION_SET_INST_DATA64:
|
||||||
case SMART_ACTION_SET_DATA:
|
case SMART_ACTION_SET_DATA:
|
||||||
|
case SMART_ACTION_INC_DATA:
|
||||||
case SMART_ACTION_MOVE_FORWARD:
|
case SMART_ACTION_MOVE_FORWARD:
|
||||||
case SMART_ACTION_ESCORT_PAUSE:
|
case SMART_ACTION_ESCORT_PAUSE:
|
||||||
case SMART_ACTION_SET_FLY:
|
case SMART_ACTION_SET_FLY:
|
||||||
|
|||||||
@@ -726,8 +726,9 @@ enum SMART_ACTION
|
|||||||
SMART_ACTION_SET_ANIM_TIER = 239, // animtier
|
SMART_ACTION_SET_ANIM_TIER = 239, // animtier
|
||||||
SMART_ACTION_SET_GOSSIP_MENU = 240, // gossipMenuId
|
SMART_ACTION_SET_GOSSIP_MENU = 240, // gossipMenuId
|
||||||
SMART_ACTION_SUMMON_GAMEOBJECT_GROUP = 241, // group
|
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
|
enum class SmartActionSummonCreatureFlags
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ TEST_F(GameObjectSummonGroupTest, DifferentGroupsAreIndependent)
|
|||||||
TEST_F(GameObjectSummonGroupTest, SmartActionEnumValue)
|
TEST_F(GameObjectSummonGroupTest, SmartActionEnumValue)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(SMART_ACTION_SUMMON_GAMEOBJECT_GROUP, 241);
|
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)
|
TEST_F(GameObjectSummonGroupTest, SmartActionUnionSize)
|
||||||
|
|||||||
Reference in New Issue
Block a user