diff --git a/common/spdat.h b/common/spdat.h index 36aef716e..30def8598 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -845,9 +845,9 @@ typedef enum { //#define SE_Fc_CastTimeMod2 500 // //#define SE_Fc_CastTimeAmt 501 // //#define SE_Fearstun 502 // -//#define SE_Melee_Damage_Position_Mod 503 // +#define SE_Melee_Damage_Position_Mod 503 // //#define SE_Melee_Damage_Position_Amt 504 // -//#define SE_Damage_Taken_Position_Mod 505 // +#define SE_Damage_Taken_Position_Mod 505 // //#define SE_Damage_Taken_Position_Amt 506 // //#define SE_Fc_Amplify_Mod 507 // //#define SE_Fc_Amplify_Amt 508 // diff --git a/zone/attack.cpp b/zone/attack.cpp index aff6ac9fa..cd0f6104f 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4656,6 +4656,7 @@ void Mob::ApplyMeleeDamageMods(uint16 skill, int &damage, Mob *defender, ExtraAt int dmgbonusmod = 0; dmgbonusmod += GetMeleeDamageMod_SE(skill); + dmgbonusmod += GetMeleeDmgPositionMod(defender); if (opts) dmgbonusmod += opts->melee_damage_bonus_flat; @@ -5269,7 +5270,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac if (spec_mod > 0) hit.damage_done = (hit.damage_done * spec_mod) / 100; - hit.damage_done += (hit.damage_done * defender->GetSkillDmgTaken(hit.skill, opts) / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill)); + hit.damage_done += (hit.damage_done * (defender->GetSkillDmgTaken(hit.skill, opts) + defender->GetPositionalDmgTaken(this)) / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill)); CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e8ca2ebce..b0bdeb843 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1512,6 +1512,30 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->AC_Avoidance_Max_Percent += base1; break; + case SE_Damage_Taken_Position_Mod: + { + //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + else if (base1 < 0 && newbon->Damage_Taken_Position_Mod[base2] > base1) + newbon->Damage_Taken_Position_Mod[base2] = base1; + else if (base1 > 0 && newbon->Damage_Taken_Position_Mod[base2] < base1) + newbon->Damage_Taken_Position_Mod[base2] = base1; + break; + } + + case SE_Melee_Damage_Position_Mod: + { + if (base2 < 0 || base2 > 2) + break; + else if (base1 < 0 && newbon->Melee_Damage_Position_Mod[base2] > base1) + newbon->Melee_Damage_Position_Mod[base2] = base1; + else if (base1 > 0 && newbon->Melee_Damage_Position_Mod[base2] < base1) + newbon->Melee_Damage_Position_Mod[base2] = base1; + break; + } + + // to do case SE_PetDiscipline: break; @@ -3311,6 +3335,34 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->AC_Avoidance_Max_Percent += effect_value; break; + case SE_Damage_Taken_Position_Mod: + { + //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + if (AdditiveWornBonus) + new_bonus->Damage_Taken_Position_Mod[base2] += effect_value; + else if (effect_value < 0 && new_bonus->Damage_Taken_Position_Mod[base2] > effect_value) + new_bonus->Damage_Taken_Position_Mod[base2] = effect_value; + else if (effect_value > 0 && new_bonus->Damage_Taken_Position_Mod[base2] < effect_value) + new_bonus->Damage_Taken_Position_Mod[base2] = effect_value; + break; + } + + case SE_Melee_Damage_Position_Mod: + { + //Increase damage by percent from behind base2 = 0, from front base2 = 1 + if (base2 < 0 || base2 > 2) + break; + if (AdditiveWornBonus) + new_bonus->Melee_Damage_Position_Mod[base2] += effect_value; + else if (effect_value < 0 && new_bonus->Melee_Damage_Position_Mod[base2] > effect_value) + new_bonus->Melee_Damage_Position_Mod[base2] = effect_value; + else if (effect_value > 0 && new_bonus->Melee_Damage_Position_Mod[base2] < effect_value) + new_bonus->Melee_Damage_Position_Mod[base2] = effect_value; + break; + } + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table diff --git a/zone/common.h b/zone/common.h index 5b43b2e1d..bcb86f531 100644 --- a/zone/common.h +++ b/zone/common.h @@ -528,6 +528,8 @@ struct StatBonuses { int32 Attack_Accuracy_Max_Percent; // Increase ATK accuracy by percent. int32 AC_Mitigation_Max_Percent; // Increase AC mitigation by percent 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 // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/mob.cpp b/zone/mob.cpp index cf1ca5032..b1a3aa624 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3816,6 +3816,33 @@ int16 Mob::GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackO return skilldmg_mod; } +int16 Mob::GetPositionalDmgTaken(Mob *attacker) +{ + if (!attacker) + return 0; + + int front_arc = 0; + int back_arc = 0; + int total_mod = 0; + + back_arc += itembonuses.Damage_Taken_Position_Mod[0] + aabonuses.Damage_Taken_Position_Mod[0] + spellbonuses.Damage_Taken_Position_Mod[0]; + front_arc += itembonuses.Damage_Taken_Position_Mod[1] + aabonuses.Damage_Taken_Position_Mod[1] + spellbonuses.Damage_Taken_Position_Mod[1]; + + 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 + total_mod = back_arc; //If so, apply the back arc modifier only + else + total_mod = front_arc;//If not, apply the front arc modifer only + } + + total_mod = round(static_cast(total_mod) * 0.1); + + if (total_mod < -100) + total_mod = -100; + + return total_mod; +} + int16 Mob::GetHealRate(uint16 spell_id, Mob* caster) { int16 heal_rate = 0; @@ -4721,6 +4748,35 @@ int16 Mob::GetCrippBlowChance() return crip_chance; } + +int16 Mob::GetMeleeDmgPositionMod(Mob* defender) +{ + if (!defender) + return 0; + + int front_arc = 0; + int back_arc = 0; + int total_mod = 0; + + back_arc += itembonuses.Melee_Damage_Position_Mod[0] + aabonuses.Melee_Damage_Position_Mod[0] + spellbonuses.Melee_Damage_Position_Mod[0]; + front_arc += itembonuses.Melee_Damage_Position_Mod[1] + aabonuses.Melee_Damage_Position_Mod[1] + spellbonuses.Melee_Damage_Position_Mod[1]; + + if (back_arc || front_arc) { //Do they have this bonus? + if (BehindMob(defender, GetX(), GetY()))//Check if attacker is striking from behind + total_mod = back_arc; //If so, apply the back arc modifier only + else + total_mod = front_arc;//If not, apply the front arc modifer only + } + + total_mod = round(static_cast(total_mod) * 0.1); + + if (total_mod < -100) + total_mod = -100; + + return total_mod; + +} + int16 Mob::GetSkillReuseTime(uint16 skill) { int skill_reduction = this->itembonuses.SkillReuseTime[skill] + this->spellbonuses.SkillReuseTime[skill] + this->aabonuses.SkillReuseTime[skill]; diff --git a/zone/mob.h b/zone/mob.h index 81ded3b3e..76dfb0b4c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -804,6 +804,7 @@ public: int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0); int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); int16 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr); + int16 GetPositionalDmgTaken(Mob *attacker); void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup); int16 CalcResistChanceBonus(); int16 CalcFearResistChance(); @@ -817,6 +818,7 @@ public: int16 GetMeleeDamageMod_SE(uint16 skill); int16 GetMeleeMinDamageMod_SE(uint16 skill); int16 GetCrippBlowChance(); + int16 GetMeleeDmgPositionMod(Mob* defender); int16 GetSkillReuseTime(uint16 skill); int GetCriticalChanceBonus(uint16 skill); int16 GetSkillDmgAmt(uint16 skill); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 1695a5a4e..03b929d8b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3126,6 +3126,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_AC_Avoidance_Max_Percent: case SE_Attack_Accuracy_Max_Percent: case SE_Critical_Melee_Damage_Mod_Max: + case SE_Melee_Damage_Position_Mod: + case SE_Damage_Taken_Position_Mod: { break; }