Moves an amount up to interpretation of things from attackby() to item_interaction() (#96757)

## About The Pull Request

Thirty files changed, one's not really changed, one's actually just a
copy of a change from a different pr, because for the sake of pipe
cleaners I decided to change the base turf. Probably wasn't a good idea.
This one contains the full set of `/turf/` `attackby()`s(besides those
meant for attacks), converted all at once because the tree of turf
subtypes looks a lot more like a spire than a bush.

Changes beyond conversion:
I added messaging for when you're crowbarring transit tube pods out of
the tubes because I genuinely wasted half an hour trying to figure out
what I'd done wrong in conversion because they don't look any different
so I thought it wasn't working.

If you're reinforcing plating and the plating is reinforced
mid-reinforcement you will no longer waste your plasteel reinforcing the
reinforced plating.


## Why It's Good For The Game

what are we at, ~120? I was expecting this to be a lot more drawn out,
but most of them are really small. I'm gonna have to do a final pass of
calls to `attackby()` once the dust settles, but the end of non-attack
`attackby()`s is just a week away.
This commit is contained in:
Leland Kemble
2026-07-15 17:37:00 -05:00
committed by GitHub
parent 7ed70def1b
commit d6f14fe29d
30 changed files with 831 additions and 715 deletions
@@ -66,12 +66,12 @@
eyeobj = new /mob/eye/camera/remote/base_construction(spawn_spot, src)
return TRUE
/obj/machinery/computer/camera_advanced/base_construction/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
/obj/machinery/computer/camera_advanced/base_construction/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
//If we have an internal RCD, we can refill it by slapping the console with some materials
if(internal_rcd && (istype(W, /obj/item/rcd_ammo) || istype(W, /obj/item/stack/sheet)))
internal_rcd.attackby(W, user, modifiers)
else
return ..()
if(!internal_rcd || (!istype(tool, /obj/item/rcd_ammo) && !istype(tool, /obj/item/stack/sheet)))
return NONE
internal_rcd.item_interaction(user, tool, modifiers)
return ITEM_INTERACT_SUCCESS
/obj/machinery/computer/camera_advanced/base_construction/Destroy()
qdel(internal_rcd)
@@ -693,13 +693,123 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets)
req_access = accesses
req_one_access = null
/obj/structure/closet/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
if(user in src)
return
if(src.tool_interact(W,user))
return 1 // No afterattack
else
return ..()
/obj/structure/closet/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(user in contents)
return ITEM_INTERACT_BLOCKING // can't even attack it from inside
if(!opened && istype(tool, /obj/item/airlock_painter))
if(!length(paint_jobs))
return ITEM_INTERACT_BLOCKING
var/choice = tgui_input_list(user, "Set Closet Paintjob", "Paintjob", paint_jobs)
if(isnull(choice))
return ITEM_INTERACT_BLOCKING
var/obj/item/airlock_painter/painter = tool
if(!painter.use_paint(user))
return ITEM_INTERACT_BLOCKING
var/list/paint_job = paint_jobs[choice]
icon_state = paint_job["icon_state"]
base_icon_state = icon_state
icon_door = paint_job["icon_door"]
update_appearance()
return ITEM_INTERACT_SUCCESS
if(istype(tool, /obj/item/electronics/airlock) && can_install_airlock_electronics(user))
user.visible_message(span_notice("[user] installs the electronics into the [src]."),\
span_notice("You start to install electronics into the [src]..."))
if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_airlock_electronics), user)))
return ITEM_INTERACT_BLOCKING
if(!user.transferItemToLoc(tool, src))
return ITEM_INTERACT_BLOCKING
inherit_airlock_electronics_access(tool)
qdel(tool)
secure = TRUE
balloon_alert(user, "electronics installed")
update_appearance()
return ITEM_INTERACT_SUCCESS
if(istype(tool, /obj/item/stock_parts/card_reader) && can_install_card_reader(user))
user.visible_message(span_notice("[user] is installing a card reader."),
span_notice("You begin installing the card reader."))
if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_card_reader), user)))
return ITEM_INTERACT_BLOCKING
qdel(tool)
card_reader_installed = TRUE
balloon_alert(user, "card reader installed")
return ITEM_INTERACT_SUCCESS
var/obj/item/card/id/card = tool.GetID()
if(secure && !broken && card_reader_installed && !locked && !opened && !access_locked && card)
var/num_choices = length(access_choices)
if(!num_choices)
return ITEM_INTERACT_BLOCKING
var/choice
if(num_choices == 1)
choice = access_choices[1]
else
choice = tgui_input_list(user, "Set Access Type", "Access Type", access_choices)
if(isnull(choice))
return ITEM_INTERACT_BLOCKING
id_card = null
switch(choice)
if("Personal") //only the player who swiped their id has access.
id_card = WEAKREF(card)
name = "[card.registered_name]'s locker"
desc += " It has been ID locked to [card.registered_name]."
if("Job") //anyone who has the same access permissions as this id has access. Does NOT apply to the whole department.
name = "[card.assignment]'s locker"
desc += " It has been access locked to [card.assignment]s."
set_access(card.GetAccess())
if("None") //free for all
name = initial(name)
desc = initial(desc)
req_access = list()
req_one_access = null
set_access(list())
if(!isnull(id_card))
balloon_alert(user, "now owned by [card.registered_name]")
else
balloon_alert(user, "set to [choice]")
return ITEM_INTERACT_SUCCESS
if(opened)
if(istype(tool, cutting_tool) && tool.tool_behaviour != TOOL_WELDER) // for example cardboard box is cut with wirecutters
user.visible_message(span_notice("[user] cut apart \the [src]."), \
span_notice("You cut \the [src] apart with \the [tool]."))
deconstruct(TRUE)
return ITEM_INTERACT_SUCCESS
if (user.combat_mode)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!user.transfer_item_to_turf(tool, drop_location())) // so we put in unlit welder too
return ITEM_INTERACT_BLOCKING
return ITEM_INTERACT_SUCCESS
if(!user.combat_mode || (tool.item_flags & NOBLUDGEON))
if(!card)
return NONE
if(opened)
return ITEM_INTERACT_BLOCKING
togglelock(user)
return ITEM_INTERACT_SUCCESS
return NONE
/obj/structure/closet/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
if (attack_hand(user, modifiers))
@@ -764,172 +874,96 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets)
return TRUE
/// returns TRUE if attackBy call shouldn't be continued (because tool was used/closet was of wrong type), FALSE if otherwise
/obj/structure/closet/proc/tool_interact(obj/item/weapon, mob/living/user)
. = TRUE
var/obj/item/card/id/id = null
if(!opened && istype(weapon, /obj/item/airlock_painter))
if(!length(paint_jobs))
return
var/choice = tgui_input_list(user, "Set Closet Paintjob", "Paintjob", paint_jobs)
if(isnull(choice))
return
/obj/structure/closet/screwdriver_act(mob/living/user, obj/item/tool)
if(user in contents)
return ITEM_INTERACT_BLOCKING
var/obj/item/airlock_painter/painter = weapon
if(!painter.use_paint(user))
return
var/list/paint_job = paint_jobs[choice]
icon_state = paint_job["icon_state"]
base_icon_state = icon_state
icon_door = paint_job["icon_door"]
if(!can_unscrew_airlock_electronics(user))
return NONE
update_appearance()
user.visible_message(span_notice("[user] begins to remove the electronics from the [src]."),\
span_notice("You begin to remove the electronics from the [src]..."))
else if(istype(weapon, /obj/item/electronics/airlock) && can_install_airlock_electronics(user))
user.visible_message(span_notice("[user] installs the electronics into the [src]."),\
span_notice("You start to install electronics into the [src]..."))
if (!tool.use_tool(src, user, 4 SECONDS, volume = 50, extra_checks = CALLBACK(src, PROC_REF(can_unscrew_airlock_electronics), user)))
return ITEM_INTERACT_BLOCKING
if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_airlock_electronics), user)))
return
if(!user.transferItemToLoc(weapon, src))
return
inherit_airlock_electronics_access(weapon)
qdel(weapon)
secure = TRUE
balloon_alert(user, "electronics installed")
update_appearance()
else if(weapon.tool_behaviour == TOOL_SCREWDRIVER && can_unscrew_airlock_electronics(user))
user.visible_message(span_notice("[user] begins to remove the electronics from the [src]."),\
span_notice("You begin to remove the electronics from the [src]..."))
if (!weapon.use_tool(src, user, 40, volume = 50, extra_checks = CALLBACK(src, PROC_REF(can_unscrew_airlock_electronics), user)))
return
var/obj/item/electronics/airlock/airlock_electronics = new(drop_location())
if(length(req_one_access))
airlock_electronics.one_access = TRUE
airlock_electronics.accesses = req_one_access
else
airlock_electronics.accesses = req_access
req_access = list()
req_one_access = null
id_card = null
secure = FALSE
balloon_alert(user, "electronics removed")
update_appearance()
else if(istype(weapon, /obj/item/stock_parts/card_reader) && can_install_card_reader(user))
user.visible_message(span_notice("[user] is installing a card reader."),
span_notice("You begin installing the card reader."))
if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_card_reader), user)))
return
qdel(weapon)
card_reader_installed = TRUE
balloon_alert(user, "card reader installed")
else if(weapon.tool_behaviour == TOOL_CROWBAR && can_pryout_card_reader(user))
user.visible_message(span_notice("[user] begins to pry the card reader out from [src]."),\
span_notice("You begin to pry the card reader out from [src]..."))
if(!weapon.use_tool(src, user, 4 SECONDS, extra_checks = CALLBACK(src, PROC_REF(can_pryout_card_reader), user)))
return
new /obj/item/stock_parts/card_reader(drop_location())
card_reader_installed = FALSE
balloon_alert(user, "card reader removed")
else if(secure && !broken && card_reader_installed && !locked && !opened && !access_locked && !isnull((id = weapon.GetID())))
var/num_choices = length(access_choices)
if(!num_choices)
return
var/choice
if(num_choices == 1)
choice = access_choices[1]
else
choice = tgui_input_list(user, "Set Access Type", "Access Type", access_choices)
if(isnull(choice))
return
id_card = null
switch(choice)
if("Personal") //only the player who swiped their id has access.
id_card = WEAKREF(id)
name = "[id.registered_name]'s locker"
desc += " It has been ID locked to [id.registered_name]."
if("Job") //anyone who has the same access permissions as this id has access. Does NOT apply to the whole department.
name = "[id.assignment]'s locker"
desc += " It has been access locked to [id.assignment]s."
set_access(id.GetAccess())
if("None") //free for all
name = initial(name)
desc = initial(desc)
req_access = list()
req_one_access = null
set_access(list())
if(!isnull(id_card))
balloon_alert(user, "now owned by [id.registered_name]")
else
balloon_alert(user, "set to [choice]")
else if(opened)
if(istype(weapon, cutting_tool))
if(weapon.tool_behaviour == TOOL_WELDER)
if(!weapon.tool_start_check(user, amount=1))
return
to_chat(user, span_notice("You begin cutting \the [src] apart..."))
if(weapon.use_tool(src, user, 40, volume=50))
if(!opened)
return
user.visible_message(span_notice("[user] slices apart \the [src]."),
span_notice("You cut \the [src] apart with \the [weapon]."),
span_hear("You hear welding."))
deconstruct(TRUE)
return
else // for example cardboard box is cut with wirecutters
user.visible_message(span_notice("[user] cut apart \the [src]."), \
span_notice("You cut \the [src] apart with \the [weapon]."))
deconstruct(TRUE)
return
if (user.combat_mode)
return
if(user.transfer_item_to_turf(weapon, drop_location())) // so we put in unlit welder too
return
else if(weapon.tool_behaviour == TOOL_WELDER && can_weld_shut)
if(!weapon.tool_start_check(user, amount=1))
return
if(weapon.use_tool(src, user, 40, volume=50))
if(opened)
return
welded = !welded
after_weld(welded)
user.visible_message(span_notice("[user] [welded ? "welds shut" : "unwelded"] \the [src]."),
span_notice("You [welded ? "weld" : "unwelded"] \the [src] with \the [weapon]."),
span_hear("You hear welding."))
user.log_message("[welded ? "welded":"unwelded"] closet [src] with [weapon]", LOG_GAME)
update_appearance()
else if(!user.combat_mode || (weapon.item_flags & NOBLUDGEON))
var/item_is_id = weapon.GetID()
if(!item_is_id)
return FALSE
if((item_is_id || !toggle(user)) && !opened)
togglelock(user)
var/obj/item/electronics/airlock/airlock_electronics = new(drop_location())
if(length(req_one_access))
airlock_electronics.one_access = TRUE
airlock_electronics.accesses = req_one_access
else
return FALSE
airlock_electronics.accesses = req_access
req_access = list()
req_one_access = null
id_card = null
secure = FALSE
balloon_alert(user, "electronics removed")
update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/crowbar_act(mob/living/user, obj/item/tool)
if(user in contents)
return ITEM_INTERACT_BLOCKING
if(!can_pryout_card_reader(user))
return NONE
user.visible_message(span_notice("[user] begins to pry the card reader out from [src]."),\
span_notice("You begin to pry the card reader out from [src]..."))
if(!tool.use_tool(src, user, 4 SECONDS, extra_checks = CALLBACK(src, PROC_REF(can_pryout_card_reader), user)))
return ITEM_INTERACT_BLOCKING
new /obj/item/stock_parts/card_reader(drop_location())
card_reader_installed = FALSE
balloon_alert(user, "card reader removed")
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/welder_act(mob/living/user, obj/item/tool)
if(user in contents)
return ITEM_INTERACT_BLOCKING
if(opened && istype(tool, cutting_tool)) // not all of them take welders
if(!tool.tool_start_check(user, amount=1))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You begin cutting \the [src] apart..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume=50))
return ITEM_INTERACT_BLOCKING
if(!opened)
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] slices apart \the [src]."),
span_notice("You cut \the [src] apart with \the [tool]."),
span_hear("You hear welding."))
deconstruct(TRUE)
return ITEM_INTERACT_SUCCESS
if(!can_weld_shut)
return NONE
if(!tool.tool_start_check(user, amount=1))
return ITEM_INTERACT_BLOCKING
if(!tool.use_tool(src, user, 4 SECONDS, volume=50))
return ITEM_INTERACT_BLOCKING
if(opened)
return ITEM_INTERACT_BLOCKING
welded = !welded
after_weld(welded)
user.visible_message(span_notice("[user] [welded ? "welds shut" : "unwelded"] \the [src]."),
span_notice("You [welded ? "weld" : "unwelded"] \the [src] with \the [tool]."),
span_hear("You hear welding."))
user.log_message("[welded ? "welded":"unwelded"] closet [src] with [tool]", LOG_GAME)
update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/wrench_act_secondary(mob/living/user, obj/item/tool)
if(!anchorable)
@@ -202,14 +202,25 @@
. = ..()
. += span_notice("<b>Right-click</b> with a Security-level ID to reset [src]'s registered ID.")
/obj/structure/closet/secure_closet/brig/genpop/attackby(obj/item/card/id/advanced/prisoner/user_id, mob/user, list/modifiers, list/attack_modifiers)
if(!secure || !istype(user_id))
/obj/structure/closet/secure_closet/brig/genpop/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!secure || !istype(tool, /obj/item/card/id))
return ..()
if(isnull(id_card))
say("Prisoner ID linked to locker.")
id_card = WEAKREF(user_id)
name = "genpop storage locker - [user_id.registered_name]"
if(!isnull(id_card))
return ITEM_INTERACT_BLOCKING
say("Prisoner ID linked to locker.")
id_card = WEAKREF(tool)
name = "genpop storage locker - [astype(tool, /obj/item/card/id/advanced/prisoner).registered_name]"
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/secure_closet/brig/genpop/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
var/list/id_access = astype(tool, /obj/item/card/id).GetAccess()
if(!id_card || !(ACCESS_BRIG in id_access))
return NONE
clear_access()
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/secure_closet/brig/genpop/proc/clear_access()
say("Authorized ID detected. Unlocking locker and resetting ID.")
@@ -218,16 +229,6 @@
name = initial(name)
update_appearance()
/obj/structure/closet/secure_closet/brig/genpop/attackby_secondary(obj/item/card/id/advanced/used_id, mob/user, list/modifiers, list/attack_modifiers)
if(!secure || !istype(used_id))
return ..()
var/list/id_access = used_id.GetAccess()
if(!isnull(id_card) && (ACCESS_BRIG in id_access))
clear_access()
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/structure/closet/secure_closet/evidence
anchored = TRUE
name = "secure evidence closet"
@@ -33,17 +33,15 @@
return
. += base_icon_state + "_some"
/obj/structure/closet/crate/bin/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
if(istype(W, /obj/item/storage/bag/trash) && !opened)
var/obj/item/storage/bag/trash/T = W
to_chat(user, span_notice("You fill the bag."))
for(var/obj/item/O in src)
T.atom_storage?.attempt_insert(O, user, TRUE)
T.update_appearance()
do_animate()
return TRUE
else
/obj/structure/closet/crate/bin/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, /obj/item/storage/bag/trash) || !opened)
return ..()
var/obj/item/storage/bag/trash/garbage_bag = tool
to_chat(user, span_notice("You fill the bag."))
for(var/obj/item/garbage in src)
garbage_bag.atom_storage?.attempt_insert(garbage, user, TRUE)
do_animate()
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/crate/bin/proc/do_animate()
playsound(loc, open_sound, 15, TRUE, -3)
@@ -31,32 +31,31 @@
else
to_chat(user, span_warning("You need a crowbar to pry this open!"))
/obj/structure/closet/crate/large/attackby(obj/item/W, mob/living/user, list/modifiers, list/attack_modifiers)
if(W.tool_behaviour == TOOL_CROWBAR)
if(manifest)
tear_manifest(user)
if(!open(user))
return FALSE
user.visible_message(span_notice("[user] pries \the [src] open."), \
span_notice("You pry open \the [src]."), \
span_hear("You hear splitting wood."))
playsound(src.loc, 'sound/items/weapons/slashmiss.ogg', 75, TRUE)
/obj/structure/closet/crate/large/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(user.combat_mode)
return ITEM_INTERACT_SKIP_TO_ATTACK //Stops it from opening and turning invisible when items are used on it.
var/turf/T = get_turf(src)
for(var/i in 1 to material_drop_amount)
new material_drop(src)
for(var/atom/movable/AM in contents)
AM.forceMove(T)
qdel(src)
to_chat(user, span_warning("You need a crowbar to pry this open!"))
return ITEM_INTERACT_BLOCKING //Just stop. Do nothing. Don't turn into an invisible sprite. Don't open like a locker.
//The large crate has no non-attack interactions other than the crowbar, anyway.
else
if(user.combat_mode) //Only return ..() if intent is harm, otherwise return 0 or just end it.
return ..() //Stops it from opening and turning invisible when items are used on it.
/obj/structure/closet/crate/large/crowbar_act(mob/living/user, obj/item/tool)
if(manifest)
tear_manifest(user)
if(!open(user))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] pries \the [src] open."), \
span_notice("You pry open \the [src]."), \
span_hear("You hear splitting wood."))
playsound(src.loc, 'sound/items/weapons/slashmiss.ogg', 75, TRUE)
else
to_chat(user, span_warning("You need a crowbar to pry this open!"))
return FALSE //Just stop. Do nothing. Don't turn into an invisible sprite. Don't open like a locker.
//The large crate has no non-attack interactions other than the crowbar, anyway.
var/turf/dump = get_turf(src)
for(var/i in 1 to material_drop_amount)
new material_drop(src)
for(var/atom/movable/stuff in contents)
stuff.forceMove(dump)
qdel(src)
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/crate/large/hats/PopulateContents()
..()
@@ -43,17 +43,18 @@
qdel(src)
///ensures that the syndicrate can only be unlocked by opening it with a syndicrate_key
/obj/structure/closet/crate/secure/syndicrate/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers)
if(!istype(item, /obj/item/syndicrate_key) || created_items)
/obj/structure/closet/crate/secure/syndicrate/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, /obj/item/syndicrate_key) || created_items)
return ..()
created_items = TRUE
for(var/item_path in unlock_contents)
new item_path(src)
unlock_contents = list()
qdel(item)
qdel(tool)
to_chat(user, span_notice("You twist the key into both locks at once, opening the crate."))
playsound(src, 'sound/machines/airlock/boltsup.ogg', 50, vary = FALSE)
togglelock(user)
return ITEM_INTERACT_SUCCESS
/obj/structure/closet/crate/secure/syndicrate/togglelock(mob/living/user, silent)
if(broken || !created_items)
@@ -67,8 +68,8 @@
)
update_appearance()
/obj/structure/closet/crate/secure/syndicrate/attackby_secondary(obj/item/weapon, mob/user, list/modifiers, list/attack_modifiers)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/structure/closet/crate/secure/syndicrate/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
return ITEM_INTERACT_BLOCKING
/obj/item/syndicrate_key
name = "syndicrate key"
+21 -26
View File
@@ -66,15 +66,16 @@
/obj/structure/lattice/blob_act(obj/structure/blob/B)
return
/obj/structure/lattice/attackby(obj/item/C, mob/user, list/modifiers, list/attack_modifiers)
/obj/structure/lattice/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
var/turf/underneath = get_turf(src)
return underneath.item_interaction(user, tool) //hand this off to the turf instead (for building plating, catwalks, etc)
/obj/structure/lattice/wirecutter_act(mob/living/user, obj/item/tool)
if(resistance_flags & INDESTRUCTIBLE)
return
if(C.tool_behaviour == TOOL_WIRECUTTER)
to_chat(user, span_notice("Slicing [name] joints ..."))
deconstruct()
else
var/turf/T = get_turf(src)
return T.attackby(C, user) //hand this off to the turf instead (for building plating, catwalks, etc)
return NONE
to_chat(user, span_notice("Slicing [name] joints ..."))
deconstruct()
return ITEM_INTERACT_SUCCESS
/obj/structure/lattice/atom_deconstruct(disassembled = TRUE)
if(!isnull(build_material) && number_of_mats >= 1)
@@ -158,13 +159,6 @@
desc = "A heavily reinforced catwalk used to build bridges in hostile environments. It doesn't look like anything could make this budge."
resistance_flags = INDESTRUCTIBLE
/obj/structure/lattice/catwalk/mining/attackby(obj/item/C, mob/user, list/modifiers, list/attack_modifiers)
// Allow cable placement even though we're indestructible
if(istype(C, /obj/item/stack/cable_coil))
var/turf/T = get_turf(src)
return T.attackby(C, user)
return ..()
/obj/structure/lattice/catwalk/mining/deconstruction_hints(mob/user)
return
@@ -181,21 +175,22 @@
/obj/structure/lattice/catwalk/lava/deconstruction_hints(mob/user)
return span_notice("The rods look like they could be <b>cut</b>, but the <i>heat treatment will shatter off</i>. There's space for a <i>tile</i>.")
/obj/structure/lattice/catwalk/lava/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
. = ..()
if(!ismetaltile(attacking_item))
return
var/obj/item/stack/tile/iron/attacking_tiles = attacking_item
/obj/structure/lattice/catwalk/lava/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!ismetaltile(tool))
return ..()
var/obj/item/stack/tile/iron/attacking_tiles = tool
if(!attacking_tiles.use(1))
to_chat(user, span_warning("You need one floor tile to build atop [src]."))
return
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You construct new plating with [src] as support."))
playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE)
var/turf/turf_we_place_on = get_turf(src)
turf_we_place_on.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
var/turf/base = get_turf(src)
base.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
qdel(src)
return ITEM_INTERACT_SUCCESS
/obj/structure/lattice/catwalk/boulder
name = "boulder platform"
@@ -214,10 +209,10 @@
fast_emissive_blocker(src)
AddElement(/datum/element/elevation, pixel_shift = 8)
/obj/structure/lattice/catwalk/boulder/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
if(ismetaltile(attacking_item))
/obj/structure/lattice/catwalk/boulder/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(ismetaltile(tool))
balloon_alert(user, "too unstable!")
return FALSE
return ITEM_INTERACT_BLOCKING
return ..()
/obj/structure/lattice/catwalk/boulder/CanAllowThrough(atom/movable/mover, border_dir)
@@ -62,14 +62,14 @@
RegisterSignal(reagents, COMSIG_REAGENTS_HOLDER_UPDATED, PROC_REF(start_chemming))
return PROCESS_KILL
/obj/structure/geyser/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers)
if(!istype(item, /obj/item/mining_scanner) && !istype(item, /obj/item/t_scanner/adv_mining_scanner))
/obj/structure/geyser/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, /obj/item/mining_scanner) && !istype(tool, /obj/item/t_scanner/adv_mining_scanner))
playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE)
return ..() //this runs the plunger code
return NONE //this runs the plunger code
if(discovered)
to_chat(user, span_warning("This geyser has already been discovered!"))
return
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You discovered the geyser and mark it on the GPS system!"))
playsound(src, 'sound/machines/beep/twobeep_high.ogg', 30)
@@ -83,13 +83,11 @@
AddComponent(/datum/component/gps, true_name) //put it on the gps so miners can mark it and chemists can profit off of it
if(isliving(user))
var/mob/living/living = user
var/obj/item/card/id/card = living.get_idcard()
if(card)
to_chat(user, span_notice("[point_value] mining points have been paid out!"))
card.registered_account.mining_points += point_value
var/obj/item/card/id/card = user.get_idcard()
if(card)
to_chat(user, span_notice("[point_value] mining points have been paid out!"))
card.registered_account.mining_points += point_value
return ITEM_INTERACT_SUCCESS
/obj/structure/geyser/wittel
reagent_id = /datum/reagent/wittel
@@ -107,17 +107,16 @@
SSore_generation.processed_vents -= src
return ..()
/obj/structure/ore_vent/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
. = ..()
if(.)
return TRUE
if(!is_type_in_list(attacking_item, scanning_equipment))
return TRUE
/obj/structure/ore_vent/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!is_type_in_list(tool, scanning_equipment))
return NONE
if(tapped)
balloon_alert_to_viewers("vent tapped!")
return TRUE
return ITEM_INTERACT_BLOCKING
scan_and_confirm(user)
return TRUE
return ITEM_INTERACT_SUCCESS
/obj/structure/ore_vent/attack_hand(mob/living/user, list/modifiers)
. = ..()
@@ -82,37 +82,45 @@
atom_integrity = max_integrity
return TRUE
/obj/structure/plaque/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers)
if(istype(I, /obj/item/pen/fountain))
if(engraved)
to_chat(user, span_warning("This plaque has already been engraved."))
return
var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN)
if(!namechoice)
return
var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN)
if(!descriptionchoice)
return
if(!Adjacent(user)) //Make sure user is adjacent still
to_chat(user, span_warning("You need to stand next to the plaque to engrave it!"))
return
user.visible_message(span_notice("[user] begins engraving [src]."), \
span_notice("You begin engraving [src]."))
if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay.
return
name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title.
desc = "The plaque reads: '[descriptionchoice]'"
engraved = TRUE //The plaque now has a name, description, and can't be altered again.
user.visible_message(span_notice("[user] engraves [src]."), \
span_notice("You engrave [src]."))
return
if(istype(I, /obj/item/pen))
/obj/structure/plaque/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, /obj/item/pen))
return NONE
if(!istype(tool, /obj/item/pen/fountain))
if(engraved)
to_chat(user, span_warning("This plaque has already been engraved, and your pen isn't fancy enough to engrave it anyway! Find a fountain pen."))
return
return ITEM_INTERACT_BLOCKING
to_chat(user, span_warning("Your pen isn't fancy enough to engrave this! Find a fountain pen.")) //Go steal the Curator's.
return
return ..()
return ITEM_INTERACT_BLOCKING
if(engraved)
to_chat(user, span_warning("This plaque has already been engraved."))
return ITEM_INTERACT_BLOCKING
var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN)
if(!namechoice)
return ITEM_INTERACT_BLOCKING
var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN)
if(!descriptionchoice)
return ITEM_INTERACT_BLOCKING
if(!Adjacent(user)) //Make sure user is adjacent still
to_chat(user, span_warning("You need to stand next to the plaque to engrave it!"))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] begins engraving [src]."), \
span_notice("You begin engraving [src]."))
if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay.
return ITEM_INTERACT_BLOCKING
name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title.
desc = "The plaque reads: '[descriptionchoice]'"
engraved = TRUE //The plaque now has a name, description, and can't be altered again.
user.visible_message(span_notice("[user] engraves [src]."), \
span_notice("You engrave [src]."))
return ITEM_INTERACT_SUCCESS
/obj/item/plaque //The item version of the above.
icon = 'icons/obj/signs.dmi'
@@ -155,37 +163,45 @@
return TRUE
/obj/item/plaque/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) //Same as part of the above, except for the item in hand instead of the structure.
if(istype(I, /obj/item/pen/fountain))
if(engraved)
to_chat(user, span_warning("This plaque has already been engraved."))
return
var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN)
if(!namechoice)
return
var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN)
if(!descriptionchoice)
return
if(!Adjacent(user)) //Make sure user is adjacent still
to_chat(user, span_warning("You need to stand next to the plaque to engrave it!"))
return
user.visible_message(span_notice("[user] begins engraving [src]."), \
span_notice("You begin engraving [src]."))
if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay.
return
name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title.
desc = "The plaque reads: '[descriptionchoice]'"
engraved = TRUE //The plaque now has a name, description, and can't be altered again.
user.visible_message(span_notice("[user] engraves [src]."), \
span_notice("You engrave [src]."))
return
if(istype(I, /obj/item/pen))
/obj/item/plaque/item_interaction(mob/living/user, obj/item/tool, list/modifiers) //Same as part of the above, except for the item in hand instead of the structure.
if(!istype(tool, /obj/item/pen))
return NONE
if(!istype(tool, /obj/item/pen/fountain))
if(engraved)
to_chat(user, span_warning("This plaque has already been engraved, and your pen isn't fancy enough to engrave it anyway! Find a fountain pen."))
return
return ITEM_INTERACT_BLOCKING
to_chat(user, span_warning("Your pen isn't fancy enough to engrave this! Find a fountain pen.")) //Go steal the Curator's.
return
return ..()
return ITEM_INTERACT_BLOCKING
if(engraved)
to_chat(user, span_warning("This plaque has already been engraved."))
return ITEM_INTERACT_BLOCKING
var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN)
if(!namechoice)
return ITEM_INTERACT_BLOCKING
var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN)
if(!descriptionchoice)
return ITEM_INTERACT_BLOCKING
if(!Adjacent(user)) //Make sure user is adjacent still
to_chat(user, span_warning("You need to stand next to the plaque to engrave it!"))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] begins engraving [src]."), \
span_notice("You begin engraving [src]."))
if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay.
return ITEM_INTERACT_BLOCKING
name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title.
desc = "The plaque reads: '[descriptionchoice]'"
engraved = TRUE //The plaque now has a name, description, and can't be altered again.
user.visible_message(span_notice("[user] engraves [src]."), \
span_notice("You engrave [src]."))
return ITEM_INTERACT_SUCCESS
/obj/item/plaque/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!iswallturf(interacting_with))
+32 -27
View File
@@ -81,33 +81,38 @@
atom_integrity = max_integrity
return TRUE
/obj/structure/sign/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers)
if(is_editable && IS_WRITING_UTENSIL(I))
if(!length(GLOB.editable_sign_types))
CRASH("GLOB.editable_sign_types failed to populate")
var/choice = tgui_input_list(user, "Select a sign type", "Sign Customization", GLOB.editable_sign_types)
if(isnull(choice))
return
if(!Adjacent(user)) //Make sure user is adjacent still.
to_chat(user, span_warning("You need to stand next to the sign to change it!"))
return
user.visible_message(span_notice("[user] begins changing [src]."), \
span_notice("You begin changing [src]."))
if(!do_after(user, 4 SECONDS, target = src)) //Small delay for changing signs instead of it being instant, so somebody could be shoved or stunned to prevent them from doing so.
return
var/sign_type = GLOB.editable_sign_types[choice]
//It's import to clone the pixel layout information.
//Otherwise signs revert to being on the turf and
//move jarringly.
var/obj/structure/sign/changedsign = new sign_type(get_turf(src))
changedsign.pixel_x = pixel_x
changedsign.pixel_y = pixel_y
changedsign.atom_integrity = atom_integrity
qdel(src)
user.visible_message(span_notice("[user] finishes changing the sign."), \
span_notice("You finish changing the sign."))
return
return ..()
/obj/structure/sign/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!is_editable || !IS_WRITING_UTENSIL(tool))
return NONE
if(!length(GLOB.editable_sign_types))
CRASH("GLOB.editable_sign_types failed to populate")
var/choice = tgui_input_list(user, "Select a sign type", "Sign Customization", GLOB.editable_sign_types)
if(isnull(choice))
return ITEM_INTERACT_BLOCKING
if(!Adjacent(user)) //Make sure user is adjacent still.
to_chat(user, span_warning("You need to stand next to the sign to change it!"))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] begins changing [src]."), \
span_notice("You begin changing [src]."))
if(!do_after(user, 4 SECONDS, target = src)) //Small delay for changing signs instead of it being instant, so somebody could be shoved or stunned to prevent them from doing so.
return ITEM_INTERACT_BLOCKING
var/sign_type = GLOB.editable_sign_types[choice]
//It's import to clone the pixel layout information.
//Otherwise signs revert to being on the turf and
//move jarringly.
var/obj/structure/sign/changedsign = new sign_type(get_turf(src))
changedsign.pixel_x = pixel_x
changedsign.pixel_y = pixel_y
changedsign.atom_integrity = atom_integrity
qdel(src)
user.visible_message(span_notice("[user] finishes changing the sign."), \
span_notice("You finish changing the sign."))
return ITEM_INTERACT_SUCCESS
/obj/structure/sign/atom_deconstruct(disassembled)
var/turf/drop_turf = drop_location()
@@ -93,12 +93,13 @@
break
/obj/structure/transit_tube/station/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
if(W.tool_behaviour == TOOL_CROWBAR)
for(var/obj/structure/transit_tube_pod/P in loc)
P.deconstruct(FALSE, user)
else
return ..()
/obj/structure/transit_tube/station/crowbar_act(mob/living/user, obj/item/tool)
var/anything_done = FALSE
for(var/obj/structure/transit_tube_pod/victim in loc)
victim.deconstruct(FALSE, user)
anything_done = TRUE
to_chat(user, span_notice("[anything_done ? "You empty \the [src]." : "\The [src] is already empty!"]"))
return ITEM_INTERACT_SUCCESS
/obj/structure/transit_tube/station/proc/open_animation()
if(open_status == STATION_TUBE_CLOSED)
@@ -32,25 +32,31 @@
if(current_size >= STAGE_FIVE)
deconstruct(FALSE)
/obj/structure/transit_tube/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
if(W.tool_behaviour == TOOL_WRENCH)
if(tube_construction)
for(var/obj/structure/transit_tube_pod/pod in src.loc)
to_chat(user, span_warning("Remove the pod first!"))
return
user.visible_message(span_notice("[user] starts to detach \the [src]."), span_notice("You start to detach \the [src]..."))
if(W.use_tool(src, user, 2 SECONDS, volume=50))
to_chat(user, span_notice("You detach \the [src]."))
var/obj/structure/c_transit_tube/R = new tube_construction(loc)
R.setDir(dir)
transfer_fingerprints_to(R)
R.add_fingerprint(user)
qdel(src)
else if(W.tool_behaviour == TOOL_CROWBAR)
for(var/obj/structure/transit_tube_pod/pod in src.loc)
pod.attackby(W, user)
else
return ..()
/obj/structure/transit_tube/wrench_act(mob/living/user, obj/item/tool)
if(!tube_construction)
return NONE
for(var/obj/structure/transit_tube_pod/pod in loc)
to_chat(user, span_warning("Remove the pod first!"))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] starts to detach \the [src]."), \
span_notice("You start to detach \the [src]..."))
if(!tool.use_tool(src, user, 2 SECONDS, volume=50))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You detach \the [src]."))
var/obj/structure/c_transit_tube/husk = new tube_construction(loc)
husk.setDir(dir)
transfer_fingerprints_to(husk)
husk.add_fingerprint(user)
qdel(src)
return ITEM_INTERACT_SUCCESS
/obj/structure/transit_tube/crowbar_act(mob/living/user, obj/item/tool)
for(var/obj/structure/transit_tube_pod/pod in loc)
pod.item_interaction(user, tool)
return ITEM_INTERACT_SUCCESS
// Called to check if a pod should stop upon entering this tube.
/obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir)
@@ -26,17 +26,18 @@
icon_state = contents.len ? occupied_icon_state : initial(icon_state)
return ..()
/obj/structure/transit_tube_pod/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers)
if(I.tool_behaviour == TOOL_CROWBAR)
if(!moving)
I.play_tool_sound(src)
if(contents.len)
user.visible_message(span_notice("[user] empties \the [src]."), span_notice("You empty \the [src]."))
empty_pod()
else
deconstruct(TRUE)
/obj/structure/transit_tube_pod/crowbar_act(mob/living/user, obj/item/tool)
if(moving) // can you even click on one of these while they're in a tube?
return NONE // for that matter can you click them when they're outside of a tube?
tool.play_tool_sound(src)
if(contents.len)
user.visible_message(span_notice("[user] empties \the [src]."), \
span_notice("You empty \the [src]."))
empty_pod()
else
return ..()
deconstruct(TRUE)
return ITEM_INTERACT_SUCCESS
/obj/structure/transit_tube_pod/atom_deconstruct(disassembled = TRUE)
var/atom/location = get_turf(src)
@@ -51,21 +51,25 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/urinal, 32)
return
return ..()
/obj/structure/urinal/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
if(exposed)
if(hidden_item)
to_chat(user, span_warning("There is already something in the drain enclosure!"))
return
if(attacking_item.w_class > WEIGHT_CLASS_TINY)
to_chat(user, span_warning("[attacking_item] is too large for the drain enclosure."))
return
if(!user.transferItemToLoc(attacking_item, src))
to_chat(user, span_warning("[attacking_item] is stuck to your hand, you cannot put it in the drain enclosure!"))
return
hidden_item = attacking_item
to_chat(user, span_notice("You place [attacking_item] into the drain enclosure."))
return
return ..()
/obj/structure/urinal/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!exposed)
return NONE
if(hidden_item)
to_chat(user, span_warning("There is already something in the drain enclosure!"))
return ITEM_INTERACT_BLOCKING
if(tool.w_class > WEIGHT_CLASS_TINY)
to_chat(user, span_warning("[tool] is too large for the drain enclosure."))
return ITEM_INTERACT_BLOCKING
if(!user.transferItemToLoc(tool, src))
to_chat(user, span_warning("[tool] is stuck to your hand, you cannot put it in the drain enclosure!"))
return ITEM_INTERACT_BLOCKING
hidden_item = tool
to_chat(user, span_notice("You place [tool] into the drain enclosure."))
return ITEM_INTERACT_SUCCESS
/obj/structure/urinal/screwdriver_act(mob/living/user, obj/item/I)
if(..())
@@ -57,26 +57,28 @@
span_notice("You wash your [washing_face ? "face" : "hands"] using [src]."),
)
/obj/structure/water_source/attackby(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers)
/obj/structure/water_source/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(busy)
to_chat(user, span_warning("Someone's already washing here!"))
return
return ITEM_INTERACT_BLOCKING
if(attacking_item.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(tool.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 ITEM_INTERACT_BLOCKING
if(is_reagent_container(attacking_item))
var/obj/item/reagent_containers/container = attacking_item
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, span_notice("You fill [container] from [src]."))
return TRUE
to_chat(user, span_notice("\The [container] is full."))
return FALSE
if(is_reagent_container(tool))
var/obj/item/reagent_containers/container = tool
if(container.is_refillable()) // no early return, we want items that cannot perform their unique interactions to wash
if(container.reagents.holder_full())
to_chat(user, span_notice("\The [container] is full."))
return ITEM_INTERACT_BLOCKING
if(istype(attacking_item, /obj/item/melee/baton/security))
var/obj/item/melee/baton/security/baton = attacking_item
container.reagents.add_reagent(dispensedreagent, min(container.volume - container.reagents.total_volume, container.amount_per_transfer_from_this))
to_chat(user, span_notice("You fill [container] from [src]."))
return ITEM_INTERACT_SUCCESS
if(istype(tool, /obj/item/melee/baton/security))
var/obj/item/melee/baton/security/baton = tool
if(baton.cell?.charge && baton.active)
flick("baton_active", src)
user.Paralyze(baton.knockdown_time)
@@ -86,29 +88,29 @@
span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!"),
span_userdanger("You unwisely attempt to wash [baton] while it's still on."))
playsound(src, baton.on_stun_sound, 50, TRUE)
return
return ITEM_INTERACT_SUCCESS
if(istype(attacking_item, /obj/item/mop))
attacking_item.reagents.add_reagent(dispensedreagent, 5)
to_chat(user, span_notice("You wet [attacking_item] in [src]."))
if(istype(tool, /obj/item/mop))
tool.reagents.add_reagent(dispensedreagent, 5)
to_chat(user, span_notice("You wet [tool] in [src]."))
playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE)
return
return ITEM_INTERACT_SUCCESS
if(!user.combat_mode || (attacking_item.item_flags & NOBLUDGEON))
to_chat(user, span_notice("You start washing [attacking_item]..."))
if(!user.combat_mode || (tool.item_flags & NOBLUDGEON))
to_chat(user, span_notice("You start washing [tool]..."))
busy = TRUE
if(!do_after(user, 4 SECONDS, target = src))
busy = FALSE
return TRUE
return ITEM_INTERACT_BLOCKING
busy = FALSE
attacking_item.wash(CLEAN_WASH)
reagents.expose(attacking_item, TOUCH, 5 / max(reagents.total_volume, 5))
tool.wash(CLEAN_WASH)
reagents.expose(tool, TOUCH, 5 / max(reagents.total_volume, 5))
user.visible_message(
span_notice("[user] washes [attacking_item] using [src]."),
span_notice("You wash [attacking_item] using [src]."))
return TRUE
span_notice("[user] washes [tool] using [src]."),
span_notice("You wash [tool] using [src]."))
return ITEM_INTERACT_SUCCESS
return ..()
return NONE
/obj/structure/water_source/puddle //splishy splashy ^_^
name = "puddle"
@@ -132,7 +134,7 @@
. = ..()
icon_state = base_icon_state
/obj/structure/water_source/puddle/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
/obj/structure/water_source/puddle/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
icon_state = "[base_icon_state]-splash"
. = ..()
icon_state = base_icon_state