From 110edaa153a6222de47fea37956ecee1fdb84269 Mon Sep 17 00:00:00 2001 From: Gandalf <9026500+Gandalf2k15@users.noreply.github.com> Date: Sat, 25 Jun 2022 01:01:45 +0100 Subject: [PATCH] Security Level Datums (#67949) --- code/__DEFINES/subsystems.dm | 1 + code/controllers/subsystem/nightshift.dm | 2 +- code/controllers/subsystem/security_level.dm | 104 +++++++++++++++++- code/controllers/subsystem/shuttle.dm | 6 +- code/datums/world_topic.dm | 2 +- code/game/gamemodes/dynamic/dynamic.dm | 4 +- .../game/machinery/computer/communications.dm | 8 +- code/game/machinery/defibrillator_mount.dm | 4 +- code/game/machinery/doors/door.dm | 4 +- code/game/machinery/firealarm.dm | 6 +- code/game/world.dm | 2 +- code/modules/admin/verbs/adminevents.dm | 15 ++- code/modules/antagonists/blob/overmind.dm | 2 +- code/modules/antagonists/cult/cult_items.dm | 2 +- .../equipment/nuclear_bomb/_nuclear_bomb.dm | 8 +- .../traitor/equipment/Malf_Modules.dm | 4 +- code/modules/power/singularity/narsie.dm | 4 +- .../supermatter/supermatter_delamination.dm | 2 +- .../security_levels/keycard_authentication.dm | 4 +- .../security_levels/security_level_datums.dm | 82 ++++++++++++++ .../security_levels/security_levels.dm | 82 -------------- code/modules/shuttle/emergency.dm | 6 +- code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/security_levels.dm | 16 +++ tgstation.dme | 2 +- 25 files changed, 243 insertions(+), 130 deletions(-) create mode 100644 code/modules/security_levels/security_level_datums.dm delete mode 100644 code/modules/security_levels/security_levels.dm create mode 100644 code/modules/unit_tests/security_levels.dm diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index df95c8d4eaa..453b0dc2047 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -119,6 +119,7 @@ #define INIT_ORDER_INSTRUMENTS 82 #define INIT_ORDER_GREYSCALE 81 #define INIT_ORDER_VIS 80 +#define INIT_ORDER_SECURITY_LEVEL 79 // We need to load before events so that it has a security level to choose from. #define INIT_ORDER_DISCORD 78 #define INIT_ORDER_ACHIEVEMENTS 77 #define INIT_ORDER_STATION 74 //This is high priority because it manipulates a lot of the subsystems that will initialize after it. diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm index 1e8daad6e61..f420185ec5e 100644 --- a/code/controllers/subsystem/nightshift.dm +++ b/code/controllers/subsystem/nightshift.dm @@ -27,7 +27,7 @@ SUBSYSTEM_DEF(nightshift) priority_announce(message, sound='sound/misc/notice2.ogg', sender_override="Automated Lighting System Announcement") /datum/controller/subsystem/nightshift/proc/check_nightshift() - var/emergency = SSsecurity_level.current_level >= SEC_LEVEL_RED + var/emergency = SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED var/announcing = TRUE var/time = station_time() var/night_time = (time < nightshift_end_time) || (time > nightshift_start_time) diff --git a/code/controllers/subsystem/security_level.dm b/code/controllers/subsystem/security_level.dm index e3168dee0c3..94dc351bdec 100644 --- a/code/controllers/subsystem/security_level.dm +++ b/code/controllers/subsystem/security_level.dm @@ -1,17 +1,109 @@ SUBSYSTEM_DEF(security_level) name = "Security Level" - flags = SS_NO_FIRE + can_fire = FALSE // We will control when we fire in this subsystem + init_order = INIT_ORDER_SECURITY_LEVEL /// Currently set security level - var/current_level = SEC_LEVEL_GREEN + 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(start_timeofday) + . = ..() + for(var/iterating_security_level_type in subtypesof(/datum/security_level)) + var/datum/security_level/new_security_level = new iterating_security_level_type + available_levels[new_security_level.name] = new_security_level + current_security_level = available_levels[number_level_to_text(SEC_LEVEL_GREEN)] + +/datum/controller/subsystem/security_level/fire(resumed) + if(!current_security_level.looping_sound) // No sound? No play. + can_fire = FALSE + return + sound_to_playing_players(current_security_level.looping_sound) + /** * 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 + * * new_level - The new security level that will become our current level */ /datum/controller/subsystem/security_level/proc/set_level(new_level) - SSsecurity_level.current_level = new_level - SEND_SIGNAL(src, COMSIG_SECURITY_LEVEL_CHANGED, new_level) + new_level = istext(new_level) ? new_level : number_level_to_text(new_level) + if(new_level == current_security_level.name) // If we are already at the desired level, do nothing + return + + var/datum/security_level/selected_level = available_levels[new_level] + + if(!selected_level) + CRASH("set_level was called with an invalid security level([new_level])") + + announce_security_level(selected_level) // We want to announce BEFORE updating to the new level + + var/old_shuttle_call_time_mod = current_security_level.shuttle_call_time_mod // Need this before we set the new one + + SSsecurity_level.current_security_level = selected_level + + if(selected_level.looping_sound) + wait = selected_level.looping_sound_interval + can_fire = TRUE + else + can_fire = FALSE + + if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) // By god this is absolutely shit + old_shuttle_call_time_mod = 1 / old_shuttle_call_time_mod + SSshuttle.emergency.modTimer(old_shuttle_call_time_mod) + SSshuttle.emergency.modTimer(selected_level.shuttle_call_time_mod) + + SEND_SIGNAL(src, COMSIG_SECURITY_LEVEL_CHANGED, selected_level.number_level) SSnightshift.check_nightshift() - SSblackbox.record_feedback("tally", "security_level_changes", 1, get_security_level()) + SSblackbox.record_feedback("tally", "security_level_changes", 1, selected_level.name) + +/** + * 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) // We are elevating to this level. + minor_announce(selected_level.elevating_to_announcemnt, "Attention! Security level elevated to [selected_level.name]:") + else // Going down + minor_announce(selected_level.lowering_to_announcement, "Attention! Security level lowered to [selected_level.name]:") + if(selected_level.sound) + sound_to_playing_players(selected_level.sound) + +/** + * Returns the current security level as a number + */ +/datum/controller/subsystem/security_level/proc/get_current_level_as_number() + return current_security_level.number_level + +/** + * Returns the current security level as text + */ +/datum/controller/subsystem/security_level/proc/get_current_level_as_text() + return 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/iterating_level_text in available_levels) + var/datum/security_level/iterating_security_level = available_levels[iterating_level_text] + if(iterating_security_level.number_level == number_level) + return iterating_security_level.name diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 084b0aa60ea..390de70f33c 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -307,13 +307,13 @@ SUBSYSTEM_DEF(shuttle) call_reason = trim(html_encode(call_reason)) - if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && seclevel2num(get_security_level()) > SEC_LEVEL_GREEN) + if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && SSsecurity_level.get_current_level_as_number() > SEC_LEVEL_GREEN) to_chat(user, span_alert("You must provide a reason.")) return var/area/signal_origin = get_area(user) var/emergency_reason = "\nNature of emergency:\n\n[call_reason]" - var/security_num = seclevel2num(get_security_level()) + var/security_num = SSsecurity_level.get_current_level_as_number() switch(security_num) if(SEC_LEVEL_RED,SEC_LEVEL_DELTA) emergency.request(null, signal_origin, html_decode(emergency_reason), 1) //There is a serious threat we gotta move no time to give them five minutes. @@ -376,7 +376,7 @@ SUBSYSTEM_DEF(shuttle) /datum/controller/subsystem/shuttle/proc/canRecall() if(!emergency || emergency.mode != SHUTTLE_CALL || admin_emergency_no_recall || emergency_no_recall) return - var/security_num = seclevel2num(get_security_level()) + var/security_num = SSsecurity_level.get_current_level_as_number() switch(security_num) if(SEC_LEVEL_GREEN) if(emergency.timeLeft(1) < emergency_call_time) diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index b6e96dd4b16..bb22827a8e5 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -213,7 +213,7 @@ if(key_valid) .["active_players"] = get_active_player_count() - .["security_level"] = get_security_level() + .["security_level"] = SSsecurity_level.get_current_level_as_text() .["round_duration"] = SSticker ? round((world.time-SSticker.round_start_time)/10) : 0 // Amount of world's ticks in seconds, useful for calculating round duration diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index f3f74152bd4..4e7b22e7ef5 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -340,8 +340,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", SSstation.announcer.get_rand_report_sound()) else priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", ANNOUNCER_INTERCEPT) - if(SSsecurity_level.current_level < SEC_LEVEL_BLUE) - set_security_level(SEC_LEVEL_BLUE) + if(SSsecurity_level.get_current_level_as_number() < SEC_LEVEL_BLUE) + SSsecurity_level.set_level(SEC_LEVEL_BLUE) /datum/game_mode/dynamic/proc/show_threatlog(mob/admin) if(!SSticker.HasRoundStarted()) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 9e7b15eff08..9e474cfef41 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -197,13 +197,13 @@ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return - var/new_sec_level = seclevel2num(params["newSecurityLevel"]) + var/new_sec_level = SSsecurity_level.text_level_to_number(params["newSecurityLevel"]) if (new_sec_level != SEC_LEVEL_GREEN && new_sec_level != SEC_LEVEL_BLUE) return - if (SSsecurity_level.current_level == new_sec_level) + if (SSsecurity_level.get_current_level_as_number() == new_sec_level) return - set_security_level(new_sec_level) + SSsecurity_level.set_level(new_sec_level) to_chat(usr, span_notice("Authorization confirmed. Modifying security level.")) playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) @@ -517,7 +517,7 @@ data["shuttleCalled"] = FALSE data["shuttleLastCalled"] = FALSE data["aprilFools"] = SSevents.holidays && SSevents.holidays[APRIL_FOOLS] - data["alertLevel"] = get_security_level() + data["alertLevel"] = SSsecurity_level.get_current_level_as_text() data["authorizeName"] = authorize_name data["canLogOut"] = !issilicon(user) data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac(user) diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm index 2b9851033e0..648e5ae15d8 100644 --- a/code/game/machinery/defibrillator_mount.dm +++ b/code/game/machinery/defibrillator_mount.dm @@ -41,7 +41,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/defibrillator_mount, 28) . = ..() if(defib) . += span_notice("There is a defib unit hooked up. Alt-click to remove it.") - if(SSsecurity_level.current_level >= SEC_LEVEL_RED) + if(SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED) . += span_notice("Due to a security situation, its locking clamps can be toggled by swiping any ID.") else . += span_notice("Its locking clamps can be [clamps_locked ? "dis" : ""]engaged by swiping an ID with access.") @@ -107,7 +107,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/defibrillator_mount, 28) return var/obj/item/card/id = I.GetID() if(id) - if(check_access(id) || SSsecurity_level.current_level >= SEC_LEVEL_RED) //anyone can toggle the clamps in red alert! + if(check_access(id) || SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED) //anyone can toggle the clamps in red alert! if(!defib) to_chat(user, span_warning("You can't engage the clamps on a defibrillator that isn't there.")) return diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 26015873b55..d06d431e268 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -68,7 +68,7 @@ /obj/machinery/door/examine(mob/user) . = ..() if(red_alert_access) - if(SSsecurity_level.current_level >= SEC_LEVEL_RED) + if(SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED) . += span_notice("Due to a security threat, its access requirements have been lifted!") else . += span_notice("In the event of a red alert, its access requirements will automatically lift.") @@ -88,7 +88,7 @@ return CONTEXTUAL_SCREENTIP_SET /obj/machinery/door/check_access_list(list/access_list) - if(red_alert_access && SSsecurity_level.current_level >= SEC_LEVEL_RED) + if(red_alert_access && SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED) return TRUE return ..() diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 7a5fad78b1b..31be707ea87 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -128,9 +128,9 @@ . += "fire_overlay" if(is_station_level(z)) - . += "fire_[SSsecurity_level.current_level]" - . += mutable_appearance(icon, "fire_[SSsecurity_level.current_level]") - . += emissive_appearance(icon, "fire_[SSsecurity_level.current_level]", alpha = src.alpha) + . += "fire_[SSsecurity_level.get_current_level_as_number()]" + . += mutable_appearance(icon, "fire_[SSsecurity_level.get_current_level_as_number()]") + . += emissive_appearance(icon, "fire_[SSsecurity_level.get_current_level_as_number()]", alpha = src.alpha) else . += "fire_[SEC_LEVEL_GREEN]" . += mutable_appearance(icon, "fire_[SEC_LEVEL_GREEN]") diff --git a/code/game/world.dm b/code/game/world.dm index 6c1bc850d3b..8097ca7c2a4 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -342,7 +342,7 @@ GLOBAL_VAR(restart_counter) s += ": [jointext(features, ", ")]" s += "
Round time: [gameTimestamp("hh:mm")]" - s += "
Alert level: [capitalize(get_security_level())]" + s += "
Alert level: [capitalize(SSsecurity_level.get_current_level_as_text())]" status = s diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm index af32ef6a1d7..ba07eb7858b 100644 --- a/code/modules/admin/verbs/adminevents.dm +++ b/code/modules/admin/verbs/adminevents.dm @@ -268,13 +268,16 @@ if(!check_rights(R_ADMIN)) return - var/level = input("Select security level to change to","Set Security Level") as null|anything in list("green","blue","red","delta") - if(level) - set_security_level(level) + var/level = tgui_input_list(usr, "Select Security Level:", "Set Security Level", SSsecurity_level.available_levels) - log_admin("[key_name(usr)] changed the security level to [level]") - message_admins("[key_name_admin(usr)] changed the security level to [level]") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Security Level [capitalize(level)]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + if(!level) + return + + SSsecurity_level.set_level(level) + + log_admin("[key_name(usr)] changed the security level to [level]") + message_admins("[key_name_admin(usr)] changed the security level to [level]") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Security Level [capitalize(level)]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/run_weather() set category = "Admin.Events" diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index f2d28f9c6f1..4bb83647d9d 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -139,7 +139,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) else if(!victory_in_progress && (blobs_legit.len >= blobwincount)) victory_in_progress = TRUE priority_announce("Biohazard has reached critical mass. Station loss is imminent.", "Biohazard Alert") - set_security_level("delta") + SSsecurity_level.set_level(SEC_LEVEL_DELTA) max_blob_points = INFINITY blob_points = INFINITY addtimer(CALLBACK(src, .proc/victory), 450) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index cfa9bfd9cae..e36961a93f6 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -549,7 +549,7 @@ Striking a noncultist, however, will tear their flesh."} if(SSshuttle.emergency.mode == SHUTTLE_CALL) var/cursetime = 3 MINUTES var/timer = SSshuttle.emergency.timeLeft(1) + cursetime - var/security_num = seclevel2num(get_security_level()) + var/security_num = SSsecurity_level.get_current_level_as_number() var/set_coefficient = 1 if(totalcurses == 0) diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm index e9e3a9fba2b..b90b56ec743 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm @@ -62,7 +62,7 @@ GLOBAL_VAR(station_nuke_source) STOP_PROCESSING(SSobj, core) update_appearance() SSpoints_of_interest.make_point_of_interest(src) - previous_level = get_security_level() + previous_level = SSsecurity_level.get_current_level_as_text() /obj/machinery/nuclearbomb/Destroy() safety = FALSE @@ -451,7 +451,7 @@ GLOBAL_VAR(station_nuke_source) message_admins("\The [src] was armed at [ADMIN_VERBOSEJMP(our_turf)] by [armer ? ADMIN_LOOKUPFLW(armer) : "an unknown user"].") log_game("\The [src] was armed at [loc_name(our_turf)] by [armer ? key_name(armer) : "an unknown user"].") - previous_level = get_security_level() + previous_level = SSsecurity_level.get_current_level_as_number() detonation_timer = world.time + (timer_set * 10) for(var/obj/item/pinpointer/nuke/syndicate/nuke_pointer in GLOB.pinpointer_list) nuke_pointer.switch_mode_to(TRACK_INFILTRATOR) @@ -459,7 +459,7 @@ GLOBAL_VAR(station_nuke_source) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NUKE_DEVICE_ARMED, src) countdown.start() - set_security_level("delta") + SSsecurity_level.set_level(SEC_LEVEL_DELTA) update_appearance() /// Disarms the nuke, reverting all pinpointers and the security level @@ -469,7 +469,7 @@ GLOBAL_VAR(station_nuke_source) log_game("\The [src] at [loc_name(our_turf)] was disarmed by [disarmer ? key_name(disarmer) : "an unknown user"].") detonation_timer = null - set_security_level(previous_level) + SSsecurity_level.set_level(previous_level) for(var/obj/item/pinpointer/nuke/syndicate/nuke_pointer in GLOB.pinpointer_list) nuke_pointer.switch_mode_to(initial(nuke_pointer.mode)) diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index efa3ecdf502..5b9c6f21b92 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -282,7 +282,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return if (owner_AI.stat != DEAD) priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", ANNOUNCER_AIMALF) - set_security_level("delta") + SSsecurity_level.set_level(SEC_LEVEL_DELTA) var/obj/machinery/doomsday_device/DOOM = new(owner_AI) owner_AI.nuking = TRUE owner_AI.doomsday_device = DOOM @@ -319,7 +319,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) STOP_PROCESSING(SSfastprocess, src) SSshuttle.clearHostileEnvironment(src) SSmapping.remove_nuke_threat(src) - set_security_level("red") + SSsecurity_level.set_level(SEC_LEVEL_RED) for(var/mob/living/silicon/robot/borg in owner?.connected_robots) borg.lamp_doom = FALSE borg.toggle_headlamp(FALSE, TRUE) //forces borg lamp to update diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index d8e9ae1b2ab..bcb2a8b51ff 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -235,7 +235,7 @@ ///security level and shuttle lockdowns for [/proc/begin_the_end()] /proc/narsie_start_destroy_station() - set_security_level("delta") + SSsecurity_level.set_level(SEC_LEVEL_DELTA) SSshuttle.registerHostileEnvironment(GLOB.cult_narsie) SSshuttle.lockdown = TRUE addtimer(CALLBACK(GLOBAL_PROC, .proc/narsie_apocalypse), 1 MINUTES) @@ -255,7 +255,7 @@ ///Called only if the crew managed to destroy narsie at the very last second for [/proc/begin_the_end()] /proc/narsie_last_second_win() - set_security_level("red") + SSsecurity_level.set_level(SEC_LEVEL_RED) SSshuttle.lockdown = FALSE INVOKE_ASYNC(GLOBAL_PROC, .proc/cult_ending_helper, CULT_FAILURE_NARSIE_KILLED) diff --git a/code/modules/power/supermatter/supermatter_delamination.dm b/code/modules/power/supermatter/supermatter_delamination.dm index 961d9b7defc..1fb0335e947 100644 --- a/code/modules/power/supermatter/supermatter_delamination.dm +++ b/code/modules/power/supermatter/supermatter_delamination.dm @@ -223,7 +223,7 @@ * Adds a bit of spiciness to the cascade by breaking lights and turning emergency maint access on */ /datum/supermatter_delamination/proc/create_cascade_ambience() - if(SSsecurity_level.current_level != SEC_LEVEL_DELTA) + if(SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_DELTA) SSsecurity_level.set_level(SEC_LEVEL_DELTA) // skip the announcement and shuttle timer adjustment in set_security_level() make_maint_all_access() break_lights_on_station() diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index 26f43924410..738b65ec868 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -43,7 +43,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/keycard_auth, 26) var/list/data = list() data["waiting"] = waiting data["auth_required"] = event_source ? event_source.event : 0 - data["red_alert"] = (seclevel2num(get_security_level()) >= SEC_LEVEL_RED) ? 1 : 0 + data["red_alert"] = (SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED) ? 1 : 0 data["emergency_maint"] = GLOB.emergency_access data["bsa_unlock"] = GLOB.bsa_unlock return data @@ -131,7 +131,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/keycard_auth, 26) deadchat_broadcast(" confirmed [event] at [span_name("[A2.name]")].", span_name("[confirmer]"), confirmer, message_type=DEADCHAT_ANNOUNCEMENT) switch(event) if(KEYCARD_RED_ALERT) - set_security_level(SEC_LEVEL_RED) + SSsecurity_level.set_level(SEC_LEVEL_RED) if(KEYCARD_EMERGENCY_MAINTENANCE_ACCESS) make_maint_all_access() if(KEYCARD_BSA_UNLOCK) diff --git a/code/modules/security_levels/security_level_datums.dm b/code/modules/security_levels/security_level_datums.dm new file mode 100644 index 00000000000..c6addd4d4eb --- /dev/null +++ b/code/modules/security_levels/security_level_datums.dm @@ -0,0 +1,82 @@ +/** + * Security levels + * + * These are used by the security level subsystem. Each one of these represents a security level that a player can set. + * + * Base type is abstract + */ + +/datum/security_level + /// The name of this security level. + var/name = "not set" + /// The numerical level of this security level, see defines for more information. + var/number_level = -1 + /// The sound that we will play when this security level is set + var/sound + /// The looping sound that will be played while the security level is set + var/looping_sound + /// The looping sound interval + var/looping_sound_interval + /// The shuttle call time modification of this security level + var/shuttle_call_time_mod = 0 + /// Our announcement when lowering to this level + var/lowering_to_announcement + /// Our announcement when elevating to this level + var/elevating_to_announcemnt + /// Our configuration key for lowering to text, if set, will override the default lowering to announcement. + var/lowering_to_configuration_key + /// Our configuration key for elevating to text, if set, will override the default elevating to announcement. + var/elevating_to_configuration_key + +/datum/security_level/New() + . = ..() + if(lowering_to_configuration_key) // I'm not sure about you, but isn't there an easier way to do this? + lowering_to_announcement = global.config.Get(lowering_to_configuration_key) + if(elevating_to_configuration_key) + elevating_to_announcemnt = global.config.Get(elevating_to_configuration_key) + +/** + * GREEN + * + * No threats + */ +/datum/security_level/green + name = "green" + number_level = SEC_LEVEL_GREEN + lowering_to_configuration_key = /datum/config_entry/string/alert_green + shuttle_call_time_mod = 2 + +/** + * BLUE + * + * Caution advised + */ +/datum/security_level/blue + name = "blue" + number_level = SEC_LEVEL_BLUE + lowering_to_configuration_key = /datum/config_entry/string/alert_blue_downto + elevating_to_configuration_key = /datum/config_entry/string/alert_blue_upto + shuttle_call_time_mod = 1 + +/** + * RED + * + * Hostile threats + */ +/datum/security_level/red + name = "red" + number_level = SEC_LEVEL_RED + lowering_to_configuration_key = /datum/config_entry/string/alert_red_downto + elevating_to_configuration_key = /datum/config_entry/string/alert_red_upto + shuttle_call_time_mod = 0.5 + +/** + * DELTA + * + * Station destruction is imminent + */ +/datum/security_level/delta + name = "delta" + number_level = SEC_LEVEL_DELTA + elevating_to_configuration_key = /datum/config_entry/string/alert_delta + shuttle_call_time_mod = 0.25 diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm deleted file mode 100644 index c289f90b607..00000000000 --- a/code/modules/security_levels/security_levels.dm +++ /dev/null @@ -1,82 +0,0 @@ -/proc/set_security_level(level) - switch(level) - if("green") - level = SEC_LEVEL_GREEN - if("blue") - level = SEC_LEVEL_BLUE - if("red") - level = SEC_LEVEL_RED - if("delta") - level = SEC_LEVEL_DELTA - - //Will not be announced if you try to set to the same level as it already is - if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != SSsecurity_level.current_level) - switch(level) - if(SEC_LEVEL_GREEN) - minor_announce(CONFIG_GET(string/alert_green), "Attention! Security level lowered to green:") - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - if(SSsecurity_level.current_level >= SEC_LEVEL_RED) - SSshuttle.emergency.modTimer(4) - else - SSshuttle.emergency.modTimer(2) - if(SEC_LEVEL_BLUE) - if(SSsecurity_level.current_level < SEC_LEVEL_BLUE) - minor_announce(CONFIG_GET(string/alert_blue_upto), "Attention! Security level elevated to blue:",1) - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - SSshuttle.emergency.modTimer(0.5) - else - minor_announce(CONFIG_GET(string/alert_blue_downto), "Attention! Security level lowered to blue:") - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - SSshuttle.emergency.modTimer(2) - if(SEC_LEVEL_RED) - if(SSsecurity_level.current_level < SEC_LEVEL_RED) - minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!",1) - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - if(SSsecurity_level.current_level == SEC_LEVEL_GREEN) - SSshuttle.emergency.modTimer(0.25) - else - SSshuttle.emergency.modTimer(0.5) - else - minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!") - if(SEC_LEVEL_DELTA) - minor_announce(CONFIG_GET(string/alert_delta), "Attention! Delta security level reached!",1) - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - if(SSsecurity_level.current_level == SEC_LEVEL_GREEN) - SSshuttle.emergency.modTimer(0.25) - else if(SSsecurity_level.current_level == SEC_LEVEL_BLUE) - SSshuttle.emergency.modTimer(0.5) - - SSsecurity_level.set_level(level) - -/proc/get_security_level() - switch(SSsecurity_level.current_level) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/num2seclevel(num) - switch(num) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/seclevel2num(seclevel) - switch( lowertext(seclevel) ) - if("green") - return SEC_LEVEL_GREEN - if("blue") - return SEC_LEVEL_BLUE - if("red") - return SEC_LEVEL_RED - if("delta") - return SEC_LEVEL_DELTA diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 06babb9198f..73b613d2970 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -321,7 +321,7 @@ /obj/docking_port/mobile/emergency/request(obj/docking_port/stationary/S, area/signalOrigin, reason, redAlert, set_coefficient=null) if(!isnum(set_coefficient)) - var/security_num = seclevel2num(get_security_level()) + var/security_num = SSsecurity_level.get_current_level_as_number() switch(security_num) if(SEC_LEVEL_GREEN) set_coefficient = 2 @@ -571,7 +571,7 @@ var/obj/machinery/computer/shuttle/C = getControlConsole() if(!istype(C, /obj/machinery/computer/shuttle/pod)) return ..() - if(SSsecurity_level.current_level >= SEC_LEVEL_RED || (C && (C.obj_flags & EMAGGED))) + if(SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED || (C && (C.obj_flags & EMAGGED))) if(launch_status == UNLAUNCHED) launch_status = EARLY_LAUNCHED return ..() @@ -732,7 +732,7 @@ /obj/item/storage/pod/can_interact(mob/user) if(!..()) return FALSE - if(SSsecurity_level.current_level >= SEC_LEVEL_RED || unlocked) + if(SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED || unlocked) return TRUE to_chat(user, "The storage unit will only unlock during a Red or Delta security alert.") return FALSE diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 6bbbe23804d..17027ecfc13 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -137,6 +137,7 @@ #include "screenshot_basic.dm" #include "screenshot_humanoids.dm" #include "security_officer_distribution.dm" +#include "security_levels.dm" #include "serving_tray.dm" #include "siunit.dm" #include "slips.dm" diff --git a/code/modules/unit_tests/security_levels.dm b/code/modules/unit_tests/security_levels.dm new file mode 100644 index 00000000000..eecef51ff99 --- /dev/null +++ b/code/modules/unit_tests/security_levels.dm @@ -0,0 +1,16 @@ +/** + * Security Level Unit Test + * + * This test is here to ensure there are no security levels with the same name or number level. Having the same name or number level will cause problems. + */ +/datum/unit_test/security_levels + +/datum/unit_test/security_levels/Run() + var/list/comparison = subtypesof(/datum/security_level) + + for(var/datum/security_level/iterating_level in comparison) + for(var/datum/security_level/iterating_level_check in comparison) + if(iterating_level == iterating_level_check) // If they are the same type, don't check + continue + TEST_ASSERT_NOTEQUAL(iterating_level.name, iterating_level_check.name, "Security level [iterating_level] has the same name as [iterating_level_check]!") + TEST_ASSERT_NOTEQUAL(iterating_level.number_level, iterating_level_check.number_level, "Security level [iterating_level] has the same level number as [iterating_level_check]!") diff --git a/tgstation.dme b/tgstation.dme index 5baa62cd39c..d918df94b7c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4133,7 +4133,7 @@ #include "code\modules\research\xenobiology\vatgrowing\samples\cell_lines\common.dm" #include "code\modules\research\xenobiology\vatgrowing\samples\viruses\_virus.dm" #include "code\modules\security_levels\keycard_authentication.dm" -#include "code\modules\security_levels\security_levels.dm" +#include "code\modules\security_levels\security_level_datums.dm" #include "code\modules\shuttle\arrivals.dm" #include "code\modules\shuttle\assault_pod.dm" #include "code\modules\shuttle\battlecruiser_starfury.dm"