Large diffs are not rendered by default.

@@ -11,6 +11,7 @@
#include "artifact.h"
#include "itype.h"
#include "mtype.h"
#include "bodypart.h"

class game;
class player;
@@ -89,7 +90,7 @@ class item : public JsonSerializer, public JsonDeserializer
{
public:
item();
item(const std::string new_type, unsigned int turn, bool rand = true, int handed = 0);
item(const std::string new_type, unsigned int turn, bool rand = true, handedness handed = NONE);
void make_corpse(const std::string new_type, mtype* mt, unsigned int turn);
void make_corpse(const std::string new_type, mtype* mt, unsigned int turn, const std::string &name);
item(std::string itemdata);
@@ -459,7 +460,6 @@ class item : public JsonSerializer, public JsonDeserializer
bool is_tool() const;
bool is_software() const;
bool is_macguffin() const;
bool is_other() const; // Doesn't belong in other categories
bool is_var_veh_part() const;
bool is_artifact() const;

@@ -497,6 +497,105 @@ class item : public JsonSerializer, public JsonDeserializer

std::vector<item> contents;

/**
* Get a material reference to a random material that this item is made of.
* This might return the null-material, you may check this with @ref material_type::is_null.
* Note that this may also return a different material each time it's invoked (if the
* item is made from several materials).
*/
const material_type &get_random_material() const;
/**
* Get the basic (main) material of this item. May return the null-material.
*/
const material_type &get_base_material() const;
/**
* Callback when a player starts wearing the item. The item is already in the worn
* items vector and is called from there.
*/
void on_wear( player &p );
/**
* Callback when a player starts wielding the item. The item is already in the weapon
* slot and is called from there.
*/
void on_wield( player &p );
/**
* Callback when a player starts carrying the item. The item is already in the inventory
* and is called from there. This is not called when the item is added to the inventory
* from worn vector or weapon slot. The item is considered already carried.
*/
void on_pickup( player &p );
/**
* Name of the item type (not the item), with proper plural.
* This is only special when the item itself has a special name ("name" entry in
* @ref item_tags) or is a named corpse.
* It's effectively the same as calling @ref nname with the item type id. Use this when
* the actual item is not meant, for example "The shovel" instead of "Your shovel".
* Or "The jacket is too small", when it applies to all jackets, not just the one the
* character tried to wear).
*/
std::string type_name( unsigned int quantity = 1 ) const;

/**
* @name Armor related functions.
*
* The functions here refer to values from @ref it_armor. They only apply to armor items,
* those items can be worn. The functions are safe to call for any item, for non-armor they
* return a default value.
*/
/*@{*/
/**
* Make this item into a handed item.
* All previous handed info is erased and reset.
* Does nothing if the item is no armor at all. If the item type is not handed, it is only
* reset to be non-handed regardless of the requested handedness.
* @param handed The new handedness. If NONE, the item is made non-handed - all handed
* information is erased and only the default coverage (@ref it_armor::covers) is applied.
*/
void make_handed( handedness handed );
/**
* Returns the warmth value that this item has when worn. See player class for temperature
* related code, or @ref player:::warmth. Returned values should be positive. A value
* of 0 indicates no warmth from this item at all (this is also the default for non-armor).
*/
int get_warmth() const;
/**
* Returns the @ref it_armor::thickness value, or 0 for non-armor. Thickness is are
* relative value that affects the items resistance against bash / cutting damage.
*/
int get_thickness() const;
/**
* Returns the relative coverage that this item has when worn.
* Values range from 0 (not covering anything, or no armor at all) to
* 100 (covering the whole body part). Items that cover more are more likely to absorb
* damage from attacks.
*/
int get_coverage() const;
/**
* Returns the encumbrance value that this item has when worn.
* Returns 0 if this is can not be worn at all.
* Note that this does not include any bonus from the FIT tag or similar, only
* @ref it_armor::encumber.
*/
int get_encumber() const;
/**
* Returns the storage amount (@ref it_armor::storage) that this item provides when worn.
* For non-armor it returns 0. The storage amount increases the volume capacity of the
* character that wears the item.
*/
int get_storage() const;
/**
* Returns the resistance to environmental effects (@ref it_armor::env_resist) that this
* item provides when worn. See @ref player::get_env_resist. Higher values are better.
* For non-armor it returns 0.
*/
int get_env_resist() const;
/**
* Whether this is a power armor item. Not necessarily the main armor, it could be a helmet
* or similar.
*/
bool is_power_armor() const;
/*@}*/

/**
* Recursively check the contents of this item and remove those items
* that match the filter. Note that this function does *not* match
@@ -554,7 +653,7 @@ class item : public JsonSerializer, public JsonDeserializer
bool active; // If true, it has active effects to be processed
signed char damage; // How much damage it's sustained; generally, max is 5
int burnt; // How badly we're burnt
std::bitset<13> covers; // What body parts it covers
std::bitset<num_bp> covers; // What body parts it covers
int bday; // The turn on which it was created
int owned; // UID of NPC owner; 0 = player, -1 = unowned
light_emission light;
@@ -571,16 +670,13 @@ class item : public JsonSerializer, public JsonDeserializer
int mission_id; // Refers to a mission in game's master list
int player_id; // Only give a mission to the right player!
std::map<std::string, std::string> item_vars;
static itype * nullitem();
typedef std::vector<item> t_item_vector;
t_item_vector components;

item clone(bool rand = true);

int add_ammo_to_quiver(player *u, bool isAutoPickup);
int max_charges_from_flag(std::string flagName);
private:
static itype * nullitem_m;
};

std::ostream &operator<<(std::ostream &, const item &);
@@ -989,11 +989,11 @@ void Item_factory::set_qualities_from_json(JsonObject &jo, std::string member,
}
}

std::bitset<13> Item_factory::flags_from_json(JsonObject &jo, const std::string &member,
std::bitset<num_bp> Item_factory::flags_from_json(JsonObject &jo, const std::string &member,
std::string flag_type)
{
//If none is found, just use the standard none action
std::bitset<13> flag = 0;
std::bitset<num_bp> flag = 0;
//Otherwise, grab the right label to look for
if (jo.has_array(member)) {
JsonArray jarr = jo.get_array(member);
@@ -1400,7 +1400,7 @@ use_function Item_factory::use_from_string(std::string function_name)
}
}

void Item_factory::set_flag_by_string(std::bitset<13> &cur_flags, const std::string &new_flag,
void Item_factory::set_flag_by_string(std::bitset<num_bp> &cur_flags, const std::string &new_flag,
const std::string &flag_type)
{
if (flag_type == "bodyparts") {
@@ -237,7 +237,7 @@ class Item_factory
void set_qualities_from_json(JsonObject &jo, std::string member, itype *new_item);

// Currently only used for body part stuff, if used for anything else in the future bitset size may need to be increased.
std::bitset<13> flags_from_json(JsonObject &jo, const std::string &member,
std::bitset<num_bp> flags_from_json(JsonObject &jo, const std::string &member,
std::string flag_type = "");

void set_material_from_json(JsonObject &jo, std::string member, itype *new_item);
@@ -246,7 +246,7 @@ class Item_factory
void set_intvar(std::string tag, unsigned int &var, int min, int max);

//Currently only used to body_part stuff, bitset size might need to be increased in the future
void set_flag_by_string(std::bitset<13> &cur_flags, const std::string &new_flag,
void set_flag_by_string(std::bitset<num_bp> &cur_flags, const std::string &new_flag,
const std::string &flag_type);
void clear();
void init();
@@ -201,22 +201,8 @@ struct itype {

bool has_use() const;
bool can_use( std::string iuse_name ) const;
/** Returns true if is_armor() and covers bp */
bool is_covering(body_part bp) const;
/** Returns true if is_armor() and is sided on bp */
bool is_sided(body_part bp) const;
int invoke( player *p, item *it, bool active, point pos );

std::string dmg_adj(int dam)
{
std::string primary_mat_id = "null";
if (materials.size() > 0) {
primary_mat_id = materials[0];
}

return material_type::find_material(primary_mat_id)->dmg_adj(dam);
}

std::vector<use_function> use_methods;// Special effects of use

itype() : id("null"), price(0), name("none"), name_plural("none"), description(), sym('#'),
@@ -431,8 +417,8 @@ struct it_gunmod : public virtual itype {
};

struct it_armor : public virtual itype {
std::bitset<13> covers; // Bitfield of enum body_part
std::bitset<13> sided; // Bitfield of enum body_part
std::bitset<num_bp> covers; // Bitfield of enum body_part
std::bitset<num_bp> sided; // Bitfield of enum body_part
signed char encumber;
unsigned char coverage;
unsigned char thickness;
@@ -463,23 +449,6 @@ struct it_armor : public virtual itype {
{
return "ARMOR";
}

std::string bash_dmg_verb()
{
std::string chosen_mat_id = "null";
if (materials.size()) {
chosen_mat_id = materials[rng(0, materials.size() - 1)];
}
return material_type::find_material(chosen_mat_id)->bash_dmg_verb();
}
std::string cut_dmg_verb()
{
std::string chosen_mat_id = "null";
if (materials.size()) {
chosen_mat_id = materials[rng(0, materials.size() - 1)];
}
return material_type::find_material(chosen_mat_id)->cut_dmg_verb();
}
};

struct recipe;
@@ -27,25 +27,6 @@ bool itype::can_use( std::string iuse_name ) const
*func ) != use_methods.cend();
}

bool itype::is_covering(body_part bp) const
{
if (!is_armor()) {
return false;
}
const it_armor *armor = dynamic_cast<const it_armor *>(this);
return armor->covers.test(bp);
}


bool itype::is_sided(body_part bp) const
{
if (!is_armor()) {
return false;
}
const it_armor *armor = dynamic_cast<const it_armor *>(this);
return armor->sided.test(bp);
}

int itype::invoke( player *p, item *it, bool active, point pos )
{
int charges_to_use = 0;
@@ -134,7 +134,7 @@ static bool item_inscription(player *p, item *cut, std::string verb, std::string
std::string message = "";
std::string messageprefix = string_format(hasnote ? _("(To delete, input one '.')\n") : "") +
string_format(_("%1$s on the %2$s is: "),
gerund.c_str(), cut->type->nname(1).c_str());
gerund.c_str(), cut->type_name().c_str());
message = string_input_popup(string_format(_("%s what?"), verb.c_str()), 64,
(hasnote ? cut->item_vars["item_note"] : message),
messageprefix, "inscribe_item", 128);
@@ -7862,7 +7862,7 @@ static bool heat_item(player *p)
return false;
}
item *target = heat->is_food_container() ? &(heat->contents[0]) : heat;
if ((target->type->is_food()) && (target->has_flag("EATEN_HOT"))) {
if ((target->is_food()) && (target->has_flag("EATEN_HOT"))) {
p->moves -= 300;
add_msg(_("You heat up the food."));
target->item_tags.insert("HOT");
@@ -7952,7 +7952,7 @@ int iuse::quiver(player *p, item *it, bool, point)
int arrowsRemoved = arrows.charges;
p->add_msg_if_player(ngettext("You remove the %s from the %s.", "You remove the %s from the %s.",
arrowsRemoved),
arrows.type->nname(arrowsRemoved).c_str(), it->tname().c_str());
arrows.type_name( arrowsRemoved ).c_str(), it->tname().c_str());
p->inv.assign_empty_invlet(arrows, false);
p->i_add(arrows);
it->contents.erase(it->contents.begin());
@@ -7969,7 +7969,7 @@ int iuse::quiver(player *p, item *it, bool, point)
return 0;
}

if (!(put->type->is_ammo() && (put->ammo_type() == "arrow" || put->ammo_type() == "bolt"))) {
if (!(put->is_ammo() && (put->ammo_type() == "arrow" || put->ammo_type() == "bolt"))) {
p->add_msg_if_player(m_info, _("Those aren't arrows!"));
return 0;
}
@@ -8013,7 +8013,7 @@ int iuse::quiver(player *p, item *it, bool, point)
arrowsStored = it->contents[0].charges - arrowsStored;
p->add_msg_if_player(ngettext("You store %d %s in your %s.", "You store %d %s in your %s.",
arrowsStored),
arrowsStored, it->contents[0].type->nname(arrowsStored).c_str(), it->tname().c_str());
arrowsStored, it->contents[0].type_name( arrowsStored ).c_str(), it->tname().c_str());
p->moves -= 10 * arrowsStored;
} else {
p->add_msg_if_player(_("Never mind."));
@@ -8034,7 +8034,7 @@ int iuse::holster_pistol(player *p, item *it, bool, point)
}

// make sure we're holstering a pistol
if (put->type->is_gun()) {
if (put->is_gun()) {
it_gun *gun = dynamic_cast<it_gun *>(put->type);
if (!(gun->skill_used == Skill::skill("pistol"))) {
p->add_msg_if_player(m_info, _("The %s isn't a pistol!"), put->tname().c_str());
@@ -8357,7 +8357,7 @@ int iuse::boots(player *p, item *it, bool, point)
p->add_msg_if_player(m_info, _("That isn't a knife!"));
return 0;
}
if (put->type->volume > 5) {
if (put->volume() > 5) {
p->add_msg_if_player(m_info, _("That item does not fit in your boot!"));
return 0;
}
@@ -8990,17 +8990,17 @@ bool einkpc_download_memory_card(player *p, item *eink, item *mc)
eink->item_vars["EIPC_RECIPES"] = "," + rident + ",";

p->add_msg_if_player(m_good, _("You download a recipe for %s into the tablet's memory."),
dummy.type->nname(1).c_str());
dummy.type_name().c_str());
} else {
if (eink->item_vars["EIPC_RECIPES"].find("," + rident + ",") == std::string::npos) {
something_downloaded = true;
eink->item_vars["EIPC_RECIPES"] += rident + ",";

p->add_msg_if_player(m_good, _("You download a recipe for %s into the tablet's memory."),
dummy.type->nname(1).c_str());
dummy.type_name().c_str());
} else {
p->add_msg_if_player(m_good, _("Your tablet already has a recipe for %s."),
dummy.type->nname(1).c_str());
dummy.type_name().c_str());
}
}
}
@@ -9258,8 +9258,7 @@ int iuse::einktabletpc(player *p, item *it, bool t, point pos)

auto recipe = find_recipe( s );
if( recipe ) {
const item dummy( recipe->result, 0 );
rmenu.addentry(k++, true, -1, dummy.type->nname(1).c_str());
rmenu.addentry( k++, true, -1, item::nname( recipe->result ) );
}
}

@@ -9274,10 +9273,9 @@ int iuse::einktabletpc(player *p, item *it, bool t, point pos)

auto recipe = find_recipe( it->item_vars["RECIPE"] );
if( recipe ) {
const item dummy( recipe->result, 0 );
p->add_msg_if_player(m_info,
_("You change the e-ink screen to show a recipe for %s."),
dummy.type->nname(1).c_str());
item::nname( recipe->result ).c_str());
}
}

@@ -10261,17 +10259,12 @@ int iuse::multicooker(player *p, item *it, bool t, point pos)
const inventory &cinv = g->u.crafting_inventory();

if (!cinv.has_amount("soldering_iron", 1)) {
item tmp("soldering_iron", 0);

p->add_msg_if_player(m_warning, _("You need a %s."), tmp.type->nname(1).c_str());
p->add_msg_if_player(m_warning, _("You need a %s."), item::nname( "soldering_iron" ).c_str());
has_tools = false;
}

if (!cinv.has_tools("screwdriver", 1)) {

item tmp("screwdriver", 0);

p->add_msg_if_player(m_warning, _("You need a %s."), tmp.type->nname(1).c_str());
p->add_msg_if_player(m_warning, _("You need a %s."), item::nname( "screwdriver" ).c_str());
has_tools = false;
}

@@ -189,7 +189,7 @@ long unfold_vehicle_iuse::use(player *p, item *it, bool /*t*/, point /*pos*/) co
// Amount == -1 means need one, but don't consume it.
if (!p->has_amount(tool->first, 1)) {
p->add_msg_if_player(_("You need %s to do it!"),
item(tool->first, 0).type->nname(1).c_str());
item::nname( tool->first ).c_str());
return 0;
}
}
@@ -259,8 +259,8 @@ long consume_drug_iuse::use(player *p, item *it, bool, point) const
// Amount == -1 means need one, but don't consume it.
if( !p->has_amount( tool->first, 1 ) ) {
p->add_msg_if_player( _("You need %s to consume %s!"),
item(tool->first, 0).type->nname(1).c_str(),
it->type->nname(1).c_str() );
item::nname( tool->first ).c_str(),
it->type_name( 1 ).c_str() );
return -1;
}
}
@@ -270,8 +270,8 @@ long consume_drug_iuse::use(player *p, item *it, bool, point) const
if( !p->has_charges( consumable->first, (consumable->second == -1) ?
1 : consumable->second ) ) {
p->add_msg_if_player( _("You need %s to consume %s!"),
item(consumable->first, 0).type->nname(1).c_str(),
it->type->nname(1).c_str() );
item::nname( consumable->first ).c_str(),
it->type_name( 1 ).c_str() );
return -1;
}
}
@@ -355,7 +355,7 @@ long place_monster_iuse::use( player *p, item *it, bool, point ) const
amdef.second = 0;
p->add_msg_if_player( m_info,
_( "If you had standard factory-built %s bullets, you could load the %s." ),
ammo_item.type->nname( 2 ).c_str(), newmon.name().c_str() );
ammo_item.type_name( 2 ).c_str(), newmon.name().c_str() );
continue;
}
// Don't load more than the default from the the monster definition.
@@ -364,7 +364,7 @@ long place_monster_iuse::use( player *p, item *it, bool, point ) const
//~ First %s is the ammo item (with plural form and count included), second is the monster name
p->add_msg_if_player( ngettext( "You load %d x %s round into the %s.",
"You load %d x %s rounds into the %s.", ammo_item.charges ),
ammo_item.charges, ammo_item.type->nname( ammo_item.charges ).c_str(),
ammo_item.charges, ammo_item.type_name( ammo_item.charges ).c_str(),
newmon.name().c_str() );
amdef.second = ammo_item.charges;
}
@@ -409,7 +409,7 @@ bool has_power_armor_interface(const player &p)
}

bool has_powersource(const item &i, const player &p) {
if( i.type->is_power_armor() && has_power_armor_interface( p ) && p.power_level > 0 ) {
if( i.is_power_armor() && has_power_armor_interface( p ) && p.power_level > 0 ) {
return true;
}
return p.has_charges( "UPS", 1 );
@@ -430,7 +430,7 @@ long ups_based_armor_actor::use( player *p, item *it, bool t, point ) const
}
if( !it->active && !has_powersource( *it, *p ) ) {
p->add_msg_if_player( m_info, _( "You need some source of power for your %s (a simple UPS will do)." ), it->tname().c_str() );
if( it->type->is_power_armor() ) {
if( it->is_power_armor() ) {
p->add_msg_if_player( m_info, _( "There is also a certain bionic that helps with this kind of armor." ) );
}
return 0;
@@ -1373,13 +1373,14 @@ bool JsonIn::read(std::string &s)
return true;
}

bool JsonIn::read(std::bitset<13> &b)
template<size_t N>
bool JsonIn::read(std::bitset<N> &b)
{
if (!test_bitset()) {
return false;
}
std::string tmp_string = get_string();
b = std::bitset<13> (tmp_string);
b = std::bitset<N> (tmp_string);
return true;
}

@@ -1758,7 +1759,8 @@ void JsonOut::write(const std::string &s)
need_separator = true;
}

void JsonOut::write(const std::bitset<13> &b)
template<size_t N>
void JsonOut::write(const std::bitset<N> &b)
{
if (need_separator) {
write_separator();
@@ -1820,3 +1822,8 @@ void JsonDeserializer::deserialize(std::istream &i)
deserialize(jin);
}

// Need to instantiate those template to make them available for other compilation units.
// Currently only bitsets of size 12 are loaded / stored, if you need other sizes, either explicitly
// instantiate them here, or move the templated read/write functions into the header.
template void JsonOut::write<12>(const std::bitset<12> &);
template bool JsonIn::read<12>(std::bitset<12> &);
@@ -200,7 +200,8 @@ class JsonIn
bool read(float &f);
bool read(double &d);
bool read(std::string &s);
bool read(std::bitset<13> &b);
template<size_t N>
bool read(std::bitset<N> &b);
bool read(JsonDeserializer &j);
// array ~> vector
template <typename T> bool read(std::vector<T> &v)
@@ -424,7 +425,8 @@ class JsonOut
void write(const unsigned long &ul);
void write(const double &f);
void write(const std::string &s);
void write(const std::bitset<13> &b);
template<size_t N>
void write(const std::bitset<N> &b);
void write(const char *cstr)
{
write(std::string(cstr));
@@ -2784,36 +2784,9 @@ void map::spawn_items(const int x, const int y, const std::vector<item> &new_ite
continue;
}
if (new_item.is_armor() && new_item.has_flag("PAIRED") && x_in_y(4, 5)) {
//Clear old side info
it_armor* armor = dynamic_cast<it_armor*>(new_item.type);
new_item.covers = armor->covers;
if (new_item.has_flag("RIGHT")) {
new_item.item_tags.erase("RIGHT");
}
if (new_item.has_flag("LEFT")) {
new_item.item_tags.erase("LEFT");
}
//Clone unsided item
item new_item2 = new_item;
//Add new sides to both items
new_item.item_tags.insert("LEFT");
new_item2.item_tags.insert("RIGHT");
if (new_item.type->is_sided(bp_arm_l)) {
new_item.covers.set(bp_arm_l);
new_item2.covers.set(bp_arm_r);
}
if (new_item.type->is_sided(bp_hand_l)) {
new_item.covers.set(bp_hand_l);
new_item2.covers.set(bp_hand_r);
}
if (new_item.type->is_sided(bp_leg_l)) {
new_item.covers.set(bp_leg_l);
new_item2.covers.set(bp_leg_r);
}
if (new_item.type->is_sided(bp_foot_l)) {
new_item.covers.set(bp_foot_l);
new_item2.covers.set(bp_foot_r);
}
new_item.make_handed( LEFT );
new_item2.make_handed( RIGHT );
add_item_or_charges(x, y, new_item2);
}
add_item_or_charges(x, y, new_item);
@@ -437,7 +437,7 @@ void mdeath::amigara(monster *z)
if (count <= 1) { // We're the last!
g->u.remove_effect("amigara");
add_msg(_("Your obsession with the fault fades away..."));
g->m.add_item_or_charges( z->posx(), z->posy(), item( new_artifact(), calendar::turn ) );
g->m.spawn_artifact( z->posx(), z->posy() );
}
}

@@ -149,8 +149,7 @@ void player::activate_mutation( std::string mut )
traits[mut].powered = false;
return;
} else if (traits[mut].id == "VINES3"){
int handed = 0;
item newit("vine_30", calendar::turn, false, handed);
item newit("vine_30", calendar::turn, false);
if (!can_pickVolume(newit.volume())) { //Accounts for result_mult
add_msg(_("You detach a vine but don't have room to carry it, so you drop it."));
g->m.add_item_or_charges(posx, posy, newit);
@@ -1006,11 +1006,10 @@ bool npc::wear_if_wanted(item it)
return false;
}

it_armor* armor = dynamic_cast<it_armor*>(it.type);
int max_encumb[num_bp] = {2, 3, 3, 4, 3, 3, 3, 2};
bool encumb_ok = true;
for (int i = 0; i < num_bp && encumb_ok; i++) {
if (it.covers.test(i) && encumb(body_part(i)) + armor->encumber > max_encumb[i]) {
if (it.covers.test(i) && encumb(body_part(i)) + it.get_encumber() > max_encumb[i]) {
encumb_ok = false;
}
}
@@ -7,6 +7,7 @@
#include "debug.h"
#include "catacharset.h"
#include "messages.h"
#include "ammo.h"
#include <vector>
#include <string>
#include <sstream>
@@ -3256,8 +3257,7 @@ void parse_tags(std::string &phrase, const player *u, const npc *me)
if (!me->weapon.is_gun())
phrase.replace(fa, l, _("BADAMMO"));
else {
it_gun* gun = dynamic_cast<it_gun*>(me->weapon.type);
phrase.replace(fa, l, ammo_name(gun->ammo));
phrase.replace(fa, l, ammunition_type::find_ammunition_type( me->weapon.ammo_type() )->name() );
}
} else if (tag == "<punc>") {
switch (rng(0, 2)) {

Large diffs are not rendered by default.

@@ -955,10 +955,10 @@ class player : public Character, public JsonSerializer, public JsonDeserializer
bool has_artifact_with(const art_effect_passive effect) const;
bool worn_with_flag( std::string flag ) const;

bool covered_with_flag(const std::string flag, std::bitset<13> parts) const;
bool covered_with_flag_exclusively(const std::string flag, std::bitset<13> parts) const;
bool is_water_friendly(std::bitset<13> parts) const;
bool is_waterproof(std::bitset<13> parts) const;
bool covered_with_flag(const std::string flag, std::bitset<num_bp> parts) const;
bool covered_with_flag_exclusively(const std::string flag, std::bitset<num_bp> parts) const;
bool is_water_friendly(std::bitset<num_bp> parts) const;
bool is_waterproof(std::bitset<num_bp> parts) const;

// has_amount works ONLY for quantity.
// has_charges works ONLY for charges.
@@ -1043,7 +1043,7 @@ std::vector<point> game::target(int &x, int &y, int lowx, int lowy, int hix,
} else {
item *gunmod = u.weapon.active_gunmod();
if (gunmod != NULL) {
mode = gunmod->type->nname(1);
mode = gunmod->type_name();
}
}
if (mode != "") {
@@ -955,7 +955,7 @@ void item::deserialize(JsonObject &data)
int lettmp = 0;
std::string corptmp = "null";
int damtmp = 0;
std::bitset<13> tmp_covers;
std::bitset<num_bp> tmp_covers;

if ( ! data.read( "typeid", idtmp) ) {
debugmsg("Invalid item type: %s ", data.str().c_str() );
@@ -1005,7 +1005,7 @@ void item::deserialize(JsonObject &data)
make(idtmp);

if ( ! data.read( "name", name ) ) {
name = type->nname(1);
name = type_name(1);
}
// Compatiblity for item type changes: for example soap changed from being a generic item
// (item::charges == -1) to comestible (and thereby counted by charges), old saves still have
@@ -1038,39 +1038,11 @@ void item::deserialize(JsonObject &data)
}

data.read( "covers", tmp_covers );
if (is_armor() && tmp_covers.none()) {
it_armor *armor = dynamic_cast<it_armor *>( type );
const auto armor = dynamic_cast<const it_armor *>( type );
if( armor != nullptr && tmp_covers.none() ) {
covers = armor->covers;
if (armor->sided.any()) {
bool left = one_in(2);
if (armor->sided.test(bp_arm_l)) {
if (left == true) {
covers.set(bp_arm_l);
} else {
covers.set(bp_arm_r);
}
}
if (armor->sided.test(bp_hand_l)) {
if (left == true) {
covers.set(bp_hand_l);
} else {
covers.set(bp_hand_r);
}
}
if (armor->sided.test(bp_leg_l)) {
if (left == true) {
covers.set(bp_leg_l);
} else {
covers.set(bp_leg_r);
}
}
if (armor->sided.test(bp_foot_l)) {
if (left == true) {
covers.set(bp_foot_l);
} else {
covers.set(bp_foot_r);
}
}
make_handed( one_in( 2 ) ? LEFT : RIGHT );
}
} else {
covers = tmp_covers;
@@ -1180,7 +1152,7 @@ void item::serialize(JsonOut &json, bool save_contents) const
json.member( "item_vars", item_vars );
}

if ( name != type->nname(1) ) {
if ( name != type_name(1) ) {
json.member( "name", name );
}

@@ -189,12 +189,11 @@ void tutorial_game::post_action(action_id act)
case ACTION_WEAR: {
item it( g->u.last_item, 0 );
if (it.is_armor()) {
it_armor *armor = dynamic_cast<it_armor*>(it.type);
if (armor->coverage >= 2 || armor->thickness >= 2)
if (it.get_coverage() >= 2 || it.get_thickness() >= 2)
add_message(LESSON_WORE_ARMOR);
if (armor->storage >= 20)
if (it.get_storage() >= 20)
add_message(LESSON_WORE_STORAGE);
if (armor->env_resist >= 2)
if (it.get_env_resist() >= 2)
add_message(LESSON_WORE_MASK);
}
} break;
@@ -219,7 +218,7 @@ void tutorial_game::post_action(action_id act)
add_message(LESSON_GOT_TOOL);
else if (it.is_food())
add_message(LESSON_GOT_FOOD);
else if (it.type->melee_dam > 7 || it.type->melee_cut > 5)
else if (it.is_weap())
add_message(LESSON_GOT_WEAPON);

if (g->u.volume_carried() > g->u.volume_capacity() - 2)
@@ -1426,7 +1426,7 @@ int vehicle::install_part( int dx, int dy, const vehicle_part &new_part )
void vehicle_part::properties_from_item( const item &used_item )
{
const vpart_info &vpinfo = vehicle_part_int_types[iid];
if( used_item.type->is_var_veh_part() ) {
if( used_item.is_var_veh_part() ) {
bigness = used_item.bigness;
}
// item damage is 0,1,2,3, or 4. part hp is 1..durability.
@@ -1451,12 +1451,12 @@ item vehicle_part::properties_to_item() const
{
const vpart_info &vpinfo = vehicle_part_int_types[iid];
item tmp( vpinfo.item, calendar::turn );
if( tmp.type->is_var_veh_part() ) {
if( tmp.is_var_veh_part() ) {
tmp.bigness = bigness;
}
// tools go unloaded to prevent user from exploiting this to
// refill their (otherwise not refillable) tools
if( tmp.type->is_tool() ) {
if( tmp.is_tool() ) {
tmp.charges = 0;
}
// Cables get special handling: their target coordinates need to remain