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

Fixed segfault when an NPC completes a pickup after a player has alre… #72958

Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c1be0c5
Fixed segfault when an NPC completes a pickup after a player has alre…
Apr 11, 2024
5185bc7
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
5566196
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
7723ed7
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
c2e7e8a
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
12fbd60
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
eeed19b
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
63dd2db
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
a69c722
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
71a8fca
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
13e0bc3
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
3d1183a
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
289ff90
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
ea5af71
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
2d594d6
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
7633581
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
f6606b6
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
16b0ef3
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
3510e41
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
60d183e
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
4ef26e3
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
96c0e51
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
20ff19b
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
ecb546b
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
0b83ab4
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
66764d2
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
8eff9c9
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
d385993
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
1f0f7da
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
f26fb28
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
2445b7c
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
a24958a
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
363774a
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
3701140
Locally linted npcmove.cpp
Apr 11, 2024
8edc26e
Fixed a complaint about if() braces from clang-tidy
Apr 11, 2024
85a4f10
Update src/npcmove.cpp
Levitator0 Apr 11, 2024
f22232f
Fixed another if() brace complaint for clang-tidy
Apr 11, 2024
0483e6f
astyle demanded a space if() {
Apr 11, 2024
92735cf
Comment cleanup per I-am-Erk
Apr 12, 2024
c085cfd
Removed some more comments
Apr 12, 2024
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
7 changes: 6 additions & 1 deletion src/npc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,12 @@ class npc : public Character
// Player orders a friendly NPC to move to this position
std::optional<tripoint_abs_ms> goto_to_this_pos;
int last_seen_player_turn = 0; // Timeout to forgetting
const item *wanted_item = nullptr;

//Safe reference to an item at a specific location which can be checked for subsequent invalidation
//in case the object is destroyed or more than one creature goes for it.
//const item *wanted_item = nullptr;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
item_location wanted_item = {};

tripoint wanted_item_pos; // The square containing an item we want
// These are the coordinates that a guard will return to inside of their goal tripoint
std::optional<tripoint_abs_ms> guard_pos;
Expand Down
61 changes: 35 additions & 26 deletions src/npcmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#include "vehicle.h"
#include "viewer.h"
#include "visitable.h"
#include "vehicle_selector.h"
#include "vpart_position.h"
#include "vpart_range.h"

Expand Down Expand Up @@ -3504,7 +3505,7 @@ void npc::find_item()
}

fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
int best_value = minimum_item_value();
// Not perfect, but has to mirror pickup code
units::volume volume_allowed = volume_capacity() - volume_carried();
Expand All @@ -3514,7 +3515,8 @@ void npc::find_item()
//int range = sight_range( g->light_level( posz() ) );
//range = std::max( 1, std::min( 12, range ) );

const item *wanted = wanted_item;
//Redundant with respect to wanted_item
//item_location wanted = wanted_item;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved

if( volume_allowed <= 0_ml || weight_allowed <= 0_gram ) {
add_msg_debug( debugmode::DF_NPC_ITEMAI, "%s considered picking something up, but no storage left.",
Expand All @@ -3523,23 +3525,27 @@ void npc::find_item()
}

const auto consider_item =
[&wanted, &best_value, this]
[&best_value, this]
( const item & it, const tripoint & p ) {
if( ::good_for_pickup( it, *this, p ) ) {
wanted_item_pos = p;
wanted_item = &it;
wanted = wanted_item;
//wanted_item = &it;
//wanted = wanted_item;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
best_value = has_item_whitelist() ? 1000 : value( it );
return true;
} else {
return false;
}
};
}
};
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved

map &here = get_map();
// Harvest item doesn't exist, so we'll be checking by its name
std::string wanted_name;
const auto consider_terrain =
[ this, volume_allowed, &wanted, &wanted_name, &here ]( const tripoint & p ) {
[ this, volume_allowed, &wanted_name, &here ]( const tripoint & p ) {
// We only want to pick plants when there are no items to pick
if( !has_item_whitelist() || wanted != nullptr || !wanted_name.empty() ||
if( !has_item_whitelist() || wanted_item.get_item() != nullptr || !wanted_name.empty() ||
volume_allowed < 250_ml ) {
return;
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -3566,7 +3572,7 @@ void npc::find_item()
const tripoint abs_p = get_location().raw() - pos() + p;
const int prev_num_items = ai_cache.searched_tiles.get( abs_p, -1 );
// Prefetch the number of items present so we can bail out if we already checked here.
const map_stack m_stack = here.i_at( p );
map_stack m_stack = here.i_at( p );
int num_items = m_stack.size();
const optional_vpart_position vp = here.veh_at( p );
if( vp ) {
Expand All @@ -3577,18 +3583,18 @@ void npc::find_item()
if( prev_num_items == num_items ) {
continue;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}
auto cache_tile = [this, &abs_p, num_items, &wanted]() {
if( wanted == nullptr ) {
auto cache_tile = [this, &abs_p, num_items]() {
if( wanted_item.get_item() == nullptr ) {
ai_cache.searched_tiles.insert( 1000, abs_p, num_items );
}
};
bool can_see = false;
if( here.sees_some_items( p, *this ) && sees( p ) ) {
can_see = true;
for( const item &it : m_stack ) {
consider_item( it, p );
for( item &it : m_stack ) {
if( consider_item( it, p ) )
wanted_item = item_location{ map_cursor{p}, &it };
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}

// Not cached because it gets checked once and isn't expected to change.
if( can_see || sees( p ) ) {
Expand All @@ -3614,14 +3620,15 @@ void npc::find_item()
continue;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved

for( const item &it : cargo->items() ) {
consider_item( it, p );
for( item &it : cargo->items() ) {
if( consider_item( it, p ) )
wanted_item = { vehicle_cursor{ cargo->vehicle(), static_cast<ptrdiff_t>( cargo->part_index() ) }, &it };
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
cache_tile();
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved

if( wanted != nullptr ) {
wanted_name = wanted->tname();
if( wanted_item.get_item() != nullptr ) {
wanted_name = wanted_item->tname();
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}

if( wanted_name.empty() ) {
Expand All @@ -3640,7 +3647,7 @@ void npc::find_item()
if( path.empty() && dist_to_item > 1 ) {
// Item not reachable, let's just totally give up for now
fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved

if( fetching_item && rl_dist( wanted_item_pos, pos() ) > 1 && is_walking_with() ) {
Expand All @@ -3657,7 +3664,7 @@ void npc::pick_up_item()
if( !rules.has_flag( ally_rule::allow_pick_up ) && is_player_ally() ) {
add_msg_debug( debugmode::DF_NPC, "%s::pick_up_item(); Canceling on player's request", get_name() );
fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
mod_moves( -1 );
return;
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -3673,21 +3680,22 @@ void npc::pick_up_item()
// Items we wanted no longer exist and we can see it
// Or player who is leading us doesn't want us to pick it up
fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
move_pause();
add_msg_debug( debugmode::DF_NPC, "Canceling pickup - no items or new zone" );
return;
}

// Check: Is the item owned? Has the situation changed since we last moved? Am 'I' now
// standing in front of the shopkeeper/player that I am about to steal from?
if( wanted_item != nullptr ) {
if( wanted_item ) {
if( !::good_for_pickup( *wanted_item, *this, wanted_item_pos ) ) {
add_msg_debug( debugmode::DF_NPC_ITEMAI,
"%s canceling pickup - situation changed since they decided to take item", get_name() );
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
move_pause();
add_msg_debug( debugmode::DF_NPC, "Canceling pickup - no items or new zone" );
return;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -3710,7 +3718,7 @@ void npc::pick_up_item()
add_msg_debug( debugmode::DF_NPC, "Can't find path" );
// This can happen, always do something
fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
move_pause();
return;
}
Expand All @@ -3729,7 +3737,8 @@ void npc::pick_up_item()
// Note: we didn't actually pick up anything, just spawned items
// but we want the item picker to find new items
fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
move_pause();
return;
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
}
}
Expand Down Expand Up @@ -3759,7 +3768,7 @@ void npc::pick_up_item()
}

fetching_item = false;
wanted_item = nullptr;
wanted_item = {};
has_new_items = true;
}
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved
Levitator0 marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
Loading