From 135c4d85477c224bc5ba6f7be6d8cacf4671f16c Mon Sep 17 00:00:00 2001 From: Kate Martin <51387586+renanthera@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:04:58 -0600 Subject: [PATCH 1/3] [monk] Zenith Stomp can be cast while channeling Spinning Crane Kick. Zenith Stomp is considered a combo strike ability. --- engine/class_modules/monk/sc_monk.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp index 7087ce112ae..cc763b8154d 100644 --- a/engine/class_modules/monk/sc_monk.cpp +++ b/engine/class_modules/monk/sc_monk.cpp @@ -3958,8 +3958,9 @@ struct zenith_stomp_t : monk_spell_t aoe = -1; reduced_aoe_targets = player->talent.monk.zenith_stomp->effectN( 1 ).base_value(); - may_combo_strike = false; + may_combo_strike = player->wowv_ge( { 12, 1, 0 } ); ww_mastery = true; + cast_during_sck = true; } void init() override From 3af7969a4c23659b0b9ed9e736e07b1df307de44 Mon Sep 17 00:00:00 2001 From: Kate Martin <51387586+renanthera@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:05:49 -0600 Subject: [PATCH 2/3] [monk] Reimplement `cast_during_sck` using `action_t::usable_during_current_cast()` and by setting `action_t::usable_while_casting` and `action_t::use_while_casting` automatically to avoid a terrible APL experience. --- engine/class_modules/monk/sc_monk.cpp | 31 ++++++--------------------- engine/class_modules/monk/sc_monk.hpp | 2 +- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp index cc763b8154d..aeb3053313e 100644 --- a/engine/class_modules/monk/sc_monk.cpp +++ b/engine/class_modules/monk/sc_monk.cpp @@ -221,18 +221,12 @@ bool monk_action_t::usable_moving() const } template -bool monk_action_t::ready() +bool monk_action_t::usable_during_current_cast() const { - // Spell data nil or not_found - if ( base_t::data().id() == 0 ) - return false; - - // These abilities are able to be used during Spinning Crane Kick - if ( cast_during_sck ) - base_t::usable_while_casting = p()->channeling && p()->baseline.monk.spinning_crane_kick && - ( p()->channeling->id == p()->baseline.monk.spinning_crane_kick->id() ); + if ( cast_during_sck && p()->channeling && p()->channeling->id == p()->baseline.monk.spinning_crane_kick->id() ) + return true; - return base_t::ready(); + return base_t::usable_during_current_cast(); } template @@ -260,20 +254,8 @@ void monk_action_t::init() } } - // Allow this ability to be cast during SCK - if ( cast_during_sck && !base_t::background && !base_t::dual ) - { - if ( base_t::usable_while_casting ) - { - cast_during_sck = false; - p()->sim->print_debug( "{}: cast_during_sck ignored because usable_while_casting = true", full_name() ); - } - else - { - base_t::usable_while_casting = true; - base_t::use_while_casting = true; - } - } + if ( cast_during_sck ) + base_t::usable_while_casting = base_t::use_while_casting = true; } template @@ -2502,7 +2484,6 @@ struct keg_smash_t : monk_melee_attack_t fuel_on_the_fire( nullptr ) { parse_options( options_str ); - // TODO: can cast_during_sck be automated? cast_during_sck = true; full_amount_targets = 1; diff --git a/engine/class_modules/monk/sc_monk.hpp b/engine/class_modules/monk/sc_monk.hpp index c96afdd6741..923171a3450 100644 --- a/engine/class_modules/monk/sc_monk.hpp +++ b/engine/class_modules/monk/sc_monk.hpp @@ -97,7 +97,7 @@ struct monk_action_t : public parse_action_effects_t std::unique_ptr create_expression( std::string_view name_str ) override; bool usable_moving() const override; - bool ready() override; + bool usable_during_current_cast() const override; void init() override; void init_finished() override; void reset_swing(); From a29f51f42792df411e2a3485e9ebf0357b844879 Mon Sep 17 00:00:00 2001 From: Kate Martin <51387586+renanthera@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:14:35 -0600 Subject: [PATCH 3/3] [monk] Clean up some unused actions. Use Slicing Winds constructor for Flying Serpent Kick actions if talent is selected. --- engine/class_modules/monk/sc_monk.cpp | 115 +------------------------- 1 file changed, 2 insertions(+), 113 deletions(-) diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp index aeb3053313e..21deaee0570 100644 --- a/engine/class_modules/monk/sc_monk.cpp +++ b/engine/class_modules/monk/sc_monk.cpp @@ -2799,60 +2799,6 @@ struct touch_of_karma_t : public monk_melee_attack_t } }; -struct provoke_t : public monk_melee_attack_t -{ - provoke_t( monk_t *p, std::string_view options_str ) : monk_melee_attack_t( p, "provoke", p->baseline.monk.provoke ) - { - parse_options( options_str ); - use_off_gcd = true; - ignore_false_positive = true; - } - - void impact( action_state_t *s ) override - { - if ( s->target->is_enemy() ) - target->taunt( player ); - - monk_melee_attack_t::impact( s ); - } -}; - -struct spear_hand_strike_t : public monk_melee_attack_t -{ - spear_hand_strike_t( monk_t *p, std::string_view options_str ) - : monk_melee_attack_t( p, "spear_hand_strike", p->talent.monk.spear_hand_strike ) - { - parse_options( options_str ); - ignore_false_positive = true; - is_interrupt = true; - cast_during_sck = player->specialization() != MONK_WINDWALKER; - may_miss = may_block = may_dodge = may_parry = false; - } -}; - -struct leg_sweep_t : public monk_melee_attack_t -{ - leg_sweep_t( monk_t *p, std::string_view options_str ) - : monk_melee_attack_t( p, "leg_sweep", p->baseline.monk.leg_sweep ) - { - parse_options( options_str ); - ignore_false_positive = true; - may_miss = may_block = may_dodge = may_parry = false; - cast_during_sck = true; - } -}; - -struct paralysis_t : public monk_melee_attack_t -{ - paralysis_t( monk_t *p, std::string_view options_str ) - : monk_melee_attack_t( p, "paralysis", p->talent.monk.paralysis ) - { - parse_options( options_str ); - ignore_false_positive = true; - may_miss = may_block = may_dodge = may_parry = false; - } -}; - struct flying_serpent_kick_t : public monk_melee_attack_t { bool first_charge; @@ -3139,31 +3085,6 @@ struct black_ox_brew_t : public brew_t } }; -struct roll_t : public monk_spell_t -{ - roll_t( monk_t *player, std::string_view options_str ) - : monk_spell_t( player, "roll", - ( player->talent.monk.chi_torpedo->ok() ? spell_data_t::not_found() : player->baseline.monk.roll ) ) - { - cast_during_sck = true; - - parse_options( options_str ); - } -}; - -struct chi_torpedo_t : public monk_spell_t -{ - chi_torpedo_t( monk_t *player, std::string_view options_str ) - : monk_spell_t( - player, "chi_torpedo", - ( player->talent.monk.chi_torpedo->ok() ? player->talent.monk.chi_torpedo : spell_data_t::not_found() ) ) - { - parse_options( options_str ); - - cast_during_sck = true; - } -}; - struct crackling_jade_lightning_t : public monk_spell_t { struct aoe_dot_t : public monk_spell_t @@ -4013,26 +3934,6 @@ struct zenith_t : public monk_spell_t } }; -struct vivify_t : public harmonic_surge_t -{ - vivify_t( monk_t *player, std::string_view options_str ) : base_t( player, "vivify", player->baseline.monk.vivify ) - { - parse_options( options_str ); - - spell_power_mod.direct = data().effectN( 1 ).sp_coeff(); - base_execute_time += player->talent.monk.vivacious_vivification->effectN( 1 ).time_value(); - - cast_during_sck = false; - } - - void execute() override - { - base_t::execute(); - - p()->action.chi_wave->execute(); - } -}; - struct expel_harm_t : monk_heal_t { struct damage_t : monk_spell_t @@ -5364,28 +5265,14 @@ action_t *monk_t::create_action( std::string_view name, std::string_view options return new blackout_kick_t( this, options_str ); if ( name == "expel_harm" ) return new expel_harm_t( this, options_str ); - if ( name == "leg_sweep" ) - return new leg_sweep_t( this, options_str ); - if ( name == "paralysis" ) - return new paralysis_t( this, options_str ); if ( name == "rising_sun_kick" ) return new rising_sun_kick_t( this, options_str ); if ( name == "rushing_wind_kick" ) return new rushing_wind_kick_t( this, options_str ); - if ( name == "roll" ) - return new roll_t( this, options_str ); - if ( name == "spear_hand_strike" ) - return new spear_hand_strike_t( this, options_str ); if ( name == "spinning_crane_kick" ) return new spinning_crane_kick_t( this, options_str ); - if ( name == "vivify" ) - return new vivify_t( this, options_str ); if ( name == "fortifying_brew" ) return new fortifying_brew_t( this, options_str ); - if ( name == "provoke" ) - return new provoke_t( this, options_str ); - if ( name == "chi_torpedo" ) - return new chi_torpedo_t( this, options_str ); if ( name == "touch_of_death" ) return new touch_of_death_t( this, options_str ); @@ -5418,6 +5305,8 @@ action_t *monk_t::create_action( std::string_view name, std::string_view options // Windwalker if ( name == "fists_of_fury" ) return new fists_of_fury_t( this, options_str ); + if ( name == "flying_serpent_kick" && talent.windwalker.slicing_winds->ok() ) + return new slicing_winds_t( this, options_str ); if ( name == "flying_serpent_kick" ) return new flying_serpent_kick_t( this, options_str ); if ( name == "slicing_winds" )