Files
Bubberstation/code/game/objects/items/devices/powersink.dm
SkyratBot b6ffb1e31b [MIRROR] Refactor /turf/var/intact [MDB IGNORE] (#9114)
* Refactor /turf/var/intact (#62331)

Turfs have a variable, intact, which conflates three meanings:

    Determining whether there's something that can be pried out, such as directly with a crowbar or indirectly with a tile stack and a crowbar off-hand.
    Determining whether underfloor pieces are visible.
    Determining whether underfloor pieces can be interacted with - by players with tools, through interaction with effects like chemical acid, or foam.

When plating is hit with a stack of tiles, /turf/open/floor/attackby checks whether the turf is intact, and if so, ends the attack chain regardless of whether or not the attempt to hotswap a turf (with a crowbar) is successful or not. However, turfs which want the underfloor to be visible - such as catwalks and glass - set the intact variable to FALSE, and so can be repeatedly placed over one another, as if they were the first tile to be placed over the plating.

This refactors /turf/var/intact into two distinct variables:

    /turf/var/overfloor_placed, for whether or not there is something over plating.
    /turf/var/underfloor_visible, for whether or not the various underfloor pieces should be invisible, visible, or both visible and interactable.

All references to /turf/var/intact have been replaced with an equivalent overfloor_placed or underfloor_visible reference, depending on which check is appropriate. underfloor_accessibility can take one of UNDERFLOOR_HIDDEN, UNDERFLOOR_VISIBLE, or UNDERFLOOR_INTERACTABLE. This prevents cases such as acid foam or tools phasing through glass floors to affect the underfloor pieces underneath, and covers all kinds of unusual, not-wiring-visiblity usage such as Holodeck completeness, Revenant interaction, or station integrity checking.

* Refactor /turf/var/intact

* Thank

Co-authored-by: esainane <esainane+github@gmail.com>
Co-authored-by: Funce <funce.973@gmail.com>
2021-10-30 00:19:21 +13:00

203 lines
6.4 KiB
Plaintext

#define DISCONNECTED 0
#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 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"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
item_flags = NO_PIXEL_RANDOM_DROP
throwforce = 5
throw_speed = 1
throw_range = 2
custom_materials = list(/datum/material/iron=750)
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
/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_danger("[src] is warping the air above it. It must be very hot.")
/obj/item/powersink/set_anchored(anchorvalue)
. = ..()
set_density(anchorvalue)
/obj/item/powersink/proc/set_mode(value)
if(value == mode)
return
switch(value)
if(DISCONNECTED)
attached = null
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 && internal_heat < MINIMUM_HEAT)
STOP_PROCESSING(SSobj, src)
internal_heat = 0
set_anchored(TRUE)
if(OPERATING)
if(!attached)
return
START_PROCESSING(SSobj, src)
set_anchored(TRUE)
mode = value
update_appearance()
set_light(0)
/obj/item/powersink/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_WRENCH)
if(mode == DISCONNECTED)
var/turf/T = loc
if(isturf(T) && T.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE)
attached = locate() in T
if(!attached)
to_chat(user, span_warning("\The [src] must be placed over an exposed, powered cable node!"))
else
set_mode(CLAMPED_OFF)
user.visible_message( \
"[user] attaches \the [src] to the cable.", \
span_notice("You bolt \the [src] into the floor and connect it to the cable."),
span_hear("You hear some wires being connected to something."))
else
to_chat(user, span_warning("\The [src] must be placed over an exposed, powered cable node!"))
else
set_mode(DISCONNECTED)
user.visible_message( \
"[user] detaches \the [src] from the cable.", \
span_notice("You unbolt \the [src] from the floor and detach it from the cable."),
span_hear("You hear some wires being disconnected from something."))
else if(I.tool_behaviour == TOOL_SCREWDRIVER)
user.visible_message( \
"[user] messes with \the [src] for a bit.", \
span_notice("You can't fit the screwdriver into \the [src]'s bolts! Try using a wrench."))
else
return ..()
/obj/item/powersink/attack_paw(mob/user, list/modifiers)
return
/obj/item/powersink/attack_ai()
return
/obj/item/powersink/attack_hand(mob/user, list/modifiers)
. = ..()
if(.)
return
switch(mode)
if(DISCONNECTED)
..()
if(CLAMPED_OFF)
user.visible_message( \
"[user] activates \the [src]!", \
span_notice("You activate \the [src]."),
span_hear("You hear a click."))
message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_VERBOSEJMP(src)]")
log_game("Power sink activated by [key_name(user)] at [AREACOORD(src)]")
set_mode(OPERATING)
if(OPERATING)
user.visible_message( \
"[user] deactivates \the [src]!", \
span_notice("You deactivate \the [src]."),
span_hear("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] - <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
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>) has reached [ALERT]% of max heat. Explosion imminent.")
playsound(src, 'sound/effects/screech.ogg', 100, TRUE, TRUE)
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