\n";
os << "
Known Bugs and Issues
\n";
From d455b3985641eba6fa9649cd1dff67d4e2c5db19 Mon Sep 17 00:00:00 2001
From: Kate Martin <51387586+renanthera@users.noreply.github.com>
Date: Sun, 12 Jul 2026 13:18:57 -0600
Subject: [PATCH 8/9] [monk] Use `player` instead of `p` in action
constructors. Prototype for updates to make `use_during_sck` concept more
general.
---
engine/class_modules/monk/sc_monk.cpp | 137 ++++++++++++++------------
engine/class_modules/monk/sc_monk.hpp | 4 +-
2 files changed, 78 insertions(+), 63 deletions(-)
diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp
index 2660eee363f..18033f82f40 100644
--- a/engine/class_modules/monk/sc_monk.cpp
+++ b/engine/class_modules/monk/sc_monk.cpp
@@ -46,6 +46,11 @@ Manatee
#include "simulationcraft.hpp"
+#define CAST_DURING( ... ) cast_during_ids = { __VA_ARGS__ }
+#define SPINNING_CRANE_KICK_IDS \
+ player->baseline.brewmaster.spinning_crane_kick->id(), player->baseline.monk.spinning_crane_kick->id()
+#define CELESTIAL_CONDUIT_IDS player->talent.conduit_of_the_celestials.celestial_conduit_action->id()
+
namespace monk
{
namespace functions
@@ -73,8 +78,10 @@ monk_action_t
::monk_action_t( Args &&...args )
: parse_action_effects_t
( std::forward
( args )... ),
ww_mastery( false ),
may_combo_strike( false ),
- cast_during_sck( false ),
- track_cd_waste( false )
+ cast_during_ids(),
+ track_cd_waste( false ),
+ persistent_multiplier_effects(),
+ _resource_by_stance()
{
range::fill( _resource_by_stance, RESOURCE_MAX );
@@ -221,12 +228,13 @@ bool monk_action_t::usable_moving() const
}
template
-bool monk_action_t::usable_during_current_cast() const
+bool monk_action_t::ready()
{
- if ( cast_during_sck && p()->channeling && p()->channeling->id == p()->baseline.monk.spinning_crane_kick->id() )
- return true;
+ if ( p()->channeling )
+ base_t::usable_while_casting = range::any_of(
+ cast_during_ids, [ this ]( const unsigned &id ) { return id != 0 && p()->channeling->id == id; } );
- return base_t::usable_during_current_cast();
+ return base_t::ready();
}
template
@@ -254,7 +262,7 @@ void monk_action_t::init()
}
}
- if ( cast_during_sck )
+ if ( cast_during_ids.size() && !base_t::background && !base_t::dual )
base_t::usable_while_casting = base_t::use_while_casting = true;
}
@@ -828,7 +836,7 @@ struct tiger_palm_t : public harmonic_surge_tbuff.combat_wisdom );
}
@@ -1101,7 +1109,7 @@ struct rising_sun_kick_t : monk_melee_attack_t
parse_options( options_str );
may_combo_strike = true;
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
add_child( rising_sun_kick );
}
@@ -1362,7 +1370,7 @@ struct blackout_kick_t : overwhelming_force_ttalent.brewmaster.rushing_jade_wind->effectN( 1 ).trigger() );
@@ -1615,8 +1623,8 @@ struct spinning_crane_kick_t : public monk_melee_attack_t
interrupt_auto_attack = player->specialization() != MONK_WINDWALKER;
if ( player->specialization() == MONK_BREWMASTER )
{
- dot_behavior = DOT_EXTEND;
- cast_during_sck = true;
+ dot_behavior = DOT_EXTEND;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
}
if ( player->specialization() == MONK_WINDWALKER )
@@ -1916,7 +1924,7 @@ struct whirling_dragon_punch_t : public monk_melee_attack_t
// action using `tick_action` is nonviable. ticks must be scheduled manually.
may_combo_strike = true;
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
aoe = new damage_t( player, "aoe", player->talent.windwalker.whirling_dragon_punch_aoe_tick );
aoe->aoe = -1;
@@ -2029,7 +2037,7 @@ struct strike_of_the_windlord_t : public monk_melee_attack_t
off_hand( nullptr )
{
may_combo_strike = true;
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
cooldown->hasted = false;
trigger_gcd = data().gcd();
@@ -2484,7 +2492,7 @@ struct keg_smash_t : monk_melee_attack_t
fuel_on_the_fire( nullptr )
{
parse_options( options_str );
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
full_amount_targets = 1;
reduced_aoe_targets = data().effectN( 7 ).base_value();
@@ -2605,14 +2613,14 @@ struct stomp_t : monk_melee_attack_t
struct touch_of_death_t : public monk_melee_attack_t
{
- touch_of_death_t( monk_t *p, std::string_view options_str )
- : monk_melee_attack_t( p, "touch_of_death", p->baseline.monk.touch_of_death )
+ touch_of_death_t( monk_t *player, std::string_view options_str )
+ : monk_melee_attack_t( player, "touch_of_death", player->baseline.monk.touch_of_death )
{
ww_mastery = true;
may_crit = hasted_ticks = false;
may_combo_strike = true;
- cast_during_sck = true;
- ignores_armor = true; // instead use the trick to have no multipliers apply?
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
+ ignores_armor = true; // instead use the trick to have no multipliers apply?
parse_options( options_str );
cooldown->duration = data().cooldown();
@@ -2688,7 +2696,8 @@ struct touch_of_death_t : public monk_melee_attack_t
struct touch_of_karma_dot_t : public residual_action::residual_periodic_action_t
{
using base_t = residual_action::residual_periodic_action_t;
- touch_of_karma_dot_t( monk_t *p ) : base_t( "touch_of_karma", p, p->baseline.windwalker.touch_of_karma_tick )
+ touch_of_karma_dot_t( monk_t *player )
+ : base_t( "touch_of_karma", player, player->baseline.windwalker.touch_of_karma_tick )
{
may_miss = may_crit = false;
dual = true;
@@ -2721,13 +2730,14 @@ struct touch_of_karma_t : public monk_melee_attack_t
double interval_stddev_opt;
double pct_health;
touch_of_karma_dot_t *touch_of_karma_dot;
- touch_of_karma_t( monk_t *p, std::string_view options_str )
- : monk_melee_attack_t( p, "touch_of_karma", p->baseline.windwalker.touch_of_karma ),
+
+ touch_of_karma_t( monk_t *player, std::string_view options_str )
+ : monk_melee_attack_t( player, "touch_of_karma", player->baseline.windwalker.touch_of_karma ),
interval( 100 ),
interval_stddev( 0.05 ),
interval_stddev_opt( 0 ),
pct_health( 0.5 ),
- touch_of_karma_dot( new touch_of_karma_dot_t( p ) )
+ touch_of_karma_dot( new touch_of_karma_dot_t( player ) )
{
add_option( opt_float( "interval", interval ) );
add_option( opt_float( "interval_stddev", interval_stddev_opt ) );
@@ -2737,7 +2747,7 @@ struct touch_of_karma_t : public monk_melee_attack_t
cooldown->duration = data().cooldown();
base_dd_min = base_dd_max = 0;
ap_type = attack_power_type::NO_WEAPON;
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
double max_pct = data().effectN( 3 ).percent();
@@ -2802,8 +2812,9 @@ struct touch_of_karma_t : public monk_melee_attack_t
struct flying_serpent_kick_t : public monk_melee_attack_t
{
bool first_charge;
- flying_serpent_kick_t( monk_t *p, std::string_view options_str )
- : monk_melee_attack_t( p, "flying_serpent_kick", p->baseline.windwalker.flying_serpent_kick ), first_charge( true )
+ flying_serpent_kick_t( monk_t *player, std::string_view options_str )
+ : monk_melee_attack_t( player, "flying_serpent_kick", player->baseline.windwalker.flying_serpent_kick ),
+ first_charge( true )
{
parse_options( options_str );
may_crit = true;
@@ -3226,7 +3237,7 @@ struct breath_of_fire_t : public monk_spell_t
aoe = -1;
reduced_aoe_targets = 1.0;
full_amount_targets = 1;
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
dot = new dot_t( player );
add_child( dot );
@@ -3276,27 +3287,29 @@ struct fortifying_brew_t : brew_t
{
struct niuzaos_protection_t : public monk_absorb_t
{
- niuzaos_protection_t( monk_t *p )
- : monk_absorb_t( p, "niuzaos_protection", p->talent.conduit_of_the_celestials.niuzaos_protection )
+ niuzaos_protection_t( monk_t *player )
+ : monk_absorb_t( player, "niuzaos_protection", player->talent.conduit_of_the_celestials.niuzaos_protection )
{
background = true;
- target = p;
- base_dd_min = p->max_health() * data().effectN( 2 ).percent();
+ target = player;
+ base_dd_min = player->max_health() * data().effectN( 2 ).percent();
base_dd_max = base_dd_min;
}
};
niuzaos_protection_t *absorb;
- fortifying_brew_t( monk_t *p, std::string_view options_str )
- : brew_t( p, "fortifying_brew", p->talent.monk.fortifying_brew.find_override_spell() ),
- absorb( p->talent.conduit_of_the_celestials.niuzaos_protection->ok() ? new niuzaos_protection_t( p ) : nullptr )
+ fortifying_brew_t( monk_t *player, std::string_view options_str )
+ : brew_t( player, "fortifying_brew", player->talent.monk.fortifying_brew.find_override_spell() ),
+ absorb( nullptr )
{
- cast_during_sck = true;
-
parse_options( options_str );
harmful = may_crit = false;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
+
+ if ( player->talent.conduit_of_the_celestials.niuzaos_protection->ok() )
+ absorb = new niuzaos_protection_t( player );
}
void execute() override
@@ -3333,14 +3346,15 @@ struct exploding_keg_t : public monk_spell_t
{
cooldown_t *keg_smash;
- exploding_keg_t( monk_t *p, std::string_view options_str )
- : monk_spell_t( p, "exploding_keg", p->talent.brewmaster.exploding_keg )
+ exploding_keg_t( monk_t *player, std::string_view options_str )
+ : monk_spell_t( player, "exploding_keg", player->talent.brewmaster.exploding_keg )
{
parse_options( options_str );
- cast_during_sck = true;
- aoe = -1;
- add_child( p->action.exploding_keg );
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
+ aoe = -1;
+
+ add_child( player->action.exploding_keg );
keg_smash = player->get_cooldown( "keg_smash" );
}
@@ -3444,9 +3458,9 @@ struct purifying_brew_t : public brew_t
{
parse_options( options_str );
- harmful = false;
- cast_during_sck = true;
- use_off_gcd = true;
+ harmful = false;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
+ use_off_gcd = true;
}
bool ready() override
@@ -3558,7 +3572,7 @@ struct xuen_summon_t : public monk_spell_t
{
parse_options( options_str );
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
}
void execute() override
@@ -3685,12 +3699,12 @@ struct flight_of_the_red_crane_t : conduit_of_the_celestials_container_t
struct niuzao_spell_t : public monk_spell_t
{
- niuzao_spell_t( monk_t *p, std::string_view options_str )
- : monk_spell_t( p, "invoke_niuzao_the_black_ox", p->talent.brewmaster.invoke_niuzao_the_black_ox )
+ niuzao_spell_t( monk_t *player, std::string_view options_str )
+ : monk_spell_t( player, "invoke_niuzao_the_black_ox", player->talent.brewmaster.invoke_niuzao_the_black_ox )
{
parse_options( options_str );
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
// Specifically set for 10.1 class trinket
harmful = true;
// Forcing the minimum GCD to 750 milliseconds
@@ -3709,8 +3723,8 @@ struct niuzao_spell_t : public monk_spell_t
struct unity_within_t : public monk_spell_t
{
- unity_within_t( monk_t *p, std::string_view options_str )
- : monk_spell_t( p, "unity_within", p->talent.conduit_of_the_celestials.unity_within )
+ unity_within_t( monk_t *player, std::string_view options_str )
+ : monk_spell_t( player, "unity_within", player->talent.conduit_of_the_celestials.unity_within )
{
parse_options( options_str );
@@ -3866,7 +3880,7 @@ struct zenith_stomp_t : monk_spell_t
reduced_aoe_targets = 5.0;
may_combo_strike = player->wowv_ge( { 12, 1, 0 } );
ww_mastery = true;
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS, CELESTIAL_CONDUIT_IDS );
}
void init() override
@@ -3968,7 +3982,7 @@ struct expel_harm_t : monk_heal_t
damage( new damage_t( player ) )
{
parse_options( options_str );
- cast_during_sck = true;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
if ( player->talent.windwalker.combat_wisdom->ok() )
background = true;
@@ -4018,15 +4032,15 @@ struct expel_harm_t : monk_heal_t
struct celestial_fortune_t : public monk_heal_t
{
- celestial_fortune_t( monk_t *p )
- : monk_heal_t( p, "celestial_fortune", p->baseline.brewmaster.celestial_fortune_heal )
+ celestial_fortune_t( monk_t *player )
+ : monk_heal_t( player, "celestial_fortune", player->baseline.brewmaster.celestial_fortune_heal )
{
background = true;
proc = true;
target = player;
may_crit = false;
- base_multiplier = p->baseline.brewmaster.celestial_fortune->effectN( 1 ).percent();
+ base_multiplier = player->baseline.brewmaster.celestial_fortune->effectN( 1 ).percent();
}
void init() override
@@ -4045,8 +4059,8 @@ struct absorb_brew_t : public brew_t
: brew_t( player, name, spell_data )
{
parse_options( options_str );
- cast_during_sck = true;
- harmful = false;
+ CAST_DURING( SPINNING_CRANE_KICK_IDS );
+ harmful = false;
}
void execute() override
@@ -4474,13 +4488,14 @@ struct empty_barrel_buff_t : buffs::monk_buff_t<>
struct touch_of_karma_buff_t : public monk_buff_t<>
{
- touch_of_karma_buff_t( monk_t *p, std::string_view n, const spell_data_t *s ) : monk_buff_t( p, n, s )
+ touch_of_karma_buff_t( monk_t *player, std::string_view name, const spell_data_t *spell_data )
+ : monk_buff_t( player, name, spell_data )
{
default_value = 0;
set_cooldown( timespan_t::zero() );
- set_trigger_spell( p->baseline.windwalker.touch_of_karma );
+ set_trigger_spell( player->baseline.windwalker.touch_of_karma );
- set_duration( s->duration() );
+ set_duration( spell_data->duration() );
}
bool trigger( int stacks, double value, double chance, timespan_t duration ) override
diff --git a/engine/class_modules/monk/sc_monk.hpp b/engine/class_modules/monk/sc_monk.hpp
index 923171a3450..20fdf73ed50 100644
--- a/engine/class_modules/monk/sc_monk.hpp
+++ b/engine/class_modules/monk/sc_monk.hpp
@@ -63,7 +63,7 @@ struct monk_action_t : public parse_action_effects_t
{
bool ww_mastery;
bool may_combo_strike;
- bool cast_during_sck;
+ std::vector cast_during_ids;
bool track_cd_waste;
std::vector persistent_multiplier_effects;
@@ -96,8 +96,8 @@ struct monk_action_t : public parse_action_effects_t
std::unique_ptr create_expression( std::string_view name_str ) override;
+ bool ready() override;
bool usable_moving() const override;
- bool usable_during_current_cast() const override;
void init() override;
void init_finished() override;
void reset_swing();
From b17057f8ea140419ec547f966f084f0399b8e9c1 Mon Sep 17 00:00:00 2001
From: Kate Martin <51387586+renanthera@users.noreply.github.com>
Date: Sun, 12 Jul 2026 13:34:43 -0600
Subject: [PATCH 9/9] [monk] Fix condition used to determine when spells should
be checked if they're able to be CWC'd.
---
engine/class_modules/monk/sc_monk.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp
index 18033f82f40..a591a53fff0 100644
--- a/engine/class_modules/monk/sc_monk.cpp
+++ b/engine/class_modules/monk/sc_monk.cpp
@@ -230,9 +230,10 @@ bool monk_action_t::usable_moving() const
template
bool monk_action_t::ready()
{
- if ( p()->channeling )
- base_t::usable_while_casting = range::any_of(
- cast_during_ids, [ this ]( const unsigned &id ) { return id != 0 && p()->channeling->id == id; } );
+ if ( cast_during_ids.size() )
+ base_t::usable_while_casting = range::any_of( cast_during_ids, [ this ]( const unsigned &id ) {
+ return id != 0 && p()->channeling && p()->channeling->id == id;
+ } );
return base_t::ready();
}