Skip to content
Permalink
Browse files

Complete support for reactors

  • Loading branch information...
mugling committed Nov 27, 2016
1 parent 6d550e2 commit ffc84b7cd851a1f5e9b6e667fe86147570d778c9
Showing with 56 additions and 38 deletions.
  1. +1 −0 data/json/items/ammo.json
  2. +1 −1 src/bionics.cpp
  3. +1 −1 src/map.cpp
  4. +2 −2 src/pickup.cpp
  5. +38 −27 src/vehicle.cpp
  6. +12 −6 src/vehicle.h
  7. +1 −1 tests/vehicle_engine.cpp
@@ -179,6 +179,7 @@
"weight" : 80,
"ammo_type" : "plutonium",
"count" : 5,
"energy": 200,
"effects" : ["COOKOFF", "NEVER_MISFIRES"]
},
{
@@ -689,7 +689,7 @@ void player::process_bionic( int b )
continue;
}

wants_power_amt = veh->discharge_battery( wants_power_amt );
wants_power_amt = veh->discharge( wants_power_amt );
if( wants_power_amt == 0 ) {
charge_power( 1 );
break;
@@ -4681,7 +4681,7 @@ static void process_vehicle_items( vehicle *cur_veh, int part )
}
if( n.ammo_capacity() > n.ammo_remaining() ) {
constexpr int per_charge = 10;
const int missing = cur_veh->discharge_battery( per_charge, false );
const int missing = cur_veh->discharge( per_charge, false );
if( missing < per_charge &&
( missing == 0 || x_in_y( per_charge - missing, per_charge ) ) ) {
n.ammo_set( "battery", n.ammo_remaining() + 1 );
@@ -155,7 +155,7 @@ interact_results interact_with_vehicle( vehicle *veh, const tripoint &pos,
if( veh->fuel_left( "battery" ) < pseudo.ammo_required() ) {
return false;
}
auto qty = pseudo.ammo_capacity() - veh->discharge_battery( pseudo.ammo_capacity() );
auto qty = pseudo.ammo_capacity() - veh->discharge( pseudo.ammo_capacity() );
pseudo.ammo_set( "battery", qty );
g->u.invoke_item( &pseudo );
veh->charge_battery( pseudo.ammo_remaining() );
@@ -224,7 +224,7 @@ interact_results interact_with_vehicle( vehicle *veh, const tripoint &pos,
add_msg( m_good, _( "You purify the contents of the %1$s's %2$s" ),
veh->name.c_str(), tank.name().c_str() );

veh->discharge_battery( tank.ammo_remaining() * cost );
veh->discharge( tank.ammo_remaining() * cost );
tank.ammo_set( "water_clean", tank.ammo_remaining() );
}
}
@@ -985,7 +985,7 @@ void vehicle::use_controls( const tripoint &pos )
if( camera_on ) {
camera_on = false;
add_msg( _("Camera system disabled") );
} else if( fuel_left(fuel_type_battery, true) ) {
} else if( fuel_left(fuel_type_battery, true, true ) ) {
camera_on = true;
add_msg( _("Camera system enabled") );
} else {
@@ -1094,7 +1094,7 @@ bool vehicle::start_engine( const int e )
const vpart_info &einfo = part_info( engines[e] );
const vehicle_part &eng = parts[ engines[ e ] ];

if( !fuel_left( einfo.fuel_type ) ) {
if( !fuel_left( einfo.fuel_type, true, true ) ) {
if( einfo.fuel_type == fuel_type_muscle ) {
add_msg( _("The %s's mechanism is out of reach!"), name.c_str() );
} else {
@@ -1121,7 +1121,7 @@ bool vehicle::start_engine( const int e )
}

int joules = eng.base.engine_start_energy( g->temperature );
if( fuel_left( fuel_type_battery ) < joules ) {
if( fuel_left( fuel_type_battery, true, true ) < joules ) {
add_msg( _( "The %s need at least %i battery charges to start" ), eng.name().c_str(), joules );
return false;
}
@@ -1131,7 +1131,7 @@ bool vehicle::start_engine( const int e )
return false;
}

discharge_battery( joules, true );
discharge( joules, true );
return true;
}

@@ -1175,7 +1175,7 @@ void vehicle::backfire( const int e ) const

void vehicle::honk_horn()
{
const bool no_power = ! fuel_left( fuel_type_battery, true );
const bool no_power = !fuel_left( fuel_type_battery, true, true );
bool honked = false;

for( size_t p = 0; p < parts.size(); ++p ) {
@@ -1214,7 +1214,7 @@ void vehicle::honk_horn()
void vehicle::beeper_sound()
{
// No power = no sound
if( fuel_left( fuel_type_battery, true ) == 0 ) {
if( fuel_left( fuel_type_battery, true, true ) == 0 ) {
return;
}

@@ -2101,7 +2101,7 @@ bool vehicle::can_enable( const vehicle_part &pt, bool alert ) const

// @todo check fuel for combustion engines

if( fuel_left( "battery", true ) < -std::min( pt.info().epower, 0 ) ) {
if( fuel_left( "battery", true, true ) < -std::min( pt.info().epower, 0 ) ) {
if( alert ) {
add_msg( m_bad, _( "Insufficient power to enable %s" ), pt.name().c_str() );
}
@@ -2770,7 +2770,7 @@ point vehicle::pivot_displacement() const
return dp;
}

int vehicle::fuel_left (const itype_id & ftype, bool recurse) const
int vehicle::fuel_left( const itype_id &ftype, bool recurse, bool reactor ) const
{
int fl = std::accumulate( parts.begin(), parts.end(), 0, [&ftype]( const int &lhs, const vehicle_part &rhs ) {
return lhs + ( rhs.ammo_current() == ftype ? rhs.ammo_remaining() : 0 );
@@ -2787,6 +2787,17 @@ int vehicle::fuel_left (const itype_id & ftype, bool recurse) const
fl = traverse_vehicle_graph(this, fl + 1, fuel_counting_visitor) - 1;
}

if( ftype == fuel_type_battery && reactor ) {
for( const auto &pt : parts ) {
if( pt.is_reactor() && pt.enabled && !pt.is_broken() ) {
const itype *fuel = item::find_type( pt.ammo_current() );
if( fuel->ammo ) {
fl += pt.ammo_remaining() * fuel->ammo->energy;
}
}
}
}

//muscle engines have infinite fuel
if( ftype == fuel_type_muscle && g->m.veh_at( g->u.pos() ) == this && player_in_control( g->u ) &&
has_part( g->u.pos(), []( const vehicle_part &e ) {
@@ -2808,11 +2819,11 @@ int vehicle::fuel_capacity (const itype_id &ftype) const
int vehicle::drain (const itype_id & ftype, int amount) {
if( ftype == fuel_type_battery ) {
// Batteries get special handling to take advantage of jumper
// cables -- discharge_battery knows how to recurse properly
// cables -- discharge knows how to recurse properly
// (including taking cable power loss into account).
int remnant = discharge_battery(amount, true);
int remnant = discharge(amount, true);

// discharge_battery returns amount of charges that were not
// discharge returns amount of charges that were not
// found anywhere in the power network, whereas this function
// returns amount of charges consumed; simple subtraction.
return amount - remnant;
@@ -3372,44 +3383,44 @@ int vehicle::charge_battery (int amount, bool include_other_vehicles)
return amount;
}

int vehicle::discharge_battery (int amount, bool recurse)
int vehicle::discharge( int amount, bool recurse, bool reactor )
{
// try initially to obtain power from local batteries
for( auto &p : parts ) {
if( amount <= 0 ) {
break;
}
if( !p.is_broken() && p.is_battery() ) {
if( p.is_battery() && !p.is_broken() ) {
amount -= p.ammo_consume( amount, global_part_pos3( p ) );
}
}

auto discharge_visitor = [] (vehicle* veh, int amount, int lost) {
g->u.add_msg_if_player(m_debug, "CH: %d", amount + lost);
return veh->discharge_battery(amount + lost, false);
};
if(amount > 0 && recurse) { // need more power!
amount = traverse_vehicle_graph(this, amount, discharge_visitor);
// if insufficient local power try any networked vehicles
if( amount > 0 && recurse ) {
amount = traverse_vehicle_graph( this, amount, []( vehicle *veh, int amount, int lost ) {
return veh->discharge( amount + lost, false, false );
} );
}

// if insufficient local or network electrical power try to engage any reactors
if( amount > 0 ) {
if( amount > 0 && reactor ) {
for( auto &pt : parts ) {

// consider only enabled reactors that have remaining fuel
if( pt.is_reactor() && pt.enabled && pt.ammo_remaining() ) {
if( pt.is_reactor() && pt.enabled && !pt.is_broken() && pt.ammo_remaining() ) {

const itype *fuel = item::find_type( pt.ammo_current() );
if( fuel->ammo ) {
assert( fuel->ammo->energy > 0 ); // enforced in item_factory.cpp
int density = fuel->ammo->energy;

// calculate electrical power (kJ) reactor will provide
int qty = std::min( amount, int( pt.ammo_remaining() * density ) );
int qty = std::min( amount, int( pt.ammo_remaining() * double( density ) / 1000 ) );

// calculate reactor charges that will be consumed...
double burn = double( qty ) / density;

// partial charges have a proportional chance of being consumed each turn
// ...partial charges have a proportional chance of being consumed each turn
burn += x_in_y( fmod( burn, 1.0 ) * 1000, 1000 ) ? 1 : 0;

pt.ammo_consume( burn, global_part_pos3( pt ) );
@@ -3423,7 +3434,7 @@ int vehicle::discharge_battery (int amount, bool recurse)
}
}

return amount; // non-zero if we weren't able to fulfill demand.
return amount;
}

void vehicle::idle(bool on_map) {
@@ -3435,8 +3446,8 @@ void vehicle::idle(bool on_map) {
// ...so partial charges have a proportional chance of being consumed each turn
deficit += x_in_y( deficit % 1000, 1000 ) ? 1000 : 0;

// electrical power not supplied from battery must be found from alternators or reactors
deficit = discharge_battery( deficit / 1000 );
// electrical power not supplied must be found from alternators
deficit = discharge( deficit / 1000, true, true );

// calculate maximum possible output from all active alternators
int generate = 0;
@@ -3718,7 +3729,7 @@ void vehicle::operate_scoop()
sounds::sound( position, rng(10, that_item_there->volume() / units::legacy_volume_factor * 2 + 10),
_("BEEEThump") );
}
const int battery_deficit = discharge_battery( that_item_there->weight() *
const int battery_deficit = discharge( that_item_there->weight() *
-part_epower( scoop ) / rng( 8, 15 ) );
if( battery_deficit == 0 && add_item( scoop, *that_item_there ) ) {
g->m.i_rem( position, itemdex );
@@ -775,12 +775,16 @@ class vehicle : public JsonSerializer, public JsonDeserializer
*/
std::map<itype_id, long> fuels_left() const;

// Checks how much certain fuel left in tanks.
int fuel_left (const itype_id &ftype, bool recurse = false) const;
/**
* How much of a given fuel type is available from various sources
* @param recurse for battery power should networked vehicles be considered?
* @param reactor for battery power should active reactors be considered?
*/
int fuel_left( const itype_id &ftype, bool recurse = false, bool reactor = false ) const;

int fuel_capacity (const itype_id &ftype) const;

// drains a fuel type (e.g. for the kitchen unit)
// returns amount actually drained, does not engage reactor
int drain (const itype_id &ftype, int amount);

/**
@@ -796,11 +800,13 @@ class vehicle : public JsonSerializer, public JsonDeserializer
int charge_battery (int amount, bool recurse = true);

/**
* Try to discharge our (and, optionally, connected vehicles') batteries by the given amount.
* @note if insufficient power is available any active reactors will be engaged
* Attempt to obtain electrical power from various sources
* @param amount maximum power (kJ) to obtain
* @param recurse if insufficient local power available should networked vehicles be drained?
* @param reactor if insufficient power is available should active reactors will be engaged?
* @return amount of request unfulfilled (0 if totally successful).
*/
int discharge_battery (int amount, bool recurse = true);
int discharge( int amount, bool recurse = true, bool reactor = true );

/**
* Mark mass caches and pivot cache as dirty
@@ -38,7 +38,7 @@ TEST_CASE( "vehicle_engine", "[vehicle] [engine]" ) {
REQUIRE( veh.safe_velocity( pt ) <= veh.max_velocity( pt ) );

// sufficient power available to start the engine at 10°C
REQUIRE( base->engine_start_energy( 10 ) <= veh.fuel_left( "battery" ) );
REQUIRE( base->engine_start_energy( 10 ) <= veh.fuel_left( "battery", true, true ) );
}

g->m.destroy_vehicle( &veh );

0 comments on commit ffc84b7

Please sign in to comment.
You can’t perform that action at this time.