diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 16214b58117a..022343e7dca0 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -8926,6 +8926,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
dir = 4
},
+/obj/structure/cable,
/turf/open/floor/plating,
/area/station/maintenance/department/science/xenobiology)
"caH" = (
@@ -12277,6 +12278,7 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/effect/mapping_helpers/airlock/access/any/science/maintenance,
/obj/effect/mapping_helpers/airlock/access/any/service/maintenance,
+/obj/structure/cable,
/turf/open/floor/iron,
/area/station/service/abandoned_gambling_den)
"cRT" = (
@@ -13439,6 +13441,13 @@
/obj/machinery/duct,
/turf/open/floor/iron,
/area/station/hallway/secondary/exit/departure_lounge)
+"dgZ" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/closed/wall,
+/area/station/service/library/printer)
"dhk" = (
/obj/structure/cable,
/obj/effect/turf_decal/tile/neutral/fourcorners,
@@ -17325,9 +17334,6 @@
/turf/open/floor/plating,
/area/station/cargo/storage)
"ehg" = (
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
/obj/machinery/newscaster/directional/west,
/obj/structure/table/wood,
/obj/item/clipboard,
@@ -18837,9 +18843,6 @@
/obj/structure/sign/painting/library_private{
pixel_y = -32
},
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
/obj/machinery/modular_computer/console/preset/curator{
dir = 1
},
@@ -31620,9 +31623,8 @@
/turf/open/floor/wood,
/area/station/service/theater/abandoned)
"hHF" = (
-/turf/open/floor/plating{
- icon_state = "foam_plating"
- },
+/obj/structure/cable,
+/turf/open/floor/glass/reinforced,
/area/station/maintenance/department/science/xenobiology)
"hHG" = (
/obj/machinery/telecomms/receiver/preset_left,
@@ -37966,10 +37968,9 @@
/turf/open/floor/iron,
/area/station/hallway/secondary/construction)
"jiX" = (
-/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/cable,
-/turf/open/floor/iron/dark,
+/turf/open/floor/plating,
/area/station/service/abandoned_gambling_den)
"jjc" = (
/obj/structure/frame/computer{
@@ -44192,6 +44193,9 @@
},
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/structure/cable,
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
/turf/open/floor/iron/dark,
/area/station/service/library/printer)
"kHp" = (
@@ -46905,6 +46909,7 @@
/area/station/maintenance/department/eva/abandoned)
"lqa" = (
/obj/machinery/light/small/red/directional/east,
+/obj/structure/cable,
/turf/open/floor/iron/smooth,
/area/station/maintenance/department/science/xenobiology)
"lql" = (
@@ -47972,6 +47977,9 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/structure/cable,
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
/turf/open/floor/iron/dark,
/area/station/service/library/printer)
"lDV" = (
@@ -51463,6 +51471,7 @@
"mwA" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/oil,
+/obj/structure/cable,
/turf/open/floor/iron/smooth,
/area/station/maintenance/department/science/xenobiology)
"mwK" = (
@@ -52119,6 +52128,9 @@
/obj/effect/turf_decal/bot_white,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/structure/cable,
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
/turf/open/floor/iron/dark,
/area/station/service/library/printer)
"mEx" = (
@@ -52185,6 +52197,7 @@
/area/station/security/warden)
"mFq" = (
/obj/structure/sign/warning/secure_area/directional/north,
+/obj/structure/cable,
/turf/open/floor/glass/reinforced,
/area/station/maintenance/department/science/xenobiology)
"mFu" = (
@@ -56874,6 +56887,21 @@
pixel_y = 2;
pixel_x = 9
},
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
/turf/open/floor/iron/vaporwave,
/area/station/service/library/printer)
"nMN" = (
@@ -59137,6 +59165,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/mapping_helpers/broken_floor,
/obj/effect/spawner/random/structure/steam_vent,
+/obj/structure/cable,
/turf/open/floor/iron/smooth,
/area/station/maintenance/department/science/xenobiology)
"opv" = (
@@ -66189,6 +66218,9 @@
dir = 8
},
/obj/structure/cable,
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
/turf/open/floor/iron/dark,
/area/station/service/library/printer)
"qaF" = (
@@ -68364,9 +68396,6 @@
/turf/open/floor/iron/white,
/area/station/medical/medbay)
"qEj" = (
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
/obj/machinery/light/small/directional/south,
/obj/structure/table/wood,
/obj/item/paper_bin{
@@ -75072,6 +75101,7 @@
"smj" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/effect/turf_decal/delivery,
+/obj/structure/cable,
/turf/open/floor/iron/smooth,
/area/station/maintenance/department/science/xenobiology)
"smo" = (
@@ -76145,6 +76175,7 @@
/obj/effect/decal/cleanable/xenoblood,
/obj/structure/sign/warning/xeno_mining/directional/north,
/obj/effect/decal/cleanable/cobweb/cobweb2,
+/obj/structure/cable,
/turf/open/floor/iron/smooth,
/area/station/maintenance/department/science/xenobiology)
"sAm" = (
@@ -82902,9 +82933,6 @@
/area/station/commons/toilet/locker)
"ufz" = (
/obj/machinery/firealarm/directional/south,
-/obj/structure/disposalpipe/segment{
- dir = 9
- },
/obj/effect/turf_decal/bot_white,
/obj/structure/filingcabinet,
/turf/open/floor/iron/dark,
@@ -84964,6 +84992,7 @@
/turf/open/floor/iron/cafeteria,
/area/station/service/cafeteria)
"uGn" = (
+/obj/structure/cable,
/turf/open/floor/plating,
/area/station/maintenance/department/science/xenobiology)
"uGx" = (
@@ -88806,6 +88835,7 @@
/area/station/maintenance/port)
"vBO" = (
/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable,
/turf/open/floor/plating{
icon_state = "foam_plating"
},
@@ -92724,7 +92754,9 @@
/obj/effect/turf_decal/tile/neutral/fourcorners,
/obj/machinery/power/apc/auto_name/directional/east,
/obj/structure/cable,
-/obj/structure/disposalpipe/segment,
+/obj/structure/disposalpipe/segment{
+ dir = 9
+ },
/turf/open/floor/iron/dark,
/area/station/service/library/printer)
"wwP" = (
@@ -93073,9 +93105,6 @@
/area/station/maintenance/starboard/aft)
"wAZ" = (
/obj/effect/turf_decal/tile/neutral/fourcorners,
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
/obj/structure/table/wood,
/obj/item/taperecorder,
/obj/item/camera,
@@ -118460,7 +118489,7 @@ sfN
sfN
sfN
nCi
-vPU
+hHF
nCi
nCi
hCt
@@ -118974,7 +119003,7 @@ sfN
sfN
sfN
nCi
-vPU
+hHF
nCi
bET
hVB
@@ -119749,7 +119778,7 @@ jPZ
oia
nCi
mwA
-hHF
+jDc
guA
nCi
aaa
@@ -120777,7 +120806,7 @@ uhb
uhb
mAt
qCs
-blc
+jiX
hLM
jBx
pxb
@@ -121035,7 +121064,7 @@ fOp
mAt
ifk
mMb
-jiX
+bNr
blc
rCc
rCc
@@ -146975,7 +147004,7 @@ dLH
dfZ
dfZ
fcx
-dfZ
+dgZ
dfZ
khZ
nHY
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index a5e759c6d785..0a7dc2984940 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -14435,6 +14435,21 @@
pixel_y = 2;
pixel_x = 9
},
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
/turf/open/floor/glass,
/area/station/service/library)
"ezJ" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index da5ab5939ef9..572db0791f1e 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -2747,6 +2747,21 @@
pixel_y = 2;
pixel_x = 9
},
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
/turf/open/floor/iron/vaporwave,
/area/station/service/library)
"aWl" = (
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index 4180df4b30a2..1b30f3328465 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -17238,6 +17238,9 @@
name = "CentCom Security"
},
/obj/effect/mapping_helpers/airlock/access/any/admin/general,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
/turf/open/floor/iron,
/area/centcom/central_command_areas/ferry)
"Zc" = (
diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm
index 40a172f77cc3..3a631e34457f 100644
--- a/_maps/map_files/tramstation/tramstation.dmm
+++ b/_maps/map_files/tramstation/tramstation.dmm
@@ -19551,12 +19551,6 @@
"ffa" = (
/obj/machinery/vending/wallmed/directional/west,
/obj/effect/decal/cleanable/dirt,
-/obj/item/toy/plush/pkplush{
- pixel_x = -3
- },
-/obj/item/toy/plush/rouny{
- dir = 4
- },
/obj/effect/turf_decal/tile/blue/opposingcorners,
/turf/open/floor/iron/white,
/area/station/asteroid)
@@ -23397,9 +23391,6 @@
"gvS" = (
/obj/effect/decal/cleanable/dirt,
/obj/item/kirbyplants/random,
-/obj/structure/sign/poster/contraband/ambrosia_vulgaris{
- pixel_x = 32
- },
/obj/machinery/light/warm{
dir = 4
},
@@ -32787,7 +32778,6 @@
/obj/structure/sign/poster/contraband/kudzu{
pixel_x = -32
},
-/obj/item/seeds/cocaleaf,
/obj/machinery/light/warm,
/turf/open/floor/iron/smooth,
/area/station/maintenance/starboard/central)
@@ -33469,9 +33459,14 @@
/area/station/maintenance/central/lesser)
"jJt" = (
/obj/effect/decal/cleanable/dirt,
-/obj/item/kirbyplants/random,
-/obj/item/seeds/kudzu,
-/turf/open/floor/iron/smooth,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/structure/cable,
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/open/floor/catwalk_floor,
/area/station/maintenance/starboard/central)
"jJv" = (
/turf/open/floor/circuit,
@@ -39810,17 +39805,15 @@
/turf/open/floor/iron,
/area/station/engineering/atmos)
"lLW" = (
-/obj/item/toy/plush/moth{
- name = "Delivers-The-Pizza"
- },
-/obj/item/clothing/head/soft/red{
- pixel_x = -4;
- pixel_y = 9
- },
/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/tile/blue/opposingcorners,
-/turf/open/floor/iron/white,
-/area/station/asteroid)
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/structure/cable,
+/obj/structure/disposalpipe/segment{
+ dir = 5
+ },
+/turf/open/floor/catwalk_floor,
+/area/station/maintenance/starboard/central)
"lMd" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
@@ -44075,7 +44068,6 @@
/turf/open/floor/plating,
/area/station/security/execution/transfer)
"neX" = (
-/obj/item/kirbyplants/random,
/obj/effect/decal/cleanable/dirt,
/obj/machinery/light/directional/south,
/obj/effect/turf_decal/tile/blue/fourcorners,
@@ -49772,15 +49764,6 @@
},
/turf/open/floor/iron,
/area/station/security/brig)
-"pac" = (
-/obj/item/pizzabox/margherita{
- pixel_y = 27
- },
-/obj/structure/dresser,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/tile/blue/opposingcorners,
-/turf/open/floor/iron/white,
-/area/station/asteroid)
"pal" = (
/obj/structure/disposalpipe/segment{
dir = 10
@@ -51804,7 +51787,7 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/structure/cable,
-/obj/effect/mapping_helpers/airlock/access/all/engineering,
+/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/turf/open/floor/catwalk_floor,
/area/station/maintenance/starboard/lesser)
"pFw" = (
@@ -53975,14 +53958,6 @@
},
/turf/open/floor/iron,
/area/station/engineering/atmos)
-"qpR" = (
-/obj/structure/filingcabinet/chestdrawer{
- pixel_y = 2
- },
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/tile/blue/opposingcorners,
-/turf/open/floor/iron/white,
-/area/station/asteroid)
"qpW" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
@@ -55990,9 +55965,9 @@
pixel_x = -3;
pixel_y = 3
},
-/obj/item/clothing/under/syndicate,
-/obj/item/clothing/under/syndicate,
/obj/item/clothing/under/misc/syndicate_souvenir,
+/obj/item/clothing/under/syndicate/tacticool,
+/obj/item/clothing/under/syndicate/tacticool,
/turf/open/floor/iron/grimy,
/area/ruin/powered/clownplanet)
"qVH" = (
@@ -60439,7 +60414,6 @@
/turf/open/floor/iron,
/area/station/hallway/primary/tram/right)
"srX" = (
-/obj/structure/closet/wardrobe/pjs,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/iron,
/area/station/asteroid)
@@ -66874,6 +66848,21 @@
pixel_y = 2;
pixel_x = 9
},
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
+/obj/item/device/cassette_tape/random{
+ pixel_y = 8
+ },
/turf/open/floor/iron/vaporwave,
/area/station/service/library/upper)
"uss" = (
@@ -124036,7 +124025,7 @@ mbJ
aaa
qxm
hGg
-jJt
+iqy
jys
qxm
aaa
@@ -128136,7 +128125,7 @@ qxm
bjI
fsM
fsM
-fsM
+lLW
oys
oys
oys
@@ -128393,7 +128382,7 @@ qxm
qxm
qxm
qxm
-qoO
+jJt
gDw
gDw
gDw
@@ -177388,7 +177377,7 @@ jhd
jhd
jhd
jhd
-jhd
+vXM
jhd
jhd
jhd
@@ -180848,7 +180837,7 @@ whz
kSi
whz
ffa
-qpR
+rXK
ugt
kOL
vrJ
@@ -181618,8 +181607,8 @@ ebw
whz
qdj
whz
-lLW
-pac
+rXK
+rXK
ugt
ugt
ugt
diff --git a/_maps/~monkestation/RandomBars/Icebox/cultbar_icebox.dmm b/_maps/~monkestation/RandomBars/Icebox/cultbar_icebox.dmm
index b9afa7452553..1201953d3555 100644
--- a/_maps/~monkestation/RandomBars/Icebox/cultbar_icebox.dmm
+++ b/_maps/~monkestation/RandomBars/Icebox/cultbar_icebox.dmm
@@ -192,7 +192,6 @@
/area/station/service/theater)
"iX" = (
/obj/effect/spawner/random/structure/musician/piano/random_piano,
-/obj/machinery/power/apc/auto_name/directional/north,
/obj/structure/cable,
/turf/open/floor/cult,
/area/station/service/theater)
@@ -401,7 +400,6 @@
"uL" = (
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/cult,
/area/station/service/bar/backroom)
"vh" = (
diff --git a/_maps/~monkestation/RandomEngines/KiloStation/singularity.dmm b/_maps/~monkestation/RandomEngines/KiloStation/singularity.dmm
index 0a79c673dcd7..ae0b4e69c26f 100644
--- a/_maps/~monkestation/RandomEngines/KiloStation/singularity.dmm
+++ b/_maps/~monkestation/RandomEngines/KiloStation/singularity.dmm
@@ -93,8 +93,10 @@
"is" = (
/obj/structure/cable,
/obj/machinery/door/airlock/external,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/structure/cable/layer1,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{
+ cycle_id = "kilo_singularity_airlock"
+ },
/turf/open/floor/iron,
/area/station/engineering/supermatter/room)
"iW" = (
@@ -106,11 +108,11 @@
"jc" = (
/obj/structure/cable,
/obj/machinery/door/airlock/external,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
/obj/structure/fans/tiny,
/obj/structure/cable/layer1,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{
+ cycle_id = "kilo_singularity_airlock"
+ },
/turf/open/floor/iron,
/area/station/engineering/supermatter/room)
"jl" = (
@@ -396,7 +398,6 @@
dir = 1
},
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
-/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/obj/structure/cable,
/turf/open/floor/iron,
/area/station/engineering/supermatter/room)
@@ -1004,7 +1005,7 @@ IJ
rz
Ib
oK
-Hs
+oK
pk
Ii
Ii
@@ -1026,7 +1027,7 @@ En
(12,1,1) = {"
pa
UA
-oK
+Hs
NK
pk
lZ
@@ -1121,9 +1122,9 @@ Ib
oK
NK
pk
-sz
-sz
-sz
+oK
+oK
+oK
Fj
RL
WZ
diff --git a/code/__DEFINES/acid.dm b/code/__DEFINES/acid.dm
index 37bf5f07ed54..7434fd94cd45 100644
--- a/code/__DEFINES/acid.dm
+++ b/code/__DEFINES/acid.dm
@@ -1,9 +1,9 @@
/// The acid power required to destroy most closed turfs.
#define ACID_POWER_MELT_TURF 200
/// The maximum amount of damage (per second) acid can deal to an [/obj].
-#define OBJ_ACID_DAMAGE_MAX 300
+#define MOVABLE_ACID_DAMAGE_MAX 300
/// Maximum acid volume that can be applied to an [/obj].
-#define OBJ_ACID_VOLUME_MAX 300
+#define MOVABLE_ACID_VOLUME_MAX 300
/// Maximum acid volume that can be applied to a [/mob/living].
#define MOB_ACID_VOLUME_MAX 1000
/// Maximum acid volume that can be applied to a [/turf].
@@ -15,7 +15,5 @@
/// The scaling factor for the acid decay rate.
#define ACID_DECAY_SCALING 1
-/// The default icon state for the acid overlay. Not to be confused with the error icon state.
-#define ACID_OVERLAY_DEFAULT "default"
/// The combined acid power and acid volume required to burn hands.
#define ACID_LEVEL_HANDBURN 20
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 8456deca3363..7883f5ba9ae9 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -196,6 +196,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_GUN_NATURAL "gunnatural"
/// Causes death-like unconsciousness
#define TRAIT_DEATHCOMA "deathcoma"
+/// The mob has the stasis effect.
+/// Does nothing on its own, applied via status effect.
+#define TRAIT_STASIS "in_stasis"
/// Makes the owner appear as dead to most forms of medical examination
#define TRAIT_FAKEDEATH "fakedeath"
#define TRAIT_DISFIGURED "disfigured"
@@ -256,8 +259,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_LIVERLESS_METABOLISM "liverless_metabolism"
/// Humans with this trait cannot be turned into zombies
#define TRAIT_NO_ZOMBIFY "no_zombify"
-/// Humans with this trait cannot be affected by changeling transformation stings
-#define TRAIT_NO_TRANSFORMATION_STING "no_transformation_sting"
/// Carbons with this trait can't have their DNA copied by diseases nor changelings
#define TRAIT_NO_DNA_COPY "no_dna_copy"
/// Carbons with this trait can eat blood to regenerate their own blood volume, instead of injecting it
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index e8f8d96b9a41..6b6dca84f290 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -612,8 +612,6 @@ GLOBAL_LIST_EMPTY(species_list)
#define ISADVANCEDTOOLUSER(mob) (HAS_TRAIT(mob, TRAIT_ADVANCEDTOOLUSER) && !HAS_TRAIT(mob, TRAIT_DISCOORDINATED_TOOL_USER))
-#define IS_IN_STASIS(mob) (mob.has_status_effect(/datum/status_effect/grouped/stasis) || mob.has_status_effect(/datum/status_effect/embryonic))
-
/// Gets the client of the mob, allowing for mocking of the client.
/// You only need to use this if you know you're going to be mocking clients somewhere else.
#define GET_CLIENT(mob) (##mob.client || ##mob.mock_client)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 5b9d561afcae..4fb02a8bb3b6 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -439,6 +439,7 @@ Used by the AI doomsday and the self-destruct nuke.
template.weight = (template.weight / 2)
if(template.stock <= 0)
template.spawned = TRUE
+ log_world("Loading random room template [template.name] ([template.type]) at [AREACOORD(R)]")
template.stationinitload(get_turf(R), centered = template.centerspawner)
SSmapping.random_room_spawners -= R
qdel(R)
@@ -459,6 +460,7 @@ Used by the AI doomsday and the self-destruct nuke.
possible_engine_templates[engine_candidate] = engine_candidate.weight
if(possible_engine_templates.len)
var/datum/map_template/random_room/random_engines/template = pick_weight(possible_engine_templates)
+ log_world("Loading random engine template [template.name] ([template.type]) at [AREACOORD(engine_spawner)]")
template.stationinitload(get_turf(engine_spawner), centered = template.centerspawner)
SSmapping.random_engine_spawners -= engine_spawner
qdel(engine_spawner)
@@ -480,6 +482,7 @@ Used by the AI doomsday and the self-destruct nuke.
possible_bar_templates[bar_candidate] = bar_candidate.weight
if(possible_bar_templates.len)
var/datum/map_template/random_room/random_bar/template = pick_weight(possible_bar_templates)
+ log_world("Loading random bar template [template.name] ([template.type]) at [AREACOORD(bar_spawner)]")
template.stationinitload(get_turf(bar_spawner), centered = template.centerspawner)
SSmapping.random_bar_spawners -= bar_spawner
qdel(bar_spawner)
@@ -500,6 +503,7 @@ Used by the AI doomsday and the self-destruct nuke.
possible_arena_templates[arena_candidate] = arena_candidate.weight
if(possible_arena_templates.len)
var/datum/map_template/random_room/random_arena/template = pick_weight(possible_arena_templates)
+ log_world("Loading random arena template [template.name] ([template.type]) at [AREACOORD(arena_spawner)]")
template.stationinitload(get_turf(arena_spawner), centered = template.centerspawner)
SSmapping.random_arena_spawners -= arena_spawner
qdel(arena_spawner)
diff --git a/code/controllers/subsystem/processing/fire_burning.dm b/code/controllers/subsystem/processing/fire_burning.dm
index 43c9ffd33064..6cde5e3c34f6 100644
--- a/code/controllers/subsystem/processing/fire_burning.dm
+++ b/code/controllers/subsystem/processing/fire_burning.dm
@@ -1,6 +1,6 @@
/// The subsystem used to tick [/datum/component/burning] instances.
-PROCESSING_SUBSYSTEM_DEF(fire_burning)
- name = "Fire Burning"
+PROCESSING_SUBSYSTEM_DEF(burning)
+ name = "Burning"
priority = FIRE_PRIORITY_BURNING
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
diff --git a/code/datums/components/acid.dm b/code/datums/components/acid.dm
index 8e78089022f7..89430ff368e2 100644
--- a/code/datums/components/acid.dm
+++ b/code/datums/components/acid.dm
@@ -1,10 +1,11 @@
-GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', "acid"))
+GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/acid.dmi', "default"))
-/** Component representing acid applied to an object.
- *
+/**
+ * Component representing acid applied to an object.
* Must be attached to an atom.
* Processes, repeatedly damaging whatever it is attached to.
* If the parent atom is a turf it applies acid to the contents of the turf.
+ * If not being applied to a mob or turf, the atom must use the integrity system.
*/
/datum/component/acid
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
@@ -14,6 +15,8 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
var/acid_volume
/// The maximum volume of acid on the parent [/atom].
var/max_volume = INFINITY
+ /// Acid overlay appearance we apply
+ var/acid_overlay
/// The ambiant sound of acid eating away at the parent [/atom].
var/datum/looping_sound/acid/sizzle
/// Used exclusively for melting turfs. TODO: Move integrity to the atom level so that this can be dealt with there.
@@ -23,71 +26,80 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/// The proc used to handle the parent [/atom] when processing. TODO: Unify damage and resistance flags so that this doesn't need to exist!
var/datum/callback/process_effect
-/datum/component/acid/Initialize(_acid_power, _acid_volume, _max_volume=null)
- if((_acid_power) <= 0 || (_acid_volume <= 0))
- stack_trace("Acid component added with insufficient acid power ([_acid_power]) or acid volume ([_acid_power]).")
- return COMPONENT_INCOMPATIBLE // Not enough acid or the acid's too weak, either one.
+/datum/component/acid/Initialize(acid_power = ACID_POWER_MELT_TURF, acid_volume = 50, acid_overlay = GLOB.acid_overlay)
if(!isatom(parent))
- stack_trace("Acid component added to [parent] ([parent?.type]) which is not a /atom subtype.")
- return COMPONENT_INCOMPATIBLE // Incompatible type. TODO: Rework take_damage to the atom level and move this there.
-
- if(isobj(parent))
- var/obj/parent_object = parent
- if(parent_object.resistance_flags & UNACIDABLE) // The parent object cannot have acid. Should never happen, will happen.
- stack_trace("Acid component added to unacidable object [parent].")
- return COMPONENT_INCOMPATIBLE
-
- max_volume = OBJ_ACID_VOLUME_MAX
- process_effect = CALLBACK(src, PROC_REF(process_obj), parent)
- else if(isliving(parent))
+ return COMPONENT_INCOMPATIBLE
+ //not incompatible, but pointless
+ var/atom/atom_parent = parent
+ if((acid_power) <= 0 || (acid_volume <= 0))
+ stack_trace("Acid component added to an atom ([atom_parent.type]) with insufficient acid power ([acid_power]) or acid volume ([acid_volume]).")
+ qdel(src)
+ return
+
+
+ if(isliving(parent))
max_volume = MOB_ACID_VOLUME_MAX
process_effect = CALLBACK(src, PROC_REF(process_mob), parent)
else if(isturf(parent))
max_volume = TURF_ACID_VOLUME_MAX
process_effect = CALLBACK(src, PROC_REF(process_turf), parent)
+ //if we failed all other checks, we must be an /atom/movable that uses integrity
+ else if(atom_parent.uses_integrity)
+ // The parent object cannot have acid. Not incompatible, but should not really happen.
+ if(atom_parent.resistance_flags & UNACIDABLE)
+ qdel(src)
+ return
+
+ max_volume = MOVABLE_ACID_VOLUME_MAX
+ process_effect = CALLBACK(src, PROC_REF(process_movable), parent)
+ //or not...
+ else
+ stack_trace("Tried to add /datum/component/acid to an atom ([atom_parent.type]) which does not use atom_integrity!")
+ return COMPONENT_INCOMPATIBLE
+
+ src.acid_power = acid_power
+ set_volume(acid_volume)
+ src.acid_overlay = acid_overlay
- acid_power = _acid_power
- set_volume(_acid_volume)
-
- var/atom/parent_atom = parent
- RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
- parent_atom.update_appearance()
sizzle = new(parent, TRUE)
START_PROCESSING(SSacid, src)
/datum/component/acid/Destroy(force, silent)
STOP_PROCESSING(SSacid, src)
- QDEL_NULL(sizzle)
+ if(sizzle)
+ QDEL_NULL(sizzle)
if(process_effect)
QDEL_NULL(process_effect)
- UnregisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS)
- if(parent && !QDELING(parent))
- var/atom/parent_atom = parent
- parent_atom.update_appearance()
return ..()
/datum/component/acid/RegisterWithParent()
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+ RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean))
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(on_attack_hand))
RegisterSignal(parent, COMSIG_ATOM_EXPOSE_REAGENT, PROC_REF(on_expose_reagent))
if(isturf(parent))
RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(on_entered))
+ var/atom/atom_parent = parent
+ atom_parent.update_appearance()
/datum/component/acid/UnregisterFromParent()
UnregisterSignal(parent, list(
COMSIG_ATOM_EXAMINE,
+ COMSIG_ATOM_UPDATE_OVERLAYS,
COMSIG_COMPONENT_CLEAN_ACT,
COMSIG_ATOM_ATTACK_HAND,
COMSIG_ATOM_EXPOSE_REAGENT))
-
if(isturf(parent))
UnregisterSignal(parent, COMSIG_ATOM_ENTERED)
+ var/atom/atom_parent = parent
+ if(!QDELETED(atom_parent))
+ atom_parent.update_appearance()
/// Averages corrosive power and sums volume.
-/datum/component/acid/InheritComponent(datum/component/C, i_am_original, _acid_power, _acid_volume)
- acid_power = ((acid_power * acid_volume) + (_acid_power * _acid_volume)) / (acid_volume + _acid_volume)
- set_volume(acid_volume + _acid_volume)
+/datum/component/acid/InheritComponent(datum/component/new_comp, i_am_original, acid_power, acid_volume)
+ acid_power = ((src.acid_power * src.acid_volume) + (acid_power * acid_volume)) / (src.acid_volume + acid_volume)
+ set_volume(src.acid_volume + acid_volume)
/// Sets the acid volume to a new value. Limits the acid volume by the amount allowed to exist on the parent atom.
/datum/component/acid/proc/set_volume(new_volume)
@@ -95,7 +107,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!acid_volume)
qdel(src)
-
/// Handles the slow corrosion of the parent [/atom].
/datum/component/acid/process(seconds_per_tick)
process_effect?.InvokeAsync(seconds_per_tick)
@@ -103,11 +114,11 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
return
set_volume(acid_volume - (ACID_DECAY_BASE + (ACID_DECAY_SCALING*round(sqrt(acid_volume)))) * seconds_per_tick)
-/// Handles processing on a [/obj].
-/datum/component/acid/proc/process_obj(obj/target, seconds_per_tick)
+/// Handles processing on an [/atom/movable] (that uses atom_integrity).
+/datum/component/acid/proc/process_movable(atom/movable/target, seconds_per_tick)
if(target.resistance_flags & ACID_PROOF)
return
- target.take_damage(min(1 + round(sqrt(acid_power * acid_volume)*0.3), OBJ_ACID_DAMAGE_MAX) * seconds_per_tick, BURN, ACID, 0)
+ target.take_damage(min(1 + round(sqrt(acid_power * acid_volume)*0.3), MOVABLE_ACID_DAMAGE_MAX) * seconds_per_tick, BURN, ACID, 0)
/// Handles processing on a [/mob/living].
/datum/component/acid/proc/process_mob(mob/living/target, seconds_per_tick)
@@ -117,8 +128,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/datum/component/acid/proc/process_turf(turf/target_turf, seconds_per_tick)
var/acid_used = min(acid_volume * 0.05, 20) * seconds_per_tick
var/applied_targets = 0
- for(var/am in target_turf)
- var/atom/movable/target_movable = am
+ for(var/atom/movable/target_movable as anything in target_turf)
if(target_movable.acid_act(acid_power, acid_used))
applied_targets++
@@ -150,16 +160,17 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/datum/component/acid/proc/on_update_overlays(atom/parent_atom, list/overlays)
SIGNAL_HANDLER
- overlays += mutable_appearance('icons/effects/acid.dmi', parent_atom.custom_acid_overlay || ACID_OVERLAY_DEFAULT)
+ if(acid_overlay)
+ overlays += acid_overlay
/// Alerts any examiners to the acid on the parent atom.
-/datum/component/acid/proc/on_examine(atom/A, mob/user, list/examine_list)
+/datum/component/acid/proc/on_examine(atom/source, mob/user, list/examine_list)
SIGNAL_HANDLER
- examine_list += span_danger("[A.p_theyre()] covered in corrosive liquid!")
+ examine_list += span_danger("[source.p_theyre(TRUE)] covered in a corrosive liquid!")
/// Makes it possible to clean acid off of objects.
-/datum/component/acid/proc/on_clean(atom/A, clean_types)
+/datum/component/acid/proc/on_clean(atom/source, clean_types)
SIGNAL_HANDLER
if(!(clean_types & CLEAN_TYPE_ACID))
@@ -178,7 +189,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
set_volume(acid_volume + reac_volume)
return NONE
-
/// Handles searing the hand of anyone who tries to touch this without protection.
/datum/component/acid/proc/on_attack_hand(atom/parent_atom, mob/living/carbon/user)
SIGNAL_HANDLER
@@ -201,7 +211,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
user.update_damage_overlays()
return COMPONENT_CANCEL_ATTACK_CHAIN
-
/// Handles searing the feet of whoever walks over this without protection. Only active if the parent is a turf.
/datum/component/acid/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
diff --git a/code/datums/components/burning.dm b/code/datums/components/burning.dm
index d2ccd03147c7..347340e3e2c4 100644
--- a/code/datums/components/burning.dm
+++ b/code/datums/components/burning.dm
@@ -2,7 +2,8 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
/**
* Component representing an atom being on fire.
- * Should not be used on mobs, they use the fire stacks system.
+ * Should not be used on mobs, they use the fire stacks status effects.
+ * Can only be used on atoms that use the integrity system.
*/
/datum/component/burning
/// Fire overlay appearance we apply
@@ -10,12 +11,12 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
/// Particle holder for fire particles, if any
var/obj/effect/abstract/particle_holder/particle_effect
-/datum/component/burning/Initialize(fire_overlay, fire_particles)
+/datum/component/burning/Initialize(fire_overlay = GLOB.fire_overlay, fire_particles = /particles/smoke/burning)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
var/atom/atom_parent = parent
if(!atom_parent.uses_integrity)
- stack_trace("Tried to add /datum/component/burning to an atom ([atom_parent]) that does not use atom_integrity!")
+ stack_trace("Tried to add /datum/component/burning to an atom ([atom_parent.type]) that does not use atom_integrity!")
return COMPONENT_INCOMPATIBLE
// only flammable atoms should have this component, but it's not really an error if we try to apply this to a non flammable one
if(!(atom_parent.resistance_flags & FLAMMABLE) || (atom_parent.resistance_flags & FIRE_PROOF))
@@ -23,30 +24,30 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
return
src.fire_overlay = fire_overlay
if(fire_particles)
- particle_effect = new(atom_parent, fire_particles)
- atom_parent.resistance_flags |= ON_FIRE
- START_PROCESSING(SSfire_burning, src)
+ // burning particles look pretty bad when they stack on mobs, so that behavior is not wanted for items
+ particle_effect = new(atom_parent, fire_particles, isitem(atom_parent) ? NONE : PARTICLE_ATTACH_MOB)
+ START_PROCESSING(SSburning, src)
+
+/datum/component/burning/Destroy(force, silent)
+ STOP_PROCESSING(SSburning, src)
+ if(particle_effect)
+ QDEL_NULL(particle_effect)
+ return ..()
/datum/component/burning/RegisterWithParent()
- . = ..()
+ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
RegisterSignal(parent, COMSIG_ATOM_EXTINGUISH, PROC_REF(on_extinguish))
var/atom/atom_parent = parent
- atom_parent.update_appearance(UPDATE_ICON)
+ atom_parent.resistance_flags |= ON_FIRE
+ atom_parent.update_appearance()
/datum/component/burning/UnregisterFromParent()
- . = ..()
- UnregisterSignal(parent, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ATOM_EXTINGUISH))
-
-/datum/component/burning/Destroy(force, silent)
- STOP_PROCESSING(SSfire_burning, src)
- if(particle_effect)
- QDEL_NULL(particle_effect)
+ UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ATOM_EXTINGUISH))
var/atom/atom_parent = parent
- if(!QDELING(atom_parent) && (atom_parent.resistance_flags & ON_FIRE))
+ if(!QDELETED(atom_parent))
atom_parent.resistance_flags &= ~ON_FIRE
- atom_parent.update_appearance(UPDATE_ICON)
- return ..()
+ atom_parent.update_appearance()
/datum/component/burning/process(seconds_per_tick)
var/atom/atom_parent = parent
@@ -56,10 +57,20 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
return
atom_parent.take_damage(10 * seconds_per_tick, BURN, FIRE, FALSE)
+/// Alerts any examiners that the parent is on fire (even though it should be rather obvious)
+/datum/component/burning/proc/on_examine(atom/source, mob/user, list/examine_list)
+ SIGNAL_HANDLER
+
+ examine_list += span_danger("[source.p_theyre(TRUE)] burning!")
+
/// Maintains the burning overlay on the parent atom
/datum/component/burning/proc/on_update_overlays(atom/source, list/overlays)
SIGNAL_HANDLER
+ //most likely means the component is being removed
+ if(!(source.resistance_flags & ON_FIRE))
+ return
+
if(fire_overlay)
overlays += fire_overlay
diff --git a/code/datums/components/irradiated.dm b/code/datums/components/irradiated.dm
index c8a57f3761ad..bffd56459bfb 100644
--- a/code/datums/components/irradiated.dm
+++ b/code/datums/components/irradiated.dm
@@ -96,7 +96,7 @@
process_tox_damage(human_parent, seconds_per_tick)
/datum/component/irradiated/proc/should_halt_effects(mob/living/carbon/human/target)
- if (IS_IN_STASIS(target))
+ if (HAS_TRAIT(target, TRAIT_STASIS))
return TRUE
if (HAS_TRAIT(target, TRAIT_HALT_RADIATION_EFFECTS))
diff --git a/code/datums/mutations/void_magnet.dm b/code/datums/mutations/void_magnet.dm
index d6636b0b6306..48f04eda636a 100644
--- a/code/datums/mutations/void_magnet.dm
+++ b/code/datums/mutations/void_magnet.dm
@@ -60,7 +60,7 @@
/datum/action/cooldown/spell/void/cursed/proc/on_life(mob/living/source, seconds_per_tick, times_fired)
SIGNAL_HANDLER
- if(!isliving(source) || IS_IN_STASIS(source) || source.stat == DEAD || HAS_TRAIT(source, TRAIT_NO_TRANSFORM))
+ if(!isliving(source) || HAS_TRAIT(source, TRAIT_STASIS) || source.stat == DEAD || HAS_TRAIT(source, TRAIT_NO_TRANSFORM))
return
if(!is_valid_target(source))
diff --git a/code/datums/quirks/negative_quirks.dm b/code/datums/quirks/negative_quirks.dm
index 3a6f72acdc9b..77328dfce103 100644
--- a/code/datums/quirks/negative_quirks.dm
+++ b/code/datums/quirks/negative_quirks.dm
@@ -981,7 +981,7 @@
if(!iscarbon(quirk_holder))
return
- if(IS_IN_STASIS(quirk_holder))
+ if(HAS_TRAIT(quirk_holder, TRAIT_STASIS))
return
if(quirk_holder.stat == DEAD)
diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm
index fa9a3f785581..504b89e590ff 100644
--- a/code/datums/status_effects/debuffs/debuffs.dm
+++ b/code/datums/status_effects/debuffs/debuffs.dm
@@ -254,7 +254,7 @@
. = ..()
if(!.)
return
- owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_STATUS_EFFECT(id))
+ owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS), TRAIT_STATUS_EFFECT(id))
owner.add_filter("stasis_status_ripple", 2, list("type" = "ripple", "flags" = WAVE_BOUNDED, "radius" = 0, "size" = 2))
var/filter = owner.get_filter("stasis_status_ripple")
animate(filter, radius = 0, time = 0.2 SECONDS, size = 2, easing = JUMP_EASING, loop = -1, flags = ANIMATION_PARALLEL)
@@ -267,7 +267,7 @@
update_time_of_death()
/datum/status_effect/grouped/stasis/on_remove()
- owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), TRAIT_STATUS_EFFECT(id))
+ owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS), TRAIT_STATUS_EFFECT(id))
owner.remove_filter("stasis_status_ripple")
update_time_of_death()
if(iscarbon(owner))
diff --git a/code/datums/status_effects/debuffs/dna_transformation.dm b/code/datums/status_effects/debuffs/dna_transformation.dm
new file mode 100644
index 000000000000..09c688e7c1f4
--- /dev/null
+++ b/code/datums/status_effects/debuffs/dna_transformation.dm
@@ -0,0 +1,92 @@
+/// Transforms a carbon mob into a new DNA for a set amount of time,
+/// then turns them back to how they were before transformation.
+/datum/status_effect/temporary_transformation
+ id = "temp_dna_transformation"
+ tick_interval = -1
+ duration = 1 MINUTES // set in on creation, this just needs to be any value to process
+ alert_type = null
+ remove_on_fullheal = TRUE
+ /// A reference to a COPY of the DNA that the mob will be transformed into.
+ var/datum/dna/new_dna
+ /// A reference to a COPY of the DNA of the mob prior to transformation.
+ var/datum/dna/old_dna
+
+/datum/status_effect/temporary_transformation/Destroy()
+ . = ..() // parent must be called first, so we clear DNA refs AFTER transforming back... yeah i know
+ QDEL_NULL(new_dna)
+ QDEL_NULL(old_dna)
+
+/datum/status_effect/temporary_transformation/on_creation(mob/living/new_owner, new_duration = 1 MINUTES, datum/dna/dna_to_copy)
+ src.duration = (new_duration == INFINITY) ? -1 : new_duration
+ src.new_dna = new()
+ src.old_dna = new()
+ dna_to_copy.copy_dna(new_dna)
+ return ..()
+
+/datum/status_effect/temporary_transformation/on_apply()
+ if(!iscarbon(owner))
+ return FALSE
+
+ var/mob/living/carbon/transforming = owner
+ if(!transforming.has_dna())
+ return FALSE
+
+ // Save the old DNA
+ transforming.dna.copy_dna(old_dna)
+ // Makes them into the new DNA
+ new_dna.transfer_identity(transforming)
+ transforming.real_name = new_dna.real_name
+ transforming.name = transforming.get_visible_name()
+ transforming.updateappearance(mutcolor_update = TRUE)
+ transforming.domutcheck()
+ return TRUE
+
+/datum/status_effect/temporary_transformation/on_remove()
+ var/mob/living/carbon/transforming = owner
+
+ if(!QDELING(owner)) // Don't really need to do appearance stuff if we're being deleted
+ old_dna.transfer_identity(transforming)
+ transforming.updateappearance(mutcolor_update = TRUE)
+ transforming.domutcheck()
+
+ transforming.real_name = old_dna.real_name // Name is fine though
+ transforming.name = transforming.get_visible_name()
+
+/datum/status_effect/temporary_transformation/trans_sting
+ /// Tracks the time left on the effect when the owner last died. Used to pause the effect.
+ var/time_before_pause = -1
+ /// Signals which we react to to determine if we should pause the effect.
+ var/static/list/update_on_signals = list(
+ COMSIG_MOB_STATCHANGE,
+ SIGNAL_ADDTRAIT(TRAIT_STASIS),
+ SIGNAL_REMOVETRAIT(TRAIT_STASIS),
+ SIGNAL_ADDTRAIT(TRAIT_DEATHCOMA),
+ SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA),
+ )
+
+/datum/status_effect/temporary_transformation/trans_sting/on_apply()
+ . = ..()
+ if(!.)
+ return
+ RegisterSignals(owner, update_on_signals, PROC_REF(pause_effect))
+ pause_effect(owner) // for if we sting a dead guy
+
+/datum/status_effect/temporary_transformation/trans_sting/on_remove()
+ . = ..()
+ UnregisterSignal(owner, update_on_signals)
+
+/datum/status_effect/temporary_transformation/trans_sting/proc/pause_effect(mob/living/source)
+ SIGNAL_HANDLER
+
+ // Pause if we're dead, appear dead, or in stasis
+ if(source.stat == DEAD || HAS_TRAIT(source, TRAIT_DEATHCOMA) || HAS_TRAIT(source, TRAIT_STASIS))
+ if(duration == -1)
+ return // Already paused
+
+ time_before_pause = duration - world.time
+ duration = -1
+
+ // Resume if we're none of the above and also were paused
+ else if(time_before_pause != -1)
+ duration = time_before_pause + world.time
+ time_before_pause = -1
diff --git a/code/datums/status_effects/debuffs/drowsiness.dm b/code/datums/status_effects/debuffs/drowsiness.dm
index 5bc415d7cd44..a64fd710068d 100644
--- a/code/datums/status_effects/debuffs/drowsiness.dm
+++ b/code/datums/status_effects/debuffs/drowsiness.dm
@@ -29,7 +29,7 @@
/datum/status_effect/drowsiness/tick(seconds_per_tick)
// You do not feel drowsy while unconscious or in stasis
- if(owner.stat >= UNCONSCIOUS || IS_IN_STASIS(owner))
+ if(owner.stat >= UNCONSCIOUS || HAS_TRAIT(owner, TRAIT_STASIS))
return
// Resting helps against drowsiness
diff --git a/code/datums/status_effects/debuffs/drunk.dm b/code/datums/status_effects/debuffs/drunk.dm
index adba65380261..e0b26797b9f4 100644
--- a/code/datums/status_effects/debuffs/drunk.dm
+++ b/code/datums/status_effects/debuffs/drunk.dm
@@ -63,7 +63,7 @@
/datum/status_effect/inebriated/tick()
// Drunk value does not decrease while dead or in stasis
- if(owner.stat == DEAD || IS_IN_STASIS(owner))
+ if(owner.stat == DEAD || HAS_TRAIT(owner, TRAIT_STASIS))
return
// Every tick, the drunk value decrases by
diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm
index c84c0598b642..12482d152236 100644
--- a/code/datums/wounds/bones.dm
+++ b/code/datums/wounds/bones.dm
@@ -76,7 +76,7 @@
/datum/wound/blunt/bone/handle_process(seconds_per_tick, times_fired)
. = ..()
- if (!victim || IS_IN_STASIS(victim))
+ if (!victim || HAS_TRAIT(victim, TRAIT_STASIS))
return
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle)
diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm
index 42203c4f2a70..f34cd34623b6 100644
--- a/code/datums/wounds/burns.dm
+++ b/code/datums/wounds/burns.dm
@@ -37,7 +37,7 @@
/datum/wound/burn/flesh/handle_process(seconds_per_tick, times_fired)
- if (!victim || IS_IN_STASIS(victim))
+ if (!victim || HAS_TRAIT(victim, TRAIT_STASIS))
return
. = ..()
diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm
index 82f49b035032..1085b422263d 100644
--- a/code/datums/wounds/pierce.dm
+++ b/code/datums/wounds/pierce.dm
@@ -66,7 +66,7 @@
return BLOOD_FLOW_STEADY
/datum/wound/pierce/bleed/handle_process(seconds_per_tick, times_fired)
- if (!victim || IS_IN_STASIS(victim))
+ if (!victim || HAS_TRAIT(victim, TRAIT_STASIS))
return
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm
index 410f48d9d576..e297849e61a3 100644
--- a/code/datums/wounds/slash.dm
+++ b/code/datums/wounds/slash.dm
@@ -134,7 +134,7 @@
/datum/wound/slash/flesh/handle_process(seconds_per_tick, times_fired)
- if (!victim || IS_IN_STASIS(victim))
+ if (!victim || HAS_TRAIT(victim, TRAIT_STASIS))
return
// in case the victim has the NOBLOOD trait, the wound will simply not clot on it's own
diff --git a/code/game/atom_defense.dm b/code/game/atom_defense.dm
index 7d6fa23911f9..0149a0175f79 100644
--- a/code/game/atom_defense.dm
+++ b/code/game/atom_defense.dm
@@ -137,19 +137,3 @@
if(uses_integrity)
return clamp(PENETRATE_ARMOUR(get_armor_rating(impacting_projectile.armor_flag), impacting_projectile.armour_penetration), 0, 100)
return 0
-
-/**
- * Should be called when the atom is destroyed by fire
- * This proc is terrible. I do not know why it exists.
- * Please remove it at some point.
- */
-/atom/proc/burn()
- return
-
-/**
- * Sends COMSIG_ATOM_EXTINGUISH signal which properly removes burning component.
- * Can be hooked onto for extra behavior.
- */
-/atom/proc/extinguish()
- SHOULD_CALL_PARENT(TRUE)
- return SEND_SIGNAL(src, COMSIG_ATOM_EXTINGUISH)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 779671e94a46..e8b4b6f9c7f0 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -949,9 +949,23 @@
return FALSE
return TRUE
+/**
+ * Respond to fire being used on our atom
+ *
+ * Default behaviour is to send [COMSIG_ATOM_FIRE_ACT] and return
+ */
/atom/proc/fire_act(exposed_temperature, exposed_volume)
SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume)
- return
+ return FALSE
+
+/**
+ * Sends [COMSIG_ATOM_EXTINGUISH] signal, which properly removes burning component if it is present.
+ *
+ * Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return
+ */
+/atom/proc/extinguish()
+ SHOULD_CALL_PARENT(TRUE)
+ return SEND_SIGNAL(src, COMSIG_ATOM_EXTINGUISH)
/**
* React to being hit by a thrown object
@@ -1912,6 +1926,7 @@
* Override this if you want custom behaviour in whatever gets hit by the rust
*/
/atom/proc/rust_heretic_act()
+ return
/**
* Used to set something as 'open' if it's being used as a supplypod
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 5fca4a56b0d1..3123bc4749f9 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -1114,8 +1114,6 @@
if(machine_stat & BROKEN)
. += span_notice("It looks broken and non-functional.")
if(!(resistance_flags & INDESTRUCTIBLE))
- if(resistance_flags & ON_FIRE)
- . += span_warning("It's on fire!")
var/healthpercent = (atom_integrity/max_integrity) * 100
switch(healthpercent)
if(50 to 99)
diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm
index 54deffb85626..b60b563f7b2d 100644
--- a/code/game/machinery/stasis.dm
+++ b/code/game/machinery/stasis.dm
@@ -68,7 +68,7 @@
/obj/machinery/stasis/Exited(atom/movable/gone, direction)
if(gone == occupant)
var/mob/living/L = gone
- if(IS_IN_STASIS(L))
+ if(HAS_TRAIT(L, TRAIT_STASIS))
thaw_them(L)
return ..()
@@ -157,9 +157,9 @@
return
var/mob/living/L_occupant = occupant
if(stasis_running())
- if(!IS_IN_STASIS(L_occupant))
+ if(!HAS_TRAIT(L_occupant, TRAIT_STASIS))
chill_out(L_occupant)
- else if(IS_IN_STASIS(L_occupant))
+ else if(HAS_TRAIT(L_occupant, TRAIT_STASIS))
thaw_them(L_occupant)
/obj/machinery/stasis/screwdriver_act(mob/living/user, obj/item/I)
diff --git a/code/game/objects/effects/particles/smoke.dm b/code/game/objects/effects/particles/smoke.dm
index 13c8da4218e0..4f31ffc08699 100644
--- a/code/game/objects/effects/particles/smoke.dm
+++ b/code/game/objects/effects/particles/smoke.dm
@@ -18,6 +18,11 @@
/particles/smoke/burning
position = list(0, 0, 0)
+/particles/smoke/burning/small
+ spawning = 1
+ scale = list(0.8, 0.8)
+ velocity = list(0, 0.4, 0)
+
/particles/smoke/steam
icon_state = list("steam_1" = 1, "steam_2" = 1, "steam_3" = 2)
fade = 1.5 SECONDS
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index e2078dad2d2b..02588d175c03 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -3,6 +3,7 @@
name = "item"
icon = 'icons/obj/objects.dmi'
blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ burning_particles = /particles/smoke/burning/small
pass_flags_self = PASSITEM
/* !!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 0d29aa1f203d..383c9d88af7e 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -116,10 +116,10 @@
///the obj's reaction when touched by acid
/obj/acid_act(acidpwr, acid_volume)
. = ..()
- if((resistance_flags & UNACIDABLE) || (acid_volume <= 0) || acidpwr <= 0)
+ if((resistance_flags & UNACIDABLE) || (acid_volume <= 0) || (acidpwr <= 0))
return FALSE
- AddComponent(/datum/component/acid, acidpwr, acid_volume)
+ AddComponent(/datum/component/acid, acidpwr, acid_volume, custom_acid_overlay || GLOB.acid_overlay)
return TRUE
///called when the obj is destroyed by acid.
@@ -131,8 +131,8 @@
///Called when the obj is exposed to fire.
/obj/fire_act(exposed_temperature, exposed_volume)
if(isturf(loc))
- var/turf/T = loc
- if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE))
+ var/turf/our_turf = loc
+ if(our_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE))
return
if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0)
@@ -141,9 +141,8 @@
return TRUE
return ..()
-///called when the obj is destroyed by fire
-/obj/burn()
- . = ..()
+/// Should be called when the atom is destroyed by fire, comparable to acid_melt() proc
+/obj/proc/burn()
deconstruct(FALSE)
///Called when the obj is hit by a tesla bolt.
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index f9568d660cb3..2e5f404b5849 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -339,11 +339,6 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
if(. && receive_ricochet_damage_coeff)
take_damage(P.damage * receive_ricochet_damage_coeff, P.damage_type, P.armor_flag, 0, turn(P.dir, 180), P.armour_penetration) // pass along receive_ricochet_damage_coeff damage to the structure for the ricochet
-/obj/update_overlays()
- . = ..()
- if(resistance_flags & ON_FIRE)
- . += custom_fire_overlay ? custom_fire_overlay : GLOB.fire_overlay
-
/// Handles exposing an object to reagents.
/obj/expose_reagents(list/reagents, datum/reagents/source, methods=TOUCH, volume_modifier=1, show_message=TRUE)
. = ..()
diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm
index 871a58e823b5..3e2d83550000 100644
--- a/code/game/objects/structures/bonfire.dm
+++ b/code/game/objects/structures/bonfire.dm
@@ -146,13 +146,13 @@
var/mob/living/burn_victim = burn_target
burn_victim.adjust_fire_stacks(BONFIRE_FIRE_STACK_STRENGTH * 0.5 * seconds_per_tick)
burn_victim.ignite_mob()
- else if(isobj(burn_target))
- var/obj/burned_object = burn_target
- if(grill && isitem(burned_object))
- var/obj/item/grilled_item = burned_object
+ else
+ var/atom/movable/burned_movable = burn_target
+ if(grill && isitem(burned_movable))
+ var/obj/item/grilled_item = burned_movable
SEND_SIGNAL(grilled_item, COMSIG_ITEM_GRILL_PROCESS, src, seconds_per_tick) //Not a big fan, maybe make this use fire_act() in the future.
continue
- burned_object.fire_act(1000, 250 * seconds_per_tick)
+ burned_movable.fire_act(1000, 250 * seconds_per_tick)
/obj/structure/bonfire/process(seconds_per_tick)
if(!check_oxygen())
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 8808b89125e3..5303c8856515 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -601,12 +601,12 @@ GLOBAL_LIST_EMPTY(station_turfs)
if((acidpwr <= 0) || (acid_volume <= 0))
return FALSE
- AddComponent(/datum/component/acid, acidpwr, acid_volume)
- for(var/obj/O in src)
- if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
+ AddComponent(/datum/component/acid, acidpwr, acid_volume, GLOB.acid_overlay)
+ for(var/atom/movable/movable_atom as anything in src)
+ if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(movable_atom, TRAIT_T_RAY_VISIBLE))
continue
- O.acid_act(acidpwr, acid_volume)
+ movable_atom.acid_act(acidpwr, acid_volume)
return . || TRUE
diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm
index f8e731e820e9..0eab76764623 100644
--- a/code/modules/antagonists/changeling/powers/tiny_prick.dm
+++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm
@@ -65,46 +65,74 @@
/datum/action/changeling/sting/transformation
name = "Transformation Sting"
- desc = "We silently sting a human, injecting a retrovirus that forces them to transform. Costs 50 chemicals."
- helptext = "The victim will transform much like a changeling would. Does not provide a warning to others. Mutations will not be transferred, and monkeys will become human."
+ desc = "We silently sting an organism, injecting a retrovirus that forces them to transform."
+ helptext = "The victim will transform much like a changeling would. \
+ For complex humanoids, the transformation is temporarily, but the duration is paused while the victim is dead or in stasis. \
+ For more simple humanoids, such as monkeys, the transformation is permanent. \
+ Does not provide a warning to others. Mutations will not be transferred."
button_icon_state = "sting_transform"
- chemical_cost = 50
- dna_cost = 3
- var/datum/changeling_profile/selected_dna = null
+ chemical_cost = 33 // Low enough that you can sting only two people in quick succession
+ dna_cost = 2
+ /// A reference to our active profile, which we grab DNA from
+ VAR_FINAL/datum/changeling_profile/selected_dna
+ /// Duration of the sting
+ var/sting_duration = 8 MINUTES
+
+/datum/action/changeling/sting/transformation/Grant(mob/grant_to)
+ . = ..()
+ build_all_button_icons(UPDATE_BUTTON_NAME)
-/datum/action/changeling/sting/transformation/Trigger(trigger_flags)
- var/mob/user = usr
+/datum/action/changeling/sting/transformation/update_button_name(atom/movable/screen/movable/action_button/button, force)
+ . = ..()
+ button.desc += " Lasts [DisplayTimeText(sting_duration)] for humans, but duration is paused while dead or in stasis."
+ button.desc += " Costs [chemical_cost] chemicals."
+
+/datum/action/changeling/sting/transformation/Destroy()
+ selected_dna = null
+ return ..()
+
+/datum/action/changeling/sting/transformation/set_sting(mob/user)
+ selected_dna = null
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
- if(changeling.chosen_sting)
- unset_sting(user)
+ var/datum/changeling_profile/new_selected_dna = changeling.select_dna()
+ if(QDELETED(src) || QDELETED(changeling) || QDELETED(user))
return
- selected_dna = changeling.select_dna()
- if(!selected_dna)
+ if(!new_selected_dna || changeling.chosen_sting || selected_dna) // selected other sting or other DNA while sleeping
return
- if(NOTRANSSTING in selected_dna.dna.species.species_traits)
- user.balloon_alert(user, "incompatible DNA!")
- return
- ..()
+ selected_dna = new_selected_dna
+ return ..()
/datum/action/changeling/sting/transformation/can_sting(mob/user, mob/living/carbon/target)
. = ..()
if(!.)
return
- if((HAS_TRAIT(target, TRAIT_HUSK)) || !iscarbon(target) || (NOTRANSSTING in target.dna.species.species_traits))
+ // Similar checks here are ran to that of changeling can_absorb_dna -
+ // Logic being that if their DNA is incompatible with us, it's also bad for transforming
+ if(!iscarbon(target) \
+ || !target.has_dna() \
+ || HAS_TRAIT(target, TRAIT_HUSK) \
+ || HAS_TRAIT(target, TRAIT_BADDNA) \
+ || (HAS_TRAIT(target, TRAIT_NO_DNA_COPY) && !ismonkey(target))) // sure, go ahead, make a monk-clone
user.balloon_alert(user, "incompatible DNA!")
return FALSE
+ if(target.has_status_effect(/datum/status_effect/temporary_transformation/trans_sting))
+ user.balloon_alert(user, "already transformed!")
+ return FALSE
return TRUE
-/datum/action/changeling/sting/transformation/sting_action(mob/user, mob/target)
- log_combat(user, target, "stung", "transformation sting", " new identity is '[selected_dna.dna.real_name]'")
- var/datum/dna/NewDNA = selected_dna.dna
-
- var/mob/living/carbon/C = target
- . = TRUE
- if(istype(C))
- C.real_name = NewDNA.real_name
- NewDNA.transfer_identity(C)
- C.updateappearance(mutcolor_update=1)
+/datum/action/changeling/sting/transformation/sting_action(mob/living/user, mob/living/target)
+ var/final_duration = sting_duration
+ var/final_message = span_notice("We transform [target] into [selected_dna.dna.real_name].")
+ if(ismonkey(target))
+ final_duration = INFINITY
+ final_message = span_warning("Our genes cry out as we transform the lesser form of [target] into [selected_dna.dna.real_name] permanently!")
+
+ if(target.apply_status_effect(/datum/status_effect/temporary_transformation/trans_sting, final_duration, selected_dna.dna))
+ ..()
+ log_combat(user, target, "stung", "transformation sting", " new identity is '[selected_dna.dna.real_name]'")
+ to_chat(user, final_message)
+ return TRUE
+ return FALSE
/datum/action/changeling/sting/false_armblade
diff --git a/code/modules/bitrunning/antagonists/cyber_police.dm b/code/modules/bitrunning/antagonists/cyber_police.dm
index 438b86acdec9..73ff96ff7c8c 100644
--- a/code/modules/bitrunning/antagonists/cyber_police.dm
+++ b/code/modules/bitrunning/antagonists/cyber_police.dm
@@ -33,7 +33,6 @@
player.add_traits(list(
//TRAIT_NO_AUGMENTS,
TRAIT_NO_DNA_COPY,
- TRAIT_NO_TRANSFORMATION_STING,
TRAIT_NOBLOOD,
TRAIT_NOBREATH,
TRAIT_NOHUNGER,
diff --git a/code/modules/bitrunning/components/netpod_healing.dm b/code/modules/bitrunning/components/netpod_healing.dm
index fc7de89bcf3e..2d302d5b4adb 100644
--- a/code/modules/bitrunning/components/netpod_healing.dm
+++ b/code/modules/bitrunning/components/netpod_healing.dm
@@ -59,6 +59,15 @@
id = "embryonic"
alert_type = /atom/movable/screen/alert/status_effect/embryonic
+/datum/status_effect/embryonic/on_apply()
+ . = ..()
+ if(.)
+ ADD_TRAIT(owner, TRAIT_STASIS, TRAIT_STATUS_EFFECT(id))
+
+/datum/status_effect/embryonic/on_remove()
+ REMOVE_TRAIT(owner, TRAIT_STASIS, TRAIT_STATUS_EFFECT(id))
+ return ..()
+
/atom/movable/screen/alert/status_effect/embryonic
name = "Embryonic Stasis"
icon_state = "netpod_stasis"
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index 2e2674e14e76..147079ae720c 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -3,7 +3,7 @@
/mob/living/carbon/alien/larva/Life(seconds_per_tick = SSMOBS_DT, times_fired)
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
return
- if(!..() || IS_IN_STASIS(src) || (amount_grown >= max_grown))
+ if(!..() || HAS_TRAIT(src, TRAIT_STASIS) || (amount_grown >= max_grown))
return // We're dead, in stasis, or already grown.
// GROW!
amount_grown = min(amount_grown + (0.5 * seconds_per_tick), max_grown)
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index ac449c7794c9..9d9be81466ac 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -1548,7 +1548,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
return
//Only stabilise core temp when alive and not in statis
- if(humi.stat < DEAD && !IS_IN_STASIS(humi))
+ if(humi.stat < DEAD && !HAS_TRAIT(humi, TRAIT_STASIS))
body_temperature_core(humi, seconds_per_tick, times_fired)
//These do run in statis
@@ -1556,7 +1556,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
body_temperature_alerts(humi, seconds_per_tick, times_fired)
//Do not cause more damage in statis
- if(!IS_IN_STASIS(humi))
+ if(!HAS_TRAIT(humi, TRAIT_STASIS))
body_temperature_damage(humi, seconds_per_tick, times_fired)
/**
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 678442bd79d3..09e83b21d87a 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -29,7 +29,7 @@
//Body temperature stability and damage
dna.species.handle_body_temperature(src, seconds_per_tick, times_fired)
- if(!IS_IN_STASIS(src))
+ if(!HAS_TRAIT(src, TRAIT_STASIS))
if(.) //not dead
for(var/datum/mutation/human/HM in dna.mutations) // Handle active genes
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 45d36076c6f6..037df6b982e3 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -16,7 +16,6 @@
TRAIT_PIERCEIMMUNE,
TRAIT_RADIMMUNE,
TRAIT_NO_DNA_COPY,
- TRAIT_NO_TRANSFORMATION_STING,
TRAIT_NODISMEMBER,
TRAIT_NEVER_WOUNDED
)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 660fb28e8e81..e9dd49a3a951 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -14,7 +14,7 @@
damageoverlaytemp = 0
update_damage_hud()
- if(IS_IN_STASIS(src))
+ if(HAS_TRAIT(src, TRAIT_STASIS))
. = ..()
reagents.handle_stasis_chems(src, seconds_per_tick, times_fired)
else
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 27995ce1ce00..cda90a8e7316 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -40,7 +40,7 @@
if(isnull(loc) || HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
return
- if(!IS_IN_STASIS(src))
+ if(!HAS_TRAIT(src, TRAIT_STASIS))
if(stat != DEAD)
//Mutations and radiation
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index e8be8f51da47..07150137a295 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -531,7 +531,7 @@
return TRUE
if(!(flags & IGNORE_GRAB) && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE)
return TRUE
- if(!(flags & IGNORE_STASIS) && IS_IN_STASIS(src))
+ if(!(flags & IGNORE_STASIS) && HAS_TRAIT(src, TRAIT_STASIS))
return TRUE
return FALSE
@@ -1564,9 +1564,9 @@ GLOBAL_LIST_EMPTY(fire_appearances)
return fire_status.ignite(silent)
/mob/living/proc/update_fire()
- var/datum/status_effect/fire_handler/fire_handler = has_status_effect(/datum/status_effect/fire_handler)
- if(fire_handler)
- fire_handler.update_overlay()
+ var/datum/status_effect/fire_handler/fire_stacks/fire_stacks = has_status_effect(/datum/status_effect/fire_handler/fire_stacks)
+ if(fire_stacks)
+ fire_stacks.update_overlay()
/**
* Extinguish all fire on the mob
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 8df5e8b6d596..f5224f337d1f 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -1154,12 +1154,12 @@
if(BLEED_OVERLAY_LOW to BLEED_OVERLAY_MED)
new_bleed_icon = "[body_zone]_1"
if(BLEED_OVERLAY_MED to BLEED_OVERLAY_GUSH)
- if(owner.body_position == LYING_DOWN || IS_IN_STASIS(owner) || owner.stat == DEAD)
+ if(owner.body_position == LYING_DOWN || HAS_TRAIT(owner, TRAIT_STASIS) || owner.stat == DEAD)
new_bleed_icon = "[body_zone]_2s"
else
new_bleed_icon = "[body_zone]_2"
if(BLEED_OVERLAY_GUSH to INFINITY)
- if(IS_IN_STASIS(owner) || owner.stat == DEAD)
+ if(HAS_TRAIT(owner, TRAIT_STASIS) || owner.stat == DEAD)
new_bleed_icon = "[body_zone]_2s"
else
new_bleed_icon = "[body_zone]_3"
diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm
index 449f636c8303..03554ac081d4 100644
--- a/code/modules/vehicles/_vehicle.dm
+++ b/code/modules/vehicles/_vehicle.dm
@@ -64,8 +64,6 @@
/obj/vehicle/examine(mob/user)
. = ..()
- if(resistance_flags & ON_FIRE)
- . += span_warning("It's on fire!")
. += generate_integrity_message()
/// Returns a readable string of the vehicle's health for examining. Overridden by subtypes who want to be more verbose with their health messages.
diff --git a/monkestation/code/modules/datums/components/nanites.dm b/monkestation/code/modules/datums/components/nanites.dm
index 29f516da7828..a2d5a962e249 100644
--- a/monkestation/code/modules/datums/components/nanites.dm
+++ b/monkestation/code/modules/datums/components/nanites.dm
@@ -110,7 +110,7 @@
adjust_nanites(null, amount) //just add to the nanite volume
/datum/component/nanites/process(seconds_per_tick)
- if(!IS_IN_STASIS(host_mob))
+ if(!HAS_TRAIT(host_mob, TRAIT_STASIS))
adjust_nanites(null, (regen_rate + (SSresearch.science_tech.researched_nodes["nanite_harmonic"] ? HARMONIC_REGEN_BOOST : 0)) * seconds_per_tick)
add_research()
for(var/X in programs)
diff --git a/monkestation/code/modules/ghost_players/arena/arena_assets/event_floors.dm b/monkestation/code/modules/ghost_players/arena/arena_assets/event_floors.dm
index 5ed0633862cc..64d10d42108c 100644
--- a/monkestation/code/modules/ghost_players/arena/arena_assets/event_floors.dm
+++ b/monkestation/code/modules/ghost_players/arena/arena_assets/event_floors.dm
@@ -8,3 +8,9 @@
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
+
+/turf/open/misc/ashplanet/rocky/arena
+ initial_gas_mix = OPENTURF_DEFAULT_ATMOS
+
+/turf/open/water/arena
+ initial_gas_mix = OPENTURF_DEFAULT_ATMOS
diff --git a/monkestation/code/modules/ghost_players/arena/maps/atlantis.dmm b/monkestation/code/modules/ghost_players/arena/maps/atlantis.dmm
index 06e098ddcf56..de89b464516c 100644
--- a/monkestation/code/modules/ghost_players/arena/maps/atlantis.dmm
+++ b/monkestation/code/modules/ghost_players/arena/maps/atlantis.dmm
@@ -10,41 +10,31 @@
"b" = (
/mob/living/basic/aquatic/fish,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"d" = (
/obj/structure/flora/bush/stalky/style_3,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"g" = (
/obj/structure/flora/rock/pile/icy/style_2{
name = "rocks"
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"h" = (
/obj/structure/flora/rock/icy/style_2{
name = "rock"
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"i" = (
/obj/effect/overlay/water,
/obj/machinery/light/floor/has_bulb,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"k" = (
/obj/structure/atlantis/column/broken_1,
@@ -91,27 +81,21 @@
anchored = 1
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"v" = (
/obj/structure/flora/rock/pile/icy/style_3{
name = "rocks"
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"w" = (
/obj/structure/flora/rock/icy{
name = "rock"
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"z" = (
/obj/effect/overlay/water,
@@ -122,9 +106,7 @@
"A" = (
/obj/structure/flora/bush/stalky/style_2,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"B" = (
/obj/item/aquarium_prop/seaweed_top{
@@ -132,9 +114,7 @@
},
/obj/effect/overlay/water,
/obj/machinery/light/floor/has_bulb,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"D" = (
/obj/effect/overlay/water,
@@ -146,56 +126,42 @@
"E" = (
/obj/structure/flora/bush/stalky,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"G" = (
/obj/structure/flora/rock/pile/icy{
name = "rocks"
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"H" = (
/mob/living/basic/aquatic/fish/gupper,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"K" = (
/obj/structure/flora/rock/icy/style_3{
name = "rock"
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"L" = (
/obj/machinery/light/floor/has_bulb,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"N" = (
/obj/item/aquarium_prop/seaweed_top{
anchored = 1
},
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"P" = (
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"Q" = (
/obj/structure/atlantis/statue{
@@ -209,9 +175,7 @@
"R" = (
/obj/structure/flora/bush/reed/style_3,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"T" = (
/obj/structure/atlantis/column/lantern,
@@ -226,16 +190,12 @@
/obj/structure/flora/bush/reed/style_3,
/mob/living/basic/aquatic/fish/gupper,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"V" = (
/mob/living/basic/aquatic/fish/cod,
/obj/effect/overlay/water,
-/turf/open/misc/ashplanet/rocky{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/misc/ashplanet/rocky,
/area/centcom/tdome/arena/actual)
"X" = (
/obj/effect/overlay/water,
diff --git a/monkestation/code/modules/ghost_players/arena/maps/two_forts.dmm b/monkestation/code/modules/ghost_players/arena/maps/two_forts.dmm
index ea3c06ee5cb5..c2bdb05d8de6 100644
--- a/monkestation/code/modules/ghost_players/arena/maps/two_forts.dmm
+++ b/monkestation/code/modules/ghost_players/arena/maps/two_forts.dmm
@@ -26,9 +26,7 @@
/area/centcom/tdome/arena/actual)
"hA" = (
/obj/structure/flora/bush/reed/style_3,
-/turf/open/water{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/water/arena,
/area/centcom/tdome/arena/actual)
"hL" = (
/obj/effect/turf_decal/siding/wood{
@@ -76,9 +74,7 @@
/area/centcom/tdome/arena/actual)
"wZ" = (
/obj/machinery/light/directional/north,
-/turf/open/water{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/water/arena,
/area/centcom/tdome/arena/actual)
"yW" = (
/obj/machinery/light/small/blacklight/directional/west,
@@ -94,15 +90,11 @@
/area/centcom/tdome/arena/actual)
"BT" = (
/obj/structure/flora/bush/reed/style_2,
-/turf/open/water{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/water/arena,
/area/centcom/tdome/arena/actual)
"Cb" = (
/obj/machinery/light/directional/south,
-/turf/open/water{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/water/arena,
/area/centcom/tdome/arena/actual)
"Cu" = (
/obj/effect/turf_decal/sand/plating,
@@ -159,9 +151,7 @@
/turf/open/floor/wood/parquet,
/area/centcom/tdome/arena/actual)
"VF" = (
-/turf/open/water{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/water/arena,
/area/centcom/tdome/arena/actual)
"Wh" = (
/obj/effect/turf_decal/sand/plating,
@@ -185,9 +175,7 @@
/area/centcom/tdome/arena/actual)
"Zu" = (
/obj/structure/flora/bush/reed,
-/turf/open/water{
- initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
- },
+/turf/open/water/arena,
/area/centcom/tdome/arena/actual)
(1,1,1) = {"
diff --git a/monkestation/code/modules/research/techweb/all_nodes.dm b/monkestation/code/modules/research/techweb/all_nodes.dm
index 4e07d6cebf3e..7a491327307b 100644
--- a/monkestation/code/modules/research/techweb/all_nodes.dm
+++ b/monkestation/code/modules/research/techweb/all_nodes.dm
@@ -207,5 +207,3 @@
design_ids = list("linked_surgery")
boost_item_paths = list(/obj/item/organ/internal/cyberimp/brain/linked_surgery)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
- hidden = TRUE
- experimental = TRUE
diff --git a/monkestation/code/modules/surgery/organs/augments.dm b/monkestation/code/modules/surgery/organs/augments.dm
index 91002d049d0a..8f2ea371e9ce 100644
--- a/monkestation/code/modules/surgery/organs/augments.dm
+++ b/monkestation/code/modules/surgery/organs/augments.dm
@@ -19,7 +19,7 @@
/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/on_step_completion(mob/living/user, datum/surgery_step/current_step, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
SIGNAL_HANDLER
- if(CHECK_BITFIELD(organ_flags, ORGAN_FAILING))
+ if(organ_flags & ORGAN_FAILING)
return
var/possible_steps = list()
if(current_step.repeatable)
@@ -36,8 +36,8 @@
/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/check_surgery(mob/user, datum/surgery/surgery, mob/patient)
SIGNAL_HANDLER
- if(CHECK_BITFIELD(organ_flags, ORGAN_FAILING))
- return
+ if(organ_flags & ORGAN_FAILING)
+ return FALSE
if(surgery.replaced_by in loaded_surgeries)
return COMPONENT_CANCEL_SURGERY
if(surgery.type in loaded_surgeries)
@@ -45,7 +45,7 @@
/obj/item/organ/internal/cyberimp/brain/linked_surgery/on_insert(mob/living/carbon/organ_owner, special)
. = ..()
- update_surgeries(download_from_held = FALSE, silent = TRUE)
+ update_surgeries(download_from_held = FALSE)
RegisterSignal(organ_owner, COMSIG_SURGERY_STARTING, PROC_REF(check_surgery))
RegisterSignal(organ_owner, COMSIG_MOB_SURGERY_STEP_SUCCESS, PROC_REF(on_step_completion))
@@ -59,7 +59,7 @@
return
update_surgeries()
-/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/update_surgeries(download_from_held = TRUE, silent = FALSE)
+/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/update_surgeries(download_from_held = TRUE)
var/list/prev_amt = length(loaded_surgeries)
for(var/design in linked_techweb.researched_designs)
var/datum/design/surgery/surgery_design = SSresearch.techweb_design_by_id(design)
@@ -84,8 +84,7 @@
surgeries_to_add |= surgery_design.surgery
else if(istype(held_item, /obj/item/disk/nuclear))
// funny joke message
- if(!silent)
- to_chat(owner, span_warning("Do you want to explode? You can't get surgery data from \the [held_item]!"))
+ to_chat(owner, span_warning("Do you want to explode? You can't get surgery data from \the [held_item]!"))
continue
else
continue
@@ -97,8 +96,6 @@
owner.balloon_alert(owner, "surgery download interrupted!")
return
loaded_surgeries |= surgeries_to_add
- if(silent)
- return
var/new_amt = length(loaded_surgeries)
var/diff = new_amt - prev_amt
if(diff)
@@ -113,12 +110,24 @@
organ_traits = list(TRAIT_PERFECT_SURGEON)
actions_types = null
var/list/blocked_surgeries = list(
- /datum/surgery/advanced/brainwashing_sleeper,
+ /datum/surgery/advanced/brainwashing_sleeper, // this one has special handling
/datum/surgery/advanced/necrotic_revival,
/datum/surgery/organ_extraction
)
-/obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect/update_surgeries(download_from_held = TRUE, silent = FALSE)
+// Special behavior to allow for sleeper agent surgery to be done if the traitor has the objective
+/obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect/check_surgery(mob/user, datum/surgery/surgery, mob/patient)
+ . = ..()
+ if(istype(surgery, /datum/surgery/advanced/brainwashing_sleeper))
+ var/datum/antagonist/traitor/traitor_datum = user.mind?.has_antag_datum(/datum/antagonist/traitor)
+ var/list/active_objectives = traitor_datum?.uplink_handler?.active_objectives
+ if(!length(active_objectives))
+ return
+ if(locate(/datum/traitor_objective/sleeper_protocol) in active_objectives)
+ return COMPONENT_FORCE_SURGERY
+
+
+/obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect/update_surgeries(download_from_held = TRUE)
loaded_surgeries.Cut()
for(var/datum/surgery/surgery as() in GLOB.surgeries_list)
if(surgery.type in blocked_surgeries)
diff --git a/monkestation/code/modules/uplink/uplink_items/device_tools.dm b/monkestation/code/modules/uplink/uplink_items/device_tools.dm
index 3ccfc94cb441..bc0776cbb196 100644
--- a/monkestation/code/modules/uplink/uplink_items/device_tools.dm
+++ b/monkestation/code/modules/uplink/uplink_items/device_tools.dm
@@ -3,3 +3,12 @@
/datum/uplink_item/device_tools/rad_laser
surplus = 40
+
+/datum/uplink_item/device_tools/hacked_linked_surgery
+ name = "Syndicate Surgery Implant"
+ desc = "A powerful brain implant, capable of uploading perfect, forbidden surgical knowledge to its users mind, \
+ allowing them to do just about any surgery, anywhere, without making any (unintentional) mistakes. \
+ Comes with a syndicate autosurgeon for immediate self-application."
+ cost = 12
+ item = /obj/item/autosurgeon/syndicate/hacked_linked_surgery
+ surplus = 50
diff --git a/monkestation/code/modules/uplink/uplink_items/job.dm b/monkestation/code/modules/uplink/uplink_items/job.dm
index f912bc23cd5f..216d4cb5987d 100644
--- a/monkestation/code/modules/uplink/uplink_items/job.dm
+++ b/monkestation/code/modules/uplink/uplink_items/job.dm
@@ -11,13 +11,3 @@
/datum/uplink_item/role_restricted/modified_syringe_gun
surplus = 50
-
-/datum/uplink_item/role_restricted/hacked_linked_surgery
- name = "Syndicate Surgery Implant"
- desc = "A powerful brain implant, capable of uploading perfect, forbidden surgical knowledge to its users mind, \
- allowing them to do just about any surgery, anywhere, without making any (unintentional) mistakes. \
- Comes with a syndicate autosurgeon for immediate self-application."
- cost = 12
- item = /obj/item/autosurgeon/syndicate/hacked_linked_surgery
- restricted_roles = list(JOB_CHIEF_MEDICAL_OFFICER, JOB_MEDICAL_DOCTOR, JOB_PARAMEDIC, JOB_ROBOTICIST)
- surplus = 50
diff --git a/tgstation.dme b/tgstation.dme
index 1a20274810b6..b9cf0383be47 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1568,6 +1568,7 @@
#include "code\datums\status_effects\debuffs\confusion.dm"
#include "code\datums\status_effects\debuffs\debuffs.dm"
#include "code\datums\status_effects\debuffs\dizziness.dm"
+#include "code\datums\status_effects\debuffs\dna_transformation.dm"
#include "code\datums\status_effects\debuffs\drowsiness.dm"
#include "code\datums\status_effects\debuffs\drugginess.dm"
#include "code\datums\status_effects\debuffs\drunk.dm"