From de32a195d700d39078031f526d87684858152fda Mon Sep 17 00:00:00 2001
From: skoglol <33292112+kriskog@users.noreply.github.com>
Date: Thu, 27 May 2021 13:26:07 +0200
Subject: [PATCH] Powersinks now converts power to heat (#59309)
---
code/game/objects/items/devices/powersink.dm | 107 ++++++++++++-------
1 file changed, 71 insertions(+), 36 deletions(-)
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 3681eecea2a30..d97393ed75ec3 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -2,11 +2,15 @@
#define CLAMPED_OFF 1
#define OPERATING 2
+#define FRACTION_TO_RELEASE 50
+#define ALERT 90
+#define MINIMUM_HEAT 10000
+
// Powersink - used to drain station power
/obj/item/powersink
name = "power sink"
- desc = "A nulling power sink which drains energy from electrical systems."
+ desc = "A power sink which drains energy from electrical systems and converts it to heat. Ensure short workloads and ample time to cool down if used in high energy systems."
icon = 'icons/obj/device.dmi'
icon_state = "powersink0"
inhand_icon_state = "electronic"
@@ -19,18 +23,24 @@
throw_speed = 1
throw_range = 2
custom_materials = list(/datum/material/iron=750)
- var/drain_rate = 2000000 // amount of power to drain per tick
- var/power_drained = 0 // has drained this much power
- var/max_power = 6e8 // maximum power that can be drained before exploding
- var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
- var/admins_warned = FALSE // stop spam, only warn the admins once that we are about to boom
+ var/max_heat = 5e7 // Maximum contained heat before exploding. Not actual temperature.
+ var/internal_heat = 0 // Contained heat, goes down every tick.
+ var/mode = DISCONNECTED // DISCONNECTED, CLAMPED_OFF, OPERATING
+ var/admins_warned = FALSE // Stop spam, only warn the admins once that we are about to boom.
- var/obj/structure/cable/attached // the attached cable
+ var/obj/structure/cable/attached
/obj/item/powersink/update_icon_state()
icon_state = "powersink[mode == OPERATING]"
return ..()
+/obj/item/powersink/examine(mob/user)
+ . = ..()
+ if(mode)
+ . += "\The [src] is bolted to the floor."
+ if(in_range(user, src) || isobserver(user) && internal_heat > max_heat * 0.5)
+ . += "[src] is warping the air above it. It must be very hot."
+
/obj/item/powersink/set_anchored(anchorvalue)
. = ..()
density = anchorvalue
@@ -41,15 +51,17 @@
switch(value)
if(DISCONNECTED)
attached = null
- if(mode == OPERATING)
+ if(mode == OPERATING && internal_heat < MINIMUM_HEAT)
STOP_PROCESSING(SSobj, src)
+ internal_heat = 0
set_anchored(FALSE)
if(CLAMPED_OFF)
if(!attached)
return
- if(mode == OPERATING)
+ if(mode == OPERATING && internal_heat < MINIMUM_HEAT)
STOP_PROCESSING(SSobj, src)
+ internal_heat = 0
set_anchored(TRUE)
if(OPERATING)
@@ -122,42 +134,62 @@
"You hear a click.")
set_mode(CLAMPED_OFF)
+/// Removes internal heat and shares it with the atmosphere.
+/obj/item/powersink/proc/release_heat()
+ var/turf/our_turf = get_turf(src)
+ var/temp_to_give = internal_heat / FRACTION_TO_RELEASE
+ internal_heat -= temp_to_give
+ var/datum/gas_mixture/environment = our_turf.return_air()
+ var/delta_temperature = temp_to_give / environment.heat_capacity()
+ if(delta_temperature)
+ environment.temperature += delta_temperature
+ air_update_turf(FALSE, FALSE)
+ if(admins_warned && internal_heat < max_heat * 0.75)
+ admins_warned = FALSE
+ message_admins("Power sink at ([x],[y],[z] - JMP) has cooled down and will not explode.")
+ if(mode != OPERATING && internal_heat < MINIMUM_HEAT)
+ internal_heat = 0
+ STOP_PROCESSING(SSobj, src)
+
+/// Drains power from the connected powernet, if any.
+/obj/item/powersink/proc/drain_power()
+ var/datum/powernet/PN = attached.powernet
+ var/drained = 0
+ set_light(5)
+
+ // Drain as much as we can from the powernet.
+ drained = attached.newavail()
+ attached.add_delayedload(drained)
+
+ // If tried to drain more than available on powernet, now look for APCs and drain their cells
+ for(var/obj/machinery/power/terminal/T in PN.nodes)
+ if(istype(T.master, /obj/machinery/power/apc))
+ var/obj/machinery/power/apc/A = T.master
+ if(A.operating && A.cell)
+ A.cell.charge = max(0, A.cell.charge - 50)
+ drained += 50
+ if(A.charging == 2) // If the cell was full
+ A.charging = 1 // It's no longer full
+ internal_heat += drained
+
/obj/item/powersink/process()
if(!attached)
set_mode(DISCONNECTED)
+
+ release_heat()
+
+ if(mode != OPERATING)
return
- var/datum/powernet/PN = attached.powernet
- if(PN)
- set_light(5)
-
- // found a powernet, so drain up to max power from it
-
- var/drained = min ( drain_rate, attached.newavail() )
- attached.add_delayedload(drained)
- power_drained += drained
-
- // if tried to drain more than available on powernet
- // now look for APCs and drain their cells
- if(drained < drain_rate)
- for(var/obj/machinery/power/terminal/T in PN.nodes)
- if(istype(T.master, /obj/machinery/power/apc))
- var/obj/machinery/power/apc/A = T.master
- if(A.operating && A.cell)
- A.cell.charge = max(0, A.cell.charge - 50)
- power_drained += 50
- if(A.charging == 2) // If the cell was full
- A.charging = 1 // It's no longer full
- if(drained >= drain_rate)
- break
-
- if(power_drained > max_power * 0.98)
+ drain_power()
+
+ if(internal_heat > max_heat * ALERT / 100)
if (!admins_warned)
admins_warned = TRUE
- message_admins("Power sink at ([x],[y],[z] - JMP) is 95% full. Explosion imminent.")
+ message_admins("Power sink at ([x],[y],[z] - JMP) has reached [ALERT]% of max heat. Explosion imminent.")
playsound(src, 'sound/effects/screech.ogg', 100, TRUE, TRUE)
- if(power_drained >= max_power)
+ if(internal_heat >= max_heat)
STOP_PROCESSING(SSobj, src)
explosion(src, devastation_range = 4, heavy_impact_range = 8, light_impact_range = 16, flash_range = 32)
qdel(src)
@@ -165,3 +197,6 @@
#undef DISCONNECTED
#undef CLAMPED_OFF
#undef OPERATING
+#undef FRACTION_TO_RELEASE
+#undef ALERT
+#undef MINIMUM_HEAT