示例#1
0
// 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);
    }
}
示例#2
0
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 );
            }
        }
    }
}
示例#3
0
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));
    }
}
示例#4
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." );
        }
    }
}
示例#7
0
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();
}
示例#8
0
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));
    }
}
示例#9
0
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));
    }
}
示例#10
0
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"];
    }
}
示例#11
0
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 );
}
示例#12
0
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 );
    }
}
示例#13
0
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" );
    }
}
示例#14
0
// 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);
    }
}
示例#15
0
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"];
    }
}
示例#16
0
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
}
示例#17
0
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", "" );
}
示例#18
0
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" );
    }
}
示例#19
0
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);
    }
}
示例#20
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 );
        }
    }
}
示例#21
0
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() );
        }
    }
}
示例#22
0
/*
 * 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);
}
示例#23
0
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);
}
示例#24
0
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 );
}
示例#25
0
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());
    }
}
示例#26
0
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 );
    }
}
示例#28
0
void item_comp::load( JsonArray &ja )
{
    JsonArray comp = ja.next_array();
    type = comp.get_string( 0 );
    count = comp.get_int( 1 );
}
示例#29
0
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);
}
示例#30
0
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 );
}