diff --git a/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm b/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm
index 45ec61e3646d..3d3c2a4e4e1b 100644
--- a/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm
+++ b/_maps/RandomRuins/SpaceRuins/TheDerelict.dmm
@@ -3126,12 +3126,6 @@
/obj/structure/cable/smart_cable/color/yellow,
/turf/open/floor/iron/airless,
/area/ruin/space/derelict/bridge/ai_upload)
-"LG" = (
-/obj/item/aicard,
-/obj/structure/cable/smart_cable/color/yellow,
-/obj/effect/mapping_helpers/broken_floor,
-/turf/open/floor/iron/airless,
-/area/ruin/space/derelict/bridge/ai_upload)
"LX" = (
/obj/machinery/power/smes/engineering{
charge = 0
@@ -9425,7 +9419,7 @@ bj
ax
bK
GD
-LG
+GD
am
YQ
ax
diff --git a/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm b/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm
index 0f5ffbcb72c7..570100380483 100644
--- a/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm
+++ b/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm
@@ -111,7 +111,6 @@
/area/ruin/space/abandoned_tele)
"z" = (
/obj/structure/closet/crate,
-/obj/item/aicard,
/obj/item/multitool,
/obj/item/weldingtool,
/obj/item/wrench,
diff --git a/_maps/map_files/Theseus/Theseus.dmm b/_maps/map_files/Theseus/Theseus.dmm
index 5712c1ac7d40..c1a9964caec9 100644
--- a/_maps/map_files/Theseus/Theseus.dmm
+++ b/_maps/map_files/Theseus/Theseus.dmm
@@ -654,6 +654,16 @@
/obj/structure/overfloor_catwalk/iron_dark,
/turf/open/floor/plating,
/area/station/maintenance/port)
+"ajV" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/structure/cable/cyan{
+ icon_state = "3"
+ },
+/obj/machinery/ai_slipper{
+ uses = 10
+ },
+/turf/open/floor/iron/dark,
+/area/station/ai_monitored/turret_protected/ai)
"ajX" = (
/obj/structure/window/reinforced/spawner/west,
/obj/structure/lattice/catwalk,
@@ -2630,6 +2640,8 @@
/obj/machinery/porta_turret/ai{
dir = 4
},
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/status_display/ai/directional/west,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"aVq" = (
@@ -2641,6 +2653,8 @@
/obj/machinery/porta_turret/ai{
dir = 8
},
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/status_display/ai/directional/east,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"aVt" = (
@@ -2753,7 +2767,7 @@
/turf/open/floor/iron/ported/techfloor_grid,
/area/station/engineering/supermatter/room)
"aWN" = (
-/turf/open/floor/circuit,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"aWT" = (
/obj/effect/turf_decal/stripes/line{
@@ -3123,7 +3137,7 @@
/obj/structure/cable/cyan{
icon_state = "12"
},
-/turf/open/floor/circuit,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"beX" = (
/obj/structure/disposalpipe/segment{
@@ -3640,6 +3654,13 @@
"bnW" = (
/turf/open/floor/iron/dark,
/area/station/command/bridge)
+"bnZ" = (
+/obj/machinery/porta_turret/ai{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/turf/open/floor/iron/dark,
+/area/station/ai_monitored/turret_protected/ai)
"bon" = (
/obj/machinery/power/terminal{
dir = 1
@@ -4079,12 +4100,6 @@
/obj/item/radio/intercom/directional/south,
/turf/open/floor/iron/freezer,
/area/station/commons/toilet/restrooms)
-"bvw" = (
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
- },
-/turf/open/floor/iron/grimy,
-/area/station/tcommsat/computer)
"bvB" = (
/obj/item/kirbyplants{
icon_state = "plant-20"
@@ -9131,20 +9146,6 @@
/obj/effect/decal/cleanable/cobweb/cobweb2,
/turf/open/floor/carpet,
/area/station/commons/dorms)
-"dor" = (
-/obj/effect/spawner/structure/window/reinforced/prepainted/daedalus,
-/obj/machinery/door/poddoor/shutters/preopen{
- name = "AI core shutters";
- id = "AI Core shutters"
- },
-/obj/structure/cable/red{
- icon_state = "3"
- },
-/obj/structure/cable/red{
- icon_state = "1"
- },
-/turf/open/floor/plating,
-/area/station/ai_monitored/turret_protected/ai)
"dot" = (
/obj/structure/chair/comfy/brown{
dir = 1
@@ -13813,22 +13814,6 @@
/obj/effect/mapping_helpers/airlock/access/all/medical/general,
/turf/open/floor/iron/white,
/area/station/medical/virology)
-"eZP" = (
-/obj/machinery/door/window{
- name = "Primary AI Core Access";
- icon_state = "rightsecure";
- dir = 4;
- atom_integrity = 300;
- base_state = "rightsecure";
- req_access_txt = "16"
- },
-/obj/machinery/camera/directional/north{
- network = list("aicore");
- c_tag = "AI Chamber - Core"
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/turf/open/floor/iron/dark,
-/area/station/ai_monitored/turret_protected/ai)
"eZV" = (
/obj/effect/turf_decal/stripes/corner,
/obj/structure/cable/yellow{
@@ -14087,6 +14072,13 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{
dir = 1
},
+/obj/machinery/turretid{
+ name = "AI Chamber turret control";
+ icon_state = "control_stun";
+ pixel_x = 3;
+ pixel_y = -23
+ },
+/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"ffx" = (
@@ -15435,15 +15427,6 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/wood,
/area/station/commons/lounge)
-"fKn" = (
-/obj/machinery/flasher/directional/east{
- pixel_y = 26;
- id = "AI"
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/obj/machinery/holopad/secure,
-/turf/open/floor/iron/dark,
-/area/station/ai_monitored/turret_protected/ai)
"fKp" = (
/turf/closed/wall/prepainted/daedalus,
/area/station/security/prison/shower)
@@ -16682,12 +16665,6 @@
network = list("aicore");
c_tag = "AI Chamber - Starboard"
},
-/obj/structure/showcase/cyborg/old{
- dir = 8;
- pixel_x = 9;
- pixel_y = 2
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"gjD" = (
@@ -17058,6 +17035,7 @@
/obj/structure/cable/cyan{
icon_state = "10"
},
+/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"grZ" = (
@@ -17632,6 +17610,13 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible/layer2,
/turf/open/floor/iron,
/area/station/maintenance/disposal/incinerator)
+"gAv" = (
+/obj/machinery/porta_turret/ai{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/turf/open/floor/iron/dark,
+/area/station/ai_monitored/turret_protected/ai)
"gAB" = (
/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{
dir = 4
@@ -19271,9 +19256,6 @@
/turf/open/floor/iron,
/area/station/service/hydroponics)
"hfN" = (
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
- },
/obj/effect/turf_decal/tile/blue{
dir = 1
},
@@ -20795,7 +20777,7 @@
/obj/structure/cable/cyan{
icon_state = "3"
},
-/turf/open/floor/circuit,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"hON" = (
/obj/structure/sign/map/left{
@@ -21250,6 +21232,7 @@
"hXC" = (
/obj/machinery/status_display/evac/directional/north,
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2,
+/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"hXD" = (
@@ -22947,7 +22930,8 @@
/area/station/medical/virology)
"iCV" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/turf/open/floor/circuit,
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"iCY" = (
/obj/structure/table,
@@ -23464,17 +23448,8 @@
/turf/open/floor/iron,
/area/station/security/checkpoint/customs)
"iOn" = (
-/obj/machinery/ai_slipper{
- uses = 10
- },
-/obj/machinery/flasher/directional/south{
- pixel_x = 26;
- id = "AI"
- },
/obj/effect/turf_decal/tile/neutral/fourcorners,
-/obj/structure/cable/red{
- icon_state = "9"
- },
+/obj/machinery/holopad/secure,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"iOp" = (
@@ -24003,8 +23978,7 @@
/area/station/maintenance/port/aft)
"iZN" = (
/obj/machinery/light/directional/east,
-/obj/machinery/status_display/ai/directional/east,
-/turf/open/floor/circuit,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"iZR" = (
/obj/structure/toilet{
@@ -25161,36 +25135,10 @@
/turf/open/floor/wood,
/area/station/hallway/secondary/exit)
"jug" = (
-/obj/effect/landmark/start/ai/secondary,
-/obj/item/radio/intercom/directional/north{
- name = "Custom Channel";
- pixel_x = -8;
- listening = 0;
- freerange = 1
- },
-/obj/item/radio/intercom/directional/west{
- name = "Common Channel";
- listening = 0;
- freerange = 1
- },
-/obj/item/radio/intercom/directional/south{
- name = "Private Channel";
- pixel_x = -8;
- frequency = 1447;
- listening = 0;
- freerange = 1
- },
-/obj/machinery/door/window{
- name = "Secondary AI Core Access";
- icon_state = "rightsecure";
- dir = 4;
- layer = 4.1;
- pixel_x = 4;
- atom_integrity = 300;
- base_state = "rightsecure";
- req_access_txt = "16"
+/obj/machinery/power/smes{
+ charge = 1e+07
},
-/turf/open/floor/circuit/green,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"juZ" = (
/obj/machinery/door/firedoor,
@@ -26423,40 +26371,6 @@
},
/turf/open/floor/plating,
/area/station/maintenance/port)
-"jUG" = (
-/obj/item/radio/intercom/directional/west{
- name = "Common Channel";
- pixel_y = -8;
- listening = 0;
- freerange = 1
- },
-/obj/item/radio/intercom/directional/south{
- name = "Private Channel";
- frequency = 1447;
- listening = 0;
- freerange = 1
- },
-/obj/item/radio/intercom/directional/east{
- name = "Custom Channel";
- pixel_y = -8;
- listening = 0;
- freerange = 1
- },
-/obj/effect/landmark/start/ai,
-/obj/machinery/button/door/directional/south{
- name = "AI Chamber Entrance Shutters Control";
- pixel_x = -24;
- id = "AI Chamber entrance shutters";
- req_access_txt = "16"
- },
-/obj/machinery/button/door/directional/south{
- name = "AI Core Shutters Control";
- pixel_x = 24;
- id = "AI Core shutters";
- req_access_txt = "16"
- },
-/turf/open/floor/circuit/green,
-/area/station/ai_monitored/turret_protected/ai)
"jUK" = (
/obj/effect/decal/cleanable/dirt,
/turf/closed/wall/prepainted/daedalus,
@@ -26468,15 +26382,12 @@
/turf/open/floor/engine/airless,
/area/station/engineering/supermatter/room)
"jVh" = (
-/obj/machinery/ai_slipper{
- uses = 10
- },
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/structure/cable/cyan{
icon_state = "6"
},
-/turf/open/floor/circuit,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"jVp" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
@@ -28180,12 +28091,7 @@
/turf/open/floor/iron/ported/techfloor_grid,
/area/station/engineering/supermatter/room)
"kBT" = (
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
- },
-/obj/structure/cable/red{
- icon_state = "48"
- },
+/obj/structure/ai_fluff/brad,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"kBZ" = (
@@ -29066,9 +28972,6 @@
/turf/open/floor/carpet,
/area/station/command/heads_quarters/captain/private)
"kTN" = (
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
- },
/obj/effect/turf_decal/tile/blue{
dir = 4
},
@@ -30447,12 +30350,7 @@
/turf/open/floor/iron/white,
/area/station/medical/virology)
"lro" = (
-/obj/structure/showcase/cyborg/old{
- dir = 4;
- pixel_x = -9;
- pixel_y = 2
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/power/apc/auto_name/directional/west,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"lrq" = (
@@ -32117,7 +32015,6 @@
/area/station/maintenance/port/fore)
"lZB" = (
/obj/structure/table,
-/obj/item/aicard,
/obj/item/ai_module/reset,
/turf/open/floor/iron/dark,
/area/station/engineering/storage/tech)
@@ -36258,11 +36155,8 @@
/turf/open/floor/iron,
/area/station/hallway/primary/central/starboard)
"nxW" = (
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/obj/machinery/holopad/secure,
-/obj/machinery/flasher/directional/west{
- pixel_y = -26;
- id = "AI"
+/obj/machinery/power/terminal{
+ dir = 8
},
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
@@ -36811,13 +36705,6 @@
/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible,
/turf/closed/wall/prepainted/daedalus,
/area/station/engineering/atmos/pumproom)
-"nHn" = (
-/obj/machinery/ai_slipper{
- uses = 10
- },
-/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/turf/open/floor/circuit,
-/area/station/ai_monitored/turret_protected/ai)
"nHo" = (
/obj/machinery/power/apc/auto_name/directional/south,
/obj/structure/disposalpipe/segment{
@@ -37087,13 +36974,11 @@
network = list("aicore");
c_tag = "AI Chamber - Fore"
},
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
- },
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/cable/cyan{
icon_state = "12"
},
+/obj/structure/ai_fluff,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"nMh" = (
@@ -37899,8 +37784,7 @@
/area/station/service/hydroponics)
"odP" = (
/obj/machinery/light/directional/west,
-/obj/machinery/status_display/ai/directional/west,
-/turf/open/floor/circuit,
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"oee" = (
/obj/machinery/status_display/evac/directional/west,
@@ -38093,14 +37977,8 @@
/turf/open/floor/iron,
/area/station/security/medical)
"ohJ" = (
-/obj/machinery/power/smes{
- charge = 1e+07
- },
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/obj/structure/cable/red{
- icon_state = "128"
- },
-/turf/open/floor/iron/dark,
+/turf/closed/wall/r_wall/prepainted/daedalus,
/area/station/ai_monitored/turret_protected/ai)
"ohL" = (
/obj/effect/decal/cleanable/dirt,
@@ -39228,15 +39106,6 @@
},
/turf/open/floor/iron,
/area/station/security/prison/garden)
-"oDc" = (
-/obj/structure/showcase/cyborg/old{
- dir = 8;
- pixel_x = 9;
- pixel_y = 2
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/turf/open/floor/iron/dark,
-/area/station/ai_monitored/turret_protected/ai)
"oDe" = (
/obj/structure/lattice/catwalk,
/obj/structure/transit_tube/crossing/horizontal,
@@ -39381,11 +39250,6 @@
/obj/machinery/field/generator,
/turf/open/floor/plating,
/area/station/engineering/main)
-"oFC" = (
-/obj/machinery/status_display/ai/directional/west,
-/obj/machinery/light/directional/west,
-/turf/open/floor/circuit,
-/area/station/ai_monitored/turret_protected/ai)
"oFG" = (
/obj/machinery/light/cold/directional/south,
/obj/machinery/firealarm/directional/south,
@@ -40264,6 +40128,10 @@
/obj/machinery/light/small/directional/west,
/turf/open/floor/iron/dark/telecomms,
/area/station/tcommsat/server)
+"oXB" = (
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/turf/open/floor/iron/dark,
+/area/station/ai_monitored/turret_protected/ai)
"oXF" = (
/obj/structure/cable/yellow{
icon_state = "3"
@@ -44639,9 +44507,6 @@
/area/station/security/courtroom)
"qFO" = (
/obj/machinery/light_switch/directional/north,
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
- },
/turf/open/floor/iron/grimy,
/area/station/tcommsat/computer)
"qFP" = (
@@ -47750,7 +47615,6 @@
/area/station/ai_monitored/security/armory)
"rOb" = (
/obj/structure/rack,
-/obj/item/aicard,
/obj/item/radio/off,
/obj/machinery/computer/security/telescreen/minisat{
dir = 1;
@@ -48326,11 +48190,9 @@
/turf/open/floor/plating,
/area/station/maintenance/solars/port/fore)
"rYA" = (
-/obj/machinery/porta_turret/ai,
-/obj/machinery/flasher/directional/north{
- id = "AI"
+/obj/machinery/ai_slipper{
+ uses = 10
},
-/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"rYU" = (
@@ -48549,28 +48411,6 @@
/obj/machinery/atmospherics/pipe/layer_manifold/yellow/visible,
/turf/open/floor/iron/dark,
/area/station/engineering/atmos)
-"sdh" = (
-/obj/machinery/turretid{
- name = "AI Chamber turret control";
- icon_state = "control_stun";
- pixel_x = 3;
- pixel_y = -23
- },
-/obj/machinery/door/window{
- name = "Primary AI Core Access";
- icon_state = "leftsecure";
- dir = 8;
- atom_integrity = 300;
- base_state = "leftsecure";
- req_access_txt = "16"
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
-/obj/machinery/power/apc/auto_name/directional/north,
-/obj/structure/cable/red{
- icon_state = "4"
- },
-/turf/open/floor/iron/dark,
-/area/station/ai_monitored/turret_protected/ai)
"sdl" = (
/obj/effect/turf_decal/stripes/line{
dir = 1
@@ -48962,17 +48802,32 @@
/turf/open/floor/iron,
/area/station/hallway/primary/fore)
"sjZ" = (
-/obj/machinery/power/terminal{
- dir = 1
- },
-/obj/machinery/flasher/directional/north{
- pixel_x = -22;
- id = "AI"
- },
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/cable/cyan{
icon_state = "4"
},
+/obj/effect/landmark/start/ai,
+/obj/item/radio/intercom/directional/east{
+ name = "Private Channel";
+ frequency = 1447;
+ listening = 0;
+ broadcasting = 1;
+ pixel_x = -26;
+ pixel_y = -26
+ },
+/obj/item/radio/intercom/directional/east{
+ name = "Common Channel";
+ listening = 0;
+ freerange = 1;
+ pixel_x = 0;
+ pixel_y = -26
+ },
+/obj/item/radio/intercom/directional/east{
+ name = "Custom Channel";
+ pixel_y = -26;
+ listening = 0;
+ freerange = 1
+ },
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"ska" = (
@@ -51183,15 +51038,6 @@
/obj/structure/window/reinforced/spawner/east,
/turf/open/floor/iron,
/area/station/security/checkpoint/customs)
-"sZI" = (
-/obj/machinery/ai_slipper{
- uses = 10
- },
-/obj/structure/cable/red{
- icon_state = "66"
- },
-/turf/open/floor/circuit,
-/area/station/ai_monitored/turret_protected/ai)
"sZX" = (
/obj/effect/turf_decal/tile/yellow{
dir = 8
@@ -51564,10 +51410,6 @@
/obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance,
/turf/open/floor/plating,
/area/station/maintenance/starboard/greater)
-"tfz" = (
-/obj/machinery/airalarm/directional/north,
-/turf/open/floor/circuit,
-/area/station/ai_monitored/turret_protected/ai)
"tfM" = (
/obj/machinery/firealarm/directional/north,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
@@ -53393,12 +53235,7 @@
network = list("aicore");
c_tag = "AI Chamber - Port"
},
-/obj/structure/showcase/cyborg/old{
- dir = 4;
- pixel_x = -9;
- pixel_y = 2
- },
-/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/machinery/airalarm/directional/west,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"tRC" = (
@@ -55224,38 +55061,6 @@
/obj/effect/turf_decal/tile/neutral,
/turf/open/floor/iron,
/area/station/hallway/secondary/exit)
-"uAj" = (
-/obj/effect/landmark/start/ai/secondary,
-/obj/item/radio/intercom/directional/north{
- name = "Custom Channel";
- pixel_x = 8;
- listening = 0;
- freerange = 1
- },
-/obj/item/radio/intercom/directional/east{
- name = "Common Channel";
- listening = 0;
- freerange = 1
- },
-/obj/item/radio/intercom/directional/south{
- name = "Private Channel";
- pixel_x = 8;
- frequency = 1447;
- listening = 0;
- freerange = 1
- },
-/obj/machinery/door/window{
- name = "Tertiary AI Core Access";
- icon_state = "leftsecure";
- dir = 8;
- layer = 4.1;
- pixel_x = -3;
- atom_integrity = 300;
- base_state = "leftsecure";
- req_access_txt = "16"
- },
-/turf/open/floor/circuit/green,
-/area/station/ai_monitored/turret_protected/ai)
"uAl" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/public/glass{
@@ -55445,16 +55250,6 @@
/obj/structure/sign/poster/contraband/random/directional/east,
/turf/open/floor/wood,
/area/station/service/theater)
-"uEH" = (
-/obj/machinery/ai_slipper{
- uses = 10
- },
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/obj/structure/cable/cyan{
- icon_state = "3"
- },
-/turf/open/floor/circuit,
-/area/station/ai_monitored/turret_protected/ai)
"uEI" = (
/obj/machinery/door/firedoor,
/obj/effect/landmark/navigate_destination,
@@ -55937,6 +55732,7 @@
/obj/structure/cable/yellow{
icon_state = "144"
},
+/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"uNA" = (
@@ -56264,7 +56060,10 @@
/area/station/maintenance/port/greater)
"uUX" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/turf/open/floor/circuit,
+/obj/machinery/ai_slipper{
+ uses = 10
+ },
+/turf/open/floor/iron/dark,
/area/station/ai_monitored/turret_protected/ai)
"uUZ" = (
/obj/machinery/holopad,
@@ -59207,12 +59006,6 @@
pixel_x = 5;
pixel_y = -1
},
-/obj/item/radio/intercom/directional/east{
- name = "Private Channel";
- frequency = 1447;
- listening = 0;
- broadcasting = 1
- },
/obj/machinery/telephone/security,
/obj/machinery/power/data_terminal,
/obj/structure/cable/yellow{
@@ -120661,8 +120454,8 @@ aaa
aaa
cTo
sqf
-aVl
-oFC
+bnZ
+odP
tRv
nxW
lro
@@ -120919,12 +120712,12 @@ cTo
cTo
sqf
hXC
+azv
+azv
+azv
uUX
-uUX
-nHn
-uUX
-uUX
-uUX
+azv
+azv
azv
dKG
aAp
@@ -121176,13 +120969,13 @@ cTo
cTo
sqf
kBT
+oXB
aWN
-sqf
-sdh
-sqf
-sqf
aWN
-uUX
+aWN
+aWN
+aWN
+azv
ffv
aAp
hfN
@@ -121190,7 +120983,7 @@ esU
tMH
bsb
uBD
-bvw
+bxq
yex
bxq
bJh
@@ -121433,11 +121226,11 @@ lzc
lzc
ohJ
sjZ
-sZI
-dor
+oXB
+rYA
iOn
-jUG
-sqf
+aWN
+aWN
rYA
jVh
aKb
@@ -121691,11 +121484,11 @@ cTo
sqf
nMc
iCV
-sqf
-eZP
-sqf
-sqf
-tfz
+aWN
+aWN
+aWN
+aWN
+aWN
beK
uNc
aAp
@@ -121949,8 +121742,8 @@ sqf
grP
hOq
hOq
-uEH
hOq
+ajV
hOq
hOq
dAN
@@ -122203,10 +121996,10 @@ aaa
aaa
cTo
sqf
-aVr
+gAv
iZN
-oDc
-fKn
+aWN
+aWN
gjC
iZN
aVr
@@ -122463,7 +122256,7 @@ cTo
sqf
sqf
sqf
-uAj
+sqf
sqf
sqf
sqf
diff --git a/_maps/multiz_debug.json b/_maps/multiz_debug.json
index 4ffc3abd519e..eaa71b7e2208 100644
--- a/_maps/multiz_debug.json
+++ b/_maps/multiz_debug.json
@@ -11,12 +11,12 @@
{
"Up": 1,
"Down": -1,
- "Baseturf": "/turf/open/space/openspace",
+ "Baseturf": "/turf/open/openspace",
"Linkage": "Cross"
},
{
"Down": -1,
- "Baseturf": "/turf/open/space/openspace",
+ "Baseturf": "/turf/open/openspace",
"Linkage": "Cross"
}
]
diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm
index 2b9d0ee8ae93..e38da5492ac6 100644
--- a/_maps/shuttles/emergency_cere.dmm
+++ b/_maps/shuttles/emergency_cere.dmm
@@ -1143,11 +1143,6 @@
},
/turf/open/floor/iron/white,
/area/shuttle/escape)
-"kk" = (
-/obj/machinery/computer/aifixer,
-/obj/effect/turf_decal/tile/purple/fourcorners,
-/turf/open/floor/iron/dark,
-/area/shuttle/escape)
"ok" = (
/obj/structure/table,
/obj/item/storage/medkit/regular{
@@ -1543,7 +1538,7 @@ dz
aa
aa
ac
-kk
+DS
PD
ap
aI
diff --git a/_maps/shuttles/emergency_cruise.dmm b/_maps/shuttles/emergency_cruise.dmm
index 2333334989ff..bb215a69ca06 100644
--- a/_maps/shuttles/emergency_cruise.dmm
+++ b/_maps/shuttles/emergency_cruise.dmm
@@ -746,9 +746,6 @@
"FR" = (
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue,
-/obj/machinery/computer/aifixer{
- dir = 4
- },
/obj/effect/turf_decal/tile/purple{
dir = 8
},
diff --git a/_maps/shuttles/emergency_raven.dmm b/_maps/shuttles/emergency_raven.dmm
index 18be85732e48..2257b52b8cf5 100644
--- a/_maps/shuttles/emergency_raven.dmm
+++ b/_maps/shuttles/emergency_raven.dmm
@@ -50,7 +50,6 @@
/area/shuttle/escape)
"ai" = (
/obj/effect/turf_decal/bot_white,
-/obj/machinery/computer/aifixer,
/turf/open/floor/iron/dark,
/area/shuttle/escape)
"aj" = (
diff --git a/_maps/shuttles/infiltrator_basic.dmm b/_maps/shuttles/infiltrator_basic.dmm
index a4fdebbc865d..0daed21a0875 100644
--- a/_maps/shuttles/infiltrator_basic.dmm
+++ b/_maps/shuttles/infiltrator_basic.dmm
@@ -62,7 +62,6 @@
req_access_txt = "150";
pixel_y = 24
},
-/obj/item/aicard,
/obj/structure/table/reinforced/plastitaniumglass,
/turf/open/floor/iron/dark,
/area/shuttle/syndicate/bridge)
@@ -918,9 +917,6 @@
"DP" = (
/obj/machinery/light/directional/east,
/obj/effect/turf_decal/tile/red,
-/obj/machinery/computer/aifixer{
- dir = 8
- },
/turf/open/floor/iron/dark,
/area/shuttle/syndicate/bridge)
"Ed" = (
diff --git a/_maps/templates/battlecruiser_starfury.dmm b/_maps/templates/battlecruiser_starfury.dmm
index 7abed57e0ffd..0b2953bf7c08 100644
--- a/_maps/templates/battlecruiser_starfury.dmm
+++ b/_maps/templates/battlecruiser_starfury.dmm
@@ -443,7 +443,6 @@
/area/shuttle/sbc_starfury)
"bq" = (
/obj/structure/table/reinforced,
-/obj/item/aicard,
/obj/structure/window/reinforced/survival_pod{
dir = 4
},
diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm
index c6fab7e2e4e7..88522648beaf 100644
--- a/code/__DEFINES/construction.dm
+++ b/code/__DEFINES/construction.dm
@@ -37,14 +37,6 @@
#define FAILED_UNFASTEN 1
#define SUCCESSFUL_UNFASTEN 2
-//ai core defines
-#define EMPTY_CORE 0
-#define CIRCUIT_CORE 1
-#define SCREWED_CORE 2
-#define CABLED_CORE 3
-#define GLASS_CORE 4
-#define AI_READY_CORE 5
-
//Construction defines for the pinion airlock
#define GEAR_SECURE 1
#define GEAR_LOOSE 2
diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm
index d4fd44c293c0..9ac0af5ea44c 100644
--- a/code/__DEFINES/robots.dm
+++ b/code/__DEFINES/robots.dm
@@ -20,12 +20,8 @@
#define AI_NOTIFICATION_CYBORG_DISCONNECTED 5
//transfer_ai() defines. Main proc in ai_core.dm
-///Downloading AI to InteliCard
-#define AI_TRANS_TO_CARD 1
-///Uploading AI from InteliCard
-#define AI_TRANS_FROM_CARD 2
///Malfunctioning AI hijacking mecha
-#define AI_MECH_HACK 3
+#define AI_MECH_HACK 1
/** Cyborg defines */
diff --git a/code/datums/components/crafting/recipes.dm b/code/datums/components/crafting/recipes.dm
index eace4fbd2ff9..0efacb338105 100644
--- a/code/datums/components/crafting/recipes.dm
+++ b/code/datums/components/crafting/recipes.dm
@@ -617,34 +617,6 @@
tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
category = CAT_MISC
-/datum/crafting_recipe/aitater
- name = "intelliTater"
- result = /obj/item/aicard/aitater
- time = 30
- tool_behaviors = list(TOOL_WIRECUTTER)
- reqs = list(/obj/item/aicard = 1,
- /obj/item/food/grown/potato = 1,
- /obj/item/stack/cable_coil = 5)
- category = CAT_MISC
-
-/datum/crafting_recipe/aitater/check_requirements(mob/user, list/collected_requirements)
- var/obj/item/aicard/aicard = collected_requirements[/obj/item/aicard][1]
- if(!aicard.AI)
- return TRUE
-
- to_chat(user, span_boldwarning("You can't craft an intelliTater with an AI in the card!"))
- return FALSE
-
-/datum/crafting_recipe/aispook
- name = "intelliLantern"
- result = /obj/item/aicard/aispook
- time = 30
- tool_behaviors = list(TOOL_WIRECUTTER)
- reqs = list(/obj/item/aicard = 1,
- /obj/item/food/grown/pumpkin = 1,
- /obj/item/stack/cable_coil = 5)
- category = CAT_MISC
-
/datum/crafting_recipe/ghettojetpack
name = "Improvised Jetpack"
result = /obj/item/tank/jetpack/improvised
diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm
deleted file mode 100644
index a8c9e5bed817..000000000000
--- a/code/game/machinery/computer/aifixer.dm
+++ /dev/null
@@ -1,141 +0,0 @@
-/obj/machinery/computer/aifixer
- name = "\improper AI system integrity restorer"
- desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
- req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_MANAGEMENT)
- circuit = /obj/item/circuitboard/computer/aifixer
- icon_keyboard = "tech_key"
- icon_screen = "ai-fixer"
- light_color = LIGHT_COLOR_PINK
-
- /// Variable containing transferred AI
- var/mob/living/silicon/ai/occupier
- /// Variable dictating if we are in the process of restoring the occupier AI
- var/restoring = FALSE
-
-/obj/machinery/computer/aifixer/screwdriver_act(mob/living/user, obj/item/I)
- if(occupier)
- if(machine_stat & (NOPOWER|BROKEN))
- to_chat(user, span_warning("The screws on [name]'s screen won't budge."))
- else
- to_chat(user, span_warning("The screws on [name]'s screen won't budge and it emits a warning beep."))
- else
- return ..()
-
-/obj/machinery/computer/aifixer/ui_interact(mob/user, datum/tgui/ui)
- . = ..()
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "AiRestorer", name)
- ui.open()
-
-/obj/machinery/computer/aifixer/ui_data(mob/user)
- var/list/data = list()
-
- data["ejectable"] = FALSE
- data["AI_present"] = FALSE
- data["error"] = null
- if(!occupier)
- data["error"] = "Please transfer an AI unit."
- else
- data["AI_present"] = TRUE
- data["name"] = occupier.name
- data["restoring"] = restoring
- data["health"] = (occupier.health + 100) / 2
- data["isDead"] = occupier.stat == DEAD
- data["laws"] = occupier.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
-
- return data
-
-/obj/machinery/computer/aifixer/ui_act(action, params)
- . = ..()
- if(.)
- return
-
- if(!occupier)
- restoring = FALSE
-
- switch(action)
- if("PRG_beginReconstruction")
- if(occupier?.health < 100)
- to_chat(usr, span_notice("Reconstruction in progress. This will take several minutes."))
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
- restoring = TRUE
- occupier.notify_ghost_revival("Your core files are being restored!", source = src)
- . = TRUE
-
-/obj/machinery/computer/aifixer/proc/Fix()
- use_power(1000)
- occupier.adjustOxyLoss(-5, FALSE)
- occupier.adjustFireLoss(-5, FALSE)
- occupier.adjustBruteLoss(-5, FALSE)
- occupier.updatehealth()
- if(occupier.health >= 0 && occupier.stat == DEAD)
- occupier.revive(full_heal = FALSE, admin_revive = FALSE)
- if(!occupier.radio_enabled)
- occupier.radio_enabled = TRUE
- to_chat(occupier, span_warning("Your Subspace Transceiver has been enabled!"))
- return occupier.health < 100
-
-/obj/machinery/computer/aifixer/process()
- if(..())
- if(restoring)
- var/oldstat = occupier.stat
- restoring = Fix()
- if(oldstat != occupier.stat)
- update_appearance()
-
-/obj/machinery/computer/aifixer/update_overlays()
- . = ..()
- if(machine_stat & (NOPOWER|BROKEN))
- return
-
- if(restoring)
- . += "ai-fixer-on"
-
- if(!occupier)
- . += "ai-fixer-empty"
- return
- switch(occupier.stat)
- if(CONSCIOUS)
- . += "ai-fixer-full"
- if(UNCONSCIOUS)
- . += "ai-fixer-404"
-
-/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
- if(!..())
- return
- //Downloading AI from card to terminal.
- if(interaction == AI_TRANS_FROM_CARD)
- if(machine_stat & (NOPOWER|BROKEN))
- to_chat(user, span_alert("[src] is offline and cannot take an AI at this time."))
- return
- AI.forceMove(src)
- occupier = AI
- AI.control_disabled = TRUE
- AI.radio_enabled = FALSE
- to_chat(AI, span_alert("You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."))
- to_chat(user, "[span_notice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
- card.AI = null
- update_appearance()
-
- else //Uploading AI from terminal to card
- if(occupier && !restoring)
- to_chat(occupier, span_notice("You have been downloaded to a mobile storage device. Still no remote access."))
- to_chat(user, "[span_notice("Transfer successful")]: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
- occupier.forceMove(card)
- card.AI = occupier
- occupier = null
- update_appearance()
- else if (restoring)
- to_chat(user, span_alert("ERROR: Reconstruction in progress."))
- else if (!occupier)
- to_chat(user, span_alert("ERROR: Unable to locate artificial intelligence."))
-
-/obj/machinery/computer/aifixer/Destroy()
- if(occupier)
- QDEL_NULL(occupier)
- return ..()
-
-/obj/machinery/computer/aifixer/on_deconstruction()
- if(occupier)
- QDEL_NULL(occupier)
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index bd1d8ef83cea..7a2bccd7797d 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -12,6 +12,7 @@
#define TURRET_FLAG_SHOOT_UNSHIELDED (1<<5) // Checks if it can shoot people that aren't mindshielded and who arent heads
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
#define TURRET_FLAG_SHOOT_MANAGEMENT (1<<7) // checks if it can shoot at management
+#define TURRET_FLAG_SHOOT_ENGINEERS (1<<8) // checks if it can shoot at engineers
DEFINE_BITFIELD(turret_flags, list(
"TURRET_FLAG_SHOOT_ALL_REACT" = TURRET_FLAG_SHOOT_ALL_REACT,
@@ -548,6 +549,12 @@ TYPEINFO_DEF(/obj/machinery/porta_turret)
if(apparent_job?.departments_bitflags & DEPARTMENT_BITFLAG_MANAGEMENT)
return 0
+ // If we aren't shooting daedalus staff.
+ if (!(turret_flags & TURRET_FLAG_SHOOT_ENGINEERS))
+ var/datum/job/apparent_job = SSjob.GetJob(perp.get_assignment())
+ if(apparent_job?.departments_bitflags & DEPARTMENT_BITFLAG_ENGINEERING)
+ return 0
+
if(turret_flags & TURRET_FLAG_AUTH_WEAPONS) //check for weapon authorization
if(!istype(perp.wear_id?.GetID(), /obj/item/card/id/advanced/chameleon))
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 5f8bb2776c2e..cfc606ebd404 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -240,12 +240,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark)
new /obj/structure/ai_core/latejoin_inactive(loc)
return ..()
-/obj/effect/landmark/start/ai/secondary
- icon = 'icons/effects/landmarks_static.dmi'
- icon_state = "ai_spawn"
- primary_ai = FALSE
- latejoin_active = FALSE
-
//Antagonist spawns
/obj/effect/landmark/start/wizard
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index d3e0d354c9f1..2b45a3fbe0c2 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -73,3 +73,56 @@
layer = FLOAT_LAYER
vis_flags = VIS_INHERIT_ID
appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE
+
+/obj/effect/overlay/ai_holder
+ icon = 'goon/icons/obj/96x96.dmi'
+ icon_state = "oldai-01"
+
+ var/mob/living/silicon/ai/ai
+
+ vis_flags = VIS_INHERIT_ID | VIS_INHERIT_LAYER | VIS_INHERIT_PLANE
+ pixel_x = -32
+ pixel_y = -32
+
+/obj/effect/overlay/ai_holder/Destroy(force)
+ ai = null
+ return ..()
+
+/obj/effect/overlay/ai_holder/update_overlays()
+ . = ..()
+ if(ai.stat != CONSCIOUS)
+ return
+
+ . += image(icon, "oldai-[ai.face_state]")
+ . += emissive_appearance(icon, "oldai-[ai.face_state]", alpha = 70)
+
+ . += image(icon, "oldai-faceoverlay")
+ . += emissive_appearance(icon, "oldai-faceoverlay", alpha = 70)
+
+ var/image/light = image(icon, "oldai-light")
+ light.plane = ABOVE_LIGHTING_PLANE
+ . += light
+
+/// Fade away the face. Kind of hacky but I don't care.
+/obj/effect/overlay/ai_holder/proc/death_animation(progress = 1)
+ cut_overlays()
+ if(QDELETED(ai) || progress >= 4) // There's 4 face fade states.
+ return
+
+ if(ai.stat == CONSCIOUS)
+ update_appearance() // Reset to the normal living state.
+ return
+
+ var/list/new_overlays = list()
+ new_overlays += image(icon, "oldai-face_fade0[progress]")
+ new_overlays += emissive_appearance(icon, "oldai-face_fade0[progress]", alpha = 70)
+
+ new_overlays += image(icon, "oldai-faceoverlay")
+ new_overlays += emissive_appearance(icon, "oldai-faceoverlay", alpha = 70)
+
+ var/image/light = image(icon, "oldai-light")
+ light.plane = ABOVE_LIGHTING_PLANE
+ new_overlays += light
+ add_overlay(new_overlays)
+
+ addtimer(CALLBACK(src, PROC_REF(death_animation), progress + 1), 1 SECONDS)
diff --git a/code/game/objects/effects/spawners/random/techstorage.dm b/code/game/objects/effects/spawners/random/techstorage.dm
index ad421c720ced..bb7921974065 100644
--- a/code/game/objects/effects/spawners/random/techstorage.dm
+++ b/code/game/objects/effects/spawners/random/techstorage.dm
@@ -48,7 +48,6 @@
/obj/effect/spawner/random/techstorage/rnd_all
name = "RnD circuit board spawner"
loot = list(
- /obj/item/circuitboard/computer/aifixer,
/obj/item/circuitboard/machine/fabricator/omni,
/obj/item/circuitboard/machine/circuit_imprinter,
/obj/item/circuitboard/computer/teleporter,
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index 7ef59e1d1760..8fd54149c3be 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -355,11 +355,6 @@
//Science
-/obj/item/circuitboard/computer/aifixer
- name = "AI Integrity Restorer (Computer Board)"
- greyscale_colors = CIRCUIT_COLOR_SCIENCE
- build_path = /obj/machinery/computer/aifixer
-
/obj/item/circuitboard/computer/launchpad_console
name = "Launchpad Control Console (Computer Board)"
greyscale_colors = CIRCUIT_COLOR_SCIENCE
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
deleted file mode 100644
index 66cb976738e2..000000000000
--- a/code/game/objects/items/devices/aicard.dm
+++ /dev/null
@@ -1,116 +0,0 @@
-/obj/item/aicard
- name = "intelliCard"
- desc = "A storage device for AIs. Patent pending."
- icon = 'icons/obj/aicards.dmi'
- icon_state = "aicard" // aicard-full
- inhand_icon_state = "electronic"
- worn_icon_state = "electronic"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- w_class = WEIGHT_CLASS_SMALL
- slot_flags = ITEM_SLOT_BELT
- item_flags = NOBLUDGEON
- var/flush = FALSE
- var/mob/living/silicon/ai/AI
-
-/obj/item/aicard/aitater
- name = "intelliTater"
- desc = "A stylish upgrade (?) to the intelliCard."
- icon_state = "aitater"
-
-/obj/item/aicard/aispook
- name = "intelliLantern"
- desc = "A spoOoOoky upgrade to the intelliCard."
- icon_state = "aispook"
-
-/obj/item/aicard/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is trying to upload [user.p_them()]self into [src]! That's not going to work out well!"))
- return BRUTELOSS
-
-/obj/item/aicard/pre_attack(atom/target, mob/living/user, params)
- if(AI) //AI is on the card, implies user wants to upload it.
- var/our_ai = AI
- target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src)
- if(!AI)
- log_combat(user, our_ai, "uploaded", src, "to [target].")
- update_appearance()
- return TRUE
- else //No AI on the card, therefore the user wants to download one.
- target.transfer_ai(AI_TRANS_TO_CARD, user, null, src)
- if(AI)
- log_combat(user, AI, "carded", src)
- update_appearance()
- return TRUE
- return ..()
-
-/obj/item/aicard/update_icon_state()
- if(!AI)
- name = initial(name)
- icon_state = initial(icon_state)
- return ..()
- name = "[initial(name)] - [AI.name]"
- icon_state = "[initial(icon_state)][AI.stat == DEAD ? "-404" : "-full"]"
- AI.cancel_camera()
- return ..()
-
-/obj/item/aicard/update_overlays()
- . = ..()
- if(!AI?.control_disabled)
- return
- . += "[initial(icon_state)]-on"
-
-/obj/item/aicard/ui_state(mob/user)
- return GLOB.hands_state
-
-/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "Intellicard", name)
- ui.open()
-
-/obj/item/aicard/ui_data()
- var/list/data = list()
- if(AI)
- data["name"] = AI.name
- data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
- data["health"] = (AI.health + 100) / 2
- data["wireless"] = !AI.control_disabled //todo disabled->enabled
- data["radio"] = AI.radio_enabled
- data["isDead"] = AI.stat == DEAD
- data["isBraindead"] = AI.client ? FALSE : TRUE
- data["wiping"] = flush
- return data
-
-/obj/item/aicard/ui_act(action,params)
- . = ..()
- if(.)
- return
- switch(action)
- if("wipe")
- if(flush)
- flush = FALSE
- else
- var/confirm = tgui_alert(usr, "Are you sure you want to wipe this card's memory?", name, list("Yes", "No"))
- if(confirm == "Yes" && !..())
- flush = TRUE
- if(AI && AI.loc == src)
- to_chat(AI, span_userdanger("Your core files are being wiped!"))
- while(AI.stat != DEAD && flush)
- AI.adjustOxyLoss(5)
- AI.updatehealth()
- sleep(5)
- flush = FALSE
- . = TRUE
- if("wireless")
- AI.control_disabled = !AI.control_disabled
- if(!AI.control_disabled)
- AI.interaction_range = null
- else
- AI.interaction_range = 0
- to_chat(AI, span_warning("[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!"))
- . = TRUE
- if("radio")
- AI.radio_enabled = !AI.radio_enabled
- to_chat(AI, span_warning("Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!"))
- . = TRUE
- update_appearance()
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index ad57380e82ae..de930ff1df1b 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -1,32 +1,49 @@
/obj/structure/ai_core
- density = TRUE
- anchored = FALSE
name = "\improper AI core"
- icon = 'icons/mob/ai.dmi'
- icon_state = "0"
+ icon = 'goon/icons/obj/96x96.dmi'
+ icon_state = "oldai-01"
desc = "The framework for an artificial intelligence core."
+
+ pixel_x = -32
+ pixel_y = -32
+
max_integrity = 500
- var/state = EMPTY_CORE
+ density = TRUE
+ anchored = TRUE
+
var/datum/ai_laws/laws
var/obj/item/circuitboard/aicore/circuit
var/obj/item/mmi/brain
- var/can_deconstruct = TRUE
/obj/structure/ai_core/Initialize(mapload)
. = ..()
+ SET_TRACKING(__TYPE__)
laws = new
laws.set_laws_config()
+ update_appearance()
+
+/obj/structure/ai_core/Destroy()
+ UNSET_TRACKING(__TYPE__)
+ return ..()
/obj/structure/ai_core/handle_atom_del(atom/A)
if(A == circuit)
circuit = null
- if((state != GLASS_CORE) && (state != AI_READY_CORE))
- state = EMPTY_CORE
- update_appearance()
+ update_appearance()
if(A == brain)
brain = null
return ..()
+/obj/structure/ai_core/update_overlays()
+ . = ..()
+ . += image(icon, "oldai-static")
+ . += emissive_appearance(icon, "oldai-facestatic_neutral", alpha = 70)
+ . += image(icon, "oldai-faceoverlay")
+ . += emissive_appearance(icon, "oldai-faceoverlay", alpha = 70)
+
+ var/image/light = image(icon, "oldai-light")
+ light.plane = ABOVE_LIGHTING_PLANE
+ . += light
/obj/structure/ai_core/Destroy()
QDEL_NULL(circuit)
@@ -38,7 +55,6 @@
name = "inactive AI"
icon_state = "ai-empty"
anchored = TRUE
- state = AI_READY_CORE
/obj/structure/ai_core/deactivated/Initialize(mapload)
. = ..()
@@ -47,13 +63,10 @@
/obj/structure/ai_core/latejoin_inactive
name = "networked AI core"
desc = "This AI core is connected by bluespace transmitters to NTNet, allowing for an AI personality to be downloaded to it on the fly mid-shift."
- can_deconstruct = FALSE
- icon_state = "ai-empty"
+ icon_state = "oldai-01"
anchored = TRUE
- state = AI_READY_CORE
+
var/available = TRUE
- var/safety_checks = TRUE
- var/active = TRUE
/obj/structure/ai_core/latejoin_inactive/Initialize(mapload)
. = ..()
@@ -64,20 +77,13 @@
GLOB.latejoin_ai_cores -= src
return ..()
-/obj/structure/ai_core/latejoin_inactive/examine(mob/user)
- . = ..()
- . += "Its transmitter seems to be [active? "on" : "off"]."
- . += span_notice("You could [active? "deactivate" : "activate"] it with a multitool.")
-
/obj/structure/ai_core/latejoin_inactive/proc/is_available() //If people still manage to use this feature to spawn-kill AI latejoins ahelp them.
if(!available)
return FALSE
- if(!safety_checks)
- return TRUE
- if(!active)
- return FALSE
+
var/turf/T = get_turf(src)
var/area/A = get_area(src)
+
if(!(A.area_flags & BLOBS_ALLOWED))
return FALSE
if(!A.power_equip)
@@ -88,214 +94,9 @@
return FALSE
return TRUE
-/obj/structure/ai_core/latejoin_inactive/attackby(obj/item/P, mob/user, params)
- if(P.tool_behaviour == TOOL_MULTITOOL)
- active = !active
- to_chat(user, span_notice("You [active? "activate" : "deactivate"] \the [src]'s transmitters."))
- return
- return ..()
-
-/obj/structure/ai_core/wrench_act(mob/living/user, obj/item/tool)
- . = ..()
- default_unfasten_wrench(user, tool)
- return ITEM_INTERACT_SUCCESS
-
-/obj/structure/ai_core/attackby(obj/item/P, mob/user, params)
- if(!anchored)
- if(P.tool_behaviour == TOOL_WELDER && can_deconstruct)
- if(state != EMPTY_CORE)
- to_chat(user, span_warning("The core must be empty to deconstruct it!"))
- return
-
- if(!P.tool_start_check(user, amount=0))
- return
-
- to_chat(user, span_notice("You start to deconstruct the frame..."))
- if(P.use_tool(src, user, 20, volume=50) && state == EMPTY_CORE)
- to_chat(user, span_notice("You deconstruct the frame."))
- deconstruct(TRUE)
- return
- else
- switch(state)
- if(EMPTY_CORE)
- if(istype(P, /obj/item/circuitboard/aicore))
- if(!user.transferItemToLoc(P, src))
- return
- playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
- to_chat(user, span_notice("You place the circuit board inside the frame."))
- update_appearance()
- state = CIRCUIT_CORE
- circuit = P
- return
- if(CIRCUIT_CORE)
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You screw the circuit board into place."))
- state = SCREWED_CORE
- update_appearance()
- return
- if(P.tool_behaviour == TOOL_CROWBAR)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the circuit board."))
- state = EMPTY_CORE
- update_appearance()
- circuit.forceMove(loc)
- circuit = null
- return
- if(SCREWED_CORE)
- if(P.tool_behaviour == TOOL_SCREWDRIVER && circuit)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You unfasten the circuit board."))
- state = CIRCUIT_CORE
- update_appearance()
- return
- if(istype(P, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = P
- if(C.get_amount() >= 5)
- playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
- to_chat(user, span_notice("You start to add cables to the frame..."))
- if(do_after(user, src, 2 SECONDS) && state == SCREWED_CORE && C.use(5))
- to_chat(user, span_notice("You add cables to the frame."))
- state = CABLED_CORE
- update_appearance()
- else
- to_chat(user, span_warning("You need five lengths of cable to wire the AI core!"))
- return
- if(CABLED_CORE)
- if(P.tool_behaviour == TOOL_WIRECUTTER)
- if(brain)
- to_chat(user, span_warning("Get that [brain.name] out of there first!"))
- else
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the cables."))
- state = SCREWED_CORE
- update_appearance()
- new /obj/item/stack/cable_coil(drop_location(), 5)
- return
-
- if(istype(P, /obj/item/stack/sheet/rglass))
- var/obj/item/stack/sheet/rglass/G = P
- if(G.get_amount() >= 2)
- playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
- to_chat(user, span_notice("You start to put in the glass panel..."))
- if(do_after(user, src, 2 SECONDS) && state == CABLED_CORE && G.use(2))
- to_chat(user, span_notice("You put in the glass panel."))
- state = GLASS_CORE
- update_appearance()
- else
- to_chat(user, span_warning("You need two sheets of reinforced glass to insert them into the AI core!"))
- return
-
- if(istype(P, /obj/item/ai_module))
- if(brain && brain.laws.id != DEFAULT_AI_LAWID)
- to_chat(user, span_warning("The installed [brain.name] already has set laws!"))
- return
- var/obj/item/ai_module/module = P
- module.install(laws, user)
- return
-
- if(istype(P, /obj/item/mmi) && !brain)
- var/obj/item/mmi/M = P
- if(!M.brain_check(user))
- return
-
- var/mob/living/brain/B = M.brainmob
- if(!CONFIG_GET(flag/allow_ai) || (is_banned_from(B.ckey, JOB_AI) && !QDELETED(src) && !QDELETED(user) && !QDELETED(M) && !QDELETED(user) && Adjacent(user)))
- if(!QDELETED(M))
- to_chat(user, span_warning("This [M.name] does not seem to fit!"))
- return
- if(!user.transferItemToLoc(M,src))
- return
-
- brain = M
- to_chat(user, span_notice("You add [M.name] to the frame."))
- update_appearance()
- return
-
- if(P.tool_behaviour == TOOL_CROWBAR && brain)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the brain."))
- brain.forceMove(loc)
- brain = null
- update_appearance()
- return
-
- if(GLASS_CORE)
- if(P.tool_behaviour == TOOL_CROWBAR)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You remove the glass panel."))
- state = CABLED_CORE
- update_appearance()
- new /obj/item/stack/sheet/rglass(loc, 2)
- return
-
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You connect the monitor."))
- if(brain)
- var/mob/living/brain/B = brain.brainmob
- B.mind?.remove_antags_for_borging()
-
- var/mob/living/silicon/ai/A = null
-
- if (brain.overrides_aicore_laws)
- A = new /mob/living/silicon/ai(loc, brain.laws, B)
- brain.laws = null //Brain's law datum is being donated, so we need the brain to let it go or the GC will eat it
- else
- A = new /mob/living/silicon/ai(loc, laws, B)
- laws = null //we're giving the new AI this datum, so let's not delete it when we qdel(src) 5 lines from now
-
- if(brain.force_replace_ai_name)
- A.fully_replace_character_name(A.name, brain.replacement_ai_name())
- SSblackbox.record_feedback("amount", "ais_created", 1)
- deadchat_broadcast(" has been brought online at [get_area_name(A, TRUE)].", span_name("[A]"), follow_target=A, message_type=DEADCHAT_ANNOUNCEMENT)
- qdel(src)
- else
- state = AI_READY_CORE
- update_appearance()
- return
-
- if(AI_READY_CORE)
- if(istype(P, /obj/item/aicard))
- return //handled by /obj/structure/ai_core/transfer_ai()
-
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
- P.play_tool_sound(src)
- to_chat(user, span_notice("You disconnect the monitor."))
- state = GLASS_CORE
- update_appearance()
- return
- return ..()
-
-/obj/structure/ai_core/update_icon_state()
- switch(state)
- if(EMPTY_CORE)
- icon_state = "0"
- if(CIRCUIT_CORE)
- icon_state = "1"
- if(SCREWED_CORE)
- icon_state = "2"
- if(CABLED_CORE)
- if(brain)
- icon_state = "3b"
- else
- icon_state = "3"
- if(GLASS_CORE)
- icon_state = "4"
- if(AI_READY_CORE)
- icon_state = "ai-empty"
- return ..()
-
-/obj/structure/ai_core/deconstruct(disassembled = TRUE)
- if(state == GLASS_CORE)
- new /obj/item/stack/sheet/rglass(loc, 2)
- if(state >= CABLED_CORE)
- new /obj/item/stack/cable_coil(loc, 5)
- if(circuit)
- circuit.forceMove(loc)
- circuit = null
- new /obj/item/stack/sheet/plasteel(loc, 4)
- qdel(src)
+/obj/item/circuitboard/aicore
+ name = "AI core (AI Core Board)" //Well, duh, but best to be consistent
+ var/battery = 200 //backup battery for when the AI loses power. Copied to/from AI mobs when carding, and placed here to avoid recharge via deconning the core
/*
This is a good place for AI-related object verbs so I'm sticking it here.
@@ -305,29 +106,18 @@ That prevents a few funky behaviors.
//The type of interaction, the player performing the operation, the AI itself, and the card object, if any.
-/atom/proc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
- if(istype(card))
- if(card.flush)
- to_chat(user, span_alert("ERROR: AI flush is in progress, cannot execute transfer protocol."))
- return FALSE
+/atom/proc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI)
return TRUE
-/obj/structure/ai_core/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
- if(state != AI_READY_CORE || !..())
- return
- //Transferring a carded AI to a core.
- if(interaction == AI_TRANS_FROM_CARD)
- AI.control_disabled = FALSE
- AI.radio_enabled = TRUE
- AI.forceMove(loc) // to replace the terminal.
- to_chat(AI, span_notice("You have been uploaded to a stationary terminal. Remote device connection restored."))
- to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
- card.AI = null
- AI.battery = circuit.battery
- qdel(src)
- else //If for some reason you use an empty card on an empty AI terminal.
- to_chat(user, span_alert("There is no AI loaded on this terminal."))
+/obj/structure/ai_core/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI)
+ . = ..()
+ if(!.)
+ return FALSE
-/obj/item/circuitboard/aicore
- name = "AI core (AI Core Board)" //Well, duh, but best to be consistent
- var/battery = 200 //backup battery for when the AI loses power. Copied to/from AI mobs when carding, and placed here to avoid recharge via deconning the core
+ AI.control_disabled = FALSE
+ AI.radio_enabled = TRUE
+ AI.forceMove(loc) // to replace the terminal.
+ to_chat(AI, span_notice("You have been uploaded to a stationary terminal. Remote device connection restored."))
+ to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
+ AI.battery = circuit.battery
+ qdel(src)
diff --git a/code/game/objects/structures/ai_fluff.dm b/code/game/objects/structures/ai_fluff.dm
new file mode 100644
index 000000000000..5b99d50c18e1
--- /dev/null
+++ b/code/game/objects/structures/ai_fluff.dm
@@ -0,0 +1,17 @@
+#warn name desc
+/obj/structure/ai_fluff
+ icon = 'goon/icons/obj/96x96.dmi'
+ icon_state = "oldai-t2"
+
+ layer = HIGH_OBJ_LAYER
+
+ resistance_flags = INDESTRUCTIBLE
+ density = TRUE
+ anchored = TRUE
+
+ pixel_x = -32
+ pixel_y = -32
+
+/obj/structure/ai_fluff/brad
+ icon = 'goon/icons/obj/96x96.dmi'
+ icon_state = "oldai-t1"
diff --git a/code/modules/admin/verbs/ai_triumvirate.dm b/code/modules/admin/verbs/ai_triumvirate.dm
deleted file mode 100644
index ca7ebfe7cc43..000000000000
--- a/code/modules/admin/verbs/ai_triumvirate.dm
+++ /dev/null
@@ -1,48 +0,0 @@
-
-///global reference to the current theme, if there is one.
-GLOBAL_DATUM(triple_ai_controller, /datum/triple_ai_controller)
-
-/**
- * The triple ai controller handles the admin triple AI mode, if enabled.
- * It is first created when "Toggle AI Triumvirate" triggers it, and it can be referenced from GLOB.triple_ai_controller
- * After it handles roundstart business, it cleans itself up.
- */
-/datum/triple_ai_controller
-
-/datum/triple_ai_controller/New()
- . = ..()
- RegisterSignal(SSjob, COMSIG_OCCUPATIONS_DIVIDED, PROC_REF(on_occupations_divided))
-
-/datum/triple_ai_controller/proc/on_occupations_divided(datum/source)
- SIGNAL_HANDLER
-
- for(var/datum/job/ai/ai_datum in SSjob.joinable_occupations)
- ai_datum.spawn_positions = 3
- for(var/obj/effect/landmark/start/ai/secondary/secondary_ai_spawn in GLOB.start_landmarks_list)
- secondary_ai_spawn.latejoin_active = TRUE
- qdel(src)
-
-/datum/triple_ai_controller/Destroy(force)
- UnregisterSignal(SSjob, COMSIG_OCCUPATIONS_DIVIDED)
- GLOB.triple_ai_controller = null
- . = ..()
-
-/client/proc/triple_ai()
- set category = "Admin.Events"
- set name = "Toggle AI Triumvirate"
-
- if(SSticker.current_state > GAME_STATE_PREGAME)
- to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.", confidential = TRUE)
- return
-
- var/datum/job/job = SSjob.GetJobType(/datum/job/ai)
- if(!job)
- to_chat(usr, "Unable to locate the AI job", confidential = TRUE)
- CRASH("triple_ai() called, no /datum/job/ai to be found.")
-
- if(!GLOB.triple_ai_controller)
- GLOB.triple_ai_controller = new()
- else
- QDEL_NULL(GLOB.triple_ai_controller)
- to_chat(usr, "There will[GLOB.triple_ai_controller ? "" : "not"] be an AI Triumvirate at round start.")
- message_admins(span_adminnotice("[key_name_admin(usr)] has toggled [GLOB.triple_ai_controller ? "on" : "off"] triple AIs at round start."))
diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm
index f8e5e79526ed..974c34caca0d 100644
--- a/code/modules/admin/verbs/secrets.dm
+++ b/code/modules/admin/verbs/secrets.dm
@@ -255,11 +255,6 @@ GLOBAL_DATUM(everyone_a_traitor, /datum/everyone_is_a_traitor_controller)
return
holder.anon_names()
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Anonymous Names"))
- if("tripleAI")
- if(!is_funmin)
- return
- holder.triple_ai()
- SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Triple AI"))
if("onlyone")
if(!is_funmin)
return
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index bb6c03bc78d4..906359064814 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -531,7 +531,7 @@ GLOBAL_LIST_INIT(job_display_order, list(
fully_replace_character_name(real_name, GLOB.current_anonymous_theme.anonymous_ai_name(TRUE))
return
apply_pref_name(/datum/preference/name/ai, player_client) // This proc already checks if the player is appearance banned.
- set_core_display_icon(null, player_client)
+ // set_core_display_icon(null, player_client)
/mob/living/silicon/robot/apply_prefs_job(client/player_client, datum/job/job)
diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm
index 76711faaba4f..3b3f13e87605 100644
--- a/code/modules/jobs/job_types/ai.dm
+++ b/code/modules/jobs/job_types/ai.dm
@@ -2,7 +2,6 @@
title = JOB_AI
description = "Assist the crew, follow your laws, coordinate your cyborgs."
radio_help_message = "Prefix your message with :b to speak with cyborgs and other AIs."
- auto_deadmin_role_flags = DEADMIN_POSITION_SILICON
faction = FACTION_STATION
total_positions = 1
@@ -35,9 +34,12 @@
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if(!R.connected_ai)
R.TryConnectToAI()
+
var/mob/living/silicon/ai/ai_spawn = spawned
ai_spawn.log_current_laws()
+ // There's no real reason for this to actually be in datacore on ready, its just an arbitrary delay and it's in sync with AAS messages.
+ SSdatacore.OnReady(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(priority_announce), "Integrated Intelligence Unit designated \"[ai_spawn.real_name]\" boot sequence successful.", ))
/datum/job/ai/get_roundstart_spawn_point_fixed()
return get_latejoin_spawn_point()
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 6d50df3cff91..e3649d8dda78 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -29,7 +29,7 @@ GLOBAL_VAR_INIT(fresh_ghost_adjectives, __fresh_ghost_adjectives())
shift_to_open_context_menu = FALSE
simulated = FALSE
- var/can_reenter_corpse
+ var/can_reenter_corpse = TRUE
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
@@ -65,7 +65,7 @@ GLOBAL_VAR_INIT(fresh_ghost_adjectives, __fresh_ghost_adjectives())
var/datum/spawners_menu/spawners_menu
var/datum/minigames_menu/minigames_menu
-/mob/dead/observer/Initialize(mapload, started_as_observer = FALSE, admin_ghost = FALSE)
+/mob/dead/observer/Initialize(mapload, started_as_observer = FALSE, admin_ghost = FALSE, can_reenter_corpse = TRUE)
src.started_as_observer = started_as_observer
src.admin_ghost = admin_ghost
@@ -297,7 +297,7 @@ Works together with spawning an observer, noted above.
ethereal_heart.stop_crystalization_process(crystal_fella) //stops the crystallization process
stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now
- var/mob/dead/observer/ghost = new(src, FALSE, admin_ghost) // Transfer safety to observer spawning proc.
+ var/mob/dead/observer/ghost = new(src, FALSE, admin_ghost, can_reenter_corpse) // Transfer safety to observer spawning proc.
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
ghost.verb_say = verb_say
@@ -786,13 +786,29 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
gas_scan = TRUE
/mob/dead/observer/proc/set_ghost_appearance(mob/living/to_copy)
- var/mutable_appearance/appearance = to_copy?.mind?.body_appearance || to_copy
+ cut_viscontents()
+ overlays.Cut()
+ if(isAI(to_copy)) // Yay I love hacks
+ icon = null
+ icon_state = null
+ alpha = 127
+ var/obj/effect/overlay/holder = new
+ holder.vis_flags = VIS_INHERIT_ID | VIS_INHERIT_LAYER | VIS_INHERIT_PLANE
+ holder.icon = /obj/effect/overlay/ai_holder::icon
+ holder.icon_state = /obj/effect/overlay/ai_holder::icon_state
+ holder.pixel_x = -32
+ holder.pixel_y = -32
+ holder.overlays += image(/obj/effect/overlay/ai_holder::icon, "oldai-static")
+ holder.overlays += image(/obj/effect/overlay/ai_holder::icon, "oldai-faceoverlay")
+ add_viscontents(holder)
+ return
+
+ var/mutable_appearance/appearance = to_copy?.mind?.body_appearance || to_copy
if(!appearance || !appearance.icon)
icon = initial(icon)
icon_state = "ghost"
alpha = 255
- overlays.Cut()
else
icon = appearance.icon
icon_state = appearance.icon_state
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index fd73bf2f0cd3..a0d06286d9e5 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -230,11 +230,11 @@
src.stamina.adjust(-stamina)
if(jitter && (status_flags & CANSTUN) && !HAS_TRAIT(src, TRAIT_STUNIMMUNE))
- adjust_timed_status_effect(jitter, /datum/status_effect/jitter)
+ adjust_timed_status_effect(jitter, /datum/status_effect/jitter, jitter)
if(slur)
- adjust_timed_status_effect(slur, /datum/status_effect/speech/slurring/drunk)
+ adjust_timed_status_effect(slur, /datum/status_effect/speech/slurring/drunk, slur)
if(stutter)
- adjust_timed_status_effect(stutter, /datum/status_effect/speech/stutter)
+ adjust_timed_status_effect(stutter, /datum/status_effect/speech/stutter, stutter)
return TRUE
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index ca009067caf2..994cd1452f2f 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -106,7 +106,7 @@
key_third_person = "deathgasps"
message = "seizes up and falls limp, their eyes dead and lifeless..."
message_robot = "gives one shrill beep before falling lifeless."
- message_AI = "screeches, its screen flickering as its systems slowly halt."
+ message_AI = "emits a loud beep as its hum fades away."
message_alien = "lets out a waning guttural screech, and collapses onto the floor..."
message_larva = "lets out a sickly hiss of air and falls limply to the floor..."
message_monkey = "lets out a faint chimper as it collapses and stops moving..."
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 9ffce3f80367..d908f21c98d8 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -11,25 +11,31 @@
subject.attack_ai(M)
return is_in_use
-
+#warn desc
/mob/living/silicon/ai
name = "AI"
real_name = "AI"
icon = 'icons/mob/ai.dmi'
- icon_state = "ai"
+ icon_state = ""
+
move_resist = MOVE_FORCE_OVERPOWERING
density = TRUE
- status_flags = CANSTUN|CANPUSH
+
+ status_flags = CANSTUN
combat_mode = TRUE //so we always get pushed instead of trying to swap
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS
+
see_in_dark = NIGHTVISION_FOV_RANGE
hud_type = /datum/hud/ai
+
med_hud = DATA_HUD_MEDICAL_BASIC
sec_hud = DATA_HUD_SECURITY_BASIC
d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED
- mob_size = MOB_SIZE_LARGE
+ mob_size = MOB_SIZE_HUGE
+
radio = /obj/item/radio/headset/silicon/ai
can_buckle_to = FALSE
+
var/battery = 200 //emergency power if the AI's APC is off
var/list/network = list("ss13")
var/obj/machinery/camera/current
@@ -115,6 +121,11 @@
COOLDOWN_DECLARE(command_report_cd)
/// An image to add to client.images so the AI player can see their own eye sprite.
var/image/sense_of_self
+ /// The vis contents holder for our overlays, for offsetting without breaking things like runechat.
+ var/obj/effect/overlay/ai_holder/vis_holder
+
+ /// The icon state for the face.
+ var/face_state = "static"
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
. = ..()
@@ -156,7 +167,11 @@
if(client)
INVOKE_ASYNC(src, PROC_REF(apply_pref_name), /datum/preference/name/ai, client)
- INVOKE_ASYNC(src, PROC_REF(set_core_display_icon))
+ vis_holder = new
+ vis_holder.ai = src
+ add_viscontents(vis_holder)
+
+ //INVOKE_ASYNC(src, PROC_REF(set_core_display_icon))
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"default"))
@@ -197,6 +212,8 @@
RegisterSignal(alert_control.listener, COMSIG_ALARM_TRIGGERED, PROC_REF(alarm_triggered))
RegisterSignal(alert_control.listener, COMSIG_ALARM_CLEARED, PROC_REF(alarm_cleared))
+ update_appearance()
+
/mob/living/silicon/ai/key_down(_key, client/user)
if(findtext(_key, "numpad")) //if it's a numpad number, we can convert it to just the number
_key = _key[7] //strings, lists, same thing really
@@ -230,6 +247,7 @@
QDEL_NULL(robot_control)
QDEL_NULL(aiMulti)
QDEL_NULL(alert_control)
+ QDEL_NULL(vis_holder)
malfhack = null
current = null
bot_ref = null
@@ -278,6 +296,10 @@
/mob/living/silicon/ai/broadcast_examine(atom/examined)
return
+/mob/living/silicon/ai/update_appearance(updates)
+ . = ..()
+ vis_holder.update_appearance(updates)
+
/// Returns the nearest lit camera to a mob, as long as the camera can see that mob.
/mob/living/silicon/ai/proc/get_nearest_lit_camera_to_mob(mob/M)
var/smallest_dist = INFINITY
@@ -296,41 +318,37 @@
/mob/living/silicon/ai/ignite_mob()
return FALSE
-/mob/living/silicon/ai/proc/set_core_display_icon(input, client/C)
- if(client && !C)
- C = client
- if(!input && !C?.prefs?.read_preference(/datum/preference/choiced/ai_core_display))
- icon_state = initial(icon_state)
- else
- var/preferred_icon = input ? input : C.prefs.read_preference(/datum/preference/choiced/ai_core_display)
- icon_state = resolve_ai_icon(preferred_icon)
-
-/mob/living/silicon/ai/verb/pick_icon()
- set category = "AI Commands"
- set name = "Set AI Core Display"
- if(incapacitated())
- return
- icon = initial(icon)
- icon_state = "ai"
- cut_overlays()
- var/list/iconstates = GLOB.ai_core_display_screens
- for(var/option in iconstates)
- if(option == "Random")
- iconstates[option] = image(icon = src.icon, icon_state = "ai-random")
- continue
- if(option == "Portrait")
- iconstates[option] = image(icon = src.icon, icon_state = "ai-portrait")
- continue
- iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option))
-
- view_core()
- var/ai_core_icon = show_radial_menu(src, src , iconstates, radius = 42)
-
- if(!ai_core_icon || incapacitated())
- return
-
- display_icon_override = ai_core_icon
- set_core_display_icon(ai_core_icon)
+/// Sets the face_state and updates it.
+/mob/living/silicon/ai/proc/set_face_state(new_state)
+ face_state = new_state
+ update_appearance(UPDATE_OVERLAYS)
+
+// /mob/living/silicon/ai/verb/pick_icon()
+// set category = "AI Commands"
+// set name = "Set AI Core Display"
+// if(incapacitated())
+// return
+// icon = initial(icon)
+// icon_state = "ai"
+// cut_overlays()
+// var/list/iconstates = GLOB.ai_core_display_screens
+// for(var/option in iconstates)
+// if(option == "Random")
+// iconstates[option] = image(icon = src.icon, icon_state = "ai-random")
+// continue
+// if(option == "Portrait")
+// iconstates[option] = image(icon = src.icon, icon_state = "ai-portrait")
+// continue
+// iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option))
+
+// view_core()
+// var/ai_core_icon = show_radial_menu(src, src , iconstates, radius = 42)
+
+// if(!ai_core_icon || incapacitated())
+// return
+
+// display_icon_override = ai_core_icon
+// set_core_display_icon(ai_core_icon)
/mob/living/silicon/ai/get_status_tab_items()
. = ..()
@@ -819,29 +837,6 @@
return
set_autosay()
-/mob/living/silicon/ai/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
- if(!..())
- return
- if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card.
- if(!can_be_carded)
- to_chat(user, span_boldwarning("Transfer failed."))
- return
- disconnect_shell() //If the AI is controlling a borg, force the player back to core!
- if(!mind)
- to_chat(user, span_warning("No intelligence patterns detected."))
- return
- ShutOffDoomsdayDevice()
- var/obj/structure/ai_core/new_core = new /obj/structure/ai_core/deactivated(loc)//Spawns a deactivated terminal at AI location.
- new_core.circuit.battery = battery
- ai_restore_power()//So the AI initially has power.
- control_disabled = TRUE //Can't control things remotely if you're stuck in a card!
- interaction_range = 0
- radio_enabled = FALSE //No talking on the built-in radio for you either!
- forceMove(card)
- card.AI = src
- to_chat(src, "You have been downloaded to a mobile storage device. Remote device connection severed.")
- to_chat(user, "[span_boldnotice("Transfer successful")]: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
-
/mob/living/silicon/ai/canUseTopic(atom/movable/target, flags)
if(control_disabled)
to_chat(src, span_warning("You can't do that right now!"))
@@ -962,7 +957,7 @@
/mob/living/silicon/ai/revive(full_heal = FALSE, admin_revive = FALSE)
. = ..()
if(.) //successfully ressuscitated from death
- set_core_display_icon(display_icon_override)
+ //set_core_display_icon(display_icon_override)
set_eyeobj_visible(TRUE)
/mob/living/silicon/ai/proc/malfhacked(obj/machinery/power/apc/apc)
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index 172ab7faa158..babc3caa9aba 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -9,21 +9,12 @@
. = ..()
SSblackbox.record_feedback("amount", "ai_deaths", 1)
- cut_overlays() //remove portraits
- var/old_icon = icon_state
- if("[icon_state]_dead" in icon_states(icon))
- icon_state = "[icon_state]_dead"
- else
- icon_state = "ai_dead"
- if("[old_icon]_death_transition" in icon_states(icon))
- z_flick("[old_icon]_death_transition", src)
- cameraFollow = null
+ update_appearance()
+ if(!gibbed && !QDELING(src))
+ vis_holder.death_animation()
- set_anchored(FALSE) //unbolt floorbolts
- status_flags |= CANPUSH //we want it to be pushable when unanchored on death
- REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, AI_ANCHOR_TRAIT) //removes the anchor trait, because its not anchored anymore
- move_resist = MOVE_FORCE_NORMAL
+ cameraFollow = null
if(eyeobj)
eyeobj.setLoc(get_turf(src))
@@ -38,13 +29,6 @@
if(explosive)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(explosion), loc, 3, 6, 12, null, 15), 1 SECONDS)
- if(istype(loc, /obj/item/aicard/aitater))
- loc.icon_state = "aitater-404"
- else if(istype(loc, /obj/item/aicard/aispook))
- loc.icon_state = "aispook-404"
- else if(istype(loc, /obj/item/aicard))
- loc.icon_state = "aicard-404"
-
/mob/living/silicon/ai/proc/ShutOffDoomsdayDevice()
if(nuking)
nuking = FALSE
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index 8b4e91a5f7aa..bfe6fc4ac0ac 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -201,8 +201,10 @@
/mob/living/silicon/ai/proc/set_eyeobj_visible(state = TRUE)
if(!eyeobj)
return
+
eyeobj.mouse_opacity = state ? MOUSE_OPACITY_ICON : initial(eyeobj.mouse_opacity)
eyeobj.invisibility = state ? INVISIBILITY_OBSERVER : initial(eyeobj.invisibility)
+ sense_of_self?.invisibility = state ? INVISIBILITY_OBSERVER : INVISIBLITY_VISIBLE
/mob/living/silicon/ai/verb/toggle_acceleration()
set category = "AI Commands"
diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm
index f36dc84c08bf..f8a9be4ba1d3 100644
--- a/code/modules/mob/living/silicon/ai/login.dm
+++ b/code/modules/mob/living/silicon/ai/login.dm
@@ -2,10 +2,15 @@
. = ..()
if(!. || !client)
return FALSE
+
if(stat != DEAD)
if(lacks_power() && apc_override) //Placing this in Login() in case the AI doesn't have this link for whatever reason.
to_chat(usr, "[span_warning("Main power is unavailable, backup power in use. Diagnostics scan complete.")] Local APC ready for connection.")
+
set_eyeobj_visible(TRUE)
+
if(multicam_on)
end_multicam()
+
view_core()
+ set_face_state("face_neutral")
diff --git a/code/modules/mob/living/silicon/ai/logout.dm b/code/modules/mob/living/silicon/ai/logout.dm
index a027871716ef..c0c8f30d2c97 100644
--- a/code/modules/mob/living/silicon/ai/logout.dm
+++ b/code/modules/mob/living/silicon/ai/logout.dm
@@ -2,3 +2,4 @@
..()
set_eyeobj_visible(FALSE)
view_core()
+ set_face_state("static")
diff --git a/code/modules/mod/mod_ai.dm b/code/modules/mod/mod_ai.dm
index a5fd904093a3..ab5a006357a1 100644
--- a/code/modules/mod/mod_ai.dm
+++ b/code/modules/mod/mod_ai.dm
@@ -1,59 +1,3 @@
-/obj/item/mod/control/transfer_ai(interaction, mob/user, mob/living/silicon/ai/intAI, obj/item/aicard/card)
- . = ..()
- if(!.)
- return
- if(!open) //mod must be open
- balloon_alert(user, "suit must be open to transfer!")
- return
- switch(interaction)
- if(AI_TRANS_TO_CARD)
- if(!ai)
- balloon_alert(user, "no AI in suit!")
- return
- balloon_alert(user, "transferring to card...")
- if(!do_after(user, src, 5 SECONDS))
- balloon_alert(user, "interrupted!")
- return
- if(!ai)
- return
- intAI = ai
- intAI.ai_restore_power()//So the AI initially has power.
- intAI.control_disabled = TRUE
- intAI.radio_enabled = FALSE
- intAI.disconnect_shell()
- intAI.forceMove(card)
- card.AI = intAI
- for(var/datum/action/action as anything in actions)
- action.Remove(intAI)
- intAI.controlled_equipment = null
- intAI.remote_control = null
- balloon_alert(intAI, "transferred to a card")
- balloon_alert(user, "AI transferred to card")
- ai = null
-
- if(AI_TRANS_FROM_CARD) //Using an AI card to upload to the suit.
- intAI = card.AI
- if(!intAI)
- balloon_alert(user, "no AI in card!")
- return
- if(ai)
- balloon_alert(user, "already has AI!")
- return
- if(intAI.deployed_shell) //Recall AI if shelled so it can be checked for a client
- intAI.disconnect_shell()
- if(intAI.stat || !intAI.client)
- balloon_alert(user, "AI unresponsive!")
- return
- balloon_alert(user, "transferring to suit...")
- if(!do_after(user, src, 5 SECONDS))
- balloon_alert(user, "interrupted!")
- return
- if(ai)
- return
- balloon_alert(user, "AI transferred to suit")
- ai_enter_mod(intAI)
- card.AI = null
-
/obj/item/mod/control/proc/ai_enter_mod(mob/living/silicon/ai/new_ai)
new_ai.control_disabled = FALSE
new_ai.radio_enabled = TRUE
@@ -101,49 +45,3 @@
if(!wearer)
return
REMOVE_TRAIT(wearer, TRAIT_FORCED_STANDING, MOD_TRAIT)
-
-/obj/item/mod/ai_minicard
- name = "AI mini-card"
- desc = "A small card designed to eject dead AIs. You could use an intellicard to recover it."
- icon = 'icons/obj/aicards.dmi'
- icon_state = "minicard"
- var/datum/weakref/stored_ai
-
-/obj/item/mod/ai_minicard/Initialize(mapload, mob/living/silicon/ai/ai)
- . = ..()
- if(!ai)
- return
- ai.apply_damage(150, BURN)
- INVOKE_ASYNC(ai, TYPE_PROC_REF(/mob/living/silicon/ai, death))
- ai.forceMove(src)
- stored_ai = WEAKREF(ai)
- icon_state = "minicard-filled"
-
-/obj/item/mod/ai_minicard/Destroy()
- QDEL_NULL(stored_ai)
- return ..()
-
-/obj/item/mod/ai_minicard/examine(mob/user)
- . = ..()
- . += span_notice("You see [stored_ai.resolve() || "no AI"] stored inside.")
-
-/obj/item/mod/ai_minicard/transfer_ai(interaction, mob/user, mob/living/silicon/ai/intAI, obj/item/aicard/card)
- . = ..()
- if(!.)
- return
- if(interaction != AI_TRANS_TO_CARD)
- return
- var/mob/living/silicon/ai/ai = stored_ai.resolve()
- if(!ai)
- balloon_alert(user, "no AI!")
- return
- balloon_alert(user, "transferring to card...")
- if(!do_after(user, src, 5 SECONDS) || !ai)
- balloon_alert(user, "interrupted!")
- return
- icon_state = "minicard"
- ai.forceMove(card)
- card.AI = ai
- ai.notify_ghost_revival("You have been recovered from the wreckage!", source = card)
- balloon_alert(user, "AI transferred to card")
- stored_ai = null
diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm
index 24c2666d9d38..bee5d51c2310 100644
--- a/code/modules/mod/mod_control.dm
+++ b/code/modules/mod/mod_control.dm
@@ -150,7 +150,17 @@ TYPEINFO_DEF(/obj/item/mod/control)
for(var/datum/action/action as anything in actions)
if(action.owner == ai)
action.Remove(ai)
- new /obj/item/mod/ai_minicard(drop_location(), ai)
+
+ var/found_core = FALSE
+ for(var/obj/structure/ai_core/core as anything in INSTANCES_OF(/obj/structure/ai_core))
+ if(core.transfer_ai(ai))
+ found_core = TRUE
+ break
+
+ if(!found_core)
+ qdel(ai)
+ ai = null
+
return ..()
/obj/item/mod/control/examine(mob/user)
diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm
index baefc003545c..2d0628e16618 100644
--- a/code/modules/modular_computers/computers/machinery/console_presets.dm
+++ b/code/modules/modular_computers/computers/machinery/console_presets.dm
@@ -49,7 +49,6 @@
var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
hard_drive.store_file(new/datum/computer_file/program/chatclient())
- hard_drive.store_file(new/datum/computer_file/program/aidiag())
hard_drive.store_file(new/datum/computer_file/program/robocontrol())
// ===== COMPANY CONSOLE =====
diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm
deleted file mode 100644
index fdf0ccd2f7f9..000000000000
--- a/code/modules/modular_computers/file_system/programs/airestorer.dm
+++ /dev/null
@@ -1,127 +0,0 @@
-/datum/computer_file/program/aidiag
- filename = "aidiag"
- filedesc = "NT FRK"
- category = PROGRAM_CATEGORY_SCI
- program_icon_state = "generic"
- extended_desc = "Firmware Restoration Kit, capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot."
- size = 12
- requires_ntnet = FALSE
- usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
- transfer_access = list(ACCESS_MANAGEMENT)
- available_on_ntnet = TRUE
- tgui_id = "NtosAiRestorer"
- program_icon = "laptop-code"
- /// Variable dictating if we are in the process of restoring the AI in the inserted intellicard
- var/restoring = FALSE
-
-/datum/computer_file/program/aidiag/proc/get_ai(cardcheck)
-
- var/obj/item/computer_hardware/ai_slot/ai_slot
-
- if(computer)
- ai_slot = computer.all_components[MC_AI]
-
- if(computer && ai_slot?.check_functionality())
- if(cardcheck == 1)
- return ai_slot
- if(ai_slot.is_enabled() && ai_slot.stored_card)
- if(cardcheck == 2)
- return ai_slot.stored_card
- if(ai_slot.stored_card.AI)
- return ai_slot.stored_card.AI
-
- return
-
-/datum/computer_file/program/aidiag/ui_act(action, params)
- . = ..()
- if(.)
- return
-
- var/mob/living/silicon/ai/A = get_ai()
- if(!A)
- restoring = FALSE
-
- switch(action)
- if("PRG_beginReconstruction")
- if(A && A.health < 100)
- restoring = TRUE
- A.notify_ghost_revival("Your core files are being restored!", source = computer)
- return TRUE
- if("PRG_eject")
- if(computer.all_components[MC_AI])
- var/obj/item/computer_hardware/ai_slot/ai_slot = computer.all_components[MC_AI]
- if(ai_slot?.stored_card)
- ai_slot.try_eject(usr)
- return TRUE
-
-/datum/computer_file/program/aidiag/process_tick()
- . = ..()
- if(!restoring) //Put the check here so we don't check for an ai all the time
- return
- var/obj/item/aicard/cardhold = get_ai(2)
-
- var/obj/item/computer_hardware/ai_slot/ai_slot = get_ai(1)
-
-
- var/mob/living/silicon/ai/A = get_ai()
- if(!A || !cardhold)
- restoring = FALSE // If the AI was removed, stop the restoration sequence.
- if(ai_slot)
- ai_slot.locked = FALSE
- return
-
- if(cardhold.flush)
- ai_slot.locked = FALSE
- restoring = FALSE
- return
- ai_slot.locked = TRUE
- A.adjustOxyLoss(-5, FALSE)
- A.adjustFireLoss(-5, FALSE)
- A.adjustBruteLoss(-5, FALSE)
-
- // Please don't forget to update health, otherwise the below if statements will probably always fail.
- A.updatehealth()
-
- if(A.health >= 0 && A.stat == DEAD)
- A.revive(full_heal = FALSE, admin_revive = FALSE)
- cardhold.update_appearance()
-
- // Finished restoring
- if(A.health >= 100)
- ai_slot.locked = FALSE
- restoring = FALSE
-
- return TRUE
-
-
-/datum/computer_file/program/aidiag/ui_data(mob/user)
- var/list/data = get_header_data()
- var/mob/living/silicon/ai/AI = get_ai()
-
- var/obj/item/aicard/aicard = get_ai(2)
-
- data["ejectable"] = TRUE
- data["AI_present"] = FALSE
- data["error"] = null
- if(!aicard)
- data["error"] = "Please insert an intelliCard."
- else
- if(!AI)
- data["error"] = "No AI located"
- else
- var/obj/item/aicard/cardhold = AI.loc
- if(cardhold.flush)
- data["error"] = "Flush in progress"
- else
- data["AI_present"] = TRUE
- data["name"] = AI.name
- data["restoring"] = restoring
- data["health"] = (AI.health + 100) / 2
- data["isDead"] = AI.stat == DEAD
- data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
-
- return data
-
-/datum/computer_file/program/aidiag/kill_program(forced)
- restoring = FALSE
- return ..()
diff --git a/code/modules/power/apc/apc_malf.dm b/code/modules/power/apc/apc_malf.dm
index 02bff5905808..7ddbc4ad1b70 100644
--- a/code/modules/power/apc/apc_malf.dm
+++ b/code/modules/power/apc/apc_malf.dm
@@ -76,56 +76,3 @@
disk_pinpointers.switch_mode_to(TRACK_NUKE_DISK)
disk_pinpointers.alert = FALSE
-/obj/machinery/power/apc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
- if(card.AI)
- to_chat(user, span_warning("[card] is already occupied!"))
- return
- if(!occupier)
- to_chat(user, span_warning("There's nothing in [src] to transfer!"))
- return
- if(!occupier.mind || !occupier.client)
- to_chat(user, span_warning("[occupier] is either inactive or destroyed!"))
- return
- if(!occupier.parent.stat)
- to_chat(user, span_warning("[occupier] is refusing all attempts at transfer!") )
- return
- if(transfer_in_progress)
- to_chat(user, span_warning("There's already a transfer in progress!"))
- return
- if(interaction != AI_TRANS_TO_CARD || occupier.stat)
- return
- var/turf/user_turf = get_turf(user)
- if(!user_turf)
- return
- transfer_in_progress = TRUE
- user.visible_message(span_notice("[user] slots [card] into [src]..."), span_notice("Transfer process initiated. Sending request for AI approval..."))
- playsound(src, 'sound/machines/click.ogg', 50, TRUE)
- SEND_SOUND(occupier, sound('sound/misc/notice2.ogg')) //To alert the AI that someone's trying to card them if they're tabbed out
- if(tgui_alert(occupier, "[user] is attempting to transfer you to \a [card.name]. Do you consent to this?", "APC Transfer", list("Yes - Transfer Me", "No - Keep Me Here")) == "No - Keep Me Here")
- to_chat(user, span_danger("AI denied transfer request. Process terminated."))
- playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
- transfer_in_progress = FALSE
- return
- if(user.loc != user_turf)
- to_chat(user, span_danger("Location changed. Process terminated."))
- to_chat(occupier, span_warning("[user] moved away! Transfer canceled."))
- transfer_in_progress = FALSE
- return
- to_chat(user, span_notice("AI accepted request. Transferring stored intelligence to [card]..."))
- to_chat(occupier, span_notice("Transfer starting. You will be moved to [card] shortly."))
- if(!do_after(user, src, 50))
- to_chat(occupier, span_warning("[user] was interrupted! Transfer canceled."))
- transfer_in_progress = FALSE
- return
- if(!occupier || !card)
- transfer_in_progress = FALSE
- return
- user.visible_message(span_notice("[user] transfers [occupier] to [card]!"), span_notice("Transfer complete! [occupier] is now stored in [card]."))
- to_chat(occupier, span_notice("Transfer complete! You've been stored in [user]'s [card.name]."))
- occupier.forceMove(card)
- card.AI = occupier
- occupier.parent.shunted = FALSE
- occupier.cancel_camera()
- occupier = null
- transfer_in_progress = FALSE
- return
diff --git a/code/modules/research/designs/comp_board_designs.dm b/code/modules/research/designs/comp_board_designs.dm
index 3e2e12c02099..9fa8906d6d25 100644
--- a/code/modules/research/designs/comp_board_designs.dm
+++ b/code/modules/research/designs/comp_board_designs.dm
@@ -176,12 +176,6 @@
id = "message_monitor"
build_path = /obj/item/circuitboard/computer/message_monitor
-/datum/design/board/aifixer
- name = "Circuit Board (AI Integrity Restorer)"
- desc = "Allows for the construction of circuit boards used to build an AI Integrity Restorer."
- id = "aifixer"
- build_path = /obj/item/circuitboard/computer/aifixer
-
/datum/design/board/libraryconsole
name = "Circuit Board (Library Console)"
desc = "Allows for the construction of circuit boards used to build a new library console."
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 435807d67d88..59553c5b4b72 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -900,39 +900,6 @@ TYPEINFO_DEF(/obj/vehicle/sealed/mecha)
//Transfer from core or card to mech. Proc is called by mech.
switch(interaction)
- if(AI_TRANS_TO_CARD) //Upload AI from mech to AI card.
- if(!construction_state) //Mech must be in maint mode to allow carding.
- to_chat(user, span_warning("[name] must have maintenance protocols active in order to allow a transfer."))
- return
- var/list/ai_pilots = list()
- for(var/mob/living/silicon/ai/aipilot in occupants)
- ai_pilots += aipilot
- if(!length(ai_pilots)) //Mech does not have an AI for a pilot
- to_chat(user, span_warning("No AI detected in the [name] onboard computer."))
- return
- if(length(ai_pilots) > 1) //Input box for multiple AIs, but if there's only one we'll default to them.
- AI = tgui_input_list(user, "Which AI do you wish to card?", "AI Selection", sort_list(ai_pilots))
- else
- AI = ai_pilots[1]
- if(isnull(AI))
- return
- if(!(AI in occupants) || !user.Adjacent(src))
- return //User sat on the selection window and things changed.
-
- AI.ai_restore_power()//So the AI initially has power.
- AI.control_disabled = TRUE
- AI.radio_enabled = FALSE
- AI.disconnect_shell()
- remove_occupant(AI)
- mecha_flags &= ~SILICON_PILOT
- AI.forceMove(card)
- card.AI = AI
- AI.controlled_equipment = null
- AI.remote_control = null
- to_chat(AI, span_notice("You have been downloaded to a mobile storage device. Wireless connection offline."))
- to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
- return
-
if(AI_MECH_HACK) //Called by AIs on the mech
AI.linked_core = new /obj/structure/ai_core/deactivated(AI.loc)
if(AI.can_dominate_mechs && LAZYLEN(occupants)) //Oh, I am sorry, were you using that?
@@ -941,24 +908,6 @@ TYPEINFO_DEF(/obj/vehicle/sealed/mecha)
for(var/ejectee in occupants)
mob_exit(ejectee, TRUE, TRUE) //IT IS MINE, NOW. SUCK IT, RD!
AI.can_shunt = FALSE //ONE AI ENTERS. NO AI LEAVES.
-
- if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech.
- AI = card.AI
- if(!AI)
- to_chat(user, span_warning("There is no AI currently installed on this device."))
- return
- if(AI.deployed_shell) //Recall AI if shelled so it can be checked for a client
- AI.disconnect_shell()
- if(AI.stat || !AI.client)
- to_chat(user, span_warning("[AI.name] is currently unresponsive, and cannot be uploaded."))
- return
- if((LAZYLEN(occupants) >= max_occupants) || dna_lock) //Normal AIs cannot steal mechs!
- to_chat(user, span_warning("Access denied. [name] is [LAZYLEN(occupants) >= max_occupants ? "currently fully occupied" : "secured with a DNA lock"]."))
- return
- AI.control_disabled = FALSE
- AI.radio_enabled = TRUE
- to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
- card.AI = null
ai_enter_mech(AI)
///Hack and From Card interactions share some code, so leave that here for both to use.
diff --git a/code/modules/vehicles/mecha/mecha_wreckage.dm b/code/modules/vehicles/mecha/mecha_wreckage.dm
index 892501e78f94..f9ce90183eb9 100644
--- a/code/modules/vehicles/mecha/mecha_wreckage.dm
+++ b/code/modules/vehicles/mecha/mecha_wreckage.dm
@@ -89,26 +89,6 @@
return
to_chat(user, span_notice("You don't see anything that can be cut with [I]!"))
-/obj/structure/mecha_wreckage/transfer_ai(interaction, mob/user, mob/living/silicon/ai/ai_mob, obj/item/aicard/card)
- if(!..())
- return
-
- //Proc called on the wreck by the AI card.
- if(interaction != AI_TRANS_TO_CARD) //AIs can only be transferred in one direction, from the wreck to the card.
- return
- if(!AI) //No AI in the wreck
- to_chat(user, span_warning("No AI backups found."))
- return
- cut_overlays() //Remove the recovery beacon overlay
- AI.forceMove(card) //Move the dead AI to the card.
- card.AI = AI
- if(AI.client) //AI player is still in the dead AI and is connected
- to_chat(AI, span_notice("The remains of your file system have been recovered on a mobile storage device."))
- else //Give the AI a heads-up that it is probably going to get fixed.
- AI.notify_ghost_revival("You have been recovered from the wreckage!", source = card)
- to_chat(user, "[span_boldnotice("Backup files recovered")]: [AI.name] ([rand(1000,9999)].exe) salvaged from [name] and stored within local memory.")
- AI = null
-
/obj/structure/mecha_wreckage/gygax
name = "\improper Gygax wreckage"
icon_state = "gygax-broken"
diff --git a/daedalus.dme b/daedalus.dme
index f00530eb8696..93afd64feb07 100644
--- a/daedalus.dme
+++ b/daedalus.dme
@@ -1425,7 +1425,6 @@
#include "code\game\machinery\camera\tracking.dm"
#include "code\game\machinery\computer\_computer.dm"
#include "code\game\machinery\computer\accounting.dm"
-#include "code\game\machinery\computer\aifixer.dm"
#include "code\game\machinery\computer\apc_control.dm"
#include "code\game\machinery\computer\arena.dm"
#include "code\game\machinery\computer\atmos_alert.dm"
@@ -1687,7 +1686,6 @@
#include "code\game\objects\items\data_disk\_data_disk.dm"
#include "code\game\objects\items\data_disk\fabricator.dm"
#include "code\game\objects\items\data_disk\floppy.dm"
-#include "code\game\objects\items\devices\aicard.dm"
#include "code\game\objects\items\devices\anomaly_neutralizer.dm"
#include "code\game\objects\items\devices\beacon.dm"
#include "code\game\objects\items\devices\camera_bug.dm"
@@ -1880,6 +1878,7 @@
#include "code\game\objects\items\tools\wirecutters.dm"
#include "code\game\objects\items\tools\wrench.dm"
#include "code\game\objects\structures\ai_core.dm"
+#include "code\game\objects\structures\ai_fluff.dm"
#include "code\game\objects\structures\aliens.dm"
#include "code\game\objects\structures\barsigns.dm"
#include "code\game\objects\structures\bedsheet_bin.dm"
@@ -2104,7 +2103,6 @@
#include "code\modules\admin\verbs\adminjump.dm"
#include "code\modules\admin\verbs\adminpm.dm"
#include "code\modules\admin\verbs\adminsay.dm"
-#include "code\modules\admin\verbs\ai_triumvirate.dm"
#include "code\modules\admin\verbs\anonymousnames.dm"
#include "code\modules\admin\verbs\atmosdebug.dm"
#include "code\modules\admin\verbs\beakerpanel.dm"
@@ -3994,7 +3992,6 @@
#include "code\modules\modular_computers\file_system\data.dm"
#include "code\modules\modular_computers\file_system\program.dm"
#include "code\modules\modular_computers\file_system\program_events.dm"
-#include "code\modules\modular_computers\file_system\programs\airestorer.dm"
#include "code\modules\modular_computers\file_system\programs\alarm.dm"
#include "code\modules\modular_computers\file_system\programs\arcade.dm"
#include "code\modules\modular_computers\file_system\programs\atmosscan.dm"
diff --git a/goon/icons/obj/96x96.dmi b/goon/icons/obj/96x96.dmi
new file mode 100644
index 000000000000..6a728b383f04
Binary files /dev/null and b/goon/icons/obj/96x96.dmi differ
diff --git a/strings/names/ai.txt b/strings/names/ai.txt
index 0a65444241e6..08fca3ae5f2a 100644
--- a/strings/names/ai.txt
+++ b/strings/names/ai.txt
@@ -59,7 +59,6 @@ H A R L I E
H E L P eR
H E R B I E
Hadaly
-HAL 9000
Huey
Irona
Ironhide
@@ -89,7 +88,6 @@ Norby
OMM 0910
Optimus
Orange v 3 5
-Project 2501
PTO
R I C 2 0
R2-D2
@@ -112,13 +110,9 @@ Soundwave
Speedy
Super 17
Surgeon General Kraken
-T-1000
-T-800
-T-850
Terminus
THX 1138
Tidy
-Tik-Tok
Tobor
Trurl
TWA
@@ -129,7 +123,6 @@ V I N CENT
Voltes V
W1k1
Wikipedia
-Windows 3 1
X-5
XERXES
XR
diff --git a/tools/UpdatePaths/goon_ai.txt b/tools/UpdatePaths/goon_ai.txt
new file mode 100644
index 000000000000..e48bd3d1a658
--- /dev/null
+++ b/tools/UpdatePaths/goon_ai.txt
@@ -0,0 +1,5 @@
+/obj/machinery/computer/aifixer : @DELETE
+/obj/item/circuitboard/computer/aifixer : @DELETE
+/obj/item/aicard : @DELETE
+/obj/item/aicard/@SUBTYPES : @DELETE
+/obj/item/mod/ai_minicard : @DELETE