diff --git a/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm b/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm
index 1fb4e60aff..d440e2d15b 100644
--- a/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm
+++ b/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm
@@ -69,7 +69,7 @@
/turf/open/floor/plasteel/white,
/area/ruin/space/has_grav/powered/ancient_shuttle)
"j" = (
-/obj/machinery/computer/prototype_cloning,
+/obj/machinery/computer/cloning/prototype,
/obj/machinery/light{
dir = 1
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index eda78e4206..588b55679c 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -263,15 +263,484 @@
},
/turf/open/floor/plasteel,
/area/maintenance/department/engine)
+"aaD" = (
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 10
+ },
+/obj/structure/closet/crate{
+ icon_state = "crateopen"
+ },
+/obj/effect/spawner/lootdrop/maintenance{
+ lootcount = 2;
+ name = "2maintenance loot spawner"
+ },
+/obj/item/clothing/mask/balaclava,
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"aaE" = (
+/obj/machinery/light/small,
+/obj/machinery/space_heater,
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"aaF" = (
+/turf/closed/wall,
+/area/crew_quarters/fitness/pool)
+"aaG" = (
+/obj/structure/closet,
+/obj/item/weldingtool,
+/obj/item/crowbar,
+/obj/effect/spawner/lootdrop/maintenance,
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"aaH" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "12"
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"aaI" = (
+/obj/structure/closet/secure_closet/personal,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/crew_quarters/fitness/pool)
+"aaJ" = (
+/obj/effect/spawner/structure/window/reinforced,
+/turf/open/floor/plating,
+/area/crew_quarters/fitness/pool)
+"aaK" = (
+/obj/machinery/light{
+ dir = 1;
+ light_color = "#706891"
+ },
+/obj/structure/closet/secure_closet/personal,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/crew_quarters/fitness/pool)
+"aaL" = (
+/turf/open/floor/plasteel/yellowsiding,
+/area/crew_quarters/fitness/pool)
+"aaM" = (
+/turf/open/floor/plasteel/yellowsiding/corner{
+ icon_state = "yellowcornersiding";
+ dir = 8
+ },
+/area/crew_quarters/fitness/pool)
+"aaN" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 6
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaO" = (
+/turf/open/pool,
+/area/crew_quarters/fitness/pool)
+"aaP" = (
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 8
+ },
+/area/crew_quarters/fitness/pool)
+"aaQ" = (
+/obj/structure/table,
+/obj/effect/spawner/lootdrop/maintenance,
+/obj/item/storage/box/lights/mixed,
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"aaR" = (
+/obj/machinery/airalarm{
+ pixel_y = 22
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaS" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaT" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/machinery/camera{
+ c_tag = "Pool"
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaU" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/structure/sign/poster/official/walk{
+ pixel_y = 32
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaV" = (
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/structure/extinguisher_cabinet{
+ pixel_y = 30
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaW" = (
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"aaX" = (
+/obj/structure/bed,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/crew_quarters/fitness/pool)
+"aaY" = (
+/obj/effect/spawner/structure/window,
+/turf/open/floor/plating,
+/area/crew_quarters/fitness/pool)
+"aaZ" = (
+/obj/structure/bed,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner,
+/area/crew_quarters/fitness/pool)
+"aba" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/recreation)
+"abb" = (
+/obj/machinery/camera{
+ c_tag = "Fitness Room"
+ },
+/obj/machinery/computer/security/telescreen/entertainment{
+ pixel_y = 32
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/recreation)
+"abc" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/yellowsiding/corner,
+/area/crew_quarters/fitness/pool)
+"abd" = (
+/obj/structure/closet/lasertag/red,
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abe" = (
+/obj/machinery/vending/kink,
+/obj/machinery/status_display/evac{
+ pixel_x = 32;
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
"abf" = (
/obj/structure/bed,
/turf/open/floor/plating,
/area/maintenance/department/science)
+"abg" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abh" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/closet/lasertag/blue,
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abi" = (
+/obj/machinery/disposal/bin,
+/obj/structure/disposalpipe/trunk{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abj" = (
+/obj/machinery/pool/controller,
+/turf/open/floor/plasteel/yellowsiding,
+/area/crew_quarters/fitness/pool)
+"abk" = (
+/obj/machinery/light{
+ dir = 4;
+ light_color = "#e8eaff"
+ },
+/obj/structure/bed,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner,
+/area/crew_quarters/fitness/pool)
+"abl" = (
+/obj/machinery/airalarm{
+ dir = 4;
+ pixel_x = -23
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/recreation)
+"abm" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 4
+ },
+/area/crew_quarters/fitness/pool)
+"abn" = (
+/obj/machinery/pool/filter{
+ pixel_y = 24
+ },
+/turf/open/pool,
+/area/crew_quarters/fitness/pool)
+"abo" = (
+/obj/structure/pool/ladder{
+ dir = 2;
+ pixel_y = 24
+ },
+/turf/open/pool,
+/area/crew_quarters/fitness/pool)
+"abp" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner,
+/area/crew_quarters/fitness/pool)
+"abq" = (
+/obj/machinery/light{
+ dir = 8;
+ light_color = "#e8eaff"
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 4
+ },
+/area/crew_quarters/fitness/pool)
+"abr" = (
+/obj/machinery/pool/drain,
+/turf/open/pool,
+/area/crew_quarters/fitness/pool)
+"abs" = (
+/obj/structure/pool/Lboard,
+/turf/open/pool,
+/area/crew_quarters/fitness/pool)
+"abt" = (
+/obj/structure/pool/Rboard,
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 8
+ },
+/area/crew_quarters/fitness/pool)
+"abu" = (
+/obj/item/radio/intercom{
+ name = "Station Intercom (General)";
+ pixel_x = 28
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner,
+/area/crew_quarters/fitness/pool)
+"abv" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/item/cigbutt,
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"abw" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/structure/table/glass,
+/obj/item/storage/firstaid/regular,
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/pool)
+"abx" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
+/obj/structure/closet/athletic_mixed,
+/obj/item/toy/poolnoodle/blue,
+/obj/item/toy/poolnoodle/red,
+/obj/item/toy/poolnoodle/yellow,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner,
+/area/crew_quarters/fitness/pool)
"aby" = (
/obj/structure/lattice,
/obj/structure/grille,
/turf/open/space,
/area/space/nearstation)
+"abz" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/structure/extinguisher_cabinet{
+ pixel_x = -24
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/crew_quarters/fitness/pool)
+"abA" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/yellowsiding/corner{
+ icon_state = "yellowcornersiding";
+ dir = 4
+ },
+/area/crew_quarters/fitness/pool)
+"abB" = (
+/obj/machinery/firealarm{
+ dir = 1;
+ pixel_x = -2;
+ pixel_y = -27
+ },
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"abC" = (
+/obj/machinery/light,
+/turf/open/floor/plasteel/yellowsiding{
+ icon_state = "yellowsiding";
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"abD" = (
+/turf/open/floor/plasteel/yellowsiding/corner{
+ icon_state = "yellowcornersiding";
+ dir = 1
+ },
+/area/crew_quarters/fitness/pool)
+"abE" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 5
+ },
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/obj/machinery/power/apc{
+ areastring = "/area/crew_quarters/fitness/pool";
+ name = "Pool APC";
+ pixel_y = -24
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner,
+/area/crew_quarters/fitness/pool)
+"abF" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "12"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plating,
+/area/crew_quarters/fitness/pool)
+"abG" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/crew_quarters/dorms)
+"abH" = (
+/obj/machinery/door/firedoor,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/door/airlock/public/glass{
+ name = "Pool"
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/crew_quarters/fitness/pool)
"abI" = (
/obj/structure/lattice,
/turf/open/space,
@@ -285,6 +754,26 @@
},
/turf/open/space,
/area/space/nearstation)
+"abK" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/crew_quarters/fitness/recreation)
+"abL" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abM" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
"abN" = (
/obj/effect/landmark/carpspawn,
/turf/open/space,
@@ -292,6 +781,42 @@
"abO" = (
/turf/closed/wall/r_wall,
/area/ai_monitored/turret_protected/ai)
+"abP" = (
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abQ" = (
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abR" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 9
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abS" = (
+/obj/structure/weightmachine/stacklifter,
+/turf/open/floor/plasteel,
+/area/crew_quarters/fitness/recreation)
+"abT" = (
+/obj/machinery/door/firedoor,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/door/airlock/public/glass{
+ name = "Pool"
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/crew_quarters/fitness/pool)
"abV" = (
/obj/effect/turf_decal/stripes/corner,
/turf/open/floor/plasteel/white,
@@ -3820,18 +4345,6 @@
},
/turf/open/floor/plating,
/area/maintenance/department/crew_quarters/dorms)
-"akq" = (
-/obj/structure/cable{
- icon_state = "2-8"
- },
-/obj/machinery/light/small{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 10
- },
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"akr" = (
/obj/machinery/washing_machine,
/obj/item/radio/intercom{
@@ -5230,16 +5743,6 @@
},
/turf/open/floor/plating,
/area/maintenance/department/crew_quarters/dorms)
-"anp" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
-/obj/effect/decal/cleanable/robot_debris{
- icon_state = "gib6"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"anq" = (
/obj/structure/grille/broken,
/turf/open/floor/plating,
@@ -6932,10 +7435,6 @@
},
/turf/open/space/basic,
/area/space)
-"aqZ" = (
-/obj/machinery/space_heater,
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"ara" = (
/obj/structure/lattice/catwalk,
/obj/structure/cable{
@@ -7525,35 +8024,6 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plating,
/area/crew_quarters/dorms)
-"asl" = (
-/obj/structure/grille/broken,
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
-"asm" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/light{
- dir = 1
- },
-/obj/item/cigbutt,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
-"asn" = (
-/obj/structure/cable{
- icon_state = "2-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 10
- },
-/obj/effect/decal/cleanable/cobweb{
- icon_state = "cobweb2"
- },
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"aso" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -8021,26 +8491,9 @@
/obj/structure/closet/emcloset/anchored,
/turf/open/floor/plating,
/area/crew_quarters/dorms)
-"atm" = (
-/obj/structure/closet,
-/obj/item/weldingtool,
-/obj/item/crowbar,
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"atn" = (
/turf/closed/wall,
/area/crew_quarters/fitness/recreation)
-"ato" = (
-/obj/structure/closet/crate{
- icon_state = "crateopen"
- },
-/obj/effect/spawner/lootdrop/maintenance{
- lootcount = 2;
- name = "2maintenance loot spawner"
- },
-/obj/item/clothing/mask/balaclava,
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"atp" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -8506,41 +8959,6 @@
},
/turf/open/floor/plating,
/area/crew_quarters/dorms)
-"aun" = (
-/obj/structure/table,
-/obj/effect/spawner/lootdrop/maintenance,
-/obj/item/storage/box/lights/mixed,
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
-"auo" = (
-/obj/structure/cable{
- icon_state = "1-4"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 5
- },
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
-"aup" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/structure/grille/broken,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
-"auq" = (
-/obj/effect/spawner/lootdrop/maintenance,
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 9
- },
-/turf/open/floor/plating,
-/area/maintenance/department/crew_quarters/dorms)
"aur" = (
/turf/open/floor/engine{
name = "Holodeck Projector Floor"
@@ -9564,57 +9982,6 @@
},
/turf/open/floor/plating,
/area/crew_quarters/fitness/recreation)
-"awy" = (
-/obj/structure/closet/lasertag/blue,
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/obj/machinery/airalarm{
- pixel_y = 22
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/turf/open/floor/plasteel/white/corner{
- dir = 1
- },
-/area/crew_quarters/fitness/recreation)
-"awz" = (
-/obj/structure/closet/lasertag/red,
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/obj/machinery/status_display/evac{
- pixel_y = 32
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/turf/open/floor/plasteel/white/corner{
- dir = 1
- },
-/area/crew_quarters/fitness/recreation)
-"awA" = (
-/obj/machinery/disposal/bin,
-/obj/machinery/light{
- dir = 1
- },
-/obj/structure/disposalpipe/trunk{
- dir = 8
- },
-/obj/machinery/camera{
- c_tag = "Fitness Room"
- },
-/obj/machinery/computer/security/telescreen/entertainment{
- pixel_y = 32
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/turf/open/floor/plasteel/white/corner{
- dir = 1
- },
-/area/crew_quarters/fitness/recreation)
"awB" = (
/obj/machinery/vending/clothing,
/obj/effect/turf_decal/tile/blue{
@@ -10025,10 +10392,6 @@
"axw" = (
/turf/open/floor/plasteel,
/area/crew_quarters/fitness/recreation)
-"axx" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/turf/open/floor/plasteel,
-/area/crew_quarters/fitness/recreation)
"axy" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/public/glass{
@@ -10406,13 +10769,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/fitness/recreation)
-"ayv" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 9
- },
-/obj/structure/weightmachine/stacklifter,
-/turf/open/floor/plasteel,
-/area/crew_quarters/fitness/recreation)
"ayw" = (
/obj/machinery/computer/holodeck{
dir = 4
@@ -54124,15 +54480,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/kitchen)
-"gcj" = (
-/obj/machinery/vending/kink,
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/turf/open/floor/plasteel/white/corner{
- dir = 1
- },
-/area/crew_quarters/fitness/recreation)
"gdJ" = (
/obj/structure/table/glass,
/obj/item/folder/blue,
@@ -102547,11 +102894,11 @@ aaa
aaa
aaa
aaa
-apX
-apX
-apX
-apX
-apX
+aaF
+aaF
+aaF
+aaF
+atn
atn
aww
axv
@@ -102798,19 +103145,19 @@ aaa
aiS
cBy
aiS
-aiS
-aiS
-aiT
-aiT
-aiT
-aiS
-aiS
-aiS
-aiS
-atm
-aun
-atn
-awz
+aaF
+aaF
+aaJ
+aaJ
+aaJ
+aaF
+aaF
+abw
+abz
+abH
+abl
+axw
+abg
axw
ayu
azC
@@ -103053,23 +103400,23 @@ aaa
aaa
aaa
aiT
-akq
-ale
-ale
-ale
-anp
-ale
-ale
-ale
-ale
-ale
-ale
-ale
-auo
-atn
-awy
-axw
-ayu
+akn
+ajv
+aaH
+aaN
+abc
+abm
+abm
+abq
+abm
+abm
+abA
+abT
+abK
+abL
+abM
+abP
+abR
azC
axw
aBU
@@ -103310,23 +103657,23 @@ aaa
aaa
aaa
aiS
-aiS
-aiS
-aiS
-aiS
-aiT
-aiT
-aiT
-aiS
-aiS
-aiS
-asl
-aiS
-aup
-atn
-awA
-axx
-ayv
+akn
+aaE
+aaF
+aaR
+aaL
+aaO
+aaO
+aaO
+aaO
+aaO
+aaW
+aaF
+abb
+abd
+abh
+abQ
+abS
azD
aAS
aat
@@ -103566,22 +103913,22 @@ rmC
aaa
aaa
aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
aiS
-apu
-ale
-auq
-atn
-awB
+akn
+aaG
+aaF
+aaS
+aaL
+abn
+aaO
+aaO
+aaO
+aaO
+aaW
+aaY
+aba
+axw
+abg
axw
axw
axw
@@ -103823,22 +104170,22 @@ rmC
aaa
aaa
aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
aiS
akn
-ajv
-aqZ
-atn
-gcj
+aaF
+aaF
+aaS
+abj
+aaO
+aaO
+aaO
+aaO
+aaO
+aaW
+aaY
+awB
+abe
+abi
axw
axw
axw
@@ -104080,18 +104427,18 @@ rmC
aaa
aaa
aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
aiS
akn
+aaF
+aaI
+aaS
+aaL
+abo
+aaO
+abr
+aaO
+aaO
+abB
atn
atn
avm
@@ -104337,18 +104684,18 @@ rmC
aaa
aaa
aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aiT
+aiS
akn
+aaF
+aaK
+aaS
+aaL
+aaO
+aaO
+aaO
+aaO
+aaO
+abC
atn
aur
aur
@@ -104591,22 +104938,22 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
aaa
aaa
aaa
-aaa
-aiT
+aiS
akn
-atn
+aaF
+aaI
+aaS
+aaL
+aaO
+aaO
+aaO
+aaO
+aaO
+aaW
+avm
aur
aur
aur
@@ -104848,22 +105195,22 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiS
-asm
-atn
+akn
+aaF
+aaF
+aaT
+aaL
+aaO
+aaO
+aaO
+aaO
+aaO
+aaW
+avm
aur
aur
aur
@@ -105105,22 +105452,22 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiT
akn
-atn
+ajv
+aaF
+aaU
+aaL
+aaO
+aaO
+abs
+aaO
+aaO
+aaW
+avm
aur
aur
aur
@@ -105362,21 +105709,21 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiT
akn
+aaQ
+aaF
+aaV
+aaM
+aaP
+aaP
+abt
+aaP
+aaP
+abD
atn
aur
aur
@@ -105619,21 +105966,21 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiS
akn
+sbk
+aaF
+aaX
+aaZ
+aaZ
+abk
+abp
+abu
+abx
+abE
atn
atn
avm
@@ -105876,22 +106223,22 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiS
akn
-ato
+ajv
+aaF
+aaF
+aaF
+aaF
+aaF
+aaF
+aaF
+aaF
+abF
+aaF
aiS
atn
awC
@@ -106133,21 +106480,21 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiS
-asn
+aaD
+ale
+ale
+ale
+ale
+ale
+ale
+ale
+abv
+ale
+abG
ale
ale
avn
@@ -106390,20 +106737,20 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-aaa
aaa
aaa
aaa
aiS
+aiS
+aiS
+aiS
+aiS
+aiT
+aiS
+aiS
+aiS
+aiS
+aiS
aiT
aiS
aiS
@@ -106647,15 +106994,15 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -106904,15 +107251,15 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -107161,15 +107508,15 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -107418,15 +107765,15 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -107675,15 +108022,15 @@ rmC
rmC
rmC
rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
-rmC
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index fe06b7037e..0e8e34d20e 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -118,4 +118,4 @@
#define CLONEPOD_GET_MIND 1
#define CLONEPOD_POLL_MIND 2
-#define CLONEPOD_NO_MIND 3
+#define CLONEPOD_NO_MIND 3
\ No newline at end of file
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 3391458817..78a0365ac0 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -109,7 +109,7 @@
/obj/machinery/clonepod/attack_ai(mob/user)
return examine(user)
-//Start growing a clone in the pod!
+//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
if(panel_open)
return FALSE
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 7834d6f2a2..400ce041c7 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -8,6 +8,7 @@
circuit = /obj/item/circuitboard/computer/cloning
req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW.
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
+ var/clonepod_type = /obj/machinery/clonepod
var/list/pods //Linked cloning pods
var/temp = "Inactive"
var/scantemp_ckey
@@ -17,6 +18,7 @@
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
var/loading = 0 // Nice loading text
var/autoprocess = 0
+ var/use_records = TRUE // Old experimental cloner.
var/list/records = list()
light_color = LIGHT_COLOR_BLUE
@@ -36,29 +38,32 @@
return ..()
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/pod = P
- if(pod.occupant && pod.clonemind == mind)
- return null
- if(pod.is_operational() && !(pod.occupant || pod.mess))
- return pod
+ if(!pods)
+ return
+ for(var/P in pods)
+ var/obj/machinery/clonepod/pod = P
+ if(pod.occupant && pod.get_clone_mind == CLONEPOD_GET_MIND && pod.clonemind == mind)
+ return null
+ if(pod.is_operational() && !(pod.occupant || pod.mess))
+ return pod
/obj/machinery/computer/cloning/proc/HasEfficientPod()
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/pod = P
- if(pod.is_operational() && pod.efficiency > 5)
- return TRUE
+ if(!pods)
+ return
+ for(var/P in pods)
+ var/obj/machinery/clonepod/pod = P
+ if(pod.is_operational() && pod.efficiency > 5)
+ return TRUE
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/pod = P
- if(pod.occupant && pod.clonemind == mind)
- return pod
- else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
- . = pod
+ if(!pods)
+ return
+ for(var/P in pods)
+ var/obj/machinery/clonepod/pod = P
+ if(pod.occupant && pod.clonemind == mind)
+ return pod
+ else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
+ . = pod
/obj/machinery/computer/cloning/process()
if(!(scanner && LAZYLEN(pods) && autoprocess))
@@ -73,7 +78,7 @@
if(pod.occupant)
continue //how though?
- if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
+ if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
temp = "[R.fields["name"]] => Cloning cycle in progress..."
records -= R
@@ -103,12 +108,10 @@
return null
/obj/machinery/computer/cloning/proc/findcloner()
- var/obj/machinery/clonepod/podf = null
-
+ var/obj/machinery/clonepod/podf
for(var/direction in GLOB.cardinals)
-
- podf = locate(/obj/machinery/clonepod, get_step(src, direction))
- if (!isnull(podf) && podf.is_operational())
+ podf = locate(clonepod_type, get_step(src, direction))
+ if(podf?.is_operational())
AttachCloner(podf)
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
@@ -132,7 +135,7 @@
else if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
- if(istype(P.buffer, /obj/machinery/clonepod))
+ if(istype(P.buffer, clonepod_type))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-")
P.buffer = null
@@ -157,13 +160,14 @@
var/dat = ""
dat += "Refresh"
- if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
- if(!autoprocess)
- dat += "Autoclone"
+ if(use_records)
+ if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
+ if(!autoprocess)
+ dat += "Autoclone"
+ else
+ dat += "Stop autoclone"
else
- dat += "Stop autoclone"
- else
- dat += "Autoclone"
+ dat += "Autoclone"
dat += "
Cloning Pod Status
"
dat += "[temp]
"
@@ -190,26 +194,29 @@
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
- if(scanner_occupant.ckey != scantemp_ckey)
- scantemp = "Ready to Scan"
- scantemp_ckey = scanner_occupant.ckey
+ if(use_records)
+ if(scanner_occupant.ckey != scantemp_ckey)
+ scantemp = "Ready to Scan"
+ scantemp_ckey = scanner_occupant.ckey
+ else
+ scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += ""
if(scanner_occupant)
- dat += "Start Scan"
- dat += "
[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]"
+ dat += "[use_records ? "Start Scan" : "Clone"]"
+ dat += "
[scanner.locked ? "Unlock Scanner" : "Lock Scanner"]"
else
- dat += "Start Scan"
-
- // Database
- dat += "Database Functions
"
- if (src.records.len && src.records.len > 0)
- dat += "View Records ([src.records.len])
"
- else
- dat += "View Records (0)
"
- if (src.diskette)
- dat += "Eject Disk
"
+ dat += "[use_records ? "Start Scan" : "Clone"]"
+ if(use_records)
+ // Database
+ dat += "Database Functions
"
+ if (src.records.len && src.records.len > 0)
+ dat += "View Records ([src.records.len])
"
+ else
+ dat += "View Records (0)
"
+ if (src.diskette)
+ dat += "Eject Disk
"
@@ -290,24 +297,19 @@
autoprocess = FALSE
STOP_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ . = TRUE
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
- loading = 1
+ loading = TRUE
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
- spawn(20)
- src.scan_occupant(scanner.occupant)
-
- loading = 0
- src.updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
- scanner.locked = prev_locked
-
+ addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
+ . = TRUE
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
@@ -317,8 +319,17 @@
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ . = TRUE
- else if(href_list["view_rec"])
+
+ else if (href_list["refresh"])
+ src.updateUsrDialog()
+ playsound(src, "terminal_type", 25, 0)
+ . = TRUE
+
+ if(. || !use_records)
+ return
+ if(href_list["view_rec"])
playsound(src, "terminal_type", 25, 0)
src.active_record = find_record("id", href_list["view_rec"], records)
if(active_record)
@@ -330,6 +341,7 @@
src.menu = 3
else
src.temp = "Record missing."
+ . = TRUE
else if (href_list["del_rec"])
if ((!src.active_record) || (src.menu < 3))
@@ -353,8 +365,9 @@
else
src.temp = "Access Denied."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ . = TRUE
- else if (href_list["disk"]) //Load or eject.
+ else if (href_list["disk"] && use_records) //Load or eject.
switch(href_list["disk"])
if("load")
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
@@ -392,10 +405,7 @@
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
src.temp = "Save successful."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
- else if (href_list["refresh"])
- src.updateUsrDialog()
- playsound(src, "terminal_type", 25, 0)
+ . = TRUE
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
@@ -415,7 +425,7 @@
else if(pod.occupant)
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"]))
+ else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
temp = "[C.fields["name"]] => Cloning cycle in progress..."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
@@ -429,14 +439,28 @@
else
temp = "Data corruption."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ . = TRUE
- else if (href_list["menu"])
- src.menu = text2num(href_list["menu"])
+ else if (href_list["menu"] && use_records)
+ menu = text2num(href_list["menu"])
playsound(src, "terminal_type", 25, 0)
+ . = TRUE
+/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
+ if(!scanner || !L)
+ return
src.add_fingerprint(usr)
src.updateUsrDialog()
- return
+
+ if(use_records)
+ scan_occupant(L)
+ else
+ clone_occupant(L)
+
+ loading = FALSE
+ src.updateUsrDialog()
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ scanner.locked = prev_locked
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
@@ -455,30 +479,9 @@
if(isbrain(mob_occupant))
dna = B.stored_dna
- if(!istype(dna))
- scantemp = "Unable to locate valid genetic data."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if(mob_occupant.suiciding || mob_occupant.hellbound)
- scantemp = "Subject's brain is not responding to scanning stimuli."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
- scantemp = "Subject no longer contains the fundamental materials required to create a living clone."
- playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
- return
- if ((!mob_occupant.ckey) || (!mob_occupant.client))
- scantemp = "Mental interface failure."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if (find_record("ckey", mob_occupant.ckey, records))
- scantemp = "Subject already in database."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if(SSeconomy.full_ancap && !has_bank_account)
- scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ if(!can_scan(dna, mob_occupant, FALSE, has_bank_account))
return
+
var/datum/data/record/R = new()
if(dna.species)
// We store the instance rather than the path, because some
@@ -529,3 +532,78 @@
board.records = records
scantemp = "Subject successfully scanned."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+
+//Used by the experimental cloning computer.
+/obj/machinery/computer/cloning/proc/clone_occupant(occupant)
+ var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
+ var/datum/dna/dna
+ if(ishuman(mob_occupant))
+ var/mob/living/carbon/C = mob_occupant
+ dna = C.has_dna()
+ if(isbrain(mob_occupant))
+ var/mob/living/brain/B = mob_occupant
+ dna = B.stored_dna
+
+ if(!can_scan(dna, mob_occupant, TRUE))
+ return
+
+ var/clone_species
+ if(dna.species)
+ clone_species = dna.species
+ else
+ var/datum/species/rando_race = pick(GLOB.roundstart_races)
+ clone_species = rando_race.type
+
+ var/obj/machinery/clonepod/pod = GetAvailablePod()
+ //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
+ if(!LAZYLEN(pods))
+ temp = "No Clonepods detected."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else if(!pod)
+ temp = "No Clonepods available."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else if(pod.occupant)
+ temp = "Cloning cycle already in progress."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else
+ pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
+ temp = "[mob_occupant.real_name] => Cloning data sent to pod."
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+
+/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account)
+ if(!istype(dna))
+ scantemp = "Unable to locate valid genetic data."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if(!experimental)
+ if(mob_occupant.suiciding || mob_occupant.hellbound)
+ scantemp = "Subject's brain is not responding to scanning stimuli."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
+ scantemp = "Subject no longer contains the fundamental materials required to create a living clone."
+ playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
+ return
+ if (!experimental)
+ if(!mob_occupant.ckey || !mob_occupant.client)
+ scantemp = "Mental interface failure."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if (find_record("ckey", mob_occupant.ckey, records))
+ scantemp = "Subject already in database."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ if(SSeconomy.full_ancap && !account)
+ scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
+ return TRUE
+
+//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
+/obj/machinery/computer/cloning/prototype
+ name = "prototype cloning console"
+ desc = "Used to operate an experimental cloner."
+ icon_screen = "dna"
+ icon_keyboard = "med_key"
+ circuit = /obj/item/circuitboard/computer/cloning/prototype
+ clonepod_type = /obj/machinery/clonepod/experimental
diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm
deleted file mode 100644
index 2c669aac80..0000000000
--- a/code/game/machinery/exp_cloner.dm
+++ /dev/null
@@ -1,298 +0,0 @@
-//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
-/obj/machinery/clonepod/experimental
- name = "experimental cloning pod"
- desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
- icon = 'icons/obj/machines/cloning.dmi'
- icon_state = "pod_0"
- req_access = null
- circuit = /obj/item/circuitboard/machine/clonepod/experimental
- internal_radio = FALSE
-
-//Start growing a human clone in the pod!
-/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
- if(panel_open)
- return FALSE
- if(mess || attempting)
- return FALSE
-
- attempting = TRUE //One at a time!!
- countdown.start()
-
- var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
-
- H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
-
- if(efficiency > 2)
- var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
- H.dna.remove_mutation_group(unclean_mutations)
- if(efficiency > 5 && prob(20))
- H.easy_randmut(POSITIVE)
- if(efficiency < 3 && prob(50))
- var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
- if(ismob(M))
- H = M
-
- H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
- occupant = H
-
- if(!clonename) //to prevent null names
- clonename = "clone ([rand(1,999)])"
- H.real_name = clonename
-
- icon_state = "pod_1"
- //Get the clone body ready
- maim_clone(H)
- ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
- ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
- ADD_TRAIT(H, TRAIT_MUTE, "cloning")
- ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
- ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
- H.Unconscious(80)
-
- var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
- if(LAZYLEN(candidates))
- var/mob/C = pick(candidates)
- H.key = C.key
-
- if(grab_ghost_when == CLONER_FRESH_CLONE)
- H.grab_ghost()
- to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
So this is what cloning feels like?")
-
- if(grab_ghost_when == CLONER_MATURE_CLONE)
- H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
- to_chat(H.get_ghost(TRUE), "Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.")
-
- if(H)
- H.faction |= factions
-
- H.set_cloned_appearance()
-
- H.suiciding = FALSE
- attempting = FALSE
- return TRUE
-
-
-//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
-/obj/machinery/computer/prototype_cloning
- name = "prototype cloning console"
- desc = "Used to operate an experimental cloner."
- icon_screen = "dna"
- icon_keyboard = "med_key"
- circuit = /obj/item/circuitboard/computer/prototype_cloning
- var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
- var/list/pods //Linked experimental cloning pods
- var/temp = "Inactive"
- var/scantemp = "Ready to Scan"
- var/loading = FALSE // Nice loading text
-
- light_color = LIGHT_COLOR_BLUE
-
-/obj/machinery/computer/prototype_cloning/Initialize()
- . = ..()
- updatemodules(TRUE)
-
-/obj/machinery/computer/prototype_cloning/Destroy()
- if(pods)
- for(var/P in pods)
- DetachCloner(P)
- pods = null
- return ..()
-
-/obj/machinery/computer/prototype_cloning/proc/GetAvailablePod(mind = null)
- if(pods)
- for(var/P in pods)
- var/obj/machinery/clonepod/experimental/pod = P
- if(pod.is_operational() && !(pod.occupant || pod.mess))
- return pod
-
-/obj/machinery/computer/prototype_cloning/proc/updatemodules(findfirstcloner)
- scanner = findscanner()
- if(findfirstcloner && !LAZYLEN(pods))
- findcloner()
-
-/obj/machinery/computer/prototype_cloning/proc/findscanner()
- var/obj/machinery/dna_scannernew/scannerf = null
-
- // Loop through every direction
- for(var/direction in GLOB.cardinals)
- // Try to find a scanner in that direction
- scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
- // If found and operational, return the scanner
- if (!isnull(scannerf) && scannerf.is_operational())
- return scannerf
-
- // If no scanner was found, it will return null
- return null
-
-/obj/machinery/computer/prototype_cloning/proc/findcloner()
- var/obj/machinery/clonepod/experimental/podf = null
- for(var/direction in GLOB.cardinals)
- podf = locate(/obj/machinery/clonepod/experimental, get_step(src, direction))
- if (!isnull(podf) && podf.is_operational())
- AttachCloner(podf)
-
-/obj/machinery/computer/prototype_cloning/proc/AttachCloner(obj/machinery/clonepod/experimental/pod)
- if(!pod.connected)
- pod.connected = src
- LAZYADD(pods, pod)
-
-/obj/machinery/computer/prototype_cloning/proc/DetachCloner(obj/machinery/clonepod/experimental/pod)
- pod.connected = null
- LAZYREMOVE(pods, pod)
-
-/obj/machinery/computer/prototype_cloning/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/multitool))
- var/obj/item/multitool/P = W
-
- if(istype(P.buffer, /obj/machinery/clonepod/experimental))
- if(get_area(P.buffer) != get_area(src))
- to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-")
- P.buffer = null
- return
- to_chat(user, "-% Successfully linked [P.buffer] with [src] %-")
- var/obj/machinery/clonepod/experimental/pod = P.buffer
- if(pod.connected)
- pod.connected.DetachCloner(pod)
- AttachCloner(pod)
- else
- P.buffer = src
- to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-")
- return
- else
- return ..()
-
-/obj/machinery/computer/prototype_cloning/attack_hand(mob/user)
- if(..())
- return
- interact(user)
-
-/obj/machinery/computer/prototype_cloning/interact(mob/user)
- user.set_machine(src)
- add_fingerprint(user)
-
- if(..())
- return
-
- updatemodules(TRUE)
-
- var/dat = ""
- dat += "Refresh"
-
- dat += "Cloning Pod Status
"
- dat += "[temp]
"
-
- if (isnull(src.scanner) || !LAZYLEN(pods))
- dat += "Modules
"
- //dat += "Reload Modules"
- if (isnull(src.scanner))
- dat += "ERROR: No Scanner detected!
"
- if (!LAZYLEN(pods))
- dat += "ERROR: No Pod detected
"
-
- // Scan-n-Clone
- if (!isnull(src.scanner))
- var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
-
- dat += "Cloning
"
-
- dat += ""
- if(!scanner_occupant)
- dat += "Scanner Unoccupied"
- else if(loading)
- dat += "[scanner_occupant] => Scanning..."
- else
- scantemp = "Ready to Clone"
- dat += "[scanner_occupant] => [scantemp]"
- dat += "
"
-
- if(scanner_occupant)
- dat += "Clone"
- dat += "
[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]"
- else
- dat += "Clone"
-
- var/datum/browser/popup = new(user, "cloning", "Prototype Cloning System Control")
- popup.set_content(dat)
- popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
- popup.open()
-
-/obj/machinery/computer/prototype_cloning/Topic(href, href_list)
- if(..())
- return
-
- if(loading)
- return
-
- else if ((href_list["clone"]) && !isnull(scanner) && scanner.is_operational())
- scantemp = ""
-
- loading = TRUE
- updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
- say("Initiating scan...")
-
- spawn(20)
- clone_occupant(scanner.occupant)
- loading = FALSE
- updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
- //No locking an open scanner.
- else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
- if ((!scanner.locked) && (scanner.occupant))
- scanner.locked = TRUE
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else
- scanner.locked = FALSE
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
- else if (href_list["refresh"])
- updateUsrDialog()
- playsound(src, "terminal_type", 25, 0)
-
- add_fingerprint(usr)
- updateUsrDialog()
- return
-
-/obj/machinery/computer/prototype_cloning/proc/clone_occupant(occupant)
- var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
- var/datum/dna/dna
- if(ishuman(mob_occupant))
- var/mob/living/carbon/C = mob_occupant
- dna = C.has_dna()
- if(isbrain(mob_occupant))
- var/mob/living/brain/B = mob_occupant
- dna = B.stored_dna
-
- if(!istype(dna))
- scantemp = "Unable to locate valid genetic data."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- return
- if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
- scantemp = "Subject no longer contains the fundamental materials required to create a living clone."
- playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
- return
-
- var/clone_species
- if(dna.species)
- clone_species = dna.species
- else
- var/datum/species/rando_race = pick(GLOB.roundstart_races)
- clone_species = rando_race.type
-
- var/obj/machinery/clonepod/pod = GetAvailablePod()
- //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
- if(!LAZYLEN(pods))
- temp = "No Clonepods detected."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(!pod)
- temp = "No Clonepods available."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(pod.occupant)
- temp = "Cloning cycle already in progress."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else
- pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
- temp = "[mob_occupant.real_name] => Cloning data sent to pod."
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
-
diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm
index c56731b3d3..faab0df6e9 100644
--- a/code/game/objects/effects/contraband.dm
+++ b/code/game/objects/effects/contraband.dm
@@ -212,6 +212,11 @@
desc = "A heretical poster depicting the titular star of an equally heretical book."
icon_state = "poster4"
+/obj/structure/sign/poster/contraband/post_ratvar
+ name = "Post This Ratvar"
+ desc = "Oh what in the hell? Those cultists have animated paper technology and they use it for a meme?"
+ icon_state = "postvar"
+
/obj/structure/sign/poster/contraband/syndicate_recruitment
name = "Syndicate Recruitment"
desc = "See the galaxy! Shatter corrupt megacorporations! Join today!"
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index f94c8f3513..2fa48582f7 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -116,9 +116,9 @@
build_path = /obj/machinery/computer/cloning
var/list/records = list()
-/obj/item/circuitboard/computer/prototype_cloning
+/obj/item/circuitboard/computer/cloning/prototype
name = "Prototype Cloning (Computer Board)"
- build_path = /obj/machinery/computer/prototype_cloning
+ build_path = /obj/machinery/computer/cloning/prototype
/obj/item/circuitboard/computer/arcade/battle
name = "Arcade Battle (Computer Board)"
diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm
index 9d9409acf0..4960474d94 100644
--- a/code/game/objects/items/pet_carrier.dm
+++ b/code/game/objects/items/pet_carrier.dm
@@ -22,6 +22,11 @@
var/occupant_weight = 0
var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
+ var/entrance_name = "door" //name of the entrance to the item
+ var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this)
+ var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier
+ var/has_lock_sprites = TRUE //whether to load the lock overlays or not
+ var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
/obj/item/pet_carrier/Destroy()
if(occupants.len)
@@ -51,20 +56,20 @@
else
. += "It has nothing inside."
if(user.canUseTopic(src))
- . += "Activate it in your hand to [open ? "close" : "open"] its door."
+ . += "Activate it in your hand to [open ? "close" : "open"] its [entrance_name]."
if(!open)
- . += "Alt-click to [locked ? "unlock" : "lock"] its door."
+ . += "Alt-click to [locked ? "unlock" : "lock"] its [entrance_name]."
/obj/item/pet_carrier/attack_self(mob/living/user)
if(open)
- to_chat(user, "You close [src]'s door.")
+ to_chat(user, "You close [src]'s [entrance_name].")
playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE)
open = FALSE
else
if(locked)
to_chat(user, "[src] is locked!")
return
- to_chat(user, "You open [src]'s door.")
+ to_chat(user, "You open [src]'s [entrance_name].")
playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE)
open = TRUE
update_icon()
@@ -86,7 +91,7 @@
if(user.a_intent == INTENT_HARM)
return ..()
if(!open)
- to_chat(user, "You need to open [src]'s door!")
+ to_chat(user, "You need to open [src]'s [entrance_name]!")
return
if(target.mob_size > max_occupant_weight)
if(ishuman(target))
@@ -94,13 +99,15 @@
if(iscatperson(H))
to_chat(user, "You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.")
else
- to_chat(user, "Humans, generally, do not fit into pet carriers.")
+ to_chat(user, "Humans, generally, do not fit into [name]s.")
else
to_chat(user, "You get the feeling [target] isn't meant for a [name].")
return
if(user == target)
to_chat(user, "Why would you ever do that?")
return
+ if(ishostile(target) && !allows_hostiles && target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers
+ to_chat(user, "You have a feeling you shouldn't keep this as a pet.")
load_occupant(user, target)
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
@@ -110,8 +117,8 @@
remove_occupant(user)
return
else if(!locked)
- loc.visible_message("[user] pushes open the door to [src]!", \
- "[user] pushes open the door of [src]!")
+ loc.visible_message("[user] pushes open the [entrance_name] to [src]!", \
+ "[user] pushes open the [entrance_name] of [src]!")
open = TRUE
update_icon()
return
@@ -119,12 +126,19 @@
container_resist(user)
/obj/item/pet_carrier/container_resist(mob/living/user)
+ //don't do the whole resist timer thing if it's open!
+ if(open)
+ loc.visible_message("[user] climbs out of [src]!", \
+ "[user] jumps out of [src]!")
+ remove_occupant(user)
+ return
+
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.mob_size <= MOB_SIZE_SMALL)
- to_chat(user, "You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)")
- to_chat(loc, "You see [user] reach through the bars and fumble for the lock switch!")
- if(!do_after(user, rand(300, 400), target = user) || open || !locked || !(user in occupants))
+ to_chat(user, "You begin to try escaping the [src] and start fumbling for the lock switch... (This will take some time.)")
+ to_chat(loc, "You see [user] attempting to unlock the [src]!")
+ if(!do_after(user, rand(escape_time * 1.5, escape_time * 2), target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("[user] flips the lock switch on [src] by reaching through!", null, null, null, user)
to_chat(user, "Bingo! The lock pops open!")
@@ -132,12 +146,12 @@
playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE)
update_icon()
else
- loc.visible_message("[src] starts rattling as something pushes against the door!", null, null, null, user)
+ loc.visible_message("[src] starts rattling as something pushes against the [entrance_name]!", null, null, null, user)
to_chat(user, "You start pushing out of [src]... (This will take about 20 seconds.)")
- if(!do_after(user, 200, target = user) || open || !locked || !(user in occupants))
+ if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("[user] shoves out of [src]!", null, null, null, user)
- to_chat(user, "You shove open [src]'s door against the lock's resistance and fall out!")
+ to_chat(user, "You shove open [src]'s [entrance_name] against the lock's resistance and fall out!")
locked = FALSE
open = TRUE
update_icon()
@@ -151,7 +165,7 @@
/obj/item/pet_carrier/update_overlays()
. = ..()
- if(!open)
+ if(!open && has_lock_sprites)
. += "[locked ? "" : "un"]locked"
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
@@ -170,7 +184,7 @@
user.visible_message("[user] starts loading [target] into [src].", \
"You start loading [target] into [src]...", null, null, target)
to_chat(target, "[user] starts loading you into [user.p_their()] [name]!")
- if(!do_mob(user, target, 30))
+ if(!do_mob(user, target, load_time))
return
if(target in occupants)
return
@@ -192,9 +206,74 @@
/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
if(!(occupant in occupants) || !istype(occupant))
return
- occupant.forceMove(new_turf ? new_turf : drop_location())
+ occupant.forceMove(new_turf ? new_turf : get_turf(src))
occupants -= occupant
occupant_weight -= occupant.mob_size
occupant.setDir(SOUTH)
+//bluespace jar, a reskin of the pet carrier that can fit people and smashes when thrown
+/obj/item/pet_carrier/bluespace
+ name = "bluespace jar"
+ desc = "A jar, that seems to be bigger on the inside, somehow allowing lifeforms to fit through its narrow entrance."
+ open = FALSE //starts closed so it looks better on menus
+ icon_state = "bluespace_jar"
+ item_state = "bluespace_jar"
+ lefthand_file = ""
+ righthand_file = ""
+ max_occupant_weight = MOB_SIZE_HUMAN //can fit people, like a bluespace bodybag!
+ load_time = 40 //loading things into a jar takes longer than a regular pet carrier
+ entrance_name = "lid"
+ w_class = WEIGHT_CLASS_SMALL //it's a jar
+ throw_speed = 3
+ throw_range = 7
+ max_occupants = 1 //far less than a regular carrier or bluespace bodybag, because it can be thrown to release the contents
+ allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless
+ has_lock_sprites = FALSE //jar doesn't show the regular lock overlay
+ custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
+ escape_time = 10 //half the time of a bluespace bodybag
+ var/datum/gas_mixture/occupant_gas_supply
+
+/obj/item/pet_carrier/bluespace/update_icon_state()
+ if(open)
+ icon_state = "bluespace_jar_open"
+ else
+ icon_state = "bluespace_jar"
+
+/obj/item/pet_carrier/bluespace/throw_impact()
+ . = ..()
+ //delete the item upon impact, releasing the creature inside (this is handled by its deletion)
+ if(occupants.len)
+ loc.visible_message("The bluespace jar smashes, releasing [occupants[1]]!")
+ playsound(src, "shatter", 70, 1)
+ qdel(src)
+
+/obj/item/pet_carrier/bluespace/add_occupant(mob/living/occupant) //update the gas supply as required, this acts like magical internals
+ . = ..()
+ if(!occupant_gas_supply)
+ occupant_gas_supply = new
+ if(isanimal(occupant))
+ var/mob/living/simple_animal/animal = occupant
+ occupant_gas_supply.temperature = animal.minbodytemp //simple animals only care about temperature when their turf isnt a location
+ else
+ if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
+ ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
+ ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
+ ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
+ ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
+ ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
+
+/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant)
+ . = ..()
+ if(ishuman(occupant))
+ REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
+ REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
+ REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
+ REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
+ REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
+
+/obj/item/pet_carrier/bluespace/return_air()
+ if(!occupant_gas_supply)
+ occupant_gas_supply = new
+ return occupant_gas_supply
+
#undef pet_carrier_full
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index aac642a05e..2831311eff 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -326,6 +326,7 @@
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
custom_materials = list(/datum/material/iron=3000)
+ var/max_items = 7
/obj/item/storage/bag/tray/ComponentInitialize()
. = ..()
@@ -333,6 +334,7 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food, /obj/item/reagent_containers/glass, /datum/reagent/consumable, /obj/item/kitchen/knife, /obj/item/kitchen/rollingpin, /obj/item/kitchen/fork, /obj/item/storage/box)) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Kitchen Tools, and ingredient boxes.
STR.insert_preposition = "on"
+ STR.max_items = max_items
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
. = ..()
@@ -373,6 +375,14 @@
. = ..()
update_icon()
+//bluespace tray, holds more items
+/obj/item/storage/bag/tray/bluespace
+ name = "bluespace tray"
+ icon_state = "bluespace_tray"
+ desc = "A tray created using bluespace technology to fit more food on it."
+ max_items = 30 // far more items
+ custom_materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
+
/*
* Chemistry bag
*/
@@ -462,4 +472,4 @@
STR.max_combined_w_class = INFINITY
STR.max_items = 2
STR.display_numerical_stacking = TRUE
- STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
\ No newline at end of file
+ STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm
index f4f9bbbcfb..3d969e1a77 100644
--- a/code/modules/atmospherics/machinery/portable/canister.dm
+++ b/code/modules/atmospherics/machinery/portable/canister.dm
@@ -268,6 +268,7 @@ obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/ite
/obj/machinery/portable_atmospherics/canister/obj_break(damage_flag)
if((stat & BROKEN) || (flags_1 & NODECONSTRUCT_1))
return
+ stat |= BROKEN
canister_break()
/obj/machinery/portable_atmospherics/canister/proc/canister_break()
diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm
index 60f8cc179a..632d59187f 100644
--- a/code/modules/clothing/suits/toggles.dm
+++ b/code/modules/clothing/suits/toggles.dm
@@ -76,6 +76,7 @@
/obj/item/clothing/head/hooded
var/obj/item/clothing/suit/hooded/suit
+ dynamic_hair_suffix = ""
/obj/item/clothing/head/hooded/Destroy()
suit = null
diff --git a/code/modules/hydroponics/grown/peas.dm b/code/modules/hydroponics/grown/peas.dm
index 6229d98b2c..79d506cf56 100644
--- a/code/modules/hydroponics/grown/peas.dm
+++ b/code/modules/hydroponics/grown/peas.dm
@@ -61,6 +61,7 @@
filling_color = "#ee7bee"
bitesize_mod = 2
foodtype = VEGETABLES
+ juice_results = list (/datum/reagent/consumable/laughsyrup = 0)
tastes = list ("a prancing rabbit" = 1) //Vib Ribbon sends her regards.. wherever she is.
wine_power = 90
wine_flavor = "a vector-graphic rabbit dancing on your tongue"
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index ce4436a343..31f326fd53 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -23,6 +23,13 @@
heatmod = 0.5 // = 1/4x heat damage
burnmod = 0.5 // = 1/2x generic burn damage
species_language_holder = /datum/language_holder/jelly
+ mutant_brain = /obj/item/organ/brain/jelly
+
+/obj/item/organ/brain/jelly
+ name = "slime nucleus"
+ desc = "A slimey membranous mass from a slime person"
+ icon_state = "brain-slime"
+
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
diff --git a/code/modules/research/designs/bluespace_designs.dm b/code/modules/research/designs/bluespace_designs.dm
index 0d11b8e887..336dc4ec8e 100644
--- a/code/modules/research/designs/bluespace_designs.dm
+++ b/code/modules/research/designs/bluespace_designs.dm
@@ -95,3 +95,23 @@
build_path = /obj/item/storage/bag/ore/holding
category = list("Bluespace Designs")
departmental_flags = DEPARTMENTAL_FLAG_CARGO
+
+/datum/design/bluespace_tray
+ name = "Bluespace Tray"
+ desc = "A tray created using bluespace technology to fit more food on it."
+ id = "bluespace_tray"
+ build_type = PROTOLATHE
+ build_path = /obj/item/storage/bag/tray/bluespace
+ materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
+ category = list("Bluespace Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+
+/datum/design/bluespace_carrier
+ name = "Bluespace Jar"
+ desc = "A jar used to contain creatures, using the power of bluespace."
+ id = "bluespace_carrier"
+ build_type = PROTOLATHE
+ build_path = /obj/item/pet_carrier/bluespace
+ materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
+ category = list("Bluespace Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
\ No newline at end of file
diff --git a/code/modules/research/techweb/nodes/bluespace_nodes.dm b/code/modules/research/techweb/nodes/bluespace_nodes.dm
index 3aacc9fec5..b0705a0b76 100644
--- a/code/modules/research/techweb/nodes/bluespace_nodes.dm
+++ b/code/modules/research/techweb/nodes/bluespace_nodes.dm
@@ -13,7 +13,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
- design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic")
+ design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "bluespace_carrier")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
/datum/techweb_node/adv_bluespace
diff --git a/html/changelog.html b/html/changelog.html
index f12ab97b29..1d6318811e 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -50,6 +50,36 @@
-->
+
09 July 2020
+
timothyteakettle updated:
+
+ - bluespace tray added, allowing twice as many items as the regular tray, printable at the service lathe, researched through science
+ - bluespace jar added, a kind of pet carrier that allows human sized mobs inside, and smashes when thrown, researched and printed through science
+
+
+
08 July 2020
+
DeltaFire15 updated:
+
+ - The kill-once objective now works properly.
+
+
EmeraldSundisk updated:
+
+ - CogStation now has an apothecary
+ - Removes an outdated note on sleepers
+ - Readjusts CogStation's chemistry lab
+ - Slight area designation adjustments for Robotics
+ - The arrivals plaque should be readable now
+
+
Owai-Seek updated:
+
+ - Margarine, Chili Cheese Fries.
+ - Egg Wraps are now categorized under egg foods.
+ - Tuna Sandwich crafting/sprite is now visible.
+ - Icons for chicken, cooked chicken, steak, grilled carp, corndogs
+ - Icons for chili cheese fries, margarine, BLT sandwich
+ - (Unused) icons for raw meatballs, and lard
+
+
07 July 2020
KasparoVy updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 383bc23a00..0553c64ce7 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -26274,3 +26274,25 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
use custom sprite sizes so just ignore these changes.
- bugfix: Fixed the "Move it to the threshold" button; it now does what it says.
- tweak: Reworded some text to be clearer.
+2020-07-08:
+ DeltaFire15:
+ - bugfix: The kill-once objective now works properly.
+ EmeraldSundisk:
+ - rscadd: CogStation now has an apothecary
+ - rscdel: Removes an outdated note on sleepers
+ - tweak: Readjusts CogStation's chemistry lab
+ - tweak: Slight area designation adjustments for Robotics
+ - bugfix: The arrivals plaque should be readable now
+ Owai-Seek:
+ - rscadd: Margarine, Chili Cheese Fries.
+ - tweak: Egg Wraps are now categorized under egg foods.
+ - bugfix: Tuna Sandwich crafting/sprite is now visible.
+ - imageadd: Icons for chicken, cooked chicken, steak, grilled carp, corndogs
+ - imageadd: Icons for chili cheese fries, margarine, BLT sandwich
+ - imageadd: (Unused) icons for raw meatballs, and lard
+2020-07-09:
+ timothyteakettle:
+ - rscadd: bluespace tray added, allowing twice as many items as the regular tray,
+ printable at the service lathe, researched through science
+ - rscadd: bluespace jar added, a kind of pet carrier that allows human sized mobs
+ inside, and smashes when thrown, researched and printed through science
diff --git a/html/changelogs/AutoChangeLog-pr-12684.yml b/html/changelogs/AutoChangeLog-pr-12684.yml
deleted file mode 100644
index 4736c9544e..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12684.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-author: "Owai-Seek"
-delete-after: True
-changes:
- - rscadd: "Margarine, Chili Cheese Fries."
- - tweak: "Egg Wraps are now categorized under egg foods."
- - bugfix: "Tuna Sandwich crafting/sprite is now visible."
- - imageadd: "Icons for chicken, cooked chicken, steak, grilled carp, corndogs"
- - imageadd: "Icons for chili cheese fries, margarine, BLT sandwich"
- - imageadd: "(Unused) icons for raw meatballs, and lard"
diff --git a/html/changelogs/AutoChangeLog-pr-12697.yml b/html/changelogs/AutoChangeLog-pr-12697.yml
deleted file mode 100644
index 28c74fcb3e..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12697.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-author: "EmeraldSundisk"
-delete-after: True
-changes:
- - rscadd: "CogStation now has an apothecary"
- - rscdel: "Removes an outdated note on sleepers"
- - tweak: "Readjusts CogStation's chemistry lab"
- - tweak: "Slight area designation adjustments for Robotics"
- - bugfix: "The arrivals plaque should be readable now"
diff --git a/html/changelogs/AutoChangeLog-pr-12702.yml b/html/changelogs/AutoChangeLog-pr-12702.yml
deleted file mode 100644
index 5f95611fdd..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12702.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "DeltaFire15"
-delete-after: True
-changes:
- - bugfix: "The kill-once objective now works properly."
diff --git a/html/changelogs/AutoChangeLog-pr-12707.yml b/html/changelogs/AutoChangeLog-pr-12707.yml
new file mode 100644
index 0000000000..49b71ea8f7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12707.yml
@@ -0,0 +1,5 @@
+author: "Chiirno"
+delete-after: True
+changes:
+ - code_imp: "Gave jellypeople a unique brain object /obj/item/organ/brain/jelly"
+ - imageadd: "added an icon for jellypeople brains."
diff --git a/html/changelogs/AutoChangeLog-pr-12708.yml b/html/changelogs/AutoChangeLog-pr-12708.yml
new file mode 100644
index 0000000000..a7c8d8f40d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12708.yml
@@ -0,0 +1,5 @@
+author: "EmeraldSundisk"
+delete-after: True
+changes:
+ - rscadd: "Adds a pool to PubbyStation"
+ - tweak: "Slight adjustments to the surrounding area as to fit said pool"
diff --git a/html/changelogs/AutoChangeLog-pr-12710.yml b/html/changelogs/AutoChangeLog-pr-12710.yml
new file mode 100644
index 0000000000..0adf58c8c2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12710.yml
@@ -0,0 +1,4 @@
+author: "Sneakyrat6"
+delete-after: True
+changes:
+ - bugfix: "Fixes hair falling out of hoodies."
diff --git a/html/changelogs/AutoChangeLog-pr-12712.yml b/html/changelogs/AutoChangeLog-pr-12712.yml
new file mode 100644
index 0000000000..f2da8210f3
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12712.yml
@@ -0,0 +1,4 @@
+author: "TheObserver-sys"
+delete-after: True
+changes:
+ - bugfix: "Actually adds the juice reagent to make laugh peas donuts."
diff --git a/icons/obj/contraband.dmi b/icons/obj/contraband.dmi
index a1d5bc5900..a6c554f7da 100644
Binary files a/icons/obj/contraband.dmi and b/icons/obj/contraband.dmi differ
diff --git a/icons/obj/food/containers.dmi b/icons/obj/food/containers.dmi
index 641715fd87..ceda2fc9eb 100644
Binary files a/icons/obj/food/containers.dmi and b/icons/obj/food/containers.dmi differ
diff --git a/icons/obj/pet_carrier.dmi b/icons/obj/pet_carrier.dmi
index 340636056c..b3c11be98f 100644
Binary files a/icons/obj/pet_carrier.dmi and b/icons/obj/pet_carrier.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index e998ce442d..3996f0ead2 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
index 37ec1ee69f..8ef302e904 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
@@ -63,7 +63,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
startHunger = M.nutrition
if(pollStarted == FALSE)
pollStarted = TRUE
- candies = pollGhostCandidates("Do you want and agree to play as a clone of [M], respect their character and not engage in ERP without permission from the original?", ignore_category = POLL_IGNORE_CLONE)
+ candies = pollGhostCandidates("Do you want to play as [M]'s defective clone? (Don't ERP without permission from the original)", ignore_category = POLL_IGNORE_CLONE)
log_reagent("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.")
if(20 to INFINITY)
if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there!
diff --git a/tgstation.dme b/tgstation.dme
index 0aff0b16d5..01d2d5f982 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -745,7 +745,6 @@
#include "code\game\machinery\dna_scanner.dm"
#include "code\game\machinery\doppler_array.dm"
#include "code\game\machinery\droneDispenser.dm"
-#include "code\game\machinery\exp_cloner.dm"
#include "code\game\machinery\firealarm.dm"
#include "code\game\machinery\flasher.dm"
#include "code\game\machinery\gulag_item_reclaimer.dm"