diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm index fbff4a4ec73..aaf54ca770c 100644 --- a/code/game/machinery/telecomms/logbrowser.dm +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -19,205 +19,188 @@ req_access = list(access_tcomsat) - attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/dat = "Telecommunication Server Monitor
Telecommunications Server Monitor
" + var/last_print_time - switch(screen) - - - // --- Main Menu --- - - if(0) - dat += "
[temp]
" - dat += "
Current Network: [network]
" - if(servers.len) - dat += "
Detected Telecommunication Servers:" - dat += "
\[Flush Buffer\]" - - else - dat += "
No servers detected. Scan for servers: \[Scan\]" - - - // --- Viewing Server --- - - if(1) - dat += "
[temp]
" - dat += "
\[Main Menu\] \[Refresh\]
" - dat += "
Current Network: [network]" - dat += "
Selected Server: [SelectedServer.id]" - - if(SelectedServer.totaltraffic >= 1024) - dat += "
Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes

" - else - dat += "
Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes

" - - dat += "Stored Logs:
    " - - var/i = 0 - for(var/datum/comm_log_entry/C in SelectedServer.log_entries) - i++ - - - // If the log is a speech file - if(C.input_type == "Speech File") - - dat += "
  1. [C.name] \[X\]
    " - - // -- Determine race of orator -- - - var/race = C.parameters["race"] // The actual race of the mob - var/language = C.parameters["language"] // The language spoken, or null/"" - - // -- If the orator is a human, or universal translate is active, OR mob has universal speech on -- - - if(universal_translate || C.parameters["uspeech"] || C.parameters["intelligible"]) - dat += "Data type: [C.input_type]
    " - dat += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]])
    " - dat += "Class: [race]
    " - dat += "Contents: \"[C.parameters["message"]]\"
    " - if(language) - dat += "Language: [language]
    " - - // -- Orator is not human and universal translate not active -- - - else - dat += "Data type: Audio File
    " - dat += "Source: Unidentifiable
    " - dat += "Class: [race]
    " - dat += "Contents: Unintelligble
    " - - dat += "

  2. " - - else if(C.input_type == "Execution Error") - - dat += "
  3. [C.name] \[X\]
    " - dat += "Output: \"[C.parameters["message"]]\"
    " - dat += "

  4. " - - - dat += "
" - - - - user << browse(dat, "window=comm_monitor;size=575x400") - onclose(user, "server_control") - - temp = "" +/obj/machinery/computer/telecomms/server/attack_hand(mob/user) + if(stat & (BROKEN|NOPOWER)) return + user.set_machine(src) + var/dat = "Telecommunication Server Monitor
Telecommunications Server Monitor
" + + switch(screen) - Topic(href, href_list) - if(..()) - return + // --- Main Menu --- - - add_fingerprint(usr) - usr.set_machine(src) - - if(href_list["viewserver"]) - screen = 1 - for(var/obj/machinery/telecomms/T in servers) - if(T.id == href_list["viewserver"]) - SelectedServer = T - break - - if(href_list["operation"]) - switch(href_list["operation"]) - - if("release") - servers = list() - screen = 0 - - if("mainmenu") - screen = 0 - - if("scan") - if(servers.len > 0) - temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" - - else - for(var/obj/machinery/telecomms/server/T in range(25, src)) - if(T.network == network) - servers.Add(T) - - if(!servers.len) - temp = "- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -" - else - temp = "- [servers.len] SERVERS PROBED & BUFFERED -" - - screen = 0 - - if(href_list["delete"]) - - if(!src.allowed(usr) && !emagged) - to_chat(usr, "ACCESS DENIED.") - return - - if(SelectedServer) - - var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])] - - temp = "- DELETED ENTRY: [D.name] -" - - SelectedServer.log_entries.Remove(D) - qdel(D) + if(0) + dat += "
[temp]
" + dat += "
Current Network: [network]
" + if(servers.len) + dat += "
Detected Telecommunication Servers:" + dat += "
\[Flush Buffer\]" else - temp = "- FAILED: NO SELECTED MACHINE -" + dat += "
No servers detected. Scan for servers: \[Scan\]" - if(href_list["network"]) - var/newnet = sanitize(input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text) + // --- Viewing Server --- - if(newnet && ((usr in range(1, src) || issilicon(usr)))) - if(length(newnet) > 15) - temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + if(1) + dat += "
[temp]
" + dat += "
\[Main Menu\] \[Refresh\] \[Print Logs\]
" + dat += "
Current Network: [network]" + dat += "
Selected Server: [SelectedServer.id]" + + if(SelectedServer.totaltraffic >= 1024) + dat += "
Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes

" + else + dat += "
Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes

" + + dat += log_entries_to_text(SelectedServer) + + user << browse(dat, "window=comm_monitor;size=575x400") + onclose(user, "server_control") + + temp = "" + return + +/obj/machinery/computer/telecomms/server/Topic(href, href_list) + if(..()) + return + + + add_fingerprint(usr) + usr.set_machine(src) + + if(href_list["viewserver"]) + screen = 1 + for(var/obj/machinery/telecomms/T in servers) + if(T.id == href_list["viewserver"]) + SelectedServer = T + break + + if(href_list["operation"]) + switch(href_list["operation"]) + + if("release") + servers = list() + screen = 0 + + if("mainmenu") + screen = 0 + + if("scan") + if(servers.len > 0) + temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" else + for(var/obj/machinery/telecomms/server/T in range(25, src)) + if(T.network == network) + servers.Add(T) + + if(!servers.len) + temp = "- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -" + else + temp = "- [servers.len] SERVERS PROBED & BUFFERED -" - network = newnet screen = 0 - servers = list() - temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" - updateUsrDialog() - return - - attackby(var/obj/item/D as obj, var/mob/user as mob) - if(D.isscrewdriver()) - playsound(src.loc, D.usesound, 50, 1) - if(do_after(user, 20/D.toolspeed)) - if (src.stat & BROKEN) - to_chat(user, "The broken glass falls out.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/material/shard( src.loc ) - var/obj/item/circuitboard/comm_server/M = new /obj/item/circuitboard/comm_server( A ) - for (var/obj/C in src) - C.forceMove(src.loc) - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - qdel(src) + if("printlog") + var/start_point = 1 + var/end_point = SelectedServer.log_entries.len + if(SelectedServer) + if(SelectedServer.log_entries.len) + start_point = input(usr, "Type the start address to print from, cancel to print full log.", "Start Address") as null|num + if(!isnum(start_point)) + start_point = 1 + else + end_point = input(usr, "Type the end address to print to, cancel to print full log.", "End Address") as null|num + if(!isnum(end_point)) + end_point = 0 + else + to_chat(usr, SPAN_WARNING("Cannot print from server that has no logs.")) + return else - to_chat(user, "You disconnect the monitor.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/circuitboard/comm_server/M = new /obj/item/circuitboard/comm_server( A ) - for (var/obj/C in src) - C.forceMove(src.loc) - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - qdel(src) - src.updateUsrDialog() - return + to_chat(usr, SPAN_WARNING("Select a server before trying to print logs.")) + return + + if(!last_print_time || (last_print_time + 2 SECONDS < world.time)) + last_print_time = world.time + var/obj/item/paper/P = new /obj/item/paper(get_turf(src), log_entries_to_text(SelectedServer, start_point, end_point), "[SelectedServer.id] Logs ([start_point] - [end_point])") + var/mob/M = usr + if(M) + M.put_in_hands(P) + else + to_chat(usr, SPAN_WARNING("Please wait before trying to print more logs.")) + + if(href_list["delete"]) + + if(!src.allowed(usr) && !emagged) + to_chat(usr, "ACCESS DENIED.") + return + + if(SelectedServer) + + var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])] + + temp = "- DELETED ENTRY: [D.name] -" + + SelectedServer.log_entries.Remove(D) + qdel(D) + + else + temp = "- FAILED: NO SELECTED MACHINE -" + + if(href_list["network"]) + + var/newnet = sanitize(input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text) + + if(newnet && ((usr in range(1, src) || issilicon(usr)))) + if(length(newnet) > 15) + temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" + + else + + network = newnet + screen = 0 + servers = list() + temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" + + updateUsrDialog() + return + +/obj/machinery/computer/telecomms/server/attackby(var/obj/item/D, var/mob/user) + if(D.isscrewdriver()) + playsound(src.loc, D.usesound, 50, 1) + if(do_after(user, 20/D.toolspeed)) + if (src.stat & BROKEN) + to_chat(user, "The broken glass falls out.") + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + new /obj/item/material/shard( src.loc ) + var/obj/item/circuitboard/comm_server/M = new /obj/item/circuitboard/comm_server( A ) + for (var/obj/C in src) + C.forceMove(src.loc) + A.circuit = M + A.state = 3 + A.icon_state = "3" + A.anchored = 1 + qdel(src) + else + to_chat(user, "You disconnect the monitor.") + var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) + var/obj/item/circuitboard/comm_server/M = new /obj/item/circuitboard/comm_server( A ) + for (var/obj/C in src) + C.forceMove(src.loc) + A.circuit = M + A.state = 4 + A.icon_state = "4" + A.anchored = 1 + qdel(src) + src.updateUsrDialog() + return /obj/machinery/computer/telecomms/server/emag_act(var/remaining_charges, var/mob/user) if(!emagged) @@ -226,3 +209,55 @@ to_chat(user, "You you disable the security protocols") src.updateUsrDialog() return 1 + +/obj/machinery/computer/telecomms/server/proc/log_entries_to_text(var/obj/machinery/telecomms/server/SelectedServer, start = 1, end = SelectedServer.log_entries.len) + if(!end) + end = SelectedServer.log_entries.len + start = between(1, start, SelectedServer.log_entries.len) + end = between(0, end, SelectedServer.log_entries.len) + var/list/log_entries = SelectedServer.log_entries.Copy(start, end + 1) + + . += "Stored Logs:
    " + + var/i = start - 1 + for(var/datum/comm_log_entry/C as anything in log_entries) + i++ + + // If the log is a speech file + if(C.input_type == "Speech File") + + . += "
  1. [C.name] \[X\]
    " + + // -- Determine race of orator -- + + var/race = C.parameters["race"] // The actual race of the mob + var/language = C.parameters["language"] // The language spoken, or null/"" + + // -- If the orator is a human, or universal translate is active, OR mob has universal speech on -- + + if(universal_translate || C.parameters["uspeech"] || C.parameters["intelligible"]) + . += "Data type: [C.input_type]
    " + . += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]])
    " + . += "Class: [race]
    " + . += "Contents: \"[C.parameters["message"]]\"
    " + if(language) + . += "Language: [language]
    " + + // -- Orator is not human and universal translate not active -- + + else + . += "Data type: Audio File
    " + . += "Source: Unidentifiable
    " + . += "Class: [race]
    " + . += "Contents: Unintelligble
    " + + . += "

  2. " + + else if(C.input_type == "Execution Error") + + . += "
  3. [C.name] \[X\]
    " + . += "Output: \"[C.parameters["message"]]\"
    " + . += "

  4. " + + + . += "
" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 94b8cbb79c8..01b7ee52ec8 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -337,6 +337,7 @@ new /obj/item/device/laser_pointer/blue(src) new /obj/item/device/camera/detective(src) new /obj/item/device/camera_film(src) + new /obj/item/stamp/investigations(src) //Belts new /obj/item/clothing/accessory/holster/waist(src) new /obj/item/clothing/accessory/storage/pouches/black(src) diff --git a/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm b/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm index e247430e460..37014f64af0 100644 --- a/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm +++ b/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm @@ -51,11 +51,16 @@ active_warrant = null if(href_list["editwarrant"]) - . = TRUE for(var/datum/record/warrant/W in SSrecords.warrants) if(W.id == text2num(href_list["editwarrant"])) active_warrant = W break + return TRUE + + if(href_list["back"]) + . = TRUE + active_warrant = null + return TRUE // The following actions will only be possible if the user has an ID with security access equipped. This is in line with modular computer framework's authentication methods, // which also use RFID scanning to allow or disallow access to some functions. Anyone can view warrants, editing requires ID. @@ -64,10 +69,15 @@ if(!istype(user)) return var/obj/item/card/id/I = user.GetIdCard() - if(!istype(I) || !I.registered_name || !(access_armory in I.access) || issilicon(user)) + if(!istype(I) || !I.registered_name || !(access_security in I.access) || issilicon(user)) to_chat(user, SPAN_WARNING("Authentication error: Unable to locate ID with appropriate access to allow this operation.")) return + // Require higher access to edit warrants that have already been authorized + if(active_warrant && active_warrant.authorization != "Unauthorized" && !(access_armory in I.access)) + to_chat(user, SPAN_WARNING("Authentication error: Unable to locate ID with appropriate access to adjust an authorized warrant.")) + return + if(href_list["addwarrant"]) . = TRUE var/datum/record/warrant/W = new() @@ -83,6 +93,8 @@ W.notes = "No reason given" W.authorization = "Unauthorized" W.wtype = "search" + if(isnull(temp)) + return active_warrant = W if(href_list["savewarrant"]) @@ -123,10 +135,9 @@ active_warrant.notes = new_charges if(href_list["editwarrantauth"]) + if(!(access_armory in I.access)) + to_chat(user, SPAN_WARNING("Authentication error: Unable to locate ID with appropriate access to allow this operation.")) + return . = TRUE active_warrant.authorization = "[I.registered_name] - [I.assignment ? I.assignment : "(Unknown)"]" - - if(href_list["back"]) - . = TRUE - active_warrant = null \ No newline at end of file diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm index d15c33cc30a..d19df4ac44b 100644 --- a/code/modules/paperwork/stamps.dm +++ b/code/modules/paperwork/stamps.dm @@ -35,6 +35,10 @@ name = "chief medical officer's rubber stamp" icon_state = "stamp-cmo" +/obj/item/stamp/investigations + name = "case closed stamp" + icon_state = "stamp-investigator" + /obj/item/stamp/denied name = "\improper DENIED rubber stamp" icon_state = "stamp-deny" diff --git a/html/changelog.html b/html/changelog.html index 9724a3ccd2b..539ee6794b5 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -35,6 +35,14 @@ -->
+

10 April 2022

+

mikomyazaki updated:

+ +

09 April 2022

MattAtlas updated: