Skip to content

Commit

Permalink
inv_ui: fix accumulated minor issues (#62423)
Browse files Browse the repository at this point in the history
* inv_ui: fix map category toggle and save state

* inv_ui: don't stack identical wield and worn items

* item: don't count contents of corpse pockets

* item: ignore collapsed status for empty items

* trade_ui: fix cat_sort_compare

for real this time. what was I even thinking before?!
  • Loading branch information
andrei8l authored Nov 28, 2022
1 parent fbab752 commit 4034a38
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 50 deletions.
12 changes: 12 additions & 0 deletions data/json/item_category.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@
"name": { "str": "ITEMS WORN" },
"sort_rank": -100
},
{
"id": "INTEGRATED",
"type": "ITEM_CATEGORY",
"name": { "str": "INTEGRATED" },
"sort_rank": -99
},
{
"id": "BIONIC_FUEL_SOURCE",
"type": "ITEM_CATEGORY",
"name": { "str": "BIONIC FUEL SOURCE" },
"sort_rank": -98
},
{
"id": "WEAPON_HELD",
"type": "ITEM_CATEGORY",
Expand Down
5 changes: 4 additions & 1 deletion src/game_inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ void game_menus::inv::common( avatar &you )
// Return to inventory menu on those inputs
static const std::set<int> loop_options = { { '\0', '=', 'f', '<', '>'}};

inventory_pick_selector inv_s( you );
inventory_selector_preset inv_s_p = default_preset;
inv_s_p.save_state = &inventory_ui_default_state;
inventory_pick_selector inv_s( you, inv_s_p );

inv_s.set_title( _( "Inventory" ) );
inv_s.set_hint( string_format(
Expand Down Expand Up @@ -477,6 +479,7 @@ class pickup_inventory_preset : public inventory_selector_preset
explicit pickup_inventory_preset( const Character &you,
bool skip_wield_check = false, bool ignore_liquidcont = false ) : you( you ),
skip_wield_check( skip_wield_check ), ignore_liquidcont( ignore_liquidcont ) {
save_state = &pickup_ui_default_state;
_pk_type = item_pocket::pocket_type::LAST;
}

Expand Down
109 changes: 72 additions & 37 deletions src/inventory_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "cuboid_rectangle.h"
#include "debug.h"
#include "enums.h"
#include "flag.h"
#include "inventory.h"
#include "item.h"
#include "item_category.h"
Expand Down Expand Up @@ -58,6 +59,8 @@
#include <unordered_map>
#include <vector>

static const item_category_id item_category_BIONIC_FUEL_SOURCE( "BIONIC_FUEL_SOURCE" );
static const item_category_id item_category_INTEGRATED( "INTEGRATED" );
static const item_category_id item_category_ITEMS_WORN( "ITEMS_WORN" );
static const item_category_id item_category_WEAPON_HELD( "WEAPON_HELD" );

Expand Down Expand Up @@ -116,6 +119,29 @@ bool is_container( const item_location &loc )
return loc.where() == item_location::type::container;
}

bool is_worn_id( item_category_id const &id )
{
return id == item_category_ITEMS_WORN || id == item_category_INTEGRATED ||
id == item_category_BIONIC_FUEL_SOURCE;
}

item_category const *wielded_worn_category( item_location const &loc, Character const &u )
{
if( loc == u.get_wielded_item() ) {
return &item_category_WEAPON_HELD.obj();
}
if( u.is_worn( *loc ) || ( loc.has_parent() && is_worn_ablative( loc.parent_item(), loc ) ) ) {
if( loc->has_flag( flag_BIONIC_FUEL_SOURCE ) ) {
return &item_category_BIONIC_FUEL_SOURCE.obj();
}
if( loc->has_flag( flag_INTEGRATED ) ) {
return &item_category_INTEGRATED.obj();
}
return &item_category_ITEMS_WORN.obj();
}
return nullptr;
}

} // namespace

bool is_worn_ablative( item_location const &container, item_location const &child )
Expand Down Expand Up @@ -235,19 +261,16 @@ class selection_column_preset : public inventory_selector_preset
}
};

struct inventory_selector_save_state {
public:
inventory_selector::uimode uimode = inventory_selector::uimode::categories;

void serialize( JsonOut &json ) const {
json.start_object();
json.member( "uimode", uimode );
json.end_object();
}
void deserialize( JsonObject const &jo ) {
jo.read( "uimode", uimode );
}
};
void inventory_selector_save_state::serialize( JsonOut &json ) const
{
json.start_object();
json.member( "uimode", uimode );
json.end_object();
}
void inventory_selector_save_state::deserialize( JsonObject const &jo )
{
jo.read( "uimode", uimode );
}

namespace io
{
Expand All @@ -265,16 +288,22 @@ std::string enum_to_string<inventory_selector::uimode>( inventory_selector::uimo
}
} // namespace io

static inventory_selector_save_state inventory_ui_default_state;
static inventory_selector_save_state inventory_sel_default_state{ inventory_selector::uimode::categories };
inventory_selector_save_state inventory_ui_default_state{ inventory_selector::uimode::categories };
inventory_selector_save_state pickup_ui_default_state{ inventory_selector::uimode::hierarchy };

void save_inv_state( JsonOut &json )
{
json.member( "inventory_sel_default_state", inventory_sel_default_state );
json.member( "inventory_ui_state", inventory_ui_default_state );
json.member( "pickup_ui_state", pickup_ui_default_state );
}

void load_inv_state( const JsonObject &jo )
{
jo.read( "inventory_sel_default_state", inventory_sel_default_state );
jo.read( "inventory_ui_state", inventory_ui_default_state );
jo.read( "pickup_ui_state", pickup_ui_default_state );
}

void uistatedata::serialize( JsonOut &json ) const
Expand Down Expand Up @@ -643,7 +672,7 @@ std::string inventory_selector_preset::get_cell_text( const inventory_entry &ent
if( info_display != "NONE" ) {
// if we want additional info for all items or it is worn then add the additional info
if( info_display == "ALL" || ( info_display == "WORN" &&
entry.get_category_ptr()->get_id() == item_category_ITEMS_WORN &&
is_worn_id( entry.get_category_ptr()->get_id() ) &&
actual_item.is_worn_by_player() ) ) {
if( cell_index == 0 && !text.empty() &&
actual_item.is_container() && actual_item.has_unrestricted_pockets() ) {
Expand Down Expand Up @@ -1160,13 +1189,14 @@ inventory_entry *inventory_column::add_entry( const inventory_entry &entry )
item_location entry_item = entry.locations.front();

auto entry_with_loc = std::find_if( entries.begin(),
entries.end(), [&entry_item, this]( const inventory_entry & entry ) {
if( !entry.is_item() ) {
entries.end(), [&entry, &entry_item, this]( const inventory_entry & e ) {
if( !e.is_item() ) {
return false;
}
item_location found_entry_item = entry.locations.front();
item_location found_entry_item = e.locations.front();
// this would be much simpler if item::parent_item() didn't call debugmsg
return entry_item.where() == found_entry_item.where() &&
return e.get_category_ptr() == entry.get_category_ptr() &&
entry_item.where() == found_entry_item.where() &&
entry_item.position() == found_entry_item.position() &&
( ( !entry_item.has_parent() && !found_entry_item.has_parent() ) ||
( entry_item.has_parent() && found_entry_item.has_parent() &&
Expand Down Expand Up @@ -1763,11 +1793,13 @@ void inventory_selector::add_character_items( Character &character )
hierarchy ? &item_category_WEAPON_HELD.obj() : nullptr );
}
for( item_location &worn_item : character.top_items_loc() ) {
item_category const *const custom_cat = wielded_worn_category( worn_item, u );
add_entry_rec( own_gear_column, hierarchy ? own_gear_column : own_inv_column, worn_item,
&item_category_ITEMS_WORN.obj(),
hierarchy ? &item_category_ITEMS_WORN.obj() : nullptr );
custom_cat, hierarchy ? custom_cat : nullptr );
}
if( !hierarchy ) {
own_inv_column.set_indent_entries_override( false );
}
own_inv_column.set_indent_entries_override( false );
}

void inventory_selector::add_map_items( const tripoint &target )
Expand Down Expand Up @@ -1803,14 +1835,17 @@ void inventory_selector::add_vehicle_items( const tripoint &target )
void inventory_selector::_add_map_items( tripoint const &target, item_category const &cat,
item_stack &items, std::function<item_location( item & )> const &floc )
{
item_category const *const custom_cat =
_categorize_map_items ? nullptr : naturalize_category( cat, target );
bool const hierarchy = _uimode == uimode::hierarchy;
item_category const *const custom_cat = hierarchy ? naturalize_category( cat, target ) : nullptr;
inventory_column *const col = _categorize_map_items ? &own_inv_column : &map_column;

for( item &it : items ) {
item_location loc = floc( it );
add_entry_rec( *col, *col, loc, custom_cat, custom_cat );
}
if( !hierarchy ) {
col->set_indent_entries_override( false );
}
}

void inventory_selector::add_nearby_items( int radius )
Expand Down Expand Up @@ -2379,6 +2414,9 @@ void inventory_selector::draw_footer( const catacurses::window &w ) const
wprintz( w, c_light_gray, " >" );
}

right_print( w, getmaxy( w ) - border, border + 1, c_light_gray,
string_format( "< [%s] %s >", ctxt.get_desc( "VIEW_CATEGORY_MODE" ),
io::enum_to_string( _uimode ) ) );
const auto footer = get_footer( mode );
if( !footer.first.empty() ) {
const int string_width = utf8_width( footer.first );
Expand All @@ -2404,7 +2442,8 @@ inventory_selector::inventory_selector( Character &u, const inventory_selector_p
, own_inv_column( preset )
, own_gear_column( preset )
, map_column( preset )
, _uimode( inventory_ui_default_state.uimode )
, _uimode( preset.save_state == nullptr ? inventory_sel_default_state.uimode :
preset.save_state->uimode )
{
ctxt.register_action( "DOWN", to_translation( "Next item" ) );
ctxt.register_action( "UP", to_translation( "Previous item" ) );
Expand Down Expand Up @@ -2441,7 +2480,11 @@ inventory_selector::inventory_selector( Character &u, const inventory_selector_p

inventory_selector::~inventory_selector()
{
inventory_ui_default_state.uimode = _uimode;
if( preset.save_state == nullptr ) {
inventory_sel_default_state.uimode = _uimode;
} else {
preset.save_state->uimode = _uimode;
}
}

bool inventory_selector::empty() const
Expand Down Expand Up @@ -2628,14 +2671,8 @@ void inventory_selector::_categorize( inventory_column &col )
// Remove custom category and allow entries to categorize by their item's category
for( inventory_entry *entry : col.get_entries( return_item, true ) ) {
const item_location loc = entry->any_item();
const item_category *custom_category = nullptr;

// ensure top-level equipped entries don't lose their special categories
if( loc == u.get_wielded_item() ) {
custom_category = &item_category_WEAPON_HELD.obj();
} else if( u.is_worn( *loc ) ) {
custom_category = &item_category_ITEMS_WORN.obj();
}
const item_category *custom_category = wielded_worn_category( loc, u );

entry->set_custom_category( custom_category );
}
Expand All @@ -2658,10 +2695,8 @@ void inventory_selector::_uncategorize( inventory_column &col )
const std::string name = to_upper_case( remove_color_tags( ancestor.describe() ) );
const item_category map_cat( name, no_translation( name ), 100 );
custom_category = naturalize_category( map_cat, ancestor.position() );
} else if( ancestor == u.get_wielded_item() ) {
custom_category = &item_category_WEAPON_HELD.obj();
} else if( u.is_worn( *ancestor ) ) {
custom_category = &item_category_ITEMS_WORN.obj();
} else {
custom_category = wielded_worn_category( ancestor, u );
}

entry->set_custom_category( custom_category );
Expand Down
13 changes: 13 additions & 0 deletions src/inventory_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class inventory_entry

};

struct inventory_selector_save_state;
class inventory_selector_preset
{
public:
Expand Down Expand Up @@ -228,6 +229,8 @@ class inventory_selector_preset
return _indent_entries;
}

inventory_selector_save_state *save_state = nullptr;

protected:
/** Text of the first column (default: item name) */
virtual std::string get_caption( const inventory_entry &entry ) const;
Expand Down Expand Up @@ -1050,4 +1053,14 @@ class inventory_examiner : public inventory_selector

bool is_worn_ablative( item_location const &container, item_location const &child );

struct inventory_selector_save_state {
public:
inventory_selector::uimode uimode = inventory_selector::uimode::categories;

void serialize( JsonOut &json ) const;
void deserialize( JsonObject const &jo );
};
extern inventory_selector_save_state inventory_ui_default_state;
extern inventory_selector_save_state pickup_ui_default_state;

#endif // CATA_SRC_INVENTORY_UI_H
2 changes: 1 addition & 1 deletion src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6742,7 +6742,7 @@ std::string item::display_name( unsigned int quantity ) const

bool item::is_collapsed() const
{
return !contents.get_pockets( []( item_pocket const & pocket ) {
return !contents.empty() && !contents.get_pockets( []( item_pocket const & pocket ) {
return pocket.settings.is_collapsed() && pocket.is_standard_type();
} ).empty();
}
Expand Down
3 changes: 2 additions & 1 deletion src/item_contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,8 @@ size_t item_contents::num_item_stacks() const
size_t num = 0;
for( const item_pocket &pocket : contents ) {
if( pocket.is_type( item_pocket::pocket_type::MOD ) ||
pocket.is_type( item_pocket::pocket_type::MAGAZINE_WELL ) ) {
pocket.is_type( item_pocket::pocket_type::MAGAZINE_WELL ) ||
pocket.is_type( item_pocket::pocket_type::CORPSE ) ) {
// mods and magazine wells aren't really a contained item, which this function gets
continue;
}
Expand Down
18 changes: 8 additions & 10 deletions src/trade_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ point _pane_size()
trade_preset::trade_preset( Character const &you, Character const &trader )
: _u( you ), _trader( trader )
{
save_state = &inventory_ui_default_state;
append_cell(
[&]( item_location const & loc ) {
return format_money( npc_trading::trading_price( _trader, _u, { loc, 1 } ) );
Expand Down Expand Up @@ -85,16 +86,13 @@ std::string trade_preset::get_denial( const item_location &loc ) const

bool trade_preset::cat_sort_compare( const inventory_entry &lhs, const inventory_entry &rhs ) const
{
item_category const *const lcat = lhs.get_category_ptr();
if( lcat->get_id() == item_category_ITEMS_WORN || lcat->get_id() == item_category_WEAPON_HELD ) {
return false;
}
item_category const *const rcat = rhs.get_category_ptr();
if( rcat->get_id() == item_category_ITEMS_WORN || rcat->get_id() == item_category_WEAPON_HELD ) {
return true;
}

return inventory_selector_preset::cat_sort_compare( lhs, rhs );
// sort worn and held categories last we likely don't want to trade them
auto const fudge_rank = []( inventory_entry const & e ) -> int {
item_category_id const cat = e.get_category_ptr()->get_id();
int const rank = e.get_category_ptr()->sort_rank();
return cat != item_category_ITEMS_WORN && cat != item_category_WEAPON_HELD ? rank : rank + 10000;
};
return fudge_rank( lhs ) < fudge_rank( rhs );
}

trade_ui::trade_ui( party_t &you, npc &trader, currency_t cost, std::string title )
Expand Down

0 comments on commit 4034a38

Please sign in to comment.