[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.
This commit is contained in:
KayenEQ 2025-04-09 22:23:39 -04:00 committed by GitHub
parent 5522eda6e4
commit 8e2961dda5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 17 deletions

View File

@ -5331,6 +5331,14 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id)
spellbonuses.SEResist[e] = effect_value; spellbonuses.SEResist[e] = effect_value;
spellbonuses.SEResist[e + 1] = 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; break;
} }

View File

@ -962,7 +962,7 @@ public:
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
bool TryFadeEffect(int slot); bool TryFadeEffect(int slot);
void DispelMagic(Mob* casterm, uint16 spell_id, int effect_value); 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); 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 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 **** int64 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); //**** This can be removed when bot healing focus code is updated ****

View File

@ -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]) if (!IsValidSpell(spell_id)) {
return 0; 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) 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) for(int d = 0; d < MAX_RESISTABLE_EFFECTS*2; d+=2)
{ {
resist_chance = 0;
if (spells[spell_id].effect_id[i] == aabonuses.SEResist[d]){ if (spells[spell_id].effect_id[i] == aabonuses.SEResist[d]){
resist_chance += aabonuses.SEResist[d+1]; resist_chance += aabonuses.SEResist[d+1];
found = true;
} }
if (spells[spell_id].effect_id[i] == itembonuses.SEResist[d]){ if (spells[spell_id].effect_id[i] == itembonuses.SEResist[d]){
resist_chance += itembonuses.SEResist[d+1]; resist_chance += itembonuses.SEResist[d+1];
found = true;
} }
if (spells[spell_id].effect_id[i] == spellbonuses.SEResist[d]){ if (spells[spell_id].effect_id[i] == spellbonuses.SEResist[d]){
resist_chance += spellbonuses.SEResist[d+1]; resist_chance += spellbonuses.SEResist[d+1];
found = true;
} }
if (found) if (resist_chance) {
continue; 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){ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){

View File

@ -5359,8 +5359,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
if (!CharmTick) { if (!CharmTick) {
//Check for Spell Effect specific resistance chances (ie AA Mental Fortitude) //Check for Spell Effect specific resistance chances (ie AA Mental Fortitude)
int se_resist_bonuses = GetSpellEffectResistChance(spell_id); if (resist_type != RESIST_NONE && TrySpellEffectResist(spell_id)) {
if (se_resist_bonuses && zone->random.Roll(se_resist_bonuses)) {
return 0; return 0;
} }