diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d78537eb2d5..80c5ac84574 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -168,7 +168,7 @@ jobs: Hunter_Beast_Mastery, Hunter_Marksmanship, Hunter_Survival, Mage_Arcane, Mage_Fire, Mage_Frost, Monk_Brewmaster, Monk_Windwalker, - Paladin_Protection, Paladin_Retribution, + Paladin_Holy, Paladin_Protection, Paladin_Retribution, Priest_Discipline, Priest_Shadow, Rogue_Assassination, Rogue_Outlaw, Rogue_Subtlety, Shaman_Elemental, Shaman_Enhancement, Shaman_Restoration, diff --git a/engine/class_modules/paladin/sc_paladin.cpp b/engine/class_modules/paladin/sc_paladin.cpp index 607c4f1af25..bb8912a0ef8 100644 --- a/engine/class_modules/paladin/sc_paladin.cpp +++ b/engine/class_modules/paladin/sc_paladin.cpp @@ -107,6 +107,12 @@ avenging_wrath_buff_t::avenging_wrath_buff_t( paladin_t* p ) base_buff_duration *= 1.0 + p->talents.holy_sanctified_wrath->effectN( 1 ).percent(); took_sw = true; } + if ( p->spells.avenging_wrath_3->ok() ) + { + healing_modifier += p->spells.avenging_wrath_3->effectN( 1 ).percent(); + crit_bonus += p->spells.avenging_wrath_3->effectN( 4 ).percent(); + damage_modifier += p->spells.avenging_wrath_3->effectN( 1 ).percent(); + } break; case PALADIN_RETRIBUTION: if ( p->talents.ret_sanctified_wrath->ok() ) @@ -184,6 +190,8 @@ struct avenging_wrath_t : public paladin_spell_t if ( p->talents.crusade->ok() ) background = true; + if ( p->talents.avenging_crusader->ok() ) + background = true; harmful = false; @@ -784,7 +792,6 @@ struct crusader_strike_t : public paladin_melee_attack_t { timespan_t cm_cdr = p()->talents.crusaders_might->effectN( 1 ).time_value(); p()->cooldowns.holy_shock->adjust( cm_cdr ); - p()->cooldowns.light_of_dawn->adjust( cm_cdr ); } // Special things that happen when CS connects @@ -831,6 +838,96 @@ struct crusader_strike_t : public paladin_melee_attack_t } }; +// Word of Glory =================================================== + +struct word_of_glory_t : public holy_power_consumer_t +{ + word_of_glory_t( paladin_t* p, const std::string& options_str ) + : holy_power_consumer_t( "word_of_glory", p, p->find_class_spell( "Word of Glory" ) ) + { + parse_options( options_str ); + target = p; + is_wog = true; + } + + double composite_target_multiplier( player_t* t ) const override + { + double m = holy_power_consumer_t::composite_target_multiplier( t ); + + if ( p()->spec.word_of_glory_2->ok() ) + { + // Heals for a base amount, increased by up to +300% based on the target's missing health + // Linear increase, each missing health % increases the healing by 3% + double missing_health_percent = std::min( 1.0 - t->resources.pct( RESOURCE_HEALTH ), 1.0 ); + + m *= 1.0 + missing_health_percent * p()->spec.word_of_glory_2->effectN( 1 ).percent(); + + sim->print_debug( "Player {} missing {:.2f}% health, healing increased by {:.2f}%", t->name(), + missing_health_percent * 100, + missing_health_percent * p()->spec.word_of_glory_2->effectN( 1 ).percent() * 100 ); + } + return m; + } + + void impact( action_state_t* s ) override + { + holy_power_consumer_t::impact( s ); + if ( p()->conduit.shielding_words->ok() && s->result_amount > 0 ) + { + p()->buffs.shielding_words->trigger( 1, s->result_amount * p()->conduit.shielding_words.percent() ); + } + } + + void execute() override + { + holy_power_consumer_t::execute(); + + if ( p()->specialization() == PALADIN_PROTECTION && p()->buffs.vanquishers_hammer->up() ) + { + p()->buffs.vanquishers_hammer->expire(); + p()->active.necrolord_shield_of_the_righteous->execute(); + } + + if ( p()->specialization() == PALADIN_HOLY && p()->talents.awakening->ok() ) + { + if ( rng().roll( p()->talents.awakening->effectN( 1 ).percent() ) ) + { + buff_t* main_buff = p()->buffs.avenging_wrath; + timespan_t trigger_duration = timespan_t::from_seconds( p()->talents.awakening->effectN( 2 ).base_value() ); + if ( main_buff->check() ) + { + p()->buffs.avengers_might->extend_duration( p(), trigger_duration ); + } + else + { + main_buff->trigger( 1, buff_t::DEFAULT_VALUE(), -1.0, trigger_duration ); + } + } + } + } + + double action_multiplier() const override + { + double am = holy_power_consumer_t::action_multiplier(); + 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(); + return am; + } + + double cost() const override + { + double c = holy_power_consumer_t::cost(); + + if ( p()->buffs.shining_light_free->check() ) + c *= 1.0 + p()->buffs.shining_light_free->data().effectN( 1 ).percent(); + if ( p()->buffs.royal_decree->check() ) + c *= 1.0 + p()->buffs.royal_decree->data().effectN( 1 ).percent(); + + return c; + } +}; + // Hammer of Justice ======================================================== struct hammer_of_justice_t : public paladin_melee_attack_t @@ -1116,15 +1213,7 @@ struct hallowed_discernment_tick_t : public paladin_spell_t hallowed_discernment_tick_t( paladin_t* p ) : paladin_spell_t( "hallowed_discernment", p, p->find_spell( 340203 ) ) { base_multiplier *= p->conduit.hallowed_discernment.percent(); - background = true; - aoe_multiplier = 1.0; // This gets overwritten - } - - double action_multiplier() const override - { - double am = paladin_spell_t::action_multiplier(); - am *= aoe_multiplier; - return am; + background = true; } }; @@ -1186,8 +1275,6 @@ struct ashen_hallow_tick_t : public paladin_spell_t } ); hd_damage_tick->set_target( lowest_hp_target ); // Damage is calculated independently of Ashen Hallow. ie. they crit separately - // Hitting more targets with Ashen Hallow reduces the damage of Hallowed Discernment - hd_damage_tick->aoe_multiplier = composite_aoe_multiplier( execute_state ); hd_damage_tick->execute(); } } @@ -1786,6 +1873,8 @@ action_t* paladin_t::create_action( util::string_view name, const std::string& o return new ashen_hallow_t( this, options_str ); if ( name == "blessing_of_the_seasons" ) return new blessing_of_the_seasons_t( this, options_str ); + if ( name == "word_of_glory" ) + return new word_of_glory_t( this, options_str ); return player_t::create_action( name, options_str ); } @@ -2060,9 +2149,9 @@ std::string paladin_t::default_potion() const std::string protection_pot = ( true_level > 50 ) ? "phantom_fire" : "disabled"; - std::string holy_dps_pot = ( true_level > 100 ) ? "old_war" : "disabled"; + std::string holy_dps_pot = ( true_level > 50 ) ? "phantom_fire" : "disabled"; - std::string holy_pot = "disabled"; + std::string holy_pot = ( true_level > 50 ) ? "spectral_intellect" : "disabled"; switch ( specialization() ) { @@ -2083,17 +2172,9 @@ std::string paladin_t::default_food() const std::string protection_food = ( true_level > 50 ) ? "feast_of_gluttonous_hedonism" : "disabled"; - std::string holy_dps_food = ( true_level > 100 ) ? "the_hungry_magister" - : ( true_level >= 90 ) ? "pickled_eel" - : ( true_level >= 85 ) ? "mogu_fish_stew" - : ( true_level >= 80 ) ? "seafood_magnifique_feast" - : "disabled"; + std::string holy_dps_food = ( true_level > 50 ) ? "feast_of_gluttonous_hedonism" : "disabled"; - std::string holy_food = ( true_level > 100 ) ? "lavish_suramar_feast" - : ( true_level >= 90 ) ? "pickled_eel" - : ( true_level >= 85 ) ? "mogu_fish_stew" - : ( true_level >= 80 ) ? "seafood_magnifique_feast" - : "disabled"; + std::string holy_food = ( true_level > 50 ) ? "feast_of_gluttonous_hedonism" : "disabled"; switch ( specialization() ) { @@ -2114,17 +2195,9 @@ std::string paladin_t::default_flask() const std::string protection_flask = ( true_level > 50 ) ? "spectral_flask_of_power" : "disabled"; - std::string holy_dps_flask = ( true_level > 100 ) ? "flask_of_the_whispered_pact" - : ( true_level >= 90 ) ? "greater_draenic_intellect_flask" - : ( true_level >= 85 ) ? "warm_sun" - : ( true_level >= 80 ) ? "draconic_mind" - : "disabled"; + std::string holy_dps_flask = ( true_level > 50 ) ? "spectral_flask_of_power" : "disabled"; - std::string holy_flask = ( true_level > 100 ) ? "flask_of_the_whispered_pact" - : ( true_level >= 90 ) ? "greater_draenic_intellect_flask" - : ( true_level >= 85 ) ? "warm_sun" - : ( true_level >= 80 ) ? "draconic_mind" - : "disabled"; + std::string holy_flask = ( true_level > 50 ) ? "spectral_flask_of_power" : "disabled"; switch ( specialization() ) { @@ -2164,16 +2237,6 @@ std::string paladin_t::default_temporary_enchant() const void paladin_t::init_action_list() { - // 2019-04-03: The Holy module is outdated and not supported (both for dps and healing) - if ( !sim->allow_experimental_specializations && specialization() == PALADIN_HOLY ) - { - if ( !quiet ) - sim->errorf( "Paladin holy for player %s is not currently supported.", name() ); - - quiet = true; - return; - } - // sanity check - Prot/Ret can't do anything w/o main hand weapon equipped if ( main_hand_weapon.type == WEAPON_NONE && ( specialization() == PALADIN_RETRIBUTION || specialization() == PALADIN_PROTECTION ) ) @@ -2260,6 +2323,7 @@ void paladin_t::init_spells() spells.avenging_wrath = find_class_spell( "Avenging Wrath" ); spells.judgment_2 = find_rank_spell( "Judgment", "Rank 2" ); // 327977 spells.avenging_wrath_2 = find_rank_spell( "Avenging Wrath", "Rank 2" ); // 317872 + spells.avenging_wrath_3 = find_rank_spell( "Avenging Wrath", "Rank 3" ); // 327979 spells.hammer_of_wrath_2 = find_rank_spell( "Hammer of Wrath", "Rank 2" ); // 326730 spec.word_of_glory_2 = find_rank_spell( "Word of Glory", "Rank 2" ); spells.divine_purpose_buff = find_spell( 223819 ); @@ -2619,6 +2683,12 @@ double paladin_t::composite_melee_attack_power() const double paladin_t::composite_melee_attack_power_by_type( attack_power_type ap_type ) const { + // Holy paladin AP scales purely off of Spell power and nothing else not even Weapon + if ( specialization() == PALADIN_HOLY ) + { + return player_t::composite_melee_attack_power_by_type( attack_power_type::NO_WEAPON ); + } + return player_t::composite_melee_attack_power_by_type( ap_type ); } @@ -2632,6 +2702,14 @@ double paladin_t::composite_attack_power_multiplier() const if ( specialization() == PALADIN_PROTECTION ) ap *= 1.0 + cache.mastery() * mastery.divine_bulwark->effectN( 2 ).mastery_value(); + // Holy paladin AP scales purely off of Spell power and nothing else not even Weapon + // This means literally nothing, not sharpning/weight stones, battle shout, weapon, etc etc + // It is purely off SP and nothing effects it. + if ( specialization() == PALADIN_HOLY ) + { + return 1.0; + } + return ap; } diff --git a/engine/class_modules/paladin/sc_paladin.hpp b/engine/class_modules/paladin/sc_paladin.hpp index 3be7d1649c4..8a98fca4eaa 100644 --- a/engine/class_modules/paladin/sc_paladin.hpp +++ b/engine/class_modules/paladin/sc_paladin.hpp @@ -172,6 +172,7 @@ struct paladin_t : public player_t // Holy buff_t* divine_protection; buff_t* holy_avenger; + buff_t* avenging_crusader; buff_t* infusion_of_light; // Prot @@ -252,6 +253,7 @@ struct paladin_t : public player_t const spell_data_t* retribution_paladin; const spell_data_t* hammer_of_the_righteous_2; const spell_data_t* word_of_glory_2; + const spell_data_t* holy_shock_2; } spec; // Cooldowns @@ -342,6 +344,7 @@ struct paladin_t : public player_t const spell_data_t* judgment_2; const spell_data_t* avenging_wrath_2; + const spell_data_t* avenging_wrath_3; const spell_data_t* hammer_of_wrath_2; const spell_data_t* ashen_hallow_how; @@ -770,6 +773,7 @@ struct paladin_action_t : public Base { bool avenging_wrath, judgment, blessing_of_dawn, the_magistrates_judgment; // Shared bool crusade, divine_purpose, divine_purpose_cost, hand_of_light, final_reckoning, reckoning; // Ret + bool avenging_crusader; // Holy } affected_by; // haste scaling bools @@ -795,6 +799,11 @@ struct paladin_action_t : public Base this -> affected_by.reckoning = this -> data().affected_by( p -> spells.reckoning -> effectN( 1 ) ); this -> affected_by.final_reckoning = this -> data().affected_by( p -> talents.final_reckoning -> effectN( 3 ) ); } + if ( p->specialization() == PALADIN_HOLY ) + { + this->affected_by.avenging_crusader = this->data().affected_by( p->talents.avenging_crusader->effectN(1) ); + } + this -> affected_by.judgment = this -> data().affected_by( p -> spells.judgment_debuff -> effectN( 1 ) ); this -> affected_by.avenging_wrath = this -> data().affected_by( p -> spells.avenging_wrath -> effectN( 1 ) ); this -> affected_by.divine_purpose_cost = this -> data().affected_by( p -> spells.divine_purpose_buff -> effectN( 1 ) ); @@ -917,6 +926,11 @@ struct paladin_action_t : public Base am *= 1.0 + p() -> buffs.avenging_wrath -> get_damage_mod(); } + if ( affected_by.avenging_crusader ) + { + am *= 1.0 + p()->buffs.avenging_crusader->check_value(); + } + // Divine purpose damage increase handled here, // Cost handled in holy_power_consumer_t if ( affected_by.divine_purpose && p() -> buffs.divine_purpose -> up() ) @@ -1354,6 +1368,7 @@ struct judgment_t : public paladin_melee_attack_t proc_types proc_type() const override; void impact( action_state_t* s ) override; void execute() override; + private: void do_ctor_common( paladin_t* p ); }; diff --git a/engine/class_modules/paladin/sc_paladin_holy.cpp b/engine/class_modules/paladin/sc_paladin_holy.cpp index c39b2b15e12..759ddd4c2f2 100644 --- a/engine/class_modules/paladin/sc_paladin_holy.cpp +++ b/engine/class_modules/paladin/sc_paladin_holy.cpp @@ -1,11 +1,10 @@ #include "sc_paladin.hpp" - #include "simulationcraft.hpp" namespace paladin { -// Beacon of Light ========================================================== +// Beacon of Light ========================================================== struct beacon_of_light_t : public paladin_heal_t { beacon_of_light_t( paladin_t* p, const std::string& options_str ) @@ -219,23 +218,22 @@ struct holy_prism_t : public paladin_spell_t struct holy_shock_damage_t : public paladin_spell_t { - double crit_chance_multiplier; + double crit_chance_boost; holy_shock_damage_t( paladin_t* p ) : paladin_spell_t( "holy_shock_damage", p, p->find_spell( 25912 ) ) { background = may_crit = true; trigger_gcd = 0_ms; - - // this grabs the 100% base crit bonus from 20473 - crit_chance_multiplier = p->find_class_spell( "Holy Shock" )->effectN( 1 ).base_value() / 10.0; + // this grabs the 30% base crit bonus from 272906 + crit_chance_boost = p->spec.holy_shock_2->effectN( 1 ).percent(); } double composite_crit_chance() const override { double cc = paladin_spell_t::composite_crit_chance(); - // effect 1 doubles crit chance - cc *= crit_chance_multiplier; + // effect 1 increases crit chance flattly + cc += crit_chance_boost; return cc; } @@ -245,23 +243,23 @@ struct holy_shock_damage_t : public paladin_spell_t struct holy_shock_heal_t : public paladin_heal_t { - double crit_chance_multiplier; + double crit_chance_boost; holy_shock_heal_t( paladin_t* p ) : paladin_heal_t( "holy_shock_heal", p, p->find_spell( 25914 ) ) { background = true; trigger_gcd = 0_ms; - // this grabs the crit multiplier bonus from 20473 - crit_chance_multiplier = p->find_class_spell( "Holy Shock" )->effectN( 1 ).base_value() / 10.0; + // this grabs the crit multiplier bonus from 272906 + crit_chance_boost = p->spec.holy_shock_2->effectN( 1 ).percent(); } double composite_crit_chance() const override { double cc = paladin_heal_t::composite_crit_chance(); - // effect 1 doubles crit chance - cc *= crit_chance_multiplier; + // effect 1 increases crit chance flattly + cc += crit_chance_boost; return cc; } @@ -307,20 +305,24 @@ struct holy_shock_t : public paladin_spell_t void execute() override { - paladin_spell_t::execute(); - if ( dmg ) { // damage enemy - damage->set_target( execute_state->target ); + damage->set_target( target ); damage->execute(); } else { // heal friendly - heal->set_target( execute_state->target ); + heal->set_target( target ); heal->execute(); } + // The reason the subspell is allowed to execute first is so we can consume judgment correctly. + // If this is first then a dummy holy shock is fired off that consumes the judgment debuff + // meaning when we attempt to do damage judgment will not be factored in even when it should be. + // because of dumb blizz spelldata that makes every holy shock spell affected by judgment, + // instead of just affecting the damaging holy shock spell. + paladin_spell_t::execute(); } double recharge_multiplier( const cooldown_t& cd ) const override @@ -450,16 +452,53 @@ struct lights_hammer_t : public paladin_spell_t // Light of Dawn (Holy) ======================================================= -struct light_of_dawn_t : public paladin_heal_t +struct light_of_dawn_t : public holy_power_consumer_t { light_of_dawn_t( paladin_t* p, const std::string& options_str ) - : paladin_heal_t( "light_of_dawn", p, p->find_class_spell( "Light of Dawn" ) ) + : holy_power_consumer_t( "light_of_dawn", p, p->find_class_spell( "Light of Dawn" ) ) { parse_options( options_str ); aoe = 6; + } + + void execute() override + { + holy_power_consumer_t::execute(); - cooldown = p->cooldowns.light_of_dawn; + // deal with awakening + if ( p()->talents.awakening->ok() ) + { + if ( rng().roll( p()->talents.awakening->effectN( 1 ).percent() ) ) + { + buff_t* main_buff = p()->buffs.avenging_wrath; + timespan_t trigger_duration = timespan_t::from_seconds( p()->talents.awakening->effectN( 2 ).base_value() ); + if ( main_buff->check() ) + { + p()->buffs.avengers_might->extend_duration( p(), trigger_duration ); + } + else + { + main_buff->trigger( 1, buff_t::DEFAULT_VALUE(), -1.0, trigger_duration ); + } + } + } + } +}; + +struct avenging_crusader_t : public paladin_spell_t +{ + avenging_crusader_t( paladin_t* p, const std::string& options_str ) + : paladin_spell_t( "avenging_crusader", p, p->talents.avenging_crusader ) + { + parse_options( options_str ); + } + + void execute() override + { + paladin_spell_t::execute(); + + p()->buffs.avenging_crusader->trigger(); } }; @@ -492,6 +531,8 @@ action_t* paladin_t::create_action_holy( util::string_view name, const std::stri return new light_of_dawn_t( this, options_str ); if ( name == "lights_hammer" ) return new lights_hammer_t( this, options_str ); + if ( name == "avenging_crusader" ) + return new avenging_crusader_t( this, options_str ); if ( specialization() == PALADIN_HOLY ) { @@ -507,6 +548,8 @@ void paladin_t::create_buffs_holy() buffs.divine_protection = make_buff( this, "divine_protection", find_class_spell( "Divine Protection" ) ) ->set_cooldown( 0_ms ); // Handled by the action buffs.infusion_of_light = make_buff( this, "infusion_of_light", find_spell( 54149 ) ); + buffs.avenging_crusader = + make_buff( this, "avenging_crusader", talents.avenging_crusader )->set_default_value_from_effect( 1 ); } void paladin_t::init_spells_holy() @@ -539,8 +582,7 @@ void paladin_t::init_spells_holy() spec.judgment_3 = find_specialization_spell( 231644 ); spells.judgment_debuff = find_spell( 214222 ); - // TODO: is this still a thing? - spells.divine_purpose_buff = find_spell( 216411 ); // Not whitelisted + spec.holy_shock_2 = find_spell( 272906 ); } passives.infusion_of_light = find_specialization_spell( "Infusion of Light" ); @@ -579,6 +621,7 @@ void paladin_t::generate_action_prio_list_holy_dps() def->add_action( "call_action_list,name=priority" ); cds->add_action( "avenging_wrath" ); + cds->add_action( "ashen_hallow" ); if ( sim->allow_potions ) { cds->add_action( "potion,if=(buff.avenging_wrath.up)" ); @@ -587,9 +630,12 @@ void paladin_t::generate_action_prio_list_holy_dps() cds->add_action( "berserking,if=(buff.avenging_wrath.up)" ); cds->add_action( "holy_avenger,if=(buff.avenging_wrath.up)" ); cds->add_action( "use_items,if=(buff.avenging_wrath.up)" ); + cds->add_action( "seraphim,if=(buff.avenging_wrath.up)" ); - priority->add_action( "judgment" ); + priority->add_action( this, "Shield of the Righteous" ); + priority->add_action( this, "Hammer of Wrath" ); priority->add_action( "holy_shock,damage=1" ); + priority->add_action( "judgment" ); priority->add_action( "crusader_strike" ); priority->add_action( "holy_prism,target=self,if=active_enemies>=2" ); priority->add_action( "holy_prism" ); diff --git a/engine/class_modules/paladin/sc_paladin_protection.cpp b/engine/class_modules/paladin/sc_paladin_protection.cpp index 76784bdbcfd..e3374c324e8 100644 --- a/engine/class_modules/paladin/sc_paladin_protection.cpp +++ b/engine/class_modules/paladin/sc_paladin_protection.cpp @@ -425,81 +425,6 @@ struct judgment_prot_t : public judgment_t } }; -// Word of Glory =================================================== - -struct word_of_glory_t : public holy_power_consumer_t -{ - word_of_glory_t( paladin_t* p, const std::string& options_str ) : - holy_power_consumer_t( "word_of_glory", p, p -> find_class_spell( "Word of Glory" ) ) - { - parse_options( options_str ); - target = p; - is_wog = true; - } - - double composite_target_multiplier( player_t* t ) const override - { - double m = holy_power_consumer_t::composite_target_multiplier( t ); - - if ( p() -> spec.word_of_glory_2 -> ok() ) - { - // Heals for a base amount, increased by up to +300% based on the target's missing health - // Linear increase, each missing health % increases the healing by 3% - double missing_health_percent = std::min( 1.0 - t -> resources.pct( RESOURCE_HEALTH ), 1.0 ); - - m *= 1.0 + missing_health_percent * p() -> spec.word_of_glory_2 -> effectN( 1 ).percent(); - - sim -> print_debug( "Player {} missing {:.2f}% health, healing increased by {:.2f}%", - t -> name(), missing_health_percent * 100, - missing_health_percent * p() -> spec.word_of_glory_2 -> effectN( 1 ).percent() * 100 ); - } - return m; - } - - void impact( action_state_t *s ) override - { - holy_power_consumer_t::impact( s ); - if ( p() -> conduit.shielding_words -> ok() && s -> result_amount > 0 ) - { - p() -> buffs.shielding_words -> trigger( 1, - s -> result_amount * p() -> conduit.shielding_words.percent() - ); - } - } - - void execute() override - { - holy_power_consumer_t::execute(); - - if ( p() -> specialization() == PALADIN_PROTECTION && p() -> buffs.vanquishers_hammer -> up() ) - { - p() -> buffs.vanquishers_hammer -> expire(); - p() -> active.necrolord_shield_of_the_righteous -> execute(); - } - } - - double action_multiplier() const override - { - double am = holy_power_consumer_t::action_multiplier(); - 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(); - return am; - } - - double cost() const override - { - double c = holy_power_consumer_t::cost(); - - if ( p() -> buffs.shining_light_free -> check() ) - c *= 1.0 + p() -> buffs.shining_light_free -> data().effectN( 1 ).percent(); - if ( p() -> buffs.royal_decree -> check() ) - c *= 1.0 + p() -> buffs.royal_decree -> data().effectN( 1 ).percent(); - - return c; - } -}; - // Shield of the Righteous ================================================== shield_of_the_righteous_buff_t::shield_of_the_righteous_buff_t( paladin_t* p ) : @@ -834,7 +759,6 @@ action_t* paladin_t::create_action_protection( util::string_view name, const std if ( name == "blessing_of_spellwarding" ) return new blessing_of_spellwarding_t ( this, options_str ); if ( name == "guardian_of_ancient_kings" ) return new guardian_of_ancient_kings_t( this, options_str ); if ( name == "hammer_of_the_righteous" ) return new hammer_of_the_righteous_t ( this, options_str ); - if ( name == "word_of_glory" ) return new word_of_glory_t ( this, options_str ); if ( name == "shield_of_the_righteous" ) return new shield_of_the_righteous_t ( this, options_str ); if ( name == "moment_of_glory" ) return new moment_of_glory_t ( this, options_str ); diff --git a/profiles/PreRaids/PR_Paladin_Holy.simc b/profiles/PreRaids/PR_Paladin_Holy.simc new file mode 100644 index 00000000000..3e28ed1b8e5 --- /dev/null +++ b/profiles/PreRaids/PR_Paladin_Holy.simc @@ -0,0 +1,81 @@ +paladin="PR_Paladin_Holy" +source=default +spec=holy +level=60 +race=blood_elf +role=attack +position=back +talents=1212231 +covenant=venthyr +soulbind=theotar,soothing_shade/templars_vindication:4 +renown=40 + +# Default consumables +potion=phantom_fire +flask=spectral_flask_of_power +food=feast_of_gluttonous_hedonism +augmentation=veiled +temporary_enchant=main_hand:shadowcore_oil + +# This default action priority list is automatically created based on your character. +# It is a attempt to provide you with a action list that is both simple and practicable, +# while resulting in a meaningful and good simulation. It may not result in the absolutely highest possible dps. +# Feel free to edit, adapt and improve it to your own needs. +# SimulationCraft is always looking for updates and improvements to the default action lists. + +# Executed before combat begins. Accepts non-harmful actions only. +actions.precombat=flask +actions.precombat+=/food +actions.precombat+=/augmentation +# Snapshot raid buffed stats before combat begins and pre-potting is done. +actions.precombat+=/snapshot_stats +actions.precombat+=/potion + +# Executed every time the actor is available. +actions=auto_attack +actions+=/call_action_list,name=cooldowns +actions+=/call_action_list,name=priority + +actions.cooldowns=avenging_wrath +actions.cooldowns+=/ashen_hallow +actions.cooldowns+=/potion,if=(buff.avenging_wrath.up) +actions.cooldowns+=/blood_fury,if=(buff.avenging_wrath.up) +actions.cooldowns+=/berserking,if=(buff.avenging_wrath.up) +actions.cooldowns+=/holy_avenger,if=(buff.avenging_wrath.up) +actions.cooldowns+=/use_items,if=(buff.avenging_wrath.up) +actions.cooldowns+=/seraphim,if=(buff.avenging_wrath.up) + +actions.priority=shield_of_the_righteous +actions.priority+=/hammer_of_wrath +actions.priority+=/holy_shock,damage=1 +actions.priority+=/judgment +actions.priority+=/crusader_strike +actions.priority+=/holy_prism,target=self,if=active_enemies>=2 +actions.priority+=/holy_prism +actions.priority+=/consecration +actions.priority+=/light_of_dawn + +head=plague_handlers_greathelm,id=178773,bonus_id=6807/1498/6646 +neck=sin_stained_pendant,id=178827,bonus_id=6807/1498/6646 +shoulders=pauldrons_of_unleashed_pride,id=178820,bonus_id=6807/1498/6646 +back=drape_of_twisted_loyalties,id=180123,bonus_id=6807/1498/6646 +chest=abdominal_securing_chestguard,id=178793,bonus_id=6807/1498/6646,enchant=eternal_skirmish +wrists=vambraces_of_the_depraved_warden,id=178845,bonus_id=6807/1498/6646,enchant=eternal_intellect +hands=fleshfused_crushers,id=178775,bonus_id=6807/1498/6646 +waist=scarred_bloodbound_girdle,id=178931,bonus_id=6807/1498/6646 +legs=galvanized_oxxein_legguards,id=178800,bonus_id=6807/1498/6646 +feet=shadowghast_sabatons,id=171413,bonus_id=6647/6649/6716/7054/1487 +finger1=death_gods_signet,id=179355,bonus_id=6807/1498/6646,enchant=tenet_of_critical_strike +finger2=bloodoath_signet,id=178871,bonus_id=6807/1498/6646,enchant=tenet_of_critical_strike +main_hand=amarths_spellblade,id=178737,bonus_id=6807/1498/6646,enchant=sinful_revelation +off_hand=encrusted_canopic_lid,id=178750,bonus_id=6807/1498/6646 + +# Gear Summary +# gear_ilvl=184.43 +# gear_stamina=860 +# gear_intellect=653 +# gear_crit_rating=342 +# gear_haste_rating=541 +# gear_mastery_rating=233 +# gear_versatility_rating=266 +# gear_armor=1543 diff --git a/profiles/Tier26/T26_Paladin_Holy.simc b/profiles/Tier26/T26_Paladin_Holy.simc new file mode 100644 index 00000000000..a8820592948 --- /dev/null +++ b/profiles/Tier26/T26_Paladin_Holy.simc @@ -0,0 +1,84 @@ +paladin="T26_Paladin_Holy" +source=default +spec=holy +level=60 +race=blood_elf +role=attack +position=back +talents=1212231 +covenant=venthyr +soulbind=theotar_the_mad_duke:9,336239/159:7/336147/215:7/336184/133:7/163:7/319983 +renown=40 + +# Default consumables +potion=phantom_fire +flask=spectral_flask_of_power +food=feast_of_gluttonous_hedonism +augmentation=veiled +temporary_enchant=main_hand:shadowcore_oil + +# This default action priority list is automatically created based on your character. +# It is a attempt to provide you with a action list that is both simple and practicable, +# while resulting in a meaningful and good simulation. It may not result in the absolutely highest possible dps. +# Feel free to edit, adapt and improve it to your own needs. +# SimulationCraft is always looking for updates and improvements to the default action lists. + +# Executed before combat begins. Accepts non-harmful actions only. +actions.precombat=flask +actions.precombat+=/food +actions.precombat+=/augmentation +# Snapshot raid buffed stats before combat begins and pre-potting is done. +actions.precombat+=/snapshot_stats +actions.precombat+=/potion + +# Executed every time the actor is available. +actions=auto_attack +actions+=/call_action_list,name=cooldowns +actions+=/call_action_list,name=priority + +actions.cooldowns=avenging_wrath +actions.cooldowns+=/ashen_hallow +actions.cooldowns+=/potion,if=(buff.avenging_wrath.up) +actions.cooldowns+=/blood_fury,if=(buff.avenging_wrath.up) +actions.cooldowns+=/berserking,if=(buff.avenging_wrath.up) +actions.cooldowns+=/holy_avenger,if=(buff.avenging_wrath.up) +actions.cooldowns+=/use_items,if=(buff.avenging_wrath.up) +actions.cooldowns+=/seraphim,if=(buff.avenging_wrath.up) + +actions.priority=shield_of_the_righteous +actions.priority+=/hammer_of_wrath +actions.priority+=/holy_shock,damage=1 +actions.priority+=/judgment +actions.priority+=/crusader_strike +actions.priority+=/holy_prism,target=self,if=active_enemies>=2 +actions.priority+=/holy_prism +actions.priority+=/consecration +actions.priority+=/light_of_dawn + +head=plague_handlers_greathelm,id=178773,bonus_id=6536/1540/6646/6935,gem_id=173127 +neck=azurevenom_choker,id=180115,bonus_id=6536/1540/6646/6935,gem_id=173127 +shoulders=epaulettes_of_overwhelming_force,id=182994,bonus_id=7187/1498 +back=crest_of_the_legionnaire_general,id=183032,bonus_id=7187/1498 +chest=breastplate_of_cautious_calculation,id=182987,bonus_id=7187/1498,enchant=eternal_skirmish +wrists=hellhound_cuffs,id=183018,bonus_id=7187/1498/6935,gem_id=173127,enchant=eternal_intellect +hands=colossal_plate_gauntlets,id=182984,bonus_id=7187/1498 +waist=binding_of_warped_desires,id=183015,bonus_id=7187/1498/6935,gem_id=173127 +legs=ceremonial_parade_legguards,id=183002,bonus_id=7187/1498 +feet=shadowghast_sabatons,id=171413,bonus_id=6647/6649/6758/7054/1532 +finger1=ritualists_treasured_ring,id=183037,bonus_id=7187/1498/6935,gem_id=173127,enchant=tenet_of_critical_strike +finger2=most_regal_signet_of_sire_denathrius,id=183036,bonus_id=7187/1498/6935,gem_id=173127,enchant=tenet_of_critical_strike +trinket1=sinful_gladiators_insignia_of_alacrity,id=178386,bonus_id=41/6623/1498/6646 +trinket2=inscrutable_quantum_device,id=179350,bonus_id=6536/1540/6646 +main_hand=hungering_ritualists_animablade,id=182396,bonus_id=7187/6652/1531/6646,enchant=sinful_revelation +off_hand=stonewrought_gargoyles_barrier,id=182399,bonus_id=7187/6652/1531/6646 + +# Gear Summary +# gear_ilvl=228.75 +# gear_stamina=1517 +# gear_intellect=1070 +# gear_crit_rating=669 +# gear_haste_rating=846 +# gear_mastery_rating=264 +# gear_versatility_rating=280 +# gear_leech_rating=46 +# gear_armor=1973 diff --git a/profiles/generators/PreRaids/PR_Generate_Paladin.simc b/profiles/generators/PreRaids/PR_Generate_Paladin.simc index c00b9ac5ccb..75b22c76cf4 100644 --- a/profiles/generators/PreRaids/PR_Generate_Paladin.simc +++ b/profiles/generators/PreRaids/PR_Generate_Paladin.simc @@ -55,3 +55,38 @@ trinket2=overwhelming_power_crystal,id=179342,bonus_id=6807/1498/6646 main_hand=rimebinders_runeblade,id=178780,bonus_id=6807/1498/6646,enchant=sinful_revelation save=PR_Paladin_Retribution.simc + + + +paladin="PR_Paladin_Holy" +level=60 +race=blood_elf +spec=holy +role=attack +position=back +talents=1212231 +covenant=venthyr +soulbind=theotar,soothing_shade/templars_vindication:4 +renown=40 +head=plague_handlers_greathelm,id=178773,bonus_id=6807/1498/6646 +neck=sin_stained_pendant,id=178827,bonus_id=6807/1498/6646 +shoulders=pauldrons_of_unleashed_pride,id=178820,bonus_id=6807/1498/6646 +back=drape_of_twisted_loyalties,id=180123,bonus_id=6807/1498/6646 +chest=abdominal_securing_chestguard,id=178793,bonus_id=6807/1498/6646,enchant=eternal_skirmish +wrists=vambraces_of_the_depraved_warden,id=178845,bonus_id=6807/1498/6646,enchant=eternal_intellect +hands=fleshfused_crushers,id=178775,bonus_id=6807/1498/6646 +waist=scarred_bloodbound_girdle,id=178931,bonus_id=6807/1498/6646 +legs=galvanized_oxxein_legguards,id=178800,bonus_id=6807/1498/6646 +feet=shadowghast_sabatons,id=171413,bonus_id=6647/6649/6716/7054/1487 +finger1=death_gods_signet,id=179355,bonus_id=6807/1498/6646,enchant=tenet_of_critical_strike +finger2=bloodoath_signet,id=178871,bonus_id=6807/1498/6646,enchant=tenet_of_critical_strike +main_hand=,id=178737,bonus_id=6807/1498/6646,enchant=sinful_revelation +off_hand=encrusted_canopic_lid,id=178750,bonus_id=6807/1498/6646 + +save=PR_Paladin_Holy.simc + + + + + + diff --git a/profiles/generators/Tier26/T26_Generate_Paladin.simc b/profiles/generators/Tier26/T26_Generate_Paladin.simc index e57567b24cd..9cd14cf1fad 100644 --- a/profiles/generators/Tier26/T26_Generate_Paladin.simc +++ b/profiles/generators/Tier26/T26_Generate_Paladin.simc @@ -87,3 +87,34 @@ trinket2=inscrutable_quantum_device,id=179350,bonus_id=6536/1540/6646 main_hand=stoneborn_goliaths_cleaver,id=182415,bonus_id=7187/1531,enchant=sinful_revelation save=T26_Paladin_Retribution_Venthyr.simc + + +paladin="T26_Paladin_Holy" +level=60 +race=blood_elf +spec=holy +role=attack +position=back +talents=1212231 +covenant=venthyr +soulbind=theotar_the_mad_duke:9,336239/159:7/336147/215:7/336184/133:7/163:7/319983 +renown=40 + +head=plague_handlers_greathelm,id=178773,bonus_id=6536/1540/6646/6935,gem_id=173127 +neck=azurevenom_choker,id=180115,bonus_id=6536/1540/6646/6935,gem_id=173127 +shoulders=epaulettes_of_overwhelming_force,id=182994,bonus_id=7187/1498 +back=crest_of_the_legionnaire_general,id=183032,bonus_id=7187/1498 +chest=breastplate_of_cautious_calculation,id=182987,bonus_id=7187/1498,enchant=eternal_skirmish +wrists=hellhound_cuffs,id=183018,bonus_id=7187/1498/6935,gem_id=173127,enchant=eternal_intellect +hands=colossal_plate_gauntlets,id=182984,bonus_id=7187/1498 +waist=binding_of_warped_desires,id=183015,bonus_id=7187/1498/6935,gem_id=173127 +legs=ceremonial_parade_legguards,id=183002,bonus_id=7187/1498 +feet=shadowghast_sabatons,id=171413,bonus_id=6647/6649/6758/7054/1532 +finger1=ritualists_treasured_ring,id=183037,bonus_id=7187/1498/6935,gem_id=173127,enchant=tenet_of_critical_strike +finger2=most_regal_signet_of_sire_denathrius,id=183036,bonus_id=7187/1498/6935,gem_id=173127,enchant=tenet_of_critical_strike +trinket1=sinful_gladiators_insignia_of_alacrity,id=178386,bonus_id=41/6623/1498/6646 +trinket2=inscrutable_quantum_device,id=179350,bonus_id=6536/1540/6646 +main_hand=,id=182396,enchant=sinful_revelation,bonus_id=7187/6652/1531/6646 +off_hand=,id=182399,bonus_id=7187/6652/1531/6646 + +save=T26_Paladin_Holy.simc \ No newline at end of file