From 268f2619bdf2c6e62359bbe77fe157f522a3e113 Mon Sep 17 00:00:00 2001 From: Joshua Kidder <49173900+Metekillot@users.noreply.github.com> Date: Wed, 4 Jun 2025 22:46:14 -0400 Subject: [PATCH] SSid_access now has a proc for getting information about an ID holder from their ID, there is also a define to invoke this proc in a less verbose way (#91269) ## About The Pull Request As part of the ore silo logging PR I'm working on I needed a way to get the information on someone's ID in a robust and consistent way. I decided on adding this proc to SSID_access and also adding a define to invoke it since it's otherwise quite verbose. ``` /datum/controller/subsystem/id_access/proc/__in_character_record_id_information( atom/movable/target_of_record, bypass_chameleon = FALSE ) as /alist #define ID_DATA(subject) SSid_access.__in_character_record_id_information(subject) ``` This proc expects either a living mob or an ID. It returns an alist of: "Name" Current ID name "Age" Current ID age "Assignment" Current ID job "Account ID" ID# of the attached bank account if a standard ID, random number if chameleon ID "Account Holder" Name of attached bank account holder if one is attached, current ID name if chameleon "Account Assignment" 'title' of the job datum of the attached bank account if normal ID, current ID name if chameleon "Accesses" a list of the accesses on the ID, in the style of our other access lists Additionally, if it fails to read an ID, it also adds [ID_READ_FAILURE] = ID_READ_FAILURE Finally, there are overrides for if The card is a chameleon card. The being scanned is a silicon. Which appends, respectively, .[SILICON_OVERRIDE] = SILICON_OVERRIDE .[CHAMELEON_OVERRIDE] = CHAMELEON_OVERRIDE And does special handling. This collects a significant quantity of relevant information into a single convenient proc call, which is also named to reflect that the information returned is meant to serve as an in character record of what is being read (if it is used anywhere). ## Why It's Good For The Game Offers standardized information returned from an ID for scenarios where the information of an ID is especially relevant, rather than writing boilerplate ID reading code for varying situations. ## Changelog :cl: Bisar code: A proc has been added to the subsystem for ID access to serve to standardize the way information is read and returned from a given ID. /:cl: --- code/__DEFINES/access.dm | 5 ++ .../subsystem/networks/id_access.dm | 74 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index 1aa8a7f1e8c..34f08625483 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -595,3 +595,8 @@ #define FORCE_ADD_ALL 2 /// Used in ID card access adding procs. Will stack trace on fail. #define ERROR_ON_FAIL 3 + +#define ID_DATA(T) SSid_access.__in_character_record_id_information(T) +#define SILICON_OVERRIDE "silicon_override" +#define CHAMELEON_OVERRIDE "chameleon_override" +#define ID_READ_FAILURE "id_read_failure" diff --git a/code/controllers/subsystem/networks/id_access.dm b/code/controllers/subsystem/networks/id_access.dm index 720ac3d14de..027ab454e42 100644 --- a/code/controllers/subsystem/networks/id_access.dm +++ b/code/controllers/subsystem/networks/id_access.dm @@ -519,3 +519,77 @@ SUBSYSTEM_DEF(id_access) tally++ return tally + +/** + * Helper proc for creating a copy of the in-character information you could render from scanning for an ID card. + * Accounts for chameleon cards, silicons, and ID read failures. + * Pertinently, it also returns relevant information for their bank account (if they have one). + * To return bank account info for a chameleon card, bypass_chameleon must be set to TRUE. Otherwise it returns + * a bogey record. + * datum/source - + */ +/datum/controller/subsystem/id_access/proc/__in_character_record_id_information( + atom/movable/target_of_record, + bypass_chameleon = FALSE + ) as /alist + + var/alist/returned_record = alist( + "Name" = null, + "Age" = null, + "Assignment" = null, + "Account ID" = null, + "Account Holder" = null, + "Account Assignment" = null, + "Accesses" = null, + ) + . = returned_record + if(isnull(target_of_record)) + .["Name"] = ID_READ_FAILURE + .["Age"] = ID_READ_FAILURE + .["Assignment"] = ID_READ_FAILURE + .["Account ID"] = ID_READ_FAILURE + .["Account Holder"] = ID_READ_FAILURE + .["Account Assignment"] = ID_READ_FAILURE + .[ID_READ_FAILURE] = ID_READ_FAILURE + return . + var/mob/living/target = astype(target_of_record, /mob/living) + if(target) + if(!issilicon(target)) + . = __in_character_record_id_information(astype(target.get_idcard(), /obj/item/card/id/advanced)) + return . + .["Name"] = target.name + .["Age"] = "INSPECT MANUFACTURER MANIFEST" + .["Account ID"] = 0 + .["Account Holder"] = "NO ACCOUNT." + .["Account Assignment"] = "NO ACCOUNT." + .["Bank Account"] = "N/A" + .["Assignment"] = target.mind?.assigned_role?.title + .[SILICON_OVERRIDE] = SILICON_OVERRIDE + return . + var/obj/item/card/id/advanced/id_card = astype(target_of_record, /obj/item/card/id/advanced) + if(id_card) + .["Name"] = id_card.registered_name || "Unknown" + .["Age"] = id_card.registered_age || "Unknown" + .["Assignment"] = id_card.assignment || "Unassigned" + .["Accesses"] = id_card.access + var/datum/bank_account/id_account = id_card.registered_account + if(istype(id_card, /obj/item/card/id/advanced/chameleon) && !bypass_chameleon) + // Generate a bogey record based only on the ID card + // Generates a random bank account number every time as a 'spot the thread' for anyone who + // went through records for this entry for whatever reason. + .["Account ID"] = rand(111111, 999999) + .["Account Holder"] = .["Name"] + .["Account Assignment"] = .["Assignment"] + .[CHAMELEON_OVERRIDE] = CHAMELEON_OVERRIDE + return . + if(!id_account) + .["Account ID"] = 0 + .["Account Holder"] = "NO ACCOUNT." + .["Account Assignment"] = "NO ACCOUNT." + return . + .["Account ID"] = id_account.account_id + .["Account Holder"] = id_account.account_holder + .["Account Assignment"] = id_account.account_job?.title || "Unassigned" + return . + else + . = ID_DATA(null)