예제 #1
0
void mtype::add_special_attacks( JsonObject &jo, const std::string &member,
                                 const std::string &src )
{

    if( !jo.has_array( member ) ) {
        return;
    }

    JsonArray outer = jo.get_array( member );
    while( outer.has_more() ) {
        if( outer.test_array() ) {
            add_special_attack( outer.next_array(), src );
        } else if( outer.test_object() ) {
            add_special_attack( outer.next_object(), src );
        } else {
            outer.throw_error( "array element is neither array nor object." );
        }
    }
}
예제 #2
0
void npc_class::load( JsonObject &jo, const std::string & )
{
    mandatory( jo, was_loaded, "name", name, translated_string_reader );
    mandatory( jo, was_loaded, "job_description", job_description, translated_string_reader );

    optional( jo, was_loaded, "common", common, true );
    bonus_str = load_distribution( jo, "bonus_str" );
    bonus_dex = load_distribution( jo, "bonus_dex" );
    bonus_int = load_distribution( jo, "bonus_int" );
    bonus_per = load_distribution( jo, "bonus_per" );

    optional( jo, was_loaded, "shopkeeper_item_group", shopkeeper_item_group, "EMPTY_GROUP" );
    optional( jo, was_loaded, "worn_override", worn_override );
    optional( jo, was_loaded, "carry_override", carry_override );
    optional( jo, was_loaded, "weapon_override", weapon_override );

    if( jo.has_array( "traits" ) ) {
        JsonArray jarr = jo.get_array( "traits" );
        while( jarr.has_more() ) {
            JsonArray jarr_in = jarr.next_array();
            traits[ trait_id( jarr_in.get_string( 0 ) ) ] = jarr_in.get_int( 1 );
        }
    }

    if( jo.has_array( "skills" ) ) {
        JsonArray jarr = jo.get_array( "skills" );
        while( jarr.has_more() ) {
            JsonObject skill_obj = jarr.next_object();
            auto skill_ids = skill_obj.get_tags( "skill" );
            if( skill_obj.has_object( "level" ) ) {
                distribution dis = load_distribution( skill_obj, "level" );
                for( const auto &sid : skill_ids ) {
                    skills[ skill_id( sid ) ] = dis;
                }
            } else {
                distribution dis = load_distribution( skill_obj, "bonus" );
                for( const auto &sid : skill_ids ) {
                    bonus_skills[ skill_id( sid ) ] = dis;
                }
            }
        }
    }
}
예제 #3
0
void MonsterGroupManager::LoadMonsterGroup(JsonObject &jo)
{
    MonsterGroup g;

    g.name = jo.get_string("name");
    g.defaultMonster = jo.get_string("default");
    if (jo.has_array("monsters")){
        JsonArray monarr = jo.get_array("monsters");

        while (monarr.has_more()) {
            JsonObject mon = monarr.next_object();
            std::string name = mon.get_string("monster");
            int freq = mon.get_int("freq");
            int cost = mon.get_int("cost_multiplier");
            int pack_min = 1;
            int pack_max = 1;
            if(mon.has_member("pack_size")){
                JsonArray packarr = mon.get_array("pack_size");
                pack_min = packarr.next_int();
                pack_max = packarr.next_int();
            }
            int starts = 0;
            int ends = 0;
            if(mon.has_member("starts")){
                starts = mon.get_int("starts");
            }
            if(mon.has_member("ends")){
                ends = mon.get_int("ends");
            }
            MonsterGroupEntry new_mon_group = MonsterGroupEntry(name,freq,cost,pack_min,pack_max,starts,ends);
            if(mon.has_member("conditions")){
              JsonArray conditions_arr = mon.get_array("conditions");
              while(conditions_arr.has_more()){
                new_mon_group.conditions.push_back(conditions_arr.next_string());
              }
            }
            g.monsters.push_back(new_mon_group);
        }
    }

    monsterGroupMap[g.name] = g;
}
예제 #4
0
void map_data_common_t::load( JsonObject &jo, const std::string &src )
{
    if( jo.has_member( "examine_action" ) ) {
        examine = iexamine_function_from_string( jo.get_string( "examine_action" ) );
    } else {
        examine = iexamine_function_from_string( "none" );
    }

    if( jo.has_array( "harvest_by_season" ) ) {
        JsonArray jsarr = jo.get_array( "harvest_by_season" );
        while( jsarr.has_more() ) {
            JsonObject harvest_jo = jsarr.next_object();
            auto season_strings = harvest_jo.get_tags( "seasons" );
            std::set<season_type> seasons;
            std::transform( season_strings.begin(), season_strings.end(), std::inserter( seasons,
                            seasons.begin() ),
            []( const std::string & data ) {
                return io::string_to_enum<season_type>( data );
            } );

            harvest_id hl;
            if( harvest_jo.has_array( "entries" ) ) {
                // @todo: A better inline name - can't use id or name here because it's not set yet
                size_t num = harvest_list::all().size() + 1;
                hl = harvest_list::load( harvest_jo, src,
                                         string_format( "harvest_inline_%d", static_cast<int>( num ) ) );
            } else if( harvest_jo.has_string( "id" ) ) {
                hl = harvest_id( harvest_jo.get_string( "id" ) );
            } else {
                jo.throw_error( "Each harvest entry must specify either \"entries\" or \"id\"",
                                "harvest_by_season" );
            }

            for( season_type s : seasons ) {
                harvest_by_season[ s ] = hl;
            }
        }
    }

    optional( jo, false, "description", description, translated_string_reader );
}
예제 #5
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 );
        }
    }
}
예제 #6
0
/*
 * Invlet cache: player specific, thus not wrapped in inventory::json_load/save
 */
void inventory::json_load_invcache(JsonIn &jsin)
{
    try {
        JsonArray ja = jsin.get_array();
        while ( ja.has_more() ) {
            JsonObject jo = ja.next_object();
            std::set<std::string> members = jo.get_member_names();
            for (std::set<std::string>::iterator it = members.begin();
                    it != members.end(); ++it) {
                std::vector<char> vect;
                JsonArray pvect = jo.get_array(*it);
                while ( pvect.has_more() ) {
                    vect.push_back( pvect.next_int() );
                }
                invlet_cache[*it] = vect;
            }
        }
    } catch (std::string jsonerr) {
        debugmsg("bad invcache json:\n%s", jsonerr.c_str() );
    }
}
예제 #7
0
void mutation_branch::add_entry( Trait_group &tg, JsonObject &obj )
{
    std::unique_ptr<Trait_creation_data> ptr;
    int probability = obj.get_int( "prob", 100 );
    JsonArray jarr;

    if( obj.has_member( "collection" ) ) {
        ptr.reset( new Trait_group_collection( probability ) );
        jarr = obj.get_array( "collection" );
    } else if( obj.has_member( "distribution" ) ) {
        ptr.reset( new Trait_group_distribution( probability ) );
        jarr = obj.get_array( "distribution" );
    }

    if( ptr ) {
        Trait_group &tg2 = dynamic_cast<Trait_group &>( *ptr );
        while( jarr.has_more() ) {
            JsonObject job2 = jarr.next_object();
            add_entry( tg2, job2 );
        }
        tg.add_entry( ptr );
        return;
    }

    if( obj.has_member( "trait" ) ) {
        trait_id id( obj.get_string( "trait" ) );
        ptr.reset( new Single_trait_creator( id, probability ) );
    } else if( obj.has_member( "group" ) ) {
        ptr.reset( new Trait_group_creator( trait_group::Trait_group_tag( obj.get_string( "group" ) ),
                                            probability ) );
    }

    if( !ptr ) {
        return;
    }

    tg.add_entry( ptr );
}
예제 #8
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 );

    // TODO: allow adding/removing specific entries if `was_loaded` is true
    if( jo.has_array( "attack_effs" ) ) {
        JsonArray jsarr = jo.get_array( "attack_effs" );
        while( jsarr.has_more() ) {
            JsonObject e = jsarr.next_object();
            mon_effect_data new_eff( efftype_id( e.get_string( "id" ) ), e.get_int( "duration", 0 ),
                                     get_body_part_token( e.get_string( "bp", "NUM_BP" ) ), e.get_bool( "permanent", false ),
                                     e.get_int( "chance", 100 ) );
            atk_effs.push_back( new_eff );
        }
    }

    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 );
    }

    // TODO: allow overriding/adding/removing those if `was_loaded` is true
    gen.load_special_defense( this, jo, "special_when_hit" );
    gen.load_special_attacks( this, jo, "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 );
}
예제 #9
0
void load_mutation(JsonObject &jsobj)
{
    trait new_trait;
    JsonArray jsarr;
    std::string id = jsobj.get_string("id");
    new_trait.id = id;
    new_trait.name = _(jsobj.get_string("name").c_str());
    new_trait.description = _(jsobj.get_string("description").c_str());
    new_trait.points = jsobj.get_int("points");
    new_trait.visibility = jsobj.get_int("visibility", 0);
    new_trait.ugliness = jsobj.get_int("ugliness", 0);
    new_trait.startingtrait = jsobj.get_bool("starting_trait", false);
    new_trait.mixed_effect = jsobj.get_bool("mixed_effect", false);
    new_trait.activated = jsobj.get_bool("active", false);
    new_trait.cost = jsobj.get_int("cost", 0);
    new_trait.cooldown = jsobj.get_int("time",0);
    new_trait.hunger = jsobj.get_bool("hunger",false);
    new_trait.thirst = jsobj.get_bool("thirst",false);
    new_trait.fatigue = jsobj.get_bool("fatigue",false);
    new_trait.charge = 0;


    traits[id] = new_trait;

    mutation_data[id].valid = jsobj.get_bool("valid", true);
    mutation_data[id].purifiable = jsobj.get_bool("purifiable", true);
    mutation_data[id].threshold = jsobj.get_bool("threshold", false);

    jsarr = jsobj.get_array("prereqs");
    while (jsarr.has_more()) {
        mutation_data[id].prereqs.push_back(jsarr.next_string());
    }
    // Helps to be able to have a trait require more than one other trait
    // (Individual prereq-lists are "OR", not "AND".)
    // Traits shoud NOT appear in both lists for a given mutation, unless
    // you want that trait to satisfy both requirements.
    // These are additional to the first list.
    jsarr = jsobj.get_array("prereqs2");
    while (jsarr.has_more()) {
        mutation_data[id].prereqs2.push_back(jsarr.next_string());
    }
    // Dedicated-purpose prereq slot for Threshold mutations
    jsarr = jsobj.get_array("threshreq");
    // Stuff like Huge might fit in more than one mutcat post-threshold, so yeah
    while (jsarr.has_more()) {
        mutation_data[id].threshreq.push_back(jsarr.next_string());
    }
    jsarr = jsobj.get_array("cancels");
    while (jsarr.has_more()) {
        mutation_data[id].cancels.push_back(jsarr.next_string());
    }
    jsarr = jsobj.get_array("changes_to");
    while (jsarr.has_more()) {
        mutation_data[id].replacements.push_back(jsarr.next_string());
    }
    jsarr = jsobj.get_array("leads_to");
    while (jsarr.has_more()) {
        mutation_data[id].additions.push_back(jsarr.next_string());
    }
    jsarr = jsobj.get_array("category");
    while (jsarr.has_more()) {
        std::string s = jsarr.next_string();
        mutation_data[id].category.push_back(s);
        mutations_category[s].push_back(id);
    }
    jsarr = jsobj.get_array("wet_protection");
    while (jsarr.has_more()) {
        JsonObject jo = jsarr.next_object();
        std::string part_id = jo.get_string("part");
        int ignored = jo.get_int("ignored", 0);
        int neutral = jo.get_int("neutral", 0);
        int good = jo.get_int("good", 0);
        tripoint protect = tripoint(ignored, neutral, good);
        mutation_data[id].protection[part_id] =
            mutation_wet(body_parts[part_id], protect);
    }
}
예제 #10
0
void input_manager::init()
{
    init_keycode_mapping();

    std::ifstream data_file;

    std::string file_name = "data/raw/keybindings.json";
    data_file.open(file_name.c_str(), std::ifstream::in | std::ifstream::binary);

    if(!data_file.good()) {
        throw "Could not read " + file_name;
    }

    JsonIn jsin(data_file);

    //Crawl through once and create an entry for every definition
    jsin.start_array();
    while (!jsin.end_array()) {
        // JSON object representing the action
        JsonObject action = jsin.get_object();

        const std::string action_id = action.get_string("id");
        actionID_to_name[action_id] = action.get_string("name", action_id);
        const std::string context = action.get_string("category", "default");

        // Iterate over the bindings JSON array
        JsonArray bindings = action.get_array("bindings");
        const bool defaultcontext = (context == "default");
        while (bindings.has_more()) {
            JsonObject keybinding = bindings.next_object();
            std::string input_method = keybinding.get_string("input_method");
            input_event new_event;
            if(input_method == "keyboard") {
                new_event.type = CATA_INPUT_KEYBOARD;
            } else if(input_method == "gamepad") {
                new_event.type = CATA_INPUT_GAMEPAD;
            } else if(input_method == "mouse") {
                new_event.type = CATA_INPUT_MOUSE;
            }

            if (keybinding.has_array("key")) {
                JsonArray keys = keybinding.get_array("key");
                while (keys.has_more()) {
                    new_event.sequence.push_back(
                        get_keycode(keys.next_string())
                    );
                }
            } else { // assume string if not array, and throw if not string
                new_event.sequence.push_back(
                    get_keycode(keybinding.get_string("key"))
                );
            }

            if (defaultcontext) {
                action_to_input[action_id].push_back(new_event);
            } else {
                action_contexts[context][action_id].push_back(new_event);
            }
        }
    }

    data_file.close();
}
예제 #11
0
void mutation_branch::load( JsonObject &jsobj )
{
    const std::string id = jsobj.get_string( "id" );
    mutation_branch &new_mut = mutation_data[id];

    JsonArray jsarr;
    new_mut.name = _(jsobj.get_string("name").c_str());
    new_mut.description = _(jsobj.get_string("description").c_str());
    new_mut.points = jsobj.get_int("points");
    new_mut.visibility = jsobj.get_int("visibility", 0);
    new_mut.ugliness = jsobj.get_int("ugliness", 0);
    new_mut.startingtrait = jsobj.get_bool("starting_trait", false);
    new_mut.mixed_effect = jsobj.get_bool("mixed_effect", false);
    new_mut.activated = jsobj.get_bool("active", false);
    new_mut.cost = jsobj.get_int("cost", 0);
    new_mut.cooldown = jsobj.get_int("time",0);
    new_mut.hunger = jsobj.get_bool("hunger",false);
    new_mut.thirst = jsobj.get_bool("thirst",false);
    new_mut.fatigue = jsobj.get_bool("fatigue",false);
    new_mut.valid = jsobj.get_bool("valid", true);
    new_mut.purifiable = jsobj.get_bool("purifiable", true);
    for( auto & s : jsobj.get_string_array( "initial_ma_styles" ) ) {
        new_mut.initial_ma_styles.push_back( matype_id( s ) );
    }

    JsonArray bodytemp_array = jsobj.get_array( "bodytemp_modifiers" );
    if( bodytemp_array.has_more() ) {
        new_mut.bodytemp_min = bodytemp_array.get_int( 0 );
        new_mut.bodytemp_max = bodytemp_array.get_int( 1 );
    }
    new_mut.bodytemp_sleep = jsobj.get_int( "bodytemp_sleep", 0 );
    new_mut.threshold = jsobj.get_bool("threshold", false);
    new_mut.profession = jsobj.get_bool("profession", false);

    load_mutation_mods(jsobj, "passive_mods", new_mut.mods);
    /* Not currently supported due to inability to save active mutation state
    load_mutation_mods(jsobj, "active_mods", new_mut.mods); */

    new_mut.prereqs = jsobj.get_string_array( "prereqs" );
    // Helps to be able to have a trait require more than one other trait
    // (Individual prereq-lists are "OR", not "AND".)
    // Traits shoud NOT appear in both lists for a given mutation, unless
    // you want that trait to satisfy both requirements.
    // These are additional to the first list.
    new_mut.prereqs2 = jsobj.get_string_array( "prereqs2" );
    // Dedicated-purpose prereq slot for Threshold mutations
    // Stuff like Huge might fit in more than one mutcat post-threshold, so yeah
    new_mut.threshreq = jsobj.get_string_array( "threshreq" );
    new_mut.cancels = jsobj.get_string_array( "cancels" );
    new_mut.replacements = jsobj.get_string_array( "changes_to" );
    new_mut.additions = jsobj.get_string_array( "leads_to" );
    jsarr = jsobj.get_array("category");
    while (jsarr.has_more()) {
        std::string s = jsarr.next_string();
        new_mut.category.push_back(s);
        mutations_category[s].push_back(id);
    }
    jsarr = jsobj.get_array("wet_protection");
    while (jsarr.has_more()) {
        JsonObject jo = jsarr.next_object();
        std::string part_id = jo.get_string("part");
        int ignored = jo.get_int("ignored", 0);
        int neutral = jo.get_int("neutral", 0);
        int good = jo.get_int("good", 0);
        tripoint protect = tripoint(ignored, neutral, good);
        new_mut.protection[get_body_part_token( part_id )] = protect;
    }
}
예제 #12
0
/**
 *Caches a vehicle definition from a JsonObject to be loaded after itypes is initialized.
 */
void vehicle_prototype::load(JsonObject &jo)
{
    vehicle_prototype &vproto = vtypes[ vproto_id( jo.get_string( "id" ) ) ];
    // If there are already parts defined, this vehicle prototype overrides an existing one.
    // If the json contains a name, it means a completely new prototype (replacing the
    // original one), therefor the old data has to be cleared.
    // If the json does not contain a name (the prototype would have no name), it means appending
    // to the existing prototype (the parts are not cleared).
    if( !vproto.parts.empty() && jo.has_string( "name" ) ) {
        vproto =  vehicle_prototype();
    }
    if( vproto.parts.empty() ) {
        vproto.name = jo.get_string( "name" );
    }

    vgroups[vgroup_id(jo.get_string("id"))].add_vehicle(vproto_id(jo.get_string("id")), 100);

    JsonArray parts = jo.get_array("parts");
    while (parts.has_more()) {
        JsonObject part = parts.next_object();

        part_def pt;
        pt.pos = point( part.get_int( "x" ), part.get_int( "y" ) );
        pt.part = vpart_id( part.get_string( "part" ) );

        assign( part, "ammo", pt.with_ammo, true, 0, 100 );
        assign( part, "ammo_types", pt.ammo_types, true );
        assign( part, "ammo_qty", pt.ammo_qty, true, 0 );
        assign( part, "fuel", pt.fuel, true );

        vproto.parts.push_back( pt );
    }

    JsonArray items = jo.get_array("items");
    while(items.has_more()) {
        JsonObject spawn_info = items.next_object();
        vehicle_item_spawn next_spawn;
        next_spawn.pos.x = spawn_info.get_int("x");
        next_spawn.pos.y = spawn_info.get_int("y");

        next_spawn.chance = spawn_info.get_int("chance");
        if(next_spawn.chance <= 0 || next_spawn.chance > 100) {
            debugmsg("Invalid spawn chance in %s (%d, %d): %d%%",
                     vproto.name.c_str(), next_spawn.pos.x, next_spawn.pos.y, next_spawn.chance);
        }

        // constrain both with_magazine and with_ammo to [0-100]
        next_spawn.with_magazine = std::max( std::min( spawn_info.get_int( "magazine", next_spawn.with_magazine ), 100 ), 0 );
        next_spawn.with_ammo = std::max( std::min( spawn_info.get_int( "ammo", next_spawn.with_ammo ), 100 ), 0 );

        if(spawn_info.has_array("items")) {
            //Array of items that all spawn together (ie jack+tire)
            JsonArray item_group = spawn_info.get_array("items");
            while(item_group.has_more()) {
                next_spawn.item_ids.push_back(item_group.next_string());
            }
        } else if(spawn_info.has_string("items")) {
            //Treat single item as array
            next_spawn.item_ids.push_back(spawn_info.get_string("items"));
        }
        if(spawn_info.has_array("item_groups")) {
            //Pick from a group of items, just like map::place_items
            JsonArray item_group_names = spawn_info.get_array("item_groups");
            while(item_group_names.has_more()) {
                next_spawn.item_groups.push_back(item_group_names.next_string());
            }
        } else if(spawn_info.has_string("item_groups")) {
            next_spawn.item_groups.push_back(spawn_info.get_string("item_groups"));
        }
        vproto.item_spawns.push_back( std::move( next_spawn ) );
    }
}
예제 #13
0
void input_manager::load(const std::string &file_name, bool is_user_preferences)
{
    std::ifstream data_file(file_name.c_str(), std::ifstream::in | std::ifstream::binary);

    if(!data_file.good()) {
        // Only throw if this is the first file to load, that file _must_ exist,
        // otherwise the keybindings can not be read at all.
        if (action_contexts.empty()) {
            throw "Could not read " + file_name;
        }
        return;
    }

    JsonIn jsin(data_file);

    //Crawl through once and create an entry for every definition
    jsin.start_array();
    while (!jsin.end_array()) {
        // JSON object representing the action
        JsonObject action = jsin.get_object();

        const std::string action_id = action.get_string("id");
        const std::string context = action.get_string("category", default_context_id);
        t_actions &actions = action_contexts[context];
        if (!is_user_preferences && action.has_member("name")) {
            // Action names are not user preferences. Some experimental builds
            // post-0.A had written action names into the user preferences
            // config file. Any names that exist in user preferences will be
            // ignored.
            actions[action_id].name = action.get_string("name");
        }

        // Iterate over the bindings JSON array
        JsonArray bindings = action.get_array("bindings");
        t_input_event_list events;
        while (bindings.has_more()) {
            JsonObject keybinding = bindings.next_object();
            std::string input_method = keybinding.get_string("input_method");
            input_event new_event;
            if(input_method == "keyboard") {
                new_event.type = CATA_INPUT_KEYBOARD;
            } else if(input_method == "gamepad") {
                new_event.type = CATA_INPUT_GAMEPAD;
            } else if(input_method == "mouse") {
                new_event.type = CATA_INPUT_MOUSE;
            }

            if (keybinding.has_array("key")) {
                JsonArray keys = keybinding.get_array("key");
                while (keys.has_more()) {
                    new_event.sequence.push_back(
                        get_keycode(keys.next_string())
                    );
                }
            } else { // assume string if not array, and throw if not string
                new_event.sequence.push_back(
                    get_keycode(keybinding.get_string("key"))
                );
            }

            events.push_back(new_event);
        }

        // An invariant of this class is that user-created, local keybindings
        // with an empty set of input_events do not exist in the
        // action_contexts map. In prior versions of this class, this was not
        // true, so users of experimental builds post-0.A will have empty
        // local keybindings saved in their keybindings.json config.
        //
        // To be backwards compatible with keybindings.json from prior
        // experimental builds, we will detect user-created, local keybindings
        // with empty input_events and disregard them. When keybindings are
        // later saved, these remnants won't be saved.
        if (!is_user_preferences ||
            !events.empty() ||
            context == default_context_id ||
            actions.count(action_id) > 0) {
            // In case this is the second file containing user preferences,
            // this replaces the default bindings with the user's preferences.
            action_attributes &attributes = actions[action_id];
            attributes.input_events = events;
            if (action.has_member("is_user_created")) {
                attributes.is_user_created = action.get_bool("is_user_created");
            }
        }
    }
}
예제 #14
0
void mutation_branch::load( JsonObject &jsobj )
{
    const std::string id = jsobj.get_string( "id" );
    mutation_branch &new_mut = mutation_data[id];

    JsonArray jsarr;
    new_mut.name = _(jsobj.get_string("name").c_str());
    new_mut.description = _(jsobj.get_string("description").c_str());
    new_mut.points = jsobj.get_int("points");
    new_mut.visibility = jsobj.get_int("visibility", 0);
    new_mut.ugliness = jsobj.get_int("ugliness", 0);
    new_mut.startingtrait = jsobj.get_bool("starting_trait", false);
    new_mut.mixed_effect = jsobj.get_bool("mixed_effect", false);
    new_mut.activated = jsobj.get_bool("active", false);
    new_mut.starts_active = jsobj.get_bool("starts_active", false);
    new_mut.destroys_gear = jsobj.get_bool("destroys_gear", false);
    new_mut.allow_soft_gear = jsobj.get_bool("allow_soft_gear", false);
    new_mut.cost = jsobj.get_int("cost", 0);
    new_mut.cooldown = jsobj.get_int("time",0);
    new_mut.hunger = jsobj.get_bool("hunger",false);
    new_mut.thirst = jsobj.get_bool("thirst",false);
    new_mut.fatigue = jsobj.get_bool("fatigue",false);
    new_mut.valid = jsobj.get_bool("valid", true);
    new_mut.purifiable = jsobj.get_bool("purifiable", true);
    for( auto & s : jsobj.get_string_array( "initial_ma_styles" ) ) {
        new_mut.initial_ma_styles.push_back( matype_id( s ) );
    }

    JsonArray bodytemp_array = jsobj.get_array( "bodytemp_modifiers" );
    if( bodytemp_array.has_more() ) {
        new_mut.bodytemp_min = bodytemp_array.get_int( 0 );
        new_mut.bodytemp_max = bodytemp_array.get_int( 1 );
    }
    new_mut.bodytemp_sleep = jsobj.get_int( "bodytemp_sleep", 0 );
    new_mut.threshold = jsobj.get_bool("threshold", false);
    new_mut.profession = jsobj.get_bool("profession", false);

    auto vr = jsobj.get_array( "vitamin_rates" );
    while( vr.has_more() ) {
        auto pair = vr.next_array();
        new_mut.vitamin_rates[ vitamin_id( pair.get_string( 0 ) ) ] = pair.get_int( 1 );
    }

    load_mutation_mods(jsobj, "passive_mods", new_mut.mods);
    /* Not currently supported due to inability to save active mutation state
    load_mutation_mods(jsobj, "active_mods", new_mut.mods); */

    new_mut.prereqs = jsobj.get_string_array( "prereqs" );
    // Helps to be able to have a trait require more than one other trait
    // (Individual prereq-lists are "OR", not "AND".)
    // Traits shoud NOT appear in both lists for a given mutation, unless
    // you want that trait to satisfy both requirements.
    // These are additional to the first list.
    new_mut.prereqs2 = jsobj.get_string_array( "prereqs2" );
    // Dedicated-purpose prereq slot for Threshold mutations
    // Stuff like Huge might fit in more than one mutcat post-threshold, so yeah
    new_mut.threshreq = jsobj.get_string_array( "threshreq" );
    new_mut.cancels = jsobj.get_string_array( "cancels" );
    new_mut.replacements = jsobj.get_string_array( "changes_to" );
    new_mut.additions = jsobj.get_string_array( "leads_to" );
    new_mut.flags = jsobj.get_tags( "flags" );
    jsarr = jsobj.get_array("category");
    while (jsarr.has_more()) {
        std::string s = jsarr.next_string();
        new_mut.category.push_back(s);
        mutations_category[s].push_back(id);
    }
    jsarr = jsobj.get_array("wet_protection");
    while (jsarr.has_more()) {
        JsonObject jo = jsarr.next_object();
        std::string part_id = jo.get_string("part");
        int ignored = jo.get_int("ignored", 0);
        int neutral = jo.get_int("neutral", 0);
        int good = jo.get_int("good", 0);
        tripoint protect = tripoint(ignored, neutral, good);
        new_mut.protection[get_body_part_token( part_id )] = protect;
    }

    jsarr = jsobj.get_array("encumbrance_always");
    while (jsarr.has_more()) {
        JsonArray jo = jsarr.next_array();
        std::string part_id = jo.next_string();
        int enc = jo.next_int();
        new_mut.encumbrance_always[get_body_part_token( part_id )] = enc;
    }

    jsarr = jsobj.get_array("encumbrance_covered");
    while (jsarr.has_more()) {
        JsonArray jo = jsarr.next_array();
        std::string part_id = jo.next_string();
        int enc = jo.next_int();
        new_mut.encumbrance_covered[get_body_part_token( part_id )] = enc;
    }

    jsarr = jsobj.get_array("restricts_gear");
    while( jsarr.has_more() ) {
        new_mut.restricts_gear.insert( get_body_part_token( jsarr.next_string() ) );
    }

    jsarr = jsobj.get_array( "armor" );
    while( jsarr.has_more() ) {
        JsonObject jo = jsarr.next_object();
        auto parts = jo.get_tags( "parts" );
        std::set<body_part> bps;
        for( const std::string &part_string : parts ) {
            if( part_string == "ALL" ) {
                // Shorthand, since many muts protect whole body
                for( size_t i = 0; i < num_bp; i++ ) {
                    bps.insert( static_cast<body_part>( i ) );
                }
            } else {
                bps.insert( get_body_part_token( part_string ) );
            }
        }

        resistances res = load_resistances_instance( jo );

        for( body_part bp : bps ) {
            new_mut.armor[ bp ] = res;
        }
    }
}
예제 #15
0
void profession::load_profession(JsonObject &jsobj)
{
    profession prof;
    JsonArray jsarr;

    prof._ident = jsobj.get_string("ident");
    //If the "name" is an object then we have to deal with gender-specific titles,
    //otherwise we assume "name" is a string and use its value for prof._name
    if(jsobj.has_object("name")) {
        JsonObject name_obj=jsobj.get_object("name");
        prof._name_male = _(name_obj.get_string("male").c_str());
        prof._name_female = _(name_obj.get_string("female").c_str());
        prof._name = "";
    }
    else {
        // Json only has a gender neutral name, construct additional
        // gender specific names using a prefix.
        // extract_json_strings.py contains code that automatically adds
        // these constructed strings to the translation table.
        const std::string name = jsobj.get_string("name");
        const std::string name_female = std::string("female ") + name;
        const std::string name_male = std::string("male ") + name;
        // Now attempt to translate them...
        prof._name = _(name.c_str());
        prof._name_female = _(name_female.c_str());
        prof._name_male = _(name_male.c_str());
        // ... if it fails, translate the gender prefix and use it to
        // construct generic specific names:
        if (prof._name_female == name_female) {
            //~ player info: "female <gender unspecific profession>"
            prof._name_female = string_format(_("female %s"), prof._name.c_str());
        }
        if (prof._name_male == name_male) {
            //~ player info: "male <gender unspecific profession>"
            prof._name_male = string_format(_("male %s"), prof._name.c_str());
        }
    }

    prof._description = _(jsobj.get_string("description").c_str());
    prof._point_cost = jsobj.get_int("points");

    JsonObject items_obj=jsobj.get_object("items");
    prof.add_items_from_jsonarray(items_obj.get_array("both"), "both");
    prof.add_items_from_jsonarray(items_obj.get_array("male"), "male");
    prof.add_items_from_jsonarray(items_obj.get_array("female"), "female");

    jsarr = jsobj.get_array("skills");
    while (jsarr.has_more()) {
        JsonObject jo = jsarr.next_object();
        prof.add_skill(jo.get_string("name"),
                       jo.get_int("level"));
    }
    jsarr = jsobj.get_array("addictions");
    while (jsarr.has_more()) {
        JsonObject jo = jsarr.next_object();
        prof.add_addiction(addiction_type(jo.get_string("type")),
                           jo.get_int("intensity"));
    }
    jsarr = jsobj.get_array("CBMs");
    while (jsarr.has_more()) {
        prof.add_CBM(jsarr.next_string());
    }
    jsarr = jsobj.get_array("flags");
    while (jsarr.has_more()) {
        prof.flags.insert(jsarr.next_string());
    }

    _all_profs[prof._ident] = prof;
    //dout(D_INFO) << "Loaded profession: " << prof._name;
}
예제 #16
0
void MonsterGenerator::load_monster(JsonObject &jo)
{
    // id
    std::string mid;
    if (jo.has_member("id")) {
        mid = jo.get_string("id");
        if (mon_templates.count(mid) > 0) {
            delete mon_templates[mid];
        }

        mtype *newmon = new mtype;

        newmon->id = mid;
        newmon->name = jo.get_string("name").c_str();
        if(jo.has_member("name_plural")) {
            newmon->name_plural = jo.get_string("name_plural");
        } else {
            // default behaviour: Assume the regular plural form (appending an “s”)
            newmon->name_plural = newmon->name + "s";
        }
        newmon->description = _(jo.get_string("description").c_str());

        newmon->mat = jo.get_string("material");

        newmon->species = jo.get_tags("species");
        newmon->categories = jo.get_tags("categories");

        newmon->sym = jo.get_string("symbol");
        if( utf8_wrapper( newmon->sym ).display_width() != 1 ) {
            jo.throw_error( "monster symbol should be exactly one console cell width", "symbol" );
        }
        newmon->color = color_from_string(jo.get_string("color"));
        newmon->size = get_from_string(jo.get_string("size", "MEDIUM"), size_map, MS_MEDIUM);
        newmon->phase = get_from_string(jo.get_string("phase", "SOLID"), phase_map, SOLID);

        newmon->difficulty = jo.get_int("diff", 0);
        newmon->agro = jo.get_int("aggression", 0);
        newmon->morale = jo.get_int("morale", 0);
        newmon->speed = jo.get_int("speed", 0);
        newmon->melee_skill = jo.get_int("melee_skill", 0);
        newmon->melee_dice = jo.get_int("melee_dice", 0);
        newmon->melee_sides = jo.get_int("melee_dice_sides", 0);
        newmon->melee_cut = jo.get_int("melee_cut", 0);
        newmon->sk_dodge = jo.get_int("dodge", 0);
        newmon->armor_bash = jo.get_int("armor_bash", 0);
        newmon->armor_cut = jo.get_int("armor_cut", 0);
        newmon->hp = jo.get_int("hp", 0);
        jo.read("starting_ammo", newmon->starting_ammo);
        newmon->luminance = jo.get_float("luminance", 0);
        newmon->revert_to_itype = jo.get_string( "revert_to_itype", "" );
        
        if (jo.has_array("attack_effs")) {
            JsonArray jsarr = jo.get_array("attack_effs");
            while (jsarr.has_more()) {
                JsonObject e = jsarr.next_object();
                mon_effect_data new_eff(e.get_string("id", "null"), e.get_int("duration", 0),
                                    body_parts[e.get_string("bp", "NUM_BP")], e.get_bool("permanent", false),
                                    e.get_int("chance", 100));
                newmon->atk_effs.push_back(new_eff);
            }
        }

        if (jo.has_string("death_drops")) {
            newmon->death_drops = jo.get_string("death_drops");
        } else if (jo.has_object("death_drops")) {
            JsonObject death_frop_json = jo.get_object("death_drops");
            // Make up a group name, should be unique (include the monster id),
            newmon->death_drops = newmon->id + "_death_drops_auto";
            const std::string subtype = death_frop_json.get_string("subtype", "distribution");
            // and load the entry as a standard item group using the made up name.
            item_group::load_item_group(death_frop_json, newmon->death_drops, subtype);
        } else if (jo.has_member("death_drops")) {
            jo.throw_error("invalid type, must be string or object", "death_drops");
        }

        newmon->dies = get_death_functions(jo, "death_function");
        load_special_defense(newmon, jo, "special_when_hit");
        load_special_attacks(newmon, jo, "special_attacks");

        std::set<std::string> flags, anger_trig, placate_trig, fear_trig;
        flags = jo.get_tags("flags");
        anger_trig = jo.get_tags("anger_triggers");
        placate_trig = jo.get_tags("placate_triggers");
        fear_trig = jo.get_tags("fear_triggers");

        newmon->flags = get_set_from_tags(flags, flag_map, MF_NULL);
        newmon->anger = get_set_from_tags(anger_trig, trigger_map, MTRIG_NULL);
        newmon->fear = get_set_from_tags(fear_trig, trigger_map, MTRIG_NULL);
        newmon->placate = get_set_from_tags(placate_trig, trigger_map, MTRIG_NULL);

        mon_templates[mid] = newmon;
    }
}
예제 #17
0
void MonsterGenerator::load_monster(JsonObject &jo)
{
    const mtype_id mid = mtype_id( jo.get_string("id") );
        if (mon_templates.count(mid) > 0) {
            delete mon_templates[mid];
        }

        mtype *newmon = new mtype;

        newmon->id = mid;
        newmon->name = jo.get_string("name").c_str();
        if(jo.has_member("name_plural")) {
            newmon->name_plural = jo.get_string("name_plural");
        } else {
            // default behaviour: Assume the regular plural form (appending an “s”)
            newmon->name_plural = newmon->name + "s";
        }
        newmon->description = _(jo.get_string("description").c_str());

        // Have to overwrite the default { "hflesh" } here
        newmon->mat = { jo.get_string("material") };

        for( auto &s : jo.get_tags( "species" ) ) {
            newmon->species.insert( species_id( s ) );
        }
        newmon->categories = jo.get_tags("categories");

        // See monfaction.cpp
        newmon->default_faction =
            monfactions::get_or_add_faction( mfaction_str_id( jo.get_string("default_faction") ) );

        newmon->sym = jo.get_string("symbol");
        if( utf8_wrapper( newmon->sym ).display_width() != 1 ) {
            jo.throw_error( "monster symbol should be exactly one console cell width", "symbol" );
        }
        newmon->color = color_from_string(jo.get_string("color"));
        newmon->size = get_from_string(jo.get_string("size", "MEDIUM"), Creature::size_map, MS_MEDIUM);
        newmon->phase = get_from_string(jo.get_string("phase", "SOLID"), phase_map, SOLID);

        newmon->difficulty = jo.get_int("diff", 0);
        newmon->agro = jo.get_int("aggression", 0);
        newmon->morale = jo.get_int("morale", 0);
        newmon->speed = jo.get_int("speed", 0);
        newmon->attack_cost = jo.get_int("attack_cost", 100);
        newmon->melee_skill = jo.get_int("melee_skill", 0);
        newmon->melee_dice = jo.get_int("melee_dice", 0);
        newmon->melee_sides = jo.get_int("melee_dice_sides", 0);
        newmon->melee_cut = jo.get_int("melee_cut", 0);
        newmon->sk_dodge = jo.get_int("dodge", 0);
        newmon->armor_bash = jo.get_int("armor_bash", 0);
        newmon->armor_cut = jo.get_int("armor_cut", 0);
        newmon->hp = jo.get_int("hp", 0);
        jo.read("starting_ammo", newmon->starting_ammo);
        newmon->luminance = jo.get_float("luminance", 0);
        newmon->revert_to_itype = jo.get_string( "revert_to_itype", "" );
        newmon->vision_day = jo.get_int("vision_day", 40);
        newmon->vision_night = jo.get_int("vision_night", 1);

        if (jo.has_array("attack_effs")) {
            JsonArray jsarr = jo.get_array("attack_effs");
            while (jsarr.has_more()) {
                JsonObject e = jsarr.next_object();
                mon_effect_data new_eff(e.get_string("id", "null"), e.get_int("duration", 0),
                                    get_body_part_token( e.get_string("bp", "NUM_BP") ), e.get_bool("permanent", false),
                                    e.get_int("chance", 100));
                newmon->atk_effs.push_back(new_eff);
            }
        }

        if( jo.has_member( "death_drops" ) ) {
            JsonIn& stream = *jo.get_raw( "death_drops" );
            newmon->death_drops = item_group::load_item_group( stream, "distribution" );
        }

        newmon->dies = get_death_functions(jo, "death_function");
        load_special_defense(newmon, jo, "special_when_hit");
        load_special_attacks(newmon, jo, "special_attacks");

        if (jo.has_member("upgrades")) {
            JsonObject upgrades = jo.get_object("upgrades");
            newmon->half_life = upgrades.get_int("half_life", -1);
            newmon->upgrade_group = mongroup_id( upgrades.get_string("into_group", mongroup_id::NULL_ID.str() ) );
            newmon->upgrade_into = mtype_id( upgrades.get_string("into", mtype_id::NULL_ID.str() ) );
            newmon->upgrades = true;
        }

        std::set<std::string> flags, anger_trig, placate_trig, fear_trig;
        flags = jo.get_tags("flags");
        anger_trig = jo.get_tags("anger_triggers");
        placate_trig = jo.get_tags("placate_triggers");
        fear_trig = jo.get_tags("fear_triggers");

        newmon->flags = get_set_from_tags(flags, flag_map, MF_NULL);
        newmon->anger = get_set_from_tags(anger_trig, trigger_map, MTRIG_NULL);
        newmon->fear = get_set_from_tags(fear_trig, trigger_map, MTRIG_NULL);
        newmon->placate = get_set_from_tags(placate_trig, trigger_map, MTRIG_NULL);

        mon_templates[mid] = newmon;
}
예제 #18
0
void load_martial_art(JsonObject &jo)
{
    martialart ma;
    JsonArray jsarr;

    ma.id = jo.get_string("id");
    ma.name = _(jo.get_string("name").c_str());
    ma.description = _(jo.get_string("description").c_str());

    jsarr = jo.get_array("static_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.static_buffs.push_back(load_buff(jsobj));
    }

    jsarr = jo.get_array("onmove_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.onmove_buffs.push_back(load_buff(jsobj));
    }

    jsarr = jo.get_array("onhit_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.onhit_buffs.push_back(load_buff(jsobj));
    }

    jsarr = jo.get_array("onattack_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.onattack_buffs.push_back(load_buff(jsobj));
    }

    jsarr = jo.get_array("ondodge_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.ondodge_buffs.push_back(load_buff(jsobj));
    }

    jsarr = jo.get_array("onblock_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.onblock_buffs.push_back(load_buff(jsobj));
    }

    jsarr = jo.get_array("ongethit_buffs");
    while (jsarr.has_more()) {
        JsonObject jsobj = jsarr.next_object();
        ma.onblock_buffs.push_back(load_buff(jsobj));
    }

    ma.techniques = jo.get_tags("techniques");
    ma.weapons = jo.get_tags("weapons");

    ma.leg_block = jo.get_int("leg_block", -1);
    ma.arm_block = jo.get_int("arm_block", -1);

    ma.arm_block_with_bio_armor_arms = jo.get_bool("arm_block_with_bio_armor_arms", false);
    ma.leg_block_with_bio_armor_legs = jo.get_bool("leg_block_with_bio_armor_legs", false);

    martialarts[ma.id] = ma;
}
예제 #19
0
bool map_bash_info::load(JsonObject &jsobj, std::string member, bool isfurniture) {
    if( jsobj.has_object(member) ) {
        JsonObject j = jsobj.get_object(member);

        if ( jsonint(j, "num_tests", num_tests ) == false ) {
           if ( jsonint(j, "str_min", str_min ) && jsonint(j, "str_max", str_max ) ) {
               num_tests = 1;
           }
        } else if ( num_tests > 0 ) {
           str_min = j.get_int("str_min");
           str_max = j.get_int("str_max");
        }

        jsonint(j, "str_min_blocked", str_min_blocked );
        jsonint(j, "str_max_blocked", str_max_blocked );
        jsonint(j, "str_min_roll", str_min_roll );
        jsonint(j, "explosive", explosive );
        jsonint(j, "chance", chance );
        jsonstring(j, "sound", sound );
        jsonstring(j, "sound_fail", sound_fail );
        jsonstring(j, "furn_set", furn_set );

        if ( jsonstring(j, "ter_set", ter_set ) == false && isfurniture == false ) {
           ter_set = "t_rubble";
           debugmsg("terrain[\"%s\"].bash.ter_set is not set!",jsobj.get_string("id").c_str() );
        }

        if ( j.has_array("items") ) {
           JsonArray ja = j.get_array("items");
           if (ja.size() > 0) {
               int c=0;
               while ( ja.has_more() ) {
                   if ( ja.has_object(c) ) {
                       JsonObject jio = ja.next_object();
                       if ( jio.has_string("item") && jio.has_int("amount") ) {
                           if ( jio.has_int("minamount") ) {
                               map_bash_item_drop drop( jio.get_string("item"), jio.get_int("amount"), jio.get_int("minamount") );
                               jsonint(jio, "chance", drop.chance);
                               items.push_back(drop);
                           } else {
                               map_bash_item_drop drop( jio.get_string("item"), jio.get_int("amount") );
                               jsonint(jio, "chance", drop.chance);
                               items.push_back(drop);
                           }
                       } else {
                           debugmsg("terrain[\"%s\"].bash.items[%d]: invalid entry",jsobj.get_string("id").c_str(),c);
                       }
                   } else {
                       debugmsg("terrain[\"%s\"].bash.items[%d]: invalid entry",jsobj.get_string("id").c_str(),c);
                   } 
                   c++;
               }
           }
        }
     
//debugmsg("%d/%d %s %s/%s %d",str_min,str_max, ter_set.c_str(), sound.c_str(), sound_fail.c_str(), items.size() );
    return true;
  } else {
    return false;
  }
}
예제 #20
0
void MonsterGroupManager::LoadMonsterGroup( JsonObject &jo )
{
    float mon_upgrade_factor = get_option<float>( "MONSTER_UPGRADE_FACTOR" );

    MonsterGroup g;

    g.name = mongroup_id( jo.get_string( "name" ) );
    bool extending = false;  //If already a group with that name, add to it instead of overwriting it
    if( monsterGroupMap.count( g.name ) != 0 && !jo.get_bool( "override", false ) ) {
        g = monsterGroupMap[g.name];
        extending = true;
    }
    if( !extending
        || jo.has_string( "default" ) ) { //Not mandatory to specify default if extending existing group
        g.defaultMonster = mtype_id( jo.get_string( "default" ) );
    }
    g.is_animal = jo.get_bool( "is_animal", false );
    if( jo.has_array( "monsters" ) ) {
        JsonArray monarr = jo.get_array( "monsters" );

        while( monarr.has_more() ) {
            JsonObject mon = monarr.next_object();
            const mtype_id name = mtype_id( mon.get_string( "monster" ) );

            int freq = mon.get_int( "freq" );
            int cost = mon.get_int( "cost_multiplier" );
            int pack_min = 1;
            int pack_max = 1;
            if( mon.has_member( "pack_size" ) ) {
                JsonArray packarr = mon.get_array( "pack_size" );
                pack_min = packarr.next_int();
                pack_max = packarr.next_int();
            }
            static const time_duration tdfactor = 1_hours;
            time_duration starts = 0_turns;
            time_duration ends = 0_turns;
            if( mon.has_member( "starts" ) ) {
                starts = tdfactor * mon.get_int( "starts" ) * ( mon_upgrade_factor > 0 ? mon_upgrade_factor : 1 );
            }
            if( mon.has_member( "ends" ) ) {
                ends = tdfactor * mon.get_int( "ends" ) * ( mon_upgrade_factor > 0 ? mon_upgrade_factor : 1 );
            }
            MonsterGroupEntry new_mon_group = MonsterGroupEntry( name, freq, cost, pack_min, pack_max, starts,
                                              ends );
            if( mon.has_member( "conditions" ) ) {
                JsonArray conditions_arr = mon.get_array( "conditions" );
                while( conditions_arr.has_more() ) {
                    new_mon_group.conditions.push_back( conditions_arr.next_string() );
                }
            }

            g.monsters.push_back( new_mon_group );
        }
    }
    g.replace_monster_group = jo.get_bool( "replace_monster_group", false );
    g.new_monster_group = mongroup_id( jo.get_string( "new_monster_group_id",
                                       mongroup_id::NULL_ID().str() ) );
    assign( jo, "replacement_time", g.monster_group_time, false, 1_days );
    g.is_safe = jo.get_bool( "is_safe", false );

    g.freq_total = jo.get_int( "freq_total", ( extending ? g.freq_total : 1000 ) );
    if( jo.get_bool( "auto_total", false ) ) { //Fit the max size to the sum of all freqs
        int total = 0;
        for( MonsterGroupEntry &mon : g.monsters ) {
            total += mon.frequency;
        }
        g.freq_total = total;
    }

    monsterGroupMap[g.name] = g;
}
예제 #21
0
void npc_class::load( JsonObject &jo, const std::string & )
{
    mandatory( jo, was_loaded, "name", name, translated_string_reader );
    mandatory( jo, was_loaded, "job_description", job_description, translated_string_reader );

    optional( jo, was_loaded, "common", common, true );
    bonus_str = load_distribution( jo, "bonus_str" );
    bonus_dex = load_distribution( jo, "bonus_dex" );
    bonus_int = load_distribution( jo, "bonus_int" );
    bonus_per = load_distribution( jo, "bonus_per" );

    optional( jo, was_loaded, "shopkeeper_item_group", shopkeeper_item_group, "EMPTY_GROUP" );
    optional( jo, was_loaded, "worn_override", worn_override );
    optional( jo, was_loaded, "carry_override", carry_override );
    optional( jo, was_loaded, "weapon_override", weapon_override );

    if( jo.has_array( "traits" ) ) {
        traits = trait_group::load_trait_group( *jo.get_raw( "traits" ), "collection" );
    }

    /* Mutation rounds can be specified as follows:
     *   "mutation_rounds": {
     *     "ANY" : { "constant": 1 },
     *     "INSECT" : { "rng": [1, 3] }
     *   }
     */
    if( jo.has_object( "mutation_rounds" ) ) {
        const std::map<std::string, mutation_category_trait> &mutation_categories =
            mutation_category_trait::get_all();
        auto jo2 = jo.get_object( "mutation_rounds" );
        for( auto &mutation : jo2.get_member_names() ) {
            auto category_match = [&mutation]( std::pair<const std::string, mutation_category_trait> p ) {
                return p.second.id == mutation;
            };
            if( std::find_if( mutation_categories.begin(), mutation_categories.end(),
                              category_match ) == mutation_categories.end() ) {
                debugmsg( "Unrecognized mutation category %s", mutation );
                continue;
            }
            auto distrib = jo2.get_object( mutation );
            mutation_rounds[mutation] = load_distribution( distrib );
        }
    }

    if( jo.has_array( "skills" ) ) {
        JsonArray jarr = jo.get_array( "skills" );
        while( jarr.has_more() ) {
            JsonObject skill_obj = jarr.next_object();
            auto skill_ids = skill_obj.get_tags( "skill" );
            if( skill_obj.has_object( "level" ) ) {
                distribution dis = load_distribution( skill_obj, "level" );
                for( const auto &sid : skill_ids ) {
                    skills[ skill_id( sid ) ] = dis;
                }
            } else {
                distribution dis = load_distribution( skill_obj, "bonus" );
                for( const auto &sid : skill_ids ) {
                    bonus_skills[ skill_id( sid ) ] = dis;
                }
            }
        }
    }
}