Power related cleanup and tweaks (#19577)

* Power related QOL

Enables visual feedback when SMES maintenance hatches are open. Also cleans up some of the code and magic numbers for power amounts for readability.

* Housekeeping pass on port_gens

* Better Multitool usage for power cables

Displaying More information and curbing instances of negative electricity being reported.

* MEGAWATTS

* that very readability thing I was talking about

* Better emp clearing

* I can maths right. Totally.

* Update code/modules/power/port_gen.dm

Co-authored-by: Cameron Lennox <killer65311@gmail.com>

---------

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
Poojawa
2026-07-17 06:18:35 -05:00
committed by GitHub
parent e69bbf73bd
commit 272987ac2a
8 changed files with 99 additions and 104 deletions
+2
View File
@@ -455,6 +455,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
// Format a power value in W, kW, MW, or GW.
/proc/DisplayPower(powerused)
if(powerused <= 0) //no negative numbers, please.
return "0 W"
if(powerused < 1000) //Less than a kW
return "[powerused] W"
else if(powerused < 1000000) //Less than a MW
+11 -11
View File
@@ -199,8 +199,8 @@ GLOBAL_LIST_INIT(possible_cable_coil_colours, list(
else
CC = new/obj/item/stack/cable_coil(T, 1, color)
src.add_fingerprint(user)
src.transfer_fingerprints_to(CC)
add_fingerprint(user)
transfer_fingerprints_to(CC)
for(var/mob/O in viewers(src, null))
O.show_message(span_warning("[user] cuts the cable."), 1)
@@ -225,21 +225,15 @@ GLOBAL_LIST_INIT(possible_cable_coil_colours, list(
return
coil.cable_join(src, user)
else if(istype(W, /obj/item/multitool))
if(powernet && (powernet.avail > 0)) // is it powered?
to_chat(user, span_warning("[DisplayPower(powernet.avail)] in power network."))
else
to_chat(user, span_warning("The cable is not powered."))
if(W.has_tool_quality(TOOL_MULTITOOL))
to_chat(user, get_power_info())
shock(user, 5, 0.2)
else
if(!(W.flags & NOCONDUCT))
shock(user, 50, 0.7)
src.add_fingerprint(user)
add_fingerprint(user)
// shock the user with probability prb
/obj/structure/cable/proc/shock(mob/user, prb, siemens_coeff = 1.0)
@@ -275,6 +269,12 @@ GLOBAL_LIST_INIT(possible_cable_coil_colours, list(
color_n = colorC
color = color_n
/obj/structure/cable/proc/get_power_info()
if(powernet?.avail > 0)
return span_warning("Total power: [DisplayPower(powernet.viewavail)]\nLoad: [DisplayPower(powernet.viewload)]\nExcess power: [DisplayPower(powernet.netexcess)]")
else
return span_warning("The cable is not powered.")
/////////////////////////////////////////////////
// Cable laying helpers
////////////////////////////////////////////////
+32 -24
View File
@@ -2,23 +2,24 @@
/obj/machinery/power/port_gen
name = "Placeholder Generator" //seriously, don't use this. It can't be anchored without VV magic.
desc = "A portable generator for emergency backup power"
icon = 'icons/obj/power_vr.dmi' //VOREStation Edit
icon_state = "portgen0" //VOREStation Edit
icon = 'icons/obj/power_vr.dmi'
icon_state = "portgen0"
density = TRUE
anchored = FALSE
use_power = USE_POWER_OFF
interact_offline = TRUE
var/active = 0
var/power_gen = 5000
var/recent_fault = 0
var/power_output = 1
var/active = FALSE
var/power_gen = 5 KILOWATTS
var/recent_fault = FALSE
var/power_output = TRUE
var/emp_duration = 0 SECONDS
/obj/machinery/power/port_gen/proc/IsBroken()
return (stat & (BROKEN|EMPED))
/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check.
return 1
return TRUE
/obj/machinery/power/port_gen/proc/UseFuel() //Placeholder for fuel use.
return
@@ -55,7 +56,7 @@
icon_state = initial(icon_state)
/obj/machinery/power/powered()
return 1 //doesn't require an external power source
return TRUE //doesn't require an external power source
/obj/machinery/power/port_gen/attack_hand(mob/user as mob)
if(..())
@@ -70,12 +71,14 @@
. += span_notice("The generator is on.")
else
. += span_notice("The generator is off.")
if(stat & EMPED)
. += span_warning("The generator's readout estimates [round((emp_duration - world.time) * 0.1)] seconds remaining until it can restart.")
/obj/machinery/power/port_gen/emp_act(severity, recursive)
. = ..()
if (. & EMP_PROTECT_SELF)
return
var/duration = 6000 //ten minutes
var/base_duration = 10 MINUTES
switch(severity)
if(EMP_HEAVY)
stat &= BROKEN
@@ -85,15 +88,20 @@
if(prob(10)) explode()
if(EMP_LIGHT)
if(prob(25)) stat &= BROKEN
duration = 300
base_duration = 3 MINUTES
if(EMP_HARMLESS)
if(prob(10)) stat &= BROKEN
duration = 300
base_duration = 3 MINUTES
stat |= EMPED
if(duration)
spawn(duration)
stat &= ~EMPED
emp_duration = world.time + base_duration
addtimer(CALLBACK(src, PROC_REF(clear_emp)), base_duration, TIMER_DELETE_ME)
/obj/machinery/power/port_gen/proc/clear_emp()
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
stat &= ~EMPED
emp_duration = 0
/obj/machinery/power/port_gen/proc/explode()
explosion(src.loc, -1, 3, 5, -1)
@@ -116,7 +124,7 @@
temperature_gain and max_temperature are set so that the max safe power level is 4.
Setting to 5 or higher can only be done temporarily before the generator overheats.
*/
power_gen = 20000 //Watts output per power_output level
power_gen = 20 KILOWATTS //Watts output per power_output level
var/max_power_output = 5 //The maximum power setting without emagging.
var/max_safe_output = 4 // For UI use, maximal output that won't cause overheat.
var/time_per_sheet = 96 //fuel efficiency - how long 1 sheet lasts at power level 1
@@ -166,8 +174,8 @@
/obj/machinery/power/port_gen/pacman/HasFuel()
var/needed_sheets = power_output / time_per_sheet
if(sheets >= needed_sheets - sheet_left)
return 1
return 0
return TRUE
return FALSE
//Removes one stack's worth of material from the generator.
/obj/machinery/power/port_gen/pacman/DropFuel()
@@ -225,7 +233,7 @@
overheat()
else if (overheating > 0)
overheating--
update_icon() //Port RS PR #484
update_icon()
/obj/machinery/power/port_gen/pacman/handleInactive()
var/cooling_temperature = 20
@@ -242,7 +250,7 @@
if(overheating)
overheating--
update_icon() //Port RS PR #484
update_icon()
/obj/machinery/power/port_gen/pacman/proc/overheat()
overheating++
@@ -267,8 +275,8 @@
explode() //if they're foolish enough to emag while it's running
if (!emagged)
emagged = 1
return 1
emagged = TRUE
return TRUE
/obj/machinery/power/port_gen/pacman/attackby(obj/item/O, mob/user)
if(istype(O, sheet_path))
@@ -382,7 +390,7 @@
icon_state = "portgen1"
sheet_path = /obj/item/stack/material/uranium
sheet_name = "Uranium Sheets"
time_per_sheet = 576 //same power output, but a 50 sheet stack will last 2 hours at max safe power
time_per_sheet = 2.5 MINUTES //same power output, but a 50 sheet stack will last 2 hours at max safe power
circuit = /obj/item/circuitboard/pacman/super
/obj/machinery/power/port_gen/pacman/super/UseFuel()
@@ -420,10 +428,10 @@
//I don't think tritium has any other use, so we might as well make this rewarding for players
//max safe power output (power level = 8) is 200 kW and lasts for 1 hour - 3 or 4 of these could power the station
power_gen = 25000 //watts
power_gen = 25 KILOWATTS //watts
max_power_output = 10
max_safe_output = 8
time_per_sheet = 576
time_per_sheet = 2.5 MINUTES
max_temperature = 800
temperature_gain = 90
circuit = /obj/item/circuitboard/pacman/mrs
+7 -9
View File
@@ -4,10 +4,9 @@
icon = 'icons/obj/power.dmi'
icon_state = "potato"
time_per_sheet = 1152 //same power output, but a 50 sheet stack will last 4 hours at max safe power
power_gen = 50000 //watts
power_gen = 50 KILOWATTS
anchored = TRUE
//Port Start, RS PR #484
/obj/machinery/power/port_gen/pacman/super/potato/Destroy()
. = ..()
cut_overlays() // sanity checks
@@ -32,7 +31,6 @@
return
else //off and it isn't angry, so we just vibe as 'off'
icon_state = initial(icon_state)
//Port Emd, RS PR #484
// Circuits for the RTGs below
/obj/item/circuitboard/machine/rtg
@@ -201,7 +199,7 @@
icon = 'icons/obj/power.dmi'
icon_state = "gridchecker_off"
name = "capacitor bank"
power_gen = 12000
power_gen = 12 KILOWATTS
// Void Core, power source for Abductor ships and bases.
// Provides a lot of power, but tends to explode when mistreated.
@@ -210,7 +208,7 @@
icon_state = "core-nocell"
desc = "An alien power source that produces energy seemingly out of nowhere."
circuit = /obj/item/circuitboard/machine/abductor/core
power_gen = 10000
power_gen = 10 KILOWATTS
irradiate = FALSE // Green energy!
can_buckle = FALSE
pixel_y = 7
@@ -326,7 +324,7 @@
icon_state = "bigdice"
bound_width = 64
bound_height = 64
power_gen = 30000
power_gen = 30 KILOWATTS
irradiate = FALSE // Green energy!
can_buckle = FALSE
@@ -361,7 +359,7 @@
circuit = /obj/item/circuitboard/machine/reg_d
irradiate = FALSE
power_gen = 0
var/default_power_gen = 1000000 //It's big but it gets adjusted based on what you put into it!!!
var/default_power_gen = 1 MEGAWATTS //It's big but it gets adjusted based on what you put into it!!!
var/part_mult = 0
var/nutrition_drain = 1
pixel_x = -32
@@ -488,7 +486,7 @@
bound_width = 64
bound_height = 64
anchored = TRUE
power_gen = 250000
power_gen = 250 KILOWATTS
var/sheet_name = "Phoron Sheets"
var/sheet_path = /obj/item/stack/material/phoron
@@ -568,7 +566,7 @@
desc = "Reacts hydrogen and anti-hydrogen with a phoron moderator to produce near limitless power! The magnetic fields are prone to easily rupturing, so the reactor design never took off."
icon = 'icons/am_engine.dmi'
icon_state = "core_on"
power_gen = 1000000 // 1MW
power_gen = 1 MEGAWATTS
irradiate = FALSE // Green energy!
can_buckle = FALSE
plane = ABOVE_MOB_PLANE
+30 -43
View File
@@ -3,8 +3,8 @@
GLOBAL_LIST_EMPTY(smeses)
//# define SMESMAXCHARGELEVEL 250000 Unused
//# define SMESMAXOUTPUT 250000 Unused
//# define SMESMAXCHARGELEVEL 250 KILOWATTS Unused
//# define SMESMAXOUTPUT 250 KILOWATTS Unused
/obj/machinery/power/smes
name = "power storage unit"
@@ -20,17 +20,17 @@ GLOBAL_LIST_EMPTY(smeses)
var/capacity = 5e6 // maximum charge
var/charge = 1e6 // actual charge
var/input_attempt = 0 // 1 = attempting to charge, 0 = not attempting to charge
var/inputting = 0 // 1 = actually inputting, 0 = not inputting
var/input_level = 50000 // amount of power the SMES attempts to charge by
var/input_level_max = 200000 // cap on input_level
var/input_available = 0 // amount of charge available from input last tick
var/input_attempt = 0 // 1 = attempting to charge, 0 = not attempting to charge
var/inputting = 0 // 1 = actually inputting, 0 = not inputting
var/input_level = 50 KILOWATTS // amount of power the SMES attempts to charge by
var/input_level_max = 200 KILOWATTS // cap on input_level
var/input_available = 0 // amount of charge available from input last tick
var/output_attempt = 1 // 1 = attempting to output, 0 = not attempting to output
var/outputting = 0 // 1 = actually outputting, 0 = not outputting
var/output_level = 50000 // amount of power the SMES attempts to output
var/output_level_max = 200000 // cap on output_level
var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power
var/output_attempt = 1 // 1 = attempting to output, 0 = not attempting to output
var/outputting = 0 // 1 = actually outputting, 0 = not outputting
var/output_level = 50 KILOWATTS // amount of power the SMES attempts to output
var/output_level_max = 200 KILOWATTS // cap on output_level
var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power
//Holders for powerout event.
var/last_output_attempt = 0
@@ -60,7 +60,7 @@ GLOBAL_LIST_EMPTY(smeses)
/obj/machinery/power/smes/drain_power(drain_check, surge, amount = 0)
if(drain_check)
return 1
return TRUE
var/smes_amt = min((amount * SMESRATE), charge)
charge -= smes_amt
@@ -140,8 +140,8 @@ GLOBAL_LIST_EMPTY(smeses)
/obj/machinery/power/smes/add_avail(amount)
if(..(amount))
powernet.smes_newavail += amount
return 1
return 0
return TRUE
return FALSE
/obj/machinery/power/smes/disconnect_terminal(obj/machinery/power/terminal/term)
terminals -= term
@@ -149,24 +149,30 @@ GLOBAL_LIST_EMPTY(smeses)
/obj/machinery/power/smes/update_icon()
cut_overlays()
if(stat & BROKEN) return
icon_state = "[initial(icon_state)]" //more sanity than anything else.
add_overlay("smes-op[outputting]")
if(stat & BROKEN)
icon_state = "[icon_state]-off" //for the "hybrid"/fancy SMES units mostly since they have a working screen animation
return
if(panel_open)
icon_state = "[icon_state]-o"
return //effectively off, but visually update.
add_overlay("[icon_state]-op[outputting]")
if(inputting == 2)
add_overlay("smes-oc2")
add_overlay("[icon_state]-oc2")
else if (inputting == 1)
add_overlay("smes-oc1")
add_overlay("[icon_state]-oc1")
else
if(input_attempt)
add_overlay("smes-oc0")
add_overlay("[icon_state]-oc0")
var/clevel = chargedisplay()
if(clevel>0)
add_overlay("smes-og[clevel]")
add_overlay("[icon_state]-og[clevel]")
return
/obj/machinery/power/smes/proc/chargedisplay()
return round(5.5*charge/(capacity ? capacity : 5e6))
@@ -588,32 +594,13 @@ GLOBAL_LIST_EMPTY(smeses)
name = "hybrid power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit, modified with alien technology to generate small amounts of power from seemingly nowhere."
icon = 'icons/obj/power_vr.dmi'
var/recharge_rate = 10000
var/recharge_rate = 10 KILOWATTS
var/overlay_icon = 'icons/obj/power_vr.dmi'
/obj/machinery/power/smes/buildable/hybrid/attackby(obj/item/W as obj, mob/user as mob)
if(W.has_tool_quality(TOOL_SCREWDRIVER) || W.has_tool_quality(TOOL_WIRECUTTER))
to_chat(user,span_warning("\The [src] full of weird alien technology that's best not messed with."))
return 0
/obj/machinery/power/smes/buildable/hybrid/update_icon()
cut_overlays()
if(stat & BROKEN) return
add_overlay("smes-op[outputting]")
if(inputting == 2)
add_overlay("smes-oc2")
else if (inputting == 1)
add_overlay("smes-oc1")
else
if(input_attempt)
add_overlay("smes-oc0")
var/clevel = chargedisplay()
if(clevel>0)
add_overlay("smes-og[clevel]")
return
return FALSE
/obj/machinery/power/smes/buildable/hybrid/process()
charge += min(recharge_rate, capacity - charge)
+17 -17
View File
@@ -11,61 +11,61 @@
desc = "The standard superconductive magnetic coil, with average capacity and I/O rating."
icon = 'icons/obj/stock_parts.dmi'
icon_state = "smes_coil" // Just few icons patched together. If someone wants to make better icon, feel free to do so!
w_class = ITEMSIZE_LARGE // It's LARGE (backpack size)
var/ChargeCapacity = 6000000 // 100 kWh
var/IOCapacity = 250000 // 250 kW
w_class = ITEMSIZE_LARGE // It's LARGE (backpack size)
var/ChargeCapacity = 6 MEGAWATTS // 100 kWh
var/IOCapacity = 250 KILOWATTS // 250 kW
// 20% Charge Capacity, 60% I/O Capacity. Used for substation/outpost SMESs.
/obj/item/smes_coil/weak
name = "basic superconductive magnetic coil"
desc = "A cheaper model of superconductive magnetic coil. Its capacity and I/O rating are considerably lower."
icon_state = "smes_coil_weak"
ChargeCapacity = 1200000 // 20 kWh
IOCapacity = 150000 // 150 kW
ChargeCapacity = 1.2 MEGAWATTS // 20 kWh
IOCapacity = 150 KILOWATTS // 150 kW
// Capacity Coils: High Capacity, Low Flow
/obj/item/smes_coil/super_capacity
name = "superconductive capacitance coil"
desc = "A specialised type of superconductive magnetic coil with a significantly stronger containment field, allowing for larger power storage. Its IO rating is much lower, however."
icon_state = "smes_coil_capacitance"
ChargeCapacity = 60000000 // 1000 kWh
IOCapacity = 50000 // 50 kW
ChargeCapacity = 60 MEGAWATTS // 1000 kWh
IOCapacity = 50 KILOWATTS // 50 kW
/obj/item/smes_coil/super_capacity/ultra
name = "ultraconductive capacitance coil"
desc = "A specialised type of superconductive magnetic coil with a significantly stronger containment field, allowing for larger power storage. Its IO rating is much lower, however."
icon_state = "smes_coil_capacitance_ultra"
ChargeCapacity = 120000000 // 2000 kWh
IOCapacity = 100000 // 100 kW
ChargeCapacity = 120 MEGAWATTS // 2000 kWh
IOCapacity = 100 KILOWATTS // 100 kW
/obj/item/smes_coil/super_capacity/hyper
name = "hyperconductive capacitance coil"
desc = "A specialised type of superconductive magnetic coil with a significantly stronger containment field, allowing for larger power storage. Its IO rating is much lower, however."
icon_state = "smes_coil_capacitance_hyper"
ChargeCapacity = 360000000 // 6000 kWh
IOCapacity = 200000 // 200 kW
ChargeCapacity = 360 MEGAWATTS // 6000 kWh
IOCapacity = 200 KILOWATTS // 200 kW
// Flow Coils: Low Capacity, High Flow
/obj/item/smes_coil/super_io
name = "superconductive transmission coil"
desc = "A specialised type of superconductive magnetic coil with reduced storage capabilites but vastly improved power transmission capabilities, making it useful in systems which require large throughput."
icon_state = "smes_coil_transmission"
ChargeCapacity = 600000 // 10 kWh
IOCapacity = 1000000 // 1000 kW
ChargeCapacity = 600 KILOWATTS // 10 kWh
IOCapacity = 1 MEGAWATTS // 1000 kW
/obj/item/smes_coil/super_io/ultra
name = "ultraconductive transmission coil"
desc = "A specialised type of superconductive magnetic coil with reduced storage capabilites but vastly improved power transmission capabilities, making it useful in systems which require large throughput."
icon_state = "smes_coil_transmission_ultra"
ChargeCapacity = 1200000 // 20 kWh
IOCapacity = 2000000 // 2000 kW
ChargeCapacity = 1.2 MEGAWATTS // 20 kWh
IOCapacity = 2 MEGAWATTS // 2000 kW
/obj/item/smes_coil/super_io/hyper
name = "hyperconductive transmission coil"
desc = "A specialised type of superconductive magnetic coil with reduced storage capabilites but vastly improved power transmission capabilities, making it useful in systems which require large throughput."
icon_state = "smes_coil_transmission_hyper"
ChargeCapacity = 2400000 // 40 kWh
IOCapacity = 6000000 // 6000 kW
ChargeCapacity = 2.4 MEGAWATTS // 40 kWh
IOCapacity = 6 MEGAWATTS // 6000 kW
// SMES SUBTYPES - THESE ARE MAPPED IN AND CONTAIN DIFFERENT TYPES OF COILS
Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB