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

Fix segfault when using vehicle tool to hacksaw #70945

Merged
merged 3 commits into from
Jan 16, 2024
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
79 changes: 60 additions & 19 deletions src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,22 @@
return;
}

const int qual = tool->get_quality( qual_SAW_M );
int qual;

Check failure on line 1247 in src/activity_actor.cpp

View workflow job for this annotation

GitHub Actions / GCC 9, Curses, LTO

‘qual’ may be used uninitialized in this function [-Werror=maybe-uninitialized]

Check failure on line 1247 in src/activity_actor.cpp

View workflow job for this annotation

GitHub Actions / GCC 9, Curses, LTO

‘qual’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
if( type.has_value() ) {
item veh_tool = item( type.value(), calendar::turn );
for( const std::pair<const quality_id, int> &quality : type.value()->qualities ) {
if( quality.first == qual_SAW_M ) {
qual = quality.second;
}
}
for( const std::pair<const quality_id, int> &quality : type.value()->charged_qualities ) {
if( quality.first == qual_SAW_M ) {
qual = std::max( qual, quality.second );
}
}
} else {
qual = tool->get_quality( qual_SAW_M );
}
if( qual < 2 ) {
if( !testing ) {
debugmsg( "Item %s with 'HACKSAW' use action requires SAW_M quality of at least 2.",
Expand All @@ -1266,27 +1281,52 @@
{
std::string method = "HACKSAW";

if( tool->ammo_sufficient( &who, method ) ) {
int ammo_consumed = tool->ammo_required();
std::map<std::string, int>::const_iterator iter = tool->type->ammo_scale.find( method );
if( iter != tool->type->ammo_scale.end() ) {
ammo_consumed *= iter->second;
}
if( !veh_pos.has_value() ) {
if( tool->ammo_sufficient( &who, method ) ) {
int ammo_consumed = tool->ammo_required();
std::map<std::string, int>::const_iterator iter = tool->type->ammo_scale.find( method );
if( iter != tool->type->ammo_scale.end() ) {
ammo_consumed *= iter->second;
}

tool->ammo_consume( ammo_consumed, tool.position(), &who );
sfx::play_activity_sound( "tool", "hacksaw", sfx::get_heard_volume( target ) );
if( calendar::once_every( 1_minutes ) ) {
//~ Sound of a metal sawing tool at work!
sounds::sound( target, 15, sounds::sound_t::destructive_activity, _( "grnd grnd grnd" ) );
tool->ammo_consume( ammo_consumed, tool.position(), &who );
sfx::play_activity_sound( "tool", "hacksaw", sfx::get_heard_volume( target ) );
if( calendar::once_every( 1_minutes ) ) {
//~ Sound of a metal sawing tool at work!
sounds::sound( target, 15, sounds::sound_t::destructive_activity, _( "grnd grnd grnd" ) );
}
} else {
if( who.is_avatar() ) {
who.add_msg_if_player( m_bad, _( "Your %1$s ran out of charges." ), tool->tname() );
} else { // who.is_npc()
add_msg_if_player_sees( who.pos(), _( "%1$s %2$s ran out of charges." ), who.disp_name( false,
true ), tool->tname() );
}
who.cancel_activity();
}
} else {
if( who.is_avatar() ) {
who.add_msg_if_player( m_bad, _( "Your %1$s ran out of charges." ), tool->tname() );
} else { // who.is_npc()
add_msg_if_player_sees( who.pos(), _( "%1$s %2$s ran out of charges." ), who.disp_name( false,
true ), tool->tname() );
map &here = get_map();
const optional_vpart_position vp = here.veh_at( veh_pos.value() );
if( !vp ) {
debugmsg( "Lost ACT_HACKSAW vehicle tool" );
return;
}
vehicle &veh = vp->vehicle();
if( vehicle::use_vehicle_tool( veh, veh_pos.value(), type.value(), true ) ) {
sfx::play_activity_sound( "tool", "hacksaw", sfx::get_heard_volume( target ) );
if( calendar::once_every( 1_minutes ) ) {
//~ Sound of a metal sawing tool at work!
sounds::sound( target, 15, sounds::sound_t::destructive_activity, _( "grnd grnd grnd" ) );
}
} else {
if( who.is_avatar() ) {
who.add_msg_if_player( m_bad, _( "Your %1$s ran out of charges." ), type.value()->nname( 1 ) );
} else { // who.is_npc()
add_msg_if_player_sees( who.pos(), _( "%1$s %2$s ran out of charges." ), who.disp_name( false,
true ), type.value()->nname( 1 ) );
}
who.cancel_activity();
}
who.cancel_activity();
}
}

Expand Down Expand Up @@ -1374,7 +1414,8 @@
{
const hacksaw_activity_actor &actor = static_cast<const hacksaw_activity_actor &>
( other );
return actor.target == target && actor.tool.operator == ( tool );
return actor.target == target && ( ( veh_pos.has_value() &&
veh_pos.value() == actor.veh_pos.value_or( tripoint_max ) ) || actor.tool.operator == ( tool ) );
}

void hacksaw_activity_actor::serialize( JsonOut &jsout ) const
Expand Down
6 changes: 4 additions & 2 deletions src/activity_actor_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
public:
explicit hacksaw_activity_actor( const tripoint &target,
const item_location &tool ) : target( target ), tool( tool ) {};

explicit hacksaw_activity_actor( const tripoint &target, const itype_id &type,
const tripoint &veh_pos ) : target( target ), type( type ), veh_pos( veh_pos ) {};
activity_id get_type() const override {
return activity_id( "ACT_HACKSAW" );
}
Expand All @@ -197,7 +198,8 @@
private:
tripoint target;
item_location tool;

std::optional<itype_id> type;

Check failure on line 201 in src/activity_actor_definitions.h

View workflow job for this annotation

GitHub Actions / build (src)

Function 'deserialize' appears to be a serialization function for class 'hacksaw_activity_actor' but does not mention field 'type'. [cata-serialize,-warnings-as-errors]

Check failure on line 201 in src/activity_actor_definitions.h

View workflow job for this annotation

GitHub Actions / build (src)

Function 'serialize' appears to be a serialization function for class 'hacksaw_activity_actor' but does not mention field 'type'. [cata-serialize,-warnings-as-errors]
std::optional<tripoint> veh_pos;

Check failure on line 202 in src/activity_actor_definitions.h

View workflow job for this annotation

GitHub Actions / build (src)

Function 'deserialize' appears to be a serialization function for class 'hacksaw_activity_actor' but does not mention field 'veh_pos'. [cata-serialize,-warnings-as-errors]

Check failure on line 202 in src/activity_actor_definitions.h

View workflow job for this annotation

GitHub Actions / build (src)

Function 'serialize' appears to be a serialization function for class 'hacksaw_activity_actor' but does not mention field 'veh_pos'. [cata-serialize,-warnings-as-errors]
bool can_resume_with_internal( const activity_actor &other,
const Character &/*who*/ ) const override;
};
Expand Down
9 changes: 6 additions & 3 deletions src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4913,7 +4913,7 @@ std::optional<int> iuse::oxytorch( Character *p, item *it, const tripoint & )
return std::nullopt;
}

std::optional<int> iuse::hacksaw( Character *p, item *it, const tripoint & )
std::optional<int> iuse::hacksaw( Character *p, item *it, const tripoint &it_pnt )
{
if( !p ) {
debugmsg( "%s called action hacksaw that requires character but no character is present",
Expand Down Expand Up @@ -4952,8 +4952,11 @@ std::optional<int> iuse::hacksaw( Character *p, item *it, const tripoint & )
}
return std::nullopt;
}

p->assign_activity( hacksaw_activity_actor( pnt, item_location{*p, it} ) );
if( p->pos() == it_pnt ) {
p->assign_activity( hacksaw_activity_actor( pnt, item_location{ *p, it } ) );
} else {
p->assign_activity( hacksaw_activity_actor( pnt, it->typeId(), it_pnt ) );
}

return std::nullopt;
}
Expand Down
2 changes: 1 addition & 1 deletion src/iuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ std::optional<int> granade_act( Character *, item *, const tripoint & );
std::optional<int> grenade_inc_act( Character *, item *, const tripoint & );
std::optional<int> gun_repair( Character *, item *, const tripoint & );
std::optional<int> gunmod_attach( Character *, item *, const tripoint & );
std::optional<int> hacksaw( Character *, item *, const tripoint & );
std::optional<int> hacksaw( Character *, item *, const tripoint &it_pnt );
std::optional<int> hairkit( Character *, item *, const tripoint & );
std::optional<int> hammer( Character *, item *, const tripoint & );
std::optional<int> hand_crank( Character *, item *, const tripoint & );
Expand Down
2 changes: 2 additions & 0 deletions src/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,8 @@ class vehicle
* @return amount of ammo in the `pseudo_magazine` or 0
*/
int prepare_tool( item &tool ) const;
static bool use_vehicle_tool( vehicle &veh, const tripoint &vp_pos, const itype_id &tool_type,
bool no_invoke = false );
/**
* if \p tool is not an itype with tool != nullptr this returns { itype::NULL_ID(), 0 } pair
* @param tool the item to examine
Expand Down
9 changes: 6 additions & 3 deletions src/vehicle_use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,8 @@ int vehicle::prepare_tool( item &tool ) const
return ammo_count;
}

static bool use_vehicle_tool( vehicle &veh, const tripoint &vp_pos, const itype_id &tool_type )
bool vehicle::use_vehicle_tool( vehicle &veh, const tripoint &vp_pos, const itype_id &tool_type,
bool no_invoke )
{
item tool( tool_type, calendar::turn );
const auto &[ammo_type_id, avail_ammo_amount] = veh.tool_ammo_available( tool_type );
Expand All @@ -1783,7 +1784,9 @@ static bool use_vehicle_tool( vehicle &veh, const tripoint &vp_pos, const itype_
if( tool.ammo_required() > avail_ammo_amount ) {
return false;
}
get_player_character().invoke_item( &tool );
if( !no_invoke ) {
get_player_character().invoke_item( &tool, vp_pos );
}

// HACK: Evil hack incoming
player_activity &act = get_player_character().activity;
Expand Down Expand Up @@ -2415,4 +2418,4 @@ void vehicle::interact_with( const tripoint &p, bool with_pickup )
menu.reset();
build_interact_menu( menu, p, with_pickup );
} while( menu.query() );
}
}
Loading