mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-18 14:10:18 -04:00
Core/SAI: Spell casts that cannot be executed because the unit is currently casting another spell will be retried asap with priority over other events (#25238)
* Core/SAI: Spell casts that cannot be executed because the unit is currently casting another spell will be retried asap with priority over other events
* Core/SAI: Re-sort the events only when needed
* Fix some priority reset and wrong mEventSortingRequired handling
* Code cleanup.
Sort only events loaded from db (not stored events, not timed action list).
* Code cleanup.
Raise priority of failed casts so they are retried before other spells
* Keep priority of the action fails and is rescheduled on next update
* Don't try recasting a spell in SMART_ACTION_CAST if there are multiple targets and at least 1 was successful
(cherry picked from commit ca25e8d019)
This commit is contained in:
@@ -61,6 +61,8 @@ SmartScript::SmartScript()
|
||||
mTemplate = SMARTAI_TEMPLATE_BASIC;
|
||||
mScriptType = SMART_SCRIPT_TYPE_CREATURE;
|
||||
isProcessingTimedActionList = false;
|
||||
mCurrentPriority = 0;
|
||||
mEventSortingRequired = false;
|
||||
}
|
||||
|
||||
SmartScript::~SmartScript()
|
||||
@@ -186,6 +188,12 @@ void SmartScript::OnReset()
|
||||
InitTimer(event);
|
||||
event.runOnce = false;
|
||||
}
|
||||
|
||||
if (event.priority != SmartScriptHolder::DEFAULT_PRIORITY)
|
||||
{
|
||||
event.priority = SmartScriptHolder::DEFAULT_PRIORITY;
|
||||
mEventSortingRequired = true;
|
||||
}
|
||||
}
|
||||
ProcessEventsFor(SMART_EVENT_RESET);
|
||||
mLastInvoker.Clear();
|
||||
@@ -541,6 +549,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (e.action.cast.targetsLimit > 0 && targets.size() > e.action.cast.targetsLimit)
|
||||
Trinity::Containers::RandomResize(targets, e.action.cast.targetsLimit);
|
||||
|
||||
bool failedSpellCast = false, successfulSpellCast = false;
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
// may be nullptr
|
||||
@@ -576,7 +586,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
|
||||
if (spellCastFailed)
|
||||
RecalcTimer(e, 500, 500);
|
||||
failedSpellCast = true;
|
||||
else
|
||||
successfulSpellCast = true;
|
||||
}
|
||||
else if (go)
|
||||
go->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlag);
|
||||
@@ -587,6 +599,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
else
|
||||
TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, target->GetGUID().ToString().c_str());
|
||||
}
|
||||
|
||||
// If there is at least 1 failed cast and no successful casts at all, retry again on next loop
|
||||
if (failedSpellCast && !successfulSpellCast)
|
||||
RaisePriority(e);
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SELF_CAST:
|
||||
@@ -3754,7 +3770,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
{
|
||||
if (me && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
e.timer = 1;
|
||||
RaisePriority(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3771,6 +3787,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
}
|
||||
|
||||
e.active = true;//activate events with cooldown
|
||||
|
||||
switch (e.GetEventType())//process ONLY timed events
|
||||
{
|
||||
case SMART_EVENT_UPDATE:
|
||||
@@ -3814,6 +3831,18 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.priority != SmartScriptHolder::DEFAULT_PRIORITY)
|
||||
{
|
||||
// Reset priority to default one only if the event hasn't been rescheduled again to next loop
|
||||
if (e.timer > 1)
|
||||
{
|
||||
// Re-sort events if this was moved to the top of the queue
|
||||
mEventSortingRequired = true;
|
||||
// Reset priority to default one
|
||||
e.priority = SmartScriptHolder::DEFAULT_PRIORITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
e.timer -= diff;
|
||||
@@ -3922,6 +3951,12 @@ void SmartScript::OnUpdate(uint32 const diff)
|
||||
|
||||
InstallEvents();//before UpdateTimers
|
||||
|
||||
if (mEventSortingRequired)
|
||||
{
|
||||
SortEvents(mEvents);
|
||||
mEventSortingRequired = false;
|
||||
}
|
||||
|
||||
for (SmartScriptHolder& mEvent : mEvents)
|
||||
UpdateTimer(mEvent, diff);
|
||||
|
||||
@@ -3979,6 +4014,22 @@ void SmartScript::OnUpdate(uint32 const diff)
|
||||
}
|
||||
}
|
||||
|
||||
void SmartScript::SortEvents(SmartAIEventList& events)
|
||||
{
|
||||
std::sort(events.begin(), events.end());
|
||||
}
|
||||
|
||||
void SmartScript::RaisePriority(SmartScriptHolder& e)
|
||||
{
|
||||
e.timer = 1;
|
||||
// Change priority only if it's set to default, otherwise keep the current order of events
|
||||
if (e.priority == SmartScriptHolder::DEFAULT_PRIORITY)
|
||||
{
|
||||
e.priority = mCurrentPriority++;
|
||||
mEventSortingRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest)
|
||||
{
|
||||
if (e.empty())
|
||||
|
||||
Reference in New Issue
Block a user