diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
index 528d23bbd54..bb84e6b37f9 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
@@ -1250,7 +1250,7 @@
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"do" = (
-/obj/structure/sink/puddle{
+/obj/structure/water_source/puddle{
pixel_x = -3;
pixel_y = 1
},
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm
index feef234b483..2ce3d404c08 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm
@@ -33,7 +33,7 @@
},
/area/ruin/powered)
"j" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/turf/open/floor/plating/asteroid{
name = "dirt"
},
diff --git a/_maps/RandomRuins/SpaceRuins/clownplanet.dmm b/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
index fbf51dd539e..659eb745f04 100644
--- a/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
+++ b/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
@@ -88,7 +88,7 @@
},
/area/ruin/powered/clownplanet)
"as" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/turf/open/floor/grass{
color = "#1eff00"
},
diff --git a/_maps/RandomRuins/SpaceRuins/gondolaasteroid.dmm b/_maps/RandomRuins/SpaceRuins/gondolaasteroid.dmm
index 71b8f516cbe..2833430be12 100644
--- a/_maps/RandomRuins/SpaceRuins/gondolaasteroid.dmm
+++ b/_maps/RandomRuins/SpaceRuins/gondolaasteroid.dmm
@@ -79,7 +79,7 @@
/turf/open/floor/grass,
/area/ruin/space/has_grav)
"u" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/turf/open/floor/grass,
/area/ruin/space/has_grav)
"v" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index f7f444ce5e8..745fdb0e9c1 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -75104,7 +75104,7 @@
/turf/open/floor/plating,
/area/maintenance/starboard)
"tgQ" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/obj/structure/flora/junglebush/large{
pixel_y = 0
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index f95097975f2..e3336f8bf34 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -26709,7 +26709,7 @@
/turf/open/floor/grass,
/area/medical/medbay/zone2)
"bqU" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/obj/structure/flora/ausbushes/reedbush{
pixel_y = 6
},
@@ -43218,7 +43218,7 @@
/turf/open/floor/grass,
/area/hydroponics/garden/monastery)
"chk" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/obj/item/reagent_containers/glass/bucket,
/obj/effect/landmark/event_spawn,
/turf/open/floor/grass,
@@ -51947,7 +51947,7 @@
/turf/closed/wall/r_wall,
/area/medical/medbay/zone2)
"llS" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/obj/structure/window/reinforced{
dir = 1
},
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index 06558a07e9b..95fdb948980 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -903,7 +903,7 @@
/turf/open/floor/holofloor,
/area/holodeck/rec_center/dodgeball)
"cD" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/turf/open/floor/holofloor/grass,
/area/holodeck/rec_center/pet_lounge)
"cE" = (
diff --git a/_maps/shuttles/emergency_nature.dmm b/_maps/shuttles/emergency_nature.dmm
index 447ff995b1f..1b76b0d425f 100644
--- a/_maps/shuttles/emergency_nature.dmm
+++ b/_maps/shuttles/emergency_nature.dmm
@@ -5,7 +5,7 @@
/turf/open/floor/grass,
/area/shuttle/escape)
"au" = (
-/obj/structure/sink/puddle,
+/obj/structure/water_source/puddle,
/turf/open/floor/grass,
/area/shuttle/escape)
"ay" = (
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 30bd5c63b16..ed92fb3fbcf 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -426,27 +426,6 @@
name = "kitchen sink"
icon_state = "sink_alt"
-
-/obj/structure/sink/puddle //splishy splashy ^_^
- name = "puddle"
- desc = "A puddle used for washing one's hands and face."
- icon_state = "puddle"
- resistance_flags = UNACIDABLE
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/structure/sink/puddle/attack_hand(mob/M)
- icon_state = "puddle-splash"
- . = ..()
- icon_state = "puddle"
-
-/obj/structure/sink/puddle/attackby(obj/item/O, mob/user, params)
- icon_state = "puddle-splash"
- . = ..()
- icon_state = "puddle"
-
-/obj/structure/sink/puddle/deconstruct(disassembled = TRUE)
- qdel(src)
-
/obj/structure/sink/greyscale
icon_state = "sink_greyscale"
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
@@ -480,6 +459,147 @@
return
return ..()
+//Water source, use the type water_source for unlimited water sources like classic sinks.
+/obj/structure/water_source
+ name = "Water Source"
+ icon = 'icons/obj/watercloset.dmi'
+ icon_state = "sink"
+ desc = "A sink used for washing one's hands and face. This one seems to be infinite!"
+ anchored = TRUE
+ var/busy = FALSE //Something's being washed at the moment
+ var/dispensedreagent = /datum/reagent/water // for whenever plumbing happens
+
+/obj/structure/water_source/attack_hand(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ if(!iscarbon(user))
+ return
+ if(!Adjacent(user))
+ return
+
+ if(busy)
+ to_chat(user, "Someone's already washing here!")
+ return
+ var/selected_area = parse_zone(user.zone_selected)
+ var/washing_face = FALSE
+ if(selected_area in list(BODY_ZONE_HEAD, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_PRECISE_EYES))
+ washing_face = TRUE
+ user.visible_message("[user] starts washing [user.p_their()] [washing_face ? "face" : "hands"]...", \
+ "You start washing your [washing_face ? "face" : "hands"]...")
+ busy = TRUE
+
+ if(!do_after(user, 4 SECONDS, target = src))
+ busy = FALSE
+ return
+
+ 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].")
+
+/obj/structure/water_source/attackby(obj/item/O, mob/living/user, params)
+ if(busy)
+ to_chat(user, "Someone's already washing here!")
+ return
+
+ if(istype(O, /obj/item/reagent_containers))
+ var/obj/item/reagent_containers/container = O
+ if(container.is_refillable())
+ if(!container.reagents.holder_full())
+ container.reagents.add_reagent(dispensedreagent, min(container.volume - container.reagents.total_volume, container.amount_per_transfer_from_this))
+ to_chat(user, "You fill [container] from [src].")
+ return TRUE
+ to_chat(user, "\The [container] is full.")
+ return FALSE
+
+ if(istype(O, /obj/item/melee/baton))
+ var/obj/item/melee/baton/baton = O
+ if(baton.cell && baton.cell.charge && baton.turned_on)
+ flick("baton_active", src)
+ user.Paralyze(baton.stun_time)
+ user.stuttering = baton.stun_time * 0.05
+ baton.deductcharge(baton.cell_hit_cost)
+ user.visible_message("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!", \
+ "You unwisely attempt to wash [baton] while it's still on.")
+ playsound(src, baton.stun_sound, 50, TRUE)
+ return
+
+ if(istype(O, /obj/item/mop))
+ O.reagents.add_reagent(dispensedreagent, 5)
+ to_chat(user, "You wet [O] in [src].")
+ playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE)
+ return
+
+ if(istype(O, /obj/item/stack/medical/gauze))
+ var/obj/item/stack/medical/gauze/G = O
+ new /obj/item/reagent_containers/glass/rag(loc)
+ to_chat(user, "You tear off a strip of gauze and make a rag.")
+ G.use(1)
+ return
+
+ if(istype(O, /obj/item/stack/ore/glass))
+ new /obj/item/stack/sheet/sandblock(loc)
+ to_chat(user, "You wet the sand and form it into a block.")
+ O.use(1)
+ return
+
+ if(O.item_flags & ABSTRACT) //Abstract items like grabs won't wash. No-drop items will though because it's still technically an item in your hand.
+ return
+
+ if(user.a_intent != INTENT_HARM)
+ to_chat(user, "You start washing [O]...")
+ busy = TRUE
+ if(!do_after(user, 4 SECONDS, target = src))
+ busy = FALSE
+ return TRUE
+ busy = FALSE
+ O.wash(CLEAN_WASH)
+ O.acid_level = 0
+ create_reagents(5)
+ reagents.add_reagent(dispensedreagent, 5)
+ reagents.expose(O, TOUCH)
+ user.visible_message("[user] washes [O] using [src].", \
+ "You wash [O] using [src].")
+ return TRUE
+
+ return ..()
+
+
+/obj/structure/water_source/puddle //splishy splashy ^_^
+ name = "puddle"
+ desc = "A puddle used for washing one's hands and face."
+ icon_state = "puddle"
+ resistance_flags = UNACIDABLE
+
+//ATTACK HAND IGNORING PARENT RETURN VALUE
+/obj/structure/water_source/puddle/attack_hand(mob/M)
+ icon_state = "puddle-splash"
+ . = ..()
+ icon_state = "puddle"
+
+/obj/structure/water_source/puddle/attackby(obj/item/O, mob/user, params)
+ icon_state = "puddle-splash"
+ . = ..()
+ icon_state = "puddle"
+
+/obj/structure/water_source/puddle/deconstruct(disassembled = TRUE)
+ qdel(src)
+
+//End legacy sink
+
+
//Shower Curtains//
//Defines used are pre-existing in layers.dm//