fix(Core/SmartAI) : use explicit stack DS for ProcessAction instead of recursion (#16739)

* Use dequeue instead of recursion

* Remove to do comments

* Fix formatting

* Fix more formatting :(

* Use references instead of copies in the stack to correctly update event state

* formatting

* Revert FindLinkedEvent parameter name change and check for event type

* Fix event processing in SmartScript::UpdateTimer

* Use struct for defining SmartScriptFrame instead of tuple

* Fix emplace_back not working on default constructor on clang 15

* Fix const placement
This commit is contained in:
Dan Costinas
2024-10-22 18:31:45 +03:00
committed by GitHub
parent bb40bf7727
commit 87aeaf10fd
2 changed files with 39 additions and 9 deletions
@@ -145,7 +145,16 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject(), me ? me->GetVictim() : nullptr); ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject(), me ? me->GetVictim() : nullptr);
if (sConditionMgr->IsObjectMeetToConditions(info, conds)) if (sConditionMgr->IsObjectMeetToConditions(info, conds))
ProcessEvent(*i, unit, var0, var1, bvar, spell, gob); {
ASSERT(executionStack.empty());
executionStack.emplace_back(SmartScriptFrame{ *i, unit, var0, var1, bvar, spell, gob });
while (!executionStack.empty())
{
auto [stack_holder , stack_unit, stack_var0, stack_var1, stack_bvar, stack_spell, stack_gob] = executionStack.back();
executionStack.pop_back();
ProcessEvent(stack_holder, stack_unit, stack_var0, stack_var1, stack_bvar, stack_spell, stack_gob);
}
}
} }
} }
} }
@@ -3255,9 +3264,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.link && e.link != e.event_id) if (e.link && e.link != e.event_id)
{ {
SmartScriptHolder linked = FindLinkedEvent(e.link); auto linked = FindLinkedEvent(e.link);
if (linked.GetActionType() && linked.GetEventType() == SMART_EVENT_LINK) if (linked.has_value() && linked.value().get().GetEventType() == SMART_EVENT_LINK)
ProcessEvent(linked, unit, var0, var1, bvar, spell, gob); executionStack.emplace_back(SmartScriptFrame{ linked.value(), unit, var0, var1, bvar, spell, gob });
else else
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Link Event {} not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Link Event {} not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link);
} }
@@ -4852,7 +4861,14 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
case SMART_EVENT_DISTANCE_CREATURE: case SMART_EVENT_DISTANCE_CREATURE:
case SMART_EVENT_DISTANCE_GAMEOBJECT: case SMART_EVENT_DISTANCE_GAMEOBJECT:
{ {
ProcessEvent(e); ASSERT(executionStack.empty());
executionStack.emplace_back(SmartScriptFrame{ e, nullptr, 0, 0, false, nullptr, nullptr });
while (!executionStack.empty())
{
auto [stack_holder, stack_unit, stack_var0, stack_var1, stack_bvar, stack_spell, stack_gob] = executionStack.back();
executionStack.pop_back();
ProcessEvent(stack_holder, stack_unit, stack_var0, stack_var1, stack_bvar, stack_spell, stack_gob);
}
if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST) if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
{ {
e.enableTimed = false;//disable event if it is in an ActionList and was processed once e.enableTimed = false;//disable event if it is in an ActionList and was processed once
+18 -4
View File
@@ -25,9 +25,21 @@
#include "SmartScriptMgr.h" #include "SmartScriptMgr.h"
#include "Spell.h" #include "Spell.h"
#include "Unit.h" #include "Unit.h"
#include <deque>
class SmartScript class SmartScript
{ {
struct SmartScriptFrame
{
SmartScriptHolder& holder;
Unit* unit;
uint32 var0;
uint32 var1;
bool bvar;
SpellInfo const* spell;
GameObject* gob;
};
public: public:
SmartScript(); SmartScript();
~SmartScript(); ~SmartScript();
@@ -253,7 +265,8 @@ private:
} }
} }
} }
SmartScriptHolder FindLinkedEvent (uint32 link) std::optional<std::reference_wrapper<
SmartScriptHolder>> FindLinkedEvent(uint32 link)
{ {
if (!mEvents.empty()) if (!mEvents.empty())
{ {
@@ -261,15 +274,16 @@ private:
{ {
if (i->event_id == link) if (i->event_id == link)
{ {
return (*i); return std::ref(*i);
} }
} }
} }
SmartScriptHolder s; return std::nullopt;
return s;
} }
GuidUnorderedSet _summonList; GuidUnorderedSet _summonList;
std::deque<SmartScriptFrame> executionStack;
}; };
#endif #endif