diff --git a/engine/class_modules/sc_demon_hunter.cpp b/engine/class_modules/sc_demon_hunter.cpp index eaeb54f955a..6bcd027af1f 100644 --- a/engine/class_modules/sc_demon_hunter.cpp +++ b/engine/class_modules/sc_demon_hunter.cpp @@ -4904,7 +4904,8 @@ struct auto_attack_damage_t : public burning_blades_trigger_tdebuffs.reavers_mark->up() ) { + if ( target_data->debuffs.reavers_mark->up() ) + { m *= 1.0 + target_data->debuffs.reavers_mark->check_stack_value(); } @@ -6303,6 +6304,55 @@ struct soul_cleave_t : public soul_cleave_base_t } }; +// Reaver's Glaive ========================================================== +struct reavers_glaive_t : public soulscar_trigger_t +{ + reavers_glaive_t( demon_hunter_t* p ) : base_t( "reavers_glaive", p, p->hero_spec.reavers_glaive ) + { + if ( p->talent.aldrachi_reaver.keen_engagement->ok() ) + { + energize_type = action_energize::ON_CAST; + energize_resource = data().effectN( 2 ).resource_gain_type(); + energize_amount = p->talent.aldrachi_reaver.keen_engagement->effectN( 1 ).resource( energize_resource ); + } + else + { + energize_type = action_energize::NONE; + } + } + + void execute() override + { + p()->buff.reavers_glaive->expire(); + + base_t::execute(); + + if ( p()->active.preemptive_strike ) + { + p()->active.preemptive_strike->execute_on_target( target ); + } + + p()->buff.glaive_flurry->trigger(); + p()->buff.rending_strike->trigger(); + p()->buff.art_of_the_glaive_first->trigger(); + } + + bool ready() override + { + if ( !p()->buff.reavers_glaive->up() ) + { + return false; + } + // 2024-07-11 -- Reaver's Glaive can't be cast unless a GCD is available, but doesn't trigger a GCD. + if ( p()->gcd_ready > sim->current_time() ) + { + return false; + } + + return base_t::ready(); + } +}; + // Throw Glaive ============================================================= struct throw_glaive_t : public demon_hunter_attack_t @@ -6312,34 +6362,18 @@ struct throw_glaive_t : public demon_hunter_attack_t THROWN = 0, SCREAMING_BRUTALITY_SLASH_PROC_THROW = 1, SCREAMING_BRUTALITY_BLADE_DANCE_THROW = 2, - SCREAMING_BRUTALITY_DEATH_SWEEP_THROW = 3 + SCREAMING_BRUTALITY_DEATH_SWEEP_THROW = 3, + FURIOUS_THROWS = 4, }; struct throw_glaive_damage_t : public soulscar_trigger_t> { - glaive_source source; - - throw_glaive_damage_t( util::string_view name, demon_hunter_t* p, glaive_source source = glaive_source::THROWN ) - : base_t( name, p, p->spell.throw_glaive->effectN( 1 ).trigger() ), source( source ) + throw_glaive_damage_t( util::string_view name, demon_hunter_t* p, double damage_multiplier = 1.0 ) + : base_t( name, p, p->spell.throw_glaive->effectN( 1 ).trigger() ) { background = dual = true; radius = 10.0; - - switch ( source ) - { - case glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW: - // slash procs have one multiplier - base_multiplier *= p->talent.havoc.screaming_brutality->effectN( 1 ).percent(); - break; - case glaive_source::SCREAMING_BRUTALITY_BLADE_DANCE_THROW: - case glaive_source::SCREAMING_BRUTALITY_DEATH_SWEEP_THROW: - // regular procs have a different multiplier - base_multiplier *= p->talent.havoc.screaming_brutality->effectN( 3 ).percent(); - break; - default: - // this handles THROWN (multiplier of 1 by default) and any new sources - break; - } + base_multiplier *= damage_multiplier; } void impact( action_state_t* state ) override @@ -6361,48 +6395,52 @@ struct throw_glaive_t : public demon_hunter_attack_t } }; - throw_glaive_damage_t* furious_throws; + throw_glaive_t* furious_throws; + reavers_glaive_t* reavers_glaive; + double reavers_glaive_cost; + glaive_source source; throw_glaive_t( util::string_view name, demon_hunter_t* p, util::string_view options_str, glaive_source source = glaive_source::THROWN ) - : demon_hunter_attack_t( name, p, p->spell.throw_glaive, options_str ), furious_throws( nullptr ) + : demon_hunter_attack_t( name, p, p->spell.throw_glaive, options_str ), + furious_throws( nullptr ), + reavers_glaive( nullptr ), + reavers_glaive_cost( 0 ), + source( source ) { - throw_glaive_damage_t* damage; - + // set the execute action based on the source switch ( source ) { case glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW: - damage = p->get_background_action( "throw_glaive_damage_sb_slash_proc_throw", source ); + execute_action = p->get_background_action( + fmt::format( "{}_damage_sb_slash", name ), p->talent.havoc.screaming_brutality->effectN( 1 ).percent() ); break; case glaive_source::SCREAMING_BRUTALITY_BLADE_DANCE_THROW: - damage = p->get_background_action( "throw_glaive_damage_sb_bd_throw", source ); + execute_action = p->get_background_action( + fmt::format( "{}_damage_sb_bd", name ), p->talent.havoc.screaming_brutality->effectN( 3 ).percent() ); break; case glaive_source::SCREAMING_BRUTALITY_DEATH_SWEEP_THROW: - damage = p->get_background_action( "throw_glaive_damage_sb_ds_throw", source ); + execute_action = p->get_background_action( + fmt::format( "{}_damage_sb_ds", name ), p->talent.havoc.screaming_brutality->effectN( 3 ).percent() ); break; default: - damage = p->get_background_action( "throw_glaive_damage", source ); + execute_action = p->get_background_action( fmt::format( "{}_damage", name ) ); break; } - - execute_action = damage; execute_action->stats = stats; if ( source == glaive_source::SCREAMING_BRUTALITY_BLADE_DANCE_THROW || source == glaive_source::SCREAMING_BRUTALITY_DEATH_SWEEP_THROW ) { - cooldown->duration = 0_s; - cooldown->charges = 0; - cooldown = p->cooldown.throw_glaive; } - if ( source == glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW ) + if ( source == glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW || source == glaive_source::FURIOUS_THROWS ) { cooldown->duration = 0_s; cooldown->charges = 0; } - if ( p->talent.havoc.furious_throws->ok() ) + if ( source != glaive_source::FURIOUS_THROWS && p->talent.havoc.furious_throws->ok() ) { if ( source == glaive_source::THROWN ) { @@ -6410,27 +6448,17 @@ struct throw_glaive_t : public demon_hunter_attack_t base_costs[ RESOURCE_FURY ] = p->talent.havoc.furious_throws->effectN( 1 ).base_value(); } - switch ( source ) - { - case glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW: - furious_throws = p->get_background_action( - "throw_glaive_furious_throws_sb_slash_proc_throw", source ); - break; - case glaive_source::SCREAMING_BRUTALITY_BLADE_DANCE_THROW: - furious_throws = - p->get_background_action( "throw_glaive_furious_throws_sb_bd_throw", source ); - break; - case glaive_source::SCREAMING_BRUTALITY_DEATH_SWEEP_THROW: - furious_throws = - p->get_background_action( "throw_glaive_furious_throws_sb_ds_throw", source ); - break; - default: - furious_throws = p->get_background_action( "throw_glaive_furious_throws", source ); - break; - } - + furious_throws = p->get_background_action( fmt::format( "{}_furious_throws", name ), "", + glaive_source::FURIOUS_THROWS ); add_child( furious_throws ); } + + if ( source == glaive_source::THROWN && p->talent.aldrachi_reaver.art_of_the_glaive->ok() ) + { + reavers_glaive = new reavers_glaive_t( p ); + reavers_glaive_cost = p->hero_spec.reavers_glaive->cost( POWER_FURY ); + add_child( reavers_glaive ); + } } void init() override @@ -6447,84 +6475,55 @@ struct throw_glaive_t : public demon_hunter_attack_t p()->template get_data_entry( "throw_glaive", p()->cd_waste_iter ); } - void execute() override + double cost() const override { - demon_hunter_attack_t::execute(); - - if ( hit_any_target && furious_throws ) + if ( p()->talent.aldrachi_reaver.art_of_the_glaive.ok() && p()->buff.reavers_glaive->up() ) { - make_event( *sim, p(), furious_throws, target, 400_ms ); + return reavers_glaive_cost; } - - if ( td( target )->debuffs.serrated_glaive->up() ) - { - p()->proc.throw_glaive_in_serrated_glaive->occur(); - } - - if ( p()->active.preemptive_strike ) + else { - p()->active.preemptive_strike->execute_on_target( target ); + return base_costs[ RESOURCE_FURY ]; } } - bool ready() override + void execute() override { - if ( p()->buff.reavers_glaive->up() ) + if ( reavers_glaive && p()->buff.reavers_glaive->up() ) { - return false; + reavers_glaive->execute_on_target( target ); + stats->add_execute( 0_ms, target ); + return; } - return demon_hunter_attack_t::ready(); - } -}; + demon_hunter_attack_t::execute(); -// Reaver's Glaive ========================================================== -struct reavers_glaive_t : public soulscar_trigger_t -{ - reavers_glaive_t( demon_hunter_t* p, util::string_view options_str ) - : base_t( "reavers_glaive", p, p->hero_spec.reavers_glaive, options_str ) - { - if ( p->talent.aldrachi_reaver.keen_engagement->ok() ) + if ( source != glaive_source::FURIOUS_THROWS && furious_throws && hit_any_target ) { - energize_type = action_energize::ON_CAST; - energize_resource = data().effectN( 2 ).resource_gain_type(); - energize_amount = p->talent.aldrachi_reaver.keen_engagement->effectN( 1 ).resource( energize_resource ); + make_event( *sim, p(), furious_throws, target, 400_ms ); } - else + + if ( td( target )->debuffs.serrated_glaive->up() ) { - energize_type = action_energize::NONE; + p()->proc.throw_glaive_in_serrated_glaive->occur(); } - } - - void execute() override - { - p()->buff.reavers_glaive->expire(); - - base_t::execute(); if ( p()->active.preemptive_strike ) { p()->active.preemptive_strike->execute_on_target( target ); } - - p()->buff.glaive_flurry->trigger(); - p()->buff.rending_strike->trigger(); - p()->buff.art_of_the_glaive_first->trigger(); } bool ready() override { - if ( !p()->buff.reavers_glaive->up() ) - { - return false; - } // 2024-07-11 -- Reaver's Glaive can't be cast unless a GCD is available, but doesn't trigger a GCD. - if ( p()->gcd_ready > sim->current_time() ) + if ( source == glaive_source::THROWN && reavers_glaive && p()->buff.reavers_glaive->up() && + p()->gcd_ready > sim->current_time() ) { return false; } - return base_t::ready(); + return demon_hunter_attack_t::ready(); } }; @@ -7697,8 +7696,6 @@ action_t* demon_hunter_t::create_action( util::string_view name, util::string_vi return new vengeful_retreat_t( this, options_str ); if ( name == "soul_carver" ) return new soul_carver_t( this, options_str ); - if ( name == "reavers_glaive" ) - return new reavers_glaive_t( this, options_str ); return base_t::create_action( name, options_str ); } @@ -8873,7 +8870,7 @@ void demon_hunter_t::init_spells() active.screaming_brutality_death_sweep_throw_glaive = get_background_action( "throw_glaive_sb_ds_throw", "", throw_glaive_t::glaive_source::SCREAMING_BRUTALITY_DEATH_SWEEP_THROW ); active.screaming_brutality_slash_proc_throw_glaive = get_background_action( - "throw_glaive_sb_slash_proc_throw", "", throw_glaive_t::glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW ); + "throw_glaive_sb_slash_throw", "", throw_glaive_t::glaive_source::SCREAMING_BRUTALITY_SLASH_PROC_THROW ); } if ( talent.vengeance.retaliation->ok() )