void mission::load_info(std::istream &data) { int type_id, rewtype, reward_id, rew_skill, tmpfollow, item_num, target_npc_id; std::string rew_item, itemid; data >> type_id; type = mission_type::get( mission_type::from_legacy( type_id ) ); std::string tmpdesc; do { data >> tmpdesc; if (tmpdesc != "<>") { description += tmpdesc + " "; } } while (tmpdesc != "<>"); description = description.substr( 0, description.size() - 1 ); // Ending ' ' bool failed; // Dummy, no one has saves this old data >> failed >> value >> rewtype >> reward_id >> rew_item >> rew_skill >> uid >> target.x >> target.y >> itemid >> item_num >> deadline >> npc_id >> good_fac_id >> bad_fac_id >> step >> tmpfollow >> target_npc_id; target.z = 0; follow_up = mission_type::from_legacy(tmpfollow); reward.type = npc_favor_type(reward_id); reward.item_id = itype_id( rew_item ); reward.skill = Skill::from_legacy_int( rew_skill ); item_id = itype_id(itemid); item_count = int(item_num); }
/** * Reads engine info from a JsonObject. */ void vpart_info::load_engine( cata::optional<vpslot_engine> &eptr, JsonObject &jo, const itype_id &fuel_type ) { vpslot_engine e_info; if( eptr ) { e_info = *eptr; } assign( jo, "backfire_threshold", e_info.backfire_threshold ); assign( jo, "backfire_freq", e_info.backfire_freq ); assign( jo, "noise_factor", e_info.noise_factor ); assign( jo, "damaged_power_factor", e_info.damaged_power_factor ); assign( jo, "m2c", e_info.m2c ); assign( jo, "muscle_power_factor", e_info.muscle_power_factor ); auto excludes = jo.get_array( "exclusions" ); if( !excludes.empty() ) { e_info.exclusions.clear(); while( excludes.has_more() ) { e_info.exclusions.push_back( excludes.next_string() ); } } auto fuel_opts = jo.get_array( "fuel_options" ); if( !fuel_opts.empty() ) { e_info.fuel_opts.clear(); while( fuel_opts.has_more() ) { e_info.fuel_opts.push_back( itype_id( fuel_opts.next_string() ) ); } } else if( e_info.fuel_opts.empty() && fuel_type != itype_id( "null" ) ) { e_info.fuel_opts.push_back( fuel_type ); } eptr = e_info; assert( eptr ); }
static void arm_shooter( npc &shooter, std::string gun_type, std::vector<std::string> mods = {} ) { shooter.remove_weapon(); itype_id gun_id( gun_type ); // Give shooter a loaded gun of the requested type. item &gun = shooter.i_add( item( gun_id ) ); const itype_id ammo_id = gun.ammo_default(); if( gun.magazine_integral() ) { item &ammo = shooter.i_add( item( ammo_id, calendar::turn, gun.ammo_capacity() ) ); REQUIRE( gun.is_reloadable_with( ammo_id ) ); REQUIRE( shooter.can_reload( gun, ammo_id ) ); gun.reload( shooter, item_location( shooter, &ammo ), gun.ammo_capacity() ); } else { const itype_id magazine_id = gun.magazine_default(); item &magazine = shooter.i_add( item( magazine_id ) ); item &ammo = shooter.i_add( item( ammo_id, calendar::turn, magazine.ammo_capacity() ) ); REQUIRE( magazine.is_reloadable_with( ammo_id ) ); REQUIRE( shooter.can_reload( magazine, ammo_id ) ); magazine.reload( shooter, item_location( shooter, &ammo ), magazine.ammo_capacity() ); gun.reload( shooter, item_location( shooter, &magazine ), magazine.ammo_capacity() ); } for( auto mod : mods ) { gun.contents.push_back( item( itype_id( mod ) ) ); } shooter.wield( gun ); }
////////////////// mission.h //// void mission::deserialize(JsonIn &jsin) { JsonObject jo = jsin.get_object(); if (jo.has_member("type_id")) { type = &(g->mission_types[jo.get_int("type_id")]); } jo.read("description", description); jo.read("failed", failed); jo.read("value", value); jo.read("reward", reward); jo.read("uid", uid ); JsonArray ja = jo.get_array("target"); if (ja.size() == 2) { target.x = ja.get_int(0); target.y = ja.get_int(1); } follow_up = mission_id(jo.get_int("follow_up", follow_up)); item_id = itype_id(jo.get_string("item_id", item_id)); jo.read("deadline", deadline ); jo.read("step", step ); jo.read("count", count ); jo.read("npc_id", npc_id ); jo.read("good_fac_id", good_fac_id ); jo.read("bad_fac_id", bad_fac_id ); }
std::vector<std::pair<std::string, std::string>> plot_options::get_descriptions() const { auto options = std::vector<std::pair<std::string, std::string>>(); options.emplace_back( std::make_pair( _( "Plant seed: " ), !seed.empty() ? item::nname( itype_id( seed ) ) : _( "No seed" ) ) ); return options; }
plot_options::query_seed_result plot_options::query_seed() { player &p = g->u; std::vector<item *> seed_inv = p.items_with( []( const item & itm ) { return itm.is_seed(); } ); auto seed_entries = iexamine::get_seed_entries( seed_inv ); seed_entries.emplace( seed_entries.begin(), seed_tuple( itype_id( "null" ), _( "No seed" ), 0 ) ); int seed_index = iexamine::query_seed( seed_entries ); if( seed_index > 0 && seed_index < static_cast<int>( seed_entries.size() ) ) { const auto &seed_entry = seed_entries[seed_index]; const auto &new_seed = std::get<0>( seed_entry ); std::string new_mark; item it = item( itype_id( new_seed ) ); if( it.is_seed() ) { new_mark = it.type->seed->fruit_id; } else { new_mark = seed; } if( new_seed != seed || new_mark != mark ) { seed = new_seed; mark = new_mark; return changed; } else { return successful; } } else if( seed_index == 0 ) { // No seeds if( !seed.empty() || !mark.empty() ) { seed.clear(); mark.clear(); return changed; } else { return successful; } } else { return canceled; } }
std::string plot_options::get_zone_name_suggestion() const { if( !seed.empty() ) { auto type = itype_id( seed ); item it = item( type ); if( it.is_seed() ) { return it.type->seed->plant_name; } else { return item::nname( type ); } } return _( "No seed" ); }
std::vector<item> starting_inv(npc *me, npc_class type, game *g) { int total_space = me->volume_capacity() - 2; std::vector<item> ret; itype_id tmp; // First, if we're wielding a gun, get some ammo for it if (me->weapon.is_gun()) { it_gun *gun = dynamic_cast<it_gun*>(me->weapon.type); tmp = default_ammo(gun->ammo); if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); total_space -= ret[ret.size() - 1].volume(); } while ((type == NC_COWBOY || type == NC_BOUNTY_HUNTER || !one_in(3)) && !one_in(4) && total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); total_space -= ret[ret.size() - 1].volume(); } } if (type == NC_TRADER) { // Traders just have tons of random junk while (total_space > 0 && !one_in(50)) { tmp = itype_id(rng(2, num_items - 1)); // Make sure the item *isn't* in the list of not-okay items // TODO: Make this more efficient for (int i = 0; i < g->mapitems[mi_trader_avoid].size(); i++) { if (tmp == g->mapitems[mi_trader_avoid][i]) { tmp = itype_id(rng(2, num_items - 1)); i = 0; } } if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); ret[ret.size() - 1] = ret[ret.size() - 1].in_its_container(&g->itypes); total_space -= ret[ret.size() - 1].volume(); } } return ret; } int index; items_location from; if (type == NC_DOCTOR) { while(total_space > 0 && !one_in(10)) { if (one_in(3)) from = mi_softdrugs; else from = mi_harddrugs; index = rng(0, g->mapitems[from].size() - 1); tmp = g->mapitems[from][index]; if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); ret[ret.size() - 1] = ret[ret.size() - 1].in_its_container(&g->itypes); total_space -= ret[ret.size() - 1].volume(); } } } // TODO: More specifics. while (total_space > 0 && !one_in(8)) { tmp = itype_id(rng(2, num_items - 1)); if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); ret[ret.size() - 1] = ret[ret.size() - 1].in_its_container(&g->itypes); total_space -= ret[ret.size() - 1].volume(); } } return ret; }
int npc::value(item &it) { int ret = it.price() / 50; skill best = best_skill(); if (best != sk_unarmed) { int weapon_val = it.weapon_value(sklevel) - weapon.weapon_value(sklevel); if (weapon_val > 0) ret += weapon_val; } if (it.is_food()) { it_comest* comest = dynamic_cast<it_comest*>(it.type); if (comest->nutr > 0 || comest->quench > 0) ret++; if (hunger > 40) ret += (comest->nutr + hunger - 40) / 6; if (thirst > 40) ret += (comest->quench + thirst - 40) / 4; } if (it.is_ammo()) { it_ammo* ammo = dynamic_cast<it_ammo*>(it.type); it_gun* gun; if (weapon.is_gun()) { gun = dynamic_cast<it_gun*>(weapon.type); if (ammo->type == gun->ammo) ret += 14; } for (int i = 0; i < inv.size(); i++) { if (inv[i].is_gun()) { gun = dynamic_cast<it_gun*>(inv[i].type); if (ammo->type == gun->ammo) ret += 6; } } } if (it.is_book()) { it_book* book = dynamic_cast<it_book*>(it.type); if (book->intel <= int_cur) { ret += book->fun; if (sklevel[book->type] < book->level && sklevel[book->type] >= book->req) ret += book->level * 3; } } // TODO: Sometimes we want more than one tool? Also we don't want EVERY tool. if (it.is_tool() && !has_amount(itype_id(it.type->id), 1)) { ret += 8; } // TODO: Artifact hunting from relevant factions // ALSO TODO: Bionics hunting from relevant factions if (fac_has_job(FACJOB_DRUGS) && it.is_food() && (dynamic_cast<it_comest*>(it.type))->addict >= 5) ret += 10; if (fac_has_job(FACJOB_DOCTORS) && it.type->id >= itm_bandages && it.type->id <= itm_prozac) ret += 10; if (fac_has_value(FACVAL_BOOKS) && it.is_book()) ret += 14; if (fac_has_job(FACJOB_SCAVENGE)) { // Computed last for _reasons_. ret += 6; ret *= 1.3; } return ret; }
int item::pick_reload_ammo(player &u, bool interactive) { if (!type->is_gun() && !type->is_tool()) { debugmsg("RELOADING NON-GUN NON-TOOL"); return false; } bool has_m203 = false; for (int i = 0; i < contents.size() && !has_m203; i++) { if (contents[i].type->id == itm_m203) has_m203 = true; } std::vector<int> am; // List of indicies of valid ammo if (type->is_gun()) { if (charges > 0) { itype_id aid = itype_id(curammo->id); for (int i = 0; i < u.inv.size(); i++) { if (u.inv[i].type->id == aid) am.push_back(i); } } else { it_gun* tmp = dynamic_cast<it_gun*>(type); am = u.has_ammo(ammo_type()); if (has_m203) { std::vector<int> grenades = u.has_ammo(AT_40MM); for (int i = 0; i < grenades.size(); i++) am.push_back(grenades[i]); } } } else { it_tool* tmp = dynamic_cast<it_tool*>(type); am = u.has_ammo(ammo_type()); } int index = -1; if (am.size() > 1 && interactive) {// More than one option; list 'em and pick WINDOW* w_ammo = newwin(am.size() + 1, 80, 0, 0); if (charges == 0) { char ch; clear(); it_ammo* ammo_type; mvwprintw(w_ammo, 0, 0, _("\ Choose ammo type: Damage Armor Pierce Range Accuracy")); for (int i = 0; i < am.size(); i++) { ammo_type = dynamic_cast<it_ammo*>(u.inv[am[i]].type); mvwaddch(w_ammo, i + 1, 1, i + 'a'); mvwprintw(w_ammo, i + 1, 3, "%s (%d)", u.inv[am[i]].tname().c_str(), u.inv[am[i]].charges); mvwprintw(w_ammo, i + 1, 27, "%d", ammo_type->damage); mvwprintw(w_ammo, i + 1, 38, "%d", ammo_type->pierce); mvwprintw(w_ammo, i + 1, 55, "%d", ammo_type->range); mvwprintw(w_ammo, i + 1, 65, "%d", 100 - ammo_type->accuracy); } refresh(); wrefresh(w_ammo); do ch = getch(); while ((ch < 'a' || ch - 'a' > am.size() - 1) && ch != ' ' && ch != 27); werase(w_ammo); delwin(w_ammo); erase(); if (ch == ' ' || ch == 27) index = -1; else index = am[ch - 'a']; } else {
bool mission::is_complete( const int _npc_id ) const { if( status == mission_status::success ) { return true; } auto &u = g->u; switch( type->goal ) { case MGOAL_GO_TO: { const tripoint cur_pos = g->u.global_omt_location(); return ( rl_dist( cur_pos, target ) <= 1 ); } case MGOAL_GO_TO_TYPE: { const auto cur_ter = overmap_buffer.ter( g->u.global_omt_location() ); return is_ot_type( type->target_id.str(), cur_ter ); } case MGOAL_FIND_ITEM_GROUP: { inventory tmp_inv = u.crafting_inventory(); std::vector<item *> items = std::vector<item *>(); tmp_inv.dump( items ); Group_tag grp_type = type->group_id; itype_id container = type->container_id; bool specific_container_required = container.compare( "null" ) != 0; std::map<itype_id, int> matches = std::map<itype_id, int>(); get_all_item_group_matches( items, grp_type, matches, container, itype_id( "null" ), specific_container_required ); int total_match = std::accumulate( matches.begin(), matches.end(), 0, []( const std::size_t previous, const std::pair<const std::string, std::size_t> &p ) { return previous + p.second; } ); if( total_match >= ( type->item_count ) ) { return true; } } return false; case MGOAL_FIND_ITEM: { if( npc_id != -1 && npc_id != _npc_id ) { return false; } inventory tmp_inv = u.crafting_inventory(); // TODO: check for count_by_charges and use appropriate player::has_* function if( !tmp_inv.has_amount( type->item_id, item_count ) ) { return tmp_inv.has_amount( type->item_id, 1 ) && tmp_inv.has_charges( type->item_id, item_count ); } } return true; case MGOAL_FIND_ANY_ITEM: return u.has_mission_item( uid ) && ( npc_id == -1 || npc_id == _npc_id ); case MGOAL_FIND_MONSTER: if( npc_id != -1 && npc_id != _npc_id ) { return false; } return g->get_creature_if( [&]( const Creature & critter ) { const monster *const mon_ptr = dynamic_cast<const monster *>( &critter ); return mon_ptr && mon_ptr->mission_id == uid; } ); case MGOAL_RECRUIT_NPC: { npc *p = g->find_npc( target_npc_id ); return p != nullptr && p->get_attitude() == NPCATT_FOLLOW; } case MGOAL_RECRUIT_NPC_CLASS: { const auto npcs = overmap_buffer.get_npcs_near_player( 100 ); for( auto &npc : npcs ) { if( npc->myclass == recruit_class && npc->get_attitude() == NPCATT_FOLLOW ) { return true; } } return false; } case MGOAL_FIND_NPC: return npc_id == _npc_id; case MGOAL_ASSASSINATE: return step >= 1; case MGOAL_KILL_MONSTER: return step >= 1; case MGOAL_KILL_MONSTER_TYPE: return g->kill_count( monster_type ) >= kill_count_to_reach; case MGOAL_KILL_MONSTER_SPEC: return g->kill_count( monster_species ) >= kill_count_to_reach; case MGOAL_COMPUTER_TOGGLE: return step >= 1; default: return false; } }
void mission::wrap_up() { auto &u = g->u; if( u.getID() != player_id ) { // This is called from npctalk.cpp, the npc should only offer the option to wrap up mission // that have been assigned to the current player. debugmsg( "mission::wrap_up called, player %d was assigned, but current player is %d", player_id, u.getID() ); } status = mission_status::success; u.on_mission_finished( *this ); std::vector<item_comp> comps; switch( type->goal ) { case MGOAL_FIND_ITEM_GROUP: { inventory tmp_inv = u.crafting_inventory(); std::vector<item *> items = std::vector<item *>(); tmp_inv.dump( items ); Group_tag grp_type = type->group_id; itype_id container = type->container_id; bool specific_container_required = container != "null"; bool remove_container = type->remove_container; itype_id empty_container = type->empty_container; std::map<itype_id, int> matches = std::map<itype_id, int>(); get_all_item_group_matches( items, grp_type, matches, container, itype_id( "null" ), specific_container_required ); std::map<std::string, int>::iterator cnt_it; for( cnt_it = matches.begin(); cnt_it != matches.end(); cnt_it++ ) { comps.push_back( item_comp( cnt_it->first, cnt_it->second ) ); } u.consume_items( comps ); if( remove_container ) { std::vector<item_comp> container_comp = std::vector<item_comp>(); if( empty_container != "null" ) { container_comp.push_back( item_comp( empty_container, type->item_count ) ); u.consume_items( container_comp ); } else { container_comp.push_back( item_comp( container, type->item_count ) ); u.consume_items( container_comp ); } } } break; case MGOAL_FIND_ITEM: comps.push_back( item_comp( type->item_id, item_count ) ); u.consume_items( comps ); break; case MGOAL_FIND_ANY_ITEM: u.remove_mission_items( uid ); break; default: //Suppress warnings break; } type->end( this ); }
std::vector<item> starting_inv(npc *me, npc_class type, game *g) { int total_space = me->volume_capacity() - 2; std::vector<item> ret; ret.push_back( item(g->itypes[itm_lighter], 0) ); itype_id tmp; // First, if we're wielding a gun, get some ammo for it if (me->weapon.is_gun()) { it_gun *gun = dynamic_cast<it_gun*>(me->weapon.type); tmp = default_ammo(gun->ammo); if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); total_space -= ret[ret.size() - 1].volume(); } while ((type == NC_COWBOY || type == NC_BOUNTY_HUNTER || !one_in(3)) && !one_in(4) && total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); total_space -= ret[ret.size() - 1].volume(); } } if (type == NC_TRADER) { // Traders just have tons of random junk while (total_space > 0 && !one_in(50)) { tmp = itype_id(rng(2, num_items - 1)); if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); ret[ret.size() - 1] = ret[ret.size() - 1].in_its_container(&g->itypes); total_space -= ret[ret.size() - 1].volume(); } } } int index; items_location from; if (type == NC_HACKER) { from = mi_npc_hacker; while(total_space > 0 && !one_in(10)) { index = rng(0, g->mapitems[from].size() - 1); tmp = g->mapitems[from][index]; item tmpit(g->itypes[tmp], 0); tmpit = tmpit.in_its_container(&g->itypes); if (total_space >= tmpit.volume()) { ret.push_back(tmpit); total_space -= tmpit.volume(); } } } if (type == NC_DOCTOR) { while(total_space > 0 && !one_in(10)) { if (one_in(3)) from = mi_softdrugs; else from = mi_harddrugs; index = rng(0, g->mapitems[from].size() - 1); tmp = g->mapitems[from][index]; item tmpit(g->itypes[tmp], 0); tmpit = tmpit.in_its_container(&g->itypes); if (total_space >= tmpit.volume()) { ret.push_back(tmpit); total_space -= tmpit.volume(); } } } // TODO: More specifics. while (total_space > 0 && !one_in(8)) { tmp = itype_id(rng(4, num_items - 1)); if (total_space >= g->itypes[tmp]->volume) { ret.push_back(item(g->itypes[tmp], 0)); ret[ret.size() - 1] = ret[ret.size() - 1].in_its_container(&g->itypes); total_space -= ret[ret.size() - 1].volume(); } } for (int i = 0; i < ret.size(); i++) { for (int j = 0; j < g->mapitems[mi_trader_avoid].size(); j++) { if (ret[i].type->id == g->mapitems[mi_trader_avoid][j]) { ret.erase(ret.begin() + i); i--; } } } return ret; }