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
🆑

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()

/🆑
This commit is contained in:
Leland Kemble
2026-07-05 10:02:06 +02:00
committed by GitHub
parent ae315a22a1
commit e816dfebeb
23 changed files with 332 additions and 321 deletions
+25 -15
View File
@@ -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)
+18 -14
View File
@@ -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)
. = ..()
+14 -14
View File
@@ -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)
+31 -26
View File
@@ -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"
+7 -7
View File
@@ -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))
+23 -24
View File
@@ -39,27 +39,27 @@
detailed_desc = span_notice("<i>As you sift through the papers, you slowly start to piece together what you're reading.</i>")
/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.
+24 -20
View File
@@ -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