bool item::has_flag(item_flag f) const { bool ret = false; // first check for flags specific to item type // gun flags if (is_gun()) { if (mode == IF_MODE_AUX) { item const* gunmod = inspect_active_gunmod(); if( gunmod != NULL ) ret = gunmod->has_flag(f); if (ret) return ret; } else { for (int i = 0; i < contents.size(); i++) { // Don't report flags from active gunmods for the gun. if (contents[i].has_flag(f) && contents[i].has_flag(IF_MODE_AUX)) { ret = true; return ret; } } } } // other item type flags ret = type->item_flags & mfb(f); if (ret) return ret; // now check for item specific flags ret = item_flags & mfb(f); return ret; }
int item::range(player *p) { if (!is_gun()) return 0; // Just use the raw ammo range for now. if(mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); if(gunmod != NULL && gunmod->curammo != NULL) return gunmod->curammo->range; else return 0; } int ret = (curammo?curammo->range:0); if (has_flag(IF_STR8_DRAW) && p != NULL) { if (p->str_cur < 4) return 0; else if (p->str_cur < 8) ret -= 2 * (8 - p->str_cur); } else if (has_flag(IF_STR10_DRAW) && p != NULL) { if (p->str_cur < 5) return 0; else if (p->str_cur < 10) ret -= 2 * (10 - p->str_cur); } return ret; }
int item::reload_time(player &u) { int ret = 0; if (is_gun()) { it_gun* reloading = dynamic_cast<it_gun*>(type); ret = reloading->reload_time; if (charges == 0) { int spare_mag = has_gunmod(itm_spare_mag); if (spare_mag != -1 && contents[spare_mag].charges > 0) ret -= double(ret) * 0.9; } double skill_bonus = double(u.sklevel[reloading->skill_used]) * .075; if (skill_bonus > .75) skill_bonus = .75; ret -= double(ret) * skill_bonus; } else if (is_tool()) ret = 100 + volume() + weight(); if (has_flag(IF_STR_RELOAD)) ret -= u.str_cur * 20; if (ret < 25) ret = 25; ret += u.encumb(bp_hands) * 30; return ret; }
std::string item::save_info() { if (type == NULL) debugmsg("Tried to save an item with NULL type!"); int ammotmp = 0; /* TODO: This causes a segfault sometimes, even though we check to make sure * curammo isn't NULL. The crashes seem to occur most frequently when saving an * NPC, or when saving map data containing an item an NPC has dropped. */ if (is_gun() && curammo != NULL) ammotmp = curammo->id; if (ammotmp < 0 || ammotmp > num_items) ammotmp = 0; // Saves us from some bugs std::stringstream dump;// (std::stringstream::in | std::stringstream::out); dump << " " << int(invlet) << " " << int(type->id) << " " << int(charges) << " " << int(damage) << " " << int(burnt) << " " << poison << " " << ammotmp << " " << owned << " " << int(bday); if (active) dump << " 1"; else dump << " 0"; if (corpse != NULL) dump << " " << corpse->id; else dump << " -1"; dump << " " << mission_id << " " << player_id; size_t pos = name.find_first_of("\n"); while (pos != std::string::npos) { name.replace(pos, 1, "@@"); pos = name.find_first_of("\n"); } dump << " '" << name << "'"; return dump.str(); }
void item::load_info(std::string data, game *g) { std::stringstream dump; dump << data; int idtmp, ammotmp, lettmp, damtmp, burntmp, acttmp, corp; dump >> lettmp >> idtmp >> charges >> damtmp >> burntmp >> poison >> ammotmp >> owned >> bday >> acttmp >> corp >> mission_id >> player_id; if (corp != -1) corpse = g->mtypes[corp]; else corpse = NULL; getline(dump, name); if (name == " ''") name = ""; else { size_t pos = name.find_first_of("@@"); while (pos != std::string::npos) { name.replace(pos, 2, "\n"); pos = name.find_first_of("@@"); } name = name.substr(2, name.size() - 3); // s/^ '(.*)'$/\1/ } make(g->itypes[idtmp]); invlet = char(lettmp); damage = damtmp; burnt = burntmp; active = false; if (acttmp == 1) active = true; if (is_gun() && ammotmp > 0) curammo = dynamic_cast<it_ammo*>(g->itypes[ammotmp]); else curammo = NULL; }
ammotype item::ammo_type() { if (is_gun()) { it_gun* gun = dynamic_cast<it_gun*>(type); ammotype ret = gun->ammo; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod() && !contents[i].has_flag(IF_MODE_AUX)) { it_gunmod* mod = dynamic_cast<it_gunmod*>(contents[i].type); if (mod->newtype != AT_NULL) ret = mod->newtype; } } return ret; } else if (is_tool()) { it_tool* tool = dynamic_cast<it_tool*>(type); return tool->ammo; } else if (is_ammo()) { it_ammo* amm = dynamic_cast<it_ammo*>(type); return amm->type; } else if (is_gunmod()) { it_gunmod* mod = dynamic_cast<it_gunmod*>(type); return mod->newtype; } return AT_NULL; }
nc_color item::color(player *u) { nc_color ret = c_ltgray; if (active) // Active items show up as yellow ret = c_yellow; else if (is_gun()) { // Guns are green if you are carrying ammo for them ammotype amtype = ammo_type(); if (u->has_ammo(amtype).size() > 0) ret = c_green; } else if (is_ammo()) { // Likewise, ammo is green if you have guns that use it ammotype amtype = ammo_type(); if (u->weapon.is_gun() && u->weapon.ammo_type() == amtype) ret = c_green; else { for (int i = 0; i < u->inv.size(); i++) { if (u->inv[i].is_gun() && u->inv[i].ammo_type() == amtype) { i = u->inv.size(); ret = c_green; } } } } else if (is_book()) { it_book* tmp = dynamic_cast<it_book*>(type); if (tmp->type !=sk_null && tmp->intel <= u->int_cur + u->sklevel[tmp->type] && (tmp->intel == 0 || !u->has_trait(PF_ILLITERATE)) && tmp->req <= u->sklevel[tmp->type] && tmp->level > u->sklevel[tmp->type]) ret = c_ltblue; } return ret; }
int item::volume() { if (typeId() == itm_corpse) { switch (corpse->size) { case MS_TINY: return 2; case MS_SMALL: return 40; case MS_MEDIUM: return 75; case MS_LARGE: return 160; case MS_HUGE: return 600; } } if( is_null() ) return 0; int ret = type->volume; if (count_by_charges()) { ret *= charges; ret /= 100; } if (is_gun()) { for (int i = 0; i < contents.size(); i++) ret += contents[i].volume(); } return ret; }
bool item::is_weap() { if (is_gun() || is_food() || is_ammo() || is_food_container() || is_armor() || is_book() || is_tool()) return false; return (type->melee_dam > 7 || type->melee_cut > 5); }
int item::weapon_value(int skills[num_skill_types]) { if( is_null() ) return 0; int my_value = 0; if (is_gun()) { int gun_value = 14; it_gun* gun = dynamic_cast<it_gun*>(type); gun_value += gun->dmg_bonus; gun_value += int(gun->burst / 2); gun_value += int(gun->clip / 3); gun_value -= int(gun->accuracy / 5); gun_value *= (.5 + (.3 * skills[sk_gun])); gun_value *= (.3 + (.7 * skills[gun->skill_used])); my_value += gun_value; } my_value += int(type->melee_dam * (1 + .3 * skills[sk_bashing] + .1 * skills[sk_melee] )); //debugmsg("My value: (+bash) %d", my_value); my_value += int(type->melee_cut * (1 + .4 * skills[sk_cutting] + .1 * skills[sk_melee] )); //debugmsg("My value: (+cut) %d", my_value); my_value += int(type->m_to_hit * (1.2 + .3 * skills[sk_melee])); //debugmsg("My value: (+hit) %d", my_value); return my_value; }
bool item::is_other() { if( is_null() ) return false; return (!is_gun() && !is_ammo() && !is_armor() && !is_food() && !is_food_container() && !is_tool() && !is_gunmod() && !is_bionic() && !is_book() && !is_weap()); }
int item::has_gunmod(int type) { if (!is_gun()) return -1; for (int i = 0; i < contents.size(); i++) if (contents[i].is_gunmod() && contents[i].typeId() == type) return i; return -1; }
int item::damage_cut() { if (is_gun()) { for (int i = 0; i < contents.size(); i++) { if (contents[i].type->id == itm_bayonet) return contents[i].type->melee_cut; } } return type->melee_cut; }
bool item::has_flag(item_flag f) { if (is_gun()) { for (int i = 0; i < contents.size(); i++) { if (contents[i].has_flag(f)) return true; } } return (type->item_flags & mfb(f)); }
int item::damage_cut() { if (is_gun()) { for (int i = 0; i < contents.size(); i++) { if (contents[i].typeId() == "bayonet") return contents[i].type->melee_cut; } } if( is_null() ) return 0; return type->melee_cut; }
int item::accuracy() { if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->accuracy; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret -= (dynamic_cast<it_gunmod*>(contents[i].type))->accuracy; } ret += damage * 2; return ret; }
int item::burst_size() { if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->burst; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->burst; } if (ret < 0) return 0; return ret; }
int item::recoil(bool with_ammo) { if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->recoil; if (with_ammo && curammo != NULL) ret += curammo->recoil; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->recoil; } return ret; }
int item::num_charges() { if (is_gun()) { if (mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); if (gunmod != NULL) return gunmod->charges; } else { return charges; } } if (is_gunmod() && mode == IF_MODE_AUX) return charges; return 0; }
int item::noise() { if (!is_gun()) return 0; int ret = 0; if (curammo != NULL) ret = curammo->damage * .8; if (ret >= 5) ret += 20; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->loudness; } return ret; }
int item::gun_damage(bool with_ammo) { if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->dmg_bonus; if (with_ammo && curammo != NULL) ret += curammo->damage; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->damage; } ret -= damage * 2; return ret; }
int item::clip_size() { if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->clip; if (gun->ammo != AT_40MM && charges > 0 && curammo->type == AT_40MM) return 1; // M203 mod in use for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) { int bonus = (ret * (dynamic_cast<it_gunmod*>(contents[i].type))->clip) / 100; ret = int(ret + bonus); } } return ret; }
int item::clip_size() { if(is_gunmod() && has_flag(IF_MODE_AUX)) return (dynamic_cast<it_gunmod*>(type))->clip; if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->clip; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod() && !contents[i].has_flag(IF_MODE_AUX)) { int bonus = (ret * (dynamic_cast<it_gunmod*>(contents[i].type))->clip) / 100; ret = int(ret + bonus); } } return ret; }
int item::burst_size() { if (!is_gun()) return 0; // No burst fire for gunmods right now. if(mode == IF_MODE_AUX) return 1; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->burst; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->burst; } if (ret < 0) return 0; return ret; }
int item::volume() { if (type->id == itm_corpse) { switch (corpse->size) { case MS_TINY: return 2; case MS_SMALL: return 40; case MS_MEDIUM: return 75; case MS_LARGE: return 160; case MS_HUGE: return 600; } } int ret = type->volume; if (is_gun()) { for (int i = 0; i < contents.size(); i++) ret += contents[i].volume(); } return type->volume; }
bool item::has_flag(item_flag f) { if (is_gun()) { if (mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); if( gunmod != NULL ) return gunmod->has_flag(f); } else { for (int i = 0; i < contents.size(); i++) { // Don't report flags from active gunmods for the gun. if (contents[i].has_flag(f) && contents[i].has_flag(IF_MODE_AUX)) return true; } } } if( is_null() ) return false; return (type->item_flags & mfb(f)); }
int item::reload_time(player &u) { int ret = 0; if (is_gun()) { it_gun* reloading = dynamic_cast<it_gun*>(type); ret = reloading->reload_time; double skill_bonus = double(u.sklevel[reloading->skill_used]) * .075; if (skill_bonus > .75) skill_bonus = .75; ret -= double(ret) * skill_bonus; } else if (is_tool()) ret = 100 + volume() + weight(); if (has_flag(IF_STR_RELOAD)) ret -= u.str_cur * 20; if (ret < 25) ret = 25; ret += u.encumb(bp_hands) * 30; return ret; }
int item::noise() { if (!is_gun()) return 0; int ret = 0; if(mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); if (gunmod != NULL && gunmod->curammo != NULL) ret = gunmod->curammo->damage; } else if (curammo != NULL) ret = curammo->damage; ret *= .8; if (ret >= 5) ret += 20; if(mode == IF_MODE_AUX) return ret; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->loudness; } return ret; }
int item::recoil(bool with_ammo) { if (!is_gun()) return 0; // Just use the raw ammo recoil for now. if(mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); if (gunmod != NULL && gunmod->curammo != NULL) return gunmod->curammo->recoil; else return 0; } it_gun* gun = dynamic_cast<it_gun*>(type); int ret = gun->recoil; if (with_ammo && curammo != NULL) ret += curammo->recoil; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) ret += (dynamic_cast<it_gunmod*>(contents[i].type))->recoil; } return ret; }
int item::range(player *p) { if (!is_gun()) return 0; it_gun* gun = dynamic_cast<it_gun*>(type); int ret = 0; if (curammo != NULL) ret += curammo->range; if (has_flag(IF_STR8_DRAW) && p != NULL) { if (p->str_cur < 4) return 0; else if (p->str_cur < 8) ret -= 2 * (8 - p->str_cur); } else if (has_flag(IF_STR10_DRAW) && p != NULL) { if (p->str_cur < 5) return 0; else if (p->str_cur < 10) ret -= 2 * (10 - p->str_cur); } return ret; }