diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
index 6c58eaa8c8fb..32e76893cd9d 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
@@ -1305,7 +1305,7 @@
/obj/effect/turf_decal/tile/brown{
dir = 1
},
-/obj/machinery/photocopier/gratis,
+/obj/machinery/photocopier/gratis/prebuilt,
/turf/open/floor/iron,
/area/ruin/syndicate_lava_base/cargo)
"gQ" = (
diff --git a/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm b/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm
index c0125ed5398d..c9da64d2e8c3 100644
--- a/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm
+++ b/_maps/RandomRuins/SpaceRuins/allamericandiner.dmm
@@ -371,7 +371,7 @@
/turf/open/floor/iron,
/area/ruin/space/has_grav/allamericandiner)
"tg" = (
-/obj/machinery/photocopier/gratis,
+/obj/machinery/photocopier/gratis/prebuilt,
/obj/structure/sign/flag/ssc/directional/north,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/iron/grimy,
diff --git a/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm b/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm
index 995a736c620e..498a13896021 100644
--- a/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm
+++ b/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm
@@ -589,7 +589,7 @@
/turf/open/floor/iron/showroomfloor,
/area/ruin/space/has_grav/derelictsulaco)
"tp" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/pod/light,
diff --git a/_maps/RandomRuins/SpaceRuins/hellfactory.dmm b/_maps/RandomRuins/SpaceRuins/hellfactory.dmm
index 5e2038ac70a1..aa9b462d2c6d 100644
--- a/_maps/RandomRuins/SpaceRuins/hellfactory.dmm
+++ b/_maps/RandomRuins/SpaceRuins/hellfactory.dmm
@@ -182,7 +182,7 @@
/turf/open/floor/plastic,
/area/ruin/space/has_grav/hellfactory)
"aE" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/ruin/space/has_grav/hellfactoryoffice)
"aF" = (
diff --git a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm
index c338834ad7c3..e83499a74091 100644
--- a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm
+++ b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm
@@ -1635,7 +1635,7 @@
/turf/open/floor/engine,
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
"Lr" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
"Lw" = (
diff --git a/_maps/RandomRuins/SpaceRuins/meatderelict.dmm b/_maps/RandomRuins/SpaceRuins/meatderelict.dmm
index 3e4bece11e8e..7e1fcc4803b3 100644
--- a/_maps/RandomRuins/SpaceRuins/meatderelict.dmm
+++ b/_maps/RandomRuins/SpaceRuins/meatderelict.dmm
@@ -2324,7 +2324,7 @@
/turf/open/indestructible/meat,
/area/ruin/space/has_grav/powered/biooutpost/vault)
"Ue" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/purple/opposingcorners,
/turf/open/indestructible/white,
/area/ruin/space/has_grav/powered/biooutpost)
diff --git a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
index ea2ca46c0921..d2cf049c0a57 100644
--- a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
+++ b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
@@ -840,7 +840,7 @@
/obj/structure/fluff/paper{
dir = 10
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/indestructible/paper,
/area/ruin/space/has_grav/powered)
"cq" = (
diff --git a/_maps/RandomRuins/SpaceRuins/waystation.dmm b/_maps/RandomRuins/SpaceRuins/waystation.dmm
index 5642e9b85c3c..022e4889c46e 100644
--- a/_maps/RandomRuins/SpaceRuins/waystation.dmm
+++ b/_maps/RandomRuins/SpaceRuins/waystation.dmm
@@ -218,7 +218,7 @@
/area/ruin/space/has_grav/waystation/cargobay)
"ea" = (
/obj/effect/turf_decal/tile/brown/half/contrasted,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/iron,
/area/ruin/space/has_grav/waystation/cargooffice)
@@ -946,7 +946,7 @@
/turf/open/floor/iron,
/area/ruin/space/has_grav/waystation/dorms)
"pl" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/ruin/space/has_grav/waystation/qm)
"pm" = (
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 6a77ae8388d7..8d69c91deff6 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -1586,7 +1586,7 @@
/area/station/security/checkpoint/arrivals)
"amx" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/button/door/directional/east{
id = "left_arrivals_shutters";
name = "Left Arrivals Hallway Shutters";
@@ -8531,7 +8531,7 @@
/turf/open/floor/iron/dark,
/area/station/security/detectives_office)
"bJm" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/status_display/ai/directional/north,
/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/bot_white,
@@ -17527,7 +17527,7 @@
dir = 8
},
/obj/machinery/airalarm/directional/south,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/science/research)
"ddW" = (
@@ -18773,7 +18773,7 @@
name = "medbay camera";
network = list("ss13","medbay")
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/medical/medbay)
"dlO" = (
@@ -28526,7 +28526,7 @@
/turf/open/floor/iron,
/area/station/hallway/primary/central/aft)
"ffd" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/requests_console/directional/north{
department = "Head of Security's Desk";
name = "Head of Security's Requests Console"
@@ -32609,7 +32609,7 @@
/area/station/ai_monitored/turret_protected/aisat_interior)
"goP" = (
/obj/item/radio/intercom/directional/north,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/checker,
/area/station/hallway/secondary/service)
"goR" = (
@@ -41737,7 +41737,7 @@
/turf/open/floor/iron,
/area/station/hallway/secondary/entry)
"iKf" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/east,
/turf/open/floor/carpet/royalblack,
/area/station/service/chapel/office)
@@ -45268,7 +45268,7 @@
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/ce)
"jNF" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/tile/neutral/fourcorners,
/turf/open/floor/iron/dark,
@@ -50708,7 +50708,7 @@
/obj/effect/decal/cleanable/cobweb,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/newspaper{
pixel_x = 3;
pixel_y = 3
@@ -51895,7 +51895,7 @@
/turf/open/floor/iron,
/area/station/commons/storage/tools)
"lEN" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/computer/security/telescreen/entertainment/directional/west,
/turf/open/floor/wood,
/area/station/command/heads_quarters/captain/private)
@@ -52695,7 +52695,7 @@
/turf/open/floor/plating,
/area/station/maintenance/department/security)
"lSF" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/computer/security/telescreen/entertainment/directional/north,
/turf/open/floor/wood/large,
/area/station/service/library)
@@ -56419,7 +56419,7 @@
/turf/open/floor/iron,
/area/station/engineering/main)
"mUF" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/power/apc/auto_name/directional/north,
/obj/structure/cable,
/obj/effect/turf_decal/bot_white,
@@ -56697,7 +56697,7 @@
/area/station/command/heads_quarters/rd)
"mYI" = (
/obj/machinery/light_switch/directional/north,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/light/directional/north,
/turf/open/floor/wood,
/area/station/command/heads_quarters/captain)
@@ -60653,7 +60653,7 @@
/turf/open/floor/iron/dark,
/area/station/science/robotics/lab)
"ocD" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/structure/sign/poster/official/work_for_a_future/directional/east,
/turf/open/floor/wood,
/area/station/command/heads_quarters/hop)
@@ -70156,7 +70156,7 @@
/area/station/maintenance/department/science)
"qKC" = (
/obj/effect/turf_decal/stripes/white/line,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/engineering/break_room)
"qKF" = (
@@ -73946,7 +73946,7 @@
/turf/open/floor/iron,
/area/station/engineering/atmos)
"rPg" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/decal/cleanable/dirt,
/obj/machinery/light/small/broken/directional/south,
/turf/open/floor/plating,
@@ -77136,7 +77136,7 @@
/area/station/service/kitchen/abandoned)
"sKa" = (
/obj/structure/cable,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/command/meeting_room/council)
"sKd" = (
@@ -78639,7 +78639,7 @@
/area/station/hallway/primary/central/fore)
"tiI" = (
/obj/machinery/newscaster/directional/east,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/bot_white,
/obj/machinery/light/small/directional/east,
/obj/effect/turf_decal/tile/neutral/fourcorners,
@@ -80010,7 +80010,7 @@
/turf/open/floor/iron,
/area/station/cargo/storage)
"tEy" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/status_display/evac/directional/east,
/obj/machinery/camera/directional/east{
c_tag = "Lawyer's Office"
@@ -80606,7 +80606,7 @@
/turf/open/floor/iron/dark,
/area/station/science/genetics)
"tMm" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/south,
/obj/effect/turf_decal/box/white,
/obj/effect/turf_decal/tile/neutral/fourcorners,
@@ -83196,7 +83196,7 @@
/obj/effect/turf_decal/siding/wood{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/station/commons/vacant_room/office)
"uyF" = (
@@ -84305,7 +84305,7 @@
/turf/open/floor/iron/dark,
/area/station/engineering/main)
"uOw" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/brown/half/contrasted{
dir = 8
},
@@ -91781,7 +91781,7 @@
/turf/open/floor/iron/dark,
/area/station/security/courtroom)
"wPU" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/brown/half/contrasted{
dir = 1
},
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index 3f2cd29fc509..8fdff6e0d46e 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -193,7 +193,7 @@
/area/station/science/xenobiology)
"adZ" = (
/obj/effect/turf_decal/tile/brown/fourcorners,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/engineering/lobby)
"aee" = (
@@ -17599,7 +17599,7 @@
/turf/open/floor/iron,
/area/station/hallway/primary/starboard)
"fgm" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/structure/sign/poster/official/random/directional/east,
/turf/open/floor/wood,
/area/station/service/library)
@@ -23772,7 +23772,7 @@
/turf/open/floor/iron,
/area/station/hallway/primary/starboard)
"hbp" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/command/meeting_room)
"hbt" = (
@@ -24476,7 +24476,7 @@
/turf/open/openspace,
/area/station/science/xenobiology)
"hnP" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/cafeteria{
dir = 8
},
@@ -25303,7 +25303,7 @@
},
/area/station/science/research)
"hAo" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood/corner,
/obj/structure/sign/calendar/directional/west,
/turf/open/floor/wood,
@@ -28536,7 +28536,7 @@
/obj/structure/disposalpipe/segment{
dir = 5
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/medical/medbay/aft)
"iyL" = (
@@ -33506,7 +33506,7 @@
/turf/open/floor/iron,
/area/station/hallway/primary/starboard)
"kaw" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/north,
/turf/open/floor/iron,
/area/station/cargo/office)
@@ -61156,7 +61156,7 @@
/area/station/science/ordnance)
"sbi" = (
/obj/machinery/newscaster/directional/north,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron,
/area/station/command/heads_quarters/hop)
"sbv" = (
@@ -73360,7 +73360,7 @@
/turf/open/floor/plating,
/area/station/maintenance/aft/greater)
"vLt" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/red/half/contrasted{
dir = 8
},
@@ -73954,7 +73954,7 @@
/obj/machinery/light_switch/directional/west{
pixel_y = 5
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/airalarm/directional/north,
/turf/open/floor/wood,
/area/station/hallway/secondary/service)
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index ee1cdc76a9d0..bb4f167d9440 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -831,7 +831,7 @@
/turf/open/floor/plating/airless,
/area/space/nearstation)
"aeM" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
@@ -13162,7 +13162,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/bot,
/turf/open/floor/iron/dark,
/area/station/security/detectives_office)
@@ -28199,7 +28199,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/blue{
dir = 1
},
@@ -39173,7 +39173,7 @@
/area/station/maintenance/starboard/aft)
"imu" = (
/obj/machinery/light/small/directional/west,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -52088,7 +52088,7 @@
/area/station/security/prison/safe)
"mAS" = (
/obj/effect/turf_decal/tile/red,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/structure/sign/poster/official/space_cops/directional/south,
/turf/open/floor/iron,
/area/station/security/office)
@@ -54435,7 +54435,7 @@
/obj/structure/sign/painting/library{
pixel_x = 32
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/south,
/obj/effect/turf_decal/box/white,
/turf/open/floor/iron/dark,
@@ -58767,7 +58767,7 @@
/turf/open/floor/iron,
/area/station/cargo/storage)
"oMj" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
@@ -76110,7 +76110,7 @@
"uou" = (
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/cable,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -78254,7 +78254,7 @@
/area/station/cargo/warehouse)
"vaK" = (
/obj/effect/decal/cleanable/cobweb/cobweb2,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/newspaper{
pixel_x = 4;
pixel_y = 4
@@ -86702,7 +86702,7 @@
},
/obj/structure/cable,
/obj/machinery/power/apc/auto_name/directional/north,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/hos)
"xJP" = (
diff --git a/_maps/map_files/LimaStation/LimaStation.dmm b/_maps/map_files/LimaStation/LimaStation.dmm
index 2b0f7a1c944e..6a3d4b8040f0 100644
--- a/_maps/map_files/LimaStation/LimaStation.dmm
+++ b/_maps/map_files/LimaStation/LimaStation.dmm
@@ -5752,7 +5752,7 @@
/area/station/security/lockers)
"bTN" = (
/obj/machinery/firealarm/directional/east,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark/side{
dir = 4
},
@@ -6917,7 +6917,7 @@
/turf/open/floor/wood,
/area/station/service/library)
"cra" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/service/library)
"crf" = (
@@ -10831,7 +10831,7 @@
/obj/structure/secure_safe{
pixel_x = -23
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/commons/vacant_room/office)
"dEN" = (
@@ -17654,7 +17654,7 @@
/turf/open/floor/iron/dark,
/area/station/engineering/atmos/experiment_room)
"fQB" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/newscaster/directional/south,
/obj/effect/turf_decal/bot_white,
/obj/effect/turf_decal/siding/wood{
@@ -29553,7 +29553,7 @@
/turf/open/floor/iron/grimy,
/area/station/service/library)
"jEc" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/status_display/evac/directional/west,
/obj/machinery/firealarm/directional/south,
/turf/open/floor/iron/grimy,
@@ -39365,7 +39365,7 @@
},
/area/station/service/bar)
"mHl" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood{
dir = 1
},
@@ -55167,7 +55167,7 @@
/turf/open/floor/iron/sepia,
/area/station/hallway/secondary/service)
"rvi" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/status_display/supply{
pixel_y = 30
},
@@ -66132,7 +66132,7 @@
/area/station/hallway/secondary/exit)
"uMU" = (
/obj/machinery/status_display/ai/directional/west,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/structure/cable,
/obj/effect/turf_decal/bot_white,
/turf/open/floor/iron/dark/telecomms,
@@ -68714,7 +68714,7 @@
/turf/closed/wall/r_wall,
/area/station/medical/abandoned)
"vHB" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood{
dir = 4
},
@@ -69387,7 +69387,7 @@
/obj/structure/secure_safe/hos{
pixel_y = 34
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/hos)
"vTG" = (
@@ -73258,7 +73258,7 @@
/turf/open/floor/engine,
/area/station/engineering/supermatter)
"xfM" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/trimline/red/filled/line{
dir = 8
},
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index fa683179a155..5fbbe49938c2 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -13216,7 +13216,7 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{
dir = 1
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/south,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hos)
@@ -17780,7 +17780,7 @@
"eJb" = (
/obj/machinery/airalarm/directional/south,
/obj/effect/turf_decal/stripes/corner,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/yellow/half/contrasted,
/turf/open/floor/iron,
/area/station/engineering/break_room)
@@ -20446,7 +20446,7 @@
/area/station/science/xenobiology)
"fFD" = (
/obj/structure/cable,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hop)
"fFJ" = (
@@ -21688,7 +21688,7 @@
/turf/open/floor/carpet,
/area/station/service/theater)
"gdY" = (
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 3
},
/turf/open/floor/wood,
@@ -27647,7 +27647,7 @@
/turf/open/floor/iron,
/area/station/engineering/atmos)
"isH" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/science/research)
"isK" = (
@@ -32142,7 +32142,7 @@
/area/station/maintenance/port/fore)
"kjv" = (
/obj/effect/decal/cleanable/cobweb,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/service/library)
"kjG" = (
@@ -32872,7 +32872,7 @@
/turf/open/floor/iron,
/area/station/commons/locker)
"kyN" = (
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 3
},
/turf/open/floor/iron/dark,
@@ -34266,7 +34266,7 @@
/obj/effect/turf_decal/trimline/blue/filled/line{
dir = 5
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/medical/office)
"lcd" = (
@@ -54456,7 +54456,7 @@
/turf/open/floor/plating,
/area/station/maintenance/port/aft)
"sJV" = (
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 3
},
/obj/effect/turf_decal/tile/red/half/contrasted{
@@ -54635,7 +54635,7 @@
/turf/open/floor/iron/dark,
/area/station/service/chapel)
"sOr" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/camera/directional/east{
c_tag = "Law Office"
},
@@ -64771,7 +64771,7 @@
/turf/open/floor/carpet,
/area/station/command/heads_quarters/hop)
"wNe" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/brown/anticorner/contrasted{
dir = 8
},
diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm
index a503bca5c450..2f537e54506e 100644
--- a/_maps/map_files/NebulaStation/NebulaStation.dmm
+++ b/_maps/map_files/NebulaStation/NebulaStation.dmm
@@ -4764,7 +4764,7 @@
/turf/open/floor/iron/dark,
/area/station/medical/morgue)
"aKP" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/bot,
/obj/structure/sign/calendar/directional/north,
/turf/open/floor/iron/dark/textured_large,
@@ -7074,7 +7074,7 @@
},
/area/station/engineering/atmos/storage)
"bcE" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/bot_white,
/turf/open/floor/iron/dark/textured,
/area/station/security/office)
@@ -7575,7 +7575,7 @@
dir = 1
},
/obj/effect/turf_decal/siding/wood,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/north,
/turf/open/floor/wood/large,
/area/station/security/detectives_office)
@@ -28968,7 +28968,7 @@
/obj/effect/turf_decal/siding/wood{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/camera/autoname/directional/east,
/turf/open/floor/wood/large,
/area/station/service/lawoffice)
@@ -29263,7 +29263,7 @@
/obj/effect/turf_decal/siding/wood/corner{
dir = 8
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood/large,
/area/station/service/library)
"eqr" = (
@@ -32849,7 +32849,7 @@
/turf/open/floor/iron/dark,
/area/station/cargo/storage)
"eSx" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/power/apc/auto_name/directional/north,
/obj/structure/cable,
/turf/open/floor/iron/dark,
@@ -34560,7 +34560,7 @@
/area/station/maintenance/port/aft)
"ffC" = (
/obj/effect/turf_decal/siding/wood/end,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood/large,
/area/station/service/chapel/office)
"ffE" = (
@@ -45004,7 +45004,7 @@
/turf/open/floor/iron/dark/textured,
/area/station/commons/fitness/recreation)
"gIo" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood{
dir = 5
},
@@ -50104,7 +50104,7 @@
dir = 10
},
/obj/machinery/firealarm/directional/south,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/cargo/office)
"hvR" = (
@@ -70321,7 +70321,7 @@
/turf/open/floor/iron/dark,
/area/station/hallway/primary/port)
"ksS" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/structure/sign/flag/ssc/directional/south,
/turf/open/floor/iron/dark,
/area/station/command/meeting_room)
@@ -75122,7 +75122,7 @@
dir = 4
},
/obj/machinery/light_switch/directional/west,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/command)
"lfg" = (
@@ -82169,7 +82169,7 @@
/obj/effect/turf_decal/siding/wood{
dir = 6
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood/large,
/area/station/command/heads_quarters/ce)
"mkx" = (
@@ -84746,7 +84746,7 @@
/obj/effect/turf_decal/siding/thinplating_new/dark/corner{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/camera/autoname/directional/south,
/turf/open/floor/iron/dark/diagonal,
/area/station/engineering/lobby)
@@ -99845,7 +99845,7 @@
/obj/effect/turf_decal/siding/wood/corner{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood/large,
/area/station/service/library/upper)
"oQA" = (
@@ -123360,7 +123360,7 @@
/obj/effect/turf_decal/siding/wood{
dir = 9
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/toy/figure/hos{
pixel_y = 12;
pixel_x = 3
@@ -140328,7 +140328,7 @@
/turf/open/floor/iron/dark,
/area/station/hallway/secondary/service)
"uVy" = (
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 4
},
/obj/effect/turf_decal/siding/wood{
@@ -142364,7 +142364,7 @@
},
/obj/effect/turf_decal/trimline/white/line,
/obj/structure/table/reinforced/rglass,
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 4
},
/turf/open/floor/iron/dark/textured_large,
@@ -150554,7 +150554,7 @@
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"wwD" = (
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 3
},
/obj/machinery/newscaster/directional/north,
@@ -151376,7 +151376,7 @@
/turf/open/misc/asteroid/airless,
/area/space/nearstation)
"wCZ" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood{
dir = 6
},
@@ -157183,7 +157183,7 @@
},
/obj/machinery/airalarm/directional/east,
/obj/structure/table/glass,
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 5
},
/turf/open/floor/iron/white,
diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm
index 8aca9bf29ad1..bb83ed43d2c0 100644
--- a/_maps/map_files/NorthStar/north_star.dmm
+++ b/_maps/map_files/NorthStar/north_star.dmm
@@ -9869,7 +9869,7 @@
/turf/open/floor/iron/white,
/area/station/medical/office)
"cuK" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/hop)
"cuL" = (
@@ -41052,7 +41052,7 @@
/turf/open/floor/engine,
/area/station/maintenance/floor4/starboard/aft)
"kFJ" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/camera/autoname/directional/north,
/obj/machinery/light_switch/directional/north,
/turf/open/floor/wood/tile,
@@ -50770,7 +50770,7 @@
},
/area/station/commons/fitness/recreation)
"naI" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/purple/opposingcorners,
/turf/open/floor/iron/white,
/area/station/science/circuits)
@@ -53740,7 +53740,7 @@
/turf/open/floor/iron/dark,
/area/station/hallway/floor4/aft)
"nMD" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/half{
dir = 1
},
@@ -54640,7 +54640,7 @@
/turf/open/floor/iron,
/area/station/hallway/floor3/aft)
"nXJ" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/science/lower)
"nXO" = (
@@ -55727,7 +55727,7 @@
"omG" = (
/obj/effect/turf_decal/bot,
/obj/effect/turf_decal/bot,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark/textured_large,
/area/station/service/library/printer)
"omK" = (
@@ -57408,7 +57408,7 @@
/turf/open/floor/iron/dark/smooth_large,
/area/station/engineering/storage/tech)
"oKD" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/requests_console/directional/west{
department = "Detective";
name = "Detective Requests Console"
@@ -58506,7 +58506,7 @@
"oYL" = (
/obj/machinery/power/apc/auto_name/directional/north,
/obj/structure/cable,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/carpet,
/area/station/command/heads_quarters/captain)
"oYT" = (
@@ -61804,7 +61804,7 @@
},
/obj/structure/window/reinforced/spawner/directional/west,
/obj/machinery/status_display/ai/directional/south,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark/side{
dir = 8
},
@@ -70343,7 +70343,7 @@
/turf/open/floor/plating,
/area/station/maintenance/floor4/port/aft)
"sfR" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/wood/parquet,
/area/station/service/lawoffice)
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 6964f67be16d..181d04a347bb 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -360,7 +360,7 @@
/obj/effect/turf_decal/tile/neutral/half/contrasted{
dir = 8
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/command/bridge)
"abn" = (
@@ -576,6 +576,7 @@
dir = 2
},
/obj/machinery/meter/layer4,
+/obj/structure/cable,
/turf/open/floor/plating,
/area/station/maintenance/solars/port/fore)
"abU" = (
@@ -1620,7 +1621,7 @@
/turf/open/floor/iron/dark/side,
/area/station/command/heads_quarters/hop)
"aeL" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/dark/side,
/area/station/command/heads_quarters/hop)
@@ -2288,11 +2289,18 @@
/area/station/command/heads_quarters/hop)
"agr" = (
/obj/structure/table/wood,
-/obj/item/paper_bin,
+/obj/item/paper_bin{
+ pixel_y = 2;
+ pixel_x = 2
+ },
/obj/item/pen,
/obj/item/stamp/head/hop,
/obj/effect/mapping_helpers/broken_floor,
/obj/structure/cable,
+/obj/item/ashtray{
+ pixel_y = -5;
+ pixel_x = -8
+ },
/turf/open/floor/wood,
/area/station/command/heads_quarters/hop)
"ags" = (
@@ -2492,6 +2500,10 @@
/obj/item/folder/blue,
/obj/item/melee/chainofcommand,
/obj/item/stamp/head/captain,
+/obj/item/ashtray{
+ pixel_y = 12;
+ pixel_x = -6
+ },
/turf/open/floor/carpet/royalblue,
/area/station/command/heads_quarters/captain/private)
"agR" = (
@@ -2786,6 +2798,10 @@
/obj/structure/table/wood,
/obj/item/folder/red,
/obj/item/stamp/head/hos,
+/obj/item/ashtray{
+ pixel_y = 12;
+ pixel_x = -6
+ },
/turf/open/floor/carpet/red,
/area/station/command/heads_quarters/hos)
"ahF" = (
@@ -2837,7 +2853,7 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/machinery/newscaster/directional/south,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/station/command/heads_quarters/captain/private)
"ahM" = (
@@ -3614,7 +3630,7 @@
/obj/effect/turf_decal/tile/brown{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron,
/area/station/cargo/storage)
"ajO" = (
@@ -3630,7 +3646,7 @@
/turf/open/floor/plating,
/area/station/security/prison)
"ajR" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/firealarm/directional/west{
pixel_y = -5
},
@@ -3699,6 +3715,10 @@
dir = 8
},
/obj/machinery/newscaster/directional/east,
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = -7
+ },
/turf/open/floor/iron/dark,
/area/station/hallway/primary/fore)
"ajW" = (
@@ -4701,6 +4721,10 @@
c_tag = "Engineering - Chief Engineer's Office";
network = list("ss13","engine","heads")
},
+/obj/item/ashtray{
+ pixel_y = -5;
+ pixel_x = -8
+ },
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/ce)
"amG" = (
@@ -5610,6 +5634,10 @@
},
/obj/item/gavelhammer,
/obj/machinery/airalarm/directional/south,
+/obj/item/ashtray{
+ pixel_y = -4;
+ pixel_x = -2
+ },
/turf/open/floor/carpet/green,
/area/station/service/lawoffice)
"aoE" = (
@@ -5840,13 +5868,6 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron,
/area/station/cargo/miningdock)
-"apn" = (
-/obj/effect/turf_decal/stripes/line,
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
-/turf/open/floor/iron,
-/area/station/cargo/miningdock)
"apo" = (
/obj/effect/turf_decal/stripes/line{
dir = 6
@@ -7418,7 +7439,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/mapping_helpers/broken_floor,
/obj/structure/table/wood,
-/obj/item/stack/medical/gauze/improvised,
+/obj/item/stack/medical/wrap/gauze/improvised,
/obj/item/restraints/handcuffs/cable,
/turf/open/floor/wood,
/area/station/maintenance/department/science)
@@ -7482,7 +7503,7 @@
"atC" = (
/obj/effect/decal/cleanable/cobweb,
/obj/effect/mapping_helpers/broken_floor,
-/obj/machinery/photocopier/gratis,
+/obj/machinery/photocopier/gratis/prebuilt,
/obj/machinery/airalarm/directional/west,
/turf/open/floor/wood,
/area/station/maintenance/department/science)
@@ -8038,6 +8059,10 @@
/obj/effect/turf_decal/siding/wood{
dir = 8
},
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = 5
+ },
/turf/open/floor/iron/dark/side{
dir = 8
},
@@ -8504,6 +8529,7 @@
"awX" = (
/obj/structure/table/reinforced,
/obj/effect/turf_decal/tile/neutral,
+/obj/item/ashtray/random_contents,
/turf/open/floor/iron/dark/side{
dir = 4
},
@@ -9178,6 +9204,10 @@
/obj/effect/turf_decal/siding/wood{
dir = 8
},
+/obj/item/ashtray{
+ pixel_y = -4;
+ pixel_x = 5
+ },
/turf/open/floor/iron/dark/side{
dir = 8
},
@@ -9877,6 +9907,10 @@
/obj/structure/table/reinforced,
/obj/item/folder/red,
/obj/effect/turf_decal/stripes/line,
+/obj/item/ashtray{
+ pixel_y = -3;
+ pixel_x = -8
+ },
/turf/open/floor/iron,
/area/station/hallway/secondary/exit/departure_lounge)
"aBg" = (
@@ -10843,6 +10877,7 @@
"aEa" = (
/obj/structure/table,
/obj/effect/turf_decal/delivery,
+/obj/item/storage/medkit/emergency,
/turf/open/floor/iron/dark/side{
dir = 4
},
@@ -11168,6 +11203,10 @@
name = "Station Intercom";
pixel_y = -26
},
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = 5
+ },
/turf/open/floor/iron/dark/side,
/area/station/service/theater)
"aEU" = (
@@ -11423,9 +11462,8 @@
/obj/effect/turf_decal/stripes/line{
dir = 8
},
-/obj/machinery/atmospherics/components/unary/airlock_pump/unbolt_only{
- dir = 8
- },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron,
/area/station/maintenance/department/cargo)
"aFC" = (
@@ -11486,7 +11524,6 @@
/obj/structure/extinguisher_cabinet{
pixel_x = -26
},
-/obj/item/kirbyplants/organic/plant22,
/obj/machinery/camera/directional/west{
c_tag = "Cafeteria - Aft";
network = list("ss13","service")
@@ -11535,6 +11572,10 @@
/obj/item/storage/fancy/donut_box{
pixel_y = 15
},
+/obj/item/ashtray{
+ pixel_y = 3;
+ pixel_x = -4
+ },
/turf/open/floor/iron,
/area/station/service/kitchen)
"aFR" = (
@@ -12273,6 +12314,7 @@
},
/obj/machinery/status_display/ai/directional/east,
/obj/machinery/light/directional/east,
+/obj/item/kirbyplants/organic/plant21,
/turf/open/floor/iron,
/area/station/service/cafeteria)
"aHW" = (
@@ -12654,6 +12696,7 @@
},
/obj/effect/turf_decal/tile/red/opposingcorners,
/obj/machinery/newscaster/directional/east,
+/obj/machinery/restaurant_portal/restaurant,
/turf/open/floor/iron,
/area/station/service/cafeteria)
"aIR" = (
@@ -12766,6 +12809,10 @@
pixel_y = 7;
pixel_x = 7
},
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = -8
+ },
/turf/open/floor/iron/dark,
/area/station/command/heads_quarters/cmo)
"aJg" = (
@@ -13105,9 +13152,9 @@
dir = 8
},
/obj/effect/turf_decal/tile/red/opposingcorners,
-/obj/item/kirbyplants/organic/plant21,
/obj/structure/sign/poster/official/random/directional/east,
/obj/effect/landmark/start/hangover,
+/obj/structure/closet/crate/bin,
/turf/open/floor/iron,
/area/station/service/cafeteria)
"aJY" = (
@@ -13174,6 +13221,10 @@
req_access = list("cargo")
},
/obj/effect/turf_decal/delivery,
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = -8
+ },
/turf/open/floor/iron,
/area/station/hallway/secondary/exit/departure_lounge)
"aKj" = (
@@ -13193,6 +13244,7 @@
dir = 1
},
/obj/effect/landmark/event_spawn,
+/mob/living/basic/bot/cleanbot/medbay,
/turf/open/floor/iron/white,
/area/station/medical/treatment_center)
"aKm" = (
@@ -13636,7 +13688,7 @@
/turf/open/floor/iron,
/area/station/service/cafeteria)
"aLg" = (
-/obj/machinery/restaurant_portal/restaurant,
+/obj/machinery/vending/coffee,
/turf/open/floor/iron/dark/side{
dir = 4
},
@@ -13990,6 +14042,7 @@
dir = 4
},
/obj/structure/table/reinforced,
+/obj/item/storage/medkit/emergency,
/turf/open/floor/iron,
/area/station/engineering/main)
"aMe" = (
@@ -15045,7 +15098,7 @@
/area/station/science/lab)
"aOY" = (
/obj/structure/table/reinforced,
-/obj/item/stack/medical/gauze{
+/obj/item/stack/medical/wrap/gauze{
pixel_x = 8
},
/obj/item/stack/medical/suture,
@@ -15069,7 +15122,6 @@
},
/obj/machinery/airalarm/directional/east,
/obj/machinery/camera/autoname/directional/east,
-/obj/machinery/light/small/directional/east,
/turf/open/floor/iron/white,
/area/station/commons/long_term_storage)
"aPc" = (
@@ -16616,6 +16668,10 @@
},
/obj/structure/table/reinforced,
/obj/structure/sign/poster/official/ue_no/directional/north,
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = -8
+ },
/turf/open/floor/iron,
/area/station/command/heads_quarters/rd)
"aTp" = (
@@ -16691,11 +16747,15 @@
/area/station/science/ordnance/testlab)
"aTy" = (
/obj/structure/table/wood,
-/obj/item/flashlight/lamp,
+/obj/item/flashlight/lamp{
+ pixel_y = 5;
+ pixel_x = -3
+ },
/obj/machinery/status_display/evac/directional/north,
/obj/effect/turf_decal/siding/thinplating{
dir = 8
},
+/obj/item/stack/medical/wrap/gauze,
/turf/open/floor/iron/grimy,
/area/station/hallway/primary/aft)
"aTz" = (
@@ -16795,19 +16855,6 @@
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/station/science/lab)
-"aTM" = (
-/obj/machinery/door/airlock/external{
- name = "External Docking Port"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/turf/open/floor/iron,
-/area/station/hallway/secondary/exit/departure_lounge)
"aTO" = (
/obj/machinery/door/airlock/maintenance_hatch{
name = "Science Maintenance"
@@ -16822,6 +16869,9 @@
"aTS" = (
/obj/effect/landmark/blobstart,
/obj/effect/mapping_helpers/burnt_floor,
+/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
+ dir = 8
+ },
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"aTU" = (
@@ -16890,7 +16940,7 @@
/turf/closed/wall/rust,
/area/station/maintenance/department/engine)
"aUj" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood{
dir = 8
},
@@ -17125,6 +17175,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
+/obj/effect/mapping_helpers/cycling_airlock_old/marker/inner_door{
+ dir = 2
+ },
/turf/open/floor/iron,
/area/station/medical/virology)
"aUL" = (
@@ -17493,6 +17546,10 @@
"aVP" = (
/obj/structure/table/wood,
/obj/item/flashlight/lamp,
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = -8
+ },
/turf/open/floor/iron/dark/side{
dir = 10
},
@@ -17862,6 +17919,10 @@
/obj/machinery/camera/directional/east{
c_tag = "Library - Starboard"
},
+/obj/item/ashtray{
+ pixel_y = -2;
+ pixel_x = -8
+ },
/turf/open/floor/iron/dark,
/area/station/service/library)
"aWH" = (
@@ -17899,6 +17960,9 @@
/obj/structure/cable,
/obj/machinery/airalarm/directional/north,
/obj/machinery/light/small/directional/north,
+/obj/effect/mapping_helpers/cycling_airlock_old{
+ access = list("virology")
+ },
/turf/open/floor/iron/white,
/area/station/medical/virology)
"aWL" = (
@@ -17906,7 +17970,9 @@
dir = 8
},
/obj/machinery/duct,
-/obj/machinery/firealarm/directional/east,
+/obj/machinery/firealarm/directional/east{
+ pixel_y = -6
+ },
/obj/effect/turf_decal/stripes/line{
dir = 4
},
@@ -17980,6 +18046,10 @@
/obj/effect/turf_decal/siding/thinplating{
dir = 4
},
+/obj/item/ashtray{
+ pixel_y = 3;
+ pixel_x = -4
+ },
/turf/open/floor/iron/grimy,
/area/station/hallway/primary/aft)
"aWU" = (
@@ -18049,6 +18119,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 8
},
+/obj/effect/mapping_helpers/cycling_airlock_old/marker/outer_door{
+ dir = 2
+ },
/turf/open/floor/iron/white,
/area/station/maintenance/department/medical)
"aXe" = (
@@ -18310,7 +18383,6 @@
/obj/structure/sign/warning/secure_area/directional/west{
pixel_y = -32
},
-/obj/structure/sign/departments/virology/directional/west,
/turf/open/floor/plating,
/area/station/maintenance/department/medical)
"aXP" = (
@@ -18355,7 +18427,7 @@
/area/station/medical/treatment_center)
"aXT" = (
/obj/structure/table/reinforced,
-/obj/item/stack/medical/gauze{
+/obj/item/stack/medical/wrap/gauze{
pixel_x = 8
},
/obj/item/stack/medical/mesh,
@@ -18553,6 +18625,9 @@
c_tag = "Medical - Virology Airlock";
network = list("ss13","medbay","viro")
},
+/obj/machinery/firealarm/directional/west{
+ pixel_y = -6
+ },
/turf/open/floor/iron/white,
/area/station/medical/virology)
"aYA" = (
@@ -20106,6 +20181,9 @@
/obj/effect/turf_decal/caution{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/airlock_pump/unbolt_only{
+ dir = 8
+ },
/turf/open/floor/iron,
/area/station/maintenance/department/cargo)
"bcL" = (
@@ -21327,11 +21405,11 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{
dir = 8
},
-/obj/item/radio/intercom/directional/south,
/obj/effect/turf_decal/siding/green,
/obj/effect/turf_decal/trimline/green/end{
dir = 1
},
+/obj/structure/sign/departments/virology/directional/south,
/turf/open/floor/iron/white,
/area/station/medical/virology)
"bfN" = (
@@ -21775,7 +21853,8 @@
"bhp" = (
/obj/machinery/door/morgue{
name = "Relic Closet";
- req_one_access = list("chapel_office", "crematorium")
+ req_one_access = list("chapel_office", "crematorium");
+ dir = 1
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -22442,7 +22521,7 @@
/turf/open/floor/circuit/telecomms,
/area/station/science/xenobiology)
"bjJ" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/radio/intercom/directional/west,
/obj/machinery/computer/security/telescreen/entertainment/directional/south,
/turf/open/floor/iron/grimy,
@@ -22584,6 +22663,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
dir = 4
},
+/mob/living/basic/bot/medbot/autopatrol,
/turf/open/floor/iron,
/area/station/medical/treatment_center)
"bkt" = (
@@ -23722,7 +23802,6 @@
/turf/open/floor/iron,
/area/station/hallway/primary/fore)
"bNe" = (
-/obj/structure/closet/crate/bin,
/obj/effect/landmark/start/hangover,
/turf/open/floor/iron/dark/side{
dir = 8
@@ -23924,7 +24003,7 @@
/obj/effect/turf_decal/siding/wood{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/item/newspaper{
pixel_x = 3;
pixel_y = 3
@@ -23966,18 +24045,14 @@
},
/area/station/hallway/secondary/service)
"cgi" = (
-/obj/effect/turf_decal/caution{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
/obj/effect/turf_decal/stripes/line{
dir = 8
},
-/obj/machinery/atmospherics/components/unary/airlock_pump{
+/obj/effect/turf_decal/caution{
dir = 8
},
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron,
/area/station/maintenance/department/science)
"cgO" = (
@@ -24118,8 +24193,15 @@
/turf/open/floor/iron,
/area/station/service/hydroponics)
"cpo" = (
-/obj/machinery/vending/coffee,
/obj/structure/sign/warning/doors/directional/south,
+/obj/structure/table,
+/obj/effect/spawner/random/trash/food_packaging,
+/obj/effect/spawner/random/trash/cigbutt,
+/obj/effect/spawner/random/trash/cigbutt,
+/obj/item/ashtray{
+ pixel_y = 3;
+ pixel_x = -4
+ },
/turf/open/floor/iron/dark/side{
dir = 10
},
@@ -25744,7 +25826,6 @@
/area/station/science/ordnance/testlab)
"fcU" = (
/obj/item/cigbutt,
-/obj/structure/sign/warning/secure_area/directional/south,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -25872,6 +25953,7 @@
/obj/structure/sign/nanotrasen{
pixel_y = -32
},
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron{
heat_capacity = 1e+006
},
@@ -29773,6 +29855,15 @@
},
/turf/open/floor/iron,
/area/station/security/prison)
+"mdS" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/machinery/atmospherics/components/unary/airlock_pump{
+ dir = 8
+ },
+/turf/open/floor/iron,
+/area/station/maintenance/department/science)
"meo" = (
/obj/machinery/navbeacon{
codes_txt = "patrol;next_patrol=5.2-Cargo";
@@ -29878,6 +29969,9 @@
dir = 1
},
/area/station/hallway/secondary/entry)
+"mlz" = (
+/turf/closed/wall/r_wall/rust,
+/area/station/maintenance/department/medical)
"mmf" = (
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
@@ -29892,6 +29986,7 @@
dir = 1
},
/obj/effect/turf_decal/tile/neutral/anticorner/contrasted,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron,
/area/station/hallway/primary/aft)
"mmW" = (
@@ -30026,6 +30121,12 @@
/obj/item/inspector,
/turf/open/floor/iron,
/area/station/security/brig)
+"mtl" = (
+/obj/structure/table/wood,
+/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/item/ashtray/random_contents,
+/turf/open/floor/iron,
+/area/station/service/cafeteria)
"mvj" = (
/obj/machinery/atmospherics/pipe/smart/simple/supply/hidden{
dir = 9
@@ -30462,9 +30563,6 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer5,
/turf/open/floor/iron,
/area/station/hallway/primary/starboard)
-"nhh" = (
-/turf/closed/wall,
-/area/space)
"nhB" = (
/obj/structure/cable,
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2,
@@ -31211,6 +31309,7 @@
dir = 1
},
/obj/effect/turf_decal/tile/neutral/anticorner/contrasted,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron,
/area/station/hallway/primary/aft)
"oCy" = (
@@ -32539,6 +32638,15 @@
},
/turf/open/floor/iron/dark/corner,
/area/station/cargo/bitrunning/den)
+"qQo" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/turf/open/floor/iron,
+/area/station/cargo/miningdock)
"qQO" = (
/obj/machinery/door/firedoor,
/obj/structure/sign/departments/medbay/alt/directional/south,
@@ -32555,7 +32663,7 @@
/turf/open/floor/iron,
/area/station/hallway/primary/central)
"qRz" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/newscaster/directional/east,
/turf/open/floor/carpet/green,
/area/station/service/lawoffice)
@@ -33022,6 +33130,7 @@
/area/space/nearstation)
"rFA" = (
/obj/structure/table,
+/obj/item/storage/medkit/emergency,
/turf/open/floor/iron,
/area/station/commons/dorms)
"rIZ" = (
@@ -33070,6 +33179,21 @@
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/engineering/supermatter/room)
+"rMs" = (
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/landmark/start/hangover,
+/obj/item/kirbyplants/organic/plant21,
+/turf/open/floor/iron,
+/area/station/service/cafeteria)
"rOb" = (
/obj/machinery/atmospherics/pipe/smart/simple/orange/hidden{
dir = 4
@@ -33753,6 +33877,7 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{
dir = 4
},
+/obj/machinery/light/cold/dim/directional/south,
/turf/open/floor/iron/white,
/area/station/commons/long_term_storage)
"sHz" = (
@@ -34417,6 +34542,10 @@
pixel_x = 7;
pixel_y = 2
},
+/obj/item/ashtray{
+ pixel_y = -5;
+ pixel_x = -8
+ },
/turf/open/floor/iron,
/area/station/command/heads_quarters/qm)
"sMe" = (
@@ -35208,6 +35337,12 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer5,
/turf/open/floor/iron/white/corner,
/area/station/hallway/primary/starboard)
+"tbZ" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/turf/open/floor/iron,
+/area/station/hallway/secondary/entry)
"tdz" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/structure/table,
@@ -35267,6 +35402,10 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/effect/turf_decal/tile/neutral/fourcorners,
+/obj/item/ashtray{
+ pixel_y = 6;
+ pixel_x = 2
+ },
/turf/open/floor/iron,
/area/station/service/cafeteria)
"tin" = (
@@ -35328,6 +35467,7 @@
/obj/effect/mapping_helpers/airlock/unres{
dir = 4
},
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"tlg" = (
@@ -35344,6 +35484,7 @@
dir = 1
},
/obj/effect/turf_decal/tile/neutral,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/white/corner{
dir = 8
},
@@ -35666,6 +35807,13 @@
/obj/effect/landmark/start/station_engineer,
/turf/open/floor/iron,
/area/station/engineering/main)
+"tVj" = (
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/turf/open/floor/iron,
+/area/station/hallway/primary/aft)
"tVp" = (
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/cable,
@@ -35690,7 +35838,8 @@
},
/obj/machinery/door/morgue{
name = "Curator's Study";
- req_access = list("library")
+ req_access = list("library");
+ dir = 1
},
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/dark,
@@ -36091,6 +36240,7 @@
/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{
dir = 1
},
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron{
heat_capacity = 1e+006
},
@@ -36148,6 +36298,12 @@
/obj/machinery/iv_drip,
/turf/open/floor/iron,
/area/station/medical/treatment_center)
+"uAP" = (
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/turf/open/floor/iron,
+/area/station/hallway/secondary/exit/departure_lounge)
"uBJ" = (
/obj/machinery/computer/security{
dir = 1
@@ -36892,6 +37048,7 @@
/area/station/science/breakroom)
"wdt" = (
/obj/effect/turf_decal/bot,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron/dark/side{
dir = 4
},
@@ -37172,6 +37329,13 @@
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/cargo/storage)
+"wAa" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/turf/open/floor/plating,
+/area/station/maintenance/department/science)
"wAw" = (
/turf/open/space,
/area/space)
@@ -37994,6 +38158,10 @@
/obj/effect/turf_decal/siding/wood{
dir = 1
},
+/obj/item/ashtray{
+ pixel_y = -2;
+ pixel_x = -8
+ },
/turf/open/floor/iron/dark,
/area/station/service/library)
"xSs" = (
@@ -38067,7 +38235,6 @@
/turf/open/floor/iron/dark,
/area/station/science/ordnance/storage)
"xZz" = (
-/obj/item/kirbyplants/organic/plant22,
/obj/effect/turf_decal/tile/red,
/obj/effect/turf_decal/tile/yellow{
dir = 4
@@ -38079,6 +38246,7 @@
dir = 1
},
/obj/effect/landmark/start/hangover,
+/obj/structure/tank_holder/extinguisher,
/turf/open/floor/iron,
/area/station/service/cafeteria)
"xZL" = (
@@ -38295,10 +38463,10 @@
dir = 6
},
/obj/structure/closet/l3closet/virology,
-/obj/machinery/firealarm/directional/south,
/obj/effect/turf_decal/siding/green{
dir = 6
},
+/obj/item/radio/intercom/directional/south,
/turf/open/floor/iron/white,
/area/station/medical/virology)
"ylH" = (
@@ -63922,7 +64090,7 @@ aSs
aUl
aKm
ayM
-bea
+mlz
aWJ
bfM
bea
@@ -64179,7 +64347,7 @@ aTb
aUp
aTU
jXv
-aKV
+bxN
aWM
ylF
aKV
@@ -68307,7 +68475,7 @@ aaa
aaa
aaa
aaa
-aaa
+bwz
aaa
aaa
aaa
@@ -68563,15 +68731,15 @@ aaa
aaa
aaa
aaa
-aaa
-bwz
-aaa
-aaa
-aaa
-aaa
+bgU
+bkj
+bgU
aaa
aaa
aaa
+bgU
+bkj
+bgU
aaa
aaa
aaa
@@ -68821,13 +68989,13 @@ aaa
aaa
aaa
bgU
-bkj
+eIU
bgU
sdX
sdX
sdX
bgU
-bkj
+eIU
bgU
aaa
aaa
@@ -69078,13 +69246,13 @@ aae
aae
aae
bgU
-eIU
+tbZ
bgU
bgP
bgU
bgP
bgU
-eIU
+tbZ
bgU
aae
aae
@@ -70363,13 +70531,13 @@ aae
aae
aae
bgU
-bki
+tbZ
bgU
bgP
bgU
bgP
bgU
-bki
+tbZ
bgU
aae
aae
@@ -70620,13 +70788,13 @@ aaa
aaa
aaa
bgU
-btl
+bki
bgU
sdX
sdX
sdX
bgU
-btl
+bki
bgU
aaa
aaa
@@ -70876,15 +71044,15 @@ aaa
aaa
aaa
aaa
+bgU
+btl
+bgU
aaa
aaa
aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
+bgU
+btl
+bgU
aaa
aaa
aaa
@@ -71401,7 +71569,7 @@ aaa
aaa
aaa
aaa
-lUq
+aaa
aaa
aaa
aaa
@@ -71658,7 +71826,7 @@ aaa
aaa
aaa
aaa
-aaa
+lUq
aaa
aaa
aaa
@@ -71850,7 +72018,7 @@ auc
pcN
avg
awl
-aBZ
+mtl
gpG
rdB
eZj
@@ -71861,7 +72029,7 @@ eZj
oTd
aFO
kcP
-aBZ
+mtl
sAA
pcN
auc
@@ -72379,7 +72547,7 @@ vPL
vPL
asg
hDi
-ubG
+rMs
arb
aOq
aPn
@@ -72658,7 +72826,7 @@ bcq
bfJ
aDE
bfJ
-aDE
+tVj
qks
rJx
bhH
@@ -73686,7 +73854,7 @@ bcu
bdm
beh
sKP
-xKp
+wAa
sJL
pej
hrd
@@ -79295,7 +79463,7 @@ aaa
aae
amD
aol
-gtS
+qQo
aqu
amD
aae
@@ -79552,7 +79720,7 @@ aaa
aae
ant
aom
-apn
+gtS
aqv
nzE
aae
@@ -79862,7 +80030,7 @@ eBJ
aiQ
pMh
pMh
-sKH
+mdS
pMh
uTo
aaa
@@ -80118,8 +80286,9 @@ aiQ
aiQ
aiQ
aiQ
-aiQ
-bvg
+pMh
+sKH
+pMh
uTo
aaa
aaa
@@ -80210,7 +80379,6 @@ aaa
aaa
aaa
aaa
-aaa
"}
(164,1,1) = {"
aaa
@@ -80376,6 +80544,7 @@ aiQ
aiQ
aiQ
aiQ
+bvg
uTo
aaa
aaa
@@ -80467,7 +80636,6 @@ aaa
aaa
aaa
aaa
-aaa
"}
(165,1,1) = {"
aaa
@@ -80632,7 +80800,7 @@ aiQ
aiQ
aiQ
aiQ
-aaa
+aiQ
aaa
aaa
aaa
@@ -80887,8 +81055,8 @@ aDw
imR
ozW
aHq
-aaa
-aaa
+aiQ
+uTo
aaa
aaa
aaa
@@ -82130,7 +82298,7 @@ aaa
aaa
aaf
aae
-nhh
+aKh
sDP
azb
azb
@@ -82142,7 +82310,7 @@ aKh
aGc
aKh
azb
-aTM
+aBh
aCn
aBh
azb
@@ -82391,17 +82559,17 @@ rel
aae
aae
azb
-aDh
+uAP
azb
-aDh
+uAP
azb
aae
aae
aae
azb
-aDh
+uAP
azb
-aDh
+uAP
azb
aae
rel
@@ -82648,17 +82816,17 @@ aaa
aaa
aaa
azb
-fWz
+aDh
azb
-fWz
+aDh
azb
-aaa
-aaa
-aaa
+aae
+aae
+aae
azb
-fWz
+aDh
azb
-fWz
+aDh
azb
aaa
aaa
@@ -82671,7 +82839,7 @@ aaa
aaa
aaa
aaa
-jYq
+aae
uTo
xUx
uTo
@@ -82904,19 +83072,19 @@ aaa
aaa
aaa
aaa
+azb
+fWz
+azb
+fWz
+azb
aaa
aaa
aaa
-fsl
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
+azb
+fWz
+azb
+fWz
+azb
aaa
aaa
aaa
@@ -83164,7 +83332,7 @@ aaa
aaa
aaa
aaa
-aaa
+fsl
aaa
aaa
aaa
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 501ef891da57..3091f52612ab 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -2685,7 +2685,7 @@
/turf/open/floor/iron/large,
/area/station/security)
"ajp" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/computer/security/telescreen/entertainment/directional/north,
/turf/open/floor/iron/large,
/area/station/security)
@@ -7981,7 +7981,7 @@
/turf/open/floor/wood,
/area/station/command/heads_quarters/hop)
"aBC" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/airalarm/directional/north,
/turf/open/floor/wood,
/area/station/command/heads_quarters/hop)
@@ -10460,7 +10460,7 @@
/turf/open/floor/iron,
/area/station/commons/storage/art)
"aLz" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -21119,7 +21119,7 @@
/obj/machinery/light_switch/directional/east{
name = "Light Switch"
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/command/heads_quarters/cmo)
"bDy" = (
@@ -28283,7 +28283,7 @@
/turf/open/floor/plating,
/area/station/maintenance/department/chapel/monastery)
"ckl" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/light/small/directional/west,
/turf/open/floor/iron/dark/smooth_large,
/area/station/service/library/lounge)
@@ -33008,7 +33008,7 @@
/obj/effect/turf_decal/trimline/brown/filled/line,
/obj/machinery/power/apc/auto_name/directional/north,
/obj/structure/cable,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/station/cargo/sorting)
"dWk" = (
@@ -40117,7 +40117,7 @@
/area/station/cargo/storage)
"jdj" = (
/obj/structure/disposalpipe/segment,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/siding/wood/corner{
dir = 8
},
@@ -42600,7 +42600,7 @@
/obj/effect/turf_decal/tile/yellow/half{
dir = 4
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/edge{
dir = 4
},
@@ -42979,7 +42979,7 @@
/turf/open/floor/plating,
/area/station/maintenance/department/cargo)
"lui" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/station/security/detectives_office)
"luA" = (
@@ -59405,7 +59405,7 @@
/turf/open/floor/iron/dark/smooth_edge,
/area/station/command/heads_quarters/rd)
"wrU" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/power/apc/auto_name/directional/west,
/obj/structure/cable,
/turf/open/floor/wood,
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index f0d3d9663262..3930eb7343ea 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -909,7 +909,7 @@
/turf/open/floor/grass,
/area/centcom/central_command_areas/control)
"hx" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/centcom/central_command_areas/briefing)
"hz" = (
@@ -2872,7 +2872,7 @@
/turf/open/floor/iron,
/area/centcom/central_command_areas/supply)
"ou" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/stripes/line{
dir = 6
},
@@ -4641,7 +4641,7 @@
/turf/open/floor/iron/dark,
/area/centcom/central_command_areas/control)
"vJ" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/machinery/button/door/indestructible{
id = "XCCFerry";
name = "Hanger Bay Shutters";
diff --git a/_maps/map_files/tramstation/maintenance_modules/secbarupper_attachment_a_1.dmm b/_maps/map_files/tramstation/maintenance_modules/secbarupper_attachment_a_1.dmm
index c709ff932851..e4c4505d62e2 100644
--- a/_maps/map_files/tramstation/maintenance_modules/secbarupper_attachment_a_1.dmm
+++ b/_maps/map_files/tramstation/maintenance_modules/secbarupper_attachment_a_1.dmm
@@ -85,7 +85,7 @@
/area/station/maintenance/department/security)
"Q" = (
/obj/effect/decal/cleanable/dirt,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/smooth,
/area/station/maintenance/department/security)
"T" = (
diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm
index 697c14b8f9a8..f38086a022e1 100644
--- a/_maps/map_files/tramstation/tramstation.dmm
+++ b/_maps/map_files/tramstation/tramstation.dmm
@@ -6241,7 +6241,7 @@
/turf/open/floor/iron/white,
/area/station/medical/medbay/central)
"bbM" = (
-/obj/machinery/photocopier{
+/obj/machinery/photocopier/prebuilt{
pixel_y = 3
},
/obj/structure/sign/clock/directional/west,
@@ -6721,7 +6721,7 @@
/area/station/engineering/atmos/pumproom)
"bnh" = (
/obj/item/radio/intercom/directional/north,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/wood,
/area/station/service/lawoffice)
"bnY" = (
@@ -19880,7 +19880,7 @@
/obj/effect/turf_decal/trimline/purple/filled/line{
dir = 8
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/white,
/area/station/science/lower)
"gbp" = (
@@ -39022,7 +39022,7 @@
/turf/open/floor/iron,
/area/station/cargo/sorting)
"mNV" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/grimy,
/area/station/service/library/lounge)
"mOi" = (
@@ -51979,7 +51979,7 @@
/turf/open/floor/iron,
/area/station/commons/dorms)
"rxN" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/structure/extinguisher_cabinet/directional/north,
/turf/open/floor/wood,
/area/station/command/heads_quarters/hop)
@@ -61265,7 +61265,7 @@
/area/station/cargo/miningdock)
"uHb" = (
/obj/machinery/airalarm/directional/north,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/brown/fourcorners,
/turf/open/floor/iron,
/area/station/cargo/sorting)
@@ -66266,7 +66266,7 @@
/obj/effect/turf_decal/trimline/dark_green/filled/corner{
dir = 1
},
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/obj/effect/turf_decal/tile/purple/fourcorners,
/turf/open/floor/iron/white,
/area/station/science/research)
diff --git a/_maps/shuttles/emergency_monastery.dmm b/_maps/shuttles/emergency_monastery.dmm
index 07a9ef7acdc6..5f89a426c1a3 100644
--- a/_maps/shuttles/emergency_monastery.dmm
+++ b/_maps/shuttles/emergency_monastery.dmm
@@ -556,7 +556,7 @@
/area/shuttle/escape)
"iB" = (
/obj/machinery/light/small/directional/west,
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/iron/dark,
/area/shuttle/escape)
"iE" = (
diff --git a/_maps/shuttles/pirate_irs.dmm b/_maps/shuttles/pirate_irs.dmm
index 82c0ac6185b6..838b0080347b 100644
--- a/_maps/shuttles/pirate_irs.dmm
+++ b/_maps/shuttles/pirate_irs.dmm
@@ -1721,7 +1721,7 @@
/turf/open/floor/iron,
/area/shuttle/pirate)
"SQ" = (
-/obj/machinery/photocopier/gratis,
+/obj/machinery/photocopier/gratis/prebuilt,
/obj/machinery/firealarm/directional/south,
/turf/open/floor/iron/white,
/area/shuttle/pirate)
diff --git a/_maps/templates/lazy_templates/ninja_den.dmm b/_maps/templates/lazy_templates/ninja_den.dmm
index 1713ec116bb3..b16e571cc687 100644
--- a/_maps/templates/lazy_templates/ninja_den.dmm
+++ b/_maps/templates/lazy_templates/ninja_den.dmm
@@ -34,7 +34,7 @@
/turf/open/floor/bamboo/tatami/purple,
/area/centcom/central_command_areas/holding)
"bH" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/catwalk_floor,
/area/centcom/central_command_areas/holding)
"bP" = (
diff --git a/_maps/virtual_domains/meta_central.dmm b/_maps/virtual_domains/meta_central.dmm
index 024799dcc897..750d22e34700 100644
--- a/_maps/virtual_domains/meta_central.dmm
+++ b/_maps/virtual_domains/meta_central.dmm
@@ -2174,7 +2174,7 @@
/turf/open/floor/wood,
/area/virtual_domain)
"rX" = (
-/obj/machinery/photocopier,
+/obj/machinery/photocopier/prebuilt,
/turf/open/floor/carpet,
/area/virtual_domain)
"sa" = (
diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm
index 391ed0112ac9..5446ab83fcc2 100644
--- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm
@@ -42,3 +42,18 @@
///Called when an atom has a light template applied to it. Frombase of [/datum/light_template/proc/mirror_onto]: ()
#define COMSIG_ATOM_LIGHT_TEMPLATE_MIRRORED "atom_light_template_mirrored"
+
+///Called when an atom's overlay component applies visuals, from base of [/datum/component/overlay_lighting/proc/show_to_holder]: (image/mask, image/cone, atom/movable/light_holder)
+#define COMSIG_ATOM_OVERLAY_LIGHT_APPLIED "atom_overlay_light_applied"
+///Above, but send to the holder of the light instead of the light source itself: (image/mask, image/cone, atom/movable/light_source)
+#define COMSIG_ATOM_HOLDER_OVERLAY_LIGHT_APPLIED "atom_holder_overlay_light_applied"
+
+///Called when an atom's overlay component hides its visuals, from base of [/datum/component/overlay_lighting/proc/hide_from_holder]: (atom/movable/light_holder)
+#define COMSIG_ATOM_OVERLAY_LIGHT_REMOVED "atom_overlay_light_removed"
+///Above, but send to the holder of the light instead of the light source itself: (atom/movable/light_source)
+#define COMSIG_ATOM_HOLDER_OVERLAY_LIGHT_REMOVED "atom_holder_overlay_light_removed"
+
+/// Called when a light fixture is broken, from base of [/obj/machinery/light/break_light_tube]: (was_ok)
+#define COMSIG_LIGHT_FIXTURE_BROKEN "light_fixture_broken"
+/// Called when a light fixture is toggled on or off, from base of [/obj/machinery/light/toggle_light]: (new_status)
+#define COMSIG_LIGHT_FIXTURE_TOGGLED "light_fixture_toggled"
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
index a1303046e1f6..e8dbddc50827 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
@@ -310,6 +310,9 @@
#define COMSIG_LIVING_PERCEIVE_EXAMINE_NAME "living_perceive_examine_name"
#define COMPONENT_EXAMINE_NAME_OVERRIDEN (1<<0)
+/// From /obj/item/book/bible/attack() : (mob/living/user, obj/item/book/bible/bible, bless_result)
+#define COMSIG_LIVING_BLESSED "living_blessed"
+
/// From /datum/element/death_drops/on_death(mob/living/target, gibbed) : (list/loot, gibbed)
#define COMSIG_LIVING_DROP_LOOT "living_drop_loot"
/// Prevent loot from being dropped
diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm
index 986e5290186b..ed3ba0553bf9 100644
--- a/code/__DEFINES/dcs/signals/signals_object.dm
+++ b/code/__DEFINES/dcs/signals/signals_object.dm
@@ -595,3 +595,32 @@
/// Sent from /obj/effect/rune/convert/try_sacrifice_item(obj/effect/rune/convert/rune)
#define COMSIG_ITEM_CULT_SACRIFICE "item_cult_sacrifice"
#define COMPONENT_SACRIFICE_SUCCESSFUL (1<<0)
+
+/// Send to items that have been unwrapped from a gift
+#define COMSIG_ITEM_OPENED_FROM_GIFT "gift_opened"
+
+/// From /obj/machinery/vending/ui_interact(): (mob/user, datum/vending_ui/ui)
+#define COMSIG_VENDING_UI_INTERACT "vending_ui_interact"
+ #define VENDING_DENIED (1<<0)
+
+/// From /obj/machinery/vending/dispense(): (obj/item/vended_item)
+#define COMSIG_VENDING_DISPENSED "vending_dispensed"
+
+/// From /obj/machinery/vending/vend(): (mob/user, obj/machinery/vending_machine, obj/item/vended_item)
+#define COMSIG_MOB_VENDING_PURCHASE "mob_vending_purchase"
+ /// Stops the mob from picking up whatevr they just purchased (it just goes to the floor)
+ #define VENDING_NO_PICKUP (1<<0)
+
+/// Sent from /datum/component/reflection when the reflection is updated to the mob reflecting: (atom/movable/reflecting_in, obj/effect/abstract/reflection)
+#define COMSIG_REFLECTION_UPDATED "reflection_updated"
+
+/// Sent from /datum/component/reflection when the reflection is updated to the component parent: (obj/effect/abstract/reflection)
+#define COMSIG_REFLECTED_IMAGE_UPDATED "reflected_image_updated"
+
+/// From /datum/element/weapon_description: (list/readout)
+#define COMSIG_ITEM_WEAPON_LABEL_READOUT "item_weapon_label_readout"
+
+/// Sent from /obj/machinery/door/airlock/close, to a movable blocking it from closing: (obj/machinery/door/being_blocked, force_close, force_crush)
+#define COMSIG_MOVABLE_BLOCKING_AIRLOCK "movable_blocking_airlock"
+ /// Forces the airlock to crush whatever's blocking it even if it normally wouldn't
+ #define AIRLOCK_BLOCK_FORCE_CRUSH (1<<0)
diff --git a/code/datums/components/crafting/furniture.dm b/code/datums/components/crafting/furniture.dm
index 39f5a25a19f8..c03e1d0fc286 100644
--- a/code/datums/components/crafting/furniture.dm
+++ b/code/datums/components/crafting/furniture.dm
@@ -71,3 +71,37 @@
tool_behaviors = list(TOOL_SCREWDRIVER)
category = CAT_FURNITURE
time = 10 SECONDS
+
+/datum/crafting_recipe/lamp
+ name = "Desk Lamp"
+ result = /obj/item/flashlight/lamp
+ reqs = list(
+ /obj/item/flashlight = 1,
+ /obj/item/stack/rods = 1,
+ /obj/item/light/bulb = 1,
+ )
+ // crafting_flags = CRAFT_SKIP_MATERIALS_PARITY
+ tool_behaviors = list(TOOL_SCREWDRIVER)
+ category = CAT_FURNITURE
+
+/datum/crafting_recipe/lamp/New()
+ . = ..()
+ blacklist += subtypesof(/obj/item/flashlight)
+
+/datum/crafting_recipe/lamp/green
+ name = "Green Desk Lamp"
+ result = /obj/item/flashlight/lamp/green
+
+/datum/crafting_recipe/banana_lamp
+ name = "Banana Lamp"
+ result = /obj/item/flashlight/lamp/bananalamp
+ reqs = list(
+ /obj/item/flashlight/lamp = 1,
+ /obj/item/grown/bananapeel = 1,
+ )
+ blacklist = list(
+ /obj/item/flashlight/lamp/bananalamp,
+ )
+ // requirements_mats_blacklist = list(/obj/item/grown/bananapeel)
+ tool_behaviors = list(TOOL_SCREWDRIVER)
+ category = CAT_FURNITURE
diff --git a/code/datums/components/crafting/tools.dm b/code/datums/components/crafting/tools.dm
index 46faafa75613..32b9976c88ca 100644
--- a/code/datums/components/crafting/tools.dm
+++ b/code/datums/components/crafting/tools.dm
@@ -90,3 +90,15 @@
// crafting_flags = CRAFT_SKIP_MATERIALS_PARITY
tool_behaviors = list(TOOL_SCREWDRIVER)
category = CAT_TOOLS
+
+/datum/crafting_recipe/lantern
+ name = "Lantern"
+ result = /obj/item/flashlight/lantern
+ reqs = list(
+ /obj/item/flashlight/flare/candle = 1,
+ /obj/item/stack/rods = 1,
+ /obj/item/stack/sheet/glass = 1,
+ )
+ // crafting_flags = CRAFT_SKIP_MATERIALS_PARITY
+ tool_behaviors = list(TOOL_SCREWDRIVER)
+ category = CAT_TOOLS
diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm
index 75cce3ee3d4a..f6aa7ce76689 100644
--- a/code/datums/components/omen.dm
+++ b/code/datums/components/omen.dm
@@ -16,22 +16,28 @@
var/luck_mod = 1
/// Base damage from negative events. Cursed take 25% of this damage.
var/damage_mod = 1
-
-/datum/component/omen/Initialize(obj/vessel, incidents_left, luck_mod, damage_mod)
+ /// If TRUE being blessed by the chaplain can remove the omen
+ var/bless_fixable = TRUE
+ /// Callback invoked on death
+ var/datum/callback/on_death
+ /// List of light fixtures nearby - we track their state to see if they break or toggle
+ VAR_FINAL/list/tracked_lights = list()
+
+/datum/component/omen/Initialize(obj/vessel, incidents_left = INFINITY, luck_mod = 1, damage_mod = 1, bless_fixable = TRUE, datum/callback/on_death)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
if(istype(vessel))
src.vessel = vessel
RegisterSignal(vessel, COMSIG_QDELETING, PROC_REF(vessel_qdeleting))
- if(!isnull(incidents_left))
- src.incidents_left = incidents_left
- if(!isnull(luck_mod))
- src.luck_mod = luck_mod
- if(!isnull(damage_mod))
- src.damage_mod = damage_mod
- ADD_TRAIT(parent, TRAIT_CURSED, SMITE_TRAIT)
+ src.incidents_left = incidents_left
+ src.luck_mod = luck_mod
+ src.damage_mod = damage_mod
+ src.bless_fixable = bless_fixable
+ src.on_death = on_death
+
+ ADD_TRAIT(parent, TRAIT_CURSED, REF(src))
/**
* This is a omen eat omen world! The stronger omen survives.
@@ -52,7 +58,8 @@
/datum/component/omen/Destroy(force)
var/mob/living/person = parent
- REMOVE_TRAIT(person, TRAIT_CURSED, SMITE_TRAIT)
+ REMOVE_TRAIT(person, TRAIT_CURSED, REF(src))
+ REMOVE_TRAIT(person, TRAIT_NO_MIRROR_REFLECTION, REF(src))
to_chat(person, span_nicegreen("You feel a horrible omen lifted off your shoulders!"))
if(vessel)
@@ -61,6 +68,9 @@
vessel.burn()
vessel = null
+ for(var/obj/machinery/light/to_untrack as anything in tracked_lights)
+ untrack_light(to_untrack)
+
return ..()
/datum/component/omen/RegisterWithParent()
@@ -68,164 +78,251 @@
RegisterSignal(parent, COMSIG_ON_CARBON_SLIP, PROC_REF(check_slip))
RegisterSignal(parent, COMSIG_CARBON_MOOD_UPDATE, PROC_REF(check_bless))
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(check_death))
+ RegisterSignal(parent, COMSIG_MOVABLE_BLOCKING_AIRLOCK, PROC_REF(check_airlock_crush))
+ RegisterSignal(parent, COMSIG_MOB_VENDING_PURCHASE, PROC_REF(check_vending))
+ RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(on_life))
/datum/component/omen/UnregisterFromParent()
- UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_CARBON_MOOD_UPDATE, COMSIG_LIVING_DEATH))
+ UnregisterSignal(parent, list(
+ COMSIG_ON_CARBON_SLIP,
+ COMSIG_MOVABLE_MOVED,
+ COMSIG_LIVING_BLESSED,
+ COMSIG_LIVING_DEATH,
+ COMSIG_MOVABLE_BLOCKING_AIRLOCK,
+ COMSIG_MOB_VENDING_PURCHASE,
+ COMSIG_LIVING_LIFE,
+ ))
/datum/component/omen/proc/consume_omen()
+ if(incidents_left == INFINITY)
+ return
+
incidents_left--
if(incidents_left < 1)
qdel(src)
-/**
- * check_accident() is called each step we take
- *
- * While we're walking around, roll to see if there's any environmental hazards on one of the adjacent tiles we can trigger.
- * We do the prob() at the beginning to A. add some tension for /when/ it will strike, and B. (more importantly) ameliorate the fact that we're checking up to 5 turfs's contents each time
- */
-/datum/component/omen/proc/check_accident(atom/movable/our_guy)
+/// Roll an accident happening, factoring in a few things, based on some base change.
+/datum/component/omen/proc/roll_for_accident(base_chance = 4)
+ var/chance = base_chance * luck_mod
+ for(var/mob/viewer in viewers(parent))
+ if(!viewer.client?.is_afk())
+ chance *= 2
+ break
+
+ return prob(chance)
+
+/// When we obstruct an airlock, there's a chance it will crush us instead of stopping like it should
+/datum/component/omen/proc/check_airlock_crush(mob/living/source, obj/machinery/door/airlock/darth_airlock, forced, force_crush)
SIGNAL_HANDLER
- if(!isliving(our_guy))
+ if(force_crush || !roll_for_accident(25))
+ return NONE
+
+ consume_omen()
+ to_chat(parent, span_warning("As you stand in [darth_airlock], it doesn't stop closing like it should..."))
+ return AIRLOCK_BLOCK_FORCE_CRUSH
+
+/// When we vend an item from a vending machine, there's a chance the machine will tip
+/datum/component/omen/proc/check_vending(mob/living/source, obj/machinery/vending/darth_vendor, obj/item/vended_item)
+ SIGNAL_HANDLER
+
+ if(!source.Adjacent(darth_vendor) || !roll_for_accident(10))
+ return NONE
+
+ consume_omen()
+ to_chat(source, span_warning("As you grab [vended_item] from the slot, [darth_vendor] wobbles ominously..."))
+ INVOKE_ASYNC(darth_vendor, TYPE_PROC_REF(/obj/machinery/vending, tilt), source)
+ return VENDING_NO_PICKUP
+
+/// On life tick, run a few generic checks for accidents, and track nearby lights
+/datum/component/omen/proc/on_life(mob/living/source)
+ SIGNAL_HANDLER
+
+ if(source.stat == DEAD || HAS_TRAIT(source, TRAIT_STASIS))
return
- var/mob/living/living_guy = our_guy
+ if(roll_for_accident(0.001))
+ spontaneous_combustion(source)
+ return
- if(prob(0.001) && (living_guy.stat != DEAD)) // You hit the lottery! Kinda.
- living_guy.visible_message(span_danger("[living_guy] suddenly bursts into flames!"), span_danger("You suddenly burst into flames!"))
- INVOKE_ASYNC(living_guy, TYPE_PROC_REF(/mob, emote), "scream")
- living_guy.adjust_fire_stacks(20)
- living_guy.ignite_mob(silent = TRUE)
- consume_omen()
+ if(HAS_TRAIT(source, TRAIT_SHOCKIMMUNE))
+ for(var/obj/machinery/light/to_untrack as anything in tracked_lights)
+ untrack_light(to_untrack)
return
- var/effective_luck = luck_mod
+ var/list/light_list = list()
+ for(var/obj/machinery/light/evil_light in view(2, source))
+ if(evil_light.status == LIGHT_OK)
+ light_list += evil_light
+ for(var/obj/machinery/light/to_track as anything in light_list - tracked_lights)
+ track_light(to_track)
+ for(var/obj/machinery/light/to_untrack as anything in tracked_lights - light_list)
+ untrack_light(to_untrack)
+
+/// Start tracking a light, because it's near us and could be a threat
+/datum/component/omen/proc/track_light(obj/machinery/light/evil_light)
+ tracked_lights += evil_light
+ RegisterSignal(evil_light, COMSIG_LIGHT_FIXTURE_BROKEN, PROC_REF(check_break_zap))
+ RegisterSignal(evil_light, COMSIG_LIGHT_FIXTURE_TOGGLED, PROC_REF(check_toggle_zap))
+ RegisterSignal(evil_light, COMSIG_QDELETING, PROC_REF(untrack_light))
+
+/// Stop tracking a light, either because it broke or we moved away from it
+/datum/component/omen/proc/untrack_light(obj/machinery/light/evil_light)
+ SIGNAL_HANDLER
- // If there's nobody to witness the misfortune, make it less likely.
- // This way, we allow for people to be able to get into hilarious situations without making the game nigh unplayable most of the time.
+ tracked_lights -= evil_light
+ UnregisterSignal(evil_light, list(COMSIG_LIGHT_FIXTURE_BROKEN, COMSIG_LIGHT_FIXTURE_TOGGLED, COMSIG_QDELETING))
- var/has_watchers = FALSE
- for(var/mob/viewer in viewers(our_guy, world.view))
- if(viewer.client)
- has_watchers = TRUE
- break
- if(!has_watchers)
- effective_luck *= 0.5
+/// When a light we track breaks, there's a chance of zapping us
+/datum/component/omen/proc/check_break_zap(obj/machinery/light/evil_light, was_ok)
+ SIGNAL_HANDLER
+
+ if(was_ok && !HAS_TRAIT(parent, TRAIT_SHOCKIMMUNE) && roll_for_accident(10))
+ evil_light.visible_message(span_boldwarning("A bolt of electricity jumps from [evil_light] to [parent] as it breaks!"))
+ light_zap(evil_light)
+ consume_omen()
+ // always untrack because it's broken now
+ untrack_light(evil_light)
- if(!prob(8 * effective_luck))
+/// When a light we track is toggled on or off, there's a chance of zapping us
+/datum/component/omen/proc/check_toggle_zap(obj/machinery/light/evil_light, new_status)
+ SIGNAL_HANDLER
+
+ if(HAS_TRAIT(parent, TRAIT_SHOCKIMMUNE) || !roll_for_accident(20))
return
- var/our_guy_pos = get_turf(living_guy)
- for(var/obj/machinery/door/airlock/darth_airlock in our_guy_pos)
- if(darth_airlock.locked || !darth_airlock.hasPower())
- continue
+ evil_light.visible_message(span_boldwarning("A bolt of electricity jumps from [evil_light] to [parent] as it turns [new_status ? "on" : "off"]!"))
+ light_zap(evil_light)
+ consume_omen()
+ // we're about to break it, so untrack to avoid a double zap
+ untrack_light(evil_light)
+ // and then actually break the thing
+ evil_light.break_light_tube()
+
+/// Zap the target with electricity from a light fixture
+/datum/component/omen/proc/light_zap(obj/machinery/light/evil_light)
+ PRIVATE_PROC(TRUE)
+
+ var/mob/living/target = parent
+ evil_light.Beam(target, icon_state = "lightning[rand(1, 12)]", time = 0.5 SECONDS)
+ target.electrocute_act(35 * damage_mod, evil_light, flags = SHOCK_NOGLOVES)
+ INVOKE_ASYNC(target, TYPE_PROC_REF(/mob, emote), "scream")
+ consume_omen()
+
+/// Randomly burst into flames
+/datum/component/omen/proc/spontaneous_combustion()
+ var/mob/living/target = parent
+ target.adjust_fire_stacks(20)
+ if(!target.ignite_mob(silent = TRUE))
+ return FALSE
+
+ target.visible_message(
+ span_danger("[target] suddenly bursts into flames!"),
+ span_userdanger("You suddenly burst into flames!"),
+ )
+ INVOKE_ASYNC(target, TYPE_PROC_REF(/mob, emote), "scream")
+ consume_omen()
+ return TRUE
+
+/// Every time we move we need to check a few things for potential incidents
+/datum/component/omen/proc/check_accident(mob/living/source)
+ SIGNAL_HANDLER
+
+ if(mirror_interaction())
+ return
- to_chat(living_guy, span_warning("A malevolent force launches your body to the floor..."))
- living_guy.Paralyze(1 SECONDS, ignore_canstun = TRUE)
- INVOKE_ASYNC(src, PROC_REF(slam_airlock), darth_airlock)
+ if(fall_down())
return
- for(var/turf/the_turf as anything in get_adjacent_open_turfs(living_guy))
- if(istype(the_turf, /turf/open/floor/glass/reinforced/tram)) // don't fall off the tram bridge, we want to hit you instead
- return
- if(living_guy.can_z_move(DOWN, the_turf, z_move_flags = ZMOVE_FALL_FLAGS))
- to_chat(living_guy, span_warning("A malevolent force guides you towards the edge..."))
- living_guy.throw_at(the_turf, 1, 10, force = MOVE_FORCE_EXTREMELY_STRONG)
- consume_omen()
- return
-
- for(var/obj/machinery/vending/darth_vendor in the_turf)
- if(!darth_vendor.tiltable || darth_vendor.tilted)
- continue
- to_chat(living_guy, span_warning("A malevolent force tugs at the [darth_vendor]..."))
- INVOKE_ASYNC(darth_vendor, TYPE_PROC_REF(/obj/machinery/vending, tilt), living_guy)
- consume_omen()
- return
-
- for(var/obj/machinery/light/evil_light in the_turf)
- if((evil_light.status == LIGHT_BURNED || evil_light.status == LIGHT_BROKEN) || (HAS_TRAIT(living_guy, TRAIT_SHOCKIMMUNE))) // we cant do anything :( // Why in the world is there no get_siemens_coeff proc???
- to_chat(living_guy, span_warning("[evil_light] sparks weakly for a second."))
- do_sparks(2, FALSE, evil_light) // hey maybe it'll ignite them
- return
-
- to_chat(living_guy, span_warning("[evil_light] glows ominously...")) // omenously
- evil_light.visible_message(span_boldwarning("[evil_light] suddenly flares brightly and sparks!"))
- evil_light.break_light_tube(skip_sound_and_sparks = FALSE)
- do_sparks(number = 4, cardinal_only = FALSE, source = evil_light)
- evil_light.Beam(living_guy, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS)
- living_guy.electrocute_act(35 * (damage_mod * 0.5), evil_light, flags = SHOCK_NOGLOVES)
- INVOKE_ASYNC(living_guy, TYPE_PROC_REF(/mob, emote), "scream")
- consume_omen()
-
- for(var/obj/structure/mirror/evil_mirror in the_turf)
- to_chat(living_guy, span_warning("You pass by the mirror and glance at it..."))
- if(evil_mirror.broken)
- to_chat(living_guy, span_notice("You feel lucky, somehow."))
- return
- switch(rand(1, 5))
- if(1)
- to_chat(living_guy, span_warning("The mirror explodes into a million pieces! Wait, does that mean you're even more unlucky?"))
- evil_mirror.take_damage(evil_mirror.max_integrity, BRUTE, MELEE, FALSE)
- if(prob(50 * effective_luck)) // sometimes
- luck_mod += 0.25
- damage_mod += 0.25
- if(2 to 3)
- to_chat(living_guy, span_big(span_hypnophrase("Oh god, you can't see your reflection!!")))
- if(HAS_TRAIT(living_guy, TRAIT_NO_MIRROR_REFLECTION)) // not so living i suppose
- to_chat(living_guy, span_green("Well, obviously."))
- return
- INVOKE_ASYNC(living_guy, TYPE_PROC_REF(/mob, emote), "scream")
-
- if(4 to 5)
- if(HAS_TRAIT(living_guy, TRAIT_NO_MIRROR_REFLECTION))
- to_chat(living_guy, span_warning("You don't see anything of notice. Huh."))
- return
- to_chat(living_guy, span_userdanger("You see your reflection, but it is grinning malevolently and staring directly at you!"))
- INVOKE_ASYNC(living_guy, TYPE_PROC_REF(/mob, emote), "scream")
-
- living_guy.set_jitter_if_lower(25 SECONDS)
- if(prob(7 * effective_luck))
- to_chat(living_guy, span_warning("You are completely shocked by this turn of events!"))
- to_chat(living_guy, span_userdanger("You clutch at your heart!"))
- var/mob/living/carbon/carbon_guy = living_guy
- if(istype(carbon_guy))
- carbon_guy.set_heartattack(status = TRUE)
-
- consume_omen()
-
-/datum/component/omen/proc/slam_airlock(obj/machinery/door/airlock/darth_airlock)
- . = darth_airlock.close(force_crush = TRUE)
- if(.)
+/// Attempts to throw us down a nearby open space
+/datum/component/omen/proc/fall_down()
+ var/mob/living/our_guy = parent
+ var/turf/open/mob_turf = get_turf(our_guy)
+ if(isgroundlessturf(mob_turf) || istype(mob_turf, /turf/open/floor/glass/reinforced/tram)) // snowflake check is to increase likelihood of being hit with the tram
+ return FALSE
+
+ for(var/turf/adjacent_turf as anything in get_adjacent_open_turfs(mob_turf))
+ if(!our_guy.can_z_move(DOWN, adjacent_turf, z_move_flags = ZMOVE_FALL_FLAGS))
+ continue
+ if(!roll_for_accident(4))
+ return FALSE
+
+ var/obj/structure/railing/rail = locate() in mob_turf
+ to_chat(our_guy, span_warning("As you step on [mob_turf], you lose footing and fall[rail ? " over the railing and" : ""] off the edge!"))
+ our_guy.throw_at(adjacent_turf, 1, 10, force = MOVE_FORCE_EXTREMELY_STRONG)
consume_omen()
+ return TRUE
+
+ return FALSE
+
+/// Gaze into a mirror and see if something bad happens
+/datum/component/omen/proc/mirror_interaction()
+ var/mob/living/our_guy = parent
+ var/obj/structure/mirror/evil_mirror = locate() in get_turf(our_guy)
+ if(isnull(evil_mirror) || !roll_for_accident(10))
+ REMOVE_TRAIT(our_guy, TRAIT_NO_MIRROR_REFLECTION, REF(src))
+ return FALSE
+
+ to_chat(our_guy, span_warning("You pass by the mirror and glance at it..."))
+ if(evil_mirror.broken)
+ to_chat(our_guy, span_notice("...You feel lucky, somehow."))
+ return TRUE
+
+ switch(rand(1, 5))
+ if(1)
+ to_chat(our_guy, span_warning("...The mirror explodes into a million pieces! Wait, does that mean you're even more unlucky?"))
+ evil_mirror.take_damage(evil_mirror.max_integrity, BRUTE, MELEE, FALSE)
+ if(roll_for_accident(20))
+ luck_mod += 0.25
+ damage_mod += 0.25
+
+ if(2 to 3)
+ if(HAS_TRAIT(our_guy, TRAIT_NO_MIRROR_REFLECTION)) // not so living i suppose
+ to_chat(our_guy, span_green("...Oh god, you can't see your reflection - wait, that's normal."))
+ return TRUE
+ to_chat(our_guy, span_big(span_hypnophrase("...Oh god, you can't see your reflection!!")))
+ INVOKE_ASYNC(our_guy, TYPE_PROC_REF(/mob, emote), "scream")
+ ADD_TRAIT(our_guy, TRAIT_NO_MIRROR_REFLECTION, REF(src))
+
+ if(4 to 5)
+ if(HAS_TRAIT(our_guy, TRAIT_NO_MIRROR_REFLECTION))
+ to_chat(our_guy, span_warning("...but you don't see anything of notice."))
+ return TRUE
+ to_chat(our_guy, span_userdanger("You see your reflection, but it is grinning malevolently and staring directly at you!"))
+ INVOKE_ASYNC(our_guy, TYPE_PROC_REF(/mob, emote), "scream")
+
+ our_guy.set_jitter_if_lower(25 SECONDS)
+ if(roll_for_accident(2))
+ to_chat(our_guy, span_warning("You are completely shocked by this turn of events!"))
+ to_chat(our_guy, span_userdanger("You clutch at your heart!"))
+ if(iscarbon(our_guy))
+ var/mob/living/carbon/carbon_guy = our_guy
+ carbon_guy.set_heartattack(status = TRUE)
+
+ consume_omen()
+ return TRUE
/// If we get knocked down, see if we have a really bad slip and bash our head hard
/datum/component/omen/proc/check_slip(mob/living/our_guy, amount)
SIGNAL_HANDLER
- if(prob(30)) // AAAA
- INVOKE_ASYNC(our_guy, TYPE_PROC_REF(/mob, emote), "scream")
- to_chat(our_guy, span_warning("What a horrible night... To have a curse!"))
-
- if(prob(30 * luck_mod)) /// Bonk!
- var/obj/item/bodypart/the_head = our_guy.get_bodypart(BODY_ZONE_HEAD)
- if(!the_head)
- return
- playsound(our_guy, 'sound/effects/tableheadsmash.ogg', 90, TRUE)
- our_guy.visible_message(span_danger("[our_guy] hits [our_guy.p_their()] head really badly falling down!"), span_userdanger("You hit your head really badly falling down!"))
- our_guy.apply_damage(75 * damage_mod, BRUTE, the_head, attacking_item = "slipping")
- our_guy.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100 * damage_mod)
- consume_omen()
+ if(!our_guy.get_bodypart(BODY_ZONE_HEAD) || !roll_for_accident(15)) // Bonk!
+ return
- return
+ playsound(our_guy, 'sound/effects/tableheadsmash.ogg', 90, TRUE)
+ our_guy.visible_message(
+ span_danger("[our_guy] hits [our_guy.p_their()] head really badly falling down!"),
+ span_userdanger("You hit your head really badly falling down!"),
+ )
+ our_guy.apply_damage(75 * damage_mod, BRUTE, BODY_ZONE_HEAD, attacking_item = "slipping")
+ our_guy.apply_damage(100 * damage_mod, BRAIN)
+ consume_omen()
/// Hijack the mood system to see if we get the blessing mood event to cancel the omen
-/datum/component/omen/proc/check_bless(mob/living/our_guy, category)
+/datum/component/omen/proc/check_bless(mob/living/our_guy, mob/blesser, obj/item/bible, bless_result)
SIGNAL_HANDLER
- if(incidents_left == INFINITY)
- return
-
- if(!("blessing" in our_guy.mob_mood.mood_events))
+ if(incidents_left == INFINITY || !bless_result/* != BLESSING_SUCCESS*/ || !bless_fixable)
return
playsound(our_guy, 'sound/effects/pray_chaplain.ogg', 40, TRUE)
@@ -237,6 +334,7 @@
/datum/component/omen/proc/check_death(mob/living/our_guy)
SIGNAL_HANDLER
+ on_death?.Invoke(src)
if(incidents_left == INFINITY)
return
@@ -256,53 +354,6 @@
UnregisterSignal(vessel, COMSIG_QDELETING)
vessel = null
-/**
- * The smite omen. Permanent.
- */
-/datum/component/omen/smite
-
-/datum/component/omen/smite/check_death(mob/living/our_guy)
- if(incidents_left == INFINITY)
- return ..()
-
- death_explode(our_guy)
- our_guy.gib(DROP_ALL_REMAINS)
-
-/**
- * The quirk omen. Permanent.
- * Has only a 50% chance of bad things happening, and takes only 25% of normal damage.
- */
-/datum/component/omen/quirk
- incidents_left = INFINITY
- luck_mod = 0.3 // 30% chance of bad things happening
- damage_mod = 0.25 // 25% of normal damage
-
-/datum/component/omen/quirk/RegisterWithParent()
- RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(check_accident))
- RegisterSignal(parent, COMSIG_ON_CARBON_SLIP, PROC_REF(check_slip))
- RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(check_death))
-
-/datum/component/omen/quirk/UnregisterFromParent()
- UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH))
-
-/datum/component/omen/quirk/check_death(mob/living/our_guy)
- if(!iscarbon(our_guy))
- our_guy.gib(DROP_ALL_REMAINS)
- return
-
- // Don't explode if buckled to a stasis bed
- if(our_guy.buckled)
- var/obj/machinery/stasis/stasis_bed = our_guy.buckled
- if(istype(stasis_bed))
- return
-
- death_explode(our_guy)
- var/mob/living/carbon/player = our_guy
- player.spread_bodyparts()
- player.spawn_gibs()
-
- return
-
/**
* The bible omen.
* While it lasts, parent gets a cursed aura filter.
diff --git a/code/datums/elements/rust.dm b/code/datums/elements/rust.dm
index 135f45b7c2f3..e94e3703ad77 100644
--- a/code/datums/elements/rust.dm
+++ b/code/datums/elements/rust.dm
@@ -51,12 +51,10 @@
/datum/element/rust/proc/handle_tool_use(atom/source, mob/user, obj/item/item)
switch(item.tool_behaviour)
if(TOOL_WELDER)
- if(!item.tool_start_check(user, amount=1))
+ if(!item.tool_start_check(user, amount = 1))
return
-
user.balloon_alert(user, "burning off rust...")
-
- if(!item.use_tool(source, user, 5 SECONDS))
+ if(!item.use_tool(source, user, 5 SECONDS, amount = 1, volume = 50))
return
user.balloon_alert(user, "burned off rust")
Detach(source)
@@ -67,7 +65,7 @@
if(!item.tool_start_check(user))
return
user.balloon_alert(user, "scraping off rust...")
- if(!item.use_tool(source, user, 2 SECONDS))
+ if(!item.use_tool(source, user, 2 SECONDS, volume = 50))
return
user.balloon_alert(user, "scraped off rust")
Detach(source)
diff --git a/code/datums/mood.dm b/code/datums/mood.dm
index 890b5bf022ce..206b25a7ab0d 100644
--- a/code/datums/mood.dm
+++ b/code/datums/mood.dm
@@ -610,6 +610,9 @@
else
msg += "• [span_grey("I don't have much of a reaction to anything right now.")]
"
+ if(LAZYLEN(mob_parent.personalities))
+ msg += span_notice("You know yourself to be [mob_parent.get_parsonality_string()].
")
+
if(LAZYLEN(mob_parent.quirks))
msg += span_notice("You have these quirks: [mob_parent.get_quirk_string(FALSE, CAT_QUIRK_ALL)].")
@@ -798,20 +801,23 @@
switch(esanity)
if (0 to 10)
new_screen = mob_parent.overlay_fullscreen("sanity", /atom/movable/screen/fullscreen/sanity, 4)
- mob_parent.add_client_colour(/datum/client_colour/sanity/tier4, "sanity")
+ mob_parent.add_client_colour(/datum/client_colour/sanity/tier4)
if (10 to 20)
new_screen = mob_parent.overlay_fullscreen("sanity", /atom/movable/screen/fullscreen/sanity, 3)
- mob_parent.add_client_colour(/datum/client_colour/sanity/tier3, "sanity")
+ mob_parent.add_client_colour(/datum/client_colour/sanity/tier3)
if (20 to 30)
new_screen = mob_parent.overlay_fullscreen("sanity", /atom/movable/screen/fullscreen/sanity, 2)
- mob_parent.add_client_colour(/datum/client_colour/sanity/tier2, "sanity")
+ mob_parent.add_client_colour(/datum/client_colour/sanity/tier2)
if (30 to 40)
new_screen = mob_parent.overlay_fullscreen("sanity", /atom/movable/screen/fullscreen/sanity, 1)
- mob_parent.add_client_colour(/datum/client_colour/sanity/tier1, "sanity")
+ mob_parent.add_client_colour(/datum/client_colour/sanity/tier1)
else
mob_parent.clear_fullscreen("sanity")
mob_parent.clear_fullscreen("sanity_static")
- mob_parent.remove_client_colour("sanity")
+ mob_parent.remove_client_colour(/datum/client_colour/sanity/tier4)
+ mob_parent.remove_client_colour(/datum/client_colour/sanity/tier3)
+ mob_parent.remove_client_colour(/datum/client_colour/sanity/tier2)
+ mob_parent.remove_client_colour(/datum/client_colour/sanity/tier1)
if(new_screen && old_state != new_screen.icon_state)
// updating static effect for new sanity level
diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm
index 36363d46ab1e..2098400b217c 100644
--- a/code/datums/quirks/_quirk.dm
+++ b/code/datums/quirks/_quirk.dm
@@ -198,45 +198,3 @@
to_chat(quirk_holder, chat_string)
where_items_spawned = null
-
-/**
- * get_quirk_string() is used to get a printable string of all the quirk traits someone has for certain criteria
- *
- * Arguments:
- * * Medical- If we want the long, fancy descriptions that show up in medical records, or if not, just the name
- * * Category- Which types of quirks we want to print out. Defaults to everything
- * * from_scan- If the source of this call is like a health analyzer or HUD, in which case QUIRK_HIDE_FROM_MEDICAL hides the quirk.
- */
-/mob/living/proc/get_quirk_string(medical = FALSE, category = CAT_QUIRK_ALL, from_scan = FALSE, none_text)
- var/list/dat = list()
- for(var/datum/quirk/candidate as anything in quirks)
- if(from_scan && (candidate.quirk_flags & QUIRK_HIDE_FROM_SCAN))
- continue
- if(medical && !candidate.medical_record_text)
- continue
- switch(category)
- if(CAT_QUIRK_MAJOR_DISABILITY)
- if(candidate.value >= -4)
- continue
- if(CAT_QUIRK_MINOR_DISABILITY)
- if(!ISINRANGE(candidate.value, -4, -1))
- continue
- if(CAT_QUIRK_NOTES)
- if(candidate.value < 0)
- continue
- dat += medical ? candidate.medical_record_text : candidate.name
-
- if(!dat.len)
- return isnull(none_text) ? (medical ? "No issues have been declared." : "None") : none_text
- return medical ? dat.Join("
") : dat.Join(", ")
-
-/mob/living/proc/cleanse_quirk_datums() //removes all trait datums
- QDEL_LAZYLIST(quirks)
-
-/mob/living/proc/transfer_quirk_datums(mob/living/to_mob)
- // We could be done before the client was moved or after the client was moved
- var/datum/preferences/to_pass = client || to_mob.client
-
- for(var/datum/quirk/quirk as anything in quirks)
- quirk.remove_from_current_holder(quirk_transfer = TRUE)
- quirk.add_to_holder(to_mob, quirk_transfer = TRUE, client_source = to_pass)
diff --git a/code/datums/quirks/negative_quirks/cursed.dm b/code/datums/quirks/negative_quirks/cursed.dm
index f58d31be28e4..6063d15dccb9 100644
--- a/code/datums/quirks/negative_quirks/cursed.dm
+++ b/code/datums/quirks/negative_quirks/cursed.dm
@@ -10,4 +10,25 @@
hardcore_value = 8
/datum/quirk/cursed/add(client/client_source)
- quirk_holder.AddComponent(/datum/component/omen/quirk)
+ quirk_holder.AddComponent( \
+ /datum/component/omen, \
+ incidents_left = INFINITY, \
+ luck_mod = 0.3, \
+ damage_mod = 0.25, \
+ bless_fixable = FALSE, \
+ on_death = CALLBACK(src, PROC_REF(on_death)), \
+ )
+
+/datum/quirk/cursed/proc/on_death(datum/component/omen/omen)
+ var/mob/living/carbon/cursed = omen.parent
+ if(!iscarbon(cursed))
+ cursed.gib(DROP_ALL_REMAINS)
+ return
+
+ // Don't explode if buckled to a stasis bed
+ if(istype(cursed.buckled, /obj/machinery/stasis))
+ return
+
+ omen.death_explode(cursed)
+ cursed.spread_bodyparts()
+ cursed.spawn_gibs()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index e8584049e681..a83454b681e4 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1310,6 +1310,11 @@
if(!dangerous_close)
for(var/turf/checked_turf in locs)
for(var/atom/movable/blocking in checked_turf)
+ var/sigreturn = SEND_SIGNAL(blocking, COMSIG_MOVABLE_BLOCKING_AIRLOCK, src, forced, force_crush)
+ if(sigreturn & AIRLOCK_BLOCK_FORCE_CRUSH)
+ dangerous_close = TRUE
+ continue
+
if(blocking.density && blocking != src)
autoclose_in(DOOR_CLOSE_WAIT)
return FALSE
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 3da43c1294f3..f4c7010fc97b 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -179,16 +179,33 @@ GLOBAL_LIST_INIT(dye_registry, list(
icon_state = "wm_1_0"
density = TRUE
state_open = TRUE
+ custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/glass = SHEET_MATERIAL_AMOUNT)
+ circuit = /obj/item/circuitboard/machine/washing_machine
var/busy = FALSE
var/bloody_mess = FALSE
var/obj/item/color_source
- var/max_wash_capacity = 5
+ /// The max amount of items that can be washed per load
+ var/max_wash_capacity
+ /// The time it takes to wash a load of laundry
+ var/time_to_wash
+ /// The current number of items inserted
+ var/total_load = 0
/obj/machinery/washing_machine/examine(mob/user)
. = ..()
if(!busy)
. += span_notice("Right-click with an empty hand to start a wash cycle.")
+/obj/machinery/washing_machine/RefreshParts()
+ . = ..()
+ var/total_volume = 0
+ for(var/obj/item/reagent_containers/cup/beaker/beaker in component_parts)
+ total_volume += beaker.reagents.maximum_volume
+ max_wash_capacity = floor(total_volume/20)
+
+ for(var/datum/stock_part/servo/servo in component_parts)
+ time_to_wash = 20 SECONDS / servo.tier
+
/obj/machinery/washing_machine/process(seconds_per_tick)
if(!busy)
animate(src, transform=matrix(), time=2)
@@ -320,7 +337,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
icon_state = "wm_[state_open]_blood"
return ..()
- var/full = contents.len ? 1 : 0
+ var/full = total_load ? 1 : 0
icon_state = "wm_[state_open]_[full]"
return ..()
@@ -352,7 +369,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
if(bloody_mess)
to_chat(user, span_warning("[src] must be cleaned up first!"))
return ITEM_INTERACT_BLOCKING
- if(contents.len >= max_wash_capacity)
+ if(total_load >= max_wash_capacity)
to_chat(user, span_warning("The washing machine is full!"))
return ITEM_INTERACT_BLOCKING
if(!user.transferItemToLoc(item, src))
@@ -360,6 +377,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
return ITEM_INTERACT_BLOCKING
if(item.dye_color)
color_source = item
+ total_load++
update_appearance()
return ITEM_INTERACT_SUCCESS
@@ -408,7 +426,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
if(HAS_TRAIT(user, TRAIT_BRAINWASHING))
ADD_TRAIT(src, TRAIT_BRAINWASHING, SKILLCHIP_TRAIT)
update_appearance()
- addtimer(CALLBACK(src, PROC_REF(wash_cycle)), 20 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(wash_cycle), user), time_to_wash)
START_PROCESSING(SSfastprocess, src)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
@@ -422,3 +440,4 @@ GLOBAL_LIST_INIT(dye_registry, list(
. = ..()
set_density(TRUE) //because machinery/open_machine() sets it to FALSE
color_source = null
+ total_load = 0
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 8e168b25f082..9985f87dacf3 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -16,6 +16,8 @@
var/can_dry = TRUE
/// Is this blood dried out?
var/dried = FALSE
+ /// Do we delete ourselves when we dry out?
+ var/qdel_on_dry = FALSE
/// How much our blood glows, up to 255 (it's the alpha of the EM overlay). 0 = no glow
var/emissive_alpha = 0
@@ -43,6 +45,9 @@
if(mapload || starting_dna)
init_dna(starting_dna)
if(dried)
+ if(qdel_on_dry)
+ stack_trace("Blood decal set to dry on init but qdel on dry, you probably don't want that?")
+ qdel_on_dry = FALSE
dry()
else if(can_dry)
START_PROCESSING(SSblood_drying, src)
@@ -159,6 +164,8 @@
update_atom_colour()
STOP_PROCESSING(SSblood_drying, src)
clear_smells()
+ if(qdel_on_dry)
+ qdel(src)
return TRUE
/obj/effect/decal/cleanable/blood/adjust_bloodiness(by_amount)
diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
index 260e1e87a592..7f290b93178d 100644
--- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
@@ -725,6 +725,16 @@
/datum/stock_part/scanning_module = 1,
)
+/obj/item/circuitboard/machine/photocopier
+ name = "Photocopier"
+ greyscale_colors = CIRCUIT_COLOR_GENERIC
+ build_path = /obj/machinery/photocopier
+ req_components = list(
+ /datum/stock_part/scanning_module = 1,
+ /datum/stock_part/micro_laser = 1,
+ /datum/stock_part/matter_bin = 1
+ )
+
//Medical
/obj/item/circuitboard/machine/chem_dispenser
@@ -1651,3 +1661,23 @@
/datum/stock_part/capacitor = 2,
/datum/stock_part/micro_laser = 2,
/obj/item/stack/sheet/glass = 1)
+
+// /obj/item/circuitboard/machine/atmos_shield_gen
+// name = /obj/machinery/atmos_shield_gen::name
+// greyscale_colors = CIRCUIT_COLOR_ENGINEERING
+// build_path = /obj/machinery/atmos_shield_gen
+// req_components = list(
+// /datum/stock_part/micro_laser = 1,
+// /datum/stock_part/capacitor = 1,
+// )
+
+/obj/item/circuitboard/machine/washing_machine
+ name = "Washing Machine"
+ greyscale_colors = CIRCUIT_COLOR_SERVICE
+ build_path = /obj/machinery/washing_machine
+ req_components = list(
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/reagent_containers/cup/beaker = 2,
+ /datum/stock_part/water_recycler = 1,
+ /datum/stock_part/servo = 1,
+ )
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index c0ea987aaca4..fa2d8ada6435 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -17,7 +17,10 @@
w_class = WEIGHT_CLASS_SMALL
obj_flags = CONDUCTS_ELECTRICITY
slot_flags = ITEM_SLOT_BELT
- custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 0.2)
+ custom_materials = list(
+ /datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5,
+ /datum/material/glass = SMALL_MATERIAL_AMOUNT * 0.2,
+ )
actions_types = list(/datum/action/item_action/toggle_light)
action_slots = ALL
light_system = OVERLAY_LIGHT_DIRECTIONAL
@@ -435,7 +438,11 @@
var/trash_type = /obj/item/trash/flare
/// If the light source can be extinguished
var/can_be_extinguished = FALSE
- custom_materials = list(/datum/material/plastic= SMALL_MATERIAL_AMOUNT * 0.5)
+ custom_materials = list(
+ /datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5,
+ /datum/material/plasma = SMALL_MATERIAL_AMOUNT * 0.5,
+ /datum/material/plastic = SMALL_MATERIAL_AMOUNT * 0.5,
+ )
/obj/item/flashlight/flare/Initialize(mapload)
. = ..()
@@ -693,6 +700,26 @@
slot_flags = null
trash_type = /obj/effect/decal/cleanable/ash
can_be_extinguished = TRUE
+ custom_materials = list(/datum/material/wood = SMALL_MATERIAL_AMOUNT*0.5)
+
+/obj/item/flashlight/flare/torch/on
+ start_on = TRUE
+
+/obj/item/flashlight/flare/torch/everburning
+ name = "everburning torch"
+ desc = "A torch which burns continuously, even in the vacuum of space"
+ can_be_extinguished = FALSE
+ fuel = INFINITY
+ randomize_fuel = FALSE
+ start_on = TRUE
+ custom_materials = null
+
+/obj/item/flashlight/flare/torch/red
+ color = "#ff0000"
+ light_range = 2
+
+/obj/item/flashlight/flare/torch/red/on
+ start_on = TRUE
/obj/item/flashlight/lantern
name = "lantern"
@@ -817,6 +844,7 @@
/// How many seconds of fuel we have left
var/fuel = 0
ignore_base_color = TRUE
+ custom_materials = null
/obj/item/flashlight/glowstick/Initialize(mapload)
fuel = rand(50 MINUTES, 60 MINUTES)
diff --git a/code/game/objects/items/food/burgers.dm b/code/game/objects/items/food/burgers.dm
index 95b40f03d32a..ec00d39899bc 100644
--- a/code/game/objects/items/food/burgers.dm
+++ b/code/game/objects/items/food/burgers.dm
@@ -659,6 +659,12 @@
tastes = list("bun" = 2, "beef patty" = 4, "cheese" = 2, "beef soaked in chili" = 3, "a smoking flare" = 2)
foodtypes = GRAIN | MEAT | DAIRY | VEGETABLES
crafting_complexity = FOOD_COMPLEXITY_4
+ // custom_materials = list(
+ // /datum/material/meat = MEATDISH_MATERIAL_AMOUNT * 2,
+ // /datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5,
+ // /datum/material/plasma = SMALL_MATERIAL_AMOUNT * 0.5,
+ // /datum/material/plastic = SMALL_MATERIAL_AMOUNT * 0.5,
+ // )
/obj/item/food/burger/crazy/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 7a137cde9a4b..cf78ac563bab 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -437,6 +437,7 @@ GLOBAL_LIST_INIT(adamantine_recipes, list(
GLOBAL_LIST_INIT(abductor_recipes, list ( \
new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), \
new/datum/stack_recipe("alien locker", /obj/structure/closet/abductor, 2, time = 2 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), \
+ new/datum/stack_recipe("strange closet", /obj/structure/closet/acloset, 2, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_CONTAINERS), \
new/datum/stack_recipe("alien table frame", /obj/structure/table_frame/abductor, 1, time = 2 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), \
new/datum/stack_recipe("alien airlock assembly", /obj/structure/door_assembly/door_assembly_abductor, 4, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_DOORS), \
null, \
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 908cc0d4f7b8..d507c41e6652 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -272,6 +272,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 5 SECONDS, crafting_flags = NONE, category = CAT_CHEMISTRY),
new/datum/stack_recipe("Large Gas Tank", /obj/structure/tank_frame, 4, time=1 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF, category = CAT_ATMOSPHERIC),
new/datum/stack_recipe("shutter assembly", /obj/machinery/door/poddoor/shutters/preopen/deconstructed, 5, time = 5 SECONDS, crafting_flags = CRAFT_ONE_PER_TURF, category = CAT_DOORS),
+ new/datum/stack_recipe("large metal box", /obj/structure/closet/cardboard/metal, 4, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_CONTAINERS),
null,
new /datum/stack_recipe_list("airlock assemblies", list( \
new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_DOORS),
@@ -336,6 +337,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("wooden barrel", /obj/structure/fermenting_barrel, 8, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_CONTAINERS), \
new/datum/stack_recipe("dog bed", /obj/structure/bed/dogbed, 10, time = 1 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), \
new/datum/stack_recipe("dresser", /obj/structure/dresser, 10, time = 1.5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), \
+ new/datum/stack_recipe("cabinet", /obj/structure/closet/cabinet, 2, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_CONTAINERS), \
new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 1 SECONDS, crafting_flags = NONE, category = CAT_ENTERTAINMENT),\
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 1 SECONDS, crafting_flags = NONE, category = CAT_ENTERTAINMENT),\
new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), \
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 523d8f6d79b0..b50753449122 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets)
/// How insulated the thing is, for the purposes of calculating body temperature. Must be between 0 and 1!
contents_thermal_insulation = 0
pass_flags_self = PASSSTRUCTURE | LETPASSCLICKS
-
+ custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2)
/// The overlay for the closet's door
var/obj/effect/overlay/closet_door/door_obj
/// Whether or not this door is being animated
diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
index b398731e7d8a..b532fa9b2d89 100644
--- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
+++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
@@ -9,6 +9,8 @@
can_weld_shut = 0
cutting_tool = /obj/item/wirecutters
material_drop = /obj/item/stack/sheet/cardboard
+ material_drop_amount = 4
+ custom_materials = list(/datum/material/cardboard = SHEET_MATERIAL_AMOUNT * 4)
delivery_icon = "deliverybox"
anchorable = FALSE
open_sound = 'sound/machines/cardboard_box.ogg'
@@ -117,4 +119,5 @@
close_sound = 'sound/machines/crate_close.ogg'
open_sound_volume = 35
close_sound_volume = 50
+ custom_materials = list(/datum/material/alloy/plasteel = SHEET_MATERIAL_AMOUNT * 4)
material_drop = /obj/item/stack/sheet/plasteel
diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
index 2ee4f780ff3c..73c2eee5321b 100644
--- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm
+++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
@@ -9,12 +9,15 @@
close_sound_volume = 50
max_integrity = 70
door_anim_time = 0 // no animation
+ material_drop = /obj/item/stack/sheet/mineral/wood
+ custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 2)
/obj/structure/closet/acloset
name = "strange closet"
desc = "It looks alien!"
icon_state = "alien"
material_drop = /obj/item/stack/sheet/mineral/abductor
+ custom_materials = list(/datum/material/alloy/alien = SHEET_MATERIAL_AMOUNT * 2)
/obj/structure/closet/gimmick
name = "administrative supply closet"
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
index d0487198d4c7..5b5676c26e47 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
@@ -45,6 +45,8 @@
open_sound_volume = 25
close_sound_volume = 50
door_anim_time = 0 // no animation
+ custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 2)
+ material_drop = /obj/item/stack/sheet/mineral/wood
/obj/structure/closet/secure_closet/personal/cabinet/PopulateContents()
new /obj/item/storage/backpack/satchel/leather/withwallet( src )
diff --git a/code/game/objects/structures/crates_lockers/crates/wooden.dm b/code/game/objects/structures/crates_lockers/crates/wooden.dm
index a5e0b78cadb6..b98ee5c1601c 100644
--- a/code/game/objects/structures/crates_lockers/crates/wooden.dm
+++ b/code/game/objects/structures/crates_lockers/crates/wooden.dm
@@ -1,6 +1,7 @@
/obj/structure/closet/crate/wooden
name = "wooden crate"
desc = "Works just as well as a metal one."
+ custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 6)
material_drop = /obj/item/stack/sheet/mineral/wood
material_drop_amount = 6
icon_state = "wooden"
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 93040121f0fd..c4176048e4dc 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -2,7 +2,7 @@
name = "extinguisher cabinet"
desc = "A small wall mounted cabinet designed to hold a fire extinguisher."
icon = 'icons/obj/wallmounts.dmi'
- icon_state = "extinguisher_closed"
+ icon_state = "extinguisher"
anchored = TRUE
density = FALSE
max_integrity = 200
@@ -153,11 +153,12 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/extinguisher_cabinet, 29)
else if(istype(stored_extinguisher, /obj/item/extinguisher))
icon_state += "_default"
- if(!opened)
- icon_state += "_closed"
-
return ..()
+/obj/structure/extinguisher_cabinet/update_overlays()
+ . = ..()
+ . += mutable_appearance(icon, opened ? "door_open" : "door")
+
/obj/structure/extinguisher_cabinet/atom_break(damage_flag)
. = ..()
if(!broken)
@@ -182,6 +183,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/extinguisher_cabinet, 29)
name = "extinguisher cabinet frame"
desc = "Used for building wall-mounted extinguisher cabinets."
icon = 'icons/obj/wallmounts.dmi'
- icon_state = "extinguisher_assembly"
+ icon_state = "extinguisher" //Reuses wallmount icon, but no door overlay
result_path = /obj/structure/extinguisher_cabinet
pixel_shift = 29
diff --git a/code/game/objects/structures/janitor.dm b/code/game/objects/structures/janitor.dm
index 4f5bdf281273..0413bcac5398 100644
--- a/code/game/objects/structures/janitor.dm
+++ b/code/game/objects/structures/janitor.dm
@@ -73,6 +73,7 @@
/obj/structure/mop_bucket/janitorialcart/Initialize(mapload)
. = ..()
+ reagents.maximum_volume *= 2.5
GLOB.janitor_devices += src
/obj/structure/mop_bucket/janitorialcart/Destroy()
diff --git a/code/modules/admin/smites/bad_luck.dm b/code/modules/admin/smites/bad_luck.dm
index 34592dd200d4..82551955a534 100644
--- a/code/modules/admin/smites/bad_luck.dm
+++ b/code/modules/admin/smites/bad_luck.dm
@@ -18,11 +18,23 @@
. = ..()
//if permanent, replace any existing omen
if(incidents == INFINITY)
- var/existing_component = target.GetComponent(/datum/component/omen)
- qdel(existing_component)
- target.AddComponent(/datum/component/omen/smite, incidents_left = incidents)
+ qdel(target.GetComponent(/datum/component/omen))
+ target.AddComponent( \
+ /datum/component/omen, \
+ incidents_left = incidents, \
+ on_death = CALLBACK(src, PROC_REF(on_death)), \
+ bless_fixable = incidents != INFINITY, \
+ )
if(silent)
return
to_chat(target, span_warning("You get a bad feeling..."))
if(incidents == INFINITY)
to_chat(target, span_warning("A very bad feeling... As if malevolent forces are watching you..."))
+
+/datum/smite/bad_luck/proc/on_death(datum/component/omen/omen)
+ if(omen.incidents_left == INFINITY)
+ return
+
+ var/mob/living/our_guy = omen.parent
+ omen.death_explode(our_guy)
+ our_guy.gib(DROP_ALL_REMAINS)
diff --git a/code/modules/clothing/masks/bandana.dm b/code/modules/clothing/masks/bandana.dm
index b5f7b7bf3710..758cb1ddb9a1 100644
--- a/code/modules/clothing/masks/bandana.dm
+++ b/code/modules/clothing/masks/bandana.dm
@@ -72,12 +72,17 @@
widen.Scale(1.25, 1)
transform = widen
user.visible_message(span_notice("[user] ties [src] up like a neckerchief."), span_notice("You tie [src] up like a neckerchief."))
- else
- undyeable = initial(undyeable)
- slot_flags = initial(slot_flags)
- worn_y_offset = initial(worn_y_offset)
- transform = initial(transform)
- user.visible_message(span_notice("[user] unties the neckercheif."), span_notice("You untie the neckercheif."))
+ flags_inv = NONE
+ flags_cover = NONE
+ return CLICK_ACTION_SUCCESS
+
+ undyeable = initial(undyeable)
+ slot_flags = initial(slot_flags)
+ worn_y_offset = initial(worn_y_offset)
+ transform = initial(transform)
+ user.visible_message(span_notice("[user] unties the neckercheif."), span_notice("You untie the neckercheif."))
+ flags_inv = initial(flags_inv)
+ flags_cover = initial(flags_cover)
return CLICK_ACTION_SUCCESS
/obj/item/clothing/mask/bandana/red
diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm
index f02d9e2450a2..f5e704b668fb 100644
--- a/code/modules/forensics/forensics_helpers.dm
+++ b/code/modules/forensics/forensics_helpers.dm
@@ -135,7 +135,7 @@
if(unique_blood[blood_type])
continue
var/datum/blood_type/blood = find_blood_type(blood_type)
- blood.set_up_blood(src, first_dna == 0)
+ blood.set_up_blood(src, first_dna == 0, only_type = length(blood_DNA_to_add) == 1)
unique_blood[blood_type] = TRUE
// handle smells
refresh_smells()
diff --git a/code/modules/library/bibles.dm b/code/modules/library/bibles.dm
index d43fdfa85800..48c0b24d6179 100644
--- a/code/modules/library/bibles.dm
+++ b/code/modules/library/bibles.dm
@@ -212,7 +212,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
if(GLOB.religious_sect)
return GLOB.religious_sect.sect_bless(blessed,user)
if(!ishuman(blessed))
- return
+ return FALSE
var/mob/living/carbon/human/built_in_his_image = blessed
for(var/obj/item/bodypart/bodypart as anything in built_in_his_image.get_bodyparts())
if(!IS_ORGANIC_LIMB(bodypart))
@@ -265,6 +265,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
smack_chance = GLOB.religious_sect.smack_chance
var/success = !prob(smack_chance) && bless(target_mob, user)
if(success)
+ SEND_SIGNAL(target_mob, COMSIG_LIVING_BLESSED, user, src, success)
return
if(iscarbon(target_mob))
var/mob/living/carbon/carbon_target = target_mob
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index bdb7ff67c520..f373c21fa07a 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -495,6 +495,49 @@
return quirk
return null
+/**
+ * get_quirk_string() is used to get a printable string of all the quirk traits someone has for certain criteria
+ *
+ * Arguments:
+ * * Medical- If we want the long, fancy descriptions that show up in medical records, or if not, just the name
+ * * Category- Which types of quirks we want to print out. Defaults to everything
+ * * from_scan- If the source of this call is like a health analyzer or HUD, in which case QUIRK_HIDE_FROM_MEDICAL hides the quirk.
+ */
+/mob/living/proc/get_quirk_string(medical = FALSE, category = CAT_QUIRK_ALL, from_scan = FALSE, none_text)
+ var/list/dat = list()
+ for(var/datum/quirk/candidate as anything in quirks)
+ if(from_scan && (candidate.quirk_flags & QUIRK_HIDE_FROM_SCAN))
+ continue
+ if(medical && !candidate.medical_record_text)
+ continue
+ switch(category)
+ if(CAT_QUIRK_MAJOR_DISABILITY)
+ if(candidate.value >= -4)
+ continue
+ if(CAT_QUIRK_MINOR_DISABILITY)
+ if(!ISINRANGE(candidate.value, -4, -1))
+ continue
+ if(CAT_QUIRK_NOTES)
+ if(candidate.value < 0)
+ continue
+ dat += medical ? candidate.medical_record_text : candidate.name
+
+ if(!dat.len)
+ return isnull(none_text) ? (medical ? "No issues have been declared." : "None") : none_text
+ return medical ? dat.Join("
") : dat.Join(", ")
+
+/mob/living/proc/cleanse_quirk_datums() //removes all trait datums
+ QDEL_LAZYLIST(quirks)
+
+/mob/living/proc/transfer_quirk_datums(mob/living/to_mob)
+ // We could be done before the client was moved or after the client was moved
+ var/datum/preferences/to_pass = client || to_mob.client
+
+ for(var/datum/quirk/quirk as anything in quirks)
+ quirk.remove_from_current_holder(quirk_transfer = TRUE)
+ quirk.add_to_holder(to_mob, quirk_transfer = TRUE, client_source = to_pass)
+
+
/// Helper to easily add a personality by a typepath
/mob/living/proc/add_personality(personality_type)
var/datum/personality/personality = SSpersonalities.personalities_by_type[personality_type]
@@ -515,6 +558,14 @@
for(var/personality_type in personalities)
remove_personality(personality_type)
+/// Returns a string with the names of the personalities of this mob, and their description as tooltip
+/mob/living/proc/get_parsonality_string()
+ var/list/return_list = list()
+ for(var/personality_type in personalities)
+ var/datum/personality/personality = SSpersonalities.personalities_by_type[personality_type]
+ return_list += span_tooltip(personality.desc, personality.name)
+ return english_list(return_list)
+
/mob/living/proc/cure_husk(source)
REMOVE_TRAIT(src, TRAIT_HUSK, source)
if(HAS_TRAIT(src, TRAIT_HUSK))
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 62f4b8581089..9828633fc2e5 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -910,12 +910,17 @@
)
/obj/item/paper/construction
+ name = "construction paper"
+ icon = 'icons/effects/random_spawners.dmi'
/obj/item/paper/construction/Initialize(mapload)
. = ..()
+ icon = 'icons/obj/service/bureaucracy.dmi'
color = pick(COLOR_RED, COLOR_LIME, COLOR_LIGHT_ORANGE, COLOR_DARK_PURPLE, COLOR_FADED_PINK, COLOR_BLUE_LIGHT)
+ update_appearance()
/obj/item/paper/natural
+ name = "natural paper"
color = COLOR_OFF_WHITE
/obj/item/paper/crumpled
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 56f302acbdc1..88e2c27e13f9 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -32,8 +32,8 @@
/// How much paper is used for making a copy of paperwork.
#define PAPERWORK_PAPER_USE 10
-/// Maximum capacity of a photocopier
-#define MAX_PAPER_CAPACITY 60
+/// Paper capacity of a matter bin
+#define MATTER_BIN_PAPER_CAPACITY 30
/// The maximum amount of copies you can make with one press of the copy button.
#define MAX_COPIES_AT_ONCE 10
@@ -62,41 +62,94 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
desc = "Used to copy important documents and anatomy studies."
icon = 'icons/obj/service/library.dmi'
icon_state = "photocopier"
+ base_icon_state = "photocopier"
density = TRUE
power_channel = AREA_USAGE_EQUIP
max_integrity = 300
integrity_failure = 0.33
interaction_flags_mouse_drop = NEED_DEXTERITY | ALLOW_RESTING
-
+ circuit = /obj/item/circuitboard/machine/photocopier
+
+ /// The max paper capacity this photocopier can store
+ var/max_paper_capacity
+ /// How long it takes to print something in seconds
+ var/time_to_print
+ /// How efficent our toner is when printing
+ var/toner_efficiency
/// A reference to a mob on top of the photocopier trying to copy their ass. Null if there is no mob.
var/mob/living/ass
/// A reference to the toner cartridge that's inserted into the copier. Null if there is no cartridge.
var/obj/item/toner/toner_cartridge
+ /// Type path of toner this photocopier should starts with. Null if he should start without it.
+ var/obj/item/toner/starting_toner
/// How many copies will be printed with one click of the "copy" button.
var/num_copies = 1
/// Used with photos. Determines if the copied photo will be in greyscale or color.
var/color_mode = PHOTO_COLOR
/// Indicates whether the printer is currently busy copying or not.
var/busy = FALSE
+ /// How much does it cost to use this photocopier.
+ var/usage_cost = PHOTOCOPIER_FEE
/// Variable that holds a reference to any object supported for photocopying inside the photocopier
var/obj/object_copy
/// Variable for the UI telling us how many copies are in the queue.
var/copies_left = 0
/// The amount of paper this photocoper starts with.
- var/starting_paper = 30
- /// A stack for all the empty paper we have newly inserted (LIFO)
+ var/starting_paper = 0
+ /// The paper loaded into the machine
var/list/paper_stack = list()
-
+ /// Type path to the paper that's created when we're initalized
+ var/created_paper = /obj/item/paper
+ /// Typecache of objects that can be inserted and scanned into the photocopier for copying
+ var/static/list/whitelist_scannable_objects = typecacheof(list(
+ /obj/item/paper,
+ /obj/item/photo,
+ /obj/item/documents,
+ /obj/item/paperwork
+ ))
+ /// List of paper types that can be inserted as blank paper
+ var/static/list/valid_paper_types = list(
+ /obj/item/paper,
+ /obj/item/paper/carbon,
+ /obj/item/paper/construction,
+ /obj/item/paper/natural,
+ )
+
+/obj/machinery/photocopier/prebuilt
+ starting_toner = /obj/item/toner
+ starting_paper = 30
+
+/obj/machinery/photocopier/get_save_vars()
+ . = ..()
+ . += NAMEOF(src, paper_stack)
+ return .
/obj/machinery/photocopier/Initialize(mapload)
. = ..()
- toner_cartridge = new(src)
setup_components()
AddElement(/datum/element/elevation, pixel_shift = 8) //enough to look like your bums are on the machine.
+ if(starting_paper)
+ paper_stack[created_paper] = starting_paper
+ if(starting_toner)
+ toner_cartridge = new starting_toner(src)
/// Simply adds the necessary components for this to function.
/obj/machinery/photocopier/proc/setup_components()
- AddComponent(/datum/component/payment, PHOTOCOPIER_FEE, SSeconomy.get_dep_account(ACCOUNT_CIV), PAYMENT_CLINICAL)
+ AddComponent(/datum/component/payment, usage_cost, SSeconomy.get_dep_account(ACCOUNT_CIV), PAYMENT_CLINICAL)
+
+/obj/machinery/photocopier/RefreshParts()
+ . = ..()
+ max_paper_capacity = 0
+ for(var/datum/stock_part/matter_bin/matter_bin in component_parts)
+ max_paper_capacity += MATTER_BIN_PAPER_CAPACITY * matter_bin.tier
+
+ toner_efficiency = 1
+ for(var/datum/stock_part/micro_laser/micro_laser in component_parts)
+ toner_efficiency += micro_laser.tier
+
+ time_to_print = 5 SECONDS
+ for(var/datum/stock_part/scanning_module/scanning_module in component_parts)
+ time_to_print -= (scanning_module.tier SECONDS)
/obj/machinery/photocopier/Exited(atom/movable/gone, direction)
. = ..()
@@ -104,20 +157,45 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
object_copy = null
if(gone == toner_cartridge)
toner_cartridge = null
- if(gone in paper_stack)
- paper_stack -= gone
+
+/obj/machinery/photocopier/dump_contents()
+ var/dump_location = drop_location()
+
+ // object_copy can be a traitor objective, don't qdel
+ object_copy?.forceMove(dump_location)
+ toner_cartridge?.forceMove(dump_location)
+
+ for(var/paper_path in paper_stack)
+ var/paper_amount = paper_stack[paper_path]
+ if(paper_amount <= 0)
+ stack_trace("Detected zero or negative [paper_path] amount inside photocopier. There should be at least 1 or more of paper amount inside the list")
+ continue
+
+ for(var/i in 1 to paper_amount)
+ var/obj/item/paper/new_paper = new paper_path(dump_location)
+ if(!new_paper.pixel_y)
+ new_paper.pixel_y = rand(-3,3)
+ if(!new_paper.pixel_x)
+ new_paper.pixel_x = rand(-3,3)
+
+ paper_stack.Remove(paper_path)
+
+ update_appearance()
/obj/machinery/photocopier/Destroy()
// object_copy can be a traitor objective, don't qdel
- if(object_copy)
- object_copy.forceMove(drop_location())
+ object_copy?.forceMove(drop_location())
QDEL_NULL(toner_cartridge)
- QDEL_LIST(paper_stack)
-
+ paper_stack = null
ass = null //the mob isn't actually contained and just referenced, no need to delete it.
return ..()
+/obj/machinery/photocopier/on_deconstruction(disassembled)
+ if(disassembled)
+ dump_contents()
+ return ..()
+
/obj/machinery/photocopier/examine(mob/user)
. = ..()
if(object_copy)
@@ -147,7 +225,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
static_data["blanks"] = blank_infos
static_data["categories"] = category_names
- static_data["max_paper_count"] = MAX_PAPER_CAPACITY
+ static_data["max_paper_count"] = max_paper_capacity
static_data["max_copies"] = MAX_COPIES_AT_ONCE
return static_data
@@ -162,9 +240,9 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
data["is_photo"] = TRUE
data["color_mode"] = color_mode
- if(isAI(user))
+ if(isAI(user) || isAdminGhostAI(user))
data["isAI"] = TRUE
- data["can_AI_print"] = toner_cartridge && (toner_cartridge.charges >= PHOTO_TONER_USE) && (get_paper_count() >= PHOTO_PAPER_USE)
+ data["can_AI_print"] = toner_cartridge && (toner_cartridge.charges >= PHOTO_TONER_USE) && (get_paper_count(created_paper) >= PHOTO_PAPER_USE)
else
data["isAI"] = FALSE
@@ -175,11 +253,24 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
else
data["has_toner"] = FALSE
+ data["created_paper"] = created_paper
+ data["paper_stack"] = paper_stack
data["paper_count"] = get_paper_count()
+ var/list/paper_types = list()
+ for(var/obj/item/paper/paper as anything in valid_paper_types)
+ paper_types += list(list(
+ name = paper::name,
+ icon = paper::icon,
+ icon_state = paper::icon_state,
+ amount = paper_stack[paper::type] || 0,
+ type = paper::type,
+ ))
+ data["paper_types"] = paper_types
+
return data
-/obj/machinery/photocopier/ui_act(action, list/params)
+/obj/machinery/photocopier/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
@@ -224,7 +315,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
// Remove the paper/photo/document from the photocopier.
if("remove")
if(object_copy)
- remove_photocopy(object_copy, usr)
+ remove_photocopy(usr, object_copy)
object_copy = null
else if(check_ass())
to_chat(ass, span_notice("You feel a slight pressure on your ass."))
@@ -272,6 +363,20 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
var/list/blank = GLOB.paper_blanks[params["code"]]
do_copies(CALLBACK(src, PROC_REF(make_blank_print), blank), usr, PAPER_PAPER_USE, PAPER_TONER_USE, num_copies)
return TRUE
+ if("select_paper_type")
+ if(check_busy(usr))
+ return FALSE
+
+ var/paper_path = text2path(params["created_paper"])
+
+ if(!ispath(paper_path, /obj/item/paper))
+ return FALSE
+
+ if(!paper_stack[paper_path])
+ return FALSE
+
+ created_paper = paper_path
+ return TRUE
/// Returns the color used for the printing operation. If the color is below TONER_LOW_PERCENTAGE, it returns a gray color.
/obj/machinery/photocopier/proc/get_toner_color()
@@ -286,28 +391,38 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
busy = TRUE
update_use_power(ACTIVE_POWER_USE)
// fucking god proc
- INVOKE_ASYNC(src, PROC_REF(do_copy_loop), copy_cb, user, paper_use, toner_use, copies_amount)
+ INVOKE_ASYNC(src, PROC_REF(do_copy_loop), user, copy_cb, paper_use, toner_use, copies_amount)
+
+/obj/machinery/photocopier/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
+ obj_flags |= EMAGGED
+
+ playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ visible_message(span_warning("Sparks fly out of [src]!"))
+ balloon_alert(user, "payment system shorted")
+ return TRUE
/**
* Will invoke the passed in `copy_cb` callback in 4 second intervals, and charge the user 5 credits for each copy made.
*
* Arguments:
- * * copy_cb - a callback for which proc to call. Should only be one of the `make_x_copy()` procs, such as `make_paper_copy()`.
* * user - the mob who clicked copy.
+ * * copy_cb - a callback for which proc to call. Should only be one of the `make_x_copy()` procs, such as `make_paper_copy()`.
* * paper_use - the amount of paper used in this operation
* * toner_use - the amount of toner used in this operation
* * copies_amount - the amount of copies we should make
*/
-/obj/machinery/photocopier/proc/do_copy_loop(datum/callback/copy_cb, mob/user, paper_use, toner_use, copies_amount)
+/obj/machinery/photocopier/proc/do_copy_loop(mob/user, datum/callback/copy_cb, paper_use, toner_use, copies_amount)
var/error_message = null
if(!toner_cartridge)
copies_amount = 0
error_message = span_warning("An error message flashes across \the [src]'s screen: \"No toner cartridge found. Aborting.\"")
- else if(toner_cartridge.charges < toner_use * copies_amount)
- copies_amount = FLOOR(toner_cartridge.charges / toner_use, 1)
+ else if(toner_cartridge.charges < (toner_use / toner_efficiency) * copies_amount)
+ copies_amount = FLOOR(toner_cartridge.charges / (toner_use / toner_efficiency), 1)
error_message = span_warning("An error message flashes across \the [src]'s screen: \"Not enough toner to perform [copies_amount >= 1 ? "full " : ""]operation.\"")
- if(get_paper_count() < paper_use * copies_amount)
- copies_amount = FLOOR(get_paper_count() / paper_use, 1)
+ if(get_paper_count(created_paper) < paper_use * copies_amount)
+ copies_amount = FLOOR(get_paper_count(created_paper) / paper_use, 1)
error_message = span_warning("An error message flashes across \the [src]'s screen: \"Not enough paper to perform [copies_amount >= 1 ? "full " : ""]operation.\"")
copies_left = copies_amount
@@ -317,14 +432,11 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
reset_busy()
return
- if(attempt_charge(src, user, (copies_amount - 1) * PHOTOCOPIER_FEE) & COMPONENT_OBJ_CANCEL_CHARGE)
- reset_busy()
- return
-
if(error_message)
to_chat(user, error_message)
// if you managed to cancel the copy operation, tough luck. you aren't getting your money back.
+ var/list/copies_made = list()
for(var/i in 1 to copies_amount)
if(machine_stat & (BROKEN|NOPOWER))
break
@@ -338,13 +450,25 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
break
playsound(src, 'sound/machines/printer.ogg', 50, vary = FALSE)
- sleep(4 SECONDS)
+ sleep(time_to_print)
// reveal our copied item
- copied_obj.forceMove(drop_location())
- give_pixel_offset(copied_obj)
+ if(!QDELETED(copied_obj))
+ copied_obj.forceMove(drop_location())
+ give_pixel_offset(copied_obj)
+ copies_made += copied_obj
copies_left--
+ if(copies_made.len)
+ if(!(obj_flags & EMAGGED) && attempt_charge(src, user, (copies_made.len - 1) * usage_cost) & COMPONENT_OBJ_CANCEL_CHARGE)
+ visible_message(
+ span_warning("An error message flashes across \the [src]'s screen."), \
+ span_warning("Failed to charge bank account. Scrapping copies.") \
+ )
+ QDEL_LIST(copies_made)
+ else
+ to_chat(user, span_warning("Failed to copy object!"))
+
copies_left = 0
reset_busy()
@@ -372,19 +496,36 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
copied_item.pixel_x = copied_item.base_pixel_x + rand(-10, 10)
copied_item.pixel_y = copied_item.base_pixel_y + rand(-10, 10)
-/// Gets the total amount of paper this printer has stored.
-/obj/machinery/photocopier/proc/get_paper_count()
- return length(paper_stack) + starting_paper
+/**
+ * Gets the total amount of paper this printer has stored
+ *
+ * Returns the amount of paper stored in the photocopier if passed with no args
+ * If paper_type is supplied will only return the amount of that paper type
+ *
+ * Arguments:
+ * * paper_type - The paper type to check to see quantity stored
+ */
+/obj/machinery/photocopier/proc/get_paper_count(paper_type)
+ if(paper_type)
+ return paper_stack[paper_type] || 0
+
+ var/total_amount = 0
+ for(var/paper_path in paper_stack)
+ var/paper_amount = paper_stack[paper_path]
+ if(paper_amount <= 0)
+ stack_trace("Detected zero or negative [paper_path] amount inside photocopier. There should be at least 1 or more of paper amount inside the list")
+ continue
+
+ total_amount += paper_amount
+
+ return total_amount
/**
* Returns an empty paper, used for blanks and paper copies.
* Prioritizes `paper_stack`, creates new paper in case `paper_stack` is empty.
*/
-/obj/machinery/photocopier/proc/get_empty_paper()
- var/obj/item/paper/new_paper = pop(paper_stack)
- if(new_paper == null && starting_paper > 0)
- new_paper = new /obj/item/paper
- starting_paper--
+/obj/machinery/photocopier/proc/get_empty_paper(paper_type)
+ var/obj/item/paper/new_paper = new paper_type()
return new_paper
/**
@@ -392,14 +533,12 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
* This lets us pretend we actually consumed paper when we were actually printing something that wasn't paper.
*/
/obj/machinery/photocopier/proc/delete_paper(number)
- if(number > get_paper_count())
+ if(!paper_stack[created_paper] || (number > paper_stack[created_paper]))
CRASH("Trying to delete more paper than is stored in the photocopier")
- for(var/i in 1 to number)
- var/to_delete = pop(paper_stack)
- if(to_delete)
- qdel(to_delete)
- else
- starting_paper--
+
+ paper_stack[created_paper] -= number
+ if(paper_stack[created_paper] <= 0)
+ paper_stack.Remove(created_paper)
/**
* Handles the copying of paper. Transfers all the text, stamps and so on from the old paper, to the copy.
@@ -410,8 +549,9 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
if(isnull(paper_copy))
return null
- var/obj/item/paper/empty_paper = get_empty_paper()
- toner_cartridge.charges -= PAPER_TONER_USE
+ var/obj/item/paper/empty_paper = get_empty_paper(created_paper)
+ delete_paper(PAPER_PAPER_USE)
+ use_toner(PAPER_TONER_USE)
var/copy_colour = get_toner_color()
@@ -429,7 +569,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
return null
var/obj/item/photo/copied_pic = new(src, photo.Copy(photo_color == PHOTO_GREYSCALE ? TRUE : FALSE))
delete_paper(PHOTO_PAPER_USE)
- toner_cartridge.charges -= PHOTO_TONER_USE
+ use_toner(PHOTO_TONER_USE)
return copied_pic
/**
@@ -442,7 +582,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
return null
var/obj/item/documents/photocopy/copied_doc = new(src, document_copy)
delete_paper(DOCUMENT_PAPER_USE)
- toner_cartridge.charges -= DOCUMENT_TONER_USE
+ use_toner(DOCUMENT_TONER_USE)
return copied_doc
/**
@@ -460,13 +600,13 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
copied_paperwork.stamp_icon = "paper_stamp-pc" //Override with the photocopy overlay sprite
copied_paperwork.add_stamp()
delete_paper(PAPERWORK_PAPER_USE)
- toner_cartridge.charges -= PAPERWORK_TONER_USE
+ use_toner(PAPERWORK_TONER_USE)
return copied_paperwork
/// Handles the copying of blanks. No mutating state, so this should not fail.
/obj/machinery/photocopier/proc/make_blank_print(list/blank)
var/copy_colour = get_toner_color()
- var/obj/item/paper/printblank = get_empty_paper()
+ var/obj/item/paper/printblank = get_empty_paper(created_paper)
var/printname = blank["name"]
var/list/printinfo
@@ -476,8 +616,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
printblank.name = "paper - '[printname]'"
printblank.add_raw_text(printinfo, color = copy_colour)
printblank.update_appearance()
-
- toner_cartridge.charges -= PAPER_TONER_USE
+ use_toner(PAPER_TONER_USE)
return printblank
/**
@@ -489,17 +628,16 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
/obj/machinery/photocopier/proc/make_ass_copy()
if(!check_ass())
return null
- var/butt_icon_state = ass.get_butt_sprite()
- if(isnull(butt_icon_state))
+ var/icon/temp_img = ass.get_butt_sprite()
+ if(isnull(temp_img))
return null
- var/icon/temp_img = icon('icons/mob/butts.dmi', butt_icon_state)
var/obj/item/photo/copied_ass = new /obj/item/photo(src)
var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img)
toEmbed.psize_x = 128
toEmbed.psize_y = 128
copied_ass.set_picture(toEmbed, TRUE, TRUE)
delete_paper(ASS_PAPER_USE)
- toner_cartridge.charges -= ASS_TONER_USE
+ use_toner(ASS_TONER_USE)
return copied_ass
/**
@@ -512,60 +650,133 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
* * object - the item we're trying to remove.
* * user - the user removing the item.
*/
-/obj/machinery/photocopier/proc/remove_photocopy(obj/item/object, mob/user)
+/obj/machinery/photocopier/proc/remove_photocopy(mob/user, obj/item/object)
if(issilicon(user))
object.forceMove(drop_location())
return
- try_put_in_hand(object, user)
+ object.forceMove(user.loc)
+ user.put_in_hands(object)
to_chat(user, span_notice("You take [object] out of [src]. [busy ? "The [src] comes to a halt." : ""]"))
+/obj/machinery/photocopier/update_icon_state()
+ . = ..()
+ icon_state = panel_open ? "[base_icon_state]2" : base_icon_state
+
+/obj/machinery/photocopier/screwdriver_act(mob/living/user, obj/item/tool)
+ return default_deconstruction_screwdriver(user, tool)
+
+/obj/machinery/photocopier/crowbar_act(mob/living/user, obj/item/tool)
+ return default_deconstruction_crowbar(user, tool)
+
/obj/machinery/photocopier/wrench_act(mob/living/user, obj/item/tool)
. = ..()
default_unfasten_wrench(user, tool)
return ITEM_INTERACT_SUCCESS
-/obj/machinery/photocopier/attackby(obj/item/object, mob/user, params)
- if(istype(object, /obj/item/paper) || istype(object, /obj/item/photo) || istype(object, /obj/item/documents))
- if(istype(object, /obj/item/paper))
- var/obj/item/paper/paper = object
- if(paper.is_empty())
- insert_empty_paper(paper, user)
- return
- insert_copy_object(object, user)
+/obj/machinery/photocopier/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ // No infinite paper chain. You need the original paperwork to make more copies.
+ if(istype(tool, /obj/item/paperwork/photocopy))
+ balloon_alert(user, "too blurry!")
+ to_chat(user, span_warning("The [tool] is far too messy to produce a good copy!"))
+ return ITEM_INTERACT_FAILURE
+
+ if(istype(tool, /obj/item/paper/paperslip))
+ balloon_alert(user, "too small!")
+ return ITEM_INTERACT_FAILURE
+
+ if(istype(tool, /obj/item/blueprints))
+ balloon_alert(user, "too large!")
+ to_chat(user, span_warning("\The [tool] is too large to put into the copier. You need to find something else to record the document."))
+ return ITEM_INTERACT_FAILURE
- else if(istype(object, /obj/item/toner))
+ if(istype(tool, /obj/item/toner))
if(toner_cartridge)
balloon_alert(user, "another cartridge inside!")
- return
- object.forceMove(src)
- toner_cartridge = object
- balloon_alert(user, "cartridge inserted")
+ return ITEM_INTERACT_FAILURE
- else if(istype(object, /obj/item/blueprints))
- to_chat(user, span_warning("\The [object] is too large to put into the copier. You need to find something else to record the document."))
-
- else if(istype(object, /obj/item/paperwork))
- if(istype(object, /obj/item/paperwork/photocopy)) //No infinite paper chain. You need the original paperwork to make more copies.
- to_chat(user, span_warning("The [object] is far too messy to produce a good copy!"))
- else
- insert_copy_object(object, user)
+ tool.forceMove(src)
+ toner_cartridge = tool
+ balloon_alert(user, "cartridge inserted")
+ return ITEM_INTERACT_SUCCESS
+
+ if(istype(tool, /obj/item/paperplane))
+ balloon_alert(user, "flatten paper first!")
+ return ITEM_INTERACT_FAILURE
+
+ if(istype(tool, /obj/item/paper))
+ var/obj/item/paper/paper = tool
+
+ if(paper.resistance_flags & ON_FIRE)
+ balloon_alert(user, "paper on fire!")
+ return ITEM_INTERACT_FAILURE
+
+ if(paper.is_empty()) // if not empty it gets inserted as an object to be copied
+ if(!has_room_for_paper())
+ balloon_alert(user, "cannot hold more paper!")
+ return ITEM_INTERACT_FAILURE
+
+ insert_empty_paper(user, paper.type)
+ qdel(paper)
+ return ITEM_INTERACT_SUCCESS
+
+ if(istype(tool, /obj/item/paper_bin))
+ var/obj/item/paper_bin/paper_bin = tool
+
+ if(!paper_bin.total_paper)
+ balloon_alert(user, "paper bin empty!")
+ return ITEM_INTERACT_FAILURE
+
+ var/paper_inserted = 0
+ for(var/obj/item/paper/stacked_paper in paper_bin.paper_stack) // insert all paper that is already initialized
+ var/is_empty = stacked_paper.is_empty()
+ var/is_room = has_room_for_paper()
+ if(!is_empty || !is_room)
+ continue
+
+ insert_empty_paper(user, stacked_paper.type, silent=TRUE)
+ paper_bin.paper_stack -= stacked_paper
+ paper_bin.total_paper -= 1
+ paper_inserted++
+ qdel(stacked_paper)
+
+ if(paper_bin.total_paper) // then insert non-initialized paper that is always considered empty paper
+ var/noninitialized_paper_total = paper_bin.total_paper - length(paper_bin.paper_stack)
+ var/paper_to_take = min(max_paper_capacity - get_paper_count(), noninitialized_paper_total)
+ if(paper_to_take)
+ insert_empty_paper(user, paper_bin.papertype, paper_to_take, silent=TRUE)
+ paper_inserted += paper_to_take
+ paper_bin.total_paper -= (paper_to_take)
+
+ if(!paper_inserted && !has_room_for_paper()) // no paper was inserted because it was full
+ balloon_alert(user, "cannot hold more paper!")
+ return ITEM_INTERACT_FAILURE
+
+ paper_bin.update_appearance()
+ // we use silent for insert_empty_paper() so that we don't spam balloon_alerts and instead condense them into one alert here
+ balloon_alert(user, "[paper_inserted] paper inserted")
+ return ITEM_INTERACT_SUCCESS
+
+ if(is_type_in_typecache(tool, whitelist_scannable_objects))
+ insert_copy_object(user, tool)
+ return ITEM_INTERACT_SUCCESS
+
+ return NONE
+
+/// Check if there is enough room to insert paper
+/obj/machinery/photocopier/proc/has_room_for_paper(mob/user, amount = 1)
+ return get_paper_count() < max_paper_capacity
/// Proc that handles insertion of empty paper, useful for copying later.
-/obj/machinery/photocopier/proc/insert_empty_paper(obj/item/paper/paper, mob/user)
- if(istype(paper, /obj/item/paper/paperslip))
- return
- if(get_paper_count() >= MAX_PAPER_CAPACITY)
- balloon_alert(user, "cannot hold more paper!")
- return
- if(!user.temporarilyRemoveItemFromInventory(paper))
- return
- paper_stack += paper
- paper.forceMove(src)
- balloon_alert(user, "paper inserted")
-
-/obj/machinery/photocopier/proc/insert_copy_object(obj/item/object, mob/user)
+/obj/machinery/photocopier/proc/insert_empty_paper(mob/user, paper_type, amount = 1, silent = FALSE)
+ if(!paper_stack[paper_type])
+ paper_stack[paper_type] = 0
+ paper_stack[paper_type] += amount
+ if(!silent)
+ balloon_alert(user, "paper inserted")
+
+/obj/machinery/photocopier/proc/insert_copy_object(mob/user, obj/item/object)
if(!copier_empty())
balloon_alert(user, "scanner tray occupied!")
return
@@ -578,7 +789,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
/obj/machinery/photocopier/atom_break(damage_flag)
. = ..()
- if(. && toner_cartridge.charges)
+ if(. && toner_cartridge?.charges)
new /obj/effect/decal/cleanable/oil(get_turf(src))
toner_cartridge.charges = 0
@@ -636,6 +847,12 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
return TRUE
return FALSE
+/**
+ * Removes a certain amount of toner that is affected by the efficiency of stock parts
+ */
+/obj/machinery/photocopier/proc/use_toner(amount)
+ toner_cartridge.charges -= (amount / toner_efficiency)
+
/**
* Checks if there is an item inserted into the copier or a mob sitting on top of it.
*
@@ -650,10 +867,11 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
/// Subtype of photocopier that is free to use.
/obj/machinery/photocopier/gratis
desc = "Does the same important paperwork, but it's free to use! The best type of free."
+ usage_cost = 0 // it's free! no charge! very cool and gratis-pilled.
-/obj/machinery/photocopier/gratis/setup_components()
- // it's free! no charge! very cool and gratis-pilled.
- AddComponent(/datum/component/payment, 0, SSeconomy.get_dep_account(ACCOUNT_CIV), PAYMENT_CLINICAL)
+/obj/machinery/photocopier/gratis/prebuilt
+ starting_toner = /obj/item/toner
+ starting_paper = 30
/*
* Toner cartridge
@@ -663,6 +881,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
desc = "A small, lightweight cartridge of Nanotrasen ValueBrand toner. Fits photocopiers and autopainters alike."
icon = 'icons/obj/service/bureaucracy.dmi'
icon_state = "tonercartridge"
+ w_class = WEIGHT_CLASS_SMALL
grind_results = list(/datum/reagent/iodine = 40, /datum/reagent/iron = 10)
var/charges = 5
var/max_charges = 5
@@ -674,9 +893,9 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
/obj/item/toner/large
name = "large toner cartridge"
desc = "A hefty cartridge of Nanotrasen ValueBrand toner. Fits photocopiers and autopainters alike."
- grind_results = list(/datum/reagent/iodine = 90, /datum/reagent/iron = 10)
charges = 25
max_charges = 25
+ grind_results = list(/datum/reagent/iodine = 90, /datum/reagent/iron = 10)
/obj/item/toner/extreme
name = "extremely large toner cartridge"
@@ -684,6 +903,12 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
charges = 200
max_charges = 200
+/obj/item/toner/infinite
+ name = "infinite toner cartridge"
+ desc = "...are you satisfied now?"
+ charges = INFINITY
+ max_charges = INFINITY
+
#undef PHOTOCOPIER_FEE
#undef BLANKS_FILE_NAME
#undef PAPER_PAPER_USE
@@ -691,7 +916,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
#undef DOCUMENT_PAPER_USE
#undef ASS_PAPER_USE
#undef PAPERWORK_PAPER_USE
-#undef MAX_PAPER_CAPACITY
+#undef MATTER_BIN_PAPER_CAPACITY
#undef TONER_CHARGE_LOW_AMOUNT
#undef PHOTO_GREYSCALE
#undef PHOTO_COLOR
diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm
index ad398c2b599e..bf624e02c360 100644
--- a/code/modules/power/lighting/light.dm
+++ b/code/modules/power/lighting/light.dm
@@ -313,7 +313,11 @@
// attempt to set the light's on/off status
// will not switch on if broken/burned/empty
/obj/machinery/light/proc/set_on(turn_on)
+ var/was_on = on
on = (turn_on && status == LIGHT_OK)
+ if(on == was_on)
+ return
+ SEND_SIGNAL(src, COMSIG_LIGHT_FIXTURE_TOGGLED, on)
update()
/obj/machinery/light/get_cell()
@@ -629,12 +633,15 @@
if(status == LIGHT_EMPTY || status == LIGHT_BROKEN)
return
+ var/was_ok = (status == LIGHT_OK || status == LIGHT_BURNED)
+ status = LIGHT_BROKEN
+
+ SEND_SIGNAL(src, COMSIG_LIGHT_FIXTURE_BROKEN, was_ok)
if(!skip_sound_and_sparks)
- if(status == LIGHT_OK || status == LIGHT_BURNED)
+ if(was_ok)
playsound(loc, 'sound/effects/glasshit.ogg', 75, TRUE)
if(on)
do_sparks(3, TRUE, src)
- status = LIGHT_BROKEN
update()
/obj/machinery/light/proc/fix()
diff --git a/code/modules/research/designs/autolathe/multi-department_designs.dm b/code/modules/research/designs/autolathe/multi-department_designs.dm
index b6cc72951134..8e88f505b603 100644
--- a/code/modules/research/designs/autolathe/multi-department_designs.dm
+++ b/code/modules/research/designs/autolathe/multi-department_designs.dm
@@ -9,6 +9,21 @@
RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_MISC,
)
+/datum/design/flare
+ name = "Flare"
+ id = "flare"
+ build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
+ materials = list(
+ /datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5,
+ /datum/material/plasma = SMALL_MATERIAL_AMOUNT * 0.5,
+ /datum/material/plastic = SMALL_MATERIAL_AMOUNT * 0.5,
+ )
+ build_path = /obj/item/flashlight/flare
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_MISC,
+ )
+
/datum/design/crowbar
name = "Pocket Crowbar"
id = "crowbar"
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 74df51e520c2..4c206c4be3f1 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -1202,3 +1202,33 @@
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO
)
departmental_flags = DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_ENGINEERING
+
+/datum/design/board/photopcopier
+ name = "Photocopier"
+ desc = "The circuit for a photocopier."
+ id = "photocopier"
+ build_path = /obj/item/circuitboard/machine/photocopier
+ category = list(
+ RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_SERVICE
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SERVICE
+
+// /datum/design/board/atmosshieldgen
+// name = "Atmospherics Shield Generator Board"
+// desc = "The circuit board for an atmospherics shield generator."
+// id = "atmosshieldgen"
+// build_path = /obj/item/circuitboard/machine/atmos_shield_gen
+// category = list(
+// RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ATMOS
+// )
+// departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING
+
+/datum/design/board/washing_machine
+ name = "Washing Machine"
+ desc = "The circuit board to build a washing machine."
+ id = "washing_machine"
+ build_path = /obj/item/circuitboard/machine/washing_machine
+ category = list(
+ RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_SERVICE
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_SERVICE
diff --git a/code/modules/research/techweb/nodes/service_nodes.dm b/code/modules/research/techweb/nodes/service_nodes.dm
index 125b3fef0563..6d5f5a434970 100644
--- a/code/modules/research/techweb/nodes/service_nodes.dm
+++ b/code/modules/research/techweb/nodes/service_nodes.dm
@@ -33,10 +33,12 @@
"normtrash",
"wirebrush",
"flashlight",
+ "flare",
"water_balloon",
"ticket_machine",
"radio_entertainment",
"barber_scissors",
+ "photocopier",
)
/datum/techweb_node/sanitation
@@ -52,6 +54,7 @@
"beartrap",
"buffer",
"vacuum",
+ "washing_machine",
)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS)
discount_experiments = list(/datum/experiment/scanning/random/janitor_trash = TECHWEB_TIER_2_POINTS)
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index e7093ece0393..d4ca5ce02a5d 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -1451,7 +1451,8 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
if(greyscale_colors)
vended_item.set_greyscale(colors=greyscale_colors)
item_record.amount--
- if(usr.CanReach(src) && try_put_in_hand(vended_item, usr))
+ var/sigreturn = SEND_SIGNAL(usr, COMSIG_MOB_VENDING_PURCHASE, src, vended_item)
+ if(!(sigreturn & VENDING_NO_PICKUP) && usr.CanReach(src) && try_put_in_hand(vended_item, usr))
to_chat(usr, span_notice("You take [item_record.name] out of the slot."))
else
to_chat(usr, span_warning("[capitalize(format_text(item_record.name))] falls onto the floor!"))
diff --git a/icons/obj/wallmounts.dmi b/icons/obj/wallmounts.dmi
index e70024a9edb2..2e7cb6b0f623 100644
Binary files a/icons/obj/wallmounts.dmi and b/icons/obj/wallmounts.dmi differ
diff --git a/maplestation_modules/code/modules/mob/living/blood.dm b/maplestation_modules/code/modules/mob/living/blood.dm
index 866b6ccfcfe9..7aeab63d3c62 100644
--- a/maplestation_modules/code/modules/mob/living/blood.dm
+++ b/maplestation_modules/code/modules/mob/living/blood.dm
@@ -118,8 +118,9 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
* Arguments
* * blood - the blood being set up
* * new_splat - whether this is a newly instantiated blood decal, or an existing one this blood is being added to
+ * * only_type - whether this blood decal is only of this blood type, or if it has other blood types mixed in
*/
-/datum/blood_type/proc/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat = FALSE)
+/datum/blood_type/proc/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat = FALSE, only_type = TRUE)
return
/**
@@ -301,7 +302,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
restoration_chem = /datum/reagent/silver
scent_text = null
-/datum/blood_type/silver/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat)
+/datum/blood_type/silver/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat, only_type)
blood.can_dry = FALSE
blood.emissive_alpha = max(blood.emissive_alpha, new_splat ? 125 : 63)
@@ -323,7 +324,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
salgu_compatible = TRUE
scent_text = null
-/datum/blood_type/crew/ethereal/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat)
+/datum/blood_type/crew/ethereal/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat, only_type)
blood.emissive_alpha = max(blood.emissive_alpha, new_splat ? 188 : 125)
if(!new_splat)
return
@@ -357,7 +358,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
restoration_chem = /datum/reagent/fuel/oil
scent_text = /datum/smell/oil
-/datum/blood_type/oil/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat)
+/datum/blood_type/oil/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat, only_type)
if(!new_splat)
return
// Oil blood will never dry and can be ignited with fire
@@ -402,6 +403,11 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
salgu_compatible = TRUE
scent_text = null
+/datum/blood_type/water/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat, only_type)
+ if(!new_splat || !only_type)
+ return
+ blood.qdel_on_dry = TRUE
+
/// Snails have Lube for blood, for some reason?
/datum/blood_type/snail
name = "Lube"
@@ -410,7 +416,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
scent_text = /obj/effect/abstract/smell/reagent/lube::name
scent_category = /obj/effect/abstract/smell/reagent/lube::category
-/datum/blood_type/snail/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat)
+/datum/blood_type/snail/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat, only_type)
if(blood.bloodiness < BLOOD_AMOUNT_PER_DECAL)
return
var/slip_amt = new_splat ? 4 SECONDS : 1 SECONDS
diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/android.dm b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/android.dm
index b7bfaf46fd3b..e8a9bc8feb3c 100644
--- a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/android.dm
+++ b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/android.dm
@@ -432,7 +432,7 @@
/datum/species/android/proc/update_heat_modifiers(mob/living/carbon/human/source)
var/obj/item/organ/lungs = source.get_organ_slot(ORGAN_SLOT_LUNGS)
if(HAS_TRAIT_NOT_FROM_LUNGS(source, TRAIT_RESISTHEAT, lungs))
- remove_heat_modifiers()
+ remove_heat_modifiers(source)
return
if(source.body_temperature > source.bodytemp_heat_damage_limit * 2)
@@ -461,12 +461,12 @@
else // ??
if(is_overheating != 0)
- remove_heat_modifiers()
+ remove_heat_modifiers(source)
/datum/species/android/proc/update_cold_modifiers(mob/living/carbon/human/source)
var/obj/item/organ/lungs = source.get_organ_slot(ORGAN_SLOT_LUNGS)
if(HAS_TRAIT_NOT_FROM_LUNGS(source, TRAIT_RESISTCOLD, lungs))
- remove_cold_modifiers()
+ remove_cold_modifiers(source)
return
if(source.body_temperature < source.bodytemp_cold_damage_limit * 2)
@@ -495,7 +495,7 @@
else // ??
if(is_overcooled != 0)
- remove_cold_modifiers()
+ remove_cold_modifiers(source)
#undef HAS_TRAIT_NOT_FROM_LUNGS
diff --git a/tgui/packages/tgui/interfaces/Photocopier.tsx b/tgui/packages/tgui/interfaces/Photocopier.tsx
index 40ae11f5dba7..d4f4ebe98bd3 100644
--- a/tgui/packages/tgui/interfaces/Photocopier.tsx
+++ b/tgui/packages/tgui/interfaces/Photocopier.tsx
@@ -1,6 +1,7 @@
import { useState } from 'react';
import {
Button,
+ ImageButton,
Input,
LabeledList,
ProgressBar,
@@ -30,6 +31,16 @@ type Data = {
paper_count: number;
max_paper_count: number;
blanks: Blank[];
+ paper_types: Paper[];
+ created_paper: string;
+};
+
+type Paper = {
+ name: string;
+ icon: string;
+ icon_state: string;
+ amount: number;
+ type: string;
};
type Blank = {
@@ -45,7 +56,7 @@ export const Photocopier = (props) => {
return (
@@ -100,6 +111,8 @@ const Status = (props: StatusProps) => {
max_toner,
paper_count,
max_paper_count,
+ paper_types,
+ created_paper,
} = data;
const average_toner = max_toner * 0.66;
@@ -166,6 +179,29 @@ const Status = (props: StatusProps) => {
{selectedBlank ? selectedBlank : 'Not Selected'}
+
+
+
+ {paper_types.map((paper) => (
+
+
+ act('select_paper_type', {
+ created_paper: paper.type,
+ })
+ }
+ />
+
+ ))}
+
+
);
diff --git a/tools/UpdatePaths/Scripts/90685_buildable_photocopiers.txt b/tools/UpdatePaths/Scripts/90685_buildable_photocopiers.txt
new file mode 100644
index 000000000000..da25320533f7
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/90685_buildable_photocopiers.txt
@@ -0,0 +1 @@
+/obj/machinery/photocopier : /obj/machinery/photocopier/prebuilt{@OLD}
\ No newline at end of file