diff --git a/_maps/RandomRuins/StationRuins/GaxStation/ai_whale.dmm b/_maps/RandomRuins/StationRuins/GaxStation/ai_whale.dmm index ff3182149f64..4f99de8995cd 100644 --- a/_maps/RandomRuins/StationRuins/GaxStation/ai_whale.dmm +++ b/_maps/RandomRuins/StationRuins/GaxStation/ai_whale.dmm @@ -7,9 +7,6 @@ /turf/open/floor/plating, /area/tcommsat/computer) "aA" = ( -/obj/machinery/computer/ai_resource_distribution{ - dir = 8 - }, /obj/machinery/computer/security/telescreen{ dir = 8; name = "MiniSat Camera Monitor"; @@ -2206,7 +2203,7 @@ dir = 8; pixel_x = 24 }, -/obj/machinery/computer/ai_control_console{ +{ dir = 8 }, /turf/open/floor/plasteel/grimy, diff --git a/_maps/map_files/EclipseStation/EclipseStation.dmm b/_maps/map_files/EclipseStation/EclipseStation.dmm index 85baa543423e..879d1b12eb0a 100644 --- a/_maps/map_files/EclipseStation/EclipseStation.dmm +++ b/_maps/map_files/EclipseStation/EclipseStation.dmm @@ -45018,9 +45018,6 @@ /obj/structure/window/reinforced{ layer = 4.1 }, -/obj/machinery/computer/ai_resource_distribution{ - dir = 1 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload) "bOT" = ( @@ -59457,7 +59454,7 @@ /area/crew_quarters/heads/hor) "cto" = ( /obj/structure/rack, -/obj/item/circuitboard/computer/ai_upload_download, +, /obj/item/disk/holodisk/tutorial/AICore, /turf/open/floor/plasteel, /area/crew_quarters/heads/hor) @@ -86278,9 +86275,6 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "nsA" = ( -/obj/machinery/computer/ai_resource_distribution{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/open/floor/carpet, @@ -90567,7 +90561,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 1 }, -/obj/machinery/computer/ai_control_console{ +{ dir = 1 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/map_files/GaxStation/GaxStation.dmm b/_maps/map_files/GaxStation/GaxStation.dmm index 74f61e2b2f10..4dfde9638ac4 100644 --- a/_maps/map_files/GaxStation/GaxStation.dmm +++ b/_maps/map_files/GaxStation/GaxStation.dmm @@ -65,7 +65,7 @@ /obj/structure/rack, /obj/item/aicard, /obj/item/disk/holodisk/tutorial/AICore, -/obj/item/circuitboard/computer/ai_upload_download, +, /obj/machinery/power/apc{ areastring = "/area/crew_quarters/heads/hor"; dir = 8; @@ -11064,9 +11064,6 @@ /turf/open/floor/plasteel, /area/security/main) "fvC" = ( -/obj/machinery/computer/ai_resource_distribution{ - dir = 4 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/secondarydatacore) "fvG" = ( @@ -18746,7 +18743,7 @@ /obj/machinery/computer/robotics{ dir = 8 }, -/obj/structure/sign/plaques/ai_password{ +{ pixel_x = 32 }, /turf/open/floor/carpet/exoticpurple, diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 63cdf54eefe5..d152380c5be4 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -85994,7 +85994,7 @@ /obj/effect/turf_decal/tile/neutral, /obj/structure/table, /obj/item/hand_labeler, -/obj/item/circuitboard/computer/ai_upload_download, +, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) "fMR" = ( @@ -91824,9 +91824,6 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/obj/machinery/computer/ai_resource_distribution{ - dir = 8 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/storage/satellite) "laJ" = ( @@ -92192,7 +92189,7 @@ dir = 1 }, /obj/effect/mapping_helpers/teleport_anchor, -/obj/structure/sign/plaques/ai_password{ +{ pixel_x = -32 }, /turf/open/floor/plasteel/showroomfloor, @@ -92215,7 +92212,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/computer/ai_control_console{ +{ dir = 8 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/map_files/Omegastation/omegastation.dmm b/_maps/map_files/Omegastation/omegastation.dmm index 416486332452..2d4ddd5f8ab0 100644 --- a/_maps/map_files/Omegastation/omegastation.dmm +++ b/_maps/map_files/Omegastation/omegastation.dmm @@ -43172,9 +43172,6 @@ /turf/open/floor/plasteel/white, /area/science/research) "tZB" = ( -/obj/machinery/computer/ai_resource_distribution{ - dir = 1 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, diff --git a/_maps/map_files/YogStation/YogStation.dmm b/_maps/map_files/YogStation/YogStation.dmm index 13a8725706f1..53dc0e83aa69 100644 --- a/_maps/map_files/YogStation/YogStation.dmm +++ b/_maps/map_files/YogStation/YogStation.dmm @@ -220,12 +220,6 @@ }, /turf/open/floor/plasteel, /area/security/prison) -"abx" = ( -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/dirt/dust, -/obj/machinery/ai/server_cabinet/prefilled, -/turf/open/floor/circuit/green/telecomms, -/area/ai_monitored/turret_protected/ai) "aby" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 8 @@ -605,6 +599,16 @@ }, /turf/open/space/basic, /area/space) +"acX" = ( +/obj/structure/rack, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/structure/sign/plaques/cave{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/white, +/area/crew_quarters/heads/hor) "acY" = ( /obj/structure/closet/bombcloset/security, /turf/open/floor/plasteel/showroomfloor, @@ -1217,6 +1221,12 @@ /obj/machinery/recharger, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"agv" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "agy" = ( /obj/structure/table, /obj/item/storage/firstaid/regular{ @@ -2543,6 +2553,21 @@ }, /turf/open/floor/carpet, /area/crew_quarters/fitness) +"aob" = ( +/obj/structure/sign/warning/electricshock{ + pixel_y = -32 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "aof" = ( /turf/closed/wall/r_wall, /area/maintenance/solars/starboard/fore) @@ -3389,18 +3414,6 @@ }, /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) -"aue" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plating{ - icon_state = "platingdmg3" - }, -/area/maintenance/starboard/aft) "aug" = ( /obj/structure/table, /obj/item/storage/toolbox/electrical{ @@ -6021,6 +6034,14 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"aJj" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "aJk" = ( /obj/machinery/light, /obj/structure/table, @@ -6483,6 +6504,13 @@ /obj/machinery/vending/cigarette, /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) +"aLA" = ( +/obj/structure/window/reinforced, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "aLD" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -6660,22 +6688,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) -"aMD" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "aME" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 4; @@ -7820,15 +7832,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/vacant_room/commissary) -"aSy" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "aSG" = ( /obj/structure/table, /obj/item/stack/sheet/glass/fifty, @@ -10633,6 +10636,14 @@ /obj/structure/closet/wardrobe/black, /turf/open/floor/plating, /area/maintenance/central) +"bkY" = ( +/obj/item/stack/cable_coil, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/ethernet_cable{ + icon_state = "2-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "bkZ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -10956,6 +10967,16 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/quartermaster/office) +"bnB" = ( +/obj/machinery/ai/networking{ + label = "Computer Science"; + roundstart_connection = "Main Core" + }, +/obj/structure/ethernet_cable{ + icon_state = "0-4" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "bnE" = ( /obj/machinery/door/airlock/research{ name = "Research Division Access"; @@ -13160,18 +13181,6 @@ "bCv" = ( /turf/closed/wall, /area/janitor) -"bCw" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "bCz" = ( /obj/machinery/vending/cigarette, /turf/open/floor/plasteel/dark, @@ -13973,22 +13982,16 @@ }, /turf/open/floor/plasteel, /area/engine/atmos_distro) -"bKB" = ( -/obj/structure/closet/emcloset, -/obj/structure/sign/warning/electricshock{ - pixel_y = -32 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 9 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 9 +"bKx" = ( +/obj/machinery/modular_computer/console/preset/netmin{ + dir = 1 }, -/obj/structure/cable{ - icon_state = "1-8" +/obj/effect/turf_decal/trimline/purple/filled/line, +/obj/structure/ethernet_cable{ + icon_state = "0-2" }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "bKG" = ( /obj/machinery/requests_console{ department = "EVA"; @@ -14476,6 +14479,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/white, /area/medical/virology) +"bOz" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-4" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "bOH" = ( /obj/structure/sign/warning/docking, /obj/effect/spawner/structure/window/reinforced/shutter, @@ -14852,23 +14861,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/medical/virology) -"bRR" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only, -/obj/machinery/door/airlock/research/glass{ - name = "Secondary AI Core"; - normalspeed = 0; - req_access_txt = "47" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "bSm" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ @@ -15045,6 +15037,13 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) +"bUU" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/ai_monitored/secondarydatacore) "bUV" = ( /obj/machinery/vending/wardrobe/sec_wardrobe, /obj/machinery/light, @@ -15692,6 +15691,12 @@ }, /turf/open/space, /area/solar/port/aft) +"cde" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "cdh" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ @@ -15865,10 +15870,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"ceR" = ( -/obj/effect/landmark/blobstart, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "ceW" = ( /obj/structure/rack, /obj/effect/spawner/lootdrop/techstorage/RnD_secure, @@ -17483,25 +17484,15 @@ }, /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) -"cyZ" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only, -/obj/machinery/door/airlock/hatch{ - name = "Hardware Workshop"; - req_access_txt = "61" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 +"czb" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/structure/cable{ - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 }, -/turf/open/floor/plasteel/grimy, -/area/tcommsat/computer) +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "czc" = ( /obj/machinery/door/airlock/highsecurity{ name = "AI Upload Access"; @@ -17967,6 +17958,20 @@ }, /turf/open/floor/plasteel, /area/quartermaster/miningdock) +"cGu" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "cGw" = ( /obj/machinery/meter, /obj/machinery/atmospherics/pipe/simple/supply/visible, @@ -18531,6 +18536,12 @@ }, /turf/open/floor/plasteel, /area/quartermaster/miningdock) +"cPu" = ( +/obj/effect/turf_decal/trimline/purple/filled/line, +/obj/machinery/portable_atmospherics/canister/nitrogen, +/obj/machinery/atmospherics/components/unary/portables_connector/visible, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "cPD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 6 @@ -19092,16 +19103,6 @@ }, /turf/open/floor/plasteel/dark, /area/science/xenobiology) -"dbJ" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/obj/structure/sign/plaques/ai_password{ - pixel_x = 32 - }, -/obj/machinery/papershredder, -/turf/open/floor/plasteel/white, -/area/crew_quarters/heads/hor) "dcc" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -19159,6 +19160,15 @@ /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/plasteel, /area/quartermaster/miningdock) +"ddQ" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1; + external_pressure_bound = 140; + plane = -2; + pressure_checks = 0 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "dea" = ( /obj/structure/table, /obj/item/folder/yellow, @@ -19666,6 +19676,15 @@ }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) +"duc" = ( +/obj/structure/ethernet_cable{ + icon_state = "2-8" + }, +/obj/structure/ethernet_cable{ + icon_state = "2-4" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "dus" = ( /obj/structure/table/wood, /obj/item/flashlight/lantern, @@ -19834,6 +19853,26 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) +"dxO" = ( +/obj/structure/chair/office/dark{ + dir = 4 + }, +/obj/machinery/computer/security/telescreen{ + dir = 1; + name = "Telecomms Camera Monitor"; + network = list("tcomms"); + pixel_x = 30; + pixel_y = -37 + }, +/obj/item/radio/intercom{ + dir = 1; + freerange = 1; + name = "Station Intercom (Telecomms)"; + pixel_x = 28; + pixel_y = -26 + }, +/turf/open/floor/plasteel/grimy, +/area/tcommsat/computer) "dxV" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table, @@ -20000,13 +20039,6 @@ }, /turf/open/floor/plasteel/dark, /area/ai_monitored/nuke_storage) -"dBH" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 4 - }, -/obj/machinery/meter, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "dBU" = ( /obj/machinery/light_switch{ pixel_x = 27 @@ -20161,15 +20193,6 @@ }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet) -"dFJ" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "dFX" = ( /obj/machinery/door/airlock/maintenance{ name = "Security Maintenance"; @@ -20500,16 +20523,6 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab) -"dMA" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dMJ" = ( /obj/machinery/advanced_airlock_controller{ dir = 8; @@ -20815,6 +20828,13 @@ }, /turf/open/floor/plasteel, /area/quartermaster/qm) +"dTf" = ( +/obj/structure/frame/machine{ + anchored = 1; + state = 2 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "dTu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, @@ -21278,6 +21298,12 @@ }, /turf/open/floor/plasteel, /area/security/checkpoint/engineering) +"efW" = ( +/obj/structure/table, +/obj/item/storage/box/donkpockets, +/obj/effect/turf_decal/trimline/purple/filled/line, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "egc" = ( /obj/machinery/door/poddoor/preopen{ id = "atmos"; @@ -21392,6 +21418,13 @@ }, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"ehY" = ( +/obj/machinery/ai/server_cabinet/prefilled, +/obj/structure/ethernet_cable{ + icon_state = "0-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "eie" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -21950,6 +21983,13 @@ }, /turf/open/floor/plasteel, /area/engine/atmos_distro) +"euD" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/machinery/papershredder, +/turf/open/floor/plasteel/white, +/area/crew_quarters/heads/hor) "euJ" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/machinery/door/firedoor/border_only, @@ -22044,6 +22084,15 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/wood, /area/library) +"exA" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "exB" = ( /obj/structure/chair/office/dark{ dir = 4 @@ -22503,6 +22552,18 @@ }, /turf/open/floor/plasteel/dark, /area/chapel/office) +"eFt" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/ai/networking{ + label = "Main Core"; + roundstart_connection = "Computer Science" + }, +/obj/structure/ethernet_cable{ + icon_state = "0-4" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "eFL" = ( /obj/machinery/camera{ c_tag = "Engineering Escape Pod"; @@ -23130,6 +23191,25 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /turf/open/floor/plasteel, /area/janitor) +"eUd" = ( +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, +/obj/machinery/door/airlock/hatch{ + name = "Telecommunications"; + req_access_txt = "61" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/grimy, +/area/tcommsat/computer) "eUf" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -23548,6 +23628,17 @@ }, /turf/open/floor/plasteel/white, /area/science/research) +"fcx" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 + }, +/obj/structure/table, +/obj/item/stack/ethernet_coil, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 5 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "fcB" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ @@ -23559,17 +23650,6 @@ /obj/machinery/holopad, /turf/open/floor/plasteel, /area/engine/foyer) -"fdU" = ( -/obj/structure/rack, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/obj/structure/sign/plaques/cave{ - pixel_y = 32 - }, -/obj/item/circuitboard/computer/ai_upload_download, -/turf/open/floor/plasteel/white, -/area/crew_quarters/heads/hor) "fen" = ( /obj/machinery/computer/upload/ai{ dir = 1 @@ -23620,6 +23700,18 @@ }, /turf/open/floor/plasteel/white, /area/medical/chemistry) +"feK" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "feV" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -23900,6 +23992,15 @@ /obj/effect/turf_decal/trimline/red/filled/corner, /turf/open/floor/plasteel, /area/security/brig) +"flr" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "flC" = ( /obj/machinery/door/firedoor/border_only{ dir = 4 @@ -24117,18 +24218,6 @@ /obj/machinery/door/firedoor/border_only, /turf/open/floor/plating, /area/maintenance/starboard/aft) -"frD" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 8 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "frH" = ( /obj/machinery/light/small{ dir = 8 @@ -24840,18 +24929,6 @@ }, /turf/open/floor/plasteel/dark, /area/security/prison) -"fFO" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/computer/ai_resource_distribution{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "fFS" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor/border_only{ @@ -24984,6 +25061,18 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/storage/tech) +"fIh" = ( +/obj/machinery/power/apc{ + areastring = "/area/maintenance/starboard/aft"; + dir = 4; + name = "Starboard Quarter Maintenance APC"; + pixel_x = 24 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "fIn" = ( /obj/machinery/computer/cargo{ dir = 4 @@ -25010,15 +25099,6 @@ }, /turf/open/floor/plating, /area/maintenance/port/aft) -"fIs" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "fIu" = ( /obj/machinery/door/airlock/public/glass{ name = "Central Access" @@ -25032,13 +25112,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft_starboard) -"fIH" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "fIS" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 @@ -25882,6 +25955,14 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) +"gcd" = ( +/obj/structure/table, +/obj/machinery/microwave, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 10 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "gce" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/door/firedoor/border_only{ @@ -25983,12 +26064,6 @@ }, /turf/open/floor/wood, /area/library) -"gdI" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 10 - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "gdU" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -26163,6 +26238,15 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"giM" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "giP" = ( /obj/machinery/door/window/eastright{ base_state = "left"; @@ -26291,19 +26375,6 @@ }, /turf/open/floor/plasteel/dark, /area/bridge) -"goW" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/power/apc/highcap{ - areastring = "/area/ai_monitored/secondarydatacore"; - dir = 4; - name = "AI Secondary Datacore"; - pixel_x = 24 - }, -/obj/structure/cable, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "goZ" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -26322,6 +26393,18 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"gqo" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "gqu" = ( /obj/machinery/door/firedoor/border_only{ dir = 1 @@ -26868,22 +26951,6 @@ }, /turf/open/floor/plasteel, /area/security/prison/hallway) -"gDs" = ( -/obj/machinery/doorButtons/access_button{ - idDoor = "secondary_aicore_interior"; - idSelf = "secondary_aicore_controller"; - name = "Secondary AI Core Access Button"; - pixel_x = -24; - pixel_y = 8; - req_one_access_txt = "30;70" - }, -/obj/structure/chair/office/light, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "gDD" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 8 @@ -27420,6 +27487,10 @@ icon_state = "platingdmg3" }, /area/maintenance/port) +"gRT" = ( +/obj/machinery/atmospherics/pipe/manifold4w/cyan/hidden, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "gSd" = ( /obj/machinery/camera{ c_tag = "Research Division Access" @@ -27871,12 +27942,6 @@ /obj/effect/turf_decal/trimline/purple/filled/warning, /turf/open/floor/plasteel/white, /area/science/research) -"hbO" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "hcu" = ( /obj/structure/table, /obj/item/storage/box/fancy/heart_box{ @@ -28527,6 +28592,12 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) +"hnb" = ( +/obj/structure/ethernet_cable{ + icon_state = "2-4" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "hnh" = ( /obj/structure/cable{ icon_state = "4-8" @@ -29448,10 +29519,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos_distro) -"hJq" = ( -/obj/machinery/ai/data_core/primary, -/turf/open/floor/circuit/green/telecomms, -/area/ai_monitored/turret_protected/ai) "hJu" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small{ @@ -29708,15 +29775,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"hOU" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/computer/ai_server_console{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "hPk" = ( /obj/machinery/holopad, /turf/open/floor/plasteel/white, @@ -30220,6 +30278,10 @@ }, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) +"hYR" = ( +/obj/effect/spawner/structure/window/reinforced/shutter, +/turf/open/floor/plating, +/area/space) "hYX" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -30230,19 +30292,6 @@ }, /turf/open/floor/plasteel/grimy, /area/ai_monitored/turret_protected/aisat_interior) -"hYY" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 4 - }, -/obj/machinery/power/terminal{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "hZg" = ( /obj/machinery/power/smes/engineering{ charge = 5e+006; @@ -30502,20 +30551,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"ief" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{ - dir = 4; - external_pressure_bound = 120 - }, -/obj/machinery/airalarm/tcomms{ - dir = 4; - pixel_x = -24 - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "ieh" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ @@ -30699,10 +30734,6 @@ }, /turf/open/floor/plasteel, /area/hydroponics) -"iiJ" = ( -/obj/machinery/ai/server_cabinet, -/turf/open/floor/circuit/green/telecomms/mainframe, -/area/ai_monitored/secondarydatacore) "iiO" = ( /obj/machinery/gulag_item_reclaimer{ pixel_y = 24 @@ -30778,10 +30809,6 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) -"ikV" = ( -/obj/machinery/ai/server_cabinet/prefilled, -/turf/open/floor/circuit/green/telecomms, -/area/ai_monitored/turret_protected/ai) "ilk" = ( /obj/structure/closet/secure_closet/captains, /turf/open/floor/carpet/blue, @@ -31493,6 +31520,12 @@ }, /turf/open/floor/plasteel/dark, /area/bridge) +"izK" = ( +/obj/structure/ethernet_cable{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "izV" = ( /obj/item/radio/intercom{ name = "Station Intercom (General)"; @@ -32350,27 +32383,6 @@ /obj/effect/turf_decal/trimline/yellow/filled/line, /turf/open/floor/plasteel, /area/construction/mining/aux_base) -"iRV" = ( -/obj/structure/chair/office/dark{ - dir = 4 - }, -/obj/machinery/computer/security/telescreen{ - dir = 1; - name = "Telecomms Camera Monitor"; - network = list("tcomms"); - pixel_x = 30; - pixel_y = -37 - }, -/obj/item/radio/intercom{ - dir = 1; - freerange = 1; - name = "Station Intercom (Telecomms)"; - pixel_x = 28; - pixel_y = -26 - }, -/obj/effect/landmark/start/yogs/network_admin, -/turf/open/floor/plasteel/grimy, -/area/tcommsat/computer) "iRY" = ( /obj/structure/table, /obj/item/flashlight{ @@ -32536,10 +32548,6 @@ }, /turf/open/floor/plating, /area/medical/paramedic) -"iVk" = ( -/obj/structure/girder, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "iVn" = ( /obj/structure/closet/crate{ icon_state = "crateopen" @@ -32639,6 +32647,14 @@ /obj/structure/cable, /turf/open/floor/plasteel, /area/science/mixing) +"iWz" = ( +/obj/machinery/camera{ + c_tag = "Secondary AI Core"; + dir = 8; + network = list("ss13","rd") + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "iWF" = ( /obj/effect/spawner/structure/window/reinforced/shutter, /obj/structure/cable{ @@ -33046,6 +33062,16 @@ }, /turf/closed/wall/r_wall, /area/engine/atmos_distro) +"jgW" = ( +/obj/machinery/ai/data_core/primary, +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/obj/structure/ethernet_cable{ + icon_state = "0-2" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "jhc" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2, @@ -33166,6 +33192,13 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"jkO" = ( +/obj/structure/ethernet_cable{ + icon_state = "0-4" + }, +/obj/machinery/ai/server_cabinet, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "jld" = ( /obj/structure/rack, /obj/effect/spawner/lootdrop/techstorage/rnd, @@ -33884,12 +33917,6 @@ }, /turf/open/floor/plating, /area/maintenance/disposal/incinerator) -"jzm" = ( -/obj/structure/cable/yellow{ - icon_state = "2-4" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "jzo" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 1 @@ -34324,6 +34351,29 @@ /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood, /area/library) +"jJv" = ( +/obj/machinery/doorButtons/access_button{ + idDoor = "secondary_aicore_interior"; + idSelf = "secondary_aicore_controller"; + name = "Secondary AI Core Access Button"; + pixel_x = -24; + pixel_y = 8; + req_one_access_txt = "30;70" + }, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 5 + }, +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "jJy" = ( /obj/structure/chair{ dir = 4 @@ -34394,6 +34444,15 @@ }, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/hor) +"jKp" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 8 + }, +/obj/structure/window/reinforced{ + dir = 8 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "jKG" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2, /turf/open/floor/plasteel, @@ -34549,20 +34608,13 @@ }, /turf/open/floor/plating, /area/hallway/secondary/exit) -"jPU" = ( -/obj/machinery/door/firedoor/border_only, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" +"jPF" = ( +/obj/machinery/ai/data_core, +/obj/structure/ethernet_cable{ + icon_state = "0-8" }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "jQg" = ( /obj/effect/turf_decal/arrows/white{ color = "#99ccff"; @@ -35087,6 +35139,13 @@ }, /turf/open/floor/circuit/telecomms/server, /area/ai_monitored/turret_protected/ai) +"kcA" = ( +/obj/structure/ethernet_cable{ + icon_state = "0-8" + }, +/obj/machinery/ai/server_cabinet/prefilled, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "kcH" = ( /obj/machinery/disposal/bin, /obj/structure/window/reinforced, @@ -35509,6 +35568,16 @@ }, /turf/open/floor/plasteel, /area/janitor) +"kkY" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-4" + }, +/obj/structure/ethernet_cable{ + icon_state = "1-8" + }, +/obj/machinery/light, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "klD" = ( /obj/structure/sign/departments/minsky/medical/chemistry/chemical2, /turf/closed/wall, @@ -36428,12 +36497,6 @@ }, /turf/open/floor/carpet, /area/crew_quarters/fitness) -"kJz" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "kJK" = ( /obj/structure/grille, /obj/structure/window{ @@ -36833,16 +36896,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/fore) -"kSZ" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "kTm" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /obj/structure/window/reinforced{ @@ -37040,6 +37093,21 @@ /obj/structure/closet/firecloset, /turf/open/floor/plating, /area/maintenance/port/aft) +"kYZ" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 5 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "kZl" = ( /obj/structure/closet/l3closet, /turf/open/floor/plating, @@ -37143,12 +37211,6 @@ /obj/effect/turf_decal/trimline/yellow/filled/line, /turf/open/floor/plasteel, /area/hallway/primary/central) -"lbr" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "lbE" = ( /obj/machinery/light, /obj/effect/turf_decal/trimline/blue/filled/corner{ @@ -37253,6 +37315,13 @@ "ldW" = ( /turf/template_noop, /area/maintenance/aft) +"lej" = ( +/obj/effect/turf_decal/trimline/purple/filled/line, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "leo" = ( /obj/structure/window/reinforced{ dir = 4 @@ -37782,6 +37851,23 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"lpZ" = ( +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only, +/obj/machinery/door/airlock/research/glass{ + name = "Computer Science"; + normalspeed = 0; + req_access_txt = "47" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "lql" = ( /obj/structure/rack, /obj/item/storage/toolbox/electrical{ @@ -38123,6 +38209,21 @@ }, /turf/open/floor/plasteel, /area/quartermaster/office) +"lzq" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 10 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "lzt" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/trimline/yellow/filled/warning{ @@ -38396,11 +38497,6 @@ /obj/structure/chair/sofa/right, /turf/open/floor/wood, /area/medical/psych) -"lHO" = ( -/obj/item/stack/cable_coil, -/obj/effect/decal/cleanable/dirt/dust, -/turf/open/floor/circuit/green/telecomms, -/area/ai_monitored/turret_protected/ai) "lIb" = ( /obj/structure/sign/warning/electricshock{ pixel_y = 32 @@ -38453,6 +38549,15 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/engine, /area/science/xenobiology) +"lJK" = ( +/obj/effect/landmark/blobstart, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "lKd" = ( /obj/machinery/firealarm{ pixel_y = 28 @@ -38670,6 +38775,15 @@ }, /turf/open/floor/plasteel/white, /area/science/xenobiology) +"lQo" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "lQB" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -38782,6 +38896,9 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"lTx" = ( +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "lTC" = ( /obj/machinery/light, /obj/machinery/disposal/bin, @@ -39770,6 +39887,10 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"mnp" = ( +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "mnN" = ( /obj/structure/chair{ dir = 4 @@ -40782,6 +40903,15 @@ /obj/effect/turf_decal/trimline/yellow/filled/line, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"mEQ" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "mFg" = ( /obj/machinery/airalarm{ dir = 4; @@ -41188,6 +41318,21 @@ }, /turf/open/floor/plasteel/white, /area/science/research) +"mQO" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "mQY" = ( /obj/effect/turf_decal/stripes/end{ dir = 4 @@ -41275,10 +41420,6 @@ }, /turf/open/floor/wood, /area/crew_quarters/heads/captain) -"mSg" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "mSl" = ( /obj/structure/closet/l3closet/scientist, /obj/effect/turf_decal/trimline/purple/filled/line{ @@ -41552,6 +41693,9 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"mYX" = ( +/turf/closed/wall/r_wall, +/area/maintenance/starboard/aft) "mZa" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 5 @@ -41882,6 +42026,21 @@ }, /turf/open/floor/plating, /area/science/robotics/lab) +"ncw" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "ncA" = ( /obj/machinery/button/door{ desc = "A remote control-switch for shuttle construction storage."; @@ -43063,14 +43222,6 @@ }, /turf/open/floor/plasteel, /area/security/prison/hallway) -"nDW" = ( -/obj/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "nEu" = ( /obj/effect/turf_decal/loading_area{ dir = 1 @@ -43270,13 +43421,6 @@ }, /turf/open/floor/plating, /area/maintenance/aft) -"nJj" = ( -/obj/machinery/holopad, -/obj/machinery/door/firedoor/border_only{ - dir = 8 - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "nJl" = ( /obj/effect/turf_decal/pool{ dir = 8 @@ -43346,6 +43490,13 @@ }, /turf/closed/wall, /area/engine/atmos_distro) +"nKi" = ( +/obj/machinery/rack_creator, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "nKv" = ( /obj/effect/turf_decal/bot_white/right, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2, @@ -43499,6 +43650,18 @@ }, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/cmo) +"nQz" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8; + external_pressure_bound = 140; + plane = -2; + pressure_checks = 0 + }, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "nQC" = ( /obj/effect/spawner/structure/window/reinforced/shutter, /obj/structure/cable{ @@ -43592,6 +43755,18 @@ }, /turf/open/floor/plasteel/white, /area/medical/storage) +"nSD" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 9 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "nSI" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 @@ -43683,15 +43858,6 @@ }, /turf/open/floor/plasteel/white, /area/science/research) -"nTI" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "nTR" = ( /obj/item/cigbutt/roach, /turf/open/floor/plating, @@ -43773,6 +43939,10 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"nUE" = ( +/obj/structure/table, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "nUH" = ( /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 1 @@ -44522,6 +44692,16 @@ "omk" = ( /turf/template_noop, /area/maintenance/fore) +"omv" = ( +/obj/structure/window/reinforced, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "omI" = ( /obj/item/instrument/piano_synth{ pixel_x = -10 @@ -45375,6 +45555,15 @@ /obj/effect/turf_decal/trimline/red/filled/line, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"oDB" = ( +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "1-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "oDR" = ( /obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk{ @@ -45585,6 +45774,16 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engine_smes) +"oJg" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-8" + }, +/obj/structure/ethernet_cable{ + icon_state = "1-4" + }, +/obj/machinery/light, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "oJj" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plating, @@ -46595,20 +46794,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/medical/sleeper) -"piV" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plating{ - icon_state = "platingdmg3" - }, -/area/maintenance/starboard/aft) "pjc" = ( /obj/effect/turf_decal/arrows/white{ color = "#99ccff"; @@ -46630,6 +46815,17 @@ }, /turf/open/floor/plasteel, /area/security/main) +"pkn" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "pkC" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -47566,10 +47762,6 @@ }, /turf/open/space, /area/solar/port/aft) -"pDa" = ( -/obj/machinery/ai/data_core, -/turf/open/floor/circuit/green/telecomms/mainframe, -/area/ai_monitored/secondarydatacore) "pDq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 1 @@ -47863,6 +48055,19 @@ /obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos_distro) +"pLx" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{ + dir = 1; + external_pressure_bound = 120; + plane = -2 + }, +/obj/machinery/camera{ + c_tag = "Secondary AI Core"; + dir = 4; + network = list("ss13","rd") + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "pLQ" = ( /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ @@ -48026,6 +48231,14 @@ /obj/item/stock_parts/subspace/treatment, /turf/open/floor/plasteel/white, /area/storage/tech) +"pPm" = ( +/obj/machinery/airalarm/tcomms{ + dir = 4; + pixel_x = -24 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "pPs" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -48211,6 +48424,15 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /turf/open/floor/plating, /area/maintenance/port/aft) +"pTp" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 8 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "pTL" = ( /obj/structure/sign/departments/minsky/engineering/telecommmunications{ pixel_y = 32 @@ -48409,28 +48631,6 @@ }, /turf/open/floor/plasteel/dark, /area/security/courtroom) -"pYv" = ( -/obj/machinery/camera{ - c_tag = "Secondary AI Core"; - dir = 8; - network = list("ss13","rd") - }, -/obj/machinery/airalarm{ - pixel_y = 24 - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = 27 - }, -/obj/machinery/power/smes/engineering{ - charge = 5e+006; - input_level = 25000; - output_level = 20000 - }, -/obj/structure/cable{ - icon_state = "0-2" - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/secondarydatacore) "pYC" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -48653,6 +48853,14 @@ }, /turf/open/floor/plasteel, /area/hydroponics/garden) +"qdb" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/frame/machine{ + anchored = 1; + state = 2 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "qdv" = ( /turf/open/floor/carpet, /area/crew_quarters/fitness) @@ -48883,6 +49091,11 @@ /obj/effect/turf_decal/trimline/blue/filled/warning, /turf/open/floor/plasteel/dark, /area/bridge) +"qiX" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plating, +/area/ai_monitored/secondarydatacore) "qjc" = ( /obj/structure/disposalpipe/sorting/mail{ sortType = 10 @@ -48935,18 +49148,6 @@ }, /turf/open/floor/plasteel/dark, /area/security/courtroom) -"qjZ" = ( -/obj/machinery/power/apc{ - areastring = "/area/maintenance/starboard/aft"; - dir = 1; - name = "Starboard Quarter Maintenance APC"; - pixel_y = 23 - }, -/obj/structure/cable{ - icon_state = "0-2" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "qko" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -49633,16 +49834,6 @@ }, /turf/open/floor/wood, /area/lawoffice) -"qzd" = ( -/obj/machinery/airalarm{ - dir = 8; - pixel_x = 24 - }, -/obj/machinery/computer/ai_control_console{ - dir = 8 - }, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "qzt" = ( /obj/machinery/door/airlock/external{ name = "Engineering External Access"; @@ -49694,6 +49885,11 @@ }, /turf/open/space/basic, /area/ai_monitored/turret_protected/aisat_interior) +"qAr" = ( +/obj/effect/turf_decal/trimline/purple/filled/line, +/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "qAt" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -50072,12 +50268,6 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard/fore) -"qJg" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/turret_protected/ai) "qJt" = ( /obj/machinery/door/firedoor/border_only{ dir = 1 @@ -50217,20 +50407,6 @@ }, /turf/open/floor/plating, /area/storage/tech) -"qLi" = ( -/obj/machinery/camera{ - c_tag = "MiniSat - Monitoring room"; - dir = 8; - network = list("minisat","ss13") - }, -/obj/machinery/newscaster/security_unit{ - pixel_x = 28 - }, -/obj/machinery/computer/ai_resource_distribution{ - dir = 8 - }, -/turf/open/floor/plasteel/grimy, -/area/ai_monitored/turret_protected/aisat_interior) "qLt" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -51281,6 +51457,18 @@ }, /turf/open/floor/plating, /area/construction) +"rjl" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "rjo" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 @@ -51572,13 +51760,6 @@ /obj/machinery/light, /turf/open/floor/plasteel, /area/crew_quarters/dorms) -"rqW" = ( -/obj/structure/window/reinforced, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "rqZ" = ( /obj/machinery/door/poddoor{ id = "QMLoaddoor"; @@ -51935,6 +52116,22 @@ }, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/cmo) +"rzU" = ( +/obj/machinery/power/terminal{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/purple/filled/warning{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "rAb" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/components/binary/pump/layer2{ @@ -51985,6 +52182,15 @@ }, /turf/open/floor/plasteel, /area/engine/atmos_distro) +"rBx" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "rBz" = ( /obj/item/radio/intercom{ pixel_y = -27 @@ -52263,15 +52469,6 @@ /obj/machinery/teleport/station, /turf/open/floor/plating, /area/teleporter) -"rGM" = ( -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/structure/cable/yellow{ - icon_state = "1-8" - }, -/turf/open/floor/plasteel/dark/telecomms, -/area/ai_monitored/turret_protected/ai) "rHf" = ( /turf/open/floor/engine/vacuum, /area/engine/atmos_distro) @@ -52474,6 +52671,32 @@ }, /turf/open/floor/plating, /area/maintenance/department/electrical) +"rKn" = ( +/obj/machinery/power/apc/highcap{ + areastring = "/area/ai_monitored/secondarydatacore"; + dir = 4; + name = "AI Secondary Datacore"; + pixel_x = 24 + }, +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/table, +/obj/item/circuitboard/machine/server_cabinet, +/obj/item/circuitboard/machine/ai_data_core, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Secondary AI Core"; + dir = 8; + network = list("ss13","rd") + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "rKs" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, @@ -52588,6 +52811,13 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) +"rOm" = ( +/obj/machinery/computer/ai_overclocking, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "rOz" = ( /obj/structure/table, /obj/item/storage/belt/utility, @@ -54308,6 +54538,18 @@ }, /turf/open/floor/plasteel, /area/science/nanite) +"sDx" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "sDG" = ( /obj/structure/closet{ name = "Evidence Closet" @@ -54317,6 +54559,12 @@ }, /turf/open/floor/plasteel, /area/security/brig) +"sDM" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "sEr" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -54702,6 +54950,16 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/theatre) +"sKT" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "sKX" = ( /obj/structure/table, /obj/item/clothing/gloves/color/latex, @@ -54759,12 +55017,6 @@ }, /turf/open/floor/plasteel/dark, /area/bridge) -"sLZ" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on{ - dir = 4 - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "sMh" = ( /obj/structure/filingcabinet, /obj/machinery/light_switch{ @@ -55391,6 +55643,15 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"sYO" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/ethernet_cable{ + icon_state = "1-2" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "sZn" = ( /obj/structure/table/wood, /obj/item/stamp/captain{ @@ -56292,12 +56553,26 @@ }, /turf/open/floor/plasteel/white, /area/medical/virology) +"trH" = ( +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 6 + }, +/obj/item/twohanded/required/kirbyplants/random, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "tsu" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 }, /turf/open/floor/plasteel, /area/hallway/primary/fore) +"tsx" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{ + external_pressure_bound = 120; + plane = -2 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "tsS" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, @@ -56421,12 +56696,6 @@ }, /turf/open/floor/plasteel/white, /area/science/mixing) -"twt" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 4 - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "twv" = ( /obj/effect/spawner/structure/window, /obj/machinery/door/firedoor/border_only{ @@ -56451,6 +56720,15 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"txn" = ( +/obj/structure/window/reinforced{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "txG" = ( /obj/machinery/light{ dir = 1 @@ -56787,6 +57065,13 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) +"tEQ" = ( +/obj/machinery/rnd/production/circuit_imprinter/department/netmin, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "tEV" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ @@ -57309,6 +57594,14 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/fore) +"tPR" = ( +/obj/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "tPY" = ( /obj/machinery/light/small, /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ @@ -57346,17 +57639,6 @@ }, /turf/open/floor/plasteel, /area/clerk) -"tQv" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8; - external_pressure_bound = 140; - pressure_checks = 0 - }, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "tQD" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, @@ -57621,9 +57903,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"tXb" = ( -/turf/open/floor/circuit/green/telecomms/mainframe, -/area/ai_monitored/secondarydatacore) "tXk" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 4 @@ -57861,6 +58140,10 @@ }, /turf/open/floor/circuit, /area/ai_monitored/turret_protected/ai_upload) +"uaD" = ( +/obj/structure/grille, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "uaL" = ( /obj/machinery/light/small{ dir = 1 @@ -59141,30 +59424,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"uFS" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 4 - }, -/obj/machinery/doorButtons/access_button{ - idDoor = "secondary_aicore_exterior"; - idSelf = "secondary_aicore_controller"; - name = "Secondary AI Core Access Button"; - pixel_x = -24; - pixel_y = 8; - req_one_access_txt = "30;70" - }, -/obj/machinery/doorButtons/airlock_controller{ - idExterior = "secondary_aicore_exterior"; - idInterior = "secondary_aicore_interior"; - idSelf = "secondary_aicore_controller"; - name = "Secondary AI Core Access Console"; - pixel_x = -26; - pixel_y = -6; - req_one_access_txt = "30;70" - }, -/obj/machinery/portable_atmospherics/canister/nitrogen, -/turf/open/floor/circuit/telecomms/server, -/area/ai_monitored/secondarydatacore) "uFW" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/plating, @@ -59710,24 +59969,6 @@ /obj/item/stack/sheet/mineral/plasma, /turf/open/floor/plasteel/white, /area/medical/virology) -"uSq" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/structure/cable{ - icon_state = "2-4" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "uSG" = ( /obj/machinery/power/apc{ areastring = "/area/engine/foyer"; @@ -60551,6 +60792,28 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) +"vkE" = ( +/obj/machinery/camera{ + c_tag = "Secondary AI Core"; + dir = 8; + network = list("ss13","rd") + }, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/obj/machinery/power/smes/engineering{ + charge = 5e+006; + input_level = 25000; + output_level = 20000 + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "vkJ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -60760,6 +61023,12 @@ }, /turf/open/floor/plating, /area/maintenance/port/aft) +"vsl" = ( +/obj/structure/window/reinforced{ + dir = 4 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "vst" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ dir = 4 @@ -60875,6 +61144,18 @@ /obj/machinery/portable_atmospherics/canister/toxins, /turf/open/floor/plating, /area/construction/mining/aux_base) +"vuY" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "vvd" = ( /obj/structure/lattice/catwalk, /obj/structure/cable/yellow{ @@ -62529,6 +62810,13 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"wcX" = ( +/obj/machinery/airalarm{ + dir = 8; + pixel_x = 24 + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "wdb" = ( /obj/structure/door_assembly/door_assembly_mhatch, /turf/open/floor/plating, @@ -62572,14 +62860,6 @@ }, /turf/open/floor/plasteel, /area/quartermaster/office) -"wer" = ( -/obj/effect/decal/cleanable/dirt/dust, -/obj/structure/frame/machine{ - anchored = 1; - state = 2 - }, -/turf/open/floor/circuit/green/telecomms, -/area/ai_monitored/turret_protected/ai) "weD" = ( /obj/machinery/disposal/deliveryChute{ dir = 8 @@ -62753,6 +63033,12 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"wjt" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "wjG" = ( /obj/structure/reagent_dispensers/water_cooler, /turf/open/floor/wood, @@ -62980,13 +63266,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/chemistry) -"wnI" = ( -/obj/structure/frame/machine{ - anchored = 1; - state = 2 - }, -/turf/open/floor/circuit/green/telecomms/mainframe, -/area/ai_monitored/secondarydatacore) "wnN" = ( /obj/structure/table, /obj/item/storage/toolbox/mechanical{ @@ -64183,6 +64462,13 @@ }, /turf/open/floor/plasteel/white, /area/science/nanite) +"wOd" = ( +/obj/machinery/holopad, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "wOj" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 6 @@ -64433,6 +64719,14 @@ /obj/effect/turf_decal/trimline/brown/filled/warning, /turf/open/floor/plasteel, /area/quartermaster/sorting) +"wVN" = ( +/obj/structure/table, +/obj/item/storage/toolbox/mechanical, +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "wVP" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 @@ -64459,6 +64753,17 @@ /obj/machinery/light/small, /turf/open/floor/plating, /area/maintenance/aft) +"wVY" = ( +/obj/machinery/camera{ + c_tag = "MiniSat - Monitoring room"; + dir = 8; + network = list("minisat","ss13") + }, +/obj/machinery/newscaster/security_unit{ + pixel_x = 28 + }, +/turf/open/floor/plasteel/grimy, +/area/ai_monitored/turret_protected/aisat_interior) "wWl" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, @@ -65539,6 +65844,12 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, /turf/open/floor/plasteel, /area/engine/engineering) +"xAS" = ( +/obj/structure/ethernet_cable{ + icon_state = "1-8" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/secondarydatacore) "xAW" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cloth_curtain{ @@ -65773,6 +66084,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood, /area/library) +"xFQ" = ( +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "xFW" = ( /obj/effect/landmark/stationroom/maint/fivexfour, /turf/template_noop, @@ -65984,6 +66301,15 @@ /obj/item/twohanded/required/kirbyplants/random, /turf/open/floor/carpet, /area/library) +"xLm" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/window/reinforced{ + dir = 8 + }, +/turf/open/floor/catwalk_floor/telecomms, +/area/ai_monitored/turret_protected/ai) "xLR" = ( /obj/structure/table, /obj/item/flashlight/lamp/green{ @@ -66224,6 +66550,19 @@ }, /turf/open/floor/plating, /area/maintenance/starboard) +"xRG" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 4 + }, +/obj/effect/landmark/start/yogs/network_admin, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/secondarydatacore) "xRO" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -66259,22 +66598,6 @@ }, /turf/open/floor/plating, /area/maintenance/port/aft) -"xTe" = ( -/obj/machinery/door/firedoor/border_only, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "xTZ" = ( /obj/structure/cloth_curtain{ color = "#99ccff" @@ -66338,13 +66661,6 @@ }, /turf/open/floor/plasteel/dark, /area/engine/atmos_distro) -"xUW" = ( -/obj/structure/frame/machine{ - anchored = 1; - state = 2 - }, -/turf/open/floor/circuit/green/telecomms, -/area/ai_monitored/turret_protected/ai) "xVm" = ( /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 4 @@ -97008,7 +97324,7 @@ dcc qsZ lFe rEb -cyZ +eUd kLA sYk rtp @@ -97519,7 +97835,7 @@ fPM wKU bVJ rzx -iRV +dxO aSV agz aJw @@ -107869,8 +108185,8 @@ kik eEZ jWq vmm -qzd -qLi +wcX +wVY mtW tiN gtB @@ -109405,11 +109721,11 @@ cva cva cva gQa -jzm -fIs -rGM -hbO -lbr +xFQ +txn +oDB +vsl +wjt yap cva cva @@ -109660,15 +109976,15 @@ pEf pEf cva cva -abx +eFt nLw -nDW +tPR enZ nSN xlV -dFJ +giM rjo -wer +qdb cva cva pEf @@ -109917,15 +110233,15 @@ pEf koy cva cva -lHO -rjo -rqW -rjo -hJq -sAu -dFJ -rjo -xlV +bkY +sYO +omv +sYO +jgW +agv +feK +sYO +bOz cva cva vUh @@ -110174,15 +110490,15 @@ pEf pEf cva cva -xUW +dTf rjo -rqW +aLA jTn nVK enZ -kSZ +sKT pyn -ikV +ehY cva cva pEf @@ -110433,11 +110749,11 @@ cva cva cva mWE -qJg -aSy -nJj -nTI -pnR +sDM +xLm +wOd +jKp +wjt kcr cva cva @@ -116796,7 +117112,7 @@ dRo kxz oaO bvK -fdU +acX bys bzM aDa @@ -116829,7 +117145,7 @@ atN atN atN atN -cOe +mYX fXS cOe gpq @@ -117081,11 +117397,11 @@ iKk oGM mwf oxg -uFS -sLZ -ief -tXb -oGM +tsx +pPm +pTp +pLx +bnB oGM fXS cOe @@ -117312,7 +117628,7 @@ eEA bvK bxm byu -dbJ +euD bCf aGs bvK @@ -117338,11 +117654,11 @@ rnA oGM mQY nlV -gdI -kJz -mSg -wnI -oGM +lTx +lTx +cde +hnb +oJg oGM fXS cOe @@ -117597,9 +117913,9 @@ fKM oGM oxg oxg -dBH -pDa -oGM +cde +izK +jPF oGM fXS cNW @@ -117849,14 +118165,14 @@ alj aXb xix uVI -bRR -hYY -gDs -fFO +lpZ +rzU +jJv +gcd oxg -twt -wnI -oGM +cde +izK +jkO oGM fXS bNA @@ -118107,13 +118423,13 @@ pWH pgx gxq oGM -pYv -goW -hOU +vkE +vuY +efW oxg -tQv -iiJ -oGM +cde +duc +kkY oGM fXS cOe @@ -118364,13 +118680,13 @@ aRv bQZ bQZ oGM -oGM -oGM -oGM -oGM -oGM -oGM -oGM +tEQ +sDx +lej +oxg +cde +izK +kcA oGM fXS cjE @@ -118618,17 +118934,17 @@ cOe cOe alZ aMC -cOe thv cOe -cOe -cOe -cOe -ezr oGM +nKi +xRG +bKx +bUU +lQo +xAS oGM oGM -cOe fXS cjD cjD @@ -118872,20 +119188,20 @@ lNU cNW qHY cNW -cNW +bNB cdR xHc -bNB -cNW -cOe -cOe cNW -iVk -cNW -cNW -ceR -fIH cOe +oGM +rOm +rBx +qAr +qiX +mnp +lTx +oGM +nUE mfN cjD bQq @@ -119128,22 +119444,22 @@ axl cNW cNW xSu -bMB cNW cNW -aMC -cNW cNW -cOe -cOe -bNB -cOe +aMC cNW -axl cOe -cNW -qjZ -uSq +oGM +wVN +flr +cPu +qiX +gRT +ddQ +oGM +bNA +ncw kQW iwk mNK @@ -119385,22 +119701,22 @@ cNZ cNZ bSm aWg -cNZ -cNZ -cNZ -aMD -dMA -jPU -dMA -aue -dMA -dMA -dMA -frD -piV -xTe -bCw -bKB +kYZ +bMB +cNW +mEQ +cNW +cOe +oGM +fcx +rKn +trH +oxg +nQz +iWz +oGM +cou +aob cjD shT clz @@ -119642,22 +119958,22 @@ nex cNW cNW cNW +mQO +cOe cNW +mEQ cNW -woo -cNW -cNW -cNW -cNW -cNW -cNW -cNW -cNW -umE -cNW -cNW -arG -cNW +cOe +oGM +oGM +oGM +oGM +oGM +oGM +oGM +oGM +cOe +rjl cjD cjD cjD @@ -119899,22 +120215,22 @@ iKq iKq eoH cNW -cou -cou -cae -cmo -cNW -iKq -iKq -cCG -cNW -ccW -hLb -jjr -cNW -iKq -iKq -hNs +lzq +exA +exA +cGu +aJj +aJj +aJj +aJj +aJj +aJj +aJj +gqo +aJj +pkn +lJK +nSD cNW gXs aaf @@ -120158,20 +120474,20 @@ iKq euJ cOe cOe -cae cOe -vKX -iKq -iKq -iKq -yeN +cNW +ezr cOe -wZs -jjr +cOe +axl cNW -iKq -iKq -iKq +bNB +cOe +czb +uaD +fIh +cOe +cdR cNW aaa aaa @@ -120413,22 +120729,22 @@ iKq iKq iKq cNW -chH cNW cNW +woo cNW cNW -iKq -iKq -iKq cNW -chH -cOe -tPY cNW -iKq -iKq -iKq +cNW +cNW +cNW +cNW +umE +cNW +cNW +arG +cNW cNW gXs gXs @@ -120670,22 +120986,22 @@ cNW bPp bPp cNW +cou +cou +cae +cmo cNW +iKq +iKq +cCG cNW -aaf -pEf -cNW -bPp -bPp -bPp -cNW -cNW -cNW -kRp +ccW +hLb +jjr cNW iKq iKq -iKq +hNs cNW aoV aaa @@ -120925,20 +121241,20 @@ aaf aaa aaa aaf -aaa -aaa -aoV -aaf -aaf -pEf -aaf -aaa -aaa -aaa -aaf -aaf +gXs cNW -szB +cOe +cOe +cae +cOe +vKX +iKq +iKq +iKq +yeN +cOe +wZs +jjr cNW iKq iKq @@ -121183,23 +121499,23 @@ aaa aaa aaf aaa -aaa -aoV -aaa -aaa -aag -aaf -aaa -aaa -aaa -aaa -aaf cNW -jSR +chH cNW cNW cNW cNW +iKq +iKq +iKq +cNW +chH +cOe +tPY +cNW +iKq +iKq +iKq cNW gXs gXs @@ -121290,199 +121606,8 @@ aaa aaa aaa aaa -"} -(211,1,1) = {" -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -afa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaf -aaf -aaa -aaf -aaf -aaf -aaa -aaf -gXs -gXs -aaa -aaa -aaf -aaa -aaf -aaa -aaa -aaa -aaf -aaa -aaa -aaa -aaa -aaa -pEf -aaf -aaa -aaa -aaa -aaa -aaf -aag -aag -aag -aoV -aaa -aaa -aoV -aaa -aaa -aaa -aoV -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +"} +(211,1,1) = {" aaa aaa aaa @@ -121547,8 +121672,6 @@ aaa aaa aaa aaa -"} -(212,1,1) = {" aaa aaa aaa @@ -121593,6 +121716,7 @@ aaa aaa aaa aaa +afa aaa aaa aaa @@ -121612,18 +121736,48 @@ aaa aaa aaa aaa +aaf +aaf aaa +aaf +aaf +aaf aaa +aaf +gXs +gXs aaa aaa +aaf aaa +aaf aaa aaa aaa +aaf aaa +cNW +cNW +cNW +aaf +pEf +cNW +hYR +bPp +bPp +cNW +cNW +cNW +kRp +cNW +iKq +iKq +iKq +cNW aaa aaa aaa +aoV aaa aaa aaa @@ -121677,31 +121831,24 @@ aaa aaa aaa aaa -aaf aaa aaa aaa -aaf aaa aaa -aaf aaa aaa aaa aaa -aaf aaa -aaf aaa aaa aaa -aag aaa aaa aaa aaa aaa -pEf aaa aaa aaa @@ -121709,7 +121856,6 @@ aaa aaa aaa aaa -aag aaa aaa aaa @@ -121717,6 +121863,8 @@ aaa aaa aaa aaa +"} +(212,1,1) = {" aaa aaa aaa @@ -121804,8 +121952,6 @@ aaa aaa aaa aaa -"} -(213,1,1) = {" aaa aaa aaa @@ -121847,24 +121993,44 @@ aaa aaa aaa aaa +aaf aaa aaa aaa +aaf aaa aaa +aaf aaa aaa aaa aaa +aaf aaa +aaf aaa aaa aaa +aag aaa aaa +aoV +aaf +aaf +pEf +aaf aaa aaa aaa +aaf +aaf +cNW +szB +cNW +iKq +iKq +iKq +cNW aaa aaa aaa @@ -121934,31 +122100,80 @@ aaa aaa aaa aaa -aaf aaa aaa aaa -aaf aaa aaa -aaf aaa aaa aaa aaa -aaf aaa -aaf aaa aaa aaa -aag aaa aaa aaa aaa aaa -pEf +aaa +aaa +"} +(213,1,1) = {" +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -121966,24 +122181,113 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaf +aaa +aaa +aaa aaf aaa aaa +aaf +aaa aaa aaa aaa +aaf aaa +aaf aaa aaa aaa +aag aaa aaa +aoV aaa aaa +aag +aaf aaa aaa aaa aaa +aaf +cNW +jSR +cNW +cNW +cNW +cNW +cNW aaa aaa aaa @@ -122061,8 +122365,6 @@ aaa aaa aaa aaa -"} -(214,1,1) = {" aaa aaa aaa @@ -122075,6 +122377,10 @@ aaa aaa aaa aaa +"} +(214,1,1) = {" +aaa +aaa aaa aaa aaa @@ -122191,44 +122497,54 @@ aaa aaa aaa aaa -aaf aaa aaa aaa -aaf aaa aaa -aag aaa aaa aaa aaa -aaf aaa aaf aaa aaa aaa +aaf +aaa +aaa aag aaa aaa aaa aaa +aaf aaa aaf aaa aaa aaa +aag +aaa aaa aaa aaa aaa +pEf aaf aaa aaa aaa aaa +aaf +aag +aag +aag +aoV +aaa aaa +aoV aaa aaa aaa @@ -122472,15 +122788,15 @@ aaa aaa aaa aaa +pEf aaa aaa aaa aaa -aae aaa aaa aaa -aaf +aag aaa aaa aaa @@ -122729,7 +123045,7 @@ aaa aaa aaa aaa -aaa +pEf aaa aaa aaa @@ -122986,6 +123302,7 @@ aaa aaa aaa aaa +aaf aaa aaa aaa @@ -122993,8 +123310,7 @@ aaa aaa aaa aaa -aaa -aaa +aaf aaa aaa aaa @@ -123247,11 +123563,11 @@ aaa aaa aaa aaa +aae aaa aaa aaa -aaa -aaa +aaf aaa aaa aaa @@ -123508,7 +123824,7 @@ aaa aaa aaa aaa -aaa +aaf aaa aaa aaa diff --git a/_maps/map_files/YogsDelta/YogsDelta.dmm b/_maps/map_files/YogsDelta/YogsDelta.dmm index 2273af75c1c4..760b2e907fde 100644 --- a/_maps/map_files/YogsDelta/YogsDelta.dmm +++ b/_maps/map_files/YogsDelta/YogsDelta.dmm @@ -66011,7 +66011,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/computer/ai_control_console{ +{ dir = 1 }, /turf/open/floor/plasteel/dark, @@ -66054,9 +66054,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/computer/ai_resource_distribution{ - dir = 1 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "cao" = ( @@ -81321,9 +81318,6 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cAD" = ( -/obj/machinery/computer/ai_resource_distribution{ - dir = 1 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/secondarydatacore) "cAE" = ( @@ -127272,7 +127266,7 @@ /obj/structure/table/reinforced, /obj/item/aicard, /obj/effect/turf_decal/bot, -/obj/item/circuitboard/computer/ai_upload_download, +, /obj/item/disk/holodisk/tutorial/AICore, /turf/open/floor/plasteel, /area/crew_quarters/heads/hor) diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index 85ea68c70876..11106b57a5ce 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -61,3 +61,24 @@ GLOBAL_LIST_INIT(ai_project_categories, list( #define MAX_AI_BITCOIN_MINED_PER_TICK 350 //Self explanatory, see MAX_AI_BITCOIN_MINED_PER_TICK * this = max money 1 AI can contribute per tick. (17,5 credits every 2 seconds, max 63k over 2 hours) #define AI_BITCOIN_PRICE 0.05 + + +//How much RAM and CPU a core needs locally to be functional +#define AI_CORE_CPU_REQUIREMENT 1 +#define AI_CORE_RAM_REQUIREMENT 1 + +//For network based research and tasks. Since each network are going to contribute to a "global" pool of research there's no point in making this more complicated or modular +//Adding an entry here automatically adds it to the UI and allows CPU to be allocated. Just use your define in the network process() to do stuff +#define AI_CRYPTO "Cryptocurrency Mining" + +GLOBAL_LIST_INIT(possible_ainet_activities, list( + "[AI_CRYPTO]" +)) + +GLOBAL_LIST_INIT(ainet_activity_tagline, list( + "[AI_CRYPTO]" = "Use CPU to generate credits!" +)) + +GLOBAL_LIST_INIT(ainet_activity_description, list( + "[AI_CRYPTO]" = "Using CPU to mine NTCoin should allow for a meager sum of passive credit income." +)) diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm index b1af0b7cd6f5..a95acefa16f6 100644 --- a/code/__DEFINES/footsteps.dm +++ b/code/__DEFINES/footsteps.dm @@ -6,6 +6,7 @@ #define FOOTSTEP_GRASS "grass" #define FOOTSTEP_WATER "water" #define FOOTSTEP_LAVA "lava" +#define FOOTSTEP_CATWALK "catwalk" //barefoot sounds #define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot" #define FOOTSTEP_WOOD_CLAW "woodclaw" @@ -71,6 +72,12 @@ GLOBAL_LIST_INIT(footstep, list( 'sound/effects/footstep/lava1.ogg', 'sound/effects/footstep/lava2.ogg', 'sound/effects/footstep/lava3.ogg'), 100, 0), + FOOTSTEP_CATWALK = list(list( + 'sound/effects/footstep/catwalk1.ogg', + 'sound/effects/footstep/catwalk2.ogg', + 'sound/effects/footstep/catwalk3.ogg', + 'sound/effects/footstep/catwalk4.ogg', + 'sound/effects/footstep/catwalk5.ogg'), 100, 1), )) //bare footsteps lists GLOBAL_LIST_INIT(barefootstep, list( diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index b7389061fba6..6f8bf703e1a9 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -28,6 +28,7 @@ #define LATTICE_LAYER 2.2 #define DISPOSAL_PIPE_LAYER 2.25 #define GAS_PIPE_HIDDEN_LAYER 2.35 //layer = initial(layer) + piping_layer / 1000 in atmospherics/update_icon() to determine order of pipe overlap +#define ETHERNET_LAYER 2.38 #define WIRE_LAYER 2.4 #define WIRE_TERMINAL_LAYER 2.45 #define UNDER_CATWALK 2.454 diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index d9fdd3d79a75..8ae6027d1b3e 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -47,6 +47,7 @@ #define MC_CHARGE "CHARGE" #define MC_AI "AI" #define MC_SENSORS "SENSORS" +#define MC_AI_NETWORK "AINETWORK" //NTNet stuff, for modular computers // NTNet module-configuration values. Do not change these. If you need to add another use larger number (5..6..7 etc) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index b4455e63a8e1..e33fd3c38b8c 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -8,6 +8,10 @@ #define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL)) #define CULT_POLL_WAIT 2400 +#define UNDERFLOOR_HIDDEN 0 +#define UNDERFLOOR_VISIBLE 1 +#define UNDERFLOOR_INTERACTABLE 2 + /proc/get_area_name(atom/X, format_text = FALSE, is_sensor = FALSE) var/area/A = isarea(X) ? X : get_area(X) if(!A) diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 331f30de8bd1..eb469d6bd9e3 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -1,4 +1,5 @@ GLOBAL_LIST_EMPTY(cable_list) //Index for all cables, so that powernets don't have to look through the entire world all the time +GLOBAL_LIST_EMPTY(ethernet_cable_list) //Index for all ethernet cables, so that ainets don't have to look through the entire world all the time GLOBAL_LIST_EMPTY(portals) //list of all /obj/effect/portal GLOBAL_LIST_EMPTY(airlocks) //list of all airlocks GLOBAL_LIST_EMPTY(mechas_list) //list of all mechs. Used by hostile mobs target tracking. @@ -8,7 +9,7 @@ GLOBAL_LIST_EMPTY(navigation_computers) //list of all /obj/machinery/computer GLOBAL_LIST_EMPTY(syndicate_shuttle_boards) //important to keep track of for managing nukeops war declarations. GLOBAL_LIST_EMPTY(navbeacons) //list of all bot nagivation beacons, used for patrolling. GLOBAL_LIST_EMPTY(teleportbeacons) //list of all tracking beacons used by teleporters -GLOBAL_LIST_EMPTY(deliverybeacons) //list of all MULEbot delivery beacons. +GLOBAL_LIST_EMPTY(deliverybeacons) //lisAt of all MULEbot delivery beacons. GLOBAL_LIST_EMPTY(deliverybeacontags) //list of all tags associated with delivery beacons. GLOBAL_LIST_EMPTY(nuke_list) GLOBAL_LIST_EMPTY(alarmdisplay) //list of all machines or programs that can display station alerts diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 99bfb0a61c5b..50b3c4928858 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -256,6 +256,21 @@ SUBSYSTEM_DEF(job) return TRUE return FALSE +/datum/controller/subsystem/job/proc/FillNetminPosition() + var/datum/job/job = GetJob("Network Admin") + if(!job) + return + for(var/i = job.total_positions, i > 0, i--) + if(job.current_positions >= job.total_positions) //If we assign a netmin before this proc is run, (malf rework?) + return TRUE + for(var/level in level_order) + var/list/candidates = list() + candidates = FindOccupationCandidates(job, level) + if(candidates.len) + var/mob/dead/new_player/candidate = pick(candidates) + if(AssignRole(candidate, "Network Admin")) + break + /// Rolls a number of security based on the roundstart population /datum/controller/subsystem/job/proc/FillSecurityPositions() var/coeff = CONFIG_GET(number/min_security_scaling_coeff) @@ -339,7 +354,8 @@ SUBSYSTEM_DEF(job) //Check for an AI JobDebug("DO, Running AI Check") - FillAIPosition() + if(FillAIPosition()) + FillNetminPosition() JobDebug("DO, AI Check end") //Check for Security diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm index 3c641fac1e62..b176fc561da5 100644 --- a/code/controllers/subsystem/machines.dm +++ b/code/controllers/subsystem/machines.dm @@ -5,9 +5,11 @@ SUBSYSTEM_DEF(machines) var/list/processing = list() var/list/currentrun = list() var/list/powernets = list() + var/list/ainets = list() /datum/controller/subsystem/machines/Initialize() makepowernets() + makeainets() fire() return ..() @@ -22,8 +24,22 @@ SUBSYSTEM_DEF(machines) NewPN.add_cable(PC) propagate_network(PC,PC.powernet) +/datum/controller/subsystem/machines/proc/makeainets() + for(var/datum/ai_network/AN in ainets) + qdel(AN) + ainets.Cut() + + for(var/obj/structure/ethernet_cable/EC in GLOB.ethernet_cable_list) + if(!EC.network) + var/datum/ai_network/NewAN = new() + NewAN.add_cable(EC) + propagate_ai_network(EC,EC.network) + + for(var/obj/machinery/ai/networking/N in GLOB.ai_networking_machines) + N.roundstart_connect() + /datum/controller/subsystem/machines/stat_entry(msg) - msg = "M:[length(processing)]|PN:[length(powernets)]" + msg = "M:[length(processing)]|PN:[length(powernets)]|AN:[length(ainets)]" return ..() @@ -58,8 +74,18 @@ SUBSYSTEM_DEF(machines) NewPN.add_cable(PC) propagate_network(PC,PC.powernet) +/datum/controller/subsystem/machines/proc/setup_template_ainets(list/cables) + for(var/A in cables) + var/obj/structure/ethernet_cable/PC = A + if(!PC.network) + var/datum/ai_network/NewPN = new() + NewPN.add_cable(PC) + propagate_ai_network(PC,PC.network) + /datum/controller/subsystem/machines/Recover() if (istype(SSmachines.processing)) processing = SSmachines.processing if (istype(SSmachines.powernets)) powernets = SSmachines.powernets + if (istype(SSmachines.ainets)) + ainets = SSmachines.ainets diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm index d9e137bf2299..44f16d4890ff 100644 --- a/code/controllers/subsystem/minor_mapping.dm +++ b/code/controllers/subsystem/minor_mapping.dm @@ -39,7 +39,7 @@ SUBSYSTEM_DEF(minor_mapping) while(turfs.len && amount > 0) var/turf/T = pick_n_take(turfs) var/obj/item/storage/backpack/satchel/flat/S = new(T) - S.hide(intact=TRUE) + S.hide(intact=(T.underfloor_accessibility < UNDERFLOOR_VISIBLE)) amount-- diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm index 8d849c8c145e..bb8c481f4c68 100644 --- a/code/game/machinery/Beacon.dm +++ b/code/game/machinery/Beacon.dm @@ -16,7 +16,7 @@ Beacon = new(T) Beacon.invisibility = INVISIBILITY_MAXIMUM - hide(T.intact) + hide(T.underfloor_accessibility < UNDERFLOOR_VISIBLE) /obj/machinery/bluespace_beacon/Destroy() QDEL_NULL(Beacon) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index cce089a75e6a..da53b455f929 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -363,15 +363,6 @@ new /obj/item/card/id/captains_spare/temporary(loc) COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) priority_announce("The emergency spare ID has been printed by [authorize_name].", "Emergency Spare ID Warning System", RANDOM_REPORT_SOUND) - if("printAIControlCode") - if(authenticated_as_non_silicon_head(usr)) - if(!COOLDOWN_FINISHED(src, important_action_cooldown)) - return - playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) - GLOB.ai_control_code = random_nukecode(6) - new /obj/item/paper/ai_control_code(loc) - COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN) - priority_announce("The AI Control Code been printed by [authorize_name]. All previous codes have been invalidated.", "Central Tech Support", RANDOM_REPORT_SOUND) /obj/machinery/computer/communications/ui_data(mob/user) diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 0110312e5634..158db804d677 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -30,7 +30,7 @@ /obj/machinery/magnetic_module/Initialize() ..() var/turf/T = loc - hide(T.intact) + hide(T.underfloor_accessibility < UNDERFLOOR_VISIBLE) center = T SSradio.add_object(src, freq, RADIO_MAGNETS) return INITIALIZE_HINT_LATELOAD diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index c70c592003f2..58a1f425eaa9 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -27,7 +27,7 @@ set_codes() var/turf/T = loc - hide(T.intact) + hide(T.underfloor_accessibility < UNDERFLOOR_VISIBLE) if(codes["patrol"]) if(!GLOB.navbeacons["[z]"]) GLOB.navbeacons["[z]"] = list() @@ -86,8 +86,8 @@ /obj/machinery/navbeacon/attackby(obj/item/I, mob/user, params) var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) + return // prevent intraction when T-scanner revealed if(I.tool_behaviour == TOOL_SCREWDRIVER) open = !open @@ -119,9 +119,8 @@ . = ..() var/ai = isAI(user) var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) + return // prevent intraction when T-scanner revealed if(!open && !ai) // can't alter controls if not open, unless you're an AI to_chat(user, span_warning("The beacon's control cover is closed!")) return diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 595356289b9b..dd3f0ef360df 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -450,7 +450,7 @@ if(!T.broken && !T.burnt) new T.floor_tile(T) T.make_plating() - return !new_turf.intact + return !(new_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) /obj/item/mecha_parts/mecha_equipment/cable_layer/proc/layCable(var/turf/new_turf) if(equip_ready || !istype(new_turf) || !dismantleFloor(new_turf)) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 3c8e2843d528..f94e0596c748 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -146,7 +146,7 @@ continue if(isturf(O.loc)) var/turf/T = O.loc - if(T.intact && O.level == 1) //hidden under the floor + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && O.level == 1) //hidden under the floor continue if(lifetime % reagent_divisor) reagents.reaction(O, VAPOR, fraction) diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index e83f4da302a0..e28dba3d7315 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -230,7 +230,7 @@ for(var/atom/movable/AM in T) if(AM.type == src.type) continue - if(T.intact && AM.level == 1) //hidden under the floor + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && AM.level == 1) //hidden under the floor continue reagents.reaction(AM, TOUCH, fraction) diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index df6723de0afb..06a848f31c88 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -534,7 +534,6 @@ name = "secure AI circuit board spawner" loot = list( /obj/item/circuitboard/computer/aiupload, - /obj/item/circuitboard/computer/ai_upload_download, /obj/item/circuitboard/computer/borgupload ) diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm index da0e1b9891fb..dfe4938c9e6f 100644 --- a/code/game/objects/items/RCL.dm +++ b/code/game/objects/items/RCL.dm @@ -178,7 +178,7 @@ if(last) if(get_dist(last, user) == 1) //hacky, but it works var/turf/T = get_turf(user) - if(T.intact || !T.can_have_cabling()) + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling()) last = null return if(get_dir(last, user) == last.d2) @@ -203,7 +203,7 @@ return T = get_turf(user) - if(T.intact || !T.can_have_cabling()) + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling()) return for(var/obj/structure/cable/C in T) @@ -263,7 +263,7 @@ return var/turf/T = get_turf(user) - if(T.intact || !T.can_have_cabling()) + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling()) return loaded.color = colors[current_color_index] diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 32ee802d8443..204d0b9ecc03 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -393,20 +393,12 @@ name = "Shuttle Navigation Computer (Computer Board)" build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom -/obj/item/circuitboard/computer/ai_upload_download - name = "AI Control Console (Computer Board)" - icon_state = "science" - build_path = /obj/machinery/computer/ai_control_console /obj/item/circuitboard/computer/ai_server_overview name = "AI Server Overview Console (Computer Board)" icon_state = "science" build_path = /obj/machinery/computer/ai_server_console -/obj/item/circuitboard/computer/ai_resource_distribution - name = "AI Resource Distribution Console (Computer Board)" - icon_state = "science" - build_path = /obj/machinery/computer/ai_resource_distribution //Security diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 449e9e660fa2..eef412632548 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -63,7 +63,7 @@ if(I.tool_behaviour == TOOL_SCREWDRIVER) if(mode == DISCONNECTED) var/turf/T = loc - if(isturf(T) && !T.intact) + if(isturf(T) && T.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE) attached = locate() in T if(!attached) to_chat(user, span_warning("This device must be placed over an exposed, powered cable node!")) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 0e4bd241045b..ea04b5bdac18 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -10,6 +10,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ new/datum/stack_recipe("fore port spacepod frame", /obj/item/pod_parts/pod_frame/fore_port, 15, time = 30, one_per_turf = 0), \ new/datum/stack_recipe("fore starboard spacepod frame", /obj/item/pod_parts/pod_frame/fore_starboard, 15, time = 30, one_per_turf = 0), \ new/datum/stack_recipe("aft port spacepod frame", /obj/item/pod_parts/pod_frame/aft_port, 15, time = 30, one_per_turf = 0), \ + new/datum/stack_recipe("catwalk floor tile", /obj/item/stack/tile/catwalk_tile, 1, 4, 20), \ new/datum/stack_recipe("aft starboard spacepod frame", /obj/item/pod_parts/pod_frame/aft_starboard, 15, time = 30, one_per_turf = 0), \ // yogs end )) diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 8f0808ac5bda..86c650ad937f 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -403,3 +403,52 @@ /obj/item/stack/tile/eighties/loaded amount = 15 + +//Catwalk Tiles +/obj/item/stack/tile/catwalk_tile //This is our base type, sprited to look maintenance-styled + name = "catwalk plating" + singular_name = "catwalk plating tile" + desc = "Flooring that shows its contents underneath. Engineers love it!" + icon_state = "maint_catwalk" + materials = list(/datum/material/iron=100) + turf_type = /turf/open/floor/catwalk_floor + merge_type = /obj/item/stack/tile/catwalk_tile //Just to be cleaner, these all stack with eachother + +/obj/item/stack/tile/catwalk_tile/sixty + amount = 60 + +/obj/item/stack/tile/catwalk_tile/iron + name = "iron catwalk floor" + singular_name = "iron catwalk floor tile" + icon_state = "iron_catwalk" + turf_type = /turf/open/floor/catwalk_floor/iron + +/obj/item/stack/tile/catwalk_tile/iron_white + name = "white catwalk floor" + singular_name = "white catwalk floor tile" + icon_state = "whiteiron_catwalk" + turf_type = /turf/open/floor/catwalk_floor/iron_white + +/obj/item/stack/tile/catwalk_tile/iron_dark + name = "dark catwalk floor" + singular_name = "dark catwalk floor tile" + icon_state = "darkiron_catwalk" + turf_type = /turf/open/floor/catwalk_floor/iron_dark + +/obj/item/stack/tile/catwalk_tile/flat_white + name = "flat white catwalk floor" + singular_name = "flat white catwalk floor tile" + icon_state = "flatwhite_catwalk" + turf_type = /turf/open/floor/catwalk_floor/flat_white + +/obj/item/stack/tile/catwalk_tile/titanium + name = "titanium catwalk floor" + singular_name = "titanium catwalk floor tile" + icon_state = "titanium_catwalk" + turf_type = /turf/open/floor/catwalk_floor/titanium + +/obj/item/stack/tile/catwalk_tile/iron_smooth //this is the greenish one + name = "smooth iron catwalk floor" + singular_name = "smooth iron catwalk floor tile" + icon_state = "smoothiron_catwalk" + turf_type = /turf/open/floor/catwalk_floor/iron_smooth diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 2a2405095db4..f8b76f338ac3 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -102,7 +102,7 @@ /obj/blob_act(obj/structure/blob/B) if(isturf(loc)) var/turf/T = loc - if(T.intact && level == 1) //the blob doesn't destroy thing below the floor + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && level == 1) //the blob doesn't destroy thing below the floor return take_damage(400, BRUTE, MELEE, 0, get_dir(src, B)) @@ -213,7 +213,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e /obj/fire_act(exposed_temperature, exposed_volume) if(isturf(loc)) var/turf/T = loc - if(T.intact && level == 1) //fire can't damage things hidden below the floor. + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && level == 1) //fire can't damage things hidden below the floor. return if(exposed_temperature && !(resistance_flags & FIRE_PROOF)) take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0) diff --git a/code/game/objects/structures/signs/signs_plaques.dm b/code/game/objects/structures/signs/signs_plaques.dm index 3220e0523054..216ba23cf52b 100644 --- a/code/game/objects/structures/signs/signs_plaques.dm +++ b/code/game/objects/structures/signs/signs_plaques.dm @@ -26,21 +26,6 @@ desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"." icon_state = "kiddieplaque" -/obj/structure/sign/plaques/ai_password - name = "\improper AI default password" - desc = "This plaque contains the default password for AI control consoles onboard this station." - var/control_code = "BUG" - -/obj/structure/sign/plaques/ai_password/Initialize(mapload) - . = ..() - control_code = GLOB.ai_control_code - -/obj/structure/sign/plaques/ai_password/examine(mob/living/user) - . = ..() - if(Adjacent(user)) - . += span_notice("The following digits are stamped into the plaque: [control_code]") - else - . += span_notice("You must be closer to read the code.") /obj/structure/sign/plaques/kiddie/badger name = "\improper Remembrance Plaque" diff --git a/code/game/turfs/openspace/openspace.dm b/code/game/turfs/openspace/openspace.dm index 1cf670c3da6e..0d861d897505 100644 --- a/code/game/turfs/openspace/openspace.dm +++ b/code/game/turfs/openspace/openspace.dm @@ -7,6 +7,8 @@ //mouse_opacity = MOUSE_OPACITY_TRANSPARENT var/can_cover_up = TRUE var/can_build_on = TRUE + overfloor_placed = FALSE + underfloor_accessibility = UNDERFLOOR_INTERACTABLE /turf/open/openspace/debug/update_multiz() ..() diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 4101efd3ac69..dfe5b6c73072 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -16,9 +16,11 @@ var/icon_plating = "plating" thermal_conductivity = 0.040 heat_capacity = 10000 - intact = 1 + var/broken = 0 var/burnt = 0 + + overfloor_placed = TRUE var/floor_tile = null //tile that this floor drops var/list/broken_states var/list/burnt_states @@ -172,7 +174,7 @@ return 1 if(..()) return 1 - if(intact && istype(C, /obj/item/stack/tile)) + if(overfloor_placed && istype(C, /obj/item/stack/tile)) try_replace_tile(C, user, params) return 0 @@ -180,7 +182,7 @@ if(istype(I,/obj/item/jawsoflife/jimmy)) to_chat(user,"The [I] cannot pry tiles.") return - return intact ? pry_tile(I, user) : FALSE + return overfloor_placed ? pry_tile(I, user) : FALSE /turf/open/floor/proc/try_replace_tile(obj/item/stack/tile/T, mob/user, params) if(T.turf_type == type) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 4614d4f06669..cd086783fd72 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -10,7 +10,8 @@ /turf/open/floor/plating name = "plating" icon_state = "plating" - intact = FALSE + overfloor_placed = FALSE + underfloor_accessibility = UNDERFLOOR_INTERACTABLE baseturfs = /turf/baseturf_bottom footstep = FOOTSTEP_PLATING barefootstep = FOOTSTEP_HARD_BAREFOOT diff --git a/code/game/turfs/simulated/floor/plating/catwalk_plating.dm b/code/game/turfs/simulated/floor/plating/catwalk_plating.dm new file mode 100644 index 000000000000..0339cac2be89 --- /dev/null +++ b/code/game/turfs/simulated/floor/plating/catwalk_plating.dm @@ -0,0 +1,103 @@ +/** + * ## catwalk flooring + * + * They show what's underneath their catwalk flooring (pipes and the like) + * you can screwdriver it to interact with the underneath stuff without destroying the tile... + * unless you want to! + */ +/turf/open/floor/catwalk_floor //the base type, meant to look like a maintenance panel + icon = 'icons/turf/floors/catwalk_plating.dmi' + icon_state = "maint_above" + name = "catwalk floor" + desc = "Flooring that shows its contents underneath. Engineers love it!" + baseturfs = /turf/open/floor/plating + floor_tile = /obj/item/stack/tile/catwalk_tile + layer = CATWALK_LAYER + plane = GAME_PLANE + footstep = FOOTSTEP_CATWALK + overfloor_placed = TRUE + underfloor_accessibility = UNDERFLOOR_VISIBLE + var/covered = TRUE + var/catwalk_type = "maint" + var/static/list/catwalk_underlays = list() + +/turf/open/floor/catwalk_floor/Initialize(mapload) + . = ..() + if(!catwalk_underlays[catwalk_type]) + var/mutable_appearance/plating_underlay = mutable_appearance(icon, "[catwalk_type]_below", TURF_LAYER) + catwalk_underlays[catwalk_type] = plating_underlay + underlays += catwalk_underlays[catwalk_type] + update_icon() + +/turf/open/floor/catwalk_floor/examine(mob/user) + . = ..() + + if(covered) + . += span_notice("You can unscrew it to reveal the contents beneath.") + else + . += span_notice("You can screw it to hide the contents beneath.") + . += span_notice("There's a small crack on the edge of it.") + +/turf/open/floor/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool) + . = ..() + covered = !covered + if(!covered) + underfloor_accessibility = UNDERFLOOR_INTERACTABLE + layer = TURF_LAYER + plane = FLOOR_PLANE + icon_state = "[catwalk_type]_below" + else + underfloor_accessibility = UNDERFLOOR_VISIBLE + layer = CATWALK_LAYER + plane = GAME_PLANE + icon_state = "[catwalk_type]_above" + user.balloon_alert(user, "[!covered ? "cover removed" : "cover added"]") + tool.play_tool_sound(src) + update_icon() + +/turf/open/floor/catwalk_floor/crowbar_act(mob/user, obj/item/crowbar) + if(covered) + user.balloon_alert(user, "remove cover first!") + return FALSE + . = ..() + +//Reskins! More fitting with most of our tiles, and appear as a radial on the base type +/turf/open/floor/catwalk_floor/iron + name = "iron plated catwalk floor" + icon_state = "iron_above" + floor_tile = /obj/item/stack/tile/catwalk_tile/iron + catwalk_type = "iron" + + +/turf/open/floor/catwalk_floor/iron_white + name = "white plated catwalk floor" + icon_state = "whiteiron_above" + floor_tile = /obj/item/stack/tile/catwalk_tile/iron_white + catwalk_type = "whiteiron" + +/turf/open/floor/catwalk_floor/iron_dark + name = "dark plated catwalk floor" + icon_state = "darkiron_above" + floor_tile = /obj/item/stack/tile/catwalk_tile/iron_dark + catwalk_type = "darkiron" + +/turf/open/floor/catwalk_floor/flat_white + name = "white large plated catwalk floor" + icon_state = "flatwhite_above" + floor_tile = /obj/item/stack/tile/catwalk_tile/flat_white + catwalk_type = "flatwhite" + +/turf/open/floor/catwalk_floor/titanium + name = "titanium plated catwalk floor" + icon_state = "titanium_above" + floor_tile = /obj/item/stack/tile/catwalk_tile/titanium + catwalk_type = "titanium" + +/turf/open/floor/catwalk_floor/iron_smooth //the original green type + name = "smooth plated catwalk floor" + icon_state = "smoothiron_above" + floor_tile = /obj/item/stack/tile/catwalk_tile/iron_smooth + catwalk_type = "smoothiron" + +/turf/open/floor/catwalk_floor/telecomms + initial_gas_mix = TCOMMS_ATMOS diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 537bf53e53ba..24e352f25198 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -2,7 +2,8 @@ icon = 'icons/turf/space.dmi' icon_state = "0" name = "\proper space" - intact = 0 + overfloor_placed = FALSE + underfloor_accessibility = UNDERFLOOR_INTERACTABLE temperature = TCMB thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index b54880c5725e..086d4712d2bc 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -4,7 +4,10 @@ GLOBAL_LIST_EMPTY(station_turfs) icon = 'icons/turf/floors.dmi' level = 1 - var/intact = 1 + /// If there's a tile over a basic floor that can be ripped out + var/overfloor_placed = FALSE + /// How accessible underfloor pieces such as wires, pipes, etc are on this turf. Can be HIDDEN, VISIBLE, or INTERACTABLE. + var/underfloor_accessibility = UNDERFLOOR_HIDDEN // baseturfs can be either a list or a single turf type. // In class definition like here it should always be a single type. @@ -201,6 +204,15 @@ GLOBAL_LIST_EMPTY(station_turfs) coil.place_turf(src, user) return TRUE + if(can_lay_cable() && istype(C, /obj/item/stack/ethernet_coil)) + var/obj/item/stack/ethernet_coil/coil = C + for(var/obj/structure/ethernet_cable/LC in src) + if(!LC.d1 || !LC.d2) + LC.attackby(C,user) + return + coil.place_turf(src, user) + return TRUE + else if(istype(C, /obj/item/twohanded/rcl)) handleRCL(C, user) @@ -328,7 +340,7 @@ GLOBAL_LIST_EMPTY(station_turfs) /turf/proc/levelupdate() for(var/obj/O in src) if(O.level == 1 && (O.flags_1 & INITIALIZED_1)) - O.hide(src.intact) + O.hide(underfloor_accessibility < UNDERFLOOR_VISIBLE) // override for space turfs, since they should never hide anything /turf/open/space/levelupdate() @@ -390,7 +402,7 @@ GLOBAL_LIST_EMPTY(station_turfs) //////////////////////////////////////////////////// /turf/singularity_act() - if(intact) + if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE) for(var/obj/O in contents) //this is for deleting things like wires contained in the turf if(O.level != 1) continue @@ -403,7 +415,7 @@ GLOBAL_LIST_EMPTY(station_turfs) return TRUE /turf/proc/can_lay_cable() - return can_have_cabling() & !intact + return can_have_cabling() && underfloor_accessibility >= UNDERFLOOR_INTERACTABLE /turf/proc/visibilityChanged() GLOB.cameranet.updateVisibility(src) @@ -478,7 +490,7 @@ GLOBAL_LIST_EMPTY(station_turfs) acid_type = /obj/effect/acid/alien var/has_acid_effect = FALSE for(var/obj/O in src) - if(intact && O.level == 1) //hidden under the floor + if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE && O.level == 1) //hidden under the floor continue if(istype(O, acid_type)) var/obj/effect/acid/A = O diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 014bd9421ab1..a24a4c04fd86 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1123,3 +1123,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) return if(alert(usr, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modificatoins?", "Really reset?", "No", "Yes") == "Yes") config.admin_reload() + +/client/proc/debug_ai_networks() + set category = "Misc.Server Debug" + set name = "Debug AI Networks" + set desc = "Displays a list of all AI networks to ALL admins" + if(!check_rights(R_DEBUG)) + return + _debug_ai_networks() diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 8b1368e57938..41d36ea8cdc5 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -76,6 +76,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug_all, list( /client/proc/cmd_display_init_log, /client/proc/cmd_display_overlay_log, /client/proc/reload_configuration, + /client/proc/debug_ai_networks, /datum/admins/proc/create_or_modify_area, /client/proc/debug_typeof, // Yogs -- Adds a debug verb for getting the subtypes of something /client/proc/toggle_cdn diff --git a/code/modules/antagonists/blob/blob_report.dm b/code/modules/antagonists/blob/blob_report.dm index f0d46888c2f6..d8ee7857d635 100644 --- a/code/modules/antagonists/blob/blob_report.dm +++ b/code/modules/antagonists/blob/blob_report.dm @@ -29,15 +29,11 @@ floor += 1 if(iswallturf(T)) - var/turf/closed/wall/TW = T - if(TW.intact) - wall += 2 - else - wall += 1 + wall += 1 if(istype(T, /turf/closed/wall/r_wall)) var/turf/closed/wall/r_wall/TRW = T - if(TRW.intact) + if(TRW.d_state == INTACT) r_wall += 2 else r_wall += 1 diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm index 70cad681d522..ba330090874a 100644 --- a/code/modules/antagonists/revenant/revenant_abilities.dm +++ b/code/modules/antagonists/revenant/revenant_abilities.dm @@ -244,7 +244,7 @@ if(!isplatingturf(T) && !istype(T, /turf/open/floor/engine/cult) && isfloorturf(T) && prob(15)) var/turf/open/floor/floor = T - if(floor.intact && floor.floor_tile) + if(floor.overfloor_placed && floor.floor_tile) new floor.floor_tile(floor) floor.broken = 0 floor.burnt = 0 diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 587100913ea5..9260e12a0304 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -191,7 +191,7 @@ GLOBAL_LIST_EMPTY(pipeimages) return ..() var/turf/T = get_turf(src) - if (level==1 && isturf(T) && T.intact) + if (level==1 && isturf(T) && T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) to_chat(user, span_warning("You must remove the plating first!")) return TRUE @@ -277,7 +277,7 @@ GLOBAL_LIST_EMPTY(pipeimages) pipe_color = obj_color setPipingLayer(set_layer) var/turf/T = get_turf(src) - level = T.intact ? 2 : 1 + level = (T.underfloor_accessibility < UNDERFLOOR_VISIBLE) ? 2 : 1 atmosinit() var/list/nodes = pipeline_expansion() for(var/obj/machinery/atmospherics/A in nodes) diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm index 00285a5f77d1..fae5d24afd7d 100644 --- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm +++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm @@ -106,7 +106,7 @@ normalize_cardinal_directions() findAllConnections() var/turf/T = loc // hide if turf is not intact - hide(T.intact) + hide(T.underfloor_accessibility < UNDERFLOOR_VISIBLE) /obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer() piping_layer = PIPING_LAYER_DEFAULT diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index cbd6f8a10b51..e4b411c75cb3 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -39,7 +39,7 @@ /obj/machinery/atmospherics/pipe/atmosinit() var/turf/T = loc // hide if turf is not intact - hide(T.intact) + hide(T.underfloor_accessibility < UNDERFLOOR_VISIBLE) ..() /obj/machinery/atmospherics/pipe/hide(i) diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index 2ef90774b114..a75b4aa34f62 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -18,6 +18,10 @@ #define HOLODECK_CD 25 #define HOLODECK_DMG_CD 500 +/// typecache for turfs that should be considered ok during floorchecks. +/// A linked turf being anything not in this typecache will cause the holodeck to perform an emergency shutdown. +GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf/open/floor/holofloor, /turf/closed))) + /obj/machinery/computer/holodeck name = "holodeck control console" desc = "A computer used to control a nearby holodeck." @@ -223,8 +227,9 @@ /obj/machinery/computer/holodeck/proc/floorcheck() for(var/turf/T in linked) - if(!T.intact || isspaceturf(T)) - return FALSE + if (is_type_in_typecache(T, GLOB.typecache_holodeck_linked_floorcheck_ok)) + continue + return FALSE return TRUE /obj/machinery/computer/holodeck/proc/nerf(active) diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm index 67c87a60c5d3..d39e5c5a8b5c 100644 --- a/code/modules/holodeck/turfs.dm +++ b/code/modules/holodeck/turfs.dm @@ -122,7 +122,7 @@ /turf/open/floor/holofloor/carpet/update_icon() if(!..()) return 0 - if(intact) + if(overfloor_placed) queue_smooth(src) /turf/open/floor/holofloor/wood diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index fe094589de30..90aa7c304604 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -28,13 +28,13 @@ var/mob/living/silicon/ai/AI = H - AI.relocate(TRUE) + AI.relocate(TRUE, TRUE) + + var/total_available_cpu = 1 - AI.ai_network.resources.total_cpu_assigned() + var/total_available_ram = AI.ai_network.resources.total_ram() - AI.ai_network.resources.total_ram_assigned() - var/total_available_cpu = 1 - GLOB.ai_os.total_cpu_assigned() - var/total_available_ram = GLOB.ai_os.total_ram - GLOB.ai_os.total_ram_assigned() - - GLOB.ai_os.set_cpu(AI, total_available_cpu) - GLOB.ai_os.add_ram(AI, total_available_ram) + AI.ai_network.resources.set_cpu(AI, total_available_cpu) + AI.ai_network.resources.add_ram(AI, total_available_ram) AI.apply_pref_name("ai", M.client) //If this runtimes oh well jobcode is fucked. AI.set_core_display_icon(null, M.client) diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm index 3a6caa8a806d..36e26a43d5f3 100644 --- a/code/modules/mapping/map_template.dm +++ b/code/modules/mapping/map_template.dm @@ -28,6 +28,7 @@ /datum/parsed_map/proc/initTemplateBounds() var/list/obj/machinery/atmospherics/atmos_machines = list() var/list/obj/structure/cable/cables = list() + var/list/obj/structure/ethernet_cable/ethernet_cables = list() var/list/atom/atoms = list() var/list/area/areas = list() @@ -44,6 +45,9 @@ if(istype(A, /obj/structure/cable)) cables += A continue + if(istype(A, /obj/structure/ethernet_cable)) + ethernet_cables += A + continue if(istype(A, /obj/machinery/atmospherics)) atmos_machines += A for(var/L in border) @@ -53,6 +57,7 @@ SSmapping.reg_in_areas_in_z(areas) SSatoms.InitializeAtoms(atoms) SSmachines.setup_template_powernets(cables) + SSmachines.setup_template_ainets(ethernet_cables) SSair.setup_template_machinery(atmos_machines) /datum/map_template/proc/load_new_z(secret = FALSE) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 261f74ecbc83..41eed9e98be6 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -112,7 +112,6 @@ //Reduces/Increases download speed by this modifier var/downloadSpeedModifier = 1 - var/login_warned_temp = FALSE //Do we have access to camera tracking? var/canCameraMemoryTrack = FALSE @@ -123,8 +122,8 @@ //Did we get the death prompt? var/is_dying = FALSE - ///Multiplier for amount of points gained when passively using CPU for science - var/research_point_booster = 1 + + var/datum/ai_network/ai_network @@ -134,7 +133,7 @@ return INITIALIZE_HINT_QDEL //Delete AI. if(!istype(loc, /obj/machinery/ai/data_core) && !shunted) - relocate(TRUE) + relocate(TRUE, TRUE) if(L && istype(L, /datum/ai_laws)) laws = L @@ -234,7 +233,7 @@ qdel(eyeobj) // No AI, no Eye malfhack = null apc_override = null - GLOB.ai_os.remove_ai(src) + ai_network.remove_ai(src) . = ..() @@ -557,7 +556,7 @@ if(href_list["instant_download"]) if(!href_list["console"]) return - var/obj/machinery/computer/ai_control_console/C = locate(href_list["console"]) + var/datum/computer_file/program/ai_network_interface/C = locate(href_list["console"]) if(!C) return if(C.downloading != src) @@ -576,6 +575,10 @@ to_chat(src, "[target] is not on or near any active cameras on the station.") +/mob/living/silicon/ai/proc/switch_ainet(datum/ai_network/old_net, datum/ai_network/new_net) + for(var/datum/ai_project/project in dashboard.completed_projects) + project.switch_network(old_net, new_net) + /mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C) if(QDELETED(C)) diff --git a/code/modules/mob/living/silicon/ai/ai_network/ai_network.dm b/code/modules/mob/living/silicon/ai/ai_network/ai_network.dm new file mode 100644 index 000000000000..8e815d23666f --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_network/ai_network.dm @@ -0,0 +1,346 @@ +//////////////////////////////////////////// +// AI NETWORK DATUM +// each contiguous network of ethernet cables & AI machinery +///////////////////////////////////// +/datum/ai_network + var/number // unique id + var/list/cables = list() // all cables & junctions + var/list/nodes = list() // all connected machines + + var/list/ai_list = list() //List of all AIs in this network + + var/list/remote_networks = list() + + var/previous_ram = 0 + + var/datum/ai_shared_resources/resources + //Cash from crypto, can be withdrawn at network console + var/bitcoin_payout = 0 + + var/temp_limit = AI_TEMP_LIMIT + + var/local_cpu_usage = list() //How we use CPU locally + + var/label + + + + +/datum/ai_network/New() + SSmachines.ainets += src + label = num2hex(rand(1,65535), -1) + resources = new(starting_network = src) + +/datum/ai_network/Destroy() + //Go away references, you suck! + for(var/obj/structure/ethernet_cable/C in cables) + cables -= C + C.network = null + for(var/obj/machinery/ai/M in nodes) + nodes -= M + M.network = null + + resources.networks -= src + + if(!length(resources.networks)) + qdel(resources) + + resources = null + + SSmachines.ainets -= src + return ..() + +/datum/ai_network/process() + var/total_cpu = resources.total_cpu() + var/resources_assigned = resources.cpu_assigned[src] ? resources.cpu_assigned[src] : 0 + + if(local_cpu_usage[AI_CRYPTO]) + var/points = max(round(AI_RESEARCH_PER_CPU * (local_cpu_usage[AI_CRYPTO] * total_cpu * resources_assigned)), 0) + var/bitcoin_mined = points * (1-0.05*sqrt(points)) + bitcoin_mined = clamp(bitcoin_mined, 0, MAX_AI_BITCOIN_MINED_PER_TICK) + bitcoin_payout += bitcoin_mined * AI_BITCOIN_PRICE + + var/locally_used = 0 + for(var/A in local_cpu_usage) + locally_used += local_cpu_usage[A] + + var/research_points = max(round(AI_RESEARCH_PER_CPU * ((1 - locally_used) * total_cpu * resources_assigned)), 0) + SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_AI = research_points)) + + + +/datum/ai_network/proc/is_empty() + return !cables.len && !nodes.len + +//remove a cable from the current network +//if the network is then empty, delete it +//Warning : this proc DON'T check if the cable exists +/datum/ai_network/proc/remove_cable(obj/structure/ethernet_cable/C) + cables -= C + C.network = null + if(is_empty())//the network is now empty... + qdel(src)///... delete it + +//add a cable to the current network +//Warning : this proc DON'T check if the cable exists +/datum/ai_network/proc/add_cable(obj/structure/ethernet_cable/C) + if(C.network)// if C already has a network... + if(C.network == src) + return + else + C.network.remove_cable(C) //..remove it + C.network = src + cables +=C + +//remove a power machine from the current network +//if the network is then empty, delete it +//Warning : this proc DON'T check if the machine exists +/datum/ai_network/proc/remove_machine(obj/machinery/ai/M) + nodes -=M + M.network = null + if(is_empty())//the network is now empty... + qdel(src)///... delete it + +//add a power machine to the current network +//Warning : this proc DOESN'T check if the machine exists +/datum/ai_network/proc/add_machine(obj/machinery/ai/M) + if(M.network)// if M already has a network... + if(M.network == src) + return + else + M.disconnect_from_network()//..remove it + M.network = src + nodes[M] = M + +/datum/ai_network/proc/find_data_core() + for(var/obj/machinery/ai/data_core/core in get_all_nodes()) + if(core.can_transfer_ai()) + return core + +/datum/ai_network/proc/get_all_nodes(checked_nets = list()) + . = nodes.Copy() + for(var/datum/ai_network/net in resources.networks) + if(net == src) + continue + . += net.nodes + +/datum/ai_network/proc/get_local_nodes_oftype(type_to_check) + . = list() + for(var/A in nodes) + if(istype(A, type_to_check)) + . += A + + +/datum/ai_network/proc/get_all_ais(checked_nets = list()) + . = ai_list.Copy() + for(var/datum/ai_network/net in resources.networks) + if(net == src) + continue + . += net.ai_list + +/datum/ai_network/proc/remove_ai(mob/living/silicon/ai/AI) + resources.cpu_assigned[AI] = 0 + resources.ram_assigned[AI] = 0 + ai_list -= AI + + +/datum/ai_network/proc/update_resources() + resources.update_resources() + + +/datum/ai_network/proc/total_cpu() + . = 0 + for(var/obj/machinery/ai/server_cabinet/C in nodes) + . += C.total_cpu + +/datum/ai_network/proc/total_ram() + . = 0 + for(var/obj/machinery/ai/server_cabinet/C in nodes) + . += C.total_ram + + +/datum/ai_network/proc/get_temp_limit() + return temp_limit + +/datum/ai_network/proc/total_cpu_assigned() + return resources.total_cpu_assigned() + +/datum/ai_network/proc/total_ram_assigned() + return resources.total_ram_assigned() + +/* +/datum/ai_network/proc/rebuild_remote(externally_linked = FALSE, touched_networks = list()) + if(!resources) + return + if(src in touched_networks) + return + touched_networks += src + var/list/networks_to_rebuild = list() + for(var/obj/machinery/ai/networking/N in nodes) + if(N.partner && N.partner.network && N.partner.network.resources) + if(N.partner.network in touched_networks) + message_admins("[REF(src)] found touched_network!") + continue + message_admins("[REF(src)] found no mismatched resources!") + if(N.partner.network.resources != resources) + if(length(N.partner.network.resources.networks) > length(resources.networks)) //We merge into the biggest network + N.partner.network.resources.add_resource(resources) + else + resources.add_resource(N.partner.network.resources) + message_admins("[REF(src)] actually rebuilt!") + externally_linked = TRUE + + networks_to_rebuild += N.partner.network + + + if(!externally_linked) + resources.split_resources(src) + + for(var/datum/ai_network/AN in networks_to_rebuild) + message_admins("Telling network [REF(AN)] to rebuild!") + AN.rebuild_remote(TRUE, touched_networks) + +*/ + +/datum/ai_network/proc/rebuild_remote(externally_linked = FALSE, touched_networks = list(), datum/ai_network/originator) + if(src in touched_networks) + return + + if(!originator) + originator = src + + var/list/found_networks = list() + for(var/obj/machinery/ai/networking/N in nodes) + if(N.partner && N.partner.network && N.partner.network.resources) + if(N.partner.network == src) + continue + externally_linked = TRUE + found_networks += N.partner.network + + if(!externally_linked) + if(resources && length(resources.networks) > 1) //We only split if we are actually connected to an external resource network + resources.split_resources(src) + + found_networks -= touched_networks + + uniqueList_inplace(found_networks) + + for(var/datum/ai_network/AN in found_networks) + + + if(originator.resources != AN.resources) + if(length(originator.resources.networks) > length(AN.resources.networks)) + originator.resources.add_resource(AN.resources) + else + AN.resources.add_resource(originator.resources) + AN.rebuild_remote(TRUE, found_networks + src, originator) + + + +/proc/merge_ainets(datum/ai_network/net1, datum/ai_network/net2) + if(!net1 || !net2) //if one of the network doesn't exist, return + return + + if(net1 == net2) //don't merge same networks + return + + //We assume net1 is larger. If net2 is in fact larger we are just going to make them switch places to reduce on code. + if(net1.cables.len < net2.cables.len) //net2 is larger than net1. Let's switch them around + var/temp = net1 + net1 = net2 + net2 = temp + + + //merge net2 into net1 + for(var/obj/structure/ethernet_cable/Cable in net2.cables) //merge cables + net1.add_cable(Cable) + + for(var/obj/machinery/ai/Node in net2.nodes) //merge power machines + if(!Node.connect_to_network()) + Node.disconnect_from_network() //if somehow we can't connect the machine to the new network, disconnect it from the old nonetheless + + + net1.ai_list += net2.ai_list //AIs can only be in 1 network at a time + /* + net1.rebuild_remote() + net2.rebuild_remote() */ + + net1.update_resources() + + + return net1 + + +//remove the old network and replace it with a new one throughout the network. +/proc/propagate_ai_network(obj/O, datum/ai_network/AN) + var/list/worklist = list() + var/list/found_machines = list() + var/index = 1 + var/obj/P = null + + worklist+=O //start propagating from the passed object + + while(index<=worklist.len) //until we've exhausted all power objects + P = worklist[index] //get the next power object found + index++ + + if( istype(P, /obj/structure/ethernet_cable)) + var/obj/structure/ethernet_cable/C = P + if(C.network != AN) //add it to the network, if it isn't already there + AN.add_cable(C) + worklist |= C.get_connections() //get adjacents power objects, with or without a network + else if(P.anchored && istype(P, /obj/machinery/ai)) + var/obj/machinery/ai/M = P + found_machines |= M //we wait until the network is fully propagates to connect the machines + else + continue + + //now that the network is set, connect found machines to it + for(var/obj/machinery/ai/PM in found_machines) + if(!PM.connect_to_network()) //couldn't find a node on its turf... + PM.disconnect_from_network() //... so disconnect if already on a network + + //AN.rebuild_remote() + + +/proc/ai_list(turf/T, source, d, unmarked = FALSE, cable_only = FALSE) + . = list() + + for(var/AM in T) + if(AM == source) + continue //we don't want to return source + + if(!cable_only && istype(AM, /obj/machinery/ai)) + var/obj/machinery/ai/P = AM + if(P.network == 0) + continue + + if(!unmarked || !P.network) //if unmarked we only return things with no network + if(d == 0) + . += P + + else if(istype(AM, /obj/structure/ethernet_cable)) + var/obj/structure/ethernet_cable/C = AM + + if(!unmarked || !C.network) + if(C.d1 == d || C.d2 == d) + . += C + return . + +/proc/_debug_ai_networks() + var/i = 1 + var/list/resource_list = list() + for(var/datum/ai_network/AN in SSmachines.ainets) + var/list/interconnections = list() + for(var/obj/machinery/ai/networking/N in AN.nodes) + if(N.partner && N.partner.network) + interconnections += "#[i] Networking[ADMIN_JMP(N)] connected to [ADMIN_JMP(N.partner)]/[REF(N.partner.network)] | Same resources: [N.partner.network.resources == AN.resources ? "YES" : "NO"]" + i++ + message_admins("Network: [REF(AN)] | Resources: [REF(AN.resources)]") + for(var/A in interconnections) + message_admins(A) + resource_list |= AN.resources + message_admins("----------------------------") + for(var/datum/ai_shared_resources/ASR in resource_list) + message_admins("Resource count [REF(ASR)], CPU: [ASR.total_cpu()] | RAM: [ASR.total_ram()]") + diff --git a/code/modules/mob/living/silicon/ai/ai_network/ethernet_cable.dm b/code/modules/mob/living/silicon/ai/ai_network/ethernet_cable.dm new file mode 100644 index 000000000000..7816c4801e21 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_network/ethernet_cable.dm @@ -0,0 +1,651 @@ +/////////////////////////////// +//CABLE STRUCTURE +/////////////////////////////// + + +//////////////////////////////// +// Definitions +//////////////////////////////// + +/* Cable directions (d1 and d2) + + + 9 1 5 + \ | / + 8 - 0 - 4 + / | \ + 10 2 6 + +If d1 = 0 and d2 = 0, there's no cable +If d1 = 0 and d2 = dir, it's a O-X cable, getting from the center of the tile to dir (knot cable) +If d1 = dir1 and d2 = dir2, it's a full X-X cable, getting from dir1 to dir2 +By design, d1 is the smallest direction and d2 is the highest +*/ + +/obj/structure/ethernet_cable + name = "ethernet cable" + desc = "A rigid and shielded cat 16a cable used for transferring vast amounts of data over long distances. Primarily used for large scale computing networks or advanced neural networks." + icon = 'icons/obj/power_cond/power_local.dmi' + icon_state = "0-1" + level = 1 //is underfloor + layer = ETHERNET_LAYER //Above hidden pipes, GAS_PIPE_HIDDEN_LAYER + anchored = TRUE + obj_flags = CAN_BE_HIT | ON_BLUEPRINTS + var/d1 = 0 // cable direction 1 (see above) + var/d2 = 1 // cable direction 2 (see above) + var/datum/ai_network/network + //Cables no longer keep a copy of the cable to be dropped in nullspace + + FASTDMM_PROP(\ + pipe_type = PIPE_TYPE_CABLE,\ + pipe_interference_group = list("cable"),\ + pipe_group = "cable-ethernet"\ + ) + + +// the ethernet cable object +/obj/structure/ethernet_cable/Initialize(mapload, param_color) + . = ..() + + // ensure d1 & d2 reflect the icon_state for entering and exiting cable + var/dash = findtext(icon_state, "-") + d1 = text2num( copytext( icon_state, 1, dash ) ) + d2 = text2num( copytext( icon_state, dash+1 ) ) + + var/turf/T = get_turf(src) // hide if turf is not intact + if(level==1) + hide(T.underfloor_accessibility < UNDERFLOOR_VISIBLE) + GLOB.ethernet_cable_list += src //add it to the global cable list + + update_icon() + +/obj/structure/ethernet_cable/Destroy() // called when a cable is deleted + if(network) + cut_cable_from_ainet() // update the ai networks + GLOB.ethernet_cable_list -= src //remove it from global cable list + return ..() // then go ahead and delete the cable + +/obj/structure/ethernet_cable/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + var/turf/T = loc + var/cableNum = 1 + if (d1*d2 > 0) //this be true if the cable has two directions, aka it contains two cables. If there is only one cable, one out of d1 and d2 will be zero + cableNum = 2 + var/newCables = new /obj/item/stack/ethernet_coil(T, cableNum) + TransferComponents(newCables) //this copies the fingerprints over to the new object + qdel(src) + +/////////////////////////////////// +// General procedures +/////////////////////////////////// + +//If underfloor, hide the cable +/obj/structure/ethernet_cable/hide(i) + + if(level == 1 && isturf(loc)) + invisibility = i ? INVISIBILITY_MAXIMUM : 0 + update_icon() + +/obj/structure/ethernet_cable/update_icon() + icon_state = "[d1]-[d2]" + +/obj/structure/ethernet_cable/proc/handlecable(obj/item/W, mob/user, params) + var/turf/T = get_turf(src) + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) + return + if(W.tool_behaviour == TOOL_WIRECUTTER) + user.visible_message("[user] cuts the ethernet cable.", span_notice("You cut the ethernet cable.")) + investigate_log("was cut by [key_name(usr)] in [AREACOORD(src)]", INVESTIGATE_WIRES) + add_fingerprint(user) + deconstruct() + return + + else if(istype(W, /obj/item/stack/ethernet_coil)) + var/obj/item/stack/ethernet_coil/coil = W + if (coil.get_amount() < 1) + to_chat(user, span_warning("Not enough cable!")) + return + coil.cable_join(src, user) + /* + else if(W.tool_behaviour == TOOL_MULTITOOL) //FIX NETWORK STATS + + if(ai network && (ai network.avail > 0)) // is it powered? + to_chat(user, span_danger("Total power: [DisplayPower(ai network.avail)]\nLoad: [DisplayPower(ai network.load)]\nExcess power: [DisplayPower(surplus())]")) + else + to_chat(user, span_danger("The cable is not powered.")) + shock(user, 5, 0.2) + */ + else if(istype(W, /obj/item/modular_computer)) + var/obj/item/modular_computer/MC = W + + if(MC.all_components[MC_AI_NETWORK]) + var/obj/item/computer_hardware/ai_interface/ai_interface = MC.all_components[MC_AI_NETWORK] + if(ai_interface) + if(ai_interface.connected_cable != src) + ai_interface.connect_cable(src) + to_chat(user, span_notice("You connect to the ethernet cable.")) + else + to_chat(user, span_warning("[MC] has no AI interface!")) + + + add_fingerprint(user) + +// Items usable on a cable : +// - Wirecutters : cut it duh ! +// - Cable coil : merge cables +// - Multitool : get the network stats +// +/obj/structure/ethernet_cable/attackby(obj/item/W, mob/user, params) + handlecable(W, user, params) + + +/obj/structure/ethernet_cable/singularity_pull(S, current_size) + ..() + if(current_size >= STAGE_FIVE) + deconstruct() + +///////////////////////////////////////////////// +// Cable laying helpers +//////////////////////////////////////////////// + +//handles merging diagonally matching cables +//for info : direction^3 is flipping horizontally, direction^12 is flipping vertically +/obj/structure/ethernet_cable/proc/mergeDiagonalsNetworks(direction) + + //search for and merge diagonally matching cables from the first direction component (north/south) + var/turf/T = get_step(src, direction&3)//go north/south + + for(var/obj/structure/ethernet_cable/C in T) + + if(!C) + continue + + if(src == C) + continue + + if(C.d1 == (direction^3) || C.d2 == (direction^3)) //we've got a diagonally matching cable + if(!C.network) //if the matching cable somehow got no ai network, make him one (should not happen for cables) + var/datum/ai_network/newAN = new() + newAN.add_cable(C) + + if(network) //if we already have a ai network, then merge the two ai networks + merge_ainets(network,C.network) + //network.rebuild_remote() + else + C.network.add_cable(src) //else, we simply connect to the matching cable ai network + C.network.rebuild_remote() + + //the same from the second direction component (east/west) + T = get_step(src, direction&12)//go east/west + + for(var/obj/structure/ethernet_cable/C in T) + + if(!C) + continue + + if(src == C) + continue + if(C.d1 == (direction^12) || C.d2 == (direction^12)) //we've got a diagonally matching cable + if(!C.network) //if the matching cable somehow got no ai network, make him one (should not happen for cables) + var/datum/ai_network/newAN = new() + newAN.add_cable(C) + + if(network) //if we already have a ai network, then merge the two ai networks + merge_ainets(network,C.network) + //network.rebuild_remote() + else + C.network.add_cable(src) //else, we simply connect to the matching cable ai network + C.network.rebuild_remote() + + + +// merge with the ai networks of power objects in the given direction +/obj/structure/ethernet_cable/proc/mergeConnectedNetworks(direction) + + var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf + + if(!(d1 == direction || d2 == direction)) //if the cable is not pointed in this direction, do nothing + return + + var/turf/TB = get_step(src, direction) + + for(var/obj/structure/ethernet_cable/C in TB) + + if(!C) + continue + + if(src == C) + continue + + if(C.d1 == fdir || C.d2 == fdir) //we've got a matching cable in the neighbor turf + if(!C.network) //if the matching cable somehow got no ai network, make him one (should not happen for cables) + var/datum/ai_network/newAN = new(C.loc.z) + newAN.add_cable(C) + + if(network) //if we already have a ai network, then merge the two ai networks + merge_ainets(network,C.network) + //network.rebuild_remote() + else + C.network.add_cable(src) //else, we simply connect to the matching cable ai network + C.network.rebuild_remote() + +// merge with the ai networks of power objects in the source turf +/obj/structure/ethernet_cable/proc/mergeConnectedNetworksOnTurf() + var/list/to_connect = list() + + if(!network) //if we somehow have no ai network, make one (should not happen for cables) + var/datum/ai_network/newAN = new(loc.z) + newAN.add_cable(src) + + //first let's add turf cables to our ai network + //then we'll connect machines on turf with a node cable is present + for(var/AM in loc) + if(istype(AM, /obj/structure/ethernet_cable)) + var/obj/structure/ethernet_cable/C = AM + if(C.d1 == d1 || C.d2 == d1 || C.d1 == d2 || C.d2 == d2) //only connected if they have a common direction + if(C.network == network) + continue + if(C.network) + merge_ainets(network, C.network) + //network.rebuild_remote() + else + network.add_cable(C) //the cable was ai networkless, let's just add it to our ai network + network.rebuild_remote() + + else if(istype(AM, /obj/machinery/ai)) //other power machines + var/obj/machinery/ai/M = AM + + if(M.network == network) + continue + + to_connect += M //we'll connect the machines after all cables are merged + + + //now that cables are done, let's connect found machines + for(var/obj/machinery/ai/PM in to_connect) + if(!PM.connect_to_network()) + PM.disconnect_from_network() //if we somehow can't connect the machine to the new ai network, remove it from the old nonetheless + + +////////////////////////////////////////////// +// ai networks handling helpers +////////////////////////////////////////////// + +//if ai_networkless_only = 1, will only get connections without ai network +/obj/structure/ethernet_cable/proc/get_connections(ai_networkless_only = 0) + . = list() // this will be a list of all connected power objects + var/turf/T + + //get matching cables from the first direction + if(d1) //if not a node cable + T = get_step(src, d1) + if(T) + . += ai_list(T, src, turn(d1, 180), ai_networkless_only) //get adjacents matching cables + + if(d1&(d1-1)) //diagonal direction, must check the 4 possibles adjacents tiles + T = get_step(src,d1&3) // go north/south + if(T) + . += ai_list(T, src, d1 ^ 3, ai_networkless_only) //get diagonally matching cables + T = get_step(src,d1&12) // go east/west + if(T) + . += ai_list(T, src, d1 ^ 12, ai_networkless_only) //get diagonally matching cables + + . += ai_list(loc, src, d1, ai_networkless_only) //get on turf matching cables + + //do the same on the second direction (which can't be 0) + T = get_step(src, d2) + if(T) + . += ai_list(T, src, turn(d2, 180), ai_networkless_only) //get adjacents matching cables + + if(d2&(d2-1)) //diagonal direction, must check the 4 possibles adjacents tiles + T = get_step(src,d2&3) // go north/south + if(T) + . += ai_list(T, src, d2 ^ 3, ai_networkless_only) //get diagonally matching cables + T = get_step(src,d2&12) // go east/west + if(T) + . += ai_list(T, src, d2 ^ 12, ai_networkless_only) //get diagonally matching cables + . += ai_list(loc, src, d2, ai_networkless_only) //get on turf matching cables + + return . + +//should be called after placing a cable which extends another cable, creating a "smooth" cable that no longer terminates in the centre of a turf. +//needed as this can, unlike other placements, disconnect cables +/obj/structure/ethernet_cable/proc/denode() + var/turf/T1 = loc + if(!T1) + return + + var/list/powerlist = ai_list(T1,src,0,0) //find the other cables that ended in the centre of the turf, with or without a ai network + if(powerlist.len>0) + var/datum/ai_network/AN = new() + propagate_ai_network(powerlist[1],AN) //propagates the new ai network beginning at the source cable + + if(AN.is_empty()) //can happen with machines made nodeless when smoothing cables + qdel(AN) + +/obj/structure/ethernet_cable/proc/auto_propogate_cut_cable(obj/O, ) + if(O && !QDELETED(O)) + var/datum/ai_network/newAN = new()// creates a new ai network... + + propagate_ai_network(O, newAN)//... and propagates it to the other side of the cable + + + +// cut the cable's ai network at this cable and updates the powergrid +/obj/structure/ethernet_cable/proc/cut_cable_from_ainet(remove=TRUE) + var/turf/T1 = loc + var/list/P_list + if(!T1) + return + if(d1) + T1 = get_step(T1, d1) + P_list = ai_list(T1, src, turn(d1,180),0,cable_only = 1) // what adjacently joins on to cut cable... + + P_list += ai_list(loc, src, d1, 0, cable_only = 1)//... and on turf + + if(P_list.len == 0)//if nothing in both list, then the cable was a lone cable, just delete it and its ai network + network.remove_cable(src) + + for(var/obj/machinery/ai/P in T1)//check if it was powering a machine + if(!P.connect_to_network()) //can't find a node cable on a the turf to connect to + P.disconnect_from_network() //remove from current network (and delete ai network) + return + + var/obj/O = P_list[1] + // remove the cut cable from its turf and ai network, so that it doesn't get count in propagate_network worklist + if(remove) + moveToNullspace() + + network.remove_cable(src) //remove the cut cable from its ai network + + + addtimer(CALLBACK(O, .proc/auto_propogate_cut_cable, O), 0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables + + // Disconnect machines connected to nodes + if(d1 == 0) // if we cut a node (O-X) cable + for(var/obj/machinery/ai/P in T1) + if(!P.connect_to_network()) //can't find a node cable on a the turf to connect to + P.disconnect_from_network() //remove from current network + + +/////////////////////////////////////////////// +// The cable coil object, used for laying cable +/////////////////////////////////////////////// + +//////////////////////////////// +// Definitions +//////////////////////////////// + +/obj/item/stack/ethernet_coil + name = "ethernet cable coil" + desc = "A coil of shielded ethernet cable." + custom_price = 25 + gender = NEUTER //That's a cable coil sounds better than that's some cable coils + icon = 'icons/obj/power.dmi' + icon_state = "wire" + item_state = "coil" + lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + max_amount = MAXCOIL + amount = MAXCOIL + merge_type = /obj/item/stack/ethernet_coil // This is here to let its children merge between themselves + + throwforce = 0 + w_class = WEIGHT_CLASS_SMALL + throw_speed = 3 + throw_range = 5 + materials = list(/datum/material/iron=10, /datum/material/glass=5, /datum/material/gold=1) + slot_flags = ITEM_SLOT_BELT + attack_verb = list("whipped", "lashed", "disciplined", "flogged") + singular_name = "ethernet cable piece" + full_w_class = WEIGHT_CLASS_SMALL + grind_results = list(/datum/reagent/copper = 2) //2 copper per cable in the coil + usesound = 'sound/items/deconstruct.ogg' + +/obj/item/stack/ethernet_coil/cyborg + is_cyborg = TRUE + materials = list() + cost = 1 + +/obj/item/stack/ethernet_coil/suicide_act(mob/user) + if(locate(/obj/structure/chair/stool) in get_turf(user)) + user.visible_message(span_suicide("[user] is making a noose with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) + else + user.visible_message(span_suicide("[user] is trying to upload [user.p_them()]selves to the afterlife with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) + return(OXYLOSS) + +/obj/item/stack/ethernet_coil/Initialize(mapload, new_amount = null, param_color = null) + . = ..() + + pixel_x = rand(-2,2) + pixel_y = rand(-2,2) + update_icon() + +/////////////////////////////////// +// General procedures +/////////////////////////////////// + + +//you can use wires to heal robotics +/obj/item/stack/ethernet_coil/attack(mob/living/carbon/human/H, mob/user) + if(!istype(H)) + return ..() + + var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) + if(affecting.burn_dam <= 0) + to_chat(user, span_warning("[affecting] is already in good condition!")) + return FALSE + if(affecting && affecting.status == BODYPART_ROBOTIC) + user.visible_message(span_notice("[user] starts to fix some of the wires in [H]'s [affecting.name]."), span_notice("You start fixing some of the wires in [H == user ? "your" : "[H]'s"] [affecting.name].")) + heal_robo_limb(src, H, user, 0, 15) + user.visible_message(span_notice("[user] fixes the wires in [H]'s [affecting.name]."), span_notice("You fix the wires in [H == user ? "your" : "[H]'s"] [affecting.name].")) + return + else + return ..() + +/obj/item/stack/ethernet_coil/proc/heal_robo_limb(obj/item/I, mob/living/carbon/human/H, mob/user, brute_heal, burn_heal) + if(I.use_tool(H, user, 2 SECONDS, amount=1)) + if(item_heal_robotic(H, user, brute_heal, burn_heal)) + return heal_robo_limb(I, H, user, brute_heal, burn_heal) + return TRUE + +/obj/item/stack/ethernet_coil/update_icon() + icon_state = "[initial(icon_state)][amount < 3 ? amount : ""]" + name = "ethernet cable [amount < 3 ? "piece" : "coil"]" + +/obj/item/stack/ethernet_coil/attack_hand(mob/user) + . = ..() + if(.) + return + var/obj/item/stack/ethernet_coil/new_cable = ..() + if(istype(new_cable)) + new_cable.update_icon() + +//add cables to the stack +/obj/item/stack/ethernet_coil/proc/give(extra) + if(amount + extra > max_amount) + amount = max_amount + else + amount += extra + update_icon() + + + +/////////////////////////////////////////////// +// Cable laying procedures +////////////////////////////////////////////// + +/obj/item/stack/ethernet_coil/proc/get_new_cable(location) + var/path = /obj/structure/ethernet_cable + return new path(location) + +// called when cable_coil is clicked on a turf +/obj/item/stack/ethernet_coil/proc/place_turf(turf/T, mob/user, dirnew) + if(!isturf(user.loc)) + return + + if(!isturf(T) || T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling()) + to_chat(user, span_warning("You can only lay cables on top of exterior catwalks and plating!")) + return + + if(get_amount() < 1) // Out of cable + to_chat(user, span_warning("There is no cable left!")) + return + + if(get_dist(T,user) > 1) // Too far + to_chat(user, span_warning("You can't lay cable at a place that far away!")) + return + + var/dirn + if(!dirnew) //If we weren't given a direction, come up with one! (Called as null from catwalk.dm and floor.dm) + if(user.loc == T) + dirn = user.dir //If laying on the tile we're on, lay in the direction we're facing + else + dirn = get_dir(T, user) + else + dirn = dirnew + + + for(var/obj/structure/ethernet_cable/LC in T) + if(LC.d2 == dirn && LC.d1 == 0) + to_chat(user, span_warning("There's already a cable at that position!")) + return + + var/obj/structure/ethernet_cable/C = get_new_cable(T) + + //set up the new cable + C.d1 = 0 //it's a O-X node cable + C.d2 = dirn + C.add_fingerprint(user) + C.update_icon() + + //create a new ai network with the cable, if needed it will be merged later + var/datum/ai_network/AN = new() + AN.add_cable(C) + + C.mergeConnectedNetworks(C.d2) //merge the ai network with adjacents ai networks + C.mergeConnectedNetworksOnTurf() //merge the ai network with on turf ai networks + + if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions + C.mergeDiagonalsNetworks(C.d2) + + use(1) + + return C + +// called when cable_coil is click on an installed obj/cable +// or click on a turf that already contains a "node" cable +/obj/item/stack/ethernet_coil/proc/cable_join(obj/structure/ethernet_cable/C, mob/user, var/showerror = TRUE, forceddir) + var/turf/U = user.loc + if(!isturf(U)) + return + + var/turf/T = C.loc + + if(!isturf(T) || T.underfloor_accessibility ) // sanity checks, also stop use interacting with T-scanner revealed cable + return + + if(get_dist(C, user) > 1) // make sure it's close enough + to_chat(user, span_warning("You can't lay cable at a place that far away!")) + return + + + if(U == T && !forceddir) //if clicked on the turf we're standing on and a direction wasn't supplied, try to put a cable in the direction we're facing + place_turf(T,user) + return + + var/dirn = get_dir(C, user) + if(forceddir) + dirn = forceddir + + // one end of the clicked cable is pointing towards us and no direction was supplied + if((C.d1 == dirn || C.d2 == dirn) && !forceddir) + if(!U.can_have_cabling()) //checking if it's a plating or catwalk + if (showerror) + to_chat(user, span_warning("You can only lay cables on catwalks and plating!")) + return + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //can't place a cable if it's a plating with a tile on it + to_chat(user, span_warning("You can't lay cable there unless the floor tiles are removed!")) + return + else + // cable is pointing at us, we're standing on an open tile + // so create a stub pointing at the clicked cable on our tile + + var/fdirn = turn(dirn, 180) // the opposite direction + + for(var/obj/structure/ethernet_cable/LC in U) // check to make sure there's not a cable there already + if(LC.d1 == fdirn || LC.d2 == fdirn) + if (showerror) + to_chat(user, span_warning("There's already a cable at that position!")) + return + + var/obj/structure/ethernet_cable/NC = get_new_cable (U) + + NC.d1 = 0 + NC.d2 = fdirn + NC.add_fingerprint(user) + NC.update_icon() + + //create a new ai network with the cable, if needed it will be merged later + var/datum/ai_network/newAN = new() + newAN.add_cable(NC) + + NC.mergeConnectedNetworks(NC.d2) //merge the ai network with adjacents ai networks + NC.mergeConnectedNetworksOnTurf() //merge the ai network with on turf ai networks + + if(NC.d2 & (NC.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions + NC.mergeDiagonalsNetworks(NC.d2) + + + use(1) + + return + + // exisiting cable doesn't point at our position or we have a supplied direction, so see if it's a stub + else if(C.d1 == 0) + // if so, make it a full cable pointing from it's old direction to our dirn + var/nd1 = C.d2 // these will be the new directions + var/nd2 = dirn + + + if(nd1 > nd2) // swap directions to match icons/states + nd1 = dirn + nd2 = C.d2 + + + for(var/obj/structure/ethernet_cable/LC in T) // check to make sure there's no matching cable + if(LC == C) // skip the cable we're interacting with + continue + if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction + if (showerror) + to_chat(user, span_warning("There's already a cable at that position!")) + + return + + + C.update_icon() + + C.d1 = nd1 + C.d2 = nd2 + + //updates the stored cable coil + + C.add_fingerprint(user) + C.update_icon() + + + C.mergeConnectedNetworks(C.d1) //merge the ai networks... + C.mergeConnectedNetworks(C.d2) //...in the two new cable directions + C.mergeConnectedNetworksOnTurf() + + if(C.d1 & (C.d1 - 1))// if the cable is layed diagonally, check the others 2 possible directions + C.mergeDiagonalsNetworks(C.d1) + + if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions + C.mergeDiagonalsNetworks(C.d2) + + + use(1) + + C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the ai networks. + return diff --git a/code/modules/mob/living/silicon/ai/ai_network/networking_machines.dm b/code/modules/mob/living/silicon/ai/ai_network/networking_machines.dm new file mode 100644 index 000000000000..cd6b5ed89975 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_network/networking_machines.dm @@ -0,0 +1,189 @@ +GLOBAL_LIST_EMPTY(ai_networking_machines) + +/obj/machinery/ai/networking + name = "networking machine" + desc = "A solar panel. Generates electricity when in contact with sunlight." + icon = 'goon/icons/obj/power.dmi' + icon_state = "sp_base" + density = TRUE + use_power = NO_POWER_USE + idle_power_usage = 0 + active_power_usage = 0 + max_integrity = 150 + integrity_failure = 0.33 + + var/label + //For mapping, will connect to machine with this label if found + var/roundstart_connection + + var/mutable_appearance/panelstructure + var/mutable_appearance/paneloverlay + + var/obj/machinery/ai/networking/partner + var/rotation_to_partner + var/locked = FALSE + var/mob/remote_control + + +/obj/machinery/ai/networking/Initialize(mapload) + . = ..() + if(!label) + label = num2hex(rand(1,65535), -1) + GLOB.ai_networking_machines += src + panelstructure = mutable_appearance(icon, "solar_panel", FLY_LAYER) + paneloverlay = mutable_appearance(icon, "solar_panel-o", FLY_LAYER) + paneloverlay.color = "#599ffa" + update_icon(TRUE) + +/obj/machinery/ai/networking/Destroy(mapload) + GLOB.ai_networking_machines -= src + disconnect() + . = ..() +/obj/machinery/ai/networking/proc/roundstart_connect(mapload) + for(var/obj/machinery/ai/networking/N in GLOB.ai_networking_machines) + if(partner) + break + if(N == src) + continue + if(N.partner) + continue + if(roundstart_connection && N.label == roundstart_connection) + connect_to_partner(N) + break + if(!roundstart_connection) + connect_to_partner(N) + break + + +/obj/machinery/ai/networking/update_icon(forced = FALSE) + ..() + if(!rotation_to_partner && !forced) + return + cut_overlays() + var/matrix/turner = matrix() + turner.Turn(rotation_to_partner) + panelstructure.transform = turner + paneloverlay.transform = turner + add_overlay(list(paneloverlay, panelstructure)) + +/obj/machinery/ai/networking/proc/disconnect() + if(partner) + var/datum/ai_network/AN = partner.network + + partner.partner = null + partner = null + AN.rebuild_remote() + network.rebuild_remote() + + +/obj/machinery/ai/networking/proc/connect_to_partner(obj/machinery/ai/networking/target) + if(target.partner) + return + if(target == src) + return + + + partner = target + rotation_to_partner = Get_Angle(src, partner) + target.partner = src + target.rotation_to_partner = Get_Angle(target, src) + target.update_icon() + + + network.rebuild_remote() + + update_icon() + + +/obj/machinery/ai/networking/ui_status(mob/user) + . = ..() + if (!QDELETED(remote_control) && user == remote_control) + . = UI_INTERACTIVE + +/obj/machinery/ai/networking/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AiNetworking", name) + ui.open() + +/obj/machinery/ai/networking/ui_data(mob/living/carbon/human/user) + var/list/data = list() + + data["is_connected"] = partner ? partner.label : FALSE + data["label"] = label + + data["locked"] = locked + + data["possible_targets"] = list() + for(var/obj/machinery/ai/networking/N in GLOB.ai_networking_machines) + if(N == src) + continue + if(N.z != src.z) + continue + if(N.locked) + continue + data["possible_targets"] += N.label + + return data + +/obj/machinery/ai/networking/ui_act(action, params) + if(..()) + return + + switch(action) + if("switch_label") + if(locked) + return + var/new_label = stripped_input(usr, "Enter new label", "Set label", max_length = 16) + if(new_label) + if(isnotpretty(new_label)) + to_chat(usr, span_notice("The machine rejects the input. See rule 0.1.")) + var/log_message = "[key_name(usr)] just tripped a pretty filter: '[new_label]'." + message_admins(log_message) + log_say(log_message) + return + for(var/obj/machinery/ai/networking/N in GLOB.ai_networking_machines) + if(N.label == new_label) + to_chat(usr, span_warning("A machine with this label already exists!")) + return + label = new_label + . = TRUE + if("connect") + if(locked) + return + var/target_label = params["target_label"] + if(target_label == label) + return + for(var/obj/machinery/ai/networking/N in GLOB.ai_networking_machines) + if(N.z != src.z) + return + if(N.label == target_label) + if(N.locked) + to_chat(usr, span_warning("Unable to connect to '[target_label]'! It seems to be locked.")) + return + if(N.partner) + to_chat(usr, span_warning("Unable to connect to '[target_label]'! It seems to already have a connection established.")) + return + connect_to_partner(N) + to_chat(usr, span_notice("Connection established to '[target_label]'.")) + return + . = TRUE + if("disconnect") + if(locked) + return + disconnect() + . = TRUE + if("toggle_lock") + locked = !locked + . = TRUE + +/obj/machinery/ai/networking/connect_to_network() + . = ..() + if(partner) + network.rebuild_remote() + +/obj/machinery/ai/networking/disconnect_from_network() + var/datum/ai_network/temp = network + . = ..() + if(partner) + temp.rebuild_remote() diff --git a/code/modules/mob/living/silicon/ai/ai_network/shared_resources.dm b/code/modules/mob/living/silicon/ai/ai_network/shared_resources.dm new file mode 100644 index 000000000000..148dbf999d7e --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_network/shared_resources.dm @@ -0,0 +1,250 @@ +/datum/ai_shared_resources + var/ram_sources = list() + var/cpu_sources = list() + + + var/list/cpu_assigned = list() + var/list/ram_assigned = list() + + var/networks = list() + + var/previous_ram = 0 + + + +/datum/ai_shared_resources/New(network_assigned_cpu, network_assigned_ram, datum/ai_network/split_network, datum/ai_network/starting_network) + if((network_assigned_ram || network_assigned_cpu) && split_network) + ram_assigned = network_assigned_ram + cpu_assigned = network_assigned_cpu + + if(split_network) + split_network.resources = src + networks |= split_network + update_resources() + + if(starting_network) + starting_network.resources = src + networks |= starting_network + + for(var/datum/ai_network/AN in networks) + AN.rebuild_remote() + + START_PROCESSING(SSobj, src) + +/datum/ai_shared_resources/Destroy(network_assigned_cpu, network_assigned_ram, datum/ai_network/split_network, datum/ai_network/starting_network) + STOP_PROCESSING(SSobj, src) + . = ..() + +/datum/ai_shared_resources/process() + for(var/datum/ai_network/net in networks) + net.process() + + //Networks automatically use their unspent CPU to research, this just catches cluster unassigned CPU. Local clusters can have their points boosted by local AIs + var/unused_cpu = 1 - total_cpu_assigned() + + var/research_points = max(round(AI_RESEARCH_PER_CPU * (unused_cpu * total_cpu())), 0) + SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_AI = research_points)) + + + + +/datum/ai_shared_resources/proc/total_cpu_assigned() + var/total = 0 + for(var/AI in cpu_assigned) + total += cpu_assigned[AI] + return total + +/datum/ai_shared_resources/proc/total_ram_assigned() + var/total = 0 + for(var/AI in ram_assigned) + total += (ram_assigned[AI]) + return total + +/datum/ai_shared_resources/proc/total_cpu() + var/total = 0 + for(var/C in cpu_sources) + total += cpu_sources[C] + return total + +/datum/ai_shared_resources/proc/total_ram() + var/total = 0 + for(var/C in ram_sources) + total += ram_sources[C] + return total + +/datum/ai_shared_resources/proc/update_resources() + previous_ram = total_ram() + ram_sources = list() + cpu_sources = list() + for(var/datum/ai_network/N in networks) + ram_sources[N] += N.total_ram() + cpu_sources[N] += N.total_cpu() + update_allocations() + +/datum/ai_shared_resources/proc/add_resource(datum/ai_shared_resources/new_resources) + + for(var/RU in new_resources.ram_assigned) + ram_assigned[RU] = new_resources.ram_assigned[RU] + + for(var/CU in cpu_assigned) //We split the CPUs 50/50 + cpu_assigned[CU] = round((cpu_assigned[CU] * 0.5) * 100) / 100 + + for(var/CU in new_resources.cpu_assigned) + cpu_assigned[CU] = round((new_resources.cpu_assigned[CU] * 0.5) * 100) / 100 + + for(var/datum/ai_network/N in new_resources.networks) + networks |= N + N.resources = src + + update_resources() + update_allocations() + qdel(new_resources) + +/datum/ai_shared_resources/proc/split_resources(datum/ai_network/split_network) + var/network_ram_assign = list() + var/network_cpu_assign = list() + + + var/split_network_cpu = 0 + var/network_ais = split_network.ai_list + for(var/A in cpu_assigned) + if(A in network_ais || A == split_network) + network_cpu_assign[A] = cpu_assigned[A] + split_network_cpu += cpu_assigned[A] + cpu_assigned[A] = 0 + + //Normalize CPU so 100% is used in the new network if 100% was used in total before + var/total_usage = total_cpu_assigned() //We normalise around this value, so the split network CPU usage will (approximately) end up at this too + for(var/A in network_cpu_assign) + var/split_usage = network_cpu_assign[A] / split_network_cpu + network_cpu_assign[A] = 1 * round(split_usage, 0.01) + + //We do the same for the network we leave behid + for(var/A in cpu_assigned) + var/split_usage = cpu_assigned[A] / total_usage + cpu_assigned[A] = 1 * round(split_usage, 0.01) + + + //Not needed for RAM since it's not a percentage + for(var/A in ram_assigned) + if(A in network_ais || A == split_network) + network_ram_assign[A] = ram_assigned[A] + ram_assigned[A] = 0 + + networks -= split_network + update_resources() + + new /datum/ai_shared_resources(network_cpu_assign, network_ram_assign, split_network) + + if(!length(networks)) + qdel(src) + + +/datum/ai_shared_resources/proc/update_allocations() + //Do we have the same amount or more RAM than before? Do nothing + var/total_ram = total_ram() + if(total_ram >= previous_ram) + return + //Find out how much is actually assigned. We can have more total_cpu than the sum of cpu_assigned. Same with RAM + var/total_assigned_ram = total_ram_assigned() + //If we have less assigned ram than we have cpu and ram, just return, everything is fine. + if(total_assigned_ram < total_ram) + return + + //Copy the lists of assigned resources so we don't manipulate the list prematurely. + var/list/ram_assigned_copy = ram_assigned.Copy() + //List of touched AIs so we can notify them at the end. + var/list/affected_AIs = list() + + + if(total_assigned_ram > total_ram) + var/needed_amount = total_assigned_ram - total_ram + for(var/A in ram_assigned_copy) + if(isAI(A)) + var/mob/living/silicon/ai/AI = A + if((ram_assigned_copy[AI]) >= needed_amount) + ram_assigned_copy[AI] -= needed_amount + total_assigned_ram -= needed_amount + affected_AIs |= AI + break + else if(ram_assigned_copy[AI]) + var/amount = ram_assigned_copy[AI] + ram_assigned_copy[AI] -= amount + affected_AIs |= AI + needed_amount -= amount + total_assigned_ram -= amount + if(total_ram >= total_assigned_ram) + break + else //If we're not an AI we are a network, networks have no programs to stop (for now) + if((ram_assigned_copy[A]) >= needed_amount) + ram_assigned_copy[A] -= needed_amount + total_assigned_ram -= needed_amount + break + else if(ram_assigned_copy[A]) + var/amount = ram_assigned_copy[A] + ram_assigned_copy[A] -= amount + needed_amount -= amount + total_assigned_ram -= amount + if(total_ram >= total_assigned_ram) + break + //Set the actual values of the assigned to our manipulated copies. Bypass helper procs as we assume we're correct. + ram_assigned = ram_assigned_copy + + to_chat(affected_AIs, span_warning("You have been deducted memory capacity. Please contact your network administrator if you believe this to be an error.")) + + + +/datum/ai_shared_resources/proc/set_cpu(target, amount) + if(!istype(target, /datum/ai_network) && !istype(target, /mob/living/silicon/ai)) + stack_trace("Attempted to set_cpu with non-AI/network target! T: [target]") + return + + if(!target) + return + if(amount > 1 || amount < 0) + return + cpu_assigned[target] = amount + + update_allocations() + + +/datum/ai_shared_resources/proc/add_ram(target, amount) + if(!istype(target, /datum/ai_network) && !istype(target, /mob/living/silicon/ai)) + stack_trace("Attempted to add_ram with non-AI/network target! T: [target]") + return + + if(!target || !amount) + return + ram_assigned[target] += amount + + update_allocations() + + +/datum/ai_shared_resources/proc/remove_ram(target, amount) + if(!istype(target, /datum/ai_network) && !istype(target, /mob/living/silicon/ai)) + stack_trace("Attempted to remove_ram with non-AI/network target! T: [target]") + return + + if(!target || !amount) + return + if(ram_assigned[target] - amount < 0) + ram_assigned[target] = 0 + else + ram_assigned[target] -= amount + + update_allocations() + + +/datum/ai_shared_resources/proc/clear_ai_resources(target) + if(!istype(target, /datum/ai_network) && !istype(target, /mob/living/silicon/ai)) + stack_trace("Attempted to clear_ai_resources with non-AI/network target! T: [target]") + return + + if(!target) + return + + remove_ram(target, ram_assigned[target]) + cpu_assigned[target] = 0 + + update_allocations() + diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index a646a92fb17e..435812c1e0fc 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -26,7 +26,7 @@ ShutOffDoomsdayDevice() - GLOB.ai_os.remove_ai(src) + ai_network?.remove_ai(src) if(explosive) spawn(10) diff --git a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm index dda04e4f79ce..fe7cca02dad2 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/_ai_machinery.dm @@ -9,17 +9,22 @@ icon_state = "RD-server-on" density = TRUE + var/datum/ai_network/network + /obj/machinery/ai/Initialize(mapload) . = ..() SSair.atmos_machinery += src + connect_to_network() /obj/machinery/ai/Destroy() . = ..() - + disconnect_from_network() SSair.atmos_machinery -= src /obj/machinery/ai/proc/valid_holder() + if(!network) + return FALSE if(stat & (BROKEN|NOPOWER|EMPED)) return FALSE @@ -31,13 +36,15 @@ if(istype(T, /turf/open/space) || total_moles < 10) return FALSE - if(env.return_temperature() > GLOB.ai_os.get_temp_limit() || !env.heat_capacity()) + if(env.return_temperature() > network.get_temp_limit() || !env.heat_capacity()) return FALSE return TRUE /obj/machinery/ai/proc/get_holder_status() if(stat & (BROKEN|NOPOWER|EMPED)) return FALSE + if(!network) + return FALSE var/turf/T = get_turf(src) var/datum/gas_mixture/env = T.return_air() @@ -47,6 +54,39 @@ if(istype(T, /turf/open/space) || total_moles < 10) return AI_MACHINE_NO_MOLES - if(env.return_temperature() > GLOB.ai_os.get_temp_limit() || !env.heat_capacity()) + if(env.return_temperature() > network.get_temp_limit() || !env.heat_capacity()) return AI_MACHINE_TOO_HOT - \ No newline at end of file + + +/obj/machinery/ai/proc/connect_to_network() + var/turf/T = src.loc + if(!T || !istype(T)) + return FALSE + + var/obj/structure/ethernet_cable/C = T.get_ai_cable_node() //check if we have a node cable on the machine turf, the first found is picked + if(!C || !C.network) + return FALSE + + C.network.add_machine(src) + return TRUE + +// remove and disconnect the machine from its current powernet +/obj/machinery/ai/proc/disconnect_from_network() + if(!network) + return FALSE + network.remove_machine(src) + return TRUE + +// attach a wire to a power machine - leads from the turf you are standing on +//almost never called, overwritten by all power machines but terminal and generator +/obj/machinery/ai/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/stack/ethernet_coil)) + var/obj/item/stack/ethernet_coil/coil = W + var/turf/T = user.loc + if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !isfloorturf(T)) + return + if(get_dist(src, user) > 1) + return + coil.place_turf(T, user) + else + return ..() diff --git a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm index 69683bb2cf55..61ea4531ef20 100644 --- a/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm +++ b/code/modules/mob/living/silicon/ai/decentralized/ai_data_core.dm @@ -2,7 +2,7 @@ GLOBAL_LIST_EMPTY(data_cores) GLOBAL_VAR_INIT(primary_data_core, null) /obj/machinery/ai/data_core - name = "AI Data Core" + name = "AI data core" desc = "A complicated computer system capable of emulating the neural functions of an organic being at near-instantanous speeds." icon = 'icons/obj/machines/ai_core.dmi' icon_state = "core-offline" @@ -113,8 +113,9 @@ GLOBAL_VAR_INIT(primary_data_core, null) /obj/machinery/ai/data_core/proc/valid_data_core() if(!is_reebe(z) && !is_station_level(z)) return FALSE - if(valid_ticks > 0) + if(valid_ticks > 0 && network && network.total_cpu() >= AI_CORE_CPU_REQUIREMENT && network.total_ram() >= AI_CORE_RAM_REQUIREMENT) return TRUE + return FALSE @@ -168,6 +169,14 @@ GLOBAL_VAR_INIT(primary_data_core, null) AI.forceMove(src) if(AI.eyeobj) AI.eyeobj.forceMove(get_turf(src)) + + if(network != AI.ai_network) + if(AI.ai_network) + AI.ai_network.remove_ai(AI) + var/old_net = AI.ai_network + AI.ai_network = network + network.ai_list += AI + AI.switch_ainet(old_net, network) /obj/machinery/ai/data_core/update_icon() cut_overlays() @@ -179,6 +188,25 @@ GLOBAL_VAR_INIT(primary_data_core, null) else icon_state = "core-offline" +/obj/machinery/ai/data_core/connect_to_network() //If we ever get connected to a network (or a new one gets created) we get the AIs to the correct one too + . = ..() + for(var/mob/living/silicon/ai/AI in contents) + if(!AI.ai_network) + network.ai_list |= AI + var/old_net = AI.ai_network + AI.ai_network = network + AI.switch_ainet(old_net, network) + + if(AI.ai_network != network) + if(AI.ai_network) + AI.ai_network.remove_ai(AI) + var/old_net = AI.ai_network + AI.ai_network = network + network.ai_list |= AI + AI.switch_ainet(old_net, network) + + + /obj/machinery/ai/data_core/proc/partytime() var/current_color = random_color() set_light(7, 3, current_color) @@ -189,6 +217,9 @@ GLOBAL_VAR_INIT(primary_data_core, null) if(TimerID) deltimer(TimerID) TimerID = null + + + /obj/machinery/ai/data_core/primary name = "primary AI Data Core" desc = "A complicated computer system capable of emulating the neural functions of a human at near-instantanous speeds. This one has a scrawny and faded note saying: 'Primary AI Data Core'" diff --git a/code/modules/mob/living/silicon/ai/decentralized/computer_science_datum.dm b/code/modules/mob/living/silicon/ai/decentralized/computer_science_datum.dm new file mode 100644 index 000000000000..daabc3307057 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/decentralized/computer_science_datum.dm @@ -0,0 +1,3 @@ +/datum/computer_science + var/projects = list() + diff --git a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm b/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm deleted file mode 100644 index 42ba34b5257f..000000000000 --- a/code/modules/mob/living/silicon/ai/decentralized/decentralized_os.dm +++ /dev/null @@ -1,131 +0,0 @@ -GLOBAL_DATUM_INIT(ai_os, /datum/ai_os, new) - -/datum/ai_os - var/name = "Decentralized Resource Management System (DRMS)" - - var/total_cpu = 0 - var/total_ram = 0 - - var/previous_ram = 0 - - var/list/cpu_assigned - var/list/ram_assigned - - var/temp_limit = AI_TEMP_LIMIT - -/datum/ai_os/New() - update_hardware() - cpu_assigned = list() - ram_assigned = list() - -/datum/ai_os/proc/remove_ai(mob/living/silicon/ai/AI) - cpu_assigned.Remove(AI) - ram_assigned.Remove(AI) - update_allocations() - -/datum/ai_os/proc/total_cpu_assigned() - var/total = 0 - for(var/N in cpu_assigned) - total += cpu_assigned[N] - return total - -/datum/ai_os/proc/total_ram_assigned() - var/total = 0 - for(var/mob/living/silicon/ai/AI in ram_assigned) - total += (ram_assigned[AI] - AI.dashboard.free_ram) - return total - -/datum/ai_os/proc/update_hardware() - previous_ram = total_ram - total_ram = 0 - total_cpu = 0 - for(var/obj/machinery/ai/server_cabinet/C in GLOB.server_cabinets) - if(!C.valid_holder() && !C.roundstart) - continue - total_ram += C.total_ram - total_cpu += C.total_cpu - - update_allocations() - -/datum/ai_os/proc/update_allocations() - //Do we have the same amount or more RAM than before? Do nothing - if(total_ram >= previous_ram) - return - //Find out how much is actually assigned. We can have more total_cpu than the sum of cpu_assigned. Same with RAM - var/total_assigned_ram = total_ram_assigned() - //If we have less assigned ram than we have cpu and ram, just return, everything is fine. - if(total_assigned_ram < total_ram) - return - - //Copy the lists of assigned resources so we don't manipulate the list prematurely. - var/list/ram_assigned_copy = ram_assigned.Copy() - //List of touched AIs so we can notify them at the end. - var/list/affected_AIs = list() - - - if(total_assigned_ram > total_ram) - var/needed_amount = total_assigned_ram - total_ram - for(var/A in ram_assigned_copy) - var/mob/living/silicon/ai/AI = A - if((ram_assigned_copy[AI] - AI.dashboard.free_ram) >= needed_amount) - ram_assigned_copy[AI] -= needed_amount - total_assigned_ram -= needed_amount - affected_AIs |= AI - break - else if(ram_assigned_copy[AI]) - var/amount = ram_assigned_copy[AI] - AI.dashboard.free_ram - ram_assigned_copy[AI] -= amount - affected_AIs |= AI - needed_amount -= amount - total_assigned_ram -= amount - if(total_ram >= total_assigned_ram) - break - //Set the actual values of the assigned to our manipulated copies. Bypass helper procs as we assume we're correct. - ram_assigned = ram_assigned_copy - - to_chat(affected_AIs, span_warning("You have been deducted memory capacity. Please contact your network administrator if you believe this to be an error.")) - -/datum/ai_os/proc/set_cpu(mob/living/silicon/ai/AI, amount) - if(!AI) - return - if(amount > 1 || amount < 0) - return - if(!istype(AI)) - return - cpu_assigned[AI] = amount - - update_allocations() - -/datum/ai_os/proc/add_ram(mob/living/silicon/ai/AI, amount) - if(!AI || !amount) - return - if(!istype(AI)) - return - ram_assigned[AI] += amount - - update_allocations() - -/datum/ai_os/proc/remove_ram(mob/living/silicon/ai/AI, amount) - if(!AI || !amount) - return - if(!istype(AI)) - return - if(ram_assigned[AI] - amount < 0) - ram_assigned[AI] = 0 - else - ram_assigned[AI] -= amount - - update_allocations() - - -/datum/ai_os/proc/clear_ai_resources(mob/living/silicon/ai/AI) - if(!AI || !istype(AI)) - return - - remove_ram(AI, ram_assigned[AI]) - cpu_assigned[AI] = 0 - - update_allocations() - -/datum/ai_os/proc/get_temp_limit() - return temp_limit diff --git a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm b/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm deleted file mode 100644 index d5ada3439079..000000000000 --- a/code/modules/mob/living/silicon/ai/decentralized/management/ai_controlpanel.dm +++ /dev/null @@ -1,446 +0,0 @@ -GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6)) - -/obj/machinery/computer/ai_control_console - name = "\improper AI control console" - desc = "Used for accessing the central AI repository from which AIs can be downloaded or uploaded." - req_access = list(ACCESS_RD) - icon_keyboard = "tech_key" - icon_screen = "ai-fixer" - light_color = LIGHT_COLOR_PINK - - var/cleared_for_use = FALSE //Have we inserted the RDs code to unlock upload/download? - - var/one_time_password_used = FALSE //Did we use the one time password to log in? If so disallow logging out. - - authenticated = FALSE - - var/obj/item/aicard/intellicard - - var/mob/living/silicon/ai/downloading - var/mob/user_downloading - var/download_progress = 0 - var/download_warning = FALSE - - circuit = /obj/item/circuitboard/computer/ai_upload_download - -/obj/machinery/computer/ai_control_console/Initialize(mapload) - . = ..() - if(mapload) - cleared_for_use = TRUE - -/obj/machinery/computer/ai_control_console/Destroy() - stop_download() - . = ..() - -/obj/machinery/computer/ai_control_console/attackby(obj/item/W, mob/living/user, params) - if(istype(W, /obj/item/aicard)) - if(intellicard) - to_chat(user, span_warning("There's already an IntelliCard inserted!")) - return ..() - to_chat(user, span_notice("You insert [W].")) - W.forceMove(src) - intellicard = W - return FALSE - if(istype(W, /obj/item/mmi)) - var/obj/item/mmi/brain = W - if(!brain.brainmob) - to_chat(user, span_warning("[W] is not active!")) - return ..() - SSticker.mode.remove_antag_for_borging(brain.brainmob.mind) - if(!istype(brain.laws, /datum/ai_laws/ratvar)) - remove_servant_of_ratvar(brain.brainmob, TRUE) - var/mob/living/silicon/ai/A = null - - var/datum/ai_laws/laws = new - laws.set_laws_config() - - if (brain.overrides_aicore_laws) - A = new /mob/living/silicon/ai(loc, brain.laws, brain.brainmob) - else - A = new /mob/living/silicon/ai(loc, laws, brain.brainmob) - - A.relocate(TRUE) - - if(brain.force_replace_ai_name) - A.fully_replace_character_name(A.name, brain.replacement_ai_name()) - SSblackbox.record_feedback("amount", "ais_created", 1) - qdel(W) - to_chat(user, span_notice("AI succesfully uploaded.")) - return FALSE - if(istype(W, /obj/item/surveillance_upgrade)) - if(!authenticated) - to_chat(user, span_warning("You need to be logged in to do this!")) - return ..() - var/mob/living/silicon/ai/AI = input("Select an AI", "Select an AI", null, null) as null|anything in GLOB.ai_list - if(!AI) - return ..() - var/obj/item/surveillance_upgrade/upgrade = W - upgrade.afterattack(AI, user) - - if(istype(W, /obj/item/malf_upgrade)) - if(!authenticated) - to_chat(user, span_warning("You need to be logged in to do this!")) - return ..() - var/mob/living/silicon/ai/AI = input("Select an AI", "Select an AI", null, null) as null|anything in GLOB.ai_list - if(!AI) - return ..() - var/obj/item/malf_upgrade/upgrade = W - upgrade.afterattack(AI, user) - - return ..() - -/obj/machinery/computer/ai_control_console/emag_act(mob/user) - if(obj_flags & EMAGGED) - return - to_chat(user, span_warning("You bypass the access restrictions")) - authenticated = TRUE - obj_flags |= EMAGGED - -/obj/machinery/computer/ai_control_console/process() - if(stat & (BROKEN|NOPOWER|EMPED)) - return - - if(downloading && download_progress >= 50 && !download_warning) - var/turf/T = get_turf(src) - to_chat(downloading, span_userdanger("Warning! Download is 50% completed! Download location: [get_area(src)] ([T.x], [T.y], [T.z])!")) - download_warning = TRUE - if(downloading && download_progress >= 100) - finish_download() - - if(downloading) - if(!downloading.can_download) - stop_download() - return - download_progress += AI_DOWNLOAD_PER_PROCESS * downloading.downloadSpeedModifier - - -/obj/machinery/computer/ai_control_console/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "AiControlPanel", name) - ui.open() - -/obj/machinery/computer/ai_control_console/ui_data(mob/living/carbon/human/user) - var/list/data = list() - - if(!cleared_for_use) - data["cleared_for_use"] = FALSE - return data - - data["cleared_for_use"] = TRUE - data["authenticated"] = authenticated - - if(issilicon(user)) - var/mob/living/silicon/borg = user - data["username"] = borg.name - data["has_access"] = TRUE - - if(IsAdminGhost(user)) - data["username"] = user.client.holder.admin_signature - data["has_access"] = TRUE - - if(ishuman(user) && !(obj_flags & EMAGGED)) - var/username = user.get_authentification_name("Unknown") - data["username"] = user.get_authentification_name("Unknown") - if(username != "Unknown") - var/datum/data/record/record - for(var/RP in GLOB.data_core.general) - var/datum/data/record/R = RP - - if(!istype(R)) - continue - if(R.fields["name"] == username) - record = R - break - if(record) - if(istype(record.fields["photo_front"], /obj/item/photo)) - var/obj/item/photo/P1 = record.fields["photo_front"] - var/icon/picture = icon(P1.picture.picture_image) - picture.Crop(10, 32, 22, 22) - var/md5 = md5(fcopy_rsc(picture)) - - if(!SSassets.cache["photo_[md5]_cropped.png"]) - SSassets.transport.register_asset("photo_[md5]_cropped.png", picture) - SSassets.transport.send_assets(user, list("photo_[md5]_cropped.png" = picture)) - - data["user_image"] = SSassets.transport.get_asset_url("photo_[md5]_cropped.png") - data["has_access"] = check_access(user.get_idcard()) - - if(obj_flags & EMAGGED) - data["username"] = "ERROR" - data["has_access"] = TRUE - - if(!authenticated) - return data - - data["intellicard"] = intellicard - if(intellicard && intellicard.AI) - data["intellicard_ai"] = intellicard.AI.real_name - data["intellicard_ai_health"] = intellicard.AI.health - else - data["intellicard_ai"] = null - data["intellicard_ai_health"] = 0 - - data["can_upload"] = available_ai_cores() - - if(downloading) - data["downloading"] = downloading.real_name - data["download_progress"] = download_progress - data["downloading_ref"] = REF(downloading) - else - data["downloading"] = null - data["download_progress"] = 0 - - data["ais"] = list() - data["current_ai_ref"] = null - if(isAI(user)) - data["current_ai_ref"] = REF(user) - - data["can_log_out"] = !one_time_password_used - - for(var/mob/living/silicon/ai/A in GLOB.ai_list) - var/being_hijacked = A.hijacking ? TRUE : FALSE - data["ais"] += list(list("name" = A.name, "ref" = REF(A), "can_download" = A.can_download, "health" = A.health, "active" = A.mind ? TRUE : FALSE, "being_hijacked" = being_hijacked, "in_core" = istype(A.loc, /obj/machinery/ai/data_core))) - - data["is_infiltrator"] = is_infiltrator(user) - - return data - -/obj/machinery/computer/ai_control_console/proc/finish_download() - if(!is_station_level(z)) - return - if(intellicard) - if(!isaicore(downloading.loc)) - stop_download(TRUE) - return - downloading.transfer_ai(AI_TRANS_TO_CARD, user_downloading, null, intellicard) - intellicard.forceMove(get_turf(src)) - intellicard.update_icon() - intellicard = null - stop_download(TRUE) - -/obj/machinery/computer/ai_control_console/proc/stop_download(silent = FALSE) - if(downloading) - if(!silent) - to_chat(downloading, span_userdanger("Download stopped.")) - downloading = null - user_downloading = null - download_progress = 0 - download_warning = FALSE - -/obj/machinery/computer/ai_control_console/proc/upload_ai(silent = FALSE) - to_chat(intellicard.AI, span_notice("You are being uploaded. Please stand by...")) - intellicard.AI.radio_enabled = TRUE - intellicard.AI.control_disabled = FALSE - intellicard.AI.relocate(TRUE) - intellicard.AI = null - intellicard.update_icon() - -/obj/machinery/computer/ai_control_console/ui_act(action, params) - if(..()) - return - - if(!cleared_for_use) - if(action == "clear_for_use") - var/code = params["control_code"] - - if(!code) - return - - if(!GLOB.ai_control_code) - return - - var/length_of_number = length(code) - if(length_of_number < 6) - to_chat(usr, span_warning("Incorrect code. Too short")) - return - - if(length_of_number > 6) - to_chat(usr, span_warning("Incorrect code. Too long")) - return - - if(!is_station_level(z)) - to_chat(usr, span_warning("Unable to connect to NT Servers. Please verify you are onboard the station.")) - return - - if(code == GLOB.ai_control_code) - cleared_for_use = TRUE - else - to_chat(usr, span_warning("Incorrect code. Make sure you have the latest one.")) - - return - - if(!authenticated) - if(action == "log_in") - if(issilicon(usr)) - authenticated = TRUE - return - - if(IsAdminGhost(usr)) - authenticated = TRUE - - if(obj_flags & EMAGGED) - authenticated = TRUE - - var/mob/living/carbon/human/H = usr - if(!istype(H)) - return - - if(check_access(H.get_idcard())) - authenticated = TRUE - if(action == "log_in_control_code") - var/code = params["control_code"] - - if(!code) - return - - if(!GLOB.ai_control_code) - return - - var/length_of_number = length(code) - if(length_of_number < 6) - to_chat(usr, span_warning("Incorrect code. Too short")) - return - - if(length_of_number > 6) - to_chat(usr, span_warning("Incorrect code. Too long")) - return - - if(code == GLOB.ai_control_code) - cleared_for_use = TRUE - authenticated = TRUE - one_time_password_used = TRUE - var/msg = "