diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_lodge.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_lodge.dmm index d4fe617c4c2..c7ffbefb0d2 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_lodge.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_lodge.dmm @@ -8,7 +8,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/floor, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/tile, @@ -21,7 +21,7 @@ pixel_x = 5; pixel_y = 8 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/carpet/royalblack, @@ -75,7 +75,7 @@ }, /area/ruin/huntinglodge) "bV" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/effect/turf_decal/weather/snow/corner{ @@ -153,7 +153,7 @@ /turf/open/floor/wood/tile, /area/ruin/huntinglodge) "cS" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /turf/open/misc/hay/icemoon, @@ -167,7 +167,7 @@ pixel_y = -4 }, /obj/item/gun/ballistic/automatic/pistol/m1911/no_mag, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /turf/open/floor/carpet/red, @@ -293,7 +293,7 @@ /turf/open/floor/wood/large, /area/ruin/huntinglodge) "fb" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /turf/open/misc/asteroid/snow/icemoon/do_not_chasm, @@ -388,7 +388,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/large, @@ -552,7 +552,7 @@ }, /obj/item/bodypart/head/ethereal, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/item/chair/stool, @@ -674,7 +674,7 @@ /obj/effect/decal/cleanable/blood/footprints{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/carpet/royalblack, @@ -752,7 +752,7 @@ /area/ruin/huntinglodge) "mb" = ( /obj/item/ammo_casing/shotgun/buckshot/spent, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/item/gun/ballistic/automatic/pistol/m1911/no_mag, @@ -1021,7 +1021,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/item/chair/stool, @@ -1042,7 +1042,7 @@ /area/icemoon/surface/outdoors/nospawn) "rI" = ( /obj/effect/decal/cleanable/blood/tracks, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/turf_decal/weather/snow/corner{ @@ -1088,7 +1088,7 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/effect/decal/cleanable/brimdust, @@ -1243,7 +1243,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 5 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/item/kirbyplants/random, @@ -1343,7 +1343,7 @@ /area/icemoon/surface/outdoors/nospawn) "xz" = ( /obj/effect/decal/cleanable/blood/gibs/body, -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/wood/corner, /obj/effect/turf_decal/siding/wood/corner{ @@ -1485,7 +1485,7 @@ /area/icemoon/surface/outdoors/nospawn) "yO" = ( /obj/effect/decal/cleanable/garbage, -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /obj/effect/decal/cleanable/blood/footprints{ dir = 2 }, @@ -1550,7 +1550,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/blood/gibs/core, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/tile, @@ -1579,13 +1579,13 @@ /turf/open/floor/wood/large, /area/ruin/huntinglodge) "As" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /turf/open/misc/asteroid/snow/icemoon/do_not_chasm, /area/icemoon/surface/outdoors/nospawn) "Aw" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/effect/turf_decal/weather/snow/corner{ @@ -1610,7 +1610,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /turf/open/floor/wood/large, @@ -1693,7 +1693,7 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/large, @@ -1767,7 +1767,7 @@ "Dc" = ( /obj/effect/turf_decal/siding/wood, /obj/structure/chair/stool/directional/south, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/confetti, @@ -1782,7 +1782,7 @@ /turf/open/floor/wood, /area/ruin/huntinglodge) "Dq" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/stone/icemoon, @@ -1952,7 +1952,7 @@ /turf/open/floor/wood, /area/ruin/huntinglodge) "EY" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/turf_decal/weather/snow/corner{ @@ -2330,7 +2330,7 @@ /obj/effect/turf_decal/siding/wood, /obj/structure/chair/stool/directional/south, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/tile, @@ -2353,7 +2353,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/confetti, @@ -2461,7 +2461,7 @@ /obj/structure/chair/stool/directional/south, /obj/effect/decal/cleanable/plastic, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/tile, @@ -2484,7 +2484,7 @@ dir = 1 }, /obj/structure/chair/stool/directional/north, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/confetti, @@ -2521,7 +2521,7 @@ /turf/open/floor/carpet/green, /area/ruin/huntinglodge) "NN" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -2555,7 +2555,7 @@ /area/ruin/huntinglodge) "Ok" = ( /obj/effect/turf_decal/siding/wood, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/wood/tile, @@ -2730,7 +2730,7 @@ dir = 4 }, /obj/effect/decal/cleanable/blood/gibs/limb, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/turf_decal/siding/wood/corner{ @@ -2765,7 +2765,7 @@ /obj/effect/decal/cleanable/blood/footprints{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/turf_decal/siding/wood/corner{ @@ -2777,11 +2777,11 @@ /obj/effect/turf_decal/siding/wood{ dir = 1 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /mob/living/basic/viscerator, @@ -2789,7 +2789,7 @@ /area/ruin/huntinglodge) "RB" = ( /obj/effect/decal/cleanable/blood/gibs/body, -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/checker, /area/ruin/huntinglodge) @@ -2836,7 +2836,7 @@ /turf/open/floor/stone/icemoon, /area/icemoon/surface/outdoors/nospawn) "Sp" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -2904,7 +2904,7 @@ /obj/effect/turf_decal/weather/snow/corner{ dir = 1 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/stone/icemoon, @@ -3095,7 +3095,7 @@ /area/ruin/huntinglodge) "Xd" = ( /obj/effect/decal/cleanable/blood/drip, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/floor/carpet/royalblack, @@ -3197,7 +3197,7 @@ pixel_x = -1; pixel_y = -1 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/turf_decal/weather/snow/corner{ @@ -3235,7 +3235,7 @@ /obj/machinery/door/airlock/wood{ color = "#beada5" }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/structure/fans/tiny, @@ -3284,7 +3284,7 @@ /turf/open/floor/carpet, /area/ruin/huntinglodge) "ZI" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/item/bodypart/head/ethereal, diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_mailroom.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_mailroom.dmm index 05d5324cac0..c62c9f09e4e 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_mailroom.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_mailroom.dmm @@ -207,7 +207,7 @@ /turf/closed/indestructible/reinforced, /area/ruin/powered/mailroom) "vV" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/smooth_large, /area/ruin/powered/mailroom) "wc" = ( @@ -433,7 +433,7 @@ /turf/open/floor/iron/smooth_large, /area/ruin/powered/mailroom) "TN" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/door/puzzle/keycard/icebox/office, /turf/open/floor/iron/white, /area/ruin/powered/mailroom) diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm index e41c2db6863..51b616bced9 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm @@ -53,7 +53,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "al" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -142,7 +142,7 @@ /turf/open/floor/plating, /area/ruin/syndibiodome) "bC" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/glass/plastitanium, @@ -210,7 +210,7 @@ /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "cx" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/structure/fluff/fake_scrubber{ @@ -310,7 +310,7 @@ /turf/open/floor/iron/cafeteria, /area/ruin/syndibiodome) "dJ" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/structure/fluff/fake_scrubber, @@ -361,7 +361,7 @@ }, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/glass/plastitanium, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /turf/open/floor/iron/dark/side{ @@ -421,7 +421,7 @@ /area/icemoon/surface/outdoors/noteleport) "fO" = ( /obj/structure/flora/bush/flowers_pp/style_3, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/effect/turf_decal/weather/dirt{ @@ -600,7 +600,7 @@ /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "hR" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /obj/effect/decal/cleanable/dirt, @@ -708,7 +708,7 @@ /obj/effect/turf_decal/trimline/green/line{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/effect/decal/cleanable/dirt, @@ -763,7 +763,7 @@ /obj/effect/turf_decal/siding/wood/corner{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /turf/open/floor/wood, @@ -774,7 +774,7 @@ /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "jR" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/turf_decal/trimline/dark_red/line, @@ -879,7 +879,7 @@ dir = 1 }, /obj/effect/turf_decal/siding/wideplating/dark, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /obj/effect/decal/cleanable/dirt, @@ -1020,7 +1020,7 @@ /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "mF" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) @@ -1120,7 +1120,7 @@ /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "oq" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/effect/decal/cleanable/dirt, @@ -1128,7 +1128,7 @@ /area/ruin/syndibiodome) "ox" = ( /obj/effect/decal/cleanable/glass/plastitanium, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /obj/effect/turf_decal/weather/dirt{ @@ -1262,7 +1262,7 @@ /area/ruin/syndibiodome) "qi" = ( /obj/effect/decal/cleanable/blood, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -1299,7 +1299,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/turf_decal/siding/wideplating/dark, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /turf/open/floor/iron/dark, @@ -1404,7 +1404,7 @@ dir = 8 }, /obj/effect/turf_decal/siding/wideplating_new/dark, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /obj/effect/turf_decal/tile/dark_red/opposingcorners, @@ -1494,7 +1494,7 @@ /area/ruin/syndibiodome) "tK" = ( /obj/effect/turf_decal/trimline/green/corner, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/effect/decal/cleanable/dirt, @@ -1515,7 +1515,7 @@ /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "ui" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/structure/fluff/fake_scrubber{ @@ -1722,7 +1722,7 @@ /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "vK" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /obj/structure/fluff/fake_vent, @@ -1738,7 +1738,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "vO" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -1882,7 +1882,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "xh" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -1961,7 +1961,7 @@ /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "xH" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/effect/decal/cleanable/dirt, @@ -2031,7 +2031,7 @@ dir = 5 }, /obj/structure/flora/bush/flowers_br/style_3, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/structure/fluff/fake_camera{ @@ -2082,7 +2082,7 @@ /area/ruin/syndibiodome) "yH" = ( /obj/effect/decal/cleanable/blood/splatter/over_window, -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /obj/effect/decal/cleanable/glass/plastitanium, /obj/machinery/door/poddoor/shutters/indestructible{ id = "biosurglockdown"; @@ -2184,7 +2184,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "zI" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -2376,7 +2376,7 @@ /obj/effect/turf_decal/trimline/green/corner{ dir = 1 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 9 }, /obj/effect/decal/cleanable/dirt, @@ -2513,7 +2513,7 @@ /turf/open/floor/iron/white/small, /area/ruin/syndibiodome) "EE" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -2556,7 +2556,7 @@ /obj/effect/turf_decal/siding/wideplating/dark{ dir = 1 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/effect/decal/cleanable/dirt, @@ -2565,7 +2565,7 @@ /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "Fe" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -2658,7 +2658,7 @@ /turf/open/floor/plating, /area/ruin/syndibiodome) "Gh" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -2816,7 +2816,7 @@ /turf/open/floor/iron/white/small, /area/ruin/syndibiodome) "Ij" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -2948,7 +2948,7 @@ /turf/open/floor/stone/icemoon, /area/icemoon/surface/outdoors/noteleport) "JZ" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /obj/effect/decal/cleanable/glass/plastitanium, @@ -2964,7 +2964,7 @@ "Ki" = ( /obj/machinery/door/airlock/public/glass, /obj/machinery/door/firedoor, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -3217,7 +3217,7 @@ /obj/effect/decal/cleanable/blood/tracks{ dir = 6 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /obj/effect/turf_decal/tile/dark_red/opposingcorners, @@ -3423,7 +3423,7 @@ /turf/open/floor/plating, /area/ruin/syndibiodome) "OH" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /obj/machinery/door/airlock/external/ruin, @@ -3716,7 +3716,7 @@ "St" = ( /obj/structure/fans/tiny, /obj/structure/door_assembly/door_assembly_grunge, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /turf/open/floor/iron/dark, @@ -3788,7 +3788,7 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /turf/open/floor/iron/dark, @@ -3841,7 +3841,7 @@ /obj/structure/fluff/fake_scrubber{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /obj/effect/decal/cleanable/glass/plastitanium, @@ -3875,7 +3875,7 @@ /obj/effect/turf_decal/trimline/blue/corner{ dir = 4 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /turf/open/floor/mineral/plastitanium/red, @@ -3893,7 +3893,7 @@ dir = 1 }, /obj/effect/turf_decal/siding/wideplating/dark, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 9 }, /obj/effect/decal/cleanable/dirt, @@ -4078,7 +4078,7 @@ dir = 8 }, /obj/structure/flora/bush/flowers_pp/style_3, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /turf/open/floor/grass, @@ -4140,13 +4140,13 @@ /turf/open/misc/asteroid/snow/icemoon, /area/ruin/syndibiodome) "VJ" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 9 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/turf_decal/siding/wideplating/dark{ @@ -4178,7 +4178,7 @@ "VT" = ( /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/shutters/preopen, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /obj/structure/fans/tiny, @@ -4394,7 +4394,7 @@ "YZ" = ( /obj/effect/turf_decal/siding/wideplating/dark, /obj/structure/fluff/fake_vent, -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, @@ -4419,14 +4419,14 @@ /turf/open/floor/grass, /area/ruin/syndibiodome) "Zp" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "ZD" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /obj/effect/decal/cleanable/dirt, diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm index 9df4af38f1b..7a02673c4e0 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm @@ -323,7 +323,7 @@ /area/ruin/syndielab) "tb" = ( /obj/machinery/light/warm/directional/north, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, /obj/structure/cable/layer1, /turf/open/floor/iron/dark/textured, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm b/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm index 6cf75767578..8b4dd1bc5d0 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm @@ -246,7 +246,7 @@ /turf/open/floor/plating, /area/ruin/powered/clownplanet) "bE" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/disposalpipe/segment{ dir = 10 }, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm index f5e69e12989..bbf0c14f8f3 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm @@ -437,7 +437,7 @@ /turf/open/floor/plating, /area/ruin/powered/snow_biodome) "Sj" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) "Ub" = ( diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm index bd900021094..f61188c3a46 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm @@ -38,7 +38,7 @@ /turf/closed/mineral/strong/wasteland, /area/ruin/unpowered/elephant_graveyard) "bh" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/chair/office/light, /turf/open/floor/mineral/titanium/white, /area/ruin/powered/graveyard_shuttle) @@ -83,7 +83,7 @@ /turf/closed/wall, /area/ruin/unpowered/elephant_graveyard) "bS" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/machinery/rnd/destructive_analyzer, /turf/open/floor/mineral/titanium/white, /area/ruin/powered/graveyard_shuttle) @@ -328,7 +328,7 @@ /turf/open/misc/asteroid/basalt/wasteland, /area/ruin/unpowered/elephant_graveyard) "yG" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/decal/cleanable/glass, /turf/open/misc/asteroid/basalt/wasteland, /area/ruin/unpowered/elephant_graveyard) diff --git a/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm b/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm index 51fea0a9517..8eddb65ddf5 100644 --- a/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm +++ b/_maps/RandomRuins/SpaceRuins/abandonedteleporter.dmm @@ -56,7 +56,7 @@ /turf/open/floor/plating/airless, /area/ruin/space/abandoned_tele) "n" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/floor/plating/airless, /area/ruin/space/abandoned_tele) "o" = ( @@ -89,7 +89,7 @@ /turf/open/floor/plating/airless, /area/ruin/space/abandoned_tele) "v" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating/airless, /area/ruin/space/abandoned_tele) "w" = ( diff --git a/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm b/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm index b2bdd4cac3b..171775eca42 100644 --- a/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm +++ b/_maps/RandomRuins/SpaceRuins/anomaly_research.dmm @@ -134,7 +134,7 @@ /turf/open/floor/wood, /area/misc/anomaly_research) "eW" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/purple/opposingcorners, /turf/open/floor/iron/white, @@ -1115,7 +1115,7 @@ /area/misc/anomaly_research) "Ff" = ( /obj/effect/turf_decal/trimline/purple/line, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/purple/opposingcorners, /turf/open/floor/iron/white, @@ -1474,7 +1474,7 @@ /turf/open/floor/iron/white, /area/misc/anomaly_research) "Oa" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/tile/purple/opposingcorners, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1509,7 +1509,7 @@ /area/misc/anomaly_research) "Ov" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/tile/purple/opposingcorners, /turf/open/floor/iron/white, /area/misc/anomaly_research) diff --git a/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm b/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm index 5e219273e13..03a29e782d1 100644 --- a/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm +++ b/_maps/RandomRuins/SpaceRuins/bigderelict1.dmm @@ -664,7 +664,7 @@ /turf/open/floor/iron, /area/ruin/space/has_grav/derelictoutpost/cargobay) "cV" = ( -/obj/effect/decal/cleanable/xenoblood/xsplatter, +/obj/effect/decal/cleanable/blood/splatter/xeno, /turf/open/floor/iron, /area/ruin/space/has_grav/derelictoutpost/cargobay) "cW" = ( @@ -769,7 +769,7 @@ /turf/open/floor/iron, /area/ruin/space/has_grav/derelictoutpost) "dq" = ( -/obj/effect/decal/cleanable/xenoblood/xsplatter, +/obj/effect/decal/cleanable/blood/splatter/xeno, /obj/structure/alien/weeds/creature, /turf/open/floor/iron, /area/ruin/space/has_grav/derelictoutpost/cargobay) diff --git a/_maps/RandomRuins/SpaceRuins/bus.dmm b/_maps/RandomRuins/SpaceRuins/bus.dmm index b821bf32195..d951c536f52 100644 --- a/_maps/RandomRuins/SpaceRuins/bus.dmm +++ b/_maps/RandomRuins/SpaceRuins/bus.dmm @@ -221,7 +221,7 @@ /area/ruin/space) "jH" = ( /obj/item/storage/toolbox/mechanical, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/airless, /area/ruin/space) "kn" = ( @@ -260,7 +260,7 @@ /turf/open/misc/asteroid/airless, /area/ruin/space) "Bw" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/airless, /area/ruin/space) "CO" = ( @@ -331,7 +331,7 @@ /obj/structure/fluff/bus/dense{ icon_state = "frontwallbottom" }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/airless, /area/ruin/space) "KK" = ( @@ -366,7 +366,7 @@ /turf/open/misc/asteroid/airless, /area/ruin/space) "Wn" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/misc/asteroid/airless, /area/ruin/space) "WQ" = ( diff --git a/_maps/RandomRuins/SpaceRuins/commsbuoy_nt.dmm b/_maps/RandomRuins/SpaceRuins/commsbuoy_nt.dmm index 4fa47033077..43c2ff96326 100644 --- a/_maps/RandomRuins/SpaceRuins/commsbuoy_nt.dmm +++ b/_maps/RandomRuins/SpaceRuins/commsbuoy_nt.dmm @@ -163,7 +163,7 @@ /turf/open/floor/mineral/titanium/yellow, /area/ruin/space/nt_commsbuoy) "lB" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/blood/footprints{ @@ -479,7 +479,7 @@ /turf/open/floor/mineral/titanium/yellow, /area/ruin/space/nt_commsbuoy) "Qd" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /obj/item/paper/fluff/ruins/nt_commsbuoy/torn_page, diff --git a/_maps/RandomRuins/SpaceRuins/cyborg_mothership.dmm b/_maps/RandomRuins/SpaceRuins/cyborg_mothership.dmm index f72cdd8ecad..d0a89db3bc8 100644 --- a/_maps/RandomRuins/SpaceRuins/cyborg_mothership.dmm +++ b/_maps/RandomRuins/SpaceRuins/cyborg_mothership.dmm @@ -11,8 +11,8 @@ /turf/open/misc/asteroid/airless, /area/space) "e" = ( -/obj/effect/decal/cleanable/oil/streak, -/obj/effect/decal/cleanable/oil{ +/obj/effect/decal/cleanable/blood/splatter/oil, +/obj/effect/decal/cleanable/blood/oil{ pixel_x = 8; pixel_y = 15 }, @@ -20,7 +20,7 @@ /area/space) "f" = ( /obj/structure/spacevine, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/airless, /area/space) "g" = ( @@ -38,7 +38,7 @@ /area/space) "k" = ( /obj/structure/spacevine, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/misc/asteroid/airless, /area/space) "m" = ( @@ -46,7 +46,7 @@ /turf/open/misc/asteroid/airless, /area/space) "n" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /turf/open/misc/asteroid/airless, /area/space) "o" = ( @@ -67,11 +67,11 @@ /area/space) "u" = ( /obj/structure/spacevine, -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/misc/asteroid/airless, /area/space) "v" = ( -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /turf/open/misc/asteroid/airless, /area/space) "w" = ( @@ -103,7 +103,7 @@ /turf/open/misc/asteroid/airless, /area/space) "G" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/misc/asteroid/airless, /area/space) "H" = ( @@ -130,7 +130,7 @@ /turf/open/misc/asteroid/airless, /area/space) "N" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/airless, /area/space) "O" = ( @@ -144,7 +144,7 @@ /turf/open/misc/asteroid/airless, /area/space) "R" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/misc/asteroid/airless, /area/space) "S" = ( @@ -172,7 +172,7 @@ /area/space) "Y" = ( /mob/living/basic/hivebot/range, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/misc/asteroid/airless, /area/space) "Z" = ( diff --git a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm index f8c87d30eb2..9a172cb8565 100644 --- a/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm +++ b/_maps/RandomRuins/SpaceRuins/dangerous_research.dmm @@ -152,7 +152,7 @@ "ci" = ( /obj/effect/decal/cleanable/dirt, /obj/item/wallframe/camera, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -2665,7 +2665,7 @@ }, /obj/item/wallframe/camera, /obj/item/stack/cable_coil, -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /turf/open/floor/iron/white, /area/ruin/space/has_grav/dangerous_research/medical) "IZ" = ( @@ -3209,7 +3209,7 @@ /area/ruin/space/has_grav/dangerous_research/dorms) "PZ" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 4 }, @@ -3765,7 +3765,7 @@ /obj/machinery/power/apc/auto_name/directional/north, /obj/effect/mapping_helpers/apc/away_general_access, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ dir = 4 }, diff --git a/_maps/RandomRuins/SpaceRuins/derelict_construction.dmm b/_maps/RandomRuins/SpaceRuins/derelict_construction.dmm index a8c3607258d..9da222e89c0 100644 --- a/_maps/RandomRuins/SpaceRuins/derelict_construction.dmm +++ b/_maps/RandomRuins/SpaceRuins/derelict_construction.dmm @@ -390,7 +390,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/derelictconstruction) "Vh" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/trash/caution_sign, /turf/open/floor/plating, diff --git a/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm b/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm index 92d886ad9ea..ba3512e7a96 100644 --- a/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm +++ b/_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm @@ -42,7 +42,7 @@ /area/ruin/space/has_grav/derelictsulaco) "cl" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/smooth, /area/ruin/space/has_grav/derelictsulaco) "cu" = ( @@ -92,7 +92,7 @@ /area/ruin/space) "dD" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/limb, +/obj/effect/decal/cleanable/blood/gibs/xeno/limb, /turf/open/floor/plating, /area/ruin/space/has_grav/derelictsulaco) "dJ" = ( @@ -124,7 +124,7 @@ /turf/open/floor/iron/smooth_edge, /area/ruin/space/has_grav/derelictsulaco) "eF" = ( -/obj/effect/decal/cleanable/blood/xtracks, +/obj/effect/decal/cleanable/blood/tracks/xeno, /turf/open/floor/plating/airless, /area/ruin/space) "eU" = ( @@ -157,7 +157,7 @@ /area/ruin/space/has_grav/derelictsulaco) "fI" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -312,7 +312,7 @@ }, /area/ruin/space/has_grav/derelictsulaco) "kH" = ( -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/structure/alien/weeds, /turf/open/floor/plating, /area/ruin/space/has_grav/derelictsulaco) @@ -421,14 +421,14 @@ /area/template_noop) "mS" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/larva, +/obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/item/stack/sheet/mineral/sandbags{ amount = 2 }, /turf/open/floor/plating, /area/ruin/space/has_grav/derelictsulaco) "mU" = ( -/obj/effect/decal/cleanable/xenoblood/xsplatter, +/obj/effect/decal/cleanable/blood/splatter/xeno, /obj/effect/turf_decal/tile/red/half, /turf/open/floor/iron/smooth_edge, /area/ruin/space/has_grav/derelictsulaco) @@ -478,7 +478,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/derelictsulaco) "qx" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/pod/light, /area/ruin/space/has_grav/derelictsulaco) @@ -670,7 +670,7 @@ /area/ruin/space/has_grav/derelictsulaco) "vl" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -699,7 +699,7 @@ /area/ruin/space/has_grav/derelictsulaco) "wR" = ( /obj/effect/mapping_helpers/burnt_floor, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -925,7 +925,7 @@ /area/ruin/space/has_grav/derelictsulaco) "FA" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/up, +/obj/effect/decal/cleanable/blood/gibs/xeno/up, /turf/open/floor/plating, /area/ruin/space/has_grav/derelictsulaco) "FK" = ( @@ -1015,7 +1015,7 @@ /area/ruin/space) "Ie" = ( /obj/effect/mapping_helpers/burnt_floor, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1191,7 +1191,7 @@ /area/ruin/space/has_grav/derelictsulaco) "MG" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs, +/obj/effect/decal/cleanable/blood/gibs/xeno, /turf/open/floor/plating, /area/ruin/space/has_grav/derelictsulaco) "Ne" = ( @@ -1253,7 +1253,7 @@ network = list() }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood/xgibs/down, +/obj/effect/decal/cleanable/blood/gibs/xeno/down, /obj/machinery/computer/monitor{ dir = 1 }, @@ -1329,7 +1329,7 @@ /area/ruin/space/has_grav/derelictsulaco) "QR" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 5 }, /obj/item/trash/flare, @@ -1354,7 +1354,7 @@ "RH" = ( /obj/structure/alien/weeds, /obj/effect/decal/remains/xeno, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/plating/airless, /area/ruin/space) "RP" = ( @@ -1364,7 +1364,7 @@ /turf/template_noop, /area/template_noop) "RZ" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /turf/open/floor/iron/smooth, /area/ruin/space/has_grav/derelictsulaco) "Sj" = ( @@ -1424,7 +1424,7 @@ "Ti" = ( /obj/machinery/light/floor, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/effect/decal/cleanable/blood, /turf/open/floor/iron/smooth, /area/ruin/space/has_grav/derelictsulaco) @@ -1438,7 +1438,7 @@ /area/ruin/space/has_grav/derelictsulaco) "TL" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -1647,7 +1647,7 @@ /area/ruin/space/has_grav/derelictsulaco) "ZA" = ( /obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 4 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, diff --git a/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm b/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm index 17e9d92a2f4..b9bf82f7241 100644 --- a/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm +++ b/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm @@ -82,7 +82,7 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "fc" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 8 }, /turf/open/misc/asteroid/basalt/airless, @@ -353,7 +353,7 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "we" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /turf/open/misc/asteroid/basalt/airless, @@ -536,7 +536,7 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "Jj" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /mob/living/basic/mining/ice_whelp/ash, @@ -547,7 +547,7 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "JY" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/open/misc/asteroid/basalt/airless, @@ -559,7 +559,7 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "Ky" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 6 }, /turf/open/misc/asteroid/basalt/airless, @@ -719,19 +719,19 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "Qa" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 1 }, /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "Qg" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 9 }, /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "QQ" = ( -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "QY" = ( @@ -821,7 +821,7 @@ /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) "Va" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /turf/open/misc/asteroid/basalt/airless, diff --git a/_maps/RandomRuins/SpaceRuins/fasttravel.dmm b/_maps/RandomRuins/SpaceRuins/fasttravel.dmm index 2a8a8a2226a..ca51f7525f5 100644 --- a/_maps/RandomRuins/SpaceRuins/fasttravel.dmm +++ b/_maps/RandomRuins/SpaceRuins/fasttravel.dmm @@ -214,7 +214,7 @@ }, /area/ruin/space/massdriverhub) "Fw" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/machinery/conveyor{ dir = 4; id = "zaza" diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm index 05da4138d0f..4f36c39e6ad 100644 --- a/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck1.dmm @@ -411,7 +411,7 @@ desc = "It's just a wooden stick with some compressed ash on the end. At least it can write."; name = "charcoal stick" }, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/structure/closet/crate/trashcart, /obj/item/food/grown/ash_flora/shavings, /turf/open/floor/plating/dumpsterair, @@ -912,7 +912,7 @@ pixel_y = -2 }, /obj/effect/decal/cleanable/plastic, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/decal/cleanable/glass, /obj/effect/spawner/random/engineering/material_cheap, /obj/item/crowbar/hammer{ diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm index ae7fe201988..78410dcdb31 100644 --- a/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm @@ -163,7 +163,7 @@ /obj/effect/decal/cleanable/fuel_pool, /obj/item/rack_parts, /obj/item/storage/pill_bottle/mannitol, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/medicalwaste) "qC" = ( @@ -275,7 +275,7 @@ /obj/item/food/badrecipe/moldy, /obj/item/food/badrecipe/moldy, /obj/structure/closet/mini_fridge/grimy, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/reagent_containers/cup/bottle/morphine, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/medicalwaste) @@ -424,7 +424,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/medicalwaste) "IM" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/closet/crate/freezer, /obj/item/organ/liver/roach, /obj/item/organ/stomach, @@ -550,7 +550,7 @@ /turf/template_noop, /area/ruin/space/has_grav/garbagetruck/medicalwaste) "Pe" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /obj/structure/frame/computer, /obj/item/stack/sheet/glass{ amount = 2 @@ -571,7 +571,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/medicalwaste) "QK" = ( -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /obj/item/circular_saw, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/medicalwaste) diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm index 1bc775220c2..fc94b80d68b 100644 --- a/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck3.dmm @@ -503,7 +503,7 @@ /area/ruin/space/has_grav/garbagetruck/squat) "zz" = ( /obj/item/cigbutt/cigarbutt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/fuel_pool, /obj/structure/closet/crate/trashcart, /obj/item/storage/bag/trash, @@ -648,7 +648,7 @@ "Hn" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/fuel_pool, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/item/pen, /obj/item/stock_parts/subspace/analyzer, /turf/open/floor/plating/dumpsterair, @@ -707,7 +707,7 @@ /area/ruin/space/has_grav/garbagetruck/squat) "JR" = ( /obj/effect/decal/cleanable/ash, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /mob/living/basic/trooper/russian, /turf/open/floor/plating/dumpsterair, /area/ruin/space/has_grav/garbagetruck/squat) @@ -783,7 +783,7 @@ "Ol" = ( /obj/item/plate_shard, /obj/effect/decal/cleanable/fuel_pool, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating/dumpsterair, /area/ruin/space/has_grav/garbagetruck/squat) "Pz" = ( diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm index 35b18eff47f..00f49ef1cf1 100644 --- a/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm @@ -201,7 +201,7 @@ /turf/closed/wall/r_wall, /area/ruin/space/has_grav/garbagetruck/toystore) "rc" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/flashlight/flare/torch, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) @@ -383,7 +383,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "wK" = ( -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /obj/item/clothing/under/costume/skeleton, /obj/item/clothing/mask/gas/prop, /turf/open/floor/plating, @@ -394,15 +394,15 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "xd" = ( -/obj/effect/decal/cleanable/robot_debris/up, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, +/obj/effect/decal/cleanable/blood/oil, /obj/item/melee/skateboard, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "xf" = ( /obj/structure/door_assembly/door_assembly_wood, /obj/effect/decal/cleanable/plastic, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "xC" = ( @@ -844,7 +844,7 @@ /area/ruin/space/has_grav/garbagetruck/toystore) "XL" = ( /obj/item/scooter_frame, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/decal/cleanable/garbage, /obj/effect/decal/cleanable/blood/old, /turf/open/floor/plating, diff --git a/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm b/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm index ac76b2c8ea3..b7c9cf52c7b 100644 --- a/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm +++ b/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm @@ -49,7 +49,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/hauntedtradingpost/public/corridor) "aD" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /obj/item/assembly/igniter{ pixel_x = -7; pixel_y = -11 @@ -160,7 +160,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/office) "bt" = ( /obj/structure/cable/layer1, -/obj/effect/decal/cleanable/oil/streak{ +/obj/effect/decal/cleanable/blood/splatter/oil{ pixel_y = -7 }, /obj/effect/mapping_helpers/airalarm/syndicate_access, @@ -247,7 +247,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/public) "ca" = ( /obj/structure/cable/layer1, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/machinery/camera/xray/directional/west, /turf/open/floor/carpet/donk, /area/ruin/space/has_grav/hauntedtradingpost/employees/breakroom) @@ -297,7 +297,7 @@ "ct" = ( /obj/structure/table/wood, /obj/machinery/microwave, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/structure/cable/layer1, /obj/effect/overloader_trap{ trigger_delay = 10 @@ -675,7 +675,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/hauntedtradingpost/maint/toystorage) "fZ" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/structure/cable/layer1, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/space/has_grav/hauntedtradingpost/aicore) @@ -1265,7 +1265,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/maint) "kE" = ( /obj/structure/cable/layer1, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/structure/sign/departments/cargo/directional/east, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4, /obj/structure/reagent_dispensers/water_cooler, @@ -1556,7 +1556,7 @@ /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/space/has_grav/hauntedtradingpost/employees/corridor) "nk" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/machinery/duct, /obj/machinery/firealarm/directional/south, /obj/item/food/deadmouse, @@ -1896,7 +1896,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/maint/toystorage) "qF" = ( /obj/structure/cable/layer1, -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /obj/item/ammo_casing/foam_dart{ pixel_x = 2 }, @@ -2909,7 +2909,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/maint/toolstorage) "zg" = ( /obj/structure/cable/layer1, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/space/has_grav/hauntedtradingpost/aicore) "zi" = ( @@ -4029,9 +4029,9 @@ /area/ruin/space/has_grav/hauntedtradingpost/public/corridor) "IQ" = ( /obj/structure/cable/layer1, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /mob/living/basic/mouse/rat, -/obj/effect/decal/cleanable/oil/streak{ +/obj/effect/decal/cleanable/blood/splatter/oil{ pixel_y = -7 }, /turf/open/floor/catwalk_floor/iron_dark, @@ -4040,7 +4040,7 @@ /obj/structure/closet/cardboard{ desc = "A typical example of the ubiquitous cardboard box. Handy if you want to store things. This box is labelled 'OUTLET 6013' and has the Donk Co. logo stamped on it." }, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/item/trash/popcorn/salty, /obj/item/ammo_casing/shotgun/flechette/donk{ pixel_x = 8; @@ -4357,7 +4357,7 @@ /turf/open/floor/carpet/orange, /area/ruin/space/has_grav/hauntedtradingpost/office/meetingroom) "LM" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/duct, /turf/open/floor/carpet/donk, @@ -5402,7 +5402,7 @@ pixel_y = 8; pixel_x = 14 }, -/obj/effect/decal/cleanable/oil/slippery{ +/obj/effect/decal/cleanable/blood/oil/slippery{ pixel_y = 6; pixel_x = 6 }, @@ -5513,7 +5513,7 @@ /turf/open/floor/carpet/donk, /area/ruin/space/has_grav/hauntedtradingpost/employees/workstation) "VA" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/carpet/donk, /area/ruin/space/has_grav/hauntedtradingpost/employees) "VJ" = ( diff --git a/_maps/RandomRuins/SpaceRuins/hellfactory.dmm b/_maps/RandomRuins/SpaceRuins/hellfactory.dmm index da3fb83e79f..fd5196e4547 100644 --- a/_maps/RandomRuins/SpaceRuins/hellfactory.dmm +++ b/_maps/RandomRuins/SpaceRuins/hellfactory.dmm @@ -963,11 +963,11 @@ /turf/open/floor/iron, /area/ruin/space/has_grav/hellfactory) "Sz" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/ruin/space/has_grav/hellfactory) "UK" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/iron, /area/ruin/space/has_grav/hellfactory) "UN" = ( diff --git a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm index 8dabc82080e..cc336e6c3fc 100644 --- a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm +++ b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm @@ -1061,7 +1061,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 1 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/wood, /area/ruin/space/has_grav/powered/hilbertresearchfacility) "zM" = ( @@ -1520,7 +1520,7 @@ dir = 8 }, /obj/structure/railing/corner, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/glass, /area/ruin/space/has_grav/powered/hilbertresearchfacility) "IY" = ( @@ -2019,7 +2019,7 @@ dir = 1 }, /obj/effect/turf_decal/siding/wood, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/wood, /area/ruin/space/has_grav/powered/hilbertresearchfacility) "To" = ( diff --git a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm index 18694d3b4a0..9565fa689c3 100644 --- a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm +++ b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm @@ -203,10 +203,10 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/infested_frigate) "cX" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/up{ +/obj/effect/decal/cleanable/blood/gibs/xeno/up{ icon_state = "xgibbl4" }, -/obj/effect/decal/cleanable/xenoblood/xgibs/up{ +/obj/effect/decal/cleanable/blood/gibs/xeno/up{ icon_state = "xgibleg"; dir = 4 }, @@ -615,7 +615,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/infested_frigate) "iS" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/up{ +/obj/effect/decal/cleanable/blood/gibs/xeno/up{ icon_state = "xgib1" }, /turf/open/floor/mineral/plastitanium, @@ -655,7 +655,7 @@ /obj/effect/turf_decal{ dir = 8 }, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/structure/fluff/broken_canister_frame, /obj/item/ammo_casing/spent, /obj/item/ammo_casing/spent, @@ -872,7 +872,7 @@ icon_state = "arrows_red"; dir = 4 }, -/obj/effect/decal/cleanable/oil/slippery{ +/obj/effect/decal/cleanable/blood/oil/slippery{ icon_state = "floor7" }, /obj/effect/turf_decal{ @@ -891,7 +891,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/infested_frigate) "oV" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/up{ +/obj/effect/decal/cleanable/blood/gibs/xeno/up{ icon_state = "xltrails_2"; dir = 8 }, @@ -1284,7 +1284,7 @@ "vM" = ( /obj/item/ammo_casing/spent, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood{ +/obj/effect/decal/cleanable/blood/xeno{ icon_state = "xltrails_1"; dir = 8 }, @@ -1353,7 +1353,7 @@ icon_state = "caution_red"; dir = 1 }, -/obj/effect/decal/cleanable/xenoblood/xgibs{ +/obj/effect/decal/cleanable/blood/gibs/xeno{ icon_state = "xltrails_1"; dir = 4 }, @@ -1576,7 +1576,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/infested_frigate) "yG" = ( -/obj/effect/decal/cleanable/robot_debris{ +/obj/effect/decal/cleanable/blood/gibs/robot_debris{ icon_state = "gib4" }, /obj/effect/decal/cleanable/blood/tracks{ @@ -1737,7 +1737,7 @@ dir = 8 }, /obj/item/ammo_casing/spent, -/obj/effect/decal/cleanable/xenoblood/xgibs{ +/obj/effect/decal/cleanable/blood/gibs/xeno{ icon_state = "tracks"; dir = 1 }, @@ -1746,7 +1746,7 @@ "Bw" = ( /obj/item/ammo_casing/spent, /obj/item/ammo_casing/spent, -/obj/effect/decal/cleanable/xenoblood/xgibs/up{ +/obj/effect/decal/cleanable/blood/gibs/xeno/up{ icon_state = "xgibtorso"; dir = 4 }, @@ -2074,7 +2074,7 @@ /area/ruin/space/has_grav/infested_frigate) "HA" = ( /obj/item/ammo_casing/spent, -/obj/effect/decal/cleanable/xenoblood/xgibs/up{ +/obj/effect/decal/cleanable/blood/gibs/xeno/up{ icon_state = "xgibhead"; dir = 4 }, @@ -2145,7 +2145,7 @@ /obj/effect/turf_decal{ icon_state = "bot_red" }, -/obj/effect/decal/cleanable/xenoblood/xgibs{ +/obj/effect/decal/cleanable/blood/gibs/xeno{ icon_state = "xgibup1" }, /turf/open/floor/mineral/plastitanium, @@ -2340,7 +2340,7 @@ /obj/effect/turf_decal{ dir = 8 }, -/obj/effect/decal/cleanable/xenoblood/xgibs{ +/obj/effect/decal/cleanable/blood/gibs/xeno{ icon_state = "xgibmid1" }, /obj/effect/mapping_helpers/broken_floor, @@ -2378,7 +2378,7 @@ /obj/effect/turf_decal{ icon_state = "bot_right_red" }, -/obj/effect/decal/cleanable/xenoblood/xgibs{ +/obj/effect/decal/cleanable/blood/gibs/xeno{ icon_state = "xgibtorso" }, /turf/open/floor/mineral/plastitanium, @@ -3015,7 +3015,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/infested_frigate) "Xm" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs{ +/obj/effect/decal/cleanable/blood/gibs/xeno{ icon_state = "xgibbl3" }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, @@ -3157,7 +3157,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/infested_frigate) "ZN" = ( -/obj/effect/decal/cleanable/robot_debris{ +/obj/effect/decal/cleanable/blood/gibs/robot_debris{ icon_state = "gibup" }, /obj/effect/decal/cleanable/blood/gibs{ diff --git a/_maps/RandomRuins/SpaceRuins/interdyne.dmm b/_maps/RandomRuins/SpaceRuins/interdyne.dmm index b115c323a35..a6657902c13 100644 --- a/_maps/RandomRuins/SpaceRuins/interdyne.dmm +++ b/_maps/RandomRuins/SpaceRuins/interdyne.dmm @@ -310,7 +310,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/interdyne) "mx" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/interdyne) "mD" = ( @@ -512,7 +512,7 @@ /area/ruin/space/has_grav/interdyne) "vA" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/interdyne) "vK" = ( @@ -1036,7 +1036,7 @@ /turf/open/floor/iron/smooth, /area/ruin/space/has_grav/interdyne) "Qw" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/interdyne) "QC" = ( @@ -1165,7 +1165,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/interdyne) "Un" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/interdyne) "UN" = ( diff --git a/_maps/RandomRuins/SpaceRuins/meateor.dmm b/_maps/RandomRuins/SpaceRuins/meateor.dmm index b9a731a08cb..b64e93ed1a2 100644 --- a/_maps/RandomRuins/SpaceRuins/meateor.dmm +++ b/_maps/RandomRuins/SpaceRuins/meateor.dmm @@ -36,7 +36,7 @@ /area/ruin/space/meateor) "q" = ( /obj/effect/mob_spawn/corpse/headcrab, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/material/meat/airless, /area/ruin/space/meateor) "r" = ( @@ -47,7 +47,7 @@ /area/ruin/space/meateor) "s" = ( /obj/effect/mob_spawn/corpse/headcrab, -/obj/effect/decal/cleanable/xenoblood/xgibs, +/obj/effect/decal/cleanable/blood/gibs/xeno, /turf/open/floor/material/meat/airless, /area/ruin/space/meateor) "v" = ( diff --git a/_maps/RandomRuins/SpaceRuins/mechtransport.dmm b/_maps/RandomRuins/SpaceRuins/mechtransport.dmm index 6c96a3a0a75..2591d4991e5 100644 --- a/_maps/RandomRuins/SpaceRuins/mechtransport.dmm +++ b/_maps/RandomRuins/SpaceRuins/mechtransport.dmm @@ -18,7 +18,7 @@ /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) "dW" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) @@ -51,7 +51,7 @@ /turf/open/floor/mineral/titanium/blue/airless, /area/ruin/space/has_grav/powered/mechtransport) "jI" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/floor/plating/airless, /area/ruin/space/has_grav/powered/mechtransport) "jZ" = ( @@ -112,7 +112,7 @@ /turf/open/floor/mineral/titanium/blue/airless, /area/ruin/space/has_grav/powered/mechtransport) "lP" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating/airless, /area/ruin/space/has_grav/powered/mechtransport) "mU" = ( @@ -215,7 +215,7 @@ /turf/open/floor/plating/airless, /area/ruin/space/has_grav/powered/mechtransport) "CT" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/catwalk_floor/iron_smooth/airless, /area/ruin/space/has_grav/powered/mechtransport) "DD" = ( @@ -274,7 +274,7 @@ /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) "Mn" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) @@ -289,7 +289,7 @@ /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) "Ov" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/catwalk_floor/iron_smooth/airless, /area/ruin/space/has_grav/powered/mechtransport) "OJ" = ( @@ -311,7 +311,7 @@ /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) "Te" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible/layer2, /obj/effect/turf_decal/stripes/full, @@ -334,7 +334,7 @@ /turf/open/floor/iron/smooth_large/airless, /area/ruin/space/has_grav/powered/mechtransport) "WN" = ( -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /obj/effect/turf_decal/stripes/full, /obj/effect/turf_decal/stripes/red/line{ dir = 4 diff --git a/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm b/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm index fbdc62bae7a..20c84d90c1c 100644 --- a/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldAIsat.dmm @@ -475,7 +475,7 @@ /turf/open/floor/plating, /area/ruin/space/tcommsat_oldaisat) "bT" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating/airless, /area/ruin/space/tcommsat_oldaisat) "bU" = ( diff --git a/_maps/RandomRuins/SpaceRuins/old_infiltrator.dmm b/_maps/RandomRuins/SpaceRuins/old_infiltrator.dmm index 494e6467666..af6bfe66965 100644 --- a/_maps/RandomRuins/SpaceRuins/old_infiltrator.dmm +++ b/_maps/RandomRuins/SpaceRuins/old_infiltrator.dmm @@ -142,7 +142,7 @@ /turf/open/floor/circuit/red/airless, /area/ruin/space/unpowered) "jt" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/spawner/random/maintenance, /turf/open/floor/mineral/plastitanium/red/airless, /area/ruin/space/unpowered) diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm index 16be6f10c41..d347eef5695 100644 --- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm @@ -82,7 +82,7 @@ /turf/open/floor/plating, /area/ruin/space/ancientstation/charlie/hall) "aF" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/alien/weeds, /obj/structure/alien/egg/burst, /turf/open/floor/iron/dark, @@ -132,7 +132,7 @@ /area/ruin/space/ancientstation/charlie/bridge) "aM" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/up, +/obj/effect/decal/cleanable/blood/gibs/xeno/up, /turf/open/floor/iron/dark, /area/ruin/space/ancientstation/delta/ai) "aN" = ( @@ -250,7 +250,7 @@ /area/ruin/space/ancientstation/delta/ai) "bp" = ( /obj/machinery/door/window/brigdoor/left/directional/west, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/alien/weeds/node, /turf/open/floor/iron/dark, /area/ruin/space/ancientstation/delta/ai) @@ -670,7 +670,7 @@ /turf/open/floor/iron, /area/ruin/space/ancientstation/delta/hall) "cY" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/alien/weeds, /turf/open/floor/iron/dark, /area/ruin/space/ancientstation/delta/ai) @@ -706,7 +706,7 @@ /area/ruin/space/ancientstation/charlie/bridge) "dd" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, +/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body, /turf/open/floor/iron/dark, /area/ruin/space/ancientstation/delta/ai) "de" = ( @@ -1588,7 +1588,7 @@ /area/ruin/space/ancientstation/charlie/engie) "hh" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood/xgibs/core, +/obj/effect/decal/cleanable/blood/gibs/xeno/core, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, @@ -2104,7 +2104,7 @@ /turf/open/floor/plating, /area/ruin/space/ancientstation/charlie/storage) "jk" = ( -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2{ dir = 8 }, @@ -2316,7 +2316,7 @@ /obj/machinery/door/airlock/highsecurity, /obj/structure/alien/weeds, /obj/structure/cable, -/obj/effect/decal/cleanable/blood/xtracks, +/obj/effect/decal/cleanable/blood/tracks/xeno, /obj/effect/decal/cleanable/blood/tracks, /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "oldstation-aisat" @@ -2614,7 +2614,7 @@ "lo" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/west, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 8 @@ -3220,7 +3220,7 @@ "nX" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4{ dir = 8 @@ -3288,13 +3288,13 @@ "oq" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, +/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body, /turf/open/floor/iron, /area/ruin/space/ancientstation/delta/hall) "ou" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood/xgibs/up, +/obj/effect/decal/cleanable/blood/gibs/xeno/up, /turf/open/floor/iron, /area/ruin/space/ancientstation/delta/hall) "oy" = ( @@ -3329,7 +3329,7 @@ /turf/open/floor/iron/airless, /area/ruin/space/ancientstation/beta/medbay) "oD" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/core, +/obj/effect/decal/cleanable/blood/gibs/xeno/core, /turf/open/floor/iron/white, /area/ruin/space/ancientstation/delta/rnd) "oE" = ( @@ -3352,7 +3352,7 @@ /area/ruin/space/ancientstation/beta/medbay) "oH" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood/xgibs/core, +/obj/effect/decal/cleanable/blood/gibs/xeno/core, /turf/open/floor/iron/white, /area/ruin/space/ancientstation/delta/rnd) "oL" = ( @@ -3409,7 +3409,7 @@ "oU" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, -/obj/effect/decal/cleanable/xenoblood/xgibs/up, +/obj/effect/decal/cleanable/blood/gibs/xeno/up, /turf/open/floor/iron, /area/ruin/space/ancientstation/delta/hall) "oV" = ( @@ -3546,7 +3546,7 @@ }, /area/ruin/space/ancientstation/delta/rnd) "pW" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/alien/weeds, /obj/machinery/light/small/broken/directional/west, /turf/open/floor/iron/dark, @@ -3725,7 +3725,7 @@ /turf/open/floor/engine/n2, /area/ruin/space/ancientstation/beta/atmos) "rC" = ( -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 8 }, /obj/effect/decal/cleanable/glass, @@ -4073,7 +4073,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/item/shard, -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 6 }, /obj/effect/turf_decal/tile/purple/half/contrasted, @@ -6226,7 +6226,7 @@ /turf/open/floor/iron, /area/ruin/space/ancientstation/delta/hall) "Js" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/alien/weeds, /obj/structure/closet/crate, /obj/item/stack/sheet/glass/fifty{ @@ -6909,7 +6909,7 @@ /turf/open/floor/iron/dark, /area/ruin/space/ancientstation/delta/hall) "Np" = ( -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 10 }, /turf/open/floor/engine, @@ -7002,7 +7002,7 @@ /area/ruin/space/ancientstation/beta/medbay) "NQ" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/iron/white, /area/ruin/space/ancientstation/delta/rnd) "NS" = ( @@ -7103,7 +7103,7 @@ /turf/open/floor/iron, /area/ruin/space/ancientstation/charlie/hydro) "Om" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/ruin/space/ancientstation/charlie/hall) @@ -7655,7 +7655,7 @@ /area/ruin/space/ancientstation/charlie/bridge) "Sz" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, +/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8140,7 +8140,7 @@ /turf/open/floor/iron/dark, /area/ruin/space/ancientstation/charlie/engie) "Wd" = ( -/obj/effect/decal/cleanable/blood/xtracks{ +/obj/effect/decal/cleanable/blood/tracks/xeno{ dir = 5 }, /turf/open/floor/engine, diff --git a/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm b/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm index ee2eb851cfd..a580fa0da1c 100644 --- a/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm +++ b/_maps/RandomRuins/SpaceRuins/prison_shuttle.dmm @@ -144,7 +144,7 @@ /area/ruin/space/prison_shuttle) "O" = ( /obj/effect/turf_decal/tile/brown/fourcorners, -/obj/effect/decal/cleanable/xenoblood/xsplatter, +/obj/effect/decal/cleanable/blood/splatter/xeno, /turf/open/floor/iron/dark/airless, /area/ruin/space/prison_shuttle) "P" = ( diff --git a/_maps/RandomRuins/SpaceRuins/space_ghost_restaurant.dmm b/_maps/RandomRuins/SpaceRuins/space_ghost_restaurant.dmm index fa97cdd8966..ad0c7241594 100644 --- a/_maps/RandomRuins/SpaceRuins/space_ghost_restaurant.dmm +++ b/_maps/RandomRuins/SpaceRuins/space_ghost_restaurant.dmm @@ -115,7 +115,7 @@ /turf/open/floor/iron/showroomfloor/airless, /area/ruin/space/space_ghost_restaurant) "vs" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/iron/showroomfloor/airless, /area/ruin/space/space_ghost_restaurant) "wF" = ( @@ -150,7 +150,7 @@ /turf/template_noop, /area/template_noop) "BA" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/decal/cleanable/glass, /turf/open/floor/iron/cafeteria/airless, /area/ruin/space/space_ghost_restaurant) @@ -290,7 +290,7 @@ /turf/open/floor/iron/cafeteria/airless, /area/ruin/space/space_ghost_restaurant) "Xc" = ( -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /turf/open/floor/iron/cafeteria/airless, /area/ruin/space/space_ghost_restaurant) "Xn" = ( diff --git a/_maps/RandomRuins/SpaceRuins/the_faceoff.dmm b/_maps/RandomRuins/SpaceRuins/the_faceoff.dmm index a358d59956e..48844fb46b2 100644 --- a/_maps/RandomRuins/SpaceRuins/the_faceoff.dmm +++ b/_maps/RandomRuins/SpaceRuins/the_faceoff.dmm @@ -120,7 +120,7 @@ /area/ruin/space) "cZ" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/dark/airless, /area/ruin/space) "de" = ( @@ -138,7 +138,7 @@ /area/ruin/space) "dt" = ( /obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/dark/airless, /area/ruin/space) "eg" = ( @@ -209,7 +209,7 @@ /area/ruin/space) "gh" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/misc/asteroid/basalt/airless, /area/ruin/space) "gq" = ( @@ -246,7 +246,7 @@ /turf/open/floor/mineral/plastitanium/airless, /area/ruin/space) "hA" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/stripes/red/full, /turf/open/floor/iron/dark/smooth_large/airless, /area/ruin/space) @@ -493,7 +493,7 @@ /obj/effect/mapping_helpers/burnt_floor, /obj/effect/mob_spawn/corpse/human/pirate/melee/space, /obj/effect/decal/cleanable/blood, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/spawner/random/structure/chair_flipped{ dir = 1 }, @@ -706,7 +706,7 @@ /turf/open/floor/iron/dark/airless, /area/ruin/space) "CT" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/dark/airless, /area/ruin/space) "CY" = ( @@ -790,7 +790,7 @@ pixel_x = 5; pixel_y = 2 }, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/dark/airless, /area/ruin/space) "FV" = ( diff --git a/_maps/RandomRuins/SpaceRuins/the_outlet.dmm b/_maps/RandomRuins/SpaceRuins/the_outlet.dmm index 922715ca8d7..88502eb5933 100644 --- a/_maps/RandomRuins/SpaceRuins/the_outlet.dmm +++ b/_maps/RandomRuins/SpaceRuins/the_outlet.dmm @@ -233,7 +233,7 @@ icon_state = "dirt-0" }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/oil{ +/obj/effect/decal/cleanable/blood/oil{ icon_state = "floor4" }, /turf/open/floor/iron, @@ -869,7 +869,7 @@ /obj/effect/decal/cleanable/dirt{ icon_state = "dirt-137" }, -/obj/effect/decal/cleanable/oil{ +/obj/effect/decal/cleanable/blood/oil{ icon_state = "floor7" }, /obj/machinery/light/dim/directional/south, @@ -976,7 +976,7 @@ icon_state = "dirt-0" }, /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/ruin/space/has_grav/the_outlet/employeesection) "ya" = ( diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm index bbc1f67457e..73fc2b0391e 100644 --- a/_maps/RandomZLevels/SnowCabin.dmm +++ b/_maps/RandomZLevels/SnowCabin.dmm @@ -1281,7 +1281,7 @@ /area/awaymission/cabin/snowforest) "gL" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/cabin) "gM" = ( @@ -1439,7 +1439,7 @@ /area/awaymission/cabin) "hr" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/generic, /obj/structure/cable, /turf/open/floor/plating, @@ -3201,7 +3201,7 @@ /turf/open/floor/plating/snowed/snow_cabin, /area/awaymission/cabin/snowforest/sovietsurface) "uz" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) "uF" = ( @@ -5327,7 +5327,7 @@ desc = "It looks like fancy glitter to me."; name = "icy wind" }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) "WF" = ( diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm index df0347e5729..4bbb319a9f7 100644 --- a/_maps/RandomZLevels/TheBeach.dmm +++ b/_maps/RandomZLevels/TheBeach.dmm @@ -829,7 +829,7 @@ /turf/open/floor/wood/large, /area/awaymission/beach) "kp" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/button/door/directional/south{ id = "BeachGarage" }, @@ -1683,7 +1683,7 @@ /obj/vehicle/ridden/atv{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/herringbone, /area/awaymission/beach) "vq" = ( @@ -2175,7 +2175,7 @@ pixel_y = 4 }, /obj/item/storage/toolbox/emergency, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/herringbone, /area/awaymission/beach) "Cf" = ( @@ -3123,7 +3123,7 @@ /obj/item/clothing/head/soft/black, /obj/item/clothing/head/soft/black, /obj/item/clothing/head/soft/black, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/clothing/glasses/sunglasses, /obj/item/clothing/glasses/heat, /turf/open/floor/iron/dark/herringbone, diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index ea63bf1b7fe..f507c0be120 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -472,7 +472,7 @@ /area/awaymission/caves/bmp_asteroid/level_two) "cN" = ( /obj/machinery/door/window/left/directional/east, -/obj/effect/decal/cleanable/xenoblood/xgibs, +/obj/effect/decal/cleanable/blood/gibs/xeno, /turf/open/floor/plating, /area/awaymission/caves/research) "cP" = ( @@ -488,7 +488,7 @@ /turf/open/floor/plating, /area/awaymission/caves/research) "cV" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs, +/obj/effect/decal/cleanable/blood/gibs/xeno, /turf/open/floor/plating, /area/awaymission/caves/research) "cX" = ( @@ -724,7 +724,7 @@ }, /area/awaymission/caves/northblock) "eg" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/floor/iron, /area/awaymission/caves/listeningpost) "eh" = ( @@ -845,7 +845,7 @@ /turf/open/floor/iron, /area/awaymission/caves/listeningpost) "eN" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/awaymission/caves/listeningpost) "eO" = ( @@ -1749,7 +1749,7 @@ /area/awaymission/caves/bmp_asteroid/level_three) "JP" = ( /obj/structure/window/reinforced/spawner/directional/east, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/plating, /area/awaymission/caves/research) "Kq" = ( diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index 5b0bbb0c733..67b5f85ea8f 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -419,7 +419,7 @@ /area/awaymission/moonoutpost19/mines) "cT" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/effect/turf_decal/siding/thinplating_new/light, /turf/open/floor/iron, /area/awaymission/moonoutpost19/arrivals) @@ -1067,7 +1067,7 @@ }, /area/awaymission/moonoutpost19/mines) "hm" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs, +/obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ dir = 1 @@ -1664,7 +1664,7 @@ }, /area/awaymission/moonoutpost19/main) "lp" = ( -/obj/effect/decal/cleanable/xenoblood/xsplatter, +/obj/effect/decal/cleanable/blood/splatter/xeno, /turf/open/misc/asteroid/moon{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251" }, @@ -2161,7 +2161,7 @@ /turf/open/floor/plating, /area/awaymission/moonoutpost19/arrivals) "od" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, +/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body, /turf/open/misc/asteroid/moon{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251" }, @@ -4724,8 +4724,8 @@ }, /area/awaymission/moonoutpost19/arrivals) "Ft" = ( -/obj/effect/decal/cleanable/robot_debris, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, +/obj/effect/decal/cleanable/blood/oil, /obj/item/storage/medkit/regular{ empty = 1; name = "First-Aid (empty)" @@ -5633,7 +5633,7 @@ /turf/open/floor/iron/white, /area/awaymission/moonoutpost19/research) "LW" = ( -/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." }, @@ -5782,7 +5782,7 @@ /turf/open/floor/iron, /area/awaymission/moonoutpost19/research) "Nm" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/moonoutpost19/arrivals) "No" = ( @@ -5841,7 +5841,7 @@ desc = "Remains of the historical mech that first touched down on Moon Outpost 19. Completely irreparable, but perhaps something can be salvaged."; name = "\improper Historical Ripley MK-II wreckage" }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/food/grown/moonflower{ pixel_x = 7; pixel_y = -18 @@ -6214,7 +6214,7 @@ }, /area/awaymission/moonoutpost19/main) "Pu" = ( -/obj/effect/decal/cleanable/xenoblood{ +/obj/effect/decal/cleanable/blood/xeno{ desc = "It's green and acidic. Nothing good could come of this..." }, /obj/structure/fluff/meteor/large, @@ -7174,7 +7174,7 @@ }, /area/awaymission/moonoutpost19/main) "VW" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/duct, /turf/open/floor/plating, /area/awaymission/moonoutpost19/arrivals) @@ -7381,7 +7381,7 @@ /turf/open/floor/iron/white, /area/awaymission/moonoutpost19/research) "Xr" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /turf/open/floor/plating, /area/awaymission/moonoutpost19/research) @@ -7433,7 +7433,7 @@ }, /area/awaymission/moonoutpost19/arrivals) "XN" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/limb, +/obj/effect/decal/cleanable/blood/gibs/xeno/limb, /turf/open/misc/asteroid/moon{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251" }, diff --git a/_maps/RandomZLevels/museum.dmm b/_maps/RandomZLevels/museum.dmm index 113fe2b6987..482652c6734 100644 --- a/_maps/RandomZLevels/museum.dmm +++ b/_maps/RandomZLevels/museum.dmm @@ -3910,7 +3910,7 @@ "Fw" = ( /obj/effect/decal/cleanable/blood/tracks{ name = "replica blood"; - should_dry = 0 + can_dry = 0 }, /obj/effect/mapping_helpers/burnt_floor, /obj/effect/decal/cleanable/dirt/dust, @@ -5541,7 +5541,7 @@ "UH" = ( /obj/structure/mirror/broken/directional/east, /obj/structure/sink/directional/west, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/white/small, /area/awaymission/museum) "UI" = ( diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index d9fe59325e4..9ef900b3e01 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -2819,7 +2819,7 @@ /turf/open/floor/iron, /area/awaymission/snowdin/post/garage) "kl" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/snowdin/post/garage) "km" = ( @@ -3029,7 +3029,7 @@ /area/awaymission/snowdin/post/garage) "lc" = ( /obj/vehicle/ridden/atv, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/snowdin/post/garage) "ld" = ( @@ -6616,7 +6616,7 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_dock) "zy" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/snowdin/post/minipost) "zz" = ( @@ -8254,7 +8254,7 @@ /turf/open/floor/iron, /area/awaymission/snowdin/post/mining_main/mechbay) "Hd" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/awaymission/snowdin/post/mining_main/mechbay) "He" = ( @@ -8332,7 +8332,7 @@ /turf/open/floor/iron, /area/awaymission/snowdin/post/mining_main/mechbay) "HA" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_main/mechbay) "HB" = ( @@ -8397,7 +8397,7 @@ /area/awaymission/snowdin/post/mining_main/mechbay) "HP" = ( /obj/effect/turf_decal/stripes/line, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/awaymission/snowdin/post/mining_main/mechbay) "HQ" = ( @@ -8519,7 +8519,7 @@ /obj/vehicle/ridden/atv{ dir = 1 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_main) "Iy" = ( @@ -8579,7 +8579,7 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_main) "II" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_main) diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index bb612f1c84b..b9623993cef 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -17529,7 +17529,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/aft) "ggn" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/byteforge, /obj/effect/turf_decal/box, /turf/open/floor/iron/dark/smooth_large, @@ -29104,7 +29104,7 @@ /turf/open/floor/iron/cafeteria, /area/station/science/circuits) "jJW" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/item/stack/sheet/cardboard, /turf/open/floor/iron, /area/station/maintenance/department/engine/atmos) @@ -36361,7 +36361,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/structure/broken_flooring/singular/directional/south, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/item/crowbar, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, diff --git a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm index f83d88f8bdb..1f626e54208 100644 --- a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm +++ b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm @@ -2787,7 +2787,7 @@ /area/station/maintenance/disposal/incinerator) "aUC" = ( /obj/effect/decal/cleanable/glitter, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/spawner/random/maintenance/two, /obj/structure/rack, /turf/open/floor/plating, @@ -5057,7 +5057,7 @@ /turf/open/floor/carpet, /area/station/service/janitor) "bCl" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/port/greater) "bCv" = ( @@ -15336,7 +15336,7 @@ /area/space/nearstation) "eCz" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "eCD" = ( @@ -16356,7 +16356,7 @@ /turf/open/floor/iron/dark/textured, /area/station/science/xenobiology) "eUg" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/dark/smooth_large, /area/station/maintenance/port) "eUh" = ( @@ -17331,7 +17331,7 @@ /turf/open/floor/plating, /area/station/maintenance/port/fore) "fkv" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/iron/dark, /area/station/engineering/engine_smes) "fkw" = ( @@ -31819,7 +31819,7 @@ /turf/open/floor/glass, /area/station/commons/fitness/recreation) "jvU" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den) "jvX" = ( @@ -32273,7 +32273,7 @@ "jAX" = ( /obj/vehicle/sealed/mecha/ripley/paddy/preset, /obj/effect/turf_decal/bot, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt/dust, /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron/small, @@ -33190,7 +33190,7 @@ /area/station/hallway/primary/central) "jOq" = ( /obj/effect/spawner/random/maintenance, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "jOE" = ( @@ -33344,7 +33344,7 @@ /area/station/security/brig) "jRj" = ( /obj/structure/sign/poster/random/directional/north, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /obj/machinery/camera/autoname/directional/north, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -33629,7 +33629,7 @@ /area/station/science/xenobiology) "jWc" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating, /area/station/maintenance/solars/port/aft) "jWg" = ( @@ -35071,7 +35071,7 @@ /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) "ksx" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/textured_edge{ dir = 8 }, @@ -36782,7 +36782,7 @@ "kVm" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/cigbutt{ pixel_x = 8; pixel_y = -2 @@ -37448,7 +37448,7 @@ /turf/open/floor/iron, /area/station/cargo/miningoffice) "leY" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/closet/firecloset, /obj/effect/turf_decal/bot, /turf/open/floor/iron, @@ -38495,7 +38495,7 @@ /obj/structure/railing{ dir = 1 }, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -41316,7 +41316,7 @@ /turf/open/floor/iron/dark, /area/station/engineering/atmos/upper) "mlG" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/plating, /area/station/engineering/supermatter/room) "mlL" = ( @@ -45071,8 +45071,8 @@ /turf/open/floor/wood, /area/station/ai_monitored/command/storage/eva) "nuF" = ( -/obj/effect/decal/cleanable/oil, /obj/structure/closet/crate/trashcart/filled, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/very_dim/directional/north, /turf/open/floor/plating, /area/station/maintenance/disposal) @@ -49416,7 +49416,7 @@ /turf/open/floor/catwalk_floor/iron_dark, /area/station/ai_monitored/turret_protected/ai) "oKc" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -50284,7 +50284,7 @@ "oVZ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/cigbutt{ pixel_x = -12; pixel_y = 11 @@ -50402,7 +50402,7 @@ /obj/machinery/computer/slot_machine{ pixel_y = 2 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "oYn" = ( @@ -57394,7 +57394,7 @@ /obj/machinery/recycler{ dir = 8 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/disposal) "rhx" = ( @@ -59114,7 +59114,7 @@ /area/station/maintenance/starboard/aft) "rFs" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/construction/storage_wing) @@ -59360,7 +59360,7 @@ name = "forgotten exosuit fabricator" }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "rIZ" = ( @@ -60938,7 +60938,7 @@ output_dir = 1 }, /obj/structure/window/reinforced/spawner/directional/south, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/disposal) "shR" = ( @@ -62128,7 +62128,7 @@ }, /area/station/service/library) "sCg" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/department/engine) "sCv" = ( @@ -63673,7 +63673,7 @@ "taZ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "tbf" = ( @@ -64738,7 +64738,7 @@ "tts" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/maintenance, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "ttx" = ( @@ -65998,7 +65998,7 @@ pixel_y = -2 }, /obj/item/stack/cable_coil, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/smooth_large, /area/station/ai_monitored/turret_protected/ai_upload) @@ -75613,7 +75613,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/small, /area/station/security/mechbay) @@ -78332,7 +78332,7 @@ name = "Mr Johnson" }, /obj/structure/spider/stickyweb, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/plating, /area/station/maintenance/port/greater) "xtC" = ( @@ -80603,7 +80603,7 @@ /turf/open/floor/iron, /area/station/command/heads_quarters/qm) "ycp" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/extinguisher_cabinet/directional/north, /turf/open/floor/iron/dark/smooth_large, /area/station/ai_monitored/turret_protected/ai_upload) diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index fa4d824418f..92e91471017 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -1179,7 +1179,7 @@ /obj/item/exodrone, /obj/machinery/exodrone_launcher, /obj/effect/turf_decal/box, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/machinery/status_display/evac/directional/north, /turf/open/floor/plating, /area/station/cargo/drone_bay) @@ -1247,7 +1247,7 @@ /area/station/security/checkpoint/supply) "ape" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 1 }, @@ -1372,7 +1372,7 @@ /area/station/service/chapel) "aqE" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/spawner/random/structure/crate, /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, @@ -2288,7 +2288,7 @@ /turf/open/floor/iron/dark, /area/station/command/heads_quarters/ce) "aBy" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron, /area/station/maintenance/department/security) @@ -2580,7 +2580,7 @@ /area/station/command/teleporter) "aFH" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/bot, /obj/machinery/light/small/directional/south, /turf/open/floor/iron, @@ -4134,7 +4134,7 @@ }, /area/station/service/chapel) "aYR" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/cargo/office) @@ -9482,7 +9482,7 @@ /obj/machinery/light/small/directional/north, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -10195,7 +10195,7 @@ /area/station/engineering/supermatter/room) "cwt" = ( /obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/cargo/storage) @@ -10964,7 +10964,7 @@ /area/station/maintenance/department/engine/atmos) "cFs" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 }, @@ -12412,7 +12412,7 @@ /turf/open/floor/iron/dark, /area/station/service/chapel/storage) "cYT" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, /area/station/maintenance/port) @@ -13353,8 +13353,8 @@ /turf/open/floor/plating, /area/station/maintenance/port/fore) "dlo" = ( -/obj/effect/decal/cleanable/robot_debris/down, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/department/science) "dlp" = ( @@ -15228,7 +15228,7 @@ /turf/open/floor/iron, /area/station/maintenance/starboard/aft) "dKx" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/maintenance/department/crew_quarters/bar) "dKC" = ( @@ -27822,7 +27822,7 @@ /area/station/hallway/secondary/exit/departure_lounge) "gQh" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/storage) @@ -28061,7 +28061,7 @@ /turf/open/floor/engine/vacuum, /area/station/science/ordnance/burnchamber) "gTq" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /obj/effect/spawner/random/engineering/tank, /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -28211,7 +28211,7 @@ /area/station/science/circuits) "gUE" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/science/robotics/mechbay) @@ -32853,7 +32853,7 @@ /turf/open/floor/iron/white, /area/station/medical/virology) "iga" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -37522,7 +37522,7 @@ /area/station/engineering/atmos/pumproom) "joa" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/science/research/abandoned) @@ -39467,7 +39467,7 @@ /turf/open/floor/iron, /area/station/commons/storage/primary) "jMM" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/engineering/supermatter/room) "jMQ" = ( @@ -40995,7 +40995,7 @@ /obj/effect/turf_decal/stripes/corner{ dir = 1 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/engineering/atmos/hfr_room) "kfQ" = ( @@ -41714,7 +41714,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -43335,7 +43335,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/checker, /area/station/engineering/supermatter/room) @@ -43876,7 +43876,7 @@ /turf/closed/wall/r_wall, /area/station/engineering/gravity_generator) "kUg" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/delivery, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -44022,7 +44022,7 @@ /turf/closed/wall, /area/station/hallway/secondary/service) "kVT" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/port) "kVZ" = ( @@ -47540,7 +47540,7 @@ "lNc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/cargo/warehouse) "lNd" = ( @@ -48137,7 +48137,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/science/research/abandoned) @@ -49968,7 +49968,7 @@ /area/station/medical/pharmacy) "mwA" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/smooth, /area/station/maintenance/department/science/xenobiology) "mwK" = ( @@ -51758,7 +51758,7 @@ /turf/open/floor/iron/dark, /area/station/service/abandoned_gambling_den) "mSY" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/structure/table, /obj/item/storage/toolbox/mechanical{ pixel_y = 7 @@ -53208,7 +53208,7 @@ /turf/open/floor/iron/white, /area/station/security/prison/toilet) "nnZ" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -55269,7 +55269,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/engineering/supermatter/room) "nPa" = ( @@ -59087,7 +59087,7 @@ "oQw" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/engineering/supermatter/room) "oQJ" = ( @@ -59421,7 +59421,7 @@ /obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/structure/curtain/bounty{ pixel_y = 32 }, @@ -59830,7 +59830,7 @@ /area/station/hallway/primary/fore) "pbn" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/corner{ dir = 4 }, @@ -60822,7 +60822,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/airalarm/directional/north, @@ -61657,7 +61657,7 @@ /turf/open/floor/plating, /area/station/maintenance/fore) "pyd" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 8 }, @@ -64347,7 +64347,7 @@ /turf/open/floor/iron/white, /area/station/science/research) "qbj" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/corner{ dir = 4 }, @@ -64890,7 +64890,7 @@ "qje" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 }, @@ -67283,7 +67283,7 @@ /turf/closed/wall, /area/station/commons/fitness/recreation) "qOr" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/science) @@ -67889,7 +67889,7 @@ /area/station/science/lab) "qYn" = ( /obj/effect/turf_decal/stripes/line, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/science/research/abandoned) "qYo" = ( @@ -69641,7 +69641,7 @@ /turf/open/floor/iron/dark, /area/station/engineering/transit_tube) "rvu" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/engineering/tracking_beacon, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -71195,7 +71195,7 @@ /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) "rOU" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/reflector/single, /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/burnt_floor, @@ -71879,7 +71879,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/cargo/sorting) "rWo" = ( @@ -72644,7 +72644,7 @@ /turf/open/floor/plating, /area/station/maintenance/port/aft) "sfE" = ( -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/engine/xenobio, /area/station/science/xenobiology) "sfH" = ( @@ -74234,7 +74234,7 @@ /area/station/service/barber) "sAi" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/structure/sign/warning/xeno_mining/directional/north, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron/smooth, @@ -76359,7 +76359,7 @@ "tcd" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/bot, /obj/machinery/mineral/stacking_unit_console{ pixel_x = 32 @@ -80893,7 +80893,7 @@ /turf/open/floor/iron, /area/station/security/checkpoint/escape) "ujT" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 1 }, @@ -80998,7 +80998,7 @@ /turf/open/floor/plating, /area/station/engineering/transit_tube) "ulE" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/event_spawn, /turf/open/floor/engine, @@ -84046,7 +84046,7 @@ /area/station/command/bridge) "uWm" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/structure/sign/warning/xeno_mining/directional/south, /turf/open/floor/iron/smooth, /area/station/maintenance/department/science/xenobiology) @@ -85839,7 +85839,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/camera/directional/north{ c_tag = "Engineering - Freezers"; name = "engineering camera"; @@ -87988,7 +87988,7 @@ /area/station/maintenance/department/medical/morgue) "vWQ" = ( /obj/machinery/netpod, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/sign/poster/contraband/random/directional/south, /turf/open/floor/catwalk_floor/iron_dark, /area/station/cargo/bitrunning/den) @@ -88536,7 +88536,7 @@ /turf/open/floor/iron/white, /area/station/science/research) "weM" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/broken/directional/north, /obj/effect/turf_decal/tile/neutral/half{ dir = 1 @@ -89835,7 +89835,7 @@ /area/station/ai_monitored/security/armory) "wtH" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "wtS" = ( @@ -91840,7 +91840,7 @@ dir = 8 }, /obj/item/radio/intercom/directional/south, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 }, @@ -94958,7 +94958,7 @@ }, /obj/item/radio/intercom/directional/south, /obj/machinery/power/apc/auto_name/directional/east, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/engineering/atmos/hfr_room) "xHx" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 305b12ac07b..3b888765e12 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -6159,7 +6159,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/port/aft) "bGm" = ( @@ -6443,7 +6443,7 @@ /area/station/service/library) "bJX" = ( /obj/effect/decal/cleanable/generic, -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /turf/open/floor/iron/checker, /area/station/maintenance/port/fore) "bKp" = ( @@ -17372,7 +17372,7 @@ /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/north, /obj/machinery/quantum_server, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/iron/dark/smooth_corner{ dir = 4 }, @@ -18183,7 +18183,7 @@ /turf/open/floor/iron/dark, /area/station/service/hydroponics) "fcI" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/aft) @@ -25509,7 +25509,7 @@ /area/station/commons/dorms/laundry) "hkQ" = ( /obj/structure/table/optable, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/iron/dark, /area/station/medical/morgue) "hkS" = ( @@ -31772,7 +31772,7 @@ /area/station/security/prison) "jaX" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 8 }, @@ -33153,7 +33153,7 @@ /obj/effect/turf_decal/tile/brown{ dir = 1 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark, /area/station/maintenance/disposal) "jwF" = ( @@ -36428,7 +36428,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/fore) "ksb" = ( @@ -39901,7 +39901,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "lqL" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) "lqM" = ( @@ -58567,7 +58567,7 @@ /turf/open/floor/iron/cafeteria, /area/mine/laborcamp) "qDF" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/smooth, /area/station/maintenance/department/chapel) "qDG" = ( @@ -60630,7 +60630,7 @@ dir = 8 }, /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/wrench, /obj/effect/turf_decal/tile/dark{ dir = 8 @@ -61652,7 +61652,7 @@ /area/station/maintenance/department/chapel) "rtq" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/radio/intercom/directional/south, /turf/open/floor/iron/checker, /area/station/maintenance/port/fore) @@ -62195,7 +62195,7 @@ /turf/open/floor/iron/white, /area/station/maintenance/port/fore) "rCB" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -65003,7 +65003,7 @@ /obj/machinery/airalarm/directional/west, /obj/effect/landmark/start/bitrunner, /obj/machinery/light/small/directional/south, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/iron/dark/textured_large, /area/station/cargo/bitrunning/den) "srP" = ( @@ -65301,7 +65301,7 @@ /turf/open/floor/iron/dark, /area/station/medical/morgue) "svy" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/stack/ore/glass, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -68594,7 +68594,7 @@ /area/station/hallway/secondary/exit/departure_lounge) "tsR" = ( /obj/structure/chair/stool/directional/south, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating, /area/station/maintenance/department/electrical) "ttb" = ( @@ -78617,7 +78617,7 @@ dir = 1 }, /obj/machinery/holopad, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/textured_large, /area/station/cargo/bitrunning/den) "wuA" = ( @@ -80529,7 +80529,7 @@ /turf/open/floor/engine, /area/station/engineering/supermatter/room) "wWc" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/structure/tank_holder, /turf/open/floor/plating, @@ -82343,7 +82343,7 @@ "xwq" = ( /obj/structure/reagent_dispensers/fueltank, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) "xwr" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 6a8dc34839d..6601f98e0db 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -11788,7 +11788,7 @@ /turf/open/floor/iron/white, /area/station/medical/treatment_center) "eks" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light_switch/directional/east, /turf/open/floor/plating, /area/station/maintenance/disposal) @@ -14434,7 +14434,7 @@ /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/blood/gibs/down, /mob/living/simple_animal/bot/mulebot{ name = "Leaping Rabbit" @@ -16607,7 +16607,7 @@ /area/station/security/prison) "fXZ" = ( /obj/effect/turf_decal/delivery, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/turf_decal/trimline/brown/filled/arrow_cw, /turf/open/floor/iron, /area/station/cargo/storage) @@ -18763,7 +18763,7 @@ /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "gLm" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/spawner/random/engineering/tank, /obj/machinery/light/small/dim/directional/west, /turf/open/floor/plating, @@ -21154,7 +21154,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/port) "hCK" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/siding/purple{ dir = 1 }, @@ -23528,7 +23528,7 @@ /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) "itn" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/engine, /area/station/science/explab) "itp" = ( @@ -45468,7 +45468,7 @@ /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) "qeZ" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /turf/open/floor/wood, /area/station/command/corporate_showroom) @@ -46149,7 +46149,7 @@ /turf/open/floor/carpet, /area/station/command/heads_quarters/captain/private) "qrL" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/structure/extinguisher_cabinet/directional/north, /turf/open/floor/iron/dark/smooth_large, @@ -52840,7 +52840,7 @@ /area/station/engineering/main) "sHX" = ( /obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/sorting) @@ -53552,7 +53552,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "sTU" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/maintenance, /obj/effect/turf_decal/bot_white, @@ -59269,7 +59269,7 @@ "uSh" = ( /obj/item/stack/sheet/iron/five, /obj/item/stack/cable_coil/five, -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /obj/effect/turf_decal/box, /turf/open/floor/plating, /area/station/maintenance/port/fore) @@ -59919,7 +59919,7 @@ "vdg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/netpod, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_dark, /area/station/cargo/bitrunning/den) @@ -61704,7 +61704,7 @@ /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) "vHa" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron, /area/station/cargo/warehouse) "vHs" = ( @@ -64109,7 +64109,7 @@ /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/item/chair/wood, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating, /area/station/maintenance/port/fore) "wwW" = ( @@ -67925,7 +67925,7 @@ /area/station/engineering/atmos/pumproom) "xSc" = ( /obj/structure/frame/machine/secured, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/turf_decal/box, /turf/open/floor/plating, /area/station/maintenance/port/fore) @@ -68259,7 +68259,7 @@ /turf/open/floor/iron/dark, /area/station/command/heads_quarters/captain/private) "xXR" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/railing/corner/end{ dir = 8 }, diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm index 1b1de275d48..c91976bafe3 100644 --- a/_maps/map_files/NebulaStation/NebulaStation.dmm +++ b/_maps/map_files/NebulaStation/NebulaStation.dmm @@ -28277,7 +28277,7 @@ pixel_x = -8; pixel_y = 5 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/station/maintenance/fore/lesser) @@ -28378,7 +28378,7 @@ /turf/open/space/openspace, /area/space/nearstation) "ejI" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -51023,7 +51023,7 @@ /turf/open/floor/iron/dark/textured, /area/station/command) "hCg" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/cigbutt/cigarbutt, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/trimline/dark, @@ -65688,7 +65688,7 @@ /turf/open/floor/iron/dark/textured_half, /area/station/science/ordnance) "jLi" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/mapping_helpers/broken_floor, /obj/structure/sign/warning/electric_shock/directional/east, /turf/open/floor/iron, @@ -72897,7 +72897,7 @@ /area/station/security/brig) "kJJ" = ( /obj/structure/rack, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/bot_white, /obj/item/clothing/suit/hazardvest, /obj/item/clothing/suit/hazardvest, @@ -110516,7 +110516,7 @@ }, /area/station/command) "qqh" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -113776,7 +113776,7 @@ /turf/open/floor/wood/tile, /area/station/service/barber) "qOD" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/smooth, /area/station/maintenance/port/central) "qOE" = ( @@ -114606,7 +114606,7 @@ /turf/open/floor/iron, /area/station/cargo/storage) "qWH" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/carpet/red, /area/station/maintenance/starboard/central) "qWR" = ( @@ -121075,7 +121075,7 @@ /turf/open/floor/iron/white, /area/station/science/lower) "rUO" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/engine/hull/reinforced, /area/space/nearstation) "rUT" = ( @@ -129712,7 +129712,7 @@ /turf/open/floor/carpet/royalblue, /area/station/command/corporate_suite) "tmg" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/cigbutt/cigarbutt, /turf/open/floor/engine/hull/reinforced, /area/space/nearstation) @@ -137031,7 +137031,7 @@ /turf/open/floor/iron/white, /area/station/medical/lower) "urz" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/port/central) "urH" = ( @@ -149936,7 +149936,7 @@ "wmi" = ( /obj/structure/rack, /obj/item/storage/toolbox/emergency, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/screwdriver, /obj/effect/turf_decal/bot_white, /turf/open/floor/iron/dark/textured_large, @@ -153604,7 +153604,7 @@ dir = 1 }, /obj/structure/sign/departments/science/directional/south, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/textured_large, /area/station/maintenance/fore/lesser) "wQd" = ( diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 9408693271c..af1ff676467 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -4945,7 +4945,7 @@ dir = 6 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/small/directional/west, /turf/open/floor/iron/smooth_large, /area/centcom/central_command_areas/evacuation/ship) @@ -5564,7 +5564,7 @@ dir = 1 }, /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/smooth_large, /area/centcom/central_command_areas/evacuation/ship) "zb" = ( @@ -6103,7 +6103,7 @@ "Bm" = ( /obj/structure/reagent_dispensers/fueltank, /obj/item/weldingtool/experimental, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, diff --git a/_maps/map_files/tramstation/maintenance_modules/atmoscilower_attachment_a_3.dmm b/_maps/map_files/tramstation/maintenance_modules/atmoscilower_attachment_a_3.dmm index 670386ca829..cdcf962c3c2 100644 --- a/_maps/map_files/tramstation/maintenance_modules/atmoscilower_attachment_a_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/atmoscilower_attachment_a_3.dmm @@ -105,7 +105,7 @@ "y" = ( /obj/effect/decal/cleanable/dirt, /obj/vehicle/sealed/mecha/ripley, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) "A" = ( @@ -176,7 +176,7 @@ /area/station/maintenance/starboard/lesser) "Q" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/stock_parts/power_store/cell/empty, /obj/item/screwdriver{ pixel_y = -10; diff --git a/_maps/map_files/tramstation/maintenance_modules/cargoscilower_1.dmm b/_maps/map_files/tramstation/maintenance_modules/cargoscilower_1.dmm index 4e78a2717af..30be136452c 100644 --- a/_maps/map_files/tramstation/maintenance_modules/cargoscilower_1.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/cargoscilower_1.dmm @@ -104,7 +104,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/small/directional/south, /turf/open/floor/plating, /area/station/maintenance/starboard/central) @@ -282,7 +282,7 @@ /area/station/maintenance/starboard/central) "uB" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/mineral/titanium/blue, /area/station/maintenance/starboard/central) "vk" = ( @@ -399,7 +399,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/station/maintenance/starboard/central) "JD" = ( diff --git a/_maps/map_files/tramstation/maintenance_modules/cargoscilower_3.dmm b/_maps/map_files/tramstation/maintenance_modules/cargoscilower_3.dmm index 53d727123ce..18e7138664c 100644 --- a/_maps/map_files/tramstation/maintenance_modules/cargoscilower_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/cargoscilower_3.dmm @@ -56,7 +56,7 @@ /turf/open/floor/iron, /area/station/maintenance/starboard/central) "fv" = ( -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/loading_area{ dir = 8 @@ -374,7 +374,7 @@ /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 1 }, -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/maintenance/starboard/central) @@ -449,7 +449,7 @@ /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 1 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, diff --git a/_maps/map_files/tramstation/maintenance_modules/medsciupper_attachment_a_1.dmm b/_maps/map_files/tramstation/maintenance_modules/medsciupper_attachment_a_1.dmm index f58d6cd2a20..23efbb97bf1 100644 --- a/_maps/map_files/tramstation/maintenance_modules/medsciupper_attachment_a_1.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/medsciupper_attachment_a_1.dmm @@ -4,7 +4,7 @@ /area/template_noop) "e" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/item/wrench, /turf/open/floor/plating, /area/station/maintenance/department/science) @@ -17,7 +17,7 @@ /obj/effect/decal/cleanable/dirt, /obj/structure/mecha_wreckage/ripley/mk2, /obj/effect/turf_decal/bot, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/station/maintenance/department/science) "l" = ( diff --git a/_maps/map_files/tramstation/maintenance_modules/secbarupper_1.dmm b/_maps/map_files/tramstation/maintenance_modules/secbarupper_1.dmm index 0dbec6e9baf..6c18e97d137 100644 --- a/_maps/map_files/tramstation/maintenance_modules/secbarupper_1.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/secbarupper_1.dmm @@ -302,7 +302,7 @@ "Pa" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/spawner/random{ - loot = list(/obj/effect/decal/cleanable/oil/slippery=10,/obj/effect/decal/cleanable/oil=90); + loot = list(/obj/effect/decal/cleanable/blood/oil/slippery=10,/obj/effect/decal/cleanable/blood/oil=90); name = "funny slipper :)" }, /turf/open/floor/plating, diff --git a/_maps/map_files/tramstation/maintenance_modules/secbarupper_2.dmm b/_maps/map_files/tramstation/maintenance_modules/secbarupper_2.dmm index 11e0cd730ca..6b0093caccd 100644 --- a/_maps/map_files/tramstation/maintenance_modules/secbarupper_2.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/secbarupper_2.dmm @@ -335,7 +335,7 @@ }, /obj/effect/turf_decal/trimline/yellow/warning, /obj/effect/spawner/random{ - loot = list(/obj/effect/decal/cleanable/oil/slippery=10,/obj/effect/decal/cleanable/oil=90); + loot = list(/obj/effect/decal/cleanable/blood/oil/slippery=10,/obj/effect/decal/cleanable/blood/oil=90); name = "funny slipper :)" }, /turf/open/floor/iron/smooth, diff --git a/_maps/map_files/tramstation/maintenance_modules/secbarupper_3.dmm b/_maps/map_files/tramstation/maintenance_modules/secbarupper_3.dmm index a4fa633f0f9..9291070132b 100644 --- a/_maps/map_files/tramstation/maintenance_modules/secbarupper_3.dmm +++ b/_maps/map_files/tramstation/maintenance_modules/secbarupper_3.dmm @@ -456,7 +456,7 @@ "Vn" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/spawner/random{ - loot = list(/obj/effect/decal/cleanable/oil/slippery=10,/obj/effect/decal/cleanable/oil=90); + loot = list(/obj/effect/decal/cleanable/blood/oil/slippery=10,/obj/effect/decal/cleanable/blood/oil=90); name = "funny slipper :)" }, /turf/open/floor/plating, diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 950d173846c..170b721a26b 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -3046,7 +3046,7 @@ /obj/effect/turf_decal/trimline/yellow/warning{ dir = 8 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/clothing/glasses/welding, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -11143,7 +11143,7 @@ name = "inactive propulsion engine"; desc = "A standard reliable bluespace engine used by many forms of shuttles. This one has the bluespace core removed." }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, @@ -26251,7 +26251,7 @@ /area/station/asteroid) "itH" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/smooth, /area/station/security/mechbay) @@ -35048,7 +35048,7 @@ /obj/effect/turf_decal/tile/neutral/tram, /obj/effect/spawner/random{ name = "funny slipper :)"; - loot = list(/obj/effect/decal/cleanable/oil/slippery=10, /obj/effect/decal/cleanable/oil=90) + loot = list(/obj/effect/decal/cleanable/blood/oil/slippery=10, /obj/effect/decal/cleanable/blood/oil=90) }, /turf/open/floor/tram/plate, /area/station/hallway/primary/tram/left) @@ -36684,7 +36684,7 @@ dir = 1 }, /obj/structure/extinguisher_cabinet/directional/west, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/landmark/start/bitrunner, /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron/dark/textured_large, @@ -37534,7 +37534,7 @@ /area/station/science/lobby) "mez" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/iron/smooth, /area/station/security/mechbay) @@ -41598,7 +41598,7 @@ /area/station/hallway/secondary/service) "nDY" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/smooth, /area/station/maintenance/port/central) "nEc" = ( @@ -45282,7 +45282,7 @@ /turf/open/floor/iron, /area/station/hallway/secondary/entry) "pbw" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/structure/sign/poster/random/directional/north, /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, @@ -59698,7 +59698,7 @@ /obj/effect/turf_decal/tile/neutral/tram, /obj/effect/spawner/random{ name = "funny slipper :)"; - loot = list(/obj/effect/decal/cleanable/oil/slippery=10, /obj/effect/decal/cleanable/oil=90) + loot = list(/obj/effect/decal/cleanable/blood/oil/slippery=10, /obj/effect/decal/cleanable/blood/oil=90) }, /turf/open/floor/tram/plate, /area/station/hallway/primary/tram/right) diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 541ad5d0958..310e6a5f28b 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -4089,7 +4089,7 @@ /turf/open/floor/iron/white, /area/station/medical/treatment_center) "bvJ" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/spawner/random/entertainment/arcade{ @@ -11431,7 +11431,7 @@ name = "AI Antechamber turret control"; pixel_y = -27 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/blood/old, /turf/open/floor/iron/dark, @@ -17217,7 +17217,7 @@ /area/station/medical/virology) "gcD" = ( /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/item/flashlight/lamp, /turf/open/floor/iron, /area/station/cargo/warehouse/upper) @@ -22950,7 +22950,7 @@ /area/station/medical/virology) "hZO" = ( /obj/structure/table, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt/dust, /obj/item/clothing/head/costume/cardborg, @@ -34429,7 +34429,7 @@ /area/station/engineering/atmospherics_engine) "lXJ" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/radio/intercom/directional/north, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/uppernorth) @@ -35593,7 +35593,7 @@ /area/station/security/brig) "msE" = ( /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/camera/autoname/directional/south, /turf/open/floor/iron, /area/station/cargo/warehouse/upper) @@ -48182,7 +48182,7 @@ /turf/open/floor/wood, /area/station/service/library) "qNU" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/small/directional/west, /turf/open/floor/plating, /area/station/maintenance/port/lesser) @@ -58256,7 +58256,7 @@ /area/station/cargo/storage) "udf" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, @@ -60292,7 +60292,7 @@ /turf/open/floor/iron, /area/station/commons/storage/primary) "uNK" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/blood/tracks, /turf/open/floor/plating, @@ -61918,7 +61918,7 @@ /turf/open/floor/wood/parquet, /area/station/medical/psychology) "vvn" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/small/directional/west, /obj/structure/disposalpipe/segment{ dir = 9 @@ -63602,7 +63602,7 @@ /turf/open/floor/iron/white, /area/station/medical/chemistry/minisat) "vZj" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, /obj/item/reagent_containers/spray/cleaner, diff --git a/_maps/minigame/CTF/downtown.dmm b/_maps/minigame/CTF/downtown.dmm index fd11025e943..94377fd404c 100644 --- a/_maps/minigame/CTF/downtown.dmm +++ b/_maps/minigame/CTF/downtown.dmm @@ -73,7 +73,7 @@ /turf/open/floor/wood, /area/centcom/ctf) "bA" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible{ dir = 4; mouse_opacity = 0; @@ -220,7 +220,7 @@ /area/centcom/ctf) "ff" = ( /obj/effect/turf_decal/siding/white, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/barricade/sandbags{ resistance_flags = 64 }, @@ -354,7 +354,7 @@ /area/centcom/ctf) "hF" = ( /obj/effect/turf_decal/siding/yellow, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark, /area/centcom/ctf) "hK" = ( @@ -1016,7 +1016,7 @@ /turf/open/floor/wood, /area/centcom/ctf) "xD" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/barricade/security/ctf, /obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible{ dir = 4; @@ -1038,7 +1038,7 @@ /area/centcom/ctf) "yp" = ( /obj/effect/turf_decal/siding/yellow, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/barricade/security/ctf, /turf/open/floor/iron/dark, /area/centcom/ctf) @@ -1687,7 +1687,7 @@ /area/centcom/ctf) "KV" = ( /obj/effect/turf_decal/siding/white, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark, /area/centcom/ctf) "Ll" = ( @@ -1812,7 +1812,7 @@ /turf/open/floor/iron, /area/centcom/ctf) "Oc" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/centcom/ctf) "Oe" = ( @@ -1911,7 +1911,7 @@ /turf/open/floor/iron, /area/centcom/ctf) "Qw" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark, /area/centcom/ctf) "QC" = ( diff --git a/_maps/minigame/basketball/greytide_worldwide.dmm b/_maps/minigame/basketball/greytide_worldwide.dmm index 6711c66743d..3c9ce6ad692 100644 --- a/_maps/minigame/basketball/greytide_worldwide.dmm +++ b/_maps/minigame/basketball/greytide_worldwide.dmm @@ -177,7 +177,7 @@ /area/centcom/basketball) "ku" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/spawner/random/structure/chair_maintenance{ dir = 1 }, @@ -419,7 +419,7 @@ /turf/closed/indestructible/fakeglass, /area/centcom/basketball) "CD" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/centcom/basketball) "De" = ( @@ -482,7 +482,7 @@ /area/centcom/basketball) "HH" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/centcom/basketball) "Ic" = ( diff --git a/_maps/minigame/basketball/lusty_xenomorphs.dmm b/_maps/minigame/basketball/lusty_xenomorphs.dmm index f3550c0c15f..498de4c8e86 100644 --- a/_maps/minigame/basketball/lusty_xenomorphs.dmm +++ b/_maps/minigame/basketball/lusty_xenomorphs.dmm @@ -6,7 +6,7 @@ /area/centcom/basketball) "aw" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/iron/white, /area/centcom/basketball) "be" = ( @@ -70,7 +70,7 @@ /area/centcom/basketball) "eU" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs, +/obj/effect/decal/cleanable/blood/gibs/xeno, /turf/open/floor/iron/white, /area/centcom/basketball) "fi" = ( @@ -223,7 +223,7 @@ "qU" = ( /obj/structure/sign/xenobio_guide/directional/west, /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/down, +/obj/effect/decal/cleanable/blood/gibs/xeno/down, /turf/open/floor/iron/white, /area/centcom/basketball) "rT" = ( @@ -254,7 +254,7 @@ /area/centcom/basketball) "tU" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/limb, +/obj/effect/decal/cleanable/blood/gibs/xeno/limb, /turf/open/floor/iron/white, /area/centcom/basketball) "tX" = ( @@ -279,7 +279,7 @@ /turf/open/floor/iron/white, /area/centcom/basketball) "wZ" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/larva, +/obj/effect/decal/cleanable/blood/gibs/xeno/larva, /turf/open/floor/engine, /area/centcom/basketball) "zy" = ( @@ -344,7 +344,7 @@ /area/centcom/basketball) "CD" = ( /obj/structure/alien/weeds, -/obj/effect/decal/cleanable/xenoblood/xgibs/core, +/obj/effect/decal/cleanable/blood/gibs/xeno/core, /turf/open/floor/iron/white, /area/centcom/basketball) "CV" = ( @@ -398,7 +398,7 @@ /turf/open/floor/iron/white, /area/centcom/basketball) "IA" = ( -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/engine, /area/centcom/basketball) "Jc" = ( @@ -541,7 +541,7 @@ /turf/open/floor/iron/white, /area/centcom/basketball) "Uv" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/torso, +/obj/effect/decal/cleanable/blood/gibs/xeno/torso, /turf/open/floor/engine, /area/centcom/basketball) "Uy" = ( diff --git a/_maps/minigame/basketball/soviet_bear.dmm b/_maps/minigame/basketball/soviet_bear.dmm index 36f47288a03..a612daa3653 100644 --- a/_maps/minigame/basketball/soviet_bear.dmm +++ b/_maps/minigame/basketball/soviet_bear.dmm @@ -29,7 +29,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/lead_pipe, /turf/open/floor/plating, /area/centcom/basketball) @@ -121,7 +121,7 @@ /turf/open/floor/iron/dark/small, /area/centcom/basketball) "hB" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating, /area/centcom/basketball) "jj" = ( @@ -191,7 +191,7 @@ /turf/open/floor/plating, /area/centcom/basketball) "mV" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/centcom/basketball) @@ -257,7 +257,7 @@ /turf/open/floor/plating, /area/centcom/basketball) "tU" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/plating, /area/centcom/basketball) "tX" = ( @@ -283,7 +283,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/decal/cleanable/dirt, /obj/item/shard, /turf/open/floor/plating, diff --git a/_maps/minigame/deathmatch/maint_mania.dmm b/_maps/minigame/deathmatch/maint_mania.dmm index 914006c3cb8..b742b695c14 100644 --- a/_maps/minigame/deathmatch/maint_mania.dmm +++ b/_maps/minigame/deathmatch/maint_mania.dmm @@ -259,7 +259,7 @@ /turf/open/indestructible, /area/deathmatch) "FH" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/indestructible, /area/deathmatch) "FL" = ( diff --git a/_maps/minigame/deathmatch/meta_brig.dmm b/_maps/minigame/deathmatch/meta_brig.dmm index a17b4ded433..81d88229a11 100644 --- a/_maps/minigame/deathmatch/meta_brig.dmm +++ b/_maps/minigame/deathmatch/meta_brig.dmm @@ -62,7 +62,7 @@ /turf/open/floor/carpet, /area/deathmatch) "aI" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron/grimy, /area/deathmatch) "aR" = ( @@ -275,7 +275,7 @@ /area/deathmatch) "dN" = ( /obj/effect/turf_decal/trimline/red/filled/corner, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/indestructible/dark, /area/deathmatch) "ew" = ( @@ -1152,7 +1152,7 @@ /obj/structure/disposalpipe/segment{ dir = 1 }, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/indestructible, /area/deathmatch) "sb" = ( @@ -3290,7 +3290,7 @@ /turf/open/floor/plating, /area/deathmatch) "Wp" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/indestructible, /area/deathmatch) "Wv" = ( @@ -3407,7 +3407,7 @@ /area/deathmatch) "XL" = ( /obj/structure/cable, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/indestructible, /area/deathmatch) "XS" = ( @@ -3619,7 +3619,7 @@ /turf/open/indestructible, /area/deathmatch) "ZO" = ( -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /turf/open/floor/plating, /area/deathmatch) diff --git a/_maps/minigame/deathmatch/ragnarok.dmm b/_maps/minigame/deathmatch/ragnarok.dmm index 89273eb45ad..a7e8652ddcf 100644 --- a/_maps/minigame/deathmatch/ragnarok.dmm +++ b/_maps/minigame/deathmatch/ragnarok.dmm @@ -418,7 +418,7 @@ "rh" = ( /obj/structure/fluff/clockwork/alloy_shards/medium, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/misc/asteroid/moon, /area/deathmatch) "rm" = ( diff --git a/_maps/minigame/deathmatch/species_warfare.dmm b/_maps/minigame/deathmatch/species_warfare.dmm index 66e7e9b2275..d452a28d41d 100644 --- a/_maps/minigame/deathmatch/species_warfare.dmm +++ b/_maps/minigame/deathmatch/species_warfare.dmm @@ -194,7 +194,7 @@ /area/deathmatch) "hG" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/item/mecha_parts/mecha_equipment/ripleyupgrade, /turf/open/floor/iron/dark, /area/deathmatch) @@ -743,7 +743,7 @@ "Ag" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/tile/purple/half/contrasted, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/indestructible/white, /area/deathmatch) "AE" = ( diff --git a/_maps/modular_generic/beach_l_ribs.dmm b/_maps/modular_generic/beach_l_ribs.dmm index 69992c2ed76..d857c840a20 100644 --- a/_maps/modular_generic/beach_l_ribs.dmm +++ b/_maps/modular_generic/beach_l_ribs.dmm @@ -37,7 +37,7 @@ "fi" = ( /obj/structure/reagent_dispensers/fueltank, /obj/effect/decal/cleanable/fuel_pool, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/beach/sand, /area/template_noop) "fw" = ( @@ -372,7 +372,7 @@ /obj/structure/statue/bone/rib{ dir = 1 }, -/obj/effect/decal/cleanable/xenoblood{ +/obj/effect/decal/cleanable/blood/xeno{ icon_state = "floor4" }, /turf/open/misc/asteroid{ @@ -522,7 +522,7 @@ /area/template_noop) "OJ" = ( /obj/structure/statue/bone/rib, -/obj/effect/decal/cleanable/xenoblood{ +/obj/effect/decal/cleanable/blood/xeno{ icon_state = "floor5" }, /turf/open/misc/asteroid{ @@ -540,7 +540,7 @@ /area/template_noop) "PS" = ( /obj/structure/statue/bone/rib, -/obj/effect/decal/cleanable/xenoblood{ +/obj/effect/decal/cleanable/blood/xeno{ icon_state = "floor7" }, /obj/effect/turf_decal/trimline/dark/warning{ @@ -669,7 +669,7 @@ /obj/effect/turf_decal/weather/sand{ dir = 4 }, -/obj/effect/decal/cleanable/xenoblood{ +/obj/effect/decal/cleanable/blood/xeno{ icon_state = "floor5" }, /obj/effect/turf_decal/trimline/dark/warning{ diff --git a/_maps/modular_generic/ice_s_freezer.dmm b/_maps/modular_generic/ice_s_freezer.dmm index b150be62220..ec8aef221d9 100644 --- a/_maps/modular_generic/ice_s_freezer.dmm +++ b/_maps/modular_generic/ice_s_freezer.dmm @@ -89,7 +89,7 @@ /turf/template_noop, /area/template_noop) "M" = ( -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/item/food/meat/slab/meatproduct{ pixel_y = 6; pixel_x = 6 diff --git a/_maps/modular_generic/jungle_m_armory.dmm b/_maps/modular_generic/jungle_m_armory.dmm index a99a173cc8a..39090181945 100644 --- a/_maps/modular_generic/jungle_m_armory.dmm +++ b/_maps/modular_generic/jungle_m_armory.dmm @@ -135,7 +135,7 @@ /obj/effect/turf_decal/weather/dirt{ dir = 6 }, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/effect/decal/remains/xeno, /obj/structure/flora/bush/large/style_random{ pixel_y = -3 diff --git a/_maps/modular_generic/station_m_shipping.dmm b/_maps/modular_generic/station_m_shipping.dmm index 0fbfc3f7ddd..f2fdb43ab0f 100644 --- a/_maps/modular_generic/station_m_shipping.dmm +++ b/_maps/modular_generic/station_m_shipping.dmm @@ -4,7 +4,7 @@ dir = 8; name = "Cargo Hold" }, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/iron/smooth, /area/template_noop) "b" = ( @@ -135,7 +135,7 @@ /obj/effect/turf_decal/stripes/corner{ dir = 8 }, -/obj/effect/decal/cleanable/oil/streak{ +/obj/effect/decal/cleanable/blood/splatter/oil{ pixel_x = 1 }, /turf/open/floor/iron/smooth, @@ -167,7 +167,7 @@ /obj/effect/turf_decal/stripes{ dir = 8 }, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/iron/smooth, /area/template_noop) "L" = ( diff --git a/_maps/modular_generic/station_s_chasm.dmm b/_maps/modular_generic/station_s_chasm.dmm index 2865aca985b..655e90077e6 100644 --- a/_maps/modular_generic/station_s_chasm.dmm +++ b/_maps/modular_generic/station_s_chasm.dmm @@ -61,7 +61,7 @@ /area/template_noop) "E" = ( /obj/effect/mapping_helpers/burnt_floor, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/iron, /area/template_noop) "N" = ( diff --git a/_maps/safehouses/dig.dmm b/_maps/safehouses/dig.dmm index aa26f980d60..1a417a5bcf6 100644 --- a/_maps/safehouses/dig.dmm +++ b/_maps/safehouses/dig.dmm @@ -58,7 +58,7 @@ dir = 8 }, /obj/effect/turf_decal/siding/yellow, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/misc/asteroid, /area/virtual_domain/safehouse) "x" = ( diff --git a/_maps/shuttles/cargo_delta.dmm b/_maps/shuttles/cargo_delta.dmm index c12c7c17878..71477acd357 100644 --- a/_maps/shuttles/cargo_delta.dmm +++ b/_maps/shuttles/cargo_delta.dmm @@ -63,7 +63,7 @@ /turf/open/floor/plating, /area/shuttle/supply) "l" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/shuttle/supply) diff --git a/_maps/shuttles/cargo_pubby.dmm b/_maps/shuttles/cargo_pubby.dmm index 4ff003c70b3..45d764e9e1f 100644 --- a/_maps/shuttles/cargo_pubby.dmm +++ b/_maps/shuttles/cargo_pubby.dmm @@ -52,7 +52,7 @@ /area/shuttle/supply) "s" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/chapel{ dir = 1 }, diff --git a/_maps/shuttles/emergency_bballhooper.dmm b/_maps/shuttles/emergency_bballhooper.dmm index cb593436971..49972dccae1 100644 --- a/_maps/shuttles/emergency_bballhooper.dmm +++ b/_maps/shuttles/emergency_bballhooper.dmm @@ -503,7 +503,7 @@ name = "TIMEOUT BOX" }, /obj/effect/mapping_helpers/airlock/access/all/security/general, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) "Cf" = ( diff --git a/_maps/shuttles/emergency_birdshot.dmm b/_maps/shuttles/emergency_birdshot.dmm index 47e5de8ac3a..798dfc02225 100644 --- a/_maps/shuttles/emergency_birdshot.dmm +++ b/_maps/shuttles/emergency_birdshot.dmm @@ -42,7 +42,7 @@ /turf/open/floor/plating/airless, /area/shuttle/escape) "cr" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/glass/reinforced, /area/shuttle/escape) "cX" = ( @@ -198,7 +198,7 @@ dir = 1 }, /obj/effect/spawner/random/structure/crate, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/escape) "iU" = ( @@ -309,7 +309,7 @@ /obj/structure/chair/comfy/shuttle{ dir = 1 }, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/structure/window/reinforced/survival_pod/spawner/directional/south, /turf/open/floor/glass/reinforced, /area/shuttle/escape) @@ -890,7 +890,7 @@ /obj/structure/chair/comfy/shuttle{ dir = 4 }, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/glass/reinforced, /area/shuttle/escape) "UG" = ( diff --git a/_maps/shuttles/emergency_cruise.dmm b/_maps/shuttles/emergency_cruise.dmm index 2558bc9c5bb..b6d635deea2 100644 --- a/_maps/shuttles/emergency_cruise.dmm +++ b/_maps/shuttles/emergency_cruise.dmm @@ -3199,7 +3199,7 @@ "Ra" = ( /obj/structure/extinguisher_cabinet/directional/north, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil{ +/obj/effect/decal/cleanable/blood/oil{ icon_state = "floor5" }, /turf/open/floor/iron, diff --git a/_maps/shuttles/emergency_lance.dmm b/_maps/shuttles/emergency_lance.dmm index 2f62bc945bd..d39e66077bb 100644 --- a/_maps/shuttles/emergency_lance.dmm +++ b/_maps/shuttles/emergency_lance.dmm @@ -1539,7 +1539,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) "WO" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 1 }, diff --git a/_maps/shuttles/emergency_luxury.dmm b/_maps/shuttles/emergency_luxury.dmm index 2eb0e949737..1e57d5f2ce5 100644 --- a/_maps/shuttles/emergency_luxury.dmm +++ b/_maps/shuttles/emergency_luxury.dmm @@ -1,6 +1,6 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "bg" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/shuttle/escape) "bJ" = ( @@ -347,9 +347,9 @@ "qc" = ( /obj/effect/spawner/random/maintenance/eight, /obj/structure/closet/crate/engineering/electrical, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/turf_decal/delivery, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/shuttle/escape) @@ -425,7 +425,7 @@ dir = 1 }, /obj/structure/window/spawner/directional/south, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/light/small/directional/east, /turf/open/floor/iron, /area/shuttle/escape) @@ -488,7 +488,7 @@ "uC" = ( /obj/effect/spawner/random/maintenance/eight, /obj/structure/closet/crate/engineering/electrical, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/turf_decal/delivery, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, @@ -725,7 +725,7 @@ /area/shuttle/escape/luxury) "DP" = ( /obj/effect/decal/cleanable/glass, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/iron, /area/shuttle/escape) "DQ" = ( @@ -782,9 +782,9 @@ "EZ" = ( /obj/effect/spawner/random/maintenance/eight, /obj/structure/closet/crate/preopen, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/turf_decal/delivery, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/shuttle/escape) @@ -855,7 +855,7 @@ "IT" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/generic, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/iron, /area/shuttle/escape) "Jd" = ( @@ -946,7 +946,7 @@ /turf/open/floor/mineral/titanium/white, /area/shuttle/escape/luxury) "Mb" = ( -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /obj/structure/door_assembly, /obj/item/stack/tile/iron/base, /obj/effect/decal/cleanable/dirt, @@ -1191,7 +1191,7 @@ /turf/open/floor/plating, /area/shuttle/escape/luxury) "XY" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/escape) "Yb" = ( diff --git a/_maps/shuttles/emergency_nature.dmm b/_maps/shuttles/emergency_nature.dmm index 16e1b107212..88df39d90b4 100644 --- a/_maps/shuttles/emergency_nature.dmm +++ b/_maps/shuttles/emergency_nature.dmm @@ -277,7 +277,7 @@ /turf/open/floor/plating, /area/shuttle/escape) "iV" = ( -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/turf_decal/stripes/corner{ dir = 4 }, @@ -901,7 +901,7 @@ }, /area/shuttle/escape) "IB" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/turf_decal/stripes/line{ dir = 1 }, diff --git a/_maps/shuttles/emergency_russiafightpit.dmm b/_maps/shuttles/emergency_russiafightpit.dmm index a00f6804bbc..029a3c5c0fa 100644 --- a/_maps/shuttles/emergency_russiafightpit.dmm +++ b/_maps/shuttles/emergency_russiafightpit.dmm @@ -187,7 +187,7 @@ /turf/open/floor/engine, /area/shuttle/escape) "aM" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /obj/machinery/door/poddoor{ id = "bearsbearsbears" }, @@ -212,7 +212,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) "aQ" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/floor/engine, /area/shuttle/escape) "aR" = ( diff --git a/_maps/shuttles/emergency_scrapheap/classic_aft3.dmm b/_maps/shuttles/emergency_scrapheap/classic_aft3.dmm index 20a9fac8161..4eca7aeb766 100644 --- a/_maps/shuttles/emergency_scrapheap/classic_aft3.dmm +++ b/_maps/shuttles/emergency_scrapheap/classic_aft3.dmm @@ -14,7 +14,7 @@ /turf/open/floor/plating/airless, /area/shuttle/escape) "g" = ( -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /obj/effect/decal/cleanable/blood/drip, /obj/structure/falsewall/titanium, /obj/effect/mapping_helpers/burnt_floor, @@ -22,7 +22,7 @@ /turf/open/floor/plating, /area/shuttle/escape) "h" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /turf/open/floor/plating, @@ -105,7 +105,7 @@ /turf/open/floor/plating, /area/shuttle/escape) "D" = ( -/obj/effect/decal/cleanable/blood/trails, +/obj/effect/decal/cleanable/blood/trail_holder, /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 }, @@ -114,13 +114,13 @@ /turf/open/floor/iron/freezer, /area/shuttle/escape) "E" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /turf/template_noop, /area/template_noop) "F" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/effect/decal/cleanable/blood/drip, @@ -173,7 +173,7 @@ /turf/open/floor/iron/freezer, /area/shuttle/escape) "M" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 10 }, /obj/structure/extinguisher_cabinet/directional/south, @@ -196,7 +196,7 @@ /turf/template_noop, /area/shuttle/escape) "T" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 5 }, /obj/item/stack/tile/iron, @@ -238,7 +238,7 @@ /turf/open/floor/iron, /area/shuttle/escape) "Z" = ( -/obj/effect/decal/cleanable/blood/trails{ +/obj/effect/decal/cleanable/blood/trail_holder{ dir = 4 }, /obj/effect/decal/cleanable/blood/drip, diff --git a/_maps/shuttles/hunter_psyker.dmm b/_maps/shuttles/hunter_psyker.dmm index 980bb552122..476e58ce6f8 100644 --- a/_maps/shuttles/hunter_psyker.dmm +++ b/_maps/shuttles/hunter_psyker.dmm @@ -215,7 +215,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/structure/cable, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/hunter) "jB" = ( @@ -226,7 +226,7 @@ /area/shuttle/hunter) "ke" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /turf/open/floor/plating, /area/shuttle/hunter) @@ -898,7 +898,7 @@ /obj/machinery/airalarm/directional/west, /obj/effect/mapping_helpers/airalarm/all_access, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/robot_debris/up, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /turf/open/floor/plating, /area/shuttle/hunter) "RK" = ( diff --git a/_maps/shuttles/infiltrator_advanced.dmm b/_maps/shuttles/infiltrator_advanced.dmm index 1800d638fc5..44742ef5b5b 100644 --- a/_maps/shuttles/infiltrator_advanced.dmm +++ b/_maps/shuttles/infiltrator_advanced.dmm @@ -358,7 +358,7 @@ /obj/structure/reagent_dispensers/fueltank, /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /turf/open/floor/mineral/plastitanium, /area/shuttle/syndicate/eva) @@ -1592,7 +1592,7 @@ /obj/structure/reagent_dispensers/fueltank, /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 182f51ad3b6..432e3e93129 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -398,7 +398,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/pirate) "bf" = ( diff --git a/_maps/shuttles/whiteship_delta.dmm b/_maps/shuttles/whiteship_delta.dmm index b330503ceaf..a83cd9c28b6 100644 --- a/_maps/shuttles/whiteship_delta.dmm +++ b/_maps/shuttles/whiteship_delta.dmm @@ -510,7 +510,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/spider/stickyweb, /turf/open/floor/plating, /area/shuttle/abandoned/engine) @@ -1157,7 +1157,7 @@ /area/shuttle/abandoned/engine) "cC" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/structure/cable, /turf/open/floor/plating, diff --git a/_maps/shuttles/whiteship_donut.dmm b/_maps/shuttles/whiteship_donut.dmm index 1c28cd34818..65402aba73c 100644 --- a/_maps/shuttles/whiteship_donut.dmm +++ b/_maps/shuttles/whiteship_donut.dmm @@ -101,7 +101,7 @@ /area/shuttle/abandoned) "hP" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/stack/cable_coil, /turf/open/floor/iron/airless, /area/shuttle/abandoned) @@ -178,7 +178,7 @@ /area/shuttle/abandoned) "qy" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil/slippery, +/obj/effect/decal/cleanable/blood/oil/slippery, /turf/open/floor/plating/airless, /area/shuttle/abandoned) "rq" = ( @@ -195,7 +195,7 @@ "sg" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/generic, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/airless, /area/shuttle/abandoned) "sw" = ( diff --git a/_maps/shuttles/whiteship_kilo.dmm b/_maps/shuttles/whiteship_kilo.dmm index 350c5cb8f71..590c18e7868 100644 --- a/_maps/shuttles/whiteship_kilo.dmm +++ b/_maps/shuttles/whiteship_kilo.dmm @@ -118,7 +118,7 @@ }, /obj/machinery/light/cold/no_nightlight/directional/south, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /obj/item/bot_assembly/cleanbot, /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -395,7 +395,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/plating, /area/shuttle/abandoned/cargo) "ry" = ( @@ -435,7 +435,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/effect/turf_decal/stripes/corner, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/south, /turf/open/floor/plating, @@ -984,8 +984,8 @@ /area/shuttle/abandoned/crew) "RI" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/oil, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /turf/open/floor/plating, /area/shuttle/abandoned/cargo) "RN" = ( diff --git a/_maps/shuttles/whiteship_meta.dmm b/_maps/shuttles/whiteship_meta.dmm index cbc057ff246..91e83d3e272 100644 --- a/_maps/shuttles/whiteship_meta.dmm +++ b/_maps/shuttles/whiteship_meta.dmm @@ -259,7 +259,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/blood, /obj/effect/decal/remains/human, /turf/open/floor/plating, @@ -1111,7 +1111,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark, /area/shuttle/abandoned/cargo) "dr" = ( @@ -1413,12 +1413,12 @@ /area/shuttle/abandoned/bar) "el" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/abandoned/engine) "em" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark, /area/shuttle/abandoned/cargo) "eD" = ( diff --git a/_maps/shuttles/whiteship_pubby.dmm b/_maps/shuttles/whiteship_pubby.dmm index beb88d5c9d3..2486da85094 100644 --- a/_maps/shuttles/whiteship_pubby.dmm +++ b/_maps/shuttles/whiteship_pubby.dmm @@ -305,7 +305,7 @@ "na" = ( /obj/machinery/light/small/built/directional/east, /obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /turf/open/floor/plating, /area/shuttle/abandoned) diff --git a/_maps/templates/battlecruiser_starfury.dmm b/_maps/templates/battlecruiser_starfury.dmm index 7a28474079a..df92775842b 100644 --- a/_maps/templates/battlecruiser_starfury.dmm +++ b/_maps/templates/battlecruiser_starfury.dmm @@ -1167,7 +1167,7 @@ /area/shuttle/sbc_starfury) "eA" = ( /obj/effect/turf_decal/stripes/line, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/pod/dark, /area/shuttle/sbc_starfury) "eB" = ( @@ -1340,7 +1340,7 @@ /turf/open/floor/plating, /area/shuttle/sbc_starfury) "eY" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -1497,7 +1497,7 @@ dir = 8 }, /obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/textured_large, /area/shuttle/sbc_starfury) "fu" = ( @@ -3441,7 +3441,7 @@ /turf/open/floor/iron, /area/shuttle/sbc_starfury) "lN" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/sbc_starfury) "lO" = ( @@ -3562,7 +3562,7 @@ /area/shuttle/sbc_starfury) "mI" = ( /obj/effect/turf_decal/stripes/line, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/shuttle/sbc_starfury) "mJ" = ( @@ -5355,7 +5355,7 @@ /turf/open/floor/iron/dark, /area/shuttle/sbc_starfury) "Sh" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, diff --git a/_maps/templates/lazy_templates/heretic_sacrifice.dmm b/_maps/templates/lazy_templates/heretic_sacrifice.dmm index 44300c13735..7a752a33e73 100644 --- a/_maps/templates/lazy_templates/heretic_sacrifice.dmm +++ b/_maps/templates/lazy_templates/heretic_sacrifice.dmm @@ -23,7 +23,7 @@ /turf/open/misc/asteroid, /area/centcom/heretic_sacrifice/void) "dX" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/ashplanet/wateryrock{ initial_gas_mix = "o2=22;n2=82;TEMP=293.15"; planetary_atmos = 0; @@ -160,7 +160,7 @@ /obj/effect/turf_decal/weather/dirt{ dir = 9 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/misc/ashplanet/wateryrock{ initial_gas_mix = "o2=22;n2=82;TEMP=293.15"; planetary_atmos = 0; diff --git a/_maps/virtual_domains/abductor_ship.dmm b/_maps/virtual_domains/abductor_ship.dmm index b74435a9ab1..092f8d31400 100644 --- a/_maps/virtual_domains/abductor_ship.dmm +++ b/_maps/virtual_domains/abductor_ship.dmm @@ -214,7 +214,7 @@ /turf/open/floor/plating/abductor, /area/virtual_domain) "yt" = ( -/obj/effect/decal/cleanable/blood/xtracks, +/obj/effect/decal/cleanable/blood/tracks/xeno, /turf/open/floor/plating/abductor, /area/virtual_domain) "zX" = ( @@ -386,7 +386,7 @@ pixel_x = 9; pixel_y = -5 }, -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /turf/open/floor/plating/abductor, /area/virtual_domain) "We" = ( @@ -410,11 +410,11 @@ /turf/open/floor/plating/abductor, /area/virtual_domain) "XU" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/body, +/obj/effect/decal/cleanable/blood/gibs/xeno/body, /turf/open/floor/plating/abductor, /area/virtual_domain) "Yq" = ( -/obj/effect/decal/cleanable/xenoblood/xsplatter, +/obj/effect/decal/cleanable/blood/splatter/xeno, /turf/open/floor/plating/abductor, /area/virtual_domain) "YV" = ( diff --git a/_maps/virtual_domains/clown_planet.dmm b/_maps/virtual_domains/clown_planet.dmm index 37e00bd45fc..76408477f7e 100644 --- a/_maps/virtual_domains/clown_planet.dmm +++ b/_maps/virtual_domains/clown_planet.dmm @@ -701,7 +701,7 @@ /turf/open/floor/carpet, /area/lavaland/surface/outdoors/virtual_domain) "UL" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/structure/disposalpipe/segment{ dir = 10 }, diff --git a/_maps/virtual_domains/fredingtonfastingbear.dmm b/_maps/virtual_domains/fredingtonfastingbear.dmm index 422395c72bc..67b3965ba96 100644 --- a/_maps/virtual_domains/fredingtonfastingbear.dmm +++ b/_maps/virtual_domains/fredingtonfastingbear.dmm @@ -65,7 +65,7 @@ "dN" = ( /obj/effect/turf_decal/tile/blue/opposingcorners, /obj/effect/turf_decal/tile/blue/opposingcorners, -/obj/effect/decal/cleanable/blood/xtracks, +/obj/effect/decal/cleanable/blood/tracks/xeno, /turf/open/floor/iron/kitchen, /area/virtual_domain) "dV" = ( diff --git a/_maps/virtual_domains/island_brawl.dmm b/_maps/virtual_domains/island_brawl.dmm index f9bbc496950..9032dae1ac7 100644 --- a/_maps/virtual_domains/island_brawl.dmm +++ b/_maps/virtual_domains/island_brawl.dmm @@ -306,7 +306,7 @@ pixel_y = 4 }, /obj/item/storage/toolbox/emergency, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/herringbone, /area/virtual_domain) "dA" = ( @@ -648,7 +648,7 @@ /turf/open/misc/beach/sand, /area/virtual_domain/fullbright) "hD" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/machinery/button/door/directional/south{ id = "BeachGarage" }, @@ -2185,7 +2185,7 @@ /obj/item/clothing/head/soft/black, /obj/item/clothing/head/soft/black, /obj/item/clothing/head/soft/black, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /obj/item/clothing/glasses/sunglasses, /obj/item/clothing/glasses/heat, /turf/open/floor/iron/dark/herringbone, @@ -3887,7 +3887,7 @@ /obj/vehicle/ridden/atv{ dir = 4 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron/dark/herringbone, /area/virtual_domain) "UO" = ( diff --git a/_maps/virtual_domains/meta_central.dmm b/_maps/virtual_domains/meta_central.dmm index 5fc9b465c7a..823d9b25184 100644 --- a/_maps/virtual_domains/meta_central.dmm +++ b/_maps/virtual_domains/meta_central.dmm @@ -122,7 +122,7 @@ "aZ" = ( /obj/machinery/airalarm/directional/south, /obj/effect/turf_decal/tile/neutral, -/obj/effect/decal/cleanable/robot_debris/limb, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb, /obj/machinery/exoscanner, /obj/effect/turf_decal/bot_red, /turf/open/floor/iron, @@ -1082,7 +1082,7 @@ /turf/open/floor/iron, /area/virtual_domain) "jh" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/wood, /area/virtual_domain) "jk" = ( @@ -1687,7 +1687,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/decal/cleanable/oil{ +/obj/effect/decal/cleanable/blood/oil{ icon_state = "floor6" }, /obj/structure/railing{ @@ -1852,7 +1852,7 @@ /turf/open/floor/iron, /area/virtual_domain) "pI" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/up, +/obj/effect/decal/cleanable/blood/gibs/xeno/up, /obj/structure/alien/weeds, /turf/open/floor/plating, /area/virtual_domain) @@ -1877,7 +1877,7 @@ /turf/open/indestructible/meat, /area/virtual_domain) "pO" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /obj/effect/decal/cleanable/dirt/dust, /obj/structure/fluff/paper/stack{ dir = 4 @@ -1936,7 +1936,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/effect/decal/cleanable/oil{ +/obj/effect/decal/cleanable/blood/oil{ icon_state = "floor5" }, /turf/open/floor/iron, @@ -2337,7 +2337,7 @@ /turf/open/floor/plating, /area/virtual_domain) "tn" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/core, +/obj/effect/decal/cleanable/blood/gibs/xeno/core, /obj/structure/alien/weeds, /turf/open/floor/plating, /area/virtual_domain) @@ -3485,7 +3485,7 @@ /turf/open/floor/iron, /area/virtual_domain) "CQ" = ( -/obj/effect/decal/cleanable/xenoblood, +/obj/effect/decal/cleanable/blood/xeno, /obj/structure/alien/weeds, /turf/open/floor/plating, /area/virtual_domain) @@ -3758,7 +3758,7 @@ /turf/open/floor/carpet, /area/virtual_domain) "Fr" = ( -/obj/effect/decal/cleanable/xenoblood/xgibs/down, +/obj/effect/decal/cleanable/blood/gibs/xeno/down, /obj/structure/alien/weeds, /turf/open/floor/plating, /area/virtual_domain) @@ -4236,7 +4236,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/decal/cleanable/robot_debris, +/obj/effect/decal/cleanable/blood/gibs/robot_debris, /turf/open/floor/iron, /area/virtual_domain) "JP" = ( @@ -5691,7 +5691,7 @@ "VZ" = ( /obj/structure/extinguisher_cabinet/directional/south, /obj/effect/turf_decal/tile/neutral, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/virtual_domain) "Wf" = ( diff --git a/_maps/virtual_domains/pipedream.dmm b/_maps/virtual_domains/pipedream.dmm index a455ee49aa5..3fd631ca178 100644 --- a/_maps/virtual_domains/pipedream.dmm +++ b/_maps/virtual_domains/pipedream.dmm @@ -587,7 +587,7 @@ /area/virtual_domain) "rJ" = ( /obj/structure/railing, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/virtual_domain) "rM" = ( @@ -615,7 +615,7 @@ /turf/open/floor/iron, /area/virtual_domain) "sW" = ( -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /obj/effect/turf_decal/trimline/yellow/corner{ dir = 1 }, @@ -966,7 +966,7 @@ /turf/open/floor/iron, /area/virtual_domain) "BX" = ( -/obj/effect/decal/cleanable/robot_debris/old, +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old, /turf/open/floor/iron, /area/virtual_domain) "Ci" = ( @@ -1049,7 +1049,7 @@ /obj/effect/turf_decal/stripes{ dir = 8 }, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/iron, /area/virtual_domain) "EJ" = ( @@ -1867,7 +1867,7 @@ /turf/open/floor/iron, /area/virtual_domain) "Zb" = ( -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/plating, /area/virtual_domain) "Zg" = ( diff --git a/_maps/virtual_domains/pirates.dmm b/_maps/virtual_domains/pirates.dmm index 6d429572c7b..12e17b3c68a 100644 --- a/_maps/virtual_domains/pirates.dmm +++ b/_maps/virtual_domains/pirates.dmm @@ -217,7 +217,7 @@ /obj/effect/turf_decal/weather/sand{ dir = 1 }, -/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/blood/splatter/oil, /turf/open/floor/wood, /area/virtual_domain/fullbright) "mp" = ( @@ -412,7 +412,7 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/blood/oil, /turf/open/floor/wood, /area/virtual_domain/fullbright) "wu" = ( diff --git a/code/__DEFINES/blood.dm b/code/__DEFINES/blood.dm index 2c8576a2eda..92753667574 100644 --- a/code/__DEFINES/blood.dm +++ b/code/__DEFINES/blood.dm @@ -9,16 +9,8 @@ #define BLOOD_POOL_MAX 300 /// How much blood a footprint need to at least contain #define BLOOD_FOOTPRINTS_MIN 5 - -//Bloody shoe blood states -/// Red blood -#define BLOOD_STATE_HUMAN "blood" -/// Green xeno blood -#define BLOOD_STATE_XENO "xeno" -/// Black robot oil -#define BLOOD_STATE_OIL "oil" -/// No blood is present -#define BLOOD_STATE_NOT_BLOODY "no blood whatsoever" +/// Bloodiness -> reagent units multiplier +#define BLOOD_TO_UNITS_MULTIPLIER 0.1 // Bitflags for mob dismemberment and gibbing /// Mobs will drop a brain diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 6f664ff848a..a70515e1653 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -217,11 +217,12 @@ #define COLOR_SAMPLE_GRAY "#5e5856" ///Colors for blood greyscale sprites -#define BLOOD_COLOR_RED "#FF291E" // This is lighter than the blood reagent itself because for the greyscale to look the same as before it needs to be the lightest parts of the sprite. -#define BLOOD_COLOR_LIZARD "#047200" -#define BLOOD_COLOR_XENO "#D5FF2C" -#define BLOOD_COLOR_OIL "#262626" -#define BLOOD_COLOR_BLACK "#2C0903" +#define BLOOD_COLOR_RED "#AA1010" +#define BLOOD_COLOR_LIZARD "#035A00" +#define BLOOD_COLOR_XENO "#96BB00" +#define BLOOD_COLOR_OIL "#2C2C2C" +#define BLOOD_COLOR_BLACK "#1F1A00" +#define BLOOD_COLOR_DRIED "#370404" // Not to be used normally, only exists for mapper convinience ///Main colors for UI themes #define COLOR_THEME_MIDNIGHT "#6086A0" diff --git a/code/__DEFINES/dcs/signals/signals_gib.dm b/code/__DEFINES/dcs/signals/signals_gib.dm index aefc908bf1f..a5c54e38de4 100644 --- a/code/__DEFINES/dcs/signals/signals_gib.dm +++ b/code/__DEFINES/dcs/signals/signals_gib.dm @@ -1,5 +1,5 @@ //Gibs ///from base of /obj/effect/decal/cleanable/blood/gibs/streak(): (list/directions, list/diseases) #define COMSIG_GIBS_STREAK "gibs_streak" -/// Called on mobs when they step in blood. (blood_amount, blood_state, list/blood_DNA) +/// Called on mobs when they step in blood. (obj/effect/decal/cleanable/blood/blood) #define COMSIG_STEP_ON_BLOOD "step_on_blood" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index 1aa28be695a..ba3cfe7396c 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -174,3 +174,6 @@ /// Called at the very end of human character setup /// At this point all quirks are assigned and the mob has a mind / client #define COMSIG_HUMAN_CHARACTER_SETUP_FINISHED "human_character_setup_finished" + +/// From /mob/living/carbon/proc/set_blood_type : (mob/living/carbon/user, datum/blood_type, update_cached_blood_dna_info) +#define COMSIG_CARBON_CHANGED_BLOOD_TYPE "carbon_set_blood_type" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 5a6e982d32a..a6ffc9afc5a 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -326,6 +326,3 @@ /// From /obj/item/book/bible/attack() : (mob/living/user, obj/item/book/bible/bible, bless_result) #define COMSIG_LIVING_BLESSED "living_blessed" - -/// From /mob/living/set_blood_type : (mob/living/user, datum/blood_type, update_cached_blood_dna_info) -#define COMSIG_LIVING_CHANGED_BLOOD_TYPE "living_set_blood_type" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 3106afa7975..e7408caa02a 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -11,10 +11,10 @@ #define COMSIG_MOB_MIND_INITIALIZED "mob_mind_inited" ///from base of mob/set_stat(): (new_stat, old_stat) #define COMSIG_MOB_STATCHANGE "mob_statchange" -///from base of mob/reagent_check(): (datum/reagent/chem, seconds_per_tick, times_fired) -#define COMSIG_MOB_REAGENT_CHECK "mob_reagent_check" +///from base of mob/reagent_tick(): (datum/reagent/chem, seconds_per_tick, times_fired) +#define COMSIG_MOB_REAGENT_TICK "mob_reagent_tick" ///stops the reagent check call - #define COMSIG_MOB_STOP_REAGENT_CHECK (1<<0) + #define COMSIG_MOB_STOP_REAGENT_TICK (1<<0) ///from base of mob/clickon(): (atom/A, list/modifiers) #define COMSIG_MOB_CLICKON "mob_clickon" ///from base of mob/MiddleClickOn(): (atom/A) diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 8d91c1b2e6b..7e2954e7d22 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -18,6 +18,10 @@ #define COMSIG_REAGENT_EXPOSE_MOB "reagent_expose_mob" ///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume) #define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf" +///from base of [/datum/reagent/proc/on_merge(data, amount)]: (list/data, amount) +#define COMSIG_REAGENT_ON_MERGE "reagent_on_merge" +///from base of [/datum/reagent/proc/on_transfer_creation(reagent, target_holder, new_reagent)]: (datum/reagents/target_holder, datum/reagent/new_reagent) +#define COMSIG_REAGENT_ON_TRANSFER "reagent_on_transfer" ///from base of [/datum/materials_controller/proc/InitializeMaterial]: (/datum/material) #define COMSIG_MATERIALS_INIT_MAT "SSmaterials_init_mat" diff --git a/code/__DEFINES/dcs/signals/signals_species.dm b/code/__DEFINES/dcs/signals/signals_species.dm index 5c9998a1f80..ba5cde804f7 100644 --- a/code/__DEFINES/dcs/signals/signals_species.dm +++ b/code/__DEFINES/dcs/signals/signals_species.dm @@ -3,6 +3,3 @@ #define COMSIG_SPECIES_GAIN "species_gain" ///from datum/species/on_species_loss(): (datum/species/lost_species) #define COMSIG_SPECIES_LOSS "species_loss" -///from datum/species/handle_chemical(): (datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) -#define COMSIG_SPECIES_HANDLE_CHEMICAL "species_handle_chemicals" - // same return values as COMSIG_MOB_STOP_REAGENT_CHECK diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index b6554bb7beb..9dd06dae572 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -54,6 +54,29 @@ #define BLOOD_TYPE_H2O "H2O" #define BLOOD_TYPE_SNAIL "S" +// Blood exposure behavior flag defines +/// Add our DNA to turfs/mobs/items, does not correlate with adding decals/overlays +/// mob/turf/item flags will add DNA when triggered even if this flag is false +#define BLOOD_ADD_DNA (1<<0) +/// Cover the entire mob in *visible* blood +#define BLOOD_COVER_MOBS (1<<1) +/// Create blood splashes and trails on floors, does not affect gibs creation +#define BLOOD_COVER_TURFS (1<<2) +/// Cover items in ourselves +#define BLOOD_COVER_ITEMS (1<<3) +/// Usually you want all COVER flags together or none at all +#define BLOOD_COVER_ALL (BLOOD_COVER_MOBS | BLOOD_COVER_TURFS | BLOOD_COVER_ITEMS) +/// Transfer blood immunities and viruses to exposed mobs +#define BLOOD_TRANSFER_VIRAL_DATA (1<<4) + +// Bleed check results +/// We cannot bleed (here, or in general) at all +#define BLEED_NONE 0 +/// We cannot make a splatter, but we can add our DNA +#define BLEED_ADD_DNA 1 +/// We can bleed just fine +#define BLEED_SPLATTER 2 + //Sizes of mobs, used by mob/living/var/mob_size #define MOB_SIZE_TINY 0 #define MOB_SIZE_SMALL 1 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 1f4d5497c5f..98d143fd1fe 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -134,6 +134,7 @@ #define FIRE_PRIORITY_RESEARCH 10 #define FIRE_PRIORITY_VIS 10 #define FIRE_PRIORITY_AMBIENCE 10 +#define FIRE_PRIORITY_BLOOD_DRYING 10 #define FIRE_PRIORITY_GARBAGE 15 #define FIRE_PRIORITY_DATABASE 16 #define FIRE_PRIORITY_WET_FLOORS 20 diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 184d9e6d8c4..d788081055b 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1499,6 +1499,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Demolition modifier when hitting this object is inverted (ie, 1 / demolition) #define TRAIT_INVERTED_DEMOLITION "demolition_inverted" +/// Makes the mob immune to carpotoxin +#define TRAIT_CARPOTOXIN_IMMUNE "carpotoxin_immune" + /// Trait given when we escape into our shell #define TRAIT_SHELL_RETREATED "shell_retreated" diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index d1ff5a4f63c..dfe731eddfe 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -381,4 +381,4 @@ rough example of the "cone" made by the 3 dirs checked ) /// Helper for easily adding blood from INSIDE a mob to an atom (NOT blood ON the mob) -#define add_mob_blood(from_who) add_blood_DNA(from_who.get_blood_dna_list()) +#define add_mob_blood(from_who) add_blood_DNA(from_who.get_blood_dna_list(), from_who.get_static_viruses()) diff --git a/code/__HELPERS/forensics.dm b/code/__HELPERS/forensics.dm index 2d43a1ad61b..77b3bd357a6 100644 --- a/code/__HELPERS/forensics.dm +++ b/code/__HELPERS/forensics.dm @@ -4,7 +4,11 @@ #define GET_ATOM_HIDDENPRINTS(atom) atom.forensics?.hiddenprints /// Returns the blood dna on this atom #define GET_ATOM_BLOOD_DNA(atom) atom.forensics?.blood_DNA +/// Returns visible blood dna on this atom +#define GET_ATOM_BLOOD_DECALS(atom) atom.forensics?.get_visible_blood() /// Returns the fibers on this atom #define GET_ATOM_FIBRES(atom) atom.forensics?.fibers /// Returns the number of unique blood dna sources on this atom #define GET_ATOM_BLOOD_DNA_LENGTH(atom) (isnull(atom.forensics) ? 0 : length(atom.forensics.blood_DNA)) +/// Returns the number of *visible* blood dna on this atom +#define GET_ATOM_BLOOD_DECAL_LENGTH(atom) (isnull(atom.forensics) ? 0 : length(atom.forensics.get_visible_blood())) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index bd1caf851c5..20b798ff123 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -8,6 +8,7 @@ /// Returns one of the human blood types at random, weighted by their rarity /proc/random_human_blood_type() + RETURN_TYPE(/datum/blood_type) return get_blood_type(pick_weight( list( BLOOD_TYPE_O_MINUS = 4, diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 158e8ace8f0..4948fac4ba7 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -86,7 +86,7 @@ GLOBAL_LIST_EMPTY(narcd_underages) GLOBAL_LIST_INIT_TYPED(language_datum_instances, /datum/language, init_language_prototypes()) /// List if all language typepaths learnable, IE, those with keys GLOBAL_LIST_INIT(all_languages, init_all_languages()) -// /List of language prototypes to reference, assoc "name" = typepath +/// /List of language prototypes to reference, assoc "name" = typepath GLOBAL_LIST_INIT(language_types_by_name, init_language_types_by_name()) /proc/init_language_prototypes() @@ -114,7 +114,7 @@ GLOBAL_LIST_INIT(language_types_by_name, init_language_types_by_name()) lang_list[initial(lang_type.name)] = lang_type return lang_list -// A list of all the possible blood types, keyed by id (which is just the name in most cases) +/// A list of all the possible blood types, keyed by id (which is just the name in most cases) GLOBAL_LIST_INIT(blood_types, init_blood_types()) /// Initializes the list of blood type singletons diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 1dcaa809043..1d24deae3ff 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -624,6 +624,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_PREVENT_BLINKING" = TRAIT_PREVENT_BLINKING, "TRAIT_PREVENT_BLINK_LOOPS" = TRAIT_PREVENT_BLINK_LOOPS, "TRAIT_NO_EYELIDS" = TRAIT_NO_EYELIDS, + "TRAIT_CARPOTOXIN_IMMUNE" = TRAIT_CARPOTOXIN_IMMUNE, "TRAIT_CRUSHER_MARK_IMMUNE" = TRAIT_CRUSHER_MARK_IMMUNE, // BUBBER EDIT ADDITION ), /mob/dead/observer = list( diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index ff061b6d930..6b76d1f9280 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -343,6 +343,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_IGNORE_FIRE_PROTECTION" = TRAIT_IGNORE_FIRE_PROTECTION, "TRAIT_LEFT_EYE_SCAR" = TRAIT_LEFT_EYE_SCAR, "TRAIT_RIGHT_EYE_SCAR" = TRAIT_RIGHT_EYE_SCAR, + "TRAIT_CARPOTOXIN_IMMUNE" = TRAIT_CARPOTOXIN_IMMUNE, ), /obj/item = list( "TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING, diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index bfe605247bc..0a92ea7091a 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -372,28 +372,31 @@ * Return TRUE if an effect was done, FALSE otherwise. */ /mob/living/proc/attack_effects(damage_done, hit_zone, armor_block, obj/item/attacking_item, mob/living/attacker) - if(damage_done > 0 && attacking_item.damtype == BRUTE && prob(25 + damage_done * 2)) - attacking_item.add_mob_blood(src) - add_splatter_floor(get_turf(src)) - if(get_dist(attacker, src) <= 1) - if(ishuman(attacker)) - var/bloodied_things = ITEM_SLOT_GLOVES - if(damage_done >= 20 || (damage_done >= 15 && prob(25))) - bloodied_things |= ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING - if(prob(33) && damage_done >= 10) - bloodied_things |= ITEM_SLOT_FEET - if(prob(33) && damage_done >= 24) // fireaxe damage, because heeeeere's johnny - bloodied_things |= ITEM_SLOT_MASK - if(prob(33) && damage_done >= 30) // esword damage - bloodied_things |= ITEM_SLOT_HEAD + if(damage_done <= 0 || attacking_item.damtype != BRUTE || !prob(25 + damage_done * 2)) + return FALSE - var/mob/living/carbon/human/human_attacker = attacker - human_attacker.add_blood_DNA_to_items(get_blood_dna_list(), bloodied_things) - else - attacker.add_mob_blood(src) + attacking_item.add_mob_blood(src) + add_splatter_floor(get_turf(src)) + if(get_dist(attacker, src) > 1) return TRUE - return FALSE + if(ishuman(attacker)) + attacker.add_mob_blood(src) + return TRUE + + var/bloodied_things = ITEM_SLOT_GLOVES + if(damage_done >= 20 || (damage_done >= 15 && prob(25))) + bloodied_things |= ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING + if(prob(33) && damage_done >= 10) + bloodied_things |= ITEM_SLOT_FEET + if(prob(33) && damage_done >= 24) // fireaxe damage, because heeeeere's johnny + bloodied_things |= ITEM_SLOT_MASK + if(prob(33) && damage_done >= 30) // esword damage + bloodied_things |= ITEM_SLOT_HEAD + + var/mob/living/carbon/human/human_attacker = attacker + human_attacker.add_blood_DNA_to_items(get_blood_dna_list(), bloodied_things) + return TRUE /mob/living/carbon/attack_effects(damage_done, hit_zone, armor_block, obj/item/attacking_item, mob/living/attacker) var/obj/item/bodypart/hit_bodypart = get_bodypart(hit_zone) || bodyparts[1] diff --git a/code/controllers/subsystem/blood_drying.dm b/code/controllers/subsystem/blood_drying.dm new file mode 100644 index 00000000000..79202cb8d8c --- /dev/null +++ b/code/controllers/subsystem/blood_drying.dm @@ -0,0 +1,11 @@ +/** + * Blood Drying SS + * Used as a low priority background system to handling the drying of blood on the ground + * (basically just handles reducing their bloodiness value over time) + */ +PROCESSING_SUBSYSTEM_DEF(blood_drying) + name = "Blood Drying" + flags = SS_NO_INIT | SS_BACKGROUND + priority = FIRE_PRIORITY_BLOOD_DRYING + runlevels = RUNLEVEL_GAME + wait = 4 SECONDS diff --git a/code/datums/components/blood_walk.dm b/code/datums/components/blood_walk.dm index f6d8a07e289..299b031fb50 100644 --- a/code/datums/components/blood_walk.dm +++ b/code/datums/components/blood_walk.dm @@ -17,6 +17,8 @@ var/target_dir_change ///Should we transfer the parent's blood DNA to created blood decal var/transfer_blood_dna + ///List of additional blood DNA we're adding to the decal + var/list/blood_dna_info /datum/component/blood_walk/Initialize( blood_type = /obj/effect/decal/cleanable/blood, @@ -26,7 +28,7 @@ target_dir_change = FALSE, transfer_blood_dna = FALSE, max_blood = INFINITY, - blood_dna_info = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT)) + list/blood_dna_info = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT)) ) if(!ismovable(parent)) @@ -38,6 +40,7 @@ src.blood_spawn_chance = blood_spawn_chance src.target_dir_change = target_dir_change src.transfer_blood_dna = transfer_blood_dna + src.blood_dna_info = blood_dna_info.Copy() blood_remaining = max_blood @@ -70,26 +73,34 @@ blood_remaining += max_blood ///Spawns blood (if possible) under the source, and plays a sound effect (if any) -/datum/component/blood_walk/proc/spread_blood(datum/source) +/datum/component/blood_walk/proc/spread_blood(atom/movable/source) SIGNAL_HANDLER - var/atom/movable/movable_source = source - var/turf/current_turf = movable_source.loc + var/turf/current_turf = source.loc if(!isturf(current_turf) || isclosedturf(current_turf) || isgroundlessturf(current_turf)) return + if(!prob(blood_spawn_chance)) return - var/obj/effect/decal/cleanable/blood/blood = new blood_type(current_turf) + var/list/blood_DNA = blood_dna_info.Copy() + if(transfer_blood_dna && GET_ATOM_BLOOD_DNA_LENGTH(source)) + blood_DNA = GET_ATOM_BLOOD_DNA(source) | blood_DNA + + if(!has_blood_flag(blood_DNA, BLOOD_COVER_TURFS)) + if (has_blood_flag(blood_DNA, BLOOD_ADD_DNA)) + current_turf.add_blood_DNA(blood_DNA) + return + + var/obj/effect/decal/cleanable/blood/blood = new blood_type(current_turf, null, blood_DNA) + if(QDELETED(blood)) // Our blood was placed on somewhere it shouldn't be and qdeleted in init. return if(target_dir_change) - blood.setDir(movable_source.dir) - if(transfer_blood_dna) - blood.add_blood_DNA(GET_ATOM_BLOOD_DNA(movable_source)) + blood.setDir(source.dir) if(!isnull(sound_played)) - playsound(movable_source, sound_played, sound_volume, TRUE, 2, TRUE) + playsound(source, sound_played, sound_volume, TRUE, 2, TRUE) blood_remaining = max(blood_remaining - 1, 0) if(blood_remaining <= 0) diff --git a/code/datums/components/bloody_spreader.dm b/code/datums/components/bloody_spreader.dm index ff9702f7133..073dfe07dd6 100644 --- a/code/datums/components/bloody_spreader.dm +++ b/code/datums/components/bloody_spreader.dm @@ -7,21 +7,32 @@ // Blood splashed around everywhere will carry these diseases. Oh no... var/list/diseases -/datum/component/bloody_spreader/Initialize(blood_left = INFINITY, list/blood_dna, list/diseases) +/datum/component/bloody_spreader/Initialize(blood_left = INFINITY, list/blood_dna = list(get_blood_type(BLOOD_TYPE_MEAT).dna_string = get_blood_type(BLOOD_TYPE_MEAT)), list/diseases = null) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE - var/list/signals_to_add = list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACKBY) - if(ismovable(parent)) - signals_to_add += list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT) - if(isitem(parent)) - signals_to_add += list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_ATOM, COMSIG_ITEM_HIT_REACT, COMSIG_ITEM_ATTACK_SELF, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED) - var/atom/atom_parent = parent - if(atom_parent.atom_storage) - signals_to_add += list(COMSIG_ATOM_STORED_ITEM) - else if(isstructure(parent)) - signals_to_add += list(COMSIG_ATOM_ATTACK_HAND) - RegisterSignals(parent, signals_to_add, PROC_REF(spread_yucky_blood)) + var/static/list/hand_signals = list( + COMSIG_ATOM_HULK_ATTACK, + COMSIG_ITEM_ATTACK_SELF, + COMSIG_ITEM_ATTACK_SELF_SECONDARY, + COMSIG_ITEM_DROPPED, + ) + RegisterSignals(parent, hand_signals, PROC_REF(spread_to_hands)) + + if (isstructure(parent)) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(spread_to_hands)) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(spread_to_hands)) + + RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(spread_to_atom)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_ATOM, PROC_REF(spread_to_atom)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(spread_to_atom)) + RegisterSignal(parent, COMSIG_ITEM_HIT_REACT, PROC_REF(spread_to_atom)) + RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(spread_to_atom)) + RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(spread_to_atom)) + RegisterSignal(parent, COMSIG_MOVABLE_IMPACT, PROC_REF(spread_to_atom)) + + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(spread_on_equip)) + RegisterSignal(parent, COMSIG_ATOM_STORED_ITEM, PROC_REF(spread_on_stored)) if(isclothing(parent)) parent.AddComponent(/datum/component/bloodysoles) @@ -30,24 +41,82 @@ src.blood_dna = blood_dna src.diseases = diseases -/datum/component/bloody_spreader/proc/spread_yucky_blood(atom/parent, atom/bloody_fool) +/datum/component/bloody_spreader/InheritComponent(/datum/component/new_comp, i_am_original, blood_left = 0, list/blood_dna = null, list/diseases = null) + src.blood_dna |= blood_dna + src.diseases |= diseases + if(src.blood_left >= INFINITY) + return + src.blood_left += blood_left + +/// Apply blood to the mob who interacted with us +/datum/component/bloody_spreader/proc/spread_to_hands(atom/parent, mob/bloody_fool) SIGNAL_HANDLER + if(ishuman(bloody_fool)) - var/mob/living/carbon/human/bloody_fool_human = bloody_fool - bloody_fool_human.add_blood_DNA_to_items(blood_dna, ITEM_SLOT_GLOVES) + var/mob/living/carbon/human/as_human = bloody_fool + as_human.add_blood_DNA_to_items(blood_dna, ITEM_SLOT_GLOVES) blood_left -= 3 else bloody_fool.add_blood_DNA(blood_dna, diseases) blood_left -= 1 + if(blood_left <= 0) qdel(src) -/datum/component/bloody_spreader/InheritComponent(/datum/component/new_comp, i_am_original, blood_left = 0) +/// Apply blood to the atom that interacted with us, ignoring that they may be human +/datum/component/bloody_spreader/proc/spread_to_atom(atom/parent, atom/bloody_fool) + SIGNAL_HANDLER - if(!i_am_original) + bloody_fool.add_blood_DNA(blood_dna, diseases) + blood_left -= 1 + + if(blood_left <= 0) + qdel(src) + +/// Apply blood to both the item put into us, and the mob who put it there +/datum/component/bloody_spreader/proc/spread_on_stored(atom/parent, obj/item/stored, mob/user) + SIGNAL_HANDLER + + spread_to_atom(parent, stored) + if (blood_left > 0) + spread_to_hands(parent, user) + +/// Apply blood to the slots that our item covers when equipped +/datum/component/bloody_spreader/proc/spread_on_equip(obj/item/parent, mob/equipper, slot) + SIGNAL_HANDLER + + if (!ishuman(equipper)) + equipper.add_blood_DNA(blood_dna, diseases) + blood_left -= 1 + if(blood_left <= 0) + qdel(src) return - if(src.blood_left >= INFINITY) - return + var/mob/living/carbon/human/as_human = equipper - src.blood_left += blood_left + var/blood_slots = ITEM_SLOT_GLOVES + var/blood_lost = 3 + if (slot & (ITEM_SLOT_LPOCKET | ITEM_SLOT_RPOCKET | ITEM_SLOT_ID)) + blood_slots |= ITEM_SLOT_ICLOTHING + blood_lost += 1 + else if (slot & (ITEM_SLOT_SUITSTORE | ITEM_SLOT_BELT | ITEM_SLOT_BACK | ITEM_SLOT_NECK)) + blood_slots |= ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING // Will only actually bloody one of these, thus blood_lost is increased by one instead of two + blood_lost += 1 + + if (!(slot & ITEM_SLOT_HANDS)) + var/list/equipment = as_human.get_equipped_items() + for (var/obj/item/equipped as anything in equipment) + var/item_slot = as_human.get_slot_by_item(equipped) + if ((item_slot & equipped.slot_flags) && (parent.body_parts_covered & equipped.body_parts_covered)) + if (!(blood_slots & item_slot)) + blood_lost += 1 + blood_slots |= item_slot + + if (blood_slots != ITEM_SLOT_GLOVES) + blood_lost -= 1 + + as_human.add_blood_DNA_to_items(blood_dna, blood_slots) + blood_left -= blood_lost + + if(blood_left <= 0) + qdel(src) diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 4ab1f7354b8..60e38c898f4 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -1,39 +1,34 @@ -/// The percentage of blood we lose on each step -#define BLOOD_PERCENT_LOSS_ON_STEP 0.33 - /** * Component for clothing items that can pick up blood from decals and spread it around everywhere when walking, such as shoes or suits with integrated shoes. */ /datum/component/bloodysoles - /// The type of the last grub pool we stepped in, used to decide the type of footprints to make - var/last_blood_state = BLOOD_STATE_NOT_BLOODY - - /// How much of each grubby type we have on our feet - var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) - /// The ITEM_SLOT_* slot the item is equipped on, if it is. var/equipped_slot - - /// The parent item but casted into atom type for easier use. - var/atom/parent_atom - + /// What percentage of the bloodiness is deposited on the ground per step + var/blood_dropped_per_step = 3 + /// Bloodiness on our clothines + VAR_FINAL/total_bloodiness = 0 /// Either the mob carrying the item, or the mob itself for the /feet component subtype - var/mob/living/carbon/wielder - + VAR_FINAL/mob/living/carbon/wielder /// The world.time when we last picked up blood - var/last_pickup - - var/footprint_sprite = FOOTPRINT_SPRITE_SHOES + VAR_FINAL/last_pickup + /// How much blood can we hold maximum + var/max_bloodiness = BLOOD_ITEM_MAX + /// Multiplier on how much blood taken from pools + var/share_mod = 1 /datum/component/bloodysoles/Initialize() if(!isclothing(parent)) return COMPONENT_INCOMPATIBLE - parent_atom = parent RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean)) +/datum/component/bloodysoles/Destroy() + wielder = null + return ..() + /** * Unregisters from the wielder if necessary */ @@ -48,7 +43,7 @@ * Returns true if the parent item is obscured by something else that the wielder is wearing */ /datum/component/bloodysoles/proc/is_obscured() - return wielder.check_covered_slots() & equipped_slot || is_under_feet_covered() + return (wielder.check_covered_slots() & equipped_slot) || is_under_feet_covered() /** * Returns true if the parent item is worn in the ITEM_SLOT_ICLOTHING slot and the @@ -70,27 +65,15 @@ var/obj/item/parent_item = parent parent_item.update_slot_icon() +/// Called whenever the value of bloody_soles changes to update our icon and behavior +/datum/component/bloodysoles/proc/change_blood_amount(some_amount) + total_bloodiness = clamp(round(total_bloodiness + some_amount, 0.1), 0, max_bloodiness) + update_icon() -/datum/component/bloodysoles/proc/reset_bloody_shoes() - bloody_shoes = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) - on_changed_bloody_shoes(BLOOD_STATE_NOT_BLOODY) - -///lowers bloody_shoes[index] by adjust_by -/datum/component/bloodysoles/proc/adjust_bloody_shoes(index, adjust_by) - bloody_shoes[index] = max(bloody_shoes[index] - adjust_by, 0) - on_changed_bloody_shoes(index) - -/datum/component/bloodysoles/proc/set_bloody_shoes(index, new_value) - bloody_shoes[index] = new_value - on_changed_bloody_shoes(index) - -///called whenever the value of bloody_soles changes -/datum/component/bloodysoles/proc/on_changed_bloody_shoes(index) - if(index && index != last_blood_state) - last_blood_state = index if(!wielder) return - if(bloody_shoes[index] <= BLOOD_FOOTPRINTS_MIN * 2)//need twice that amount to make footprints + + if(total_bloodiness <= BLOOD_FOOTPRINTS_MIN * 2) // Need twice that amount to make footprints UnregisterSignal(wielder, COMSIG_MOVABLE_MOVED) else RegisterSignal(wielder, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved), override = TRUE) @@ -98,44 +81,56 @@ /** * Run to equally share the blood between us and a decal */ -/datum/component/bloodysoles/proc/share_blood(obj/effect/decal/cleanable/pool) +/datum/component/bloodysoles/proc/share_blood(obj/effect/decal/cleanable/blood/pool) // Share the blood between our boots and the blood pool - var/total_bloodiness = pool.bloodiness + bloody_shoes[pool.blood_state] + var/new_total_bloodiness = min(max_bloodiness, share_mod * (pool.bloodiness + total_bloodiness) / 2) + if(new_total_bloodiness == total_bloodiness || new_total_bloodiness == 0) + return FALSE - // We can however be limited by how much blood we can hold - var/new_our_bloodiness = min(BLOOD_ITEM_MAX, total_bloodiness / 2) + var/delta = new_total_bloodiness - total_bloodiness + pool.adjust_bloodiness(-1 * delta) + change_blood_amount(delta) - set_bloody_shoes(pool.blood_state, new_our_bloodiness) - pool.bloodiness = total_bloodiness - new_our_bloodiness // Give the pool the remaining blood incase we were limited - - if(HAS_TRAIT(parent_atom, TRAIT_LIGHT_STEP) || (wielder && HAS_TRAIT(wielder, TRAIT_LIGHT_STEP))) //the character is agile enough to don't mess their clothing and hands just from one blood splatter at floor + if(!ishuman(parent)) + var/atom/to_bloody = parent + to_bloody.add_blood_DNA(GET_ATOM_BLOOD_DNA(pool)) return TRUE - if(ishuman(parent)) - var/bloody_slots = ITEM_SLOT_OCLOTHING|ITEM_SLOT_ICLOTHING|ITEM_SLOT_FEET - var/mob/living/carbon/human/to_bloody = parent - if(to_bloody.body_position == LYING_DOWN) - bloody_slots |= ITEM_SLOT_HEAD|ITEM_SLOT_MASK|ITEM_SLOT_GLOVES + var/bloody_slots = ITEM_SLOT_OCLOTHING|ITEM_SLOT_ICLOTHING|ITEM_SLOT_FEET + var/mob/living/carbon/human/to_bloody = parent + if(to_bloody.body_position == LYING_DOWN) + bloody_slots |= ITEM_SLOT_HEAD|ITEM_SLOT_MASK|ITEM_SLOT_GLOVES - to_bloody.add_blood_DNA_to_items(GET_ATOM_BLOOD_DNA(pool), bloody_slots) - return - - var/atom/to_bloody = parent - to_bloody.add_blood_DNA(GET_ATOM_BLOOD_DNA(pool)) + to_bloody.add_blood_DNA_to_items(GET_ATOM_BLOOD_DNA(pool), bloody_slots) + return TRUE /** - * Find a blood decal on a turf that matches our last_blood_state + * Adds blood to an existing (or new) footprint */ -/datum/component/bloodysoles/proc/find_pool_by_blood_state(turf/turfLoc, typeFilter = null, footprint_sprite) - for(var/obj/effect/decal/cleanable/blood/pool in turfLoc) - if(pool.blood_state == last_blood_state && pool.footprint_sprite == footprint_sprite && (!typeFilter || istype(pool, typeFilter))) - return pool +/datum/component/bloodysoles/proc/add_blood_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint, bloodiness_to_add, exiting = FALSE, no_dna = FALSE) + add_parent_to_footprint(footprint) + footprint.adjust_bloodiness(bloodiness_to_add) + if (!no_dna) + footprint.add_blood_DNA(get_blood_dna()) + var/new_alpha = min(BLOODY_FOOTPRINT_BASE_ALPHA + (255 - BLOODY_FOOTPRINT_BASE_ALPHA) * footprint.bloodiness / (BLOOD_ITEM_MAX * BLOOD_TO_UNITS_MULTIPLIER), 255) + if(new_alpha > footprint.alpha) + footprint.alpha = new_alpha + if(exiting) + footprint.exited_dirs |= wielder.dir + else + footprint.entered_dirs |= wielder.dir + footprint.update_appearance() + +/// Fetches this component's blood DNA +/datum/component/bloodysoles/proc/get_blood_dna() + var/atom/atom_parent = parent + return GET_ATOM_BLOOD_DNA(atom_parent) /** * Adds the parent type to the footprint's shoe_types var */ -/datum/component/bloodysoles/proc/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/FP) - FP.shoe_types |= parent.type +/datum/component/bloodysoles/proc/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint) + LAZYOR(footprint.shoe_types, parent.type) /** * Called when the parent item is equipped by someone @@ -154,7 +149,7 @@ equipped_slot = slot wielder = equipper - if(bloody_shoes[last_blood_state] > BLOOD_FOOTPRINTS_MIN * 2) + if(total_bloodiness > BLOOD_FOOTPRINTS_MIN * 2) RegisterSignal(wielder, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(wielder, COMSIG_STEP_ON_BLOOD, PROC_REF(on_step_blood)) @@ -165,7 +160,6 @@ */ /datum/component/bloodysoles/proc/on_drop(datum/source, mob/dropper) SIGNAL_HANDLER - unregister() /** @@ -173,63 +167,65 @@ * * Used to make bloody footprints on the ground */ -/datum/component/bloodysoles/proc/on_moved(datum/source, OldLoc, Dir, Forced) +/datum/component/bloodysoles/proc/on_moved(datum/source, atom/old_loc, Dir, Forced) SIGNAL_HANDLER - if(bloody_shoes[last_blood_state] == 0) + if(total_bloodiness <= 0) return if(QDELETED(wielder) || is_obscured()) return - if(wielder.body_position == LYING_DOWN || !wielder.has_gravity(wielder.loc)) + if(wielder.body_position == LYING_DOWN || (wielder.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)) return - var/blood_lost = bloody_shoes[last_blood_state] * BLOOD_PERCENT_LOSS_ON_STEP - var/theoretical_new_blood = bloody_shoes[last_blood_state] - blood_lost - var/footprint_sprite = wielder.get_footprint_sprite() + var/atom/parent_atom = parent + var/blood_used = round(total_bloodiness / 3, 0.01) + // This is more of a sanity check than an actual concern, but *just* in case + var/blood_flags = has_blood_flag(get_blood_dna(), BLOOD_ADD_DNA | BLOOD_COVER_TURFS) + // Add footprints in old loc if we have enough cream - if(theoretical_new_blood >= BLOOD_FOOTPRINTS_MIN) - var/turf/oldLocTurf = get_turf(OldLoc) - var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints, footprint_sprite) - if(oldLocFP) - // Footprints found in the tile we left, add us to it - add_parent_to_footprint(oldLocFP) - if (!(oldLocFP.exited_dirs & wielder.dir)) - oldLocFP.exited_dirs |= wielder.dir - oldLocFP.update_appearance() - else if(find_pool_by_blood_state(oldLocTurf, footprint_sprite = footprint_sprite)) + if(blood_used >= BLOOD_FOOTPRINTS_MIN) + var/turf/old_loc_turf = get_turf(old_loc) + var/obj/effect/decal/cleanable/blood/footprints/old_loc_prints = locate() in old_loc_turf + if(!(blood_flags & BLOOD_COVER_TURFS)) + if(blood_flags & BLOOD_ADD_DNA) + old_loc_prints?.add_blood_DNA(get_blood_dna()) + else if(old_loc_prints) + add_blood_to_footprint(old_loc_prints, 0, TRUE) // Add no actual blood, just update sprite + else if(locate(/obj/effect/decal/cleanable/blood) in old_loc_turf) // No footprints in the tile we left, but there was some other blood pool there. Add exit footprints on it - adjust_bloody_shoes(last_blood_state, blood_lost) - update_icon() - - oldLocFP = new(oldLocTurf, footprint_sprite) - if(!QDELETED(oldLocFP)) ///prints merged - oldLocFP.blood_state = last_blood_state - oldLocFP.exited_dirs |= wielder.dir - add_parent_to_footprint(oldLocFP) - oldLocFP.bloodiness = blood_lost - oldLocFP.add_blood_DNA(GET_ATOM_BLOOD_DNA(parent_atom)) - oldLocFP.update_appearance() - - blood_lost = bloody_shoes[last_blood_state] * BLOOD_PERCENT_LOSS_ON_STEP - theoretical_new_blood = theoretical_new_blood - blood_lost + change_blood_amount(-1 * blood_used) + old_loc_prints = new(old_loc_turf, null, get_blood_dna()) + old_loc_prints.alpha = 0 + if(!QDELETED(old_loc_prints)) // prints merged + add_blood_to_footprint(old_loc_prints, blood_used, TRUE, no_dna = TRUE) + blood_used = round(total_bloodiness / 3, 0.01) // If we picked up the blood on this tick in on_step_blood, don't make footprints at the same place - if(last_pickup && last_pickup == world.time) + if(last_pickup == world.time) + return + + if(blood_used < BLOOD_FOOTPRINTS_MIN) return // Create new footprints - if(theoretical_new_blood >= BLOOD_FOOTPRINTS_MIN) - adjust_bloody_shoes(last_blood_state, blood_lost) + var/turf/new_loc_turf = get_turf(parent_atom) + var/obj/effect/decal/cleanable/blood/footprints/new_loc_prints = locate() in new_loc_turf + if(new_loc_prints) + if(blood_flags & BLOOD_COVER_TURFS) + add_blood_to_footprint(new_loc_prints, 0, FALSE) // Add no actual blood, just update sprite + return + if(blood_flags & BLOOD_ADD_DNA) + new_loc_prints.add_blood_DNA(get_blood_dna()) + return - var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom), footprint_sprite) - if(!QDELETED(FP)) ///prints merged - FP.blood_state = last_blood_state - FP.entered_dirs |= wielder.dir - add_parent_to_footprint(FP) - FP.bloodiness = blood_lost - FP.add_blood_DNA(GET_ATOM_BLOOD_DNA(parent_atom)) - FP.update_appearance() + if(!(blood_flags & BLOOD_COVER_TURFS)) + return + change_blood_amount(-1 * blood_used) + new_loc_prints = new(new_loc_turf, null, get_blood_dna()) + new_loc_prints.alpha = 0 + if(!QDELETED(new_loc_prints)) // prints merged + add_blood_to_footprint(new_loc_prints, blood_used, FALSE, no_dna = TRUE) /** * Called when the wielder steps in a pool of blood @@ -239,21 +235,18 @@ /datum/component/bloodysoles/proc/on_step_blood(datum/source, obj/effect/decal/cleanable/pool) SIGNAL_HANDLER - if(QDELETED(wielder) || is_obscured()) + if(QDELETED(wielder) || is_obscured() || (wielder.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)) return - if(istype(pool, /obj/effect/decal/cleanable/blood/footprints) && pool.blood_state == last_blood_state) - // The pool we stepped in was actually footprints with the same type - var/obj/effect/decal/cleanable/blood/footprints/pool_FP = pool - add_parent_to_footprint(pool_FP) - if((bloody_shoes[last_blood_state] - (bloody_shoes[last_blood_state] * BLOOD_PERCENT_LOSS_ON_STEP)) >= BLOOD_FOOTPRINTS_MIN && !(pool_FP.entered_dirs & wielder.dir)) - // If our feet are bloody enough, add an entered dir - pool_FP.entered_dirs |= wielder.dir - pool_FP.update_appearance() + /// The character is agile enough to not mess their clothing and hands just from one blood splatter at floor + if(HAS_TRAIT(wielder, TRAIT_LIGHT_STEP)) + return + + // Don't share from other feetprints, not super realistic but I think it ruins the effect a bit + if(istype(pool, /obj/effect/decal/cleanable/blood/footprints)) return share_blood(pool) - last_pickup = world.time /** @@ -262,63 +255,81 @@ /datum/component/bloodysoles/proc/on_clean(datum/source, clean_types) SIGNAL_HANDLER - if(!(clean_types & CLEAN_TYPE_BLOOD) || last_blood_state == BLOOD_STATE_NOT_BLOODY) + if(!(clean_types & CLEAN_TYPE_BLOOD)) return NONE - reset_bloody_shoes() + total_bloodiness = 0 update_icon() return COMPONENT_CLEANED - /** * Like its parent but can be applied to carbon mobs instead of clothing items */ /datum/component/bloodysoles/feet + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + equipped_slot = ITEM_SLOT_FEET var/static/mutable_appearance/bloody_feet -/datum/component/bloodysoles/feet/Initialize() + /// List of DNA on mob's feet, so we can handle it separately from blood on mob's hands + var/list/blood_DNA = null + +/datum/component/bloodysoles/feet/Initialize(list/new_blood) if(!iscarbon(parent)) return COMPONENT_INCOMPATIBLE - parent_atom = parent + wielder = parent - if(footprint_sprite) - src.footprint_sprite = footprint_sprite + if(!bloody_feet) - bloody_feet = mutable_appearance('icons/effects/blood.dmi', "shoeblood", SHOES_LAYER, appearance_flags = RESET_COLOR) - bloody_feet.color = BLOOD_COLOR_RED + bloody_feet = mutable_appearance('icons/effects/blood.dmi', "shoeblood", SHOES_LAYER) RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean)) RegisterSignal(parent, COMSIG_STEP_ON_BLOOD, PROC_REF(on_step_blood)) - RegisterSignal(parent, COMSIG_MOB_EQUIPPED_ITEM, PROC_REF(unequip_shoecover)) - RegisterSignal(parent, COMSIG_MOB_UNEQUIPPED_ITEM, PROC_REF(equip_shoecover)) + RegisterSignals(parent, list(COMSIG_MOB_EQUIPPED_ITEM, COMSIG_MOB_UNEQUIPPED_ITEM), PROC_REF(shoecover)) + + if(new_blood) + blood_DNA = new_blood + update_icon() + +/datum/component/bloodysoles/feet/InheritComponent(datum/component/bloodysoles/feet/soles, original, list/new_blood) + if (!length(new_blood)) + return + + LAZYOR(blood_DNA, new_blood) + update_icon() + +/datum/component/bloodysoles/feet/share_blood(obj/effect/decal/cleanable/pool) + . = ..() + if (!.) + return + LAZYOR(blood_DNA, GET_ATOM_BLOOD_DNA(pool)) + update_icon() /datum/component/bloodysoles/feet/update_icon() if(!ishuman(wielder) || HAS_TRAIT(wielder, TRAIT_NO_BLOOD_OVERLAY)) return - if(bloody_shoes[BLOOD_STATE_HUMAN] > 0 && !is_obscured()) - wielder.remove_overlay(SHOES_LAYER) - wielder.overlays_standing[SHOES_LAYER] = bloody_feet - wielder.apply_overlay(SHOES_LAYER) - else - wielder.update_worn_shoes() -/datum/component/bloodysoles/feet/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/FP) + wielder.remove_overlay(SHOES_LAYER) + if(!total_bloodiness || is_obscured()) + wielder.update_worn_shoes() + return + + bloody_feet.color = wielder.get_blood_dna_color() + wielder.overlays_standing[SHOES_LAYER] = bloody_feet + wielder.apply_overlay(SHOES_LAYER) + +/datum/component/bloodysoles/feet/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint) if(!ishuman(wielder)) - FP.species_types |= "unknown" + LAZYSET(footprint.species_types, "unknown", TRUE) return // Find any leg of our human and add that to the footprint, instead of the default which is to just add the human type - for(var/X in wielder.bodyparts) - var/obj/item/bodypart/affecting = X - if(affecting.body_part == LEG_RIGHT || affecting.body_part == LEG_LEFT) - if(!affecting.bodypart_disabled) - FP.species_types |= affecting.limb_id - break + for(var/obj/item/bodypart/leg/affecting in wielder.bodyparts) + if(!affecting.bodypart_disabled) + LAZYSET(footprint.species_types, affecting.limb_id, TRUE) -/datum/component/bloodysoles/feet/is_obscured() - if(wielder.shoes) - return TRUE - return wielder.check_covered_slots() & ITEM_SLOT_FEET +/datum/component/bloodysoles/feet/is_under_feet_covered() + return !isnull(wielder.shoes) /datum/component/bloodysoles/feet/on_moved(datum/source, OldLoc, Dir, Forced) if(wielder.num_legs >= 2) @@ -328,22 +339,36 @@ if(wielder.num_legs >= 2) return ..() -/datum/component/bloodysoles/feet/share_blood(obj/effect/decal/cleanable/pool) - . = ..() - if(.) - return - - bloody_feet.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(pool)) - update_icon() - -/datum/component/bloodysoles/feet/proc/equip_shoecover(datum/source, obj/item/item) +/datum/component/bloodysoles/feet/proc/shoecover(datum/source, obj/item/item) SIGNAL_HANDLER if ((item.body_parts_covered & FEET) || (item.flags_inv & HIDESHOES)) update_icon() -/datum/component/bloodysoles/feet/proc/unequip_shoecover(datum/source, obj/item/item) - SIGNAL_HANDLER - if ((item.body_parts_covered & FEET) || (item.flags_inv & HIDESHOES)) - update_icon() +/datum/component/bloodysoles/feet/get_blood_dna() + return blood_DNA -#undef BLOOD_PERCENT_LOSS_ON_STEP +/** + * Simplified version of the kind applied to carbons for simple/basic mobs, primarily robots + */ +/datum/component/bloodysoles/bot + max_bloodiness = 150 + share_mod = 0.75 + +/datum/component/bloodysoles/bot/Initialize() + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + wielder = parent + RegisterSignal(wielder, COMSIG_STEP_ON_BLOOD, PROC_REF(on_step_blood)) + +/datum/component/bloodysoles/bot/is_obscured() + return FALSE + +/datum/component/bloodysoles/bot/is_under_feet_covered() + return FALSE + +/datum/component/bloodysoles/bot/add_parent_to_footprint(obj/effect/decal/cleanable/blood/footprints/footprint) + LAZYSET(footprint.species_types, "bot", TRUE) + +/datum/component/bloodysoles/bot/update_icon() + // Future idea: Bot blood overlays + return diff --git a/code/datums/dna.dm b/code/datums/dna.dm index f2b54e6ded4..fbee431755f 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -73,7 +73,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/unique_enzymes ///Stores the hashed values of traits such as skin tones, hair style, and gender var/unique_identity - /// The singleton blood type + ///The blood type datum, usually a singleton var/datum/blood_type/blood_type ///The type of mutant race the player is if applicable (i.e. potato-man) var/datum/species/species = new /datum/species/human @@ -82,7 +82,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) var/list/features = list("mcolor" = COLOR_WHITE) ///Stores the hashed values of the person's non-human features var/unique_features - ///Stores the real name of the person who originally got this dna datum. Used primarily for changelings, + ///Stores the real name of the person who originally got this dna datum. Used primarily for changelings var/real_name ///All mutations are from now on here var/list/mutations = list() @@ -108,11 +108,11 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) holder = new_holder /datum/dna/Destroy() - if(iscarbon(holder)) - var/mob/living/carbon/cholder = holder + if (iscarbon(holder)) + var/mob/living/carbon/as_carbon = holder remove_all_mutations() // mutations hold a reference to the dna - if(cholder.dna == src) - cholder.dna = null + if(as_carbon.dna == src) + as_carbon.dna = null holder = null QDEL_NULL(species) @@ -159,7 +159,9 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) //SKYRAT EDIT ADDITION END //if the new DNA has a holder, transform them immediately, otherwise save it if(new_dna.holder) - new_dna.holder.set_blood_type(blood_type) + if (iscarbon(new_dna.holder)) + var/mob/living/carbon/as_carbon = new_dna.holder + as_carbon.set_blood_type(blood_type) new_dna.holder.set_species(species.type, icon_update = 0) else new_dna.blood_type = blood_type diff --git a/code/datums/elements/blood_reagent.dm b/code/datums/elements/blood_reagent.dm new file mode 100644 index 00000000000..74c2dff9ba8 --- /dev/null +++ b/code/datums/elements/blood_reagent.dm @@ -0,0 +1,224 @@ +/// Element that blood reagents use to apply their data (not blood regen!) to mobs +/// Only added to blood drawn *from* someone, so don't put behavior that should work with any reagent onto this +/datum/element/blood_reagent + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 3 + /// Blood type associated with this element + var/datum/blood_type/blood_type + +/* + * Arguments: + * * blood_source - mob this blood came from, can be null + * * blood_type - blood type datum we grab data and behavior from, cannot be null + */ +/datum/element/blood_reagent/Attach(datum/reagent/target, mob/living/blood_source, datum/blood_type/blood_type) + . = ..() + if (!istype(target) || !istype(blood_type)) + return ELEMENT_INCOMPATIBLE + + src.blood_type = blood_type + RegisterSignal(target, COMSIG_REAGENT_EXPOSE_MOB, PROC_REF(on_mob_expose)) + RegisterSignal(target, COMSIG_REAGENT_EXPOSE_TURF, PROC_REF(on_turf_expose)) + RegisterSignal(target, COMSIG_REAGENT_EXPOSE_OBJ, PROC_REF(on_obj_expose)) + RegisterSignal(target, COMSIG_REAGENT_ON_MERGE, PROC_REF(on_merge)) + RegisterSignal(target, COMSIG_REAGENT_ON_TRANSFER, PROC_REF(on_transfer)) + + if (!target.data) + target.data = list() + + target.data["blood_type"] = blood_type + if (blood_type.desc) + target.description = blood_type.desc + target.color = blood_type.get_color() + + if (!blood_source) + return + + var/list/blood_data = blood_source.get_blood_data() + if(blood_data["viruses"]) + var/list/to_preserve = list() + for (var/datum/disease/disease in blood_data["viruses"]) + to_preserve += disease.Copy() + blood_data["viruses"] = to_preserve + + for (var/key in blood_data) + if (!islist(blood_data[key])) + target.data[key] = blood_data[key] + continue + + var/list/data_list = blood_data[key] + var/list/target_data = target.data[key] + if (!target_data) + target.data[key] = data_list.Copy() + else + // Concat viruses, resistances, etc + target_data |= data_list + +// Shouldn't realistically happen but just in case +/datum/element/blood_reagent/Detach(datum/reagent/target) + . = ..() + UnregisterSignal(target, list( + COMSIG_REAGENT_EXPOSE_MOB, + COMSIG_REAGENT_EXPOSE_TURF, + COMSIG_REAGENT_EXPOSE_OBJ, + COMSIG_REAGENT_ON_MERGE, + COMSIG_REAGENT_ON_TRANSFER, + )) + +/// Cover the mob in blood and transfer our viruses and resistances to them +/datum/element/blood_reagent/proc/on_mob_expose( + datum/reagent/source, + mob/living/exposed_mob, + methods = TOUCH, + reac_volume, + show_message = TRUE, + touch_protection = 0, +) + SIGNAL_HANDLER + + if ((methods & (TOUCH | VAPOR)) && reac_volume >= 3 && (blood_type.blood_flags & (BLOOD_ADD_DNA | BLOOD_COVER_MOBS))) + exposed_mob.add_blood_DNA(list("[source.data?["blood_DNA"] || blood_type.dna_string]" = blood_type)) + + // Somehow got a no-data reagent, probably artificially created blood + if (!source.data) + return + + if (!(blood_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA)) + return + + for(var/datum/disease/strain as anything in source.data["viruses"]) + if ((strain.spread_flags & DISEASE_SPREAD_SPECIAL) || (strain.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) + continue + + if (methods & INGEST) + if (!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_STOMACH)) + continue + exposed_mob.ForceContractDisease(strain) + + else if (methods & (INJECT|PATCH)) + if (!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_HEART)) + continue + exposed_mob.ForceContractDisease(strain) + + else if ((methods & (VAPOR|INHALE)) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) + if (!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_LUNGS)) + continue + exposed_mob.ContactContractDisease(strain) + + else if ((methods & TOUCH) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) + exposed_mob.ContactContractDisease(strain) + + /// Have to inject, inhale or ingest it. No curefoam/cheap curesprays + if (source.data["resistances"] && (methods & (INGEST|INJECT|INHALE))) + for(var/datum/disease/infection in exposed_mob.diseases) + if (!infection.bypasses_immunity && (infection.GetDiseaseID() in source.data["resistances"])) + infection.cure(add_resistance = FALSE) + +/// Create or mix in a blood splatter and transfer our diseases to it +/datum/element/blood_reagent/proc/on_turf_expose(datum/reagent/source, turf/exposed_turf, reac_volume) + SIGNAL_HANDLER + + if (reac_volume < 3 || !(blood_type.blood_flags & (BLOOD_ADD_DNA | BLOOD_COVER_TURFS))) + return + + var/dna_list = list("[source.data?["blood_DNA"] || blood_type.dna_string]" = blood_type) + var/obj/effect/decal/cleanable/blood/splatter = locate() in exposed_turf + if (!splatter) + if (!(blood_type.blood_flags & BLOOD_COVER_TURFS)) + return + splatter = new(exposed_turf, (blood_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA) ? source.data?["viruses"] : null, dna_list) + splatter.adjust_bloodiness(-splatter.bloodiness + reac_volume / BLOOD_TO_UNITS_MULTIPLIER) + return + + splatter.add_blood_DNA(dna_list) + if (blood_type.blood_flags & BLOOD_COVER_TURFS) + splatter.adjust_bloodiness(reac_volume / BLOOD_TO_UNITS_MULTIPLIER) + + if (!(blood_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA) || !source.data?["viruses"]) + return + + var/list/viruses_to_add = list() + for(var/datum/disease/virus in source.data["viruses"]) + if (virus.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS) + viruses_to_add += virus + + if (length(viruses_to_add)) + splatter.AddComponent(/datum/component/infective, viruses_to_add) + +/datum/element/blood_reagent/proc/on_obj_expose(datum/reagent/source, obj/exposed_obj, reac_volume, methods = TOUCH, show_message = TRUE) + SIGNAL_HANDLER + + if (reac_volume < 3 || !(methods & (VAPOR | TOUCH))) + return + + if (blood_type.blood_flags & (BLOOD_ADD_DNA | BLOOD_COVER_ITEMS)) + exposed_obj.add_blood_DNA(list(list("[source.data?["blood_DNA"] || blood_type.dna_string]" = blood_type) = blood_type)) + + if (!(blood_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA) || !source.data?["viruses"]) + return + + var/list/viruses_to_add = list() + for (var/datum/disease/virus in source.data["viruses"]) + if (virus.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS) + viruses_to_add += virus + + if (length(viruses_to_add)) + exposed_obj.AddComponent(/datum/component/infective, viruses_to_add) + +/datum/element/blood_reagent/proc/on_merge(datum/reagent/source, list/mix_data, amount) + SIGNAL_HANDLER + + // Presumably artificially generated blood + if (!source.data || !mix_data) + return + + // Mixed blood cannot be used for cloning + if (source.data["blood_DNA"] != mix_data["blood_DNA"]) + source.data["cloneable"] = FALSE + + var/list/source_viruses = source.data["viruses"] + var/list/mix_viruses = mix_data["viruses"] + if (source_viruses && mix_viruses) + var/list/mix_target = list() + var/list/to_preserve = list() + for (var/datum/disease/disease as anything in source_viruses) + if (istype(disease, /datum/disease/advance)) + mix_target += disease + else + to_preserve += disease + + for (var/datum/disease/disease as anything in mix_viruses) + if (istype(disease, /datum/disease/advance)) + mix_target += disease + else + to_preserve += disease + + var/datum/disease/advance/disease = Advance_Mix(mix_target) + if (disease) + to_preserve += disease + source.data["viruses"] = to_preserve + else if (mix_viruses) + source.data["viruses"] = mix_viruses.Copy() + + if (mix_data["resistances"]) + if (!source.data["resistances"]) + source.data["resistances"] = list() + source.data["resistances"] |= mix_data["resistances"] + + // Features are randomly recombinated based on amount mixed in + var/list/source_features = source.data["features"] + var/list/mix_features = mix_data["features"] + if (source_features && mix_features) + for (var/feature_key in mix_features) + if (!source_features[feature_key] || prob(amount / (source.volume + amount) * 100)) + source_features[feature_key] = mix_features[feature_key] + + if (mix_data["trace_chem"]) + if (!source.data["trace_chem"]) + source.data["trace_chem"] = mix_data["trace_chem"] + else + source.data["trace_chem"] = list2params(params2list(source.data["trace_chem"]) | params2list(mix_data["trace_chem"])) + +/datum/element/blood_reagent/proc/on_transfer(datum/reagent/reagent, datum/reagents/target_holder, datum/reagent/new_reagent) + SIGNAL_HANDLER + new_reagent.AddElement(/datum/element/blood_reagent, null, blood_type) diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index 11f011a2e75..801a0bd7b52 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -1,17 +1,20 @@ /datum/element/decal/blood /// Whenever the parent atom has a color filter applied to it, and thus needs additional overlay handling var/uses_filter = FALSE + /// Emissive alpha of our parent + var/emissive_alpha = null -/datum/element/decal/blood/Attach(datum/target, _icon, _icon_state, _dir, _plane, _layer, _alpha, _color, _smoothing, _cleanable=CLEAN_TYPE_BLOOD, _description, mutable_appearance/_pic, _uses_filter) +/datum/element/decal/blood/Attach(datum/target, _icon, _icon_state, _dir, _plane, _layer, _alpha, _color, _smoothing, _cleanable = CLEAN_TYPE_BLOOD, _description, mutable_appearance/_pic, _uses_filter, _emissive) if (!isitem(target)) return ELEMENT_INCOMPATIBLE var/obj/item/as_item = target if (_uses_filter != !isnull(as_item.cached_color_filter)) - as_item.AddElement(type, _icon, _icon_state, _dir, _plane, _layer, _alpha, _color, _smoothing, _cleanable, _description, _pic, !isnull(as_item.cached_color_filter)) + as_item.AddElement(type, _icon, _icon_state, _dir, _plane, _layer, _alpha, _color, _smoothing, _cleanable, _description, _pic, !isnull(as_item.cached_color_filter), _emissive) return uses_filter = _uses_filter + emissive_alpha = _emissive . = ..() RegisterSignal(as_item, COMSIG_ATOM_GET_EXAMINE_NAME, PROC_REF(get_examine_name), TRUE) RegisterSignal(as_item, COMSIG_ATOM_COLOR_UPDATED, PROC_REF(on_color_update), TRUE) @@ -26,25 +29,40 @@ /datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _plane, _layer, _color = BLOOD_COLOR_RED, _alpha, _smoothing, source) var/obj/item/as_item = source ADD_KEEP_TOGETHER(as_item, type) - var/icon/icon_for_size = icon(as_item.icon, as_item.icon_state) - var/scale_factor_x = icon_for_size.Width()/ICON_SIZE_X - var/scale_factor_y = icon_for_size.Height()/ICON_SIZE_Y + var/scale_factor_x = as_item.get_cached_width() / ICON_SIZE_X + var/scale_factor_y = as_item.get_cached_height() / ICON_SIZE_Y var/mutable_appearance/blood_splatter = mutable_appearance('icons/effects/blood.dmi', "itemblood", appearance_flags = RESET_COLOR) //MA of the blood that we apply blood_splatter.transform = blood_splatter.transform.Scale(scale_factor_x, scale_factor_y) blood_splatter.blend_mode = BLEND_INSET_OVERLAY blood_splatter.color = _color + var/mutable_appearance/emissive_splatter = null + if (emissive_alpha) + emissive_splatter = emissive_appearance('icons/effects/blood.dmi', "itemblood", as_item, alpha = emissive_alpha) + emissive_splatter.blend_mode = BLEND_INSET_OVERLAY if (uses_filter) blood_splatter.appearance_flags |= KEEP_APART if (!as_item.render_target) as_item.render_target = "blood_target_[REF(as_item)]" blood_splatter.add_filter("blood_cutout", -1, alpha_mask_filter(render_source = as_item.render_target)) + if (emissive_splatter) + emissive_splatter.add_filter("blood_cutout", -1, alpha_mask_filter(render_source = as_item.render_target)) + if (emissive_splatter) + blood_splatter.overlays += emissive_splatter pic = blood_splatter return TRUE /datum/element/decal/blood/proc/get_examine_name(atom/source, mob/user, list/override) SIGNAL_HANDLER - override[EXAMINE_POSITION_BEFORE] = "blood-stained" + var/list/blood_stains = GET_ATOM_BLOOD_DECALS(source) + if (!length(blood_stains)) + return + var/datum/blood_type/blood_type = blood_stains[blood_stains[length(blood_stains)]] + var/blood_descriptor = "blood" + if(istype(blood_type)) + blood_descriptor = LOWER_TEXT(blood_type.get_blood_name()) + + override[EXAMINE_POSITION_BEFORE] = "[blood_descriptor]-stained" /datum/element/decal/blood/proc/on_color_update(obj/item/source, color_updated) SIGNAL_HANDLER diff --git a/code/datums/elements/easy_ignite.dm b/code/datums/elements/easy_ignite.dm new file mode 100644 index 00000000000..4304df0890c --- /dev/null +++ b/code/datums/elements/easy_ignite.dm @@ -0,0 +1,108 @@ +/// Creates a hotspot and deletes the owner atom upon being exposed to high temperatures, by Melbert +/datum/element/easy_ignite + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY|ELEMENT_BESPOKE // because turfs + argument_hash_start_idx = 2 + /// Temp required for ignition + var/required_temp = 480 + +/datum/element/easy_ignite/Attach(datum/target, required_temp = 480) + . = ..() + if(!isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + + src.required_temp = required_temp + RegisterSignal(target, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(attackby_react)) + RegisterSignal(target, COMSIG_ATOM_FIRE_ACT, PROC_REF(flame_react)) + RegisterSignal(target, COMSIG_ATOM_BULLET_ACT, PROC_REF(projectile_react)) + RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(welder_react)) + if(isturf(target)) + RegisterSignal(target, COMSIG_TURF_EXPOSE, PROC_REF(hotspots_react)) + +/datum/element/easy_ignite/Detach(datum/source, ...) + . = ..() + UnregisterSignal(source, COMSIG_ATOM_ITEM_INTERACTION) + UnregisterSignal(source, COMSIG_ATOM_FIRE_ACT) + UnregisterSignal(source, COMSIG_ATOM_BULLET_ACT) + UnregisterSignal(source, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER)) + if(isturf(source)) + UnregisterSignal(source, COMSIG_TURF_EXPOSE) + +/datum/element/easy_ignite/proc/ignite(atom/igniting, mob/user) + var/delete_after = TRUE + + igniting.visible_message(span_warning("[igniting] catch[igniting.p_es()] fire!"), span_warning("You ignite into flames!")) + new /obj/effect/hotspot(isturf(igniting) ? igniting : igniting.loc) + + if(isturf(igniting)) + var/turf/parent_turf = igniting + parent_turf.ScrapeAway(1, CHANGETURF_INHERIT_AIR) + delete_after = FALSE + + // Logging-related + var/log_message = "ignited [igniting]" + if(user) + user.log_message(log_message, LOG_ATTACK, log_globally = FALSE)//only individual log + + else + log_message = "[key_name(user)] " + log_message + " by fire" + log_attack(log_message) + + if(delete_after && !QDELETED(igniting)) + qdel(igniting) + +/datum/element/easy_ignite/proc/flame_react(obj/item/source, exposed_temperature, exposed_volume) + SIGNAL_HANDLER + + if(exposed_temperature > required_temp) + ignite(source) + +/datum/element/easy_ignite/proc/hotspots_react(obj/item/source, air, exposed_temperature) + SIGNAL_HANDLER + + if(exposed_temperature > required_temp) + ignite(source) + +/datum/element/easy_ignite/proc/attackby_react(obj/item/source, mob/user, obj/item/tool, modifiers) + SIGNAL_HANDLER + + if(!tool.get_temperature()) + return NONE + + if (!item_ignition(source, tool, user)) + return ITEM_INTERACT_BLOCKING + + ignite(source, user) + return ITEM_INTERACT_SUCCESS + +/datum/element/easy_ignite/proc/projectile_react(obj/item/source, obj/projectile/shot) + SIGNAL_HANDLER + + if(shot.damage_type == BURN && shot.damage > 0) + ignite(source, shot.firer) + +/datum/element/easy_ignite/proc/welder_react(obj/item/source, mob/user, obj/item/tool) + SIGNAL_HANDLER + + if(!tool.get_temperature()) + return NONE + + if (!item_ignition(source, tool, user)) + return ITEM_INTERACT_BLOCKING + + ignite(source, user) + return ITEM_INTERACT_SUCCESS + +/datum/element/easy_ignite/proc/item_ignition(obj/item/source, obj/item/tool, mob/user) + if(tool.get_temperature() >= required_temp) + source.visible_message( + span_warning("[user] ignites [source] with [tool]!"), + span_warning("You ignite [source] with [tool]!"), + ) + ignite(source, user) + return TRUE + + source.visible_message( + span_warning("[user] tries to ignite [source] with [tool]!"), + span_warning("You try to ignite [source] with [tool], but it's not hot enough!"), + ) + return FALSE diff --git a/code/datums/materials/meat.dm b/code/datums/materials/meat.dm index 175772d01a7..7eeb88144e5 100644 --- a/code/datums/materials/meat.dm +++ b/code/datums/materials/meat.dm @@ -52,8 +52,6 @@ source.AddComponent( /datum/component/bloody_spreader,\ blood_left = (protein_count + fat_count) * 0.3,\ - blood_dna = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT)),\ - diseases = null,\ ) // Turfs can't handle the meaty goodness of blood walk. diff --git a/code/datums/mutations/touch.dm b/code/datums/mutations/touch.dm index 28f6ee82c7b..190dc84f72e 100644 --- a/code/datums/mutations/touch.dm +++ b/code/datums/mutations/touch.dm @@ -317,8 +317,11 @@ var/blood_to_hurtguy = min(max_blood_transfer, max_blood_to_hurtguy) if(!blood_to_hurtguy) return . + // We ignore incompatibility here. - mendicant.transfer_blood_to(hurtguy, blood_to_hurtguy, forced = TRUE) + if(!mendicant.transfer_blood_to(hurtguy, blood_to_hurtguy, forced = TRUE, ignore_incompatibility = TRUE)) + return + to_chat(mendicant, span_notice("Your veins (and brain) feel a bit lighter.")) . = TRUE // Because we do our own spin on it! @@ -327,23 +330,28 @@ to_chat(hurtguy, span_notice("Your veins feel thicker, but they itch a bit.")) else to_chat(hurtguy, span_notice("Your veins feel thicker!")) + return + + if(hurtguy.blood_volume < BLOOD_VOLUME_MAXIMUM) + return // Too MUCH blood - if(hurtguy.blood_volume > BLOOD_VOLUME_MAXIMUM) - var/max_blood_to_mendicant = BLOOD_VOLUME_EXCESS - hurtguy.blood_volume - var/blood_to_mendicant = min(max_blood_transfer, max_blood_to_mendicant) - // mender always gonna have blood + var/max_blood_to_mendicant = BLOOD_VOLUME_EXCESS - hurtguy.blood_volume + var/blood_to_mendicant = min(max_blood_transfer, max_blood_to_mendicant) + // mender always gonna have blood - // We ignore incompatibility here. - hurtguy.transfer_blood_to(mendicant, hurtguy.blood_volume - BLOOD_VOLUME_EXCESS, forced = TRUE) - to_chat(hurtguy, span_notice("Your veins don't feel quite so swollen anymore.")) - . = TRUE - // Because we do our own spin on it! - if(mendicant.get_blood_compatibility(hurtguy) == FALSE) - mendicant.adjustToxLoss((blood_to_mendicant * 0.1) * pain_multiplier) // 1 dmg per 10 blood - to_chat(mendicant, span_notice("Your veins swell and itch!")) - else - to_chat(mendicant, span_notice("Your veins swell!")) + // We ignore incompatibility here. + if(!hurtguy.transfer_blood_to(mendicant, hurtguy.blood_volume - BLOOD_VOLUME_EXCESS, forced = TRUE, ignore_incompatibility = TRUE)) + return + + to_chat(hurtguy, span_notice("Your veins don't feel quite so swollen anymore.")) + . = TRUE + // Because we do our own spin on it! + if(mendicant.get_blood_compatibility(hurtguy) == FALSE) + mendicant.adjustToxLoss((blood_to_mendicant * 0.1) * pain_multiplier) // 1 dmg per 10 blood + to_chat(mendicant, span_notice("Your veins swell and itch!")) + else + to_chat(mendicant, span_notice("Your veins swell!")) /datum/action/cooldown/spell/touch/lay_on_hands/proc/determine_if_this_hurts_instead(mob/living/carbon/mendicant, mob/living/hurtguy) diff --git a/code/datums/quirks/negative_quirks/addict.dm b/code/datums/quirks/negative_quirks/addict.dm index f943ea9bb94..2136e319244 100644 --- a/code/datums/quirks/negative_quirks/addict.dm +++ b/code/datums/quirks/negative_quirks/addict.dm @@ -203,7 +203,7 @@ /datum/quirk/item_quirk/addict/alcoholic/post_add() . = ..() - RegisterSignal(quirk_holder, COMSIG_MOB_REAGENT_CHECK, PROC_REF(check_brandy)) + RegisterSignal(quirk_holder, COMSIG_MOB_REAGENT_TICK, PROC_REF(check_brandy)) var/obj/item/reagent_containers/brandy_container = drug_container_type if(isnull(brandy_container)) stack_trace("Alcoholic quirk added while the GLOB.possible_alcoholic_addictions is (somehow) not initialized!") @@ -218,7 +218,7 @@ alcohol_liver.healing_factor = alcohol_liver.healing_factor * 0.75 /datum/quirk/item_quirk/addict/alcoholic/remove() - UnregisterSignal(quirk_holder, COMSIG_MOB_REAGENT_CHECK) + UnregisterSignal(quirk_holder, COMSIG_MOB_REAGENT_TICK) /datum/quirk/item_quirk/addict/alcoholic/proc/check_brandy(mob/source, datum/reagent/booze) SIGNAL_HANDLER diff --git a/code/datums/quirks/negative_quirks/blood_deficiency.dm b/code/datums/quirks/negative_quirks/blood_deficiency.dm index c65208ca9dd..bacdcff80ea 100644 --- a/code/datums/quirks/negative_quirks/blood_deficiency.dm +++ b/code/datums/quirks/negative_quirks/blood_deficiency.dm @@ -17,11 +17,11 @@ var/mob/living/carbon/human/human_holder = quirk_holder if(!istype(human_holder)) return - update_mail(human_quirk_holder = human_holder, new_blood_type = human_holder.dna.blood_type) // matches the mail goodies blood bag to our blood type - RegisterSignal(quirk_holder, COMSIG_LIVING_CHANGED_BLOOD_TYPE, PROC_REF(update_mail)) + update_mail(human_quirk_holder = human_holder, new_blood_type = human_holder.get_bloodtype()) // matches the mail goodies blood bag to our blood type + RegisterSignal(quirk_holder, COMSIG_CARBON_CHANGED_BLOOD_TYPE, PROC_REF(update_mail)) /datum/quirk/blooddeficiency/remove() - UnregisterSignal(quirk_holder, list(COMSIG_HUMAN_ON_HANDLE_BLOOD, COMSIG_LIVING_CHANGED_BLOOD_TYPE)) + UnregisterSignal(quirk_holder, list(COMSIG_HUMAN_ON_HANDLE_BLOOD, COMSIG_CARBON_CHANGED_BLOOD_TYPE)) /datum/quirk/blooddeficiency/is_species_appropriate(datum/species/mob_species) var/datum/species_traits = GLOB.species_prototypes[mob_species].inherent_traits @@ -37,20 +37,17 @@ var/mob/living/carbon/human/human_holder = quirk_holder if(human_holder.stat == DEAD || human_holder.blood_volume <= min_blood) return - // This exotic blood check is solely to snowflake slimepeople into working with this quirk - if(HAS_TRAIT(quirk_holder, TRAIT_NOBLOOD) && isnull(human_holder.dna.species.exotic_blood)) - return - human_holder.blood_volume = max(min_blood, human_holder.blood_volume - human_holder.dna.species.blood_deficiency_drain_rate * seconds_per_tick) + if(!HAS_TRAIT(quirk_holder, TRAIT_NOBLOOD)) + human_holder.blood_volume = max(min_blood, human_holder.blood_volume - human_holder.dna.species.blood_deficiency_drain_rate * seconds_per_tick) /// Try to update the mail goodies to match the quirk holder's blood type. If we fail for whatever reason then it will just default to the initial O- blood pack that we start with. /datum/quirk/blooddeficiency/proc/update_mail(mob/living/carbon/human/human_quirk_holder, datum/blood_type/new_blood_type, update_cached_blood_dna_info) SIGNAL_HANDLER - if(isnull(human_quirk_holder.dna.species.exotic_blood) && isnull(human_quirk_holder.dna.species.exotic_bloodtype)) - if(TRAIT_NOBLOOD in human_quirk_holder.dna.species.inherent_traits) // jellypeople have both exotic_blood and TRAIT_NOBLOOD - mail_goodies.Cut() - return + if(TRAIT_NOBLOOD in human_quirk_holder.dna.species.inherent_traits) + mail_goodies.Cut() + return if(isnull(new_blood_type)) return diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index 9414242fcf6..3e6bc6f0549 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -129,7 +129,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) var/datum/record/locked/lockfile = new( age = person.age, chrono_age = person.chrono_age, // SKYRAT EDIT ADDITION - Chronological age - blood_type = record_dna.blood_type.name, + blood_type = person.get_bloodtype()?.name || "UNKNOWN", character_appearance = character_appearance, dna_string = record_dna.unique_enzymes, fingerprint = md5(record_dna.unique_identity), @@ -151,7 +151,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) new /datum/record/crew( age = person.age, chrono_age = person.chrono_age, // SKYRAT EDIT ADDITION - Chronological age - blood_type = record_dna.blood_type.name, + blood_type = person.get_bloodtype()?.name || "UNKNOWN", character_appearance = character_appearance, dna_string = record_dna.unique_enzymes, fingerprint = md5(record_dna.unique_identity), diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index a50ef89b714..30c04976e01 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -164,12 +164,8 @@ bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += (15 * severity * (limb.current_gauze?.splint_factor || 1)) /datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) + if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE || !victim.can_bleed()) return - if(ishuman(victim)) - var/mob/living/carbon/human/human_victim = victim - if(HAS_TRAIT(human_victim, TRAIT_NOBLOOD)) - return if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg)) var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index f278b29f6b8..0e913d9be6a 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -121,7 +121,11 @@ var/datum/ai_controller/ai_controller /// forensics datum, contains fingerprints, fibres, blood_dna and hiddenprints on this atom - var/datum/forensics/forensics + var/datum/forensics/forensics = null + /// Cached color for all blood on us to avoid doing constant math + var/cached_blood_color = null + /// Cached emissive alpha for all blood on us to avoid doing constant math + var/cached_blood_emissive = null /// How this atom should react to having its astar blocking checked var/can_astar_pass = CANASTARPASS_DENSITY @@ -488,21 +492,21 @@ ///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() != /datum/reagent/blood) + var/datum/blood_type/blood_type = get_bloodtype() + if (!blood_type) return - return list("ANIMAL DNA" = get_blood_type(BLOOD_TYPE_ANIMAL)) + + return list(blood_type.dna_string = blood_type) ///Get the mobs dna list /mob/living/carbon/get_blood_dna_list() - var/list/blood_dna = list() - if(dna) - blood_dna[dna.unique_enzymes] = dna.blood_type - else - blood_dna["UNKNOWN DNA"] = get_blood_type(BLOOD_TYPE_XENO) - return blood_dna + var/datum/blood_type/blood_type = get_bloodtype() + if (!blood_type) + return -/mob/living/carbon/alien/get_blood_dna_list() - return list("UNKNOWN DNA" = get_blood_type(BLOOD_TYPE_XENO)) + if (dna?.unique_enzymes) + return list(dna.unique_enzymes = blood_type) + return list(blood_type.dna_string = blood_type) /mob/living/silicon/get_blood_dna_list() return diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index fe10a55d8bf..17ee25c0c0d 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -1258,7 +1258,7 @@ "UE"=scanner_occupant.dna.unique_enzymes, "UF"=scanner_occupant.dna.unique_features, "name"=scanner_occupant.real_name, - "blood_type"=scanner_occupant.dna.blood_type) + "blood_type"=scanner_occupant.get_bloodtype()?.name) return diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm index b0f36acbfe0..0c7498888a6 100644 --- a/code/game/machinery/computer/operating_computer.dm +++ b/code/game/machinery/computer/operating_computer.dm @@ -123,7 +123,7 @@ data["patient"]["stat"] = "Dead" data["patient"]["statstate"] = "bad" data["patient"]["health"] = patient.health - data["patient"]["blood_type"] = patient.dna?.blood_type.name + data["patient"]["blood_type"] = patient.get_bloodtype()?.name || "UNKNOWN" data["patient"]["maxHealth"] = patient.maxHealth data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD data["patient"]["bruteLoss"] = patient.getBruteLoss() diff --git a/code/game/machinery/experimental_cloner/experimental_cloner_fuckup.dm b/code/game/machinery/experimental_cloner/experimental_cloner_fuckup.dm index 6002ee0476f..681dd8c6ccd 100644 --- a/code/game/machinery/experimental_cloner/experimental_cloner_fuckup.dm +++ b/code/game/machinery/experimental_cloner/experimental_cloner_fuckup.dm @@ -136,7 +136,7 @@ span_boldwarning("[victim]'s flesh slithers off in a disgusting heap!"),\ span_boldwarning("As you emerge from the pod, your skin slithers off onto the ground!")) victim.set_species(/datum/species/skeleton) - new /obj/effect/gibspawner/human/bodypartless(victim.drop_location()) + new /obj/effect/gibspawner/human/bodypartless(victim.drop_location(), victim) /// Become a psyker, possibly the worst fate on this list /datum/experimental_cloner_fuckup/psykerize diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm index a7603303f8d..2a968b7651c 100644 --- a/code/game/machinery/medical_kiosk.dm +++ b/code/game/machinery/medical_kiosk.dm @@ -236,8 +236,9 @@ var/bleed_status = "Patient is not currently bleeding." var/blood_status = " Patient either has no blood, or does not require it to function." - var/blood_percent = round((patient.blood_volume / BLOOD_VOLUME_NORMAL)*100) - var/datum/blood_type/blood_type = patient.dna.blood_type + var/blood_percent = round((patient.blood_volume / BLOOD_VOLUME_NORMAL) * 100) + var/datum/blood_type/blood_type = patient.get_bloodtype() + var/blood_name = "error" var/blood_warning = " " var/blood_alcohol = patient.get_blood_alcohol_content() @@ -247,14 +248,30 @@ sickness = "Warning: Patient is harboring some form of viral disease. Seek further medical attention." sickness_data = "\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]" - if(!HAS_TRAIT(patient, TRAIT_GENELESS) && !HAS_TRAIT(patient, TRAIT_NOBLOOD)) //Blood levels Information + if(patient.can_bleed()) //Blood levels Information + blood_name = LOWER_TEXT(blood_type.get_blood_name()) if(patient.is_bleeding()) - bleed_status = "Patient is currently bleeding!" + bleed_status = " Patient is currently bleeding!" + if(blood_percent <= 80) - blood_warning = " Patient has low blood levels. Seek a large meal, or iron supplements." - if(blood_percent <= 60) - blood_warning = " Patient has DANGEROUSLY low blood levels. Seek a blood transfusion, iron supplements, or saline glucose immedietly. Ignoring treatment may lead to death!" - blood_status = "Patient blood levels are currently reading [blood_percent]%. Patient has [ blood_type.name] type blood. [blood_warning]" + blood_warning = " Patient has [blood_percent <= 60 ? "DANGEROUSLY low" : "low"] [blood_name] levels." + var/list/treatments = list() + if(blood_percent <= 60) + treatments += "[blood_name] transfusion" + else if(!HAS_TRAIT(patient, TRAIT_NOHUNGER)) + treatments += "a large meal" + if(blood_type.restoration_chem) + treatments += "[LOWER_TEXT(blood_type.restoration_chem::name)] supplements" + if(blood_percent <= 60 && blood_type.restoration_chem == /datum/reagent/iron) + treatments += "saline-glucose immediately" + + if (length(treatments)) + blood_warning += " Seek [english_list(treatments, and_text = " or ")]" + + if (blood_percent <= 60) + blood_warning += " Ignoring treatment may lead to death!" + + blood_status = "Patient [blood_name] levels are currently reading [blood_percent]%.[blood_type.get_type() ? " Patient has [blood_type.get_type()] type [blood_name]." : ""][blood_warning]" var/trauma_status = "Patient is free of unique brain trauma." var/brain_loss = patient.get_organ_loss(ORGAN_SLOT_BRAIN) @@ -361,6 +378,7 @@ data["patient_illness"] = sickness data["illness_info"] = sickness_data data["bleed_status"] = bleed_status + data["blood_name"] = capitalize(blood_name) data["blood_levels"] = blood_percent - (chaos_modifier * (rand(1,35))) data["blood_status"] = blood_status data["blood_alcohol"] = blood_alcohol diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index f8986806892..af163f21a80 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -105,15 +105,11 @@ /obj/machinery/recycler/update_overlays() . = ..() - if(!bloody) + if(!bloody || !GET_ATOM_BLOOD_DECAL_LENGTH(src)) return var/mutable_appearance/blood_overlay = mutable_appearance(icon, "[icon_state]bld", appearance_flags = RESET_COLOR|KEEP_APART) - var/blood_dna = GET_ATOM_BLOOD_DNA(src) - if(blood_dna) - blood_overlay.color = get_blood_dna_color(blood_dna) - else - blood_overlay.color = BLOOD_COLOR_RED + blood_overlay.color = get_blood_dna_color() . += blood_overlay /obj/machinery/recycler/CanAllowThrough(atom/movable/mover, border_dir) @@ -263,9 +259,9 @@ if(iscarbon(living_mob)) if(living_mob.stat == CONSCIOUS) living_mob.say("ARRRRRRRRRRRGH!!!", forced= "recycler grinding") - add_mob_blood(living_mob) - if(!bloody && !issilicon(living_mob)) + if(!issilicon(living_mob)) + add_mob_blood(living_mob) bloody = TRUE // Instantly lie down, also go unconscious from the pain, before you die. diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm index 5a8b137c701..f9fb183e53e 100644 --- a/code/game/machinery/telecomms/machines/message_server.dm +++ b/code/game/machinery/telecomms/machines/message_server.dm @@ -50,7 +50,7 @@ /obj/machinery/blackbox_recorder/Destroy() if(stored) stored.forceMove(loc) - new /obj/effect/decal/cleanable/oil(loc) + new /obj/effect/decal/cleanable/blood/oil(loc) return ..() /obj/machinery/blackbox_recorder/update_icon_state() diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index c267c0092d7..adcd251402a 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -1,15 +1,12 @@ /obj/effect/decal/cleanable gender = PLURAL layer = CLEANABLE_FLOOR_OBJECT_LAYER + flags_1 = UNPAINTABLE_1 var/list/random_icon_states = null - ///I'm sorry but cleanable/blood code is ass, and so is blood_DNA - var/blood_state = "" - ///0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints - var/bloodiness = 0 - ///When two of these are on a same tile or do we need to merge them into just one? + /// When two of these are on a same tile or do we need to merge them into just one? var/mergeable_decal = TRUE var/beauty = 0 - ///The type of cleaning required to clean the decal. See __DEFINES/cleaning.dm for the options + /// The type of cleaning required to clean the decal. See __DEFINES/cleaning.dm for the options var/clean_type = CLEAN_TYPE_LIGHT_DECAL ///The reagent this decal holds. Leave blank for none. var/datum/reagent/decal_reagent @@ -19,6 +16,106 @@ /// Set to FALSE for things that hang high on the walls or things which generally shouldn't be mopped up var/is_mopped = TRUE +/obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) + . = ..() + if (LAZYLEN(random_icon_states)) + icon_state = pick(random_icon_states) + base_icon_state = icon_state + + if (isturf(loc)) + for (var/obj/effect/decal/cleanable/other in loc) + if (other != src && other.type == type && !QDELETED(other) && replace_decal(other)) + handle_merge_decal(other) + return INITIALIZE_HINT_QDEL + + if (is_mopped) + ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) + + if (LAZYLEN(diseases)) + add_diseases(diseases) + + AddElement(/datum/element/beauty, beauty) + + var/turf/our_turf = get_turf(src) + if (our_turf && is_station_level(our_turf.z)) + SSblackbox.record_feedback("tally", "station_mess_created", 1, name) + +/obj/effect/decal/cleanable/Destroy() + var/turf/our_turf = get_turf(src) + if (our_turf && is_station_level(our_turf.z)) + SSblackbox.record_feedback("tally", "station_mess_destroyed", 1, name) + return ..() + +/obj/effect/decal/cleanable/proc/add_diseases(list/datum/disease/diseases) + var/list/datum/disease/diseases_to_add = list() + for (var/datum/disease/disease as anything in diseases) + if (disease.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS) + diseases_to_add += disease + if (LAZYLEN(diseases_to_add)) + AddComponent(/datum/component/infective, diseases_to_add) + +/// Check if we should give up in favor of the pre-existing decal +/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/other) + if (mergeable_decal) + return TRUE + +/obj/effect/decal/cleanable/wash(clean_types) + . = ..() + if (. || (clean_types & clean_type)) + qdel(src) + return TRUE + +/obj/effect/decal/cleanable/proc/handle_merge_decal(obj/effect/decal/cleanable/merger) + if (!reagents && !decal_reagent) + return + + if (!reagents && !merger.reagents && (!merger.decal_reagent || merger.decal_reagent == decal_reagent)) + merger.decal_reagent = decal_reagent + merger.reagent_amount += reagent_amount + else if (lazy_init_reagents() && merger.lazy_init_reagents()) + merger.reagents.maximum_volume += reagents.total_volume + reagents.trans_to(merger, reagents.total_volume) + +/// Returns reagents datum if it exists, or lazyloads one if it doesn't +/obj/effect/decal/cleanable/proc/lazy_init_reagents() + if (reagents) + return reagents + + if (!decal_reagent) + return + + create_reagents(reagent_amount) + reagents.add_reagent(decal_reagent, reagent_amount) + +/obj/effect/decal/cleanable/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + // Why are rags cups??? + if (!istype(tool, /obj/item/reagent_containers/cup) || istype(tool, /obj/item/rag)) + return NONE + + if (!lazy_init_reagents()) + to_chat(user, span_notice("[src] isn't thick enough to scoop up!")) + return ITEM_INTERACT_BLOCKING + + if (!reagents.trans_to(tool, reagents.total_volume, transferred_by = user)) + to_chat(user, span_warning("[tool] is full!")) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You scoop up [reagents.total_volume > 0 ? "some of " : ""]\the [src] into \the [tool]!")) + if (!reagents.total_volume) //scooped up all of it + qdel(src) + return ITEM_INTERACT_SUCCESS + +/// Checks if this decal can be bloodcrawled in +/obj/effect/decal/cleanable/proc/can_bloodcrawl_in() + if (decal_reagent == /datum/reagent/blood || reagents?.has_reagent(/datum/reagent/blood)) + return TRUE + + var/list/blood_DNA = GET_ATOM_BLOOD_DECALS(src) + for (var/blood_key in blood_DNA) + var/datum/blood_type/blood_type = blood_DNA[blood_key] + if (blood_type.reagent_type == /datum/reagent/blood) + return TRUE + /// Creates a cleanable decal on a turf /// Use this if your decal is one of one, and thus we should not spawn it if it's there already /// Returns either the existing cleanable, the one we created, or null if we can't spawn on that turf @@ -32,129 +129,6 @@ // There is no need to spam unique cleanables, they don't stack and it just chews cpu var/obj/effect/decal/cleanable/existing = locate(cleanable_type) in checkturf - if(existing) + if (existing) return existing return new cleanable_type(checkturf) - -/obj/effect/decal/cleanable/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) - create_reagents(300) - if(decal_reagent) - reagents.add_reagent(decal_reagent, reagent_amount) - if(loc && isturf(loc)) - for(var/obj/effect/decal/cleanable/C in loc) - if(C != src && C.type == type && !QDELETED(C)) - if (replace_decal(C)) - handle_merge_decal(C) - return INITIALIZE_HINT_QDEL - - if(is_mopped) - ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) - - if(LAZYLEN(diseases)) - var/list/datum/disease/diseases_to_add = list() - for(var/datum/disease/D in diseases) - if(D.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS) - diseases_to_add += D - if(LAZYLEN(diseases_to_add)) - AddComponent(/datum/component/infective, diseases_to_add) - - AddElement(/datum/element/beauty, beauty) - - var/turf/T = get_turf(src) - if(T && is_station_level(T.z)) - SSblackbox.record_feedback("tally", "station_mess_created", 1, name) - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = PROC_REF(on_entered), - ) - AddElement(/datum/element/connect_loc, loc_connections) - -/obj/effect/decal/cleanable/Destroy() - var/turf/T = get_turf(src) - if(T && is_station_level(T.z)) - SSblackbox.record_feedback("tally", "station_mess_destroyed", 1, name) - return ..() - -/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 - -/obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) - if((istype(W, /obj/item/reagent_containers/cup) && !istype(W, /obj/item/rag)) || istype(W, /obj/item/reagent_containers/cup/glass)) - if(src.reagents && W.reagents) - . = 1 //so the containers don't splash their content on the src while scooping. - if(!src.reagents.total_volume) - to_chat(user, span_notice("[src] isn't thick enough to scoop up!")) - return - if(W.reagents.total_volume >= W.reagents.maximum_volume) - to_chat(user, span_notice("[W] is full!")) - return - to_chat(user, span_notice("You scoop up [src] into [W]!")) - reagents.trans_to(W, reagents.total_volume, transferred_by = user) - if(!reagents.total_volume) //scooped up all of it - qdel(src) - return - if(W.get_temperature()) //todo: make heating a reagent holder proc - if(istype(W, /obj/item/cigarette)) - return - else - var/hotness = W.get_temperature() - reagents.expose_temperature(hotness) - to_chat(user, span_notice("You heat [name] with [W]!")) - else - return ..() - -/obj/effect/decal/cleanable/fire_act(exposed_temperature, exposed_volume) - if(reagents) - reagents.expose_temperature(exposed_temperature) - ..() - - -//Add "bloodiness" of this blood's type, to the human's shoes -//This is on /cleanable because fuck this ancient mess -/obj/effect/decal/cleanable/proc/on_entered(datum/source, atom/movable/AM) - SIGNAL_HANDLER - if(iscarbon(AM) && blood_state && bloodiness >= 40) - SEND_SIGNAL(AM, COMSIG_STEP_ON_BLOOD, src) - update_appearance() - -/obj/effect/decal/cleanable/wash(clean_types) - . = ..() - if (. || (clean_types & clean_type)) - qdel(src) - return TRUE - return . - -/** - * Checks if this decal is a valid decal that can be blood crawled in. - */ -/obj/effect/decal/cleanable/proc/can_bloodcrawl_in() - if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY)) - return bloodiness - - return FALSE - -/** - * Gets the color associated with the any blood present on this decal. If there is no blood, returns null. - */ -/obj/effect/decal/cleanable/proc/get_blood_color() - switch(blood_state) - if(BLOOD_STATE_HUMAN) - return rgb(149, 10, 10) - if(BLOOD_STATE_XENO) - return rgb(43, 186, 0) - if(BLOOD_STATE_OIL) - return rgb(22, 22, 22) - - return null - -/obj/effect/decal/cleanable/blood/get_blood_color() - return color || ..() - -/obj/effect/decal/cleanable/proc/handle_merge_decal(obj/effect/decal/cleanable/merger) - if(!merger) - return - if(merger.reagents && reagents) - reagents.trans_to(merger, reagents.total_volume) diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index 74c38afe755..a489e1e3f02 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -1,127 +1,65 @@ // Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code. -/obj/effect/decal/cleanable/xenoblood - name = "xeno blood" +/obj/effect/decal/cleanable/blood/xeno + name = "pool of acid" + // This is fetched in /datum/blood_type/xeno/set_up_blood() for all blood decals with default desc desc = "It's green and acidic. It looks like... blood?" - icon = 'icons/effects/blood.dmi' - icon_state = "floor1" - random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") - bloodiness = BLOOD_AMOUNT_PER_DECAL - blood_state = BLOOD_STATE_XENO - beauty = -250 - clean_type = CLEAN_TYPE_BLOOD + color = /datum/blood_type/xeno::color // For mapper sanity -/obj/effect/decal/cleanable/xenoblood/add_blood_DNA(list/blood_DNA, no_visuals = FALSE) - . = ..() - if(!no_visuals && length(blood_DNA)) - color = get_blood_dna_color(blood_DNA) +/obj/effect/decal/cleanable/blood/xeno/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_XENO) -/obj/effect/decal/cleanable/xenoblood/Initialize(mapload) - . = ..() - add_blood_DNA(list("UNKNOWN DNA" = get_blood_type(BLOOD_TYPE_XENO))) +/obj/effect/decal/cleanable/blood/splatter/xeno + name = "pool of acid" + color = /datum/blood_type/xeno::color // For mapper sanity -/obj/effect/decal/cleanable/xenoblood/xsplatter - random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5") +/obj/effect/decal/cleanable/blood/splatter/xeno/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_XENO) -/obj/effect/decal/cleanable/xenoblood/xgibs +/obj/effect/decal/cleanable/blood/gibs/xeno name = "xeno gibs" desc = "Gnarly..." - icon = 'icons/effects/blood.dmi' icon_state = "xgib1" - plane = GAME_PLANE - layer = GIB_LAYER random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6") - mergeable_decal = FALSE + color = /datum/blood_type/xeno::color // For mapper sanity - is_mopped = TRUE // probably shouldn't be, but janitor powercreep +/obj/effect/decal/cleanable/blood/gibs/xeno/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_XENO) -/obj/effect/decal/cleanable/xenoblood/xgibs/Initialize(mapload) - . = ..() - RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) - update_appearance(UPDATE_OVERLAYS) - -/obj/effect/decal/cleanable/xenoblood/xgibs/update_overlays() - . = ..() - var/mutable_appearance/gib_overlay = mutable_appearance(icon, "[icon_state]-overlay", appearance_flags = KEEP_APART|RESET_COLOR) - if(gib_overlay) - . += gib_overlay - -/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(list/directions, mapload=FALSE) - SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions) - var/direction = pick(directions) - var/delay = 2 - var/range = pick(0, 200; 1, 150; 2, 50; 3, 17; 50) //the 3% chance of 50 steps is intentional and played for laughs. - if(!step_to(src, get_step(src, direction), 0)) - return - if(mapload) - for (var/i in 1 to range) - var/turf/my_turf = get_turf(src) - if(!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf)) - var/obj/effect/decal/cleanable/xenoblood/xsplatter/new_splatter = new /obj/effect/decal/cleanable/xenoblood/xsplatter(my_turf) - new_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - if (!step_to(src, get_step(src, direction), 0)) - break - return - - var/datum/move_loop/loop = GLOB.move_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) - RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) - -/obj/effect/decal/cleanable/xenoblood/xgibs/proc/spread_movement_effects(datum/move_loop/has_target/source) - SIGNAL_HANDLER - if(NeverShouldHaveComeHere(loc)) - return - new /obj/effect/decal/cleanable/xenoblood/xsplatter(loc) - -/obj/effect/decal/cleanable/xenoblood/xgibs/proc/on_pipe_eject(atom/source, direction) - SIGNAL_HANDLER - - var/list/dirs - if(direction) - dirs = list(direction, turn(direction, -45), turn(direction, 45)) - else - dirs = GLOB.alldirs.Copy() - - streak(dirs) - -/obj/effect/decal/cleanable/xenoblood/xgibs/ex_act() - return FALSE - -/obj/effect/decal/cleanable/xenoblood/xgibs/up +/obj/effect/decal/cleanable/blood/gibs/xeno/up icon_state = "xgibup1" random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibup1","xgibup1","xgibup1") -/obj/effect/decal/cleanable/xenoblood/xgibs/down +/obj/effect/decal/cleanable/blood/gibs/xeno/down icon_state = "xgibdown1" random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibdown1","xgibdown1","xgibdown1") -/obj/effect/decal/cleanable/xenoblood/xgibs/body +/obj/effect/decal/cleanable/blood/gibs/xeno/body icon_state = "xgibtorso" random_icon_states = list("xgibhead", "xgibtorso") -/obj/effect/decal/cleanable/xenoblood/xgibs/torso +/obj/effect/decal/cleanable/blood/gibs/xeno/torso icon_state = "xgibtorso" random_icon_states = list("xgibtorso") -/obj/effect/decal/cleanable/xenoblood/xgibs/limb +/obj/effect/decal/cleanable/blood/gibs/xeno/limb icon_state = "xgibleg" random_icon_states = list("xgibleg", "xgibarm") -/obj/effect/decal/cleanable/xenoblood/xgibs/core +/obj/effect/decal/cleanable/blood/gibs/xeno/core icon_state = "xgibmid1" random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3") -/obj/effect/decal/cleanable/xenoblood/xgibs/larva +/obj/effect/decal/cleanable/blood/gibs/xeno/larva icon_state = "xgiblarva1" random_icon_states = list("xgiblarva1", "xgiblarva2") -/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body +/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body icon_state = "xgiblarvatorso" random_icon_states = list("xgiblarvahead", "xgiblarvatorso") -/obj/effect/decal/cleanable/blood/xtracks - icon_state = "tracks" - random_icon_states = null +/obj/effect/decal/cleanable/blood/tracks/xeno + color = /datum/blood_type/xeno::color // For mapper sanity -/obj/effect/decal/cleanable/blood/xtracks/Initialize(mapload) - . = ..() - add_blood_DNA(list("Unknown DNA" = get_blood_type(BLOOD_TYPE_XENO))) +/obj/effect/decal/cleanable/blood/tracks/xeno/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_XENO) diff --git a/code/game/objects/effects/decals/cleanable/blood.dm b/code/game/objects/effects/decals/cleanable/blood.dm new file mode 100644 index 00000000000..b8bf3ff40f1 --- /dev/null +++ b/code/game/objects/effects/decals/cleanable/blood.dm @@ -0,0 +1,895 @@ +/obj/effect/decal/cleanable/blood + name = "pool of blood" + desc = "It's slippery and 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") + beauty = -100 + clean_type = CLEAN_TYPE_BLOOD + color = BLOOD_COLOR_RED + + /// Amount of blood, in units, in this decal + /// Spent when drying or making footprints + var/bloodiness = BLOOD_AMOUNT_PER_DECAL + /// Can this decal dry out? + var/can_dry = TRUE + /// Has this decal dried out already? + var/dried = FALSE + /// If TRUE our bloodiness decreases over time as we dry out + var/decay_bloodiness = TRUE + /// How long we have until the decal fully dries out + var/drying_time = 5 MINUTES + /// How much time it took us to dry from the start to the end + var/total_dry_time = null + /// Emissive value of the blood pool, if any + var/emissive_alpha = 0 + + /// The "base name" of the blood, IE the "pool of" in "pool of blood" + var/base_name = "pool of" + /// Suffix added to the name so we can have "blood trail" where "trail" is the suffix + var/base_suffix = null + /// When dried, this is prefixed to the name + var/dry_prefix = "dried" + /// When dried, this becomes the desc of the blood + var/dry_desc = "Looks like it's been here a while. Eew." + +/* + * diseases - List of diseases to add to this decal on init + * blood_or_dna - Either a blood type which will get added, or a full list of DNA + */ +/obj/effect/decal/cleanable/blood/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna = get_default_blood_type()) + var/can_hold_viruses = TRUE + if(istype(blood_or_dna, /datum/blood_type)) + var/datum/blood_type/default_type = blood_or_dna + can_hold_viruses = default_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA + else if (islist(blood_or_dna)) + can_hold_viruses = FALSE + for (var/blood_key in blood_or_dna) + var/datum/blood_type/blood_type = blood_or_dna[blood_key] + if (blood_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA) + can_hold_viruses = TRUE + break + . = ..(diseases = can_hold_viruses ? diseases : null) + if(islist(blood_or_dna)) + add_blood_DNA(blood_or_dna) + else if(istype(blood_or_dna, /datum/blood_type)) + var/datum/blood_type/default_type = blood_or_dna + add_blood_DNA(list(default_type.dna_string = default_type)) + + if(dried) + dry() + else if(can_dry) + total_dry_time = drying_time + START_PROCESSING(SSblood_drying, src) + + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered) + ) + AddElement(/datum/element/connect_loc, loc_connections) + + if (bloodiness || GET_ATOM_BLOOD_DECAL_LENGTH(src)) + update_appearance() + +/obj/effect/decal/cleanable/blood/Destroy() + STOP_PROCESSING(SSblood_drying, src) + return ..() + +/// Returns the default blood type for this decal for maploaded decals +/obj/effect/decal/cleanable/blood/proc/get_default_blood_type() + return random_human_blood_type() + +// Add "bloodiness" of this blood's type to the human's shoes +/obj/effect/decal/cleanable/blood/proc/on_entered(datum/source, atom/movable/AM) + SIGNAL_HANDLER + + if(dried) + return + + if(isliving(AM) && bloodiness >= 40) + SEND_SIGNAL(AM, COMSIG_STEP_ON_BLOOD, src) + +/obj/effect/decal/cleanable/blood/update_name(updates) + . = ..() + name = initial(name) + if(base_name) + name = "[base_name] [get_blood_string()]" + if(base_suffix) + name = "[base_name ? name : get_blood_string()] [base_suffix]" + if(dried && dry_prefix) + name = "[dry_prefix] [name]" + +/obj/effect/decal/cleanable/blood/update_desc(updates) + . = ..() + desc = initial(desc) + if(dried && dry_desc) + desc = dry_desc + +/// Returns a string of all the blood reagents in the blood +/obj/effect/decal/cleanable/blood/proc/get_blood_string() + var/list/blood_DNA = GET_ATOM_BLOOD_DECALS(src) + var/list/all_blood_names = list() + for(var/dna_sample in blood_DNA) + var/datum/blood_type/blood_type = blood_DNA[dna_sample] + all_blood_names |= LOWER_TEXT(blood_type.get_blood_name()) + return english_list(all_blood_names, nothing_text = "blood") + +/obj/effect/decal/cleanable/blood/update_overlays() + . = ..() + if(icon_state && emissive_alpha && emissive_alpha < alpha && !dried) + . += blood_emissive(icon, icon_state) + +/obj/effect/decal/cleanable/blood/proc/blood_emissive(icon_to_use, icon_state_to_use) + return emissive_appearance(icon_to_use, icon_state_to_use, src, layer, 255 * emissive_alpha / alpha) + +/obj/effect/decal/cleanable/blood/lazy_init_reagents() + if (reagents) + return reagents + + var/list/blood_DNA = GET_ATOM_BLOOD_DNA(src) + var/list/reagents_to_add = list() + for(var/dna_sample in blood_DNA) + var/datum/blood_type/blood_type = blood_DNA[dna_sample] + reagents_to_add += blood_type.reagent_type + + create_reagents(round(bloodiness * BLOOD_TO_UNITS_MULTIPLIER, CHEMICAL_VOLUME_ROUNDING)) + var/num_reagents = length(reagents_to_add) + for(var/reagent_type in reagents_to_add) + reagents.add_reagent(reagent_type, round(bloodiness * BLOOD_TO_UNITS_MULTIPLIER / num_reagents, CHEMICAL_VOLUME_ROUNDING)) + return reagents + +/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/merger) + if(merger.dried) // New blood will lie on dry blood + return FALSE + return ..() + +/obj/effect/decal/cleanable/blood/handle_merge_decal(obj/effect/decal/cleanable/blood/merger) + . = ..() + merger.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + merger.adjust_bloodiness(bloodiness) + +/obj/effect/decal/cleanable/blood/process(seconds_per_tick) + if(dried || !can_dry) + return PROCESS_KILL + + if(decay_bloodiness) + adjust_bloodiness(-bloodiness / drying_time * seconds_per_tick * 1 SECONDS, ignore_timer = TRUE) + + drying_time -= seconds_per_tick * 1 SECONDS + if(drying_time <= 0) + dry() + +/// Slows down the drying time by a given amount, +/// then updates the effect, meaning the animation will slow down +/obj/effect/decal/cleanable/blood/proc/slow_dry(by_amount) + drying_time += by_amount + total_dry_time += by_amount + update_atom_colour() + +/// This is what actually "dries" the blood +/obj/effect/decal/cleanable/blood/proc/dry() + dried = TRUE + // Not deleting as doing so would cause reagents to get lazyloaded again + reagents?.clear_reagents() + update_appearance() + update_atom_colour() + STOP_PROCESSING(SSblood_drying, src) + +/// Increments or decrements the bloodiness value +/obj/effect/decal/cleanable/blood/proc/adjust_bloodiness(by_amount, ignore_timer = FALSE) + if(by_amount == 0) + return FALSE + + if(QDELING(src)) + return FALSE + + bloodiness = clamp((bloodiness + by_amount), 0, BLOOD_POOL_MAX) + if (bloodiness == 0) + dry() + else if (ignore_timer) + slow_dry(5 SECONDS * by_amount * BLOOD_TO_UNITS_MULTIPLIER) + return TRUE + +/obj/effect/decal/cleanable/blood/update_atom_colour() + . = ..() + update_blood_color() + +// When color changes we need to update the drying animation +/obj/effect/decal/cleanable/blood/proc/update_blood_color() + var/base_color = BLOOD_COLOR_RED + // Get a default color based on DNA if it ends up unset somehow + var/list/blood_DNA = GET_ATOM_BLOOD_DECALS(src) + if (!length(blood_DNA)) // In case we're only composed of stuff that doesn't normally have a visual + blood_DNA = GET_ATOM_BLOOD_DNA(src) + if (length(blood_DNA)) + base_color = get_color_from_blood_list(blood_DNA) + + if (!color) + color = base_color + + // Stop ongoing drying animations + animate(src) + + var/dried_color = get_dried_color(base_color) + // If it's dried (or about to dry) we can just set color directly + if(dried || drying_time <= 0) + color = dried_color + return TRUE + + if(!total_dry_time) + return FALSE + + var/dry_coeff = round(1 - drying_time / total_dry_time, 0.01) + // Otherwise set the color to what it should be at the current drying progress, then animate down to the dried color if we can + color = BlendRGB(color, dried_color, dry_coeff) + if(can_dry) + animate(src, time = drying_time, color = dried_color) + return TRUE + +/// Calculates and returns either an RGB or a matrix color for dried blood, depending on whever our current color is RGB or matrix +/// Because BYOND does *not* like animating from text to matrix and vice versa +/obj/effect/decal/cleanable/blood/proc/get_dried_color(base_color) + var/list/starting_color = rgb2num(base_color) + + if (!starting_color) + starting_color = list(255, 255, 255) + + // We want a fixed offset for a fixed drop in color intensity, plus a scaling offset based on our strongest color + // The scaling offset helps keep dark colors from turning black, while also ensurse bright colors don't stay super bright + var/max_color = max(starting_color[1], starting_color[2], starting_color[3]) + var/red_offset = 50 + (75 * (starting_color[1] / max_color)) + var/green_offset = 50 + (75 * (starting_color[2] / max_color)) + var/blue_offset = 50 + (75 * (starting_color[3] / max_color)) + + // If the color is already decently dark, we should reduce the offsets even further + // This is intended to prevent already dark blood (mixed blood in particular) from becoming full black + var/strength = starting_color[1] + starting_color[2] + starting_color[3] + if(strength <= 192) + red_offset *= 0.5 + green_offset *= 0.5 + blue_offset *= 0.5 + + // Finally, get this show on the road + return rgb( + clamp(starting_color[1] - red_offset, 0, 255), + clamp(starting_color[2] - green_offset, 0, 255), + clamp(starting_color[3] - blue_offset, 0, 255), + ) + +/obj/effect/decal/cleanable/blood/old + bloodiness = 0 + dried = TRUE + color = BLOOD_COLOR_DRIED // Just for mappers. Overriden in init + +/obj/effect/decal/cleanable/blood/splatter + icon_state = "gibbl1" + random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5") + +/obj/effect/decal/cleanable/blood/splatter/over_window // special layer/plane set to appear on windows + layer = ABOVE_WINDOW_LAYER + plane = GAME_PLANE + vis_flags = VIS_INHERIT_PLANE + alpha = 180 + is_mopped = FALSE + +/obj/effect/decal/cleanable/blood/splatter/over_window/NeverShouldHaveComeHere(turf/here_turf) + return isgroundlessturf(here_turf) + +/obj/effect/decal/cleanable/blood/tracks + desc = "They look like tracks left by wheels." + icon_state = "tracks" + random_icon_states = null + beauty = -50 + base_name = null + dry_desc = "Some old bloody tracks left by wheels. Machines are evil, perhaps." + +/obj/effect/decal/cleanable/blood/trail_holder + name = "trail of blood" + desc = "Your instincts say you shouldn't be following these." + icon = 'icons/effects/blood.dmi' + icon_state = "trails_1" // For mappers + random_icon_states = null + beauty = -50 + base_name = "trail of" + bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.1 + + /// All the components of the trail + var/list/obj/effect/decal/cleanable/blood/trail/trail_components + +/obj/effect/decal/cleanable/blood/trail_holder/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna = get_default_blood_type()) + . = ..() + icon_state = "nothing" + update_appearance() // Cut possible overlays + if(mapload) + add_dir_to_trail(dir) + +/obj/effect/decal/cleanable/blood/trail_holder/Destroy() + QDEL_LIST_ASSOC_VAL(trail_components) + return ..() + +/** + * Returns the trail component corresponding to the given direction + * + * * for_dir: The direction to get the trail for + * * check_reverse: If TRUE, will also check for the reverse direction + * For example if you pass dir = EAST it will return the first EAST or WEST trail component + * * check_diagonals: If TRUE, will also check for any diagonal directions + * For example if you pass dir = EAST it will return the first EAST, NORTHEAST, or SOUTHEAST trail component + * * check_reverse_diagonals: If TRUE, will also check for any reverse diagonal directions + * For example if you pass dir = EAST it will return the first SOUTHEAST, EAST, NORTHEAST, WEST, SOUTHWEST, or NORTHWEST trail component + */ +/obj/effect/decal/cleanable/blood/trail_holder/proc/get_trail_component(for_dir, check_reverse = FALSE, check_diagonals = FALSE, check_reverse_diagonals = FALSE) + . = LAZYACCESS(trail_components, "[for_dir]") + if(.) + return . + + if(check_reverse) + . = LAZYACCESS(trail_components, "[REVERSE_DIR(for_dir)]") + if(.) + return . + + if(!check_diagonals) + return null + + for(var/comp_dir_txt in trail_components) + var/comp_dir = text2num(comp_dir_txt) + if(comp_dir <= 0) + continue + + if(comp_dir & for_dir) + return LAZYACCESS(trail_components, comp_dir_txt) + + if(check_reverse_diagonals && (comp_dir & REVERSE_DIR(for_dir))) + return LAZYACCESS(trail_components, comp_dir_txt) + + return null + +/** + * Add a new direction to this trail + * + * * new_dir: The direction to add + * * source - Mob we're sourcing blood from, if any + * * blood_to_add - Amount of bloodiness to give to the new component. Does not adjust this decal's own bloodiness + * * half_piece - If TRUE, only creates start of a trail. Does not support corners (diagonal directions) + * This can be a cardinal direction, a diagonal direction, or a negative number to denote a cardinal direction angled 45 degrees. + * + * Returns the new trail, a [/obj/effect/decal/cleanable/blood/trail] + */ +/obj/effect/decal/cleanable/blood/trail_holder/proc/add_dir_to_trail(new_dir = NORTH, mob/living/source, blood_to_add = BLOOD_AMOUNT_PER_DECAL * 0.1, half_piece = FALSE) + var/check_reverse = TRUE + // Do not check the reverse dir if we're a diagonal corner + if (new_dir > 0 && !(new_dir in GLOB.cardinals)) + check_reverse = FALSE + var/obj/effect/decal/cleanable/blood/trail/new_trail = get_trail_component(new_dir, check_reverse = check_reverse, check_diagonals = half_piece) + var/list/blood_DNA = GET_ATOM_BLOOD_DNA(src) + if (source) + // Source's DNA goes first as to override possible matches in non-enzyme DNA + blood_DNA = (source.get_blood_dna_list() || list()) | blood_DNA + + if(new_trail) + // If we found a full trail (straight or diagonal), or a half trail that fully overlaps with us, abort this + if (!new_trail.half_piece || half_piece && LAZYACCESS(trail_components, "[new_dir]") == new_trail) + new_trail.adjust_bloodiness(blood_to_add) + if (source) + new_trail.add_mob_blood(source) + return new_trail + + // We've found a mirrored half-piece, so we should merge into a full piece + // Alternatively, we've found a half piece while being a straight piece that overlaps with it + // in which case we just overlap with it which should get us the same full piece + new_trail.half_piece = FALSE + new_trail.update_appearance() + new_trail.adjust_bloodiness(blood_to_add) + if (source) + new_trail.add_mob_blood(source) + return new_trail + + // There's a chance that we're on the same tile as a diagonal corner, in which case we need to check for those too + if (half_piece && new_dir > 0) + var/first_dir = (new_dir & (NORTH|SOUTH)) ? EAST : NORTH + var/second_dir = (new_dir & (NORTH|SOUTH)) ? WEST : SOUTH + new_trail = get_trail_component(new_dir | first_dir) || get_trail_component(new_dir | second_dir) + // Found a diagonal overlapping with us, abort + if (new_trail) + new_trail.adjust_bloodiness(blood_to_add) + if (source) + new_trail.add_mob_blood(source) + return new_trail + + // Look for perpendicular pieces to merge into a diagonal with + new_trail = get_trail_component(first_dir) + if (!new_trail?.half_piece) + new_trail = get_trail_component(second_dir) + + if (new_trail?.half_piece) + new_trail.half_piece = FALSE + LAZYREMOVE(trail_components, "[new_trail.dir]") + new_trail.setDir(new_dir | new_trail.dir) + LAZYSET(trail_components, "[new_trail.dir]", new_trail) + new_trail.update_appearance() + new_trail.adjust_bloodiness(blood_to_add) + if (source) + new_trail.add_mob_blood(source) + return new_trail + + new_trail = new(src, source?.get_static_viruses(), blood_DNA) + if (half_piece) + new_trail.half_piece = TRUE + new_trail.update_appearance() + + new_trail.adjust_bloodiness(blood_to_add - new_trail.bloodiness) + + if(new_dir > 0) + // add some free sprite variation by flipping it around + if((new_dir in GLOB.cardinals) && prob(50) && !half_piece) + new_trail.setDir(REVERSE_DIR(new_dir)) + // otherwise the dir is the same + else + new_trail.setDir(new_dir) + // negative dirs denote "straight diagonal" dirs + else + var/real_dir = abs(new_dir) + new_trail.setDir(real_dir & (EAST|WEST)) + switch(real_dir) + if(NORTHEAST) + new_trail.transform = new_trail.transform.Turn(-45) + if(NORTHWEST) + new_trail.transform = new_trail.transform.Turn(45) + if(SOUTHEAST) + new_trail.transform = new_trail.transform.Turn(-135) + if(SOUTHWEST) + new_trail.transform = new_trail.transform.Turn(135) + + LAZYSET(trail_components, "[new_dir]", new_trail) + vis_contents += new_trail + return new_trail + +/obj/effect/decal/cleanable/blood/trail + name = "blood trail" + desc = "A trail of blood." + icon_state = "ltrails_1" + random_icon_states = list("ltrails_1", "ltrails_2") + vis_flags = VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID + appearance_flags = parent_type::appearance_flags | RESET_COLOR | KEEP_APART + beauty = -50 + decay_bloodiness = FALSE // bloodiness is used as a metric for for how big the sprite is, so don't decay passively + bloodiness = BLOOD_AMOUNT_PER_DECAL * 0.1 + base_suffix = "trail" + /// Is this just half of a trail + var/half_piece = FALSE + /// Beyond a threshold we change to a bloodier icon state + var/very_bloody = FALSE + +/obj/effect/decal/cleanable/blood/update_desc(updates) + . = ..() + desc = "A [dried ? "dried " : ""]trail of [get_blood_string()]." + +/obj/effect/decal/cleanable/blood/lazy_init_reagents() + if(!istype(loc, /obj/effect/decal/cleanable/blood/trail_holder)) + return ..() + +/obj/effect/decal/cleanable/blood/trail/adjust_bloodiness(by_amount, ignore_timer = FALSE) + . = ..() + if(very_bloody || bloodiness < 0.25 * BLOOD_AMOUNT_PER_DECAL) + return + + very_bloody = TRUE + icon_state = pick("trails_1", "trails_2") + base_icon_state = icon_state + update_appearance() + +/obj/effect/decal/cleanable/blood/trail/update_icon(updates) + if (half_piece) + icon_state = "[base_icon_state]_start" + else + icon_state = base_icon_state + return ..() + +/obj/effect/decal/cleanable/blood/gibs + name = "gibs" + desc = "They look extremely gruesome." + icon_state = "gib1" + layer = GIB_LAYER + plane = GAME_PLANE + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") + mergeable_decal = FALSE + + base_name = null + dry_prefix = "rotting" + dry_desc = "They look extremely gruesome as some terrible smell fills the air." + decal_reagent = /datum/reagent/consumable/liquidgibs + reagent_amount = 5 + is_mopped = TRUE // probably shouldn't be, but janitor powercreep + + /// Lazylist with information about the diseases our streaking spawns + var/list/streak_diseases + /// Do these gibs produce squishy sounds? + var/squishy = TRUE + /// Do these gibs have a separate non-blood-colored overlay? + var/has_overlay = TRUE + /// Should we be creating blood decals as we streak? + var/leave_blood = TRUE + +/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna = get_default_blood_type()) + . = ..() + leave_blood = has_blood_flag(GET_ATOM_BLOOD_DNA(src), BLOOD_COVER_TURFS) + if(squishy) + AddElement(/datum/element/squish_sound) + RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) + update_appearance(UPDATE_OVERLAYS) + +/obj/effect/decal/cleanable/blood/gibs/update_overlays() + . = ..() + if(!has_overlay) + return + var/mutable_appearance/gib_overlay = mutable_appearance(icon, "[icon_state]-overlay", appearance_flags = KEEP_APART|RESET_COLOR) + if(dried) + gib_overlay.color = COLOR_GRAY + else if (total_dry_time) + gib_overlay.color = BlendRGB(COLOR_WHITE, COLOR_GRAY, 1 - drying_time / total_dry_time) + . += gib_overlay + +/obj/effect/decal/cleanable/blood/gibs/get_blood_string() + return null + +/obj/effect/decal/cleanable/blood/gibs/Destroy() + LAZYNULL(streak_diseases) + return ..() + +/obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C) + return FALSE //Never fail to place us + +/obj/effect/decal/cleanable/blood/gibs/dry() + . = ..() + if(!.) + return + // AddComponent(/datum/component/rot, 0, 5 MINUTES, 0.7) SKYRAT EDIT REMOVAL + update_appearance(UPDATE_OVERLAYS) + +/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target) + return FALSE + +/obj/effect/decal/cleanable/blood/gibs/proc/on_pipe_eject(atom/source, direction) + SIGNAL_HANDLER + + var/list/dirs + if(direction) + dirs = list(direction, turn(direction, -45), turn(direction, 45)) + else + dirs = GLOB.alldirs.Copy() + + streak(dirs) + +/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions, mapload = FALSE) + SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions) + var/direction = pick(directions) + var/delay = 2 + var/range = pick(0, 200; 1, 150; 2, 50; 3, 17; 50) //the 3% chance of 50 steps is intentional and played for laughs. + if(!step_to(src, get_step(src, direction), 0)) + return + + if(!mapload) + var/datum/move_loop/loop = GLOB.move_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + if (leave_blood) + RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) + return + + for (var/i in 1 to range) + if (leave_blood) + create_splatter() + + if (!step_to(src, get_step(src, direction), 0)) + break + +/obj/effect/decal/cleanable/blood/gibs/proc/create_splatter() + var/turf/my_turf = get_turf(src) + if(!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf)) + new /obj/effect/decal/cleanable/blood/splatter(my_turf, streak_diseases, GET_ATOM_BLOOD_DNA(src)) + +/obj/effect/decal/cleanable/blood/gibs/proc/spread_movement_effects(datum/move_loop/has_target/source) + SIGNAL_HANDLER + if(!NeverShouldHaveComeHere(loc)) + new /obj/effect/decal/cleanable/blood/splatter(loc, streak_diseases, GET_ATOM_BLOOD_DNA(src)) + +/obj/effect/decal/cleanable/blood/gibs/up + icon_state = "gibup1" + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1") + +/obj/effect/decal/cleanable/blood/gibs/down + icon_state = "gibdown1" + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1") + +/obj/effect/decal/cleanable/blood/gibs/body + icon_state = "gibtorso" + random_icon_states = list("gibhead", "gibtorso") + +/obj/effect/decal/cleanable/blood/gibs/torso + icon_state = "gibtorso" + random_icon_states = null + +/obj/effect/decal/cleanable/blood/gibs/limb + icon_state = "gibleg" + random_icon_states = list("gibleg", "gibarm") + +/obj/effect/decal/cleanable/blood/gibs/core + icon_state = "gibmid1" + 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? They smell terrible." + color = BLOOD_COLOR_DRIED // Just for mappers. Overriden in init + bloodiness = 0 + dried = TRUE + dry_prefix = null + dry_desc = null + +/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna = get_default_blood_type()) + . = ..() + setDir(pick(GLOB.cardinals)) + AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10) + +/obj/effect/decal/cleanable/blood/drip + name = "drop of blood" + desc = "A spattering." + icon_state = "drip5" //using drip5 since the others tend to blend in with pipes & wires. + random_icon_states = list("drip1","drip2","drip3","drip4","drip5") + bloodiness = 0 + base_name = "drop of" + dry_desc = "A dried spattering." + +/obj/effect/decal/cleanable/blood/footprints + name = "footprints" + desc = "WHOSE FOOTPRINTS ARE THESE?" + icon = 'icons/effects/footprints.dmi' + icon_state = "blood1" + random_icon_states = null + appearance_flags = parent_type::appearance_flags | KEEP_TOGETHER + bloodiness = 0 // set based on the bloodiness of the foot + base_name = null + dry_desc = "HMM... SOMEONE WAS HERE!" + + var/entered_dirs = 0 + var/exited_dirs = 0 + + /// Lazylist of shoe or other clothing that covers feet types that have made footprints here. + var/list/shoe_types + + /// Lazylist of species that have made footprints here. + var/list/species_types + +/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna = get_default_blood_type()) + . = ..() + icon_state = "" // All of the footprint visuals come from overlays + if(mapload) + entered_dirs |= dir // Keep the same appearance as in the map editor + update_appearance() + +/obj/effect/decal/cleanable/blood/footprints/get_blood_string() + return null + +//Rotate all of the footprint directions too +/obj/effect/decal/cleanable/blood/footprints/setDir(newdir) + if(dir == newdir) + return ..() + + var/ang_change = dir2angle(newdir) - dir2angle(dir) + var/old_entered_dirs = entered_dirs + var/old_exited_dirs = exited_dirs + entered_dirs = NONE + exited_dirs = NONE + + for(var/Ddir in GLOB.cardinals) + if(old_entered_dirs & Ddir) + entered_dirs |= angle2dir_cardinal(dir2angle(Ddir) + ang_change) + if(old_exited_dirs & Ddir) + exited_dirs |= angle2dir_cardinal(dir2angle(Ddir) + ang_change) + + update_appearance() + return ..() + +/obj/effect/decal/cleanable/blood/footprints/update_overlays() + . = ..() + var/static/list/bloody_footprints_cache = list() + var/icon_state_to_use = "blood" + if(LAZYACCESS(species_types, BODYPART_ID_DIGITIGRADE)) + icon_state_to_use += "claw" + else if(LAZYACCESS(species_types, SPECIES_MONKEY)) + icon_state_to_use += "paw" + else if(LAZYACCESS(species_types, "bot")) + icon_state_to_use += "bot" + + for(var/Ddir in GLOB.cardinals) + if(entered_dirs & Ddir) + var/enter_state = "entered-[icon_state_to_use]-[Ddir]" + var/image/bloodstep_overlay = bloody_footprints_cache[enter_state] + if(!bloodstep_overlay) + bloodstep_overlay = image(icon, "[icon_state_to_use]1", dir = Ddir) + bloody_footprints_cache[enter_state] = bloodstep_overlay + . += bloodstep_overlay + + if(emissive_alpha && emissive_alpha < alpha && !dried) + var/enter_emissive_state = "[enter_state]_emissive-[emissive_alpha]" + var/mutable_appearance/emissive_overlay = bloody_footprints_cache[enter_emissive_state] + if(!emissive_overlay) + emissive_overlay = blood_emissive(icon, "[icon_state_to_use]1") + emissive_overlay.dir = Ddir + bloody_footprints_cache[enter_emissive_state] = emissive_overlay + . += emissive_overlay + + if(exited_dirs & Ddir) + var/exit_state = "exited-[icon_state_to_use]-[Ddir]" + var/image/bloodstep_overlay = bloody_footprints_cache[exit_state] + if(!bloodstep_overlay) + bloodstep_overlay = image(icon, "[icon_state_to_use]2", dir = Ddir) + bloody_footprints_cache[exit_state] = bloodstep_overlay + . += bloodstep_overlay + + if(emissive_alpha && emissive_alpha < alpha && !dried) + var/exit_emissive_state = "[exit_state]_emissive-[emissive_alpha]" + var/mutable_appearance/emissive_overlay = bloody_footprints_cache[exit_emissive_state] + if(!emissive_overlay) + emissive_overlay = blood_emissive(icon, "[icon_state_to_use]2") + emissive_overlay.dir = Ddir + bloody_footprints_cache[exit_emissive_state] = emissive_overlay + . += emissive_overlay + +/obj/effect/decal/cleanable/blood/footprints/examine(mob/user) + . = ..() + if(LAZYLEN(species_types) + LAZYLEN(shoe_types) == 0) + return + + . += "You recognise the footprints as belonging to:" + for(var/obj/item/clothing/shoes/sole as anything in shoe_types) + var/article = initial(sole.article) || (initial(sole.gender) == PLURAL ? "Some" : "A") + . += "[icon2html(initial(sole.icon), user, initial(sole.icon_state))] [article] [initial(sole.name)]." + + for(var/species in species_types) + switch(species) + if("unknown") + . += "• Some creature's feet." + if(SPECIES_MONKEY) + . += "• Some monkey feet." + if(SPECIES_HUMAN) + . += "• Some human feet." + else + . += "• Some [species] feet." + +/obj/effect/decal/cleanable/blood/hitsplatter + name = "blood splatter" + pass_flags = PASSTABLE | PASSGRILLE + icon_state = "hitsplatter1" + random_icon_states = list("hitsplatter1", "hitsplatter2", "hitsplatter3") + + plane = GAME_PLANE + layer = ABOVE_WINDOW_LAYER + is_mopped = FALSE + + base_name = null + base_suffix = "splatter" + can_dry = FALSE // No point + + /// The turf we just came from, so we can back up when we hit a wall + var/turf/prev_loc + /// Skip making the final blood splatter when we're done, like if we're not in a turf + var/skip = FALSE + /// How many tiles/items/people we can paint red + var/splatter_strength = 3 + /// Insurance so that we don't keep moving once we hit a stoppoint + var/hit_endpoint = FALSE + /// How fast the splatter moves + var/splatter_speed = 0.1 SECONDS + /// Tracks what direction we're flying + var/flight_dir = NONE + /// Should we be leaving any decals, or just adding DNA to mobs? + var/leave_blood = TRUE + +/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna = get_default_blood_type(), splatter_strength) + . = ..() + leave_blood = has_blood_flag(GET_ATOM_BLOOD_DNA(src), BLOOD_COVER_TURFS) + prev_loc = loc //Just so we are sure prev_loc exists + if(splatter_strength) + src.splatter_strength = splatter_strength + +/obj/effect/decal/cleanable/blood/hitsplatter/proc/expire() + if(isturf(loc) && !skip) + playsound(src, 'sound/effects/wounds/splatter.ogg', 60, TRUE, -1) + loc.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + qdel(src) + +/// Set the splatter up to fly through the air until it rounds out of steam or hits something +/obj/effect/decal/cleanable/blood/hitsplatter/proc/fly_towards(turf/target_turf, range) + flight_dir = get_dir(src, target_turf) + var/datum/move_loop/loop = GLOB.move_manager.move_towards(src, target_turf, splatter_speed, timeout = splatter_speed * range, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_START_FAST) + RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) + RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) + RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(loop_done)) + +/obj/effect/decal/cleanable/blood/hitsplatter/proc/pre_move(datum/move_loop/source) + SIGNAL_HANDLER + prev_loc = loc + +/obj/effect/decal/cleanable/blood/hitsplatter/proc/post_move(datum/move_loop/source) + SIGNAL_HANDLER + if(loc == prev_loc || !isturf(loc)) + return + + for(var/atom/movable/iter_atom in loc) + if(hit_endpoint) + return + if(iter_atom == src || iter_atom.invisibility || iter_atom.alpha <= 0 || (isobj(iter_atom) && !iter_atom.density)) + continue + if(splatter_strength <= 0) + break + iter_atom.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + + splatter_strength-- + // we used all our blood so go away + if(splatter_strength <= 0) + expire() + return + + if(!leave_blood) + loc.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + return + + // make a trail + var/obj/effect/decal/cleanable/blood/fly_trail = new(loc, null, GET_ATOM_BLOOD_DNA(src)) + fly_trail.dir = dir + if(ISDIAGONALDIR(flight_dir)) + fly_trail.transform = fly_trail.transform.Turn((flight_dir == NORTHEAST || flight_dir == SOUTHWEST) ? 135 : 45) + fly_trail.icon_state = pick("trails_1", "trails_2") + fly_trail.adjust_bloodiness(fly_trail.bloodiness * -0.66) + fly_trail.update_appearance() + +/obj/effect/decal/cleanable/blood/hitsplatter/proc/loop_done(datum/source) + SIGNAL_HANDLER + if(!QDELETED(src)) + expire() + +/obj/effect/decal/cleanable/blood/hitsplatter/Bump(atom/bumped_atom) + if(!iswallturf(bumped_atom) && !istype(bumped_atom, /obj/structure/window)) + expire() + return + + if(istype(bumped_atom, /obj/structure/window)) + var/obj/structure/window/bumped_window = bumped_atom + if(!bumped_window.fulltile) + hit_endpoint = TRUE + expire() + return + + hit_endpoint = TRUE + if(!isturf(prev_loc)) // This will only happen if prev_loc is not even a turf, which is highly unlikely. + abstract_move(bumped_atom) + expire() + return + + abstract_move(bumped_atom) + skip = TRUE + //Adjust pixel offset to make splatters appear on the wall + if(istype(bumped_atom, /obj/structure/window)) + if(land_on_window(bumped_atom)) + return + + if(!leave_blood) + prev_loc.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + return + + var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new(prev_loc, null, GET_ATOM_BLOOD_DNA(src)) + final_splatter.pixel_x = (dir == EAST ? 32 : (dir == WEST ? -32 : 0)) + final_splatter.pixel_y = (dir == NORTH ? 32 : (dir == SOUTH ? -32 : 0)) + +/// A special case for hitsplatters hitting windows, since those can actually be moved around, store it in the window and slap it in the vis_contents +/obj/effect/decal/cleanable/blood/hitsplatter/proc/land_on_window(obj/structure/window/the_window) + if(!leave_blood) + the_window.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) + return TRUE + + if(!the_window.fulltile) + return FALSE + + var/obj/effect/decal/cleanable/final_splatter = new /obj/effect/decal/cleanable/blood/splatter/over_window(prev_loc, null, GET_ATOM_BLOOD_DNA(src)) + final_splatter.forceMove(the_window) + the_window.vis_contents += final_splatter + expire() + return TRUE diff --git a/code/game/objects/effects/decals/cleanable/food.dm b/code/game/objects/effects/decals/cleanable/food.dm index d612bd9e7f5..911f1ba4f14 100644 --- a/code/game/objects/effects/decals/cleanable/food.dm +++ b/code/game/objects/effects/decals/cleanable/food.dm @@ -35,6 +35,13 @@ icon_state = "salt_pile" var/safepasses = 3 //how many times can this salt pile be passed before dissipating +/obj/effect/decal/cleanable/food/salt/Initialize(mapload, list/datum/disease/diseases) + . = ..() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(on_entered) + ) + AddElement(/datum/element/connect_loc, loc_connections) + /obj/effect/decal/cleanable/food/salt/CanAllowThrough(atom/movable/mover, border_dir) . = ..() if(is_species(mover, /datum/species/snail)) @@ -45,14 +52,17 @@ if(is_species(AM, /datum/species/snail)) to_chat(AM, span_danger("Your path is obstructed by [span_phobia("salt")].")) -/obj/effect/decal/cleanable/food/salt/on_entered(datum/source, atom/movable/AM) - . = ..() +/obj/effect/decal/cleanable/food/salt/proc/on_entered(datum/source, atom/movable/AM) + SIGNAL_HANDLER + if(!isliving(AM)) return + if(iscarbon(AM)) var/mob/living/carbon/C = AM if(C.move_intent == MOVE_INTENT_WALK) return + safepasses-- if(safepasses <= 0 && !QDELETED(src)) qdel(src) @@ -65,7 +75,7 @@ /obj/effect/decal/cleanable/food/squid_ink name = "ink smear" desc = "a smear from some inky substance..." - icon = 'icons/mob/silicon/robots.dmi' + icon = 'icons/effects/blood.dmi' icon_state = "floor1" color = COLOR_DARK diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm deleted file mode 100644 index 35b5d5830f1..00000000000 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ /dev/null @@ -1,508 +0,0 @@ -/obj/effect/decal/cleanable/blood - name = "blood" - desc = "It's red and 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 - beauty = -100 - clean_type = CLEAN_TYPE_BLOOD - color = BLOOD_COLOR_RED - var/should_dry = TRUE - var/dryname = "dried blood" //when the blood lasts long enough, it becomes dry and gets a new name - var/drydesc = "Looks like it's been here a while. Eew." //as above - var/drytime = 0 - var/footprint_sprite = null - /// If we've dried already - var/has_dried - -/obj/effect/decal/cleanable/blood/Initialize(mapload) - . = ..() - if(!should_dry) - return - if(bloodiness) - start_drying() - else - dry(freshly_made = TRUE) - -/obj/effect/decal/cleanable/blood/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/decal/cleanable/blood/process() - if(world.time > drytime) - dry() - -/obj/effect/decal/cleanable/blood/add_blood_DNA(list/blood_DNA, no_visuals = FALSE) - . = ..() - if(!no_visuals && length(blood_DNA)) - color = get_blood_dna_color(blood_DNA) - -/obj/effect/decal/cleanable/blood/proc/get_timer() - drytime = world.time + 3 MINUTES - -/obj/effect/decal/cleanable/blood/proc/start_drying() - get_timer() - START_PROCESSING(SSobj, src) - -///This is what actually "dries" the blood. Returns true if it's all out of blood to dry, and false otherwise -/obj/effect/decal/cleanable/blood/proc/dry(freshly_made = FALSE) - if(freshly_made) - start_drying() - return FALSE - if(bloodiness > 20) - bloodiness -= BLOOD_AMOUNT_PER_DECAL - get_timer() - return FALSE - - name = dryname - has_dried = TRUE - desc = drydesc - bloodiness = 0 - STOP_PROCESSING(SSobj, src) - // We're not using a matrix so we're free to use BlendRGB - if(!islist(color)) - add_atom_colour(BlendRGB(color, COLOR_BLACK, 0.5), FIXED_COLOUR_PRIORITY) - return TRUE - - // We're using a matrix, so we need to halve all values - var/list/blood_matrix = color - for(var/i in 1 to min(length(blood_matrix), 16)) - if (length(blood_matrix) == 12 && i > 9) // Don't modify constants - break - if (length(blood_matrix) >= 16 && i % 4 == 0) // Don't modify alpha either - continue - blood_matrix[i] *= 0.5 - color = blood_matrix - return TRUE - -/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) - C.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - if (bloodiness) - C.bloodiness = min((C.bloodiness + bloodiness), BLOOD_AMOUNT_PER_DECAL) - return ..() - -/obj/effect/decal/cleanable/blood/old - bloodiness = 0 - icon_state = "floor1-old" - -/obj/effect/decal/cleanable/blood/old/Initialize(mapload, list/datum/disease/diseases) - add_blood_DNA(list("Non-human DNA" = random_human_blood_type())) // Needs to happen before ..() - return ..() - -/obj/effect/decal/cleanable/blood/splatter - icon_state = "gibbl1" - random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5") - -/obj/effect/decal/cleanable/blood/splatter/over_window // special layer/plane set to appear on windows - layer = ABOVE_WINDOW_LAYER - plane = GAME_PLANE - vis_flags = VIS_INHERIT_PLANE - alpha = 180 - is_mopped = FALSE - -/obj/effect/decal/cleanable/blood/splatter/over_window/NeverShouldHaveComeHere(turf/here_turf) - return isgroundlessturf(here_turf) - -/obj/effect/decal/cleanable/blood/tracks - icon_state = "tracks" - desc = "They look like tracks left by wheels." - random_icon_states = null - beauty = -50 - dryname = "dried tracks" - drydesc = "Some old bloody tracks left by wheels. Machines are evil, perhaps." - -/obj/effect/decal/cleanable/blood/trail_holder - name = "blood" - desc = "Your instincts say you shouldn't be following these." - icon = 'icons/effects/blood.dmi' - icon_state = null - random_icon_states = null - beauty = -50 - var/list/existing_dirs = list() - -/obj/effect/decal/cleanable/blood/trail_holder/replace_decal(obj/effect/decal/cleanable/blood/trail_holder/blood_decal) - if(blood_state != blood_decal.blood_state) - return FALSE - return ..() - -// normal version of the above trail holder object for use in less convoluted things -/obj/effect/decal/cleanable/blood/trails - desc = "Looks like a corpse was smeared all over the floor like ketchup. Kinda makes you hungry." - random_icon_states = list("trails_1", "trails_2") - icon_state = "trails_1" - beauty = -50 - dryname = "dried tracks" - drydesc = "Looks like a corpse was smeared all over the floor like ketchup, but it's all dried up and nasty now, ew. You lose some of your appetite." - -/obj/effect/decal/cleanable/blood/gibs - name = "gibs" - desc = "They look bloody and gruesome." - icon = 'icons/effects/blood.dmi' - icon_state = "gib1" - layer = GIB_LAYER - plane = GAME_PLANE - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") - mergeable_decal = FALSE - - dryname = "rotting gibs" - drydesc = "They look bloody and gruesome while some terrible smell fills the air." - decal_reagent = /datum/reagent/consumable/liquidgibs - reagent_amount = 5 - - is_mopped = TRUE // probably shouldn't be, but janitor powercreep - -/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases) - . = ..() - AddElement(/datum/element/squish_sound) - RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) - update_appearance(UPDATE_OVERLAYS) - -/obj/effect/decal/cleanable/blood/gibs/update_overlays() - . = ..() - var/mutable_appearance/gib_overlay = mutable_appearance(icon, "[icon_state]-overlay", appearance_flags = KEEP_APART|RESET_COLOR) - if(gib_overlay) - if(has_dried) - gib_overlay.color = COLOR_GRAY - . += gib_overlay - -/obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C) - return FALSE //Never fail to place us - -/obj/effect/decal/cleanable/blood/gibs/dry(freshly_made = FALSE) - . = ..() - if(!.) - return - update_appearance(UPDATE_OVERLAYS) - //AddComponent(/datum/component/rot, 0, 5 MINUTES, 0.7) skyrat edit - -/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target) - return FALSE - -/obj/effect/decal/cleanable/blood/gibs/proc/on_pipe_eject(atom/source, direction) - SIGNAL_HANDLER - - var/list/dirs - if(direction) - dirs = list(direction, turn(direction, -45), turn(direction, 45)) - else - dirs = GLOB.alldirs.Copy() - - streak(dirs) - -/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions, mapload=FALSE) - SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions) - var/direction = pick(directions) - var/delay = 2 - var/range = pick(0, 200; 1, 150; 2, 50; 3, 17; 50) //the 3% chance of 50 steps is intentional and played for laughs. - if(!step_to(src, get_step(src, direction), 0)) - return - - if(!mapload) - var/datum/move_loop/loop = GLOB.move_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) - RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) - return - - for (var/i in 1 to range) - var/turf/my_turf = get_turf(src) - if(!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf)) - var/obj/effect/decal/cleanable/blood/splatter/new_splatter = new /obj/effect/decal/cleanable/blood/splatter(my_turf) - new_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - - if (!step_to(src, get_step(src, direction), 0)) - break - -/obj/effect/decal/cleanable/blood/gibs/proc/spread_movement_effects(datum/move_loop/has_target/source) - SIGNAL_HANDLER - if(NeverShouldHaveComeHere(loc)) - return - var/obj/effect/decal/cleanable/blood/splatter/new_splatter = new /obj/effect/decal/cleanable/blood/splatter(loc) - new_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - -/obj/effect/decal/cleanable/blood/gibs/up - icon_state = "gibup1" - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1") - -/obj/effect/decal/cleanable/blood/gibs/down - icon_state = "gibdown1" - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1") - -/obj/effect/decal/cleanable/blood/gibs/body - icon_state = "gibtorso" - random_icon_states = list("gibhead", "gibtorso") - -/obj/effect/decal/cleanable/blood/gibs/torso - icon_state = "gibtorso" - random_icon_states = null - -/obj/effect/decal/cleanable/blood/gibs/limb - icon_state = "gibleg" - random_icon_states = list("gibleg", "gibarm") - -/obj/effect/decal/cleanable/blood/gibs/core - icon_state = "gibmid1" - 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? They smell terrible." - icon_state = "gib1-old" - bloodiness = 0 - should_dry = FALSE - dryname = "old rotting gibs" - drydesc = "Space Jesus, why didn't anyone clean this up? They smell terrible." - -/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases) - . = ..() - setDir(pick(1,2,4,8)) - add_blood_DNA(list("Non-human DNA" = random_human_blood_type())) - AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10) - dry() - -/obj/effect/decal/cleanable/blood/drip - name = "drips of blood" - desc = "It's red." - icon_state = "drip5" //using drip5 since the others tend to blend in with pipes & wires. - random_icon_states = list("drip1","drip2","drip3","drip4","drip5") - bloodiness = 0 - var/drips = 1 - dryname = "drips of blood" - drydesc = "It's red." - -/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in() - return TRUE - -//BLOODY FOOTPRINTS -/obj/effect/decal/cleanable/blood/footprints - name = "footprints" - desc = "WHOSE FOOTPRINTS ARE THESE?" - icon = 'icons/effects/footprints.dmi' - icon_state = "blood_shoes_enter" - random_icon_states = null - blood_state = BLOOD_STATE_HUMAN //the icon state to load images from - var/entered_dirs = 0 - var/exited_dirs = 0 - - /// List of shoe or other clothing that covers feet types that have made footprints here. - var/list/shoe_types = list() - - /// List of species that have made footprints here. - var/list/species_types = list() - - dryname = "dried footprints" - drydesc = "HMM... SOMEONE WAS HERE!" - -/obj/effect/decal/cleanable/blood/footprints/get_save_vars() - return ..() - NAMEOF(src, icon_state) - -/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, footprint_sprite) - src.footprint_sprite = footprint_sprite - . = ..() - icon_state = "" //All of the footprint visuals come from overlays - if(mapload) - entered_dirs |= dir //Keep the same appearance as in the map editor - update_appearance(mapload ? (ALL) : (UPDATE_NAME | UPDATE_DESC)) - -//Rotate all of the footprint directions too -/obj/effect/decal/cleanable/blood/footprints/setDir(newdir) - if(dir == newdir) - return ..() - - var/ang_change = dir2angle(newdir) - dir2angle(dir) - var/old_entered_dirs = entered_dirs - var/old_exited_dirs = exited_dirs - entered_dirs = 0 - exited_dirs = 0 - - for(var/Ddir in GLOB.cardinals) - if(old_entered_dirs & Ddir) - entered_dirs |= turn_cardinal(Ddir, ang_change) - if(old_exited_dirs & Ddir) - exited_dirs |= turn_cardinal(Ddir, ang_change) - - update_appearance() - return ..() - -/obj/effect/decal/cleanable/blood/footprints/update_name(updates) - switch(footprint_sprite) - if(FOOTPRINT_SPRITE_CLAWS) - name = "clawprints" - if(FOOTPRINT_SPRITE_SHOES) - name = "footprints" - if(FOOTPRINT_SPRITE_PAWS) - name = "pawprints" - dryname = "dried [name]" - return ..() - -/obj/effect/decal/cleanable/blood/footprints/update_desc(updates) - desc = "WHOSE [uppertext(name)] ARE THESE?" - return ..() - -/obj/effect/decal/cleanable/blood/footprints/update_icon() - . = ..() - alpha = max(BLOODY_FOOTPRINT_BASE_ALPHA, min(255 * (bloodiness / 15), 255)) - -//Cache of bloody footprint images -//Key: -//"entered-[blood_state]-[dir_of_image]" -//or: "exited-[blood_state]-[dir_of_image]" -GLOBAL_LIST_EMPTY(bloody_footprints_cache) - -/obj/effect/decal/cleanable/blood/footprints/update_overlays() - . = ..() - for(var/Ddir in GLOB.cardinals) - if(entered_dirs & Ddir) - var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"] - if(!bloodstep_overlay) - GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_enter", dir = Ddir) - bloodstep_overlay.color = color - . += bloodstep_overlay - - if(exited_dirs & Ddir) - var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"] - if(!bloodstep_overlay) - GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_exit", dir = Ddir) - bloodstep_overlay.color = color - . += bloodstep_overlay - - -/obj/effect/decal/cleanable/blood/footprints/examine(mob/user) - . = ..() - if(length(shoe_types) + length(species_types) == 0) - return - - . += "You recognise \the [src] as belonging to:" - - for(var/sole in shoe_types) - var/obj/item/clothing/item = sole - var/article = initial(item.gender) == PLURAL ? "Some" : "A" - . += "[icon2html(initial(item.icon), user, initial(item.icon_state))] [article] [initial(item.name)]." - - for(var/species in species_types) - // god help me - if(species == "unknown") - . += "Some feet." - else if(species == SPECIES_MONKEY) - . += "[icon2html('icons/mob/human/human.dmi', user, "monkey")] Some monkey paws." - else if(species == SPECIES_HUMAN) - . += "[icon2html('icons/mob/human/bodyparts.dmi', user, "default_human_l_leg")] Some human feet." - else - . += "[icon2html('icons/mob/human/bodyparts.dmi', user, "[species]_l_leg")] Some [species] feet." - -/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/blood/blood_decal) - if(blood_state != blood_decal.blood_state || footprint_sprite != blood_decal.footprint_sprite) //We only replace footprints of the same type as us - return FALSE - return ..() - -/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in() - if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY)) - return TRUE - return FALSE - -/obj/effect/decal/cleanable/blood/hitsplatter - name = "blood splatter" - pass_flags = PASSTABLE | PASSGRILLE - icon_state = "hitsplatter1" - random_icon_states = list("hitsplatter1", "hitsplatter2", "hitsplatter3") - plane = GAME_PLANE - layer = ABOVE_WINDOW_LAYER - is_mopped = FALSE - /// The turf we just came from, so we can back up when we hit a wall - var/turf/prev_loc - /// The cached info about the blood - var/list/blood_dna_info - /// Skip making the final blood splatter when we're done, like if we're not in a turf - var/skip = FALSE - /// How many tiles/items/people we can paint red - var/splatter_strength = 3 - /// Insurance so that we don't keep moving once we hit a stoppoint - var/hit_endpoint = FALSE - -/obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, splatter_strength) - . = ..() - prev_loc = loc //Just so we are sure prev_loc exists - if(splatter_strength) - src.splatter_strength = splatter_strength - -/obj/effect/decal/cleanable/blood/hitsplatter/proc/expire() - if(isturf(loc) && !skip) - playsound(src, 'sound/effects/wounds/splatter.ogg', 60, TRUE, -1) - if(blood_dna_info) - loc.add_blood_DNA(blood_dna_info) - qdel(src) - -/// Set the splatter up to fly through the air until it rounds out of steam or hits something -/obj/effect/decal/cleanable/blood/hitsplatter/proc/fly_towards(turf/target_turf, range) - var/delay = 2 - var/datum/move_loop/loop = GLOB.move_manager.move_towards(src, target_turf, delay, timeout = delay * range, priority = MOVEMENT_ABOVE_SPACE_PRIORITY, flags = MOVEMENT_LOOP_START_FAST) - RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move)) - RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move)) - RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(loop_done)) - -/obj/effect/decal/cleanable/blood/hitsplatter/proc/pre_move(datum/move_loop/source) - SIGNAL_HANDLER - prev_loc = loc - -/obj/effect/decal/cleanable/blood/hitsplatter/proc/post_move(datum/move_loop/source) - SIGNAL_HANDLER - - for(var/atom/movable/iter_atom in loc) - if(hit_endpoint) - return - if(iter_atom == src || iter_atom.invisibility || iter_atom.alpha <= 0 || (isobj(iter_atom) && !iter_atom.density)) - continue - if(splatter_strength <= 0) - break - - iter_atom.add_blood_DNA(blood_dna_info) - splatter_strength-- - - if(splatter_strength <= 0) // we used all the puff so we delete it. - expire() - -/obj/effect/decal/cleanable/blood/hitsplatter/proc/loop_done(datum/source) - SIGNAL_HANDLER - if(!QDELETED(src)) - expire() - -/obj/effect/decal/cleanable/blood/hitsplatter/Bump(atom/bumped_atom) - if(!iswallturf(bumped_atom) && !istype(bumped_atom, /obj/structure/window)) - expire() - return - - if(istype(bumped_atom, /obj/structure/window)) - var/obj/structure/window/bumped_window = bumped_atom - if(!bumped_window.fulltile) - hit_endpoint = TRUE - expire() - return - - hit_endpoint = TRUE - if(!isturf(prev_loc)) // This will only happen if prev_loc is not even a turf, which is highly unlikely. - abstract_move(bumped_atom) - expire() - return - - abstract_move(bumped_atom) - skip = TRUE - //Adjust pixel offset to make splatters appear on the wall - if(istype(bumped_atom, /obj/structure/window)) - land_on_window(bumped_atom) - return - - var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new(prev_loc) - final_splatter.add_blood_DNA(blood_dna_info) - final_splatter.pixel_x = (dir == EAST ? 32 : (dir == WEST ? -32 : 0)) - final_splatter.pixel_y = (dir == NORTH ? 32 : (dir == SOUTH ? -32 : 0)) - -/// A special case for hitsplatters hitting windows, since those can actually be moved around, store it in the window and slap it in the vis_contents -/obj/effect/decal/cleanable/blood/hitsplatter/proc/land_on_window(obj/structure/window/the_window) - if(!the_window.fulltile) - return - var/obj/effect/decal/cleanable/final_splatter = new /obj/effect/decal/cleanable/blood/splatter/over_window(prev_loc) - final_splatter.add_blood_DNA(blood_dna_info) - final_splatter.forceMove(the_window) - the_window.vis_contents += final_splatter - the_window.bloodied = TRUE - expire() diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index cb99987ba77..f283a2b9c7d 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -395,7 +395,7 @@ /obj/effect/decal/cleanable/ants/proc/update_ant_damage(ant_min_damage, ant_max_damage) if(!ant_max_damage) - ant_max_damage = min(10, round((reagents.get_reagent_amount(/datum/reagent/ants) * 0.1),0.1)) // 100u ants = 10 max_damage + ant_max_damage = min(10, round((reagents ? reagents.get_reagent_amount(/datum/reagent/ants) : reagent_amount) * 0.1,0.1)) // 100u ants = 10 max_damage if(!ant_min_damage) ant_min_damage = 0.1 var/ant_flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN) /// Small amounts of ants won't be able to bite through shoes. @@ -472,10 +472,11 @@ /obj/effect/decal/cleanable/fuel_pool/Initialize(mapload, burn_stacks) . = ..() - var/static/list/ignition_trigger_connections = list( + var/static/list/loc_connections = list( COMSIG_TURF_MOVABLE_THROW_LANDED = PROC_REF(ignition_trigger), + COMSIG_ATOM_ENTERED = PROC_REF(on_entered) ) - AddElement(/datum/element/connect_loc, ignition_trigger_connections) + AddElement(/datum/element/connect_loc, loc_connections) for(var/obj/effect/decal/cleanable/fuel_pool/pool in get_turf(src)) //Can't use locate because we also belong to that turf if(pool == src) continue @@ -543,11 +544,11 @@ log_combat(user, src, "used [item] to ignite") return ..() -/obj/effect/decal/cleanable/fuel_pool/on_entered(datum/source, atom/movable/entered_atom) - . = ..() - if(entered_atom.throwing) // don't light from things being thrown over us, we handle that somewhere else - return - ignition_trigger(source = src, enflammable_atom = entered_atom) +/obj/effect/decal/cleanable/fuel_pool/proc/on_entered(datum/source, atom/movable/entered_atom) + SIGNAL_HANDLER + + if(!entered_atom.throwing) // don't light from things being thrown over us, we handle that somewhere else + ignition_trigger(source = src, enflammable_atom = entered_atom) /obj/effect/decal/cleanable/fuel_pool/proc/ignition_trigger(datum/source, atom/movable/enflammable_atom) SIGNAL_HANDLER diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index 7406cd910a1..85bce021f47 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -1,115 +1,61 @@ -// Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code. - -/obj/effect/decal/cleanable/robot_debris +/obj/effect/decal/cleanable/blood/gibs/robot_debris name = "robot debris" desc = "It's a useless heap of junk... or is it?" icon = 'icons/mob/silicon/robots.dmi' - icon_state = "gib1" - plane = GAME_PLANE - layer = GIB_LAYER random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") - blood_state = BLOOD_STATE_OIL - bloodiness = BLOOD_AMOUNT_PER_DECAL - mergeable_decal = FALSE - beauty = -50 - clean_type = CLEAN_TYPE_BLOOD + has_overlay = FALSE + squishy = FALSE + color = null - is_mopped = TRUE // probably shouldn't be, but janitor powercreep +/obj/effect/decal/cleanable/blood/gibs/robot_debris/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_OIL) -/obj/effect/decal/cleanable/robot_debris/Initialize(mapload) - . = ..() - RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) +/obj/effect/decal/cleanable/blood/gibs/robot_debris/create_splatter() + if(prob(40)) + return ..() -/obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions, mapload=FALSE) - var/direction = pick(directions) - var/delay = 2 - var/range = pick(1, 200; 2, 150; 3, 50; 4, 17; 50) //the 3% chance of 50 steps is intentional and played for laughs. - if(!step_to(src, get_step(src, direction), 0)) - return - if(mapload) - for (var/i in 1 to range) - var/turf/my_turf = get_turf(src) - if(prob(40) && (!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf))) - new /obj/effect/decal/cleanable/oil/streak(my_turf) - if (!step_to(src, get_step(src, direction), 0)) - break - return - - var/datum/move_loop/loop = GLOB.move_manager.move(src, direction, delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) - RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) - -/obj/effect/decal/cleanable/robot_debris/proc/spread_movement_effects(datum/move_loop/has_target/source) - SIGNAL_HANDLER +/obj/effect/decal/cleanable/blood/gibs/robot_debris/spread_movement_effects(datum/move_loop/has_target/source) if(NeverShouldHaveComeHere(loc)) return if (prob(40)) - new /obj/effect/decal/cleanable/oil/streak(loc) + new /obj/effect/decal/cleanable/blood/splatter(loc, null, GET_ATOM_BLOOD_DNA(src)) else if (prob(10)) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(3, 1, src) s.start() -/obj/effect/decal/cleanable/robot_debris/proc/on_pipe_eject(atom/source, direction) - SIGNAL_HANDLER +// Doesn't have overlay support as of now +/obj/effect/decal/cleanable/blood/gibs/robot_debris/update_blood_color() + color = null - var/list/dirs - if(direction) - dirs = list(direction, turn(direction, -45), turn(direction, 45)) - else - dirs = GLOB.alldirs.Copy() - - streak(dirs) - -/obj/effect/decal/cleanable/robot_debris/ex_act() - return FALSE - -/obj/effect/decal/cleanable/robot_debris/limb +/obj/effect/decal/cleanable/blood/gibs/robot_debris/limb icon_state = "gibarm" random_icon_states = list("gibarm", "gibleg") -/obj/effect/decal/cleanable/robot_debris/up +/obj/effect/decal/cleanable/blood/gibs/robot_debris/up icon_state = "gibup" random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup","gibup") -/obj/effect/decal/cleanable/robot_debris/down +/obj/effect/decal/cleanable/blood/gibs/robot_debris/down icon_state = "gibdown" random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown","gibdown") -/obj/effect/decal/cleanable/oil +/obj/effect/decal/cleanable/blood/oil name = "motor oil" + // This is fetched in /datum/blood_type/oil/set_up_blood() for all blood decals with default desc desc = "It's black and greasy. Looks like Beepsky made another mess." - icon = 'icons/mob/silicon/robots.dmi' - icon_state = "floor1" - random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") - blood_state = BLOOD_STATE_OIL - bloodiness = BLOOD_AMOUNT_PER_DECAL - beauty = -100 - clean_type = CLEAN_TYPE_BLOOD - decal_reagent = /datum/reagent/fuel/oil - reagent_amount = 30 + color = /datum/blood_type/oil::color // For mapper sanity -/obj/effect/decal/cleanable/oil/attackby(obj/item/I, mob/living/user) - var/attacked_by_hot_thing = I.get_temperature() - if(attacked_by_hot_thing) - user.visible_message(span_warning("[user] tries to ignite [src] with [I]!"), span_warning("You try to ignite [src] with [I].")) - log_combat(user, src, (attacked_by_hot_thing < 480) ? "tried to ignite" : "ignited", I) - fire_act(attacked_by_hot_thing) - return - return ..() +/obj/effect/decal/cleanable/blood/oil/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_OIL) -/obj/effect/decal/cleanable/oil/fire_act(exposed_temperature, exposed_volume) - if(exposed_temperature < 480) - return - visible_message(span_danger("[src] catches fire!")) - var/turf/T = get_turf(src) - qdel(src) - new /obj/effect/hotspot(T) - -/obj/effect/decal/cleanable/oil/streak - icon_state = "streak1" - random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5") - beauty = -50 - -/obj/effect/decal/cleanable/oil/slippery/Initialize(mapload) +/obj/effect/decal/cleanable/blood/oil/slippery/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna) . = ..() AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE)) + +/obj/effect/decal/cleanable/blood/splatter/oil + name = "motor oil" + color = /datum/blood_type/oil::color + +/obj/effect/decal/cleanable/blood/splatter/oil/get_default_blood_type() + return get_blood_type(BLOOD_TYPE_OIL) diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index 803555ae89a..a527317b476 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -82,6 +82,6 @@ icon = 'icons/mob/silicon/robots.dmi' icon_state = "remainsrobot" -/obj/effect/decal/cleanable/robot_debris/old +/obj/effect/decal/cleanable/blood/gibs/robot_debris/old name = "dusty robot debris" desc = "Looks like nobody has touched this in a while." diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index 66006a8b3ec..1c291bf6f17 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -1,4 +1,3 @@ - /obj/effect/gibspawner icon_state = "gibspawner"// For the map editor var/sparks = 0 //whether sparks spread @@ -21,8 +20,6 @@ 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) @@ -31,7 +28,6 @@ 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. if(blood_dna_info) dna_to_add = blood_dna_info @@ -49,16 +45,15 @@ if(gibamounts[i]) for(var/j in 1 to gibamounts[i]) var/gibType = gibtypes[i] - gib = new gibType(loc, diseases) - - gib.add_blood_DNA(dna_to_add) - // These might streak off into space and cause annoying flaky failures with mapping nearstation tests #ifndef UNIT_TESTS + var/obj/effect/decal/cleanable/blood/gibs/gib = new gibType(loc, diseases, dna_to_add) var/list/directions = gibdirections[i] if(isturf(loc)) if(directions.len) gib.streak(directions, mapload) +#else + new gibType(loc, diseases, dna_to_add) #endif return INITIALIZE_HINT_QDEL @@ -99,65 +94,59 @@ return ..() - /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, /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) gibamounts = list(1, 1, 1, 1, 1, 1) /obj/effect/gibspawner/human/bodypartless/Initialize(mapload) if(!gibdirections.len) - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list()) + 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) + 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(mapload) 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()) + 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/xeno/bodypartless //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) + 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(mapload) if(!gibdirections.len) - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list()) + 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/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(mapload) if(!gibdirections.len) - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list(), GLOB.alldirs) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST), list(SOUTH, SOUTHEAST, SOUTHWEST), list(), GLOB.alldirs) return ..() /obj/effect/gibspawner/larva/bodypartless - gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva) + 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/larva/bodypartless/Initialize(mapload) if(!gibdirections.len) - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list()) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST), list(SOUTH, SOUTHEAST, SOUTHWEST), list()) return ..() /obj/effect/gibspawner/robot sparks = 1 - 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) + gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/robot_debris/up, /obj/effect/decal/cleanable/blood/gibs/robot_debris/down, /obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/decal/cleanable/blood/gibs/robot_debris/limb) gibamounts = list(1, 1, 1, 1, 1, 1) gib_mob_type = /mob/living/silicon diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 3dec4218ca2..7ee54407274 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -1,11 +1,12 @@ //unsorted miscellaneous temporary visuals /obj/effect/temp_visual/dir_setting/bloodsplatter icon = 'icons/effects/blood.dmi' + icon_state = "splatter1" + base_icon_state = "splatter" duration = 5 randomdir = FALSE layer = BELOW_MOB_LAYER plane = GAME_PLANE - var/splatter_type = "splatter" // set_color arg can be either a color string or a singleton /datum/blood_type to pull the color from /obj/effect/temp_visual/dir_setting/bloodsplatter/Initialize(mapload, set_dir, set_color = BLOOD_COLOR_RED) @@ -16,9 +17,9 @@ else color = set_color if(ISDIAGONALDIR(set_dir)) - icon_state = "[splatter_type][pick(1, 2, 6)]" + icon_state = "[base_icon_state][pick(1, 2, 6)]" else - icon_state = "[splatter_type][pick(3, 4, 5)]" + icon_state = "[base_icon_state][pick(3, 4, 5)]" . = ..() var/target_pixel_x = 0 var/target_pixel_y = 0 @@ -46,13 +47,7 @@ target_pixel_x = -16 target_pixel_y = -16 layer = ABOVE_MOB_LAYER - 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 = "splatter" - -/obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter/Initialize(mapload, set_dir, set_color = get_blood_type(/datum/blood_type/xeno::name)) - return ..() + animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration, flags = CUBIC_EASING | EASE_OUT) /obj/effect/temp_visual/dir_setting/speedbike_trail name = "speedbike trails" diff --git a/code/game/objects/items/devices/scanners/autopsy_scanner.dm b/code/game/objects/items/devices/scanners/autopsy_scanner.dm index 7b9fdd81c7c..c997a4b51bd 100644 --- a/code/game/objects/items/devices/scanners/autopsy_scanner.dm +++ b/code/game/objects/items/devices/scanners/autopsy_scanner.dm @@ -89,12 +89,12 @@ else autopsy_information += "Unknown causes.
" else - var/blood_id = scanned.get_blood_id() - if(blood_id) + var/datum/blood_type/blood_type = scanned.get_bloodtype() + if(blood_type) var/blood_percent = round((scanned.blood_volume / BLOOD_VOLUME_NORMAL) * 100) - var/datum/blood_type/blood_type = scanned.dna.blood_type - autopsy_information += "Blood Type: [blood_type.name]
" - autopsy_information += "Blood Volume: [scanned.blood_volume] cl ([blood_percent]%)
" + if (blood_type.get_type()) + autopsy_information += "[blood_type.get_blood_name()] Type: [blood_type.get_type()]
" + autopsy_information += "[blood_type.get_blood_name()] Volume: [scanned.blood_volume] cl ([blood_percent]%)
" for(var/datum/disease/diseases as anything in scanned.diseases) autopsy_information += "Name: [diseases.name] | Type: [diseases.spread_text]
" diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 34fc58f5eae..05a273b4463 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -373,35 +373,47 @@ render_list += "[body_temperature_message]
" // Blood Level - var/mob/living/carbon/carbontarget = target - var/blood_id = carbontarget.get_blood_id() - if(blood_id) - var/blood_percent = round((carbontarget.blood_volume / BLOOD_VOLUME_NORMAL) * 100) - var/datum/blood_type/blood_type = carbontarget.dna.blood_type + var/datum/blood_type/blood_type = target.get_bloodtype() + if(blood_type) + var/blood_percent = round((target.blood_volume / BLOOD_VOLUME_NORMAL) * 100) var/blood_type_format var/level_format - if(carbontarget.blood_volume <= BLOOD_VOLUME_SAFE && carbontarget.blood_volume > BLOOD_VOLUME_OKAY) - level_format = conditional_tooltip("LOW [blood_percent]%, [carbontarget.blood_volume] cl", "Recommendation: [blood_type.restoration_chem::name] supplement.", tochat) - else if(carbontarget.blood_volume <= BLOOD_VOLUME_OKAY) - level_format = conditional_tooltip("CRITICAL [blood_percent]%, [carbontarget.blood_volume] cl", "Recommendation: [blood_type.restoration_chem::name] supplement, [/datum/reagent/medicine/salglu_solution::name], or blood transfusion.", tochat) + if(target.blood_volume <= BLOOD_VOLUME_SAFE && target.blood_volume > BLOOD_VOLUME_OKAY) + level_format = "LOW [blood_percent]%, [target.blood_volume] cl" + if (blood_type.restoration_chem) + level_format = conditional_tooltip(level_format, "Recommendation: [blood_type.restoration_chem::name] supplement.", tochat) + else if(target.blood_volume <= BLOOD_VOLUME_OKAY) + level_format = "CRITICAL [blood_percent]%, [target.blood_volume] cl" + var/recommendation = list() + if (blood_type.restoration_chem) + recommendation += "[blood_type.restoration_chem::name] supplement" + if (blood_type.restoration_chem == /datum/reagent/iron) + recommendation += "[/datum/reagent/medicine/salglu_solution::name]" + if (length(recommendation)) + recommendation += "[blood_type.get_blood_name()] transufion" + else + recommendation += "immediate [blood_type.get_blood_name()] transufion" + level_format = conditional_tooltip(level_format, "Recommendation: [english_list(recommendation, and_text = " or ")].", tochat) else - level_format = "[blood_percent]%, [carbontarget.blood_volume] cl" + level_format = "[blood_percent]%, [target.blood_volume] cl" - blood_type_format = "type: [blood_type]" - if(tochat && length(blood_type.compatible_types)) - var/list/compatible_types_readable = list() - for(var/datum/blood_type/comp_blood_type as anything in blood_type.compatible_types) - compatible_types_readable |= initial(comp_blood_type.name) - blood_type_format = span_tooltip("Can receive from types [english_list(compatible_types_readable)].", blood_type_format) + if (blood_type.get_type()) + blood_type_format = "type: [blood_type.get_type()]" + if(tochat && length(blood_type.compatible_types)) + var/list/compatible_types_readable = list() + for(var/datum/blood_type/comp_blood_type as anything in blood_type.compatible_types) + compatible_types_readable |= initial(comp_blood_type.name) + blood_type_format = span_tooltip("Can receive from types [english_list(compatible_types_readable)].", blood_type_format) - render_list += "Blood level: [level_format], [blood_type_format]
" + render_list += "[blood_type.get_blood_name()] level: [level_format], [blood_type_format]
" var/blood_alcohol_content = target.get_blood_alcohol_content() if(blood_alcohol_content > 0) if(blood_alcohol_content >= 0.24) - render_list += "Blood alcohol content: CRITICAL [blood_alcohol_content]%
" + // "Oil alcohol content" is kinda funny if you think about it from a technical standpoint + render_list += "[blood_type?.get_blood_name() || "Blood"] alcohol content: CRITICAL [blood_alcohol_content]%
" else - render_list += "Blood alcohol content: [blood_alcohol_content]%
" + render_list += "[blood_type?.get_blood_name() || "Blood"] alcohol content: [blood_alcohol_content]%
" //Diseases var/disease_hr = FALSE @@ -527,9 +539,9 @@ render_block += "[round(reagent.volume, 0.001)] units of [reagent.name][reagent.overdosed ? " - [span_bolddanger("OVERDOSING")]" : "."]
" if(!length(render_block)) //If no VISIBLY DISPLAYED reagents are present, we report as if there is nothing. - render_list += "Subject contains no reagents in their blood.
" + render_list += "Subject contains no reagents in their [LOWER_TEXT(target.get_bloodtype()?.get_blood_name()) || "blood"]stream.
" else - render_list += "Subject contains the following reagents in their blood:
" + render_list += "Subject contains the following reagents in their [LOWER_TEXT(target.get_bloodtype()?.get_blood_name()) || "blood"]stream:
" render_list += render_block //Otherwise, we add the header, reagent readouts, and clear the readout block for use on the stomach. render_block.Cut() diff --git a/code/game/objects/items/devices/scanners/sequence_scanner.dm b/code/game/objects/items/devices/scanners/sequence_scanner.dm index 03ed5670d7e..c64e6aae2d1 100644 --- a/code/game/objects/items/devices/scanners/sequence_scanner.dm +++ b/code/game/objects/items/devices/scanners/sequence_scanner.dm @@ -119,7 +119,7 @@ "UE"=target.dna.unique_enzymes, "UF"=target.dna.unique_features, "name"=target.real_name, - "blood_type"=target.dna.blood_type) + "blood_type"=target.get_bloodtype()) /obj/item/sequence_scanner/proc/display_sequence(mob/living/user) if(!LAZYLEN(buffer) || !ready) diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index 5d298ff1db4..35c17ca7f75 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -131,7 +131,7 @@ if(!target.dna.previous["UE"]) target.dna.previous["UE"] = target.dna.unique_enzymes if(!target.dna.previous["blood_type"]) - target.dna.previous["blood_type"] = target.dna.blood_type + target.dna.previous["blood_type"] = target.get_bloodtype() target.real_name = fields["name"] target.dna.unique_enzymes = fields["UE"] target.name = target.real_name diff --git a/code/game/objects/items/food/meatslab.dm b/code/game/objects/items/food/meatslab.dm index d0b79db44fd..179812872e7 100644 --- a/code/game/objects/items/food/meatslab.dm +++ b/code/game/objects/items/food/meatslab.dm @@ -24,7 +24,6 @@ /datum/component/bloody_spreader,\ blood_left = custom_materials[custom_materials[1]] / SHEET_MATERIAL_AMOUNT,\ blood_dna = blood_dna_list,\ - diseases = null,\ ) /obj/item/food/meat/slab @@ -290,7 +289,7 @@ bite_consumption = 4 tastes = list("meat" = 1, "acid" = 1) foodtypes = RAW | MEAT - blood_decal_type = /obj/effect/decal/cleanable/xenoblood + blood_decal_type = /obj/effect/decal/cleanable/blood/xeno /obj/item/food/meat/slab/xeno/make_processable() AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/meat/rawcutlet/xeno, 3, 3 SECONDS, table_required = TRUE, screentip_verb = "Cut") @@ -670,7 +669,7 @@ /obj/item/food/meat/rawcutlet/xeno name = "raw xeno cutlet" tastes = list("meat" = 1, "acid" = 1) - blood_decal_type = /obj/effect/decal/cleanable/xenoblood + blood_decal_type = /obj/effect/decal/cleanable/blood/xeno /obj/item/food/meat/rawcutlet/xeno/make_grillable() AddComponent(/datum/component/grillable, /obj/item/food/meat/cutlet/xeno, rand(35 SECONDS, 50 SECONDS), TRUE, TRUE) diff --git a/code/game/objects/items/lighter.dm b/code/game/objects/items/lighter.dm index 066d75a1e54..650405f467f 100644 --- a/code/game/objects/items/lighter.dm +++ b/code/game/objects/items/lighter.dm @@ -63,7 +63,7 @@ /obj/item/lighter/proc/on_intercepted_bullet(mob/living/victim, obj/projectile/bullet) victim.visible_message(span_warning("\The [bullet] shatters on [victim]'s lighter!")) playsound(victim, SFX_RICOCHET, 100, TRUE) - new /obj/effect/decal/cleanable/oil(get_turf(src)) + new /obj/effect/decal/cleanable/blood/oil(get_turf(src)) do_sparks(1, TRUE, src) victim.dropItemToGround(src, force = TRUE, silent = TRUE) qdel(src) diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 16da3fddbbc..66a01dfbfa3 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -287,8 +287,6 @@ AddComponent( /datum/component/bloody_spreader,\ blood_left = custom_materials[custom_materials[1]] / SHEET_MATERIAL_AMOUNT,\ - blood_dna = list("MEAT DNA" = "MT+"),\ - diseases = null,\ ) /* diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index 1c179bb1495..7d62320f3b5 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -524,7 +524,7 @@ ///Bleed and make blood splatters at tele start and end points /obj/item/syndicate_teleporter/proc/make_bloods(turf/old_location, turf/new_location, mob/living/user) - if(HAS_TRAIT(user, TRAIT_NOBLOOD)) + if(!user.can_bleed(BLOOD_COVER_TURFS) != BLEED_SPLATTER) return FALSE user.add_splatter_floor(old_location) user.add_splatter_floor(new_location) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index c7ef0edb806..2376faaae2d 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -30,8 +30,6 @@ var/knock_sound = 'sound/effects/glass/glassknock.ogg' var/bash_sound = 'sound/effects/glass/glassbash.ogg' var/hit_sound = 'sound/effects/glass/glasshit.ogg' - /// If some inconsiderate jerk has had their blood spilled on this window, thus making it cleanable - var/bloodied = FALSE ///Datum that the shard and debris type is pulled from for when the glass is broken. var/datum/material/glass_material_datum = /datum/material/glass /// Whether or not we're disappearing but dramatically @@ -385,7 +383,6 @@ if(!cleanables.wash(clean_types)) continue vis_contents -= cleanables - bloodied = FALSE /obj/structure/window/Destroy() set_density(FALSE) diff --git a/code/game/turfs/open/dirtystation.dm b/code/game/turfs/open/dirtystation.dm index 63d25fefb87..3808622982d 100644 --- a/code/game/turfs/open/dirtystation.dm +++ b/code/game/turfs/open/dirtystation.dm @@ -55,9 +55,9 @@ switch (rand(1, 100)) if(1 to 35)//35% if(prob(4)) - new /obj/effect/decal/cleanable/robot_debris/old(src) + new /obj/effect/decal/cleanable/blood/gibs/robot_debris/old(src) else - new /obj/effect/decal/cleanable/oil(src) + new /obj/effect/decal/cleanable/blood/oil(src) if(35 to 95)//60% new /obj/effect/decal/cleanable/dirt(src) if(95 to 100)//5% @@ -83,7 +83,7 @@ var/static/list/oily_areas = typecacheof(/area/station/cargo) if(is_type_in_typecache(A, oily_areas)) if(prob(25)) - new /obj/effect/decal/cleanable/oil(src) + new /obj/effect/decal/cleanable/blood/oil(src) else if(prob(20)) // or occasionally the signs of opened packages new /obj/effect/decal/cleanable/wrapping(src) diff --git a/code/modules/admin/verbs/list_exposer.dm b/code/modules/admin/verbs/list_exposer.dm index 2f7e3d67d5f..5dee40c6da1 100644 --- a/code/modules/admin/verbs/list_exposer.dm +++ b/code/modules/admin/verbs/list_exposer.dm @@ -36,7 +36,7 @@ for(var/entry in GLOB.human_list) var/mob/living/carbon/human/subject = entry if(subject.ckey) - data += "[subject][subject.dna.unique_enzymes][subject.dna.blood_type.name]" + data += "[subject][subject.dna.unique_enzymes][subject.get_bloodtype()?.name]" data += "" var/datum/browser/browser = new(usr, "DNA", "DNA Log", 440, 410) diff --git a/code/modules/antagonists/abductor/equipment/glands/blood.dm b/code/modules/antagonists/abductor/equipment/glands/blood.dm index b1d40852673..7523d00ffdd 100644 --- a/code/modules/antagonists/abductor/equipment/glands/blood.dm +++ b/code/modules/antagonists/abductor/equipment/glands/blood.dm @@ -12,7 +12,12 @@ /obj/item/organ/heart/gland/blood/activate() if(!ishuman(owner) || !owner.dna.species) return - var/mob/living/carbon/human/H = owner - var/datum/species/species = H.dna.species - to_chat(H, span_warning("You feel your blood heat up for a moment.")) - species.exotic_blood = get_random_reagent_id() + var/mob/living/carbon/human/owner_mob = owner + to_chat(owner_mob, span_warning("You feel your blood heat up for a moment.")) + var/datum/reagent/new_blood_reagent = get_random_reagent_id() + // Try to find a corresponding blood type for this reagent + var/datum/blood_type/new_blood_type = get_blood_type(new_blood_reagent) + if(isnull(new_blood_type)) // this blood type doesn't exist yet in the global list, so make a new one + new_blood_type = new /datum/blood_type/random_chemical(new_blood_reagent) + GLOB.blood_types[new_blood_type::id] = new_blood_type + owner_mob.set_blood_type(new_blood_type) diff --git a/code/modules/antagonists/abductor/equipment/glands/heal.dm b/code/modules/antagonists/abductor/equipment/glands/heal.dm index 9800b4fa308..eb50a7e9fda 100644 --- a/code/modules/antagonists/abductor/equipment/glands/heal.dm +++ b/code/modules/antagonists/abductor/equipment/glands/heal.dm @@ -215,15 +215,14 @@ playsound(owner, 'sound/effects/magic/clockwork/anima_fragment_attack.ogg', 50, TRUE) var/list/dirs = GLOB.alldirs.Copy() for(var/i in 1 to 3) - var/obj/effect/decal/cleanable/robot_debris/debris = new(get_turf(owner)) + var/obj/effect/decal/cleanable/blood/gibs/robot_debris/debris = new(get_turf(owner)) debris.streak(dirs) else owner.visible_message(span_warning("[owner]'s [chest.name] sheds off its damaged flesh, rapidly replacing it!"), span_warning("Your [chest.name] sheds off its damaged flesh, rapidly replacing it!")) playsound(owner, 'sound/effects/splat.ogg', 50, TRUE) var/list/dirs = GLOB.alldirs.Copy() for(var/i in 1 to 3) - var/obj/effect/decal/cleanable/blood/gibs/gibs = new(get_turf(owner)) - gibs.add_blood_DNA(blood_dna_info) + var/obj/effect/decal/cleanable/blood/gibs/gibs = new(get_turf(owner), owner.get_static_viruses(), blood_dna_info) gibs.streak(dirs) var/obj/item/bodypart/chest/new_chest = new(null) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 1234422ea19..81d92c3a039 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -901,15 +901,12 @@ var/turf/our_turf = get_turf(target) if(!our_turf) return - for(var/obj/effect/decal/cleanable/blood/blood_around_us in range(our_turf,2)) - if(blood_around_us.blood_state != BLOOD_STATE_HUMAN) - continue - if(blood_around_us.bloodiness == 100) // Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam - blood_to_gain += 30 - else - blood_to_gain += max((blood_around_us.bloodiness**2)/800,1) - new /obj/effect/temp_visual/cult/turf/floor(get_turf(blood_around_us)) - qdel(blood_around_us) + for(var/obj/effect/decal/cleanable/blood/blood_around_us in range(our_turf, 2)) + // NON-MODULE CHANGE for blood + if(blood_around_us.decal_reagent == /datum/reagent/blood || blood_around_us.reagents?.has_reagent(/datum/reagent/blood)) + blood_to_gain += max(blood_around_us.bloodiness * 0.6 * BLOOD_TO_UNITS_MULTIPLIER, 1) + new /obj/effect/temp_visual/cult/turf/floor(get_turf(blood_around_us)) + qdel(blood_around_us) if(!blood_to_gain) return diff --git a/code/modules/antagonists/fugitive/hunters/hunter_gear.dm b/code/modules/antagonists/fugitive/hunters/hunter_gear.dm index 46d04d7a4e4..4efe29b1048 100644 --- a/code/modules/antagonists/fugitive/hunters/hunter_gear.dm +++ b/code/modules/antagonists/fugitive/hunters/hunter_gear.dm @@ -148,11 +148,7 @@ max_blood = INFINITY,\ ) - AddComponent(/datum/component/bloody_spreader,\ - blood_left = INFINITY,\ - blood_dna = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT)),\ - diseases = null,\ - ) + AddComponent(/datum/component/bloody_spreader) /obj/structure/bouncy_castle/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) diff --git a/code/modules/antagonists/heretic/items/heretic_blades.dm b/code/modules/antagonists/heretic/items/heretic_blades.dm index cd695587ca3..198ff5d469f 100644 --- a/code/modules/antagonists/heretic/items/heretic_blades.dm +++ b/code/modules/antagonists/heretic/items/heretic_blades.dm @@ -136,9 +136,7 @@ AddComponent( /datum/component/bloody_spreader,\ - blood_left = INFINITY,\ - blood_dna = list("Unknown DNA" = BLOOD_TYPE_XENO),\ - diseases = null,\ + blood_dna = list("Alien DNA" = get_blood_type(BLOOD_TYPE_XENO)),\ ) // Path of Void's blade diff --git a/code/modules/cargo/bounties/virus.dm b/code/modules/cargo/bounties/virus.dm index 33990ec1413..2721b2124d1 100644 --- a/code/modules/cargo/bounties/virus.dm +++ b/code/modules/cargo/bounties/virus.dm @@ -23,12 +23,10 @@ return FALSE if(!istype(export, /obj/item/reagent_containers || !export.reagents || !export.reagents.reagent_list)) return FALSE - var/datum/reagent/blood/blud = locate() in export.reagents.reagent_list - if(!blud) - return FALSE - for(var/datum/disease/advance/virus in blud.get_diseases()) - if(accepts_virus(virus)) - return TRUE + for(var/datum/reagent/reagent as anything in export.reagents.reagent_list) + for(var/datum/disease/advance/virus in reagent.data?["viruses"]) + if(accepts_virus(virus)) + return TRUE return FALSE /datum/bounty/virus/ship(obj/export) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index e492c2504f6..f0ba988143a 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -628,3 +628,23 @@ BLIND // can't see anything /obj/item/clothing/remove_fantasy_bonuses(bonus) set_armor(get_armor().generate_new_with_modifiers(list(ARMOR_ALL = -bonus))) return ..() + +/// Returns a list of overlays with our blood, if we're bloodied +/obj/item/clothing/proc/get_blood_overlay(blood_state) + if (!GET_ATOM_BLOOD_DECAL_LENGTH(src)) + return + + var/mutable_appearance/blood_overlay = null + if(clothing_flags & LARGE_WORN_ICON) + blood_overlay = mutable_appearance('icons/effects/64x64.dmi', "[blood_state]blood_large") + else + blood_overlay = mutable_appearance('icons/effects/blood.dmi', "[blood_state]blood") + + blood_overlay.color = get_blood_dna_color() + + var/emissive_alpha = get_blood_emissive_alpha(is_worn = TRUE) + if (emissive_alpha) + var/mutable_appearance/emissive_overlay = emissive_appearance(blood_overlay.icon, blood_overlay.icon_state, src, alpha = emissive_alpha) + blood_overlay.overlays += emissive_overlay + + return blood_overlay diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index f1feb7165ff..c23748b05f6 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -53,11 +53,10 @@ /obj/item/clothing/gloves/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file) . = ..() - if(isinhands) + if (isinhands) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "gloveblood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) + var/blood_overlay = get_blood_overlay("glove") + if (blood_overlay) . += blood_overlay /obj/item/clothing/gloves/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm index e7be69b8f59..8aa8c6ee5c2 100644 --- a/code/modules/clothing/gloves/special.dm +++ b/code/modules/clothing/gloves/special.dm @@ -140,7 +140,7 @@ greyscale_colors = "#15191a" clothing_traits = list(TRAIT_QUICK_CARRY, TRAIT_FASTMED) -/obj/item/clothing/gloves/latex/coroner/add_blood_DNA(list/blood_DNA_to_add) +/obj/item/clothing/gloves/latex/coroner/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) return FALSE /obj/item/clothing/gloves/tinkerer diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index c5c36a03537..a732613edf7 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -63,17 +63,11 @@ /obj/item/clothing/head/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file) . = ..() - if(isinhands) + if (isinhands) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - if(clothing_flags & LARGE_WORN_ICON) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/64x64.dmi', "helmetblood_large") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) - . += blood_overlay - else - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "helmetblood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) - . += blood_overlay + var/blood_overlay = get_blood_overlay("helmet") + if (blood_overlay) + . += blood_overlay /obj/item/clothing/head/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 5d5e2b87070..9cafd6c1c3a 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -35,11 +35,10 @@ /obj/item/clothing/mask/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file) . = ..() - if(isinhands || !(body_parts_covered & HEAD)) + if (isinhands || !(body_parts_covered & HEAD)) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "maskblood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) + var/blood_overlay = get_blood_overlay("mask") + if (blood_overlay) . += blood_overlay /obj/item/clothing/mask/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 75e5b1f9db0..454065d31b7 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -16,11 +16,10 @@ /obj/item/clothing/neck/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file) . = ..() - if(isinhands || !(body_parts_covered & HEAD)) + if (isinhands || !(body_parts_covered & HEAD)) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "maskblood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) + var/blood_overlay = get_blood_overlay("mask") + if (blood_overlay) . += blood_overlay /obj/item/clothing/neck/bowtie diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index f5cbee74c41..9e0d2258bcf 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -62,17 +62,11 @@ /obj/item/clothing/shoes/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands = FALSE, icon_file) . = ..() - if(isinhands) + if (isinhands) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - if(clothing_flags & LARGE_WORN_ICON) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/64x64.dmi', "shoeblood_large") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) - . += blood_overlay - else - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "shoeblood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) - . += blood_overlay + var/blood_overlay = get_blood_overlay("shoe") + if (blood_overlay) + . += blood_overlay */ //SKYRAT EDIT REMOVAL END /obj/item/clothing/shoes/examine(mob/user) diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index df62e190ba6..8ea44091eda 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -48,11 +48,10 @@ /obj/item/clothing/suit/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands = FALSE, icon_file) . = ..() - if(isinhands) + if (isinhands) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) + var/blood_overlay = get_blood_overlay(blood_overlay_type) + if (blood_overlay) . += blood_overlay /obj/item/clothing/suit/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index cf2dc9a0072..f0e32b5007a 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -105,11 +105,10 @@ /obj/item/clothing/under/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands = FALSE, icon_file) . = ..() - if(isinhands) + if (isinhands) return - if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "uniformblood") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) + var/blood_overlay = get_blood_overlay("uniform") + if (blood_overlay) . += blood_overlay /obj/item/clothing/under/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) diff --git a/code/modules/events/shuttle_loan/shuttle_loan_datum.dm b/code/modules/events/shuttle_loan/shuttle_loan_datum.dm index 706274dfd85..be0d010ed95 100644 --- a/code/modules/events/shuttle_loan/shuttle_loan_datum.dm +++ b/code/modules/events/shuttle_loan/shuttle_loan_datum.dm @@ -75,7 +75,7 @@ pack.generate(pick_n_take(empty_shuttle_turfs)) for(var/i in 1 to 5) - var/decal = pick(/obj/effect/decal/cleanable/food/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil) + var/decal = pick(/obj/effect/decal/cleanable/food/flour, /obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/decal/cleanable/blood/oil) new decal(pick_n_take(empty_shuttle_turfs)) /datum/shuttle_loan_situation/syndiehijacking diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index 93bc2fc900a..1aec7399c9a 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -50,7 +50,7 @@ filth_spawn_types = list( /obj/effect/decal/cleanable/vomit, /obj/effect/decal/cleanable/insectguts, - /obj/effect/decal/cleanable/oil, + /obj/effect/decal/cleanable/blood/oil, ) /datum/round_event/vent_clog/start() @@ -219,7 +219,7 @@ /obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/insectguts, /obj/effect/decal/cleanable/fuel_pool, - /obj/effect/decal/cleanable/oil, + /obj/effect/decal/cleanable/blood/oil, ) /datum/round_event/vent_clog/major/get_mob() @@ -282,7 +282,7 @@ spawn_delay = rand(6, 25) maximum_spawns = rand(MOB_SPAWN_MINIMUM, 10) filth_spawn_types = list( - /obj/effect/decal/cleanable/xenoblood, + /obj/effect/decal/cleanable/blood/xeno, /obj/effect/decal/cleanable/fuel_pool, /obj/effect/decal/cleanable/greenglow, /obj/effect/decal/cleanable/vomit, diff --git a/code/modules/food_and_drinks/machinery/gibber.dm b/code/modules/food_and_drinks/machinery/gibber.dm index 0e4b028e3fd..7b09fbb7308 100644 --- a/code/modules/food_and_drinks/machinery/gibber.dm +++ b/code/modules/food_and_drinks/machinery/gibber.dm @@ -56,7 +56,7 @@ if(dirty) var/mutable_appearance/blood_overlay = mutable_appearance(icon, "grinder_bloody", appearance_flags = RESET_COLOR|KEEP_APART) if(blood_dna_info) - blood_overlay.color = get_blood_dna_color(blood_dna_info) + blood_overlay.color = get_color_from_blood_list(blood_dna_info) else blood_overlay.color = BLOOD_COLOR_RED . += blood_overlay @@ -284,9 +284,7 @@ for (var/i in 1 to meat_produced**2) //2 slabs: 4 giblets, 3 slabs: 9, etc. var/turf/gibturf = pick(nearby_turfs) if (!gibturf.density && (src in view(gibturf))) - var/obj/effect/decal/cleanable/new_gibs = new gibtype(gibturf, round(1 + i / meat_produced), diseases) - if(blood_dna_info) - new_gibs.add_blood_DNA(blood_dna_info) + new gibtype(gibturf, diseases, blood_dna_info) pixel_x = base_pixel_x //return to its spot after shaking operating = FALSE diff --git a/code/modules/forensics/_forensics.dm b/code/modules/forensics/_forensics.dm index a6801d63dbf..278cbcbc6fe 100644 --- a/code/modules/forensics/_forensics.dm +++ b/code/modules/forensics/_forensics.dm @@ -229,6 +229,32 @@ /datum/forensics/proc/check_blood() if(!isitem(parent) || isorgan(parent)) // organs don't spawn with blood decals by default return - if(!length(blood_DNA)) + var/blood_color = parent.get_blood_dna_color() + if (blood_color) + parent.AddElement(/datum/element/decal/blood, _color = blood_color, _emissive = parent.get_blood_emissive_alpha()) + +/// Returns how many blood datums on us fit our parent's expose flags +/datum/forensics/proc/get_visible_blood() + RETURN_TYPE(/list) + var/expose_flag = null + if (isturf(parent) || istype(parent, /obj/effect/decal)) + expose_flag = BLOOD_COVER_TURFS + else if (ismob(parent)) + expose_flag = BLOOD_COVER_MOBS + else if (isitem(parent)) + expose_flag = BLOOD_COVER_ITEMS + + if (!expose_flag) return - parent.AddElement(/datum/element/decal/blood, _color = get_blood_dna_color(blood_DNA)) + + var/visible_blood = list() + for (var/blood_key in blood_DNA) + var/datum/blood_type/blood_type = blood_DNA[blood_key] + if (!istype(blood_type)) + blood_type = get_blood_type(blood_type) + if (!istype(blood_type)) + continue + if (blood_type.blood_flags & expose_flag) + visible_blood[blood_key] = blood_type + + return visible_blood diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm index 1285b6eca9e..fb034fbf3ad 100644 --- a/code/modules/forensics/forensics_helpers.dm +++ b/code/modules/forensics/forensics_helpers.dm @@ -38,12 +38,12 @@ var/old = 0 if(suspect.gloves && istype(suspect.gloves, /obj/item/clothing)) var/obj/item/clothing/gloves/suspect_gloves = suspect.gloves - old = length(GET_ATOM_BLOOD_DNA(suspect_gloves)) + old = GET_ATOM_BLOOD_DNA_LENGTH(suspect_gloves) if(suspect_gloves.transfer_blood > 1) //bloodied gloves transfer blood to touched objects if(add_blood_DNA(GET_ATOM_BLOOD_DNA(suspect_gloves)) && GET_ATOM_BLOOD_DNA_LENGTH(suspect_gloves) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody suspect_gloves.transfer_blood -= 1 else if(suspect.blood_in_hands > 1) - old = length(GET_ATOM_BLOOD_DNA(suspect)) + old = GET_ATOM_BLOOD_DNA_LENGTH(suspect) if(add_blood_DNA(GET_ATOM_BLOOD_DNA(suspect)) && GET_ATOM_BLOOD_DNA_LENGTH(suspect) > old) suspect.blood_in_hands -= 1 if (isnull(forensics)) @@ -72,44 +72,100 @@ forensics.add_hiddenprint(suspect) return TRUE +/// Fetch current blood color +/atom/proc/get_blood_dna_color() + if (cached_blood_color) + return cached_blood_color + + var/list/blood_DNA = GET_ATOM_BLOOD_DECALS(src) + if (!length(blood_DNA)) + return + + cached_blood_color = get_color_from_blood_list(blood_DNA) + return cached_blood_color + +/// Check if we have any emissive blood on us +/// is_worn - When TRUE, we're fetching the value for mob overlays, in which case we bypass the cache +/atom/proc/get_blood_emissive_alpha(is_worn = FALSE) + if (cached_blood_emissive && !is_worn) + return cached_blood_emissive + + var/list/blood_DNA = GET_ATOM_BLOOD_DECALS(src) + if (!length(blood_DNA)) + return 0 + + var/blood_alpha = 0 + for (var/blood_key in blood_DNA) + var/datum/blood_type/blood_type = blood_DNA[blood_key] + blood_alpha += blood_type.get_emissive_alpha(src, is_worn) + + blood_alpha /= length(blood_DNA) + if (!is_worn) + cached_blood_emissive = blood_alpha + return blood_alpha + /// Adds blood dna to the atom -/atom/proc/add_blood_DNA(list/blood_DNA_to_add) //ASSOC LIST DNA = BLOODTYPE +/atom/proc/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) //ASSOC LIST DNA = BLOODTYPE return FALSE -/obj/add_blood_DNA(list/blood_DNA_to_add) +/obj/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) if (QDELETED(src)) return . = ..() if (isnull(blood_DNA_to_add)) return . + cached_blood_color = null + cached_blood_emissive = null if (forensics) forensics.inherit_new(blood_DNA = blood_DNA_to_add) else forensics = new(src, blood_DNA = blood_DNA_to_add) return TRUE -/obj/item/add_blood_DNA(list/blood_DNA_to_add) +/obj/effect/decal/cleanable/blood/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) + var/first_dna = GET_ATOM_BLOOD_DNA_LENGTH(src) + if(!..()) + return FALSE + if(dried) + return TRUE + // Imperfect, ends up with some blood types being double-set-up, but harmless (for now) + for(var/blood_key in blood_DNA_to_add) + var/datum/blood_type/blood_type = blood_DNA_to_add[blood_key] + // We shouldn't ever get no valid blood types with BLOOD_COVER_TURFS and first_dna == 0 here so we're safe + if(blood_type.blood_flags & BLOOD_COVER_TURFS) + blood_type.set_up_blood(src, first_dna == 0) + add_diseases(diseases) + update_appearance() + add_atom_colour(get_blood_dna_color(), FIXED_COLOUR_PRIORITY) + return TRUE + +/obj/item/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) if(item_flags & NO_BLOOD_ON_ITEM) return FALSE return ..() /obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - transfer_blood = rand(2, 4) - return ..() + . = ..() + if (. && has_blood_flag(blood_dna, BLOOD_COVER_ITEMS)) + transfer_blood = min(transfer_blood, rand(2, 4)) /turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) var/obj/effect/decal/cleanable/blood/splatter/blood_splatter = locate() in src + var/blood_flags = has_blood_flag(blood_dna, BLOOD_COVER_TURFS|BLOOD_ADD_DNA|BLOOD_TRANSFER_VIRAL_DATA) if(!blood_splatter) - blood_splatter = new /obj/effect/decal/cleanable/blood/splatter(src, diseases) - if(!QDELETED(blood_splatter)) - blood_splatter.add_blood_DNA(blood_dna) //give blood info to the blood decal. - return TRUE //we bloodied the floor - return FALSE + if(blood_flags & BLOOD_COVER_TURFS) + blood_splatter = new /obj/effect/decal/cleanable/blood/splatter(src, diseases, blood_dna) + else + if(blood_flags & BLOOD_ADD_DNA) + blood_splatter.add_blood_DNA(blood_dna) + if(blood_flags & BLOOD_TRANSFER_VIRAL_DATA) + blood_splatter.add_diseases(diseases) + return !QDELETED(blood_splatter) ? blood_splatter : null /turf/closed/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) return FALSE -/obj/item/clothing/under/add_blood_DNA(list/blood_DNA_to_add) +/obj/item/clothing/under/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) . = ..() if(!.) return @@ -119,15 +175,17 @@ thing_accessory.add_blood_DNA(blood_DNA_to_add) /mob/living/carbon/human/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) - return add_blood_DNA_to_items(blood_DNA_to_add) + return add_blood_DNA_to_items(blood_DNA_to_add, diseases = diseases) /// Adds blood DNA to certain slots the mob is wearing /mob/living/carbon/human/proc/add_blood_DNA_to_items( list/blood_DNA_to_add, target_flags = ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING|ITEM_SLOT_GLOVES|ITEM_SLOT_HEAD|ITEM_SLOT_MASK, + list/datum/disease/diseases, ) if(QDELING(src)) return FALSE + if(!length(blood_DNA_to_add)) return FALSE @@ -141,7 +199,7 @@ var/list/all_worn = get_equipped_items() for(var/obj/item/thing as anything in all_worn) if(thing.slot_flags & slots_to_bloody) - thing.add_blood_DNA(blood_DNA_to_add) + thing.add_blood_DNA(blood_DNA_to_add, diseases) if(thing.body_parts_covered & HANDS) dirty_hands = FALSE if(thing.body_parts_covered & FEET) @@ -151,15 +209,38 @@ for(var/obj/item/thing in held_items) thing.add_blood_DNA(blood_DNA_to_add) + cached_blood_color = null + cached_blood_emissive = null + if(!has_blood_flag(blood_DNA_to_add, BLOOD_COVER_MOBS)) + update_clothing(slots_to_bloody) + return + if(dirty_hands || dirty_feet || !length(all_worn)) if(isnull(forensics)) forensics = new(src) forensics.inherit_new(blood_DNA = blood_DNA_to_add) - if(dirty_hands) - blood_in_hands = rand(2, 4) + + if(dirty_hands) + blood_in_hands = min(blood_in_hands, rand(2, 4)) + + if(dirty_feet) + AddComponent(/datum/component/bloodysoles/feet, blood_DNA_to_add) // Add blood to our feet + update_clothing(slots_to_bloody) return TRUE +/mob/living/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) + if(QDELING(src)) + return FALSE + if(!length(blood_DNA_to_add)) + return FALSE + if(isnull(forensics)) + forensics = new(src) + cached_blood_color = null + cached_blood_emissive = null + forensics.inherit_new(blood_DNA = blood_DNA_to_add) + return TRUE + /* * Transfer all the fingerprints and hidden prints from [src] to [transfer_to]. */ diff --git a/code/modules/hallucination/blood_flow.dm b/code/modules/hallucination/blood_flow.dm index 71a58896bf3..0ae641d34a0 100644 --- a/code/modules/hallucination/blood_flow.dm +++ b/code/modules/hallucination/blood_flow.dm @@ -9,8 +9,9 @@ return FALSE var/mob/living/carbon/carb_hallucinator = hallucinator - if(!length(carb_hallucinator.bodyparts) || HAS_TRAIT(carb_hallucinator, TRAIT_NOBLOOD) || carb_hallucinator.dna?.blood_type.no_bleed_overlays) + if(!length(carb_hallucinator.bodyparts) || !carb_hallucinator.can_bleed()) return FALSE + var/obj/item/bodypart/picked var/list/bodyparts = carb_hallucinator.bodyparts.Copy() while(isnull(picked) && length(bodyparts)) @@ -39,7 +40,7 @@ icon_state = "[picked.body_zone]_[pick(2, 3)]", loc = hallucinator, ) - bleeding.color = carb_hallucinator.dna.blood_type.get_color() + bleeding.color = carb_hallucinator.get_bloodtype()?.get_wound_color(carb_hallucinator) || BLOOD_COLOR_RED bleeding.layer = -WOUND_LAYER hallucinator.client?.images += bleeding return TRUE diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 3602d5a9801..5a655d06ef2 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -56,11 +56,9 @@ var/list/quirks var/sampleDNA var/contains_sample = FALSE - var/being_harvested = FALSE /obj/item/seeds/replicapod/Initialize(mapload) . = ..() - create_reagents(volume, INJECTABLE | DRAWABLE) /obj/item/seeds/replicapod/create_reagents(max_vol, flags) @@ -70,26 +68,27 @@ /// Handles reagents getting added to this seed. /obj/item/seeds/replicapod/proc/on_reagent_update(datum/reagents/reagents) SIGNAL_HANDLER - var/datum/reagent/blood/B = reagents.has_reagent(/datum/reagent/blood) - if(!B) + + var/datum/reagent/blood/blood = reagents.has_reagent(/datum/reagent/blood) + if(!blood) return - if(B.data["mind"] && B.data["cloneable"]) - mind = B.data["mind"] - ckey = B.data["ckey"] - realName = B.data["real_name"] - blood_gender = B.data["gender"] - blood_type = B.data["blood_type"] - features = B.data["features"] - factions = B.data["factions"] - quirks = B.data["quirks"] - sampleDNA = B.data["blood_DNA"] - contains_sample = TRUE - visible_message(span_notice("The [src] is injected with a fresh blood sample.")) - investigate_log("[key_name(mind)]'s cloning record was added to [src]", INVESTIGATE_BOTANY) - else + if(!blood.data["mind"] || !blood.data["cloneable"]) visible_message(span_warning("The [src] rejects the sample!")) - return NONE + return + + mind = blood.data["mind"] + ckey = blood.data["ckey"] + realName = blood.data["real_name"] + blood_gender = blood.data["gender"] + blood_type = blood.data["blood_type"] + features = blood.data["features"] + factions = blood.data["factions"] + quirks = blood.data["quirks"] + sampleDNA = blood.data["blood_DNA"] + contains_sample = TRUE + visible_message(span_notice("The [src] is injected with a fresh blood sample.")) + investigate_log("[key_name(mind)]'s cloning record was added to [src]", INVESTIGATE_BOTANY) /// Handles reagents being deleted from these seeds. /obj/item/seeds/replicapod/proc/on_reagent_del(changetype) @@ -106,7 +105,6 @@ factions = null sampleDNA = null contains_sample = FALSE - return NONE /obj/item/seeds/replicapod/get_unique_analyzer_text() if(contains_sample) @@ -121,32 +119,45 @@ var/list/result = list() if(CONFIG_GET(flag/revival_pod_plants)) if(ckey) - for(var/mob/M in GLOB.player_list) - if(isobserver(M)) - var/mob/dead/observer/O = M - if(O.ckey == ckey && O.can_reenter_corpse) + for(var/mob/corpse as anything in GLOB.player_list) + if (corpse.ckey != ckey || HAS_TRAIT(corpse, TRAIT_SUICIDED)) + continue + + if(isobserver(corpse)) + var/mob/dead/observer/ghost = corpse + if(ghost.can_reenter_corpse) make_podman = TRUE - break - else - if(M.ckey == ckey && M.stat == DEAD && !HAS_TRAIT(M, TRAIT_SUICIDED) && !HAS_TRAIT(M, TRAIT_MIND_TEMPORARILY_GONE)) - make_podman = TRUE - break - else //If the player has ghosted from his corpse before blood was drawn, his ckey is no longer attached to the mob, so we need to match up the cloned player through the mind key - for(var/mob/M in GLOB.player_list) - if(mind && M.mind && ckey(M.mind.key) == ckey(mind.key) && M.ckey && M.client && M.stat == DEAD && !HAS_TRAIT(M, TRAIT_SUICIDED)) - if(isobserver(M)) - var/mob/dead/observer/O = M - if(!O.can_reenter_corpse) - break + else if(corpse.stat == DEAD && !HAS_TRAIT(corpse, TRAIT_MIND_TEMPORARILY_GONE)) make_podman = TRUE - ckey_holder = M.ckey - break + + break + + else if (mind) + // If the player has ghosted from his corpse before blood was drawn, his ckey is no longer attached to the mob, so we need to match up the cloned player through the mind key + for(var/mob/corpse in GLOB.player_list) + if (!corpse.mind || !corpse.ckey || !corpse.client) + continue + + if (ckey(corpse.mind.key) != ckey(mind.key)) + continue + + if (corpse.stat != DEAD || HAS_TRAIT(corpse, TRAIT_SUICIDED)) + continue + + if(isobserver(corpse)) + var/mob/dead/observer/ghost = corpse + if(!ghost.can_reenter_corpse) + break + + make_podman = TRUE + ckey_holder = corpse.ckey + break // No podman player, give one or two seeds. if(!make_podman) // Prevent accidental harvesting. Make sure the user REALLY wants to do this if there's a chance of this coming from a living creature. - if(mind || ckey) - var/choice = tgui_alert(usr,"The pod is currently devoid of soul. There is a possibility that a soul could claim this creature, or you could harvest it for seeds.", "Harvest Seeds?", list("Harvest Seeds", "Cancel")) + if(user.client && (mind || ckey)) + var/choice = tgui_alert(user, "The pod is currently devoid of soul. There is a possibility that a soul could claim this creature, or you could harvest it for seeds.", "Harvest Seeds?", list("Harvest Seeds", "Cancel")) if(choice != "Harvest Seeds") return result @@ -179,11 +190,13 @@ podman.real_name = realName else podman.real_name = "Pod Person ([rand(1,999)])" + mind.transfer_to(podman) if(ckey) podman.PossessByPlayer(ckey) else podman.PossessByPlayer(ckey_holder) + podman.gender = blood_gender podman.faction |= factions if(!features["mcolor"]) @@ -206,8 +219,6 @@ most_plentiful_reagent[reagent] = reagents_add[reagent] var/datum/reagent/new_blood_reagent = most_plentiful_reagent[1] - podman.dna.species.exotic_blood = new_blood_reagent - // Try to find a corresponding blood type for this reagent var/datum/blood_type/new_blood_type = get_blood_type(new_blood_reagent) if(isnull(new_blood_type)) // this blood type doesn't exist yet in the global list, so make a new one diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm index 65a40fd14e6..99d252254e4 100644 --- a/code/modules/hydroponics/grown/tomato.dm +++ b/code/modules/hydroponics/grown/tomato.dm @@ -72,7 +72,7 @@ desc = "I say blue-mah-to, you say blue-mae-to." icon_state = "bluetomato" bite_consumption_mod = 2 - splat_type = /obj/effect/decal/cleanable/oil + splat_type = /obj/effect/decal/cleanable/blood/oil distill_reagent = /datum/reagent/consumable/laughter // Bluespace Tomato diff --git a/code/modules/lost_crew/damages/_damages.dm b/code/modules/lost_crew/damages/_damages.dm index ab54334af70..6bf0088265f 100644 --- a/code/modules/lost_crew/damages/_damages.dm +++ b/code/modules/lost_crew/damages/_damages.dm @@ -88,7 +88,7 @@ body_data += decay.type // Simulate bloodloss by dragging/moving - victim.blood_volume = max(victim.blood_volume - victim.bleedDragAmount() * rand(20, 100), 0) + victim.blood_volume = max(victim.blood_volume - victim.bleed_drag_amount() * rand(20, 100), 0) set_death_date(victim) death_lore += area_lore + " " + cause_of_death.cause_of_death diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm index 89058e33f5a..0fd481824c0 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm @@ -128,7 +128,7 @@ return ..() /obj/structure/sink/oil_well/drop_materials() - new /obj/effect/decal/cleanable/oil(loc) + new /obj/effect/decal/cleanable/blood/oil(loc) //***Grave mounds. /// has no items inside unless you use the filled subtype diff --git a/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm b/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm index c87d5c20dd0..e4266e59c13 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm @@ -45,11 +45,7 @@ /obj/structure/meateor_fluff/Initialize(mapload) . = ..() - AddComponent(/datum/component/bloody_spreader,\ - blood_left = INFINITY,\ - blood_dna = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT)),\ - diseases = null,\ - ) + AddComponent(/datum/component/bloody_spreader) /obj/structure/meateor_fluff/play_attack_sound(damage_amount, damage_type, damage_flag) switch(damage_type) @@ -137,6 +133,6 @@ max_integrity = 15 /obj/structure/meateor_fluff/abandoned_headcrab_egg/atom_destruction(damage_flag) - new /obj/effect/decal/cleanable/xenoblood(loc) + new /obj/effect/decal/cleanable/blood/xeno(loc) playsound(loc, 'sound/effects/footstep/gib_step.ogg', vol = 50, vary = TRUE, pressure_affected = FALSE) return ..() diff --git a/code/modules/meteors/meteor_types.dm b/code/modules/meteors/meteor_types.dm index 751da2a08dc..f632717000f 100644 --- a/code/modules/meteors/meteor_types.dm +++ b/code/modules/meteors/meteor_types.dm @@ -429,7 +429,7 @@ /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/modules/mob/living/basic/alien/_alien.dm b/code/modules/mob/living/basic/alien/_alien.dm index ee2c25e5199..30713a6ffa6 100644 --- a/code/modules/mob/living/basic/alien/_alien.dm +++ b/code/modules/mob/living/basic/alien/_alien.dm @@ -47,6 +47,7 @@ unsuitable_heat_damage = 20 ai_controller = /datum/ai_controller/basic_controller/alien + blood_volume = BLOOD_VOLUME_NORMAL ///List of loot items to drop when deleted, if this is set then we apply DEL_ON_DEATH var/list/loot @@ -75,9 +76,6 @@ visible_message(span_alertalien("[src] plants some alien weeds!")) new /obj/structure/alien/weeds/node(loc) -/mob/living/basic/alien/create_splatter(splatter_dir) - new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(get_turf(src), splatter_dir) - ///Lays an egg on the turf the mob is currently standing on. /mob/living/basic/alien/proc/lay_alien_egg() if(!isturf(loc) || isspaceturf(loc)) @@ -93,3 +91,5 @@ else new /obj/effect/gibspawner/xeno/bodypartless(drop_location(), src) +/mob/living/basic/alien/get_bloodtype() + return get_blood_type(BLOOD_TYPE_XENO) diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index 954f830bfb0..a154f363cfd 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -113,6 +113,7 @@ GLOBAL_LIST_INIT(command_strings, list( RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(after_attacked)) RegisterSignal(src, COMSIG_MOB_TRIED_ACCESS, PROC_REF(attempt_access)) add_traits(list(TRAIT_NO_GLIDE, TRAIT_SILICON_EMOTES_ALLOWED), INNATE_TRAIT) + LoadComponent(/datum/component/bloodysoles/bot) GLOB.bots_list += src // Give bots a fancy new ID card that can hold any access. diff --git a/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm b/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm index e6771d098a6..c49da9b36e7 100644 --- a/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm +++ b/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm @@ -83,9 +83,9 @@ /obj/effect/decal/cleanable/greenglow, /obj/effect/decal/cleanable/insectguts, /obj/effect/decal/cleanable/molten_object, - /obj/effect/decal/cleanable/oil, + /obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/food, - /obj/effect/decal/cleanable/robot_debris, + /obj/effect/decal/cleanable/blood/gibs/robot_debris, /obj/effect/decal/cleanable/shreds, /obj/effect/decal/cleanable/glass, /obj/effect/decal/cleanable/vomit, @@ -93,7 +93,7 @@ )) ///blood we can clean var/static/list/cleanable_blood = typecacheof(list( - /obj/effect/decal/cleanable/xenoblood, + /obj/effect/decal/cleanable/blood/xeno, /obj/effect/decal/cleanable/blood, )) ///pests we hunt diff --git a/code/modules/mob/living/basic/clown/clown.dm b/code/modules/mob/living/basic/clown/clown.dm index 169e8573005..4d891a4f718 100644 --- a/code/modules/mob/living/basic/clown/clown.dm +++ b/code/modules/mob/living/basic/clown/clown.dm @@ -25,6 +25,7 @@ habitable_atmos = list("min_oxy" = 5, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) minimum_survivable_temperature = (T0C - 10) maximum_survivable_temperature = (T0C + 100) + blood_volume = BLOOD_VOLUME_NORMAL faction = list(FACTION_CLOWN) ai_controller = /datum/ai_controller/basic_controller/clown ///list of stuff we drop on death @@ -64,6 +65,11 @@ unripe_bunch.start_ripening() log_combat(src, target, "explosively ripened") +/mob/living/basic/clown/get_bloodtype() + if (check_holidays(APRIL_FOOLS)) + return get_blood_type(BLOOD_TYPE_CLOWN) + return ..() + /mob/living/basic/clown/lube name = "Living Lube" desc = "A puddle of lube brought to life by the honkmother." diff --git a/code/modules/mob/living/basic/cytology/vatbeast.dm b/code/modules/mob/living/basic/cytology/vatbeast.dm index 8b938677e2b..0075061cda1 100644 --- a/code/modules/mob/living/basic/cytology/vatbeast.dm +++ b/code/modules/mob/living/basic/cytology/vatbeast.dm @@ -26,6 +26,7 @@ lighting_cutoff_blue = 20 ai_controller = /datum/ai_controller/basic_controller/vatbeast faction = list(FACTION_HOSTILE) + blood_volume = BLOOD_VOLUME_NORMAL /// What can you feed a vatbeast to tame it? var/static/list/enjoyed_food = list( /obj/item/food/carrotfries, @@ -56,6 +57,9 @@ /mob/living/basic/vatbeast/proc/add_cell_sample() AddElement(/datum/element/swabable, CELL_LINE_TABLE_VATBEAST, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) +/mob/living/basic/vatbeast/get_bloodtype() + return get_blood_type(BLOOD_TYPE_LIZARD) // Green and alien + /// Attack people and slap them /datum/ai_controller/basic_controller/vatbeast blackboard = list( diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index 61650ce9387..e755f420d41 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -181,6 +181,7 @@ AddComponent(/datum/component/basic_inhands, y_offset = getItemPixelShiftY()) AddComponent(/datum/component/simple_access, SSid_access.get_region_access_list(list(REGION_ALL_GLOBAL))) AddComponent(/datum/component/personal_crafting) // Kind of hard to be a drone and not be able to make tiles + LoadComponent(/datum/component/bloodysoles/bot) //only shy drones (so all the station ones) gets a camera. if(shy) diff --git a/code/modules/mob/living/basic/drone/interaction.dm b/code/modules/mob/living/basic/drone/interaction.dm index 2e22bb99752..b0ef90c7a53 100644 --- a/code/modules/mob/living/basic/drone/interaction.dm +++ b/code/modules/mob/living/basic/drone/interaction.dm @@ -17,7 +17,7 @@ if(do_after(drone, 6 SECONDS, 0, target = src)) drone.visible_message(span_notice("[drone] repairs itself using [src]'s remains!"), span_notice("You repair yourself using [src]'s remains.")) drone.adjustBruteLoss(-src.maxHealth) - new /obj/effect/decal/cleanable/oil/streak(get_turf(src)) + new /obj/effect/decal/cleanable/blood/splatter/oil(get_turf(src)) ghostize(can_reenter_corpse = FALSE) qdel(src) else diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm index ef9b59f47c5..debd43e4504 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm @@ -7,10 +7,8 @@ plane = GAME_PLANE layer = CLEANABLE_OBJECT_LAYER mergeable_decal = FALSE - -/obj/effect/decal/cleanable/brimdust/Initialize(mapload) - . = ..() - reagents.add_reagent(/datum/reagent/brimdust, 15) + decal_reagent = /datum/reagent/brimdust + reagent_amount = 15 /// Ashwalker ore sensor crafted from brimdemon ash /obj/item/ore_sensor diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm index 9223b7dfa58..e847f08ba70 100644 --- a/code/modules/mob/living/basic/minebots/minebot.dm +++ b/code/modules/mob/living/basic/minebots/minebot.dm @@ -65,7 +65,7 @@ neutral_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_grey") combat_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_offense_grey") AddComponent(/datum/component/obeys_commands, pet_commands) - var/static/list/death_drops = list(/obj/effect/decal/cleanable/robot_debris/old) + var/static/list/death_drops = list(/obj/effect/decal/cleanable/blood/gibs/robot_debris/old) AddElement(/datum/element/death_drops, death_drops) add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), INNATE_TRAIT) AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) diff --git a/code/modules/mob/living/basic/ruin_defender/blob_of_flesh.dm b/code/modules/mob/living/basic/ruin_defender/blob_of_flesh.dm index e4e9f9d0560..8972b13860d 100644 --- a/code/modules/mob/living/basic/ruin_defender/blob_of_flesh.dm +++ b/code/modules/mob/living/basic/ruin_defender/blob_of_flesh.dm @@ -43,7 +43,7 @@ AddElement(/datum/element/death_drops, string_list(list(/obj/effect/gibspawner/generic))) AddComponent(\ /datum/component/blood_walk, \ - blood_type = /obj/effect/decal/cleanable/blood/trails, \ + blood_type = /obj/effect/decal/cleanable/blood/trail_holder, \ target_dir_change = TRUE,\ ) diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm b/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm index c4c7d4a3383..7c21e14fd2b 100644 --- a/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm +++ b/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm @@ -41,7 +41,7 @@ /mob/living/basic/hivebot/Initialize(mapload) . = ..() - var/static/list/death_loot = list(/obj/effect/decal/cleanable/robot_debris) + var/static/list/death_loot = list(/obj/effect/decal/cleanable/blood/gibs/robot_debris) AddElement(/datum/element/death_drops, death_loot) AddComponent(/datum/component/appearance_on_aggro, overlay_icon = icon, overlay_state = "[initial(icon_state)]_attack") if(!ranged_attacker) diff --git a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm index 561ced890cc..e5b988e13d1 100644 --- a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm +++ b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm @@ -58,12 +58,7 @@ soundloop.pressure_affected = FALSE soundloop.start() - AddComponent(\ - /datum/component/bloody_spreader,\ - blood_left = INFINITY,\ - blood_dna = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT)),\ - diseases = null,\ - ) + AddComponent(/datum/component/bloody_spreader) /// Called when we get mad at something, either for attacking us or attacking the nearby area /mob/living/basic/meteor_heart/proc/aggro() diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm index e7bc44c4749..09cb6b8ecf9 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm @@ -81,7 +81,7 @@ if (9) new /obj/effect/decal/cleanable/vomit/old(mess_location) if (10) - new /obj/effect/decal/cleanable/oil/slippery(mess_location) + new /obj/effect/decal/cleanable/blood/oil/slippery(mess_location) else new /obj/effect/decal/cleanable/dirt(mess_location) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 1f22d4baed8..c5792804dd8 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -120,24 +120,27 @@ for(var/obj/item/bodypart/iter_part as anything in bodyparts) iter_part.update_part_wound_overlay() -//Makes a blood drop, leaking amt units of blood from the mob -/mob/living/carbon/proc/bleed(amt) - if(!blood_volume || HAS_TRAIT(src, TRAIT_GODMODE)) +/// Makes a blood drop, leaking amt units of blood from the mob +/mob/living/proc/bleed(amt) + if(HAS_TRAIT(src, TRAIT_GODMODE) || !can_bleed()) return + blood_volume = max(blood_volume - amt, 0) - //Blood loss still happens in locker, floor stays clean - if(isturf(loc) && prob(sqrt(amt)*BLOOD_DRIP_RATE_MOD)) + // Blood loss still happens in locker, floor stays clean + if(isturf(loc) && prob(sqrt(amt) * BLOOD_DRIP_RATE_MOD)) add_splatter_floor(loc, (amt <= 10)) /mob/living/carbon/human/bleed(amt) amt *= physiology.bleed_mod - if(!HAS_TRAIT(src, TRAIT_NOBLOOD)) - ..() + return ..() /// A helper to see how much blood we're losing per tick -/mob/living/carbon/proc/get_bleed_rate() - if(!blood_volume) +/mob/living/proc/get_bleed_rate() + return 0 + +/mob/living/carbon/get_bleed_rate() + if(HAS_TRAIT(src, TRAIT_GODMODE) || !can_bleed()) return var/bleed_amt = 0 for(var/X in bodyparts) @@ -146,10 +149,7 @@ return bleed_amt /mob/living/carbon/human/get_bleed_rate() - if(HAS_TRAIT(src, TRAIT_NOBLOOD)) - return - . = ..() - . *= physiology.bleed_mod + return ..() * physiology.bleed_mod /** * bleed_warn() is used to for carbons with an active client to occasionally receive messages warning them about their bleeding status (if applicable) @@ -229,183 +229,412 @@ /mob/living/proc/transfer_blood_to(atom/movable/receiver, amount, forced, ignore_incompatibility) if(!blood_volume || !receiver.reagents) return FALSE + if(blood_volume < BLOOD_VOLUME_BAD && !forced) return FALSE if(blood_volume < amount) amount = blood_volume - var/blood_id = get_blood_id() - if(!blood_id) + var/datum/blood_type/blood_type = get_bloodtype() + if (!blood_type) return FALSE + var/blood_reagent = get_blood_reagent() + blood_volume -= amount + var/list/blood_data = get_blood_data() - var/list/blood_data = get_blood_data(blood_id) + if (!isliving(receiver)) + receiver.reagents.add_reagent(blood_reagent, amount, blood_data, bodytemperature, creation_callback = CALLBACK(src, PROC_REF(on_blood_created), blood_type)) + return TRUE - if(iscarbon(receiver)) - var/mob/living/carbon/carbon_receiver = receiver - if(blood_id == carbon_receiver.get_blood_id()) //both mobs have the same blood substance - if(blood_id == /datum/reagent/blood) //normal blood - if(blood_data["viruses"]) - for(var/datum/disease/blood_disease as anything in blood_data["viruses"]) - if((blood_disease.spread_flags & DISEASE_SPREAD_SPECIAL) || (blood_disease.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) - continue - carbon_receiver.ForceContractDisease(blood_disease) - var/datum/blood_type/blood_type = blood_data["blood_type"] - if(!ignore_incompatibility && !(blood_type.type_key() in carbon_receiver.dna.blood_type.compatible_types)) - carbon_receiver.reagents.add_reagent(/datum/reagent/toxin, amount * 0.5) - return TRUE + var/mob/living/target = receiver + if (target.get_blood_reagent() != blood_reagent) + target.reagents.add_reagent(blood_reagent, amount, blood_data, bodytemperature, creation_callback = CALLBACK(src, PROC_REF(on_blood_created), blood_type)) + return TRUE - carbon_receiver.blood_volume = min(carbon_receiver.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAX_LETHAL) - return TRUE + if(blood_data["viruses"]) + for(var/datum/disease/blood_disease as anything in blood_data["viruses"]) + if((blood_disease.spread_flags & DISEASE_SPREAD_SPECIAL) || (blood_disease.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) + continue + target.ForceContractDisease(blood_disease) - receiver.reagents.add_reagent(blood_id, amount, blood_data, bodytemperature) + if(!ignore_incompatibility && !(blood_type.type_key() in target.get_bloodtype().compatible_types)) + target.reagents.add_reagent(/datum/reagent/toxin, amount * 0.5) + return TRUE + + target.blood_volume = min(target.blood_volume + round(amount, 0.1), BLOOD_VOLUME_MAX_LETHAL) return TRUE +/// Callback that adds blood_reagent to any blood extracted from ourselves +/mob/living/proc/on_blood_created(datum/blood_type/blood_type, datum/reagent/new_blood) + new_blood.AddElement(/datum/element/blood_reagent, src, blood_type) -/mob/living/proc/get_blood_data(blood_id) - return +/mob/living/proc/get_blood_data() + SHOULD_CALL_PARENT(TRUE) + RETURN_TYPE(/list) -/mob/living/carbon/get_blood_data(blood_id) - if(blood_id == /datum/reagent/blood) //actual blood reagent - var/blood_data = list() - //set the blood data - blood_data["viruses"] = list() + var/datum/blood_type/blood_type = get_bloodtype() + if (!blood_type || !can_bleed()) + return - for(var/datum/disease/disease as anything in diseases) - blood_data["viruses"] += disease.Copy() + var/blood_data = list() + blood_data["blood_type"] = blood_type + blood_data["blood_DNA"] = blood_type.dna_string - blood_data["blood_DNA"] = dna.unique_enzymes - if(LAZYLEN(disease_resistances)) - blood_data["resistances"] = disease_resistances.Copy() + if (reagents) var/list/temp_chem = list() for(var/datum/reagent/blood_reagent in reagents.reagent_list) temp_chem[blood_reagent.type] = blood_reagent.volume blood_data["trace_chem"] = list2params(temp_chem) - 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) - if(!HAS_TRAIT_FROM(src, TRAIT_SUICIDED, REF(src))) - blood_data["cloneable"] = 1 - blood_data["blood_type"] = dna.blood_type - blood_data["gender"] = gender - blood_data["real_name"] = real_name - blood_data["features"] = dna.features - blood_data["factions"] = faction - blood_data["quirks"] = list() - for(var/datum/quirk/quirk as anything in quirks) - blood_data["quirks"] += quirk.type + if (blood_type.blood_flags & BLOOD_TRANSFER_VIRAL_DATA) + // Viruses we possess + blood_data["viruses"] = list() + for(var/datum/disease/disease as anything in diseases) + blood_data["viruses"] += disease.Copy() + + if(LAZYLEN(disease_resistances)) + blood_data["resistances"] = disease_resistances.Copy() + + // DNA, mind, facitons, etc don't get stored in stuff like oil + if (!(blood_type.blood_flags & BLOOD_ADD_DNA)) return blood_data -//get the id of the substance this mob use as blood. -/mob/proc/get_blood_id() - return + if(mind) + blood_data["mind"] = mind -/mob/living/simple_animal/get_blood_id() - if(blood_volume) - return /datum/reagent/blood + if(ckey) + blood_data["ckey"] = ckey + else if (persistent_client?.mob?.ckey) + blood_data["ckey"] = persistent_client.mob.ckey -/mob/living/carbon/human/get_blood_id() - if(HAS_TRAIT(src, TRAIT_HUSK) || !dna) + blood_data["factions"] = faction + return blood_data + +/mob/living/carbon/get_blood_data() + var/list/blood_data = ..() + if (!blood_data) return - if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role)) - return /datum/reagent/colorful_reagent - if(dna.species.exotic_blood) - return dna.species.exotic_blood - else if(HAS_TRAIT(src, TRAIT_NOBLOOD)) + + var/datum/blood_type/blood_type = get_bloodtype() + if (!(blood_type.blood_flags & BLOOD_ADD_DNA)) + return blood_data + + // If we haven't suicided but the ghost cannot reenter, i.e. we ghosted, don't set ourselves as cloneable + var/mob/dead/observer/ghost = get_ghost(TRUE, TRUE) + if(!HAS_TRAIT(src, TRAIT_SUICIDED) && (!ghost || ghost.can_reenter_corpse)) + blood_data["cloneable"] = TRUE + + if (!blood_data["mind"] && last_mind) + blood_data["mind"] = last_mind + + if (!blood_data["ckey"] && last_mind) + blood_data["ckey"] = ckey(last_mind.key) + + blood_data["gender"] = gender + blood_data["real_name"] = real_name + if (dna) + blood_data["blood_DNA"] = dna.unique_enzymes + blood_data["features"] = dna.features + + blood_data["quirks"] = list() + for(var/datum/quirk/quirk as anything in quirks) + blood_data["quirks"] += quirk.type + + return blood_data + +/mob/living/proc/get_bloodtype() + RETURN_TYPE(/datum/blood_type) + if (!blood_volume) return - return /datum/reagent/blood + + if (!(mob_biotypes & MOB_ORGANIC)) + if (mob_biotypes & MOB_ROBOTIC) + return get_blood_type(BLOOD_TYPE_OIL) + return + + if (mob_biotypes & MOB_SLIME) + return get_blood_type(BLOOD_TYPE_TOX) + else if (mob_biotypes & MOB_PLANT) + return get_blood_type(BLOOD_TYPE_H2O) + else if (mob_biotypes & MOB_REPTILE) + return get_blood_type(BLOOD_TYPE_LIZARD) + else if (mob_biotypes & MOB_HUMANOID) + // O+ as to avoid mobs bleeding all human bloodtypes under the sun, and its statistically the most common one + return get_blood_type(BLOOD_TYPE_O_PLUS) + + return get_blood_type(BLOOD_TYPE_ANIMAL) + +/// Returns the reagent type this mob has for blood +/mob/living/proc/get_blood_reagent() + if (!can_bleed()) + return + + var/datum/blood_type/blood_type = get_bloodtype() + return blood_type?.reagent_type + +/// Check if a mob can bleed, and possibly if they're capable of leaving decals on turfs/mobs/items +/mob/living/proc/can_bleed(bleed_flag = NONE) + if (HAS_TRAIT(src, TRAIT_HUSK) || HAS_TRAIT(src, TRAIT_NOBLOOD)) + return BLEED_NONE + + if (!bleed_flag) + return BLEED_SPLATTER + + var/datum/blood_type/blood_type = get_bloodtype() + if (!blood_type) + return BLEED_NONE + + if (blood_type.blood_flags & bleed_flag) + return BLEED_SPLATTER + + if (blood_type.blood_flags & BLOOD_ADD_DNA) + return BLEED_ADD_DNA + + return BLEED_NONE /// Returns the blood_type datum that corresponds to the string id key in GLOB.blood_types /proc/get_blood_type(id) + RETURN_TYPE(/datum/blood_type) return GLOB.blood_types[id] -/// Returns the hex color string of a given blood_type datum given an assoc list of blood_DNA e.g. ("Unknown Blood Type", "*X") -/proc/get_blood_dna_color(list/blood_DNA) +/// Returns the hex color string, or a color matrix, of a given blood_type datum given an assoc list of blood_DNA e.g. ("Unknown Blood Type", "*X") +/proc/get_color_from_blood_list(list/blood_DNA) var/datum/blood_type/blood_type - if(length(blood_DNA)) - var/last_added_bloodtype_key = blood_DNA[length(blood_DNA)] - blood_type = blood_DNA[last_added_bloodtype_key] - if(!istype(blood_type)) - blood_type = get_blood_type(blood_type) || random_human_blood_type() - return blood_type.get_color() + if(!length(blood_DNA)) + return get_blood_type(BLOOD_TYPE_O_PLUS).get_color() + else if (length(blood_DNA) == 1) // Microop for when we don't need to do color mixing + blood_type = blood_DNA[blood_DNA[length(blood_DNA)]] + return blood_type.get_color() + + var/r_color = 0 + var/g_color = 0 + var/b_color = 0 + var/valid_colors = 0 + for (var/blood_key in blood_DNA) + blood_type = blood_DNA[blood_key] + if(!istype(blood_type)) + continue + + var/list/rgb_blood = rgb2num(blood_type.get_color()) + r_color += rgb_blood[1] + g_color += rgb_blood[2] + b_color += rgb_blood[3] + valid_colors += 1 + + if (valid_colors == 0) + return get_blood_type(BLOOD_TYPE_O_PLUS).get_color() + + r_color /= valid_colors + g_color /= valid_colors + b_color /= valid_colors + return rgb(r_color, g_color, b_color) + +/// Checks if any of the passed blood types have certain blood flags +/proc/has_blood_flag(list/blood_DNA, blood_flags) + if (isnull(blood_DNA)) + return FALSE + + if (!islist(blood_DNA)) + var/datum/blood_type/blood_type = blood_DNA + blood_DNA = list(blood_type.dna_string = blood_type) + + var/matches = NONE + for (var/blood_key in blood_DNA) + var/datum/blood_type/blood_type = blood_DNA[blood_key] + matches |= (blood_type.blood_flags & blood_flags) + return matches /** * Returns TRUE if src is compatible with donor's blood, otherwise FALSE. - * * donor: Carbon mob, the one that is donating blood. + * * donor: Mob that is donating blood. */ -/mob/living/carbon/proc/get_blood_compatibility(mob/living/carbon/donor) - var/datum/blood_type/patient_blood_data = dna.blood_type - var/datum/blood_type/donor_blood_data = donor.dna.blood_type - return (donor_blood_data in patient_blood_data.compatible_types) +/mob/living/proc/get_blood_compatibility(mob/living/donor) + if (get_blood_reagent() != donor.get_blood_reagent()) + return FALSE -//to add a splatter of blood or other mob liquid. -/mob/living/proc/add_splatter_floor(turf/splatter_turf, small_drip, skip_reagents_check = FALSE) - if(!skip_reagents_check && !(get_blood_id() in list(/datum/reagent/blood, /datum/reagent/toxin/acid))) + var/datum/blood_type/patient_blood_data = get_bloodtype() + var/datum/blood_type/donor_blood_data = donor.get_bloodtype() + return (donor_blood_data?.type_key() in patient_blood_data?.compatible_types) + +/// Create a small visual-only blood splatter +/mob/living/proc/create_splatter(splatter_dir = pick(GLOB.cardinals)) + // Check for husking and TRAIT_NOBLOOD + if (!can_bleed()) // Even if we can't cover turfs, we still can add DNA to everything our blood hits return + var/obj/effect/temp_visual/dir_setting/bloodsplatter/splatter = new(get_turf(src), splatter_dir, get_bloodtype()?.get_color()) + splatter.color = get_bloodtype()?.color - if(!splatter_turf) +/* + * Create a splatter or drip of this mob's blood type + * Arguments: + * * splatter_turf - If the splatter should be made on a different turf than the mob + * * small_drip + */ +/mob/living/proc/add_splatter_floor(turf/splatter_turf, small_drip = FALSE) + if (!splatter_turf) splatter_turf = get_turf(src) - if(isclosedturf(splatter_turf) || (isgroundlessturf(splatter_turf) && !GET_TURF_BELOW(splatter_turf))) + + // Check for husking and TRAIT_NOBLOOD + switch (can_bleed(BLOOD_COVER_TURFS)) + if (BLEED_NONE) + return + if (BLEED_ADD_DNA) + return splatter_turf.add_mob_blood(src) + + return get_bloodtype()?.make_blood_splatter(src, splatter_turf, small_drip) + +/** + * This proc is a helper for spraying blood for things like slashing/piercing wounds and dismemberment. + * + * The strength of the splatter in the second argument determines how much it can dirty and how far it can go + * + * Arguments: + * * splatter_direction: Which direction the blood is flying + * * splatter_strength: How many tiles it can go, and how many items it can pass over and dirty + */ +/mob/living/carbon/proc/spray_blood(splatter_direction, splatter_strength = 3) + // Check if we can bleed and if our splatter can even go anywhere + if(!isturf(loc) || can_bleed(BLOOD_COVER_TURFS) != BLEED_SPLATTER) + return + var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc, get_static_viruses(), get_blood_dna_list(), splatter_strength) + var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) + our_splatter.fly_towards(targ, splatter_strength) + +/mob/living/proc/make_blood_trail(turf/target_turf, turf/start, was_facing, movement_direction) + if(!has_gravity() || !isturf(start)) return // BUBBER EDIT BEGIN - Blood pooling for(var/obj/effect/decal/cleanable/blood/blood_effect in splatter_turf) blood_effect.increase_blood_pool() // BUBBER EDIT END - var/list/temp_blood_DNA - if(small_drip) - // Only a certain number of drips (or one large splatter) can be on a given turf. - var/obj/effect/decal/cleanable/blood/drip/drop = locate() in splatter_turf - if(drop) - if(drop.drips < 5) - drop.drips++ - drop.add_overlay(pick(drop.random_icon_states)) - drop.add_mob_blood(src) - return - else - temp_blood_DNA = GET_ATOM_BLOOD_DNA(drop) //we transfer the dna from the drip to the splatter - qdel(drop)//the drip is replaced by a bigger splatter - else - drop = new(splatter_turf, get_static_viruses()) - drop.add_mob_blood(src) - return + var/base_bleed_rate = get_bleed_rate() + var/base_brute = getBruteLoss() - // Find a blood decal or create a new one. - var/obj/effect/decal/cleanable/blood/blood_spew = locate() in splatter_turf - if(!blood_spew) - blood_spew = new /obj/effect/decal/cleanable/blood/splatter(splatter_turf, get_static_viruses()) - if(QDELETED(blood_spew)) //Give it up + var/brute_ratio = round(base_brute / (maxHealth * 4), 0.1) + var/bleeding_rate = round(base_bleed_rate / 4, 0.1) + // We only leave a trail if we're below a certain blood threshold + // The more brute damage we have, or the more we're bleeding, the less blood we need to leave a trail + if(blood_volume < max(BLOOD_VOLUME_NORMAL * (1 - max(bleeding_rate, brute_ratio)), 0)) return - blood_spew.bloodiness = min((blood_spew.bloodiness + BLOOD_AMOUNT_PER_DECAL), BLOOD_POOL_MAX) - blood_spew.add_mob_blood(src) //give blood info to the blood decal. - if(temp_blood_DNA) - blood_spew.add_blood_DNA(temp_blood_DNA, no_visuals = small_drip) -/mob/living/carbon/human/add_splatter_floor(turf/splatter_turf, small_drip, skip_reagents_check = TRUE) - if(!HAS_TRAIT(src, TRAIT_NOBLOOD) && !dna?.blood_type.no_bleed_overlays) - . = ..() + var/blood_to_add = BLOOD_AMOUNT_PER_DECAL * 0.1 + if(body_position == LYING_DOWN) + blood_to_add += bleed_drag_amount() + blood_volume = max(blood_volume - blood_to_add, 0) + else + blood_to_add += base_bleed_rate -/mob/living/carbon/alien/add_splatter_floor(turf/splatter_turf, small_drip, skip_reagents_check) - if(!splatter_turf) - splatter_turf = get_turf(src) - var/obj/effect/decal/cleanable/xenoblood/xeno_blood_splatter = locate() in splatter_turf.contents - if(!xeno_blood_splatter) - xeno_blood_splatter = new(splatter_turf) - xeno_blood_splatter.add_blood_DNA(list("UNKNOWN DNA" = BLOOD_TYPE_XENO)) + // If we're very damaged or bleeding a lot, add even more blood to the trail + if(base_brute >= 300 || base_bleed_rate >= 7) + blood_to_add *= 2 -/mob/living/silicon/robot/add_splatter_floor(turf/splatter_turf, small_drip, skip_reagents_check) - if(!splatter_turf) - splatter_turf = get_turf(src) - var/obj/effect/decal/cleanable/oil/oil_splatter = locate() in splatter_turf.contents - if(!oil_splatter) - oil_splatter = new(splatter_turf) + switch (can_bleed(BLOOD_COVER_TURFS)) + if (BLEED_NONE) + return + if (BLEED_ADD_DNA) + return start.add_mob_blood(src) + + var/trail_dir = REVERSE_DIR(movement_direction) + // The mob is performing a diagonal movement so we need to make a diagonal trail + // This is not the same as a diagonal dir. Sorry. + // This is insteas denoted by a negative direction (so we don't conflict with real dirs) + if(movement_direction in GLOB.diagonals) + trail_dir = -1 * movement_direction + // Create a full trail on the tile we came from, and a start of a trail at the one we arrived to + create_blood_trail_component(start, trail_dir, blood_to_add * 0.67, FALSE) + create_blood_trail_component(target_turf, get_dir(start, target_turf), blood_to_add * 0.33, TRUE) + return + + var/continuing_trail = FALSE + // The mob is going a direction they were not previously facing + // We now factor in their facing direction to make a trail that looks like they're turning + // This is done by creating a diagonal dir + if(trail_dir != was_facing && trail_dir != REVERSE_DIR(was_facing)) + // Look a step back to see if we should be constructing a diagonal dir + // If there's no existing trail making a curve would look weird + for(var/obj/effect/decal/cleanable/blood/trail_holder/past_trail in get_step(start, REVERSE_DIR(was_facing))) + if(past_trail.get_trail_component(was_facing, check_reverse = TRUE, check_diagonals = TRUE, check_reverse_diagonals = TRUE)) + trail_dir |= was_facing + continuing_trail = TRUE + // In case we produced an invalid dir: go back on relevant axis + if((trail_dir & (NORTH|SOUTH)) == (NORTH|SOUTH)) + trail_dir &= ~(was_facing & (NORTH|SOUTH)) + if((trail_dir & (EAST|WEST)) == (EAST|WEST)) + trail_dir &= ~(was_facing & (EAST|WEST)) + break + + if (continuing_trail || (trail_dir in GLOB.diagonals)) + create_blood_trail_component(start, trail_dir, blood_to_add * 0.67, FALSE) + create_blood_trail_component(target_turf, get_dir(start, target_turf), blood_to_add * 0.33, TRUE) + return + + // If we're still moving cardinally and didn't change our dir, there's a chance that there's a half-trail on our turf + // in which case we want to continue it instead of doing a full trail + // Only scenario in which we don't have one is if we just started the trail from our tile + for(var/obj/effect/decal/cleanable/blood/trail_holder/trail_holder in start) + var/obj/effect/decal/cleanable/blood/trail/trail = trail_holder.get_trail_component(trail_dir) + if (trail?.half_piece) // We're moving straight, so just continue the path + continuing_trail = TRUE + break + + // If we've just started moving, put a half-trail on our previous turf instead of a full one + create_blood_trail_component(start, trail_dir, blood_to_add * 0.67, !continuing_trail) + create_blood_trail_component(target_turf, get_dir(start, target_turf), blood_to_add * 0.33, TRUE) +/* + * Locate or create a trail holder, and add a dir to it + * Arguments: + * * trail_turf - Turf on which to look for/spawn a trail + * * trail_dir - Direction in which the trail will be facing. Could be diagonal for a corner, or negative for a true diagonal trail + * * blood_to_add - How much bloodiness we should add to the trail + * * half_piece - Should we only create a beginning of a trail, and not a full tile trail? Does not support corners + */ +/mob/living/proc/create_blood_trail_component(turf/trail_turf, trail_dir, blood_to_add, half_piece) + var/obj/effect/decal/cleanable/blood/trail_holder/trail + var/check_reverse = TRUE + // Do not check the reverse dir if we're a diagonal corner or a half piece + if (trail_dir > 0 && !(trail_dir in GLOB.cardinals) || half_piece) + check_reverse = FALSE + // Pick any trail in the turf to add onto + for(var/obj/effect/decal/cleanable/blood/trail_holder/any_trail in trail_turf) + // If there exists a trail already, we will add onto the trial + // UNLESS that trail has the same direction component and it is already dried + // + // If that is the case we will look for another trail (or create a new one) + // (this will let fresh blood be laid over very dried blood) + var/obj/effect/decal/cleanable/blood/trail/any_trail_component = any_trail.get_trail_component(trail_dir, check_reverse = check_reverse) + if(isnull(any_trail_component) || !any_trail_component.dried) + trail = any_trail + break + + if(!isnull(trail)) + trail.adjust_bloodiness(blood_to_add) + return trail.add_dir_to_trail(trail_dir, src, blood_to_add, half_piece) + + trail = new(trail_turf, get_static_viruses(), get_blood_dna_list()) + if(QDELETED(trail)) + return + trail.bloodiness = blood_to_add + return trail.add_dir_to_trail(trail_dir, src, blood_to_add, half_piece) + +/mob/living/carbon/human/make_blood_trail(turf/target_turf, turf/start, direction) + if(!is_bleeding()) + return + return ..() + +/// Returns how much blood we're losing from being dragged a tile, from [/mob/living/proc/make_blood_trail] +/mob/living/proc/bleed_drag_amount() + var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) + return max(1, brute_ratio * 2) + +/mob/living/carbon/bleed_drag_amount() + var/bleed_amount = 0 + for(var/i in all_wounds) + var/datum/wound/iter_wound = i + bleed_amount += iter_wound.drag_bleed_amount() + return bleed_amount /mob/living/proc/get_blood_alcohol_content() var/blood_alcohol_content = 0 diff --git a/code/modules/mob/living/blood_types.dm b/code/modules/mob/living/blood_types.dm index a589f448415..20f95d534dc 100644 --- a/code/modules/mob/living/blood_types.dm +++ b/code/modules/mob/living/blood_types.dm @@ -5,30 +5,29 @@ var/desc /// Unique identifier for the blood type in the global list of singletons. Typically this is just the name, but some blood types might have the same name (e.g. evil blood) var/id + /// What DNA string does this bloodtype have by default, if not set by a mob? + var/dna_string = "Unknown DNA" /// Shown color of the blood type. var/color = BLOOD_COLOR_RED - /// Additional lightness multiplier for the blood color, useful for when the default lightness from the greyscaling doesn't cut it and you want something more vibrant. - /// When set, color will be transformed into a matrix with coefficients multiplied by this value - var/lightness_mult = null - /// The cached color matrix for blood with a lightness_mult. We only need to calculate this once since blood types are singletons - var/list/blood_color_matrix /// Blood types that are safe to use with people that have this blood type (for blood transfusions) var/list/compatible_types = list() /// What reagent is represented by this blood type? var/datum/reagent/reagent_type = /datum/reagent/blood /// What chem is used to restore this blood type (outside of itself, of course)? var/datum/reagent/restoration_chem = /datum/reagent/iron - /// Whether or not this blood type should create blood trails, blood sprays, etc - var/no_bleed_overlays /// Exclude abstract root types from being initialized by defining them here var/root_abstract_type /// If this blood type is meant to persist across species changes var/is_species_universal + /// Splash and expose behaviors for this blood type's reagent, to prevent water-blood covered items, as well as information transfer flags + var/blood_flags = BLOOD_ADD_DNA | BLOOD_COVER_ALL | BLOOD_TRANSFER_VIRAL_DATA /datum/blood_type/New() . = ..() id = name compatible_types |= type_key() + if (!desc) + desc = reagent_type::description /datum/blood_type/Destroy(force) if(!force) @@ -45,29 +44,127 @@ /datum/blood_type/proc/type_key() return type +/// Name of the reagent we use for blood +/datum/blood_type/proc/get_blood_name() + return capitalize(LOWER_TEXT(reagent_type::name)) + +/// Type string of this bloodtype. Used to prevent "Oil type: Oil" scenarios +/datum/blood_type/proc/get_type() + if (reagent_type != /datum/reagent/blood) + return null + return name + /// Returns blood color or color matrix /// Useful when you want to have a blood color with values out of normal hex bounds for that acidic look /// set dynamic to TRUE to redo the matrix each time (e.g. for clown blood dynamically shifting each time) /datum/blood_type/proc/get_color(dynamic = FALSE) - if(isnull(lightness_mult)) - return color + return color - if(!isnull(blood_color_matrix) && !dynamic) - return blood_color_matrix +/// Returns blood color for mob damage overlays +/datum/blood_type/proc/get_damage_color(mob/living/carbon/victim) + return get_color() - blood_color_matrix = color_to_full_rgba_matrix(color) - for(var/i in 1 to min(length(blood_color_matrix), 16)) - if (length(blood_color_matrix) == 12 && i > 9) // Don't modify constants - break - if (length(blood_color_matrix) >= 16 && i % 4 == 0) // Don't modify alpha either - continue - blood_color_matrix[i] *= lightness_mult +/// Returns blood color for wound bleeding overlays +/datum/blood_type/proc/get_wound_color(mob/living/carbon/victim) + return get_color() - return blood_color_matrix +/// Returns emissive value for an atom +/// is_worn - Emissive is being fetched for a mob overlay and not the item itself +/datum/blood_type/proc/get_emissive_alpha(atom/source, is_worn = FALSE) + return 0 -// human blood type, for organizational purposes mainly +/** + * Used to handle any unique facets of blood spawned of this blood type + * + * You don't need to worry about updating the icon of the decal, + * it will be handled automatically after setup is finished + * + * Arguments + * * blood - the blood being set up + * * new_splat - whether this is a newly instantiated blood decal, or an existing one this blood is being added to + */ +/datum/blood_type/proc/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat = FALSE) + if(new_splat && !blood.decal_reagent) + blood.decal_reagent = reagent_type + else if(blood.reagents && blood.bloodiness) // If reagents don't exist yet, we'll be added via lazyloading + blood.reagents.add_reagent(reagent_type, round(blood.bloodiness / (GET_ATOM_BLOOD_DNA_LENGTH(blood) - 1) * BLOOD_TO_UNITS_MULTIPLIER, CHEMICAL_VOLUME_ROUNDING)) // -1 as this happens before bloodiness is adjusted + + +/** + * Helper proc to make a blood splatter from the passed mob of this type + * + * Arguments + * * bleeding - the mob bleeding the blood, note we assume this blood type is that mob's blood + * * blood_turf - the turf to spawn the blood on + * * drip - whether to spawn a drip or a splatter + */ +/datum/blood_type/proc/make_blood_splatter(mob/living/bleeding, turf/blood_turf, drip = FALSE) + if(!(blood_flags & BLOOD_COVER_TURFS)) + return + + if(isgroundlessturf(blood_turf)) + blood_turf = GET_TURF_BELOW(blood_turf) + + if(isnull(blood_turf) || isclosedturf(blood_turf)) + return + + var/list/temp_blood_DNA + if(drip) + var/new_blood = /obj/effect/decal/cleanable/blood/drip::bloodiness + // Only a certain number of drips (or one large splatter) can be on a given turf. + var/obj/effect/decal/cleanable/blood/drip/drop = locate() in blood_turf + if(isnull(drop)) + var/obj/effect/decal/cleanable/blood/splatter = locate() in blood_turf + if(!QDELETED(splatter) && !splatter.dried) + splatter.add_mob_blood(bleeding) + splatter.adjust_bloodiness(new_blood) + return splatter + + drop = new(blood_turf, bleeding.get_static_viruses(), bleeding.get_blood_dna_list()) + if(!QDELETED(drop)) + drop.random_icon_states -= drop.icon_state + return drop + + if(length(drop.random_icon_states)) + // Handle adding a single drip to the base atom + // Makes use of viscontents so every drip can dry at an individual rate (with an individual color) + var/obj/effect/decal/cleanable/blood/drip/new_drop = new(drop, null, bleeding.get_blood_dna_list()) + new_drop.bloodiness = 0 + new_drop.icon_state = pick_n_take(drop.random_icon_states) + new_drop.color = color + new_drop.vis_flags |= (VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID) + new_drop.appearance_flags |= (RESET_COLOR) + drop.gender = PLURAL + drop.base_name = "drips of" + drop.vis_contents += new_drop + // Handle adding blood to the base atom + drop.adjust_bloodiness(new_blood) + drop.add_mob_blood(bleeding) + drop.add_diseases(bleeding.get_static_viruses()) + return drop + + temp_blood_DNA = GET_ATOM_BLOOD_DNA(drop) // We transfer the dna from the drip to the splatter + qdel(drop) // The drip is replaced by a bigger splatter + + // Find a blood decal or create a new one. + var/obj/effect/decal/cleanable/blood/splatter = locate() in blood_turf + if(isnull(splatter) || splatter.dried) + splatter = new(blood_turf, bleeding.get_static_viruses(), bleeding.get_blood_dna_list()) + if(QDELETED(splatter)) //Give it up + return null + else + splatter.adjust_bloodiness(BLOOD_AMOUNT_PER_DECAL) + splatter.add_diseases(bleeding.get_static_viruses()) + splatter.add_mob_blood(bleeding) // Give blood info to the blood decal + + if(LAZYLEN(temp_blood_DNA)) + splatter.add_blood_DNA(temp_blood_DNA) + return splatter + +// Human blood type, for organizational purposes mainly /datum/blood_type/human desc = "Blood cells suspended in plasma, the most abundant of which being the hemoglobin-containing red blood cells." + dna_string = "Human DNA" root_abstract_type = /datum/blood_type/human /datum/blood_type/human/a_minus @@ -129,59 +226,106 @@ /datum/blood_type/human/o_plus, ) -/datum/blood_type/animal - name = BLOOD_TYPE_ANIMAL - compatible_types = list( - /datum/blood_type/animal, - ) - -/datum/blood_type/lizard - name = BLOOD_TYPE_LIZARD - // color = BLOOD_COLOR_LIZARD //BUBBER EDIT REMOVAL - compatible_types = list( - /datum/blood_type/lizard, - ) - -/datum/blood_type/ethereal - name = BLOOD_TYPE_ETHEREAL - color = /datum/reagent/consumable/liquidelectricity::color - lightness_mult = 1.255 // for more vibrant gatorade coloring - compatible_types = list( - /datum/blood_type/ethereal, - ) - -/datum/blood_type/oil - name = BLOOD_TYPE_OIL - color = BLOOD_COLOR_OIL - reagent_type = /datum/reagent/fuel/oil - -/datum/blood_type/vampire - name = BLOOD_TYPE_VAMPIRE - compatible_types = list( - /datum/blood_type/vampire, - ) - -/datum/blood_type/meat // why does this exist - name = BLOOD_TYPE_MEAT - -/datum/blood_type/universal +/datum/blood_type/human/universal name = BLOOD_TYPE_UNIVERSAL -/datum/blood_type/universal/New() +/datum/blood_type/human/universal/New() . = ..() compatible_types = subtypesof(/datum/blood_type) +/datum/blood_type/animal + name = BLOOD_TYPE_ANIMAL + desc = "Blood cells suspended in plasma, the most abundant of which being the hemoglobin-containing red blood cells." + dna_string = "Animal DNA" + +/datum/blood_type/lizard + name = BLOOD_TYPE_LIZARD + desc = "Green sulfhemoglobin subtype-based blood, which while less effective at transporting oxygen, \ + is capable of withstanding much higher temperatures without breaking down or clotting." + dna_string = "Lizard DNA" + // color = BLOOD_COLOR_LIZARD //BUBBER EDIT REMOVAL + +/datum/blood_type/ethereal + name = BLOOD_TYPE_ETHEREAL + dna_string = "Ethereal DNA" + color = /datum/reagent/consumable/liquidelectricity::color + reagent_type = /datum/reagent/consumable/liquidelectricity + +/datum/blood_type/ethereal/get_emissive_alpha(atom/source, is_worn = FALSE) + if (is_worn) + return 102 + return 125 + +/datum/blood_type/ethereal/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat = FALSE) + . = ..() + blood.emissive_alpha = max(blood.emissive_alpha, new_splat ? 125 : 63) + if (new_splat) + return + blood.can_dry = FALSE + +/datum/blood_type/oil + name = BLOOD_TYPE_OIL + dna_string = "Oil" + color = BLOOD_COLOR_OIL + reagent_type = /datum/reagent/fuel/oil + restoration_chem = /datum/reagent/fuel + blood_flags = BLOOD_COVER_ALL + +/datum/blood_type/oil/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat = FALSE) + . = ..() + if (!new_splat) + return + + // Oil blood will never dry and can be ignited with fire or anything sufficiently hot + blood.can_dry = FALSE + blood.dry_prefix = null + blood.dry_desc = null + + // Always force our decals to have our reagent, we don't want liquid gibs from oily guts + blood.decal_reagent = reagent_type + + // Oily guts are not converted to robotic ones, so you can still have your biomechanical abominations >X) + if (!istype(blood, /obj/effect/decal/cleanable/blood/gibs)) + blood.AddElement(/datum/element/easy_ignite) + + // Replace only the default description + if (blood.desc == /obj/effect/decal/cleanable/blood::desc) + blood.desc = /obj/effect/decal/cleanable/blood/oil::desc + +/datum/blood_type/vampire + name = BLOOD_TYPE_VAMPIRE + dna_string = "Hemovore DNA" + +/datum/blood_type/meat // why does this exist + name = BLOOD_TYPE_MEAT + dna_string = "Meaty DNA" + /datum/blood_type/xeno name = BLOOD_TYPE_XENO + desc = "An incredibly potent mineral acid, somehow capable of carrying oxygen." + dna_string = "Alien DNA" color = BLOOD_COLOR_XENO - lightness_mult = 1.255 // For parity with pre-refactor xeno blood sprites - compatible_types = list(/datum/blood_type/xeno) + reagent_type = /datum/reagent/toxin/acid + // Viruses cannot survive in acid + blood_flags = BLOOD_ADD_DNA | BLOOD_COVER_ALL + +/datum/blood_type/xeno/get_blood_name() + return "Acid" // "pool of sulphuric acid" is a bit too lengthy of a name + +/datum/blood_type/xeno/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat = FALSE) + . = ..() + if (!new_splat) + return + blood.can_dry = FALSE + // Replace only the default description + if (blood.desc == /obj/effect/decal/cleanable/blood::desc) + blood.desc = "It's green and acidic. It looks like... blood?" /// April fool's blood for clowns /datum/blood_type/clown name = BLOOD_TYPE_CLOWN + dna_string = "Clown DNA" reagent_type = /datum/reagent/colorful_reagent - lightness_mult = 1.255 is_species_universal = TRUE /// The cached list of random colors to pick from var/list/random_color_list @@ -199,33 +343,57 @@ /// Slimeperson blood, aka 'toxin' blood type /datum/blood_type/slime name = BLOOD_TYPE_TOX + dna_string = "Slime DNA" color = /datum/reagent/toxin/slimejelly::color reagent_type = /datum/reagent/toxin/slimejelly - no_bleed_overlays = TRUE + restoration_chem = /datum/reagent/stable_plasma // Because normal plasma already refills our blood + +// Ensures that lighter slimefolk look half-decent when wounded and bleeding +/datum/blood_type/slime/get_wound_color(mob/living/carbon/victim) + return victim.dna?.features?["mcolor"] || get_color() +/datum/blood_type/slime/get_damage_color(mob/living/carbon/victim) + return victim.dna?.features?["mcolor"] || get_color() /// Podpeople blood /datum/blood_type/water name = BLOOD_TYPE_H2O + dna_string = "Plant DNA" color = /datum/reagent/water::color reagent_type = /datum/reagent/water - no_bleed_overlays = TRUE + restoration_chem = null + blood_flags = BLOOD_ADD_DNA | BLOOD_TRANSFER_VIRAL_DATA + +// Prevents awkward grey wounds on the mob while keeping bleed overlays looking like water leaking from a balloon +/datum/blood_type/water/get_damage_color(mob/living/carbon/victim) + return COLOR_LIME /// Snail blood /datum/blood_type/snail name = BLOOD_TYPE_SNAIL + dna_string = "Snail DNA" reagent_type = /datum/reagent/lube + restoration_chem = /datum/reagent/silicon + +/datum/blood_type/snail/set_up_blood(obj/effect/decal/cleanable/blood/blood, new_splat) + . = ..() + if(blood.bloodiness < BLOOD_AMOUNT_PER_DECAL) + return + var/slip_amt = new_splat ? 4 SECONDS : 1 SECONDS + var/slip_flags = new_splat ? (NO_SLIP_WHEN_WALKING | SLIDE) : (NO_SLIP_WHEN_WALKING) + blood.AddComponent(/datum/component/slippery, slip_amt, slip_flags) /// An abstract-ish blood type used particularly for species with blood set to random reagents, such as podpeople /datum/blood_type/random_chemical root_abstract_type = /datum/blood_type/random_chemical -/datum/blood_type/random_chemical/New(datum/reagent/reagent_type) +/datum/blood_type/random_chemical/New(datum/reagent/reagent) + name = initial(reagent.name) + desc = initial(reagent.description) . = ..() - src.name = initial(reagent_type.name) - src.color = initial(reagent_type.color) - src.reagent_type = reagent_type - src.restoration_chem = reagent_type - src.root_abstract_type = null + id = type_key() + color = initial(reagent.color) + reagent_type = reagent + root_abstract_type = null /datum/blood_type/random_chemical/type_key() return reagent_type diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index aca44e180dc..2bd3ac0d011 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -19,7 +19,7 @@ var/leaping = FALSE ///The speed this alien should move at. var/alien_speed = 0 - gib_type = /obj/effect/decal/cleanable/xenoblood/xgibs + gib_type = /obj/effect/decal/cleanable/blood/gibs/xeno unique_name = TRUE var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|princess|queen)( \\(\\d+\\))?") @@ -74,47 +74,39 @@ // Run base mob body temperature proc before taking damage // this balances body temp to the environment and natural stabilization . = ..() - - if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) - //Body temperature is too hot. - throw_alert(ALERT_XENO_FIRE, /atom/movable/screen/alert/alien_fire) - switch(bodytemperature) - if(360 to 400) - apply_damage(HEAT_DAMAGE_LEVEL_1 * seconds_per_tick, BURN) - if(400 to 460) - apply_damage(HEAT_DAMAGE_LEVEL_2 * seconds_per_tick, BURN) - if(460 to INFINITY) - if(on_fire) - apply_damage(HEAT_DAMAGE_LEVEL_3 * seconds_per_tick, BURN) - else - apply_damage(HEAT_DAMAGE_LEVEL_2 * seconds_per_tick, BURN) - else + if(bodytemperature <= BODYTEMP_HEAT_DAMAGE_LIMIT) clear_alert(ALERT_XENO_FIRE) + return -/mob/living/carbon/alien/getTrail() - if(getBruteLoss() < 200) - return pick (list("ltrails_1", "ltrails2")) - else - return pick (list("trails_1", "trails2")) + //Body temperature is too hot. + throw_alert(ALERT_XENO_FIRE, /atom/movable/screen/alert/alien_fire) + switch(bodytemperature) + if(360 to 400) + apply_damage(HEAT_DAMAGE_LEVEL_1 * seconds_per_tick, BURN) + if(400 to 460) + apply_damage(HEAT_DAMAGE_LEVEL_2 * seconds_per_tick, BURN) + if(460 to INFINITY) + if(on_fire) + apply_damage(HEAT_DAMAGE_LEVEL_3 * seconds_per_tick, BURN) + else + apply_damage(HEAT_DAMAGE_LEVEL_2 * seconds_per_tick, BURN) -/mob/living/carbon/alien/get_trail_blood() - return BLOOD_STATE_XENO +/mob/living/carbon/alien/get_bloodtype() + return get_blood_type(BLOOD_TYPE_XENO) /*---------------------------------------- Proc: AddInfectionImages() Des: Gives the client of the alien an image on each infected mob. ----------------------------------------*/ /mob/living/carbon/alien/proc/AddInfectionImages() - if (client) - for (var/i in GLOB.mob_living_list) - var/mob/living/L = i - if(HAS_TRAIT(L, TRAIT_XENO_HOST)) - var/obj/item/organ/body_egg/alien_embryo/A = L.get_organ_by_type(/obj/item/organ/body_egg/alien_embryo) - if(A) - var/I = image('icons/mob/nonhuman-player/alien.dmi', loc = L, icon_state = "infected[A.stage]") - client.images += I - return + if (!client) + return + for (var/mob/living/target as anything in GLOB.mob_living_list) + if(HAS_TRAIT(target, TRAIT_XENO_HOST)) + var/obj/item/organ/body_egg/alien_embryo/embryo = target.get_organ_by_type(/obj/item/organ/body_egg/alien_embryo) + if(embryo) + client.images += image('icons/mob/nonhuman-player/alien.dmi', loc = target, icon_state = "infected[embryo.stage]") /*---------------------------------------- Proc: RemoveInfectionImages() diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 2c91579e976..e5c5731dc03 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -66,9 +66,6 @@ In all, this is a lot like the monkey code. /N var/obj/item/bodypart/affecting = get_bodypart(get_random_valid_zone(user.zone_selected)) apply_damage(rand(1, 3), BRUTE, affecting) -/mob/living/carbon/alien/create_splatter(splatter_dir) - new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(get_turf(src), splatter_dir) - /mob/living/carbon/alien/ex_act(severity, target, origin) . = ..() if(!. || QDELETED(src)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 66c29fed1f4..fb7fabc73d4 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1324,27 +1324,6 @@ return TRUE return FALSE -/** - * This proc is a helper for spraying blood for things like slashing/piercing wounds and dismemberment. - * - * The strength of the splatter in the second argument determines how much it can dirty and how far it can go - * - * Arguments: - * * splatter_direction: Which direction the blood is flying - * * splatter_strength: How many tiles it can go, and how many items it can pass over and dirty - */ -/mob/living/carbon/proc/spray_blood(splatter_direction, splatter_strength = 3) - if(!isturf(loc)) - return - if(dna.blood_type.no_bleed_overlays) - return - var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc) - our_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) - our_splatter.blood_dna_info = get_blood_dna_list() - our_splatter.color = get_blood_dna_color(our_splatter.blood_dna_info) - var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) - our_splatter.fly_towards(targ, splatter_strength) - /// Goes through the organs and bodyparts of the mob and updates their blood_dna_info, in case their blood type has changed (via set_species() or otherwise) /mob/living/carbon/proc/update_cached_blood_dna_info() var/list/blood_dna_info = get_blood_dna_list() @@ -1353,17 +1332,20 @@ for(var/obj/item/bodypart/bodypart in bodyparts) bodypart.blood_dna_info = blood_dna_info -/mob/living/carbon/set_blood_type(datum/blood_type/new_blood_type, update_cached_blood_dna_info = TRUE) +/// Setter for changing a mob's blood type +/mob/living/carbon/proc/set_blood_type(datum/blood_type/new_blood_type, update_cached_blood_dna_info = TRUE) + SHOULD_CALL_PARENT(TRUE) + if(isnull(dna)) return - if(dna.blood_type == new_blood_type) // already has this blood type, we don't need to do anything. + + if(get_bloodtype() == new_blood_type) // already has this blood type, we don't need to do anything. return dna.blood_type = new_blood_type if(update_cached_blood_dna_info) update_cached_blood_dna_info() - - return ..() + SEND_SIGNAL(src, COMSIG_CARBON_CHANGED_BLOOD_TYPE, new_blood_type, update_cached_blood_dna_info) /mob/living/carbon/dropItemToGround(obj/item/to_drop, force = FALSE, silent = FALSE, invdrop = TRUE, turf/newloc = null) if(to_drop && (organs.Find(to_drop) || bodyparts.Find(to_drop))) //let's not do this, aight? @@ -1398,7 +1380,7 @@ var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) if(isnull(head)) return ..() - if(HAS_TRAIT(src, TRAIT_NOBLOOD)) + if(!can_bleed()) to_chat(src, span_notice("You get a headache.")) return head.adjustBleedStacks(5) @@ -1409,3 +1391,7 @@ return hit_zone // When a limb is missing the damage is actually passed to the chest return BODY_ZONE_CHEST + +/mob/living/carbon/get_bloodtype() + RETURN_TYPE(/datum/blood_type) + return dna?.blood_type diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 9b89e649aab..88d75d7a0c6 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -772,7 +772,4 @@ if(HAS_TRAIT(src, TRAIT_NO_SIDE_KICK)) // added as an extra check, just in case . &= ~SHOVE_CAN_KICK_SIDE -/mob/living/carbon/create_splatter(splatter_dir) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(get_turf(src), splatter_dir, dna?.blood_type.get_color()) - #undef SHAKE_ANIMATION_OFFSET diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index 53cb6edcd9e..28607bffc56 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -303,7 +303,7 @@ damage_overlay.color = iter_part.damage_overlay_color if(iter_part.brutestate) var/mutable_appearance/blood_damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "[iter_part.dmg_overlay_type]_[iter_part.body_zone]_[iter_part.brutestate]0", appearance_flags = RESET_COLOR) //we're adding icon_states of the base image as overlays - blood_damage_overlay.color = dna.blood_type.get_color() + blood_damage_overlay.color = get_bloodtype()?.get_damage_color(src) var/mutable_appearance/brute_damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "[iter_part.dmg_overlay_type]_[iter_part.body_zone]_[iter_part.brutestate]0_overlay", appearance_flags = RESET_COLOR) blood_damage_overlay.overlays += brute_damage_overlay damage_overlay.add_overlay(blood_damage_overlay) @@ -316,17 +316,19 @@ overlays_standing[DAMAGE_LAYER] = damage_overlay apply_overlay(DAMAGE_LAYER) -/mob/living/carbon/update_wound_overlays() +/// Handles bleeding overlays +/mob/living/carbon/proc/update_wound_overlays() remove_overlay(WOUND_LAYER) - if(dna?.blood_type.no_bleed_overlays) + var/datum/blood_type/blood_type = get_bloodtype() + if(!blood_type || !can_bleed()) return var/mutable_appearance/wound_overlay for(var/obj/item/bodypart/iter_part as anything in bodyparts) if(iter_part.bleed_overlay_icon) var/mutable_appearance/blood_overlay = mutable_appearance('icons/mob/effects/bleed_overlays.dmi', "blank", -WOUND_LAYER, appearance_flags = KEEP_TOGETHER) - blood_overlay.color = dna.blood_type.get_color() + blood_overlay.color = blood_type.get_wound_color(src) wound_overlay ||= blood_overlay wound_overlay.add_overlay(iter_part.bleed_overlay_icon) diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 0c4a16a244e..e82978b8be9 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -440,10 +440,14 @@ . += "[t_He] [t_is] holding [held_thing.examine_title_worn(user)] in [t_his] [get_held_index_name(get_held_index_of_item(held_thing))]." //gloves if(gloves && !(obscured & ITEM_SLOT_GLOVES) && !HAS_TRAIT(gloves, TRAIT_EXAMINE_SKIP)) - . += "[t_He] [t_has] [gloves.examine_title_worn(user)] on [t_his] hands." - else if(GET_ATOM_BLOOD_DNA_LENGTH(src)) - if(num_hands) - . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!") + . += "[t_He] [t_has] [gloves.examine_title(user)] on [t_his] hands." + else if(GET_ATOM_BLOOD_DECAL_LENGTH(src) && num_hands) + var/list/blood_stains = GET_ATOM_BLOOD_DECALS(src) + var/datum/blood_type/blood_type = blood_stains[blood_stains[length(blood_stains)]] + var/blood_descriptior = "blood" + if(istype(blood_type)) + blood_descriptior = LOWER_TEXT(blood_type.get_blood_name()) + . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "][blood_descriptior]-stained hand[num_hands > 1 ? "s" : ""]!") //handcuffed? if(handcuffed) var/cables_or_cuffs = istype(handcuffed, /obj/item/restraints/handcuffs/cable) ? "restrained with cable" : "handcuffed" @@ -536,8 +540,8 @@ . += "[t_He] [t_is] holding [held_thing.examine_title_worn(user)] in [t_his] [get_held_index_name(get_held_index_of_item(held_thing))]." //gloves if(gloves && !(obscured & ITEM_SLOT_GLOVES) && !HAS_TRAIT(gloves, TRAIT_EXAMINE_SKIP)) - . += "[t_He] [t_has] [gloves.examine_title_worn(user)] on [t_his] hands." - else if(GET_ATOM_BLOOD_DNA_LENGTH(src) || blood_in_hands) + . += "[t_He] [t_has] [gloves.examine_title(user)] on [t_his] hands." + else if(GET_ATOM_BLOOD_DECAL_LENGTH(src) || blood_in_hands) if(num_hands) . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!") //handcuffed? diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 4c1f3ed4331..8af474c9d2e 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -45,9 +45,8 @@ GLOBAL_LIST_EMPTY(features_by_species) ///Never, Optional, or Forced digi legs? var/digitigrade_customization = DIGITIGRADE_NEVER - ///If your race bleeds something other than bog standard blood, change this to reagent id. For example, ethereals bleed liquid electricity. - var/datum/reagent/exotic_blood ///If your race uses a non standard bloodtype (A+, O-, AB-, etc). For example, lizards have L type blood. + ///Reagent that your species bleeds, and what chemical can be used to recover lost blood depend on this var/exotic_bloodtype ///The rate at which blood is passively drained by having the blood deficiency quirk. Some races such as slimepeople can regen their blood at different rates so this is to account for that var/blood_deficiency_drain_rate = BLOOD_REGEN_FACTOR + BLOOD_DEFICIENCY_MODIFIER // slightly above the regen rate so it slowly drains instead of regenerates. @@ -395,17 +394,13 @@ GLOBAL_LIST_EMPTY(features_by_species) if(old_species.type != type) replace_body(human_who_gained_species, src) - if(!human_who_gained_species.dna.blood_type.is_species_universal) // Clown blood is forever. + if(!human_who_gained_species.get_bloodtype()?.is_species_universal) // Clown blood is forever. //Assigns exotic blood type if the species has one - if(exotic_bloodtype && human_who_gained_species.dna.blood_type != exotic_bloodtype) + if(exotic_bloodtype && human_who_gained_species.get_bloodtype()?.id != exotic_bloodtype) human_who_gained_species.set_blood_type(get_blood_type(exotic_bloodtype)) - // updates the cached organ blood types in case our blood type changed - human_who_gained_species.update_cached_blood_dna_info() //Otherwise, check if the previous species had an exotic bloodtype and we do not have one and assign a random blood type - //(why the fuck is blood type not tied to a fucking DNA block?) else if(old_species.exotic_bloodtype && isnull(exotic_bloodtype)) human_who_gained_species.set_blood_type(random_human_blood_type()) - human_who_gained_species.update_cached_blood_dna_info() regenerate_organs(human_who_gained_species, old_species, replace_current = human_who_gained_species.visual_only_organs, visual_only = human_who_gained_species.visual_only_organs) // SKYRAT EDIT - Allows existing organs to be properly removed when regenerating organs - ORIGINAL: regenerate_organs(human_who_gained_species, old_species, replace_current = FALSE, visual_only = human_who_gained_species.visual_only_organs) // Update locked slots AFTER all organ and body stuff is handled @@ -772,32 +767,6 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/pre_equip_species_outfit(datum/job/job, mob/living/carbon/human/equipping, visuals_only = FALSE) return -/** - * Handling special reagent interactions. - * - * Return null continue running the normal on_mob_life() for that reagent. - * Return COMSIG_MOB_STOP_REAGENT_CHECK to not run the normal metabolism effects. - * - * NOTE: If you return COMSIG_MOB_STOP_REAGENT_CHECK, that reagent will not be removed liike normal! You must handle it manually. - **/ -/datum/species/proc/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) - SHOULD_CALL_PARENT(TRUE) - if(!istype(chem, /datum/reagent/blood)) // the blood reagent handles this itself, this is for exotic blood types - var/datum/blood_type/blood_type = affected.dna.blood_type - if(chem.type == blood_type?.reagent_type) - affected.blood_volume = min(affected.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM) - affected.reagents.del_reagent(chem.type) - return COMSIG_MOB_STOP_REAGENT_CHECK - if(chem.type == blood_type?.restoration_chem && affected.blood_volume < BLOOD_VOLUME_NORMAL) - affected.blood_volume += BLOOD_REGEN_FACTOR * seconds_per_tick - affected.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) - return COMSIG_MOB_STOP_REAGENT_CHECK - if(!chem.overdosed && chem.overdose_threshold && chem.volume >= chem.overdose_threshold && !HAS_TRAIT(affected, TRAIT_OVERDOSEIMMUNE)) - chem.overdosed = TRUE - chem.overdose_start(affected) - affected.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME) - return SEND_SIGNAL(affected, COMSIG_SPECIES_HANDLE_CHEMICAL, chem, seconds_per_tick, times_fired) - /** * Equip the outfit required for life. Replaces items currently worn. */ @@ -1836,6 +1805,7 @@ GLOBAL_LIST_EMPTY(features_by_species) */ /datum/species/proc/create_pref_blood_perks() var/list/to_add = list() + var/datum/blood_type/blood_type = exotic_bloodtype ? get_blood_type(exotic_bloodtype) : null // TRAIT_NOBLOOD takes priority by default if(TRAIT_NOBLOOD in inherent_traits) @@ -1847,12 +1817,12 @@ GLOBAL_LIST_EMPTY(features_by_species) )) // Otherwise, check if their exotic blood is a valid typepath - else if(ispath(exotic_blood)) + else if(ispath(blood_type?.reagent_type)) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, SPECIES_PERK_ICON = "tint", - SPECIES_PERK_NAME = initial(exotic_blood.name), - SPECIES_PERK_DESC = "[name] blood is [initial(exotic_blood.name)], which can make receiving medical treatment harder.", + SPECIES_PERK_NAME = initial(blood_type.reagent_type.name), + SPECIES_PERK_DESC = "[name] blood is [initial(blood_type.reagent_type.name)], which can make receiving medical treatment harder.", )) // Otherwise otherwise, see if they have an exotic bloodtype set diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 4d110e701dc..74dc07f83ec 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -42,12 +42,12 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) investigate_log("has died at [loc_name(src)].
\ BRUTE: [src.getBruteLoss()] BURN: [src.getFireLoss()] TOX: [src.getToxLoss()] OXY: [src.getOxyLoss()] STAM: [src.getStaminaLoss()]
\ Brain damage: [src.get_organ_loss(ORGAN_SLOT_BRAIN) || "0"]
\ - Blood volume: [src.blood_volume]cl ([round((src.blood_volume / BLOOD_VOLUME_NORMAL) * 100, 0.1)]%)
\ + [get_bloodtype()?.get_blood_name() || "Blood"] volume: [src.blood_volume]cl ([round((src.blood_volume / BLOOD_VOLUME_NORMAL) * 100, 0.1)]%)
\ Reagents:
[reagents_readout()]", INVESTIGATE_DEATHS) to_chat(src, span_warning("You have died. Barring complete bodyloss, you can in most cases be revived by other players. If you do not wish to be brought back, use the \"Do Not Resuscitate\" verb in the ghost tab.")) /mob/living/carbon/human/proc/reagents_readout() - var/readout = "Blood:" + var/readout = "[get_bloodtype()?.get_blood_name() || "Blood"]stream:" for(var/datum/reagent/reagent in reagents?.reagent_list) readout += "
[round(reagent.volume, 0.001)] units of [reagent.name]" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 459bd070fa5..3701a490026 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -135,7 +135,7 @@ if(istype(id, /obj/item/card/id/advanced/chameleon)) id_gender ||= gender id_species ||= dna.species.name - id_blood_type ||= dna.blood_type + id_blood_type ||= get_bloodtype() if(istype(id, /obj/item/card/id/advanced)) var/obj/item/card/id/advanced/advancedID = id @@ -1048,12 +1048,6 @@ return FALSE return ..() -/mob/living/carbon/human/reagent_check(datum/reagent/chem, seconds_per_tick, times_fired) - . = ..() - if(. & COMSIG_MOB_STOP_REAGENT_CHECK) - return - return dna.species.handle_chemical(chem, src, seconds_per_tick, times_fired) - /mob/living/carbon/human/updatehealth() . = ..() var/health_deficiency = max((maxHealth - health), staminaloss) diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 9b419028bcf..94fb2c4f62b 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -204,71 +204,70 @@ There are several things that need to be remembered: //Bloody hands begin if(isnull(gloves)) - if(blood_in_hands && num_hands > 0) - // When byond gives us filters that respect dirs we can just use an alpha mask for this but until then, two icons weeeee - var/mutable_appearance/hands_combined = mutable_appearance(layer = -GLOVES_LAYER, appearance_flags = KEEP_TOGETHER) - if(has_left_hand(check_disabled = FALSE)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands_left") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) - hands_combined.overlays += blood_overlay - if(has_right_hand(check_disabled = FALSE)) - var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands_right") - blood_overlay.color = get_blood_dna_color(GET_ATOM_BLOOD_DNA(src)) - hands_combined.overlays += blood_overlay - overlays_standing[GLOVES_LAYER] = hands_combined - apply_overlay(GLOVES_LAYER) + if(!blood_in_hands || !num_hands || !GET_ATOM_BLOOD_DECAL_LENGTH(src)) + return + // When byond gives us filters that respect dirs we can just use an alpha mask for this but until then, two icons weeeee + var/mutable_appearance/hands_combined = mutable_appearance(layer = -GLOVES_LAYER, appearance_flags = KEEP_TOGETHER) + if(has_left_hand(check_disabled = FALSE)) + var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands_left") + blood_overlay.color = get_blood_dna_color() + hands_combined.overlays += blood_overlay + if(has_right_hand(check_disabled = FALSE)) + var/mutable_appearance/blood_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands_right") + blood_overlay.color = get_blood_dna_color() + hands_combined.overlays += blood_overlay + overlays_standing[GLOVES_LAYER] = hands_combined + apply_overlay(GLOVES_LAYER) return // Bloody hands end - if(gloves) - var/obj/item/worn_item = gloves - update_hud_gloves(worn_item) + var/obj/item/worn_item = gloves + update_hud_gloves(worn_item) - if(update_obscured) - update_obscured_slots(worn_item.flags_inv) + if(update_obscured) + update_obscured_slots(worn_item.flags_inv) - if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_GLOVES)) - return + if(HAS_TRAIT(worn_item, TRAIT_NO_WORN_ICON) || (check_obscured_slots() & ITEM_SLOT_GLOVES)) + return - var/icon_file = 'icons/mob/clothing/hands.dmi' + var/icon_file = 'icons/mob/clothing/hands.dmi' - // SKYRAT EDIT ADDITION - var/mutant_override = FALSE - if(bodyshape & BODYSHAPE_CUSTOM) - var/species_icon_file = dna.species.generate_custom_worn_icon(OFFSET_GLOVES, gloves, src) - if(species_icon_file) - icon_file = species_icon_file - mutant_override = TRUE - // SKYRAT EDIT END + // SKYRAT EDIT ADDITION + var/mutant_override = FALSE + if(bodyshape & BODYSHAPE_CUSTOM) + var/species_icon_file = dna.species.generate_custom_worn_icon(OFFSET_GLOVES, gloves, src) + if(species_icon_file) + icon_file = species_icon_file + mutant_override = TRUE + // SKYRAT EDIT END - var/mutable_appearance/gloves_overlay = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE + var/mutable_appearance/gloves_overlay = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) // SKYRAT EDIT CHANGE - var/feature_y_offset = 0 - //needs to be typed, hand_bodyparts can have nulls - for (var/obj/item/bodypart/arm/my_hand in hand_bodyparts) - var/list/glove_offset = my_hand.worn_glove_offset?.get_offset() - if (glove_offset && (!feature_y_offset || glove_offset["y"] > feature_y_offset)) - feature_y_offset = glove_offset["y"] + var/feature_y_offset = 0 + //needs to be typed, hand_bodyparts can have nulls + for (var/obj/item/bodypart/arm/my_hand in hand_bodyparts) + var/list/glove_offset = my_hand.worn_glove_offset?.get_offset() + if (glove_offset && (!feature_y_offset || glove_offset["y"] > feature_y_offset)) + feature_y_offset = glove_offset["y"] - gloves_overlay.pixel_z += feature_y_offset + gloves_overlay.pixel_z += feature_y_offset - // We dont have any >2 hands human species (and likely wont ever), so theres no point in splitting this because: - // It will only run if the left hand OR the right hand is missing, and it wont run if both are missing because you cant wear gloves with no arms - // (unless admins mess with this then its their fault) - if(num_hands < default_num_hands) - var/static/atom/movable/alpha_filter_target - if(isnull(alpha_filter_target)) - alpha_filter_target = new(null) - alpha_filter_target.icon = 'icons/effects/effects.dmi' - alpha_filter_target.icon_state = "missing[!has_left_hand(check_disabled = FALSE) ? "l" : "r"]" - alpha_filter_target.render_target = "*MissGlove [REF(src)] [!has_left_hand(check_disabled = FALSE) ? "L" : "R"]" - gloves_overlay.add_overlay(alpha_filter_target) - gloves_overlay.filters += filter(type="alpha", render_source=alpha_filter_target.render_target, y=feature_y_offset, flags=MASK_INVERSE) + // We dont have any >2 hands human species (and likely wont ever), so theres no point in splitting this because: + // It will only run if the left hand OR the right hand is missing, and it wont run if both are missing because you cant wear gloves with no arms + // (unless admins mess with this then its their fault) + if(num_hands < default_num_hands) + var/static/atom/movable/alpha_filter_target + if(isnull(alpha_filter_target)) + alpha_filter_target = new(null) + alpha_filter_target.icon = 'icons/effects/effects.dmi' + alpha_filter_target.icon_state = "missing[!has_left_hand(check_disabled = FALSE) ? "l" : "r"]" + alpha_filter_target.render_target = "*MissGlove [REF(src)] [!has_left_hand(check_disabled = FALSE) ? "L" : "R"]" + gloves_overlay.add_overlay(alpha_filter_target) + gloves_overlay.filters += filter(type="alpha", render_source=alpha_filter_target.render_target, y=feature_y_offset, flags=MASK_INVERSE) - overlays_standing[GLOVES_LAYER] = gloves_overlay + overlays_standing[GLOVES_LAYER] = gloves_overlay apply_overlay(GLOVES_LAYER) - /mob/living/carbon/human/update_worn_glasses(update_obscured = TRUE) remove_overlay(GLASSES_LAYER) @@ -310,7 +309,6 @@ There are several things that need to be remembered: overlays_standing[GLASSES_LAYER] = glasses_overlay apply_overlay(GLASSES_LAYER) - /mob/living/carbon/human/update_worn_ears(update_obscured = TRUE) remove_overlay(EARS_LAYER) @@ -1179,6 +1177,9 @@ mutant_styles: The mutant style - taur bodytype, STYLE_TESHARI, etc. // SKYRAT E var/list/separate_overlays = separate_worn_overlays(standing, draw_target, isinhands, file2use) if(length(separate_overlays)) standing.overlays += separate_overlays + else // Don't nest overlays if there's nothing to nest against + standing.overlays -= draw_target + standing = draw_target standing = center_image(standing, isinhands ? inhand_x_dimension : worn_x_dimension, isinhands ? inhand_y_dimension : worn_y_dimension) diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 2974155515d..28ff1fc3ea6 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -25,6 +25,7 @@ ) inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID + exotic_bloodtype = BLOOD_TYPE_OIL meat = null mutantbrain = /obj/item/organ/brain/cybernetic mutanttongue = /obj/item/organ/tongue/robot diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index b98e5fc77cf..69aba91b98d 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -7,7 +7,6 @@ mutantstomach = /obj/item/organ/stomach/ethereal mutanttongue = /obj/item/organ/tongue/ethereal mutantheart = /obj/item/organ/heart/ethereal - exotic_blood = /datum/reagent/consumable/liquidelectricity //Liquid Electricity. fuck you think of something better gamer exotic_bloodtype = BLOOD_TYPE_ETHEREAL siemens_coeff = 0.5 //They thrive on energy payday_modifier = 1.0 diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 572d4e05aa5..5b9d9c04260 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -26,15 +26,6 @@ /// Yummy! species_cookie = /obj/item/food/nugget -// Prevents felinids from taking toxin damage from carpotoxin -/datum/species/human/felinid/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) - . = ..() - if(. & COMSIG_MOB_STOP_REAGENT_CHECK) - return - if(istype(chem, /datum/reagent/toxin/carpotoxin)) - var/datum/reagent/toxin/carpotoxin/fish = chem - fish.toxpwr = 0 - /datum/species/human/felinid/on_species_gain(mob/living/carbon/carbon_being, datum/species/old_species, pref_load, regenerate_icons) if(ishuman(carbon_being)) var/mob/living/carbon/human/target_human = carbon_being 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 7dbfab5011c..81749c6028a 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -15,14 +15,12 @@ inherent_traits = list( TRAIT_MUTANT_COLORS, TRAIT_TOXINLOVER, - TRAIT_NOBLOOD, ) mutanttongue = /obj/item/organ/tongue/jelly mutantlungs = /obj/item/organ/lungs/slime mutanteyes = /obj/item/organ/eyes/jelly mutantheart = null meat = /obj/item/food/meat/slab/human/mutant/slime - exotic_blood = /datum/reagent/toxin/slimejelly exotic_bloodtype = BLOOD_TYPE_TOX blood_deficiency_drain_rate = JELLY_REGEN_RATE + BLOOD_DEFICIENCY_MODIFIER coldmod = 6 // = 3x cold damage @@ -126,12 +124,13 @@ // They may not be roundstart but in the unlikely event they become one might as well not leave a glaring issue open. /datum/species/jelly/create_pref_blood_perks() var/list/to_add = list() + var/datum/blood_type/blood_type = get_blood_type(exotic_bloodtype) to_add += list(list( SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, SPECIES_PERK_ICON = "tint", SPECIES_PERK_NAME = "Jelly Blood", - SPECIES_PERK_DESC = "[plural_form] don't have blood, but instead have toxic [initial(exotic_blood.name)]! \ + SPECIES_PERK_DESC = "[plural_form] don't have blood, but instead have toxic [initial(blood_type.reagent_type.name)]! \ Jelly is extremely important, as losing it will cause you to lose limbs. Having low jelly will make medical treatment very difficult.", )) diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index da4c245a57a..9596946d929 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -49,13 +49,6 @@ . = ..() QDEL_NULL(mush) -/datum/species/mush/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) - . = ..() - if(. & COMSIG_MOB_STOP_REAGENT_CHECK) - return - if(chem.type == /datum/reagent/toxin/plantbgone/weedkiller) - affected.adjustToxLoss(3 * REM * seconds_per_tick) - /datum/species/mush/get_fixed_hair_color(mob/living/carbon/human/for_mob) return "#FF4B19" //cap color, spot color uses eye color diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 1bb39cce4f3..cc76f0716ec 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -16,7 +16,6 @@ heatmod = 1.5 payday_modifier = 1.0 meat = /obj/item/food/meat/slab/human/mutant/plant - exotic_blood = /datum/reagent/water exotic_bloodtype = BLOOD_TYPE_H2O changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/plant @@ -40,13 +39,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/pod, ) -/datum/species/pod/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) - . = ..() - if(. & COMSIG_MOB_STOP_REAGENT_CHECK) - return - if(chem.type == /datum/reagent/toxin/plantbgone) - affected.adjustToxLoss(3 * REM * seconds_per_tick) - /datum/species/pod/prepare_human_for_preview(mob/living/carbon/human/human) human.dna.features["mcolor"] = "#886600" human.dna.features["pod_hair"] = "Rose" diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm index da4a57cd375..bfb2379f38c 100644 --- a/code/modules/mob/living/carbon/human/species_types/snail.dm +++ b/code/modules/mob/living/carbon/human/species_types/snail.dm @@ -16,7 +16,7 @@ mutanteyes = /obj/item/organ/eyes/snail mutanttongue = /obj/item/organ/tongue/snail - exotic_blood = /datum/reagent/lube + mutantliver = /obj/item/organ/liver/snail exotic_bloodtype = BLOOD_TYPE_SNAIL bodypart_overrides = list( @@ -28,9 +28,6 @@ BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/snail ) - ///Multiplier for the speed we give them. Positive numbers make it move slower, negative numbers make it move faster. - var/snail_speed_mod = 1 // SKYRAT EDIT REMOVAL - Moved the movespeed to the shell. Original - var/snail_speed_mod = 6 - /datum/species/snail/prepare_human_for_preview(mob/living/carbon/human/human) human.dna.features["mcolor"] = COLOR_BEIGE human.update_body(is_creating = TRUE) @@ -77,28 +74,14 @@ )) return to_add -/datum/species/snail/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired) - . = ..() - if(. & COMSIG_MOB_STOP_REAGENT_CHECK) - return - if(istype(chem,/datum/reagent/consumable/salt)) - playsound(affected, SFX_SEAR, 30, TRUE) - affected.adjustFireLoss(2 * REM * seconds_per_tick) - affected.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) - return COMSIG_MOB_STOP_REAGENT_CHECK - /datum/species/snail/on_species_gain(mob/living/carbon/new_snailperson, datum/species/old_species, pref_load, regenerate_icons) . = ..() var/obj/item/storage/backpack/bag = new_snailperson.get_item_by_slot(ITEM_SLOT_BACK) if(!istype(bag, /obj/item/storage/backpack/snail)) new_snailperson.equip_to_slot_or_del(new /obj/item/storage/backpack/snail(new_snailperson), ITEM_SLOT_BACK) - new_snailperson.AddElement(/datum/element/lube_walking, require_resting = TRUE) - new_snailperson.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/snail, multiplicative_slowdown = snail_speed_mod) /datum/species/snail/on_species_loss(mob/living/carbon/former_snailperson, datum/species/new_species, pref_load) . = ..() - former_snailperson.remove_movespeed_modifier(/datum/movespeed_modifier/snail) - former_snailperson.RemoveElement(/datum/element/lube_walking, require_resting = TRUE) var/obj/item/storage/backpack/bag = former_snailperson.get_item_by_slot(ITEM_SLOT_BACK) if(istype(bag, /obj/item/storage/backpack/snail)) bag.emptyStorage() diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 99e869c1cf8..68dcc4ea89e 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -189,8 +189,12 @@ if(victim.stat == DEAD) to_chat(user, span_warning("You need a living victim!")) return FALSE - if(!victim.blood_volume || (victim.dna && (HAS_TRAIT(victim, TRAIT_NOBLOOD) || victim.dna.species.exotic_blood))) - to_chat(user, span_warning("[victim] doesn't have blood!")) + var/blood_name = LOWER_TEXT(user.get_bloodtype()?.get_blood_name()) + if(!victim.blood_volume || victim.get_blood_reagent() != user.get_blood_reagent()) + if (blood_name) + to_chat(user, span_warning("[victim] doesn't have [blood_name]!")) + else + to_chat(user, span_warning("[victim] doesn't have anything inside of them you could stomach!")) return FALSE COOLDOWN_START(licker_drinker, drain_cooldown, 3 SECONDS) if(victim.can_block_magic(MAGIC_RESISTANCE_HOLY, charge_cost = 0)) @@ -211,7 +215,7 @@ victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM) user.blood_volume = clamp(user.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM) if(!victim.blood_volume) - to_chat(user, span_notice("You finish off [victim]'s blood supply.")) + to_chat(user, span_notice("You finish off [victim]'s [blood_name] supply.")) return TRUE /obj/item/organ/heart/vampire diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 05fd015e5bc..4e5a43d130a 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -483,6 +483,42 @@ /mob/living/carbon/proc/handle_blood(seconds_per_tick, times_fired) return +/mob/living/carbon/reagent_tick(datum/reagent/chem, seconds_per_tick, times_fired) + . = ..() + if(. & COMSIG_MOB_STOP_REAGENT_TICK) + return + + var/datum/blood_type/blood_type = get_bloodtype() + if(!blood_type) + return + + if(chem.type == blood_type?.restoration_chem && blood_volume < BLOOD_VOLUME_NORMAL) + blood_volume += BLOOD_REGEN_FACTOR * seconds_per_tick + reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) + return COMSIG_MOB_STOP_REAGENT_TICK + +/mob/living/carbon/reagent_expose(datum/reagent/chem, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() + + if(. & COMPONENT_NO_EXPOSE_REAGENTS) + return + + if(!(methods & INJECT) && !((methods & INGEST) && HAS_TRAIT(src, TRAIT_DRINKS_BLOOD))) + return + + var/datum/blood_type/blood_type = get_bloodtype() + if(blood_type.reagent_type != chem.type) + return + + if(chem.data?["blood_type"]) + var/datum/blood_type/donor_type = chem.data["blood_type"] + if(!(donor_type.type_key() in blood_type.compatible_types)) + reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) + return COMPONENT_NO_EXPOSE_REAGENTS + + blood_volume = min(blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) + return COMPONENT_NO_EXPOSE_REAGENTS + /mob/living/carbon/proc/handle_bodyparts(seconds_per_tick, times_fired) for(var/obj/item/bodypart/limb as anything in bodyparts) . |= limb.on_life(seconds_per_tick, times_fired) @@ -518,7 +554,6 @@ if(organ?.owner) // This exist mostly because reagent metabolization can cause organ reshuffling organ.on_life(seconds_per_tick, times_fired) - /mob/living/carbon/handle_diseases(seconds_per_tick, times_fired) for(var/datum/disease/disease as anything in diseases) if(QDELETED(disease)) //Got cured/deleted while the loop was still going. diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 1e9b219c255..ebe2f875609 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -144,4 +144,13 @@ var/grav_strength = gravity - GRAVITY_DAMAGE_THRESHOLD adjustBruteLoss(min(GRAVITY_DAMAGE_SCALING * grav_strength, GRAVITY_DAMAGE_MAXIMUM) * seconds_per_tick) +/// Proc used for custom metabolization of reagents, if any +/mob/living/proc/reagent_tick(datum/reagent/chem, seconds_per_tick, times_fired) + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_MOB_REAGENT_TICK, chem, seconds_per_tick, times_fired) + +/// Proc used for custom reagent exposure effects, if any +/mob/living/proc/reagent_expose(datum/reagent/chem, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + return + #undef BODYTEMP_DIVISOR diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d2e08df22ed..ef62bc031f8 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1081,10 +1081,6 @@ /mob/living/proc/update_damage_overlays() return -/// Proc that only really gets called for humans, to handle bleeding overlays. -/mob/living/proc/update_wound_overlays() - return - /mob/living/Move(atom/newloc, direct, glide_size_override) if(lying_angle != 0) lying_angle_on_movement(direct) @@ -1096,7 +1092,7 @@ return var/old_direction = dir - var/turf/T = loc + var/turf/old_loc = loc if(pulling) update_pull_movespeed() @@ -1104,8 +1100,8 @@ . = ..() if(moving_diagonally != FIRST_DIAG_STEP && isliving(pulledby)) - var/mob/living/L = pulledby - L.set_pull_offsets(src, pulledby.grab_state) + var/mob/living/puller = pulledby + puller.set_pull_offsets(src, puller.grab_state) if(active_storage) var/storage_is_important_recurisve = (active_storage.parent in important_recursive_contents?[RECURSIVE_CONTENTS_ACTIVE_STORAGE]) @@ -1113,8 +1109,12 @@ if(!storage_is_important_recurisve && !can_reach_active_storage) active_storage.hide_contents(src) - if(body_position == LYING_DOWN && !buckled && prob(getBruteLoss()*200/maxHealth)) - makeTrail(newloc, T, old_direction) + if(!buckled && !moving_diagonally && loc != old_loc) + var/blood_flow = get_bleed_rate() + var/health_check = body_position == LYING_DOWN && prob(getBruteLoss() * 200 / maxHealth) + var/bleeding_check = blood_flow > 3 && prob(blood_flow * 16) + if(health_check || bleeding_check) + make_blood_trail(newloc, old_loc, old_direction, direct) ///Called by mob Move() when the lying_angle is different than zero, to better visually simulate crawling. /mob/living/proc/lying_angle_on_movement(direct) @@ -1126,85 +1126,6 @@ /mob/living/carbon/alien/adult/lying_angle_on_movement(direct) return -/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction) - if(!has_gravity() || !isturf(start) || !blood_volume) - return - - var/trail_type = getTrail() - var/trail_blood_type = get_trail_blood() - if(!trail_type || !trail_blood_type) - return - - var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) - if(blood_volume < max(BLOOD_VOLUME_NORMAL * (1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold - return - - var/bleed_amount = bleedDragAmount() - blood_volume = max(blood_volume - bleed_amount, 0) //that depends on our brute damage. - var/newdir = get_dir(target_turf, start) - if(newdir != direction) - newdir = newdir | direction - if(newdir == (NORTH|SOUTH)) - newdir = NORTH - else if(newdir == (EAST|WEST)) - newdir = EAST - - if((newdir in GLOB.cardinals) && (prob(50))) - newdir = REVERSE_DIR(get_dir(target_turf, start)) - - var/found_trail = FALSE - for(var/obj/effect/decal/cleanable/blood/trail_holder/trail in start) - if (trail.blood_state != trail_blood_type) - continue - - // Don't make double trails, even if they're of a different type - if(newdir in trail.existing_dirs) - found_trail = TRUE - break - - trail.existing_dirs += newdir - trail.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) - trail.add_mob_blood(src) - trail.bloodiness = min(trail.bloodiness + bleed_amount, BLOOD_POOL_MAX) - found_trail = TRUE - break - - if (found_trail) - return - - var/obj/effect/decal/cleanable/blood/trail_holder/trail = new(start, get_static_viruses()) - trail.blood_state = trail_blood_type - trail.existing_dirs += newdir - trail.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) - trail.add_mob_blood(src) - trail.bloodiness = min(bleed_amount, BLOOD_POOL_MAX) - -/mob/living/proc/get_trail_blood() - return BLOOD_STATE_HUMAN - -/mob/living/carbon/human/makeTrail(turf/T) - if(HAS_TRAIT(src, TRAIT_NOBLOOD) || !is_bleeding() || dna.blood_type.no_bleed_overlays) - return - ..() - -///Returns how much blood we're losing from being dragged a tile, from [/mob/living/proc/makeTrail] -/mob/living/proc/bleedDragAmount() - var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) - return max(1, brute_ratio * 2) - -/mob/living/carbon/bleedDragAmount() - var/bleed_amount = 0 - for(var/i in all_wounds) - var/datum/wound/iter_wound = i - bleed_amount += iter_wound.drag_bleed_amount() - return bleed_amount - -/mob/living/proc/getTrail() - if(getBruteLoss() < 300) - return pick("ltrails_1", "ltrails_2") - else - return pick("trails_1", "trails_2") - /// Print a message about an annoying sensation you are feeling. Returns TRUE if successful. /mob/living/proc/itch(obj/item/bodypart/target_part = null, damage = 0.5, can_scratch = TRUE, silent = FALSE) if ((mob_biotypes & (MOB_ROBOTIC | MOB_SPIRIT))) @@ -3143,8 +3064,3 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(HAS_TRAIT(src, TRAIT_ANALGESIA) && !force) return INVOKE_ASYNC(src, PROC_REF(emote), "scream") - -/// Setter for changing a mob's blood type -/mob/living/proc/set_blood_type(datum/blood_type/new_blood_type, update_cached_blood_dna_info) - SHOULD_CALL_PARENT(TRUE) - SEND_SIGNAL(src, COMSIG_LIVING_CHANGED_BLOOD_TYPE, new_blood_type, update_cached_blood_dna_info) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index cd27950cec3..95696b88df4 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -276,9 +276,6 @@ return log_combat(thrown_by, src, "threw and hit", thrown_item) return log_combat(thrown_item, src, "hit ") -/mob/living/proc/create_splatter(splatter_dir) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(get_turf(src), splatter_dir) - ///The core of catching thrown items, which non-carbons cannot without the help of items or abilities yet, as they've no throw mode. /mob/living/proc/try_catch_item(obj/item/item, skip_throw_mode_check = FALSE, try_offhand = FALSE) if(!can_catch_item(skip_throw_mode_check, try_offhand) || !isitem(item) || HAS_TRAIT(item, TRAIT_UNCATCHABLE) || !isturf(item.loc)) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 928bb449fe4..7f7c412bfea 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -55,6 +55,8 @@ update_icons() . = ..() + LoadComponent(/datum/component/bloodysoles/bot) + //If this body is meant to be a borg controlled by the AI player if(shell) var/obj/item/borg/upgrade/ai/board = new(src) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index d310301b922..6d4adbb688b 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -162,8 +162,9 @@ /mob/living/simple_animal/bot/Initialize(mapload) . = ..() - add_traits(list(TRAIT_SILICON_ACCESS, TRAIT_REAGENT_SCANNER, TRAIT_UNOBSERVANT), INNATE_TRAIT) GLOB.bots_list += src + add_traits(list(TRAIT_SILICON_ACCESS, TRAIT_REAGENT_SCANNER, TRAIT_UNOBSERVANT), INNATE_TRAIT) + LoadComponent(/datum/component/bloodysoles/bot) path_hud = new /datum/atom_hud/data/bot_path/private() for(var/hud in path_hud.hud_icons) // You get to see your own path @@ -348,7 +349,7 @@ /mob/living/simple_animal/bot/adjustHealth(amount, updating_health = TRUE, forced = FALSE) if(amount > 0 && prob(10)) - new /obj/effect/decal/cleanable/oil(loc) + new /obj/effect/decal/cleanable/blood/oil(loc) return ..() /mob/living/simple_animal/bot/updatehealth() diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 1bd4a0f51bd..e6d6aedfc4d 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -757,7 +757,7 @@ cell.forceMove(Tsec) cell = null - new /obj/effect/decal/cleanable/oil(loc) + new /obj/effect/decal/cleanable/blood/oil(loc) return ..() /mob/living/simple_animal/bot/mulebot/remove_air(amount) //To prevent riders suffocating diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index b07bf8efe32..bd4b7518e63 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -550,7 +550,7 @@ new /obj/item/assembly/prox_sensor(Tsec) drop_part(baton_type, Tsec) - new /obj/effect/decal/cleanable/oil(loc) + new /obj/effect/decal/cleanable/blood/oil(loc) return ..() /mob/living/simple_animal/bot/secbot/attack_alien(mob/living/carbon/alien/user, list/modifiers) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 80e5e1b7458..9c24eb728dc 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1607,11 +1607,6 @@ stat = new_stat SEND_SIGNAL(src, COMSIG_MOB_STATCHANGE, new_stat, .) -/// Proc used for custom metabolization of reagents, if any -/mob/proc/reagent_check(datum/reagent/chem, seconds_per_tick, times_fired) - SHOULD_CALL_PARENT(TRUE) - return SEND_SIGNAL(src, COMSIG_MOB_REAGENT_CHECK, chem, seconds_per_tick, times_fired) - /mob/vv_edit_var(var_name, var_value) switch(var_name) if(NAMEOF(src, focus)) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 2957d9a969c..4ff13573b5c 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -600,7 +600,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks()) /obj/machinery/photocopier/atom_break(damage_flag) . = ..() if(. && toner_cartridge.charges) - new /obj/effect/decal/cleanable/oil(get_turf(src)) + new /obj/effect/decal/cleanable/blood/oil(get_turf(src)) toner_cartridge.charges = 0 /obj/machinery/photocopier/mouse_drop_receive(mob/target, mob/user, params) diff --git a/code/modules/reagents/chemistry/holder/holder.dm b/code/modules/reagents/chemistry/holder/holder.dm index 11483810442..ef2a27feb1a 100644 --- a/code/modules/reagents/chemistry/holder/holder.dm +++ b/code/modules/reagents/chemistry/holder/holder.dm @@ -81,6 +81,7 @@ * * added_ph - override to force a pH when added * * override_base_ph - ingore the present pH of the reagent, and instead use the default (i.e. if buffers/reactions alter it) * * ignore splitting - Don't call the process that handles reagent spliting in a mob (impure/inverse) - generally leave this false unless you care about REAGENTS_DONOTSPLIT flags (see reagent defines) + * * creation_callback - Callback to invoke when the reagent is created */ /datum/reagents/proc/add_reagent( datum/reagent/reagent_type, @@ -88,10 +89,11 @@ list/data = null, reagtemp = DEFAULT_REAGENT_TEMPERATURE, added_purity = null, - added_ph, + added_ph = null, no_react = FALSE, override_base_ph = FALSE, - ignore_splitting = FALSE + ignore_splitting = FALSE, + datum/callback/creation_callback = null, ) if(!ispath(reagent_type)) stack_trace("invalid reagent passed to add reagent [reagent_type]") @@ -173,6 +175,8 @@ new_reagent.purity = added_purity new_reagent.creation_purity = added_purity new_reagent.ph = added_ph + if (creation_callback) + creation_callback.Invoke(new_reagent) new_reagent.on_new(data) if(isliving(my_atom)) @@ -488,7 +492,7 @@ update_total() target_holder.update_total() continue - transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //we only handle reaction after every reagent has been transferred. + transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT, creation_callback = CALLBACK(src, PROC_REF(on_transfer_creation), reagent, target_holder)) //we only handle reaction after every reagent has been transferred. if(!transfered_amount) continue if(methods) @@ -530,6 +534,9 @@ return total_transfered_amount +/datum/reagents/proc/on_transfer_creation(datum/reagent/reagent, datum/reagents/target_holder, datum/reagent/new_reagent) + SEND_SIGNAL(reagent, COMSIG_REAGENT_ON_TRANSFER, target_holder, new_reagent) + /** * Copies the reagents to the target object * Arguments @@ -710,8 +717,10 @@ // that could possibly eat up a lot of memory needlessly // if most data lists are read-only. if(trans_data["viruses"]) - var/list/v = trans_data["viruses"] - trans_data["viruses"] = v.Copy() + var/list/viruses = list() + for (var/datum/disease/disease as anything in trans_data["viruses"]) + viruses += disease.Copy() + trans_data["viruses"] = viruses return trans_data diff --git a/code/modules/reagents/chemistry/holder/mob_life.dm b/code/modules/reagents/chemistry/holder/mob_life.dm index 7975e48f91e..b4705ac3c27 100644 --- a/code/modules/reagents/chemistry/holder/mob_life.dm +++ b/code/modules/reagents/chemistry/holder/mob_life.dm @@ -86,7 +86,6 @@ * * liverless - Stops reagents that aren't set as [/datum/reagent/var/self_consuming] from metabolizing */ /datum/reagents/proc/metabolize_reagent(mob/living/carbon/owner, datum/reagent/reagent, seconds_per_tick, times_fired, can_overdose = FALSE, liverless = FALSE, dead = FALSE) - var/need_mob_update = FALSE if(QDELETED(reagent.holder)) return FALSE @@ -101,31 +100,40 @@ return //SKYRAT EDIT ADDITION END - if(owner && reagent && (!dead || (reagent.chemical_flags & REAGENT_DEAD_PROCESS))) - if(owner.reagent_check(reagent, seconds_per_tick, times_fired)) - return - if(liverless && !reagent.self_consuming) //need to be metabolized - return - if(!reagent.metabolizing) - reagent.metabolizing = TRUE - reagent.on_mob_metabolize(owner) - if(can_overdose && !HAS_TRAIT(owner, TRAIT_OVERDOSEIMMUNE)) - if(reagent.overdose_threshold) - if(reagent.volume >= reagent.overdose_threshold && !reagent.overdosed) - reagent.overdosed = TRUE - need_mob_update += reagent.overdose_start(owner) - owner.log_message("has started overdosing on [reagent.name] at [reagent.volume] units.", LOG_GAME) - for(var/addiction in reagent.addiction_types) - owner.mind?.add_addiction_points(addiction, reagent.addiction_types[addiction] * REAGENTS_METABOLISM) + if(!owner || !reagent || (dead && !(reagent.chemical_flags & REAGENT_DEAD_PROCESS))) + return FALSE - if(reagent.overdosed) - need_mob_update += reagent.overdose_process(owner, seconds_per_tick, times_fired) - reagent.current_cycle++ - need_mob_update += reagent.on_mob_life(owner, seconds_per_tick, times_fired) - if(dead && !QDELETED(owner) && !QDELETED(reagent)) - need_mob_update += reagent.on_mob_dead(owner, seconds_per_tick) - if(!QDELETED(owner) && !QDELETED(reagent)) - reagent.metabolize_reagent(owner, seconds_per_tick, times_fired) + if(owner.reagent_tick(reagent, seconds_per_tick, times_fired)) + return FALSE + + if(liverless && !reagent.self_consuming) //need to be metabolized + return FALSE + + var/need_mob_update = FALSE + if(!reagent.metabolizing) + reagent.metabolizing = TRUE + reagent.on_mob_metabolize(owner) + + if(can_overdose && !HAS_TRAIT(owner, TRAIT_OVERDOSEIMMUNE)) + if(reagent.overdose_threshold && reagent.volume >= reagent.overdose_threshold && !reagent.overdosed) + reagent.overdosed = TRUE + need_mob_update += reagent.overdose_start(owner) + owner.log_message("has started overdosing on [reagent.name] at [reagent.volume] units.", LOG_GAME) + + for(var/addiction in reagent.addiction_types) + owner.mind?.add_addiction_points(addiction, reagent.addiction_types[addiction] * REAGENTS_METABOLISM) + + if(reagent.overdosed) + need_mob_update += reagent.overdose_process(owner, seconds_per_tick, times_fired) + + reagent.current_cycle++ + need_mob_update += reagent.on_mob_life(owner, seconds_per_tick, times_fired) + + if(dead && !QDELETED(owner) && !QDELETED(reagent)) + need_mob_update += reagent.on_mob_dead(owner, seconds_per_tick) + + if(!QDELETED(owner) && !QDELETED(reagent)) + reagent.metabolize_reagent(owner, seconds_per_tick, times_fired) return need_mob_update diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index 54ebe3871ac..124dc5cfc86 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -141,7 +141,7 @@ "volume" = round(beaker.reagents?.total_volume, 0.01) || 0, "capacity" = beaker.volume, ) - var/datum/reagent/blood/blood = locate() in beaker.reagents.reagent_list + var/datum/reagent/blood = get_blood_reagent() if(!blood) data["has_blood"] = FALSE return data @@ -199,11 +199,11 @@ if(!beaker) return cures - var/datum/reagent/blood/blood = beaker.reagents.has_reagent(/datum/reagent/blood) + var/datum/reagent/blood = get_blood_reagent() if(!blood) return cures - var/list/viruses = blood.get_diseases() + var/list/viruses = blood.data["viruses"] if(!length(viruses)) return cures @@ -251,6 +251,12 @@ addtimer(CALLBACK(src, PROC_REF(reset_replicator_cooldown)), 5 SECONDS) return TRUE +/// Tries to locate a reagent with valid blood_type data +/obj/machinery/computer/pandemic/proc/get_blood_reagent() + for (var/datum/reagent/reagent as anything in beaker?.reagents?.reagent_list) + if (reagent.data?["blood_type"]) + return reagent + /** * Creates a vaccine bottle for the specified disease. * @@ -334,9 +340,9 @@ * * @returns {list} - A list of virus info present in the sample. */ -/obj/machinery/computer/pandemic/proc/get_viruses_data(datum/reagent/blood/blood) +/obj/machinery/computer/pandemic/proc/get_viruses_data(datum/reagent/blood) var/list/data = list() - var/list/viruses = blood.get_diseases() + var/list/viruses = blood.data?["viruses"] var/index = 1 for(var/datum/disease/disease as anything in viruses) if(!istype(disease) || disease.visibility_flags & HIDDEN_PANDEMIC) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index c1cb20f0d9c..448c79dd75c 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -117,18 +117,22 @@ . |= SEND_SIGNAL(exposed_atom, COMSIG_ATOM_EXPOSE_REAGENT, src, reac_volume, methods) /// Applies this reagent to a [/mob/living] -/datum/reagent/proc/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) +/datum/reagent/proc/expose_mob(mob/living/exposed_mob, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) SHOULD_CALL_PARENT(TRUE) - . = SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_MOB, exposed_mob, methods, reac_volume, show_message, touch_protection) + if(SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_MOB, exposed_mob, methods, reac_volume, show_message, touch_protection) & COMPONENT_NO_EXPOSE_REAGENTS) + return if(isnull(exposed_mob.reagents)) // lots of simple mobs do not have a reagents holder return + if(exposed_mob.reagent_expose(src, methods, reac_volume, show_message, touch_protection) & COMPONENT_NO_EXPOSE_REAGENTS) + return + if(penetrates_skin & methods) // models things like vapors which penetrate the skin var/amount = round(reac_volume * clamp((1 - touch_protection), 0, 1), 0.1) if(amount >= 0.5) - exposed_mob.reagents.add_reagent(type, amount, added_purity = purity) + exposed_mob.reagents.add_reagent(type, amount, data, holder.chem_temp, purity) /// Applies this reagent to an [/obj] /datum/reagent/proc/expose_obj(obj/exposed_obj, reac_volume, methods=TOUCH, show_message=TRUE) @@ -232,8 +236,9 @@ Primarily used in reagents/reaction_agents src.data = data /// Called when two reagents of the same are mixing. -/datum/reagent/proc/on_merge(data, amount) - return +/datum/reagent/proc/on_merge(list/mix_data, amount) + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_REAGENT_ON_MERGE, mix_data, amount) /// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects. Returning UPDATE_MOB_HEALTH will cause updatehealth() to be called on the holder mob by /datum/reagents/proc/metabolize. /datum/reagent/proc/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index d8096c8cd50..42330587a4e 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -392,10 +392,10 @@ glass_price = DRINK_PRICE_STOCK default_container = /obj/item/reagent_containers/cup/glass/bottle/wine -/datum/reagent/consumable/ethanol/wine/on_merge(data) +/datum/reagent/consumable/ethanol/wine/on_merge(list/mix_data, amount) . = ..() - if(src.data && data && data["vintage"] != src.data["vintage"]) - src.data["vintage"] = "mixed wine" + if(data && mix_data && data["vintage"] != mix_data["vintage"]) + data["vintage"] = "mixed wine" /datum/reagent/consumable/ethanol/wine/get_taste_description(mob/living/taster) if(HAS_TRAIT(taster,TRAIT_WINE_TASTER)) @@ -1970,25 +1970,25 @@ color = data["color"] generate_data_info(data) -/datum/reagent/consumable/ethanol/fruit_wine/on_merge(list/data, amount) - ..() +/datum/reagent/consumable/ethanol/fruit_wine/on_merge(list/mix_data, amount) + . = ..() var/diff = (amount/volume) if(diff < 1) - color = BlendRGB(color, data["color"], diff/2) //The percentage difference over two, so that they take average if equal. + color = BlendRGB(color, mix_data["color"], diff/2) //The percentage difference over two, so that they take average if equal. else - color = BlendRGB(color, data["color"], (1/diff)/2) //Adjust so it's always blending properly. + color = BlendRGB(color, mix_data["color"], (1/diff)/2) //Adjust so it's always blending properly. var/oldvolume = volume-amount - var/list/cachednames = data["names"] + var/list/cachednames = mix_data["names"] for(var/name in names | cachednames) names[name] = ((names[name] * oldvolume) + (cachednames[name] * amount)) / volume - var/list/cachedtastes = data["tastes"] + var/list/cachedtastes = mix_data["tastes"] for(var/taste in tastes | cachedtastes) tastes[taste] = ((tastes[taste] * oldvolume) + (cachedtastes[taste] * amount)) / volume boozepwr *= oldvolume - var/newzepwr = data["boozepwr"] * amount + var/newzepwr = mix_data["boozepwr"] * amount boozepwr += newzepwr boozepwr /= volume //Blending boozepwr to volume. generate_data_info(data) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index b4f538842c9..5518722475f 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -152,7 +152,7 @@ color = BlendRGB(initial(color), "#FAFAFA", effective_impurity) //we need to update the color whenever purity gets changed -/datum/reagent/drug/methamphetamine/on_merge(data, amount) +/datum/reagent/drug/methamphetamine/on_merge(list/mix_data, amount) . = ..() var/effective_impurity = min(1, (1 - creation_purity)/0.5) color = BlendRGB(initial(color), "#FAFAFA", effective_impurity) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 8083fa16d20..381eadb26d1 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -99,9 +99,9 @@ data = counterlist_normalise(supplied_data) -/datum/reagent/consumable/nutriment/on_merge(list/newdata, newvolume) +/datum/reagent/consumable/nutriment/on_merge(list/mix_data, amount) . = ..() - if(!islist(newdata) || !newdata.len) + if(!islist(mix_data) || !mix_data.len) return // data for nutriment is one or more (flavour -> ratio) @@ -113,8 +113,8 @@ counterlist_scale(taste_amounts, volume) - var/list/other_taste_amounts = newdata.Copy() - counterlist_scale(other_taste_amounts, newvolume) + var/list/other_taste_amounts = mix_data.Copy() + counterlist_scale(other_taste_amounts, amount) counterlist_combine(taste_amounts, other_taste_amounts) @@ -176,7 +176,7 @@ exposed_obj.visible_message(span_warning("[exposed_obj] rapidly fries as it's splashed with hot oil! Somehow.")) exposed_obj.AddElement(/datum/element/fried_item, volume SECONDS) - exposed_obj.reagents.add_reagent(src.type, reac_volume, reagtemp = holder.chem_temp) + exposed_obj.reagents.add_reagent(type, reac_volume, data, holder.chem_temp) /datum/reagent/consumable/nutriment/fat/expose_mob(mob/living/exposed_mob, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 7bdfd00857e..10ed8b31706 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -299,7 +299,14 @@ /datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() - var/need_mob_update + var/need_mob_update = FALSE + if(SPT_PROB(18, seconds_per_tick)) + need_mob_update = affected_mob.adjustBruteLoss(-0.5 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_biotype) + need_mob_update += affected_mob.adjustFireLoss(-0.5 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_biotype) + var/datum/blood_type/blood_type = affected_mob.get_bloodtype() + // Only suppliments base blood types + if(blood_type?.restoration_chem != /datum/reagent/iron) + return need_mob_update ? UPDATE_MOB_HEALTH : null if(last_added) affected_mob.blood_volume -= last_added last_added = 0 @@ -308,9 +315,6 @@ var/new_blood_level = min(affected_mob.blood_volume + amount_to_add, maximum_reachable) last_added = new_blood_level - affected_mob.blood_volume affected_mob.blood_volume = new_blood_level + (extra_regen * REM * seconds_per_tick) - if(SPT_PROB(18, seconds_per_tick)) - need_mob_update = affected_mob.adjustBruteLoss(-0.5 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_biotype) - need_mob_update += affected_mob.adjustFireLoss(-0.5 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_biotype) if(need_mob_update) return UPDATE_MOB_HEALTH diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 73f0690bb97..0133d872619 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1,6 +1,6 @@ /datum/reagent/blood - data = list("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,"quirks"=null, "monkey_origins" = FALSE) // SKYRAT EDIT - Rebalancing blood for Hemophages - ORIGINAL: data = list("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,"quirks"=null) name = "Blood" + description = "Blood cells suspended in plasma, the most abundant of which being the hemoglobin-containing red blood cells." color = "#C80000" // rgb: 200, 0, 0 metabolization_rate = 12.5 * REAGENTS_METABOLISM //fast rate so it disappears fast. taste_description = "iron" @@ -18,158 +18,24 @@ name = "glass of tomato juice" desc = "Are you sure this is tomato juice?" - // FEED ME +// FEED ME /datum/reagent/blood/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user) mytray.adjust_pestlevel(rand(2, 3)) -/datum/reagent/blood/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) - . = ..() - if(data && data["viruses"]) - for(var/thing in data["viruses"]) - var/datum/disease/strain = thing - - if((strain.spread_flags & DISEASE_SPREAD_SPECIAL) || (strain.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) - continue - - if(methods & INGEST) - if(!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_STOMACH)) - continue - - exposed_mob.ForceContractDisease(strain) - else if(methods & (INJECT|PATCH)) - if(!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_HEART)) - continue - - exposed_mob.ForceContractDisease(strain) - else if((methods & (VAPOR|INHALE)) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) - if(!strain.has_required_infectious_organ(exposed_mob, ORGAN_SLOT_LUNGS)) - continue - - exposed_mob.ContactContractDisease(strain) - else if((methods & TOUCH) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) - exposed_mob.ContactContractDisease(strain) - - if(data && data["resistances"]) - if(methods & (INGEST|INJECT|INHALE)) //have to inject, inhale or ingest it. no curefoam/cheap curesprays - for(var/stuff in exposed_mob.diseases) - var/datum/disease/infection = stuff - if(infection.GetDiseaseID() in data["resistances"]) - if(!infection.bypasses_immunity) - infection.cure(add_resistance = FALSE) - - if(iscarbon(exposed_mob)) - var/mob/living/carbon/exposed_carbon = exposed_mob - var/datum/blood_type/carbon_blood_type = exposed_carbon.dna.blood_type - if(carbon_blood_type.reagent_type == type && ((methods & INJECT) || ((methods & INGEST) && HAS_TRAIT(exposed_carbon, TRAIT_DRINKS_BLOOD)))) - var/datum/blood_type/recipient_blood_type = exposed_carbon.dna.blood_type - var/datum/blood_type/donor_blood_type = data["blood_type"] - if(!(donor_blood_type.type_key() in recipient_blood_type.compatible_types)) - exposed_carbon.reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) - else - /* SKYRAT EDIT - Rebalancing blood for Hemophages - ORIGINAL: - exposed_carbon.blood_volume = min(exposed_carbon.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) - */ // ORIGINAL END - SKYRAT EDIT: - // We do a max() here so that being injected with monkey blood when you're past 560u doesn't reset you back to 560 - var/max_blood_volume = data["monkey_origins"] ? max(exposed_carbon.blood_volume, BLOOD_VOLUME_NORMAL) : BLOOD_VOLUME_MAXIMUM - - exposed_carbon.blood_volume = min(exposed_carbon.blood_volume + round(reac_volume, 0.1), max_blood_volume) - // SKYRAT EDIT END - - exposed_carbon.reagents.remove_reagent(type, reac_volume) // Because we don't want blood to just lie around in the patient's blood, makes no sense. - - // covers them and their worn equipment in blood - if((methods & (TOUCH|VAPOR)) && reac_volume > 3) - if(data["blood_DNA"] && data["blood_type"]) - exposed_carbon.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - else - exposed_carbon.add_blood_DNA(list("Non-human DNA" = random_human_blood_type())) - /datum/reagent/blood/on_new(list/data) . = ..() - if(!istype(data)) + // If we were artificially created without blood data, we still want to have the blood_reagent element for exposure effects + if(!istype(data) || !data["blood_type"]) + AddElement(/datum/element/blood_reagent, null, get_blood_type(BLOOD_TYPE_UNIVERSAL)) return - SetViruses(src, data) + var/datum/blood_type/blood_type = data["blood_type"] - if(!blood_type) + if(!istype(blood_type)) return + var/blood_color = blood_type.get_color() - if(blood_color != BLOOD_COLOR_RED) // If the blood is default red, just use the darker red color for the reagent. - color = blood_color - -/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. - if(data["viruses"] || mix_data["viruses"]) - - var/list/mix1 = data["viruses"] - var/list/mix2 = mix_data["viruses"] - - // Stop issues with the list changing during mixing. - var/list/to_mix = list() - - for(var/datum/disease/advance/AD in mix1) - to_mix += AD - for(var/datum/disease/advance/AD in mix2) - to_mix += AD - - var/datum/disease/advance/AD = Advance_Mix(to_mix) - if(AD) - var/list/preserve = list(AD) - for(var/D in data["viruses"]) - if(!istype(D, /datum/disease/advance)) - preserve += D - data["viruses"] = preserve - return 1 - -/datum/reagent/blood/proc/get_diseases() - . = list() - if(data && data["viruses"]) - for(var/thing in data["viruses"]) - var/datum/disease/D = thing - . += D - -/datum/reagent/blood/expose_turf(turf/exposed_turf, reac_volume)//splash the blood all over the place - . = ..() - if(!istype(exposed_turf)) - return - if(reac_volume < 3) - return - - var/obj/effect/decal/cleanable/blood/bloodsplatter = locate() in exposed_turf //find some blood here - if(!bloodsplatter) - bloodsplatter = new(exposed_turf, data["viruses"]) - if(LAZYLEN(data["viruses"])) - var/list/viruses_to_add = list() - for(var/datum/disease/virus in data["viruses"]) - if(virus.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS) - viruses_to_add += virus - if(LAZYLEN(viruses_to_add)) - bloodsplatter.AddComponent(/datum/component/infective, viruses_to_add) - if(data["blood_DNA"]) - bloodsplatter.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - -/datum/reagent/blood/expose_obj(obj/exposed_obj, reac_volume, methods=TOUCH, show_message=TRUE) - . = ..() - if(!istype(exposed_obj)) - return - if(reac_volume < 3) - return - - if(!(methods & (VAPOR|TOUCH))) - return - - if(LAZYLEN(data["viruses"])) - var/list/viruses_to_add = list() - for(var/datum/disease/virus in data["viruses"]) - if(virus.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS) - viruses_to_add += virus - if(length(viruses_to_add)) - exposed_obj.AddComponent(/datum/component/infective, viruses_to_add) - if(data["blood_DNA"] && data["blood_type"]) - exposed_obj.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - else - exposed_obj.add_blood_DNA(list("Non-human DNA" = random_human_blood_type())) + if(blood_color == BLOOD_COLOR_RED) // If the blood is default red, just use the darker red color for the reagent. + color = initial(color) /datum/reagent/blood/get_taste_description(mob/living/taster) if(isnull(taster)) @@ -219,9 +85,10 @@ infection.cure(add_resistance = TRUE) LAZYOR(exposed_mob.disease_resistances, data) -/datum/reagent/vaccine/on_merge(list/data) - if(istype(data)) - src.data |= data.Copy() +/datum/reagent/vaccine/on_merge(list/mix_data, amount) + . = ..() + if(mix_data) + data |= mix_data /datum/reagent/vaccine/fungal_tb name = "Vaccine (Fungal Tuberculosis)" @@ -1949,7 +1816,7 @@ burning_volume = 0.05 //but has a lot of hydrocarbons chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = null - default_container = /obj/effect/decal/cleanable/oil + default_container = /obj/effect/decal/cleanable/blood/oil /datum/reagent/stable_plasma name = "Stable Plasma" diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 1ccbc37a507..7c2d7d7fd77 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -214,7 +214,7 @@ /datum/reagent/toxin/slimejelly name = "Slime Jelly" description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL." - color = "#801E28" // rgb: 128, 30, 40 + color = "#a6959d" toxpwr = 0 taste_description = "slime" taste_mult = 1.3 @@ -241,6 +241,11 @@ ph = 12 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED +/datum/reagent/toxin/carpotoxin/on_mob_add(mob/living/affected_mob, amount) + . = ..() + if (HAS_TRAIT(affected_mob, TRAIT_CARPOTOXIN_IMMUNE)) + toxpwr = 0 + /datum/reagent/toxin/zombiepowder name = "Zombie Powder" description = "A strong neurotoxin that puts the subject into a death-like state." diff --git a/code/modules/reagents/reagent_containers/misc.dm b/code/modules/reagents/reagent_containers/misc.dm index f046100dc15..8d54761a211 100644 --- a/code/modules/reagents/reagent_containers/misc.dm +++ b/code/modules/reagents/reagent_containers/misc.dm @@ -259,8 +259,8 @@ if(istype(what, /obj/item/rag)) var/obj/item/rag/friend_rag = what return friend_rag.blood_level - if(istype(what, /obj/effect/decal/cleanable)) - var/obj/effect/decal/cleanable/mess = what + if(istype(what, /obj/effect/decal/cleanable/blood)) + var/obj/effect/decal/cleanable/blood/mess = what return round(mess.bloodiness / 20, 1) return 1 @@ -284,12 +284,14 @@ /obj/item/rag/update_appearance(updates) . = ..() - // v = green and blue color components (reduced as it gets dirtier) + // Gets closer to the mixed blood color as we get dirtier + var/blood_color = get_blood_dna_color() || COLOR_RED + var/list/color_breakdown = rgb2num(blood_color) var/v = max(1 - (0.1 * blood_level), 0) var/list/colormatrix = list( - 1, 0, 0, 0, - 0, v, 0, 0, - 0, 0, v, 0, + color_breakdown[1] / 255 + v * (1 - color_breakdown[1] / 255), 0, 0, 0, + 0, color_breakdown[2] / 255 + v * (1 - color_breakdown[2] / 255), 0, 0, + 0, 0, color_breakdown[3] / 255 + v * (1 - color_breakdown[3] / 255), 0, 0, 0, 0, 1, ) diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm index 08616429dca..72ed3c6b67c 100644 --- a/code/modules/religion/religion_sects.dm +++ b/code/modules/religion/religion_sects.dm @@ -386,18 +386,15 @@ if(!HAS_TRAIT(chaplain, TRAIT_NOBLOOD)) if(target.blood_volume < BLOOD_VOLUME_SAFE) - var/datum/blood_type/target_blood_data = target.dna.blood_type - var/datum/blood_type/chaplain_blood_data = chaplain.dna.blood_type var/transferred_blood_amount = min(chaplain.blood_volume, BLOOD_VOLUME_SAFE - target.blood_volume) - if(transferred_blood_amount && (chaplain_blood_data.type_key() in target_blood_data.compatible_types)) - transferred = TRUE - chaplain.transfer_blood_to(target, transferred_blood_amount, forced = TRUE) - if(target.blood_volume > BLOOD_VOLUME_EXCESS) - target.transfer_blood_to(chaplain, target.blood_volume - BLOOD_VOLUME_EXCESS, forced = TRUE) + if(transferred_blood_amount && target.get_blood_compatibility(chaplain)) + transferred = chaplain.transfer_blood_to(target, transferred_blood_amount, forced = TRUE) + else if(target.blood_volume > BLOOD_VOLUME_EXCESS) + transferred = target.transfer_blood_to(chaplain, target.blood_volume - BLOOD_VOLUME_EXCESS, forced = TRUE) target.update_damage_overlays() chaplain.update_damage_overlays() - if(transferred) + if(!transferred) to_chat(chaplain, span_warning("They hold no burden!")) return BLESSING_IGNORED diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index ff4f096d091..40dc0fd9b83 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -449,7 +449,7 @@ if(SLIME_ACTIVATE_MINOR) to_chat(user, span_warning("You vomit slippery oil.")) playsound(user, 'sound/effects/splat.ogg', 50, TRUE) - new /obj/effect/decal/cleanable/oil/slippery(get_turf(user)) + new /obj/effect/decal/cleanable/blood/oil/slippery(get_turf(user)) return 450 if(SLIME_ACTIVATE_MAJOR) diff --git a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm index 56fcc898767..3b0f9b4633c 100644 --- a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm +++ b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm @@ -145,8 +145,8 @@ playsound(landing_turf, 'sound/effects/magic/exit_blood.ogg', 50, TRUE, -1) // Make the mob have the color of the blood pool it came out of - var/obj/effect/decal/cleanable/came_from = locate() in landing_turf - var/new_color = came_from?.get_blood_color() + var/obj/effect/decal/cleanable/blood/came_from = locate() in landing_turf + var/new_color = came_from?.color if(!new_color) return diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 02dfd31bf33..47f9dd3fd95 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -249,7 +249,7 @@ if(!IS_ORGANIC_LIMB(src)) grind_results = null else - blood_dna_info = list("UNKNOWN DNA" = get_blood_type(BLOOD_TYPE_O_PLUS)) + blood_dna_info = list("Unknown DNA" = get_blood_type(BLOOD_TYPE_O_PLUS)) name = "[limb_id] [parse_zone(body_zone)]" update_icon_dropped() @@ -614,7 +614,7 @@ update_disabled() if(updating_health) owner.updatehealth() - return update_bodypart_damage_state() || . + return update_bodypart_damage_state() /// Returns a bitflag using ANATOMY_EXTERIOR or ANATOMY_INTERIOR. Used to determine if we as a whole have a interior or exterior biostate, or both. /obj/item/bodypart/proc/get_bio_state_status() @@ -970,7 +970,7 @@ if(IS_ORGANIC_LIMB(src)) // Try to add a cached blood type data, we must do it in here because for some reason DNA gets initialized AFTER the mob's limbs are created. // Should be fine as this gets called before all the important stuff happens - if(!(bodypart_flags & ORGAN_VIRGIN) && owner?.dna?.blood_type) + if(bodypart_flags & ORGAN_VIRGIN) blood_dna_info = owner.get_blood_dna_list() // need to remove the synethic blood DNA that is initialized // wash also adds the blood dna again @@ -1114,7 +1114,7 @@ if(brutestate) // divided into two overlays: one that gets colored and one that doesn't. var/image/brute_blood_overlay = image('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0", -DAMAGE_LAYER) - brute_blood_overlay.color = get_blood_dna_color(update_on ? update_on.get_blood_dna_list() : blood_dna_info) // living mobs can just get it fresh, dropped limbs use blood_dna_info + brute_blood_overlay.color = get_color_from_blood_list(update_on ? update_on.get_blood_dna_list() : blood_dna_info) // living mobs can just get it fresh, dropped limbs use blood_dna_info var/mutable_appearance/brute_damage_overlay = mutable_appearance('icons/mob/effects/dam_mob.dmi', "[dmg_overlay_type]_[body_zone]_[brutestate]0_overlay", -DAMAGE_LAYER, appearance_flags = RESET_COLOR) if(brute_damage_overlay) brute_blood_overlay.overlays += brute_damage_overlay @@ -1436,7 +1436,7 @@ /obj/item/bodypart/proc/can_bleed() SHOULD_BE_PURE(TRUE) - return ((biological_state & BIO_BLOODED) && (!owner || !HAS_TRAIT(owner, TRAIT_NOBLOOD))) + return ((biological_state & BIO_BLOODED) && (!owner || owner.can_bleed())) /** * apply_gauze() is used to- well, apply gauze to a bodypart diff --git a/code/modules/surgery/bodyparts/wounds.dm b/code/modules/surgery/bodyparts/wounds.dm index 83a9dfbeefb..00542eba8fb 100644 --- a/code/modules/surgery/bodyparts/wounds.dm +++ b/code/modules/surgery/bodyparts/wounds.dm @@ -70,7 +70,7 @@ if(HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) && !HAS_TRAIT(owner, TRAIT_NODISMEMBER)) damage *= 1.1 - if(HAS_TRAIT(owner, TRAIT_EASYBLEED) && !HAS_TRAIT(owner, TRAIT_NOBLOOD) && ((woundtype == WOUND_PIERCE) || (woundtype == WOUND_SLASH))) + if(HAS_TRAIT(owner, TRAIT_EASYBLEED) && owner.can_bleed() && ((woundtype == WOUND_PIERCE) || (woundtype == WOUND_SLASH))) damage *= 1.5 var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT)) diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index bb0780a9a76..ee1bfe42f37 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -70,13 +70,14 @@ /datum/surgery_step/incise_heart/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) if(ishuman(target)) var/mob/living/carbon/human/target_human = target - if (!HAS_TRAIT(target_human, TRAIT_NOBLOOD)) + if (target_human.can_bleed()) + var/blood_name = target_human.get_bloodtype()?.get_blood_name() || "Blood" display_results( user, target, - span_notice("Blood pools around the incision in [target_human]'s heart."), - span_notice("Blood pools around the incision in [target_human]'s heart."), - span_notice("Blood pools around the incision in [target_human]'s heart."), + span_notice("[blood_name] pools around the incision in [target_human]'s heart."), + span_notice("[blood_name] pools around the incision in [target_human]'s heart."), + span_notice("[blood_name] pools around the incision in [target_human]'s heart."), ) var/obj/item/bodypart/target_bodypart = target_human.get_bodypart(target_zone) target_bodypart.adjustBleedStacks(10) @@ -86,12 +87,13 @@ /datum/surgery_step/incise_heart/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(ishuman(target)) var/mob/living/carbon/human/target_human = target + var/blood_name = LOWER_TEXT(target_human.get_bloodtype()?.get_blood_name()) || "blood" display_results( user, target, span_warning("You screw up, cutting too deeply into the heart!"), - span_warning("[user] screws up, causing blood to spurt out of [target_human]'s chest!"), - span_warning("[user] screws up, causing blood to spurt out of [target_human]'s chest!"), + span_warning("[user] screws up, causing [blood_name] to spurt out of [target_human]'s chest!"), + span_warning("[user] screws up, causing [blood_name] to spurt out of [target_human]'s chest!"), ) var/obj/item/bodypart/target_bodypart = target_human.get_bodypart(target_zone) target_bodypart.adjustBleedStacks(10) diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index 22d95c9afd5..cdcb324c867 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -32,13 +32,14 @@ /datum/surgery_step/incise/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) if ishuman(target) var/mob/living/carbon/human/human_target = target - if (!HAS_TRAIT(human_target, TRAIT_NOBLOOD)) + if (human_target.can_bleed()) + var/blood_name = human_target.get_bloodtype()?.get_blood_name() || "Blood" display_results( user, target, - span_notice("Blood pools around the incision in [human_target]'s [target.parse_zone_with_bodypart(target_zone)]."), - span_notice("Blood pools around the incision in [human_target]'s [target.parse_zone_with_bodypart(target_zone)]."), - span_notice("Blood pools around the incision in [human_target]'s [target.parse_zone_with_bodypart(target_zone)]."), + span_notice("[blood_name] pools around the incision in [human_target]'s [target.parse_zone_with_bodypart(target_zone)]."), + span_notice("[blood_name] pools around the incision in [human_target]'s [target.parse_zone_with_bodypart(target_zone)]."), + span_notice("[blood_name] pools around the incision in [human_target]'s [target.parse_zone_with_bodypart(target_zone)]."), ) var/obj/item/bodypart/target_bodypart = target.get_bodypart(target_zone) if(target_bodypart) diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index 2cf51c88a04..4d5e3b752d0 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -77,7 +77,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /obj/item/organ/Initialize(mapload) . = ..() - blood_dna_info = list("UNKNOWN DNA" = get_blood_type(BLOOD_TYPE_O_PLUS)) + blood_dna_info = list("Unknown DNA" = get_blood_type(BLOOD_TYPE_O_PLUS)) if(organ_flags & ORGAN_EDIBLE) AddComponentFrom( SOURCE_EDIBLE_INNATE, \ diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index 69e5afa8af6..e548b25e835 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -333,7 +333,10 @@ owner.visible_message(span_userdanger("[owner]'s brain falls off the back of [owner.p_their()] head!!!"), span_boldwarning("You feel like you're missing something.")) return chippy_brain - new /obj/effect/decal/cleanable/blood/gibs/up(get_turf(owner)) + var/gib_type = /obj/effect/decal/cleanable/blood/gibs/up + if (IS_ROBOTIC_ORGAN(chippy_brain)) + gib_type = /obj/effect/decal/cleanable/blood/gibs/robot_debris/up + new gib_type(get_turf(owner), owner.get_static_viruses(), owner.get_blood_dna_list()) return FALSE /obj/item/organ/cyberimp/brain/connector/proc/reboot() diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm index d7c8e0a5d5e..1bd09e48ed8 100644 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -59,23 +59,21 @@ qdel(GetComponent(/datum/component/squeak)) -/// Registers COMSIG_SPECIES_HANDLE_CHEMICAL from owner /obj/item/organ/liver/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - RegisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL, PROC_REF(handle_chemical)) + RegisterSignal(organ_owner, COMSIG_MOB_REAGENT_TICK, PROC_REF(handle_chemical)) RegisterSignal(organ_owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine)) -/// Unregisters COMSIG_SPECIES_HANDLE_CHEMICAL from owner /obj/item/organ/liver/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - UnregisterSignal(organ_owner, list(COMSIG_SPECIES_HANDLE_CHEMICAL, COMSIG_ATOM_EXAMINE)) + UnregisterSignal(organ_owner, list(COMSIG_MOB_REAGENT_TICK, COMSIG_ATOM_EXAMINE)) /** * This proc can be overriden by liver subtypes so they can handle certain chemicals in special ways. * Return null to continue running the normal on_mob_life() for that reagent. - * Return COMSIG_MOB_STOP_REAGENT_CHECK to not run the normal metabolism effects. + * Return COMSIG_MOB_STOP_REAGENT_TICK to not run the normal metabolism effects. * - * NOTE: If you return COMSIG_MOB_STOP_REAGENT_CHECK, that reagent will not be removed like normal! You must handle it manually. + * NOTE: If you return COMSIG_MOB_STOP_REAGENT_TICK, that reagent will not be removed like normal! You must handle it manually. **/ /obj/item/organ/liver/proc/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) SIGNAL_HANDLER @@ -288,13 +286,41 @@ /obj/item/organ/liver/pod/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) . = ..() - if(. & COMSIG_MOB_STOP_REAGENT_CHECK) + if((. & COMSIG_MOB_STOP_REAGENT_TICK) || (organ_flags & ORGAN_FAILING)) return if(!(organ_owner.mob_biotypes & MOB_PLANT)) return if(chem.type == /datum/reagent/toxin/plantbgone) organ_owner.adjustToxLoss(3 * REM * seconds_per_tick) +/obj/item/organ/liver/snail + name = "snail liver" + desc = "A slimy liver, constantly secreting impressive volumes of lube. Usually cooked with olive oil and cilantro, and traditionally eaten under a white flag." + icon_state = "liver-bone" // Its greyscale, so works perfectly for coloring + color = "#96DB00" + /// Speed modifier for snails who have this organ. Positive numbers make them move slower, negative numbers make them move faster. + var/snail_speed_mod = 6 + +/obj/item/organ/liver/snail/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) + . = ..() + organ_owner.AddElement(/datum/element/lube_walking, require_resting = TRUE) + organ_owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/snail, multiplicative_slowdown = snail_speed_mod) + +/obj/item/organ/liver/snail/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags) + . = ..() + organ_owner.remove_movespeed_modifier(/datum/movespeed_modifier/snail) + organ_owner.RemoveElement(/datum/element/lube_walking, require_resting = TRUE) + +/obj/item/organ/liver/snail/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) + . = ..() + if((. & COMSIG_MOB_STOP_REAGENT_TICK) || (organ_flags & ORGAN_FAILING)) + return + if(istype(chem, /datum/reagent/consumable/salt)) + playsound(organ_owner, SFX_SEAR, 30, TRUE) + organ_owner.adjustFireLoss(2 * REM * seconds_per_tick) + organ_owner.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) + return COMSIG_MOB_STOP_REAGENT_TICK + #undef LIVER_DEFAULT_TOX_TOLERANCE //#undef LIVER_DEFAULT_TOX_RESISTANCE // SKYRAT EDIT REMOVAL - Needed in modular #undef LIVER_FAILURE_STAGE_SECONDS diff --git a/code/modules/surgery/organs/internal/liver/liver_golem.dm b/code/modules/surgery/organs/internal/liver/liver_golem.dm index d9c3d4632cf..22e4091daec 100644 --- a/code/modules/surgery/organs/internal/liver/liver_golem.dm +++ b/code/modules/surgery/organs/internal/liver/liver_golem.dm @@ -14,8 +14,8 @@ /obj/item/organ/liver/golem/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) . = ..() - // parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing - if((. & COMSIG_MOB_STOP_REAGENT_CHECK) || (organ_flags & ORGAN_FAILING)) + // parent returned COMSIG_MOB_STOP_REAGENT_TICK or we are failing + if((. & COMSIG_MOB_STOP_REAGENT_TICK) || (organ_flags & ORGAN_FAILING)) return // golems can only eat minerals if(istype(chem, /datum/reagent/consumable) && !istype(chem, /datum/reagent/consumable/nutriment/mineral)) diff --git a/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm b/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm index 714916d183e..a8c335f8bee 100644 --- a/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm +++ b/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm @@ -12,8 +12,8 @@ /obj/item/organ/liver/bone/plasmaman/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) . = ..() - // parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing - if((. & COMSIG_MOB_STOP_REAGENT_CHECK) || (organ_flags & ORGAN_FAILING)) + // parent returned COMSIG_MOB_STOP_REAGENT_TICK or we are failing + if((. & COMSIG_MOB_STOP_REAGENT_TICK) || (organ_flags & ORGAN_FAILING)) return // plasmamen use plasma to reform their bones or whatever if(istype(chem, /datum/reagent/toxin/plasma) || istype(chem, /datum/reagent/toxin/hot_ice)) diff --git a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm index 6ed49b8f113..b067e68ad3d 100644 --- a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm +++ b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm @@ -15,8 +15,8 @@ /obj/item/organ/liver/bone/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) . = ..() - // parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing - if((. & COMSIG_MOB_STOP_REAGENT_CHECK) || (organ_flags & ORGAN_FAILING)) + // parent returned COMSIG_MOB_STOP_REAGENT_TICK or we are failing + if((. & COMSIG_MOB_STOP_REAGENT_TICK) || (organ_flags & ORGAN_FAILING)) return if(istype(chem, /datum/reagent/toxin/bonehurtingjuice)) organ_owner.adjustStaminaLoss(7.5 * REM * seconds_per_tick, updating_stamina = FALSE) @@ -42,7 +42,7 @@ to_chat(organ_owner, span_warning("Your missing [parse_zone(selected_part)] aches from wherever you left it.")) INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/mob, emote), "sigh") organ_owner.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick) - return COMSIG_MOB_STOP_REAGENT_CHECK // Stop metabolism + return COMSIG_MOB_STOP_REAGENT_TICK // Stop metabolism if(chem.type == /datum/reagent/consumable/milk) if(chem.volume > 50) organ_owner.reagents.remove_reagent(chem.type, (chem.volume - 50)) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index 260ef32b440..ff5af0562a9 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -636,7 +636,7 @@ say_mod = "meows" liked_foodtypes = SEAFOOD | ORANGES | BUGS | GORE disliked_foodtypes = GROSS | CLOTH | RAW - organ_traits = list(TRAIT_WOUND_LICKER, TRAIT_FISH_EATER) + organ_traits = list(TRAIT_WOUND_LICKER, TRAIT_FISH_EATER, TRAIT_CARPOTOXIN_IMMUNE) languages_native = list(/datum/language/nekomimetic) /obj/item/organ/tongue/cat/on_bodypart_insert(obj/item/bodypart/head) diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm index 30039888445..bb7a043e24e 100644 --- a/code/modules/surgery/organs/organ_movement.dm +++ b/code/modules/surgery/organs/organ_movement.dm @@ -238,7 +238,9 @@ SHOULD_CALL_PARENT(TRUE) if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM) && !QDELING(src)) - AddElement(/datum/element/decal/blood, _color = get_blood_dna_color(blood_dna_info)) + var/blood_color = get_color_from_blood_list(blood_dna_info) + if (blood_color) + AddElement(/datum/element/decal/blood, _color = blood_color) item_flags &= ~ABSTRACT REMOVE_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) @@ -281,7 +283,7 @@ /obj/item/organ/proc/on_surgical_removal(mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ORGAN_SURGICALLY_REMOVED, user, old_owner, target_zone, tool) - RemoveElement(/datum/element/decal/blood, _color = old_owner.dna.blood_type.get_color()) + RemoveElement(/datum/element/decal/blood, _color = old_owner.get_bloodtype()?.get_color() || BLOOD_COLOR_RED) /** * Proc that gets called when the organ is surgically inserted by someone. Seem familiar? */ diff --git a/code/modules/unit_tests/bloody_footprints.dm b/code/modules/unit_tests/bloody_footprints.dm index 76b86590861..2a786414fa2 100644 --- a/code/modules/unit_tests/bloody_footprints.dm +++ b/code/modules/unit_tests/bloody_footprints.dm @@ -21,9 +21,8 @@ blood_master.forceMove(run_loc_floor_bottom_left) var/datum/component/bloodysoles/soles = holds_blood.GetComponent(/datum/component/bloodysoles) - var/blood_type = pool.blood_state - TEST_ASSERT(soles.bloody_shoes[blood_type], "Shoes didn't become stained after stepping in a pool of [blood_type]") + TEST_ASSERT(soles.total_bloodiness, "Shoes didn't become stained after stepping in a pool of blood") //The bloody soles component handles the order of stepping on blood/stepping on a bloody tile in a constranating way //Which means it needs to check and see if any time has passed between steps, so it can be sure the player is stepping onto a new tile (that should become bloody) @@ -39,10 +38,9 @@ var/footprint_total = 0 for(var/obj/effect/decal/cleanable/blood/footprints/print_set in move_to) - if(print_set.blood_state == blood_type) - footprint_total += 1 + footprint_total += 1 - TEST_ASSERT(footprint_total, "The floor didn't get covered in [blood_type] after being walked over") + TEST_ASSERT(footprint_total, "The floor didn't get covered in blood after being walked over") soles.last_pickup -= 1 @@ -54,8 +52,7 @@ footprint_total = 0 for(var/obj/effect/decal/cleanable/blood/footprints/print_set in move_to) - if(print_set.blood_state == blood_type) - footprint_total += 1 + footprint_total += 1 TEST_ASSERT(footprint_total, "The floor somehow lost its footprints after being walked over") TEST_ASSERT_EQUAL(footprint_total, 1, "The floor had more than one set of footprints in it, something is fucked") diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index b8ddc586594..6bfbc1bbae1 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -114,39 +114,25 @@ /obj/vehicle/sealed/car/clowncar/Bump(atom/bumped) . = ..() - if(isliving(bumped)) - if(ismegafauna(bumped)) - return - var/mob/living/hittarget_living = bumped + if(isclosedturf(bumped)) + visible_message(span_warning("[src] rams into [bumped] and crashes!")) + playsound(src, pick( + 'sound/vehicles/clown_car/clowncar_crash1.ogg', + 'sound/vehicles/clown_car/clowncar_crash2.ogg', + ), 75) + playsound(src, 'sound/vehicles/clown_car/clowncar_crashpins.ogg', 75) + dump_mobs(TRUE) + log_combat(src, bumped, "crashed into", null, "dumping all passengers") - if(istype(hittarget_living, /mob/living/basic/deer)) - visible_message(span_warning("[src] careens into [hittarget_living]! Oh the humanity!")) - for(var/mob/living/carbon/carbon_occupant in occupants) - if(prob(35)) //Note: The randomstep on dump_mobs throws occupants into each other and often causes wounds regardless. - continue - for(var/obj/item/bodypart/head/head_to_wound as anything in carbon_occupant.bodyparts) - var/pick_mode = text2num(pick(list( - "[WOUND_PICK_LOWEST_SEVERITY]", - "[WOUND_PICK_HIGHEST_SEVERITY]" - ))) - carbon_occupant.cause_wound_of_type_and_severity(WOUND_BLUNT, head_to_wound, WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, pick_mode) - carbon_occupant.playsound_local(src, 'sound/items/weapons/flash_ring.ogg', 50) - carbon_occupant.set_eye_blur_if_lower(rand(10 SECONDS, 20 SECONDS)) - - hittarget_living.adjustBruteLoss(200) - var/obj/effect/decal/cleanable/blood/splatter/blood_splatter = new /obj/effect/decal/cleanable/blood/splatter(get_turf(hittarget_living)) - if(iscarbon(hittarget_living)) - var/mob/living/carbon/carbon_target = hittarget_living - blood_splatter.add_mob_blood(carbon_target) - - log_combat(src, hittarget_living, "rammed into", null, "injuring all passengers and killing the [hittarget_living]") - dump_mobs(TRUE) - playsound(src, 'sound/vehicles/car_crash.ogg', 100) - return + if(!isliving(bumped) || ismegafauna(bumped)) + return + var/mob/living/hittarget_living = bumped + if(!istype(hittarget_living, /mob/living/basic/deer)) if(iscarbon(hittarget_living)) var/mob/living/carbon/carb = hittarget_living carb.Paralyze(4 SECONDS) //I play to make sprites go horizontal + hittarget_living.visible_message(span_warning("[src] rams into [hittarget_living] and sucks [hittarget_living.p_them()] up!")) //fuck off shezza this isn't ERP. mob_forced_enter(hittarget_living) playsound(src, pick( @@ -156,16 +142,25 @@ ), 75) log_combat(src, hittarget_living, "sucked up") return - if(!isclosedturf(bumped)) - return - visible_message(span_warning("[src] rams into [bumped] and crashes!")) - playsound(src, pick( - 'sound/vehicles/clown_car/clowncar_crash1.ogg', - 'sound/vehicles/clown_car/clowncar_crash2.ogg', - ), 75) - playsound(src, 'sound/vehicles/clown_car/clowncar_crashpins.ogg', 75) + + visible_message(span_warning("[src] careens into [hittarget_living]! Oh the humanity!")) + for(var/mob/living/carbon/carbon_occupant in occupants) + if(prob(35)) //Note: The randomstep on dump_mobs throws occupants into each other and often causes wounds regardless. + continue + for(var/obj/item/bodypart/head/head_to_wound as anything in carbon_occupant.bodyparts) + var/pick_mode = text2num(pick(list( + "[WOUND_PICK_LOWEST_SEVERITY]", + "[WOUND_PICK_HIGHEST_SEVERITY]" + ))) + carbon_occupant.cause_wound_of_type_and_severity(WOUND_BLUNT, head_to_wound, WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, pick_mode) + carbon_occupant.playsound_local(src, 'sound/items/weapons/flash_ring.ogg', 50) + carbon_occupant.set_eye_blur_if_lower(rand(10 SECONDS, 20 SECONDS)) + + hittarget_living.add_splatter_floor(small_drip = FALSE) + hittarget_living.adjustBruteLoss(200) + log_combat(src, hittarget_living, "rammed into", null, "injuring all passengers and killing the [hittarget_living]") dump_mobs(TRUE) - log_combat(src, bumped, "crashed into", null, "dumping all passengers") + playsound(src, 'sound/vehicles/car_crash.ogg', 100) /obj/vehicle/sealed/car/clowncar/proc/check_crossed(datum/source, atom/movable/crossed) SIGNAL_HANDLER @@ -263,7 +258,7 @@ ///Deploys oil when the clowncar moves in oil deploy mode /obj/vehicle/sealed/car/clowncar/proc/cover_in_oil() SIGNAL_HANDLER - new /obj/effect/decal/cleanable/oil/slippery(loc) + new /obj/effect/decal/cleanable/blood/oil/slippery(loc) ///Stops dropping oil after the time has run up /obj/vehicle/sealed/car/clowncar/proc/stop_dropping_oil() diff --git a/code/modules/vehicles/cars/vim.dm b/code/modules/vehicles/cars/vim.dm index 7cb6d4b939c..7ae87590d0e 100644 --- a/code/modules/vehicles/cars/vim.dm +++ b/code/modules/vehicles/cars/vim.dm @@ -44,7 +44,7 @@ . += span_notice("[src] can be repaired with a welder.") /obj/vehicle/sealed/car/vim/atom_destruction(damage_flag) - new /obj/effect/decal/cleanable/oil(get_turf(src)) + new /obj/effect/decal/cleanable/blood/oil(get_turf(src)) do_sparks(5, TRUE, src) visible_message(span_bolddanger("[src] blows apart!")) return ..() diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi index b71df50e638..f17e62045ec 100644 Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ diff --git a/icons/effects/footprints.dmi b/icons/effects/footprints.dmi index cef2898e893..175b0c17f66 100644 Binary files a/icons/effects/footprints.dmi and b/icons/effects/footprints.dmi differ diff --git a/icons/mob/silicon/robots.dmi b/icons/mob/silicon/robots.dmi index 770e271fc45..89fa25568fb 100644 Binary files a/icons/mob/silicon/robots.dmi and b/icons/mob/silicon/robots.dmi differ diff --git a/modular_skyrat/master_files/code/modules/mob/living/blood.dm b/modular_skyrat/master_files/code/modules/mob/living/blood.dm index d6f1559527d..e1676d77d4c 100644 --- a/modular_skyrat/master_files/code/modules/mob/living/blood.dm +++ b/modular_skyrat/master_files/code/modules/mob/living/blood.dm @@ -5,13 +5,11 @@ // there's a way to track if blood was extracted from a monkey or not. /mob/living/carbon/get_blood_data(blood_id) . = ..() - if(blood_id == /datum/reagent/blood) - .[MONKEY_ORIGINS] = ismonkey(src) + .[MONKEY_ORIGINS] = ismonkey(src) - -/datum/reagent/blood/on_merge(list/mix_data) +/datum/element/blood_reagent/on_merge(datum/reagent/source, list/mix_data, amount) . = ..() - if(data && mix_data) - data[MONKEY_ORIGINS] = data[MONKEY_ORIGINS] || mix_data[MONKEY_ORIGINS] + if(source.data && mix_data) + source.data[MONKEY_ORIGINS] = source.data[MONKEY_ORIGINS] || mix_data[MONKEY_ORIGINS] #undef MONKEY_ORIGINS diff --git a/modular_skyrat/modules/digi_bloodsole/code/_shoes.dm b/modular_skyrat/modules/digi_bloodsole/code/_shoes.dm index 9076ce503fd..b80aa21e5cf 100644 --- a/modular_skyrat/modules/digi_bloodsole/code/_shoes.dm +++ b/modular_skyrat/modules/digi_bloodsole/code/_shoes.dm @@ -1,9 +1,11 @@ -/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE,icon_file,mutant_styles=NONE) +/obj/item/clothing/shoes/worn_overlays(mutable_appearance/standing, isinhands = FALSE) . = ..() if(isinhands) return if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe") + +/obj/item/clothing/shoes/separate_worn_overlays(mutable_appearance/standing, mutable_appearance/draw_target, isinhands = FALSE, icon_file) if(GET_ATOM_BLOOD_DNA(src)) if (mutant_styles & CLOTHING_DIGITIGRADE_VARIATION) if(clothing_flags & LARGE_WORN_ICON) diff --git a/tgstation.dme b/tgstation.dme index ffdf4b77521..667df634194 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -801,6 +801,7 @@ #include "code\controllers\subsystem\augury.dm" #include "code\controllers\subsystem\ban_cache.dm" #include "code\controllers\subsystem\blackbox.dm" +#include "code\controllers\subsystem\blood_drying.dm" #include "code\controllers\subsystem\chat.dm" #include "code\controllers\subsystem\dbcore.dm" #include "code\controllers\subsystem\dcs.dm" @@ -1619,6 +1620,7 @@ #include "code\datums\elements\befriend_petting.dm" #include "code\datums\elements\block_turf_fingerprints.dm" #include "code\datums\elements\blocks_explosives.dm" +#include "code\datums\elements\blood_reagent.dm" #include "code\datums\elements\body_temp_sensitive.dm" #include "code\datums\elements\bombable_turf.dm" #include "code\datums\elements\bonus_damage.dm" @@ -1662,6 +1664,7 @@ #include "code\datums\elements\dryable.dm" #include "code\datums\elements\earhealing.dm" #include "code\datums\elements\easily_fragmented.dm" +#include "code\datums\elements\easy_ignite.dm" #include "code\datums\elements\effect_trail.dm" #include "code\datums\elements\elevation.dm" #include "code\datums\elements\empprotection.dm" @@ -2499,8 +2502,8 @@ #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\blood.dm" #include "code\game\objects\effects\decals\cleanable\food.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" #include "code\game\objects\effects\decals\turfdecal\dirt.dm" diff --git a/tgui/packages/tgui/interfaces/MedicalKiosk.jsx b/tgui/packages/tgui/interfaces/MedicalKiosk.jsx index 15708faa787..258d57f7913 100644 --- a/tgui/packages/tgui/interfaces/MedicalKiosk.jsx +++ b/tgui/packages/tgui/interfaces/MedicalKiosk.jsx @@ -186,6 +186,7 @@ const MedicalKioskScanResults2 = (props) => { illness_info, bleed_status, blood_levels, + blood_name, blood_status, } = data; return ( @@ -202,7 +203,7 @@ const MedicalKioskScanResults2 = (props) => { {illness_info} - + @@ -210,7 +211,7 @@ const MedicalKioskScanResults2 = (props) => { {bleed_status} - + {blood_status} diff --git a/tools/UpdatePaths/Scripts/91053_update_blood_decals.txt b/tools/UpdatePaths/Scripts/91053_update_blood_decals.txt new file mode 100644 index 00000000000..b5a26c20846 --- /dev/null +++ b/tools/UpdatePaths/Scripts/91053_update_blood_decals.txt @@ -0,0 +1,9 @@ +# Alien guts and oil spills are now blood decals +/obj/effect/decal/cleanable/blood/trails : /obj/effect/decal/cleanable/blood/trail_holder{@OLD} +/obj/effect/decal/cleanable/robot_debris : /obj/effect/decal/cleanable/blood/gibs/robot_debris{@OLD} +/obj/effect/decal/cleanable/oil/streak : /obj/effect/decal/cleanable/blood/splatter/oil{@OLD} +/obj/effect/decal/cleanable/oil : /obj/effect/decal/cleanable/blood/oil{@OLD} +/obj/effect/decal/cleanable/xenoblood/xsplatter : /obj/effect/decal/cleanable/blood/splatter/xeno{@OLD} +/obj/effect/decal/cleanable/xenoblood/xgibs : /obj/effect/decal/cleanable/blood/gibs/xeno{@OLD} +/obj/effect/decal/cleanable/xenoblood : /obj/effect/decal/cleanable/blood/xeno{@OLD} +/obj/effect/decal/cleanable/blood/tracks/xeno: /obj/effect/decal/cleanable/blood/tracks/xeno{@OLD}