Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Charge bionics from UPS via Cable Charger System CBM + bugfixes for solar backpacks #33546

Merged
merged 11 commits into from
Sep 4, 2019
2 changes: 1 addition & 1 deletion data/json/bionics.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
"type": "bionic",
"name": "Cable Charger System",
"capacity": 10,
"description": "You have a complex port surgically mounted above your hip. While active, it will recharge bionic power when connected to a battery via jumper cable.",
"description": "You have a complex port surgically mounted above your hip. While active, it will recharge bionic power when connected to a power source via jumper cable.",
"occupied_bodyparts": [ [ "TORSO", 10 ] ],
"flags": [ "BIONIC_POWER_SOURCE", "BIONIC_SHOCKPROOF", "BIONIC_TOGGLED" ]
},
Expand Down
8 changes: 5 additions & 3 deletions data/json/items/tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
"type": "TOOL",
"name": "UPS",
"name_plural": "UPS's",
"description": "This is a unified power supply, or UPS. It is a device developed jointly by military and scientific interests for use in combat and the field. The UPS is designed to power armor and some guns, but drains batteries quickly.",
"description": "This is a unified power supply, or UPS. It is a device developed jointly by military and scientific interests for use in combat and the field. The UPS is designed to power bionics, armor and some guns, but drains batteries quickly.",
"weight": 680,
"volume": "2500 ml",
"price": 280000,
Expand All @@ -121,7 +121,8 @@
"magazines": [
[ "battery", [ "heavy_plus_battery_cell", "heavy_battery_cell", "heavy_atomic_battery_cell", "heavy_disposable_cell" ] ]
],
"magazine_well": 4
"magazine_well": 4,
"flags": [ "IS_UPS" ]
},
{
"id": "acidbomb",
Expand Down Expand Up @@ -155,7 +156,8 @@
"symbol": ";",
"color": "light_green",
"ammo": "plutonium",
"max_charges": 2500
"max_charges": 2500,
"flags": [ "IS_UPS" ]
},
{
"id": "advanced_ecig",
Expand Down
4 changes: 2 additions & 2 deletions data/json/items/vehicle/cables.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": "TOOL",
"id": "jumper_cable",
"name": "jumper cable",
"description": "A jumper cable, like you've seen many times before: it's a short multi-stranded copper cable with power leads on either end, whose purpose is to share power between vehicles.",
"description": "A jumper cable, like you've seen many times before: it's a short multi-stranded copper cable with power leads on either end, whose main purpose is to share power between vehicles, but can also link other electrical systems.",
"to_hit": 1,
"color": "light_blue",
"symbol": "&",
Expand All @@ -22,7 +22,7 @@
"type": "TOOL",
"id": "jumper_cable_heavy",
"name": "heavy-duty cable",
"description": "A long, thick, heavy-duty cable with power leads on either end. It looks like you could use it to hook up two vehicles to each other, though you expect the power loss would be noticeable.",
"description": "A long, thick, heavy-duty cable with power leads on either end. It looks like you could use it to hook up two vehicles to each other, though you expect the power loss would be noticeable. Can also link other electrical systems.",
"volume": "1500 ml",
"weight": 750,
"max_charges": 20,
Expand Down
1 change: 1 addition & 0 deletions doc/JSON_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,7 @@ Melee flags are fully compatible with tool flags, and vice versa.
- ```FISH_GOOD``` When used for fishing, it's a good tool (requires that the matching use_action has been set).
- ```FISH_POOR``` When used for fishing, it's a poor tool (requires that the matching use_action has been set).
- ```HAS_RECIPE``` Used by the E-Ink tablet to indicates it's currently showing a recipe.
- ```IS_UPS``` Item is Unified Power Supply. Used in active item processing
- ```LIGHT_[X]``` Illuminates the area with light intensity `[X]` where `[X]` is an intensity value. (e.x. `LIGHT_4` or `LIGHT_100`).
- ```MC_MOBILE```, ```MC_RANDOM_STUFF```, ```MC_SCIENCE_STUFF```, ```MC_USED```, ```MC_HAS_DATA``` Memory card related flags, see `iuse.cpp`
- ```NO_DROP``` Item should never exist on map tile as a discrete item (must be contained by another item)
Expand Down
81 changes: 63 additions & 18 deletions src/bionics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,28 +670,49 @@ bool player::activate_bionic( int b, bool eff_only )
reactor_plut = 0;
}
} else if( bio.id == "bio_cable" ) {
bool has_cable = has_item_with( []( const item & it ) {
return it.active && it.has_flag( "CABLE_SPOOL" );
} );
bool has_connected_cable = has_item_with( []( const item & it ) {
return it.active && it.has_flag( "CABLE_SPOOL" ) && it.get_var( "state" ) == "solar_pack_link";
std::vector<item *> cables = items_with( []( const item & it ) {
return it.has_flag( "CABLE_SPOOL" );
} );

bool has_cable = cables.empty();
nexusmrsep marked this conversation as resolved.
Show resolved Hide resolved
bool free_cable = false;
if( !has_cable ) {
add_msg_if_player( m_info,
_( "You need a jumper cable connected to a vehicle to drain power from it." ) );
}
if( is_wearing( "solarpack_on" ) || is_wearing( "q_solarpack_on" ) ) {
if( has_connected_cable ) {
add_msg_if_player( m_info, _( "Your plugged-in solar pack is now able to charge"
" your system." ) );
} else {
add_msg_if_player( m_info, _( "You need to connect the cable to yourself and the solar pack"
" before your solar pack can charge your system." ) );
_( "You need a jumper cable connected to a power source to drain power from it." ) );
} else {
for( item *cable : cables ) {
const std::string state = cable->get_var( "state" );
if( state == "cable_charger" ) {
add_msg_if_player( m_info,
_( "Cable is plugged-in to the CBM but it has to be also connected to the power source." ) );
}
if( state == "cable_charger_link" ) {
add_msg_if_player( m_info,
_( "You are plugged to the vehicle. It will charge you if it has some juice in it." ) );
}
if( state == "solar_pack_link" ) {
add_msg_if_player( m_info,
_( "You are plugged to a solar pack. It will charge you if it's unfolded and in sunlight." ) );
}
if( state == "UPS_link" ) {
add_msg_if_player( m_info,
_( "You are plugged to a UPS. It will charge you if it has some juice in it." ) );
}
if( state == "solar_pack" || state == "UPS" ) {
add_msg_if_player( m_info,
_( "You have a cable plugged to a portable power source, but you need to plug it in to the CBM." ) );
}
if( state == "pay_oyt_cable" ) {
add_msg_if_player( m_info,
_( "You have a cable plugged to a vehicle, but you need to plug it in to the CBM." ) );
}
if( state == "attach_first" ) {
free_cable = true;
}
}
} else if( is_wearing( "solarpack" ) || is_wearing( "q_solarpack" ) ) {
add_msg_if_player( m_info, _( "You might plug in your solar pack to the cable charging"
" system, if you unfold it." ) );
}
if( free_cable ) {
add_msg_if_player( m_info,
_( "You have at least one free cable in your inventory that you could use to plug yourself in." ) );
}
}

Expand Down Expand Up @@ -973,6 +994,30 @@ void player::process_bionic( int b )
for( const item *cable : cables ) {
const cata::optional<tripoint> target = cable->get_cable_target( this, pos() );
if( !target ) {
if( g->m.is_outside( pos() ) && !is_night( calendar::turn ) &&
cable->get_var( "state" ) == "solar_pack_link" ) {
double modifier = g->natural_light_level( pos().z ) / default_daylight_level();
// basic solar panel produces 50W = 1 charge/20_seconds = 180 charges/hour(3600)
if( is_wearing( "solarpack_on" ) && x_in_y( 180 * modifier, 3600 ) ) {
charge_power( 1 );
}
// quantum solar backpack = solar panel x6
if( is_wearing( "q_solarpack_on" ) && x_in_y( 6 * 180 * modifier, 3600 ) ) {
charge_power( 1 );
}
}
if( cable->get_var( "state" ) == "UPS_link" ) {
static const item_filter used_ups = [&]( const item & itm ) {
return itm.get_var( "cable" ) == "plugged_in";
};
if( has_charges( "UPS_off", 1, used_ups ) ) {
use_charges( "UPS_off", 1, used_ups );
charge_power( 1 );
} else if( has_charges( "adv_UPS_off", 1, used_ups ) ) {
use_charges( "adv_UPS_off", roll_remainder( 0.6 ), used_ups );
charge_power( 1 );
}
}
continue;
}
const optional_vpart_position vp = g->m.veh_at( *target );
Expand Down
68 changes: 60 additions & 8 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3520,6 +3520,8 @@ std::string item::tname( unsigned int quantity, bool with_prefix, unsigned int t
}
if( active && ( has_flag( "WATER_EXTINGUISH" ) || has_flag( "LITCIG" ) ) ) {
ret << _( " (lit)" );
} else if( has_flag( "IS_UPS" ) && get_var( "cable" ) == "plugged_in" ) {
ret << _( " (plugged in)" );
} else if( active && !is_food() && !is_corpse() && ( typeId().length() < 3 ||
typeId().compare( typeId().length() - 3, 3, "_on" ) != 0 ) ) {
// Usually the items whose ids end in "_on" have the "active" or "on" string already contained
Expand Down Expand Up @@ -8201,18 +8203,46 @@ cata::optional<tripoint> item::get_cable_target( player *p, const tripoint &pos
return g->m.getlocal( source );
}

bool item::process_cable( player *p, const tripoint &pos )
bool item::process_cable( player *carrier, const tripoint &pos )
{
const cata::optional<tripoint> source = get_cable_target( p, pos );
if( carrier == nullptr ) {
reset_cable( carrier );
return false;
}
std::string state = get_var( "state" );
if( state == "solar_pack_link" || state == "solar_pack" ) {
if( !carrier->has_item( *this ) || ( !carrier->is_wearing( "solarpack_on" ) ||
!carrier->is_wearing( "solarpack_on" ) ) ) {
nexusmrsep marked this conversation as resolved.
Show resolved Hide resolved
carrier->add_msg_if_player( m_bad, _( "You notice the cable has come loose!" ) );
reset_cable( carrier );
return false;
}
}

static const item_filter used_ups = [&]( const item & itm ) {
return itm.get_var( "cable" ) == "plugged_in";
};

if( state == "UPS" ) {
if( !carrier->has_item( *this ) || ( !carrier->has_item_with( used_ups ) ) ) {
nexusmrsep marked this conversation as resolved.
Show resolved Hide resolved
carrier->add_msg_if_player( m_bad, _( "You notice the cable has come loose!" ) );
for( item *used : carrier->items_with( used_ups ) ) {
used->erase_var( "cable" );
}
reset_cable( carrier );
return false;
}
}
const cata::optional<tripoint> source = get_cable_target( carrier, pos );
if( !source ) {
return false;
}

if( !g->m.veh_at( *source ) || ( source->z != g->get_levz() && !g->m.has_zlevels() ) ) {
if( p != nullptr && p->has_item( *this ) ) {
p->add_msg_if_player( m_bad, _( "You notice the cable has come loose!" ) );
if( carrier != nullptr && carrier->has_item( *this ) ) {
carrier->add_msg_if_player( m_bad, _( "You notice the cable has come loose!" ) );
}
reset_cable( p );
reset_cable( carrier );
return false;
}

Expand All @@ -8221,10 +8251,10 @@ bool item::process_cable( player *p, const tripoint &pos )
charges = max_charges - distance;

if( charges < 1 ) {
if( p != nullptr && p->has_item( *this ) ) {
p->add_msg_if_player( m_bad, _( "The over-extended cable breaks loose!" ) );
if( carrier != nullptr && carrier->has_item( *this ) ) {
carrier->add_msg_if_player( m_bad, _( "The over-extended cable breaks loose!" ) );
}
reset_cable( p );
reset_cable( carrier );
}

return false;
Expand All @@ -8247,6 +8277,24 @@ void item::reset_cable( player *p )
}
}

bool item::process_UPS( player *carrier, const tripoint & /*pos*/ )
{
if( carrier == nullptr ) {
erase_var( "cable" );
active = false;
return false;
}
bool has_connected_cable = carrier->has_item_with( []( const item & it ) {
return it.active && it.has_flag( "CABLE_SPOOL" ) && ( it.get_var( "state" ) == "UPS_link" ||
it.get_var( "state" ) == "UPS" );
} );
if( !has_connected_cable ) {
erase_var( "cable" );
active = false;
}
return false;
}

bool item::process_wet( player * /*carrier*/, const tripoint & /*pos*/ )
{
if( item_counter == 0 ) {
Expand Down Expand Up @@ -8415,6 +8463,10 @@ bool item::process( player *carrier, const tripoint &pos, bool activate,
// DO NOT process this as a tool! It really isn't!
return process_cable( carrier, pos );
}
if( has_flag( "IS_UPS" ) ) {
// DO NOT process this as a tool! It really isn't!
return process_UPS( carrier, pos );
}
if( is_tool() ) {
return process_tool( carrier, pos );
}
Expand Down
3 changes: 2 additions & 1 deletion src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -2020,7 +2020,8 @@ class item : public visitable<item>
// Place conditions that should remove fake smoke item in this sub-function
bool process_fake_smoke( player *carrier, const tripoint &pos );
bool process_fake_mill( player *carrier, const tripoint &pos );
bool process_cable( player *p, const tripoint &pos );
bool process_cable( player *carrier, const tripoint &pos );
nexusmrsep marked this conversation as resolved.
Show resolved Hide resolved
bool process_UPS( player *carrier, const tripoint &pos );
bool process_blackpowder_fouling( player *carrier );
bool process_tool( player *carrier, const tripoint &pos );

Expand Down
Loading