Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion engine/action/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -497,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<action_state_t>( this, p ) ),
target_cache(),
options(),
state_cache(),
Expand Down Expand Up @@ -5143,7 +5145,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, energize_state.get() );
}

return ret;
}

bool action_t::usable_during_current_cast() const
Expand Down
7 changes: 6 additions & 1 deletion engine/action/action.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -594,7 +597,6 @@ struct action_t : private noncopyable
std::unique_ptr<cooldown_t> line_cooldown;
const action_priority_t* signature;


/// State of the last execute()
action_state_t* execute_state;

Expand All @@ -605,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<action_state_t> energize_state;

/**
* Target Cache System
* - list: contains the cached target pointers
Expand Down
7 changes: 6 additions & 1 deletion engine/action/action_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ void travel_event_t::execute()

void action_state_t::release( action_state_t*& s )
{
assert( s );
assert( s && !s->is_energize() );
s->action->release_state( s );
s = nullptr;
}
Expand Down Expand Up @@ -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();
}
3 changes: 3 additions & 0 deletions engine/action/action_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ struct action_state_t : private noncopyable
virtual proc_types2 cast_proc_type2() const;

virtual proc_types2 interrupt_proc_type2() const;

// checks for special states
bool is_energize() const;
};

struct travel_event_t : public event_t
Expand Down
40 changes: 26 additions & 14 deletions engine/action/dbc_proc_callback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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->is_energize() )
source_state = s;
else
source_state = s->action->get_state( s );
}
else
{
source_state = nullptr;
}

schedule( timespan_t::zero() );
#ifndef NDEBUG
if ( !cb )
Expand All @@ -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->is_energize() )
action_state_t::release( source_state );
}

Expand Down Expand Up @@ -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 );
// Detach proc execution from proc triggering
make_event<proc_event_t>( *listener->sim, this, a, state );

Expand Down Expand Up @@ -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.
//
Expand All @@ -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->action->player == listener )
return listener->target;
SC_FALLTHROUGH;
default:
return self_hit ? state->action->player->target : state->action->player;
return listener;
}
}

Expand Down
4 changes: 0 additions & 4 deletions engine/player/unique_gear_dragonflight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions engine/player/unique_gear_midnight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
Loading