From 8fedf404404bd1b6842ede45edcd13cc7c937ca9 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 14 Jul 2021 10:31:46 -0400 Subject: [PATCH] Implemented SPA 474, 494 Implemented SE_Pet_Crit_Melee_Damage_Pct_Owner 474 - Gives pets a critical melee damage modifier from the owner SE_Pet_Add_Atk 494 - Gives pet a ATK bonus from the owner Fixed SE_PetMeleeMitigation 397 - The bonus was not being calculated --- common/spdat.h | 20 ++++++------- zone/attack.cpp | 64 +++++++++++++++++++++++++++++++----------- zone/bonuses.cpp | 27 ++++++++++++++++++ zone/common.h | 4 ++- zone/mob.cpp | 10 +++++-- zone/mob.h | 5 +++- zone/spell_effects.cpp | 15 +++++++++- 7 files changed, 112 insertions(+), 33 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 27f7e1870..187cadcf4 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -381,7 +381,7 @@ typedef enum { #define SE_PoisonCounter 36 // implemented //#define SE_DetectHostile 37 // not used //#define SE_DetectMagic 38 // not used -//#define SE_DetectPoison 39 // not used +//#define SE_DetectPoison 39 // not used TODO: NEW EFFECT Stacking:: Twincast Blocker #define SE_DivineAura 40 // implemented #define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows #define SE_ShadowStep 42 // implemented @@ -464,7 +464,7 @@ typedef enum { #define SE_AttackSpeed3 119 // implemented #define SE_HealRate 120 // implemented - reduces healing by a % #define SE_ReverseDS 121 // implemented -//#define SE_ReduceSkill 122 // not used +//#define SE_ReduceSkill 122 // not implemented TODO: Now used on live, decreases skills by percent #define SE_Screech 123 // implemented Spell Blocker(If have buff with value +1 will block any effect with -1) #define SE_ImprovedDamage 124 // implemented #define SE_ImprovedHeal 125 // implemented @@ -488,7 +488,7 @@ typedef enum { #define SE_LimitCastTimeMin 143 // implemented #define SE_LimitCastTimeMax 144 // implemented (*not used in any known live spell) #define SE_Teleport2 145 // implemented - Banishment of the Pantheon -//#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233) +//#define SE_ElectricityResist 146 // *not implemented TODO: Now used on live, xyz for teleport spells? also in temp pets? #define SE_PercentalHeal 147 // implemented #define SE_StackingCommand_Block 148 // implemented? #define SE_StackingCommand_Overwrite 149 // implemented? @@ -674,7 +674,7 @@ typedef enum { #define SE_ManaAbsorbPercentDamage 329 // implemented #define SE_CriticalDamageMob 330 // implemented #define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine -#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) +#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) TOOD: implement this. #define SE_CastOnRuneFadeEffect 333 // implemented #define SE_BardAEDot 334 // implemented #define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494) @@ -739,7 +739,7 @@ typedef enum { #define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions. #define SE_FcHealPctCritIncoming 395 // implemented[AA] - Increases chance of having a heal crit when cast on you. [focus limited] #define SE_FcHealAmtCrit 396 // implemented - Adds a direct healing amount to spells -#define SE_PetMeleeMitigation 397 // implemented[AA] - additional mitigation to your pets. Adds AC. +#define SE_PetMeleeMitigation 397 // implemented[AA] - additional mitigation to your pets. Adds AC #define SE_SwarmPetDuration 398 // implemented - Affects the duration of swarm pets #define SE_FcTwincast 399 // implemented - cast 2 spells for every 1 #define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained @@ -809,15 +809,15 @@ typedef enum { #define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round //#define SE_PC_Pet_AE_Rampage 465 // Would assume as above but need to confirm. #define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit. -#define SE_DS_Mitigation_Amount 467 // implemented - Modify incoming damage shield damage by percentage -#define SE_DS_Mitigation_Percentage 468 // implemented - Modify incoming damage shield damage by a flat amount +#define SE_DS_Mitigation_Amount 467 // implemented - Modify incoming damage shield damage by a flat amount +#define SE_DS_Mitigation_Percentage 468 // implemented - Modify incoming damage shield damage by percentage #define SE_Chance_Best_in_Spell_Grp 469 // implemented - Chance to cast highest scribed spell within a spell group. All base2 spells share roll chance, only 1 cast. #define SE_Trigger_Best_in_Spell_Grp 470 // implemented - Chance to cast highest scribed spell within a spell group. Each spell has own chance. //#define SE_Double_Melee_Round 471 // //#define SE_Buy_AA_Rank 472 // #define SE_Double_Backstab_Front 473 // implemented - Chance to double backstab from front -//#define SE_Pet_Crit_Melee_Damage_Pct_Owner 474 // -//#define SE_Trigger_Spell_Non_Item 475 // +#define SE_Pet_Crit_Melee_Damage_Pct_Owner 474 // implemenetd - Critical damage mod applied to pets from owner +#define SE_Trigger_Spell_Non_Item 475 // implemented - Trigger spell on cast only if not from item click. //#define SE_Weapon_Stance 476 // //#define SE_Hatelist_To_Top_Index 477 // //#define SE_Hatelist_To_Tail_Index 478 // @@ -836,7 +836,7 @@ typedef enum { //#define SE_Ff_ReuseTimeMax 491 // //#define SE_Ff_Endurance_Min 492 // //#define SE_Ff_Endurance_Max 493 // -//#define SE_Pet_Add_Atk 494 // +#define SE_Pet_Add_Atk 494 // //#define SE_Ff_DurationMax 495 // #define SE_Critical_Melee_Damage_Mod_Max 496 // implemented - increase or decrease by percent critical damage (not stackable) //#define SE_Ff_FocusCastProcNoBypass 497 // diff --git a/zone/attack.cpp b/zone/attack.cpp index 303d46fe5..a49131365 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -274,14 +274,8 @@ int Mob::GetTotalDefense() // 172 Evasion aka SE_AvoidMeleeChance evasion_bonus += itembonuses.AvoidMeleeChanceEffect + aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance - Mob *owner = nullptr; - if (IsPet()) - owner = GetOwner(); - else if (IsNPC() && CastToNPC()->GetSwarmOwner()) - owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); - - if (owner) // 215 Pet Avoidance % aka SE_PetAvoidance - evasion_bonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + // 215 Pet Avoidance % aka SE_PetAvoidance + evasion_bonus += GetPetAvoidanceBonusFromOwner(); // Evasion is a percentage bonus according to AA descriptions if (evasion_bonus) @@ -823,13 +817,7 @@ int Mob::ACSum(bool skip_caps) // According to the guild hall Combat Dummies, a level 50 classic EQ mob it should be ~115 // For a 60 PoP mob ~120, 70 OoW ~120 ac += GetAC(); - Mob *owner = nullptr; - if (IsPet()) - owner = GetOwner(); - else if (CastToNPC()->GetSwarmOwner()) - owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); - if (owner) - ac += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + ac += GetPetACBonusFromOwner(); auto spell_aa_ac = aabonuses.AC + spellbonuses.AC; ac += GetSkill(EQ::skills::SkillDefense) / 5; if (EQ::ValueWithin(static_cast(GetClass()), NECROMANCER, ENCHANTER)) @@ -925,7 +913,7 @@ int Mob::offense(EQ::skills::SkillType skill) if (stat_bonus >= 75) offense += (2 * stat_bonus - 150) / 3; - offense += GetATK(); + offense += GetATK() + GetPetATKBonusFromOwner(); return offense; } @@ -4343,7 +4331,7 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit) if (critChance > 0) { if (zone->random.Roll(critChance)) { - critMod += GetCritDmgMod(hit.skill); + critMod += GetCritDmgMod(hit.skill, owner); hit.damage_done += 5; hit.damage_done = (hit.damage_done * critMod) / 100; @@ -5625,6 +5613,48 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) } } + +int Mob::GetPetAvoidanceBonusFromOwner() +{ + Mob *owner = nullptr; + if (IsPet()) + owner = GetOwner(); + else if (IsNPC() && CastToNPC()->GetSwarmOwner()) + owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + + if (owner) + return owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + + return 0; +} +int Mob::GetPetACBonusFromOwner() +{ + Mob *owner = nullptr; + if (IsPet()) + owner = GetOwner(); + else if (IsNPC() && CastToNPC()->GetSwarmOwner()) + owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + + if (owner) + return owner->aabonuses.PetMeleeMitigation + owner->spellbonuses.PetMeleeMitigation + owner->itembonuses.PetMeleeMitigation; + + return 0; +} +int Mob::GetPetATKBonusFromOwner() +{ + Mob *owner = nullptr; + if (IsPet()) + owner = GetOwner(); + else if (IsNPC() && CastToNPC()->GetSwarmOwner()) + owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + + if (owner) + return owner->aabonuses.Pet_Add_Atk + owner->spellbonuses.Pet_Add_Atk + owner->itembonuses.Pet_Add_Atk; + + return 0; +} + + bool Mob::GetWasSpawnedInWater() const { return spawned_in_water; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index bc8075275..f973ab14c 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1546,6 +1546,14 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->DS_Mitigation_Percentage += base1; break; + case SE_Pet_Crit_Melee_Damage_Pct_Owner: + newbon->Pet_Crit_Melee_Damage_Pct_Owner += base1; + break; + + case SE_Pet_Add_Atk: + newbon->Pet_Add_Atk += base1; + break; + // to do case SE_PetDiscipline: @@ -3386,7 +3394,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->DS_Mitigation_Percentage += effect_value; break; + case SE_Pet_Crit_Melee_Damage_Pct_Owner: + new_bonus->Pet_Crit_Melee_Damage_Pct_Owner += effect_value; + break; + case SE_Pet_Add_Atk: + new_bonus->Pet_Add_Atk += effect_value; + break; //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4978,6 +4992,19 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.DS_Mitigation_Percentage = effect_value; break; + case SE_Pet_Crit_Melee_Damage_Pct_Owner: + spellbonuses.Pet_Crit_Melee_Damage_Pct_Owner = effect_value; + itembonuses.Pet_Crit_Melee_Damage_Pct_Owner = effect_value; + aabonuses.Pet_Crit_Melee_Damage_Pct_Owner = effect_value; + break; + + case SE_Pet_Add_Atk: + spellbonuses.Pet_Add_Atk = effect_value; + itembonuses.Pet_Add_Atk = effect_value; + aabonuses.Pet_Add_Atk = effect_value; + break; + + case SE_SkillProcSuccess:{ for(int e = 0; e < MAX_SKILL_PROCS; e++) { diff --git a/zone/common.h b/zone/common.h index 01c074b11..1df689416 100644 --- a/zone/common.h +++ b/zone/common.h @@ -532,7 +532,9 @@ struct StatBonuses { int32 Melee_Damage_Position_Mod[2]; // base = percent 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 + int32 DS_Mitigation_Percentage; // base = percent amt of DS mitigation. Negative value to reduce + int32 Pet_Crit_Melee_Damage_Pct_Owner; // base = percent mod for pet critcal damage from owner + int32 Pet_Add_Atk; // base = Pet ATK bonus from owner // AAs int8 Packrat; //weight reduction for items, 1 point = 10% diff --git a/zone/mob.cpp b/zone/mob.cpp index 94d85de13..0695545ab 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4672,17 +4672,21 @@ bool Mob::TrySpellOnDeath() //in death because the heal will not register before the script kills you. } -int16 Mob::GetCritDmgMod(uint16 skill) +int16 Mob::GetCritDmgMod(uint16 skill, Mob* owner) { int critDmg_mod = 0; // All skill dmg mod + Skill specific [SPA 330 and 496] critDmg_mod += itembonuses.CritDmgMod[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMod[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMod[EQ::skills::HIGHEST_SKILL + 1] + itembonuses.CritDmgMod[skill] + spellbonuses.CritDmgMod[skill] + aabonuses.CritDmgMod[skill]; - Shout("Mod 1 %i", critDmg_mod); + critDmg_mod += itembonuses.CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgModNoStack[EQ::skills::HIGHEST_SKILL + 1] + itembonuses.CritDmgModNoStack[skill] + spellbonuses.CritDmgModNoStack[skill] + aabonuses.CritDmgModNoStack[skill]; - Shout("Mod 2 %i", critDmg_mod); + + if (owner) //Checked in TryPetCriticalHit + critDmg_mod += owner->aabonuses.Pet_Crit_Melee_Damage_Pct_Owner + owner->itembonuses.Pet_Crit_Melee_Damage_Pct_Owner + owner->spellbonuses.Pet_Crit_Melee_Damage_Pct_Owner; + + return critDmg_mod; } diff --git a/zone/mob.h b/zone/mob.h index c0ce7bf5a..a4cf3b07e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -814,7 +814,7 @@ public: void CastOnCure(uint32 spell_id); void CastOnNumHitFade(uint32 spell_id); void SlowMitigation(Mob* caster); - int16 GetCritDmgMod(uint16 skill); + int16 GetCritDmgMod(uint16 skill, Mob* owner = nullptr); int16 GetMeleeDamageMod_SE(uint16 skill); int16 GetMeleeMinDamageMod_SE(uint16 skill); int16 GetCrippBlowChance(); @@ -909,6 +909,9 @@ public: inline bool IsTempPet() const { return _IsTempPet; } inline void SetTempPet(bool value) { _IsTempPet = value; } inline bool IsHorse() { return is_horse; } + int GetPetAvoidanceBonusFromOwner(); + int GetPetACBonusFromOwner(); + int GetPetATKBonusFromOwner(); inline const bodyType GetBodyType() const { return bodytype; } inline const bodyType GetOrigBodyType() const { return orig_bodytype; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index aec467742..1b7e02257 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2895,8 +2895,19 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } break; } - + case SE_Trigger_Spell_Non_Item: { + //Only trigger if not from item + if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) + break; + + if (zone->random.Roll(spells[spell_id].base[i]) && IsValidSpell(spells[spell_id].base2[i])) + caster->SpellFinished(spells[spell_id].base2[i], this, EQ::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + + break; + } + + case SE_PersistentEffect: MakeAura(spell_id); break; @@ -3153,6 +3164,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_DS_Mitigation_Amount: case SE_DS_Mitigation_Percentage: case SE_Double_Backstab_Front: + case SE_Pet_Crit_Melee_Damage_Pct_Owner: + case SE_Pet_Add_Atk: { break; }