diff --git a/engine/class_modules/sc_demon_hunter.cpp b/engine/class_modules/sc_demon_hunter.cpp index 7365c1767e2..682d2686463 100644 --- a/engine/class_modules/sc_demon_hunter.cpp +++ b/engine/class_modules/sc_demon_hunter.cpp @@ -1408,16 +1408,16 @@ class demon_hunter_t : public parse_player_effects_t void init() { - if ( p()->talent.devourer.soul_glutton.enabled() ) + if ( dh()->talent.devourer.soul_glutton.enabled() ) { // Why separate multiplier - Easier to find stuff in the future. - meta_drain_multiplier /= 1 + p()->talent.devourer.soul_glutton->effectN( 2 ).percent(); + meta_drain_multiplier /= 1 + dh()->talent.devourer.soul_glutton->effectN( 2 ).percent(); } - p()->sim->print_debug( "{} applying overall drain multiplier of {} to initial drain of {}, result: {}", *p(), + dh()->sim->print_debug( "{} applying overall drain multiplier of {} to initial drain of {}, result: {}", *dh(), meta_drain_multiplier, initial_drain, initial_drain * meta_drain_multiplier ); - p()->sim->print_debug( "{} applying overall drain multiplier of {} to exp_factor of {}, result: {}", *p(), + dh()->sim->print_debug( "{} applying overall drain multiplier of {} to exp_factor of {}, result: {}", *dh(), meta_drain_multiplier, exp_factor, exp_factor * meta_drain_multiplier ); // Handled here to do less runtime math later - If formula changes, may need to move Drain Multiplier into the calculation. @@ -1433,12 +1433,12 @@ class demon_hunter_t : public parse_player_effects_t void reset(); - demon_hunter_t* p() + demon_hunter_t* dh() { return actor; } - demon_hunter_t* p() const + demon_hunter_t* dh() const { return actor; } @@ -2083,19 +2083,19 @@ class demon_hunter_action_t : public parse_action_effects_t } } - demon_hunter_t* p() + demon_hunter_t* dh() { return static_cast( ab::player ); } - const demon_hunter_t* p() const + const demon_hunter_t* dh() const { return static_cast( ab::player ); } demon_hunter_td_t* td( player_t* t ) const { - return p()->get_target_data( t ); + return dh()->get_target_data( t ); } void init() override @@ -2108,11 +2108,11 @@ class demon_hunter_action_t : public parse_action_effects_t if ( track_cd_waste ) { cd_wasted_exec = - p()->template get_data_entry( ab::name_str, p()->cd_waste_exec ); - cd_wasted_cumulative = p()->template get_data_entry( - ab::name_str, p()->cd_waste_cumulative ); + dh()->template get_data_entry( ab::name_str, dh()->cd_waste_exec ); + cd_wasted_cumulative = dh()->template get_data_entry( + ab::name_str, dh()->cd_waste_cumulative ); cd_wasted_iter = - p()->template get_data_entry( ab::name_str, p()->cd_waste_iter ); + dh()->template get_data_entry( ab::name_str, dh()->cd_waste_iter ); } // Make sure background is set for triggered actions. @@ -2130,36 +2130,36 @@ class demon_hunter_action_t : public parse_action_effects_t void apply_buff_effects() { // Shared - ab::parse_effects( p()->buff.demon_soul ); - ab::parse_effects( p()->buff.empowered_demon_soul ); - ab::parse_effects( p()->mastery.monster_within, [ this ]( double v ) { - if ( p()->buff.enduring_torment->check() ) - v *= 1.0 + p()->buff.enduring_torment->check_value(); + ab::parse_effects( dh()->buff.demon_soul ); + ab::parse_effects( dh()->buff.empowered_demon_soul ); + ab::parse_effects( dh()->mastery.monster_within, [ this ]( double v ) { + if ( dh()->buff.enduring_torment->check() ) + v *= 1.0 + dh()->buff.enduring_torment->check_value(); return v; } ); effect_mask_t meta_mask = effect_mask_t( true ); - if ( p()->specialization() == DEMON_HUNTER_VENGEANCE && !p()->talent.vengeance.vengeful_beast->ok() ) + if ( dh()->specialization() == DEMON_HUNTER_VENGEANCE && !dh()->talent.vengeance.vengeful_beast->ok() ) { meta_mask.disable( 14 ); } - ab::parse_effects( p()->buff.metamorphosis, p()->mastery.monster_within, meta_mask ); + ab::parse_effects( dh()->buff.metamorphosis, dh()->mastery.monster_within, meta_mask ); // Devourer - ab::parse_effects( p()->buff.feast_of_souls ); - ab::parse_effects( p()->buff.rolling_torment ); - ab::parse_effects( p()->buff.impending_apocalypse ); + ab::parse_effects( dh()->buff.feast_of_souls ); + ab::parse_effects( dh()->buff.rolling_torment ); + ab::parse_effects( dh()->buff.impending_apocalypse ); // Havoc - ab::parse_effects( p()->buff.exergy ); - ab::parse_effects( p()->buff.inertia ); - ab::parse_effects( p()->buff.empowered_eye_beam ); + ab::parse_effects( dh()->buff.exergy ); + ab::parse_effects( dh()->buff.inertia ); + ab::parse_effects( dh()->buff.empowered_eye_beam ); // Vengeance // Aldrachi Reaver - ab::parse_effects( p()->buff.warblades_hunger ); - ab::parse_effects( p()->buff.thrill_of_the_fight_damage ); + ab::parse_effects( dh()->buff.warblades_hunger ); + ab::parse_effects( dh()->buff.thrill_of_the_fight_damage ); // Art of the Glaive empowered ability buffs GO std::vector art_of_the_glaive_affected_list = {}; auto art_of_the_glaive = [ &art_of_the_glaive_affected_list, this ]( int idx, buff_t* buff ) { @@ -2168,7 +2168,7 @@ class demon_hunter_action_t : public parse_action_effects_t art_of_the_glaive_affected_list.end(); }; - if ( const auto& effect = p()->talent.aldrachi_reaver.art_of_the_glaive->effectN( idx ); + if ( const auto& effect = dh()->talent.aldrachi_reaver.art_of_the_glaive->effectN( idx ); effect.ok() && in_whitelist() ) { auto added_entry = add_parse_entry( ab::da_multiplier_effects ) @@ -2187,31 +2187,31 @@ class demon_hunter_action_t : public parse_action_effects_t art_of_the_glaive_affected_list.insert( art_of_the_glaive_affected_list.end(), art_of_the_glaive_rending_strike_affected_list.begin(), art_of_the_glaive_rending_strike_affected_list.end() ); - art_of_the_glaive( 3, p()->buff.art_of_the_glaive_first ); + art_of_the_glaive( 3, dh()->buff.art_of_the_glaive_first ); // Second empowered art_of_the_glaive_affected_list = art_of_the_glaive_glaive_flurry_affected_list; - art_of_the_glaive( 4, p()->buff.art_of_the_glaive_second_glaive_flurry ); + art_of_the_glaive( 4, dh()->buff.art_of_the_glaive_second_glaive_flurry ); art_of_the_glaive_affected_list = art_of_the_glaive_rending_strike_affected_list; - art_of_the_glaive( 4, p()->buff.art_of_the_glaive_second_rending_strike ); + art_of_the_glaive( 4, dh()->buff.art_of_the_glaive_second_rending_strike ); // End Art of the Glaive bullshittery // Scarred - ab::parse_effects( p()->buff.enduring_torment ); - ab::parse_effects( p()->buff.demonsurge_demonsurge ); - ab::parse_effects( p()->buff.demonsurge_demonic_intensity ); - ab::parse_effects( p()->buff.demonsurge ); - ab::parse_effects( p()->buff.voidsurge ); + ab::parse_effects( dh()->buff.enduring_torment ); + ab::parse_effects( dh()->buff.demonsurge_demonsurge ); + ab::parse_effects( dh()->buff.demonsurge_demonic_intensity ); + ab::parse_effects( dh()->buff.demonsurge ); + ab::parse_effects( dh()->buff.voidsurge ); - ab::parse_effects( p()->talent.scarred.blind_focus, [ this ]( double v ) { - if ( p()->buff.metamorphosis->check() ) + ab::parse_effects( dh()->talent.scarred.blind_focus, [ this ]( double v ) { + if ( dh()->buff.metamorphosis->check() ) { - if ( p()->specialization() == DEMON_HUNTER_DEVOURER ) + if ( dh()->specialization() == DEMON_HUNTER_DEVOURER ) { - v *= 1.0 + p()->spec.void_metamorphosis->effectN( 16 ).percent(); + v *= 1.0 + dh()->spec.void_metamorphosis->effectN( 16 ).percent(); } else { - v *= 1.0 + p()->spec.metamorphosis_buff->effectN( 13 ).percent(); + v *= 1.0 + dh()->spec.metamorphosis_buff->effectN( 13 ).percent(); } } return v; @@ -2225,26 +2225,26 @@ class demon_hunter_action_t : public parse_action_effects_t // Shared // Devourer - ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::devourers_bite ), p()->spec.devourers_bite_debuff ); + ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::devourers_bite ), dh()->spec.devourers_bite_debuff ); // Havoc - ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::burning_wound ), p()->spec.burning_wound_debuff ); + ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::burning_wound ), dh()->spec.burning_wound_debuff ); ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::serrated_glaive ), - p()->talent.havoc.serrated_glaive->effectN( 1 ).trigger(), - p()->talent.havoc.serrated_glaive ); + dh()->talent.havoc.serrated_glaive->effectN( 1 ).trigger(), + dh()->talent.havoc.serrated_glaive ); // Vengeance - if ( p()->talent.vengeance.vulnerability->ok() ) + if ( dh()->talent.vengeance.vulnerability->ok() ) { - ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::frailty ), p()->spec.frailty_debuff, + ab::parse_target_effects( d_fn( &demon_hunter_td_t::debuffs_t::frailty ), dh()->spec.frailty_debuff, effect_mask_t( false ).enable( 4, 5 ), - p()->talent.vengeance.vulnerability->effectN( 1 ).percent() + - p()->talent.vengeance.soulcrush->effectN( 4 ).percent() ); + dh()->talent.vengeance.vulnerability->effectN( 1 ).percent() + + dh()->talent.vengeance.soulcrush->effectN( 4 ).percent() ); } // Vengeance Demon Hunter's DF S2 tier set spell data is baked into Fiery Brand's spell data at effect #4. // We exclude parsing effect #4 as that tier set is no longer active. - ab::parse_target_effects( d_fn( &demon_hunter_td_t::dots_t::fiery_brand ), p()->spec.fiery_brand_debuff, + ab::parse_target_effects( d_fn( &demon_hunter_td_t::dots_t::fiery_brand ), dh()->spec.fiery_brand_debuff, effect_mask_t( true ).disable( 4 ) ); // Aldrachi Reaver @@ -2277,24 +2277,24 @@ class demon_hunter_action_t : public parse_action_effects_t if ( affected_by.demonic_presence.direct ) { - m *= 1.0 + p()->cache.mastery_value(); + m *= 1.0 + dh()->cache.mastery_value(); } if ( affected_by.a_fire_inside.direct ) { - m *= 1.0 + p()->cache.mastery_value(); + m *= 1.0 + dh()->cache.mastery_value(); } if ( affected_by.chaotic_disposition ) { - double chance = p()->talent.havoc.chaotic_disposition->effectN( 2 ).percent() / 100; - size_t rolls = as( p()->talent.havoc.chaotic_disposition->effectN( 1 ).base_value() ); - double damage_percent = p()->talent.havoc.chaotic_disposition->effectN( 3 ).percent(); + double chance = dh()->talent.havoc.chaotic_disposition->effectN( 2 ).percent() / 100; + size_t rolls = as( dh()->talent.havoc.chaotic_disposition->effectN( 1 ).base_value() ); + double damage_percent = dh()->talent.havoc.chaotic_disposition->effectN( 3 ).percent(); double da = 0; for ( size_t i = 0; i < rolls; i++ ) { - if ( p()->rng().roll( chance ) ) + if ( dh()->rng().roll( chance ) ) { da += damage_percent; } @@ -2324,24 +2324,24 @@ class demon_hunter_action_t : public parse_action_effects_t if ( affected_by.demonic_presence.periodic ) { - m *= 1.0 + p()->cache.mastery_value(); + m *= 1.0 + dh()->cache.mastery_value(); } if ( affected_by.a_fire_inside.periodic ) { - m *= 1.0 + p()->cache.mastery_value(); + m *= 1.0 + dh()->cache.mastery_value(); } if ( affected_by.chaotic_disposition ) { - double chance = p()->talent.havoc.chaotic_disposition->effectN( 2 ).percent() / 100; - size_t rolls = as( p()->talent.havoc.chaotic_disposition->effectN( 1 ).base_value() ); - double damage_percent = p()->talent.havoc.chaotic_disposition->effectN( 3 ).percent(); + double chance = dh()->talent.havoc.chaotic_disposition->effectN( 2 ).percent() / 100; + size_t rolls = as( dh()->talent.havoc.chaotic_disposition->effectN( 1 ).base_value() ); + double damage_percent = dh()->talent.havoc.chaotic_disposition->effectN( 3 ).percent(); double da = 0; for ( size_t i = 0; i < rolls; i++ ) { - if ( p()->rng().roll( chance ) ) + if ( dh()->rng().roll( chance ) ) { da += damage_percent; } @@ -2369,10 +2369,10 @@ class demon_hunter_action_t : public parse_action_effects_t { double c = ab::composite_crit_chance(); - if ( affected_by.chaos_theory && p()->buff.chaos_theory->up() ) + if ( affected_by.chaos_theory && dh()->buff.chaos_theory->up() ) { - const double bonus = p()->rng().range( p()->talent.havoc.chaos_theory->effectN( 1 ).percent(), - p()->talent.havoc.chaos_theory->effectN( 2 ).percent() ); + const double bonus = dh()->rng().range( dh()->talent.havoc.chaos_theory->effectN( 1 ).percent(), + dh()->talent.havoc.chaos_theory->effectN( 2 ).percent() ); c += bonus; } @@ -2386,7 +2386,7 @@ class demon_hunter_action_t : public parse_action_effects_t if ( energize_delta > 0 ) { // Round the entire post-delta value as some effects (Demon Blades) with deltas have fractional values - ea = static_cast( ea + p()->rng().range( 0, 1 + energize_delta ) - ( energize_delta / 2.0 ) ); + ea = static_cast( ea + dh()->rng().range( 0, 1 + energize_delta ) - ( energize_delta / 2.0 ) ); } return ea; @@ -2433,17 +2433,17 @@ class demon_hunter_action_t : public parse_action_effects_t bool ready() override { - if ( ( ab::execute_time() > timespan_t::zero() || ab::channeled ) && p()->buff.out_of_range->check() ) + if ( ( ab::execute_time() > timespan_t::zero() || ab::channeled ) && dh()->buff.out_of_range->check() ) { return false; } - if ( p()->buff.out_of_range->check() && ab::range <= 5.0 ) + if ( dh()->buff.out_of_range->check() && ab::range <= 5.0 ) { return false; } - if ( p()->buff.fel_rush_move->check() ) + if ( dh()->buff.fel_rush_move->check() ) { return false; } @@ -2459,9 +2459,9 @@ class demon_hunter_action_t : public parse_action_effects_t ab::cooldown->last_charged < ab::sim->current_time() ) { double time_ = ( ab::sim->current_time() - ab::cooldown->last_charged ).total_seconds(); - if ( p()->sim->debug ) + if ( dh()->sim->debug ) { - p()->sim->out_debug.printf( "%s %s cooldown waste tracking waste=%.3f exec_time=%.3f", p()->name(), ab::name(), + dh()->sim->out_debug.printf( "%s %s cooldown waste tracking waste=%.3f exec_time=%.3f", dh()->name(), ab::name(), time_, ab::time_to_execute.total_seconds() ); } time_ -= ab::time_to_execute.total_seconds(); @@ -2480,7 +2480,7 @@ class demon_hunter_action_t : public parse_action_effects_t { if ( ab::resource_current == RESOURCE_FURY ) { - p()->resource_gain( ab::resource_current, ab::last_resource_cost * 0.80, p()->gain.miss_refund ); + dh()->resource_gain( ab::resource_current, ab::last_resource_cost * 0.80, dh()->gain.miss_refund ); } } @@ -2496,38 +2496,38 @@ class demon_hunter_action_t : public parse_action_effects_t } // 2024-07-12 -- Shattered Destiny only accumulates while in Metamorphosis - if ( p()->talent.havoc.shattered_destiny->ok() && p()->buff.metamorphosis->check() ) + if ( dh()->talent.havoc.shattered_destiny->ok() && dh()->buff.metamorphosis->check() ) { // 2024-07-12 -- If a cast costs Fury, it seems to use the base cost instead of the actual cost. resource_e cr = ab::current_resource(); const auto& bc = ab::base_costs[ cr ]; auto base = bc.base; - p()->shattered_destiny_accumulator += base; - const double threshold = p()->talent.havoc.shattered_destiny->effectN( 2 ).base_value(); - while ( p()->shattered_destiny_accumulator >= threshold ) + dh()->shattered_destiny_accumulator += base; + const double threshold = dh()->talent.havoc.shattered_destiny->effectN( 2 ).base_value(); + while ( dh()->shattered_destiny_accumulator >= threshold ) { - p()->shattered_destiny_accumulator -= threshold; - p()->buff.metamorphosis->extend_duration( p(), - p()->talent.havoc.shattered_destiny->effectN( 1 ).time_value() ); - p()->proc.shattered_destiny->occur(); + dh()->shattered_destiny_accumulator -= threshold; + dh()->buff.metamorphosis->extend_duration( dh(), + dh()->talent.havoc.shattered_destiny->effectN( 1 ).time_value() ); + dh()->proc.shattered_destiny->occur(); } } - if ( p()->talent.vengeance.feed_the_demon->ok() ) + if ( dh()->talent.vengeance.feed_the_demon->ok() ) { resource_e cr = ab::current_resource(); const auto& bc = ab::base_costs[ cr ]; auto base = bc.base; - p()->feed_the_demon_accumulator += base; + dh()->feed_the_demon_accumulator += base; - const double threshold = p()->talent.vengeance.feed_the_demon->effectN( 1 ).base_value(); - while ( p()->feed_the_demon_accumulator >= threshold ) + const double threshold = dh()->talent.vengeance.feed_the_demon->effectN( 1 ).base_value(); + while ( dh()->feed_the_demon_accumulator >= threshold ) { - p()->feed_the_demon_accumulator -= threshold; - p()->cooldown.demon_spikes->adjust( -p()->talent.vengeance.feed_the_demon->effectN( 2 ).time_value() ); - p()->proc.feed_the_demon->occur(); + dh()->feed_the_demon_accumulator -= threshold; + dh()->cooldown.demon_spikes->adjust( -dh()->talent.vengeance.feed_the_demon->effectN( 2 ).time_value() ); + dh()->proc.feed_the_demon->occur(); } } } @@ -2535,7 +2535,7 @@ class demon_hunter_action_t : public parse_action_effects_t void accumulate_frailty( action_state_t* s ) { - if ( !p()->talent.vengeance.frailty->ok() ) + if ( !dh()->talent.vengeance.frailty->ok() ) return; if ( !( ab::harmful && s->result_amount > 0 ) ) @@ -2546,7 +2546,7 @@ class demon_hunter_action_t : public parse_action_effects_t return; const double multiplier = target_data->debuffs.frailty->stack_value(); - p()->frailty_accumulator += s->result_amount * multiplier; + dh()->frailty_accumulator += s->result_amount * multiplier; } void trigger_chaos_brand( action_state_t* s ) @@ -2557,7 +2557,7 @@ class demon_hunter_action_t : public parse_action_effects_t if ( ab::result_is_miss( s->result ) || s->result_amount == 0.0 ) return; - if ( s->target->debuffs.chaos_brand && p()->spell.chaos_brand->ok() ) + if ( s->target->debuffs.chaos_brand && dh()->spell.chaos_brand->ok() ) { s->target->debuffs.chaos_brand->trigger(); } @@ -2568,34 +2568,34 @@ class demon_hunter_action_t : public parse_action_effects_t if ( ab::result_is_miss( s->result ) || s->result_amount == 0.0 ) return; - if ( !p()->talent.havoc.initiative->ok() ) + if ( !dh()->talent.havoc.initiative->ok() ) return; if ( !s->target->is_enemy() || td( s->target )->debuffs.initiative_tracker->check() ) return; - p()->buff.initiative->trigger(); + dh()->buff.initiative->trigger(); td( s->target )->debuffs.initiative_tracker->trigger(); } bool trigger_untethered_rage( const int souls_consumed ) { - if ( souls_consumed <= 0 || !p()->talent.vengeance.untethered_rage_1->ok() ) + if ( souls_consumed <= 0 || !dh()->talent.vengeance.untethered_rage_1->ok() ) return false; // TODO: base chance and growth factor are approximations, no spell data source - double chance_to_proc = souls_consumed * 0.0075 * pow( 1.35, p()->buff.seething_anger->stack() ); + double chance_to_proc = souls_consumed * 0.0075 * pow( 1.35, dh()->buff.seething_anger->stack() ); if ( ab::rng().roll( chance_to_proc ) ) { - p()->buff.seething_anger->expire(); - p()->buff.untethered_rage->trigger(); - p()->proc.untethered_rage->occur(); + dh()->buff.seething_anger->expire(); + dh()->buff.untethered_rage->trigger(); + dh()->proc.untethered_rage->occur(); return true; } - if ( !p()->buff.untethered_rage->up() && p()->talent.vengeance.untethered_rage_3->ok() ) + if ( !dh()->buff.untethered_rage->up() && dh()->talent.vengeance.untethered_rage_3->ok() ) { - p()->buff.seething_anger->trigger(); + dh()->buff.seething_anger->trigger(); } return false; @@ -2628,16 +2628,16 @@ struct demonsurge_trigger_t : public BASE { BASE::execute(); - BASE::p()->trigger_demonsurge( ABILITY ); + BASE::dh()->trigger_demonsurge( ABILITY ); } std::unique_ptr create_expression( util::string_view name ) override { if ( util::str_compare_ci( name, "demonsurge_available" ) ) { - if ( BASE::p()->talent.scarred.demonsurge->ok() ) + if ( BASE::dh()->talent.scarred.demonsurge->ok() ) { - return make_fn_expr( name, [ this ]() { return BASE::p()->buff.demonsurge_abilities[ ABILITY ]->check(); } ); + return make_fn_expr( name, [ this ]() { return BASE::dh()->buff.demonsurge_abilities[ ABILITY ]->check(); } ); } return expr_t::create_constant( name, 0 ); } @@ -2660,16 +2660,16 @@ struct voidsurge_trigger_t : public BASE { BASE::execute(); - BASE::p()->trigger_voidsurge( ABILITY ); + BASE::dh()->trigger_voidsurge( ABILITY ); } std::unique_ptr create_expression( util::string_view name ) override { if ( util::str_compare_ci( name, "voidsurge_available" ) ) { - if ( BASE::p()->talent.scarred.demonsurge->ok() ) + if ( BASE::dh()->talent.scarred.demonsurge->ok() ) { - return make_fn_expr( name, [ this ]() { return BASE::p()->buff.voidsurge_abilities[ ABILITY ]->check(); } ); + return make_fn_expr( name, [ this ]() { return BASE::dh()->buff.voidsurge_abilities[ ABILITY ]->check(); } ); } return expr_t::create_constant( name, 0 ); } @@ -2699,41 +2699,41 @@ struct art_of_the_glaive_trigger_t : public BASE bool second_ability = false; if ( ABILITY == art_of_the_glaive_ability::GLAIVE_FLURRY && - BASE::p()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() && BASE::p()->buff.glaive_flurry->up() ) + BASE::dh()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() && BASE::dh()->buff.glaive_flurry->up() ) { - second_ability = !BASE::p()->buff.rending_strike->up(); + second_ability = !BASE::dh()->buff.rending_strike->up(); - if ( BASE::p()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() ) + if ( BASE::dh()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() ) { - BASE::p()->active.art_of_the_glaive->execute_on_target( BASE::target ); + BASE::dh()->active.art_of_the_glaive->execute_on_target( BASE::target ); } - BASE::p()->buff.glaive_flurry->expire(); - make_event( *BASE::p()->sim, thrill_delay, [ this, second_ability ] { + BASE::dh()->buff.glaive_flurry->expire(); + make_event( *BASE::dh()->sim, thrill_delay, [ this, second_ability ] { // 2025-07-19 -- Using glaive flurry as havoc causes all subsequent death sweeps and blade dances to // gain the first art of the glaive buff, even after all related reavers glaives buffs expire until // either chaos strike of annihilation are used. - if ( BASE::p()->specialization() != DEMON_HUNTER_HAVOC ) + if ( BASE::dh()->specialization() != DEMON_HUNTER_HAVOC ) { - BASE::p()->buff.art_of_the_glaive_first->expire(); + BASE::dh()->buff.art_of_the_glaive_first->expire(); } - BASE::p()->buff.art_of_the_glaive_second_glaive_flurry->expire(); - BASE::p()->buff.art_of_the_glaive_second_rending_strike->expire(); + BASE::dh()->buff.art_of_the_glaive_second_glaive_flurry->expire(); + BASE::dh()->buff.art_of_the_glaive_second_rending_strike->expire(); if ( !second_ability ) { - BASE::p()->buff.art_of_the_glaive_second_rending_strike->trigger(); + BASE::dh()->buff.art_of_the_glaive_second_rending_strike->trigger(); } } ); } else if ( ABILITY == art_of_the_glaive_ability::RENDING_STRIKE && - BASE::p()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() && BASE::p()->buff.rending_strike->up() ) + BASE::dh()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() && BASE::dh()->buff.rending_strike->up() ) { - second_ability = !BASE::p()->buff.glaive_flurry->up(); + second_ability = !BASE::dh()->buff.glaive_flurry->up(); int first_ability_amount = 1; int second_ability_amount = - 1 + as( BASE::p()->talent.aldrachi_reaver.reavers_mark->effectN( 2 ).base_value() ); - if ( BASE::p()->talent.aldrachi_reaver.reavers_mark->ok() ) + 1 + as( BASE::dh()->talent.aldrachi_reaver.reavers_mark->effectN( 2 ).base_value() ); + if ( BASE::dh()->talent.aldrachi_reaver.reavers_mark->ok() ) { BASE::td( BASE::target ) ->debuffs.reavers_mark->trigger( second_ability ? second_ability_amount : first_ability_amount ); @@ -2741,36 +2741,36 @@ struct art_of_the_glaive_trigger_t : public BASE // 2025-07-19 -- Consuming rending strike as havoc during a death sweep before the final hit causes the // final death sweep hit to also gain the second art of the glaive damage buff. This applies that buff // temporarily during the rending strike even to ensure the final death sweep hit also gains the buff. - if ( ( BASE::p()->specialization() == DEMON_HUNTER_HAVOC ) && second_ability ) + if ( ( BASE::dh()->specialization() == DEMON_HUNTER_HAVOC ) && second_ability ) { - BASE::p()->buff.art_of_the_glaive_first->expire(); - BASE::p()->buff.art_of_the_glaive_second_glaive_flurry->trigger(); + BASE::dh()->buff.art_of_the_glaive_first->expire(); + BASE::dh()->buff.art_of_the_glaive_second_glaive_flurry->trigger(); } - BASE::p()->buff.rending_strike->expire(); - make_event( *BASE::p()->sim, thrill_delay, [ this, second_ability ] { - BASE::p()->buff.art_of_the_glaive_first->expire(); - BASE::p()->buff.art_of_the_glaive_second_glaive_flurry->expire(); - BASE::p()->buff.art_of_the_glaive_second_rending_strike->expire(); + BASE::dh()->buff.rending_strike->expire(); + make_event( *BASE::dh()->sim, thrill_delay, [ this, second_ability ] { + BASE::dh()->buff.art_of_the_glaive_first->expire(); + BASE::dh()->buff.art_of_the_glaive_second_glaive_flurry->expire(); + BASE::dh()->buff.art_of_the_glaive_second_rending_strike->expire(); if ( !second_ability ) { - BASE::p()->buff.art_of_the_glaive_second_glaive_flurry->trigger(); + BASE::dh()->buff.art_of_the_glaive_second_glaive_flurry->trigger(); } } ); } if ( second_ability ) { - if ( BASE::p()->talent.aldrachi_reaver.thrill_of_the_fight->ok() ) + if ( BASE::dh()->talent.aldrachi_reaver.thrill_of_the_fight->ok() ) { - BASE::p()->buff.thrill_of_the_fight_haste->trigger(); + BASE::dh()->buff.thrill_of_the_fight_haste->trigger(); - make_event( *BASE::p()->sim, thrill_delay, - [ this ] { BASE::p()->buff.thrill_of_the_fight_damage->trigger(); } ); + make_event( *BASE::dh()->sim, thrill_delay, + [ this ] { BASE::dh()->buff.thrill_of_the_fight_damage->trigger(); } ); } - if ( BASE::p()->talent.aldrachi_reaver.aldrachi_tactics->ok() ) + if ( BASE::dh()->talent.aldrachi_reaver.aldrachi_tactics->ok() ) { - BASE::p()->spawn_soul_fragment( BASE::p()->proc.soul_fragment_from_aldrachi_tactics, soul_fragment::LESSER ); + BASE::dh()->spawn_soul_fragment( BASE::dh()->proc.soul_fragment_from_aldrachi_tactics, soul_fragment::LESSER ); } } } @@ -2788,13 +2788,13 @@ struct exergy_trigger_t : public BASE virtual bool can_trigger_exergy() { - return BASE::p()->talent.havoc.exergy->ok(); + return BASE::dh()->talent.havoc.exergy->ok(); } void execute() override { if ( can_trigger_exergy() ) - BASE::p()->buff.exergy->trigger(); + BASE::dh()->buff.exergy->trigger(); BASE::execute(); } @@ -2812,7 +2812,7 @@ struct inertia_trigger_trigger_t : public BASE virtual bool can_trigger_inertia_trigger() { - return BASE::p()->talent.havoc.inertia->ok(); + return BASE::dh()->talent.havoc.inertia->ok(); } void execute() override @@ -2820,7 +2820,7 @@ struct inertia_trigger_trigger_t : public BASE BASE::execute(); if ( can_trigger_inertia_trigger() ) - BASE::p()->buff.inertia_trigger->trigger(); + BASE::dh()->buff.inertia_trigger->trigger(); } }; @@ -2836,7 +2836,7 @@ struct inertia_trigger_t : public BASE virtual bool can_trigger_inertia() { - return BASE::p()->talent.havoc.inertia->ok() && BASE::p()->buff.inertia_trigger->up(); + return BASE::dh()->talent.havoc.inertia->ok() && BASE::dh()->buff.inertia_trigger->up(); } void execute() override @@ -2845,8 +2845,8 @@ struct inertia_trigger_t : public BASE if ( can_trigger_inertia() ) { - BASE::p()->buff.inertia_trigger->expire(); - BASE::p()->buff.inertia->trigger(); + BASE::dh()->buff.inertia_trigger->expire(); + BASE::dh()->buff.inertia->trigger(); } } }; @@ -2863,7 +2863,7 @@ struct unbound_chaos_trigger_t : public BASE virtual bool can_trigger_unbound_chaos() { - return BASE::p()->talent.havoc.unbound_chaos->ok(); + return BASE::dh()->talent.havoc.unbound_chaos->ok(); } void execute() override @@ -2872,7 +2872,7 @@ struct unbound_chaos_trigger_t : public BASE if ( can_trigger_unbound_chaos() ) { - BASE::p()->buff.unbound_chaos->trigger(); + BASE::dh()->buff.unbound_chaos->trigger(); } } }; @@ -2891,7 +2891,7 @@ struct wounded_quarry_accumulator_t : public BASE { BASE::impact( s ); - if ( !BASE::p()->talent.aldrachi_reaver.wounded_quarry->ok() || !BASE::p()->active.wounded_quarry ) + if ( !BASE::dh()->talent.aldrachi_reaver.wounded_quarry->ok() || !BASE::dh()->active.wounded_quarry ) return; if ( BASE::school != SCHOOL_PHYSICAL ) @@ -2900,32 +2900,32 @@ struct wounded_quarry_accumulator_t : public BASE if ( s->target->is_sleeping() ) return; - if ( !BASE::p()->last_reavers_mark_applied || - !BASE::p()->get_target_data( BASE::p()->last_reavers_mark_applied )->debuffs.reavers_mark->up() ) + if ( !BASE::dh()->last_reavers_mark_applied || + !BASE::dh()->get_target_data( BASE::dh()->last_reavers_mark_applied )->debuffs.reavers_mark->up() ) return; double da = s->result_amount; if ( da > 0 ) { - da *= BASE::p()->talent.aldrachi_reaver.wounded_quarry->effectN( 1 ).percent(); - BASE::p()->wounded_quarry_accumulator += da; - BASE::p()->sim->print_debug( "{} accumulates Wounded Quarry from {} on target {}: da={} total={}", - BASE::p()->name(), s->action->name(), s->target->name(), da, - BASE::p()->wounded_quarry_accumulator ); - if ( BASE::p()->cooldown.wounded_quarry_trigger_icd->up() ) + da *= BASE::dh()->talent.aldrachi_reaver.wounded_quarry->effectN( 1 ).percent(); + BASE::dh()->wounded_quarry_accumulator += da; + BASE::dh()->sim->print_debug( "{} accumulates Wounded Quarry from {} on target {}: da={} total={}", + BASE::dh()->name(), s->action->name(), s->target->name(), da, + BASE::dh()->wounded_quarry_accumulator ); + if ( BASE::dh()->cooldown.wounded_quarry_trigger_icd->up() ) { - BASE::p()->sim->print_debug( "{} triggers Wounded Quarry from {} on target {}: {}", BASE::p()->name(), - s->action->name(), BASE::p()->last_reavers_mark_applied->name(), - BASE::p()->wounded_quarry_accumulator ); + BASE::dh()->sim->print_debug( "{} triggers Wounded Quarry from {} on target {}: {}", BASE::dh()->name(), + s->action->name(), BASE::dh()->last_reavers_mark_applied->name(), + BASE::dh()->wounded_quarry_accumulator ); if ( s->target->debuffs.chaos_brand->up() ) { - BASE::p()->wounded_quarry_accumulator *= 1.0 + BASE::p()->spell.chaos_brand->effectN( 1 ).percent(); + BASE::dh()->wounded_quarry_accumulator *= 1.0 + BASE::dh()->spell.chaos_brand->effectN( 1 ).percent(); } - BASE::p()->active.wounded_quarry->execute_on_target( BASE::p()->last_reavers_mark_applied, - BASE::p()->wounded_quarry_accumulator ); - BASE::p()->wounded_quarry_accumulator = 0.0; + BASE::dh()->active.wounded_quarry->execute_on_target( BASE::dh()->last_reavers_mark_applied, + BASE::dh()->wounded_quarry_accumulator ); + BASE::dh()->wounded_quarry_accumulator = 0.0; // per dev communication, it's batched per second - BASE::p()->cooldown.wounded_quarry_trigger_icd->start( 1_s ); + BASE::dh()->cooldown.wounded_quarry_trigger_icd->start( 1_s ); } } } @@ -2946,21 +2946,21 @@ struct voidfall_building_trigger_t : public BASE { BASE::execute(); - if ( !BASE::p()->talent.annihilator.voidfall->ok() ) + if ( !BASE::dh()->talent.annihilator.voidfall->ok() ) return; - if ( !BASE::rng().roll( BASE::p()->talent.annihilator.voidfall->effectN( 3 ).percent() ) ) + if ( !BASE::rng().roll( BASE::dh()->talent.annihilator.voidfall->effectN( 3 ).percent() ) ) return; // can't gain building while spending is up - if ( BASE::p()->buff.voidfall_spending->up() ) + if ( BASE::dh()->buff.voidfall_spending->up() ) { return; } - BASE::p()->proc.voidfall_from_builder->occur(); - BASE::p()->buff.voidfall_building->trigger( - as( BASE::p()->talent.annihilator.voidfall->effectN( 1 ).base_value() ) ); + BASE::dh()->proc.voidfall_from_builder->occur(); + BASE::dh()->buff.voidfall_building->trigger( + as( BASE::dh()->talent.annihilator.voidfall->effectN( 1 ).base_value() ) ); } }; @@ -2979,25 +2979,25 @@ struct voidfall_spending_trigger_t : public BASE { BASE::execute(); - if ( !BASE::p()->talent.annihilator.voidfall->ok() ) + if ( !BASE::dh()->talent.annihilator.voidfall->ok() ) return; - if ( !BASE::p()->buff.voidfall_spending->up() ) + if ( !BASE::dh()->buff.voidfall_spending->up() ) return; - if ( BASE::p()->buff.voidfall_spending->at_max_stacks() && BASE::p()->talent.annihilator.meteoric_fall->ok() ) + if ( BASE::dh()->buff.voidfall_spending->at_max_stacks() && BASE::dh()->talent.annihilator.meteoric_fall->ok() ) return; - BASE::p()->sim->print_debug( "{} triggering Voidfall spending", BASE::p()->name() ); + BASE::dh()->sim->print_debug( "{} triggering Voidfall spending", BASE::dh()->name() ); - if ( BASE::p()->buff.voidfall_spending->stack() == 1 && BASE::p()->talent.annihilator.world_killer->ok() && - !BASE::p()->talent.annihilator.meteoric_fall->ok() ) + if ( BASE::dh()->buff.voidfall_spending->stack() == 1 && BASE::dh()->talent.annihilator.world_killer->ok() && + !BASE::dh()->talent.annihilator.meteoric_fall->ok() ) { - BASE::p()->active.world_killer->execute_on_target( BASE::target ); + BASE::dh()->active.world_killer->execute_on_target( BASE::target ); } else { - BASE::p()->active.voidfall_meteor->execute_on_target( BASE::target ); + BASE::dh()->active.voidfall_meteor->execute_on_target( BASE::target ); } } }; @@ -3017,30 +3017,30 @@ struct meteoric_fall_trigger_t : public BASE { BASE::execute(); - if ( !BASE::p()->talent.annihilator.meteoric_fall->ok() ) + if ( !BASE::dh()->talent.annihilator.meteoric_fall->ok() ) return; - if ( !BASE::p()->buff.voidfall_spending->at_max_stacks() ) + if ( !BASE::dh()->buff.voidfall_spending->at_max_stacks() ) return; - BASE::p()->sim->print_debug( "{} triggering Meteoric Fall", BASE::p()->name() ); + BASE::dh()->sim->print_debug( "{} triggering Meteoric Fall", BASE::dh()->name() ); - int stacks = BASE::p()->buff.voidfall_spending->stack(); - if ( BASE::p()->talent.annihilator.world_killer->ok() ) + int stacks = BASE::dh()->buff.voidfall_spending->stack(); + if ( BASE::dh()->talent.annihilator.world_killer->ok() ) { stacks -= 1; } for ( int i = 0; i < stacks; ++i ) { - make_event( *BASE::sim, BASE::p(), BASE::p()->active.voidfall_meteor, BASE::target, - ( BASE::p()->active.voidfall_meteor->travel_time() * i ) ); + make_event( *BASE::sim, BASE::dh(), BASE::dh()->active.voidfall_meteor, BASE::target, + ( BASE::dh()->active.voidfall_meteor->travel_time() * i ) ); } - if ( BASE::p()->talent.annihilator.world_killer->ok() ) + if ( BASE::dh()->talent.annihilator.world_killer->ok() ) { - make_event( *BASE::sim, BASE::p(), BASE::p()->active.world_killer, BASE::target, - ( stacks * BASE::p()->active.voidfall_meteor->travel_time() ) ); + make_event( *BASE::sim, BASE::dh(), BASE::dh()->active.world_killer, BASE::target, + ( stacks * BASE::dh()->active.voidfall_meteor->travel_time() ) ); } } }; @@ -3060,14 +3060,14 @@ struct burning_blades_trigger_t : public BASE { BASE::impact( s ); - if ( !BASE::p()->talent.scarred.burning_blades->ok() ) + if ( !BASE::dh()->talent.scarred.burning_blades->ok() ) return; if ( !action_t::result_is_hit( s->result ) ) return; - const double dot_damage = s->result_amount * BASE::p()->talent.scarred.burning_blades->effectN( 1 ).percent(); - residual_action::trigger( BASE::p()->active.burning_blades, s->target, dot_damage ); + const double dot_damage = s->result_amount * BASE::dh()->talent.scarred.burning_blades->effectN( 1 ).percent(); + residual_action::trigger( BASE::dh()->active.burning_blades, s->target, dot_damage ); } }; @@ -3086,17 +3086,17 @@ struct burning_blades_live_trigger_t : public BASE { BASE::impact( s ); - if ( BASE::p()->is_ptr() ) + if ( BASE::dh()->is_ptr() ) return; - if ( !BASE::p()->talent.scarred.burning_blades->ok() ) + if ( !BASE::dh()->talent.scarred.burning_blades->ok() ) return; if ( !action_t::result_is_hit( s->result ) ) return; - const double dot_damage = s->result_amount * BASE::p()->talent.scarred.burning_blades->effectN( 1 ).percent(); - residual_action::trigger( BASE::p()->active.burning_blades, s->target, dot_damage ); + const double dot_damage = s->result_amount * BASE::dh()->talent.scarred.burning_blades->effectN( 1 ).percent(); + residual_action::trigger( BASE::dh()->active.burning_blades, s->target, dot_damage ); } }; @@ -3115,17 +3115,17 @@ struct burning_blades_ptr_trigger_t : public BASE { BASE::impact( s ); - if ( !BASE::p()->is_ptr() ) + if ( !BASE::dh()->is_ptr() ) return; - if ( !BASE::p()->talent.scarred.burning_blades->ok() ) + if ( !BASE::dh()->talent.scarred.burning_blades->ok() ) return; if ( !action_t::result_is_hit( s->result ) ) return; - const double dot_damage = s->result_amount * BASE::p()->talent.scarred.burning_blades->effectN( 1 ).percent(); - residual_action::trigger( BASE::p()->active.burning_blades, s->target, dot_damage ); + const double dot_damage = s->result_amount * BASE::dh()->talent.scarred.burning_blades->effectN( 1 ).percent(); + residual_action::trigger( BASE::dh()->active.burning_blades, s->target, dot_damage ); } }; @@ -3144,14 +3144,14 @@ struct catastrophe_trigger_t : public BASE { BASE::impact( s ); - if ( !BASE::p()->talent.annihilator.catastrophe->ok() ) + if ( !BASE::dh()->talent.annihilator.catastrophe->ok() ) return; if ( !action_t::result_is_hit( s->result ) ) return; - const double dot_damage = s->result_amount * BASE::p()->talent.annihilator.catastrophe->effectN( 1 ).percent(); - residual_action::trigger( BASE::p()->active.catastrophe, s->target, dot_damage ); + const double dot_damage = s->result_amount * BASE::dh()->talent.annihilator.catastrophe->effectN( 1 ).percent(); + residual_action::trigger( BASE::dh()->active.catastrophe, s->target, dot_damage ); } }; @@ -3170,20 +3170,20 @@ struct mass_acceleration_trigger_t : public BASE { BASE::execute(); - if ( !BASE::p()->talent.annihilator.mass_acceleration->ok() ) + if ( !BASE::dh()->talent.annihilator.mass_acceleration->ok() ) return; - BASE::p()->proc.voidfall_from_mass_acceleration->occur(); - BASE::p()->buff.voidfall_building->trigger( - as( BASE::p()->talent.annihilator.mass_acceleration->effectN( 1 ).base_value() ) ); + BASE::dh()->proc.voidfall_from_mass_acceleration->occur(); + BASE::dh()->buff.voidfall_building->trigger( + as( BASE::dh()->talent.annihilator.mass_acceleration->effectN( 1 ).base_value() ) ); - switch ( BASE::p()->specialization() ) + switch ( BASE::dh()->specialization() ) { case DEMON_HUNTER_DEVOURER: - BASE::p()->cooldown.reap->reset( true ); + BASE::dh()->cooldown.reap->reset( true ); break; case DEMON_HUNTER_VENGEANCE: - BASE::p()->cooldown.spirit_bomb->reset( true ); + BASE::dh()->cooldown.spirit_bomb->reset( true ); break; default: break; @@ -3206,14 +3206,14 @@ struct dark_matter_trigger_t : public BASE { BASE::execute(); - if ( !BASE::p()->talent.annihilator.dark_matter->ok() ) + if ( !BASE::dh()->talent.annihilator.dark_matter->ok() ) return; - if ( !BASE::p()->buff.dark_matter->up() ) + if ( !BASE::dh()->buff.dark_matter->up() ) return; - BASE::p()->buff.dark_matter->expire(); - BASE::p()->active.meteor_shower->execute_on_target( BASE::target ); + BASE::dh()->buff.dark_matter->expire(); + BASE::dh()->active.meteor_shower->execute_on_target( BASE::target ); } }; @@ -3232,8 +3232,8 @@ struct hungering_slash_trigger_t : BASE { BASE::execute(); - if ( BASE::p()->talent.devourer.hungering_slash->ok() ) - BASE::p()->buff.hungering_slash->trigger(); + if ( BASE::dh()->talent.devourer.hungering_slash->ok() ) + BASE::dh()->buff.hungering_slash->trigger(); } }; @@ -3252,8 +3252,8 @@ struct voidrush_trigger_t : BASE { BASE::execute(); - if ( BASE::p()->talent.devourer.voidrush->ok() ) - BASE::p()->buff.voidrush->trigger(); + if ( BASE::dh()->talent.devourer.voidrush->ok() ) + BASE::dh()->buff.voidrush->trigger(); } }; @@ -3272,30 +3272,30 @@ struct doomsayer_trigger_t : public BASE { BASE::execute(); - if ( !BASE::p()->talent.annihilator.doomsayer->ok() ) + if ( !BASE::dh()->talent.annihilator.doomsayer->ok() ) return; - if ( !( BASE::p()->buff.doomsayer_in_combat->up() || BASE::p()->buff.doomsayer_out_of_combat->up() ) ) + if ( !( BASE::dh()->buff.doomsayer_in_combat->up() || BASE::dh()->buff.doomsayer_out_of_combat->up() ) ) return; - BASE::p()->sim->print_debug( "{} triggering Doomsayer", BASE::p()->name() ); + BASE::dh()->sim->print_debug( "{} triggering Doomsayer", BASE::dh()->name() ); - int meteors_to_trigger = as( BASE::p()->talent.annihilator.doomsayer->effectN( 1 ).base_value() ); - if ( BASE::p()->talent.annihilator.world_killer->ok() ) + int meteors_to_trigger = as( BASE::dh()->talent.annihilator.doomsayer->effectN( 1 ).base_value() ); + if ( BASE::dh()->talent.annihilator.world_killer->ok() ) { meteors_to_trigger -= 1; } - BASE::p()->buff.doomsayer_in_combat->expire(); - BASE::p()->buff.doomsayer_out_of_combat->expire(); + BASE::dh()->buff.doomsayer_in_combat->expire(); + BASE::dh()->buff.doomsayer_out_of_combat->expire(); for ( int i = 0; i < meteors_to_trigger; ++i ) { - BASE::p()->active.voidfall_meteor->execute_on_target( BASE::target ); + BASE::dh()->active.voidfall_meteor->execute_on_target( BASE::target ); } - if ( BASE::p()->talent.annihilator.world_killer->ok() ) + if ( BASE::dh()->talent.annihilator.world_killer->ok() ) { - BASE::p()->active.world_killer->execute_on_target( BASE::target ); + BASE::dh()->active.world_killer->execute_on_target( BASE::target ); } } }; @@ -3315,12 +3315,12 @@ struct final_breath_trigger_t : public BASE { BASE::last_tick( d ); - if ( !BASE::p()->talent.demon_hunter.final_breath->ok() ) + if ( !BASE::dh()->talent.demon_hunter.final_breath->ok() ) return; assert( BASE::tick_action != nullptr ); - if ( d->current_tick >= ( d->num_ticks() - BASE::p()->options.channel_tick_cutoff_benefit ) ) + if ( d->current_tick >= ( d->num_ticks() - BASE::dh()->options.channel_tick_cutoff_benefit ) ) { action_state_t* tick_state = BASE::tick_action->get_state( BASE::tick_action->execute_state ); if ( BASE::tick_action->pre_execute_state ) @@ -3338,7 +3338,7 @@ struct final_breath_trigger_t : public BASE } BASE::tick_action->snapshot_state( tick_state, result_amount_type::DMG_DIRECT ); - tick_state->da_multiplier *= BASE::p()->talent.demon_hunter.final_breath->effectN( 1 ).percent(); + tick_state->da_multiplier *= BASE::dh()->talent.demon_hunter.final_breath->effectN( 1 ).percent(); BASE::tick_action->schedule_execute( tick_state ); } @@ -3360,9 +3360,9 @@ struct student_of_suffering_trigger_t : public BASE { BASE::execute(); - if ( BASE::p()->talent.scarred.student_of_suffering->ok() ) + if ( BASE::dh()->talent.scarred.student_of_suffering->ok() ) { - BASE::p()->buff.student_of_suffering->trigger(); + BASE::dh()->buff.student_of_suffering->trigger(); } } }; @@ -3382,15 +3382,15 @@ struct otherworldly_focus_benefit_t : public BASE { double m = BASE::composite_da_multiplier( s ); - if ( BASE::p()->talent.annihilator.otherworldly_focus->ok() ) + if ( BASE::dh()->talent.annihilator.otherworldly_focus->ok() ) { // 1 target is always effect 1 % // 2 target is effect 1 % - effect 2 % // 3 target is effect 1 % - (effect 2 % * 2) // etc until reaching 0 benefit - auto num_target_reduction_percent = BASE::p()->talent.annihilator.otherworldly_focus->effectN( 2 ).percent() * + auto num_target_reduction_percent = BASE::dh()->talent.annihilator.otherworldly_focus->effectN( 2 ).percent() * ( std::max( std::min( s->n_targets - 1, 10U ), 0U ) ); - m *= 1.0 + std::max( 0.0, BASE::p()->talent.annihilator.otherworldly_focus->effectN( 1 ).percent() - + m *= 1.0 + std::max( 0.0, BASE::dh()->talent.annihilator.otherworldly_focus->effectN( 1 ).percent() - num_target_reduction_percent ); } @@ -3422,7 +3422,7 @@ struct shattered_souls_trigger_t : public BASE { BASE::impact( s ); - if ( BASE::p()->specialization() != DEMON_HUNTER_DEVOURER ) + if ( BASE::dh()->specialization() != DEMON_HUNTER_DEVOURER ) return; if ( !BASE::result_is_hit( s->result ) || s->proc_type() == PROC1_PERIODIC || s->result_total <= 0 ) @@ -3431,9 +3431,9 @@ struct shattered_souls_trigger_t : public BASE double chance = shattered_souls_chance( s ); if ( BASE::rng().roll( chance ) ) { - BASE::p()->sim->print_debug( "{} proc-ed Shattered Souls with {} ({}) chance: {:.3f}", BASE::p()->name(), + BASE::dh()->sim->print_debug( "{} proc-ed Shattered Souls with {} ({}) chance: {:.3f}", BASE::dh()->name(), BASE::name(), BASE::data().id(), chance ); - BASE::p()->spawn_soul_fragment( BASE::p()->proc.soul_fragment_from_shattered_souls, soul_fragment::LESSER, 1 ); + BASE::dh()->spawn_soul_fragment( BASE::dh()->proc.soul_fragment_from_shattered_souls, soul_fragment::LESSER, 1 ); shattered_souls_proc->occur(); } } @@ -3507,7 +3507,7 @@ struct demon_hunter_sigil_t : public demon_hunter_spell_t void place_sigil( player_t* target ) { - make_event( *sim, p(), + make_event( *sim, dh(), ground_aoe_params_t() .target( target ) .x( target->x_position ) @@ -3523,10 +3523,10 @@ struct demon_hunter_sigil_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); - if ( hit_any_target && p()->talent.vengeance.soul_sigils->ok() ) + if ( hit_any_target && dh()->talent.vengeance.soul_sigils->ok() ) { - unsigned num_souls = as( p()->talent.vengeance.soul_sigils->effectN( 1 ).base_value() ); - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_soul_sigils, soul_fragment::LESSER, num_souls, false ); + unsigned num_souls = as( dh()->talent.vengeance.soul_sigils->effectN( 1 ).base_value() ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_soul_sigils, soul_fragment::LESSER, num_souls, false ); } } @@ -3598,7 +3598,7 @@ struct consume_soul_t : public demon_hunter_heal_t double calculate_heal( const action_state_t* ) const { - switch ( p()->specialization() ) + switch ( dh()->specialization() ) { case DEMON_HUNTER_VENGEANCE: if ( type == soul_fragment::LESSER ) @@ -3622,9 +3622,9 @@ struct consume_soul_t : public demon_hunter_heal_t { double pct = demon_hunter_heal_t::composite_pct_heal( s ); - if ( p()->talent.demon_hunter.shattered_restoration->ok() ) + if ( dh()->talent.demon_hunter.shattered_restoration->ok() ) { - pct *= 1.0 + p()->talent.demon_hunter.shattered_restoration->effectN( 1 ).percent(); + pct *= 1.0 + dh()->talent.demon_hunter.shattered_restoration->effectN( 1 ).percent(); } return pct; @@ -3634,9 +3634,9 @@ struct consume_soul_t : public demon_hunter_heal_t double base_da_min( const action_state_t* s ) const override { double base_heal = calculate_heal( s ); - if ( p()->talent.demon_hunter.shattered_restoration->ok() ) + if ( dh()->talent.demon_hunter.shattered_restoration->ok() ) { - base_heal *= 1.0 + p()->talent.demon_hunter.shattered_restoration->effectN( 1 ).percent(); + base_heal *= 1.0 + dh()->talent.demon_hunter.shattered_restoration->effectN( 1 ).percent(); } return base_heal; } @@ -3645,9 +3645,9 @@ struct consume_soul_t : public demon_hunter_heal_t double base_da_max( const action_state_t* s ) const override { double base_heal = calculate_heal( s ); - if ( p()->talent.demon_hunter.shattered_restoration->ok() ) + if ( dh()->talent.demon_hunter.shattered_restoration->ok() ) { - base_heal *= 1.0 + p()->talent.demon_hunter.shattered_restoration->effectN( 1 ).percent(); + base_heal *= 1.0 + dh()->talent.demon_hunter.shattered_restoration->effectN( 1 ).percent(); } return base_heal; } @@ -3662,36 +3662,36 @@ struct consume_soul_t : public demon_hunter_heal_t { demon_hunter_heal_t::impact( s ); - p()->buff.painbringer->trigger(); - p()->buff.art_of_the_glaive->trigger(); + dh()->buff.painbringer->trigger(); + dh()->buff.art_of_the_glaive->trigger(); - p()->buff.feast_of_souls->trigger(); - if ( !p()->buff.metamorphosis->up() ) + dh()->buff.feast_of_souls->trigger(); + if ( !dh()->buff.metamorphosis->up() ) { - p()->buff.void_metamorphosis_stack->trigger(); + dh()->buff.void_metamorphosis_stack->trigger(); } else { - if ( p()->talent.devourer.collapsing_star->ok() ) + if ( dh()->talent.devourer.collapsing_star->ok() ) { - p()->buff.collapsing_star_stack->trigger(); + dh()->buff.collapsing_star_stack->trigger(); } - if ( p()->talent.devourer.emptiness->ok() ) + if ( dh()->talent.devourer.emptiness->ok() ) { - p()->buff.emptiness->trigger(); + dh()->buff.emptiness->trigger(); } } // Warblade's hunger currently applies an additional stack on first buff application - if ( !p()->buff.warblades_hunger->up() ) + if ( !dh()->buff.warblades_hunger->up() ) { - p()->buff.warblades_hunger->trigger(); + dh()->buff.warblades_hunger->trigger(); } - p()->buff.warblades_hunger->trigger(); + dh()->buff.warblades_hunger->trigger(); if ( type == soul_fragment::GREATER_DEMON ) { - p()->buff.demon_soul->trigger(); + dh()->buff.demon_soul->trigger(); } } }; @@ -3732,13 +3732,13 @@ struct soul_barrier_t : public demon_hunter_action_t void execute() override { - souls_consumed = p()->consume_soul_fragments( soul_fragment::ANY, false ); + souls_consumed = dh()->consume_soul_fragments( soul_fragment::ANY, false ); demon_hunter_action_t::execute(); } void impact( action_state_t* s ) override { - p()->buff.soul_barrier->trigger( 1, s->result_amount ); + dh()->buff.soul_barrier->trigger( 1, s->result_amount ); } }; @@ -3806,7 +3806,7 @@ struct blur_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); - p()->buff.blur->trigger(); + dh()->buff.blur->trigger(); } }; @@ -3865,7 +3865,7 @@ struct demon_spikes_t : public demon_hunter_spell_t void execute() override { demon_hunter_spell_t::execute(); - p()->buff.demon_spikes->trigger(); + dh()->buff.demon_spikes->trigger(); } }; @@ -3927,9 +3927,9 @@ struct eye_beam_base_t : public student_of_suffering_trigger_ttalent.havoc.isolated_prey->ok() && targets_in_range_list( target_list() ).size() == 1 ) + if ( dh()->talent.havoc.isolated_prey->ok() && targets_in_range_list( target_list() ).size() == 1 ) { - m *= 1.0 + p()->talent.havoc.isolated_prey->effectN( 2 ).percent(); + m *= 1.0 + dh()->talent.havoc.isolated_prey->effectN( 2 ).percent(); } return m; @@ -3939,7 +3939,7 @@ struct eye_beam_base_t : public student_of_suffering_trigger_tsim->default_aura_delay ); + return rng().gauss( dh()->sim->default_aura_delay ); } }; @@ -3982,65 +3982,65 @@ struct eye_beam_base_t : public student_of_suffering_trigger_tcurrent_tick < d->num_ticks() ) { - p()->buff.blind_fury->cancel(); - p()->proc.eye_beam_canceled->occur(); + dh()->buff.blind_fury->cancel(); + dh()->proc.eye_beam_canceled->occur(); } - if ( p()->talent.havoc.furious_gaze->ok() && - d->current_tick >= ( d->num_ticks() - p()->options.channel_tick_cutoff_benefit ) ) + if ( dh()->talent.havoc.furious_gaze->ok() && + d->current_tick >= ( d->num_ticks() - dh()->options.channel_tick_cutoff_benefit ) ) { - p()->buff.furious_gaze->trigger(); + dh()->buff.furious_gaze->trigger(); } - if ( p()->talent.havoc.eternal_hunt_3->ok() && - d->current_tick >= ( d->num_ticks() - p()->options.channel_tick_cutoff_benefit ) ) + if ( dh()->talent.havoc.eternal_hunt_3->ok() && + d->current_tick >= ( d->num_ticks() - dh()->options.channel_tick_cutoff_benefit ) ) { - p()->buff.eternal_hunt->trigger(); + dh()->buff.eternal_hunt->trigger(); } - if ( p()->buff.empowered_eye_beam->up() ) + if ( dh()->buff.empowered_eye_beam->up() ) { - p()->buff.empowered_eye_beam->expire(); + dh()->buff.empowered_eye_beam->expire(); } } void execute() override { // Trigger Meta before the execute so that the channel duration is affected by Meta haste - p()->trigger_demonic(); + dh()->trigger_demonic(); tick_action = tick; - if ( empowered_tick && p()->buff.empowered_eye_beam->up() ) + if ( empowered_tick && dh()->buff.empowered_eye_beam->up() ) { tick_action = empowered_tick; } base_t::execute(); - if ( p()->talent.havoc.cycle_of_hatred->ok() ) + if ( dh()->talent.havoc.cycle_of_hatred->ok() ) { - p()->buff.cycle_of_hatred->trigger(); + dh()->buff.cycle_of_hatred->trigger(); } timespan_t duration = composite_dot_duration( execute_state ); // Since Demonic triggers Meta with 5s + hasted duration, need to extend by the hasted duration after have an // execute_state - if ( p()->talent.havoc.demonic->ok() ) + if ( dh()->talent.havoc.demonic->ok() ) { - p()->buff.metamorphosis->extend_duration( p(), duration ); + dh()->buff.metamorphosis->extend_duration( dh(), duration ); } - if ( p()->talent.havoc.blind_fury->ok() ) + if ( dh()->talent.havoc.blind_fury->ok() ) { - p()->buff.blind_fury->trigger( duration ); + dh()->buff.blind_fury->trigger( duration ); } // Collective Anguish - if ( p()->active.collective_anguish ) + if ( dh()->active.collective_anguish ) { - p()->active.collective_anguish->set_target( target ); - p()->active.collective_anguish->execute(); + dh()->active.collective_anguish->set_target( target ); + dh()->active.collective_anguish->execute(); } } @@ -4052,7 +4052,7 @@ struct eye_beam_base_t : public student_of_suffering_trigger_t( p()->buff.cycle_of_hatred->check_stack_value() ) ); + timespan_t::from_millis( as( dh()->buff.cycle_of_hatred->check_stack_value() ) ); } }; @@ -4083,7 +4083,7 @@ struct eye_beam_t : public eye_beam_base_t double cost() const override { - if ( p()->buff.demonsurge_demonic_intensity->check() ) + if ( dh()->buff.demonsurge_demonic_intensity->check() ) { return abyssal_gaze_cost; } @@ -4092,7 +4092,7 @@ struct eye_beam_t : public eye_beam_base_t void execute() override { - if ( p()->buff.demonsurge_demonic_intensity->check() ) + if ( dh()->buff.demonsurge_demonic_intensity->check() ) { abyssal_gaze->execute_on_target( target ); stats->add_execute( time_to_execute, target ); @@ -4164,7 +4164,7 @@ struct fel_devastation_t : public final_breath_trigger_t void execute() override { - p()->trigger_demonic(); + dh()->trigger_demonic(); base_t::execute(); if ( heal ) @@ -4178,23 +4178,23 @@ struct fel_devastation_t : public final_breath_trigger_t { base_t::last_tick( d ); - if ( p()->talent.vengeance.darkglare_boon->ok() ) + if ( dh()->talent.vengeance.darkglare_boon->ok() ) { // CDR reduction and Fury refund are separate rolls per Realz - double base_cooldown = p()->talent.vengeance.fel_devastation->cooldown().total_seconds(); + double base_cooldown = dh()->talent.vengeance.fel_devastation->cooldown().total_seconds(); timespan_t minimum_cdr_reduction = - timespan_t::from_seconds( p()->talent.vengeance.darkglare_boon->effectN( 1 ).percent() * base_cooldown ); + timespan_t::from_seconds( dh()->talent.vengeance.darkglare_boon->effectN( 1 ).percent() * base_cooldown ); timespan_t maximum_cdr_reduction = - timespan_t::from_seconds( p()->talent.vengeance.darkglare_boon->effectN( 2 ).percent() * base_cooldown ); + timespan_t::from_seconds( dh()->talent.vengeance.darkglare_boon->effectN( 2 ).percent() * base_cooldown ); timespan_t cdr_reduction = rng().range( minimum_cdr_reduction, maximum_cdr_reduction ); - double minimum_fury_refund = p()->talent.vengeance.darkglare_boon->effectN( 3 ).base_value(); - double maximum_fury_refund = p()->talent.vengeance.darkglare_boon->effectN( 4 ).base_value(); + double minimum_fury_refund = dh()->talent.vengeance.darkglare_boon->effectN( 3 ).base_value(); + double maximum_fury_refund = dh()->talent.vengeance.darkglare_boon->effectN( 4 ).base_value(); double fury_refund = rng().range( minimum_fury_refund, maximum_fury_refund ); - p()->sim->print_debug( "{} rolled {}s of CDR on {} from Darkglare Boon", *p(), cdr_reduction.total_seconds(), + dh()->sim->print_debug( "{} rolled {}s of CDR on {} from Darkglare Boon", *dh(), cdr_reduction.total_seconds(), name_str ); - p()->cooldown.fel_devastation->adjust( -cdr_reduction ); - p()->resource_gain( RESOURCE_FURY, fury_refund, p()->gain.darkglare_boon ); + dh()->cooldown.fel_devastation->adjust( -cdr_reduction ); + dh()->resource_gain( RESOURCE_FURY, fury_refund, dh()->gain.darkglare_boon ); } } @@ -4207,13 +4207,13 @@ struct fel_devastation_t : public final_breath_trigger_t base_t::tick( d ); - if ( p()->talent.annihilator.meteoric_rise->ok() ) + if ( dh()->talent.annihilator.meteoric_rise->ok() ) { int expected_before = ( d->current_tick - 1 ) * soul_fragments_from_meteoric_rise / d->num_ticks(); int expected_after = d->current_tick * soul_fragments_from_meteoric_rise / d->num_ticks(); if ( expected_after > expected_before ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_meteoric_rise, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_meteoric_rise, soul_fragment::LESSER ); } } } @@ -4270,7 +4270,7 @@ struct fiery_brand_t : public demon_hunter_spell_t { // Fiery Brand can be extended beyond the 10s duration, but any hardcast Fiery Brand always overwrites existing // DoT to 10s. - if ( triggered_duration == p()->spec.fiery_brand_debuff->duration() ) + if ( triggered_duration == dh()->spec.fiery_brand_debuff->duration() ) { return triggered_duration; } @@ -4299,7 +4299,7 @@ struct fiery_brand_t : public demon_hunter_spell_t void trigger_burning_alive( dot_t* d ) { - if ( !p()->talent.vengeance.burning_alive->ok() ) + if ( !dh()->talent.vengeance.burning_alive->ok() ) return; if ( !debug_cast( d->state )->primary ) @@ -4321,7 +4321,7 @@ struct fiery_brand_t : public demon_hunter_spell_t return; // Execute a dot on a random target - player_t* target = targets[ static_cast( p()->rng().range( 0, static_cast( targets.size() ) ) ) ]; + player_t* target = targets[ static_cast( dh()->rng().range( 0, static_cast( targets.size() ) ) ) ]; this->set_target( target ); this->schedule_execute(); } @@ -4392,14 +4392,14 @@ struct glaive_tempest_t : public demon_hunter_spell_t // Has one initial period for 2*(6+1) ticks plus hasted duration and tick rate // However, hasted duration is snapshotted on cast, which is likely a bug // This allows it to sometimes tick more or less than the intended 14 times - make_event( *sim, p(), + make_event( *sim, dh(), ground_aoe_params_t() .target( execute_state->target ) - .x( p()->x_position ) - .y( p()->y_position ) + .x( dh()->x_position ) + .y( dh()->y_position ) .pulse_time( 500_ms ) .hasted( ground_aoe_params_t::hasted_with::ATTACK_HASTE ) - .duration( data().duration() * p()->cache.attack_haste() ) + .duration( data().duration() * dh()->cache.attack_haste() ) .action( action ), true ); } @@ -4430,7 +4430,7 @@ struct sigil_of_flame_t : public demon_hunter_spell_t demon_hunter_sigil_t::impact( s ); // Sigil of Flame can apply Frailty if Frailty is talented - if ( result_is_hit( s->result ) && p()->talent.vengeance.frailty->ok() ) + if ( result_is_hit( s->result ) && dh()->talent.vengeance.frailty->ok() ) { td( s->target )->debuffs.frailty->trigger(); } @@ -4580,7 +4580,7 @@ struct infernal_strike_t : public doomsayer_trigger_t { base_t::execute(); - if ( felfire_fist && ( p()->buff.felfire_fist_in_combat->up() || p()->buff.felfire_fist_out_of_combat->up() ) ) + if ( felfire_fist && ( dh()->buff.felfire_fist_in_combat->up() || dh()->buff.felfire_fist_out_of_combat->up() ) ) { felfire_fist->place_sigil( target ); } @@ -4696,7 +4696,7 @@ struct immolation_aura_t : public demon_hunter_spell_t { double ccc = demon_hunter_spell_t::composite_crit_chance(); - if ( p()->talent.havoc.isolated_prey->ok() ) + if ( dh()->talent.havoc.isolated_prey->ok() ) { if ( targets_in_range_list( target_list() ).size() == 1 ) { @@ -4716,19 +4716,19 @@ struct immolation_aura_t : public demon_hunter_spell_t if ( result_is_hit( s->result ) ) { bool spawn_fallout_soul = false; - if ( p()->talent.vengeance.fallout->ok() ) + if ( dh()->talent.vengeance.fallout->ok() ) { spawn_fallout_soul = s->n_targets == 1 || rng().roll( 0.60 ); } if ( initial && spawn_fallout_soul ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_fallout, soul_fragment::LESSER, 1 ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_fallout, soul_fragment::LESSER, 1 ); } - if ( p()->talent.vengeance.charred_flesh->ok() ) + if ( dh()->talent.vengeance.charred_flesh->ok() ) { - auto duration_extension = p()->talent.vengeance.charred_flesh->effectN( 1 ).time_value(); + auto duration_extension = dh()->talent.vengeance.charred_flesh->effectN( 1 ).time_value(); demon_hunter_td_t* target_data = td( s->target ); if ( target_data->dots.fiery_brand->is_ticking() ) { @@ -4740,14 +4740,14 @@ struct immolation_aura_t : public demon_hunter_spell_t } } - if ( s->result == RESULT_CRIT && p()->talent.vengeance.volatile_flameblood->ok() && - p()->cooldown.volatile_flameblood_icd->up() ) + if ( s->result == RESULT_CRIT && dh()->talent.vengeance.volatile_flameblood->ok() && + dh()->cooldown.volatile_flameblood_icd->up() ) { - p()->resource_gain( RESOURCE_FURY, p()->talent.vengeance.volatile_flameblood->effectN( 1 ).base_value(), - p()->talent.vengeance.volatile_flameblood->effectN( 1 ).m_delta(), - p()->gain.volatile_flameblood ); - p()->cooldown.volatile_flameblood_icd->start( - p()->talent.vengeance.volatile_flameblood->internal_cooldown() ); + dh()->resource_gain( RESOURCE_FURY, dh()->talent.vengeance.volatile_flameblood->effectN( 1 ).base_value(), + dh()->talent.vengeance.volatile_flameblood->effectN( 1 ).m_delta(), + dh()->gain.volatile_flameblood ); + dh()->cooldown.volatile_flameblood_icd->start( + dh()->talent.vengeance.volatile_flameblood->internal_cooldown() ); } accumulate_ragefire( cast_state( s ) ); @@ -4823,20 +4823,20 @@ struct immolation_aura_t : public demon_hunter_spell_t void execute() override { - p()->buff.immolation_aura->trigger(); + dh()->buff.immolation_aura->trigger(); demon_hunter_spell_t::execute(); - p()->trigger_demonsurge( demonsurge_ability::CONSUMING_FIRE ); + dh()->trigger_demonsurge( demonsurge_ability::CONSUMING_FIRE ); } std::unique_ptr create_expression( util::string_view name ) override { if ( util::str_compare_ci( name, "demonsurge_available" ) ) { - if ( p()->talent.scarred.demonsurge->ok() ) + if ( dh()->talent.scarred.demonsurge->ok() ) { return make_fn_expr( name, [ this ]() { - return p()->buff.demonsurge_abilities[ demonsurge_ability::CONSUMING_FIRE ]->check(); + return dh()->buff.demonsurge_abilities[ demonsurge_ability::CONSUMING_FIRE ]->check(); } ); } return expr_t::create_constant( name, 0 ); @@ -4909,7 +4909,7 @@ struct metamorphosis_t : public mass_acceleration_trigger_tspecialization() ) + switch ( dh()->specialization() ) { case DEMON_HUNTER_DEVOURER: return timespan_t::zero(); @@ -4925,68 +4925,68 @@ struct metamorphosis_t : public mass_acceleration_trigger_tbuff.untethered_rage->up(); + bool untethered = dh()->buff.untethered_rage->up(); base_t::execute(); - switch ( p()->specialization() ) + switch ( dh()->specialization() ) { case DEMON_HUNTER_DEVOURER: for ( voidsurge_ability ability : voidsurge_abilities ) { - p()->buff.voidsurge_abilities[ ability ]->trigger(); + dh()->buff.voidsurge_abilities[ ability ]->trigger(); } - p()->buff.demonsurge_demonsurge->trigger(); - p()->buff.demonsurge_demonic_intensity->trigger(); - p()->buff.demonsurge->expire(); + dh()->buff.demonsurge_demonsurge->trigger(); + dh()->buff.demonsurge_demonic_intensity->trigger(); + dh()->buff.demonsurge->expire(); - p()->devourer_fury_state.start(); + dh()->devourer_fury_state.start(); - p()->buff.dark_matter->trigger(); + dh()->buff.dark_matter->trigger(); - if ( p()->talent.scarred.violent_transformation->ok() ) + if ( dh()->talent.scarred.violent_transformation->ok() ) { - p()->cooldown.voidblade->reset( true ); - p()->cooldown.predators_wake->reset( true ); + dh()->cooldown.voidblade->reset( true ); + dh()->cooldown.predators_wake->reset( true ); } break; case DEMON_HUNTER_HAVOC: for ( demonsurge_ability ability : demonsurge_abilities ) { - p()->buff.demonsurge_abilities[ ability ]->trigger(); + dh()->buff.demonsurge_abilities[ ability ]->trigger(); } - p()->buff.demonsurge_demonic_intensity->trigger(); - p()->buff.demonsurge->expire(); + dh()->buff.demonsurge_demonic_intensity->trigger(); + dh()->buff.demonsurge->expire(); // Buff is gained at the start of the leap. - p()->buff.metamorphosis->extend_duration_or_trigger(); + dh()->buff.metamorphosis->extend_duration_or_trigger(); - if ( p()->talent.havoc.chaotic_transformation->ok() ) + if ( dh()->talent.havoc.chaotic_transformation->ok() ) { - p()->cooldown.eye_beam->reset( false ); - p()->cooldown.blade_dance->reset( false ); + dh()->cooldown.eye_beam->reset( false ); + dh()->cooldown.blade_dance->reset( false ); } - if ( p()->talent.scarred.violent_transformation->ok() ) + if ( dh()->talent.scarred.violent_transformation->ok() ) { - p()->cooldown.immolation_aura->reset( false, -1 ); - p()->cooldown.sigil_of_flame->reset( false ); + dh()->cooldown.immolation_aura->reset( false, -1 ); + dh()->cooldown.sigil_of_flame->reset( false ); } // Cancel all previous movement events, as Metamorphosis is ground-targeted // If we are landing outside of point-blank range, trigger the movement buff - p()->set_out_of_range( timespan_t::zero() ); + dh()->set_out_of_range( timespan_t::zero() ); if ( landing_distance > 0.0 ) { - p()->buff.metamorphosis_move->distance_moved = landing_distance; - p()->buff.metamorphosis_move->trigger(); + dh()->buff.metamorphosis_move->distance_moved = landing_distance; + dh()->buff.metamorphosis_move->trigger(); } - if ( p()->talent.scarred.volatile_instinct->ok() ) + if ( dh()->talent.scarred.volatile_instinct->ok() ) { - p()->trigger_demonsurge( + dh()->trigger_demonsurge( demonsurge_ability::ENTER_META, - timespan_t::from_millis( p()->hero_spec.demonsurge_meta_trigger->effectN( 1 ).misc_value1() ), false ); + timespan_t::from_millis( dh()->hero_spec.demonsurge_meta_trigger->effectN( 1 ).misc_value1() ), false ); } break; case DEMON_HUNTER_VENGEANCE: @@ -4994,14 +4994,14 @@ struct metamorphosis_t : public mass_acceleration_trigger_ttalent.vengeance.untethered_rage_1->effectN( 1 ).base_value() ); - p()->buff.metamorphosis->extend_duration_or_trigger( ur_duration ); + timespan_t::from_seconds( dh()->talent.vengeance.untethered_rage_1->effectN( 1 ).base_value() ); + dh()->buff.metamorphosis->extend_duration_or_trigger( ur_duration ); } else { - p()->buff.metamorphosis->trigger(); + dh()->buff.metamorphosis->trigger(); } - p()->buff.dark_matter->trigger(); + dh()->buff.dark_matter->trigger(); break; default: break; @@ -5010,7 +5010,7 @@ struct metamorphosis_t : public mass_acceleration_trigger_tspecialization() == DEMON_HUNTER_DEVOURER && !p()->buff.void_metamorphosis_stack->at_max_stacks() ) + if ( dh()->specialization() == DEMON_HUNTER_DEVOURER && !dh()->buff.void_metamorphosis_stack->at_max_stacks() ) { return false; } @@ -5021,9 +5021,9 @@ struct metamorphosis_t : public mass_acceleration_trigger_tbuff.untethered_rage->up() ) + if ( dh()->buff.untethered_rage->up() ) { - p()->buff.untethered_rage->expire(); + dh()->buff.untethered_rage->expire(); } else { @@ -5163,23 +5163,23 @@ struct pick_up_fragment_t : public demon_hunter_spell_t double dtm; if ( frag->is_type( soul_fragment::EMPOWERED_DEMON ) ) { - dtm = std::max( 0.0, frag->get_distance( p() ) - 6.0 ); + dtm = std::max( 0.0, frag->get_distance( dh() ) - 6.0 ); } else { - switch ( p()->specialization() ) + switch ( dh()->specialization() ) { case DEMON_HUNTER_DEVOURER: - dtm = std::max( 0.0, frag->get_distance( p() ) - 4.0 ); + dtm = std::max( 0.0, frag->get_distance( dh() ) - 4.0 ); break; case DEMON_HUNTER_HAVOC: - dtm = std::max( 0.0, frag->get_distance( p() ) - 8.0 ); + dtm = std::max( 0.0, frag->get_distance( dh() ) - 8.0 ); break; case DEMON_HUNTER_VENGEANCE: - dtm = std::max( 0.0, frag->get_distance( p() ) - 4.0 ); + dtm = std::max( 0.0, frag->get_distance( dh() ) - 4.0 ); break; default: - dtm = std::max( 0.0, frag->get_distance( p() ) - 6.0 ); + dtm = std::max( 0.0, frag->get_distance( dh() ) - 6.0 ); break; } if ( frag->is_type( soul_fragment::GREATER_DEMON ) ) @@ -5187,7 +5187,7 @@ struct pick_up_fragment_t : public demon_hunter_spell_t dtm -= 2.0; } } - timespan_t mt = timespan_t::from_seconds( dtm / p()->cache.run_speed() ); + timespan_t mt = timespan_t::from_seconds( dtm / dh()->cache.run_speed() ); return mt; } @@ -5200,7 +5200,7 @@ struct pick_up_fragment_t : public demon_hunter_spell_t { case soul_fragment_select_mode::NEAREST: candidate_value = timespan_t::max(); - for ( auto frag : p()->soul_fragments ) + for ( auto frag : dh()->soul_fragments ) { timespan_t movement_time = calculate_movement_time( frag ); if ( frag->is_type( type ) && frag->active() && frag->remains() > movement_time ) @@ -5216,7 +5216,7 @@ struct pick_up_fragment_t : public demon_hunter_spell_t break; case soul_fragment_select_mode::NEWEST: candidate_value = timespan_t::min(); - for ( auto frag : p()->soul_fragments ) + for ( auto frag : dh()->soul_fragments ) { timespan_t remains = frag->remains(); if ( frag->is_type( type ) && frag->active() && remains > calculate_movement_time( frag ) ) @@ -5233,7 +5233,7 @@ struct pick_up_fragment_t : public demon_hunter_spell_t case soul_fragment_select_mode::OLDEST: default: candidate_value = timespan_t::max(); - for ( auto frag : p()->soul_fragments ) + for ( auto frag : dh()->soul_fragments ) { timespan_t remains = frag->remains(); if ( frag->is_type( type ) && frag->active() && remains > calculate_movement_time( frag ) ) @@ -5260,18 +5260,18 @@ struct pick_up_fragment_t : public demon_hunter_spell_t assert( frag ); timespan_t time = calculate_movement_time( frag ); - assert( p()->soul_fragment_pick_up == nullptr ); - p()->soul_fragment_pick_up = make_event( *sim, frag, time, if_expr.get() ); + assert( dh()->soul_fragment_pick_up == nullptr ); + dh()->soul_fragment_pick_up = make_event( *sim, frag, time, if_expr.get() ); } bool ready() override { - if ( p()->soul_fragment_pick_up ) + if ( dh()->soul_fragment_pick_up ) { return false; } - if ( !p()->get_active_soul_fragments( type ) ) + if ( !dh()->get_active_soul_fragments( type ) ) { return false; } @@ -5282,7 +5282,7 @@ struct pick_up_fragment_t : public demon_hunter_spell_t } // Not usable during the root effect of Stormeater's Boon - if ( p()->buffs.stormeaters_boon && p()->buffs.stormeaters_boon->check() ) + if ( dh()->buffs.stormeaters_boon && dh()->buffs.stormeaters_boon->check() ) return false; // Catch edge case where a fragment exists but we can't pick it up in time. @@ -5309,7 +5309,7 @@ struct spirit_bomb_t : public demon_hunter_spell_t base_t::impact( s ); // Spirit Bomb can apply Frailty if Frailty is talented - if ( result_is_hit( s->result ) && p()->talent.vengeance.frailty->ok() ) + if ( result_is_hit( s->result ) && dh()->talent.vengeance.frailty->ok() ) { td( s->target )->debuffs.frailty->trigger(); } @@ -5339,7 +5339,7 @@ struct spirit_bomb_t : public demon_hunter_spell_t demon_hunter_spell_t::execute(); // Soul fragments consumed are capped for Spirit Bomb - const int fragments_consumed = p()->consume_soul_fragments( soul_fragment::ANY, true, max_fragments_consumed ); + const int fragments_consumed = dh()->consume_soul_fragments( soul_fragment::ANY, true, max_fragments_consumed ); if ( fragments_consumed > 0 ) { damage->set_target( target ); @@ -5356,7 +5356,7 @@ struct spirit_bomb_t : public demon_hunter_spell_t bool action_ready() override { - if ( p()->get_active_soul_fragments() < 1 ) + if ( dh()->get_active_soul_fragments() < 1 ) return false; return demon_hunter_spell_t::action_ready(); @@ -5369,7 +5369,7 @@ struct spirit_bomb_t : public demon_hunter_spell_t if ( util::str_compare_ci( name, "souls_consumed" ) ) return make_fn_expr( name, [ this ]() { - return std::min( p()->get_active_soul_fragments( soul_fragment::ANY ), max_fragments_consumed ); + return std::min( dh()->get_active_soul_fragments( soul_fragment::ANY ), max_fragments_consumed ); } ); return demon_hunter_spell_t::create_expression( name ); @@ -5394,7 +5394,7 @@ struct sigil_of_spite_t : public demon_hunter_spell_t void execute() override { demon_hunter_sigil_t::execute(); - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_sigil_of_spite, soul_fragment::LESSER, + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_sigil_of_spite, soul_fragment::LESSER, soul_fragments_to_spawn ); } }; @@ -5427,7 +5427,7 @@ struct sigil_of_spite_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); sigil->place_sigil( target ); - p()->buff.reavers_glaive->trigger(); + dh()->buff.reavers_glaive->trigger(); } std::unique_ptr create_expression( util::string_view name ) override @@ -5472,21 +5472,21 @@ struct the_hunt_base_t { base_t::impact( s ); - if ( s->chain_target == 0 && p()->talent.devourer.devourers_bite->ok() ) + if ( s->chain_target == 0 && dh()->talent.devourer.devourers_bite->ok() ) { td( target )->debuffs.devourers_bite->trigger(); } - if ( s->chain_target == 0 && p()->talent.aldrachi_reaver.broken_spirit->ok() ) + if ( s->chain_target == 0 && dh()->talent.aldrachi_reaver.broken_spirit->ok() ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); } - if ( s->chain_target == 0 && p()->specialization() == DEMON_HUNTER_DEVOURER && p()->is_ptr() && - p()->talent.scarred.violent_transformation->ok() ) + if ( s->chain_target == 0 && dh()->specialization() == DEMON_HUNTER_DEVOURER && dh()->is_ptr() && + dh()->talent.scarred.violent_transformation->ok() ) { // only resets one charge of Soul Immo - p()->cooldown.soul_immolation->reset( true, 1 ); + dh()->cooldown.soul_immolation->reset( true, 1 ); } } }; @@ -5503,11 +5503,11 @@ struct the_hunt_base_t { base_t::execute(); - p()->set_out_of_range( timespan_t::zero() ); // Cancel all other movement + dh()->set_out_of_range( timespan_t::zero() ); // Cancel all other movement - p()->buff.reavers_glaive->trigger(); + dh()->buff.reavers_glaive->trigger(); - p()->buff.empowered_eye_beam->trigger(); + dh()->buff.empowered_eye_beam->trigger(); } timespan_t travel_time() const override @@ -5525,7 +5525,7 @@ struct predators_wake_t : public voidsurge_trigger_ttalent.scarred.demonic_intensity->ok() || !p()->buff.metamorphosis->check() ) + if ( !dh()->talent.scarred.demonic_intensity->ok() || !dh()->buff.metamorphosis->check() ) { return false; } @@ -5541,8 +5541,8 @@ struct the_hunt_t : public the_hunt_base_t bool action_ready() override { - if ( p()->specialization() == DEMON_HUNTER_DEVOURER && p()->talent.scarred.demonic_intensity->ok() && - p()->buff.metamorphosis->check() ) + if ( dh()->specialization() == DEMON_HUNTER_DEVOURER && dh()->talent.scarred.demonic_intensity->ok() && + dh()->buff.metamorphosis->check() ) { return false; } @@ -5703,15 +5703,15 @@ struct surge_base_t : public demon_hunter_spell_t double m = demon_hunter_spell_t::composite_da_multiplier( s ); // Focused Hatred increases _surge damage when hitting less than 6 targets - if ( p()->talent.scarred.focused_hatred->ok() && s->n_targets <= 5 ) + if ( dh()->talent.scarred.focused_hatred->ok() && s->n_targets <= 5 ) { // 1 target is always effect 1 % // 2 target is effect 1 % - effect 2 % // 3 target is effect 1 % - (effect 2 % * 2) // etc up to 5 target auto num_target_reduction_percent = - p()->talent.scarred.focused_hatred->effectN( 2 ).percent() * ( s->n_targets - 1 ); - m *= 1.0 + ( p()->talent.scarred.focused_hatred->effectN( 1 ).percent() - num_target_reduction_percent ); + dh()->talent.scarred.focused_hatred->effectN( 2 ).percent() * ( s->n_targets - 1 ); + m *= 1.0 + ( dh()->talent.scarred.focused_hatred->effectN( 1 ).percent() - num_target_reduction_percent ); } return m; @@ -5727,7 +5727,7 @@ struct demonsurge_t : public surge_base_t void execute() override { surge_base_t::execute(); - p()->buff.demonsurge->trigger(); + dh()->buff.demonsurge->trigger(); } }; @@ -5740,7 +5740,7 @@ struct voidsurge_t : public surge_base_t void execute() override { surge_base_t::execute(); - p()->buff.voidsurge->trigger(); + dh()->buff.voidsurge->trigger(); } }; @@ -5758,10 +5758,10 @@ struct consume_base_t : public shattered_souls_trigger_ttalent.devourer.predators_thirst->ok() ) + if ( dh()->talent.devourer.predators_thirst->ok() ) { - p()->spawn_soul_fragment( soul_fragment_generation_proc, soul_fragment::LESSER, - as( p()->spec.shattered_souls->effectN( 3 ).base_value() ) ); + dh()->spawn_soul_fragment( soul_fragment_generation_proc, soul_fragment::LESSER, + as( dh()->spec.shattered_souls->effectN( 3 ).base_value() ) ); } } }; @@ -5781,19 +5781,19 @@ struct devour_t : public consume_base_t { consume_base_t::init_finished(); - soul_fragment_generation_proc = p()->proc.soul_fragment_from_devour; + soul_fragment_generation_proc = dh()->proc.soul_fragment_from_devour; } void execute() override { consume_base_t::execute(); - p()->cooldown.reap->adjust( -reap_cdr ); + dh()->cooldown.reap->adjust( -reap_cdr ); } bool action_ready() override { - if ( !p()->buff.metamorphosis->check() ) + if ( !dh()->buff.metamorphosis->check() ) { return false; } @@ -5813,12 +5813,12 @@ struct consume_t : public consume_base_t { consume_base_t::init_finished(); - soul_fragment_generation_proc = p()->proc.soul_fragment_from_consume; + soul_fragment_generation_proc = dh()->proc.soul_fragment_from_consume; } bool action_ready() override { - if ( p()->buff.metamorphosis->check() ) + if ( dh()->buff.metamorphosis->check() ) { return false; } @@ -5842,7 +5842,7 @@ struct voidblade_base_t : public voidrush_trigger_tresult ) && p()->talent.devourer.devourers_bite->ok() ) + if ( result_is_hit( s->result ) && dh()->talent.devourer.devourers_bite->ok() ) { td( s->target )->debuffs.devourers_bite->trigger(); } @@ -5863,7 +5863,7 @@ struct voidblade_base_t : public voidrush_trigger_tbuff.hungering_slash->check() ) + if ( dh()->buff.hungering_slash->check() ) { return false; } @@ -5881,7 +5881,7 @@ struct pierce_the_veil_t : public voidsurge_trigger_tbuff.metamorphosis->check() ) + if ( !dh()->buff.metamorphosis->check() ) { return false; } @@ -5899,7 +5899,7 @@ struct voidblade_t : public voidblade_base_t bool action_ready() override { - if ( p()->talent.scarred.demonsurge->ok() && p()->buff.metamorphosis->check() ) + if ( dh()->talent.scarred.demonsurge->ok() && dh()->buff.metamorphosis->check() ) { return false; } @@ -5942,13 +5942,13 @@ struct soul_immolation_base_t : public demon_hunter_spell_t void execute() override { - target = p(); + target = dh(); demon_hunter_spell_t::execute(); } void impact( action_state_t* s ) override { - assert( s->target == p() ); + assert( s->target == dh() ); demon_hunter_spell_t::impact( s ); } @@ -5959,7 +5959,7 @@ struct soul_immolation_base_t : public demon_hunter_spell_t // seems to spawn a soul fragment every other tick, starting with the first tick if ( d->current_tick % 2 == 0 ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_soul_immolation, soul_fragment::LESSER, 1 ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_soul_immolation, soul_fragment::LESSER, 1 ); } } @@ -5967,17 +5967,17 @@ struct soul_immolation_base_t : public demon_hunter_spell_t { demon_hunter_spell_t::last_tick( d ); - if ( p()->talent.scarred.undying_embers->ok() && - rng().roll( p()->talent.scarred.undying_embers->effectN( 2 ).percent() ) ) + if ( dh()->talent.scarred.undying_embers->ok() && + rng().roll( dh()->talent.scarred.undying_embers->effectN( 2 ).percent() ) ) { - p()->proc.undying_embers->occur(); + dh()->proc.undying_embers->occur(); // retriggers the DoT but doesn't count as a cast/execute action_state_t* undying_embers_state = get_state(); undying_embers_state->target = d->state->target; snapshot_state( undying_embers_state, result_amount_type::DMG_OVER_TIME ); - make_event( *sim, p(), this, undying_embers_state ); + make_event( *sim, dh(), this, undying_embers_state ); } } }; @@ -5990,7 +5990,7 @@ struct soul_immolation_t : public soul_immolation_base_t bool action_ready() override { - if ( !p()->is_ptr() && p()->talent.devourer.spontaneous_immolation->ok() ) + if ( !dh()->is_ptr() && dh()->talent.devourer.spontaneous_immolation->ok() ) { return false; } @@ -6010,7 +6010,7 @@ struct spontaneous_immolation_t : public soul_immolation_base_t { soul_immolation_base_t::execute(); - p()->proc.spontaneous_immolation->occur(); + dh()->proc.spontaneous_immolation->occur(); } }; @@ -6025,13 +6025,13 @@ struct soul_immolation_heal_t : public demon_hunter_heal_t void execute() override { - target = p(); + target = dh(); demon_hunter_heal_t::execute(); } void impact( action_state_t* s ) override { - assert( s->target == p() ); + assert( s->target == dh() ); demon_hunter_heal_t::impact( s ); } @@ -6042,7 +6042,7 @@ struct soul_immolation_heal_t : public demon_hunter_heal_t // seems to spawn a soul fragment every other tick, starting with the first tick if ( d->current_tick % 2 == 0 ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_soul_immolation, soul_fragment::LESSER, 1 ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_soul_immolation, soul_fragment::LESSER, 1 ); } } @@ -6050,17 +6050,17 @@ struct soul_immolation_heal_t : public demon_hunter_heal_t { demon_hunter_heal_t::last_tick( d ); - if ( p()->talent.scarred.undying_embers->ok() && - rng().roll( p()->talent.scarred.undying_embers->effectN( 2 ).percent() ) ) + if ( dh()->talent.scarred.undying_embers->ok() && + rng().roll( dh()->talent.scarred.undying_embers->effectN( 2 ).percent() ) ) { - p()->proc.undying_embers->occur(); + dh()->proc.undying_embers->occur(); // retriggers the DoT but doesn't count as a cast/execute action_state_t* undying_embers_state = get_state(); undying_embers_state->target = d->state->target; snapshot_state( undying_embers_state, result_amount_type::HEAL_OVER_TIME ); - make_event( *sim, p(), this, undying_embers_state ); + make_event( *sim, dh(), this, undying_embers_state ); } } }; @@ -6095,10 +6095,10 @@ struct reap_base_t : public voidfall_spending_trigger_t( p()->spec.shattered_souls->effectN( 2 ).base_value() ); - if ( p()->buff.moment_of_craving->up() ) + unsigned int souls = as( dh()->spec.shattered_souls->effectN( 2 ).base_value() ); + if ( dh()->buff.moment_of_craving->up() ) { - souls += as( p()->buff.moment_of_craving->check_value() ); + souls += as( dh()->buff.moment_of_craving->check_value() ); } return souls; } @@ -6110,7 +6110,7 @@ struct reap_base_t : public voidfall_spending_trigger_tget_active_soul_fragments( soul_fragment::ANY ), souls_to_consume() ); + return std::min( dh()->get_active_soul_fragments( soul_fragment::ANY ), souls_to_consume() ); } ); return base_t::create_expression( name ); @@ -6118,27 +6118,27 @@ struct reap_base_t : public voidfall_spending_trigger_tbuff.reap->trigger(); + dh()->buff.reap->trigger(); base_t::execute(); - unsigned fragments_consumed = p()->consume_soul_fragments( soul_fragment::LESSER, false, souls_to_consume() ); + unsigned fragments_consumed = dh()->consume_soul_fragments( soul_fragment::LESSER, false, souls_to_consume() ); // TOCHECK: This delay is a guess based on averages in logs as there is no spelldata - make_event( *p()->sim, 220_ms, [ this, fragments_consumed ] { + make_event( *dh()->sim, 220_ms, [ this, fragments_consumed ] { damage_action->set_target( target ); action_state_t* damage_state = damage_action->get_state(); damage_state->target = target; damage_action->snapshot_state( damage_state, result_amount_type::DMG_DIRECT ); - if ( p()->talent.devourer.soulshaper->ok() ) + if ( dh()->talent.devourer.soulshaper->ok() ) { damage_state->da_multiplier *= - 1.0 + fragments_consumed * p()->talent.devourer.soulshaper->effectN( 1 ).percent(); + 1.0 + fragments_consumed * dh()->talent.devourer.soulshaper->effectN( 1 ).percent(); } damage_action->schedule_execute( damage_state ); } ); - p()->buff.moment_of_craving->expire(); + dh()->buff.moment_of_craving->expire(); } }; @@ -6183,10 +6183,10 @@ struct eradicate_t : public voidfall_spending_trigger_t( p()->spec.shattered_souls->effectN( 2 ).base_value() ); - if ( p()->buff.moment_of_craving->up() ) + unsigned int souls = as( dh()->spec.shattered_souls->effectN( 2 ).base_value() ); + if ( dh()->buff.moment_of_craving->up() ) { - souls += as( p()->buff.moment_of_craving->check_value() ); + souls += as( dh()->buff.moment_of_craving->check_value() ); } return souls; } @@ -6198,7 +6198,7 @@ struct eradicate_t : public voidfall_spending_trigger_tget_active_soul_fragments( soul_fragment::ANY ), souls_to_consume() ); + return std::min( dh()->get_active_soul_fragments( soul_fragment::ANY ), souls_to_consume() ); } ); return base_t::create_expression( name ); @@ -6206,36 +6206,36 @@ struct eradicate_t : public voidfall_spending_trigger_tbuff.reap->trigger(); + dh()->buff.reap->trigger(); base_t::execute(); - unsigned fragments_consumed = p()->consume_soul_fragments( soul_fragment::LESSER, false, souls_to_consume() ); - auto damage = p()->buff.metamorphosis->up() ? damage_action_meta : damage_action; + unsigned fragments_consumed = dh()->consume_soul_fragments( soul_fragment::LESSER, false, souls_to_consume() ); + auto damage = dh()->buff.metamorphosis->up() ? damage_action_meta : damage_action; // TOCHECK: This delay is a guess based on averages in logs as there is no spelldata - make_event( *p()->sim, 220_ms, [ this, fragments_consumed, damage ] { + make_event( *dh()->sim, 220_ms, [ this, fragments_consumed, damage ] { damage->set_target( target ); action_state_t* damage_state = damage->get_state(); damage_state->target = target; damage->snapshot_state( damage_state, result_amount_type::DMG_DIRECT ); - if ( p()->talent.devourer.soulshaper->ok() ) + if ( dh()->talent.devourer.soulshaper->ok() ) { damage_state->da_multiplier *= - 1.0 + fragments_consumed * p()->talent.devourer.soulshaper->effectN( 1 ).percent(); + 1.0 + fragments_consumed * dh()->talent.devourer.soulshaper->effectN( 1 ).percent(); } damage->schedule_execute( damage_state ); } ); - p()->buff.moment_of_craving->expire(); + dh()->buff.moment_of_craving->expire(); - p()->buff.eradicate->expire(); + dh()->buff.eradicate->expire(); } bool action_ready() override { - if ( !p()->buff.eradicate->check() ) + if ( !dh()->buff.eradicate->check() ) { return false; } @@ -6253,7 +6253,7 @@ struct cull_t : public reap_base_t bool action_ready() override { - if ( p()->buff.eradicate->check() || !p()->buff.metamorphosis->check() ) + if ( dh()->buff.eradicate->check() || !dh()->buff.metamorphosis->check() ) { return false; } @@ -6271,7 +6271,7 @@ struct reap_t : public reap_base_t bool action_ready() override { - if ( p()->buff.eradicate->check() || p()->buff.metamorphosis->check() ) + if ( dh()->buff.eradicate->check() || dh()->buff.metamorphosis->check() ) { return false; } @@ -6297,10 +6297,10 @@ struct void_ray_t { double m = base_t::composite_da_multiplier( s ); - if ( p()->talent.devourer.focused_ray->ok() && - s->n_targets <= as( p()->talent.devourer.focused_ray->effectN( 2 ).base_value() ) ) + if ( dh()->talent.devourer.focused_ray->ok() && + s->n_targets <= as( dh()->talent.devourer.focused_ray->effectN( 2 ).base_value() ) ) { - m *= 1.0 + p()->talent.devourer.focused_ray->effectN( 1 ).percent(); + m *= 1.0 + dh()->talent.devourer.focused_ray->effectN( 1 ).percent(); } return m; @@ -6310,7 +6310,7 @@ struct void_ray_t { // Void Beam is applied via a player aura and experiences aura delay in applying damage tick events // Not a perfect implementation, but closer than the instant execution in current sims - return rng().gauss( p()->sim->default_aura_delay ); + return rng().gauss( dh()->sim->default_aura_delay ); } double cost() const override @@ -6322,7 +6322,7 @@ struct void_ray_t double shattered_souls_chance( action_state_t* s ) override { double m = base_t::shattered_souls_chance( s ); - if ( p()->options.shattered_souls_chance_aoe_reduction_linear ) + if ( dh()->options.shattered_souls_chance_aoe_reduction_linear ) m /= s->n_targets; // Reduce Void Ray Soul Generation - Estimate is approximately n^(0.3 ~ 0.33) @@ -6380,47 +6380,47 @@ struct void_ray_t { base_t::last_tick( d ); - if ( d->current_tick >= ( d->num_ticks() - p()->options.channel_tick_cutoff_benefit ) ) + if ( d->current_tick >= ( d->num_ticks() - dh()->options.channel_tick_cutoff_benefit ) ) { - if ( p()->talent.devourer.eradicate->ok() ) + if ( dh()->talent.devourer.eradicate->ok() ) { - p()->buff.eradicate->trigger(); + dh()->buff.eradicate->trigger(); } - if ( p()->talent.devourer.moment_of_craving->ok() ) + if ( dh()->talent.devourer.moment_of_craving->ok() ) { - p()->buff.moment_of_craving->trigger(); - p()->cooldown.reap->reset( true ); + dh()->buff.moment_of_craving->trigger(); + dh()->cooldown.reap->reset( true ); } if ( voidglare_boon_energize ) { voidglare_boon_energize->execute(); } - if ( p()->talent.annihilator.meteoric_rise->ok() ) + if ( dh()->talent.annihilator.meteoric_rise->ok() ) { - p()->proc.voidfall_from_meteoric_rise->occur(); - p()->buff.voidfall_building->trigger(); + dh()->proc.voidfall_from_meteoric_rise->occur(); + dh()->buff.voidfall_building->trigger(); } } - p()->devourer_fury_state.reschedule_drain(); + dh()->devourer_fury_state.reschedule_drain(); } void execute() override { - tick_action = p()->buff.metamorphosis->up() ? tick_meta : tick; - cooldown->duration = p()->buff.metamorphosis->up() ? p()->spec.void_metamorphosis->effectN( 8 ).time_value() + - p()->talent.devourer.voidpurge->effectN( 1 ).time_value() - : p()->talent.devourer.void_ray->cooldown(); + tick_action = dh()->buff.metamorphosis->up() ? tick_meta : tick; + cooldown->duration = dh()->buff.metamorphosis->up() ? dh()->spec.void_metamorphosis->effectN( 8 ).time_value() + + dh()->talent.devourer.voidpurge->effectN( 1 ).time_value() + : dh()->talent.devourer.void_ray->cooldown(); base_t::execute(); - p()->devourer_fury_state.reschedule_drain(); + dh()->devourer_fury_state.reschedule_drain(); } bool action_ready() override { // Void Ray requires 100 Fury to cast but doesn't cost 100 Fury - if ( p()->buff.metamorphosis->up() || p()->resource_available( RESOURCE_FURY, data().cost( POWER_FURY ) ) ) + if ( dh()->buff.metamorphosis->up() || dh()->resource_available( RESOURCE_FURY, data().cost( POWER_FURY ) ) ) { return base_t::action_ready(); } @@ -6441,8 +6441,8 @@ struct void_ray_t } // Void Ray costs 5 Fury per tick outside of Meta, 0 in Meta - return p()->buff.metamorphosis->check() ? p()->spec.void_ray_tick_meta->cost( POWER_FURY ) - : p()->spec.void_ray_tick->cost( POWER_FURY ); + return dh()->buff.metamorphosis->check() ? dh()->spec.void_ray_tick_meta->cost( POWER_FURY ) + : dh()->spec.void_ray_tick->cost( POWER_FURY ); } result_amount_type amount_type( const action_state_t*, bool ) const override @@ -6467,9 +6467,9 @@ struct collapsing_star_t : public demon_hunter_spell_t { auto cm = base_t::composite_crit_damage_bonus_multiplier(); - if ( p()->talent.devourer.midnight2->ok() ) + if ( dh()->talent.devourer.midnight2->ok() ) { - cm *= 1.0 + p()->talent.devourer.midnight2->effectN( 3 ).percent() * p()->cache.spell_crit_chance(); + cm *= 1.0 + dh()->talent.devourer.midnight2->effectN( 3 ).percent() * dh()->cache.spell_crit_chance(); } return cm; @@ -6481,7 +6481,7 @@ struct collapsing_star_t : public demon_hunter_spell_t if ( s->chain_target == 0 ) { - m *= 1.0 + p()->spec.collapsing_star_spell->effectN( 2 ).percent(); + m *= 1.0 + dh()->spec.collapsing_star_spell->effectN( 2 ).percent(); } return m; @@ -6491,16 +6491,16 @@ struct collapsing_star_t : public demon_hunter_spell_t { base_t::execute(); - if ( p()->talent.devourer.star_fragments->ok() ) + if ( dh()->talent.devourer.star_fragments->ok() ) { - unsigned fragments_to_spawn = as( p()->talent.devourer.star_fragments->effectN( 1 ).base_value() ); - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_star_fragments, soul_fragment::LESSER, + unsigned fragments_to_spawn = as( dh()->talent.devourer.star_fragments->effectN( 1 ).base_value() ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_star_fragments, soul_fragment::LESSER, fragments_to_spawn ); } - if ( p()->talent.devourer.voidrush->ok() ) + if ( dh()->talent.devourer.voidrush->ok() ) { - p()->cooldown.voidblade->adjust( -p()->talent.devourer.voidrush->effectN( 1 ).time_value() ); + dh()->cooldown.voidblade->adjust( -dh()->talent.devourer.voidrush->effectN( 1 ).time_value() ); } } @@ -6508,9 +6508,9 @@ struct collapsing_star_t : public demon_hunter_spell_t { base_t::impact( s ); - if ( p()->talent.devourer.impending_apocalypse->ok() && s->chain_target == 0 ) + if ( dh()->talent.devourer.impending_apocalypse->ok() && s->chain_target == 0 ) { - make_event( *p()->sim, 1.2_s, [ this ] { p()->buff.impending_apocalypse->trigger(); } ); + make_event( *dh()->sim, 1.2_s, [ this ] { dh()->buff.impending_apocalypse->trigger(); } ); } } }; @@ -6537,14 +6537,14 @@ struct collapsing_star_t : public demon_hunter_spell_t void execute() override { - p()->buff.collapsing_star->expire(); - p()->buff.collapsing_star_stack->decrement( soul_cost ); + dh()->buff.collapsing_star->expire(); + dh()->buff.collapsing_star_stack->decrement( soul_cost ); demon_hunter_spell_t::execute(); } bool action_ready() override { - if ( !p()->buff.collapsing_star->check() ) + if ( !dh()->buff.collapsing_star->check() ) { return false; } @@ -6578,7 +6578,7 @@ struct voidfall_meteor_base_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); - p()->buff.voidfall_spending->decrement(); + dh()->buff.voidfall_spending->decrement(); } }; @@ -6604,15 +6604,15 @@ struct world_killer_t : public voidfall_meteor_base_t { voidfall_meteor_base_t::impact( s ); - switch ( p()->specialization() ) + switch ( dh()->specialization() ) { case DEMON_HUNTER_DEVOURER: - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_world_killer, soul_fragment::LESSER, - as( p()->talent.annihilator.world_killer->effectN( 4 ).base_value() ) ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_world_killer, soul_fragment::LESSER, + as( dh()->talent.annihilator.world_killer->effectN( 4 ).base_value() ) ); break; case DEMON_HUNTER_VENGEANCE: - p()->cooldown.metamorphosis->adjust( - -timespan_t::from_seconds( as( p()->talent.annihilator.world_killer->effectN( 3 ).base_value() ) ) ); + dh()->cooldown.metamorphosis->adjust( + -timespan_t::from_seconds( as( dh()->talent.annihilator.world_killer->effectN( 3 ).base_value() ) ) ); break; default: break; @@ -6664,11 +6664,11 @@ struct meteor_shower_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); - int tick_count = as( p()->talent.annihilator.dark_matter->effectN( 1 ).base_value() ); + int tick_count = as( dh()->talent.annihilator.dark_matter->effectN( 1 ).base_value() ); timespan_t duration = timespan_t::from_seconds( tick_count / 2 ); timespan_t pulse_time = duration / tick_count; - make_event( *sim, p(), + make_event( *sim, dh(), ground_aoe_params_t() .target( target ) .x( target->x_position ) @@ -6700,16 +6700,16 @@ struct hungering_slash_base_t : public demon_hunter_spell_t { base_t::execute(); - p()->spawn_soul_fragment( soul_generation_proc, soul_fragment::LESSER, number_of_souls_to_spawn ); + dh()->spawn_soul_fragment( soul_generation_proc, soul_fragment::LESSER, number_of_souls_to_spawn ); } double composite_da_multiplier( const action_state_t* s ) const override { double m = base_t::composite_da_multiplier( s ); - if ( p()->talent.devourer.singular_strikes->ok() && s->chain_target == 0 ) + if ( dh()->talent.devourer.singular_strikes->ok() && s->chain_target == 0 ) { - m *= 1.0 + p()->talent.devourer.singular_strikes->effectN( 2 ).percent(); + m *= 1.0 + dh()->talent.devourer.singular_strikes->effectN( 2 ).percent(); } return m; @@ -6730,13 +6730,13 @@ struct hungering_slash_base_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); - p()->buff.hungering_slash->expire(); - p()->buff.voidstep->trigger(); + dh()->buff.hungering_slash->expire(); + dh()->buff.voidstep->trigger(); } bool action_ready() override { - if ( !p()->buff.hungering_slash->check() ) + if ( !dh()->buff.hungering_slash->check() ) { return false; } @@ -6756,12 +6756,12 @@ struct reapers_toll_t : public voidsurge_trigger_t( execute_action )->soul_generation_proc = - p()->proc.soul_fragment_from_reapers_toll; + dh()->proc.soul_fragment_from_reapers_toll; } bool action_ready() override { - if ( !p()->buff.metamorphosis->check() ) + if ( !dh()->buff.metamorphosis->check() ) { return false; } @@ -6781,12 +6781,12 @@ struct hungering_slash_t : public hungering_slash_base_t base_t::init_finished(); debug_cast( execute_action )->soul_generation_proc = - p()->proc.soul_fragment_from_hungering_slash; + dh()->proc.soul_fragment_from_hungering_slash; } bool action_ready() override { - if ( p()->talent.scarred.demonsurge->ok() && p()->buff.metamorphosis->check() ) + if ( dh()->talent.scarred.demonsurge->ok() && dh()->buff.metamorphosis->check() ) { return false; } @@ -6816,7 +6816,7 @@ struct rolling_torment_energize_t : demon_hunter_energize_t { double e = demon_hunter_energize_t::composite_energize_amount( s ); - int stacks = p()->buff.collapsing_star_stack->check(); + int stacks = dh()->buff.collapsing_star_stack->check(); return e * stacks; } @@ -6846,14 +6846,14 @@ struct soulscar_trigger_t : public BASE { BASE::impact( s ); - if ( !BASE::p()->talent.havoc.soulscar->ok() ) + if ( !BASE::dh()->talent.havoc.soulscar->ok() ) return; if ( !action_t::result_is_hit( s->result ) ) return; - const double dot_damage = s->result_amount * BASE::p()->talent.havoc.soulscar->effectN( 1 ).percent(); - residual_action::trigger( BASE::p()->active.soulscar, s->target, dot_damage ); + const double dot_damage = s->result_amount * BASE::dh()->talent.havoc.soulscar->effectN( 1 ).percent(); + residual_action::trigger( BASE::dh()->active.soulscar, s->target, dot_damage ); } }; @@ -6941,10 +6941,10 @@ struct auto_attack_damage_t : public burning_blades_trigger_tcurrent.distance_to_move > 5 || p()->buff.out_of_range->check() ) + if ( dh()->current.distance_to_move > 5 || dh()->buff.out_of_range->check() ) { aa_contact c = aa_contact::LOST_RANGE; - p()->proc.delayed_aa_range->occur(); + dh()->proc.delayed_aa_range->occur(); if ( weapon->slot == SLOT_MAIN_HAND ) { @@ -6981,16 +6981,16 @@ struct auto_attack_t : public demon_hunter_attack_t void execute() override { - p()->main_hand_attack->set_target( target ); - if ( p()->main_hand_attack->execute_event == nullptr ) + dh()->main_hand_attack->set_target( target ); + if ( dh()->main_hand_attack->execute_event == nullptr ) { - p()->main_hand_attack->schedule_execute(); + dh()->main_hand_attack->schedule_execute(); } - p()->off_hand_attack->set_target( target ); - if ( p()->off_hand_attack->execute_event == nullptr ) + dh()->off_hand_attack->set_target( target ); + if ( dh()->off_hand_attack->execute_event == nullptr ) { - p()->off_hand_attack->schedule_execute(); + dh()->off_hand_attack->schedule_execute(); } } @@ -7000,7 +7000,7 @@ struct auto_attack_t : public demon_hunter_attack_t if ( !demon_hunter_attack_t::ready() ) return false; - if ( p()->main_hand_attack->execute_event == nullptr || p()->off_hand_attack->execute_event == nullptr ) + if ( dh()->main_hand_attack->execute_event == nullptr || dh()->off_hand_attack->execute_event == nullptr ) return true; return false; @@ -7041,7 +7041,7 @@ struct blade_dance_base_t double composite_da_multiplier( const action_state_t* s ) const override { double m = base_t::composite_da_multiplier( s ); - m *= 1.0 + p()->talent.havoc.first_blood->effectN( 1 ).percent(); + m *= 1.0 + dh()->talent.havoc.first_blood->effectN( 1 ).percent(); return m; } @@ -7051,10 +7051,10 @@ struct blade_dance_base_t if ( result_is_hit( s->result ) && td( s->target )->debuffs.essence_break->up() ) { - cooldown_t* tcd = p()->cooldown.essence_break_proc_icd->get_cooldown( s->target ); + cooldown_t* tcd = dh()->cooldown.essence_break_proc_icd->get_cooldown( s->target ); if ( tcd->up() ) { - p()->active.essence_break_proc->execute_on_target( s->target ); + dh()->active.essence_break_proc->execute_on_target( s->target ); tcd->start(); } } @@ -7097,10 +7097,10 @@ struct blade_dance_base_t if ( result_is_hit( s->result ) && td( s->target )->debuffs.essence_break->up() ) { - cooldown_t* tcd = p()->cooldown.essence_break_proc_icd->get_cooldown( s->target ); + cooldown_t* tcd = dh()->cooldown.essence_break_proc_icd->get_cooldown( s->target ); if ( tcd->up() ) { - p()->active.essence_break_proc->execute_on_target( s->target ); + dh()->active.essence_break_proc->execute_on_target( s->target ); tcd->start(); } } @@ -7114,12 +7114,12 @@ struct blade_dance_base_t // First Blood splits the primary target into a separate single-target hit, // so add 1 to account for it when checking the target threshold. - if ( p()->talent.havoc.glaive_tempest->ok() && - s->n_targets + ( p()->talent.havoc.first_blood->ok() ? 1U : 0U ) >= glaive_tempest_targets && - p()->resource_available( RESOURCE_FURY, p()->talent.havoc.glaive_tempest->effectN( 1 ).base_value() ) && + if ( dh()->talent.havoc.glaive_tempest->ok() && + s->n_targets + ( dh()->talent.havoc.first_blood->ok() ? 1U : 0U ) >= glaive_tempest_targets && + dh()->resource_available( RESOURCE_FURY, dh()->talent.havoc.glaive_tempest->effectN( 1 ).base_value() ) && s->chain_target == 0 ) { - p()->active.glaive_tempest->execute_on_target( target ); + dh()->active.glaive_tempest->execute_on_target( target ); } } } @@ -7169,13 +7169,13 @@ struct blade_dance_base_t attacks.back()->last_attack = true; // Trail of Ruin is added to the final hit in the attack list - if ( p()->talent.havoc.trail_of_ruin->ok() && trail_of_ruin_dot ) + if ( dh()->talent.havoc.trail_of_ruin->ok() && trail_of_ruin_dot ) { attacks.back()->trail_of_ruin_dot = trail_of_ruin_dot; } } - if ( p()->talent.havoc.first_blood->ok() ) + if ( dh()->talent.havoc.first_blood->ok() ) { for ( auto& attack : first_blood_attacks ) { @@ -7187,7 +7187,7 @@ struct blade_dance_base_t first_blood_attacks.back()->last_attack = true; // Trail of Ruin is added to the final hit in the attack list - if ( p()->talent.havoc.trail_of_ruin->ok() && trail_of_ruin_dot ) + if ( dh()->talent.havoc.trail_of_ruin->ok() && trail_of_ruin_dot ) { first_blood_attacks.back()->trail_of_ruin_dot = trail_of_ruin_dot; } @@ -7208,69 +7208,69 @@ struct blade_dance_base_t base_t::execute(); - p()->buff.chaos_theory->trigger(); + dh()->buff.chaos_theory->trigger(); // Metamorphosis benefit and Essence Break stats tracking - if ( p()->buff.metamorphosis->up() ) + if ( dh()->buff.metamorphosis->up() ) { if ( td( target )->debuffs.essence_break->up() ) - p()->proc.death_sweep_in_essence_break->occur(); + dh()->proc.death_sweep_in_essence_break->occur(); } else { if ( td( target )->debuffs.essence_break->up() ) - p()->proc.blade_dance_in_essence_break->occur(); + dh()->proc.blade_dance_in_essence_break->occur(); } // Create Strike Events - if ( p()->talent.havoc.first_blood->ok() ) + if ( dh()->talent.havoc.first_blood->ok() ) { for ( auto& attack : first_blood_attacks ) { - make_event( *sim, p(), attack, target, attack->delay ); + make_event( *sim, dh(), attack, target, attack->delay ); // TODO: (Topple) Clean up Screaming Brutality - if ( p()->talent.havoc.screaming_brutality->ok() ) + if ( dh()->talent.havoc.screaming_brutality->ok() ) { - double chance = p()->talent.havoc.screaming_brutality->effectN( 2 ).percent(); + double chance = dh()->talent.havoc.screaming_brutality->effectN( 2 ).percent(); if ( rng().roll( chance ) ) { - make_event( *sim, p(), p()->active.screaming_brutality_slash_proc_throw_glaive, + make_event( *sim, dh(), dh()->active.screaming_brutality_slash_proc_throw_glaive, target, attack->delay ); } } } } - if ( !p()->talent.havoc.first_blood->ok() || p()->sim->target_non_sleeping_list.size() > 1 ) + if ( !dh()->talent.havoc.first_blood->ok() || dh()->sim->target_non_sleeping_list.size() > 1 ) { for ( auto& attack : attacks ) { - make_event( *sim, p(), attack, target, attack->delay ); + make_event( *sim, dh(), attack, target, attack->delay ); // TODO: (Topple) Clean up Screaming Brutality - if ( p()->talent.havoc.screaming_brutality->ok() && !p()->talent.havoc.first_blood->ok() ) + if ( dh()->talent.havoc.screaming_brutality->ok() && !dh()->talent.havoc.first_blood->ok() ) { - double chance = p()->talent.havoc.screaming_brutality->effectN( 2 ).percent(); + double chance = dh()->talent.havoc.screaming_brutality->effectN( 2 ).percent(); if ( rng().roll( chance ) ) { - make_event( *sim, p(), p()->active.screaming_brutality_slash_proc_throw_glaive, + make_event( *sim, dh(), dh()->active.screaming_brutality_slash_proc_throw_glaive, target, attack->delay ); } } } } - if ( p()->talent.aldrachi_reaver.broken_spirit->ok() && - rng().roll( p()->talent.aldrachi_reaver.broken_spirit->effectN( 4 ).percent() ) ) + if ( dh()->talent.aldrachi_reaver.broken_spirit->ok() && + rng().roll( dh()->talent.aldrachi_reaver.broken_spirit->effectN( 4 ).percent() ) ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); } // Eternal Hunt buff expires ~500ms after Blade Dance is used - if ( p()->buff.eternal_hunt->up() ) + if ( dh()->buff.eternal_hunt->up() ) { - make_event( *p()->sim, 500_ms, [ this ] { - p()->buff.eternal_hunt->expire(); + make_event( *dh()->sim, 500_ms, [ this ] { + dh()->buff.eternal_hunt->expire(); cooldown->reset( true ); } ); } @@ -7316,16 +7316,16 @@ struct blade_dance_t : public blade_dance_base_t if ( !blade_dance_base_t::ready() ) return false; - return !p()->buff.metamorphosis->check(); + return !dh()->buff.metamorphosis->check(); } void execute() override { blade_dance_base_t::execute(); - if ( p()->talent.havoc.screaming_brutality->ok() && p()->cooldown.throw_glaive->up() ) + if ( dh()->talent.havoc.screaming_brutality->ok() && dh()->cooldown.throw_glaive->up() ) { - p()->active.screaming_brutality_blade_dance_throw_glaive->execute_on_target( target ); + dh()->active.screaming_brutality_blade_dance_throw_glaive->execute_on_target( target ); } } }; @@ -7363,21 +7363,21 @@ struct death_sweep_t : public demonsurge_trigger_tbuff.metamorphosis->check() ); + assert( dh()->buff.metamorphosis->check() ); timespan_t ds_extension = timespan_t::from_millis( data().effectN( 5 ).misc_value1() ); // If Metamorphosis has less than 950ms remaining, it gets extended so the whole Death Sweep happens during Meta. - if ( p()->buff.metamorphosis->remains_lt( ds_extension ) ) + if ( dh()->buff.metamorphosis->remains_lt( ds_extension ) ) { - p()->buff.metamorphosis->extend_duration( p(), ds_extension - p()->buff.metamorphosis->remains() ); + dh()->buff.metamorphosis->extend_duration( dh(), ds_extension - dh()->buff.metamorphosis->remains() ); } base_t::execute(); - if ( p()->talent.havoc.screaming_brutality->ok() && p()->cooldown.throw_glaive->up() ) + if ( dh()->talent.havoc.screaming_brutality->ok() && dh()->cooldown.throw_glaive->up() ) { - p()->active.screaming_brutality_death_sweep_throw_glaive->execute_on_target( target ); + dh()->active.screaming_brutality_death_sweep_throw_glaive->execute_on_target( target ); } } @@ -7387,7 +7387,7 @@ struct death_sweep_t : public demonsurge_trigger_tbuff.metamorphosis->remains() > cooldown->queue_delay() ); + return ( dh()->buff.metamorphosis->remains() > cooldown->queue_delay() ); } }; @@ -7408,7 +7408,7 @@ struct relentless_onslaught_t : public demon_hunter_spell_t { demon_hunter_spell_t::execute(); - if ( p()->buff.metamorphosis->up() ) + if ( dh()->buff.metamorphosis->up() ) { annihilation->execute_on_target( target ); } @@ -7417,7 +7417,7 @@ struct relentless_onslaught_t : public demon_hunter_spell_t chaos_strike->execute_on_target( target ); } - p()->cooldown.relentless_onslaught_icd->start( p()->talent.havoc.relentless_onslaught->internal_cooldown() ); + dh()->cooldown.relentless_onslaught_icd->start( dh()->talent.havoc.relentless_onslaught->internal_cooldown() ); } }; @@ -7455,15 +7455,15 @@ struct chaos_strike_base_t { double chance = refund_proc_chance; - if ( p()->buff.chaos_theory->check() ) + if ( dh()->buff.chaos_theory->check() ) { - chance += p()->buff.chaos_theory->data().effectN( 2 ).percent(); + chance += dh()->buff.chaos_theory->data().effectN( 2 ).percent(); } - if ( p()->talent.havoc.critical_chaos->ok() ) + if ( dh()->talent.havoc.critical_chaos->ok() ) { // DFALPHA TOCHECK -- Double check this uses the correct crit calculations - chance += p()->talent.havoc.critical_chaos->effectN( 2 ).percent() * p()->cache.attack_crit_chance(); + chance += dh()->talent.havoc.critical_chaos->effectN( 2 ).percent() * dh()->cache.attack_crit_chance(); } return chance; @@ -7477,16 +7477,16 @@ struct chaos_strike_base_t { // Technically this appears to have a 0.5s ICD, but this is handled elsewhere // Onslaught can currently proc refunds due to being delayed by 600ms - if ( p()->cooldown.chaos_strike_refund_icd->up() && p()->rng().roll( this->get_refund_proc_chance() ) ) + if ( dh()->cooldown.chaos_strike_refund_icd->up() && dh()->rng().roll( this->get_refund_proc_chance() ) ) { - p()->resource_gain( RESOURCE_FURY, p()->spec.chaos_strike_fury->effectN( 1 ).resource( RESOURCE_FURY ), + dh()->resource_gain( RESOURCE_FURY, dh()->spec.chaos_strike_fury->effectN( 1 ).resource( RESOURCE_FURY ), parent->gain ); - p()->cooldown.chaos_strike_refund_icd->start( p()->spec.chaos_strike_refund->internal_cooldown() ); + dh()->cooldown.chaos_strike_refund_icd->start( dh()->spec.chaos_strike_refund->internal_cooldown() ); } - if ( p()->talent.havoc.chaos_theory->ok() ) + if ( dh()->talent.havoc.chaos_theory->ok() ) { - p()->buff.chaos_theory->expire(); + dh()->buff.chaos_theory->expire(); } } } @@ -7496,35 +7496,35 @@ struct chaos_strike_base_t base_t::impact( s ); // Relentless Onslaught cannot self-proc and is delayed by ~300ms after the normal OH impact - if ( p()->talent.havoc.relentless_onslaught->ok() && result_is_hit( s->result ) && may_refund && + if ( dh()->talent.havoc.relentless_onslaught->ok() && result_is_hit( s->result ) && may_refund && !parent->from_onslaught ) { - double chance = p()->talent.havoc.relentless_onslaught->effectN( 1 ).percent(); - if ( p()->cooldown.relentless_onslaught_icd->up() && p()->rng().roll( chance ) ) + double chance = dh()->talent.havoc.relentless_onslaught->effectN( 1 ).percent(); + if ( dh()->cooldown.relentless_onslaught_icd->up() && dh()->rng().roll( chance ) ) { - make_event( *sim, p(), p()->active.relentless_onslaught, target, this->delay ); + make_event( *sim, dh(), dh()->active.relentless_onslaught, target, this->delay ); } } // TOCHECK -- Does this proc from Relentless Onslaught? // TOCHECK -- Does the applying Chaos Strike/Annihilation benefit from the debuff? - if ( p()->talent.havoc.serrated_glaive->ok() ) + if ( dh()->talent.havoc.serrated_glaive->ok() ) { td( s->target )->debuffs.serrated_glaive->trigger(); } - if ( p()->talent.aldrachi_reaver.warblades_hunger && p()->buff.warblades_hunger->up() ) + if ( dh()->talent.aldrachi_reaver.warblades_hunger && dh()->buff.warblades_hunger->up() ) { - p()->active.warblades_hunger->execute_on_target( target ); - p()->buff.warblades_hunger->expire(); + dh()->active.warblades_hunger->execute_on_target( target ); + dh()->buff.warblades_hunger->expire(); } if ( result_is_hit( s->result ) && td( s->target )->debuffs.essence_break->up() ) { - cooldown_t* tcd = p()->cooldown.essence_break_proc_icd->get_cooldown( s->target ); + cooldown_t* tcd = dh()->cooldown.essence_break_proc_icd->get_cooldown( s->target ); if ( tcd->up() ) { - p()->active.essence_break_proc->execute_on_target( s->target ); + dh()->active.essence_break_proc->execute_on_target( s->target ); tcd->start(); } } @@ -7567,43 +7567,43 @@ struct chaos_strike_base_t // Create Strike Events for ( auto& attack : attacks ) { - make_event( *sim, p(), attack, target, attack->delay ); + make_event( *sim, dh(), attack, target, attack->delay ); } // Metamorphosis benefit and Essence Break + Serrated Glaive stats tracking - if ( p()->buff.metamorphosis->up() ) + if ( dh()->buff.metamorphosis->up() ) { if ( td( target )->debuffs.essence_break->up() ) - p()->proc.annihilation_in_essence_break->occur(); + dh()->proc.annihilation_in_essence_break->occur(); if ( td( target )->debuffs.serrated_glaive->up() ) - p()->proc.annihilation_in_serrated_glaive->occur(); + dh()->proc.annihilation_in_serrated_glaive->occur(); } else { if ( td( target )->debuffs.essence_break->up() ) - p()->proc.chaos_strike_in_essence_break->occur(); + dh()->proc.chaos_strike_in_essence_break->occur(); if ( td( target )->debuffs.serrated_glaive->up() ) - p()->proc.chaos_strike_in_serrated_glaive->occur(); + dh()->proc.chaos_strike_in_serrated_glaive->occur(); } // Demonic Appetite - if ( p()->rppm.demonic_appetite->trigger() ) + if ( dh()->rppm.demonic_appetite->trigger() ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_demonic_appetite, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_demonic_appetite, soul_fragment::LESSER ); } - if ( p()->talent.aldrachi_reaver.broken_spirit->ok() && - rng().roll( p()->talent.aldrachi_reaver.broken_spirit->effectN( 4 ).percent() ) ) + if ( dh()->talent.aldrachi_reaver.broken_spirit->ok() && + rng().roll( dh()->talent.aldrachi_reaver.broken_spirit->effectN( 4 ).percent() ) ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); } - if ( p()->buff.inner_demon->check() ) + if ( dh()->buff.inner_demon->check() ) { - make_event( *sim, p(), p()->active.inner_demon, target, 1.25_s ); - p()->buff.inner_demon->expire(); + make_event( *sim, dh(), dh()->active.inner_demon, target, 1.25_s ); + dh()->buff.inner_demon->expire(); } } @@ -7631,15 +7631,15 @@ struct chaos_strike_t : public chaos_strike_base_t { chaos_strike_base_t::init(); - if ( !from_onslaught && p()->active.relentless_onslaught ) + if ( !from_onslaught && dh()->active.relentless_onslaught ) { - add_child( p()->active.relentless_onslaught->chaos_strike ); + add_child( dh()->active.relentless_onslaught->chaos_strike ); } } bool ready() override { - if ( p()->buff.metamorphosis->check() ) + if ( dh()->buff.metamorphosis->check() ) { return false; } @@ -7668,15 +7668,15 @@ struct annihilation_t : public demonsurge_trigger_tactive.relentless_onslaught ) + if ( !from_onslaught && dh()->active.relentless_onslaught ) { - add_child( p()->active.relentless_onslaught->annihilation ); + add_child( dh()->active.relentless_onslaught->annihilation ); } } bool ready() override { - if ( !p()->buff.metamorphosis->check() ) + if ( !dh()->buff.metamorphosis->check() ) { return false; } @@ -7723,7 +7723,7 @@ struct burning_wound_t : public demon_hunter_spell_t } ); auto tdata = td( lowest_duration ); - p()->sim->print_debug( "{} removes burning_wound on {} with duration {}", *p(), *lowest_duration, + dh()->sim->print_debug( "{} removes burning_wound on {} with duration {}", *dh(), *lowest_duration, tdata->dots.burning_wound->remains().total_seconds() ); tdata->debuffs.burning_wound->cancel(); tdata->dots.burning_wound->cancel(); @@ -7756,9 +7756,9 @@ struct demon_blades_t : public demon_hunter_attack_t { double ea = base_t::composite_energize_amount( s ); - if ( p()->talent.scarred.demonsurge->ok() && p()->buff.metamorphosis->check() ) + if ( dh()->talent.scarred.demonsurge->ok() && dh()->buff.metamorphosis->check() ) { - ea += as( p()->spec.metamorphosis_buff->effectN( 10 ).base_value() ); + ea += as( dh()->spec.metamorphosis_buff->effectN( 10 ).base_value() ); } return ea; @@ -7768,9 +7768,9 @@ struct demon_blades_t : public demon_hunter_attack_t { base_t::impact( s ); - if ( p()->spec.burning_wound_debuff->ok() ) + if ( dh()->spec.burning_wound_debuff->ok() ) { - p()->active.burning_wound->execute_on_target( s->target ); + dh()->active.burning_wound->execute_on_target( s->target ); } } }; @@ -7796,7 +7796,7 @@ struct essence_break_t : public demon_hunter_attack_t { // Debuff application appears to be delayed by 250-300ms according to logs buff_t* debuff = td( s->target )->debuffs.essence_break; - make_event( *p()->sim, 250_ms, [ debuff ] { debuff->trigger(); } ); + make_event( *dh()->sim, 250_ms, [ debuff ] { debuff->trigger(); } ); } } }; @@ -7820,7 +7820,7 @@ struct felblade_t : public inertia_trigger_t { double am = demon_hunter_attack_t::action_multiplier(); - am *= 1.0 + p()->buff.unbound_chaos->value(); + am *= 1.0 + dh()->buff.unbound_chaos->value(); return am; } @@ -7848,19 +7848,19 @@ struct felblade_t : public inertia_trigger_t void execute() override { base_t::execute(); - p()->set_out_of_range( timespan_t::zero() ); // Cancel all other movement + dh()->set_out_of_range( timespan_t::zero() ); // Cancel all other movement if ( max_fragments_consumed > 0 ) { - event_t::cancel( p()->soul_fragment_pick_up ); - p()->consume_soul_fragments( soul_fragment::ANY, false, max_fragments_consumed ); + event_t::cancel( dh()->soul_fragment_pick_up ); + dh()->consume_soul_fragments( soul_fragment::ANY, false, max_fragments_consumed ); } - p()->buff.unbound_chaos->expire(); + dh()->buff.unbound_chaos->expire(); } bool ready() override { // Felblade has a 1s cooldown triggered by Vengeful Retreat - if ( p()->cooldown.felblade_vengeful_retreat_movement_shared->down() ) + if ( dh()->cooldown.felblade_vengeful_retreat_movement_shared->down() ) return false; return base_t::ready(); @@ -7885,7 +7885,7 @@ struct fel_rush_t : public inertia_trigger_t { double am = base_t::action_multiplier(); - am *= 1.0 + p()->buff.unbound_chaos->value(); + am *= 1.0 + dh()->buff.unbound_chaos->value(); return am; } @@ -7919,14 +7919,14 @@ struct fel_rush_t : public inertia_trigger_t { base_t::execute(); - p()->buff.unbound_chaos->expire(); + dh()->buff.unbound_chaos->expire(); // Fel Rush and VR shared a 1 second GCD when one or the other is triggered - p()->cooldown.fel_rush_vengeful_retreat_movement_shared->start( timespan_t::from_seconds( 1.0 ) ); + dh()->cooldown.fel_rush_vengeful_retreat_movement_shared->start( timespan_t::from_seconds( 1.0 ) ); - p()->consume_nearby_soul_fragments( soul_fragment::LESSER ); + dh()->consume_nearby_soul_fragments( soul_fragment::LESSER ); - p()->buff.fel_rush_move->trigger(); + dh()->buff.fel_rush_move->trigger(); } void schedule_execute( action_state_t* s ) override @@ -7953,11 +7953,11 @@ struct fel_rush_t : public inertia_trigger_t bool ready() override { // Fel Rush and VR shared a 1 second GCD when one or the other is triggered - if ( p()->cooldown.fel_rush_vengeful_retreat_movement_shared->down() ) + if ( dh()->cooldown.fel_rush_vengeful_retreat_movement_shared->down() ) return false; // Not usable during the root effect of Stormeater's Boon - if ( p()->buffs.stormeaters_boon && p()->buffs.stormeaters_boon->check() ) + if ( dh()->buffs.stormeaters_boon && dh()->buffs.stormeaters_boon->check() ) return false; return base_t::ready(); @@ -7984,7 +7984,7 @@ struct fracture_t : public voidfall_building_trigger_t< { demon_hunter_attack_t::impact( s ); - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_fracture, soul_fragment::LESSER, soul_fragments_to_spawn ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_fracture, soul_fragment::LESSER, soul_fragments_to_spawn ); } }; @@ -8027,9 +8027,9 @@ struct fracture_t : public voidfall_building_trigger_t< { double ea = base_t::composite_energize_amount( s ); - if ( p()->buff.metamorphosis->check() ) + if ( dh()->buff.metamorphosis->check() ) { - ea += p()->spec.metamorphosis_buff->effectN( 10 ).resource( RESOURCE_FURY ); + ea += dh()->spec.metamorphosis_buff->effectN( 10 ).resource( RESOURCE_FURY ); } return ea; @@ -8054,29 +8054,29 @@ struct fracture_t : public voidfall_building_trigger_t< mh->execute(); // offhand hit is ~150ms after cast - make_event( *p()->sim, p(), oh, s->target, + make_event( *dh()->sim, dh(), oh, s->target, timespan_t::from_millis( data().effectN( 3 ).misc_value1() ) ); - if ( p()->buff.metamorphosis->check() ) + if ( dh()->buff.metamorphosis->check() ) { // In all reviewed logs, it's always 500ms (based on Fires of Fel application) make_event( sim, 500_ms, [ this ]() { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_fracture_meta, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_fracture_meta, soul_fragment::LESSER ); } ); } - if ( p()->talent.aldrachi_reaver.warblades_hunger && p()->buff.warblades_hunger->up() ) + if ( dh()->talent.aldrachi_reaver.warblades_hunger && dh()->buff.warblades_hunger->up() ) { - p()->active.warblades_hunger->execute_on_target( target ); - p()->buff.warblades_hunger->expire(); + dh()->active.warblades_hunger->execute_on_target( target ); + dh()->buff.warblades_hunger->expire(); } - if ( p()->set_bonuses.mid1_vengeance_4pc->ok() && - rng().roll( p()->set_bonuses.mid1_vengeance_4pc->effectN( 1 ).percent() ) && - p()->cooldown.explosion_of_the_soul_icd->up() ) + if ( dh()->set_bonuses.mid1_vengeance_4pc->ok() && + rng().roll( dh()->set_bonuses.mid1_vengeance_4pc->effectN( 1 ).percent() ) && + dh()->cooldown.explosion_of_the_soul_icd->up() ) { explosion_of_the_soul->execute_on_target( target ); - p()->cooldown.explosion_of_the_soul_icd->start( p()->set_bonuses.mid1_vengeance_4pc->internal_cooldown() ); + dh()->cooldown.explosion_of_the_soul_icd->start( dh()->set_bonuses.mid1_vengeance_4pc->internal_cooldown() ); } } } @@ -8111,7 +8111,7 @@ struct soul_cleave_t base_t::impact( s ); // Soul Cleave can apply Frailty if Frailty is talented - if ( result_is_hit( s->result ) && p()->talent.vengeance.frailty->ok() ) + if ( result_is_hit( s->result ) && dh()->talent.vengeance.frailty->ok() ) { td( s->target )->debuffs.frailty->trigger(); } @@ -8121,9 +8121,9 @@ struct soul_cleave_t { double m = base_t::composite_da_multiplier( s ); - if ( s->chain_target == 0 && p()->talent.vengeance.focused_cleave->ok() ) + if ( s->chain_target == 0 && dh()->talent.vengeance.focused_cleave->ok() ) { - m *= 1.0 + p()->talent.vengeance.focused_cleave->effectN( 1 ).percent(); + m *= 1.0 + dh()->talent.vengeance.focused_cleave->effectN( 1 ).percent(); } return m; @@ -8163,7 +8163,7 @@ struct soul_cleave_t heal->execute_on_target( player ); // Soul fragments consumed are capped for Soul Cleave - const int fragments_consumed = p()->consume_soul_fragments( soul_fragment::ANY, true, max_fragments_consumed ); + const int fragments_consumed = dh()->consume_soul_fragments( soul_fragment::ANY, true, max_fragments_consumed ); damage->set_target( target ); action_state_t* damage_state = damage->get_state(); damage_state->target = target; @@ -8176,10 +8176,10 @@ struct soul_cleave_t trigger_untethered_rage( fragments_consumed ); - if ( p()->talent.aldrachi_reaver.broken_spirit->ok() && - rng().roll( p()->talent.aldrachi_reaver.broken_spirit->effectN( 3 ).percent() ) ) + if ( dh()->talent.aldrachi_reaver.broken_spirit->ok() && + rng().roll( dh()->talent.aldrachi_reaver.broken_spirit->effectN( 3 ).percent() ) ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_broken_spirit, soul_fragment::LESSER ); } } }; @@ -8230,12 +8230,12 @@ struct throw_glaive_t : public demon_hunter_attack_t if ( result_is_hit( state->result ) ) { - if ( p()->spec.burning_wound_debuff->ok() ) + if ( dh()->spec.burning_wound_debuff->ok() ) { - p()->active.burning_wound->execute_on_target( state->target ); + dh()->active.burning_wound->execute_on_target( state->target ); } - if ( p()->talent.havoc.serrated_glaive->ok() ) + if ( dh()->talent.havoc.serrated_glaive->ok() ) { td( state->target )->debuffs.serrated_glaive->trigger(); } @@ -8326,11 +8326,11 @@ struct throw_glaive_t : public demon_hunter_attack_t track_cd_waste = true; cd_wasted_exec = - p()->template get_data_entry( "throw_glaive", p()->cd_waste_exec ); - cd_wasted_cumulative = p()->template get_data_entry( - "throw_glaive", p()->cd_waste_cumulative ); + dh()->template get_data_entry( "throw_glaive", dh()->cd_waste_exec ); + cd_wasted_cumulative = dh()->template get_data_entry( + "throw_glaive", dh()->cd_waste_cumulative ); cd_wasted_iter = - p()->template get_data_entry( "throw_glaive", p()->cd_waste_iter ); + dh()->template get_data_entry( "throw_glaive", dh()->cd_waste_iter ); } void execute() override @@ -8339,28 +8339,28 @@ struct throw_glaive_t : public demon_hunter_attack_t if ( hit_any_target && furious_throws ) { - make_event( *sim, p(), furious_throws, target, 400_ms ); + make_event( *sim, dh(), furious_throws, target, 400_ms ); - if ( p()->active.preemptive_strike ) + if ( dh()->active.preemptive_strike ) { - make_event( *sim, p(), p()->active.preemptive_strike, target, 400_ms ); + make_event( *sim, dh(), dh()->active.preemptive_strike, target, 400_ms ); } } if ( td( target )->debuffs.serrated_glaive->up() ) { - p()->proc.throw_glaive_in_serrated_glaive->occur(); + dh()->proc.throw_glaive_in_serrated_glaive->occur(); } - if ( p()->active.preemptive_strike ) + if ( dh()->active.preemptive_strike ) { - p()->active.preemptive_strike->execute_on_target( target ); + dh()->active.preemptive_strike->execute_on_target( target ); } } bool ready() override { - if ( p()->buff.reavers_glaive->up() ) + if ( dh()->buff.reavers_glaive->up() ) { return false; } @@ -8379,35 +8379,35 @@ struct reavers_glaive_t : public soulscar_trigger_t void execute() override { - p()->buff.reavers_glaive->expire(); + dh()->buff.reavers_glaive->expire(); base_t::execute(); - if ( p()->active.preemptive_strike ) + if ( dh()->active.preemptive_strike ) { - p()->active.preemptive_strike->execute_on_target( target ); + dh()->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(); + dh()->buff.glaive_flurry->trigger(); + dh()->buff.rending_strike->trigger(); + dh()->buff.art_of_the_glaive_first->trigger(); } void impact( action_state_t* s ) override { base_t::impact( s ); - p()->buff.thrill_of_the_fight_damage->expire(); + dh()->buff.thrill_of_the_fight_damage->expire(); } bool ready() override { - if ( !p()->buff.reavers_glaive->up() ) + if ( !dh()->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 ( dh()->gcd_ready > sim->current_time() ) { return false; } @@ -8436,13 +8436,13 @@ struct soulscar_t : public residual_action::residual_periodic_action_ttarget->debuffs.chaos_brand->up() ) { - amount *= 1.0 + p()->spell.chaos_brand->effectN( 1 ).percent(); + amount *= 1.0 + dh()->spell.chaos_brand->effectN( 1 ).percent(); } // Currently double dips off Demon Hide - if ( p()->bugs && p()->talent.havoc.demon_hide->ok() ) + if ( dh()->bugs && dh()->talent.havoc.demon_hide->ok() ) { - amount *= 1.0 + p()->talent.havoc.demon_hide->effectN( 1 ).percent(); + amount *= 1.0 + dh()->talent.havoc.demon_hide->effectN( 1 ).percent(); } return amount; } @@ -8471,9 +8471,9 @@ struct burning_blades_t : public residual_action::residual_periodic_action_tbugs && s->target->debuffs.chaos_brand->up() ) + if ( !dh()->bugs && s->target->debuffs.chaos_brand->up() ) { - amount *= 1.0 + p()->spell.chaos_brand->effectN( 1 ).percent(); + amount *= 1.0 + dh()->spell.chaos_brand->effectN( 1 ).percent(); } return amount; @@ -8497,7 +8497,7 @@ struct vengeful_retreat_t { base_t::execute(); - p()->buff.voidstep->expire(); + dh()->buff.voidstep->expire(); } }; @@ -8513,7 +8513,7 @@ struct vengeful_retreat_t void execute() override { // Initiative reset mechanic happens prior to the ability dealing damage - if ( p()->talent.havoc.initiative->ok() ) + if ( dh()->talent.havoc.initiative->ok() ) { for ( auto p : sim->target_non_sleeping_list ) { @@ -8523,7 +8523,7 @@ struct vengeful_retreat_t demon_hunter_spell_t::execute(); - p()->buff.tactical_retreat->trigger(); + dh()->buff.tactical_retreat->trigger(); } }; @@ -8557,7 +8557,7 @@ struct vengeful_retreat_t void execute() override { // base_t::execute() will expire the voidstep buff so we do the damage before - if ( p()->buff.voidstep->up() ) + if ( dh()->buff.voidstep->up() ) { voidstep->execute_on_target( target ); } @@ -8565,32 +8565,32 @@ struct vengeful_retreat_t base_t::execute(); // Fel Rush and VR share a 1 second GCD when one or the other is triggered - p()->cooldown.fel_rush_vengeful_retreat_movement_shared->start( 1_s ); + dh()->cooldown.fel_rush_vengeful_retreat_movement_shared->start( 1_s ); // Vengeful Retreat triggers a lockout for Felblade - p()->cooldown.felblade_vengeful_retreat_movement_shared->start( - timespan_t::from_seconds( p()->options.felblade_lockout_from_vengeful_retreat ) ); - p()->buff.vengeful_retreat_move->trigger(); + dh()->cooldown.felblade_vengeful_retreat_movement_shared->start( + timespan_t::from_seconds( dh()->options.felblade_lockout_from_vengeful_retreat ) ); + dh()->buff.vengeful_retreat_move->trigger(); - if ( p()->specialization() == DEMON_HUNTER_HAVOC ) + if ( dh()->specialization() == DEMON_HUNTER_HAVOC ) { - p()->consume_nearby_soul_fragments( soul_fragment::LESSER ); + dh()->consume_nearby_soul_fragments( soul_fragment::LESSER ); } - if ( p()->talent.aldrachi_reaver.unhindered_assault->ok() ) + if ( dh()->talent.aldrachi_reaver.unhindered_assault->ok() ) { - p()->proc.unhindered_assault->occur(); - p()->cooldown.felblade->reset( true ); + dh()->proc.unhindered_assault->occur(); + dh()->cooldown.felblade->reset( true ); } } bool ready() override { // Fel Rush and VR shared a 1 second GCD when one or the other is triggered - if ( p()->cooldown.fel_rush_vengeful_retreat_movement_shared->down() ) + if ( dh()->cooldown.fel_rush_vengeful_retreat_movement_shared->down() ) return false; // Not usable during the root effect of Stormeater's Boon - if ( p()->buffs.stormeaters_boon && p()->buffs.stormeaters_boon->check() ) + if ( dh()->buffs.stormeaters_boon && dh()->buffs.stormeaters_boon->check() ) return false; return base_t::ready(); @@ -8600,9 +8600,9 @@ struct vengeful_retreat_t { // Decrementing a stack of Voidstep will consume a max charge. Consuming a max charge loses you a current // charge. Therefore update_ready needs to not be called in that case. - if ( p()->buff.voidstep->up() ) + if ( dh()->buff.voidstep->up() ) { - p()->buff.voidstep->decrement(); + dh()->buff.voidstep->decrement(); } else { @@ -8647,7 +8647,7 @@ struct soul_carver_t : public demon_hunter_attack_t if ( !result_is_hit( s->result ) ) return; - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_soul_carver, soul_fragment::LESSER, + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_soul_carver, soul_fragment::LESSER, as( data().effectN( 3 ).base_value() ) ); } @@ -8655,7 +8655,7 @@ struct soul_carver_t : public demon_hunter_attack_t { demon_hunter_attack_t::tick( d ); - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_soul_carver, soul_fragment::LESSER, + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_soul_carver, soul_fragment::LESSER, as( data().effectN( 4 ).base_value() ) ); } }; @@ -8709,22 +8709,22 @@ struct art_of_the_glaive_t : public demon_hunter_attack_t // if glaive flurry is up and rending strike is not up // fury of the aldrachi causes art of the glaive to retrigger itself for 3 additional procs 300ms after initial // execution - if ( p()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() && p()->buff.glaive_flurry->up() && - !p()->buff.rending_strike->up() ) + if ( dh()->talent.aldrachi_reaver.fury_of_the_aldrachi->ok() && dh()->buff.glaive_flurry->up() && + !dh()->buff.rending_strike->up() ) { - make_event( *sim, p(), p()->active.art_of_the_glaive, target, 300_ms ); + make_event( *sim, dh(), dh()->active.art_of_the_glaive, target, 300_ms ); // Bladecraft makes it trigger 6 more times - if ( p()->talent.aldrachi_reaver.bladecraft->ok() ) + if ( dh()->talent.aldrachi_reaver.bladecraft->ok() ) { - make_event( *sim, p(), p()->active.art_of_the_glaive, target, 300_ms ); - make_event( *sim, p(), p()->active.art_of_the_glaive, target, 300_ms ); + make_event( *sim, dh(), dh()->active.art_of_the_glaive, target, 300_ms ); + make_event( *sim, dh(), dh()->active.art_of_the_glaive, target, 300_ms ); } } for ( auto attack : attacks ) { - make_event( *sim, p(), attack, target, attack->delay ); + make_event( *sim, dh(), attack, target, attack->delay ); } } }; @@ -8785,7 +8785,7 @@ struct wounded_quarry_t : public demon_hunter_attack_t if ( rng().roll( chance ) ) { - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_wounded_quarry, soul_fragment::LESSER ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_wounded_quarry, soul_fragment::LESSER ); } } }; @@ -8821,12 +8821,12 @@ struct demon_hunter_buff_t : public BuffBase } protected: - demon_hunter_t* p() + demon_hunter_t* dh() { return static_cast( BuffBase::source ); } - const demon_hunter_t* p() const + const demon_hunter_t* dh() const { return static_cast( BuffBase::source ); } @@ -8889,16 +8889,16 @@ struct immolation_aura_buff_t : public demon_hunter_buff_t ragefire_crit_accumulator = 0; growing_inferno_ticks = 1; - if ( p()->active.immolation_aura_initial && p()->sim->current_time() > 0_s ) + if ( dh()->active.immolation_aura_initial && dh()->sim->current_time() > 0_s ) { - state_t* s = static_cast( p()->active.immolation_aura_initial->get_state() ); + state_t* s = static_cast( dh()->active.immolation_aura_initial->get_state() ); - s->target = p()->target; + s->target = dh()->target; s->growing_inferno_multiplier = 1 + growing_inferno_ticks * growing_inferno_multiplier; s->immolation_aura = this; - p()->active.immolation_aura_initial->snapshot_state( s, p()->active.immolation_aura_initial->amount_type( s ) ); - p()->active.immolation_aura_initial->schedule_execute( s ); + dh()->active.immolation_aura_initial->snapshot_state( s, dh()->active.immolation_aura_initial->amount_type( s ) ); + dh()->active.immolation_aura_initial->schedule_execute( s ); } growing_inferno_ticks++; @@ -8908,10 +8908,10 @@ struct immolation_aura_buff_t : public demon_hunter_buff_t { demon_hunter_buff_t::expire_override( expiration_stacks, remaining_duration ); - if ( p()->talent.havoc.ragefire->ok() ) + if ( dh()->talent.havoc.ragefire->ok() ) { make_event( *sim, 200_ms, [ this ] { - p()->active.ragefire->execute_on_target( p()->target, ragefire_accumulator ); + dh()->active.ragefire->execute_on_target( dh()->target, ragefire_accumulator ); ragefire_accumulator = 0; ragefire_crit_accumulator = 0; } ); @@ -9053,19 +9053,19 @@ struct metamorphosis_buff_t : public demon_hunter_buff_t { actions::demon_hunter_energize_t* rolling_torment_energize; - metamorphosis_buff_t( demon_hunter_t* dh ) - : base_t( *dh, "metamorphosis", dh->spec.metamorphosis_buff ), rolling_torment_energize( nullptr ) + metamorphosis_buff_t( demon_hunter_t* p ) + : base_t( *p, "metamorphosis", p->spec.metamorphosis_buff ), rolling_torment_energize( nullptr ) { set_cooldown( timespan_t::zero() ); - if ( dh->specialization() != DEMON_HUNTER_DEVOURER ) + if ( p->specialization() != DEMON_HUNTER_DEVOURER ) { disable_ticking( true ); } else { freeze_stacks = true; - set_tick_callback( [ this ]( buff_t*, int, timespan_t ) { p()->devourer_fury_state.drain_stacks++; } ); + set_tick_callback( [ this ]( buff_t*, int, timespan_t ) { dh()->devourer_fury_state.drain_stacks++; } ); } // Spell 187827 has a Periodic Dummy effect (#7, 2s period) for visual/server logic that // SimC doesn't model. Without this override, init() -> set_period() detects the periodic @@ -9074,7 +9074,7 @@ struct metamorphosis_buff_t : public demon_hunter_buff_t // hardcasting Meta during an active Untethered Rage-procced Meta). set_refresh_behavior( buff_refresh_behavior::DURATION ); - switch ( dh->specialization() ) + switch ( p->specialization() ) { case DEMON_HUNTER_DEVOURER: set_duration( timespan_t::zero() ); @@ -9093,85 +9093,85 @@ struct metamorphosis_buff_t : public demon_hunter_buff_t break; } - if ( dh->talent.demon_hunter.soul_rending->ok() ) + if ( p->talent.demon_hunter.soul_rending->ok() ) { add_invalidate( CACHE_LEECH ); } - if ( dh->talent.devourer.rolling_torment->ok() ) + if ( p->talent.devourer.rolling_torment->ok() ) { rolling_torment_energize = - dh->get_background_action( "rolling_torment_energize" ); + p->get_background_action( "rolling_torment_energize" ); } } void trigger_demonic() { - if ( p()->specialization() != DEMON_HUNTER_HAVOC ) + if ( dh()->specialization() != DEMON_HUNTER_HAVOC ) { return; } - if ( !p()->buff.metamorphosis->up() ) + if ( !dh()->buff.metamorphosis->up() ) { - p()->buff.demonsurge_demonsurge->trigger(); - if ( p()->talent.scarred.volatile_instinct->ok() ) + dh()->buff.demonsurge_demonsurge->trigger(); + if ( dh()->talent.scarred.volatile_instinct->ok() ) { - p()->trigger_demonsurge( demonsurge_ability::ENTER_META, false ); + dh()->trigger_demonsurge( demonsurge_ability::ENTER_META, false ); } } - p()->buff.demonsurge_abilities[ demonsurge_ability::ANNIHILATION ]->trigger(); - p()->buff.demonsurge_abilities[ demonsurge_ability::DEATH_SWEEP ]->trigger(); + dh()->buff.demonsurge_abilities[ demonsurge_ability::ANNIHILATION ]->trigger(); + dh()->buff.demonsurge_abilities[ demonsurge_ability::DEATH_SWEEP ]->trigger(); - const timespan_t extend_duration = p()->talent.havoc.demonic->effectN( 1 ).time_value(); - p()->buff.metamorphosis->extend_duration_or_trigger( extend_duration ); + const timespan_t extend_duration = dh()->talent.havoc.demonic->effectN( 1 ).time_value(); + dh()->buff.metamorphosis->extend_duration_or_trigger( extend_duration ); } void extend_duration_or_trigger( timespan_t duration, player_t* player ) override { demon_hunter_buff_t::extend_duration_or_trigger( duration, player ); - p()->buff.inner_demon->trigger(); + dh()->buff.inner_demon->trigger(); } void start( int stacks, double value, timespan_t duration ) override { demon_hunter_buff_t::start( stacks, value, duration ); - if ( p()->specialization() == DEMON_HUNTER_VENGEANCE ) + if ( dh()->specialization() == DEMON_HUNTER_VENGEANCE ) { - p()->metamorphosis_health = p()->max_health() * value; - p()->stat_gain( STAT_MAX_HEALTH, p()->metamorphosis_health, (gain_t*)nullptr, (action_t*)nullptr, true ); + dh()->metamorphosis_health = dh()->max_health() * value; + dh()->stat_gain( STAT_MAX_HEALTH, dh()->metamorphosis_health, (gain_t*)nullptr, (action_t*)nullptr, true ); } - if ( p()->talent.devourer.void_metamorphosis->ok() ) + if ( dh()->talent.devourer.void_metamorphosis->ok() ) { - p()->buff.void_metamorphosis_stack->expire(); + dh()->buff.void_metamorphosis_stack->expire(); } - if ( p()->talent.devourer.midnight3->ok() ) + if ( dh()->talent.devourer.midnight3->ok() ) { - p()->buff.collapsing_star->trigger(); - p()->buff.collapsing_star_stack->trigger( - as( p()->talent.devourer.collapsing_star->effectN( 1 ).base_value() ) ); - p()->spawn_soul_fragment( p()->proc.soul_fragment_from_void_metamorphosis, soul_fragment::LESSER, - as( p()->talent.devourer.midnight3->effectN( 1 ).base_value() ) ); + dh()->buff.collapsing_star->trigger(); + dh()->buff.collapsing_star_stack->trigger( + as( dh()->talent.devourer.collapsing_star->effectN( 1 ).base_value() ) ); + dh()->spawn_soul_fragment( dh()->proc.soul_fragment_from_void_metamorphosis, soul_fragment::LESSER, + as( dh()->talent.devourer.midnight3->effectN( 1 ).base_value() ) ); } - if ( ( sim->dbc->wowv() >= wowv_t( 12, 0, 1 ) || p()->specialization() == DEMON_HUNTER_HAVOC ) && - p()->talent.scarred.monster_rising->ok() ) + if ( ( sim->dbc->wowv() >= wowv_t( 12, 0, 1 ) || dh()->specialization() == DEMON_HUNTER_HAVOC ) && + dh()->talent.scarred.monster_rising->ok() ) { - p()->buff.monster_rising->expire(); + dh()->buff.monster_rising->expire(); } - if ( ( sim->dbc->wowv() >= wowv_t( 12, 0, 1 ) || p()->specialization() == DEMON_HUNTER_HAVOC ) && - p()->talent.scarred.enduring_torment->ok() ) + if ( ( sim->dbc->wowv() >= wowv_t( 12, 0, 1 ) || dh()->specialization() == DEMON_HUNTER_HAVOC ) && + dh()->talent.scarred.enduring_torment->ok() ) { - p()->buff.enduring_torment->expire(); + dh()->buff.enduring_torment->expire(); } - if ( p()->specialization() == DEMON_HUNTER_DEVOURER && p()->talent.scarred.volatile_instinct->ok() ) + if ( dh()->specialization() == DEMON_HUNTER_DEVOURER && dh()->talent.scarred.volatile_instinct->ok() ) { - p()->buff.volatile_instinct->trigger(); + dh()->buff.volatile_instinct->trigger(); } } @@ -9179,57 +9179,57 @@ struct metamorphosis_buff_t : public demon_hunter_buff_t { demon_hunter_buff_t::expire_override( expiration_stacks, remaining_duration ); - if ( p()->specialization() == DEMON_HUNTER_VENGEANCE ) + if ( dh()->specialization() == DEMON_HUNTER_VENGEANCE ) { - p()->stat_loss( STAT_MAX_HEALTH, p()->metamorphosis_health, (gain_t*)nullptr, (action_t*)nullptr, true ); - p()->metamorphosis_health = 0; + dh()->stat_loss( STAT_MAX_HEALTH, dh()->metamorphosis_health, (gain_t*)nullptr, (action_t*)nullptr, true ); + dh()->metamorphosis_health = 0; } - if ( p()->talent.scarred.monster_rising->ok() ) + if ( dh()->talent.scarred.monster_rising->ok() ) { - p()->buff.monster_rising->trigger(); + dh()->buff.monster_rising->trigger(); } - if ( p()->talent.scarred.enduring_torment->ok() ) + if ( dh()->talent.scarred.enduring_torment->ok() ) { - p()->buff.enduring_torment->trigger(); + dh()->buff.enduring_torment->trigger(); } - if ( p()->specialization() == DEMON_HUNTER_DEVOURER ) + if ( dh()->specialization() == DEMON_HUNTER_DEVOURER ) { - p()->resources.current[ RESOURCE_FURY ] = 0; - p()->buff.collapsing_star->expire(); - if ( p()->talent.devourer.rolling_torment->ok() && p()->buff.collapsing_star_stack->up() ) + dh()->resources.current[ RESOURCE_FURY ] = 0; + dh()->buff.collapsing_star->expire(); + if ( dh()->talent.devourer.rolling_torment->ok() && dh()->buff.collapsing_star_stack->up() ) { - p()->buff.rolling_torment->trigger( p()->buff.collapsing_star_stack->stack() ); - rolling_torment_energize->execute_on_target( p() ); + dh()->buff.rolling_torment->trigger( dh()->buff.collapsing_star_stack->stack() ); + rolling_torment_energize->execute_on_target( dh() ); } - p()->buff.collapsing_star_stack->expire(); - p()->buff.emptiness->expire(); - p()->buff.impending_apocalypse->expire(); - event_t::cancel( p()->devourer_fury_state.next_drain_event ); - p()->devourer_fury_state.clear_state(); - p()->cooldown.void_ray->reset( false ); + dh()->buff.collapsing_star_stack->expire(); + dh()->buff.emptiness->expire(); + dh()->buff.impending_apocalypse->expire(); + event_t::cancel( dh()->devourer_fury_state.next_drain_event ); + dh()->devourer_fury_state.clear_state(); + dh()->cooldown.void_ray->reset( false ); - action_t* executing = p()->executing; + action_t* executing = dh()->executing; if ( executing && - ( executing->id == p()->spec.devour->id() || executing->id == p()->hero_spec.predators_wake->id() ) ) + ( executing->id == dh()->spec.devour->id() || executing->id == dh()->hero_spec.predators_wake->id() ) ) { - p()->interrupt(); + dh()->interrupt(); } } for ( demonsurge_ability ability : demonsurge_abilities ) { - p()->buff.demonsurge_abilities[ ability ]->expire(); + dh()->buff.demonsurge_abilities[ ability ]->expire(); } for ( voidsurge_ability ability : voidsurge_abilities ) { - p()->buff.voidsurge_abilities[ ability ]->expire(); + dh()->buff.voidsurge_abilities[ ability ]->expire(); } - p()->buff.demonsurge->expire(); - p()->buff.voidsurge->expire(); - p()->buff.demonsurge_demonsurge->expire(); - p()->buff.demonsurge_demonic_intensity->expire(); + dh()->buff.demonsurge->expire(); + dh()->buff.voidsurge->expire(); + dh()->buff.demonsurge_demonsurge->expire(); + dh()->buff.demonsurge_demonic_intensity->expire(); } }; @@ -9282,7 +9282,7 @@ struct collapsing_star_stacking_t : public demon_hunter_buff_t add_stack_change_callback( [ this ]( buff_t*, int old, int new_ ) { if ( new_ >= trigger_threshold && old < trigger_threshold ) { - this->p()->buff.collapsing_star->trigger(); + this->dh()->buff.collapsing_star->trigger(); } } ); } @@ -9305,7 +9305,7 @@ struct voidfall_building_buff_t : public demon_hunter_buff_t { make_event( *sim, [ this ] { expire(); - p()->buff.voidfall_spending->trigger( max_stack() ); + dh()->buff.voidfall_spending->trigger( max_stack() ); } ); } } @@ -9323,7 +9323,7 @@ struct voidfall_spending_buff_t : public demon_hunter_buff_t { base_t::decrement( stacks, value ); - p()->buff.voidfall_final_hour->trigger( stacks ); + dh()->buff.voidfall_final_hour->trigger( stacks ); } void expire( timespan_t d ) override @@ -9332,7 +9332,7 @@ struct voidfall_spending_buff_t : public demon_hunter_buff_t base_t::expire( d ); - p()->buff.voidfall_final_hour->trigger( stacks ); + dh()->buff.voidfall_final_hour->trigger( stacks ); } }; @@ -9365,7 +9365,7 @@ namespace spells { void immolation_aura_t::immolation_aura_damage_t::accumulate_ragefire( immolation_aura_state_t* s ) { - if ( !p()->talent.havoc.ragefire->ok() ) + if ( !dh()->talent.havoc.ragefire->ok() ) return; assert( s->immolation_aura && "Immolation Aura state should contain the parent buff while executing damage." ); @@ -9376,10 +9376,10 @@ void immolation_aura_t::immolation_aura_damage_t::accumulate_ragefire( immolatio buffs::immolation_aura_buff_t::immolation_aura_functional_buff_t* immo = static_cast( s->immolation_aura ); - if ( immo->ragefire_crit_accumulator >= p()->talent.havoc.ragefire->effectN( 2 ).base_value() ) + if ( immo->ragefire_crit_accumulator >= dh()->talent.havoc.ragefire->effectN( 2 ).base_value() ) return; - const double multiplier = p()->talent.havoc.ragefire->effectN( 1 ).percent(); + const double multiplier = dh()->talent.havoc.ragefire->effectN( 1 ).percent(); immo->ragefire_accumulator += s->result_amount * multiplier; immo->ragefire_crit_accumulator++; } @@ -9445,11 +9445,11 @@ struct demon_hunter_proc_callback_t : public dbc_proc_callback_t activate(); } - demon_hunter_t* p() const + demon_hunter_t* dh() const { return debug_cast( listener ); } - demon_hunter_t* p() + demon_hunter_t* dh() { return debug_cast( listener ); } @@ -12329,9 +12329,9 @@ void demon_hunter_t::fury_state_t::start() { assert( !next_drain_event ); - p()->buff.metamorphosis->trigger(); + dh()->buff.metamorphosis->trigger(); - p()->resource_gain( RESOURCE_FURY, 200.00, p()->gain.metamorphosis ); + dh()->resource_gain( RESOURCE_FURY, 200.00, dh()->gain.metamorphosis ); start_time = actor->sim->current_time(); schedule_tick(); @@ -12348,9 +12348,9 @@ double demon_hunter_t::fury_state_t::fury_drain_per_second( int stacks ) const { double drain = base_fury_drain_per_second( stacks ); - bool has_reduced_drain = !p()->in_combat || p()->buff.voidrush->check() || - ( p()->executing && p()->executing->id == p()->spec.collapsing_star_spell->id() ) || - ( p()->channeling && p()->channeling->id == p()->talent.devourer.void_ray->id() ); + bool has_reduced_drain = !dh()->in_combat || dh()->buff.voidrush->check() || + ( dh()->executing && dh()->executing->id == dh()->spec.collapsing_star_spell->id() ) || + ( dh()->channeling && dh()->channeling->id == dh()->talent.devourer.void_ray->id() ); if ( has_reduced_drain ) { @@ -12402,7 +12402,7 @@ void demon_hunter_t::fury_state_t::clear_state() void demon_hunter_t::fury_state_t::stop() { - p()->buff.metamorphosis->expire(); + dh()->buff.metamorphosis->expire(); } void demon_hunter_t::fury_state_t::reset() @@ -12414,13 +12414,13 @@ void demon_hunter_t::fury_state_t::reset() void demon_hunter_t::fury_state_t::drain() { - p()->active.void_buildup->stats->add_execute( 0_s, p() ); - p()->active.void_buildup->consume_resource(); + dh()->active.void_buildup->stats->add_execute( 0_s, dh() ); + dh()->active.void_buildup->consume_resource(); - if ( p()->resources.current[ RESOURCE_FURY ] <= 0.0 ) + if ( dh()->resources.current[ RESOURCE_FURY ] <= 0.0 ) { - bool cannot_end_meta = ( p()->channeling && p()->channeling->id == p()->talent.devourer.void_ray->id() ) || - ( p()->executing && p()->executing->id == p()->talent.devourer.collapsing_star->id() ); + bool cannot_end_meta = ( dh()->channeling && dh()->channeling->id == dh()->talent.devourer.void_ray->id() ) || + ( dh()->executing && dh()->executing->id == dh()->talent.devourer.collapsing_star->id() ); if ( !cannot_end_meta ) { @@ -12668,7 +12668,7 @@ std::unique_ptr actions::demon_hunter_sigil_t::create_sigil_expression( else if ( util::str_compare_ci( name, "sigil_placed" ) || util::str_compare_ci( name, "placed" ) ) { return make_fn_expr( name, [ this ] { - if ( p()->sim->current_time() < sigil_activates ) + if ( dh()->sim->current_time() < sigil_activates ) return 1; else return 0;