// Load an item group from JSON void Item_factory::load_item_group(JsonObject &jsobj) { Item_tag group_id = jsobj.get_string("id"); Item_group *current_group; if (m_template_groups.count(group_id) > 0) { current_group = m_template_groups[group_id]; } else { current_group = new Item_group(group_id); m_template_groups[group_id] = current_group; } current_group->m_guns_have_ammo = jsobj.get_bool("guns_have_ammo", current_group->m_guns_have_ammo); JsonArray items = jsobj.get_array("items"); while (items.has_more()) { JsonArray pair = items.next_array(); current_group->add_entry(pair.get_string(0), pair.get_int(1)); } JsonArray groups = jsobj.get_array("groups"); while (groups.has_more()) { JsonArray pair = groups.next_array(); std::string name = pair.get_string(0); int frequency = pair.get_int(1); if (m_template_groups.count(name) == 0) { m_template_groups[name] = new Item_group(name); } current_group->add_group(m_template_groups[name], frequency); } }
void mutation_branch::load_trait_group( JsonObject &jsobj, const trait_group::Trait_group_tag &gid, const std::string &subtype ) { if( subtype != "distribution" && subtype != "collection" && subtype != "old" ) { jsobj.throw_error( "unknown trait group type", "subtype" ); } Trait_group &tg = make_group_or_throw( gid, ( subtype == "collection" || subtype == "old" ) ); // TODO: (sm) Looks like this makes the new code backwards-compatible with the old format. Great if so! if( subtype == "old" ) { JsonArray traits = jsobj.get_array( "traits" ); while( traits.has_more() ) { JsonArray pair = traits.next_array(); tg.add_trait_entry( trait_id( pair.get_string( 0 ) ), pair.get_int( 1 ) ); } return; } // TODO: (sm) Taken from item_factory.cpp almost verbatim. Ensure that these work! if( jsobj.has_member( "entries" ) ) { JsonArray traits = jsobj.get_array( "entries" ); while( traits.has_more() ) { JsonObject subobj = traits.next_object(); add_entry( tg, subobj ); } } if( jsobj.has_member( "traits" ) ) { JsonArray traits = jsobj.get_array( "traits" ); while( traits.has_more() ) { if( traits.test_string() ) { tg.add_trait_entry( trait_id( traits.next_string() ), 100 ); } else if( traits.test_array() ) { JsonArray subtrait = traits.next_array(); tg.add_trait_entry( trait_id( subtrait.get_string( 0 ) ), subtrait.get_int( 1 ) ); } else { JsonObject subobj = traits.next_object(); add_entry( tg, subobj ); } } } if( jsobj.has_member( "groups" ) ) { JsonArray traits = jsobj.get_array( "groups" ); while( traits.has_more() ) { if( traits.test_string() ) { tg.add_group_entry( trait_group::Trait_group_tag( traits.next_string() ), 100 ); } else if( traits.test_array() ) { JsonArray subtrait = traits.next_array(); tg.add_group_entry( trait_group::Trait_group_tag( traits.get_string( 0 ) ), subtrait.get_int( 1 ) ); } else { JsonObject subobj = traits.next_object(); add_entry( tg, subobj ); } } } }
void load_colors(JsonObject &jsobj) { std::string colors[16]={"BLACK","RED","GREEN","BROWN","BLUE","MAGENTA","CYAN","GRAY", "DGRAY","LRED","LGREEN","YELLOW","LBLUE","LMAGENTA","LCYAN","WHITE"}; JsonArray jsarr; for(int c=0;c<16;c++) { jsarr = jsobj.get_array(colors[c]); if(jsarr.size()<3)continue; consolecolors[colors[c]].clear(); consolecolors[colors[c]].push_back(jsarr.get_int(2)); consolecolors[colors[c]].push_back(jsarr.get_int(1)); consolecolors[colors[c]].push_back(jsarr.get_int(0)); } }
////////////////// 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 ); }
void mtype::add_special_attack( JsonArray inner, const std::string & ) { MonsterGenerator &gen = MonsterGenerator::generator(); const std::string name = inner.get_string( 0 ); const auto iter = gen.attack_map.find( name ); if( iter == gen.attack_map.end() ) { inner.throw_error( "Invalid special_attacks" ); } if( special_attacks.count( name ) > 0 ) { special_attacks.erase( name ); const auto iter = std::find( special_attacks_names.begin(), special_attacks_names.end(), name ); if( iter != special_attacks_names.end() ) { special_attacks_names.erase( iter ); } if( test_mode ) { debugmsg( "%s specifies more than one attack of (sub)type %s, ignoring all but the last", id.c_str(), name.c_str() ); } } auto new_attack = mtype_special_attack( iter->second ); new_attack.actor->cooldown = inner.get_int( 1 ); special_attacks.emplace( name, new_attack ); special_attacks_names.push_back( name ); }
void MonsterGenerator::load_special_attacks(mtype *m, JsonObject &jo, std::string member) { m->special_attacks.clear(); // make sure we're running with everything cleared if( !jo.has_array( member ) ) { return; } JsonArray outer = jo.get_array(member); while( outer.has_more() ) { if( outer.test_array() ) { JsonArray inner = outer.next_array(); const auto &aname = inner.get_string(0); if ( attack_map.find(aname) != attack_map.end() ) { auto new_entry = mtype_special_attack( attack_map[aname], inner.get_int(1) ); m->special_attacks[aname] = new_entry; m->special_attacks_names.push_back(aname); } else { inner.throw_error("Invalid special_attacks"); } } else if( outer.test_object() ) { set_attack_from_object( outer.next_object(), m->special_attacks, m->special_attacks_names ); } else { outer.throw_error( "array element is neither array nor object." ); } } }
distribution load_distribution( JsonObject &jo ) { if( jo.has_float( "constant" ) ) { return distribution::constant( jo.get_float( "constant" ) ); } if( jo.has_float( "one_in" ) ) { return distribution::one_in( jo.get_float( "one_in" ) ); } if( jo.has_array( "dice" ) ) { JsonArray jarr = jo.get_array( "dice" ); return distribution::dice_roll( jarr.get_int( 0 ), jarr.get_int( 1 ) ); } if( jo.has_array( "rng" ) ) { JsonArray jarr = jo.get_array( "rng" ); return distribution::rng_roll( jarr.get_int( 0 ), jarr.get_int( 1 ) ); } if( jo.has_array( "sum" ) ) { JsonArray jarr = jo.get_array( "sum" ); JsonObject obj = jarr.next_object(); distribution ret = load_distribution( obj ); while( jarr.has_more() ) { obj = jarr.next_object(); ret = ret + load_distribution( obj ); } return ret; } if( jo.has_array( "mul" ) ) { JsonArray jarr = jo.get_array( "mul" ); JsonObject obj = jarr.next_object(); distribution ret = load_distribution( obj ); while( jarr.has_more() ) { obj = jarr.next_object(); ret = ret * load_distribution( obj ); } return ret; } jo.throw_error( "Invalid distribution" ); return distribution(); }
void VehicleFactory::load_vehicle_group(JsonObject &jo) { const Vehicle_tag group_id = jo.get_string("id"); JsonArray vehicles = jo.get_array("vehicles"); while (vehicles.has_more()) { JsonArray pair = vehicles.next_array(); groups[group_id].add_vehicle(pair.get_string(0), pair.get_int(1)); } }
void VehicleGroup::load(JsonObject &jo) { VehicleGroup &group = vgroups[vgroup_id(jo.get_string("id"))]; JsonArray vehicles = jo.get_array("vehicles"); while (vehicles.has_more()) { JsonArray pair = vehicles.next_array(); group.add_vehicle(vproto_id(pair.get_string(0)), pair.get_int(1)); } }
void MonsterGenerator::load_special_defense(mtype *m, JsonObject &jo, std::string member) { if (jo.has_array(member)) { JsonArray jsarr = jo.get_array(member); m->sp_defense = defense_map[jsarr.get_string(0)]; m->def_chance = jsarr.get_int(1); } if (m->sp_defense == NULL) { m->sp_defense = defense_map["NONE"]; } }
void mtype::add_special_attack( JsonArray inner ) { MonsterGenerator &gen = MonsterGenerator::generator(); const std::string name = inner.get_string( 0 ); const auto iter = gen.attack_map.find( name ); if( iter == gen.attack_map.end() ) { inner.throw_error( "Invalid special_attacks" ); } special_attacks[name] = mtype_special_attack( iter->second, inner.get_int( 1 ) ); special_attacks_names.push_back( name ); }
void tool_comp::load( JsonArray &ja ) { if( ja.test_string() ) { // constructions uses this format: [ "tool", ... ] type = ja.next_string(); count = -1; } else { JsonArray comp = ja.next_array(); type = comp.get_string( 0 ); count = comp.get_int( 1 ); } }
void item_comp::load( JsonArray &ja ) { JsonArray comp = ja.next_array(); type = comp.get_string( 0 ); count = comp.get_int( 1 ); // Recoverable is true by default. if( comp.size() > 2 ) { recoverable = comp.get_string( 2 ) == "NO_RECOVER" ? false : true; } if( count <= 0 ) { ja.throw_error( "item count must be a positive number" ); } }
// Load an item group from JSON void Item_factory::load_item_group(JsonObject &jsobj) { Item_tag group_id = jsobj.get_string("id"); Item_group *current_group = new Item_group(group_id); m_template_groups[group_id] = current_group; JsonArray items = jsobj.get_array("items"); while (items.has_more()) { JsonArray pair = items.next_array(); current_group->add_entry(pair.get_string(0), pair.get_int(1)); } JsonArray groups = jsobj.get_array("groups"); while (groups.has_more()) { JsonArray pair = groups.next_array(); std::string name = pair.get_string(0); int frequency = pair.get_int(1); // we had better have loaded it already! if (m_template_groups.find(name) == m_template_groups.end()) { throw jsobj.line_number() + ": unrecognized group name: " + name; } current_group->add_group(m_template_groups[name], frequency); } }
void MonsterGenerator::load_special_defense(mtype *m, JsonObject &jo, std::string member) { if (jo.has_array(member)) { JsonArray jsarr = jo.get_array(member); if ( defense_map.find(jsarr.get_string(0)) != defense_map.end() ) { m->sp_defense = defense_map[jsarr.get_string(0)]; m->def_chance = jsarr.get_int(1); } else { jsarr.throw_error("Invalid special_when_hit"); } } if (m->sp_defense == NULL) { m->sp_defense = defense_map["NONE"]; } }
void tool_comp::load( JsonArray &ja ) { if( ja.test_string() ) { // constructions uses this format: [ "tool", ... ] type = ja.next_string(); count = -1; } else { JsonArray comp = ja.next_array(); type = comp.get_string( 0 ); count = comp.get_int( 1 ); } if( count == 0 ) { ja.throw_error( "tool count must not be 0" ); } // Note: negative count means charges (of the tool) should be consumed }
void gun_actor::load( JsonObject &obj ) { // Mandatory gun_type = obj.get_string( "gun_type" ); ammo_type = obj.get_string( "ammo_type" ); JsonArray jarr = obj.get_array( "fake_skills" ); while( jarr.has_more() ) { JsonArray cur = jarr.next_array(); fake_skills[skill_id( cur.get_string( 0 ) )] = cur.get_int( 1 ); } range = obj.get_float( "range" ); description = obj.get_string( "description" ); move_cost = obj.get_int( "move_cost" ); targeting_cost = obj.get_int( "targeting_cost" ); // Optional: max_ammo = obj.get_int( "max_ammo", INT_MAX ); fake_str = obj.get_int( "fake_str", 8 ); fake_dex = obj.get_int( "fake_dex", 8 ); fake_int = obj.get_int( "fake_int", 8 ); fake_per = obj.get_int( "fake_per", 8 ); require_targeting_player = obj.get_bool( "require_targeting_player", true ); require_targeting_npc = obj.get_bool( "require_targeting_npc", false ); require_targeting_monster = obj.get_bool( "require_targeting_monster", false ); targeting_timeout = obj.get_int( "targeting_timeout", 8 ); targeting_timeout_extend = obj.get_int( "targeting_timeout_extend", 3 ); burst_limit = obj.get_int( "burst_limit", INT_MAX ); laser_lock = obj.get_bool( "laser_lock", false ); range_no_burst = obj.get_float( "range_no_burst", range + 1 ); if( obj.has_member( "targeting_sound" ) || obj.has_member( "targeting_volume" ) ) { // Both or neither, but not just one targeting_sound = obj.get_string( "targeting_sound" ); targeting_volume = obj.get_int( "targeting_volume" ); } // Sound of no ammo no_ammo_sound = obj.get_string( "no_ammo_sound", "" ); }
void item_comp::load( JsonArray &ja ) { JsonArray comp = ja.next_array(); type = comp.get_string( 0 ); count = comp.get_int( 1 ); size_t handled = 2; while( comp.size() > handled ) { const std::string &flag = comp.get_string( handled++ ); if( flag == "NO_RECOVER" ) { recoverable = false; } else if( flag == "LIST" ) { requirement = true; } } if( count <= 0 ) { ja.throw_error( "item count must be a positive number" ); } }
void MonsterGenerator::load_special_attacks(mtype *m, JsonObject &jo, std::string member) { m->sp_attack.clear(); // make sure we're running with m->sp_freq.clear(); // everything cleared if (jo.has_array(member)) { JsonArray outer = jo.get_array(member); while (outer.has_more()) { JsonArray inner = outer.next_array(); m->sp_attack.push_back(attack_map[inner.get_string(0)]); m->sp_freq.push_back(inner.get_int(1)); } } if (m->sp_attack.empty()) { m->sp_attack.push_back(attack_map["NONE"]); m->sp_freq.push_back(0); } }
void mutation_branch::load_trait_group( JsonArray &entries, const trait_group::Trait_group_tag &gid, const bool is_collection ) { Trait_group &tg = make_group_or_throw( gid, is_collection ); while( entries.has_more() ) { // Backwards-compatibility with old format ["TRAIT", 100] if( entries.test_array() ) { JsonArray subarr = entries.next_array(); trait_id id( subarr.get_string( 0 ) ); std::unique_ptr<Trait_creation_data> ptr( new Single_trait_creator( id, subarr.get_int( 1 ) ) ); tg.add_entry( ptr ); // Otherwise load new format {"trait": ... } or {"group": ...} } else { JsonObject subobj = entries.next_object(); add_entry( tg, subobj ); } } }
void game::load_monitem(JsonObject &jo) { std::vector<std::string> tmp_keys; std::vector<items_location_and_chance> tmp_items; std::string mkey=""; if ( jo.has_string("id") ) { tmp_keys.push_back( jo.get_string("id") ); } else if ( jo.has_array("id") ) { jo.read("id", tmp_keys); } else { jo.throw_error("monitems: requires \"id\": \"monster_id\" or \"id\": [ \"multiple\", \"monster_ids\" ]"); } if ( ! jo.has_array("item_groups") ) { jo.throw_error("monitems: requires \"item_groups\": [ [ \"group_one\", (chance) ], ... ]"); } JsonArray ja = jo.get_array("item_groups"); JsonArray ga; while ( ja.has_more() ) { ga = ja.next_array(); if ( ! ga.has_string(0) || ! ga.has_number(1) ) { jo.throw_error("monitems: item_groups must contain arrays of [ \"string\", number ]"); } tmp_items.push_back( items_location_and_chance( ga.get_string(0), ga.get_int(1) ) ); } for( size_t i = 0; i < tmp_keys.size(); ++i ) { std::map<std::string, std::vector <items_location_and_chance> >::iterator it = monitems.find( tmp_keys[i] ); if ( it == monitems.end() ) { monitems[ tmp_keys[i] ] = tmp_items; } else { it->second.insert( it->second.end(), tmp_items.begin(), tmp_items.end() ); } } }
/* * load player from ginormous json blob */ void player::deserialize(JsonIn &jsin) { JsonObject data = jsin.get_object(); JsonArray parray; json_load_common_variables( data ); std::string prof_ident="(null)"; if ( data.read("profession",prof_ident) && profession::exists(prof_ident) ) { prof = profession::prof(prof_ident); } else { debugmsg("Tried to use non-existent profession '%s'", prof_ident.c_str()); } data.read("activity",activity); data.read("backlog",backlog); data.read("driving_recoil",driving_recoil); data.read("in_vehicle",in_vehicle); data.read("controlling_vehicle",controlling_vehicle); data.read("grab_point", grab_point); std::string grab_typestr="OBJECT_NONE"; if( grab_point.x != 0 || grab_point.y != 0 ) { grab_typestr = "OBJECT_VEHICLE"; data.read( "grab_type", grab_typestr); } if ( obj_type_id.find(grab_typestr) != obj_type_id.end() ) { grab_type = (object_type)obj_type_id[grab_typestr]; } data.read( "blocks_left", num_blocks); data.read( "focus_pool", focus_pool); data.read( "style_selected", style_selected ); data.read( "health", health ); data.read( "mutations", my_mutations ); set_highest_cat_level(); drench_mut_calc(); parray = data.get_array("temp_cur"); if ( parray.size() == num_bp ) { for(int i=0; i < num_bp; i++) { temp_cur[i]=parray.get_int(i); } } else { debugmsg("Error, incompatible temp_cur in save file %s",parray.str().c_str()); } parray = data.get_array("temp_conv"); if ( parray.size() == num_bp ) { for(int i=0; i < num_bp; i++) { temp_conv[i]=parray.get_int(i); } } else { debugmsg("Error, incompatible temp_conv in save file %s",parray.str().c_str()); } parray = data.get_array("frostbite_timer"); if ( parray.size() == num_bp ) { for(int i=0; i < num_bp; i++) { frostbite_timer[i]=parray.get_int(i); } } else { debugmsg("Error, incompatible frostbite_timer in save file %s",parray.str().c_str()); } parray = data.get_array("learned_recipes"); if ( !parray.empty() ) { learned_recipes.clear(); std::string pstr=""; while ( parray.has_more() ) { if ( parray.read_next(pstr) ) { learned_recipes[ pstr ] = recipe_by_name( pstr ); } } } data.read("morale", morale); data.read( "active_mission", active_mission ); data.read( "active_missions", active_missions ); data.read( "failed_missions", failed_missions ); data.read( "completed_missions", completed_missions ); stats & pstats = *lifetime_stats(); data.read("player_stats",pstats); inv.clear(); if ( data.has_member("inv") ) { JsonIn* jip = data.get_raw("inv"); inv.json_load_items( *jip ); } if ( data.has_member("invcache") ) { JsonIn* jip = data.get_raw("invcache"); inv.json_load_invcache( *jip ); } worn.clear(); data.read("worn", worn); weapon.contents.clear(); data.read("weapon", weapon); }
void player::json_load_common_variables(JsonObject & data) { JsonArray parray; // todo/maybe: // std::map<std::string, int*> strmap_common_variables; // void player::init_strmap_common_variables() { // strmap_common_variables["posx"]=&posx; // + all this below and in save_common_variables // } // load: // for(std::map<std::string, int*>::iterator it... // data.read(it->first,it->second); // save: // for(... // json.member( it->first, it->second ); if(!data.read("posx",posx) ) { // uh-oh. debugmsg("BAD PLAYER/NPC JSON: no 'posx'?"); } data.read("posy",posy); data.read("str_cur",str_cur); data.read("str_max",str_max); data.read("dex_cur",dex_cur); data.read("dex_max",dex_max); data.read("int_cur",int_cur); data.read("int_max",int_max); data.read("per_cur",per_cur); data.read("per_max",per_max); data.read("hunger",hunger); data.read("thirst",thirst); data.read("fatigue",fatigue); data.read("stim",stim); data.read("pain",pain); data.read("pkill",pkill); data.read("radiation",radiation); data.read("scent",scent); data.read("moves",moves); data.read("dodges_left",num_dodges); data.read("underwater",underwater); data.read("oxygen",oxygen); data.read("male",male); data.read("cash",cash); data.read("recoil",recoil); parray = data.get_array("hp_cur"); if ( parray.size() == num_hp_parts ) { for(int i=0; i < num_hp_parts; i++) { hp_cur[i] = parray.get_int(i); } } else { debugmsg("Error, incompatible hp_cur in save file '%s'",parray.str().c_str()); } parray = data.get_array("hp_max"); if ( parray.size() == num_hp_parts ) { for(int i=0; i < num_hp_parts; i++) { hp_max[i] = parray.get_int(i); } } else { debugmsg("Error, incompatible hp_max in save file '%s'",parray.str().c_str()); } data.read("power_level",power_level); data.read("max_power_level",max_power_level); data.read("traits",my_traits); if (data.has_object("skills")) { JsonObject pmap = data.get_object("skills"); for (std::vector<Skill*>::iterator aSkill = Skill::skills.begin(); aSkill != Skill::skills.end(); ++aSkill) { if ( pmap.has_object( (*aSkill)->ident() ) ) { pmap.read( (*aSkill)->ident(), skillLevel(*aSkill) ); } else { debugmsg("Load (%s) Missing skill %s","",(*aSkill)->ident().c_str() ); } } } else { debugmsg("Skills[] no bueno"); } data.read("ma_styles",ma_styles); data.read("illness",illness); data.read("effects",effects); data.read("addictions",addictions); data.read("my_bionics",my_bionics); }
void mtype::load( JsonObject &jo ) { MonsterGenerator &gen = MonsterGenerator::generator(); // Name and name plural are not translated here, but when needed in // combination with the actual count in `mtype::nname`. mandatory( jo, was_loaded, "name", name ); // default behaviour: Assume the regular plural form (appending an “s”) optional( jo, was_loaded, "name_plural", name_plural, name + "s" ); mandatory( jo, was_loaded, "description", description, translated_string_reader ); // Have to overwrite the default { "hflesh" } here if( !was_loaded || jo.has_member( "material" ) ) { mat = { jo.get_string( "material" ) }; } optional( jo, was_loaded, "species", species, auto_flags_reader<species_id> {} ); optional( jo, was_loaded, "categories", categories, auto_flags_reader<> {} ); // See monfaction.cpp if( !was_loaded || jo.has_member( "default_faction" ) ) { const auto faction = mfaction_str_id( jo.get_string( "default_faction" ) ); default_faction = monfactions::get_or_add_faction( faction ); } if( !was_loaded || jo.has_member( "symbol" ) ) { sym = jo.get_string( "symbol" ); if( utf8_wrapper( sym ).display_width() != 1 ) { jo.throw_error( "monster symbol should be exactly one console cell width", "symbol" ); } } mandatory( jo, was_loaded, "color", color, color_reader{} ); const typed_flag_reader<decltype( Creature::size_map )> size_reader{ Creature::size_map, "invalid creature size" }; optional( jo, was_loaded, "size", size, size_reader, MS_MEDIUM ); const typed_flag_reader<decltype( gen.phase_map )> phase_reader{ gen.phase_map, "invalid phase id" }; optional( jo, was_loaded, "phase", phase, phase_reader, SOLID ); optional( jo, was_loaded, "diff", difficulty, 0 ); optional( jo, was_loaded, "aggression", agro, 0 ); optional( jo, was_loaded, "morale", morale, 0 ); optional( jo, was_loaded, "speed", speed, 0 ); optional( jo, was_loaded, "attack_cost", attack_cost, 100 ); optional( jo, was_loaded, "melee_skill", melee_skill, 0 ); optional( jo, was_loaded, "melee_dice", melee_dice, 0 ); optional( jo, was_loaded, "melee_dice_sides", melee_sides, 0 ); optional( jo, was_loaded, "melee_cut", melee_cut, 0 ); optional( jo, was_loaded, "dodge", sk_dodge, 0 ); optional( jo, was_loaded, "armor_bash", armor_bash, 0 ); optional( jo, was_loaded, "armor_cut", armor_cut, 0 ); optional( jo, was_loaded, "armor_acid", armor_acid, armor_cut / 2 ); optional( jo, was_loaded, "armor_fire", armor_fire, 0 ); optional( jo, was_loaded, "hp", hp, 0 ); optional( jo, was_loaded, "starting_ammo", starting_ammo ); optional( jo, was_loaded, "luminance", luminance, 0 ); optional( jo, was_loaded, "revert_to_itype", revert_to_itype, "" ); optional( jo, was_loaded, "vision_day", vision_day, 40 ); optional( jo, was_loaded, "vision_night", vision_night, 1 ); optional( jo, was_loaded, "armor_stab", armor_stab, 0.8f * armor_cut ); optional( jo, was_loaded, "attack_effs", atk_effs, mon_attack_effect_reader{} ); if( jo.has_member( "death_drops" ) ) { JsonIn &stream = *jo.get_raw( "death_drops" ); death_drops = item_group::load_item_group( stream, "distribution" ); } const typed_flag_reader<decltype( gen.death_map )> death_reader{ gen.death_map, "invalid monster death function" }; optional( jo, was_loaded, "death_function", dies, death_reader ); if( dies.empty() ) { // TODO: really needed? Is an empty `dies` container not allowed? dies.push_back( mdeath::normal ); } if( jo.has_member( "special_when_hit" ) ) { JsonArray jsarr = jo.get_array( "special_when_hit" ); const auto iter = gen.defense_map.find( jsarr.get_string( 0 ) ); if( iter == gen.defense_map.end() ) { jsarr.throw_error( "Invalid monster defense function" ); } sp_defense = iter->second; def_chance = jsarr.get_int( 1 ); } else if( !was_loaded ) { sp_defense = &mdefense::none; def_chance = 0; } if( !was_loaded || jo.has_member( "special_attacks" ) ) { special_attacks.clear(); special_attacks_names.clear(); add_special_attacks( jo, "special_attacks" ); } else { // Note: special_attacks left as is, new attacks are added to it! // Note: member name prefixes are compatible with those used by generic_typed_reader remove_special_attacks( jo, "remove:special_attacks" ); add_special_attacks( jo, "add:special_attacks" ); } // Disable upgrading when JSON contains `"upgrades": false`, but fallback to the // normal behavior (including error checking) if "upgrades" is not boolean or not `false`. if( jo.has_bool( "upgrades" ) && !jo.get_bool( "upgrades" ) ) { upgrade_group = mongroup_id::NULL_ID; upgrade_into = mtype_id::NULL_ID; upgrades = false; } else if( jo.has_member( "upgrades" ) ) { JsonObject up = jo.get_object( "upgrades" ); optional( up, was_loaded, "half_life", half_life, -1 ); optional( up, was_loaded, "into_group", upgrade_group, auto_flags_reader<mongroup_id> {}, mongroup_id::NULL_ID ); optional( up, was_loaded, "into", upgrade_into, auto_flags_reader<mtype_id> {}, mtype_id::NULL_ID ); upgrades = true; } const typed_flag_reader<decltype( gen.flag_map )> flag_reader{ gen.flag_map, "invalid monster flag" }; optional( jo, was_loaded, "flags", flags, flag_reader ); const typed_flag_reader<decltype( gen.trigger_map )> trigger_reader{ gen.trigger_map, "invalid monster trigger" }; optional( jo, was_loaded, "anger_triggers", anger, trigger_reader ); optional( jo, was_loaded, "placate_triggers", placate, trigger_reader ); optional( jo, was_loaded, "fear_triggers", fear, trigger_reader ); }
void Item_factory::set_qualities_from_json(JsonObject& jo, std::string member, itype* new_item_template) { if ( jo.has_array(member) ) { JsonArray jarr = jo.get_array(member); while (jarr.has_more()){ JsonArray curr = jarr.next_array(); new_item_template->qualities.insert(std::pair<std::string, int>(curr.get_string(0), curr.get_int(1))); } } else { debugmsg("Qualities list for item %s not an array", new_item_template->id.c_str()); } }
void load_construction(JsonObject &jo) { construction *con = new construction; JsonArray temp; con->description = _(jo.get_string("description").c_str()); con->difficulty = jo.get_int("difficulty"); con->time = jo.get_int("time"); temp = jo.get_array("tools"); while (temp.has_more()) { std::vector<component> tool_choices; JsonArray ja = temp.next_array(); while (ja.has_more()) { std::string name = ja.next_string(); tool_choices.push_back(component(name, 1)); } con->tools.push_back(tool_choices); } temp = jo.get_array("components"); while (temp.has_more()) { std::vector<component> comp_choices; JsonArray ja = temp.next_array(); while (ja.has_more()) { JsonArray comp = ja.next_array(); std::string name = comp.get_string(0); int quant = comp.get_int(1); comp_choices.push_back(component(name, quant)); } con->components.push_back(comp_choices); } con->pre_terrain = jo.get_string("pre_terrain", ""); if (con->pre_terrain.size() > 1 && con->pre_terrain[0] == 'f' && con->pre_terrain[1] == '_') { con->pre_is_furniture = true; } else { con->pre_is_furniture = false; } con->post_terrain = jo.get_string("post_terrain", ""); if (con->post_terrain.size() > 1 && con->post_terrain[0] == 'f' && con->post_terrain[1] == '_') { con->post_is_furniture = true; } else { con->post_is_furniture = false; } con->pre_flags = jo.get_tags("pre_flags"); std::string prefunc = jo.get_string("pre_special", ""); if (prefunc == "check_empty") { con->pre_special = &construct::check_empty; } else if (prefunc == "check_support") { con->pre_special = &construct::check_support; } else { // should probably print warning if not "" con->pre_special = &construct::check_nothing; } std::string postfunc = jo.get_string("post_special", ""); if (postfunc == "done_tree") { con->post_special = &construct::done_tree; } else if (postfunc == "done_trunk_log") { con->post_special = &construct::done_trunk_log; } else if (postfunc == "done_trunk_plank") { con->post_special = &construct::done_trunk_plank; } else if (postfunc == "done_vehicle") { con->post_special = &construct::done_vehicle; } else if (postfunc == "done_deconstruct") { con->post_special = &construct::done_deconstruct; } else { // ditto, should probably warn here con->post_special = &construct::done_nothing; } con->id = constructions.size(); constructions.push_back(con); constructions_by_desc[con->description].push_back(con); }
void mtype::load( JsonObject &jo, const std::string &src ) { bool strict = src == "dda"; MonsterGenerator &gen = MonsterGenerator::generator(); // Name and name plural are not translated here, but when needed in // combination with the actual count in `mtype::nname`. mandatory( jo, was_loaded, "name", name ); // default behavior: Assume the regular plural form (appending an “s”) optional( jo, was_loaded, "name_plural", name_plural, name + "s" ); optional( jo, was_loaded, "description", description ); optional( jo, was_loaded, "material", mat, auto_flags_reader<material_id> {} ); optional( jo, was_loaded, "species", species, auto_flags_reader<species_id> {} ); optional( jo, was_loaded, "categories", categories, auto_flags_reader<> {} ); // See monfaction.cpp if( !was_loaded || jo.has_member( "default_faction" ) ) { const auto faction = mfaction_str_id( jo.get_string( "default_faction" ) ); default_faction = monfactions::get_or_add_faction( faction ); } if( !was_loaded || jo.has_member( "symbol" ) ) { sym = jo.get_string( "symbol" ); if( utf8_wrapper( sym ).display_width() != 1 ) { jo.throw_error( "monster symbol should be exactly one console cell width", "symbol" ); } } if( was_loaded && jo.has_member( "copy-from" ) && looks_like.empty() ) { looks_like = jo.get_string( "copy-from" ); } if( jo.has_member( "looks_like" ) ) { looks_like = jo.get_string( "looks_like" ); } assign( jo, "color", color ); const typed_flag_reader<decltype( Creature::size_map )> size_reader{ Creature::size_map, "invalid creature size" }; optional( jo, was_loaded, "size", size, size_reader, MS_MEDIUM ); const typed_flag_reader<decltype( gen.phase_map )> phase_reader{ gen.phase_map, "invalid phase id" }; optional( jo, was_loaded, "phase", phase, phase_reader, SOLID ); assign( jo, "diff", difficulty, strict, 0 ); assign( jo, "hp", hp, strict, 1 ); assign( jo, "speed", speed, strict, 0 ); assign( jo, "aggression", agro, strict, -100, 100 ); assign( jo, "morale", morale, strict ); assign( jo, "attack_cost", attack_cost, strict, 0 ); assign( jo, "melee_skill", melee_skill, strict, 0 ); assign( jo, "melee_dice", melee_dice, strict, 0 ); assign( jo, "melee_dice_sides", melee_sides, strict, 0 ); assign( jo, "dodge", sk_dodge, strict, 0 ); assign( jo, "armor_bash", armor_bash, strict, 0 ); assign( jo, "armor_cut", armor_cut, strict, 0 ); assign( jo, "armor_stab", armor_stab, strict, 0 ); assign( jo, "armor_acid", armor_acid, strict, 0 ); assign( jo, "armor_fire", armor_fire, strict, 0 ); assign( jo, "vision_day", vision_day, strict, 0 ); assign( jo, "vision_night", vision_night, strict, 0 ); optional( jo, was_loaded, "starting_ammo", starting_ammo ); optional( jo, was_loaded, "luminance", luminance, 0 ); optional( jo, was_loaded, "revert_to_itype", revert_to_itype, "" ); optional( jo, was_loaded, "attack_effs", atk_effs, mon_attack_effect_reader{} ); // TODO: make this work with `was_loaded` if( jo.has_array( "melee_damage" ) ) { JsonArray arr = jo.get_array( "melee_damage" ); melee_damage = load_damage_instance( arr ); } else if( jo.has_object( "melee_damage" ) ) { melee_damage = load_damage_instance( jo ); } if( jo.has_int( "melee_cut" ) ) { int bonus_cut = jo.get_int( "melee_cut" ); melee_damage.add_damage( DT_CUT, bonus_cut ); } if( jo.has_member( "death_drops" ) ) { JsonIn &stream = *jo.get_raw( "death_drops" ); death_drops = item_group::load_item_group( stream, "distribution" ); } assign( jo, "harvest", harvest, strict ); const typed_flag_reader<decltype( gen.death_map )> death_reader{ gen.death_map, "invalid monster death function" }; optional( jo, was_loaded, "death_function", dies, death_reader ); if( dies.empty() ) { // TODO: really needed? Is an empty `dies` container not allowed? dies.push_back( mdeath::normal ); } assign( jo, "emit_fields", emit_fields ); if( jo.has_member( "special_when_hit" ) ) { JsonArray jsarr = jo.get_array( "special_when_hit" ); const auto iter = gen.defense_map.find( jsarr.get_string( 0 ) ); if( iter == gen.defense_map.end() ) { jsarr.throw_error( "Invalid monster defense function" ); } sp_defense = iter->second; def_chance = jsarr.get_int( 1 ); } else if( !was_loaded ) { sp_defense = &mdefense::none; def_chance = 0; } if( !was_loaded || jo.has_member( "special_attacks" ) ) { special_attacks.clear(); special_attacks_names.clear(); add_special_attacks( jo, "special_attacks", src ); } else { // Note: special_attacks left as is, new attacks are added to it! // Note: member name prefixes are compatible with those used by generic_typed_reader if( jo.has_object( "extend" ) ) { auto tmp = jo.get_object( "extend" ); add_special_attacks( tmp, "special_attacks", src ); } if( jo.has_object( "delete" ) ) { auto tmp = jo.get_object( "delete" ); remove_special_attacks( tmp, "special_attacks", src ); } } // Disable upgrading when JSON contains `"upgrades": false`, but fallback to the // normal behavior (including error checking) if "upgrades" is not boolean or not `false`. if( jo.has_bool( "upgrades" ) && !jo.get_bool( "upgrades" ) ) { upgrade_group = mongroup_id::NULL_ID(); upgrade_into = mtype_id::NULL_ID(); upgrades = false; } else if( jo.has_member( "upgrades" ) ) { JsonObject up = jo.get_object( "upgrades" ); optional( up, was_loaded, "half_life", half_life, -1 ); optional( up, was_loaded, "age_grow", age_grow, -1 ); optional( up, was_loaded, "into_group", upgrade_group, auto_flags_reader<mongroup_id> {}, mongroup_id::NULL_ID() ); optional( up, was_loaded, "into", upgrade_into, auto_flags_reader<mtype_id> {}, mtype_id::NULL_ID() ); upgrades = true; } //Reproduction if( jo.has_member( "reproduction" ) ) { JsonObject repro = jo.get_object( "reproduction" ); optional( repro, was_loaded, "baby_count", baby_count, -1 ); optional( repro, was_loaded, "baby_timer", baby_timer, -1 ); optional( repro, was_loaded, "baby_monster", baby_monster, auto_flags_reader<mtype_id> {}, mtype_id::NULL_ID() ); optional( repro, was_loaded, "baby_egg", baby_egg, auto_flags_reader<itype_id> {}, "null" ); if( jo.has_member( "baby_flags" ) ) { baby_flags.clear(); JsonArray baby_tags = jo.get_array( "baby_flags" ); while( baby_tags.has_more() ) { baby_flags.push_back( baby_tags.next_string() ); } } reproduces = true; } if( jo.has_member( "biosignature" ) ) { JsonObject biosig = jo.get_object( "biosignature" ); optional( biosig, was_loaded, "biosig_timer", biosig_timer, -1 ); optional( biosig, was_loaded, "biosig_item", biosig_item, auto_flags_reader<itype_id> {}, "null" ); biosignatures = true; } optional( jo, was_loaded, "burn_into", burn_into, auto_flags_reader<mtype_id> {}, mtype_id::NULL_ID() ); const typed_flag_reader<decltype( gen.flag_map )> flag_reader{ gen.flag_map, "invalid monster flag" }; optional( jo, was_loaded, "flags", flags, flag_reader ); // Can't calculate yet - we want all flags first optional( jo, was_loaded, "bash_skill", bash_skill, -1 ); const typed_flag_reader<decltype( gen.trigger_map )> trigger_reader{ gen.trigger_map, "invalid monster trigger" }; optional( jo, was_loaded, "anger_triggers", anger, trigger_reader ); optional( jo, was_loaded, "placate_triggers", placate, trigger_reader ); optional( jo, was_loaded, "fear_triggers", fear, trigger_reader ); if( jo.has_member( "path_settings" ) ) { auto jop = jo.get_object( "path_settings" ); // Here rather than in pathfinding.cpp because we want monster-specific defaults and was_loaded optional( jop, was_loaded, "max_dist", path_settings.max_dist, 0 ); optional( jop, was_loaded, "max_length", path_settings.max_length, -1 ); optional( jop, was_loaded, "bash_strength", path_settings.bash_strength, -1 ); optional( jop, was_loaded, "allow_open_doors", path_settings.allow_open_doors, false ); optional( jop, was_loaded, "avoid_traps", path_settings.avoid_traps, false ); optional( jop, was_loaded, "allow_climb_stairs", path_settings.allow_climb_stairs, true ); } }
void item_comp::load( JsonArray &ja ) { JsonArray comp = ja.next_array(); type = comp.get_string( 0 ); count = comp.get_int( 1 ); }
void Item_factory::load_gun(JsonObject& jo) { it_gun* gun_template = new it_gun(); gun_template->ammo = jo.get_string("ammo"); gun_template->skill_used = Skill::skill(jo.get_string("skill")); gun_template->dmg_bonus = jo.get_int("ranged_damage"); gun_template->range = jo.get_int("range"); gun_template->dispersion = jo.get_int("dispersion"); gun_template->recoil = jo.get_int("recoil"); gun_template->durability = jo.get_int("durability"); gun_template->burst = jo.get_int("burst"); gun_template->clip = jo.get_int("clip_size"); gun_template->reload_time = jo.get_int("reload"); gun_template->pierce = jo.get_int("pierce", 0); gun_template->ammo_effects = jo.get_tags("ammo_effects"); if ( jo.has_array("valid_mod_locations") ) { JsonArray jarr = jo.get_array("valid_mod_locations"); while (jarr.has_more()){ JsonArray curr = jarr.next_array(); gun_template->valid_mod_locations.insert(std::pair<std::string, int>(curr.get_string(0), curr.get_int(1))); gun_template->occupied_mod_locations.insert(std::pair<std::string, int>(curr.get_string(0), 0)); } } itype *new_item_template = gun_template; load_basic_info(jo, new_item_template); }
void gun_actor::load_internal( JsonObject &obj, const std::string & ) { gun_type = obj.get_string( "gun_type" ); obj.read( "ammo_type", ammo_type ); if( obj.has_array( "fake_skills" ) ) { JsonArray jarr = obj.get_array( "fake_skills" ); while( jarr.has_more() ) { JsonArray cur = jarr.next_array(); fake_skills[skill_id( cur.get_string( 0 ) )] = cur.get_int( 1 ); } } obj.read( "fake_str", fake_str ); obj.read( "fake_dex", fake_dex ); obj.read( "fake_int", fake_int ); obj.read( "fake_per", fake_per ); auto arr = obj.get_array( "ranges" ); while( arr.has_more() ) { auto mode = arr.next_array(); if( mode.size() < 2 || mode.get_int( 0 ) > mode.get_int( 1 ) ) { obj.throw_error( "incomplete or invalid range specified", "ranges" ); } ranges.emplace( std::make_pair<int, int>( mode.get_int( 0 ), mode.get_int( 1 ) ), gun_mode_id( mode.size() > 2 ? mode.get_string( 2 ) : "" ) ); } obj.read( "max_ammo", max_ammo ); obj.read( "move_cost", move_cost ); if( obj.read( "description", description ) ) { description = _( description ); } if( obj.read( "failure_msg", failure_msg ) ) { failure_msg = _( failure_msg ); } if( obj.read( "no_ammo_sound", no_ammo_sound ) ) { no_ammo_sound = _( no_ammo_sound ); } else { no_ammo_sound = _( "Click." ); } obj.read( "targeting_cost", targeting_cost ); obj.read( "require_targeting_player", require_targeting_player ); obj.read( "require_targeting_npc", require_targeting_npc ); obj.read( "require_targeting_monster", require_targeting_monster ); obj.read( "targeting_timeout", targeting_timeout ); obj.read( "targeting_timeout_extend", targeting_timeout_extend ); if( obj.read( "targeting_sound", targeting_sound ) ) { targeting_sound = _( targeting_sound ); } else { targeting_sound = _( "Beep." ); } obj.read( "targeting_volume", targeting_volume ); obj.get_bool( "laser_lock", laser_lock ); obj.read( "require_sunlight", require_sunlight ); }