diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm index 3d8d22218f6..671822abfeb 100644 --- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm +++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm @@ -167,7 +167,7 @@ /turf/simulated/floor/wood, /area/ruin/powered/snow_cabin) "aL" = ( -/obj/structure/displaycase/captain, +/obj/mecha/working/ripley/mining, /turf/simulated/floor/wood, /area/ruin/powered/snow_cabin) "aM" = ( @@ -392,12 +392,6 @@ /obj/structure/filingcabinet, /turf/simulated/floor/pod/dark, /area/ruin/powered/snow_biodome) -"UM" = ( -/obj/machinery/computer/monitor/secret{ - dir = 1 - }, -/turf/simulated/floor/pod/dark, -/area/ruin/powered/snow_biodome) "Wg" = ( /turf/simulated/wall/r_wall, /area/ruin/powered/snow_biodome) @@ -484,7 +478,7 @@ HP tl PK gz -UM +HP Wg ak ak diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm index 1dc60364d99..ceb8067f7ac 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm @@ -68,7 +68,6 @@ "an" = ( /obj/machinery/navbeacon/invisible{ codes_txt = "patrol;next_patrol=SDNW"; - invisibility = 100; location = "SDNE" }, /turf/simulated/floor/plating/asteroid/airless, @@ -292,15 +291,13 @@ "aU" = ( /obj/machinery/navbeacon/invisible{ codes_txt = "patrol;next_patrol=SDSW"; - invisibility = 100; location = "SDNW" }, /turf/simulated/floor/plating/asteroid/airless, /area/syndicate_depot/outer) "aV" = ( /obj/machinery/light{ - dir = 4; - icon_state = "tube1" + dir = 4 }, /turf/simulated/floor/plating/asteroid/airless, /area/syndicate_depot/outer) @@ -429,8 +426,7 @@ /area/syndicate_depot/core) "bo" = ( /obj/machinery/light{ - dir = 4; - icon_state = "tube1" + dir = 4 }, /obj/effect/spawner/random_spawners/syndicate/loot, /turf/simulated/floor/plasteel{ @@ -512,7 +508,6 @@ id = "syndi_depot_rear"; idle_power_usage = 0; name = "mysterious button"; - normaldoorcontrol = 0; pixel_x = 24; use_power = 0 }, @@ -663,8 +658,8 @@ /obj/machinery/turretid/syndicate{ name = "external turret controls"; pixel_x = -32; - pixel_y = 0; - req_access = list(150) + req_access = null; + req_access_txt = "150" }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -745,9 +740,8 @@ /area/syndicate_depot/core) "ce" = ( /obj/machinery/light/small{ - tag = "icon-bulb1 (EAST)"; - icon_state = "bulb1"; - dir = 4 + dir = 4; + tag = "icon-bulb1 (EAST)" }, /turf/simulated/floor/mineral/silver, /area/syndicate_depot/core) @@ -757,7 +751,6 @@ id = "syndi_depot_rear"; idle_power_usage = 0; name = "mysterious button"; - normaldoorcontrol = 0; use_power = 0 }, /obj/structure/sign/poster/contraband/syndicate_recruitment, @@ -774,8 +767,8 @@ /area/syndicate_depot/core) "ci" = ( /obj/structure/cable{ - icon_state = "0-2"; - d2 = 2 + d2 = 2; + icon_state = "0-2" }, /obj/machinery/power/smes/upgraded{ charge = 5e+006; @@ -845,7 +838,6 @@ "cr" = ( /obj/structure/sink{ dir = 4; - icon_state = "sink"; pixel_x = 12 }, /turf/simulated/floor/mineral/silver, @@ -1154,7 +1146,6 @@ "dc" = ( /obj/machinery/navbeacon/invisible{ codes_txt = "patrol;next_patrol=SDSE"; - invisibility = 100; location = "SDSW" }, /turf/simulated/floor/plating/asteroid/airless, @@ -1179,7 +1170,6 @@ "df" = ( /obj/machinery/navbeacon/invisible{ codes_txt = "patrol;next_patrol=SDNE"; - invisibility = 100; location = "SDSE" }, /turf/simulated/floor/plating/asteroid/airless, diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 83347c20d3b..f205c7cf0ce 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -95,7 +95,7 @@ proc/isDay(var/month, var/day) /proc/seconds_to_time(var/seconds as num) var/numSeconds = seconds % 60 var/numMinutes = (seconds - numSeconds) / 60 - return "[numMinutes] [numMinutes > 1 ? "minutes" : "minute"] and [numSeconds] seconds." + return "[numMinutes] [numMinutes > 1 ? "minutes" : "minute"] and [numSeconds] seconds" //Take a value in seconds and makes it display like a clock /proc/seconds_to_clock(var/seconds as num) diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm index 08fa7709320..b03013bf256 100644 --- a/code/controllers/subsystem/shuttles.dm +++ b/code/controllers/subsystem/shuttles.dm @@ -93,6 +93,11 @@ SUBSYSTEM_DEF(shuttle) return S WARNING("couldn't find dock with id: [id]") +/datum/controller/subsystem/shuttle/proc/secondsToRefuel() + var/elapsed = world.time - SSticker.round_start_time + var/remaining = round((config.shuttle_refuel_delay - elapsed) / 10) + return remaining ? remaining : 0 + /datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason) if(!emergency) WARNING("requestEvac(): There is no emergency shuttle, but the shuttle was called. Using the backup shuttle instead.") @@ -107,7 +112,7 @@ SUBSYSTEM_DEF(shuttle) return emergency = backup_shuttle - if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay) + if(secondsToRefuel()) to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.") return @@ -192,7 +197,7 @@ SUBSYSTEM_DEF(shuttle) var/obj/machinery/computer/communications/C = thing if(C.stat & BROKEN) continue - else if(istype(thing, /datum/computer_file/program/comm) || istype(thing, /obj/item/circuitboard/communications)) + else if(istype(thing, /obj/item/circuitboard/communications)) continue var/turf/T = get_turf(thing) diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index f826b6ff0d2..a19d75275fa 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -16,7 +16,7 @@ name = "Biodome Winter" id = "biodome-winter" description = "For those getaways where you want to get back to nature, but you don't want to leave the fortified military compound where you spend your days. \ - Includes a unique(*) laser pistol display case, and the recently introduced I.C.E(tm)." + Includes the recently introduced I.C.E(tm)." suffix = "lavaland_biodome_winter.dmm" /datum/map_template/ruin/lavaland/biodome/clown diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index a651edbc79c..a196a60fcc5 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -6,44 +6,47 @@ qdel(src) owner = new_owner -/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = FALSE, datum/topic_state/state = GLOB.ghost_state, datum/nanoui/master_ui = null) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/spawners_menu/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui_state/state = GLOB.tgui_observer_state, datum/tgui/master_ui = null) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "spawners_menu.tmpl", "Spawners Menu", 700, 600, master_ui, state = state) + ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state = state) ui.open() -/datum/spawners_menu/ui_data(mob/user) +/datum/spawners_menu/tgui_data(mob/user) var/list/data = list() data["spawners"] = list() for(var/spawner in GLOB.mob_spawners) var/list/this = list() this["name"] = spawner this["desc"] = "" + this["important_info"] = "" + this["fluff"] = "" this["uids"] = list() - for(var/spawner_obj in GLOB.mob_spawners[spawner]) + for(var/spawner_obj in GLOB.mob_spawners[spawner])//each spawner can contain multiple actual spawners, we use only one desc/info this["uids"] += "\ref[spawner_obj]" - if(!this["desc"]) + if(!this["desc"]) //haven't set descriptions yet if(istype(spawner_obj, /obj/effect/mob_spawn)) var/obj/effect/mob_spawn/MS = spawner_obj - this["desc"] = MS.flavour_text + this["desc"] = MS.description + this["important_info"] = MS.important_info + this["fluff"] = MS.flavour_text else var/obj/O = spawner_obj this["desc"] = O.desc this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner]) data["spawners"] += list(this) - return data -/datum/spawners_menu/Topic(href, href_list) +/datum/spawners_menu/tgui_act(action, params) if(..()) - return 1 - var/spawners = replacetext(href_list["uid"], ",", ";") + return + var/spawners = replacetext(params["ID"], ",", ";") var/list/possible_spawners = params2list(spawners) var/obj/effect/mob_spawn/MS = locate(pick(possible_spawners)) if(!MS || !istype(MS)) log_runtime(EXCEPTION("A ghost tried to interact with an invalid spawner, or the spawner didn't exist.")) return - switch(href_list["action"]) + switch(action) if("jump") owner.forceMove(get_turf(MS)) . = TRUE diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index 9c7fb99fe81..93b84dbb54d 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -40,7 +40,7 @@ aiPlayer.set_zeroth_law(law) to_chat(aiPlayer, "Laws Updated: [law]") - print_command_report(intercepttext, interceptname) + print_command_report(intercepttext, interceptname, FALSE) GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg', from = "[command_name()] Update") /datum/station_state diff --git a/code/game/gamemodes/devil/contracts/friend.dm b/code/game/gamemodes/devil/contracts/friend.dm index 7760ee10ee7..8838dc8a371 100644 --- a/code/game/gamemodes/devil/contracts/friend.dm +++ b/code/game/gamemodes/devil/contracts/friend.dm @@ -17,7 +17,8 @@ /obj/effect/mob_spawn/human/demonic_friend/Initialize(mapload, datum/mind/owner_mind, obj/effect/proc_holder/spell/targeted/summon_friend/summoning_spell) . = ..() owner = owner_mind - flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil. Be aware that if you do not live up to [owner.name]'s expectations, [owner.p_they()] can send you back to hell with a single thought. [owner.name]'s death will also return you to hell." + description = "Be someone's loyal friend/slave. If they die, you die as well." //best I could think of in the moment, not sure how this role plays in practise, have never seen it. + flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil. Be aware that if you do not live up to [owner.name]'s expectations, [owner.p_they()] can send you back to hell with a single thought. [owner.name]'s death will also return you to hell." var/area/A = get_area(src) if(!mapload && A) notify_ghosts("\A friendship shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = TRUE) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 1e2dd3d554b..1d50606c190 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -507,7 +507,7 @@ proc/display_roundstart_logout_report() message_text += G.get_report() message_text += "
" - print_command_report(message_text, "[command_name()] Orders") + print_command_report(message_text, "[command_name()] Orders", FALSE) /datum/game_mode/proc/declare_station_goal_completion() for(var/V in station_goals) diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index 8da5b4468d7..7fe146d3e47 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -19,15 +19,13 @@ mob_name = "a swarmer" death = FALSE roundstart = FALSE - flavour_text = {" - You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate. - Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful. - Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage. - Objectives: + important_info = "Follow your objectives, do not make the station inhospitable or try and kill crew." + flavour_text = "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate." + description = {" Your goal is to create more of yourself by consuming the station. Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful. Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage. + Objectives: 1. Consume resources and replicate until there are no more resources left. 2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable. - 3. Biological resources will be harvested at a later date; do not harm them. - "} + 3. Biological resources will be harvested at a later date; do not harm them."} /obj/effect/mob_spawn/swarmer/Initialize(mapload) . = ..() diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm index fbceda6bd94..5c4b83e965c 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm @@ -7,7 +7,7 @@ var/swarmer_report = "[command_name()] High-Priority Update" swarmer_report += "

Our long-range sensors have detected an odd signal emanating from your station's gateway. We recommend immediate investigation of your gateway, as something may have come \ through." - print_command_report(swarmer_report, "Classified [command_name()] Update") + print_command_report(swarmer_report, "Classified [command_name()] Update", FALSE) GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg') /datum/event/spawn_swarmer/start() diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 366946254ea..af0bc5c2b95 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -1,35 +1,39 @@ #define COMM_SCREEN_MAIN 1 #define COMM_SCREEN_STAT 2 #define COMM_SCREEN_MESSAGES 3 -#define COMM_SCREEN_SECLEVEL 4 #define COMM_AUTHENTICATION_NONE 0 #define COMM_AUTHENTICATION_MIN 1 #define COMM_AUTHENTICATION_MAX 2 +#define COMM_MSGLEN_MINIMUM 6 +#define COMM_CCMSGLEN_MINIMUM 20 + // The communications computer /obj/machinery/computer/communications name = "communications console" - desc = "This can be used for various important functions. Still under developement." + 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/prints_intercept = 1 - var/authenticated = COMM_AUTHENTICATION_NONE var/list/messagetitle = list() var/list/messagetext = list() - var/currmsg = 0 - var/aicurrmsg = 0 + var/currmsg + + var/authenticated = COMM_AUTHENTICATION_NONE var/menu_state = COMM_SCREEN_MAIN var/ai_menu_state = COMM_SCREEN_MAIN - var/message_cooldown = 0 - var/centcomm_message_cooldown = 0 + var/aicurrmsg + + var/message_cooldown + var/centcomm_message_cooldown var/tmp_alertlevel = 0 var/stat_msg1 var/stat_msg2 - var/display_type="blank" + var/display_type = "blank" + var/display_icon var/datum/announcement/priority/crew_announcement = new @@ -70,123 +74,114 @@ feedback_inc("alert_comms_blue",1) tmp_alertlevel = 0 -/obj/machinery/computer/communications/Topic(href, href_list) - if(..(href, href_list)) - return 1 - - if(!is_secure_level(src.z)) +/obj/machinery/computer/communications/tgui_act(action, params) + if(..()) + return + if(!is_secure_level(z)) to_chat(usr, "Unable to establish a connection: You're too far away from the station!") - return 1 + return - if(href_list["login"]) + . = TRUE + + if(action == "auth") if(!ishuman(usr)) to_chat(usr, "Access denied.") + return FALSE + // Logout function. + if(authenticated != COMM_AUTHENTICATION_NONE) + authenticated = COMM_AUTHENTICATION_NONE + crew_announcement.announcer = null + setMenuState(usr, COMM_SCREEN_MAIN) return - + // Login function. var/list/access = usr.get_access() if(allowed(usr)) authenticated = COMM_AUTHENTICATION_MIN - if(ACCESS_CAPTAIN in access) authenticated = COMM_AUTHENTICATION_MAX var/mob/living/carbon/human/H = usr var/obj/item/card/id = H.get_idcard(TRUE) if(istype(id)) crew_announcement.announcer = GetNameAndAssignmentFromId(id) - - SSnanoui.update_uis(src) - return - - if(href_list["logout"]) - authenticated = COMM_AUTHENTICATION_NONE - crew_announcement.announcer = "" - setMenuState(usr,COMM_SCREEN_MAIN) - SSnanoui.update_uis(src) + if(authenticated == COMM_AUTHENTICATION_NONE) + to_chat(usr, "You need to wear your ID.") return + // All functions below this point require authentication. if(!is_authenticated(usr)) - return 1 + return FALSE - switch(href_list["operation"]) + switch(action) if("main") - setMenuState(usr,COMM_SCREEN_MAIN) - - if("changeseclevel") - setMenuState(usr,COMM_SCREEN_SECLEVEL) + setMenuState(usr, COMM_SCREEN_MAIN) if("newalertlevel") if(isAI(usr) || isrobot(usr)) to_chat(usr, "Firewalls prevent you from changing the alert level.") - return 1 + return else if(usr.can_admin_interact()) - change_security_level(text2num(href_list["level"])) - return 1 + change_security_level(text2num(params["level"])) + return else if(!ishuman(usr)) to_chat(usr, "Security measures prevent you from changing the alert level.") - return 1 + return - var/mob/living/carbon/human/L = usr - var/obj/item/card = L.get_active_hand() - var/obj/item/card/id/I = (card && card.GetID()) || L.wear_id || L.wear_pda - if(istype(I, /obj/item/pda)) - var/obj/item/pda/pda = I - I = pda.id - if(I && istype(I)) + var/mob/living/carbon/human/H = usr + var/obj/item/card/id/I = H.get_idcard(TRUE) + if(istype(I)) if(ACCESS_CAPTAIN in I.access) - change_security_level(text2num(href_list["level"])) + change_security_level(text2num(params["level"])) else to_chat(usr, "You are not authorized to do this.") - setMenuState(usr,COMM_SCREEN_MAIN) + setMenuState(usr, COMM_SCREEN_MAIN) else - to_chat(usr, "You need to swipe your ID.") + to_chat(usr, "You need to wear your ID.") if("announce") if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX) - if(message_cooldown) + if(message_cooldown > world.time) to_chat(usr, "Please allow at least one minute to pass between announcements.") - SSnanoui.update_uis(src) return var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") - if(!input || message_cooldown || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) + if(!input || message_cooldown > world.time || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) + return + if(length(input) < COMM_MSGLEN_MINIMUM) + to_chat(usr, "Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.") return crew_announcement.Announce(input) - message_cooldown = 1 - spawn(600)//One minute cooldown - message_cooldown = 0 + message_cooldown = world.time + 600 //One minute if("callshuttle") var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") if(!input || ..() || !is_authenticated(usr)) - SSnanoui.update_uis(src) return call_shuttle_proc(usr, input) if(SSshuttle.emergency.timer) post_status("shuttle") - setMenuState(usr,COMM_SCREEN_MAIN) + setMenuState(usr, COMM_SCREEN_MAIN) if("cancelshuttle") if(isAI(usr) || isrobot(usr)) to_chat(usr, "Firewalls prevent you from recalling the shuttle.") - SSnanoui.update_uis(src) - return 1 + return var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No") if(response == "Yes") cancel_call_proc(usr) if(SSshuttle.emergency.timer) post_status("shuttle") - setMenuState(usr,COMM_SCREEN_MAIN) + setMenuState(usr, COMM_SCREEN_MAIN) if("messagelist") - currmsg = 0 - if(href_list["msgid"]) - setCurrentMessage(usr, text2num(href_list["msgid"])) - setMenuState(usr,COMM_SCREEN_MESSAGES) + currmsg = null + aicurrmsg = null + if(params["msgid"]) + setCurrentMessage(usr, text2num(params["msgid"])) + setMenuState(usr, COMM_SCREEN_MESSAGES) if("delmessage") - if(href_list["msgid"]) - currmsg = text2num(href_list["msgid"]) + if(params["msgid"]) + currmsg = text2num(params["msgid"]) var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No") if(response == "Yes") if(currmsg) @@ -196,95 +191,95 @@ messagetitle.Remove(title) messagetext.Remove(text) if(currmsg == id) - currmsg = 0 + currmsg = null if(aicurrmsg == id) - aicurrmsg = 0 - setMenuState(usr,COMM_SCREEN_MESSAGES) + aicurrmsg = null + setMenuState(usr, COMM_SCREEN_MESSAGES) if("status") - setMenuState(usr,COMM_SCREEN_STAT) + setMenuState(usr, COMM_SCREEN_STAT) // Status display stuff if("setstat") - display_type=href_list["statdisp"] + display_type = params["statdisp"] switch(display_type) if("message") + display_icon = null post_status("message", stat_msg1, stat_msg2, usr) if("alert") - post_status("alert", href_list["alert"], user = usr) + display_icon = params["alert"] + post_status("alert", params["alert"], user = usr) else - post_status(href_list["statdisp"], user = usr) - setMenuState(usr,COMM_SCREEN_STAT) + display_icon = null + post_status(params["statdisp"], user = usr) + setMenuState(usr, COMM_SCREEN_STAT) if("setmsg1") stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1) - setMenuState(usr,COMM_SCREEN_STAT) + setMenuState(usr, COMM_SCREEN_STAT) if("setmsg2") stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2) - setMenuState(usr,COMM_SCREEN_STAT) + setMenuState(usr, COMM_SCREEN_STAT) if("nukerequest") if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX) - if(centcomm_message_cooldown) + if(centcomm_message_cooldown > world.time) to_chat(usr, "Arrays recycling. Please stand by.") - SSnanoui.update_uis(src) return var/input = stripped_input(usr, "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.","") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) + return + if(length(input) < COMM_CCMSGLEN_MINIMUM) + to_chat(usr, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.") return Nuke_request(input, usr) to_chat(usr, "Request sent.") log_game("[key_name(usr)] has requested the nuclear codes from Centcomm") GLOB.priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') - centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) + centcomm_message_cooldown = world.time + 6000 // 10 minutes + setMenuState(usr, COMM_SCREEN_MAIN) if("MessageCentcomm") if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX) - if(centcomm_message_cooldown) + if(centcomm_message_cooldown > world.time) to_chat(usr, "Arrays recycling. Please stand by.") - SSnanoui.update_uis(src) return var/input = stripped_input(usr, "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.", "To abort, send an empty message.", "") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) + return + if(length(input) < COMM_CCMSGLEN_MINIMUM) + to_chat(usr, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.") return Centcomm_announce(input, usr) print_centcom_report(input, station_time_timestamp() + " Captain's Message") to_chat(usr, "Message transmitted.") log_game("[key_name(usr)] has made a Centcomm announcement: [input]") - centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) + centcomm_message_cooldown = world.time + 6000 // 10 minutes + setMenuState(usr, COMM_SCREEN_MAIN) // OMG SYNDICATE ...LETTERHEAD if("MessageSyndicate") if((is_authenticated(usr) == COMM_AUTHENTICATION_MAX) && (src.emagged)) - if(centcomm_message_cooldown) + if(centcomm_message_cooldown > world.time) to_chat(usr, "Arrays recycling. Please stand by.") - SSnanoui.update_uis(src) return var/input = stripped_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.", "To abort, send an empty message.", "") if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) + return + if(length(input) < COMM_CCMSGLEN_MINIMUM) + to_chat(usr, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.") return Syndicate_announce(input, usr) to_chat(usr, "Message transmitted.") log_game("[key_name(usr)] has made a Syndicate announcement: [input]") - centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) + centcomm_message_cooldown = world.time + 6000 // 10 minutes + setMenuState(usr, COMM_SCREEN_MAIN) if("RestoreBackup") to_chat(usr, "Backup routing data restored!") src.emagged = 0 - setMenuState(usr,COMM_SCREEN_MAIN) + setMenuState(usr, COMM_SCREEN_MAIN) if("RestartNanoMob") if(SSmob_hunt) @@ -298,14 +293,13 @@ else to_chat(usr, "Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.") - SSnanoui.update_uis(src) - return 1 + /obj/machinery/computer/communications/emag_act(user as mob) if(!emagged) src.emagged = 1 to_chat(user, "You scramble the communication routing circuits!") - SSnanoui.update_uis(src) + SStgui.update_uis(src) /obj/machinery/computer/communications/attack_ai(var/mob/user as mob) return src.attack_hand(user) @@ -321,28 +315,25 @@ to_chat(user, "Unable to establish a connection: You're too far away from the station!") return - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/communications/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui) +/obj/machinery/computer/communications/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "comm_console.tmpl", "Communications Console", 400, 500) - // open the new ui window + ui = new(user, src, ui_key, "CommunicationsComputer", name, 500, 600, master_ui, state) ui.open() -/obj/machinery/computer/communications/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/machinery/computer/communications/tgui_data(mob/user) + var/list/data = list() data["is_ai"] = isAI(user) || isrobot(user) data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state data["emagged"] = emagged data["authenticated"] = is_authenticated(user, 0) - data["screen"] = getMenuState(usr) + data["authmax"] = data["authenticated"] == COMM_AUTHENTICATION_MAX ? TRUE : FALSE data["stat_display"] = list( "type" = display_type, + "icon" = display_icon, "line_1" = (stat_msg1 ? stat_msg1 : "-----"), "line_2" = (stat_msg2 ? stat_msg2 : "-----"), @@ -360,12 +351,20 @@ ) ) - data["security_level"] = GLOB.security_level + data["security_level"] = GLOB.security_level + switch(GLOB.security_level) + if(SEC_LEVEL_GREEN) + data["security_level_color"] = "green"; + if(SEC_LEVEL_BLUE) + data["security_level_color"] = "blue"; + if(SEC_LEVEL_RED) + data["security_level_color"] = "red"; + else + data["security_level_color"] = "purple"; data["str_security_level"] = capitalize(get_security_level()) data["levels"] = list( - list("id" = SEC_LEVEL_GREEN, "name" = "Green"), - list("id" = SEC_LEVEL_BLUE, "name" = "Blue"), - //SEC_LEVEL_RED = list("name"="Red"), + list("id" = SEC_LEVEL_GREEN, "name" = "Green", "icon" = "dove"), + list("id" = SEC_LEVEL_BLUE, "name" = "Blue", "icon" = "eye"), ) var/list/msg_data = list() @@ -373,27 +372,29 @@ msg_data.Add(list(list("title" = messagetitle[i], "body" = messagetext[i], "id" = i))) data["messages"] = msg_data + + data["current_message"] = null + data["current_message_title"] = null if((data["is_ai"] && aicurrmsg) || (!data["is_ai"] && currmsg)) data["current_message"] = data["is_ai"] ? messagetext[aicurrmsg] : messagetext[currmsg] data["current_message_title"] = data["is_ai"] ? messagetitle[aicurrmsg] : messagetitle[currmsg] data["lastCallLoc"] = SSshuttle.emergencyLastCallLoc ? format_text(SSshuttle.emergencyLastCallLoc.name) : null + data["msg_cooldown"] = message_cooldown ? (round((message_cooldown - world.time) / 10)) : 0 + data["cc_cooldown"] = centcomm_message_cooldown ? (round((centcomm_message_cooldown - world.time) / 10)) : 0 - var/shuttle[0] - switch(SSshuttle.emergency.mode) - if(SHUTTLE_IDLE, SHUTTLE_RECALL) - shuttle["callStatus"] = 2 //#define - else - shuttle["callStatus"] = 1 - if(SSshuttle.emergency.mode == SHUTTLE_CALL) + var/secondsToRefuel = SSshuttle.secondsToRefuel() + data["esc_callable"] = SSshuttle.emergency.mode == SHUTTLE_IDLE && !secondsToRefuel ? TRUE : FALSE + data["esc_recallable"] = SSshuttle.emergency.mode == SHUTTLE_CALL ? TRUE : FALSE + data["esc_status"] = FALSE + if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) var/timeleft = SSshuttle.emergency.timeLeft() - shuttle["eta"] = "[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" - - data["shuttle"] = shuttle - + data["esc_status"] = SSshuttle.emergency.mode == SHUTTLE_CALL ? "ETA:" : "RECALLING:" + data["esc_status"] += " [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" + else if(secondsToRefuel) + data["esc_status"] = "Refueling: [secondsToRefuel / 60 % 60]:[add_zero(num2text(secondsToRefuel % 60), 2)]" return data - /obj/machinery/computer/communications/proc/setCurrentMessage(var/mob/user,var/value) if(isAI(user) || isrobot(user)) aicurrmsg = value @@ -412,12 +413,6 @@ else menu_state=value -/obj/machinery/computer/communications/proc/getMenuState(var/mob/user) - if(isAI(user) || isrobot(user)) - return ai_menu_state - else - return menu_state - /proc/call_shuttle_proc(var/mob/user, var/reason) if(GLOB.sent_strike_team == 1) to_chat(user, "Central Command will not allow the shuttle to be called. Consider all contracts terminated.") @@ -521,24 +516,16 @@ SSshuttle.autoEvac() return ..() -/proc/print_command_report(text = "", title = "Central Command Update") +/proc/print_command_report(text = "", title = "Central Command Update", add_to_records = TRUE) for(var/obj/machinery/computer/communications/C in GLOB.shuttle_caller_list) if(!(C.stat & (BROKEN|NOPOWER)) && is_station_contact(C.z)) var/obj/item/paper/P = new /obj/item/paper(C.loc) P.name = "paper- '[title]'" P.info = text P.update_icon() - C.messagetitle.Add("[title]") - C.messagetext.Add(text) - for(var/datum/computer_file/program/comm/P in GLOB.shuttle_caller_list) - var/turf/T = get_turf(P.computer) - if(T && P.program_state != PROGRAM_STATE_KILLED && is_station_contact(T.z)) - if(P.computer) - var/obj/item/computer_hardware/printer/printer = P.computer.all_components[MC_PRINT] - if(printer) - printer.print_text(text, "paper- '[title]'") - P.messagetitle.Add("[title]") - P.messagetext.Add(text) + if(add_to_records) + C.messagetitle.Add("[title]") + C.messagetext.Add(text) /proc/print_centcom_report(text = "", title = "Incoming Message") for(var/obj/machinery/computer/communications/C in GLOB.shuttle_caller_list) @@ -549,12 +536,5 @@ P.update_icon() C.messagetitle.Add("[title]") C.messagetext.Add(text) - for(var/datum/computer_file/program/comm/P in GLOB.shuttle_caller_list) - var/turf/T = get_turf(P.computer) - if(T && P.program_state != PROGRAM_STATE_KILLED && is_admin_level(T.z)) - if(P.computer) - var/obj/item/computer_hardware/printer/printer = P.computer.all_components[MC_PRINT] - if(printer) - printer.print_text(text, "paper- '[title]'") - P.messagetitle.Add("[title]") - P.messagetext.Add(text) + + diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 6134860733a..ed3b3d95099 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -20,221 +20,210 @@ return if(stat & (NOPOWER|BROKEN)) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/robotics/proc/is_authenticated(var/mob/user as mob) +/obj/machinery/computer/robotics/proc/is_authenticated(mob/user) + if(!istype(user)) + return FALSE if(user.can_admin_interact()) - return 1 - else if(allowed(user)) - return 1 - return 0 + return TRUE + if(allowed(user)) + return TRUE + return FALSE -/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/** + * Does this borg show up in the console + * + * Returns TRUE if a robot will show up in the console + * Returns FALSE if a robot will not show up in the console + * Arguments: + * * R - The [mob/living/silicon/robot] to be checked + */ +/obj/machinery/computer/robotics/proc/console_shows(mob/living/silicon/robot/R) + if(!istype(R)) + return FALSE + if(istype(R, /mob/living/silicon/robot/drone)) + return FALSE + if(R.scrambledcodes) + return FALSE + if(!atoms_share_level(src, R)) + return FALSE + return TRUE + +/** + * Check if a user can send a lockdown/detonate command to a specific borg + * + * Returns TRUE if a user can send the command (does not guarantee it will work) + * Returns FALSE if a user cannot + * Arguments: + * * user - The [mob/user] to be checked + * * R - The [mob/living/silicon/robot] to be checked + * * telluserwhy - Bool of whether the user should be sent a to_chat message if they don't have access + */ +/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R, telluserwhy = FALSE) + if(!istype(user)) + return FALSE + if(!console_shows(R)) + return FALSE + if(isAI(user)) + if(R.connected_ai != user) + if(telluserwhy) + to_chat(user, "AIs can only control cyborgs which are linked to them.") + return FALSE + if(isrobot(user)) + if(R != user) + if(telluserwhy) + to_chat(user, "Cyborgs cannot control other cyborgs.") + return FALSE + return TRUE + +/** + * Check if the user is the right kind of entity to be able to hack borgs + * + * Returns TRUE if a user is a traitor AI, or aghost + * Returns FALSE otherwise + * Arguments: + * * user - The [mob/user] to be checked + */ +/obj/machinery/computer/robotics/proc/can_hack_any(mob/user) + if(!istype(user)) + return FALSE + if(user.can_admin_interact()) + return TRUE + if(!isAI(user)) + return FALSE + return (user.mind.special_role && user.mind.original == user) + +/** + * Check if the user is allowed to hack a specific borg + * + * Returns TRUE if a user can hack the specific cyborg + * Returns FALSE if a user cannot + * Arguments: + * * user - The [mob/user] to be checked + * * R - The [mob/living/silicon/robot] to be checked + */ +/obj/machinery/computer/robotics/proc/can_hack(mob/user, mob/living/silicon/robot/R) + if(!can_hack_any(user)) + return FALSE + if(!istype(R)) + return FALSE + if(R.emagged) + return FALSE + if(R.connected_ai != user) + return FALSE + return TRUE + +/obj/machinery/computer/robotics/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "robot_control.tmpl", "Robotic Control Console", 400, 500) + ui = new(user, src, ui_key, "RoboticsControlConsole", name, 500, 460, master_ui, state) ui.open() - ui.set_auto_update(1) -/obj/machinery/computer/robotics/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - var/list/robots = get_cyborgs(user) - if(robots.len) - data["robots"] = robots +/obj/machinery/computer/robotics/tgui_data(mob/user) + var/list/data = list() + data["auth"] = is_authenticated(user) + data["can_hack"] = can_hack_any(user) + data["cyborgs"] = list() data["safety"] = safety - // Also applies for cyborgs. Hides the manual self-destruct button. - data["is_ai"] = issilicon(user) - data["allowed"] = is_authenticated(user) + for(var/mob/living/silicon/robot/R in GLOB.mob_list) + if(!console_shows(R)) + continue + var/area/A = get_area(R) + var/turf/T = get_turf(R) + var/list/cyborg_data = list( + name = R.name, + uid = R.UID(), + locked_down = R.lockcharge, + locstring = "[A.name] ([T.x], [T.y])", + status = R.stat, + health = round(R.health * 100 / R.maxHealth, 0.1), + charge = R.cell ? round(R.cell.percent()) : null, + cell_capacity = R.cell ? R.cell.maxcharge : null, + module = R.module ? R.module.name : "No Module Detected", + synchronization = R.connected_ai, + is_hacked = R.connected_ai && R.emagged, + hackable = can_hack(user, R), + ) + data["cyborgs"] += list(cyborg_data) + data["show_detonate_all"] = (data["auth"] && length(data["cyborgs"]) > 0 && ishuman(user)) return data -/obj/machinery/computer/robotics/Topic(href, href_list) +/obj/machinery/computer/robotics/tgui_act(action, params) if(..()) - return 1 - - var/mob/user = usr - if(!is_authenticated(user)) - to_chat(user, "Access denied.") return - - // Destroys the cyborg - if(href_list["detonate"]) - var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["detonate"]) - if(!target || !istype(target)) - return - if(isAI(user) && (target.connected_ai != user)) - to_chat(user, "Access Denied. This robot is not linked to you.") - return - // Cyborgs may blow up themselves via the console - if((isrobot(user) && user != target) || !is_authenticated(user)) - to_chat(user, "Access Denied.") - return - var/choice = input("Really detonate [target.name]?") in list ("Yes", "No") - if(choice != "Yes") - return - if(!target || !istype(target)) - return - - // Antagonistic cyborgs? Left here for downstream - if(target.mind && target.mind.special_role && target.emagged) - to_chat(target, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.") - target.ResetSecurityCodes() - else - message_admins("[key_name_admin(usr)] detonated [key_name_admin(target)] (JMP)!") - log_game("\[key_name(usr)] detonated [key_name(target)]!") - to_chat(target, "Self-destruct command received.") - if(target.connected_ai) - to_chat(target.connected_ai, "

ALERT - Cyborg detonation detected: [target.name]
") - spawn(10) - target.self_destruct() - - // Locks or unlocks the cyborg - else if(href_list["lockdown"]) - var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"]) - if(!target || !istype(target)) - return - - if(isAI(user) && (target.connected_ai != user)) - to_chat(user, "Access Denied. This robot is not linked to you.") - return - - if(isrobot(user)) - to_chat(user, "Access Denied.") - return - - var/choice = input("Really [target.lockcharge ? "unlock" : "lockdown"] [target.name] ?") in list ("Yes", "No") - if(choice != "Yes") - return - - if(!target || !istype(target)) - return - - message_admins("[key_name_admin(usr)] [target.canmove ? "locked down" : "released"] [key_name_admin(target)]!") - log_game("[key_name(usr)] [target.canmove ? "locked down" : "released"] [key_name(target)]!") - target.SetLockdown(!target.lockcharge) - to_chat(target, "[!target.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]") - if(target.connected_ai) - to_chat(target.connected_ai, "[!target.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [target.name]
") - - // Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs. - else if(href_list["hack"]) - var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"]) - if(!target || !istype(target)) - return - - // Antag AI checks - if(!istype(user, /mob/living/silicon/ai) || !(user.mind.special_role && user.mind.original == user)) - to_chat(user, "Access Denied.") - return - - if(target.connected_ai != user) - to_chat(user, "Access Denied. This robot is not linked to you.") - return - - if(target.emagged) - to_chat(user, "Robot is already hacked.") - return - - var/choice = input("Really hack [target.name]? This cannot be undone.") in list("Yes", "No") - if(choice != "Yes") - return - - if(!target || !istype(target)) - return - - message_admins("[key_name_admin(usr)] emagged [key_name_admin(target)] using robotic console!") - log_game("[key_name(usr)] emagged [key_name(target)] using robotic console!") - target.emagged = 1 - to_chat(target, "Failsafe protocols overriden. New tools available.") - - // Arms the emergency self-destruct system - else if(href_list["arm"]) - if(istype(user, /mob/living/silicon)) - to_chat(user, "Access Denied.") - return - - safety = !safety - to_chat(user, "You [safety ? "disarm" : "arm"] the emergency self destruct.") - - // Destroys all accessible cyborgs if safety is disabled - else if(href_list["nuke"]) - if(istype(user, /mob/living/silicon)) - to_chat(user, "Access Denied") - return - if(safety) - to_chat(user, "Self-destruct aborted - safety active") - return - - message_admins("[key_name_admin(usr)] detonated all cyborgs!") - log_game("\[key_name(usr)] detonated all cyborgs!") - - for(var/mob/living/silicon/robot/R in GLOB.mob_list) - if(istype(R, /mob/living/silicon/robot/drone)) - continue - // Ignore antagonistic cyborgs - if(R.scrambledcodes) - continue + . = FALSE + if(!is_authenticated(usr)) + to_chat(usr, "Access denied.") + return + switch(action) + if("arm") // Arms the emergency self-destruct system + if(issilicon(usr)) + to_chat(usr, "Access Denied (silicon detected)") + return + safety = !safety + to_chat(usr, "You [safety ? "disarm" : "arm"] the emergency self destruct.") + . = TRUE + if("nuke") // Destroys all accessible cyborgs if safety is disabled + if(issilicon(usr)) + to_chat(usr, "Access Denied (silicon detected)") + return + if(safety) + to_chat(usr, "Self-destruct aborted - safety active") + return + message_admins("[key_name_admin(usr)] detonated all cyborgs!") + log_game("\[key_name(usr)] detonated all cyborgs!") + for(var/mob/living/silicon/robot/R in GLOB.mob_list) + if(istype(R, /mob/living/silicon/robot/drone)) + continue + // Ignore antagonistic cyborgs + if(R.scrambledcodes) + continue + to_chat(R, "Self-destruct command received.") + if(R.connected_ai) + to_chat(R.connected_ai, "

ALERT - Cyborg detonation detected: [R.name]
") + R.self_destruct() + . = TRUE + if("killbot") // destroys one specific cyborg + var/mob/living/silicon/robot/R = locateUID(params["uid"]) + if(!can_control(usr, R, TRUE)) + return + if(R.mind && R.mind.special_role && R.emagged) + to_chat(R, "Extreme danger! Termination codes detected. Scrambling security codes and automatic AI unlink triggered.") + R.ResetSecurityCodes() + . = TRUE + return + var/turf/T = get_turf(R) + message_admins("[key_name_admin(usr)] detonated [key_name_admin(R)] ([ADMIN_COORDJMP(T)])!") + log_game("\[key_name(usr)] detonated [key_name(R)]!") to_chat(R, "Self-destruct command received.") if(R.connected_ai) to_chat(R.connected_ai, "

ALERT - Cyborg detonation detected: [R.name]
") - spawn(10) - R.self_destruct() - -// Proc: get_cyborgs() -// Parameters: 1 (operator - mob which is operating the console.) -// Description: Returns NanoUI-friendly list of accessible cyborgs. -/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator) - var/list/robots = list() - - for(var/mob/living/silicon/robot/R in GLOB.mob_list) - // Ignore drones - if(istype(R, /mob/living/silicon/robot/drone)) - continue - // Ignore antagonistic cyborgs - if(R.scrambledcodes) - continue - - var/list/robot = list() - robot["name"] = R.name - if(R.stat) - robot["status"] = "Not Responding" - else if(!R.canmove) - robot["status"] = "Lockdown" - else - robot["status"] = "Operational" - - if(R.cell) - robot["cell"] = 1 - robot["cell_capacity"] = R.cell.maxcharge - robot["cell_current"] = R.cell.charge - robot["cell_percentage"] = round(R.cell.percent()) - else - robot["cell"] = 0 - - var/turf/pos = get_turf(R) - var/area/bot_area = get_area(R) - robot["xpos"] = pos.x - robot["ypos"] = pos.y - robot["zpos"] = pos.z - robot["area"] = format_text(bot_area.name) - - robot["health"] = round(R.health * 100 / R.maxHealth,0.1) - - robot["module"] = R.module ? R.module.name : "None" - robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None" - robot["hackable"] = 0 - // Antag AIs know whether linked cyborgs are hacked or not. - if(operator && istype(operator, /mob/living/silicon/ai) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator)) - robot["hacked"] = R.emagged ? 1 : 0 - robot["hackable"] = R.emagged? 0 : 1 - robots.Add(list(robot)) - return robots - -// Proc: get_cyborg_by_name() -// Parameters: 1 (name - Cyborg we are trying to find) -// Description: Helper proc for finding cyborg by name -/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name) - if(!name) - return - for(var/mob/living/silicon/robot/R in GLOB.mob_list) - if(R.name == name) - return R + R.self_destruct() + . = TRUE + if("stopbot") // lock or unlock the borg + if(isrobot(usr)) + to_chat(usr, "Access Denied.") + return + var/mob/living/silicon/robot/R = locateUID(params["uid"]) + if(!can_control(usr, R, TRUE)) + return + message_admins("[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!") + log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!") + R.SetLockdown(!R.lockcharge) + to_chat(R, "[!R.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]") + if(R.connected_ai) + to_chat(R.connected_ai, "[!R.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
") + . = TRUE + if("hackbot") // AIs hacking/emagging a borg + var/mob/living/silicon/robot/R = locateUID(params["uid"]) + if(!can_hack(usr, R)) + return + var/choice = input("Really hack [R.name]? This cannot be undone.") in list("Yes", "No") + if(choice != "Yes") + return + log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!") + message_admins("[key_name_admin(usr)] emagged [key_name_admin(R)] using robotic console!") + R.emagged = TRUE + to_chat(R, "Failsafe protocols overriden. New tools available.") + . = TRUE diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 36eba1a6ee5..268f2ede9fb 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -36,9 +36,10 @@ var/crimes = CELL_NONE var/time = 0 var/officer = CELL_NONE - var/prisoner_name = "" - var/prisoner_charge = "" - var/prisoner_time = "" + var/prisoner_name + var/prisoner_charge + var/prisoner_time + var/prisoner_hasrecord = FALSE /obj/machinery/door_timer/New() GLOB.celltimers_list += src @@ -82,10 +83,15 @@ var/datum/data/record/R = find_security_record("name", occupant) - var/announcetext = "Detainee [occupant] ([prisoner_drank]) has been incarcerated for [seconds_to_time(timetoset / 10)] for the charges of: '[crimes]'. \ + var/timetext = seconds_to_time(timetoset / 10) + var/announcetext = "Detainee [occupant] ([prisoner_drank]) has been incarcerated for [timetext] for the crime of: '[crimes]'. \ Arresting Officer: [usr.name].[R ? "" : " Detainee record not found, manual record update required."]" Radio.autosay(announcetext, name, "Security", list(z)) + // Notify the actual criminal being brigged. This is a QOL thing to ensure they always know the charges against them. + // Announcing it on radio isn't enough, as they're unlikely to have sec radio. + notify_prisoner("You have been incarcerated for [timetext] for the crime of: '[crimes]'.") + if(prisoner_trank != "unknown" && prisoner_trank != "Civilian") SSjobs.notify_dept_head(prisoner_trank, announcetext) @@ -104,6 +110,13 @@ update_all_mob_security_hud() return 1 +/obj/machinery/door_timer/proc/notify_prisoner(notifytext) + for(var/mob/living/carbon/human/H in range(4, get_turf(src))) + if(occupant == H.name) + to_chat(H, "[src] beeps, \"[notifytext]\"") + return + atom_say("[src] beeps, \"[occupant]: [notifytext]\"") + /obj/machinery/door_timer/Initialize() ..() @@ -261,13 +274,11 @@ return -//Allows AIs to use door_timer, see human attack_hand function below /obj/machinery/door_timer/attack_ai(mob/user) - attack_hand(user) - ui_interact(user) + tgui_interact(user) /obj/machinery/door_timer/attack_ghost(mob/user) - ui_interact(user) + tgui_interact(user) //Allows humans to use door_timer //Opens dialog window when someone clicks on door timer @@ -276,71 +287,109 @@ /obj/machinery/door_timer/attack_hand(mob/user) if(..()) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/door_timer/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "brig_timer.tmpl", "Brig Timer", 500, 400) + ui = new(user, src, ui_key, "BrigTimer", name, 500, 450, master_ui, state) ui.open() - ui.set_auto_update(TRUE) -/obj/machinery/door_timer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/machinery/door_timer/tgui_static_data(mob/user) + var/list/data = list() + data["spns"] = list() + for(var/mob/living/carbon/human/H in range(4, get_turf(src))) + if(H.handcuffed) + data["spns"] += H.name + return data + +/obj/machinery/door_timer/tgui_data(mob/user) + var/list/data = list() data["cell_id"] = name data["occupant"] = occupant data["crimes"] = crimes data["brigged_by"] = officer - data["time_set"] = seconds_to_clock(time / 10) + data["time_set"] = seconds_to_clock(timetoset / 10) data["time_left"] = seconds_to_clock(timeleft()) data["timing"] = timing data["isAllowed"] = allowed(user) data["prisoner_name"] = prisoner_name data["prisoner_charge"] = prisoner_charge data["prisoner_time"] = prisoner_time - + data["prisoner_hasrec"] = prisoner_hasrecord return data -/obj/machinery/door_timer/Topic(href, href_list) - if(!allowed(usr) && !usr.can_admin_interact()) - return 1 +/obj/machinery/door_timer/allowed(mob/user) + if(user.can_admin_interact()) + return TRUE + return ..() - if(href_list["flash"]) - for(var/obj/machinery/flasher/F in targets) - if(F.last_flash && (F.last_flash + 150) > world.time) - to_chat(usr, "Flash still charging.") +/obj/machinery/door_timer/tgui_act(action, params) + if(..()) + return + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return + . = TRUE + switch(action) + if("prisoner_name") + if(params["prisoner_name"]) + prisoner_name = params["prisoner_name"] else - F.flash() - - if(href_list["release"]) - if(timing) - timer_end() - Radio.autosay("Timer stopped manually from cell control.", name, "Security", list(z)) - ui_interact(usr) - - if(href_list["prisoner_name"]) - prisoner_name = input("Prisoner Name:", name, prisoner_name) as text|null - - if(href_list["prisoner_charge"]) - prisoner_charge = input("Prisoner Charge:", name, prisoner_charge) as text|null - - if(href_list["prisoner_time"]) - prisoner_time = input("Prisoner Time (in minutes):", name, prisoner_time) as num|null - prisoner_time = min(max(round(prisoner_time), 0), 60) - - if(href_list["set_timer"]) - if(!prisoner_name || !prisoner_charge || !prisoner_time) - return - timeset(prisoner_time * 60) - occupant = prisoner_name - crimes = prisoner_charge - prisoner_name = "" - prisoner_charge = "" - prisoner_time = "" - timing = TRUE - timer_start() - ui_interact(usr) - update_icon() + prisoner_name = input("Prisoner Name:", name, prisoner_name) as text|null + if(prisoner_name) + var/datum/data/record/R = find_security_record("name", prisoner_name) + if(istype(R)) + prisoner_hasrecord = TRUE + else + prisoner_hasrecord = FALSE + if("prisoner_charge") + prisoner_charge = input("Prisoner Charge:", name, prisoner_charge) as text|null + if("prisoner_time") + prisoner_time = input("Prisoner Time (in minutes):", name, prisoner_time) as num|null + prisoner_time = min(max(round(prisoner_time), 0), 60) + if("start") + if(!prisoner_name || !prisoner_charge || !prisoner_time) + return FALSE + timeset(prisoner_time * 60) + occupant = prisoner_name + crimes = prisoner_charge + prisoner_name = null + prisoner_charge = null + prisoner_time = null + timing = TRUE + timer_start() + update_icon() + if("restart_timer") + if(timing) + var/reset_reason = sanitize(copytext(input(usr, "Reason for resetting timer:", name, "") as text|null, 1, MAX_MESSAGE_LEN)) + if(!reset_reason) + to_chat(usr, "Cancelled reset: reason field is required.") + return FALSE + releasetime = world.timeofday + timetoset + var/resettext = isobserver(usr) ? "for: [reset_reason]." : "by [usr.name] for: [reset_reason]." + Radio.autosay("Prisoner [occupant] had their timer reset [resettext]", name, "Security", list(z)) + notify_prisoner("Your brig timer has been reset for: '[reset_reason]'.") + var/datum/data/record/R = find_security_record("name", occupant) + if(istype(R)) + R.fields["comments"] += "Autogenerated by [name] on [GLOB.current_date_string] [station_time_timestamp()]
Timer reset [resettext]" + else + . = FALSE + if("stop") + if(timing) + timer_end() + var/stoptext = isobserver(usr) ? "from cell control." : "by [usr.name]." + Radio.autosay("Timer stopped manually [stoptext]", name, "Security", list(z)) + else + . = FALSE + if("flash") + for(var/obj/machinery/flasher/F in targets) + if(F.last_flash && (F.last_flash + 150) > world.time) + to_chat(usr, "Flash still charging.") + else + F.flash() + else + . = FALSE //icon update function diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index fdca5c56194..48b022a65f3 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -11,9 +11,6 @@ var/max_amount = 0 var/price = 0 // Price to buy one -/** - * A vending machine - */ /obj/machinery/vending name = "\improper Vendomat" desc = "A generic vending machine." @@ -25,8 +22,10 @@ max_integrity = 300 integrity_failure = 100 armor = list(melee = 20, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70) - var/icon_vend //Icon_state when vending - var/icon_deny //Icon_state when denying access + /// Icon_state when vending + var/icon_vend + /// Icon_state when denying access + var/icon_deny // Power use_power = IDLE_POWER_USE @@ -34,12 +33,14 @@ var/vend_power_usage = 150 // Vending-related - var/active = 1 //No sales pitches if off! - var/vend_ready = 1 //Are we ready to vend?? Is it time?? - var/vend_delay = 10 //How long does it take to vend? - var/datum/data/vending_product/currently_vending = null // What we're requesting payment for right now - var/status_message = "" // Status screen messages like "insufficient funds", displayed in NanoUI - var/status_error = 0 // Set to 1 if status_message is an error + /// No sales pitches if off + var/active = 1 + /// If off, vendor is busy and unusable until current action finishes + var/vend_ready = TRUE + /// How long vendor takes to vend one item. + var/vend_delay = 10 + /// Item currently being bought + var/datum/data/vending_product/currently_vending = null // To be filled out at compile time var/list/products = list() // For each, use the following pattern: @@ -51,16 +52,19 @@ var/list/product_records = list() var/list/hidden_records = list() var/list/coin_records = list() + var/list/imagelist = list() - - var/list/ads_list = list() //Small ad messages in the vending screen - random chance, TODO: implementation + /// Unimplemented list of ads that are meant to show up somewhere, but don't. + var/list/ads_list = list() // Stuff relating vocalizations - var/list/slogan_list = list() //List of slogans the vendor will say, optional + /// List of slogans the vendor will say, optional + var/list/slogan_list = list() var/vend_reply //Thank you for shopping! - var/shut_up = 0 //Stop spouting those godawful pitches! + /// If true, prevent saying sales pitches + var/shut_up = FALSE ///can we access the hidden inventory? - var/extended_inventory = 0 + var/extended_inventory = FALSE var/last_reply = 0 var/last_slogan = 0 //When did we last pitch? var/slogan_delay = 6000 //How long until we can pitch again? @@ -69,17 +73,26 @@ var/obj/item/vending_refill/refill_canister = null // Things that can go wrong - emagged = 0 //Ignores if somebody doesn't have card access to that machine. - var/seconds_electrified = 0 //Shock customers like an airlock. - var/shoot_inventory = 0 //Fire items at customers! We're broken! - var/shoot_speed = 3 //How hard are we firing the items? - var/shoot_chance = 2 //How often are we firing the items? + /// Allows people to access a vendor that's normally access restricted. + emagged = 0 + /// Shocks people like an airlock + var/seconds_electrified = 0 + /// Fire items at customers! We're broken! + var/shoot_inventory = FALSE + /// How hard are we firing the items? + var/shoot_speed = 3 + /// How often are we firing the items? (prob(...)) + var/shoot_chance = 2 - var/scan_id = 1 + /// If true, enforce access checks on customers. Disabled by messing with wires. + var/scan_id = TRUE + /// Holder for a coin inserted into the vendor var/obj/item/coin/coin var/datum/wires/vending/wires = null + /// boolean, whether this vending machine can accept people inserting items into it, used for coffee vendors var/item_slot = FALSE + /// the actual item inserted var/obj/item/inserted_item = null /obj/machinery/vending/Initialize(mapload) @@ -92,6 +105,10 @@ build_inventory(products, product_records) build_inventory(contraband, hidden_records) build_inventory(premium, coin_records) + for (var/datum/data/vending_product/R in (product_records + coin_records + hidden_records)) + var/obj/item/I = R.product_path + var/pp = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-") + imagelist[pp] = "[icon2base64(icon(initial(I.icon), initial(I.icon_state)))]" if(LAZYLEN(slogan_list)) // So not all machines speak at the exact same time. // The first time this machine says something will be at slogantime + this random value, @@ -214,37 +231,16 @@ ..() /obj/machinery/vending/attackby(obj/item/I, mob/user, params) - if(currently_vending && GLOB.vendor_account && !GLOB.vendor_account.suspended) - var/paid = 0 - var/handled = 0 - if(istype(I, /obj/item/card/id)) - var/obj/item/card/id/C = I - paid = pay_with_card(C) - handled = 1 - if(istype(I, /obj/item/pda)) - var/obj/item/pda/PDA = I - if(PDA.id) - paid = pay_with_card(PDA.id) - handled = 1 - else if(istype(I, /obj/item/stack/spacecash)) - var/obj/item/stack/spacecash/C = I - paid = pay_with_cash(C, user) - handled = 1 - - if(paid) - vend(currently_vending, usr) + if(istype(I, /obj/item/coin)) + if(!premium.len) + to_chat(user, "[src] does not accept coins.") return - else if(handled) - SSnanoui.update_uis(src) - return // don't smack that machine with your 2 thalers - - if(istype(I, /obj/item/coin) && premium.len) if(!user.drop_item()) return I.forceMove(src) coin = I to_chat(user, "You insert the [I] into the [src]") - SSnanoui.update_uis(src) + SStgui.update_uis(src) return if(refill_canister && istype(I, refill_canister)) if(!panel_open) @@ -295,7 +291,7 @@ else SCREWDRIVER_CLOSE_PANEL_MESSAGE overlays.Cut() - SSnanoui.update_uis(src) // Speaker switch is on the main UI, not wires UI + SStgui.update_uis(src) /obj/machinery/vending/wirecutter_act(mob/user, obj/item/I) . = TRUE @@ -359,12 +355,10 @@ if(!user.drop_item()) to_chat(user, "[I] is stuck to your hand, you can't seem to put it down!") return - inserted_item = I I.forceMove(src) - to_chat(user, "You insert [I] into [src].") - SSnanoui.update_uis(src) + SStgui.update_uis(src) /obj/machinery/vending/proc/eject_item(mob/user) if(!item_slot || !inserted_item) @@ -377,23 +371,19 @@ var/turf/T = get_turf(src) inserted_item.forceMove(T) inserted_item = null - SSnanoui.update_uis(src) + SStgui.update_uis(src) /obj/machinery/vending/emag_act(user as mob) emagged = TRUE to_chat(user, "You short out the product lock on [src]") -/** - * Receive payment with cashmoney. - * - * usr is the mob who gets the change. - */ + /obj/machinery/vending/proc/pay_with_cash(obj/item/stack/spacecash/cashmoney, mob/user) if(currently_vending.price > cashmoney.amount) // This is not a status display message, since it's something the character // themselves is meant to see BEFORE putting the money in to_chat(usr, "[bicon(cashmoney)] That is not enough money.") - return 0 + return FALSE // Bills (banknotes) cannot really have worth different than face value, // so we have to eat the bill and spit out change in a bundle @@ -405,50 +395,36 @@ // Vending machines have no idea who paid with cash GLOB.vendor_account.credit(currently_vending.price, "Sale of [currently_vending.name]", name, "(cash)") - return 1 + return TRUE -/** - * Scan a card and attempt to transfer payment from associated account. - * - * Takes payment for whatever is the currently_vending item. Returns 1 if - * successful, 0 if failed - */ -/obj/machinery/vending/proc/pay_with_card(var/obj/item/card/id/I) - visible_message("[usr] swipes a card through [src].") - return pay_with_account(get_card_account(I)) -/obj/machinery/vending/proc/pay_with_account(var/datum/money_account/customer_account) +/obj/machinery/vending/proc/pay_with_card(obj/item/card/id/I, mob/M) + visible_message("[M] swipes a card through [src].") + return pay_with_account(get_card_account(I), M) + +/obj/machinery/vending/proc/pay_with_account(datum/money_account/customer_account, mob/M) if(!customer_account) - src.status_message = "Error: Unable to access account. Please contact technical support if problem persists." - src.status_error = 1 - return 0 - + to_chat(M, "Error: Unable to access account. Please contact technical support if problem persists.") + return FALSE if(customer_account.suspended) - src.status_message = "Unable to access account: account suspended." - src.status_error = 1 - return 0 - - // Have the customer punch in the PIN before checking if there's enough money. Prevents people from figuring out acct is - // empty at high security levels - if(customer_account.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2) + to_chat(M, "Unable to access account: account suspended.") + return FALSE + // Have the customer punch in the PIN before checking if there's enough money. + // Prevents people from figuring out acct is empty at high security levels + if(customer_account.security_level != 0) + // If card requires pin authentication (ie seclevel 1 or 2) var/attempt_pin = input("Enter pin code", "Vendor transaction") as num - if(!attempt_account_access(customer_account.account_number, attempt_pin, 2)) - src.status_message = "Unable to access account: incorrect credentials." - src.status_error = 1 - return 0 - + to_chat(M, "Unable to access account: incorrect credentials.") + return FALSE if(currently_vending.price > customer_account.money) - src.status_message = "Insufficient funds in account." - src.status_error = 1 - return 0 - else - // Okay to move the money at this point - customer_account.charge(currently_vending.price, GLOB.vendor_account, - "Purchase of [currently_vending.name]", name, GLOB.vendor_account.owner_name, - "Sale of [currently_vending.name]", customer_account.owner_name) - - return TRUE + to_chat(M, "Your bank account has insufficient money to purchase this.") + return FALSE + // Okay to move the money at this point + customer_account.charge(currently_vending.price, GLOB.vendor_account, + "Purchase of [currently_vending.name]", name, GLOB.vendor_account.owner_name, + "Sale of [currently_vending.name]", customer_account.owner_name) + return TRUE /obj/machinery/vending/attack_ai(mob/user) @@ -465,174 +441,238 @@ if(src.shock(user, 100)) return - ui_interact(user) + tgui_interact(user) wires.Interact(user) -/** - * Display the NanoUI window for the vending machine. - * - * See NanoUI documentation for details. - */ -/obj/machinery/vending/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/vending/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "vending_machine.tmpl", src.name, 440, 600) + var/estimated_height = 100 + (length(product_records) * 34) + if(length(prices) > 0) + estimated_height += 100 // to account for the "current user" interface + ui = new(user, src, ui_key, "Vending", name, 470, estimated_height, master_ui, state) ui.open() -/obj/machinery/vending/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) +/obj/machinery/vending/tgui_data(mob/user) var/list/data = list() - if(currently_vending) - data["mode"] = 1 - data["product"] = sanitize(currently_vending.name) - data["price"] = currently_vending.price - data["message_err"] = 0 - data["message"] = src.status_message - data["message_err"] = src.status_error - else - data["mode"] = 0 - var/list/listed_products = list() - - var/list/display_records = product_records + coin_records - if(extended_inventory) - display_records = product_records + coin_records + hidden_records - - for(var/key = 1 to display_records.len) - var/datum/data/vending_product/I = display_records[key] - - if(coin_records.Find(I) && !coin) - continue - - if(hidden_records.Find(I) && !extended_inventory) - continue - - listed_products.Add(list(list( - "key" = key, - "name" = sanitize(I.name), - "price" = I.price, - "amount" = I.amount))) - - data["products"] = listed_products - - if(coin) - data["coin"] = coin.name - - if(item_slot) - data["item_slot"] = 1 - if(inserted_item) - data["inserted_item"] = inserted_item - else - data["inserted_item"] = null - else - data["item_slot"] = 0 - - if(panel_open) - data["panel"] = 1 - data["speaker"] = shut_up ? 0 : 1 - else - data["panel"] = 0 + var/mob/living/carbon/human/H + var/obj/item/card/id/C + data["guestNotice"] = "No valid ID card detected. Wear your ID, or present cash."; + data["userMoney"] = 0 + data["user"] = null + if(ishuman(user)) + H = user + C = H.get_idcard(TRUE) + var/obj/item/stack/spacecash/S = H.get_active_hand() + if(istype(S)) + data["userMoney"] = S.amount + data["guestNotice"] = "Accepting Cash. You have: [S.amount] credits." + else if(istype(C)) + var/datum/money_account/A = get_card_account(C) + if(istype(A)) + data["user"] = list() + data["user"]["name"] = A.owner_name + data["userMoney"] = A.money + data["user"]["job"] = (istype(C) && C.rank) ? C.rank : "No Job" + else + data["guestNotice"] = "Unlinked ID detected. Present cash to pay."; + data["stock"] = list() + for (var/datum/data/vending_product/R in product_records + coin_records + hidden_records) + data["stock"][R.name] = R.amount + data["extended_inventory"] = extended_inventory + data["vend_ready"] = vend_ready + data["coin_name"] = coin ? coin.name : FALSE + data["panel_open"] = panel_open ? TRUE : FALSE + data["speaker"] = shut_up ? FALSE : TRUE + data["item_slot"] = item_slot // boolean + data["inserted_item_name"] = inserted_item ? inserted_item.name : FALSE return data -/obj/machinery/vending/Topic(href, href_list) - if(..()) - return 1 - if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) - if(!coin) - to_chat(usr, "There is no coin in this machine.") - return +/obj/machinery/vending/tgui_static_data(mob/user) + var/list/data = list() + data["chargesMoney"] = length(prices) > 0 ? TRUE : FALSE + data["product_records"] = list() + var/i = 1 + for (var/datum/data/vending_product/R in product_records) + var/list/data_pr = list( + path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), + name = R.name, + price = (R.product_path in prices) ? prices[R.product_path] : 0, + max_amount = R.max_amount, + req_coin = FALSE, + is_hidden = FALSE, + inum = i + ) + data["product_records"] += list(data_pr) + i++ + data["coin_records"] = list() + for (var/datum/data/vending_product/R in coin_records) + var/list/data_cr = list( + path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), + name = R.name, + price = (R.product_path in prices) ? prices[R.product_path] : 0, + max_amount = R.max_amount, + req_coin = TRUE, + is_hidden = FALSE, + inum = i, + premium = TRUE + ) + data["coin_records"] += list(data_cr) + i++ + data["hidden_records"] = list() + for (var/datum/data/vending_product/R in hidden_records) + var/list/data_hr = list( + path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), + name = R.name, + price = (R.product_path in prices) ? prices[R.product_path] : 0, + max_amount = R.max_amount, + req_coin = FALSE, + is_hidden = TRUE, + inum = i, + premium = TRUE + ) + data["hidden_records"] += list(data_hr) + i++ + data["imagelist"] = imagelist + return data - usr.put_in_hands(coin) - coin = null - to_chat(usr, "You remove [coin] from [src].") +/obj/machinery/vending/tgui_act(action, params) + . = ..() + if(.) + return + if(issilicon(usr) && !isrobot(usr)) + to_chat(usr, "The vending machine refuses to interface with you, as you are not in its target demographic!") + return + switch(action) + if("toggle_voice") + if(panel_open) + shut_up = !shut_up + . = TRUE + if("eject_item") + eject_item(usr) + . = TRUE + if("remove_coin") + if(!coin) + to_chat(usr, "There is no coin in this machine.") + return + if(istype(usr, /mob/living/silicon)) + to_chat(usr, "You lack hands.") + return + to_chat(usr, "You remove [coin] from [src].") + usr.put_in_hands(coin) + coin = null + . = TRUE + if("vend") + if(!vend_ready) + to_chat(usr, "The vending machine is busy!") + return + if(panel_open) + to_chat(usr, "The vending machine cannot dispense products while its service panel is open!") + return + var/key = text2num(params["inum"]) + var/list/display_records = product_records + coin_records + if(extended_inventory) + display_records = product_records + coin_records + hidden_records + if(key < 1 || key > length(display_records)) + to_chat(usr, "ERROR: invalid inum passed to vendor. Report this bug.") + return + var/datum/data/vending_product/R = display_records[key] + if(!istype(R)) + to_chat(usr, "ERROR: unknown vending_product record. Report this bug.") + return + var/list/record_to_check = product_records + coin_records + if(extended_inventory) + record_to_check = product_records + coin_records + hidden_records + if(!R || !istype(R) || !R.product_path) + to_chat(usr, "ERROR: unknown product record. Report this bug.") + return + if(R in hidden_records) + if(!extended_inventory) + // Exploit prevention, stop the user purchasing hidden stuff if they haven't hacked the machine. + to_chat(usr, "ERROR: machine does not allow extended_inventory in current state. Report this bug.") + return + else if (!(R in record_to_check)) + // Exploit prevention, stop the user + message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!") + return + if (R.amount <= 0) + to_chat(usr, "Sold out of [R.name].") + flick(icon_deny, src) + return - if(href_list["remove_item"]) - eject_item(usr) + vend_ready = FALSE // From this point onwards, vendor is locked to performing this transaction only, until it is resolved. - if(href_list["pay"]) - if(currently_vending && GLOB.vendor_account && !GLOB.vendor_account.suspended) - var/paid = 0 - var/handled = 0 - var/datum/money_account/A = usr.get_worn_id_account() - if(A) - paid = pay_with_account(A) - handled = 1 - else if(istype(usr.get_active_hand(), /obj/item/card)) - paid = pay_with_card(usr.get_active_hand()) - handled = 1 - else if(usr.can_admin_interact()) - paid = 1 - handled = 1 + if(!ishuman(usr) || R.price <= 0) + // Either the purchaser is not human, or the item is free. + // Skip all payment logic. + vend(R, usr) + add_fingerprint(usr) + vend_ready = TRUE + . = TRUE + return + + // --- THE REST OF THIS PROC IS JUST PAYMENT LOGIC --- + + var/mob/living/carbon/human/H = usr + var/obj/item/card/id/C = H.get_idcard(TRUE) + + if(!GLOB.vendor_account || GLOB.vendor_account.suspended) + to_chat(usr, "Vendor account offline. Unable to process transaction.") + flick(icon_deny, src) + vend_ready = TRUE + return + + currently_vending = R + var/paid = FALSE + + if(istype(usr.get_active_hand(), /obj/item/stack/spacecash)) + var/obj/item/stack/spacecash/S = usr.get_active_hand() + paid = pay_with_cash(S) + else if(istype(C, /obj/item/card)) + // Because this uses H.get_idcard(TRUE), it will attempt to use: + // active hand, inactive hand, pda.id, and then wear_id ID in that order + // this is important because it lets people buy stuff with someone else's ID by holding it while using the vendor + paid = pay_with_card(C, usr) + else if(usr.can_advanced_admin_interact()) + to_chat(usr, "Vending object due to admin interaction.") + paid = TRUE + else + to_chat(usr, "Payment failure: you have no ID or other method of payment.") + vend_ready = TRUE + flick(icon_deny, src) + . = TRUE // we set this because they shouldn't even be able to get this far, and we want the UI to update. + return if(paid) vend(currently_vending, usr) - return - else if(handled) - SSnanoui.update_uis(src) - return // don't smack that machine with your 2 credits - - if((href_list["vend"]) && vend_ready && !currently_vending) - - if(issilicon(usr) && !isrobot(usr)) - to_chat(usr, "The vending machine refuses to interface with you, as you are not in its target demographic!") - return - - if(!allowed(usr) && !usr.can_admin_interact() && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - to_chat(usr, "Access denied.") //Unless emagged of course - flick(icon_deny,src) - return - - var/key = text2num(href_list["vend"]) - var/list/display_records = product_records + coin_records - if(extended_inventory) - display_records = product_records + coin_records + hidden_records - var/datum/data/vending_product/R = display_records[key] - - // This should not happen unless the request from NanoUI was bad - if(coin_records.Find(R) && !coin) - return - - if(hidden_records.Find(R) && !extended_inventory) - return - - if(R.price <= 0) - vend(R, usr) - else - currently_vending = R - if(!GLOB.vendor_account || GLOB.vendor_account.suspended) - status_message = "This machine is currently unable to process payments due to problems with the associated account." - status_error = 1 + . = TRUE else - status_message = "Please swipe a card or insert cash to pay for the item." - status_error = 0 + to_chat(usr, "Payment failure: unable to process payment.") + vend_ready = TRUE + if(.) + add_fingerprint(usr) - else if(href_list["cancelpurchase"]) - currently_vending = null - else if(href_list["togglevoice"] && panel_open) - shut_up = !src.shut_up - add_fingerprint(usr) - SSnanoui.update_uis(src) /obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user) - if(!allowed(usr) && !usr.can_admin_interact() && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - to_chat(usr, "Access denied.")//Unless emagged of course - flick(icon_deny,src) + if(!allowed(user) && !user.can_admin_interact() && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH + to_chat(user, "Access denied.")//Unless emagged of course + flick(icon_deny, src) + vend_ready = TRUE return if(!R.amount) to_chat(user, "The vending machine has ran out of that product.") + vend_ready = TRUE return - vend_ready = 0 //One thing at a time!! - status_message = "Vending..." - status_error = 0 - SSnanoui.update_uis(src) + vend_ready = FALSE //One thing at a time!! if(coin_records.Find(R)) if(!coin) to_chat(user, "You need to insert a coin to get this item.") + vend_ready = TRUE return if(coin.string_attached) if(prob(50)) @@ -652,15 +692,13 @@ use_power(vend_power_usage) //actuators and stuff if(icon_vend) //Show the vending animation if needed flick(icon_vend, src) + playsound(get_turf(src), 'sound/machines/machine_vend.ogg', 50, TRUE) addtimer(CALLBACK(src, .proc/delayed_vend, R, user), vend_delay) /obj/machinery/vending/proc/delayed_vend(datum/data/vending_product/R, mob/user) do_vend(R, user) - status_message = "" - status_error = 0 - vend_ready = 1 + vend_ready = TRUE currently_vending = null - SSnanoui.update_uis(src) //override this proc to add handling for what to do with the vended product when you have a inserted item and remember to include a parent call for this generic handling /obj/machinery/vending/proc/do_vend(datum/data/vending_product/R, mob/user) @@ -796,17 +834,6 @@ */ -/* -/obj/machinery/vending/atmospherics //Commenting this out until someone ponies up some actual working, broken, and unpowered sprites - Quarxink - name = "\improper Tank Vendor" - desc = "A vendor with a wide variety of masks and gas tanks." - icon = 'icons/obj/objects.dmi' - icon_state = "dispenser" - product_paths = "/obj/item/tank/oxygen;/obj/item/tank/plasma;/obj/item/tank/emergency_oxygen;/obj/item/tank/emergency_oxygen/engi;/obj/item/clothing/mask/breath" - product_amounts = "10;10;10;5;25" - vend_delay = 0 -*/ - /obj/machinery/vending/assist products = list( /obj/item/assembly/prox_sensor = 5,/obj/item/assembly/igniter = 3,/obj/item/assembly/signaler = 4, /obj/item/wirecutters = 1, /obj/item/cartridge/signal = 4) @@ -1553,7 +1580,6 @@ desc = "Tools for tools." icon_state = "tool" icon_deny = "tool-deny" - //req_access_txt = "12" //Maintenance access products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/crowbar = 5,/obj/item/weldingtool = 3,/obj/item/wirecutters = 5, /obj/item/wrench = 5,/obj/item/analyzer = 5,/obj/item/t_scanner = 5,/obj/item/screwdriver = 5) contraband = list(/obj/item/weldingtool/hugetank = 2,/obj/item/clothing/gloves/color/fyellow = 2) diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 896ce886887..34e8648c59e 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -158,36 +158,36 @@ /obj/machinery/computer/mech_bay_power_console/attack_hand(mob/user as mob) if(..()) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/mech_bay_power_console/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "mech_bay_console.tmpl", "Mech Bay Control Console", 500, 325) - // open the new ui window + ui = new(user, src, ui_key, "MechBayConsole", name, 400, 150, master_ui, state) ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) -/obj/machinery/computer/mech_bay_power_console/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/machinery/computer/mech_bay_power_console/tgui_act(action, params) + if(..()) + return + switch(action) + if("reconnect") + reconnect() + . = TRUE + update_icon() + +/obj/machinery/computer/mech_bay_power_console/tgui_data(mob/user) + var/data = list() if(!recharge_port) reconnect() if(recharge_port && !QDELETED(recharge_port)) data["recharge_port"] = list("mech" = null) if(recharge_port.recharging_mecha && !QDELETED(recharge_port.recharging_mecha)) - data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mecha.obj_integrity, "maxhealth" = initial(recharge_port.recharging_mecha.max_integrity), "cell" = null) + data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mecha.obj_integrity, "maxhealth" = recharge_port.recharging_mecha.max_integrity, "cell" = null, "name" = recharge_port.recharging_mecha.name) if(recharge_port.recharging_mecha.cell && !QDELETED(recharge_port.recharging_mecha.cell)) - data["has_mech"] = 1 - data["mecha_name"] = recharge_port.recharging_mecha || "None" - data["mecha_charge"] = isnull(recharge_port.recharging_mecha) ? 0 : recharge_port.recharging_mecha.cell.charge - data["mecha_maxcharge"] = isnull(recharge_port.recharging_mecha) ? 0 : recharge_port.recharging_mecha.cell.maxcharge - data["mecha_charge_percentage"] = isnull(recharge_port.recharging_mecha) ? 0 : round(recharge_port.recharging_mecha.cell.percent()) - else - data["has_mech"] = 0 - + data["recharge_port"]["mech"]["cell"] = list( + "charge" = recharge_port.recharging_mecha.cell.charge, + "maxcharge" = recharge_port.recharging_mecha.cell.maxcharge + ) return data /obj/machinery/computer/mech_bay_power_console/Initialize() diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 5aabfdea9a0..cdcc2361937 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -126,7 +126,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list( wires.Interact(user) tgui_interact(user) -/obj/item/radio/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_physical_state) +/obj/item/radio/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "Radio", name, 360, 150 + (length(channels) * 20), master_ui, state) diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index acba0087caf..fdef93dc7a3 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -86,64 +86,64 @@ O.hear_message(M, msg) /obj/item/transfer_valve/attack_self(mob/user) - ui_interact(user) + tgui_interact(user) -/obj/item/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/transfer_valve/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_inventory_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "transfer_valve.tmpl", "Tank Transfer Valve", 460, 280) - // open the new ui window + ui = new(user, src, ui_key, "TransferValve", name, 460, 320, master_ui, state) ui.open() - // auto update every Master Controller tick - //ui.set_auto_update(1) - -/obj/item/transfer_valve/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - - data["attachmentOne"] = tank_one ? tank_one.name : null - data["attachmentTwo"] = tank_two ? tank_two.name : null - data["valveAttachment"] = attached_device ? attached_device.name : null - data["valveOpen"] = valve_open ? 1 : 0 +/obj/item/transfer_valve/tgui_data(mob/user) + var/list/data = list() + data["tank_one"] = tank_one ? tank_one.name : null + data["tank_two"] = tank_two ? tank_two.name : null + data["attached_device"] = attached_device ? attached_device.name : null + data["valve"] = valve_open return data -/obj/item/transfer_valve/Topic(href, href_list) - ..() - if(usr.incapacitated()) - return 0 - if(loc != usr) - return 0 - if(tank_one && href_list["tankone"]) - split_gases() - valve_open = 0 - tank_one.forceMove(get_turf(src)) - tank_one = null + + +/obj/item/transfer_valve/tgui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("tankone") + if(tank_one) + split_gases() + valve_open = FALSE + tank_one.forceMove(get_turf(src)) + tank_one = null + update_icon() + if((!tank_two || tank_two.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL)) + w_class = WEIGHT_CLASS_NORMAL + if("tanktwo") + if(tank_two) + split_gases() + valve_open = FALSE + tank_two.forceMove(get_turf(src)) + tank_two = null + update_icon() + if((!tank_one || tank_one.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL)) + w_class = WEIGHT_CLASS_NORMAL + if("toggle") + toggle_valve() + if("device") + if(attached_device) + attached_device.attack_self(usr) + if("remove_device") + if(attached_device) + attached_device.forceMove(get_turf(src)) + attached_device.holder = null + attached_device = null + update_icon() + else + . = FALSE + if(.) update_icon() - if((!tank_two || tank_two.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL)) - w_class = WEIGHT_CLASS_NORMAL - else if(tank_two && href_list["tanktwo"]) - split_gases() - valve_open = 0 - tank_two.forceMove(get_turf(src)) - tank_two = null - update_icon() - if((!tank_one || tank_one.w_class < WEIGHT_CLASS_BULKY) && (w_class > WEIGHT_CLASS_NORMAL)) - w_class = WEIGHT_CLASS_NORMAL - else if(href_list["open"]) - toggle_valve() - else if(attached_device) - if(href_list["rem_device"]) - attached_device.forceMove(get_turf(src)) - attached_device.holder = null - attached_device = null - update_icon() - if(href_list["device"]) - attached_device.attack_self(usr) - add_fingerprint(usr) - return 1 // Returning 1 sends an update to attached UIs + add_fingerprint(usr) + /obj/item/transfer_valve/proc/process_activation(obj/item/D) if(toggle) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 3864f573597..ac2cce4de01 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -624,11 +624,11 @@ Traitors and the like can also be revived with the previous role mostly intact. var/beepsound = input(usr, "What sound should the announcement make?", "Announcement Sound", "") as anything in MsgSound GLOB.command_announcement.Announce(input, customname, MsgSound[beepsound], , , type) - print_command_report(input, "[command_name()] Update") + print_command_report(input, customname) if("No") //same thing as the blob stuff - it's not public, so it's classified, dammit GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.") - print_command_report(input, "Classified [command_name()] Update") + print_command_report(input, "Classified: [customname]") else return diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index bac8d64d9f2..5d3d6494e48 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -16,7 +16,9 @@ var/death = TRUE //Kill the mob var/roundstart = TRUE //fires on initialize var/instant = FALSE //fires on New - var/flavour_text = "The mapper forgot to set this!" + var/flavour_text = "" //flavour/fluff about the role, optional. + var/description = "A description for this has not been set. This is either an oversight or an admin-spawned spawner not in normal use." //intended as OOC info about the role + var/important_info = "" //important info such as rules that apply to you, etc. Optional. var/faction = null var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses. var/random = FALSE //Don't set a name or gender, just go random @@ -336,7 +338,7 @@ name = "sleeper" icon = 'icons/obj/cryogenic2.dmi' icon_state = "sleeper" - flavour_text = "You are a space doctor!" + flavour_text = "You are a space doctor!" assignedrole = "Space Doctor" /obj/effect/mob_spawn/human/doctor/alive/equip(mob/living/carbon/human/H) @@ -470,11 +472,14 @@ name = "bartender sleeper" icon = 'icons/obj/cryogenic2.dmi' icon_state = "sleeper" - flavour_text = "You are a space bartender! Time to mix drinks and change lives." + description = "Stuck on Lavaland, you could try getting back to civilisation...or serve drinks to those that wander by." + flavour_text = "You are a space bartender! Time to mix drinks and change lives. Wait, where did your bar just get transported to?" assignedrole = "Space Bartender" /obj/effect/mob_spawn/human/beach/alive/lifeguard - flavour_text = "You're a spunky lifeguard! It's up to you to make sure nobody drowns or gets eaten by sharks and stuff." + flavour_text = "You're a spunky lifeguard! It's up to you to make sure nobody drowns or gets eaten by sharks and stuff. Then suddenly your entire beach was transported to this strange hell.\ + You aren't trained for this, but you'll still keep your guests alive!" + description = "Try to survive on lavaland with the pitiful equipment of a lifeguard. Or hide in your biodome." mob_gender = "female" name = "lifeguard sleeper" id_job = "Lifeguard" @@ -502,7 +507,8 @@ name = "beach bum sleeper" icon = 'icons/obj/cryogenic2.dmi' icon_state = "sleeper" - flavour_text = "You are a beach bum!" + flavour_text = "You are a beach bum! You think something just happened to the beach but you don't really pay too much attention." + description = "Try to survive on lavaland or just enjoy the beach, waiting for visitors." assignedrole = "Beach Bum" /datum/outfit/beachbum @@ -523,6 +529,7 @@ roundstart = FALSE icon = 'icons/effects/blood.dmi' icon_state = "remains" + description = "Be a spooky scary skeleton." //not mapped in anywhere so admin spawner, who knows what they'll use this for. flavour_text = "By unknown powers, your skeletal remains have been reanimated! Walk this mortal plain and terrorize all living adventurers who dare cross your path." assignedrole = "Skeleton" diff --git a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm index 9a5bf275abc..0996f214691 100644 --- a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm +++ b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm @@ -64,9 +64,11 @@ var/has_owner = FALSE var/can_transfer = TRUE //if golems can switch bodies to this new shell var/mob/living/owner = null //golem's owner if it has one - flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \ + important_info = "You are not an antag. Do not mess with the station or create AIs." + description = "As a Free Golem on lavaland, you are unable to use most weapons, but you can mine, research and make more of your kind. Earn enough mining points and you can even move your shuttle out of there." + flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \ travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \ - golems, so that no golem may ever be forced to serve again." + golems, so that no golem may ever be forced to serve again." /obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null) if(species) //spawners list uses object name to register so this goes before ..() @@ -77,8 +79,10 @@ if(!mapload && A) notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in [A.name].", source = src) if(has_owner && creator) - flavour_text = "You are a Golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \ - Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost." + important_info = "Serve your creator, even if they are an antag." + flavour_text = "You are a golem created to serve your creator." + description = "You are a Golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \ + Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost." owner = creator /obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn, name) diff --git a/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation.dm b/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation.dm index bb1aae5f8a8..62f4226394d 100644 --- a/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation.dm +++ b/code/modules/awaymissions/mission_code/ghost_role_spawners/oldstation.dm @@ -10,10 +10,11 @@ death = FALSE random = TRUE mob_species = /datum/species/human - flavour_text = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ + description = "Work as a team with your fellow survivors aboard a ruined, ancient space station." + important_info = "" + flavour_text = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ - Work as a team with your fellow survivors and do not abandon them." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod." uniform = /obj/item/clothing/under/retro/security shoes = /obj/item/clothing/shoes/jackboots id = /obj/item/card/id/away/old/sec @@ -35,10 +36,11 @@ death = FALSE random = TRUE mob_species = /datum/species/human - flavour_text = "You are a medical working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ + description = "Work as a team with your fellow survivors aboard a ruined, ancient space station." + important_info = "" + flavour_text = "You are a medical doctor working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ - Work as a team with your fellow survivors and do not abandon them." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod." uniform = /obj/item/clothing/under/retro/medical shoes = /obj/item/clothing/shoes/black id = /obj/item/card/id/away/old/med @@ -60,10 +62,11 @@ death = FALSE random = TRUE mob_species = /datum/species/human - flavour_text = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ + description = "Work as a team with your fellow survivors aboard a ruined, ancient space station." + important_info = "" + flavour_text = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ - Work as a team with your fellow survivors and do not abandon them." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod." uniform = /obj/item/clothing/under/retro/engineering shoes = /obj/item/clothing/shoes/workboots id = /obj/item/card/id/away/old/eng @@ -85,10 +88,11 @@ death = FALSE random = TRUE mob_species = /datum/species/human - flavour_text = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ + description = "Work as a team with your fellow survivors aboard a ruined, ancient space station." + important_info = "" + flavour_text = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ - Work as a team with your fellow survivors and do not abandon them." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod." uniform = /obj/item/clothing/under/retro/science shoes = /obj/item/clothing/shoes/laceup id = /obj/item/card/id/away/old/sci diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm index 7007a99f0ec..b28dc6a467d 100644 --- a/code/modules/events/sentience.dm +++ b/code/modules/events/sentience.dm @@ -39,7 +39,7 @@ SA.health = SA.maxHealth SA.del_on_death = FALSE greet_sentient(SA) - print_command_report(sentience_report, "[command_name()] Update") + print_command_report(sentience_report, "[command_name()] Update", FALSE) processing = TRUE // Let it naturally end, if it runs successfully /datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M) diff --git a/code/modules/mining/laborcamp/laborshuttle.dm b/code/modules/mining/laborcamp/laborshuttle.dm index 8e585eb15b0..88b0a6601dc 100644 --- a/code/modules/mining/laborcamp/laborshuttle.dm +++ b/code/modules/mining/laborcamp/laborshuttle.dm @@ -13,15 +13,3 @@ possible_destinations = "laborcamp_away" circuit = /obj/item/circuitboard/labor_shuttle/one_way req_access = list( ) - -/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list) - if(href_list["move"]) - var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp") - if(!M) - to_chat(usr, "Cannot locate shuttle!") - return 0 - var/obj/docking_port/stationary/S = M.get_docked() - if(S && S.name == "laborcamp_away") - to_chat(usr, "Shuttle is already at the outpost!") - return 0 - ..() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 31ff0098335..ef5268fa104 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -780,4 +780,4 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set category = "Ghost" var/datum/spawners_menu/menu = new /datum/spawners_menu(src) - menu.ui_interact(src) + menu.tgui_interact(src) diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index a2357fd9ebe..8e0ff5aca2c 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -63,7 +63,6 @@ var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/chatclient()) hard_drive.store_file(new/datum/computer_file/program/card_mod()) - hard_drive.store_file(new/datum/computer_file/program/comm()) // ===== CIVILIAN CONSOLE ===== /obj/machinery/modular_computer/console/preset/civilian diff --git a/code/modules/modular_computers/file_system/programs/command/comms.dm b/code/modules/modular_computers/file_system/programs/command/comms.dm deleted file mode 100644 index c23f0c9e3c7..00000000000 --- a/code/modules/modular_computers/file_system/programs/command/comms.dm +++ /dev/null @@ -1,385 +0,0 @@ -/datum/computer_file/program/comm - filename = "comm" - filedesc = "Command and communications" - program_icon_state = "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/authenticated = COMM_AUTHENTICATION_NONE - var/list/messagetitle = list() - var/list/messagetext = list() - var/currmsg = 0 - var/aicurrmsg = 0 - var/menu_state = COMM_SCREEN_MAIN - var/ai_menu_state = COMM_SCREEN_MAIN - var/message_cooldown = 0 - var/centcomm_message_cooldown = 0 - var/tmp_alertlevel = 0 - - var/stat_msg1 - var/stat_msg2 - var/display_type="blank" - - var/datum/announcement/priority/crew_announcement = new - -/datum/computer_file/program/comm/New() - GLOB.shuttle_caller_list += src - ..() - crew_announcement.newscast = 0 - -/datum/computer_file/program/comm/Destroy() - GLOB.shuttle_caller_list -= src - SSshuttle.autoEvac() - return ..() - -/datum/computer_file/program/comm/proc/is_authenticated(mob/user, loud = 1) - if(authenticated == COMM_AUTHENTICATION_MAX) - return COMM_AUTHENTICATION_MAX - else if(user.can_admin_interact()) - return COMM_AUTHENTICATION_MAX - else if(authenticated) - return COMM_AUTHENTICATION_MIN - else - if(loud) - to_chat(user, "Access denied.") - return COMM_AUTHENTICATION_NONE - -/datum/computer_file/program/comm/proc/change_security_level(mob/user, new_level) - tmp_alertlevel = new_level - var/old_level = GLOB.security_level - if(!tmp_alertlevel) - tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel < SEC_LEVEL_GREEN) - tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel > SEC_LEVEL_BLUE) - tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this - set_security_level(tmp_alertlevel) - if(GLOB.security_level != old_level) - log_game("[key_name(user)] has changed the security level to [get_security_level()].") - message_admins("[key_name_admin(user)] has changed the security level to [get_security_level()].") - switch(GLOB.security_level) - if(SEC_LEVEL_GREEN) - feedback_inc("alert_comms_green", 1) - if(SEC_LEVEL_BLUE) - feedback_inc("alert_comms_blue", 1) - tmp_alertlevel = 0 - -/datum/computer_file/program/comm/proc/setCurrentMessage(mob/user, value) - if(isAI(user) || isrobot(user)) - aicurrmsg = value - else - currmsg = value - -/datum/computer_file/program/comm/proc/getCurrentMessage(mob/user) - if(isAI(user) || isrobot(user)) - return aicurrmsg - else - return currmsg - -/datum/computer_file/program/comm/proc/setMenuState(mob/user, value) - if(isAI(user) || isrobot(user)) - ai_menu_state=value - else - menu_state=value - -/datum/computer_file/program/comm/proc/getMenuState(mob/user) - if(isAI(user) || isrobot(user)) - return ai_menu_state - else - return menu_state - -/datum/computer_file/program/comm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui) - if(!ui) - var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) - assets.send(user) - ui = new(user, src, ui_key, "comm_program.tmpl", "Command and communications program", 575, 500) - ui.set_layout_key("program") - ui.open() - -/datum/computer_file/program/comm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/list/data = get_header_data() - data["is_ai"] = isAI(user) || isrobot(user) - data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state - data["emagged"] = computer ? computer.emagged : null - data["authenticated"] = is_authenticated(user, 0) - data["screen"] = getMenuState(usr) - - data["stat_display"] = list( - "type" = display_type, - "line_1" = (stat_msg1 ? stat_msg1 : "-----"), - "line_2" = (stat_msg2 ? stat_msg2 : "-----"), - - "presets" = list( - list("name" = "blank", "label" = "Clear", "desc" = "Blank slate"), - list("name" = "shuttle", "label" = "Shuttle ETA", "desc" = "Display how much time is left."), - list("name" = "message", "label" = "Message", "desc" = "A custom message.") - ), - - "alerts"=list( - list("alert" = "default", "label" = "Nanotrasen", "desc" = "Oh god."), - list("alert" = "redalert", "label" = "Red Alert", "desc" = "Nothing to do with communists."), - list("alert" = "lockdown", "label" = "Lockdown", "desc" = "Let everyone know they're on lockdown."), - list("alert" = "biohazard", "label" = "Biohazard", "desc" = "Great for virus outbreaks and parties."), - ) - ) - - data["security_level"] = GLOB.security_level - data["str_security_level"] = capitalize(get_security_level()) - data["levels"] = list( - list("id" = SEC_LEVEL_GREEN, "name" = "Green"), - list("id" = SEC_LEVEL_BLUE, "name" = "Blue"), - ) - - var/list/msg_data = list() - for(var/i = 1; i <= messagetext.len; i++) - msg_data.Add(list(list("title" = messagetitle[i], "body" = messagetext[i], "id" = i))) - - data["messages"] = msg_data - if((data["is_ai"] && aicurrmsg) || (!data["is_ai"] && currmsg)) - data["current_message"] = data["is_ai"] ? messagetext[aicurrmsg] : messagetext[currmsg] - data["current_message_title"] = data["is_ai"] ? messagetitle[aicurrmsg] : messagetitle[currmsg] - - data["lastCallLoc"] = SSshuttle.emergencyLastCallLoc ? format_text(SSshuttle.emergencyLastCallLoc.name) : null - - var/shuttle[0] - switch(SSshuttle.emergency.mode) - if(SHUTTLE_IDLE, SHUTTLE_RECALL) - shuttle["callStatus"] = 2 //#define - else - shuttle["callStatus"] = 1 - if(SSshuttle.emergency.mode == SHUTTLE_CALL) - var/timeleft = SSshuttle.emergency.timeLeft() - shuttle["eta"] = "[timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" - - data["shuttle"] = shuttle - - return data - -/datum/computer_file/program/comm/Topic(href, href_list) - if(..()) - return 1 - - var/turf/T = get_turf(computer) - if(!is_secure_level(T.z)) - to_chat(usr, "Unable to establish a connection: You're too far away from the station!") - return 1 - - if(href_list["PRG_login"]) - if(!ishuman(usr)) - to_chat(usr, "Access denied.") - return - - var/list/access = usr.get_access() - if(ACCESS_HEADS in access) - authenticated = COMM_AUTHENTICATION_MIN - - if(ACCESS_CAPTAIN in access) - authenticated = COMM_AUTHENTICATION_MAX - var/mob/living/carbon/human/H = usr - var/obj/item/card/id = H.get_idcard(TRUE) - if(istype(id)) - crew_announcement.announcer = GetNameAndAssignmentFromId(id) - - SSnanoui.update_uis(src) - return 1 - - if(href_list["PRG_logout"]) - authenticated = COMM_AUTHENTICATION_NONE - crew_announcement.announcer = "" - setMenuState(usr, COMM_SCREEN_MAIN) - SSnanoui.update_uis(src) - return 1 - - if(is_authenticated(usr)) - switch(href_list["PRG_operation"]) - if("main") - setMenuState(usr, COMM_SCREEN_MAIN) - - if("changeseclevel") - setMenuState(usr,COMM_SCREEN_SECLEVEL) - - if("newalertlevel") - if(isAI(usr) || isrobot(usr)) - to_chat(usr, "Firewalls prevent you from changing the alert level.") - return 1 - else if(usr.can_admin_interact()) - change_security_level(usr, text2num(href_list["level"])) - return 1 - else if(!ishuman(usr)) - to_chat(usr, "Security measures prevent you from changing the alert level.") - return 1 - - var/mob/living/carbon/human/L = usr - var/obj/item/card = L.get_active_hand() - var/obj/item/card/id/I = (card && card.GetID()) || L.wear_id || L.wear_pda - if(istype(I, /obj/item/pda)) - var/obj/item/pda/pda = I - I = pda.id - if(I && istype(I)) - if(ACCESS_CAPTAIN in I.access) - change_security_level(usr, text2num(href_list["level"])) - else - to_chat(usr, "You are not authorized to do this.") - setMenuState(usr, COMM_SCREEN_MAIN) - else - to_chat(usr, "You need to swipe your ID.") - - if("announce") - if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX) - if(message_cooldown) - to_chat(usr, "Please allow at least one minute to pass between announcements.") - SSnanoui.update_uis(src) - return 1 - var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") - if(!input || message_cooldown || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) - return 1 - crew_announcement.Announce(input) - message_cooldown = 1 - spawn(600)//One minute cooldown - message_cooldown = 0 - - if("callshuttle") - var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") - if(!input || ..() || !is_authenticated(usr)) - SSnanoui.update_uis(src) - return 1 - - call_shuttle_proc(usr, input) - if(SSshuttle.emergency.timer) - post_status("shuttle") - setMenuState(usr, COMM_SCREEN_MAIN) - - if("cancelshuttle") - if(isAI(usr) || isrobot(usr)) - to_chat(usr, "Firewalls prevent you from recalling the shuttle.") - SSnanoui.update_uis(src) - return 1 - var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No") - if(response == "Yes") - cancel_call_proc(usr) - if(SSshuttle.emergency.timer) - post_status("shuttle") - setMenuState(usr, COMM_SCREEN_MAIN) - - if("messagelist") - currmsg = 0 - if(href_list["msgid"]) - setCurrentMessage(usr, text2num(href_list["msgid"])) - setMenuState(usr,COMM_SCREEN_MESSAGES) - - if("delmessage") - if(href_list["msgid"]) - currmsg = text2num(href_list["msgid"]) - var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No") - if(response == "Yes") - if(currmsg) - var/id = getCurrentMessage() - var/title = messagetitle[id] - var/text = messagetext[id] - messagetitle.Remove(title) - messagetext.Remove(text) - if(currmsg == id) - currmsg = 0 - if(aicurrmsg == id) - aicurrmsg = 0 - setMenuState(usr,COMM_SCREEN_MESSAGES) - - if("status") - setMenuState(usr,COMM_SCREEN_STAT) - - // Status display stuff - if("setstat") - display_type=href_list["statdisp"] - switch(display_type) - if("message") - post_status("message", stat_msg1, stat_msg2, usr) - if("alert") - post_status("alert", href_list["alert"], user = usr) - else - post_status(href_list["statdisp"], user = usr) - setMenuState(usr, COMM_SCREEN_STAT) - - if("setmsg1") - stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1) - setMenuState(usr, COMM_SCREEN_STAT) - - if("setmsg2") - stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2) - setMenuState(usr, COMM_SCREEN_STAT) - - if("nukerequest") - if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX) - if(centcomm_message_cooldown) - to_chat(usr, "Arrays recycling. Please stand by.") - SSnanoui.update_uis(src) - return 1 - var/input = stripped_input(usr, "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.","") - if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) - return 1 - Nuke_request(input, usr) - to_chat(usr, "Request sent.") - log_game("[key_name(usr)] has requested the nuclear codes from Centcomm") - GLOB.priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') - centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - - if("MessageCentcomm") - if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX) - if(centcomm_message_cooldown) - to_chat(usr, "Arrays recycling. Please stand by.") - SSnanoui.update_uis(src) - return 1 - var/input = stripped_input(usr, "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.", "To abort, send an empty message.", "") - if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) - return 1 - Centcomm_announce(input, usr) - to_chat(usr, "Message transmitted.") - log_game("[key_name(usr)] has made a Centcomm announcement: [input]") - centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - - // OMG SYNDICATE ...LETTERHEAD - if("MessageSyndicate") - if((is_authenticated(usr) == COMM_AUTHENTICATION_MAX) && (computer && computer.emagged)) - if(centcomm_message_cooldown) - to_chat(usr, "Arrays recycling. Please stand by.") - SSnanoui.update_uis(src) - return 1 - var/input = stripped_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.", "To abort, send an empty message.", "") - if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)) - SSnanoui.update_uis(src) - return 1 - Syndicate_announce(input, usr) - to_chat(usr, "Message transmitted.") - log_game("[key_name(usr)] has made a Syndicate announcement: [input]") - centcomm_message_cooldown = 1 - spawn(6000)//10 minute cooldown - centcomm_message_cooldown = 0 - setMenuState(usr,COMM_SCREEN_MAIN) - - if("RestartNanoMob") - if(SSmob_hunt) - if(SSmob_hunt.manual_reboot()) - var/loading_msg = pick("Respawning spawns", "Reticulating splines", "Flipping hat", - "Capturing all of them", "Fixing minor text issues", "Being the very best", - "Nerfing this", "Not communicating with playerbase", "Coding a ripoff in a 2D spaceman game") - to_chat(usr, "Restarting Nano-Mob Hunter GO! game server. [loading_msg]...") - else - to_chat(usr, "Nano-Mob Hunter GO! game server reboot failed due to recent restart. Please wait before re-attempting.") - else - to_chat(usr, "Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.") - - SSnanoui.update_uis(src) - return 1 diff --git a/code/modules/nano/modules/ert_manager.dm b/code/modules/nano/modules/ert_manager.dm deleted file mode 100644 index 98a3e19d052..00000000000 --- a/code/modules/nano/modules/ert_manager.dm +++ /dev/null @@ -1,105 +0,0 @@ -/datum/nano_module/ert_manager - name = "ERT Manager" - var/ert_type = "Code Red" - var/commander_slots = 1 - var/security_slots = 3 - var/medical_slots = 3 - var/engineering_slots = 3 - var/janitor_slots = 0 - var/paranormal_slots = 0 - var/cyborg_slots = 0 - var/autoclose = 0 - - -/datum/nano_module/ert_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.admin_state) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) - if(ui && autoclose) - ui.close() - return 0 - if(!ui) - ui = new(user, src, ui_key, "ert_config.tmpl", "ERT Panel", 600, 600, state = state) - ui.open() - ui.set_auto_update(1) - -/datum/nano_module/ert_manager/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["set_code"]) - ert_type = href_list["set_code"] - - if(href_list["set_com"]) - commander_slots = text2num(href_list["set_com"]) - - if(href_list["set_sec"]) - security_slots = text2num(href_list["set_sec"]) - - if(href_list["set_med"]) - medical_slots = text2num(href_list["set_med"]) - - if(href_list["set_eng"]) - engineering_slots = text2num(href_list["set_eng"]) - - if(href_list["set_jan"]) - janitor_slots = text2num(href_list["set_jan"]) - - if(href_list["set_par"]) - paranormal_slots = text2num(href_list["set_par"]) - - if(href_list["set_cyb"]) - cyborg_slots = text2num(href_list["set_cyb"]) - - if(href_list["dispatch_ert"]) - GLOB.ert_request_answered = TRUE - var/slots_list = list() - if(commander_slots > 0) - slots_list += "commander: [commander_slots]" - if(security_slots > 0) - slots_list += "security: [security_slots]" - if(medical_slots > 0) - slots_list += "medical: [medical_slots]" - if(engineering_slots > 0) - slots_list += "engineering: [engineering_slots]" - if(janitor_slots > 0) - slots_list += "janitor: [janitor_slots]" - if(paranormal_slots > 0) - slots_list += "paranormal: [paranormal_slots]" - if(cyborg_slots > 0) - slots_list += "cyborg: [cyborg_slots]" - var/slot_text = jointext(slots_list, ", ") - notify_ghosts("An ERT is being dispatched. Open positions: [slot_text]") - message_admins("[key_name_admin(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]", 1) - log_admin("[key_name(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]") - GLOB.event_announcement.Announce("Attention, [station_name()]. We are attempting to assemble an ERT. Standby.", "ERT Protocol Activated") - autoclose = 1 - ui_interact(usr) - trigger_armed_response_team(convert_ert_string(ert_type), commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) - return 0 - - ui_interact(usr) - - -/proc/convert_ert_string(thestring) - switch(thestring) - if("Code Amber") - return new /datum/response_team/amber - if("Code Red") - return new /datum/response_team/red - if("Code Gamma") - return new /datum/response_team/gamma - - -/datum/nano_module/ert_manager/ui_data() - var/data[0] - data["alert_level"] = get_security_level() - data["ert_type"] = ert_type - data["com"] = commander_slots - data["sec"] = security_slots - data["med"] = medical_slots - data["eng"] = engineering_slots - data["jan"] = janitor_slots - data["par"] = paranormal_slots - data["cyb"] = cyborg_slots - - return data - diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 09858073142..32416a8d5e7 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -12,24 +12,32 @@ GLOBAL_LIST_EMPTY(fax_blacklist) insert_anim = "faxsend" pass_flags = PASSTABLE var/fax_network = "Local Fax Network" - var/syndie_restricted = FALSE //is it a syndicate base fax restricted from contacting NT assets? + /// If true, prevents fax machine from sending messages to NT machines + var/syndie_restricted = FALSE - var/long_range_enabled = 0 // Can we send messages off the station? + /// Can we send messages off-station? + var/long_range_enabled = FALSE req_one_access = list(ACCESS_LAWYER, ACCESS_HEADS, ACCESS_ARMORY) use_power = IDLE_POWER_USE idle_power_usage = 30 active_power_usage = 200 - var/obj/item/card/id/scan = null // identification + /// ID card inserted into the machine, used to log in with + var/obj/item/card/id/scan = null - var/authenticated = 0 - var/sendcooldown = 0 // to avoid spamming fax messages + /// Whether the machine is "logged in" or not + var/authenticated = FALSE + /// Next world.time at which this fax machine can send a message to CC/syndicate + var/sendcooldown = 0 + /// After sending a message to CC/syndicate, cannot send another to them for this many deciseconds var/cooldown_time = 1800 - var/department = "Unknown" // our department + /// Our department, determines whether this machine gets faxes sent to a department + var/department = "Unknown" - var/destination = "Not Selected" // the department we're sending to + /// Target department to send outgoing faxes to + var/destination /obj/machinery/photocopier/faxmachine/New() ..() @@ -44,7 +52,7 @@ GLOBAL_LIST_EMPTY(fax_blacklist) /obj/machinery/photocopier/faxmachine/longrange name = "long range fax machine" fax_network = "Central Command Quantum Entanglement Network" - long_range_enabled = 1 + long_range_enabled = TRUE /obj/machinery/photocopier/faxmachine/longrange/syndie name = "syndicate long range fax machine" @@ -58,17 +66,17 @@ GLOBAL_LIST_EMPTY(fax_blacklist) GLOB.hidden_departments |= department /obj/machinery/photocopier/faxmachine/attack_hand(mob/user) - ui_interact(user) + tgui_interact(user) /obj/machinery/photocopier/faxmachine/attack_ghost(mob/user) - ui_interact(user) + tgui_interact(user) /obj/machinery/photocopier/faxmachine/attackby(obj/item/item, mob/user, params) if(istype(item,/obj/item/card/id) && !scan) scan(item) else if(istype(item, /obj/item/paper) || istype(item, /obj/item/photo) || istype(item, /obj/item/paper_bundle)) ..() - SSnanoui.update_uis(src) + SStgui.update_uis(src) else return ..() @@ -80,42 +88,6 @@ GLOBAL_LIST_EMPTY(fax_blacklist) else to_chat(user, "You swipe the card through [src], but nothing happens.") -/obj/machinery/photocopier/faxmachine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "faxmachine.tmpl", "Fax Machine UI", 540, 450) - ui.open() - -/obj/machinery/photocopier/faxmachine/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - var/is_authenticated = is_authenticated(user) - - if(scan) - data["scan_name"] = scan.name - else - data["scan_name"] = "-----" - data["authenticated"] = is_authenticated - if(!is_authenticated) - data["network"] = "Disconnected" - else if(!emagged) - data["network"] = fax_network - else - data["network"] = "ERR*?*%!*" - if(copyitem) - data["paper"] = copyitem.name - data["paperinserted"] = 1 - else - data["paper"] = "-----" - data["paperinserted"] = 0 - data["destination"] = destination - data["cooldown"] = sendcooldown - if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments)) - data["respectcooldown"] = 1 - else - data["respectcooldown"] = 0 - - return data - /obj/machinery/photocopier/faxmachine/proc/is_authenticated(mob/user) if(authenticated) return TRUE @@ -123,87 +95,134 @@ GLOBAL_LIST_EMPTY(fax_blacklist) return TRUE return FALSE -/obj/machinery/photocopier/faxmachine/Topic(href, href_list) - if(..()) - return 1 +/obj/machinery/photocopier/faxmachine/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "FaxMachine", name, 540, 300, master_ui, state) + ui.open() +/obj/machinery/photocopier/faxmachine/tgui_data(mob/user) + var/list/data = list() + data["authenticated"] = is_authenticated(user) + data["scan_name"] = scan ? scan.name : FALSE + if(!data["authenticated"]) + data["network"] = "Disconnected" + else if(!emagged) + data["network"] = fax_network + else + data["network"] = "ERR*?*%!*" + data["paper"] = copyitem ? copyitem.name : FALSE + data["paperinserted"] = copyitem ? TRUE : FALSE + data["destination"] = destination ? destination : FALSE + data["sendError"] = FALSE + if(stat & (BROKEN|NOPOWER)) + data["sendError"] = "No Power" + else if(!data["authenticated"]) + data["sendError"] = "Not Logged In" + else if(!data["paper"]) + data["sendError"] = "Nothing Inserted" + else if(!data["destination"]) + data["sendError"] = "Destination Not Set" + else if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments)) + var/cooldown_seconds = cooldown_seconds() + if(cooldown_seconds) + data["sendError"] = "Re-aligning in [cooldown_seconds] seconds..." + return data + + +/obj/machinery/photocopier/faxmachine/tgui_act(action, params) + if(..()) + return var/is_authenticated = is_authenticated(usr) - if(href_list["send"]) - if(copyitem && is_authenticated) + . = TRUE + switch(action) + if("scan") // insert/remove your ID card + scan() + if("auth") // log in/out + if(!is_authenticated && scan) + if(scan.registered_name in GLOB.fax_blacklist) + to_chat(usr, "Login rejected: individual is blacklisted from fax network.") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + . = FALSE + else if(check_access(scan)) + authenticated = TRUE + else // ID doesn't have access to this machine + to_chat(usr, "Login rejected: ID card does not have required access.") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + . = FALSE + else if(is_authenticated) + authenticated = FALSE + if("paper") // insert/eject paper/paperbundle/photo + if(copyitem) + copyitem.forceMove(get_turf(src)) + if(ishuman(usr)) + if(!usr.get_active_hand() && Adjacent(usr)) + usr.put_in_hands(copyitem) + to_chat(usr, "You eject [copyitem] from [src].") + copyitem = null + else + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/paper) || istype(I, /obj/item/photo) || istype(I, /obj/item/paper_bundle)) + usr.drop_item() + copyitem = I + I.forceMove(src) + to_chat(usr, "You insert [I] into [src].") + flick(insert_anim, src) + else + to_chat(usr, "[src] only accepts paper, paper bundles, and photos.") + . = FALSE + if("rename") // rename the item that is currently in the fax machine + if(copyitem) + var/n_name = sanitize(copytext(input(usr, "What would you like to label the fax?", "Fax Labelling", copyitem.name) as text, 1, MAX_MESSAGE_LEN)) + if((copyitem && copyitem.loc == src && usr.stat == 0)) + if(istype(copyitem, /obj/item/paper)) + copyitem.name = "[(n_name ? text("[n_name]") : initial(copyitem.name))]" + copyitem.desc = "This is a paper titled '" + copyitem.name + "'." + else if(istype(copyitem, /obj/item/photo)) + copyitem.name = "[(n_name ? text("[n_name]") : "photo")]" + else if(istype(copyitem, /obj/item/paper_bundle)) + copyitem.name = "[(n_name ? text("[n_name]") : "paper")]" + else + . = FALSE + else + . = FALSE + else + . = FALSE + if("dept") // choose which department receives the fax + if(is_authenticated) + var/lastdestination = destination + var/list/combineddepartments = GLOB.alldepartments.Copy() + if(long_range_enabled) + combineddepartments += GLOB.admin_departments.Copy() + if(emagged) + combineddepartments += GLOB.hidden_admin_departments.Copy() + combineddepartments += GLOB.hidden_departments.Copy() + if(syndie_restricted) + combineddepartments = GLOB.hidden_admin_departments.Copy() + combineddepartments += GLOB.hidden_departments.Copy() + for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) + if(F.emagged)//we can contact emagged faxes on the station + combineddepartments |= F.department + destination = input(usr, "To which department?", "Choose a department", "") as null|anything in combineddepartments + if(!destination) + destination = lastdestination + if("send") // actually send the fax + if(!copyitem || !is_authenticated || !destination) + return + if(stat & (BROKEN|NOPOWER)) + return if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments)) + var/cooldown_seconds = cooldown_seconds() + if(cooldown_seconds > 0) + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + to_chat(usr, "[src] is not ready for another [cooldown_seconds] seconds.") + return send_admin_fax(usr, destination) + sendcooldown = world.time + cooldown_time else sendfax(destination, usr) - - if(sendcooldown) - spawn(sendcooldown) // cooldown time - sendcooldown = 0 - SSnanoui.update_uis(src) - - if(href_list["paper"]) - if(copyitem) - copyitem.forceMove(get_turf(src)) - if(ishuman(usr)) - if(!usr.get_active_hand() && Adjacent(usr)) - usr.put_in_hands(copyitem) - to_chat(usr, "You eject \the [copyitem] from \the [src].") - copyitem = null - else - var/obj/item/I = usr.get_active_hand() - if(istype(I, /obj/item/paper) || istype(I, /obj/item/photo) || istype(I, /obj/item/paper_bundle)) - usr.drop_item() - copyitem = I - I.forceMove(src) - to_chat(usr, "You insert \the [I] into \the [src].") - flick(insert_anim, src) - - if(href_list["scan"]) - scan() - - if(href_list["dept"]) - if(is_authenticated) - var/lastdestination = destination - var/list/combineddepartments = GLOB.alldepartments.Copy() - if(long_range_enabled) - combineddepartments += GLOB.admin_departments.Copy() - - if(emagged) - combineddepartments += GLOB.hidden_admin_departments.Copy() - combineddepartments += GLOB.hidden_departments.Copy() - - if(syndie_restricted) - combineddepartments = GLOB.hidden_admin_departments.Copy() - combineddepartments += GLOB.hidden_departments.Copy() - for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) - if(F.emagged)//we can contact emagged faxes on the station - combineddepartments |= F.department - - destination = input(usr, "To which department?", "Choose a department", "") as null|anything in combineddepartments - if(!destination) - destination = lastdestination - - if(href_list["auth"]) - if(!is_authenticated && scan) - if(scan.registered_name in GLOB.fax_blacklist) - playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - else if(check_access(scan)) - authenticated = 1 - else if(is_authenticated) - authenticated = 0 - - if(href_list["rename"]) - if(copyitem) - var/n_name = sanitize(copytext(input(usr, "What would you like to label the fax?", "Fax Labelling", copyitem.name) as text, 1, MAX_MESSAGE_LEN)) - if((copyitem && copyitem.loc == src && usr.stat == 0)) - if(istype(copyitem, /obj/item/paper)) - copyitem.name = "[(n_name ? text("[n_name]") : initial(copyitem.name))]" - copyitem.desc = "This is a paper titled '" + copyitem.name + "'." - else if(istype(copyitem, /obj/item/photo)) - copyitem.name = "[(n_name ? text("[n_name]") : "photo")]" - else if(istype(copyitem, /obj/item/paper_bundle)) - copyitem.name = "[(n_name ? text("[n_name]") : "paper")]" - - SSnanoui.update_uis(src) + if(.) + add_fingerprint(usr) /obj/machinery/photocopier/faxmachine/proc/scan(var/obj/item/card/id/card = null) if(scan) // Card is in machine @@ -226,7 +245,7 @@ GLOBAL_LIST_EMPTY(fax_blacklist) usr.drop_item() card.forceMove(src) scan = card - SSnanoui.update_uis(src) + SStgui.update_uis(src) /obj/machinery/photocopier/faxmachine/verb/eject_id() set category = null @@ -237,25 +256,20 @@ GLOBAL_LIST_EMPTY(fax_blacklist) return if(scan) - to_chat(usr, "You remove \the [scan] from \the [src].") + to_chat(usr, "You remove [scan] from [src].") scan.forceMove(get_turf(src)) if(!usr.get_active_hand() && Adjacent(usr)) usr.put_in_hands(scan) scan = null else - to_chat(usr, "There is nothing to remove from \the [src].") + to_chat(usr, "There is nothing to remove from [src].") /obj/machinery/photocopier/faxmachine/proc/sendfax(var/destination,var/mob/sender) - if(stat & (BROKEN|NOPOWER)) - return - - use_power(200) - + use_power(active_power_usage) var/success = 0 for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(F.department == destination) success = F.receivefax(copyitem) - if(success) var/datum/fax/F = new /datum/fax() F.name = copyitem.name @@ -272,10 +286,10 @@ GLOBAL_LIST_EMPTY(fax_blacklist) /obj/machinery/photocopier/faxmachine/proc/receivefax(var/obj/item/incoming) if(stat & (BROKEN|NOPOWER)) - return 0 + return FALSE if(department == "Unknown") - return 0 //You can't send faxes to "Unknown" + return FALSE //You can't send faxes to "Unknown" flick("faxreceive", src) @@ -291,19 +305,13 @@ GLOBAL_LIST_EMPTY(fax_blacklist) else if(istype(incoming, /obj/item/paper_bundle)) bundlecopy(incoming) else - return 0 + return FALSE use_power(active_power_usage) - return 1 + return TRUE /obj/machinery/photocopier/faxmachine/proc/send_admin_fax(var/mob/sender, var/destination) - if(stat & (BROKEN|NOPOWER)) - return - - if(sendcooldown) - return - - use_power(200) + use_power(active_power_usage) if(!(istype(copyitem, /obj/item/paper) || istype(copyitem, /obj/item/paper_bundle) || istype(copyitem, /obj/item/photo))) visible_message("[src] beeps, \"Error transmitting message.\"") @@ -327,10 +335,12 @@ GLOBAL_LIST_EMPTY(fax_blacklist) for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(F.department == destination) F.receivefax(copyitem) - sendcooldown = cooldown_time - spawn(50) - visible_message("[src] beeps, \"Message transmitted successfully.\"") + visible_message("[src] beeps, \"Message transmitted successfully.\"") +/obj/machinery/photocopier/faxmachine/proc/cooldown_seconds() + if(sendcooldown < world.time) + return 0 + return round((sendcooldown - world.time) / 10) /obj/machinery/photocopier/faxmachine/proc/message_admins(var/mob/sender, var/faxname, var/faxtype, var/obj/item/sent, font_colour="#9A04D1") var/msg = "[faxname]: [key_name_admin(sender)] | REPLY: (RADIO) (FAX) ([ADMIN_SM(sender,"SM")]) | REJECT: (TEMPLATE) ([ADMIN_BSA(sender,"BSA")]) (EVILFAX) : Receiving '[sent.name]' via secure connection... view message" diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 59ce091b170..2fa2c4c1573 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -227,8 +227,8 @@ if(terminal) terminal.master = null terminal = null - return 1 - return 0 + return TRUE + return FALSE /obj/machinery/power/smes/proc/make_terminal(user, tempDir, tempLoc) // create a terminal object at the same position as original turf loc @@ -339,89 +339,91 @@ /obj/machinery/power/smes/attack_ai(mob/user) add_hiddenprint(user) - ui_interact(user) + tgui_interact(user) /obj/machinery/power/smes/attack_ghost(mob/user) - ui_interact(user) + tgui_interact(user) /obj/machinery/power/smes/attack_hand(mob/user) add_fingerprint(user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/power/smes/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) if(stat & BROKEN) return - - - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "smes.tmpl", "SMES Power Storage Unit", 540, 380) - // open the new ui window + ui = new(user, src, ui_key, "Smes", name, 340, 350, master_ui, state) ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) - -/obj/machinery/power/smes/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - - data["nameTag"] = name_tag - data["storedCapacity"] = round(100.0*charge/capacity, 0.1) - data["charging"] = inputting - data["chargeMode"] = input_attempt - data["chargeLevel"] = input_level - data["chargeMax"] = input_level_max - data["outputOnline"] = output_attempt - data["outputLevel"] = output_level - data["outputMax"] = output_level_max - data["outputLoad"] = round(output_used) - - if(outputting) - data["outputting"] = 2 // smes is outputting - else if(!outputting && output_attempt) - data["outputting"] = 1 // smes is online but not outputting because it's charge level is too low - else - data["outputting"] = 0 // smes is not outputting +/obj/machinery/power/smes/tgui_data(mob/user) + var/list/data = list( + "capacity" = capacity, + "capacityPercent" = round(100*charge/capacity, 0.1), + "charge" = charge, + "inputAttempt" = input_attempt, + "inputting" = inputting, + "inputLevel" = input_level, + "inputLevel_text" = DisplayPower(input_level), + "inputLevelMax" = input_level_max, + "inputAvailable" = input_available, + "outputAttempt" = output_attempt, + "outputting" = outputting, + "outputLevel" = output_level, + "outputLevel_text" = DisplayPower(output_level), + "outputLevelMax" = output_level_max, + "outputUsed" = round(output_used), + ) return data -/obj/machinery/power/smes/Topic(href, href_list) +/obj/machinery/power/smes/tgui_act(action, params) if(..()) - return 1 + return + . = TRUE + switch(action) + if("tryinput") + inputting(!input_attempt) + update_icon() + if("tryoutput") + outputting(!output_attempt) + update_icon() + if("input") + var/target = params["target"] + var/adjust = text2num(params["adjust"]) + if(target == "min") + target = 0 + else if(target == "max") + target = input_level_max + else if(adjust) + target = input_level + adjust + else if(text2num(target) != null) + target = text2num(target) + else + . = FALSE + if(.) + input_level = clamp(target, 0, input_level_max) + if("output") + var/target = params["target"] + var/adjust = text2num(params["adjust"]) + if(target == "min") + target = 0 + else if(target == "max") + target = output_level_max + else if(adjust) + target = output_level + adjust + else if(text2num(target) != null) + target = text2num(target) + else + . = FALSE + if(.) + output_level = clamp(target, 0, output_level_max) + else + . = FALSE + if(.) + log_smes(usr) - if( href_list["cmode"] ) - inputting(!input_attempt) - update_icon() - - else if( href_list["online"] ) - outputting(!output_attempt) - update_icon() - - else if( href_list["input"] ) - switch( href_list["input"] ) - if("min") - input_level = 0 - if("max") - input_level = input_level_max - if("set") - input_level = input(usr, "Enter new input level (0-[input_level_max])", "SMES Input Power Control", input_level) as num - input_level = max(0, min(input_level_max, input_level)) // clamp to range - - else if( href_list["output"] ) - switch( href_list["output"] ) - if("min") - output_level = 0 - if("max") - output_level = output_level_max - if("set") - output_level = input(usr, "Enter new output level (0-[output_level_max])", "SMES Output Power Control", output_level) as num - output_level = max(0, min(output_level_max, output_level)) // clamp to range - - investigate_log("input/output; [input_level>output_level?"":""][input_level]/[output_level] | Output-mode: [output_attempt?"on":"off"] | Input-mode: [input_attempt?"auto":"off"] by [usr.key]","singulo") - - return 1 +/obj/machinery/power/smes/proc/log_smes(mob/user) + investigate_log("input/output; [input_level>output_level?"":""][input_level]/[output_level] | Charge: [charge] | Output-mode: [output_attempt?"on":"off"] | Input-mode: [input_attempt?"auto":"off"] by [user ? key_name(user) : "outside forces"]", "singulo") /obj/machinery/power/smes/proc/ion_act() if(is_station_level(src.z)) @@ -448,6 +450,7 @@ smoke.attach(src) smoke.start() + /obj/machinery/power/smes/proc/inputting(var/do_input) input_attempt = do_input if(!input_attempt) @@ -459,14 +462,15 @@ outputting = 0 /obj/machinery/power/smes/emp_act(severity) - inputting(rand(0,1)) - outputting(rand(0,1)) + inputting(rand(0, 1)) + outputting(rand(0, 1)) output_level = rand(0, output_level_max) input_level = rand(0, input_level_max) charge -= 1e6/severity if(charge < 0) charge = 0 update_icon() + log_smes() ..() /obj/machinery/power/smes/engineering diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 68ed3cb7749..78022bb6d7c 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -33,8 +33,8 @@ GLOBAL_VAR_INIT(ert_request_answered, FALSE) to_chat(usr, "Central Command has already dispatched an emergency response team!") return - var/datum/nano_module/ert_manager/E = new() - E.ui_interact(usr) + var/datum/tgui_module/ert_manager/E = new() + E.tgui_interact(usr) /mob/dead/observer/proc/JoinResponseTeam() @@ -209,7 +209,7 @@ GLOBAL_VAR_INIT(ert_request_answered, FALSE) var/paranormal_outfit var/borg_path = /mob/living/silicon/robot/ert -/datum/response_team/proc/setSlots(com=1, sec=3, med=3, eng=3, jan=0, par=0, cyb=0) +/datum/response_team/proc/setSlots(com=1, sec=4, med=0, eng=0, jan=0, par=0, cyb=0) slots["Commander"] = com slots["Security"] = sec slots["Medic"] = med diff --git a/code/modules/ruins/lavalandruin_code/animal_hospital.dm b/code/modules/ruins/lavalandruin_code/animal_hospital.dm index 1cf21d5a890..18ea13770a6 100644 --- a/code/modules/ruins/lavalandruin_code/animal_hospital.dm +++ b/code/modules/ruins/lavalandruin_code/animal_hospital.dm @@ -6,9 +6,10 @@ name = "broken rejuvenation pod" desc = "A small sleeper typically used to instantly restore minor wounds. This one seems broken, and its occupant is comatose." mob_name = "a translocated vet" - flavour_text = "What...? Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \ + description = "You are an intern working in an animal hospital that suddenly got transported to lavaland. Good luck." + flavour_text = "What...? Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \ everyone's gone. One of the cats scratched you just a few minutes ago. That's why you were in the pod - to heal the scratch. The scabs are still fresh; you see them right now. So where is \ - everyone? Where did they go? What happened to the hospital? And is that smoke you smell? You need to find someone else. Maybe they can tell you what happened." + everyone? Where did they go? What happened to the hospital? And is that smoke you smell? You need to find someone else. Maybe they can tell you what happened." assignedrole = "Translocated Vet" allow_species_pick = TRUE diff --git a/code/modules/ruins/lavalandruin_code/ash_walker_den.dm b/code/modules/ruins/lavalandruin_code/ash_walker_den.dm index 62b2343f10a..c173097fcad 100644 --- a/code/modules/ruins/lavalandruin_code/ash_walker_den.dm +++ b/code/modules/ruins/lavalandruin_code/ash_walker_den.dm @@ -67,9 +67,10 @@ anchored = FALSE move_resist = MOVE_FORCE_NORMAL density = FALSE - flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. \ - You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest. \ -
You are free to attack miners and other outsiders. DO NOT leave Lavaland without admin permission! DO NOT attack the mining outpost without being provoked.
" + important_info = "Do not leave Lavaland without admin permission. Do not attack the mining outpost without being provoked." + description = "You are an ashwalker, a native inhabitant of Lavaland. Try to survive with nothing but spears and other tribal technology. Bring dead bodies back to your tendril to create more of your kind. You are free to attack miners and other outsiders." + flavour_text = "Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. \ + You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest." assignedrole = "Ash Walker" /obj/effect/mob_spawn/human/ash_walker/special(mob/living/carbon/human/new_spawn) diff --git a/code/modules/ruins/lavalandruin_code/hermit.dm b/code/modules/ruins/lavalandruin_code/hermit.dm index a28f30b9ed1..93056ee1d9a 100644 --- a/code/modules/ruins/lavalandruin_code/hermit.dm +++ b/code/modules/ruins/lavalandruin_code/hermit.dm @@ -10,7 +10,8 @@ random = TRUE allow_species_pick = TRUE mob_species = /datum/species/human - flavour_text = "You've been stranded in this godless prison of a planet for longer than you can remember. Each day you barely scrape by, and between the terrible \ + description = "You are a single survivor stranded on lavaland in a makeshift shelter. Try to survive with barely any equipment. For when miner is just too boring." + flavour_text = "You've been stranded in this godless prison of a planet for longer than you can remember. Each day you barely scrape by, and between the terrible \ conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \ the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... " assignedrole = "Hermit" @@ -22,28 +23,28 @@ if(1) flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \ only one pod left when you got to the escape bay. You took it and launched it alone, and the crowd of terrified faces crowding at the airlock door as your pod's engines burst to \ - life and sent you to this hell are forever branded into your memory." + life and sent you to this hell are forever branded into your memory." outfit.uniform = /obj/item/clothing/under/assistantformal outfit.shoes = /obj/item/clothing/shoes/black outfit.back = /obj/item/storage/backpack if(2) flavour_text += "you're an exile from the Tiger Cooperative. Their technological fanaticism drove you to question the power and beliefs of the Exolitics, and they saw you as a \ heretic and subjected you to hours of horrible torture. You were hours away from execution when a high-ranking friend of yours in the Cooperative managed to secure you a pod, \ - scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since." + scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since." outfit.uniform = /obj/item/clothing/under/color/orange outfit.shoes = /obj/item/clothing/shoes/orange outfit.back = /obj/item/storage/backpack if(3) flavour_text += "you were a doctor on one of Nanotrasen's space stations, but you left behind that damn corporation's tyranny and everything it stood for. From a metaphorical hell \ - to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there." + to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there." outfit.uniform = /obj/item/clothing/under/rank/medical outfit.suit = /obj/item/clothing/suit/storage/labcoat outfit.back = /obj/item/storage/backpack/medic outfit.shoes = /obj/item/clothing/shoes/black if(4) - flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so kindly put it. It seems that they were right when you, on a tour \ + flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so kindly put it. It seems that they were right when you, on a tour \ at one of Nanotrasen's state-of-the-art research facilities, were in one of the escape pods alone and saw the red button. It was big and shiny, and it caught your eye. You pressed \ - it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now." + it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now." outfit.uniform = /obj/item/clothing/under/color/grey/glorf outfit.shoes = /obj/item/clothing/shoes/black outfit.back = /obj/item/storage/backpack diff --git a/code/modules/ruins/lavalandruin_code/seed_vault.dm b/code/modules/ruins/lavalandruin_code/seed_vault.dm index 2c999a7ce29..1a5e863c52f 100644 --- a/code/modules/ruins/lavalandruin_code/seed_vault.dm +++ b/code/modules/ruins/lavalandruin_code/seed_vault.dm @@ -18,9 +18,10 @@ roundstart = FALSE death = FALSE mob_species = /datum/species/diona/pod - flavour_text = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \ + description = "You are a diona on Lavaland with access to a full botany setup. Perfect to mess around with plants in peace." + flavour_text = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \ seed vaults and spread them across the universe to every planet they could chart. You are in one such seed vault. Your goal is to cultivate and spread life wherever it will go while waiting \ - for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago." + for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago." assignedrole = "Lifebringer" /obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn) diff --git a/code/modules/ruins/lavalandruin_code/syndicate_base.dm b/code/modules/ruins/lavalandruin_code/syndicate_base.dm index d053e139f61..1e745e8d3ed 100644 --- a/code/modules/ruins/lavalandruin_code/syndicate_base.dm +++ b/code/modules/ruins/lavalandruin_code/syndicate_base.dm @@ -28,8 +28,10 @@ death = FALSE icon = 'icons/obj/cryogenic2.dmi' icon_state = "sleeper_s" - flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Continue your research as best you can, and try to keep a low profile. The base is rigged with explosives, do not abandon it or let it fall into enemy hands! \ -
You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. DO NOT work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. DO NOT leave your base without admin permission." + important_info = "Do not work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. Do not leave your base without admin permission." + description = "Experiment with deadly chems and viruses in peace or help any visiting Syndicate Agent." + flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Continue your research as best you can, and try to keep a low profile. The base is rigged with explosives, do not abandon it or let it fall into enemy hands!\ + It's been made clear to you that the Syndicate will make you regret it if you disappoint them." outfit = /datum/outfit/lavaland_syndicate assignedrole = "Lavaland Syndicate" del_types = list() // Necessary to prevent del_types from removing radio! @@ -59,13 +61,13 @@ /obj/effect/mob_spawn/human/lavaland_syndicate/comms name = "Syndicate Comms Agent sleeper" mob_name = "Syndicate Comms Agent" - flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Monitor enemy activity as best you can, and try to keep a low profile. Do not abandon the base. Use the communication equipment to provide support to any field agents, and sow disinformation to throw Nanotrasen off your trail. Do not let the base fall into enemy hands! \ -
You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. DO NOT work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. DO NOT leave your base without admin permission." + important_info = "Do not work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. Do not leave your base without admin permission. Do not reveal the existence of yourself to NT." + description = "Monitor comms and cameras and try to assist any agents on station while keeping your existence a secret." + flavour_text = "You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. Monitor enemy activity as best you can, and try to keep a low profile." outfit = /datum/outfit/lavaland_syndicate/comms /obj/effect/mob_spawn/human/lavaland_syndicate/comms/space - flavour_text = "You are a syndicate agent, assigned to a small listening post station situated near your hated enemy's top secret research facility: Space Station 13. Monitor enemy activity as best you can, and try to keep a low profile. Do not abandon the base. Use the communication equipment to provide support to any field agents, and sow disinformation to throw Nanotrasen off your trail. Do not let the base fall into enemy hands! \ -
You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. DO NOT work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. DO NOT leave your base without admin permission." + flavour_text = "You are a syndicate agent, employed in a small listening outpost. You'd be bored to death if you couldn't listen in on those NT idiots mess up all the time." /obj/effect/mob_spawn/human/lavaland_syndicate/comms/space/Initialize(mapload) . = ..() diff --git a/code/modules/security_levels/keycard authentication.dm b/code/modules/security_levels/keycard authentication.dm index 87723701281..e51355e89bb 100644 --- a/code/modules/security_levels/keycard authentication.dm +++ b/code/modules/security_levels/keycard authentication.dm @@ -4,17 +4,17 @@ icon = 'icons/obj/monitors.dmi' icon_state = "auth_off" - var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made. - var/event = "" - var/screen = 1 + var/active = FALSE // This gets set to TRUE on all devices except the one where the initial request was made. + var/event + var/swiping = FALSE // on swiping screen? var/list/ert_chosen = list() - var/confirmed = 0 //This variable is set by the device that confirms the request. - var/confirm_delay = 20 //(2 seconds) - var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device. + var/confirmed = FALSE // This variable is set by the device that confirms the request. + var/confirm_delay = 5 SECONDS // time allowed for a second person to confirm a swipe. + var/busy = FALSE // Busy when waiting for authentication or an event request has been sent from this device. var/obj/machinery/keycard_auth/event_source var/mob/event_triggered_by var/mob/event_confirmed_by - var/ert_reason = "Reason for ERT" + var/ert_reason anchored = 1 use_power = IDLE_POWER_USE @@ -35,16 +35,19 @@ return if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda)) if(check_access(W)) - if(active == 1) + if(active) //This is not the device that made the initial request. It is the device confirming the request. if(event_source) - event_source.confirmed = 1 + event_source.confirmed = TRUE event_source.event_confirmed_by = usr - else if(screen == 2) - if(event == "Emergency Response Team" && ert_reason == "Reason for ERT") - to_chat(user, "Supply a reason for calling the ERT first!") + SStgui.update_uis(event_source) + SStgui.update_uis(src) + else if(swiping) + if(event == "Emergency Response Team" && !ert_reason) + to_chat(user, "Supply a reason for calling the ERT first!") return event_triggered_by = usr + SStgui.update_uis(src) broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices else to_chat(user, "Access denied.") @@ -59,57 +62,58 @@ stat |= NOPOWER /obj/machinery/keycard_auth/attack_ghost(mob/user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/keycard_auth/attack_hand(mob/user as mob) +/obj/machinery/keycard_auth/attack_hand(mob/user) if(..()) - return 1 - ui_interact(user) + return TRUE + tgui_interact(user) -/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(busy) - to_chat(user, "This device is busy.") - return - - user.set_machine(src) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/keycard_auth/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 540, 320) + ui = new(user, src, ui_key, "KeycardAuth", name, 540, 300, master_ui, state) ui.open() -/obj/machinery/keycard_auth/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - data["screen"] = screen - data["event"] = event - data["ertreason"] = ert_reason + +/obj/machinery/keycard_auth/tgui_data() + var/list/data = list() + data["redAvailable"] = GLOB.security_level == SEC_LEVEL_RED ? FALSE : TRUE + data["swiping"] = swiping + data["busy"] = busy + data["event"] = active && event_source && event_source.event ? event_source.event : event + data["ertreason"] = active && event_source && event_source.ert_reason ? event_source.ert_reason : ert_reason + data["isRemote"] = active ? TRUE : FALSE + data["hasSwiped"] = event_triggered_by ? TRUE : FALSE + data["hasConfirm"] = event_confirmed_by || (active && event_source && event_source.event_confirmed_by) ? TRUE : FALSE return data -/obj/machinery/keycard_auth/Topic(href, href_list) +/obj/machinery/keycard_auth/tgui_act(action, params) if(..()) - return 1 - - if(busy) - to_chat(usr, "This device is busy.") return + if(busy) + to_chat(usr, "This device is busy.") + return + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return + . = TRUE + switch(action) + if("ert") + ert_reason = stripped_input(usr, "Reason for ERT Call:", "", "") + if("reset") + reset() + if("triggerevent") + event = params["triggerevent"] + swiping = TRUE - if(href_list["triggerevent"]) - event = href_list["triggerevent"] - screen = 2 - if(href_list["reset"]) - reset() - if(href_list["ert"]) - ert_reason = stripped_input(usr, "Reason for ERT Call:", "", "") - - SSnanoui.update_uis(src) add_fingerprint(usr) - return /obj/machinery/keycard_auth/proc/reset() - active = 0 - event = "" - screen = 1 - confirmed = 0 + active = FALSE + event = null + swiping = FALSE + confirmed = FALSE event_source = null icon_state = "auth_off" event_triggered_by = null @@ -125,7 +129,7 @@ sleep(confirm_delay) if(confirmed) - confirmed = 0 + confirmed = FALSE trigger_event(event) log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]") message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1) @@ -135,16 +139,17 @@ if(stat & (BROKEN|NOPOWER)) return event_source = source - busy = 1 - active = 1 + busy = TRUE + active = TRUE + SStgui.update_uis(src) icon_state = "auth_on" sleep(confirm_delay) event_source = null icon_state = "auth_off" - active = 0 - busy = 0 + active = FALSE + busy = FALSE /obj/machinery/keycard_auth/proc/trigger_event() switch(event) @@ -178,7 +183,7 @@ if(fullmin_count) GLOB.ert_request_answered = TRUE ERT_Announce(ert_reason , event_triggered_by, 0) - ert_reason = "Reason for ERT" + ert_reason = null feedback_inc("alert_keycard_auth_ert",1) spawn(3000) if(!GLOB.ert_request_answered) diff --git a/code/modules/shuttle/ert.dm b/code/modules/shuttle/ert.dm index 5168ce89278..ddb7bb343b6 100644 --- a/code/modules/shuttle/ert.dm +++ b/code/modules/shuttle/ert.dm @@ -6,13 +6,12 @@ resistance_flags = INDESTRUCTIBLE flags = NODECONSTRUCT -/obj/machinery/computer/shuttle/ert/Topic(href, href_list) - if(href_list["move"]) +/obj/machinery/computer/shuttle/ert/can_call_shuttle(mob/user, action) + if(action == "move") var/authorized_roles = list(SPECIAL_ROLE_ERT, SPECIAL_ROLE_DEATHSQUAD) - if(!((usr.mind?.assigned_role in authorized_roles) || is_admin(usr))) - message_admins("Potential ERT shuttle hijack, ERT shuttle moved by unauthorized user: [key_name_admin(usr)]") - ..() - + if(!((user.mind?.assigned_role in authorized_roles) || is_admin(user))) + message_admins("Potential ERT shuttle hijack, ERT shuttle moved by unauthorized user: [key_name_admin(user)]") + return TRUE /obj/machinery/computer/camera_advanced/shuttle_docker/ert name = "specops navigation computer" diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index cfd3ab8e6f2..86cfe2a7444 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -727,13 +727,13 @@ name = "Shuttle Console" icon_screen = "shuttle" icon_keyboard = "tech_key" - req_access = list( ) + req_access = list() circuit = /obj/item/circuitboard/shuttle var/shuttleId var/possible_destinations = "" var/admin_controlled var/max_connect_range = 7 - var/docking_request = 0 + var/moved = FALSE //workaround for nukie shuttle, hope I find a better way to do this... /obj/machinery/computer/shuttle/New(location, obj/item/circuitboard/shuttle/C) ..() @@ -773,21 +773,20 @@ return connect() add_fingerprint(user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/shuttle/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/shuttle/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "shuttle_console.tmpl", M ? M.name : "shuttle", 300, 200) + ui = new(user, src, ui_key, "ShuttleConsole", name, 350, 150, master_ui, state) ui.open() -/obj/machinery/computer/shuttle/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/machinery/computer/shuttle/tgui_data(mob/user) + var/list/data = list() var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) data["status"] = M ? M.getStatusText() : null if(M) - data["shuttle"] = 1 + data["shuttle"] = TRUE //this should just be boolean, right? var/list/docking_ports = list() data["docking_ports"] = docking_ports var/list/options = params2list(possible_destinations) @@ -799,34 +798,35 @@ docking_ports[++docking_ports.len] = list("name" = S.name, "id" = S.id) data["docking_ports_len"] = docking_ports.len data["admin_controlled"] = admin_controlled - data["docking_request"] = docking_request - return data -/obj/machinery/computer/shuttle/Topic(href, href_list) - if(..()) - return 1 - +/obj/machinery/computer/shuttle/tgui_act(action, params) + if(..()) //we can't actually interact, so no action + return TRUE if(!allowed(usr)) to_chat(usr, "Access denied.") - return - + return TRUE + if(!can_call_shuttle(usr, action)) + return TRUE var/list/options = params2list(possible_destinations) - if(href_list["move"]) - if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. - // Seriously, though, NEVER trust a Topic with something like this. Ever. - // Sidenote for whoever did this last. Why did you set it to echo whatever the user entered to admin chat? You solved one exploit and created another. + if(action == "move") + var/destination = params["move"] + if(!options.Find(destination))//figure out if this translation works message_admins("EXPLOIT: [ADMIN_LOOKUPFLW(usr)] attempted to move [src] to an invalid location! [ADMIN_COORDJMP(src)]") return - switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1, usr)) + switch(SSshuttle.moveShuttle(shuttleId, destination, TRUE, usr)) if(0) atom_say("Shuttle departing! Please stand away from the doors.") usr.create_log(MISC_LOG, "used [src] to call the [shuttleId] shuttle") + if(!moved) + moved = TRUE + add_fingerprint(usr) + return TRUE if(1) to_chat(usr, "Invalid shuttle requested.") else to_chat(usr, "Unable to comply.") - return 1 + /obj/machinery/computer/shuttle/emag_act(mob/user) if(!emagged) @@ -834,6 +834,10 @@ emagged = 1 to_chat(user, "You fried the consoles ID checking system.") +//for restricting when the computer can be used, needed for some console subtypes. +/obj/machinery/computer/shuttle/proc/can_call_shuttle(mob/user, action) + return TRUE + /obj/machinery/computer/shuttle/ferry name = "transport ferry console" circuit = /obj/item/circuitboard/ferry @@ -844,25 +848,23 @@ /obj/machinery/computer/shuttle/ferry/request name = "ferry console" circuit = /obj/item/circuitboard/ferry/request - var/cooldown //prevents spamming admins + var/next_request //to prevent spamming admins possible_destinations = "ferry_home" - admin_controlled = 1 + admin_controlled = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF -/obj/machinery/computer/shuttle/ferry/request/Topic(href, href_list) - if(..()) - return 1 - if(href_list["request"]) - if(cooldown) +/obj/machinery/computer/shuttle/ferry/request/tgui_act(action, params) + if(..()) // Note that the parent handels normal shuttle movement on top of security checks + return + if(action == "request") + if(world.time < next_request) return - cooldown = 1 + next_request = world.time + 60 SECONDS //1 minute cooldown to_chat(usr, "Your request has been recieved by Centcom.") log_admin("[key_name(usr)] requested to move the transport ferry to Centcom.") message_admins("FERRY: [key_name_admin(usr)] (Move Ferry) is requesting to move the transport ferry to Centcom.") - . = 1 - SSnanoui.update_uis(src) - spawn(600) //One minute cooldown - cooldown = 0 + return TRUE + /obj/machinery/computer/shuttle/white_ship name = "White Ship Console" diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index f9ec738b167..1ff2959ff08 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -11,20 +11,18 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF flags = NODECONSTRUCT var/challenge = FALSE - var/moved = FALSE /obj/machinery/computer/shuttle/syndicate/recall name = "syndicate shuttle recall terminal" circuit = /obj/item/circuitboard/shuttle/syndicate/recall possible_destinations = "syndicate_away" -/obj/machinery/computer/shuttle/syndicate/Topic(href, href_list) - if(href_list["move"]) +/obj/machinery/computer/shuttle/syndicate/can_call_shuttle(user, action) + if(action == "move") if(challenge && world.time < SYNDICATE_CHALLENGE_TIMER) - to_chat(usr, "You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare.") - return 0 - moved = TRUE - ..() + to_chat(user, "You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare.") + return FALSE + return TRUE /obj/machinery/computer/shuttle/syndicate/drop_pod name = "syndicate assault pod control" @@ -35,11 +33,11 @@ shuttleId = "steel_rain" possible_destinations = null -/obj/machinery/computer/shuttle/syndicate/drop_pod/Topic(href, href_list) - if(href_list["move"]) +/obj/machinery/computer/shuttle/syndicate/drop_pod/can_call_shuttle(user, action) + if(action == "move") if(z != level_name_to_num(CENTCOMM)) - to_chat(usr, "Pods are one way!") - return 0 + to_chat(user, "Pods are one way!") + return FALSE ..() /obj/machinery/computer/shuttle/sst diff --git a/code/modules/station_goals/station_goal.dm b/code/modules/station_goals/station_goal.dm index 47f65ea2553..7f13651168b 100644 --- a/code/modules/station_goals/station_goal.dm +++ b/code/modules/station_goals/station_goal.dm @@ -13,7 +13,7 @@ /datum/station_goal/proc/send_report() GLOB.priority_announcement.Announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", 'sound/AI/commandreport.ogg') - print_command_report(get_report(), "Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]") + print_command_report(get_report(), "Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]", FALSE) on_report() /datum/station_goal/proc/on_report() diff --git a/code/modules/tgui/modules/ert_manager.dm b/code/modules/tgui/modules/ert_manager.dm new file mode 100644 index 00000000000..582d03f5a54 --- /dev/null +++ b/code/modules/tgui/modules/ert_manager.dm @@ -0,0 +1,100 @@ +/datum/tgui_module/ert_manager + name = "ERT Manager" + var/ert_type = "Red" + var/commander_slots = 1 // defaults for open slots + var/security_slots = 4 + var/medical_slots = 0 + var/engineering_slots = 0 + var/janitor_slots = 0 + var/paranormal_slots = 0 + var/cyborg_slots = 0 + +/datum/tgui_module/ert_manager/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_admin_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "ERTManager", name, 350, 430, master_ui, state) + ui.autoupdate = TRUE + ui.open() + +/datum/tgui_module/ert_manager/tgui_data(mob/user) + var/list/data = list() + data["str_security_level"] = capitalize(get_security_level()) + switch(GLOB.security_level) + if(SEC_LEVEL_GREEN) + data["security_level_color"] = "green" + if(SEC_LEVEL_BLUE) + data["security_level_color"] = "blue" + if(SEC_LEVEL_RED) + data["security_level_color"] = "red" + else + data["security_level_color"] = "purple" + data["ert_type"] = ert_type + data["com"] = commander_slots + data["sec"] = security_slots + data["med"] = medical_slots + data["eng"] = engineering_slots + data["jan"] = janitor_slots + data["par"] = paranormal_slots + data["cyb"] = cyborg_slots + data["total"] = commander_slots + security_slots + medical_slots + engineering_slots + janitor_slots + paranormal_slots + cyborg_slots + data["spawnpoints"] = GLOB.emergencyresponseteamspawn.len + return data + +/datum/tgui_module/ert_manager/tgui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("ert_type") + ert_type = params["ert_type"] + if("toggle_com") + commander_slots = commander_slots ? 0 : 1 + if("set_sec") + security_slots = text2num(params["set_sec"]) + if("set_med") + medical_slots = text2num(params["set_med"]) + if("set_eng") + engineering_slots = text2num(params["set_eng"]) + if("set_jan") + janitor_slots = text2num(params["set_jan"]) + if("set_par") + paranormal_slots = text2num(params["set_par"]) + if("set_cyb") + cyborg_slots = text2num(params["set_cyb"]) + if("dispatch_ert") + var/datum/response_team/D + switch(ert_type) + if("Amber") + D = new /datum/response_team/amber + if("Red") + D = new /datum/response_team/red + if("Gamma") + D = new /datum/response_team/gamma + else + to_chat(usr, "Invalid ERT type.") + return + GLOB.ert_request_answered = TRUE + var/slots_list = list() + if(commander_slots > 0) + slots_list += "commander: [commander_slots]" + if(security_slots > 0) + slots_list += "security: [security_slots]" + if(medical_slots > 0) + slots_list += "medical: [medical_slots]" + if(engineering_slots > 0) + slots_list += "engineering: [engineering_slots]" + if(janitor_slots > 0) + slots_list += "janitor: [janitor_slots]" + if(paranormal_slots > 0) + slots_list += "paranormal: [paranormal_slots]" + if(cyborg_slots > 0) + slots_list += "cyborg: [cyborg_slots]" + var/slot_text = english_list(slots_list) + notify_ghosts("An ERT is being dispatched. Open positions: [slot_text]") + message_admins("[key_name_admin(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]", 1) + log_admin("[key_name(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]") + GLOB.event_announcement.Announce("Attention, [station_name()]. We are attempting to assemble an ERT. Standby.", "ERT Protocol Activated") + trigger_armed_response_team(D, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) + else + return FALSE + diff --git a/icons/obj/food/containers.dmi b/icons/obj/food/containers.dmi index ff25b77ab45..ad31ac04998 100644 Binary files a/icons/obj/food/containers.dmi and b/icons/obj/food/containers.dmi differ diff --git a/nano/templates/brig_timer.tmpl b/nano/templates/brig_timer.tmpl deleted file mode 100644 index 2cd1ab73a23..00000000000 --- a/nano/templates/brig_timer.tmpl +++ /dev/null @@ -1,91 +0,0 @@ - -
-
- Cell: -
-
- {{:data.cell_id}} -
-
-
-
- Occupant: -
-
- {{:data.occupant}} -
-
-
-
- Crimes: -
-
- {{:data.crimes}} -
-
-
-
- Brigged By: -
-
- {{:data.brigged_by}} -
-
-
-
- Time Brigged For: -
-
- {{:data.time_set}} -
-
-
-
- Time Left: -
-
- {{:data.time_left}} -
-
-{{if data.isAllowed}} -
-
- Actions: -
-
- {{:helper.link('Flash', 'flash', {'flash' : 1}, null, data.isAllowed ? '' : 'dsabled')}} - {{:helper.link('Release', null, {'release' : 1}, null, data.isAllowed ? '' : 'disabled')}} -
-
- {{if !data.timing}} -

Inmate Information

-
-
- Name: -
-
- {{:helper.link('Set', 'pencil', {'prisoner_name' : 'input'})}} {{:data.prisoner_name}} -
-
-
-
- Charge: -
-
- {{:helper.link('Set', 'pencil', {'prisoner_charge' : 'input'})}} {{:data.prisoner_charge}} -
-
-
-
- Time (in minutes): -
-
- {{:helper.link('Set', 'pencil', {'prisoner_time' : 'input'})}} {{:data.prisoner_time}} -
-
- {{:helper.link('Submit', null, {'set_timer' : 1}, null, data.isAllowed ? '' : 'disabled')}} - {{/if}} -{{/if}} \ No newline at end of file diff --git a/nano/templates/comm_console.tmpl b/nano/templates/comm_console.tmpl deleted file mode 100644 index 2c36a011ac6..00000000000 --- a/nano/templates/comm_console.tmpl +++ /dev/null @@ -1,142 +0,0 @@ - - -{{if !data.authenticated}} -
Please swipe your ID card. {{:helper.link('Log In','unlock',{'login':1},null,'fixed')}}
-{{else}} - {{if !data.is_ai}} -
Please remember to {{:helper.link('Log Out','lock',{'logout':1},null,'fixed')}}
- {{/if}} - {{if data.lastCallLoc}} -
Most recent shuttle call/recall traced to: {{:data.lastCallLoc}}
- {{else}} -
Unable to trace most recent shuttle call/recall signal.
- {{/if}} -
-

Emergency Shuttle:

- {{if data.shuttle.eta}} -
ETA:
-
- {{>data.shuttle.eta}} -
- {{/if}} -
Options:
-
- {{if data.shuttle.callStatus == 1 && !data.is_ai}} - {{:helper.link('Cancel Shuttle','arrow-left',{'operation':'cancelshuttle'})}} - {{else data.shuttle.callStatus == 2}} - {{:helper.link('Call Shuttle','arrow-circle-down',{'operation':'callshuttle'})}} - {{/if}} -
-
- - {{if data.screen==1}} - -

Menu

-
- {{if data.authenticated==2}} -
- {{:helper.link('Make an Announcement','info',{'operation':'announce'})}} -
-
- {{if data.emagged}} - {{:helper.link('Message [UNKNOWN]','envelope',{'operation':'MessageSyndicate'})}} -
-
- {{:helper.link('Reset Relays','refresh',{'operation':'RestoreBackup'})}} - {{else}} - {{:helper.link('Message CentComm','envelope',{'operation':'MessageCentcomm'})}} - {{/if}} -
-
- {{:helper.link('Request Nuclear Authentication Codes','exclamation-triangle',{'operation':'nukerequest'})}} -
- {{/if}} -
- {{:helper.link('Change Alert Level','signal',{'operation':'changeseclevel'})}} -
-
- {{:helper.link('Change Status Displays','info',{'operation':'status'})}} -
-
- {{:helper.link('Message List','comment',{'operation':'messagelist'})}} -
-
- {{:helper.link('Restart Nano-Mob Hunter GO! Server','power-off',{'operation':'RestartNanoMob'})}} -
-
- {{else data.screen==2}} - -

Status Displays

- {{:helper.link('Back','home',{'operation':'main'})}} -

Presets

- {{for data.stat_display.presets}} -
-
{{:helper.link(value.label,'info',{'operation':'setstat','statdisp':value.name},null,(name==data.stat_display.type?'linkOn':''))}}
-
- {{/for}} -

Alerts

- {{for data.stat_display.alerts}} -
-
{{:helper.link(value.label,'exclamation-triangle',{'operation':'setstat','statdisp':'alert','alert':value.alert},null,(value.alert==data.stat_display.type?'linkOn':''))}}
-
- {{/for}} -

Messages

-
- {{if data.stat_display.type}} -
-
{{:helper.link('Line 1:','gear',{'operation':'setmsg1'})}}
-
{{>data.stat_display.line_1}}
-
-
-
{{:helper.link('Line 2:','gear',{'operation':'setmsg2'})}}
-
{{>data.stat_display.line_2}}
-
- {{/if}} -
- {{else data.screen==3}} - -

Messages

- {{if data.current_message}} - {{:helper.link('Messages','home',{'operation':'messagelist'})}} -

{{:data.current_message_title}}

-
- {{:data.current_message}} -
- {{else}} - {{:helper.link('Back','home',{'operation':'main'})}} - {{for data.messages}} -
- {{:value.title}}
- {{:helper.link('Open','envelope-o',{'operation':'messagelist','msgid':value.id})}} - {{:helper.link('Delete','close',{'operation':'delmessage','msgid':value.id})}} -
- {{/for}} - {{/if}} - {{else data.screen==4}} - -

Security Level

- {{:helper.link('Back','home',{'operation':'main'})}} -
-
-
Security Level:
-
{{>data.str_security_level}}
-
-
-
Presets:
-
- {{for data.levels}} - {{:helper.link(value.name,'comment',{'operation':'newalertlevel','level':value.id},null,(value.id==data.security_level?'linkOn':''))}} - {{/for}} -
-
-
- {{/if}} -{{/if}} \ No newline at end of file diff --git a/nano/templates/ert_config.tmpl b/nano/templates/ert_config.tmpl deleted file mode 100644 index c8ff0645b3b..00000000000 --- a/nano/templates/ert_config.tmpl +++ /dev/null @@ -1,75 +0,0 @@ -
- - - - - - -
Station Alert Level{{:data.alert_level}}
ERT Type - {{if data.ert_type == 'Code Amber'}} AMBER {{else}} {{:helper.link('Amber', null, {"set_code": 'Code Amber'})}} {{/if}} - {{if data.ert_type == 'Code Red'}} RED {{else}} {{:helper.link('Red', null, {"set_code": 'Code Red'})}} {{/if}} - {{if data.ert_type == 'Code Gamma'}} GAMMA {{else}} {{:helper.link('Gamma', null, {"set_code": 'Code Gamma'})}} {{/if}} -
-
-
-
- - - - - - - - - -
DepartmentSlotsChange Slots
Command{{if data.com == 0}}-{{else}}{{:helper.smoothRound(data.com)}}{{/if}} - {{:helper.link('0', null, {"set_com": 0})}} - {{:helper.link('1', null, {"set_com": 1})}}
Security{{if data.sec == 0}}-{{else}}{{:helper.smoothRound(data.sec)}}{{/if}} - {{:helper.link('0', null, {"set_sec": 0})}} - {{:helper.link('1', null, {"set_sec": 1})}} - {{:helper.link('2', null, {"set_sec": 2})}} - {{:helper.link('3', null, {"set_sec": 3})}} - {{:helper.link('4', null, {"set_sec": 4})}} - {{:helper.link('5', null, {"set_sec": 5})}} -
Medical{{if data.med == 0}}-{{else}}{{:helper.smoothRound(data.med)}}{{/if}} - {{:helper.link('0', null, {"set_med": 0})}} - {{:helper.link('1', null, {"set_med": 1})}} - {{:helper.link('2', null, {"set_med": 2})}} - {{:helper.link('3', null, {"set_med": 3})}} - {{:helper.link('4', null, {"set_med": 4})}} - {{:helper.link('5', null, {"set_med": 5})}} -
Engineering{{if data.eng == 0}}-{{else}}{{:helper.smoothRound(data.eng)}}{{/if}} - {{:helper.link('0', null, {"set_eng": 0})}} - {{:helper.link('1', null, {"set_eng": 1})}} - {{:helper.link('2', null, {"set_eng": 2})}} - {{:helper.link('3', null, {"set_eng": 3})}} - {{:helper.link('4', null, {"set_eng": 4})}} - {{:helper.link('5', null, {"set_eng": 5})}} -
Paranormal{{if data.par == 0}}-{{else}}{{:helper.smoothRound(data.par)}}{{/if}} - {{:helper.link('0', null, {"set_par": 0})}} - {{:helper.link('1', null, {"set_par": 1})}} - {{:helper.link('2', null, {"set_par": 2})}} - {{:helper.link('3', null, {"set_par": 3})}} - {{:helper.link('4', null, {"set_par": 4})}} - {{:helper.link('5', null, {"set_par": 5})}} -
Janitor{{if data.jan == 0}}-{{else}}{{:helper.smoothRound(data.jan)}}{{/if}} - {{:helper.link('0', null, {"set_jan": 0})}} - {{:helper.link('1', null, {"set_jan": 1})}} - {{:helper.link('2', null, {"set_jan": 2})}} - {{:helper.link('3', null, {"set_jan": 3})}} - {{:helper.link('4', null, {"set_jan": 4})}} - {{:helper.link('5', null, {"set_jan": 5})}} -
{{if data.ert_type == 'Code Gamma'}}GAMMA {{/if}}Cyborg{{if data.cyb == 0}}-{{else}}{{:helper.smoothRound(data.cyb)}}{{/if}} - {{:helper.link('0', null, {"set_cyb": 0})}} - {{:helper.link('1', null, {"set_cyb": 1})}} - {{:helper.link('2', null, {"set_cyb": 2})}} - {{:helper.link('3', null, {"set_cyb": 3})}} - {{:helper.link('4', null, {"set_cyb": 4})}} - {{:helper.link('5', null, {"set_cyb": 5})}} -
-
-
-
- {{:helper.link('Dispatch', null, {"dispatch_ert": 1})}} -
- diff --git a/nano/templates/faxmachine.tmpl b/nano/templates/faxmachine.tmpl deleted file mode 100644 index e52c40eb927..00000000000 --- a/nano/templates/faxmachine.tmpl +++ /dev/null @@ -1,67 +0,0 @@ - -
-

Authorization

-
-
-
- Confirm identity: -
-
- {{:helper.link(data.scan_name, 'eject', {'scan' : 1})}} -
-
-
-
- Authorize: -
-
- {{:helper.link(data.authenticated ? 'Log Out' : 'Log In', data.authenticated ? 'unlock' : 'lock', {'auth' : 1})}} -
-
-
-
-

Fax Menu

-
-
-
- Network: -
- -
- {{:data.network}} -
-
-
-
- Currently sending: -
-
- {{:helper.link(data.paper, 'eject', {'paper' : 1})}} - {{if data.paperinserted}} - {{:helper.link('Rename', 'pencil', {'rename' : 1})}} - {{/if}} -
-
-
-
- Sending to: -
-
- {{:helper.link(data.destination, 'print', {'dept' : 1}, !data.authenticated ? 'disabled' : '')}} -
-
-
-
- Action: -
-
- {{if data.authenticated}} - {{:helper.link(data.cooldown && data.respectcooldown ? "Realigning" : "Send", data.cooldown && data.respectcooldown ? 'clock-o' : "envelope-o", {'send' : 1}, data.cooldown && data.respectcooldown ? 'disabled' : "")}} - {{else}} - {{:helper.link(data.cooldown && data.respectcooldown ? "Realigning" : "Send", data.cooldown && data.respectcooldown ? 'clock-o' : "envelope-o", null, !data.authenticated ? 'disabled' : "")}} - {{/if}} -
-
\ No newline at end of file diff --git a/nano/templates/keycard_auth.tmpl b/nano/templates/keycard_auth.tmpl deleted file mode 100644 index 96a3f44f60a..00000000000 --- a/nano/templates/keycard_auth.tmpl +++ /dev/null @@ -1,39 +0,0 @@ - - -
-

Keycard Authentication Device

- This device is used to trigger certain high security events. It requires the simultaneous swipe of two high-level ID cards. -
- {{if data.screen == 1}} -

Trigger Event

- {{:helper.link('Red Alert', 'exclamation-triangle', { 'triggerevent' : 'Red Alert' })}} - {{:helper.link('Emergency Response Team', 'exclamation-triangle', { 'triggerevent' : 'Emergency Response Team' })}} - {{:helper.link('Grant Emergency Maintenance Access', 'unlock', { 'triggerevent' : 'Grant Emergency Maintenance Access' })}} - {{:helper.link('Revoke Emergency Maintenance Access', 'lock', { 'triggerevent' : 'Revoke Emergency Maintenance Access' })}} - {{:helper.link('Activate Station-Wide Emergency Access', 'unlock', { 'triggerevent' : 'Activate Station-Wide Emergency Access' })}} - {{:helper.link('Deactivate Station-Wide Emergency Access', 'lock', { 'triggerevent' : 'Deactivate Station-Wide Emergency Access' })}} - {{else data.screen == 2}} - {{if data.event == 'Emergency Response Team'}} -
-
Reason for ERT Call:
-
- {{:helper.link(data.ertreason, 'exclamation-triangle', { 'ert' : 'callreason' })}} -
-
- {{/if}} -

Please swipe your card to authorize the following event:

-
{{:data.event}}
- {{:helper.link('Back', 'close', { 'reset' : 1 })}} - {{/if}} -
-
\ No newline at end of file diff --git a/nano/templates/mech_bay_console.tmpl b/nano/templates/mech_bay_console.tmpl deleted file mode 100644 index 2a4cf5d6085..00000000000 --- a/nano/templates/mech_bay_console.tmpl +++ /dev/null @@ -1,55 +0,0 @@ -

Subsystems

-
-
- Power Port: -
-
- {{if data.recharge_port}} - OK - {{else}} - ERROR - {{/if}} -
-
-
-
- Mecha: -
-
- {{if data.has_mech}} - LOCATED ({{:data.mecha_name}}) - {{else}} - NONE - {{/if}} -
-
-{{if data.has_mech}} -

Charging

-
-
- Charge Level: -
-
- {{:helper.displayBar(data.mecha_charge_percentage, 0, 100)}} -
- {{:helper.smoothRound(data.mecha_charge_percentage)}}%
-
-
-
-
-
- Cell Rating: -
-
- {{:data.mecha_maxcharge}} -
-
-
-
- Cell Charge: -
-
- {{:helper.smoothRound(data.mecha_charge)}} -
-
-{{/if}} \ No newline at end of file diff --git a/nano/templates/robot_control.tmpl b/nano/templates/robot_control.tmpl deleted file mode 100644 index 6e97ffaf3d7..00000000000 --- a/nano/templates/robot_control.tmpl +++ /dev/null @@ -1,100 +0,0 @@ -{{if data.robots}} - {{if !data.is_ai}} -
-
- Emergency Self-Destruct: -
-
- {{if data.safety}} - {{:helper.link('ARM', 'unlock', {'arm' : 1}, !data.allowed ? 'disabled' : null)}} - {{:helper.link('DETONATE', 'exclamation-circle', {'nuke' : 1}, 'disabled')}} - {{else}} - {{:helper.link('DISARM', 'lock', {'arm' : 1}, !data.allowed ? 'disabled' : null)}} - {{:helper.link('DETONATE', 'exclamation-circle', {'nuke' : 1}, !data.allowed ? 'disabled' : null, 'redButton')}} - {{/if}} -
-
-
- {{/if}} - {{for data.robots}} -
-
-

{{:value.name}}

-

Information

- - Status: - - - {{:value.status}} - - - System Integrity: - - - {{:helper.smoothRound(value.health)}}% - - - Location: - - - ({{:value.xpos}}, {{:value.ypos}}, {{:value.zpos}}): {{:value.area}} - - - Master AI: - - - {{:value.master_ai}} - - - Module: - - - {{:value.module}} - - - {{if value.hackable}} - - Safeties: - - - ENABLED - - {{else value.hacked}} - - Safeties: - - - DISABLED - - {{/if}} -

Power Cell

- {{if value.cell}} - - Rating: - - - {{:value.cell_capacity}} - - {{:helper.displayBar(value.cell_percentage, 0, 100, (value.cell_percentage >= 50) ? 'good' : (value.cell_percentage >= 25) ? 'average' : 'bad')}} - {{:helper.smoothRound(value.cell_percentage)}}% - {{else}} - Not Installed - {{:helper.displayBar(100, 0, 100, 'bad')}} - {{/if}} -

Actions

- {{if value.status == "Operational"}} - {{:helper.link('Lockdown', 'lock', {'lockdown' : value.name}, !data.allowed ? 'disabled' : null)}} - {{else}} - {{:helper.link('Unlock', 'unlock', {'lockdown' : value.name}, !data.allowed ? 'disabled' : null)}} - {{/if}} - {{:helper.link('Self-Destruct', 'exclamation-circle', {'detonate' : value.name}, !data.allowed ? 'disabled' : null, 'redButton')}} - {{if value.hackable}} - {{:helper.link('Hack', 'calculator', {'hack' : value.name}, !data.allowed ? 'disabled' : null, 'redButton')}} - {{/if}} -
- {{/for}} -{{else}} -
-

No robots were found.

-
-{{/if}} \ No newline at end of file diff --git a/nano/templates/shuttle_console.tmpl b/nano/templates/shuttle_console.tmpl deleted file mode 100644 index 8277e92eb76..00000000000 --- a/nano/templates/shuttle_console.tmpl +++ /dev/null @@ -1,37 +0,0 @@ - - -
-
Location:
-
{{:data.status ? data.status : '*Missing*'}}
-
-{{if data.shuttle}} - {{if data.docking_ports_len}} -
-
- {{for data.docking_ports}} -
{{:helper.link('Send to ' + value.name, 'sign-out', {'move' : value.id})}}
- {{/for}} -
- {{else}} -
-
Status:
-
Shuttle locked - {{if data.admin_controlled}} - , authorized personnel only -
-
-
{{:helper.link('Request authorization', 'share-square-o', {'request' : 1})}}
- {{else}} - - -
- {{/if}} - {{/if}} - - {{if data.docking_request}} -
{{:helper.link('Request docking at the station', 'share-square-o', {'request' : 1})}}
- {{/if}} -{{/if}} diff --git a/nano/templates/smes.tmpl b/nano/templates/smes.tmpl deleted file mode 100644 index 2657c0f724e..00000000000 --- a/nano/templates/smes.tmpl +++ /dev/null @@ -1,89 +0,0 @@ -
-
- Stored Capacity: -
-
- {{:helper.displayBar(data.storedCapacity, 0, 100, data.charging ? 'good' : 'average')}} -
- {{:helper.smoothRound(data.storedCapacity)}}% -
-
-
- -

Input Management

-
-
- Charge Mode: -
-
- {{:helper.link('Auto', 'refresh', {'cmode' : 1}, data.chargeMode ? 'selected' : null)}}{{:helper.link('Off', 'close', {'cmode' : 1}, data.chargeMode ? null : 'selected')}} -   - {{if data.charging == 2}} - [Charging] - {{else data.charging == 1}} - [Partially Charging] - {{else}} - [Not Charging] - {{/if}} -
-
- -
-
- Input Level: -
-
- {{:helper.displayBar(data.chargeLevel, 0, data.chargeMax)}} -
- {{:helper.link('MIN', null, {'input' : 'min'}, (data.chargeLevel > 0) ? null : 'disabled')}} - {{:helper.link('SET', null, {'input' : 'set'}, null)}} - {{:helper.link('MAX', null, {'input' : 'max'}, (data.chargeLevel < data.chargeMax) ? null : 'disabled')}} -
 {{:data.chargeLevel}} W 
-
-
-
- -

Output Management

-
-
- Output Status: -
-
- {{:helper.link('Online', 'power-off', {'online' : 1}, data.outputOnline ? 'selected' : null)}}{{:helper.link('Offline', 'close', {'online' : 1}, data.outputOnline ? null : 'selected')}} -   - {{if data.outputting == 2}} - [Outputting] - {{else data.outputting == 1}} - [Stored energy too low] - {{else}} - [Not Outputting] - {{/if}} -
-
- -
-
- Output Level: -
-
- {{:helper.displayBar(data.outputLevel, 0, data.outputMax)}} -
- {{:helper.link('MIN', null, {'output' : 'min'}, (data.outputLevel > 0) ? null : 'disabled')}} - {{:helper.link('SET', null, {'output' : 'set'}, null)}} - {{:helper.link('MAX', null, {'output' : 'max'}, (data.outputLevel < data.outputMax) ? null : 'disabled')}} -
 {{:data.outputLevel}} W 
-
-
-
- -
-
- Output Load: -
-
- {{:helper.displayBar(data.outputLoad, 0, data.outputMax, (data.outputLoad < data.outputLevel) ? 'good' : 'average')}} -
- {{:helper.smoothRound(data.outputLoad)}} W -
-
-
\ No newline at end of file diff --git a/nano/templates/spawners_menu.tmpl b/nano/templates/spawners_menu.tmpl deleted file mode 100644 index c12490bbb60..00000000000 --- a/nano/templates/spawners_menu.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -
-

Mob Spawners

- - {{for data.spawners}} -
-
-

{{:value.name}}

-

{{:value.amount_left}} spawners left.

-
-
- {{:value.desc}} -
-
- {{:helper.link('Jump', null, {'action': 'jump', 'uid': value.uids}, null)}} - {{:helper.link('Spawn', null, {'action': 'spawn', 'uid': value.uids}, value.amount_left > 0 ? null : 'disabled')}} -
-
- {{/for}} -
-
diff --git a/nano/templates/transfer_valve.tmpl b/nano/templates/transfer_valve.tmpl deleted file mode 100644 index be64b5cc6f4..00000000000 --- a/nano/templates/transfer_valve.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -
-
- Attachment One: -
-
- {{if data.attachmentOne}} - {{:data.attachmentOne}} - {{else}} - None - {{/if}} - {{:helper.link('Remove', 'eject', {'tankone' : 1}, data.attachmentOne ? null : 'disabled')}} -
-
- -
-
- Attachment Two: -
-
- {{if data.attachmentTwo}} - {{:data.attachmentTwo}} - {{else}} - None - {{/if}} - {{:helper.link('Remove', 'eject', {'tanktwo' : 1}, data.attachmentTwo ? null : 'disabled')}} -
-
- -
-
- Valve Attachment: -
-
- {{if data.valveAttachment}} - {{:data.valveAttachment}} - {{else}} - None - {{/if}} - {{:helper.link('Remove', 'eject', {'rem_device' : 1}, data.valveAttachment ? null : 'disabled')}} - {{if data.valveAttachment}} - {{:helper.link('View', 'wrench', {'device' : 1})}} - {{/if}} -
-
- -
 
- -
-
- Valve Status: -
-
- {{:helper.link('Open', 'unlock', {'open' : 1}, (!data.attachmentOne || !data.attachmentTwo) ? 'disabled' : (data.valveOpen ? 'selected' : null))}}{{:helper.link('Close', 'lock', {'open' : 1}, (!data.attachmentOne || !data.attachmentTwo) ? 'disabled' : (data.valveOpen ? null : 'selected'))}} -
-
- diff --git a/nano/templates/vending_machine.tmpl b/nano/templates/vending_machine.tmpl deleted file mode 100644 index 1849e3e51d5..00000000000 --- a/nano/templates/vending_machine.tmpl +++ /dev/null @@ -1,68 +0,0 @@ - - -{{if data.mode == 0}} -

Items available

-
- {{for data.products}} -
-
- {{if value.price > 0}} - {{:helper.link('Buy (' + value.price + ')', 'shopping-cart', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}} - {{else}} - {{:helper.link('Vend', 'arrow-circle-down', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}} - {{/if}} -
-
- {{if value.color}}{{:value.name}} - {{else}}{{:value.name}} - {{/if}} - ({{:value.amount ? value.amount : "NONE LEFT"}}) -
-
- {{empty}} - No items available! - {{/for}} -
-{{if data.coin}} -

Coin

-
-
Coin deposited:
-
{{:helper.link(data.coin, 'eject', {'remove_coin' : 1})}}
-
-{{/if}} -{{if data.item_slot == 1}} -

Item Slot

-
-
Item Slot:
- {{if data.inserted_item}} -
{{:helper.link(data.inserted_item, 'eject', {'remove_item' : 1})}}
- {{else}} -
Empty
- {{/if}} -
-{{/if}} -{{else data.mode == 1}} -

Item selected

-
-
-
Item selected:
{{:data.product}}
-
Charge:
{{:data.price}}
-
-
- {{if data.message_err}} {{/if}} {{:data.message}} -
-
- {{:helper.link('Pay', 'shopping-cart', {'pay' : 1})}} - {{:helper.link('Cancel', 'arrow-left', {'cancelpurchase' : 1})}} -
-
-{{/if}} -{{if data.panel}} -

Maintenance panel

-
-
Speaker
{{:helper.link(data.speaker ? 'Enabled' : 'Disabled', 'gear', {'togglevoice' : 1})}}
-
-{{/if}} \ No newline at end of file diff --git a/paradise.dme b/paradise.dme index 6e1235bfc86..5222b6b0067 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2082,7 +2082,6 @@ #include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\revelation.dm" #include "code\modules\modular_computers\file_system\programs\command\card.dm" -#include "code\modules\modular_computers\file_system\programs\command\comms.dm" #include "code\modules\modular_computers\file_system\programs\engineering\power_monitor.dm" #include "code\modules\modular_computers\file_system\programs\engineering\sm_monitor.dm" #include "code\modules\modular_computers\file_system\programs\generic\configurator.dm" @@ -2121,7 +2120,6 @@ #include "code\modules\nano\interaction\self.dm" #include "code\modules\nano\interaction\zlevel.dm" #include "code\modules\nano\modules\atmos_control.dm" -#include "code\modules\nano\modules\ert_manager.dm" #include "code\modules\nano\modules\human_appearance.dm" #include "code\modules\nano\modules\law_manager.dm" #include "code\modules\nano\modules\nano_module.dm" @@ -2461,6 +2459,7 @@ #include "code\modules\tgui\tgui.dm" #include "code\modules\tgui\modules\_base.dm" #include "code\modules\tgui\modules\crew_monitor.dm" +#include "code\modules\tgui\modules\ert_manager.dm" #include "code\modules\tgui\states\admin.dm" #include "code\modules\tgui\states\always.dm" #include "code\modules\tgui\states\conscious.dm" diff --git a/sound/machines/machine_vend.ogg b/sound/machines/machine_vend.ogg new file mode 100644 index 00000000000..92867a1f3d3 Binary files /dev/null and b/sound/machines/machine_vend.ogg differ diff --git a/tgui/packages/tgui/interfaces/BrigTimer.js b/tgui/packages/tgui/interfaces/BrigTimer.js new file mode 100644 index 00000000000..5895b333c9c --- /dev/null +++ b/tgui/packages/tgui/interfaces/BrigTimer.js @@ -0,0 +1,123 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Button, LabeledList, Dropdown, Box, Section } from '../components'; +import { Window } from '../layouts'; + +export const BrigTimer = (props, context) => { + const { act, data } = useBackend(context); + data.nameText = data.occupant; + if (data.timing) { + if (data.prisoner_hasrec) { + data.nameText = ({data.occupant}); + } else { + data.nameText = ({data.occupant}); + } + } + let nameIcon = "pencil-alt"; + if (data.prisoner_name) { + if (!data.prisoner_hasrec) { + nameIcon = "exclamation-triangle"; + } + } + let nameOptions = []; + let i = 0; + for (i = 0; i < data.spns.length; i++) { + nameOptions.push(data.spns[i]); + } + return ( + + +
+ + + {data.cell_id} + + + {data.nameText} + + + {data.crimes} + + + {data.brigged_by} + + + {data.time_set} + + + {data.time_left} + + + +
+ {!data.timing && ( +
+ + +
+ )} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/CommunicationsComputer.js b/tgui/packages/tgui/interfaces/CommunicationsComputer.js new file mode 100644 index 00000000000..238ef3dfc6d --- /dev/null +++ b/tgui/packages/tgui/interfaces/CommunicationsComputer.js @@ -0,0 +1,315 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Button, LabeledList, Box, Section } from '../components'; +import { Window } from '../layouts'; + +export const CommunicationsComputer = (props, context) => { + const { act, data } = useBackend(context); + + let authReadable; + if (!data.authenticated) { + authReadable = "Not Logged In"; + } else if (data.is_ai) { + authReadable = "AI"; + } else if (data.authenticated === 1) { + authReadable = "Command"; + } else if (data.authenticated === 2) { + authReadable = "Captain"; + } else { + authReadable = "ERROR: Report This Bug!"; + } + let reportText = "View (" + data.messages.length + ")"; + let authBlock = ( + +
+ + {data.is_ai && ( + + AI + + ) || ( + +
+
+ + {!!data.esc_status && ( + + {data.esc_status} + + )} + {!!data.esc_callable && ( + +
+
+ ); + let announceText = "Make Priority Announcement"; + if (data.msg_cooldown > 0) { + announceText += " (" + data.msg_cooldown + "s)"; + } + let ccMessageText = data.emagged ? "Message [UNKNOWN]" : "Message CentComm"; + let nukeRequestText = "Request Authentication Codes"; + if (data.cc_cooldown > 0) { + ccMessageText += " (" + data.cc_cooldown + "s)"; + nukeRequestText += " (" + data.cc_cooldown + "s)"; + } + let alertLevelText = data.str_security_level; + let alertLevelButtons = data.levels.map(slevel => { + return ( + + }> + + {capacityPercent >= 100 && 'Fully Charged' + || inputting && 'Charging' + || 'Not Charging'} + + + + + + + }> + + {outputting + ? 'Sending' + : charge > 0 + ? 'Not Sending' + : 'No Charge'} + + + + + +