From afc1a1169a54c7225a75dec06becd65355bc7551 Mon Sep 17 00:00:00 2001 From: bombasticSlacks Date: Thu, 27 Jan 2022 23:42:08 -0400 Subject: [PATCH 1/2] fixed it all --- data/json/flags.json | 6 ++++++ src/character.cpp | 34 +++++++++++++++++++--------------- src/character.h | 10 +++++++++- src/character_body.cpp | 11 +++++++++++ src/flag.cpp | 1 + src/flag.h | 1 + src/item.cpp | 6 +++--- src/item.h | 2 +- src/mutation.cpp | 9 +++++++++ src/newcharacter.cpp | 25 ++++++++++++++----------- 10 files changed, 74 insertions(+), 31 deletions(-) diff --git a/data/json/flags.json b/data/json/flags.json index 860d502a22e48..60ef14c8a7bcf 100644 --- a/data/json/flags.json +++ b/data/json/flags.json @@ -1332,6 +1332,12 @@ "id": "MOUNTED_GUN", "type": "json_flag" }, + { + "id": "MUNDANE", + "//": "For items that have relic data but aren't actually magic", + "info": "This item is designed to have special effects", + "type": "json_flag" + }, { "id": "MYCUS_OK", "type": "json_flag" diff --git a/src/character.cpp b/src/character.cpp index e75ab4d246069..c7b6a3586de96 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -8676,14 +8676,10 @@ void Character::on_item_wear( const item &it ) { invalidate_inventory_validity_cache(); for( const trait_id &mut : it.mutations_from_wearing( *this ) ) { - mutation_effect( mut, true ); - recalc_sight_limits(); - calc_encumbrance(); - - // If the stamina is higher than the max (Languorous), set it back to max - if( get_stamina() > get_stamina_max() ) { - set_stamina( get_stamina_max() ); - } + // flag these mutations to be added at the start of the next turn + // without doing this you still count as wearing the item providing + // the traits so most the calcs don't work in mutation_loss_effect + mutations_to_add.push_back( mut ); } morale->on_item_wear( it ); } @@ -8691,17 +8687,25 @@ void Character::on_item_wear( const item &it ) void Character::on_item_takeoff( const item &it ) { invalidate_inventory_validity_cache(); - for( const trait_id &mut : it.mutations_from_wearing( *this ) ) { - mutation_loss_effect( mut ); - recalc_sight_limits(); - calc_encumbrance(); - if( get_stamina() > get_stamina_max() ) { - set_stamina( get_stamina_max() ); - } + for( const trait_id &mut : it.mutations_from_wearing( *this, true ) ) { + // flag these mutations to be removed at the start of the next turn + // without doing this you still count as wearing the item providing + // the traitssdd so most the calcs don't work in mutation_loss_effect + mutations_to_remove.push_back( mut ); + } morale->on_item_takeoff( it ); } +void Character::enchantment_wear_change() +{ + recalc_sight_limits(); + calc_encumbrance(); + if( get_stamina() > get_stamina_max() ) { + set_stamina( get_stamina_max() ); + } +} + void Character::on_item_acquire( const item &it ) { if( is_avatar() && it.has_item_with( []( const item & it ) { diff --git a/src/character.h b/src/character.h index 6e503029ad22f..79a0a86ec04d1 100644 --- a/src/character.h +++ b/src/character.h @@ -2246,7 +2246,8 @@ class Character : public Creature, public visitable /** Get the idents of all base traits. */ std::vector get_base_traits() const; /** Get the idents of all traits/mutations. */ - std::vector get_mutations( bool include_hidden = true ) const; + std::vector get_mutations( bool include_hidden = true, + bool ignore_enchantment = false ) const; const std::bitset &get_vision_modes() const { return vision_mode_cache; } @@ -2599,6 +2600,8 @@ class Character : public Creature, public visitable void on_item_wear( const item &it ); /** Called when an item is taken off */ void on_item_takeoff( const item &it ); + // things to call when mutations enchantments change + void enchantment_wear_change(); /** Called when an item is washed */ void on_worn_item_washed( const item &it ); /** Called when an item is acquired (picked up, worn, or wielded) */ @@ -3286,6 +3289,11 @@ class Character : public Creature, public visitable * Pointers to mutation branches in @ref my_mutations. */ std::vector cached_mutations; + + // if the player puts on and takes off items these mutations + // are added or removed at the beginning of the next + std::vector mutations_to_remove; + std::vector mutations_to_add; /** * The amount of weight the Character is carrying. * If it is nullopt, needs to be recalculated diff --git a/src/character_body.cpp b/src/character_body.cpp index f9efeeb63e512..a86dee59011c9 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -174,6 +174,17 @@ void Character::update_body( const time_point &from, const time_point &to ) } update_stomach( from, to ); recalculate_enchantment_cache(); + // after recalcing the enchantment cache can properly remove and add mutations + for( const trait_id &mut : mutations_to_remove ) { + mutation_loss_effect( mut ); + enchantment_wear_change(); + } + for( const trait_id &mut : mutations_to_add ) { + mutation_effect( mut, true ); + enchantment_wear_change(); + } + mutations_to_add.clear(); + mutations_to_remove.clear(); if( ticks_between( from, to, 3_minutes ) > 0 ) { magic->update_mana( *this, to_turns( 3_minutes ) ); } diff --git a/src/flag.cpp b/src/flag.cpp index 2637b2770335c..7366005ec93cb 100644 --- a/src/flag.cpp +++ b/src/flag.cpp @@ -167,6 +167,7 @@ const flag_id flag_MELTS( "MELTS" ); const flag_id flag_MESSY( "MESSY" ); const flag_id flag_MISSION_ITEM( "MISSION_ITEM" ); const flag_id flag_MOUNTED_GUN( "MOUNTED_GUN" ); +const flag_id flag_MUNDANE( "MUNDANE" ); const flag_id flag_MUSHY( "MUSHY" ); const flag_id flag_MUTE( "MUTE" ); const flag_id flag_MYCUS_OK( "MYCUS_OK" ); diff --git a/src/flag.h b/src/flag.h index e8297343fc80a..2bcb410712aad 100644 --- a/src/flag.h +++ b/src/flag.h @@ -177,6 +177,7 @@ extern const flag_id flag_MELTS; extern const flag_id flag_MESSY; extern const flag_id flag_MISSION_ITEM; extern const flag_id flag_MOUNTED_GUN; +extern const flag_id flag_MUNDANE; extern const flag_id flag_MUSHY; extern const flag_id flag_MYCUS_OK; extern const flag_id flag_NANOFAB_TEMPLATE; diff --git a/src/item.cpp b/src/item.cpp index e832927b1de6b..54bedc4e8ecde 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -5393,7 +5393,7 @@ nc_color item::color_in_inventory( const Character *const ch ) const ret = c_red; } else if( is_filthy() || has_own_flag( flag_DIRTY ) ) { ret = c_brown; - } else if( is_relic() ) { + } else if( is_relic() && !has_flag( flag_MUNDANE ) ) { ret = c_pink; } else if( is_bionic() ) { if( !player_character.has_bionic( type->bionic->id ) || type->bionic->id->dupes_allowed ) { @@ -11756,7 +11756,7 @@ void item::reset_temp_check() last_temp_check = calendar::turn; } -std::vector item::mutations_from_wearing( const Character &guy ) const +std::vector item::mutations_from_wearing( const Character &guy, bool removing ) const { if( !is_relic() ) { return std::vector {}; @@ -11770,7 +11770,7 @@ std::vector item::mutations_from_wearing( const Character &guy ) const } } - for( const trait_id &char_mut : guy.get_mutations() ) { + for( const trait_id &char_mut : guy.get_mutations( true, removing ) ) { for( auto iter = muts.begin(); iter != muts.end(); ) { if( char_mut == *iter ) { iter = muts.erase( iter ); diff --git a/src/item.h b/src/item.h index b43e0fe6db41e..367e6924a93ee 100644 --- a/src/item.h +++ b/src/item.h @@ -1613,7 +1613,7 @@ class item : public visitable bool use_relic( Character &guy, const tripoint &pos ); bool has_relic_recharge() const; bool has_relic_activation() const; - std::vector mutations_from_wearing( const Character &guy ) const; + std::vector mutations_from_wearing( const Character &guy, bool removing = false ) const; /** * Name of the item type (not the item), with proper plural. diff --git a/src/mutation.cpp b/src/mutation.cpp index b32fff1ab714e..bf019939a2f4e 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -411,6 +411,15 @@ void Character::mutation_effect( const trait_id &mut, const bool worn_destroyed_ if( !branch.conflicts_with_item( armor ) ) { return false; } + + // if an item gives an enchantment it shouldn't break or be shoved off + for( const enchantment &ench : armor.get_enchantments() ) { + for( const trait_id &inner_mut : ench.get_mutations() ) { + if( mut == inner_mut ) { + return false; + } + } + } if( !worn_destroyed_override && branch.destroys_gear ) { add_msg_player_or_npc( m_bad, _( "Your %s is destroyed!" ), diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 5d723bf434268..c3d1cd0cd6918 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -4163,7 +4163,8 @@ std::vector Character::get_base_traits() const return std::vector( my_traits.begin(), my_traits.end() ); } -std::vector Character::get_mutations( bool include_hidden ) const +std::vector Character::get_mutations( bool include_hidden, + bool ignore_enchantments ) const { std::vector result; result.reserve( my_mutations.size() + enchantment_cache->get_mutations().size() ); @@ -4172,17 +4173,19 @@ std::vector Character::get_mutations( bool include_hidden ) const result.push_back( t.first ); } } - for( const trait_id &ench_trait : enchantment_cache->get_mutations() ) { - if( include_hidden || ench_trait->player_display ) { - bool found = false; - for( const trait_id &exist : result ) { - if( exist == ench_trait ) { - found = true; - break; + if( !ignore_enchantments ) { + for( const trait_id &ench_trait : enchantment_cache->get_mutations() ) { + if( include_hidden || ench_trait->player_display ) { + bool found = false; + for( const trait_id &exist : result ) { + if( exist == ench_trait ) { + found = true; + break; + } + } + if( !found ) { + result.push_back( ench_trait ); } - } - if( !found ) { - result.push_back( ench_trait ); } } } From c7d178048c1171123dba403e6ff10d7f017d0935 Mon Sep 17 00:00:00 2001 From: bombasticSlacks Date: Sat, 29 Jan 2022 13:45:05 -0400 Subject: [PATCH 2/2] add check for multi wearing --- src/character_body.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/character_body.cpp b/src/character_body.cpp index a86dee59011c9..49787d776a993 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -175,9 +175,15 @@ void Character::update_body( const time_point &from, const time_point &to ) update_stomach( from, to ); recalculate_enchantment_cache(); // after recalcing the enchantment cache can properly remove and add mutations + const std::vector ¤t_traits = get_mutations(); for( const trait_id &mut : mutations_to_remove ) { - mutation_loss_effect( mut ); - enchantment_wear_change(); + // check if the player still has a mutation + // since a trait from an item might be provided by another item as well + auto it = std::find( current_traits.begin(), current_traits.end(), mut ); + if( it == current_traits.end() ) { + mutation_loss_effect( mut ); + enchantment_wear_change(); + } } for( const trait_id &mut : mutations_to_add ) { mutation_effect( mut, true );