diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp
index 87a4c8d501c..1fcae9ff822 100644
--- a/engine/class_modules/monk/sc_monk.cpp
+++ b/engine/class_modules/monk/sc_monk.cpp
@@ -166,7 +166,8 @@ void monk_action_t::apply_buff_effects()
parse_effects( p()->buff.blackout_combo );
parse_effects(
p()->buff.counterstrike,
- affect_list_t( 1 ).add_spell( p()->baseline.brewmaster.spinning_crane_kick->effectN( 1 ).trigger()->id() ) );
+ affect_list_t( 1 ).add_spell( p()->baseline.brewmaster.spinning_crane_kick->effectN( 1 ).trigger()->id() ),
+ CONSUME_BUFF );
// Mistweaver
parse_effects( p()->buff.jadefire_brand, p()->talent.windwalker.jadefire_brand_heal );
@@ -450,11 +451,11 @@ void monk_action_t::consume_resource()
if ( !base_t::execute_state ) // Fixes rare crashes at combat_end.
return;
- auto cost = base_t::cost();
+ auto final_cost = base_t::cost();
if ( current_resource() == RESOURCE_ENERGY )
{
- if ( cost > 0 )
+ if ( final_cost > 0 )
{
if ( p()->talent.shado_pan.flurry_strikes.ok() )
{
@@ -464,7 +465,7 @@ void monk_action_t::consume_resource()
// Crackling Jade Lightning is whatever the current cost
else if ( base_t::id == p()->baseline.monk.crackling_jade_lightning->id() )
// this needs to be rounded to the nearest whole number
- p()->flurry_strikes_energy += as( std::round( cost ) );
+ p()->flurry_strikes_energy += as( std::round( final_cost ) );
// Detox, Paralysis and Vivify do not count towards Flurry Strikes
if ( p()->flurry_strikes_energy >= p()->talent.shado_pan.flurry_strikes->effectN( 2 ).base_value() )
{
@@ -475,7 +476,7 @@ void monk_action_t::consume_resource()
if ( p()->talent.shado_pan.efficient_training.ok() )
{
- p()->efficient_training_energy += as( cost );
+ p()->efficient_training_energy += as( final_cost );
if ( p()->efficient_training_energy >= p()->talent.shado_pan.efficient_training->effectN( 3 ).base_value() )
{
timespan_t cdr =
@@ -494,16 +495,16 @@ void monk_action_t::consume_resource()
// Dance of Chi-Ji talent triggers from spending chi
p()->buff.dance_of_chiji->trigger();
- cost = base_t::base_cost();
+ auto base_cost = base_t::base_cost();
- if ( cost )
+ if ( base_cost )
{
// This triggers prior to cost reduction
- p()->buff.heart_of_the_jade_serpent_stack_ww->trigger( as( cost ) );
+ p()->buff.heart_of_the_jade_serpent_stack_ww->trigger( as( base_cost ) );
if ( p()->talent.windwalker.spiritual_focus->ok() )
{
- p()->spiritual_focus_count += cost;
+ p()->spiritual_focus_count += base_cost;
if ( p()->spiritual_focus_count >= p()->talent.windwalker.spiritual_focus->effectN( 1 ).base_value() )
{
@@ -520,7 +521,7 @@ void monk_action_t::consume_resource()
if ( p()->buff.storm_earth_and_fire->up() )
{
auto time_extend = p()->talent.windwalker.drinking_horn_cover->effectN( 1 ).percent();
- time_extend *= cost;
+ time_extend *= base_cost;
p()->buff.storm_earth_and_fire->extend_duration( p(), timespan_t::from_seconds( time_extend ) );
@@ -1398,7 +1399,11 @@ struct tiger_palm_t : public monk_melee_attack_t
apply_affecting_aura( p->talent.windwalker.touch_of_the_tiger );
apply_affecting_aura( p->talent.windwalker.inner_peace );
- parse_effects( p->talent.brewmaster.face_palm, [ this ]() { return face_palm; } );
+ if ( const auto &effect = p->talent.brewmaster.face_palm->effectN( 2 ); effect.ok() )
+ add_parse_entry( da_multiplier_effects )
+ .set_func( [ & ] { return face_palm; } )
+ .set_value( effect.percent() - 1.0 )
+ .set_eff( &effect );
parse_effects( p->buff.combat_wisdom );
parse_effects( p->buff.martial_mixture );
parse_effects( p->buff.darting_hurricane );
@@ -1432,16 +1437,16 @@ struct tiger_palm_t : public monk_melee_attack_t
if ( p()->buff.blackout_combo->up() )
p()->proc.blackout_combo_tiger_palm->occur();
- p()->buff.blackout_combo->expire();
if ( p()->buff.counterstrike->up() )
p()->proc.counterstrike_tp->occur();
- p()->buff.counterstrike->expire();
//------------
monk_melee_attack_t::execute();
+ p()->buff.blackout_combo->expire();
+
if ( result_is_miss( execute_state->result ) )
return;
@@ -1552,7 +1557,8 @@ struct press_the_advantage_t : base_action_t
damage_t( monk_t *player, std::string_view name )
: base_action_t( player, {}, name ),
- mod( 1.0 - player->talent.brewmaster.press_the_advantage->effectN( 3 ).percent() )
+ mod( 1.0 - player->talent.brewmaster.press_the_advantage->effectN( 3 ).percent() ),
+ face_palm( false )
{
base_action_t::proc = true;
base_action_t::trigger_gcd = 0_s;
@@ -1562,23 +1568,32 @@ struct press_the_advantage_t : base_action_t
base_action_t::parse_effects( player->buff.counterstrike,
affect_list_t( 1 ).add_spell( base_action_t::data().id() ),
player->buff.counterstrike->data().effectN( 1 ).percent() * mod );
+ base_action_t::parse_effects( player->buff.blackout_combo,
+ affect_list_t( 1 ).add_spell( base_action_t::data().id() ),
+ player->buff.blackout_combo->data().effectN( 1 ).percent() * mod );
+
// effect must still be rolled in execute so it triggers brew cdr
- base_action_t::parse_effects(
- player->buff.blackout_combo, affect_list_t( 1 ).add_spell( base_action_t::data().id() ),
- player->buff.counterstrike->data().effectN( 1 ).percent() * mod, [ this ]() { return face_palm; } );
+ if ( const auto &effect = player->talent.brewmaster.face_palm->effectN( 2 ); effect.ok() )
+ add_parse_entry( base_action_t::da_multiplier_effects )
+ .set_func( [ & ] { return face_palm; } )
+ .set_value( ( effect.percent() - 1.0 ) * mod )
+ .set_eff( &effect );
}
void execute() override
{
base_action_t::p()->buff.press_the_advantage->expire();
- face_palm = base_action_t::rng().roll( base_action_t::p()->talent.brewmaster.face_palm->effectN( 1 ).percent() );
- base_action_t::execute();
-
- if ( face_palm )
+ if ( ( face_palm = base_action_t::rng().roll(
+ base_action_t::p()->talent.brewmaster.face_palm->effectN( 1 ).percent() ) ) )
+ {
+ base_action_t::p()->proc.face_palm->occur();
base_action_t::p()->baseline.brewmaster.brews->adjust(
base_action_t::p()->talent.brewmaster.face_palm->effectN( 3 ).time_value() );
- base_action_t::p()->buff.counterstrike->expire();
+ }
+
+ base_action_t::execute();
+
base_action_t::p()->buff.blackout_combo->expire();
if ( base_action_t::p()->talent.brewmaster.chi_surge->ok() )
@@ -1658,7 +1673,7 @@ struct rising_sun_kick_dmg_t : public monk_melee_attack_t
// Brewmaster RSK also applies the WoO debuff.
if ( p()->buff.weapons_of_order->up() )
- for ( auto &target : target_list() )
+ for ( const auto &target : target_list() )
get_td( target )->debuff.weapons_of_order->trigger();
}
@@ -2397,10 +2412,7 @@ struct spinning_crane_kick_t : public monk_melee_attack_t
p()->buff.kicks_of_flowing_momentum->decrement();
if ( p()->buff.counterstrike->up() )
- {
p()->proc.counterstrike_sck->occur();
- p()->buff.counterstrike->expire();
- }
}
};
@@ -2984,9 +2996,7 @@ struct melee_t : public monk_melee_attack_t
void execute() override
{
- if ( first )
- first = false;
-
+ first = false;
monk_melee_attack_t::execute();
}
@@ -3430,14 +3440,6 @@ struct spear_hand_strike_t : public monk_melee_attack_t
cast_during_sck = player->specialization() != MONK_WINDWALKER;
may_miss = may_block = may_dodge = may_parry = false;
}
-
- void execute() override
- {
- monk_melee_attack_t::execute();
-
- // if ( p()->level() <= 50 )
- // p()->trigger_sephuzs_secret( execute_state, MECHANIC_INTERRUPT );
- }
};
// ==========================================================================
@@ -3456,14 +3458,6 @@ struct leg_sweep_t : public monk_melee_attack_t
radius += p->talent.monk.tiger_tail_sweep->effectN( 1 ).base_value();
}
-
- void execute() override
- {
- monk_melee_attack_t::execute();
-
- // if ( p()->level() <= 50 )
- // p()->trigger_sephuzs_secret( execute_state, MECHANIC_STUN );
- }
};
// ==========================================================================
@@ -3719,7 +3713,7 @@ struct crackling_jade_lightning_t : public monk_spell_t
parse_options( options_str );
// Forcing the minimum GCD to 750 milliseconds for all 3 specs
- min_gcd = timespan_t::from_millis( 750 );
+ min_gcd = timespan_t::from_millis( 750 );
parse_effects( p->talent.windwalker.power_of_the_thunder_king, effect_mask_t( true ).disable( 1 ) );
parse_effects( p->buff.the_emperors_capacitor );
@@ -3735,7 +3729,7 @@ struct crackling_jade_lightning_t : public monk_spell_t
if ( p()->talent.windwalker.power_of_the_thunder_king->ok() )
{
const auto &tl = target_list();
- double count = 0;
+ int count = 0;
for ( auto &t : tl )
{
@@ -3761,9 +3755,7 @@ struct crackling_jade_lightning_t : public monk_spell_t
if ( p()->talent.windwalker.power_of_the_thunder_king->ok() )
{
const auto &tl = target_list();
- double count = 0;
-
- for ( auto &t : tl )
+ for ( const auto &t : tl )
{
get_td( t )->dot.crackling_jade_lightning_aoe->cancel();
get_td( t )->dot.crackling_jade_lightning_sef->cancel();
@@ -3798,7 +3790,8 @@ struct breath_of_fire_dot_t : public monk_spell_t
{
bool blackout_combo;
- breath_of_fire_dot_t( monk_t *p ) : monk_spell_t( p, "breath_of_fire_dot", p->talent.brewmaster.breath_of_fire_dot )
+ breath_of_fire_dot_t( monk_t *p )
+ : monk_spell_t( p, "breath_of_fire_dot", p->talent.brewmaster.breath_of_fire_dot ), blackout_combo( false )
{
background = true;
tick_may_crit = may_crit = true;
@@ -4043,7 +4036,8 @@ struct purifying_brew_t : public brew_t
p()->buff.ox_stance->trigger( stacks );
p()->buff.aspect_of_harmony->trigger_flat(
stacks * p()->talent.master_of_harmony.clarity_of_purpose->effectN( 1 ).percent() *
- ( 1.0 + p()->composite_damage_versatility() ) );
+ ( 1.0 + p()->composite_damage_versatility() ) *
+ p()->composite_total_attack_power_by_type( attack_power_type::WEAPON_MAINHAND ) );
p()->buff.recent_purifies->trigger( stacks );
}
@@ -4382,11 +4376,6 @@ struct strength_of_the_black_ox_t : public monk_spell_t
.set_value( effect.percent() )
.set_eff( &effect );
}
-
- void execute() override
- {
- monk_spell_t::execute();
- }
};
struct strength_of_the_black_ox_absorb_t : public monk_absorb_t
@@ -5377,7 +5366,7 @@ struct chi_wave_t : public monk_spell_t
TBase::execute();
}
- void impact( action_state_t *state )
+ void impact( action_state_t *state ) override
{
TBase::impact( state );
other_cb( ++count );
@@ -5627,7 +5616,6 @@ struct celestial_brew_t : public brew_t
p()->buff.purified_chi->trigger( (int)p()->talent.brewmaster.blackout_combo->effectN( 6 ).base_value() );
p()->proc.blackout_combo_celestial_brew->occur();
}
- p()->buff.blackout_combo->expire();
if ( p()->sets->has_set_bonus( MONK_BREWMASTER, T31, B4 ) )
{
@@ -5639,6 +5627,7 @@ struct celestial_brew_t : public brew_t
p()->buff.aspect_of_harmony->trigger_spend();
brew_t::execute();
+ p()->buff.blackout_combo->expire();
p()->buff.purified_chi->expire();
p()->buff.pretense_of_instability->trigger();
p()->active_actions.special_delivery->execute();
@@ -5893,17 +5882,6 @@ void shuffle_t::trigger( timespan_t duration )
accumulator -= threshold * count;
}
-// ===============================================================================
-// Elixir of Determination
-// ===============================================================================
-
-struct flow_of_chi_t : hp_triggered_buff_t
-{
- flow_of_chi_t( monk_t *player ) : hp_triggered_buff_t( player, player->talent.monk.flow_of_chi )
- {
- }
-};
-
// ===============================================================================
// Fortifying Brew Buff
// ===============================================================================
@@ -5987,7 +5965,7 @@ struct rushing_jade_wind_buff_t : public monk_buff_t
reduced_aoe_targets = p->passives.rushing_jade_wind->effectN( 1 ).base_value();
// Merge action statistics if RJW exists as an active ability
- if ( action_t *action = p->find_action( "rushing_jade_wind" ); action )
+ if ( const action_t *action = p->find_action( "rushing_jade_wind" ); action )
stats = action->stats;
}
};
@@ -6337,7 +6315,7 @@ struct blackout_reinforcement_t : public monk_buff_t
// ===============================================================================
aspect_of_harmony_t::aspect_of_harmony_t( monk_t *player )
- : accumulator( nullptr ), spender( nullptr ), path_of_resurgence( nullptr ), heal( nullptr )
+ : accumulator( nullptr ), spender( nullptr ), path_of_resurgence( nullptr ), heal( nullptr ), fallback( false )
{
if ( !player->talent.master_of_harmony.aspect_of_harmony->ok() )
{
@@ -6368,6 +6346,8 @@ void aspect_of_harmony_t::trigger_flat( double amount )
if ( fallback || spender->check() )
return;
+ accumulator->sim->print_debug( "Aspect of Harmony +A: {}, P: {}, T: {}", amount, accumulator->current_value,
+ accumulator->current_value + amount );
accumulator->current_value += amount;
}
@@ -6426,6 +6406,8 @@ void aspect_of_harmony_t::accumulator_t::trigger_with_state( action_state_t *sta
multiplier *= 1.0 + effect.percent();
double amount = std::min( check_value() + state->result_amount * multiplier, p().max_health() );
+ sim->print_debug( "Aspect of Harmony +A: {}, P: {}, T: {}", state->result_amount * multiplier, check_value(),
+ check_value() + state->result_amount * multiplier );
monk_buff_t::trigger( -1, amount );
}
@@ -6464,12 +6446,14 @@ void aspect_of_harmony_t::spender_t::reset()
{
monk_buff_t::reset();
pool = 0.0;
+ sim->print_debug( "Aspect of Harmony =P: 0" );
}
bool aspect_of_harmony_t::spender_t::trigger( int stacks, double, double chance, timespan_t duration )
{
pool = accumulator->check_value();
accumulator->expire();
+ sim->print_debug( "Aspect of Harmony +P: {}", pool );
return monk_buff_t::trigger( stacks, pool, chance, duration );
}
@@ -6479,13 +6463,15 @@ void aspect_of_harmony_t::spender_t::trigger_with_state( action_state_t *state )
return;
double multiplier = p().talent.master_of_harmony.aspect_of_harmony->effectN( 6 ).percent();
- double amount = std::min( state->result_amount * multiplier, pool );
- if ( amount == pool )
+ double amount = std::min( state->result_amount * multiplier, current_value );
+ if ( amount >= current_value )
{
+ sim->print_debug( "Aspect of Harmony -P: {}, P: {}, T: {}", amount, current_value, current_value - amount );
+ pool = current_value;
expire();
return;
}
- pool -= amount;
+ current_value -= amount;
const auto whitelist = { p().baseline.monk.expel_harm->id(), p().baseline.monk.vivify->id(),
p().baseline.monk.blackout_kick->id(), p().baseline.monk.tiger_palm->id() };
@@ -6500,15 +6486,21 @@ void aspect_of_harmony_t::spender_t::trigger_with_state( action_state_t *state )
case result_amount_type::DMG_DIRECT:
case result_amount_type::DMG_OVER_TIME:
if ( p().specialization() == MONK_BREWMASTER || in_hg_whitelist() )
+ {
+ sim->print_debug( "Aspect of Harmony -P: {}, P: {}, T: {}", amount, current_value + amount, current_value );
residual_action::trigger( damage, state->target, amount );
- return;
+ }
+ break;
case result_amount_type::HEAL_DIRECT:
case result_amount_type::HEAL_OVER_TIME:
if ( p().specialization() == MONK_MISTWEAVER || in_hg_whitelist() )
+ {
+ sim->print_debug( "Aspect of Harmony -P: {}, P: {}, T: {}", amount, current_value + amount, current_value );
residual_action::trigger( heal, state->target, amount );
- return;
+ }
+ break;
default:
- return;
+ break;
}
}
@@ -7962,7 +7954,7 @@ void monk_t::create_buffs()
{ "quick_sip", "staggering_strikes", "touch_of_death", "purifying_brew", "tranquil_spirit_eh",
"tranquil_spirit_goto" },
[ this ]() { return specialization() == MONK_BREWMASTER; },
- [ this ]( school_e, result_amount_type, action_state_t *state ) {
+ [ this ]( school_e, result_amount_type, const action_state_t *state ) {
if ( state->action->id == baseline.brewmaster.stagger_self_damage->id() )
return false;
return true;
@@ -8562,8 +8554,6 @@ void monk_t::create_buffs()
movement.whirling_dragon_punch = new monk_movement_t( this, "wdp_movement", talent.windwalker.whirling_dragon_punch );
movement.whirling_dragon_punch->set_distance( 1 );
-
- buff.flow_of_chi = new buffs::flow_of_chi_t( this );
}
// monk_t::init_gains =======================================================
@@ -8765,9 +8755,9 @@ void monk_t::create_proc_callback( const spell_data_t *effect_driver,
if ( !state->target->is_sleeping() )
{
// Dynamically find and execute proc tracking
- auto proc = p->find_proc( effect.trigger()->_name );
- if ( proc )
- proc->occur();
+ auto effect_proc = p->find_proc( effect.trigger()->_name );
+ if ( effect_proc )
+ effect_proc->occur();
}
dbc_proc_callback_t::execute( a, state );
@@ -8912,15 +8902,13 @@ void monk_t::init_special_effects()
// ======================================
if ( talent.master_of_harmony.aspect_of_harmony->ok() )
{
- auto register_cb = [ this ]( const spell_data_t *spell_data ) {
- auto filter_cb = []( monk_t *, action_state_t *) { return true; };
- auto trigger_cb = [ this ]( const dbc_proc_callback_t *, action_t *, action_state_t *state ) {
- buff.aspect_of_harmony->trigger( state );
- };
- create_proc_callback( spell_data, filter_cb );
- callbacks.register_callback_execute_function( spell_data->id(), trigger_cb );
- };
- register_cb( talent.master_of_harmony.aspect_of_harmony_driver );
+ create_proc_callback( talent.master_of_harmony.aspect_of_harmony_driver,
+ []( monk_t *, action_state_t * ) { return true; } );
+ callbacks.register_callback_execute_function(
+ talent.master_of_harmony.aspect_of_harmony_driver->id(),
+ [ this ]( const dbc_proc_callback_t *, action_t *, action_state_t *state ) {
+ buff.aspect_of_harmony->trigger( state );
+ } );
}
if ( talent.master_of_harmony.balanced_stratagem->ok() )
@@ -9067,7 +9055,7 @@ std::vector monk_t::create_storm_earth_and_fire_target_list() const
// Sort the list by selecting non-cyclone striked targets first, followed by ascending order of
// the debuff remaining duration
- range::sort( l, [ this ]( player_t *l, player_t *r ) {
+ range::sort( l, [ this ]( const player_t *l, const player_t *r ) {
auto td_left = find_target_data( l );
auto td_right = find_target_data( r );
bool lcs = td_left ? td_left->debuff.mark_of_the_crane->check() : false;
@@ -9488,7 +9476,7 @@ void monk_t::assess_damage( school_e school, result_amount_type dtype, action_st
void monk_t::target_mitigation( school_e school, result_amount_type dt, action_state_t *s )
{
- auto target_data = get_target_data( s->action->player );
+ monk_td_t *target_td = get_target_data( s->action->player );
// Dampen Harm // Reduces hits by 20 - 50% based on the size of the hit
if ( buff.dampen_harm->up() )
@@ -9509,7 +9497,7 @@ void monk_t::target_mitigation( school_e school, result_amount_type dt, action_s
s->result_amount *= 1.0 + buff.diffuse_magic->value(); // Stored as -60%
// If Breath of Fire is ticking on the source target, the player receives 5% less damage
- if ( target_data->dot.breath_of_fire->is_ticking() )
+ if ( target_td->dot.breath_of_fire->is_ticking() )
s->result_amount *=
1.0 + active_actions.breath_of_fire->data().effectN( 2 ).percent() + buff.celestial_flames->value() / 100.0;
@@ -9797,7 +9785,7 @@ class monk_report_t : public player_report_extension_t
// Description: Self-explanatory
// Date: Self-explanatory
// Match: True if sim matches in-game behavior
- auto ReportIssue = [ this ]( std::string desc, std::string date, bool match = false ) {
+ auto ReportIssue = [ this ]( std::string_view desc, std::string_view date, bool match = false ) {
monk_bug *new_issue = new monk_bug;
new_issue->desc = desc;
new_issue->date = date;
diff --git a/engine/class_modules/monk/sc_monk.hpp b/engine/class_modules/monk/sc_monk.hpp
index beda0c02e27..6d1ea437526 100644
--- a/engine/class_modules/monk/sc_monk.hpp
+++ b/engine/class_modules/monk/sc_monk.hpp
@@ -27,42 +27,6 @@
#include "simulationcraft.hpp"
-template
-struct hp_triggered_buff_t
-{
- struct buff_pack_t
- {
- const spelleffect_data_t *effect;
- const spell_data_t *spell_data;
- propagate_const buff;
-
- buff_pack_t( TActor *player, const spelleffect_data_t *effect )
- : effect( effect ),
- spell_data( effect->trigger() ),
- buff( make_buff( player, fmt::format( "{}_{}", effect->spell()->name_cstr(), effect->id() ),
- effect->trigger() ) )
- {
- }
- };
-
- std::vector> buffs;
- hp_triggered_buff_t( TActor *player, const spell_data_t *driver )
- {
- for ( const spelleffect_data_t &effect : driver->effects() )
- if ( effect.type() == E_APPLY_AURA && effect.subtype() == A_468 )
- buffs.emplace_back( std::make_unique( player, &effect ) );
-
- std::sort( buffs.begin(), buffs.end(),
- []( const std::unique_ptr &lhs, const std::unique_ptr &rhs ) {
- return lhs->effect->base_value() > rhs->effect->base_value();
- } );
- }
-
- std::unique_ptr trigger()
- {
- }
-};
-
namespace monk
{
struct monk_t;
@@ -768,8 +732,6 @@ struct monk_t : public stagger_t
propagate_const tigers_ferocity;
propagate_const flow_of_battle_damage;
propagate_const flow_of_battle_free_keg_smash;
-
- propagate_const *> flow_of_chi;
} buff;
struct gains_t