From 8e2961dda53067fdf7ec61b37f4658266a6dfeb6 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 9 Apr 2025 22:23:39 -0400 Subject: [PATCH] [Spells] Update to SPA 378 SE_SpellEffectResistChance (#4845) * SPA 378 update Update to SPA 378 SE_SpellEffectResistChance provides chance to resist specific spell effects. This updates allows support for multiple resistance checks against different effects in same spell. Example. If a spell has a silence and a blind effect and the target has an AA that gives 10% chance to resist silence and 5% chance to resist blind. It will roll against effect respectively each giving a chance to resist the spell. * Update spells.cpp Unresistable spells (resisttype = 0) do not ever resist a spell even with SPA378 Example: Pheonix Charm in Plane of Fire, or Storm Comet in Bastion of Thunder. Parsed both and never got a resist despite having the AA that has effect specific resists which both those spells match. --- zone/bonuses.cpp | 8 ++++++++ zone/mob.h | 2 +- zone/spell_effects.cpp | 41 +++++++++++++++++++++++++++-------------- zone/spells.cpp | 3 +-- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index bea237160..8ef663730 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -5331,6 +5331,14 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) spellbonuses.SEResist[e] = effect_value; spellbonuses.SEResist[e + 1] = effect_value; } + if (negate_itembonus) { + itembonuses.SEResist[e] = effect_value; + itembonuses.SEResist[e + 1] = effect_value; + } + if (negate_aabonus) { + aabonuses.SEResist[e] = effect_value; + aabonuses.SEResist[e + 1] = effect_value; + } } break; } diff --git a/zone/mob.h b/zone/mob.h index 01798720a..8664aca76 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -962,7 +962,7 @@ public: uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); bool TryFadeEffect(int slot); void DispelMagic(Mob* casterm, uint16 spell_id, int effect_value); - uint16 GetSpellEffectResistChance(uint16 spell_id); + bool TrySpellEffectResist(uint16 spell_id); int32 GetVulnerability(Mob *caster, uint32 spell_id, uint32 ticsremaining, bool from_buff_tic = false); int64 GetFcDamageAmtIncoming(Mob *caster, int32 spell_id, bool from_buff_tic = false); int64 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); //**** This can be removed when bot healing focus code is updated **** diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4783018a7..e99028737 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -7465,44 +7465,57 @@ void Mob::DispelMagic(Mob* caster, uint16 spell_id, int effect_value) } } -uint16 Mob::GetSpellEffectResistChance(uint16 spell_id) +bool Mob::TrySpellEffectResist(uint16 spell_id) { + /* + SEResist variable + 0 = spell effect id to be check if can resist + 1 = percent chance of resistance + */ - if(!IsValidSpell(spell_id)) - return 0; - if (!aabonuses.SEResist[1] && !spellbonuses.SEResist[1] && !itembonuses.SEResist[1]) - return 0; + if (!IsValidSpell(spell_id)) { + return false; + } - uint16 resist_chance = 0; + if (!aabonuses.SEResist[1] && !spellbonuses.SEResist[1] && !itembonuses.SEResist[1]) { + return false; + } + + int resist_chance = 0; for(int i = 0; i < EFFECT_COUNT; ++i) { - bool found = false; + if (spells[spell_id].effect_id[i] == SE_Blank) { + continue; + } for(int d = 0; d < MAX_RESISTABLE_EFFECTS*2; d+=2) { + resist_chance = 0; if (spells[spell_id].effect_id[i] == aabonuses.SEResist[d]){ resist_chance += aabonuses.SEResist[d+1]; - found = true; } if (spells[spell_id].effect_id[i] == itembonuses.SEResist[d]){ resist_chance += itembonuses.SEResist[d+1]; - found = true; } - if (spells[spell_id].effect_id[i] == spellbonuses.SEResist[d]){ resist_chance += spellbonuses.SEResist[d+1]; - found = true; } - if (found) - continue; + if (resist_chance) { + if (zone->random.Roll(resist_chance)) { + LogSpells("Resisted spell from Spell Effect Resistance, had [{}] chance to resist spell effect id [{}]", resist_chance, spells[spell_id].effect_id[i]); + return true; + } + + break; + } } } - return resist_chance; + return false; } bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){ diff --git a/zone/spells.cpp b/zone/spells.cpp index 051503b7a..e1eb943a4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5359,8 +5359,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use if (!CharmTick) { //Check for Spell Effect specific resistance chances (ie AA Mental Fortitude) - int se_resist_bonuses = GetSpellEffectResistChance(spell_id); - if (se_resist_bonuses && zone->random.Roll(se_resist_bonuses)) { + if (resist_type != RESIST_NONE && TrySpellEffectResist(spell_id)) { return 0; }