From 35d60d088612c60268eb20c261a133fc8cda3a87 Mon Sep 17 00:00:00 2001 From: Geeves Date: Sun, 31 Dec 2023 20:00:27 +0200 Subject: [PATCH] Warrant Fix & More (#18085) * Warrant Fix & More * the nuclear option * i hate the dme! * fluffy review --- aurorastation.dme | 1 + code/__defines/dcs/signals.dm | 1 + code/__defines/dcs/signals/signals_record.dm | 5 + code/controllers/subsystems/garbage.dm | 3 +- code/controllers/subsystems/records.dm | 27 ++-- code/datums/records.dm | 5 +- .../game/objects/items/devices/holowarrant.dm | 144 +++++++++++------- .../programs/security/digitalwarrant.dm | 11 +- html/changelogs/geeves-warrant_fix.yml | 9 ++ icons/obj/modular_laptop.dmi | Bin 28031 -> 28120 bytes icons/obj/modular_tablet.dmi | Bin 4017 -> 4180 bytes 11 files changed, 132 insertions(+), 74 deletions(-) create mode 100644 code/__defines/dcs/signals/signals_record.dm create mode 100644 html/changelogs/geeves-warrant_fix.yml diff --git a/aurorastation.dme b/aurorastation.dme index f159a69c46e..5de0815deb2 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -133,6 +133,7 @@ #include "code\__defines\dcs\helpers.dm" #include "code\__defines\dcs\signals.dm" #include "code\__defines\dcs\signals\signals_global.dm" +#include "code\__defines\dcs\signals\signals_record.dm" #include "code\__defines\dcs\signals\signals_atom\signals_atom_main.dm" #include "code\__defines\dcs\signals\signals_atom\signals_atom_x_act.dm" #include "code\_global_vars\edible.dm" diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index a2b9b0e9734..2bf44bee8df 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -28,6 +28,7 @@ /// fires on the target datum when an element is attached to it (/datum/element) #define COMSIG_ELEMENT_DETACH_ON_HOST_DESTROY "ELEMENT_DETACH_ON_HOST_DESTROY" + // /atom signals // /area signals diff --git a/code/__defines/dcs/signals/signals_record.dm b/code/__defines/dcs/signals/signals_record.dm new file mode 100644 index 00000000000..3a481f89002 --- /dev/null +++ b/code/__defines/dcs/signals/signals_record.dm @@ -0,0 +1,5 @@ +// Signals related to the creation and deletion of records, such as employment, security, medical, or warrants +// Sent from subsystem records.dm + +#define COMSIG_RECORD_CREATED "record_created" +#define COMSIG_RECORD_MODIFIED "record_modified" diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index dfbe8e8f523..4c5664fa495 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -217,10 +217,11 @@ SUBSYSTEM_DEF(garbage) else if(isnull(D.gcDestroyed)) if (SEND_SIGNAL(D, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted return + // this SEND_SIGNAL should be above Destroy because Destroy sets signal_enabled to FALSE + SEND_SIGNAL(D, COMSIG_QDELETING, force) // Let the (remaining) components know about the result of Destroy D.gcDestroyed = GC_CURRENTLY_BEING_QDELETED var/start_time = world.time var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up. - SEND_SIGNAL(D, COMSIG_QDELETING, force) // Let the (remaining) components know about the result of Destroy if(world.time != start_time) SSgarbage.sleptDestroy["[D.type]"]++ if(!D) diff --git a/code/controllers/subsystems/records.dm b/code/controllers/subsystems/records.dm index f529e5e5387..857e4155ea8 100644 --- a/code/controllers/subsystems/records.dm +++ b/code/controllers/subsystems/records.dm @@ -107,6 +107,7 @@ SUBSYSTEM_DEF(records) viruses += record if(/datum/record/shuttle_manifest) shuttle_manifests += record + onCreate(record) /datum/controller/subsystem/records/proc/update_record(var/datum/record/record) switch(record.type) @@ -286,19 +287,23 @@ SUBSYSTEM_DEF(records) get_manifest_list() return manifest_json -/datum/controller/subsystem/records/proc/onDelete(var/datum/record/r) - for (var/listener in GET_LISTENERS("SSrecords")) - var/listener/record/rl = listener - if(istype(rl)) - rl.on_delete(r) +/datum/controller/subsystem/records/proc/onCreate(var/datum/record/record) + SEND_SIGNAL(src, COMSIG_RECORD_CREATED, record) -/datum/controller/subsystem/records/proc/onModify(var/datum/record/r) - if(r in records) - reset_manifest() +/datum/controller/subsystem/records/proc/onDelete(var/datum/record/record) for (var/listener in GET_LISTENERS("SSrecords")) - var/listener/record/rl = listener - if(istype(rl)) - rl.on_modify(r) + var/listener/record/record_listener = listener + if(istype(record_listener)) + record_listener.on_delete(record) + +/datum/controller/subsystem/records/proc/onModify(var/datum/record/record) + if(record in records) + reset_manifest() + SEND_SIGNAL(record, COMSIG_RECORD_MODIFIED) + for (var/listener in GET_LISTENERS("SSrecords")) + var/listener/record/record_listener = listener + if(istype(record_listener)) + record_listener.on_modify(record) /* * Helping functions for everyone diff --git a/code/datums/records.dm b/code/datums/records.dm index 541bb5aa4ce..d6a1c6b5d08 100644 --- a/code/datums/records.dm +++ b/code/datums/records.dm @@ -217,12 +217,13 @@ // Digital warrant /datum/record/warrant - var/authorization = "Unauthorized" - var/wtype = "Unknown" name = "Unknown" notes = "No charges present" cmp_field = "name" + var/authorization = "Unauthorized" + var/wtype = "Unknown" + var/warrant_uid = 0 /datum/record/warrant/New() ..() diff --git a/code/game/objects/items/devices/holowarrant.dm b/code/game/objects/items/devices/holowarrant.dm index 300277adb94..0291624944f 100644 --- a/code/game/objects/items/devices/holowarrant.dm +++ b/code/game/objects/items/devices/holowarrant.dm @@ -1,6 +1,7 @@ /obj/item/device/holowarrant name = "warrant projector" desc = "The practical paperwork replacement for the officer on the go." + desc_info = "Use this item in-hand to select the active warrant. Click on the person you want to show it to to display the warrant." icon = 'icons/obj/holowarrant.dmi' icon_state = "holowarrant" item_state = "holowarrant" @@ -9,69 +10,100 @@ throw_speed = 4 throw_range = 10 obj_flags = OBJ_FLAG_CONDUCTABLE - var/list/storedwarrant = list() //All the warrants currently stored - var/activename = null - var/activecharges = null - var/activeauth = null //Currently active warrant - var/activetype = null //Is this a search or arrest warrant? -//look at it + var/datum/record/warrant/selected_warrant + +/obj/item/device/holowarrant/Initialize(mapload, ...) + . = ..() + RegisterSignal(SSrecords, COMSIG_RECORD_CREATED, PROC_REF(handle_warrant_created)) + +/obj/item/device/holowarrant/Destroy() + unload_warrant() + return ..() + /obj/item/device/holowarrant/examine(mob/user, distance, is_adjacent) . = ..() - if(activename) - to_chat(user, "It's a holographic warrant for '[activename]'.") - if(is_adjacent) - show_content(user) - else - to_chat(user, SPAN_NOTICE("You have to go closer if you want to read it.")) + if(selected_warrant) + to_chat(user, "It's a holographic warrant for '[selected_warrant.name]'.") -//hit yourself with it /obj/item/device/holowarrant/attack_self(mob/living/user as mob) - sync(user) - if(activename) - activename = null - activecharges = null - activeauth = null - activetype = null - if(!storedwarrant.len) + if(!LAZYLEN(SSrecords.warrants)) to_chat(user, SPAN_NOTICE("There are no warrants available at this time.")) return - var/temp - temp = tgui_input_list(usr, "Which warrant would you like to load?", storedwarrant) - for(var/datum/record/warrant/W in SSrecords.warrants) - if(W.name == temp) - activename = W.name - activecharges = W.notes - activeauth = W.authorization - activetype = W.wtype + + var/list/warrant_list = list() + for(var/datum/record/warrant/warrant in SSrecords.warrants) + warrant_list["[warrant.id] - [warrant.name] - [capitalize_first_letters(warrant.wtype)]"] = warrant + + if(selected_warrant) + warrant_list += "Unload Warrant" + + var/chosen_warrant = tgui_input_list(usr, "Which warrant do you want to load?", "Warrant Projector", warrant_list) + if(!chosen_warrant) + return + else if(chosen_warrant == "Unload Warrant") + unload_warrant() + else + load_warrant(warrant_list[chosen_warrant]) + + play_message(SPAN_NOTICE("\The [src] pings, \"Warrant [selected_warrant ? "" : "un"]loaded.\"")) + +/obj/item/device/holowarrant/proc/load_warrant(var/datum/record/warrant/warrant) + selected_warrant = warrant + RegisterSignal(selected_warrant, COMSIG_QDELETING, PROC_REF(handle_warrant_delete)) + RegisterSignal(selected_warrant, COMSIG_RECORD_MODIFIED, PROC_REF(handle_warrant_modify)) update_icon() -//hit other people with it -/obj/item/device/holowarrant/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(activename) - user.visible_message(SPAN_NOTICE("[user] holds up a warrant projector and shows the contents to [M]."), \ - SPAN_NOTICE("You show the warrant to [M].")) - examinate(M, src) - else +/obj/item/device/holowarrant/proc/unload_warrant() + if(selected_warrant) + UnregisterSignal(selected_warrant, COMSIG_QDELETING) + UnregisterSignal(selected_warrant, COMSIG_RECORD_MODIFIED) + selected_warrant = null + update_icon() + +/obj/item/device/holowarrant/proc/play_message(var/message) + playsound(get_turf(src), 'sound/machines/ping.ogg', 40) + audible_message(message) + +/// Called when a warrant is created +/obj/item/device/holowarrant/proc/handle_warrant_created(datum/source, datum/record/record) + SIGNAL_HANDLER + + if(istype(record, /datum/record/warrant)) + play_message(SPAN_NOTICE("\The [src] pings, \"New warrant on database.\"")) + +/// Called right before the warrant is deleted +/obj/item/device/holowarrant/proc/handle_warrant_delete(datum/source) + SIGNAL_HANDLER + + unload_warrant() + + play_message(SPAN_NOTICE("\The [src] pings, \"Active warrant deleted.\"")) + +/// Called right after the warrant is modified +/obj/item/device/holowarrant/proc/handle_warrant_modify(datum/source) + SIGNAL_HANDLER + + play_message(SPAN_NOTICE("\The [src] pings, \"Active warrant modified.\"")) + +/obj/item/device/holowarrant/attack(mob/living/victim, mob/living/user) + if(!selected_warrant) to_chat(user, SPAN_WARNING("There are no warrants loaded!")) + return + + user.visible_message("[user] holds \the [src] up to \the [victim].", SPAN_NOTICE("You hold up \the [src] to \the [victim].")) + show_content(victim) /obj/item/device/holowarrant/update_icon() - if(activename) + if(selected_warrant) icon_state = "holowarrant_filled" else icon_state = "holowarrant" -//sync with database -/obj/item/device/holowarrant/proc/sync(var/mob/user) - storedwarrant = list() - for(var/datum/record/warrant/W in SSrecords.warrants) - storedwarrant += W.name - to_chat(user, SPAN_NOTICE("The device hums faintly as it syncs with the station database.")) - -/obj/item/device/holowarrant/proc/show_content(mob/user, forceshow) - if(activetype == "arrest") +/obj/item/device/holowarrant/proc/show_content(mob/user) + if(selected_warrant.wtype == "arrest") var/output = {" - Arrest Warrant: [activename] + Arrest Warrant: [selected_warrant.name]
Stellar Corporate Conglomerate @@ -93,21 +125,21 @@

Suspect's name: -
[activename] +
[selected_warrant.name]

Reason(s): -
[activecharges] +
[selected_warrant.notes]
-
__[activeauth]__ +
__[selected_warrant.authorization]__
Person authorizing arrest
"} - show_browser(user, output, "window=Warrant for the arrest of [activename]") - if(activetype == "search") + show_browser(user, output, "window=Warrant for the arrest of [selected_warrant.name]") + if(selected_warrant.wtype == "search") var/output= {" - Search Warrant: [activename] + Search Warrant: [selected_warrant.name]
Stellar Corporate Conglomerate @@ -129,14 +161,14 @@ In the event of the Suspect/Department staff attempting to resist/impede this search or flee, they must be taken into custody immediately!
All confiscated items must be filed and taken to Evidence!

Suspect's/location name: -
[activename] +
[selected_warrant.name]

For the following reasons: -
[activecharges] +
[selected_warrant.notes]
-
__[activeauth]__ +
__[selected_warrant.authorization]__
Person authorizing search
"} - show_browser(user, output, "window=Search warrant for [activename]") + show_browser(user, output, "window=Search warrant for [selected_warrant.name]") 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 018147fd10a..209d2cebb55 100644 --- a/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm +++ b/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm @@ -2,9 +2,9 @@ filename = "digitalwarrant" filedesc = "Warrant Assistant" extended_desc = "Official NTsec program for creation and handling of warrants." - program_icon_state = "security" - program_key_icon_state = "yellow_key" - color = LIGHT_COLOR_ORANGE + program_icon_state = "warrant" + program_key_icon_state = "red_key" + color = LIGHT_COLOR_RED size = 8 requires_ntnet = TRUE available_on_ntnet = TRUE @@ -97,7 +97,10 @@ active_warrant = W if("savewarrant") - SSrecords.update_record(active_warrant) + if(!(active_warrant in SSrecords.warrants)) + SSrecords.add_record(active_warrant) + else + SSrecords.update_record(active_warrant) active_warrant = null SStgui.update_uis(computer) diff --git a/html/changelogs/geeves-warrant_fix.yml b/html/changelogs/geeves-warrant_fix.yml new file mode 100644 index 00000000000..f7efb17566e --- /dev/null +++ b/html/changelogs/geeves-warrant_fix.yml @@ -0,0 +1,9 @@ +author: Geeves + +delete-after: True + +changes: + - bugfix: "Fixed not being able to load warrants on the warrant projector." + - rscadd: "The warrant projector will now alert you if a new warrant was loaded, and will alert you if the currently active warrant is modified or deleted." + - tweak: "Tweaked how warrant projectors work, you now use it in-hand to load or unload warrants, and then click on the target to display it. Shift-clicking no longer opens the warrant." + - bugfix: "Fixed the digital warrant assistant not having an icon on the PDA." \ No newline at end of file diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi index 65db47b87679b4e10d68d51b0a2bdfbb6edadf79..6d6354cf8fd78b794761aac17377ca7fff331a96 100644 GIT binary patch delta 5663 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 diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi index 0849cfd88a40055b62d7787e0ee86e9a51b459ed..3338c5d39a3cc0bb683a261e289d04cc4e6c272b 100644 GIT binary patch delta 3933 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 delta 3756 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