From bfa2300918ad2abec88f2f2503a4c55ee16b5304 Mon Sep 17 00:00:00 2001 From: meemofcourse <75212565+meemofcourse@users.noreply.github.com> Date: Sun, 21 Jan 2024 01:47:30 -0300 Subject: [PATCH 01/14] requests manager https://github.com/BeeStation/BeeStation-Hornet/pull/9408, https://github.com/BeeStation/BeeStation-Hornet/pull/9236 --- code/__DEFINES/admin.dm | 2 + code/_globalvars/lists/faxes.dm | 26 -- code/_globalvars/lists/objects.dm | 1 + .../circuitboards/machine_circuitboards.dm | 1 - code/modules/admin/admin_fax_panel.dm | 145 ++++++++ code/modules/admin/admin_verbs.dm | 6 +- code/modules/admin/topic.dm | 8 +- code/modules/admin/verbs/fax_manager.dm | 9 - code/modules/admin/verbs/pray.dm | 8 +- code/modules/admin/verbs/requests.dm | 7 + code/modules/client/client_procs.dm | 2 + code/modules/paperwork/fax.dm | 192 ++++++----- code/modules/paperwork/fax_manager.dm | 154 --------- code/modules/paperwork/paper.dm | 7 +- code/modules/requests/request.dm | 37 ++ code/modules/requests/requests_manager.dm | 249 ++++++++++++++ shiptest.dme | 7 +- tgui/packages/tgui/interfaces/AdminFax.js | 200 +++++++++++ tgui/packages/tgui/interfaces/Fax.tsx | 96 ++---- tgui/packages/tgui/interfaces/FaxManager.tsx | 317 ------------------ .../tgui/interfaces/RequestManager.js | 151 +++++++++ 21 files changed, 965 insertions(+), 660 deletions(-) delete mode 100644 code/_globalvars/lists/faxes.dm create mode 100644 code/modules/admin/admin_fax_panel.dm delete mode 100644 code/modules/admin/verbs/fax_manager.dm create mode 100644 code/modules/admin/verbs/requests.dm delete mode 100644 code/modules/paperwork/fax_manager.dm create mode 100644 code/modules/requests/request.dm create mode 100644 code/modules/requests/requests_manager.dm create mode 100644 tgui/packages/tgui/interfaces/AdminFax.js delete mode 100644 tgui/packages/tgui/interfaces/FaxManager.tsx create mode 100644 tgui/packages/tgui/interfaces/RequestManager.js diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 1adec75b74ac..44f0893cd9a5 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -67,6 +67,8 @@ #define ADMIN_COORDJMP(src) "[src ? "[COORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]" #define ADMIN_VERBOSEJMP(src) "[src ? "[AREACOORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]" #define ADMIN_INDIVIDUALLOG(user) "(LOGS)" +/// Displays "(SHOW)" in the chat, when clicked it tries to show atom(paper). First you need to set the request_state variable to TRUE for the paper. +#define ADMIN_SHOW_PAPER(atom) "(SHOW)" #define ADMIN_PUNISHMENT_BREAK_BONES "Break all bones" #define ADMIN_PUNISHMENT_LIGHTNING "Lightning bolt" diff --git a/code/_globalvars/lists/faxes.dm b/code/_globalvars/lists/faxes.dm deleted file mode 100644 index 5c78629de283..000000000000 --- a/code/_globalvars/lists/faxes.dm +++ /dev/null @@ -1,26 +0,0 @@ -/** - * This defines the list of faxes managed by the server administrators. They are not physically present in - * the game, but are shown in the fax list as existing. - * Lists: - * * additional_faxes_list - A list of "legal" faxes available with authorization. - * * frontier_faxes_list - List of faxes available after hacking. - * - * The list consists of the following elements: - * * fax_name - The name displayed in the fax list. - * * button_color - The color of this fax button in the list of all faxes. - */ -GLOBAL_LIST_INIT(additional_faxes_list, list( - list("fax_name" = "Nanotrasen Central Command", "button_color" = "#46B946"), - list("fax_name" = "Inteq Management Field Command", "button_color" = "#FACE65"), - list("fax_name" = "Colonial Minutemen Headquarters", "button_color" = "#538ACF"), - list("fax_name" = "Saint-Roumain Council of Huntsmen", "button_color" = "#6B443D"), - list("fax_name" = "SolGov Department of Administrative Affairs", "button_color" = "#536380"), - list("fax_name" = "Syndicate Coordination Center", "button_color" = "#B22C20"), - list("fax_name" = "Outpost Administration", "button_color" = "#dddfc9"), -)) - -GLOBAL_LIST_INIT(frontier_faxes_list, list( - list("fax_name" = "Frontiersmen Communications Outpost", "button_color" = "#70654C") -)) - -GLOBAL_LIST_EMPTY(fax_machines) //list of all fax machines diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 82258dfdcd43..ac54c7a39b33 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -11,6 +11,7 @@ GLOBAL_LIST_EMPTY(wayfindingbeacons) //list of all navigation beacons used GLOBAL_LIST_EMPTY(nuke_list) GLOBAL_LIST_EMPTY(alarmdisplay) //list of all machines or programs that can display station alerts GLOBAL_LIST_EMPTY(singularities) //list of all singularities on the station (actually technically all engines) +GLOBAL_LIST_EMPTY(fax_machines) //list of all fax machines GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction datums. Used during chemical reactions GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index faa366f893b0..662051554e9b 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -687,7 +687,6 @@ name = "Fax Machine" build_path = /obj/machinery/fax req_components = list( - /obj/item/stock_parts/subspace/crystal = 1, /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/micro_laser = 1, /obj/item/stock_parts/manipulator = 1,) diff --git a/code/modules/admin/admin_fax_panel.dm b/code/modules/admin/admin_fax_panel.dm new file mode 100644 index 000000000000..746d3b2421af --- /dev/null +++ b/code/modules/admin/admin_fax_panel.dm @@ -0,0 +1,145 @@ +/** + * If client have R_ADMIN flag, opens an admin fax panel. + */ +/client/proc/fax_panel() + set name = "Send Fax Message" + set category = "Admin" + + if(!check_rights(R_ADMIN)) + return + + var/datum/fax_panel_interface/ui = new(usr) + ui.ui_interact(usr) + +/// Admin Fax Panel. Tool for sending fax messages faster. +/datum/fax_panel_interface + /// All faxes in from machinery list() + var/available_faxes = list() + /// List with available stamps + var/stamp_list = list() + + /// Paper which admin edit and send. + var/obj/item/paper/fax_paper = new /obj/item/paper(null) + + /// Default name of fax. Used when field with fax name not edited. + var/sending_fax_name = "Secret" + /// Default name of paper. paper - bluh-bluh. Used when field with paper name not edited. + var/default_paper_name = "Standard Report" + +/datum/fax_panel_interface/New() + //Get all faxes, and save them to our list. + for(var/obj/machinery/fax/fax as anything in GLOB.fax_machines) + available_faxes += WEAKREF(fax) + + //Get all stamps + for(var/stamp in subtypesof(/obj/item/stamp)) + var/obj/item/stamp/real_stamp = new stamp() + if(!istype(real_stamp, /obj/item/stamp/chameleon)) + var/stamp_detail = real_stamp.get_writing_implement_details() + stamp_list += list(list(real_stamp.name, real_stamp.icon_state, stamp_detail["stamp_class"])) + + //Give our paper special status, to read everywhere. + fax_paper.request_state = TRUE + +/** + * Return fax if name exists + * Arguments: + * * name - Name of fax what we try to find. + */ +/datum/fax_panel_interface/proc/get_fax_by_name(name) + if(!length(available_faxes)) + return null + + for(var/datum/weakref/weakrefed_fax as anything in available_faxes) + var/obj/machinery/fax/potential_fax = weakrefed_fax.resolve() + if(potential_fax && istype(potential_fax)) + if(potential_fax.fax_name == name) + return potential_fax + return null + +/datum/fax_panel_interface/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AdminFax") + ui.open() + +/datum/fax_panel_interface/ui_state(mob/user) + return GLOB.admin_state + +/datum/fax_panel_interface/ui_static_data(mob/user) + var/list/data = list() + + data["faxes"] = list() + data["stamps"] = list() + + for(var/stamp in stamp_list) + data["stamps"] += list(stamp[1]) // send only names. + + for(var/datum/weakref/weakrefed_fax as anything in available_faxes) + var/obj/machinery/fax/another_fax = weakrefed_fax.resolve() + if(another_fax && istype(another_fax)) + data["faxes"] += list(another_fax.fax_name) + + return data + +/datum/fax_panel_interface/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return + + if(!check_rights(R_ADMIN)) + return + + var/obj/machinery/fax/action_fax + + if(params["faxName"]) + action_fax = get_fax_by_name(params["faxName"]) + + switch(action) + + if("follow") + if(!isobserver(usr)) + usr.client?.admin_ghost() + + usr.client?.holder?.admin_follow(action_fax) + + if("preview") // see saved variant + if(!fax_paper) + return + fax_paper.ui_interact(usr) + + if("save") // save paper + if(params["paperName"]) + default_paper_name = params["paperName"] + if(params["fromWho"]) + sending_fax_name = params["fromWho"] + + fax_paper.clear_paper() + var/stamp + var/stamp_class + + for(var/needed_stamp in stamp_list) + if(needed_stamp[1] == params["stamp"]) + stamp = needed_stamp[2] + stamp_class = needed_stamp[3] + break + + fax_paper.name = "paper — [default_paper_name]" + fax_paper.add_raw_text(params["rawText"]) + + if(stamp) + fax_paper.add_stamp(stamp_class, params["stampX"], params["stampY"], params["stampAngle"], stamp) + + fax_paper.update_static_data(usr) // OK, it's work, and update UI. + + if("send") + //copy + var/obj/item/paper/our_fax = fax_paper.copy(/obj/item/paper) + our_fax.name = fax_paper.name + //send + action_fax.receive(our_fax, sending_fax_name, important = TRUE) + message_admins("[key_name_admin(usr)] has sent a custom fax message to [action_fax.name][ADMIN_FLW(action_fax)][ADMIN_SHOW_PAPER(fax_paper)].") + log_admin("[key_name(usr)] has sent a custom fax message to [action_fax.name]") + + if("createPaper") + var/obj/item/paper/our_paper = fax_paper.copy(/obj/item/paper, usr.loc) + our_paper.name = fax_paper.name diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 929cf33f3315..a853f66963af 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -26,7 +26,9 @@ GLOBAL_PROTECT(admin_verbs_default) /client/proc/resetasaycolor, /client/proc/fix_air, /*resets air in designated radius to its default atmos composition*/ /client/proc/addbunkerbypass, - /client/proc/revokebunkerbypass + /client/proc/revokebunkerbypass, + /client/proc/requests, + /client/proc/fax_panel, /*send a paper to fax*/ ) GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin()) GLOBAL_PROTECT(admin_verbs_admin) @@ -119,7 +121,6 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/polymorph_all, /client/proc/show_tip, /client/proc/smite, - /client/proc/fax_manager, /client/proc/spawn_ruin, )) GLOBAL_PROTECT(admin_verbs_fun) @@ -283,7 +284,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( /client/proc/cmd_display_del_log, /client/proc/toggle_combo_hud, /client/proc/debug_huds, - /client/proc/fax_manager )) GLOBAL_PROTECT(admin_verbs_hideable) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index bb46d7250b0b..b917501d0bb8 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2218,10 +2218,14 @@ return GLOB.interviews.ui_interact(usr) - else if(href_list["open_fax_manager"]) + else if(href_list["show_paper"]) if(!check_rights(R_ADMIN)) return - usr.client.fax_manager() + + var/obj/item/paper/paper_to_show = locate(href_list["show_paper"]) + if(!istype(paper_to_show)) + return + paper_to_show.ui_interact(usr) /datum/admins/proc/HandleCMode() if(!check_rights(R_ADMIN)) diff --git a/code/modules/admin/verbs/fax_manager.dm b/code/modules/admin/verbs/fax_manager.dm deleted file mode 100644 index 6c6de9d5d100..000000000000 --- a/code/modules/admin/verbs/fax_manager.dm +++ /dev/null @@ -1,9 +0,0 @@ -/client/proc/fax_manager() - set category = "Fun" - set name = "Fax Manager" - set desc = "Open the manager panel to view all requests during the round in progress." - if(!check_rights(R_ADMIN)) - return - - SSblackbox.record_feedback("tally", "admin_verb", 1, "Fax Manager") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - GLOB.fax_manager.ui_interact(usr) diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 05dccfc0ca75..c2be9649d7c3 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -44,23 +44,21 @@ deity = "Ashen Hunter" var/msg_tmp = msg + GLOB.requests.pray(usr.client, msg, usr.job == "Chaplain") msg = "[icon2html(cross, GLOB.admins)][prayer_type][deity ? " (to [deity])" : ""]: [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]: [msg]" for(var/client/C in GLOB.admins) if(C.prefs.chat_toggles & CHAT_PRAYER) to_chat(C, msg, confidential = TRUE) - if(C.prefs.toggles & SOUND_PRAYERS) - if(usr.job == "Chaplain") - SEND_SOUND(C, sound('sound/effects/pray.ogg')) to_chat(usr, "You pray to the gods: \"[msg_tmp]\"", confidential = TRUE) SSredbot.send_discord_message("admin", "Prayer from [src.key]/([src.name]): [msg]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Prayer") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - //log_admin("HELP: [key_name(src)]: [msg]") /// Used by communications consoles to message CentCom /proc/message_centcom(text, mob/sender) var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN) + GLOB.requests.message_centcom(sender.client, msg) msg = "CENTCOM:[ADMIN_FULLMONTY(sender)] [ADMIN_CENTCOM_REPLY(sender)]: [msg]" to_chat(GLOB.admins, msg, confidential = TRUE) for(var/obj/machinery/computer/communications/console in GLOB.machines) @@ -69,6 +67,7 @@ /// Used by communications consoles to message the Syndicate /proc/message_syndicate(text, mob/sender) var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN) + GLOB.requests.message_syndicate(sender.client, msg) msg = "SYNDICATE:[ADMIN_FULLMONTY(sender)] [ADMIN_SYNDICATE_REPLY(sender)]: [msg]" to_chat(GLOB.admins, msg, confidential = TRUE) for(var/obj/machinery/computer/communications/console in GLOB.machines) @@ -77,6 +76,7 @@ /// Used by communications consoles to request the nuclear launch codes /proc/nuke_request(text, mob/sender) var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN) + GLOB.requests.nuke_request(sender.client, msg) msg = "NUKE CODE REQUEST:[ADMIN_FULLMONTY(sender)] [ADMIN_CENTCOM_REPLY(sender)] [ADMIN_SET_SD_CODE]: [msg]" to_chat(GLOB.admins, msg, confidential = TRUE) for(var/obj/machinery/computer/communications/console in GLOB.machines) diff --git a/code/modules/admin/verbs/requests.dm b/code/modules/admin/verbs/requests.dm new file mode 100644 index 000000000000..94aa976dbd1a --- /dev/null +++ b/code/modules/admin/verbs/requests.dm @@ -0,0 +1,7 @@ +/// Verb for opening the requests manager panel +/client/proc/requests() + set name = "Requests Manager" + set desc = "Open the request manager panel to view all requests during this round" + set category = "Admin" + SSblackbox.record_feedback("tally", "admin_verb", 1, "Request Manager") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + GLOB.requests.ui_interact(usr) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 06d96d7229cc..8db2e8454828 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -231,6 +231,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( GLOB.ahelp_tickets.client_login(src) GLOB.interviews.client_login(src) + GLOB.requests.client_login(src) var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins. //Admin Authorisation holder = GLOB.admin_datums[ckey] @@ -501,6 +502,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( log_access("Logout: [key_name(src)]") GLOB.ahelp_tickets.client_logout(src) GLOB.interviews.client_logout(src) + GLOB.requests.client_logout(src) SSserver_maint.UpdateHubStatus() if(credits) QDEL_LIST(credits) diff --git a/code/modules/paperwork/fax.dm b/code/modules/paperwork/fax.dm index b1696a27fca0..e370680703f3 100644 --- a/code/modules/paperwork/fax.dm +++ b/code/modules/paperwork/fax.dm @@ -18,10 +18,6 @@ var/seconds_electrified = MACHINE_NOT_ELECTRIFIED /// If true, the fax machine is jammed and needs cleaning var/jammed = FALSE - /// Determines the possibility of sending papers to the additional faxes. - var/access_additional_faxes = FALSE - /// Defines a list of accesses whose owners can open a connection with the additional faxes. - var/static/access_additional_faxes_required = list(ACCESS_HEADS, ACCESS_LAWYER, ACCESS_SECURITY) /// Necessary to hide syndicate faxes from the general list. Doesn't mean he's EMAGGED! var/frontier_network = FALSE /// True if the fax machine should be visible to other fax machines in general. @@ -53,6 +49,25 @@ /obj/item/holochip, /obj/item/card, ) + /// Internal radio for announcing over comms + var/obj/item/radio/radio + /// Radio channel to speak into + var/radio_channel + /// Cooldown for aformentioned radio, prevents radio spam + COOLDOWN_DECLARE(radio_cooldown) + + /// List with a fake-networks(not a fax actually), for request manager. + var/list/special_networks = list( + list(fax_name = "Nanotrasen Central Command", fax_id = "nanotrasen", color = "green", emag_needed = FALSE), + list(fax_name = "IRMG Mothership", fax_id = "inteq", color = "gold", emag_needed = FALSE), + list(fax_name = "Solarian Confederation Frontier Affairs", fax_id = "solgov", color = "teal", emag_needed = FALSE), + list(fax_name = "Roumain Council of Huntsmen", fax_id = "roumain", color = "brown", emag_needed = FALSE), + list(fax_name = "Colonial League Leadership", fax_id = "minutemen", color = "navy", emag_needed = FALSE), + list(fax_name = "Syndicate Coalition Coordination Center", fax_id = "syndicate", color = "red", emag_needed = FALSE), + list(fax_name = "Frontiersmen Communications Quartermaster", fax_id = "frontiersmen", color = "black") + ) + // should we make our message be important and be recieved in admin faxes + var/admin_fax_id /obj/machinery/fax/Initialize(mapload) . = ..() @@ -63,10 +78,29 @@ fax_name = "[get_area_name(src)] Fax Machine" wires = new /datum/wires/fax(src) + radio = new(src) + radio.subspace_transmission = TRUE + radio.canhear_range = 0 + // Override in subtypes // no + radio.on = TRUE + + // Mapping Error checking + if(!mapload) + return + for(var/obj/machinery/fax/fax as anything in GLOB.fax_machines) + if(fax == src) // skip self + continue + if(fax.fax_name == fax_name) + fax_name = "Unregistered Fax Machine " + fax_id + CRASH("Duplicate fax_name [fax.fax_name] detected! Loc 1 [AREACOORD(src)]; Loc 2 [AREACOORD(fax)]; Falling back on random names.") + +/obj/machinery/fax/ruin + visible_to_network = FALSE + fax_name = "Unregistered Fax Machine " + fax_id + /obj/machinery/fax/hacked set_obj_flags = "EMAGGED" allow_exotic_faxes = TRUE - access_additional_faxes = TRUE /obj/machinery/fax/frontiersmen frontier_network = TRUE @@ -113,6 +147,20 @@ obj_flags |= EMAGGED to_chat(user, "The screen of the [src] flickers!") +/** + * EMP Interaction + */ +/obj/machinery/fax/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + allow_exotic_faxes = !allow_exotic_faxes + visible_message("[src] [allow_exotic_faxes ? "starts beeping" : "stops beeping"] ominously[allow_exotic_faxes ? "..." : "."]") + +/** + * Unanchor/anchor + */ + /obj/machinery/fax/wrench_act(mob/living/user, obj/item/tool) . = ..() default_unfasten_wrench(user, tool) @@ -161,27 +209,6 @@ return return ..() -// Checks if the card has access to switch "legal" faxes of administrators. -/obj/machinery/fax/proc/access_additional_faxes_check(mob/living/user) - if(isAdminObserver(user)) - return TRUE - - var/obj/item/card/id/used_card = user.get_idcard(TRUE) - if(used_card) - // We check if it makes sense to check access at all. - if(!access_additional_faxes_required || !used_card.access) - return FALSE - - for(var/requested_access in access_additional_faxes_required) - if(requested_access in used_card.access) - return TRUE - return FALSE - -// Switches access to the "legal" administrator's fax list. Access to the "illegal" is switched by hacking. -/obj/machinery/fax/proc/access_additional_faxes_toggle() - access_additional_faxes = !access_additional_faxes - say("Bluespace channel communication [access_additional_faxes ? "opened" : "closed"].") - /** * Attempts to clean out a jammed machine using a passed item. * Returns true if successful. @@ -237,12 +264,6 @@ ui.open() ui.set_autoupdate(TRUE) -/obj/machinery/fax/ui_static_data(mob/user) - var/list/data = list() - data["additional_faxes_list"] = GLOB.additional_faxes_list - data["frontier_faxes_list"] = GLOB.frontier_faxes_list - return data - /obj/machinery/fax/ui_data(mob/user) var/list/data = list() //Record a list of all existing faxes. @@ -264,12 +285,11 @@ data["fax_id"] = fax_id data["fax_name"] = fax_name data["visible"] = visible_to_network - data["access_additional_faxes"] = access_additional_faxes - data["сan_switch_access"] = access_additional_faxes_check(user) // In this case, we don't care if the fax is hacked or in the syndicate's network. The main thing is to check the visibility of other faxes. data["frontier_network"] = (frontier_network || (obj_flags & EMAGGED)) data["has_paper"] = !!loaded_item_ref?.resolve() data["fax_history"] = fax_history + data["special_faxes"] = special_networks return data /obj/machinery/fax/ui_act(action, list/params) @@ -287,8 +307,6 @@ loaded_item_ref = null update_icon() return TRUE - if("access_additional_faxes_toggle") - access_additional_faxes_toggle() if("send") var/obj/item/loaded = loaded_item_ref?.resolve() if(!loaded) @@ -299,17 +317,31 @@ loaded_item_ref = null update_icon() return TRUE - if("send_to_additional_fax") - var/obj/item/loaded = loaded_item_ref?.resolve() - if(!loaded) + if("send_special") + var/obj/item/paper/fax_paper = loaded_item_ref?.resolve() + if(!fax_paper) + return + if(!istype(fax_paper)) + to_chat(usr, icon2html(src.icon, usr) + "ERROR: Failed to send fax.") return - if(istype(loaded, /obj/item/paper)) - if(send_to_additional_faxes(loaded, usr, params["name"], params["color"])) - loaded_item_ref = null - update_icon() - return TRUE - else - say("The destination fax blocks the reception of this item.") + + fax_paper.request_state = TRUE + fax_paper.loc = null + + INVOKE_ASYNC(src, PROC_REF(animate_object_travel), fax_paper, "fax_receive", find_overlay_state(fax_paper, "send")) + history_add("Send", params["name"]) + + GLOB.requests.fax_request(usr.client, "sent a fax message from [fax_name]/[fax_id] to [params["name"]]", fax_paper) + to_chat(GLOB.admins, "[icon2html(src.icon, GLOB.admins)]FAX REQUEST: [ADMIN_FULLMONTY(usr)]: sent a fax message from [fax_name]/[fax_id][ADMIN_FLW(src)] to [html_encode(params["name"])] [ADMIN_SHOW_PAPER(fax_paper)]") + log_fax(fax_paper, params["id"], params["name"]) + loaded_item_ref = null + + for(var/obj/machinery/fax/fax as anything in GLOB.fax_machines) + if(fax.admin_fax_id == params["id"]) + fax.receive(fax_paper, fax_name) + break + update_appearance() + if("history_clear") history_clear() return TRUE @@ -349,40 +381,12 @@ balloon_alert(usr, "destination port jammed") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, -9) return FALSE - fax.receive(loaded, fax_name) - playback_sending(loaded, fax.fax_name) + fax.receive(loaded, fax_name, important = admin_fax_id) + history_add("Send", fax.fax_name) + INVOKE_ASYNC(src, PROC_REF(animate_object_travel), loaded, "fax_receive", find_overlay_state(loaded, "send")) return TRUE return FALSE -/** - * The procedure for sending a item to virtual admins fax machine. - * - * This procedure is similar to the send procedure except that it sends the item to - * a "virtual" fax to a special administrator list. - * Arguments: - * * loaded - The item to be sent. - * * sender - Reference to the sender's substance. - * * receiver_name - The recipient's fax name, which will be displayed in the administrator's list. - * * receiver_color - The color the receiver_name will be colored in. - */ -/obj/machinery/fax/proc/send_to_additional_faxes(obj/item/loaded, mob/sender, receiver_name, receiver_color) - GLOB.fax_manager.receive_request(sender, src, receiver_name, loaded, receiver_color) - playback_sending(loaded, receiver_name) - log_fax(loaded, "ADDITIONAL", receiver_name) - return TRUE - -/** - * The procedure for playing the animation. - * - * Procedure called to add to the history of sending messages, playing the sending animation. - * Arguments: - * * loaded - Sending item to determine the animation.. - * * receiver_name - Recipient's name to be added to the message history. - */ -/obj/machinery/fax/proc/playback_sending(obj/item/loaded, receiver_name) - history_add("Send", receiver_name) - INVOKE_ASYNC(src, PROC_REF(animate_object_travel), loaded, "fax_receive", find_overlay_state(loaded, "send")) - /** * Procedure for accepting papers from another fax machine. * @@ -391,7 +395,7 @@ * * loaded - The object to be printed. * * sender_name - The sender's name, which will be displayed in the message and recorded in the history of operations. */ -/obj/machinery/fax/proc/receive(obj/item/loaded, sender_name) +/obj/machinery/fax/proc/receive(obj/item/loaded, sender_name, important = FALSE) playsound(src, 'sound/items/poster_being_created.ogg', 20, FALSE) INVOKE_ASYNC(src, PROC_REF(animate_object_travel), loaded, "fax_receive", find_overlay_state(loaded, "receive")) say("Received correspondence from [sender_name].") @@ -504,3 +508,35 @@ do_sparks(5, TRUE, src) var/check_range = TRUE return electrocute_mob(user, get_area(src), src, 0.7, check_range) + +/obj/machinery/fax/admin + name = "Central Command Fax Machine" + fax_name = "Central Command" + radio_channel = RADIO_CHANNEL_CENTCOM + visible_to_network = FALSE + admin_fax_id = "nanotrasen" + +/obj/machinery/fax/admin/syndicate + name = "Syndicate Coordination Fax Machine" + fax_name = "Syndicate Coordination Center" + admin_fax_id = "syndicate" + +/obj/machinery/fax/admin/inteq + name = "IRMG Fax Machine" + fax_name = "IRMG Mothership" + admin_fax_id = "inteq" + +/obj/machinery/fax/admin/minutemen + name = "CLIP HiComm Fax Machine" + fax_name = "Colonial League Leadership" + admin_fax_id = "minutemen" + +/obj/machinery/fax/admin/roumain + name = "Huntsman Council Fax Machine" + fax_name = "Saint-Roumain Council of Huntsmen" + admin_fax_id = "roumain" + +/obj/machinery/fax/admin/frontiersmen + name = "old fax machine" + fax_name = "Frontiersmen Communications Quartermaster" + admin_fax_id = "frontiersmen" diff --git a/code/modules/paperwork/fax_manager.dm b/code/modules/paperwork/fax_manager.dm deleted file mode 100644 index 0107e440bec2..000000000000 --- a/code/modules/paperwork/fax_manager.dm +++ /dev/null @@ -1,154 +0,0 @@ -GLOBAL_DATUM_INIT(fax_manager, /datum/fax_manager, new) - -/** - * Fax Request Manager - * - * In its functionality it is similar to the usual Request Manager, but respectively for faxes. - * This manager allows you to send faxes on behalf of certain virtual faxes to all existing faxes, - * as well as receive faxes in their name from the players. - */ -/datum/fax_manager - /// A list that contains faxes from players and other related information. You can view the filling of its fields in the procedure receive_request. - var/list/requests = list() - -/datum/fax_manager/Destroy(force, ...) - QDEL_LIST(requests) - return ..() - -/datum/fax_manager/ui_interact(mob/user, datum/tgui/ui = null) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "FaxManager") - ui.open() - ui.set_autoupdate(TRUE) - -/datum/fax_manager/ui_state(mob/user) - return GLOB.admin_state - -/datum/fax_manager/ui_static_data(mob/user) - var/list/data = list() - //Record additional faxes on a separate list - data["additional_faxes"] = GLOB.additional_faxes_list + GLOB.frontier_faxes_list - return data - -/datum/fax_manager/ui_data(mob/user) - var/list/data = list() - //Record a list of all existing faxes. - for(var/obj/machinery/fax/fax as anything in GLOB.fax_machines) - var/list/fax_data = list() - fax_data["fax_name"] = fax.fax_name - fax_data["fax_id"] = fax.fax_id - fax_data["frontier_network"] = fax.frontier_network - data["faxes"] += list(fax_data) - for(var/list/requested in requests) - var/list/request = list() - request["id_message"] = requested["id_message"] - request["time"] = requested["time"] - var/mob/sender = requested["sender"] - request["sender_name"] = sender.name - request["sender_fax_id"] = requested["sender_fax_id"] - request["sender_fax_name"] = requested["sender_fax_name"] - request["receiver_fax_name"] = requested["receiver_fax_name"] - data["requests"] += list(request) - return data - -/datum/fax_manager/ui_act(action, list/params) - . = ..() - if(.) - return - var/datum/admins/admin_datum = GLOB.admin_datums[usr.ckey] - - switch(action) - if("send") - for(var/obj/machinery/fax/fax as anything in GLOB.fax_machines) - if(fax.fax_id == params["fax_id"]) - var/obj/item/paper/paper = new() - paper.add_raw_text(params["message"]) - paper.update_appearance() - fax.receive(paper, params["fax_name"]) - return TRUE - if("flw_fax") - for(var/obj/machinery/fax/fax as anything in GLOB.fax_machines) - if(fax.fax_id == params["fax_id"]) - admin_datum.admin_follow(fax) - return TRUE - if("read_message") - var/list/request = get_request(params["id_message"]) - var/obj/item/paper/request/paper = request["paper"] - paper.ui_interact(usr) - return TRUE - if("flw") - var/list/request = get_request(params["id_message"]) - admin_datum.admin_follow(request["sender"]) - return TRUE - if("pp") - var/list/request = get_request(params["id_message"]) - usr.client.holder.show_player_panel(request["sender"]) - return TRUE - if("vv") - var/list/request = get_request(params["id_message"]) - usr.client.debug_variables(request["sender"]) - return TRUE - if("sm") - var/list/request = get_request(params["id_message"]) - usr.client.cmd_admin_subtle_message(request["sender"]) - return TRUE - if("logs") - var/list/request = get_request(params["id_message"]) - if(!ismob(request["sender"])) - to_chat(usr, "This can only be used on instances of type /mob.") - return TRUE - show_individual_logging_panel(request["sender"], null, null) - return TRUE - if("smite") - var/list/request = get_request(params["id_message"]) - if(!check_rights(R_FUN)) - to_chat(usr, "Insufficient permissions to smite, you require +FUN") - return TRUE - var/mob/living/carbon/human/H = request["sender"] - if (!H || !istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return TRUE - usr.client.smite(H) - return TRUE - -/datum/fax_manager/proc/get_request(id_message) - for(var/list/request in requests) - if(request["id_message"] == id_message) - return request - -/datum/fax_manager/proc/receive_request(mob/sender, obj/machinery/fax/sender_fax, receiver_fax_name, obj/item/paper/paper, receiver_color) - var/list/request = list() - var/obj/item/paper/request/message = new() - request["id_message"] = requests.len - request["time"] = game_timestamp() - request["sender"] = sender - request["sender_fax_id"] = sender_fax.fax_id - request["sender_fax_name"] = sender_fax.fax_name - request["receiver_fax_name"] = receiver_fax_name - message.copy_properties(paper) - request["paper"] = message - requests += list(request) - var/msg = "\"[sanitize(receiver_fax_name)]\" fax received a message from \"[sanitize(sender_fax.fax_name)]\" fax SENT BY [ADMIN_FULLMONTY(sender)] (Open Fax Manager)" - for(var/client/C in GLOB.admins) - if(C.prefs.chat_toggles & CHAT_PRAYER) - to_chat(C, msg) - for(var/client/admin in GLOB.admins) - if((admin.prefs.chat_toggles & CHAT_PRAYER) && (admin.prefs.toggles & SOUND_PRAYERS)) - SEND_SOUND(admin, sound('sound/items/poster_being_created.ogg')) - -// A special piece of paper for the administrator that will open the interface no matter what. -/obj/item/paper/request/ui_status() - return UI_INTERACTIVE - -// I'm sure there's a better way to transfer it, I just couldn't find it -/obj/item/paper/request/proc/copy_properties(obj/item/paper/paper) - raw_text_inputs = paper.raw_text_inputs - raw_stamp_data = paper.raw_stamp_data - raw_field_input_data = paper.raw_field_input_data - show_written_words = paper.show_written_words - stamp_cache = paper.stamp_cache - contact_poison = paper.contact_poison - contact_poison_volume = paper.contact_poison_volume - default_raw_text = paper.default_raw_text - input_field_count = paper.input_field_count diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 4080f68c5d74..b5ede755d62e 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -60,6 +60,9 @@ /// state checking on if it should be shown to a viewer. var/datum/weakref/camera_holder + ///If TRUE, staff can read paper everywhere, but usually from requests panel. + var/request_state = FALSE + /// The (text for the) stamps on the paper. var/list/stamps /// Positioning for the stamp in tgui var/list/stamped /// Overlay info @@ -320,7 +323,7 @@ // Are we on fire? Hard to read if so if(resistance_flags & ON_FIRE) return UI_CLOSE - if(camera_holder && can_show_to_mob_through_camera(user)) + if(camera_holder && can_show_to_mob_through_camera(user) || request_state) return UI_UPDATE if(!in_range(user, src) && !isobserver(user)) return UI_CLOSE @@ -373,7 +376,7 @@ return // Handle writing items. - var/writing_stats = attacking_item.get_writing_implement_details() + var/writing_stats = istype(attacking_item) ? attacking_item.get_writing_implement_details() : null if(!writing_stats) ui_interact(user) diff --git a/code/modules/requests/request.dm b/code/modules/requests/request.dm new file mode 100644 index 000000000000..0ac37f63187e --- /dev/null +++ b/code/modules/requests/request.dm @@ -0,0 +1,37 @@ +/** + * # Request + * + * A representation of an in-game request, such as a prayer. + */ +/datum/request + /// Unique ID of the request + var/id + /// Atomic ID for increment unique request IDs + var/static/atomic_id = 0 + /// The type of request + var/req_type + /// The owner of the request, the player who created it + var/client/owner + /// The ckey of the owner, used for re-binding variables on login + var/owner_ckey + /// The name of the owner, in format /, assigned at time of request creation + var/owner_name + /// The message associated with the request + var/message + /// Just any information, which you can to send with request. For example paper datum. + var/additional_information + /// When the request was created + var/timestamp + +/datum/request/New(client/requestee, type, request, additional_info) + if (!requestee) + qdel(src) + return + id = ++atomic_id + owner = requestee + owner_ckey = owner.ckey + req_type = type + message = request + timestamp = world.time + additional_information = additional_info + owner_name = key_name(requestee, FALSE) diff --git a/code/modules/requests/requests_manager.dm b/code/modules/requests/requests_manager.dm new file mode 100644 index 000000000000..e33da846d4de --- /dev/null +++ b/code/modules/requests/requests_manager.dm @@ -0,0 +1,249 @@ +/// Requests from prayers +#define REQUEST_PRAYER "request_prayer" +/// Requests for Centcom +#define REQUEST_CENTCOM "request_centcom" +/// Requests for the Syndicate +#define REQUEST_SYNDICATE "request_syndicate" +/// Requests for the nuke code +#define REQUEST_NUKE "request_nuke" +/// Requests somebody from fax +#define REQUEST_FAX "request_fax" + +GLOBAL_DATUM_INIT(requests, /datum/request_manager, new) + +/** + * # Request Manager + * + * Handles all player requests (prayers, centcom requests, syndicate requests) + * that occur in the duration of a round. + */ +/datum/request_manager + /// Associative list of ckey -> list of requests + var/list/requests = list() + /// List where requests can be accessed by ID + var/list/requests_by_id = list() + +/datum/request_manager/Destroy(force, ...) + QDEL_LIST(requests) + return ..() + +/** + * Used in the new client pipeline to catch when clients are reconnecting and need to have their + * reference re-assigned to the 'owner' variable of any requests + * + * Arguments: + * * C - The client who is logging in + */ +/datum/request_manager/proc/client_login(client/C) + if (!requests[C.ckey]) + return + for (var/datum/request/request as anything in requests[C.ckey]) + request.owner = C + +/** + * Used in the destroy client pipeline to catch when clients are disconnecting and need to have their + * reference nulled on the 'owner' variable of any requests + * + * Arguments: + * * C - The client who is logging out + */ +/datum/request_manager/proc/client_logout(client/C) + if (!requests[C.ckey]) + return + for (var/datum/request/request as anything in requests[C.ckey]) + request.owner = null + +/** + * Creates a request for a prayer, and notifies admins who have the sound notifications enabled when appropriate + * + * Arguments: + * * C - The client who is praying + * * message - The prayer + * * is_chaplain - Boolean operator describing if the prayer is from a chaplain + */ +/datum/request_manager/proc/pray(client/C, message, is_chaplain) + request_for_client(C, REQUEST_PRAYER, message) + for(var/client/admin in GLOB.admins) + if(is_chaplain && admin.prefs.chat_toggles & CHAT_PRAYER && admin.prefs.toggles & SOUND_PRAYERS) + SEND_SOUND(admin, sound('sound/effects/pray.ogg')) + +/** + * Creates a request for a Centcom message + * + * Arguments: + * * C - The client who is sending the request + * * message - The message + */ +/datum/request_manager/proc/message_centcom(client/C, message) + request_for_client(C, REQUEST_CENTCOM, message) + +/** + * Creates a request for a Syndicate message + * + * Arguments: + * * C - The client who is sending the request + * * message - The message + */ +/datum/request_manager/proc/message_syndicate(client/C, message) + request_for_client(C, REQUEST_SYNDICATE, message) + +/** + * Creates a request for the nuclear self destruct codes + * + * Arguments: + * * C - The client who is sending the request + * * message - The message + */ +/datum/request_manager/proc/nuke_request(client/C, message) + request_for_client(C, REQUEST_NUKE, message) + +/** + * Creates a request for fax answer + * + * Arguments: + * * requester - The client who is sending the request + * * message - Paper with text.. some stamps.. and another things. + */ +/datum/request_manager/proc/fax_request(client/requester, message, additional_info) + request_for_client(requester, REQUEST_FAX, message, additional_info) + +/** + * Creates a request and registers the request with all necessary internal tracking lists + * + * Arguments: + * * C - The client who is sending the request + * * type - The type of request, see defines + * * message - The message + */ +/datum/request_manager/proc/request_for_client(client/C, type, message, additional_info) + var/datum/request/request = new(C, type, message, additional_info) + if (!requests[C.ckey]) + requests[C.ckey] = list() + requests[C.ckey] += request + requests_by_id.len++ + requests_by_id[request.id] = request + +/datum/request_manager/ui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "RequestManager") + ui.open() + +/datum/request_manager/ui_state(mob/user) + return GLOB.admin_state + +/datum/request_manager/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if (..()) + return + + // Only admins should be sending actions + if (!check_rights(R_ADMIN)) + to_chat(usr, "You do not have permission to do this, you require +ADMIN") + return + + // Get the request this relates to + var/id = params["id"] != null ? text2num(params["id"]) : null + if (!id) + to_chat(usr, "Failed to find a request ID in your action, please report this") + CRASH("Received an action without a request ID, this shouldn't happen!") + var/datum/request/request = !id ? null : requests_by_id[id] + var/datum/admins/admin_datum = GLOB.admin_datums[usr.ckey] + + switch(action) + if ("pp") + var/mob/M = request.owner?.mob + usr.client.holder.show_player_panel(M) + return TRUE + if ("vv") + var/mob/M = request.owner?.mob + usr.client.debug_variables(M) + return TRUE + if ("sm") + var/mob/M = request.owner?.mob + usr.client.cmd_admin_subtle_message(M) + return TRUE + if ("flw") + var/mob/M = request.owner?.mob + admin_datum.admin_follow(M) + return TRUE + if ("tp") + if(!SSticker.HasRoundStarted()) + to_chat(usr,"The game hasn't started yet!") + return TRUE + var/mob/M = request.owner?.mob + if(!ismob(M)) + var/datum/mind/D = M + if(!istype(D)) + to_chat(usr, "This can only be used on instances of type /mob and /mind") + return TRUE + else + D.traitor_panel() + return TRUE + else + usr.client.holder.show_traitor_panel(M) + return TRUE + if ("logs") + var/mob/M = request.owner?.mob + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob.") + return TRUE + show_individual_logging_panel(M, null, null) + return TRUE + if ("smite") + if(!check_rights(R_FUN)) + to_chat(usr, "Insufficient permissions to smite, you require +FUN") + return TRUE + var/mob/living/carbon/human/H = request.owner?.mob + if (!H || !istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return TRUE + usr.client.smite(H) + return TRUE + if ("rply") + if (request.req_type == REQUEST_PRAYER) + to_chat(usr, "Cannot reply to a prayer") + return TRUE + var/mob/M = request.owner?.mob + usr.client.admin_headset_message(M, request.req_type == REQUEST_SYNDICATE ? RADIO_CHANNEL_SYNDICATE : RADIO_CHANNEL_CENTCOM) + return TRUE + if ("setcode") + if (request.req_type != REQUEST_NUKE) + to_chat(usr, "You cannot set the nuke code for a non-nuke-code-request request!") + return TRUE + var/code = random_nukecode() + for(var/obj/machinery/nuclearbomb/selfdestruct/SD in GLOB.nuke_list) + SD.r_code = code + message_admins("[key_name_admin(usr)] has set the self-destruct code to \"[code]\".") + return TRUE + if ("show") + if(request.req_type != REQUEST_FAX) + to_chat(usr, "Request doesn't have a paper to read.") + return TRUE + var/obj/item/paper/request_message = request.additional_information + request_message.ui_interact(usr) + return TRUE + +/datum/request_manager/ui_data(mob/user) + . = list( + "requests" = list() + ) + for (var/ckey in requests) + for (var/datum/request/request as anything in requests[ckey]) + var/list/data = list( + "id" = request.id, + "req_type" = request.req_type, + "owner" = request.owner ? "[REF(request.owner)]" : null, + "owner_ckey" = request.owner_ckey, + "owner_name" = request.owner_name, + "message" = request.message, + "additional_info" = request.additional_information, + "timestamp" = request.timestamp, + "timestamp_str" = station_time_timestamp(wtime = request.timestamp) + ) + .["requests"] += list(data) + +#undef REQUEST_PRAYER +#undef REQUEST_CENTCOM +#undef REQUEST_SYNDICATE +#undef REQUEST_NUKE +#undef REQUEST_FAX diff --git a/shiptest.dme b/shiptest.dme index 543b4322394d..702a865a6e60 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -222,7 +222,6 @@ #include "code\_globalvars\lists\achievements.dm" #include "code\_globalvars\lists\admin.dm" #include "code\_globalvars\lists\client.dm" -#include "code\_globalvars\lists\faxes.dm" #include "code\_globalvars\lists\flavor_misc.dm" #include "code\_globalvars\lists\jobs.dm" #include "code\_globalvars\lists\keybindings.dm" @@ -1465,6 +1464,7 @@ #include "code\game\turfs\open\space\space.dm" #include "code\game\turfs\open\space\transit.dm" #include "code\modules\admin\admin.dm" +#include "code\modules\admin\admin_fax_panel.dm" #include "code\modules\admin\admin_follow.dm" #include "code\modules\admin\admin_investigate.dm" #include "code\modules\admin\admin_ranks.dm" @@ -1509,7 +1509,6 @@ #include "code\modules\admin\verbs\deadsay.dm" #include "code\modules\admin\verbs\debug.dm" #include "code\modules\admin\verbs\diagnostics.dm" -#include "code\modules\admin\verbs\fax_manager.dm" #include "code\modules\admin\verbs\fix_air.dm" #include "code\modules\admin\verbs\fps.dm" #include "code\modules\admin\verbs\getlogs.dm" @@ -1530,6 +1529,7 @@ #include "code\modules\admin\verbs\randomverbs.dm" #include "code\modules\admin\verbs\reestablish_db_connection.dm" #include "code\modules\admin\verbs\rejuvenate.dm" +#include "code\modules\admin\verbs\requests.dm" #include "code\modules\admin\verbs\secrets.dm" #include "code\modules\admin\verbs\selectequipment.dm" #include "code\modules\admin\verbs\shuttlepanel.dm" @@ -2862,7 +2862,6 @@ #include "code\modules\paperwork\clipboard.dm" #include "code\modules\paperwork\contract.dm" #include "code\modules\paperwork\fax.dm" -#include "code\modules\paperwork\fax_manager.dm" #include "code\modules\paperwork\filingcabinet.dm" #include "code\modules\paperwork\folders.dm" #include "code\modules\paperwork\handlabeler.dm" @@ -3120,6 +3119,8 @@ #include "code\modules\religion\religion_sects.dm" #include "code\modules\religion\religion_structures.dm" #include "code\modules\religion\rites.dm" +#include "code\modules\requests\request.dm" +#include "code\modules\requests\requests_manager.dm" #include "code\modules\research\bepis.dm" #include "code\modules\research\designs.dm" #include "code\modules\research\destructive_analyzer.dm" diff --git a/tgui/packages/tgui/interfaces/AdminFax.js b/tgui/packages/tgui/interfaces/AdminFax.js new file mode 100644 index 000000000000..89870f45451d --- /dev/null +++ b/tgui/packages/tgui/interfaces/AdminFax.js @@ -0,0 +1,200 @@ +import { useBackend, useLocalState } from '../backend'; +import { Section, Box, Dropdown, Button, Input, TextArea, Divider, NumberInput, Tooltip, Knob } from '../components'; +import { Window } from '../layouts'; + +export const AdminFax = (props, context) => { + return ( + + + + + + ); +}; + +export const FaxMainPanel = (props, context) => { + const { act, data } = useBackend(context); + + const [fax, setFax] = useLocalState(context, 'fax', ''); + const [saved, setSaved] = useLocalState(context, 'saved', false); + const [paperName, setPaperName] = useLocalState(context, 'paperName', ''); + const [fromWho, setFromWho] = useLocalState(context, 'fromWho', ''); + const [rawText, setRawText] = useLocalState(context, 'rawText', ''); + const [stamp, setStamp] = useLocalState(context, 'stampType', ''); + const [stampCoordX, setStampCoordX] = useLocalState(context, 'stampCoordX', 0); + const [stampCoordY, setStampCoordY] = useLocalState(context, 'stampCoordY', 0); + const [stampAngle, setStampAngle] = useLocalState(context, 'stampAngle', 0); + if (stamp && data.stamps[0] !== 'None') { + data.stamps.unshift('None'); + } + return ( + <> +
+ + + }> + + setFax(value)} + /> + +
+
+ act('preview', { + faxName: fax, + }) + }> + Preview + + }> + + setPaperName(v)} /> + + + + + + + setFromWho(v)} /> + + + + + + +