diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e52e61533..6ae0075bd 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1750,7 +1750,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_ChangeFrenzyRad: { - // redundant to have level check here + if (max != 0 && GetLevel() > max) + break; + if(new_bonus->AggroRange == -1 || effect_value < new_bonus->AggroRange) { new_bonus->AggroRange = static_cast(effect_value); @@ -1760,6 +1762,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_Harmony: { + if (max != 0 && GetLevel() > max) + break; // Harmony effect as buff - kinda tricky // harmony could stack with a lull spell, which has better aggro range // take the one with less range in any case diff --git a/zone/mob.h b/zone/mob.h index 4e051d76f..ee3801833 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -837,6 +837,7 @@ public: inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; }; inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; }; int32 GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot = 0); + bool HarmonySpellLevelCheck(int32 spell_id, Mob* target = nullptr); void CastSpellOnLand(Mob* caster, uint32 spell_id); void FocusProcLimitProcess(); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f39340876..18cd28117 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -7441,3 +7441,21 @@ void Client::BreakFeignDeathWhenCastOn(bool IsResisted) MessageString(Chat::SpellFailure,FD_CAST_ON); } } + +bool Mob::HarmonySpellLevelCheck(int32 spell_id, Mob *target) +{ + //'this' = caster of spell + if (!target) { + return false; + } + + for (int i = 0; i < EFFECT_COUNT; i++) { + // not important to check limit on SE_Lull as it doesnt have one and if the other components won't land, then SE_Lull wont either + if (spells[spell_id].effectid[i] == SE_ChangeFrenzyRad || spells[spell_id].effectid[i] == SE_Harmony) { + if ((spells[spell_id].max[i] != 0 && target->GetLevel() > spells[spell_id].max[i]) || target->GetSpecialAbility(IMMUNE_PACIFY)) { + return false; + } + } + } + return true; +} diff --git a/zone/spells.cpp b/zone/spells.cpp index c246c79a8..9a2d6f27c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -224,17 +224,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, if (spellbonuses.NegateIfCombat) BuffFadeByEffect(SE_NegateIfCombat); - if(IsClient() && GetTarget() && IsHarmonySpell(spell_id)) - { - for(int i = 0; i < EFFECT_COUNT; i++) { - // not important to check limit on SE_Lull as it doesnt have one and if the other components won't land, then SE_Lull wont either - if (spells[spell_id].effectid[i] == SE_ChangeFrenzyRad || spells[spell_id].effectid[i] == SE_Harmony) { - if((spells[spell_id].max[i] != 0 && GetTarget()->GetLevel() > spells[spell_id].max[i]) || GetTarget()->GetSpecialAbility(IMMUNE_PACIFY)) { - InterruptSpell(CANNOT_AFFECT_NPC, 0x121, spell_id); - return(false); - } - } - } + if (IsClient() && IsHarmonySpell(spell_id) && !HarmonySpellLevelCheck(spell_id, entity_list.GetMobID(target_id))) { + InterruptSpell(SPELL_NO_EFFECT, 0x121, spell_id); + return false; } if (HasActiveSong() && IsBardSong(spell_id)) { @@ -3789,6 +3781,12 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r return false; } } + //Need this to account for special AOE cases. + if (IsClient() && IsHarmonySpell(spell_id) && !HarmonySpellLevelCheck(spell_id, spelltar)) { + MessageString(Chat::SpellFailure, SPELL_NO_EFFECT); + return false; + } + // Block next spell effect should be used up first(since its blocking the next spell) if(CanBlockSpell()) { int buff_count = GetMaxTotalSlots();