#define COMM_SCREEN_MAIN 1 #define COMM_SCREEN_STAT 2 #define COMM_SCREEN_MESSAGES 3 #define COMM_SCREEN_ANNOUNCER 4 #define COMM_AUTHENTICATION_NONE 0 #define COMM_AUTHENTICATION_HEAD 1 #define COMM_AUTHENTICATION_CAPT 2 #define COMM_AUTHENTICATION_CENTCOM 3 // Admin-only access #define COMM_AUTHENTICATION_AGHOST 4 #define COMM_MSGLEN_MINIMUM 6 #define COMM_CCMSGLEN_MINIMUM 20 #define ADMIN_CHECK(user) (check_rights_all(R_ADMIN|R_EVENT, FALSE, user) && (authenticated >= COMM_AUTHENTICATION_CENTCOM || user.can_admin_interact())) // The communications computer /obj/machinery/computer/communications name = "communications console" desc = "This allows the Captain to contact Central Command, or change the alert level. It also allows the command staff to call the Escape Shuttle." icon_keyboard = "tech_key" icon_screen = "comm" req_access = list(ACCESS_HEADS) circuit = /obj/item/circuitboard/communications var/list/messagetitle = list() var/list/messagetext = list() var/currmsg var/authenticated = COMM_AUTHENTICATION_NONE var/menu_state = COMM_SCREEN_MAIN var/ai_menu_state = COMM_SCREEN_MAIN var/aicurrmsg var/message_cooldown var/centcomm_message_cooldown var/alert_level_cooldown = 0 var/stat_msg1 var/stat_msg2 var/display_type = STATUS_DISPLAY_TIME var/display_icon var/datum/announcer/announcer = new(config_type = /datum/announcement_configuration/comms_console) light_color = LIGHT_COLOR_LIGHTBLUE var/list/cc_announcement_sounds = list("Beep" = 'sound/misc/notice2.ogg', "Enemy Communications Intercepted" = 'sound/AI/intercept.ogg', "New Command Report Created" = 'sound/AI/commandreport.ogg') /obj/machinery/computer/communications/New() GLOB.shuttle_caller_list += src ..() /obj/machinery/computer/communications/Initialize(mapload) . = ..() /obj/machinery/computer/communications/proc/is_authenticated(mob/user, message = 1) if(check_rights_all(R_ADMIN|R_EVENT, FALSE, user)) if(user.can_admin_interact()) return COMM_AUTHENTICATION_AGHOST if(authenticated == COMM_AUTHENTICATION_CENTCOM) return COMM_AUTHENTICATION_CENTCOM if(authenticated == COMM_AUTHENTICATION_CAPT) return COMM_AUTHENTICATION_CAPT if(authenticated) return COMM_AUTHENTICATION_HEAD if(message) to_chat(user, "Access denied.") return COMM_AUTHENTICATION_NONE /obj/machinery/computer/communications/proc/change_security_level(new_level, force) var/old_level = SSsecurity_level.get_current_level_as_number() if(!force) new_level = clamp(new_level, SEC_LEVEL_GREEN, SEC_LEVEL_BLUE) SSsecurity_level.set_level(new_level) if(SSsecurity_level.get_current_level_as_number() != old_level) //Only notify the admins if an actual change happened log_game("[key_name(usr)] has changed the security level to [SSsecurity_level.get_current_level_as_text()].") message_admins("[key_name_admin(usr)] has changed the security level to [SSsecurity_level.get_current_level_as_text()].") if(new_level == SEC_LEVEL_EPSILON) // episilon is delayed... but we still want to log it log_game("[key_name(usr)] has changed the security level to epsilon.") message_admins("[key_name_admin(usr)] has changed the security level to epsilon.") /obj/machinery/computer/communications/ui_act(action, params, datum/tgui/ui) if(..()) return if(!is_secure_level(z)) to_chat(ui.user, "Unable to establish a connection: You're too far away from the station!") return . = TRUE if(action == "auth") if(!ishuman(ui.user)) to_chat(ui.user, "Access denied, no humanoid lifesign detected.") return FALSE // Logout function. if(authenticated != COMM_AUTHENTICATION_NONE) authenticated = COMM_AUTHENTICATION_NONE announcer.author = null setMenuState(ui.user, COMM_SCREEN_MAIN) return // Login function. var/list/access = ui.user.get_access() if(allowed(ui.user)) authenticated = COMM_AUTHENTICATION_HEAD if(ACCESS_CAPTAIN in access) authenticated = COMM_AUTHENTICATION_CAPT if(ACCESS_CENT_COMMANDER in access) if(!check_rights_all(R_ADMIN|R_EVENT, FALSE, ui.user)) to_chat(ui.user, "[src] buzzes, invalid central command clearance.") return authenticated = COMM_AUTHENTICATION_CENTCOM if(authenticated >= COMM_AUTHENTICATION_CAPT) var/mob/living/carbon/human/H = ui.user if(!istype(H)) return var/obj/item/card/id = H.get_idcard(TRUE) if(istype(id)) announcer.author = GetNameAndAssignmentFromId(id) if(authenticated == COMM_AUTHENTICATION_NONE) to_chat(ui.user, "You need to wear a command or Captain-level ID.") return // All functions below this point require authentication. if(!is_authenticated(ui.user)) return FALSE switch(action) if("main") setMenuState(ui.user, COMM_SCREEN_MAIN) if("newalertlevel") if(isAI(ui.user) || isrobot(ui.user)) to_chat(ui.user, "Firewalls prevent you from changing the alert level.") return else if(ADMIN_CHECK(ui.user)) change_security_level(text2num(params["level"]), force = TRUE) return else if(!ishuman(ui.user)) to_chat(ui.user, "Security measures prevent you from changing the alert level.") return else if(alert_level_cooldown > world.time) to_chat(ui.user, "Please allow at least one minute between manual changes to the alert level.") return alert_level_cooldown = world.time + 60 SECONDS var/mob/living/carbon/human/H = ui.user var/obj/item/card/id/I = H.get_idcard(TRUE) if(istype(I)) // You must have captain access and it must be red alert or lower (no getting off delta/epsilon) if((ACCESS_CAPTAIN in I.access) && SSsecurity_level.get_current_level_as_number() <= SEC_LEVEL_RED) change_security_level(text2num(params["level"])) else to_chat(ui.user, "You are not authorized to do this.") setMenuState(ui.user, COMM_SCREEN_MAIN) else to_chat(ui.user, "You need to wear your ID.") if("announce") if(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT) if(message_cooldown > world.time) to_chat(ui.user, "Please allow at least one minute to pass between announcements.") return var/input = input(ui.user, "Please write a message to announce to the station crew.", "Priority Announcement") as null|message if(!input || message_cooldown > world.time || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)) return if(length(input) < COMM_MSGLEN_MINIMUM) to_chat(ui.user, "Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.") return announcer.Announce(input) message_cooldown = world.time + 600 //One minute if("callshuttle") var/input = input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.") as null|message if(!input || ..() || !is_authenticated(ui.user)) return call_shuttle_proc(ui.user, input) if(SSshuttle.emergency.timer) post_status(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) setMenuState(ui.user, COMM_SCREEN_MAIN) if("cancelshuttle") if(isAI(ui.user) || isrobot(ui.user)) to_chat(ui.user, "Firewalls prevent you from recalling the shuttle.") return var/response = tgui_alert(usr, "Are you sure you wish to recall the shuttle?", "Confirm", list("Yes", "No")) if(response == "Yes") cancel_call_proc(ui.user) if(SSshuttle.emergency.timer) post_status(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) setMenuState(ui.user, COMM_SCREEN_MAIN) if("messagelist") currmsg = null aicurrmsg = null if(params["msgid"]) setCurrentMessage(ui.user, text2num(params["msgid"])) setMenuState(ui.user, COMM_SCREEN_MESSAGES) if("delmessage") if(params["msgid"]) currmsg = text2num(params["msgid"]) if(currmsg) var/id = getCurrentMessage() var/title = messagetitle[id] var/text = messagetext[id] messagetitle.Remove(title) messagetext.Remove(text) if(currmsg == id) currmsg = null if(aicurrmsg == id) aicurrmsg = null setMenuState(ui.user, COMM_SCREEN_MESSAGES) if("status") setMenuState(ui.user, COMM_SCREEN_STAT) // Status display stuff if("setstat") display_type = text2num(params["statdisp"]) switch(display_type) if(STATUS_DISPLAY_MESSAGE) display_icon = null post_status(STATUS_DISPLAY_MESSAGE, stat_msg1, stat_msg2) if(STATUS_DISPLAY_ALERT) display_icon = params["alert"] post_status(STATUS_DISPLAY_ALERT, params["alert"]) else display_icon = null post_status(display_type) setMenuState(ui.user, COMM_SCREEN_STAT) if("setmsg1") stat_msg1 = tgui_input_text(ui.user, "Line 1", stat_msg1, "Enter Message Text", encode = FALSE) setMenuState(ui.user, COMM_SCREEN_STAT) if("setmsg2") stat_msg2 = tgui_input_text(ui.user, "Line 2", stat_msg2, "Enter Message Text", encode = FALSE) setMenuState(ui.user, COMM_SCREEN_STAT) if("nukerequest") if(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT) if(centcomm_message_cooldown > world.time) to_chat(ui.user, "Arrays recycling. Please stand by.") return var/input = tgui_input_text(ui.user, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.", encode = FALSE) if(isnull(input) || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)) return if(length(input) < COMM_CCMSGLEN_MINIMUM) to_chat(ui.user, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.") return Nuke_request(input, ui.user) to_chat(ui.user, "Request sent.") log_game("[key_name(ui.user)] has requested the nuclear codes from Centcomm") GLOB.major_announcement.Announce("The codes for the on-station nuclear self-destruction device have been requested by [ui.user]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested", 'sound/AI/nuke_codes.ogg') centcomm_message_cooldown = world.time + 6000 // 10 minutes setMenuState(ui.user, COMM_SCREEN_MAIN) if("MessageCentcomm") if(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT) if(centcomm_message_cooldown > world.time) to_chat(ui.user, "Arrays recycling. Please stand by.") return var/input = tgui_input_text(ui.user, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "CentComm Message", encode = FALSE) if(!input || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)) return if(length(input) < COMM_CCMSGLEN_MINIMUM) to_chat(ui.user, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.") return Centcomm_announce(input, ui.user) print_centcom_report(input, station_time_timestamp() + " Captain's Message") to_chat(ui.user, "Message transmitted.") log_game("[key_name(ui.user)] has made a Centcomm announcement: [input]") centcomm_message_cooldown = world.time + 6000 // 10 minutes setMenuState(ui.user, COMM_SCREEN_MAIN) // OMG SYNDICATE ...LETTERHEAD if("MessageSyndicate") if((is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT) && (src.emagged)) if(centcomm_message_cooldown > world.time) to_chat(ui.user, "Arrays recycling. Please stand by.") return var/input = tgui_input_text(ui.user, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send Message", encode = FALSE) if(!input || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)) return if(length(input) < COMM_CCMSGLEN_MINIMUM) to_chat(ui.user, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.") return Syndicate_announce(input, ui.user) to_chat(ui.user, "Message transmitted.") log_game("[key_name(ui.user)] has made a Syndicate announcement: [input]") centcomm_message_cooldown = world.time + 6000 // 10 minutes setMenuState(ui.user, COMM_SCREEN_MAIN) if("RestoreBackup") to_chat(ui.user, "Backup routing data restored!") emagged = FALSE setMenuState(ui.user, COMM_SCREEN_MAIN) // ADMIN CENTCOMM ONLY STUFF if("send_to_cc_announcement_page") if(!ADMIN_CHECK(ui.user)) return setMenuState(ui.user, COMM_SCREEN_ANNOUNCER) if("make_other_announcement") if(!ADMIN_CHECK(ui.user)) return ui.user.client.cmd_admin_create_centcom_report() if("dispatch_ert") if(!ADMIN_CHECK(ui.user)) return ui.user.client.response_team() // check_rights is handled on the other side, if someone does get ahold of this if("send_nuke_codes") if(!ADMIN_CHECK(ui.user)) return print_nuke_codes() if("move_gamma_armory") if(!ADMIN_CHECK(ui.user)) return SSblackbox.record_feedback("tally", "admin_comms_console", 1, "Send Gamma Armory") log_and_message_admins("moved the gamma armory") move_gamma_ship() if("test_sound") if(!ADMIN_CHECK(ui.user)) return SEND_SOUND(ui.user, sound(cc_announcement_sounds[params["sound"]])) if("toggle_ert_allowed") if(!ADMIN_CHECK(ui.user)) return ui.user.client.toggle_ert_calling() if("view_econ") if(!ADMIN_CHECK(ui.user)) return ui.user.client.economy_manager() if("view_fax") if(!ADMIN_CHECK(ui.user)) return ui.user.client.fax_panel() if("make_cc_announcement") if(!ADMIN_CHECK(ui.user)) return if(!text2bool(params["classified"])) GLOB.major_announcement.Announce( params["text"], new_title = "Central Command Report", new_subtitle = params["subtitle"], new_sound = cc_announcement_sounds[params["beepsound"]] ) print_command_report(params["text"], params["subtitle"]) else GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.") print_command_report(params["text"], "Classified: [params["subtitle"]]") log_and_message_admins("has created a communications report: [params["text"]]") // Okay but this is just an IC way of accessing the same verb SSblackbox.record_feedback("tally", "admin_comms_console", 1, "Create CC Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /obj/machinery/computer/communications/proc/print_nuke_codes() playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE) var/obj/item/paper/P = new /obj/item/paper(get_turf(src)) P.name = "'CONFIDENTIAL' - [station_name()] Nuclear Codes" P.info = "
