mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-03-28 15:04:38 +00:00
About The Pull Request Alphabetized several long lists of strings so its easier for us to look through them, just code polish, nothing the players would see. Fixed some minor spelling errors as well. Clarified door bolt state to be less ambiguous in the door wiring gui. Originally it would say the door bolts have fallen, and the door bolts "Look up". i dont know about you but that was very not clear for me to read. Like where are the bolts? In the door or the frame? Arnt there bolts on top and bottom? Just didn't make sense to me. Now it says "Have engaged!" & "Have disengaged" hopefully that makes the state clearer at a glance. I also added a small handful of funny texts to some string files. See changelog Why It's Good For The Game Well, who doesn't like a bit of polish? Just makes the game a little easier for people. Also funny text funny text. Changelog spelling: improves spelling and adds more flavortext
210 lines
8.1 KiB
Plaintext
210 lines
8.1 KiB
Plaintext
//This files deals with the generic sending and receiving of "alarms"
|
|
//This is a somewhat blanket term, it covers things like fire/power/atmos alarms, along with some oddballs
|
|
//Side effect of how the system is used, these are mostly things that are of interest to ais and borgs
|
|
//Though it could easily be expanded to cover other senders/revievers
|
|
//The system as a whole differs from reading off a global list in a few ways.
|
|
//In that A, it allows us to send cameras for ais/borgs/potentially others to jump to
|
|
//And B, it's not like we're giving you all the alarms that have been sent, because of the separate listing for each reviever
|
|
//You only receive alarms sent after you start to listen
|
|
//Also of note, due to an optimization done on areas, one alarm handler will only ever send one "on" or "off" alarm
|
|
//So the whole only receiving stuff sent post creation thing actually matters
|
|
//Honestly I'm not sure how much of this is a feature, and how much is just old code
|
|
//But I'm leaving it how I found it
|
|
|
|
///Represents a single source of alarms, one alarm handler will only ever count for one alarm per listener
|
|
/datum/alarm_handler
|
|
///A list of alarm type -> list of areas we currently have alarms in
|
|
var/list/sent_alarms = list()
|
|
///Our source atom
|
|
var/atom/source_atom
|
|
|
|
/datum/alarm_handler/New(atom/source_atom)
|
|
if(istype(source_atom))
|
|
src.source_atom = source_atom
|
|
else
|
|
var/source_type = (isdatum(source_atom)) ? source_atom.type : ""
|
|
stack_trace("a non atom was passed into alarm_handler! [source_atom] [source_type]")
|
|
return ..()
|
|
|
|
/datum/alarm_handler/Destroy()
|
|
for(var/alarm_type in sent_alarms)
|
|
for(var/area/area_to_clear as anything in sent_alarms[alarm_type])
|
|
//Yeet all connected alarms
|
|
clear_alarm_from_area(alarm_type, area_to_clear)
|
|
source_atom = null
|
|
return ..()
|
|
|
|
///Sends an alarm to any interested things, does some checks to prevent unneeded work
|
|
///Important to note is that source_atom is not held as a ref, we're used as a proxy to prevent hard deletes
|
|
///optional_camera should only be used when you have one camera you want to pass along to alarm listeners, most of the time you should have no use for it
|
|
/datum/alarm_handler/proc/send_alarm(alarm_type, atom/use_as_source_atom, optional_camera)
|
|
if(!use_as_source_atom)
|
|
use_as_source_atom = source_atom
|
|
if(!use_as_source_atom)
|
|
return
|
|
|
|
var/area/our_area = get_area(use_as_source_atom)
|
|
var/our_z_level = use_as_source_atom.z
|
|
|
|
if (our_area.area_flags & NO_ALERTS)
|
|
return FALSE
|
|
|
|
var/list/existing_alarms = sent_alarms[alarm_type]
|
|
if(existing_alarms)
|
|
if(our_area in existing_alarms)
|
|
return FALSE
|
|
else
|
|
sent_alarms[alarm_type] = list()
|
|
existing_alarms = sent_alarms[alarm_type]
|
|
|
|
existing_alarms += our_area
|
|
|
|
our_area.active_alarms[alarm_type] += 1
|
|
|
|
SEND_SIGNAL(src, COMSIG_ALARM_TRIGGERED, alarm_type, our_area)
|
|
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ALARM_FIRE(alarm_type), src, alarm_type, our_area, our_z_level, optional_camera)
|
|
|
|
return TRUE
|
|
|
|
///Clears an alarm from any interested listeners
|
|
/datum/alarm_handler/proc/clear_alarm(alarm_type, use_as_source_atom)
|
|
SIGNAL_HANDLER
|
|
if(!use_as_source_atom)
|
|
use_as_source_atom = source_atom
|
|
if(!use_as_source_atom)
|
|
return
|
|
|
|
return clear_alarm_from_area(alarm_type, get_area(use_as_source_atom))
|
|
|
|
///Exists so we can request that the alarms from an area are cleared, even if our source atom is no longer in that area
|
|
/datum/alarm_handler/proc/clear_alarm_from_area(alarm_type, area/our_area)
|
|
if (our_area.area_flags & NO_ALERTS)
|
|
return FALSE
|
|
|
|
var/list/existing_alarms = sent_alarms[alarm_type]
|
|
if(!existing_alarms)
|
|
return FALSE
|
|
|
|
if(!(our_area in existing_alarms))
|
|
return FALSE
|
|
|
|
existing_alarms -= our_area
|
|
if(!length(existing_alarms))
|
|
sent_alarms -= alarm_type
|
|
|
|
our_area.active_alarms[alarm_type] -= 1
|
|
if(!length(our_area.active_alarms))
|
|
our_area.active_alarms -= alarm_type
|
|
|
|
SEND_SIGNAL(src, COMSIG_ALARM_CLEARED, alarm_type, our_area)
|
|
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ALARM_CLEAR(alarm_type), src, alarm_type, our_area)
|
|
return TRUE
|
|
|
|
/datum/alarm_listener
|
|
///List of valid source z levels, ignored if null
|
|
var/list/allowed_z_levels
|
|
///List of allowed areas. if this is null it's ignored
|
|
var/list/allowed_areas
|
|
|
|
///List of alarm type -> list of area name -> list(area, ref to area's cameras, list(sources))
|
|
var/list/alarms = list()
|
|
///Should we allow alarm changes to go through or not
|
|
var/accepting_alarm_changes = TRUE
|
|
|
|
///Accepts a list of alarm types to pay attention to, a list of valid z levels, and a list of valid areas. areas and zlevels are ignored if null
|
|
/datum/alarm_listener/New(alarms_to_listen_for, allowed_z_levels, allowed_areas)
|
|
src.allowed_z_levels = allowed_z_levels
|
|
src.allowed_areas = allowed_areas
|
|
for(var/alarm_type in alarms_to_listen_for)
|
|
RegisterSignal(SSdcs, COMSIG_GLOB_ALARM_FIRE(alarm_type), .proc/add_alarm)
|
|
RegisterSignal(SSdcs, COMSIG_GLOB_ALARM_CLEAR(alarm_type), .proc/clear_alarm)
|
|
|
|
return ..()
|
|
|
|
///Adds an alarm to our alarms list, you shouldn't be calling this manually
|
|
///It should all be handled by the signal listening we do, unless you want to only send an alarm to one listener
|
|
/datum/alarm_listener/proc/add_alarm(datum/source, datum/alarm_handler/handler, alarm_type, area/source_area, source_z, optional_camera)
|
|
SIGNAL_HANDLER
|
|
|
|
if (!accepting_alarm_changes)
|
|
return
|
|
|
|
if(allowed_z_levels && !(source_z in allowed_z_levels))
|
|
return
|
|
|
|
if(allowed_areas && !(source_area.type in allowed_areas))
|
|
return
|
|
|
|
var/list/alarms_of_our_type = alarms[alarm_type]
|
|
if(!alarms_of_our_type)
|
|
alarms[alarm_type] = list()
|
|
alarms_of_our_type = alarms[alarm_type]
|
|
|
|
if(alarms_of_our_type[source_area.name])
|
|
var/list/alarm = alarms_of_our_type[source_area.name]
|
|
var/list/sources = alarm[3]
|
|
sources |= handler
|
|
//Return if a source already exists, we don't want to send a signal or add a new entry
|
|
return
|
|
|
|
//We normally directly pass in a ref to the area's camera's list to prevent hanging refs
|
|
var/list/cameras = source_area.cameras
|
|
if(optional_camera)
|
|
cameras = list(optional_camera) // This will cause harddels, so we need to clear manually
|
|
RegisterSignal(optional_camera, COMSIG_PARENT_QDELETING, .proc/clear_camera_ref, override = TRUE) //It's just fine to override, cause we clear all refs in the proc
|
|
|
|
//This does mean that only the first alarm of that camera type in the area will send a ping, but jesus what else can ya do
|
|
alarms_of_our_type[source_area.name] = list(source_area, cameras, list(handler))
|
|
SEND_SIGNAL(src, COMSIG_ALARM_LISTENER_TRIGGERED, alarm_type, source_area)
|
|
|
|
///Removes an alarm to our alarms list, you probably shouldn't be calling this manually
|
|
///It should all be handled by the signal listening we do, unless you want to only remove an alarm to one listener
|
|
/datum/alarm_listener/proc/clear_alarm(datum/source, datum/alarm_handler/handler, alarm_type, area/source_area)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!accepting_alarm_changes)
|
|
return
|
|
|
|
var/list/alarms_of_our_type = alarms[alarm_type]
|
|
|
|
if(!alarms_of_our_type)
|
|
return
|
|
|
|
if(!alarms_of_our_type[source_area.name])
|
|
return
|
|
|
|
var/list/alarm = alarms_of_our_type[source_area.name]
|
|
var/list/sources = alarm[3]
|
|
sources -= handler
|
|
|
|
if (length(sources))
|
|
return //Return if there's still sources left, no sense clearing the list or bothering anyone about it
|
|
|
|
alarms_of_our_type -= source_area.name
|
|
|
|
if(!length(alarms_of_our_type))
|
|
alarms -= alarm_type
|
|
|
|
SEND_SIGNAL(src, COMSIG_ALARM_LISTENER_CLEARED, alarm_type, source_area)
|
|
|
|
///Does what it says on the tin, exists for signal hooking
|
|
/datum/alarm_listener/proc/prevent_alarm_changes()
|
|
SIGNAL_HANDLER
|
|
accepting_alarm_changes = FALSE
|
|
|
|
///Does what it says on the tin, exists for signal hooking
|
|
/datum/alarm_listener/proc/allow_alarm_changes()
|
|
SIGNAL_HANDLER
|
|
accepting_alarm_changes = TRUE
|
|
|
|
///Used to manually clear camera refs if one is ref'd directly
|
|
/datum/alarm_listener/proc/clear_camera_ref(obj/machinery/camera/source)
|
|
SIGNAL_HANDLER
|
|
var/list/alarms_cache = alarms //Cache for sonic speec
|
|
for(var/alarm_type in alarms_cache)
|
|
var/list/alarms_of_type = alarms_cache[alarm_type] //Sonic cache speed forads
|
|
for(var/area_name as anything in alarms_of_type)
|
|
var/list/alarm_packet = alarms_of_type[area_name]
|
|
var/list/cameras = alarm_packet[2]
|
|
cameras -= source // REF FOUND AND CLEARED BOYSSSS
|