Adding space cleaner or water to a rag will consume as you clean to keep it fresher for longer (#91239)

## About The Pull Request

Follow up to #90700 because I had some ideas to expand upon it after the
fact

- Removes some now dead code in the sink. It can't reach these anymore
AFAIK.

- Makes use of the new blood helper.

- You can use spray bottles directly on rags and it will transfer
reagents from the spray to the rag.

- Rags with space cleaner in them will be more effective at cleaning
messes - the cleaner will be consumed to avoid bloodying the rag
entirely, allowing you to clean longer without needing to refresh the
rag.
- This is slightly more effective than just using space cleaner spray
alone in some situations (cleaning up footsteps), but slightly less
effective in others (full on pools of blood).
- Other "cleaning" reagents like Water will also have this effect, but
drastically weaker than space cleaner.

## Why It's Good For The Game

Being able to combine cleaning types is (kind of) the pinnacle of
janitor gameplay. I'm sure every janitor has had the epiphany that a mop
bucket full of space cleaner could be awesome, for example.

So thought "how do people ACTUALLY use rags? with a cleaning agent" - I
figured people spritzing a rag before wiping stuff down would pretty
easily transfer to SS13

## Changelog

🆑 Melbert
add: Adding Space Cleaner or Water to a rag will consume it as you clean
to keep the rag fresher for longer.
add: You can spray a rag with a spray bottle directly to transfer
reagents over.
/🆑
This commit is contained in:
MrMelbert
2025-05-20 21:19:15 -04:00
committed by GitHub
parent 7b2d129889
commit 315e84bca2
2 changed files with 55 additions and 19 deletions
@@ -162,20 +162,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sink, (-14))
to_chat(user, span_notice("You remove the water reclaimer from [src]"))
return
if(istype(O, /obj/item/stack/medical/gauze))
var/obj/item/stack/medical/gauze/G = O
new /obj/item/rag(src.loc)
to_chat(user, span_notice("You tear off a strip of gauze and make a rag."))
G.use(1)
return
if(istype(O, /obj/item/stack/sheet/cloth))
var/obj/item/stack/sheet/cloth/cloth = O
new /obj/item/rag(loc)
to_chat(user, span_notice("You tear off a strip of cloth and make a rag."))
cloth.use(1)
return
if(istype(O, /obj/item/stack/ore/glass))
new /obj/item/stack/sheet/sandblock(loc)
to_chat(user, span_notice("You wet the sand in the sink and form it into a block."))
@@ -137,16 +137,44 @@
AddElement(/datum/element/reagents_exposed_on_fire)
AddElement(/datum/element/reagents_item_heatable)
/obj/item/rag/examine(mob/user)
. = ..()
. += span_notice("Adding [/datum/reagent/water::name] or [/datum/reagent/space_cleaner::name] to it would make it a fair bit better at scrubbing.")
switch(blood_level)
if(1 to 4)
. += span_info("The [name] is a bit dirty, but it should still be good for cleaning.")
if(5 to 9)
. += span_warning("This [name] is dirty! But it still probably has a few wipes left in it.")
if(10 to INFINITY)
. += span_warning("This [name] is filthy! I couldn't clean a thing with it!")
/obj/item/rag/pickup(mob/user)
. = ..()
if(prob(5 * blood_level))
bloody_holder(user)
/obj/item/rag/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(istype(tool, /obj/item/reagent_containers/spray))
if(tool.reagents.total_volume <= 0)
balloon_alert(user, "spray is empty!")
return ITEM_INTERACT_BLOCKING
if(reagents.holder_full())
balloon_alert(user, "[name] is full!")
return ITEM_INTERACT_BLOCKING
tool.reagents.trans_to(reagents, tool.reagents.total_volume, transferred_by = user)
balloon_alert(user, "[name] spritzed")
var/obj/item/reagent_containers/spray/spray = tool
playsound(src, spray.spray_sound, 33, TRUE, -6)
return ITEM_INTERACT_SUCCESS
return ..()
/obj/item/rag/proc/bloody_holder(mob/living/holder)
var/obj/item/clothing/gloves/gloves = holder.get_item_by_slot(ITEM_SLOT_GLOVES)
if(gloves)
gloves.add_blood_DNA(GET_ATOM_BLOOD_DNA(src))
holder.update_worn_gloves()
if(ishuman(holder))
var/mob/living/carbon/human/human_holder = holder
human_holder.add_blood_DNA_to_items(GET_ATOM_BLOOD_DNA(src), ITEM_SLOT_GLOVES)
else
holder.add_blood_DNA(GET_ATOM_BLOOD_DNA(src))
@@ -209,7 +237,9 @@
cleaned.add_blood_DNA(GET_ATOM_BLOOD_DNA(src))
// THEN increment blood level
if(length(all_cleaned[cleaned]))
blood_level += get_blood_level_of_movable(cleaned)
var/how_dirty = get_blood_level_of_movable(cleaned)
if(!remove_cleanable_reagents(how_dirty))
blood_level += how_dirty
// you didn't think you could "clean" a burning person and escape scot-free did you?
var/mob/living/living_cleaned = cleaned
if((cleaned.resistance_flags & ON_FIRE) || (istype(living_cleaned) && living_cleaned.on_fire))
@@ -223,7 +253,9 @@
if(prob(10 * blood_level))
bloody_holder(cleaner)
/// Checks an atom and returns how "dirty" it is scaled to our rag
/obj/item/rag/proc/get_blood_level_of_movable(atom/movable/what)
PRIVATE_PROC(TRUE)
if(istype(what, /obj/item/rag))
var/obj/item/rag/friend_rag = what
return friend_rag.blood_level
@@ -232,6 +264,24 @@
return round(mess.bloodiness / 20, 1)
return 1
/// Takes in a "dirty" amount and tries to "counteract" it with reagents, returning TRUE if successful
/obj/item/rag/proc/remove_cleanable_reagents(how_dirty = 1)
PRIVATE_PROC(TRUE)
var/amount_to_remove = how_dirty * 0.2
// cleaner is the best at scrubbing blood
if(reagents.has_reagent(/datum/reagent/space_cleaner, amount_to_remove, check_subtypes = TRUE))
reagents.remove_reagent(/datum/reagent/space_cleaner, amount_to_remove)
return TRUE
// rest of the stuff is generically worse
amount_to_remove = how_dirty * 1.2
for(var/datum/reagent/other_reagent as anything in reagents.reagent_list)
if((other_reagent.chemical_flags & REAGENT_CLEANS) && other_reagent.volume >= amount_to_remove)
reagents.remove_reagent(other_reagent, amount_to_remove)
return TRUE
return FALSE
/obj/item/rag/update_appearance(updates)
. = ..()
// v = green and blue color components (reduced as it gets dirtier)