From 2253e43d2c95dd325f53fd53c4b43763030bf5d2 Mon Sep 17 00:00:00 2001 From: Aeadoin <109764533+Aeadoin@users.noreply.github.com> Date: Sat, 7 Jan 2023 19:04:41 -0500 Subject: [PATCH] [AI] Add Support to Heals to allow Trigger based spells (#2709) --- common/spdat.cpp | 137 ++++++++++++++++++++++++++++++++++++------- common/spdat.h | 1 + zone/botspellsai.cpp | 4 +- 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 02d001485..3d8d6186f 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -513,6 +513,27 @@ bool IsEffectInSpell(uint16 spellid, int effect) return false; } + +uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect) { + + for (int index = 0; index < EFFECT_COUNT; index++) { + if ( + spells[spell_id].effect_id[index] == SE_TriggerOnCast || + spells[spell_id].effect_id[index] == SE_SpellTrigger || + spells[spell_id].effect_id[index] == SE_ApplyEffect || + spells[spell_id].effect_id[index] == SE_Trigger_Spell_Non_Item + ) { + int apply_effect_spell_id = spells[spell_id].limit_value[index]; + if (IsEffectInSpell(apply_effect_spell_id, effect)) { + if (IsValidSpell(apply_effect_spell_id)) { + return apply_effect_spell_id; + } + } + } + } + return 0; +} + // arguments are spell id and the index of the effect to check. // this is used in loops that process effects inside a spell to skip // the blanks @@ -938,18 +959,31 @@ int32 GetSpellTargetType(uint16 spell_id) bool IsHealOverTimeSpell(uint16 spell_id) { - if (IsEffectInSpell(spell_id, SE_HealOverTime) && !IsGroupSpell(spell_id)) + if ( + ( + IsEffectInSpell(spell_id, SE_HealOverTime) || + GetTriggerSpellID(spell_id, SE_HealOverTime) + ) && + !IsGroupSpell(spell_id) + ) { return true; + } return false; } bool IsCompleteHealSpell(uint16 spell_id) { - if (spell_id == 13 || IsEffectInSpell(spell_id, SE_CompleteHeal) || - (IsPercentalHealSpell(spell_id) && !IsGroupSpell(spell_id))) + if ( + ( + IsEffectInSpell(spell_id, SE_CompleteHeal) || + IsPercentalHealSpell(spell_id) || + GetTriggerSpellID(spell_id, SE_CompleteHeal) + ) && + !IsGroupSpell(spell_id) + ) { return true; - + } return false; } @@ -957,11 +991,25 @@ bool IsFastHealSpell(uint16 spell_id) { const int MaxFastHealCastingTime = 2000; - if (spells[spell_id].cast_time <= MaxFastHealCastingTime && - spells[spell_id].effect_id[0] == 0 && spells[spell_id].base_value[0] > 0 && - !IsGroupSpell(spell_id)) - return true; - + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (spells[spell_id].cast_time <= MaxFastHealCastingTime && spells[spell_id].good_effect && !IsGroupSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 + ) { + return true; + } + } + } + } return false; } @@ -969,30 +1017,77 @@ bool IsVeryFastHealSpell(uint16 spell_id) { const int MaxFastHealCastingTime = 1000; - if (spells[spell_id].cast_time <= MaxFastHealCastingTime && - spells[spell_id].effect_id[0] == 0 && spells[spell_id].base_value[0] > 0 && - !IsGroupSpell(spell_id)) - return true; + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (spells[spell_id].cast_time <= MaxFastHealCastingTime && spells[spell_id].good_effect && !IsGroupSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 + ) { + return true; + } + } + } + } return false; } bool IsRegularSingleTargetHealSpell(uint16 spell_id) { - if(spells[spell_id].effect_id[0] == 0 && spells[spell_id].base_value[0] > 0 && - spells[spell_id].target_type == ST_Target && spells[spell_id].buff_duration == 0 && - !IsCompleteHealSpell(spell_id) && - !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) - return true; + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (spells[spell_id].target_type == ST_Target && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 && + spells[spell_id].buff_duration == 0 + ) { + return true; + } + } + } + } return false; } bool IsRegularGroupHealSpell(uint16 spell_id) { - if (IsGroupSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id)) - return true; - + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHP)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHP); + if (!spell_id) { + spell_id = (IsEffectInSpell(spell_id, SE_CurrentHPOnce)) ? spell_id : GetTriggerSpellID(spell_id, SE_CurrentHPOnce); + } + if (spell_id) { + if (IsGroupSpell(spell_id) && !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if ( + ( + spells[spell_id].effect_id[i] == SE_CurrentHP || + spells[spell_id].effect_id[i] == SE_CurrentHPOnce + ) && + spells[spell_id].base_value[i] > 0 && + spells[spell_id].buff_duration == 0 + ) { + return true; + } + } + } + } return false; } diff --git a/common/spdat.h b/common/spdat.h index 68082ae2d..89baaadfb 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1480,6 +1480,7 @@ bool IsGroupSpell(uint16 spell_id); bool IsTGBCompatibleSpell(uint16 spell_id); bool IsBardSong(uint16 spell_id); bool IsEffectInSpell(uint16 spellid, int effect); +uint16 GetTriggerSpellID(uint16 spell_id, uint32 effect); bool IsBlankSpellEffect(uint16 spellid, int effect_index); bool IsValidSpell(uint32 spellid); bool IsSummonSpell(uint16 spellid); diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 5e8859698..5b2ecd64f 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -1801,7 +1801,7 @@ std::list Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff continue; } - if (IsEffectInSpell(botSpellList[i].spellid, spellEffect)) { + if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) { BotSpell botSpell; botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellIndex = i; @@ -1833,7 +1833,7 @@ std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, continue; } - if (IsEffectInSpell(botSpellList[i].spellid, spellEffect)) { + if (IsEffectInSpell(botSpellList[i].spellid, spellEffect) || GetTriggerSpellID(botSpellList[i].spellid, spellEffect)) { if (spells[botSpellList[i].spellid].target_type == targetType) { BotSpell botSpell; botSpell.SpellId = botSpellList[i].spellid;