Skip to content

Commit

Permalink
[Priest] Adjust how Power Word Shield works
Browse files Browse the repository at this point in the history
  • Loading branch information
Saeldur committed Nov 19, 2024
1 parent cee502b commit 6ce4316
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 42 deletions.
130 changes: 88 additions & 42 deletions engine/class_modules/priest/sc_priest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,67 @@

namespace priestspace
{
namespace buffs
{
// ==========================================================================
// Power Word: Shield
// ==========================================================================
struct power_word_shield_buff_t : public priest_buff_t<absorb_buff_t>
{
double initial_size;
double energize_amount;
using ab = priest_buff_t<absorb_buff_t>;

power_word_shield_buff_t( priest_t* player, player_t* target )
: ab( actor_pair_t( target, player ), "power_word_shield", player->find_class_spell( "Power Word: Shield" ) ),
energize_amount( player->find_spell( 47755 )->effectN( 1 ).percent() / 100 *
priest().resources.max[ RESOURCE_MANA ] )
{
set_absorb_source( player->get_stats( "power_word_shield" ) );
set_cooldown( 0_s );
initial_size = 0;
buff_period = 0_s; // TODO: Work out why Power Word: Shield has buff period. Work out why shields ticking refreshes
// them to full value.
}

bool trigger( int stacks, double value, double chance, timespan_t duration ) override
{
sim->print_debug( "{} changes stored Power Word: Shield maximum from {} to {}", *player, initial_size, value );
initial_size = value;

return ab::trigger( stacks, value, chance, duration );
}

void trigger_void_shield( double result_amount )
{
// The initial amount of the shield and our "cap" is stored in the Void Shield buff
double left_to_refill = initial_size - current_value;
double refill_amount = std::min( left_to_refill, result_amount );

if ( refill_amount > 0 )
{
sim->print_debug( "{} adds value to Power Word: Shield. original={}, left_to_refill={}, refill_amount={}",
*player, current_value, left_to_refill, refill_amount );
current_value += refill_amount;
}
}

void expire_override( int expiration_stacks, timespan_t remaining_duration ) override
{
if ( remaining_duration > timespan_t::zero() )
{
if ( priest().talents.discipline.shield_discipline.enabled() )
{
priest().resource_gain( RESOURCE_MANA, energize_amount, priest().gains.shield_discipline );
}
}

ab::expire_override( expiration_stacks, remaining_duration );
}
};

} // namespace buffs

namespace actions
{
namespace spells
Expand Down Expand Up @@ -2272,9 +2333,32 @@ struct power_word_shield_t final : public priest_absorb_t
}

// Manually create the buff so we can reference it with Void Shield
absorb_buff_t* create_buff( const action_state_t* ) override
absorb_buff_t* create_buff( const action_state_t* s ) override
{
return priest().buffs.power_word_shield;
if ( s->target == player )
{
if ( priest().buffs.power_word_shield->absorb_source != stats )
priest().buffs.power_word_shield->set_absorb_source( stats );
return priest().buffs.power_word_shield;
}

buff_t* b = buff_t::find( s->target, name_str );
if ( b )
return debug_cast<absorb_buff_t*>( b );

std::string stats_obj_name = name_str;
if ( s->target != player )
stats_obj_name += "_" + player->name_str;
stats_t* stats_obj = player->get_stats( stats_obj_name, this );
if ( stats != stats_obj )
{
// Add absorb target stats as a child to the main stats object for reporting
stats->add_child( stats_obj );
}
auto buff = make_buff<buffs::power_word_shield_buff_t>( &priest(), s->target );
buff->set_absorb_source( stats_obj );

return buff;
}

double composite_da_multiplier( const action_state_t* s ) const override
Expand Down Expand Up @@ -2553,45 +2637,6 @@ struct cauterizing_shadows_t final : public priest_heal_t

namespace buffs
{
// ==========================================================================
// Power Word: Shield
// ==========================================================================
struct power_word_shield_buff_t : public absorb_buff_t
{
double initial_size;

power_word_shield_buff_t( priest_t* player )
: absorb_buff_t( player, "power_word_shield", player->find_class_spell( "Power Word: Shield" ) )
{
set_absorb_source( player->get_stats( "power_word_shield" ) );
set_cooldown( 0_s );
initial_size = 0;
buff_period = 0_s; // TODO: Work out why Power Word: Shield has buff period. Work out why shields ticking refreshes
// them to full value.
}

bool trigger( int stacks, double value, double chance, timespan_t duration ) override
{
sim->print_debug( "{} changes stored Power Word: Shield maximum from {} to {}", *player, initial_size, value );
initial_size = value;

return absorb_buff_t::trigger( stacks, value, chance, duration );
}

void trigger_void_shield( double result_amount )
{
// The initial amount of the shield and our "cap" is stored in the Void Shield buff
double left_to_refill = initial_size - current_value;
double refill_amount = std::min( left_to_refill, result_amount );

if ( refill_amount > 0 )
{
sim->print_debug( "{} adds value to Power Word: Shield. original={}, left_to_refill={}, refill_amount={}",
*player, current_value, left_to_refill, refill_amount );
current_value += refill_amount;
}
}
};

// ==========================================================================
// Desperate Prayer - Health Increase buff
Expand Down Expand Up @@ -2859,6 +2904,7 @@ void priest_t::create_gains()
gains.insanity_maddening_touch = get_gain( "Maddening Touch" );
gains.insanity_t30_2pc = get_gain( "Insanity Gained from T30 2PC" );
gains.cauterizing_shadows_health = get_gain( "Health from Cauterizing Shadows" );
gains.shield_discipline = get_gain( "Shield Discipline" );
}

/** Construct priest procs */
Expand Down Expand Up @@ -3785,7 +3831,7 @@ void priest_t::create_buffs()

// Generic buffs
buffs.desperate_prayer = make_buff<buffs::desperate_prayer_t>( *this );
buffs.power_word_shield = new buffs::power_word_shield_buff_t( this );
buffs.power_word_shield = new buffs::power_word_shield_buff_t( this, this );
buffs.fade = make_buff( this, "fade", find_class_spell( "Fade" ) )->set_default_value_from_effect( 1 );
buffs.levitate = make_buff( this, "levitate", specs.levitate_buff )->set_duration( timespan_t::zero() );

Expand Down
6 changes: 6 additions & 0 deletions engine/class_modules/priest/sc_priest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ struct priest_t final : public player_t
propagate_const<gain_t*> insanity_maddening_touch;
propagate_const<gain_t*> insanity_t30_2pc;
propagate_const<gain_t*> cauterizing_shadows_health;
propagate_const<gain_t*> shield_discipline;
} gains;

// Benefits
Expand Down Expand Up @@ -1672,6 +1673,11 @@ struct priest_buff_t : public Base
: Base( td, name, s, item )
{
}
priest_buff_t( actor_pair_t q, util::string_view name, const spell_data_t* s = spell_data_t::nil(),
const item_t* item = nullptr )
: Base( q, name, s, item )
{
}

priest_buff_t( priest_t& p, util::string_view name, const spell_data_t* s = spell_data_t::nil(),
const item_t* item = nullptr )
Expand Down

0 comments on commit 6ce4316

Please sign in to comment.