void recipe_dictionary::finalize()
{
    if( !DynamicDataLoader::get_instance().load_deferred( deferred ) ) {
        debugmsg( "JSON contains circular dependency: discarded %i recipes", deferred.size() );
    }

    finalize_internal( recipe_dict.recipes );
    finalize_internal( recipe_dict.uncraft );

    for( auto &e : recipe_dict.recipes ) {
        auto &r = e.second;

        for( const auto &bk : r.booksets ) {
            islot_book::recipe_with_description_t desc{ &r, bk.second, item::nname( r.result ), false };
            item::find_type( bk.first )->book->recipes.insert( desc );
        }

        if( r.contained && r.container == "null" ) {
            r.container = item::find_type( r.result )->default_container;
        }

        if( r.autolearn ) {
            r.autolearn_requirements = r.required_skills;
            if( r.skill_used ) {
                r.autolearn_requirements[ r.skill_used ] = r.difficulty;
            }
        }

        // add recipe to category and component caches
        recipe_dict.category[r.category].insert( &r );

        for( const auto &opts : r.requirements().get_components() ) {
            for( const item_comp &comp : opts ) {
                recipe_dict.component[comp.type].insert( &r );
            }
        }

        // if reversible and no specific uncraft recipe exists use this recipe
        if( r.reversible && !recipe_dict.uncraft.count( r.result ) ) {
            recipe_dict.uncraft[ r.result ] = r;
        }
    }

    // add pseudo uncrafting recipes
    for( const auto &e : item_controller->get_all_itypes() ) {

        // books that don't alreay have an uncrafting recipe
        if( e.second->book && !recipe_dict.uncraft.count( e.first ) && e.second->volume > 0 ) {
            int pages = e.second->volume / units::from_milliliter( 12.5 );
            auto &bk = recipe_dict.uncraft[ e.first ];
            bk.ident_ = e.first;
            bk.result = e.first;
            bk.reversible = true;
            bk.requirements_ = *requirement_id( "uncraft_book" ) * pages;
            bk.time = pages * 10; // @todo allow specifying time in requirement_data
        }
    }
}
Пример #2
0
recipe &recipe_dictionary::load( JsonObject &jo, const std::string &src,
                                 std::map<std::string, recipe> &dest )
{
    recipe r;

    // defer entries dependent upon as-yet unparsed definitions
    if( jo.has_string( "copy-from" ) ) {
        auto base = jo.get_string( "copy-from" );
        if( !dest.count( base ) ) {
            deferred.emplace_back( jo.str(), src );
            return null_recipe;
        }
        r = dest[ base ];
    }

    r.load( jo, src );

    dest[ r.ident() ] = std::move( r );

    return dest[ r.ident() ];
}
Пример #3
0
/**
 * Reads in a vehicle part from a JsonObject.
 */
void vpart_info::load( JsonObject &jo, const std::string &src )
{
    vpart_info def;

    if( jo.has_string( "copy-from" ) ) {
        auto const base = vpart_info_all.find( vpart_id( jo.get_string( "copy-from" ) ) );
        auto const ab = abstract_parts.find( vpart_id( jo.get_string( "copy-from" ) ) );
        if( base != vpart_info_all.end() ) {
            def = base->second;
        } else if( ab != abstract_parts.end() ) {
            def = ab->second;
        } else {
            deferred.emplace_back( jo.str(), src );
            return;
        }
    }

    if( jo.has_string( "abstract" ) ) {
        def.id = vpart_id( jo.get_string( "abstract" ) );
    } else {
        def.id = vpart_id( jo.get_string( "id" ) );
    }

    assign( jo, "name", def.name_ );
    assign( jo, "item", def.item );
    assign( jo, "location", def.location );
    assign( jo, "durability", def.durability );
    assign( jo, "damage_modifier", def.dmg_mod );
    assign( jo, "power", def.power );
    assign( jo, "epower", def.epower );
    assign( jo, "fuel_type", def.fuel_type );
    assign( jo, "default_ammo", def.default_ammo );
    assign( jo, "folded_volume", def.folded_volume );
    assign( jo, "size", def.size );
    assign( jo, "difficulty", def.difficulty );
    assign( jo, "bonus", def.bonus );
    assign( jo, "flags", def.flags );

    if( jo.has_member( "requirements" ) ) {
        auto reqs = jo.get_object( "requirements" );

        parse_vp_reqs( reqs, def.id.str(), "install", def.install_reqs, def.install_skills, def.install_moves );
        parse_vp_reqs( reqs, def.id.str(), "removal", def.removal_reqs, def.removal_skills, def.removal_moves );
        parse_vp_reqs( reqs, def.id.str(), "repair",  def.repair_reqs,  def.repair_skills,  def.repair_moves  );

        def.legacy = false;
    }

    if( jo.has_member( "symbol" ) ) {
        def.sym = jo.get_string( "symbol" )[ 0 ];
    }
    if( jo.has_member( "broken_symbol" ) ) {
        def.sym_broken = jo.get_string( "broken_symbol" )[ 0 ];
    }

    if( jo.has_member( "color" ) ) {
        def.color = color_from_string( jo.get_string( "color" ) );
    }
    if( jo.has_member( "broken_color" ) ) {
        def.color_broken = color_from_string( jo.get_string( "broken_color" ) );
    }

    if( jo.has_member( "breaks_into" ) ) {
        JsonIn& stream = *jo.get_raw( "breaks_into" );
        def.breaks_into_group = item_group::load_item_group( stream, "collection" );
    }

    auto qual = jo.get_array( "qualities" );
    if( !qual.empty() ) {
        def.qualities.clear();
        while( qual.has_more() ) {
            auto pair = qual.next_array();
            def.qualities[ quality_id( pair.get_string( 0 ) ) ] = pair.get_int( 1 );
        }
    }

    if( jo.has_member( "damage_reduction" ) ) {
        JsonObject dred = jo.get_object( "damage_reduction" );
        def.damage_reduction = load_damage_array( dred );
    } else {
        def.damage_reduction.fill( 0.0f );
    }

    if( jo.has_string( "abstract" ) ) {
        abstract_parts[def.id] = def;
    } else {
        vpart_info_all[def.id] = def;
    }
}
Пример #4
0
void recipe_dictionary::load( JsonObject &jo, const std::string &src, bool uncraft )
{
    bool strict = src == "core";

    recipe r;

    // defer entries dependent upon as-yet unparsed definitions
    if( jo.has_string( "copy-from" ) ) {
        auto base = jo.get_string( "copy-from" );
        if( uncraft ) {
            if( !recipe_dict.uncraft.count( base ) ) {
                deferred.emplace_back( jo.str(), src );
                return;
            }
            r = recipe_dict.uncraft[ base ];
        } else {
            if( !recipe_dict.recipes.count( base ) ) {
                deferred.emplace_back( jo.str(), src );
                return;
            }
            r = recipe_dict.recipes[ base ];
        }
    }

    if( jo.has_string( "abstract" ) ) {
        r.ident_ = jo.get_string( "abstract" );
        r.abstract = true;
    } else {
        r.ident_ = r.result = jo.get_string( "result" );
        r.abstract = false;
    }

    if( !uncraft ) {
        if( jo.has_string( "id_suffix" ) ) {
            if( r.abstract ) {
                jo.throw_error( "abstract recipe cannot specify id_suffix", "id_suffix" );
            }
            r.ident_ += "_" + jo.get_string( "id_suffix" );
        }
        assign( jo, "category", r.category, strict );
        assign( jo, "subcategory", r.subcategory, strict );
        assign( jo, "reversible", r.reversible, strict );
    } else {
        r.reversible = true;
    }

    assign( jo, "time", r.time, strict, 0 );
    assign( jo, "difficulty", r.difficulty, strict, 0, MAX_SKILL );
    assign( jo, "flags", r.flags );

    // automatically set contained if we specify as container
    assign( jo, "contained", r.contained, strict );
    r.contained |= assign( jo, "container", r.container, strict );

    if( jo.has_array( "batch_time_factors" ) ) {
        auto batch = jo.get_array( "batch_time_factors" );
        r.batch_rscale = batch.get_int( 0 ) / 100.0;
        r.batch_rsize  = batch.get_int( 1 );
    }

    assign( jo, "charges", r.charges );
    assign( jo, "result_mult", r.result_mult );

    assign( jo, "skill_used", r.skill_used, strict );

    if( jo.has_member( "skills_required" ) ) {
        auto sk = jo.get_array( "skills_required" );
        r.required_skills.clear();

        if( sk.empty() ) {
            // clear all requirements

        } else if( sk.has_array( 0 ) ) {
            // multiple requirements
            while( sk.has_more() ) {
                auto arr = sk.next_array();
                r.required_skills[skill_id( arr.get_string( 0 ) )] = arr.get_int( 1 );
            }

        } else {
            // single requirement
            r.required_skills[skill_id( sk.get_string( 0 ) )] = sk.get_int( 1 );
        }
    }

    // simplified autolearn sets requirements equal to required skills at finalization
    if( jo.has_bool( "autolearn" ) ) {
        assign( jo, "autolearn", r.autolearn );

    } else if( jo.has_array( "autolearn" ) ) {
        r.autolearn = true;
        auto sk = jo.get_array( "autolearn" );
        while( sk.has_more() ) {
            auto arr = sk.next_array();
            r.autolearn_requirements[skill_id( arr.get_string( 0 ) )] = arr.get_int( 1 );
        }
    }

    if( jo.has_member( "decomp_learn" ) ) {
        r.learn_by_disassembly.clear();

        if( jo.has_int( "decomp_learn" ) ) {
            if( !r.skill_used ) {
                jo.throw_error( "decomp_learn specified with no skill_used" );
            }
            assign( jo, "decomp_learn", r.learn_by_disassembly[r.skill_used] );

        } else if( jo.has_array( "decomp_learn" ) ) {
            auto sk = jo.get_array( "decomp_learn" );
            while( sk.has_more() ) {
                auto arr = sk.next_array();
                r.learn_by_disassembly[skill_id( arr.get_string( 0 ) )] = arr.get_int( 1 );
            }
        }
    }

    if( !uncraft && jo.has_member( "byproducts" ) ) {
        auto bp = jo.get_array( "byproducts" );
        r.byproducts.clear();
        while( bp.has_more() ) {
            auto arr = bp.next_array();
            r.byproducts[ arr.get_string( 0 ) ] += arr.size() == 2 ? arr.get_int( 1 ) : 1;
        }
    }

    if( jo.has_member( "book_learn" ) ) {
        auto bk = jo.get_array( "book_learn" );
        r.booksets.clear();

        while( bk.has_more() ) {
            auto arr = bk.next_array();
            r.booksets.emplace( arr.get_string( 0 ), arr.get_int( 1 ) );
        }
    }

    // recipes not specifying any external requirements inherit from their parent recipe (if any)
    if( jo.has_string( "using" ) ) {
        r.reqs_external = { { requirement_id( jo.get_string( "using" ) ), 1 } };

    } else if( jo.has_array( "using" ) ) {
        auto arr = jo.get_array( "using" );
        r.reqs_external.clear();

        while( arr.has_more() ) {
            auto cur = arr.next_array();
            r.reqs_external.emplace_back( requirement_id( cur.get_string( 0 ) ), cur.get_int( 1 ) );
        }
    }

    // inline requirements are always replaced (cannot be inherited)
    auto req_id = string_format( "inline_%s_%s", uncraft ? "uncraft" : "recipe", r.ident_.c_str() );
    requirement_data::load_requirement( jo, req_id );
    r.reqs_internal = { { requirement_id( req_id ), 1 } };

    if( uncraft ) {
        recipe_dict.uncraft[ r.ident_ ] = r;
    } else {
        recipe_dict.recipes[ r.ident_ ] = r;
    }
}
Пример #5
0
void vpart_info::finalize()
{
    if( !DynamicDataLoader::get_instance().load_deferred( deferred ) ) {
        debugmsg( "JSON contains circular dependency: discarded %i vehicle parts", deferred.size() );
    }

    for( auto& e : vpart_info_all ) {
        // if part name specified ensure it is translated
        // otherwise the name of the base item will be used
        if( !e.second.name_.empty() ) {
            e.second.name_ = _( e.second.name_.c_str() );
        }

        if( e.second.folded_volume > 0 ) {
            e.second.set_flag( "FOLDABLE" );
        }

        for( const auto& f : e.second.flags ) {
            auto b = vpart_bitflag_map.find( f );
            if( b != vpart_bitflag_map.end() ) {
                e.second.bitflags.set( b->second );
            }            
        }

        e.second.power = hp_to_watt( e.second.power );

        // Calculate and cache z-ordering based off of location
        // list_order is used when inspecting the vehicle
        if( e.second.location == "on_roof" ) {
            e.second.z_order = 9;
            e.second.list_order = 3;
        } else if( e.second.location == "on_cargo" ) {
            e.second.z_order = 8;
            e.second.list_order = 6;
        } else if( e.second.location == "center" ) {
            e.second.z_order = 7;
            e.second.list_order = 7;
        } else if( e.second.location == "under" ) {
            // Have wheels show up over frames
            e.second.z_order = 6;
            e.second.list_order = 10;
        } else if( e.second.location == "structure" ) {
            e.second.z_order = 5;
            e.second.list_order = 1;
        } else if( e.second.location == "engine_block" ) {
            // Should be hidden by frames
            e.second.z_order = 4;
            e.second.list_order = 8 ;
        } else if( e.second.location == "on_battery_mount" ){
            // Should be hidden by frames
            e.second.z_order = 3;
            e.second.list_order = 10;
        } else if( e.second.location == "fuel_source" ) {
            // Should be hidden by frames
            e.second.z_order = 3;
            e.second.list_order = 9;
        } else if( e.second.location == "roof" ) {
            // Shouldn't be displayed
            e.second.z_order = -1;
            e.second.list_order = 4;
        } else if( e.second.location == "armor" ) {
            // Shouldn't be displayed (the color is used, but not the symbol)
            e.second.z_order = -2;
            e.second.list_order = 2;
        } else {
            // Everything else
            e.second.z_order = 0;
            e.second.list_order = 5;
        }
    }
}