Skip to content

Commit

Permalink
Move wielded item data to body part (#2864)
Browse files Browse the repository at this point in the history
* Move wielded item to body part

* Remove unused
  • Loading branch information
Coolthulhu authored Jun 18, 2023
1 parent 5f2414f commit 910b218
Show file tree
Hide file tree
Showing 25 changed files with 169 additions and 78 deletions.
4 changes: 2 additions & 2 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1237,9 +1237,9 @@ bool avatar::wield( item &target )
moves -= mv;

if( has_item( target ) ) {
primary_weapon() = i_rem( &target );
set_primary_weapon( i_rem( &target ) );
} else {
primary_weapon() = target;
set_primary_weapon( target );
}

last_item = primary_weapon().typeId();
Expand Down
4 changes: 2 additions & 2 deletions src/bionics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ bool Character::activate_bionic( bionic &bio, bool eff_only )
}

add_msg_activate();
primary_weapon() = item( bio.info().fake_item );
set_primary_weapon( item( bio.info().fake_item ) );
primary_weapon().invlet = '#';
if( is_player() && bio.ammo_count > 0 ) {
primary_weapon().ammo_set( bio.ammo_loaded, bio.ammo_count );
Expand Down Expand Up @@ -1152,7 +1152,7 @@ bool Character::deactivate_bionic( bionic &bio, bool eff_only )
primary_weapon().ammo_data() != nullptr ? primary_weapon().ammo_data()->get_id() :
itype_id::NULL_ID();
bio.ammo_count = static_cast<unsigned int>( primary_weapon().ammo_remaining() );
primary_weapon() = item();
set_primary_weapon( item() );
invalidate_crafting_inventory();
}
} else if( bio.id == bio_cqb ) {
Expand Down
11 changes: 11 additions & 0 deletions src/bodypart.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
class JsonObject;
class JsonIn;
class JsonOut;
class item;
struct body_part_type;

template <typename E> struct enum_traits;
Expand Down Expand Up @@ -153,6 +154,12 @@ struct body_part_type {
int bionic_slots_ = 0;
};

class wield_status
{
public:
std::shared_ptr<item> wielded;
};

class bodypart
{
private:
Expand All @@ -166,6 +173,10 @@ class bodypart
int damage_bandaged = 0;
int damage_disinfected = 0;

public:
// TODO: private
wield_status wielding;

public:
bodypart(): id( bodypart_str_id( "num_bp" ) ), hp_cur( 0 ), hp_max( 0 ) {}
bodypart( bodypart_str_id id ): id( id ), hp_cur( id->base_hp ), hp_max( id->base_hp ) {}
Expand Down
53 changes: 37 additions & 16 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ Character::Character() :
set_stim( 0 );
set_stamina( 10000 ); //Temporary value for stamina. It will be reset later from external json option.
set_anatomy( anatomy_id("human_anatomy") );
set_body();
update_type_of_scent( true );
pkill = 0;
stored_calories = max_stored_kcal() - 100;
Expand Down Expand Up @@ -1010,6 +1011,7 @@ void Character::mount_creature( monster &z )
}
add_msg_if_player( m_good, _( "You hear your %s whir to life." ), z.get_name() );
}
add_msg_if_player( m_good, _( "You hear your %s whir to life." ), z.get_name() );
}
// some rideable mechs have night-vision
recalc_sight_limits();
Expand Down Expand Up @@ -1088,7 +1090,7 @@ void Character::forced_dismount()
auto mon = mounted_creature.get();
if( mon->has_flag( MF_RIDEABLE_MECH ) && !mon->type->mech_weapon.is_empty() ) {
mech = true;
remove_item( weapon );
remove_item( primary_weapon() );
}
mon->mounted_player_id = character_id();
mon->remove_effect( effect_ridden );
Expand Down Expand Up @@ -1193,6 +1195,7 @@ void Character::dismount()
remove_effect( effect_riding );
monster *critter = mounted_creature.get();
critter->mounted_player_id = character_id();
item &weapon = primary_weapon();
if( critter->has_flag( MF_RIDEABLE_MECH ) && !critter->type->mech_weapon.is_empty() &&
weapon.typeId() == critter->type->mech_weapon ) {
remove_item( weapon );
Expand Down Expand Up @@ -1594,7 +1597,7 @@ void Character::recalc_hp()
void Character::calc_all_parts_hp( float hp_mod, float hp_adjustment, int str_max )
{
for( const std::pair<const bodypart_str_id, bodypart> &part : get_body() ) {
bodypart &bp = *get_part( part.first );
bodypart &bp = get_part( part.first );
int new_max = ( part.first->base_hp + str_max * 3 + hp_adjustment ) * hp_mod;

if( has_trait( trait_id( "GLASSJAW" ) ) && part.first == bodypart_str_id( "head" ) ) {
Expand Down Expand Up @@ -2327,7 +2330,7 @@ item *Character::invlet_to_item( const int linvlet )
const item &Character::i_at( int position ) const
{
if( position == -1 ) {
return weapon;
return primary_weapon();
}
if( position < -1 ) {
int worn_index = worn_position_to_index( position );
Expand All @@ -2348,6 +2351,7 @@ item &Character::i_at( int position )

int Character::get_item_position( const item *it ) const
{
const item &weapon = primary_weapon();
if( weapon.has_item( *it ) ) {
return -1;
}
Expand All @@ -2367,8 +2371,8 @@ item Character::i_rem( int pos )
{
item tmp;
if( pos == -1 ) {
tmp = weapon;
weapon = item();
tmp = primary_weapon();
set_primary_weapon( item() );
return tmp;
} else if( pos < -1 && pos > worn_position_to_index( worn.size() ) ) {
auto iter = worn.begin();
Expand Down Expand Up @@ -2489,6 +2493,7 @@ invlets_bitset Character::allocated_invlets() const
{
invlets_bitset invlets = inv.allocated_invlets();

const item &weapon = primary_weapon();
invlets.set( weapon.invlet );
for( const auto &w : worn ) {
invlets.set( w.invlet );
Expand All @@ -2508,8 +2513,8 @@ bool Character::has_active_item( const itype_id &id ) const

item Character::remove_weapon()
{
item tmp = weapon;
weapon = item();
item tmp = primary_weapon();
set_primary_weapon( item() );
clear_npc_ai_info_cache( npc_ai_info::ideal_weapon_value );
return tmp;
}
Expand Down Expand Up @@ -2575,6 +2580,7 @@ units::mass Character::weight_carried_reduced_by( const excluded_stacks &without

// Wielded item
units::mass weaponweight = 0_gram;
const item &weapon = primary_weapon();
auto weapon_it = without.find( &weapon );
if( weapon_it == without.end() ) {
weaponweight = weapon.weight();
Expand Down Expand Up @@ -2916,6 +2922,7 @@ ret_val<bool> Character::can_wear( const item &it, bool with_equip_change ) cons
}

// Check if we don't have both hands available before wearing a briefcase, shield, etc. Also occurs if we're already wearing one.
const item &weapon = primary_weapon();
if( it.has_flag( flag_RESTRICT_HANDS ) && ( worn_with_flag( flag_RESTRICT_HANDS ) ||
weapon.is_two_handed( *this ) ) ) {
return ret_val<bool>::make_failure( ( is_player() ? _( "You don't have a hand free to wear that." )
Expand Down Expand Up @@ -2986,6 +2993,7 @@ Character::wear_possessed( item &to_wear, bool interactive )

bool was_weapon;
item to_wear_copy( to_wear );
item &weapon = primary_weapon();
if( &to_wear == &weapon ) {
weapon = item();
was_weapon = true;
Expand Down Expand Up @@ -3087,6 +3095,7 @@ ret_val<bool> Character::can_wield( const item &it ) const
_( "You need at least one arm to even consider wielding something." ) );
}

const item &weapon = primary_weapon();
if( is_armed() && weapon.has_flag( "NO_UNWIELD" ) ) {
return ret_val<bool>::make_failure( _( "The %s is preventing you from wielding the %s." ),
character_funcs::fmt_wielded_weapon( *this ), it.tname() );
Expand Down Expand Up @@ -3126,6 +3135,7 @@ ret_val<bool> Character::can_unwield( const item &it ) const

bool Character::unwield()
{
item &weapon = primary_weapon();
if( weapon.is_null() ) {
return true;
}
Expand Down Expand Up @@ -3203,8 +3213,10 @@ void Character::drop_invalid_inventory()

bool Character::has_artifact_with( const art_effect_passive effect ) const
{
if( weapon.has_effect_when_wielded( effect ) ) {
return true;
for( const item *weapon : wielded_items() ) {
if( weapon->has_effect_when_wielded( effect ) ) {
return true;
}
}
for( auto &i : worn ) {
if( i.has_effect_when_worn( effect ) ) {
Expand All @@ -3218,7 +3230,7 @@ bool Character::has_artifact_with( const art_effect_passive effect ) const

bool Character::is_wielding( const item &target ) const
{
return &weapon == &target;
return &primary_weapon() == &target;
}

bool Character::is_wearing( const item &itm ) const
Expand Down Expand Up @@ -3312,6 +3324,7 @@ std::vector<std::string> Character::get_overlay_ids() const

// last weapon
// TODO: might there be clothing that covers the weapon?
const item &weapon = primary_weapon();
if( is_armed() ) {
rval.push_back( "wielded_" + weapon.typeId().str() );
}
Expand Down Expand Up @@ -3686,6 +3699,7 @@ units::mass Character::get_weight() const
ret += bodyweight(); // The base weight of the player's body
ret += inv.weight(); // Weight of the stored inventory
ret += wornWeight; // Weight of worn items
const item &weapon = primary_weapon();
ret += weapon.weight(); // Weight of wielded item
ret += bionics_weight(); // Weight of installed bionics
return ret;
Expand Down Expand Up @@ -4605,12 +4619,12 @@ void Character::regen( int rate_multiplier )
}

// remove effects if the limb was healed by other way
if( has_effect( effect_bandaged, bp->token ) && ( get_part( bp )->is_at_max_hp() ) ) {
if( has_effect( effect_bandaged, bp->token ) && ( get_part( bp ).is_at_max_hp() ) ) {
damage_bandaged[i] = 0;
remove_effect( effect_bandaged, bp->token );
add_msg_if_player( _( "Bandaged wounds on your %s healed." ), body_part_name( bp ) );
}
if( has_effect( effect_disinfected, bp->token ) && ( get_part( bp )->is_at_max_hp() ) ) {
if( has_effect( effect_disinfected, bp->token ) && ( get_part( bp ).is_at_max_hp() ) ) {
damage_disinfected[i] = 0;
remove_effect( effect_disinfected, bp->token );
add_msg_if_player( _( "Disinfected wounds on your %s healed." ), body_part_name( bp ) );
Expand Down Expand Up @@ -5313,6 +5327,7 @@ void Character::update_bodytemp( const map &m, const weather_manager &weather )
}
}
// If player is wielding something large, pockets are not usable
const item &weapon = primary_weapon();
if( weapon.volume() >= 500_ml ) {
bonus_clothing_map[body_part_hand_l].clear();
bonus_clothing_map[body_part_hand_r].clear();
Expand Down Expand Up @@ -6530,6 +6545,7 @@ std::string Character::extended_description() const

ss += "--\n";
ss += _( "Wielding:" ) + std::string( " " );
const item &weapon = primary_weapon();
if( weapon.is_null() ) {
ss += _( "Nothing" );
} else {
Expand Down Expand Up @@ -7463,6 +7479,7 @@ int Character::item_handling_cost( const item &it, bool penalties, int base_cost
mv += std::min( 200, it.volume() / 20_ml );
}

const item &weapon = primary_weapon();
if( weapon.typeId() == itype_e_handcuffs ) {
mv *= 4;
} else if( penalties && has_effect( effect_grabbed ) ) {
Expand Down Expand Up @@ -8245,6 +8262,7 @@ void Character::on_dodge( Creature *source, int difficulty )
dodges_left--;

// dodging throws of our aim unless we are either skilled at dodging or using a small weapon
const item &weapon = primary_weapon();
if( is_armed() && weapon.is_gun() ) {
recoil += std::max( weapon.volume() / 250_ml - get_skill_level( skill_dodge ), 0 ) * rng( 0, 100 );
recoil = std::min( MAX_RECOIL, recoil );
Expand Down Expand Up @@ -8404,6 +8422,7 @@ void Character::apply_damage( Creature *source, bodypart_id hurt, int dam,
mod_part_hp_cur( part_to_damage, - dam_to_bodypart );
get_event_bus().send<event_type::character_takes_damage>( getID(), dam_to_bodypart );

const item &weapon = primary_weapon();
if( !weapon.is_null() && !as_player()->can_wield( weapon ).success() &&
can_unwield( weapon ).success() ) {
add_msg_if_player( _( "You are no longer able to wield your %s and drop it!" ),
Expand Down Expand Up @@ -8538,6 +8557,7 @@ dealt_damage_instance Character::deal_damage( Creature *source, bodypart_id bp,


// TODO: Scale with damage in a way that makes sense for power armors, plate armor and naked skin.
const item &weapon = primary_weapon();
recoil += recoil_mul * weapon.volume() / 250_ml;
recoil = std::min( MAX_RECOIL, recoil );
//looks like this should be based off of dealt damages, not d as d has no damage reduction applied.
Expand Down Expand Up @@ -8941,8 +8961,8 @@ int Character::shoe_type_count( const itype_id &it ) const
std::vector<item *> Character::inv_dump()
{
std::vector<item *> ret;
if( is_armed() && can_unwield( weapon ).success() ) {
ret.push_back( &weapon );
if( is_armed() && can_unwield( primary_weapon() ).success() ) {
ret.push_back( &primary_weapon() );
}
for( auto &i : worn ) {
ret.push_back( &i );
Expand Down Expand Up @@ -9612,7 +9632,7 @@ std::list<item> Character::use_amount( itype_id it, int quantity,
const std::function<bool( const item & )> &filter )
{
std::list<item> ret;
if( weapon.use_amount( it, quantity, ret ) ) {
if( primary_weapon().use_amount( it, quantity, ret ) ) {
remove_weapon();
}
for( auto a = worn.begin(); a != worn.end() && quantity > 0; ) {
Expand Down Expand Up @@ -9954,6 +9974,7 @@ const pathfinding_settings &Character::get_pathfinding_settings() const

float Character::power_rating() const
{
const item &weapon = primary_weapon();
int dmg = std::max( { weapon.damage_melee( DT_BASH ),
weapon.damage_melee( DT_CUT ),
weapon.damage_melee( DT_STAB )
Expand Down Expand Up @@ -10308,7 +10329,7 @@ std::vector<std::string> Character::short_description_parts() const
std::string gender = male ? _( "Male" ) : _( "Female" );
result.push_back( name + ", " + gender );
if( is_armed() ) {
result.push_back( _( "Wielding: " ) + weapon.tname() );
result.push_back( _( "Wielding: " ) + primary_weapon().tname() );
}
const std::string worn_str = enumerate_as_string( worn.begin(), worn.end(),
[]( const item & it ) {
Expand Down
8 changes: 6 additions & 2 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,11 @@ class Character : public Creature, public visitable<Character>
const item &primary_weapon() const;
/*@}*/

/**
* Use this when primary weapon might not exist yet.
*/
void set_primary_weapon( const item &new_weapon );

/**
* Try to find a container/s on character containing ammo of type it.typeId() and
* add charges until the container is full.
Expand Down Expand Up @@ -1575,8 +1580,7 @@ class Character : public Creature, public visitable<Character>
std::optional<tripoint> destination_point;
inventory inv;
itype_id last_item;
private:
item weapon;

public:

int scent = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/character_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ void add_pain_msg( const Character &who, int val, body_part bp )
void normalize( Character &who )
{
who.martial_arts_data->reset_style();
who.primary_weapon() = item();
who.set_primary_weapon( item() );

who.set_body();
who.recalc_hp();
Expand Down Expand Up @@ -545,7 +545,7 @@ bool try_wield_contents( Character &who, item &container, item *internal_item, b
who.inv.unsort();
}

who.primary_weapon() = std::move( *internal_item );
who.set_primary_weapon( *internal_item );
container.remove_item( *internal_item );
container.on_contents_changed();

Expand Down
1 change: 1 addition & 0 deletions src/character_turn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@ void Character::environmental_revert_effect()

void Character::process_items()
{
item &weapon = primary_weapon();
if( weapon.needs_processing() && weapon.process( as_player(), pos(), false ) ) {
weapon = item();
}
Expand Down
2 changes: 1 addition & 1 deletion src/consumption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1551,7 +1551,7 @@ void Character::consume( item_location loc )
}

if( was_in_container && wielding ) {
add_msg_if_player( _( "You are now wielding an empty %s." ), weapon.tname() );
add_msg_if_player( _( "You are now wielding an empty %s." ), primary_weapon().tname() );
} else if( was_in_container && worn ) {
add_msg_if_player( _( "You are now wearing an empty %s." ), target.tname() );
} else if( was_in_container && !is_npc() ) {
Expand Down
2 changes: 1 addition & 1 deletion src/crafting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ const inventory &Character::crafting_inventory( const tripoint &src_pos, int rad
}
cached_crafting_inventory.form_from_map( inv_pos, radius, this, false, clear_path );
cached_crafting_inventory += inv;
cached_crafting_inventory += weapon;
cached_crafting_inventory += primary_weapon();
cached_crafting_inventory += worn;
for( const bionic &bio : *my_bionics ) {
const bionic_data &bio_data = bio.info();
Expand Down
Loading

0 comments on commit 910b218

Please sign in to comment.