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 65db47b8767..6d6354cf8fd 100644 Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi index 0849cfd88a4..3338c5d39a3 100644 Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ