-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
id_access.dm
482 lines (423 loc) · 20.2 KB
/
id_access.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
/**
* Non-processing subsystem that holds various procs and data structures to manage ID cards, trims and access.
*/
SUBSYSTEM_DEF(id_access)
name = "IDs and Access"
init_order = INIT_ORDER_IDACCESS
flags = SS_NO_FIRE
/// Dictionary of access flags. Keys are accesses. Values are their associated bitflags.
var/list/flags_by_access = list()
/// Dictionary of access lists. Keys are access flag names. Values are lists of all accesses as part of that access.
var/list/accesses_by_flag = list()
/// Dictionary of access flag string representations. Keys are bitflags. Values are their associated names.
var/list/access_flag_string_by_flag = list()
/// Dictionary of trim singletons. Keys are paths. Values are their associated singletons.
var/list/trim_singletons_by_path = list()
/// Dictionary of wildcard compatibility flags. Keys are strings for the wildcards. Values are their associated flags.
var/list/wildcard_flags_by_wildcard = list()
/// Dictionary of accesses based on station region. Keys are region strings. Values are lists of accesses.
var/list/accesses_by_region = list()
/// Specially formatted list for sending access levels to tgui interfaces.
var/list/all_region_access_tgui = list()
/// Dictionary of access names. Keys are access levels. Values are their associated names.
var/list/desc_by_access = list()
/// List of accesses for the Heads of each sub-department alongside the regions they control and their job name.
var/list/sub_department_managers_tgui = list()
/// Helper list containing all trim paths that can be used as job templates. Intended to be used alongside logic for ACCESS_CHANGE_IDS. Grab templates from sub_department_managers_tgui for Head of Staff restrictions.
var/list/station_job_templates = list()
/// Helper list containing all trim paths that can be used as Centcom templates.
var/list/centcom_job_templates = list()
/// Helper list containing all PDA paths that can be painted by station machines. Intended to be used alongside logic for ACCESS_CHANGE_IDS. Grab templates from sub_department_managers_tgui for Head of Staff restrictions.
var/list/station_pda_templates = list()
/// Helper list containing all station regions.
var/list/station_regions = list()
/// The roundstart generated code for the spare ID safe. This is given to the Captain on shift start. If there's no Captain, it's given to the HoP. If there's no HoP
var/spare_id_safe_code = ""
/datum/controller/subsystem/id_access/Initialize(timeofday)
// We use this because creating the trim singletons requires the config to be loaded.
setup_access_flags()
setup_region_lists()
setup_trim_singletons()
setup_wildcard_dict()
setup_access_descriptions()
setup_tgui_lists()
spare_id_safe_code = "[rand(0,9)][rand(0,9)][rand(0,9)][rand(0,9)][rand(0,9)]"
return ..()
/**
* Called by [/datum/controller/subsystem/ticker/proc/setup]
*
* This runs through every /datum/id_trim/job singleton and ensures that its access is setup according to
* appropriate config entries.
*/
/datum/controller/subsystem/id_access/proc/refresh_job_trim_singletons()
for(var/trim in typesof(/datum/id_trim/job))
var/datum/id_trim/job/job_trim = trim_singletons_by_path[trim]
if(QDELETED(job_trim))
stack_trace("Trim \[[trim]\] missing from trim singleton list. Reinitialising this trim.")
trim_singletons_by_path[trim] = new trim()
continue
job_trim.refresh_trim_access()
/// Build access flag lists.
/datum/controller/subsystem/id_access/proc/setup_access_flags()
accesses_by_flag["[ACCESS_FLAG_COMMON]"] = COMMON_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_COMMON]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_COMMON)
accesses_by_flag["[ACCESS_FLAG_COMMAND]"] = COMMAND_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_COMMAND]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_COMMAND)
accesses_by_flag["[ACCESS_FLAG_PRV_COMMAND]"] = PRIVATE_COMMAND_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_PRV_COMMAND]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_PRV_COMMAND)
accesses_by_flag["[ACCESS_FLAG_CAPTAIN]"] = CAPTAIN_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_CAPTAIN]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_CAPTAIN)
accesses_by_flag["[ACCESS_FLAG_CENTCOM]"] = CENTCOM_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_CENTCOM]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_CENTCOM)
accesses_by_flag["[ACCESS_FLAG_SYNDICATE]"] = SYNDICATE_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_SYNDICATE]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_SYNDICATE)
accesses_by_flag["[ACCESS_FLAG_AWAY]"] = AWAY_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_AWAY]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_AWAY)
accesses_by_flag["[ACCESS_FLAG_SPECIAL]"] = CULT_ACCESS
for(var/access in accesses_by_flag["[ACCESS_FLAG_SPECIAL]"])
flags_by_access |= list("[access]" = ACCESS_FLAG_SPECIAL)
access_flag_string_by_flag["[ACCESS_FLAG_COMMON]"] = ACCESS_FLAG_COMMON_NAME
access_flag_string_by_flag["[ACCESS_FLAG_COMMAND]"] = ACCESS_FLAG_COMMAND_NAME
access_flag_string_by_flag["[ACCESS_FLAG_PRV_COMMAND]"] = ACCESS_FLAG_PRV_COMMAND_NAME
access_flag_string_by_flag["[ACCESS_FLAG_CAPTAIN]"] = ACCESS_FLAG_CAPTAIN_NAME
access_flag_string_by_flag["[ACCESS_FLAG_CENTCOM]"] = ACCESS_FLAG_CENTCOM_NAME
access_flag_string_by_flag["[ACCESS_FLAG_SYNDICATE]"] = ACCESS_FLAG_SYNDICATE_NAME
access_flag_string_by_flag["[ACCESS_FLAG_AWAY]"] = ACCESS_FLAG_AWAY_NAME
access_flag_string_by_flag["[ACCESS_FLAG_SPECIAL]"] = ACCESS_FLAG_SPECIAL_NAME
/// Populates the region lists with data about which accesses correspond to which regions.
/datum/controller/subsystem/id_access/proc/setup_region_lists()
accesses_by_region[REGION_ALL_STATION] = REGION_ACCESS_ALL_STATION
accesses_by_region[REGION_ALL_GLOBAL] = REGION_ACCESS_ALL_GLOBAL
accesses_by_region[REGION_GENERAL] = REGION_ACCESS_GENERAL
accesses_by_region[REGION_SECURITY] = REGION_ACCESS_SECURITY
accesses_by_region[REGION_MEDBAY] = REGION_ACCESS_MEDBAY
accesses_by_region[REGION_RESEARCH] = REGION_ACCESS_RESEARCH
accesses_by_region[REGION_ENGINEERING] = REGION_ACCESS_ENGINEERING
accesses_by_region[REGION_SUPPLY] = REGION_ACCESS_SUPPLY
accesses_by_region[REGION_COMMAND] = REGION_ACCESS_COMMAND
accesses_by_region[REGION_CENTCOM] = REGION_ACCESS_CENTCOM
station_regions = REGION_AREA_STATION
/// Instantiate trim singletons and add them to a list.
/datum/controller/subsystem/id_access/proc/setup_trim_singletons()
for(var/trim in typesof(/datum/id_trim))
trim_singletons_by_path[trim] = new trim()
/// Creates various data structures that primarily get fed to tgui interfaces, although these lists are used in other places.
/datum/controller/subsystem/id_access/proc/setup_tgui_lists()
for(var/region in accesses_by_region)
var/list/region_access = accesses_by_region[region]
var/parsed_accesses = list()
for(var/access in region_access)
var/access_desc = get_access_desc(access)
if(!access_desc)
continue
parsed_accesses += list(list(
"desc" = replacetext(access_desc, " ", " "),
"ref" = access,
))
all_region_access_tgui[region] = list(list(
"name" = region,
"accesses" = parsed_accesses,
))
sub_department_managers_tgui = list(
"[ACCESS_CAPTAIN]" = list(
"regions" = list(REGION_COMMAND),
"head" = "Captain",
"templates" = list(),
"pdas" = list(),
),
"[ACCESS_HOP]" = list(
"regions" = list(REGION_GENERAL, REGION_SUPPLY),
"head" = "Head of Personnel",
"templates" = list(),
"pdas" = list(),
),
"[ACCESS_HOS]" = list(
"regions" = list(REGION_SECURITY),
"head" = "Head of Security",
"templates" = list(),
"pdas" = list(),
),
"[ACCESS_CMO]" = list(
"regions" = list(REGION_MEDBAY),
"head" = "Chief Medical Officer",
"templates" = list(),
"pdas" = list(),
),
"[ACCESS_RD]" = list(
"regions" = list(REGION_RESEARCH),
"head" = "Research Director",
"templates" = list(),
"pdas" = list(),
),
"[ACCESS_CE]" = list(
"regions" = list(REGION_ENGINEERING),
"head" = "Chief Engineer",
"templates" = list(),
"pdas" = list(),
),
)
var/list/station_job_trims = subtypesof(/datum/id_trim/job)
for(var/trim_path in station_job_trims)
var/datum/id_trim/job/trim = trim_singletons_by_path[trim_path]
if(!length(trim.template_access))
continue
station_job_templates[trim_path] = trim.assignment
for(var/access in trim.template_access)
var/list/manager = sub_department_managers_tgui["[access]"]
if(!manager)
if(access != ACCESS_CHANGE_IDS)
WARNING("Invalid template access access \[[access]\] registered with [trim_path]. Template added to global list anyway.")
continue
var/list/templates = manager["templates"]
templates[trim_path] = trim.assignment
var/list/centcom_job_trims = typesof(/datum/id_trim/centcom) - typesof(/datum/id_trim/centcom/corpse)
for(var/trim_path in centcom_job_trims)
var/datum/id_trim/trim = trim_singletons_by_path[trim_path]
centcom_job_templates[trim_path] = trim.assignment
var/list/all_pda_paths = typesof(/obj/item/pda)
var/list/pda_regions = PDA_PAINTING_REGIONS
for(var/pda_path in all_pda_paths)
if(!(pda_path in pda_regions))
continue
var/list/region_whitelist = pda_regions[pda_path]
for(var/access_txt in sub_department_managers_tgui)
var/list/manager_info = sub_department_managers_tgui[access_txt]
var/list/manager_regions = manager_info["regions"]
for(var/whitelisted_region in region_whitelist)
if(!(whitelisted_region in manager_regions))
continue
var/list/manager_pdas = manager_info["pdas"]
var/obj/item/pda/fake_pda = pda_path
manager_pdas[pda_path] = initial(fake_pda.name)
station_pda_templates[pda_path] = initial(fake_pda.name)
/// Set up dictionary to convert wildcard names to flags.
/datum/controller/subsystem/id_access/proc/setup_wildcard_dict()
wildcard_flags_by_wildcard[WILDCARD_NAME_ALL] = WILDCARD_FLAG_ALL
wildcard_flags_by_wildcard[WILDCARD_NAME_COMMON] = WILDCARD_FLAG_COMMON
wildcard_flags_by_wildcard[WILDCARD_NAME_COMMAND] = WILDCARD_FLAG_COMMAND
wildcard_flags_by_wildcard[WILDCARD_NAME_PRV_COMMAND] = WILDCARD_FLAG_PRV_COMMAND
wildcard_flags_by_wildcard[WILDCARD_NAME_CAPTAIN] = WILDCARD_FLAG_CAPTAIN
wildcard_flags_by_wildcard[WILDCARD_NAME_CENTCOM] = WILDCARD_FLAG_CENTCOM
wildcard_flags_by_wildcard[WILDCARD_NAME_SYNDICATE] = WILDCARD_FLAG_SYNDICATE
wildcard_flags_by_wildcard[WILDCARD_NAME_AWAY] = WILDCARD_FLAG_AWAY
wildcard_flags_by_wildcard[WILDCARD_NAME_SPECIAL] = WILDCARD_FLAG_SPECIAL
wildcard_flags_by_wildcard[WILDCARD_NAME_FORCED] = WILDCARD_FLAG_FORCED
/// Setup dictionary that converts access levels to text descriptions.
/datum/controller/subsystem/id_access/proc/setup_access_descriptions()
desc_by_access["[ACCESS_CARGO]"] = "Cargo Bay"
desc_by_access["[ACCESS_SECURITY]"] = "Security"
desc_by_access["[ACCESS_BRIG]"] = "Holding Cells"
desc_by_access["[ACCESS_COURT]"] = "Courtroom"
desc_by_access["[ACCESS_FORENSICS_LOCKERS]"] = "Forensics"
desc_by_access["[ACCESS_MEDICAL]"] = "Medical"
desc_by_access["[ACCESS_GENETICS]"] = "Genetics Lab"
desc_by_access["[ACCESS_MORGUE]"] = "Morgue"
desc_by_access["[ACCESS_RND]"] = "R&D Lab"
desc_by_access["[ACCESS_ORDNANCE]"] = "Ordnance Lab"
desc_by_access["[ACCESS_ORDNANCE_STORAGE]"] = "Ordnance Storage"
desc_by_access["[ACCESS_CHEMISTRY]"] = "Chemistry Lab"
desc_by_access["[ACCESS_RD]"] = "RD Office"
desc_by_access["[ACCESS_BAR]"] = "Bar"
desc_by_access["[ACCESS_JANITOR]"] = "Custodial Closet"
desc_by_access["[ACCESS_ENGINE]"] = "Engineering"
desc_by_access["[ACCESS_ENGINE_EQUIP]"] = "Power and Engineering Equipment"
desc_by_access["[ACCESS_MAINT_TUNNELS]"] = "Maintenance"
desc_by_access["[ACCESS_EXTERNAL_AIRLOCKS]"] = "External Airlocks"
desc_by_access["[ACCESS_CHANGE_IDS]"] = "ID Console"
desc_by_access["[ACCESS_AI_UPLOAD]"] = "AI Chambers"
desc_by_access["[ACCESS_TELEPORTER]"] = "Teleporter"
desc_by_access["[ACCESS_EVA]"] = "EVA"
desc_by_access["[ACCESS_HEADS]"] = "Bridge"
desc_by_access["[ACCESS_CAPTAIN]"] = "Captain"
desc_by_access["[ACCESS_ALL_PERSONAL_LOCKERS]"] = "Personal Lockers"
desc_by_access["[ACCESS_CHAPEL_OFFICE]"] = "Chapel Office"
desc_by_access["[ACCESS_TECH_STORAGE]"] = "Technical Storage"
desc_by_access["[ACCESS_ATMOSPHERICS]"] = "Atmospherics"
desc_by_access["[ACCESS_CREMATORIUM]"] = "Crematorium"
desc_by_access["[ACCESS_ARMORY]"] = "Armory"
desc_by_access["[ACCESS_CONSTRUCTION]"] = "Construction"
desc_by_access["[ACCESS_KITCHEN]"] = "Kitchen"
desc_by_access["[ACCESS_HYDROPONICS]"] = "Hydroponics"
desc_by_access["[ACCESS_LIBRARY]"] = "Library"
desc_by_access["[ACCESS_LAWYER]"] = "Law Office"
desc_by_access["[ACCESS_ROBOTICS]"] = "Robotics"
desc_by_access["[ACCESS_VIROLOGY]"] = "Virology"
desc_by_access["[ACCESS_PSYCHOLOGY]"] = "Psychology"
desc_by_access["[ACCESS_CMO]"] = "CMO Office"
desc_by_access["[ACCESS_QM]"] = "Quartermaster"
desc_by_access["[ACCESS_SURGERY]"] = "Surgery"
desc_by_access["[ACCESS_THEATRE]"] = "Theatre"
desc_by_access["[ACCESS_RESEARCH]"] = "Science"
desc_by_access["[ACCESS_MINING]"] = "Mining"
desc_by_access["[ACCESS_MAILSORTING]"] = "Cargo Office"
desc_by_access["[ACCESS_VAULT]"] = "Main Vault"
desc_by_access["[ACCESS_MINING_STATION]"] = "Mining EVA"
desc_by_access["[ACCESS_XENOBIOLOGY]"] = "Xenobiology Lab"
desc_by_access["[ACCESS_HOP]"] = "HoP Office"
desc_by_access["[ACCESS_HOS]"] = "HoS Office"
desc_by_access["[ACCESS_CE]"] = "CE Office"
desc_by_access["[ACCESS_PHARMACY]"] = "Pharmacy"
desc_by_access["[ACCESS_RC_ANNOUNCE]"] = "RC Announcements"
desc_by_access["[ACCESS_KEYCARD_AUTH]"] = "Keycode Auth."
desc_by_access["[ACCESS_TCOMSAT]"] = "Telecommunications"
desc_by_access["[ACCESS_GATEWAY]"] = "Gateway"
desc_by_access["[ACCESS_SEC_DOORS]"] = "Brig"
desc_by_access["[ACCESS_MINERAL_STOREROOM]"] = "Mineral Storage"
desc_by_access["[ACCESS_MINISAT]"] = "AI Satellite"
desc_by_access["[ACCESS_WEAPONS]"] = "Weapon Permit"
desc_by_access["[ACCESS_NETWORK]"] = "Network Access"
desc_by_access["[ACCESS_MECH_MINING]"] = "Mining Mech Access"
desc_by_access["[ACCESS_MECH_MEDICAL]"] = "Medical Mech Access"
desc_by_access["[ACCESS_MECH_SECURITY]"] = "Security Mech Access"
desc_by_access["[ACCESS_MECH_SCIENCE]"] = "Science Mech Access"
desc_by_access["[ACCESS_MECH_ENGINE]"] = "Engineering Mech Access"
desc_by_access["[ACCESS_AUX_BASE]"] = "Auxiliary Base"
desc_by_access["[ACCESS_CENT_GENERAL]"] = "Code Grey"
desc_by_access["[ACCESS_CENT_THUNDER]"] = "Code Yellow"
desc_by_access["[ACCESS_CENT_STORAGE]"] = "Code Orange"
desc_by_access["[ACCESS_CENT_LIVING]"] = "Code Green"
desc_by_access["[ACCESS_CENT_MEDICAL]"] = "Code White"
desc_by_access["[ACCESS_CENT_TELEPORTER]"] = "Code Blue"
desc_by_access["[ACCESS_CENT_SPECOPS]"] = "Code Black"
desc_by_access["[ACCESS_CENT_CAPTAIN]"] = "Code Gold"
desc_by_access["[ACCESS_CENT_BAR]"] = "Code Scotch"
/**
* Returns the access bitflags associated with any given access level.
*
* In proc form due to accesses being stored in the list as text instead of numbers.
* Arguments:
* * access - Access as either pure number or as a string representation of the number.
*/
/datum/controller/subsystem/id_access/proc/get_access_flag(access)
var/flag = flags_by_access["[access]"]
return flag
/**
* Returns the access description associated with any given access level.
*
* In proc form due to accesses being stored in the list as text instead of numbers.
* Arguments:
* * access - Access as either pure number or as a string representation of the number.
*/
/datum/controller/subsystem/id_access/proc/get_access_desc(access)
return desc_by_access["[access]"]
/**
* Builds and returns a list of accesses from a list of regions.
*
* Arguments:
* * regions - A list of region defines.
*/
/datum/controller/subsystem/id_access/proc/get_region_access_list(list/regions)
if(!length(regions))
return
var/list/built_region_list = list()
for(var/region in regions)
built_region_list |= accesses_by_region[region]
return built_region_list
/**
* Returns the list of all accesses associated with any given access flag.
*
* In proc form due to accesses being stored in the list as text instead of numbers.
* Arguments:
* * flag - The flag to get access for as either a pure number of string representation of the flag.
*/
/datum/controller/subsystem/id_access/proc/get_flag_access_list(flag)
return accesses_by_flag["[flag]"]
/**
* Applies a trim singleton to a card.
*
* Returns FALSE if the trim could not be applied due to being incompatible with the card.
* Incompatibility is defined as a card not being able to hold all the trim's required wildcards.
* Returns TRUE otherwise.
* Arguments:
* * id_card - ID card to apply the trim_path to.
* * trim_path - A trim path to apply to the card. Grabs the trim's associated singleton and applies it.
* * copy_access - Boolean value. If true, the trim's access is also copied to the card.
*/
/datum/controller/subsystem/id_access/proc/apply_trim_to_card(obj/item/card/id/id_card, trim_path, copy_access = TRUE)
var/datum/id_trim/trim = trim_singletons_by_path[trim_path]
if(!id_card.can_add_wildcards(trim.wildcard_access))
return FALSE
id_card.clear_access()
id_card.trim = trim
if(copy_access)
id_card.access = trim.access.Copy()
id_card.add_wildcards(trim.wildcard_access)
if(trim.assignment)
id_card.assignment = trim.assignment
id_card.update_label()
id_card.update_icon()
return TRUE
/**
* Removes a trim from an ID card. Also removes all accesses from it too.
*
* Arguments:
* * id_card - The ID card to remove the trim from.
*/
/datum/controller/subsystem/id_access/proc/remove_trim_from_card(obj/item/card/id/id_card)
id_card.trim = null
id_card.clear_access()
id_card.update_label()
id_card.update_icon()
/**
* Applies a trim to a chameleon card. This is purely visual, utilising the card's override vars.
*
* Arguments:
* * id_card - The chameleon card to apply the trim visuals to.
* * trim_path - A trim path to apply to the card. Grabs the trim's associated singleton and applies it.
* * check_forged - Boolean value. If TRUE, will not overwrite the card's assignment if the card has been forged.
*/
/datum/controller/subsystem/id_access/proc/apply_trim_to_chameleon_card(obj/item/card/id/advanced/chameleon/id_card, trim_path, check_forged = TRUE)
var/datum/id_trim/trim = trim_singletons_by_path[trim_path]
id_card.trim_icon_override = trim.trim_icon
id_card.trim_state_override = trim.trim_state
id_card.trim_assignment_override = trim.assignment
if(!check_forged || !id_card.forged)
id_card.assignment = trim.assignment
// We'll let the chameleon action update the card's label as necessary instead of doing it here.
/**
* Removes a trim from a chameleon ID card.
*
* Arguments:
* * id_card - The ID card to remove the trim from.
*/
/datum/controller/subsystem/id_access/proc/remove_trim_from_chameleon_card(obj/item/card/id/advanced/chameleon/id_card)
id_card.trim_icon_override = null
id_card.trim_state_override = null
id_card.trim_assignment_override = null
/**
* Adds the accesses associated with a trim to an ID card.
*
* Clears the card's existing access levels first.
* Primarily intended for applying trim templates to cards. Will attempt to add as many ordinary access
* levels as it can, without consuming any wildcards. Will then attempt to apply the trim-specific wildcards after.
*
* Arguments:
* * id_card - The ID card to remove the trim from.
*/
/datum/controller/subsystem/id_access/proc/add_trim_access_to_card(obj/item/card/id/id_card, trim_path)
var/datum/id_trim/trim = trim_singletons_by_path[trim_path]
id_card.clear_access()
id_card.add_access(trim.access, mode = TRY_ADD_ALL_NO_WILDCARD)
id_card.add_wildcards(trim.wildcard_access, mode = TRY_ADD_ALL)
/**
* Tallies up all accesses the card has that have flags greater than or equal to the access_flag supplied.
*
* Returns the number of accesses that have flags matching access_flag or a higher tier access.
* Arguments:
* * id_card - The ID card to tally up access for.
* * access_flag - The minimum access flag required for an access to be tallied up.
*/
/datum/controller/subsystem/id_access/proc/tally_access(obj/item/card/id/id_card, access_flag = NONE)
var/tally = 0
var/list/id_card_access = id_card.access
for(var/access in id_card_access)
if(flags_by_access["[access]"] >= access_flag)
tally++
return tally