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

Encapsulate Character::weapon #2657

Merged
merged 7 commits into from
May 8, 2023
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
2 changes: 1 addition & 1 deletion src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ action_id handle_action_menu()
action_weightings[ACTION_CYCLE_MOVE] = 400;
}
// Only prioritize fire weapon options if we're wielding a ranged weapon.
if( g->u.weapon.is_gun() || g->u.weapon.has_flag( flag_REACH_ATTACK ) ) {
if( g->u.primary_weapon().is_gun() || g->u.primary_weapon().has_flag( flag_REACH_ATTACK ) ) {
action_weightings[ACTION_FIRE] = 350;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ item *aim_activity_actor::get_weapon()
} else {
// Check for lost gun (e.g. yanked by zombie technician)
// TODO: check that this is the same gun that was used to start aiming
item *weapon = &get_player_character().weapon;
item *weapon = &get_player_character().primary_weapon();
return weapon->is_null() ? nullptr : weapon;
}
}
Expand Down Expand Up @@ -1191,7 +1191,7 @@ void throw_activity_actor::do_turn( player_activity &act, Character &who )
return;
}

if( &*target != &who.weapon ) {
if( &*target != &who.primary_weapon() ) {
// This is to represent "implicit offhand wielding"
int extra_cost = who.item_handling_cost( *target, true, INVENTORY_HANDLING_PENALTY / 2 );
who.mod_moves( -extra_cost );
Expand Down
10 changes: 5 additions & 5 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1986,17 +1986,17 @@ void activity_handlers::pulp_do_turn( player_activity *act, player *p )
const tripoint &pos = here.getlocal( act->placement );

// Stabbing weapons are a lot less effective at pulping
const int cut_power = std::max( p->weapon.damage_melee( DT_CUT ),
p->weapon.damage_melee( DT_STAB ) / 2 );
const int cut_power = std::max( p->primary_weapon().damage_melee( DT_CUT ),
p->primary_weapon().damage_melee( DT_STAB ) / 2 );

///\EFFECT_STR increases pulping power, with diminishing returns
float pulp_power = std::sqrt( ( p->str_cur + p->weapon.damage_melee( DT_BASH ) ) *
float pulp_power = std::sqrt( ( p->str_cur + p->primary_weapon().damage_melee( DT_BASH ) ) *
( cut_power + 1.0f ) );
float pulp_effort = p->str_cur + p->weapon.damage_melee( DT_BASH );
float pulp_effort = p->str_cur + p->primary_weapon().damage_melee( DT_BASH );
// Multiplier to get the chance right + some bonus for survival skill
pulp_power *= 40 + p->get_skill_level( skill_survival ) * 5;

const int mess_radius = p->weapon.has_flag( flag_MESSY ) ? 2 : 1;
const int mess_radius = p->primary_weapon().has_flag( flag_MESSY ) ? 2 : 1;

int moves = 0;
// use this to collect how many corpse are pulped
Expand Down
12 changes: 6 additions & 6 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,18 +1238,18 @@ bool avatar::wield( item &target )
moves -= mv;

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

last_item = weapon.typeId();
last_item = primary_weapon().typeId();
recoil = MAX_RECOIL;

weapon.on_wield( *this, mv );
primary_weapon().on_wield( *this, mv );

inv.update_invlet( weapon );
inv.update_cache_with_item( weapon );
inv.update_invlet( primary_weapon() );
inv.update_cache_with_item( primary_weapon() );

return true;
}
Expand Down
51 changes: 31 additions & 20 deletions src/avatar_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,15 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d )
get_option<bool>( "AUTO_FEATURES" ) && get_option<bool>( "AUTO_MINING" ) &&
!m.veh_at( dest_loc ) && !you.is_underwater() && !you.has_effect( effect_stunned ) &&
!is_riding ) {
if( you.weapon.has_flag( flag_DIG_TOOL ) ) {
if( you.weapon.type->can_use( "JACKHAMMER" ) && you.weapon.ammo_sufficient() ) {
you.invoke_item( &you.weapon, "JACKHAMMER", dest_loc );
item &digging_tool = you.primary_weapon();
if( digging_tool.has_flag( flag_DIG_TOOL ) ) {
if( digging_tool.type->can_use( "JACKHAMMER" ) && digging_tool.ammo_sufficient() ) {
you.invoke_item( &digging_tool, "JACKHAMMER", dest_loc );
// don't move into the tile until done mining
you.defer_move( dest_loc );
return true;
} else if( you.weapon.type->can_use( "PICKAXE" ) ) {
you.invoke_item( &you.weapon, "PICKAXE", dest_loc );
} else if( digging_tool.type->can_use( "PICKAXE" ) ) {
you.invoke_item( &digging_tool, "PICKAXE", dest_loc );
// don't move into the tile until done mining
you.defer_move( dest_loc );
return true;
Expand Down Expand Up @@ -585,7 +586,7 @@ static float rate_critter( const Creature &c )

void avatar_action::autoattack( avatar &you, map &m )
{
int reach = you.weapon.reach_range( you );
int reach = you.primary_weapon().reach_range( you );
std::vector<Creature *> critters = ranged::targetable_creatures( you, reach );
critters.erase( std::remove_if( critters.begin(), critters.end(), []( const Creature * c ) {
if( !c->is_npc() ) {
Expand Down Expand Up @@ -705,7 +706,7 @@ bool can_fire_turret( avatar &you, const map &m, const turret_data &turret )

void avatar_action::fire_wielded_weapon( avatar &you )
{
item &weapon = you.weapon;
item &weapon = you.primary_weapon();
if( weapon.is_gunmod() ) {
add_msg( m_info,
_( "The %s must be attached to a gun, it can not be fired separately." ),
Expand Down Expand Up @@ -754,7 +755,7 @@ void avatar_action::mend( avatar &you, item_location loc )
{
if( !loc ) {
if( you.is_armed() ) {
loc = item_location( you, &you.weapon );
loc = item_location( you, &you.primary_weapon() );
} else {
add_msg( m_info, _( "You're not wielding anything." ) );
return;
Expand Down Expand Up @@ -915,18 +916,21 @@ void avatar_action::plthrow( avatar &you, item_location loc,
}
// you must wield the item to throw it
// But only if you don't have enough free hands
int usable_hands = you.get_working_arm_count() -
( you.is_armed() ? 1 : 0 ) -
( you.weapon.is_two_handed( you ) ? 1 : 0 );
const auto &wielded = you.wielded_items();
int required_arms = std::accumulate( wielded.begin(), wielded.end(), 0,
[&you]( int acc, const item * it ) {
return acc + ( it->is_two_handed( you ) ? 2 : 1 );
} );

if( !you.is_wielding( *loc ) &&
( usable_hands < ( loc->is_two_handed( you ) ? 2 : 1 ) ) ) {
( you.get_working_arm_count() < required_arms ) ) {
if( !you.wield( *loc ) ) {
add_msg( m_info, _( "You do not have enough free hands to throw %s without wielding it." ),
loc->tname() );
return;
}

loc = item_location( you, &you.weapon );
loc = item_location( you, &you.primary_weapon() );
}

throw_activity_actor actor( loc, blind_throw_from_pos );
Expand Down Expand Up @@ -1233,12 +1237,15 @@ void avatar_action::reload_item()
void avatar_action::reload_wielded( bool prompt )
{
avatar &u = get_avatar();
if( u.weapon.is_null() || !u.weapon.is_reloadable() ) {
add_msg( _( "You aren't holding something you can reload." ) );
return;
for( item *it : u.wielded_items() ) {
if( it->is_reloadable() ) {
item_location item_loc = item_location( u, it );
reload( item_loc, prompt );
return;
}
}
item_location item_loc = item_location( u, &u.weapon );
reload( item_loc, prompt );

add_msg( _( "You aren't holding something you can reload." ) );
}

void avatar_action::reload_weapon( bool try_everything )
Expand All @@ -1252,9 +1259,14 @@ void avatar_action::reload_weapon( bool try_everything )
// Reload misc magazines in inventory.
avatar &u = get_avatar();
map &here = get_map();
std::set<itype_id> compatible_magazines;
for( const item *gun : u.wielded_items() ) {
const std::set<itype_id> &mags = gun->magazine_compatible();
compatible_magazines.insert( mags.begin(), mags.end() );
}
std::vector<item_location> reloadables = character_funcs::find_reloadables( u );
std::sort( reloadables.begin(), reloadables.end(),
[&u]( const item_location & a, const item_location & b ) {
[&u, &compatible_magazines]( const item_location & a, const item_location & b ) {
const item *ap = a.get_item();
const item *bp = b.get_item();
// Current wielded weapon comes first.
Expand All @@ -1265,7 +1277,6 @@ void avatar_action::reload_weapon( bool try_everything )
return true;
}
// Second sort by affiliation with wielded gun
const std::set<itype_id> compatible_magazines = u.weapon.magazine_compatible();
const bool mag_ap = compatible_magazines.count( ap->typeId() ) > 0;
const bool mag_bp = compatible_magazines.count( bp->typeId() ) > 0;
if( mag_ap != mag_bp ) {
Expand Down
34 changes: 18 additions & 16 deletions src/bionics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,8 @@ void npc::check_or_use_weapon_cbm()
}

// There's no point in checking the bionics if they can't unwield what they have.
if( !weapon.has_flag( flag_NO_UNWIELD ) && cbm_toggled.is_null() && !avail_toggle_cbms.empty() ) {
if( !primary_weapon().has_flag( flag_NO_UNWIELD ) && cbm_toggled.is_null() &&
!avail_toggle_cbms.empty() ) {
int toggle_index = -1;
item best_cbm_weap = null_item_reference();
for( int i : avail_toggle_cbms ) {
Expand Down Expand Up @@ -569,7 +570,7 @@ void npc::check_or_use_weapon_cbm()

if( cbm_active.is_null() && !avail_active_cbms.empty() ) {
int active_index = -1;
bool wield_gun = weapon.is_gun();
bool wield_gun = primary_weapon().is_gun();
item best_cbm_active = null_item_reference();
for( int i : avail_active_cbms ) {
bionic &bio = ( *my_bionics )[ i ];
Expand Down Expand Up @@ -688,27 +689,27 @@ bool Character::activate_bionic( bionic &bio, bool eff_only )
avatar_action::fire_ranged_bionic( *this->as_avatar(), item( bio.info().fake_item ),
bio.info().power_activate );
} else if( bio.info().has_flag( flag_BIONIC_WEAPON ) ) {
if( weapon.has_flag( flag_NO_UNWIELD ) ) {
add_msg_if_player( m_info, _( "Deactivate your %s first!" ), weapon.tname() );
if( primary_weapon().has_flag( flag_NO_UNWIELD ) ) {
add_msg_if_player( m_info, _( "Deactivate your %s first!" ), primary_weapon().tname() );
refund_power();
bio.powered = false;
return false;
}

if( !weapon.is_null() ) {
const std::string query = string_format( _( "Stop wielding %s?" ), weapon.tname() );
if( !dispose_item( item_location( *this, &weapon ), query ) ) {
if( !primary_weapon().is_null() ) {
const std::string query = string_format( _( "Stop wielding %s?" ), primary_weapon().tname() );
if( !dispose_item( item_location( *this, &primary_weapon() ), query ) ) {
refund_power();
bio.powered = false;
return false;
}
}

add_msg_activate();
weapon = item( bio.info().fake_item );
weapon.invlet = '#';
primary_weapon() = item( bio.info().fake_item );
primary_weapon().invlet = '#';
if( bio.ammo_count > 0 ) {
weapon.ammo_set( bio.ammo_loaded, bio.ammo_count );
primary_weapon().ammo_set( bio.ammo_loaded, bio.ammo_count );
avatar_action::fire_wielded_weapon( g->u );
}
} else if( bio.id == bio_ears && has_active_bionic( bio_earplugs ) ) {
Expand Down Expand Up @@ -1178,16 +1179,17 @@ bool Character::deactivate_bionic( bionic &bio, bool eff_only )

// Deactivation effects go here
if( bio.info().has_flag( flag_BIONIC_WEAPON ) ) {
if( weapon.typeId() == bio.info().fake_item ) {
add_msg_if_player( _( "You withdraw your %s." ), weapon.tname() );
if( primary_weapon().typeId() == bio.info().fake_item ) {
add_msg_if_player( _( "You withdraw your %s." ), primary_weapon().tname() );
if( g->u.sees( pos() ) ) {
add_msg_if_npc( m_info, _( "<npcname> withdraws %s %s." ), disp_name( true ),
weapon.tname() );
primary_weapon().tname() );
}
bio.ammo_loaded =
weapon.ammo_data() != nullptr ? weapon.ammo_data()->get_id() : itype_id::NULL_ID();
bio.ammo_count = static_cast<unsigned int>( weapon.ammo_remaining() );
weapon = item();
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();
invalidate_crafting_inventory();
}
} else if( bio.id == bio_cqb ) {
Expand Down
2 changes: 1 addition & 1 deletion src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8250,7 +8250,7 @@ void Character::on_dodge( Creature *source, int difficulty )

// For adjacent attackers check for techniques usable upon successful dodge
if( source && square_dist( pos(), source->pos() ) == 1 ) {
matec_id tec = pick_technique( *source, used_weapon(), false, true, false );
matec_id tec = pick_technique( *source, primary_weapon(), false, true, false );

if( tec != tec_none && !is_dead_state() ) {
if( get_stamina() < get_stamina_max() / 3 ) {
Expand Down
27 changes: 24 additions & 3 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1190,12 +1190,31 @@ class Character : public Creature, public visitable<Character>
int get_item_position( const item *it ) const;

/**
* Returns a reference to the item which will be used to make attacks.
* At the moment it's always @ref weapon or a reference to a null item.
* Returns all equipped items that require a limb to be held.
*/
/*@{*/
std::vector<item *> wielded_items();
std::vector<const item *> wielded_items() const;
/*@}*/

/**
* Legacy code hack, don't use.
* Returns the null item if martial art forces unarmed, otherwise @ref primary_weapon.
* Use @ref wielded_items instead.
*/
/*@{*/
const item &used_weapon() const;
item &used_weapon();
const item &used_weapon() const;
/*@}*/

/**
* Legacy code hack, don't use.
* Returns the first wielded weapon or a null item.
* Use @ref wielded_items instead.
*/
/*@{*/
item &primary_weapon();
const item &primary_weapon() const;
/*@}*/

/**
Expand Down Expand Up @@ -1553,7 +1572,9 @@ 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;
pimpl<bionic_collection> my_bionics;
Expand Down
8 changes: 4 additions & 4 deletions src/character_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,12 @@ int intimidation( const Character &ch )
{
/** @EFFECT_STR increases intimidation factor */
int ret = ch.get_str() * 2;
if( ch.weapon.is_gun() ) {
if( ch.primary_weapon().is_gun() ) {
ret += 10;
}
if( ch.weapon.damage_melee( DT_BASH ) >= 12 ||
ch.weapon.damage_melee( DT_CUT ) >= 12 ||
ch.weapon.damage_melee( DT_STAB ) >= 12 ) {
if( ch.primary_weapon().damage_melee( DT_BASH ) >= 12 ||
ch.primary_weapon().damage_melee( DT_CUT ) >= 12 ||
ch.primary_weapon().damage_melee( DT_STAB ) >= 12 ) {
ret += 5;
}

Expand Down
8 changes: 4 additions & 4 deletions src/character_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ std::string fmt_wielded_weapon( const Character &who )
if( !who.is_armed() ) {
return _( "fists" );
}
const item &weapon = who.weapon;
const item &weapon = who.primary_weapon();
if( weapon.is_gun() ) {
std::string str = string_format( "(%d) [%s] %s", weapon.ammo_remaining(),
weapon.gun_current_mode().tname(), weapon.type_name() );
Expand Down 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.weapon = item();
who.primary_weapon() = item();

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

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

item &weapon = who.weapon;
item &weapon = who.primary_weapon();

who.inv.update_invlet( weapon );
who.inv.update_cache_with_item( weapon );
Expand Down
2 changes: 1 addition & 1 deletion src/character_martial_arts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ std::string character_martial_arts::enumerate_known_styles( const itype_id &weap

std::string character_martial_arts::selected_style_name( const Character &owner ) const
{
if( style_selected->force_unarmed || style_selected->weapon_valid( owner.weapon ) ) {
if( style_selected->force_unarmed || style_selected->weapon_valid( owner.primary_weapon() ) ) {
return style_selected->name.translated();
} else if( owner.is_armed() ) {
return _( "Normal" );
Expand Down
2 changes: 1 addition & 1 deletion src/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ void conditional_t<T>::set_can_stow_weapon( bool is_npc )
if( is_npc ) {
actor = dynamic_cast<player *>( d.beta );
}
return !actor->unarmed_attack() && actor->can_pick_volume( actor->weapon );
return !actor->unarmed_attack() && actor->can_pick_volume( actor->primary_weapon() );
};
}

Expand Down
Loading