Files
Bubberstation/code/game/objects/items/devices/powersink.dm
Rhials c5dce84be8 Deadchat Announcement Variety Pack 1 (#75140)
## About The Pull Request

Adds announce_to_ghosts()/notify_ghosts() calls to a bunch of different
things.

**THIS INCLUDES:**
- Powersink being activated/reaching critical (explosion) heat capacity.
- His Grace being awoken.
- Hot Potatoes being armed.
- Ascension Rituals being completed.
- Eyesnatcher victims.
- Ovens exploding as a result of the Aurora Caelus event.
- Wizard Imposter spawns.
- Rock-Paper-Scissors with death as the result of Helbital consumption.
- BSA impact sites.
- Spontaneous Appendicitis.
- The purchasing of a badass syndie balloon.
- The Supermatter beginning to delaminate.

This was everything that I could think of that would be worth announcing
to deadchat. These were all chosen with consideration to questions like
"how easy would it be to spam deadchat with this?" and "will observers
actually see the interesting thing happen, or just the aftermath?".

Not gonna lie, I've really become an observer main as of recently. Maybe
that's being reflected in my recent PRs. Who's to say? Deadchat
Announcement Variety Pack 2 will probably never come out. Sorry.
## Why It's Good For The Game

Gives deadchat a better indiciation of when/where something **REALLY
FUNNY** is about to happen. Draws attention to certain things that are
likely to gather an audience anyways, but sooner (for your viewing
pleasure). In simple terms, it helps the observers observe things
better.

Some cases, such as the aurora caelus or helbitaljanken, are occurrences
so rare that they deserve the audience.
## Changelog
🆑 Rhials
qol: Observers now recieve an alert when a powersink is activated/about
to explode.
qol: His Grace being awoken now alerts observers, to give you a
headstart on your murderbone ghost ring.
qol: Ascension Rituals being completed will also alert observers, for
basically the same reason.
qol: Arming a hot potato will now alert observers. Catch!
qol: Eyesnatcher victims will now notify observers, and invite them to
laugh at their state of misery and impotence.
qol: Observers will be notified of any acute references to The Simpsons
or other 20th Television America copyright properties.
qol: Wizard Imposter spawns alert observers, much like any other ghost
role event should.
qol: Playing Rock-Paper-Scissors with death will now alert the observers
and invite them to watch. Better not choke!
qol: Observers now get an orbit link for BSA impact sites. Why does it
keep teleporting me to the AI upload??
qol: Spontaneous Appendicitis now alerts deadchat. 
qol: The purchasing of a badass syndie balloon now alerts deadchat. You
might not be any more powerful, but at least you have an audience.
qol: When beginning to delaminate, the Supermatter will alert observers
and invite them to watch the fireworks.
/🆑
2023-05-05 17:34:46 +01:00

205 lines
6.7 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/items/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/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=SMALL_MATERIAL_AMOUNT* 7.5)
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/warning_given = FALSE //! Stop warning spam, only warn the admins/deadchat 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/wrench_act(mob/living/user, obj/item/tool)
. = TRUE
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."))
/obj/item/powersink/screwdriver_act(mob/living/user, obj/item/tool)
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."))
return TRUE
/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)]")
user.log_message("activated a powersink", LOG_GAME)
notify_ghosts("[user] has activated a power sink!", source = src, header = "Shocking News!")
set_mode(OPERATING)
if(OPERATING)
user.visible_message( \
"[user] deactivates \the [src]!", \
span_notice("You deactivate \the [src]."),
span_hear("You hear a click."))
user.log_message("deactivated the powersink", LOG_GAME)
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(warning_given && internal_heat < max_heat * 0.75)
warning_given = 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 (!warning_given)
warning_given = 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.")
notify_ghosts("[src] is about to reach critical heat capacity!", source = src, header = "Power Sunk")
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