Audits wash/cleaning signals + refactors wash() to ensure no needless mob updates occur (#91259)

## About The Pull Request

This has the potential to create a lot of needless mob updates which is
not great. Now should only update a mob's clothing if it was actually
washed.

This PR

1) ensures that all wash() procs return a bitflag.
2) ensures that `wash()` proccalls which result in expensive operations
like icon updates only do so when it is necessary

## Why It's Good For The Game

Updating mob sprites is expensive, and doing it when nothing has been
changed is bad.

## Changelog

Nothing really player facing
This commit is contained in:
Bloop
2025-06-02 18:54:53 +00:00
committed by GitHub
parent 300087a3aa
commit 2bae025bfe
48 changed files with 156 additions and 79 deletions
@@ -4,6 +4,8 @@
#define COMSIG_COMPONENT_CLEAN_ACT "clean_act"
///Returned by cleanable components when they are cleaned.
#define COMPONENT_CLEANED (1<<0)
///Returned by cleanable components when they are cleaned and give xp for it.
#define COMPONENT_CLEANED_GAIN_XP (1<<1)
// Vacuum signals
/// Called on a bag being attached to a vacuum parent
+1 -1
View File
@@ -223,7 +223,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!(clean_types & CLEAN_TYPE_ACID))
return NONE
qdel(src)
return COMPONENT_CLEANED
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/// Handles water diluting the acid on the object.
/datum/component/acid/proc/on_expose_reagent(atom/parent_atom, datum/reagent/exposing_reagent, reac_volume, methods)
+4 -2
View File
@@ -259,8 +259,10 @@
return NONE
total_bloodiness = 0
update_icon()
return COMPONENT_CLEANED
var/obj/item/clothing/shoes/parent_shoes = parent
if(!istype(parent_shoes)) // if we are wearing shoes, wash() will already be calling update_worn_shoes() so we don't have to do it twice
update_icon()
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/**
* Like its parent but can be applied to carbon mobs instead of clothing items
+4
View File
@@ -133,6 +133,8 @@
/datum/component/clothing_dirt/proc/on_clean(datum/source, clean_types)
SIGNAL_HANDLER
. = NONE
var/obj/item/clothing/clothing = parent
var/mob/living/carbon/wearer
if(iscarbon(clothing.loc))
@@ -143,3 +145,5 @@
dirtiness = 0
if(!isnull(wearer))
wearer.update_tint()
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
+1 -1
View File
@@ -95,7 +95,7 @@
return NONE
qdel(src)
return COMPONENT_CLEANED
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/// Ensures normal_overlay overlay in case the mob is not a carbon
/datum/component/face_decal/proc/update_overlays(atom/parent_atom, list/overlays)
@@ -121,6 +121,9 @@ GLOBAL_LIST_INIT(floor_diseases, list(
/datum/component/germ_sensitive/proc/delete_germs()
SIGNAL_HANDLER
. = NONE
if(infective)
infective = FALSE
qdel(parent.GetComponent(/datum/component/infective))
+2 -1
View File
@@ -71,10 +71,11 @@
var/mob/living/living_parent = parent
if (living_parent.stat != CONSCIOUS)
return
return NONE
COOLDOWN_START(src, groom_cooldown, GROOM_COOLDOWN)
increase_happiness_level(on_groom_change)
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/datum/component/happiness/proc/on_petted(datum/source, mob/living/petter, list/modifiers)
SIGNAL_HANDLER
+1 -1
View File
@@ -133,7 +133,7 @@
. = NONE
if(clean_types & required_clean_types)
qdel(src)
return COMPONENT_CLEANED
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/datum/component/infective/proc/try_infect_buckle(datum/source, mob/M, force)
SIGNAL_HANDLER
+2 -2
View File
@@ -168,11 +168,11 @@
SIGNAL_HANDLER
if (!(clean_types & CLEAN_TYPE_RADIATION))
return
return NONE
if (isitem(parent))
qdel(src)
return COMPONENT_CLEANED
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
COOLDOWN_START(src, clean_cooldown, RADIATION_CLEAN_IMMUNITY_TIME)
+3 -1
View File
@@ -111,9 +111,11 @@
/datum/component/sticker/proc/on_clean(datum/source, clean_types)
SIGNAL_HANDLER
. = NONE
peel()
return COMPONENT_CLEANED
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/datum/component/sticker/proc/on_turf_expose(datum/source, datum/gas_mixture/air, exposed_temperature)
SIGNAL_HANDLER
+2
View File
@@ -147,6 +147,8 @@
/datum/component/thermite/proc/clean_react(datum/source, strength)
SIGNAL_HANDLER
. = NONE
//Thermite is just some loose powder, you could probably clean it with your hands
qdel(src)
+1 -1
View File
@@ -139,7 +139,7 @@
if(clean_types & cleanable)
Detach(source)
return COMPONENT_CLEANED
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
return NONE
/datum/element/decal/proc/examine(datum/source, mob/user, list/examine_list)
@@ -865,8 +865,11 @@
/datum/status_effect/ants/proc/ants_washed()
SIGNAL_HANDLER
owner.remove_status_effect(/datum/status_effect/ants)
return COMPONENT_CLEANED
. = NONE
if(owner.remove_status_effect(/datum/status_effect/ants))
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/datum/status_effect/ants/get_examine_text()
return span_warning("[owner.p_They()] [owner.p_are()] covered in ants!")
@@ -29,7 +29,10 @@
///Handles the source of the pheromones getting deleted, or the owner getting washed
/datum/status_effect/slime_food/proc/on_feeder_deleted(datum/source)
SIGNAL_HANDLER
. = NONE
qdel(src)
return COMPONENT_CLEANED
///Gaze upon the target
/datum/status_effect/slime_food/proc/on_examine(datum/source, mob/user, list/examine_list)
+6 -4
View File
@@ -567,17 +567,19 @@
* Returns true if any washing was necessary and thus performed
* Arguments:
* * clean_types: any of the CLEAN_ constants
* Returns: A bitflag if it successfully cleaned something: e.g. COMPONENT_CLEANED, or NONE if not. COMPONENT_CLEANED_GAIN_XP being flipped on signals whether the cleaning should yield cleaning xp.
*/
/atom/proc/wash(clean_types)
SHOULD_CALL_PARENT(TRUE)
if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types) & COMPONENT_CLEANED)
return TRUE
. = SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types)
if(.)
return
// 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
return FALSE
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
return NONE
///Where atoms should drop if taken from this atom
/atom/proc/drop_location()
+1 -1
View File
@@ -109,7 +109,7 @@
cut_overlays()
return ITEM_INTERACT_SUCCESS
/obj/machinery/medipen_refiller/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
/obj/machinery/medipen_refiller/plunger_act(obj/item/plunger/attacking_plunger, mob/living/user, reinforced)
user.balloon_alert_to_viewers("furiously plunging...", "plunging medipen refiller...")
if(do_after(user, 3 SECONDS, target = src))
user.balloon_alert_to_viewers("finished plunging")
+1 -1
View File
@@ -212,7 +212,7 @@ GLOBAL_LIST_INIT(dye_registry, list(
if(!busy && bloody_mess && (clean_types & CLEAN_TYPE_BLOOD))
bloody_mess = FALSE
update_appearance()
. = TRUE
. |= COMPONENT_CLEANED
/obj/machinery/washing_machine/proc/wash_cycle(mob/user)
for(var/X in contents)
@@ -61,9 +61,9 @@
/obj/effect/decal/cleanable/wash(clean_types)
. = ..()
if (. || (clean_types & clean_type))
if (. || clean_types & clean_type)
qdel(src)
return TRUE
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/obj/effect/decal/cleanable/proc/handle_merge_decal(obj/effect/decal/cleanable/merger)
if (!reagents && !decal_reagent)
+2
View File
@@ -1428,6 +1428,8 @@
// Update icons if this is being carried by a mob
/obj/item/wash(clean_types)
. = ..()
if(!.) // we don't need mob updates when the item was already clean
return
if(ismob(loc))
var/mob/mob_loc = loc
mob_loc.update_clothing(slot_flags)
+2 -2
View File
@@ -187,8 +187,8 @@
else
return ..()
/obj/item/extinguisher/attack_atom(obj/O, mob/living/user, list/modifiers, list/attack_modifiers)
if(AttemptRefill(O, user))
/obj/item/extinguisher/attack_atom(obj/attacked_obj, mob/living/user, list/modifiers, list/attack_modifiers)
if(AttemptRefill(attacked_obj, user))
refilling = TRUE
return FALSE
else
+1 -1
View File
@@ -223,7 +223,7 @@
/obj/effect/decal/cleanable/traitor_rune/wash(clean_types)
if (clean_proof)
return FALSE
return NONE
return ..()
@@ -249,21 +249,24 @@
/obj/item/gun_control/CanItemAutoclick()
return TRUE
/obj/item/gun_control/attack_atom(obj/O, mob/living/user, list/modifiers, list/attack_modifiers)
/obj/item/gun_control/attack_atom(obj/attacked_obj, mob/living/user, list/modifiers, list/attack_modifiers)
user.changeNext_move(CLICK_CD_MELEE)
O.attacked_by(src, user, modifiers)
attacked_obj.attacked_by(src, user, modifiers)
/obj/item/gun_control/attack(mob/living/M, mob/living/user, list/modifiers, list/attack_modifiers)
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
M.attacked_by(src, user, modifiers)
/obj/item/gun_control/attack(mob/living/target_mob, mob/living/user, list/modifiers, list/attack_modifiers)
target_mob.lastattacker = user.real_name
target_mob.lastattackerckey = user.ckey
target_mob.attacked_by(src, user, modifiers)
add_fingerprint(user)
/obj/item/gun_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
var/obj/machinery/deployable_turret/E = user.buckled
E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, interacting_with, modifiers)
E.direction_track(user, interacting_with)
E.checkfire(interacting_with, user)
var/obj/machinery/deployable_turret/buckled_turret = user.buckled
if(!istype(buckled_turret))
return NONE
buckled_turret.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, interacting_with, modifiers)
buckled_turret.direction_track(user, interacting_with)
buckled_turret.checkfire(interacting_with, user)
return ITEM_INTERACT_SUCCESS
/obj/item/gun_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
return ranged_interact_with_atom(interacting_with, user, modifiers)
@@ -143,12 +143,12 @@
///What layer we set it to
var/target_layer = DUCT_LAYER_DEFAULT
/obj/item/plunger/attack_atom(obj/O, mob/living/user, list/modifiers, list/attack_modifiers)
/obj/item/plunger/attack_atom(obj/attacked_obj, mob/living/user, list/modifiers, list/attack_modifiers)
if(layer_mode)
SEND_SIGNAL(O, COMSIG_MOVABLE_CHANGE_DUCT_LAYER, O, target_layer)
SEND_SIGNAL(attacked_obj, COMSIG_MOVABLE_CHANGE_DUCT_LAYER, attacked_obj, target_layer)
return ..()
else
if(!O.plunger_act(src, user, reinforced))
if(!attacked_obj.plunger_act(src, user, reinforced))
return ..()
/obj/item/plunger/throw_impact(atom/hit_atom, datum/thrownthing/tt)
+7
View File
@@ -128,6 +128,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
to_chat(user, span_notice("The water temperature seems to be [current_temperature]."))
return TRUE
/obj/machinery/shower/plunger_act(obj/item/plunger/attacking_plunger, mob/living/user, reinforced)
user.balloon_alert_to_viewers("furiously plunging...", "plunging shower...")
if(do_after(user, 3 SECONDS, target = src))
user.balloon_alert_to_viewers("finished plunging")
reagents.expose(get_turf(src), TOUCH) //splash on the floor
reagents.clear_reagents()
/obj/machinery/shower/attackby(obj/item/tool, mob/user, list/modifiers, list/attack_modifiers)
if(istype(tool, /obj/item/stock_parts/water_recycler))
if(has_water_reclaimer)
+7 -3
View File
@@ -375,13 +375,17 @@
. = ..()
if(!(clean_types & CLEAN_SCRUB))
return
set_opacity(initial(opacity))
remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
var/initial_opacity = initial(opacity)
if(opacity != initial_opacity)
set_opacity(initial_opacity)
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
for(var/atom/movable/cleanables as anything in src)
if(cleanables == src)
continue
if(!cleanables.wash(clean_types))
var/cleanable_washed = cleanables.wash(clean_types)
if(!cleanable_washed)
continue
. |= cleanable_washed
vis_contents -= cleanables
/obj/structure/window/Destroy()
+1 -1
View File
@@ -712,7 +712,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
. = ..()
for(var/atom/movable/to_clean as anything in src)
if(all_contents || HAS_TRAIT(to_clean, TRAIT_MOPABLE))
to_clean.wash(clean_types)
. |= to_clean.wash(clean_types)
/turf/set_density(new_value)
var/old_density = density
+6 -6
View File
@@ -112,15 +112,15 @@
visible_message(span_warning("[src] burns up in a sinister flash, taking an evil energy with it..."))
burn()
/obj/item/coupon/attack_atom(obj/O, mob/living/user, list/modifiers, list/attack_modifiers)
if(!istype(O, /obj/machinery/computer/cargo))
/obj/item/coupon/attack_atom(obj/attacked_obj, mob/living/user, list/modifiers, list/attack_modifiers)
if(!istype(attacked_obj, /obj/machinery/computer/cargo))
return ..()
if(discount_pct_off == COUPON_OMEN)
to_chat(user, span_warning("\The [O] validates the coupon as authentic, but refuses to accept it..."))
O.say("Coupon fulfillment already in progress...")
to_chat(user, span_warning("\The [attacked_obj] validates the coupon as authentic, but refuses to accept it..."))
attacked_obj.say("Coupon fulfillment already in progress...")
return
inserted_console = O
inserted_console = attacked_obj
LAZYADD(inserted_console.loaded_coupons, src)
inserted_console.say("Coupon for [initial(discounted_pack.name)] applied!")
forceMove(inserted_console)
@@ -129,4 +129,4 @@
if(inserted_console)
LAZYREMOVE(inserted_console.loaded_coupons, src)
inserted_console = null
. = ..()
return ..()
+1 -1
View File
@@ -38,7 +38,7 @@
. = ..()
if((clean_types & CLEAN_TYPE_BLOOD) && transfer_blood > 0)
transfer_blood = 0
return TRUE
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/obj/item/clothing/gloves/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("\the [src] are forcing [user]'s hands around [user.p_their()] neck! It looks like the gloves are possessed!"))
@@ -81,12 +81,16 @@
/obj/item/clothing/gloves/color/yellow/sprayon/proc/use_charge()
SIGNAL_HANDLER
. = NONE
charges_remaining--
if(charges_remaining <= 0)
var/turf/location = get_turf(src)
location.visible_message(span_warning("[src] crumble[p_s()] away into nothing.")) // just like my dreams after working with .dm
qdel(src)
. |= COMPONENT_CLEANED
/obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap
desc = "These gloves are cheap knockoffs of the coveted ones - no way this can end badly."
name = "budget insulated gloves"
@@ -191,11 +191,12 @@
. += smiley
/obj/item/clothing/head/helmet/space/plasmaman/wash(clean_types)
. = ..()
. = NONE
if(smile && (clean_types & CLEAN_TYPE_HARD_DECAL))
smile = FALSE
update_appearance()
return TRUE
update_appearance(UPDATE_OVERLAYS)
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
. |= ..()
/obj/item/clothing/head/helmet/space/plasmaman/attack_self(mob/user)
helmet_on = !helmet_on
@@ -250,5 +250,10 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list(
return ..()
/obj/machinery/deepfryer/proc/on_cleaned(obj/source_component, obj/source)
SIGNAL_HANDLER
. = NONE
grease_level = 0
update_appearance(UPDATE_OVERLAYS)
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
@@ -304,5 +304,10 @@
victim.gib(DROP_ALL_REMAINS)
/obj/machinery/gibber/proc/on_cleaned(obj/source_component, obj/source)
SIGNAL_HANDLER
. = NONE
dirty = FALSE
update_appearance(UPDATE_OVERLAYS)
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
@@ -552,7 +552,7 @@
dirty = 0
update_appearance()
return . || TRUE
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
/obj/machinery/microwave/proc/eject()
var/atom/drop_loc = drop_location()
+16 -6
View File
@@ -73,29 +73,39 @@
/// Empties the fingerprints list
/datum/forensics/proc/wipe_fingerprints()
if(isnull(fingerprints))
return NONE
fingerprints = null
return TRUE
return COMPONENT_CLEANED
/// Empties the blood_DNA list
/datum/forensics/proc/wipe_blood_DNA()
if(isnull(blood_DNA))
return NONE
blood_DNA = null
return TRUE
return COMPONENT_CLEANED
/// Empties the fibers list
/datum/forensics/proc/wipe_fibers()
if(isnull(fibers))
return NONE
fibers = null
return TRUE
return COMPONENT_CLEANED
/// Handles cleaning up the various forensic types
/datum/forensics/proc/clean_act(datum/source, clean_types)
SIGNAL_HANDLER
. = NONE
if(clean_types & CLEAN_TYPE_FINGERPRINTS)
wipe_fingerprints()
. |= wipe_fingerprints()
if(clean_types & CLEAN_TYPE_BLOOD)
wipe_blood_DNA()
. |= wipe_blood_DNA()
if(clean_types & CLEAN_TYPE_FIBERS)
wipe_fibers()
. |= wipe_fibers()
/// Adds the given list into fingerprints
/datum/forensics/proc/add_fingerprint_list(list/fingerprints)
@@ -137,8 +137,10 @@
/// When you are cleaned, wash off the buff
/datum/status_effect/stacking/brimdust_coating/proc/on_cleaned()
SIGNAL_HANDLER
owner.remove_status_effect(/datum/status_effect/stacking/brimdust_coating)
return COMPONENT_CLEANED
. = NONE
if(owner.remove_status_effect(/datum/status_effect/stacking/brimdust_coating))
. |= COMPONENT_CLEANED
/// When you take brute damage, schedule an explosion
/datum/status_effect/stacking/brimdust_coating/proc/on_take_damage(datum/source, damage, damagetype, ...)
@@ -123,7 +123,6 @@
for(var/mob/living/carbon/human in loc)
commence_wash(human)
/mob/living/basic/bot/hygienebot/proc/generate_ai_speech()
ai_controller.set_blackboard_key(BB_WASH_FOUND, found_announcements)
ai_controller.set_blackboard_key(BB_WASH_THREATS, threat_announcements)
@@ -48,8 +48,8 @@
if(atom_integrity < 90)
Die()
/obj/item/clothing/mask/facehugger/attackby(obj/item/O, mob/user, list/modifiers, list/attack_modifiers)
return O.attack_atom(src, user, modifiers)
/obj/item/clothing/mask/facehugger/attackby(obj/item/attacked_item, mob/user, list/modifiers, list/attack_modifiers)
return attacked_item.attack_atom(src, user, modifiers)
/obj/item/clothing/mask/facehugger/proc/react_to_mob(datum/source, mob/user)
SIGNAL_HANDLER
+1 -2
View File
@@ -1127,8 +1127,7 @@
. = ..()
// Wash equipped stuff that cannot be covered
for(var/obj/item/held_thing in held_items)
if(held_thing.wash(clean_types))
. = TRUE
. |= held_thing.wash(clean_types)
// Check and wash stuff that isn't covered
var/covered = check_covered_slots()
@@ -593,8 +593,7 @@
return FALSE
if(gloves)
if(gloves.wash(clean_types))
update_worn_gloves()
gloves.wash(clean_types)
else if((clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0)
blood_in_hands = 0
update_worn_gloves()
@@ -622,13 +621,13 @@
/mob/living/carbon/human/wash(clean_types)
. = ..()
if(!is_mouth_covered() && clean_lips())
. = TRUE
. |= COMPONENT_CLEANED
// Wash hands if exposed
if(!gloves && (clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0 && !(check_covered_slots() & ITEM_SLOT_GLOVES))
blood_in_hands = 0
update_worn_gloves()
. = TRUE
. |= COMPONENT_CLEANED
//Turns a mob black, flashes a skeleton overlay
//Just like a cartoon!
@@ -175,10 +175,12 @@ GLOBAL_LIST_EMPTY(virtual_pets_list)
/datum/computer_file/program/virtual_pet/proc/post_cleaned(mob/source, mob/user)
SIGNAL_HANDLER
. = NONE
source.spin(spintime = 2 SECONDS, speed = 1) //celebrate!
happiness = min(happiness + PET_CLEAN_BONUS, max_happiness)
COOLDOWN_START(src, on_clean_cooldown, 1 MINUTES)
START_PROCESSING(SSprocessing, src)
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
///manage the pet's hat offsets when he changes direction
/datum/computer_file/program/virtual_pet/proc/on_change_dir(datum/source, old_dir, new_dir)
@@ -96,7 +96,7 @@
return ITEM_INTERACT_BLOCKING
/obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
/obj/machinery/plumbing/plunger_act(obj/item/plunger/attacking_plunger, mob/living/user, reinforced)
user.balloon_alert_to_viewers("furiously plunging...")
if(do_after(user, 3 SECONDS, target = src))
user.balloon_alert_to_viewers("finished plunging")
+1 -1
View File
@@ -23,7 +23,7 @@
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/iv_drip/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
/obj/machinery/iv_drip/plumbing/plunger_act(obj/item/plunger/attacking_plunger, mob/living/user, reinforced)
user.balloon_alert_to_viewers("furiously plunging...", "plunging iv drip...")
if(do_after(user, 3 SECONDS, target = src))
user.balloon_alert_to_viewers("finished plunging")
+2 -2
View File
@@ -127,9 +127,9 @@
..()
shatter(M)
/obj/item/light/attack_atom(obj/O, mob/living/user, list/modifiers, list/attack_modifiers)
/obj/item/light/attack_atom(obj/attacked_obj, mob/living/user, list/modifiers, list/attack_modifiers)
..()
shatter(O)
shatter(attacked_obj)
/obj/item/light/proc/shatter(target)
if(status == LIGHT_OK || status == LIGHT_BURNED)
@@ -57,13 +57,14 @@
/obj/item/reagent_containers/cup/glass/drinkingglass/proc/on_cleaned(obj/source_component, obj/source)
SIGNAL_HANDLER
if(!HAS_TRAIT(src, TRAIT_WAS_RENAMED))
return
return NONE
qdel(GetComponent(/datum/component/rename))
REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, SHAKER_LABEL_TRAIT)
name = initial(name)
desc = initial(desc)
update_appearance(UPDATE_NAME | UPDATE_DESC)
return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
//Shot glasses!//
// This lets us add shots in here instead of lumping them in with drinks because >logic //
@@ -204,8 +204,10 @@
. = ..()
if(!(clean_types & CLEAN_TYPE_BLOOD))
return
blood_level = 0
update_appearance()
if(blood_level)
blood_level = 0
update_appearance()
. |= COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP
///Checks whether or not we should clean.
/obj/item/rag/proc/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner)
+8 -3
View File
@@ -947,7 +947,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)
if(is_creating && !(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
@@ -1019,11 +1019,16 @@
/// Called when limb's current owner gets washed
/obj/item/bodypart/proc/on_owner_clean(mob/living/carbon/source, clean_types)
SIGNAL_HANDLER
wash(clean_types)
. = NONE
if(wash(clean_types))
. |= COMPONENT_CLEANED
/obj/item/bodypart/wash(clean_types)
. = ..()
if(!.) // Already clean. Nothing to do here.
return
// always add the original dna to the organ after it's washed
if(IS_ORGANIC_LIMB(src) && (clean_types & CLEAN_TYPE_BLOOD))
add_blood_DNA(blood_dna_info)
+2 -1
View File
@@ -137,7 +137,8 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
/obj/item/organ/wash(clean_types)
. = ..()
if(!.)
return
// always add the original dna to the organ after it's washed
if(!IS_ROBOTIC_ORGAN(src) && (clean_types & CLEAN_TYPE_BLOOD))
add_blood_DNA(blood_dna_info)
+2
View File
@@ -40,4 +40,6 @@
/datum/unit_test/washing/proc/clean_caught(...)
SIGNAL_HANDLER
clean_sig_caught += 1
return COMPONENT_CLEANED