Skip to content

[DH] throw glaive refactor #10300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: thewarwithin
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 104 additions & 107 deletions engine/class_modules/sc_demon_hunter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4904,7 +4904,8 @@ struct auto_attack_damage_t : public burning_blades_trigger_t<demon_hunter_attac
double m = base_t::composite_target_da_multiplier( t );

demon_hunter_td_t* target_data = td( t );
if ( target_data->debuffs.reavers_mark->up() ) {
if ( target_data->debuffs.reavers_mark->up() )
{
m *= 1.0 + target_data->debuffs.reavers_mark->check_stack_value();
}

Expand Down Expand Up @@ -6303,6 +6304,55 @@ struct soul_cleave_t : public soul_cleave_base_t
}
};

// Reaver's Glaive ==========================================================
struct reavers_glaive_t : public soulscar_trigger_t<demon_hunter_attack_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
Expand All @@ -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<burning_blades_trigger_t<demon_hunter_attack_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
Expand All @@ -6361,76 +6395,70 @@ 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_t>( "throw_glaive_damage_sb_slash_proc_throw", source );
execute_action = p->get_background_action<throw_glaive_damage_t>(
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_t>( "throw_glaive_damage_sb_bd_throw", source );
execute_action = p->get_background_action<throw_glaive_damage_t>(
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_t>( "throw_glaive_damage_sb_ds_throw", source );
execute_action = p->get_background_action<throw_glaive_damage_t>(
fmt::format( "{}_damage_sb_ds", name ), p->talent.havoc.screaming_brutality->effectN( 3 ).percent() );
break;
default:
damage = p->get_background_action<throw_glaive_damage_t>( "throw_glaive_damage", source );
execute_action = p->get_background_action<throw_glaive_damage_t>( 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 )
{
resource_current = RESOURCE_FURY;
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_damage_t>(
"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_damage_t>( "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_damage_t>( "throw_glaive_furious_throws_sb_ds_throw", source );
break;
default:
furious_throws = p->get_background_action<throw_glaive_damage_t>( "throw_glaive_furious_throws", source );
break;
}

furious_throws = p->get_background_action<throw_glaive_t>( 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
Expand All @@ -6447,84 +6475,55 @@ struct throw_glaive_t : public demon_hunter_attack_t
p()->template get_data_entry<simple_sample_data_t, simple_data_t>( "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<delayed_execute_event_t>( *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<demon_hunter_attack_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<delayed_execute_event_t>( *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();
}
};

Expand Down Expand Up @@ -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 );
}
Expand Down Expand Up @@ -8873,7 +8870,7 @@ void demon_hunter_t::init_spells()
active.screaming_brutality_death_sweep_throw_glaive = get_background_action<throw_glaive_t>(
"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_t>(
"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() )
Expand Down
Loading