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

Bulk loading items saves time cost for generic "pick up(g)" process #69244

Merged
merged 5 commits into from
Nov 12, 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
5 changes: 4 additions & 1 deletion src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2205,7 +2205,8 @@ void pickup_activity_actor::do_turn( player_activity &, Character &who )
}

// False indicates that the player canceled pickup when met with some prompt
const bool keep_going = Pickup::do_pickup( target_items, quantities, autopickup, stash_successful );
const bool keep_going = Pickup::do_pickup( target_items, quantities, autopickup,
stash_successful, info );

// If there are items left we ran out of moves, so continue the activity
// Otherwise, we are done.
Expand Down Expand Up @@ -2238,6 +2239,7 @@ void pickup_activity_actor::serialize( JsonOut &jsout ) const
jsout.member( "starting_pos", starting_pos );
jsout.member( "stash_successful", stash_successful );
jsout.member( "autopickup", autopickup );
jsout.member( "info", info );

jsout.end_object();
}
Expand All @@ -2253,6 +2255,7 @@ std::unique_ptr<activity_actor> pickup_activity_actor::deserialize( JsonValue &j
data.read( "starting_pos", actor.starting_pos );
data.read( "stash_successful", actor.stash_successful );
data.read( "autopickup", actor.autopickup );
data.read( "info", actor.info );

return actor.clone();
}
Expand Down
2 changes: 2 additions & 0 deletions src/activity_actor_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "itype.h"
#include "item_location.h"
#include "memory_fast.h"
#include "pickup.h"
#include "point.h"
#include "string_id.h"
#include "type_id.h"
Expand Down Expand Up @@ -495,6 +496,7 @@ class pickup_activity_actor : public activity_actor
/** Target items and the quantities thereof */
std::vector<item_location> target_items;
std::vector<int> quantities;
Pickup::pick_info info;

/**
* Position of the character when the activity is started. This is
Expand Down
92 changes: 84 additions & 8 deletions src/pickup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,40 @@ bool Pickup::query_thief()
return false;
}

static bool is_bulk_load( const Pickup::pick_info &lhs, const Pickup::pick_info &rhs )
{
// Check if storage is the same
if( lhs.dst && rhs.dst && lhs.dst->stacks_with( *rhs.dst ) &&
lhs.dst.where() == item_location::type::container &&
rhs.dst.where() == item_location::type::container &&
lhs.dst.parent_item() == rhs.dst.parent_item() ) {
// Check if source is the same
if( lhs.src_type == rhs.src_type ) {
switch( lhs.src_type ) {
case item_location::type::container:
return lhs.src_container == rhs.src_container;
break;
case item_location::type::map:
case item_location::type::vehicle:
return lhs.src_pos == rhs.src_pos;
break;
default:
break;
}
}
}
return false;
}

// Returns false if pickup caused a prompt and the player selected to cancel pickup
static bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool &got_gas,
PickupMap &mapPickup,
bool autopickup, bool &stash_successful, bool &got_frozen_liquid )
PickupMap &mapPickup, bool autopickup, bool &stash_successful, bool &got_frozen_liquid,
Pickup::pick_info &info )
{
Character &player_character = get_player_character();
int moves_taken = loc.obtain_cost( player_character, quantity );
bool picked_up = false;
bool crushed = false;
Pickup::pick_info pre_info( info );

pickup_answer option = CANCEL;

Expand Down Expand Up @@ -290,11 +315,25 @@ static bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool
picked_up = true;
}
}
if( picked_up ) {
// Update info
info.set_dst( added_it );
}
break;
}
}

if( picked_up ) {
info.set_src( loc );
info.total_bulk_volume += loc->volume( false, false, quantity );
if( !is_bulk_load( pre_info, info ) ) {
// Cost to take an item from a container or map
player_character.moves -= loc.obtain_cost( player_character, quantity );
} else {
// Pure cost to handling item excluding overhead.
player_character.moves -= std::max( player_character.item_handling_cost( *loc, true, 0, quantity,
true ), 1 );
}
contents_change_handler handler;
handler.unseal_pocket_containing( loc );
item &orig_it = *loc.get_item();
Expand All @@ -306,7 +345,6 @@ static bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool
} else {
loc.remove_item();
}
player_character.moves -= moves_taken;
player_character.flag_encumbrance();
player_character.invalidate_weight_carried_cache();
}
Expand All @@ -315,7 +353,8 @@ static bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool
}

bool Pickup::do_pickup( std::vector<item_location> &targets, std::vector<int> &quantities,
bool autopickup, bool &stash_successful )
bool autopickup,
bool &stash_successful, Pickup::pick_info &info )
{
bool got_water = false;
bool got_gas = false;
Expand All @@ -340,10 +379,12 @@ bool Pickup::do_pickup( std::vector<item_location> &targets, std::vector<int> &q
debugmsg( "lost target item of ACT_PICKUP" );
continue;
}

problem = !pick_one_up( target, quantity, got_water, got_gas, mapPickup, autopickup,
stash_successful,
got_frozen_liquid );
stash_successful, got_frozen_liquid, info );
if( info.total_bulk_volume > 200_ml ) {
// Bulk loading is not allowed beyond a certain volume
info = Pickup::pick_info();
}
}

if( !mapPickup.empty() ) {
Expand Down Expand Up @@ -438,6 +479,41 @@ int Pickup::cost_to_move_item( const Character &who, const item &it )
return std::min( 400, ret );
}

void Pickup::pick_info::serialize( JsonOut &jsout ) const
{
jsout.start_object();
jsout.member( "total_bulk_volume", total_bulk_volume );
jsout.member( "src_type", static_cast<int>( src_type ) );
jsout.member( "src_pos", src_pos );
jsout.member( "src_container", src_container );
jsout.member( "dst", dst );
jsout.end_object();
}

void Pickup::pick_info::deserialize( const JsonObject &jsobj )
{
int src_type_;
jsobj.read( "total_bulk_volume", total_bulk_volume );
jsobj.read( "src_type", src_type_ );
src_type = static_cast<item_location::type>( src_type_ );
jsobj.read( "src_pos", src_pos );
jsobj.read( "src_container", src_container );
jsobj.read( "dst", dst );
}

void Pickup::pick_info::set_src( const item_location &src_ )
{
// item_location of source may become invalid after the item is moved, so save the information separately.
src_pos = src_.position();
src_container = src_.parent_item();
src_type = src_.where();
}

void Pickup::pick_info::set_dst( const item_location &dst_ )
{
dst = dst_;
}

std::vector<Pickup::pickup_rect> Pickup::pickup_rect::list;

Pickup::pickup_rect *Pickup::pickup_rect::find_by_coordinate( const point &p )
Expand Down
19 changes: 17 additions & 2 deletions src/pickup.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,35 @@
#include <vector>

#include "cuboid_rectangle.h"
#include "item_location.h"
#include "point.h"

class Character;
class item;
class item_location;

namespace Pickup
{
/** Pick up information reminder for bulk loading */
struct pick_info {
pick_info() = default;
void serialize( JsonOut &jsout ) const;
void deserialize( const JsonObject &jsobj );
void set_src( const item_location &src_ );
void set_dst( const item_location &dst_ );

units::volume total_bulk_volume = 0_ml;
item_location::type src_type = item_location::type::invalid;
tripoint src_pos;
item_location src_container;
item_location dst;
};

/**
* Returns `false` if the player was presented a prompt and decided to cancel the pickup.
* `true` in other cases.
*/
bool do_pickup( std::vector<item_location> &targets, std::vector<int> &quantities,
bool autopickup, bool &stash_successful );
bool autopickup, bool &stash_successful, Pickup::pick_info &info );
bool query_thief();

enum from_where : int {
Expand Down