diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp
index 6f2108ecfe9..72d0ee8ee7d 100644
--- a/engine/class_modules/monk/sc_monk.cpp
+++ b/engine/class_modules/monk/sc_monk.cpp
@@ -589,7 +589,7 @@ void monk_action_t::execute()
base_t::execute();
- trigger_storm_earth_and_fire( this );
+ // trigger_storm_earth_and_fire( this );
}
template
@@ -761,6 +761,30 @@ monk_buff_t::monk_buff_t( monk_td_t *target_data, std::string_view name, const s
{
}
+void monk_buff_t::expire( timespan_t delay )
+{
+ if ( !p().freeze_expiration )
+ base_t::expire( delay );
+}
+
+void monk_buff_t::expire( action_t *action, timespan_t delay )
+{
+ if ( !p().freeze_expiration )
+ base_t::expire( action, delay );
+}
+
+void monk_buff_t::expire_override( int expiration_stacks, timespan_t remaining_duration )
+{
+ if ( !p().freeze_expiration )
+ base_t::expire_override( expiration_stacks, remaining_duration );
+}
+
+void monk_buff_t::decrement( int stacks, double value )
+{
+ if ( !p().freeze_expiration )
+ base_t::decrement( stacks, value );
+}
+
monk_td_t &monk_buff_t::get_td( player_t *t )
{
return *( p().get_target_data( t ) );
@@ -819,16 +843,6 @@ struct monk_snapshot_stats_t : public snapshot_stats_t
monk_snapshot_stats_t( monk_t *player, util::string_view options ) : snapshot_stats_t( player, options )
{
}
-
- void execute() override
- {
- snapshot_stats_t::execute();
-
- // auto *monk = debug_cast( player );
- // monk->stagger->sample_data->buffed_base_value = monk->stagger->base_value();
- // monk->stagger->sample_data->buffed_percent_player_level = monk->stagger->percent( monk->level() );
- // monk->stagger->sample_data->buffed_percent_target_level = monk->stagger->percent( target->level() );
- }
};
namespace pet_summon
@@ -839,6 +853,9 @@ namespace pet_summon
struct storm_earth_and_fire_t : public monk_spell_t
{
+ action_t *fire_sef;
+ action_t *earth_sef;
+
storm_earth_and_fire_t( monk_t *p, util::string_view options_str )
: monk_spell_t( p, "storm_earth_and_fire", p->talent.windwalker.storm_earth_and_fire )
{
@@ -848,6 +865,9 @@ struct storm_earth_and_fire_t : public monk_spell_t
trigger_gcd = timespan_t::zero();
may_combo_strike = true;
callbacks = harmful = may_miss = may_crit = may_dodge = may_parry = may_block = false;
+
+ fire_sef = new monk_spell_t( p, "sef_fire_elemental", spell_data_t::nil() );
+ earth_sef = new monk_spell_t( p, "sef_earth_elemental", spell_data_t::nil() );
}
bool ready() override
@@ -862,8 +882,6 @@ struct storm_earth_and_fire_t : public monk_spell_t
{
monk_spell_t::execute();
- p()->summon_storm_earth_and_fire( data().duration() );
-
if ( p()->talent.windwalker.ordered_elements.ok() )
{
p()->cooldown.rising_sun_kick->reset( true );
@@ -905,9 +923,225 @@ struct storm_earth_and_fire_fixate_t : public monk_spell_t
} // namespace pet_summon
-namespace attacks
+enum sef_type_e
{
+ SEF_TYPE_FIRE,
+ SEF_TYPE_EARTH
+};
+
+template
+struct sef_action_t : monk_spell_t
+{
+ struct child_action_t : TBase
+ {
+ using base_t = TBase;
+ sef_type_e type;
+ bool is_fixated;
+ player_t *target;
+
+ template
+ child_action_t( sef_type_e type, Args &&...args ) : base_t( std::forward( args )... ), type( type )
+ {
+ base_t::background = true;
+
+ // Action name must be amended after construction, requiring changing out
+ // several members of `action_t` as well.
+ switch ( type )
+ {
+ case SEF_TYPE_FIRE:
+ base_t::name_str += "_sef_fire";
+ break;
+ case SEF_TYPE_EARTH:
+ base_t::name_str += "_sef_earth";
+ break;
+ }
+ base_t::internal_id = base_t::p()->get_action_id( base_t::name_str );
+ base_t::gain = base_t::p()->get_gain( base_t::name_str );
+ base_t::cooldown = base_t::p()->get_cooldown( base_t::name_str, this );
+ base_t::internal_cooldown = base_t::p()->get_cooldown( base_t::name_str + "_internal", this );
+ base_t::stats = base_t::p()->get_stats( base_t::name_str, this );
+ }
+
+ bool from_caster_spells( const spelleffect_data_t *eff ) const
+ {
+ switch ( eff->subtype() )
+ {
+ case A_MOD_DAMAGE_FROM_CASTER:
+ case A_MOD_DAMAGE_FROM_CASTER_SPELLS:
+ case A_MOD_CRIT_CHANCE_FROM_CASTER:
+ case A_MOD_CRIT_CHANCE_FROM_CASTER_SPELLS:
+ case A_MOD_AUTO_ATTACK_FROM_CASTER:
+ case A_MOD_CRIT_DAMAGE_PCT_FROM_CASTER_SPELLS:
+ case A_MOD_DAMAGE_FROM_CASTER_SPELLS_LABEL:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ bool add_mod( const spelleffect_data_t *eff ) const
+ {
+ switch ( eff->subtype() )
+ {
+ case A_ADD_FLAT_MODIFIER:
+ case A_ADD_PCT_MODIFIER:
+ case A_ADD_PCT_LABEL_MODIFIER:
+ case A_ADD_FLAT_LABEL_MODIFIER:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ void init_finished() override
+ {
+ base_t::init_finished();
+
+ switch ( type )
+ {
+ case SEF_TYPE_FIRE:
+ base_t::p()->find_action( "sef_fire_elemental" )->add_child( this );
+ break;
+ case SEF_TYPE_EARTH:
+ base_t::p()->find_action( "sef_earth_elemental" )->add_child( this );
+ break;
+ }
+ }
+
+ double composite_player_multiplier( const action_state_t * ) const override
+ {
+ // Composite Player Multiplier is strictly school mods, which get skipped.
+ return 1.0;
+ }
+
+ double composite_crit_chance() const override
+ {
+ auto cc = base_t::derived_t::composite_crit_chance();
+
+ for ( const auto &i : base_t::crit_chance_effects )
+ if ( !from_caster_spells( i.eff ) )
+ cc += base_t::get_effect_value( i );
+
+ return cc;
+ }
+
+ double composite_crit_damage_bonus_multiplier() const override
+ {
+ // Crit Damage Bonus Multipliers double dip.
+ auto cd = std::pow( base_t::derived_t::composite_crit_damage_bonus_multiplier(), 2 );
+
+ // If non-A_ADD, apply again.
+ for ( const auto &i : base_t::crit_bonus_effects )
+ if ( !add_mod( i.eff ) )
+ cd *= 1.0 + base_t::get_effect_value( i, false );
+
+ return cd;
+ }
+ double composite_target_crit_damage_bonus_multiplier( player_t *target ) const override
+ {
+ auto cd = base_t::derived_t::composite_target_crit_damage_bonus_multiplier( target );
+ auto td = base_t::p()->get_target_data( target );
+
+ for ( const auto &i : base_t::target_crit_bonus_effects )
+ if ( !from_caster_spells( i.eff ) )
+ cd *= 1.0 + base_t::get_effect_value( i, td );
+
+ return cd;
+ }
+
+ double composite_da_multiplier( const action_state_t *state ) const override
+ {
+ auto da = base_t::derived_t::composite_da_multiplier( state );
+
+ for ( const auto &i : base_t::da_multiplier_effects )
+ if ( !from_caster_spells( i.eff ) )
+ da *= 1.0 + base_t::get_effect_value( i, false );
+
+ return da;
+ }
+
+ double composite_ta_multiplier( const action_state_t *state ) const override
+ {
+ auto ta = base_t::derived_t::composite_ta_multiplier( state );
+
+ for ( const auto &i : base_t::ta_multiplier_effects )
+ if ( !from_caster_spells( i.eff ) )
+ ta *= 1.0 + base_t::get_effect_value( i, false );
+
+ return ta;
+ }
+ };
+
+ action_t *parent_action;
+ action_t *sef_fire_action;
+ action_t *sef_earth_action;
+
+ template
+ sef_action_t( TBase *parent, Args &&...args )
+ : monk_spell_t( parent->p(), parent->name_str + "_sef_composite" ),
+ parent_action( parent ),
+ sef_fire_action( new child_action_t( SEF_TYPE_FIRE, parent->p(), std::forward( args )... ) ),
+ sef_earth_action( new child_action_t( SEF_TYPE_EARTH, parent->p(), std::forward( args )... ) )
+ {
+ }
+
+ void execute() override
+ {
+ p()->freeze_expiration = true;
+ sef_fire_action->execute();
+ sef_earth_action->execute();
+ p()->freeze_expiration = false;
+
+ parent_action->execute();
+ base_t::execute();
+ }
+};
+
+// struct sef_action_t : base_t
+// {
+// action_t *sef_fire_action;
+// action_t *sef_earth_action;
+
+// // TODO: Target Fire/Earth actions
+// /*
+// * If a non-sleeping target exists with MotC debuff <10s, target that.
+// * If it is already targeted by another elemental, do not retarget.
+// * If all MotC debuffs >=10s, do not retarget.
+// * If fixated, do not retarget.
+// */
+
+// template
+// sef_action_t( monk_t *player, Args &&...args ) : base_t( player, std::forward( args )... )
+// {
+// if ( !player->talent.windwalker.storm_earth_and_fire->ok() )
+// return;
+
+// sef_fire_action =
+// new child_action_t( player, fmt::format( "{}_{}", base_t::name_str, "fire" ), std::forward( args )...
+// );
+// sef_earth_action =
+// new child_action_t( player, fmt::format( "{}_{}", base_t::name_str, "earth" ), std::forward( args )...
+// );
+
+// // TODO: Set SEF actions as children of the parent SEF action for each elemental.
+// }
+
+// void execute() override
+// {
+// base_t::p()->freeze_expiration = true;
+// sef_fire_action->execute_on_target( base_t::p()->target );
+// sef_earth_action->execute_on_target( base_t::p()->target );
+
+// base_t::p()->freeze_expiration = false;
+// base_t::execute();
+// }
+// };
+
+namespace attacks
+{
// ==========================================================================
// Windwalking Aura Toggle
// ==========================================================================
@@ -1708,7 +1942,7 @@ struct charred_passions_t : base_action_t
// Blackout Kick Baseline ability =======================================
struct blackout_kick_t : overwhelming_force_t>
{
- blackout_kick_totm_proc_t *bok_totm_proc;
+ action_t *bok_totm_proc;
cooldown_t *keg_smash_cooldown;
blackout_kick_t( monk_t *p, util::string_view options_str )
@@ -1739,8 +1973,13 @@ struct blackout_kick_t : overwhelming_force_tshared.teachings_of_the_monastery->ok() )
{
- bok_totm_proc = new blackout_kick_totm_proc_t( p );
- add_child( bok_totm_proc );
+ if ( action_t *totm = p->find_action( "blackout_kick_totm_proc" ); totm )
+ bok_totm_proc = totm;
+ else
+ {
+ bok_totm_proc = new blackout_kick_totm_proc_t( p );
+ add_child( bok_totm_proc );
+ }
}
if ( p->baseline.windwalker.blackout_kick_rank_2->ok() )
@@ -1848,8 +2087,8 @@ struct blackout_kick_t : overwhelming_force_ttalent.windwalker.memory_of_the_monastery.enabled() && p()->bugs )
{
- // TODO: Confirm proper mechanics for this. Tested 17/06/2024 and behaviour has it expire previous stacks before
- // triggering new which feels like a bug.
+ // TODO: Confirm proper mechanics for this. Tested 17/06/2024 and behaviour has it expire previous stacks
+ // before triggering new which feels like a bug.
p()->buff.memory_of_the_monastery->expire();
}
@@ -4251,7 +4490,7 @@ struct celestial_conduit_t : public monk_spell_t
struct celestial_conduit_dmg_t : public monk_spell_t
{
celestial_conduit_dmg_t( monk_t *p )
- : monk_spell_t( p, "celestial_conduit_dmg", p->talent.conduit_of_the_celestials.celestial_conduit_dmg )
+ : monk_spell_t( p, "celestial_conduit_damage", p->talent.conduit_of_the_celestials.celestial_conduit_dmg )
{
background = true;
aoe = -1;
@@ -6292,6 +6531,7 @@ monk_t::monk_t( sim_t *sim, util::string_view name, race_e r )
efficient_training_energy( 0 ),
flurry_strikes_energy( 0 ),
flurry_strikes_damage( 0 ),
+ freeze_expiration( false ),
buff(),
gain(),
proc(),
@@ -6339,9 +6579,9 @@ monk_t::monk_t( sim_t *sim, util::string_view name, race_e r )
}
user_options.initial_chi =
talent.windwalker.combat_wisdom.ok() ? (int)talent.windwalker.combat_wisdom->effectN( 1 ).base_value() : 0;
- user_options.chi_burst_healing_targets = 8;
- user_options.motc_override = 0;
- user_options.squirm_frequency = 15;
+ user_options.motc_override = 0;
+ user_options.squirm_frequency = 15;
+ user_options.sef_beta = false;
}
void monk_t::parse_player_effects()
@@ -6449,121 +6689,117 @@ action_t *monk_t::create_action( util::string_view name, util::string_view optio
if ( name == "auto_attack" )
return new auto_attack_t( this, options_str );
if ( name == "crackling_jade_lightning" )
- return new crackling_jade_lightning_t( this, options_str );
+ return make_action( options_str );
if ( name == "tiger_palm" )
- return new tiger_palm_t( this, options_str );
+ return make_action( options_str );
if ( name == "blackout_kick" )
- return new blackout_kick_t( this, options_str );
+ return make_action( options_str );
if ( name == "expel_harm" )
- return new expel_harm_t( this, options_str );
+ return make_action( options_str );
if ( name == "leg_sweep" )
- return new leg_sweep_t( this, options_str );
+ return make_action( options_str );
if ( name == "paralysis" )
- return new paralysis_t( this, options_str );
+ return make_action( options_str );
if ( name == "rising_sun_kick" )
- return new rising_sun_kick_t( this, options_str );
+ return make_action( options_str );
if ( name == "roll" )
- return new roll_t( this, options_str );
+ return make_action( options_str );
if ( name == "spear_hand_strike" )
- return new spear_hand_strike_t( this, options_str );
+ return make_action( options_str );
if ( name == "spinning_crane_kick" )
- return new spinning_crane_kick_t( this, options_str );
+ return make_action( options_str );
if ( name == "vivify" )
- return new vivify_t( this, options_str );
+ return make_action( options_str );
// Brewmaster
if ( name == "breath_of_fire" )
- return new breath_of_fire_t( this, options_str );
+ return make_action( options_str );
if ( name == "celestial_brew" )
- return new celestial_brew_t( this, options_str );
+ return make_action( options_str );
if ( name == "exploding_keg" )
- return new exploding_keg_t( this, options_str );
+ return make_action( options_str );
if ( name == "fortifying_brew" )
- return new fortifying_brew_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_niuzao" )
- return new niuzao_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_niuzao_the_black_ox" )
- return new niuzao_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "keg_smash" )
- return new press_the_advantage_t( this, options_str );
+ return make_action>( options_str );
if ( name == "purifying_brew" )
- return new purifying_brew_t( this, options_str );
+ return make_action( options_str );
if ( name == "provoke" )
- return new provoke_t( this, options_str );
+ return make_action( options_str );
// Mistweaver
if ( name == "enveloping_mist" )
- return new enveloping_mist_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_chiji" )
- return new chiji_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_chiji_the_red_crane" )
- return new chiji_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_yulon" )
- return new yulon_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_yulon_the_jade_serpent" )
- return new yulon_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "life_cocoon" )
- return new life_cocoon_t( this, options_str );
+ return make_action( options_str );
if ( name == "mana_tea" )
- return new mana_tea_t( this, options_str );
- // if ( name == "renewing_mist" )
- // return new renewing_mist_t( this, options_str );
+ return make_action( options_str );
if ( name == "revival" )
- return new revival_t( this, options_str );
+ return make_action( options_str );
if ( name == "thunder_focus_tea" )
- return new thunder_focus_tea_t( this, options_str );
- // if ( name == "zen_pulse" )
- // return new zen_pulse_t( this, options_str );
+ return make_action( options_str );
// Windwalker
if ( name == "fists_of_fury" )
- return new fists_of_fury_t( this, options_str );
+ return make_action( options_str );
if ( name == "flying_serpent_kick" )
- return new flying_serpent_kick_t( this, options_str );
+ return make_action( options_str );
if ( name == "touch_of_karma" )
- return new touch_of_karma_t( this, options_str );
+ return make_action( options_str );
if ( name == "touch_of_death" )
- return new touch_of_death_t( this, options_str );
+ return make_action( options_str );
if ( name == "storm_earth_and_fire" )
- return new storm_earth_and_fire_t( this, options_str );
+ return make_action( options_str );
if ( name == "storm_earth_and_fire_fixate" )
- return new storm_earth_and_fire_fixate_t( this, options_str );
+ return make_action( options_str );
// Talents
if ( name == "chi_burst" )
- return new chi_burst_t( this, options_str );
+ return make_action( options_str );
if ( name == "chi_torpedo" )
- return new chi_torpedo_t( this, options_str );
+ return make_action( options_str );
if ( name == "black_ox_brew" )
- return new black_ox_brew_t( this, options_str );
+ return make_action( options_str );
if ( name == "dampen_harm" )
- return new dampen_harm_t( this, options_str );
+ return make_action( options_str );
if ( name == "diffuse_magic" )
- return new diffuse_magic_t( this, options_str );
+ return make_action( options_str );
if ( name == "strike_of_the_windlord" )
- return new strike_of_the_windlord_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_xuen" )
- return new xuen_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "invoke_xuen_the_white_tiger" )
- return new xuen_spell_t( this, options_str );
+ return make_action( options_str );
if ( name == "refreshing_jade_wind" )
- return new refreshing_jade_wind_t( this, options_str );
+ return make_action( options_str );
if ( name == "rushing_jade_wind" )
- return new rushing_jade_wind_t( this, options_str );
+ return make_action( options_str );
if ( name == "whirling_dragon_punch" )
- return new whirling_dragon_punch_t( this, options_str );
+ return make_action( options_str );
// Covenant Abilities
if ( name == "jadefire_stomp" )
- return new jadefire_stomp_t( this, options_str );
+ return make_action( options_str );
if ( name == "weapons_of_order" )
- return new weapons_of_order_t( this, options_str );
+ return make_action( options_str );
// Hero Talents
if ( name == "celestial_conduit" )
- return new celestial_conduit_t( this, options_str );
+ return make_action( options_str );
if ( name == "unity_within" )
- return new unity_within_t( this, options_str );
+ return make_action( options_str );
return base_t::create_action( name, options_str );
}
@@ -8791,9 +9027,9 @@ void monk_t::create_options()
base_t::create_options();
add_option( opt_int( "monk.initial_chi", user_options.initial_chi, 0, 6 ) );
- add_option( opt_int( "monk.chi_burst_healing_targets", user_options.chi_burst_healing_targets, 0, 30 ) );
add_option( opt_int( "monk.motc_override", user_options.motc_override, 0, 5 ) );
add_option( opt_float( "monk.squirm_frequency", user_options.squirm_frequency, 0, 30 ) );
+ add_option( opt_bool( "monk.sef_beta", user_options.sef_beta ) );
}
// monk_t::copy_from =========================================================
@@ -8807,6 +9043,32 @@ void monk_t::copy_from( player_t *source )
user_options = source_p->user_options;
}
+template
+action_t *monk_t::make_action( Args &&...args )
+{
+ // 1. create action A no matter what
+ // 2. if the action should not be replicated (channeled, repeated action), return action A
+ // 3. if action A is affected by sef, create sef composite action B using action A
+ // 4. when executing, use sef composite action B execute as to override necessary behaviour
+
+ TAction *parent = new TAction( this, std::forward( args )... );
+ if ( parent->channeled )
+ return parent;
+ if ( talent.windwalker.storm_earth_and_fire->ok() &&
+ parent->data().affected_by( talent.windwalker.storm_earth_and_fire ) )
+ return new actions::sef_action_t( parent, std::forward( args )... );
+ return parent;
+}
+
+// monk_t::copy_from =========================================================
+action_t *monk_t::find_action( unsigned int id ) const
+{
+ for ( action_t *action : action_list )
+ if ( id == action->id )
+ return action;
+ return nullptr;
+}
+
// monk_t::primary_resource =================================================
resource_e monk_t::primary_resource() const
diff --git a/engine/class_modules/monk/sc_monk.hpp b/engine/class_modules/monk/sc_monk.hpp
index 7fdb544461d..e5a0d8acdf2 100644
--- a/engine/class_modules/monk/sc_monk.hpp
+++ b/engine/class_modules/monk/sc_monk.hpp
@@ -83,9 +83,14 @@ enum class sef_ability_e
SEF_MAX
};
+template
+struct sef_action_t;
+
template
struct monk_action_t : public parse_action_effects_t
{
+ using derived_t = Base;
+ using base_t = parse_action_effects_t;
sef_ability_e sef_ability;
bool ww_mastery;
bool may_combo_strike;
@@ -97,8 +102,6 @@ struct monk_action_t : public parse_action_effects_t
std::array _resource_by_stance;
public:
- using base_t = parse_action_effects_t;
-
template
monk_action_t( Args &&...args );
std::string full_name() const;
@@ -176,6 +179,8 @@ struct monk_melee_attack_t : public monk_action_t
struct monk_buff_t : public buff_t
{
+ using base_t = buff_t;
+
monk_buff_t( monk_t *player, std::string_view name, const spell_data_t *spell_data = spell_data_t::nil(),
const item_t *item = nullptr );
monk_buff_t( monk_td_t *player, std::string_view name, const spell_data_t *spell_data = spell_data_t::nil(),
@@ -184,6 +189,11 @@ struct monk_buff_t : public buff_t
const monk_td_t *find_td( player_t *target ) const;
monk_t &p();
const monk_t &p() const;
+
+ void expire( timespan_t delay = timespan_t::zero() ) override;
+ void expire( action_t *action, timespan_t delay = timespan_t::zero() );
+ void decrement( int stacks = 1, double value = DEFAULT_VALUE() ) override;
+ void expire_override( int expiration_stacks, timespan_t remaining_duration ) override;
};
struct summon_pet_t : public monk_spell_t
@@ -489,6 +499,8 @@ struct monk_t : public stagger_t
int efficient_training_energy;
int flurry_strikes_energy;
double flurry_strikes_damage;
+ bool freeze_expiration;
+ bool freeze_buffs;
//==============================================
// Monk Movement
@@ -1302,9 +1314,10 @@ struct monk_t : public stagger_t
int initial_chi;
double expel_harm_effectiveness;
double jadefire_stomp_uptime;
- int chi_burst_healing_targets;
int motc_override;
double squirm_frequency;
+
+ bool sef_beta;
} user_options;
// exterminate these structs
@@ -1384,6 +1397,10 @@ struct monk_t : public stagger_t
void reset() override;
void create_options() override;
void copy_from( player_t * ) override;
+ template
+ action_t *make_action( Args &&...args );
+ using player_t::find_action;
+ action_t *find_action( unsigned int id ) const;
resource_e primary_resource() const override;
role_e primary_role() const override;
stat_e convert_hybrid_stat( stat_e s ) const override;
diff --git a/engine/class_modules/monk/sc_monk_pets.cpp b/engine/class_modules/monk/sc_monk_pets.cpp
index 5ab5f7e6f7c..4c078ff1183 100644
--- a/engine/class_modules/monk/sc_monk_pets.cpp
+++ b/engine/class_modules/monk/sc_monk_pets.cpp
@@ -349,20 +349,6 @@ struct monk_pet_buff_t : public buff_t
return p().o();
};
};
-
-// ===============================================================================
-// Tier 28 Primordial Power Buff
-// ===============================================================================
-
-struct primordial_power_buff_t : public monk_pet_buff_t
-{
- primordial_power_buff_t( monk_pet_t &p, util::string_view n, const spell_data_t *s ) : monk_pet_buff_t( p, n, s )
- {
- add_invalidate( CACHE_PLAYER_DAMAGE_MULTIPLIER );
- set_reverse( true );
- set_reverse_stack_count( s->max_stacks() );
- }
-};
} // namespace buffs
// ==========================================================================
@@ -376,58 +362,42 @@ struct storm_earth_and_fire_pet_t : public monk_pet_t
template
struct sef_action_base_t : public pet_action_base_t
{
- using super_t = pet_action_base_t;
- using base_t = sef_action_base_t;
+ using base_t = pet_action_base_t;
const action_t *source_action;
- // Windwalker Tier 28 4-piece info
- // Currently Primordial Power is only a visual buff and not tied to any direct damage buff
- // the buff is pulled from the player
- // Currently the buff appears if SEF is summoned before Primordial Potential becomes Primordial Power
- // buff does not appear if SEF is summoned after Primordial Power is active.
-
- sef_action_base_t( util::string_view n, storm_earth_and_fire_pet_t *p,
- const spell_data_t *data = spell_data_t::nil() )
- : super_t( n, p, data ), source_action( nullptr )
+ sef_action_base_t( std::string_view name, storm_earth_and_fire_pet_t *p,
+ const spell_data_t *spell_data = spell_data_t::nil() )
+ : base_t( name, p, spell_data ), source_action( nullptr )
{
- // Make SEF attacks always background, so they do not consume resources
- // or do anything associated with "foreground actions".
- this->background = this->may_crit = true;
- this->callbacks = false;
+ base_t::background = true;
+ base_t::cooldown->duration = timespan_t::zero();
- // Cooldowns are handled automatically by the mirror abilities, the SEF specific ones need none.
- this->cooldown->duration = timespan_t::zero();
+ // TODO: Is this correct?
+ base_t::callbacks = false;
+ }
- // No costs are needed either
- this->base_costs[ RESOURCE_ENERGY ] = 0;
- this->base_costs[ RESOURCE_CHI ] = 0;
+ double base_cost() const override
+ {
+ return 0.0;
}
void init() override
{
- super_t::init();
+ base_t::init();
- // Find source_action from the owner by matching the action name and
- // spell id with eachother. This basically means that by default, any
- // spell-data driven ability with 1:1 mapping of name/spell id will
- // always be chosen as the source action. In some cases this needs to be
- // overridden (see sef_zen_sphere_t for example).
- for ( const action_t *a : this->o()->action_list )
- {
- if ( ( this->id > 0 && this->id == a->id ) || util::str_compare_ci( this->name_str, a->name_str ) )
- {
- source_action = a;
- break;
- }
- }
+ // Look up source action based on id, falling back to name if not found.
+ if ( action_t *action = base_t::o()->find_action( base_t::id ) )
+ source_action = action;
+ else
+ source_action = base_t::o()->find_action( base_t::name_str );
- if ( source_action )
- {
- this->update_flags = source_action->update_flags;
- auto pet_multiplier_snapshot = this->snapshot_flags & STATE_MUL_PET;
- this->snapshot_flags = source_action->snapshot_flags | pet_multiplier_snapshot;
- }
+ if ( !source_action )
+ return;
+
+ base_t::update_flags = source_action->update_flags;
+ // isn't base_t::snapshot_flags == source_action->snapshot_flags or 0?
+ base_t::snapshot_flags = source_action->snapshot_flags | ( base_t::snapshot_flags & STATE_MUL_PET );
}
void snapshot_internal( action_state_t *state, unsigned flags, result_amount_type rt ) override
@@ -509,6 +479,7 @@ struct storm_earth_and_fire_pet_t : public monk_pet_t
struct sef_melee_attack_t : public sef_action_base_t
{
+ using base_t = sef_action_base_t;
sef_melee_attack_t( util::string_view n, storm_earth_and_fire_pet_t *p,
const spell_data_t *data = spell_data_t::nil() )
: base_t( n, p, data )
@@ -533,6 +504,7 @@ struct storm_earth_and_fire_pet_t : public monk_pet_t
struct sef_spell_t : public sef_action_base_t
{
+ using base_t = sef_action_base_t;
sef_spell_t( util::string_view n, storm_earth_and_fire_pet_t *p, const spell_data_t *data = spell_data_t::nil() )
: base_t( n, p, data )
{
@@ -739,7 +711,7 @@ struct storm_earth_and_fire_pet_t : public monk_pet_t
sef_glory_of_the_dawn_t *glory_of_the_dawn;
sef_rising_sun_kick_dmg_t( storm_earth_and_fire_pet_t *player )
- : sef_melee_attack_t( "rising_sun_kick_dmg", player,
+ : sef_melee_attack_t( "rising_sun_kick_damage", player,
player->o()->talent.monk.rising_sun_kick->effectN( 1 ).trigger() )
{
background = true;
@@ -1203,8 +1175,6 @@ struct storm_earth_and_fire_pet_t : public monk_pet_t
propagate_const bok_proc_sef = nullptr;
propagate_const pressure_point_sef = nullptr;
propagate_const rushing_jade_wind_sef = nullptr;
- // Tier 28 Buff
- propagate_const primordial_power = nullptr;
} buff;
storm_earth_and_fire_pet_t( util::string_view name, monk_t *owner, bool dual_wield, weapon_e weapon_type )