diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 8548c284ced..60be4d01182 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -253,8 +253,6 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define ismecha(A) (istype(A, /obj/vehicle/sealed/mecha)) -#define ismopable(A) (A && ((PLANE_TO_TRUE(A.plane) == FLOOR_PLANE) ? (A.layer <= FLOOR_CLEAN_LAYER) : (A.layer <= GAME_CLEAN_LAYER))) //If something can be cleaned by floor-cleaning devices such as mops or clean bots - #define isorgan(A) (istype(A, /obj/item/organ)) #define isclothing(A) (istype(A, /obj/item/clothing)) diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 2c5d8722f11..35dd5cc35ce 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -156,9 +156,7 @@ #define CATWALK_LAYER (14 + TOPDOWN_LAYER) #define LOWER_RUNE_LAYER (15 + TOPDOWN_LAYER) #define RUNE_LAYER (16 + TOPDOWN_LAYER) -/// [GAME_CLEAN_LAYER] but for floors. -/// Basically any layer below this (numerically) is "on" a floor for the purposes of washing -#define FLOOR_CLEAN_LAYER (21 + TOPDOWN_LAYER) +#define CLEANABLE_FLOOR_OBJECT_LAYER (21 + TOPDOWN_LAYER) //Placeholders in case the game plane and possibly other things between it and the floor plane are ever made into topdown planes @@ -185,9 +183,7 @@ #define BOT_PATH_LAYER 2.497 #define LOW_OBJ_LAYER 2.5 #define HIGH_PIPE_LAYER 2.54 -// Anything above this layer is not "on" a turf for the purposes of washing -// I hate this life of ours -#define GAME_CLEAN_LAYER 2.55 +#define CLEANABLE_OBJECT_LAYER 2.55 #define TRAM_STRUCTURE_LAYER 2.57 #define TRAM_FLOOR_LAYER 2.58 #define TRAM_WALL_LAYER 2.59 @@ -201,6 +197,7 @@ #define DOOR_HELPER_LAYER 2.72 //keep this above DOOR_ACCESS_HELPER_LAYER and OPEN_DOOR_LAYER since the others tend to have tiny sprites that tend to be covered up. #define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible #define TABLE_LAYER 2.8 +#define GIB_LAYER 2.85 // sit on top of tables, but below machines #define BELOW_OBJ_LAYER 2.9 #define LOW_ITEM_LAYER 2.95 //#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index e868097b579..32718ae4784 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1401,4 +1401,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait given to atoms currently affected by projectile dampeners #define TRAIT_GOT_DAMPENED "got_dampened" +/// Apply to movables to say "hey, this movable is technically flat on the floor, so it'd be mopped up by a mop" +#define TRAIT_MOPABLE "mopable" + // END TRAIT DEFINES diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 318506f1f7a..cb180abf208 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -48,7 +48,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER, "TRAIT_COMBAT_MODE_SKIP_INTERACTION" = TRAIT_COMBAT_MODE_SKIP_INTERACTION, "TRAIT_DEL_ON_SPACE_DUMP" = TRAIT_DEL_ON_SPACE_DUMP, - "TRAIT_VALID_DNA_INFUSION" = TRAIT_VALID_DNA_INFUSION, "TRAIT_FROZEN" = TRAIT_FROZEN, "TRAIT_HAS_LABEL" = TRAIT_HAS_LABEL, "TRAIT_HEARING_SENSITIVE" = TRAIT_HEARING_SENSITIVE, @@ -57,34 +56,36 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_IRRADIATED" = TRAIT_IRRADIATED, "TRAIT_IS_AQUARIUM" = TRAIT_IS_AQUARIUM, "TRAIT_LAVA_IMMUNE" = TRAIT_LAVA_IMMUNE, + "TRAIT_MOPABLE" = TRAIT_MOPABLE, "TRAIT_MOVE_FLOATING" = TRAIT_MOVE_FLOATING, "TRAIT_MOVE_FLYING" = TRAIT_MOVE_FLYING, "TRAIT_MOVE_GROUND" = TRAIT_MOVE_GROUND, "TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING, "TRAIT_MOVE_UPSIDE_DOWN" = TRAIT_MOVE_UPSIDE_DOWN, - "TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING, "TRAIT_MOVE_UPSIDE_DOWN" = TRAIT_MOVE_UPSIDE_DOWN, + "TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING, + "TRAIT_NOT_BARFABLE" = TRAIT_NOT_BARFABLE, + "TRAIT_NOT_ENGRAVABLE" = TRAIT_NOT_ENGRAVABLE, "TRAIT_NO_FLOATING_ANIM" = TRAIT_NO_FLOATING_ANIM, "TRAIT_NO_MANIFEST_CONTENTS_ERROR" = TRAIT_NO_MANIFEST_CONTENTS_ERROR, "TRAIT_NO_MISSING_ITEM_ERROR" = TRAIT_NO_MISSING_ITEM_ERROR, "TRAIT_NO_THROW_HITPUSH" = TRAIT_NO_THROW_HITPUSH, - "TRAIT_NOT_BARFABLE" = TRAIT_NOT_BARFABLE, - "TRAIT_NOT_ENGRAVABLE" = TRAIT_NOT_ENGRAVABLE, "TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT" = TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT, "TRAIT_ON_HIT_EFFECT" = TRAIT_ON_HIT_EFFECT, "TRAIT_RUNECHAT_HIDDEN" = TRAIT_RUNECHAT_HIDDEN, "TRAIT_SCARY_FISHERMAN" = TRAIT_SCARY_FISHERMAN, "TRAIT_SECLUDED_LOCATION" = TRAIT_SECLUDED_LOCATION, + "TRAIT_SILENT_REACTIONS" = TRAIT_SILENT_REACTIONS, "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE, "TRAIT_SPELLS_TRANSFER_TO_LOC" = TRAIT_SPELLS_TRANSFER_TO_LOC, "TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH" = TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH, "TRAIT_TELEKINESIS_CONTROLLED" = TRAIT_TELEKINESIS_CONTROLLED, "TRAIT_UNDERFLOOR" = TRAIT_UNDERFLOOR, "TRAIT_UNIQUE_IMMERSE" = TRAIT_UNIQUE_IMMERSE, + "TRAIT_VALID_DNA_INFUSION" = TRAIT_VALID_DNA_INFUSION, "TRAIT_WADDLING" = TRAIT_WADDLING, "TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED, "TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE, - "TRAIT_SILENT_REACTIONS" = TRAIT_SILENT_REACTIONS, ), /datum/controller/subsystem/economy = list( "TRAIT_MARKET_CRASHING" = TRAIT_MARKET_CRASHING, diff --git a/code/datums/components/cleaner.dm b/code/datums/components/cleaner.dm index 7072f271c7a..035f0c054db 100644 --- a/code/datums/components/cleaner.dm +++ b/code/datums/components/cleaner.dm @@ -96,8 +96,8 @@ ADD_TRAIT(target, TRAIT_CURRENTLY_CLEANING, REF(src)) // We need to update our planes on overlay changes RegisterSignal(target, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(cleaning_target_moved)) - var/mutable_appearance/low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", GAME_CLEAN_LAYER, target, GAME_PLANE) - var/mutable_appearance/high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", GAME_CLEAN_LAYER, target, ABOVE_GAME_PLANE) + var/mutable_appearance/low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", CLEANABLE_OBJECT_LAYER, target, GAME_PLANE) + var/mutable_appearance/high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", CLEANABLE_OBJECT_LAYER, target, ABOVE_GAME_PLANE) var/list/icon_offsets = target.get_oversized_icon_offsets() low_bubble.pixel_x = icon_offsets["x"] low_bubble.pixel_y = icon_offsets["y"] @@ -140,13 +140,13 @@ if(same_z_layer) return // First, get rid of the old overlay - var/mutable_appearance/old_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", GAME_CLEAN_LAYER, old_turf, GAME_PLANE) - var/mutable_appearance/old_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", GAME_CLEAN_LAYER, old_turf, ABOVE_GAME_PLANE) + var/mutable_appearance/old_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", CLEANABLE_OBJECT_LAYER, old_turf, GAME_PLANE) + var/mutable_appearance/old_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", CLEANABLE_OBJECT_LAYER, old_turf, ABOVE_GAME_PLANE) source.cut_overlay(old_low_bubble) source.cut_overlay(old_high_bubble) // Now, add the new one - var/mutable_appearance/new_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", GAME_CLEAN_LAYER, new_turf, GAME_PLANE) - var/mutable_appearance/new_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", GAME_CLEAN_LAYER, new_turf, ABOVE_GAME_PLANE) + var/mutable_appearance/new_low_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", CLEANABLE_OBJECT_LAYER, new_turf, GAME_PLANE) + var/mutable_appearance/new_high_bubble = mutable_appearance('icons/effects/effects.dmi', "bubbles", CLEANABLE_OBJECT_LAYER, new_turf, ABOVE_GAME_PLANE) source.add_overlay(new_low_bubble) source.add_overlay(new_high_bubble) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 21eff5028b5..14e56b3ed69 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -1,6 +1,6 @@ /obj/effect/decal/cleanable gender = PLURAL - layer = FLOOR_CLEAN_LAYER + layer = CLEANABLE_FLOOR_OBJECT_LAYER var/list/random_icon_states = null ///I'm sorry but cleanable/blood code is ass, and so is blood_DNA var/blood_state = "" @@ -15,6 +15,9 @@ var/datum/reagent/decal_reagent ///The amount of reagent this decal holds, if decal_reagent is defined var/reagent_amount = 0 + /// If TRUE, gains TRAIT_MOPABLE on init - thus this cleanable will cleaned if its turf is cleaned + /// Set to FALSE for things that hang high on the walls or things which generally shouldn't be mopped up + var/is_mopped = 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 @@ -40,6 +43,9 @@ 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) diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index bc7923ac0ed..f2543f33c86 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -24,10 +24,12 @@ icon = 'icons/effects/blood.dmi' icon_state = "xgib1" plane = GAME_PLANE - layer = BELOW_OBJ_LAYER + layer = GIB_LAYER random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6") mergeable_decal = FALSE + is_mopped = TRUE // probably shouldn't be, but janitor powercreep + /obj/effect/decal/cleanable/xenoblood/xgibs/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index fcac7b06601..bf9493ac4fe 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -75,6 +75,7 @@ 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) @@ -111,7 +112,7 @@ desc = "They look bloody and gruesome." icon = 'icons/effects/blood.dmi' icon_state = "gib1" - layer = BELOW_OBJ_LAYER + layer = GIB_LAYER plane = GAME_PLANE random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") mergeable_decal = FALSE @@ -121,6 +122,8 @@ 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) @@ -356,6 +359,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) 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 diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index caf7428ef01..65d22c8d856 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -11,7 +11,7 @@ icon = 'icons/obj/debris.dmi' icon_state = "ash" plane = GAME_PLANE - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER mergeable_decal = FALSE beauty = -50 decal_reagent = /datum/reagent/ash @@ -153,6 +153,7 @@ resistance_flags = FLAMMABLE beauty = -100 clean_type = CLEAN_TYPE_HARD_DECAL + is_mopped = FALSE /obj/effect/decal/cleanable/cobweb/cobweb2 icon_state = "cobweb2" @@ -164,7 +165,7 @@ icon = 'icons/effects/effects.dmi' icon_state = "molten" plane = GAME_PLANE - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER mergeable_decal = FALSE beauty = -150 clean_type = CLEAN_TYPE_HARD_DECAL @@ -251,7 +252,7 @@ desc = "A pile of chemicals. You can't quite tell what's inside it." gender = NEUTER plane = GAME_PLANE - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER icon = 'icons/obj/debris.dmi' icon_state = "ash" @@ -330,7 +331,7 @@ icon = 'icons/obj/debris.dmi' icon_state = "paper_shreds" plane = GAME_PLANE - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER /obj/effect/decal/cleanable/wrapping/pinata name = "pinata shreds" @@ -349,7 +350,7 @@ icon = 'icons/obj/debris.dmi' icon_state = "garbage" plane = GAME_PLANE - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER beauty = -150 clean_type = CLEAN_TYPE_HARD_DECAL @@ -567,7 +568,9 @@ mergeable_decal = FALSE beauty = -10 plane = GAME_PLANE - layer = BELOW_OBJ_LAYER + layer = GIB_LAYER + clean_type = CLEAN_TYPE_HARD_DECAL + is_mopped = FALSE /obj/effect/decal/cleanable/rubble/Initialize(mapload) . = ..() diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index 3f2957a9c9e..7406cd910a1 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -6,7 +6,7 @@ icon = 'icons/mob/silicon/robots.dmi' icon_state = "gib1" plane = GAME_PLANE - layer = BELOW_OBJ_LAYER + layer = GIB_LAYER random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL @@ -14,6 +14,8 @@ beauty = -50 clean_type = CLEAN_TYPE_BLOOD + is_mopped = TRUE // probably shouldn't be, but janitor powercreep + /obj/effect/decal/cleanable/robot_debris/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_MOVABLE_PIPE_EJECTING, PROC_REF(on_pipe_eject)) diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index e27e6f91337..2e60cfb8bda 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -15,7 +15,7 @@ if(isclosedturf(loc) && loc.density) // allows for wall graffiti to be seen SET_PLANE_IMPLICIT(src, GAME_PLANE) - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER if(e_name) name = e_name if(desc_override) diff --git a/code/game/objects/effects/forcefields.dm b/code/game/objects/effects/forcefields.dm index dc51e5079f4..bc9f8a0bfd6 100644 --- a/code/game/objects/effects/forcefields.dm +++ b/code/game/objects/effects/forcefields.dm @@ -84,7 +84,7 @@ icon = 'icons/effects/eldritch.dmi' icon_state = "cosmic_carpet" anchored = TRUE - layer = BELOW_OBJ_LAYER + layer = GIB_LAYER density = FALSE can_atmos_pass = ATMOS_PASS_NO initial_duration = 30 SECONDS diff --git a/code/game/objects/items/syndie_spraycan.dm b/code/game/objects/items/syndie_spraycan.dm index 5690ecb7a28..bc1910595d4 100644 --- a/code/game/objects/items/syndie_spraycan.dm +++ b/code/game/objects/items/syndie_spraycan.dm @@ -171,7 +171,7 @@ /// Timer until the rune can be cleaned up off the floor var/protected_timer -/obj/effect/decal/cleanable/traitor_rune/traitor/Destroy() +/obj/effect/decal/cleanable/traitor_rune/Destroy() deltimer(protected_timer) QDEL_NULL(demoraliser) return ..() diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm index 9f7660b05e6..ce6c987ba10 100644 --- a/code/game/objects/structures/shower.dm +++ b/code/game/objects/structures/shower.dm @@ -344,11 +344,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16)) return mode == SHOWER_MODE_FOREVER ? 0 : PROCESS_KILL // Wash up. - wash_atom(loc) - for(var/atom/movable/movable_content as anything in loc) - if(!ismopable(movable_content)) // Mopables will be cleaned anyways by the turf wash above - wash_atom(movable_content) // Reagent exposure is handled in wash_atom - + wash_atom(loc, TRUE) reagents.remove_all(SHOWER_SPRAY_VOLUME) /obj/machinery/shower/on_deconstruction(disassembled = TRUE) diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 6ad32fe7a65..27aa1d36920 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -337,11 +337,7 @@ for(var/mob/living/basic/slime/M in src) M.apply_water() - wash(CLEAN_WASH) - for(var/atom/movable/movable_content as anything in src) - if(ismopable(movable_content)) // Will have already been washed by the wash call above at this point. - continue - movable_content.wash(CLEAN_WASH) + wash(CLEAN_WASH, TRUE) return TRUE /turf/open/handle_slip(mob/living/slipper, knockdown_amount, obj/slippable, lube, paralyze_amount, force_drop) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 318bb5ebb4c..b3cf3761e1d 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -702,19 +702,14 @@ GLOBAL_LIST_EMPTY(station_turfs) var/reac_volume = reagents[reagent] . |= reagent.expose_turf(src, reac_volume) -/** - * Called when this turf is being washed. Washing a turf will also wash any mopable floor decals - */ -/turf/wash(clean_types) +// When our turf is washed, we may wash everything on top of the turf +// By default we will only wash mopable things (like blood or vomit) +// but you may optionally pass in all_contents = TRUE to wash everything +/turf/wash(clean_types, all_contents = FALSE) . = ..() - - 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) + for(var/atom/movable/to_clean as anything in src) + if(all_contents || HAS_TRAIT(to_clean, TRAIT_MOPABLE)) + to_clean.wash(clean_types) /turf/set_density(new_value) var/old_density = density diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index af7254119dd..f4b424e4f20 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -82,6 +82,7 @@ Runes can either be invoked by one's self or with many different cultists. Each var/image/I = image(icon = 'icons/effects/blood.dmi', icon_state = null, loc = src) I.override = TRUE add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "cult_runes", I) + ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) /obj/effect/rune/examine(mob/user) . = ..() diff --git a/code/modules/antagonists/heretic/magic/cosmic_runes.dm b/code/modules/antagonists/heretic/magic/cosmic_runes.dm index be8f103678e..7eee200dd4a 100644 --- a/code/modules/antagonists/heretic/magic/cosmic_runes.dm +++ b/code/modules/antagonists/heretic/magic/cosmic_runes.dm @@ -69,6 +69,7 @@ var/image/silicon_image = image(icon = 'icons/obj/service/hand_of_god_structures.dmi', icon_state = null, loc = src) silicon_image.override = TRUE add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "cosmic", silicon_image) + ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) /obj/effect/cosmic_rune/attack_paw(mob/living/user, list/modifiers) return attack_hand(user, modifiers) diff --git a/code/modules/antagonists/heretic/rust_effect.dm b/code/modules/antagonists/heretic/rust_effect.dm index 9af6c4f6d89..294fe42cff1 100644 --- a/code/modules/antagonists/heretic/rust_effect.dm +++ b/code/modules/antagonists/heretic/rust_effect.dm @@ -13,3 +13,4 @@ pixel_x = rand(-6, 6) icon_state = "small_rune_[rand(1, 12)]" update_appearance() + ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) diff --git a/code/modules/antagonists/heretic/transmutation_rune.dm b/code/modules/antagonists/heretic/transmutation_rune.dm index a2bf4af77f4..ee25b0a18fd 100644 --- a/code/modules/antagonists/heretic/transmutation_rune.dm +++ b/code/modules/antagonists/heretic/transmutation_rune.dm @@ -17,6 +17,7 @@ var/image/silicon_image = image(icon = 'icons/effects/eldritch.dmi', icon_state = null, loc = src) silicon_image.override = TRUE add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "heretic_rune", silicon_image) + ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) /obj/effect/heretic_rune/examine(mob/user) . = ..() diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm index 6d08cd539fe..74c647777bf 100644 --- a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm +++ b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm @@ -79,6 +79,7 @@ silicon_image.override = TRUE add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "wizard_rune", silicon_image) announce_rune() + ADD_TRAIT(src, TRAIT_MOPABLE, INNATE_TRAIT) /// I cast Summon Security /obj/effect/grand_rune/proc/announce_rune() 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 014cfb626be..9b1916c9ac0 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_loot.dm @@ -21,7 +21,7 @@ icon_state = "brimdust" icon = 'icons/obj/mining.dmi' plane = GAME_PLANE - layer = GAME_CLEAN_LAYER + layer = CLEANABLE_OBJECT_LAYER mergeable_decal = FALSE /obj/effect/decal/cleanable/brimdust/Initialize(mapload) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 4444ef843c8..b5397344d0a 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1389,12 +1389,7 @@ if(reac_volume < 1) return - exposed_turf.wash(clean_types) - for(var/am in exposed_turf) - var/atom/movable/movable_content = am - if(ismopable(movable_content)) // Mopables will be cleaned anyways by the turf wash - continue - movable_content.wash(clean_types) + exposed_turf.wash(clean_types, TRUE) for(var/mob/living/basic/slime/exposed_slime in exposed_turf) exposed_slime.adjustToxLoss(rand(5,10)) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 4d16d24e9e9..6e6045d675c 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -311,6 +311,7 @@ #include "unit_test.dm" #include "verify_config_tags.dm" #include "verify_emoji_names.dm" +#include "washing.dm" #include "weird_food.dm" #include "wizard_loadout.dm" #include "worn_icons.dm" diff --git a/code/modules/unit_tests/washing.dm b/code/modules/unit_tests/washing.dm new file mode 100644 index 00000000000..c0239e9244f --- /dev/null +++ b/code/modules/unit_tests/washing.dm @@ -0,0 +1,43 @@ +/datum/unit_test/washing + /// Stuff we want to test that isn't cleanables, just to make sure they are getting cleaned when they should + var/list/cleanable_bonus_list = list( + /obj/effect/rune, + /obj/item/clothing/gloves/color/black, + /mob/living/carbon/human/dummy/consistent, + ) + + /// Tracks if we caught the clean signal, to know we washed successfully + VAR_PRIVATE/clean_sig_caught = 0 + +/datum/unit_test/washing/Run() + for(var/i in subtypesof(/obj/effect/decal/cleanable) + cleanable_bonus_list) + var/atom/movable/to_clean = allocate(i) + var/mopable = HAS_TRAIT(to_clean, TRAIT_MOPABLE) + + clean_sig_caught = 0 + RegisterSignal(to_clean, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean_caught)) + run_loc_floor_bottom_left.wash(CLEAN_ALL) + // mopables are cleaned when their turf is cleaned + if(mopable) + if(clean_sig_caught == 0) + TEST_FAIL("[i] was not cleaned when its turf was cleaned (cleaning only mopables)!") + if(clean_sig_caught > 1) + TEST_FAIL("[i] was cleaned more than once when its turf was cleaned (cleaning only mopables)!") + // non-mopables require the all_contents = TRUE flag to be cleaned + else + if(clean_sig_caught != 0) + TEST_FAIL("[i] was cleaned when its turf was cleaned (cleaning only mopables)!") + run_loc_floor_bottom_left.wash(CLEAN_ALL, TRUE) + if(clean_sig_caught == 0) + TEST_FAIL("[i] was not cleaned when its turf was cleaned (cleaning all contents)!") + if(clean_sig_caught > 1) + TEST_FAIL("[i] was cleaned more than once when its turf was cleaned (cleaning all contents)!") + + if(!QDELETED(to_clean)) + if(istype(to_clean, /obj/effect/decal/cleanable)) + TEST_FAIL("[i] was not deleted when its turf was cleaned!") + qdel(to_clean) + +/datum/unit_test/washing/proc/clean_caught(...) + SIGNAL_HANDLER + clean_sig_caught += 1