diff --git a/_maps/RandomRuins/JungleRuins/jungle_interceptor.dmm b/_maps/RandomRuins/JungleRuins/jungle_interceptor.dmm
index 057b0cbdbe8f..fafbd48050f4 100644
--- a/_maps/RandomRuins/JungleRuins/jungle_interceptor.dmm
+++ b/_maps/RandomRuins/JungleRuins/jungle_interceptor.dmm
@@ -3395,7 +3395,7 @@
/turf/open/floor/plating/rust,
/area/ruin/jungle/interceptor/starlauncherone)
"CU" = (
-/obj/machinery/computer/secure_data,
+/obj/machinery/computer/records/sec,
/obj/structure/cable/orange{
icon_state = "2-8"
},
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_abandonedlisteningpost.dmm b/_maps/RandomRuins/LavaRuins/lavaland_abandonedlisteningpost.dmm
index 444f4ec52509..fb7822c1a57f 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_abandonedlisteningpost.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_abandonedlisteningpost.dmm
@@ -1029,7 +1029,7 @@
/area/ruin/unpowered/listening_post/commons)
"rb" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop,
+/obj/machinery/computer/records/sec/laptop,
/obj/effect/turf_decal/siding/thinplating/dark{
dir = 4
},
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_wrecked_factory.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_wrecked_factory.dmm
index 2c84843cf776..0959a665bf13 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_wrecked_factory.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_wrecked_factory.dmm
@@ -2920,7 +2920,7 @@
/area/overmap_encounter/planetoid/lava/explored)
"By" = (
/obj/structure/table/wood,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4;
pixel_x = -5;
pixel_y = 5
@@ -4953,7 +4953,7 @@
/turf/open/floor/plating/grass/lava/orange,
/area/overmap_encounter/planetoid/lava/explored)
"Xp" = (
-/obj/machinery/computer/secure_data,
+/obj/machinery/computer/records/sec,
/turf/open/floor/carpet/nanoweave/red,
/area/ruin/lavaland/factory/adminstrative)
"Xv" = (
diff --git a/_maps/RandomRuins/RockRuins/rockplanet_budgetcuts.dmm b/_maps/RandomRuins/RockRuins/rockplanet_budgetcuts.dmm
index b837eff979f7..6a5960bde27b 100644
--- a/_maps/RandomRuins/RockRuins/rockplanet_budgetcuts.dmm
+++ b/_maps/RandomRuins/RockRuins/rockplanet_budgetcuts.dmm
@@ -64,7 +64,7 @@
/area/overmap_encounter/planetoid/rockplanet/explored)
"bc" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 4;
pixel_x = -7;
pixel_y = 6
@@ -1329,7 +1329,7 @@
/obj/machinery/status_display/evac{
pixel_y = 32
},
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
pixel_x = 5;
pixel_y = 4
},
@@ -2395,11 +2395,11 @@
/area/ruin/rockplanet/nanotrasen)
"Po" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
pixel_x = -5;
pixel_y = 3
},
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
pixel_x = 16;
pixel_y = 3
},
diff --git a/_maps/RandomRuins/RockRuins/rockplanet_harmfactory.dmm b/_maps/RandomRuins/RockRuins/rockplanet_harmfactory.dmm
index a86efe2e9744..284ffa7f47ac 100644
--- a/_maps/RandomRuins/RockRuins/rockplanet_harmfactory.dmm
+++ b/_maps/RandomRuins/RockRuins/rockplanet_harmfactory.dmm
@@ -111,7 +111,7 @@
/area/ruin/powered)
"cy" = (
/obj/structure/table/wood/reinforced,
-/obj/machinery/computer/secure_data/laptop,
+/obj/machinery/computer/records/sec/laptop,
/turf/open/floor/plating/rust,
/area/ruin/powered)
"cQ" = (
@@ -121,7 +121,7 @@
/area/ruin/powered)
"dr" = (
/obj/structure/table/wood/reinforced,
-/obj/machinery/computer/med_data/laptop,
+/obj/machinery/computer/records/med/laptop,
/obj/effect/decal/cleanable/dirt/dust,
/obj/item/newspaper{
pixel_x = 8;
@@ -271,7 +271,7 @@
/turf/open/floor/plating/rust,
/area/ruin/powered)
"gx" = (
-/obj/structure/filingcabinet/employment,
+/obj/structure/filingcabinet/record/gen,
/obj/structure/safe/floor,
/obj/item/keycard/harmfactory/office,
/turf/open/floor/plating/rust,
diff --git a/_maps/RandomRuins/RockRuins/rockplanet_nomadcrash.dmm b/_maps/RandomRuins/RockRuins/rockplanet_nomadcrash.dmm
index ff58248ffc4e..4d75b0dd1ec5 100644
--- a/_maps/RandomRuins/RockRuins/rockplanet_nomadcrash.dmm
+++ b/_maps/RandomRuins/RockRuins/rockplanet_nomadcrash.dmm
@@ -1495,7 +1495,7 @@
dir = 4
},
/obj/structure/table,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_x = 2;
pixel_y = 6
diff --git a/_maps/RandomRuins/RockRuins/rockplanet_shippingdock.dmm b/_maps/RandomRuins/RockRuins/rockplanet_shippingdock.dmm
index 342b1422b80f..663fc8752c65 100644
--- a/_maps/RandomRuins/RockRuins/rockplanet_shippingdock.dmm
+++ b/_maps/RandomRuins/RockRuins/rockplanet_shippingdock.dmm
@@ -896,7 +896,7 @@
/area/ruin/rockplanet/shippingdocksecure)
"il" = (
/obj/structure/table,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_x = 1
},
diff --git a/_maps/RandomRuins/SpaceRuins/power_puzzle.dmm b/_maps/RandomRuins/SpaceRuins/power_puzzle.dmm
index 3d05cfb13d35..15e9c3c21bc0 100644
--- a/_maps/RandomRuins/SpaceRuins/power_puzzle.dmm
+++ b/_maps/RandomRuins/SpaceRuins/power_puzzle.dmm
@@ -3178,7 +3178,7 @@
dir = 4
},
/obj/effect/decal/cleanable/dirt/dust,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 1;
pixel_y = 5
},
diff --git a/_maps/RandomRuins/SpaceRuins/spacemall.dmm b/_maps/RandomRuins/SpaceRuins/spacemall.dmm
index eb48bcae1626..c96d92cc893c 100644
--- a/_maps/RandomRuins/SpaceRuins/spacemall.dmm
+++ b/_maps/RandomRuins/SpaceRuins/spacemall.dmm
@@ -1360,7 +1360,7 @@
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/spacemall)
"fa" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 1
},
/obj/effect/turf_decal/corner/opaque/red/mono,
@@ -8454,7 +8454,7 @@
/turf/open/floor/wood,
/area/ruin/space/has_grav/spacemall/maint)
"FC" = (
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 1
},
/obj/structure/table/reinforced,
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index 13e075e9884d..46390bd00b3c 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -3781,7 +3781,7 @@
/turf/open/floor/mineral/titanium/blue,
/area/centcom/evac)
"aLj" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 4
},
/turf/open/floor/mineral/plastitanium/red,
@@ -6479,7 +6479,7 @@
/turf/open/floor/plasteel,
/area/centcom/control)
"bIA" = (
-/obj/machinery/computer/secure_data,
+/obj/machinery/computer/records/sec,
/obj/effect/turf_decal/industrial/warning,
/turf/open/floor/plasteel,
/area/centcom/control)
@@ -7010,7 +7010,7 @@
/turf/open/floor/plasteel,
/area/centcom/control)
"cRF" = (
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 4
},
/obj/effect/turf_decal/corner/transparent/neutral{
@@ -7040,7 +7040,7 @@
/obj/structure/sign/poster/contraband/syndicate_recruitment{
pixel_x = -32
},
-/obj/machinery/computer/secure_data/syndie{
+/obj/machinery/computer/records/sec/syndie{
dir = 4
},
/turf/open/floor/mineral/plastitanium,
@@ -7217,7 +7217,7 @@
/turf/open/floor/plasteel,
/area/tdome/tdomeobserve)
"dsk" = (
-/obj/structure/filingcabinet/security,
+/obj/structure/filingcabinet/record/security,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
@@ -7341,7 +7341,7 @@
/turf/open/floor/plasteel,
/area/centcom)
"dGq" = (
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 8
},
/obj/effect/turf_decal/corner/opaque/blue{
@@ -8170,7 +8170,7 @@
/turf/open/floor/plasteel/dark,
/area/centcom/ferry)
"fdr" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
@@ -8901,7 +8901,7 @@
/turf/open/floor/plasteel,
/area/centcom/supply)
"gLL" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 8
},
/obj/machinery/button/door/indestructible{
@@ -9779,7 +9779,7 @@
/turf/open/floor/mineral/plastitanium,
/area/centcom)
"izl" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 1
},
/obj/machinery/light/directional/south,
@@ -9972,7 +9972,7 @@
/obj/machinery/newscaster/directional/north{
pixel_y = -30
},
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 1
},
/obj/effect/turf_decal/corner/transparent/neutral{
@@ -10065,7 +10065,7 @@
/turf/open/floor/plasteel,
/area/centcom/supplypod/loading/ert)
"jly" = (
-/obj/machinery/computer/med_data/syndie{
+/obj/machinery/computer/records/med/syndie{
dir = 1
},
/turf/open/floor/mineral/plastitanium/red,
@@ -10172,7 +10172,7 @@
/turf/open/floor/plasteel/dark,
/area/tdome/tdomeobserve)
"jvG" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 1
},
/obj/effect/turf_decal/industrial/warning{
@@ -10958,7 +10958,7 @@
/turf/open/floor/plasteel,
/area/centcom/control)
"lhE" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 4
},
/obj/effect/turf_decal/corner/transparent/neutral{
@@ -11612,7 +11612,7 @@
/area/ctf)
"moE" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4;
pixel_y = 6;
pixel_x = -4
@@ -12436,7 +12436,7 @@
/obj/effect/turf_decal/corner/opaque/brown{
dir = 8
},
-/obj/machinery/computer/secure_data,
+/obj/machinery/computer/records/sec,
/obj/machinery/light/directional/north,
/turf/open/floor/plasteel,
/area/centcom)
@@ -12663,7 +12663,7 @@
/area/centcom/ferry)
"owZ" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/med_data/laptop,
+/obj/machinery/computer/records/med/laptop,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
@@ -13681,7 +13681,7 @@
/turf/open/floor/plasteel,
/area/centcom/supply)
"qxD" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/machinery/light/directional/north,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
@@ -14574,7 +14574,7 @@
/turf/open/floor/plasteel/dark,
/area/tdome/tdomeobserve)
"sho" = (
-/obj/structure/filingcabinet/security,
+/obj/structure/filingcabinet/record/security,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
@@ -15156,7 +15156,7 @@
/turf/open/floor/plasteel/dark,
/area/ctf)
"tyD" = (
-/obj/structure/filingcabinet/security,
+/obj/structure/filingcabinet/record/security,
/obj/effect/turf_decal/industrial/warning{
dir = 9
},
@@ -15195,7 +15195,7 @@
/turf/open/floor/plasteel/patterned/grid,
/area/centcom)
"tAB" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
@@ -16008,7 +16008,7 @@
/turf/open/floor/plasteel/dark,
/area/ctf)
"vyk" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 1
},
/obj/effect/turf_decal/corner/transparent/neutral{
@@ -16033,7 +16033,7 @@
/turf/open/floor/plasteel,
/area/centcom/control)
"vAM" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 8
},
/obj/effect/turf_decal/corner/transparent/neutral{
@@ -16438,7 +16438,7 @@
/turf/open/floor/plasteel,
/area/centcom/control)
"wER" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
@@ -16724,7 +16724,7 @@
/turf/open/floor/plasteel,
/area/centcom/evac)
"xEN" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/effect/turf_decal/industrial/warning{
dir = 5
},
@@ -16802,7 +16802,7 @@
/area/centcom/supply)
"xSR" = (
/obj/structure/table/wood,
-/obj/machinery/computer/med_data/laptop,
+/obj/machinery/computer/records/med/laptop,
/obj/effect/turf_decal/corner/transparent/neutral{
dir = 1
},
diff --git a/_maps/outpost/hangar/nt_ice_40x40.dmm b/_maps/outpost/hangar/nt_ice_40x40.dmm
index 69d81767fd7f..13a233acfcb7 100644
--- a/_maps/outpost/hangar/nt_ice_40x40.dmm
+++ b/_maps/outpost/hangar/nt_ice_40x40.dmm
@@ -1555,7 +1555,7 @@
},
/area/hangar)
"Ps" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
icon_state = "computer-left";
dir = 4;
pixel_x = -7
diff --git a/_maps/outpost/hangar/nt_ice_56x40.dmm b/_maps/outpost/hangar/nt_ice_56x40.dmm
index b89f435a4a8c..615c8f8fcb64 100644
--- a/_maps/outpost/hangar/nt_ice_56x40.dmm
+++ b/_maps/outpost/hangar/nt_ice_56x40.dmm
@@ -1462,7 +1462,7 @@
},
/area/hangar)
"Mt" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
icon_state = "computer-left";
dir = 4;
pixel_x = -7
diff --git a/_maps/outpost/nanotrasen_asteroid.dmm b/_maps/outpost/nanotrasen_asteroid.dmm
index 08f1322e7c60..164e7f8a2df2 100644
--- a/_maps/outpost/nanotrasen_asteroid.dmm
+++ b/_maps/outpost/nanotrasen_asteroid.dmm
@@ -282,10 +282,10 @@
/area/outpost/hallway/central)
"bn" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
pixel_x = -3
},
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
pixel_x = 14
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
@@ -931,7 +931,7 @@
/area/outpost/crew/garden)
"dD" = (
/obj/structure/table/glass,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
pixel_x = 4;
pixel_y = 4
},
@@ -2890,7 +2890,7 @@
/turf/open/floor/plasteel/rockvault,
/area/outpost/operations)
"kN" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 8
},
/obj/structure/railing{
@@ -4323,7 +4323,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/machinery/computer/med_data,
+/obj/machinery/computer/records/med,
/turf/open/floor/plasteel/dark,
/area/outpost/crew/cryo)
"qb" = (
@@ -4931,7 +4931,7 @@
/turf/open/floor/plasteel/dark,
/area/outpost/cargo)
"rO" = (
-/obj/structure/filingcabinet/security{
+/obj/structure/filingcabinet/record/security{
pixel_x = 11
},
/obj/machinery/newscaster/directional/east,
@@ -7522,7 +7522,7 @@
/turf/open/floor/plating/rust,
/area/outpost/maintenance/aft)
"As" = (
-/obj/machinery/computer/med_data,
+/obj/machinery/computer/records/med,
/obj/effect/turf_decal/trimline/opaque/green/filled/line,
/obj/effect/turf_decal/techfloor{
dir = 1
@@ -8129,7 +8129,7 @@
/area/outpost/operations)
"CA" = (
/obj/structure/table/wood,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 8
},
/turf/open/floor/plasteel,
@@ -8364,7 +8364,7 @@
/turf/open/floor/plating,
/area/outpost/maintenance/aft)
"Du" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 8
},
/obj/effect/turf_decal/techfloor{
@@ -8484,7 +8484,7 @@
/area/outpost/hallway/central)
"DV" = (
/obj/structure/table/wood,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 4;
pixel_x = -1;
pixel_y = 3
@@ -9822,7 +9822,7 @@
/area/outpost/hallway/central)
"Iy" = (
/obj/structure/window/reinforced/spawner/west,
-/obj/machinery/computer/med_data,
+/obj/machinery/computer/records/med,
/turf/open/floor/plasteel/dark,
/area/outpost/crew/cryo)
"Iz" = (
@@ -10986,7 +10986,7 @@
/turf/open/floor/plasteel/patterned/grid,
/area/outpost/hallway/fore)
"MC" = (
-/obj/structure/filingcabinet/employment{
+/obj/structure/filingcabinet/record/gen{
pixel_x = -11
},
/turf/open/floor/plasteel/dark,
@@ -14142,7 +14142,7 @@
/turf/open/floor/grass,
/area/outpost/crew/garden)
"XI" = (
-/obj/machinery/computer/secure_data,
+/obj/machinery/computer/records/sec,
/obj/effect/turf_decal/trimline/opaque/red/filled/line,
/obj/effect/turf_decal/techfloor{
dir = 1
diff --git a/_maps/outpost/nanotrasen_ice.dmm b/_maps/outpost/nanotrasen_ice.dmm
index 70fb809c4c95..5101716991f1 100644
--- a/_maps/outpost/nanotrasen_ice.dmm
+++ b/_maps/outpost/nanotrasen_ice.dmm
@@ -2021,7 +2021,7 @@
/area/outpost/exterior)
"nU" = (
/obj/effect/decal/cleanable/dirt/dust,
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
icon_state = "computer-left"
},
/turf/open/floor/plasteel/telecomms_floor,
@@ -5740,7 +5740,7 @@
/turf/closed/indestructible/reinforced,
/area/outpost/exterior)
"Nl" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
icon_state = "computer-left"
},
/turf/open/floor/plasteel/telecomms_floor,
diff --git a/_maps/shuttles/independent/independent_beluga.dmm b/_maps/shuttles/independent/independent_beluga.dmm
index c8ef49a3b35e..6aac1547358a 100644
--- a/_maps/shuttles/independent/independent_beluga.dmm
+++ b/_maps/shuttles/independent/independent_beluga.dmm
@@ -467,7 +467,7 @@
/obj/effect/turf_decal/borderfloorblack{
dir = 8
},
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 4
},
/obj/structure/railing{
@@ -1132,7 +1132,7 @@
/obj/structure/table/reinforced{
color = "#c1b6a5"
},
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_x = 5;
pixel_y = 2
@@ -4586,7 +4586,7 @@
/area/ship/engineering)
"SW" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4;
pixel_x = -7;
pixel_y = 5
diff --git a/_maps/shuttles/independent/independent_box.dmm b/_maps/shuttles/independent/independent_box.dmm
index 31891a371d8c..1a05296ec8b6 100644
--- a/_maps/shuttles/independent/independent_box.dmm
+++ b/_maps/shuttles/independent/independent_box.dmm
@@ -2494,7 +2494,7 @@
/area/ship/engineering)
"LG" = (
/obj/structure/table/glass,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
density = 0;
pixel_x = 3
},
@@ -2638,7 +2638,7 @@
/turf/open/floor/plating,
/area/ship/crew)
"RR" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/item/radio/intercom/directional/west,
/turf/open/floor/plasteel/dark,
/area/ship/crew)
diff --git a/_maps/shuttles/independent/independent_lagoon.dmm b/_maps/shuttles/independent/independent_lagoon.dmm
index 248ee9240efd..7f899020d513 100644
--- a/_maps/shuttles/independent/independent_lagoon.dmm
+++ b/_maps/shuttles/independent/independent_lagoon.dmm
@@ -724,7 +724,7 @@
/area/ship/crew/library)
"eR" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_x = 3;
pixel_y = 5
@@ -1671,7 +1671,7 @@
/area/ship/crew/chapel)
"kX" = (
/obj/structure/table/glass,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 1
},
/obj/machinery/light/directional/south,
diff --git a/_maps/shuttles/independent/independent_rigger.dmm b/_maps/shuttles/independent/independent_rigger.dmm
index 15265d30016b..ad70de20744c 100644
--- a/_maps/shuttles/independent/independent_rigger.dmm
+++ b/_maps/shuttles/independent/independent_rigger.dmm
@@ -378,7 +378,7 @@
/obj/machinery/light/small/directional/south,
/obj/effect/turf_decal/borderfloor,
/obj/structure/table/glass,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 1
},
/obj/effect/turf_decal/corner/opaque/green{
@@ -1390,7 +1390,7 @@
/turf/open/floor/plating,
/area/ship/engineering/engine)
"rH" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/machinery/airalarm/directional/south,
/obj/effect/turf_decal/borderfloor{
dir = 6
@@ -2538,7 +2538,7 @@
"EB" = (
/obj/item/radio/intercom/directional/south,
/obj/structure/table/wood,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 1
},
/obj/item/lighter/greyscale{
@@ -4036,7 +4036,7 @@
/turf/open/floor/plating,
/area/ship/engineering/atmospherics)
"Vq" = (
-/obj/structure/filingcabinet/security,
+/obj/structure/filingcabinet/record/security,
/obj/machinery/newscaster/security_unit/directional/south,
/turf/open/floor/plasteel/grimy,
/area/ship/security)
diff --git a/_maps/shuttles/independent/independent_schmiedeberg.dmm b/_maps/shuttles/independent/independent_schmiedeberg.dmm
index ce7b407a4731..2dc1768d2575 100644
--- a/_maps/shuttles/independent/independent_schmiedeberg.dmm
+++ b/_maps/shuttles/independent/independent_schmiedeberg.dmm
@@ -1811,7 +1811,7 @@
/area/ship/security)
"zW" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 8
},
/obj/machinery/door/window/brigdoor{
diff --git a/_maps/shuttles/independent/independent_shetland.dmm b/_maps/shuttles/independent/independent_shetland.dmm
index 0481bd2506fa..32a4fab17b31 100644
--- a/_maps/shuttles/independent/independent_shetland.dmm
+++ b/_maps/shuttles/independent/independent_shetland.dmm
@@ -1662,7 +1662,7 @@
/area/ship/hallway/central)
"oG" = (
/obj/structure/table,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
density = 0
},
/obj/effect/turf_decal/corner/opaque/black{
@@ -1800,7 +1800,7 @@
/area/ship/crew/cryo)
"pR" = (
/obj/structure/table/glass,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 8
},
/obj/effect/turf_decal/corner/opaque/bottlegreen/full,
diff --git a/_maps/shuttles/independent/independent_tranquility.dmm b/_maps/shuttles/independent/independent_tranquility.dmm
index 641a74a202ef..3bdfbebf931d 100644
--- a/_maps/shuttles/independent/independent_tranquility.dmm
+++ b/_maps/shuttles/independent/independent_tranquility.dmm
@@ -645,7 +645,7 @@
/area/ship/external)
"fk" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/med_data/laptop,
+/obj/machinery/computer/records/med/laptop,
/obj/effect/turf_decal/techfloor{
dir = 5
},
@@ -2016,7 +2016,7 @@
/area/ship/external)
"qe" = (
/obj/structure/table,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8
},
/obj/effect/turf_decal/borderfloorblack/cee{
@@ -4266,7 +4266,7 @@
/area/ship/crew/crewfive)
"Io" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4
},
/obj/effect/turf_decal/techfloor{
diff --git a/_maps/shuttles/inteq/inteq_colossus.dmm b/_maps/shuttles/inteq/inteq_colossus.dmm
index 920d16cfc1c7..46bf2c56f6dd 100644
--- a/_maps/shuttles/inteq/inteq_colossus.dmm
+++ b/_maps/shuttles/inteq/inteq_colossus.dmm
@@ -706,7 +706,7 @@
/area/ship/hallway/fore)
"hv" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4
},
/obj/effect/turf_decal/corner/opaque/yellow{
@@ -1758,7 +1758,7 @@
/area/ship/cargo)
"tx" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4
},
/turf/open/floor/plasteel/dark,
diff --git a/_maps/shuttles/inteq/inteq_talos.dmm b/_maps/shuttles/inteq/inteq_talos.dmm
index 1babd6a9b001..af8a6ed60afe 100644
--- a/_maps/shuttles/inteq/inteq_talos.dmm
+++ b/_maps/shuttles/inteq/inteq_talos.dmm
@@ -3987,7 +3987,7 @@
/area/ship/storage)
"yx" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop,
+/obj/machinery/computer/records/sec/laptop,
/turf/open/floor/plasteel/dark,
/area/ship/security)
"yz" = (
diff --git a/_maps/shuttles/inteq/inteq_valor.dmm b/_maps/shuttles/inteq/inteq_valor.dmm
index c405c803521a..cec2b29c1059 100644
--- a/_maps/shuttles/inteq/inteq_valor.dmm
+++ b/_maps/shuttles/inteq/inteq_valor.dmm
@@ -1323,7 +1323,7 @@
pixel_x = 13;
pixel_y = 5
},
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 1;
pixel_y = 4
},
@@ -2646,7 +2646,7 @@
/obj/structure/window/reinforced{
dir = 8
},
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 1;
pixel_y = 8
},
@@ -4531,7 +4531,7 @@
pixel_x = 32
},
/obj/structure/table/glass,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 8;
pixel_x = 3;
pixel_y = 7
diff --git a/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm b/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm
index 96bd414525c0..2fc8a3c51bf3 100644
--- a/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm
+++ b/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm
@@ -53,7 +53,7 @@
layer = 4.1
},
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 1;
pixel_y = 4;
pixel_x = 2
@@ -1206,7 +1206,7 @@
/obj/effect/turf_decal/borderfloorblack{
dir = 1
},
-/obj/machinery/computer/secure_data,
+/obj/machinery/computer/records/sec,
/turf/open/floor/plasteel/tech/grid,
/area/ship/bridge)
"eX" = (
@@ -2012,7 +2012,7 @@
/obj/effect/turf_decal/techfloor{
dir = 4
},
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 8
},
/turf/open/floor/plasteel/tech,
@@ -6824,7 +6824,7 @@
/turf/open/floor/plating,
/area/ship/engineering/electrical)
"zf" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 4
},
/obj/structure/extinguisher_cabinet/directional/north,
@@ -8740,7 +8740,7 @@
/obj/structure/table/reinforced{
color = "#c1b6a5"
},
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
pixel_y = 8;
pixel_x = -2
},
@@ -12759,7 +12759,7 @@
/area/ship/crew/office)
"VK" = (
/obj/structure/table,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4;
pixel_x = -8;
pixel_y = 5
@@ -13117,7 +13117,7 @@
/obj/effect/turf_decal/techfloor{
dir = 4
},
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 8
},
/obj/item/radio/intercom/directional/south,
diff --git a/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm b/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm
index 928fc6bd90ee..afef69d50092 100644
--- a/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm
+++ b/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm
@@ -1139,7 +1139,7 @@
/turf/open/floor/plasteel,
/area/ship/security/prison)
"gF" = (
-/obj/structure/filingcabinet/security,
+/obj/structure/filingcabinet/record/security,
/obj/machinery/airalarm/directional/south,
/obj/effect/turf_decal/siding/red,
/turf/open/floor/plasteel/dark,
diff --git a/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm b/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm
index 564cf0733f9f..ef53d495e72a 100644
--- a/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm
+++ b/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm
@@ -5717,7 +5717,7 @@
/turf/open/floor/plasteel,
/area/ship/hallway/central)
"Lc" = (
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 4
},
/turf/open/floor/plasteel/white,
diff --git a/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm b/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm
index 802756c19d04..98db26ec60e2 100644
--- a/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm
+++ b/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm
@@ -453,7 +453,7 @@
/turf/open/floor/plasteel/tech,
/area/ship/engineering/atmospherics)
"dW" = (
-/obj/structure/filingcabinet/employment,
+/obj/structure/filingcabinet/record/gen,
/turf/open/floor/carpet/nanoweave/blue,
/area/ship/crew/office)
"dX" = (
@@ -3030,7 +3030,7 @@
/turf/open/floor/plating,
/area/ship/crew/toilet)
"xA" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 4
},
/obj/machinery/light/small/directional/west,
diff --git a/_maps/shuttles/pgf/pgf_crying_sun.dmm b/_maps/shuttles/pgf/pgf_crying_sun.dmm
index c0584df1e945..7ce458b64d08 100644
--- a/_maps/shuttles/pgf/pgf_crying_sun.dmm
+++ b/_maps/shuttles/pgf/pgf_crying_sun.dmm
@@ -4473,7 +4473,7 @@
/area/ship/hallway/central)
"Jd" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop,
+/obj/machinery/computer/records/sec/laptop,
/obj/effect/turf_decal/spline/fancy/opaque/lime{
dir = 5
},
diff --git a/_maps/shuttles/solgov/solgov_chronicle.dmm b/_maps/shuttles/solgov/solgov_chronicle.dmm
index 19730904ab41..9f8bb1a84d50 100644
--- a/_maps/shuttles/solgov/solgov_chronicle.dmm
+++ b/_maps/shuttles/solgov/solgov_chronicle.dmm
@@ -1136,7 +1136,7 @@
/area/ship/crew/crewtwo)
"kl" = (
/obj/structure/table/wood/fancy/purple,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_x = 4;
pixel_y = 5
diff --git a/_maps/shuttles/solgov/solgov_inkwell.dmm b/_maps/shuttles/solgov/solgov_inkwell.dmm
index d89314c2f769..34c668600a31 100644
--- a/_maps/shuttles/solgov/solgov_inkwell.dmm
+++ b/_maps/shuttles/solgov/solgov_inkwell.dmm
@@ -4526,7 +4526,7 @@
/area/ship/crew/canteen/kitchen)
"CN" = (
/obj/structure/table/wood/fancy/blue,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4
},
/turf/open/floor/wood/walnut,
@@ -5641,7 +5641,7 @@
/turf/open/floor/plasteel/white,
/area/ship/cargo/office)
"Kg" = (
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 4
},
/obj/structure/table/wood/fancy/purple,
diff --git a/_maps/shuttles/solgov/solgov_paracelsus.dmm b/_maps/shuttles/solgov/solgov_paracelsus.dmm
index b235794d6cd4..b8bac029b178 100644
--- a/_maps/shuttles/solgov/solgov_paracelsus.dmm
+++ b/_maps/shuttles/solgov/solgov_paracelsus.dmm
@@ -789,7 +789,7 @@
"if" = (
/obj/structure/table/wood,
/obj/machinery/light/directional/west,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 4;
pixel_x = -4;
pixel_y = 7
@@ -5388,7 +5388,7 @@
pixel_x = 8;
pixel_y = -8
},
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 8;
pixel_x = 4;
pixel_y = 7
diff --git a/_maps/shuttles/subshuttles/inteq_anvil.dmm b/_maps/shuttles/subshuttles/inteq_anvil.dmm
index 4a4c4073ced1..334b41dab881 100644
--- a/_maps/shuttles/subshuttles/inteq_anvil.dmm
+++ b/_maps/shuttles/subshuttles/inteq_anvil.dmm
@@ -1,6 +1,6 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
-/obj/machinery/computer/secure_data{
+/obj/machinery/computer/records/sec{
dir = 8
},
/obj/effect/turf_decal/techfloor{
diff --git a/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm b/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm
index d218dc5581b1..5d616a1376cc 100644
--- a/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm
+++ b/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm
@@ -616,7 +616,7 @@
/obj/structure/table/reinforced,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 4
},
/obj/effect/turf_decal/spline/fancy/opaque/black{
@@ -807,7 +807,7 @@
/turf/open/floor/plasteel/tech,
/area/ship/maintenance/starboard)
"ip" = (
-/obj/machinery/computer/med_data/syndie,
+/obj/machinery/computer/records/med/syndie,
/obj/effect/turf_decal/techfloor{
dir = 1
},
@@ -908,7 +908,7 @@
/turf/open/floor/plasteel/tech/techmaint,
/area/ship/engineering)
"jn" = (
-/obj/machinery/computer/secure_data/syndie{
+/obj/machinery/computer/records/sec/syndie{
dir = 1
},
/obj/effect/turf_decal/techfloor,
diff --git a/_maps/shuttles/syndicate/syndicate_litieguai.dmm b/_maps/shuttles/syndicate/syndicate_litieguai.dmm
index 2b12f177f57e..46143a322557 100644
--- a/_maps/shuttles/syndicate/syndicate_litieguai.dmm
+++ b/_maps/shuttles/syndicate/syndicate_litieguai.dmm
@@ -1198,7 +1198,7 @@
/turf/open/floor/engine,
/area/ship/cargo)
"yQ" = (
-/obj/machinery/computer/med_data{
+/obj/machinery/computer/records/med{
dir = 8
},
/turf/open/floor/plasteel/dark,
@@ -2199,7 +2199,7 @@
/obj/structure/window/reinforced{
dir = 8
},
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 4
},
/obj/machinery/door/firedoor/border_only{
@@ -2652,7 +2652,7 @@
/turf/open/floor/plasteel/tech,
/area/ship/medical)
"TZ" = (
-/obj/structure/filingcabinet/medical,
+/obj/structure/filingcabinet/record/medical,
/obj/machinery/airalarm/directional/east,
/obj/machinery/light/directional/north,
/turf/open/floor/carpet/cyan,
diff --git a/_maps/shuttles/syndicate/syndicate_panacea.dmm b/_maps/shuttles/syndicate/syndicate_panacea.dmm
index 24334160f64b..03defd494174 100644
--- a/_maps/shuttles/syndicate/syndicate_panacea.dmm
+++ b/_maps/shuttles/syndicate/syndicate_panacea.dmm
@@ -1292,7 +1292,7 @@
/area/ship/crew/dorm/dormtwo)
"hs" = (
/obj/structure/table/wood/reinforced,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 1;
pixel_y = 4
},
@@ -2936,7 +2936,7 @@
/area/ship/crew/dorm)
"qk" = (
/obj/structure/table/wood/reinforced,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 1;
pixel_y = 4
},
@@ -5855,7 +5855,7 @@
/area/ship/engineering)
"Ix" = (
/obj/structure/table,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_y = 5;
pixel_x = 4
@@ -8310,7 +8310,7 @@
},
/area/ship/crew/dorm/dormfour)
"Xw" = (
-/obj/machinery/computer/med_data/syndie{
+/obj/machinery/computer/records/med/syndie{
dir = 8
},
/turf/open/floor/suns/hatch{
diff --git a/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm b/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm
index bca4d457916a..f0e5a755a498 100644
--- a/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm
+++ b/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm
@@ -589,7 +589,7 @@
/area/ship/cargo)
"dq" = (
/obj/structure/table/reinforced,
-/obj/machinery/computer/secure_data/laptop{
+/obj/machinery/computer/records/sec/laptop{
dir = 8;
pixel_y = 6;
pixel_x = 1
@@ -1000,7 +1000,7 @@
/area/ship/engineering/engine)
"gq" = (
/obj/structure/table,
-/obj/machinery/computer/med_data/laptop{
+/obj/machinery/computer/records/med/laptop{
dir = 8;
pixel_y = 6
},
diff --git a/code/__DEFINES/datacore.dm b/code/__DEFINES/datacore.dm
new file mode 100644
index 000000000000..fa224c91bda8
--- /dev/null
+++ b/code/__DEFINES/datacore.dm
@@ -0,0 +1,85 @@
+#define DATACORE_ID "id"
+#define DATACORE_RANK "rank"
+#define DATACORE_INITIAL_RANK "initial_rank"
+#define DATACORE_NAME "name"
+#define DATACORE_AGE "age"
+#define DATACORE_GENDER "gender"
+#define DATACORE_SPECIES "species"
+
+#define DATACORE_APPEARANCE "character_appearance"
+#define DATACORE_NOTES "notes"
+
+#define DATACORE_PHYSICAL_HEALTH "p_stat"
+#define DATACORE_MENTAL_HEALTH "m_stat"
+
+#define DATACORE_BLOOD_TYPE "blood_type"
+#define DATACORE_BLOOD_DNA "b_dna"
+#define DATACORE_DISEASES "cdi"
+#define DATACORE_DISEASES_DETAILS "cdi_d"
+#define DATACORE_DISABILITIES "ma_dis"
+#define DATACORE_DISABILITIES_DETAILS "ma_dis_d"
+#define DATACORE_NOTES_MEDICAL "medical_note"
+
+#define DATACORE_FINGERPRINT "fingerprint"
+#define DATACORE_CRIMES "crim"
+#define DATACORE_CRIMINAL_STATUS "criminal"
+#define DATACORE_NOTES_SECURITY "security_note"
+
+//Not very used
+#define DATACORE_IMAGE "image"
+#define DATACORE_DNA_IDENTITY "identity"
+#define DATACORE_DNA_FEATURES "features"
+#define DATACORE_MINDREF "mind"
+
+/// Keys for SSdatacore.library
+#define DATACORE_RECORDS_OUTPOST "outpost"
+//#define DATACORE_RECORDS_SECURITY "security"
+//#define DATACORE_RECORDS_MEDICAL "medical"
+//#define DATACORE_RECORDS_LOCKED "locked"
+
+
+/// Physical statuses
+#define PHYSICAL_ACTIVE "Active"
+#define PHYSICAL_DEBILITATED "Debilitated"
+#define PHYSICAL_UNCONSCIOUS "Unconscious"
+#define PHYSICAL_DECEASED "Deceased"
+
+/// List of available physical statuses
+#define PHYSICAL_STATUSES list(\
+ PHYSICAL_ACTIVE, \
+ PHYSICAL_DEBILITATED, \
+ PHYSICAL_UNCONSCIOUS, \
+ PHYSICAL_DECEASED, \
+)
+
+/// Mental statuses
+#define MENTAL_STABLE "Stable"
+#define MENTAL_WATCH "Watch"
+#define MENTAL_UNSTABLE "Unstable"
+#define MENTAL_INSANE "Insane"
+
+/// List of available mental statuses
+#define MENTAL_STATUSES list(\
+ MENTAL_STABLE, \
+ MENTAL_WATCH, \
+ MENTAL_UNSTABLE, \
+ MENTAL_INSANE, \
+)
+
+/// Wanted statuses
+#define WANTED_ARREST "Arrest"
+#define WANTED_DISCHARGED "Discharged"
+#define WANTED_NONE "None"
+#define WANTED_PAROLE "Parole"
+#define WANTED_PRISONER "Incarcerated"
+#define WANTED_SUSPECT "Suspected"
+
+/// List of available wanted statuses
+#define WANTED_STATUSES list(\
+ WANTED_NONE, \
+ WANTED_SUSPECT, \
+ WANTED_ARREST, \
+ WANTED_PRISONER, \
+ WANTED_PAROLE, \
+ WANTED_DISCHARGED, \
+)
diff --git a/code/__DEFINES/dcs/signals/signals.dm b/code/__DEFINES/dcs/signals/signals.dm
index 38f7d8692853..5fcd3e4b9137 100644
--- a/code/__DEFINES/dcs/signals/signals.dm
+++ b/code/__DEFINES/dcs/signals/signals.dm
@@ -730,6 +730,12 @@
///called in /obj/item/gun/process_chamber (src)
#define COMSIG_GUN_CHAMBER_PROCESSED "gun_chamber_processed"
+
+///Global signal sent when the Datacore's initial manifest is complete
+#define COMSIG_GLOB_DATACORE_READY "datacore_ready"
+///Global signal sent when the datacore is added to via manifest_inject() (datum/data/record/general, datum/data/record/medical, datum/data/record/security, datum/data/record/locked)
+#define COMSIG_GLOB_MANIFEST_INJECT "manifest_inject"
+
///called when an elzu should unroot
#define COMSIG_DIGOUT "dig_out"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 3c815ef1fc37..1d77af86f9fd 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -329,7 +329,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
//Dummy mob reserve slots
#define DUMMY_HUMAN_SLOT_PREFERENCES "dummy_preference_preview"
#define DUMMY_HUMAN_SLOT_ADMIN "admintools"
-#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
//This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 54874bc9e16b..868eae83cf34 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -120,6 +120,7 @@
#define INIT_ORDER_EVENTS 70
#define INIT_ORDER_JOBS 65
#define INIT_ORDER_QUIRKS 60
+#define INIT_ORDER_DATACORE 57 // Must come before SSticker so datacore reading things can access it
#define INIT_ORDER_TICKER 55
#define INIT_ORDER_FACTION 53
#define INIT_ORDER_MAPPING 50
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 435b83e29797..0586f458cf06 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -460,14 +460,6 @@
i++
return i
-/// Returns datum/data/record
-/proc/find_record(field, value, list/L)
- for(var/datum/data/record/R in L)
- if(R.fields[field] == value)
- return R
- return FALSE
-
-
//Move a single element from position fromIndex within a list, to position toIndex
//All elements in the range [1,toIndex) before the move will be before the pivot afterwards
//All elements in the range [toIndex, L.len+1) before the move will be after the pivot afterwards
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index 38e540e996b9..11f1bd430a81 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -712,206 +712,180 @@ world
/// appearance system (overlays/underlays, etc.) is not available.
///
/// Only the first argument is required.
-/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = TRUE)
- //Define... defines.
+/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
+ // Loop through the underlays, then overlays, sorting them into the layers list
+ #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \
+ for (var/i in 1 to process.len) { \
+ var/image/current = process[i]; \
+ if (!current) { \
+ continue; \
+ } \
+ if (current.plane != FLOAT_PLANE && current.plane != appearance.plane) { \
+ continue; \
+ } \
+ var/current_layer = current.layer; \
+ if (current_layer < 0) { \
+ if (current_layer <= -1000) { \
+ return flat; \
+ } \
+ current_layer = base_layer + appearance.layer + current_layer / 1000; \
+ } \
+ for (var/index_to_compare_to in 1 to layers.len) { \
+ var/compare_to = layers[index_to_compare_to]; \
+ if (current_layer < layers[compare_to]) { \
+ layers.Insert(index_to_compare_to, current); \
+ break; \
+ } \
+ } \
+ layers[current] = current_layer; \
+ }
+
var/static/icon/flat_template = icon('icons/blanks/32x32.dmi', "nothing")
- #define BLANK icon(flat_template)
- #define SET_SELF(SETVAR) do { \
- var/icon/SELF_ICON=icon(icon(curicon, curstate, base_icon_dir),"",SOUTH,no_anim?1:null); \
- if(A.alpha<255) { \
- SELF_ICON.Blend(rgb(255,255,255,A.alpha),ICON_MULTIPLY);\
- } \
- if(A.color) { \
- if(islist(A.color)){ \
- SELF_ICON.MapColors(arglist(A.color))} \
- else{ \
- SELF_ICON.Blend(A.color,ICON_MULTIPLY)} \
- } \
- ##SETVAR=SELF_ICON;\
- } while (0)
- #define INDEX_X_LOW 1
- #define INDEX_X_HIGH 2
- #define INDEX_Y_LOW 3
- #define INDEX_Y_HIGH 4
-
- #define flatX1 flat_size[INDEX_X_LOW]
- #define flatX2 flat_size[INDEX_X_HIGH]
- #define flatY1 flat_size[INDEX_Y_LOW]
- #define flatY2 flat_size[INDEX_Y_HIGH]
- #define addX1 add_size[INDEX_X_LOW]
- #define addX2 add_size[INDEX_X_HIGH]
- #define addY1 add_size[INDEX_Y_LOW]
- #define addY2 add_size[INDEX_Y_HIGH]
-
- if(!A || A.alpha <= 0)
- return BLANK
-
- var/noIcon = FALSE
+ if(!appearance || appearance.alpha <= 0)
+ return icon(flat_template)
+
if(start)
if(!defdir)
- defdir = A.dir
+ defdir = appearance.dir
if(!deficon)
- deficon = A.icon
+ deficon = appearance.icon
if(!defstate)
- defstate = A.icon_state
+ defstate = appearance.icon_state
if(!defblend)
- defblend = A.blend_mode
+ defblend = appearance.blend_mode
+
+ var/curicon = appearance.icon || deficon
+ var/curstate = appearance.icon_state || defstate
+ var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir
- var/curicon = A.icon || deficon
- var/curstate = A.icon_state || defstate
+ var/render_icon = curicon
- if(!((noIcon = (!curicon))))
+ if (render_icon)
var/curstates = icon_states(curicon)
if(!(curstate in curstates))
- if("" in curstates)
+ if ("" in curstates)
curstate = ""
else
- noIcon = TRUE // Do not render this object.
+ render_icon = FALSE
- var/curdir
- var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
-
- //These should use the parent's direction (most likely)
- if(!A.dir || A.dir == SOUTH)
- curdir = defdir
- else
- curdir = A.dir
+ var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
//Try to remove/optimize this section ASAP, CPU hog.
//Determines if there's directionals.
- if(!noIcon && curdir != SOUTH)
- var/exist = FALSE
- var/static/list/checkdirs = list(NORTH, EAST, WEST)
- for(var/i in checkdirs) //Not using GLOB for a reason.
- if(length(icon_states(icon(curicon, curstate, i))))
- exist = TRUE
- break
- if(!exist)
+ if(render_icon && curdir != SOUTH)
+ if (
+ !length(icon_states(icon(curicon, curstate, NORTH))) \
+ && !length(icon_states(icon(curicon, curstate, EAST))) \
+ && !length(icon_states(icon(curicon, curstate, WEST))) \
+ )
base_icon_dir = SOUTH
- //
if(!base_icon_dir)
base_icon_dir = curdir
- ASSERT(!BLEND_DEFAULT) //I might just be stupid but lets make sure this define is 0.
+ var/curblend = appearance.blend_mode || defblend
- var/curblend = A.blend_mode || defblend
-
- if(A.overlays.len || A.underlays.len)
- var/icon/flat = BLANK
+ if(appearance.overlays.len || appearance.underlays.len)
+ var/icon/flat = icon(flat_template)
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
var/list/layers = list()
var/image/copy
// Add the atom's icon itself, without pixel_x/y offsets.
- if(!noIcon)
- copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=base_icon_dir)
- copy.color = A.color
- copy.alpha = A.alpha
+ if(render_icon)
+ copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=base_icon_dir)
+ copy.color = appearance.color
+ copy.alpha = appearance.alpha
copy.blend_mode = curblend
- layers[copy] = A.layer
-
- // Loop through the underlays, then overlays, sorting them into the layers list
- for(var/process_set in 0 to 1)
- var/list/process = process_set? A.overlays : A.underlays
- for(var/i in 1 to process.len)
- var/image/current = process[i]
- if(!current)
- continue
- if(current.plane != FLOAT_PLANE && current.plane != A.plane)
- continue
- var/current_layer = current.layer
- if(current_layer < 0)
- if(current_layer <= -1000)
- return flat
- current_layer = process_set + A.layer + current_layer / 1000
-
- for(var/p in 1 to layers.len)
- var/image/cmp = layers[p]
- if(current_layer < layers[cmp])
- layers.Insert(p, current)
- break
- layers[current] = current_layer
-
- //sortTim(layers, /proc/cmp_image_layer_asc)
+ layers[copy] = appearance.layer
+
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.underlays, 0)
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.overlays, 1)
var/icon/add // Icon of overlay being added
- // Current dimensions of flattened icon
- var/list/flat_size = list(1, flat.Width(), 1, flat.Height())
- // Dimensions of overlay being added
- var/list/add_size[4]
+ var/flatX1 = 1
+ var/flatX2 = flat.Width()
+ var/flatY1 = 1
+ var/flatY2 = flat.Height()
- for(var/V in layers)
- var/image/I = V
- if(I.alpha == 0)
+ var/addX1 = 0
+ var/addX2 = 0
+ var/addY1 = 0
+ var/addY2 = 0
+
+ for(var/image/layer_image as anything in layers)
+ if(layer_image.alpha == 0)
continue
- if(I == copy) // 'I' is an /image based on the object being flattened.
+ if(layer_image == copy) // 'layer_image' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
- add = icon(I.icon, I.icon_state, base_icon_dir)
+ add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir)
else // 'I' is an appearance object.
- add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim)
+ add = getFlatIcon(image(layer_image), curdir, curicon, curstate, curblend, FALSE, no_anim)
if(!add)
continue
+
// Find the new dimensions of the flat icon to fit the added overlay
- add_size = list(
- min(flatX1, I.pixel_x+1),
- max(flatX2, I.pixel_x+add.Width()),
- min(flatY1, I.pixel_y+1),
- max(flatY2, I.pixel_y+add.Height())
+ addX1 = min(flatX1, layer_image.pixel_x + 1)
+ addX2 = max(flatX2, layer_image.pixel_x + add.Width())
+ addY1 = min(flatY1, layer_image.pixel_y + 1)
+ addY2 = max(flatY2, layer_image.pixel_y + add.Height())
+
+ if (
+ addX1 != flatX1 \
+ && addX2 != flatX2 \
+ && addY1 != flatY1 \
+ && addY2 != flatY2 \
)
-
- if(flat_size ~! add_size)
// Resize the flattened icon so the new icon fits
flat.Crop(
- addX1 - flatX1 + 1,
- addY1 - flatY1 + 1,
- addX2 - flatX1 + 1,
- addY2 - flatY1 + 1
+ addX1 - flatX1 + 1,
+ addY1 - flatY1 + 1,
+ addX2 - flatX1 + 1,
+ addY2 - flatY1 + 1
)
- flat_size = add_size.Copy()
+
+ flatX1 = addX1
+ flatX2 = addY1
+ flatY1 = addX2
+ flatY2 = addY2
// Blend the overlay into the flattened icon
- flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1)
+ flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1)
- if(A.color)
- if(islist(A.color))
- flat.MapColors(arglist(A.color))
+ if(appearance.color)
+ if(islist(appearance.color))
+ flat.MapColors(arglist(appearance.color))
else
- flat.Blend(A.color, ICON_MULTIPLY)
+ flat.Blend(appearance.color, ICON_MULTIPLY)
- if(A.alpha < 255)
- flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
+ if(appearance.alpha < 255)
+ flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
if(no_anim)
//Clean up repeated frames
var/icon/cleaned = new /icon()
cleaned.Insert(flat, "", SOUTH, 1, 0)
- . = cleaned
+ return cleaned
else
- . = icon(flat, "", SOUTH)
- else //There's no overlays.
- if(!noIcon)
- SET_SELF(.)
-
- //Clear defines
- #undef flatX1
- #undef flatX2
- #undef flatY1
- #undef flatY2
- #undef addX1
- #undef addX2
- #undef addY1
- #undef addY2
-
- #undef INDEX_X_LOW
- #undef INDEX_X_HIGH
- #undef INDEX_Y_LOW
- #undef INDEX_Y_HIGH
-
- #undef BLANK
- #undef SET_SELF
+ return icon(flat, "", SOUTH)
+ else if (render_icon) // There's no overlays.
+ var/icon/final_icon = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? TRUE : null)
+
+ if (appearance.alpha < 255)
+ final_icon.Blend(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY)
+
+ if (appearance.color)
+ if (islist(appearance.color))
+ final_icon.MapColors(arglist(appearance.color))
+ else
+ final_icon.Blend(appearance.color, ICON_MULTIPLY)
+
+ return final_icon
+
+ #undef PROCESS_OVERLAYS_OR_UNDERLAYS
+
/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index d78667dbfb4b..de002044a836 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -176,8 +176,8 @@ GLOBAL_DATUM(syndicate_code_response_regex, /regex)
var/locations = strings(LOCATIONS_FILE, "locations")
var/list/names = list()
- for(var/datum/data/record/t in GLOB.data_core.general)//Picks from crew manifest.
- names += t.fields["name"]
+ for(var/datum/data/record/t in SSdatacore.get_records(DATACORE_RECORDS_OUTPOST))//Picks from crew manifest.
+ names += t.fields[DATACORE_NAME]
var/maxwords = words//Extra var to check for duplicates.
diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm
index d6c720380f46..6b4e519f2444 100644
--- a/code/_globalvars/misc.dm
+++ b/code/_globalvars/misc.dm
@@ -6,8 +6,6 @@ GLOBAL_VAR_INIT(timezoneOffset, 0) // The difference betwen midnight (of the hos
// However it'd be ok to use for accessing attack logs and such too, which are even laggier.
GLOBAL_VAR_INIT(fileaccess_timer, 0)
-GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
-
GLOBAL_VAR_INIT(CELLRATE, 0.002) // conversion ratio between a watt-tick and kilojoule
GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second)
diff --git a/code/controllers/subsystem/datacore.dm b/code/controllers/subsystem/datacore.dm
new file mode 100644
index 000000000000..14d75ec3e211
--- /dev/null
+++ b/code/controllers/subsystem/datacore.dm
@@ -0,0 +1,273 @@
+
+///Dummy mob reserve slot for manifest
+#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
+
+SUBSYSTEM_DEF(datacore)
+ name = "Data Core"
+ flags = SS_NO_FIRE
+ init_order = INIT_ORDER_DATACORE
+
+ /// A list of data libraries keyed by DATACORE_RECORDS_*
+ var/list/datum/data_library/library = list(
+ DATACORE_RECORDS_OUTPOST,
+ )
+
+ /// Set to TRUE when the initial roundstart manifest is complete
+ var/finished_setup = FALSE
+
+ var/list/datum/callback/datacore_ready_callbacks = list()
+
+/datum/controller/subsystem/datacore/Initialize(start_timeofday)
+ for(var/id in library)
+ library[id] = new /datum/data_library
+ return ..()
+
+/datum/controller/subsystem/datacore/Recover()
+ library = SSdatacore.library
+ finished_setup = SSdatacore.finished_setup
+
+/datum/controller/subsystem/datacore/proc/create_library(library_key)
+ var/datum/data_library/new_library = new /datum/data_library
+ library[library_key] = new_library
+ return new_library
+
+/// Returns a data record or null.
+/datum/controller/subsystem/datacore/proc/get_record_by_name(name, record_type = DATACORE_RECORDS_OUTPOST)
+ RETURN_TYPE(/datum/data/record)
+
+ return library[record_type].get_record_by_name(name)
+
+/// Returns a data library's records list
+/datum/controller/subsystem/datacore/proc/get_records(record_type = DATACORE_RECORDS_OUTPOST)
+ RETURN_TYPE(/list)
+ return library[record_type].records
+
+/datum/controller/subsystem/datacore/proc/find_record(field, needle, haystack = DATACORE_RECORDS_OUTPOST)
+ RETURN_TYPE(/datum/data/record)
+ for(var/datum/data/record/record_to_check in get_records(haystack))
+ if(record_to_check.fields[field] == needle)
+ return record_to_check
+
+/// Empties out a library
+/datum/controller/subsystem/datacore/proc/wipe_records(record_type)
+ var/datum/data_library/to_wipe = library[record_type]
+ if(!to_wipe)
+ return
+
+ QDEL_LIST(to_wipe.records)
+
+/// Removes a person from history. Except locked. That's permanent history.
+/datum/controller/subsystem/datacore/proc/demanifest(name)
+ //for(var/id in library - DATACORE_RECORDS_LOCKED)
+ for(var/id in library)
+ var/datum/data/record/R = get_record_by_name(name, id)
+ qdel(R)
+
+/datum/controller/subsystem/datacore/proc/inject_record(datum/data/record/R, record_type)
+ if(isnull(record_type))
+ CRASH("inject_record() called with no record type")
+
+ library[record_type].inject_record(R)
+
+/// Create the roundstart manifest using the newplayer list.
+/datum/controller/subsystem/datacore/proc/generate_manifest()
+ for(var/mob/dead/new_player/N as anything in GLOB.new_player_list)
+ if(N.new_character)
+ log_manifest(N.ckey, N.new_character.mind, N.new_character)
+
+ if(ishuman(N.new_character))
+ inject_library(N.new_character, N.client, DATACORE_RECORDS_OUTPOST)
+
+ CHECK_TICK
+
+ finished_setup = TRUE
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_DATACORE_READY, src)
+ invoke_datacore_callbacks()
+
+/// Add a callback to execute when the datacore has loaded
+/datum/controller/subsystem/datacore/proc/OnReady(datum/callback/CB)
+ if(finished_setup)
+ CB.InvokeAsync()
+ else
+ datacore_ready_callbacks += CB
+
+/datum/controller/subsystem/datacore/proc/invoke_datacore_callbacks()
+ for(var/datum/callback/CB as anything in datacore_ready_callbacks)
+ CB.InvokeAsync()
+
+ datacore_ready_callbacks.Cut()
+
+/datum/controller/subsystem/datacore/proc/manifest_modify(name, assignment)
+ var/datum/data/record/foundrecord = library[DATACORE_RECORDS_OUTPOST].get_record_by_name(name)
+ if(foundrecord)
+ foundrecord.fields[DATACORE_RANK] = assignment
+
+/datum/controller/subsystem/datacore/proc/get_manifest(record_type = DATACORE_RECORDS_OUTPOST)
+ var/list/manifest_out = list()
+ var/list/departments = list(
+ "Command" = GLOB.command_positions,
+ "Security" = GLOB.security_positions,
+ "Engineering" = GLOB.engineering_positions,
+ "Medical" = GLOB.medical_positions,
+ "Science" = GLOB.science_positions,
+ "Supply" = GLOB.supply_positions,
+ "Service" = GLOB.service_positions,
+ "Silicon" = GLOB.nonhuman_positions
+ )
+ for(var/datum/data/record/record as anything in SSdatacore.get_records(record_type))
+ var/name = record.fields[DATACORE_NAME]
+ var/rank = record.fields[DATACORE_RANK] // user-visible job
+ var/has_department = FALSE
+ for(var/department in departments)
+ var/list/jobs = departments[department]
+ if((rank in jobs))
+ if(!manifest_out[department])
+ manifest_out[department] = list()
+ // Append to beginning of list if captain or department head
+ if (rank == "Captain" || (department != "Command" && (rank in GLOB.command_positions)))
+ manifest_out[department] = list(list(
+ "name" = name,
+ "rank" = rank
+ )) + manifest_out[department]
+ else
+ manifest_out[department] += list(list(
+ "name" = name,
+ "rank" = rank
+ ))
+ has_department = TRUE
+ if(!has_department)
+ if(!manifest_out["Misc"])
+ manifest_out["Misc"] = list()
+ manifest_out["Misc"] += list(list(
+ "name" = name,
+ "rank" = rank
+ ))
+
+ return manifest_out
+
+//For ship records
+/datum/controller/subsystem/datacore/proc/inject_library(mob/living/carbon/human/H, client/C, datum/data_library/custom_library)
+ var/static/list/show_directions = list(SOUTH, WEST)
+ if(!(H.mind && (H.mind.assigned_role != H.mind.special_role)))
+ return
+
+ var/assignment
+ if(H.mind.assigned_role)
+ assignment = H.mind.assigned_role
+ else if(H.job)
+ assignment = H.job
+ else
+ assignment = "Unassigned"
+
+ var/static/record_id_num = 1001
+ var/id = num2hex(record_id_num++,6)
+ if(!C)
+ C = H.client
+
+ var/person_gender = "Other"
+ if(H.gender == "male")
+ person_gender = "Male"
+ if(H.gender == "female")
+ person_gender = "Female"
+
+ var/mutable_appearance/character_appearance = new(H.appearance)
+
+ //General Record
+ var/datum/data/record/G = new()
+ G.fields[DATACORE_ID] = id
+ G.fields[DATACORE_RANK] = assignment
+ G.fields[DATACORE_INITIAL_RANK] = assignment
+ G.fields[DATACORE_NAME] = H.real_name
+ G.fields[DATACORE_AGE] = H.age
+ G.fields[DATACORE_GENDER] = person_gender
+ G.fields[DATACORE_SPECIES] = H.dna.species.name
+
+ G.fields[DATACORE_APPEARANCE] = character_appearance
+ G.fields[DATACORE_NOTES] = "No notes."
+
+ G.fields[DATACORE_PHYSICAL_HEALTH] = PHYSICAL_ACTIVE
+ G.fields[DATACORE_MENTAL_HEALTH] = MENTAL_STABLE
+
+ G.fields[DATACORE_BLOOD_TYPE] = H.dna.blood_type.name
+ G.fields[DATACORE_BLOOD_DNA] = H.dna.unique_enzymes
+ G.fields[DATACORE_DISABILITIES] = "None"
+ G.fields[DATACORE_DISABILITIES_DETAILS] = "No minor disabilities have been declared."
+ G.fields[DATACORE_DISEASES] = "None"
+ G.fields[DATACORE_DISEASES_DETAILS] = "No diseases have been diagnosed at the moment."
+ G.fields[DATACORE_NOTES_MEDICAL] = list()
+
+ G.fields[DATACORE_FINGERPRINT] = md5(H.dna.uni_identity)
+ G.fields[DATACORE_CRIMINAL_STATUS] = "None"
+ G.fields[DATACORE_CRIMES] = list()
+ G.fields[DATACORE_NOTES_SECURITY] = "No security notes."
+
+ if(istype(custom_library, /datum/data_library))
+ custom_library.inject_record(G)
+ else
+ library[custom_library].inject_record(G)
+
+/datum/controller/subsystem/datacore/proc/create_record(library_target, name)
+ var/datum/data/record/new_record = new /datum/data/record
+ new_record.fields[DATACORE_NAME] = name
+ library[library_target].inject_record(new_record)
+ return new_record
+
+/**
+ * Supporing proc for getting general records
+ * and using them as pAI ui data. This gets
+ * medical information - or what I would deem
+ * medical information - and sends it as a list.
+ *
+ * @return - list(general_records_out)
+ */
+/datum/controller/subsystem/datacore/proc/get_general_records(record_key = DATACORE_RECORDS_OUTPOST)
+ if(!get_records(record_key))
+ return list()
+
+ /// The array of records
+ var/list/general_records_out = list()
+ for(var/datum/data/record/gen_record as anything in get_records(record_key))
+ /// The object containing the crew info
+ var/list/crew_record = list()
+ crew_record["ref"] = REF(gen_record)
+ crew_record[DATACORE_NAME] = gen_record.fields[DATACORE_NAME]
+ crew_record[DATACORE_PHYSICAL_HEALTH] = gen_record.fields[DATACORE_PHYSICAL_HEALTH]
+ crew_record[DATACORE_MENTAL_HEALTH] = gen_record.fields[DATACORE_MENTAL_HEALTH]
+ general_records_out += list(crew_record)
+ return general_records_out
+
+/**
+ * Supporing proc for getting secrurity records
+ * and using them as pAI ui data. Sends it as a
+ * list.
+ *
+ * @return - list(security_records_out)
+ */
+/datum/controller/subsystem/datacore/proc/get_security_records(record_key = DATACORE_RECORDS_OUTPOST)
+ if(!get_records(record_key))
+ return list()
+
+ /// The array of records
+ var/list/security_records_out = list()
+ for(var/datum/data/record/sec_record as anything in get_records(record_key))
+ /// The object containing the crew info
+ var/list/crew_record = list()
+ crew_record["ref"] = REF(sec_record)
+ crew_record["name"] = sec_record.fields[DATACORE_NAME]
+ crew_record["status"] = sec_record.fields[DATACORE_CRIMINAL_STATUS] // wanted status
+ crew_record["crimes"] = length(sec_record.fields[DATACORE_CRIMES])
+ security_records_out += list(crew_record)
+ return security_records_out
+
+/// Creates a new crime entry and hands it back.
+/datum/controller/subsystem/datacore/proc/new_crime_entry(cname = "", cdetails = "", author = "", time = "", fine = 0)
+ var/datum/data/crime/c = new /datum/data/crime
+ c.crimeName = cname
+ c.crimeDetails = cdetails
+ c.author = author
+ c.time = time
+ c.fine = fine
+ c.paid = 0
+ return c
+
+#undef DUMMY_HUMAN_SLOT_MANIFEST
diff --git a/code/controllers/subsystem/overmap.dm b/code/controllers/subsystem/overmap.dm
index 113bfefa7a52..5f70d23c400e 100644
--- a/code/controllers/subsystem/overmap.dm
+++ b/code/controllers/subsystem/overmap.dm
@@ -463,33 +463,6 @@ SUBSYSTEM_DEF(overmap)
return manifest_out
-/datum/controller/subsystem/overmap/proc/get_manifest_html(monochrome = FALSE)
- var/list/manifest = get_manifest()
- var/dat = {"
-
-
- Name Rank
- "}
- for(var/department in manifest)
- var/list/entries = manifest[department]
- dat += "[department] "
- var/even = FALSE
- for(var/entry in entries)
- var/list/entry_list = entry
- dat += "[entry_list["name"]] [entry_list["rank"]] "
- even = !even
-
- dat += "
"
- dat = replacetext(dat, "\n", "")
- dat = replacetext(dat, "\t", "")
- return dat
-
/datum/controller/subsystem/overmap/Recover()
overmap_objects = SSovermap.overmap_objects
controlled_ships = SSovermap.controlled_ships
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
deleted file mode 100644
index 0103be96ce03..000000000000
--- a/code/datums/datacore.dm
+++ /dev/null
@@ -1,291 +0,0 @@
-//TODO: someone please get rid of this shit
-/datum/datacore
- var/list/medical = list()
- var/medicalPrintCount = 0
- var/list/general = list()
- var/list/security = list()
- var/securityPrintCount = 0
- var/securityCrimeCounter = 0
- ///This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
- var/list/locked = list()
-
-/datum/data
- var/name = "data"
-
-/datum/data/record
- name = "record"
- var/list/fields = list()
-
-/datum/data/record/Destroy()
- if(src in GLOB.data_core.medical)
- GLOB.data_core.medical -= src
- if(src in GLOB.data_core.security)
- GLOB.data_core.security -= src
- if(src in GLOB.data_core.general)
- GLOB.data_core.general -= src
- if(src in GLOB.data_core.locked)
- GLOB.data_core.locked -= src
- . = ..()
-
-/datum/data/crime
- name = "crime"
- var/crimeName = ""
- var/crimeDetails = ""
- var/author = ""
- var/time = ""
- var/fine = 0
- var/paid = 0
- var/dataId = 0
-
-/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "", fine = 0)
- var/datum/data/crime/c = new /datum/data/crime
- c.crimeName = cname
- c.crimeDetails = cdetails
- c.author = author
- c.time = time
- c.fine = fine
- c.paid = 0
- c.dataId = ++securityCrimeCounter
- return c
-
-/**
- * Adds crime to security record.
- *
- * Is used to add single crime to someone's security record.
- * Arguments:
- * * id - record id.
- * * datum/data/crime/crime - premade array containing every variable, usually created by createCrimeEntry.
- */
-/datum/datacore/proc/addCrime(id = "", datum/data/crime/crime)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["crim"]
- crimes |= crime
- return
-
-/**
- * Deletes crime from security record.
- *
- * Is used to delete single crime to someone's security record.
- * Arguments:
- * * id - record id.
- * * cDataId - id of already existing crime.
- */
-/datum/datacore/proc/removeCrime(id, cDataId)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["crim"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crimes -= crime
- return
-
-/**
- * Adds details to a crime.
- *
- * Is used to add or replace details to already existing crime.
- * Arguments:
- * * id - record id.
- * * cDataId - id of already existing crime.
- * * details - data you want to add.
- */
-/datum/datacore/proc/addCrimeDetails(id, cDataId, details)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["crim"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crime.crimeDetails = details
- return
-
-/datum/datacore/proc/manifest()
- for(var/i in GLOB.new_player_list)
- var/mob/dead/new_player/N = i
- if(N.new_character)
- log_manifest(N.ckey,N.new_character.mind,N.new_character)
- if(ishuman(N.new_character))
- manifest_inject(N.new_character, N.client)
- CHECK_TICK
-
-/datum/datacore/proc/manifest_modify(name, assignment)
- var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general)
- if(foundrecord)
- foundrecord.fields["rank"] = assignment
-
-/datum/datacore/proc/get_manifest()
- var/list/manifest_out = list()
- var/list/departments = list(
- "Command" = GLOB.command_positions,
- "Security" = GLOB.security_positions,
- "Engineering" = GLOB.engineering_positions,
- "Medical" = GLOB.medical_positions,
- "Science" = GLOB.science_positions,
- "Supply" = GLOB.supply_positions,
- "Service" = GLOB.service_positions,
- "Silicon" = GLOB.nonhuman_positions
- )
- for(var/datum/data/record/t in GLOB.data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/has_department = FALSE
- for(var/department in departments)
- var/list/jobs = departments[department]
- if((rank in jobs))
- if(!manifest_out[department])
- manifest_out[department] = list()
- // Append to beginning of list if captain or department head
- if (rank == "Captain" || (department != "Command" && (rank in GLOB.command_positions)))
- manifest_out[department] = list(list(
- "name" = name,
- "rank" = rank
- )) + manifest_out[department]
- else
- manifest_out[department] += list(list(
- "name" = name,
- "rank" = rank
- ))
- has_department = TRUE
- if(!has_department)
- if(!manifest_out["Misc"])
- manifest_out["Misc"] = list()
- manifest_out["Misc"] += list(list(
- "name" = name,
- "rank" = rank
- ))
- return manifest_out
-
-/datum/datacore/proc/get_manifest_html(monochrome = FALSE)
- var/list/manifest = get_manifest()
- var/dat = {"
-
-
- Name Rank
- "}
- for(var/department in manifest)
- var/list/entries = manifest[department]
- dat += "[department] "
- //JUST
- var/even = FALSE
- for(var/entry in entries)
- var/list/entry_list = entry
- dat += "[entry_list["name"]] [entry_list["rank"]] "
- even = !even
-
- dat += "
"
- dat = replacetext(dat, "\n", "")
- dat = replacetext(dat, "\t", "")
- return dat
-
-
-/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C)
- set waitfor = FALSE
- var/static/list/show_directions = list(SOUTH, WEST)
- if(H.mind && (H.mind.assigned_role != H.mind.special_role))
- var/assignment
- if(H.mind.assigned_role)
- assignment = H.mind.assigned_role
- else if(H.job)
- assignment = H.job
- else
- assignment = "Unassigned"
-
- var/static/record_id_num = 1001
- var/id = num2hex(record_id_num++,6)
- if(!C)
- C = H.client
- var/image = get_id_photo(H, C, show_directions)
- var/datum/picture/pf = new
- var/datum/picture/ps = new
- pf.picture_name = "[H]"
- ps.picture_name = "[H]"
- pf.picture_desc = "This is [H]."
- ps.picture_desc = "This is [H]."
- pf.picture_image = icon(image, dir = SOUTH)
- ps.picture_image = icon(image, dir = WEST)
- var/obj/item/photo/photo_front = new(null, pf)
- var/obj/item/photo/photo_side = new(null, ps)
-
- //These records should ~really~ be merged or something
- //General Record
- var/datum/data/record/G = new()
- G.fields["id"] = id
- G.fields["name"] = H.real_name
- G.fields["rank"] = assignment
- G.fields["age"] = H.age
- G.fields["species"] = H.dna.species.name
- G.fields["fingerprint"] = md5(H.dna.uni_identity)
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["gender"] = H.gender
- if(H.gender == "male")
- G.fields["gender"] = "Male"
- else if(H.gender == "female")
- G.fields["gender"] = "Female"
- else
- G.fields["gender"] = "Other"
- G.fields["photo_front"] = photo_front
- G.fields["photo_side"] = photo_side
- general += G
-
- //Medical Record
- var/datum/data/record/M = new()
- M.fields["id"] = id
- M.fields["name"] = H.real_name
- M.fields["blood_type"] = H.dna.blood_type.name
- M.fields["b_dna"] = H.dna.unique_enzymes
- 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"] = H.get_trait_string(medical)
- medical += M
-
- //Security Record
- var/datum/data/record/S = new()
- S.fields["id"] = id
- S.fields["name"] = H.real_name
- S.fields["criminal"] = "None"
- S.fields["crim"] = list()
- S.fields["notes"] = "No notes."
- security += S
-
- //Locked Record
- var/datum/data/record/L = new()
- L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
- L.fields["name"] = H.real_name
- L.fields["rank"] = H.mind.assigned_role
- L.fields["age"] = H.age
- L.fields["gender"] = H.gender
- if(H.gender == "male")
- G.fields["gender"] = "Male"
- else if(H.gender == "female")
- G.fields["gender"] = "Female"
- else
- G.fields["gender"] = "Other"
- L.fields["blood_type"] = H.dna.blood_type
- L.fields["b_dna"] = H.dna.unique_enzymes
- L.fields["identity"] = H.dna.uni_identity
- L.fields["species"] = H.dna.species.type
- L.fields["features"] = H.dna.features
- L.fields["image"] = image
- L.fields["mindref"] = H.mind
- locked += L
- return
-
-/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C, show_directions = list(SOUTH), datum/job/J)
- var/datum/preferences/P
- if(!C)
- C = H.client
- if(C)
- P = C.prefs
- return get_flat_human_icon(null, J, P, DUMMY_HUMAN_SLOT_MANIFEST, show_directions)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index f52b9bdace9e..77949a931f19 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -1372,7 +1372,7 @@
return
///Connect this atom to a shuttle
-/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
+/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, handheld = FALSE)
return
/atom/proc/disconnect_from_shuttle(obj/docking_port/mobile/port)
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 4020895f29bd..bf02f983d244 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -91,6 +91,18 @@ Medical HUD! Basic mode needs suit sensors on.
//HELPERS
+/mob/proc/get_datacore_key()
+ return
+
+/mob/living/carbon/human/get_datacore_key()
+ var/linked_datacore
+ var/obj/item/card/id/ID = src.get_idcard()
+ if(!istype(ID))
+ return
+ if(length(ID.ship_access))
+ linked_datacore = ID.ship_access[1]
+ return linked_datacore
+
//called when a carbon changes virus
/mob/living/carbon/proc/check_virus()
var/threat
@@ -271,10 +283,10 @@ Security HUDs! Basic mode shows only the job.
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
var/perpname = get_face_name(get_id_name(""))
- if(perpname && GLOB.data_core)
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
+ if(perpname)
+ var/datum/data/record/R = SSdatacore.get_record_by_name(perpname, get_datacore_key())
if(R)
- switch(R.fields["criminal"])
+ switch(R.fields[DATACORE_CRIMINAL_STATUS])
if("*Arrest*")
holder.icon_state = "hudwanted"
return
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 24f66242d58e..c91b557dbf93 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -542,10 +542,10 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
gamer.client.give_award(/datum/award/achievement/misc/gamer, gamer) // PSYCH REPORT NOTE: patient kept rambling about how they did it for an "achievement", recommend continued holding for observation
gamer.mind?.adjust_experience(/datum/skill/gaming, 50) // cheevos make u better
- if(!isnull(GLOB.data_core.general))
- for(var/datum/data/record/R in GLOB.data_core.general)
- if(R.fields["name"] == gamer.name)
- R.fields["m_stat"] = "*Unstable*"
+ if(!isnull(SSdatacore.get_records(DATACORE_RECORDS_OUTPOST)))
+ for(var/datum/data/record/R in SSdatacore.get_records(DATACORE_RECORDS_OUTPOST))
+ if(R.fields[DATACORE_NAME] == gamer.name)
+ R.fields[DATACORE_MENTAL_HEALTH] = "*Unstable*"
return
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 63f9284c28ae..cb8cee14dfb3 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -180,8 +180,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/list/dat = list()
if (mode == 1) // accessing crew manifest
dat += "Crew Manifest: Please use security record computer to modify entries. "
- for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
- dat += {"[t.fields["name"]] - [t.fields["rank"]] "}
+ for(var/datum/data/record/t in sortRecord(SSdatacore.get_records(DATACORE_RECORDS_OUTPOST)))
+ dat += {"[t.fields[DATACORE_NAME]] - [t.fields[DATACORE_RANK]] "}
dat += "Print Access ID modification console. "
else
@@ -464,8 +464,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
sleep(50)
var/obj/item/paper/printed_paper = new /obj/item/paper(loc)
var/t1 = "Crew Manifest: "
- for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
- t1 += t.fields["name"] + " - " + t.fields["rank"] + " "
+ for(var/datum/data/record/t in sortRecord(SSdatacore.get_records(DATACORE_RECORDS_OUTPOST)))
+ t1 += t.fields[DATACORE_NAME] + " - " + t.fields[DATACORE_RANK] + " "
printed_paper.add_raw_text(t1)
printed_paper.name = "paper- 'Crew Manifest'"
printing = null
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 3916ad0d4b00..8ec531a03a37 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -63,7 +63,7 @@
. = pod
/proc/grow_clone_from_record(obj/machinery/clonepod/pod, datum/data/record/R, empty)
- return pod.growclone(R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mindref"], R.fields["last_death"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"], empty)
+ return pod.growclone(R.fields[DATACORE_NAME], R.fields["UI"], R.fields["SE"], R.fields[DATACORE_MINDREF], R.fields["last_death"], R.fields[DATACORE_BLOOD_TYPE], R.fields["mrace"], R.fields[DATACORE_DNA_FEATURES], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"], empty)
/obj/machinery/computer/cloning/process()
if(!(scanner && LAZYLEN(pods) && autoprocess))
@@ -73,7 +73,7 @@
scan_occupant(scanner.occupant)
for(var/datum/data/record/R in records)
- var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields["mindref"])
+ var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields[DATACORE_MINDREF])
if(!pod)
return
@@ -83,8 +83,8 @@
var/result = grow_clone_from_record(pod, R)
if(result & CLONING_SUCCESS)
- temp = "[R.fields["name"]] => Cloning cycle in progress... "
- log_cloning("Cloning of [key_name(R.fields["mindref"])] automatically started via autoprocess - [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
+ temp = "[R.fields[DATACORE_NAME]] => Cloning cycle in progress... "
+ log_cloning("Cloning of [key_name(R.fields[DATACORE_MINDREF])] automatically started via autoprocess - [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
if(result & CLONING_DELETE_RECORD)
records -= R
@@ -231,7 +231,7 @@
dat += "Current records "
dat += "<< Back "
for(var/datum/data/record/R in records)
- dat += "[R.fields["name"]] Scan ID [R.fields["id"]] View Record "
+ dat += "[R.fields[DATACORE_NAME]] Scan ID [R.fields[DATACORE_ID]] View Record "
if(3)
dat += "Selected Record "
dat += "<< Back "
@@ -240,10 +240,10 @@
dat += "Record not found. "
else
var/body_only = active_record.fields["body_only"]
- dat += "[active_record.fields["name"]][body_only ? " - BODY-ONLY" : ""] "
- dat += "Scan ID [active_record.fields["id"]] \
- [!body_only ? "Clone " : "" ]\
- Empty Clone "
+ dat += "[active_record.fields[DATACORE_NAME]][body_only ? " - BODY-ONLY" : ""] "
+ dat += "Scan ID [active_record.fields[DATACORE_ID]] \
+ [!body_only ? "Clone " : "" ]\
+ Empty Clone "
var/obj/item/implant/health/H = locate(active_record.fields["imp"])
@@ -269,7 +269,7 @@
var/list/L = list()
if(diskette.fields["UI"])
L += "Unique Identifier"
- if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"])
+ if(diskette.fields["UE"] && diskette.fields[DATACORE_NAME] && diskette.fields[DATACORE_BLOOD_TYPE])
L += "Unique Enzymes"
if(diskette.fields["SE"])
L += "Structural Enzymes"
@@ -369,7 +369,7 @@
else if(href_list["view_rec"])
playsound(src, "terminal_type", 25, FALSE)
- active_record = find_record("id", href_list["view_rec"], records)
+ active_record = SSdatacore.find_record(DATACORE_ID, href_list["view_rec"], records)
if(active_record)
menu = 3
else
@@ -399,8 +399,8 @@
else if (menu == 4)
- log_cloning("[key_name(usr)] deleted [key_name(active_record.fields["mindref"])]'s cloning records from [src] at [AREACOORD(src)].")
- temp = "[active_record.fields["name"]] => Record deleted."
+ log_cloning("[key_name(usr)] deleted [key_name(active_record.fields[DATACORE_MINDREF])]'s cloning records from [src] at [AREACOORD(src)].")
+ temp = "[active_record.fields[DATACORE_NAME]] => Record deleted."
records.Remove(active_record)
active_record = null
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
@@ -432,7 +432,7 @@
if(include_se)
overwrite_field_if_available(active_record, diskette, "SE")
- log_cloning("[key_name(usr)] uploaded [key_name(active_record.fields["mindref"])]'s cloning records to [src] at [AREACOORD(src)] via [diskette].")
+ log_cloning("[key_name(usr)] uploaded [key_name(active_record.fields[DATACORE_MINDREF])]'s cloning records to [src] at [AREACOORD(src)] via [diskette].")
temp = "Load successful."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
@@ -448,9 +448,9 @@
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return
- log_cloning("[key_name(usr)] added [key_name(active_record.fields["mindref"])]'s cloning records to [diskette] via [src] at [AREACOORD(src)].")
+ log_cloning("[key_name(usr)] added [key_name(active_record.fields[DATACORE_MINDREF])]'s cloning records to [diskette] via [src] at [AREACOORD(src)].")
diskette.fields = active_record.fields.Copy()
- diskette.name = "data disk - '[diskette.fields["name"]]'"
+ diskette.name = "data disk - '[diskette.fields[DATACORE_NAME]]'"
temp = "Save successful."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
@@ -459,7 +459,7 @@
playsound(src, "terminal_type", 25, FALSE)
else if (href_list["clone"])
- var/datum/data/record/C = find_record("id", href_list["clone"], records)
+ var/datum/data/record/C = SSdatacore.find_record(DATACORE_ID, href_list["clone"], records)
var/empty = href_list["empty"]
//Look for that player! They better be dead!
if(C)
@@ -484,16 +484,16 @@
else
var/result = grow_clone_from_record(pod, C, empty)
if(result & CLONING_SUCCESS)
- temp = "[C.fields["name"]] => Cloning cycle in progress... "
+ temp = "[C.fields[DATACORE_NAME]] => Cloning cycle in progress... "
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if(active_record == C)
active_record = null
menu = 1
success = TRUE
if(!empty)
- log_cloning("[key_name(usr)] initiated cloning of [key_name(C.fields["mindref"])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
+ log_cloning("[key_name(usr)] initiated cloning of [key_name(C.fields[DATACORE_MINDREF])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
else
- log_cloning("[key_name(usr)] initiated EMPTY cloning of [key_name(C.fields["mindref"])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
+ log_cloning("[key_name(usr)] initiated EMPTY cloning of [key_name(C.fields[DATACORE_MINDREF])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
if(result & CLONING_DELETE_RECORD)
if(active_record == C)
active_record = null
@@ -501,7 +501,7 @@
records -= C
if(!success)
- temp = "[C.fields["name"]] => Initialisation failure. "
+ temp = "[C.fields[DATACORE_NAME]] => Initialisation failure. "
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
else
@@ -573,13 +573,13 @@
var/datum/species/rando_race = pick(GLOB.roundstart_races)
R.fields["mrace"] = rando_race.type
- R.fields["name"] = mob_occupant.real_name
- R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6)
+ R.fields[DATACORE_NAME] = mob_occupant.real_name
+ R.fields[DATACORE_ID] = copytext_char(md5(mob_occupant.real_name), 2, 6)
R.fields["UE"] = dna.unique_enzymes
R.fields["UI"] = dna.uni_identity
R.fields["SE"] = dna.mutation_index
- R.fields["blood_type"] = dna.blood_type
- R.fields["features"] = dna.features
+ R.fields[DATACORE_BLOOD_TYPE] = dna.blood_type
+ R.fields[DATACORE_DNA_FEATURES] = dna.features
R.fields["factions"] = mob_occupant.faction
R.fields["quirks"] = list()
for(var/V in mob_occupant.roundstart_quirks)
@@ -593,7 +593,7 @@
R.fields["traumas"] = B.get_traumas()
R.fields["bank_account"] = has_bank_account
- R.fields["mindref"] = "[REF(mob_occupant.mind)]"
+ R.fields[DATACORE_MINDREF] = "[REF(mob_occupant.mind)]"
R.fields["last_death"] = mob_occupant.stat == DEAD && mob_occupant.mind ? mob_occupant.mind.last_death : -1
R.fields["body_only"] = body_only
@@ -608,9 +608,9 @@
imp.implant(mob_occupant)
R.fields["imp"] = "[REF(imp)]"
- var/datum/data/record/old_record = find_record("mindref", REF(mob_occupant.mind), records)
+ var/datum/data/record/old_record = SSdatacore.find_record("mindref", REF(mob_occupant.mind), records)
if(body_only)
- old_record = find_record("UE", dna.unique_enzymes, records) //Body-only records cannot be identified by mind, so we use the DNA
+ old_record = SSdatacore.find_record("UE", dna.unique_enzymes, records) //Body-only records cannot be identified by mind, so we use the DNA
if(old_record && ((old_record.fields["UI"] != dna.uni_identity) || (!old_record.fields["body_only"]))) //Never overwrite a mind-and-body record if it exists
old_record = null
if(old_record)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
deleted file mode 100644
index 17c5dc2ef39c..000000000000
--- a/code/game/machinery/computer/medical.dm
+++ /dev/null
@@ -1,581 +0,0 @@
-
-
-/obj/machinery/computer/med_data//TODO:SANITY
- name = "medical records console"
- desc = "This can be used to check medical records."
- icon_screen = "medcomp"
- icon_keyboard = "med_key"
- req_one_access = list(ACCESS_MEDICAL, ACCESS_FORENSICS_LOCKERS)
- circuit = /obj/item/circuitboard/computer/med_data
- light_color = LIGHT_COLOR_BLUE
- var/rank = null
- var/screen = null
- var/datum/data/record/active1
- var/datum/data/record/active2
- var/temp = null
- var/printing = null
- //Sorting Variables
- var/sortBy = "name"
- var/order = 1 // -1 = Descending - 1 = Ascending
-
-
-/obj/machinery/computer/med_data/syndie
- icon_keyboard = "syndie_key"
-
-/obj/machinery/computer/med_data/ui_interact(mob/user)
- . = ..()
- if(isliving(user))
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- var/dat
- if(temp)
- dat = text("[temp] Clear Screen ")
- else
- if(authenticated)
- switch(screen)
- if(1)
- dat += {"
-Search Records
-List Records
-
-Virus Database
-Medbot Tracking
-
-Record Maintenance
-{Log Out}
-"}
- if(2)
- dat += {"
-
-
-
-
-Name
-ID
-Fingerprints (F) | DNA UE (D)
-Blood Type
-Physical Status
-Mental Status
- "}
-
-
- if(!isnull(GLOB.data_core.general))
- for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order))
- var/blood_type = ""
- var/b_dna = ""
- for(var/datum/data/record/E in GLOB.data_core.medical)
- if((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
- blood_type = E.fields["blood_type"]
- b_dna = E.fields["b_dna"]
- var/background
-
- if(R.fields["m_stat"] == "*Insane*" || R.fields["p_stat"] == "*Deceased*")
- background = "'background-color:#990000;'"
- else if(R.fields["p_stat"] == "*Unconscious*" || R.fields["m_stat"] == "*Unstable*")
- background = "'background-color:#CD6500;'"
- else if(R.fields["p_stat"] == "Physically Unfit" || R.fields["m_stat"] == "*Watch*")
- background = "'background-color:#3BB9FF;'"
- else
- background = "'background-color:#4F7529;'"
-
- dat += text("[] ", background, R.fields["id"], R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("F: []D: [] ", R.fields["fingerprint"], b_dna)
- dat += text("[] ", blood_type)
- dat += text("[] ", R.fields["p_stat"])
- dat += text("[] ", R.fields["m_stat"])
- dat += "
"
- dat += "Back "
- if(3)
- dat += "Records Maintenance \nBackup To Disk \nUpload From Disk \nDelete All Records \n \nBack "
- if(4)
-
- dat += ""
- if(5)
- dat += "Virus Database "
- for(var/Dt in typesof(/datum/disease/))
- var/datum/disease/Dis = new Dt(0)
- if(istype(Dis, /datum/disease/advance))
- continue // TODO (tm): Add advance diseases to the virus database which no one uses.
- if(!Dis.desc)
- continue
- dat += "[Dis.name] "
- dat += "Back "
- if(6)
- dat += "Medical Robot Monitor "
- dat += "Back "
- dat += "Medical Robots: "
- var/bdat = null
- for(var/mob/living/simple_animal/bot/medbot/M in GLOB.alive_mob_list)
- if(M.virtual_z() != src.virtual_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(!bdat)
- dat += "None detected "
- else
- dat += " [bdat]"
-
- else
- else
- dat += "{Log In} "
- var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400)
- popup.set_content(dat)
- popup.open()
-
-/obj/machinery/computer/med_data/Topic(href, href_list)
- . = ..()
- if(.)
- return .
- if(!(active1 in GLOB.data_core.general))
- active1 = null
- if(!(active2 in GLOB.data_core.medical))
- active2 = null
-
- if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || isAdminGhostAI(usr))
- usr.set_machine(src)
- if(href_list["temp"])
- temp = null
- else if(href_list["logout"])
- authenticated = null
- screen = null
- active1 = null
- active2 = null
- playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
- else if(href_list["choice"])
- // SORTING!
- if(href_list["choice"] == "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)
- else if(href_list["login"])
- var/mob/M = usr
- var/obj/item/card/id/I = M.get_idcard(TRUE)
- if(issilicon(M))
- active1 = null
- active2 = null
- authenticated = 1
- rank = "AI"
- screen = 1
- else if(isAdminGhostAI(M))
- active1 = null
- active2 = null
- authenticated = 1
- rank = "Central Command"
- screen = 1
- else if(istype(I) && check_access(I))
- active1 = null
- active2 = null
- authenticated = I.registered_name
- rank = I.assignment
- screen = 1
- else
- to_chat(usr, "Unauthorized access. ")
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
- if(authenticated)
- if(href_list["screen"])
- screen = text2num(href_list["screen"])
- if(screen < 1)
- screen = 1
-
- active1 = null
- active2 = null
-
- else if(href_list["vir"])
- var/type = href_list["vir"]
- var/datum/disease/Dis = new type(0)
- var/AfS = ""
- for(var/mob/M in Dis.viable_mobtypes)
- AfS += " [initial(M.name)];"
- temp = {"Name: [Dis.name]
-Number of stages: [Dis.max_stages]
-Spread: [Dis.spread_text] Transmission
-Possible Cure: [(Dis.cure_text||"none")]
-Affected Lifeforms: [AfS]
-
-Notes: [Dis.desc]
-
-Severity: [Dis.severity]"}
-
- else if(href_list["del_all"])
- temp = "Are you sure you wish to delete all records? \n\tYes \n\tNo "
-
- else if(href_list["del_all2"])
- investigate_log("[key_name(usr)] has deleted all medical records.", INVESTIGATE_RECORDS)
- GLOB.data_core.medical.Cut()
- temp = "All records deleted."
-
- else if(href_list["field"])
- var/a1 = active1
- var/a2 = active2
- switch(href_list["field"])
- if("fingerprint")
- if(active1)
- var/t1 = stripped_input("Please input fingerprint hash:", "Med. records", active1.fields["fingerprint"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, a1))
- return
- active1.fields["fingerprint"] = t1
- if("gender")
- if(active1)
- if(active1.fields["gender"] == "Male")
- active1.fields["gender"] = "Female"
- else if(active1.fields["gender"] == "Female")
- active1.fields["gender"] = "Other"
- else
- active1.fields["gender"] = "Male"
- if("age")
- if(active1)
- var/t1 = input("Please input age:", "Med. records", active1.fields["age"], null) as num
- if(!canUseMedicalRecordsConsole(usr, t1, a1))
- return
- active1.fields["age"] = t1
- if("species")
- if(active1)
- var/t1 = stripped_input("Please input species name", "Med. records", active1.fields["species"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, a1))
- return
- active1.fields["species"] = t1
- if("mi_dis")
- if(active2)
- var/t1 = stripped_input("Please input minor disabilities list:", "Med. records", active2.fields["mi_dis"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["mi_dis"] = t1
- if("mi_dis_d")
- if(active2)
- var/t1 = stripped_input("Please summarize minor dis.:", "Med. records", active2.fields["mi_dis_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["mi_dis_d"] = t1
- if("ma_dis")
- if(active2)
- var/t1 = stripped_input("Please input major disabilities list:", "Med. records", active2.fields["ma_dis"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["ma_dis"] = t1
- if("ma_dis_d")
- if(active2)
- var/t1 = stripped_input("Please summarize major dis.:", "Med. records", active2.fields["ma_dis_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["ma_dis_d"] = t1
- if("alg")
- if(active2)
- var/t1 = stripped_input("Please state allergies:", "Med. records", active2.fields["alg"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["alg"] = t1
- if("alg_d")
- if(active2)
- var/t1 = stripped_input("Please summarize allergies:", "Med. records", active2.fields["alg_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["alg_d"] = t1
- if("cdi")
- if(active2)
- var/t1 = stripped_input("Please state diseases:", "Med. records", active2.fields["cdi"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["cdi"] = t1
- if("cdi_d")
- if(active2)
- var/t1 = stripped_input("Please summarize diseases:", "Med. records", active2.fields["cdi_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["cdi_d"] = t1
- if("notes")
- if(active2)
- var/t1 = stripped_input("Please summarize notes:", "Med. records", active2.fields["notes"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["notes"] = t1
- if("p_stat")
- if(active1)
- temp = "Physical Condition: \n\t*Deceased* \n\t*Unconscious* \n\tActive \n\tPhysically Unfit "
- if("m_stat")
- if(active1)
- temp = "Mental Condition: \n\t*Insane* \n\t*Unstable* \n\t*Watch* \n\tStable "
- if("blood_type")
- if(active2)
- temp = "Blood Type: \n\tA- A+ \n\tB- B+ \n\tAB- AB+ \n\tO- O+ "
- if("b_dna")
- if(active2)
- var/t1 = stripped_input("Please input DNA hash:", "Med. records", active2.fields["b_dna"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["b_dna"] = t1
- if("show_photo_front")
- if(active1)
- if(active1.fields["photo_front"])
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_front"]
- P.show(usr)
- if("show_photo_side")
- if(active1)
- if(active1.fields["photo_side"])
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_side"]
- P.show(usr)
- else
-
- else if(href_list["p_stat"])
- if(active1)
- switch(href_list["p_stat"])
- if("deceased")
- active1.fields["p_stat"] = "*Deceased*"
- if("unconscious")
- active1.fields["p_stat"] = "*Unconscious*"
- if("active")
- active1.fields["p_stat"] = "Active"
- if("unfit")
- active1.fields["p_stat"] = "Physically Unfit"
-
- else if(href_list["m_stat"])
- if(active1)
- switch(href_list["m_stat"])
- if("insane")
- active1.fields["m_stat"] = "*Insane*"
- if("unstable")
- active1.fields["m_stat"] = "*Unstable*"
- if("watch")
- active1.fields["m_stat"] = "*Watch*"
- if("stable")
- active1.fields["m_stat"] = "Stable"
-
-
- else if(href_list["blood_type"])
- if(active2)
- switch(href_list["blood_type"])
- if("an")
- active2.fields["blood_type"] = "A-"
- if("bn")
- active2.fields["blood_type"] = "B-"
- if("abn")
- active2.fields["blood_type"] = "AB-"
- if("on")
- active2.fields["blood_type"] = "O-"
- if("ap")
- active2.fields["blood_type"] = "A+"
- if("bp")
- active2.fields["blood_type"] = "B+"
- if("abp")
- active2.fields["blood_type"] = "AB+"
- if("op")
- active2.fields["blood_type"] = "O+"
-
-
- else if(href_list["del_r"])
- if(active2)
- temp = "Are you sure you wish to delete the record (Medical Portion Only)? \n\tYes \n\tNo "
-
- else if(href_list["del_r2"])
- investigate_log("[key_name(usr)] has deleted the medical records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
- if(active2)
- qdel(active2)
- active2 = null
-
- else if(href_list["d_rec"])
- active1 = find_record("id", href_list["d_rec"], GLOB.data_core.general)
- if(active1)
- active2 = find_record("id", href_list["d_rec"], GLOB.data_core.medical)
- if(!active2)
- active1 = null
- screen = 4
-
- else if(href_list["new"])
- if((istype(active1, /datum/data/record) && !(istype(active2, /datum/data/record))))
- var/datum/data/record/R = new /datum/data/record()
- R.fields["name"] = active1.fields["name"]
- R.fields["id"] = active1.fields["id"]
- R.name = text("Medical Record #[]", R.fields["id"])
- R.fields["blood_type"] = "Unknown"
- R.fields["b_dna"] = "Unknown"
- R.fields["mi_dis"] = "None"
- R.fields["mi_dis_d"] = "No minor disabilities have been diagnosed."
- 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."
- GLOB.data_core.medical += R
- active2 = R
- screen = 4
-
- else if(href_list["add_c"])
- if(!(active2 in GLOB.data_core.medical))
- return
- var/a2 = active2
- var/t1 = stripped_multiline_input("Add Comment:", "Med. records", null, null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], [] []", authenticated, rank, station_time_timestamp(), sector_datestamp(), t1)
-
- else if(href_list["del_c"])
- if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
- active2.fields[text("com_[]", href_list["del_c"])] = "Deleted "
-
- else if(href_list["search"])
- var/t1 = stripped_input(usr, "Search String: (Name, DNA, or ID)", "Med. records")
- if(!canUseMedicalRecordsConsole(usr, t1))
- return
- active1 = null
- active2 = null
- t1 = lowertext(t1)
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"])))
- active2 = R
- else
- //Foreach continue //goto(3229)
- if(!(active2))
- temp = text("Could not locate record [].", sanitize(t1))
- else
- for(var/datum/data/record/E in GLOB.data_core.general)
- if((E.fields["name"] == active2.fields["name"] || E.fields["id"] == active2.fields["id"]))
- active1 = E
- else
- //Foreach continue //goto(3334)
- screen = 4
-
- else if(href_list["print_p"])
- if(!(printing))
- printing = 1
- GLOB.data_core.medicalPrintCount++
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- sleep(30)
- var/obj/item/paper/printed_paper = new /obj/item/paper(loc)
- var/final_paper_text = "Medical Record - (MR-[GLOB.data_core.medicalPrintCount]) "
- if(active1 in GLOB.data_core.general)
- final_paper_text += text("Name: [] ID: [] \nGender: [] \nAge: [] ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"])
- final_paper_text += "\nSpecies: [active1.fields["species"]] "
- final_paper_text += text("\nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"])
- else
- final_paper_text += "General Record Lost! "
- if(active2 in GLOB.data_core.medical)
- final_paper_text += 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 ", active2.fields["blood_type"], active2.fields["b_dna"], active2.fields["mi_dis"], active2.fields["mi_dis_d"], active2.fields["ma_dis"], active2.fields["ma_dis_d"], active2.fields["alg"], active2.fields["alg_d"], active2.fields["cdi"], active2.fields["cdi_d"], active2.fields["notes"])
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- final_paper_text += text("[] ", active2.fields[text("com_[]", counter)])
- counter++
- printed_paper.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, active1.fields["name"])
- else
- final_paper_text += "Medical Record Lost! "
- printed_paper.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, "Record Lost")
- final_paper_text += ""
- printed_paper.add_raw_text(final_paper_text)
- printed_paper.update_appearance()
- printing = null
-
- add_fingerprint(usr)
- updateUsrDialog()
- return
-
-/obj/machinery/computer/med_data/emp_act(severity)
- . = ..()
- if(!(machine_stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- if(prob(10))
- R.fields["name"] = random_unique_lizard_name(R.fields["gender"],1)
- else
- R.fields["name"] = random_unique_name(R.fields["gender"],1)
- if(2)
- R.fields["gender"] = pick("Male", "Female", "Other")
- if(3)
- R.fields["age"] = rand(AGE_MIN, AGE_MAX)
- if(4)
- var/datum/blood_type/blood = random_blood_type()
- R.fields["blood_type"] = blood.name
- if(5)
- R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit")
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
-/obj/machinery/computer/med_data/proc/canUseMedicalRecordsConsole(mob/user, message = 1, record1, record2)
- if(user)
- if(message)
- if(authenticated)
- if(user.canUseTopic(src, !issilicon(user)))
- if(!record1 || record1 == active1)
- if(!record2 || record2 == active2)
- return 1
- return 0
-
-/obj/machinery/computer/med_data/laptop
- name = "medical laptop"
- desc = "A cheap Nanotrasen medical laptop, it functions as a medical records computer. It's bolted to the table."
- icon_state = "laptop"
- icon_screen = "medlaptop"
- icon_keyboard = "laptop_key"
- pass_flags = PASSTABLE
- unique_icon = TRUE
diff --git a/code/game/machinery/computer/prisoner/gulag_teleporter.dm b/code/game/machinery/computer/prisoner/gulag_teleporter.dm
deleted file mode 100644
index f05ab6b8dea9..000000000000
--- a/code/game/machinery/computer/prisoner/gulag_teleporter.dm
+++ /dev/null
@@ -1,154 +0,0 @@
-//computer that handle the points and teleports the prisoner
-/obj/machinery/computer/prisoner/gulag_teleporter_computer
- name = "labor camp teleporter console"
- desc = "Used to send criminals to the Labor Camp."
- icon_screen = "explosive"
- icon_keyboard = "security_key"
- req_access = list(ACCESS_ARMORY)
- circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
- light_color = COLOR_SOFT_RED
-
- var/default_goal = 200
- var/obj/machinery/gulag_teleporter/teleporter = null
- var/obj/structure/gulag_beacon/beacon = null
- var/mob/living/carbon/human/prisoner = null
- var/datum/data/record/temporary_record = null
-
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/Initialize()
- . = ..()
- scan_machinery()
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "GulagTeleporterConsole", name)
- ui.open()
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
- var/list/data = list()
-
- var/list/prisoner_list = list()
- var/can_teleport = FALSE
-
- if(teleporter && (teleporter.occupant && ishuman(teleporter.occupant)))
- prisoner = teleporter.occupant
- prisoner_list["name"] = prisoner.real_name
- if(contained_id)
- can_teleport = TRUE
- if(!isnull(GLOB.data_core.general))
- for(var/r in GLOB.data_core.security)
- var/datum/data/record/R = r
- if(R.fields["name"] == prisoner_list["name"])
- temporary_record = R
- prisoner_list["crimstat"] = temporary_record.fields["criminal"]
-
- data["prisoner"] = prisoner_list
-
- if(teleporter)
- data["teleporter"] = teleporter
- data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.virtual_z()])"
- data["teleporter_lock"] = teleporter.locked
- data["teleporter_state_open"] = teleporter.state_open
- else
- data["teleporter"] = null
- if(beacon)
- data["beacon"] = beacon
- data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.virtual_z()])"
- else
- data["beacon"] = null
- if(contained_id)
- data["id"] = contained_id
- data["id_name"] = contained_id.registered_name
- data["goal"] = contained_id.goal
- else
- data["id"] = null
- data["can_teleport"] = can_teleport
-
- return data
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_act(action, list/params)
- . = ..()
- if(.)
- return
- if(isliving(usr))
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- if(!allowed(usr))
- to_chat(usr, "Access denied. ")
- return
- switch(action)
- if("scan_teleporter")
- teleporter = findteleporter()
- return TRUE
- if("scan_beacon")
- beacon = findbeacon()
- return TRUE
- if("handle_id")
- if(contained_id)
- id_eject(usr)
- else
- id_insert(usr)
- return TRUE
- if("set_goal")
- var/new_goal = text2num(params["value"])
- if(!isnum(new_goal))
- return
- if(!new_goal)
- new_goal = default_goal
- contained_id.goal = clamp(new_goal, 0, 1000) //maximum 1000 points
- return TRUE
- if("toggle_open")
- if(teleporter.locked)
- to_chat(usr, "The teleporter must be unlocked first. ")
- return
- teleporter.toggle_open()
- return TRUE
- if("teleporter_lock")
- if(teleporter.state_open)
- to_chat(usr, "The teleporter must be closed first. ")
- return
- teleporter.locked = !teleporter.locked
- return TRUE
- if("teleport")
- if(!teleporter || !beacon)
- return
- addtimer(CALLBACK(src, PROC_REF(teleport), usr), 5)
- return TRUE
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/scan_machinery()
- teleporter = findteleporter()
- beacon = findbeacon()
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/findteleporter()
- var/obj/machinery/gulag_teleporter/teleporterf = null
-
- for(var/direction in GLOB.cardinals)
- teleporterf = locate(/obj/machinery/gulag_teleporter, get_step(src, direction))
- if(teleporterf?.is_operational)
- return teleporterf
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/findbeacon()
- return locate(/obj/structure/gulag_beacon)
-
-/obj/machinery/computer/prisoner/gulag_teleporter_computer/proc/teleport(mob/user)
- if(!contained_id) //incase the ID was removed after the transfer timer was set.
- say("Warning: Unable to transfer prisoner without a valid Prisoner ID inserted!")
- return
- var/id_goal_not_set
- if(!contained_id.goal)
- id_goal_not_set = TRUE
- contained_id.goal = default_goal
- say("[contained_id]'s ID card goal defaulting to [contained_id.goal] points.")
- log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][contained_id.goal] points.")
- teleporter.handle_prisoner(contained_id, temporary_record)
- playsound(src, 'sound/weapons/emitter.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- prisoner.forceMove(get_turf(beacon))
- prisoner.Paralyze(40) // small travel dizziness
- to_chat(prisoner, "The teleportation makes you a little dizzy. ")
- new /obj/effect/particle_effect/sparks(get_turf(prisoner))
- playsound(src, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- if(teleporter.locked)
- teleporter.locked = FALSE
- teleporter.toggle_open()
- contained_id = null
- temporary_record = null
diff --git a/code/game/machinery/computer/record/medical.dm b/code/game/machinery/computer/record/medical.dm
new file mode 100644
index 000000000000..959a24556981
--- /dev/null
+++ b/code/game/machinery/computer/record/medical.dm
@@ -0,0 +1,133 @@
+
+
+/obj/machinery/computer/records/med//TODO:SANITY
+ name = "medical records console"
+ desc = "This can be used to check medical records."
+ icon_screen = "medcomp"
+ icon_keyboard = "med_key"
+ req_one_access = list(ACCESS_MEDICAL, ACCESS_FORENSICS_LOCKERS)
+ circuit = /obj/item/circuitboard/computer/med_data
+ light_color = LIGHT_COLOR_BLUE
+
+/obj/machinery/computer/records/med/ui_interact(mob/user, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+ ui = SStgui.try_update_ui(user, src, ui)
+ if (!ui)
+ ui = new(user, src, "MedicalRecords")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/obj/machinery/computer/records/med/ui_data(mob/user)
+ var/list/data = ..()
+
+ var/list/records = list()
+ if(linked_ship)
+ for(var/datum/data/record/target in SSdatacore.get_records(linked_ship))
+ var/list/notes = list()
+ for(var/datum/medical_note/note in target.fields[DATACORE_NOTES_MEDICAL])
+ notes += list(list(
+ author = note.author,
+ content = note.content,
+ note_ref = REF(note),
+ time = note.time,
+ ))
+ records += list(list(
+ record_ref = REF(target),
+ rank = target.fields[DATACORE_RANK],
+ age = target.fields[DATACORE_AGE],
+ name = target.fields[DATACORE_NAME],
+ gender = target.fields[DATACORE_GENDER],
+ species = target.fields[DATACORE_SPECIES],
+ physical_status = target.fields[DATACORE_PHYSICAL_HEALTH],
+ mental_status = target.fields[DATACORE_MENTAL_HEALTH],
+ blood_type = target.fields[DATACORE_BLOOD_TYPE],
+ dna = target.fields[DATACORE_BLOOD_DNA],
+ notes = notes,
+ ))
+
+ data["records"] = records
+
+ return data
+
+/obj/machinery/computer/records/med/ui_static_data(mob/user)
+ var/list/data = list()
+ data["min_age"] = AGE_MIN
+ data["max_age"] = AGE_MAX
+ data["physical_statuses"] = PHYSICAL_STATUSES
+ data["mental_statuses"] = MENTAL_STATUSES
+ return data
+
+/obj/machinery/computer/records/med/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ //var/mob/user = ui.user
+
+ var/datum/data/record/target
+ if(params["record_ref"])
+ target = locate(params["record_ref"]) in SSdatacore.get_records(linked_ship)
+
+ if(!target)
+ return FALSE
+
+ switch(action)
+ if("add_note")
+ if(!params["content"])
+ return FALSE
+ var/content = trim(params["content"], MAX_MESSAGE_LEN)
+
+ var/datum/medical_note/new_note = new(usr.name, content)
+ while(length(target.fields[DATACORE_NOTES_MEDICAL]) > 5)
+ var/list/medical_notes = target.fields[DATACORE_NOTES_MEDICAL]
+ medical_notes.Cut(1, 2)
+ target.fields[DATACORE_NOTES_MEDICAL] = medical_notes
+
+ target.fields[DATACORE_NOTES_MEDICAL] += new_note
+
+ return TRUE
+
+ if("delete_note")
+ var/datum/medical_note/old_note = locate(params["note_ref"]) in target.fields[DATACORE_NOTES_MEDICAL]
+ if(!old_note)
+ return FALSE
+
+ target.fields[DATACORE_NOTES_MEDICAL] -= old_note
+ qdel(old_note)
+
+ return TRUE
+
+ if("set_physical_status")
+ var/physical_status = params["physical_status"]
+ if(!physical_status || !(physical_status in PHYSICAL_STATUSES))
+ return FALSE
+
+ target.fields[DATACORE_PHYSICAL_HEALTH] = physical_status
+
+ return TRUE
+
+ if("set_mental_status")
+ var/mental_status = params["mental_status"]
+ if(!mental_status || !(mental_status in MENTAL_STATUSES))
+ return FALSE
+
+ target.fields[DATACORE_MENTAL_HEALTH] = mental_status
+
+ return TRUE
+
+ return FALSE
+
+/obj/machinery/computer/records/med/syndie
+ icon_keyboard = "syndie_key"
+
+/obj/machinery/computer/records/med/laptop
+ name = "medical laptop"
+ desc = "A cheap Nanotrasen medical laptop, it functions as a medical records computer. It's bolted to the table."
+ icon_state = "laptop"
+ icon_screen = "medlaptop"
+ icon_keyboard = "laptop_key"
+ pass_flags = PASSTABLE
+ unique_icon = TRUE
+
diff --git a/code/game/machinery/computer/record/records.dm b/code/game/machinery/computer/record/records.dm
new file mode 100644
index 000000000000..bd4ccd483e5a
--- /dev/null
+++ b/code/game/machinery/computer/record/records.dm
@@ -0,0 +1,164 @@
+/obj/machinery/computer/records
+ name = "records console"
+ desc = "This can be used to check records."
+ icon_screen = "medcomp"
+ icon_keyboard = "med_key"
+ req_one_access = list()
+ circuit = /obj/item/circuitboard/computer
+ var/datum/overmap/ship/controlled/linked_ship
+
+/obj/machinery/computer/records/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
+ . = ..()
+ linked_ship = port.current_ship
+
+/obj/machinery/computer/records/disconnect_from_shuttle(obj/docking_port/mobile/port)
+ . = ..()
+ linked_ship = null
+
+/*
+/obj/machinery/computer/records/attacked_by(obj/item/attacking_item, mob/living/user)
+ . = ..()
+ if(!istype(attacking_item, /obj/item/photo))
+ return
+ insert_new_record(user, attacking_item)
+*/
+
+/obj/machinery/computer/records/ui_data(mob/user)
+ var/list/data = ..()
+
+ var/has_access = (authenticated && isliving(user)) || isAdminGhostAI(user)
+ data["authenticated"] = has_access
+ data["library_name"] = linked_ship.name
+ if(!has_access)
+ return data
+
+ return data
+
+/obj/machinery/computer/records/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+ var/mob/user = ui.user
+
+ var/datum/data/record/target
+ if(params["record_ref"])
+ target = locate(params["record_ref"]) in SSdatacore.get_records(linked_ship)
+
+ switch(action)
+ if("expunge_record")
+ if(!target)
+ return FALSE
+
+ expunge_record_info(target)
+ balloon_alert(user, "record expunged")
+ investigate_log("[key_name(user)] expunged the record of [target[DATACORE_NAME]].", INVESTIGATE_RECORDS)
+ return TRUE
+
+ if("purge_records")
+ SSdatacore.wipe_records(linked_ship)
+ return TRUE
+
+ if("new_record")
+ var/name = stripped_input(user, "Enter the name of the new record.", "New Record", "", MAX_NAME_LEN)
+ if(!name)
+ return FALSE
+
+ SSdatacore.create_record(linked_ship, name)
+ balloon_alert(user, "record created")
+ return TRUE
+
+ if("login")
+ authenticated = secure_login(usr)
+ investigate_log("[key_name(usr)] [authenticated ? "successfully logged" : "failed to log"] into the [src].", INVESTIGATE_RECORDS)
+ return TRUE
+
+ if("logout")
+ balloon_alert(usr, "logged out")
+ playsound(src, 'sound/machines/terminal_off.ogg', 70, TRUE)
+ authenticated = FALSE
+
+ return TRUE
+
+ if("edit_field")
+ target = locate(params["ref"]) in SSdatacore.get_records(linked_ship)
+ var/field = params["field"]
+ if(!field || !(field in target.fields))
+ return FALSE
+
+ var/value = trim(params["value"], MAX_BROADCAST_LEN)
+ investigate_log("[key_name(usr)] changed the field: \"[field]\" with value: \"[target.fields[field]]\" to new value: \"[value || "Unknown"]\"", INVESTIGATE_RECORDS)
+ target.fields[field] = value || "Unknown"
+
+ return TRUE
+
+ if("view_record")
+ if(!target)
+ return FALSE
+
+ playsound(src, "sound/machines/terminal_button0[rand(1, 8)].ogg", 50, TRUE)
+ balloon_alert(usr, "viewing record for [target.fields[DATACORE_NAME]]")
+ return TRUE
+
+ return FALSE
+
+/obj/machinery/computer/records/proc/secure_login(mob/user)
+ if(!is_operational)
+ return FALSE
+
+ if(!allowed(user))
+ balloon_alert(user, "access denied")
+ return FALSE
+
+ balloon_alert(user, "logged in")
+ playsound(src, 'sound/machines/terminal_on.ogg', 70, TRUE)
+
+ return TRUE
+
+/// Deletes medical information from a record.
+/obj/machinery/computer/records/proc/expunge_record_info(datum/data/record/target)
+ if(!target)
+ return FALSE
+
+ target.fields[DATACORE_NAME] = "Unknown"
+ target.fields[DATACORE_AGE] = 18
+ target.fields[DATACORE_GENDER] = "Unknown"
+ target.fields[DATACORE_SPECIES] = "Unknown"
+ target.fields[DATACORE_BLOOD_TYPE] = pick(list("A+", "A-", "B+", "B-", "O+", "O-", "AB+", "AB-"))
+ target.fields[DATACORE_BLOOD_DNA] = "Unknown"
+ target.fields[DATACORE_DISABILITIES] = ""
+ target.fields[DATACORE_DISABILITIES_DETAILS] = ""
+ target.fields[DATACORE_PHYSICAL_HEALTH] = ""
+ target.fields[DATACORE_MENTAL_HEALTH] = ""
+ target.fields[DATACORE_RANK] = "Unknown"
+
+ return TRUE
+
+/*
+/obj/machinery/computer/records/proc/insert_new_record(mob/user, obj/item/photo/mugshot)
+ if(!mugshot || !is_operational)
+ return FALSE
+
+ if(!authenticated && !allowed(user))
+ balloon_alert(user, "access denied")
+ playsound(src, 'sound/machines/terminal_error.ogg', 70, TRUE)
+ return FALSE
+
+ if(mugshot.picture.psize_x > world.icon_size || mugshot.picture.psize_y > world.icon_size)
+ balloon_alert(user, "photo too large!")
+ playsound(src, 'sound/machines/terminal_error.ogg', 70, TRUE)
+ return FALSE
+
+ var/trimmed = copytext(mugshot.name, 9, MAX_NAME_LEN) // Remove "photo - "
+ var/name = stripped_input(user, "Enter the name of the new record.", "New Record", trimmed, MAX_NAME_LEN)
+ if(!name || !is_operational || !mugshot || QDELETED(mugshot) || QDELETED(src))
+ return FALSE
+
+ var/datum/data/record/new_record = SSdatacore.create_record(linked_ship, name)
+ new_record.fields[DATACORE_APPEARANCE] = mugshot.picture.picture_image
+ balloon_alert(user, "record created")
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 70, TRUE)
+
+ qdel(mugshot)
+
+ return TRUE
+*/
diff --git a/code/game/machinery/computer/record/security.dm b/code/game/machinery/computer/record/security.dm
new file mode 100644
index 000000000000..29d8f9e2164d
--- /dev/null
+++ b/code/game/machinery/computer/record/security.dm
@@ -0,0 +1,114 @@
+/obj/machinery/computer/records/sec//TODO:SANITY
+ name = "security records console"
+ desc = "Used to view and edit personnel's security records."
+ icon_screen = "security"
+ icon_keyboard = "security_key"
+ req_one_access = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS)
+ circuit = /obj/item/circuitboard/computer/secure_data
+ light_color = COLOR_SOFT_RED
+
+/obj/machinery/computer/records/sec/ui_interact(mob/user, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+ ui = SStgui.try_update_ui(user, src, ui)
+ if (!ui)
+ ui = new(user, src, "SecurityRecords")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/obj/machinery/computer/records/sec/ui_data(mob/user)
+ var/list/data = ..()
+
+ data["current_user"] = user.name
+
+ var/list/records = list()
+ for(var/datum/data/record/target in SSdatacore.get_records(linked_ship))
+ var/list/crimes = list()
+ for(var/datum/data/crime/crime in target.fields[DATACORE_CRIMES])
+ crimes += list(list(
+ author = crime.author,
+ crime_ref = REF(crime),
+ details = crime.crimeDetails,
+ name = crime.crimeName,
+ time = crime.time,
+ ))
+ records += list(list(
+ age = target.fields[DATACORE_AGE],
+ record_ref = REF(target),
+ fingerprint = target.fields[DATACORE_FINGERPRINT],
+ gender = target.fields[DATACORE_GENDER],
+ name = target.fields[DATACORE_NAME],
+ rank = target.fields[DATACORE_RANK],
+ species = target.fields[DATACORE_SPECIES],
+ wanted_status = target.fields[DATACORE_CRIMINAL_STATUS],
+ security_note = target.fields[DATACORE_NOTES_SECURITY],
+ ))
+
+ data["records"] = records
+
+ return data
+
+/obj/machinery/computer/records/sec/ui_static_data(mob/user)
+ var/list/data = list()
+ data["min_age"] = AGE_MIN
+ data["max_age"] = AGE_MAX
+ data["available_statuses"] = WANTED_STATUSES
+ return data
+
+/obj/machinery/computer/records/sec/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ var/mob/user = ui.user
+
+ var/datum/data/record/target
+ if(params["record_ref"])
+ target = locate(params["record_ref"]) in SSdatacore.get_records(linked_ship)
+
+ if(!target)
+ return FALSE
+
+ switch(action)
+ if("add_crime")
+ //add_crime(user, target, params)
+ return TRUE
+
+ if("edit_crime")
+ //edit_crime(user, target, params)
+ return TRUE
+
+ if("invalidate_crime")
+ //invalidate_crime(user, target, params)
+ return TRUE
+
+ if("set_note")
+ var/note = trim(params["security_note"], MAX_MESSAGE_LEN)
+ investigate_log("[user] has changed the security note of record: \"[target]\" from \"[target.fields[DATACORE_NOTES_SECURITY]]\" to \"[note]\".")
+ target.fields[DATACORE_NOTES_SECURITY] = note
+ return TRUE
+
+ if("set_wanted_status")
+ var/wanted_status = params["wanted_status"]
+ if(!wanted_status || !(wanted_status in WANTED_STATUSES))
+ return FALSE
+
+ investigate_log("[target.name] has been set from [target.fields[DATACORE_CRIMINAL_STATUS]] to [wanted_status] by [key_name(usr)].", INVESTIGATE_RECORDS)
+ target.fields[DATACORE_CRIMINAL_STATUS] = wanted_status
+
+ return TRUE
+
+ return FALSE
+
+/obj/machinery/computer/records/sec/syndie
+ icon_keyboard = "syndie_key"
+
+/obj/machinery/computer/records/sec/laptop
+ name = "security laptop"
+ desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table."
+ icon_state = "laptop"
+ icon_screen = "seclaptop"
+ icon_keyboard = "laptop_key"
+ pass_flags = PASSTABLE
+ unique_icon = TRUE
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
deleted file mode 100644
index 37759d04b13e..000000000000
--- a/code/game/machinery/computer/security.dm
+++ /dev/null
@@ -1,783 +0,0 @@
-/obj/machinery/computer/secure_data//TODO:SANITY
- name = "security records console"
- desc = "Used to view and edit personnel's security records."
- icon_screen = "security"
- icon_keyboard = "security_key"
- req_one_access = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS)
- circuit = /obj/item/circuitboard/computer/secure_data
- light_color = COLOR_SOFT_RED
- var/rank = null
- var/screen = null
- var/datum/data/record/active1 = null
- var/datum/data/record/active2 = null
- var/temp = null
- var/printing = null
- var/can_change_id = 0
- var/list/Perp
- var/tempname = null
- //Sorting Variables
- var/sortBy = "name"
- var/order = 1 // -1 = Descending - 1 = Ascending
-
-
-/obj/machinery/computer/secure_data/syndie
- icon_keyboard = "syndie_key"
-
-/obj/machinery/computer/secure_data/laptop
- name = "security laptop"
- desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table."
- icon_state = "laptop"
- icon_screen = "seclaptop"
- icon_keyboard = "laptop_key"
- pass_flags = PASSTABLE
- unique_icon = TRUE
-
-//Someone needs to break down the dat += into chunks instead of long ass lines.
-/obj/machinery/computer/secure_data/ui_interact(mob/user)
- . = ..()
- if(isliving(user))
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- if(src.z > 6)
- to_chat(user, "Unable to establish a connection : \black You're too far away from the station!")
- return
- var/dat
-
- if(temp)
- dat = "[temp] Clear Screen "
- else
- dat = ""
- if(authenticated)
- switch(screen)
- if(1)
-
- //body tag start + onload and onkeypress (onkeyup) javascript event calls
- dat += ""
- //search bar javascript
- dat += {"
-
-
-
-
-
-
-
- "}
- dat += {"
-"}
- dat += "New Record "
- //search bar
- dat += {"
-
- "}
- dat += {"
-
-
-
-
-
-
-Name
-ID
-Rank
-Fingerprints
-Criminal Status
- "}
- if(!isnull(GLOB.data_core.general))
- for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order))
- var/crimstat = ""
- for(var/datum/data/record/E in GLOB.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:#990000;'"
- if("Incarcerated")
- background = "'background-color:#CD6500;'"
- if("Paroled")
- background = "'background-color:#CD6500;'"
- if("Discharged")
- background = "'background-color:#006699;'"
- if("None")
- background = "'background-color:#4F7529;'"
- if("")
- background = "''" //"'background-color:#FFFFFF;'"
- crimstat = "No Record."
- dat += ""
- dat += text("[] ", R.fields["name"], R.fields["id"], R.fields["rank"], R.fields["fingerprint"], R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("[] ", R.fields["rank"])
- dat += text("[] ", R.fields["fingerprint"])
- dat += text("[] ", crimstat)
- dat += {"
-
-
- "}
- dat += "Record Maintenance "
- dat += "{Log Out} "
- if(2)
- dat += "Records Maintenance "
- dat += "Delete All Records Back "
- if(3)
- dat += "Security Record "
- if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P1 = active1.fields["photo_front"]
- user << browse_rsc(P1.picture.picture_image, "photo_front")
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P2 = active1.fields["photo_side"]
- user << browse_rsc(P2.picture.picture_image, "photo_side")
- dat += {""}
- else
- dat += " General Record Lost! "
- if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2)))
- dat += "Security Data "
- dat += " Criminal Status: [active2.fields["criminal"]] "
-
- dat += " Crimes: Add New "
-
- dat +={"
-
- Crime
- Details
- Author
- Time Added
- Del
- "}
- for(var/datum/data/crime/c in active2.fields["crim"])
- dat += "[c.crimeName] "
- if(!c.crimeDetails)
- dat += "\[+\] "
- else
- dat += "[c.crimeDetails] "
- dat += "[c.author] "
- dat += "[c.time] "
- dat += "\[X\] "
- dat += " "
- dat += "
"
-
- dat += " \nImportant Notes: \n\t [active2.fields["notes"]] "
- dat += "Comments/Log "
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- dat += (active2.fields[text("com_[]", counter)] + " ")
- if(active2.fields[text("com_[]", counter)] != "Deleted ")
- dat += text("Delete Entry ", 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 Print Missing Persons Poster Back "
- dat += "{Log Out} "
- else
- else
- dat += "{Log In} "
- var/datum/browser/popup = new(user, "secure_rec", "Security Records Console", 600, 400)
- popup.set_content(dat)
- popup.open()
- 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 .
- if(!(GLOB.data_core.general.Find(active1)))
- active1 = null
- if(!(GLOB.data_core.security.Find(active2)))
- active2 = null
- if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || isAdminGhostAI(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("Log Out")
- authenticated = null
- screen = null
- active1 = null
- active2 = null
- playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
-
- if("Log In")
- var/mob/M = usr
- var/obj/item/card/id/I = M.get_idcard(TRUE)
- if(issilicon(M))
- var/mob/living/silicon/borg = M
- active1 = null
- active2 = null
- authenticated = borg.name
- rank = "AI"
- screen = 1
- else if(isAdminGhostAI(M))
- active1 = null
- active2 = null
- authenticated = M.client.holder.admin_signature
- rank = "Central Command"
- screen = 1
- else if(I && check_access(I))
- active1 = null
- active2 = null
- authenticated = I.registered_name
- rank = I.assignment
- screen = 1
- else
- to_chat(usr, "Unauthorized Access. ")
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
-
-//RECORD FUNCTIONS
- if("Record Maintenance")
- screen = 2
- active1 = null
- active2 = null
-
- if("Browse Record")
- var/datum/data/record/R = locate(href_list["d_rec"]) in GLOB.data_core.general
- if(!R)
- temp = "Record Not Found!"
- else
- active1 = active2 = R
- for(var/datum/data/record/E in GLOB.data_core.security)
- if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- active2 = E
- screen = 3
-
- if("Print Record")
- if(!(printing))
- printing = 1
- GLOB.data_core.securityPrintCount++
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- sleep(30)
- var/obj/item/paper/printed_paper = new /obj/item/paper(loc)
- var/final_paper_text = "Security Record - (SR-[GLOB.data_core.securityPrintCount]) "
- if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))
- final_paper_text += text("Name: [] ID: [] \nGender: [] \nAge: [] ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"])
- final_paper_text += "\nSpecies: [active1.fields["species"]] "
- final_paper_text += text("\nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"])
- else
- final_paper_text += "General Record Lost! "
- if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2)))
- final_paper_text += text(" \nSecurity Data \nCriminal Status: []", active2.fields["criminal"])
-
- final_paper_text += " \n \nCrimes: \n"
- final_paper_text +={"
-
-Crime
-Details
-Author
-Time Added
- "}
- for(var/datum/data/crime/c in active2.fields["crim"])
- final_paper_text += "[c.crimeName] "
- final_paper_text += "[c.crimeDetails] "
- final_paper_text += "[c.author] "
- final_paper_text += "[c.time] "
- final_paper_text += " "
- final_paper_text += "
"
-
- final_paper_text += text(" \nImportant Notes: \n\t[] \n \nComments/Log ", active2.fields["notes"])
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- final_paper_text += text("[] ", active2.fields[text("com_[]", counter)])
- counter++
- printed_paper.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, active1.fields["name"])
- else
- final_paper_text += "Security Record Lost! "
- printed_paper.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, "Record Lost")
- final_paper_text += ""
- printed_paper.add_raw_text(final_paper_text)
- printed_paper.update_appearance()
- printing = null
- if("Print Poster")
- if(!(printing))
- var/wanted_name = stripped_input(usr, "Please enter an alias for the criminal:", "Print Wanted Poster", active1.fields["name"])
- 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/list/crimes = active2.fields["crim"]
- if(crimes.len)
- default_description += "\n[wanted_name] is wanted for the following crimes:\n"
- for(var/datum/data/crime/c in active2.fields["crim"])
- default_description += "\n[c.crimeName]\n"
- default_description += "[c.crimeDetails]\n"
-
- var/headerText = stripped_input(usr, "Please enter Poster Heading (Max 7 Chars):", "Print Wanted Poster", "WANTED", 8)
-
- var/info = stripped_multiline_input(usr, "Please input a description for the poster:", "Print Wanted Poster", default_description, null)
- if(info)
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- printing = 1
- sleep(30)
- if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists.
- var/obj/item/photo/photo = active1.fields["photo_front"]
- new /obj/item/poster/wanted(loc, photo.picture.picture_image, wanted_name, info, headerText)
- printing = 0
- if("Print Missing")
- if(!(printing))
- var/missing_name = stripped_input(usr, "Please enter an alias for the missing person:", "Print Missing Persons Poster", active1.fields["name"])
- if(missing_name)
- var/default_description = "A poster declaring [missing_name] to be a missing individual, missed by Nanotrasen. Report any sightings to security immediately."
-
- var/headerText = stripped_input(usr, "Please enter Poster Heading (Max 7 Chars):", "Print Missing Persons Poster", "MISSING", 8)
-
- var/info = stripped_multiline_input(usr, "Please input a description for the poster:", "Print Missing Persons Poster", default_description, null)
- if(info)
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- printing = 1
- sleep(30)
- if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists.
- var/obj/item/photo/photo = active1.fields["photo_front"]
- new /obj/item/poster/wanted/missing(loc, photo.picture.picture_image, missing_name, info, headerText)
- 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")
- investigate_log("[key_name(usr)] has purged all the security records.", INVESTIGATE_RECORDS)
- for(var/datum/data/record/R in GLOB.data_core.security)
- qdel(R)
- GLOB.data_core.security.Cut()
- temp = "All Security records deleted."
-
- if("Add Entry")
- if(!(istype(active2, /datum/data/record)))
- return
- var/a2 = active2
- var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null)
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], [] []", src.authenticated, src.rank, station_time_timestamp(), sector_datestamp(shortened = TRUE), 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))))
- var/datum/data/record/R = new /datum/data/record()
- R.fields["name"] = active1.fields["name"]
- R.fields["id"] = active1.fields["id"]
- R.name = text("Security Record #[]", R.fields["id"])
- R.fields["criminal"] = "None"
- R.fields["crim"] = list()
- R.fields["notes"] = "No notes."
- GLOB.data_core.security += R
- active2 = R
- screen = 3
-
- if("New Record (General)")
- //General Record
- var/datum/data/record/G = new /datum/data/record()
- G.fields["name"] = "New Record"
- G.fields["id"] = "[num2hex(rand(1, 1.6777215E7), 6)]"
- G.fields["rank"] = "Unassigned"
- G.fields["gender"] = "Male"
- G.fields["age"] = "Unknown"
- G.fields["species"] = "Human"
- G.fields["photo_front"] = new /icon()
- G.fields["photo_side"] = new /icon()
- G.fields["fingerprint"] = "?????"
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- GLOB.data_core.general += G
- active1 = G
-
- //Security Record
- var/datum/data/record/R = new /datum/data/record()
- R.fields["name"] = active1.fields["name"]
- R.fields["id"] = active1.fields["id"]
- R.name = text("Security Record #[]", R.fields["id"])
- R.fields["criminal"] = "None"
- R.fields["crim"] = list()
- R.fields["notes"] = "No notes."
- GLOB.data_core.security += R
- active2 = R
-
- //Medical Record
- var/datum/data/record/M = new /datum/data/record()
- M.fields["id"] = active1.fields["id"]
- M.fields["name"] = active1.fields["name"]
- M.fields["blood_type"] = "?"
- M.fields["b_dna"] = "?????"
- 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."
- GLOB.data_core.medical += M
-
-
-
-//FIELD FUNCTIONS
- if("Edit Field")
- var/a1 = active1
- var/a2 = active2
-
- switch(href_list["field"])
- if("name")
- if(istype(active1, /datum/data/record) || istype(active2, /datum/data/record))
- var/t1 = stripped_input(usr, "Please input name:", "Secure. records", active1.fields["name"], MAX_MESSAGE_LEN)
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- if(istype(active1, /datum/data/record))
- active1.fields["name"] = t1
- if(istype(active2, /datum/data/record))
- active2.fields["name"] = t1
- if("id")
- if(istype(active2, /datum/data/record) || istype(active1, /datum/data/record))
- var/t1 = stripped_input(usr, "Please input id:", "Secure. records", active1.fields["id"], null)
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- if(istype(active1, /datum/data/record))
- active1.fields["id"] = t1
- if(istype(active2, /datum/data/record))
- active2.fields["id"] = t1
- if("fingerprint")
- if(istype(active1, /datum/data/record))
- var/t1 = stripped_input(usr, "Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null)
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- active1.fields["fingerprint"] = t1
- if("gender")
- if(istype(active1, /datum/data/record))
- if(active1.fields["gender"] == "Male")
- active1.fields["gender"] = "Female"
- else if(active1.fields["gender"] == "Female")
- active1.fields["gender"] = "Other"
- else
- active1.fields["gender"] = "Male"
- if("age")
- if(istype(active1, /datum/data/record))
- var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num|null
-
- if (!t1)
- return
-
- if(!canUseSecurityRecordsConsole(usr, "age", a1))
- return
- active1.fields["age"] = t1
- if("species")
- if(istype(active1, /datum/data/record))
- var/t1 = input("Select a species", "Species Selection") as null|anything in GLOB.roundstart_races
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- active1.fields["species"] = t1
- if("show_photo_front")
- if(active1.fields["photo_front"])
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_front"]
- P.show(usr)
- if("upd_photo_front")
- var/obj/item/photo/photo = get_photo(usr)
- if(photo)
- qdel(active1.fields["photo_front"])
- //Lets center it to a 32x32.
- var/icon/I = photo.picture.picture_image
- var/w = I.Width()
- var/h = I.Height()
- var/dw = w - 32
- var/dh = w - 32
- I.Crop(dw/2, dh/2, w - dw/2, h - dh/2)
- active1.fields["photo_front"] = photo
- if("print_photo_front")
- if(active1.fields["photo_front"])
- if(istype(active1.fields["photo_front"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_front"]
- print_photo(P.picture.picture_image, active1.fields["name"])
- if("show_photo_side")
- if(active1.fields["photo_side"])
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_side"]
- P.show(usr)
- if("upd_photo_side")
- var/obj/item/photo/photo = get_photo(usr)
- if(photo)
- qdel(active1.fields["photo_side"])
- //Lets center it to a 32x32.
- var/icon/I = photo.picture.picture_image
- var/w = I.Width()
- var/h = I.Height()
- var/dw = w - 32
- var/dh = w - 32
- I.Crop(dw/2, dh/2, w - dw/2, h - dh/2)
- active1.fields["photo_side"] = photo
- if("print_photo_side")
- if(active1.fields["photo_side"])
- if(istype(active1.fields["photo_side"], /obj/item/photo))
- var/obj/item/photo/P = active1.fields["photo_side"]
- print_photo(P.picture.picture_image, active1.fields["name"])
- if("crim_add")
- if(istype(active1, /datum/data/record))
- var/t1 = stripped_input(usr, "Please input crime names:", "Secure. records", "", null)
- var/t2 = stripped_input(usr, "Please input crime details:", "Secure. records", "", null)
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, station_time_timestamp())
- GLOB.data_core.addCrime(active1.fields["id"], crime)
- investigate_log("New Crime: [t1] : [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- if("crim_delete")
- if(istype(active1, /datum/data/record))
- if(href_list["cdataid"])
- if(!canUseSecurityRecordsConsole(usr, "delete", null, a2))
- return
- GLOB.data_core.removeCrime(active1.fields["id"],href_list["cdataid"])
- if("add_details")
- if(istype(active1, /datum/data/record))
- if(href_list["cdataid"])
- var/t1 = stripped_input(usr, "Please input crime details:", "Secure. records", "", null)
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- GLOB.data_core.addCrimeDetails(active1.fields["id"], href_list["cdataid"], t1)
- investigate_log("New Crime details: [t1] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- if("notes")
- if(istype(active2, /datum/data/record))
- var/t1 = stripped_input(usr, "Please summarize notes:", "Secure. records", active2.fields["notes"], null)
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["notes"] = t1
- if("criminal")
- if(istype(active2, /datum/data/record))
- temp = "Criminal Status: "
- temp += ""
- if("rank")
- var/list/L = list( "Head of Personnel", "Captain", "AI", "Central Command" )
- //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 get_all_jobs())
- temp += "[rank] "
- temp += " "
- else
- alert(usr, "You do not have the required rank to do this!")
-//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"] = strip_html(href_list["rank"])
- if(href_list["rank"] in get_all_jobs())
- active1.fields["real_rank"] = href_list["real_rank"]
-
- if("Change Criminal Status")
- if(active2)
- var/old_field = active2.fields["criminal"]
- switch(href_list["criminal2"])
- if("none")
- active2.fields["criminal"] = "None"
- if("arrest")
- active2.fields["criminal"] = "*Arrest*"
- if("incarcerated")
- active2.fields["criminal"] = "Incarcerated"
- if("paroled")
- active2.fields["criminal"] = "Paroled"
- if("released")
- active2.fields["criminal"] = "Discharged"
- investigate_log("[active1.fields["name"]] has been set from [old_field] to [active2.fields["criminal"]] by [key_name(usr)].", INVESTIGATE_RECORDS)
- for(var/i in GLOB.human_list)
- var/mob/living/carbon/human/H = i
- H.sec_hud_set_security_status()
- if("Delete Record (Security) Execute")
- investigate_log("[key_name(usr)] has deleted the security records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
- if(active2)
- qdel(active2)
- active2 = null
-
- if("Delete Record (ALL) Execute")
- if(active1)
- investigate_log("[key_name(usr)] has deleted all records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
- qdel(R)
- break
- qdel(active1)
- active1 = null
-
- if(active2)
- qdel(active2)
- active2 = null
- 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/get_photo(mob/user)
- var/obj/item/photo/P = null
- if(issilicon(user))
- var/mob/living/silicon/tempAI = user
- var/datum/picture/selection = tempAI.GetPhoto(user)
- if(selection)
- P = new(null, selection)
- else if(istype(user.get_active_held_item(), /obj/item/photo))
- P = user.get_active_held_item()
- return P
-
-/obj/machinery/computer/secure_data/proc/print_photo(icon/temp, person_name)
- if (printing)
- return
- printing = TRUE
- sleep(20)
- var/obj/item/photo/P = new/obj/item/photo(drop_location())
- var/datum/picture/toEmbed = new(name = person_name, desc = "The photo on file for [person_name].", image = temp)
- P.set_picture(toEmbed, TRUE, TRUE)
- P.pixel_x = rand(-10, 10)
- P.pixel_y = rand(-10, 10)
- printing = FALSE
-
-/obj/machinery/computer/secure_data/emp_act(severity)
- . = ..()
-
- if(machine_stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_SELF)
- return
-
- for(var/datum/data/record/R in GLOB.data_core.security)
- if(prob(10/severity))
- switch(rand(1,8))
- if(1)
- if(prob(10))
- R.fields["name"] = "[pick(lizard_name(MALE),lizard_name(FEMALE))]"
- else
- R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
- if(2)
- R.fields["gender"] = pick("Male", "Female", "Other")
- if(3)
- R.fields["age"] = rand(5, 85)
- if(4)
- R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Paroled", "Discharged")
- if(5)
- R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit")
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- if(7)
- R.fields["species"] = pick(GLOB.roundstart_races)
- if(8)
- var/datum/data/record/G = pick(GLOB.data_core.general)
- R.fields["photo_front"] = G.fields["photo_front"]
- R.fields["photo_side"] = G.fields["photo_side"]
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
-/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2)
- if(user)
- if(authenticated)
- if(user.canUseTopic(src, !issilicon(user)))
- if(!trim(message1))
- return 0
- if(!record1 || record1 == active1)
- if(!record2 || record2 == active2)
- return 1
- return 0
diff --git a/code/game/machinery/computer/warrant.dm b/code/game/machinery/computer/warrant.dm
index a5b72e1aae40..f918bc4db2a1 100644
--- a/code/game/machinery/computer/warrant.dm
+++ b/code/game/machinery/computer/warrant.dm
@@ -17,7 +17,7 @@
if(current)
var/background
var/notice = ""
- switch(current.fields["criminal"])
+ switch(current.fields[DATACORE_CRIMINAL_STATUS])
if("*Arrest*")
background = "background-color:#990000;"
notice = " **REPORT TO THE BRIG**"
@@ -33,12 +33,12 @@
background = "''" //"'background-color:#FFFFFF;'"
dat += "Warrant Data "
dat += {"
- Name: [current.fields["name"]]
- ID: [current.fields["id"]]
+ Name: [current.fields[DATACORE_NAME]]
+ ID: [current.fields[DATACORE_ID]]
"}
dat += {"Criminal Status:
- [current.fields["criminal"]][notice]
+ [current.fields[DATACORE_CRIMINAL_STATUS]][notice]
"}
dat += " Crimes:"
@@ -49,7 +49,7 @@
Author
Time Added
"}
- for(var/datum/data/crime/c in current.fields["crim"])
+ for(var/datum/data/crime/c in current.fields[DATACORE_CRIMES])
dat += {"[c.crimeName]
[c.crimeDetails]
[c.author]
@@ -74,8 +74,8 @@
var/obj/item/card/id/scan = M.get_idcard(TRUE)
authenticated = scan.registered_name
if(authenticated)
- for(var/datum/data/record/R in GLOB.data_core.security)
- if(R.fields["name"] == authenticated)
+ for(var/datum/data/record/R in SSdatacore.get_records(DATACORE_RECORDS_OUTPOST))
+ if(R.fields[DATACORE_NAME] == authenticated)
current = R
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
if("Logout")
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 6b63a3ae83b8..830352fe657e 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -327,17 +327,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod/retro, 17)
mob_occupant.mind.special_role = null
// Delete them from datacore.
- var/announce_rank = null
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if((R.fields["name"] == mob_occupant.real_name))
- qdel(R)
- for(var/datum/data/record/T in GLOB.data_core.security)
- if((T.fields["name"] == mob_occupant.real_name))
- qdel(T)
- for(var/datum/data/record/G in GLOB.data_core.general)
- if((G.fields["name"] == mob_occupant.real_name))
- announce_rank = G.fields["rank"]
- qdel(G)
+ var/announce_rank = SSdatacore.get_record_by_name(mob_occupant.real_name, DATACORE_RECORDS_OUTPOST)?[DATACORE_RANK]
+ SSdatacore.demanifest(mob_occupant.real_name)
var/datum/overmap/ship/controlled/original_ship = mob_occupant.mind.original_ship.resolve()
original_ship.manifest -= mob_occupant.real_name
diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm
index 3632c204f36b..575ab512ebc9 100644
--- a/code/game/machinery/gulag_teleporter.dm
+++ b/code/game/machinery/gulag_teleporter.dm
@@ -157,7 +157,7 @@ The console is located at computer/gulag_teleporter.dm
if(id)
prisoner.equip_to_appropriate_slot(id)
if(R)
- R.fields["criminal"] = "Incarcerated"
+ R.fields[DATACORE_CRIMINAL_STATUS] = "Incarcerated"
/obj/item/circuitboard/machine/gulag_teleporter
name = "labor camp teleporter (Machine Board)"
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 3f5620c35f06..49efa36737ec 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -555,8 +555,8 @@ DEFINE_BITFIELD(turret_flags, list(
if(turret_flags & TURRET_FLAG_SHOOT_CRIMINALS) //if the turret can check the records, check if they are set to *Arrest* on records
var/perpname = perp.get_face_name(perp.get_id_name())
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
- if(!R || (R.fields["criminal"] == "*Arrest*"))
+ var/datum/data/record/R = SSdatacore.get_record_by_name(perpname, DATACORE_RECORDS_OUTPOST)
+ if(!R || (R.fields[DATACORE_CRIMINAL_STATUS] == "*Arrest*"))
threatcount += 4
if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)))
diff --git a/code/game/machinery/scan_gate.dm b/code/game/machinery/scan_gate.dm
index cf83233598aa..681058dced13 100644
--- a/code/game/machinery/scan_gate.dm
+++ b/code/game/machinery/scan_gate.dm
@@ -105,8 +105,8 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/perpname = H.get_face_name(H.get_id_name())
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
- if(!R || (R.fields["criminal"] == "*Arrest*"))
+ var/datum/data/record/R = SSdatacore.get_record_by_name(perpname, DATACORE_RECORDS_OUTPOST)
+ if(!R || (R.fields[DATACORE_CRIMINAL_STATUS] == "*Arrest*"))
beep = TRUE
if(SCANGATE_MINDSHIELD)
if(HAS_TRAIT(M, TRAIT_MINDSHIELD))
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index 9aece73946cc..f289ad4d35e4 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -232,7 +232,7 @@
/obj/item/circuitboard/computer/med_data
name = "Medical Records Console (Computer Board)"
icon_state = "medical"
- build_path = /obj/machinery/computer/med_data
+ build_path = /obj/machinery/computer/records/med
/obj/item/circuitboard/computer/operating
name = "Operating Computer (Computer Board)"
@@ -322,11 +322,6 @@
//Security
-/obj/item/circuitboard/computer/gulag_teleporter_console
- name = "Labor Camp teleporter console (Computer Board)"
- icon_state = "security"
- build_path = /obj/machinery/computer/prisoner/gulag_teleporter_computer
-
/obj/item/circuitboard/computer/prisoner
name = "Prisoner Management Console (Computer Board)"
icon_state = "security"
@@ -335,7 +330,7 @@
/obj/item/circuitboard/computer/secure_data
name = "Security Records Console (Computer Board)"
icon_state = "security"
- build_path = /obj/machinery/computer/secure_data
+ build_path = /obj/machinery/computer/records/sec
/obj/item/circuitboard/computer/warrant
name = "Security Warrant Viewer (Computer Board)"
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index e259e56ccd0e..3e9d8a668fe0 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -248,10 +248,6 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "[PDAIMG(status)] Set Status Display "
if(cartridge.access & CART_ENGINE)
dat += "[PDAIMG(power)] Power Monitor "
- if(cartridge.access & CART_MEDICAL)
- dat += "[PDAIMG(medical)] Medical Records "
- if(cartridge.access & CART_SECURITY)
- dat += "[PDAIMG(cuffs)] Security Records "
if(cartridge.access & CART_QUARTERMASTER)
dat += "[PDAIMG(crate)] Supply Records "
@@ -361,12 +357,6 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += tnote
dat += " "
- if(41) //crew manifest
- dat += "Crew Manifest "
- dat += ""
- dat += SSovermap.get_manifest_html()
- dat += " "
-
if(3)
dat += "[PDAIMG(atmos)] Atmospheric Readings "
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 65bda2aa1f54..28a35332b334 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -231,10 +231,6 @@ Code:
+
+
Send Signal "}
- if (41) //crew manifest
- menu = "[PDAIMG(notes)] Crew Manifest "
- menu += "[SSovermap.get_manifest_html()] "
-
if (42) //status displays
menu = "[PDAIMG(status)] Station Status Display Interlink "
@@ -313,99 +309,6 @@ Code:
menu += ""
- if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working.
- menu = "[PDAIMG(medical)] Medical Record List "
- if(GLOB.data_core.general)
- for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
- menu += "[PDAIMG(medical)] [R.fields["id"]]: [R.fields["name"]] "
- menu += " "
- if(441)
- menu = "[PDAIMG(medical)] Medical Record "
-
- if(active1 in GLOB.data_core.general)
- menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]] "
- menu += "Gender: [active1.fields["gender"]] "
- menu += "Age: [active1.fields["age"]] "
- menu += "Rank: [active1.fields["rank"]] "
- menu += "Fingerprint: [active1.fields["fingerprint"]] "
- menu += "Physical Status: [active1.fields["p_stat"]] "
- menu += "Mental Status: [active1.fields["m_stat"]] "
- else
- menu += "Record Lost! "
-
- menu += " "
-
- menu += "[PDAIMG(medical)] Medical Data "
- if(active2 in GLOB.data_core.medical)
- menu += "Blood Type: [active2.fields["blood_type"]] "
-
- menu += "Minor Disabilities: [active2.fields["mi_dis"]] "
- menu += "Details: [active2.fields["mi_dis_d"]] "
-
- menu += "Major Disabilities: [active2.fields["ma_dis"]] "
- menu += "Details: [active2.fields["ma_dis_d"]] "
-
- menu += "Allergies: [active2.fields["alg"]] "
- menu += "Details: [active2.fields["alg_d"]] "
-
- menu += "Current Diseases: [active2.fields["cdi"]] "
- menu += "Details: [active2.fields["cdi_d"]] "
-
- menu += "Important Notes: [active2.fields["notes"]] "
- else
- menu += "Record Lost! "
-
- menu += " "
- if (45) //security records
- menu = "[PDAIMG(cuffs)] Security Record List "
- if(GLOB.data_core.general)
- for (var/datum/data/record/R in sortRecord(GLOB.data_core.general))
- menu += "[PDAIMG(cuffs)] [R.fields["id"]]: [R.fields["name"]] "
-
- menu += " "
- if(451)
- menu = "[PDAIMG(cuffs)] Security Record "
-
- if(active1 in GLOB.data_core.general)
- menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]] "
- menu += "Gender: [active1.fields["gender"]] "
- menu += "Age: [active1.fields["age"]] "
- menu += "Rank: [active1.fields["rank"]] "
- menu += "Fingerprint: [active1.fields["fingerprint"]] "
- menu += "Physical Status: [active1.fields["p_stat"]] "
- menu += "Mental Status: [active1.fields["m_stat"]] "
- else
- menu += "Record Lost! "
-
- menu += " "
-
- menu += "[PDAIMG(cuffs)] Security Data "
- if(active3 in GLOB.data_core.security)
- menu += "Criminal Status: [active3.fields["criminal"]] "
-
- menu += text(" \nCrimes:")
-
- menu +={"
-
-Crime
-Details
-Author
-Time Added
- "}
- for(var/datum/data/crime/c in active3.fields["crim"])
- menu += "[c.crimeName] "
- menu += "[c.crimeDetails] "
- menu += "[c.author] "
- menu += "[c.time] "
- menu += " "
- menu += "
"
- menu += " \nImportant Notes: "
- menu += "[active3.fields["notes"]]"
- else
- menu += "Record Lost! "
-
- menu += " "
-
if (49) //janitorial locator
// hey there people, so there were two in world loops here that didnt have a timer assosciated with them.
// and instead of redoing this to not be actually god awful for perf and malcontent issues, I've removed it entirely.
@@ -469,22 +372,6 @@ Code:
return
switch(href_list["choice"])
- if("Medical Records")
- active1 = find_record("id", href_list["target"], GLOB.data_core.general)
- if(active1)
- active2 = find_record("id", href_list["target"], GLOB.data_core.medical)
- host_pda.mode = 441
- if(!active2)
- active1 = null
-
- if("Security Records")
- active1 = find_record("id", href_list["target"], GLOB.data_core.general)
- if(active1)
- active3 = find_record("id", href_list["target"], GLOB.data_core.security)
- host_pda.mode = 451
- if(!active3)
- active1 = null
-
if("Send Signal")
INVOKE_ASYNC(radio, TYPE_PROC_REF(/obj/item/integrated_signaler, send_activation))
diff --git a/code/modules/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm
index b1d68a719070..138dc8e36042 100644
--- a/code/modules/antagonists/traitor/equipment/contractor.dm
+++ b/code/modules/antagonists/traitor/equipment/contractor.dm
@@ -57,10 +57,6 @@
CONTRACT_PAYOUT_SMALL
)
- //What the fuck
- if(length(to_generate) > length(GLOB.data_core.locked))
- to_generate.Cut(1, length(GLOB.data_core.locked))
-
// We don't want the sum of all the payouts to be under this amount
var/lowest_TC_threshold = 30
diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm
index d6bbba359303..95846e9a1a8f 100644
--- a/code/modules/antagonists/traitor/syndicate_contract.dm
+++ b/code/modules/antagonists/traitor/syndicate_contract.dm
@@ -20,10 +20,10 @@
var/datum/data/record/record
if (contract.target)
- record = find_record("name", contract.target.name, GLOB.data_core.general)
+ record = SSdatacore.get_record_by_name(contract.target.name, DATACORE_RECORDS_OUTPOST)
if (record)
- target_rank = record.fields["rank"]
+ target_rank = record.fields[DATACORE_RANK]
else
target_rank = "Unknown"
diff --git a/code/modules/datacore/crime.dm b/code/modules/datacore/crime.dm
new file mode 100644
index 000000000000..1028ba9818e7
--- /dev/null
+++ b/code/modules/datacore/crime.dm
@@ -0,0 +1,9 @@
+/datum/data/crime
+ name = "crime"
+ var/crimeName = ""
+ var/crimeDetails = ""
+ var/author = ""
+ var/time = ""
+ var/fine = 0
+ var/paid = 0
+ var/dataId = 0
diff --git a/code/modules/datacore/library.dm b/code/modules/datacore/library.dm
new file mode 100644
index 000000000000..b2f5d0280249
--- /dev/null
+++ b/code/modules/datacore/library.dm
@@ -0,0 +1,21 @@
+/datum/data_library
+ var/list/datum/data/record/records = list()
+ var/list/datum/data/record/records_by_name = list()
+
+/// Returns a data record or null.
+/datum/data_library/proc/get_record_by_name(name)
+ RETURN_TYPE(/datum/data/record)
+
+ return records_by_name[name]
+
+/// Inject a record into this library.
+/datum/data_library/proc/inject_record(datum/data/record/new_record)
+ if(!istype(new_record))
+ CRASH("You fucked it this time!!!")
+
+ if(!new_record.fields[DATACORE_NAME])
+ CRASH("Cannot inject a record with no name!")
+
+ records += new_record
+ records_by_name[new_record.fields[DATACORE_NAME]] = new_record
+ new_record.library = src
diff --git a/code/modules/datacore/medical_note.dm b/code/modules/datacore/medical_note.dm
new file mode 100644
index 000000000000..a1843394c2ae
--- /dev/null
+++ b/code/modules/datacore/medical_note.dm
@@ -0,0 +1,15 @@
+/**
+ * Player-written medical note.
+ */
+/datum/medical_note
+ /// Player that wrote the note
+ var/author
+ /// Details of the note
+ var/content
+ /// Station timestamp
+ var/time
+
+/datum/medical_note/New(author = "Anonymous", content = "No details provided.")
+ src.author = author
+ src.content = content
+ src.time = station_time_timestamp()
diff --git a/code/modules/datacore/records.dm b/code/modules/datacore/records.dm
new file mode 100644
index 000000000000..ad06a81a0a9b
--- /dev/null
+++ b/code/modules/datacore/records.dm
@@ -0,0 +1,107 @@
+/datum/data
+ var/name = "data"
+
+/datum/data/record
+ name = "record"
+ /// A ref to the library we're contained in.
+ var/datum/data_library/library
+ /// The data
+ var/list/fields = list()
+
+/datum/data/record/Destroy(force, ...)
+ if(library)
+ library.records -= src
+ library.records_by_name -= fields["name"]
+ return ..()
+
+/// Creates a copy of the record, without it's library.
+/datum/data/record/proc/Copy()
+ var/datum/data/record/new_record = new type()
+ new_record.fields = fields.Copy()
+ return new_record
+
+
+/// A helper proc to get the front photo of a character from the record.
+/// Handles calling `get_photo()`, read its documentation for more information.
+/datum/data/record/proc/get_front_photo()
+ return get_photo("photo_front", SOUTH)
+
+/// A helper proc to get the side photo of a character from the record.
+/// Handles calling `get_photo()`, read its documentation for more information.
+/datum/data/record/proc/get_side_photo()
+ return get_photo("photo_side", WEST)
+
+
+/**
+ * You shouldn't be calling this directly, use `get_front_photo()` or `get_side_photo()`
+ * instead.
+ *
+ * This is the proc that handles either fetching (if it was already generated before) or
+ * generating (if it wasn't) the specified photo from the specified record. This is only
+ * intended to be used by records that used to try to access `fields["photo_front"]` or
+ * `fields["photo_side"]`, and will return an empty icon if there isn't any of the necessary
+ * fields.
+ *
+ * Arguments:
+ * * field_name - The name of the key in the `fields` list, of the record itself.
+ * * orientation - The direction in which you want the character appearance to be rotated
+ * in the outputed photo.
+ *
+ * Returns an empty `/icon` if there was no `character_appearance` entry in the `fields` list,
+ * returns the generated/cached photo otherwise.
+ */
+/datum/data/record/proc/get_photo(field_name, orientation)
+ if(!field_name)
+ return
+
+ if(!fields[DATACORE_APPEARANCE])
+ return new /icon()
+
+ var/mutable_appearance/character_appearance = fields[DATACORE_APPEARANCE]
+
+ var/icon/picture_image
+ if(!isicon(character_appearance))
+ var/mutable_appearance/appearance = character_appearance
+ appearance.setDir(orientation)
+ picture_image = getFlatIcon(appearance)
+ else
+ picture_image = character_appearance
+
+ var/datum/picture/picture = new
+ picture.picture_name = "[fields[DATACORE_NAME]]"
+ picture.picture_desc = "This is [fields[DATACORE_NAME]]."
+ picture.picture_image = picture_image
+
+ var/obj/item/photo/photo = new(null, picture)
+ fields[field_name] = photo
+ return photo
+
+/// Set the criminal status of a crew member in the security records.
+/datum/data/record/proc/set_criminal_status(new_status)
+ var/old_status = DATACORE_CRIMINAL_STATUS
+ if(old_status == new_status)
+ return FALSE
+
+ fields[DATACORE_CRIMINAL_STATUS] = new_status
+ return TRUE
+
+/datum/data/record/proc/add_crime(datum/data/crime/crime)
+ fields[DATACORE_CRIMES] |= crime
+
+/datum/data/record/proc/remove_crime(cDataId)
+ if(istext(cDataId))
+ cDataId = text2num(cDataId)
+
+ for(var/datum/data/crime/crime in fields[DATACORE_CRIMES])
+ if(crime.dataId == cDataId)
+ fields[DATACORE_CRIMES] -= crime
+ return
+
+/datum/data/record/proc/add_crime_details(cDataId, details)
+ if(istext(cDataId))
+ cDataId = text2num(cDataId)
+
+ for(var/datum/data/crime/crime in fields[DATACORE_CRIMES])
+ if(crime.dataId == cDataId)
+ crime.crimeDetails = details
+ return
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index 6b7f6f19fa2f..7ac63719b60c 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -46,7 +46,7 @@
// Create our paper
var/obj/item/paper/report_paper = new(get_turf(src))
- //This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm
+ //This could be a global count like sec and med record printouts. See SSdatacore.medicalPrintCount AKA datacore.dm
var/frNum = ++forensicPrintCount
report_paper.name = text("FR-[] 'Forensic Record'", frNum)
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 8fbf9c32a38e..62c77f3bd18b 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -327,10 +327,9 @@
if(ishuman(character)) //These procs all expect humans
var/mob/living/carbon/human/humanc = character
ship.manifest_inject(humanc, client, job)
- GLOB.data_core.manifest_inject(humanc, client)
+ SSdatacore.inject_library(humanc, client, DATACORE_RECORDS_OUTPOST)
ship.add_mob_to_crew_guestbook(humanc)
AnnounceArrival(humanc, job.name, ship)
- AddEmploymentContract(humanc)
SSblackbox.record_feedback("tally", "species_spawned", 1, humanc.dna.species.name)
if(GLOB.summon_guns_triggered)
@@ -348,13 +347,6 @@
minor_announce("[job.name] [character.real_name] on deck!", zlevel = ship.shuttle_port.virtual_z())
return TRUE
-/mob/dead/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee)
- //TODO: figure out a way to exclude wizards/nukeops/demons from this.
- for(var/C in GLOB.employmentCabinets)
- var/obj/structure/filingcabinet/employment/employmentCabinet = C
- if(!employmentCabinet.virgin)
- employmentCabinet.addFile(employee)
-
/mob/dead/new_player/proc/LateChoices()
if(auth_check)
return
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index cf3f5ec725ec..e29bb4401681 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -342,14 +342,37 @@
if (!isnull(trait_exam))
. += trait_exam
- var/traitstring = get_trait_string()
-
var/perpname = get_face_name(get_id_name(""))
if(perpname && (HAS_TRAIT(user, TRAIT_SECURITY_HUD) || HAS_TRAIT(user, TRAIT_MEDICAL_HUD)))
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
- if(R)
- . += "Rank: [R.fields["rank"]]\n\[Front photo\] \[Side photo\] "
+ var/linked_datacore = user.get_datacore_key()
+ var/datum/data/record/target_record
+ if(linked_datacore)
+ target_record = SSdatacore.get_record_by_name(perpname, linked_datacore)
+ if(target_record)
+ . += "Found record for datacore: [linked_datacore]. "
+ . += "Rank : [target_record.fields[DATACORE_RANK]]. Name : [target_record.fields[DATACORE_NAME]]."
+ . += "\[Front photo\] \[Side photo\] "
+ if(HAS_TRAIT(user, TRAIT_MEDICAL_HUD))
+ . += "\[[target_record.fields[DATACORE_PHYSICAL_HEALTH]]\] "
+ . += "\[[target_record.fields[DATACORE_MENTAL_HEALTH]]\] "
+
+ if(HAS_TRAIT(user, TRAIT_SECURITY_HUD))
+ var/criminal = "None"
+ criminal = target_record.fields[DATACORE_CRIMINAL_STATUS]
+
+ . += "Criminal status: \[[criminal]\] "
+ . += jointext(list("Security record: \[View\] ",
+ "\[Add crime\] ",
+ "\[View comment log\] ",
+ "\[Add comment\] "), "")
+ else if(!linked_datacore)
+ . += "No linked datacore. "
+ else
+ . += "no linked record in datacore: [linked_datacore] "
+
if(HAS_TRAIT(user, TRAIT_MEDICAL_HUD))
+ . += "\[Medical Evaluation\] "
+ . += "\[See traits\] "
var/cyberimp_detect
for(var/obj/item/organ/cyberimp/CI in internal_organs)
if(CI.status == ORGAN_ROBOTIC && !CI.syndicate_implant)
@@ -357,34 +380,6 @@
if(cyberimp_detect)
. += "Detected cybernetic modifications: "
. += "[cyberimp_detect] "
- if(R)
- var/health_r = R.fields["p_stat"]
- . += "\[[health_r]\] "
- health_r = R.fields["m_stat"]
- . += "\[[health_r]\] "
- R = find_record("name", perpname, GLOB.data_core.medical)
- if(R)
- . += "\[Medical evaluation\] "
- if(traitstring)
- . += "Detected physiological traits: "
- . += "[traitstring] "
-
- if(HAS_TRAIT(user, TRAIT_SECURITY_HUD))
- if(!user.stat && user != src)
- //|| !user.canmove || user.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
- var/criminal = "None"
-
- R = find_record("name", perpname, GLOB.data_core.security)
- if(R)
- criminal = R.fields["criminal"]
-
- . += "Criminal status: \[[criminal]\] "
- . += jointext(list("Security record: \[View\] ",
- "\[Add crime\] ",
- "\[View comment log\] ",
- "\[Add comment\] "), "")
- else if(isobserver(user) && traitstring)
- . += "Traits: [traitstring] "
//No flavor text unless the face can be seen. Prevents certain metagaming with impersonation.
var/invisible_man = skipface || get_visible_name() == "Unknown"
@@ -394,7 +389,6 @@
var/flavor = print_flavor_text()
if(flavor)
. += flavor
- . += "*---------*"
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 27fa569de7cd..ee0298a8e756 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -277,29 +277,32 @@
if(href_list["hud"])
if(!ishuman(usr))
return
- var/mob/living/carbon/human/H = usr
+ var/mob/living/carbon/human/human_or_ghost_user = usr
var/perpname = get_face_name(get_id_name(""))
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD) && !HAS_TRAIT(H, TRAIT_MEDICAL_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD) && !HAS_TRAIT(human_or_ghost_user, TRAIT_MEDICAL_HUD))
return
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
+ var/linked_datacore = human_or_ghost_user.get_datacore_key()
+ var/datum/data/record/target_record = SSdatacore.get_record_by_name(perpname, linked_datacore)
if(href_list["photo_front"] || href_list["photo_side"])
- if(!R)
+ if(!target_record)
return
- if(!H.canUseHUD())
- return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD) && !HAS_TRAIT(H, TRAIT_MEDICAL_HUD))
+ if(ishuman(human_or_ghost_user))
+ var/mob/living/carbon/human/human_user = human_or_ghost_user
+ if(!human_user.canUseHUD())
+ return
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD) && !HAS_TRAIT(human_or_ghost_user, TRAIT_MEDICAL_HUD))
return
- var/obj/item/photo/P = null
+ var/obj/item/photo/photo_from_record = null
if(href_list["photo_front"])
- P = R.fields["photo_front"]
+ photo_from_record = target_record.get_front_photo()
else if(href_list["photo_side"])
- P = R.fields["photo_side"]
- if(P)
- P.show(H)
+ photo_from_record = target_record.get_side_photo()
+ if(photo_from_record)
+ photo_from_record.show(human_or_ghost_user)
return
if(href_list["hud"] == "m")
- if(!HAS_TRAIT(H, TRAIT_MEDICAL_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_MEDICAL_HUD))
return
if(href_list["evaluation"])
if(!getBruteLoss() && !getFireLoss() && !getOxyLoss() && getToxLoss() < 20)
@@ -341,85 +344,98 @@
to_chat(usr, "Patient has signs of suffocation, emergency treatment may be required! ")
if(getToxLoss() > 20)
to_chat(usr, "Gathered data is inconsistent with the analysis, possible cause: poisoning. ")
- if(!H.wear_id) //You require access from here on out.
- to_chat(H, "ERROR: Invalid access ")
+ var/obj/item/card/id/id_card = human_or_ghost_user.get_idcard()
+ if(!id_card) //You require access from here on out.
+ to_chat(human_or_ghost_user, "ERROR: Invalid access ")
return
- var/list/access = H.wear_id.GetAccess()
+ var/list/access = id_card.GetAccess()
if(!(ACCESS_MEDICAL in access))
- to_chat(H, "ERROR: Invalid access ")
+ to_chat(human_or_ghost_user, "ERROR: Invalid access ")
return
if(href_list["p_stat"])
- var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
- if(!R)
+ var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", target_record.fields[DATACORE_PHYSICAL_HEALTH]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
+ if(!target_record)
return
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_MEDICAL_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_MEDICAL_HUD))
return
if(health_status && health_status != "Cancel")
- R.fields["p_stat"] = health_status
+ target_record.fields[DATACORE_PHYSICAL_HEALTH] = health_status
return
if(href_list["m_stat"])
- var/health_status = input(usr, "Specify a new mental status for this person.", "Medical HUD", R.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel")
- if(!R)
+ var/health_status = input(usr, "Specify a new mental status for this person.", "Medical HUD", target_record.fields[DATACORE_MENTAL_HEALTH]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel")
+ if(!target_record)
return
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_MEDICAL_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_MEDICAL_HUD))
return
if(health_status && health_status != "Cancel")
- R.fields["m_stat"] = health_status
+ target_record.fields[DATACORE_MENTAL_HEALTH] = health_status
return
+ if(href_list["quirk"])
+ var/quirkstring = get_trait_string()
+ if(quirkstring)
+ to_chat(human_or_ghost_user, "Detected physiological traits: \n[quirkstring] ")
+ else
+ to_chat(human_or_ghost_user, "No physiological traits found. ")
return //Medical HUD ends here.
if(href_list["hud"] == "s")
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
if(usr.stat || usr == src) //|| !usr.canmove || usr.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
return //Non-fluff: This allows sec to set people to arrest as they get disarmed or beaten
// Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access
var/allowed_access = null
- var/obj/item/clothing/glasses/hud/security/G = H.glasses
- if(istype(G) && (G.obj_flags & EMAGGED))
+ var/user_name = null
+ var/obj/item/clothing/glasses/hud/security/sec_hud = human_or_ghost_user.glasses
+ if(istype(sec_hud) && (sec_hud.obj_flags & EMAGGED))
allowed_access = "@%&ERROR_%$*"
else //Implant and standard glasses check access
- if(H.wear_id)
- var/list/access = H.wear_id.GetAccess()
+ var/obj/item/card/id/id_card = human_or_ghost_user.get_idcard()
+ if(id_card)
+ var/list/access = id_card.GetAccess()
if(ACCESS_SEC_DOORS in access)
- allowed_access = H.get_authentification_name()
+ allowed_access = TRUE
+ user_name = human_or_ghost_user.get_authentification_name()
if(!allowed_access)
- to_chat(H, "ERROR: Invalid access. ")
+ to_chat(human_or_ghost_user, "ERROR: Invalid access. ")
return
+ if(!user_name)
+ to_chat(human_or_ghost_user, "ERROR: Invalid name on ID. ")
+
if(!perpname)
- to_chat(H, "ERROR: Can not identify target. ")
+ to_chat(human_or_ghost_user, "ERROR: Can not identify target. ")
return
- R = find_record("name", perpname, GLOB.data_core.security)
- if(!R)
+
+ if(!target_record)
to_chat(usr, "ERROR: Unable to locate data core entry for target. ")
return
if(href_list["status"])
- var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Paroled", "Discharged", "Cancel")
+ var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", target_record.fields[DATACORE_CRIMINAL_STATUS]) in list("None", "*Arrest*", "Incarcerated", "Paroled", "Discharged", "Cancel")
if(setcriminal != "Cancel")
- if(!R)
+ if(!target_record)
return
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
- investigate_log("[key_name(src)] has been set from [R.fields["criminal"]] to [setcriminal] by [key_name(usr)].", INVESTIGATE_RECORDS)
- R.fields["criminal"] = setcriminal
+ investigate_log("[key_name(src)] has been set from [target_record.fields[DATACORE_CRIMINAL_STATUS]] to [setcriminal] by [key_name(usr)].", INVESTIGATE_RECORDS)
+ target_record.fields[DATACORE_CRIMINAL_STATUS] = setcriminal
sec_hud_set_security_status()
return
if(href_list["view"])
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
- to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]")
- for(var/datum/data/crime/c in R.fields["crim"])
+ to_chat(usr, "Name: [target_record.fields[DATACORE_NAME]]\nCriminal Status: [target_record.fields[DATACORE_CRIMINAL_STATUS]]")
+ for(var/datum/data/crime/c in target_record.fields[DATACORE_CRIMES])
to_chat(usr, "Crime: [c.crimeName]")
if (c.crimeDetails)
to_chat(usr, "Details: [c.crimeDetails]")
@@ -427,62 +443,64 @@
to_chat(usr, "Details: \[Add details] ")
to_chat(usr, "Added by [c.author] at [c.time]")
to_chat(usr, "----------")
- to_chat(usr, "Notes: [R.fields["notes"]]")
+ to_chat(usr, "Notes: [target_record.fields[DATACORE_NOTES]]")
return
if(href_list["add_crime"])
var/t1 = stripped_input("Please input crime name:", "Security HUD", "", null)
- if(!R || !t1 || !allowed_access)
+ if(!target_record || !t1 || !allowed_access)
return
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
- var/crime = GLOB.data_core.createCrimeEntry(t1, null, allowed_access, station_time_timestamp())
- GLOB.data_core.addCrime(R.fields["id"], crime)
- investigate_log("New Crime: [t1] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- to_chat(usr, "Successfully added a crime. ")
+
+ var/crime = SSdatacore.new_crime_entry(t1, null, user_name, station_time_timestamp())
+ target_record.add_crime(crime)
+ investigate_log("New Crime: [t1] | Added to [target_record.fields[DATACORE_NAME]] by [key_name(usr)]", INVESTIGATE_RECORDS)
+ to_chat(usr, span_notice("Successfully added a crime."))
return
if(href_list["add_details"])
var/t1 = stripped_input(usr, "Please input crime details:", "Secure. records", "", null)
- if(!R || !t1 || !allowed_access)
+ if(!target_record || !t1 || !allowed_access)
return
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
+
if(href_list["cdataid"])
- GLOB.data_core.addCrimeDetails(R.fields["id"], href_list["cdataid"], t1)
- investigate_log("New Crime details: [t1] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- to_chat(usr, "Successfully added details. ")
+ target_record.add_crime_details(href_list["cdataid"], t1)
+ investigate_log("New Crime details: [t1] | Added to [target_record.fields[DATACORE_NAME]] by [key_name(usr)]", INVESTIGATE_RECORDS)
+ to_chat(usr, span_notice("Successfully added details."))
return
if(href_list["view_comment"])
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
to_chat(usr, "Comments/Log: ")
var/counter = 1
- while(R.fields[text("com_[]", counter)])
- to_chat(usr, R.fields[text("com_[]", counter)])
+ while(target_record.fields[text("com_[]", counter)])
+ to_chat(usr, target_record.fields[text("com_[]", counter)])
to_chat(usr, "----------")
counter++
return
if(href_list["add_comment"])
var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null)
- if (!R || !t1 || !allowed_access)
+ if (!target_record || !t1 || !allowed_access)
return
- if(!H.canUseHUD())
+ if(!human_or_ghost_user.canUseHUD())
return
- if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD))
+ if(!HAS_TRAIT(human_or_ghost_user, TRAIT_SECURITY_HUD))
return
var/counter = 1
- while(R.fields[text("com_[]", counter)])
+ while(target_record.fields[text("com_[]", counter)])
counter++
- R.fields[text("com_[]", counter)] = text("Made by [] on [], [] []", allowed_access, station_time_timestamp(), sector_datestamp(shortened = TRUE), t1)
+ target_record.fields[text("com_[]", counter)] = text("Made by [] on [], [] []", allowed_access, station_time_timestamp(), sector_datestamp(shortened = TRUE), t1)
to_chat(usr, "Successfully added comment. ")
return
@@ -555,19 +573,6 @@
if(weaponcheck.Invoke(belt) || weaponcheck.Invoke(back)) //if a weapon is present in the belt or back slot
threatcount += 2 //not enough to trigger look_for_perp() on it's own unless they also have criminal status.
- //Check for arrest warrant
- if(judgement_criteria & JUDGE_RECORDCHECK)
- var/perpname = get_face_name(get_id_name())
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
- if(R && R.fields["criminal"])
- switch(R.fields["criminal"])
- if("*Arrest*")
- threatcount += 5
- if("Incarcerated")
- threatcount += 2
- if("Paroled")
- threatcount += 2
-
//Check for dresscode violations
if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard))
threatcount += 2
@@ -829,10 +834,13 @@
return TRUE
/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed.
- for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked))
- var/datum/data/record/R = find_record("name", oldname, L)
- if(R)
- R.fields["name"] = newname
+ for(var/id as anything in SSdatacore.library)
+ var/datum/data_library/library = SSdatacore.library[id]
+ var/datum/data/record/target_record = library.get_record_by_name(oldname)
+ if(target_record)
+ target_record.fields[DATACORE_NAME] = newname
+ library.records_by_name -= oldname
+ library.records_by_name[newname] = target_record
/mob/living/carbon/human/get_total_tint()
. = ..()
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index b7c5b9877120..d3e9cbc0259c 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -26,9 +26,11 @@
var/obj/item/card/id/id = get_idcard(FALSE)
if(id)
return id.registered_name
+ /*
var/obj/item/pda/pda = wear_id
if(istype(pda))
return pda.owner
+ */
return if_no_id
/mob/living/carbon/human/get_visible_name()
@@ -43,7 +45,7 @@
if(head && (head.flags_inv & HIDEFACE))
return if_no_face //Likewise for hats
var/obj/item/bodypart/O = get_bodypart(BODY_ZONE_HEAD)
- if(!O || (HAS_TRAIT(src, TRAIT_DISFIGURED)) || (O.brutestate+O.burnstate)>2 || cloneloss>50 || !real_name) //disfigured. use id-name if possible
+ if(!O || (HAS_TRAIT(src, TRAIT_DISFIGURED)) || (O.brutestate+O.burnstate) > 2 || cloneloss > 50 || !real_name) //disfigured. use id-name if possible
return if_no_face
return real_name
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index cfd7d9153c8d..7bddf83e8090 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -629,8 +629,8 @@
if("Crew Member")
var/list/personnel_list = list()
- for(var/datum/data/record/t in GLOB.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/data/record/t in SSdatacore.get_records(DATACORE_RECORDS_OUTPOST))//Look in data core locked.
+ personnel_list["[t.fields[DATACORE_NAME]]: [t.fields[DATACORE_RANK]]"] = t.fields[DATACORE_IMAGE]//Pull names, rank, and image.
if(personnel_list.len)
input = input("Select a crew member:") as null|anything in sortList(personnel_list)
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 9f3b85fd4a92..15543a46a5bb 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -45,7 +45,7 @@
var/secHUD = 0 // Toggles whether the Security HUD is active or not
var/medHUD = 0 // Toggles whether the Medical HUD is active or not
- var/datum/data/record/medicalActive1 // Datacore record declarations for record software
+ var/datum/data/record/active_record // Datacore record declarations for record software
var/datum/data/record/medicalActive2
var/datum/data/record/securityActive1 // Could probably just combine all these into one
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 061c4a74a4b1..667c7c6d68d6 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -308,21 +308,15 @@ GLOBAL_LIST_INIT(pai_faces_icons, list(
if("medicalrecord") // Accessing medical records
if(subscreen == 1)
- medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general)
- if(medicalActive1)
- medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical)
- if(!medicalActive2)
- medicalActive1 = null
- temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
+ active_record = SSdatacore.find_record(DATACORE_ID, href_list["med_rec"], DATACORE_RECORDS_OUTPOST)
+ if(!active_record)
+ temp = "Unable to locate requested record. Record may have been deleted, or never have existed."
if("securityrecord")
if(subscreen == 1)
- securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general)
- if(securityActive1)
- securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security)
- if(!securityActive2)
- securityActive1 = null
- temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
+ active_record = SSdatacore.find_record(DATACORE_ID, href_list["sec_rec"], DATACORE_RECORDS_OUTPOST)
+ if(!active_record)
+ temp = "Unable to locate requested record. Record may have been deleted, or never have existed."
if("securityhud")
if(href_list["toggle"])
@@ -530,9 +524,9 @@ GLOBAL_LIST_INIT(pai_faces_icons, list(
// Crew Manifest
/mob/living/silicon/pai/proc/softwareManifest()
. += "Crew Manifest "
- if(GLOB.data_core.general)
- for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
- . += "[t.fields["name"]] - [t.fields["rank"]] "
+ if(SSdatacore.get_records(DATACORE_RECORDS_OUTPOST))
+ for(var/datum/data/record/t in sortRecord(SSdatacore.get_records(DATACORE_RECORDS_OUTPOST)))
+ . += "[t.fields[DATACORE_NAME]] - [t.fields[DATACORE_RANK]] "
. += "