From e816dfebeb47ee81498a36f3d00f462915f7de07 Mon Sep 17 00:00:00 2001 From: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Date: Sun, 5 Jul 2026 04:02:06 -0400 Subject: [PATCH] Moves a great many things from attackby() to item_interaction() (#96642) ## About The Pull Request 21 things. Additionally, an actual refactor(a real one) of refunding of item-based spellbook entries, as in the three summons, which hasn't worked for four years and now does. Lastly, the holopayment stand IDs can project can now accept payment. ## Why It's Good For The Game They want you to think this is worth 210 gbp, don't believe the lies ## Changelog :cl: fix: Wizards can now successfully refund summoning items fix: Holopayment stands can now take payment code: 21 things have been moved from attackby() to item_interaction() /:cl: --- .../civilian_bounty/bounty_machinery.dm | 13 ++-- code/game/machinery/prisonlabor.dm | 23 +++--- code/game/objects/effects/posters/poster.dm | 17 ++--- code/game/objects/items/cardboard_cutouts.dm | 11 ++- code/game/objects/items/puzzle_pieces.dm | 12 ++-- code/game/objects/items/secret_documents.dm | 25 ++++--- .../equipment/spellbook_entries/_entry.dm | 10 +++ .../equipment/spellbook_entries/assistance.dm | 3 - .../wizard/equipment/wizard_spellbook.dm | 70 +++++++------------ code/modules/economy/holopay.dm | 57 +++++++-------- .../library/skill_learning/skill_station.dm | 20 +++--- .../kinetic_crusher/kinetic_crusher.dm | 11 ++- code/modules/mob/living/basic/vermin/mouse.dm | 30 ++++---- code/modules/paperwork/clipboard.dm | 40 +++++++---- code/modules/paperwork/filingcabinet.dm | 32 +++++---- code/modules/paperwork/paper.dm | 28 ++++---- code/modules/paperwork/paperbin.dm | 57 ++++++++------- code/modules/paperwork/paperplane.dm | 14 ++-- code/modules/paperwork/paperwork.dm | 47 ++++++------- code/modules/paperwork/ticketmachine.dm | 44 ++++++------ code/modules/photography/photos/frame.dm | 45 ++++++------ code/modules/photography/photos/photo.dm | 21 +++--- code/modules/power/power.dm | 23 +++--- 23 files changed, 332 insertions(+), 321 deletions(-) diff --git a/code/game/machinery/civilian_bounty/bounty_machinery.dm b/code/game/machinery/civilian_bounty/bounty_machinery.dm index 9ceeeed84aa..442290ddde4 100644 --- a/code/game/machinery/civilian_bounty/bounty_machinery.dm +++ b/code/game/machinery/civilian_bounty/bounty_machinery.dm @@ -41,12 +41,13 @@ ///Cooldown for printing the bounty sheet, and not breaking people's eardrums. COOLDOWN_DECLARE(sheet_printer_cooldown) -/obj/machinery/computer/piratepad_control/civilian/attackby(obj/item/I, mob/living/user, list/modifiers, list/attack_modifiers) - if(isidcard(I)) - if(id_insert(user, I, inserted_scan_id)) - inserted_scan_id = I - return TRUE - return ..() +/obj/machinery/computer/piratepad_control/civilian/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!isidcard(tool)) + return NONE + if(!id_insert(user, tool, inserted_scan_id)) + return ITEM_INTERACT_BLOCKING + inserted_scan_id = tool + return ITEM_INTERACT_SUCCESS /obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I) if(istype(I) && istype(I.buffer,/obj/machinery/piratepad/civilian)) diff --git a/code/game/machinery/prisonlabor.dm b/code/game/machinery/prisonlabor.dm index f7b2bbb5e24..ddca8462e97 100644 --- a/code/game/machinery/prisonlabor.dm +++ b/code/game/machinery/prisonlabor.dm @@ -26,20 +26,21 @@ QDEL_NULL(current_plate) . = ..() -/obj/machinery/plate_press/attackby(obj/item/I, mob/living/user, list/modifiers, list/attack_modifiers) +/obj/machinery/plate_press/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/stack/license_plates/empty)) + return NONE if(!is_operational) - to_chat(user, span_warning("[src] has to be on to do this!")) - return FALSE + to_chat(user, span_warning("[src] has to be on to be loaded!")) + return ITEM_INTERACT_BLOCKING if(current_plate) to_chat(user, span_warning("[src] already has a plate in it!")) - return FALSE - if(istype(I, /obj/item/stack/license_plates/empty)) - var/obj/item/stack/license_plates/empty/plate = I - plate.use(1) - current_plate = new plate.type(src, 1) //Spawn a new single sheet in the machine - update_appearance() - else - return ..() + return ITEM_INTERACT_BLOCKING + + var/obj/item/stack/license_plates/empty/plate = tool + plate.use(1) + current_plate = new plate.type(src, 1) //Spawn a new single sheet in the machine + update_appearance() + return ITEM_INTERACT_SUCCESS /obj/machinery/plate_press/attack_hand(mob/living/user, list/modifiers) . = ..() diff --git a/code/game/objects/effects/posters/poster.dm b/code/game/objects/effects/posters/poster.dm index fd66c4241ae..4068e893c73 100644 --- a/code/game/objects/effects/posters/poster.dm +++ b/code/game/objects/effects/posters/poster.dm @@ -56,18 +56,19 @@ . = ..() . += span_notice("You can booby-trap the poster by using a glass shard on it before you put it up.") -/obj/item/poster/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - if(!istype(I, /obj/item/shard)) - return ..() +/obj/item/poster/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/shard)) + return NONE - if (locate(/obj/item/shard) in (poster_structure?.contents || contents)) + if(locate(/obj/item/shard) in (poster_structure?.contents || contents)) balloon_alert(user, "already trapped!") - return + return ITEM_INTERACT_BLOCKING - if(!user.transferItemToLoc(I, src)) - return + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING - to_chat(user, span_notice("You conceal \the [I] inside the rolled up poster.")) + to_chat(user, span_notice("You conceal \the [tool] inside the rolled up poster.")) + return ITEM_INTERACT_SUCCESS /obj/item/poster/interact_with_atom(turf/closed/wall_structure, mob/living/user, list/modifiers) if(!isclosedturf(wall_structure)) diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm index 89f9a14d99c..2ccf031f61b 100644 --- a/code/game/objects/items/cardboard_cutouts.dm +++ b/code/game/objects/items/cardboard_cutouts.dm @@ -80,12 +80,11 @@ pushed_over = FALSE tacticool = AddComponent(/datum/component/tactical) -/obj/item/cardboard_cutout/attackby(obj/item/I, mob/living/user, list/modifiers, list/attack_modifiers) - if(istype(I, /obj/item/toy/crayon)) - change_appearance(I, user) - return TRUE - - return ..() +/obj/item/cardboard_cutout/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/toy/crayon)) + return NONE + change_appearance(tool, user) + return ITEM_INTERACT_SUCCESS /obj/item/cardboard_cutout/take_damage(damage_amount, damage_type, damage_flag, sound_effect, attack_dir, armour_penetration) . = ..() diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 9256ac01307..6ed39149dd9 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -124,13 +124,13 @@ desc = "This door only opens when a keycard is swiped. It looks virtually indestructible." uses_queuelinks = FALSE -/obj/machinery/door/puzzle/keycard/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - . = ..() - if(!istype(attacking_item, /obj/item/keycard)) - return - var/obj/item/keycard/key = attacking_item - if(!try_puzzle_open(key.puzzle_id)) +/obj/machinery/door/puzzle/keycard/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/keycard)) + return NONE + if(!try_puzzle_open(astype(tool, /obj/item/keycard).puzzle_id)) to_chat(user, span_notice("[src] buzzes. This must not be the right key.")) + return ITEM_INTERACT_BLOCKING + return ITEM_INTERACT_SUCCESS //Test doors. Gives admins a few doors to use quickly should they so choose for events. /obj/machinery/door/puzzle/keycard/yellow_required diff --git a/code/game/objects/items/secret_documents.dm b/code/game/objects/items/secret_documents.dm index 91a2a8934e4..e893e126235 100644 --- a/code/game/objects/items/secret_documents.dm +++ b/code/game/objects/items/secret_documents.dm @@ -66,14 +66,17 @@ var/obj/item/documents/photocopy/C = copy copy_type = C.copy_type -/obj/item/documents/photocopy/attackby(obj/item/O, mob/user, list/modifiers, list/attack_modifiers) - if(istype(O, /obj/item/toy/crayon/red) || istype(O, /obj/item/toy/crayon/blue)) - if (forgedseal) - to_chat(user, span_warning("You have already forged a seal on [src]!")) - else - var/obj/item/toy/crayon/C = O - name = "[C.crayon_color] secret documents" - icon_state = "docs_[C.crayon_color]" - forgedseal = C.crayon_color - to_chat(user, span_notice("You forge the official seal with a [C.crayon_color] crayon. No one will notice... right?")) - update_appearance() +/obj/item/documents/photocopy/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/toy/crayon/red) && !istype(tool, /obj/item/toy/crayon/blue)) + return NONE + if (forgedseal) + to_chat(user, span_warning("You have already forged a seal on [src]!")) + return ITEM_INTERACT_BLOCKING + + var/obj/item/toy/crayon/C = tool + name = "[C.crayon_color] secret documents" + icon_state = "docs_[C.crayon_color]" + forgedseal = C.crayon_color + to_chat(user, span_notice("You forge the official seal with a [C.crayon_color] crayon. No one will notice... right?")) + update_appearance() + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm index cf499350dea..1c2a2e7f9e6 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm @@ -228,6 +228,16 @@ var/was_put_in_hands = user.put_in_hands(to_equip) to_chat(user, span_notice("\A [to_equip.name] has been summoned [was_put_in_hands ? "in your hands" : "at your feet"].")) +/datum/spellbook_entry/item/can_refund(mob/living/carbon/human/user, obj/item/spellbook/book, obj/item/refunding_item) + if(HAS_TRAIT(user, TRAIT_SPELLS_LOTTERY)) + to_chat(user, span_notice("No refund.")) + return FALSE + if(!book.refunds_allowed) // We're not doing a check for refundable here because they're not refundable in-book. + return FALSE + if(refunding_item.type != item_path) + return FALSE + return TRUE + /// Ritual, these cause station wide effects and are (pretty much) a blank slate to implement stuff in /datum/spellbook_entry/summon category = "Rituals" diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm index 69c33e751ec..381ee5f513c 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/assistance.dm @@ -64,7 +64,6 @@ desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side." item_path = /obj/item/antag_spawner/contract category = SPELLBOOK_CATEGORY_ASSISTANCE - refundable = TRUE /datum/spellbook_entry/item/guardian name = "Guardian Deck" @@ -82,7 +81,6 @@ item_path = /obj/item/antag_spawner/slaughter_demon limit = 3 category = SPELLBOOK_CATEGORY_ASSISTANCE - refundable = TRUE /datum/spellbook_entry/item/hugbottle name = "Bottle of Tickles" @@ -97,7 +95,6 @@ cost = 1 //non-destructive; it's just a jape, sibling! limit = 3 category = SPELLBOOK_CATEGORY_ASSISTANCE - refundable = TRUE /datum/spellbook_entry/item/vendormancer name = "Scepter of Vendormancy" diff --git a/code/modules/antagonists/wizard/equipment/wizard_spellbook.dm b/code/modules/antagonists/wizard/equipment/wizard_spellbook.dm index 914651706e3..6d460286d9c 100644 --- a/code/modules/antagonists/wizard/equipment/wizard_spellbook.dm +++ b/code/modules/antagonists/wizard/equipment/wizard_spellbook.dm @@ -74,55 +74,39 @@ return ..() -/obj/item/spellbook/attackby(obj/item/O, mob/user, list/modifiers, list/attack_modifiers) +/obj/item/spellbook/item_interaction(mob/living/user, obj/item/tool, list/modifiers) // This can be generalized in the future, but for now it stays - if(istype(O, /obj/item/antag_spawner/contract)) - var/datum/spellbook_entry/item/contract/contract_entry = locate() in entries - if(!istype(contract_entry)) - to_chat(user, span_warning("[src] doesn't seem to want to refund [O].")) - return - if(!contract_entry.can_refund(user, src)) - to_chat(user, span_warning("You can't refund [src].")) - return - var/obj/item/antag_spawner/contract/contract = O - if(contract.used) + var/datum/spellbook_entry/item/spawner_entry + var/success_string + if(istype(tool, /obj/item/antag_spawner/contract)) + if(astype(tool, /obj/item/antag_spawner/contract).used) to_chat(user, span_warning("The contract has been used, you can't get your points back now!")) - return + return ITEM_INTERACT_BLOCKING + spawner_entry = locate(/datum/spellbook_entry/item/contract) in entries + success_string = "You feed the contract back into the spellbook, refunding your points." - to_chat(user, span_notice("You feed the contract back into the spellbook, refunding your points.")) - uses += contract_entry.cost - contract_entry.times-- - qdel(O) + if(istype(tool, /obj/item/antag_spawner/slaughter_demon/laughter)) + spawner_entry = locate(/datum/spellbook_entry/item/hugbottle) in entries + success_string = "On second thought, maybe summoning a demon isn't a funny idea. You refund your points." - else if(istype(O, /obj/item/antag_spawner/slaughter_demon/laughter)) - var/datum/spellbook_entry/item/hugbottle/demon_entry = locate() in entries - if(!istype(demon_entry)) - to_chat(user, span_warning("[src] doesn't seem to want to refund [O].")) - return - if(!demon_entry.can_refund(user, src)) - to_chat(user, span_warning("You can't refund [O].")) - return + else if(istype(tool, /obj/item/antag_spawner/slaughter_demon)) + spawner_entry = locate(/datum/spellbook_entry/item/bloodbottle) in entries + success_string = "On second thought, maybe summoning a demon is a bad idea. You refund your points." - to_chat(user, span_notice("On second thought, maybe summoning a demon isn't a funny idea. You refund your points.")) - uses += demon_entry.cost - demon_entry.times-- - qdel(O) + if(isnull(success_string)) + return NONE + if(!istype(spawner_entry)) // No success_string means it isn't a valid item, no spawner entry means the book doesn't have it(somehow)(they had this check before I got here) + to_chat(user, span_warning("[src] doesn't seem to want to refund [tool].")) + return ITEM_INTERACT_BLOCKING + if(!spawner_entry.can_refund(user, src, tool)) + to_chat(user, span_warning("You can't refund [src].")) + return ITEM_INTERACT_BLOCKING - else if(istype(O, /obj/item/antag_spawner/slaughter_demon)) - var/datum/spellbook_entry/item/bloodbottle/demon_entry = locate() in entries - if(!istype(demon_entry)) - to_chat(user, span_warning("[src] doesn't seem to want to refund [O].")) - return - if(!demon_entry.can_refund(user, src)) - to_chat(user, span_warning("You can't refund [O].")) - return - - to_chat(user, span_notice("On second thought, maybe summoning a demon is a bad idea. You refund your points.")) - uses += demon_entry.cost - demon_entry.times-- - qdel(O) - - return ..() + to_chat(user, span_notice(success_string)) + uses += spawner_entry.cost + spawner_entry.times-- + qdel(tool) + return ITEM_INTERACT_SUCCESS /// Instantiates our list of spellbook entries. /obj/item/spellbook/proc/prepare_spells() diff --git a/code/modules/economy/holopay.dm b/code/modules/economy/holopay.dm index 186c5cc7736..cfbb0bcd090 100644 --- a/code/modules/economy/holopay.dm +++ b/code/modules/economy/holopay.dm @@ -74,60 +74,57 @@ linked_card = null return ..() -/obj/structure/holopay/attackby(obj/item/held_item, mob/item_holder, list/modifiers, list/attack_modifiers) - var/mob/living/user = item_holder - if(!isliving(user)) - return ..() +/obj/structure/holopay/item_interaction(mob/living/user, obj/item/tool, list/modifiers) /// Users can pay with an ID to skip the UI - if(isidcard(held_item)) - if(istype(held_item, /obj/item/card/id/departmental_budget)) + if(isidcard(tool)) + if(istype(tool, /obj/item/card/id/departmental_budget)) balloon_alert(user, "invalid payment card") to_chat(user, span_warning("You cannot use a departamental card for this.")) - return FALSE - if(force_fee && tgui_alert(item_holder, "This holopay has a [force_fee] [MONEY_SYMBOL] fee. Confirm?", "Holopay Fee", list("Pay", "Cancel")) != "Pay") - return TRUE + return ITEM_INTERACT_BLOCKING + if(force_fee && tgui_alert(user, "This holopay has a [force_fee] [MONEY_SYMBOL] fee. Confirm?", "Holopay Fee", list("Pay", "Cancel")) != "Pay") + return ITEM_INTERACT_BLOCKING process_payment(user) - return TRUE + return ITEM_INTERACT_SUCCESS /// Users can also pay by holochip - if(istype(held_item, /obj/item/holochip)) + if(istype(tool, /obj/item/holochip)) /// Account checks - var/obj/item/holochip/chip = held_item + var/obj/item/holochip/chip = tool if(!chip.credits) balloon_alert(user, "holochip is empty") to_chat(user, span_warning("There doesn't seem to be any [MONEY_NAME] here.")) - return FALSE + return ITEM_INTERACT_BLOCKING /// Charges force fee or uses pay what you want var/cash_deposit = force_fee || tgui_input_number(user, "How much? (Max: [chip.credits])", "Patronage", max_value = chip.credits) /// Exit sanity checks if(!cash_deposit) - return TRUE - if(QDELETED(held_item) || QDELETED(user) || QDELETED(src) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return FALSE + return ITEM_INTERACT_BLOCKING + if(QDELETED(tool) || QDELETED(user) || QDELETED(src) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + return ITEM_INTERACT_BLOCKING if(!chip.spend(cash_deposit, FALSE)) balloon_alert(user, "insufficient [MONEY_NAME]") to_chat(user, span_warning("You don't have enough [MONEY_NAME] to pay with this chip.")) - return FALSE + return ITEM_INTERACT_BLOCKING /// Success: Alert buyer alert_buyer(user, cash_deposit) - return TRUE + return ITEM_INTERACT_SUCCESS /// Throws errors if they try to use space cash - if(istype(held_item, /obj/item/stack/spacecash)) + if(istype(tool, /obj/item/stack/spacecash)) to_chat(user, "What is this, the 2000s? We only take card here.") - return TRUE - if(istype(held_item, /obj/item/coin)) + return ITEM_INTERACT_BLOCKING + if(istype(tool, /obj/item/coin)) to_chat(user, "What is this, the 1800s? We only take card here.") - return TRUE - return ..() + return ITEM_INTERACT_BLOCKING + return NONE -/obj/structure/holopay/attackby_secondary(obj/item/weapon, mob/user, list/modifiers, list/attack_modifiers) +/obj/structure/holopay/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) /// Can kill it by right-clicking with ID because it seems useful and intuitive, to me, at least - if(!isidcard(weapon)) - return ..() - var/obj/item/card/id/attacking_id = weapon + if(!isidcard(tool)) + return NONE + var/obj/item/card/id/attacking_id = tool if(!attacking_id.my_store || attacking_id.my_store != src) - return ..() + return ITEM_INTERACT_BLOCKING dissipate() - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS /obj/structure/holopay/ui_interact(mob/user, datum/tgui/ui) . = ..() @@ -259,7 +256,7 @@ /// Account checks var/obj/item/card/id/id_card id_card = user.get_idcard(TRUE) - if(isnull(id_card) || id_card.can_be_used_in_payment(user)) + if(isnull(id_card) || !id_card.can_be_used_in_payment(user)) balloon_alert(user, "invalid account") to_chat(user, span_warning("You don't have a valid account.")) return FALSE diff --git a/code/modules/library/skill_learning/skill_station.dm b/code/modules/library/skill_learning/skill_station.dm index db21181e9b9..374997153d1 100644 --- a/code/modules/library/skill_learning/skill_station.dm +++ b/code/modules/library/skill_learning/skill_station.dm @@ -83,16 +83,16 @@ else toggle_open() -/obj/machinery/skill_station/attackby(obj/item/I, mob/living/user, list/modifiers, list/attack_modifiers) - if(istype(I,/obj/item/skillchip)) - if(inserted_skillchip) - to_chat(user,span_notice("There's already a skillchip inside.")) - return - if(!user.transferItemToLoc(I, src)) - return - inserted_skillchip = I - return - return ..() +/obj/machinery/skill_station/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool,/obj/item/skillchip)) + return NONE + if(inserted_skillchip) + to_chat(user,span_notice("There's already a skillchip inside.")) + return ITEM_INTERACT_BLOCKING + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + inserted_skillchip = tool + return ITEM_INTERACT_SUCCESS /obj/machinery/skill_station/dump_contents() . = ..() diff --git a/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm index 9f72047fcde..1036a196e4d 100644 --- a/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher/kinetic_crusher.dm @@ -119,12 +119,11 @@ for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) . += span_notice("It has \a [crusher_trophy] attached, which causes [crusher_trophy.effect_desc()].") -/obj/item/kinetic_crusher/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - if(istype(attacking_item, /obj/item/crusher_trophy)) - var/obj/item/crusher_trophy/crusher_trophy = attacking_item - crusher_trophy.add_to(src, user) - return - return ..() +/obj/item/kinetic_crusher/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/crusher_trophy)) + astype(tool, /obj/item/crusher_trophy).add_to(src, user) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/kinetic_crusher/crowbar_act(mob/living/user, obj/item/tool) . = ..() diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 67cae390295..b102fc8cf6c 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -381,24 +381,22 @@ qdel(src) return LAZARUS_INJECTOR_USED -/obj/item/food/deadmouse/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - var/mob/living/living_user = user - if(istype(living_user) && attacking_item.get_sharpness() && living_user.combat_mode) - if(!isturf(loc)) - balloon_alert(user, "can't butcher here!") - return +/obj/item/food/deadmouse/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!tool.get_sharpness() || !user.combat_mode) + return NONE + if(!isturf(loc)) + balloon_alert(user, "can't butcher here!") + return ITEM_INTERACT_BLOCKING - balloon_alert(user, "butchering...") - if(!do_after(user, 0.75 SECONDS, src)) - balloon_alert(user, "interrupted!") - return + balloon_alert(user, "butchering...") + if(!do_after(user, 0.75 SECONDS, src)) + balloon_alert(user, "interrupted!") + return ITEM_INTERACT_BLOCKING - loc.balloon_alert(user, "butchered") - new /obj/item/food/meat/slab/mouse(loc) - qdel(src) - return - - return ..() + loc.balloon_alert(user, "butchered") + new /obj/item/food/meat/slab/mouse(loc) + qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/food/deadmouse/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(isnull(reagents) || !interacting_with.is_open_container()) diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index 6bd119eef7b..33cd23470bd 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -121,25 +121,35 @@ return TRUE . = ..() -/obj/item/clipboard/attackby(obj/item/weapon, mob/user, list/modifiers, list/attack_modifiers) - if(istype(weapon, /obj/item/paper)) +/obj/item/clipboard/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/paper)) //Add paper into the clipboard - if(!user.transferItemToLoc(weapon, src)) - return + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING if(top_paper) UnregisterSignal(top_paper, COMSIG_ATOM_UPDATED_ICON) - RegisterSignal(weapon, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_top_paper_change)) - top_paper = weapon - to_chat(user, span_notice("You clip [weapon] onto [src].")) - else if(istype(weapon, /obj/item/pen) && !pen) + RegisterSignal(tool, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_top_paper_change)) + top_paper = tool + to_chat(user, span_notice("You clip [tool] onto [src].")) + update_appearance() + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/pen) && !pen) //Add a pen into the clipboard, attack (write) if there is already one - if(!usr.transferItemToLoc(weapon, src)) - return - pen = weapon - to_chat(usr, span_notice("You slot [weapon] into [src].")) - else if(top_paper) - top_paper.attackby(user.get_active_held_item(), user) - update_appearance() + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + pen = tool + to_chat(user, span_notice("You slot [tool] into [src].")) + update_appearance() + return ITEM_INTERACT_SUCCESS + + if(top_paper) + top_paper.item_interaction(user, user.get_active_held_item()) + update_appearance() + return ITEM_INTERACT_SUCCESS + + return NONE + /obj/item/clipboard/attack_self(mob/user) add_fingerprint(usr) diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 7f51baea891..d0877cdd259 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -43,23 +43,27 @@ for(var/obj/item/obj in src) obj.forceMove(loc) -/obj/structure/filingcabinet/attackby(obj/item/P, mob/living/user, list/modifiers, list/attack_modifiers) - if(P.tool_behaviour == TOOL_WRENCH && LAZYACCESS(modifiers, RIGHT_CLICK)) - to_chat(user, span_notice("You begin to [anchored ? "unwrench" : "wrench"] [src].")) - if(P.use_tool(src, user, 20, volume=50)) - to_chat(user, span_notice("You successfully [anchored ? "unwrench" : "wrench"] [src].")) - set_anchored(!anchored) - else if(P.w_class < WEIGHT_CLASS_NORMAL) - if(!user.transferItemToLoc(P, src)) - return - to_chat(user, span_notice("You put [P] in [src].")) +/obj/structure/filingcabinet/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(tool.w_class < WEIGHT_CLASS_NORMAL) + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You put [tool] in [src].")) icon_state = "[initial(icon_state)]-open" sleep(0.5 SECONDS) icon_state = initial(icon_state) - else if(!user.combat_mode || (P.item_flags & NOBLUDGEON)) - to_chat(user, span_warning("You can't put [P] in [src]!")) - else - return ..() + return ITEM_INTERACT_SUCCESS + if(!user.combat_mode || (tool.item_flags & NOBLUDGEON)) + to_chat(user, span_warning("You can't put [tool] in [src]!")) + return ITEM_INTERACT_BLOCKING + return NONE + +/obj/structure/filingcabinet/wrench_act_secondary(mob/living/user, obj/item/tool) + to_chat(user, span_notice("You begin to [anchored ? "unwrench" : "wrench"] [src].")) + if(!tool.use_tool(src, user, 20, volume=50)) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You successfully [anchored ? "unwrench" : "wrench"] [src].")) + set_anchored(!anchored) + return ITEM_INTERACT_SUCCESS /obj/structure/filingcabinet/attack_hand(mob/living/carbon/user, list/modifiers) . = ..() diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 52d024df1b9..e0589b3c185 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -415,44 +415,44 @@ GAME_VERB_SRC(/obj/item/paper, rename, usr, "Rename paper", null) user.put_in_hands(new_plane) return new_plane -/obj/item/paper/attackby(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers) +/obj/item/paper/item_interaction(mob/living/user, obj/item/tool, list/modifiers) // Enable picking paper up by clicking on it with the clipboard or paper bin - if(istype(attacking_item, /obj/item/clipboard) || istype(attacking_item, /obj/item/paper_bin)) - attacking_item.attackby(src, user) - return + if(istype(tool, /obj/item/clipboard) || istype(tool, /obj/item/paper_bin)) + tool.item_interaction(user, src) + return ITEM_INTERACT_SUCCESS // Handle writing items. - var/writing_stats = attacking_item.get_writing_implement_details() + var/writing_stats = tool.get_writing_implement_details() if(!writing_stats) ui_interact(user) - return ..() + return NONE if(writing_stats["interaction_mode"] == MODE_WRITING) - if(!user.can_write(attacking_item)) - return + if(!user.can_write(tool)) + return ITEM_INTERACT_BLOCKING if(get_total_length() >= MAX_PAPER_LENGTH) to_chat(user, span_warning("This sheet of paper is full!")) - return + return ITEM_INTERACT_BLOCKING ui_interact(user) - return + return ITEM_INTERACT_SUCCESS // Handle stamping items. if(writing_stats["interaction_mode"] == MODE_STAMPING) if(!user.can_read(src) || user.is_blind()) //The paper's stampable window area is assumed approx 300x400 add_stamp(writing_stats["stamp_class"], rand(0, 300), rand(0, 400), rand(0, 360), writing_stats["stamp_icon_state"], stamp_icon = writing_stats["stamp_icon"]) - user.visible_message(span_notice("[user] blindly stamps [src] with \the [attacking_item]!")) - to_chat(user, span_notice("You stamp [src] with \the [attacking_item] the best you can!")) + user.visible_message(span_notice("[user] blindly stamps [src] with \the [tool]!")) + to_chat(user, span_notice("You stamp [src] with \the [tool] the best you can!")) playsound(src, 'sound/items/handling/standard_stamp.ogg', 50, vary = TRUE) else to_chat(user, span_notice("You ready your stamp over the paper! ")) ui_interact(user) - return + return ITEM_INTERACT_SUCCESS ui_interact(user) - return ..() + return NONE /// Secondary right click interaction to quickly stamp things /obj/item/paper/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index d1b6e776990..9226a944401 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -118,27 +118,29 @@ add_fingerprint(user) return ..() -/obj/item/paper_bin/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) +/obj/item/paper_bin/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(at_overlay_limit()) dump_contents(drop_location(), TRUE) - return - if(istype(I, /obj/item/paper)) - var/obj/item/paper/paper = I - if(!user.transferItemToLoc(paper, src, silent = FALSE)) - return - to_chat(user, span_notice("You put [paper] in [src].")) - paper_stack += paper + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/paper)) + if(!user.transferItemToLoc(tool, src, silent = FALSE)) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You put [tool] in [src].")) + paper_stack += tool total_paper += 1 update_appearance() - else if(istype(I, /obj/item/pen) && !bin_pen) - var/obj/item/pen/pen = I - if(!user.transferItemToLoc(pen, src, silent = FALSE)) - return - to_chat(user, span_notice("You put [pen] in [src].")) - bin_pen = pen + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/pen) && !bin_pen) + if(!user.transferItemToLoc(tool, src, silent = FALSE)) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You put [tool] in [src].")) + bin_pen = tool update_appearance() - else - return ..() + return ITEM_INTERACT_SUCCESS + + return NONE /obj/item/paper_bin/proc/at_overlay_limit() return overlays.len >= MAX_ATOM_OVERLAYS - 1 @@ -253,16 +255,19 @@ /obj/item/paper_bin/bundlenatural/fire_act(exposed_temperature, exposed_volume) qdel(src) -/obj/item/paper_bin/bundlenatural/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/paper/carbon)) - to_chat(user, span_warning("[W] won't fit into [src].")) - return - if(W.get_sharpness()) - if(W.use_tool(src, user, 1 SECONDS)) - to_chat(user, span_notice("You slice the cable from [src].")) - deconstruct(TRUE) - else - ..() +/obj/item/paper_bin/bundlenatural/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/paper/carbon)) + to_chat(user, span_warning("[tool] won't fit into [src].")) + return ITEM_INTERACT_BLOCKING + + if(tool.get_sharpness()) + if(!tool.use_tool(src, user, 1 SECONDS)) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You slice the cable from [src].")) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + + return ..() /obj/item/paper_bin/carbon name = "carbon paper bin" diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 8c1a2ba42c9..3cdd28a9ada 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -80,16 +80,16 @@ user.put_in_hands(released_paper) -/obj/item/paperplane/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - if(IS_WRITING_UTENSIL(attacking_item)) +/obj/item/paperplane/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(IS_WRITING_UTENSIL(tool)) to_chat(user, span_warning("You should unfold [src] before changing it!")) - return - else if(istype(attacking_item, /obj/item/stamp)) //we don't randomize stamps on a paperplane - internal_paper.attackby(attacking_item, user) //spoofed attack to update internal paper. + return ITEM_INTERACT_BLOCKING + if(istype(tool, /obj/item/stamp)) //we don't randomize stamps on a paperplane + internal_paper.item_interaction(user, tool) //spoofed attack to update internal paper. update_appearance() add_fingerprint(user) - return - return ..() + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscarbon(hit_atom) && HAS_TRAIT(hit_atom, TRAIT_PAPER_MASTER)) diff --git a/code/modules/paperwork/paperwork.dm b/code/modules/paperwork/paperwork.dm index cec9076027a..68688589b73 100644 --- a/code/modules/paperwork/paperwork.dm +++ b/code/modules/paperwork/paperwork.dm @@ -39,27 +39,27 @@ detailed_desc = span_notice("As you sift through the papers, you slowly start to piece together what you're reading.") -/obj/item/paperwork/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - . = ..() - if(.) - return +/obj/item/paperwork/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/stamp)) + return NONE - if(stamped || !istype(attacking_item, /obj/item/stamp)) - return + if(stamped) + return ITEM_INTERACT_BLOCKING - if(istype(attacking_item, stamp_requested)) + if(istype(tool, stamp_requested)) add_stamp() to_chat(user, span_notice("You skim through the papers until you find a field reading 'STAMP HERE', and complete the paperwork.")) - return TRUE - var/datum/action/item_action/chameleon/change/stamp/stamp_action = locate() in attacking_item.actions - if(isnull(stamp_action)) - to_chat(user, span_warning("You hunt through the papers for somewhere to use [attacking_item], but can't find anything.")) - return TRUE + return ITEM_INTERACT_SUCCESS - to_chat(user, span_notice("[attacking_item] morphs into the appropriate stamp, which you use to complete the paperwork.")) + var/datum/action/item_action/chameleon/change/stamp/stamp_action = locate() in tool.actions + if(isnull(stamp_action)) + to_chat(user, span_warning("You hunt through the papers for somewhere to use [tool], but can't find anything.")) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("[tool] morphs into the appropriate stamp, which you use to complete the paperwork.")) stamp_action.update_look(stamp_requested) add_stamp() - return TRUE + return ITEM_INTERACT_SUCCESS /obj/item/paperwork/examine_more(mob/user) . = ..() @@ -233,16 +233,15 @@ else . += span_notice("These appear to just be a photocopy of the original documents.") -/obj/item/paperwork/photocopy/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - if(istype(attacking_item, /obj/item/stamp/void) && !stamped && !voided) - to_chat(user, span_notice("You plant the [attacking_item] firmly onto the front of the documents.")) - stamp_overlay = mutable_appearance('icons/obj/service/bureaucracy.dmi', "paper_stamp-void") - add_overlay(stamp_overlay) - voided = TRUE - stamped = TRUE //It won't get you any money, but it also can't LOSE you money now. - return - - return ..() +/obj/item/paperwork/photocopy/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/stamp/void) || stamped || voided) + return ..() + to_chat(user, span_notice("You plant the [tool] firmly onto the front of the documents.")) + stamp_overlay = mutable_appearance('icons/obj/service/bureaucracy.dmi', "paper_stamp-void") + add_overlay(stamp_overlay) + voided = TRUE + stamped = TRUE //It won't get you any money, but it also can't LOSE you money now. + return ITEM_INTERACT_SUCCESS //Ancient paperwork is a subtype of paperwork, meant to be used for any paperwork not spawned by the event. //It doesn't have any of the flavor text that the event ones spawn with. diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm index 256926e7d52..05b037f90c5 100644 --- a/code/modules/paperwork/ticketmachine.dm +++ b/code/modules/paperwork/ticketmachine.dm @@ -178,26 +178,30 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32) maptext_x = 4 maptext = MAPTEXT(current_number) //Finally, apply the maptext -/obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - ..() - if(istype(I, /obj/item/hand_labeler_refill)) - if(!(ticket_number >= max_number)) - to_chat(user, span_notice("[src] refuses [I]! There [max_number - ticket_number == 1 ? "is" : "are"] still [max_number - ticket_number] ticket\s left!")) - return - to_chat(user, span_notice("You start to refill [src]'s ticket holder (doing this will reset its ticket count!).")) - if(do_after(user, 3 SECONDS, target = src)) - to_chat(user, span_notice("You insert [I] into [src] as it whirs nondescriptly.")) - qdel(I) - ticket_number = 0 - current_number = 0 - if(tickets.len) - for(var/obj/item/ticket_machine_ticket/ticket in tickets) - ticket.audible_message(span_notice("\the [ticket] disperses!"), hearing_distance = SAMETILE_MESSAGE_RANGE) - qdel(ticket) - tickets.Cut() - max_number = initial(max_number) - update_appearance() - return +/obj/machinery/ticket_machine/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/hand_labeler_refill)) + return NONE + + if(!(ticket_number >= max_number)) + to_chat(user, span_notice("[src] refuses [tool]! There [max_number - ticket_number == 1 ? "is" : "are"] still [max_number - ticket_number] ticket\s left!")) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You start to refill [src]'s ticket holder (doing this will reset its ticket count!).")) + if(!do_after(user, 3 SECONDS, target = src)) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You insert [tool] into [src] as it whirs nondescriptly.")) + qdel(tool) + ticket_number = 0 + current_number = 0 + if(tickets.len) + for(var/obj/item/ticket_machine_ticket/ticket in tickets) + ticket.audible_message(span_notice("\the [ticket] disperses!"), hearing_distance = SAMETILE_MESSAGE_RANGE) + qdel(ticket) + tickets.Cut() + max_number = initial(max_number) + update_appearance() + return ITEM_INTERACT_SUCCESS /obj/machinery/ticket_machine/proc/reset_cooldown() ready = TRUE diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm index 983cb00977d..58f9202791c 100644 --- a/code/modules/photography/photos/frame.dm +++ b/code/modules/photography/photos/frame.dm @@ -12,16 +12,17 @@ var/obj/item/photo/displayed pixel_shift = 30 -/obj/item/wallframe/picture/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/photo)) - if(!displayed) - if(!user.transferItemToLoc(I, src)) - return - displayed = I - update_appearance() - else - to_chat(user, span_warning("\The [src] already contains a photo.")) - ..() +/obj/item/wallframe/picture/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/photo)) + return NONE + if(displayed) + to_chat(user, span_warning("\The [src] already contains a photo.")) + return ITEM_INTERACT_BLOCKING + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + displayed = tool + update_appearance() + return ITEM_INTERACT_SUCCESS //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/item/wallframe/picture/attack_hand(mob/user, list/modifiers) @@ -145,19 +146,17 @@ return ITEM_INTERACT_SUCCESS -/obj/structure/sign/picture_frame/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - - if(istype(I, /obj/item/photo)) - if(framed) - to_chat(user, span_warning("\The [src] already contains a photo.")) - return TRUE - var/obj/item/photo/P = I - if(!user.transferItemToLoc(P, src)) - return - set_and_save_framed(P) - update_appearance() - return TRUE - ..() +/obj/structure/sign/picture_frame/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/photo)) + return NONE + if(framed) + to_chat(user, span_warning("\The [src] already contains a photo.")) + return ITEM_INTERACT_BLOCKING + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + set_and_save_framed(tool) + update_appearance() + return ITEM_INTERACT_SUCCESS /obj/structure/sign/picture_frame/attack_hand(mob/user, list/modifiers) . = ..() diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm index 128d9e236bc..a4ba9695ac6 100644 --- a/code/modules/photography/photos/photo.dm +++ b/code/modules/photography/photos/photo.dm @@ -79,16 +79,17 @@ /obj/item/photo/attack_self(mob/user) user.examinate(src) -/obj/item/photo/attackby(obj/item/P, mob/user, list/modifiers, list/attack_modifiers) - if(IS_WRITING_UTENSIL(P)) - if(!user.can_write(P)) - return - var/txt = tgui_input_text(user, "What would you like to write on the back?", "Photo Writing", max_length = 128) - if(txt && user.can_perform_action(src)) - playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) - scribble = txt - else - return ..() +/obj/item/photo/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!IS_WRITING_UTENSIL(tool)) + return NONE + if(!user.can_write(tool)) + return ITEM_INTERACT_BLOCKING + var/txt = tgui_input_text(user, "What would you like to write on the back?", "Photo Writing", max_length = 128) + if(!txt || !user.can_perform_action(src)) + return ITEM_INTERACT_BLOCKING + playsound(src, SFX_WRITING_PEN, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, SOUND_FALLOFF_EXPONENT + 3, ignore_walls = FALSE) + scribble = txt + return ITEM_INTERACT_SUCCESS /obj/item/photo/examine(mob/user) . = ..() diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 82ea13b4309..58fbc7f360b 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -324,18 +324,17 @@ // attach a wire to a power machine - leads from the turf you are standing on //almost never called, overwritten by all power machines but terminal and generator -/obj/machinery/power/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - var/turf/T = user.loc - if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !isfloorturf(T)) - return - if(get_dist(src, user) > 1) - return - coil.place_turf(T, user) - else - return ..() - +/obj/machinery/power/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/stack/cable_coil)) + return NONE + var/obj/item/stack/cable_coil/coil = tool + var/turf/userturf = user.loc + if(userturf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !isfloorturf(userturf)) + return ITEM_INTERACT_BLOCKING + if(get_dist(src, user) > 1) + return ITEM_INTERACT_BLOCKING + coil.place_turf(userturf, user) + return ITEM_INTERACT_SUCCESS /////////////////////////////////////////// // Powernet handling helpers