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 activate_mutation and deactivate_mutation to Character #35227

Merged
merged 10 commits into from
Nov 8, 2019
Merged
Show file tree
Hide file tree
Changes from 5 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
188 changes: 188 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "lightmap.h"
#include "rng.h"
#include "stomach.h"
#include "text_snippets.h"
#include "ui.h"
#include "veh_type.h"
#include "vehicle.h"
Expand Down Expand Up @@ -173,6 +174,7 @@ static const trait_id trait_PYROMANIA( "PYROMANIA" );
static const trait_id trait_ROOTS2( "ROOTS2" );
static const trait_id trait_ROOTS3( "ROOTS3" );
static const trait_id trait_SEESLEEP( "SEESLEEP" );
static const trait_id trait_SELFAWARE( "SELFAWARE" );
static const trait_id trait_SHELL2( "SHELL2" );
static const trait_id trait_SHELL( "SHELL" );
static const trait_id trait_SHOUT2( "SHOUT2" );
Expand Down Expand Up @@ -2906,6 +2908,38 @@ void Character::mod_int_bonus( int nint )
int_cur = std::max( 0, int_max + int_bonus );
}

void Character::print_health() const
{
if( !is_player() ) {
return;
}
int current_health = get_healthy();
if( has_trait( trait_SELFAWARE ) ) {
add_msg_if_player( _( "Your current health value is %d." ), current_health );
}

if( current_health > 0 &&
( has_effect( effect_common_cold ) || has_effect( effect_flu ) ) ) {
return;
}

static const std::map<int, std::string> msg_categories = {
{ -100, "health_horrible" },
{ -50, "health_very_bad" },
{ -10, "health_bad" },
{ 10, "" },
{ 50, "health_good" },
{ 100, "health_very_good" },
{ INT_MAX, "health_great" }
};

auto iter = msg_categories.lower_bound( current_health );
if( iter != msg_categories.end() && !iter->second.empty() ) {
const std::string &msg = SNIPPET.random_from_category( iter->second );
add_msg_if_player( current_health > 0 ? m_good : m_bad, msg );
}
}

namespace io
{
template<>
Expand Down Expand Up @@ -5022,6 +5056,160 @@ void Character::update_stamina( int turns )
set_stamina( std::min( std::max( get_stamina(), 0 ), max_stam ) );
}

bool Character::invoke_item( item *used )
{
return invoke_item( used, pos() );
}

bool Character::invoke_item( item *used, const tripoint &pt )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool Character::invoke_item( item *used, const tripoint &pt )
bool Character::invoke_item( item *, const tripoint &pt )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget removing pt too

{
const auto &use_methods = used->type->use_methods;

if( use_methods.empty() ) {
return false;
} else if( use_methods.size() == 1 ) {
return invoke_item( used, use_methods.begin()->first, pt );
}

uilist umenu;
Copy link
Member

@KorGgenT KorGgenT Nov 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anything with a uilist really should be in avatar. that means this function(the other three should stay) should get something basic in Character and the real function in avatar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function is used by npc, and since the overload with the uilist calls the other overload I don't think I can only move that one.


umenu.text = string_format( _( "What to do with your %s?" ), used->tname() );
umenu.hilight_disabled = true;

for( const auto &e : use_methods ) {
const auto res = e.second.can_call( *this, *used, false, pt );
umenu.addentry_desc( MENU_AUTOASSIGN, res.success(), MENU_AUTOASSIGN, e.second.get_name(),
res.str() );
}

umenu.desc_enabled = std::any_of( umenu.entries.begin(),
umenu.entries.end(), []( const uilist_entry & elem ) {
return !elem.desc.empty();
} );

umenu.query();

int choice = umenu.ret;
if( choice < 0 || choice >= static_cast<int>( use_methods.size() ) ) {
return false;
}

const std::string &method = std::next( use_methods.begin(), choice )->first;

return invoke_item( used, method, pt );
}

bool Character::invoke_item( item *used, const std::string &method )
{
return invoke_item( used, method, pos() );
}

bool Character::invoke_item( item *used, const std::string &method, const tripoint &pt )
{
if( !has_enough_charges( *used, true ) ) {
return false;
}

item *actually_used = used->get_usable_item( method );
if( actually_used == nullptr ) {
debugmsg( "Tried to invoke a method %s on item %s, which doesn't have this method",
method.c_str(), used->tname() );
return false;
}

int charges_used = actually_used->type->invoke( *this->as_player(), *actually_used, pt, method );
if( charges_used == 0 ) {
return false;
}
// Prevent accessing the item as it may have been deleted by the invoked iuse function.

if( used->is_tool() || used->is_medication() || used->get_contained().is_medication() ) {
return consume_charges( *actually_used, charges_used );
} else if( used->is_bionic() || used->is_deployable() || method == "place_trap" ) {
i_rem( used );
return true;
}

return false;
}

bool Character::has_enough_charges( const item &it, bool show_msg ) const
{
if( !it.is_tool() || !it.ammo_required() ) {
return true;
}
if( it.has_flag( "USE_UPS" ) ) {
if( has_charges( "UPS", it.ammo_required() ) || it.ammo_sufficient() ) {
return true;
}
if( show_msg ) {
add_msg_if_player( m_info,
ngettext( "Your %s needs %d charge from some UPS.",
"Your %s needs %d charges from some UPS.",
it.ammo_required() ),
it.tname(), it.ammo_required() );
}
return false;
} else if( !it.ammo_sufficient() ) {
if( show_msg ) {
add_msg_if_player( m_info,
ngettext( "Your %s has %d charge but needs %d.",
"Your %s has %d charges but needs %d.",
it.ammo_remaining() ),
it.tname(), it.ammo_remaining(), it.ammo_required() );
}
return false;
}
return true;
}

bool Character::consume_charges( item &used, int qty )
{
if( qty < 0 ) {
debugmsg( "Tried to consume negative charges" );
return false;
}

if( qty == 0 ) {
return false;
}

if( !used.is_tool() && !used.is_food() && !used.is_medication() ) {
debugmsg( "Tried to consume charges for non-tool, non-food, non-med item" );
return false;
}

// Consume comestibles destroying them if no charges remain
if( used.is_food() || used.is_medication() ) {
used.charges -= qty;
if( used.charges <= 0 ) {
i_rem( &used );
return true;
}
return false;
}

// Tools which don't require ammo are instead destroyed
if( used.is_tool() && !used.ammo_required() ) {
i_rem( &used );
return true;
}

// USE_UPS never occurs on base items but is instead added by the UPS tool mod
if( used.has_flag( "USE_UPS" ) ) {
// With the new UPS system, we'll want to use any charges built up in the tool before pulling from the UPS
// The usage of the item was already approved, so drain item if possible, otherwise use UPS
if( used.charges >= qty ) {
used.ammo_consume( qty, pos() );
} else {
use_charges( "UPS", qty );
}
} else {
used.ammo_consume( std::min( qty, used.ammo_remaining() ), pos() );
}
return false;
}

int Character::item_handling_cost( const item &it, bool penalties, int base_cost ) const
{
int mv = base_cost;
Expand Down
31 changes: 31 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ class Character : public Creature, public visitable<Character>
virtual void mod_per_bonus( int nper );
virtual void mod_int_bonus( int nint );

// Prints message(s) about current health
void print_health() const;

/** Getters for health values exclusive to characters */
virtual int get_healthy() const;
virtual int get_healthy_mod() const;
Expand Down Expand Up @@ -499,6 +502,10 @@ class Character : public Creature, public visitable<Character>
void set_mutation( const trait_id &flag );
void unset_mutation( const trait_id &flag );

// Trigger and disable mutations that can be so toggled.
void activate_mutation( const trait_id &mutation );
void deactivate_mutation( const trait_id &mut );

/** Converts a body_part to an hp_part */
static hp_part bp_to_hp( body_part bp );
/** Converts an hp_part to a body_part */
Expand Down Expand Up @@ -781,6 +788,30 @@ class Character : public Creature, public visitable<Character>
return false;
}

/**
* Asks how to use the item (if it has more than one use_method) and uses it.
* Returns true if it destroys the item. Consumes charges from the item.
* Multi-use items are ONLY supported when all use_methods are iuse_actor!
*/
bool invoke_item( item *, const tripoint &pt );
/** As above, but with a pre-selected method. Debugmsg if this item doesn't have this method. */
bool invoke_item( item *, const std::string &, const tripoint &pt );
/** As above two, but with position equal to current position */
bool invoke_item( item * );
bool invoke_item( item *, const std::string & );

/**
* Has the item enough charges to invoke its use function?
* Also checks if UPS from this player is used instead of item charges.
*/
bool has_enough_charges( const item &it, bool show_msg ) const;

/** Consume charges of a tool or comestible item, potentially destroying it in the process
* @param used item consuming the charges
* @param qty number of charges to consume which must be non-zero
* @return true if item was destroyed */
bool consume_charges( item &used, int qty );

/**
* Calculate (but do not deduct) the number of moves required when handling (e.g. storing, drawing etc.) an item
* @param it Item to calculate handling cost for
Expand Down
4 changes: 2 additions & 2 deletions src/mutation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ bool Character::can_install_cbm_on_bp( const std::vector<body_part> &bps ) const
return can_install;
}

void player::activate_mutation( const trait_id &mut )
void Character::activate_mutation( const trait_id &mut )
{
const mutation_branch &mdata = mut.obj();
auto &tdata = my_mutations[mut];
Expand Down Expand Up @@ -568,7 +568,7 @@ void player::activate_mutation( const trait_id &mut )
}
}

void player::deactivate_mutation( const trait_id &mut )
void Character::deactivate_mutation( const trait_id &mut )
{
my_mutations[mut].powered = false;

Expand Down
Loading