예제 #1
0
std::vector<comp_selection<item_comp>> craft_command::check_item_components_missing(
                                        const inventory &map_inv ) const
{
    std::vector<comp_selection<item_comp>> missing;

    for( const auto &item_sel : item_selections ) {
        itype_id type = item_sel.comp.type;
        item_comp component = item_sel.comp;
        long count = ( component.count > 0 ) ? component.count * batch_size : abs( component.count );

        if( item::count_by_charges( type ) && count > 0 ) {
            switch( item_sel.use_from ) {
                case use_from_player:
                    if( !crafter->has_charges( type, count ) ) {
                        missing.push_back( item_sel );
                    }
                    break;
                case use_from_map:
                    if( !map_inv.has_charges( type, count ) ) {
                        missing.push_back( item_sel );
                    }
                    break;
                case use_from_both:
                    if( !( crafter->charges_of( type ) + map_inv.charges_of( type ) >= count ) ) {
                        missing.push_back( item_sel );
                    }
                    break;
                case use_from_none:
                case cancel:
                    break;
            }
        } else {
            // Counting by units, not charges.
            switch( item_sel.use_from ) {
                case use_from_player:
                    if( !crafter->has_amount( type, count ) ) {
                        missing.push_back( item_sel );
                    }
                    break;
                case use_from_map:
                    if( !map_inv.has_components( type, count ) ) {
                        missing.push_back( item_sel );
                    }
                    break;
                case use_from_both:
                    if( !( crafter->amount_of( type ) + map_inv.amount_of( type ) >= count ) ) {
                        missing.push_back( item_sel );
                    }
                    break;
                case use_from_none:
                case cancel:
                    break;
            }
        }
    }

    return missing;
}
예제 #2
0
static bool player_can_build(player &p, inventory pinv, construction *con)
{
    if (p.skillLevel(con->skill) < con->difficulty) {
        return false;
    }

    bool has_tool = false;
    bool has_component = false;
    bool tools_required = false;
    bool components_required = false;

    for (int j = 0; j < con->tools.size(); j++) {
        if (con->tools[j].size() > 0) {
            tools_required = true;
            has_tool = false;
            for (unsigned k = 0; k < con->tools[j].size(); k++) {
                if (pinv.has_tools(con->tools[j][k].type, 1)) {
                    has_tool = true;
                    con->tools[j][k].available = 1;
                } else {
                    con->tools[j][k].available = -1;
                }
            }
            if (!has_tool) { // missing one of the tools for this stage
                break;
            }
        }
    }

    for (int j = 0; j < con->components.size(); ++j) {
        if (con->components[j].size() > 0) {
            components_required = true;
            has_component = false;
            for (unsigned k = 0; k < con->components[j].size(); k++) {
                if (( item_controller->find_template(con->components[j][k].type)->is_ammo() &&
                      pinv.has_charges(con->components[j][k].type,
                                       con->components[j][k].count)    ) ||
                    (!item_controller->find_template(con->components[j][k].type)->is_ammo() &&
                     pinv.has_components (con->components[j][k].type,
                                      con->components[j][k].count)    )) {
                    has_component = true;
                    con->components[j][k].available = 1;
                } else {
                    con->components[j][k].available = -1;
                }
            }
            if (!has_component) { // missing one of the comps for this stage
                break;
            }
        }
    }

    return (has_component || !components_required) &&
           (has_tool || !tools_required);
}
예제 #3
0
bool item_comp::has( const inventory &crafting_inv, int batch ) const
{
    if( g->u.has_trait( "DEBUG_HS" ) ) {
        return true;
    }

    const int cnt = std::abs( count ) * batch;
    if( item::count_by_charges( type ) ) {
        return crafting_inv.has_charges( type, cnt );
    } else {
        return crafting_inv.has_components( type, cnt );
    }
}
예제 #4
0
std::string item_comp::get_color( bool has_one, const inventory &crafting_inv, int batch ) const
{
    const int cnt = std::abs( count ) * batch;
    if( available == a_insufficent ) {
        return "brown";
    } else if( item::count_by_charges( type ) ) {
        if( crafting_inv.has_charges( type, cnt ) ) {
            return "green";
        }
    } else if( crafting_inv.has_components( type, cnt ) ) {
        return "green";
    }
    return has_one ? "dkgray" : "red";
}
예제 #5
0
bool requirements::check_enough_materials( const item_comp& comp, const inventory& crafting_inv ) const
{
    if( comp.available != a_true ) {
        return false;
    }
    const itype *it = item_controller->find_template( comp.type );
    const tool_comp *tq = find_by_type( tools, comp.type );
    if( tq != nullptr ) {
        // The very same item type is also needed as tool!
        // Use charges of it, or use it by count?
        const int tc = tq->count < 0 ? std::abs( tq->count ) : 1;
        // Check for components + tool count. Check item amount (excludes
        // pseudo items) and tool amount (includes pseudo items)
        // Imagine: required = 1 welder (component) + 1 welder (tool),
        // available = 1 welder (real item), 1 welding rig (creates
        // a pseudo welder item). has_components(welder,2) returns false
        // as there is only one real welder available, but has_tools(welder,2)
        // returns true.
        // Keep in mind that both requirements (tool+component) are checked
        // before this. That assures that one real item is actually available,
        // two welding rigs (and no real welder) would make this component
        // non-available even before this function is called.
        // Only ammo and (some) food is counted by charges, both are unlikely
        // to appear as tool, but it's possible /-:
        bool has_comps;
        if( it->count_by_charges() && comp.count > 0 ) {
            has_comps = crafting_inv.has_charges( comp.type, comp.count + tc );
        } else {
            has_comps = crafting_inv.has_components( comp.type, abs( comp.count ) + tc );
        }
        if( !has_comps && !crafting_inv.has_tools( comp.type, comp.count + tc ) ) {
            comp.available = a_insufficent;
        }
    }
    for( const auto &ql : it->qualities ) {
        const quality_requirement *qr = find_by_type( qualities, ql.first );
        if( qr == nullptr || qr->level > ql.second ) {
            continue;
        }
        // This item can be used for the quality requirement, same as above for specific
        // tools applies.
        if( !crafting_inv.has_items_with_quality( qr->type, qr->level, qr->count + abs(comp.count) ) ) {
            comp.available = a_insufficent;
        }
    }
    return comp.available == a_true;
}
예제 #6
0
std::string item_comp::get_color( bool has_one, const inventory &crafting_inv, int batch ) const
{
    if( type == "rope_30" || type == "rope_6" ) {
        if( g->u.has_trait( "WEB_ROPE" ) && g->u.get_hunger() <= 300 ) {
            return "ltgreen"; // Show that WEB_ROPE is on the job!
        }
    }
    const int cnt = std::abs( count ) * batch;
    if( available == a_insufficent ) {
        return "brown";
    } else if( item::count_by_charges( type ) ) {
        if( crafting_inv.has_charges( type, cnt ) ) {
            return "green";
        }
    } else if( crafting_inv.has_components( type, cnt ) ) {
        return "green";
    }
    return has_one ? "dkgray" : "red";
}
예제 #7
0
bool item_comp::has( const inventory &crafting_inv, int batch ) const
{
    // If you've Rope Webs, you can spin up the webbing to replace any amount of
    // rope your projects may require.  But you need to be somewhat nourished:
    // Famished or worse stops it.
    if( type == "rope_30" || type == "rope_6" ) {
        // NPC don't craft?
        // TODO: what about the amount of ropes vs the hunger?
        if( g->u.has_trait( "WEB_ROPE" ) && g->u.get_hunger() <= 300 ) {
            return true;
        }
    }
    const int cnt = std::abs( count ) * batch;
    if( item::count_by_charges( type ) ) {
        return crafting_inv.has_charges( type, cnt );
    } else {
        return crafting_inv.has_components( type, cnt );
    }
}
예제 #8
0
std::string item_comp::get_color( bool has_one, const inventory &crafting_inv ) const
{
    if( type == "rope_30" || type == "rope_6" ) {
        if( g->u.has_trait( "WEB_ROPE" ) && g->u.hunger <= 300 ) {
            return "ltgreen"; // Show that WEB_ROPE is on the job!
        }
    }
    const itype *it = item_controller->find_template( type );
    if( available == a_insufficent ) {
        return "brown";
    } else if( it->count_by_charges() && count > 0 ) {
        if( crafting_inv.has_charges( type, count ) ) {
            return "green";
        }
    } else if( crafting_inv.has_components( type, abs( count ) ) ) {
        return "green";
    }
    return has_one ? "dkgray" : "red";
}
예제 #9
0
bool item_comp::has( const inventory &crafting_inv ) const
{
    // If you've Rope Webs, you can spin up the webbing to replace any amount of
    // rope your projects may require.  But you need to be somewhat nourished:
    // Famished or worse stops it.
    if( type == "rope_30" || type == "rope_6" ) {
        // NPC don't craft?
        // TODO: what about the amount of ropes vs the hunger?
        if( g->u.has_trait( "WEB_ROPE" ) && g->u.hunger <= 300 ) {
            return true;
        }
    }
    const itype *it = item_controller->find_template( type );
    if( it->count_by_charges() && count > 0 ) {
        return crafting_inv.has_charges( type, count );
    } else {
        return crafting_inv.has_components( type, abs( count ) );
    }
}
예제 #10
0
/* selection of component if a recipe requirement has multiple options (e.g. 'duct tap' or 'welder') */
comp_selection<item_comp> player::select_item_component( const std::vector<item_comp> &components,
        int batch, inventory &map_inv, bool can_cancel )
{
    std::vector<item_comp> player_has;
    std::vector<item_comp> map_has;
    std::vector<item_comp> mixed;

    comp_selection<item_comp> selected;

    for( const auto &component : components ) {
        itype_id type = component.type;
        int count = ( component.count > 0 ) ? component.count * batch : abs( component.count );
        bool pl = false, mp = false;

        if( item::count_by_charges( type ) && count > 0 ) {
            if( has_charges( type, count ) ) {
                player_has.push_back( component );
                pl = true;
            }
            if( map_inv.has_charges( type, count ) ) {
                map_has.push_back( component );
                mp = true;
            }
            if( !pl && !mp && charges_of( type ) + map_inv.charges_of( type ) >= count ) {
                mixed.push_back( component );
            }
        } else { // Counting by units, not charges

            if( has_amount( type, count ) ) {
                player_has.push_back( component );
                pl = true;
            }
            if( map_inv.has_components( type, count ) ) {
                map_has.push_back( component );
                mp = true;
            }
            if( !pl && !mp && amount_of( type ) + map_inv.amount_of( type ) >= count ) {
                mixed.push_back( component );
            }

        }
    }

    /* select 1 component to use */
    if( player_has.size() + map_has.size() + mixed.size() == 1 ) { // Only 1 choice
        if( player_has.size() == 1 ) {
            selected.use_from = use_from_player;
            selected.comp = player_has[0];
        } else if( map_has.size() == 1 ) {
            selected.use_from = use_from_map;
            selected.comp = map_has[0];
        } else {
            selected.use_from = use_from_both;
            selected.comp = mixed[0];
        }
    } else { // Let the player pick which component they want to use
        uimenu cmenu;
        // Populate options with the names of the items
        for( auto &map_ha : map_has ) {
            std::string tmpStr = item::nname( map_ha.type ) + _( " (nearby)" );
            cmenu.addentry( tmpStr );
        }
        for( auto &player_ha : player_has ) {
            cmenu.addentry( item::nname( player_ha.type ) );
        }
        for( auto &elem : mixed ) {
            std::string tmpStr = item::nname( elem.type ) + _( " (on person & nearby)" );
            cmenu.addentry( tmpStr );
        }

        // Unlike with tools, it's a bad thing if there aren't any components available
        if( cmenu.entries.empty() ) {
            if( has_trait( trait_id( "DEBUG_HS" ) ) ) {
                selected.use_from = use_from_player;
                return selected;
            }

            debugmsg( "Attempted a recipe with no available components!" );
            selected.use_from = cancel;
            return selected;
        }

        if( can_cancel ) {
            cmenu.addentry( -1, true, 'q', _( "Cancel" ) );
        }

        // Get the selection via a menu popup
        cmenu.title = _( "Use which component?" );
        cmenu.query();

        if( cmenu.ret == static_cast<int>( map_has.size() + player_has.size() + mixed.size() ) ) {
            selected.use_from = cancel;
            return selected;
        }

        size_t uselection = static_cast<size_t>( cmenu.ret );
        if( uselection < map_has.size() ) {
            selected.use_from = usage::use_from_map;
            selected.comp = map_has[uselection];
        } else if( uselection < map_has.size() + player_has.size() ) {
            uselection -= map_has.size();
            selected.use_from = usage::use_from_player;
            selected.comp = player_has[uselection];
        } else {
            uselection -= map_has.size() + player_has.size();
            selected.use_from = usage::use_from_both;
            selected.comp = mixed[uselection];
        }
    }

    return selected;
}