From b08e838fa9ae2826ecbeebf784f6e502e1384b28 Mon Sep 17 00:00:00 2001 From: Kate Martin <51387586+renanthera@users.noreply.github.com> Date: Thu, 29 May 2025 18:24:14 -0600 Subject: [PATCH 1/3] [monk] Refactor Monk APL files and update build lists. --- engine/class_modules/apl/apl_monk.cpp | 493 +++++++++++++++----------- engine/class_modules/apl/apl_monk.hpp | 19 - engine/class_modules/monk/sc_monk.cpp | 90 ----- engine/class_modules/monk/sc_monk.hpp | 47 ++- source_files/QT_engine.pri | 1 - source_files/VS_engine.props | 1 - source_files/cmake_engine.txt | 1 - 7 files changed, 311 insertions(+), 341 deletions(-) delete mode 100644 engine/class_modules/apl/apl_monk.hpp diff --git a/engine/class_modules/apl/apl_monk.cpp b/engine/class_modules/apl/apl_monk.cpp index 79e743bbef8..30e1a3291aa 100644 --- a/engine/class_modules/apl/apl_monk.cpp +++ b/engine/class_modules/apl/apl_monk.cpp @@ -1,183 +1,59 @@ -#include "class_modules/apl/apl_monk.hpp" - #include "class_modules/monk/sc_monk.hpp" #include "player/action_priority_list.hpp" #include "player/player.hpp" -namespace monk_apl +#include + +struct player_t; +using monk::monk_t; + +namespace { -std::string potion( const player_t *p ) +namespace brewmaster { - switch ( p->specialization() ) - { - case MONK_BREWMASTER: - if ( p->true_level > 70 ) - return "tempered_potion_3"; - else - return "disabled"; - break; - case MONK_MISTWEAVER: - if ( p->true_level > 70 ) - return "tempered_potion_3"; - else if ( p->true_level > 60 ) - return "elemental_potion_of_ultimate_power_3"; - else if ( p->true_level > 50 ) - return "potion_of_spectral_intellect"; - else if ( p->true_level > 45 ) - return "superior_battle_potion_of_intellect"; - else - return "disabled"; - break; - case MONK_WINDWALKER: - if ( p->true_level > 70 ) - return "tempered_potion_3"; - else if ( p->true_level > 60 ) - return "elemental_potion_of_ultimate_power_3"; - else if ( p->true_level > 50 ) - return "potion_of_spectral_agility"; - else if ( p->true_level > 45 ) - return "unbridled_fury"; - else - return "disabled"; - break; - default: - return "disabled"; - break; - } +std::string default_potion( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "tempered_potion_3"; + return "disabled"; } -std::string flask( const player_t *p ) +std::string default_flask( const monk_t* player ) { - switch ( p->specialization() ) - { - case MONK_BREWMASTER: - if ( p->true_level > 70 ) - return "flask_of_alchemical_chaos_3"; - else - return "disabled"; - break; - case MONK_MISTWEAVER: - if ( p->true_level > 70 ) - return "flask_of_alchemical_chaos_3"; - else if ( p->true_level > 60 ) - return "phial_of_elemental_chaos_3"; - else if ( p->true_level > 50 ) - return "spectral_flask_of_power"; - else if ( p->true_level > 45 ) - return "greater_flask_of_endless_fathoms"; - else - return "disabled"; - break; - case MONK_WINDWALKER: - if ( p->true_level > 70 ) - return "flask_of_alchemical_chaos_3"; - else if ( p->true_level > 60 ) - return "iced_phial_of_corrupting_rage_3"; - else if ( p->true_level > 50 ) - return "spectral_flask_of_power"; - else if ( p->true_level > 45 ) - return "greater_flask_of_the_currents"; - else - return "disabled"; - break; - default: - return "disabled"; - break; - } + if ( player->true_level >= 80 ) + return "flask_of_alchemical_chaos_3"; + return "disabled"; } -std::string food( const player_t *p ) +std::string default_food( const monk_t* player ) { - switch ( p->specialization() ) - { - case MONK_BREWMASTER: - if ( p->true_level > 70 ) - return "feast_of_the_midnight_masquerade"; - else - return "disabled"; - break; - case MONK_MISTWEAVER: - if ( p->true_level > 70 ) - return "feast_of_the_midnight_masquerade"; - else if ( p->true_level > 60 ) - return "roast_duck_delight"; - else if ( p->true_level > 50 ) - return "feast_of_gluttonous_hedonism"; - else if ( p->true_level > 45 ) - return "famine_evaluator_and_snack_table"; - else - return "disabled"; - break; - case MONK_WINDWALKER: - if ( p->true_level > 70 ) - return "feast_of_the_midnight_masquerade"; - else if ( p->true_level > 60 ) - return "aromatic_seafood_platter"; - else if ( p->true_level > 50 ) - return "feast_of_gluttonous_hedonism"; - else if ( p->true_level > 45 ) - return "mechdowels_big_mech"; - else - return "disabled"; - break; - default: - return "disabled"; - break; - } + if ( player->true_level >= 80 ) + return "feast_of_the_midnight_masquerade"; + return "disabled"; } -std::string rune( const player_t *p ) +std::string default_rune( const monk_t* player ) { - if ( p->true_level > 70 ) + if ( player->true_level >= 80 ) return "crystallized"; - else if ( p->true_level > 60 ) - return "draconic"; - else if ( p->true_level > 50 ) - return "veiled"; - else if ( p->true_level > 45 ) - return "battle_scarred"; - else if ( p->true_level > 40 ) - return "defiled"; return "disabled"; } -std::string temporary_enchant( const player_t *p ) +std::string default_temporary_enchant( const monk_t* player ) { - switch ( p->specialization() ) - { - case MONK_BREWMASTER: - if ( p->true_level > 70 ) - return "main_hand:ironclaw_whetstone_3/off_hand:ironclaw_whetstone_3"; - else - return "disabled"; - break; - case MONK_MISTWEAVER: - return "disabled"; - break; - case MONK_WINDWALKER: - if ( p->true_level > 70 ) - return "main_hand:algari_mana_oil_3/off_hand:algari_mana_oil_3"; - else if ( p->true_level > 60 ) - return "main_hand:howling_rune_3/off_hand:howling_rune_3"; - else if ( p->true_level > 50 ) - return "main_hand:shaded_weightstone/off_hand:shaded_weightstone"; - else - return "disabled"; - break; - default: - return "disabled"; - break; - } + if ( player->true_level >= 80 ) + return "main_hand:ironclaw_whetstone_3/off_hand:ironclaw_whetstone_3"; + return "disabled"; } -void brewmaster( player_t *p ) +void default_apl( monk_t* player ) { - std::vector racial_actions = p->get_racial_actions(); - action_priority_list_t *precombat = p->get_action_priority_list( "precombat" ); - action_priority_list_t *default_ = p->get_action_priority_list( "default" ); + std::vector racial_actions = player->get_racial_actions(); + action_priority_list_t* precombat = player->get_action_priority_list( "precombat" ); + action_priority_list_t* default_ = player->get_action_priority_list( "default" ); - action_priority_list_t *item_actions = p->get_action_priority_list( "item_actions" ); - action_priority_list_t *race_actions = p->get_action_priority_list( "race_actions" ); + action_priority_list_t* item_actions = player->get_action_priority_list( "item_actions" ); + action_priority_list_t* race_actions = player->get_action_priority_list( "race_actions" ); precombat->add_action( "snapshot_stats" ); precombat->add_action( "potion" ); precombat->add_action( "chi_burst" ); @@ -231,17 +107,53 @@ void brewmaster( player_t *p ) default_->add_action( "tiger_palm,if=energy>40-cooldown.keg_smash.remains*energy.regen" ); default_->add_action( "spinning_crane_kick,if=energy>40-cooldown.keg_smash.remains*energy.regen" ); } +}; // namespace brewmaster -void mistweaver( player_t *p ) +namespace mistweaver { - action_priority_list_t *pre = p->get_action_priority_list( "precombat" ); - action_priority_list_t *def = p->get_action_priority_list( "default" ); - action_priority_list_t *racials = p->get_action_priority_list( "race_actions" ); +std::string default_potion( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "tempered_potion_3"; + return "disabled"; +} + +std::string default_flask( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "flask_of_alchemical_chaos_3"; + return "disabled"; +} + +std::string default_food( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "feast_of_the_midnight_masquerade"; + return "disabled"; +} + +std::string default_rune( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "crystallized"; + return "disabled"; +} + +std::string default_temporary_enchant( const monk_t* ) +{ + return "disabled"; +} + +void default_apl( monk_t* player ) +{ + action_priority_list_t* pre = player->get_action_priority_list( "precombat" ); + action_priority_list_t* def = player->get_action_priority_list( "default" ); + action_priority_list_t* racials = player->get_action_priority_list( "race_actions" ); pre->add_action( "snapshot_stats" ); pre->add_action( "potion" ); - for ( const auto &racial_action : p->get_racial_actions() ) + for ( const auto& racial_action : player->get_racial_actions() ) racials->add_action( racial_action ); def->add_action( "auto_attack" ); @@ -255,10 +167,8 @@ void mistweaver( player_t *p ) def->add_action( "invoke_chiji,if=talent.invokers_delight" ); def->add_action( "invoke_yulon,if=talent.invokers_delight" ); def->add_action( - "sheiluns_gift,if=talent.shaohaos_lessons&(" - "buff.sheiluns_gift.stack>=10" - "|(buff.sheiluns_gift.stack*4>=fight_remains&buff.sheiluns_gift.stack>=3)" - "|(fight_style.dungeonslice&buff.sheiluns_gift.stack>=5&active_enemies>=4)" + "sheiluns_gift,if=talent.shaohaos_lessons&(buff.sheiluns_gift.stack>=10|(buff.sheiluns_gift.stack*4>=fight_" + "remains&buff.sheiluns_gift.stack>=3)|(fight_style.dungeonslice&buff.sheiluns_gift.stack>=5&active_enemies>=4)" ")" ); def->add_action( "celestial_conduit" ); def->add_action( "rising_sun_kick,if=talent.secret_infusion&buff.thunder_focus_tea.up" ); @@ -272,17 +182,55 @@ void mistweaver( player_t *p ) def->add_action( "jadefire_stomp,if=buff.jadefire_stomp.down" ); def->add_action( "rising_sun_kick,if=active_enemies<=2" ); def->add_action( - "blackout_kick,if=buff.teachings_of_the_monastery.stack>=3" - "&(active_enemies>=2|cooldown.rising_sun_kick.remains>gcd)" ); + "blackout_kick,if=buff.teachings_of_the_monastery.stack>=3&(active_enemies>=2|cooldown.rising_sun_kick.remains>" + "gcd)" ); def->add_action( "tiger_palm" ); } +}; // namespace mistweaver + +namespace windwalker +{ +std::string default_potion( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "tempered_potion_3"; + return "disabled"; +} + +std::string default_flask( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "flask_of_alchemical_chaos_3"; + return "disabled"; +} + +std::string default_food( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "feast_of_the_midnight_masquerade"; + return "disabled"; +} + +std::string default_rune( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "crystallized"; + return "disabled"; +} -void windwalker_live( player_t *p ) +std::string default_temporary_enchant( const monk_t* player ) +{ + if ( player->true_level >= 80 ) + return "main_hand:algari_mana_oil_3/off_hand:algari_mana_oil_3"; + return "disabled"; +} + +void live_apl( monk_t* player ) { //============================================================================ // On-use Items //============================================================================ - auto _WW_ON_USE = []( const item_t &item ) { + auto _WW_ON_USE = []( const item_t& item ) { //------------------------------------------- // SEF item map //------------------------------------------- @@ -307,8 +255,7 @@ void windwalker_live( player_t *p ) ",if=!trinket.1.has_use_buff&!trinket.2.has_use_buff|(trinket.1.has_use_buff|trinket.2.has_use_buff)&" "cooldown.invoke_xuen_the_white_tiger.remains>30|fight_remains<5" }, // Signet of the Priory is not properly detected as ITEM_STAT_BUFF - { "signet_of_the_priory", - ",if=pet.xuen_the_white_tiger.active|fight_remains<20" }, + { "signet_of_the_priory", ",if=pet.xuen_the_white_tiger.active|fight_remains<20" }, // Defaults: { "ITEM_STAT_BUFF", ",if=pet.xuen_the_white_tiger.active" }, @@ -357,16 +304,16 @@ void windwalker_live( player_t *p ) return concat; }; - action_priority_list_t *pre = p->get_action_priority_list( "precombat" ); - action_priority_list_t *def = p->get_action_priority_list( "default" ); - action_priority_list_t *trinkets = p->get_action_priority_list( "trinkets" ); - action_priority_list_t *aoe_opener = p->get_action_priority_list( "aoe_opener" ); - action_priority_list_t *normal_opener = p->get_action_priority_list( "normal_opener" ); - action_priority_list_t *cooldowns = p->get_action_priority_list( "cooldowns" ); - action_priority_list_t *default_aoe = p->get_action_priority_list( "default_aoe" ); - action_priority_list_t *default_cleave = p->get_action_priority_list( "default_cleave" ); - action_priority_list_t *default_st = p->get_action_priority_list( "default_st" ); - action_priority_list_t *fallback = p->get_action_priority_list( "fallback" ); + action_priority_list_t* pre = player->get_action_priority_list( "precombat" ); + action_priority_list_t* def = player->get_action_priority_list( "default" ); + action_priority_list_t* trinkets = player->get_action_priority_list( "trinkets" ); + action_priority_list_t* aoe_opener = player->get_action_priority_list( "aoe_opener" ); + action_priority_list_t* normal_opener = player->get_action_priority_list( "normal_opener" ); + action_priority_list_t* cooldowns = player->get_action_priority_list( "cooldowns" ); + action_priority_list_t* default_aoe = player->get_action_priority_list( "default_aoe" ); + action_priority_list_t* default_cleave = player->get_action_priority_list( "default_cleave" ); + action_priority_list_t* default_st = player->get_action_priority_list( "default_st" ); + action_priority_list_t* fallback = player->get_action_priority_list( "fallback" ); pre->add_action( "snapshot_stats", "Snapshot raid buffed stats before combat begins and pre-potting is done." ); pre->add_action( "use_item,name=imperfect_ascendancy_serum" ); @@ -465,7 +412,7 @@ void windwalker_live( player_t *p ) def->add_action( "arcane_pulse,if=buff.storm_earth_and_fire.down" ); // Trinkets - for ( const auto &item : p->items ) + for ( const auto& item : player->items ) { if ( item.has_special_effect( SPECIAL_EFFECT_SOURCE_ITEM, SPECIAL_EFFECT_USE ) ) trinkets->add_action( "use_item,name=" + item.name_str + _WW_ON_USE( item ) ); @@ -538,9 +485,11 @@ void windwalker_live( player_t *p ) "spinning_crane_kick,target_if=max:target.time_to_die,if=combo_strike&buff.chi_energy.stack>29&cooldown.fists_of_" "fury.remains<5" ); default_aoe->add_action( - "whirling_dragon_punch,target_if=max:target.time_to_die,if=buff.heart_of_the_jade_serpent_cdr.up&buff.dance_of_chiji.stack<2" ); + "whirling_dragon_punch,target_if=max:target.time_to_die,if=buff.heart_of_the_jade_serpent_cdr.up&buff.dance_of_" + "chiji.stack<2" ); default_aoe->add_action( "whirling_dragon_punch,target_if=max:target.time_to_die,if=buff.dance_of_chiji.stack<2" ); - default_aoe->add_action( "slicing_winds,if=buff.heart_of_the_jade_serpent_cdr.up|buff.heart_of_the_jade_serpent_cdr_celestial.up" ); + default_aoe->add_action( + "slicing_winds,if=buff.heart_of_the_jade_serpent_cdr.up|buff.heart_of_the_jade_serpent_cdr_celestial.up" ); default_aoe->add_action( "celestial_conduit,if=buff.storm_earth_and_fire.up&cooldown.strike_of_the_" "windlord.remains&(!buff.heart_of_the_jade_serpent_cdr.up|debuff.gale_force.remains<5)&(talent.xuens_bond|!" @@ -556,7 +505,8 @@ void windwalker_live( player_t *p ) "blackout_kick,if=combo_strike&buff.bok_proc.up&chi<2&talent." "energy_burst&energy<55" ); default_aoe->add_action( - "strike_of_the_windlord,target_if=max:target.time_to_die,if=(time>5|buff.invokers_delight.up&buff.storm_earth_and_fire.up)&(cooldown.invoke_xuen_the_white_tiger.remains>" + "strike_of_the_windlord,target_if=max:target.time_to_die,if=(time>5|buff.invokers_delight.up&buff.storm_earth_" + "and_fire.up)&(cooldown.invoke_xuen_the_white_tiger.remains>" "15|talent.flurry_strikes)" ); default_aoe->add_action( "slicing_winds" ); default_aoe->add_action( @@ -649,9 +599,11 @@ void windwalker_live( player_t *p ) default_cleave->add_action( "touch_of_death,if=!buff.heart_of_the_jade_serpent_cdr.up&!buff.heart_of_the_jade_serpent_cdr_celestial.up" ); default_cleave->add_action( - "whirling_dragon_punch,target_if=max:target.time_to_die,if=buff.heart_of_the_jade_serpent_cdr.up&buff.dance_of_chiji.stack<2" ); + "whirling_dragon_punch,target_if=max:target.time_to_die,if=buff.heart_of_the_jade_serpent_cdr.up&buff.dance_of_" + "chiji.stack<2" ); default_cleave->add_action( "whirling_dragon_punch,target_if=max:target.time_to_die,if=buff.dance_of_chiji.stack<2" ); - default_cleave->add_action( "slicing_winds,if=buff.heart_of_the_jade_serpent_cdr.up|buff.heart_of_the_jade_serpent_cdr_celestial.up" ); + default_cleave->add_action( + "slicing_winds,if=buff.heart_of_the_jade_serpent_cdr.up|buff.heart_of_the_jade_serpent_cdr_celestial.up" ); default_cleave->add_action( "celestial_conduit,if=buff.storm_earth_and_fire.up&cooldown.strike_of_the_" "windlord.remains&(!buff.heart_of_the_jade_serpent_cdr.up|debuff.gale_force.remains<5)&(talent.xuens_bond|!" @@ -759,9 +711,13 @@ void windwalker_live( player_t *p ) "fists_of_fury,if=buff.heart_of_the_jade_serpent_cdr_celestial.up|buff.heart_of_the_jade_serpent_cdr.up", "1 target" ); default_st->add_action( - "rising_sun_kick,if=buff.pressure_point.up&!buff.heart_of_the_jade_serpent_cdr.up&buff.heart_of_the_jade_serpent_cdr_celestial.up|buff.invokers_delight.up|buff.bloodlust.up|buff.pressure_point.up&cooldown.fists_of_fury.remains|buff.power_infusion.up" ); - default_st->add_action( "whirling_dragon_punch,if=!buff.heart_of_the_jade_serpent_cdr_celestial.up&!buff.dance_of_chiji.stack=2" ); - default_st->add_action( "slicing_winds,if=buff.heart_of_the_jade_serpent_cdr.up|buff.heart_of_the_jade_serpent_cdr_celestial.up" ); + "rising_sun_kick,if=buff.pressure_point.up&!buff.heart_of_the_jade_serpent_cdr.up&buff.heart_of_the_jade_serpent_" + "cdr_celestial.up|buff.invokers_delight.up|buff.bloodlust.up|buff.pressure_point.up&cooldown.fists_of_fury." + "remains|buff.power_infusion.up" ); + default_st->add_action( + "whirling_dragon_punch,if=!buff.heart_of_the_jade_serpent_cdr_celestial.up&!buff.dance_of_chiji.stack=2" ); + default_st->add_action( + "slicing_winds,if=buff.heart_of_the_jade_serpent_cdr.up|buff.heart_of_the_jade_serpent_cdr_celestial.up" ); default_st->add_action( "celestial_conduit,if=buff.storm_earth_and_fire.up&(!buff.heart_of_the_jade_serpent_cdr.up|debuff.gale_force." "remains<5)&cooldown.strike_of_the_windlord.remains&(talent.xuens_bond|!talent.xuens_bond&buff.invokers_delight." @@ -803,7 +759,10 @@ void windwalker_live( player_t *p ) default_st->add_action( "crackling_jade_lightning,if=buff.the_emperors_capacitor.stack>19&!buff.heart_of_the_jade_serpent_cdr.up&!buff." "heart_of_the_jade_serpent_cdr_celestial.up&combo_strike&(!fight_style.dungeonslice|target.time_to_die>20)&" - "cooldown.invoke_xuen_the_white_tiger.remains>10|buff.the_emperors_capacitor.stack>15&!buff.heart_of_the_jade_serpent_cdr.up&!buff.heart_of_the_jade_serpent_cdr_celestial.up&combo_strike&(!fight_style.dungeonslice|target.time_to_die>20)&cooldown.invoke_xuen_the_white_tiger.remains<10&cooldown.invoke_xuen_the_white_tiger.remains>2" ); + "cooldown.invoke_xuen_the_white_tiger.remains>10|buff.the_emperors_capacitor.stack>15&!buff.heart_of_the_jade_" + "serpent_cdr.up&!buff.heart_of_the_jade_serpent_cdr_celestial.up&combo_strike&(!fight_style.dungeonslice|target." + "time_to_die>20)&cooldown.invoke_xuen_the_white_tiger.remains<10&cooldown.invoke_xuen_the_white_tiger.remains>" + "2" ); default_st->add_action( "slicing_winds,if=target.time_to_die>10" ); default_st->add_action( "fists_of_fury,if=(talent.xuens_battlegear|!talent.xuens_battlegear&(cooldown.strike_of_the_windlord.remains>1|" @@ -873,34 +832,148 @@ void windwalker_live( player_t *p ) fallback->add_action( "tiger_palm,if=combo_strike&chi>5" ); } -void windwalker_ptr( player_t *p ) +void ptr_apl( monk_t* player ) { - // no ptr apl exists at this time - windwalker_live( p ); + live_apl( player ); } -void windwalker( player_t *p ) +void default_apl( monk_t* player ) { - if ( p->is_ptr() ) - windwalker_ptr( p ); + if ( !player->is_ptr() ) + live_apl( player ); else - windwalker_live( p ); + ptr_apl( player ); } +}; // namespace windwalker +}; // namespace -void no_spec( player_t *p ) +namespace monk { - action_priority_list_t *pre = p->get_action_priority_list( "precombat" ); - action_priority_list_t *def = p->get_action_priority_list( "default" ); +std::string monk_t::default_potion() const +{ + switch ( specialization() ) + { + case MONK_BREWMASTER: + return brewmaster::default_potion( this ); + case MONK_MISTWEAVER: + return mistweaver::default_potion( this ); + case MONK_WINDWALKER: + return windwalker::default_potion( this ); + default: + return "disabled"; + } +} - pre->add_action( "flask" ); - pre->add_action( "food" ); - pre->add_action( "augmentation" ); - pre->add_action( "snapshot_stats", "Snapshot raid buffed stats before combat begins and pre-potting is done." ); - pre->add_action( "potion" ); +std::string monk_t::default_flask() const +{ + switch ( specialization() ) + { + case MONK_BREWMASTER: + return brewmaster::default_flask( this ); + case MONK_MISTWEAVER: + return mistweaver::default_flask( this ); + case MONK_WINDWALKER: + return windwalker::default_flask( this ); + default: + return "disabled"; + } +} - def->add_action( "roll,if=movement.distance>5", "Move to target" ); - def->add_action( "chi_torpedo,if=movement.distance>5" ); - def->add_action( "Tiger Palm" ); +std::string monk_t::default_food() const +{ + switch ( specialization() ) + { + case MONK_BREWMASTER: + return brewmaster::default_food( this ); + case MONK_MISTWEAVER: + return mistweaver::default_food( this ); + case MONK_WINDWALKER: + return windwalker::default_food( this ); + default: + return "disabled"; + } } -} // namespace monk_apl +std::string monk_t::default_rune() const +{ + switch ( specialization() ) + { + case MONK_BREWMASTER: + return brewmaster::default_rune( this ); + case MONK_MISTWEAVER: + return mistweaver::default_rune( this ); + case MONK_WINDWALKER: + return windwalker::default_rune( this ); + default: + return "disabled"; + } +} + +std::string monk_t::default_temporary_enchant() const +{ + switch ( specialization() ) + { + case MONK_BREWMASTER: + return brewmaster::default_temporary_enchant( this ); + case MONK_MISTWEAVER: + return mistweaver::default_temporary_enchant( this ); + case MONK_WINDWALKER: + return windwalker::default_temporary_enchant( this ); + default: + return "disabled"; + } +} + +void monk_t::init_action_list() +{ + if ( specialization() == MONK_MISTWEAVER && !sim->allow_experimental_specializations ) + { + if ( !quiet ) + sim->error( "Mistweaver Monk for {} is not currently supported.", *this ); + quiet = true; + return; + } + + if ( main_hand_weapon.type == WEAPON_NONE ) + { + if ( !quiet ) + sim->error( "{} has no weapon equipped at the Main-Hand slot.", *this ); + quiet = true; + return; + } + + if ( main_hand_weapon.group() == WEAPON_2H && off_hand_weapon.group() == WEAPON_1H ) + { + if ( !quiet ) + sim->error( "{} both a 1-hand and 2-hand weapon equipped at once.", *this ); + quiet = true; + return; + } + + if ( action_list_str.empty() ) + { + clear_action_priority_lists(); + + switch ( specialization() ) + { + case MONK_BREWMASTER: + brewmaster::default_apl( this ); + break; + case MONK_MISTWEAVER: + mistweaver::default_apl( this ); + break; + case MONK_WINDWALKER: + windwalker::default_apl( this ); + break; + default: + sim->error( "No default apl can be provided as no specialization was selected for {}.", *this ); + quiet = true; + return; + } + + use_default_action_list = true; + } + + base_t::init_action_list(); +} +}; // namespace monk diff --git a/engine/class_modules/apl/apl_monk.hpp b/engine/class_modules/apl/apl_monk.hpp deleted file mode 100644 index f03af32400b..00000000000 --- a/engine/class_modules/apl/apl_monk.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -struct player_t; - -namespace monk_apl -{ -std::string potion( const player_t* ); -std::string flask( const player_t* ); -std::string food( const player_t* ); -std::string rune( const player_t* ); -std::string temporary_enchant( const player_t* ); -void brewmaster( player_t* ); -void mistweaver( player_t* ); -void windwalker( player_t* ); -void no_spec( player_t* ); - -} // namespace monk_apl diff --git a/engine/class_modules/monk/sc_monk.cpp b/engine/class_modules/monk/sc_monk.cpp index f4035e728c3..1dfbc150186 100644 --- a/engine/class_modules/monk/sc_monk.cpp +++ b/engine/class_modules/monk/sc_monk.cpp @@ -31,7 +31,6 @@ #include "action/action_callback.hpp" #include "action/parse_effects.hpp" -#include "class_modules/apl/apl_monk.hpp" #include "player/pet.hpp" #include "player/pet_spawner.hpp" #include "report/charts.hpp" @@ -9013,95 +9012,6 @@ void monk_t::assess_heal( school_e school, result_amount_type dmg_type, action_s trigger_celestial_fortune( s ); } -// ========================================================================= -// Monk APL -// ========================================================================= - -// monk_t::default_flask =================================================== -std::string monk_t::default_flask() const -{ - return monk_apl::flask( this ); -} - -// monk_t::default_potion ================================================== -std::string monk_t::default_potion() const -{ - return monk_apl::potion( this ); -} - -// monk_t::default_food ==================================================== -std::string monk_t::default_food() const -{ - return monk_apl::food( this ); -} - -// monk_t::default_rune ==================================================== -std::string monk_t::default_rune() const -{ - return monk_apl::rune( this ); -} - -// monk_t::temporary_enchant =============================================== -std::string monk_t::default_temporary_enchant() const -{ - return monk_apl::temporary_enchant( this ); -} - -// monk_t::init_action_list ===================================================== -void monk_t::init_action_list() -{ - // Mistweaver isn't supported atm - if ( !sim->allow_experimental_specializations && specialization() == MONK_MISTWEAVER && role != ROLE_ATTACK ) - { - if ( !quiet ) - sim->error( "Monk mistweaver healing for {} is not currently supported.", *this ); - - quiet = true; - return; - } - if ( main_hand_weapon.type == WEAPON_NONE ) - { - if ( !quiet ) - sim->error( "{} has no weapon equipped at the Main-Hand slot.", *this ); - quiet = true; - return; - } - if ( main_hand_weapon.group() == WEAPON_2H && off_hand_weapon.group() == WEAPON_1H ) - { - if ( !quiet ) - sim->error( "{} has a 1-Hand weapon equipped in the Off-Hand while a 2-Hand weapon is equipped in the Main-Hand.", - *this ); - quiet = true; - return; - } - if ( !action_list_str.empty() ) - { - base_t::init_action_list(); - return; - } - clear_action_priority_lists(); - - // Combat - switch ( specialization() ) - { - case MONK_BREWMASTER: - monk_apl::brewmaster( this ); - break; - case MONK_WINDWALKER: - monk_apl::windwalker( this ); - break; - case MONK_MISTWEAVER: - monk_apl::mistweaver( this ); - break; - default: - monk_apl::no_spec( this ); - break; - } - use_default_action_list = true; - - base_t::init_action_list(); -} - // monk_t::create_actions ======================================================= void monk_t::create_actions() { diff --git a/engine/class_modules/monk/sc_monk.hpp b/engine/class_modules/monk/sc_monk.hpp index 2a1e3c264db..c5970b3cacd 100644 --- a/engine/class_modules/monk/sc_monk.hpp +++ b/engine/class_modules/monk/sc_monk.hpp @@ -1392,46 +1392,55 @@ struct monk_t : public stagger_t public: monk_t( sim_t *sim, util::string_view name, race_e r ); + // APL std::string default_potion() const override; std::string default_flask() const override; std::string default_food() const override; std::string default_rune() const override; std::string default_temporary_enchant() const override; - action_t *create_action( util::string_view name, util::string_view options ) override; - double composite_attack_power_multiplier() const override; - double composite_dodge() const override; - double non_stacking_movement_modifier() const override; - double composite_player_target_armor( player_t *target ) const override; - double resource_regen_per_second( resource_e ) const override; + void init_action_list() override; + + // Init / Reset void create_pets() override; void init_spells() override; void init_background_actions() override; void init_base_stats() override; void init_scaling() override; - void create_buffs() override; - void create_actions() override; void init_gains() override; void init_procs() override; void init_assessors() override; void init_special_effects() override; void init_special_effect( special_effect_t &effect ) override; void init_finished() override; - void reset() override; + void create_buffs() override; + action_t *create_action( util::string_view name, util::string_view options ) override; + void create_actions() override; void create_options() override; + std::unique_ptr create_expression( util::string_view name_str ) override; + void reset() override; void copy_from( player_t * ) override; - resource_e primary_resource() const override; - role_e primary_role() const override; - stat_e convert_hybrid_stat( stat_e s ) const override; + void collect_resource_timeline_information() override; + + // Combat + void activate() override; void combat_begin() override; void target_mitigation( school_e, result_amount_type, action_state_t * ) override; void assess_damage( school_e, result_amount_type, action_state_t *s ) override; void assess_heal( school_e, result_amount_type, action_state_t *s ) override; void invalidate_cache( cache_e ) override; - void init_action_list() override; - void activate() override; - void collect_resource_timeline_information() override; + + // Stats + role_e primary_role() const override; + resource_e primary_resource() const override; bool validate_fight_style( fight_style_e style ) const override; - std::unique_ptr create_expression( util::string_view name_str ) override; + stat_e convert_hybrid_stat( stat_e s ) const override; + double composite_attack_power_multiplier() const override; + double composite_dodge() const override; + double non_stacking_movement_modifier() const override; + double composite_player_target_armor( player_t *target ) const override; + double resource_regen_per_second( resource_e ) const override; + + // Other const monk_td_t *find_target_data( const player_t *target ) const override { return target_data[ target ]; @@ -1445,8 +1454,6 @@ struct monk_t : public stagger_t } return td; } - - // Custom Monk Functions void parse_player_effects(); void create_proc_callback( const spell_data_t *effect_driver, bool ( *trigger )( monk_t *player, action_state_t *state ), proc_flag PF_OVERRIDE, @@ -1460,11 +1467,13 @@ struct monk_t : public stagger_t void create_proc_callback( const spell_data_t *effect_driver, bool ( *trigger )( monk_t *player, action_state_t *state ), proc_flag2 PF2_OVERRIDE, action_t *proc_action_override = nullptr ); + + // Actions void trigger_celestial_fortune( action_state_t * ); void trigger_empowered_tiger_lightning( action_state_t * ); - bool affected_by_sef( spell_data_t data ) const; // Custom handler for SEF bugs // Storm Earth and Fire targeting logic + bool affected_by_sef( spell_data_t data ) const; // Custom handler for SEF bugs std::vector create_storm_earth_and_fire_target_list() const; void summon_storm_earth_and_fire( timespan_t duration ); void retarget_storm_earth_and_fire( pet_t *pet, std::vector &targets ) const; diff --git a/source_files/QT_engine.pri b/source_files/QT_engine.pri index eaf4253b1c6..867055bbd9b 100644 --- a/source_files/QT_engine.pri +++ b/source_files/QT_engine.pri @@ -21,7 +21,6 @@ HEADERS += engine/class_modules/apl/apl_death_knight.hpp HEADERS += engine/class_modules/apl/apl_demon_hunter.hpp HEADERS += engine/class_modules/apl/apl_evoker.hpp HEADERS += engine/class_modules/apl/apl_hunter.hpp -HEADERS += engine/class_modules/apl/apl_monk.hpp HEADERS += engine/class_modules/apl/apl_paladin.hpp HEADERS += engine/class_modules/apl/apl_priest.hpp HEADERS += engine/class_modules/apl/apl_rogue.hpp diff --git a/source_files/VS_engine.props b/source_files/VS_engine.props index 1d2269c8d86..54d3434e1ea 100644 --- a/source_files/VS_engine.props +++ b/source_files/VS_engine.props @@ -25,7 +25,6 @@ To change the list of source files run synchronize.py - diff --git a/source_files/cmake_engine.txt b/source_files/cmake_engine.txt index 3d922a337e1..37cf1b34520 100644 --- a/source_files/cmake_engine.txt +++ b/source_files/cmake_engine.txt @@ -19,7 +19,6 @@ class_modules/apl/apl_death_knight.hpp class_modules/apl/apl_demon_hunter.hpp class_modules/apl/apl_evoker.hpp class_modules/apl/apl_hunter.hpp -class_modules/apl/apl_monk.hpp class_modules/apl/apl_paladin.hpp class_modules/apl/apl_priest.hpp class_modules/apl/apl_rogue.hpp From 380bd192936c54b14acea09f428a3a704e3fbf89 Mon Sep 17 00:00:00 2001 From: Kate Martin <51387586+renanthera@users.noreply.github.com> Date: Thu, 29 May 2025 20:10:33 -0600 Subject: [PATCH 2/3] [monk] Refactor pre-apl actor validation. Implement Assited Combat overrides. --- engine/class_modules/apl/apl_monk.cpp | 130 ++++++++++++++++++++------ engine/class_modules/monk/sc_monk.hpp | 6 +- 2 files changed, 109 insertions(+), 27 deletions(-) diff --git a/engine/class_modules/apl/apl_monk.cpp b/engine/class_modules/apl/apl_monk.cpp index 30e1a3291aa..8e405571fa4 100644 --- a/engine/class_modules/apl/apl_monk.cpp +++ b/engine/class_modules/apl/apl_monk.cpp @@ -7,6 +7,7 @@ struct player_t; using monk::monk_t; +// Per Specialization Defaults namespace { namespace brewmaster @@ -847,6 +848,106 @@ void default_apl( monk_t* player ) }; // namespace windwalker }; // namespace +// Shared Defaults +namespace monk +{ +void monk_t::validate_actor() +{ + if ( specialization() == MONK_MISTWEAVER && !sim->allow_experimental_specializations ) + { + if ( !quiet ) + sim->error( "Mistweaver Monk for {} is not currently supported.", *this ); + quiet = true; + return; + } + + if ( main_hand_weapon.type == WEAPON_NONE ) + { + if ( !quiet ) + sim->error( "{} has no weapon equipped at the Main-Hand slot.", *this ); + quiet = true; + return; + } + + if ( main_hand_weapon.group() == WEAPON_2H && off_hand_weapon.group() == WEAPON_1H ) + { + if ( !quiet ) + sim->error( "{} both a 1-hand and 2-hand weapon equipped at once.", *this ); + quiet = true; + return; + } + + switch ( specialization() ) + { + case MONK_BREWMASTER: + case MONK_MISTWEAVER: + case MONK_WINDWALKER: + return; + default: + sim->error( "No specialization was selected for {}.", *this ); + quiet = true; + return; + } +} + +void monk_t::init_blizzard_action_list() +{ + validate_actor(); + + action_priority_list_t* default_ = get_action_priority_list( "default" ); + + switch ( specialization() ) + { + case MONK_BREWMASTER: + case MONK_MISTWEAVER: + case MONK_WINDWALKER: + default_->add_action( "auto_attack", "Overridden" ); + break; + default: + assert( false ); + break; + } + + base_t::init_blizzard_action_list(); + + action_priority_list_t* cooldowns = get_action_priority_list( "cooldowns" ); + + switch ( specialization() ) + { + case MONK_BREWMASTER: + cooldowns->add_action( "weapons_of_order" ); + cooldowns->add_action( "invoke_niuzao_the_black_ox" ); + break; + case MONK_MISTWEAVER: + break; + case MONK_WINDWALKER: + cooldowns->add_action( "invoke_xuen_the_white_tiger" ); + cooldowns->add_action( "celestial_conduit,if=cooldown.strike_of_the_windlord.remains" ); + break; + default: + assert( false ); + break; + } +} + +std::string monk_t::parse_assisted_combat_rule( const assisted_combat_rule_data_t& rule, + const assisted_combat_step_data_t& step ) const +{ + if ( step.spell_id == 152175 && rule.condition_type == TARGET_DISTANCE_LESS ) + { + assisted_combat_rule_data_t rule_copy = rule; + rule_copy.condition_value_1 = 10; + + return base_t::parse_assisted_combat_rule( rule_copy, step ); + } + + if ( step.spell_id == 205523 && rule.condition_type == AURA_ON_PLAYER ) + return ""; + + return base_t::parse_assisted_combat_rule( rule, step ); +} +}; // namespace monk + namespace monk { std::string monk_t::default_potion() const @@ -926,29 +1027,7 @@ std::string monk_t::default_temporary_enchant() const void monk_t::init_action_list() { - if ( specialization() == MONK_MISTWEAVER && !sim->allow_experimental_specializations ) - { - if ( !quiet ) - sim->error( "Mistweaver Monk for {} is not currently supported.", *this ); - quiet = true; - return; - } - - if ( main_hand_weapon.type == WEAPON_NONE ) - { - if ( !quiet ) - sim->error( "{} has no weapon equipped at the Main-Hand slot.", *this ); - quiet = true; - return; - } - - if ( main_hand_weapon.group() == WEAPON_2H && off_hand_weapon.group() == WEAPON_1H ) - { - if ( !quiet ) - sim->error( "{} both a 1-hand and 2-hand weapon equipped at once.", *this ); - quiet = true; - return; - } + validate_actor(); if ( action_list_str.empty() ) { @@ -966,9 +1045,8 @@ void monk_t::init_action_list() windwalker::default_apl( this ); break; default: - sim->error( "No default apl can be provided as no specialization was selected for {}.", *this ); - quiet = true; - return; + assert( false ); + break; } use_default_action_list = true; diff --git a/engine/class_modules/monk/sc_monk.hpp b/engine/class_modules/monk/sc_monk.hpp index c5970b3cacd..d4f3eabfeb8 100644 --- a/engine/class_modules/monk/sc_monk.hpp +++ b/engine/class_modules/monk/sc_monk.hpp @@ -1399,6 +1399,11 @@ struct monk_t : public stagger_t std::string default_rune() const override; std::string default_temporary_enchant() const override; void init_action_list() override; + void init_blizzard_action_list() override; + void validate_actor(); + bool validate_fight_style( fight_style_e style ) const override; + std::string parse_assisted_combat_rule( const assisted_combat_rule_data_t &rule, + const assisted_combat_step_data_t &step ) const override; // Init / Reset void create_pets() override; @@ -1432,7 +1437,6 @@ struct monk_t : public stagger_t // Stats role_e primary_role() const override; resource_e primary_resource() const override; - bool validate_fight_style( fight_style_e style ) const override; stat_e convert_hybrid_stat( stat_e s ) const override; double composite_attack_power_multiplier() const override; double composite_dodge() const override; From b5aef25ce8c15d522a786537fd2453d0d4ecc4cd Mon Sep 17 00:00:00 2001 From: Kate Martin <51387586+renanthera@users.noreply.github.com> Date: Thu, 29 May 2025 20:14:38 -0600 Subject: [PATCH 3/3] [monk] Clean up. --- engine/class_modules/apl/apl_monk.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/class_modules/apl/apl_monk.cpp b/engine/class_modules/apl/apl_monk.cpp index 8e405571fa4..67005ee651a 100644 --- a/engine/class_modules/apl/apl_monk.cpp +++ b/engine/class_modules/apl/apl_monk.cpp @@ -4,7 +4,6 @@ #include -struct player_t; using monk::monk_t; // Per Specialization Defaults