Skip to content

Commit

Permalink
Powersinks now converts power to heat (tgstation#59309)
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskog authored May 27, 2021
1 parent 8918b74 commit de32a19
Showing 1 changed file with 71 additions and 36 deletions.
107 changes: 71 additions & 36 deletions code/game/objects/items/devices/powersink.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
. += "<span class='danger'>[src] is warping the air above it. It must be very hot.</span>"

/obj/item/powersink/set_anchored(anchorvalue)
. = ..()
density = anchorvalue
Expand All @@ -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)
Expand Down Expand Up @@ -122,46 +134,69 @@
"<span class='hear'>You hear a click.</span>")
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] - <A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>) 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] - <A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>) is 95% full. Explosion imminent.")
message_admins("Power sink at ([x],[y],[z] - <A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>) 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)

#undef DISCONNECTED
#undef CLAMPED_OFF
#undef OPERATING
#undef FRACTION_TO_RELEASE
#undef ALERT
#undef MINIMUM_HEAT

0 comments on commit de32a19

Please sign in to comment.