diff --git a/code/game/objects/structures/construction_console/construction_console.dm b/code/game/objects/structures/construction_console/construction_console.dm
index 73884ac7913..16b070f2d9f 100644
--- a/code/game/objects/structures/construction_console/construction_console.dm
+++ b/code/game/objects/structures/construction_console/construction_console.dm
@@ -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)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 858ab649ee9..4c557d67d51 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -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)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 56c61bb39c5..f1fd3166e43 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -202,14 +202,25 @@
. = ..()
. += span_notice("Right-click 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"
diff --git a/code/game/objects/structures/crates_lockers/crates/bins.dm b/code/game/objects/structures/crates_lockers/crates/bins.dm
index 36a907ee0b6..4867e42a471 100644
--- a/code/game/objects/structures/crates_lockers/crates/bins.dm
+++ b/code/game/objects/structures/crates_lockers/crates/bins.dm
@@ -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)
diff --git a/code/game/objects/structures/crates_lockers/crates/large.dm b/code/game/objects/structures/crates_lockers/crates/large.dm
index a527d48727a..2ebef6224a7 100644
--- a/code/game/objects/structures/crates_lockers/crates/large.dm
+++ b/code/game/objects/structures/crates_lockers/crates/large.dm
@@ -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()
..()
diff --git a/code/game/objects/structures/crates_lockers/crates/syndicrate.dm b/code/game/objects/structures/crates_lockers/crates/syndicrate.dm
index 45ffc987a0e..f1f6ce6863e 100644
--- a/code/game/objects/structures/crates_lockers/crates/syndicrate.dm
+++ b/code/game/objects/structures/crates_lockers/crates/syndicrate.dm
@@ -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"
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index e9322232650..ca935f2914e 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -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 cut, but the heat treatment will shatter off. There's space for a tile.")
-/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)
diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm
index eb969552f3a..5c8a748cd41 100644
--- a/code/game/objects/structures/lavaland/geyser.dm
+++ b/code/game/objects/structures/lavaland/geyser.dm
@@ -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
diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm
index 3f2edfc7416..f70db6870f6 100644
--- a/code/game/objects/structures/lavaland/ore_vent.dm
+++ b/code/game/objects/structures/lavaland/ore_vent.dm
@@ -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)
. = ..()
diff --git a/code/game/objects/structures/plaques/_plaques.dm b/code/game/objects/structures/plaques/_plaques.dm
index de143b17f9f..fa0e8ff0db6 100644
--- a/code/game/objects/structures/plaques/_plaques.dm
+++ b/code/game/objects/structures/plaques/_plaques.dm
@@ -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))
diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm
index 7be5596412f..8e7aaf902f6 100644
--- a/code/game/objects/structures/signs/_signs.dm
+++ b/code/game/objects/structures/signs/_signs.dm
@@ -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()
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index 213d086bfc3..e35232700a0 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -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)
diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm
index 4991eb9df11..5cae9c9b989 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube.dm
@@ -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)
diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
index 30ea69ff0d4..d9653d94bd8 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
@@ -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)
diff --git a/code/game/objects/structures/water_structures/urinal.dm b/code/game/objects/structures/water_structures/urinal.dm
index 485fe6fb3f4..ced7b893973 100644
--- a/code/game/objects/structures/water_structures/urinal.dm
+++ b/code/game/objects/structures/water_structures/urinal.dm
@@ -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(..())
diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm
index fc5411991fc..967614f8565 100644
--- a/code/game/objects/structures/water_structures/water_source.dm
+++ b/code/game/objects/structures/water_structures/water_source.dm
@@ -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
diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm
index 54ba5d28796..b16e8b45bdf 100644
--- a/code/game/turfs/closed/minerals.dm
+++ b/code/game/turfs/closed/minerals.dm
@@ -69,7 +69,7 @@
if(!held_item)
INVOKE_ASYNC(bumping, TYPE_PROC_REF(/mob, ClickOn), src)
else if(held_item.tool_behaviour == TOOL_MINING)
- attackby(held_item, bumping)
+ item_interaction(bumping, held_item)
/turf/closed/mineral/proc/spread_vein(ore_type)
if(!ispath(ore_type, /obj/item/stack/ore))
@@ -211,29 +211,35 @@
return TRUE
return ..()
-/turf/closed/mineral/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers, exp_multiplier = 1)
+/turf/closed/mineral/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(tool.tool_behaviour != TOOL_MINING)
+ return ..()
+
+ return manual_mine(user, tool)
+
+///Mining manually with a hand tool or something masquerading as one
+/turf/closed/mineral/proc/manual_mine(mob/living/user, obj/item/tool, exp_multiplier = 1)
if (!ISADVANCEDTOOLUSER(user))
- to_chat(usr, span_warning("You don't have the dexterity to do this!"))
- return
+ to_chat(user, span_warning("You don't have the dexterity to do this!"))
+ return ITEM_INTERACT_BLOCKING
- if(I.tool_behaviour != TOOL_MINING)
- return
-
- var/turf/T = user.loc
- if (!isturf(T))
- return
+ if (!isturf(user.loc))
+ return ITEM_INTERACT_BLOCKING
if(TIMER_COOLDOWN_RUNNING(src, REF(user))) //prevents mining turfs in progress
- return
+ return ITEM_INTERACT_BLOCKING
TIMER_COOLDOWN_START(src, REF(user), tool_mine_speed)
- if(!I.use_tool(src, user, tool_mine_speed, volume=50))
+ if(!tool.use_tool(src, user, tool_mine_speed, volume = 50))
TIMER_COOLDOWN_END(src, REF(user)) //if we fail we can start again immediately
- return
+ return ITEM_INTERACT_BLOCKING
- if(ismineralturf(src))
- gets_drilled(user, exp_multiplier)
- SSblackbox.record_feedback("tally", "pick_used_mining", 1, I.type)
+ if(!ismineralturf(src))
+ return ITEM_INTERACT_BLOCKING
+
+ gets_drilled(user, exp_multiplier)
+ SSblackbox.record_feedback("tally", "pick_used_mining", 1, tool.type)
+ return ITEM_INTERACT_SUCCESS
/turf/closed/mineral/attack_hand(mob/user)
var/mining_arms = HAS_TRAIT(user, TRAIT_FIST_MINING)
@@ -1066,19 +1072,19 @@
det_time = rand(8,10) //So you don't know exactly when the hot potato will explode
. = ..()
-/turf/closed/mineral/gibtonite/attackby(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers, exp_multiplier = 1)
+/turf/closed/mineral/gibtonite/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
var/previous_stage = stage
- if(istype(attacking_item, /obj/item/goliath_infuser_hammer) && stage == GIBTONITE_ACTIVE)
- user.visible_message(span_notice("[user] digs [attacking_item] to [src]..."), span_notice("Your tendril hammer instictively digs and wraps around [src] to stop it..."))
+ if(istype(tool, /obj/item/goliath_infuser_hammer) && stage == GIBTONITE_ACTIVE)
+ user.visible_message(span_notice("[user] digs [tool] to [src]..."), span_notice("Your tendril hammer instictively digs and wraps around [src] to stop it..."))
defuse(user)
- else if(istype(attacking_item, /obj/item/mining_scanner) || istype(attacking_item, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE)
- user.visible_message(span_notice("[user] holds [attacking_item] to [src]..."), span_notice("You use [attacking_item] to locate where to cut off the chain reaction and attempt to stop it..."))
+ else if(istype(tool, /obj/item/mining_scanner) || istype(tool, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE)
+ user.visible_message(span_notice("[user] holds [tool] to [src]..."), span_notice("You use [tool] to locate where to cut off the chain reaction and attempt to stop it..."))
defuse(user)
. = ..()
- if(istype(attacking_item, /obj/item/clothing/gloves/gauntlets) && previous_stage == GIBTONITE_UNSTRUCK && stage == GIBTONITE_ACTIVE && istype(user))
+ if(istype(tool, /obj/item/clothing/gloves/gauntlets) && previous_stage == GIBTONITE_UNSTRUCK && stage == GIBTONITE_ACTIVE && istype(user))
user.Immobilize(0.5 SECONDS)
user.throw_at(get_ranged_target_turf(src, get_dir(src, user), 5), range = 5, speed = 3, spin = FALSE)
- user.visible_message(span_danger("[user] hit gibtonite with [attacking_item.name], launching [user.p_them()] back!"), span_danger("You've struck gibtonite! Your [attacking_item.name] launched you back!"))
+ user.visible_message(span_danger("[user] hit gibtonite with [tool.name], launching [user.p_them()] back!"), span_danger("You've struck gibtonite! Your [tool.name] launched you back!"))
/turf/closed/mineral/gibtonite/proc/explosive_reaction(mob/user = null)
if(stage != GIBTONITE_UNSTRUCK)
@@ -1224,15 +1230,16 @@
base_icon_state = "rock_wall"
smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
-/turf/closed/mineral/strong/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers, exp_multiplier = 1)
+/turf/closed/mineral/strong/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!ishuman(user))
to_chat(usr, span_warning("Only a more advanced species could break a rock such as this one!"))
- return FALSE
- if(user.mind?.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER)
- . = ..()
- else
- to_chat(usr, span_warning("The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner."))
+ return ITEM_INTERACT_BLOCKING
+ if(!user.mind?.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER)
+ to_chat(usr, span_warning("The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner."))
+ return ITEM_INTERACT_BLOCKING
+
+ return ..()
/turf/closed/mineral/strong/gets_drilled(mob/user, exp_multiplier = 0)
if(istype(user))
diff --git a/code/game/turfs/closed/wall/mineral_walls.dm b/code/game/turfs/closed/wall/mineral_walls.dm
index 02e40a4054e..23700a6c949 100644
--- a/code/game/turfs/closed/wall/mineral_walls.dm
+++ b/code/game/turfs/closed/wall/mineral_walls.dm
@@ -173,15 +173,18 @@
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT*2)
rust_resistance = RUST_RESISTANCE_BASIC
-/turf/closed/wall/mineral/wood/attackby(obj/item/W, mob/user)
- if(W.get_sharpness() && W.force)
- var/duration = ((4.8 SECONDS)/W.force) * 2 //In seconds, for now.
- if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/fireaxe))
- duration /= 4 //Much better with hatchets and axes.
- if(do_after(user, duration * (1 SECONDS), target=src)) //Into deciseconds.
- dismantle_wall(FALSE,FALSE)
- return
- return ..()
+/turf/closed/wall/mineral/wood/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(!tool.get_sharpness() || !tool.force)
+ return ..()
+
+ var/duration = (4.8 SECONDS / tool.force) * 2 //In seconds, for now.
+ if(istype(tool, /obj/item/hatchet) || istype(tool, /obj/item/fireaxe))
+ duration /= 4 //Much better with hatchets and axes.
+ if(!do_after(user, duration * 1 SECONDS, target = src)) //Into deciseconds.
+ return ITEM_INTERACT_BLOCKING
+
+ dismantle_wall(FALSE,FALSE)
+ return ITEM_INTERACT_SUCCESS
/turf/closed/wall/mineral/hulk_recoil(obj/item/bodypart/arm, mob/living/carbon/human/hulkman, damage = 0)
return ..() //No recoil damage, wood is weak
diff --git a/code/game/turfs/open/asteroid.dm b/code/game/turfs/open/asteroid.dm
index af7c082e23a..35d6e8cdbb7 100644
--- a/code/game/turfs/open/asteroid.dm
+++ b/code/game/turfs/open/asteroid.dm
@@ -62,29 +62,36 @@
/turf/open/misc/asteroid/ex_act(severity, target)
return FALSE
-/turf/open/misc/asteroid/attackby(obj/item/attack_item, mob/user, list/modifiers)
+/turf/open/misc/asteroid/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
- if(.)
- return TRUE
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
- if(attack_item.tool_behaviour == TOOL_SHOVEL || attack_item.tool_behaviour == TOOL_MINING)
- if(!can_dig(user))
- return TRUE
-
- if(!isturf(user.loc))
- return
-
- balloon_alert(user, "digging...")
-
- if(attack_item.use_tool(src, user, 4 SECONDS, volume = 50))
- if(!can_dig(user))
- return TRUE
- getDug()
- SSblackbox.record_feedback("tally", "pick_used_mining", 1, attack_item.type)
- return TRUE
- else if(istype(attack_item, /obj/item/storage/bag/ore))
+ if(istype(tool, /obj/item/storage/bag/ore))
for(var/obj/item/stack/ore/dropped_ore in src)
- SEND_SIGNAL(attack_item, COMSIG_ATOM_ATTACKBY, dropped_ore)
+ SEND_SIGNAL(tool, COMSIG_ATOM_ATTACKBY, dropped_ore)
+ return ITEM_INTERACT_SUCCESS
+
+ if(tool.tool_behaviour != TOOL_SHOVEL && tool.tool_behaviour != TOOL_MINING)
+ return . // it still could be SKIP_TO_ATTACK and we don't want to step on that
+
+ if(!can_dig(user))
+ return ITEM_INTERACT_BLOCKING
+
+ if(!isturf(user.loc))
+ return ITEM_INTERACT_BLOCKING
+
+ balloon_alert(user, "digging...")
+
+ if(!tool.use_tool(src, user, 4 SECONDS, volume = 50))
+ return ITEM_INTERACT_BLOCKING
+
+ if(!can_dig(user))
+ return ITEM_INTERACT_BLOCKING
+
+ getDug()
+ SSblackbox.record_feedback("tally", "pick_used_mining", 1, tool.type)
+ return ITEM_INTERACT_SUCCESS
/// Drops itemstack when dug and changes icon
/turf/open/misc/asteroid/proc/getDug()
diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm
index 47c425da544..dd7e01ed224 100644
--- a/code/game/turfs/open/chasm.dm
+++ b/code/game/turfs/open/chasm.dm
@@ -55,26 +55,18 @@
underlay_appearance.icon_state = /turf/open/misc/asteroid/basalt::icon_state
return TRUE
-/turf/open/chasm/attackby(obj/item/C, mob/user, params, area/area_restriction)
+/turf/open/chasm/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
- if(ismetaltile(C))
- build_with_floor_tiles(C, user)
- return
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
- if(!istype(C, /obj/item/stack/rods))
- return
+ if(istype(tool, /obj/item/stack/rods))
+ build_with_rods(tool, user)
+ return ITEM_INTERACT_SUCCESS
- var/obj/item/stack/rods/R = C
- var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
- if(L)
- return
- if(!R.use(1))
- to_chat(user, span_warning("You need one rod to build a lattice."))
- return
- to_chat(user, span_notice("You construct a lattice."))
- playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE)
- // Create a lattice, without reverting to our baseturf
- new /obj/structure/lattice(src)
+ if(ismetaltile(tool))
+ build_with_floor_tiles(tool, user)
+ return ITEM_INTERACT_SUCCESS
/// Handles adding the chasm component to the turf (So stuff falls into it!)
@@ -140,9 +132,11 @@
/turf/open/chasm/true/no_smooth/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data)
return FALSE
-/turf/open/chasm/true/no_smooth/attackby(obj/item/item, mob/user, params, area/area_restriction)
- if(istype(item, /obj/item/stack/rods))
- return
- else if(ismetaltile(item))
- return
+/turf/open/chasm/true/no_smooth/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(istype(tool, /obj/item/stack/rods))
+ return ITEM_INTERACT_BLOCKING
+
+ if(ismetaltile(tool))
+ return ITEM_INTERACT_BLOCKING
+
return ..()
diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm
index 01be12d84af..7fe3cb6a267 100644
--- a/code/game/turfs/open/floor.dm
+++ b/code/game/turfs/open/floor.dm
@@ -125,19 +125,21 @@
W.update_appearance()
return W
-/turf/open/floor/attackby(obj/item/object, mob/living/user, list/modifiers)
- if(!object || !user)
- return TRUE
+/turf/open/floor/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
- if(.)
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
return .
- if(overfloor_placed && istype(object, /obj/item/stack/tile))
- try_replace_tile(object, user, modifiers)
- return TRUE
- if(user.combat_mode && istype(object, /obj/item/stack/sheet))
- var/obj/item/stack/sheet/sheets = object
- return sheets.on_attack_floor(src, user, modifiers)
- return FALSE
+
+ if(overfloor_placed && istype(tool, /obj/item/stack/tile))
+ try_replace_tile(tool, user, modifiers)
+ return ITEM_INTERACT_SUCCESS
+
+ if(user.combat_mode && istype(tool, /obj/item/stack/sheet))
+ var/obj/item/stack/sheet/sheets = tool
+ if(!sheets.on_attack_floor(src, user, modifiers))
+ return ITEM_INTERACT_BLOCKING
+
+ return ITEM_INTERACT_SUCCESS
/turf/open/floor/crowbar_act(mob/living/user, obj/item/I)
if(overfloor_placed && pry_tile(I, user))
diff --git a/code/game/turfs/open/floor/light_floor.dm b/code/game/turfs/open/floor/light_floor.dm
index 93ae88597ad..7c5aa262984 100644
--- a/code/game/turfs/open/floor/light_floor.dm
+++ b/code/game/turfs/open/floor/light_floor.dm
@@ -129,21 +129,31 @@
currentcolor = choice
update_appearance()
-/turf/open/floor/light/attackby(obj/item/C, mob/user, list/modifiers)
- if(..())
- return
- if(istype(C, /obj/item/light/bulb)) //only for light tiles
- var/obj/item/light/bulb/B = C
- if(B.status)/// check if broken
- to_chat(user, span_danger("The light bulb is broken!"))
- return
- if(state && user.temporarilyRemoveItemFromInventory(C))
- qdel(C)
- state = LIGHTFLOOR_FINE //fixing it by bashing it with a light bulb, fun eh?
- update_appearance()
- to_chat(user, span_notice("You replace the light bulb."))
- else
- to_chat(user, span_notice("The light bulb seems fine, no need to replace it."))
+/turf/open/floor/light/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = ..()
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
+
+ if(!istype(tool, /obj/item/light/bulb)) //only for light tiles
+ return .
+
+ if(astype(tool, /obj/item/light/bulb).status)/// check if broken
+ to_chat(user, span_danger("The light bulb is broken!"))
+ return ITEM_INTERACT_BLOCKING
+
+ if(!state)
+ to_chat(user, span_notice("The light bulb seems fine, no need to replace it."))
+ return ITEM_INTERACT_BLOCKING
+
+ if(!user.temporarilyRemoveItemFromInventory(tool))
+ return ITEM_INTERACT_BLOCKING
+
+ qdel(tool)
+ state = LIGHTFLOOR_FINE //fixing it by bashing it with a light bulb, fun eh?
+ update_appearance()
+ to_chat(user, span_notice("You replace the light bulb."))
+ return ITEM_INTERACT_SUCCESS
+
/turf/open/floor/light/emp_act(severity)
. = ..()
diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm
index 7718f4b143e..97b9b6edc35 100644
--- a/code/game/turfs/open/floor/plating.dm
+++ b/code/game/turfs/open/floor/plating.dm
@@ -42,99 +42,111 @@
#define PLATE_REINFORCE_COST 2
-/turf/open/floor/plating/attackby(obj/item/C, mob/user, list/modifiers)
- if(..())
- return
- if(istype(C, /obj/item/stack/rods) && attachment_holes)
- if(broken || burnt)
- if(!iscyborg(user))
- to_chat(user, span_warning("Repair the plating first! Use a welding tool to fix the damage."))
- else
- to_chat(user, span_warning("Repair the plating first! Use a welding tool or a plating repair tool to fix the damage.")) //we don't need to confuse humans by giving them a message about plating repair tools, since only janiborgs should have access to them outside of Christmas presents or admin intervention
- return
- var/obj/item/stack/rods/R = C
- if (R.get_amount() < 2)
- to_chat(user, span_warning("You need two rods to make a reinforced floor!"))
- return
- else
- to_chat(user, span_notice("You begin reinforcing the floor..."))
- if(do_after(user, 3 SECONDS, target = src))
- if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine))
- place_on_top(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR)
- playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
- R.use(2)
- to_chat(user, span_notice("You reinforce the floor."))
- return
- else if(istype(C, /obj/item/stack/tile))
- if(!broken && !burnt)
- for(var/obj/O in src)
- for(var/M in O.buckled_mobs)
- to_chat(user, span_warning("Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way."))
- return
- var/obj/item/stack/tile/tile = C
- tile.place_tile(src, user)
- else
- if(!iscyborg(user))
- balloon_alert(user, "too damaged, use a welding tool!")
- else
- balloon_alert(user, "too damaged, use a welding or plating repair tool!")
- else if(istype(C, /obj/item/cautery/prt)) //plating repair tool
- if((broken || burnt) && C.use_tool(src, user, 0, volume=80))
- to_chat(user, span_danger("You fix some dents on the broken plating."))
- icon_state = base_icon_state
- burnt = FALSE
- broken = FALSE
- update_appearance()
- else if(istype(C, /obj/item/stack/sheet/plasteel) && upgradable) //Reinforcement!
- if(!broken && !burnt)
- var/obj/item/stack/sheet/sheets = C
- if(sheets.get_amount() < PLATE_REINFORCE_COST)
- return
- balloon_alert(user, "reinforcing plating...")
- if(do_after(user, 12 SECONDS, target = src))
- if(sheets.get_amount() < PLATE_REINFORCE_COST)
- return
- sheets.use(PLATE_REINFORCE_COST)
- playsound(src, 'sound/machines/creak.ogg', 100, vary = TRUE)
- place_on_top(/turf/open/floor/plating/reinforced, CHANGETURF_INHERIT_AIR)
- else
- if(!iscyborg(user))
- balloon_alert(user, "too damaged, use a welding tool!")
- else
- balloon_alert(user, "too damaged, use a welding or plating repair tool!")
- else if(istype(C, /obj/item/stack/sheet/mineral/plastitanium) && attachment_holes)
- if(broken || burnt)
- if(!iscyborg(user))
- to_chat(user, span_warning("Repair the plating first! Use a welding tool to fix the damage."))
- else
- to_chat(user, span_warning("Repair the plating first! Use a welding tool or a plating repair tool to fix the damage."))
- return
- var/obj/item/stack/sheet/mineral/plastitanium/sheet = C
- if (sheet.get_amount() < 1)
- to_chat(user, span_warning("You are literally holding nothing."))
- return
- else
- balloon_alert(user, "insulating flooring...")
- if(!do_after(user, 1.5 SECONDS, target = src))
- return
- if(sheet.get_amount() < 1 || istype(src, /turf/open/floor/engine/insulation))
- return
- place_on_top(/turf/open/floor/engine/insulation, flags = CHANGETURF_INHERIT_AIR)
- playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
- sheet.use(1)
- to_chat(user, span_notice("You insulate the floor."))
- balloon_alert(user, "insulated!")
+/turf/open/floor/plating/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = ..()
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
+
+ if(istype(tool, /obj/item/stack/rods) && attachment_holes)
+ if(broken || burnt)
+ to_chat(user, span_warning("Repair the plating first! Use a welding tool[iscyborg(user) ? " or a plating repair tool" : ""] to fix the damage."))
+ return ITEM_INTERACT_BLOCKING
+
+ var/obj/item/stack/rods/material = tool
+ if (material.get_amount() < 2)
+ to_chat(user, span_warning("You need two rods to make a reinforced floor!"))
+ return ITEM_INTERACT_BLOCKING
+
+ to_chat(user, span_notice("You begin reinforcing the floor..."))
+ if(!do_after(user, 3 SECONDS, target = src))
+ return ITEM_INTERACT_BLOCKING
+
+ if (material.get_amount() < 2 || istype(src, /turf/open/floor/engine))
+ return ITEM_INTERACT_BLOCKING
+
+ place_on_top(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR)
+ playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
+ material.use(2)
+ to_chat(user, span_notice("You reinforce the floor."))
+ return ITEM_INTERACT_SUCCESS
+
+ if(istype(tool, /obj/item/stack/tile))
+ if(broken || burnt)
+ balloon_alert(user, "too damaged, use a welding[iscyborg(user) ? "or plating repair " : ""] tool!")
+ return ITEM_INTERACT_BLOCKING
+
+ for(var/obj/blocker in src)
+ for(var/mob/sitter as anything in blocker.buckled_mobs)
+ to_chat(user, span_warning("Someone is buckled to \the [blocker]! Unbuckle [sitter] to move [sitter.p_them()] out of the way."))
+ return ITEM_INTERACT_BLOCKING
+
+ var/obj/item/stack/tile/tile = tool
+ tile.place_tile(src, user)
+ return ITEM_INTERACT_SUCCESS
+
+ if(istype(tool, /obj/item/cautery/prt)) //plating repair tool
+ if((!broken && !burnt) || !tool.use_tool(src, user, 0, volume=80))
+ return ITEM_INTERACT_BLOCKING
-/turf/open/floor/plating/welder_act(mob/living/user, obj/item/I)
- ..()
- if((broken || burnt) && I.use_tool(src, user, 0, volume=80))
to_chat(user, span_danger("You fix some dents on the broken plating."))
icon_state = base_icon_state
burnt = FALSE
broken = FALSE
update_appearance()
+ return ITEM_INTERACT_SUCCESS
- return TRUE
+ if(istype(tool, /obj/item/stack/sheet/plasteel) && upgradable) //Reinforcement!
+ if(broken || burnt)
+ balloon_alert(user, "too damaged, use a welding[iscyborg(user) ? "or plating repair " : ""] tool!")
+ return ITEM_INTERACT_BLOCKING
+
+ var/obj/item/stack/sheet/sheets = tool
+ if(sheets.get_amount() < PLATE_REINFORCE_COST)
+ return ITEM_INTERACT_BLOCKING
+
+ balloon_alert(user, "reinforcing plating...")
+ if(!do_after(user, 12 SECONDS, target = src))
+ return ITEM_INTERACT_BLOCKING
+ if(sheets.get_amount() < PLATE_REINFORCE_COST || istype(src, /turf/open/floor/plating/reinforced))
+ return ITEM_INTERACT_BLOCKING
+ sheets.use(PLATE_REINFORCE_COST)
+ playsound(src, 'sound/machines/creak.ogg', 100, vary = TRUE)
+ place_on_top(/turf/open/floor/plating/reinforced, CHANGETURF_INHERIT_AIR)
+ return ITEM_INTERACT_SUCCESS
+
+ if(istype(tool, /obj/item/stack/sheet/mineral/plastitanium) && attachment_holes)
+ if(broken || burnt)
+ to_chat(user, span_warning("Repair the plating first! Use a welding tool[iscyborg(user) ? " or a plating repair tool" : ""] to fix the damage."))
+ return ITEM_INTERACT_BLOCKING
+
+ var/obj/item/stack/sheet/mineral/plastitanium/sheet = tool
+ if (sheet.get_amount() < 1)
+ to_chat(user, span_warning("You are literally holding nothing.")) // finally a reasonable message
+ return ITEM_INTERACT_BLOCKING
+
+ balloon_alert(user, "insulating flooring...")
+ if(!do_after(user, 1.5 SECONDS, target = src))
+ return ITEM_INTERACT_BLOCKING
+
+ if(sheet.get_amount() < 1 || istype(src, /turf/open/floor/engine/insulation))
+ return ITEM_INTERACT_BLOCKING
+
+ place_on_top(/turf/open/floor/engine/insulation, flags = CHANGETURF_INHERIT_AIR)
+ playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
+ sheet.use(1)
+ to_chat(user, span_notice("You insulate the floor."))
+ balloon_alert(user, "insulated!")
+ return ITEM_INTERACT_SUCCESS
+
+/turf/open/floor/plating/welder_act(mob/living/user, obj/item/tool)
+ if((!broken && !burnt) || !tool.use_tool(src, user, 0, volume=80))
+ return NONE
+ to_chat(user, span_danger("You fix some dents on the broken plating."))
+ icon_state = base_icon_state
+ burnt = FALSE
+ broken = FALSE
+ update_appearance()
+ return ITEM_INTERACT_SUCCESS
#undef PLATE_REINFORCE_COST
@@ -239,20 +251,21 @@
icon_state = "r_plate-[deconstruction_state]"
return ..()
-/turf/open/floor/plating/reinforced/attackby(obj/item/tool_used, mob/user, list/modifiers)
+/turf/open/floor/plating/reinforced/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
user.changeNext_move(CLICK_CD_MELEE)
if (!ISADVANCEDTOOLUSER(user))
to_chat(user, span_warning("You don't have the dexterity to do this!"))
- return
+ return ITEM_INTERACT_BLOCKING
//get the user's location
if(!isturf(user.loc))
- return //can't do this stuff whilst inside objects and such
+ return ITEM_INTERACT_BLOCKING//can't do this stuff whilst inside objects and such
add_fingerprint(user)
- if(deconstruct_steps(tool_used, user))
- return
+ if(deconstruct_steps(tool, user))
+ return ITEM_INTERACT_SUCCESS
+
return ..()
/turf/open/floor/plating/reinforced/proc/deconstruct_steps(obj/item/tool_used, mob/user)
diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm
index 63a4e1e5045..cd33a38fef7 100644
--- a/code/game/turfs/open/lava.dm
+++ b/code/game/turfs/open/lava.dm
@@ -205,35 +205,41 @@
/turf/open/lava/TakeTemperature(temp)
-/turf/open/lava/attackby(obj/item/C, mob/user, list/modifiers)
- ..()
- if(istype(C, /obj/item/stack/rods/lava))
- var/obj/item/stack/rods/lava/R = C
- var/obj/structure/lattice/catwalk/lava/H = locate(/obj/structure/lattice/catwalk/lava, src)
- if(H)
+/turf/open/lava/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = ..()
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
+
+ if(istype(tool, /obj/item/stack/rods/lava))
+ if(locate(/obj/structure/lattice/catwalk/lava, src))
to_chat(user, span_warning("There is already a lattice here!"))
- return
- if(R.use(1))
- to_chat(user, span_notice("You construct a lattice."))
- playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE)
- new /obj/structure/lattice/catwalk/lava(locate(x, y, z))
- else
+ return ITEM_INTERACT_BLOCKING
+
+ if(!astype(tool, /obj/item/stack/rods/lava).use(1))
to_chat(user, span_warning("You need one rod to build a heatproof lattice."))
- return
+ return ITEM_INTERACT_BLOCKING
+
+ to_chat(user, span_notice("You construct a lattice."))
+ playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE)
+ new /obj/structure/lattice/catwalk/lava(locate(x, y, z))
+ return ITEM_INTERACT_SUCCESS
+
// Light a cigarette in the lava
- if(istype(C, /obj/item/cigarette))
- var/obj/item/cigarette/ciggie = C
+ if(istype(tool, /obj/item/cigarette))
+ var/obj/item/cigarette/ciggie = tool
if(ciggie.lit)
to_chat(user, span_warning("\The [ciggie] is already lit!"))
- return TRUE
+ return ITEM_INTERACT_BLOCKING
+
var/clumsy_modifier = HAS_TRAIT(user, TRAIT_CLUMSY) ? 2 : 1
- if(prob(25 * clumsy_modifier) && isliving(user))
+ if(prob(25 * clumsy_modifier))
ciggie.light(span_warning("[user] expertly dips \the [ciggie.name] into [src], along with the rest of [user.p_their()] arm. What a dumbass."))
var/mob/living/burned_guy = user
burned_guy.apply_damage(90, BURN, user.get_active_hand())
- else
- ciggie.light(span_rose("[user] expertly dips \the [ciggie.name] into [src], lighting it with the scorching heat of the planet. Witnessing such a feat is almost enough to make you cry."))
- return TRUE
+ return ITEM_INTERACT_SUCCESS
+
+ ciggie.light(span_rose("[user] expertly dips \the [ciggie.name] into [src], lighting it with the scorching heat of the planet. Witnessing such a feat is almost enough to make you cry."))
+ return ITEM_INTERACT_SUCCESS
/turf/open/lava/proc/is_safe()
return HAS_TRAIT(src, TRAIT_LAVA_STOPPED)
diff --git a/code/game/turfs/open/misc.dm b/code/game/turfs/open/misc.dm
index 666ad1aef85..7a4bdacf781 100644
--- a/code/game/turfs/open/misc.dm
+++ b/code/game/turfs/open/misc.dm
@@ -21,18 +21,18 @@
heat_capacity = 20000
tiled_turf = TRUE
-/turf/open/misc/attackby(obj/item/attacking_item, mob/user, list/modifiers)
+/turf/open/misc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
- if(.)
- return TRUE
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
- if(istype(attacking_item, /obj/item/stack/rods))
- build_with_rods(attacking_item, user)
- return TRUE
+ if(istype(tool, /obj/item/stack/rods))
+ build_with_rods(tool, user)
+ return ITEM_INTERACT_SUCCESS
- if(ismetaltile(attacking_item))
- build_with_floor_tiles(attacking_item, user)
- return TRUE
+ if(ismetaltile(tool))
+ build_with_floor_tiles(tool, user)
+ return ITEM_INTERACT_SUCCESS
/turf/open/misc/attack_paw(mob/user, list/modifiers)
return attack_hand(user, modifiers)
diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm
index 380d7bbf315..da9141e400c 100644
--- a/code/game/turfs/open/openspace.dm
+++ b/code/game/turfs/open/openspace.dm
@@ -114,18 +114,24 @@
/turf/open/openspace/CanBuildHere()
return can_build_on
-/turf/open/openspace/attackby(obj/item/attacking_item, mob/user, list/modifiers)
- ..()
+/turf/open/openspace/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = ..()
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
+
if(!CanBuildHere())
- return
- if(istype(attacking_item, /obj/item/stack/rods))
- build_with_rods(attacking_item, user)
- else if(ismetaltile(attacking_item))
- build_with_floor_tiles(attacking_item, user)
- else if(istype(attacking_item, /obj/item/stack/thermoplastic))
- build_with_transport_tiles(attacking_item, user)
- else if(istype(attacking_item, /obj/item/stack/sheet/mineral/titanium))
- build_with_titanium(attacking_item, user)
+ return .
+
+ if(istype(tool, /obj/item/stack/rods))
+ build_with_rods(tool, user)
+ else if(ismetaltile(tool))
+ build_with_floor_tiles(tool, user)
+ else if(istype(tool, /obj/item/stack/thermoplastic))
+ build_with_transport_tiles(tool, user)
+ else if(istype(tool, /obj/item/stack/sheet/mineral/titanium))
+ build_with_titanium(tool, user)
+
+ return ITEM_INTERACT_SUCCESS
/turf/open/openspace/build_with_floor_tiles(obj/item/stack/tile/iron/used_tiles)
if(!CanCoverUp())
diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm
index e4c447008da..5045e6136ff 100644
--- a/code/game/turfs/open/space/space.dm
+++ b/code/game/turfs/open/space/space.dm
@@ -127,14 +127,19 @@ GLOBAL_LIST_EMPTY(starlight)
/turf/open/space/handle_slip()
return
-/turf/open/space/attackby(obj/item/attacking_item, mob/user, list/modifiers)
- ..()
+/turf/open/space/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = ..()
+ if(ITEM_INTERACT_ANY_BLOCKER & .)
+ return .
+
if(!CanBuildHere())
- return
- if(istype(attacking_item, /obj/item/stack/rods))
- build_with_rods(attacking_item, user)
- else if(ismetaltile(attacking_item))
- build_with_floor_tiles(attacking_item, user)
+ return .
+
+ if(istype(tool, /obj/item/stack/rods))
+ build_with_rods(tool, user)
+ else if(ismetaltile(tool))
+ build_with_floor_tiles(tool, user)
+ return ITEM_INTERACT_SUCCESS
/turf/open/space/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
return
diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm
index 62c346be9a1..47457310fca 100644
--- a/code/modules/cargo/supplypod.dm
+++ b/code/modules/cargo/supplypod.dm
@@ -253,11 +253,10 @@
if(decal)
. += decal
-/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user)
+/obj/structure/closet/supplypod/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
- return FALSE
- else
- ..()
+ return ITEM_INTERACT_BLOCKING
+ return ..()
/obj/structure/closet/supplypod/ex_act() //Explosions dont do SHIT TO US! This is because supplypods create explosions when they land.
return FALSE
diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
index ffcd8c07a49..fe8997d47ae 100644
--- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
+++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm
@@ -234,52 +234,56 @@
dug_closed = FALSE
return TRUE
-/obj/structure/closet/crate/grave/tool_interact(obj/item/weapon, mob/living/carbon/user)
+/obj/structure/closet/crate/grave/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
//anything that isn't a shovel does normal stuff to the grave[like putting stuff in]
- if(weapon.tool_behaviour != TOOL_SHOVEL)
+ if(tool.tool_behaviour != TOOL_SHOVEL)
return ..()
- //player is attempting to open/close the grave with a shovel
- if(!user.combat_mode)
- user.visible_message(
- span_notice("[user] Is attempting to [opened ? "close" : "dig open"] [src]."),
- span_notice("You start [opened ? "closing" : "digging open"] [src]."),
- )
- if(!weapon.use_tool(src, user, delay = 15, volume = 40))
- return TRUE
-
- var/is_chill_with_robbing = HAS_MIND_TRAIT(user, TRAIT_MORBID) || HAS_PERSONALITY(user, /datum/personality/callous) || HAS_PERSONALITY(user, /datum/personality/misanthropic)
- if(opened)
- dug_closed = TRUE
- close(user)
- else if(open(user, force = TRUE) && affect_mood)
- user.add_mood_event("graverobbing", is_chill_with_robbing ? /datum/mood_event/morbid_graverobbing : /datum/mood_event/graverobbing)
- if(lead_tomb && first_open)
- if(is_chill_with_robbing)
- to_chat(user, span_notice("Did someone say something? I'm sure it was nothing."))
- else
- user.gain_trauma(/datum/brain_trauma/magic/stalker)
- to_chat(user, span_boldwarning("Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!"))
- first_open = FALSE
-
- return TRUE
//player is attempting to destroy the open grave with a shovel
- else
+ if(user.combat_mode)
if(!opened)
- return TRUE
+ return ITEM_INTERACT_BLOCKING
user.visible_message(
span_notice("[user] Is attempting to remove [src]."),
span_notice("You start removing [src]."),
)
- if(!weapon.use_tool(src, user, delay = 15, volume = 40) || !opened)
- return TRUE
+ if(!tool.use_tool(src, user, delay = 1.5 SECONDS , volume = 40) || !opened)
+ return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You remove \the [src] completely."))
user.add_mood_event("graverobbing", /datum/mood_event/graverobbing)
deconstruct(TRUE)
- return TRUE
+ return ITEM_INTERACT_SUCCESS
+
+ //player is attempting to open/close the grave with a shovel
+ user.visible_message(
+ span_notice("[user] Is attempting to [opened ? "close" : "dig open"] [src]."),
+ span_notice("You start [opened ? "closing" : "digging open"] [src]."),
+ )
+ if(!tool.use_tool(src, user, delay = 1.5 SECONDS, volume = 40))
+ return ITEM_INTERACT_BLOCKING
+
+ var/is_chill_with_robbing = HAS_MIND_TRAIT(user, TRAIT_MORBID) || HAS_PERSONALITY(user, /datum/personality/callous) || HAS_PERSONALITY(user, /datum/personality/misanthropic)
+ if(opened)
+ dug_closed = TRUE
+ close(user)
+ return ITEM_INTERACT_SUCCESS
+
+ if(!open(user, force = TRUE) || !affect_mood)
+ return ITEM_INTERACT_SUCCESS
+
+ user.add_mood_event("graverobbing", is_chill_with_robbing ? /datum/mood_event/morbid_graverobbing : /datum/mood_event/graverobbing)
+ if(lead_tomb && first_open)
+ if(is_chill_with_robbing || !astype(user, /mob/living/carbon)?.gain_trauma(/datum/brain_trauma/magic/stalker))
+ to_chat(user, span_notice("Did someone say something? I'm sure it was nothing."))
+ else
+ to_chat(user, span_boldwarning("Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!"))
+ first_open = FALSE
+
+ return ITEM_INTERACT_SUCCESS
+
/obj/structure/closet/crate/grave/container_resist_act(mob/living/user, loc_required = TRUE)
if(opened)
diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm
index bef136cabea..2e3d21141f1 100644
--- a/code/modules/mod/modules/modules_supply.dm
+++ b/code/modules/mod/modules/modules_supply.dm
@@ -212,7 +212,7 @@
var/has_ore = !isnull(rock.mineral_type)
if (has_ore)
toolspeed /= 2
- rock.attackby(src, bumper, null, null, exp_multiplier)
+ rock.manual_mine(bumper, src, exp_multiplier)
if (has_ore)
toolspeed *= 2