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