diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
index 6893a41517..1ea3f19c62 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
@@ -167,7 +167,7 @@
/area/ruin/unpowered/xenonest)
"aM" = (
/obj/structure/alien/weeds,
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"aQ" = (
@@ -260,7 +260,7 @@
/obj/structure/stone_tile/cracked{
dir = 1
},
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/indestructible/boss/air,
/area/ruin/unpowered/xenonest)
"be" = (
@@ -381,7 +381,7 @@
/obj/structure/stone_tile{
dir = 1
},
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/indestructible/boss/air,
/area/ruin/unpowered/xenonest)
"bs" = (
@@ -439,7 +439,7 @@
/obj/structure/stone_tile{
dir = 8
},
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/indestructible/boss/air,
/area/ruin/unpowered/xenonest)
"by" = (
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
index 945ea515c7..fec70b215e 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
@@ -279,6 +279,7 @@
},
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/seedvault)
+
(1,1,1) = {"
a
a
diff --git a/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm b/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
index c64050ce3a..e23beb3407 100644
--- a/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
+++ b/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
@@ -90,6 +90,9 @@
/obj/structure/table,
/obj/effect/decal/cleanable/dirt,
/obj/item/organ/cyberimp/chest/reviver,
+/obj/item/stack/sheet/mineral/gold{
+ amount = 3
+ },
/turf/open/floor/plasteel,
/area/ruin/powered)
"s" = (
@@ -145,9 +148,6 @@
"A" = (
/obj/structure/table,
/obj/effect/decal/cleanable/dirt,
-/obj/item/mmi/posibrain{
- pixel_y = 9
- },
/obj/item/mmi,
/turf/open/floor/plasteel,
/area/ruin/powered)
diff --git a/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm b/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm
index f1a3005ce1..9c273f4d75 100644
--- a/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm
+++ b/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm
@@ -1288,7 +1288,7 @@
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/derelictoutpost/cargobay)
"cV" = (
-/obj/effect/decal/cleanable/xenoblood/xsplatter,
+/obj/effect/decal/cleanable/blood/splatter/xeno,
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/derelictoutpost/cargobay)
"cW" = (
@@ -1525,7 +1525,7 @@
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/derelictoutpost/cargobay)
"dq" = (
-/obj/effect/decal/cleanable/xenoblood/xsplatter,
+/obj/effect/decal/cleanable/blood/splatter/xeno,
/obj/structure/alien/weeds{
color = "#4BAE56";
desc = "A thick gelatinous surface covers the floor. Someone get the golashes.";
diff --git a/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm b/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm
new file mode 100644
index 0000000000..a89d1422d2
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm
@@ -0,0 +1,970 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/open/space/basic,
+/area/template_noop)
+"b" = (
+/turf/open/floor/plating/asteroid/airless,
+/area/ruin/unpowered/no_grav)
+"c" = (
+/turf/closed/wall/r_wall/rust,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"d" = (
+/turf/closed/wall/r_wall,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"e" = (
+/obj/machinery/porta_turret/syndicate{
+ desc = "A ballistic machine gun auto-turret that fires bluespace bullets.";
+ lethal_projectile = /obj/item/projectile/magic/teleport;
+ name = "displacement turret";
+ stun_projectile = /obj/item/projectile/magic/teleport
+ },
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"f" = (
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"g" = (
+/obj/structure/table/glass,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"h" = (
+/obj/structure/table/glass,
+/obj/item/stack/sheet/bluespace_crystal{
+ amount = 37
+ },
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"i" = (
+/obj/structure/table/glass,
+/obj/item/bodybag/bluespace,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"j" = (
+/turf/open/floor/plasteel/stairs/left,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"k" = (
+/turf/open/floor/plasteel/stairs/medium,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"l" = (
+/turf/open/floor/plasteel/stairs/right,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"m" = (
+/obj/structure/table/glass,
+/obj/item/reagent_containers/syringe/bluespace,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"n" = (
+/obj/structure/table/glass,
+/obj/item/stock_parts/matter_bin/bluespace,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"o" = (
+/turf/open/floor/plasteel/vaporwave,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"p" = (
+/obj/structure/table/glass,
+/obj/item/stack/cable_coil/blue,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"q" = (
+/obj/structure/table/glass,
+/obj/item/storage/backpack/holding,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"r" = (
+/obj/structure/table/glass,
+/obj/item/reagent_containers/glass/beaker/bluespace,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"s" = (
+/obj/structure/table/glass,
+/obj/item/stock_parts/subspace/crystal,
+/obj/item/stock_parts/subspace/transmitter,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"t" = (
+/obj/structure/displaycase{
+ start_showpiece_type = /obj/item/hilbertshotel
+ },
+/turf/open/floor/plasteel/vaporwave,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"u" = (
+/obj/structure/table/glass,
+/obj/item/analyzer,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"v" = (
+/obj/structure/table/glass,
+/obj/item/stock_parts/subspace/amplifier,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"w" = (
+/obj/item/paper/crumpled/docslogs,
+/obj/item/pen,
+/turf/open/floor/plasteel/vaporwave,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"x" = (
+/obj/structure/table/glass,
+/obj/item/assembly/signaler,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"y" = (
+/obj/structure/table/glass,
+/obj/item/slimecross/industrial/bluespace,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"z" = (
+/obj/machinery/door/airlock/vault{
+ name = "secured door";
+ req_access = 207
+ },
+/obj/effect/mapping_helpers/airlock/locked,
+/turf/open/floor/plasteel/grimy{
+ icon_state = "engine"
+ },
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"A" = (
+/obj/structure/filingcabinet,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"B" = (
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"C" = (
+/obj/structure/table/reinforced,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"D" = (
+/obj/item/twohanded/required/kirbyplants/random,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"E" = (
+/obj/structure/chair/office,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"F" = (
+/obj/machinery/door/window/eastleft,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"G" = (
+/obj/structure/table/reinforced,
+/obj/item/pen,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"H" = (
+/obj/structure/table/reinforced,
+/obj/item/paper/crumpled/robertsworkjournal,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"I" = (
+/obj/machinery/door/airlock/highsecurity{
+ req_access = 207
+ },
+/obj/effect/mapping_helpers/airlock/locked,
+/turf/open/floor/plasteel/grimy,
+/area/ruin/space/has_grav/hilbertresearchfacility)
+"J" = (
+/turf/closed/mineral/random,
+/area/ruin/unpowered/no_grav)
+"K" = (
+/turf/open/floor/plasteel/stairs/right{
+ initial_gas_mix = "TEMP=2.7"
+ },
+/area/ruin/unpowered/no_grav)
+"U" = (
+/turf/open/floor/plasteel/stairs/medium{
+ initial_gas_mix = "TEMP=2.7"
+ },
+/area/ruin/unpowered/no_grav)
+"X" = (
+/turf/open/floor/plasteel/stairs/left{
+ initial_gas_mix = "TEMP=2.7"
+ },
+/area/ruin/unpowered/no_grav)
+
+(1,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(2,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+b
+b
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(3,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+b
+J
+J
+J
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(4,1,1) = {"
+a
+a
+a
+J
+b
+J
+b
+b
+a
+b
+J
+b
+b
+b
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(5,1,1) = {"
+a
+a
+b
+J
+J
+J
+b
+J
+b
+J
+b
+b
+J
+J
+J
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(6,1,1) = {"
+a
+a
+b
+c
+c
+c
+c
+c
+d
+d
+c
+d
+d
+c
+d
+d
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(7,1,1) = {"
+a
+a
+b
+d
+e
+f
+f
+m
+r
+g
+g
+f
+f
+f
+e
+c
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(8,1,1) = {"
+a
+a
+b
+d
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+d
+J
+b
+b
+b
+b
+b
+a
+a
+a
+a
+"}
+(9,1,1) = {"
+a
+a
+J
+d
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+c
+J
+b
+b
+J
+b
+b
+b
+a
+a
+a
+"}
+(10,1,1) = {"
+a
+a
+J
+c
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+c
+J
+b
+J
+b
+b
+J
+b
+a
+a
+a
+"}
+(11,1,1) = {"
+a
+a
+J
+c
+g
+f
+f
+n
+s
+v
+f
+f
+f
+f
+f
+c
+J
+J
+J
+J
+J
+J
+b
+a
+a
+a
+"}
+(12,1,1) = {"
+a
+a
+J
+c
+g
+f
+j
+o
+o
+o
+j
+f
+f
+f
+c
+d
+d
+c
+c
+d
+c
+J
+b
+a
+a
+a
+"}
+(13,1,1) = {"
+a
+a
+J
+c
+h
+f
+k
+o
+t
+o
+k
+f
+f
+f
+c
+A
+B
+C
+B
+D
+c
+J
+J
+a
+a
+a
+"}
+(14,1,1) = {"
+a
+a
+J
+c
+g
+f
+l
+o
+o
+w
+l
+f
+f
+f
+d
+B
+B
+G
+B
+B
+c
+J
+b
+b
+a
+a
+"}
+(15,1,1) = {"
+a
+a
+J
+c
+i
+f
+f
+p
+u
+x
+f
+f
+f
+f
+d
+B
+E
+H
+B
+B
+c
+J
+J
+J
+a
+a
+"}
+(16,1,1) = {"
+a
+b
+J
+c
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+c
+B
+B
+C
+B
+B
+c
+b
+J
+b
+a
+a
+"}
+(17,1,1) = {"
+a
+b
+J
+d
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+c
+C
+F
+C
+B
+B
+c
+b
+b
+b
+a
+a
+"}
+(18,1,1) = {"
+a
+b
+J
+d
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+d
+B
+B
+B
+B
+B
+d
+b
+b
+b
+b
+a
+"}
+(19,1,1) = {"
+a
+b
+J
+d
+f
+f
+f
+f
+f
+f
+f
+f
+f
+f
+z
+B
+B
+B
+B
+B
+d
+b
+b
+b
+b
+a
+"}
+(20,1,1) = {"
+a
+a
+b
+c
+e
+f
+g
+q
+g
+y
+g
+f
+e
+f
+c
+B
+B
+B
+B
+B
+d
+b
+b
+b
+b
+a
+"}
+(21,1,1) = {"
+a
+a
+b
+c
+c
+c
+c
+c
+c
+d
+d
+c
+c
+c
+d
+B
+B
+B
+B
+B
+d
+X
+b
+b
+b
+a
+"}
+(22,1,1) = {"
+a
+a
+b
+b
+J
+J
+b
+b
+J
+J
+J
+J
+J
+J
+d
+D
+B
+B
+B
+B
+I
+U
+b
+b
+b
+a
+"}
+(23,1,1) = {"
+a
+a
+a
+b
+b
+J
+J
+b
+b
+b
+b
+J
+b
+J
+c
+d
+d
+c
+d
+c
+d
+K
+b
+b
+b
+a
+"}
+(24,1,1) = {"
+a
+a
+a
+a
+b
+b
+J
+J
+J
+b
+b
+b
+b
+J
+b
+b
+J
+J
+J
+J
+b
+b
+b
+b
+b
+a
+"}
+(25,1,1) = {"
+a
+a
+a
+a
+a
+b
+b
+b
+J
+J
+J
+J
+b
+b
+b
+b
+b
+b
+a
+J
+J
+J
+b
+J
+b
+a
+"}
+(26,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+b
+b
+b
+a
+b
+b
+b
+b
+b
+a
+a
+a
+J
+J
+J
+J
+J
+a
+"}
+(27,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
diff --git a/_maps/RandomZLevels/Academy.dmm b/_maps/RandomZLevels/Academy.dmm
index 29bd7d0526..2f08d9a29e 100644
--- a/_maps/RandomZLevels/Academy.dmm
+++ b/_maps/RandomZLevels/Academy.dmm
@@ -3830,7 +3830,7 @@
/turf/open/floor/engine/cult,
/area/awaymission/academy/academycellar)
"kY" = (
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/floor/engine/cult,
/area/awaymission/academy/academycellar)
"kZ" = (
diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm
index a25808d933..d50480c381 100644
--- a/_maps/RandomZLevels/caves.dmm
+++ b/_maps/RandomZLevels/caves.dmm
@@ -873,7 +873,7 @@
/obj/structure/window/reinforced{
dir = 4
},
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/floor/plating{
initial_gas_mix = "n2=23;o2=14"
},
@@ -945,7 +945,7 @@
/area/awaymission/caves/research)
"cN" = (
/obj/machinery/door/window/eastleft,
-/obj/effect/decal/cleanable/xenoblood/xgibs,
+/obj/effect/decal/cleanable/blood/gibs/xeno,
/turf/open/floor/plating{
initial_gas_mix = "n2=23;o2=14"
},
@@ -1015,7 +1015,7 @@
},
/area/awaymission/caves/BMP_asteroid/level_two)
"cV" = (
-/obj/effect/decal/cleanable/xenoblood/xgibs,
+/obj/effect/decal/cleanable/blood/gibs/xeno,
/turf/open/floor/plating{
initial_gas_mix = "n2=23;o2=14"
},
diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm
index 7edc7b4518..c251a338a5 100644
--- a/_maps/RandomZLevels/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/moonoutpost19.dmm
@@ -5597,8 +5597,8 @@
},
/area/awaymission/moonoutpost19/arrivals)
"kK" = (
-/obj/effect/decal/cleanable/xenoblood,
-/obj/effect/decal/cleanable/xenoblood/xgibs,
+/obj/effect/decal/cleanable/blood/xeno,
+/obj/effect/decal/cleanable/blood/gibs/xeno,
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
dir = 1
@@ -5608,7 +5608,7 @@
},
/area/awaymission/moonoutpost19/arrivals)
"kL" = (
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/obj/effect/decal/remains/xeno{
desc = "They look like the remains of something... alien. The front of skull appears to have been completely obliterated."
},
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 9c944ee1b7..125da46b81 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -34753,12 +34753,7 @@
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
"bCO" = (
-/obj/structure/table,
-/obj/item/storage/box/bodybags{
- pixel_x = 3;
- pixel_y = 3
- },
-/obj/item/storage/box/rxglasses,
+/obj/machinery/bloodbankgen,
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
"bCP" = (
@@ -36538,6 +36533,11 @@
"bGR" = (
/obj/structure/table,
/obj/item/hand_labeler,
+/obj/item/storage/box/rxglasses,
+/obj/item/storage/box/bodybags{
+ pixel_x = 3;
+ pixel_y = 3
+ },
/obj/item/gun/syringe,
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index aed08f5d8d..79b7561ebb 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -89232,7 +89232,7 @@
/area/maintenance/port)
"cTz" = (
/obj/effect/decal/remains/xeno,
-/obj/effect/decal/cleanable/xenoblood,
+/obj/effect/decal/cleanable/blood/xeno,
/turf/open/floor/circuit/green,
/area/science/xenobiology)
"cTA" = (
@@ -93013,10 +93013,10 @@
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"cZK" = (
-/obj/item/twohanded/required/kirbyplants/random,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/machinery/bloodbankgen,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"cZL" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 43c8b1155b..522d9801ca 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -56605,11 +56605,6 @@
/turf/open/floor/plasteel/dark,
/area/medical/sleeper)
"cfK" = (
-/obj/structure/table,
-/obj/item/paper_bin{
- pixel_x = -2;
- pixel_y = 4
- },
/obj/machinery/light_switch{
pixel_x = 11;
pixel_y = 23
@@ -56624,6 +56619,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/bloodbankgen,
/turf/open/floor/plasteel/dark,
/area/medical/sleeper)
"cfL" = (
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 24a5cd834a..a87c17836c 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -30073,10 +30073,8 @@
/turf/open/floor/plasteel/white,
/area/medical/medbay/zone3)
"bbs" = (
-/obj/item/twohanded/required/kirbyplants{
- icon_state = "plant-21"
- },
/obj/effect/turf_decal/tile/blue,
+/obj/machinery/bloodbankgen,
/turf/open/floor/plasteel/white,
/area/medical/medbay/zone3)
"bbt" = (
@@ -43077,7 +43075,7 @@
/turf/open/floor/plasteel,
/area/engine/atmos)
"vsf" = (
-/obj/effect/decal/cleanable/xenoblood/xgibs,
+/obj/effect/decal/cleanable/blood/gibs/xeno,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index e900a4597c..698eb6cd5a 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -31871,14 +31871,11 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/item/twohanded/required/kirbyplants{
- icon_state = "plant-21";
- pixel_y = 3
- },
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/bloodbankgen,
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
"bwG" = (
diff --git a/_maps/templates/hilbertshotel.dmm b/_maps/templates/hilbertshotel.dmm
new file mode 100644
index 0000000000..4e4d8f8267
--- /dev/null
+++ b/_maps/templates/hilbertshotel.dmm
@@ -0,0 +1,545 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/open/space/bluespace,
+/area/hilbertshotel)
+"b" = (
+/turf/closed/indestructible/hotelwall,
+/area/hilbertshotel)
+"c" = (
+/obj/machinery/jukebox{
+ req_access = null
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"d" = (
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"e" = (
+/obj/structure/table/wood,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"f" = (
+/obj/structure/table/wood,
+/obj/structure/showcase/machinery/tv,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"g" = (
+/obj/structure/dresser,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"h" = (
+/obj/structure/table/wood/fancy,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"i" = (
+/obj/structure/table/wood/fancy,
+/obj/structure/mirror{
+ pixel_y = 24
+ },
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"j" = (
+/obj/structure/table/wood/fancy,
+/obj/item/flashlight/lamp/green,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"k" = (
+/obj/structure/chair/comfy/brown{
+ dir = 4
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"l" = (
+/obj/structure/table/wood/poker,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"m" = (
+/obj/structure/chair/comfy/brown{
+ dir = 8
+ },
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"n" = (
+/obj/effect/landmark/xmastree,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"o" = (
+/obj/structure/chair/comfy/brown{
+ dir = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"p" = (
+/obj/structure/mineral_door/wood,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"q" = (
+/obj/structure/bed,
+/obj/item/bedsheet/random,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"r" = (
+/obj/structure/closet/cabinet{
+ anchored = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"s" = (
+/obj/structure/table/wood/fancy,
+/obj/item/reagent_containers/food/snacks/grown/poppy,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"t" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"u" = (
+/obj/structure/mineral_door/paperframe,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"v" = (
+/obj/structure/extinguisher_cabinet{
+ pixel_x = 32
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"w" = (
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"x" = (
+/obj/structure/curtain,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"y" = (
+/obj/machinery/door/window/northleft,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"z" = (
+/obj/structure/table/reinforced,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"A" = (
+/obj/structure/mirror{
+ pixel_x = -32
+ },
+/obj/structure/sink{
+ dir = 8;
+ pixel_x = -12;
+ pixel_y = 2
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"B" = (
+/obj/structure/chair/stool/bar,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"C" = (
+/obj/machinery/shower{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"D" = (
+/obj/machinery/light_switch{
+ pixel_x = 32
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"E" = (
+/obj/structure/table/reinforced,
+/obj/item/soap/deluxe,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"F" = (
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/obj/structure/window/reinforced/tinted{
+ dir = 1
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"G" = (
+/obj/machinery/light_switch{
+ pixel_x = -32
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"H" = (
+/obj/structure/table/reinforced,
+/obj/machinery/microwave,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"I" = (
+/turf/closed/indestructible/hoteldoor,
+/area/hilbertshotel)
+"J" = (
+/obj/machinery/light/small,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"K" = (
+/obj/structure/closet/crate/bin,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"L" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"M" = (
+/obj/structure/table/reinforced,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"N" = (
+/obj/structure/table/reinforced,
+/obj/item/soap/deluxe,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"O" = (
+/obj/item/bikehorn/rubberducky,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"P" = (
+/obj/machinery/light/small,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"Q" = (
+/obj/machinery/smartfridge/food,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"R" = (
+/obj/structure/toilet{
+ dir = 8
+ },
+/obj/structure/window/reinforced/tinted{
+ dir = 1
+ },
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"S" = (
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"T" = (
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/obj/structure/window/reinforced/tinted,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"U" = (
+/obj/structure/table/reinforced,
+/obj/structure/sink/kitchen,
+/obj/machinery/light/small,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"V" = (
+/obj/structure/table/reinforced,
+/obj/effect/spawner/lootdrop/three_course_meal,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+
+(1,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(2,1,1) = {"
+a
+b
+b
+b
+b
+b
+I
+b
+b
+b
+b
+b
+b
+b
+a
+"}
+(3,1,1) = {"
+a
+b
+d
+d
+k
+d
+d
+t
+d
+y
+t
+H
+z
+b
+a
+"}
+(4,1,1) = {"
+a
+b
+e
+d
+l
+o
+d
+d
+B
+z
+d
+d
+z
+b
+a
+"}
+(5,1,1) = {"
+a
+b
+f
+d
+l
+o
+d
+d
+B
+V
+d
+d
+U
+b
+a
+"}
+(6,1,1) = {"
+a
+b
+e
+d
+l
+o
+d
+d
+B
+z
+d
+d
+z
+b
+a
+"}
+(7,1,1) = {"
+a
+b
+c
+d
+m
+d
+D
+K
+v
+z
+M
+Q
+z
+b
+a
+"}
+(8,1,1) = {"
+a
+b
+b
+b
+b
+p
+b
+b
+b
+b
+b
+b
+b
+b
+a
+"}
+(9,1,1) = {"
+a
+b
+g
+d
+t
+d
+G
+u
+w
+A
+N
+A
+E
+b
+a
+"}
+(10,1,1) = {"
+a
+b
+h
+d
+d
+d
+d
+b
+w
+w
+w
+w
+w
+b
+a
+"}
+(11,1,1) = {"
+a
+b
+i
+d
+n
+d
+J
+b
+L
+w
+R
+w
+P
+b
+a
+"}
+(12,1,1) = {"
+a
+b
+h
+d
+d
+d
+r
+b
+x
+F
+S
+T
+x
+b
+a
+"}
+(13,1,1) = {"
+a
+b
+d
+d
+d
+d
+d
+b
+w
+w
+w
+w
+w
+b
+a
+"}
+(14,1,1) = {"
+a
+b
+d
+j
+q
+q
+s
+b
+w
+C
+O
+C
+w
+b
+a
+"}
+(15,1,1) = {"
+a
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+a
+"}
+(16,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
diff --git a/_maps/templates/hilbertshotelempty.dmm b/_maps/templates/hilbertshotelempty.dmm
new file mode 100644
index 0000000000..a0482c93ba
--- /dev/null
+++ b/_maps/templates/hilbertshotelempty.dmm
@@ -0,0 +1,289 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/open/space/bluespace,
+/area/hilbertshotel)
+"b" = (
+/turf/closed/indestructible/hotelwall,
+/area/hilbertshotel)
+"c" = (
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"d" = (
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"e" = (
+/turf/closed/indestructible/hoteldoor,
+/area/hilbertshotel)
+
+(1,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(2,1,1) = {"
+a
+b
+b
+b
+b
+b
+e
+b
+b
+b
+b
+b
+b
+b
+a
+"}
+(3,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+b
+a
+"}
+(4,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+b
+a
+"}
+(5,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+b
+a
+"}
+(6,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+b
+a
+"}
+(7,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+b
+a
+"}
+(8,1,1) = {"
+a
+b
+b
+b
+b
+c
+b
+b
+b
+b
+b
+b
+b
+b
+a
+"}
+(9,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+c
+d
+d
+d
+d
+d
+b
+a
+"}
+(10,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+b
+d
+d
+d
+d
+d
+b
+a
+"}
+(11,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+b
+d
+d
+d
+d
+d
+b
+a
+"}
+(12,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+b
+d
+d
+d
+d
+d
+b
+a
+"}
+(13,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+b
+d
+d
+d
+d
+d
+b
+a
+"}
+(14,1,1) = {"
+a
+b
+c
+c
+c
+c
+c
+b
+d
+d
+d
+d
+d
+b
+a
+"}
+(15,1,1) = {"
+a
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+b
+a
+"}
+(16,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
diff --git a/_maps/templates/hilbertshotellore.dmm b/_maps/templates/hilbertshotellore.dmm
new file mode 100644
index 0000000000..f6be66bd06
--- /dev/null
+++ b/_maps/templates/hilbertshotellore.dmm
@@ -0,0 +1,639 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aa" = (
+/turf/open/space/bluespace,
+/area/hilbertshotel)
+"ab" = (
+/turf/closed/indestructible/hotelwall,
+/area/hilbertshotel)
+"ac" = (
+/obj/structure/table/wood/fancy,
+/obj/structure/mirror{
+ broken = 1;
+ desc = "Oh no, seven years of bad luck!";
+ icon_state = "mirror_broke";
+ pixel_y = 24
+ },
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ad" = (
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ae" = (
+/obj/structure/table/wood,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"af" = (
+/obj/structure/table/wood,
+/obj/structure/showcase/machinery/tv,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ag" = (
+/obj/structure/dresser,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ah" = (
+/obj/structure/table/wood/fancy,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ai" = (
+/obj/structure/table/wood/poker,
+/obj/item/toy/cards/deck,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aj" = (
+/obj/structure/table/wood/fancy,
+/obj/item/flashlight/lamp/green,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ak" = (
+/obj/structure/chair/comfy/brown{
+ dir = 4
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"al" = (
+/obj/structure/table/wood/poker,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"am" = (
+/obj/structure/chair/comfy/brown{
+ dir = 8
+ },
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"an" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ap" = (
+/obj/structure/bed,
+/obj/item/bedsheet/random,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aq" = (
+/obj/structure/chair/comfy/brown{
+ dir = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ar" = (
+/obj/structure/mineral_door/wood,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"as" = (
+/turf/closed/indestructible/hoteldoor,
+/area/hilbertshotel)
+"at" = (
+/obj/effect/decal/cleanable/cobweb,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"au" = (
+/obj/machinery/light_switch{
+ pixel_x = -32
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"av" = (
+/obj/machinery/light/small,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aw" = (
+/obj/structure/closet/cabinet{
+ anchored = 1
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ax" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/cobweb/cobweb2,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"ay" = (
+/obj/structure/closet/crate/bin,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"az" = (
+/obj/structure/mineral_door/paperframe,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aA" = (
+/obj/structure/chair/stool/bar,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aB" = (
+/obj/structure/extinguisher_cabinet{
+ pixel_x = 32
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aC" = (
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aD" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aE" = (
+/obj/structure/curtain,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aF" = (
+/obj/machinery/door/window/northleft,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aG" = (
+/obj/structure/table/reinforced,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aH" = (
+/obj/structure/table/reinforced,
+/obj/item/pen,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aI" = (
+/obj/structure/mirror{
+ pixel_x = -32
+ },
+/obj/structure/sink{
+ dir = 8;
+ pixel_x = -12;
+ pixel_y = 2
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aJ" = (
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/obj/structure/window/reinforced/tinted{
+ dir = 1
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aK" = (
+/obj/machinery/shower{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aL" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aM" = (
+/obj/structure/table/wood/poker,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aN" = (
+/obj/structure/toilet{
+ dir = 8
+ },
+/obj/structure/window/reinforced/tinted{
+ dir = 1
+ },
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aO" = (
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aP" = (
+/obj/item/bikehorn/rubberducky,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aQ" = (
+/obj/structure/table/reinforced,
+/obj/machinery/microwave,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aR" = (
+/obj/machinery/smartfridge/food,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aS" = (
+/obj/structure/window/reinforced/tinted{
+ dir = 8
+ },
+/obj/structure/window/reinforced/tinted,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aT" = (
+/obj/structure/table/reinforced,
+/obj/structure/sink/kitchen,
+/obj/machinery/light/small,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aU" = (
+/obj/structure/bed,
+/obj/item/bedsheet/random,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aV" = (
+/obj/machinery/light/small,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"aW" = (
+/obj/machinery/jukebox{
+ req_access = null
+ },
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aX" = (
+/obj/machinery/light_switch{
+ pixel_x = 32
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aY" = (
+/obj/structure/chair/stool/bar,
+/obj/effect/decal/cleanable/blood,
+/obj/effect/decal/cleanable/vomit,
+/obj/effect/mob_spawn/human/doctorhilbert,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"aZ" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"ba" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/cobweb/cobweb2,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"bb" = (
+/obj/structure/mirror{
+ pixel_x = -32
+ },
+/obj/structure/sink{
+ dir = 8;
+ pixel_x = -12;
+ pixel_y = 2
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"bc" = (
+/obj/effect/decal/cleanable/blood,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"bd" = (
+/obj/machinery/shower{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"be" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"bf" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"bg" = (
+/obj/structure/table/reinforced,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"bh" = (
+/obj/structure/table/reinforced,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/obj/item/soap/homemade{
+ name = "used soap"
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"bi" = (
+/obj/effect/decal/cleanable/vomit,
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"bj" = (
+/obj/structure/table/reinforced,
+/obj/item/soap/homemade{
+ name = "used soap"
+ },
+/turf/open/indestructible/hoteltile,
+/area/hilbertshotel)
+"bk" = (
+/obj/structure/table/reinforced,
+/obj/item/analyzer/hilbertsanalyzer,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+"bl" = (
+/obj/structure/table/reinforced,
+/obj/item/paper/crumpled/bloody/docsdeathnote,
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotel)
+
+(1,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(2,1,1) = {"
+aa
+ab
+ab
+ab
+ab
+ab
+as
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(3,1,1) = {"
+aa
+ab
+at
+aL
+ak
+ad
+aL
+an
+ad
+aF
+be
+aQ
+aG
+ab
+aa
+"}
+(4,1,1) = {"
+aa
+ab
+ae
+ad
+al
+aq
+ad
+ad
+aA
+aH
+ad
+aL
+aG
+ab
+aa
+"}
+(5,1,1) = {"
+aa
+ab
+af
+ad
+ai
+aq
+aL
+ad
+aY
+bl
+ad
+aL
+aT
+ab
+aa
+"}
+(6,1,1) = {"
+aa
+ab
+ae
+ad
+aM
+aq
+ad
+ad
+aA
+bk
+bf
+bf
+aG
+ab
+aa
+"}
+(7,1,1) = {"
+aa
+ab
+aW
+aL
+am
+ad
+aX
+ay
+aB
+aG
+bg
+aR
+aG
+ab
+aa
+"}
+(8,1,1) = {"
+aa
+ab
+ab
+ab
+ab
+ar
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(9,1,1) = {"
+aa
+ab
+ag
+ad
+an
+ad
+au
+az
+aC
+bb
+bh
+aI
+bj
+ab
+aa
+"}
+(10,1,1) = {"
+aa
+ab
+ah
+ad
+aL
+aL
+ad
+ab
+aZ
+aZ
+aC
+aZ
+aZ
+ab
+aa
+"}
+(11,1,1) = {"
+aa
+ab
+ac
+ad
+ad
+aL
+av
+ab
+aD
+aC
+aN
+bi
+aV
+ab
+aa
+"}
+(12,1,1) = {"
+aa
+ab
+ah
+ad
+aL
+ad
+aw
+ab
+aE
+aJ
+aO
+aS
+aE
+ab
+aa
+"}
+(13,1,1) = {"
+aa
+ab
+ad
+ad
+aL
+ad
+ad
+ab
+aC
+bc
+aZ
+aZ
+aC
+ab
+aa
+"}
+(14,1,1) = {"
+aa
+ab
+ax
+aj
+ap
+aU
+ah
+ab
+ba
+bd
+aP
+aK
+aC
+ab
+aa
+"}
+(15,1,1) = {"
+aa
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+"}
+(16,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
diff --git a/_maps/templates/hilbertshotelstorage.dmm b/_maps/templates/hilbertshotelstorage.dmm
new file mode 100644
index 0000000000..756e2e5155
--- /dev/null
+++ b/_maps/templates/hilbertshotelstorage.dmm
@@ -0,0 +1,23 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/closed/indestructible/hotelwall,
+/area/hilbertshotelstorage)
+"b" = (
+/turf/open/indestructible/hotelwood,
+/area/hilbertshotelstorage)
+
+(1,1,1) = {"
+a
+a
+a
+"}
+(2,1,1) = {"
+a
+b
+a
+"}
+(3,1,1) = {"
+a
+a
+a
+"}
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index d966c73d23..3301def4a1 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -93,12 +93,6 @@
#define isgenital(A) (istype(A, /obj/item/organ/genital))
#define isborer(A) (istype(A, /mob/living/simple_animal/borer))
-#define isipcperson(A) (is_species(A, /datum/species/ipc))
-#define ismammal(A) (is_species(A, /datum/species/mammal))
-#define isavian(A) (is_species(A, /datum/species/avian))
-#define isaquatic(A) (is_species(A, /datum/species/aquatic))
-#define isinsect(A) (is_species(A, /datum/species/insect))
-#define isxenoperson(A) (is_species(A, /datum/species/xeno))
#define CITADEL_MENTOR_OOC_COLOUR "#224724"
diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm
index c4db590e90..6049fd7918 100644
--- a/code/__DEFINES/cleaning.dm
+++ b/code/__DEFINES/cleaning.dm
@@ -5,8 +5,3 @@
#define CLEAN_STRONG 4 // Industrial strength
#define CLEAN_IMPRESSIVE 5 // Cleaning strong enough your granny would be proud
#define CLEAN_GOD 6 // Cleans things spotless down to the atomic structure
-
-//How strong things have to be to wipe forensic evidence...
-#define CLEAN_STRENGTH_FINGERPRINTS CLEAN_IMPRESSIVE
-#define CLEAN_STRENGTH_BLOOD CLEAN_WEAK
-#define CLEAN_STRENGTH_FIBERS CLEAN_IMPRESSIVE
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index 06eb2ff04f..34524bbe6d 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -2,11 +2,8 @@
#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) )
-//shorthand
-#define GET_COMPONENT_FROM(varname, path, target) var##path/##varname = ##target.GetComponent(##path)
-#define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src)
-
#define COMPONENT_INCOMPATIBLE 1
+#define COMPONENT_NOTRANSFER 2
// How multiple components of the exact same type are handled in the same datum
@@ -225,9 +222,14 @@
#define COMSIG_TURF_MAKE_DRY "make_turf_try" //(max_strength, immediate, duration_decrease = INFINITY): Returns bool.
#define COMSIG_COMPONENT_CLEAN_ACT "clean_act" //called on an object to clean it of cleanables. Usualy with soap: (num/strength)
+//Blood color
+#define COMSIG_BLOOD_COLOR "blood_DNA_to_color" //RGB blood stuff
//Food
#define COMSIG_FOOD_EATEN "food_eaten" //from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder)
+//Gibs
+#define COMSIG_GIBS_STREAK "gibs_streak" // from base of /obj/effect/decal/cleanable/blood/gibs/streak(): (list/directions, list/diseases)
+
//Mood
#define COMSIG_ADD_MOOD_EVENT "add_mood" //Called when you send a mood event from anywhere in the code.
#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" //Called when you clear a mood event from anywhere in the code.
diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm
index ef96b83cc8..16d763606b 100644
--- a/code/__DEFINES/footsteps.dm
+++ b/code/__DEFINES/footsteps.dm
@@ -15,6 +15,15 @@
//misc footstep sounds
#define FOOTSTEP_GENERIC_HEAVY "heavy"
+#define FOOTPRINT_SHOE "shoe"
+#define FOOTPRINT_FOOT "foot"
+#define FOOTPRINT_PAW "paw"
+#define FOOTPRINT_CLAW "claw"
+#define FOOTPRINT_WHEEL "wheels"
+#define FOOTPRINT_TRAIL "trails_"
+#define FOOTPRINT_SNAKE "snake"
+#define FOOTPRINT_DRAG "drag"
+
/*
id = list(
diff --git a/code/__DEFINES/forensics.dm b/code/__DEFINES/forensics.dm
deleted file mode 100644
index bb512edcde..0000000000
--- a/code/__DEFINES/forensics.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-#define IF_HAS_BLOOD_DNA(__thing) GET_COMPONENT_FROM(__FR##__thing, /datum/component/forensics, __thing); if(__FR##__thing && length(__FR##__thing.blood_DNA))
-#define IF_HAS_BLOOD_DNA_AND(__thing, __conditions...) GET_COMPONENT_FROM(__FR##__thing, /datum/component/forensics, __thing); if(__FR##__thing && length(__FR##__thing.blood_DNA) && (##__conditions))
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 1709714904..9f69da0154 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -61,6 +61,15 @@
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
+// Citadel specific species
+#define isipcperson(A) (is_species(A, /datum/species/ipc))
+#define ismammal(A) (is_species(A, /datum/species/mammal))
+#define isavian(A) (is_species(A, /datum/species/avian))
+#define isaquatic(A) (is_species(A, /datum/species/aquatic))
+#define isinsect(A) (is_species(A, /datum/species/insect))
+#define isxenoperson(A) (is_species(A, /datum/species/xeno))
+#define isstartjelly(A) (is_species(A, /datum/species/jelly/roundstartslime))
+
//more carbon mobs
#define ismonkey(A) (istype(A, /mob/living/carbon/monkey))
@@ -176,6 +185,8 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list(
#define iscameramob(A) (istype(A, /mob/camera))
+#define isaicamera(A) (istype(A, /mob/camera/aiEye))
+
#define iseminence(A) (istype(A, /mob/camera/eminence))
//Footstep helpers
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index bccf1f28dd..94a189ff07 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -171,12 +171,22 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
#define BLOOD_LOSS_IN_SPREAD 20
//Bloody shoe blood states
-#define BLOOD_STATE_HUMAN "blood"
-#define BLOOD_STATE_XENO "xeno"
+#define BLOOD_STATE_BLOOD "blood"
#define BLOOD_STATE_OIL "oil"
#define BLOOD_STATE_NOT_BLOODY "no blood whatsoever"
#define BLOOD_AMOUNT_PER_DECAL 20
+//Blood Decal Colors
+#define BLOOD_COLOR_HUMAN "#dc0000"
+#define BLOOD_COLOR_XENO "#94a83c"
+#define BLOOD_COLOR_OIL "#301d02"
+#define BLOOD_COLOR_SYNTHETIC "#3f48aa"
+#define BLOOD_COLOR_SLIME "#00ff90"
+#define BLOOD_COLOR_LIZARD "#db004D"
+#define BLOOD_COLOR_UNIVERSAL "#db3300"
+#define BLOOD_COLOR_BUG "#a37c0f"
+
+
//suit sensors: sensor_mode defines
#define SENSOR_OFF 0
diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm
index e655408db1..af06a5a2d0 100644
--- a/code/__DEFINES/say.dm
+++ b/code/__DEFINES/say.dm
@@ -23,6 +23,8 @@
#define MODE_WHISPER "whisper"
#define MODE_WHISPER_CRIT "whispercrit"
+#define MODE_CUSTOM_SAY "custom_say"
+
#define MODE_DEPARTMENT "department"
#define MODE_KEY_DEPARTMENT "h"
#define MODE_TOKEN_DEPARTMENT ":h"
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 3c8d62ce3a..ce294f3749 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -756,7 +756,6 @@ Turf and target are separate in case you want to teleport some distance from a t
loc = loc.loc
return null
-
//For objects that should embed, but make no sense being is_sharp or is_pointed()
//e.g: rods
GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
@@ -1550,3 +1549,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
for(var/i in L)
if(condition.Invoke(i))
. |= i
+
+/proc/CallAsync(datum/source, proctype, list/arguments)
+ set waitfor = FALSE
+ return call(source, proctype)(arglist(arguments))
\ No newline at end of file
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index c883254afe..8b5657a6f6 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -58,3 +58,64 @@ GLOBAL_LIST_EMPTY(latejoiners) //CIT CHANGE - All latejoining people, for traito
for(var/i in GLOB.mob_list)
var/mob/M = i
M.update_config_movespeed()
+
+GLOBAL_LIST_INIT(noodle_taurs, list(
+ "Naga",
+ "Tentacle"
+ ))
+
+GLOBAL_LIST_INIT(paw_taurs, list(
+ "Fox",
+ "Wolf",
+ "Otie",
+ "Drake",
+ "Lab",
+ "Shepherd",
+ "Husky",
+ "Eevee",
+ "Panther",
+ "Horse",
+ "Cow",
+ "Tiger"
+ ))
+
+ //blood types
+GLOBAL_LIST_INIT(regular_bloods,list(
+ "O-",
+ "O+",
+ "A-",
+ "A+",
+ "B-",
+ "B+",
+ "AB-",
+ "AB+"
+ ))
+
+GLOBAL_LIST_INIT(all_types_bloods,list(
+ "O-",
+ "O+",
+ "A-",
+ "A+",
+ "B-",
+ "B+",
+ "AB-",
+ "AB+",
+ "SY",
+ "X*",
+ "HF",
+ "L",
+ "U",
+ "GEL",
+ "BUG"
+ ))
+
+GLOBAL_LIST_INIT(blood_types, list(
+ "blood",
+ "jellyblood"
+ ))
+
+GLOBAL_LIST_INIT(blood_id_types, list(
+ "blood" = /datum/reagent/blood,
+ "jellyblood" = /datum/reagent/blood/jellyblood
+ ))
+
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 6455b4ccb6..e47797f4d6 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -40,7 +40,7 @@
return TRUE
user.changeNext_move(CLICK_CD_MELEE)
if(user.a_intent == INTENT_HARM && stat == DEAD && (butcher_results || guaranteed_butcher_results)) //can we butcher it?
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, I)
+ var/datum/component/butchering/butchering = I.GetComponent(/datum/component/butchering)
if(butchering && butchering.butchering_enabled)
to_chat(user, "You begin to butcher [src]...")
playsound(loc, butchering.butcher_sound, 50, TRUE, -1)
diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm
index 3ac103affc..4406655375 100644
--- a/code/controllers/configuration/config_entry.dm
+++ b/code/controllers/configuration/config_entry.dm
@@ -1,6 +1,7 @@
#define VALUE_MODE_NUM 0
#define VALUE_MODE_TEXT 1
#define VALUE_MODE_FLAG 2
+#define VALUE_MODE_NUM_LIST 3
#define KEY_MODE_TEXT 0
#define KEY_MODE_TYPE 1
@@ -191,6 +192,18 @@
if(VALUE_MODE_TEXT)
new_value = key_value
continue_check_value = new_value
+ if(VALUE_MODE_NUM_LIST)
+ // this is all copy+pasted from number list up there, but it's super basic so I don't see it being changed soon
+ var/list/new_list = list()
+ var/list/values = splittext(key_value," ")
+ for(var/I in values)
+ var/temp = text2num(I)
+ if(isnull(temp))
+ log_admin("invalid number list entry in [key_name]: [I]")
+ continue_check_value = FALSE
+ new_list += temp
+ new_value = new_list
+ continue_check_value = new_list.len
if(continue_check_value && continue_check_key && ValidateListEntry(new_key, new_value))
config_entry_value[new_key] = new_value
return TRUE
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index cf0caebb61..fb974c85bc 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -367,3 +367,27 @@
/datum/config_entry/number/auto_transfer_delay
config_entry_value = 72000
min_val = 0
+
+/datum/config_entry/number/dynamic_high_pop_limit
+ config_entry_value = 55
+ min_val = 1
+
+/datum/config_entry/number/dynamic_pop_per_requirement
+ config_entry_value = 6
+ min_val = 1
+
+/datum/config_entry/keyed_list/dynamic_cost
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/dynamic_weight
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/dynamic_requirements
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM_LIST
+
+/datum/config_entry/keyed_list/dynamic_high_population_requirement
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index a365405ce6..345e3bb44c 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -33,6 +33,7 @@ SUBSYSTEM_DEF(mapping)
var/list/z_list
var/datum/space_level/transit
var/datum/space_level/empty_space
+ var/num_of_res_levels = 1
//dlete dis once #39770 is resolved
/datum/controller/subsystem/mapping/proc/HACK_LoadMapConfig()
@@ -449,6 +450,11 @@ GLOBAL_LIST_EMPTY(the_station_areas)
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
if(reserve.Reserve(width, height, i))
return reserve
+ //If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
+ num_of_res_levels += 1
+ var/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
+ if(reserve.Reserve(width, height, newReserved))
+ return reserve
else
if(!level_trait(z, ZTRAIT_RESERVED))
qdel(reserve)
@@ -481,6 +487,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
LAZYINITLIST(unused_turfs["[T.z]"])
unused_turfs["[T.z]"] |= T
T.flags_1 |= UNUSED_RESERVATION_TURF_1
+ GLOB.areas_by_type[world.area].contents += T
CHECK_TICK
//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm
index 435414a899..107d65a558 100644
--- a/code/controllers/subsystem/vis_overlays.dm
+++ b/code/controllers/subsystem/vis_overlays.dm
@@ -6,11 +6,9 @@ SUBSYSTEM_DEF(vis_overlays)
var/list/vis_overlay_cache
var/list/currentrun
- var/datum/callback/rotate_cb
/datum/controller/subsystem/vis_overlays/Initialize()
vis_overlay_cache = list()
- rotate_cb = CALLBACK(src, .proc/rotate_vis_overlay)
return ..()
/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
@@ -52,7 +50,7 @@ SUBSYSTEM_DEF(vis_overlays)
if(!thing.managed_vis_overlays)
thing.managed_vis_overlays = list(overlay)
- RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, rotate_cb)
+ RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_vis_overlay)
else
thing.managed_vis_overlays += overlay
diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm
index b3d3b46434..fbe94cbb9e 100644
--- a/code/datums/components/_component.dm
+++ b/code/datums/components/_component.dm
@@ -2,6 +2,10 @@
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/datum/parent
+ //only set to true if you are able to properly transfer this component
+ //At a minimum RegisterWithParent and UnregisterFromParent should be used
+ //Make sure you also implement PostTransfer for any post transfer handling
+ var/can_transfer = FALSE
/datum/component/New(datum/P, ...)
parent = P
@@ -83,7 +87,7 @@
/datum/component/proc/UnregisterFromParent()
return
-/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
+/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE)
if(QDELETED(src) || QDELETED(target))
return
@@ -96,15 +100,12 @@
if(!lookup)
target.comp_lookup = lookup = list()
- if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
- proc_or_callback = CALLBACK(src, proc_or_callback)
-
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
for(var/sig_type in sig_types)
if(!override && procs[target][sig_type])
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
- procs[target][sig_type] = proc_or_callback
+ procs[target][sig_type] = proctype
if(!lookup[sig_type]) // Nothing has registered here yet
lookup[sig_type] = src
@@ -154,7 +155,7 @@
return
/datum/component/proc/PostTransfer()
- return
+ return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it
/datum/component/proc/_GetInverseTypeList(our_type = type)
//we can do this one simple trick
@@ -171,17 +172,20 @@
var/datum/C = target
if(!C.signal_enabled)
return NONE
- var/datum/callback/CB = C.signal_procs[src][sigtype]
- return CB.InvokeAsync(arglist(arguments))
+ var/proctype = C.signal_procs[src][sigtype]
+ return NONE | CallAsync(C, proctype, arguments)
. = NONE
for(var/I in target)
var/datum/C = I
if(!C.signal_enabled)
continue
- var/datum/callback/CB = C.signal_procs[src][sigtype]
- . |= CB.InvokeAsync(arglist(arguments))
+ var/proctype = C.signal_procs[src][sigtype]
+ . |= CallAsync(C, proctype, arguments)
-/datum/proc/GetComponent(c_type)
+// The type arg is casted so initial works, you shouldn't be passing a real instance into this
+/datum/proc/GetComponent(datum/component/c_type)
+ if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED)
+ stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]")
var/list/dc = datum_components
if(!dc)
return null
@@ -220,10 +224,6 @@
if(ispath(nt))
if(nt == /datum/component)
CRASH("[nt] attempted instantiation!")
- if(!isnum(dm))
- CRASH("[nt]: Invalid dupe_mode ([dm])!")
- if(dt && !ispath(dt))
- CRASH("[nt]: Invalid dupe_type ([dt])!")
else
new_comp = nt
nt = new_comp.type
@@ -285,10 +285,13 @@
if(target.parent)
target.RemoveComponent()
target.parent = src
- if(target.PostTransfer() == COMPONENT_INCOMPATIBLE)
- var/c_type = target.type
- qdel(target)
- CRASH("Incompatible [c_type] transfer attempt to a [type]!")
+ var/result = target.PostTransfer()
+ switch(result)
+ if(COMPONENT_INCOMPATIBLE)
+ var/c_type = target.type
+ qdel(target)
+ CRASH("Incompatible [c_type] transfer attempt to a [type]!")
+
if(target == AddComponent(target))
target._JoinParent()
@@ -298,10 +301,13 @@
return
var/comps = dc[/datum/component]
if(islist(comps))
- for(var/I in comps)
- target.TakeComponent(I)
+ for(var/datum/component/I in comps)
+ if(I.can_transfer)
+ target.TakeComponent(I)
else
- target.TakeComponent(comps)
+ var/datum/component/C = comps
+ if(C.can_transfer)
+ target.TakeComponent(comps)
/datum/component/ui_host()
return parent
diff --git a/code/datums/components/cleaning.dm b/code/datums/components/cleaning.dm
index 05c26efcc1..5324a87fee 100644
--- a/code/datums/components/cleaning.dm
+++ b/code/datums/components/cleaning.dm
@@ -8,32 +8,39 @@
/datum/component/cleaning/proc/Clean()
var/atom/movable/AM = parent
- var/turf/tile = AM.loc
- if(!isturf(tile))
- return
-
- SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- for(var/A in tile)
+ var/turf/T = AM.loc
+ SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ for(var/A in T)
if(is_cleanable(A))
qdel(A)
- else if(istype(A, /obj/item))
- var/obj/item/I = A
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(ismob(I.loc))
- var/mob/M = I.loc
+ else if(isitem(A))
+ var/obj/item/cleaned_item = A
+ SEND_SIGNAL(cleaned_item, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_item.clean_blood()
+ if(ismob(cleaned_item.loc))
+ var/mob/M = cleaned_item.loc
M.regenerate_icons()
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.head.clean_blood()
+ cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.wear_suit.clean_blood()
+ cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.w_uniform.clean_blood()
+ cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.shoes.clean_blood()
+ cleaned_human.update_inv_shoes()
+ SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.clean_blood()
cleaned_human.wash_cream()
cleaned_human.regenerate_icons()
- to_chat(cleaned_human, "[AM] cleans your face!")
+ to_chat(cleaned_human, "[src] cleans your face!")
\ No newline at end of file
diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm
index e5547ee0ec..bdc1d3a2f6 100644
--- a/code/datums/components/decal.dm
+++ b/code/datums/components/decal.dm
@@ -1,6 +1,6 @@
/datum/component/decal
dupe_mode = COMPONENT_DUPE_ALLOWED
-
+ can_transfer = TRUE
var/cleanable
var/description
var/mutable_appearance/pic
diff --git a/code/datums/components/decals/blood.dm b/code/datums/components/decals/blood.dm
index 7fae975678..c8be6251b5 100644
--- a/code/datums/components/decals/blood.dm
+++ b/code/datums/components/decals/blood.dm
@@ -1,39 +1,13 @@
-/datum/component/decal/blood
- dupe_mode = COMPONENT_DUPE_UNIQUE
-
-/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
- if(!isitem(parent))
- return COMPONENT_INCOMPATIBLE
- . = ..()
- RegisterSignal(parent, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
-
-/datum/component/decal/blood/generate_appearance(_icon, _icon_state, _dir, _layer, _color)
- var/obj/item/I = parent
- if(!_icon)
- _icon = 'icons/effects/blood.dmi'
- if(!_icon_state)
- _icon_state = "itemblood"
- var/icon = initial(I.icon)
- var/icon_state = initial(I.icon_state)
- if(!icon || !icon_state)
- // It's something which takes on the look of other items, probably
- icon = I.icon
- icon_state = I.icon_state
- var/static/list/blood_splatter_appearances = list()
- //try to find a pre-processed blood-splatter. otherwise, make a new one
- var/index = "[REF(icon)]-[icon_state]"
- pic = blood_splatter_appearances[index]
-
- if(!pic)
- var/icon/blood_splatter_icon = icon(initial(I.icon), initial(I.icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
- blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
- blood_splatter_icon.Blend(icon(_icon, _icon_state), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
- pic = mutable_appearance(blood_splatter_icon, initial(I.icon_state))
- blood_splatter_appearances[index] = pic
- return TRUE
-
-/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
- var/atom/A = parent
- override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a"
- override[EXAMINE_POSITION_BEFORE] = " blood-stained "
- return COMPONENT_EXNAME_CHANGED
+/datum/component/decal/blood
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+
+/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+ . = ..()
+ RegisterSignal(parent, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
+
+/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
+ var/atom/A = parent
+
+ return COMPONENT_EXNAME_CHANGED
diff --git a/code/datums/components/earprotection.dm b/code/datums/components/earprotection.dm
index 2084943756..9256c4310a 100644
--- a/code/datums/components/earprotection.dm
+++ b/code/datums/components/earprotection.dm
@@ -1,11 +1,11 @@
/datum/component/wearertargeting/earprotection
signals = list(COMSIG_CARBON_SOUNDBANG)
mobtype = /mob/living/carbon
+ proctype = .proc/reducebang
/datum/component/wearertargeting/earprotection/Initialize(_valid_slots)
. = ..()
valid_slots = _valid_slots
- callback = CALLBACK(src, .proc/reducebang)
/datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist)
reflist[1]--
diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm
deleted file mode 100644
index c7a1f7eba5..0000000000
--- a/code/datums/components/forensics.dm
+++ /dev/null
@@ -1,159 +0,0 @@
-/datum/component/forensics
- dupe_mode = COMPONENT_DUPE_UNIQUE
- var/list/fingerprints //assoc print = print
- var/list/hiddenprints //assoc ckey = realname/gloves/ckey
- var/list/blood_DNA //assoc dna = bloodtype
- var/list/fibers //assoc print = print
-
-/datum/component/forensics/InheritComponent(datum/component/forensics/F, original) //Use of | and |= being different here is INTENTIONAL.
- fingerprints = fingerprints | F.fingerprints
- hiddenprints = hiddenprints | F.hiddenprints
- blood_DNA = blood_DNA | F.blood_DNA
- fibers = fibers | F.fibers
- check_blood()
- return ..()
-
-/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers)
- if(!isatom(parent))
- return COMPONENT_INCOMPATIBLE
- fingerprints = new_fingerprints
- hiddenprints = new_hiddenprints
- blood_DNA = new_blood_DNA
- fibers = new_fibers
- check_blood()
- RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act)
-
-/datum/component/forensics/proc/wipe_fingerprints()
- fingerprints = null
- return TRUE
-
-/datum/component/forensics/proc/wipe_hiddenprints()
- return //no.
-
-/datum/component/forensics/proc/wipe_blood_DNA()
- blood_DNA = null
- if(isitem(parent))
- qdel(parent.GetComponent(/datum/component/decal/blood))
- return TRUE
-
-/datum/component/forensics/proc/wipe_fibers()
- fibers = null
- return TRUE
-
-/datum/component/forensics/proc/clean_act(datum/source, strength)
- if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
- wipe_fingerprints()
- if(strength >= CLEAN_STRENGTH_BLOOD)
- wipe_blood_DNA()
- if(strength >= CLEAN_STRENGTH_FIBERS)
- wipe_fibers()
-
-/datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text)
- if(!length(_fingerprints))
- return
- LAZYINITLIST(fingerprints)
- for(var/i in _fingerprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
- fingerprints[i] = i
- return TRUE
-
-/datum/component/forensics/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
- if(!M)
- return
- add_hiddenprint(M)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- add_fibers(H)
- if(H.gloves) //Check if the gloves (if any) hide fingerprints
- var/obj/item/clothing/gloves/G = H.gloves
- if(G.transfer_prints)
- ignoregloves = TRUE
- if(!ignoregloves)
- H.gloves.add_fingerprint(H, TRUE) //ignoregloves = 1 to avoid infinite loop.
- return
- var/full_print = md5(H.dna.uni_identity)
- LAZYSET(fingerprints, full_print, full_print)
- return TRUE
-
-/datum/component/forensics/proc/add_fiber_list(list/_fibertext) //list(text)
- if(!length(_fibertext))
- return
- LAZYINITLIST(fibers)
- for(var/i in _fibertext) //We use an associative list, make sure we don't just merge a non-associative list into ours.
- fibers[i] = i
- return TRUE
-
-/datum/component/forensics/proc/add_fibers(mob/living/carbon/human/M)
- var/fibertext
- var/item_multiplier = isitem(src)?1.2:1
- if(M.wear_suit)
- fibertext = "Material from \a [M.wear_suit]."
- if(prob(10*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- if(!(M.wear_suit.body_parts_covered & CHEST))
- if(M.w_uniform)
- fibertext = "Fibers from \a [M.w_uniform]."
- if(prob(12*item_multiplier) && !LAZYACCESS(fibers, fibertext)) //Wearing a suit means less of the uniform exposed.
- LAZYSET(fibers, fibertext, fibertext)
- if(!(M.wear_suit.body_parts_covered & HANDS))
- if(M.gloves)
- fibertext = "Material from a pair of [M.gloves.name]."
- if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- else if(M.w_uniform)
- fibertext = "Fibers from \a [M.w_uniform]."
- if(prob(15*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- // "Added fibertext: [fibertext]"
- LAZYSET(fibers, fibertext, fibertext)
- if(M.gloves)
- fibertext = "Material from a pair of [M.gloves.name]."
- if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- else if(M.gloves)
- fibertext = "Material from a pair of [M.gloves.name]."
- if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
- LAZYSET(fibers, fibertext, fibertext)
- return TRUE
-
-/datum/component/forensics/proc/add_hiddenprint_list(list/_hiddenprints) //list(ckey = text)
- if(!length(_hiddenprints))
- return
- LAZYINITLIST(hiddenprints)
- for(var/i in _hiddenprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
- hiddenprints[i] = _hiddenprints[i]
- return TRUE
-
-/datum/component/forensics/proc/add_hiddenprint(mob/living/M)
- if(!M || !M.key)
- return
- var/hasgloves = ""
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(H.gloves)
- hasgloves = "(gloves)"
- var/current_time = TIME_STAMP("hh:mm:ss", FALSE)
- if(!LAZYACCESS(hiddenprints, M.key))
- LAZYSET(hiddenprints, M.key, "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]")
- else
- var/laststamppos = findtext(LAZYACCESS(hiddenprints, M.key), " Last: ")
- if(laststamppos)
- LAZYSET(hiddenprints, M.key, copytext(hiddenprints[M.key], 1, laststamppos))
- hiddenprints[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]" //made sure to be existing by if(!LAZYACCESS);else
- var/atom/A = parent
- A.fingerprintslast = M.ckey
- return TRUE
-
-/datum/component/forensics/proc/add_blood_DNA(list/dna) //list(dna_enzymes = type)
- if(!length(dna))
- return
- LAZYINITLIST(blood_DNA)
- for(var/i in dna)
- blood_DNA[i] = dna[i]
- check_blood()
- return TRUE
-
-/datum/component/forensics/proc/check_blood()
- if(!isitem(parent))
- return
- if(!length(blood_DNA))
- return
- parent.LoadComponent(/datum/component/decal/blood)
diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm
index cd5df8220b..ad2b7ded14 100644
--- a/code/datums/components/infective.dm
+++ b/code/datums/components/infective.dm
@@ -6,21 +6,28 @@
/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in)
if(islist(_diseases))
- diseases = diseases
+ diseases = _diseases
else
diseases = list(_diseases)
if(expire_in)
expire_time = world.time + expire_in
QDEL_IN(src, expire_in)
+
+ if(!ismovableatom(parent))
+ return COMPONENT_INCOMPATIBLE
+ RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean)
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/try_infect_buckle)
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/try_infect_collide)
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/try_infect_crossed)
- RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, .proc/try_infect_attack_zone)
- RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/try_infect_attack)
- RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/try_infect_equipped)
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT_ZONE, .proc/try_infect_impact_zone)
- RegisterSignal(parent, COMSIG_FOOD_EATEN, .proc/try_infect_eat)
- RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean)
+ if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, .proc/try_infect_attack_zone)
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/try_infect_attack)
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/try_infect_equipped)
+ if(istype(parent, /obj/item/reagent_containers/food/snacks))
+ RegisterSignal(parent, COMSIG_FOOD_EATEN, .proc/try_infect_eat)
+ else if(istype(parent, /obj/effect/decal/cleanable/blood/gibs))
+ RegisterSignal(parent, COMSIG_GIBS_STREAK, .proc/try_infect_streak)
/datum/component/infective/proc/try_infect_eat(datum/source, mob/living/eater, mob/living/feeder)
for(var/V in diseases)
@@ -73,6 +80,9 @@
if(isliving(M))
try_infect(M, BODY_ZONE_PRECISE_L_FOOT)
+/datum/component/infective/proc/try_infect_streak(datum/source, list/directions, list/output_diseases)
+ output_diseases |= diseases
+
/datum/component/infective/proc/try_infect(mob/living/L, target_zone)
for(var/V in diseases)
L.ContactContractDisease(V, target_zone)
diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm
index cc41e793ed..38b707ac19 100644
--- a/code/datums/components/lockon_aiming.dm
+++ b/code/datums/components/lockon_aiming.dm
@@ -237,6 +237,3 @@
LOCKON_RANGING_BREAK_CHECK
cd++
CHECK_TICK
-
-/datum/component/lockon_aiming/PostTransfer(datum/new_parent)
- return COMPONENT_INCOMPATIBLE
diff --git a/code/datums/components/mirage_border.dm b/code/datums/components/mirage_border.dm
index 2e6f8f79f6..20e3b317ec 100644
--- a/code/datums/components/mirage_border.dm
+++ b/code/datums/components/mirage_border.dm
@@ -1,4 +1,5 @@
/datum/component/mirage_border
+ can_transfer = TRUE
var/obj/effect/abstract/mirage_holder/holder
/datum/component/mirage_border/Initialize(turf/target, direction, range=world.view)
diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm
index 2b7c540058..8c6013aeab 100644
--- a/code/datums/components/mood.dm
+++ b/code/datums/components/mood.dm
@@ -206,8 +206,8 @@
/datum/component/mood/proc/setInsanityEffect(newval)//More code so that the previous proc works
if(newval == insanity_effect)
return
- var/mob/living/master = parent
- master.crit_threshold = (master.crit_threshold - insanity_effect) + newval
+ //var/mob/living/master = parent
+ //master.crit_threshold = (master.crit_threshold - insanity_effect) + newval
insanity_effect = newval
/datum/component/mood/proc/modify_sanity(datum/source, amount, minimum = -INFINITY, maximum = INFINITY)
@@ -231,8 +231,6 @@
if(the_event.timeout)
addtimer(CALLBACK(src, .proc/clear_event, null, category), the_event.timeout, TIMER_UNIQUE|TIMER_OVERRIDE)
- return the_event
-
/datum/component/mood/proc/clear_event(datum/source, category)
var/datum/mood_event/event = mood_events[category]
if(!event)
diff --git a/code/datums/components/ntnet_interface.dm b/code/datums/components/ntnet_interface.dm
index d945f68ca9..7c364a61ab 100644
--- a/code/datums/components/ntnet_interface.dm
+++ b/code/datums/components/ntnet_interface.dm
@@ -6,7 +6,7 @@
return
/datum/proc/ntnet_send(datum/netdata/data, netid)
- GET_COMPONENT(NIC, /datum/component/ntnet_interface)
+ var/datum/component/ntnet_interface/NIC = GetComponent(/datum/component/ntnet_interface)
if(!NIC)
return FALSE
return NIC.__network_send(data, netid)
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
index 301e50dc42..efa0fd14d5 100644
--- a/code/datums/components/orbiter.dm
+++ b/code/datums/components/orbiter.dm
@@ -1,8 +1,7 @@
/datum/component/orbiter
+ can_transfer = TRUE
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/list/orbiters
- var/datum/callback/orbiter_spy
- var/datum/callback/orbited_spy
//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
//clockwise: whether you orbit clockwise or anti clockwise
@@ -14,8 +13,6 @@
return COMPONENT_INCOMPATIBLE
orbiters = list()
- orbiter_spy = CALLBACK(src, .proc/orbiter_move_react)
- orbited_spy = CALLBACK(src, .proc/move_react)
var/atom/master = parent
master.orbiters = src
@@ -25,7 +22,7 @@
/datum/component/orbiter/RegisterWithParent()
var/atom/target = parent
while(ismovableatom(target))
- RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy)
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react)
target = target.loc
/datum/component/orbiter/UnregisterFromParent()
@@ -40,8 +37,6 @@
for(var/i in orbiters)
end_orbit(i)
orbiters = null
- QDEL_NULL(orbiter_spy)
- QDEL_NULL(orbited_spy)
return ..()
/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments)
@@ -64,7 +59,7 @@
orbiter.orbiting.end_orbit(orbiter)
orbiters[orbiter] = TRUE
orbiter.orbiting = src
- RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, orbiter_spy)
+ RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, .proc/orbiter_move_react)
var/matrix/initial_transform = matrix(orbiter.transform)
// Head first!
@@ -120,7 +115,7 @@
if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too
var/atom/target = orbited.loc
while(ismovableatom(target))
- RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy, TRUE)
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react, TRUE)
target = target.loc
var/atom/curloc = master.loc
diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm
new file mode 100644
index 0000000000..ff1c48936f
--- /dev/null
+++ b/code/datums/components/phantomthief.dm
@@ -0,0 +1,39 @@
+//This component applies a customizable drop_shadow filter to its wearer when they toggle combat mode on or off. This can stack.
+
+/datum/component/wearertargeting/phantomthief
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ signals = list(COMSIG_COMBAT_TOGGLED)
+ proctype = .proc/handlefilterstuff
+ var/filter_x
+ var/filter_y
+ var/filter_size
+ var/filter_border
+ var/filter_color
+
+/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
+ . = ..()
+ if(. == COMPONENT_INCOMPATIBLE)
+ return
+ filter_x = _x
+ filter_y = _y
+ filter_size = _size
+ filter_border = _border
+ filter_color = _color
+ valid_slots = _valid_slots
+
+/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
+ if(istype(user))
+ var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
+ if(!combatmodestate)
+ user.filters -= thefilter
+ else
+ user.filters += thefilter
+
+/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user)
+ if(istype(user))
+ var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
+ user.filters -= thefilter
+
+/datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user)
+ . = ..()
+ stripdesiredfilter(user)
diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm
index ff424dc02e..ed3ecd2ff3 100644
--- a/code/datums/components/rotation.dm
+++ b/code/datums/components/rotation.dm
@@ -44,19 +44,21 @@
if(src.rotation_flags & ROTATION_CLOCKWISE)
default_rotation_direction = ROTATION_CLOCKWISE
- if(src.rotation_flags & ROTATION_ALTCLICK)
+/datum/component/simple_rotation/proc/add_signals()
+ if(rotation_flags & ROTATION_ALTCLICK)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/HandRot)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/ExamineMessage)
- if(src.rotation_flags & ROTATION_WRENCH)
+ if(rotation_flags & ROTATION_WRENCH)
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/WrenchRot)
- if(src.rotation_flags & ROTATION_VERBS)
+/datum/component/simple_rotation/proc/add_verbs()
+ if(rotation_flags & ROTATION_VERBS)
var/atom/movable/AM = parent
- if(src.rotation_flags & ROTATION_FLIP)
+ if(rotation_flags & ROTATION_FLIP)
AM.verbs += /atom/movable/proc/simple_rotate_flip
- if(src.rotation_flags & ROTATION_CLOCKWISE)
+ if(rotation_flags & ROTATION_CLOCKWISE)
AM.verbs += /atom/movable/proc/simple_rotate_clockwise
- if(src.rotation_flags & ROTATION_COUNTERCLOCKWISE)
+ if(rotation_flags & ROTATION_COUNTERCLOCKWISE)
AM.verbs += /atom/movable/proc/simple_rotate_counterclockwise
/datum/component/simple_rotation/proc/remove_verbs()
@@ -66,11 +68,30 @@
AM.verbs -= /atom/movable/proc/simple_rotate_clockwise
AM.verbs -= /atom/movable/proc/simple_rotate_counterclockwise
-/datum/component/simple_rotation/Destroy()
+/datum/component/simple_rotation/proc/remove_signals()
+ UnregisterSignal(parent, list(COMSIG_CLICK_ALT, COMSIG_PARENT_EXAMINE, COMSIG_PARENT_ATTACKBY))
+
+/datum/component/simple_rotation/RegisterWithParent()
+ add_verbs()
+ add_signals()
+ . = ..()
+
+/datum/component/simple_rotation/PostTransfer()
+ //Because of the callbacks which we don't track cleanly we can't transfer this
+ //item cleanly, better to let the new of the new item create a new rotation datum
+ //instead (there's no real state worth transferring)
+ return COMPONENT_NOTRANSFER
+
+/datum/component/simple_rotation/UnregisterFromParent()
remove_verbs()
+ remove_signals()
+ . = ..()
+
+/datum/component/simple_rotation/Destroy()
QDEL_NULL(can_user_rotate)
QDEL_NULL(can_be_rotated)
QDEL_NULL(after_rotation)
+ //Signals + verbs removed via UnRegister
. = ..()
/datum/component/simple_rotation/RemoveComponent()
@@ -122,7 +143,7 @@
set name = "Rotate Clockwise"
set category = "Object"
set src in oview(1)
- GET_COMPONENT(rotcomp,/datum/component/simple_rotation)
+ var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
if(rotcomp)
rotcomp.HandRot(usr,ROTATION_CLOCKWISE)
@@ -130,7 +151,7 @@
set name = "Rotate Counter-Clockwise"
set category = "Object"
set src in oview(1)
- GET_COMPONENT(rotcomp,/datum/component/simple_rotation)
+ var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
if(rotcomp)
rotcomp.HandRot(usr,ROTATION_COUNTERCLOCKWISE)
@@ -138,6 +159,6 @@
set name = "Flip"
set category = "Object"
set src in oview(1)
- GET_COMPONENT(rotcomp,/datum/component/simple_rotation)
+ var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
if(rotcomp)
rotcomp.HandRot(usr,ROTATION_FLIP)
diff --git a/code/datums/components/signal_redirect.dm b/code/datums/components/signal_redirect.dm
deleted file mode 100644
index db98d5664a..0000000000
--- a/code/datums/components/signal_redirect.dm
+++ /dev/null
@@ -1,33 +0,0 @@
-// This should only be used by non components trying to listen to a signal
-// If you use this inside a component I will replace your eyes with lemons ~ninjanomnom
-
-/datum/component/redirect
- dupe_mode = COMPONENT_DUPE_ALLOWED
- var/list/signals
- var/datum/callback/turfchangeCB
-
-/datum/component/redirect/Initialize(list/_signals, flags=NONE)
- //It's not our job to verify the right signals are registered here, just do it.
- if(!LAZYLEN(_signals))
- return COMPONENT_INCOMPATIBLE
- if(flags & REDIRECT_TRANSFER_WITH_TURF && isturf(parent))
- // If they also want to listen to the turf change then we need to set it up so both callbacks run
- if(_signals[COMSIG_TURF_CHANGE])
- turfchangeCB = _signals[COMSIG_TURF_CHANGE]
- if(!istype(turfchangeCB))
- . = COMPONENT_INCOMPATIBLE
- CRASH("Redirect components must be given instanced callbacks, not proc paths.")
- _signals[COMSIG_TURF_CHANGE] = CALLBACK(src, .proc/turf_change)
-
- signals = _signals
-
-/datum/component/redirect/RegisterWithParent()
- for(var/signal in signals)
- RegisterSignal(parent, signal, signals[signal])
-
-/datum/component/redirect/UnregisterFromParent()
- UnregisterSignal(parent, signals)
-
-/datum/component/redirect/proc/turf_change(datum/source, path, new_baseturfs, flags, list/transfers)
- transfers += src
- return turfchangeCB?.InvokeAsync(arglist(args))
diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm
index 0b78605869..f7ca711421 100644
--- a/code/datums/components/storage/concrete/_concrete.dm
+++ b/code/datums/components/storage/concrete/_concrete.dm
@@ -4,6 +4,7 @@
// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement
/datum/component/storage/concrete
+ can_transfer = TRUE
var/drop_all_on_deconstruct = TRUE
var/drop_all_on_destroy = FALSE
var/drop_all_on_break = FALSE
diff --git a/code/datums/components/storage/concrete/pockets.dm b/code/datums/components/storage/concrete/pockets.dm
index fe5e1e5217..7e4a561422 100644
--- a/code/datums/components/storage/concrete/pockets.dm
+++ b/code/datums/components/storage/concrete/pockets.dm
@@ -56,7 +56,7 @@
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
- /obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol/mag
+ /obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol
))
/datum/component/storage/concrete/pockets/shoes/clown/Initialize()
@@ -67,7 +67,7 @@
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
- /obj/item/firing_pin, /obj/item/bikehorn))
+ /obj/item/firing_pin, /obj/item/bikehorn, /obj/item/gun/ballistic/automatic/pistol))
/datum/component/storage/concrete/pockets/pocketprotector
max_items = 3
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index adec6f67ce..ee9cff19c7 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -587,7 +587,7 @@
return FALSE
if(isitem(host))
var/obj/item/IP = host
- GET_COMPONENT_FROM(STR_I, /datum/component/storage, I)
+ var/datum/component/storage/STR_I = I.GetComponent(/datum/component/storage)
if((I.w_class >= IP.w_class) && STR_I && !allow_big_nesting)
if(!stop_messages)
to_chat(M, "[IP] cannot hold [I] as it's a storage item of the same size!")
diff --git a/code/datums/components/swarming.dm b/code/datums/components/swarming.dm
index 17b2178df6..64844c4c32 100644
--- a/code/datums/components/swarming.dm
+++ b/code/datums/components/swarming.dm
@@ -12,7 +12,7 @@
RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/leave_swarm)
/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/AM)
- GET_COMPONENT_FROM(other_swarm, /datum/component/swarming, AM)
+ var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming)
if(!other_swarm)
return
swarm()
@@ -21,7 +21,7 @@
other_swarm.swarm_members |= src
/datum/component/swarming/proc/leave_swarm(datum/source, atom/movable/AM)
- GET_COMPONENT_FROM(other_swarm, /datum/component/swarming, AM)
+ var/datum/component/swarming/other_swarm = AM.GetComponent(/datum/component/swarming)
if(!other_swarm || !(other_swarm in swarm_members))
return
swarm_members -= other_swarm
diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm
index 750cc045ce..f8f0679e9b 100644
--- a/code/datums/components/virtual_reality.dm
+++ b/code/datums/components/virtual_reality.dm
@@ -1,5 +1,5 @@
/datum/component/virtual_reality
- dupe_mode = COMPONENT_DUPE_ALLOWED //mindswap memes, shouldn't stack up otherwise.
+ can_transfer = TRUE
var/datum/mind/mastermind // where is my mind t. pixies
var/datum/mind/current_mind
var/obj/machinery/vr_sleeper/vr_sleeper
diff --git a/code/datums/components/wearertargeting.dm b/code/datums/components/wearertargeting.dm
index 0aa0831127..feaa88f934 100644
--- a/code/datums/components/wearertargeting.dm
+++ b/code/datums/components/wearertargeting.dm
@@ -3,7 +3,7 @@
/datum/component/wearertargeting
var/list/valid_slots = list()
var/list/signals = list()
- var/datum/callback/callback = CALLBACK(GLOBAL_PROC, .proc/pass)
+ var/proctype = .proc/pass
var/mobtype = /mob/living
/datum/component/wearertargeting/Initialize()
@@ -14,13 +14,9 @@
/datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot)
if((slot in valid_slots) && istype(equipper, mobtype))
- RegisterSignal(equipper, signals, callback, TRUE)
+ RegisterSignal(equipper, signals, proctype, TRUE)
else
UnregisterSignal(equipper, signals)
/datum/component/wearertargeting/proc/on_drop(datum/source, mob/user)
- UnregisterSignal(user, signals)
-
-/datum/component/wearertargeting/Destroy()
- QDEL_NULL(callback) //is likely to ourselves.
- return ..()
\ No newline at end of file
+ UnregisterSignal(user, signals)
\ No newline at end of file
diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm
index 6d504cefd4..84b0320375 100644
--- a/code/datums/components/wet_floor.dm
+++ b/code/datums/components/wet_floor.dm
@@ -1,5 +1,6 @@
/datum/component/wet_floor
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ can_transfer = TRUE
var/highest_strength = TURF_DRY
var/lube_flags = NONE //why do we have this?
var/list/time_left_list //In deciseconds.
@@ -26,14 +27,19 @@
if(!isopenturf(parent))
return COMPONENT_INCOMPATIBLE
add_wet(strength, duration_minimum, duration_add, duration_maximum)
- RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet)
- RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry)
permanent = _permanent
if(!permanent)
START_PROCESSING(SSwet_floors, src)
addtimer(CALLBACK(src, .proc/gc, TRUE), 1) //GC after initialization.
last_process = world.time
+/datum/component/wet_floor/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet)
+ RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry)
+
+/datum/component/wet_floor/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_TURF_IS_WET, COMSIG_TURF_MAKE_DRY))
+
/datum/component/wet_floor/Destroy()
STOP_PROCESSING(SSwet_floors, src)
var/turf/T = parent
@@ -138,12 +144,19 @@
/datum/component/wet_floor/PreTransfer()
var/turf/O = parent
O.cut_overlay(current_overlay)
+ //That turf is no longer slippery, we're out of here
+ //Slippery components don't transfer due to callbacks
+ qdel(O.GetComponent(/datum/component/slippery))
/datum/component/wet_floor/PostTransfer()
if(!isopenturf(parent))
return COMPONENT_INCOMPATIBLE
var/turf/T = parent
T.add_overlay(current_overlay)
+ //Make sure to add/update any slippery component on the new turf (update_flags calls LoadComponent)
+ update_flags()
+
+ //NB it's possible we get deleted after this, due to inherit
/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE)
var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST)
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 33e92e4de5..8a3fd82cb9 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -42,8 +42,8 @@
destination.dna.unique_enzymes = unique_enzymes
destination.dna.uni_identity = uni_identity
destination.dna.blood_type = blood_type
- destination.set_species(species.type, icon_update=0)
destination.dna.features = features.Copy()
+ destination.set_species(species.type, icon_update=0)
destination.dna.real_name = real_name
destination.dna.nameless = nameless
destination.dna.custom_species = custom_species
diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm
index 1b095c555d..31023b3fc7 100644
--- a/code/datums/mutable_appearance.dm
+++ b/code/datums/mutable_appearance.dm
@@ -10,10 +10,11 @@
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
// Helper similar to image()
-/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE)
+/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, color = "#FFFFFF")
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
MA.layer = layer
MA.plane = plane
+ MA.color = color
return MA
diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm
index 9762426608..34a676603e 100644
--- a/code/datums/ruins/space.dm
+++ b/code/datums/ruins/space.dm
@@ -282,6 +282,11 @@
name = "Ancient Cloning Lab"
description = "An experimental cloning lab snapped off from an ancient ship. The cloner model inside lacks many modern functionalities and security measures."
+/datum/map_template/ruin/space/hilbertresearchfacility
+ id = "hilbert_facility"
+ suffix = "hilbertshoteltestingsite.dmm"
+ name = "Hilbert Research Facility"
+ description = "A research facility of great bluespace discoveries. Long since abandoned, willingly or not..."
/datum/map_template/ruin/space/augmentation
id = "augmentationfacility"
suffix = "augmentationfacility.dmm"
diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm
index dfe0a1d94e..0041799314 100644
--- a/code/datums/status_effects/gas.dm
+++ b/code/datums/status_effects/gas.dm
@@ -5,7 +5,6 @@
alert_type = /obj/screen/alert/status_effect/freon
var/icon/cube
var/can_melt = TRUE
- var/datum/weakref/redirect_component
/obj/screen/alert/status_effect/freon
name = "Frozen Solid"
@@ -13,7 +12,7 @@
icon_state = "frozen"
/datum/status_effect/freon/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/owner_resist)
if(!owner.stat)
to_chat(owner, "You become frozen in a cube!")
cube = icon('icons/effects/freeze.dmi', "ice_cube")
@@ -40,8 +39,7 @@
owner.cut_overlay(cube)
owner.adjust_bodytemperature(100)
owner.update_canmove()
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
/datum/status_effect/freon/watcher
duration = 8
diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm
index dffdc92630..80a5f24250 100644
--- a/code/datums/traits/good.dm
+++ b/code/datums/traits/good.dm
@@ -16,13 +16,13 @@
mood_quirk = TRUE
/datum/quirk/apathetic/add()
- GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder)
+ var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
if(mood)
mood.mood_modifier = 0.8
/datum/quirk/apathetic/remove()
if(quirk_holder)
- GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder)
+ var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
if(mood)
mood.mood_modifier = 1 //Change this once/if species get their own mood modifiers.
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 7c9dc3f4fe..2a47d6d015 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -36,6 +36,12 @@
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
var/rad_insulation = RAD_NO_INSULATION
+ var/icon/blood_splatter_icon
+ var/list/fingerprints
+ var/list/fingerprintshidden
+ var/list/blood_DNA
+ var/list/suit_fibers
+
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -220,7 +226,7 @@
return FALSE
/atom/proc/CheckExit()
- return 1
+ return TRUE
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
return
@@ -254,14 +260,26 @@
if(article)
. = "[article] [src]"
override[EXAMINE_POSITION_ARTICLE] = article
+
+ var/should_override = FALSE
+
if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
+ should_override = TRUE
+
+
+ if(blood_DNA && !istype(src, /obj/effect/decal))
+ override[EXAMINE_POSITION_BEFORE] = " blood-stained "
+ should_override = TRUE
+
+ if(should_override)
. = override.Join("")
+///Generate the full examine string of this atom (including icon for goonchat)
/atom/proc/get_examine_string(mob/user, thats = FALSE)
. = "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]"
/atom/proc/examine(mob/user)
- to_chat(user, get_examine_string(user, TRUE))
+ to_chat(user, "[get_examine_string(user, TRUE)].")
if(desc)
to_chat(user, desc)
@@ -326,12 +344,14 @@
//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
/mob/living/proc/get_blood_dna_list()
- if(get_blood_id() != "blood")
+ var/blood_id = get_blood_id()
+ if(!(blood_id =="blood" || blood_id == "jellyblood"))
return
return list("ANIMAL DNA" = "Y-")
/mob/living/carbon/get_blood_dna_list()
- if(get_blood_id() != "blood")
+ var/blood_id = get_blood_id()
+ if(!(blood_id =="blood" || blood_id == "jellyblood"))
return
var/list/blood_dna = list()
if(dna)
@@ -349,18 +369,116 @@
var/new_blood_dna = L.get_blood_dna_list()
if(!new_blood_dna)
return FALSE
- var/old_length = blood_DNA_length()
- add_blood_DNA(new_blood_dna)
- if(blood_DNA_length() == old_length)
+ LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it.
+ var/old_length = blood_DNA.len
+ blood_DNA |= new_blood_dna
+ if(blood_DNA.len == old_length)
return FALSE
return TRUE
+//to add blood dna info to the object's blood_DNA list
+/atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases)
+ LAZYINITLIST(blood_DNA)
+ var/old_length = blood_DNA.len
+ blood_DNA |= blood_dna
+ if(blood_DNA.len > old_length)
+ return TRUE
+ //some new blood DNA was added
+
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
var/list/blood_dna = M.get_blood_dna_list()
if(!blood_dna)
return FALSE
- return add_blood_DNA(blood_dna)
+ return add_blood_DNA(blood_dna, M.diseases)
+
+//to add blood onto something, with blood dna info to include.
+/atom/proc/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
+ return FALSE
+
+/obj/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
+ return transfer_blood_dna(blood_dna, diseases)
+
+/obj/item/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
+ . = ..()
+ if(!.)
+ return
+ add_blood_overlay()
+
+/obj/item/proc/add_blood_overlay()
+ if(!blood_DNA.len)
+ return
+ if(initial(icon) && initial(icon_state))
+ blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
+ blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
+ blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
+ blood_splatter_icon.Blend(blood_DNA_to_color(), ICON_MULTIPLY)
+ add_overlay(blood_splatter_icon)
+
+/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
+ . = ..()
+ transfer_blood = rand(2, 4)
+
+/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
+ var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
+ if(!B)
+ B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
+ B.transfer_blood_dna(blood_dna, diseases) //give blood info to the blood decal.
+ return TRUE //we bloodied the floor
+
+/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
+ if(head)
+ head.add_blood_DNA(blood_dna, diseases)
+ update_inv_head()
+ else if(wear_mask)
+ wear_mask.add_blood_DNA(blood_dna, diseases)
+ update_inv_wear_mask()
+ if(wear_neck)
+ wear_neck.add_blood_DNA(blood_dna, diseases)
+ update_inv_neck()
+ if(wear_suit)
+ wear_suit.add_blood_DNA(blood_dna, diseases)
+ update_inv_wear_suit()
+ else if(w_uniform)
+ w_uniform.add_blood_DNA(blood_dna, diseases)
+ update_inv_w_uniform()
+ if(gloves)
+ var/obj/item/clothing/gloves/G = gloves
+ G.add_blood_DNA(blood_dna, diseases)
+ else
+ transfer_blood_dna(blood_dna, diseases)
+ bloody_hands = rand(2, 4)
+ update_inv_gloves() //handles bloody hands overlays and updating
+ return TRUE
+
+/atom/proc/blood_DNA_to_color()
+ var/list/colors = list()//first we make a list of all bloodtypes present
+ for(var/bloop in blood_DNA)
+ if(colors[blood_DNA[bloop]])
+ colors[blood_DNA[bloop]]++
+ else
+ colors[blood_DNA[bloop]] = 1
+
+ var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up
+
+ if(colors.len)
+ var/sum = 0 //this is all shitcode, but it works; trust me
+ final_rgb = bloodtype_to_color(colors[1])
+ sum = colors[colors[1]]
+ if(colors.len > 1)
+ var/i = 2
+ while(i <= colors.len)
+ var/tmp = colors[colors[i]]
+ final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum))
+ sum += tmp
+ i++
+
+ return final_rgb
+
+/atom/proc/clean_blood()
+ if(islist(blood_DNA))
+ blood_DNA = null
+ return TRUE
/atom/proc/wash_cream()
return TRUE
@@ -410,7 +528,7 @@
/atom/proc/component_storage_contents_dump_act(datum/component/storage/src_object, mob/user)
var/list/things = src_object.contents()
var/datum/progressbar/progress = new(user, things.len, src)
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(STR, /datum/component/storage.proc/handle_mass_item_insertion, things, src_object, user, progress)))
stoplag(1)
qdel(progress)
@@ -714,4 +832,4 @@ Proc for attack log creation, because really why not
if(filter_data[name])
filter_data -= name
update_filters()
- return TRUE
+ return TRUE
\ No newline at end of file
diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm
index 9d1a3b650c..46cef7df63 100644
--- a/code/game/gamemodes/clown_ops/clown_weapons.dm
+++ b/code/game/gamemodes/clown_ops/clown_weapons.dm
@@ -39,12 +39,12 @@
/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/Initialize()
. = ..()
- GET_COMPONENT(bananium, /datum/component/material_container)
+ var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
bananium.insert_amount(max_recharge, MAT_BANANIUM)
START_PROCESSING(SSobj, src)
/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/process()
- GET_COMPONENT(bananium, /datum/component/material_container)
+ var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
var/bananium_amount = bananium.amount(MAT_BANANIUM)
if(bananium_amount < max_recharge)
bananium.insert_amount(min(recharge_rate, max_recharge - bananium_amount), MAT_BANANIUM)
@@ -73,19 +73,19 @@
/obj/item/melee/transforming/energy/sword/bananium/Initialize()
. = ..()
AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP)
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.signal_enabled = active
/obj/item/melee/transforming/energy/sword/bananium/attack(mob/living/M, mob/living/user)
..()
if(active)
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(M)
/obj/item/melee/transforming/energy/sword/bananium/throw_impact(atom/hit_atom, throwingdatum)
. = ..()
if(active)
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(hit_atom)
/obj/item/melee/transforming/energy/sword/bananium/attackby(obj/item/I, mob/living/user, params)
@@ -98,7 +98,7 @@
/obj/item/melee/transforming/energy/sword/bananium/transform_weapon(mob/living/user, supress_message_text)
..()
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.signal_enabled = active
/obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user)
@@ -108,7 +108,7 @@
if(!active)
transform_weapon(user, TRUE)
user.visible_message("[user] is [pick("slitting [user.p_their()] stomach open with", "falling on")] [src]! It looks like [user.p_theyre()] trying to commit seppuku, but the blade slips off of [user.p_them()] harmlessly!")
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(user)
return SHAME
@@ -130,12 +130,12 @@
/obj/item/shield/energy/bananium/Initialize()
. = ..()
AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP)
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.signal_enabled = active
/obj/item/shield/energy/bananium/attack_self(mob/living/carbon/human/user)
..()
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.signal_enabled = active
/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1)
@@ -149,7 +149,7 @@
if(active)
var/caught = hit_atom.hitby(src, 0, 0)
if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it
- GET_COMPONENT(slipper, /datum/component/slippery)
+ var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
slipper.Slip(hit_atom)
if(thrownby && !caught)
throw_at(thrownby, throw_range+2, throw_speed, null, 1)
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
index e22b785670..24cfddd14f 100644
--- a/code/game/gamemodes/dynamic/dynamic.dm
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -107,6 +107,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
/// If a only ruleset has been executed.
var/only_ruleset_executed = FALSE
+/datum/game_mode/dynamic/New() // i have NO IDEA if this is the proper way to do this.
+ ..()
+ pop_per_requirement = CONFIG_GET(number/dynamic_pop_per_requirement)
+ GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit)
+
/datum/game_mode/dynamic/admin_panel()
var/list/dat = list("
Game Mode PanelGame Mode Panel
")
dat += "Dynamic Mode \[VV\]
"
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm
index 66afcbfb92..011b6ec251 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm
@@ -3,6 +3,8 @@
var/name = ""
/// For admin logging and round end screen, do not change this unless making a new rule type.
var/ruletype = ""
+ /// For config purposes, similar to config_tag for secret game modes.
+ var/config_tag = null
/// If set to TRUE, the rule won't be discarded after being executed, and dynamic will call rule_process() every time it ticks.
var/persistent = FALSE
/// If set to TRUE, dynamic mode will be able to draft this ruleset again later on. (doesn't apply for roundstart rules)
@@ -65,7 +67,18 @@
restricted_roles += protected_roles
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
restricted_roles += "Assistant"
-
+ var/weights = CONFIG_GET(keyed_list/dynamic_weight)
+ var/costs = CONFIG_GET(keyed_list/dynamic_cost)
+ var/requirementses = CONFIG_GET(keyed_list/dynamic_requirements) // can't damn well use requirements
+ var/high_population_requirements = CONFIG_GET(keyed_list/dynamic_high_population_requirement)
+ if(config_tag in weights)
+ weight = weights[config_tag]
+ if(config_tag in costs)
+ cost = costs[config_tag]
+ if(config_tag in requirementses)
+ requirements = requirementses[config_tag]
+ if(config_tag in high_population_requirements)
+ high_population_requirement = high_population_requirements[config_tag]
if (istype(SSticker.mode, /datum/game_mode/dynamic))
mode = SSticker.mode
else if (GLOB.master_mode != "dynamic") // This is here to make roundstart forced ruleset function.
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
index 24b4c67357..fde020a3ae 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
@@ -52,6 +52,7 @@
/datum/dynamic_ruleset/latejoin/infiltrator
name = "Syndicate Infiltrator"
+ config_tag = "latejoin_traitor"
antag_datum = /datum/antagonist/traitor
antag_flag = ROLE_TRAITOR
restricted_roles = list("AI", "Cyborg")
@@ -72,6 +73,7 @@
/datum/dynamic_ruleset/latejoin/provocateur
name = "Provocateur"
+ config_tag = "latejoin_revolution"
antag_datum = /datum/antagonist/rev/head
antag_flag = ROLE_REV_HEAD
antag_flag_override = ROLE_REV
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
index 4da085d5a9..56b6e57c4d 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
@@ -169,6 +169,7 @@
/datum/dynamic_ruleset/midround/autotraitor
name = "Syndicate Sleeper Agent"
+ config_tag = "midround_traitor"
antag_datum = /datum/antagonist/traitor
antag_flag = ROLE_TRAITOR
restricted_roles = list("AI", "Cyborg", "Positronic Brain")
@@ -224,6 +225,7 @@
/datum/dynamic_ruleset/midround/malf
name = "Malfunctioning AI"
+ config_tag = "malf_ai"
antag_datum = /datum/antagonist/traitor
antag_flag = ROLE_MALF
enemy_roles = list("Security Officer", "Warden","Detective","Head of Security", "Captain", "Scientist", "Chemist", "Research Director", "Chief Engineer")
@@ -276,6 +278,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/wizard
name = "Wizard"
+ config_tag = "midround_wizard"
antag_datum = /datum/antagonist/wizard
antag_flag = ROLE_WIZARD
enemy_roles = list("Security Officer","Detective","Head of Security", "Captain")
@@ -308,6 +311,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/nuclear
name = "Nuclear Assault"
+ config_tag = "midround_nuclear"
antag_flag = ROLE_OPERATIVE
antag_datum = /datum/antagonist/nukeop
enemy_roles = list("AI", "Cyborg", "Security Officer", "Warden","Detective","Head of Security", "Captain")
@@ -351,6 +355,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/blob
name = "Blob"
+ config_tag = "blob"
antag_datum = /datum/antagonist/blob
antag_flag = ROLE_BLOB
enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain")
@@ -374,6 +379,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph
name = "Alien Infestation"
+ config_tag = "xenos"
antag_datum = /datum/antagonist/xeno
antag_flag = ROLE_ALIEN
enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain")
@@ -420,6 +426,7 @@
/datum/dynamic_ruleset/midround/from_ghosts/nightmare
name = "Nightmare"
+ config_tag = "nightmare"
antag_datum = /datum/antagonist/nightmare
antag_flag = "Nightmare"
antag_flag_override = ROLE_ALIEN
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index 38ce6f68d0..6a9aefa996 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -7,6 +7,7 @@
/datum/dynamic_ruleset/roundstart/traitor
name = "Traitors"
+ config_tag = "traitor"
persistent = TRUE
antag_flag = ROLE_TRAITOR
antag_datum = /datum/antagonist/traitor/
@@ -48,6 +49,7 @@
/datum/dynamic_ruleset/roundstart/traitorbro
name = "Blood Brothers"
+ config_tag = "traitorbro"
antag_flag = ROLE_BROTHER
antag_datum = /datum/antagonist/brother/
restricted_roles = list("AI", "Cyborg")
@@ -100,6 +102,7 @@
/datum/dynamic_ruleset/roundstart/changeling
name = "Changelings"
+ config_tag = "changeling"
antag_flag = ROLE_CHANGELING
antag_datum = /datum/antagonist/changeling
restricted_roles = list("AI", "Cyborg")
@@ -149,6 +152,7 @@
// Dynamic is a wonderful thing that adds wizards to every round and then adds even more wizards during the round.
/datum/dynamic_ruleset/roundstart/wizard
name = "Wizard"
+ config_tag = "wizard"
antag_flag = ROLE_WIZARD
antag_datum = /datum/antagonist/wizard
minimum_required_age = 14
@@ -194,6 +198,7 @@
/datum/dynamic_ruleset/roundstart/bloodcult
name = "Blood Cult"
+ config_tag = "cult"
antag_flag = ROLE_CULTIST
antag_datum = /datum/antagonist/cult
minimum_required_age = 14
@@ -254,6 +259,7 @@
/datum/dynamic_ruleset/roundstart/nuclear
name = "Nuclear Emergency"
+ config_tag = "nuclear"
antag_flag = ROLE_OPERATIVE
antag_datum = /datum/antagonist/nukeop
var/datum/antagonist/antag_leader_datum = /datum/antagonist/nukeop/leader
@@ -343,6 +349,7 @@
/datum/dynamic_ruleset/roundstart/delayed/revs
name = "Revolution"
+ config_tag = "revolution"
persistent = TRUE
antag_flag = ROLE_REV_HEAD
antag_flag_override = ROLE_REV
@@ -433,6 +440,7 @@
/datum/dynamic_ruleset/roundstart/extended
name = "Extended"
+ config_tag = "extended"
antag_flag = null
antag_datum = null
restricted_roles = list()
@@ -456,6 +464,7 @@
/datum/dynamic_ruleset/roundstart/clockcult
name = "Clockcult"
+ config_tag = "clockwork_cult"
antag_flag = ROLE_SERVANT_OF_RATVAR
antag_datum = /datum/antagonist/clockcult
restricted_roles = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
@@ -559,6 +568,7 @@
/datum/dynamic_ruleset/roundstart/nuclear/clown_ops
name = "Clown Ops"
+ config_tag = "clownops"
antag_datum = /datum/antagonist/nukeop/clownop
antag_leader_datum = /datum/antagonist/nukeop/leader/clownop
requirements = list(101,101,101,101,101,101,101,101,101,101)
@@ -584,6 +594,7 @@
/datum/dynamic_ruleset/roundstart/devil
name = "Devil"
+ config_tag = "devil"
antag_flag = ROLE_DEVIL
antag_datum = /datum/antagonist/devil
restricted_roles = list("Lawyer", "Curator", "Chaplain", "Head of Security", "Captain", "AI")
@@ -642,6 +653,7 @@
/datum/dynamic_ruleset/roundstart/monkey
name = "Monkey"
+ config_tag = "monkey"
antag_flag = ROLE_MONKEY
antag_datum = /datum/antagonist/monkey/leader
restricted_roles = list("Cyborg", "AI")
@@ -704,6 +716,7 @@
/datum/dynamic_ruleset/roundstart/meteor
name = "Meteor"
+ config_tag = "meteor"
persistent = TRUE
required_candidates = 0
weight = 3
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 426d23b4ab..58f551c648 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -317,7 +317,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
/obj/effect/meteor/meaty/xeno/ram_turf(turf/T)
if(!isspaceturf(T))
- new /obj/effect/decal/cleanable/xenoblood(T)
+ new /obj/effect/decal/cleanable/blood/xeno(T)
//Station buster Tunguska
/obj/effect/meteor/tunguska
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 5a54ccd5df..1c6e21491c 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -80,7 +80,7 @@
popup.open()
/obj/machinery/autolathe/on_deconstruction()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params)
@@ -164,7 +164,7 @@
var/power = max(2000, (metal_cost+glass_cost)*multiplier/5)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff))
busy = TRUE
use_power(power)
@@ -188,7 +188,7 @@
return
/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
@@ -213,7 +213,7 @@
var/T = 0
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
T += MB.rating*75000
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
@@ -262,7 +262,7 @@
dat += "[D.name]"
if(ispath(D.build_path, /obj/item/stack))
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
if (max_multiplier>10 && !disabled)
dat += " x10"
@@ -294,7 +294,7 @@
dat += "[D.name]"
if(ispath(D.build_path, /obj/item/stack))
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
if (max_multiplier>10 && !disabled)
dat += " x10"
@@ -309,7 +309,7 @@
return dat
/obj/machinery/autolathe/proc/materials_printout()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
"
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
@@ -322,7 +322,7 @@
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
return FALSE
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
diff --git a/code/game/machinery/bloodbankgen.dm b/code/game/machinery/bloodbankgen.dm
new file mode 100644
index 0000000000..c489f6c9c9
--- /dev/null
+++ b/code/game/machinery/bloodbankgen.dm
@@ -0,0 +1,361 @@
+/obj/machinery/bloodbankgen
+ name = "blood bank generator"
+ desc = "Generates universally applicable synthetics for all blood types. Add regular blood to convert."
+ icon = 'icons/obj/bloodbank.dmi'
+ icon_state = "bloodbank-off"
+ density = TRUE
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 80
+ circuit = /obj/item/circuitboard/machine/bloodbankgen
+ interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_ALLOW_SILICON
+ var/draining = FALSE
+ var/filling = FALSE
+ var/obj/item/reagent_containers/blood/bag = null
+ var/obj/item/reagent_containers/blood/outbag = null
+ var/bloodstored = 0
+ var/maxbloodstored = 1000
+ var/menustat = "menu"
+ var/efficiency = 0
+ var/productivity = 0
+
+/obj/machinery/bloodbankgen/Initialize()
+ . = ..()
+ create_reagents(1000)
+ update_icon()
+
+/obj/machinery/bloodbankgen/Destroy()
+ QDEL_NULL(bag)
+ QDEL_NULL(outbag)
+ return ..()
+
+/obj/machinery/bloodbankgen/contents_explosion(severity, target)
+ ..()
+ if(bag)
+ bag.ex_act(severity, target)
+ if(outbag)
+ outbag.ex_act(severity, target)
+
+/obj/machinery/bloodbankgen/handle_atom_del(atom/A)
+ ..()
+ if(A == bag)
+ bag = null
+ update_icon()
+ updateUsrDialog()
+ if(A == outbag)
+ outbag = null
+ update_icon()
+ updateUsrDialog()
+
+/obj/machinery/bloodbankgen/RefreshParts()
+ var/E = 0
+ var/P = 0
+ for(var/obj/item/stock_parts/manipulator/M in component_parts)
+ E += M.rating
+ efficiency = E
+ productivity = P
+
+/obj/machinery/bloodbankgen/update_icon()
+ cut_overlays()
+ if(is_operational())
+ icon_state = "bloodbank-on"
+
+ if(panel_open)
+ add_overlay("bloodbank-panel")
+
+ if(src.bag)
+ add_overlay("bloodbag-input")
+ if(bag.reagents.total_volume)
+ var/mutable_appearance/filling_overlay = mutable_appearance(icon, "input-reagent")
+
+ var/percent = round((bag.reagents.total_volume / bag.volume) * 100)
+ switch(percent)
+ if(0 to 9)
+ filling_overlay.icon_state = "input-reagent0"
+ if(10 to 24)
+ filling_overlay.icon_state = "input-reagent10"
+ if(25 to 49)
+ filling_overlay.icon_state = "input-reagent25"
+ if(50 to 74)
+ filling_overlay.icon_state = "input-reagent50"
+ if(75 to 79)
+ filling_overlay.icon_state = "input-reagent75"
+ if(80 to 90)
+ filling_overlay.icon_state = "input-reagent80"
+ if(91 to INFINITY)
+ filling_overlay.icon_state = "input-reagent100"
+
+ filling_overlay.color = list(mix_color_from_reagents(bag.reagents.reagent_list))
+ add_overlay(filling_overlay)
+
+ if(src.outbag)
+ add_overlay("bloodbag-output")
+ if(outbag.reagents.total_volume)
+ var/mutable_appearance/filling_overlay = mutable_appearance(icon, "output-reagent")
+
+ var/percent = round((outbag.reagents.total_volume / outbag.volume) * 100)
+ switch(percent)
+ if(0 to 9)
+ filling_overlay.icon_state = "output-reagent0"
+ if(10 to 24)
+ filling_overlay.icon_state = "output-reagent10"
+ if(25 to 49)
+ filling_overlay.icon_state = "output-reagent25"
+ if(50 to 74)
+ filling_overlay.icon_state = "output-reagent50"
+ if(75 to 79)
+ filling_overlay.icon_state = "output-reagent75"
+ if(80 to 90)
+ filling_overlay.icon_state = "output-reagent80"
+ if(91 to INFINITY)
+ filling_overlay.icon_state = "output-reagent100"
+
+ filling_overlay.color = list(mix_color_from_reagents(outbag.reagents.reagent_list))
+ add_overlay(filling_overlay)
+ return
+
+/obj/machinery/bloodbankgen/process()
+ if(!is_operational())
+ return PROCESS_KILL
+
+ bloodstored = reagents.total_volume
+
+ var/transfer_amount = 20
+
+ if(draining)
+ if(reagents.total_volume >= reagents.maximum_volume)
+ draining = FALSE
+ return
+
+ if(bag)
+ if(bag.reagents.total_volume)
+ var/datum/reagent/blood/B = bag.reagents.has_reagent("blood")
+ if(B)
+ var/amount = reagents.maximum_volume - reagents.total_volume //monitor the machine's internal storage
+ amount = min(amount, transfer_amount)
+ if(!amount)
+ draining = FALSE
+ updateUsrDialog()
+ visible_message("[src] beeps loudly.")
+ playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ return
+
+ if(bag.blood_type == "SY") //no infinite loops using synthetics.
+ reagents.add_reagent("syntheticblood", amount)
+ else
+ reagents.add_reagent("syntheticblood", (amount+(5*efficiency)))
+
+ if(bag.reagents.total_volume >= amount)
+ bag.reagents.remove_reagent("blood", amount)
+ else
+ visible_message("[src] beeps loudly.")
+ playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
+ draining = FALSE
+
+ bag.update_icon()
+ update_icon()
+ updateUsrDialog()
+ else
+ draining = FALSE
+ updateUsrDialog()
+ return
+
+ if(filling)
+ if(!reagents || !reagents.total_volume)
+ filling = FALSE //there ain't anything in the machine yo.
+ return
+ if(outbag && outbag.reagents.total_volume < outbag.reagents.maximum_volume)
+ var/amount = outbag.reagents.maximum_volume - outbag.reagents.total_volume //monitor the output bag's internal storage
+ amount = min(amount, transfer_amount)
+ if(!amount)
+ filling = FALSE
+ visible_message("[src] pings.")
+ playsound(loc, 'sound/machines/beep.ogg', 50, 1)
+ updateUsrDialog()
+ return
+
+ reagents.trans_to(outbag, amount)
+ outbag.update_icon()
+ update_icon()
+ updateUsrDialog()
+ else
+ visible_message("[src] pings.")
+ playsound(loc, 'sound/machines/beep.ogg', 50, 1)
+ filling = FALSE
+ updateUsrDialog()
+ return
+
+/obj/machinery/bloodbankgen/attackby(obj/item/O, mob/user, params)
+ if(user.a_intent == INTENT_HARM)
+ return ..()
+
+ if(default_deconstruction_screwdriver(user, "bloodbank-off", "bloodbank-off", O))
+ if(bag)
+ var/obj/item/reagent_containers/blood/B = bag
+ B.forceMove(drop_location())
+ bag = null
+ if(outbag)
+ var/obj/item/reagent_containers/blood/B = outbag
+ B.forceMove(drop_location())
+ outbag = null
+ update_icon()
+ return
+
+ if(default_deconstruction_crowbar(O))
+ return
+
+ if(istype(O, /obj/item/reagent_containers/blood))
+ . = 1 //no afterattack
+ if(!panel_open)
+ if(bag && outbag)
+ to_chat(user, "This machine already has bags attached.")
+
+ if(!bag && !outbag)
+ var/choice = alert(user, "Choose where to place [O]", "", "Input", "Cancel", "Output")
+ switch(choice)
+ if("Cancel")
+ return FALSE
+ if("Input")
+ attachinput(O, user)
+ if("Output")
+ attachoutput(O, user)
+ else if(!bag)
+ attachinput(O, user)
+ else if(!outbag)
+ attachoutput(O, user)
+ else
+ to_chat(user, "Close the maintenance panel first.")
+ return
+
+ else
+ to_chat(user, "You cannot put this in [src]!")
+
+/obj/machinery/bloodbankgen/ui_interact(mob/user)
+ . = ..()
+
+ if(!is_operational())
+ return
+
+ var/dat
+ switch(menustat)
+ if("noblood")
+ dat += "You do not have enough blood product to create synthetics.
"
+ menustat = "menu"
+ if("complete")
+ dat += "Operation complete.
"
+ menustat = "menu"
+ if("nobagspace")
+ dat += "Not enough space left in container. Please replace receptical.
"
+ menustat = "menu"
+
+ dat+= "
Current Synthetics stockpile: [reagents.total_volume] units.
"
+
+ dat += "
Supply Bag
"
+ if(bag)
+ dat += "
Current Capacity: [bag.reagents.total_volume] of [bag.reagents.maximum_volume]"
+ if(bag.reagents && bag.reagents.total_volume)
+ dat += "
Drain"
+
+ dat += "
Detach"
+
+
+ dat += "
Synthetics Bag
"
+ if(outbag)
+ dat += "
Current Capacity:[outbag.reagents.total_volume] of [outbag.reagents.maximum_volume]"
+ if(!(outbag.reagents.total_volume >= outbag.reagents.maximum_volume))
+ dat += "
Fill"
+ dat += "
Detach"
+
+ if(!bag && !outbag)
+ dat += "No containers inside, please insert container.
"
+
+ var/datum/browser/popup = new(user, "bloodbankgen", name, 350, 520)
+ popup.set_content(dat)
+ popup.open()
+
+/obj/machinery/bloodbankgen/proc/activateinput()
+ if(bag)
+ draining = TRUE
+ update_icon()
+ else
+ to_chat(usr, "There is no blood bag in the input slot.")
+ return
+
+/obj/machinery/bloodbankgen/proc/activateoutput()
+ if(outbag)
+ filling = TRUE
+ update_icon()
+ else
+ to_chat(usr, "There is no blood bag in the output slot.")
+ return
+
+/obj/machinery/bloodbankgen/proc/check_container_volume(list/reagents, multiplier = 1)
+ var/sum_reagents = 0
+ for(var/R in reagents)
+ sum_reagents += reagents[R]
+ sum_reagents *= multiplier
+
+ if(outbag.reagents.total_volume + sum_reagents > outbag.reagents.maximum_volume)
+ menustat = "nobagspace"
+ return FALSE
+
+ return TRUE
+
+/obj/machinery/bloodbankgen/proc/detachinput()
+ if(bag)
+ bag.forceMove(drop_location())
+ if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
+ usr.put_in_hands(bag)
+ bag = null
+ update_icon()
+
+/obj/machinery/bloodbankgen/proc/detachoutput()
+ if(outbag)
+ outbag.forceMove(drop_location())
+ if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
+ usr.put_in_hands(outbag)
+ outbag = null
+ update_icon()
+
+/obj/machinery/bloodbankgen/proc/attachinput(obj/item/O, mob/user)
+ if(!bag)
+ if(!user.transferItemToLoc(O, src))
+ return
+ bag = O
+ to_chat(user, "You add [O] to the machine's input slot.")
+ update_icon()
+ updateUsrDialog()
+ else
+ to_chat(user, "There is already something in this slot!")
+
+/obj/machinery/bloodbankgen/proc/attachoutput(obj/item/O, mob/user)
+ if(!outbag)
+ if(!user.transferItemToLoc(O, src))
+ return
+ outbag = O
+ to_chat(user, "You add [O] to the machine's output slot.")
+ update_icon()
+ updateUsrDialog()
+ else
+ to_chat(user, "There is already something in this slot!")
+
+/obj/machinery/bloodbankgen/Topic(href, href_list)
+ if(..() || panel_open)
+ return
+
+ usr.set_machine(src)
+
+ if(href_list["activateinput"])
+ activateinput()
+ updateUsrDialog()
+
+ else if(href_list["detachinput"])
+ detachinput()
+ updateUsrDialog()
+
+ else if(href_list["activateoutput"])
+ activateoutput()
+ updateUsrDialog()
+
+ else if(href_list["detachoutput"])
+ detachoutput()
+ updateUsrDialog()
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
index 692bc8f038..67407d220e 100644
--- a/code/game/machinery/computer/telecrystalconsoles.dm
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -33,7 +33,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder)
to_chat(user, "[src] already has an uplink in it.")
return
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
+ var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
if(hidden_uplink)
if(!user.transferItemToLoc(I, src))
return
@@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
+ var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
if(amt < 0)
linkedboss.storedcrystals += hidden_uplink.telecrystals
if(addLog)
@@ -71,7 +71,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
+ var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
if(amt < 0)
hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog)
@@ -94,7 +94,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
dat += "No linked management consoles detected. Scan for uplink stations using the management console.
"
if(uplinkholder)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
+ var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.
"
if(linkedboss)
dat += "Donate TC: 1 | 5 | All"
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
dat += "[A.name] | "
if(A.uplinkholder)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, A.uplinkholder)
+ var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink)
dat += "[hidden_uplink.telecrystals] telecrystals."
if(storedcrystals)
dat+= "
Add TC: 1 | 5 | 10 | All"
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index a2da7de29a..3ac386e1fb 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -326,7 +326,7 @@
else //for simple_animals & borgs
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
var/turf/location = get_turf(src)
- //add_blood doesn't work for borgs/xenos, but add_blood_floor does.
+ //add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does.
if(iscarbon(L))
var/mob/living/carbon/C = L
C.bleed(DOOR_CRUSH_DAMAGE)
diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm
index 7c92c158b3..b121057315 100644
--- a/code/game/machinery/droneDispenser.dm
+++ b/code/game/machinery/droneDispenser.dm
@@ -146,7 +146,7 @@
if((stat & (NOPOWER|BROKEN)) || !anchored)
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(!materials.has_materials(using_materials))
return // We require more minerals
@@ -211,7 +211,7 @@
/obj/machinery/droneDispenser/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/crowbar))
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
I.play_tool_sound(src)
to_chat(user, "You retrieve the materials from [src].")
diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm
index 6b944f762d..a2d0460d25 100644
--- a/code/game/machinery/gulag_teleporter.dm
+++ b/code/game/machinery/gulag_teleporter.dm
@@ -135,18 +135,19 @@ The console is located at computer/gulag_teleporter.dm
if(linked_reclaimer)
linked_reclaimer.stored_items[occupant] = list()
var/mob/living/mob_occupant = occupant
- for(var/obj/item/W in mob_occupant)
- if(!is_type_in_typecache(W, telegulag_required_items))
- if(mob_occupant.temporarilyRemoveItemFromInventory(W))
- if(istype(W, /obj/item/restraints/handcuffs))
- W.forceMove(get_turf(src))
- continue
- if(linked_reclaimer)
- linked_reclaimer.stored_items[mob_occupant] += W
- linked_reclaimer.contents += W
- W.forceMove(linked_reclaimer)
- else
- W.forceMove(src)
+ for(var/A in mob_occupant.get_equipped_items(TRUE))
+ var/obj/item/I = A
+ if(is_type_in_typecache(I, telegulag_required_items) || !mob_occupant.temporarilyRemoveItemFromInventory(I))
+ continue
+ if(istype(I, /obj/item/restraints/handcuffs))
+ I.forceMove(get_turf(src))
+ continue
+ if(linked_reclaimer)
+ linked_reclaimer.stored_items[mob_occupant] += I
+ linked_reclaimer.contents += I
+ I.forceMove(linked_reclaimer)
+ else
+ I.forceMove(src)
/obj/machinery/gulag_teleporter/proc/handle_prisoner(obj/item/id, datum/data/record/R)
if(!ishuman(occupant))
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index b217c14e53..621ca266bb 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -8,14 +8,14 @@
icon_state = "iv_drip"
anchored = FALSE
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
- var/mob/living/carbon/attached = null
+ var/mob/living/carbon/attached
var/mode = IV_INJECTING
- var/obj/item/reagent_containers/beaker = null
+ var/obj/item/reagent_containers/beaker
var/static/list/drip_containers = typecacheof(list(/obj/item/reagent_containers/blood,
/obj/item/reagent_containers/food,
/obj/item/reagent_containers/glass))
-/obj/machinery/iv_drip/Initialize()
+/obj/machinery/iv_drip/Initialize(mapload)
. = ..()
update_icon()
@@ -84,6 +84,8 @@
if(Adjacent(target) && usr.Adjacent(target))
if(beaker)
usr.visible_message("[usr] attaches [src] to [target].", "You attach [src] to [target].")
+ log_combat(usr, target, "attached", src, "containing: [beaker.name] - ([beaker.reagents.log_list()])")
+ add_fingerprint(usr)
attached = target
START_PROCESSING(SSmachines, src)
update_icon()
@@ -100,6 +102,8 @@
return
beaker = W
to_chat(user, "You attach [W] to [src].")
+ user.log_message("attached a [W] to [src] at [AREACOORD(src)] containing ([beaker.reagents.log_list()])", LOG_ATTACK)
+ add_fingerprint(user)
update_icon()
return
else
@@ -142,10 +146,11 @@
if(!amount)
if(prob(5))
visible_message("[src] pings.")
+ playsound(loc, 'sound/machines/beep.ogg', 50, 1)
return
// If the human is losing too much blood, beep.
- if(attached.blood_volume < ( (BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) ) )
+ if(attached.blood_volume < ((BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) && ishuman(attached))) //really couldn't care less about monkeys
visible_message("[src] beeps loudly.")
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
attached.transfer_blood_to(beaker, amount)
@@ -178,9 +183,10 @@
if(usr.incapacitated())
return
-
if(beaker)
- beaker.forceMove(drop_location())
+ if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
+ if(!usr.put_in_hands(beaker))
+ beaker.forceMove(drop_location())
beaker = null
update_icon()
@@ -195,27 +201,27 @@
if(usr.incapacitated())
return
-
mode = !mode
to_chat(usr, "The IV drip is now [mode ? "injecting" : "taking blood"].")
update_icon()
/obj/machinery/iv_drip/examine(mob/user)
- ..()
+ . = ..()
if(get_dist(user, src) > 2)
return
- to_chat(user, "The IV drip is [mode ? "injecting" : "taking blood"].")
+ . += "[src] is [mode ? "injecting" : "taking blood"].\n"
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
- to_chat(user, "Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.")
+ . += "\tAttached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.\n"
else
- to_chat(user, "Attached is an empty [beaker.name].")
+ . += "\tAttached is an empty [beaker.name].\n"
else
- to_chat(user, "No chemicals are attached.")
+ . += "\tNo chemicals are attached.\n"
- to_chat(user, "[attached ? attached : "No one"] is attached.")
+ . += "\t[attached ? attached : "No one"] is attached."
+ to_chat(user,.)
#undef IV_TAKING
-#undef IV_INJECTING
+#undef IV_INJECTING
\ No newline at end of file
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 90de34a22d..1a8bc7ece4 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -32,10 +32,10 @@
mat_mod *= 50000
for(var/obj/item/stock_parts/manipulator/M in component_parts)
amt_made = 12.5 * M.rating //% of materials salvaged
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = mat_mod
amount_produced = min(50, amt_made) + 50
- GET_COMPONENT(butchering, /datum/component/butchering)
+ var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.effectiveness = amount_produced
butchering.bonus_modifier = amount_produced/5
@@ -144,7 +144,7 @@
qdel(L)
return
else
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(I)
if(!material_amount)
qdel(I)
@@ -195,7 +195,7 @@
L.Unconscious(100)
L.adjustBruteLoss(crush_damage)
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
- GET_COMPONENT(butchering, /datum/component/butchering)
+ var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.Butcher(src,L)
/obj/machinery/recycler/deathtrap
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index d308d180d0..f35caf514c 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -265,6 +265,8 @@
things_to_clear += occupant.GetAllContents()
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
+ AM.clean_blood()
+ AM.fingerprints = list()
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
if(contamination)
qdel(contamination)
@@ -435,4 +437,4 @@
if(I)
I.forceMove(loc)
. = TRUE
- update_icon()
+ update_icon()
\ No newline at end of file
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 5e8515d3d5..8be079656b 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -11,10 +11,6 @@
var/obj/item/color_source
var/max_wash_capacity = 5
-/obj/machinery/washing_machine/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
-
/obj/machinery/washing_machine/examine(mob/user)
..()
to_chat(user, "Alt-click it to start a wash cycle.")
@@ -59,7 +55,8 @@
M.Translate(rand(-3, 3), rand(-1, 3))
animate(src, transform=M, time=2)
-/obj/machinery/washing_machine/proc/clean_blood()
+/obj/machinery/washing_machine/clean_blood()
+ ..()
if(!busy)
bloody_mess = FALSE
update_icon()
@@ -67,7 +64,8 @@
/obj/machinery/washing_machine/proc/wash_cycle()
for(var/X in contents)
var/atom/movable/AM = X
- SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ AM.clean_blood()
AM.machine_wash(src)
busy = FALSE
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm
index eb3261bb27..4044951c42 100644
--- a/code/game/mecha/equipment/tools/mining_tools.dm
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -100,12 +100,12 @@
/obj/item/mecha_parts/mecha_equipment/drill/attach(obj/mecha/M)
..()
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = TRUE
/obj/item/mecha_parts/mecha_equipment/drill/detach(atom/moveto)
..()
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = FALSE
/obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user)
@@ -115,7 +115,7 @@
if(target.stat == DEAD && target.getBruteLoss() >= 200)
log_combat(user, target, "gibbed", name)
if(LAZYLEN(target.butcher_results) || LAZYLEN(target.guaranteed_butcher_results))
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.Butcher(chassis, target)
else
target.gib()
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index e1dc80911f..4acf7981bc 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -47,7 +47,7 @@
//maximum stocking amount (default 300000, 600000 at T4)
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
T += M.rating
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = (200000 + (T*50000))
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
@@ -109,7 +109,7 @@
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
output += "[M.name]: [M.amount] cm³"
@@ -130,7 +130,7 @@
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(D.reagents_list.len) // No reagents storage - no reagent designs.
return FALSE
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(materials.has_materials(get_resources_w_coeff(D)))
return TRUE
return FALSE
@@ -140,7 +140,7 @@
desc = "It's building \a [initial(D.name)]."
var/list/res_coef = get_resources_w_coeff(D)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_amount(res_coef)
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
@@ -384,14 +384,14 @@
break
if(href_list["remove_mat"] && href_list["material"])
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"])
updateUsrDialog()
return
/obj/machinery/mecha_part_fabricator/on_deconstruction()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
..()
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index ef3ba969e9..19656f2d7d 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -47,7 +47,7 @@
/obj/mecha/working/ripley/update_icon()
..()
- GET_COMPONENT(C,/datum/component/armor_plate)
+ var/datum/component/armor_plate/C = GetComponent(/datum/component/armor_plate)
if (C.amount)
cut_overlays()
if(C.amount < 3)
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index d5aff99f32..2eb4a6aa0c 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -8,6 +8,7 @@
/obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases)
. = ..()
+ LAZYINITLIST(blood_DNA) //Kinda needed
if (random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0)
icon_state = pick(random_icon_states)
create_reagents(300)
@@ -27,7 +28,7 @@
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
if(mergeable_decal)
- return TRUE
+ qdel(C)
/obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
@@ -81,7 +82,9 @@
add_blood = bloodiness
bloodiness -= add_blood
S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS,S.bloody_shoes[blood_state]+add_blood)
- S.add_blood_DNA(return_blood_DNA())
+ if(blood_DNA && blood_DNA.len)
+ S.add_blood_DNA(blood_DNA)
+ S.add_blood_overlay()
S.blood_state = blood_state
update_icon()
H.update_inv_shoes()
@@ -90,4 +93,4 @@
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
return bloodiness
else
- return 0
+ return FALSE
diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm
index ca2a8ccaff..a4d0da1bbe 100644
--- a/code/game/objects/effects/decals/cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/cleanable/aliens.dm
@@ -1,71 +1,70 @@
-// Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code.
-/obj/effect/decal/cleanable/xenoblood
+/obj/effect/decal/cleanable/blood/xeno
name = "xeno blood"
desc = "It's green and acidic. It looks like... blood?"
- icon = 'icons/effects/blood.dmi'
- icon_state = "xfloor1"
- random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
- bloodiness = BLOOD_AMOUNT_PER_DECAL
- blood_state = BLOOD_STATE_XENO
+ color = BLOOD_COLOR_XENO
-/obj/effect/decal/cleanable/xenoblood/Initialize()
+/obj/effect/decal/cleanable/blood/splatter/xeno
+ color = BLOOD_COLOR_XENO
+
+/obj/effect/decal/cleanable/blood/gibs/xeno
+ color = BLOOD_COLOR_XENO
+ gibs_reagent_id = "liquidxenogibs"
+ gibs_bloodtype = "X*"
+
+/obj/effect/decal/cleanable/blood/gibs/xeno/Initialize(mapload, list/datum/disease/diseases)
. = ..()
- add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ update_icon()
-/obj/effect/decal/cleanable/xenoblood/xsplatter
- random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5")
+/obj/effect/decal/cleanable/blood/gibs/xeno/update_icon()
+ add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/flesh = mutable_appearance(icon, "[icon_state]x_flesh")
+ flesh.appearance_flags = RESET_COLOR
+ flesh.color = body_colors
+ add_overlay(flesh)
-/obj/effect/decal/cleanable/xenoblood/xgibs
- name = "xeno gibs"
- desc = "Gnarly..."
- icon = 'icons/effects/blood.dmi'
- icon_state = "xgib1"
- layer = LOW_OBJ_LAYER
- random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
- mergeable_decal = FALSE
-
-/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(list/directions)
- set waitfor = 0
+/obj/effect/decal/cleanable/blood/gibs/xeno/streak(list/directions)
+ set waitfor = FALSE
+ var/list/diseases = list()
+ SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions, diseases)
var/direction = pick(directions)
- for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++)
+ for(var/i in 0 to pick(0, 200; 1, 150; 2, 50))
sleep(2)
if(i > 0)
- new /obj/effect/decal/cleanable/xenoblood/xsplatter(loc)
+ var/obj/effect/decal/cleanable/blood/splatter/xeno/splat = new /obj/effect/decal/cleanable/blood/splatter/xeno(loc, diseases)
+ splat.transfer_blood_dna(blood_DNA, diseases)
if(!step_to(src, get_step(src, direction), 0))
break
-/obj/effect/decal/cleanable/xenoblood/xgibs/ex_act()
- return
+/obj/effect/decal/cleanable/blood/gibs/xeno/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
-/obj/effect/decal/cleanable/xenoblood/xgibs/up
- random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibup1","xgibup1","xgibup1")
+/obj/effect/decal/cleanable/blood/gibs/xeno/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
-/obj/effect/decal/cleanable/xenoblood/xgibs/down
- random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibdown1","xgibdown1","xgibdown1")
+/obj/effect/decal/cleanable/blood/gibs/xeno/body
+ random_icon_states = list("gibhead", "gibtorso")
-/obj/effect/decal/cleanable/xenoblood/xgibs/body
- random_icon_states = list("xgibhead", "xgibtorso")
+/obj/effect/decal/cleanable/blood/gibs/xeno/torso
+ random_icon_states = list("gibtorso")
-/obj/effect/decal/cleanable/xenoblood/xgibs/torso
- random_icon_states = list("xgibtorso")
+/obj/effect/decal/cleanable/blood/gibs/xeno/limb
+ random_icon_states = list("gibleg", "gibarm")
-/obj/effect/decal/cleanable/xenoblood/xgibs/limb
- random_icon_states = list("xgibleg", "xgibarm")
+/obj/effect/decal/cleanable/blood/gibs/xeno/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-/obj/effect/decal/cleanable/xenoblood/xgibs/core
- random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3")
-
-/obj/effect/decal/cleanable/xenoblood/xgibs/larva
+/obj/effect/decal/cleanable/blood/gibs/xeno/larva
random_icon_states = list("xgiblarva1", "xgiblarva2")
-/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body
+/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body
random_icon_states = list("xgiblarvahead", "xgiblarvatorso")
/obj/effect/decal/cleanable/blood/xtracks
- icon_state = "xtracks"
+ icon_state = "tracks"
random_icon_states = null
/obj/effect/decal/cleanable/blood/xtracks/Initialize()
- . = ..()
- add_blood_DNA(list("Unknown DNA" = "X*"))
+ add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ . = ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm
new file mode 100644
index 0000000000..03eeca7d0b
--- /dev/null
+++ b/code/game/objects/effects/decals/cleanable/gibs.dm
@@ -0,0 +1,231 @@
+/obj/effect/decal/cleanable/blood/gibs
+ name = "gibs"
+ desc = "They look bloody and gruesome."
+ icon_state = "gibbl5"
+ layer = LOW_OBJ_LAYER
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
+ mergeable_decal = FALSE
+ var/body_colors = "#e3ba84" //a default color just in case.
+ var/gibs_reagent_id = "liquidgibs"
+ var/gibs_bloodtype = "A+"
+
+/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ if(random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0)
+ icon_state = pick(random_icon_states)
+ if(gibs_reagent_id)
+ reagents.add_reagent(gibs_reagent_id, 5)
+ if(gibs_bloodtype)
+ add_blood_DNA(list("Non-human DNA" = gibs_bloodtype, diseases))
+ update_icon()
+
+
+/obj/effect/decal/cleanable/blood/gibs/update_icon()
+ add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/guts = mutable_appearance(icon, "[icon_state]_guts")
+ guts.appearance_flags = RESET_COLOR
+ add_overlay(guts)
+ var/mutable_appearance/flesh = mutable_appearance(icon, "[icon_state]_flesh")
+ flesh.appearance_flags = RESET_COLOR
+ flesh.color = body_colors
+ add_overlay(flesh)
+
+/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
+ return
+
+/obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L)
+ if(istype(L) && has_gravity(loc))
+ playsound(loc, 'sound/effects/gib_step.ogg', !HAS_TRAIT(L,TRAIT_LIGHT_STEP) ? 20 : 50, 1)
+ . = ..()
+
+/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions)
+ set waitfor = FALSE
+ var/list/diseases = list()
+ SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions, diseases)
+ var/direction = pick(directions)
+ for(var/i in 0 to pick(0, 200; 1, 150; 2, 50))
+ sleep(2)
+ if(i > 0)
+ var/obj/effect/decal/cleanable/blood/splatter/splat = new /obj/effect/decal/cleanable/blood/splatter(loc, diseases)
+ splat.transfer_blood_dna(blood_DNA, diseases)
+ if(!step_to(src, get_step(src, direction), 0))
+ break
+
+/obj/effect/decal/cleanable/blood/gibs/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+/obj/effect/decal/cleanable/blood/gibs/old
+ name = "old rotting gibs"
+ desc = "Space Jesus, why didn't anyone clean this up? It smells terrible."
+ bloodiness = 0
+
+/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ setDir(pick(GLOB.cardinals))
+ icon_state += "-old"
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/drip
+ name = "drips of blood"
+ desc = "It's gooey."
+ icon_state = "1"
+ random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
+ bloodiness = 0
+ var/drips = 1
+
+/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
+ return TRUE
+
+/obj/effect/decal/cleanable/blood/gibs/human
+
+/obj/effect/decal/cleanable/blood/gibs/human/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/human/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/human/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+
+//Lizards
+/obj/effect/decal/cleanable/blood/gibs/human/lizard
+ body_colors = "117720"
+ gibs_reagent_id = "liquidgibs"
+ gibs_bloodtype = "L"
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+// Slime Gibs
+/obj/effect/decal/cleanable/blood/gibs/slime
+ desc = "They look gooey and gruesome."
+ gibs_reagent_id = "liquidslimegibs"
+ gibs_bloodtype = "GEL"
+
+/obj/effect/decal/cleanable/blood/gibs/slime/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/slime/update_icon()
+ add_atom_colour(body_colors, FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/guts = mutable_appearance(icon, "[icon_state]s_guts")
+ guts.appearance_flags = RESET_COLOR
+ guts.color = body_colors
+ add_overlay(guts)
+ var/mutable_appearance/flesh = mutable_appearance(icon, "[icon_state]_flesh")
+ flesh.appearance_flags = RESET_COLOR
+ flesh.color = body_colors
+ add_overlay(flesh)
+
+/obj/effect/decal/cleanable/blood/gibs/slime/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+/obj/effect/decal/cleanable/blood/gibs/synth
+ desc = "They look sludgy and disgusting."
+ gibs_reagent_id = "liquidsyntheticgibs"
+ gibs_bloodtype = "SY"
+
+/obj/effect/decal/cleanable/blood/gibs/synth/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+//IPCs
+/obj/effect/decal/cleanable/blood/gibs/ipc
+ desc = "They look sharp yet oozing."
+ body_colors = "00ff00"
+ gibs_reagent_id = "liquidoilgibs"
+ gibs_bloodtype = "HF"
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/update_icon()
+ add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/guts = mutable_appearance(icon, "[icon_state]r-overlay")
+ guts.appearance_flags = RESET_COLOR
+ add_overlay(guts)
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 35f06c2768..842b230b53 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -1,31 +1,45 @@
/obj/effect/decal/cleanable/blood
name = "blood"
- desc = "It's red and gooey. Perhaps it's the chef's cooking?"
+ desc = "It's gooey. Perhaps it's the chef's cooking?"
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
- blood_state = BLOOD_STATE_HUMAN
- bloodiness = BLOOD_AMOUNT_PER_DECAL
+ blood_state = BLOOD_STATE_BLOOD
+ bloodiness = MAX_SHOE_BLOODINESS
+ color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere.
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
- C.add_blood_DNA(return_blood_DNA())
- if (bloodiness)
- if (C.bloodiness < MAX_SHOE_BLOODINESS)
- C.bloodiness += bloodiness
- return ..()
+ if (C.blood_DNA)
+ blood_DNA |= C.blood_DNA.Copy()
+ update_icon()
+ ..()
+
+/obj/effect/decal/cleanable/blood/transfer_blood_dna()
+ ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/transfer_mob_blood_dna()
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/update_icon()
+ color = blood_DNA_to_color()
/obj/effect/decal/cleanable/blood/old
name = "dried blood"
- desc = "Looks like it's been here a while. Eew."
+ desc = "Looks like it's been here a while. Eew."
bloodiness = 0
/obj/effect/decal/cleanable/blood/old/Initialize(mapload, list/datum/disease/diseases)
- icon_state += "-old" //This IS necessary because the parent /blood type uses icon randomization.
- add_blood_DNA(list("Non-human DNA" = "A+")) // Needs to happen before ..()
- return ..()
+ ..()
+ icon_state += "-old"
+ add_blood_DNA(list("Non-human DNA" = "A+"))
+
+/obj/effect/decal/cleanable/blood/splats
+ random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
/obj/effect/decal/cleanable/blood/splatter
- random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
+ random_icon_states = list("splatter1", "splatter2", "splatter3", "splatter4", "splatter5")
/obj/effect/decal/cleanable/blood/tracks
icon_state = "tracks"
@@ -39,84 +53,23 @@
random_icon_states = null
var/list/existing_dirs = list()
+/obj/effect/decal/cleanable/trail_holder/update_icon()
+ color = blood_DNA_to_color()
+
+/obj/effect/cleanable/trail_holder/Initialize()
+ . = ..()
+ update_icon()
+
/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
return TRUE
-/obj/effect/decal/cleanable/blood/gibs
- name = "gibs"
- desc = "They look bloody and gruesome."
- icon = 'icons/effects/blood.dmi'
- icon_state = "gibbl5"
- layer = LOW_OBJ_LAYER
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
- mergeable_decal = FALSE
+/obj/effect/decal/cleanable/trail_holder/transfer_blood_dna()
+ ..()
+ update_icon()
-/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases)
+/obj/effect/decal/cleanable/trail_holder/transfer_mob_blood_dna()
. = ..()
- reagents.add_reagent("liquidgibs", 5)
-
-/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
- return
-
-/obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L)
- if(istype(L) && has_gravity(loc))
- playsound(loc, 'sound/effects/gib_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 20 : 50, 1)
- . = ..()
-
-/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions)
- set waitfor = 0
- var/direction = pick(directions)
- for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++)
- sleep(2)
- if(i > 0)
- var/list/datum/disease/diseases
- GET_COMPONENT(infective, /datum/component/infective)
- if(infective)
- diseases = infective.diseases
- new /obj/effect/decal/cleanable/blood/splatter(loc, diseases)
- if(!step_to(src, get_step(src, direction), 0))
- break
-
-/obj/effect/decal/cleanable/blood/gibs/up
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
-
-/obj/effect/decal/cleanable/blood/gibs/down
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
-
-/obj/effect/decal/cleanable/blood/gibs/body
- random_icon_states = list("gibhead", "gibtorso")
-
-/obj/effect/decal/cleanable/blood/gibs/torso
- random_icon_states = list("gibtorso")
-
-/obj/effect/decal/cleanable/blood/gibs/limb
- random_icon_states = list("gibleg", "gibarm")
-
-/obj/effect/decal/cleanable/blood/gibs/core
- random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-
-/obj/effect/decal/cleanable/blood/gibs/old
- name = "old rotting gibs"
- desc = "Space Jesus, why didn't anyone clean this up? It smells terrible."
- bloodiness = 0
-
-/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases)
- . = ..()
- setDir(pick(1,2,4,8))
- icon_state += "-old"
- add_blood_DNA(list("Non-human DNA" = "A+"))
-
-/obj/effect/decal/cleanable/blood/drip
- name = "drips of blood"
- desc = "It's red."
- icon_state = "1"
- random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
- bloodiness = 0
- var/drips = 1
-
-/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
- return TRUE
-
+ update_icon()
//BLOODY FOOTPRINTS
/obj/effect/decal/cleanable/blood/footprints
@@ -127,15 +80,16 @@
random_icon_states = null
var/entered_dirs = 0
var/exited_dirs = 0
- blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
+ blood_state = BLOOD_STATE_BLOOD //the icon state to load images from
var/list/shoe_types = list()
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
- ..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.bloody_shoes[blood_state])
+ if(color != bloodtype_to_color(S.last_bloodtype))
+ return
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
shoe_types |= S.type
if (!(entered_dirs & H.dir))
@@ -143,21 +97,21 @@
update_icon()
/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
- ..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.bloody_shoes[blood_state])
+ if(color != bloodtype_to_color(S.last_bloodtype))//last entry - we check its color
+ return
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
shoe_types |= S.type
if (!(exited_dirs & H.dir))
exited_dirs |= H.dir
update_icon()
-
/obj/effect/decal/cleanable/blood/footprints/update_icon()
+ ..()
cut_overlays()
-
for(var/Ddir in GLOB.cardinals)
if(entered_dirs & Ddir)
var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[blood_state]-[Ddir]"]
@@ -170,7 +124,7 @@
GLOB.bloody_footprints_cache["exited-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]2", dir = Ddir)
add_overlay(bloodstep_overlay)
- alpha = BLOODY_FOOTPRINT_BASE_ALPHA+bloodiness
+ alpha = BLOODY_FOOTPRINT_BASE_ALPHA + bloodiness
/obj/effect/decal/cleanable/blood/footprints/examine(mob/user)
@@ -179,16 +133,62 @@
. += "You recognise the footprints as belonging to:\n"
for(var/shoe in shoe_types)
var/obj/item/clothing/shoes/S = shoe
- . += "[icon2html(initial(S.icon), user)] Some [initial(S.name)].\n"
+ . += "some [initial(S.name)] [icon2html(initial(S.icon), user)]\n"
to_chat(user, .)
/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/C)
if(blood_state != C.blood_state) //We only replace footprints of the same type as us
return
+ if(color != C.color)
+ return
..()
/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
- return 1
- return 0
+ return TRUE
+ return FALSE
+
+/* Eventually TODO: make snowflake trails like baycode's
+/obj/effect/decal/cleanable/blood/footprints/tracks/shoe
+ name = "footprints"
+ desc = "They look like tracks left by footwear."
+ icon_state = FOOTPRINT_SHOE
+ print_state = FOOTPRINT_SHOE
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/foot
+ name = "footprints"
+ desc = "They look like tracks left by a bare foot."
+ icon_state = FOOTPRINT_FOOT
+ print_state = FOOTPRINT_FOOT
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/snake
+ name = "tracks"
+ desc = "They look like tracks left by a giant snake."
+ icon_state = FOOTPRINT_SNAKE
+ print_state = FOOTPRINT_SNAKE
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/paw
+ name = "footprints"
+ desc = "They look like tracks left by paws."
+ icon_state = FOOTPRINT_PAW
+ print_state = FOOTPRINT_PAW
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/claw
+ name = "footprints"
+ desc = "They look like tracks left by claws."
+ icon_state = FOOTPRINT_CLAW
+ print_state = FOOTPRINT_CLAW
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/wheels
+ name = "tracks"
+ desc = "They look like tracks left by wheels."
+ gender = PLURAL
+ icon_state = FOOTPRINT_WHEEL
+ print_state = FOOTPRINT_WHEEL
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/body
+ name = "trails"
+ desc = "A trail left by something being dragged."
+ icon_state = FOOTPRINT_DRAG
+ print_state = FOOTPRINT_DRAG */
diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm
index 484e0438e2..02bf51bdd9 100644
--- a/code/game/objects/effects/decals/cleanable/robots.dm
+++ b/code/game/objects/effects/decals/cleanable/robots.dm
@@ -11,6 +11,10 @@
bloodiness = BLOOD_AMOUNT_PER_DECAL
mergeable_decal = FALSE
+/obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ reagents.add_reagent("liquidoilgibs", 5)
+
/obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions)
set waitfor = 0
var/direction = pick(directions)
@@ -50,6 +54,7 @@
/obj/effect/decal/cleanable/oil/Initialize()
. = ..()
reagents.add_reagent("oil", 30)
+ reagents.add_reagent("liquidoilgibs", 5)
/obj/effect/decal/cleanable/oil/streak
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm
index de17582f27..6c9525008d 100644
--- a/code/game/objects/effects/proximity.dm
+++ b/code/game/objects/effects/proximity.dm
@@ -5,7 +5,6 @@
var/list/checkers //list of /obj/effect/abstract/proximity_checkers
var/current_range
var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf
- var/datum/component/movement_tracker
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
checkers = list()
@@ -15,15 +14,17 @@
SetHost(_host)
/datum/proximity_monitor/proc/SetHost(atom/H,atom/R)
+ if(H == host)
+ return
+ if(host)
+ UnregisterSignal(host, COMSIG_MOVABLE_MOVED)
if(R)
hasprox_receiver = R
else if(hasprox_receiver == host) //Default case
hasprox_receiver = H
host = H
+ RegisterSignal(host, COMSIG_MOVABLE_MOVED, .proc/HandleMove)
last_host_loc = host.loc
- if(movement_tracker)
- QDEL_NULL(movement_tracker)
- movement_tracker = host.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/HandleMove)))
SetRange(current_range,TRUE)
/datum/proximity_monitor/Destroy()
@@ -31,7 +32,6 @@
last_host_loc = null
hasprox_receiver = null
QDEL_LIST(checkers)
- QDEL_NULL(movement_tracker)
return ..()
/datum/proximity_monitor/proc/HandleMove()
diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm
index e99a2fcbc6..dd39bc567a 100644
--- a/code/game/objects/effects/spawners/gibspawner.dm
+++ b/code/game/objects/effects/spawners/gibspawner.dm
@@ -1,25 +1,69 @@
/obj/effect/gibspawner
- var/sparks = 0 //whether sparks spread
+ var/sparks = FALSE //whether sparks spread
var/virusProb = 20 //the chance for viruses to spread on the gibs
+ var/gib_mob_type //generate a fake mob to transfer DNA from if we weren't passed a mob.
+ var/gib_mob_species //We'll want to nip-pick their species for blood type stuff
+ var/sound_to_play = 'sound/effects/blobattack.ogg'
+ var/sound_vol = 60
var/list/gibtypes = list() //typepaths of the gib decals to spawn
var/list/gibamounts = list() //amount to spawn for each gib decal type we'll spawn.
var/list/gibdirections = list() //of lists of possible directions to spread each gib decal type towards.
-/obj/effect/gibspawner/Initialize(mapload, datum/dna/MobDNA, list/datum/disease/diseases)
+/obj/effect/gibspawner/Initialize(mapload, mob/living/source_mob, list/datum/disease/diseases)
. = ..()
-
- if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
- to_chat(world, "Gib list length mismatch!")
+ if(gibtypes.len != gibamounts.len)
+ stack_trace("Gib list amount length mismatch!")
+ return
+ if(gibamounts.len != gibdirections.len)
+ stack_trace("Gib list dir length mismatch!")
return
var/obj/effect/decal/cleanable/blood/gibs/gib = null
+ if(sound_to_play && isnum(sound_vol))
+ playsound(src, sound_to_play, sound_vol, TRUE)
+
if(sparks)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(2, 1, loc)
s.start()
+ var/list/dna_to_add //find the dna to pass to the spawned gibs. do note this can be null if the mob doesn't have blood. add_blood_DNA() has built in null handling.
+ var/body_coloring = ""
+ if(source_mob)
+ dna_to_add = source_mob.get_blood_dna_list() //ez pz
+ if(ishuman(source_mob))
+ var/mob/living/carbon/human/H = source_mob
+ if(H.dna.species.use_skintones)
+ body_coloring = "#[skintone2hex(H.skin_tone)]"
+ else
+ body_coloring = "#[H.dna.features["mcolor"]]"
+
+ else if(gib_mob_type)
+ var/mob/living/temp_mob = new gib_mob_type(src) //generate a fake mob so that we pull the right type of DNA for the gibs.
+ if(gib_mob_species)
+ if(ishuman(temp_mob))
+ var/mob/living/carbon/human/H = temp_mob
+ H.set_species(gib_mob_species)
+ dna_to_add = temp_mob.get_blood_dna_list()
+ if(H.dna.species.use_skintones)
+ body_coloring = "#[skintone2hex(H.skin_tone)]"
+ else
+ body_coloring = "#[H.dna.features["mcolor"]]"
+ qdel(H)
+ else
+ dna_to_add = temp_mob.get_blood_dna_list()
+ qdel(temp_mob)
+ else if(!issilicon(temp_mob))
+ dna_to_add = temp_mob.get_blood_dna_list()
+ qdel(temp_mob)
+ else
+ qdel(temp_mob)
+ else
+ dna_to_add = list("Non-human DNA" = random_blood_type()) //else, generate a random bloodtype for it.
+
+
for(var/i = 1, i<= gibtypes.len, i++)
if(gibamounts[i])
for(var/j = 1, j<= gibamounts[i], j++)
@@ -29,10 +73,11 @@
var/mob/living/carbon/digester = loc
digester.stomach_contents += gib
- if(MobDNA)
+ if(dna_to_add && dna_to_add.len)
+ gib.add_blood_DNA(dna_to_add)
+ gib.body_colors = body_coloring
+ gib.update_icon()
- else if(istype(src, /obj/effect/gibspawner/generic)) // Probably a monkey
- gib.add_blood_DNA(list("Non-human DNA" = "A+"))
var/list/directions = gibdirections[i]
if(isturf(loc))
if(directions.len)
@@ -41,80 +86,158 @@
return INITIALIZE_HINT_QDEL
-
/obj/effect/gibspawner/generic
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core)
- gibamounts = list(2,2,1)
+ gibamounts = list(2, 2, 1)
+ sound_vol = 40
/obj/effect/gibspawner/generic/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 40, 1)
- gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list())
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list())
+ return ..()
+
+/obj/effect/gibspawner/generic/animal
+ gib_mob_type = /mob/living/simple_animal/pet
/obj/effect/gibspawner/human
- gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/up, /obj/effect/decal/cleanable/blood/gibs/down, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/body, /obj/effect/decal/cleanable/blood/gibs/limb, /obj/effect/decal/cleanable/blood/gibs/core)
- gibamounts = list(1,1,1,1,1,1,1)
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human/up, /obj/effect/decal/cleanable/blood/gibs/human/down, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/body, /obj/effect/decal/cleanable/blood/gibs/human/limb, /obj/effect/decal/cleanable/blood/gibs/human/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human
+ gib_mob_species = /datum/species/human
+ sound_vol = 50
/obj/effect/gibspawner/human/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 50, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
-
-/obj/effect/gibspawner/humanbodypartless //only the gibs that don't look like actual full bodyparts (except torso).
- gibtypes = list(/obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/torso)
+/obj/effect/gibspawner/human/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/core, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/core, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/torso)
gibamounts = list(1, 1, 1, 1, 1, 1)
-/obj/effect/gibspawner/humanbodypartless/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 50, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
- . = ..()
+/obj/effect/gibspawner/human/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
+/obj/effect/gibspawner/lizard
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human/lizard/up, /obj/effect/decal/cleanable/blood/gibs/human/lizard/down, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/body, /obj/effect/decal/cleanable/blood/gibs/human/lizard/limb, /obj/effect/decal/cleanable/blood/gibs/human/lizard/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human/species/lizard
+ gib_mob_species = /datum/species/lizard
+ sound_vol = 50
+
+/obj/effect/gibspawner/lizard/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/lizard/bodypartless
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/core, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/core, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/torso)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+
+/obj/effect/gibspawner/lizard/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/slime
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/slime/up, /obj/effect/decal/cleanable/blood/gibs/slime/down, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/body, /obj/effect/decal/cleanable/blood/gibs/slime/limb, /obj/effect/decal/cleanable/blood/gibs/slime/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human/species/roundstartslime
+ gib_mob_species = /datum/species/jelly/roundstartslime
+ sound_vol = 50
+
+/obj/effect/gibspawner/slime/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/slime/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/core, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/core, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/torso)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+
+/obj/effect/gibspawner/slime/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/ipc
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/ipc/up, /obj/effect/decal/cleanable/blood/gibs/ipc/down, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/body, /obj/effect/decal/cleanable/blood/gibs/ipc/limb, /obj/effect/decal/cleanable/blood/gibs/ipc/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human/species/ipc
+ gib_mob_species = /datum/species/ipc
+ sound_vol = 50
+ sparks = TRUE
+ sound_to_play = 'sound/effects/bang.ogg'
+
+/obj/effect/gibspawner/ipc/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/ipc/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/core, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/core, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/torso)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+
+/obj/effect/gibspawner/ipc/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
/obj/effect/gibspawner/xeno
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/up, /obj/effect/decal/cleanable/xenoblood/xgibs/down, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/body, /obj/effect/decal/cleanable/xenoblood/xgibs/limb, /obj/effect/decal/cleanable/xenoblood/xgibs/core)
- gibamounts = list(1,1,1,1,1,1,1)
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/up, /obj/effect/decal/cleanable/blood/gibs/xeno/down, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/body, /obj/effect/decal/cleanable/blood/gibs/xeno/limb, /obj/effect/decal/cleanable/blood/gibs/xeno/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/alien
/obj/effect/gibspawner/xeno/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
-
-/obj/effect/gibspawner/xenobodypartless //only the gibs that don't look like actual full bodyparts (except torso).
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/core, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/core, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/torso)
+/obj/effect/gibspawner/xeno/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/core, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/core, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/torso)
gibamounts = list(1, 1, 1, 1, 1, 1)
+/obj/effect/gibspawner/xeno/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
-/obj/effect/gibspawner/xenobodypartless/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
- . = ..()
+/obj/effect/gibspawner/xeno/xenoperson
+ gib_mob_type = /mob/living/carbon/human/species/xeno
+ gib_mob_species = /datum/species/xeno
+
+/obj/effect/gibspawner/xeno/xenoperson/bodypartless
/obj/effect/gibspawner/larva
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, /obj/effect/decal/cleanable/xenoblood/xgibs/larva/body)
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva/body, /obj/effect/decal/cleanable/blood/gibs/xeno/larva/body)
gibamounts = list(1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/alien/larva
/obj/effect/gibspawner/larva/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list(), GLOB.alldirs)
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list(), GLOB.alldirs)
+ return ..()
-/obj/effect/gibspawner/larvabodypartless
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva)
+/obj/effect/gibspawner/larva/bodypartless
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva)
gibamounts = list(1, 1, 1)
-/obj/effect/gibspawner/larvabodypartless/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list())
- . = ..()
+/obj/effect/gibspawner/larva/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list())
+ return ..()
/obj/effect/gibspawner/robot
- sparks = 1
+ sparks = TRUE
gibtypes = list(/obj/effect/decal/cleanable/robot_debris/up, /obj/effect/decal/cleanable/robot_debris/down, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/robot_debris/limb)
- gibamounts = list(1,1,1,1,1,1)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/silicon/robot
/obj/effect/gibspawner/robot/Initialize()
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs)
- gibamounts[6] = pick(0,1,2)
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs)
+ gibamounts[6] = pick(0, 1, 2)
+ return ..()
+
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 7d02d9d383..fbad000098 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -6,7 +6,9 @@
layer = BELOW_MOB_LAYER
var/splatter_type = "splatter"
-/obj/effect/temp_visual/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
+/obj/effect/temp_visual/dir_setting/bloodsplatter/Initialize(mapload, set_dir, new_color)
+ if(new_color)
+ color = new_color
if(set_dir in GLOB.diagonals)
icon_state = "[splatter_type][pick(1, 2, 6)]"
else
@@ -41,7 +43,7 @@
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
/obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter
- splatter_type = "xsplatter"
+ color = BLOOD_COLOR_XENO
/obj/effect/temp_visual/dir_setting/speedbike_trail
name = "speedbike trails"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 6a706fede9..9ce2e66abf 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -111,7 +111,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
-
/obj/item/Initialize()
materials = typelist("materials", materials)
@@ -408,12 +407,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
for(var/X in actions)
var/datum/action/A = X
- if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
+ if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
item_flags |= IN_INVENTORY
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
-/obj/item/proc/item_action_slot_check(slot, mob/user)
+/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there
return FALSE
return TRUE
@@ -537,6 +536,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
M.become_blind(EYE_DAMAGE)
to_chat(M, "You go blind!")
+/obj/item/clean_blood()
+ . = ..()
+ if(.)
+ if(blood_splatter_icon)
+ cut_overlay(blood_splatter_icon)
+
+/obj/item/clothing/gloves/clean_blood()
+ . = ..()
+ if(.)
+ transfer_blood = 0
+
/obj/item/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FOUR)
diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm
index 63f460f9aa..93293155a3 100644
--- a/code/game/objects/items/RCL.dm
+++ b/code/game/objects/items/RCL.dm
@@ -20,8 +20,8 @@
var/ghetto = FALSE
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
- var/datum/component/mobhook
var/datum/radial_menu/persistent/wiring_gui_menu
+ var/mob/listeningTo
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil))
@@ -86,7 +86,7 @@
/obj/item/twohanded/rcl/Destroy()
QDEL_NULL(loaded)
last = null
- QDEL_NULL(mobhook)
+ listeningTo = null
QDEL_NULL(wiring_gui_menu)
return ..()
@@ -141,9 +141,8 @@
/obj/item/twohanded/rcl/dropped(mob/wearer)
..()
- if(mobhook)
- active = FALSE
- QDEL_NULL(mobhook)
+ UnregisterSignal(wearer, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
last = null
/obj/item/twohanded/rcl/attack_self(mob/user)
@@ -158,13 +157,12 @@
break
obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
- if(to_hook)
- if(mobhook && mobhook.parent != to_hook)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = to_hook.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger)))
- else
- QDEL_NULL(mobhook)
+ if(listeningTo == to_hook)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(to_hook, COMSIG_MOVABLE_MOVED, .proc/trigger)
+ listeningTo = to_hook
/obj/item/twohanded/rcl/proc/trigger(mob/user)
if(active)
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index 699efaac2e..10fbab56be 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -153,7 +153,9 @@
/area/centcom,
/area/asteroid,
/area/tdome,
- /area/wizard_station
+ /area/wizard_station,
+ /area/hilbertshotel,
+ /area/hilbertshotelstorage
)
for (var/type in SPECIALS)
if ( istype(A,type) )
diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm
index 5db5aa416e..911a07c288 100644
--- a/code/game/objects/items/chrono_eraser.dm
+++ b/code/game/objects/items/chrono_eraser.dm
@@ -37,7 +37,7 @@
PA = new(src)
user.put_in_hands(PA)
-/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user)
+/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_BACK)
return 1
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 639d570462..1059a310eb 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -31,6 +31,15 @@
/obj/item/stock_parts/manipulator = 1,
/obj/item/stack/sheet/glass = 1)
+/obj/item/circuitboard/machine/bloodbankgen
+ name = "Blood Bank Generator (Machine Board)"
+ build_path = /obj/machinery/bloodbankgen
+ req_components = list(
+ /obj/item/stock_parts/matter_bin = 1,
+ /obj/item/stock_parts/manipulator = 1,
+ /obj/item/stack/cable_coil = 5,
+ /obj/item/stack/sheet/glass = 1)
+
/obj/item/circuitboard/machine/clonepod
name = "Clone Pod (Machine Board)"
build_path = /obj/machinery/clonepod
diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm
index fa4524528b..c98484b81e 100644
--- a/code/game/objects/items/control_wand.dm
+++ b/code/game/objects/items/control_wand.dm
@@ -33,7 +33,7 @@
// Airlock remote works by sending NTNet packets to whatever it's pointed at.
/obj/item/door_remote/afterattack(atom/A, mob/user)
. = ..()
- GET_COMPONENT_FROM(target_interface, /datum/component/ntnet_interface, A)
+ var/datum/component/ntnet_interface/target_interface = A.GetComponent(/datum/component/ntnet_interface)
if(!target_interface)
return
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 102c6a8eed..d014f70315 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -561,7 +561,7 @@
/obj/item/storage/crayons/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 7
STR.can_hold = typecacheof(list(/obj/item/toy/crayon))
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index a4f286bf88..f5799e1a22 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -39,7 +39,6 @@
/obj/item/defibrillator/loaded/Initialize() //starts with hicap
. = ..()
- paddles = make_paddles()
cell = new(src)
update_icon()
return
@@ -193,7 +192,7 @@
remove_paddles(user)
update_icon()
-/obj/item/defibrillator/item_action_slot_check(slot, mob/user)
+/obj/item/defibrillator/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == user.getBackSlot())
return 1
@@ -208,8 +207,8 @@
var/M = get(paddles, /mob)
remove_paddles(M)
QDEL_NULL(paddles)
- . = ..()
- update_icon()
+ QDEL_NULL(cell)
+ return ..()
/obj/item/defibrillator/proc/deductcharge(chrgdeductamt)
if(cell)
@@ -244,13 +243,12 @@
w_class = WEIGHT_CLASS_NORMAL
slot_flags = ITEM_SLOT_BELT
-/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user)
+/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == user.getBeltSlot())
return TRUE
/obj/item/defibrillator/compact/loaded/Initialize()
. = ..()
- paddles = make_paddles()
cell = new(src)
update_icon()
@@ -262,7 +260,6 @@
/obj/item/defibrillator/compact/combat/loaded/Initialize()
. = ..()
- paddles = make_paddles()
cell = new /obj/item/stock_parts/cell/infinite(src)
update_icon()
@@ -297,31 +294,28 @@
var/grab_ghost = FALSE
var/tlimit = DEFIB_TIME_LIMIT * 10
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/twohanded/shockpaddles/equipped(mob/user, slot)
. = ..()
- if(req_defib)
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/check_range)))
+ if(!req_defib)
+ return
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/check_range)
/obj/item/twohanded/shockpaddles/Moved()
. = ..()
check_range()
/obj/item/twohanded/shockpaddles/proc/check_range()
- if(!req_defib)
+ if(!req_defib || !defib)
return
if(!in_range(src,defib))
var/mob/living/L = loc
if(istype(L))
to_chat(L, "[defib]'s paddles overextend and come out of your hands!")
- L.temporarilyRemoveItemFromInventory(src,TRUE)
else
visible_message("[src] snap back into [defib].")
- snap_back()
+ snap_back()
/obj/item/twohanded/shockpaddles/proc/recharge(var/time)
if(req_defib || !time)
@@ -362,14 +356,14 @@
/obj/item/twohanded/shockpaddles/dropped(mob/user)
if(!req_defib)
return ..()
- if (mobhook)
- QDEL_NULL(mobhook)
if(user)
+ UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
var/obj/item/twohanded/offhand/O = user.get_inactive_held_item()
if(istype(O))
O.unwield()
- to_chat(user, "The paddles snap back into the main unit.")
- snap_back()
+ if(user != loc)
+ to_chat(user, "The paddles snap back into the main unit.")
+ snap_back()
return unwield(user)
/obj/item/twohanded/shockpaddles/proc/snap_back()
diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm
index d85c5d72d8..28bc559b93 100644
--- a/code/game/objects/items/devices/PDA/virus_cart.dm
+++ b/code/game/objects/items/devices/PDA/virus_cart.dm
@@ -70,7 +70,7 @@
difficulty++ //if cartridge has manifest access it has extra snowflake difficulty
else
difficulty += 2
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
+ var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
if(!target.detonatable || prob(difficulty * 15) || (hidden_uplink))
U.show_message("An error flashes on your [src].", 1)
else
@@ -95,7 +95,7 @@
charges--
var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
to_chat(U, "Virus Sent! The unlock code to the target is: [lock_code]")
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
+ var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
if(!hidden_uplink)
hidden_uplink = target.AddComponent(/datum/component/uplink)
hidden_uplink.unlock_code = lock_code
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index f39d2ba0d6..dffbb46cbb 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -116,7 +116,7 @@
appearance = saved_appearance
if(istype(M.buckled, /obj/vehicle))
var/obj/vehicle/V = M.buckled
- GET_COMPONENT_FROM(VRD, /datum/component/riding, V)
+ var/datum/component/riding/VRD = V.GetComponent(/datum/component/riding)
if(VRD)
VRD.force_dismount(M)
else
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index 90cdd0386c..110676de1b 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -203,21 +203,25 @@
return TRUE
/obj/item/geiger_counter/cyborg
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/geiger_counter/cyborg/equipped(mob/user)
. = ..()
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_RAD_ACT = CALLBACK(src, .proc/redirect_rad_act)))
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
+ RegisterSignal(user, COMSIG_ATOM_RAD_ACT, .proc/redirect_rad_act)
+ listeningTo = user
/obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount)
rad_act(amount)
/obj/item/geiger_counter/cyborg/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
+ listeningTo = null
#undef RAD_LEVEL_NORMAL
#undef RAD_LEVEL_MODERATE
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 7655654f78..d644e0637e 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -410,7 +410,7 @@ SLIME SCANNER
msg += "Subject is bleeding!\n"
var/blood_percent = round((C.blood_volume / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
var/blood_type = C.dna.blood_type
- if(blood_id != "blood")//special blood substance
+ if(blood_id != ("blood" || "jellyblood"))//special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 2c234a59ba..fc768cd38e 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -195,7 +195,7 @@ effective or pretty fucking useless.
Deactivate()
return
-/obj/item/shadowcloak/item_action_slot_check(slot, mob/user)
+/obj/item/shadowcloak/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_BELT)
return 1
diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm
index 3be57d23f1..7e7dddefb6 100644
--- a/code/game/objects/items/his_grace.dm
+++ b/code/game/objects/items/his_grace.dm
@@ -29,7 +29,7 @@
. = ..()
START_PROCESSING(SSprocessing, src)
GLOB.poi_list += src
- AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_POST_THROW = CALLBACK(src, .proc/move_gracefully)))
+ RegisterSignal(src, COMSIG_MOVABLE_POST_THROW, .proc/move_gracefully)
/obj/item/his_grace/Destroy()
STOP_PROCESSING(SSprocessing, src)
diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm
index 739873af00..1f44b5318e 100644
--- a/code/game/objects/items/implants/implant_storage.dm
+++ b/code/game/objects/items/implants/implant_storage.dm
@@ -21,7 +21,7 @@
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/implant/storage/imp_e = X
- GET_COMPONENT_FROM(STR, /datum/component/storage, imp_e.pocket)
+ var/datum/component/storage/STR = imp_e.pocket.GetComponent(/datum/component/storage)
if(!STR || (STR && STR.max_items < max_slot_stacking))
imp_e.pocket.AddComponent(/datum/component/storage/concrete/implant)
qdel(src)
diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm
index aabb930bb2..850810bdb2 100644
--- a/code/game/objects/items/melee/transforming.dm
+++ b/code/game/objects/items/melee/transforming.dm
@@ -69,7 +69,7 @@
var/datum/component/butchering/BT = LoadComponent(/datum/component/butchering)
BT.butchering_enabled = TRUE
else
- GET_COMPONENT(BT, /datum/component/butchering)
+ var/datum/component/butchering/BT = GetComponent(/datum/component/butchering)
if(BT)
BT.butchering_enabled = FALSE
transform_messages(user, supress_message_text)
diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm
index 7524fc9007..3f7fe7ee8d 100644
--- a/code/game/objects/items/mop.dm
+++ b/code/game/objects/items/mop.dm
@@ -27,6 +27,7 @@
/obj/item/mop/proc/clean(turf/A)
if(reagents.has_reagent("water", 1) || reagents.has_reagent("holywater", 1) || reagents.has_reagent("vodka", 1) || reagents.has_reagent("cleaner", 1))
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ A.clean_blood()
for(var/obj/effect/O in A)
if(is_cleanable(O))
qdel(O)
diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm
index 74919016f5..7b3dcb1e00 100644
--- a/code/game/objects/items/religion.dm
+++ b/code/game/objects/items/religion.dm
@@ -168,7 +168,7 @@
/obj/item/storage/backpack/bannerpack/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times.
/obj/item/storage/backpack/bannerpack/red
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 5610cbad9a..886997eab9 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -17,7 +17,6 @@
var/self_delay = 50
/obj/item/stack/medical/attack(mob/living/M, mob/user)
-
if(M.stat == DEAD && !stop_bleeding)
var/t_him = "it"
if(M.gender == MALE)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 155d1f1643..7654199cf5 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -390,9 +390,9 @@
. = ..()
/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
- add_blood_DNA(from.return_blood_DNA())
- add_fingerprint_list(from.return_fingerprints())
- add_hiddenprint_list(from.return_hiddenprints())
+ blood_DNA = from.blood_DNA
+ fingerprints = from.fingerprints
+ fingerprintshidden = from.fingerprintshidden
fingerprintslast = from.fingerprintslast
//TODO bloody overlay
@@ -437,4 +437,4 @@
/datum/stack_recipe_list/New(title, recipes)
src.title = title
- src.recipes = recipes
+ src.recipes = recipes
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm
index 7c34ae87bf..9b5ca2b066 100644
--- a/code/game/objects/items/stacks/telecrystal.dm
+++ b/code/game/objects/items/stacks/telecrystal.dm
@@ -13,7 +13,7 @@
var/mob/living/L = user
for(var/obj/item/implant/uplink/I in L.implants)
if(I?.imp_in)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
+ var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
if(hidden_uplink)
hidden_uplink.telecrystals += amount
use(amount)
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index ad8c4306a5..a79eb299da 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -23,7 +23,7 @@
/obj/item/storage/backpack/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 21
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_items = 21
@@ -34,7 +34,7 @@
/obj/item/storage/backpack/old/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 12
/obj/item/storage/backpack/holding
@@ -58,7 +58,7 @@
/obj/item/storage/backpack/holding/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.allow_big_nesting = TRUE
STR.max_w_class = WEIGHT_CLASS_GIGANTIC
STR.max_combined_w_class = 35
@@ -87,7 +87,7 @@
/obj/item/storage/backpack/santabag/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 60
@@ -260,7 +260,7 @@
/obj/item/storage/backpack/satchel/bone/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 20
STR.max_items = 15
@@ -286,7 +286,7 @@
/obj/item/storage/backpack/satchel/flat/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 6
STR.cant_hold = typecacheof(list(/obj/item/storage/backpack/satchel/flat)) //muh recursive backpacks
@@ -338,7 +338,7 @@
/obj/item/storage/backpack/duffelbag/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 30
/obj/item/storage/backpack/duffelbag/captain
@@ -444,7 +444,7 @@
/obj/item/storage/backpack/duffelbag/syndie/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.silent = TRUE
/obj/item/storage/backpack/duffelbag/syndie/hitman
@@ -594,7 +594,7 @@
// For ClownOps.
/obj/item/storage/backpack/duffelbag/clown/syndie/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
slowdown = 0
STR.silent = TRUE
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 0a475b2af1..13efe72686 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -21,7 +21,7 @@
/obj/item/storage/bag/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.allow_quick_gather = TRUE
STR.allow_quick_empty = TRUE
STR.display_numerical_stacking = TRUE
@@ -44,7 +44,7 @@
/obj/item/storage/bag/trash/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_combined_w_class = 30
STR.max_items = 30
@@ -85,7 +85,7 @@
/obj/item/storage/bag/trash/bluespace/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 60
STR.max_items = 60
@@ -105,12 +105,12 @@
w_class = WEIGHT_CLASS_NORMAL
component_type = /datum/component/storage/concrete/stack
var/spam_protection = FALSE //If this is TRUE, the holder won't receive any messages when they fail to pick up ore through crossing it
- var/datum/component/mobhook
+ var/mob/listeningTo
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/bag/ore/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
STR.max_w_class = WEIGHT_CLASS_HUGE
@@ -118,15 +118,17 @@
/obj/item/storage/bag/ore/equipped(mob/user)
. = ..()
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/Pickup_ores)))
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/Pickup_ores)
+ listeningTo = user
/obj/item/storage/bag/ore/dropped()
. = ..()
- if (mobhook)
- QDEL_NULL(mobhook)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
/obj/item/storage/bag/ore/proc/Pickup_ores(mob/living/user)
var/show_message = FALSE
@@ -136,7 +138,7 @@
return
if (istype(user.pulling, /obj/structure/ore_box))
box = user.pulling
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
if(STR)
for(var/A in tile)
if (!is_type_in_typecache(A, STR.can_hold))
@@ -166,7 +168,7 @@
/obj/item/storage/bag/ore/cyborg/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
STR.max_w_class = WEIGHT_CLASS_HUGE
@@ -178,7 +180,7 @@
/obj/item/storage/bag/ore/large/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
STR.max_w_class = WEIGHT_CLASS_HUGE
@@ -191,7 +193,7 @@
/obj/item/storage/bag/ore/holding/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.max_items = INFINITY
STR.max_combined_w_class = INFINITY
STR.max_combined_stack_amount = INFINITY
@@ -209,7 +211,7 @@
/obj/item/storage/bag/plants/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 100
STR.max_items = 100
@@ -249,7 +251,7 @@
/obj/item/storage/bag/sheetsnatcher/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/sheet))
STR.cant_hold = typecacheof(list(/obj/item/stack/sheet/mineral/sandstone, /obj/item/stack/sheet/mineral/wood))
@@ -266,7 +268,7 @@
/obj/item/storage/bag/sheetsnatcher/borg/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.max_combined_stack_amount = 500
// -----------------------------
@@ -283,7 +285,7 @@
/obj/item/storage/bag/books/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 21
STR.max_items = 7
@@ -308,15 +310,14 @@
/obj/item/storage/bag/tray/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.insert_preposition = "on"
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
. = ..()
// Drop all the things. All of them.
var/list/obj/item/oldContents = contents.Copy()
- GET_COMPONENT(STR, /datum/component/storage)
- STR.quick_empty()
+ SEND_SIGNAL(src, COMSIG_TRY_STORAGE_QUICK_EMPTY)
// Make each item scatter a bit
for(var/obj/item/I in oldContents)
spawn()
@@ -362,7 +363,7 @@
/obj/item/storage/bag/chemistry/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 200
STR.max_items = 50
STR.insert_preposition = "in"
@@ -382,7 +383,7 @@
/obj/item/storage/bag/bio/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 200
STR.max_items = 25
STR.insert_preposition = "in"
@@ -397,6 +398,6 @@
/obj/item/storage/bag/bio/holding/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = INFINITY
STR.max_items = 100
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index e354123ab9..713dbe4133 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -44,7 +44,7 @@
/obj/item/storage/belt/utility/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
var/static/list/can_hold = typecacheof(list(
/obj/item/crowbar,
/obj/item/screwdriver,
@@ -127,7 +127,7 @@
/obj/item/storage/belt/medical/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.can_hold = typecacheof(list(
/obj/item/healthanalyzer,
@@ -199,7 +199,7 @@
/obj/item/storage/belt/security/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(
@@ -238,7 +238,7 @@
/obj/item/storage/belt/mining/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.max_combined_w_class = 20
@@ -297,7 +297,7 @@
/obj/item/storage/belt/mining/primitive/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
/obj/item/storage/belt/soulstone
@@ -308,7 +308,7 @@
/obj/item/storage/belt/soulstone/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/soulstone
@@ -331,7 +331,7 @@
/obj/item/storage/belt/champion/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
STR.can_hold = list(
/obj/item/clothing/mask/luchador
@@ -346,7 +346,7 @@
/obj/item/storage/belt/military/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
/obj/item/storage/belt/military/snack
@@ -359,7 +359,7 @@
/obj/item/storage/belt/military/snack/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.can_hold = typecacheof(list(
@@ -427,7 +427,7 @@
/obj/item/storage/belt/military/assault/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
/obj/item/storage/belt/durathread
@@ -480,7 +480,7 @@
/obj/item/storage/belt/grenade/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 30
STR.display_numerical_stacking = TRUE
STR.max_combined_w_class = 60
@@ -533,7 +533,7 @@
/obj/item/storage/belt/wands/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/gun/magic/wand
@@ -559,7 +559,7 @@
/obj/item/storage/belt/janitor/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_BULKY // Set to this so the light replacer can fit.
STR.can_hold = typecacheof(list(
@@ -586,7 +586,7 @@
/obj/item/storage/belt/bandolier/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 18
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(
@@ -602,7 +602,7 @@
/obj/item/storage/belt/bandolier/durathread/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 32
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(
@@ -617,7 +617,7 @@
/obj/item/storage/belt/medolier/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 15
STR.display_numerical_stacking = FALSE
STR.allow_quick_gather = TRUE
@@ -659,7 +659,7 @@
/obj/item/storage/belt/holster/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 3
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(
@@ -683,7 +683,7 @@
/obj/item/storage/belt/fannypack/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 3
STR.max_w_class = WEIGHT_CLASS_SMALL
@@ -750,7 +750,7 @@
/obj/item/storage/belt/sabre/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
STR.rustle_sound = FALSE
STR.max_w_class = WEIGHT_CLASS_BULKY
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 85a06f0c1e..c658eee3d5 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -11,7 +11,7 @@
/obj/item/storage/book/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
/obj/item/storage/book/attack_self(mob/user)
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index dd6a6b8453..dde0e0715b 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -398,7 +398,7 @@
/obj/item/storage/box/donkpockets/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/donkpocket))
/obj/item/storage/box/donkpockets/PopulateContents()
@@ -413,7 +413,7 @@
/obj/item/storage/box/monkeycubes/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 7
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/monkeycube))
@@ -568,7 +568,7 @@
/obj/item/storage/box/snappops/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/toy/snappop))
STR.max_items = 8
@@ -586,7 +586,7 @@
/obj/item/storage/box/matches/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 10
STR.can_hold = typecacheof(list(/obj/item/match))
@@ -609,7 +609,7 @@
/obj/item/storage/box/lights/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 21
STR.can_hold = typecacheof(list(/obj/item/light/tube, /obj/item/light/bulb))
STR.max_combined_w_class = 21
diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index ed547bc17d..782ffd3add 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -17,7 +17,7 @@
/obj/item/storage/briefcase/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 21
@@ -48,7 +48,7 @@
/obj/item/storage/briefcase/lawyer/family/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 14
diff --git a/code/game/objects/items/storage/dakis.dm b/code/game/objects/items/storage/dakis.dm
index 08748bf37e..2703581a94 100644
--- a/code/game/objects/items/storage/dakis.dm
+++ b/code/game/objects/items/storage/dakis.dm
@@ -13,7 +13,7 @@
/obj/item/storage/daki/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_combined_w_class = 21
STR.max_items = 3
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index 95639918bb..f0a9ad019b 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -25,7 +25,7 @@
var/fancy_open = FALSE
/obj/item/storage/fancy/PopulateContents()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
for(var/i = 1 to STR.max_items)
new spawn_type(src)
@@ -72,7 +72,7 @@
/obj/item/storage/fancy/donut_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/donut))
@@ -93,7 +93,7 @@
/obj/item/storage/fancy/egg_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 12
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/egg))
@@ -115,7 +115,7 @@
/obj/item/storage/fancy/candle_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
/obj/item/storage/fancy/candle_box/attack_self(mob_user)
@@ -138,7 +138,7 @@
/obj/item/storage/fancy/cigarettes/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette, /obj/item/lighter))
@@ -276,7 +276,7 @@
/obj/item/storage/fancy/rollingpapers/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 10
STR.can_hold = typecacheof(list(/obj/item/rollingpaper))
@@ -300,7 +300,7 @@
/obj/item/storage/fancy/cigarettes/cigars/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette/cigar))
@@ -347,6 +347,6 @@
/obj/item/storage/fancy/heart_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 8
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/tinychocolate))
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index 312ef35430..822a1d5011 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -170,7 +170,7 @@
/obj/item/storage/firstaid/tactical/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
/obj/item/storage/firstaid/tactical/PopulateContents()
@@ -200,7 +200,7 @@
/obj/item/storage/pill_bottle/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.allow_quick_gather = TRUE
STR.click_gather = TRUE
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice))
@@ -337,7 +337,7 @@
/obj/item/storage/pill_bottle/penis_enlargement/PopulateContents()
for(var/i in 1 to 7)
new /obj/item/reagent_containers/pill/penis_enlargement(src)
-
+
/obj/item/storage/pill_bottle/breast_enlargement
name = "breast enlargement pills"
desc = "Made by Fermichem - They have a woman with breasts larger than she is on them. The warming states not to take more than 10u at a time."
@@ -363,7 +363,7 @@
/obj/item/storage/belt/organbox/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 16
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.max_combined_w_class = 20
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index eeebc6f4c5..1607b19c2f 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -15,7 +15,7 @@
/obj/item/storage/lockbox/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 14
STR.max_items = 4
@@ -101,7 +101,7 @@
/obj/item/storage/lockbox/medal/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_items = 10
STR.max_combined_w_class = 20
diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm
index 20dae54a71..8618e4c3ae 100644
--- a/code/game/objects/items/storage/secure.dm
+++ b/code/game/objects/items/storage/secure.dm
@@ -26,7 +26,7 @@
/obj/item/storage/secure/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_combined_w_class = 14
@@ -136,7 +136,7 @@
/obj/item/storage/secure/briefcase/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 21
STR.max_w_class = WEIGHT_CLASS_NORMAL
@@ -146,7 +146,7 @@
/obj/item/storage/secure/briefcase/syndie/PopulateContents()
..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
for(var/i = 0, i < STR.max_items - 2, i++)
new /obj/item/stack/spacecash/c1000(src)
@@ -170,7 +170,7 @@
/obj/item/storage/secure/safe/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.cant_hold = typecacheof(list(/obj/item/storage/secure/briefcase))
STR.max_w_class = 8 //??
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index d18212be42..251703f907 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -35,6 +35,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/update_icon()
..()
cut_overlays()
+ if(blood_DNA && blood_DNA.len)
+ add_blood_overlay()
if(has_latches)
var/icon/I = icon('icons/obj/storage.dmi', latches)
add_overlay(I)
@@ -122,7 +124,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/syndicate/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.silent = TRUE
/obj/item/storage/toolbox/syndicate/PopulateContents()
@@ -163,7 +165,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/brass/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 28
STR.max_items = 28
@@ -218,7 +220,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/artistic/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 20
STR.max_items = 10
@@ -256,7 +258,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/gold_real/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 40
STR.max_items = 12
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index cf5d685b4a..84ebc28afa 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -220,7 +220,7 @@
/obj/item/storage/box/syndie_kit/space/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(/obj/item/clothing/suit/space/syndicate, /obj/item/clothing/head/helmet/space/syndicate))
@@ -244,7 +244,7 @@
/obj/item/storage/box/syndie_kit/chemical/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 14
/obj/item/storage/box/syndie_kit/chemical/PopulateContents()
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index cb5790e45f..7a6899ad15 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -11,7 +11,7 @@
/obj/item/storage/wallet/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 4
STR.cant_hold = typecacheof(list(/obj/item/screwdriver/power))
STR.can_hold = typecacheof(list(
diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm
index 8f2b85098d..f3be8cefc8 100644
--- a/code/game/objects/items/tanks/watertank.dm
+++ b/code/game/objects/items/tanks/watertank.dm
@@ -24,7 +24,7 @@
/obj/item/watertank/ui_action_click(mob/user)
toggle_mister(user)
-/obj/item/watertank/item_action_slot_check(slot, mob/user)
+/obj/item/watertank/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == user.getBackSlot())
return 1
@@ -341,7 +341,7 @@
/obj/item/reagent_containers/chemtank/ui_action_click()
toggle_injection()
-/obj/item/reagent_containers/chemtank/item_action_slot_check(slot, mob/user)
+/obj/item/reagent_containers/chemtank/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_BACK)
return 1
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index b1c2c36585..1bbeccb4de 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -346,7 +346,8 @@
icon_state = "dualsaber[item_color][wielded]"
else
icon_state = "dualsaber0"
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+
+ clean_blood()
/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user)
if(user.has_dna())
@@ -624,7 +625,7 @@
force = on ? force_on : initial(force)
throwforce = on ? force_on : initial(force)
icon_state = "chainsaw_[on ? "on" : "off"]"
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = on
if(on)
@@ -847,18 +848,20 @@
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
- var/datum/component/mobhook
+ var/mob/listeningTo
var/zoom_out_amt = 6
var/zoom_amt = 10
+/obj/item/twohanded/binoculars/Destroy()
+ listeningTo = null
+ return ..()
+
/obj/item/twohanded/binoculars/wield(mob/user)
. = ..()
if(!wielded)
return
- if(QDELETED(mobhook))
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/unwield)))
- else
- user.TakeComponent(mobhook)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield)
+ listeningTo = user
user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.")
item_state = "binoculars_wielded"
user.regenerate_icons()
@@ -882,7 +885,8 @@
/obj/item/twohanded/binoculars/unwield(mob/user)
. = ..()
- mobhook.RemoveComponent()
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
user.visible_message("[user] lowers [src].","You lower [src].")
item_state = "binoculars"
user.regenerate_icons()
@@ -891,4 +895,4 @@
var/client/C = user.client
C.change_view(CONFIG_GET(string/default_view))
user.client.pixel_x = 0
- user.client.pixel_y = 0
+ user.client.pixel_y = 0
\ No newline at end of file
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 46db567b10..76c8f7f11f 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -318,6 +318,7 @@
/obj/machinery/shower/proc/wash_obj(obj/O)
. = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ . = O.clean_blood()
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
if(isitem(O))
var/obj/item/I = O
@@ -328,8 +329,9 @@
/obj/machinery/shower/proc/wash_turf()
if(isturf(loc))
var/turf/tile = loc
- SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
tile.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+ tile.clean_blood()
+ SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
for(var/obj/effect/E in tile)
if(is_cleanable(E))
qdel(E)
@@ -381,7 +383,8 @@
else if(H.w_uniform && wash_obj(H.w_uniform))
H.update_inv_w_uniform()
if(washgloves)
- SEND_SIGNAL(H, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ H.clean_blood()
+ SEND_SIGNAL(H, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
if(H.shoes && washshoes && wash_obj(H.shoes))
H.update_inv_shoes()
if(H.wear_mask && washmask && wash_obj(H.wear_mask))
@@ -398,9 +401,11 @@
else
if(M.wear_mask && wash_obj(M.wear_mask))
M.update_inv_wear_mask(0)
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ M.clean_blood()
+ SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
else
- SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ L.clean_blood()
+ SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
/obj/machinery/shower/proc/contamination_cleanse(atom/movable/thing)
var/datum/component/radioactive/healthy_green_glow = thing.GetComponent(/datum/component/radioactive)
@@ -498,7 +503,8 @@
H.regenerate_icons()
user.drowsyness = max(user.drowsyness - rand(2,3), 0) //Washing your face wakes you up if you're falling asleep
else
- SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ user.clean_blood()
/obj/structure/sink/attackby(obj/item/O, mob/living/user, params)
if(busy)
@@ -554,7 +560,8 @@
busy = FALSE
return 1
busy = FALSE
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ O.clean_blood()
O.acid_level = 0
create_reagents(5)
reagents.add_reagent(dispensedreagent, 5)
@@ -675,4 +682,4 @@
else
playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
if(BURN)
- playsound(loc, 'sound/items/welder.ogg', 80, 1)
+ playsound(loc, 'sound/items/welder.ogg', 80, 1)
\ No newline at end of file
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index e441ccd6cc..f1c5080c8f 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -41,7 +41,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
/turf/open/copyTurf(turf/T, copy_air = FALSE)
. = ..()
if (isopenturf(T))
- GET_COMPONENT(slip, /datum/component/wet_floor)
+ var/datum/component/wet_floor/slip = GetComponent(/datum/component/wet_floor)
if(slip)
var/datum/component/wet_floor/WF = T.AddComponent(/datum/component/wet_floor)
WF.InheritComponent(slip)
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index f6d234b346..bd24e0ff93 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -251,6 +251,7 @@
M.apply_water()
SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ clean_blood()
for(var/obj/effect/O in src)
if(is_cleanable(O))
qdel(O)
diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm
index 677fba2990..0a7b507488 100644
--- a/code/game/turfs/simulated/chasm.dm
+++ b/code/game/turfs/simulated/chasm.dm
@@ -15,11 +15,11 @@
AddComponent(/datum/component/chasm, SSmapping.get_turf_below(src))
/turf/open/chasm/proc/set_target(turf/target)
- GET_COMPONENT(chasm_component, /datum/component/chasm)
+ var/datum/component/chasm/chasm_component = GetComponent(/datum/component/chasm)
chasm_component.target_turf = target
/turf/open/chasm/proc/drop(atom/movable/AM)
- GET_COMPONENT(chasm_component, /datum/component/chasm)
+ var/datum/component/chasm/chasm_component = GetComponent(/datum/component/chasm)
chasm_component.drop(AM)
/turf/open/chasm/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
diff --git a/code/modules/NTNet/services/_service.dm b/code/modules/NTNet/services/_service.dm
index 8611c2d25d..3622dc3881 100644
--- a/code/modules/NTNet/services/_service.dm
+++ b/code/modules/NTNet/services/_service.dm
@@ -17,7 +17,7 @@
/datum/ntnet_service/proc/connect(datum/ntnet/net)
if(!istype(net))
return FALSE
- GET_COMPONENT(interface, /datum/component/ntnet_interface)
+ var/datum/component/ntnet_interface/interface = GetComponent(/datum/component/ntnet_interface)
if(!interface.register_connection(net))
return FALSE
if(!net.register_service(src))
@@ -29,7 +29,7 @@
/datum/ntnet_service/proc/disconnect(datum/ntnet/net, force = FALSE)
if(!istype(net) || (!net.unregister_service(src) && !force))
return FALSE
- GET_COMPONENT(interface, /datum/component/ntnet_interface)
+ var/datum/component/ntnet_interface/interface = GetComponent(/datum/component/ntnet_interface)
interface.unregister_connection(net)
networks_by_id -= net.network_id
return TRUE
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index ed26b894d9..3d874aac58 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -55,7 +55,7 @@
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user)
+/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to activate the vest if he's actually wearing it.
return 1
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index 2018067b77..8000be87e6 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -366,6 +366,8 @@
break
if(!GLOB.ratvar_awakens)
+ if(GLOB.clockwork_vitality <= 0)
+ break
GLOB.clockwork_vitality -= vitality_used
sleep(2)
diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
index f44f67e9cb..28deba679b 100644
--- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
+++ b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
@@ -27,7 +27,7 @@
qdel(blaster)
return ..()
-/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user)
+/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot != SLOT_GLASSES)
return 0
return ..()
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index 49c34131fc..faea113ac5 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -31,7 +31,6 @@ the new instance inside the host to be updated to the template's stats.
var/browser_open = FALSE
var/mob/living/following_host
- var/datum/component/redirect/move_listener
var/list/disease_instances
var/list/hosts //this list is associative, affected_mob -> disease_instance
var/datum/disease/advance/sentient_disease/disease_template
@@ -261,16 +260,10 @@ the new instance inside the host to be updated to the template's stats.
refresh_adaptation_menu()
/mob/camera/disease/proc/set_following(mob/living/L)
+ if(following_host)
+ UnregisterSignal(following_host, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(L, COMSIG_MOVABLE_MOVED, .proc/follow_mob)
following_host = L
- if(!move_listener)
- move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
- else
- if(L)
- L.TakeComponent(move_listener)
- if(QDELING(move_listener))
- move_listener = null
- else
- QDEL_NULL(move_listener)
follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE)
diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm
index dee4557043..235e50008c 100644
--- a/code/modules/antagonists/revenant/revenant_blight.dm
+++ b/code/modules/antagonists/revenant/revenant_blight.dm
@@ -12,8 +12,8 @@
disease_flags = CURABLE
permeability_mod = 1
severity = DISEASE_SEVERITY_DANGEROUS
- var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
- var/datum/mood_event/revenant_blight/depression
+ var/finalstage = FALSE //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
+ var/depression = FALSE
/datum/disease/revblight/cure()
if(affected_mob)
@@ -44,7 +44,8 @@
affected_mob.emote("pale")
if(3)
if(!depression)
- depression = SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
+ SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
+ depression = TRUE
SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.12, SANITY_CRAZY)
if(prob(10))
affected_mob.emote(pick("pale","shiver"))
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 57488a6722..576fc6b9bf 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -113,7 +113,7 @@
/obj/singularity/wizard/attack_tk(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
- GET_COMPONENT_FROM(insaneinthemembrane, /datum/component/mood, C)
+ var/datum/component/mood/insaneinthemembrane = C.GetComponent(/datum/component/mood)
if(insaneinthemembrane.sanity < 15)
return //they've already seen it and are about to die, or are just too insane to care
to_chat(C, "OH GOD! NONE OF IT IS REAL! NONE OF IT IS REEEEEEEEEEEEEEEEEEEEEEEEAL!")
@@ -324,14 +324,11 @@
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
- possible = list()
+ LAZYINITLIST(possible)
if(!voodoo_link)
return
- var/list/prints = voodoo_link.return_fingerprints()
- if(!length(prints))
- return FALSE
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
- if(prints[md5(H.dna.uni_identity)])
+ if(md5(H.dna.uni_identity) in voodoo_link.fingerprints)
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 07f31a6678..7405549b3d 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -10,7 +10,7 @@
var/maxlength = 8
var/list/obj/effect/beam/i_beam/beams
var/olddir = 0
- var/datum/component/redirect/listener
+ var/turf/listeningTo
var/hearing_range = 3
/obj/item/assembly/infra/Initialize()
@@ -33,7 +33,7 @@
/obj/item/assembly/infra/Destroy()
STOP_PROCESSING(SSobj, src)
- QDEL_NULL(listener)
+ listeningTo = null
QDEL_LIST(beams)
. = ..()
@@ -163,8 +163,12 @@
next_activate = world.time + 30
/obj/item/assembly/infra/proc/switchListener(turf/newloc)
- QDEL_NULL(listener)
- listener = newloc.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_EXITED = CALLBACK(src, .proc/check_exit)))
+ if(listeningTo == newloc)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_EXITED)
+ RegisterSignal(newloc, COMSIG_ATOM_EXITED, .proc/check_exit)
+ listeningTo = newloc
/obj/item/assembly/infra/proc/check_exit(datum/source, atom/movable/offender)
if(QDELETED(src))
diff --git a/code/modules/cargo/exports/manifest.dm b/code/modules/cargo/exports/manifest.dm
index d03f5a46ce..60515781f9 100644
--- a/code/modules/cargo/exports/manifest.dm
+++ b/code/modules/cargo/exports/manifest.dm
@@ -80,7 +80,7 @@
// Paper work done correctly
/datum/export/paperwork_correct
- cost = 150
+ cost = 120 // finicky number 20 x 120 = 2400 per crate
k_elasticity = 0
unit_name = "correct paperwork"
export_types = list(/obj/item/folder/paperwork_correct)
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index c9e9c37f6c..89c463f3e3 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -35,4 +35,4 @@
A.flags_1 |= ADMIN_SPAWNED_1
else
for(var/item in contains)
- new item(C)
\ No newline at end of file
+ new item(C)
diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm
index 4713d94106..11aae8a054 100644
--- a/code/modules/cargo/packs/armory.dm
+++ b/code/modules/cargo/packs/armory.dm
@@ -87,7 +87,7 @@
/datum/supply_pack/security/armory/mindshield
name = "Mindshield Implants Crate"
desc = "Prevent against radical thoughts with three Mindshield implants. Requires Armory access to open."
- cost = 4000
+ cost = 3000 //Lowered untill cargo rework MK II is done
contains = list(/obj/item/storage/lockbox/loyalty)
crate_name = "mindshield implant crate"
@@ -175,7 +175,7 @@
/datum/supply_pack/security/armory/swat
name = "SWAT Crate"
desc = "Contains two fullbody sets of tough, fireproof, pressurized suits designed in a joint effort by IS-ERI and Nanotrasen. Each set contains a suit, helmet, mask, combat belt, and combat gloves. Requires Armory access to open."
- cost = 6750
+ cost = 6000
contains = list(/obj/item/clothing/head/helmet/swat/nanotrasen,
/obj/item/clothing/head/helmet/swat/nanotrasen,
/obj/item/clothing/suit/space/swat,
@@ -199,7 +199,7 @@
/datum/supply_pack/security/armory/woodstock
name = "Classic WoodStock Shotguns Crate"
desc = "Contains three rustic, pumpaction shotguns. Requires Armory access to open."
- cost = 3500
+ cost = 3000
contains = list(/obj/item/gun/ballistic/shotgun,
/obj/item/gun/ballistic/shotgun,
/obj/item/gun/ballistic/shotgun)
@@ -208,7 +208,7 @@
/datum/supply_pack/security/armory/wt550
name = "WT-550 Semi-Auto Rifle Crate"
desc = "Contains two high-powered, semiautomatic rifles chambered in 4.6x30mm. Requires Armory access to open."
- cost = 3250
+ cost = 2550
contains = list(/obj/item/gun/ballistic/automatic/wt550,
/obj/item/gun/ballistic/automatic/wt550)
crate_name = "auto rifle crate"
@@ -216,7 +216,7 @@
/datum/supply_pack/security/armory/wt550ammo
name = "WT-550 Semi-Auto SMG Ammo Crate"
desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
- cost = 2750
+ cost = 1750
contains = list(/obj/item/ammo_box/magazine/wt550m9,
/obj/item/ammo_box/magazine/wt550m9,
/obj/item/ammo_box/magazine/wt550m9,
@@ -226,7 +226,7 @@
/datum/supply_pack/security/armory/wt550ammo_nonlethal // Takes around 12 shots to stun crit someone
name = "WT-550 Semi-Auto SMG Non-Lethal Ammo Crate"
desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
- cost = 1200
+ cost = 1000
contains = list(/obj/item/ammo_box/magazine/wt550m9/wtrubber,
/obj/item/ammo_box/magazine/wt550m9/wtrubber,
/obj/item/ammo_box/magazine/wt550m9/wtrubber,
@@ -236,7 +236,7 @@
/datum/supply_pack/security/armory/wt550ammo_special
name = "WT-550 Semi-Auto SMG Special Ammo Crate"
desc = "Contains 2 20-round Armour Piercing and Incendiary magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
- cost = 3500
+ cost = 3000
contains = list(/obj/item/ammo_box/magazine/wt550m9/wtap,
/obj/item/ammo_box/magazine/wt550m9/wtap,
/obj/item/ammo_box/magazine/wt550m9/wtic,
diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm
index be99199f30..1987369d20 100644
--- a/code/modules/cargo/packs/emergency.dm
+++ b/code/modules/cargo/packs/emergency.dm
@@ -12,7 +12,7 @@
/datum/supply_pack/emergency/vehicle
name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN
desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!"
- cost = 2800
+ cost = 2500
contraband = TRUE
contains = list(/obj/vehicle/ridden/atv,
/obj/item/key,
@@ -26,7 +26,7 @@
/datum/supply_pack/emergency/equipment
name = "Emergency Bot/Internals Crate"
desc = "Explosions got you down? These supplies are guaranteed to patch up holes, in stations and people alike! Comes with two floorbots, two medbots, five oxygen masks and five small oxygen tanks."
- cost = 3750
+ cost = 2750
contains = list(/mob/living/simple_animal/bot/floorbot,
/mob/living/simple_animal/bot/floorbot,
/mob/living/simple_animal/bot/medbot,
@@ -132,7 +132,7 @@
/datum/supply_pack/emergency/metalfoam
name = "Metal Foam Grenade Crate"
desc = "Seal up those pesky hull breaches with 14 Metal Foam Grenades."
- cost = 2000
+ cost = 1500
contains = list(/obj/item/storage/box/metalfoam,
/obj/item/storage/box/metalfoam)
crate_name = "metal foam grenade crate"
diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm
index 3d46b776c4..19cb53489e 100644
--- a/code/modules/cargo/packs/engineering.dm
+++ b/code/modules/cargo/packs/engineering.dm
@@ -55,7 +55,7 @@
/datum/supply_pack/engineering/engihardsuit
name = "Engineering Hardsuit"
desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and mask!"
- cost = 2750
+ cost = 2250
contains = list(/obj/item/tank/internals/air,
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/hardsuit/engine)
@@ -84,7 +84,7 @@
/datum/supply_pack/engineering/powergamermitts
name = "Insulated Gloves Crate"
desc = "The backbone of modern society. Barely ever ordered for actual engineering. Contains three insulated gloves."
- cost = 2750 //Made of pure-grade bullshittinium
+ cost = 2300 //Made of pure-grade bullshittinium
contains = list(/obj/item/clothing/gloves/color/yellow,
/obj/item/clothing/gloves/color/yellow,
/obj/item/clothing/gloves/color/yellow)
@@ -121,6 +121,18 @@
crate_name = "power cell crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engineering/siezedpower
+ name = "Siezed Power Cell Crate"
+ desc = "We took the means of power! Contains three high-voltage plus power cells."
+ cost = 1300
+ contraband = TRUE
+ contains = list(/obj/item/stock_parts/cell/high/plus,
+ /obj/item/stock_parts/cell/high/plus,
+ /obj/item/stock_parts/cell/high/plus)
+ crate_name = "siezed crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
/datum/supply_pack/engineering/shuttle_engine
name = "Shuttle Engine Crate"
desc = "Through advanced bluespace-shenanigans, our engineers have managed to fit an entire shuttle engine into one tiny little crate. Requires CE access to open."
@@ -129,7 +141,22 @@
contains = list(/obj/structure/shuttle/engine/propulsion/burst/cargo)
crate_name = "shuttle engine crate"
crate_type = /obj/structure/closet/crate/secure/engineering
- special = TRUE
+
+/datum/supply_pack/engineering/siezedproduction
+ name = "The Means of Production"
+ desc = "We will win for we have took over the production! S five metal sheets, five wire, three matter bins, one manipulater and one sheet of glass."
+ cost = 1500
+ contraband = TRUE
+ contains = list(/obj/item/stock_parts/cell/high/plus,
+ /obj/item/circuitboard/machine/autolathe,
+ /obj/item/stack/cable_coil/random/five,
+ /obj/item/stack/sheet/metal/five,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/manipulator,
+ /obj/item/stack/sheet/glass,)
+ crate_name = "siezed crate"
/datum/supply_pack/engineering/tools
name = "Toolbox Crate"
@@ -183,7 +210,6 @@
)
crate_name= "dna samplers crate"
-
/datum/supply_pack/engineering/shield_sat
name = "Shield Generator Satellite"
desc = "Protect the very existence of this station with these Anti-Meteor defenses. Contains three Shield Generator Satellites."
diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm
index e1d27c5022..656474cc1d 100644
--- a/code/modules/cargo/packs/medical.dm
+++ b/code/modules/cargo/packs/medical.dm
@@ -30,17 +30,31 @@
/datum/supply_pack/medical/bloodpacks
name = "Blood Pack Variety Crate"
- desc = "Contains eight different blood packs for reintroducing blood to patients."
+ desc = "Contains ten different blood packs for reintroducing blood to patients."
cost = 3000
- contains = list(/obj/item/reagent_containers/blood,
- /obj/item/reagent_containers/blood,
+ contains = list(/obj/item/reagent_containers/blood/random,
+ /obj/item/reagent_containers/blood/random,
/obj/item/reagent_containers/blood/APlus,
/obj/item/reagent_containers/blood/AMinus,
/obj/item/reagent_containers/blood/BPlus,
/obj/item/reagent_containers/blood/BMinus,
/obj/item/reagent_containers/blood/OPlus,
/obj/item/reagent_containers/blood/OMinus,
- /obj/item/reagent_containers/blood/lizard)
+ /obj/item/reagent_containers/blood/lizard,
+ /obj/item/reagent_containers/blood/jellyblood,
+ /obj/item/reagent_containers/blood/insect)
+ crate_name = "blood freezer"
+ crate_type = /obj/structure/closet/crate/freezer
+
+/datum/supply_pack/medical/bloodpackssynth
+ name = "Synthetics Blood Pack Crate"
+ desc = "Contains five synthetics blood packs for reintroducing blood to patients."
+ cost = 3000
+ contains = list(/obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics)
crate_name = "blood freezer"
crate_type = /obj/structure/closet/crate/freezer
diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm
index 56ddd92a76..c380d5411e 100644
--- a/code/modules/cargo/packs/misc.dm
+++ b/code/modules/cargo/packs/misc.dm
@@ -117,8 +117,8 @@
/datum/supply_pack/misc/paper_work
name = "Freelance Paper work"
- desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (10) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
- cost = 700 // Net of 0 credits
+ desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (20) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
+ cost = 700 // Net of 0 credits but makes (120 x 20 = 2400)
contains = list(/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
@@ -129,11 +129,18 @@
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain)
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/pen/fountain
+ )
crate_name = "Paperwork"
/datum/supply_pack/misc/funeral
@@ -149,7 +156,7 @@
/datum/supply_pack/misc/jukebox
name = "Jukebox"
- cost = 15000
+ cost = 10000
contains = list(/obj/machinery/jukebox)
crate_name = "Jukebox"
diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm
index c7f98cac0b..14bde519e1 100644
--- a/code/modules/cargo/packs/service.dm
+++ b/code/modules/cargo/packs/service.dm
@@ -36,7 +36,7 @@
/datum/supply_pack/service/carpet_exotic
name = "Exotic Carpet Crate"
desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns."
- cost = 10000
+ cost = 7000
contains = list(/obj/item/stack/tile/carpet/blue/fifty,
/obj/item/stack/tile/carpet/blue/fifty,
/obj/item/stack/tile/carpet/cyan/fifty,
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index 33a83487fc..8b2a34a089 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -561,7 +561,7 @@
/obj/item/storage/belt/chameleon/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.silent = TRUE
/obj/item/storage/belt/chameleon/emp_act(severity)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 20a8c518f4..1793bd8f4b 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -123,7 +123,7 @@
..()
if(damaged_clothes)
to_chat(user, "It looks damaged!")
- GET_COMPONENT(pockets, /datum/component/storage)
+ var/datum/component/storage/pockets = GetComponent(/datum/component/storage)
if(pockets)
var/list/how_cool_are_your_threads = list("")
if(pockets.attack_hand_interact)
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 4928de288f..f140fb3074 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -104,7 +104,7 @@
resistance_flags = ACID_PROOF
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
-/obj/item/clothing/glasses/science/item_action_slot_check(slot)
+/obj/item/clothing/glasses/science/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_GLASSES)
return 1
@@ -307,7 +307,7 @@
M.appearance_flags |= RESET_COLOR
M.color = "#[H.eye_color]"
. += M
-
+
/obj/item/clothing/glasses/sunglasses/big
desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks flashes."
icon_state = "bigsunglasses"
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index f0c1eeb833..6b674c8595 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -14,11 +14,10 @@
/obj/item/clothing/gloves/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /obj/item/clothing/gloves/clean_blood)
-/obj/item/clothing/gloves/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
+/obj/item/clothing/gloves/clean_blood(datum/source, strength)
+ . = ..()
transfer_blood = 0
/obj/item/clothing/gloves/suicide_act(mob/living/carbon/user)
@@ -30,8 +29,8 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves")
- IF_HAS_BLOOD_DNA(src)
- . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands")
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", color = blood_DNA_to_color())
/obj/item/clothing/gloves/update_clothes_damaged_state(damaging = TRUE)
..()
@@ -41,4 +40,4 @@
// Called just before an attack_hand(), in mob/UnarmedAttack()
/obj/item/clothing/gloves/proc/Touch(atom/A, proximity)
- return 0 // return 1 to cancel attack_hand()
\ No newline at end of file
+ return FALSE // return TRUE to cancel attack_hand()
\ No newline at end of file
diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm
index 8bd7065c1f..ccc167dcbc 100644
--- a/code/modules/clothing/head/_head.dm
+++ b/code/modules/clothing/head/_head.dm
@@ -46,8 +46,8 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet")
- IF_HAS_BLOOD_DNA(src)
- . += mutable_appearance('icons/effects/blood.dmi', "helmetblood")
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "helmetblood", color = blood_DNA_to_color())
/obj/item/clothing/head/update_clothes_damaged_state(damaging = TRUE)
..()
diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm
index 9ee2ebcd54..c00e6f72e0 100644
--- a/code/modules/clothing/masks/_masks.dm
+++ b/code/modules/clothing/masks/_masks.dm
@@ -59,8 +59,8 @@
if(body_parts_covered & HEAD)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
- IF_HAS_BLOOD_DNA(src)
- . += mutable_appearance('icons/effects/blood.dmi', "maskblood")
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color())
/obj/item/clothing/mask/update_clothes_damaged_state(damaging = TRUE)
..()
diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm
index 330f69ddaf..2356bb16eb 100644
--- a/code/modules/clothing/neck/_neck.dm
+++ b/code/modules/clothing/neck/_neck.dm
@@ -12,8 +12,8 @@
if(body_parts_covered & HEAD)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
- IF_HAS_BLOOD_DNA(src)
- . += mutable_appearance('icons/effects/blood.dmi', "maskblood")
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color())
/obj/item/clothing/neck/tie
name = "tie"
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 00cb2678cd..37ab2b2bf4 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -11,17 +11,19 @@
permeability_coefficient = 0.5
slowdown = SHOES_SLOWDOWN
var/blood_state = BLOOD_STATE_NOT_BLOODY
- var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
+ var/list/bloody_shoes = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
var/offset = 0
var/equipped_before_drop = FALSE
//CITADEL EDIT Enables digitigrade shoe styles
var/adjusted = NORMAL_STYLE
mutantrace_variation = MUTANTRACE_VARIATION
+ var/last_bloodtype = "" //used to track the last bloodtype to have graced these shoes; makes for better performing footprint shenanigans
+ var/last_blood_DNA = "" //same as last one
/obj/item/clothing/shoes/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /obj/item/clothing/shoes/clean_blood)
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
if(rand(2)>1)
@@ -42,22 +44,29 @@
playsound(user, 'sound/weapons/genhit2.ogg', 50, 1)
return(BRUTELOSS)
+
+/obj/item/clothing/shoes/transfer_blood_dna(list/blood_dna, diseases)
+ ..()
+ if(blood_dna.len)
+ last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
+ last_blood_DNA = blood_dna[blood_dna.len]
+
/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
var/bloody = FALSE
- IF_HAS_BLOOD_DNA(src)
+ if(blood_DNA)
bloody = TRUE
else
- bloody = bloody_shoes[BLOOD_STATE_HUMAN]
+ bloody = bloody_shoes[BLOOD_STATE_BLOOD]
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe")
if(bloody)
if(adjusted == NORMAL_STYLE)
- . += mutable_appearance('icons/effects/blood.dmi', "shoeblood")
+ . += mutable_appearance('icons/effects/blood.dmi', "shoeblood", color = blood_DNA_to_color())
else
- . += mutable_appearance('modular_citadel/icons/mob/digishoes.dmi', "shoeblood")
+ . += mutable_appearance('modular_citadel/icons/mob/digishoes.dmi', "shoeblood", color = blood_DNA_to_color())
/obj/item/clothing/shoes/equipped(mob/user, slot)
. = ..()
@@ -93,14 +102,13 @@
var/mob/M = loc
M.update_inv_shoes()
-/obj/item/clothing/shoes/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
- bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
+/obj/item/clothing/shoes/clean_blood(datum/source, strength)
+ . = ..()
+ bloody_shoes = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
blood_state = BLOOD_STATE_NOT_BLOODY
if(ismob(loc))
var/mob/M = loc
M.update_inv_shoes()
/obj/item/proc/negates_gravity()
- return FALSE
\ No newline at end of file
+ return FALSE
diff --git a/code/modules/clothing/shoes/bananashoes.dm b/code/modules/clothing/shoes/bananashoes.dm
index b634894805..d13e655d43 100644
--- a/code/modules/clothing/shoes/bananashoes.dm
+++ b/code/modules/clothing/shoes/bananashoes.dm
@@ -17,7 +17,7 @@
/obj/item/clothing/shoes/clown_shoes/banana_shoes/step_action()
. = ..()
- GET_COMPONENT(bananium, /datum/component/material_container)
+ var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
if(on)
if(bananium.amount(MAT_BANANIUM) < 100)
on = !on
@@ -30,7 +30,7 @@
bananium.use_amount_type(100, MAT_BANANIUM)
/obj/item/clothing/shoes/clown_shoes/banana_shoes/attack_self(mob/user)
- GET_COMPONENT(bananium, /datum/component/material_container)
+ var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
var/sheet_amount = bananium.retrieve_all()
if(sheet_amount)
to_chat(user, "You retrieve [sheet_amount] sheets of bananium from the prototype shoes.")
@@ -42,7 +42,7 @@
to_chat(user, "The shoes are [on ? "enabled" : "disabled"].")
/obj/item/clothing/shoes/clown_shoes/banana_shoes/ui_action_click(mob/user)
- GET_COMPONENT(bananium, /datum/component/material_container)
+ var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
if(bananium.amount(MAT_BANANIUM))
on = !on
update_icon()
diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm
index b105b72234..7ead462b1e 100644
--- a/code/modules/clothing/spacesuits/flightsuit.dm
+++ b/code/modules/clothing/spacesuits/flightsuit.dm
@@ -547,7 +547,7 @@
changeWearer()
..()
-/obj/item/flightpack/item_action_slot_check(slot)
+/obj/item/flightpack/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == ITEM_SLOT_BACK)
return TRUE
@@ -574,7 +574,7 @@
momentum_speed_y = 0
momentum_speed = max(momentum_speed_x, momentum_speed_y)
-/obj/item/flightpack/item_action_slot_check(slot)
+/obj/item/flightpack/item_action_slot_check(slot, mob/user, datum/action/A)
return slot == SLOT_BACK
/obj/item/flightpack/proc/enable_stabilizers()
@@ -730,7 +730,7 @@
if(!active)
clothing_flags &= ~NOSLIP
-/obj/item/clothing/shoes/flightshoes/item_action_slot_check(slot)
+/obj/item/clothing/shoes/flightshoes/item_action_slot_check(slot, mob/user, datum/action/A)
return slot == SLOT_SHOES
/obj/item/clothing/shoes/flightshoes/proc/delink_suit()
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index ea2905c5b9..d11c13a374 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -47,7 +47,7 @@
suit.RemoveHelmet()
soundloop.stop(user)
-/obj/item/clothing/head/helmet/space/hardsuit/item_action_slot_check(slot)
+/obj/item/clothing/head/helmet/space/hardsuit/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_HEAD)
return 1
@@ -158,7 +158,7 @@
var/datum/action/A = X
A.Remove(user)
-/obj/item/clothing/suit/space/hardsuit/item_action_slot_check(slot)
+/obj/item/clothing/suit/space/hardsuit/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to toggle the helmet if he's wearing the hardsuit.
return 1
@@ -605,7 +605,6 @@
armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75)
item_color = "ancient"
resistance_flags = FIRE_PROOF
- var/datum/component/mobhook
/obj/item/clothing/suit/space/hardsuit/ancient
name = "prototype RIG hardsuit"
@@ -617,7 +616,7 @@
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient
resistance_flags = FIRE_PROOF
var/footstep = 1
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/clothing/suit/space/hardsuit/ancient/mason
name = "M.A.S.O.N RIG"
@@ -674,20 +673,24 @@
/obj/item/clothing/suit/space/hardsuit/ancient/equipped(mob/user, slot)
. = ..()
- if (slot == SLOT_WEAR_SUIT)
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
- else
- QDEL_NULL(mobhook)
+ if(slot != SLOT_WEAR_SUIT)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ return
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
/obj/item/clothing/suit/space/hardsuit/ancient/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
/obj/item/clothing/suit/space/hardsuit/ancient/Destroy()
- QDEL_NULL(mobhook) // mobhook is not our component
+ listeningTo = null
return ..()
/////////////SHIELDED//////////////////////////////////
diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm
index 342429e480..932c08ed74 100644
--- a/code/modules/clothing/suits/_suits.dm
+++ b/code/modules/clothing/suits/_suits.dm
@@ -31,12 +31,12 @@
adjusted = NORMAL_STYLE
if(("taur" in H.dna.species.mutant_bodyparts) && (H.dna.features["taur"] != "None"))
- if(H.dna.features["taur"] in list("Naga", "Tentacle"))
+ if(H.dna.features["taur"] in GLOB.noodle_taurs)
taurmode = SNEK_TAURIC
if(tauric == TRUE)
center = TRUE
dimension_x = 64
- else if(H.dna.features["taur"] in list("Fox","Wolf","Otie","Drake","Lab","Shepherd","Husky","Eevee","Panther","Horse","Cow","Tiger","Deer"))
+ else if(H.dna.features["taur"] in GLOB.paw_taurs)
taurmode = PAW_TAURIC
if(tauric == TRUE)
center = TRUE
@@ -54,11 +54,11 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]")
- IF_HAS_BLOOD_DNA(src)
+ if(blood_DNA)
if(tauric)
- . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood")
+ . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color())
else
- . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood")
+ . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color())
var/mob/living/carbon/human/M = loc
if(ishuman(M) && M.w_uniform)
var/obj/item/clothing/under/U = M.w_uniform
diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm
index 5d534e00a7..cc983dbb0f 100644
--- a/code/modules/clothing/suits/toggles.dm
+++ b/code/modules/clothing/suits/toggles.dm
@@ -23,7 +23,7 @@
/obj/item/clothing/suit/hooded/ui_action_click()
ToggleHood()
-/obj/item/clothing/suit/hooded/item_action_slot_check(slot, mob/user)
+/obj/item/clothing/suit/hooded/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT || slot == SLOT_NECK)
return 1
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index c2c3f19b9d..eda0e31e93 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -22,8 +22,8 @@
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform")
- IF_HAS_BLOOD_DNA(src)
- . += mutable_appearance('icons/effects/blood.dmi', "uniformblood")
+ if(blood_DNA)
+ . += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = blood_DNA_to_color())
if(accessory_overlay)
. += accessory_overlay
diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm
index 6dd6164d79..706f7edb0a 100644
--- a/code/modules/clothing/under/accessories.dm
+++ b/code/modules/clothing/under/accessories.dm
@@ -12,7 +12,7 @@
var/datum/component/storage/detached_pockets
/obj/item/clothing/accessory/proc/attach(obj/item/clothing/under/U, user)
- GET_COMPONENT(storage, /datum/component/storage)
+ var/datum/component/storage/storage = GetComponent(/datum/component/storage)
if(storage)
if(SEND_SIGNAL(U, COMSIG_CONTAINS_STORAGE))
return FALSE
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index c892bfeffc..1a2405b9c4 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -1,111 +1,107 @@
//CONTAINS: Suit fibers and Detective's Scanning Computer
-/atom/proc/return_fingerprints()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.fingerprints
+/atom/proc/add_fibers(mob/living/carbon/human/M)
+ if(M.gloves && istype(M.gloves, /obj/item/clothing/))
+ var/obj/item/clothing/gloves/G = M.gloves
+ if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
+ if(add_blood_DNA(G.blood_DNA)) //only reduces the bloodiness of our gloves if the item wasn't already bloody
+ G.transfer_blood--
+ else if(M.bloody_hands > 1)
+ if(add_blood_DNA(M.blood_DNA, M.diseases))
+ M.bloody_hands--
+ if(!suit_fibers)
+ suit_fibers = list()
+ var/fibertext
+ var/item_multiplier = isitem(src)?1.2:1
+ if(M.wear_suit)
+ fibertext = "Material from \a [M.wear_suit]."
+ if(prob(10*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += fibertext
+ if(!(M.wear_suit.body_parts_covered & CHEST))
+ if(M.w_uniform)
+ fibertext = "Fibers from \a [M.w_uniform]."
+ if(prob(12*item_multiplier) && !(fibertext in suit_fibers)) //Wearing a suit means less of the uniform exposed.
+ suit_fibers += fibertext
+ if(!(M.wear_suit.body_parts_covered & HANDS))
+ if(M.gloves)
+ fibertext = "Material from a pair of [M.gloves.name]."
+ if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += fibertext
+ else if(M.w_uniform)
+ fibertext = "Fibers from \a [M.w_uniform]."
+ if(prob(15*item_multiplier) && !(fibertext in suit_fibers))
+ // "Added fibertext: [fibertext]"
+ suit_fibers += fibertext
+ if(M.gloves)
+ fibertext = "Material from a pair of [M.gloves.name]."
+ if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += "Material from a pair of [M.gloves.name]."
+ else if(M.gloves)
+ fibertext = "Material from a pair of [M.gloves.name]."
+ if(prob(20*item_multiplier) && !(fibertext in suit_fibers))
+ suit_fibers += "Material from a pair of [M.gloves.name]."
-/atom/proc/return_hiddenprints()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.hiddenprints
-/atom/proc/return_blood_DNA()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.blood_DNA
+/atom/proc/add_hiddenprint(mob/living/M)
+ if(!M || !M.key)
+ return
-/atom/proc/blood_DNA_length()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = length(D.blood_DNA)
+ if(!fingerprintshidden) //Add the list if it does not exist
+ fingerprintshidden = list()
-/atom/proc/return_fibers()
- GET_COMPONENT(D, /datum/component/forensics)
- if(D)
- . = D.fibers
+ var/hasgloves = ""
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(H.gloves)
+ hasgloves = "(gloves)"
+
+ var/current_time = TIME_STAMP("hh:mm:ss", FALSE)
+ if(!fingerprintshidden[M.key])
+ fingerprintshidden[M.key] = "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]"
+ else
+ var/laststamppos = findtext(fingerprintshidden[M.key], " Last: ")
+ if(laststamppos)
+ fingerprintshidden[M.key] = copytext(fingerprintshidden[M.key], 1, laststamppos)
+ fingerprintshidden[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]"
+
+ fingerprintslast = M.ckey
-/atom/proc/add_fingerprint_list(list/fingerprints) //ASSOC LIST FINGERPRINT = FINGERPRINT
- if(length(fingerprints))
- . = AddComponent(/datum/component/forensics, fingerprints)
//Set ignoregloves to add prints irrespective of the mob having gloves on.
/atom/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
- var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
- . = D.add_fingerprint(M, ignoregloves)
+ if(!M || !M.key)
+ return
-/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT
- if(length(fibertext))
- . = AddComponent(/datum/component/forensics, null, null, null, fibertext)
+ add_hiddenprint(M)
-/atom/proc/add_fibers(mob/living/carbon/human/M)
- var/old = 0
- if(M.gloves && istype(M.gloves, /obj/item/clothing))
- var/obj/item/clothing/gloves/G = M.gloves
- old = length(G.return_blood_DNA())
- if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
- if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody
- G.transfer_blood--
- else if(M.bloody_hands > 1)
- old = length(M.return_blood_DNA())
- if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old)
- M.bloody_hands--
- var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
- . = D.add_fibers(M)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
-/atom/proc/add_hiddenprint_list(list/hiddenprints) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM
- if(length(hiddenprints))
- . = AddComponent(/datum/component/forensics, null, hiddenprints)
+ add_fibers(H)
-/atom/proc/add_hiddenprint(mob/living/M)
- var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
- . = D.add_hiddenprint(M)
+ if(H.gloves) //Check if the gloves (if any) hide fingerprints
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.transfer_prints)
+ ignoregloves = TRUE
-/atom/proc/add_blood_DNA(list/dna) //ASSOC LIST DNA = BLOODTYPE
- return FALSE
+ if(!ignoregloves)
+ H.gloves.add_fingerprint(H, TRUE) //ignoregloves = TRUE to avoid infinite loop.
+ return
-/obj/add_blood_DNA(list/dna)
- . = ..()
- if(length(dna))
- . = AddComponent(/datum/component/forensics, null, null, dna)
-
-/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
- . = ..()
- transfer_blood = rand(2, 4)
-
-/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
- var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
- if(!B)
- B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
- B.add_blood_DNA(blood_dna) //give blood info to the blood decal.
- return TRUE //we bloodied the floor
-
-/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
- if(wear_suit)
- wear_suit.add_blood_DNA(blood_dna)
- update_inv_wear_suit()
- else if(w_uniform)
- w_uniform.add_blood_DNA(blood_dna)
- update_inv_w_uniform()
- if(gloves)
- var/obj/item/clothing/gloves/G = gloves
- G.add_blood_DNA(blood_dna)
- else if(length(blood_dna))
- AddComponent(/datum/component/forensics, null, null, blood_dna)
- bloody_hands = rand(2, 4)
- if(head)
- head.add_blood_DNA(blood_dna)
- update_inv_head()
- else if(wear_mask)
- wear_mask.add_blood_DNA(blood_dna)
- update_inv_wear_mask()
- if(wear_neck)
- wear_neck.add_blood_DNA(blood_dna)
- update_inv_neck()
- update_inv_gloves() //handles bloody hands overlays and updating
- return TRUE
+ LAZYINITLIST(fingerprints) //Add the list if it does not exist
+ var/full_print = md5(H.dna.uni_identity)
+ fingerprints[full_print] = full_print
/atom/proc/transfer_fingerprints_to(atom/A)
- A.add_fingerprint_list(return_fingerprints())
- A.add_hiddenprint_list(return_hiddenprints())
- A.fingerprintslast = fingerprintslast
+ // Make sure everything are lists.
+ LAZYINITLIST(A.fingerprints)
+ LAZYINITLIST(A.fingerprintshidden)
+ LAZYINITLIST(fingerprints)
+ LAZYINITLIST(fingerprintshidden)
+
+ // Transfer
+ if(fingerprints)
+ A.fingerprints |= fingerprints.Copy() //detective
+ if(fingerprintshidden)
+ A.fingerprintshidden |= fingerprintshidden.Copy() //admin
+ A.fingerprintslast = fingerprintslast
\ No newline at end of file
diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm
index a3b17a4c1f..5b4a75a36c 100644
--- a/code/modules/detectivework/evidence.dm
+++ b/code/modules/detectivework/evidence.dm
@@ -16,7 +16,7 @@
/obj/item/evidencebag/attackby(obj/item/I, mob/user, params)
if(evidencebagEquip(I, user))
- return 1
+ return TRUE
/obj/item/evidencebag/handle_atom_del(atom/A)
cut_overlays()
@@ -25,12 +25,12 @@
desc = initial(desc)
/obj/item/evidencebag/proc/evidencebagEquip(obj/item/I, mob/user)
- if(!istype(I) || I.anchored == 1)
+ if(!istype(I) || I.anchored == TRUE)
return
if(istype(I, /obj/item/evidencebag))
to_chat(user, "You find putting an evidence bag in another evidence bag to be slightly absurd.")
- return 1 //now this is podracing
+ return TRUE //now this is podracing
if(I.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user, "[I] won't fit in [src].")
@@ -62,7 +62,7 @@
desc = "An evidence bag containing [I]. [I.desc]"
I.forceMove(src)
w_class = I.w_class
- return 1
+ return TRUE
/obj/item/evidencebag/attack_self(mob/user)
if(contents.len)
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index fd7591db81..c578d5b4d4 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -14,7 +14,7 @@
flags_1 = CONDUCT_1
item_flags = NOBLUDGEON
slot_flags = ITEM_SLOT_BELT
- var/scanning = 0
+ var/scanning = FALSE
var/list/log = list()
var/range = 8
var/view_check = TRUE
@@ -30,7 +30,7 @@
/obj/item/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
- scanning = 1
+ scanning = TRUE
to_chat(user, "Printing report, please wait...")
addtimer(CALLBACK(src, .proc/PrintReport), 100)
else
@@ -56,7 +56,7 @@
// Clear the logs
log = list()
- scanning = 0
+ scanning = FALSE
/obj/item/detective_scanner/afterattack(atom/A, mob/user, params)
. = ..()
@@ -70,7 +70,7 @@
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
return
- scanning = 1
+ scanning = TRUE
user.visible_message("\The [user] points the [src.name] at \the [A] and performs a forensic scan.")
to_chat(user, "You scan \the [A]. The scanner is now analysing the results...")
@@ -80,14 +80,20 @@
//Make our lists
var/list/fingerprints = list()
- var/list/blood = A.return_blood_DNA()
- var/list/fibers = A.return_fibers()
+ var/list/blood = list()
+ var/list/fibers = list()
var/list/reagents = list()
var/target_name = A.name
// Start gathering
+ if(A.blood_DNA && A.blood_DNA.len)
+ blood = A.blood_DNA.Copy()
+
+ if(A.suit_fibers && A.suit_fibers.len)
+ fibers = A.suit_fibers.Copy()
+
if(ishuman(A))
var/mob/living/carbon/human/H = A
@@ -96,7 +102,8 @@
else if(!ismob(A))
- fingerprints = A.return_fingerprints()
+ if(A.fingerprints && A.fingerprints.len)
+ fingerprints = A.fingerprints.Copy()
// Only get reagents from non-mobs.
if(A.reagents && A.reagents.reagent_list.len)
@@ -115,40 +122,40 @@
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
- var/found_something = 0
+ var/found_something = FALSE
add_log("[STATION_TIME_TIMESTAMP("hh:mm:ss")][get_timestamp()] - [target_name]", 0)
// Fingerprints
if(length(fingerprints))
- sleep(30)
+ sleep(3 SECONDS)
add_log("Prints:")
for(var/finger in fingerprints)
add_log("[finger]")
- found_something = 1
+ found_something = TRUE
// Blood
if (length(blood))
- sleep(30)
+ sleep(3 SECONDS)
add_log("Blood:")
- found_something = 1
+ found_something = TRUE
for(var/B in blood)
add_log("Type: [blood[B]] DNA: [B]")
//Fibers
if(length(fibers))
- sleep(30)
+ sleep(3 SECONDS)
add_log("Fibers:")
for(var/fiber in fibers)
add_log("[fiber]")
- found_something = 1
+ found_something = TRUE
//Reagents
if(length(reagents))
- sleep(30)
+ sleep(3 SECONDS)
add_log("Reagents:")
for(var/R in reagents)
add_log("Reagent: [R] Volume: [reagents[R]]")
- found_something = 1
+ found_something = TRUE
// Get a new user
var/mob/holder = null
@@ -164,10 +171,10 @@
to_chat(holder, "You finish scanning \the [target_name].")
add_log("---------------------------------------------------------", 0)
- scanning = 0
+ scanning = FALSE
return
-/obj/item/detective_scanner/proc/add_log(msg, broadcast = 1)
+/obj/item/detective_scanner/proc/add_log(msg, broadcast = TRUE)
if(scanning)
if(broadcast && ismob(loc))
var/mob/M = loc
@@ -207,4 +214,4 @@
return
to_chat(user, "Scanner Report")
for(var/iterLog in log)
- to_chat(user, iterLog)
+ to_chat(user, iterLog)
\ No newline at end of file
diff --git a/code/modules/events/wizard/rpgloot.dm b/code/modules/events/wizard/rpgloot.dm
index 420582ddab..3d560aefb8 100644
--- a/code/modules/events/wizard/rpgloot.dm
+++ b/code/modules/events/wizard/rpgloot.dm
@@ -13,7 +13,7 @@
if(istype(I, /obj/item/storage))
var/obj/item/storage/S = I
- GET_COMPONENT_FROM(STR, /datum/component/storage, S)
+ var/datum/component/storage/STR = S.GetComponent(/datum/component/storage)
if(prob(upgrade_scroll_chance) && S.contents.len < STR.max_items && !S.invisibility)
var/obj/item/upgradescroll/scroll = new
SEND_SIGNAL(S, COMSIG_TRY_STORAGE_INSERT, scroll, null, TRUE, TRUE)
diff --git a/code/modules/fields/fields.dm b/code/modules/fields/fields.dm
index 5e34c934d9..5b0b4bc1f8 100644
--- a/code/modules/fields/fields.dm
+++ b/code/modules/fields/fields.dm
@@ -283,7 +283,7 @@
var/field_type = /datum/proximity_monitor/advanced/debug
var/operating = FALSE
var/datum/proximity_monitor/advanced/current = null
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/multitool/field_debug/Initialize()
. = ..()
@@ -292,7 +292,7 @@
/obj/item/multitool/field_debug/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_NULL(current)
- QDEL_NULL(mobhook)
+ listeningTo = null
return ..()
/obj/item/multitool/field_debug/proc/setup_debug_field()
@@ -303,16 +303,20 @@
/obj/item/multitool/field_debug/attack_self(mob/user)
operating = !operating
to_chat(user, "You turn [src] [operating? "on":"off"].")
- QDEL_NULL(mobhook)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
if(!istype(current) && operating)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
setup_debug_field()
else if(!operating)
QDEL_NULL(current)
/obj/item/multitool/field_debug/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
/obj/item/multitool/field_debug/proc/on_mob_move()
check_turf(get_turf(src))
diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm
index 9b87002738..b468b6b1d1 100644
--- a/code/modules/food_and_drinks/food/snacks_pastry.dm
+++ b/code/modules/food_and_drinks/food/snacks_pastry.dm
@@ -38,9 +38,7 @@
if(M.mind && HAS_TRAIT(M.mind, TRAIT_LAW_ENFORCEMENT_METABOLISM) && !HAS_TRAIT(H, TRAIT_AGEUSIA))
to_chat(H,"I love this taste!")
H.adjust_disgust(-5 + -2.5 * fraction)
- GET_COMPONENT_FROM(mood, /datum/component/mood, H)
- if(mood)
- mood.add_event(null, "fav_food", /datum/mood_event/favorite_food)
+ SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "fav_food", /datum/mood_event/favorite_food)
last_check_time = world.time
return
..()
diff --git a/code/modules/holiday/easter.dm b/code/modules/holiday/easter.dm
index 829cb55312..f2d7fa1526 100644
--- a/code/modules/holiday/easter.dm
+++ b/code/modules/holiday/easter.dm
@@ -68,7 +68,7 @@
/obj/item/storage/bag/easterbasket/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/egg, /obj/item/reagent_containers/food/snacks/chocolateegg, /obj/item/reagent_containers/food/snacks/boiledegg))
/obj/item/storage/bag/easterbasket/proc/countEggs()
diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm
index ffa9e2e21d..d9bea64411 100644
--- a/code/modules/hydroponics/seed_extractor.dm
+++ b/code/modules/hydroponics/seed_extractor.dm
@@ -174,7 +174,7 @@
to_chat(usr, "\The [src] is full.")
return FALSE
- GET_COMPONENT_FROM(STR, /datum/component/storage, O.loc)
+ var/datum/component/storage/STR = O.loc.GetComponent(/datum/component/storage)
if(STR)
if(!STR.remove_from_storage(O,src))
return FALSE
diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm
index b258a15972..b7feedd312 100644
--- a/code/modules/integrated_electronics/subtypes/input.dm
+++ b/code/modules/integrated_electronics/subtypes/input.dm
@@ -893,7 +893,7 @@
return FALSE
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
- GET_COMPONENT_FROM(STR, /datum/component/storage, A)
+ var/datum/component/storage/STR = A.GetComponent(/datum/component/storage)
if(STR)
return FALSE
set_pin_data(IC_OUTPUT, 1, WEAKREF(A))
@@ -1104,7 +1104,7 @@
/obj/item/integrated_circuit/input/matscan/do_work()
var/atom/movable/H = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/turf/T = get_turf(src)
- GET_COMPONENT_FROM(mt, /datum/component/material_container, H)
+ var/datum/component/material_container/mt = H.GetComponent(/datum/component/material_container)
if(!mt) //Invalid input
return
if(H in view(T)) // This is a camera. It can't examine thngs,that it can't see.
diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm
index 682e76a46e..81961c2d9c 100644
--- a/code/modules/integrated_electronics/subtypes/manipulation.dm
+++ b/code/modules/integrated_electronics/subtypes/manipulation.dm
@@ -411,7 +411,7 @@
.=..()
/obj/item/integrated_circuit/manipulation/matman/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
set_pin_data(IC_OUTPUT, 2, materials.total_amount)
for(var/I in 1 to mtypes.len)
var/datum/material/M = materials.materials[mtypes[I]]
@@ -423,7 +423,7 @@
return TRUE
/obj/item/integrated_circuit/manipulation/matman/do_work(ord)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/movable/H = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(!check_target(H))
activate_pin(4)
@@ -441,7 +441,7 @@
else
activate_pin(4)
if(2)
- GET_COMPONENT_FROM(mt, /datum/component/material_container, H)
+ var/datum/component/material_container/mt = H.GetComponent(/datum/component/material_container)
var/suc
for(var/I in 1 to mtypes.len)
var/datum/material/M = materials.materials[mtypes[I]]
@@ -467,7 +467,7 @@
activate_pin(6)
/obj/item/integrated_circuit/manipulation/matman/Destroy()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
.=..()
@@ -509,14 +509,14 @@
if(!container || !istype(container,/obj/item/storage) || !Adjacent(container))
return
- GET_COMPONENT_FROM(STR, /datum/component/storage, container)
+ var/datum/component/storage/STR = container.GetComponent(/datum/component/storage)
if(!STR)
return
STR.attackby(src, target_obj)
else
- GET_COMPONENT_FROM(STR, /datum/component/storage, target_obj.loc)
+ var/datum/component/storage/STR = target_obj.loc.GetComponent(/datum/component/storage)
if(!STR)
return
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index ee563f3100..7dc4fd17b9 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -78,7 +78,7 @@
state = 0
if(2)
- GET_COMPONENT_FROM(STR, /datum/component/storage, I)
+ var/datum/component/storage/STR = I.GetComponent(/datum/component/storage)
if(is_type_in_list(I, allowed_books))
if(!user.transferItemToLoc(I, src))
return
diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm
index c0c5a411e7..9ceb341f91 100644
--- a/code/modules/lighting/lighting_object.dm
+++ b/code/modules/lighting/lighting_object.dm
@@ -5,7 +5,7 @@
icon = LIGHTING_ICON
icon_state = "transparent"
- color = LIGHTING_BASE_MATRIX
+ color = null //we manually set color in init instead
plane = LIGHTING_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = LIGHTING_LAYER
@@ -17,6 +17,9 @@
/atom/movable/lighting_object/Initialize(mapload)
. = ..()
verbs.Cut()
+ //We avoid setting this in the base as if we do then the parent atom handling will add_atom_color it and that
+ //is totally unsuitable for this object, as we are always changing its colour manually
+ color = LIGHTING_BASE_MATRIX
myturf = loc
if (myturf.lighting_object)
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 5990c70813..9b9d6dd3bb 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -205,7 +205,7 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/mob/living/carbon/human/active_owner
-/obj/item/clothing/neck/necklace/memento_mori/item_action_slot_check(slot)
+/obj/item/clothing/neck/necklace/memento_mori/item_action_slot_check(slot, mob/user, datum/action/A)
return slot == SLOT_NECK
/obj/item/clothing/neck/necklace/memento_mori/dropped(mob/user)
@@ -796,21 +796,21 @@
/obj/item/melee/ghost_sword/proc/ghost_check()
var/list/mob/dead/observer/current_spirits = list()
-
+
recursive_orbit_collect(src, current_spirits)
recursive_orbit_collect(loc, current_spirits) //anything holding us
-
+
for(var/i in spirits - current_spirits)
var/mob/dead/observer/G = i
G.invisibility = GLOB.observer_default_invisibility
-
+
for(var/i in current_spirits)
var/mob/dead/observer/G = i
G.invisibility = 0
-
+
spirits = current_spirits
return length(spirits)
-
+
/obj/item/melee/ghost_sword/attack(mob/living/target, mob/living/carbon/human/user)
force = 0
var/ghost_counter = ghost_check()
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index a004a6ae0d..4d8624864e 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -95,7 +95,7 @@
process_ore(AM)
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(O)
if(!materials.has_space(material_amount))
unload_mineral(O)
@@ -107,7 +107,7 @@
/obj/machinery/mineral/processing_unit/proc/get_machine_data()
var/dat = "Smelter control console
"
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
dat += "[M.name]: [M.amount] cm³"
@@ -152,7 +152,7 @@
CONSOLE.updateUsrDialog()
/obj/machinery/mineral/processing_unit/proc/smelt_ore()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/datum/material/mat = materials.materials[selected_material]
if(mat)
var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT)
@@ -175,7 +175,7 @@
on = FALSE
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_amount(alloy.materials, amount)
generate_mineral(alloy.build_path)
@@ -186,7 +186,7 @@
var/build_amount = SMELT_AMOUNT
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
@@ -204,7 +204,7 @@
unload_mineral(O)
/obj/machinery/mineral/processing_unit/on_deconstruction()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
..()
diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm
index 8fdc50d2ac..c42f1b9f4e 100644
--- a/code/modules/mining/machine_silo.dm
+++ b/code/modules/mining/machine_silo.dm
@@ -34,13 +34,13 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
var/datum/component/remote_materials/mats = C
mats.disconnect_from(src)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
/obj/machinery/ore_silo/proc/remote_attackby(obj/machinery/M, mob/user, obj/item/stack/I)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
// stolen from /datum/component/material_container/proc/OnAttackBy
if(user.a_intent != INTENT_HELP)
return
@@ -71,7 +71,7 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
popup.open()
/obj/machinery/ore_silo/proc/generate_ui()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/list/ui = list("Ore SiloStored Material:
")
var/any = FALSE
for(var/M in materials.materials)
@@ -149,7 +149,7 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
return TRUE
else if(href_list["ejectsheet"])
var/eject_sheet = href_list["ejectsheet"]
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/count = materials.retrieve_sheets(text2num(href_list["eject_amt"]), eject_sheet, drop_location())
var/list/matlist = list()
matlist[eject_sheet] = MINERAL_MATERIAL_AMOUNT
diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm
index 6b03be610d..8204977058 100644
--- a/code/modules/mining/mint.dm
+++ b/code/modules/mining/mint.dm
@@ -22,7 +22,7 @@
if(!T)
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/obj/item/stack/sheet/O in T)
materials.insert_stack(O, O.amount)
@@ -32,7 +32,7 @@
return
var/dat = "
Coin Press"
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
if(!M.amount && chosen != mat_id)
@@ -65,7 +65,7 @@
if(processing==1)
to_chat(usr, "
The machine is processing.")
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(href_list["choose"])
if(materials.materials[href_list["choose"]])
chosen = href_list["choose"]
diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm
index f567bd1daf..fd5997d3c4 100644
--- a/code/modules/mining/money_bag.dm
+++ b/code/modules/mining/money_bag.dm
@@ -11,7 +11,7 @@
/obj/item/storage/bag/money/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_items = 40
STR.max_combined_w_class = 40
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 591fc650b4..4d253a4693 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -151,7 +151,7 @@
message_admins(msg)
to_chat(usr, "
The round is either not ready, or has already finished...")
return
-
+
if(!GLOB.enter_allowed)
to_chat(usr, "
There is an administrative lock on entering the game!")
return
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm b/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm
index 2f1d48cfa7..156cc304a6 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm
@@ -54,6 +54,10 @@
name = "Redpanda"
icon_state = "redpanda"
+/datum/sprite_accessory/mam_body_markings/bat
+ name = "Bat"
+ icon_state = "bat"
+
/datum/sprite_accessory/mam_body_markings/bee
name = "Bee"
icon_state = "bee"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
index 1496ca030a..ca1253feb1 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
@@ -176,6 +176,10 @@
name = "Axolotl"
icon_state = "axolotl"
+/datum/sprite_accessory/mam_ears/bat
+ name = "Bat"
+ icon_state = "bat"
+
/datum/sprite_accessory/mam_ears/bear
name = "Bear"
icon_state = "bear"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
index 7252f85324..be2ab152a8 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
@@ -194,6 +194,10 @@
name = "Mammal, Short ALT"
icon_state = "scanidalt"
+/datum/sprite_accessory/mam_snouts/scanidalt2
+ name = "Mammal, Short ALT 2"
+ icon_state = "scanidalt2"
+
/datum/sprite_accessory/mam_snouts/wolf
name = "Mammal, Thick"
icon_state = "wolf"
@@ -306,6 +310,10 @@
name = "Mammal, Short ALT (Top)"
icon_state = "fscanidalt"
+/datum/sprite_accessory/mam_snouts/fscanidalt2
+ name = "Mammal, Short ALT 2 (Top)"
+ icon_state = "fscanidalt2"
+
/datum/sprite_accessory/mam_snouts/fwolf
name = "Mammal, Thick (Top)"
icon_state = "fwolf"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
index 3975f7bafc..33b174afa4 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
@@ -114,6 +114,26 @@
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
+/datum/sprite_accessory/mam_tails/batl
+ name = "Bat (Long)"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ icon_state = "batl"
+
+/datum/sprite_accessory/mam_tails_animated/batl
+ name = "Bat (Long)"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ icon_state = "batl"
+
+/datum/sprite_accessory/mam_tails/bats
+ name = "Bat (Short)"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ icon_state = "bats"
+
+/datum/sprite_accessory/mam_tails_animated/bats
+ name = "Bat (Short)"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ icon_state = "bats"
+
/datum/sprite_accessory/tails/human/bee
name = "Bee"
icon_state = "bee"
@@ -469,6 +489,22 @@
name = "Axolotl"
icon_state = "axolotl"
+/datum/sprite_accessory/mam_tails/batl
+ name = "Bat (Long)"
+ icon_state = "batl"
+
+/datum/sprite_accessory/mam_tails_animated/batl
+ name = "Bat (Long)"
+ icon_state = "batl"
+
+/datum/sprite_accessory/mam_tails/bats
+ name = "Bat (Short)"
+ icon_state = "bats"
+
+/datum/sprite_accessory/mam_tails_animated/bats
+ name = "Bat (Short)"
+ icon_state = "bats"
+
/datum/sprite_accessory/mam_tails/bee
name = "Bee"
icon_state = "bee"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/wings.dm b/code/modules/mob/dead/new_player/sprite_accessories/wings.dm
index 6c42177c3c..46a123c6bb 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/wings.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/wings.dm
@@ -28,74 +28,14 @@
locked = TRUE
// Decorative wings
+
/datum/sprite_accessory/deco_wings
icon = 'icons/mob/wings.dmi'
color_src = WINGCOLOR
-/datum/sprite_accessory/deco_wings/plain
- name = "Plain"
- icon_state = "plain"
-
-/datum/sprite_accessory/deco_wings/monarch
- name = "Monarch"
- icon_state = "monarch"
-
-/datum/sprite_accessory/deco_wings/luna
- name = "Luna"
- icon_state = "luna"
-
-/datum/sprite_accessory/deco_wings/atlas
- name = "Atlas"
- icon_state = "atlas"
-
-/datum/sprite_accessory/deco_wings/reddish
- name = "Reddish"
- icon_state = "redish"
-
-/datum/sprite_accessory/deco_wings/royal
- name = "Royal"
- icon_state = "royal"
-
-/datum/sprite_accessory/deco_wings/gothic
- name = "Gothic"
- icon_state = "gothic"
-
-/datum/sprite_accessory/deco_wings/lovers
- name = "Lovers"
- icon_state = "lovers"
-
-/datum/sprite_accessory/deco_wings/whitefly
- name = "White Fly"
- icon_state = "whitefly"
-
-/datum/sprite_accessory/deco_wings/punished
- name = "Burnt Off"
- icon_state = "punished"
- locked = TRUE
-
-/datum/sprite_accessory/deco_wings/firewatch
- name = "Firewatch"
- icon_state = "firewatch"
-
-/datum/sprite_accessory/deco_wings/deathhead
- name = "Deathshead"
- icon_state = "deathhead"
-
-/datum/sprite_accessory/deco_wings/poison
- name = "Poison"
- icon_state = "poison"
-
-/datum/sprite_accessory/deco_wings/ragged
- name = "Ragged"
- icon_state = "ragged"
-
-/datum/sprite_accessory/deco_wings/moonfly
- name = "Moon Fly"
- icon_state = "moonfly"
-
-/datum/sprite_accessory/deco_wings/snow
- name = "Snow"
- icon_state = "snow"
+/datum/sprite_accessory/deco_wings/none
+ name = "None"
+ icon_state = "none"
/datum/sprite_accessory/deco_wings/angel
name = "Angel"
@@ -105,6 +45,10 @@
center = TRUE
dimension_y = 34
+/datum/sprite_accessory/deco_wings/bat
+ name = "Bat"
+ icon_state = "bat"
+
/datum/sprite_accessory/deco_wings/bee
name = "Bee"
icon_state = "bee"
@@ -113,18 +57,73 @@
name = "Fairy"
icon_state = "fairy"
-/datum/sprite_accessory/deco_wings/bat
- name = "Bat"
- icon_state = "bat"
-
/datum/sprite_accessory/deco_wings/feathery
name = "Feathery"
icon_state = "feathery"
-/datum/sprite_accessory/deco_wings/none
- name = "None"
- icon_state = "none"
+/datum/sprite_accessory/deco_wings/atlas
+ name = "Atlas"
+ icon_state = "atlas"
+/datum/sprite_accessory/deco_wings/deathhead
+ name = "Deathshead"
+ icon_state = "deathhead"
+
+/datum/sprite_accessory/deco_wings/firewatch
+ name = "Firewatch"
+ icon_state = "firewatch"
+
+/datum/sprite_accessory/deco_wings/gothic
+ name = "Gothic"
+ icon_state = "gothic"
+
+/datum/sprite_accessory/deco_wings/lovers
+ name = "Lovers"
+ icon_state = "lovers"
+
+/datum/sprite_accessory/deco_wings/luna
+ name = "Luna"
+ icon_state = "luna"
+
+/datum/sprite_accessory/deco_wings/monarch
+ name = "Monarch"
+ icon_state = "monarch"
+
+/datum/sprite_accessory/deco_wings/moonfly
+ name = "Moon Fly"
+ icon_state = "moonfly"
+
+/datum/sprite_accessory/deco_wings/plain
+ name = "Plain"
+ icon_state = "plain"
+
+/datum/sprite_accessory/deco_wings/poison
+ name = "Poison"
+ icon_state = "poison"
+
+/datum/sprite_accessory/deco_wings/punished
+ name = "Burnt Off"
+ icon_state = "punished"
+
+/datum/sprite_accessory/deco_wings/ragged
+ name = "Ragged"
+ icon_state = "ragged"
+
+/datum/sprite_accessory/deco_wings/reddish
+ name = "Reddish"
+ icon_state = "redish"
+
+/datum/sprite_accessory/deco_wings/royal
+ name = "Royal"
+ icon_state = "royal"
+
+/datum/sprite_accessory/deco_wings/snow
+ name = "Snow"
+ icon_state = "snow"
+
+/datum/sprite_accessory/deco_wings/whitefly
+ name = "White Fly"
+ icon_state = "whitefly"
//INSECT WINGS
@@ -136,69 +135,9 @@
name = "None"
icon_state = "none"
-/datum/sprite_accessory/insect_wings/plain
- name = "Plain"
- icon_state = "plain"
-
-/datum/sprite_accessory/insect_wings/monarch
- name = "Monarch"
- icon_state = "monarch"
-
-/datum/sprite_accessory/insect_wings/luna
- name = "Luna"
- icon_state = "luna"
-
-/datum/sprite_accessory/insect_wings/atlas
- name = "Atlas"
- icon_state = "atlas"
-
-/datum/sprite_accessory/insect_wings/reddish
- name = "Reddish"
- icon_state = "redish"
-
-/datum/sprite_accessory/insect_wings/royal
- name = "Royal"
- icon_state = "royal"
-
-/datum/sprite_accessory/insect_wings/gothic
- name = "Gothic"
- icon_state = "gothic"
-
-/datum/sprite_accessory/insect_wings/lovers
- name = "Lovers"
- icon_state = "lovers"
-
-/datum/sprite_accessory/insect_wings/whitefly
- name = "White Fly"
- icon_state = "whitefly"
-
-/datum/sprite_accessory/insect_wings/punished
- name = "Burnt Off"
- icon_state = "punished"
-
-/datum/sprite_accessory/insect_wings/firewatch
- name = "Firewatch"
- icon_state = "firewatch"
-
-/datum/sprite_accessory/insect_wings/deathhead
- name = "Deathshead"
- icon_state = "deathhead"
-
-/datum/sprite_accessory/insect_wings/poison
- name = "Poison"
- icon_state = "poison"
-
-/datum/sprite_accessory/insect_wings/ragged
- name = "Ragged"
- icon_state = "ragged"
-
-/datum/sprite_accessory/insect_wings/moonfly
- name = "Moon Fly"
- icon_state = "moonfly"
-
-/datum/sprite_accessory/insect_wings/snow
- name = "Snow"
- icon_state = "snow"
+/datum/sprite_accessory/insect_wings/bat
+ name = "Bat"
+ icon_state = "bat"
/datum/sprite_accessory/insect_wings/bee
name = "Bee"
@@ -208,10 +147,70 @@
name = "Fairy"
icon_state = "fairy"
-/datum/sprite_accessory/insect_wings/bat
- name = "Bat"
- icon_state = "bat"
-
/datum/sprite_accessory/insect_wings/feathery
name = "Feathery"
icon_state = "feathery"
+
+/datum/sprite_accessory/insect_wings/atlas
+ name = "Atlas"
+ icon_state = "atlas"
+
+/datum/sprite_accessory/insect_wings/deathhead
+ name = "Deathshead"
+ icon_state = "deathhead"
+
+/datum/sprite_accessory/insect_wings/firewatch
+ name = "Firewatch"
+ icon_state = "firewatch"
+
+/datum/sprite_accessory/insect_wings/gothic
+ name = "Gothic"
+ icon_state = "gothic"
+
+/datum/sprite_accessory/insect_wings/lovers
+ name = "Lovers"
+ icon_state = "lovers"
+
+/datum/sprite_accessory/insect_wings/luna
+ name = "Luna"
+ icon_state = "luna"
+
+/datum/sprite_accessory/insect_wings/monarch
+ name = "Monarch"
+ icon_state = "monarch"
+
+/datum/sprite_accessory/insect_wings/moonfly
+ name = "Moon Fly"
+ icon_state = "moonfly"
+
+/datum/sprite_accessory/insect_wings/plain
+ name = "Plain"
+ icon_state = "plain"
+
+/datum/sprite_accessory/insect_wings/poison
+ name = "Poison"
+ icon_state = "poison"
+
+/datum/sprite_accessory/insect_wings/punished
+ name = "Burnt Off"
+ icon_state = "punished"
+
+/datum/sprite_accessory/insect_wings/ragged
+ name = "Ragged"
+ icon_state = "ragged"
+
+/datum/sprite_accessory/insect_wings/reddish
+ name = "Reddish"
+ icon_state = "redish"
+
+/datum/sprite_accessory/insect_wings/royal
+ name = "Royal"
+ icon_state = "royal"
+
+/datum/sprite_accessory/insect_wings/snow
+ name = "Snow"
+ icon_state = "snow"
+
+/datum/sprite_accessory/insect_wings/whitefly
+ name = "White Fly"
+ icon_state = "whitefly"
\ No newline at end of file
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index 625a923fe1..41d3d4e158 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -40,7 +40,7 @@
if(iscyborg(user) && user.has_buckled_mobs())
var/mob/living/silicon/robot/R = user
- GET_COMPONENT_FROM(riding_datum, /datum/component/riding, R)
+ var/datum/component/riding/riding_datum = R.GetComponent(/datum/component/riding)
if(riding_datum)
for(var/mob/M in R.buckled_mobs)
riding_datum.force_dismount(M)
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index ca1a961a92..757aadaea1 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -2,6 +2,9 @@
BLOOD SYSTEM
****************************************************/
+#define EXOTIC_BLEED_MULTIPLIER 4 //Multiplies the actually bled amount by this number for the purposes of turf reaction calculations.
+
+
/mob/living/carbon/human/proc/suppress_bloodloss(amount)
if(bleedsuppress)
return
@@ -30,6 +33,9 @@
bleed_rate = 0
return
+ if(bleed_rate <= 0)
+ bleed_rate = 0
+
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood.
//Blood regeneration if there is some space
@@ -80,6 +86,9 @@
var/obj/item/bodypart/BP = X
var/brutedamage = BP.brute_dam
+ if(BP.status == BODYPART_ROBOTIC) //for the moment, synth limbs won't bleed, but soon, my pretty.
+ continue
+
//We want an accurate reading of .len
listclearnulls(BP.embedded_objects)
temp_bleed += 0.5*BP.embedded_objects.len
@@ -87,7 +96,7 @@
if(brutedamage >= 20)
temp_bleed += (brutedamage * 0.013)
- bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
+ bleed_rate = max(bleed_rate - 0.50, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
if(bleed_rate && !bleedsuppress && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
bleed(bleed_rate)
@@ -105,9 +114,11 @@
/mob/living/carbon/human/bleed(amt)
amt *= physiology.bleed_mod
if(!(NOBLOOD in dna.species.species_traits))
- ..()
-
-
+ .=..()
+ if(dna.species.exotic_blood && .) // Do we have exotic blood, and have we left any on the ground?
+ var/datum/reagent/R = GLOB.chemical_reagents_list[get_blood_id()]
+ if(istype(R) && isturf(loc))
+ R.reaction_turf(get_turf(src), amt * EXOTIC_BLEED_MULTIPLIER)
/mob/living/proc/restore_blood()
blood_volume = initial(blood_volume)
@@ -123,16 +134,16 @@
//Gets blood from mob to a container or other mob, preserving all data in it.
/mob/living/proc/transfer_blood_to(atom/movable/AM, amount, forced)
if(!blood_volume || !AM.reagents)
- return 0
+ return FALSE
if(blood_volume < (BLOOD_VOLUME_BAD * blood_ratio) && !forced)
- return 0
+ return FALSE
if(blood_volume < amount)
amount = blood_volume
var/blood_id = get_blood_id()
if(!blood_id)
- return 0
+ return FALSE
blood_volume -= amount
@@ -141,29 +152,27 @@
if(iscarbon(AM))
var/mob/living/carbon/C = AM
if(blood_id == C.get_blood_id())//both mobs have the same blood substance
- if(blood_id == "blood") //normal blood
+ if(blood_id == "blood" || blood_id == "jellyblood") //normal blood
if(blood_data["viruses"])
for(var/thing in blood_data["viruses"])
var/datum/disease/D = thing
if((D.spread_flags & DISEASE_SPREAD_SPECIAL) || (D.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS))
continue
C.ForceContractDisease(D)
- if(!(blood_data["blood_type"] in get_safe_blood(C.dna.blood_type)))
- C.reagents.add_reagent("toxin", amount * 0.5)
- return 1
+ //This used to inject oof ouch results, but since we add the reagent, and the reagent causes oof ouch on mob life... why double dip?
C.blood_volume = min(C.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAXIMUM)
- return 1
+ return TRUE
AM.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature)
- return 1
+ return TRUE
/mob/living/proc/get_blood_data(blood_id)
return
/mob/living/carbon/get_blood_data(blood_id)
- if(blood_id == "blood") //actual blood reagent
+ if(blood_id == "blood" || blood_id == "jellyblood") //actual blood reagent
var/blood_data = list()
//set the blood data
blood_data["donor"] = src
@@ -174,6 +183,7 @@
blood_data["viruses"] += D.Copy()
blood_data["blood_DNA"] = copytext(dna.unique_enzymes,1,0)
+ blood_data["bloodcolor"] = bloodtype_to_color(dna.blood_type)
if(disease_resistances && disease_resistances.len)
blood_data["resistances"] = disease_resistances.Copy()
var/list/temp_chem = list()
@@ -206,21 +216,6 @@
if(istype(ling))
blood_data["changeling_loudness"] = ling.loudfactor
return blood_data
- if(blood_id == "slimejelly") //Just so MKUltra works. Takes the minimum required data. Sishen is testing if this breaks stuff.
- var/blood_data = list()
- if(mind)
- blood_data["mind"] = mind
- else if(last_mind)
- blood_data["mind"] = last_mind
- if(ckey)
- blood_data["ckey"] = ckey
- else if(last_mind)
- blood_data["ckey"] = ckey(last_mind.key)
- blood_data["gender"] = gender
- blood_data["real_name"] = real_name
- return blood_data
-
-
//get the id of the substance this mob use as blood.
/mob/proc/get_blood_id()
@@ -234,12 +229,15 @@
if(!(HAS_TRAIT(src, TRAIT_NOCLONE)))
return "blood"
-/mob/living/carbon/human/get_blood_id()
- if(dna.species.exotic_blood)
+/mob/living/carbon/get_blood_id()
+ if(isjellyperson(src))
+ return "jellyblood"
+ if(dna?.species?.exotic_blood)
return dna.species.exotic_blood
else if((NOBLOOD in dna.species.species_traits) || (HAS_TRAIT(src, TRAIT_NOCLONE)))
return
- return "blood"
+ else
+ return "blood"
// This is has more potential uses, and is probably faster than the old proc.
/proc/get_safe_blood(bloodtype)
@@ -248,16 +246,21 @@
return
var/static/list/bloodtypes_safe = list(
- "A-" = list("A-", "O-"),
- "A+" = list("A-", "A+", "O-", "O+"),
- "B-" = list("B-", "O-"),
- "B+" = list("B-", "B+", "O-", "O+"),
- "AB-" = list("A-", "B-", "O-", "AB-"),
- "AB+" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+"),
- "O-" = list("O-"),
- "O+" = list("O-", "O+"),
- "L" = list("L"),
- "U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U")
+ "A-" = list("A-", "O-", "SY"),
+ "A+" = list("A-", "A+", "O-", "O+", "SY"),
+ "B-" = list("B-", "O-", "SY"),
+ "B+" = list("B-", "B+", "O-", "O+", "SY"),
+ "AB-" = list("A-", "B-", "O-", "AB-", "SY"),
+ "AB+" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "SY"),
+ "O-" = list("O-","SY"),
+ "O+" = list("O-", "O+","SY"),
+ "L" = list("L","SY"),
+ "U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U","SY"),
+ "HF" = list("HF", "SY"),
+ "X*" = list("X*", "SY"),
+ "SY" = list("SY"),
+ "GEL" = list("GEL","SY"),
+ "BUG" = list("BUG", "SY")
)
var/safe = bloodtypes_safe[bloodtype]
@@ -266,7 +269,7 @@
//to add a splatter of blood or other mob liquid.
/mob/living/proc/add_splatter_floor(turf/T, small_drip)
- if(get_blood_id() != "blood")
+ if(get_blood_id() == null)
return
if(!T)
T = get_turf(src)
@@ -280,24 +283,27 @@
drop.drips++
drop.add_overlay(pick(drop.random_icon_states))
drop.transfer_mob_blood_dna(src)
+ drop.update_icon()
return
else
- temp_blood_DNA = drop.return_blood_DNA() //we transfer the dna from the drip to the splatter
+ temp_blood_DNA = list()
+ temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
qdel(drop)//the drip is replaced by a bigger splatter
else
drop = new(T, get_static_viruses())
drop.transfer_mob_blood_dna(src)
+ drop.update_icon()
return
// Find a blood decal or create a new one.
- var/obj/effect/decal/cleanable/blood/B = locate() in T
+ var/obj/effect/decal/cleanable/blood/splats/B = locate() in T
if(!B)
- B = new /obj/effect/decal/cleanable/blood/splatter(T, get_static_viruses())
- if (B.bloodiness < MAX_SHOE_BLOODINESS) //add more blood, up to a limit
+ B = new /obj/effect/decal/cleanable/blood/splats(T, get_static_viruses())
+ if(B.bloodiness < MAX_SHOE_BLOODINESS) //add more blood, up to a limit
B.bloodiness += BLOOD_AMOUNT_PER_DECAL
B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
if(temp_blood_DNA)
- B.add_blood_DNA(temp_blood_DNA)
+ B.blood_DNA |= temp_blood_DNA
/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip)
if(!(NOBLOOD in dna.species.species_traits))
@@ -306,10 +312,10 @@
/mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip)
if(!T)
T = get_turf(src)
- var/obj/effect/decal/cleanable/xenoblood/B = locate() in T.contents
+ var/obj/effect/decal/cleanable/blood/splatter/B = locate() in T.contents
if(!B)
B = new(T)
- B.add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ B.blood_DNA["UNKNOWN DNA"] = "X*"
/mob/living/silicon/robot/add_splatter_floor(turf/T, small_drip)
if(!T)
@@ -318,6 +324,44 @@
if(!B)
B = new(T)
+/mob/living/proc/add_splash_floor(turf/T)
+ if(get_blood_id() == null)
+ return
+ if(!T)
+ T = get_turf(src)
+
+ var/list/temp_blood_DNA
+
+ // Find a blood decal or create a new one.
+ var/obj/effect/decal/cleanable/blood/B = locate() in T
+ if(!B)
+ B = new /obj/effect/decal/cleanable/blood/splatter(T, get_static_viruses())
+ if(B.bloodiness < MAX_SHOE_BLOODINESS) //add more blood, up to a limit
+ B.bloodiness += BLOOD_AMOUNT_PER_DECAL
+ B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
+ src.transfer_blood_to(B, 10) //very heavy bleeding, should logically leave larger pools
+ if(temp_blood_DNA)
+ B.blood_DNA |= temp_blood_DNA
+
+/mob/living/carbon/human/add_splash_floor(turf/T)
+ if(!(NOBLOOD in dna.species.species_traits))
+ ..()
+
+/mob/living/carbon/alien/add_splash_floor(turf/T)
+ if(!T)
+ T = get_turf(src)
+ var/obj/effect/decal/cleanable/blood/splatter/B = locate() in T.contents
+ if(!B)
+ B = new(T)
+ B.blood_DNA["UNKNOWN DNA"] = "X*"
+
+/mob/living/silicon/robot/add_splash_floor(turf/T)
+ if(!T)
+ T = get_turf(src)
+ var/obj/effect/decal/cleanable/oil/B = locate() in T.contents
+ if(!B)
+ B = new(T)
+
//This is a terrible way of handling it.
/mob/living/proc/ResetBloodVol()
if(ishuman(src))
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index 1e75fc4ef8..d1ace36b8c 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -147,9 +147,9 @@
/mob/living/proc/exit_blood_effect(obj/effect/decal/cleanable/B)
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
//Makes the mob have the color of the blood pool it came out of
- var/newcolor = rgb(149, 10, 10)
- if(istype(B, /obj/effect/decal/cleanable/xenoblood))
- newcolor = rgb(43, 186, 0)
+ var/newcolor = BLOOD_COLOR_HUMAN
+ if(istype(B, /obj/effect/decal/cleanable/blood/xeno))
+ newcolor = BLOOD_COLOR_XENO
add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY)
// but only for a few seconds
addtimer(CALLBACK(src, /atom/.proc/remove_atom_colour, TEMPORARY_COLOUR_PRIORITY, newcolor), 6 SECONDS)
diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm
index 97b29ca4e1..1b2944c1f6 100644
--- a/code/modules/mob/living/brain/brain.dm
+++ b/code/modules/mob/living/brain/brain.dm
@@ -10,7 +10,10 @@
/mob/living/brain/Initialize()
. = ..()
create_dna(src)
- stored_dna.initialize_dna(random_blood_type())
+ if(stored_dna.blood_type)
+ stored_dna.initialize_dna(stored_dna.blood_type)
+ else
+ stored_dna.initialize_dna(random_blood_type())
if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned)
var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it.
OB.brainmob = src
@@ -21,6 +24,8 @@
if(!stored_dna.species)
var/rando_race = pick(GLOB.roundstart_races)
stored_dna.species = new rando_race()
+ if(stored_dna.species.exotic_bloodtype)
+ stored_dna.blood_type = stored_dna.species.exotic_bloodtype
/mob/living/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
diff --git a/code/modules/mob/living/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm
index 9e0bb0428b..8a70ccc4cb 100644
--- a/code/modules/mob/living/brain/posibrain.dm
+++ b/code/modules/mob/living/brain/posibrain.dm
@@ -92,6 +92,17 @@ GLOBAL_VAR(posibrain_notify_cooldown)
if(posi_ask == "No" || QDELETED(src))
return
transfer_personality(user)
+ latejoin_remove()
+
+/obj/item/mmi/posibrain/Destroy()
+ latejoin_remove()
+ return ..()
+
+/obj/item/mmi/posibrain/proc/latejoin_remove()
+ GLOB.poi_list -= src
+ LAZYREMOVE(GLOB.mob_spawners[name], src)
+ if(!LAZYLEN(GLOB.mob_spawners[name]))
+ GLOB.mob_spawners -= name
/obj/item/mmi/posibrain/transfer_identity(mob/living/carbon/C)
name = "[initial(name)] ([C])"
@@ -163,6 +174,8 @@ GLOBAL_VAR(posibrain_notify_cooldown)
brainmob.container = src
if(autoping)
ping_ghosts("created", TRUE)
+ GLOB.poi_list |= src
+ LAZYADD(GLOB.mob_spawners[name], src)
/obj/item/mmi/posibrain/attackby(obj/item/O, mob/user)
return
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index c8ece3f656..3ad7acfcdc 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -20,7 +20,7 @@
var/heat_protection = 0.5
var/leaping = 0
- gib_type = /obj/effect/decal/cleanable/xenoblood/xgibs
+ gib_type = /obj/effect/decal/cleanable/blood/gibs/xeno
unique_name = 1
var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|queen)( \\(\\d+\\))?")
diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm
index ce2b4401e9..77300e1435 100644
--- a/code/modules/mob/living/carbon/alien/death.dm
+++ b/code/modules/mob/living/carbon/alien/death.dm
@@ -2,7 +2,7 @@
if(with_bodyparts)
new /obj/effect/gibspawner/xeno(drop_location())
else
- new /obj/effect/gibspawner/xenobodypartless(drop_location())
+ new /obj/effect/gibspawner/xeno/bodypartless(drop_location())
/mob/living/carbon/alien/gib_animation()
new /obj/effect/temp_visual/gib_animation(loc, "gibbed-a")
diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm
index e16be71ccf..e7cf70f441 100644
--- a/code/modules/mob/living/carbon/alien/larva/death.dm
+++ b/code/modules/mob/living/carbon/alien/larva/death.dm
@@ -10,7 +10,7 @@
if(with_bodyparts)
new /obj/effect/gibspawner/larva(drop_location())
else
- new /obj/effect/gibspawner/larvabodypartless(drop_location())
+ new /obj/effect/gibspawner/larva/bodypartless(drop_location())
/mob/living/carbon/alien/larva/gib_animation()
new /obj/effect/temp_visual/gib_animation(loc, "gibbed-l")
diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm
index df1be454ee..7b6962794a 100644
--- a/code/modules/mob/living/carbon/alien/organs.dm
+++ b/code/modules/mob/living/carbon/alien/organs.dm
@@ -89,6 +89,8 @@
owner.adjustFireLoss(-heal_amt)
owner.adjustOxyLoss(-heal_amt)
owner.adjustCloneLoss(-heal_amt)
+ if(owner.blood_volume && (owner.blood_volume < BLOOD_VOLUME_NORMAL))
+ owner.blood_volume += 5
else
owner.adjustPlasma(plasma_rate * 0.1)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 263edf42c2..88aa5f86d0 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -905,7 +905,7 @@
/mob/living/carbon/do_after_coefficent()
. = ..()
- GET_COMPONENT_FROM(mood, /datum/component/mood, src) //Currently, only carbons or higher use mood, move this once that changes.
+ var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) //Currently, only carbons or higher use mood, move this once that changes.
if(mood)
switch(mood.sanity) //Alters do_after delay based on how sane you are
if(SANITY_INSANE to SANITY_DISTURBED)
@@ -947,7 +947,7 @@
return TRUE
if(HAS_TRAIT(src, TRAIT_DUMB))
return TRUE
- GET_COMPONENT_FROM(mood, /datum/component/mood, src)
+ var/datum/component/mood/mood = src.GetComponent(/datum/component/mood)
if(mood)
if(mood.sanity < SANITY_UNSTABLE)
return TRUE
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index bc64c8303b..b0e9b808df 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -287,7 +287,7 @@
"
You give [H] a pat on the head to make [p_them()] feel better!")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
if (mood.sanity >= SANITY_GREAT)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
else if (mood.sanity >= SANITY_DISTURBED)
@@ -322,7 +322,7 @@
"
You hug [src] to make [p_them()] feel better!")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
if (mood.sanity >= SANITY_GREAT)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
else if (mood.sanity >= SANITY_DISTURBED)
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 41daf642f2..a1184613fe 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -49,6 +49,7 @@
//Gets filled up in create_bodyparts()
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
+ var/list/leg_bodyparts = list()
var/icon_render_key = ""
var/static/list/limb_icon_cache = list()
diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm
index cc0c0d7434..7d1e5320fc 100644
--- a/code/modules/mob/living/carbon/damage_procs.dm
+++ b/code/modules/mob/living/carbon/damage_procs.dm
@@ -1,8 +1,8 @@
-/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE)
+/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
var/hit_percent = (100-blocked)/100
- if(hit_percent <= 0)
+ if(!forced && hit_percent <= 0)
return 0
var/obj/item/bodypart/BP = null
@@ -15,34 +15,35 @@
if(!BP)
BP = bodyparts[1]
+ var/damage_amount = forced ? damage : damage * hit_percent
switch(damagetype)
if(BRUTE)
if(BP)
- if(damage > 0 ? BP.receive_damage(damage * hit_percent, 0) : BP.heal_damage(abs(damage * hit_percent), 0))
+ if(damage > 0 ? BP.receive_damage(damage_amount) : BP.heal_damage(abs(damage_amount), 0))
update_damage_overlays()
else //no bodypart, we deal damage with a more general method.
- adjustBruteLoss(damage * hit_percent)
+ adjustBruteLoss(damage_amount, forced = forced)
if(BURN)
if(BP)
- if(damage > 0 ? BP.receive_damage(0, damage * hit_percent) : BP.heal_damage(0, abs(damage * hit_percent)))
+ if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount)))
update_damage_overlays()
else
- adjustFireLoss(damage * hit_percent)
+ adjustFireLoss(damage_amount, forced = forced)
if(TOX)
- adjustToxLoss(damage * hit_percent)
+ adjustToxLoss(damage_amount, forced = forced)
if(OXY)
- adjustOxyLoss(damage * hit_percent)
+ adjustOxyLoss(damage_amount, forced = forced)
if(CLONE)
- adjustCloneLoss(damage * hit_percent)
+ adjustCloneLoss(damage_amount, forced = forced)
if(STAMINA)
if(BP)
- if(damage > 0 ? BP.receive_damage(0, 0, damage * hit_percent) : BP.heal_damage(0, 0, abs(damage * hit_percent)))
+ if(damage > 0 ? BP.receive_damage(0, 0, damage_amount) : BP.heal_damage(0, 0, abs(damage_amount)))
update_damage_overlays()
else
- adjustStaminaLoss(damage * hit_percent)
+ adjustStaminaLoss(damage_amount, forced = forced)
//citadel code
if(AROUSAL)
- adjustArousalLoss(damage * hit_percent)
+ adjustArousalLoss(damage_amount, forced = forced)
return TRUE
@@ -85,7 +86,7 @@
if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage
amount = -amount
if(amount > 0)
- blood_volume -= 5*amount
+ blood_volume -= 3*amount // x5 is too much, x3 should be still penalizing enough.
else
blood_volume -= amount
return ..()
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index c029eac12b..5634d21775 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -93,7 +93,7 @@
msg += "[t_He] [t_is] visibly tense[resting ? "." : ", and [t_is] standing in combative stance."]\n"
msg += common_trait_examine()
- GET_COMPONENT_FROM(mood, /datum/component/mood, src)
+ var/datum/component/mood/mood = src.GetComponent(/datum/component/mood)
if(mood)
switch(mood.shown_mood)
if(-INFINITY to MOOD_LEVEL_SAD4)
diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm
index 7641408529..9f6a572fc8 100644
--- a/code/modules/mob/living/carbon/human/damage_procs.dm
+++ b/code/modules/mob/living/carbon/human/damage_procs.dm
@@ -1,5 +1,5 @@
-/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE)
+/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
// depending on the species, it will run the corresponding apply_damage code there
- return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src)
+ return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced)
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 64b75bc801..b0c3f61eec 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -5,10 +5,35 @@
new /obj/effect/temp_visual/dust_animation(loc, "dust-h")
/mob/living/carbon/human/spawn_gibs(with_bodyparts)
- if(with_bodyparts)
- new /obj/effect/gibspawner/human(drop_location(), dna, get_static_viruses())
+ if(isjellyperson(src))
+ if(with_bodyparts)
+ new /obj/effect/gibspawner/slime(drop_location(), dna, get_static_viruses())
+ else
+ new /obj/effect/gibspawner/slime/bodypartless(drop_location(), dna, get_static_viruses())
+
+ if(isipcperson(src))
+ if(with_bodyparts)
+ new /obj/effect/gibspawner/ipc(drop_location(), dna, get_static_viruses())
+ else
+ new /obj/effect/gibspawner/ipc/bodypartless(drop_location(), dna, get_static_viruses())
+
+ if(isxenoperson(src))
+ if(with_bodyparts)
+ new /obj/effect/gibspawner/xeno/xenoperson(drop_location(), dna, get_static_viruses())
+ else
+ new /obj/effect/gibspawner/xeno/xenoperson/bodypartless(drop_location(), dna, get_static_viruses())
+
+ if(islizard(src))
+ if(with_bodyparts)
+ new /obj/effect/gibspawner/lizard(drop_location(), dna, get_static_viruses())
+ else
+ new /obj/effect/gibspawner/lizard/bodypartless(drop_location(), dna, get_static_viruses())
+
else
- new /obj/effect/gibspawner/humanbodypartless(drop_location(), dna, get_static_viruses())
+ if(with_bodyparts)
+ new /obj/effect/gibspawner/human(drop_location(), dna, get_static_viruses())
+ else
+ new /obj/effect/gibspawner/human/bodypartless(drop_location(), dna, get_static_viruses())
/mob/living/carbon/human/spawn_dust(just_ash = FALSE)
if(just_ash)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 6ebc4f8a32..7b0fb74f44 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/human/examine(mob/user) //User is the person being examined
+/mob/living/carbon/human/examine(mob/user)
//this is very slightly better than it was because you can use it more places. still can't do \his[src] though.
var/t_He = p_they(TRUE)
var/t_His = p_their(TRUE)
@@ -45,7 +45,7 @@
if(wear_suit)
msg += "[t_He] [t_is] wearing [wear_suit.get_examine_string(user)].\n"
//suit/armor storage
- if(s_store)
+ if(s_store && !(SLOT_S_STORE in obscured))
msg += "[t_He] [t_is] carrying [s_store.get_examine_string(user)] on [t_his] [wear_suit.name].\n"
//back
if(back)
@@ -56,11 +56,10 @@
if(!(I.item_flags & ABSTRACT))
msg += "[t_He] [t_is] holding [I.get_examine_string(user)] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
- GET_COMPONENT(FR, /datum/component/forensics)
//gloves
if(gloves && !(SLOT_GLOVES in obscured))
msg += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands.\n"
- else if(FR && length(FR.blood_DNA))
+ else if(length(blood_DNA))
var/hand_number = get_num_arms(FALSE)
if(hand_number)
msg += "
[t_He] [t_has] [hand_number > 1 ? "" : "a"] blood-stained hand[hand_number > 1 ? "s" : ""]!\n"
@@ -86,7 +85,7 @@
if(wear_mask && !(SLOT_WEAR_MASK in obscured))
msg += "[t_He] [t_has] [wear_mask.get_examine_string(user)] on [t_his] face.\n"
- if (wear_neck && !(SLOT_NECK in obscured))
+ if(wear_neck && !(SLOT_NECK in obscured))
msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
//eyes
@@ -152,7 +151,7 @@
var/temp = getBruteLoss() //no need to calculate each of these twice
- msg += "
"
+ msg += "" //Everything below gets this span
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/list/disabled = list()
@@ -297,7 +296,7 @@
msg += "[t_He] seem[p_s()] winded.\n"
if (getToxLoss() >= 10)
msg += "[t_He] seem[p_s()] sickly.\n"
- GET_COMPONENT_FROM(mood, /datum/component/mood, src)
+ var/datum/component/mood/mood = src.GetComponent(/datum/component/mood)
if(mood.sanity <= SANITY_DISTURBED)
msg += "[t_He] seem[p_s()] distressed.\n"
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index ec4f073fc8..b18219122e 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -32,7 +32,7 @@
if(CONFIG_GET(flag/disable_stambuffer))
togglesprint()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /mob/living/carbon/human/clean_blood)
/mob/living/carbon/human/ComponentInitialize()
@@ -689,16 +689,17 @@
if(..())
dropItemToGround(I)
-/mob/living/carbon/human/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
- if(gloves)
- if(SEND_SIGNAL(gloves, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- update_inv_gloves()
+/mob/living/carbon/human/clean_blood()
+ var/mob/living/carbon/human/H = src
+ if(H.gloves)
+ if(H.gloves.clean_blood())
+ H.update_inv_gloves()
else
- if(bloody_hands)
- bloody_hands = 0
- update_inv_gloves()
+ ..() // Clear the Blood_DNA list
+ if(H.bloody_hands)
+ H.bloody_hands = 0
+ H.update_inv_gloves()
+ update_icons() //apply the now updated overlays to the mob
/mob/living/carbon/human/wash_cream()
if(creamed) //clean both to prevent a rare bug
@@ -1104,3 +1105,18 @@
/mob/living/carbon/human/species/zombie/krokodil_addict
race = /datum/species/krokodil_addict
+
+/mob/living/carbon/human/species/mammal
+ race = /datum/species/mammal
+
+/mob/living/carbon/human/species/insect
+ race = /datum/species/insect
+
+/mob/living/carbon/human/species/xeno
+ race = /datum/species/xeno
+
+/mob/living/carbon/human/species/ipc
+ race = /datum/species/ipc
+
+/mob/living/carbon/human/species/roundstartslime
+ race = /datum/species/jelly/roundstartslime
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 657c32ba01..b1f11f6463 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -51,6 +51,9 @@
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
+ var/blood_state = BLOOD_STATE_NOT_BLOODY
+ var/list/blood_smear = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
+
var/name_override //For temporary visible name changes
var/genital_override = FALSE //Force genitals on things incase of chems
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index b65d62b63b..8bc8866380 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -127,3 +127,9 @@
return FALSE
return .
+/*
+/mob/living/carbon/human/transfer_blood_dna(list/blood_dna)
+ ..()
+ if(blood_dna.len)
+ last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
+ last_blood_DNA = blood_dna[blood_dna.len]*/
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 6ea9c985e2..4e6f9e0eb9 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -56,20 +56,20 @@
//Bloody footprints
var/turf/T = get_turf(src)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
- for(var/obj/effect/decal/cleanable/blood/footprints/oldFP in T)
- if (oldFP.blood_state == S.blood_state)
- return
- //No oldFP or they're all a different kind of blood
- S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
- if (S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
- var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
- FP.blood_state = S.blood_state
- FP.entered_dirs |= dir
- FP.bloodiness = S.bloody_shoes[S.blood_state] - BLOOD_LOSS_IN_SPREAD
- FP.add_blood_DNA(S.return_blood_DNA())
- FP.update_icon()
+ var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
+ if(oldFP && (oldFP.blood_state == S.blood_state && oldFP.color == bloodtype_to_color(S.last_bloodtype)))
+ return
+ S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
+ var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
+ FP.blood_state = S.blood_state
+ FP.entered_dirs |= dir
+ FP.bloodiness = S.bloody_shoes[S.blood_state]
+ if(S.last_bloodtype)
+ FP.blood_DNA += list(S.last_blood_DNA = S.last_bloodtype)
+ FP.update_icon()
update_inv_shoes()
//End bloody footprints
+
S.step_action()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index eee425063d..c54f41017a 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -1,14 +1,14 @@
/mob/living/carbon/human/say_mod(input, message_mode)
verb_say = dna.species.say_mod
- switch(slurring)
- if(10 to 25)
- return "jumbles"
- if(25 to 50)
- return "slurs"
- if(50 to INFINITY)
- return "garbles"
- else
- . = ..()
+ . = ..()
+ if(message_mode != MODE_CUSTOM_SAY && message_mode != MODE_WHISPER_CRIT)
+ switch(slurring)
+ if(10 to 25)
+ return "jumbles"
+ if(25 to 50)
+ return "slurs"
+ if(50 to INFINITY)
+ return "garbles"
/mob/living/carbon/human/GetVoice()
if(istype(wear_mask, /obj/item/clothing/mask/chameleon))
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 5474838765..1f67f2b13c 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -341,7 +341,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
if(C.dna.species.exotic_bloodtype)
- C.dna.blood_type = random_blood_type()
+ if(!new_species.exotic_bloodtype)
+ C.dna.blood_type = random_blood_type()
+ else
+ C.dna.blood_type = new_species.exotic_bloodtype
if(DIGITIGRADE in species_traits)
C.Digitigrade_Leg_Swap(TRUE)
for(var/X in inherent_traits)
@@ -1028,6 +1031,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return "TAUR"
//END EDIT
+/* TODO: Snowflake trail marks
+// Impliments different trails for species depending on if they're wearing shoes.
+/datum/species/proc/get_move_trail(var/mob/living/carbon/human/H)
+ if(H.lying)
+ return /obj/effect/decal/cleanable/blood/footprints/tracks/body
+ if(H.shoes || (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)))
+ var/obj/item/clothing/shoes/shoes = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) ? H.wear_suit : H.shoes // suits take priority over shoes
+ return shoes.move_trail
+ else
+ return move_trail */
/datum/species/proc/spec_life(mob/living/carbon/human/H)
if(HAS_TRAIT(H, TRAIT_NOBREATH))
@@ -1281,7 +1294,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if (H.nutrition > 0 && H.stat != DEAD && !HAS_TRAIT(H, TRAIT_NOHUNGER))
// THEY HUNGER
var/hunger_rate = HUNGER_FACTOR
- GET_COMPONENT_FROM(mood, /datum/component/mood, H)
+ var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
if(mood && mood.sanity > SANITY_DISTURBED)
hunger_rate *= max(0.5, 1 - 0.002 * mood.sanity) //0.85 to 0.75
@@ -1917,10 +1930,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
append_message = "loosening their grip on [target_held_item]"
log_combat(user, target, "shoved", append_message)
-/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
+/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
var/hit_percent = (100-(blocked+armor))/100
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
- if(hit_percent <= 0)
+ if(!forced && hit_percent <= 0)
return 0
var/obj/item/bodypart/BP = null
@@ -1942,37 +1955,44 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
switch(damagetype)
if(BRUTE)
H.damageoverlaytemp = 20
+ var/damage_amount = forced ? damage : damage * hit_percent * brutemod * H.physiology.brute_mod
if(BP)
- if(damage > 0 ? BP.receive_damage(damage * hit_percent * brutemod * H.physiology.brute_mod, 0) : BP.heal_damage(abs(damage * hit_percent * brutemod * H.physiology.brute_mod), 0))
+ if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0))
H.update_damage_overlays()
if(HAS_TRAIT(H, TRAIT_MASO))
- H.adjustArousalLoss(damage * brutemod * H.physiology.brute_mod)
+ H.adjustArousalLoss(damage_amount, 0)
if (H.getArousalLoss() >= 100 && ishuman(H) && H.has_dna())
H.mob_climax(forced_climax=TRUE)
else//no bodypart, we deal damage with a more general method.
- H.adjustBruteLoss(damage * hit_percent * brutemod * H.physiology.brute_mod)
+ H.adjustBruteLoss(damage_amount)
if(BURN)
H.damageoverlaytemp = 20
+ var/damage_amount = forced ? damage : damage * hit_percent * burnmod * H.physiology.burn_mod
if(BP)
- if(damage > 0 ? BP.receive_damage(0, damage * hit_percent * burnmod * H.physiology.burn_mod) : BP.heal_damage(0, abs(damage * hit_percent * burnmod * H.physiology.burn_mod)))
+ if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount)))
H.update_damage_overlays()
else
- H.adjustFireLoss(damage * hit_percent * burnmod * H.physiology.burn_mod)
+ H.adjustFireLoss(damage_amount)
if(TOX)
- H.adjustToxLoss(damage * hit_percent * H.physiology.tox_mod)
+ var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.tox_mod
+ H.adjustToxLoss(damage_amount)
if(OXY)
- H.adjustOxyLoss(damage * hit_percent * H.physiology.oxy_mod)
+ var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.oxy_mod
+ H.adjustOxyLoss(damage_amount)
if(CLONE)
- H.adjustCloneLoss(damage * hit_percent * H.physiology.clone_mod)
+ var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.clone_mod
+ H.adjustCloneLoss(damage_amount)
if(STAMINA)
+ var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.stamina_mod
if(BP)
- if(damage > 0 ? BP.receive_damage(0, 0, damage * hit_percent * H.physiology.stamina_mod) : BP.heal_damage(0, 0, abs(damage * hit_percent * H.physiology.stamina_mod), only_robotic = FALSE, only_organic = FALSE))
+ if(damage > 0 ? BP.receive_damage(0, 0, damage_amount) : BP.heal_damage(0, 0, abs(damage * hit_percent * H.physiology.stamina_mod), only_robotic = FALSE, only_organic = FALSE))
H.update_stamina()
else
- H.adjustStaminaLoss(damage * hit_percent * H.physiology.stamina_mod)
+ H.adjustStaminaLoss(damage_amount)
if(BRAIN)
- H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage * hit_percent * H.physiology.brain_mod)
+ var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod
+ H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount)
if(AROUSAL) //Citadel edit - arousal
H.adjustArousalLoss(damage * hit_percent)
return 1
diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
index b4e55b60a5..d264f11b73 100644
--- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
@@ -17,6 +17,7 @@
toxic_food = MEAT | RAW
mutanteyes = /obj/item/organ/eyes/insect
should_draw_citadel = TRUE
+ exotic_bloodtype = "BUG"
/datum/species/insect/on_species_gain(mob/living/carbon/C)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
index 043ee4fde1..0c3bcc2b00 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -10,6 +10,7 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/fly
disliked_food = null
liked_food = GROSS
+ exotic_bloodtype = "BUG"
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "pestkiller")
diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
index 0390d4accc..90714b390c 100644
--- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
@@ -65,7 +65,7 @@
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
skinned_type = /obj/item/stack/sheet/animalhide/xeno
- exotic_bloodtype = "L"
+ exotic_bloodtype = "X*"
damage_overlay_type = "xeno"
liked_food = MEAT
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 8f84590ff4..a7e952f430 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -634,9 +634,10 @@
id = "clockwork golem"
say_mod = "clicks"
limbs_id = "clockgolem"
- info_text = "As a Clockwork Golem, you are faster than other types of golems. On death, you will break down into scrap."
+ info_text = "As a Clockwork Golem, you are faster than other types of golems, and are capable of using guns. On death, you will break down into scrap."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOGENITALS,NOAROUSAL)
inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID)
+ inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
armor = 20 //Reinforced, but much less so to allow for fast movement
attack_verb = "smash"
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
@@ -682,7 +683,7 @@
blacklisted = TRUE
dangerous_existence = TRUE
random_eligible = FALSE
- info_text = "As a Clockwork Golem Servant, you are faster than other types of golems." //warcult golems leave a corpse
+ info_text = "As a Clockwork Golem Servant, you are faster than other types of golems, and are capable of using guns." //warcult golems leave a corpse
/datum/species/golem/cloth
name = "Cloth Golem"
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index 95b924ea18..135c98860a 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -12,8 +12,8 @@
default_features = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
mutanttongue = /obj/item/organ/tongue/robot/ipc
-
- exotic_blood = "oil"
+ mutant_heart = /obj/item/organ/heart/ipc
+ exotic_bloodtype = "HF"
var/datum/action/innate/monitor_change/screen
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 8e98569644..f416854838 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -4,13 +4,15 @@
id = "jelly"
default_color = "00FF90"
say_mod = "chirps"
- species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD,WINGCOLOR)
+ species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR)
mutantlungs = /obj/item/organ/lungs/slime
+ mutant_heart = /obj/item/organ/heart/slime
mutant_bodyparts = list("mam_tail", "mam_ears", "mam_snouts", "taur", "deco_wings") //CIT CHANGE
default_features = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None") //CIT CHANGE
inherent_traits = list(TRAIT_TOXINLOVER)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
- exotic_blood = "slimejelly"
+ exotic_blood = "jellyblood"
+ exotic_bloodtype = "GEL"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
var/datum/action/innate/slime_change/slime_change //CIT CHANGE
@@ -121,7 +123,7 @@
name = "Xenobiological Slime Entity"
id = "slime"
default_color = "00FFFF"
- species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD)
+ species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 150
@@ -396,7 +398,7 @@
id = "slimeperson"
limbs_id = "slime"
default_color = "00FFFF"
- species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD)
+ species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
inherent_traits = list(TRAIT_TOXINLOVER)
mutant_bodyparts = list("mam_tail", "mam_ears", "mam_body_markings", "mam_snouts", "taur")
default_features = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index fefaa025d3..a1dce4fb0f 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -45,7 +45,7 @@
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
. = min(20, amount)
-/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
+/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
. = ..()
if(.)
regen_cooldown = world.time + REGENERATION_DELAY
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index fa3e29f119..a68aded85f 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -180,7 +180,7 @@ There are several things that need to be remembered:
inv.update_icon()
if(!gloves && bloody_hands)
- var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER)
+ var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
if(get_num_arms() < 2)
if(has_left_hand())
bloody_overlay.icon_state = "bloodyhands_left"
@@ -270,6 +270,32 @@ There are several things that need to be remembered:
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
inv.update_icon()
+/*
+ if(!shoes && bloody_feet)
+ var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyfeet", -SHOES_LAYER, color = blood_DNA_to_color())
+ if(dna.features["taur"] != "None")
+ if(dna.features["taur"] in GLOB.noodle_taurs)
+ bloody_overlay = mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "snekbloodyfeet", -SHOES_LAYER, color = blood_DNA_to_color())
+ if(get_num_legs() < 2)
+ if(has_left_leg())
+ bloody_overlay.icon_state = "snekbloodyfeet_left"
+ else if(has_right_leg())
+ bloody_overlay.icon_state = "snekbloodyfeet_right"
+ else if(dna.features["taur"] in GLOB.paw_taurs)
+ bloody_overlay = mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "pawbloodyfeet", -SHOES_LAYER, color = blood_DNA_to_color())
+ if(get_num_legs() < 2)
+ if(has_left_leg())
+ bloody_overlay.icon_state = "pawbloodyfeet_left"
+ else if(has_right_leg())
+ bloody_overlay.icon_state = "pawbloodyfeet_right"
+ else
+ if(get_num_legs() < 2)
+ if(has_left_leg())
+ bloody_overlay.icon_state = "bloodyfeet_left"
+ else if(has_right_leg())
+ bloody_overlay.icon_state = "bloodyfeet_right"
+
+ overlays_standing[GLOVES_LAYER] = bloody_overlay*/
if(shoes)
var/obj/item/clothing/shoes/S = shoes
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index 44e91949b2..66be8058f1 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -97,8 +97,12 @@
/mob/living/carbon/update_damage_overlays()
remove_overlay(DAMAGE_LAYER)
+ var/dam_colors = "#E62525"
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ dam_colors = bloodtype_to_color(H.dna.blood_type)
- var/mutable_appearance/damage_overlay = mutable_appearance('icons/mob/dam_mob.dmi', "blank", -DAMAGE_LAYER)
+ var/mutable_appearance/damage_overlay = mutable_appearance('icons/mob/dam_mob.dmi', "blank", -DAMAGE_LAYER, color = dam_colors)
overlays_standing[DAMAGE_LAYER] = damage_overlay
for(var/X in bodyparts)
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index fbb6074ba2..dc43ab8b07 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -8,23 +8,24 @@
Returns
standard 0 if fail
*/
-/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE)
+/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
var/hit_percent = (100-blocked)/100
if(!damage || (hit_percent <= 0))
return 0
+ var/damage_amount = forced ? damage : damage * hit_percent
switch(damagetype)
if(BRUTE)
- adjustBruteLoss(damage * hit_percent)
+ adjustBruteLoss(damage_amount, forced = forced)
if(BURN)
- adjustFireLoss(damage * hit_percent)
+ adjustFireLoss(damage_amount, forced = forced)
if(TOX)
- adjustToxLoss(damage * hit_percent)
+ adjustToxLoss(damage_amount, forced = forced)
if(OXY)
- adjustOxyLoss(damage * hit_percent)
+ adjustOxyLoss(damage_amount, forced = forced)
if(CLONE)
- adjustCloneLoss(damage * hit_percent)
+ adjustCloneLoss(damage_amount, forced = forced)
if(STAMINA)
- adjustStaminaLoss(damage * hit_percent)
+ adjustStaminaLoss(damage_amount, forced = forced)
return 1
/mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) //like apply damage except it always uses the damage procs
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 6e7676a46a..f686569fb8 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -502,7 +502,7 @@
fire_stacks = 0
confused = 0
update_canmove()
- GET_COMPONENT(mood, /datum/component/mood)
+ var/datum/component/mood/mood = GetComponent(/datum/component/mood)
if (mood)
QDEL_LIST_ASSOC_VAL(mood.mood_events)
mood.sanity = SANITY_GREAT
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 5664c2ebca..174fd5c394 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -391,16 +391,16 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return 0
/mob/living/say_mod(input, message_mode)
- if(message_mode == MODE_WHISPER)
- . = verb_whisper
- else if(message_mode == MODE_WHISPER_CRIT)
+ . = ..()
+ if(message_mode == MODE_WHISPER_CRIT)
. = "[verb_whisper] in [p_their()] last breath"
- else if(stuttering)
- . = "stammers"
- else if(derpspeech)
- . = "gibbers"
- else
- . = ..()
+ else if(message_mode != MODE_CUSTOM_SAY)
+ if(message_mode == MODE_WHISPER)
+ . = verb_whisper
+ else if(stuttering)
+ . = "stammers"
+ else if(derpspeech)
+ . = "gibbers"
/mob/living/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced)
diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm
index 69d150b315..8fbd7afbdd 100644
--- a/code/modules/mob/living/silicon/damage_procs.dm
+++ b/code/modules/mob/living/silicon/damage_procs.dm
@@ -1,16 +1,17 @@
-/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE)
+/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
var/hit_percent = (100-blocked)/100
- if(!damage || (hit_percent <= 0))
+ if(!damage || (!forced && hit_percent <= 0))
return 0
+ var/damage_amount = forced ? damage : damage * hit_percent
switch(damagetype)
if(BRUTE)
- adjustBruteLoss(damage * hit_percent)
+ adjustBruteLoss(damage_amount, forced = forced)
if(BURN)
- adjustFireLoss(damage * hit_percent)
+ adjustFireLoss(damage_amount, forced = forced)
if(OXY)
- if(damage < 0) //we shouldn't be taking oxygen damage through this proc, but we'll let it heal.
- adjustOxyLoss(damage * hit_percent)
+ if(damage < 0 || forced) //we shouldn't be taking oxygen damage through this proc, but we'll let it heal.
+ adjustOxyLoss(damage_amount, forced = forced)
return 1
@@ -29,7 +30,7 @@
/mob/living/silicon/setCloneLoss(amount, updating_health = TRUE, forced = FALSE)
return FALSE
-/mob/living/silicon/adjustStaminaLoss(amount, updating_stamina = 1)//immune to stamina damage.
+/mob/living/silicon/adjustStaminaLoss(amount, updating_stamina = 1, forced = FALSE)//immune to stamina damage.
return FALSE
/mob/living/silicon/setStaminaLoss(amount, updating_stamina = 1)
diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm
index f36e996b81..dda8ddfebd 100644
--- a/code/modules/mob/living/silicon/pai/pai_defense.dm
+++ b/code/modules/mob/living/silicon/pai/pai_defense.dm
@@ -81,8 +81,11 @@
/mob/living/silicon/pai/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE)
return FALSE
-/mob/living/silicon/pai/adjustStaminaLoss(amount)
- take_holo_damage(amount & 0.25)
+/mob/living/silicon/pai/adjustStaminaLoss(amount, updating_health, forced = FALSE)
+ if(forced)
+ take_holo_damage(amount)
+ else
+ take_holo_damage(amount * 0.25)
/mob/living/silicon/pai/adjustOrganLoss(slot, amount, maximum = 500) //I kept this in, unlike tg
Knockdown(amount * 0.2)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 2b2cc4c0b5..5b670aaa42 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1233,7 +1233,7 @@
/mob/living/silicon/robot/unbuckle_mob(mob/user, force=FALSE)
if(iscarbon(user))
- GET_COMPONENT(riding_datum, /datum/component/riding)
+ var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding)
if(istype(riding_datum))
riding_datum.unequip_buckle_inhands(user)
riding_datum.restore_position(user)
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index ab1e906cf2..d31c368ca4 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -198,7 +198,6 @@
)
if(blood)
- target_types += /obj/effect/decal/cleanable/xenoblood
target_types += /obj/effect/decal/cleanable/blood
target_types += /obj/effect/decal/cleanable/trail_holder
target_types += /obj/effect/decal/cleanable/insectguts
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index 1bc7493684..94283f82da 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -476,7 +476,8 @@
if(isturf(next))
if(bloodiness)
var/obj/effect/decal/cleanable/blood/tracks/B = new(loc)
- B.add_blood_DNA(return_blood_DNA())
+ if(blood_DNA && blood_DNA.len)
+ B.blood_DNA |= blood_DNA.Copy()
var/newdir = get_dir(next, loc)
if(newdir == dir)
B.setDir(newdir)
@@ -489,7 +490,6 @@
B.setDir(newdir)
bloodiness--
-
var/oldloc = loc
var/moved = step_towards(src, next) // attempt to move
if(cell)
diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm
index 1031c5b7ee..0cc097dc08 100644
--- a/code/modules/mob/living/simple_animal/damage_procs.dm
+++ b/code/modules/mob/living/simple_animal/damage_procs.dm
@@ -37,5 +37,5 @@
else if(damage_coeff[CLONE])
. = adjustHealth(amount * damage_coeff[CLONE] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
-/mob/living/simple_animal/adjustStaminaLoss(amount)
+/mob/living/simple_animal/adjustStaminaLoss(amount, forced = FALSE)
return
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index d28b98263c..521f458e2f 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -33,7 +33,7 @@
/mob/living/simple_animal/drone/syndrone/Initialize()
. = ..()
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, internal_storage)
+ var/datum/component/uplink/hidden_uplink = internal_storage.GetComponent(/datum/component/uplink)
hidden_uplink.telecrystals = 10
/mob/living/simple_animal/drone/syndrone/Login()
@@ -47,7 +47,7 @@
/mob/living/simple_animal/drone/syndrone/badass/Initialize()
. = ..()
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, internal_storage)
+ var/datum/component/uplink/hidden_uplink = internal_storage.GetComponent(/datum/component/uplink)
hidden_uplink.telecrystals = 30
var/obj/item/implant/weapons_auth/W = new
W.implant(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 3d92912f9c..5240b4d06c 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -168,7 +168,6 @@
/mob/living/simple_animal/hostile/alien/maid/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/cleaning)
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
if(ismovableatom(target))
@@ -177,6 +176,7 @@
qdel(target)
return TRUE
var/atom/movable/M = target
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ M.clean_blood()
visible_message("[src] polishes \the [target].")
return TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
index c2d0a214b4..910e9c3c4a 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
@@ -39,7 +39,7 @@
animal_species = /mob/living/simple_animal/hostile/asteroid/gutlunch
childtype = list(/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck = 45, /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen = 55)
- wanted_objects = list(/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/blood/gibs/)
+ wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/)
var/obj/item/udder/gutlunch/udder = null
/mob/living/simple_animal/hostile/asteroid/gutlunch/Initialize()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index c017543445..a2ef5b813b 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -536,7 +536,7 @@
//ANIMAL RIDING
/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user)
- GET_COMPONENT(riding_datum, /datum/component/riding)
+ var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding)
if(riding_datum)
if(user.incapacitated())
return
@@ -547,7 +547,7 @@
return ..()
/mob/living/simple_animal/relaymove(mob/user, direction)
- GET_COMPONENT(riding_datum, /datum/component/riding)
+ var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding)
if(tame && riding_datum)
riding_datum.handle_ride(user, direction)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 93b4d32123..eb22ab7403 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -88,7 +88,7 @@
if(newletter==" ")
newletter="...huuuhhh..."
if(newletter==".")
- newletter=" *BURP*."
+ newletter=" BURP!"
if(rand(1,100) <= strength*0.5)
if(rand(1,5) == 1)
newletter+="'"
@@ -487,6 +487,26 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
/mob/proc/can_hear()
. = TRUE
+/proc/bloodtype_to_color(var/type)
+ . = BLOOD_COLOR_HUMAN
+ switch(type)
+ if("U")//Universal blood; a bit orange
+ . = BLOOD_COLOR_UNIVERSAL
+ if("SY")//Synthetics blood; blue
+ . = BLOOD_COLOR_SYNTHETIC
+ if("L")//lizard, a bit pink/purple
+ . = BLOOD_COLOR_LIZARD
+ if("X*")//xeno blood; greenish yellow
+ . = BLOOD_COLOR_XENO
+ if("HF")// Oil/Hydraulic blood. something something why not. reee
+ . = BLOOD_COLOR_OIL
+ if("GEL")// slimepeople blood, rgb 0, 255, 144
+ . = BLOOD_COLOR_SLIME
+ if("BUG")// yellowish, like, y'know bug guts I guess.
+ . = BLOOD_COLOR_BUG
+ //add more stuff to the switch if you have more blood colors for different types
+ // the defines are in _DEFINES/misc.dm
+
//Examine text for traits shared by multiple types. I wish examine was less copypasted.
/mob/proc/common_trait_examine()
if(HAS_TRAIT(src, TRAIT_DISSECTED))
@@ -497,4 +517,4 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
dissectionmsg = " via Experimental Dissection"
else if(HAS_TRAIT_FROM(src, TRAIT_DISSECTED,"Thorough Dissection"))
dissectionmsg = " via Thorough Dissection"
- . += "This body has been dissected and analyzed[dissectionmsg].
"
\ No newline at end of file
+ . += "This body has been dissected and analyzed[dissectionmsg].
"
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 5bcb7a60df..fece60f268 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -158,6 +158,7 @@
if(..())
if(reagents.total_volume)
if(M.reagents)
+ reagents.reaction(M, INJECT)
reagents.trans_to(M, reagents.total_volume)
@@ -200,7 +201,7 @@
throwforce = 35
playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
to_chat(user, "[src] is now active.")
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = on
update_icon()
diff --git a/code/modules/photography/photos/album.dm b/code/modules/photography/photos/album.dm
index bd77d468d7..3400ed6de0 100644
--- a/code/modules/photography/photos/album.dm
+++ b/code/modules/photography/photos/album.dm
@@ -13,7 +13,7 @@
/obj/item/storage/photo_album/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/photo))
STR.max_combined_w_class = 42
STR.max_items = 21
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 1759f31344..0762ad46b0 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -20,6 +20,7 @@
var/self_recharge = 0 //does it self recharge, over time, or not?
var/ratingdesc = TRUE
var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it.
+ rad_flags = RAD_NO_CONTAMINATE // Prevent the same cheese as with the stock parts
/obj/item/stock_parts/cell/get_cell()
return src
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 8d2162a0ff..e6fa1e0ee4 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -29,7 +29,7 @@
#define MOLE_HEAT_PENALTY 350 //Heat damage scales around this. Too hot setups with this amount of moles do regular damage, anything above and below is scaled
#define POWER_PENALTY_THRESHOLD 5000 //Higher == Engine can generate more power before triggering the high power penalties.
#define SEVERE_POWER_PENALTY_THRESHOLD 7000 //Same as above, but causes more dangerous effects
-#define CRITICAL_POWER_PENALTY_THRESHOLD 9000 //Even more dangerous effects, threshold for tesla delamination
+#define CRITICAL_POWER_PENALTY_THRESHOLD 12000 //Even more dangerous effects, threshold for tesla delamination
#define HEAT_PENALTY_THRESHOLD 40 //Higher == Crystal safe operational temperature is higher.
#define DAMAGE_HARDCAP 0.002
#define DAMAGE_INCREASE_MULTIPLIER 0.25
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index fb3ed19f82..13fd834657 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -62,16 +62,16 @@
var/zoomed = FALSE //Zoom toggle
var/zoom_amt = 3 //Distance in TURFs to move the user's screen forward (the "zoom" effect)
var/zoom_out_amt = 0
- var/datum/action/toggle_scope_zoom/azoom
+ var/datum/action/item_action/toggle_scope_zoom/azoom
/obj/item/gun/Initialize()
. = ..()
if(pin)
pin = new pin(src)
if(gun_light)
- alight = new /datum/action/item_action/toggle_gunlight(src)
- build_zooming()
-
+ alight = new (src)
+ if(zoomable)
+ azoom = new (src)
/obj/item/gun/CheckParts(list/parts_list)
..()
@@ -372,6 +372,12 @@
else
return ..()
+/obj/item/gun/ui_action_click(mob/user, action)
+ if(istype(action, /datum/action/item_action/toggle_scope_zoom))
+ zoom(user)
+ else if(istype(action, alight))
+ toggle_gunlight()
+
/obj/item/gun/proc/toggle_gunlight()
if(!gun_light)
return
@@ -407,21 +413,10 @@
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/gun/pickup(mob/user)
- ..()
- if(azoom)
- azoom.Grant(user)
- if(alight)
- alight.Grant(user)
-
-/obj/item/gun/dropped(mob/user)
- ..()
- if(zoomed)
- zoom(user,FALSE)
- if(azoom)
- azoom.Remove(user)
- if(alight)
- alight.Remove(user)
+/obj/item/gun/item_action_slot_check(slot, mob/user, datum/action/A)
+ if(istype(A, /datum/action/item_action/toggle_scope_zoom) && slot != SLOT_HANDS)
+ return FALSE
+ return ..()
/obj/item/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer)
if(!ishuman(user) || !ishuman(target))
@@ -468,41 +463,32 @@
// ZOOMING //
/////////////
-/datum/action/toggle_scope_zoom
+/datum/action/item_action/toggle_scope_zoom
name = "Toggle Scope"
- check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_LYING
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
- var/obj/item/gun/gun = null
-/datum/action/toggle_scope_zoom/Trigger()
- gun.zoom(owner)
-
-/datum/action/toggle_scope_zoom/IsAvailable()
+/datum/action/item_action/toggle_scope_zoom/IsAvailable()
. = ..()
- if(!gun)
- return FALSE
if(!.)
- gun.zoom(owner, FALSE)
- if(!owner.get_held_index_of_item(gun))
- return FALSE
-
-/datum/action/toggle_scope_zoom/Remove(mob/living/L)
- gun.zoom(L, FALSE)
- ..()
+ var/obj/item/gun/G = target
+ G.zoom(owner, FALSE)
+/datum/action/item_action/toggle_scope_zoom/Remove(mob/living/L)
+ var/obj/item/gun/G = target
+ G.zoom(L, FALSE)
+ return ..()
/obj/item/gun/proc/zoom(mob/living/user, forced_zoom)
- if(!user || !user.client)
+ if(!(user?.client))
return
- switch(forced_zoom)
- if(FALSE)
- zoomed = FALSE
- if(TRUE)
- zoomed = TRUE
- else
- zoomed = !zoomed
+ if(!isnull(forced_zoom))
+ if(zoomed == forced_zoom)
+ return
+ zoomed = forced_zoom
+ else
+ zoomed = !zoomed
if(zoomed)
var/_x = 0
@@ -524,16 +510,6 @@
user.client.change_view(CONFIG_GET(string/default_view))
user.client.pixel_x = 0
user.client.pixel_y = 0
- return zoomed
-
-//Proc, so that gun accessories/scopes/etc. can easily add zooming.
-/obj/item/gun/proc/build_zooming()
- if(azoom)
- return
-
- if(zoomable)
- azoom = new()
- azoom.gun = src
/obj/item/gun/handle_atom_del(atom/A)
if(A == chambered)
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 1117bc1000..06ce7b91e4 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -170,7 +170,7 @@
if(iscarbon(user))
var/mob/living/carbon/C = user
user_dna = C.dna
- B.add_blood_DNA(user_dna)
+ B.add_blood_DNA(user_dna, C.diseases)
var/datum/callback/gibspawner = CALLBACK(GLOBAL_PROC, /proc/spawn_atom_to_turf, /obj/effect/gibspawner/generic, B, 1, FALSE, list(user_dna))
B.throw_at(target, BRAINS_BLOWN_THROW_RANGE, BRAINS_BLOWN_THROW_SPEED, callback=gibspawner)
return(BRUTELOSS)
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 4bd65a7b20..cd86b0b06c 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -51,8 +51,11 @@
else
to_chat(user, "You cannot seem to get \the [src] out of your hands!")
-/obj/item/gun/ballistic/automatic/ui_action_click()
- burst_select()
+/obj/item/gun/ballistic/automatic/ui_action_click(mob/user, action)
+ if(istype(action, /datum/action/item_action/toggle_firemode))
+ burst_select()
+ else
+ return ..()
/obj/item/gun/ballistic/automatic/proc/burst_select()
var/mob/living/carbon/human/user = usr
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index 6060ceba99..2cccc57d9e 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -174,9 +174,6 @@
itemState += "[ratio]"
item_state = itemState
-/obj/item/gun/energy/ui_action_click()
- toggle_gunlight()
-
/obj/item/gun/energy/suicide_act(mob/living/user)
if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD))
user.visible_message("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!")
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index e4d13ad315..92fe91c222 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -45,7 +45,7 @@
var/aiming_lastangle = 0
var/mob/current_user = null
var/list/obj/effect/projectile/tracer/current_tracers
-
+
var/structure_piercing = 1
var/structure_bleed_coeff = 0.7
var/wall_pierce_amount = 0
@@ -76,7 +76,7 @@
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty")
var/datum/action/item_action/zoom_lock_action/zoom_lock_action
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/gun/energy/beam_rifle/debug
delay = 0
@@ -111,7 +111,9 @@
to_chat(owner, "You switch [src]'s zooming processor to center mode.")
if(ZOOM_LOCK_OFF)
to_chat(owner, "You disable [src]'s zooming system.")
- reset_zooming()
+ reset_zooming()
+ else
+ return ..()
/obj/item/gun/energy/beam_rifle/proc/set_autozoom_pixel_offsets_immediate(current_angle)
if(zoom_lock == ZOOM_LOCK_CENTER_VIEW || zoom_lock == ZOOM_LOCK_OFF)
@@ -172,7 +174,7 @@
STOP_PROCESSING(SSfastprocess, src)
set_user(null)
QDEL_LIST(current_tracers)
- QDEL_NULL(mobhook)
+ listeningTo = null
return ..()
/obj/item/gun/energy/beam_rifle/emp_act(severity)
@@ -259,14 +261,17 @@
if(user == current_user)
return
stop_aiming(current_user)
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
if(istype(current_user))
LAZYREMOVE(current_user.mousemove_intercept_objects, src)
current_user = null
if(istype(user))
current_user = user
LAZYOR(current_user.mousemove_intercept_objects, src)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
/obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
if(aiming)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index dace31c2f7..8b881b57ed 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -163,15 +163,26 @@
var/splatter_dir = dir
if(starting)
splatter_dir = get_dir(starting, target_loca)
- if(isalien(L))
+ var/obj/item/bodypart/B = L.get_bodypart(def_zone)
+ if(B.status == BODYPART_ROBOTIC) // So if you hit a robotic, it sparks instead of bloodspatters
+ do_sparks(2, FALSE, target.loc)
+ if(prob(25))
+ new /obj/effect/decal/cleanable/oil(target_loca)
+ else if(isalien(L))
new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target_loca, splatter_dir)
else
- new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir)
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color(H.dna.blood_type))
+ else
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color())
+
if(iscarbon(L))
var/mob/living/carbon/C = L
C.bleed(damage)
else
L.add_splatter_floor(target_loca)
+
else if(impact_effect_type && !hitscan)
new impact_effect_type(target_loca, hitx, hity)
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index dfc6df537d..42aef1ec9d 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -17,31 +17,40 @@
/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
. = ..()
var/turf/T = get_turf(target)
-
- //section shamelessly copypasta'd from the clean component
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
for(var/A in T)
if(is_cleanable(A))
qdel(A)
- else if(istype(A, /obj/item))
- var/obj/item/I = A
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(ismob(I.loc))
- var/mob/M = I.loc
+ else if(isitem(A))
+ var/obj/item/cleaned_item = A
+ SEND_SIGNAL(cleaned_item, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_item.clean_blood()
+ if(ismob(cleaned_item.loc))
+ var/mob/M = cleaned_item.loc
M.regenerate_icons()
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
- if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- cleaned_human.wash_cream()
- cleaned_human.regenerate_icons()
+ if(cleaned_human.lying)
+ if(cleaned_human.head)
+ SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.head.clean_blood()
+ cleaned_human.update_inv_head()
+ if(cleaned_human.wear_suit)
+ SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.wear_suit.clean_blood()
+ cleaned_human.update_inv_wear_suit()
+ else if(cleaned_human.w_uniform)
+ SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.w_uniform.clean_blood()
+ cleaned_human.update_inv_w_uniform()
+ if(cleaned_human.shoes)
+ SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.shoes.clean_blood()
+ cleaned_human.update_inv_shoes()
+ SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.clean_blood()
+ cleaned_human.wash_cream()
+ cleaned_human.regenerate_icons()
// 4.6x30mm (Autorifles)
@@ -57,4 +66,4 @@
/obj/item/projectile/bullet/incendiary/c46x30mm
name = "4.6x30mm incendiary bullet"
damage = 10
- fire_stacks = 1
+ fire_stacks = 1
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 711fe11d5d..f540ae850d 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -175,7 +175,7 @@
data["chosenPillStyle"] = chosenPillStyle
data["isPillBottleLoaded"] = bottle ? 1 : 0
if(bottle)
- GET_COMPONENT_FROM(STRB, /datum/component/storage, bottle)
+ var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
data["pillBotContent"] = bottle.contents.len
data["pillBotMaxContent"] = STRB.max_items
@@ -263,7 +263,7 @@
var/target_loc = bottle ? bottle : drop_location()
var/drop_threshold = INFINITY
if(bottle)
- GET_COMPONENT_FROM(STRB, /datum/component/storage, bottle)
+ var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
if(STRB)
drop_threshold = STRB.max_items - bottle.contents.len
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 6efa4276b6..05fa4d382a 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -188,7 +188,7 @@
to_chat(usr, "ERROR: Cannot replicate virus strain.")
return
A = A.Copy()
- var/list/data = list("viruses" = list(A))
+ var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY", "viruses" = list(A))
var/obj/item/reagent_containers/glass/bottle/B = new(drop_location())
B.name = "[A.name] culture bottle"
B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium."
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 10d0405950..15d517a0f5 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -423,7 +423,7 @@
. = 1
/datum/reagent/drug/happiness/addiction_act_stage1(mob/living/M)// all work and no play makes jack a dull boy
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_DISTURBED))
M.Jitter(5)
if(prob(20))
@@ -431,7 +431,7 @@
..()
/datum/reagent/drug/happiness/addiction_act_stage2(mob/living/M)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_UNSTABLE))
M.Jitter(10)
if(prob(30))
@@ -439,7 +439,7 @@
..()
/datum/reagent/drug/happiness/addiction_act_stage3(mob/living/M)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_CRAZY))
M.Jitter(15)
if(prob(40))
@@ -447,7 +447,7 @@
..()
/datum/reagent/drug/happiness/addiction_act_stage4(mob/living/carbon/human/M)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(SANITY_INSANE)
M.Jitter(20)
if(prob(50))
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 4bdb22e227..592f7bc592 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -1443,7 +1443,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
M.dizziness = max(0, M.dizziness-6)
M.confused = max(0, M.confused-6)
M.disgust = max(0, M.disgust-6)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
if(mood.sanity <= SANITY_NEUTRAL) // only take effect if in negative sanity and then...
mood.setSanity(min(mood.sanity+5, SANITY_NEUTRAL)) // set minimum to prevent unwanted spiking over neutral
..()
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 40a518fd6c..40d151e021 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1,9 +1,9 @@
/datum/reagent/blood
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
name = "Blood"
id = "blood"
- color = "#C80000" // rgb: 200, 0, 0
- description = "Blood from a human, or otherwise."
+ color = BLOOD_COLOR_HUMAN // rgb: 200, 0, 0
+ description = "Blood from some creature."
metabolization_rate = 5 //fast rate so it disappears fast.
taste_description = "iron"
taste_mult = 1.3
@@ -28,27 +28,75 @@
if(iscarbon(L))
var/mob/living/carbon/C = L
- if(C.get_blood_id() == "blood" && (method == INJECT || (method == INGEST && C.dna && C.dna.species && (DRINKSBLOOD in C.dna.species.species_traits))))
- if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type)))
- C.reagents.add_reagent("toxin", reac_volume * 0.5)
- else
- C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM)
+ var/blood_id = C.get_blood_id()
+ if((blood_id == "blood" || blood_id == "jellyblood") && (method == INJECT || (method == INGEST && C.dna && C.dna.species && (DRINKSBLOOD in C.dna.species.species_traits))))
+ C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM * C.blood_ratio)
+ // we don't care about bloodtype here, we're just refilling the mob
- if(reac_volume >= 10 && istype(L))
+ if(reac_volume >= 10 && istype(L) && method != INJECT)
L.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+/datum/reagent/blood/on_mob_life(mob/living/carbon/C) //Because lethals are preferred over stamina. damnifino.
+ var/blood_id = C.get_blood_id()
+ if((blood_id == "blood" || blood_id == "jellyblood"))
+ if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type))) //we only care about bloodtype here because this is where the poisoning should be
+ C.adjustToxLoss(rand(2,8)*REM, TRUE, TRUE) //forced to ensure people don't use it to gain beneficial toxin as slime person
+ ..()
+
/datum/reagent/blood/reaction_obj(obj/O, volume)
if(volume >= 3 && istype(O))
- O.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+ O.add_blood_DNA(data)
+
+/datum/reagent/blood/reaction_turf(turf/T, reac_volume)//splash the blood all over the place
+ if(!istype(T))
+ return
+ if(reac_volume < 3)
+ return
+
+ var/obj/effect/decal/cleanable/blood/B = locate() in T //find some blood here
+ if(!B)
+ B = new(T)
+ if(data["blood_DNA"])
+ B.blood_DNA[data["blood_DNA"]] = data["blood_type"]
+ if(!B.reagents)
+ B.reagents.add_reagent(id, reac_volume)
+ B.update_icon()
/datum/reagent/blood/on_new(list/data)
if(istype(data))
SetViruses(src, data)
+ color = bloodtype_to_color(data["blood_type"])
+ if(data["blood_type"] == "SY")
+ name = "Synthetic Blood"
+ taste_description = "oily"
+
+ if(data["blood_type"] == "X*")
+ name = "Xenomorph Blood"
+ taste_description = "acidic heresy"
+ shot_glass_icon_state = "shotglassgreen"
+ pH = 2.5
+
+ if(data["blood_type"] == "HF")
+ name = "Hydraulic Blood"
+ taste_description = "burnt oil"
+ pH = 9.75
+
+ if(data["blood_type"] == "BUG")
+ name = "Insect Blood"
+ taste_description = "greasy"
+ pH = 7.25
+
+ if(data["blood_type"] == "L")
+ name = "Lizard Blood"
+ taste_description = "spicy"
+ pH = 6.85
+
+
/datum/reagent/blood/on_merge(list/mix_data)
if(data && mix_data)
if(data["blood_DNA"] != mix_data["blood_DNA"])
- data["cloneable"] = 0 //On mix, consider the genetic sampling unviable for pod cloning if the DNA sample doesn't match.
+ data["cloneable"] = FALSE //On mix, consider the genetic sampling unviable for pod cloning if the DNA sample doesn't match.
if(data["viruses"] || mix_data["viruses"])
var/list/mix1 = data["viruses"]
@@ -78,27 +126,111 @@
var/datum/disease/D = thing
. += D
-/datum/reagent/blood/reaction_turf(turf/T, reac_volume)//splash the blood all over the place
- if(!istype(T))
- return
- if(reac_volume < 3)
- return
+/datum/reagent/blood/synthetics
+ data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Synthetic Blood"
+ id = "syntheticblood"
+ taste_description = "oily"
+ color = BLOOD_COLOR_SYNTHETIC // rgb: 11, 7, 48
- var/obj/effect/decal/cleanable/blood/B = locate() in T //find some blood here
- if(!B)
- B = new(T)
- if(data["blood_DNA"])
- B.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+/datum/reagent/blood/lizard
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_LIZARD, "blood_type"="L","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Lizard Blood"
+ id = "lizardblood"
+ taste_description = "spicy"
+ color = BLOOD_COLOR_LIZARD // rgb: 11, 7, 48
+ pH = 6.85
+
+/datum/reagent/blood/jellyblood
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Slime Jelly Blood"
+ id = "jellyblood"
+ description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL."
+ color = BLOOD_COLOR_SLIME
+ taste_description = "slime"
+ taste_mult = 1.3
+ pH = 4
+
+/datum/reagent/blood/xenomorph
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Xenomorph Blood"
+ id = "xenoblood"
+ taste_description = "acidic heresy"
+ color = BLOOD_COLOR_XENO // greenish yellow ooze
+ shot_glass_icon_state = "shotglassgreen"
+ pH = 2.5
+
+/datum/reagent/blood/oil
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Hydraulic Blood"
+ id = "oilblood"
+ taste_description = "burnt oil"
+ color = BLOOD_COLOR_OIL // dark, y'know, expected batman colors.
+ pH = 9.75
+
+/datum/reagent/blood/insect
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_BUG, "blood_type"="BUG","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Insectoid Blood"
+ id = "bugblood"
+ taste_description = "waxy"
+ color = BLOOD_COLOR_BUG // Bug colored, I guess.
+ pH = 7.25
+
+
+/datum/reagent/blood/jellyblood/on_mob_life(mob/living/carbon/M)
+ if(prob(10))
+ if(M.dna?.species?.exotic_bloodtype != "GEL")
+ to_chat(M, "Your insides are burning!")
+ M.adjustToxLoss(rand(20,60)*REM, 0)
+ . = 1
+ else if(prob(40) && isjellyperson(M))
+ M.heal_bodypart_damage(2*REM)
+ . = 1
+ ..()
/datum/reagent/liquidgibs
name = "Liquid gibs"
id = "liquidgibs"
- color = "#FF9966"
+ color = BLOOD_COLOR_HUMAN
description = "You don't even want to think about what's in here."
taste_description = "gross iron"
shot_glass_icon_state = "shotglassred"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= "O+","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
pH = 7.45
+/datum/reagent/liquidgibs/xeno
+ name = "Liquid xeno gibs"
+ id = "liquidxenogibs"
+ color = BLOOD_COLOR_XENO
+ taste_description = "blended heresy"
+ shot_glass_icon_state = "shotglassgreen"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ pH = 2.5
+
+/datum/reagent/liquidgibs/slime
+ name = "Slime sludge"
+ id = "liquidslimegibs"
+ color = BLOOD_COLOR_SLIME
+ taste_description = "slime"
+ shot_glass_icon_state = "shotglassgreen"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ pH = 4
+
+/datum/reagent/liquidgibs/synth
+ name = "Synthetic sludge"
+ id = "liquidsyntheticgibs"
+ color = BLOOD_COLOR_SYNTHETIC
+ taste_description = "jellied plastic"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+
+/datum/reagent/liquidgibs/oil
+ name = "Hydraulic sludge"
+ id = "liquidoilgibs"
+ color = BLOOD_COLOR_OIL
+ taste_description = "chunky burnt oil"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ pH = 9.75
+
/datum/reagent/vaccine
//data must contain virus type
name = "Vaccine"
@@ -585,6 +717,30 @@
race = /datum/species/android
mutationtext = "The pain subsides. You feel... artificial."
+//Citadel Races
+/datum/reagent/mutationtoxin/mammal
+ name = "Mammal Mutation Toxin"
+ id = "mammalmutationtoxin"
+ description = "A glowing toxin."
+ color = "#5EFF3B" //RGB: 94, 255, 59
+ race = /datum/species/mammal
+ mutationtext = "The pain subsides. You feel... fluffier."
+
+/datum/reagent/mutationtoxin/insect
+ name = "Insect Mutation Toxin"
+ id = "insectmutationtoxin"
+ description = "A glowing toxin."
+ color = "#5EFF3B" //RGB: 94, 255, 59
+ race = /datum/species/insect
+ mutationtext = "The pain subsides. You feel... attracted to dark, moist areas."
+
+/datum/reagent/mutationtoxin/xenoperson
+ name = "Xeno-Hybrid Mutation Toxin"
+ id = "xenopersonmutationtoxin"
+ description = "A glowing toxin."
+ color = "#5EFF3B" //RGB: 94, 255, 59
+ race = /datum/species/xeno
+ mutationtext = "The pain subsides. You feel... oddly longing for the Queen." //sadly, not the British one.
//BLACKLISTED RACES
/datum/reagent/mutationtoxin/skeleton
@@ -947,12 +1103,12 @@
reagent_state = SOLID
taste_description = "iron"
pH = 6
-
+ overdose_threshold = 30
color = "#c2391d"
/datum/reagent/iron/on_mob_life(mob/living/carbon/C)
if(C.blood_volume < (BLOOD_VOLUME_NORMAL*C.blood_ratio))
- C.blood_volume += 0.5
+ C.blood_volume += 0.01 //we'll have synthetics from medbay.
..()
/datum/reagent/iron/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
@@ -961,6 +1117,17 @@
M.reagents.add_reagent("toxin", reac_volume)
..()
+/datum/reagent/iron/overdose_start(mob/living/M)
+ to_chat(M, "You start feeling your guts twisting painfully!")
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/overdose, name)
+
+/datum/reagent/iron/overdose_process(mob/living/carbon/C)
+ if(prob(20))
+ var/obj/item/organ/liver/L = C.getorganslot(ORGAN_SLOT_LIVER)
+ if (istype(L))
+ C.applyLiverDamage(2) //mild until the fabled med rework comes out. the organ damage galore
+ ..()
+
/datum/reagent/gold
name = "Gold"
id = "gold"
@@ -1077,17 +1244,19 @@
pH = 5.5
/datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume)
- if(istype(O, /obj/effect/decal/cleanable))
+ if(istype(O, /obj/effect/decal/cleanable) || istype(O, /obj/item/projectile/bullet/reusable/foam_dart) || istype(O, /obj/item/ammo_casing/caseless/foam_dart))
qdel(O)
else
if(O)
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ O.clean_blood()
/datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 1)
T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ T.clean_blood()
for(var/obj/effect/decal/cleanable/C in T)
qdel(C)
@@ -1105,26 +1274,33 @@
H.lip_style = null
H.update_body()
for(var/obj/item/I in C.held_items)
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ I.clean_blood()
if(C.wear_mask)
- if(SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(C.wear_mask.clean_blood())
C.update_inv_wear_mask()
if(ishuman(M))
var/mob/living/carbon/human/H = C
if(H.head)
- if(SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.head.clean_blood())
H.update_inv_head()
if(H.wear_suit)
- if(SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.wear_suit.clean_blood())
H.update_inv_wear_suit()
else if(H.w_uniform)
- if(SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.w_uniform.clean_blood())
H.update_inv_w_uniform()
if(H.shoes)
- if(SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.shoes.clean_blood())
H.update_inv_shoes()
H.wash_cream()
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ M.clean_blood()
/datum/reagent/space_cleaner/ez_clean
name = "EZ Clean"
@@ -2119,26 +2295,22 @@
chemical_flags = REAGENT_INVISIBLE
/datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C)
- if(C && C.dna && data["desired_dna"])
+ if(ishuman(C) && C.dna && data["desired_dna"])
original_dna = new C.dna.type
C.dna.copy_dna(original_dna)
var/datum/dna/new_dna = data["desired_dna"]
- new_dna.copy_dna(C.dna)
+ new_dna.transfer_identity(C, TRUE)
C.real_name = new_dna.real_name
- C.updateappearance(mutcolor_update=1)
- C.update_body()
+ C.updateappearance(mutcolor_update = TRUE)
C.domutcheck()
- C.regenerate_icons()
..()
/datum/reagent/changeling_string/on_mob_end_metabolize(mob/living/carbon/C)
if(original_dna)
- original_dna.copy_dna(C.dna)
+ original_dna.transfer_identity(C, TRUE)
C.real_name = original_dna.real_name
- C.updateappearance(mutcolor_update=1)
- C.update_body()
+ C.updateappearance(mutcolor_update = TRUE)
C.domutcheck()
- C.regenerate_icons()
..()
/datum/reagent/changeling_string/Destroy()
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index 2ed9a31107..374f7715bb 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -283,6 +283,12 @@
results = list("regen_jelly" = 2)
required_reagents = list("tricordrazine" = 1, "slimejelly" = 1)
+/datum/chemical_reaction/jelly_convert
+ name = "Blood Jelly Conversion"
+ id = "blood_jelly"
+ results = list("slimejelly" = 1)
+ required_reagents = list("toxin" = 1, "jellyblood" = 1)
+
/datum/chemical_reaction/corazone
name = "Corazone"
id = "corazone"
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index b3f9591f64..d475b118b2 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -26,7 +26,7 @@
create_reagents(volume, reagent_flags)
if(spawned_disease)
var/datum/disease/F = new spawned_disease()
- var/list/data = list("viruses"= list(F))
+ var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY","viruses"= list(F))
reagents.add_reagent("blood", disease_amount, data)
add_initial_reagents()
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index 3e555f385f..fe35981bfe 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -4,13 +4,16 @@
icon = 'icons/obj/bloodpack.dmi'
icon_state = "bloodpack"
volume = 200
+ reagent_flags = DRAINABLE
var/blood_type = null
var/labelled = 0
+ var/color_to_apply = "#FFFFFF"
+ var/mutable_appearance/fill_overlay
/obj/item/reagent_containers/blood/Initialize()
. = ..()
if(blood_type != null)
- reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
+ reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_colour"=color, "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
update_icon()
/obj/item/reagent_containers/blood/on_reagent_change(changetype)
@@ -18,6 +21,7 @@
var/datum/reagent/blood/B = reagents.has_reagent("blood")
if(B && B.data && B.data["blood_type"])
blood_type = B.data["blood_type"]
+ color_to_apply = bloodtype_to_color(blood_type)
else
blood_type = null
update_pack_name()
@@ -45,7 +49,7 @@
/obj/item/reagent_containers/blood/random/Initialize()
icon_state = "bloodpack"
- blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L")
+ blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L", "SY", "HF", "GEL", "BUG")
return ..()
/obj/item/reagent_containers/blood/APlus
@@ -72,6 +76,18 @@
/obj/item/reagent_containers/blood/universal
blood_type = "U"
+/obj/item/reagent_containers/blood/synthetics
+ blood_type = "SY"
+
+/obj/item/reagent_containers/blood/oilblood
+ blood_type = "HF"
+
+/obj/item/reagent_containers/blood/jellyblood
+ blood_type = "GEL"
+
+/obj/item/reagent_containers/blood/insect
+ blood_type = "BUG"
+
/obj/item/reagent_containers/blood/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon))
if(!user.is_literate())
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index a4a6a7d473..5edddd64c2 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -283,7 +283,7 @@
/obj/machinery/disposal/bin/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/bag/trash)) //Not doing component overrides because this is a specific type.
var/obj/item/storage/bag/trash/T = I
- GET_COMPONENT_FROM(STR, /datum/component/storage, T)
+ var/datum/component/storage/STR = T.GetComponent(/datum/component/storage)
to_chat(user, "You empty the bag.")
for(var/obj/item/O in T.contents)
STR.remove_from_storage(O,src)
diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm
index 624d5e0e05..348e687e03 100644
--- a/code/modules/recycling/disposal/construction.dm
+++ b/code/modules/recycling/disposal/construction.dm
@@ -29,7 +29,7 @@
pipename = initial(pipe_type.name)
if(flip)
- GET_COMPONENT(rotcomp,/datum/component/simple_rotation)
+ var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
rotcomp.BaseRot(null,ROTATION_FLIP)
update_icon()
diff --git a/code/modules/research/designs/machine_desings/machine_designs_medical.dm b/code/modules/research/designs/machine_desings/machine_designs_medical.dm
index 65b3d74f71..2f95954e01 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_medical.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_medical.dm
@@ -89,3 +89,11 @@
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_ENGINEERING
build_path = /obj/item/circuitboard/machine/clonescanner
category = list("Medical Machinery")
+
+/datum/design/board/bloodbankgen
+ name = "Machine Design (Blood Bank Generator Board)"
+ desc = "The circuit board for a blood bank generator."
+ id = "bloodbankgen"
+ build_path = /obj/item/circuitboard/machine/bloodbankgen
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ category = list ("Medical Machinery")
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 11bc31bedc..5176c4fd71 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -105,7 +105,7 @@
materials = list(MAT_METAL = 200)
build_path = /obj/item/ammo_casing/shotgun/stunslug
category = list("Ammo")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/techshell
name = "Unloaded Technological Shotshell"
@@ -139,7 +139,7 @@
materials = list(MAT_METAL = 500, MAT_GLASS = 300)
build_path = /obj/item/firing_pin/test_range
category = list("Firing Pins")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/pin_mindshield
name = "Mindshield Firing Pin"
@@ -235,7 +235,7 @@
reagents_list = list("radium" = 20)
build_path = /obj/item/gun/energy/floragun
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/xray
name = "X-ray Laser Gun"
@@ -309,7 +309,7 @@
materials = list(MAT_METAL = 2000, MAT_PLASMA = 500)
build_path = /obj/item/grenade/chem_grenade/pyro
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/cryo_grenade
name = "Cryo Grenade"
@@ -319,7 +319,7 @@
materials = list(MAT_METAL = 2000, MAT_SILVER = 500)
build_path = /obj/item/grenade/chem_grenade/cryo
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/adv_grenade
name = "Advanced Release Grenade"
@@ -329,7 +329,7 @@
materials = list(MAT_METAL = 3000, MAT_GLASS = 500)
build_path = /obj/item/grenade/chem_grenade/adv_release
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
//////////
//MISC////
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index e56350a280..0bcd0c5984 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -422,7 +422,7 @@
if(exp == SCANTYPE_OBLITERATE)
visible_message("[exp_on] activates the crushing mechanism, [exp_on] is destroyed!")
if(linked_console.linked_lathe)
- GET_COMPONENT_FROM(linked_materials, /datum/component/material_container, linked_console.linked_lathe)
+ var/datum/component/material_container/linked_materials = linked_console.linked_lathe.GetComponent(/datum/component/material_container)
for(var/material in exp_on.materials)
linked_materials.insert_amount( min((linked_materials.max_amount - linked_materials.total_amount), (exp_on.materials[material])), material)
if(prob(EFFECT_PROB_LOW) && criticalReaction)
diff --git a/code/modules/research/research_disk.dm b/code/modules/research/research_disk.dm
index 2ec2398d88..02865dc5bb 100644
--- a/code/modules/research/research_disk.dm
+++ b/code/modules/research/research_disk.dm
@@ -29,3 +29,12 @@
/obj/item/disk/tech_disk/illegal/Initialize()
. = ..()
stored_research = new /datum/techweb/syndicate
+
+/obj/item/disk/tech_disk/abductor
+ name = "Gray technology disk"
+ desc = "You feel like it's not Gray because of its color."
+ materials = list()
+
+/obj/item/disk/tech_disk/abductor/Initialize()
+ . = ..()
+ stored_research = new /datum/techweb/abductor
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index cd5a190fd6..df58bfd138 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -49,6 +49,14 @@
var/datum/techweb_node/syndicate_basic/Node = new()
research_node(Node, TRUE)
+/datum/techweb/abductor
+ id = "ABDUCTOR"
+ organization = "Aliens"
+
+/datum/techweb/abductor/New()
+ var/datum/techweb_node/alientech/Node = new()
+ research_node(Node, TRUE)
+
/datum/techweb/science //Global science techweb for RND consoles.
id = "SCIENCE"
organization = "Nanotrasen"
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 5b3a21dd5c..aea4192517 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -60,7 +60,7 @@
display_name = "Biological Technology"
description = "What makes us tick." //the MC, silly!
prereq_ids = list("base")
- design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag")
+ design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -1027,26 +1027,19 @@
id = "alien_bio"
display_name = "Alien Biological Tools"
description = "Advanced biological tools."
- prereq_ids = list("alientech", "adv_biotech")
+ prereq_ids = list("alientech", "advance_surgerytools")
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
- boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien,
- /obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor, /obj/item/stock_parts/cell/infinite/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor)
- research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
- export_price = 20000
- hidden = TRUE
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
+ export_price = 10000
/datum/techweb_node/alien_engi
id = "alien_engi"
display_name = "Alien Engineering"
description = "Alien engineering tools"
- prereq_ids = list("alientech", "adv_engi")
+ prereq_ids = list("alientech", "exp_tools")
design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
- boost_item_paths = list(/obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor, /obj/item/stock_parts/cell/infinite/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor)
- research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
- export_price = 20000
- hidden = TRUE
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
+ export_price = 10000
/datum/techweb_node/syndicate_basic
id = "syndicate_basic"
@@ -1106,4 +1099,4 @@
for(var/i in processing)
var/datum/techweb_node/TN = i
TW.add_point_list(TN.research_costs)
- return TW.printout_points()
\ No newline at end of file
+ return TW.printout_points()
diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm
index b28f1676a1..0099fe143d 100644
--- a/code/modules/research/xenobiology/crossbreeding/_misc.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm
@@ -58,9 +58,7 @@
var/mob/living/carbon/human/H = M
if(H.mind && !HAS_TRAIT(H, TRAIT_AGEUSIA))
to_chat(H,"That didn't taste very good...") //No disgust, though. It's just not good tasting.
- GET_COMPONENT_FROM(mood, /datum/component/mood, H)
- if(mood)
- mood.add_event(null,"gross_food", /datum/mood_event/gross_food)
+ SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "gross_food", /datum/mood_event/gross_food)
last_check_time = world.time
return
..()
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index d779501d30..7c812da065 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -64,10 +64,9 @@
var/interrupted = FALSE
var/mob/target
var/icon/bluespace
- var/datum/weakref/redirect_component
/datum/status_effect/slimerecall/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/resistField))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/resistField)
to_chat(owner, "You feel a sudden tug from an unknown force, and feel a pull to bluespace!")
to_chat(owner, "Resist if you wish avoid the force!")
bluespace = icon('icons/effects/effects.dmi',"chronofield")
@@ -77,9 +76,9 @@
/datum/status_effect/slimerecall/proc/resistField()
interrupted = TRUE
owner.remove_status_effect(src)
+
/datum/status_effect/slimerecall/on_remove()
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
owner.cut_overlay(bluespace)
if(interrupted || !ismob(target))
to_chat(owner, "The bluespace tug fades away, and you feel that the force has passed you by.")
@@ -98,10 +97,9 @@
duration = -1 //Will remove self when block breaks.
alert_type = /obj/screen/alert/status_effect/freon/stasis
var/obj/structure/ice_stasis/cube
- var/datum/weakref/redirect_component
/datum/status_effect/frozenstasis/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/breakCube))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/breakCube)
cube = new /obj/structure/ice_stasis(get_turf(owner))
owner.forceMove(cube)
owner.status_flags |= GODMODE
@@ -118,8 +116,7 @@
if(cube)
qdel(cube)
owner.status_flags &= ~GODMODE
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
/datum/status_effect/slime_clone
id = "slime_cloned"
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 5aebd1bafa..594ca117d7 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -29,8 +29,6 @@
var/datum/action/innate/slime_scan/scan_action
var/datum/action/innate/feed_potion/potion_action
- var/datum/component/redirect/listener
-
var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion
var/max_slimes = 5
@@ -50,7 +48,7 @@
scan_action = new
potion_action = new
stored_slimes = list()
- listener = AddComponent(/datum/component/redirect, list(COMSIG_ATOM_CONTENTS_DEL = CALLBACK(src, .proc/on_contents_del)))
+ RegisterSignal(src, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
stored_slimes = null
diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
new file mode 100644
index 0000000000..0d4d2b6ad6
--- /dev/null
+++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -0,0 +1,529 @@
+GLOBAL_VAR_INIT(hhStorageTurf, null)
+GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
+
+/obj/item/hilbertshotel
+ name = "Hilbert's Hotel"
+ desc = "A sphere of what appears to be an intricate network of bluespace. Observing it in detail seems to give you a headache as you try to comprehend the infinite amount of infinitesimally distinct points on its surface."
+ icon_state = "hilbertshotel"
+ w_class = WEIGHT_CLASS_SMALL
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ var/datum/map_template/hilbertshotel/hotelRoomTemp
+ var/datum/map_template/hilbertshotel/empty/hotelRoomTempEmpty
+ var/datum/map_template/hilbertshotel/lore/hotelRoomTempLore
+ var/list/activeRooms = list()
+ var/list/storedRooms = list()
+ var/storageTurf
+ //Lore Stuff
+ var/ruinSpawned = FALSE
+ var/mysteryRoom
+
+/obj/item/hilbertshotel/Initialize()
+ . = ..()
+ //Load templates
+ hotelRoomTemp = new()
+ hotelRoomTempEmpty = new()
+ hotelRoomTempLore = new()
+ var/area/currentArea = get_area(src)
+ if(currentArea.type == /area/ruin/space/has_grav/hilbertresearchfacility)
+ ruinSpawned = TRUE
+
+/obj/item/hilbertshotel/Destroy()
+ ejectRooms()
+ return ..()
+
+/obj/item/hilbertshotel/attack(mob/living/M, mob/living/user)
+ if(M.mind)
+ to_chat(user, "You invite [M] to the hotel.")
+ promptAndCheckIn(M)
+ else
+ to_chat(user, "[M] is not intelligent enough to understand how to use this device!")
+
+/obj/item/hilbertshotel/attack_self(mob/user)
+ . = ..()
+ promptAndCheckIn(user)
+
+/obj/item/hilbertshotel/proc/promptAndCheckIn(mob/user)
+ var/chosenRoomNumber = input(user, "What number room will you be checking into?", "Room Number") as null|num
+ if(!chosenRoomNumber)
+ return
+ if(chosenRoomNumber > SHORT_REAL_LIMIT)
+ to_chat(user, "You have to check out the first [SHORT_REAL_LIMIT] rooms before you can go to a higher numbered one!")
+ return
+ if((chosenRoomNumber < 1) || (chosenRoomNumber != round(chosenRoomNumber)))
+ to_chat(user, "That is not a valid room number!")
+ return
+ if(ismob(loc))
+ if(user == loc) //Not always the same as user
+ forceMove(get_turf(user))
+ if(!storageTurf) //Blame subsystems for not allowing this to be in Initialize
+ if(!GLOB.hhStorageTurf)
+ var/datum/map_template/hilbertshotelstorage/storageTemp = new()
+ var/datum/turf_reservation/storageReservation = SSmapping.RequestBlockReservation(3, 3)
+ storageTemp.load(locate(storageReservation.bottom_left_coords[1], storageReservation.bottom_left_coords[2], storageReservation.bottom_left_coords[3]))
+ GLOB.hhStorageTurf = locate(storageReservation.bottom_left_coords[1]+1, storageReservation.bottom_left_coords[2]+1, storageReservation.bottom_left_coords[3])
+ else
+ storageTurf = GLOB.hhStorageTurf
+ if(tryActiveRoom(chosenRoomNumber, user))
+ return
+ if(tryStoredRoom(chosenRoomNumber, user))
+ return
+ sendToNewRoom(chosenRoomNumber, user)
+
+
+/obj/item/hilbertshotel/proc/tryActiveRoom(var/roomNumber, var/mob/user)
+ if(activeRooms["[roomNumber]"])
+ var/datum/turf_reservation/roomReservation = activeRooms["[roomNumber]"]
+ do_sparks(3, FALSE, get_turf(user))
+ user.forceMove(locate(roomReservation.bottom_left_coords[1] + hotelRoomTemp.landingZoneRelativeX, roomReservation.bottom_left_coords[2] + hotelRoomTemp.landingZoneRelativeY, roomReservation.bottom_left_coords[3]))
+ return TRUE
+ else
+ return FALSE
+
+/obj/item/hilbertshotel/proc/tryStoredRoom(var/roomNumber, var/mob/user)
+ if(storedRooms["[roomNumber]"])
+ var/datum/turf_reservation/roomReservation = SSmapping.RequestBlockReservation(hotelRoomTemp.width, hotelRoomTemp.height)
+ hotelRoomTempEmpty.load(locate(roomReservation.bottom_left_coords[1], roomReservation.bottom_left_coords[2], roomReservation.bottom_left_coords[3]))
+ var/turfNumber = 1
+ for(var/i=0, iAs the sphere breaks apart, you're suddenly ejected into the depths of space!")
+ var/max = world.maxx-TRANSITIONEDGE
+ var/min = 1+TRANSITIONEDGE
+ var/list/possible_transtitons = list()
+ for(var/AZ in SSmapping.z_list)
+ var/datum/space_level/D = AZ
+ if (D.linkage == CROSSLINKED)
+ possible_transtitons += D.z_value
+ var/_z = pick(possible_transtitons)
+ var/_x = rand(min,max)
+ var/_y = rand(min,max)
+ var/turf/T = locate(_x, _y, _z)
+ A.forceMove(T)
+ qdel(room)
+
+ if(storedRooms.len)
+ for(var/x in storedRooms)
+ var/list/atomList = storedRooms[x]
+ for(var/atom/movable/A in atomList)
+ var/max = world.maxx-TRANSITIONEDGE
+ var/min = 1+TRANSITIONEDGE
+ var/list/possible_transtitons = list()
+ for(var/AZ in SSmapping.z_list)
+ var/datum/space_level/D = AZ
+ if (D.linkage == CROSSLINKED)
+ possible_transtitons += D.z_value
+ var/_z = pick(possible_transtitons)
+ var/_x = rand(min,max)
+ var/_y = rand(min,max)
+ var/turf/T = locate(_x, _y, _z)
+ A.forceMove(T)
+
+//Template Stuff
+/datum/map_template/hilbertshotel
+ name = "Hilbert's Hotel Room"
+ mappath = '_maps/templates/hilbertshotel.dmm'
+ var/landingZoneRelativeX = 2
+ var/landingZoneRelativeY = 8
+
+/datum/map_template/hilbertshotel/empty
+ name = "Empty Hilbert's Hotel Room"
+ mappath = '_maps/templates/hilbertshotelempty.dmm'
+
+/datum/map_template/hilbertshotel/lore
+ name = "Doctor Hilbert's Deathbed"
+ mappath = '_maps/templates/hilbertshotellore.dmm'
+
+/datum/map_template/hilbertshotelstorage
+ name = "Hilbert's Hotel Storage"
+ mappath = '_maps/templates/hilbertshotelstorage.dmm'
+
+
+//Turfs and Areas
+/turf/closed/indestructible/hotelwall
+ name = "hotel wall"
+ desc = "A wall designed to protect the security of the hotel's guests."
+ icon_state = "hotelwall"
+ canSmoothWith = list(/turf/closed/indestructible/hotelwall)
+ explosion_block = INFINITY
+
+/turf/open/indestructible/hotelwood
+ desc = "Stylish dark wood with extra reinforcement. Secured firmly to the floor to prevent tampering."
+ icon_state = "wood"
+ footstep = FOOTSTEP_WOOD
+ tiled_dirt = FALSE
+
+/turf/open/indestructible/hoteltile
+ desc = "Smooth tile with extra reinforcement. Secured firmly to the floor to prevent tampering."
+ icon_state = "showroomfloor"
+ footstep = FOOTSTEP_FLOOR
+ tiled_dirt = FALSE
+
+/turf/open/space/bluespace
+ name = "\proper bluespace hyperzone"
+ icon_state = "bluespace"
+ baseturfs = /turf/open/space/bluespace
+ flags_1 = NOJAUNT_1
+ explosion_block = INFINITY
+ var/obj/item/hilbertshotel/parentSphere
+
+/turf/open/space/bluespace/Entered(atom/movable/A)
+ . = ..()
+ A.forceMove(get_turf(parentSphere))
+
+/turf/closed/indestructible/hoteldoor
+ name = "Hotel Door"
+ icon_state = "hoteldoor"
+ explosion_block = INFINITY
+ var/obj/item/hilbertshotel/parentSphere
+
+/turf/closed/indestructible/hoteldoor/proc/promptExit(mob/living/user)
+ if(!isliving(user))
+ return
+ if(!user.mind)
+ return
+ if(!parentSphere)
+ to_chat(user, "The door seems to be malfunctioning and refuses to operate!")
+ return
+ if(alert(user, "Hilbert's Hotel would like to remind you that while we will do everything we can to protect the belongings you leave behind, we make no guarantees of their safety while you're gone, especially that of the health of any living creatures. With that in mind, are you ready to leave?", "Exit", "Leave", "Stay") == "Leave")
+ if(!user.canmove || (get_dist(get_turf(src), get_turf(user)) > 1)) //no teleporting around if they're dead or moved away during the prompt.
+ return
+ user.forceMove(get_turf(parentSphere))
+ do_sparks(3, FALSE, get_turf(user))
+
+/turf/closed/indestructible/hoteldoor/attack_ghost(mob/dead/observer/user)
+ if(!isobserver(user) || !parentSphere)
+ return ..()
+ user.forceMove(get_turf(parentSphere))
+
+//If only this could be simplified...
+/turf/closed/indestructible/hoteldoor/attack_tk(mob/user)
+ return //need to be close.
+
+/turf/closed/indestructible/hoteldoor/attack_hand(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_animal(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_paw(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_hulk(mob/living/carbon/human/user, does_attack_animation)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_larva(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_slime(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_robot(mob/user)
+ if(get_dist(get_turf(src), get_turf(user)) <= 1)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/AltClick(mob/user)
+ . = ..()
+ if(get_dist(get_turf(src), get_turf(user)) <= 1)
+ to_chat(user, "You peak through the door's bluespace peephole...")
+ user.reset_perspective(parentSphere)
+ user.set_machine(src)
+ var/datum/action/peepholeCancel/PHC = new
+ user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1)
+ PHC.Grant(user)
+
+/turf/closed/indestructible/hoteldoor/check_eye(mob/user)
+ if(get_dist(get_turf(src), get_turf(user)) >= 2)
+ user.unset_machine()
+ for(var/datum/action/peepholeCancel/PHC in user.actions)
+ PHC.Trigger()
+
+/datum/action/peepholeCancel
+ name = "Cancel View"
+ desc = "Stop looking through the bluespace peephole."
+ button_icon_state = "cancel_peephole"
+
+/datum/action/peepholeCancel/Trigger()
+ . = ..()
+ to_chat(owner, "You move away from the peephole.")
+ owner.reset_perspective()
+ owner.clear_fullscreen("remote_view", 0)
+ qdel(src)
+
+/area/hilbertshotel
+ name = "Hilbert's Hotel Room"
+ icon_state = "hilbertshotel"
+ requires_power = FALSE
+ has_gravity = TRUE
+ noteleport = TRUE
+ hidden = TRUE
+ unique = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+ ambientsounds = list('sound/ambience/servicebell.ogg')
+ var/roomnumber = 0
+ var/obj/item/hilbertshotel/parentSphere
+ var/datum/turf_reservation/reservation
+ var/turf/storageTurf
+
+/area/hilbertshotel/Entered(atom/movable/AM)
+ . = ..()
+ if(istype(AM, /obj/item/hilbertshotel))
+ relocate(AM)
+ var/list/obj/item/hilbertshotel/hotels = AM.GetAllContents(/obj/item/hilbertshotel)
+ for(var/obj/item/hilbertshotel/H in hotels)
+ if(parentSphere == H)
+ relocate(H)
+
+/area/hilbertshotel/proc/relocate(obj/item/hilbertshotel/H)
+ if(prob(0.135685)) //Because screw you
+ qdel(H)
+ return
+ var/turf/targetturf = find_safe_turf()
+ if(!targetturf)
+ if(GLOB.blobstart.len > 0)
+ targetturf = get_turf(pick(GLOB.blobstart))
+ else
+ CRASH("Unable to find a blobstart landmark")
+ var/turf/T = get_turf(H)
+ var/area/A = T.loc
+ log_game("[H] entered itself. Moving it to [loc_name(targetturf)].")
+ message_admins("[H] entered itself. Moving it to [ADMIN_VERBOSEJMP(targetturf)].")
+ for(var/mob/M in A)
+ to_chat(M, "[H] almost implodes in upon itself, but quickly rebounds, shooting off into a random point in space!")
+ H.forceMove(targetturf)
+
+/area/hilbertshotel/Exited(atom/movable/AM)
+ . = ..()
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.mind)
+ var/stillPopulated = FALSE
+ var/list/currentLivingMobs = GetAllContents(/mob/living) //Got to catch anyone hiding in anything
+ for(var/mob/living/L in currentLivingMobs) //Check to see if theres any sentient mobs left.
+ if(L.mind)
+ stillPopulated = TRUE
+ break
+ if(!stillPopulated)
+ storeRoom()
+
+/area/hilbertshotel/proc/storeRoom()
+ var/roomSize = (reservation.top_right_coords[1]-reservation.bottom_left_coords[1]+1)*(reservation.top_right_coords[2]-reservation.bottom_left_coords[2]+1)
+ var/storage[roomSize]
+ var/turfNumber = 1
+ var/obj/item/abstracthotelstorage/storageObj = new(storageTurf)
+ storageObj.roomNumber = roomnumber
+ storageObj.parentSphere = parentSphere
+ storageObj.name = "Room [roomnumber] Storage"
+ for(var/i=0, iIt's to far away to scan!")
+ return
+ var/obj/item/hilbertshotel/sphere = target
+ if(sphere.activeRooms.len)
+ to_chat(user, "Currently Occupied Rooms:")
+ for(var/roomnumber in sphere.activeRooms)
+ to_chat(user, roomnumber)
+ else
+ to_chat(user, "No currenty occupied rooms.")
+ if(sphere.storedRooms.len)
+ to_chat(user, "Vacated Rooms:")
+ for(var/roomnumber in sphere.storedRooms)
+ to_chat(user, roomnumber)
+ else
+ to_chat(user, "No vacated rooms.")
+
+/obj/effect/mob_spawn/human/doctorhilbert
+ name = "Doctor Hilbert"
+ mob_name = "Doctor Hilbert"
+ mob_gender = "male"
+ assignedrole = null
+ ghost_usable = FALSE
+ oxy_damage = 500
+ mob_species = /datum/species/skeleton
+ id_job = "Head Researcher"
+ id_access = ACCESS_RESEARCH
+ id_access_list = list(ACCESS_AWAY_GENERIC3, ACCESS_RESEARCH)
+ instant = TRUE
+ id = /obj/item/card/id/silver
+ uniform = /obj/item/clothing/under/rank/research_director
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ back = /obj/item/storage/backpack/satchel/leather
+ suit = /obj/item/clothing/suit/toggle/labcoat
+
+/obj/item/paper/crumpled/docslogs
+ name = "Research Logs"
+
+/obj/item/paper/crumpled/docslogs/Initialize()
+ . = ..()
+ GLOB.hhmysteryRoomNumber = rand(1, SHORT_REAL_LIMIT)
+ info = {"
Research Logs
+ I might just be onto something here!
+ The strange space-warping properties of bluespace have been known about for awhile now, but I might be on the verge of discovering a new way of harnessing it.
+ It's too soon to say for sure, but this might be the start of something quite important!
+ I'll be sure to log any major future breakthroughs. This might be a lot more than I can manage on my own, perhaps I should hire that secretary after all...
+
Breakthrough!
+ I can't believe it, but I did it! Just when I was certain it couldn't be done, I made the final necessary breakthrough.
+ Exploiting the effects of space dilation caused by specific bluespace structures combined with a precise use of geometric calculus, I've discovered a way to correlate an infinite amount of space within a finite area!
+ While the potential applications are endless, I utilized it in quite a nifty way so far by designing a system that recursively constructs subspace rooms and spatially links them to any of the infinite infinitesimally distinct points on the spheres surface.
+ I call it: Hilbert's Hotel!
+
Goodbye
+ I can't take this anymore. I know what happens next, and the fear of what is coming leaves me unable to continue working.
+ Any fool in my field has heard the stories. It's not that I didn't believe them, it's just... I guess I underestimated the importance of my own research...
+ Robert has reported a further increase in frequency of the strange, prying visitors who ask questions they have no business asking. I've requested him to keep everything on strict lockdown and have permanently dismissed all other assistants.
+ I've also instructed him to use the encryption method we discussed for any important quantitative data. The poor lad... I don't think he truly understands what he's gotten himself into...
+ It's clear what happens now. One day they'll show up uninvited, and claim my research as their own, leaving me as nothing more than a bullet ridden corpse floating in space.
+ I can't stick around to the let that happen.
+ I'm escaping into the very thing that brought all this trouble to my doorstep in the first place - my hotel.
+ I'll be in
[uppertext(num2hex(GLOB.hhmysteryRoomNumber, 0))] (That will make sense to anyone who should know)
+ I'm sorry that I must go like this. Maybe one day things will be different and it will be safe to return... maybe...
+ Goodbye
+
+
Doctor Hilbert"}
+
+/obj/item/paper/crumpled/robertsworkjournal
+ name = "Work Journal"
+ info = {"
First Week!
+ First week on the new job. It's a secretarial position, but hey, whatever pays the bills. Plus it seems like some interesting stuff goes on here.
+ Doc says its best that I don't openly talk about his research with others, I guess he doesn't want it getting out or something. I've caught myself slipping a few times when talking to others, it's hard not to brag about something this cool!
+ I'm not really sure why I'm choosing to journal this. Doc seems to log everything. He says it's incase he discovers anything important.
+ I guess that's why I'm doing it too, I've always wanted to be a part of something important.
+ Here's to a new job and to becoming a part of something important!
+
Weird times...
+ Things are starting to get a little strange around here. Just weeks after Doc's amazing breakthrough, weird visitors have began showing up unannounced, asking strange things about Doc's work.
+ I knew Doc wasn't a big fan of company, but even he seemed strangely unnerved when I told him about the visitors.
+ He said it's important that from here on out we keep tight security on everything, even other staff members.
+ He also said something about securing data, something about hexes. What's that mean? Some sort of curse? Doc never struck me as the magic type...
+ He often uses a lot of big sciencey words that I don't really understand, but I kinda dig it, it makes me feel like I'm witnessing something big.
+ I hope things go back to normal soon, but I guess that's the price you pay for being a part of something important.
+
Last day I guess?
+ Things are officially starting to get too strange for me.
+ The visitors have been coming a lot more often, and they all seem increasingly aggressive and nosey. I'm starting to see why they made Doc so nervous, they're certainly starting to creep me out too.
+ Awhile ago Doc started having me keep the place on strict lockdown and requested I refuse entry to anyone else, including previous staff.
+ But the weirdest part?
+ I haven't seen Doc in days. It's not unusual for him to work continuously for long periods of time in the lab, but when I took a peak in their yesterday - he was nowhere to be seen! I didn't risk prying much further, Doc had a habit of leaving the defense systems on these last few weeks.
+ I'm thinking it might be time to call it quits. Can't work much without a boss, plus things are starting to get kind of shady. I wanted to be a part of something important, but you gotta know when to play it safe.
+ As my dad always said, "The smart get famous, but the wise survive..."
+
+
Robert P."}
+
+/obj/item/paper/crumpled/bloody/docsdeathnote
+ name = "note"
+ info = {"This is it isn't it?
+ No one's coming to help, that much has become clear.
+ Sure, it's lonely, but do I have much choice? At least I brought the analyzer with me, they shouldn't be able to find me without it.
+ Who knows who's waiting for me out there. Its either die out there in their hands, or die a slower, slightly more comfortable death in here.
+ Everyday I can feel myself slipping away more and more, both physically and mentally. Who knows what happens now...
+ Heh, so it's true then, this must be the inescapable path of all great minds... so be it then.
+
+
+
+
Choose a room, and enter the sphere
+ Lay your head to rest, it soon becomes clear
+ There's always more room around every bend
+ Not all that's countable has an end..."}
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index dd2d7483e3..121ee2e07f 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -290,7 +290,7 @@ All ShuttleMove procs go here
// ignores the movement of the shuttle from the staging area on CentCom to
// the station as it is loaded in.
if (oldT && !is_centcom_level(oldT.z))
- GET_COMPONENT(STR, /datum/component/storage/concrete/emergency)
+ var/datum/component/storage/concrete/emergency/STR = GetComponent(/datum/component/storage/concrete/emergency)
STR?.unlock_me()
/************************************Mob move procs************************************/
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index 2249f5f10e..32c38451c5 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -24,7 +24,8 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/effect/portal,
/obj/item/shared_storage,
/obj/structure/extraction_point,
- /obj/machinery/syndicatebomb
+ /obj/machinery/syndicatebomb,
+ /obj/item/hilbertshotel
)))
/obj/docking_port/mobile/supply
diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm
index bb3cc1f7e3..0c0b20f0fc 100644
--- a/code/modules/spells/spell_types/construct_spells.dm
+++ b/code/modules/spells/spell_types/construct_spells.dm
@@ -146,7 +146,7 @@
clothes_req = 0
invocation = "none"
invocation_type = "none"
- proj_type = /obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
+ proj_type = "/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser"
proj_lifespan = 10
max_targets = 6
action_icon_state = "magicm"
diff --git a/code/modules/spells/spell_types/shapeshift.dm b/code/modules/spells/spell_types/shapeshift.dm
index 1576c55326..46eb14013f 100644
--- a/code/modules/spells/spell_types/shapeshift.dm
+++ b/code/modules/spells/spell_types/shapeshift.dm
@@ -13,7 +13,7 @@
var/revert_on_death = TRUE
var/die_with_shapeshifted_form = TRUE
- var/convert_damage = FALSE //If you want to convert the caster's health to the shift, and vice versa.
+ var/convert_damage = TRUE //If you want to convert the caster's health to the shift, and vice versa.
var/convert_damage_type = BRUTE //Since simplemobs don't have advanced damagetypes, what to convert damage back into.
var/shapeshift_type
var/list/possible_shapes = list(/mob/living/simple_animal/mouse,\
@@ -101,8 +101,10 @@
stored.forceMove(src)
stored.notransform = TRUE
if(source.convert_damage)
- var/damapply = (stored.maxHealth - (stored.health + stored.maxHealth)/2) //Carbons go from -100 to 100 naturally, while simplemobs only go from 0 to 100. Can't do a direct conversion.
- shape.apply_damage(damapply, source.convert_damage_type)
+ var/damage_percent = (stored.maxHealth - stored.health)/stored.maxHealth;
+ var/damapply = damage_percent * shape.maxHealth;
+
+ shape.apply_damage(damapply, source.convert_damage_type, forced = TRUE);
slink = soullink(/datum/soullink/shapeshift, stored , shape)
slink.source = src
@@ -152,8 +154,10 @@
stored.death()
else if(source.convert_damage)
stored.revive(full_heal = TRUE)
- var/damapply = (shape.maxHealth - 2*shape.health) //Since we halved incoming damage, double outgoing.
- stored.apply_damage(damapply, source.convert_damage_type)
+ var/damage_percent = (shape.maxHealth - shape.health)/shape.maxHealth;
+ var/damapply = stored.maxHealth * damage_percent
+
+ stored.apply_damage(damapply, source.convert_damage_type, forced = TRUE)
qdel(shape)
qdel(src)
diff --git a/code/modules/spells/spell_types/summonitem.dm b/code/modules/spells/spell_types/summonitem.dm
index 6d46c53a9d..7d9823e29b 100644
--- a/code/modules/spells/spell_types/summonitem.dm
+++ b/code/modules/spells/spell_types/summonitem.dm
@@ -61,6 +61,10 @@
organ.Remove(organ.owner)
else
while(!isturf(item_to_retrieve.loc) && infinite_recursion < 10) //if it's in something you get the whole thing.
+ if(isitem(item_to_retrieve.loc))
+ var/obj/item/I = item_to_retrieve.loc
+ if(I.item_flags & ABSTRACT) //Being able to summon abstract things because your item happened to get placed there is a no-no
+ break
if(ismob(item_to_retrieve.loc)) //If its on someone, properly drop it
var/mob/M = item_to_retrieve.loc
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index dffb7bf355..b46be627fb 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -768,6 +768,8 @@
px_y = 12
stam_heal_tick = 2
max_stamina_damage = 50
+ var/blood_state = BLOOD_STATE_NOT_BLOODY
+ var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
/obj/item/bodypart/l_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
@@ -828,6 +830,8 @@
px_y = 12
max_stamina_damage = 50
stam_heal_tick = 2
+ var/blood_state = BLOOD_STATE_NOT_BLOODY
+ var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
/obj/item/bodypart/r_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index 1b8f2c25f6..d520fbb917 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -49,6 +49,27 @@
+/mob/proc/has_left_leg()
+ return TRUE
+
+/mob/living/carbon/has_left_leg()
+ var/obj/item/bodypart/l_leg = get_bodypart(BODY_ZONE_L_LEG)
+ if(l_leg)
+ return TRUE
+ else
+ return FALSE
+
+/mob/proc/has_right_leg()
+ return TRUE
+
+/mob/living/carbon/has_right_leg()
+ var/obj/item/bodypart/r_leg = get_bodypart(BODY_ZONE_R_LEG)
+ if(r_leg)
+ return TRUE
+ else
+ return FALSE
+
+
//Limb numbers
/mob/proc/get_num_arms(check_disabled = TRUE)
return 2
diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm
index 8e4caab436..82fbf932e9 100644
--- a/code/modules/surgery/organs/heart.dm
+++ b/code/modules/surgery/organs/heart.dm
@@ -57,7 +57,7 @@
/obj/item/organ/heart/prepare_eat()
var/obj/S = ..()
- S.icon_state = "heart-off"
+ S.icon_state = "[icon_base]-off"
return S
/obj/item/organ/heart/on_life()
@@ -90,6 +90,12 @@
owner.set_heartattack(TRUE)
failed = TRUE
+obj/item/organ/heart/slime
+ name = "slime heart"
+ desc = "It seems we've gotten to the slimy core of the matter."
+ icon_state = "heart-s-on"
+ icon_base = "heart-s"
+
/obj/item/organ/heart/cursed
name = "cursed heart"
desc = "A heart that, when inserted, will force you to pump it manually."
@@ -212,6 +218,19 @@ obj/item/organ/heart/cybernetic/upgraded/on_life()
+/obj/item/organ/heart/ipc
+ name = "IPC heart"
+ desc = "An electronic pump that regulates hydraulic functions, they have an auto-restart after EMPs."
+ icon_state = "heart-c"
+ organ_flags = ORGAN_SYNTHETIC
+
+/obj/item/organ/heart/ipc/emp_act()
+ . = ..()
+ if(. & EMP_PROTECT_SELF)
+ return
+ Stop()
+ addtimer(CALLBACK(src, .proc/Restart), 10)
+
/obj/item/organ/heart/freedom
name = "heart of freedom"
desc = "This heart pumps with the passion to give... something freedom."
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 009cfce0a5..a555010567 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -917,7 +917,7 @@
speaktrigger += "[(H.client?.prefs.lewdchem?"You are my whole world and all of my being belongs to you, ":"I cannot think of anything else but aiding your cause, ")] "//Redflags!!
//mood
- GET_COMPONENT_FROM(mood, /datum/component/mood, H)
+ var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
switch(mood.sanity)
if(SANITY_GREAT to INFINITY)
speaktrigger += "I'm beyond elated!! " //did you mean byond elated? hohoho
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 8da5d7c113..642052026b 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -2,6 +2,7 @@
//Keep this sorted alphabetically
#ifdef UNIT_TESTS
+#include "component_tests.dm"
#include "reagent_id_typos.dm"
#include "reagent_recipe_collisions.dm"
#include "spawn_humans.dm"
diff --git a/code/modules/unit_tests/component_tests.dm b/code/modules/unit_tests/component_tests.dm
new file mode 100644
index 0000000000..409d7f4322
--- /dev/null
+++ b/code/modules/unit_tests/component_tests.dm
@@ -0,0 +1,12 @@
+/datum/unit_test/component_duping/Run()
+ var/list/bad_dms = list()
+ var/list/bad_dts = list()
+ for(var/t in typesof(/datum/component))
+ var/datum/component/comp = t
+ if(!isnum(initial(comp.dupe_mode)))
+ bad_dms += t
+ var/dupe_type = initial(comp.dupe_type)
+ if(dupe_type && !ispath(dupe_type))
+ bad_dts += t
+ if(length(bad_dms) || length(bad_dts))
+ Fail("Components with invalid dupe modes: ([bad_dms.Join(",")]) ||| Components with invalid dupe types: ([bad_dts.Join(",")])")
\ No newline at end of file
diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm
index b008682745..5c47a2d342 100644
--- a/code/modules/uplink/uplink_devices.dm
+++ b/code/modules/uplink/uplink_devices.dm
@@ -25,18 +25,18 @@
/obj/item/uplink/nuclear/Initialize()
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/uplink/nuclear_restricted/Initialize()
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.allow_restricted = FALSE
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/uplink/clownop/Initialize()
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear/clown_ops)
/obj/item/uplink/old
@@ -45,7 +45,7 @@
/obj/item/uplink/old/Initialize(mapload, owner, tc_amount = 10)
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.name = "dusty radio"
// Multitool uplink
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 61af0eaf78..cbdf936dfc 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1711,12 +1711,20 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
restricted_roles = list("Research Director", "Scientist")
+/datum/uplink_item/role_restricted/alientech
+ name = "Alien Research Disk"
+ desc = "A technology disk holding a terabyte of highly confidential abductor technology. \
+ Simply insert into research console of choice and import the files from the disk. You might research some useful gear from this."
+ item = /obj/item/disk/tech_disk/abductor
+ cost = 12
+ restricted_roles = list("Research Director", "Scientist", "Roboticist")
+
/datum/uplink_item/role_restricted/brainwash_disk
name = "Brainwashing Surgery Program"
desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
Insert into an Operating Console to enable the procedure."
item = /obj/item/disk/surgery/brainwashing
- restricted_roles = list("Medical Doctor")
+ restricted_roles = list("Medical Doctor", "Roboticist")
cost = 3
/datum/uplink_item/role_restricted/clown_bomb
diff --git a/config/game_options.txt b/config/game_options.txt
index 02d620eb31..ca58e58a5b 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -255,6 +255,141 @@ EVENTS_MIN_TIME_MUL 1
EVENTS_MIN_PLAYERS_MUL 1
+
+### DYNAMIC MODE ###
+
+## How many roundstart players required for high population override to take effect.
+DYNAMIC_HIGH_POP_LIMIT 55
+
+## Pop range per requirement.
+## If the value is five the range is:
+## 0-4, 5-9, 10-14, 15-19, 20-24, 25-29, 30-34, 35-39, 40-54, 45+
+## If it is six the range is:
+## 0-5, 6-11, 12-17, 18-23, 24-29, 30-35, 36-41, 42-47, 48-53, 54+
+## If it is seven the range is:
+## 0-6, 7-13, 14-20, 21-27, 28-34, 35-41, 42-48, 49-55, 56-62, 63+
+## Options outside this range can be used, of course.
+DYNAMIC_POP_PER_REQUIREMENT 6
+
+## 1 -> 9, probability for this rule to be picked against other rules.
+## Note that requirements must also be met, and some requirements are impossible to meet.
+DYNAMIC_WEIGHT TRAITOR 5
+DYNAMIC_WEIGHT TRAITORBRO 4
+DYNAMIC_WEIGHT CHANGELING 3
+DYNAMIC_WEIGHT WIZARD 1
+DYNAMIC_WEIGHT CULT 3
+DYNAMIC_WEIGHT NUCLEAR 3
+DYNAMIC_WEIGHT REVOLUTION 2
+# All below are impossible-by-default
+DYNAMIC_WEIGHT EXTENDED 3
+DYNAMIC_WEIGHT CLOCKWORK_CULT 3
+DYNAMIC_WEIGHT CLOWNOPS 3
+DYNAMIC_WEIGHT DEVIL 3
+DYNAMIC_WEIGHT MONKEY 3
+DYNAMIC_WEIGHT METEOR 3
+
+## Midround antags
+DYNAMIC_WEIGHT MIDROUND_TRAITOR 7
+DYNAMIC_WEIGHT MALF_AI 3
+DYNAMIC_WEIGHT MIDROUND_WIZARD 1
+DYNAMIC_WEIGHT MIDROUND_NUCLEAR 5
+DYNAMIC_WEIGHT BLOB 4
+DYNAMIC_WEIGHT XENOS 3
+DYNAMIC_WEIGHT NIGHTMARE 3
+
+## Latejoin antags
+DYNAMIC_WEIGHT LATEJOIN_TRAITOR 7
+DYNAMIC_WEIGHT LATEJOIN_REVOLUTION 2
+
+## Threat cost. This is decreased from the mode's threat when the rule is executed.
+DYNAMIC_COST TRAITOR 10
+DYNAMIC_COST TRAITORBRO 10
+DYNAMIC_COST CHANGELING 30
+DYNAMIC_COST WIZARD 30
+DYNAMIC_COST CULT 30
+DYNAMIC_COST NUCLEAR 40
+DYNAMIC_COST REVOLUTION 35
+# All below are impossible-by-default
+DYNAMIC_COST EXTENDED 0
+DYNAMIC_COST CLOCKWORK_CULT 0
+DYNAMIC_COST CLOWNOPS 40
+DYNAMIC_COST DEVIL 0
+DYNAMIC_COST MONKEY 0
+DYNAMIC_COST METEOR 0
+
+## Midround antags
+DYNAMIC_COST MIDROUND_TRAITOR 10
+DYNAMIC_COST MALF_AI 35
+DYNAMIC_COST MIDROUND_WIZARD 20
+DYNAMIC_COST MIDROUND_NUCLEAR 35
+DYNAMIC_COST BLOB 10
+DYNAMIC_COST XENOS 10
+DYNAMIC_COST NIGHTMARE 10
+
+## Latejoin antags
+DYNAMIC_COST LATEJOIN_TRAITOR 5
+DYNAMIC_COST LATEJOIN_REVOLUTION 20
+
+## Rule will not be generated with threat levels below requirement at a pop value. Pop values are determined by dynamic's pop-per-requirement.
+## By default it's 0-5, 6-11, 12-17, 18-23, 24-29, 30-35, 36-41, 42-47, 48-53, 54+.
+## This means that 40 30 30 20 20 20 15 15 15 10 will not generate below 40 at 0-5, 30 at 6-11 etc.
+DYNAMIC_REQUIREMENTS TRAITOR 10 10 10 10 10 10 10 10 10 10
+DYNAMIC_REQUIREMENTS TRAITORBRO 40 30 30 20 20 15 15 15 10 10
+DYNAMIC_REQUIREMENTS CHANGELING 80 70 60 50 40 20 20 10 10 10
+DYNAMIC_REQUIREMENTS WIZARD 90 90 70 40 30 20 10 10 10 10
+DYNAMIC_REQUIREMENTS CULT 100 90 80 60 40 30 10 10 10 10
+DYNAMIC_REQUIREMENTS NUCLEAR 90 90 90 80 60 40 30 20 10 10
+DYNAMIC_REQUIREMENTS REVOLUTION 101 101 70 40 30 20 10 10 10 10
+# All below are impossible-by-default
+DYNAMIC_REQUIREMENTS EXTENDED 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS CLOCKWORK_CULT 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS CLOWNOPS 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS DEVIL 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS MONKEY 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS METEOR 101 101 101 101 101 101 101 101 101 101
+
+## Midround antags
+DYNAMIC_REQUIREMENTS MIDROUND_TRAITOR 50 40 30 20 10 10 10 10 10 10
+DYNAMIC_REQUIREMENTS MALF_AI 101 101 80 70 60 60 50 50 40 40
+DYNAMIC_REQUIREMENTS MIDROUND_WIZARD 90 90 70 40 30 20 10 10 10 10
+DYNAMIC_REQUIREMENTS MIDROUND_NUCLEAR 90 90 90 80 60 40 30 20 10 10
+DYNAMIC_REQUIREMENTS BLOB 101 101 101 80 60 50 30 20 10 10
+DYNAMIC_REQUIREMENTS XENOS 101 101 101 70 50 40 20 15 10 10
+DYNAMIC_REQUIREMENTS NIGHTMARE 101 101 101 70 50 40 20 15 10 10
+
+## Latejoin antags
+DYNAMIC_REQUIREMENTS LATEJOIN_TRAITOR 40 30 20 10 10 10 10 10 10 10
+DYNAMIC_REQUIREMENTS LATEJOIN_REVOLUTION 101 101 70 40 30 20 20 20 20 20
+
+## An alternative, static requirement used instead when pop is over mode's high_pop_limit.
+DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITOR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITORBRO 15
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CHANGELING 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT WIZARD 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CULT 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT NUCLEAR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT REVOLUTION 10
+# All below are impossible-by-default
+DYNAMIC_HIGH_POPULATION_REQUIREMENT EXTENDED 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CLOCKWORK_CULT 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CLOWNOPS 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT DEVIL 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MONKEY 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT METEOR 101
+
+## Midround antags
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_TRAITOR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MALF_AI 35
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_WIZARD 50
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_NUCLEAR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT BLOB 50
+DYNAMIC_HIGH_POPULATION_REQUIREMENT XENOS 50
+DYNAMIC_HIGH_POPULATION_REQUIREMENT NIGHTMARE 50
+
+## Latejoin antags
+DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_TRAITOR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_REVOLUTION 50
+
## AI ###
## Allow the AI job to be picked.
diff --git a/config/spaceRuinBlacklist.txt b/config/spaceRuinBlacklist.txt
index deafa47969..4ea7611937 100644
--- a/config/spaceRuinBlacklist.txt
+++ b/config/spaceRuinBlacklist.txt
@@ -27,6 +27,7 @@
#_maps/RandomRuins/SpaceRuins/emptyshell.dmm
#_maps/RandomRuins/SpaceRuins/gasthelizards.dmm
#_maps/RandomRuins/SpaceRuins/gondolaasteroid.dmm
+#_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm
#_maps/RandomRuins/SpaceRuins/intactemptyship.dmm
#_maps/RandomRuins/SpaceRuins/listeningstation.dmm
#_maps/RandomRuins/SpaceRuins/mechtransport.dmm
diff --git a/html/changelogs/AutoChangeLog-pr-8654.yml b/html/changelogs/AutoChangeLog-pr-8654.yml
new file mode 100644
index 0000000000..336e55134d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8654.yml
@@ -0,0 +1,5 @@
+author: "Ghommie (Original PR by Dreamweaver)"
+delete-after: True
+changes:
+ - rscadd: "Nanotrasen has received word of a high-tech research facility that may contain advancements in bluespace-based research. Any crew members who become aware of its whereabouts are to report it to CentCom immediately and are restricted from sharing said info."
+ - refactor: "The turf reservation system now dynamically creates new z levels if the current reserved levels are full."
diff --git a/html/changelogs/AutoChangeLog-pr-9047.yml b/html/changelogs/AutoChangeLog-pr-9047.yml
new file mode 100644
index 0000000000..1f024b71e3
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9047.yml
@@ -0,0 +1,7 @@
+author: "Poojawa"
+delete-after: True
+changes:
+ - rscadd: "Added RGB blood effects, know whose blood this is by color!"
+ - rscadd: "Added Synthetics blood, and a machine that produces it. A universal donor for medical to heal people with. Make it via medical protolathe!"
+ - bugfix: "With hearts, slimepeople shouldn't die from the effects of not having a heart."
+ - bugfix: "Plasma vessels from xenomorphs will restore blood if you're on resin."
diff --git a/html/changelogs/AutoChangeLog-pr-9535.yml b/html/changelogs/AutoChangeLog-pr-9535.yml
new file mode 100644
index 0000000000..fbebfe5a54
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9535.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Gorlex Marauders are pleased to announce non-slip grooves were given to their .50 sniper rifles, and thus shouldn't accidentally flop on the floor like pocket spaghettis whenever taken out of a bag anymore."
diff --git a/html/changelogs/AutoChangeLog-pr-9542.yml b/html/changelogs/AutoChangeLog-pr-9542.yml
new file mode 100644
index 0000000000..2ba9d14986
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9542.yml
@@ -0,0 +1,5 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - tweak: "Costs of crates and paperwork"
+ - rscadd: "Adds 2 more crates hacked only"
diff --git a/html/changelogs/AutoChangeLog-pr-9548.yml b/html/changelogs/AutoChangeLog-pr-9548.yml
new file mode 100644
index 0000000000..f387875a4c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9548.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed custom say emotes conflict with drunk memes."
diff --git a/html/changelogs/AutoChangeLog-pr-9549.yml b/html/changelogs/AutoChangeLog-pr-9549.yml
new file mode 100644
index 0000000000..6958e8c390
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9549.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixes identity transfer (envy knife, changeling transformation, making a vr avatar) not copying digitigrade legs."
diff --git a/html/changelogs/AutoChangeLog-pr-9550.yml b/html/changelogs/AutoChangeLog-pr-9550.yml
new file mode 100644
index 0000000000..8a50be40f6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9550.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixes temporary transformation sting triggering heart attacks on heartless humans."
diff --git a/html/changelogs/AutoChangeLog-pr-9564.yml b/html/changelogs/AutoChangeLog-pr-9564.yml
new file mode 100644
index 0000000000..deb7601e82
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9564.yml
@@ -0,0 +1,6 @@
+author: "tinfoil hat wearer"
+delete-after: True
+changes:
+ - rscadd: "Added a new alien technology disk to scientist and roboticist uplinks that allows them to research the heavily-guarded secrets of the Grays."
+ - tweak: "Alientech is now the only Hidden alien research. To compensate for this, alien_bio and alien_engi have had their research costs doubled and now require advanced surgery tools and experimental tools respectively to research. Their export price is also halved."
+ - balance: "roboticists now have brainwashing disks AND alien technology added to their role-restricted uplink section. alien technology gives them brainwashing at a much later date, so brainwashing is the much cheaper option for instant power. makes logical sense because doctors get it as well because they do surgery, and roboticists can now either choose to brainwash people for less price but less power or emag borgs for higher prices, limited uses, but higher power."
diff --git a/html/changelogs/AutoChangeLog-pr-9568.yml b/html/changelogs/AutoChangeLog-pr-9568.yml
new file mode 100644
index 0000000000..c5e65f7adc
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9568.yml
@@ -0,0 +1,4 @@
+author: "r4d6"
+delete-after: True
+changes:
+ - bugfix: "Batteries are now Rad-Proof like the other stock parts"
diff --git a/html/changelogs/AutoChangeLog-pr-9579.yml b/html/changelogs/AutoChangeLog-pr-9579.yml
new file mode 100644
index 0000000000..df1a2c90bf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9579.yml
@@ -0,0 +1,8 @@
+author: "4dplanner, MMiracles"
+delete-after: True
+changes:
+ - tweak: "Wizard shapeshift now converts damage taken while transformed"
+ - bugfix: "transform spell transfers damage correctly instead of healing most of the time"
+ - bugfix: "0% simplemob health maps to 0 carbon health, 100% simplemob to 100% carbon"
+ - bugfix: "transforming to a form with brute resistance no longer heals you"
+ - bugfix: "transforming back to a species with brute resistance no longer heals you"
diff --git a/html/changelogs/AutoChangeLog-pr-9582.yml b/html/changelogs/AutoChangeLog-pr-9582.yml
new file mode 100644
index 0000000000..7fde7388cd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9582.yml
@@ -0,0 +1,5 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - rscadd: "Added configs for a bunch of Dynamic rule parameters."
+ - config: "Added defaults for all the configs (WIP)."
diff --git a/html/changelogs/AutoChangeLog-pr-9585.yml b/html/changelogs/AutoChangeLog-pr-9585.yml
new file mode 100644
index 0000000000..c74c0dec46
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9585.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed artificier lesser magic missile."
diff --git a/html/changelogs/AutoChangeLog-pr-9587.yml b/html/changelogs/AutoChangeLog-pr-9587.yml
new file mode 100644
index 0000000000..0eba144de5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9587.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Phantom thief masks will now fancy your combat mode yet again."
diff --git a/html/changelogs/AutoChangeLog-pr-9588.yml b/html/changelogs/AutoChangeLog-pr-9588.yml
new file mode 100644
index 0000000000..03f4ab8a57
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9588.yml
@@ -0,0 +1,5 @@
+author: "ItzGabby"
+delete-after: True
+changes:
+ - rscadd: "Bat Species parts for more leeway for character customization."
+ - code_imp: "Alphabetized decor wing selection window in character creator for simplicity."
diff --git a/html/changelogs/AutoChangeLog-pr-9589.yml b/html/changelogs/AutoChangeLog-pr-9589.yml
new file mode 100644
index 0000000000..5fbc819844
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9589.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PRs by ninjanomnom and nemvar)"
+delete-after: True
+changes:
+ - bugfix: "Trays now scatter their contents when used for attacks, like they are supposed to."
diff --git a/html/changelogs/AutoChangeLog-pr-9593.yml b/html/changelogs/AutoChangeLog-pr-9593.yml
new file mode 100644
index 0000000000..a61fcea1e4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9593.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed gulag teleporter stripping the user of stuff it really shouldn't (like storage implant bags)."
diff --git a/html/changelogs/AutoChangeLog-pr-9594.yml b/html/changelogs/AutoChangeLog-pr-9594.yml
new file mode 100644
index 0000000000..83774989ee
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9594.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - tweak: "literally every pistol subtype fits in shoes now. go wild."
diff --git a/html/changelogs/AutoChangeLog-pr-9595.yml b/html/changelogs/AutoChangeLog-pr-9595.yml
new file mode 100644
index 0000000000..bc3eab54c8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9595.yml
@@ -0,0 +1,4 @@
+author: "deathride58"
+delete-after: True
+changes:
+ - bugfix: "Examining a spaceman, and other things that use get_examine_string(), will now actually properly show when an item is blood-stained."
diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi
index 6a1a35f326..5bc30f886c 100644
Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ
diff --git a/icons/effects/fluidtracks.dmi b/icons/effects/fluidtracks.dmi
new file mode 100644
index 0000000000..e2f0c97479
Binary files /dev/null and b/icons/effects/fluidtracks.dmi differ
diff --git a/icons/effects/footprints.dmi b/icons/effects/footprints.dmi
index a98344abe4..69207097c0 100644
Binary files a/icons/effects/footprints.dmi and b/icons/effects/footprints.dmi differ
diff --git a/icons/mob/AI.dmi b/icons/mob/AI.dmi
index 7de8152118..bdf54e36e5 100644
Binary files a/icons/mob/AI.dmi and b/icons/mob/AI.dmi differ
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
index 4e23c102ce..e6e0abe111 100644
Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ
diff --git a/icons/mob/dam_mob.dmi b/icons/mob/dam_mob.dmi
index fe92746b43..c34b57b434 100644
Binary files a/icons/mob/dam_mob.dmi and b/icons/mob/dam_mob.dmi differ
diff --git a/icons/obj/bloodbank.dmi b/icons/obj/bloodbank.dmi
new file mode 100644
index 0000000000..4b4b2b6990
Binary files /dev/null and b/icons/obj/bloodbank.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 032b0c27ad..08b605a1d6 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 6336669501..416b0ef58b 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index bdfbae3d75..fcc28de7b9 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index 01cb909d27..992b37cc3d 100644
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/icons/turf/space.dmi b/icons/turf/space.dmi
index d32279e704..33e3fab9a4 100644
Binary files a/icons/turf/space.dmi and b/icons/turf/space.dmi differ
diff --git a/icons/turf/walls.dmi b/icons/turf/walls.dmi
index 3290e3f92c..dd6c7f3a7c 100644
Binary files a/icons/turf/walls.dmi and b/icons/turf/walls.dmi differ
diff --git a/modular_citadel/code/datums/components/phantomthief.dm b/modular_citadel/code/datums/components/phantomthief.dm
deleted file mode 100644
index d34e16f6e9..0000000000
--- a/modular_citadel/code/datums/components/phantomthief.dm
+++ /dev/null
@@ -1,49 +0,0 @@
-//This component applies a customizable drop_shadow filter to its wearer when they toggle combat mode on or off. This can stack.
-
-/datum/component/phantomthief
- dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
-
- var/filter_x
- var/filter_y
- var/filter_size
- var/filter_border
- var/filter_color
-
- var/datum/component/redirect/combattoggle_redir
-
-/datum/component/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111")
- filter_x = _x
- filter_y = _y
- filter_size = _size
- filter_border = _border
- filter_color = _color
-
- RegisterSignal(parent, COMSIG_COMBAT_TOGGLED, .proc/handlefilterstuff)
- RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/OnEquipped)
- RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/OnDropped)
-
-/datum/component/phantomthief/proc/handlefilterstuff(mob/user, combatmodestate)
- if(istype(user))
- var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
- if(!combatmodestate)
- user.filters -= thefilter
- else
- user.filters += thefilter
-
-/datum/component/phantomthief/proc/stripdesiredfilter(mob/user)
- if(istype(user))
- var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
- user.filters -= thefilter
-
-/datum/component/phantomthief/proc/OnEquipped(mob/user, slot)
- if(!istype(user))
- return
- if(!combattoggle_redir)
- combattoggle_redir = user.AddComponent(/datum/component/redirect, list(COMSIG_COMBAT_TOGGLED = CALLBACK(src, .proc/handlefilterstuff)))
-
-/datum/component/phantomthief/proc/OnDropped(mob/user)
- if(!istype(user))
- return
- if(combattoggle_redir)
- QDEL_NULL(combattoggle_redir)
- stripdesiredfilter(user)
diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm
index 9b37f7291d..4c01725120 100644
--- a/modular_citadel/code/datums/status_effects/chems.dm
+++ b/modular_citadel/code/datums/status_effects/chems.dm
@@ -198,7 +198,6 @@
var/enthrallGender //Use master or mistress
var/mental_capacity //Higher it is, lower the cooldown on commands, capacity reduces with resistance.
- var/datum/weakref/redirect_component //resistance
var/distancelist = list(2,1.5,1,0.8,0.6,0.5,0.4,0.3,0.2) //Distance multipliers
@@ -228,7 +227,7 @@
master = get_mob_by_key(enthrallID)
//if(M.ckey == enthrallID)
// owner.remove_status_effect(src)//At the moment, a user can enthrall themselves, toggle this back in if that should be removed.
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist)))) //Do resistance calc if resist is pressed#
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/owner_resist) //Do resistance calc if resist is pressed#
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/owner_hear)
mental_capacity = 500 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain!
var/mob/living/carbon/human/H = owner
@@ -566,8 +565,7 @@
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "EnthMissing2")
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "EnthMissing3")
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "EnthMissing4")
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(M, COMSIG_LIVING_RESIST)
UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
REMOVE_TRAIT(owner, TRAIT_PACIFISM, "MKUltra")
to_chat(owner, "You're now free of [master]'s influence, and fully independent!'")
diff --git a/modular_citadel/code/game/machinery/toylathe.dm b/modular_citadel/code/game/machinery/toylathe.dm
index 78b5fdea88..571cdfc82a 100644
--- a/modular_citadel/code/game/machinery/toylathe.dm
+++ b/modular_citadel/code/game/machinery/toylathe.dm
@@ -80,7 +80,7 @@
popup.open()
/obj/machinery/autoylathe/on_deconstruction()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
/obj/machinery/autoylathe/attackby(obj/item/O, mob/user, params)
@@ -166,7 +166,7 @@
var/plastic_cost = being_built.materials[MAT_PLASTIC]
var/power = max(2000, (metal_cost+glass_cost+plastic_cost)*multiplier/5)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff) && (materials.amount(MAT_PLASTIC) >= plastic_cost*multiplier*coeff))
busy = TRUE
use_power(power)
@@ -190,7 +190,7 @@
return
/obj/machinery/autoylathe/proc/make_item(power, metal_cost, glass_cost, plastic_cost, multiplier, coeff, is_stack)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier, MAT_PLASTIC=plastic_cost*coeff*multiplier)
@@ -215,7 +215,7 @@
var/T = 0
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
T += MB.rating*75000
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
@@ -264,7 +264,7 @@
dat += "[D.name]"
if(ispath(D.build_path, /obj/item/stack))
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS] ?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY,D.materials[MAT_PLASTIC] ?round(materials.amount(MAT_PLASTIC)/D.materials[MAT_PLASTIC]):INFINITY)
if (max_multiplier>10 && !disabled)
dat += " x10"
@@ -296,7 +296,7 @@
dat += "[D.name]"
if(ispath(D.build_path, /obj/item/stack))
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS] ?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY,D.materials[MAT_PLASTIC] ?round(materials.amount(MAT_PLASTIC)/D.materials[MAT_PLASTIC]):INFINITY)
if (max_multiplier>10 && !disabled)
dat += " x10"
@@ -311,7 +311,7 @@
return dat
/obj/machinery/autoylathe/proc/materials_printout()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
"
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
@@ -324,7 +324,7 @@
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
return FALSE
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
diff --git a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
index e677c1f3ab..e7017b8481 100644
--- a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
+++ b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
@@ -307,7 +307,7 @@
var/mob/M = loc
M.update_inv_hands()
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)//blood overlays get weird otherwise, because the sprite changes. (retained from original desword because I have no idea what this is)
+ clean_blood()
/obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user)
if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
diff --git a/modular_citadel/code/game/objects/items/storage/firstaid.dm b/modular_citadel/code/game/objects/items/storage/firstaid.dm
index 125330a9b9..95c88ecc86 100755
--- a/modular_citadel/code/game/objects/items/storage/firstaid.dm
+++ b/modular_citadel/code/game/objects/items/storage/firstaid.dm
@@ -49,7 +49,7 @@
/obj/item/storage/hypospraykit/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 12
STR.can_hold = typecacheof(list(
/obj/item/hypospray/mkii,
@@ -151,7 +151,7 @@
/obj/item/storage/hypospraykit/cmo/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/hypospray/mkii,
diff --git a/modular_citadel/code/modules/clothing/glasses/phantomthief.dm b/modular_citadel/code/modules/clothing/glasses/phantomthief.dm
index 1b13ba5dc8..5e488b9837 100644
--- a/modular_citadel/code/modules/clothing/glasses/phantomthief.dm
+++ b/modular_citadel/code/modules/clothing/glasses/phantomthief.dm
@@ -6,30 +6,28 @@
icon_state = "s-ninja"
item_state = "s-ninja"
-/obj/item/clothing/glasses/phantomthief/Initialize()
+/obj/item/clothing/glasses/phantomthief/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/phantomthief)
+ AddComponent(/datum/component/wearertargeting/phantomthief)
/obj/item/clothing/glasses/phantomthief/syndicate
name = "suspicious plastic mask"
desc = "A cheap, bulky, Syndicate-branded plastic face mask. You have to break in to break out."
var/nextadrenalinepop
- var/datum/component/redirect/combattoggle_redir
-/obj/item/clothing/glasses/phantomthief/syndicate/examine(user)
+/obj/item/clothing/glasses/phantomthief/syndicate/examine(mob/user)
. = ..()
- if(combattoggle_redir)
+ if(user.get_item_by_slot(SLOT_GLASSES) == src)
if(world.time >= nextadrenalinepop)
to_chat(user, "The built-in adrenaline injector is ready for use.")
else
to_chat(user, "[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again.")
/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/user, combatmodestate)
- if(istype(user))
- if(combatmodestate && world.time >= nextadrenalinepop)
- nextadrenalinepop = world.time + 5 MINUTES
- user.reagents.add_reagent("syndicateadrenals", 5)
- user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
+ if(istype(user) && combatmodestate && world.time >= nextadrenalinepop)
+ nextadrenalinepop = world.time + 5 MINUTES
+ user.reagents.add_reagent("syndicateadrenals", 5)
+ user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
/obj/item/clothing/glasses/phantomthief/syndicate/equipped(mob/user, slot)
. = ..()
@@ -37,12 +35,10 @@
return
if(slot != SLOT_GLASSES)
return
- if(!combattoggle_redir)
- combattoggle_redir = user.AddComponent(/datum/component/redirect, list(COMSIG_COMBAT_TOGGLED = CALLBACK(src, .proc/injectadrenaline)))
+ RegisterSignal(user, COMSIG_COMBAT_TOGGLED, .proc/injectadrenaline)
/obj/item/clothing/glasses/phantomthief/syndicate/dropped(mob/user)
. = ..()
if(!istype(user))
return
- if(combattoggle_redir)
- QDEL_NULL(combattoggle_redir)
+ UnregisterSignal(user, COMSIG_COMBAT_TOGGLED)
diff --git a/modular_citadel/code/modules/mob/living/carbon/human/human.dm b/modular_citadel/code/modules/mob/living/carbon/human/human.dm
index e0d592827e..e5d386b56b 100644
--- a/modular_citadel/code/modules/mob/living/carbon/human/human.dm
+++ b/modular_citadel/code/modules/mob/living/carbon/human/human.dm
@@ -1,12 +1,3 @@
-/mob/living/carbon/human/species/mammal
- race = /datum/species/mammal
-
-/mob/living/carbon/human/species/insect
- race = /datum/species/insect
-
-/mob/living/carbon/human/species/xeno
- race = /datum/species/xeno
-
/mob/living/proc/resist_embedded()
return
diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
index de3f43f8ee..a458e909f3 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
@@ -143,7 +143,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/obj/item/storage/bag/borgdelivery/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.max_combined_w_class = 5
STR.max_items = 1
diff --git a/modular_citadel/code/modules/mob/mob.dm b/modular_citadel/code/modules/mob/mob.dm
index bf6987ab81..aa0e6b5828 100644
--- a/modular_citadel/code/modules/mob/mob.dm
+++ b/modular_citadel/code/modules/mob/mob.dm
@@ -3,9 +3,11 @@
/mob/say_mod(input, message_mode)
var/customsayverb = findtext(input, "*")
- if(customsayverb)
+ if(customsayverb && message_mode != MODE_WHISPER_CRIT)
+ message_mode = MODE_CUSTOM_SAY
return lowertext(copytext(input, 1, customsayverb))
- . = ..()
+ else
+ return ..()
/atom/movable/proc/attach_spans(input, list/spans)
var/customsayverb = findtext(input, "*")
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
index 4acfda0573..edb4bedfed 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
@@ -182,7 +182,7 @@
/datum/reagent/fermi/nanite_b_gone/on_mob_life(mob/living/carbon/C)
//var/component/nanites/N = M.GetComponent(/datum/component/nanites)
- GET_COMPONENT_FROM(N, /datum/component/nanites, C)
+ var/datum/component/nanites/N = C.GetComponent(/datum/component/nanites)
if(isnull(N))
return ..()
N.nanite_volume = -purity//0.5 seems to be the default to me, so it'll neuter them.
@@ -190,7 +190,7 @@
/datum/reagent/fermi/nanite_b_gone/overdose_process(mob/living/carbon/C)
//var/component/nanites/N = M.GetComponent(/datum/component/nanites)
- GET_COMPONENT_FROM(N, /datum/component/nanites, C)
+ var/datum/component/nanites/N = C.GetComponent(/datum/component/nanites)
if(prob(5))
to_chat(C, "The residual voltage from the nanites causes you to seize up!")
C.electrocute_act(10, (get_turf(C)), 1, FALSE, FALSE, FALSE, TRUE)
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 00063c22d4..c8ebde11d9 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1,11 +1,3 @@
-/datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume)
- if(istype(O, /obj/effect/decal/cleanable) || istype(O, /obj/item/projectile/bullet/reusable/foam_dart) || istype(O, /obj/item/ammo_casing/caseless/foam_dart))
- qdel(O)
- else
- if(O)
- O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
-
/datum/reagent/syndicateadrenals
name = "Syndicate Adrenaline"
id = "syndicateadrenals"
diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
index 47f71d1acf..7fcae0eb13 100644
--- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
@@ -327,10 +327,10 @@
//So slimes can play too.
/datum/chemical_reaction/fermi/enthrall/slime
- required_catalysts = list("slimejelly" = 1)
+ required_catalysts = list("jellyblood" = 1)
/datum/chemical_reaction/fermi/enthrall/slime/FermiFinish(datum/reagents/holder, var/atom/my_atom)
- var/datum/reagent/toxin/slimejelly/B = locate(/datum/reagent/toxin/slimejelly) in my_atom.reagents.reagent_list//The one line change.
+ var/datum/reagent/blood/jellyblood/B = locate(/datum/reagent/blood/jellyblood) in my_atom.reagents.reagent_list//The one line change.
var/datum/reagent/fermi/enthrall/E = locate(/datum/reagent/fermi/enthrall) in my_atom.reagents.reagent_list
if(!B.data)
var/list/seen = viewers(5, get_turf(my_atom))
diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
index 0e823a658f..df3922dc09 100644
--- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
+++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
@@ -2,7 +2,7 @@
/datum/reagent/consumable/semen
name = "Semen"
id = "semen"
- description = "Sperm from some animal. Useless for anything but insemination, really."
+ description = "Sperm from some animal. I bet you'll drink this out of a bucket someday."
taste_description = "something salty"
taste_mult = 2 //Not very overpowering flavor
data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null)
@@ -39,7 +39,9 @@
add_blood_DNA(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S)
- S.add_blood_DNA(return_blood_DNA())
+ if(S.blood_DNA)
+ blood_DNA |= S.blood_DNA.Copy()
+ ..()
/datum/reagent/consumable/femcum
name = "Female Ejaculate"
@@ -71,7 +73,8 @@
add_blood_DNA(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F)
- F.add_blood_DNA(return_blood_DNA())
+ if(F.blood_DNA)
+ blood_DNA |= F.blood_DNA.Copy()
..()
/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume)
diff --git a/modular_citadel/code/modules/vehicles/secway.dm b/modular_citadel/code/modules/vehicles/secway.dm
index 85c1de15e2..9320da6dc8 100644
--- a/modular_citadel/code/modules/vehicles/secway.dm
+++ b/modular_citadel/code/modules/vehicles/secway.dm
@@ -24,7 +24,7 @@
if(H.sprinting && charge)
charge--
new_speed = chargespeed
- GET_COMPONENT(D, /datum/component/riding)
+ var/datum/component/riding/D = GetComponent(/datum/component/riding)
D.vehicle_move_delay = new_speed
for(var/i in progressbars_by_rider)
var/datum/progressbar/B = progressbars_by_rider[i]
diff --git a/modular_citadel/icons/mob/64x32_effects.dmi b/modular_citadel/icons/mob/64x32_effects.dmi
index 7db65a8fc3..a11b3584a3 100644
Binary files a/modular_citadel/icons/mob/64x32_effects.dmi and b/modular_citadel/icons/mob/64x32_effects.dmi differ
diff --git a/modular_citadel/icons/mob/mam_ears.dmi b/modular_citadel/icons/mob/mam_ears.dmi
index a23716562e..fcc124c695 100644
Binary files a/modular_citadel/icons/mob/mam_ears.dmi and b/modular_citadel/icons/mob/mam_ears.dmi differ
diff --git a/modular_citadel/icons/mob/mam_markings.dmi b/modular_citadel/icons/mob/mam_markings.dmi
index dce56de556..d61baa4a51 100644
Binary files a/modular_citadel/icons/mob/mam_markings.dmi and b/modular_citadel/icons/mob/mam_markings.dmi differ
diff --git a/modular_citadel/icons/mob/mam_snouts.dmi b/modular_citadel/icons/mob/mam_snouts.dmi
index d2cb9b7286..d0f5d56314 100644
Binary files a/modular_citadel/icons/mob/mam_snouts.dmi and b/modular_citadel/icons/mob/mam_snouts.dmi differ
diff --git a/modular_citadel/icons/mob/mam_tails.dmi b/modular_citadel/icons/mob/mam_tails.dmi
index 5395e5c7c6..e4bd5119b6 100644
Binary files a/modular_citadel/icons/mob/mam_tails.dmi and b/modular_citadel/icons/mob/mam_tails.dmi differ
diff --git a/sound/ambience/servicebell.ogg b/sound/ambience/servicebell.ogg
new file mode 100644
index 0000000000..f55c7d5a75
Binary files /dev/null and b/sound/ambience/servicebell.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 702f34f80c..63b6bcfdb8 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -47,7 +47,6 @@
#include "code\__DEFINES\flags.dm"
#include "code\__DEFINES\food.dm"
#include "code\__DEFINES\footsteps.dm"
-#include "code\__DEFINES\forensics.dm"
#include "code\__DEFINES\hud.dm"
#include "code\__DEFINES\integrated_electronics.dm"
#include "code\__DEFINES\interaction_flags.dm"
@@ -357,7 +356,6 @@
#include "code\datums\components\empprotection.dm"
#include "code\datums\components\footstep.dm"
#include "code\datums\components\forced_gravity.dm"
-#include "code\datums\components\forensics.dm"
#include "code\datums\components\infective.dm"
#include "code\datums\components\jousting.dm"
#include "code\datums\components\knockoff.dm"
@@ -370,12 +368,12 @@
#include "code\datums\components\ntnet_interface.dm"
#include "code\datums\components\orbiter.dm"
#include "code\datums\components\paintable.dm"
+#include "code\datums\components\phantomthief.dm"
#include "code\datums\components\rad_insulation.dm"
#include "code\datums\components\radioactive.dm"
#include "code\datums\components\remote_materials.dm"
#include "code\datums\components\riding.dm"
#include "code\datums\components\rotation.dm"
-#include "code\datums\components\signal_redirect.dm"
#include "code\datums\components\slippery.dm"
#include "code\datums\components\spooky.dm"
#include "code\datums\components\squeak.dm"
@@ -386,7 +384,6 @@
#include "code\datums\components\virtual_reality.dm"
#include "code\datums\components\wearertargeting.dm"
#include "code\datums\components\wet_floor.dm"
-#include "code\datums\components\decals\blood.dm"
#include "code\datums\components\storage\storage.dm"
#include "code\datums\components\storage\concrete\_concrete.dm"
#include "code\datums\components\storage\concrete\bag_of_holding.dm"
@@ -579,6 +576,7 @@
#include "code\game\machinery\autolathe.dm"
#include "code\game\machinery\bank_machine.dm"
#include "code\game\machinery\Beacon.dm"
+#include "code\game\machinery\bloodbankgen.dm"
#include "code\game\machinery\buttons.dm"
#include "code\game\machinery\cell_charger.dm"
#include "code\game\machinery\cloning.dm"
@@ -758,6 +756,7 @@
#include "code\game\objects\effects\decals\misc.dm"
#include "code\game\objects\effects\decals\remains.dm"
#include "code\game\objects\effects\decals\cleanable\aliens.dm"
+#include "code\game\objects\effects\decals\cleanable\gibs.dm"
#include "code\game\objects\effects\decals\cleanable\humans.dm"
#include "code\game\objects\effects\decals\cleanable\misc.dm"
#include "code\game\objects\effects\decals\cleanable\robots.dm"
@@ -2711,6 +2710,7 @@
#include "code\modules\ruins\spaceruin_code\crashedship.dm"
#include "code\modules\ruins\spaceruin_code\deepstorage.dm"
#include "code\modules\ruins\spaceruin_code\DJstation.dm"
+#include "code\modules\ruins\spaceruin_code\hilbertshotel.dm"
#include "code\modules\ruins\spaceruin_code\listeningstation.dm"
#include "code\modules\ruins\spaceruin_code\miracle.dm"
#include "code\modules\ruins\spaceruin_code\oldstation.dm"
@@ -2947,7 +2947,6 @@
#include "modular_citadel\code\controllers\subsystem\job.dm"
#include "modular_citadel\code\controllers\subsystem\shuttle.dm"
#include "modular_citadel\code\datums\components\material_container.dm"
-#include "modular_citadel\code\datums\components\phantomthief.dm"
#include "modular_citadel\code\datums\components\souldeath.dm"
#include "modular_citadel\code\datums\mood_events\chem_events.dm"
#include "modular_citadel\code\datums\mood_events\generic_negative_events.dm"
diff --git a/tools/mapmerge2/dmi.py b/tools/mapmerge2/dmi.py
index f0a8182c9f..c12964cead 100644
--- a/tools/mapmerge2/dmi.py
+++ b/tools/mapmerge2/dmi.py
@@ -45,6 +45,8 @@ class Dmi:
@classmethod
def from_file(cls, fname):
image = Image.open(fname)
+ if image.mode != 'RGBA':
+ image = image.convert('RGBA')
# no metadata = regular image file
if 'Description' not in image.info:
@@ -250,4 +252,4 @@ if __name__ == '__main__':
Dmi.from_file(os.path.join(dirpath, filename))
count += 1
- print(f"Successfully parsed {count} dmi files")
+ print(f"Successfully parsed {count} dmi files")
\ No newline at end of file
diff --git a/tools/mapmerge2/dmm.py b/tools/mapmerge2/dmm.py
index 8bb1dca353..15aa04c07f 100644
--- a/tools/mapmerge2/dmm.py
+++ b/tools/mapmerge2/dmm.py
@@ -343,7 +343,7 @@ def _parse(map_raw_text):
in_map_block = False
in_coord_block = False
in_map_string = False
- iter_x = 0
+ base_x = 0
adjust_y = True
curr_num = ""
@@ -487,7 +487,7 @@ def _parse(map_raw_text):
curr_x = int(curr_num)
if curr_x > maxx:
maxx = curr_x
- iter_x = 0
+ base_x = curr_x
curr_num = ""
reading_coord = "y"
elif reading_coord == "y":
@@ -521,21 +521,15 @@ def _parse(map_raw_text):
adjust_y = False
else:
curr_y += 1
- if curr_x > maxx:
- maxx = curr_x
- if iter_x > 1:
- curr_x = 1
- iter_x = 0
-
+ curr_x = base_x
else:
curr_key = BASE * curr_key + base52_r[char]
curr_key_len += 1
if curr_key_len == key_length:
- iter_x += 1
- if iter_x > 1:
- curr_x += 1
-
grid[curr_x, curr_y, curr_z] = duplicate_keys.get(curr_key, curr_key)
+ if curr_x > maxx:
+ maxx = curr_x
+ curr_x += 1
curr_key = 0
curr_key_len = 0
@@ -551,4 +545,4 @@ def _parse(map_raw_text):
data = DMM(key_length, Coordinate(maxx, maxy, maxz))
data.dictionary = dictionary
data.grid = grid
- return data
+ return data
\ No newline at end of file
diff --git a/tools/mapmerge2/update_paths.py b/tools/mapmerge2/update_paths.py
index 2c316e941d..deab468ecd 100644
--- a/tools/mapmerge2/update_paths.py
+++ b/tools/mapmerge2/update_paths.py
@@ -173,4 +173,4 @@ if __name__ == "__main__":
parser.add_argument("--directory", "-d", help="path to maps directory, defaults to _maps/")
parser.add_argument("--inline", "-i", help="treat update source as update string instead of path", action="store_true")
parser.add_argument("--verbose", "-v", help="toggle detailed update information", action="store_true")
- main(parser.parse_args())
+ main(parser.parse_args())
\ No newline at end of file