Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 102 additions & 19 deletions engine/class_modules/monk/sc_monk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Manatee
#include "report/charts.hpp"
#include "report/highchart.hpp"
#include "sc_enums.hpp"
#include "sim/profileset_control.hpp"

#include <deque>

Expand Down Expand Up @@ -2223,7 +2224,7 @@ struct auto_attack_t : public monk_melee_attack_t
action_t *damage;

template <typename... Args>
thunderfist_t( monk_t *player, Args &&...args ) : TBase( player, std::forward<Args>( args )... )
thunderfist_t( monk_t *player, Args &&...args ) : TBase( player, std::forward<Args>( args )... ), damage( nullptr )
{
if ( !player->talent.windwalker.thunderfist->ok() )
return;
Expand Down Expand Up @@ -5509,26 +5510,29 @@ bool monk_t::validate_actor()
return false;
}

int expected = 13;
for ( const auto &hero_tree : player_sub_trees )
if ( !sim->parent && !sim->profileset_enabled )
{
int count = as<int>( range::count_if(
player_traits, [ is_ptr = is_ptr(), hero_tree ]( std::tuple<talent_tree, unsigned, unsigned> entry ) {
if ( std::get<talent_tree>( entry ) != talent_tree::HERO )
return false;
const trait_data_t *trait = trait_data_t::find( std::get<1>( entry ), is_ptr );
if ( !trait )
return false;
return static_cast<hero_tree_e>( trait->id_sub_tree ) == hero_tree;
} ) );

// Report without counting the hidden talent that activates the subtree
count -= 1;
if ( count < expected )
int expected = 13;
for ( const auto &hero_tree : player_sub_trees )
{
sim->error( SEVERE, "Invalid Hero Talent tree, possibly low level. Found {} talents, expected {}.", count,
expected );
return false;
int count = as<int>( range::count_if(
player_traits, [ is_ptr = is_ptr(), hero_tree ]( std::tuple<talent_tree, unsigned, unsigned> entry ) {
if ( std::get<talent_tree>( entry ) != talent_tree::HERO )
return false;
const trait_data_t *trait = trait_data_t::find( std::get<1>( entry ), is_ptr );
if ( !trait )
return false;
return static_cast<hero_tree_e>( trait->id_sub_tree ) == hero_tree;
} ) );

// Report without counting the hidden talent that activates the subtree
count -= 1;
if ( count < expected && count != 0 )
{
sim->error( SEVERE, "Invalid Hero Talent tree, possibly low level. Found {} talents, expected {}.", count,
expected );
return false;
}
}
}

Expand Down Expand Up @@ -7018,6 +7022,11 @@ void monk_t::init_finished()
{
base_t::init_finished();
parse_player_effects();

profileset_controller_t::register_controller(
"valid_talents", profileset_controller::create_fn_pair<profileset_control::valid_talents_t>() );
std::vector<std::string> rhs = { fmt::format( "player={},count=13", name() ) };
sim->profileset_controller_options.emplace( "valid_talents", rhs );
}

void monk_t::reset()
Expand Down Expand Up @@ -7345,6 +7354,80 @@ void monk_t::create_actions()
buff.aspect_of_harmony.construct_actions( this );
}

namespace profileset_control
{
valid_talents_t::valid_talents_t( sim_t *sim, unsigned int id ) : profileset_controller_t( sim, id )
{
}

const std::string valid_talents_t::name() const
{
return "valid_talents";
}

std::function<bool( std::tuple<talent_tree, unsigned, unsigned> )> matching_talent( player_t *player,
unsigned hero_tree )
{
return [ = ]( std::tuple<talent_tree, unsigned, unsigned> entry ) {
if ( std::get<talent_tree>( entry ) != talent_tree::HERO )
return false;
const trait_data_t *trait = trait_data_t::find( std::get<1>( entry ), player->is_ptr() );
if ( !trait )
return false;
return static_cast<hero_tree_e>( trait->id_sub_tree ) == hero_tree;
};
}

std::function<unsigned( unsigned )> has_expected_count( player_t *player, unsigned expected_count )
{
return [ = ]( unsigned hero_tree ) {
unsigned count = range::count_if( player->player_traits, matching_talent( player, hero_tree ) );
return count > expected_count;
};
}

bool valid_talents_t::evaluate_post_init()
{
if ( !player || sim->enable_all_talents )
return true;

switch ( player->specialization() )
{
case MONK_BREWMASTER:
case MONK_WINDWALKER:
return range::all_of( player->player_sub_trees, has_expected_count( player, count ) );
default:
break;
}

return true;
}

const std::string valid_talents_t::reason() const
{
return fmt::format( "player {} does not have {} talents selected in hero tree", player->name(), count );
}

void valid_talents_t::create_options()
{
add_option( opt_func( "count", [ this ]( sim_t *, util::string_view, util::string_view value ) {
this->count = util::to_unsigned( value );
return true;
} ) );
add_option( opt_func( "player", [ this ]( sim_t *sim, util::string_view, util::string_view value ) {
for ( auto &player : sim->player_list )
{
if ( util::str_compare_ci( player->name(), value ) )
{
this->player = player;
return true;
}
}
return false;
} ) );
}
} // namespace profileset_control

std::unique_ptr<expr_t> monk_t::create_expression( std::string_view name_str )
{
auto splits = util::string_split<std::string_view>( name_str, "." );
Expand Down
19 changes: 19 additions & 0 deletions engine/class_modules/monk/sc_monk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "sc_enums.hpp"
#include "sc_stagger.hpp"
#include "sim/proc.hpp"
#include "sim/profileset_control.hpp"
#include "util/timeline.hpp"

#include <array>
Expand Down Expand Up @@ -1216,6 +1217,24 @@ struct monk_t : public stagger_t<parse_player_effects_t, monk_t>
void trigger_celestial_fortune( action_state_t * );
};

namespace profileset_control
{
struct valid_talents_t : profileset_controller_t
{
using data_t = profileset_controller_data_t;

player_t *player;
unsigned int count;

valid_talents_t( sim_t *sim, unsigned int id );

const std::string name() const override;
bool evaluate_post_init() override;
const std::string reason() const override;
void create_options() override;
};
} // namespace profileset_control

namespace events
{
// based on implementation from sc_demon_hunter.cpp
Expand Down
4 changes: 2 additions & 2 deletions engine/sim/profileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ void worker_t::execute()
{
try
{
m_sim = new sim_t( m_parent, 0, m_profileset->options() );
m_sim = new sim_t( m_parent, 0, m_profileset->options(), m_profileset->name() );

simulate_profileset( m_parent, *m_profileset, m_sim );
}
Expand Down Expand Up @@ -501,7 +501,7 @@ void profilesets_t::generate_work( sim_t* parent, std::unique_ptr<profile_set_t>

try
{
sim_t* profile_sim = new sim_t( parent );
sim_t* profile_sim = new sim_t( parent, 0, ptr_set->name() );

parent->control = original_opts;
simulate_profileset( parent, *ptr_set, profile_sim );
Expand Down
9 changes: 6 additions & 3 deletions engine/sim/profileset_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ void profileset_controller_data_wrapper_t::construct_controller( sim_t* sim )

bool profileset_controller_t::register_controller( std::string key, profileset_controller_t::factory_fn_pair_t&& value )
{
return factory.try_emplace( key, std::move( value ) ).second;
if ( factory.find( key ) != factory.end() )
return false;
factory.emplace( key, value );
return true;
}

bool profileset_controller_t::controller_exists( std::string key )
Expand Down Expand Up @@ -140,7 +143,7 @@ void profileset_controller_t::evaluate( sim_t* sim, call_point_e call_point )
assert( controller->parent == sim->parent );

controller->set_exit_reason(
{ sim->parent->profilesets->current_profileset_name(), call_point, controller->reason() } );
{ sim->profileset_name, call_point, controller->reason() } );

sim->canceled = true;
sim->error( error_level_e::TRIVIAL, "{}", controller->message( call_point ) );
Expand All @@ -161,7 +164,7 @@ profileset_controller_t::profileset_controller_t( sim_t* sim, unsigned int id )
const std::string profileset_controller_t::message( call_point_e call_point )
{
std::string msg = fmt::format( "Profileset {} was canceled by Profileset Controller {} after {}",
parent->profilesets->current_profileset_name(), name(),
sim->profileset_name, name(),
profileset_controller::call_point_string( call_point ) );
if ( call_point == POST_ITER )
msg += std::to_string( sim->current_iteration );
Expand Down
2 changes: 1 addition & 1 deletion engine/sim/profileset_control.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct data_wrapper_t

struct exit_reason_t
{
const std::string profileset_name;
const std::string_view profileset_name;
const call_point_e exit_point;
const std::string exit_reason;
};
Expand Down
15 changes: 11 additions & 4 deletions engine/sim/sim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1579,7 +1579,8 @@ sim_t::sim_t()
profileset_enabled( false ),
profileset_work_threads( 0 ),
profileset_init_threads( 1 ),
profilesets( std::make_unique<profileset::profilesets_t>() )
profilesets( std::make_unique<profileset::profilesets_t>() ),
profileset_name()
{
item_db_sources.assign( std::begin( default_item_db_sources ), std::end( default_item_db_sources ) );

Expand All @@ -1592,10 +1593,13 @@ sim_t::sim_t()
profileset::create_options( this );
}

sim_t::sim_t( sim_t* p, int index ) : sim_t()
sim_t::sim_t( sim_t* p, int index, std::string_view profileset_name )
: sim_t()
{
assert( p );

this->profileset_name = profileset_name;

parent = p;
thread_index = index;

Expand All @@ -1619,10 +1623,13 @@ sim_t::sim_t( sim_t* p, int index ) : sim_t()
parent -> add_relative( this );
}

sim_t::sim_t( sim_t* p, int index, sim_control_t* control ) : sim_t()
sim_t::sim_t( sim_t* p, int index, sim_control_t* control, std::string_view profileset_name )
: sim_t()
{
assert( p && control );

this->profileset_name = profileset_name;

parent = p;
thread_index = index;

Expand Down Expand Up @@ -3387,7 +3394,7 @@ void sim_t::partition()

for ( int i = 0; i < num_children; i++ )
{
auto child = new sim_t( this, i + 1, child_control );
auto child = new sim_t( this, i + 1, child_control, child_control->combat.name );

assert( child );
children.push_back( child );
Expand Down
5 changes: 3 additions & 2 deletions engine/sim/sim.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,10 +651,11 @@ struct sim_t : private sc_thread_t
bool profileset_enabled;
int profileset_work_threads, profileset_init_threads;
std::unique_ptr<profileset::profilesets_t> profilesets;
std::string_view profileset_name;

sim_t();
explicit sim_t( sim_t* parent, int thread_index = 0 );
sim_t( sim_t* parent, int thread_index, sim_control_t* control );
explicit sim_t( sim_t* parent, int thread_index = 0, std::string_view profileset_name = {} );
sim_t( sim_t* parent, int thread_index, sim_control_t* control, std::string_view profileset_name = {} );
~sim_t() override;

void run() override;
Expand Down
Loading