Core/SAI: Fix SMART_EVENT_FLAG_NOT_REPEATABLE flag being ignored when specifying a chance (and other SMART_ACTION_CAST fixes) (#25778)

* Core/SAI: Fix SMART_EVENT_FLAG_NOT_REPEATABLE flag being ignored when specifying a chance

Fix SMART_EVENT_FLAG_NOT_REPEATABLE flag being ignored when specifying a chance, always making the action trigger.

* Fix SMART_ACTION_CAST with SMART_EVENT_FLAG_NOT_REPEATABLE not casting the spell at all if rolled chance was successful but creature couldn't cast the spell

* Prevent linked actions if SMART_ACTION_CAST couldn't be completed and will be retried later

(cherry picked from commit 96b289cadbf304e427ddbd281d1a6f592af612a7)
This commit is contained in:
Giacomo Pozzoni
2022-03-05 17:11:58 +01:00
committed by Shauren
parent a8d00ddd69
commit da0d9ee283
3 changed files with 27 additions and 4 deletions
@@ -258,13 +258,17 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob, std::string const& varString) void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob, std::string const& varString)
{ {
e.runOnce = true; //used for repeat check
// calc random // calc random
if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance) if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance && !(e.event.event_flags & SMART_EVENT_FLAG_TEMP_IGNORE_CHANCE_ROLL))
{ {
if (!roll_chance_i(e.event.event_chance)) if (!roll_chance_i(e.event.event_chance))
return; return;
} }
e.runOnce = true; //used for repeat check
// Remove SMART_EVENT_FLAG_TEMP_IGNORE_CHANCE_ROLL flag after processing roll chances as it's not needed anymore
e.event.event_flags &= ~SMART_EVENT_FLAG_TEMP_IGNORE_CHANCE_ROLL;
if (unit) if (unit)
mLastInvoker = unit->GetGUID(); mLastInvoker = unit->GetGUID();
@@ -613,7 +617,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
// If there is at least 1 failed cast and no successful casts at all, retry again on next loop // If there is at least 1 failed cast and no successful casts at all, retry again on next loop
if (failedSpellCast && !successfulSpellCast) if (failedSpellCast && !successfulSpellCast)
RaisePriority(e); {
RetryLater(e, true);
// Don't execute linked events
return;
}
break; break;
} }
case SMART_ACTION_SELF_CAST: case SMART_ACTION_SELF_CAST:
@@ -4076,6 +4084,17 @@ void SmartScript::RaisePriority(SmartScriptHolder& e)
} }
} }
void SmartScript::RetryLater(SmartScriptHolder& e, bool ignoreChanceRoll)
{
RaisePriority(e);
// This allows to retry the action later without rolling again the chance roll (which might fail and end up not executing the action)
if (ignoreChanceRoll)
e.event.event_flags |= SMART_EVENT_FLAG_TEMP_IGNORE_CHANCE_ROLL;
e.runOnce = false;
}
void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest) void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest)
{ {
if (e.empty()) if (e.empty())
@@ -108,6 +108,7 @@ class TC_GAME_API SmartScript
void SortEvents(SmartAIEventList& events); void SortEvents(SmartAIEventList& events);
void RaisePriority(SmartScriptHolder& e); void RaisePriority(SmartScriptHolder& e);
void RetryLater(SmartScriptHolder& e, bool ignoreChanceRoll = false);
SmartAIEventList mEvents; SmartAIEventList mEvents;
SmartAIEventList mInstallEvents; SmartAIEventList mInstallEvents;
@@ -1619,7 +1619,10 @@ enum SmartEventFlags
SMART_EVENT_FLAG_WHILE_CHARMED = 0x200, //Event occurs even if AI owner is charmed SMART_EVENT_FLAG_WHILE_CHARMED = 0x200, //Event occurs even if AI owner is charmed
SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0|SMART_EVENT_FLAG_DIFFICULTY_1|SMART_EVENT_FLAG_DIFFICULTY_2|SMART_EVENT_FLAG_DIFFICULTY_3), SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0|SMART_EVENT_FLAG_DIFFICULTY_1|SMART_EVENT_FLAG_DIFFICULTY_2|SMART_EVENT_FLAG_DIFFICULTY_3),
SMART_EVENT_FLAGS_ALL = (SMART_EVENT_FLAG_NOT_REPEATABLE|SMART_EVENT_FLAG_DIFFICULTY_ALL|SMART_EVENT_FLAG_RESERVED_5|SMART_EVENT_FLAG_RESERVED_6|SMART_EVENT_FLAG_DEBUG_ONLY|SMART_EVENT_FLAG_DONT_RESET|SMART_EVENT_FLAG_WHILE_CHARMED) SMART_EVENT_FLAGS_ALL = (SMART_EVENT_FLAG_NOT_REPEATABLE|SMART_EVENT_FLAG_DIFFICULTY_ALL|SMART_EVENT_FLAG_RESERVED_5|SMART_EVENT_FLAG_RESERVED_6|SMART_EVENT_FLAG_DEBUG_ONLY|SMART_EVENT_FLAG_DONT_RESET|SMART_EVENT_FLAG_WHILE_CHARMED),
// Temp flags, used only at runtime, never stored in DB
SMART_EVENT_FLAG_TEMP_IGNORE_CHANCE_ROLL = 0x40000000, //Event occurs no matter what roll_chance_i(e.event.event_chance) returns.
}; };
enum SmartCastFlags enum SmartCastFlags