diff --git a/common/spdat.h b/common/spdat.h index 64e831516..98423f9a7 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1067,7 +1067,7 @@ typedef enum { #define SE_ShadowStepDirectional 379 // implemented - handled by client #define SE_Knockdown 380 // implemented - small knock back(handled by client) //#define SE_KnockTowardCaster 381 // *not implemented (Call of Hither) knocks you back to caster (value) distance units infront -#define SE_NegateSpellEffect 382 // implemented, @Debuff, negates specific spell effect benefits for the duration of the debuff, base: see NegateSpellEffecttype Enum, limit: SPA id, max: none +#define SE_NegateSpellEffect 382 // implemented, @Debuff, negates specific spell effect benefits for the duration of the debuff and prevent non-duration spell effect from working, base: see NegateSpellEffecttype Enum, limit: SPA id, max: none #define SE_SympatheticProc 383 // implemented, @Fc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid #define SE_Leap 384 // implemented - Leap effect, ie stomping leap #define SE_LimitSpellGroup 385 // implemented, @Ff, Spell group(s) that a spell focus can require or exclude, base1: spellgroup id, Include: Positive Exclude: Negative diff --git a/zone/mob.h b/zone/mob.h index 9ccf846c9..f44c715ce 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -298,6 +298,7 @@ public: uint8 WornType = 0, int32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10, bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); void NegateSpellEffectBonuses(uint16 spell_id); + bool NegateSpellEffect(uint16 spell_id, int effect_id); virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false); virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr); virtual int32 GetActDoTDamage(uint16 spell_id, int32 value, Mob* target); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 68fa5e897..6fb4ce5e1 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -216,10 +216,19 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (GetSpellPowerDistanceMod()) effect_value = effect_value*GetSpellPowerDistanceMod()/100; + //Prevents effect from being applied + if (spellbonuses.NegateEffects) { + if (effect != SE_NegateSpellEffect && NegateSpellEffect(spell_id, effect)) { + if (caster) { + caster->Message(Chat::Red, "Part or all of this spell has lost its effectiveness."); //Placeholder msg, until live one is obtained. + } + continue; + } + } + #ifdef SPELL_EFFECT_SPAM effect_desc[0] = 0; #endif - switch(effect) { case SE_CurrentHP: // nukes, heals; also regen/dot if a buff @@ -8513,3 +8522,22 @@ int Mob::GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool return zone->random.Int(focus_base, focus_base2); } + +bool Mob::NegateSpellEffect(uint16 spell_id, int effect_id) +{ + //*This works for most effects, anything handled purely by the client will bypass this (ie Gate, Shadowstep) + + for (int i = 0; i < GetMaxTotalSlots(); i++) { + //Check for any buffs containing NegateEffect + if (IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect) && spell_id != buffs[i].spellid) { + //Match each of the negate effects with the current spell effect, if found, that effect will not be applied. + for (int j = 0; j < EFFECT_COUNT; j++) + { + if (spells[buffs[i].spellid].base2[j] == effect_id) { + return true; + } + } + } + } + return false; +}