From 96f63dc622ba3d6a23b38a10a6d5237eff8bc599 Mon Sep 17 00:00:00 2001 From: gastank <42421688+gastank@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:31:51 -0700 Subject: [PATCH 1/5] [Action] trigger generic harmful procs from energize_power effects It seems 'Generic Helpful' can be triggered by various resource energize effects from actions such that items & effects described as proccing off "heals" or have otherwise incorrect proc flags can trigger off harmful attacks and spells. action_t::suppress_callback_from_energize = true to disable for the action. --- engine/action/action.cpp | 12 ++++++++- engine/action/action.hpp | 3 +++ engine/action/action_state.cpp | 2 +- engine/action/dbc_proc_callback.cpp | 40 +++++++++++++++++++---------- engine/player/player.cpp | 3 +++ engine/player/player.hpp | 1 + engine/sc_enums.hpp | 3 ++- 7 files changed, 47 insertions(+), 17 deletions(-) diff --git a/engine/action/action.cpp b/engine/action/action.cpp index db614fc398a..bfe8a2fba65 100644 --- a/engine/action/action.cpp +++ b/engine/action/action.cpp @@ -353,6 +353,7 @@ action_t::action_t( action_e ty, util::string_view token, player_t* p, const spe target_callbacks( true ), suppress_caster_procs(), suppress_target_procs(), + suppress_callback_from_energize(), enable_proc_from_suppressed(), allow_class_ability_procs(), not_a_proc(), @@ -5143,7 +5144,16 @@ player_t* action_t::get_expression_target() double action_t::gain_energize_resource( resource_e resource_type, double amount, gain_t* g ) { - return player->resource_gain( resource_type, amount, g, this ); + auto ret = player->resource_gain( resource_type, amount, g, this ); + + // energize_power can trigger generic helpful proc effects + if ( callbacks && caster_callbacks && ( !suppress_caster_procs || enable_proc_from_suppressed ) && + !suppress_callback_from_energize ) + { + player->trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, this, player->energize_state.get() ); + } + + return ret; } bool action_t::usable_during_current_cast() const diff --git a/engine/action/action.hpp b/engine/action/action.hpp index f6b5e57ffe7..b7e56a18397 100644 --- a/engine/action/action.hpp +++ b/engine/action/action.hpp @@ -121,6 +121,9 @@ struct action_t : private noncopyable /// if true, does not trigger callbacks on caster/target. bool suppress_caster_procs, suppress_target_procs; + /// engerize_power effects can trigger generic helpful procs. if true, disable this behavior for the action. + bool suppress_callback_from_energize; + /// can trigger callbacks on caster even if suppress_caster_proc is true, as long as the callback has can_proc_from_suppressed = true. /// TODO: determine if equivalent for suppressed target procs is needed. bool enable_proc_from_suppressed; diff --git a/engine/action/action_state.cpp b/engine/action/action_state.cpp index 3b3c7297f0e..8c8d53261f3 100644 --- a/engine/action/action_state.cpp +++ b/engine/action/action_state.cpp @@ -272,7 +272,7 @@ void travel_event_t::execute() void action_state_t::release( action_state_t*& s ) { - assert( s ); + assert( s && s->result_type != result_amount_type::ENERGIZE ); s->action->release_state( s ); s = nullptr; } diff --git a/engine/action/dbc_proc_callback.cpp b/engine/action/dbc_proc_callback.cpp index 7bc985e721d..d73cf331b04 100644 --- a/engine/action/dbc_proc_callback.cpp +++ b/engine/action/dbc_proc_callback.cpp @@ -32,10 +32,22 @@ struct proc_event_t : public event_t proc_event_t( dbc_proc_callback_t* c, action_t* a, action_state_t* s ) : event_t( *c->listener->sim ), cb( c ), - source_action( a ), - // Note, state has to be cloned as it's about to get recycled back into the action state cache - source_state( s ? s->action->get_state( s ) : nullptr ) + source_action( a ) { + // Unless the state is an energize state, it has to be cloned as it's about to get recycled back into the action + // state cache + if ( s ) + { + if ( s->result_type == result_amount_type::ENERGIZE ) + source_state = s; + else + source_state = s->action->get_state( s ); + } + else + { + source_state = nullptr; + } + schedule( timespan_t::zero() ); #ifndef NDEBUG if ( !cb ) @@ -57,7 +69,8 @@ struct proc_event_t : public event_t ~proc_event_t() override { - if ( source_state ) + // DON'T RELEASE ENERGIZE STATES + if ( source_state && source_state->result_type != result_amount_type::ENERGIZE ) action_state_t::release( source_state ); } @@ -255,7 +268,7 @@ void dbc_proc_callback_t::trigger( action_t* a, action_state_t* state ) if ( triggered ) { - assert( state && state -> action); + assert( state && ( state->action || state->result_type == result_amount_type::ENERGIZE ) ); // Detach proc execution from proc triggering make_event( *listener->sim, this, a, state ); @@ -435,9 +448,6 @@ player_t* dbc_proc_callback_t::target( const action_state_t* state, action_t* pr return state->target; } - // TODO: Verify this behaviour with damage to friendly Allies. - bool self_hit = state->action->player == listener; - // Incoming callbacks target either the callback actor, or the source of the incoming state. // Which is selected depends on the type of the callback proc action. // @@ -446,13 +456,15 @@ player_t* dbc_proc_callback_t::target( const action_state_t* state, action_t* pr assert( _action && "Cannot determine target of incoming callback, there is no proc_action" ); switch ( _action->type ) { - // Heals are always targeted to the callback actor on incoming events - case ACTION_ABSORB: - case ACTION_HEAL: - return listener; - // Self Damage targets are redirected to the players main target. Else they target the player. + case ACTION_ATTACK: + case ACTION_SPELL: + // Self Damage and energize targets are redirected to the players main target. Else they target the player. + // TODO: Verify this behaviour with damage to friendly Allies. + if ( state->result_type == result_amount_type::ENERGIZE || state->action->player == listener ) + return listener->target; + SC_FALLTHROUGH; default: - return self_hit ? state->action->player->target : state->action->player; + return listener; } } diff --git a/engine/player/player.cpp b/engine/player/player.cpp index 0ec3efedb75..0266e88f669 100644 --- a/engine/player/player.cpp +++ b/engine/player/player.cpp @@ -1063,6 +1063,7 @@ player_t::player_t( sim_t* s, player_e t, util::string_view n, race_e r ) cast_delay_reaction( 0_ms ), cast_delay_occurred( 0_ms ), callbacks( s ), + energize_state( std::make_unique( nullptr, this ) ), use_apl( "" ), // Actions use_default_action_list( false ), @@ -1219,6 +1220,8 @@ player_t::player_t( sim_t* s, player_e t, util::string_view n, race_e r ) } } + energize_state->result_type = result_amount_type::ENERGIZE; + main_hand_weapon.slot = SLOT_MAIN_HAND; off_hand_weapon.slot = SLOT_OFF_HAND; diff --git a/engine/player/player.hpp b/engine/player/player.hpp index 4a59cd4a3e7..c3971364232 100644 --- a/engine/player/player.hpp +++ b/engine/player/player.hpp @@ -350,6 +350,7 @@ struct player_t : public actor_t std::vector> callbacks_on_combat_state; std::vector> callbacks_on_movement; // called in movement_buff_t std::vector> callbacks_on_init_finished; + std::unique_ptr energize_state; // Action Priority List auto_dispose< std::vector > action_list; diff --git a/engine/sc_enums.hpp b/engine/sc_enums.hpp index 5a1b3f21e7e..291aab8a2d2 100644 --- a/engine/sc_enums.hpp +++ b/engine/sc_enums.hpp @@ -465,7 +465,8 @@ enum class result_amount_type DMG_OVER_TIME = 1, HEAL_DIRECT, HEAL_OVER_TIME, - ABSORB + ABSORB, + ENERGIZE // unique_ptr to player, only used to indicate the trigger_callback is from an energize_power effect }; enum stats_e From 500f9e57b77b357f47caba54c453941dd2aaca27 Mon Sep 17 00:00:00 2001 From: gastank <42421688+gastank@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:42:38 -0700 Subject: [PATCH 2/5] use static dummy state --- engine/action/action.cpp | 2 +- engine/action/action_state.cpp | 2 +- engine/action/action_state.hpp | 6 ++++++ engine/action/dbc_proc_callback.cpp | 8 ++++---- engine/player/player.cpp | 3 --- engine/player/player.hpp | 1 - engine/player/unique_gear_midnight.cpp | 6 +++--- engine/sc_enums.hpp | 3 +-- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/engine/action/action.cpp b/engine/action/action.cpp index bfe8a2fba65..48eb6f6b0e5 100644 --- a/engine/action/action.cpp +++ b/engine/action/action.cpp @@ -5150,7 +5150,7 @@ double action_t::gain_energize_resource( resource_e resource_type, double amount if ( callbacks && caster_callbacks && ( !suppress_caster_procs || enable_proc_from_suppressed ) && !suppress_callback_from_energize ) { - player->trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, this, player->energize_state.get() ); + player->trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, this, action_state_t::energize() ); } return ret; diff --git a/engine/action/action_state.cpp b/engine/action/action_state.cpp index 8c8d53261f3..d59763eeb23 100644 --- a/engine/action/action_state.cpp +++ b/engine/action/action_state.cpp @@ -272,7 +272,7 @@ void travel_event_t::execute() void action_state_t::release( action_state_t*& s ) { - assert( s && s->result_type != result_amount_type::ENERGIZE ); + assert( s && s != action_state_t::energize() ); s->action->release_state( s ); s = nullptr; } diff --git a/engine/action/action_state.hpp b/engine/action/action_state.hpp index 276a1cbe066..bbd10d176fa 100644 --- a/engine/action/action_state.hpp +++ b/engine/action/action_state.hpp @@ -140,8 +140,14 @@ struct action_state_t : private noncopyable virtual proc_types2 cast_proc_type2() const; virtual proc_types2 interrupt_proc_type2() const; + + // static dummy states + static action_state_t* energize(); }; +inline action_state_t energize_state_v { nullptr, nullptr }; +inline action_state_t* action_state_t::energize() { return &energize_state_v; } + struct travel_event_t : public event_t { action_t* action; diff --git a/engine/action/dbc_proc_callback.cpp b/engine/action/dbc_proc_callback.cpp index d73cf331b04..d1e35fba907 100644 --- a/engine/action/dbc_proc_callback.cpp +++ b/engine/action/dbc_proc_callback.cpp @@ -38,7 +38,7 @@ struct proc_event_t : public event_t // state cache if ( s ) { - if ( s->result_type == result_amount_type::ENERGIZE ) + if ( s == action_state_t::energize() ) source_state = s; else source_state = s->action->get_state( s ); @@ -70,7 +70,7 @@ struct proc_event_t : public event_t ~proc_event_t() override { // DON'T RELEASE ENERGIZE STATES - if ( source_state && source_state->result_type != result_amount_type::ENERGIZE ) + if ( source_state && source_state != action_state_t::energize() ) action_state_t::release( source_state ); } @@ -268,7 +268,7 @@ void dbc_proc_callback_t::trigger( action_t* a, action_state_t* state ) if ( triggered ) { - assert( state && ( state->action || state->result_type == result_amount_type::ENERGIZE ) ); + assert( state && ( state->action || state == action_state_t::energize() ) ); // Detach proc execution from proc triggering make_event( *listener->sim, this, a, state ); @@ -460,7 +460,7 @@ player_t* dbc_proc_callback_t::target( const action_state_t* state, action_t* pr case ACTION_SPELL: // Self Damage and energize targets are redirected to the players main target. Else they target the player. // TODO: Verify this behaviour with damage to friendly Allies. - if ( state->result_type == result_amount_type::ENERGIZE || state->action->player == listener ) + if ( state == action_state_t::energize() || state->action->player == listener ) return listener->target; SC_FALLTHROUGH; default: diff --git a/engine/player/player.cpp b/engine/player/player.cpp index 0266e88f669..0ec3efedb75 100644 --- a/engine/player/player.cpp +++ b/engine/player/player.cpp @@ -1063,7 +1063,6 @@ player_t::player_t( sim_t* s, player_e t, util::string_view n, race_e r ) cast_delay_reaction( 0_ms ), cast_delay_occurred( 0_ms ), callbacks( s ), - energize_state( std::make_unique( nullptr, this ) ), use_apl( "" ), // Actions use_default_action_list( false ), @@ -1220,8 +1219,6 @@ player_t::player_t( sim_t* s, player_e t, util::string_view n, race_e r ) } } - energize_state->result_type = result_amount_type::ENERGIZE; - main_hand_weapon.slot = SLOT_MAIN_HAND; off_hand_weapon.slot = SLOT_OFF_HAND; diff --git a/engine/player/player.hpp b/engine/player/player.hpp index c3971364232..4a59cd4a3e7 100644 --- a/engine/player/player.hpp +++ b/engine/player/player.hpp @@ -350,7 +350,6 @@ struct player_t : public actor_t std::vector> callbacks_on_combat_state; std::vector> callbacks_on_movement; // called in movement_buff_t std::vector> callbacks_on_init_finished; - std::unique_ptr energize_state; // Action Priority List auto_dispose< std::vector > action_list; diff --git a/engine/player/unique_gear_midnight.cpp b/engine/player/unique_gear_midnight.cpp index 9ab3a807357..3ab355b05c0 100644 --- a/engine/player/unique_gear_midnight.cpp +++ b/engine/player/unique_gear_midnight.cpp @@ -997,10 +997,10 @@ void b0p_curator_of_booms( special_effect_t& effect ) effect.player->callbacks.register_callback_execute_function( effect.spell_id, [ damage, heal, max_bombs ]( auto, auto, const action_state_t* s ) { - auto _bombs = s->action->rng().range( max_bombs ) + 1; + auto _bombs = damage->rng().range( max_bombs ) + 1; auto _mul = as( _bombs ) / max_bombs; - s->action->sim->print_debug( "{} launching {} BIG BOMBS", *s->action->player, _bombs ); + damage->sim->print_debug( "{} launching {} BIG BOMBS", *damage->player, _bombs ); if ( s->target->is_enemy() ) { @@ -3189,7 +3189,7 @@ void rangergenerals_call( special_effect_t& effect ) effect.player->callbacks.register_callback_execute_function( effect.spell_id, [ damage, delay ]( auto, auto, const action_state_t* s ) { - make_event( *s->action->sim, delay, [ damage, t = s->target ] { + make_event( *damage->sim, delay, [ damage, t = s->target ] { damage->execute_on_target( t ); } ); } ); diff --git a/engine/sc_enums.hpp b/engine/sc_enums.hpp index 291aab8a2d2..5a1b3f21e7e 100644 --- a/engine/sc_enums.hpp +++ b/engine/sc_enums.hpp @@ -465,8 +465,7 @@ enum class result_amount_type DMG_OVER_TIME = 1, HEAL_DIRECT, HEAL_OVER_TIME, - ABSORB, - ENERGIZE // unique_ptr to player, only used to indicate the trigger_callback is from an energize_power effect + ABSORB }; enum stats_e From 5b11b3e6cb4aa21f432a518491d39d81d6c2c971 Mon Sep 17 00:00:00 2001 From: gastank <42421688+gastank@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:16:41 -0700 Subject: [PATCH 3/5] use action-scoped unique ptr instead --- engine/action/action.cpp | 3 ++- engine/action/action.hpp | 4 +++- engine/action/action_state.cpp | 7 ++++++- engine/action/action_state.hpp | 7 ++----- engine/action/dbc_proc_callback.cpp | 8 ++++---- engine/player/unique_gear_midnight.cpp | 6 +++--- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/engine/action/action.cpp b/engine/action/action.cpp index 48eb6f6b0e5..5007ded46eb 100644 --- a/engine/action/action.cpp +++ b/engine/action/action.cpp @@ -498,6 +498,7 @@ action_t::action_t( action_e ty, util::string_view token, player_t* p, const spe pre_execute_state(), snapshot_flags(), update_flags( STATE_TGT_MUL_DA | STATE_TGT_MUL_TA | STATE_TGT_CRIT ), + energize_state( std::make_unique( this, p ) ), target_cache(), options(), state_cache(), @@ -5150,7 +5151,7 @@ double action_t::gain_energize_resource( resource_e resource_type, double amount if ( callbacks && caster_callbacks && ( !suppress_caster_procs || enable_proc_from_suppressed ) && !suppress_callback_from_energize ) { - player->trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, this, action_state_t::energize() ); + player->trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, this, energize_state.get() ); } return ret; diff --git a/engine/action/action.hpp b/engine/action/action.hpp index b7e56a18397..7e1abc27509 100644 --- a/engine/action/action.hpp +++ b/engine/action/action.hpp @@ -597,7 +597,6 @@ struct action_t : private noncopyable std::unique_ptr line_cooldown; const action_priority_t* signature; - /// State of the last execute() action_state_t* execute_state; @@ -608,6 +607,9 @@ struct action_t : private noncopyable unsigned update_flags; + /// placeholder dummy to use for energize effects that trigger generic helpful procs + std::unique_ptr energize_state; + /** * Target Cache System * - list: contains the cached target pointers diff --git a/engine/action/action_state.cpp b/engine/action/action_state.cpp index d59763eeb23..e807e85c32e 100644 --- a/engine/action/action_state.cpp +++ b/engine/action/action_state.cpp @@ -272,7 +272,7 @@ void travel_event_t::execute() void action_state_t::release( action_state_t*& s ) { - assert( s && s != action_state_t::energize() ); + assert( s && !s->is_energize() ); s->action->release_state( s ); s = nullptr; } @@ -404,3 +404,8 @@ proc_types2 action_state_t::interrupt_proc_type2() const else return PROC2_INVALID; } + +bool action_state_t::is_energize() const +{ + return this == action->energize_state.get(); +} diff --git a/engine/action/action_state.hpp b/engine/action/action_state.hpp index bbd10d176fa..e0db2569ffb 100644 --- a/engine/action/action_state.hpp +++ b/engine/action/action_state.hpp @@ -141,13 +141,10 @@ struct action_state_t : private noncopyable virtual proc_types2 interrupt_proc_type2() const; - // static dummy states - static action_state_t* energize(); + // checks for special states + bool is_energize() const; }; -inline action_state_t energize_state_v { nullptr, nullptr }; -inline action_state_t* action_state_t::energize() { return &energize_state_v; } - struct travel_event_t : public event_t { action_t* action; diff --git a/engine/action/dbc_proc_callback.cpp b/engine/action/dbc_proc_callback.cpp index d1e35fba907..6b92c2bf4e6 100644 --- a/engine/action/dbc_proc_callback.cpp +++ b/engine/action/dbc_proc_callback.cpp @@ -38,7 +38,7 @@ struct proc_event_t : public event_t // state cache if ( s ) { - if ( s == action_state_t::energize() ) + if ( s->is_energize() ) source_state = s; else source_state = s->action->get_state( s ); @@ -70,7 +70,7 @@ struct proc_event_t : public event_t ~proc_event_t() override { // DON'T RELEASE ENERGIZE STATES - if ( source_state && source_state != action_state_t::energize() ) + if ( source_state && !source_state->is_energize() ) action_state_t::release( source_state ); } @@ -268,7 +268,7 @@ void dbc_proc_callback_t::trigger( action_t* a, action_state_t* state ) if ( triggered ) { - assert( state && ( state->action || state == action_state_t::energize() ) ); + assert( state && state->action ); // Detach proc execution from proc triggering make_event( *listener->sim, this, a, state ); @@ -460,7 +460,7 @@ player_t* dbc_proc_callback_t::target( const action_state_t* state, action_t* pr case ACTION_SPELL: // Self Damage and energize targets are redirected to the players main target. Else they target the player. // TODO: Verify this behaviour with damage to friendly Allies. - if ( state == action_state_t::energize() || state->action->player == listener ) + if ( state->action->player == listener ) return listener->target; SC_FALLTHROUGH; default: diff --git a/engine/player/unique_gear_midnight.cpp b/engine/player/unique_gear_midnight.cpp index 3ab355b05c0..3ec533c9a9e 100644 --- a/engine/player/unique_gear_midnight.cpp +++ b/engine/player/unique_gear_midnight.cpp @@ -997,10 +997,10 @@ void b0p_curator_of_booms( special_effect_t& effect ) effect.player->callbacks.register_callback_execute_function( effect.spell_id, [ damage, heal, max_bombs ]( auto, auto, const action_state_t* s ) { - auto _bombs = damage->rng().range( max_bombs ) + 1; + auto _bombs = s->action->rng().range( max_bombs ) + 1; auto _mul = as( _bombs ) / max_bombs; - damage->sim->print_debug( "{} launching {} BIG BOMBS", *damage->player, _bombs ); + s->action->sim->print_debug( "{} launching {} BIG BOMBS", *damage->player, _bombs ); if ( s->target->is_enemy() ) { @@ -3189,7 +3189,7 @@ void rangergenerals_call( special_effect_t& effect ) effect.player->callbacks.register_callback_execute_function( effect.spell_id, [ damage, delay ]( auto, auto, const action_state_t* s ) { - make_event( *damage->sim, delay, [ damage, t = s->target ] { + make_event( *s->action->sim, delay, [ damage, t = s->target ] { damage->execute_on_target( t ); } ); } ); From 94ccf81f8f45a75008f0239a5b6a53497b7b668c Mon Sep 17 00:00:00 2001 From: gastank <42421688+gastank@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:57:18 -0700 Subject: [PATCH 4/5] adjust some items --- engine/player/unique_gear_dragonflight.cpp | 4 ---- engine/player/unique_gear_midnight.cpp | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/engine/player/unique_gear_dragonflight.cpp b/engine/player/unique_gear_dragonflight.cpp index db3e18a222a..dbf4a7c4f1e 100644 --- a/engine/player/unique_gear_dragonflight.cpp +++ b/engine/player/unique_gear_dragonflight.cpp @@ -1501,10 +1501,6 @@ void emerald_coachs_whistle( special_effect_t& effect ) effect.custom_buff = buff; - // self driver procs off druid hostile abilities as well as shadow hostile abilities - if ( effect.player->type == player_e::DRUID || effect.player->specialization() == PRIEST_SHADOW || effect.player->type == EVOKER ) - effect.proc_flags_ |= PF_MAGIC_SPELL | PF_MELEE_ABILITY; - new dbc_proc_callback_t( effect.player, effect ); // Pretend we are our bonded partner for the sake of procs from partner diff --git a/engine/player/unique_gear_midnight.cpp b/engine/player/unique_gear_midnight.cpp index 3ec533c9a9e..bdda460bab5 100644 --- a/engine/player/unique_gear_midnight.cpp +++ b/engine/player/unique_gear_midnight.cpp @@ -702,8 +702,8 @@ void blessed_pango_charm( special_effect_t& effect ) // 1259130 heal void primal_spore_binding( special_effect_t& effect ) { - effect.player->sim->error( UNVERIFIED_VALUE, - "Primal Spore Binding: Damage has only been verified to the tooltip and not to actual in-game damage." ); + effect.player->sim->error( UNVERIFIED_IMPLEMENTATION, + "Primal Spore Binding: What determines if you get a damage proc vs healing proc is unknown." ); auto damage_amount = effect.driver()->effectN( 1 ).average( effect ); auto heal_amount = effect.driver()->effectN( 2 ).average( effect ); @@ -1000,7 +1000,7 @@ void b0p_curator_of_booms( special_effect_t& effect ) auto _bombs = s->action->rng().range( max_bombs ) + 1; auto _mul = as( _bombs ) / max_bombs; - s->action->sim->print_debug( "{} launching {} BIG BOMBS", *damage->player, _bombs ); + s->action->sim->print_debug( "{} launching {} BIG BOMBS", *s->action->player, _bombs ); if ( s->target->is_enemy() ) { From 5c048f08cc87f38f8a2a65c54611a65cc4a38b06 Mon Sep 17 00:00:00 2001 From: gastank <42421688+gastank@users.noreply.github.com> Date: Sat, 21 Mar 2026 10:16:12 -0700 Subject: [PATCH 5/5] move trigger to player_t::resource_gain --- engine/action/action.cpp | 11 +---------- engine/player/player.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/engine/action/action.cpp b/engine/action/action.cpp index 5007ded46eb..9e061220624 100644 --- a/engine/action/action.cpp +++ b/engine/action/action.cpp @@ -5145,16 +5145,7 @@ player_t* action_t::get_expression_target() double action_t::gain_energize_resource( resource_e resource_type, double amount, gain_t* g ) { - auto ret = player->resource_gain( resource_type, amount, g, this ); - - // energize_power can trigger generic helpful proc effects - if ( callbacks && caster_callbacks && ( !suppress_caster_procs || enable_proc_from_suppressed ) && - !suppress_callback_from_energize ) - { - player->trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, this, energize_state.get() ); - } - - return ret; + return player->resource_gain( resource_type, amount, g, this ); } bool action_t::usable_during_current_cast() const diff --git a/engine/player/player.cpp b/engine/player/player.cpp index 0ec3efedb75..fd33b3150ae 100644 --- a/engine/player/player.cpp +++ b/engine/player/player.cpp @@ -7834,6 +7834,17 @@ double player_t::resource_gain( resource_e resource_type, double amount, gain_t* resources.current[ resource_type ], resources.max[ resource_type ] ); } + // energize_power from actions can trigger generic helpful proc effects + if ( action && resource_type > RESOURCE_MANA && resource_type < RESOURCE_MAX ) + { + if ( action->callbacks && action->caster_callbacks && + ( !action->suppress_caster_procs || action->enable_proc_from_suppressed ) && + !action->suppress_callback_from_energize ) + { + trigger_callbacks( PROC1_NONE_HELPFUL, PROC2_HIT, action, action->energize_state.get() ); + } + } + return actual_amount; }