From cf41110420d03981136f2936db37cb293e3df17b Mon Sep 17 00:00:00 2001
From: vode-code <65709050+vode-code@users.noreply.github.com>
Date: Tue, 9 Sep 2025 15:31:21 -0700
Subject: [PATCH 1/3] Data Core Must Die
(https://github.com/discordia-space/CEV-Eris/pull/8594)
* the datacore is dead, long live the crew record file list
apparently this stuff dates back to may 2012
new savefile version clears out old records preferences
reworked security records
character name replacer proc updates renamed items
reversed records sort polarity
reworked respawn character proc
adds setup disks for preset console programs
reduced security and medical file cabinet data to that which could be reasonably accurate for an entire round
deleted unused real rank system
fixed potential fake crew arrival runtime
cargo positions now named guild positions and JOBS_CARGO is now JOBS_GUILD
nonhuman positions now named silicon positions and JOBS_NONHUMAN is now JOBS_SILICON
world manifest now checks department rather than preset job names
updated PAI general, medical, and security records access program
fixed freelancer perk define name
added green thumb and neat job perk defines
deleted duplicate records customization file numbered 5
pruned record customization
WIP
* return to default for datacore purge
update note: setup disks merged seperately
security notes simplified
---------
Co-authored-by: Humonitarian <61586732+Humonitarian@users.noreply.github.com>
---
cev_eris.dme | 5 +-
code/__DEFINES/jobs.dm | 4 +-
code/__DEFINES/perks.dm | 4 +-
code/__HELPERS/manifest.dm | 6 +-
code/__HELPERS/names.dm | 4 +-
code/__HELPERS/unsorted.dm | 23 +-
code/controllers/subsystems/ticker.dm | 1 -
code/datums/datacore.dm | 454 ------------
code/datums/setup_option/backgrounds/fate.dm | 2 +-
code/datums/topic/world.dm | 35 +-
code/datums/uplink/announcements.dm | 52 +-
code/defines/procs/announce.dm | 5 +-
code/game/jobs/jobs.dm | 6 +-
code/game/machinery/computer/medical.dm | 519 --------------
code/game/machinery/computer/security.dm | 658 ------------------
code/game/machinery/hologram.dm | 5 +-
code/game/objects/items/devices/uplink.dm | 8 +-
.../circuitboards/computer/computer.dm | 6 -
.../admin_secrets/show_crew_manifest.dm | 2 +-
code/modules/admin/verbs/randomverbs.dm | 24 +-
.../asset_cache/assets/legacyuiicons.dm | 5 +
.../preference_setup/background/03_records.dm | 114 ++-
.../preference_setup/general/05_records.dm | 64 --
.../loadout/lists/accessories.dm | 2 +-
.../preference_setup/loadout/lists/suits.dm | 4 +-
code/modules/client/preferences.dm | 5 +-
code/modules/client/preferences_savefile.dm | 2 +-
code/modules/economy/Accounts.dm | 6 +-
code/modules/mob/hear_say.dm | 5 +-
.../mob/living/carbon/human/examine.dm | 18 +-
code/modules/mob/living/carbon/human/human.dm | 265 +++----
.../mob/living/carbon/human/human_defines.dm | 3 -
code/modules/mob/living/living.dm | 13 +-
code/modules/mob/living/silicon/ai/ai.dm | 4 +-
code/modules/mob/living/silicon/pai/pai.dm | 12 +-
.../living/silicon/pai/software_modules.dm | 114 ++-
code/modules/mob/mob_helpers.dm | 6 +-
code/modules/mob/new_player/new_player.dm | 1 -
.../computers/modular_computer/core.dm | 2 +
.../modular_computers/file_system/program.dm | 5 +-
.../file_system/programs/command/card.dm | 2 +-
.../file_system/programs/generic/records.dm | 55 +-
.../file_system/reports/crew_record.dm | 173 ++++-
.../file_system/reports/report.dm | 17 +-
.../file_system/reports/report_field.dm | 149 +++-
code/modules/nano/modules/tgui_type.dm | 92 +++
code/modules/paperwork/filingcabinet.dm | 45 +-
code/modules/research/designs/circuits.dm | 10 -
code/modules/research/nodes/biotech.dm | 6 +-
icons/ui_icons/dmis/uiicons16.dmi | Bin 0 -> 6642 bytes
maps/CEVEris/_CEV_Eris.dmm | 19 +-
nano/templates/crew_records.tmpl | 21 +
nano/templates/pai_medrecords.tmpl | 54 +-
nano/templates/pai_secrecords.tmpl | 34 +-
tgui/packages/tgui/interfaces/Computer.tsx | 169 +++++
tgui/packages/tgui/interfaces/CrewRecords.tsx | 332 +++++++++
56 files changed, 1359 insertions(+), 2292 deletions(-)
delete mode 100644 code/datums/datacore.dm
delete mode 100644 code/game/machinery/computer/medical.dm
delete mode 100644 code/game/machinery/computer/security.dm
create mode 100644 code/modules/asset_cache/assets/legacyuiicons.dm
delete mode 100644 code/modules/client/preference_setup/general/05_records.dm
create mode 100644 code/modules/nano/modules/tgui_type.dm
create mode 100644 icons/ui_icons/dmis/uiicons16.dmi
create mode 100644 tgui/packages/tgui/interfaces/Computer.tsx
create mode 100644 tgui/packages/tgui/interfaces/CrewRecords.tsx
diff --git a/cev_eris.dme b/cev_eris.dme
index 3069d243330..306aaca93a5 100644
--- a/cev_eris.dme
+++ b/cev_eris.dme
@@ -357,7 +357,6 @@
#include "code\datums\chat_payload.dm"
#include "code\datums\chatmessage.dm"
#include "code\datums\contract.dm"
-#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"
#include "code\datums\datum_click_handlers.dm"
#include "code\datums\datum_hud.dm"
@@ -833,14 +832,12 @@
#include "code\game\machinery\computer\computer.dm"
#include "code\game\machinery\computer\guestpass.dm"
#include "code\game\machinery\computer\law.dm"
-#include "code\game\machinery\computer\medical.dm"
#include "code\game\machinery\computer\message.dm"
#include "code\game\machinery\computer\Operating.dm"
#include "code\game\machinery\computer\pod.dm"
#include "code\game\machinery\computer\prisoner.dm"
#include "code\game\machinery\computer\prisonshuttle.dm"
#include "code\game\machinery\computer\robot.dm"
-#include "code\game\machinery\computer\security.dm"
#include "code\game\machinery\computer\station_alert.dm"
#include "code\game\machinery\doors\airlock.dm"
#include "code\game\machinery\doors\airlock_control.dm"
@@ -1559,6 +1556,7 @@
#include "code\modules\asset_cache\assets\chat.dm"
#include "code\modules\asset_cache\assets\icon_ref_map.dm"
#include "code\modules\asset_cache\assets\notes.dm"
+#include "code\modules\asset_cache\assets\legacyuiicons.dm"
#include "code\modules\asset_cache\assets\sanity.dm"
#include "code\modules\asset_cache\assets\sheetmaterials.dm"
#include "code\modules\asset_cache\assets\stats.dm"
@@ -2404,6 +2402,7 @@
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\law_manager.dm"
#include "code\modules\nano\modules\nano_module.dm"
+#include "code\modules\nano\modules\tgui_type.dm"
#include "code\modules\onestar\generator.dm"
#include "code\modules\onestar\os_cash.dm"
#include "code\modules\onestar\os_turret.dm"
diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm
index 18a82d9b01c..2bebcf467e3 100644
--- a/code/__DEFINES/jobs.dm
+++ b/code/__DEFINES/jobs.dm
@@ -8,10 +8,10 @@
#define JOBS_MEDICAL "Moebius Biolab Officer","Moebius Doctor","Moebius Psychiatrist","Moebius Chemist","Moebius Paramedic","Moebius Bio-Engineer"
#define JOBS_SCIENCE "Moebius Expedition Overseer","Moebius Scientist","Moebius Roboticist"
#define JOBS_MOEBIUS "Moebius Biolab Officer","Moebius Doctor","Moebius Psychiatrist","Moebius Chemist","Moebius Paramedic","Moebius Bio-Engineer","Moebius Expedition Overseer","Moebius Scientist","Moebius Roboticist"
-#define JOBS_CARGO "Guild Merchant","Guild Technician","Guild Miner",
+#define JOBS_GUILD "Guild Merchant","Guild Technician","Guild Miner",
#define JOBS_CIVILIAN "Club Manager","Club Worker","Club Artist",ASSISTANT_TITLE
#define JOBS_CHURCH "NeoTheology Preacher","NeoTheology Acolyte","NeoTheology Agrolyte","NeoTheology Custodian"
-#define JOBS_NONHUMAN "AI","Robot","pAI"
+#define JOBS_SILICON "AI","Robot","pAI"
#define CREDITS "¢"
#define CREDS "¢"
diff --git a/code/__DEFINES/perks.dm b/code/__DEFINES/perks.dm
index 210eaa70c3e..d6571683e42 100644
--- a/code/__DEFINES/perks.dm
+++ b/code/__DEFINES/perks.dm
@@ -1,6 +1,6 @@
//fate perks
#define PERK_PAPER_WORM /datum/perk/fate/paper_worm
-#define PERK_FREELACER /datum/perk/fate/freelancer
+#define PERK_FREELANCER /datum/perk/fate/freelancer
#define PERK_NIHILIST /datum/perk/fate/nihilist
#define PERK_MORALIST /datum/perk/fate/moralist
#define PERK_ALCOHOLIC /datum/perk/fate/alcoholic
@@ -49,6 +49,8 @@
#define PERK_CODESPEAK_COP /datum/perk/codespeak
#define PERK_CODESPEAK_SERB /datum/perk/codespeak/serbian
#define PERK_TECHNOMANCER /datum/perk/inspiration
+#define PERK_NEAT /datum/perk/neat
+#define PERK_GREEN_THUMB /datum/perk/greenthumb
#define PERK_CLUB /datum/perk/job/club
#define PERK_CHANNELING /datum/perk/channeling
diff --git a/code/__HELPERS/manifest.dm b/code/__HELPERS/manifest.dm
index 66527c5ebc7..135cb4a23fd 100644
--- a/code/__HELPERS/manifest.dm
+++ b/code/__HELPERS/manifest.dm
@@ -142,13 +142,13 @@
"sec" = filtered_nano_crew_manifest(security_positions),\
"eng" = filtered_nano_crew_manifest(engineering_positions),\
"med" = filtered_nano_crew_manifest(medical_positions),\
- "sup" = filtered_nano_crew_manifest(cargo_positions),\
+ "sup" = filtered_nano_crew_manifest(guild_positions),\
"chr" = filtered_nano_crew_manifest(church_positions),\
- "bot" = silicon_nano_crew_manifest(nonhuman_positions),\
+ "bot" = silicon_nano_crew_manifest(silicon_positions),\
"civ" = filtered_nano_crew_manifest(civilian_positions)\
)
/proc/flat_nano_crew_manifest()
. = list()
. += filtered_nano_crew_manifest(null, TRUE)
- . += silicon_nano_crew_manifest(nonhuman_positions)
+ . += silicon_nano_crew_manifest(silicon_positions)
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index 0c6b487f29f..0d3347c4a38 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -110,8 +110,8 @@ var/syndicate_code_response//Code response for contractors.
var/locations[] = SSmapping.teleportlocs.len ? SSmapping.teleportlocs : drinks//if null, defaults to drinks instead.
var/names[] = list()
- for(var/datum/data/record/t in data_core.general)//Picks from crew manifest.
- names += t.fields["name"]
+ for(var/datum/computer_file/report/crew_record/t in GLOB.all_crew_records)//Picks from crew manifest.
+ names += t.get_name()
var/maxwords = words//Extra var to check for duplicates.
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 775c9806297..26a1f8da684 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -276,26 +276,21 @@ Turf and target are seperate in case you want to teleport some distance from a t
mind.name = newname
if(oldname)
- //update the datacore records! This is goig to be a bit costly.
- for(var/list/L in list(data_core.general, data_core.medical, data_core.security, data_core.locked))
- for(var/datum/data/record/R in L)
- if(R.fields["name"] == oldname)
- R.fields["name"] = newname
- break
+ for(var/datum/computer_file/report/crew_record/R in GLOB.all_crew_records)
+ if(R.get_name() == oldname)
+ R.set_name(newname)
//update our pda and id if we have them on our person
- var/list/searching = GetAllContents(searchDepth = 3)
- var/search_id = 1
- var/search_pda = 1
-
- for(var/A in searching)
- if( search_id && istype(A,/obj/item/card/id) )
+ for(var/obj/A in GetAllContents(searchDepth = 3))
+ if(istype(A,/obj/item/card/id))
var/obj/item/card/id/ID = A
if(ID.registered_name == oldname)
ID.registered_name = newname
ID.name = "[newname]'s ID Card ([ID.assignment])"
- if(!search_pda) break
- search_id = 0
+ if(istype(A.loc, /obj/item/modular_computer))
+ var/obj/item/modular_computer/tolabel = A.loc
+ tolabel.update_label()
+ break
return 1
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index 839cbee07d3..d1aa6451fd0 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -264,7 +264,6 @@ SUBSYSTEM_DEF(ticker)
if(!H.mind || player_is_antag(H.mind, only_offstation_roles = 1) || !SSjob.ShouldCreateRecords(H.mind.assigned_role))
continue
CreateModularRecord(H)
- data_core.manifest()
CHECK_TICK
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
deleted file mode 100644
index 55f2af15562..00000000000
--- a/code/datums/datacore.dm
+++ /dev/null
@@ -1,454 +0,0 @@
-var/global/list/PDA_Manifest = list()
-var/global/ManifestJSON
-
-/hook/startup/proc/createDatacore()
- data_core = new /datum/datacore()
- return 1
-
-/datum/datacore
- var/name = "datacore"
- var/medical[] = list()
- var/general[] = list()
- var/security[] = list()
- //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
- var/locked[] = list()
-
-
-/datum/datacore/proc/get_manifest(monochrome, OOC)
- var/list/heads = new()
- var/list/sec = new()
- var/list/eng = new()
- var/list/med = new()
- var/list/sci = new()
- var/list/car = new()
- var/list/chr = new()
- var/list/civ = new()
- var/list/bot = new()
- var/list/misc = new()
- var/list/isactive = new()
- var/dat = {"
-
-
- Name Rank Activity
- "}
- var/even = 0
- // sort mobs
- for(var/datum/data/record/t in data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/real_rank = make_list_rank(t.fields["real_rank"])
-
- if(OOC)
- var/active = 0
- for(var/mob/M in GLOB.player_list)
- if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
- active = 1
- break
- isactive[name] = active ? "Active" : "Inactive"
- else
- isactive[name] = t.fields["p_stat"]
- //world << "[name]: [rank]"
- //cael - to prevent multiple appearances of a player/job combination, add a continue after each line
- var/department = 0
- if(real_rank in command_positions)
- heads[name] = rank
- department = 1
- if(real_rank in security_positions)
- sec[name] = rank
- department = 1
- if(real_rank in engineering_positions)
- eng[name] = rank
- department = 1
- if(real_rank in medical_positions)
- med[name] = rank
- department = 1
- if(real_rank in science_positions)
- sci[name] = rank
- department = 1
- if(real_rank in cargo_positions)
- car[name] = rank
- department = 1
- if(real_rank in church_positions)
- chr[name] = rank
- department = 1
- if(real_rank in civilian_positions)
- civ[name] = rank
- department = 1
- if(!department && !(name in heads))
- misc[name] = rank
-
- // Synthetics don't have actual records, so we will pull them from here.
-/* for(mob/living/silicon/ai/ai in SSmobs.mob_list)
- bot[ai.name] = "Artificial Intelligence"
-
- for(var/mob/living/silicon/robot/robot in SSmobs.mob_list)
- // No combat/syndicate cyborgs, no drones.
- if(robot.module && robot.module.hide_on_manifest)
- continue
-
- bot[robot.name] = "[robot.modtype] [robot.braintype]"*/
-
- if(bot.len > 0)
- dat += "Silicon "
- for(name in bot)
- dat += "[name] [bot[name]] [isactive[name]] "
- even = !even
-
- if(heads.len > 0)
- dat += "Heads "
- for(name in heads)
- dat += "[name] [heads[name]] [isactive[name]] "
- even = !even
- if(sec.len > 0)
- dat += "Security "
- for(name in sec)
- dat += "[name] [sec[name]] [isactive[name]] "
- even = !even
- if(eng.len > 0)
- dat += "Engineering "
- for(name in eng)
- dat += "[name] [eng[name]] [isactive[name]] "
- even = !even
- if(med.len > 0)
- dat += "Medical "
- for(name in med)
- dat += "[name] [med[name]] [isactive[name]] "
- even = !even
- if(sci.len > 0)
- dat += "Science "
- for(name in sci)
- dat += "[name] [sci[name]] [isactive[name]] "
- even = !even
- if(car.len > 0)
- dat += "Guild "
- for(name in car)
- dat += "[name] [car[name]] [isactive[name]] "
- even = !even
- if(chr.len > 0)
- dat += "Church "
- for(name in chr)
- dat += "[name] [chr[name]] [isactive[name]] "
- even = !even
- if(civ.len > 0)
- dat += "Civilian "
- for(name in civ)
- dat += "[name] [civ[name]] [isactive[name]] "
- even = !even
- if(misc.len > 0)
- dat += "Miscellaneous "
- for(name in misc)
- dat += "[name] [misc[name]] [isactive[name]] "
- even = !even
-
- dat += "
"
- dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
- dat = replacetext(dat, "\t", "")
- return dat
-
-/datum/datacore/proc/manifest()
- spawn()
- for(var/mob/living/carbon/human/H in GLOB.player_list)
- manifest_inject(H)
- return
-
-/datum/datacore/proc/manifest_modify(name, assignment)
- ResetPDAManifest()
- var/datum/data/record/foundrecord
- var/real_title = assignment
-
- for(var/datum/data/record/t in data_core.general)
- if (t)
- if(t.fields["name"] == name)
- foundrecord = t
- break
-
- if(foundrecord)
- foundrecord.fields["rank"] = assignment
- foundrecord.fields["real_rank"] = real_title
-
-/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H)
- if(H.mind && !player_is_antag(H.mind, only_offstation_roles = 1) && H.job != ASSISTANT_TITLE)
- var/assignment = GetAssignment(H)
-
- var/id = generate_record_id()
- //General Record
- var/datum/data/record/G = CreateGeneralRecord(H, id)
- G.fields["name"] = H.real_name
- G.fields["real_rank"] = H.mind.assigned_role
- G.fields["rank"] = assignment
- G.fields["age"] = H.age
- G.fields["fingerprint"] = H.fingers_trace
- if(H.mind.initial_account)
- G.fields["pay_account"] = H.mind.initial_account.account_number ? H.mind.initial_account.account_number : "N/A"
- G.fields["email"] = H.mind.initial_email_login["login"]
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["sex"] = H.gender
- if(H.gen_record && !jobban_isbanned(H, "Records"))
- G.fields["notes"] = H.gen_record
-
- //Medical Record
- var/datum/data/record/M = CreateMedicalRecord(H.real_name, id)
- M.fields["b_type"] = H.b_type
- M.fields["b_dna"] = H.dna_trace
- //M.fields["id_gender"] = gender2text(H.identifying_gender)
- if(H.med_record && !jobban_isbanned(H, "Records"))
- M.fields["notes"] = H.med_record
-
- //Security Record
- var/datum/data/record/S = CreateSecurityRecord(H.real_name, id)
- if(H.sec_record && !jobban_isbanned(H, "Records"))
- S.fields["notes"] = H.sec_record
-
- //Locked Record
- var/datum/data/record/L = new()
- L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]")
- L.fields["name"] = H.real_name
- L.fields["rank"] = H.mind.assigned_role
- L.fields["age"] = H.age
- L.fields["fingerprint"] = H.fingers_trace
- L.fields["sex"] = H.gender
- L.fields["b_type"] = H.b_type
- L.fields["b_dna"] = H.dna_trace
- L.fields["image"] = getFlatIcon(H) //This is god-awful
- if(H.exploit_record && !jobban_isbanned(H, "Records"))
- L.fields["exploit_record"] = H.exploit_record
- else
- L.fields["exploit_record"] = "No additional information acquired."
- locked += L
- return
-
-/proc/generate_record_id()
- return add_zero(num2hex(rand(1, 65535), 5), 4) //no point generating higher numbers because of the limitations of num2hex
-
-/proc/get_id_photo(mob/living/carbon/human/H, assigned_role)
-
- var/icon/preview_icon = new(H.stand_icon)
- var/icon/temp
-
- var/datum/sprite_accessory/hair_style = GLOB.hair_styles_list[H.h_style]
- if(hair_style)
- temp = new/icon(hair_style.icon, hair_style.icon_state)
- temp.Blend(H.hair_color, ICON_ADD)
-
- hair_style = GLOB.facial_hair_styles_list[H.h_style]
- if(hair_style)
- var/icon/facial = new/icon(hair_style.icon, hair_style.icon_state)
- facial.Blend(H.facial_color, ICON_ADD)
- temp.Blend(facial, ICON_OVERLAY)
-
- preview_icon.Blend(temp, ICON_OVERLAY)
-
-
- var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
- if(J)
- var/t_state
- temp = new /icon('icons/inventory/uniform/mob.dmi', t_state)
-
- temp.Blend(new /icon('icons/inventory/feet/mob.dmi', t_state), ICON_OVERLAY)
- else
- temp = new /icon('icons/inventory/uniform/mob.dmi', "grey")
- temp.Blend(new /icon('icons/inventory/feet/mob.dmi', "black"), ICON_OVERLAY)
-
- preview_icon.Blend(temp, ICON_OVERLAY)
-
- qdel(temp)
-
- return preview_icon
-
-/datum/datacore/proc/CreateGeneralRecord(mob/living/carbon/human/H, id)
- ResetPDAManifest()
- var/icon/front
- var/icon/side
- if(H)
- front = getFlatIcon(H, SOUTH)
- side = getFlatIcon(H, WEST)
- else
- var/mob/living/carbon/human/dummy = new()
- front = new(get_id_photo(dummy), dir = SOUTH)
- side = new(get_id_photo(dummy), dir = WEST)
- qdel(dummy)
-
- if(!id) id = text("[]", add_zero(num2hex(rand(1, 1.6777215E7), 8), 6))
- var/datum/data/record/G = new /datum/data/record()
- G.name = "Employee Record #[id]"
- G.fields["name"] = "New Record"
- G.fields["id"] = id
- G.fields["rank"] = "Unassigned"
- G.fields["real_rank"] = "Unassigned"
- G.fields["sex"] = "Male"
- G.fields["age"] = "Unknown"
- G.fields["fingerprint"] = "Unknown"
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["species"] = SPECIES_HUMAN
- G.fields["photo_front"] = front
- G.fields["photo_side"] = side
- G.fields["notes"] = "No notes found."
- general += G
-
- return G
-
-/datum/datacore/proc/CreateSecurityRecord(name, id)
- ResetPDAManifest()
- var/datum/data/record/R = new /datum/data/record()
- R.name = "Security Record #[id]"
- R.fields["name"] = name
- R.fields["id"] = id
- R.fields["criminal"] = "None"
- R.fields["mi_crim"] = "None"
- R.fields["mi_crim_d"] = "No minor crime convictions."
- R.fields["ma_crim"] = "None"
- R.fields["ma_crim_d"] = "No major crime convictions."
- R.fields["notes"] = "No notes."
- R.fields["notes"] = "No notes."
- data_core.security += R
-
- return R
-
-/datum/datacore/proc/CreateMedicalRecord(name, id)
- ResetPDAManifest()
- var/datum/data/record/M = new()
- M.name = "Medical Record #[id]"
- M.fields["id"] = id
- M.fields["name"] = name
- M.fields["b_type"] = "AB+"
- M.fields["b_dna"] = md5(name)
- M.fields["mi_dis"] = "None"
- M.fields["mi_dis_d"] = "No minor disabilities have been declared."
- M.fields["ma_dis"] = "None"
- M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
- M.fields["alg"] = "None"
- M.fields["alg_d"] = "No allergies have been detected in this patient."
- M.fields["cdi"] = "None"
- M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
- M.fields["notes"] = "No notes found."
- data_core.medical += M
-
- return M
-
-/datum/datacore/proc/ResetPDAManifest()
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
-
-/proc/find_general_record(field, value)
- return find_record(field, value, data_core.general)
-
-/proc/find_medical_record(field, value)
- return find_record(field, value, data_core.medical)
-
-/proc/find_security_record(field, value)
- return find_record(field, value, data_core.security)
-
-/proc/find_record(field, value, list/L)
- for(var/datum/data/record/R in L)
- if(R.fields[field] == value)
- return R
-
-/*/proc/GetAssignment(mob/living/carbon/human/H)
- if(H.mind.assigned_role)
- return H.mind.assigned_role
- else if(H.job)
- return H.job
- else
- return "Unassigned"
-*/
-var/list/acting_rank_prefixes = list("acting", "temporary", "interim", "provisional")
-
-/proc/make_list_rank(rank)
- for(var/prefix in acting_rank_prefixes)
- if(findtext(rank, "[prefix] ", 1, 2+length(prefix)))
- return copytext(rank, 2+length(prefix))
- return rank
-
-/datum/datacore/proc/get_manifest_json()
- if(PDA_Manifest.len)
- return
- var/heads[0]
- var/sec[0]
- var/eng[0]
- var/med[0]
- var/sci[0]
- var/chr[0]
- var/civ[0]
- var/bot[0]
- var/misc[0]
- for(var/datum/data/record/t in data_core.general)
- var/name = sanitize(t.fields["name"])
- var/rank = sanitize(t.fields["rank"])
- var/real_rank = make_list_rank(t.fields["real_rank"])
-
- var/isactive = t.fields["p_stat"]
- var/department = 0
- var/depthead = 0 // Department Heads will be placed at the top of their lists.
- if(real_rank in command_positions)
- heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- depthead = 1
- if(rank=="Captain" && heads.len != 1)
- heads.Swap(1, heads.len)
-
- if(real_rank in security_positions)
- sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && sec.len != 1)
- sec.Swap(1, sec.len)
-
- if(real_rank in engineering_positions)
- eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && eng.len != 1)
- eng.Swap(1, eng.len)
-
- if(real_rank in medical_positions)
- med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && med.len != 1)
- med.Swap(1, med.len)
-
- if(real_rank in science_positions)
- sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && sci.len != 1)
- sci.Swap(1, sci.len)
-
- if(real_rank in church_positions)
- chr[++chr.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && chr.len != 1)
- chr.Swap(1, chr.len)
-
- if(real_rank in civilian_positions)
- civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && civ.len != 1)
- civ.Swap(1, civ.len)
-
- if(real_rank in nonhuman_positions)
- bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
-
- if(!department && !(name in heads))
- misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
-
-
- PDA_Manifest = list(
- "heads" = heads,
- "sec" = sec,
- "eng" = eng,
- "med" = med,
- "sci" = sci,
- "chr" = chr,
- "civ" = civ,
- "bot" = bot,
- "misc" = misc
- )
- ManifestJSON = json_encode(PDA_Manifest)
- return
diff --git a/code/datums/setup_option/backgrounds/fate.dm b/code/datums/setup_option/backgrounds/fate.dm
index 8093c95bbc3..3cda4c9d8e7 100644
--- a/code/datums/setup_option/backgrounds/fate.dm
+++ b/code/datums/setup_option/backgrounds/fate.dm
@@ -26,7 +26,7 @@
You were always on the move, looking for a brighter future on the other side. \
And because of that you never specialised as much as you should, but have broader array of other skills."
- perks = list(PERK_FREELACER)
+ perks = list(PERK_FREELANCER)
/datum/category_item/setup_option/background/fate/nihilist
name = "Nihilist"
diff --git a/code/datums/topic/world.dm b/code/datums/topic/world.dm
index 2fe29f219d7..795bf628537 100644
--- a/code/datums/topic/world.dm
+++ b/code/datums/topic/world.dm
@@ -94,31 +94,16 @@
/datum/world_topic/manifest/Run(list/input)
var/list/positions = list()
- var/list/set_names = list(
- "heads" = command_positions,
- "sec" = security_positions,
- "eng" = engineering_positions,
- "med" = medical_positions,
- "sci" = science_positions,
- "car" = cargo_positions,
- "civ" = civilian_positions,
- "chr" = church_positions,
- "bot" = nonhuman_positions
- )
-
- for(var/datum/data/record/t in data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/real_rank = make_list_rank(t.fields["real_rank"])
-
- var/department = FALSE
- for(var/k in set_names)
- if(real_rank in set_names[k])
- if(!positions[k])
- positions[k] = list()
- positions[k][name] = rank
- department = TRUE
- if(!department)
+
+ for(var/datum/computer_file/report/crew_record/t in GLOB.all_crew_records)
+ var/name = t.get_name()
+ var/rank = t.get_job()
+
+ var/department = t.get_department()
+
+ if(department && department != "Unset")
+ positions[department][name] = rank
+ else
if(!positions["misc"])
positions["misc"] = list()
positions["misc"][name] = rank
diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index 9691d597d4b..9597596ce90 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -38,48 +38,42 @@
return 0
var/obj/item/card/id/I = user.GetIdCard()
- var/datum/data/record/random_general_record
- var/datum/data/record/random_medical_record
- if(data_core.general.len)
- random_general_record = pick(data_core.general)
- random_medical_record = find_medical_record("id", random_general_record.fields["id"])
+ var/datum/computer_file/report/crew_record/random_record
+ if(GLOB.all_crew_records.len)
+ random_record = pick(GLOB.all_crew_records)
- var/datum/data/record/general = data_core.CreateGeneralRecord(user)
+ var/datum/computer_file/report/crew_record/general = new()
if(I)
- general.fields["age"] = I.age
- general.fields["rank"] = I.assignment
- general.fields["real_rank"] = I.assignment
- general.fields["name"] = I.registered_name
- general.fields["sex"] = I.sex
+ general.set_age(I.age)
+ general.set_job(I.assignment)
+ general.set_name(I.registered_name)
+ general.set_sex(I.sex)
else
var/mob/living/carbon/human/H
if(ishuman(user))
H = user
- general.fields["age"] = H.age
+ general.set_age(H.age)
else
- general.fields["age"] = initial(H.age)
+ general.set_age(initial(H.age))
var/assignment = GetAssignment(user)
- general.fields["rank"] = assignment
- general.fields["real_rank"] = assignment
- general.fields["name"] = user.real_name
- general.fields["sex"] = capitalize(user.gender)
+ general.set_job(assignment)
+ general.set_department(args["department"])
+ general.set_name(user.real_name)
+ general.set_sex(capitalize(user.gender))
- general.fields["species"] = user.get_species()
- var/datum/data/record/medical = data_core.CreateMedicalRecord(general.fields["name"], general.fields["id"])
- data_core.CreateSecurityRecord(general.fields["name"], general.fields["id"])
+ general.set_species(user.get_species())
- if(!random_general_record)
- general.fields["fingerprint"] = random_general_record.fields["fingerprint"]
- if(random_medical_record)
- medical.fields["b_type"] = random_medical_record.fields["b_type"]
- medical.fields["b_dna"] = random_medical_record.fields["b_type"]
+ if(random_record)
+ general.set_fingerprint(random_record.get_fingerprint())
+ general.set_bloodtype(random_record.get_bloodtype())
+ general.set_dna(random_record.get_bloodtype())
if(I)
- general.fields["fingerprint"] = I.fingerprint_hash
- medical.fields["b_type"] = I.blood_type
- medical.fields["b_dna"] = I.dna_hash
+ general.set_fingerprint(I.fingerprint_hash)
+ general.set_bloodtype(I.blood_type)
+ general.set_dna(I.dna_hash)
- AnnounceArrival(general.fields["name"], general.fields["rank"], "has completed cryogenic revival")
+ AnnounceArrival(general.get_name(), general.get_job(), "has completed cryogenic revival")
return 1
/datum/uplink_item/abstract/announcements/fake_ion_storm
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 3be75945e33..f4fa7fd3537 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -119,4 +119,7 @@ var/datum/announcement/priority/command/command_announcement = new(do_log = 0, d
if(issilicon(character))
GLOB.announcer.autosay("A new [rank] [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE)
else
- GLOB.announcer.autosay("[character.real_name], [rank], [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE)
+ if(istype(character))
+ GLOB.announcer.autosay("[character.real_name], [rank], [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE)
+ else if(istext(character))
+ GLOB.announcer.autosay("[character], [rank], [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE) // send the text
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index aaeac96e804..deb597d4d4b 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -78,7 +78,7 @@ var/list/science_positions = list(JOBS_SCIENCE)
var/list/moebius_positions = list(JOBS_MOEBIUS)
//BS12 EDIT
-var/list/cargo_positions = list(JOBS_CARGO)
+var/list/guild_positions = list(JOBS_GUILD)
var/list/church_positions = list(JOBS_CHURCH)
@@ -90,7 +90,7 @@ var/list/civilian_positions = list(JOBS_CIVILIAN)
var/list/security_positions = list(JOBS_SECURITY)
var/list/armory_positions = list(JOBS_ARMORY)
-var/list/nonhuman_positions = list(JOBS_NONHUMAN)
+var/list/silicon_positions = list(JOBS_SILICON)
/proc/guest_jobbans(var/job)
- return ((job in command_positions) || (job in nonhuman_positions) || (job in armory_positions))
+ return ((job in command_positions) || (job in silicon_positions) || (job in armory_positions))
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
deleted file mode 100644
index c59fa2806ce..00000000000
--- a/code/game/machinery/computer/medical.dm
+++ /dev/null
@@ -1,519 +0,0 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
-/obj/machinery/computer/med_data//TODO:SANITY
- name = "medical records console"
- desc = "Used to view, edit and maintain medical records."
- icon_keyboard = "med_key"
- icon_screen = "medcomp"
- light_color = COLOR_LIGHTING_GREEN_MACHINERY
- req_one_access = list(access_moebius, access_forensics_lockers)
- circuit = /obj/item/electronics/circuitboard/med_data
- var/obj/item/card/id/scan
- var/authenticated
- var/rank
- var/screen
- var/datum/data/record/active1
- var/datum/data/record/active2
- var/a_id
- var/temp
- var/printing
-
-/obj/machinery/computer/med_data/verb/eject_id()
- set category = "Object"
- set name = "Eject ID Card"
- set src in oview(1)
-
- if(!usr || usr.stat || usr.lying) return
-
- if(scan)
- to_chat(usr, "You remove \the [scan] from \the [src].")
- scan.loc = get_turf(src)
- if(!usr.get_active_held_item() && ishuman(usr))
- usr.put_in_hands(scan)
- scan = null
- else
- to_chat(usr, "There is nothing to remove from the console.")
- return
-
-/obj/machinery/computer/med_data/attackby(obj/item/O, mob/user)
- if(istype(O, /obj/item/card/id) && !scan && user.unEquip(O))
- O.loc = src
- scan = O
- to_chat(user, "You insert \the [O].")
- else
- ..()
-
-/obj/machinery/computer/med_data/attack_hand(mob/user as mob)
- if(..())
- return
- nano_ui_interact(user)
-
-/obj/machinery/computer/med_data/nano_ui_interact(mob/user)
- var/dat
- if (src.temp)
- dat = text("[src.temp] Clear Screen ")
- else
- dat = text("Confirm Identity: [] ", src, (src.scan ? text("[]", src.scan.name) : "----------"))
- if (src.authenticated)
- switch(src.screen)
- if(1)
- dat += {"
-Search Records
-List Records
-Medbot Tracking
-
-Record Maintenance
-{Log Out}
-"}
- if(2)
- dat += "Record List : "
- if(!isnull(data_core.general))
- for(var/datum/data/record/R in sortRecord(data_core.general))
- dat += text("[]: [] ", src, R, R.fields["id"], R.fields["name"])
- //Foreach goto(132)
- dat += text(" Back ", src)
- if(3)
- dat += text("Records Maintenance \nBackup To Disk \nUpload From disk \nDelete All Records \n \nBack ", src, src, src, src)
- if(4)
- var/icon/front = active1.fields["photo_front"]
- var/icon/side = active1.fields["photo_side"]
- user << browse_rsc(front, "front.png")
- user << browse_rsc(side, "side.png")
- dat += "Medical Record "
- if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
- dat += ""
- else
- dat += "General Record Lost! "
- if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
- dat += text(" \nMedical Data \nBlood Type: [] \nDNA: [] \n \nMinor Disabilities: [] \nDetails: [] \n \nMajor Disabilities: [] \nDetails: [] \n \nAllergies: [] \nDetails: [] \n \nCurrent Diseases: [] (per disease info placed in log/comment section) \nDetails: [] \n \nImportant Notes: \n\t[] \n \nComments/Log ", src, src.active2.fields["b_type"], src, src.active2.fields["b_dna"], src, src.active2.fields["mi_dis"], src, src.active2.fields["mi_dis_d"], src, src.active2.fields["ma_dis"], src, src.active2.fields["ma_dis_d"], src, src.active2.fields["alg"], src, src.active2.fields["alg_d"], src, src.active2.fields["cdi"], src, src.active2.fields["cdi_d"], src, decode(src.active2.fields["notes"]))
- var/counter = 1
- while(src.active2.fields[text("com_[]", counter)])
- dat += text("[]Delete Entry ", src.active2.fields[text("com_[]", counter)], src, counter)
- counter++
- dat += text("Add Entry ", src)
- dat += text("Delete Record (Medical Only) ", src)
- else
- dat += "Medical Record Lost! "
- dat += text("New Record ")
- dat += text("\nPrint Record \nBack ", src, src)
- if(6)
- dat += "Medical Robot Monitor "
- dat += "Back "
- dat += "Medical Robots: "
- var/bdat
- for(var/mob/living/bot/medbot/M in world)
-
- if(M.z != src.z) continue //only find medibots on the same z-level as the computer
- var/turf/bl = get_turf(M)
- if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up
- bdat += "[M.name] - \[[bl.x],[bl.y]\] - [M.on ? "Online" : "Offline"] "
- if((!isnull(M.reagent_glass)) && M.use_beaker)
- bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\] "
- else
- bdat += "Using Internal Synthesizer. "
- if(!bdat)
- dat += "None detected "
- else
- dat += " [bdat]"
-
- else
- else
- dat += text("{Log In} ", src)
- user << browse(HTML_SKELETON_TITLE("Medical Records", "[dat] "), "window=med_rec")
- onclose(user, "med_rec")
- return
-
-/obj/machinery/computer/med_data/Topic(href, href_list)
- if(..())
- return 1
-
- if (!( data_core.general.Find(src.active1) ))
- src.active1 = null
-
- if (!( data_core.medical.Find(src.active2) ))
- src.active2 = null
-
- if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (issilicon(usr)))
- usr.set_machine(src)
-
- if (href_list["temp"])
- src.temp = null
-
- if (href_list["scan"])
- if (src.scan)
-
- if(ishuman(usr))
- scan.loc = usr.loc
-
- if(!usr.get_active_held_item())
- usr.put_in_hands(scan)
-
- scan = null
-
- else
- src.scan.loc = src.loc
- src.scan = null
-
- else
- var/obj/item/I = usr.get_active_held_item()
- if (istype(I, /obj/item/card/id))
- usr.drop_item()
- I.loc = src
- src.scan = I
-
- else if (href_list["logout"])
- src.authenticated = null
- src.screen = null
- src.active1 = null
- src.active2 = null
-
- else if (href_list["login"])
-
- if (isAI(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- src.rank = "AI"
- src.screen = 1
-
- else if (isrobot(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- var/mob/living/silicon/robot/R = usr
- src.rank = "[R.modtype] [R.braintype]"
- src.screen = 1
-
- else if (istype(src.scan, /obj/item/card/id))
- src.active1 = null
- src.active2 = null
-
- if (src.check_access(src.scan))
- src.authenticated = src.scan.registered_name
- src.rank = src.scan.assignment
- src.screen = 1
-
- if (src.authenticated)
-
- if(href_list["screen"])
- src.screen = text2num(href_list["screen"])
- if(src.screen < 1)
- src.screen = 1
-
- src.active1 = null
- src.active2 = null
-
- if (href_list["del_all"])
- src.temp = text("Are you sure you wish to delete all records? \n\tYes \n\tNo ", src, src)
-
- if (href_list["del_all2"])
- for(var/datum/data/record/R in data_core.medical)
- //R = null
- qdel(R)
- //Foreach goto(494)
- src.temp = "All records deleted."
-
- if (href_list["field"])
- var/a1 = src.active1
- var/a2 = src.active2
- switch(href_list["field"])
- if("fingerprint")
- if (istype(src.active1, /datum/data/record))
- var/t1 = sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active1 != a1))
- return
- src.active1.fields["fingerprint"] = t1
- if("sex")
- if (istype(src.active1, /datum/data/record))
- if (src.active1.fields["sex"] == "Male")
- src.active1.fields["sex"] = "Female"
- else
- src.active1.fields["sex"] = "Male"
- if("age")
- if (istype(src.active1, /datum/data/record))
- var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as num
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active1 != a1))
- return
- src.active1.fields["age"] = t1
- if("mi_dis")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["mi_dis"] = t1
- if("mi_dis_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["mi_dis_d"] = t1
- if("ma_dis")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["ma_dis"] = t1
- if("ma_dis_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["ma_dis_d"] = t1
- if("alg")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["alg"] = t1
- if("alg_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["alg_d"] = t1
- if("cdi")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["cdi"] = t1
- if("cdi_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["cdi_d"] = t1
- if("notes")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize notes:", "Med. records", html_decode(src.active2.fields["notes"]), null) as message, extra = 0)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["notes"] = t1
- if("p_stat")
- if (istype(src.active1, /datum/data/record))
- src.temp = text("Physical Condition: \n\t*Deceased* \n\t*SSD* \n\tActive \n\tPhysically Unfit \n\tDisabled ", src, src, src, src, src)
- if("m_stat")
- if (istype(src.active1, /datum/data/record))
- src.temp = text("Mental Condition: \n\t*Insane* \n\t*Unstable* \n\t*Watch* \n\tStable ", src, src, src, src)
- if("b_type")
- if (istype(src.active2, /datum/data/record))
- src.temp = text("Blood Type: \n\tA- A+ \n\tB- B+ \n\tAB- AB+ \n\tO- O+ ", src, src, src, src, src, src, src, src)
- if("b_dna")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please input DNA hash:", "Med. records", src.active2.fields["b_dna"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["b_dna"] = t1
- else
-
- if (href_list["p_stat"])
- if (src.active1)
- switch(href_list["p_stat"])
- if("deceased")
- src.active1.fields["p_stat"] = "*Deceased*"
- if("ssd")
- src.active1.fields["p_stat"] = "*SSD*"
- if("active")
- src.active1.fields["p_stat"] = "Active"
- if("unfit")
- src.active1.fields["p_stat"] = "Physically Unfit"
- if("disabled")
- src.active1.fields["p_stat"] = "Disabled"
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
-
- if (href_list["m_stat"])
- if (src.active1)
- switch(href_list["m_stat"])
- if("insane")
- src.active1.fields["m_stat"] = "*Insane*"
- if("unstable")
- src.active1.fields["m_stat"] = "*Unstable*"
- if("watch")
- src.active1.fields["m_stat"] = "*Watch*"
- if("stable")
- src.active1.fields["m_stat"] = "Stable"
-
-
- if (href_list["b_type"])
- if (src.active2)
- switch(href_list["b_type"])
- if("an")
- src.active2.fields["b_type"] = "A-"
- if("bn")
- src.active2.fields["b_type"] = "B-"
- if("abn")
- src.active2.fields["b_type"] = "AB-"
- if("on")
- src.active2.fields["b_type"] = "O-"
- if("ap")
- src.active2.fields["b_type"] = "A+"
- if("bp")
- src.active2.fields["b_type"] = "B+"
- if("abp")
- src.active2.fields["b_type"] = "AB+"
- if("op")
- src.active2.fields["b_type"] = "O+"
-
-
- if (href_list["del_r"])
- if (src.active2)
- src.temp = text("Are you sure you wish to delete the record (Medical Portion Only)? \n\tYes \n\tNo ", src, src)
-
- if (href_list["del_r2"])
- if (src.active2)
- //src.active2 = null
- qdel(src.active2)
-
- if (href_list["d_rec"])
- var/datum/data/record/R = locate(href_list["d_rec"])
- var/datum/data/record/M = locate(href_list["d_rec"])
- if (!( data_core.general.Find(R) ))
- src.temp = "Record Not Found!"
- return
- for(var/datum/data/record/E in data_core.medical)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- M = E
- else
- //Foreach continue //goto(2540)
- src.active1 = R
- src.active2 = M
- src.screen = 4
-
- if (href_list["new"])
- if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) )))
- var/datum/data/record/R = new /datum/data/record( )
- R.fields["name"] = src.active1.fields["name"]
- R.fields["id"] = src.active1.fields["id"]
- R.name = text("Medical Record #[]", R.fields["id"])
- R.fields["b_type"] = "Unknown"
- R.fields["b_dna"] = "Unknown"
- R.fields["mi_dis"] = "None"
- R.fields["mi_dis_d"] = "No minor disabilities have been declared."
- R.fields["ma_dis"] = "None"
- R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
- R.fields["alg"] = "None"
- R.fields["alg_d"] = "No allergies have been detected in this patient."
- R.fields["cdi"] = "None"
- R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
- R.fields["notes"] = "No notes."
- data_core.medical += R
- src.active2 = R
- src.screen = 4
-
- if (href_list["add_c"])
- if (!( istype(src.active2, /datum/data/record) ))
- return
- var/a2 = src.active2
- var/t1 = sanitize(input("Add Comment:", "Med. records", null, null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- var/counter = 1
- while(src.active2.fields[text("com_[]", counter)])
- counter++
- src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [stationtime2text()], [CURRENT_SHIP_YEAR] [t1]")
-
- if (href_list["del_c"])
- if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
- src.active2.fields[text("com_[]", href_list["del_c"])] = "Deleted "
-
- if (href_list["search"])
- var/t1 = input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text
- if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!in_range(src, usr)) && (!issilicon(usr)))))
- return
- src.active1 = null
- src.active2 = null
- t1 = lowertext(t1)
- for(var/datum/data/record/R in data_core.medical)
- if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"])))
- src.active2 = R
- else
- //Foreach continue //goto(3229)
- if (!( src.active2 ))
- src.temp = text("Could not locate record [].", t1)
- else
- for(var/datum/data/record/E in data_core.general)
- if ((E.fields["name"] == src.active2.fields["name"] || E.fields["id"] == src.active2.fields["id"]))
- src.active1 = E
- else
- //Foreach continue //goto(3334)
- src.screen = 4
-
- if (href_list["print_p"])
- if (!( src.printing ))
- src.printing = 1
- var/datum/data/record/record1
- var/datum/data/record/record2
- if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
- record1 = active1
- if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
- record2 = active2
- sleep(50)
- var/obj/item/paper/P = new /obj/item/paper( src.loc )
- P.info = "Medical Record "
- if (record1)
- P.info += text("Name: [] ID: [] \nSex: [] \nAge: [] \nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"])
- P.name = text("Medical Record ([])", record1.fields["name"])
- else
- P.info += "General Record Lost! "
- P.name = "Medical Record"
- if (record2)
- P.info += text(" \nMedical Data \nBlood Type: [] \nDNA: [] \n \nMinor Disabilities: [] \nDetails: [] \n \nMajor Disabilities: [] \nDetails: [] \n \nAllergies: [] \nDetails: [] \n \nCurrent Diseases: [] (per disease info placed in log/comment section) \nDetails: [] \n \nImportant Notes: \n\t[] \n \nComments/Log ", record2.fields["b_type"], record2.fields["b_dna"], record2.fields["mi_dis"], record2.fields["mi_dis_d"], record2.fields["ma_dis"], record2.fields["ma_dis_d"], record2.fields["alg"], record2.fields["alg_d"], record2.fields["cdi"], record2.fields["cdi_d"], decode(record2.fields["notes"]))
- var/counter = 1
- while(record2.fields[text("com_[]", counter)])
- P.info += text("[] ", record2.fields[text("com_[]", counter)])
- counter++
- else
- P.info += "Medical Record Lost! "
- P.info += ""
- src.printing = null
-
- src.add_fingerprint(usr)
- src.updateUsrDialog()
- return
-
-/obj/machinery/computer/med_data/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
-
- for(var/datum/data/record/R in data_core.medical)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
- if(2)
- R.fields["sex"] = pick("Male", "Female")
- if(3)
- R.fields["age"] = rand(5, 85)
- if(4)
- R.fields["b_type"] = pick("A-", "B-", "AB-", "O-", "A+", "B+", "AB+", "O+")
- if(5)
- R.fields["p_stat"] = pick("*SSD*", "Active", "Physically Unfit", "Disabled")
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
- ..(severity)
-
-
-/obj/machinery/computer/med_data/laptop
- name = "Medical Laptop"
- desc = "A cheap laptop."
- icon_state = "laptop"
- icon_keyboard = "laptop_key"
- icon_screen = "medlaptop"
- CheckFaceFlag = 0
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
deleted file mode 100644
index 36e2ee0983c..00000000000
--- a/code/game/machinery/computer/security.dm
+++ /dev/null
@@ -1,658 +0,0 @@
-/obj/machinery/computer/secure_data
- name = "security records console"
- desc = "Used to view, edit and maintain security records"
- icon_keyboard = "security_key"
- icon_screen = "security"
- light_color = COLOR_LIGHTING_SCI_BRIGHT
- req_one_access = list(access_security)
- circuit = /obj/item/electronics/circuitboard/secure_data
- var/obj/item/card/id/scan
- var/authenticated
- var/rank
- var/screen
- var/datum/data/record/active1
- var/datum/data/record/active2
- var/a_id
- var/temp
- var/printing
- var/can_change_id = 0
- var/list/Perp
- var/tempname
- //Sorting Variables
- var/sortBy = "name"
- var/order = 1 // -1 = Descending - 1 = Ascending
-
-/obj/machinery/computer/secure_data/verb/eject_id()
- set category = "Object"
- set name = "Eject ID Card"
- set src in oview(1)
-
- if(!usr || usr.stat || usr.lying) return
-
- if(scan)
- to_chat(usr, "You remove \the [scan] from \the [src].")
- scan.loc = get_turf(src)
- if(!usr.get_active_held_item() && ishuman(usr))
- usr.put_in_hands(scan)
- scan = null
- else
- to_chat(usr, "There is nothing to remove from the console.")
- return
-
-/obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob)
- if(istype(O, /obj/item/card/id) && !scan)
- usr.drop_item()
- O.loc = src
- scan = O
- to_chat(user, "You insert [O].")
- ..()
-
-//Someone needs to break down the dat += into chunks instead of long ass lines.
-/obj/machinery/computer/secure_data/attack_hand(mob/user)
- if(..())
- return
- nano_ui_interact(user)
-
-/obj/machinery/computer/secure_data/nano_ui_interact(user)
- if (src.z > 6)
- to_chat(user, "[span_warning("Unable to establish a connection:")] You're too far away from the station!")
- return
-
- var/dat
- if (temp)
- dat = text("[] Clear Screen ", temp, src)
- else
- dat = text("Confirm Identity: [] ", src, (scan ? text("[]", scan.name) : "----------"))
- if (authenticated)
- switch(screen)
- if(1)
- dat += {""}
- dat += text("Search Records ", src)
- dat += text("New Record ", src)
- dat += {"
-
-
-
-
-Name
-ID
-Rank
-Fingerprints
-Criminal Status
- "}
- if(!isnull(data_core.general))
- for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order))
- var/crimstat = ""
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
- crimstat = E.fields["criminal"]
- var/background
- switch(crimstat)
- if("*Arrest*")
- background = "'background-color:#DC143C;'"
- if("Incarcerated")
- background = "'background-color:#CD853F;'"
- if("Parolled")
- background = "'background-color:#CD853F;'"
- if("Released")
- background = "'background-color:#3BB9FF;'"
- if("None")
- background = "'background-color:#00FF7F;'"
- if("")
- background = "'background-color:#FFFFFF;'"
- crimstat = "No Record."
- dat += text("[] ", background, src, R, R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("[] ", R.fields["rank"])
- dat += text("[] ", R.fields["fingerprint"])
- dat += text("[] ", crimstat)
- dat += "
"
- dat += text("Record Maintenance ", src)
- dat += text("{Log Out} ",src)
- if(2)
- dat += "Records Maintenance "
- dat += "Delete All Records Back "
- if(3)
- dat += "Security Record "
- if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
- user << browse_rsc(active1.fields["photo_front"], "front.png")
- user << browse_rsc(active1.fields["photo_side"], "side.png")
- dat += {"
-
- "}
- else
- dat += "General Record Lost! "
- if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
- dat += " \nSecurity Data \nCriminal Status: \
- [active2.fields["criminal"]] \n \n \
- Minor Crimes: [active2.fields["mi_crim"]] \n \
- Details: [active2.fields["mi_crim_d"]] \n \n\
- Major Crimes: [active2.fields["ma_crim"]] \n \
- Details: [active2.fields["ma_crim_d"]] \n \n \
- Important Notes: \n\t[decode(active2.fields["notes"])] \n \n\
- Comments/Log "
- var/counter = 1
- while(active2.fields["com_[counter]"])
- dat += text("[]Delete Entry ", active2.fields["com_[counter]"], src, counter)
- counter++
- dat += "Add Entry "
- dat += "Delete Record (Security Only) "
- else
- dat += "Security Record Lost! "
- dat += "New Security Record "
- dat += "Delete Record (ALL) \
- Print Record \
- Print Wanted Poster \
- Back "
- if(4)
- if(!Perp.len)
- dat += text("ERROR. String could not be located.Back ", src)
- else
- dat += {"
-
- Search Results for '[tempname]':
-
-
- Name
- ID
- Rank
- Fingerprints
- Criminal Status
-
- "}
- for(var/i=1, i<=Perp.len, i += 2)
- var/crimstat = ""
- var/datum/data/record/R = Perp[i]
- if(istype(Perp[i+1],/datum/data/record/))
- var/datum/data/record/E = Perp[i+1]
- crimstat = E.fields["criminal"]
- var/background
- switch(crimstat)
- if("*Arrest*")
- background = "'background-color:#DC143C;'"
- if("Incarcerated")
- background = "'background-color:#CD853F;'"
- if("Parolled")
- background = "'background-color:#CD853F;'"
- if("Released")
- background = "'background-color:#3BB9FF;'"
- if("None")
- background = "'background-color:#00FF7F;'"
- if("")
- background = "'background-color:#FFFFFF;'"
- crimstat = "No Record."
- dat += text("[] ", background, src, R, R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("[] ", R.fields["rank"])
- dat += text("[] ", R.fields["fingerprint"])
- dat += text("[] ", crimstat)
- dat += "
"
- dat += text("Return to index. ", src)
- else
- else
- dat += text("{Log In} ", src)
- user << browse(HTML_SKELETON_TITLE("Security Records", "[dat] "), "window=secure_rec;size=600x400")
- onclose(user, "secure_rec")
- return
-
-/*Revised /N
-I can't be bothered to look more of the actual code outside of switch but that probably needs revising too.
-What a mess.*/
-/obj/machinery/computer/secure_data/Topic(href, href_list)
- if(..())
- return 1
- if (!( data_core.general.Find(active1) ))
- active1 = null
- if (!( data_core.security.Find(active2) ))
- active2 = null
- if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (issilicon(usr)))
- usr.set_machine(src)
- switch(href_list["choice"])
-// SORTING!
- if("Sorting")
- // Reverse the order if clicked twice
- if(sortBy == href_list["sort"])
- if(order == 1)
- order = -1
- else
- order = 1
- else
- // New sorting order!
- sortBy = href_list["sort"]
- order = initial(order)
-//BASIC FUNCTIONS
- if("Clear Screen")
- temp = null
-
- if ("Return")
- screen = 1
- active1 = null
- active2 = null
-
- if("Confirm Identity")
- if (scan)
- if(ishuman(usr) && !usr.get_active_held_item())
- usr.put_in_hands(scan)
- else
- scan.loc = get_turf(src)
- scan = null
- else
- var/obj/item/I = usr.get_active_held_item()
- if (istype(I, /obj/item/card/id) && usr.unEquip(I))
- I.loc = src
- scan = I
-
- if("Log Out")
- authenticated = null
- screen = null
- active1 = null
- active2 = null
-
- if("Log In")
- if (isAI(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- src.rank = "AI"
- src.screen = 1
- else if (isrobot(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- var/mob/living/silicon/robot/R = usr
- src.rank = "[R.modtype] [R.braintype]"
- src.screen = 1
- else if (istype(scan, /obj/item/card/id))
- active1 = null
- active2 = null
- if(check_access(scan))
- authenticated = scan.registered_name
- rank = scan.assignment
- screen = 1
-//RECORD FUNCTIONS
- if("Search Records")
- var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text
- if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr)))
- return
- Perp = new/list()
- t1 = lowertext(t1)
- var/list/components = splittext(t1, " ")
- if(components.len > 5)
- return //Lets not let them search too greedily.
- for(var/datum/data/record/R in data_core.general)
- var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"]
- for(var/i = 1, i<=components.len, i++)
- if(findtext(temptext,components[i]))
- var/prelist = new/list(2)
- prelist[1] = R
- Perp += prelist
- for(var/i = 1, i<=Perp.len, i+=2)
- for(var/datum/data/record/E in data_core.security)
- var/datum/data/record/R = Perp[i]
- if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
- Perp[i+1] = E
- tempname = t1
- screen = 4
-
- if("Record Maintenance")
- screen = 2
- active1 = null
- active2 = null
-
- if ("Browse Record")
- var/datum/data/record/R = locate(href_list["d_rec"])
- var/S = locate(href_list["d_rec"])
- if (!( data_core.general.Find(R) ))
- temp = "Record Not Found!"
- else
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- S = E
- active1 = R
- active2 = S
- screen = 3
-
-/* if ("Search Fingerprints")
- var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text
- if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!issilicon(usr))))
- return
- active1 = null
- active2 = null
- t1 = lowertext(t1)
- for(var/datum/data/record/R in data_core.general)
- if (lowertext(R.fields["fingerprint"]) == t1)
- active1 = R
- if (!( active1 ))
- temp = text("Could not locate record [].", t1)
- else
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"]))
- active2 = E
- screen = 3 */
-
- if ("Print Record")
- if (!( printing ))
- printing = 1
- var/datum/data/record/record1 = null
- var/datum/data/record/record2 = null
- if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
- record1 = active1
- if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
- record2 = active2
- sleep(50)
- var/obj/item/paper/P = new /obj/item/paper( loc )
- P.info = "Security Record "
- if (record1)
- P.info += {"
- Name: [record1.fields["name"]] ID: [record1.fields["id"]]
- Sex: [record1.fields["sex"]]
- Age: [record1.fields["age"]]
- Fingerprint: [record1.fields["fingerprint"]]
- Physical Status: [record1.fields["p_stat"]]
- Mental Status: [record1.fields["m_stat"]]
- "}
- P.name = "Security Record ([record1.fields["name"]])"
- else
- P.info += "General Record Lost! "
- P.name = "Security Record"
- if (record2)
- P.info += {"
- Security Data
- Criminal Status: [record2.fields["criminal"]]
- Minor Crimes: [record2.fields["mi_crim"]]
- Details: [record2.fields["mi_crim_d"]]
- Major Crimes: [record2.fields["ma_crim"]]
- Details: [record2.fields["ma_crim_d"]]
- Important Notes:
- \t[decode(record2.fields["notes"])]
- Comments/Log
- "}
- var/counter = 1
- while(record2.fields[text("com_[]", counter)])
- P.info += text("[] ", record2.fields[text("com_[]", counter)])
- counter++
- else
- P.info += "Security Record Lost! "
- P.info += ""
- printing = null
- updateUsrDialog()
-
- if ("Print Poster")
- if(!printing)
- var/wanted_name = sanitizeName(input("Please enter an alias for the criminal:", "Print Wanted Poster", active1.fields["name"]) as text, MAX_NAME_LEN, 1)
- if(wanted_name)
- var/default_description = "A poster declaring [wanted_name] to be a dangerous individual, wanted by Nanotrasen. Report any sightings to security immediately."
- var/major_crimes = active2.fields["ma_crim"]
- var/minor_crimes = active2.fields["mi_crim"]
- default_description += "\n[wanted_name] is wanted for the following crimes:\n"
- default_description += "\nMinor Crimes:\n[minor_crimes]\n[active2.fields["mi_crim_d"]]\n"
- default_description += "\nMajor Crimes:\n[major_crimes]\n[active2.fields["ma_crim_d"]]\n"
- printing = 1
- spawn(30)
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1)
- if((istype(active1, /datum/data/record) && data_core.general.Find(active1)))//make sure the record still exists.
- new /obj/item/contraband/poster/wanted(src.loc, active1.fields["photo_front"], wanted_name, default_description)
- printing = 0
-//RECORD DELETE
- if ("Delete All Records")
- temp = ""
- temp += "Are you sure you wish to delete all Security records? "
- temp += "Yes "
- temp += "No "
-
- if ("Purge All Records")
- for(var/datum/data/record/R in data_core.security)
- qdel(R)
- temp = "All Security records deleted."
-
- if ("Add Entry")
- if (!( istype(active2, /datum/data/record) ))
- return
- var/a2 = active2
- var/t1 = sanitize(input("Add Comment:", "Secure. records", null, null) as message)
- if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || active2 != a2))
- return
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- counter++
- active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD", NO_TIMEZONE)] [stationtime2text()], [CURRENT_SHIP_YEAR] [t1]")
-
- if ("Delete Record (ALL)")
- if (active1)
- temp = "Are you sure you wish to delete the record (ALL)? "
- temp += "Yes "
- temp += "No "
-
- if ("Delete Record (Security)")
- if (active2)
- temp = "Are you sure you wish to delete the record (Security Portion Only)? "
- temp += "Yes "
- temp += "No "
-
- if ("Delete Entry")
- if ((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
- active2.fields[text("com_[]", href_list["del_c"])] = "Deleted "
-//RECORD CREATE
- if ("New Record (Security)")
- if ((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) )))
- active2 = data_core.CreateSecurityRecord(active1.fields["name"], active1.fields["id"])
- screen = 3
-
- if ("New Record (General)")
- active1 = data_core.CreateGeneralRecord()
- active2 = null
-
-//FIELD FUNCTIONS
- if ("Edit")
- if (is_not_allowed(usr))
- return
- var/a1 = active1
- var/a2 = active2
- switch(href_list["field"])
- if("name")
- if (istype(active1, /datum/data/record))
- var/t1 = sanitizeName(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
- if (!t1 || active1 != a1)
- return
- active1.fields["name"] = t1
- if("id")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text)
- if (!t1 || active1 != a1)
- return
- active1.fields["id"] = t1
- if("fingerprint")
- if (istype(active1, /datum/data/record))
- var/t1 = sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text)
- if (!t1 || active1 != a1)
- return
- active1.fields["fingerprint"] = t1
- if("sex")
- if (istype(active1, /datum/data/record))
- if (active1.fields["sex"] == "Male")
- active1.fields["sex"] = "Female"
- else
- active1.fields["sex"] = "Male"
- if("age")
- if (istype(active1, /datum/data/record))
- var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num
- if (!t1 || active1 != a1)
- return
- active1.fields["age"] = t1
- if("mi_crim")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text)
- if (!t1 || active2 != a2)
- return
- active2.fields["mi_crim"] = t1
- if("mi_crim_d")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message)
- if (!t1 || active2 != a2)
- return
- active2.fields["mi_crim_d"] = t1
- if("ma_crim")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text)
- if (!t1 || active2 != a2)
- return
- active2.fields["ma_crim"] = t1
- if("ma_crim_d")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message)
- if (!t1 || active2 != a2)
- return
- active2.fields["ma_crim_d"] = t1
- if("notes")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message, extra = 0)
- if (!t1 || active2 != a2)
- return
- active2.fields["notes"] = t1
- if("criminal")
- if (istype(active2, /datum/data/record))
- temp = "Criminal Status: "
- temp += ""
- if("rank")
- var/list/L = list( "First Officer", "Captain", "AI" )
- //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N
- if ((istype(active1, /datum/data/record) && L.Find(rank)))
- temp = "Rank: "
- temp += ""
- for(var/rank in GLOB.joblist)
- temp += "[rank] "
- temp += " "
- else
- alert(usr, "You do not have the required rank to do this!")
- if("species")
- if (istype(active1, /datum/data/record))
- var/t1 = sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message)
- if (!t1 || active1 != a1)
- return
- active1.fields["species"] = t1
- if("photo front")
- var/icon/photo = get_photo(usr)
- if(photo)
- active1.fields["photo_front"] = photo
- if("photo side")
- var/icon/photo = get_photo(usr)
- if(photo)
- active1.fields["photo_side"] = photo
-
-
-//TEMPORARY MENU FUNCTIONS
- else//To properly clear as per clear screen.
- temp=null
- switch(href_list["choice"])
- if ("Change Rank")
- if (active1)
- active1.fields["rank"] = href_list["rank"]
- if(href_list["rank"] in GLOB.joblist)
- active1.fields["real_rank"] = href_list["real_rank"]
-
- if ("Change Criminal Status")
- if (active2)
- for(var/mob/living/carbon/human/H in GLOB.player_list)
- BITSET(H.hud_updateflag, WANTED_HUD)
- switch(href_list["criminal2"])
- if("none")
- active2.fields["criminal"] = "None"
- if("arrest")
- active2.fields["criminal"] = "*Arrest*"
- if("incarcerated")
- active2.fields["criminal"] = "Incarcerated"
- if("parolled")
- active2.fields["criminal"] = "Parolled"
- if("released")
- active2.fields["criminal"] = "Released"
-
- if ("Delete Record (Security) Execute")
- if (active2)
- qdel(active2)
-
- if ("Delete Record (ALL) Execute")
- if (active1)
- for(var/datum/data/record/R in data_core.medical)
- if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
- qdel(R)
- else
- qdel(active1)
- if (active2)
- qdel(active2)
- else
- temp = "This function does not appear to be working at the moment. Our apologies."
-
- add_fingerprint(usr)
- updateUsrDialog()
- return
-
-/obj/machinery/computer/secure_data/proc/is_not_allowed(mob/user)
- return !src.authenticated || user.stat || user.restrained() || (!in_range(src, user) && (!issilicon(user)))
-
-/obj/machinery/computer/secure_data/proc/get_photo(mob/user)
- if(istype(user.get_active_held_item(), /obj/item/photo))
- var/obj/item/photo/photo = user.get_active_held_item()
- return photo.img
- if(issilicon(user))
- var/mob/living/silicon/tempAI = usr
- var/obj/item/photo/selection = tempAI.GetPicture()
- if (selection)
- return selection.img
-
-/obj/machinery/computer/secure_data/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
-
- for(var/datum/data/record/R in data_core.security)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
- if(2)
- R.fields["sex"] = pick("Male", "Female")
- if(3)
- R.fields["age"] = rand(5, 85)
- if(4)
- R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released")
- if(5)
- R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
- ..(severity)
-
-/obj/machinery/computer/secure_data/detective_computer
- icon = 'icons/obj/computer.dmi'
- icon_state = "messyfiles"
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 8b457cc5402..58e06db8b24 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -241,9 +241,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
if(caller_id)
var/icon/tempicon = new
- for(var/datum/data/record/t in data_core.locked)
- if(t.fields["name"]==caller_id.name)
- tempicon = t.fields["image"]
+ var/datum/computer_file/report/crew_record/t = get_crewmember_record(caller_id.name)
+ tempicon = t.photo_front
hologram.overlays += getHologramIcon(icon(tempicon)) // Add the callers image as an overlay to keep coloration!
else
hologram.overlays += A.holo_icon // Add the AI's configured holo Icon
diff --git a/code/game/objects/items/devices/uplink.dm b/code/game/objects/items/devices/uplink.dm
index 677a0888c4c..e6c3c13efd6 100644
--- a/code/game/objects/items/devices/uplink.dm
+++ b/code/game/objects/items/devices/uplink.dm
@@ -234,14 +234,14 @@ A list of items and costs is stored under the datum of every game mode, alongsid
nanoui_data["items"] = items
else if(nanoui_menu == 2)
var/permanentData[0]
- for(var/datum/data/record/L in sortRecord(data_core.locked))
- permanentData[++permanentData.len] = list(Name = L.fields["name"],"id" = L.fields["id"])
+ for(var/datum/computer_file/report/crew_record/L in GLOB.all_crew_records)
+ permanentData[++permanentData.len] = list(Name = L.get_name(), "id" = jointext(L.get_name(), L.get_job()))
nanoui_data["exploit_records"] = permanentData
else if(nanoui_menu == 21)
nanoui_data["exploit_exists"] = 0
- for(var/datum/data/record/L in data_core.locked)
- if(L.fields["id"] == exploit_id)
+ for(var/datum/computer_file/report/crew_record/L in GLOB.all_crew_records)
+ if(jointext(L.get_name(), L.get_job()) == exploit_id) // datacore used name and job to make their IDs, so this would be the same level of specificity as it was in datacore
nanoui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
// We trade off being able to automatically add shit for more control over what gets passed to json
// and if it's sanitized for html.
diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
index 60a702577cd..311da9ff96f 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
@@ -18,9 +18,6 @@
build_path = /obj/machinery/computer/borgupload
origin_tech = list(TECH_DATA = 4)
-/obj/item/electronics/circuitboard/med_data
- name = T_BOARD("medical records console")
- build_path = /obj/machinery/computer/med_data
/obj/item/electronics/circuitboard/communications
name = T_BOARD("command and communications console")
@@ -33,9 +30,6 @@
build_path = /obj/machinery/computer/teleporter
origin_tech = list(TECH_DATA = 2, TECH_BLUESPACE = 2)
-/obj/item/electronics/circuitboard/secure_data
- name = T_BOARD("security records console")
- build_path = /obj/machinery/computer/secure_data
/obj/item/electronics/circuitboard/atmos_alert
rarity_value = 13.3
diff --git a/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm b/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm
index 0d7f0d248d7..aa42e71e02f 100644
--- a/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm
+++ b/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm
@@ -7,6 +7,6 @@
return
var/dat
dat += "Crew Manifest "
- dat += data_core.get_manifest()
+ dat += html_crew_manifest(TRUE)
user << browse(HTML_SKELETON_TITLE("Crew Manifest", dat), "window=manifest;size=370x420;can_close=1")
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 2ef97125f7f..2e04b04f9c3 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -319,23 +319,8 @@ Contractors and the like can also be revived with the previous role mostly intac
var/mob/living/carbon/human/new_character = new()//The mob being spawned.
- var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character.
- if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
- /*Try and locate a record for the person being respawned through data_core.
- This isn't an exact science but it does the trick more often than not.*/
- var/id = md5("[G_found.real_name][G_found.mind.assigned_role]")
- for(var/datum/data/record/t in data_core.locked)
- if(t.fields["id"]==id)
- record_found = t//We shall now reference the record.
- break
-
- if(record_found)//If they have a record we can determine a few things.
- new_character.real_name = record_found.fields["name"]
- new_character.gender = record_found.fields["sex"]
- new_character.age = record_found.fields["age"]
- new_character.b_type = record_found.fields["b_type"]
- new_character.dna_trace = record_found.fields["b_dna"]
- new_character.fingers_trace = record_found.fields["fingerprint"]
+ if(G_found.client?.prefs)//If they have a record we can determine a few things.
+ G_found.client?.prefs.copy_to(new_character)
else
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
@@ -376,12 +361,13 @@ Contractors and the like can also be revived with the previous role mostly intac
//Now for special roles and equipment.
SSjob.EquipRank(new_character, new_character.mind.assigned_role)
+ var/datum/computer_file/report/crew_record/record_found = get_crewmember_record(new_character.name)
//Announces the character on all the systems, based on the record.
if(!issilicon(new_character))//If they are not a cyborg/AI.
if(!record_found && !player_is_antag(new_character.mind, only_offstation_roles = 1)) //If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
//Power to the user!
- if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
- data_core.manifest_inject(new_character)
+ if(alert(new_character,"Warning: No record entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
+ CreateModularRecord(new_character)
if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes")
call(/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role)
diff --git a/code/modules/asset_cache/assets/legacyuiicons.dm b/code/modules/asset_cache/assets/legacyuiicons.dm
new file mode 100644
index 00000000000..5051a76d70a
--- /dev/null
+++ b/code/modules/asset_cache/assets/legacyuiicons.dm
@@ -0,0 +1,5 @@
+/datum/asset/spritesheet/legacyicons
+ name = "oldicons"
+
+/datum/asset/spritesheet/legacyicons/create_spritesheets()
+ InsertAll("", 'icons/ui_icons/dmis/uiicons16.dmi')
diff --git a/code/modules/client/preference_setup/background/03_records.dm b/code/modules/client/preference_setup/background/03_records.dm
index cc694cf9528..54084ff6555 100644
--- a/code/modules/client/preference_setup/background/03_records.dm
+++ b/code/modules/client/preference_setup/background/03_records.dm
@@ -9,15 +9,9 @@
sort_order = 5
/datum/category_item/player_setup_item/background/records/load_character(savefile/S)
- from_file(S["med_record"],pref.med_record)
- from_file(S["sec_record"],pref.sec_record)
- from_file(S["gen_record"],pref.gen_record)
from_file(S["memory"],pref.memory)
-/datum/category_item/player_setup_item/background/records/save_character(savefile/S)
- to_file(S["med_record"],pref.med_record)
- to_file(S["sec_record"],pref.sec_record)
- to_file(S["gen_record"],pref.gen_record)
+/datum/category_item/player_setup_item/background/records/save_character(var/savefile/S)
to_file(S["memory"],pref.memory)
/datum/category_item/player_setup_item/background/records/content(mob/user)
@@ -26,33 +20,30 @@
if(jobban_isbanned(user, "Records"))
. += "[span_danger("You are banned from using character records.")] "
else
- . += "Medical Records: "
- . += "[TextPreview(pref.med_record,40)] "
- . += "Employment Records: "
- . += "[TextPreview(pref.gen_record,40)] "
- . += "Security Records: "
- . += "[TextPreview(pref.sec_record,40)] "
+ if(pref.med_record)
+ . += "Medical Records: "
+ . += "[TextPreview(pref.med_record,40)] "
+ if(pref.gen_record)
+ . += "Employment Records: "
+ . += "[TextPreview(pref.gen_record,40)] "
+ if(pref.sec_record)
+ . += "Security Records: "
+ . += "[TextPreview(pref.sec_record,40)] "
. += "Memory: "
. += "[TextPreview(pref.memory,40)] "
. = jointext(.,null)
/datum/category_item/player_setup_item/background/records/OnTopic(href,list/href_list, mob/user)
if(href_list["set_medical_records"])
- var/new_medical = sanitize(input(user,"Enter medical information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.med_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.med_record = new_medical
+ input(user,"Read medical information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.med_record)) as message|null
return TOPIC_REFRESH
else if(href_list["set_general_records"])
- var/new_general = sanitize(input(user,"Enter employment information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.gen_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_general) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.gen_record = new_general
+ input(user,"Read employment information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.gen_record)) as message|null
return TOPIC_REFRESH
else if(href_list["set_security_records"])
- var/sec_medical = sanitize(input(user,"Enter security information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.sec_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(sec_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.sec_record = sec_medical
+ input(user,"Read security information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.sec_record)) as message|null
return TOPIC_REFRESH
else if(href_list["set_memory"])
@@ -62,3 +53,82 @@
return TOPIC_REFRESH
. = ..()
+
+/datum/category_item/player_setup_item/background/records/proc/load_record(savefile/S, recordtype)
+ var/recordgiven = S["[recordtype]"]
+ if(S["version"] >= 19)
+ if(!recordgiven || !(recordtype in pref.vars))
+ return FALSE
+
+ if(istype(recordgiven, /datum/storedrecord))
+ pref.vars[recordtype] = recordgiven
+ else
+ if(istext(recordgiven) && (recordtype in pref.vars))
+ pref.vars[recordtype] = recordgiven
+
+
+
+/datum/storedrecord
+
+/datum/storedrecord/proc/transfertocomputer(datum/report_field/tofile)
+ // nobody here.
+/datum/storedrecord/security
+ var/list/crimes = list()
+ var/list/evidence = list()
+ var/list/locations = list()
+
+
+/datum/storedrecord/security/transfertocomputer(datum/report_field/tofile)
+ if(!istype(tofile, /datum/report_field/arraylinkage))
+ return FALSE
+ var/datum/report_field/arraylinkage/toset = tofile
+ toset.arrays = list()
+ toset.arrays["crimes"] = crimes // edit these appropriately on any changes
+ toset.arrays["evidence"] = evidence // don't forget to synch these indexes
+ toset.arrays["locations"] = locations
+
+/datum/storedrecord/security/default // used by default
+ crimes = list("No crimes on record.")
+ evidence = list("N/A.")
+ locations = list("N/A.")
+
+
+/datum/storedrecord/medical
+ var/list/prosthetics = list()
+ var/list/wounds = list()
+ var/list/bodystate = list()
+ var/list/chemhistory = list()
+ var/list/psychological = list()
+
+
+/datum/storedrecord/medical/transfertocomputer(datum/report_field/tofile)
+ if(!istype(tofile, /datum/report_field/arrayclump))
+ return FALSE
+ var/datum/report_field/arrayclump/toset = tofile
+ var/list/tochange = toset.value
+ tochange["prosthetics"] = prosthetics // change these appropriately as well
+ tochange["wounds"] = wounds // but as an arrayclump, they don't need synchronized indexing
+ tochange["Body state"] = bodystate
+ tochange["chemhistory"] = chemhistory
+ tochange["psychological"] = psychological
+
+
+/datum/storedrecord/medical/default // used by default
+ prosthetics = list("No prosthetics on record.")
+ wounds = list("No wounds on record.")
+ bodystate = list("Alive at time of writing.")
+ chemhistory = list("Chemical record is clean.")
+ psychological = list("No psychological profiling has been done at time of writing.")
+
+
+/datum/storedrecord/general
+ var/background // background is defined by fates
+ var/origin // origin is defined by origin
+
+
+
+
+/datum/storedrecord/general/default // used by default
+ background = list("Unremarkable.")
+ origin = list("Origin unknown.")
+
diff --git a/code/modules/client/preference_setup/general/05_records.dm b/code/modules/client/preference_setup/general/05_records.dm
deleted file mode 100644
index 5a246b16f99..00000000000
--- a/code/modules/client/preference_setup/general/05_records.dm
+++ /dev/null
@@ -1,64 +0,0 @@
-/datum/preferences
- var/med_record = ""
- var/sec_record = ""
- var/gen_record = ""
- var/memory = ""
-
-/datum/category_item/player_setup_item/physical/records
- name = "Records"
- sort_order = 5
-
-/datum/category_item/player_setup_item/physical/records/load_character(savefile/S)
- from_file(S["med_record"],pref.med_record)
- from_file(S["sec_record"],pref.sec_record)
- from_file(S["gen_record"],pref.gen_record)
- from_file(S["memory"],pref.memory)
-
-/datum/category_item/player_setup_item/physical/records/save_character(savefile/S)
- to_file(S["med_record"],pref.med_record)
- to_file(S["sec_record"],pref.sec_record)
- to_file(S["gen_record"],pref.gen_record)
- to_file(S["memory"],pref.memory)
-
-/datum/category_item/player_setup_item/physical/records/content(mob/user)
- . = list()
- . += "Records : "
- if(jobban_isbanned(user, "Records"))
- . += "[span_danger("You are banned from using character records.")] "
- else
- . += "Medical Records: "
- . += "[TextPreview(pref.med_record,40)] "
- . += "Employment Records: "
- . += "[TextPreview(pref.gen_record,40)] "
- . += "Security Records: "
- . += "[TextPreview(pref.sec_record,40)] "
- . += "Memory: "
- . += "[TextPreview(pref.memory,40)] "
- . = jointext(.,null)
-
-/datum/category_item/player_setup_item/physical/records/OnTopic(href,list/href_list, mob/user)
- if(href_list["set_medical_records"])
- var/new_medical = sanitize(input(user,"Enter medical information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.med_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.med_record = new_medical
- return TOPIC_REFRESH
-
- else if(href_list["set_general_records"])
- var/new_general = sanitize(input(user,"Enter employment information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.gen_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_general) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.gen_record = new_general
- return TOPIC_REFRESH
-
- else if(href_list["set_security_records"])
- var/sec_medical = sanitize(input(user,"Enter security information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.sec_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(sec_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.sec_record = sec_medical
- return TOPIC_REFRESH
-
- else if(href_list["set_memory"])
- var/memes = sanitize(input(user,"Enter memorized information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.memory)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(memes) && CanUseTopic(user))
- pref.memory = memes
- return TOPIC_REFRESH
-
- . = ..()
diff --git a/code/modules/client/preference_setup/loadout/lists/accessories.dm b/code/modules/client/preference_setup/loadout/lists/accessories.dm
index 8ef7c68fba2..939ae4b7dae 100644
--- a/code/modules/client/preference_setup/loadout/lists/accessories.dm
+++ b/code/modules/client/preference_setup/loadout/lists/accessories.dm
@@ -43,7 +43,7 @@
/datum/gear/accessory/guild
display_name = "armband, Aster's Guild"
path = /obj/item/clothing/accessory/armband/cargo
- allowed_roles = list(JOBS_CARGO)
+ allowed_roles = list(JOBS_GUILD)
/datum/gear/accessory/engineering
display_name = "armband, Technomancer League"
diff --git a/code/modules/client/preference_setup/loadout/lists/suits.dm b/code/modules/client/preference_setup/loadout/lists/suits.dm
index aae61f2a909..2915bdfa18f 100644
--- a/code/modules/client/preference_setup/loadout/lists/suits.dm
+++ b/code/modules/client/preference_setup/loadout/lists/suits.dm
@@ -137,10 +137,10 @@
/datum/gear/suit/guild/black
display_name = "black guild coat"
path = /obj/item/clothing/suit/storage/cargo_jacket/black
- allowed_roles = list(JOBS_CARGO)
+ allowed_roles = list(JOBS_GUILD)
/datum/gear/suit/guild/black/old
display_name = "old black guild coat"
path = /obj/item/clothing/suit/storage/cargo_jacket/black/old
- allowed_roles = list(JOBS_CARGO)
+ allowed_roles = list(JOBS_GUILD)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index eb54efa9128..30422fa437d 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -239,10 +239,7 @@
for(var/lang in alternate_languages)
character.add_language(lang)
-
- character.med_record = med_record
- character.sec_record = sec_record
- character.gen_record = gen_record
+
character.exploit_record = exploit_record
if(!character.isSynthetic())
character.nutrition = rand(250, 450)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index d7d82c168db..3002912be54 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -1,5 +1,5 @@
#define SAVEFILE_VERSION_MIN 8
-#define SAVEFILE_VERSION_MAX 18
+#define SAVEFILE_VERSION_MAX 19
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey) return
diff --git a/code/modules/economy/Accounts.dm b/code/modules/economy/Accounts.dm
index dbf3eeaa6a2..d0a84e987e6 100644
--- a/code/modules/economy/Accounts.dm
+++ b/code/modules/economy/Accounts.dm
@@ -37,8 +37,12 @@
return owner_name
//Attempts to return the associated data record for this account
+// expensive to run, store the result from this.
/datum/money_account/proc/get_record()
- return find_general_record("pay_account", account_number)
+ for(var/datum/computer_file/report/crew_record/CR in GLOB.all_crew_records)
+ var/accountnum = CR.get_account()
+ if(account_number == accountnum)
+ return CR
/datum/transaction
var/target_name = ""
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index f48f77d295c..6afa52373f7 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -118,9 +118,8 @@
var/mob/living/carbon/human/H = speaker
if(H.voice)
speaker_name = H.voice
- for(var/datum/data/record/G in data_core.general)
- if(G.fields["name"] == speaker_name)
- return H.rank_prefix_name(speaker_name)
+ if(get_crewmember_record(speaker_name))
+ return H.rank_prefix_name(speaker_name)
return voice_name ? voice_name : speaker_name
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 3f1a9e16042..8bc4de7c34f 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -303,9 +303,10 @@
if(perpname)
var/datum/computer_file/report/crew_record/R = get_crewmember_record(perpname)
criminal = R ? R.get_criminalStatus() : "None"
- msg += "\n"
- msg += "Criminal status: \[[criminal]\] \n"
- msg += "Security records: \[View\] \[Add comment\] \n"
+
+ msg += "Criminal status: \[[criminal]\] \n"
+ msg += {"Security records: \[View\] \[View Brief\]
+ \[Add Note\] \n"}
if(hasHUD(user, "medical"))
var/perpname = "wot"
@@ -317,16 +318,11 @@
perpname = id_card.registered_name
else
perpname = src.name
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ medical = E.get_status()
- for (var/datum/data/record/E in data_core.general)
- if (E.fields["name"] == perpname)
- for (var/datum/data/record/R in data_core.general)
- if (R.fields["id"] == E.fields["id"])
- medical = R.fields["p_stat"]
-
- msg += "\n"
msg += "Physical status: \[[medical]\] \n"
- msg += "Medical records: \[View\] \[Add comment\] \n"
+ msg += "Medical records: \[View\] \n"
var/obj/item/clothing/under/U = w_uniform
if(U && istype(U) && U.sensor_mode >= 2)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b18473b9030..39709317b75 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -426,21 +426,20 @@ var/list/rank_prefix = list(\
if(perpname)
var/datum/computer_file/report/crew_record/R = get_crewmember_record(perpname)
if(R)
+ modified = TRUE
var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.get_criminalStatus()) in GLOB.security_statuses + "Cancel"
- if(hasHUD(usr, "security"))
- if(setcriminal != "Cancel")
- R.set_criminalStatus(setcriminal)
- modified = TRUE
- BITSET(hud_updateflag, WANTED_HUD)
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- U.handle_regular_hud_updates()
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- U.handle_regular_hud_updates()
+ if(setcriminal != "Cancel")
+ R.set_criminalStatus(setcriminal)
+ BITSET(hud_updateflag, WANTED_HUD)
+ if(ishuman(usr))
+ var/mob/living/carbon/human/U = usr
+ U.handle_regular_hud_updates()
+ if(isrobot(usr))
+ var/mob/living/silicon/robot/U = usr
+ U.handle_regular_hud_updates()
if(!modified)
- to_chat(usr, span_red("Unable to locate a data core entry for this person."))
+ to_chat(usr, span_red("Unable to locate a criminal record for this person."))
if(href_list["secrecord"])
if(hasHUD(usr,"security"))
@@ -453,52 +452,50 @@ var/list/rank_prefix = list(\
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.security)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"security"))
- to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]")
- to_chat(usr, "Minor Crimes: [R.fields["mi_crim"]]")
- to_chat(usr, "Details: [R.fields["mi_crim_d"]]")
- to_chat(usr, "Major Crimes: [R.fields["ma_crim"]]")
- to_chat(usr, "Details: [R.fields["ma_crim_d"]]")
- to_chat(usr, "Notes: [R.fields["notes"]]")
- to_chat(usr, "\[View Comment Log\] ")
- read = 1
+ var/datum/computer_file/report/crew_record/CR = get_crewmember_record(perpname)
+ if(CR)
+ to_chat(usr, "Name: [CR.get_name()] Criminal Status: [CR.get_criminalStatus()]")
+ var/datum/report_field/array/tofetch = CR.get_linkage_secNotes()
+ var/list/Briefing = tofetch.value_list
+ if(Briefing.len > 0)
+ var/list/combined = list()
+ for(var/iterator = min(Briefing.len-1, 3), iterator > -1, iterator -= 1)
+ combined.Add(Briefing[Briefing.len - iterator])
+ to_chat(usr, "Briefing latest: "+combined.Join(", "))
+ to_chat(usr, "\[Add to Brief\] ")
+ to_chat(usr, "\[View Full Brief\] ")
+ read = 1
if(!read)
- to_chat(usr, span_red("Unable to locate a data core entry for this person."))
+ to_chat(usr, span_red("Unable to locate a criminal record for this person."))
- if(href_list["secrecordComment"])
+ if(href_list["viewbrief"])
if(hasHUD(usr,"security"))
var/perpname = "wot"
- var/read = 0
- var/obj/item/card/id/id = GetIdCard()
- if(istype(id))
- perpname = id.registered_name
+ if(wear_id)
+ var/obj/item/card/id/id
+ if(istype(wear_id, /obj/item/modular_computer/pda))
+ id = wear_id.GetIdCard()
+ if(!id)
+ id = get_idcard()
+ if(id)
+ perpname = id.registered_name
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.security)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"security"))
- read = 1
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- to_chat(usr, text("[]", R.fields[text("com_[]", counter)]))
- counter++
- if(counter == 1)
- to_chat(usr, "No comment found")
- to_chat(usr, "\[Add comment\] ")
-
- if(!read)
- to_chat(usr, span_red("Unable to locate a data core entry for this person."))
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ if(!E)
+ to_chat(usr, span_danger("Unable to locate a record for this person."))
+ return
+ var/datum/report_field/array/tofetch = E.get_linkage_secNotes()
+ var/list/Briefing = tofetch.value_list
+ if(Briefing.len > 0)
+ to_chat(usr, span_notice("Brief: " + Briefing.Join(", ")))
+ else
+ to_chat(usr, span_notice("[perpname] does not have a brief."))
- if(href_list["secrecordadd"])
+ if(href_list["secnoteadd"])
if(hasHUD(usr,"security"))
var/perpname = "wot"
if(wear_id)
@@ -507,32 +504,27 @@ var/list/rank_prefix = list(\
id = wear_id.GetIdCard()
if(!id)
id = get_idcard()
- if(id)
- perpname = id.registered_name
+ if(id)
+ perpname = id.registered_name
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.security)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"security"))
- var/t1 = sanitize(input("Add Comment:", "Sec. records", null, null) as message)
- if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) )
- return
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- counter++
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [CURRENT_SHIP_YEAR] [t1]")
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [CURRENT_SHIP_YEAR] [t1]")
+
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ if(!E)
+ to_chat(usr, span_warning("Record for [perpname] not found!"))
+ return
+ var/t1 = sanitize(input("Add to Brief:", "Sec. records", null, null) as text)
+ if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) )
+ return
+
+ var/datum/report_field/array/recordnote = E.get_linkage_secNotes()
+
+ if(recordnote)
+ recordnote.add_value(t1)
if(href_list["medical"])
if(hasHUD(usr,"medical"))
var/perpname = "wot"
- var/modified = 0
var/obj/item/card/id/id = GetIdCard()
if(istype(id))
@@ -540,126 +532,49 @@ var/list/rank_prefix = list(\
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.general)
- if(R.fields["id"] == E.fields["id"])
-
- var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("*SSD*", "*Deceased*", "Physically Unfit", "Active", "Disabled", "Cancel")
-
- if(hasHUD(usr,"medical"))
- if(setmedical != "Cancel")
- R.fields["p_stat"] = setmedical
- modified = 1
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ if(E)
+ var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", E.get_status()) in GLOB.physical_statuses
- spawn()
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- U.handle_regular_hud_updates()
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- U.handle_regular_hud_updates()
+ if(hasHUD(usr,"medical"))
+ if(setmedical != "Cancel")
+ E.set_status(setmedical)
- if(!modified)
- to_chat(usr, span_red("Unable to locate a data core entry for this person."))
-
- if(href_list["medrecord"])
- if(hasHUD(usr,"medical"))
- var/perpname = "wot"
- var/read = 0
+ spawn()
+ if(ishuman(usr))
+ var/mob/living/carbon/human/U = usr
+ U.handle_regular_hud_updates()
+ if(isrobot(usr))
+ var/mob/living/silicon/robot/U = usr
+ U.handle_regular_hud_updates()
- if(wear_id)
- var/obj/item/card/id/id
- if(istype(wear_id, /obj/item/modular_computer/pda))
- id = wear_id.GetIdCard()
- if(!id)
- id = get_idcard()
- if(id)
- perpname = id.registered_name
else
- perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.medical)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"medical"))
- to_chat(usr, "Name: [R.fields["name"]] Blood Type: [R.fields["b_type"]]")
- to_chat(usr, "DNA: [R.fields["b_dna"]]")
- to_chat(usr, "Minor Disabilities: [R.fields["mi_dis"]]")
- to_chat(usr, "Details: [R.fields["mi_dis_d"]]")
- to_chat(usr, "Major Disabilities: [R.fields["ma_dis"]]")
- to_chat(usr, "Details: [R.fields["ma_dis_d"]]")
- to_chat(usr, "Notes: [R.fields["notes"]]")
- to_chat(usr, "\[View Comment Log\] ")
- read = 1
-
- if(!read)
- to_chat(usr, span_red("Unable to locate a data core entry for this person."))
+ to_chat(usr, span_red("Unable to locate a medical record for this person."))
- if(href_list["medrecordComment"])
+ if(href_list["medrecord"])
if(hasHUD(usr,"medical"))
var/perpname = "wot"
var/read = 0
- if(wear_id)
- var/obj/item/card/id/id
- if(istype(wear_id, /obj/item/modular_computer/pda))
- id = wear_id.GetIdCard()
- if(!id)
- id = get_idcard()
- if(id)
- perpname = id.registered_name
+ var/obj/item/card/id/id = GetIdCard()
+ if(istype(id))
+ perpname = id.registered_name
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.medical)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"medical"))
- read = 1
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- to_chat(usr, text("[]", R.fields[text("com_[]", counter)]))
- counter++
- if(counter == 1)
- to_chat(usr, "No comment found")
- to_chat(usr, "\[Add comment\] ")
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ var/datum/report_field/arrayclump/M = E.get_linkage_medRecord()
+ if(E)
+ to_chat(usr, "Name: [E.get_name()] Blood Type: [E.get_bloodtype()]")
+ to_chat(usr, "DNA: [E.get_dna()]")
+ to_chat(usr, "Prosthetics: [M.value["prosthetics"]]")
+ to_chat(usr, "Recorded Wounds: [M.value["wounds"]]")
+ to_chat(usr, "Autopsy: [M.value["Body state"]]")
+ to_chat(usr, "Psychological Profile: [M.value["psychological"]]")
+ to_chat(usr, "Chemical History: [M.value["chemhistory"]]")
+ read = 1
if(!read)
- to_chat(usr, span_red("Unable to locate a data core entry for this person."))
-
- if(href_list["medrecordadd"])
- if(hasHUD(usr,"medical"))
- var/perpname = "wot"
- if(wear_id)
- var/obj/item/card/id/id
- if(istype(wear_id, /obj/item/modular_computer/pda))
- id = wear_id.GetIdCard()
- if(!id)
- id = get_idcard()
- if(id)
- perpname = id.registered_name
- else
- perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.medical)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"medical"))
- var/t1 = sanitize(input("Add Comment:", "Med. records", null, null) as message)
- if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"medical")) )
- return
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- counter++
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [CURRENT_SHIP_YEAR] [t1]")
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [CURRENT_SHIP_YEAR] [t1]")
+ to_chat(usr, span_red("Unable to locate a medical record for this person."))
if(href_list["lookitem"])
var/obj/item/I = locate(href_list["lookitem"])
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index e09cf0ff7a3..479fa4bcdaf 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -82,9 +82,6 @@
var/equipment_prescription // Eye prescription granted by equipped items
var/list/equipment_overlays = list() // Extra overlays from equipped items
- var/med_record = ""
- var/sec_record = ""
- var/gen_record = ""
var/exploit_record = ""
var/stance_damage = 0 //Whether this mob's ability to stand has been affected
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 43434ed760f..1881ffe5887 100755
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -500,17 +500,8 @@ default behaviour is:
// Delete them from datacore.
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
- for(var/datum/data/record/R in data_core.medical)
- if ((R.fields["name"] == src.real_name))
- qdel(R)
- for(var/datum/data/record/T in data_core.security)
- if ((T.fields["name"] == src.real_name))
- qdel(T)
- for(var/datum/data/record/G in data_core.general)
- if ((G.fields["name"] == src.real_name))
- qdel(G)
+ var/datum/todelete = get_crewmember_record(name)
+ qdel(todelete)
//This should guarantee that ghosts don't spawn.
src.ckey = null
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index c15934b2333..84e50b597e2 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -550,8 +550,8 @@ var/list/ai_verbs_default = list(
var/personnel_list[] = list()
- for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
- personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image.
+ for(var/datum/computer_file/report/crew_record/t in GLOB.all_crew_records)
+ personnel_list["[t.get_name()]: [t.get_job()]"] = t.photo_front//Pull names, rank, and image.
if(personnel_list.len)
input = input("Select a crew member:") as null|anything in personnel_list
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 50c307c0653..f0256ca095e 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -58,12 +58,10 @@
var/medHUD = FALSE // Toggles whether the Medical HUD is active or not
var/medical_cannotfind = 0
- var/datum/data/record/medicalActive1 // Datacore record declarations for record software
- var/datum/data/record/medicalActive2
+ var/datum/data/record/medicalActive // Datacore record declarations for record software
var/security_cannotfind = 0
- var/datum/data/record/securityActive1 // Could probably just combine all these into one
- var/datum/data/record/securityActive2
+ var/datum/data/record/securityActive
var/obj/machinery/door/hackdoor // The airlock being hacked
var/hackprogress = 0 // Possible values: 0 - 1000, >= 1000 means the hack is complete and will be reset upon next check
@@ -158,11 +156,9 @@
set category = "pAI Commands"
set name = "Reset Records Software"
- securityActive1 = null
- securityActive2 = null
+ securityActive = null
security_cannotfind = 0
- medicalActive1 = null
- medicalActive2 = null
+ medicalActive = null
medical_cannotfind = 0
SSnano.update_uis(src)
to_chat(usr, span_notice("You reset your record-viewing software."))
diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm
index 9bc461a4e0d..e2a25dd9549 100644
--- a/code/modules/mob/living/silicon/pai/software_modules.dm
+++ b/code/modules/mob/living/silicon/pai/software_modules.dm
@@ -122,21 +122,19 @@
ram_cost = 5
id = "manifest"
toggle = 0
+ var/datum/nano_module/crew_manifest/manifestmodule
+ var/datum/topic_manager/program/mandatorymanager
-/datum/pai_software/crew_manifest/on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
- data_core.get_manifest_json()
+/datum/pai_software/crew_manifest/New()
+ mandatorymanager = new()
+ manifestmodule = new(src, mandatorymanager)
- var/data[0]
- // This is dumb, but NanoUI breaks if it has no data to send
- data["manifest"] = list("__json_cache" = ManifestJSON)
+/datum/pai_software/crew_manifest/Destroy()
+ . = ..()
+ QDEL_NULL(manifestmodule)
- ui = SSnano.try_update_ui(user, user, id, ui, data, force_open)
- if(!ui)
- // Don't copy-paste this unless you're making a pAI software module!
- ui = new(user, user, id, "pai_manifest.tmpl", "Crew Manifest", 450, 600)
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+/datum/pai_software/crew_manifest/on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=NANOUI_REINITIALIZE)
+ manifestmodule.nano_ui_interact(user, ui, "main", force_open) // transfers applicable vars to manifestmodule
/* Medical Records */
/datum/pai_software/med_records
@@ -148,20 +146,25 @@
/datum/pai_software/med_records/on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
- var/records[0]
- for(var/datum/data/record/general in sortRecord(data_core.general))
- var/record[0]
- record["name"] = general.fields["name"]
- record["ref"] = "\ref[general]"
- records[++records.len] = record
+ var/records[0]
+ for(var/datum/computer_file/report/crew_record/general in GLOB.all_crew_records)
+ var/record[0]
+ record["name"] = general.get_name()
+ record["ref"] = "\ref[general]"
+ records[++records.len] = record
data["records"] = records
- var/datum/data/record/G = user.medicalActive1
- var/datum/data/record/M = user.medicalActive2
- data["general"] = G ? G.fields : null
- data["medical"] = M ? M.fields : null
- data["could_not_find"] = user.medical_cannotfind
+ var/datum/computer_file/report/crew_record/G = user.securityActive
+ var/datum/report_field/arrayclump/M = G?.get_linkage_medRecord()
+ data["general"] = G ? list("name" = G.get_name(), "sex" = G.get_sex(), "species" = G.get_species(), "age" = G.get_age(), \
+ "job" = G.get_job(), "fingerprint" = G.get_fingerprint(), "status" = G.get_status(), "bloodtype" = G.get_bloodtype()) : null
+ data["prosthetics"] = M ? M.value["prosthetics"] : null
+ data["wounds"] = M ? M.value["wounds"] : null
+ data["Body state"] = M ? M.value["body state"] : null
+ data["chemhistory"] = M ? M.value["chemhistory"] : null
+ data["psychological"] = M ? M.value["psychological"] : null
+ data["could_not_find"] = user.medical_cannotfind
ui = SSnano.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
@@ -172,26 +175,17 @@
ui.set_auto_update(1)
/datum/pai_software/med_records/Topic(href, href_list)
- var/mob/living/silicon/pai/P = usr
- if(!istype(P)) return
+ var/mob/living/silicon/pai/P = usr
+ if(!istype(P)) return
- if(href_list["select"])
- var/datum/data/record/record = locate(href_list["select"])
- if(record)
- var/datum/data/record/R = record
- var/datum/data/record/M = null
- if (!( data_core.general.Find(R) ))
- P.medical_cannotfind = 1
- else
+ if(href_list["select"])
+ var/datum/computer_file/report/crew_record/record = locate(href_list["select"])
+ if(istype(record))
P.medical_cannotfind = 0
- for(var/datum/data/record/E in data_core.medical)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- M = E
- P.medicalActive1 = R
- P.medicalActive2 = M
- else
- P.medical_cannotfind = 1
- return 1
+ P.medicalActive = record
+ else
+ P.medical_cannotfind = 1
+ return TRUE
/* Security records */
/datum/pai_software/sec_records
@@ -204,19 +198,19 @@
var/data[0]
var/records[0]
- for(var/datum/data/record/general in sortRecord(data_core.general))
+ for(var/datum/computer_file/report/crew_record/general in GLOB.all_crew_records)
var/record[0]
- record["name"] = general.fields["name"]
+ record["name"] = general.get_name()
record["ref"] = "\ref[general]"
records[++records.len] = record
data["records"] = records
- var/datum/data/record/G = user.securityActive1
- var/datum/data/record/S = user.securityActive2
- data["general"] = G ? G.fields : null
- data["security"] = S ? S.fields : null
- data["could_not_find"] = user.security_cannotfind
+ var/datum/computer_file/report/crew_record/G = user.securityActive
+ data["general"] = G ? list("name" = G.get_name(), "sex" = G.get_sex(), "species" = G.get_species(), "age" = G.get_age(), \
+ "job" = G.get_job(), "fingerprint" = G.get_fingerprint(), "status" = G.get_status(), "criminalStatus" = G.get_criminalStatus(), \
+ "secNotes" = G.get_linkage_secNotes()) : null
+ data["could_not_find"] = user.security_cannotfind
ui = SSnano.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
@@ -231,26 +225,14 @@
if(!istype(P)) return
if(href_list["select"])
- var/datum/data/record/record = locate(href_list["select"])
- if(record)
- var/datum/data/record/R = record
- var/datum/data/record/S = null
- if (!( data_core.general.Find(R) ))
- P.securityActive1 = null
- P.securityActive2 = null
- P.security_cannotfind = 1
- else
- P.security_cannotfind = 0
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- S = E
- P.securityActive1 = R
- P.securityActive2 = S
+ var/datum/computer_file/report/crew_record/record = locate(href_list["select"])
+ if(istype(record))
+ P.security_cannotfind = 0
+ P.securityActive = record
else
- P.securityActive1 = null
- P.securityActive2 = null
+ P.securityActive = null
P.security_cannotfind = 1
- return 1
+ return TRUE
/* Door Jack */
/datum/pai_software/door_jack
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 354900a99a5..33bfbab68ba 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -448,11 +448,11 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
if(id)
perpname = id.registered_name
- var/datum/data/record/R = find_security_record("name", perpname)
- if(check_records && !R)
+ var/datum/computer_file/report/crew_record/CR = get_crewmember_record(perpname)
+ if(check_records && !CR)
threatcount += 4
- if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
+ if(check_arrest && CR && (CR?.get_criminalStatus() == "*Arrest*")) // why is paperwork's folly being translated to electronic format?
threatcount += 4
return threatcount
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 8a39be844e9..d488b34daf9 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -329,7 +329,6 @@
if(SSjob.ShouldCreateRecords(job.title))
if(character.mind.assigned_role != "Robot")
CreateModularRecord(character)
- data_core.manifest_inject(character)
matchmaker.do_matchmaking()
SSticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
diff --git a/code/modules/modular_computers/computers/modular_computer/core.dm b/code/modules/modular_computers/computers/modular_computer/core.dm
index a60b9c5d019..677cd0dacce 100644
--- a/code/modules/modular_computers/computers/modular_computer/core.dm
+++ b/code/modules/modular_computers/computers/modular_computer/core.dm
@@ -308,6 +308,8 @@
SetName(initial(name))
/obj/item/modular_computer/proc/update_uis()
+ if(active_program && istype(active_program?.nanomodule_path, /datum/nano_module/tgui))
+ return FALSE
if(active_program) //Should we update program ui or computer ui?
SSnano.update_uis(active_program)
if(active_program.NM)
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index e9cb4fa6618..6efb8fbc1b9 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -195,7 +195,10 @@
if(ui)
ui.close()
return computer.nano_ui_interact(user)
- if(istype(NM))
+ if(istype(NM, /datum/nano_module/tgui))
+ NM.ui_interact(user)
+ return FALSE
+ else if(istype(NM))
NM.nano_ui_interact(user, ui_key, null, force_open)
return 0
return 1
diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm
index 50a46be6b0e..4e949a6c588 100644
--- a/code/modules/modular_computers/file_system/programs/command/card.dm
+++ b/code/modules/modular_computers/file_system/programs/command/card.dm
@@ -62,7 +62,7 @@
data["security_jobs"] = format_jobs(security_positions)
//data["exploration_jobs"] = format_jobs(exploration_positions)
data["service_jobs"] = format_jobs(civilian_positions)
- data["supply_jobs"] = format_jobs(cargo_positions)
+ data["supply_jobs"] = format_jobs(guild_positions)
data["church_jobs"] = format_jobs(church_positions)
//data["civilian_jobs"] = format_jobs(civilian_positions)
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
diff --git a/code/modules/modular_computers/file_system/programs/generic/records.dm b/code/modules/modular_computers/file_system/programs/generic/records.dm
index 72bb6bdb81a..a2756ccbd89 100644
--- a/code/modules/modular_computers/file_system/programs/generic/records.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/records.dm
@@ -1,3 +1,5 @@
+
+#define NULL_RECORD list("name" = null, "uid" = null, "creator" = null, "file_time" = null, "fields" = null, "access" = null, "access_edit" = null)
/datum/computer_file/program/records
filename = "crewrecords"
filedesc = "Crew Records"
@@ -7,22 +9,22 @@
size = 14
requires_ntnet = TRUE
available_on_ntnet = TRUE
- nanomodule_path = /datum/nano_module/records
+ nanomodule_path = /datum/nano_module/tgui/records
usage_flags = PROGRAM_ALL
-/datum/nano_module/records
+/datum/nano_module/tgui/records
name = "Crew Records"
var/datum/computer_file/report/crew_record/active_record
var/message = null
-/datum/nano_module/records/nano_ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = NANOUI_FOCUS, state = GLOB.default_state)
+/datum/nano_module/tgui/records/ui_data(mob/user)
var/list/data = host.initial_data()
var/list/user_access = get_record_access(user)
data["message"] = message
if(active_record)
- user << browse_rsc(active_record.photo_front, "front_[active_record.uid].png")
- user << browse_rsc(active_record.photo_side, "side_[active_record.uid].png")
+ data["front_pic"] = icon2base64html(active_record.photo_front)
+ data["side_pic"] = icon2base64html(active_record.photo_side)
data["pic_edit"] = check_access(user, access_heads) || check_access(user, access_security)
data += active_record.generate_nano_data(user_access)
else
@@ -41,13 +43,11 @@
ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
- ui = new(user, src, ui_key, "crew_records.tmpl", name, 700, 540, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
+ currentui = new(user, src, "CrewRecords", name)
+ currentui.open()
-/datum/nano_module/records/proc/get_record_access(mob/user)
+/datum/nano_module/tgui/records/proc/get_record_access(mob/user)
var/list/user_access = using_access || user.GetAccess()
var/obj/item/modular_computer/PC = nano_host()
@@ -57,7 +57,7 @@
return user_access
-/datum/nano_module/records/proc/edit_field(mob/user, field_ID)
+/datum/nano_module/tgui/records/proc/edit_field(mob/user, field_ID)
var/datum/computer_file/report/crew_record/R = active_record
if(!R)
return
@@ -69,7 +69,7 @@
return
F.ask_value(user)
-/datum/nano_module/records/Topic(href, href_list)
+/datum/nano_module/tgui/records/ui_act(action, params)
if(..())
return 1
if(href_list["clear_active"])
@@ -113,23 +113,22 @@
var/datum/computer_file/report/crew_record/R = active_record
if(!istype(R))
return 1
- if(href_list["edit_photo_front"])
- var/photo = get_photo(usr)
- if(photo && active_record)
- active_record.photo_front = photo
- nano_ui_interact(usr)
- return 1
- if(href_list["edit_photo_side"])
- var/photo = get_photo(usr)
- if(photo && active_record)
- active_record.photo_side = photo
- nano_ui_interact(usr)
- return 1
- if(href_list["edit_field"])
- edit_field(usr, text2num(href_list["edit_field"]))
- return 1
+ switch(action)
+ if("edit_photo_front")
+ var/photo = get_photo(usr)
+ if(photo && active_record)
+ active_record.photo_front = photo
+ return 1
+ if("edit_photo_side")
+ var/photo = get_photo(usr)
+ if(photo && active_record)
+ active_record.photo_side = photo
+ return 1
+ if("edit_field")
+ edit_field(usr, text2num(params["edit_field"]))
+ return 1
-/datum/nano_module/records/proc/get_photo(mob/user)
+/datum/nano_module/tgui/records/proc/get_photo(var/mob/user)
if(istype(user.get_active_held_item(), /obj/item/photo))
var/obj/item/photo/photo = user.get_active_held_item()
return photo.img
diff --git a/code/modules/modular_computers/file_system/reports/crew_record.dm b/code/modules/modular_computers/file_system/reports/crew_record.dm
index a158121b5c7..c6fb06b2825 100644
--- a/code/modules/modular_computers/file_system/reports/crew_record.dm
+++ b/code/modules/modular_computers/file_system/reports/crew_record.dm
@@ -53,34 +53,131 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest")
// Medical record
set_bloodtype(H ? H.b_type : "Unset")
- set_medRecord((H && H.med_record && !jobban_isbanned(H.ckey, "Records") ? html_decode(H.med_record) : "No record supplied"))
+ var/datum/preferences/loadedprefs = H?.client?.prefs
+ var/datum/report_field/arrayclump/medRecord = get_linkage_medRecord()
+ if(H)
+ var/list/wounds = list()
+ var/list/prosthetics = list()
+ var/list/scannedlimbs = list()
+ for(var/datum/organ_description/OD in H.species.has_limbs) // default limbs for species
+ if(H.organs_by_name[OD.organ_tag])
+ if(istype(H.organs_by_name[OD.organ_tag], OD.default_type)) // these lists contain abnormalilities, so normalities are skipped.
+ continue
+ else
+ var/obj/item/organ/external/organthing = H.organs_by_name[OD.organ_tag]
+ if(organthing.is_stump())
+ wounds.Add("[organthing.name] instead of [OD.name]")
+ else
+ prosthetics.Add(organthing.name)
+
+ scannedlimbs.Add(organthing)
+ // TODO: add organ checks once FBPs are better coded
+ else
+ wounds.Add("Missing [OD.name]")
+ var/list/addictions = list()
+ for(var/datum/reagent/addicted in H.metabolism_effects.addiction_list)
+ addictions.Add("Observed addicted to [addicted.name]")
+
+ var/bodystate
+ switch(H.stat)
+ if(DEAD)
+ bodystate = list("Dead at time of writing")
+ if(UNCONSCIOUS)
+ if(H.getOxyLoss() > H.species.total_health/2)
+ bodystate = list("Comatose at time of writing")
+ else
+ bodystate = list("Alive at time of writing")
+ if(CONSCIOUS)
+ bodystate = list("Alive at time of writing")
+
+ medRecord.value["wounds"] = wounds.len ? wounds : list("No wounds on record.")
+ medRecord.value["prosthetics"] = prosthetics.len ? prosthetics : list("No prosthetics on record.")
+ medRecord.value["Body state"] = bodystate ? bodystate : list("\[Data Missing\]")
+ medRecord.value["chemhistory"] = addictions.len ? addictions : list("Chemical record is clean.")
+
+ var/list/psychological = list()
+ for(var/datum/perk/profile in H.stats.perks)
+ switch(profile.type)
+ if(PERK_NIHILIST)
+ psychological.Add("Has an empty outlook on life.")
+ if(PERK_MORALIST)
+ psychological.Add("High morale in groups.")
+ if(PERK_DRUG_ADDICT)
+ psychological.Add("Easily addicted, remains addicted indefinitely.")
+ if(PERK_ALCOHOLIC)
+ psychological.Add("Psychologically dependent on alcohol.")
+ if(PERK_REJECTED_GENIUS, PERK_NOBLE)
+ psychological.Add("Mentally destabilized by minor stressing factors.")
+ if(PERK_RAT)
+ psychological.Add("Innately stressed by environments, to some degree.")
+ if(PERK_PAPER_WORM)
+ psychological.Add("Accustomed to over-stress.")
+ if(PERK_OBORIN_SYNDROME)
+ psychological.Add("Innately resilient to mental harm.")
+ if(PERK_LOWBORN, PERK_VAGABOND)
+ psychological |= "Accustomed to bad living conditions."
+ if(PERK_SURVIVOR)
+ psychological.Add("Accustomed to the presence of death.")
+ if(PERK_NEAT)
+ psychological.Add("Accustomed to the presence of grime, and comforted by its removal.")
+ if(PERK_GREEN_THUMB)
+ psychological.Add("Comforted by gardening.")
+ if(PERK_CLUB)
+ psychological.Add("Provides a comfortingly professional presence.")
+ if(PERK_CHAINGUN_SMOKER)
+ psychological.Add("Invigorated by smoking.")
+ if(PERK_CHARMING_PERSONALITY)
+ psychological.Add("Provides a comfortingly charming presence.")
+ if(PERK_HORRIBLE_DEEDS)
+ psychological.Add("UNSETTLING.")
+ if(PERK_TERRIBLE_FATE)
+ psychological.Add("More afraid of death than usual.")
+ if(PERK_BALLS_OF_PLASTEEL)
+ psychological.Add("Higher pain tolerance than otherwise indicated.")
+ if(PERK_ARTIST)
+ psychological.Add("Looks at life as art.")
+
+ medRecord.value["psychological"] = psychological.len ? psychological : list("No psychological abnormality at time of writing.")
+ else // if there isn't a human
+ var/datum/storedrecord/medical/default/medrecord = new() // just use the defaults
+ medrecord.transfertocomputer(medRecord)
+ qdel(medrecord)
// Security record
set_criminalStatus(GLOB.default_security_status)
set_dna(H ? H.dna_trace : "")
set_fingerprint(H ? H.fingers_trace : "")
- set_secRecord(H && H.sec_record && !jobban_isbanned(H.ckey, "Records") ? html_decode(H.sec_record) : "No record supplied")
- // Employment record
- var/employment_record = "No record supplied"
if(H)
- if(H.gen_record && !jobban_isbanned(H.ckey, "Records"))
- employment_record = html_decode(H.gen_record)
- if(H.client && H.client.prefs)
- var/list/qualifications
- if(LAZYLEN(qualifications))
- employment_record = "[employment_record ? "[employment_record]\[br\]" : ""][jointext(qualifications, "\[br\]>")]"
- set_emplRecord(employment_record)
-
-
- if(H)
- var/stats = list()
- for(var/statName in ALL_STATS)
- var/points = H.stats.getStat(statName,pure = TRUE)
- if(points > STAT_LEVEL_NONE)
- stats += "[statName]: [points] ([statPointsToLevel(points)])"
+ for(var/datum/perk/fate/profile in H.stats.perks)
+ switch(profile)
+ if(PERK_PAPER_WORM)
+ set_emplRecord("Experienced in bureacracy.")
+ if(PERK_FREELANCER)
+ set_emplRecord("Wide variety of employments.")
+ if(PERK_DRUG_ADDICT)
+ set_emplRecord("Has a history of drug addiction.")
+ if(PERK_ALCOHOLIC)
+ set_emplRecord("Is an alcoholic.")
+ if(PERK_NOBLE)
+ set_emplRecord("Is of noble origin.")
+ if(PERK_LOWBORN)
+ set_emplRecord("Was hired from poverty.")
+ if(!get_emplRecord())
+ set_emplRecord("Standard background.")
+ else
+ set_emplRecord("No record supplied.")
- set_skillset(jointext(stats,"\n"))
+ if(loadedprefs)
+ var/originfound
+ for(var/datum/category_group/setup_option_category/background/origin/OriginBG in loadedprefs.setup_options)
+ if(loadedprefs.loaded_character[OriginBG.name])
+ originfound = OriginBG.name
+ break
+ if(originfound)
+ set_origin(originfound)
+ else
+ set_origin("Origin not on record.")
// Antag record
set_antagRecord(H && H.exploit_record && !jobban_isbanned(H, "Records") ? html_decode(H.exploit_record) : "")
@@ -96,16 +193,16 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest")
/proc/SortModularRecords()
// improved bubble sort
- if(GLOB.all_crew_records.len > 1)
- for(var/i = 1; i <= GLOB.all_crew_records.len; i++)
- var/flag = FALSE
- for(var/j = 1; j <= GLOB.all_crew_records.len - 1; j++)
- var/datum/computer_file/report/crew_record/CR = GLOB.all_crew_records[j]
- var/datum/computer_file/report/crew_record/CR_NEXT = GLOB.all_crew_records[j+1]
- if(sorttext(CR.get_name(), CR_NEXT.get_name()) == -1)
- flag = TRUE
- GLOB.all_crew_records.Swap(j,j+1)
- if(!flag)
+ if(GLOB.all_crew_records.len > 1) // if list is big enough to sort
+ for(var/i = 1, i <= GLOB.all_crew_records.len, i++) // for each entry in list
+ var/flag = FALSE // define a var as false
+ for(var/j = GLOB.all_crew_records.len-1, j >= 1, j--) // cycle through all entries,
+ var/datum/computer_file/report/crew_record/CR = GLOB.all_crew_records[j] // starting from the one before the last
+ var/datum/computer_file/report/crew_record/CR_NEXT = GLOB.all_crew_records[j+1] // and the last
+ if(sorttext(CR.get_name(), CR_NEXT.get_name()) == 1) // if the one before the last is bigger than the last
+ flag = TRUE // reset the var to true
+ GLOB.all_crew_records.Swap(j,j+1) // and swap the last and the one before the last
+ if(!flag) // if no work was done, stop
break
// Gets crew records filtered by set of positions
@@ -161,9 +258,13 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest")
#define GETTER_SETTER(PATH, KEY) /datum/computer_file/report/crew_record/proc/get_##KEY(){var/datum/report_field/F = locate(/datum/report_field/##PATH/##KEY) in fields; if(F) return F.get_value()} \
/datum/computer_file/report/crew_record/proc/set_##KEY(given_value){var/datum/report_field/F = locate(/datum/report_field/##PATH/##KEY) in fields; if(F) F.set_value(given_value)}
+#define SELF_GETTER(PATH, KEY) /datum/computer_file/report/crew_record/proc/get_linkage_##KEY(){return locate(/datum/report_field/##PATH/##KEY) in fields}
#define SETUP_FIELD(NAME, KEY, PATH, ACCESS, ACCESS_EDIT) GETTER_SETTER(PATH, KEY); /datum/report_field/##PATH/##KEY;\
/datum/computer_file/report/crew_record/generate_fields(){..(); var/datum/report_field/##KEY = add_field(/datum/report_field/##PATH/##KEY, ##NAME);\
KEY.set_access(ACCESS, ACCESS_EDIT || ACCESS || access_heads)}
+#define SETUP_ARRAYFIELD(NAME, KEY, PATH, ACCESS, ACCESS_EDIT) SELF_GETTER(PATH, KEY); /datum/report_field/##PATH/##KEY;\
+/datum/computer_file/report/crew_record/generate_fields(){..(); var/datum/report_field/##KEY = add_field(/datum/report_field/##PATH/##KEY, ##NAME);\
+KEY.set_access(ACCESS, ACCESS_EDIT || ACCESS || access_heads)}
// Fear not the preprocessor, for it is a friend. To add a field, use one of these, depending on value type and if you need special access to see it.
// It will also create getter/setter procs for record datum, named like /get_[key here]() /set_[key_here](value) e.g. get_name() set_name(value)
@@ -174,6 +275,8 @@ KEY.set_access(ACCESS, ACCESS_EDIT || ACCESS || access_heads)}
#define FIELD_LIST(NAME, KEY, OPTIONS, ACCESS, ACCESS_EDIT) FIELD_LIST_EDIT(NAME, KEY, OPTIONS, ACCESS, ACCESS_EDIT)
#define FIELD_LIST_EDIT(NAME, KEY, OPTIONS, ACCESS, ACCESS_EDIT) SETUP_FIELD(NAME, KEY, options/crew_record, ACCESS, ACCESS_EDIT);\
/datum/report_field/options/crew_record/##KEY/get_options(){return OPTIONS}
+#define ARRAYFIELD_SINGLE(NAME, KEY, ACCESS, ACCESS_EDIT) SETUP_ARRAYFIELD(NAME, KEY, array/crew_record, ACCESS, ACCESS_EDIT)
+#define ARRAYFIELD_CLUMP(NAME, KEY, ACCESS, ACCESS_EDIT) SETUP_ARRAYFIELD(NAME, KEY, arrayclump/crew_record, ACCESS, ACCESS_EDIT)
// GENERIC RECORDS
FIELD_SHORT("Name", name, null, access_change_ids)
@@ -189,17 +292,17 @@ FIELD_NUM("Account",account, null, access_change_ids)
// MEDICAL RECORDS
FIELD_LIST("Blood Type", bloodtype, GLOB.blood_types, access_moebius, access_moebius)
-FIELD_LONG("Medical Record", medRecord, access_moebius, access_moebius)
+ARRAYFIELD_CLUMP("Medical Record", medRecord, access_moebius, access_moebius)
// SECURITY RECORDS
FIELD_LIST("Criminal Status", criminalStatus, GLOB.security_statuses, access_security, access_security)
-FIELD_LONG("Security Record", secRecord, access_security, access_security)
+ARRAYFIELD_SINGLE("Brief", secNotes, access_security, access_security)
FIELD_SHORT("DNA", dna, access_security, access_security)
FIELD_SHORT("Fingerprint", fingerprint, access_security, access_security)
// EMPLOYMENT RECORDS
FIELD_LONG("Employment Record", emplRecord, access_heads, access_heads)
-FIELD_LONG("Qualifications", skillset, access_heads, access_heads)
+FIELD_LONG("Place of origin", origin, access_heads, access_heads)
// ANTAG RECORDS
FIELD_LONG("Exploitable Information", antagRecord, access_syndicate, access_syndicate)
@@ -240,9 +343,13 @@ FIELD_LONG("Exploitable Information", antagRecord, access_syndicate, access_synd
. |= BR.name
*/
#undef GETTER_SETTER
+#undef SELF_GETTER
#undef SETUP_FIELD
+#undef SETUP_ARRAYFIELD
#undef FIELD_SHORT
#undef FIELD_LONG
#undef FIELD_NUM
#undef FIELD_LIST
#undef FIELD_LIST_EDIT
+#undef ARRAYFIELD_SINGLE
+#undef ARRAYFIELD_CLUMP
diff --git a/code/modules/modular_computers/file_system/reports/report.dm b/code/modules/modular_computers/file_system/reports/report.dm
index 2be0080d016..94fe1ded684 100644
--- a/code/modules/modular_computers/file_system/reports/report.dm
+++ b/code/modules/modular_computers/file_system/reports/report.dm
@@ -133,7 +133,22 @@ If the override option is set to 0, the access supplied will instead be added as
dat["access"] = field.verify_access(given_access)
dat["access_edit"] = field.verify_access_edit(given_access)
dat["name"] = field.display_name()
- dat["value"] = field.get_value()
+
+ if(istype(field, /datum/report_field/array))
+ var/datum/report_field/array/arrayfield = field
+ dat["list_value"] = arrayfield.value_list.Copy()
+ dat["list_clumps"] = null // must override with null values or else react gets weird
+ dat["value"] = null
+ else if(istype(field, /datum/report_field/arrayclump))
+ var/datum/report_field/arrayclump/clumpfield = field
+ dat["list_value"] = null
+ dat["list_clumps"] = clumpfield.value
+ dat["value"] = null
+ else
+ dat["list_value"] = null
+ dat["list_clumps"] = null
+ dat["value"] = field.get_value()
+
dat["can_edit"] = field.can_edit
dat["needs_big_box"] = field.needs_big_box
dat["ignore_value"] = field.ignore_value
diff --git a/code/modules/modular_computers/file_system/reports/report_field.dm b/code/modules/modular_computers/file_system/reports/report_field.dm
index f453d8c2f9a..b09fb51db6f 100644
--- a/code/modules/modular_computers/file_system/reports/report_field.dm
+++ b/code/modules/modular_computers/file_system/reports/report_field.dm
@@ -211,4 +211,151 @@ Basic field subtypes.
value_list.Remove(given_value)
/datum/report_field/array/ask_value(mob/user)
- add_value(input(user, "Add value", "") as null|text)
+ var/inputchoice = input(user, "Add or Remove value", "Field Edit", "Add") in list("Add", "Remove")
+ if(inputchoice == "Add")
+ var/toadd = input(user, "Add value", "Field Input") as null|text
+ if(!isnull(toadd))
+ add_value(toadd)
+ else if(inputchoice == "Remove")
+ remove_value(input(user, "Choose value to remove", "Field Reduce") as null|anything in value_list )
+
+
+
+/datum/report_field/arraylinkage
+ var/list/arrays = list()
+ ignore_value = TRUE // value is too generic to use
+
+// retrieves index of key
+// can retrieve additional entries of same index using additionalarrays param
+/datum/report_field/arraylinkage/proc/retrieve_index_of_array(key, index = 0, additionalarrays = list())
+ if(!(key && (arrays.len > 0) && index > 0)) // can we access?
+ return FALSE
+ var/primeretrieved = arrays[key] // key's array
+ if(!(index && primeretrieved && length(primeretrieved) >= index)) // can we access the index asked for using the key?
+ return FALSE
+ var/list/toreturn = list(primeretrieved[index])
+ for(var/arrayexists in additionalarrays) // all linked arrays we also want index of
+ if((arrayexists in arrays) && length(arrays[arrayexists]) >= index)
+ var/list/toadd = arrays[arrayexists]
+ toreturn.Add(toadd[index])
+ else
+ return FALSE // we really don't want input from bad sources.
+ . = toreturn // succeeded all the checks? caller's will be done.
+
+// adds one index to the end of each list
+// sets the contents of each list for the created index on demand using either keys or arrangement of any given input of proper size
+/datum/report_field/arraylinkage/proc/add_index(list/new_entries, keyed = FALSE)
+ if(!new_entries || new_entries.len > arrays.len)
+ return FALSE
+ if(new_entries.len != arrays.len) // only accept using list-order based indexing when it has a 1 to 1 ratio
+ keyed = TRUE
+ var/count = 1
+ if(keyed)
+ for(var/key in arrays) // unfitting keys are discarded, but can still disqualify a list.
+ var/list/currentarray = arrays[key]
+ if(new_entries[key])
+ currentarray.Add(new_entries[key])
+ else
+ currentarray.Add(null) // all arrays must have the same indexing for the linkage to work.
+ . = TRUE
+ else
+ for(var/entry in new_entries) // sanitize before it's t oo late
+ if(new_entries[entry])
+ CRASH("keyed outside of key mode in add_index")
+ for(var/entry in new_entries)
+ var/list/currentarray = arrays?[count]
+ if(!currentarray) // in case a check breaks
+ return
+ count ++
+ currentarray.Add(entry)
+ . = TRUE
+
+// set one entry in one list
+/datum/report_field/arraylinkage/proc/edit_index(key, setto, index)
+ if(!arrays[key] || length(arrays[key]) < index || !islist(arrays[key]))
+ return FALSE
+ var/list/accessed = arrays[key]
+ if(accessed)
+ accessed[index] = setto
+ . = TRUE
+
+// delete one index of all lists in arraylinkage
+/datum/report_field/arraylinkage/proc/remove_index(index)
+ if(!length(arrays) || length(arrays[1]) < index) // check if there are arrays and the first one is long enough
+ return FALSE // hopefully all arrays have the same length as the first one
+ for(var/list/arraytocut in arrays)
+ arraytocut.Cut(index, index+1)
+ . = TRUE
+
+/datum/report_field/arraylinkage/ask_value(mob/user)
+
+/datum/report_field/arrayclump // these arrays are explicitly unlinked and are stored here for categorization
+ value = list() // only input key=array as entry
+
+/datum/report_field/arrayclump/set_value(given_value)
+ if(!islist(given_value))
+ return FALSE
+ . = ..()
+
+/datum/report_field/arrayclump/ask_value(mob/user)
+ . = TRUE
+ var/list/clumpvalue = value
+ if(!istype(clumpvalue))
+ return FALSE
+ var/list/entries = clumpvalue.Copy()
+ entries.Add("")
+
+ var/entrychoice = input(user, "Choose Entry Category", "Entry Category") as null | anything in entries
+ if(entrychoice == "" )
+ var/entryname = input(user, "Choose Entry Name", "Entry Name") as text | null
+ entryname = sanitizeSafe(entryname)
+ if(!istext(entryname))
+ to_chat(user, SPAN_NOTICE("Edit canceled successfully."))
+ return FALSE
+ if(clumpvalue[entryname]) // only replace entry with alert
+ if(alert(user, "Replace old entry?", "Entry Replacement", "Yes", "No") == "No")
+ to_chat(user, SPAN_NOTICE("Edit canceled successfully."))
+ return FALSE
+ var/startingvalue = input(user, "Create Entry", "Entry Creation") as text | null
+ startingvalue = sanitizeSafe(startingvalue)
+ if(!istext(startingvalue))
+ to_chat(user, SPAN_NOTICE("Edit canceled successfully."))
+ return FALSE
+ to_chat(user, SPAN_NOTICE("You have successfully added an entry to [name]."))
+ value[entryname] = list(startingvalue)
+
+ else if(entrychoice)
+ var/list/selections = clumpvalue[entrychoice]
+ selections = selections.Copy() // don't edit the original list
+ selections.Add("")
+ var/selectionchoice = input(user, "Select Entry", "Entry") as null | anything in selections
+ if(!istext(selectionchoice))
+ return FALSE
+ if(selectionchoice == "")
+ var/nextvalue = input(user, "Add Value", "Value") as text | null
+ nextvalue = sanitizeSafe(nextvalue)
+ if(!istext(nextvalue))
+ to_chat(user, SPAN_NOTICE("Addition canceled successfully."))
+ return FALSE
+ else
+ var/list/entrytoaddto = clumpvalue[entrychoice]
+ if(istype(entrytoaddto))
+ entrytoaddto.Add(nextvalue)
+ else
+ CRASH("Type Mismatch in clump list")
+
+ else
+ var/newvalue = input(user, "New Value", "Value") as text | null
+ newvalue = sanitizeSafe(newvalue)
+ if(!istext(newvalue))
+ to_chat(user, SPAN_NOTICE("Replacement canceled successfully."))
+ return FALSE
+ var/list/intermediaryvalue = clumpvalue[entrychoice]
+ if(istype(intermediaryvalue))
+ var/indexhound = clumpvalue.Find(intermediaryvalue) // the Hound finds the value we splice
+ intermediaryvalue.Splice(indexhound, indexhound+1, newvalue)
+ else
+ CRASH("Type Mismatch in clump list")
+
+
+
diff --git a/code/modules/nano/modules/tgui_type.dm b/code/modules/nano/modules/tgui_type.dm
new file mode 100644
index 00000000000..e605715301b
--- /dev/null
+++ b/code/modules/nano/modules/tgui_type.dm
@@ -0,0 +1,92 @@
+/datum/nano_module/tgui
+ var/datum/tgui/currentui // gotta save it, we can't get it any other way
+ var/show_map ; var/map_z_level // the sins of our predecessors, brought to the present by the sins of our own
+
+/datum/nano_module/tgui/ui_host(mob/user)
+ return nano_host()
+
+/datum/nano_module/tgui/ui_close(mob/user)
+ . = ..()
+ currentui = null // must clear reference to ui
+
+/datum/nano_module/tgui/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/spritesheet/legacyicons)
+ )
+
+
+/datum/nano_module/tgui/ui_act(action, params)
+ . = ..()
+
+ if(istype(host, /datum/computer_file/program))
+ var/datum/computer_file/program/program = host
+ switch(action)
+ if("PC_exit")
+ program.computer.kill_program()
+ return TRUE
+ if("PC_enable_component")
+ var/obj/item/computer_hardware/H = program.computer.find_hardware_by_name(params["component"])
+ if(istype(H) && !H.enabled)
+ H.enabled = TRUE
+ H.enabled()
+ . = TRUE
+ if("PC_disable_component")
+ var/obj/item/computer_hardware/H = program.computer.find_hardware_by_name(params["component"])
+ if(istype(H) && H.enabled)
+ H.enabled = FALSE
+ H.disabled()
+ . = TRUE
+ if("PC_toggle_component")
+ var/obj/item/computer_hardware/H = program.computer.find_hardware_by_name(params["component"])
+ if(istype(H))
+ H.enabled = !H.enabled
+ if(H.enabled)
+ H.enabled()
+ else
+ H.disabled()
+ . = TRUE
+ if("PC_shutdown")
+ program.computer.shutdown_computer()
+ return TRUE
+ if("PC_minimize")
+ var/mob/user = usr
+ program.computer.minimize_program(user)
+
+ if("PC_killprogram")
+ var/prog_name = params["PC_killprogram"]
+ var/obj/item/computer_hardware/hard_drive/prog_disk = locate(params["disk"]) in program.computer
+ if(!prog_disk)
+ return TRUE
+
+ for(var/p in program.computer.all_threads)
+ var/datum/computer_file/program/PRG = p
+ if(PRG.program_state == PROGRAM_STATE_KILLED)
+ continue
+
+ if(PRG.filename == prog_name && (PRG in prog_disk.stored_files))
+ PRG.kill_program(forced=TRUE)
+ to_chat(usr, SPAN_NOTICE("Program [PRG.filename].[PRG.filetype] has been killed."))
+ . = TRUE
+
+ if("PC_runprogram")
+ var/obj/item/computer_hardware/hard_drive/prog_disk = locate(params["disk"]) in program.computer
+ return program.computer.run_program(params["PC_runprogram"], prog_disk)
+
+ if("PC_setautorun")
+ if(!program.computer.hard_drive)
+ return
+ program.computer.set_autorun(params["PC_setautorun"])
+ if("PC_terminal")
+ program.computer.open_terminal(usr)
+ return TRUE
+
+/datum/nano_module/tgui/ui_status(mob/user, datum/ui_state/state)
+ . = ..(user, state ? state : GLOB.default_state)
+ if(. > UI_DISABLED && istype(host, /datum/computer_file/program))
+ var/datum/computer_file/program/relevant = host
+ if(relevant.program_state == PROGRAM_STATE_KILLED)
+ . = UI_CLOSE
+ else if(relevant.program_state == PROGRAM_STATE_BACKGROUND)
+ . = min(., UI_UPDATE) // theoretically might be necessary with a new system, if redundant just collapse this with the killing check.
+
+
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index da13f74c193..2e347f91a1d 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -107,22 +107,12 @@
/obj/structure/filingcabinet/security/populate()
if(virgin)
- for(var/datum/data/record/G in data_core.general)
- var/datum/data/record/S
- for(var/datum/data/record/R in data_core.security)
- if((R.fields["name"] == G.fields["name"] || R.fields["id"] == G.fields["id"]))
- S = R
- break
+ for(var/datum/computer_file/report/crew_record/G in GLOB.all_crew_records)
var/obj/item/paper/P = new /obj/item/paper(src)
P.info = "Security Record "
- P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]] \nSex: [G.fields["sex"]] \nAge: [G.fields["age"]] \nFingerprint: [G.fields["fingerprint"]] \nPhysical Status: [G.fields["p_stat"]] \nMental Status: [G.fields["m_stat"]] "
- P.info += " \nSecurity Data \nCriminal Status: [S.fields["criminal"]] \n \nMinor Crimes: [S.fields["mi_crim"]] \nDetails: [S.fields["mi_crim_d"]] \n \nMajor Crimes: [S.fields["ma_crim"]] \nDetails: [S.fields["ma_crim_d"]] \n \nImportant Notes: \n\t[S.fields["notes"]] \n \nComments/Log "
- var/counter = 1
- while(S.fields["com_[counter]"])
- P.info += "[S.fields["com_[counter]"]] "
- counter++
+ P.info += "Name: [G.get_name()] \nSex: [G.get_sex()] \nAge: [G.get_age()] \nFingerprint: [G.get_fingerprint()] "
P.info += ""
- P.name = "Security Record ([G.fields["name"]])"
+ P.name = "Security Record ([G.get_name()])"
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
@@ -142,24 +132,21 @@
/obj/structure/filingcabinet/medical/populate()
if(virgin)
- for(var/datum/data/record/G in data_core.general)
- var/datum/data/record/M
- for(var/datum/data/record/R in data_core.medical)
- if((R.fields["name"] == G.fields["name"] || R.fields["id"] == G.fields["id"]))
- M = R
- break
+ for(var/datum/computer_file/report/crew_record/G in GLOB.all_crew_records)
+ var/datum/report_field/arrayclump/M = G.get_linkage_medRecord()
if(M)
var/obj/item/paper/P = new /obj/item/paper(src)
- P.info = "Medical Record "
- P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]] \nSex: [G.fields["sex"]] \nAge: [G.fields["age"]] \nFingerprint: [G.fields["fingerprint"]] \nPhysical Status: [G.fields["p_stat"]] \nMental Status: [G.fields["m_stat"]] "
-
- P.info += " \nMedical Data \nBlood Type: [M.fields["b_type"]] \nDNA: [M.fields["b_dna"]] \n \nMinor Disabilities: [M.fields["mi_dis"]] \nDetails: [M.fields["mi_dis_d"]] \n \nMajor Disabilities: [M.fields["ma_dis"]] \nDetails: [M.fields["ma_dis_d"]] \n \nAllergies: [M.fields["alg"]] \nDetails: [M.fields["alg_d"]] \n \nCurrent Diseases: [M.fields["cdi"]] (per disease info placed in log/comment section) \nDetails: [M.fields["cdi_d"]] \n \nImportant Notes: \n\t[M.fields["notes"]] \n \nComments/Log "
- var/counter = 1
- while(M.fields["com_[counter]"])
- P.info += "[M.fields["com_[counter]"]] "
- counter++
- P.info += ""
- P.name = "Medical Record ([G.fields["name"]])"
+ var/list/infostoadd = list()
+ infostoadd += "Medical Record "
+ infostoadd += "Name: [G.get_name()] \nSex: [G.get_sex()] \nAge: [G.get_age()] "
+
+ infostoadd += " \nMedical Data \nBlood Type: [G.get_bloodtype()] \nDNA: [G.get_dna()] "
+ infostoadd += " \nProsthetics: [M.value["prosthetics"]] \nWounds: [M.value["wounds"]] \n \nAutopsy: [M.value["Body state"]] "
+ infostoadd +=" \nChemical History: [M.value["chemhistory"]] \nPsychological Profile: [M.value["psychological"]] "
+
+ infostoadd += ""
+ P.name = "Medical Record ([G.get_name()])"
+ P.info = infostoadd.Join() // minor optimization
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
diff --git a/code/modules/research/designs/circuits.dm b/code/modules/research/designs/circuits.dm
index f5c38fe0f0e..d424223f6d9 100644
--- a/code/modules/research/designs/circuits.dm
+++ b/code/modules/research/designs/circuits.dm
@@ -36,11 +36,6 @@
sort_string = "MABBA"
category = CAT_MISC
-/datum/design/research/circuit/secdata
- name = "security records console"
- build_path = /obj/item/electronics/circuitboard/secure_data
- sort_string = "DABAA"
- category = CAT_COMP
/datum/design/research/circuit/prisonmanage
name = "prisoner management console"
@@ -48,11 +43,6 @@
sort_string = "DACAA"
category = CAT_COMP
-/datum/design/research/circuit/med_data
- name = "medical records console"
- build_path = /obj/item/electronics/circuitboard/med_data
- sort_string = "FAAAA"
- category = CAT_COMP
/datum/design/research/circuit/operating
name = "patient monitoring console"
diff --git a/code/modules/research/nodes/biotech.dm b/code/modules/research/nodes/biotech.dm
index bdc911109c2..12140281da2 100644
--- a/code/modules/research/nodes/biotech.dm
+++ b/code/modules/research/nodes/biotech.dm
@@ -17,7 +17,7 @@
/datum/technology/basic_med_machines
name = "Basic Medical Machines"
- desc = "Basic medical databases and surgical monitoring."
+ desc = "Basic surgical monitoring."
tech_type = RESEARCH_BIOTECH
x = 0.25
@@ -28,9 +28,7 @@
required_tech_levels = list()
cost = 200
- unlocks_designs = list( /datum/design/research/circuit/med_data,
- /datum/design/research/circuit/operating
- )
+ unlocks_designs = list(/datum/design/research/circuit/operating)
/*
/datum/technology/virology
name = "Virology"
diff --git a/icons/ui_icons/dmis/uiicons16.dmi b/icons/ui_icons/dmis/uiicons16.dmi
new file mode 100644
index 0000000000000000000000000000000000000000..7b5d90ace41bbb78e4f6fad05779eb75da5deccc
GIT binary patch
literal 6642
zcmZu$cTf~xmu-R|N>Eht5F{%gSq3EMARvQE&OveS^cV3;;fvS!u1#GvcI*<7pNAQ%I)tTAxNoMxBTH
zwbv~PYXTD0t2%oc(-qroLZRH+FHF2r0Gt{dR8=26z4bFL+vKO`vusmu&blWC-*H>*
z(%W7XwzN|iN$Tti#Ruwswcpj{~L@svaoMjN!`RjgBe%^gEn0+c%OwDcl+>aZVgV`E!R`Rr(3JK
zr{%o3`IgY3@G@QKe2AVbPep)_S$kgb4u3usclUgL;)IL)Dy89`!8Du9-%3AcL)(z}Ti&~~
z`ygFa5TR*Y$S${1GN3(m*YK8ea|fZ`SK8NeAM{7=bM+X=xK{XPqW$wl%ygW#!zj2S
z0*dyJiJ)=|`?RT`&U^vwRq=02sR0$j`8vvVjPI#T7DQFWss1E+(zRFeG9@RDFR@$Slr6#6n9YpO=T0zR
zOA@IM(=+*&-72}ZLTQLc=Ba-jqh~8#olm}f8d`>
z{7S{$jV3e(k_yFrtt
z$w5o3ri!xUKU~fcgttF2PsTXDN}u2;J~p55teH&tp0y<;bcpvWz8x|;8u0zh{ky%5
z>i~$L1q7UM@1M~DEn=~AA?7q+7+N~fV`1Y=jrz7U5(D#@=Ze_$w|MiEfCu809MhA#E50?kQ!wx_hE`({{mQ0sDW
zf)@J3Vd*;Tc((=YO#y_P)4ZunI}IcTu0O==U($0ZSNTMqu#0UxFQm*vDozq5hCb(G|;3O=|wx7
zEYovZ=_^M(kN6ve>sEg&vk-t26Y&0h$C{0RGn@c883G^s0Vm`DU$}Y0%{uie#$EWR
zqPH_W9B?xk(H)D1fEXd{ngC`>-oC@?h$vBQ5Hj-_ajytD%X2I-mUjapFDY^RUiM-D
z^|w~#YWMl>_lthYywB^2Nx?MX3-#^%7ev5Stw{w%xVab+%#?>J`uY|OH-Ne(gyELN
zuCgpHng?M`S%Wn(>J9NurgGzAt^=1&G~v>wCMH*Oz|D$HftFK?Dm|d3sl#Gd5|}A`
zGK(wDfk-eZW!H|}U@fXsV^vPp=J(vl$mmCt9*+rr%kd5RcQTr0p8}OPqlvto&sUDa
z9K)viT8W;}4cH#!i|+h7cD{K;?ReyM?LN@twv?R_Fe@^E>NTes19sML!m3+6+0d5h
z^1P+b|8pz&n97lSmbwybb2ATLhOX<+7`1l(c|bH`3&_ylx#bwk(CsJH&c8~U?Z2n$
zLQiVxqJJRT!he(&iphZc7jZ9hXG|EwxBpymJWDEebs#dL+)pct$6dIjEc?~}MDJru
zXC??N?&cI&rT#!~NBe7Pt(|SqYSWoB5pN;#S{?R8+N<`!TzeC>>0m^5beqfQRpQ>@
z;9v#T5`@`9?N#yhASX6B18yfZ;^~46j%xV~^RMW<4!DFEVWoRo*-}mSyER7dn?5V0
zc>Z;G?t0Wd8QQiiPqX$gD{3PCYj)|-s?NE(xY!=uk$N?L$#SN0wZhT_6Op_}4Y!(T
zvPu}g&RI|iZgbO7Oi~hB>btot@WC^Zi+vo=5MernuhH-RUdRo6MISAkBVA93g{y;P
zn!ct;NJywp#b@FbX1(?!#C3<|$LM}$?M+Zed#p1X2dhkLs@W4E%9+{zb~zEu;k2~0
zvb&N27=#qgV7+=Bca4M>1k_)}~u0bS=W_yAQ>RSvsiVyH$RxTmhy4^%e#
zgdP?>dLMy)*(-4JuJ-+3v+QM9YMWZ;*4ec@IR(XQh6K6tAN({l>S`+o2N)0|Bb9{J
zw}C{_PB_zg<#k#L)YHB*83umLzVA_t;H)W&HYrmt-v=i2q;>QvME05a*SXJ#i
z+Xq5K=nZ6J*2?Y|iM~oo2bbL|jXm*=CF|fbhJAX@D`))cEx?u((V6kRmmTTl}+
zcB0ZqF1}AwmN4|g;9J8JZS@2UGWA$}{Om}b7wfQBm6d6v0_(4?5~VK46r<)LWO9Ci{
zaInlcJe7X4Zz*haWJ+$$m@)*&gY&Z+>Lg%scX#(t>m)FyelGC*O=JC;0{)ZdHZ4=l
zwy_SYbd(vT?hAr38~&(5MrGn-RkJ6DpQd9oiOs;YpZHwPYitM0Q?lTLiK?dn@~`D-
zV(cQAxdT}5Lkvfb20PtbBmLFiI+A+2k|Y24rxBm=`o#QAa9+iJXo#(FBW3At{Z(t~
zMxiq4lbxNNuiQA($pB%r<#;FQ-~cZ(uhH##cmx@=MD}LW*JyN)_Nj>0WjM_oX{Q$6
zBw4fB4UdNI|2ugEdq2#eTEP_Q5b-`fX~h{YuVFk0NUJ@vGVT{-{1s!dgP5isBj)WR(CFq^!aAZX8n-6xS1ohlF41?
zPBk7*q{Qb}0@#!z7_z#-5N6b*{s7HOya{Thhz~jmM&XqXK0IUqfgWY?H>=K^y?b$@
zy7q421DrIKGO@Ul&Kfe?C8+4t&tu!tkOz;77&zX;s{8CMqg}7B0=zvv32(%fC-=0H
zRRmvWSx0<{zJyDPB&
z%?A$r2Op%+vi=t*O7l=Up<>5-W*Go$bw
zmAsETiz;}rHd!oBl6oPQoz$Uys{b^|$M{0N>aZi4nm=}F=i+pqKFAX4BbnQ8bUHH!
z=`C)lwfs_HcCPi3i1nY$pxN{B^n@Sgsv>ey^~uXvkE7UQxeL3G+HgSg`Bvi=a@?db
z5bNI_Cmddjql_2-=%*%-oycChqjtGGb@XXnwom&WOr#H
zf+-Nz6~{!ead>tX&B?7o%=A-mZOy+*^5Nu6kNq97;FX$yJL&1CTp$)tDOKD;kH=pk
z;AB3OVy3kf?}h)#?>|j`)QnR8t5ngq&gjFJTBFmG6Aa6d2;zpxKwhF?1KPyv;;R&+
zkQJp*Z^)R*xW?R@;Zmi1q}f4Nr#rKL+o+1>Gy5Hi&e@>rfMaZmX&$ATdJyEeMH0(i
zWk82c%hj~mp9H`@Y*=U19u8(F>*j@g$Du_6d-ES|5pdbzvO<51eJOmS^pf~+
z&AZ#TDO^kX@}TpODe%O6xQM>%Ub>LddcgV;&WB?~N^XUj7Ec`n`yP?ot-dj9IJ=Q*
zG1>-opC$(ha|IcErq}+!`me2YRcM|ji`AS$KJOHO!+v;bw`rqDs
zolty9FJ}Oiv3oeEE2=$M<4a`TC8`pN{~}RlvlRbA+LfhWs+rmt
zECN>j@y_Yj@gy@+wsQFbqU?n^u*_oq5$fWGr^jLCoic(yneb2
znTlvQtgw#NXd;Ybc_zD*V2d<(X*b7PE7}VA?S2c!>r(#CNo8YWek-AO+{P5C5SplrtluQj7
z`!7x9e(YCcRyzWFrZ2p9+@b|Nb^bDzg1%COiNovM<^Qq>Ayxkwt^cX~t`rl+LTDXh
z+yr_3=a2yw3Lb?$u~ZM&j56tZV>TB3VKc7^OY-Aa1R6zQ*G+K!c2)GEjzpAx0pGx7
z3@^X8kLqag(0g`$l9_5tlnMF0I$0mnf-{3&_k(3YO5xt$l`JU2toDy-cNN=u&c$8V
z6Qith6g+-qWeKKtR?h}=$1=oy&-MRC28lJG)2(u?CTXkt3bl!H-V}T-=xXltV*ys0
z!SGxz8d_^bYZMjI)g6%~`baITiqlbfKu3u+9*j{0HRwQ#G14OYIt+UGai`+%p0RUd
zyN+3`yEdiZ+*tn!P55{8Od1y-)6)mj59SDC8MzZ*1EW{NW?^{Ne(6~J^WRO=`z*k4S^w+txeS{kLUMGnTvzq}o)M+HX*1GUh
zeJe^sKk}O$HB+5X9g)+6_0+afj|sQ?ZPfUR7>NB^6q{+XE(nJZ!DeO~$b=8vw#;7^
zrINLx66nZjQobRHlWuCf7DdrSy+#biW{r6wQNNhg$r6|L;Cv=byr`|AU@!ufRKUM-ww{HTFvttsi(uzPR5QJg`D+9DHp5`d86^Ae=VgN%ryHsVGT
zqH~kQ;>QJ$f2;l!9#_5#n}1cFKat@n^H(WHJE{b?s&-2kvMiUurX5-WwuY~(yUjOj
z@umd3wSb@Jx8{$!2>6NxtRM({*-HoJ+DJU^A7)lVSOvz57<={X(+mzrF}YO?V_X@6
zp*W(T@&|}zjCA5-YvE$n!I1P9;v4^qUij#f>d>{EFL-0YKg>0!-
z!J?dDQAmN6u=9)8#I^@7(Q2NqAieg}Lh+ISKK9<^@#~G9lJDRIy0@It%TkySK?4y_kNP75<5HxL4b(cJcKBHZ&^4bPq)n$&5_BL
z#=pTLZD5G!0-W-r>`wA%pvXG(;aWgaw%M$B1gS1#>q4`VwH~FZGVqJ|sz@*&a=hcjSa6Rvb(nCxrh*EO8{xUCAR!wCW--+Q
zRX-*_`K;Z>2&Fe;NDP@v{p?p_=9X6T$W3M*!7wZEPgc(is~yxTgAZ0e7{w^%m{jaC
z!$wGu2$?A-j&DH}Y*+^|jSAf-n?T5!Z*{4AuD!T0ecYEg!-%miauK$p1976%5rJ-u
zwSkmbaDZ5Z;F->gk8|FAyPry{w1xjaqW-HTR8rogu~?}UBmK-;+I|97K)w_5Bc2&2
zzwIjY(SWt0(wd>5wl4sM8)YxCkuuaW7!S?pxZk4=vG~EGteL3E#w%ePpl9brQ8RcGES?-;3;;B=)zyHLdb*wpnHrSRK(he~HX$0lm7
z5@siK)nrcdy`OAfeRVuZA2uAhKRA==^$}aSN7=X}u2K)6>PVq~+*@>IjR*=@wKLT)
z_EaOD4CQ=wm&lFT?-Z_Y0Rt~TV@PlQ5zJ^ig-2Fci8&H9%no0n)D*{us5-F-A0>Vp
zqEQf8R(Ik*_bdSOSo&EUZbPo$bTQX>%d}5e^H6sFuSWTQ)ZYJAbE`3Ov98)8#sm9^
z0GDg3!-_!pavM^!inx-LK%Rix>}5H&Qkk`v$VFFny#927O5PEaPTjJnm90#S5l^fU
z8u6yuz%({5nW8w@3K&+gDO!&|k|y)dcxfkpw1HL&vRwQ7!C;cK^k;EhZp!}Y#u8JM
zKX)9m$6&wcn3D$nB?SvSd#Sd8b+}t^IQyZB_(Rp*9U9|@I!9}
zJ3ZHxD}UI3vjrh(8^P_`ahQ#t>97q^!7pnmZ0T;5fU
z*9{C%n}8e3+8Fy^{jT77T+tj<>gr@^mV*XVMf=}>6TVh%)8cj3rV>!4%F9$%O*@7W
z9JvB^GOiaxTi?fM8|6glA1B|JT~is}4!?cqifzE_7>3PbperAgq6!E)LFJ0t_E9F-
zA|3t8HD2xvKjj1ZefCDe7>WKm@oXDsy_m%Qe_mZ=)MjPUOoxm)TzBb*q&RMg#MAB*
z9X=Z6CFM^3GeyF#z60-H@mGrdrlP!_Mu7{$vE7OoNKLBOuD!H*%23G(k@yLo53G5F
mgGp9d=L@j^mk;m0CeVc?T5V{ReYx4o0aO(=70TtzLjD7{Bk^(o
literal 0
HcmV?d00001
diff --git a/maps/CEVEris/_CEV_Eris.dmm b/maps/CEVEris/_CEV_Eris.dmm
index 7cb20aa7fbd..0518d04520b 100644
--- a/maps/CEVEris/_CEV_Eris.dmm
+++ b/maps/CEVEris/_CEV_Eris.dmm
@@ -102878,6 +102878,14 @@
},
/turf/floor/plating/under,
/area/eris/maintenance/sorter)
+"qmi" = (
+/obj/item/cell/medium,
+/obj/item/cell/medium,
+/obj/item/computer_hardware/processor_unit,
+/obj/item/computer_hardware/tesla_link,
+/obj/item/computer_hardware/tesla_link,
+/turf/floor/hull,
+/area/space)
"qmJ" = (
/obj/machinery/door/blast/shutters{
dir = 4;
@@ -104987,6 +104995,13 @@
},
/turf/floor/plating/under,
/area/eris/maintenance/section3deck5port)
+"tZv" = (
+/obj/item/computer_hardware/network_card/wired,
+/obj/item/computer_hardware/network_card/wired,
+/obj/item/computer_hardware/scanner/paper,
+/obj/item/computer_hardware/scanner/paper,
+/turf/floor/hull,
+/area/space)
"tZw" = (
/obj/structure/cable/green{
d1 = 4;
@@ -205277,7 +205292,7 @@ iEk
cBO
cwU
abF
-abF
+qmi
abF
cwU
cwU
@@ -205479,7 +205494,7 @@ cBO
cos
cwU
abF
-abF
+tZv
abF
abF
cwU
diff --git a/nano/templates/crew_records.tmpl b/nano/templates/crew_records.tmpl
index 543879ebe0d..009496403e1 100644
--- a/nano/templates/crew_records.tmpl
+++ b/nano/templates/crew_records.tmpl
@@ -28,6 +28,27 @@
{{if value.needs_big_box}}
{{:value.value}}
+ {{else}}
+ {{if value.list_value}}
+ {{for value.list_value}}
+ {{:value}}
+ {{/for}}
+ {{else}}
+ {{if value.list_clumps}}
+ {{for value.list_clumps}}
+ {{for value}}
+ {{:value}}
+ {{/for}}
+ {{/for}}
+ {{else}}
+ {{if value.links}}
+ {{for 1 to value.links.len}}
+ {{for value.links}}
+
+ {{/if}}
+ {{/if}}
+ {{/if}}
+ {{/if}}
{{else}}
{{:value.value}}
diff --git a/nano/templates/pai_medrecords.tmpl b/nano/templates/pai_medrecords.tmpl
index 37b1d7061ca..b45d66cd2c9 100644
--- a/nano/templates/pai_medrecords.tmpl
+++ b/nano/templates/pai_medrecords.tmpl
@@ -15,10 +15,6 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Name
{{:data.general.name}}
-
-
Record ID
-
{{:data.general.id}}
-
Sex
{{:data.general.sex}}
@@ -32,50 +28,52 @@ code/modules/mob/living/silicon/pai/software_modules.dm
{{:data.general.age}}
-
Rank
-
{{:data.general.rank}}
+
Job Title
+
{{:data.general.job}}
Fingerprint
{{:data.general.fingerprint}}
-
Physical Status
-
{{:data.general.p_stat}}
+
=Status
+
{{:data.general.status}}
-
Mental Status
-
{{:data.general.m_stat}}
+
Blood Type
+
{{:data.general.bloodtype}}
{{/if}}
{{if data.medical}}
-
Blood Type
-
{{:data.medical.b_type}}
-
-
-
Minor Disabilities
-
{{:data.medical.mi_dis}}
-
{{:data.medical.mi_dis_d}}
+
Prosthetics
+ {{for data.medical.value.prosthetics}}
+
{{:value}}
+ {{/for}}
-
Major Disabilities
-
{{:data.medical.ma_dis}}
-
{{:data.medical.ma_dis_d}}
+
Wounds
+ {{for data.medical.value.wounds}}
+
{{:value}}
+ {{/for}}
-
Allergies
-
{{:data.medical.alg}}
-
{{:data.medical.alg_d}}
+
Body State
+ {{for data.medical.value.body state}}
+
{{:value}}
+ {{/for}}
-
Current Diseases
-
{{:data.medical.cdi}}
-
{{:data.medical.cdi_d}}
+
Chemical History
+ {{for data.medical.value.chemhistory}}
+
{{:value}}
+ {{/for}}
-
Important Notes
-
{{:data.medical.notes}}
+
Psychological Profile
+ {{for data.medical.value.psychological}}
+
{{:value}}
+ {{/for}}
{{/if}}
diff --git a/nano/templates/pai_secrecords.tmpl b/nano/templates/pai_secrecords.tmpl
index e139034c0de..cdb3321a07c 100644
--- a/nano/templates/pai_secrecords.tmpl
+++ b/nano/templates/pai_secrecords.tmpl
@@ -15,10 +15,6 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Name
{{:data.general.name}}
-
-
Record ID
-
{{:data.general.id}}
-
Sex
{{:data.general.sex}}
@@ -32,40 +28,24 @@ code/modules/mob/living/silicon/pai/software_modules.dm
{{:data.general.age}}
-
Rank
-
{{:data.general.rank}}
+
Job Title
+
{{:data.general.job}}
Fingerprint
{{:data.general.fingerprint}}
-
Physical Status
-
{{:data.general.p_stat}}
+
Status
+
{{:data.general.status}}
-
-
Mental Status
-
{{:data.general.m_stat}}
-
-{{/if}}
-{{if data.security}}
Criminal Status
-
{{:data.security.criminal}}
-
-
-
Minor Crimes
-
{{:data.security.mi_crim}}
-
{{:data.security.mi_crim_d}}
-
-
-
Major Crimes
-
{{:data.security.ma_crim}}
-
{{:data.security.ma_crim_d}}
-
+ {{:data.general.criminalStatus }}
+
Important Notes
-
{{:data.security.notes}}
+
{{:data.general.secNotes}}
{{/if}}
diff --git a/tgui/packages/tgui/interfaces/Computer.tsx b/tgui/packages/tgui/interfaces/Computer.tsx
new file mode 100644
index 00000000000..cd4fa1f534f
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/Computer.tsx
@@ -0,0 +1,169 @@
+import { BooleanLike } from 'common/react';
+import { Button, Box, Table } from '../components';
+import { TableCell, TableRow } from '../components/Table';
+import { sendAct } from '../backend';
+
+export interface ComputerInterface {
+ PC_batteryicon: string;
+ PC_batterypercent: string;
+ PC_showbatteryicon: BooleanLike;
+ PC_light_name: string;
+ PC_light_on: BooleanLike;
+ PC_apclinkicon: string;
+ PC_ntneticon: string;
+ has_gps: BooleanLike;
+ gps_icon: string;
+ gps_data: string;
+ PC_programheaders: Programheader[];
+ PC_stationtime: string;
+ PC_hasheader: BooleanLike;
+ PC_showexitprogram: BooleanLike;
+ mapZLevels: number[];
+ mapZLevel: number;
+}
+
+type Programheader = {
+ icon: string;
+};
+
+export const ProgramShell = (props, context) => {
+ const {
+ PC_batteryicon,
+ PC_batterypercent,
+ PC_showbatteryicon,
+ PC_light_name,
+ PC_light_on,
+ PC_apclinkicon,
+ PC_ntneticon,
+ has_gps,
+ gps_icon,
+ gps_data,
+ PC_programheaders,
+ PC_stationtime,
+ PC_hasheader,
+ PC_showexitprogram,
+ mapZLevels,
+ mapZLevel,
+ } = props;
+ const act = sendAct;
+ return (
+ <>
+
+
+
+
+ {PC_showexitprogram && (
+
+
+
+
+ act('PC_exit')}
+ />
+
+
+ act('PC_minimize')}
+ />
+
+
+
+
+ )}
+ {PC_showexitprogram || }
+
+
+ Initiating...
+
+ >
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/CrewRecords.tsx b/tgui/packages/tgui/interfaces/CrewRecords.tsx
new file mode 100644
index 00000000000..3cb3f0bc944
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/CrewRecords.tsx
@@ -0,0 +1,332 @@
+import { BooleanLike } from 'common/react';
+import { useBackend, sendAct } from '../backend';
+import { Button, Box, Divider, Table } from '../components';
+import { GameIcon } from '../components/GameIcon';
+import { Window } from '../layouts';
+import { ComputerInterface, ProgramShell } from './Computer';
+import { classes } from 'common/react';
+
+interface CrewRecordsInterface extends RecordConcrete, ComputerInterface {
+ message: string;
+ front_pic: string;
+ side_pic: string;
+ pic_edit: BooleanLike;
+ all_records: RecordAbstract[];
+ creation: BooleanLike;
+ dnasearch: BooleanLike;
+ fingersearch: BooleanLike;
+}
+
+interface RecordConcrete {
+ name: string;
+ uid: number;
+ creator: string;
+ filetime: string;
+ fields: RecordField[];
+ access: BooleanLike;
+ access_edit: BooleanLike;
+}
+type RecordField = {
+ access: BooleanLike;
+ access_edit: BooleanLike;
+ name: string;
+ value: string | number | object;
+ list_value: any[];
+ list_clumps: object[];
+ can_edit: BooleanLike;
+ needs_big_box: BooleanLike;
+ ignore_value: BooleanLike;
+ ID: number;
+};
+
+type RecordAbstract = {
+ name: string;
+ rank: string;
+ id: number;
+};
+
+export const CrewRecords = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ message,
+ uid,
+ fields,
+ front_pic,
+ side_pic,
+ pic_edit,
+ all_records,
+ creation,
+ dnasearch,
+ fingersearch,
+ } = data;
+ return (
+
+
+ {ProgramShell(props, context)}
+ {message && act('clear_message')} />}
+ {message}
+
+ {uid &&
+ currentrecord(
+ { uid, fields, front_pic, side_pic, pic_edit },
+ context,
+ )}
+ {Boolean(uid) || (
+ <>
+ {Boolean(creation) && (
+ <>
+
+ act('new_record')}
+ />
+ >
+ )}
+ <>
+
+ act('search', { search: 'Name' })}
+ />
+ >
+ {Boolean(dnasearch) && (
+ <>
+
+ act('search', { search: 'DNA' })}
+ />
+ >
+ )}
+ {Boolean(fingersearch) && (
+ <>
+
+ act('search', { search: 'Fingerprint' })}
+ />
+ >
+ )}
+
+
+ Available records:
+
+
+
+ NamePosition
+
+
+ {all_records.map((mapped) => {
+ return (
+ <>
+
+
+
+ act('set_active', { set_active: mapped.id })
+ }
+ />
+
+
+ {mapped.rank}
+ >
+ );
+ })}
+
+ >
+ )}
+
+
+ );
+};
+
+const currentrecord = (props, context) => {
+ const act = sendAct;
+ const { uid, fields, front_pic, side_pic, pic_edit } = props;
+ return (
+ <>
+ act('clear_active')} />
+ act('print_active')} />
+
+
+ GENERIC INFORMATION
+
+
+
+
+
+
+ {Boolean(pic_edit) && (
+
+
+
+ act('edit_photo_front')}
+ />
+
+ act('edit_photo_side')} />
+
+ )}
+ {fields &&
+ fields.map((mapped) => {
+ return displayfield(mapped, context);
+ })}
+ >
+ );
+};
+const displayfield = (props, context) => {
+ const act = sendAct;
+ const {
+ access,
+ access_edit,
+ name,
+ value,
+ list_value,
+ list_clumps,
+ can_edit,
+ needs_big_box,
+ ignore_value,
+ ID,
+ } = props;
+ return (
+ <>
+ {access && access_edit && (
+
+
+ act('edit_field', { edit_field: ID })}
+ />
+
+ )}
+ {access && (Boolean(access_edit) || name)}
+ {access && (
+
+ {value}
+ {list_value &&
+ (Object.values(list_value).length
+ ? list_value.join(', ')
+ : 'Unset')}
+ {list_clumps &&
+ (Object.keys(list_clumps)
+ ? Object.keys(list_clumps).map((mapped, count) => {
+ return (
+ <>
+ {mapped}
+ {': '}
+ {returnlist(
+ { origin: list_clumps, whichlist: count },
+ context,
+ )}
+
+ >
+ );
+ })
+ : 'Unset')}
+
+ )}
+ >
+ );
+};
+
+const returnlist = (props, context) => {
+ const { origin, whichlist } = props;
+ let toreturn: any;
+ if (
+ Object.values(origin) &&
+ typeof Object.values(origin)[whichlist] !== 'undefined' &&
+ Array.isArray(Object.values(origin)[whichlist])
+ ) {
+ let unfoldthis1: any = Object.values(origin)[whichlist];
+ let unfoldthis2: any[] = unfoldthis1;
+ toreturn = unfoldthis2.toString();
+ } else toreturn = 'Sadness';
+ return toreturn;
+};
+
+/**/
+/*
+{{if data.message}}
+{{:helper.link('X', null, {'clear_message' : 1})}}{{:data.message}}
+{{/if}}
+{{if data.uid}}
+{{:helper.link('BACK', '', {'clear_active' : 1})}}{{:helper.link('PRINT', '', {'print_active' : 1})}}
+
+
+
GENERIC INFORMATION
+
+
+
+
+
+ {{if data.pic_edit}}
+
+
 
+
{{:helper.link('Edit Front', 'pencil', {'edit_photo_front' : 1}, null)}}{{:helper.link('Edit Side', 'pencil', {'edit_photo_side' : 1}, null)}}
+
+ {{/if}}
+ {{for data.fields}}
+ {{if value.access}}
+
+ {{if value.access_edit}}
+
{{:helper.link(value.name, 'pencil', {'edit_field' : value.ID}, null)}}
+ {{else}}
+
{{:value.name}}:
+ {{/if}}
+ {{if value.needs_big_box}}
+
+ {{if value.value}}
+ {{:value.value}}
+ {{else}}
+ {{if value.list_value}}
+ {{for value.list_value}}
+ {{:value}}
+ {{/for}}
+ {{else}}
+ {{if value.list_clumps}}
+ {{for value.list_clumps}}
+ {{for value}}
+ {{:value}}
+ {{/for}}
+ {{/for}}
+ {{else}}
+ {{if value.links}}
+ {{for 1 to value.links.len}}
+ {{for value.links}}
+
+ {{/if}}
+ {{/if}}
+ {{/if}}
+ {{/if}}
+
+ {{else}}
+
{{:value.value}}
+ {{/if}}
+
+ {{/if}}
+ {{/for}}
+
+{{else}}
+{{if data.creation}}
+ {{:helper.link('New Record', 'document', {'new_record' : 1}, null)}}
+{{/if}}
+{{:helper.link('Name Search', 'search', {'search' : 'Name'}, null)}}
+{{if data.dnasearch}}
+ {{:helper.link('DNA Search', 'search', {'search' : 'DNA'}, null)}}
+{{/if}}
+{{if data.fingersearch}}
+ {{:helper.link('Fingerprint Search', 'search', {'search' : 'Fingerprint'}, null)}}
+{{/if}}
+
+Available records:
+
+Name Position
+{{for data.all_records}}
+ {{:helper.link(value.name, '', {'set_active' : value.id})}}
+ {{:value.rank}}
+{{/for}}
+
+{{/if}}
+*/
From df57314abb5f0186befb5173dc0da41fc6a3614a Mon Sep 17 00:00:00 2001
From: Flleeppyy
Date: Tue, 9 Sep 2025 19:14:05 -0700
Subject: [PATCH 2/3] make it compatible with our tgui :)
---
tgui/packages/tgui/interfaces/Computer.tsx | 102 +++++++++---------
tgui/packages/tgui/interfaces/CrewRecords.tsx | 50 +++++----
2 files changed, 84 insertions(+), 68 deletions(-)
diff --git a/tgui/packages/tgui/interfaces/Computer.tsx b/tgui/packages/tgui/interfaces/Computer.tsx
index cd4fa1f534f..9da923a2ae7 100644
--- a/tgui/packages/tgui/interfaces/Computer.tsx
+++ b/tgui/packages/tgui/interfaces/Computer.tsx
@@ -1,6 +1,6 @@
-import { BooleanLike } from 'common/react';
-import { Button, Box, Table } from '../components';
-import { TableCell, TableRow } from '../components/Table';
+import { Box, Button, Table } from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
import { sendAct } from '../backend';
export interface ComputerInterface {
@@ -26,7 +26,7 @@ type Programheader = {
icon: string;
};
-export const ProgramShell = (props, context) => {
+export const ProgramShell = (props: ComputerInterface) => {
const {
PC_batteryicon,
PC_batterypercent,
@@ -48,56 +48,58 @@ export const ProgramShell = (props, context) => {
const act = sendAct;
return (
<>
-