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

Move can_reload and rate_action_* functions #41097

Merged
merged 12 commits into from
Jun 7, 2020
10 changes: 0 additions & 10 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,16 +935,6 @@ bool avatar::has_identified( const itype_id &item_id ) const
return items_identified.count( item_id ) > 0;
}

hint_rating avatar::rate_action_read( const item &it ) const
{
if( !it.is_book() ) {
return hint_rating::cant;
}

std::vector<std::string> dummy;
return get_book_reader( it, dummy ) == nullptr ? hint_rating::iffy : hint_rating::good;
}

void avatar::wake_up()
{
if( has_effect( effect_sleep ) ) {
Expand Down
2 changes: 0 additions & 2 deletions src/avatar.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ class avatar : public player
/** Note that we've read a book at least once. **/
bool has_identified( const itype_id &item_id ) const override;

hint_rating rate_action_read( const item &it ) const;

void wake_up();
// Grab furniture / vehicle
void grab( object_type grab_type, const tripoint &grab_point = tripoint_zero );
Expand Down
87 changes: 74 additions & 13 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3600,19 +3600,6 @@ int Character::extraEncumbrance( const layer_level level, const int bp ) const
return encumbrance_cache[bp].layer_penalty_details[static_cast<int>( level )].total;
}

hint_rating Character::rate_action_change_side( const item &it ) const
{
if( !is_worn( it ) ) {
return hint_rating::iffy;
}

if( !it.is_sided() ) {
return hint_rating::cant;
}

return hint_rating::good;
}

bool Character::change_side( item &it, bool interactive )
{
if( !it.swap_side() ) {
Expand Down Expand Up @@ -6734,6 +6721,80 @@ int Character::ammo_count_for( const item &gun )
return ret;
}

bool Character::can_reload( const item &it, const itype_id &ammo ) const
{
if( !it.is_reloadable_with( ammo ) ) {
return false;
}

if( it.is_ammo_belt() ) {
const cata::optional<itype_id> &linkage = it.type->magazine->linkage;
if( linkage && !has_charges( *linkage, 1 ) ) {
return false;
}
}

return true;
}

hint_rating Character::rate_action_reload( const item &it ) const
{
hint_rating res = hint_rating::cant;

// Guns may contain additional reloadable mods so check these first
for( const item *mod : it.gunmods() ) {
switch( rate_action_reload( *mod ) ) {
case hint_rating::good:
return hint_rating::good;

case hint_rating::cant:
continue;

case hint_rating::iffy:
res = hint_rating::iffy;
}
}

if( !it.is_reloadable() ) {
return res;
}

return can_reload( it ) ? hint_rating::good : hint_rating::iffy;
}

hint_rating Character::rate_action_unload( const item &it ) const
{
if( it.is_container() && !it.contents.empty() &&
it.can_unload_liquid() ) {
return hint_rating::good;
}

if( it.has_flag( "NO_UNLOAD" ) ) {
return hint_rating::cant;
}

if( it.magazine_current() ) {
return hint_rating::good;
}

for( const item *e : it.gunmods() ) {
if( e->is_gun() && !e->has_flag( "NO_UNLOAD" ) &&
( e->magazine_current() || e->ammo_remaining() > 0 || e->casings_count() > 0 ) ) {
return hint_rating::good;
}
}

if( it.ammo_types().empty() ) {
return hint_rating::cant;
}

if( it.ammo_remaining() > 0 || it.casings_count() > 0 ) {
return hint_rating::good;
}

return hint_rating::iffy;
}

float Character::rest_quality() const
{
// Just a placeholder for now.
Expand Down
20 changes: 14 additions & 6 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,20 @@ class Character : public Creature, public visitable<Character>
*/
int ammo_count_for( const item &gun );

/**
* Whether a tool or gun is potentially reloadable (optionally considering a specific ammo)
* @param it Thing to be reloaded
* @param ammo if set also check item currently compatible with this specific ammo or magazine
* @note items currently loaded with a detachable magazine are considered reloadable
* @note items with integral magazines are reloadable if free capacity permits (+/- ammo matches)
*/
bool can_reload( const item &it, const itype_id &ammo = itype_id() ) const;

/** Same as `Character::can_reload`, but checks for attached gunmods as well. */
hint_rating rate_action_reload( const item &it ) const;
/** Whether a tool or a gun can be unloaded. */
hint_rating rate_action_unload( const item &it ) const;

/** Maximum thrown range with a given item, taking all active effects into account. */
int throw_range( const item & ) const;
/** Dispersion of a thrown item, against a given target, taking into account whether or not the throw was blind. */
Expand Down Expand Up @@ -2083,8 +2097,6 @@ class Character : public Creature, public visitable<Character>
*/
item &get_consumable_from( item &it ) const;

hint_rating rate_action_eat( const item &it ) const;

/** Get calorie & vitamin contents for a comestible, taking into
* account character traits */
/** Get range of possible nutrient content, for a particular recipe,
Expand Down Expand Up @@ -2120,10 +2132,6 @@ class Character : public Creature, public visitable<Character>
bool change_side( item &it, bool interactive = true );
bool change_side( item_location &loc, bool interactive = true );

/** Used to determine player feedback on item use for the inventory code.
* rates usability lower for non-tools (books, etc.) */
hint_rating rate_action_change_side( const item &it ) const;

bool get_check_encumbrance() {
return check_encumbrance;
}
Expand Down
16 changes: 0 additions & 16 deletions src/consumption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1346,22 +1346,6 @@ bool Character::consume_effects( item &food )
return true;
}

hint_rating Character::rate_action_eat( const item &it ) const
{
if( !can_consume( it ) ) {
return hint_rating::cant;
}

const auto rating = will_eat( it );
if( rating.success() ) {
return hint_rating::good;
} else if( rating.value() == INEDIBLE || rating.value() == INEDIBLE_MUTATION ) {
return hint_rating::cant;
}

return hint_rating::iffy;
}

bool Character::can_feed_reactor_with( const item &it ) const
{
static const std::set<ammotype> acceptable = {{
Expand Down
6 changes: 3 additions & 3 deletions src/crafting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1896,12 +1896,12 @@ void player::consume_tools( const std::vector<tool_comp> &tools, int batch,

ret_val<bool> player::can_disassemble( const item &obj, const inventory &inv ) const
{
const auto &r = recipe_dictionary::get_uncraft( obj.typeId() );

if( !r || obj.has_flag( flag_ETHEREAL_ITEM ) ) {
if( !obj.is_disassemblable() ) {
return ret_val<bool>::make_failure( _( "You cannot disassemble this." ) );
}

const recipe &r = recipe_dictionary::get_uncraft( obj.typeId() );

// check sufficient light
if( lighting_craft_speed_multiplier( r ) == 0.0f ) {
return ret_val<bool>::make_failure( _( "You can't see to craft!" ) );
Expand Down
122 changes: 114 additions & 8 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static const mtype_id mon_manhack( "mon_manhack" );

static const skill_id skill_melee( "melee" );
static const skill_id skill_dodge( "dodge" );
static const skill_id skill_gun( "gun" );
static const skill_id skill_firstaid( "firstaid" );
static const skill_id skill_survival( "survival" );

Expand Down Expand Up @@ -2010,6 +2011,111 @@ static void handle_contents_changed( const item_location &acted_item )
} while( parent.where() == item_location::type::container );
}

static hint_rating rate_action_change_side( const avatar &you, const item &it )
{
if( !it.is_sided() ) {
return hint_rating::cant;
}

return you.is_worn( it ) ? hint_rating::good : hint_rating::iffy;
}

static hint_rating rate_action_disassemble( avatar &you, const item &it )
{
if( you.can_disassemble( it, you.crafting_inventory() ).success() ) {
// Possible right now
return hint_rating::good;
} else if( it.is_disassemblable() ) {
// Potentially possible, but we currently lack requirements
return hint_rating::iffy;
} else {
// Never possible
return hint_rating::cant;
}
}

static hint_rating rate_action_eat( const avatar &you, const item &it )
{
if( !you.can_consume( it ) ) {
return hint_rating::cant;
}

const auto rating = you.will_eat( it );
if( rating.success() ) {
return hint_rating::good;
} else if( rating.value() == INEDIBLE || rating.value() == INEDIBLE_MUTATION ) {
return hint_rating::cant;
}

return hint_rating::iffy;
}

static hint_rating rate_action_mend( const avatar &, const item &it )
{
// TODO: check also if item damage could be repaired via a tool
if( !it.faults.empty() ) {
return hint_rating::good;
}
return it.faults_potential().empty() ? hint_rating::cant : hint_rating::iffy;
}

static hint_rating rate_action_read( const avatar &you, const item &it )
{
if( !it.is_book() ) {
return hint_rating::cant;
}

std::vector<std::string> dummy;
return you.get_book_reader( it, dummy ) ? hint_rating::good : hint_rating::iffy;
}

static hint_rating rate_action_take_off( const avatar &you, const item &it )
{
if( !it.is_armor() || it.has_flag( "NO_TAKEOFF" ) ) {
return hint_rating::cant;
}

if( you.is_worn( it ) ) {
return hint_rating::good;
}

return hint_rating::iffy;
}

static hint_rating rate_action_use( const avatar &you, const item &it )
{
if( it.is_tool() ) {
return it.ammo_sufficient() ? hint_rating::good : hint_rating::iffy;
} else if( it.is_gunmod() ) {
/** @EFFECT_GUN >0 allows rating estimates for gun modifications */
if( you.get_skill_level( skill_gun ) == 0 ) {
return hint_rating::iffy;
} else {
return hint_rating::good;
}
} else if( it.is_food() || it.is_medication() || it.is_book() || it.is_armor() ) {
// The rating is subjective, could be argued as hint_rating::cant or hint_rating::good as well
return hint_rating::iffy;
} else if( it.type->has_use() ) {
return hint_rating::good;
}

return hint_rating::cant;
}

static hint_rating rate_action_wear( const avatar &you, const item &it )
{
if( !it.is_armor() ) {
return hint_rating::cant;
}

if( you.is_worn( it ) ) {
return hint_rating::iffy;
}

return you.can_wear( it ).success() ? hint_rating::good : hint_rating::iffy;
}

/* item submenu for 'i' and '/'
* It use draw_item_info to draw item info and action menu
*
Expand Down Expand Up @@ -2058,20 +2164,20 @@ int game::inventory_item_menu( item_location locThisItem,
break;
}
};
addentry( 'a', pgettext( "action", "activate" ), u.rate_action_use( oThisItem ) );
addentry( 'R', pgettext( "action", "read" ), u.rate_action_read( oThisItem ) );
addentry( 'E', pgettext( "action", "eat" ), u.rate_action_eat( oThisItem ) );
addentry( 'W', pgettext( "action", "wear" ), u.rate_action_wear( oThisItem ) );
addentry( 'a', pgettext( "action", "activate" ), rate_action_use( u, oThisItem ) );
addentry( 'R', pgettext( "action", "read" ), rate_action_read( u, oThisItem ) );
addentry( 'E', pgettext( "action", "eat" ), rate_action_eat( u, oThisItem ) );
addentry( 'W', pgettext( "action", "wear" ), rate_action_wear( u, oThisItem ) );
addentry( 'w', pgettext( "action", "wield" ), hint_rating::good );
addentry( 't', pgettext( "action", "throw" ), hint_rating::good );
addentry( 'c', pgettext( "action", "change side" ), u.rate_action_change_side( oThisItem ) );
addentry( 'T', pgettext( "action", "take off" ), u.rate_action_takeoff( oThisItem ) );
addentry( 'c', pgettext( "action", "change side" ), rate_action_change_side( u, oThisItem ) );
addentry( 'T', pgettext( "action", "take off" ), rate_action_take_off( u, oThisItem ) );
addentry( 'd', pgettext( "action", "drop" ), rate_drop_item );
addentry( 'U', pgettext( "action", "unload" ), u.rate_action_unload( oThisItem ) );
addentry( 'r', pgettext( "action", "reload" ), u.rate_action_reload( oThisItem ) );
addentry( 'p', pgettext( "action", "part reload" ), u.rate_action_reload( oThisItem ) );
addentry( 'm', pgettext( "action", "mend" ), u.rate_action_mend( oThisItem ) );
addentry( 'D', pgettext( "action", "disassemble" ), u.rate_action_disassemble( oThisItem ) );
addentry( 'm', pgettext( "action", "mend" ), rate_action_mend( u, oThisItem ) );
addentry( 'D', pgettext( "action", "disassemble" ), rate_action_disassemble( u, oThisItem ) );
if( oThisItem.has_pockets() ) {
addentry( 'i', pgettext( "action", "insert" ), hint_rating::good );
if( oThisItem.contents.num_item_stacks() > 0 ) {
Expand Down
5 changes: 5 additions & 0 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6550,6 +6550,11 @@ bool item::is_salvageable() const
return !has_flag( flag_NO_SALVAGE );
}

bool item::is_disassemblable() const
{
return recipe_dictionary::get_uncraft( typeId() ) && !has_flag( flag_ETHEREAL_ITEM );
}

bool item::is_craft() const
{
return craft_data_ != nullptr;
Expand Down
Loading