Skip to content

Commit

Permalink
Bulk loading items saves time cost for generic "pick up(g)" process (C…
Browse files Browse the repository at this point in the history
…leverRaven#69244)

* bulk pickup

* fix

* volume limit

* refactor

* refactor
  • Loading branch information
lispcoc authored Nov 12, 2023
1 parent 2a70d7f commit 52b0144
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 11 deletions.
5 changes: 4 additions & 1 deletion src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2177,7 +2177,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 @@ -2210,6 +2211,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 @@ -2225,6 +2227,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

0 comments on commit 52b0144

Please sign in to comment.