[Spells] Bug fix for AOE Harmony/Lull (#1472)

* Bug fix for AOE Harmony/Lull type spells.

Fixed bug with SPA 30 SE_SE_ChangeFrenzyRad and SPA 86 SE_Harmony allowing those spells to affect NPC's above their level restrictions when cast as a 'Targeted AE' spell (ie. Harmony, Wake of Tranquility) when the targeted NPC was bellow level restricted range, but the NPC's next to them were above it.

As coded now, the adjacent NPC's if over level limit will still get the buff applied to them BUT will not get any benefits from the buff.

This bug was originally reported by: Isaaru

* Live like behavior

Implemented the live like behavior, if this case occurs on live, the buff is not applied to the targets over the level limit and "Your target looks unaffected" message is given.

* code optimization

code optimization
This commit is contained in:
KayenEQ 2021-07-29 19:20:21 -04:00 committed by GitHub
parent 78b15a0214
commit 187d6e9dc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 12 deletions

View File

@ -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<float>(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

View File

@ -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();

View File

@ -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;
}

View File

@ -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();