Files
Paradise/code/controllers/subsystem/SSsecurity_level.dm
Gaxeer eda2102bdc Refactor: refactor security levels (#21899)
* refactor: datumize security levels

* refactor: implement `SSsecurity_level` for handling security level related stuff

* feat: returns back old `delta_alarm` sound

* refactor: adjust existing code to use `SSsecurity_level`

* fix: remove redundunt new init order

* fix: fix type in var

* refactor: apply reviewer changes

* fix: replace `can_fire=FALSE` with `ss_flags = SS_NO_FIRE`, as subsystem will never fire

* fix: use `flags` instead of `ss_flags` for subsystem

Co-authored-by: SteelSlayer <42044220+SteelSlayer@users.noreply.github.com>

* fix: replace old security level interactions

* feat: implement `Recover` proc for `SSsecurity_level`

* refactor: add clearer doc for `security_level_set_timer_id`  propery of `SSsecurirt_level`

* refactor: swap `security_level` datum properties to make it clearer to read

* refactor: move initialization code from `New` to `Initialize` for `/obj/machinery/firealarm`

* fix: revert back `delta_alarm` annoing sound, use `delta_claxon` on change to delta security level

---------

Co-authored-by: SteelSlayer <42044220+SteelSlayer@users.noreply.github.com>
2023-10-14 21:46:49 +02:00

159 lines
6.1 KiB
Plaintext

#define DEFAULT_SECURITY_LEVEL_NUMBER SEC_LEVEL_GREEN
#define DEFAULT_SECURITY_LEVEL_NAME "green"
GLOBAL_DATUM_INIT(security_announcement, /datum/announcer, new(config_type = /datum/announcement_configuration/security))
SUBSYSTEM_DEF(security_level)
name = "Security Level"
flags = SS_NO_FIRE
/// Option reference of a timer id of the latest set security level. Only set when security level is changed to one with `set_delay` > 0
var/security_level_set_timer_id
/// Currently set security level
var/datum/security_level/current_security_level
/// A list of initialised security level datums
var/list/available_levels = list()
/datum/controller/subsystem/security_level/Initialize()
if (!length(available_levels))
for(var/security_level_type in subtypesof(/datum/security_level))
var/datum/security_level/new_security_level = new security_level_type
available_levels[new_security_level.name] = new_security_level
if (!current_security_level)
current_security_level = available_levels[number_level_to_text(DEFAULT_SECURITY_LEVEL_NUMBER)]
/datum/controller/subsystem/security_level/Recover()
security_level_set_timer_id = SSsecurity_level.security_level_set_timer_id
current_security_level = SSsecurity_level.current_security_level
available_levels = SSsecurity_level.available_levels
/**
* Sets a new security level as our current level
*
* This is how everything should change the security level
*
* Arguments:
* * new_level - The new security level that will become our current level, could be number or name of security level
*/
/datum/controller/subsystem/security_level/proc/set_level(new_level)
var/new_level_name = istext(new_level) ? new_level : number_level_to_text(new_level)
if(new_level_name == current_security_level.name)
return
var/datum/security_level/selected_level = available_levels[new_level_name]
if(!selected_level)
CRASH("set_level was called with an invalid security level([new_level_name])")
if(security_level_set_timer_id)
deltimer(security_level_set_timer_id)
security_level_set_timer_id = null
pre_set_level(selected_level)
if(selected_level.set_delay > 0)
SEND_SIGNAL(src, COMSIG_SECURITY_LEVEL_CHANGE_PLANNED, current_security_level.number_level, selected_level.number_level)
security_level_set_timer_id = addtimer(CALLBACK(src, PROC_REF(do_set_level), selected_level), selected_level.set_delay, TIMER_UNIQUE | TIMER_STOPPABLE)
else
do_set_level(selected_level)
/**
* Do things before the actual security level set, like executing security level specific pre change behavior
*
* Arguments:
* * selected_level - The datum of security level selected to be changed to
*/
/datum/controller/subsystem/security_level/proc/pre_set_level(datum/security_level/selected_level)
PRIVATE_PROC(TRUE)
selected_level.pre_change()
/**
* Actually sets the security level after the announcement
*
* Sends `COMSIG_SECURITY_LEVEL_CHANGED` in the end
*
* Arguments:
* * selected_level - The datum of security level selected to be changed to
*/
/datum/controller/subsystem/security_level/proc/do_set_level(datum/security_level/selected_level)
PRIVATE_PROC(TRUE)
var/datum/security_level/previous_security_level = current_security_level
if(previous_security_level.number_level < SEC_LEVEL_RED && selected_level.number_level >= SEC_LEVEL_RED)
// Mark down this time to prevent shuttle cheese
SSshuttle.emergency_sec_level_time = world.time
announce_security_level(selected_level)
current_security_level = selected_level
post_status(current_security_level.status_display_mode, current_security_level.status_display_data)
SSnightshift.check_nightshift()
SSblackbox.record_feedback("tally", "security_level_changes", 1, selected_level.name)
SEND_SIGNAL(src, COMSIG_SECURITY_LEVEL_CHANGED, previous_security_level.number_level, selected_level.number_level)
/**
* Handles announcements of the newly set security level
*
* Arguments:
* * selected_level - The new security level that has been set
*/
/datum/controller/subsystem/security_level/proc/announce_security_level(datum/security_level/selected_level)
if(selected_level.number_level > current_security_level.number_level)
GLOB.security_announcement.Announce(
selected_level.elevating_to_announcement_text,
selected_level.elevating_to_announcement_title,
new_sound = selected_level.elevating_to_sound,
new_sound2 = selected_level.ai_announcement_sound)
else
GLOB.security_announcement.Announce(
selected_level.lowering_to_announcement_text,
selected_level.lowering_to_announcement_title,
new_sound = selected_level.lowering_to_sound,
new_sound2 = selected_level.ai_announcement_sound)
/**
* Returns the current security level as a number
* In case the subsystem hasn't finished initializing yet, returns default security level
*/
/datum/controller/subsystem/security_level/proc/get_current_level_as_number()
return ((!initialized || !current_security_level) ? DEFAULT_SECURITY_LEVEL_NUMBER : current_security_level.number_level)
/**
* Returns the current security level as text
*/
/datum/controller/subsystem/security_level/proc/get_current_level_as_text()
return ((!initialized || !current_security_level) ? DEFAULT_SECURITY_LEVEL_NAME : current_security_level.name)
/**
* Converts a text security level to a number
*
* Arguments:
* * level - The text security level to convert
*/
/datum/controller/subsystem/security_level/proc/text_level_to_number(text_level)
var/datum/security_level/selected_level = available_levels[text_level]
return selected_level?.number_level
/**
* Converts a number security level to a text
*
* Arguments:
* * level - The number security level to convert
*/
/datum/controller/subsystem/security_level/proc/number_level_to_text(number_level)
for(var/level_text in available_levels)
var/datum/security_level/security_level = available_levels[level_text]
if(security_level.number_level == number_level)
return security_level.name
/**
* Returns security level name formatted with it's color
*/
/datum/controller/subsystem/security_level/proc/get_colored_current_security_level_name()
return "<font color='[current_security_level.color]'>[current_security_level.name]</font>"
#undef DEFAULT_SECURITY_LEVEL_NUMBER
#undef DEFAULT_SECURITY_LEVEL_NAME