#define STATE_DEFAULT 1 #define STATE_MESSAGELIST 2 #define STATE_VIEWMESSAGE 3 #define STATE_STATUSDISPLAY 4 #define STATE_ALERT_LEVEL 5 /datum/computer_file/program/comm filename = "comm" filedesc = "Command and communications program." program_icon_state = "comm" nanomodule_path = /datum/nano_module/program/comm extended_desc = "Used to command and control the station. Can relay long-range communications. This program can not be run on tablet computers." required_access = access_heads requires_ntnet = 1 size = 12 usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP network_destination = "station long-range communication array" var/datum/comm_message_listener/message_core = new /datum/computer_file/program/comm/clone() var/datum/computer_file/program/comm/temp = ..() temp.message_core.messages = null temp.message_core.messages = message_core.messages.Copy() return temp /datum/nano_module/program/comm name = "Command and communications program" available_to_ai = TRUE var/current_status = STATE_DEFAULT var/msg_line1 = "" var/msg_line2 = "" var/centcomm_message_cooldown = 0 var/announcment_cooldown = 0 var/datum/announcement/priority/crew_announcement = new var/current_viewing_message_id = 0 var/current_viewing_message = null /datum/nano_module/program/comm/New() ..() crew_announcement.newscast = 1 /datum/nano_module/program/comm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) var/list/data = host.initial_data() if(program) data["emagged"] = program.computer_emagged data["net_comms"] = !!program.get_signal(NTNET_COMMUNICATION) //Double !! is needed to get 1 or 0 answer data["net_syscont"] = !!program.get_signal(NTNET_SYSTEMCONTROL) if(program.computer) data["have_printer"] = !!program.computer.nano_printer else data["have_printer"] = 0 else data["emagged"] = 0 data["net_comms"] = 1 data["net_syscont"] = 1 data["have_printer"] = 0 data["message_line1"] = msg_line1 data["message_line2"] = msg_line2 data["state"] = current_status data["isAI"] = issilicon(usr) data["authenticated"] = is_autenthicated(user) data["boss_short"] = boss_short data["current_security_level"] = security_level data["current_security_level_title"] = num2seclevel(security_level) data["def_SEC_LEVEL_DELTA"] = SEC_LEVEL_DELTA data["def_SEC_LEVEL_BLUE"] = SEC_LEVEL_BLUE data["def_SEC_LEVEL_GREEN"] = SEC_LEVEL_GREEN var/datum/comm_message_listener/l = obtain_message_listener() data["messages"] = l.messages data["message_deletion_allowed"] = l != global_message_listener data["message_current_id"] = current_viewing_message_id if(current_viewing_message) data["message_current"] = current_viewing_message if(emergency_shuttle.location()) data["have_shuttle"] = 1 if(emergency_shuttle.online()) data["have_shuttle_called"] = 1 else data["have_shuttle_called"] = 0 else data["have_shuttle"] = 0 ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if(!ui) ui = new(user, src, ui_key, "communication.tmpl", name, 550, 420, state = state) ui.auto_update_layout = 1 ui.set_initial_data(data) ui.open() /datum/nano_module/program/comm/proc/is_autenthicated(var/mob/user) if(program) return program.can_run(user) return 1 /datum/nano_module/program/comm/proc/obtain_message_listener() if(program) var/datum/computer_file/program/comm/P = program return P.message_core return global_message_listener /datum/nano_module/program/comm/Topic(href, href_list) if(..()) return 1 var/mob/user = usr var/ntn_comm = program ? !!program.get_signal(NTNET_COMMUNICATION) : 1 var/ntn_cont = program ? !!program.get_signal(NTNET_SYSTEMCONTROL) : 1 var/datum/comm_message_listener/l = obtain_message_listener() switch(href_list["action"]) if("sw_menu") . = 1 current_status = text2num(href_list["target"]) if("announce") . = 1 if(is_autenthicated(user) && !issilicon(usr) && ntn_comm) if(user) var/obj/item/weapon/card/id/id_card = user.GetIdCard() crew_announcement.announcer = GetNameAndAssignmentFromId(id_card) else crew_announcement.announcer = "Unknown" if(announcment_cooldown) usr << "Please allow at least one minute to pass between announcements" return TRUE var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|text if(!input || !can_still_topic()) return 1 crew_announcement.Announce(input) announcment_cooldown = 1 spawn(600)//One minute cooldown announcment_cooldown = 0 if("message") . = 1 if(href_list["target"] == "emagged") if(program) if(is_autenthicated(user) && program.computer_emagged && !issilicon(usr) && ntn_comm) if(centcomm_message_cooldown) usr << "Arrays recycling. Please stand by." nanomanager.update_uis(src) return var/input = sanitize(input(usr, "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. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") as null|text) if(!input || !can_still_topic()) return 1 Syndicate_announce(input, usr) usr << "Message transmitted." log_say("[key_name(usr)] has made an illegal announcement: [input]") centcomm_message_cooldown = 1 spawn(300)//30 second cooldown centcomm_message_cooldown = 0 else if(href_list["target"] == "regular") if(is_autenthicated(user) && !issilicon(usr) && ntn_comm) if(centcomm_message_cooldown) usr << "Arrays recycling. Please stand by." nanomanager.update_uis(src) return if(!is_relay_online())//Contact Centcom has a check, Syndie doesn't to allow for Traitor funs. usr <<"No Emergency Bluespace Relay detected. Unable to transmit message." return 1 var/input = sanitize(input("Please choose a message to transmit to [boss_short] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") as null|text) if(!input || !can_still_topic()) return 1 Centcomm_announce(input, usr) usr << "Message transmitted." log_say("[key_name(usr)] has made an IA [boss_short] announcement: [input]") centcomm_message_cooldown = 1 spawn(300) //30 second cooldown centcomm_message_cooldown = 0 if("shuttle") . = 1 if(is_autenthicated(user) && ntn_cont) if(href_list["target"] == "call") var/confirm = alert("Are you sure you want to call the shuttle?", name, "No", "Yes") if(confirm == "Yes" && can_still_topic()) call_shuttle_proc(usr) if(href_list["target"] == "cancel" && !issilicon(usr)) var/confirm = alert("Are you sure you want to cancel the shuttle?", name, "No", "Yes") if(confirm == "Yes" && can_still_topic()) cancel_call_proc(usr) if("setstatus") . = 1 if(is_autenthicated(user) && ntn_cont) switch(href_list["target"]) if("line1") var/linput = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", msg_line1) as text|null, 40), 40) if(can_still_topic()) msg_line1 = linput if("line2") var/linput = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", msg_line2) as text|null, 40), 40) if(can_still_topic()) msg_line2 = linput if("message") post_status("message", msg_line1, msg_line2) if("alert") post_status("alert", href_list["alert"]) else post_status(href_list["target"]) if("setalert") . = 1 if(is_autenthicated(user) && !issilicon(usr) && ntn_cont && ntn_comm) var/current_level = text2num(href_list["target"]) var/confirm = alert("Are you sure you want to change alert level to [num2seclevel(current_level)]?", name, "No", "Yes") if(confirm == "Yes" && can_still_topic()) var/old_level = security_level if(!current_level) current_level = SEC_LEVEL_GREEN if(current_level < SEC_LEVEL_GREEN) current_level = SEC_LEVEL_GREEN if(current_level > SEC_LEVEL_BLUE) current_level = SEC_LEVEL_BLUE //Cannot engage delta with this set_security_level(current_level) if(security_level != old_level) log_game("[key_name(usr)] has changed the security level to [get_security_level()].") message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].") switch(security_level) if(SEC_LEVEL_GREEN) feedback_inc("alert_comms_green",1) if(SEC_LEVEL_BLUE) feedback_inc("alert_comms_blue",1) else usr << "You press button, but red light flashes and nothing happens." //This should never happen current_status = STATE_DEFAULT if("viewmessage") . = 1 if(is_autenthicated(user) && ntn_comm) current_viewing_message_id = text2num(href_list["target"]) for(var/list/m in l.messages) if(m["id"] == current_viewing_message_id) current_viewing_message = m current_status = STATE_VIEWMESSAGE if("delmessage") . = 1 if(is_autenthicated(user) && ntn_comm && l != global_message_listener) l.Remove(current_viewing_message) current_status = STATE_MESSAGELIST if("printmessage") . = 1 if(is_autenthicated(user) && ntn_comm) if(program && program.computer && program.computer.nano_printer) if(!program.computer.nano_printer.print_text(current_viewing_message["contents"],current_viewing_message["title"])) usr << "Hardware error: Printer was unable to print the file. It may be out of paper." else program.computer.visible_message("\The [program.computer] prints out paper.") #undef STATE_DEFAULT #undef STATE_MESSAGELIST #undef STATE_VIEWMESSAGE #undef STATE_STATUSDISPLAY #undef STATE_ALERT_LEVEL /* General message handling stuff */ var/list/comm_message_listeners = list() //We first have to initialize list then we can use it. var/datum/comm_message_listener/global_message_listener = new //May be used by admins var/last_message_id = 0 /proc/get_comm_message_id() last_message_id = last_message_id + 1 return last_message_id /proc/post_comm_message(var/message_title, var/message_text) var/list/message = list() message["id"] = get_comm_message_id() message["title"] = message_title message["contents"] = message_text for (var/datum/comm_message_listener/l in comm_message_listeners) l.Add(message) for (var/obj/machinery/modular_computer/console/preset/command/main/computer in global_modular_computers) if(!(computer.stat & (BROKEN | NOPOWER)) && computer.cpu) if(computer.cpu.hard_drive) var/datum/computer_file/program/comm/C = locate(/datum/computer_file/program/comm) in computer.cpu.hard_drive.stored_files if(C) var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper(computer.loc) intercept.name = message_title intercept.info = message_text /datum/comm_message_listener var/list/messages /datum/comm_message_listener/New() ..() messages = list() comm_message_listeners.Add(src) /datum/comm_message_listener/proc/Add(var/list/message) messages[++messages.len] = message /datum/comm_message_listener/proc/Remove(var/list/message) messages -= list(message) /proc/post_status(var/command, var/data1, var/data2) var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) if(!frequency) return var/datum/signal/status_signal = new status_signal.source = src status_signal.transmission_method = 1 status_signal.data["command"] = command switch(command) if("message") status_signal.data["msg1"] = data1 status_signal.data["msg2"] = data2 log_admin("STATUS: [key_name(usr)] set status screen message with [src]: [data1] [data2]") if("alert") status_signal.data["picture_state"] = data1 frequency.post_signal(src, status_signal) /proc/cancel_call_proc(var/mob/user) if (!( ticker ) || !emergency_shuttle.can_recall()) return if((ticker.mode.name == "blob")||(ticker.mode.name == "Meteor")) return if(!emergency_shuttle.going_to_centcom()) //check that shuttle isn't already heading to centcomm emergency_shuttle.recall() log_game("[key_name(user)] has recalled the shuttle.") message_admins("[key_name_admin(user)] has recalled the shuttle.", 1) return /proc/is_relay_online() for(var/obj/machinery/bluespacerelay/M in machines) if(M.stat == 0) return 1 return 0 /proc/enable_prison_shuttle(var/mob/user) for(var/obj/machinery/computer/prison_shuttle/PS in machines) PS.allowedtocall = !(PS.allowedtocall) /proc/call_shuttle_proc(var/mob/user) if ((!( ticker ) || !emergency_shuttle.location())) return if(!universe.OnShuttleCall(usr)) user << "Cannot establish a bluespace connection." return if(deathsquad.deployed) user << "[boss_short] will not allow the shuttle to be called. Consider all contracts terminated." return if(emergency_shuttle.deny_shuttle) user << "The emergency shuttle may not be sent at this time. Please try again later." return if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE user << "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minute\s before trying again." return if(emergency_shuttle.going_to_centcom()) user << "The emergency shuttle may not be called while returning to [boss_short]." return if(emergency_shuttle.online()) user << "The emergency shuttle is already on its way." return if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic") user << "Under directive 7-10, [station_name()] is quarantined until further notice." return if(!emergency_shuttle.call_evac(user)) return log_and_message_admins("has called the shuttle.") /proc/init_shift_change(var/mob/user, var/force = 0) if ((!( ticker ) || !emergency_shuttle.location())) return if(emergency_shuttle.going_to_centcom()) user << "The shuttle may not be called while returning to [boss_short]." return if(emergency_shuttle.online()) user << "The shuttle is already on its way." return // if force is 0, some things may stop the shuttle call if(!force) if(emergency_shuttle.deny_shuttle) user << "[boss_short] does not currently have a shuttle available in your sector. Please try again later." return if(deathsquad.deployed == 1) user << "[boss_short] will not allow the shuttle to be called. Consider all contracts terminated." return if(world.time < 54000) // 30 minute grace period to let the game get going user << "The shuttle is refueling. Please wait another [round((54000-world.time)/60)] minutes before trying again." return if(ticker.mode.auto_recall_shuttle) //New version pretends to call the shuttle but cause the shuttle to return after a random duration. emergency_shuttle.auto_recall = 1 if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic") user << "Under directive 7-10, [station_name()] is quarantined until further notice." return emergency_shuttle.call_transfer() //delay events in case of an autotransfer if (isnull(user)) event_manager.delay_events(EVENT_LEVEL_MODERATE, 10200) //17 minutes event_manager.delay_events(EVENT_LEVEL_MAJOR, 10200) log_game("[user? key_name(user) : "Autotransfer"] has called the shuttle.") message_admins("[user? key_name_admin(user) : "Autotransfer"] has called the shuttle.", 1) return