Skip to content

Commit

Permalink
AI: Implement SPELL_LIST_FLAG_NON_BLOCKING
Browse files Browse the repository at this point in the history
  • Loading branch information
killerwife committed Oct 16, 2023
1 parent 8d7a5af commit 7b6609b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
40 changes: 29 additions & 11 deletions src/game/AI/BaseAI/UnitAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ void UnitAI::UpdateSpellLists()

// when probability is 0 for all spells, they will use priority based on positions
std::vector<std::tuple<uint32, uint32, uint32, Unit*>> eligibleSpells;
std::vector<std::tuple<uint32, uint32, uint32, Unit*>> nonBlockingSpells;
uint32 sum = 0;

// one roll due to multiple spells
Expand Down Expand Up @@ -1241,13 +1242,38 @@ void UnitAI::UpdateSpellLists()
if (!result)
continue;

eligibleSpells.emplace_back(spell.SpellId, spell.Probability, spell.ScriptId, target);
sum += spell.Probability;
if (spell.Flags & SPELL_LIST_FLAG_NON_BLOCKING)
nonBlockingSpells.emplace_back(spell.SpellId, spell.Probability, spell.ScriptId, target);
else
{
eligibleSpells.emplace_back(spell.SpellId, spell.Probability, spell.ScriptId, target);
sum += spell.Probability;
}
}

if (eligibleSpells.size() > 1 && sum != 0) // sum == 0 is meant to be priority based (lower position, higher priority)
std::shuffle(eligibleSpells.begin(), eligibleSpells.end(), *GetRandomGenerator());

auto executeSpell = [&](uint32 spellId, uint32 probability, uint32 scriptId, Unit* target) -> bool
{
CanCastResult castResult = DoCastSpellIfCan(target, spellId);
if (castResult == CAST_OK)
{
OnSpellCast(sSpellTemplate.LookupEntry<SpellEntry>(spellId), target);
if (scriptId)
m_unit->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, scriptId, m_unit, target);
return true;
}
return false;
};

for (auto& data : nonBlockingSpells)
{
uint32 spellId; uint32 probability; uint32 scriptId; Unit* target;
std::tie(spellId, probability, scriptId, target) = data;
executeSpell(spellId, probability, scriptId, target);
}

// will hit first eligible spell when sum is 0 because roll -1 < probability 0
int32 spellRoll = sum == 0 ? -1 : irand(0, sum - 1);
bool success = false;
Expand All @@ -1260,15 +1286,7 @@ void UnitAI::UpdateSpellLists()
std::tie(spellId, probability, scriptId, target) = *itr;
if (spellRoll < int32(probability))
{
CanCastResult castResult = DoCastSpellIfCan(target, spellId);
if (castResult == CAST_OK)
{
success = true;
OnSpellCast(sSpellTemplate.LookupEntry<SpellEntry>(spellId), target);
if (scriptId)
m_unit->GetMap()->ScriptsStart(SCRIPT_TYPE_RELAY, scriptId, m_unit, target);
break;
}
success = executeSpell(spellId, probability, scriptId, target);
itr = eligibleSpells.erase(itr);
}
else
Expand Down
7 changes: 4 additions & 3 deletions src/game/Entities/CreatureSpellList.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ struct CreatureSpellListTargeting

enum SpellListFlags
{
SPELL_LIST_FLAG_SUPPORT_ACTION = 1,
SPELL_LIST_FLAG_RANGED_ACTION = 2, // previously known as main ranged spell in EAI
SPELL_LIST_FLAG_CATEGORY_COOLDOWN = 4, // imposes category cooldown instead of normal cooldown
SPELL_LIST_FLAG_SUPPORT_ACTION = 1,
SPELL_LIST_FLAG_RANGED_ACTION = 2, // previously known as main ranged spell in EAI
SPELL_LIST_FLAG_CATEGORY_COOLDOWN = 4, // imposes category cooldown instead of normal cooldown
SPELL_LIST_FLAG_NON_BLOCKING = 8, // executes spell outside of rolling for one action, should be instant TODO: check if its not identical to SPELL_ATTR_EX4_ALLOW_CAST_WHILE_CASTING
};

struct CreatureSpellListSpell
Expand Down

0 comments on commit 7b6609b

Please sign in to comment.