Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes For Worn Enchanted Armor #54852

Merged
merged 2 commits into from
Jan 30, 2022
Merged
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
6 changes: 6 additions & 0 deletions data/json/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
34 changes: 19 additions & 15 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8676,32 +8676,36 @@ 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 );
}

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 ) {
Expand Down
10 changes: 9 additions & 1 deletion src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -2246,7 +2246,8 @@ class Character : public Creature, public visitable
/** Get the idents of all base traits. */
std::vector<trait_id> get_base_traits() const;
/** Get the idents of all traits/mutations. */
std::vector<trait_id> get_mutations( bool include_hidden = true ) const;
std::vector<trait_id> get_mutations( bool include_hidden = true,
bool ignore_enchantment = false ) const;
const std::bitset<NUM_VISION_MODES> &get_vision_modes() const {
return vision_mode_cache;
}
Expand Down Expand Up @@ -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) */
Expand Down Expand Up @@ -3286,6 +3289,11 @@ class Character : public Creature, public visitable
* Pointers to mutation branches in @ref my_mutations.
*/
std::vector<const mutation_branch *> 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<trait_id> mutations_to_remove;
std::vector<trait_id> mutations_to_add;
/**
* The amount of weight the Character is carrying.
* If it is nullopt, needs to be recalculated
Expand Down
17 changes: 17 additions & 0 deletions src/character_body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,23 @@ 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<trait_id> &current_traits = get_mutations();
for( const trait_id &mut : mutations_to_remove ) {
// 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 );
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<float>( 3_minutes ) );
}
Expand Down
1 change: 1 addition & 0 deletions src/flag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" );
Expand Down
1 change: 1 addition & 0 deletions src/flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down Expand Up @@ -11756,7 +11756,7 @@ void item::reset_temp_check()
last_temp_check = calendar::turn;
}

std::vector<trait_id> item::mutations_from_wearing( const Character &guy ) const
std::vector<trait_id> item::mutations_from_wearing( const Character &guy, bool removing ) const
{
if( !is_relic() ) {
return std::vector<trait_id> {};
Expand All @@ -11770,7 +11770,7 @@ std::vector<trait_id> 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 );
Expand Down
2 changes: 1 addition & 1 deletion src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<trait_id> mutations_from_wearing( const Character &guy ) const;
std::vector<trait_id> mutations_from_wearing( const Character &guy, bool removing = false ) const;

/**
* Name of the item type (not the item), with proper plural.
Expand Down
9 changes: 9 additions & 0 deletions src/mutation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!" ),
Expand Down
25 changes: 14 additions & 11 deletions src/newcharacter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4163,7 +4163,8 @@ std::vector<trait_id> Character::get_base_traits() const
return std::vector<trait_id>( my_traits.begin(), my_traits.end() );
}

std::vector<trait_id> Character::get_mutations( bool include_hidden ) const
std::vector<trait_id> Character::get_mutations( bool include_hidden,
bool ignore_enchantments ) const
{
std::vector<trait_id> result;
result.reserve( my_mutations.size() + enchantment_cache->get_mutations().size() );
Expand All @@ -4172,17 +4173,19 @@ std::vector<trait_id> 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 );
}
}
}
Expand Down