diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm
index 1c0f65cbdc8..53f4887fa20 100644
--- a/code/__DEFINES/cleaning.dm
+++ b/code/__DEFINES/cleaning.dm
@@ -1,18 +1,20 @@
-//Cleaning tool strength
-// 1 is also a valid cleaning strength but completely unused so left undefined
-#define CLEAN_WEAK 2
-/// Acceptable tools
-#define CLEAN_MEDIUM 3
-/// Industrial strength
-#define CLEAN_STRONG 4
-/// Cleaning strong enough your granny would be proud
-#define CLEAN_IMPRESSIVE 5
-/// Cleans things spotless down to the atomic structure
-#define CLEAN_GOD 6
-/// Never cleaned
-#define CLEAN_NEVER 7
-//How strong things have to be to wipe forensic evidence...
-#define CLEAN_STRENGTH_FINGERPRINTS CLEAN_IMPRESSIVE
-#define CLEAN_STRENGTH_BLOOD CLEAN_WEAK
-#define CLEAN_STRENGTH_FIBERS CLEAN_IMPRESSIVE
+// Cleaning flags
+
+// Different kinds of things that can be cleaned.
+// Use these when overriding the wash proc or registering for the clean signals to check if your thing should be cleaned
+#define CLEAN_TYPE_BLOOD (1 << 0)
+#define CLEAN_TYPE_RUNES (1 << 1)
+#define CLEAN_TYPE_FINGERPRINTS (1 << 2)
+#define CLEAN_TYPE_FIBERS (1 << 3)
+#define CLEAN_TYPE_RADIATION (1 << 4)
+#define CLEAN_TYPE_DISEASE (1 << 5)
+#define CLEAN_TYPE_WEAK (1 << 6) // Special type, add this flag to make some cleaning processes non-instant. Currently only used for showers when removing radiation.
+#define CLEAN_TYPE_PAINT (1 << 7)
+
+// Different cleaning methods.
+// Use these when calling the wash proc for your cleaning apparatus
+#define CLEAN_WASH (CLEAN_TYPE_BLOOD | CLEAN_TYPE_RUNES | CLEAN_TYPE_DISEASE)
+#define CLEAN_SCRUB (CLEAN_WASH | CLEAN_TYPE_FINGERPRINTS | CLEAN_TYPE_FIBERS | CLEAN_TYPE_PAINT)
+#define CLEAN_RAD CLEAN_TYPE_RADIATION
+#define CLEAN_ALL (ALL & ~CLEAN_TYPE_WEAK)
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 11b2655f2df..4cbff5d8f5d 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -613,7 +613,8 @@
#define COMSIG_TURF_IS_WET "check_turf_wet"
///(max_strength, immediate, duration_decrease = INFINITY): Returns bool.
#define COMSIG_TURF_MAKE_DRY "make_turf_try"
-///called on an object to clean it of cleanables. Usualy with soap: (num/strength)
+
+///Called on an object to "clean it", such as removing blood decals/overlays, etc. The clean types bitfield is sent with it. Return TRUE if any cleaning was necessary and thus performed.
#define COMSIG_COMPONENT_CLEAN_ACT "clean_act"
//Creamed
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 76c120a3373..67a6a8c2f9d 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -172,7 +172,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismecha(A) (istype(A, /obj/mecha))
-#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable
+#define ismopable(A) (A.layer <= HIGH_SIGIL_LAYER) //If something can be cleaned by floor-cleaning devices such as mops or clean bots
#define isorgan(A) (istype(A, /obj/item/organ))
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index 430d5dd230f..07079caed49 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -83,6 +83,7 @@
#define VV_HK_TRIGGER_EMP "empulse"
#define VV_HK_TRIGGER_EXPLOSION "explode"
#define VV_HK_AUTO_RENAME "auto_rename"
+#define VV_HK_RADIATE "radiate"
// /obj
#define VV_HK_OSAY "osay"
diff --git a/code/datums/components/creamed.dm b/code/datums/components/creamed.dm
index 432f146f84e..2abdf6cff0a 100644
--- a/code/datums/components/creamed.dm
+++ b/code/datums/components/creamed.dm
@@ -57,6 +57,7 @@ GLOBAL_LIST_INIT(creamable, typecacheof(list(
COMSIG_COMPONENT_CLEAN_FACE_ACT))
///Callback to remove pieface
-/datum/component/creamed/proc/clean_up(datum/source, strength)
- if(strength >= CLEAN_WEAK)
+/datum/component/creamed/proc/clean_up(datum/source, clean_types)
+ if(clean_types & CLEAN_TYPE_BLOOD)
qdel(src)
+ return TRUE
diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm
index f474e35cc8d..3a817e139cb 100644
--- a/code/datums/components/decal.dm
+++ b/code/datums/components/decal.dm
@@ -7,7 +7,7 @@
var/first_dir // This only stores the dir arg from init
-/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_NEVER, _color, _layer=TURF_LAYER, _description, _alpha=255)
+/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=FALSE, _color, _layer=TURF_LAYER, _description, _alpha=255)
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
return COMPONENT_INCOMPATIBLE
first_dir = _dir
@@ -19,7 +19,7 @@
/datum/component/decal/RegisterWithParent()
if(first_dir)
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
- if(cleanable != CLEAN_NEVER)
+ if(cleanable != FALSE)
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
if(description)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
@@ -80,9 +80,10 @@
pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
apply()
-/datum/component/decal/proc/clean_react(datum/source, strength)
- if(strength >= cleanable)
+/datum/component/decal/proc/clean_react(datum/source, clean_types)
+ if(clean_types & cleanable)
qdel(src)
+ return TRUE
/datum/component/decal/proc/examine(datum/source, mob/user, list/examine_list)
examine_list += description
diff --git a/code/datums/components/decals/blood.dm b/code/datums/components/decals/blood.dm
index 3114ddb24e9..d2c5804222e 100644
--- a/code/datums/components/decals/blood.dm
+++ b/code/datums/components/decals/blood.dm
@@ -1,7 +1,7 @@
/datum/component/decal/blood
dupe_mode = COMPONENT_DUPE_UNIQUE
-/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
+/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_TYPE_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
. = ..()
diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm
index a037604533c..afb529428a5 100644
--- a/code/datums/components/forensics.dm
+++ b/code/datums/components/forensics.dm
@@ -51,13 +51,16 @@
fibers = null
return TRUE
-/datum/component/forensics/proc/clean_act(datum/source, strength)
- if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
+/datum/component/forensics/proc/clean_act(datum/source, clean_types)
+ if(clean_types & CLEAN_TYPE_FINGERPRINTS)
wipe_fingerprints()
- if(strength >= CLEAN_STRENGTH_BLOOD)
+ . = TRUE
+ if(clean_types & CLEAN_TYPE_BLOOD)
wipe_blood_DNA()
- if(strength >= CLEAN_STRENGTH_FIBERS)
+ . = TRUE
+ if(clean_types & CLEAN_TYPE_FIBERS)
wipe_fibers()
+ . = TRUE
/datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text)
if(!length(_fingerprints))
diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm
index 930c72d590f..42baec25d69 100644
--- a/code/datums/components/infective.dm
+++ b/code/datums/components/infective.dm
@@ -2,7 +2,7 @@
dupe_mode = COMPONENT_DUPE_ALLOWED
var/list/datum/disease/diseases //make sure these are the static, non-processing versions!
var/expire_time
- var/min_clean_strength = CLEAN_WEAK
+ var/required_clean_types = CLEAN_TYPE_DISEASE
/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in)
if(islist(_diseases))
@@ -12,7 +12,7 @@
if(expire_in)
expire_time = world.time + expire_in
QDEL_IN(src, expire_in)
-
+
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean)
@@ -34,9 +34,10 @@
eater.ForceContractDisease(V)
try_infect(feeder, BODY_ZONE_L_ARM)
-/datum/component/infective/proc/clean(datum/source, clean_strength)
- if(clean_strength >= min_clean_strength)
+/datum/component/infective/proc/clean(datum/source, clean_types)
+ if(clean_types & required_clean_types)
qdel(src)
+ return TRUE
/datum/component/infective/proc/try_infect_buckle(datum/source, mob/M, force)
if(isliving(M))
diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm
index 7e62afc5ae4..1b62b8712c5 100644
--- a/code/datums/components/radioactive.dm
+++ b/code/datums/components/radioactive.dm
@@ -18,6 +18,7 @@
can_contaminate = _can_contaminate
if(istype(parent, /atom))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/rad_examine)
+ RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/rad_clean)
if(istype(parent, /obj/item))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/rad_attack)
RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, .proc/rad_attack)
@@ -90,6 +91,21 @@
return
strength -= strength / hl3_release_date
+/datum/component/radioactive/proc/rad_clean(datum/source, clean_types)
+ if(QDELETED(src))
+ return
+
+ if(!(clean_types & CLEAN_TYPE_RADIATION))
+ return
+
+ if(!(clean_types & CLEAN_TYPE_WEAK))
+ qdel(src)
+ return
+
+ strength = max(0, (strength - (RAD_BACKGROUND_RADIATION * 2)))
+ if(strength <= RAD_BACKGROUND_RADIATION)
+ qdel(src)
+
#undef RAD_AMOUNT_LOW
#undef RAD_AMOUNT_MEDIUM
#undef RAD_AMOUNT_HIGH
diff --git a/code/datums/components/thermite.dm b/code/datums/components/thermite.dm
index b745e740571..c932c6a1574 100644
--- a/code/datums/components/thermite.dm
+++ b/code/datums/components/thermite.dm
@@ -82,6 +82,7 @@
/datum/component/thermite/proc/clean_react(datum/source, strength)
//Thermite is just some loose powder, you could probably clean it with your hands. << todo?
qdel(src)
+ return TRUE
/datum/component/thermite/proc/flame_react(datum/source, exposed_temperature, exposed_volume)
if(exposed_temperature > 1922) // This is roughly the real life requirement to ignite thermite
diff --git a/code/datums/elements/cleaning.dm b/code/datums/elements/cleaning.dm
index fa563129390..9f7138b587c 100644
--- a/code/datums/elements/cleaning.dm
+++ b/code/datums/elements/cleaning.dm
@@ -14,27 +14,17 @@
if(!isturf(tile))
return
- SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ tile.wash(CLEAN_WASH)
for(var/A in tile)
- if(is_cleanable(A))
- qdel(A)
- else if(istype(A, /obj/item))
+ // Clean small items that are lying on the ground
+ if(isitem(A))
var/obj/item/I = A
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(ismob(I.loc))
- var/mob/M = I.loc
- M.regenerate_icons()
+ if(I.w_class <= WEIGHT_CLASS_SMALL && !ismob(I.loc))
+ I.wash(CLEAN_WASH)
+ // Clean humans that are lying down
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(!(cleaned_human.mobility_flags & MOBILITY_STAND))
- if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ cleaned_human.wash(CLEAN_WASH)
cleaned_human.regenerate_icons()
to_chat(cleaned_human, "[AM] cleans your face!")
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 950a9f765f6..bae6399e28d 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -933,8 +933,7 @@
///Removes an instance of colour_type from the atom's atom_colours list
/atom/proc/remove_atom_colour(colour_priority, coloration)
if(!atom_colours)
- atom_colours = list()
- atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently.
+ return
if(colour_priority > atom_colours.len)
return
if(coloration && atom_colours[colour_priority] != coloration)
@@ -945,10 +944,9 @@
///Resets the atom's color to null, and then sets it to the highest priority colour available
/atom/proc/update_atom_colour()
- if(!atom_colours)
- atom_colours = list()
- atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently.
color = null
+ if(!atom_colours)
+ return
for(var/C in atom_colours)
if(islist(C))
var/list/L = C
@@ -960,20 +958,23 @@
return
-///Proc for being washed by a shower
-/atom/proc/washed(var/atom/washer, wash_strength = CLEAN_WEAK)
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, wash_strength)
- remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+/**
+ * Wash this atom
+ *
+ * This will clean it off any temporary stuff like blood. Override this in your item to add custom cleaning behavior.
+ * Returns true if any washing was necessary and thus performed
+ * Arguments:
+ * * clean_types: any of the CLEAN_ constants
+ */
+/atom/proc/wash(clean_types)
+ . = FALSE
+ if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types))
+ . = TRUE
- var/datum/component/radioactive/healthy_green_glow = GetComponent(/datum/component/radioactive)
- if(!QDELETED(healthy_green_glow))
- healthy_green_glow.strength -= max(0, (healthy_green_glow.strength - (RAD_BACKGROUND_RADIATION * 2)))
- if(healthy_green_glow.strength <= RAD_BACKGROUND_RADIATION)
- qdel(healthy_green_glow)
-
- /// we got to return true because of mob code
- /// and not all code that uses COMSIG_COMPONENT_CLEAN_ACT returns true half the time
- return TRUE
+ // Basically "if has washable coloration"
+ if(length(atom_colours) >= WASHABLE_COLOUR_PRIORITY && atom_colours[WASHABLE_COLOUR_PRIORITY])
+ remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+ return TRUE
/**
* call back when a var is edited on this atom
@@ -1010,6 +1011,7 @@
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
+ VV_DROPDOWN_OPTION(VV_HK_RADIATE, "Radiate")
/atom/vv_do_topic(list/href_list)
. = ..()
@@ -1050,6 +1052,10 @@
usr.client.cmd_admin_explosion(src)
if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN))
usr.client.cmd_admin_emp(src)
+ if(href_list[VV_HK_RADIATE] && check_rights(R_FUN))
+ var/strength = input(usr, "Choose the radiation strength.", "Choose the strength.") as num|null
+ if(!isnull(strength))
+ AddComponent(/datum/component/radioactive, strength, src)
if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT))
var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate")
var/matrix/M = transform
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index f7bf7ec4f89..0278cb49f59 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -296,11 +296,9 @@
if(occupant)
things_to_clear += occupant
things_to_clear += occupant.GetAllContents()
- for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
- SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
- var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
- if(contamination)
- qdel(contamination)
+ for(var/am in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
+ var/atom/movable/dirty_movable = am
+ dirty_movable.wash(CLEAN_ALL)
open_machine(FALSE)
if(occupant)
dump_contents()
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 57ce9f5cddb..dd06a162dd0 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -143,10 +143,6 @@ GLOBAL_LIST_INIT(dye_registry, list(
var/obj/item/color_source
var/max_wash_capacity = 5
-/obj/machinery/washing_machine/ComponentInitialize()
- . = ..()
- RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
-
/obj/machinery/washing_machine/examine(mob/user)
. = ..()
if(!busy)
@@ -186,15 +182,17 @@ GLOBAL_LIST_INIT(dye_registry, list(
M.Translate(rand(-3, 3), rand(-1, 3))
animate(src, transform=M, time=2)
-/obj/machinery/washing_machine/proc/clean_blood()
- if(!busy)
+/obj/machinery/washing_machine/wash(clean_types)
+ . = ..()
+ if(!busy && bloody_mess && (clean_types & CLEAN_TYPE_BLOOD))
bloody_mess = FALSE
update_icon()
+ . = TRUE
/obj/machinery/washing_machine/proc/wash_cycle()
for(var/X in contents)
var/atom/movable/AM = X
- SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ AM.wash(CLEAN_WASH)
AM.machine_wash(src)
busy = FALSE
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index c1758ddbe08..8f40b808f9d 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -43,7 +43,7 @@
return TRUE
/obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
+ if((istype(W, /obj/item/reagent_containers/glass) && !istype(W, /obj/item/reagent_containers/glass/rag)) || istype(W, /obj/item/reagent_containers/food/drinks))
if(src.reagents && W.reagents)
. = 1 //so the containers don't splash their content on the src while scooping.
if(!src.reagents.total_volume)
@@ -100,9 +100,11 @@
S.blood_state = blood_state
update_icon()
H.update_inv_shoes()
-/atom/effect/decal/cleanable/washed(atom/washer)
- . = ..()
+
+/obj/effect/decal/cleanable/wash(clean_types)
+ ..()
qdel(src)
+ return TRUE
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm
index 803b7250801..0cacc65c35c 100644
--- a/code/game/objects/effects/decals/decal.dm
+++ b/code/game/objects/effects/decals/decal.dm
@@ -45,4 +45,4 @@
var/turf/T = loc
if(!istype(T)) //you know this will happen somehow
CRASH("Turf decal initialized in an object/nullspace")
- T.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_NEVER, color, null, null, alpha)
+ T.AddComponent(/datum/component/decal, icon, icon_state, dir, FALSE, color, null, null, alpha)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 808f08d281d..2ce4d0c3968 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1109,3 +1109,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
return discover_after
#undef MAX_BONUS_MATS_PER_BITE
+
+// Update icons if this is being carried by a mob
+/obj/item/wash(clean_types)
+ . = ..()
+
+ if(ismob(loc))
+ var/mob/mob_loc = loc
+ mob_loc.regenerate_icons()
diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm
index fa128bf67d8..fd6ebbf9039 100644
--- a/code/game/objects/items/airlock_painter.dm
+++ b/code/game/objects/items/airlock_painter.dm
@@ -174,7 +174,7 @@
to_chat(user, "You need to get closer!")
return
if(use_paint(user) && isturf(F))
- F.AddComponent(/datum/component/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
+ F.AddComponent(/datum/component/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_TYPE_PAINT, color, null, null, alpha)
/obj/item/airlock_painter/decal/AltClick(mob/user)
. = ..()
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index 51e758fbe37..5ddb39e92e2 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -144,11 +144,11 @@
user.visible_message("[user] begins to clean \the [target.name] with [src]...", "You begin to clean \the [target.name] with [src]...")
if(do_after(user, clean_speedies, target = target))
to_chat(user, "You clean \the [target.name].")
- for(var/obj/effect/decal/cleanable/C in target)
- user?.mind.adjust_experience(/datum/skill/cleaning, round(C.beauty/CLEAN_SKILL_BEAUTY_ADJUSTMENT))
- qdel(C)
+ if(user && isturf(target))
+ for(var/obj/effect/decal/cleanable/cleanable_decal in target)
+ user.mind.adjust_experience(/datum/skill/cleaning, round(cleanable_decal.beauty / CLEAN_SKILL_BEAUTY_ADJUSTMENT))
+ target.wash(CLEAN_SCRUB)
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
user?.mind.adjust_experience(/datum/skill/cleaning, CLEAN_SKILL_GENERIC_WASH_XP)
decreaseUses(user)
return
diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm
index 141b759860f..e5bbc475c47 100644
--- a/code/game/objects/items/mop.dm
+++ b/code/game/objects/items/mop.dm
@@ -26,12 +26,10 @@
/obj/item/mop/proc/clean(turf/A, mob/living/cleaner)
if(reagents.has_reagent(/datum/reagent/water, 1) || reagents.has_reagent(/datum/reagent/water/holywater, 1) || reagents.has_reagent(/datum/reagent/consumable/ethanol/vodka, 1) || reagents.has_reagent(/datum/reagent/space_cleaner, 1))
- SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
- for(var/obj/effect/O in A)
- if(is_cleanable(O))
- var/obj/effect/decal/cleanable/C = O
- cleaner?.mind.adjust_experience(/datum/skill/cleaning, max(round(C.beauty/CLEAN_SKILL_BEAUTY_ADJUSTMENT,1),0)) //it is intentional that the mop rounds xp but soap does not, USE THE SACRED TOOL
- qdel(O)
+ for(var/obj/effect/decal/cleanable/cleanable_decal in A)
+ cleaner?.mind.adjust_experience(/datum/skill/cleaning, max(round(cleanable_decal.beauty / CLEAN_SKILL_BEAUTY_ADJUSTMENT, 1), 0)) //it is intentional that the mop rounds xp but soap does not, USE THE SACRED TOOL
+ A.wash(CLEAN_SCRUB)
+
reagents.expose(A, TOUCH, 10) //Needed for proper floor wetting.
var/val2remove = 1
if(cleaner?.mind)
diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm
index b49c68b528c..998a0d581e2 100644
--- a/code/game/objects/structures/shower.dm
+++ b/code/game/objects/structures/shower.dm
@@ -98,7 +98,9 @@
wash_atom(AM)
/obj/machinery/shower/proc/wash_atom(atom/A)
- A.washed(src)
+ A.wash(CLEAN_RAD | CLEAN_TYPE_WEAK) // Clean radiation non-instantly
+ A.wash(CLEAN_WASH)
+ SEND_SIGNAL(A, COMSIG_ADD_MOOD_EVENT, "shower", /datum/mood_event/nice_shower)
reagents.expose(A, TOUCH, reaction_volume)
if(isliving(A))
@@ -107,8 +109,10 @@
/obj/machinery/shower/process()
if(on)
wash_atom(loc)
- for(var/AM in loc)
- wash_atom(AM)
+ for(var/am in loc)
+ var/atom/movable/movable_content = am
+ if(!ismopable(movable_content)) // Mopables will be cleaned anyways by the turf wash above
+ wash_atom(movable_content)
else
return PROCESS_KILL
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 877c79eec3c..08e3c343859 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -279,21 +279,20 @@
busy = FALSE
+ if(washing_face)
+ SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_FACE_ACT, CLEAN_WASH)
+ user.drowsyness = max(user.drowsyness - rand(2,3), 0) //Washing your face wakes you up if you're falling asleep
+ else if(ishuman(user))
+ var/mob/living/carbon/human/human_user = user
+ if(!human_user.wash_hands(CLEAN_WASH))
+ to_chat(user, "Your hands are covered by something!")
+ return
+ else
+ user.wash(CLEAN_WASH)
+
user.visible_message("[user] washes [user.p_their()] [washing_face ? "face" : "hands"] using [src].", \
"You wash your [washing_face ? "face" : "hands"] using [src].")
-
- if(washing_face)
- SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_FACE_ACT, CLEAN_STRENGTH_BLOOD)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- H.lip_style = null //Washes off lipstick
- H.lip_color = initial(H.lip_color)
- H.regenerate_icons()
- user.drowsyness = max(user.drowsyness - rand(2,3), 0) //Washing your face wakes you up if you're falling asleep
- else
- user.washed(src)
-
/obj/structure/sink/attackby(obj/item/O, mob/living/user, params)
if(busy)
to_chat(user, "Someone's already washing here!")
@@ -357,7 +356,7 @@
busy = FALSE
return 1
busy = FALSE
- O.washed(src)
+ O.wash(CLEAN_WASH)
O.acid_level = 0
create_reagents(5)
reagents.add_reagent(dispensedreagent, 5)
diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm
index f68cee68ad8..5d71aae6741 100644
--- a/code/game/turfs/open/_open.dm
+++ b/code/game/turfs/open/_open.dm
@@ -185,10 +185,12 @@
for(var/mob/living/simple_animal/slime/M in src)
M.apply_water()
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- for(var/obj/effect/O in src)
- if(is_cleanable(O))
- qdel(O)
+ wash(CLEAN_WASH)
+ for(var/am in src)
+ var/atom/movable/movable_content = am
+ if(ismopable(movable_content)) // Will have already been washed by the wash call above at this point.
+ continue
+ movable_content.wash(CLEAN_WASH)
return TRUE
/turf/open/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube, paralyze_amount, force_drop)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index b8a411aebc6..cb640fa7af0 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -559,3 +559,17 @@ GLOBAL_LIST_EMPTY(station_turfs)
for(var/reagent in reagents)
var/datum/reagent/R = reagent
. |= R.expose_turf(src, reagents[R])
+
+/**
+ * Called when this turf is being washed. Washing a turf will also wash any mopable floor decals
+ */
+/turf/wash(clean_types)
+ . = ..()
+
+ for(var/am in src)
+ if(am == src)
+ continue
+ var/atom/movable/movable_content = am
+ if(!ismopable(movable_content))
+ continue
+ movable_content.wash(clean_types)
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index 104a0172d1a..efb090c1490 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -11,14 +11,11 @@
strip_delay = 20
equip_delay_other = 40
-/obj/item/clothing/gloves/ComponentInitialize()
+/obj/item/clothing/gloves/wash(clean_types)
. = ..()
- RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
-
-/obj/item/clothing/gloves/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
- transfer_blood = 0
+ if((clean_types & CLEAN_TYPE_BLOOD) && transfer_blood > 0)
+ transfer_blood = 0
+ return TRUE
/obj/item/clothing/gloves/suicide_act(mob/living/carbon/user)
user.visible_message("\the [src] are forcing [user]'s hands around [user.p_their()] neck! It looks like the gloves are possessed!")
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 6ae00237f20..ef71a981b65 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -25,10 +25,6 @@
///any alerts we have active
var/obj/screen/alert/our_alert
-/obj/item/clothing/shoes/ComponentInitialize()
- . = ..()
- RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
-
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
if(rand(2)>1)
user.visible_message("[user] begins tying \the [src] up waaay too tightly! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -100,14 +96,16 @@
var/mob/M = loc
M.update_inv_shoes()
-/obj/item/clothing/shoes/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
+/obj/item/clothing/shoes/wash(clean_types)
+ . = ..()
+ if(!(clean_types & CLEAN_TYPE_BLOOD) || blood_state == BLOOD_STATE_NOT_BLOODY)
return
bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
blood_state = BLOOD_STATE_NOT_BLOODY
if(ismob(loc))
var/mob/M = loc
M.update_inv_shoes()
+ return TRUE
/obj/item/proc/negates_gravity()
return FALSE
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 29f64924c0e..0a08186cc83 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -77,13 +77,6 @@
playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing
update_icon()
-/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(isinhands)
- . = ..()
- if(!isinhands && !up)
- . += mutable_appearance('icons/mob/clothing/head.dmi', visor_icon)
- else
- cut_overlays()
-
/obj/item/clothing/head/helmet/space/plasmaman/update_overlays()
. = ..()
. += visor_icon
@@ -99,8 +92,7 @@
smile_color = CR.paint_color
to_chat(user, "You draw a smiley on the helmet visor.")
update_icon()
- return
- if(smile == TRUE)
+ else
to_chat(user, "Seems like someone already drew something on this helmet's visor!")
/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(isinhands)
@@ -114,15 +106,12 @@
else
cut_overlays()
-/obj/item/clothing/head/helmet/space/plasmaman/ComponentInitialize()
+/obj/item/clothing/head/helmet/space/plasmaman/wash(clean_types)
. = ..()
- RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/wipe_that_smile_off_your_face)
-
-///gets called when receiving the CLEAN_ACT signal from something, i.e soap or a shower. exists to remove any smiley faces drawn on the helmet.
-/obj/item/clothing/head/helmet/space/plasmaman/proc/wipe_that_smile_off_your_face()
- if(smile)
+ if(smile && (clean_types & CLEAN_TYPE_PAINT))
smile = FALSE
- cut_overlays()
+ update_icon()
+ return TRUE
/obj/item/clothing/head/helmet/space/plasmaman/attack_self(mob/user)
on = !on
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index fe519703671..98df8ad72d9 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -46,10 +46,10 @@
if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects
if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody
G.transfer_blood--
- else if(M.bloody_hands > 1)
+ else if(M.blood_in_hands > 1)
old = length(M.return_blood_DNA())
if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old)
- M.bloody_hands--
+ M.blood_in_hands--
var/datum/component/forensics/D = AddComponent(/datum/component/forensics)
. = D.add_fibers(M)
@@ -92,7 +92,7 @@
G.add_blood_DNA(blood_dna)
else if(length(blood_dna))
AddComponent(/datum/component/forensics, null, null, blood_dna)
- bloody_hands = rand(2, 4)
+ blood_in_hands = rand(2, 4)
update_inv_gloves() //handles bloody hands overlays and updating
return TRUE
diff --git a/code/modules/detectivework/footprints_and_rag.dm b/code/modules/detectivework/footprints_and_rag.dm
index e7e61f3e39b..aaaa1ad1bff 100644
--- a/code/modules/detectivework/footprints_and_rag.dm
+++ b/code/modules/detectivework/footprints_and_rag.dm
@@ -42,4 +42,4 @@
user.visible_message("[user] starts to wipe down [A] with [src]!", "You start to wipe down [A] with [src]...")
if(do_after(user,30, target = A))
user.visible_message("[user] finishes wiping off [A]!", "You finish wiping off [A].")
- SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ A.wash(CLEAN_SCRUB)
diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm
index e219f08e159..46688b5e97a 100644
--- a/code/modules/lighting/lighting_object.dm
+++ b/code/modules/lighting/lighting_object.dm
@@ -144,7 +144,7 @@
/atom/movable/lighting_object/onTransitZ()
return
-/atom/movable/lighting_object/washed(var/washer)
+/atom/movable/lighting_object/wash(clean_types)
return
// Override here to prevent things accidentally moving around overlays.
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index fc80e6f639f..83c370df242 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1106,35 +1106,50 @@
if(mood.sanity < SANITY_UNSTABLE)
return TRUE
-/mob/living/carbon/washed(var/atom/washer)
+/mob/living/carbon/wash(clean_types)
. = ..()
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "shower", /datum/mood_event/nice_shower)
- for(var/obj/item/I in held_items)
- I.washed(washer)
+ // Wash equipped stuff that cannot be covered
+ for(var/i in held_items)
+ var/obj/item/held_thing = i
+ if(held_thing.wash(clean_types))
+ . = TRUE
- if(back && back.washed(washer))
+ if(back?.wash(clean_types))
update_inv_back(0)
+ . = TRUE
+ if(head?.wash(clean_types))
+ update_inv_head()
+ . = TRUE
+
+ // Check and wash stuff that can be covered
var/list/obscured = check_obscured_slots()
- if(head && head.washed(washer))
- update_inv_head()
-
- if(glasses && !(ITEM_SLOT_EYES in obscured) && glasses.washed(washer))
+ // If the eyes are covered by anything but glasses, that thing will be covering any potential glasses as well.
+ if(glasses && is_eyes_covered(FALSE, TRUE, TRUE) && glasses.wash(clean_types))
update_inv_glasses()
+ . = TRUE
- if(wear_mask && !(ITEM_SLOT_MASK in obscured && wear_mask.washed(washer)))
+ if(wear_mask && !(ITEM_SLOT_MASK in obscured) && wear_mask.wash(clean_types))
update_inv_wear_mask()
+ . = TRUE
- if(ears && !(HIDEEARS in obscured) && ears.washed(washer))
+ if(ears && !(ITEM_SLOT_EARS in obscured) && ears.wash(clean_types))
update_inv_ears()
+ . = TRUE
- if(wear_neck && !(ITEM_SLOT_NECK in obscured) && wear_neck.washed(washer))
+ if(wear_neck && !(ITEM_SLOT_NECK in obscured) && wear_neck.wash(clean_types))
update_inv_neck()
+ . = TRUE
- if(shoes && !(HIDESHOES in obscured) && shoes.washed(washer))
+ if(shoes && !(ITEM_SLOT_FEET in obscured) && shoes.wash(clean_types))
update_inv_shoes()
+ . = TRUE
+
+ if(gloves && !(ITEM_SLOT_GLOVES in obscured) && gloves.wash(clean_types))
+ update_inv_gloves()
+ . = TRUE
/// if any of our bodyparts are bleeding
/mob/living/carbon/proc/is_bleeding()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 8b5ce86bc13..33828f2fc6c 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -18,7 +18,7 @@
. = ..()
- RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_blood)
+ RegisterSignal(src, COMSIG_COMPONENT_CLEAN_FACE_ACT, .proc/clean_face)
AddComponent(/datum/component/personal_crafting)
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_HUMAN, 1, 2)
GLOB.human_list += src
@@ -700,16 +700,82 @@
if(..())
dropItemToGround(I)
-/mob/living/carbon/human/proc/clean_blood(datum/source, strength)
- if(strength < CLEAN_STRENGTH_BLOOD)
- return
+/**
+ * Wash the hands, cleaning either the gloves if equipped and not obscured, otherwise the hands themselves if they're not obscured.
+ *
+ * Returns false if we couldn't wash our hands due to them being obscured, otherwise true
+ */
+/mob/living/carbon/human/proc/wash_hands(clean_types)
+ var/list/obscured = check_obscured_slots()
+ if(ITEM_SLOT_GLOVES in obscured)
+ return FALSE
+
if(gloves)
- if(SEND_SIGNAL(gloves, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- update_inv_gloves()
- else
- if(bloody_hands)
- bloody_hands = 0
+ if(gloves.wash(clean_types))
update_inv_gloves()
+ else if((clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0)
+ blood_in_hands = 0
+ update_inv_gloves()
+
+ return TRUE
+
+/**
+ * Cleans the lips of any lipstick. Returns TRUE if the lips had any lipstick and was thus cleaned
+ */
+/mob/living/carbon/human/proc/clean_lips()
+ if(isnull(lip_style) && lip_color == initial(lip_color))
+ return FALSE
+ lip_style = null
+ lip_color = initial(lip_color)
+ update_body()
+ return TRUE
+
+/**
+ * Called on the COMSIG_COMPONENT_CLEAN_FACE_ACT signal
+ */
+/mob/living/carbon/human/proc/clean_face(datum/source, clean_types)
+ if(!is_mouth_covered() && clean_lips())
+ . = TRUE
+
+ if(glasses && is_eyes_covered(FALSE, TRUE, TRUE) && glasses.wash(clean_types))
+ update_inv_glasses()
+ . = TRUE
+
+ var/list/obscured = check_obscured_slots()
+ if(wear_mask && !(ITEM_SLOT_MASK in obscured) && wear_mask.wash(clean_types))
+ update_inv_wear_mask()
+ . = TRUE
+
+/**
+ * Called when this human should be washed
+ */
+/mob/living/carbon/human/wash(clean_types)
+ . = ..()
+
+ // Wash equipped stuff that cannot be covered
+ if(wear_suit?.wash(clean_types))
+ update_inv_wear_suit()
+ . = TRUE
+
+ if(belt?.wash(clean_types))
+ update_inv_belt()
+ . = TRUE
+
+ // Check and wash stuff that can be covered
+ var/list/obscured = check_obscured_slots()
+
+ if(w_uniform && !(ITEM_SLOT_ICLOTHING in obscured) && w_uniform.wash(clean_types))
+ update_inv_w_uniform()
+ . = TRUE
+
+ if(!is_mouth_covered() && clean_lips())
+ . = TRUE
+
+ // Wash hands if exposed
+ if(!gloves && (clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0 && !(ITEM_SLOT_GLOVES in obscured))
+ blood_in_hands = 0
+ update_inv_gloves()
+ . = TRUE
//Turns a mob black, flashes a skeleton overlay
//Just like a cartoon!
@@ -1103,24 +1169,6 @@
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
-/mob/living/carbon/human/washed(var/atom/washer)
- . = ..()
- if(wear_suit && wear_suit.washed(washer))
- update_inv_wear_suit()
- else if(w_uniform && w_uniform.washed(washer))
- update_inv_w_uniform()
-
- if(!is_mouth_covered())
- lip_style = null
- update_body()
- if(belt && belt.washed(washer))
- update_inv_belt()
-
- var/list/obscured = check_obscured_slots()
-
- if(gloves && !(HIDEGLOVES in obscured) && gloves.washed(washer))
- update_inv_gloves()
-
/mob/living/carbon/human/adjust_nutrition(change) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
return FALSE
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index ac5e7db5041..144c6d936b6 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -64,3 +64,7 @@
var/hardcore_survival_score = 0
/// For agendered spessmen, which body type to use
var/body_type = MALE
+
+ /// How many "units of blood" we have on our hands
+ var/blood_in_hands = 0
+
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 92bd6b3ec4b..fe32c33cf0a 100644
--- a/code/modules/mob/living/carbon/human/human_update_icons.dm
+++ b/code/modules/mob/living/carbon/human/human_update_icons.dm
@@ -173,7 +173,7 @@ There are several things that need to be remembered:
var/obj/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_GLOVES) + 1]
inv.update_icon()
- if(!gloves && bloody_hands)
+ if(!gloves && blood_in_hands)
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER)
if(get_num_arms(FALSE) < 2)
if(has_left_hand(FALSE))
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 46ac45a68b3..c1c5b14182d 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1167,11 +1167,6 @@
//Mobs on Fire end
-//Washing
-/mob/living/washed(var/atom/washer)
- . = ..()
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
-
// used by secbot and monkeys Crossed
/mob/living/proc/knockOver(var/mob/living/carbon/C)
if(C.key) //save us from monkey hordes
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index 9ec194dce53..89fdd74fe19 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -312,18 +312,14 @@
target_types = typecacheof(target_types)
/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A)
- if(is_cleanable(A))
+ if(ismopable(A))
icon_state = "cleanbot-c"
mode = BOT_CLEANING
var/turf/T = get_turf(A)
if(do_after(src, 1, target = T))
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ T.wash(CLEAN_WASH)
visible_message("[src] cleans \the [T].")
- for(var/atom/dirtything in T)
- if(is_cleanable(dirtything))
- qdel(dirtything)
-
target = null
mode = BOT_IDLE
diff --git a/code/modules/mob/living/simple_animal/bot/hygienebot.dm b/code/modules/mob/living/simple_animal/bot/hygienebot.dm
index ed4a8aba02d..4c476ef2148 100644
--- a/code/modules/mob/living/simple_animal/bot/hygienebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/hygienebot.dm
@@ -234,7 +234,7 @@ Maintenance panel is [open ? "opened" : "closed"]"}
if(emagged)
A.fire_act() //lol pranked no cleaning besides that
else
- A.washed(src)
+ A.wash(CLEAN_WASH)
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 1030ba9fd09..b9a4407a57e 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -177,11 +177,9 @@
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
if(ismovable(target))
+ target.wash(CLEAN_WASH)
if(istype(target, /obj/effect/decal/cleanable))
visible_message("[src] cleans up \the [target].")
- qdel(target)
- return TRUE
- var/atom/movable/M = target
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- visible_message("[src] polishes \the [target].")
+ else
+ visible_message("[src] polishes \the [target].")
return TRUE
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index e07f93fef57..d6b6e4839df 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -205,8 +205,6 @@
var/datum/h_sandbox/sandbox = null
- var/bloody_hands = 0
-
var/datum/focus //What receives our keyboard inputs. src by default
/// Used for tracking last uses of emotes for cooldown purposes
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 9f46d5ec43f..cd42a1a1c5c 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1063,55 +1063,26 @@
color = "#A5F0EE" // rgb: 165, 240, 238
taste_description = "sourness"
reagent_weight = 0.6 //so it sprays further
+ var/clean_types = CLEAN_WASH
/datum/reagent/space_cleaner/expose_obj(obj/O, reac_volume)
- if(istype(O, /obj/effect/decal/cleanable))
- qdel(O)
- else
- if(O)
- O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ O?.wash(clean_types)
/datum/reagent/space_cleaner/expose_turf(turf/T, reac_volume)
if(reac_volume >= 1)
- T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- for(var/obj/effect/decal/cleanable/C in T)
- qdel(C)
+ T.wash(clean_types)
+ for(var/am in T)
+ var/atom/movable/movable_content
+ if(ismopable(movable_content)) // Mopables will be cleaned anyways by the turf wash
+ continue
+ movable_content.wash(clean_types)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(5,10))
/datum/reagent/space_cleaner/expose_mob(mob/living/M, method=TOUCH, reac_volume)
if(method == TOUCH || method == VAPOR)
- M.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(H.lip_style)
- H.lip_style = null
- H.update_body()
- for(var/obj/item/I in C.held_items)
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(C.wear_mask)
- if(SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- C.update_inv_wear_mask()
- if(ishuman(M))
- var/mob/living/carbon/human/H = C
- if(H.head)
- if(SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- H.update_inv_head()
- if(H.wear_suit)
- if(SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- H.update_inv_wear_suit()
- else if(H.w_uniform)
- if(SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- H.update_inv_w_uniform()
- if(H.shoes)
- if(SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
- H.update_inv_shoes()
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ M.wash(clean_types)
/datum/reagent/space_cleaner/ez_clean
name = "EZ Clean"