Skip to content

Commit

Permalink
Cache mutation trait flags
Browse files Browse the repository at this point in the history
The cache is very conservative, and is reset for any change to the
player's mutations.
  • Loading branch information
CLIDragon committed Nov 8, 2024
1 parent 60cf27e commit 65214bd
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,12 @@ class Character : public Creature, public visitable
bool has_flag( const json_character_flag &flag ) const;
/** Returns the count of traits, bionics, effects, bodyparts, and martial arts buffs with a flag */
int count_flag( const json_character_flag &flag ) const;

private:
// Cache if character has a flag on their mutations. It is cleared whenever my_mutations is modified.
mutable std::map<const json_character_flag, bool> trait_flag_cache;

public:
/** Returns the trait id with the given invlet, or an empty string if no trait has that invlet */
trait_id trait_by_invlet( int ch ) const;
/** Returns the vector of all traits in category, good/bad/any */
Expand Down
21 changes: 19 additions & 2 deletions src/mutation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,27 @@ bool Character::has_trait_variant( const trait_and_var &test ) const

bool Character::has_trait_flag( const json_character_flag &b ) const
{
// UGLY, SLOW, should be cached as my_mutation_flags or something
auto iter = trait_flag_cache.find( b );
if( iter != trait_flag_cache.end() ) {
return iter->second;
}

for( const trait_id &mut : get_mutations() ) {
const mutation_branch &mut_data = mut.obj();
if( mut_data.flags.count( b ) > 0 ) {
trait_flag_cache[b] = true;
return true;
} else if( mut_data.activated ) {
Character &player = get_player_character();
if( ( mut_data.active_flags.count( b ) > 0 && player.has_active_mutation( mut ) ) ||
( mut_data.inactive_flags.count( b ) > 0 && !player.has_active_mutation( mut ) ) ) {
trait_flag_cache[b] = true;
return true;
}
}
}

trait_flag_cache[b] = false;
return false;
}

Expand Down Expand Up @@ -302,6 +309,8 @@ void Character::set_mutation_unsafe( const trait_id &trait, const mutation_varia
if( !trait.obj().vanity ) {
mutation_effect( trait, false );
}

trait_flag_cache.clear();
}

void Character::do_mutation_updates()
Expand Down Expand Up @@ -334,6 +343,7 @@ void Character::set_mut_variant( const trait_id &trait, const mutation_variant *
auto mutit = my_mutations.find( trait );
if( mutit != my_mutations.end() ) {
mutit->second.variant = variant;
trait_flag_cache.clear();
}
}

Expand All @@ -357,6 +367,7 @@ void Character::unset_mutation( const trait_id &trait_ )
if( !mut.vanity ) {
mutation_loss_effect( trait );
}
trait_flag_cache.clear();
do_mutation_updates();
}

Expand All @@ -373,6 +384,7 @@ void Character::switch_mutations( const trait_id &switched, const trait_id &targ
if( has_trait( target ) ) {
my_mutations[target].powered = start_powered;
}
trait_flag_cache.clear();
}

bool Character::can_power_mutation( const trait_id &mut ) const
Expand Down Expand Up @@ -635,7 +647,7 @@ void Character::mutation_effect( const trait_id &mut, const bool worn_destroyed_
if( branch.starts_active ) {
my_mutations[mut].powered = true;
}

trait_flag_cache.clear();
on_mutation_gain( mut );
}

Expand Down Expand Up @@ -666,6 +678,7 @@ void Character::mutation_loss_effect( const trait_id &mut )
remove_moncam( moncam.first );
}

trait_flag_cache.clear();
on_mutation_loss( mut );
}

Expand Down Expand Up @@ -697,6 +710,7 @@ void Character::set_cost_timer( const trait_id &mut, time_duration set )
const auto all_iter = std::find( all_mut.begin(), all_mut.end(), mut );
if( iter != my_mutations.end() ) {
iter->second.charge = set;
trait_flag_cache.clear();
} else if( all_iter == all_mut.end() ) {
// don't have the mutation and don't have it from an item
debugmsg( "Tried to set cost timer of %s but doesn't have this mutation.", mut.c_str() );
Expand Down Expand Up @@ -808,6 +822,8 @@ void Character::activate_mutation( const trait_id &mut )
mutation_name( mut ) );
return;
}

trait_flag_cache.clear();
if( tdata.powered && tdata.charge > 0_turns ) {
// Already-on units just lose a bit of charge
tdata.charge -= 1_turns;
Expand Down Expand Up @@ -979,6 +995,7 @@ void Character::activate_mutation( const trait_id &mut )
void Character::deactivate_mutation( const trait_id &mut )
{
my_mutations[mut].powered = false;
trait_flag_cache.clear();

// Handle stat changes from deactivation
apply_mods( mut, false );
Expand Down
1 change: 1 addition & 0 deletions src/newcharacter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,7 @@ void Character::initialize( bool learn_recipes )
my_mutations[mut].powered = true;
}
}
trait_flag_cache.clear();

// Ensure that persistent morale effects (e.g. Optimist) are present at the start.
apply_persistent_morale();
Expand Down

0 comments on commit 65214bd

Please sign in to comment.