diff --git a/code/game/objects/effects/decals/Cleanable/aliens.dm b/code/game/objects/effects/decals/Cleanable/aliens.dm
index 7ee6aaa3b50..f2e3cfc3a3c 100644
--- a/code/game/objects/effects/decals/Cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/Cleanable/aliens.dm
@@ -1,30 +1,18 @@
// Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code.
-/obj/effect/decal/cleanable/xenoblood
+/obj/effect/decal/cleanable/blood/xeno
name = "xeno blood"
desc = "It's green and acidic. It looks like... blood?"
- gender = PLURAL
- density = 0
- anchored = 1
- layer = 2
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
- random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
- var/list/viruses = list()
- blood_DNA = list()
- Del()
- for(var/datum/disease/D in viruses)
- D.cure(0)
- ..()
-
-/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(var/list/directions)
+/obj/effect/decal/cleanable/blood/xeno/proc/streak(var/list/directions)
spawn (0)
var/direction = pick(directions)
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
sleep(3)
if (i > 0)
- var/obj/effect/decal/cleanable/xenoblood/b = new /obj/effect/decal/cleanable/xenoblood/xsplatter(src.loc)
+ var/obj/effect/decal/cleanable/blood/xeno/b = new /obj/effect/decal/cleanable/blood/xeno/xsplatter(src.loc)
for(var/datum/disease/D in src.viruses)
var/datum/disease/ND = D.Copy(1)
b.viruses += ND
@@ -32,10 +20,10 @@
if (step_to(src, get_step(src, direction), 0))
break
-/obj/effect/decal/cleanable/xenoblood/xsplatter
+/obj/effect/decal/cleanable/blood/xeno/xsplatter
random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5")
-/obj/effect/decal/cleanable/xenoblood/xgibs
+/obj/effect/decal/cleanable/blood/xeno/xgibs
name = "xeno gibs"
desc = "Gnarly..."
gender = PLURAL
@@ -43,19 +31,19 @@
icon_state = "xgib1"
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
-/obj/effect/decal/cleanable/xenoblood/xgibs/up
+/obj/effect/decal/cleanable/blood/xeno/xgibs/up
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/xeno/xgibs/down
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/xeno/xgibs/body
random_icon_states = list("xgibhead", "xgibtorso")
-/obj/effect/decal/cleanable/xenoblood/xgibs/limb
+/obj/effect/decal/cleanable/blood/xeno/xgibs/limb
random_icon_states = list("xgibleg", "xgibarm")
-/obj/effect/decal/cleanable/xenoblood/xgibs/core
+/obj/effect/decal/cleanable/blood/xeno/xgibs/core
random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3")
/obj/effect/decal/cleanable/blood/xtracks
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 4f472f864ff..684bf76878f 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -1,147 +1,143 @@
-#define DRYING_TIME 5 * 60*10 //for 1 unit of depth in puddle (amount var)
+#define DRYING_TIME 5 * 60*10 //for 1 unit of depth in puddle (amount var)
+
/obj/effect/decal/cleanable/blood
- name = "blood"
- desc = "It's red and gooey. Perhaps it's the chef's cooking?"
- gender = PLURAL
- density = 0
- anchored = 1
- layer = 2
- icon = 'icons/effects/blood.dmi'
- icon_state = "floor1"
- random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
- var/list/viruses = list()
- blood_DNA = list()
- var/list/datum/disease2/disease/virus2 = list()
- var/amount = 5
+ name = "blood"
+ desc = "It's red and gooey. Perhaps it's the chef's cooking?"
+ gender = PLURAL
+ density = 0
+ anchored = 1
+ layer = 2
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "floor1"
+ random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
+ var/list/viruses = list()
+ blood_DNA = list()
+ var/basecolor="#A10808" // Color when wet.
+ var/list/datum/disease2/disease/virus2 = list()
+ var/amount = 5
/obj/effect/decal/cleanable/blood/Del()
- for(var/datum/disease/D in viruses)
- D.cure(0)
- ..()
+ for(var/datum/disease/D in viruses)
+ D.cure(0)
+ ..()
/obj/effect/decal/cleanable/blood/New()
- ..()
- if(istype(src, /obj/effect/decal/cleanable/blood/gibs))
- return
- if(src.type == /obj/effect/decal/cleanable/blood)
- if(src.loc && isturf(src.loc))
- for(var/obj/effect/decal/cleanable/blood/B in src.loc)
- if(B != src)
- if (B.blood_DNA)
- blood_DNA |= B.blood_DNA.Copy()
- del(B)
- spawn(DRYING_TIME * (amount+1))
- dry()
+ ..()
+ if(istype(src, /obj/effect/decal/cleanable/blood/gibs))
+ return
+ if(istype(src, /obj/effect/decal/cleanable/blood/tracks))
+ return // We handle our own drying.
+ if(src.type == /obj/effect/decal/cleanable/blood)
+ if(src.loc && isturf(src.loc))
+ for(var/obj/effect/decal/cleanable/blood/B in src.loc)
+ if(B != src)
+ if (B.blood_DNA)
+ blood_DNA |= B.blood_DNA.Copy()
+ del(B)
+ spawn(DRYING_TIME * (amount+1))
+ dry()
/obj/effect/decal/cleanable/blood/HasEntered(mob/living/carbon/human/perp)
- if (!istype(perp))
- return
- if(amount < 1)
- return
+ if (!istype(perp))
+ return
+ if(amount < 1)
+ return
- if(perp.shoes)
- perp.shoes:track_blood = max(amount,perp.shoes:track_blood) //Adding blood to shoes
- if(!perp.shoes.blood_overlay)
- perp.shoes.generate_blood_overlay()
- if(!perp.shoes.blood_DNA)
- perp.shoes.blood_DNA = list()
- perp.shoes.overlays += perp.shoes.blood_overlay
- perp.update_inv_shoes(1)
- perp.shoes.blood_DNA |= blood_DNA.Copy()
- else
- perp.track_blood = max(amount,perp.track_blood) //Or feet
- if(!perp.feet_blood_DNA)
- perp.feet_blood_DNA = list()
- perp.feet_blood_DNA |= blood_DNA.Copy()
+ if(perp.shoes)
+ perp.shoes:track_blood = max(amount,perp.shoes:track_blood) //Adding blood to shoes
+ if(!perp.shoes.blood_overlay)
+ perp.shoes.generate_blood_overlay()
+ if(!perp.shoes.blood_DNA)
+ perp.shoes.blood_DNA = list()
+ perp.shoes.overlays += perp.shoes.blood_overlay
+ perp.update_inv_shoes(1)
+ perp.shoes.blood_DNA |= blood_DNA.Copy()
+ perp.shoes.blood_color=basecolor
+ else
+ perp.track_blood = max(amount,perp.track_blood) //Or feet
+ if(!perp.feet_blood_DNA)
+ perp.feet_blood_DNA = list()
+ perp.feet_blood_DNA |= blood_DNA.Copy()
+ perp.feet_blood_color=basecolor
- amount--
+ amount--
/obj/effect/decal/cleanable/blood/proc/dry()
- name = "dried [src]"
- desc = "It's dark red and crusty. Someone is not doing their job."
- var/icon/I = icon(icon,icon_state)
- I.SetIntensity(0.7)
- icon = I
- amount = 0
+ name = "dried [src]"
+ desc = "It's dark red and crusty. Someone is not doing their job."
+ var/icon/I = icon(icon,icon_state)
+ I.SetIntensity(0.7)
+ icon = I
+ amount = 0
/obj/effect/decal/cleanable/blood/splatter
- random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
- amount = 2
-
-/obj/effect/decal/cleanable/blood/footprints
- name = "bloody footprints"
- desc = "Whoops..."
- icon='icons/effects/footprints.dmi'
- icon_state = "blood1"
- amount = 0
- random_icon_states = null
-
-/obj/effect/decal/cleanable/blood/tracks
- icon_state = "tracks"
- desc = "They look like tracks left by wheels."
- gender = PLURAL
- random_icon_states = null
- amount = 0
+ random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
+ amount = 2
/obj/effect/decal/cleanable/blood/drip
- name = "drips of blood"
- desc = "It's red."
- gender = PLURAL
- icon = 'icons/effects/drip.dmi'
- icon_state = "1"
- amount = 0
+ name = "drips of blood"
+ desc = "It's red."
+ gender = PLURAL
+ icon = 'icons/effects/drip.dmi'
+ icon_state = "1"
+ amount = 0
/obj/effect/decal/cleanable/blood/gibs
- name = "gibs"
- desc = "They look bloody and gruesome."
- gender = PLURAL
- density = 0
- anchored = 1
- layer = 2
- icon = 'icons/effects/blood.dmi'
- icon_state = "gibbl5"
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
+ name = "gibs"
+ desc = "They look bloody and gruesome."
+ gender = PLURAL
+ density = 0
+ anchored = 1
+ layer = 2
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "gibbl5"
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
/obj/effect/decal/cleanable/blood/gibs/up
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
/obj/effect/decal/cleanable/blood/gibs/down
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
/obj/effect/decal/cleanable/blood/gibs/body
- random_icon_states = list("gibhead", "gibtorso")
+ random_icon_states = list("gibhead", "gibtorso")
/obj/effect/decal/cleanable/blood/gibs/limb
- random_icon_states = list("gibleg", "gibarm")
+ random_icon_states = list("gibleg", "gibarm")
/obj/effect/decal/cleanable/blood/gibs/core
- random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
/obj/effect/decal/cleanable/blood/gibs/proc/streak(var/list/directions)
- spawn (0)
- var/direction = pick(directions)
- for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
- sleep(3)
- if (i > 0)
- var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
- for(var/datum/disease/D in src.viruses)
- var/datum/disease/ND = D.Copy(1)
- b.viruses += ND
- ND.holder = b
+ spawn (0)
+ var/direction = pick(directions)
+ for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
+ sleep(3)
+ if (i > 0)
+ var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
+ for(var/datum/disease/D in src.viruses)
+ var/datum/disease/ND = D.Copy(1)
+ b.viruses += ND
+ ND.holder = b
- if (step_to(src, get_step(src, direction), 0))
- break
+ if (step_to(src, get_step(src, direction), 0))
+ break
/obj/effect/decal/cleanable/mucus
- name = "mucus"
- desc = "Disgusting mucus."
- gender = PLURAL
- density = 0
- anchored = 1
- layer = 2
- icon = 'icons/effects/blood.dmi'
- icon_state = "mucus"
- random_icon_states = list("mucus")
- var/list/datum/disease2/disease/virus2 = list()
+ name = "mucus"
+ desc = "Disgusting mucus."
+ gender = PLURAL
+ density = 0
+ anchored = 1
+ layer = 2
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "mucus"
+ random_icon_states = list("mucus")
+ var/list/datum/disease2/disease/virus2 = list()
+ var/dry=0 // Keeps the lag down
+
+/obj/effect/decal/cleanable/mucus/New()
+ spawn(DRYING_TIME * 2)
+ dry=1
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm
index fa3aa3bfa9d..1494e92219a 100644
--- a/code/game/objects/effects/decals/Cleanable/robots.dm
+++ b/code/game/objects/effects/decals/Cleanable/robots.dm
@@ -1,17 +1,14 @@
// 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/robot
name = "robot debris"
desc = "It's a useless heap of junk... or is it?"
- gender = PLURAL
- density = 0
- anchored = 1
- layer = 2
icon = 'icons/mob/robots.dmi'
icon_state = "gib1"
+ basecolor="#2B2B2B"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
-/obj/effect/decal/cleanable/robot_debris/proc/streak(var/list/directions)
+/obj/effect/decal/cleanable/blood/robot/proc/streak(var/list/directions)
spawn (0)
var/direction = pick(directions)
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
@@ -19,7 +16,7 @@
if (i > 0)
if (prob(40))
/*var/obj/effect/decal/cleanable/oil/o =*/
- new /obj/effect/decal/cleanable/oil/streak(src.loc)
+ new /obj/effect/decal/cleanable/blood/oil/streak(src.loc)
else if (prob(10))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
@@ -27,31 +24,22 @@
if (step_to(src, get_step(src, direction), 0))
break
-/obj/effect/decal/cleanable/robot_debris/limb
+/obj/effect/decal/cleanable/blood/robot/limb
random_icon_states = list("gibarm", "gibleg")
-/obj/effect/decal/cleanable/robot_debris/up
+/obj/effect/decal/cleanable/blood/robot/up
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4
-/obj/effect/decal/cleanable/robot_debris/down
+/obj/effect/decal/cleanable/blood/robot/down
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4
-/obj/effect/decal/cleanable/oil
+/obj/effect/decal/cleanable/blood/oil
name = "motor oil"
desc = "It's black and greasy. Looks like Beepsky made another mess."
- gender = PLURAL
- density = 0
- anchored = 1
- layer = 2
+ basecolor="#2B2B2B"
icon = 'icons/mob/robots.dmi'
icon_state = "floor1"
- var/viruses = list()
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
- Del()
- for(var/datum/disease/D in viruses)
- D.cure(0)
- ..()
-
-/obj/effect/decal/cleanable/oil/streak
+/obj/effect/decal/cleanable/blood/oil/streak
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm
new file mode 100644
index 00000000000..d1c329014ce
--- /dev/null
+++ b/code/game/objects/effects/decals/Cleanable/tracks.dm
@@ -0,0 +1,194 @@
+// Stolen en masse from N3X15 of /vg/station with much gratitude.
+
+// The idea is to have 4 bits for coming and 4 for going.
+#define TRACKS_COMING_NORTH 1
+#define TRACKS_COMING_SOUTH 2
+#define TRACKS_COMING_EAST 4
+#define TRACKS_COMING_WEST 8
+#define TRACKS_GOING_NORTH 16
+#define TRACKS_GOING_SOUTH 32
+#define TRACKS_GOING_EAST 64
+#define TRACKS_GOING_WEST 128
+
+// 5 seconds
+#define TRACKS_CRUSTIFY_TIME 50
+
+// color-dir-dry
+var/global/list/image/fluidtrack_cache=list()
+
+/datum/fluidtrack
+ var/direction=0
+ var/basecolor="#A10808"
+ var/wet=0
+ var/fresh=1
+ var/crusty=0
+ var/image/overlay
+
+ New(_direction,_color,_wet)
+ src.direction=_direction
+ src.basecolor=_color
+ src.wet=_wet
+
+// Footprints, tire trails...
+/obj/effect/decal/cleanable/blood/tracks
+ amount = 0
+ random_icon_states = null
+ var/dirs=0
+ icon = 'icons/effects/fluidtracks.dmi'
+ var/coming_state="blood1"
+ var/going_state="blood2"
+ var/updatedtracks=0
+
+ // dir = id in stack
+ var/list/setdirs=list(
+ "1"=0,
+ "2"=0,
+ "4"=0,
+ "8"=0,
+ "16"=0,
+ "32"=0,
+ "64"=0,
+ "128"=0
+ )
+
+ // List of laid tracks and their colors.
+ var/list/datum/fluidtrack/stack=list()
+
+ /**
+ * Add tracks to an existing trail.
+ *
+ * @param DNA bloodDNA to add to collection.
+ * @param comingdir Direction tracks come from, or 0.
+ * @param goingdir Direction tracks are going to (or 0).
+ * @param bloodcolor Color of the blood when wet.
+ */
+ proc/AddTracks(var/list/DNA, var/comingdir, var/goingdir, var/bloodcolor="#A10808")
+ var/updated=0
+ // Shift our goingdir 4 spaces to the left so it's in the GOING bitblock.
+ var/realgoing=goingdir<<4
+
+ // Current bit
+ var/b=0
+
+ // When tracks will start to dry out
+ var/t=world.time + TRACKS_CRUSTIFY_TIME
+
+ var/datum/fluidtrack/track
+
+ // Process 4 bits
+ for(var/bi=0;bi<4;bi++)
+ b=1<>4
+
+ if(track.overlay)
+ track.overlay=null
+
+ //var/cache_key="[track.basecolor]|[state]|[track.direction]|[track.wet