From 416fadd554ae9e61922f585ad097519ddc7449a2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 10 Aug 2021 15:46:52 -0400 Subject: [PATCH] [Spells] Implemented SPA 504 and 506 (#1488) * Implemented SPA 504 and 506 SE_Damage_Taken_Position_Amt 506 // implemented - modify melee damage by amt if dmg taken from Front or Behind SE_Melee_Damage_Position_Amt 504 // implemented - modify melee damage by amt if done from Front or Behind * fix, description updates * Update spdat.h --- common/spdat.h | 8 ++--- zone/attack.cpp | 4 +-- zone/bonuses.cpp | 82 +++++++++++++++++++++++++++++++++++------- zone/common.h | 6 ++-- zone/mob.cpp | 55 +++++++++++++++++++++++++--- zone/mob.h | 2 ++ zone/spell_effects.cpp | 2 ++ 7 files changed, 135 insertions(+), 24 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index affa7bd8c..5e29cc4e3 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -866,10 +866,10 @@ typedef enum { #define SE_Fc_CastTimeMod2 500 // implemented, @Fc, On Caster, cast time mod pct, base: pct, Note: Can reduce to instant cast #define SE_Fc_CastTimeAmt 501 // implemented, @Fc, On Caster, cast time mod flat amt, base: milliseconds, Note: Can reduce to instant cast #define SE_Fearstun 502 // implemented - Stun with a max level limit. Normal stun restrictions don't apply. -#define SE_Melee_Damage_Position_Mod 503 // implemented - modify melee damage by pct if done from Front or Behind -//#define SE_Melee_Damage_Position_Amt 504 // -#define SE_Damage_Taken_Position_Mod 505 // implemented - mitigate melee damage by pct if dmg taken from Front or Behind -//#define SE_Damage_Taken_Position_Amt 506 // +#define SE_Melee_Damage_Position_Mod 503 // implemented, @OffBonus, modify melee damage by percent if done from Front or Behind opponent, base: pct, limit: 0=back 1=front, max: none +#define SE_Melee_Damage_Position_Amt 504 // implemented, @OffBonus, modify melee damage by flat amount if done from Front or Behind opponent, base: amt, limit: 0=back 1=front, max: none +#define SE_Damage_Taken_Position_Mod 505 // implemented, @DefBonus, modify melee damage by percent if dmg taken from Front or Behind, base: pct, limit: 0=back 1=front, max: none +#define SE_Damage_Taken_Position_Amt 506 // implemented -@DefBonus, modify melee damage by flat amount if dmg taken from your Front or Behind, base: amt, limit: 0=back 1=front, max: none #define SE_Fc_Amplify_Mod 507 // implemented, @Fc, On Caster, damage-heal-dot mod pct, base: pct #define SE_Fc_Amplify_Amt 508 // implemented, @Fc, On Caster, damage-heal-dot mod flat amt, base: amt #define SE_Health_Transfer 509 // implemented - exchange health for damage or healing on a target. ie Lifeburn/Act of Valor diff --git a/zone/attack.cpp b/zone/attack.cpp index 6df1c04bb..0a828fcb7 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5219,7 +5219,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac // Seems the crit message is generated before some of them :P // worn item +skill dmg, SPA 220, 418. Live has a normalized version that should be here too - hit.min_damage += GetSkillDmgAmt(hit.skill); + hit.min_damage += GetSkillDmgAmt(hit.skill) + GetPositionalDmgAmt(defender); // shielding mod2 if (defender->itembonuses.MeleeMitigation) @@ -5276,7 +5276,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac int pct_damage_reduction = defender->GetSkillDmgTaken(hit.skill, opts) + defender->GetPositionalDmgTaken(this); - hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill)); + hit.damage_done += (hit.damage_done * pct_damage_reduction / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill)) + defender->GetPositionalDmgTakenAmt(this); CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 33c229ba2..8c4b5893f 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1545,6 +1545,26 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } + case SE_Damage_Taken_Position_Amt: + { + //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + + newbon->Damage_Taken_Position_Amt[base2] += base1; + break; + } + + case SE_Melee_Damage_Position_Amt: + { + //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + + newbon->Melee_Damage_Position_Amt[base2] += base1; + break; + } + case SE_DS_Mitigation_Amount: newbon->DS_Mitigation_Amount += base1; break; @@ -3485,6 +3505,26 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } + case SE_Damage_Taken_Position_Amt: + { + //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + + new_bonus->Damage_Taken_Position_Amt[base2] += effect_value; + break; + } + + case SE_Melee_Damage_Position_Amt: + { + //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + + new_bonus->Melee_Damage_Position_Amt[base2] += effect_value; + break; + } + case SE_DS_Mitigation_Amount: new_bonus->DS_Mitigation_Amount += effect_value; break; @@ -5121,21 +5161,39 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) break; case SE_Melee_Damage_Position_Mod: - spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] = effect_value; - aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] = effect_value; - itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] = effect_value; - spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] = effect_value; - aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] = effect_value; - itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] = effect_value; + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; + itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; + itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; break; case SE_Damage_Taken_Position_Mod: - spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] = effect_value; - aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] = effect_value; - itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] = effect_value; - spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] = effect_value; - aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] = effect_value; - itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] = effect_value; + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; + itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; + itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; + break; + + case SE_Melee_Damage_Position_Amt: + spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; + aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; + itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; + spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; + aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; + itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; + break; + + case SE_Damage_Taken_Position_Amt: + spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; + aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; + itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; + spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; + aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; + itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; break; diff --git a/zone/common.h b/zone/common.h index e92ef309e..ddcb034fc 100644 --- a/zone/common.h +++ b/zone/common.h @@ -542,6 +542,8 @@ struct StatBonuses { int32 AC_Avoidance_Max_Percent; // Increase AC avoidance by percent int32 Damage_Taken_Position_Mod[2]; // base = percent melee damage reduction base2 0=back 1=front. [0]Back[1]Front int32 Melee_Damage_Position_Mod[2]; // base = percent melee damage increase base2 0=back 1=front. [0]Back[1]Front + int32 Damage_Taken_Position_Amt[2]; // base = flat amt melee damage reduction base2 0=back 1=front. [0]Back[1]Front + int32 Melee_Damage_Position_Amt[2]; // base = flat amt melee damage increase base2 0=back 1=front. [0]Back[1]Front int32 Double_Backstab_Front; // base = percent chance to double back stab front int32 DS_Mitigation_Amount; // base = flat amt DS mitigation. Negative value to reduce int32 DS_Mitigation_Percentage; // base = percent amt of DS mitigation. Negative value to reduce @@ -652,8 +654,8 @@ namespace SBIndex { constexpr uint16 ROOT_BUFFSLOT = 1; // SPA 99 constexpr uint16 RUNE_AMOUNT = 0; // SPA 55 constexpr uint16 RUNE_BUFFSLOT = 1; // SPA 78 - constexpr uint16 POSITIONAL_DAMAGE_MOD = 0; // SPA 503-506 - constexpr uint16 POSITIONAL_LOCATION = 1; // SPA 503-506 + constexpr uint16 POSITION_BACK = 0; // SPA 503-506 + constexpr uint16 POSITION_FRONT = 1; // SPA 503-506 constexpr uint16 PET_RAMPAGE_CHANCE = 0; // SPA 464,465 constexpr uint16 PET_RAMPAGE_DMG_MOD = 1; // SPA 465,465 constexpr uint16 SKILLPROC_CHANCE = 0; // SPA 427 diff --git a/zone/mob.cpp b/zone/mob.cpp index 64333363b..ab68f0f6c 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3865,8 +3865,8 @@ int32 Mob::GetPositionalDmgTaken(Mob *attacker) int back_arc = 0; int total_mod = 0; - back_arc += itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD]; - front_arc += itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION]; + back_arc += itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK]; + front_arc += itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT]; if (back_arc || front_arc) { //Do they have this bonus? if (attacker->BehindMob(this, attacker->GetX(), attacker->GetY()))//Check if attacker is striking from behind @@ -3883,6 +3883,29 @@ int32 Mob::GetPositionalDmgTaken(Mob *attacker) return total_mod; } +int32 Mob::GetPositionalDmgTakenAmt(Mob *attacker) +{ + if (!attacker) + return 0; + + int front_arc = 0; + int back_arc = 0; + int total_amt = 0; + + back_arc += itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] + aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] + spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK]; + front_arc += itembonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] + aabonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] + spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT]; + + if (back_arc || front_arc) { + if (attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) + total_amt = back_arc; + else + total_amt = front_arc; + } + + return total_amt; +} + + int16 Mob::GetHealRate(uint16 spell_id, Mob* caster) { int16 heal_rate = 0; @@ -4859,8 +4882,8 @@ int16 Mob::GetMeleeDmgPositionMod(Mob* defender) int back_arc = 0; int total_mod = 0; - back_arc += itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD]; - front_arc += itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION]; + back_arc += itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK]; + front_arc += itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT]; if (back_arc || front_arc) { //Do they have this bonus? if (BehindMob(defender, GetX(), GetY()))//Check if attacker is striking from behind @@ -4899,6 +4922,30 @@ int16 Mob::GetSkillDmgAmt(uint16 skill) return skill_dmg; } +int16 Mob::GetPositionalDmgAmt(Mob* defender) +{ + if (!defender) + return 0; + + //SPA 504 + int front_arc_dmg_amt = 0; + int back_arc_dmg_amt = 0; + + int total_amt = 0; + + back_arc_dmg_amt += itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] + aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] + spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK]; + front_arc_dmg_amt += itembonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] + aabonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] + spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT]; + + if (back_arc_dmg_amt || front_arc_dmg_amt) { + if (BehindMob(defender, GetX(), GetY())) + total_amt = back_arc_dmg_amt; + else + total_amt = front_arc_dmg_amt; + } + + return total_amt; +} + void Mob::MeleeLifeTap(int32 damage) { int32 lifetap_amt = 0; diff --git a/zone/mob.h b/zone/mob.h index acabdce05..49b3fa2c8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -806,6 +806,7 @@ public: int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); int32 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr); int32 GetPositionalDmgTaken(Mob *attacker); + int32 GetPositionalDmgTakenAmt(Mob *attacker); void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup); int16 CalcResistChanceBonus(); int16 CalcFearResistChance(); @@ -823,6 +824,7 @@ public: int16 GetSkillReuseTime(uint16 skill); int GetCriticalChanceBonus(uint16 skill); int16 GetSkillDmgAmt(uint16 skill); + int16 GetPositionalDmgAmt(Mob* defender); bool TryReflectSpell(uint32 spell_id); inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); } bool DoHPToManaCovert(uint16 mana_cost = 0); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index fa2d1eca4..11dfb5b38 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3212,6 +3212,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Critical_Melee_Damage_Mod_Max: case SE_Melee_Damage_Position_Mod: case SE_Damage_Taken_Position_Mod: + case SE_Melee_Damage_Position_Amt: + case SE_Damage_Taken_Position_Amt: case SE_DS_Mitigation_Amount: case SE_DS_Mitigation_Percentage: case SE_Double_Backstab_Front: