Пример #1
0
void quality_requirement::load( JsonArray &jsarr )
{
    JsonObject quality_data = jsarr.next_object();
    type = quality_id( quality_data.get_string( "id" ) );
    level = quality_data.get_int( "level", 1 );
    count = quality_data.get_int( "amount", 1 );
    if( count <= 0 ) {
        quality_data.throw_error( "quality amount must be a positive number", "amount" );
    }
    // Note: level is not checked, negative values and 0 are allow, see butchering quality.
}
Пример #2
0
int visitable<Character>::amount_of( const std::string& what, bool pseudo, int limit ) const
{
    auto self = static_cast<const Character *>( this );

    if( what == "toolset" && pseudo && self->has_active_bionic( "bio_tools" ) ) {
        return 1;
    }

    if( what == "apparatus" && pseudo ) {
        int qty = 0;
        visit_items( [&qty, &limit] ( const item *e ) {
            qty += e->get_quality( quality_id( "SMOKE_PIPE" ) ) >= 1;
            return qty < limit ? VisitResponse::SKIP : VisitResponse::ABORT;
        } );
        return std::min( qty, limit );
    }

    return amount_of_internal( *this, what, pseudo, limit );
}
Пример #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
requirement_data requirement_data::disassembly_requirements() const
{
    // TODO:
    // Allow jsonizing those tool replacements

    // Make a copy
    // Maybe TODO: Cache it somewhere and return a reference instead
    requirement_data ret = *this;
    auto new_qualities = std::vector<quality_requirement>();
    for( auto &it : ret.tools ) {
        bool replaced = false;
        for( const auto &tool : it ) {
            const itype_id &type = tool.type;

            // If crafting required a welder or forge then disassembly requires metal sawing
            if( type == "welder" || type == "welder_crude" || type == "oxy_torch" ||
                type == "forge" || type == "char_forge" ) {
                new_qualities.emplace_back( quality_id( "SAW_M_FINE" ), 1, 1 );
                replaced = true;
                break;
            }

            if( type == "sewing_kit" ||
                type == "mold_plastic" ) {
                new_qualities.emplace_back( quality_id( "CUT" ), 1, 1 );
                replaced = true;
                break;
            }

            if( type == "crucible" ) {
                replaced = true;
                break;
            }
        }

        if( replaced ) {
            // Replace the entire block of variants
            // This avoids the pesky integrated toolset
            it.clear();
        }
    }

    // Warning: This depends on the fact that tool qualities
    // are all mandatory (don't use variants)
    // If that ever changes, this will be wrong!
    if( ret.qualities.empty() ) {
        ret.qualities.resize( 1 );
    }

    auto &qualities = ret.qualities[0];
    qualities.insert( qualities.end(), new_qualities.begin(), new_qualities.end() );
    // Remove duplicate qualities
    {
        auto itr = std::unique( qualities.begin(), qualities.end(),
                                []( const quality_requirement & a, const quality_requirement & b ) {
                                    return a.type == b.type;
                                } );
        qualities.resize( std::distance( qualities.begin(), itr ) );
    }

    // Remove empty variant sections
    ret.tools.erase( std::remove_if( ret.tools.begin(), ret.tools.end(),
                                     []( const std::vector<tool_comp> &tcv ) {
                                         return tcv.empty();
                                     } ), ret.tools.end() );
    // Remove unrecoverable components
    ret.components.erase( std::remove_if( ret.components.begin(), ret.components.end(),
        []( std::vector<item_comp> &cov ) {
            cov.erase( std::remove_if( cov.begin(), cov.end(),
                []( const item_comp &comp ) {
                    return !comp.recoverable || item( comp.type ).has_flag( "UNRECOVERABLE" );
                } ), cov.end() );
            return cov.empty();
        } ), ret.components.end() );

    return ret;
}
Пример #5
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 = vehicle_part_types.find( vpart_str_id( jo.get_string( "copy-from" ) ) );
        auto const ab = abstract_parts.find( vpart_str_id( jo.get_string( "copy-from" ) ) );
        if( base != vehicle_part_types.end() ) {
            def = base->second;
        } else if( ab != abstract_parts.end() ) {
            def = ab->second;
        } else {
            deferred.emplace_back( jo.str(), src );
        }
    }

    if( jo.has_string( "abstract" ) ) {
        def.id = vpart_str_id( jo.get_string( "abstract" ) );
    } else {
        def.id = vpart_str_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, "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 );

    auto reqs = jo.get_object( "requirements" );
    if( reqs.has_object( "install" ) ) {
        auto ins = reqs.get_object( "install" );

        auto sk = ins.get_array( "skills" );
        if( !sk.empty() ) {
            def.install_skills.clear();
        }
        while( sk.has_more() ) {
            auto cur = sk.next_array();
            def.install_skills.emplace( skill_id( cur.get_string( 0 ) ) , cur.size() >= 2 ? cur.get_int( 1 ) : 1 );
        }

        assign( ins, "time", def.install_moves );

        if( ins.has_string( "using" ) ) {
            def.install_reqs = { { requirement_id( ins.get_string( "using" ) ), 1 } };

        } else if( ins.has_array( "using" ) ) {
            auto arr = ins.get_array( "using" );
            while( arr.has_more() ) {
                auto cur = arr.next_array();
                def.install_reqs.emplace_back( requirement_id( cur.get_string( 0 ) ), cur.get_int( 1 ) );
            }

        } else {
            auto req_id = std::string( "inline_vehins_" ) += def.id.str();
            requirement_data::load_requirement( ins, req_id );
            def.install_reqs = { { requirement_id( req_id ), 1 } };
        }

        def.legacy = false;
    }
    if( reqs.has_object( "removal" ) ) {
        auto rem = reqs.get_object( "removal" );

        auto sk = rem.get_array( "skills" );
        if( !sk.empty() ) {
            def.removal_skills.clear();
        }
        while( sk.has_more() ) {
            auto cur = sk.next_array();
            def.removal_skills.emplace( skill_id( cur.get_string( 0 ) ) , cur.size() >= 2 ? cur.get_int( 1 ) : 1 );
        }

        assign( rem, "time", def.removal_moves );

        if( rem.has_string( "using" ) ) {
            def.removal_reqs = { { requirement_id( rem.get_string( "using" ) ), 1 } };

        } else if( rem.has_array( "using" ) ) {
            auto arr = rem.get_array( "using" );
            while( arr.has_more() ) {
                auto cur = arr.next_array();
                def.removal_reqs.emplace_back( requirement_id( cur.get_string( 0 ) ), cur.get_int( 1 ) );
            }

        } else {
            auto req_id = std::string( "inline_vehins_" ) += def.id.str();
            requirement_data::load_requirement( rem, req_id );
            def.removal_reqs = { { requirement_id( req_id ), 1 } };
        }

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

    auto const iter = vehicle_part_types.find( def.id );
    if( iter != vehicle_part_types.end() ) {
        // Entry in the map already exists, so the pointer in the vector is already correct
        // and does not need to be changed, only the int-id needs to be taken from the old entry.
        def.loadid = iter->second.loadid;
        iter->second = def;
    } else {
        // The entry is new, "generate" a new int-id and link the new entry from the vector.
        def.loadid = vpart_id( vehicle_part_int_types.size() );
        vpart_info &new_entry = vehicle_part_types[ def.id ];
        new_entry = def;
        vehicle_part_int_types.push_back( &new_entry );
    }    
}
Пример #6
0
requirement_data requirement_data::disassembly_requirements() const
{
    // TODO:
    // Allow jsonizing those tool replacements

    // Make a copy
    // Maybe TODO: Cache it somewhere and return a reference instead
    requirement_data ret = *this;
    auto new_qualities = std::vector<quality_requirement>();
    for( auto &it : ret.tools ) {
        bool replaced = false;
        for( const auto &tool : it ) {
            const itype_id &type = tool.type;

            // If crafting required a welder or forge then disassembly requires metal sawing
            if( type == "welder" || type == "welder_crude" || type == "oxy_torch" ||
                type == "forge" || type == "char_forge" ) {
                new_qualities.emplace_back( quality_id( "SAW_M_FINE" ), 1, 1 );
                replaced = true;
                break;
            }
            //This only catches instances where the two tools are explicitly stated, and not just the required sewing quality
            if( type == "sewing_kit" ||
                type == "mold_plastic" ) {
                new_qualities.emplace_back( quality_id( "CUT" ), 1, 1 );
                replaced = true;
                break;
            }

            if( type == "crucible" ) {
                replaced = true;
                break;
            }
        }

        if( replaced ) {
            // Replace the entire block of variants
            // This avoids the pesky integrated toolset
            it.clear();
        }
    }

    // Warning: This depends on the fact that tool qualities
    // are all mandatory (don't use variants)
    // If that ever changes, this will be wrong!
    if( ret.qualities.empty() ) {
        ret.qualities.resize( 1 );
    } else {
        //If the required quality level is not empty, iterate through and replace or remove
        //qualities with deconstruction equivalents
        for( auto &it : ret.qualities ) {
            bool replaced = false;
            for( const auto &quality : it ) {
                if( quality.type == quality_id( "SEW" ) ) {
                    replaced = true;
                    new_qualities.emplace_back( quality_id( "CUT" ), 1, quality.level );
                    break;
                }
                if( quality.type == quality_id( "GLARE" ) ) {
                    replaced = true;
                    //Just remove the glare protection requirement from deconstruction
                    //This only happens in case of a reversible recipe, an explicit
                    //deconstruction recipe can still specify glare protection
                    break;
                }
                if( quality.type == quality_id( "KNIT" ) ) {
                    replaced = true;
                    //Ditto for knitting needles
                    break;
                }
            }
            if( replaced ) {
                it.clear();
            }
        }
    }

    auto &qualities = ret.qualities[0];
    qualities.insert( qualities.end(), new_qualities.begin(), new_qualities.end() );
    // Remove duplicate qualities
    {
        auto itr = std::unique( qualities.begin(), qualities.end(),
        []( const quality_requirement & a, const quality_requirement & b ) {
            return a.type == b.type;
        } );
        qualities.resize( std::distance( qualities.begin(), itr ) );
    }

    // Remove empty variant sections
    ret.tools.erase( std::remove_if( ret.tools.begin(), ret.tools.end(),
    []( const std::vector<tool_comp> &tcv ) {
        return tcv.empty();
    } ), ret.tools.end() );
    // Remove unrecoverable components
    ret.components.erase( std::remove_if( ret.components.begin(), ret.components.end(),
    []( std::vector<item_comp> &cov ) {
        cov.erase( std::remove_if( cov.begin(), cov.end(),
        []( const item_comp & comp ) {
            return !comp.recoverable || item( comp.type ).has_flag( "UNRECOVERABLE" );
        } ), cov.end() );
        return cov.empty();
    } ), ret.components.end() );

    return ret;
}