From c82139736743c207338523d59ae56c043801e620 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 11 Aug 2021 02:38:38 -0400 Subject: [PATCH] [Spells] Implemented SPA 471 SE_Double_Melee_Round (#1492) * Implemented SPA 471 SE_Double_Melee_Round #define SE_Double_Melee_Round 471 Percent chance to repeat primary weapon round with a percent damage modifier, base: pct chance repeat, limit: pct dmg mod, max: none * minor fixes * tab to spaces --- common/spdat.h | 2 +- zone/bonuses.cpp | 29 +++++++++++++++++++++++++++++ zone/client_process.cpp | 5 +++++ zone/common.h | 3 +++ zone/mob.cpp | 20 ++++++++++++++++++++ zone/mob.h | 5 +++++ zone/spell_effects.cpp | 1 + 7 files changed, 64 insertions(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index 2a53e9aaa..816d8a908 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -834,7 +834,7 @@ typedef enum { #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_Double_Melee_Round 471 // implemented, @OffBonus, percent chance to repeat primary weapon round with a percent damage modifier, base: pct chance repeat, limit: pct dmg mod, max: none #define SE_Buy_AA_Rank 472 // implemented, @Special, Used in AA abilities that have Enable/Disable toggle. Spell on Disabled Rank has this effect in it, base: 1, limit: none, max: none, Note: This will not just buy an AA #define SE_Double_Backstab_Front 473 // implemented - Chance to double backstab from front #define SE_Pet_Crit_Melee_Damage_Pct_Owner 474 // implemenetd - Critical damage mod applied to pets from owner diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 9ba4f4237..94660345f 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1628,6 +1628,15 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } + case SE_Double_Melee_Round: + { + if (newbon->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] < base1) { + newbon->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = base1; + newbon->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_DMG_BONUS] = base2; + } + break; + } + case SE_Worn_Endurance_Regen_Cap: newbon->ItemEnduranceRegenCap += base1; break; @@ -2487,6 +2496,20 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } + case SE_Double_Melee_Round: + { + if (AdditiveWornBonus) { + new_bonus->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] += effect_value; + new_bonus->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_DMG_BONUS] += base2; + } + + if (new_bonus->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] < effect_value) { + new_bonus->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; + new_bonus->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_DMG_BONUS] = base2; + } + break; + } + case SE_PercentXPIncrease: { if(new_bonus->XPRateMod < effect_value) @@ -4472,6 +4495,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; break; + case SE_Double_Melee_Round: + spellbonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; + aabonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; + itembonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; + break; + case SE_PercentXPIncrease: spellbonuses.XPRateMod = effect_value; aabonuses.XPRateMod = effect_value; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index d805be19a..c984ee800 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -394,6 +394,11 @@ bool Client::Process() { TriggerDefensiveProcs(auto_attack_target, EQ::invslot::slotPrimary, false); DoAttackRounds(auto_attack_target, EQ::invslot::slotPrimary); + + if (TryDoubleMeleeRoundEffect()) { + DoAttackRounds(auto_attack_target, EQ::invslot::slotPrimary); + } + if (CheckAATimer(aaTimerRampage)) { entity_list.AEAttack(this, 30); } diff --git a/zone/common.h b/zone/common.h index feccc7910..5afde8019 100644 --- a/zone/common.h +++ b/zone/common.h @@ -454,6 +454,7 @@ struct StatBonuses { int32 ExtraAttackChance[2]; // base chance(w/ 2H weapon)=0, amt of extra attacks=1 int32 ExtraAttackChancePrimary[2]; // base chance=0, , amt of extra attacks=1 int32 ExtraAttackChanceSecondary[2]; // base chance=0, , amt of extra attacks=1 + int32 DoubleMeleeRound[2]; // base chance=0, damage mod=1 int32 DoTShielding; int32 DivineSaveChance[2]; // Second Chance (base1 = chance, base2 = spell on trigger) uint32 DeathSave[4]; // Death Pact [0](value = 1 partial 2 = full) [1]=slot [2]=LvLimit [3]=HealAmt @@ -671,6 +672,8 @@ namespace SBIndex { constexpr uint16 FINISHING_EFFECT_DMG = 1; // SPA 278, 439, 217 constexpr uint16 FINISHING_EFFECT_LEVEL_MAX = 0; // SPA 440, 345, 346 constexpr uint16 FINISHING_EFFECT_LEVEL_CHANCE_BONUS = 1; // SPA 440, 345, 346 + constexpr uint16 DOUBLE_MELEE_ROUND_CHANCE = 0; // SPA 471 + constexpr uint16 DOUBLE_MELEE_ROUND_DMG_BONUS = 1; // SPA 471 }; diff --git a/zone/mob.cpp b/zone/mob.cpp index ab68f0f6c..bf537e7ce 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -471,6 +471,8 @@ Mob::Mob( AssistAggro = false; npc_assist_cap = 0; + use_double_melee_round_dmg_bonus = false; + #ifdef BOTS m_manual_follow = false; #endif @@ -4841,6 +4843,10 @@ int16 Mob::GetMeleeDamageMod_SE(uint16 skill) dmg_mod += itembonuses.DamageModifier3[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.DamageModifier3[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.DamageModifier3[EQ::skills::HIGHEST_SKILL + 1] + itembonuses.DamageModifier3[skill] + spellbonuses.DamageModifier3[skill] + aabonuses.DamageModifier3[skill]; + if (GetUseDoubleMeleeRoundDmgBonus()) { + dmg_mod += itembonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_DMG_BONUS] + spellbonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_DMG_BONUS] + aabonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_DMG_BONUS]; + } + if(dmg_mod < -100) dmg_mod = -100; @@ -4964,6 +4970,20 @@ void Mob::MeleeLifeTap(int32 damage) { } } +bool Mob::TryDoubleMeleeRoundEffect() { + + auto chance = aabonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] + itembonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] + + spellbonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE]; + + if (chance && zone->random.Roll(chance)) { + SetUseDoubleMeleeRoundDmgBonus(true); + return true; + } + + SetUseDoubleMeleeRoundDmgBonus(false); + return false; +} + bool Mob::TryReflectSpell(uint32 spell_id) { if (!spells[spell_id].reflectable) diff --git a/zone/mob.h b/zone/mob.h index 49b3fa2c8..2f0c166b0 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -844,6 +844,10 @@ public: bool CanFocusUseRandomEffectivenessByType(focusType type); int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0); + bool TryDoubleMeleeRoundEffect(); + bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; } + inline void SetUseDoubleMeleeRoundDmgBonus(bool val) { use_double_melee_round_dmg_bonus = val; } + void CastSpellOnLand(Mob* caster, int32 spell_id); void FocusProcLimitProcess(); bool ApplyFocusProcLimiter(int32 spell_id, int buffslot = -1); @@ -1498,6 +1502,7 @@ protected: bool has_twohandbluntequiped; bool has_twohanderequipped; bool has_duelweaponsequiped; + bool use_double_melee_round_dmg_bonus; bool can_facestab; bool has_numhits; bool has_MGB; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a8626c570..5160e32ce 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3237,6 +3237,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Ff_Value_Max: case SE_AddExtraAttackPct_1h_Primary: case SE_AddExtraAttackPct_1h_Secondary: + case SE_Double_Melee_Round: case SE_Skill_Base_Damage_Mod: case SE_Worn_Endurance_Regen_Cap: case SE_Buy_AA_Rank: