From e0f6243cd55f0edb1a16664f16b5afc56d4f3439 Mon Sep 17 00:00:00 2001 From: Fluttershy-git <58604911+Fluttershy-git@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:40:19 +0200 Subject: [PATCH] [Paladin] Initial PTR changes (#9605) --- engine/class_modules/paladin/sc_paladin.cpp | 192 +++++++++++------- engine/class_modules/paladin/sc_paladin.hpp | 143 ++++++++----- .../paladin/sc_paladin_protection.cpp | 73 ++++--- .../paladin/sc_paladin_retribution.cpp | 5 +- 4 files changed, 265 insertions(+), 148 deletions(-) diff --git a/engine/class_modules/paladin/sc_paladin.cpp b/engine/class_modules/paladin/sc_paladin.cpp index 4721e3ba0c5..ff23a4eff8c 100644 --- a/engine/class_modules/paladin/sc_paladin.cpp +++ b/engine/class_modules/paladin/sc_paladin.cpp @@ -145,20 +145,28 @@ avenging_wrath_buff_t::avenging_wrath_buff_t( paladin_t* p ) healing_modifier( 0.0 ), crit_bonus( 0.0 ) { - // Map modifiers appropriately based on spec - healing_modifier = p->talents.avenging_wrath->effectN( 2 ).percent(); - crit_bonus = 0; - damage_modifier = p->talents.avenging_wrath->effectN( 2 ).percent(); + if ( !p->is_ptr() ) + { + // Map modifiers appropriately based on spec + healing_modifier = p->talents.avenging_wrath->effectN( 2 ).percent(); + crit_bonus = 0; + damage_modifier = p->talents.avenging_wrath->effectN( 2 ).percent(); + } + else + { + healing_modifier = p->talents.avenging_wrath->effectN( 1 ).percent(); + damage_modifier = p->talents.avenging_wrath->effectN( 1 ).percent(); + crit_bonus = p->talents.avenging_wrath->ok() ? p->talents.avenging_wrath->effectN( 3 ).percent() : 0; + } + + if ( !p->is_ptr() && p->talents.avenging_wrath_might->ok() ) + crit_bonus = p->talents.avenging_wrath_might->effectN( 1 ).percent(); if ( p->talents.sanctified_wrath->ok() ) { - // the tooltip doesn't say this, but the spelldata does base_buff_duration *= 1.0 + p->talents.sanctified_wrath->effectN( 1 ).percent(); } - if ( p->talents.avenging_wrath_might->ok() ) - crit_bonus = p->talents.avenging_wrath_might->effectN( 1 ).percent(); - if ( p->talents.divine_wrath->ok() ) { base_buff_duration += p->talents.divine_wrath->effectN( 1 ).time_value(); @@ -742,7 +750,7 @@ struct divine_shield_t : public paladin_spell_t bool ready() override { - if ( player->debuffs.forbearance->check() ) + if ( p()->debuffs.forbearance->check() || !( p()->is_ptr() && p()->talents.lights_revocation->ok() ) ) return false; return paladin_spell_t::ready(); @@ -757,6 +765,9 @@ struct divine_steed_t : public paladin_spell_t : paladin_spell_t( "divine_steed", p, p->find_class_spell( "Divine Steed" ) ) { parse_options( options_str ); + background = false; + if ( p->talents.cavalier->ok() ) + cooldown->charges += p->talents.cavalier->effectN( 1 ).base_value(); } void execute() override @@ -856,7 +867,7 @@ struct lay_on_hands_t : public paladin_heal_t // Uther's Counsel also reduces cooldown if ( p->talents.uthers_counsel->ok()) { - cooldown->duration *= 1.0 + p->talents.uthers_counsel->effectN( 2 ).percent(); + cooldown->duration *= 1.0 + p->talents.uthers_counsel->effectN( 1 ).percent(); } may_crit = false; @@ -1219,7 +1230,7 @@ struct melee_t : public paladin_melee_attack_t { paladin_melee_attack_t::impact( s ); - if ( p()->talents.seal_of_the_crusader->ok() ) + if ( !p()->is_ptr() && p()->talents.seal_of_the_crusader->ok() ) { seal_of_the_crusader->execute_on_target( s->target ); } @@ -1563,7 +1574,7 @@ struct word_of_glory_t : public holy_power_consumer_t if ( p()->buffs.shining_light_free->up() && p()->buffs.divine_purpose->up() ) // Shining Light does not benefit from divine purpose am /= 1.0 + p()->spells.divine_purpose_buff->effectN( 2 ).percent(); - if ( p()->talents.strength_of_conviction->ok() && p()->standing_in_consecration() ) + if ( !p()->is_ptr() && p()->talents.strength_of_conviction->ok() && p()->standing_in_consecration() ) { am *= 1.0 + p()->talents.strength_of_conviction->effectN( 1 ).percent(); } @@ -1645,7 +1656,7 @@ judgment_t::judgment_t( paladin_t* p, util::string_view name ) : base_multiplier *= 1.0 + p->talents.zealots_paragon->effectN( 3 ).percent(); } - if ( p->talents.seal_of_alacrity->ok() ) + if ( !p->is_ptr() && p->talents.seal_of_alacrity->ok() ) { cooldown->duration += timespan_t::from_millis( p->talents.seal_of_alacrity->effectN( 2 ).base_value() ); } @@ -1736,7 +1747,7 @@ double judgment_t::action_multiplier() const { double am = paladin_melee_attack_t::action_multiplier(); - if ( p()->talents.justification->ok() ) + if ( !p()->is_ptr() && p()->talents.justification->ok() ) am *= 1.0 + p()->talents.justification->effectN( 1 ).percent(); // Increase only if active Judgment, Divine Toll handling on judgment_ret_t @@ -2990,7 +3001,7 @@ struct shield_of_the_righteous_t : public holy_power_consumer_tbuffs.bulwark_of_righteous_fury->stack_value(); } - if ( p()->talents.strength_of_conviction->ok() && p()->standing_in_consecration() ) + if ( !p()->is_ptr() && p()->talents.strength_of_conviction->ok() && p()->standing_in_consecration() ) { am *= 1.0 + p()->talents.strength_of_conviction->effectN( 1 ).percent(); } @@ -3510,7 +3521,7 @@ void paladin_t::create_actions() active.armament[ HOLY_BULWARK ] = new holy_bulwark_t( this ); active.armament[ SACRED_WEAPON ] = new sacred_weapon_t( this ); - if ( talents.incandescence->ok() ) + if ( !is_ptr() && talents.incandescence->ok() ) { active.incandescence = new incandescence_t( this ); } @@ -3604,7 +3615,12 @@ void paladin_t::trigger_forbearance( player_t* target ) auto buff = debug_cast( target->debuffs.forbearance ); buff->paladin = this; - buff->trigger(); + + timespan_t dur = buff->base_buff_duration; + if ( is_ptr() && talents.holy_reprieve->ok() ) + dur += timespan_t::from_millis( talents.holy_reprieve->effectN( 1 ).base_value() ); + + buff->trigger( dur ); } int paladin_t::get_local_enemies( double distance ) const @@ -3793,8 +3809,6 @@ void paladin_t::create_buffs() ->set_max_stack( 5 ); // Buff has no stacks, but can have up to 5 different values. buffs.shield_of_vengeance = new buffs::shield_of_vengeance_buff_t( this ); - buffs.holy_avenger = - make_buff( this, "holy_avenger", talents.holy_avenger )->set_cooldown( 0_ms ); // handled by the ability buffs.devotion_aura = make_buff( this, "devotion_aura", find_spell( 465 ) ) ->set_default_value( find_spell( 465 )->effectN( 1 ).percent() ); @@ -3809,7 +3823,7 @@ void paladin_t::create_buffs() ->set_default_value_from_effect( 1 ) ->add_invalidate( CACHE_BONUS_ARMOR ); - if ( talents.seal_of_order->ok() ) + if ( !is_ptr() && talents.seal_of_order->ok() ) { buffs.blessing_of_dusk->set_stack_change_callback( [ this ]( buff_t* b, int, int new_ ) { for ( auto a : action_list ) @@ -4166,7 +4180,7 @@ void paladin_t::init_special_effects() { player_t::init_special_effects(); - if ( talents.touch_of_light->ok() ) + if ( !is_ptr() && talents.touch_of_light->ok() ) { auto const touch_of_light_driver = new special_effect_t( this ); touch_of_light_driver->name_str = "touch_of_light_driver"; @@ -4260,62 +4274,97 @@ void paladin_t::init_spells() // Shared talents talents.lay_on_hands = find_talent_spell( talent_tree::CLASS, "Lay on Hands" ); - talents.blessing_of_freedom = find_talent_spell( talent_tree::CLASS, "Blessing of Freedom" ); - talents.hammer_of_wrath = find_talent_spell( talent_tree::CLASS, "Hammer of Wrath" ); talents.auras_of_the_resolute = find_talent_spell( talent_tree::CLASS, "Auras of the Resolute" ); - talents.auras_of_swift_vengeance = find_talent_spell( talent_tree::CLASS, "Auras of Swift Vengeance" ); - talents.blinding_light = find_talent_spell( talent_tree::CLASS, "Blinding Light" ); - talents.repentance = find_talent_spell( talent_tree::CLASS, "Repentance" ); - talents.divine_steed = find_talent_spell( talent_tree::CLASS, 190784 ); + talents.hammer_of_wrath = find_talent_spell( talent_tree::CLASS, "Hammer of Wrath" ); + + talents.cleanse_toxins = find_talent_spell( talent_tree::CLASS, "Cleanse Toxins" ); + if (is_ptr()) talents.empyreal_ward = find_talent_spell( talent_tree::CLASS, "Empyreal Ward" ); talents.fist_of_justice = find_talent_spell( talent_tree::CLASS, "Fist of Justice" ); - talents.holy_aegis = find_talent_spell( talent_tree::CLASS, "Holy Aegis" ); - talents.cavalier = find_talent_spell( talent_tree::CLASS, "Cavalier" ); - talents.seasoned_warhorse = find_talent_spell( talent_tree::CLASS, "Seasoned Warhorse" ); - talents.seal_of_alacrity = find_talent_spell( talent_tree::CLASS, "Seal of Alacrity" ); - talents.golden_path = find_talent_spell( talent_tree::CLASS, "Golden Path" ); - talents.judgment_of_light = find_talent_spell( talent_tree::CLASS, "Judgment of Light" ); - //Avenging Wrath spell - talents.avenging_wrath = find_talent_spell( talent_tree::CLASS, "Avenging Wrath" ); + talents.repentance = find_talent_spell( talent_tree::CLASS, "Repentance" ); + talents.blinding_light = find_talent_spell( talent_tree::CLASS, "Blinding Light" ); talents.turn_evil = find_talent_spell( talent_tree::CLASS, "Turn Evil" ); + + if (is_ptr()) talents.a_just_reward = find_talent_spell( talent_tree::CLASS, "A Just Reward" ); + talents.afterimage = find_talent_spell( talent_tree::CLASS, "Afterimage" ); + talents.healing_hands = find_talent_spell( talent_tree::CLASS, "Healing Hands" ); + talents.divine_steed = find_talent_spell( talent_tree::CLASS, "Divine Steed" ); + if (is_ptr()) talents.lights_countenance = find_talent_spell( talent_tree::CLASS, "Light's Countenance" ); + talents.greater_judgment = find_talent_spell( talent_tree::CLASS, "Greater Judgment" ); + if (is_ptr()) talents.wrench_evil = find_talent_spell( talent_tree::CLASS, "Wrench Evil" ); + if (is_ptr()) talents.stand_against_evil = find_talent_spell( talent_tree::CLASS, "Stand Against Evil" ); + + if (is_ptr()) talents.holy_reprieve = find_talent_spell( talent_tree::CLASS, "Holy Reprieve" ); + talents.cavalier = find_talent_spell( talent_tree::CLASS, "Cavalier" ); + if (is_ptr()) talents.divine_spurs = find_talent_spell( talent_tree::CLASS, "Divine Spurs" ); + if (is_ptr()) talents.steed_of_liberty = find_talent_spell( talent_tree::CLASS, "Steed of Liberty" ); + talents.blessing_of_freedom = find_talent_spell( talent_tree::CLASS, "Blessing of Freedom" ); talents.rebuke = find_talent_spell( talent_tree::CLASS, "Rebuke" ); - talents.seal_of_mercy = find_talent_spell( talent_tree::CLASS, "Seal of Mercy" ); - talents.cleanse_toxins = find_talent_spell( talent_tree::CLASS, "Cleanse Toxins" ); + + talents.obduracy = find_talent_spell( talent_tree::CLASS, "Obduracy" ); + talents.divine_toll = find_talent_spell( talent_tree::CLASS, "Divine Toll" ); + talents.unbound_freedom = find_talent_spell( talent_tree::CLASS, "Unbound Freedom" ); + talents.sanctified_plates = find_talent_spell( talent_tree::CLASS, "Sanctified Plates" ); + talents.punishment = find_talent_spell( talent_tree::CLASS, "Punishment" ); + + talents.divine_reach = find_talent_spell( talent_tree::CLASS, "Divine Reach" ); talents.blessing_of_sacrifice = find_talent_spell( talent_tree::CLASS, "Blessing of Sacrifice" ); - //Judgment causes the target to take 25% more damage from your next holy power spending ability - talents.greater_judgment = find_talent_spell( talent_tree::CLASS, "Greater Judgment" ); - talents.afterimage = find_talent_spell( talent_tree::CLASS, "Afterimage" ); - talents.recompense = find_talent_spell( talent_tree::CLASS, "Recompense" ); - talents.sacrifice_of_the_just = find_talent_spell( talent_tree::CLASS, "Sacrifice of the Just" ); + talents.divine_resonance = find_talent_spell( talent_tree::CLASS, "Divine Resonance" ); + talents.quickened_invocation = find_talent_spell( talent_tree::CLASS, "Quickened Invocation" ); talents.blessing_of_protection = find_talent_spell( talent_tree::CLASS, "Blessing of Protection" ); - talents.holy_avenger = find_talent_spell( talent_tree::CLASS, "Holy Avenger" ); + talents.consecrated_ground = find_talent_spell( talent_tree::CLASS, "Consecrated Ground" ); + + talents.holy_aegis = find_talent_spell( talent_tree::CLASS, "Holy Aegis" ); + talents.sacrifice_of_the_just = find_talent_spell( talent_tree::CLASS, "Sacrifice of the Just" ); + talents.recompense = find_talent_spell( talent_tree::CLASS, "Recompense" ); + if (is_ptr()) talents.sacred_strength = find_talent_spell( talent_tree::CLASS, "Sacred Strength" ); talents.divine_purpose = find_talent_spell( talent_tree::CLASS, "Divine Purpose" ); - talents.obduracy = find_talent_spell( talent_tree::CLASS, "Obduracy" ); - talents.touch_of_light = find_talent_spell( talent_tree::CLASS, "Touch of Light" ); - talents.incandescence = find_talent_spell( talent_tree::CLASS, "Incandescence" ); - talents.of_dusk_and_dawn = find_talent_spell( talent_tree::CLASS, "Of Dusk and Dawn" ); + talents.improved_blessing_of_protection = find_talent_spell( talent_tree::CLASS, "Improved Blessing of Protection" ); talents.unbreakable_spirit = find_talent_spell( talent_tree::CLASS, "Unbreakable Spirit" ); + + talents.lightforged_blessing = find_talent_spell( talent_tree::CLASS, "Lightforged Blessing" ); + if (is_ptr()) talents.lead_the_charge = find_talent_spell( talent_tree::CLASS, "Lead the Charge" ); + if ( is_ptr() ) talents.worthy_sacrifice = find_talent_spell( talent_tree::CLASS, "Worthy Sacrifice" ); + if ( is_ptr() ) talents.righteous_protection = find_talent_spell( talent_tree::CLASS, "Righteous Protection" ); + if ( is_ptr() ) talents.holy_ritual= find_talent_spell( talent_tree::CLASS, "Holy Ritual"); + if ( is_ptr() ) talents.blessed_calling = find_talent_spell( talent_tree::CLASS, "Blessed Calling" ); + if ( is_ptr() ) talents.inspired_guard = find_talent_spell( talent_tree::CLASS, "Inspired Guard" ); + talents.judgment_of_light = find_talent_spell( talent_tree::CLASS, "Judgment of Light" ); + + talents.faiths_armor = find_talent_spell( talent_tree::CLASS, "Faith's Armor" ); + if (is_ptr()) talents.stoicism = find_talent_spell( talent_tree::CLASS, "Stoicism" ); talents.seal_of_might = find_talent_spell( talent_tree::CLASS, "Seal of Might" ); - talents.improved_blessing_of_protection = find_talent_spell( talent_tree::CLASS, "Improved Blessing of Protection" ); talents.seal_of_the_crusader = find_talent_spell( talent_tree::CLASS, "Seal of the Crusader" ); - talents.seal_of_order = find_talent_spell( talent_tree::CLASS, "Seal of Order" ); - talents.zealots_paragon = find_talent_spell( talent_tree::CLASS, "Zealot's Paragon" ); + // ZP/VW in Prot/Ret Init + if ( is_ptr() ) talents.eye_for_an_eye = find_talent_spell( talent_tree::CLASS, "Eye for an Eye" ); + talents.golden_path = find_talent_spell( talent_tree::CLASS, "Golden Path" ); + if ( is_ptr() ) talents.selfless_healer = find_talent_spell( talent_tree::CLASS, "Selfless Healer" ); - // spec talents shared among specs - talents.avenging_wrath_might = find_talent_spell( talent_tree::SPECIALIZATION, "Avenging Wrath: Might" ); - talents.relentless_inquisitor = find_talent_spell( talent_tree::SPECIALIZATION, "Relentless Inquisitor" ); + talents.of_dusk_and_dawn = find_talent_spell( talent_tree::CLASS, "Of Dusk and Dawn" ); + if (is_ptr()) talents.lightbearer = find_talent_spell( talent_tree::CLASS, "Lightbearer" ); + if (is_ptr()) talents.lights_revocation = find_talent_spell( talent_tree::CLASS, "Light's Revocation" ); - talents.divine_toll = find_talent_spell( talent_tree::CLASS, "Divine Toll" ); - talents.divine_resonance = find_talent_spell( talent_tree::CLASS, "Divine Resonance" ); - talents.quickened_invocation = find_talent_spell( talent_tree::CLASS, "Quickened Invocation" ); - talents.faiths_armor = find_talent_spell( talent_tree::CLASS, "Faith's Armor" ); - talents.strength_of_conviction = find_talent_spell( talent_tree::CLASS, "Strength of Conviction" ); + // This is now in the Spec Tree for every Paladin + talents.avenging_wrath = find_talent_spell( is_ptr() ? talent_tree::SPECIALIZATION : talent_tree::CLASS , "Avenging Wrath" ); - talents.justification = find_talent_spell( talent_tree::CLASS, "Justification" ); - talents.punishment = find_talent_spell( talent_tree::CLASS, "Punishment" ); - talents.sanctified_plates = find_talent_spell( talent_tree::CLASS, "Sanctified Plates" ); - talents.lightforged_blessing = find_talent_spell( talent_tree::CLASS, "Lightforged Blessing" ); - talents.crusaders_reprieve = find_talent_spell( talent_tree::CLASS, "Crusader's Reprieve" ); - talents.fading_light = find_talent_spell( talent_tree::CLASS, "Fading Light" ); + + if ( !is_ptr() ) + { + talents.auras_of_swift_vengeance = find_talent_spell( talent_tree::CLASS, "Auras of Swift Vengeance" ); + talents.seasoned_warhorse = find_talent_spell( talent_tree::CLASS, "Seasoned Warhorse" ); + talents.seal_of_alacrity = find_talent_spell( talent_tree::CLASS, "Seal of Alacrity" ); + talents.seal_of_mercy = find_talent_spell( talent_tree::CLASS, "Seal of Mercy" ); + talents.touch_of_light = find_talent_spell( talent_tree::CLASS, "Touch of Light" ); + talents.incandescence = find_talent_spell( talent_tree::CLASS, "Incandescence" ); + talents.seal_of_order = find_talent_spell( talent_tree::CLASS, "Seal of Order" ); + talents.avenging_wrath_might = find_talent_spell( talent_tree::SPECIALIZATION, "Avenging Wrath: Might" ); + talents.relentless_inquisitor = find_talent_spell( talent_tree::SPECIALIZATION, "Relentless Inquisitor" ); + + talents.strength_of_conviction = find_talent_spell( talent_tree::CLASS, "Strength of Conviction" ); + + talents.justification = find_talent_spell( talent_tree::CLASS, "Justification" ); + talents.crusaders_reprieve = find_talent_spell( talent_tree::CLASS, "Crusader's Reprieve" ); + talents.fading_light = find_talent_spell( talent_tree::CLASS, "Fading Light" ); + } // Hero Talents talents.lightsmith.holy_armaments = find_talent_spell( talent_tree::HERO, "Holy Armaments" ); @@ -4515,8 +4564,7 @@ double paladin_t::composite_attribute_multiplier( attribute_e attr ) const if ( passives.aegis_of_light -> ok() ) m *= 1.0 + passives.aegis_of_light -> effectN( 1 ).percent(); - // 2023-02-24 Sanctified Plates currently doesn't give the stamina bonus, despite an apparent bugfix (it worked before) - if ( bugs && talents.sanctified_plates->ok() ) + if ( talents.sanctified_plates->ok() ) m *= 1.0 + talents.sanctified_plates->effectN( 1 ).percent(); // This literally never gets triggered. Apparently, invalidating the Stamina cache doesn't recalculate Stamina? @@ -4667,7 +4715,7 @@ double paladin_t::composite_melee_haste() const if ( buffs.relentless_inquisitor->up() ) h /= 1.0 + buffs.relentless_inquisitor->stack_value(); - if ( talents.seal_of_alacrity->ok() ) + if ( !is_ptr() && talents.seal_of_alacrity->ok() ) h /= 1.0 + talents.seal_of_alacrity->effectN( 1 ).percent(); if ( buffs.rush_of_light->up() ) @@ -4706,7 +4754,7 @@ double paladin_t::composite_spell_haste() const if ( buffs.relentless_inquisitor->up() ) h /= 1.0 + buffs.relentless_inquisitor->stack_value(); - if ( talents.seal_of_alacrity->ok() ) + if ( !is_ptr() && talents.seal_of_alacrity->ok() ) h /= 1.0 + talents.seal_of_alacrity->effectN( 1 ).percent(); if ( buffs.rush_of_light->up() ) @@ -4876,14 +4924,6 @@ double paladin_t::matching_gear_multiplier( attribute_e attr ) const double paladin_t::resource_gain( resource_e resource_type, double amount, gain_t* source, action_t* action ) { - if ( resource_type == RESOURCE_HOLY_POWER ) - { - if ( buffs.holy_avenger->up() ) - { - amount *= 1.0 + buffs.holy_avenger->data().effectN( 1 ).percent(); - } - } - double result = player_t::resource_gain( resource_type, amount, source, action ); if ( resource_type == RESOURCE_HOLY_POWER && amount > 0 && ( talents.of_dusk_and_dawn->ok() ) ) diff --git a/engine/class_modules/paladin/sc_paladin.hpp b/engine/class_modules/paladin/sc_paladin.hpp index eca549646c9..b49cc319ad7 100644 --- a/engine/class_modules/paladin/sc_paladin.hpp +++ b/engine/class_modules/paladin/sc_paladin.hpp @@ -149,6 +149,7 @@ struct paladin_t : public player_t action_t* armament[ NUM_ARMAMENT ]; action_t* sacred_weapon_proc_damage; action_t* sacred_weapon_proc_heal; + action_t* refining_fire; } active; // Buffs @@ -469,59 +470,79 @@ struct paladin_t : public player_t // 0 const spell_data_t* lay_on_hands; - const spell_data_t* blessing_of_freedom; + const spell_data_t* auras_of_the_resolute; const spell_data_t* hammer_of_wrath; + const spell_data_t* cleanse_toxins; - const spell_data_t* auras_of_the_resolute; - const spell_data_t* obduracy; - const spell_data_t* auras_of_swift_vengeance; - const spell_data_t* turn_evil; + const spell_data_t* empyreal_ward; const spell_data_t* fist_of_justice; - const spell_data_t* divine_steed; - const spell_data_t* greater_judgment; const spell_data_t* repentance; const spell_data_t* blinding_light; + const spell_data_t* turn_evil; + + const spell_data_t* a_just_reward; + const spell_data_t* afterimage; + const spell_data_t* healing_hands; // Ret only + const spell_data_t* divine_steed; + const spell_data_t* lights_countenance; + const spell_data_t* greater_judgment; + const spell_data_t* wrench_evil; + const spell_data_t* stand_against_evil; + + const spell_data_t* holy_reprieve; const spell_data_t* cavalier; - const spell_data_t* seasoned_warhorse; + const spell_data_t* divine_spurs; + const spell_data_t* steed_of_liberty; + const spell_data_t* blessing_of_freedom; const spell_data_t* rebuke; // 8 - const spell_data_t* holy_aegis; - const spell_data_t* avenging_wrath; // Spell - const spell_data_t* justification; + const spell_data_t* obduracy; + const spell_data_t* divine_toll; + const spell_data_t* unbound_freedom; + const spell_data_t* sanctified_plates; const spell_data_t* punishment; - const spell_data_t* golden_path; + + const spell_data_t* divine_reach; const spell_data_t* blessing_of_sacrifice; - const spell_data_t* sanctified_plates; + const spell_data_t* divine_resonance; + const spell_data_t* quickened_invocation; const spell_data_t* blessing_of_protection; - const spell_data_t* unbound_freedom; - const spell_data_t* lightforged_blessing; - const spell_data_t* seal_of_mercy; - const spell_data_t* afterimage; + const spell_data_t* consecrated_ground; + + const spell_data_t* holy_aegis; const spell_data_t* sacrifice_of_the_just; const spell_data_t* recompense; - const spell_data_t* unbreakable_spirit; + const spell_data_t* sacred_strength; + const spell_data_t* divine_purpose; const spell_data_t* improved_blessing_of_protection; - const spell_data_t* crusaders_reprieve; + const spell_data_t* unbreakable_spirit; // 20 - const spell_data_t* strength_of_conviction; + const spell_data_t* lightforged_blessing; + const spell_data_t* lead_the_charge; + const spell_data_t* worthy_sacrifice; + const spell_data_t* righteous_protection; + const spell_data_t* holy_ritual; + const spell_data_t* blessed_calling; + const spell_data_t* inspired_guard; const spell_data_t* judgment_of_light; - const spell_data_t* seal_of_might; - const spell_data_t* divine_purpose; - const spell_data_t* seal_of_alacrity; - const spell_data_t* incandescence; - const spell_data_t* touch_of_light; + const spell_data_t* faiths_armor; - const spell_data_t* of_dusk_and_dawn; - const spell_data_t* divine_toll; + const spell_data_t* stoicism; + const spell_data_t* seal_of_might; const spell_data_t* seal_of_the_crusader; - const spell_data_t* seal_of_order; - const spell_data_t* fading_light; - const spell_data_t* divine_resonance; - const spell_data_t* quickened_invocation; const spell_data_t* zealots_paragon; // Prot only const spell_data_t* vengeful_wrath; // Ret only + const spell_data_t* eye_for_an_eye; + const spell_data_t* golden_path; + const spell_data_t* selfless_healer; + + const spell_data_t* of_dusk_and_dawn; + const spell_data_t* lightbearer; + const spell_data_t* lights_revocation; + + const spell_data_t* avenging_wrath; // Keeping this because it still contains all the spell data needed // Stuff that may come back const spell_data_t* seraphim; // It'll come back :copium: @@ -547,50 +568,57 @@ struct paladin_t : public player_t // Protection // 0 const spell_data_t* avengers_shield; + const spell_data_t* holy_shield; - const spell_data_t* inner_light; - const spell_data_t* redoubt; const spell_data_t* hammer_of_the_righteous; const spell_data_t* blessed_hammer; + + const spell_data_t* inner_light; + const spell_data_t* redoubt; const spell_data_t* grand_crusader; const spell_data_t* shining_light; + const spell_data_t* improved_holy_shield; - const spell_data_t* sanctuary; const spell_data_t* inspiring_vanguard; const spell_data_t* ardent_defender; const spell_data_t* barricade_of_faith; - const spell_data_t* consecration_in_flame; + const spell_data_t* sanctuary; // 8 - const spell_data_t* consecrated_ground; - const spell_data_t* tirions_devotion; + const spell_data_t* refining_fire; const spell_data_t* bulwark_of_order; const spell_data_t* improved_ardent_defender; const spell_data_t* blessing_of_spellwarding; const spell_data_t* light_of_the_titans; - const spell_data_t* strength_in_adversity; - const spell_data_t* crusaders_resolve; + const spell_data_t* tirions_devotion; + const spell_data_t* consecration_in_flame; + const spell_data_t* tyrs_enforcer; const spell_data_t* relentless_inquisitor; const spell_data_t* avenging_wrath_might; const spell_data_t* sentinel; const spell_data_t* seal_of_charity; const spell_data_t* faith_in_the_light; + + const spell_data_t* soaring_shield; const spell_data_t* seal_of_reprisal; - const spell_data_t* bastion_of_light; const spell_data_t* guardian_of_ancient_kings; const spell_data_t* hand_of_the_protector; const spell_data_t* crusaders_judgment; // 20 const spell_data_t* focused_enmity; - const spell_data_t* soaring_shield; const spell_data_t* gift_of_the_golden_valkyr; - const spell_data_t* uthers_counsel; const spell_data_t* sanctified_wrath; + const spell_data_t* uthers_counsel; + + const spell_data_t* strength_in_adversity; + const spell_data_t* crusaders_resolve; const spell_data_t* ferren_marcuss_fervor; const spell_data_t* eye_of_tyr; const spell_data_t* resolute_defender; + const spell_data_t* bastion_of_light; + const spell_data_t* moment_of_glory; const spell_data_t* bulwark_of_righteous_fury; const spell_data_t* inmost_light; @@ -730,6 +758,21 @@ struct paladin_t : public player_t const spell_data_t* suns_avatar; } herald_of_the_sun; + // Remove after 11.0.5 + const spell_data_t* auras_of_swift_vengeance; + const spell_data_t* seasoned_warhorse; + const spell_data_t* justification; + const spell_data_t* seal_of_mercy; + const spell_data_t* crusaders_reprieve; + const spell_data_t* strength_of_conviction; + const spell_data_t* seal_of_alacrity; + const spell_data_t* incandescence; + const spell_data_t* touch_of_light; + const spell_data_t* seal_of_order; + const spell_data_t* fading_light; + + + } talents; // Paladin options @@ -1122,7 +1165,7 @@ struct paladin_action_t : public Base struct affected_by_t { bool avenging_wrath, judgment, blessing_of_dawn, seal_of_reprisal, seal_of_order, divine_purpose, - divine_purpose_cost; // Shared + divine_purpose_cost, sacred_strength; // Shared bool crusade, highlords_judgment, highlords_judgment_hidden, final_reckoning_st, final_reckoning_aoe, blades_of_light, divine_hammer, ret_t29_2p, ret_t29_4p, rise_from_ash; // Ret bool avenging_crusader; // Holy @@ -1203,6 +1246,8 @@ struct paladin_action_t : public Base this->affected_by.divine_purpose = this->data().affected_by( p->spells.divine_purpose_buff->effectN( 2 ) ); this->affected_by.seal_of_reprisal = this->data().affected_by( p->talents.seal_of_reprisal->effectN( 1 ) ); this->affected_by.blessing_of_dawn = this->data().affected_by( p->find_spell( 385127 )->effectN( 1 ) ); + if ( p->is_ptr() ) + this->affected_by.sacred_strength = this->data().affected_by( p->talents.sacred_strength->effectN( 1 ) ); if ( p->talents.penitence->ok() ) { @@ -1376,7 +1421,7 @@ struct paladin_action_t : public Base // Class talent's Avenging Wrath damage multiplier affects only if base talent is talented (Could still use AW with // only Sentinel/AWM/Crusade/AC talented) - if ( affected_by.avenging_wrath && p()->talents.avenging_wrath->ok() && + if ( affected_by.avenging_wrath && ( p()->is_ptr() || p()->talents.avenging_wrath->ok() ) && ( p()->buffs.avenging_wrath->up() || p()->buffs.sentinel->up() ) ) { am *= 1.0 + p()->buffs.avenging_wrath->get_damage_mod(); @@ -1404,6 +1449,10 @@ struct paladin_action_t : public Base { am *= 1.0 + p()->spells.divine_purpose_buff->effectN( 2 ).percent(); } + if (affected_by.sacred_strength && p()->talents.sacred_strength->ok()) + { + am *= 1.0 + p()->talents.sacred_strength->effectN( 1 ).percent(); + } if ( affected_by.seal_of_reprisal && p()->talents.seal_of_reprisal->ok() ) { @@ -1416,10 +1465,10 @@ struct paladin_action_t : public Base // Get base multiplier double bod_mult = p()->buffs.blessing_of_dawn->value(); // Increase base multiplier by SoO/FL increase - if ( p()->talents.seal_of_order->ok() ) + if ( !p()->is_ptr() && p()->talents.seal_of_order->ok() ) bod_mult += p()->talents.seal_of_order->effectN( 1 ).percent(); // Separating those, in case on of them gets changed. Both do exactly the same to Dawn, though. - if ( p()->talents.fading_light->ok() ) + if ( !p()->is_ptr() && p()->talents.fading_light->ok() ) bod_mult += p()->talents.fading_light->effectN( 1 ).percent(); // Multiply by stack count bod_mult *= p()->buffs.blessing_of_dawn->stack(); @@ -1922,7 +1971,7 @@ struct holy_power_consumer_t : public Base p->procs.divine_purpose->occur(); } - if ( p->talents.incandescence->ok() ) + if ( !p->is_ptr() && p->talents.incandescence->ok() ) { for ( int hopo = 0; hopo < num_hopo_spent; hopo++ ) { diff --git a/engine/class_modules/paladin/sc_paladin_protection.cpp b/engine/class_modules/paladin/sc_paladin_protection.cpp index ba5924ab97e..b95668052c6 100644 --- a/engine/class_modules/paladin/sc_paladin_protection.cpp +++ b/engine/class_modules/paladin/sc_paladin_protection.cpp @@ -177,6 +177,12 @@ struct avengers_shield_base_t : public paladin_spell_t { td( s->target )->debuff.crusaders_resolve->trigger(); } + + if ( p()->is_ptr() && p()->talents.refining_fire->ok() ) + { + p()->active.refining_fire->target = s->target; + p()->active.refining_fire->execute(); + } } double recharge_multiplier( const cooldown_t& cd ) const override @@ -797,6 +803,15 @@ struct redoubt_buff_t : public buff_t } } }; + +struct refining_fire_t : public paladin_spell_t +{ + refining_fire_t( paladin_t* p ) : paladin_spell_t( "refining_fire", p, p->find_spell( 469882 ) ) + { + + } +}; + // Sentinel struct sentinel_t : public paladin_spell_t { @@ -1110,6 +1125,7 @@ void paladin_t::create_prot_actions() { active.divine_toll = new avengers_shield_dt_t( this ); active.divine_resonance = new avengers_shield_dr_t( this ); + active.refining_fire = new refining_fire_t( this ); } action_t* paladin_t::create_action_protection( util::string_view name, util::string_view options_str ) @@ -1216,56 +1232,67 @@ void paladin_t::init_spells_protection() // Talents //0 talents.avengers_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Avenger's Shield" ); - talents.blessed_hammer = find_talent_spell( talent_tree::SPECIALIZATION, "Blessed Hammer" ); + + talents.holy_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Holy Shield" ); talents.hammer_of_the_righteous = find_talent_spell( talent_tree::SPECIALIZATION, "Hammer of the Righteous" ); - talents.redoubt = find_talent_spell( talent_tree::SPECIALIZATION, "Redoubt" ); + talents.blessed_hammer = find_talent_spell( talent_tree::SPECIALIZATION, "Blessed Hammer" ); + talents.inner_light = find_talent_spell( talent_tree::SPECIALIZATION, "Inner Light" ); - talents.holy_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Holy Shield" ); + talents.redoubt = find_talent_spell( talent_tree::SPECIALIZATION, "Redoubt" ); talents.grand_crusader = find_talent_spell( talent_tree::SPECIALIZATION, "Grand Crusader" ); talents.shining_light = find_talent_spell( talent_tree::SPECIALIZATION, "Shining Light" ); - talents.consecrated_ground = find_talent_spell( talent_tree::SPECIALIZATION, "Consecrated Ground" ); + + talents.improved_holy_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Improved Holy Shield" ); talents.inspiring_vanguard = find_talent_spell( talent_tree::SPECIALIZATION, "Inspiring Vanguard" ); talents.ardent_defender = find_talent_spell( talent_tree::SPECIALIZATION, "Ardent Defender" ); talents.barricade_of_faith = find_talent_spell( talent_tree::SPECIALIZATION, "Barricade of Faith" ); - talents.consecration_in_flame = find_talent_spell( talent_tree::SPECIALIZATION, "Consecration in Flame" ); + talents.sanctuary = find_talent_spell( talent_tree::SPECIALIZATION, "Sanctuary" ); + if ( !is_ptr() ) talents.consecrated_ground = find_talent_spell( talent_tree::SPECIALIZATION, "Consecrated Ground" ); //8 - talents.sanctuary = find_talent_spell( talent_tree::SPECIALIZATION, "Sanctuary" ); - talents.improved_holy_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Improved Holy Shield" ); + if ( is_ptr() ) talents.refining_fire = find_talent_spell( talent_tree::SPECIALIZATION, "Refining Fire" ); talents.bulwark_of_order = find_talent_spell( talent_tree::SPECIALIZATION, "Bulwark of Order" ); talents.improved_ardent_defender = find_talent_spell( talent_tree::SPECIALIZATION, "Improved Ardent Defender" ); talents.blessing_of_spellwarding = find_talent_spell( talent_tree::SPECIALIZATION, "Blessing of Spellwarding" ); talents.light_of_the_titans = find_talent_spell( talent_tree::SPECIALIZATION, "Light of the Titans" ); - talents.strength_in_adversity = find_talent_spell( talent_tree::SPECIALIZATION, "Strength in Adversity" ); - talents.crusaders_resolve = find_talent_spell( talent_tree::SPECIALIZATION, "Crusader's Resolve" ); + talents.tirions_devotion = find_talent_spell( talent_tree::SPECIALIZATION, "Tirion's Devotion" ); + talents.consecration_in_flame = find_talent_spell( talent_tree::SPECIALIZATION, "Consecration in Flame" ); + talents.tyrs_enforcer = find_talent_spell( talent_tree::SPECIALIZATION, "Tyr's Enforcer" ); talents.relentless_inquisitor = find_talent_spell( talent_tree::SPECIALIZATION, "Relentless Inquisitor" ); talents.avenging_wrath_might = find_talent_spell( talent_tree::SPECIALIZATION, "Avenging Wrath: Might" ); talents.sentinel = find_talent_spell( talent_tree::SPECIALIZATION, "Sentinel" ); - talents.hand_of_the_protector = find_talent_spell( talent_tree::SPECIALIZATION, "Hand of the Protector" ); - talents.resolute_defender = find_talent_spell( talent_tree::SPECIALIZATION, "Resolute Defender" ); - talents.bastion_of_light = find_talent_spell( talent_tree::SPECIALIZATION, "Bastion of Light" ); + talents.seal_of_charity = find_talent_spell( talent_tree::SPECIALIZATION, "Seal of Charity" ); + talents.faith_in_the_light = find_talent_spell( talent_tree::SPECIALIZATION, "Faith in the Light" ); + + talents.soaring_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Soaring Shield" ); + talents.seal_of_reprisal = find_talent_spell( talent_tree::SPECIALIZATION, "Seal of Reprisal" ); talents.guardian_of_ancient_kings = find_talent_spell( talent_tree::SPECIALIZATION, "Guardian of Ancient Kings" ); + talents.hand_of_the_protector = find_talent_spell( talent_tree::SPECIALIZATION, "Hand of the Protector" ); talents.crusaders_judgment = find_talent_spell( talent_tree::SPECIALIZATION, "Crusader's Judgment" ); - talents.uthers_counsel = find_talent_spell( talent_tree::SPECIALIZATION, "Uther's Counsel" ); + //20 talents.focused_enmity = find_talent_spell( talent_tree::SPECIALIZATION, "Focused Enmity" ); - talents.soaring_shield = find_talent_spell( talent_tree::SPECIALIZATION, "Soaring Shield" ); talents.gift_of_the_golden_valkyr = find_talent_spell( talent_tree::SPECIALIZATION, "Gift of the Golden Val'kyr" ); - talents.eye_of_tyr = find_talent_spell( talent_tree::SPECIALIZATION, "Eye of Tyr" ); - talents.righteous_protector = find_talent_spell( talent_tree::SPECIALIZATION, "Righteous Protector" ); - talents.faith_in_the_light = find_talent_spell( talent_tree::SPECIALIZATION, "Faith in the Light" ); + talents.sanctified_wrath = find_talent_spell( talent_tree::SPECIALIZATION, "Sanctified Wrath" ); + talents.uthers_counsel = find_talent_spell( talent_tree::SPECIALIZATION, "Uther's Counsel" ); + + talents.strength_in_adversity = find_talent_spell( talent_tree::SPECIALIZATION, "Strength in Adversity" ); + talents.crusaders_resolve = find_talent_spell( talent_tree::SPECIALIZATION, "Crusader's Resolve" ); talents.ferren_marcuss_fervor = find_talent_spell( talent_tree::SPECIALIZATION, "Ferren Marcus's Fervor" ); - talents.final_stand = find_talent_spell( talent_tree::SPECIALIZATION, "Final Stand" ); + talents.eye_of_tyr = find_talent_spell( talent_tree::SPECIALIZATION, "Eye of Tyr" ); + talents.resolute_defender = find_talent_spell( talent_tree::SPECIALIZATION, "Resolute Defender" ); + talents.bastion_of_light = find_talent_spell( talent_tree::SPECIALIZATION, "Bastion of Light" ); + talents.moment_of_glory = find_talent_spell( talent_tree::SPECIALIZATION, "Moment of Glory" ); talents.bulwark_of_righteous_fury = find_talent_spell( talent_tree::SPECIALIZATION, "Bulwark of Righteous Fury" ); + talents.inmost_light = find_talent_spell( talent_tree::SPECIALIZATION, "Inmost Light" ); + talents.final_stand = find_talent_spell( talent_tree::SPECIALIZATION, "Final Stand" ); + talents.righteous_protector = find_talent_spell( talent_tree::SPECIALIZATION, "Righteous Protector" ); + + talents.zealots_paragon = find_talent_spell( talent_tree::CLASS, "Zealot's Paragon" ); - talents.sanctified_wrath = find_talent_spell( talent_tree::SPECIALIZATION, "Sanctified Wrath" ); - talents.inmost_light = find_talent_spell( talent_tree::SPECIALIZATION, "Inmost Light" ); - talents.seal_of_charity = find_talent_spell( talent_tree::SPECIALIZATION, "Seal of Charity" ); - talents.tirions_devotion = find_talent_spell( talent_tree::SPECIALIZATION, "Tirion's Devotion" ); - talents.seal_of_reprisal = find_talent_spell( talent_tree::SPECIALIZATION, "Seal of Reprisal" ); // Spec passives and useful spells spec.protection_paladin = find_specialization_spell( "Protection Paladin" ); diff --git a/engine/class_modules/paladin/sc_paladin_retribution.cpp b/engine/class_modules/paladin/sc_paladin_retribution.cpp index 10f841d85cd..45a1fac0030 100644 --- a/engine/class_modules/paladin/sc_paladin_retribution.cpp +++ b/engine/class_modules/paladin/sc_paladin_retribution.cpp @@ -22,7 +22,7 @@ namespace buffs { set_refresh_behavior( buff_refresh_behavior::DISABLED ); // TODO(mserrano): fix this when Blizzard turns the spelldata back to sane // values - if ( p->talents.avenging_wrath->ok() ) + if ( p->is_ptr() || ( !p->is_ptr() && p->talents.avenging_wrath->ok() ) ) damage_modifier = data().effectN( 1 ).percent() / 10.0; haste_bonus = data().effectN( 3 ).percent() / 10.0; @@ -1663,7 +1663,7 @@ void paladin_t::init_spells_retribution() talents.crusade = find_talent_spell( talent_tree::SPECIALIZATION, "Crusade" ); talents.radiant_glory = find_talent_spell( talent_tree::SPECIALIZATION, "Radiant Glory" ); talents.empyrean_power = find_talent_spell( talent_tree::SPECIALIZATION, "Empyrean Power" ); - talents.consecrated_ground_ret = find_talent_spell( talent_tree::SPECIALIZATION, "Consecrated Ground", PALADIN_RETRIBUTION ); + if ( !is_ptr() ) talents.consecrated_ground_ret = find_talent_spell( talent_tree::SPECIALIZATION, "Consecrated Ground", PALADIN_RETRIBUTION ); talents.tempest_of_the_lightbringer = find_talent_spell( talent_tree::SPECIALIZATION, "Tempest of the Lightbringer" ); talents.justicars_vengeance = find_talent_spell( talent_tree::SPECIALIZATION, "Justicar's Vengeance" ); talents.execution_sentence = find_talent_spell( talent_tree::SPECIALIZATION, "Execution Sentence" ); @@ -1705,6 +1705,7 @@ void paladin_t::init_spells_retribution() talents.burn_to_ash = find_talent_spell( talent_tree::SPECIALIZATION, "Burn to Ash" ); talents.vengeful_wrath = find_talent_spell( talent_tree::CLASS, "Vengeful Wrath" ); + talents.healing_hands = find_talent_spell( talent_tree::CLASS, "Healing Hands" ); // Spec passives and useful spells spec.retribution_paladin = find_specialization_spell( "Retribution Paladin" ); spec.retribution_paladin_2 = find_spell( 412314 );