diff --git a/_maps/map_files/tests/test_attack_chain_structures.dmm b/_maps/map_files/tests/test_attack_chain_structures.dmm
new file mode 100644
index 00000000000..fc050ce0ca9
--- /dev/null
+++ b/_maps/map_files/tests/test_attack_chain_structures.dmm
@@ -0,0 +1,606 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aG" = (
+/obj/structure/machine_frame,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"bw" = (
+/obj/structure/extinguisher_cabinet,
+/turf/simulated/wall/r_wall,
+/area/game_test)
+"cf" = (
+/obj/structure/fermenting_barrel,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"cH" = (
+/obj/structure/grille,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"dG" = (
+/obj/structure/holosign/barrier/atmos,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"eN" = (
+/obj/structure/mineral_door/iron,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"eY" = (
+/obj/structure/mirror/magic{
+ pixel_y = 32
+ },
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"fA" = (
+/obj/structure/closet/crate/secure/loot,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"jj" = (
+/obj/structure/rack,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"kg" = (
+/obj/structure/windoor_assembly,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"kT" = (
+/obj/structure/girder/cult,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"le" = (
+/obj/structure/noticeboard,
+/turf/simulated/wall/r_wall,
+/area/game_test)
+"lH" = (
+/obj/structure/barricade/wooden,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"ms" = (
+/obj/structure/beebox,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"nj" = (
+/obj/structure/particle_accelerator/fuel_chamber,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"nK" = (
+/obj/structure/cult/functional/forge,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"pS" = (
+/obj/structure/target_stake,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"qt" = (
+/obj/structure/constructshell,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"rT" = (
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"sE" = (
+/obj/structure/chair,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"sR" = (
+/obj/structure/displaycase,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"tn" = (
+/obj/structure/flora/ash,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"tQ" = (
+/obj/structure/guillotine,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"ve" = (
+/obj/structure/computerframe,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"wb" = (
+/obj/structure/table_frame,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"wn" = (
+/obj/effect/spawner/window,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"wr" = (
+/obj/structure/inflatable,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"yd" = (
+/obj/structure/bed/roller,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"yn" = (
+/obj/structure/big_delivery,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"zK" = (
+/obj/structure/reagent_dispensers/water_cooler,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"AG" = (
+/obj/structure/door_assembly,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"AI" = (
+/obj/structure/table,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"BX" = (
+/obj/effect/landmark{
+ icon = 'icons/effects/spawner_icons.dmi';
+ icon_state = "spooky";
+ name = "Observer-Start"
+ },
+/obj/effect/landmark/spawner/late/crew,
+/obj/effect/landmark/game_test/bottom_left_corner,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"Cd" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/simulated/floor/plating,
+/area/game_test)
+"DQ" = (
+/obj/structure/morgue,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"FH" = (
+/obj/structure/snowman/built,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"FZ" = (
+/obj/structure/largecrate,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"GO" = (
+/obj/structure/reflector,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"JP" = (
+/obj/structure/statue/gold/hop,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"NN" = (
+/obj/structure/kitchenspike_frame,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"Od" = (
+/turf/simulated/wall/r_wall,
+/area/game_test)
+"OE" = (
+/obj/structure/ai_core,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"QL" = (
+/obj/structure/disposalconstruct,
+/turf/simulated/floor/plating,
+/area/game_test)
+"RH" = (
+/obj/structure/filingcabinet,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"RN" = (
+/obj/structure/firelock_frame,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"Sw" = (
+/obj/effect/landmark/game_test/top_right_corner,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"Uu" = (
+/obj/structure/ore_box,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"UT" = (
+/obj/structure/shelf,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"VM" = (
+/obj/structure/loom,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"Wr" = (
+/obj/structure/lattice,
+/turf/space,
+/area/game_test)
+"Xt" = (
+/obj/structure/girder,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"Ye" = (
+/obj/structure/kitchenspike,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"YV" = (
+/obj/structure/clockwork/wall_gear,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+"ZY" = (
+/obj/structure/safe,
+/turf/simulated/floor/plasteel,
+/area/game_test)
+
+(1,1,1) = {"
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+"}
+(2,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(3,1,1) = {"
+Od
+rT
+nK
+rT
+aG
+rT
+cH
+rT
+wb
+rT
+VM
+rT
+JP
+rT
+rT
+BX
+rT
+Od
+"}
+(4,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(5,1,1) = {"
+Od
+rT
+OE
+rT
+FZ
+rT
+Xt
+rT
+AI
+rT
+Od
+eY
+UT
+rT
+rT
+rT
+rT
+Od
+"}
+(6,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(7,1,1) = {"
+Od
+rT
+qt
+rT
+sR
+rT
+Xt
+rT
+wr
+rT
+DQ
+rT
+FH
+rT
+rT
+rT
+rT
+Od
+"}
+(8,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+dG
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(9,1,1) = {"
+Od
+rT
+ve
+rT
+AG
+rT
+dG
+Wr
+dG
+rT
+le
+rT
+yd
+rT
+rT
+rT
+rT
+Od
+"}
+(10,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+dG
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(11,1,1) = {"
+Od
+rT
+lH
+rT
+bw
+rT
+tQ
+rT
+Ye
+rT
+GO
+rT
+sE
+rT
+zK
+rT
+rT
+Od
+"}
+(12,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(13,1,1) = {"
+Od
+rT
+RN
+rT
+kT
+rT
+NN
+rT
+eN
+rT
+ZY
+rT
+jj
+rT
+Cd
+rT
+rT
+Od
+"}
+(14,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(15,1,1) = {"
+Od
+rT
+pS
+rT
+kg
+rT
+wn
+rT
+ms
+rT
+cf
+rT
+tn
+rT
+fA
+rT
+rT
+Od
+"}
+(16,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(17,1,1) = {"
+Od
+rT
+Sw
+rT
+RH
+rT
+Uu
+rT
+yn
+rT
+YV
+rT
+nj
+rT
+QL
+rT
+rT
+Od
+"}
+(18,1,1) = {"
+Od
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+rT
+Od
+"}
+(19,1,1) = {"
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+Od
+"}
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 84afcd86611..73bbdc7b49f 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -52,17 +52,18 @@
. += "The magic in [src] is weak, it will be ready to use again in [get_ETA()]."
. += "[src] is [anchored ? "":"not "]secured to the floor."
-/obj/structure/cult/functional/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/cult/functional/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user))
if(user.holy_check())
- return
+ return ITEM_INTERACT_COMPLETE
anchored = !anchored
to_chat(user, "You [anchored ? "":"un"]secure [src] [anchored ? "to":"from"] the floor.")
if(!anchored)
icon_state = GET_CULT_DATA(get_icon("[initial(icon_state)]_off"), "[initial(icon_state)]_off")
else
icon_state = GET_CULT_DATA(get_icon(initial(icon_state)), initial(icon_state))
- return
+ return ITEM_INTERACT_COMPLETE
+
return ..()
/obj/structure/cult/functional/attack_hand(mob/living/user)
@@ -180,22 +181,22 @@
. = ..()
icon_state = GET_CULT_DATA(forge_icon_state, "forge")
-/obj/structure/cult/functional/forge/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/cult/functional/forge/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/grab))
var/obj/item/grab/G = I
if(!iscarbon(G.affecting))
- return FALSE
+ return ITEM_INTERACT_COMPLETE
if(G.affecting == LAVA_PROOF)
to_chat(user, "[G.affecting] is immune to lava!")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
if(G.affecting.stat == DEAD)
to_chat(user, "[G.affecting] is dead!")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
var/mob/living/carbon/human/C = G.affecting
var/obj/item/organ/external/head/head = C.get_organ("head")
if(!head)
to_chat(user, "[C] has no head!")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
C.visible_message("[user] dunks [C]'s face into [src]'s lava!",
"[user] dunks your face into [src]'s lava!")
@@ -205,7 +206,8 @@
C.UpdateDamageIcon()
add_attack_logs(user, C, "Lava-dunked into [src]")
user.changeNext_move(CLICK_CD_MELEE)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
+
return ..()
GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index c7736350d75..35185b94547 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -288,13 +288,13 @@
. += "A Wraith, which does high damage and can jaunt through walls, though it is quite fragile."
. += "A Juggernaut, which is very hard to kill and can produce temporary walls, but is slow."
-/obj/structure/constructshell/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
+/obj/structure/constructshell/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/soulstone))
var/obj/item/soulstone/SS = I
if(!SS.can_use(user))
to_chat(user, "An overwhelming feeling of dread comes over you as you attempt to place the soulstone into the shell.")
user.Confused(20 SECONDS)
- return
+ return ITEM_INTERACT_COMPLETE
SS.transfer_soul("CONSTRUCT", src, user)
SS.was_used()
else
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 7a2047fb0a1..c4d39c0177c 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -15,12 +15,12 @@
QDEL_NULL(brain)
return ..()
-/obj/structure/ai_core/attackby__legacy__attackchain(obj/item/P, mob/user, params)
+/obj/structure/ai_core/item_interaction(mob/living/user, obj/item/P, list/modifiers)
switch(state)
if(EMPTY_CORE)
if(istype(P, /obj/item/circuitboard/aicore))
if(!user.drop_item())
- return
+ return ITEM_INTERACT_COMPLETE
playsound(loc, P.usesound, 50, 1)
to_chat(user, "You place the circuit board inside the frame.")
update_icon(UPDATE_ICON_STATE)
@@ -28,7 +28,7 @@
P.forceMove(src)
circuit = P
update_icon(UPDATE_ICON_STATE)
- return
+ return ITEM_INTERACT_COMPLETE
if(SCREWED_CORE)
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
@@ -41,7 +41,7 @@
update_icon(UPDATE_ICON_STATE)
else
to_chat(user, "You need five lengths of cable to wire the AI core!")
- return
+ return ITEM_INTERACT_COMPLETE
if(CABLED_CORE)
if(istype(P, /obj/item/stack/sheet/rglass))
var/obj/item/stack/sheet/rglass/G = P
@@ -54,73 +54,73 @@
update_icon(UPDATE_ICON_STATE)
else
to_chat(user, "You need two sheets of reinforced glass to insert them into the AI core!")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(P, /obj/item/ai_module/purge))
laws.clear_inherent_laws()
to_chat(usr, "Law module applied.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(P, /obj/item/ai_module/freeform))
var/obj/item/ai_module/freeform/M = P
if(!M.newFreeFormLaw)
to_chat(usr, "No law detected on module, please create one.")
- return
+ return ITEM_INTERACT_COMPLETE
laws.add_supplied_law(M.lawpos, M.newFreeFormLaw)
to_chat(usr, "Added a freeform law.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(P, /obj/item/ai_module/syndicate))
var/obj/item/ai_module/syndicate/M = P
if(!M.newFreeFormLaw)
to_chat(usr, "No law detected on module, please create one.")
- return
+ return ITEM_INTERACT_COMPLETE
laws.add_ion_law(M.newFreeFormLaw)
to_chat(usr, "Added a hacked law.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(P, /obj/item/ai_module))
var/obj/item/ai_module/M = P
if(!M.laws)
to_chat(usr, "This AI module can not be applied directly to AI cores.")
- return
+ return ITEM_INTERACT_COMPLETE
laws = M.laws
to_chat(usr, "Added [M.laws.name] laws.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(P, /obj/item/mmi) && !brain)
var/obj/item/mmi/M = P
if(!M.brainmob)
to_chat(user, "Sticking an empty [P] into the frame would sort of defeat the purpose.")
- return
+ return ITEM_INTERACT_COMPLETE
if(M.brainmob.stat == DEAD)
to_chat(user, "Sticking a dead [P] into the frame would sort of defeat the purpose.")
- return
+ return ITEM_INTERACT_COMPLETE
if(!M.brainmob.client)
to_chat(user, "Sticking an inactive [M.name] into the frame would sort of defeat the purpose.")
- return
+ return ITEM_INTERACT_COMPLETE
if(jobban_isbanned(M.brainmob, "AI") || jobban_isbanned(M.brainmob, "nonhumandept"))
to_chat(user, "This [P] does not seem to fit.")
- return
+ return ITEM_INTERACT_COMPLETE
if(!M.brainmob.mind)
to_chat(user, "This [M.name] is mindless!")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(P, /obj/item/mmi/syndie))
to_chat(user, "This MMI does not seem to fit!")
- return
+ return ITEM_INTERACT_COMPLETE
if(!user.drop_item())
- return
+ return ITEM_INTERACT_COMPLETE
M.forceMove(src)
brain = M
to_chat(user, "You add [M.name] to the frame.")
update_icon(UPDATE_ICON_STATE)
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 731e02eaf1a..60f4b820663 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -686,7 +686,7 @@
I.play_tool_sound(src)
update_icon()
-/obj/structure/computerframe/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/computerframe/item_interaction(mob/living/user, obj/item/I, list/modifiers)
switch(state)
if(STATE_EMPTY)
if(!istype(I, /obj/item/circuitboard))
@@ -695,11 +695,11 @@
var/obj/item/circuitboard/B = I
if(B.board_type != "computer")
to_chat(user, "[src] does not accept circuit boards of this type!")
- return
+ return ITEM_INTERACT_COMPLETE
if(!B.build_path)
to_chat(user, "This is not a functional computer circuit board!")
- return
+ return ITEM_INTERACT_COMPLETE
B.play_tool_sound(src)
to_chat(user, "You place [B] inside [src].")
@@ -709,7 +709,7 @@
B.forceMove(src)
circuit = B
update_icon()
- return
+ return ITEM_INTERACT_COMPLETE
if(STATE_NOWIRES)
if(!istype(I, /obj/item/stack/cable_coil))
@@ -718,20 +718,20 @@
var/obj/item/stack/cable_coil/C = I
if(C.get_amount() < 5)
to_chat(user, "You need five lengths of cable to wire the frame.")
- return
+ return ITEM_INTERACT_COMPLETE
C.play_tool_sound(src)
to_chat(user, "You start to add cables to the frame.")
if(!do_after(user, 2 SECONDS * C.toolspeed, target = src))
- return
+ return ITEM_INTERACT_COMPLETE
if(C.get_amount() < 5 || !C.use(5))
to_chat(user, "At some point during construction you lost some cable. Make sure you have five lengths before trying again.")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You add cables to the frame.")
state = STATE_WIRES
update_icon()
- return
+ return ITEM_INTERACT_COMPLETE
if(STATE_WIRES)
if(!istype(I, /obj/item/stack/sheet/glass))
@@ -740,20 +740,20 @@
var/obj/item/stack/sheet/glass/G = I
if(G.get_amount() < 2)
to_chat(user, "You need two sheets of glass for this.")
- return
+ return ITEM_INTERACT_COMPLETE
G.play_tool_sound(src)
to_chat(user, "You start to add the glass panel to the frame.")
if(!do_after(user, 2 SECONDS * G.toolspeed, target = src))
- return
+ return ITEM_INTERACT_COMPLETE
if(G.get_amount() < 2 || !G.use(2))
to_chat(user, "At some point during construction you lost some glass. Make sure you have two sheets before trying again.")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You put in the glass panel.")
state = STATE_GLASS
update_icon()
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 2de04ec3ec2..8f197336525 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -92,22 +92,21 @@
bar_material = WOOD
stacktype = /obj/item/stack/sheet/wood
-
-/obj/structure/barricade/wooden/attackby__legacy__attackchain(obj/item/I, mob/user)
+/obj/structure/barricade/wooden/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I,/obj/item/stack/sheet/wood))
var/obj/item/stack/sheet/wood/W = I
if(W.get_amount() < 5)
to_chat(user, "You need at least five wooden planks to make a wall!")
- return
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You start adding [I] to [src]...")
if(do_after(user, 50, target = src))
if(!W.use(5))
- return
+ return ITEM_INTERACT_COMPLETE
var/turf/T = get_turf(src)
T.ChangeTurf(/turf/simulated/wall/mineral/wood/nonmetal)
qdel(src)
- return //return is need to prevent people from exploiting zero-hit cooldowns with the do_after here
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/barricade/wooden/crowbar_act(mob/living/user, obj/item/I)
@@ -375,8 +374,7 @@
if(!target_turf2.is_blocked_turf())
connected_shields += new barricade_type(target_turf2, src, FALSE, direction, dir_right)
-
-/obj/structure/dropwall_generator/attacked_by__legacy__attackchain(obj/item/I, mob/living/user) //No, you can not just go up to the generator and whack it. Central shield needs to go down first.
+/obj/structure/dropwall_generator/attacked_by(obj/item/I, mob/living/user)
if(protected)
visible_message("[src]'s shield absorbs the blow!")
core_shield.take_damage(I.force, I.damtype, MELEE, TRUE)
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index b5f4bb4cbd0..eb4e9d408e8 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -402,57 +402,57 @@
/obj/structure/firelock_frame/update_icon_state()
icon_state = "frame[constructionStep]"
-/obj/structure/firelock_frame/attackby__legacy__attackchain(obj/item/C, mob/user)
+/obj/structure/firelock_frame/item_interaction(mob/living/user, obj/item/C, list/modifiers)
switch(constructionStep)
if(CONSTRUCTION_PANEL_OPEN)
if(istype(C, /obj/item/stack/sheet/plasteel))
var/obj/item/stack/sheet/plasteel/P = C
if(reinforced)
to_chat(user, "[src] is already reinforced.")
- return
+ return ITEM_INTERACT_COMPLETE
if(P.get_amount() < 2)
to_chat(user, "You need more plasteel to reinforce [src].")
- return
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] begins reinforcing [src]...", \
"You begin reinforcing [src]...")
playsound(get_turf(src), C.usesound, 50, 1)
if(do_after(user, 60 * C.toolspeed, target = src))
if(constructionStep != CONSTRUCTION_PANEL_OPEN || reinforced || P.get_amount() < 2 || !P)
- return
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] reinforces [src].", \
"You reinforce [src].")
playsound(get_turf(src), C.usesound, 50, 1)
P.use(2)
reinforced = 1
- return
+ return ITEM_INTERACT_COMPLETE
if(CONSTRUCTION_GUTTED)
if(iscoil(C))
var/obj/item/stack/cable_coil/B = C
if(B.get_amount() < 5)
to_chat(user, "You need more wires to add wiring to [src].")
- return
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] begins wiring [src]...", \
"You begin adding wires to [src]...")
playsound(get_turf(src), B.usesound, 50, 1)
if(do_after(user, 60 * B.toolspeed, target = src))
if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B)
- return
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] adds wires to [src].", \
"You wire [src].")
playsound(get_turf(src), B.usesound, 50, 1)
B.use(5)
constructionStep = CONSTRUCTION_WIRES_EXPOSED
update_icon()
- return
+ return ITEM_INTERACT_COMPLETE
if(CONSTRUCTION_NOCIRCUIT)
if(istype(C, /obj/item/firelock_electronics))
user.visible_message("[user] starts adding [C] to [src]...", \
"You begin adding a circuit board to [src]...")
playsound(get_turf(src), C.usesound, 50, 1)
if(!do_after(user, 40 * C.toolspeed, target = src))
- return
+ return ITEM_INTERACT_COMPLETE
if(constructionStep != CONSTRUCTION_NOCIRCUIT)
- return
+ return ITEM_INTERACT_COMPLETE
user.drop_item()
qdel(C)
user.visible_message("[user] adds a circuit to [src].", \
@@ -460,7 +460,7 @@
playsound(get_turf(src), C.usesound, 50, 1)
constructionStep = CONSTRUCTION_GUTTED
update_icon()
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/firelock_frame/crowbar_act(mob/user, obj/item/I)
diff --git a/code/game/machinery/machine_frame.dm b/code/game/machinery/machine_frame.dm
index b727d972329..54f23c77257 100644
--- a/code/game/machinery/machine_frame.dm
+++ b/code/game/machinery/machine_frame.dm
@@ -89,7 +89,7 @@
else
icon_state = "box_0"
-/obj/structure/machine_frame/attackby__legacy__attackchain(obj/item/P, mob/living/user, params)
+/obj/structure/machine_frame/item_interaction(mob/living/user, obj/item/P, list/modifiers)
switch(state)
if(MACHINE_FRAME_EMPTY)
if(istype(P, /obj/item/stack/cable_coil))
@@ -104,16 +104,16 @@
update_icon(UPDATE_ICON_STATE)
else
to_chat(user, "At some point during construction you lost some cable. Make sure you have five lengths before trying again.")
- return
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You need five lengths of cable to wire the frame.")
- return
+ return ITEM_INTERACT_COMPLETE
if(iswrench(P))
P.play_tool_sound(src)
to_chat(user, "You dismantle the frame.")
deconstruct(TRUE)
- return
+ return ITEM_INTERACT_COMPLETE
if(MACHINE_FRAME_WIRED)
// see wirecutter_act()
@@ -122,7 +122,7 @@
if(B.board_type == frame_type)
if(!B.build_path)
to_chat(user, "This is not a functional machine board!")
- return
+ return ITEM_INTERACT_COMPLETE
playsound(src.loc, B.usesound, 50, 1)
to_chat(user, "You add the circuit board to the frame.")
circuit = P
@@ -134,7 +134,7 @@
update_appearance(UPDATE_NAME|UPDATE_DESC|UPDATE_ICON_STATE)
else
to_chat(user, "This frame does not accept circuit boards of this type!")
- return
+ return ITEM_INTERACT_COMPLETE
if(MACHINE_FRAME_CIRCUITBOARD)
// see crowbar_act()
@@ -165,7 +165,7 @@
replacer.play_rped_sound()
update_appearance(UPDATE_DESC)
- return
+ return ITEM_INTERACT_COMPLETE
if(isitem(P))
var/success
@@ -189,11 +189,11 @@
components += P
req_components[I]--
update_appearance(UPDATE_DESC)
- return 1
+ return ITEM_INTERACT_COMPLETE
if(!success)
to_chat(user, "You cannot add that to the machine!")
- return 0
- return
+ return ITEM_INTERACT_COMPLETE
+ return ITEM_INTERACT_COMPLETE
if(user.a_intent == INTENT_HARM)
return ..()
diff --git a/code/game/objects/items/bio_chips/bio_chip_stealth.dm b/code/game/objects/items/bio_chips/bio_chip_stealth.dm
index 2e9fa41da33..6ffbfa1d6cb 100644
--- a/code/game/objects/items/bio_chips/bio_chip_stealth.dm
+++ b/code/game/objects/items/bio_chips/bio_chip_stealth.dm
@@ -109,8 +109,9 @@
move_speed_multiplier = 0.5 // You can move at run speed while in this box.
material_drop = null
-/obj/structure/closet/cardboard/agent/attackby__legacy__attackchain(obj/item/I, mob/living/user)
- return
+/obj/structure/closet/cardboard/agent/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
/obj/structure/closet/cardboard/agent/open()
. = ..()
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index ac69cde165b..c92e69f09ea 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -27,20 +27,20 @@
close_sound_volume = 15
var/item_path = /obj/item/bodybag
-/obj/structure/closet/body_bag/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/closet/body_bag/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(is_pen(I))
var/t = rename_interactive(user, I)
if(isnull(t))
- return
+ return ITEM_INTERACT_COMPLETE
cut_overlays()
if(t)
add_overlay("bodybag_label")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(I, /obj/item/wirecutters))
to_chat(user, "You cut the tag off the bodybag.")
name = initial(name)
cut_overlays()
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/closet/body_bag/welder_act(mob/user, obj/item/I)
diff --git a/code/game/objects/items/picket_signs.dm b/code/game/objects/items/picket_signs.dm
index 7f6517172c7..1590eb77e9b 100644
--- a/code/game/objects/items/picket_signs.dm
+++ b/code/game/objects/items/picket_signs.dm
@@ -65,7 +65,6 @@
icon_state = "floor_sign"
/// What does the sign say?
var/label = ""
- new_attack_chain = TRUE
/obj/structure/custom_sign/New(turf/loc, new_label)
. = ..()
diff --git a/code/game/objects/items/sport.dm b/code/game/objects/items/sport.dm
index 31fb89fb4d5..5d0dce17d29 100644
--- a/code/game/objects/items/sport.dm
+++ b/code/game/objects/items/sport.dm
@@ -67,21 +67,21 @@
density = TRUE
pass_flags_self = LETPASSTHROW | PASSTAKE
-/obj/structure/holohoop/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/holohoop/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/grab) && get_dist(src, user) <= 1)
var/obj/item/grab/G = W
if(G.state < GRAB_AGGRESSIVE)
to_chat(user, "You need a better grip to do that!")
- return
+ return ITEM_INTERACT_COMPLETE
G.affecting.forceMove(loc)
G.affecting.Weaken(10 SECONDS)
visible_message("[G.assailant] dunks [G.affecting] into [src]!")
qdel(W)
- return
+ return ITEM_INTERACT_COMPLETE
else if(isitem(W) && get_dist(src,user) <= 1)
user.drop_item(src)
visible_message("[user] dunks [W] into [src]!")
- return
+ return ITEM_INTERACT_COMPLETE
/obj/structure/holohoop/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(isitem(AM) && !isprojectile(AM))
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index d75a14921eb..9322bfddd4b 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -204,7 +204,7 @@
// into the box.
if(istype(user.pulling, /obj/structure/ore_box))
var/obj/structure/ore_box/box = user.pulling
- box.attackby__legacy__attackchain(src, user)
+ box.item_interaction(user, src)
/obj/item/storage/bag/ore/cyborg
name = "cyborg mining satchel"
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 28a9d08bb2e..f1189ccb50c 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -13,6 +13,8 @@
/// How long this takes to unbuckle yourself from.
var/unbuckle_time = 0 SECONDS
+ new_attack_chain = TRUE
+
/obj/structure/New()
..()
if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK))
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index dacefab579a..98909ada9fe 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -254,7 +254,6 @@ LINEN BINS
anchored = TRUE
resistance_flags = FLAMMABLE
max_integrity = 70
- new_attack_chain = TRUE
var/amount = 20
var/list/sheets = list()
var/obj/item/hidden = null
@@ -308,22 +307,23 @@ LINEN BINS
if(istype(used, /obj/item/bedsheet))
if(!user.drop_item())
to_chat(user, "[used] is stuck to your hand!")
- return
+ return ITEM_INTERACT_COMPLETE
used.forceMove(src)
sheets.Add(used)
amount++
update_icon(UPDATE_ICON_STATE)
to_chat(user, "You put [used] in [src].")
+ return ITEM_INTERACT_COMPLETE
else if(amount && !hidden && used.w_class < WEIGHT_CLASS_BULKY) //make sure there's sheets to hide it among, make sure nothing else is hidden in there.
if(used.flags & ABSTRACT)
- return
+ return ITEM_INTERACT_COMPLETE
if(!user.drop_item())
to_chat(user, "[used] is stuck to your hand!")
- return
+ return ITEM_INTERACT_COMPLETE
used.forceMove(src)
hidden = used
to_chat(user, "You hide [used] among the sheets.")
-
+ return ITEM_INTERACT_COMPLETE
/obj/structure/bedsheetbin/attack_hand(mob/user)
diff --git a/code/game/objects/structures/coathanger.dm b/code/game/objects/structures/coathanger.dm
index 71c1a237248..6b21f9681b1 100644
--- a/code/game/objects/structures/coathanger.dm
+++ b/code/game/objects/structures/coathanger.dm
@@ -15,7 +15,7 @@
coat = null
update_icon(UPDATE_OVERLAYS)
-/obj/structure/coatrack/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
+/obj/structure/coatrack/item_interaction(mob/living/user, obj/item/W, list/modifiers)
var/can_hang = FALSE
for(var/T in allowed)
if(istype(W,T))
@@ -26,7 +26,7 @@
user.drop_item(src)
coat.forceMove(src)
update_icon(UPDATE_OVERLAYS)
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/coatrack/CanPass(atom/movable/mover, border_dir)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 4ed92e38e14..09a9e03db1a 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -284,11 +284,11 @@
if(!broken && !(flags & NODECONSTRUCT))
bust_open()
-/obj/structure/closet/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/closet/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/rcs) && !opened)
var/obj/item/rcs/E = W
E.try_send_container(user, src)
- return
+ return ITEM_INTERACT_COMPLETE
if(opened)
if(istype(W, /obj/item/grab))
@@ -298,26 +298,28 @@
else
to_chat(user, "[src] is too small to stuff [G.affecting] into!")
if(istype(W, /obj/item/tk_grab))
- return FALSE
+ return // passthrough
if(user.a_intent != INTENT_HELP) // Stops you from putting your baton in the closet on accident
- return
+ return ITEM_INTERACT_COMPLETE
if(isrobot(user) && !istype(W.loc, /obj/item/gripper))
- return
+ return ITEM_INTERACT_COMPLETE
if(!user.drop_item()) //couldn't drop the item
to_chat(user, "\The [W] is stuck to your hand, you cannot put it in \the [src]!")
- return
+ return ITEM_INTERACT_COMPLETE
if(W.loc != user.loc)
// It went somewhere else, don't teleport it back.
- return
+ return ITEM_INTERACT_COMPLETE
if(W)
W.forceMove(loc)
- return TRUE // It's resolved. No afterattack needed. Stops you from emagging lockers when putting in an emag
+ return ITEM_INTERACT_COMPLETE
else if(can_be_emaged && (istype(W, /obj/item/card/emag) || istype(W, /obj/item/melee/energy/blade) && !broken))
emag_act(user)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/stack/package_wrap))
- return
+ return ITEM_INTERACT_COMPLETE
else if(user.a_intent != INTENT_HARM)
closed_item_click(user)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
index 72e993d308e..1e692232876 100644
--- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
+++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
@@ -68,7 +68,7 @@
/obj/structure/closet/cardboard/welder_act()
return
-/obj/structure/closet/cardboard/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
+/obj/structure/closet/cardboard/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(src.opened)
if(istype(W, /obj/item/wirecutters))
var/obj/item/wirecutters/WC = W
@@ -76,26 +76,26 @@
for(var/mob/M in viewers(src))
M.show_message("\The [src] has been cut apart by [user] with \the [WC].", 3, "You hear cutting.", 2)
qdel(src)
- return
+ return ITEM_INTERACT_COMPLETE
if(is_pen(W))
var/decalselection = tgui_input_list(user, "Please select a decal", "Paint Box", list("Atmospherics", "Bartender", "Barber", "Blueshield", "Captain",
"Cargo", "Chief Engineer", "Chaplain", "Chef", "Chemist", "Assistant", "Clown", "CMO", "Coroner", "Detective", "Engineering", "Genetics", "HOP",
"HOS", "Hydroponics", "Internal Affairs Agent", "Janitor", "Magistrate", "Medical", "Mime", "Mining", "NT Representative", "Paramedic",
"Prisoner", "Research Director", "Security", "Syndicate", "Therapist", "Virology", "Warden", "Xenobiology"))
if(!decalselection)
- return
+ return ITEM_INTERACT_COMPLETE
if(user.incapacitated())
to_chat(user, "You're in no condition to perform this action.")
- return
+ return ITEM_INTERACT_COMPLETE
if(W != user.get_active_hand())
to_chat(user, "You must be holding the pen to perform this action.")
- return
+ return ITEM_INTERACT_COMPLETE
if(!Adjacent(user))
to_chat(user, "You have moved too far away from the cardboard box.")
- return
+ return ITEM_INTERACT_COMPLETE
decalselection = replacetext(decalselection, " ", "_")
decalselection = lowertext(decalselection)
custom_skin = "_[decalselection]"
update_icon() // a proc declared in the closets parent file used to update opened/closed sprites on normal closets
- return
- return ..()
+
+ return ITEM_INTERACT_COMPLETE
diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
index 2b45b4a04ef..e52e7730991 100644
--- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
@@ -29,7 +29,7 @@
else
. += "It is damaged beyond repair."
-/obj/structure/closet/fireaxecabinet/attackby__legacy__attackchain(obj/item/O as obj, mob/living/user as mob) //Marker -Agouri
+/obj/structure/closet/fireaxecabinet/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(isrobot(user) || locked)
if(istype(O, /obj/item/multitool))
to_chat(user, "Resetting circuitry...")
@@ -38,14 +38,14 @@
locked = FALSE
to_chat(user, " You disable the locking modules.")
update_icon(UPDATE_ICON_STATE)
- return
+ return ITEM_INTERACT_COMPLETE
else if(isitem(O))
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/W = O
if(smashed || localopened)
if(localopened)
operate_panel()
- return
+ return ITEM_INTERACT_COMPLETE
else
user.do_attack_animation(src)
playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time
@@ -59,16 +59,16 @@
locked = FALSE
localopened = TRUE
update_icon(UPDATE_ICON_STATE)
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(O, /obj/item/fireaxe) && localopened)
if(!fireaxe)
var/obj/item/fireaxe/F = O
if(HAS_TRAIT(F, TRAIT_WIELDED))
to_chat(user, "Unwield \the [F] first.")
- return
+ return ITEM_INTERACT_COMPLETE
if(!user.unequip(F, FALSE))
to_chat(user, "\The [F] stays stuck to your hands!")
- return
+ return ITEM_INTERACT_COMPLETE
fireaxe = F
has_axe = "full"
contents += F
@@ -76,25 +76,27 @@
update_icon(UPDATE_ICON_STATE)
else
if(smashed)
- return
+ return ITEM_INTERACT_COMPLETE
else
operate_panel()
+ return ITEM_INTERACT_COMPLETE
else
if(smashed)
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(O, /obj/item/multitool))
if(localopened)
operate_panel()
- return
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "Resetting circuitry...")
playsound(user, 'sound/machines/lockenable.ogg', 50, 1)
if(do_after(user, 20 * O.toolspeed, target = src))
locked = TRUE
to_chat(user, " You re-enable the locking modules.")
- return
+ return ITEM_INTERACT_COMPLETE
else
operate_panel()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/closet/fireaxecabinet/attack_hand(mob/user as mob)
if(locked)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/depot_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/depot_closets.dm
index faec4fe0ae1..e19cc0773c7 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/depot_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/depot_closets.dm
@@ -36,10 +36,10 @@
return
return ..()
-/obj/structure/closet/secure_closet/depot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/closet/secure_closet/depot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/rcs))
to_chat(user, "Bluespace interference prevents [W] from locking onto [src]!")
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/closet/secure_closet/depot/emp_act(severity)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
index 892205426e2..5c31946fd21 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm
@@ -34,25 +34,25 @@
new /obj/item/storage/backpack/satchel/withwallet( src )
new /obj/item/radio/headset( src )
-/obj/structure/closet/secure_closet/personal/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/closet/secure_closet/personal/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(opened || !istype(W, /obj/item/card/id))
return ..()
if(broken)
to_chat(user, "The locker appears to be broken.")
- return
+ return ITEM_INTERACT_COMPLETE
if(user.loc == src)
to_chat(user, "You can't reach the lock from inside.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/card/id/guest))
to_chat(user, "Invalid identification card.")
- return
+ return ITEM_INTERACT_COMPLETE
var/obj/item/card/id/I = W
if(!I || !I.registered_name)
- return
+ return ITEM_INTERACT_COMPLETE
if(allowed(user) || !registered_name || (istype(I) && (registered_name == I.registered_name)))
//they can open all lockers, or nobody owns this, or they own this locker
@@ -68,3 +68,5 @@
else
to_chat(user, "Access denied.")
+
+ return ITEM_INTERACT_COMPLETE
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 639f59dae6b..91d88325b26 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -85,9 +85,9 @@
opened = FALSE
return TRUE
-/obj/structure/closet/crate/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/closet/crate/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(!opened && try_rig(W, user))
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/closet/crate/toggle(mob/user, by_hand = FALSE)
@@ -311,18 +311,18 @@
return FALSE
return TRUE
-/obj/structure/closet/crate/secure/personal/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/closet/crate/secure/personal/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(opened || !istype(I, /obj/item/card/id))
return ..()
if(broken)
to_chat(user, "It appears to be broken.")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
var/obj/item/card/id/id = I
if(!is_usable_id(id))
to_chat(user, "Invalid identification card.")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
if(registered_name && allowed(user))
return ..()
@@ -330,12 +330,12 @@
if(!registered_name)
registered_name = id.registered_name
to_chat(user, "Crate reserved")
- return TRUE
+ return ITEM_INTERACT_COMPLETE
if(registered_name == id.registered_name)
return ..()
- return FALSE
+ return ITEM_INTERACT_COMPLETE
/obj/structure/closet/crate/plastic
name = "plastic crate"
diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm
index 4195f5f0031..7633872defb 100644
--- a/code/game/objects/structures/crates_lockers/largecrate.dm
+++ b/code/game/objects/structures/crates_lockers/largecrate.dm
@@ -29,11 +29,10 @@
to_chat(user, "You need a crowbar to pry this open!")
return
-/obj/structure/largecrate/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
+/obj/structure/largecrate/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(user.a_intent != INTENT_HARM)
attack_hand(user)
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/largecrate/crowbar_act(mob/living/user, obj/item/I)
. = TRUE
diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm
index 8bfb3fc0126..33b654ac3b3 100644
--- a/code/game/objects/structures/curtains.dm
+++ b/code/game/objects/structures/curtains.dm
@@ -8,7 +8,6 @@
face_while_pulling = FALSE
layer = SHOWER_CLOSED_LAYER
opacity = TRUE
- new_attack_chain = TRUE
var/assembled = TRUE
var/overlay_color = "#ffffff"
var/overlay_alpha = 255
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 13b4fd258a2..f8f1978e9e4 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -130,30 +130,32 @@
if(!open && !broken)
. += "glassbox_closed"
-/obj/structure/displaycase/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/displaycase/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(I.GetID())
if(!openable)
to_chat(user, "There is no ID scanner, looks like this one is sealed shut.")
- return
+ return ITEM_INTERACT_COMPLETE
if(broken)
to_chat(user, "[src] is broken, the ID lock won't do anything.")
- return
+ return ITEM_INTERACT_COMPLETE
if(allowed(user) || emagged)
to_chat(user, "You use [I] to [open ? "close" : "open"] [src].")
toggle_lock()
else
to_chat(user, "Access denied.")
+ return ITEM_INTERACT_COMPLETE
else if(open && !showpiece)
if(!(I.flags & (ABSTRACT | DROPDEL)) && user.drop_item())
I.forceMove(src)
showpiece = I
to_chat(user, "You put [I] on display")
update_icon()
+ return ITEM_INTERACT_COMPLETE
else if(istype(I, /obj/item/stack/sheet/glass) && broken)
var/obj/item/stack/sheet/glass/G = I
if(G.get_amount() < 2)
to_chat(user, "You need two glass sheets to fix the case!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start fixing [src]...")
if(do_after(user, 20, target = src))
G.use(2)
@@ -161,6 +163,7 @@
open = FALSE
obj_integrity = max_integrity
update_icon(UPDATE_OVERLAYS)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
@@ -231,7 +234,7 @@
icon_state = "glassbox_chassis"
var/obj/item/airlock_electronics/electronics
-/obj/structure/displaycase_chassis/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/displaycase_chassis/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/airlock_electronics))
to_chat(user, "You start installing the electronics into [src]...")
playsound(loc, I.usesound, 50, TRUE)
@@ -242,12 +245,12 @@
electronics = new_electronics
to_chat(user, "You install the airlock electronics.")
electronics.is_installed = TRUE
-
+ return ITEM_INTERACT_COMPLETE
else if(istype(I, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = I
if(G.get_amount() < 10)
to_chat(user, "You need ten glass sheets to do this!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start adding [G] to [src]...")
if(do_after(user, 20, target = src))
G.use(10)
@@ -261,6 +264,7 @@
else
display.req_access = electronics.selected_accesses
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index c5464774f6b..e7c50db3dc2 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -55,7 +55,8 @@
else
. += "There is a small paper placard on the assembly[doorname]."
-/obj/structure/door_assembly/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/door_assembly/item_interaction(mob/living/user, obj/item/W, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
if(is_pen(W))
// The door assembly gets renamed to "Assembly - Foobar",
// but the `t` returned from the proc is just "Foobar" without the prefix.
diff --git a/code/game/objects/structures/engicart.dm b/code/game/objects/structures/engicart.dm
index 51d027ecc24..a476cc034a9 100644
--- a/code/game/objects/structures/engicart.dm
+++ b/code/game/objects/structures/engicart.dm
@@ -5,7 +5,6 @@
icon_state = "cart"
face_while_pulling = FALSE
density = TRUE
- new_attack_chain = TRUE
var/obj/item/stack/sheet/glass/my_glass = null
var/obj/item/stack/sheet/metal/my_metal = null
var/obj/item/stack/sheet/plasteel/my_plasteel = null
@@ -94,7 +93,7 @@
to_chat(user, fail_msg)
return
- if(!put_in_cart(used, user))
+ if(!put_in_cart(used, user))
return
my_flashlight = used
diff --git a/code/game/objects/structures/extinguisher_cabinet.dm b/code/game/objects/structures/extinguisher_cabinet.dm
index 06244919f9b..5c22c40fa9f 100644
--- a/code/game/objects/structures/extinguisher_cabinet.dm
+++ b/code/game/objects/structures/extinguisher_cabinet.dm
@@ -61,7 +61,7 @@
has_extinguisher = null
update_icon(UPDATE_ICON_STATE)
-/obj/structure/extinguisher_cabinet/attackby__legacy__attackchain(obj/item/O, mob/user, params)
+/obj/structure/extinguisher_cabinet/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(isrobot(user) || isalien(user))
return
if(istype(O, /obj/item/extinguisher))
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index cbc23fcebd2..3a42bdb41c0 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -114,13 +114,14 @@
qdel(src)
return T
-/obj/structure/falsewall/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/falsewall/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(opening)
to_chat(user, "You must wait until the door has stopped moving.")
- return
+ return ITEM_INTERACT_COMPLETE
- if(istype(W, /obj/item/gun/energy/plasmacutter) || istype(W, /obj/item/pickaxe/drill/diamonddrill) || istype(W, /obj/item/pickaxe/drill/jackhammer) || istype(W, /obj/item/melee/energy/blade) || istype(W, /obj/item/pyro_claws))
+ if(istype(used, /obj/item/gun/energy/plasmacutter) || istype(used, /obj/item/pickaxe/drill/diamonddrill) || istype(used, /obj/item/pickaxe/drill/jackhammer) || istype(used, /obj/item/melee/energy/blade) || istype(used, /obj/item/pyro_claws))
dismantle(user, TRUE)
+ return ITEM_INTERACT_COMPLETE
/obj/structure/falsewall/attack_animal(mob/living/simple_animal/M)
. = ..()
@@ -272,15 +273,14 @@
canSmoothWith = list(SMOOTH_GROUP_PLASMA_WALLS)
cares_about_temperature = TRUE
-/obj/structure/falsewall/plasma/attackby__legacy__attackchain(obj/item/W, mob/user, params)
- if(W.get_heat() > 300)
+/obj/structure/falsewall/plasma/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(used.get_heat() > 300)
var/turf/T = locate(user)
message_admins("Plasma falsewall ignited by [key_name_admin(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma falsewall ignited by [key_name(user)] in [AREACOORD(T)]")
investigate_log("was ignited by [key_name(user)]",INVESTIGATE_ATMOS)
burnbabyburn()
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/falsewall/plasma/proc/burnbabyburn(user)
playsound(src, 'sound/items/welder.ogg', 100, 1)
diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm
index 6617e4295a0..2aa7b9eb8a7 100644
--- a/code/game/objects/structures/fence.dm
+++ b/code/game/objects/structures/fence.dm
@@ -121,16 +121,16 @@
return
update_cut_status()
-/obj/structure/fence/attackby__legacy__attackchain(obj/item/C, mob/user)
+/obj/structure/fence/item_interaction(mob/living/user, obj/item/C, list/modifiers)
if(shock(user, 90))
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(C, /obj/item/stack/rods))
if(hole_size == NO_HOLE)
- return
+ return ITEM_INTERACT_COMPLETE
var/obj/item/stack/rods/R = C
if(R.get_amount() < HOLE_REPAIR)
to_chat(user, "You need [HOLE_REPAIR] rods to fix this fence!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You begin repairing the fence...")
if(do_after(user, 3 SECONDS * C.toolspeed, target = src) && hole_size != NO_HOLE && R.use(HOLE_REPAIR))
playsound(src, C.usesound, 80, 1)
@@ -138,8 +138,7 @@
obj_integrity = max_integrity
to_chat(user, "You repair the fence.")
update_cut_status()
- return
- . = ..()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/fence/Bumped(atom/user)
if(!ismob(user))
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 0c735c95982..5cc1f08153e 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -531,7 +531,7 @@
A.loc = get_turf(src)
*/
-/obj/structure/bush/attackby__legacy__attackchain(obj/I as obj, mob/user as mob, params)
+/obj/structure/bush/item_interaction(mob/living/user, obj/item/I, list/modifiers)
//hatchets can clear away undergrowth
if(istype(I, /obj/item/hatchet) && !stump)
if(indestructable)
@@ -554,8 +554,7 @@
pixel_y = rand(-6,6)
else
qdel(src)
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
//Jungle grass
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 3dce7563874..6dd705d67eb 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -47,108 +47,114 @@
if(temp_check >= GIRDER_MELTING_TEMP)
take_damage(10)
-/obj/structure/girder/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/girder/item_interaction(mob/living/user, obj/item/W, list/modifiers)
add_fingerprint(user)
if(istype(W, /obj/item/gun/energy/plasmacutter))
to_chat(user, "You start slicing apart the girder...")
if(do_after(user, 40 * W.toolspeed, target = src))
if(!src)
- return
+ return ITEM_INTERACT_COMPLETE
playsound(loc, W.usesound, 100, 1)
to_chat(user, "You slice apart the girder.")
refundMetal(metalUsed)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/pickaxe/drill/diamonddrill))
to_chat(user, "You drill through the girder!")
refundMetal(metalUsed)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/pickaxe/drill/jackhammer))
playsound(loc, W.usesound, 100, 1)
to_chat(user, "You disintegrate the girder!")
refundMetal(metalUsed)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/pyro_claws))
playsound(loc, W.usesound, 100, 1)
to_chat(user, "You melt the girder!")
refundMetal(metalUsed)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/stack))
if(iswallturf(loc))
to_chat(user, "There is already a wall present!")
- return
+ return ITEM_INTERACT_COMPLETE
if(!isfloorturf(loc))
to_chat(user, "A floor must be present to build a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
if(locate(/obj/structure/falsewall) in loc.contents)
to_chat(user, "There is already a false wall present!")
- return
+ return ITEM_INTERACT_COMPLETE
if(islava(loc))
to_chat(user, "You can't do that while [src] is in lava!")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/stack/sheet/runed_metal))
to_chat(user, "You can't seem to make the metal bend.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/stack/sheet/bamboo)) // pending wall resprite(tm)
to_chat(user, "The bamboo doesn't seem to fit around the girder.")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(W,/obj/item/stack/rods))
var/obj/item/stack/rods/S = W
if(state == GIRDER_DISPLACED)
if(S.get_amount() < 5)
to_chat(user, "You need at least five rods to create a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start building a reinforced false wall...")
if(do_after(user, 20, target = src))
if(!loc || !S || S.get_amount() < 5)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(5)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
var/obj/structure/falsewall/iron/FW = new (loc)
transfer_fingerprints_to(FW)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
if(S.get_amount() < 5)
to_chat(user, "You need at least five rods to add plating!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start adding plating...")
if(do_after(user, 40, target = src))
if(!loc || !S || S.get_amount() < 5)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(5)
to_chat(user, "You add the plating.")
var/turf/T = get_turf(src)
T.ChangeTurf(/turf/simulated/wall/mineral/iron)
transfer_fingerprints_to(T)
qdel(src)
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/stack/ore/glass/basalt))
var/obj/item/stack/ore/glass/basalt/A = W
if(state == GIRDER_DISPLACED)
if(A.get_amount() < 2)
to_chat(user, "You need at least two [A] to create a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
if(do_after(user, 2 SECONDS, target = src))
if(!loc || !A || A.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
A.use(2)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
var/obj/structure/falsewall/rock_ancient/FW = new (loc)
transfer_fingerprints_to(FW)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
if(A.get_amount() < 2)
to_chat(user, "You need at least two [A] to add plating!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start adding [A]...")
if(do_after(user, 4 SECONDS, target = src))
if(!src || !A || A.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
A.use(2)
to_chat(user, "You add [A].")
var/turf/parent_turf = get_turf(src)
@@ -156,38 +162,39 @@
for(var/turf/simulated/mineral/X in parent_turf.loc)
X.add_hiddenprint(usr)
qdel(src)
- return
+ return ITEM_INTERACT_COMPLETE
if(!istype(W,/obj/item/stack/sheet))
- return
+ return ITEM_INTERACT_COMPLETE
var/obj/item/stack/sheet/S = W
if(!S.wall_allowed)
to_chat(user, "You don't think that is good material for a wall!")
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(S, /obj/item/stack/sheet/wood))
if(state == GIRDER_DISPLACED)
if(S.get_amount() < 2)
to_chat(user, "You need two planks of wood to create a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start building a false wall...")
if(do_after(user, 20, target = src))
if(!loc || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
var/obj/structure/falsewall/wood/falsewood = new(loc)
transfer_fingerprints_to(falsewood)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
if(S.get_amount() < 2)
to_chat(user, "You need two planks of wood to finish a wall!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start adding plating...")
if(do_after(user, 40 * W.toolspeed, target = src))
if(!src || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You add the plating.")
var/turf/Tsrc = get_turf(src)
@@ -196,30 +203,30 @@
if(X)
X.add_hiddenprint(usr)
qdel(src)
- return
-
+ return ITEM_INTERACT_COMPLETE
else if(istype(S, /obj/item/stack/sheet/metal))
if(state == GIRDER_DISPLACED)
if(S.get_amount() < 2)
to_chat(user, "You need two sheets of metal to create a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start building a false wall...")
if(do_after(user, 20, target = src))
if(!loc || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
var/obj/structure/falsewall/F = new(loc)
transfer_fingerprints_to(F)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
if(S.get_amount() < 2)
to_chat(user, "You need two sheets of metal to finish a wall!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start adding plating...")
if(do_after(user, 40 * W.toolspeed, target = src))
if(!src || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You add the plating.")
var/turf/Tsrc = get_turf(src)
@@ -228,30 +235,31 @@
if(X)
X.add_hiddenprint(usr)
qdel(src)
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(S, /obj/item/stack/sheet/plasteel))
if(state == GIRDER_DISPLACED)
if(S.get_amount() < 2)
to_chat(user, "You need at least two sheets to create a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start building a reinforced false wall...")
if(do_after(user, 20, target = src))
if(!loc || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You create a reinforced false wall. Push on it to open or close the passage.")
var/obj/structure/falsewall/reinforced/FW = new (loc)
transfer_fingerprints_to(FW)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
if(state == GIRDER_REINF)
if(S.get_amount() < 1)
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start finalizing the reinforced wall...")
if(do_after(user, 50, target = src))
if(!src || !S || S.get_amount() < 1)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(1)
to_chat(user, "You fully reinforce the wall.")
var/turf/Tsrc = get_turf(src)
@@ -260,44 +268,45 @@
if(X)
X.add_hiddenprint(usr)
qdel(src)
- return
+ return ITEM_INTERACT_COMPLETE
else
if(S.get_amount() < 1)
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start reinforcing the girder...")
if(do_after(user,60, target = src))
if(!src || !S || S.get_amount() < 1)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(1)
to_chat(user, "You reinforce the girder.")
var/obj/structure/girder/reinforced/R = new (loc)
transfer_fingerprints_to(R)
qdel(src)
- return
+ return ITEM_INTERACT_COMPLETE
if(S.sheettype)
var/M = S.sheettype
if(state == GIRDER_DISPLACED)
if(S.get_amount() < 2)
to_chat(user, "You need at least two sheets to create a false wall!")
- return
+ return ITEM_INTERACT_COMPLETE
if(do_after(user, 20, target = src))
if(!loc || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
var/F = text2path("/obj/structure/falsewall/[M]")
var/obj/structure/FW = new F (loc)
transfer_fingerprints_to(FW)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else
if(S.get_amount() < 2)
to_chat(user, "You need at least two sheets to add plating!")
- return
+ return ITEM_INTERACT_COMPLETE
to_chat(user, "You start adding plating...")
if(do_after(user,40, target = src))
if(!src || !S || S.get_amount() < 2)
- return
+ return ITEM_INTERACT_COMPLETE
S.use(2)
to_chat(user, "You add the plating.")
var/turf/Tsrc = get_turf(src)
@@ -306,12 +315,9 @@
if(X)
X.add_hiddenprint(usr)
qdel(src)
- return
-
+ return ITEM_INTERACT_COMPLETE
add_hiddenprint(user)
-
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/girder/crowbar_act(mob/user, obj/item/I)
if(!can_displace || state != GIRDER_NORMAL)
@@ -464,12 +470,13 @@
. = ..()
icon_state = GET_CULT_DATA(cult_girder_icon_state, initial(icon_state))
-/obj/structure/girder/cult/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/girder/cult/item_interaction(mob/living/user, obj/item/W, list/modifiers)
add_fingerprint(user)
if(istype(W, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user)) //Cultists can demolish cult girders instantly with their dagger
user.visible_message("[user] strikes [src] with [W]!", "You demolish [src].")
refundMetal(metalUsed)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/gun/energy/plasmacutter))
to_chat(user, "You start slicing apart the girder...")
if(do_after(user, 40* W.toolspeed, target = src))
@@ -479,6 +486,7 @@
R.amount = 1
transfer_fingerprints_to(R)
qdel(src)
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/pickaxe/drill/jackhammer))
var/obj/item/pickaxe/drill/jackhammer/D = W
to_chat(user, "Your jackhammer smashes through the girder!")
@@ -487,23 +495,22 @@
transfer_fingerprints_to(R)
D.playDigSound()
qdel(src)
-
+ return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/stack/sheet/runed_metal))
var/obj/item/stack/sheet/runed_metal/R = W
if(R.get_amount() < 1)
to_chat(user, "You need at least one sheet of runed metal to construct a runed wall!")
- return 0
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] begins laying runed metal on [src]...", "You begin constructing a runed wall...")
if(do_after(user, 10, target = src))
if(R.get_amount() < 1 || !R)
- return
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] plates [src] with runed metal.", "You construct a runed wall.")
R.use(1)
var/turf/T = get_turf(src)
T.ChangeTurf(/turf/simulated/wall/cult)
qdel(src)
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/girder/cult/narsie_act()
return
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index e01e4de3106..4538358f1ac 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -115,20 +115,21 @@
if(pass_info.is_movable)
. = . || pass_info.pass_flags & PASSGRILLE
-/obj/structure/grille/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/grille/item_interaction(mob/living/user, obj/item/I, list/modifiers)
user.changeNext_move(CLICK_CD_MELEE)
add_fingerprint(user)
if(istype(I, /obj/item/stack/rods) && broken)
repair(user, I)
+ return ITEM_INTERACT_COMPLETE
//window placing begin
else if(is_glass_sheet(I))
build_window(I, user)
- return
+ return ITEM_INTERACT_COMPLETE
//window placing end
- else if(istype(I, /obj/item/shard) || !shock(user, 70))
- return ..()
+ else if((!istype(I, /obj/item/shard)) && shock(user, 70))
+ return ITEM_INTERACT_COMPLETE
/obj/structure/grille/proc/repair(mob/user, obj/item/stack/rods/R)
if(R.get_amount() >= 1)
diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm
index ee55b07cd7d..e8e2fea71ba 100644
--- a/code/game/objects/structures/guillotine.dm
+++ b/code/game/objects/structures/guillotine.dm
@@ -154,33 +154,29 @@
blade_status = GUILLOTINE_BLADE_DROPPED
icon_state = "guillotine"
-/obj/structure/guillotine/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/guillotine/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/whetstone))
add_fingerprint(user)
if(blade_status == GUILLOTINE_BLADE_SHARPENING)
- return
+ return ITEM_INTERACT_COMPLETE
if(blade_status == GUILLOTINE_BLADE_RAISED)
if(blade_sharpness < GUILLOTINE_BLADE_MAX_SHARP)
blade_status = GUILLOTINE_BLADE_SHARPENING
- if(do_after(user, 7, target = src))
+ if(do_after(user, W.toolspeed, target = src))
blade_status = GUILLOTINE_BLADE_RAISED
user.visible_message("[user] sharpens the large blade of the guillotine.",
"You sharpen the large blade of the guillotine.")
blade_sharpness += 1
playsound(src, 'sound/items/screwdriver.ogg', 100, 1)
- return
else
blade_status = GUILLOTINE_BLADE_RAISED
- return
else
to_chat(user, "The blade is sharp enough!")
- return
else
to_chat(user, "You need to raise the blade in order to sharpen it!")
- return
- else
- return ..()
+
+ return ITEM_INTERACT_COMPLETE
/obj/structure/guillotine/wrench_act(mob/user, obj/item/I)
if(current_action)
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index 3f9b36a6b38..78b04ded2f4 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -53,7 +53,6 @@
icon_state = "wall"
var/torn = /obj/item/inflatable/torn
var/intact = /obj/item/inflatable
- new_attack_chain = TRUE
/obj/structure/inflatable/examine(mob/user)
. = ..()
@@ -219,7 +218,7 @@
if(!useResource(user))
return ITEM_INTERACT_COMPLETE
-
+
return ..()
/obj/item/inflatable/cyborg/proc/useResource(mob/user)
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index 5b9a3a9346e..47312248b06 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -8,7 +8,6 @@
density = TRUE
face_while_pulling = FALSE
container_type = OPENCONTAINER
- new_attack_chain = TRUE
//copypaste sorry
var/maximum_volume = 150
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 3d782aafc03..1fa497e829b 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -20,7 +20,7 @@
deconstruct(TRUE)
return TRUE
-/obj/structure/kitchenspike_frame/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/kitchenspike_frame/item_interaction(mob/living/user, obj/item/I, list/modifiers)
add_fingerprint(user)
if(istype(I, /obj/item/stack/rods))
var/obj/item/stack/rods/R = I
@@ -30,9 +30,9 @@
new /obj/structure/kitchenspike(loc)
add_fingerprint(user)
qdel(src)
- return
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
+
+ return ..()
/obj/structure/kitchenspike_frame/examine(mob/user)
. = ..()
@@ -56,6 +56,7 @@
buckle_lying = FALSE
can_buckle = TRUE
max_integrity = 250
+ var/impale_time = 6 SECONDS
/obj/structure/kitchenspike/examine(mob/user)
. = ..()
@@ -69,11 +70,13 @@
else
..()
-/obj/structure/kitchenspike/attackby__legacy__attackchain(obj/item/I, mob/user)
+/obj/structure/kitchenspike/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/grab))
var/obj/item/grab/G = I
if(G.affecting && isliving(G.affecting))
start_spike(G.affecting, user)
+ return ITEM_INTERACT_COMPLETE
+
return ..()
/obj/structure/kitchenspike/crowbar_act(mob/living/user, obj/item/I)
@@ -103,7 +106,7 @@
"[user] tries to slam [victim] onto the meat spike!",
"[user] tries to slam you onto the meat spike!"
)
- if(do_mob(user, victim, 6 SECONDS))
+ if(do_mob(user, victim, impale_time))
end_spike(victim, user)
/obj/structure/kitchenspike/proc/end_spike(mob/living/victim, mob/user)
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index 2abb32aadbf..7ec90313aee 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -28,18 +28,28 @@
/obj/structure/lattice/proc/deconstruction_hints(mob/user)
return "The rods look like they could be cut. There's space for more rods or a tile."
-/obj/structure/lattice/attackby__legacy__attackchain(obj/item/C, mob/user, params)
+/obj/structure/lattice/wirecutter_act(mob/living/user, obj/item/wirecutters/wirecutters)
if(resistance_flags & INDESTRUCTIBLE)
return
- if(istype(C, /obj/item/wirecutters))
- var/obj/item/wirecutters/W = C
- playsound(loc, W.usesound, 50, 1)
- to_chat(user, "Slicing [name] joints...")
- deconstruct()
- else
- // hand this off to the turf instead (for building plating, catwalks, etc)
- var/turf/T = get_turf(src)
- return T.item_interaction(user, C, params)
+ if(!istype(wirecutters))
+ return
+
+ playsound(loc, wirecutters.usesound, 50, 1)
+ to_chat(user, "Slicing [name] joints...")
+ deconstruct()
+
+ return ITEM_INTERACT_COMPLETE
+
+/obj/structure/lattice/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ // this is still here for historical reasons though it's
+ // not clear if the original intention was to prevent indestructible
+ // lattices from e.g. being built over with plating.
+ if(resistance_flags & INDESTRUCTIBLE)
+ return
+
+ // hand this off to the turf (for building plating, catwalks, etc)
+ var/turf/T = get_turf(src)
+ return T.item_interaction(user, used, modifiers)
/obj/structure/lattice/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
diff --git a/code/game/objects/structures/lavaland/necropolis_tendril.dm b/code/game/objects/structures/lavaland/necropolis_tendril.dm
index d39d7e97540..4bf4f1d81ce 100644
--- a/code/game/objects/structures/lavaland/necropolis_tendril.dm
+++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm
@@ -43,8 +43,7 @@ GLOBAL_LIST_EMPTY(tendrils)
new /obj/structure/closet/crate/necropolis/tendril(loc)
return ..()
-/obj/structure/spawner/lavaland/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
- . = ..()
+/obj/structure/spawner/lavaland/attacked_by(obj/item/attacker, mob/living/user)
SEND_SIGNAL(src, COMSIG_SPAWNER_SET_TARGET, user)
/obj/structure/spawner/lavaland/bullet_act(obj/item/projectile/P)
diff --git a/code/game/objects/structures/loom.dm b/code/game/objects/structures/loom.dm
index fd0e30d1144..9105d5a5db4 100644
--- a/code/game/objects/structures/loom.dm
+++ b/code/game/objects/structures/loom.dm
@@ -9,10 +9,14 @@
icon_state = "loom"
density = TRUE
anchored = TRUE
+ // TODO: should absolutely be keyed to tool speed but
+ // is just a constant for now for use in tests
+ var/disassemble_speed = 5 SECONDS
-/obj/structure/loom/attackby__legacy__attackchain(obj/item/I, mob/user)
+/obj/structure/loom/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(weave(I, user))
- return
+ return ITEM_INTERACT_COMPLETE
+
return ..()
/obj/structure/loom/crowbar_act(mob/user, obj/item/I)
@@ -20,7 +24,7 @@
if(!I.use_tool(src, user, 0))
return
TOOL_ATTEMPT_DISMANTLE_MESSAGE
- if(I.use_tool(src, user, 50, volume = I.tool_volume))
+ if(I.use_tool(src, user, disassemble_speed, volume = I.tool_volume))
TOOL_DISMANTLE_SUCCESS_MESSAGE
deconstruct(disassembled = TRUE)
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 64602411892..f4231e421c5 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -116,15 +116,17 @@
else
icon_state = initial_state
-/obj/structure/mineral_door/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/mineral_door/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/pickaxe))
var/obj/item/pickaxe/digTool = W
to_chat(user, "You start digging \the [src].")
if(do_after(user, 40 * digTool.toolspeed * hardness, target = src) && src)
to_chat(user, "You finished digging.")
deconstruct(TRUE)
+ return ITEM_INTERACT_COMPLETE
else if(user.a_intent != INTENT_HARM)
attack_hand(user)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
@@ -182,12 +184,13 @@
sheetType = /obj/item/stack/sheet/mineral/plasma
cares_about_temperature = TRUE
-/obj/structure/mineral_door/transparent/plasma/attackby__legacy__attackchain(obj/item/W, mob/user)
+/obj/structure/mineral_door/transparent/plasma/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(W.get_heat())
message_admins("Plasma mineral door ignited by [key_name_admin(user)] in ([x], [y], [z] - JMP)", 0, 1)
log_game("Plasma mineral door ignited by [key_name(user)] in ([x], [y], [z])")
investigate_log("was ignited by [key_name(user)]",INVESTIGATE_ATMOS)
TemperatureAct(100)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index eeea74eaeb6..1e01adef4b7 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -106,6 +106,10 @@
var/organ_warn = FALSE
var/actually_magical = TRUE
+/obj/structure/mirror/magic/Initialize(mapload, newdir, building)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
+
/obj/structure/mirror/magic/attack_hand(mob/user)
if(!ishuman(user) || broken)
return
@@ -174,9 +178,6 @@
/obj/structure/mirror/magic/ui_close(mob/user)
curse(user)
-/obj/structure/mirror/magic/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
- return
-
/obj/structure/mirror/magic/proc/curse(mob/living/user)
return
diff --git a/code/game/objects/structures/misc_structures.dm b/code/game/objects/structures/misc_structures.dm
index fa7ff2c335b..f0387c9e570 100644
--- a/code/game/objects/structures/misc_structures.dm
+++ b/code/game/objects/structures/misc_structures.dm
@@ -10,7 +10,6 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "signpost"
anchored = TRUE
- new_attack_chain = TRUE
var/writing = ""
/obj/structure/signpost/Initialize(mapload)
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index 13faf7fd874..e1b990d3438 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -6,7 +6,6 @@
density = TRUE
container_type = OPENCONTAINER
face_while_pulling = FALSE
- new_attack_chain = TRUE
var/obj/item/mop/stored_mop = null
var/maximum_volume = 150
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
@@ -39,7 +38,7 @@
/obj/structure/mopbucket/proc/handle_mop_interaction(mob/living/user, obj/item/used)
if(!istype(used, /obj/item/mop))
return FALSE
-
+
. = TRUE
var/robot_mop = used.is_robot_module()
var/obj/item/mop/attacking_mop = used
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 94f5f3f02e9..85de7d134d4 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -37,7 +37,6 @@
anchored = TRUE
var/open_sound = 'sound/items/deconstruct.ogg'
var/status
- new_attack_chain = TRUE
/obj/structure/morgue/Initialize(mapload)
. = ..()
@@ -338,7 +337,6 @@ GLOBAL_LIST_EMPTY(crematoriums)
var/repairstate = CREMATOR_OPERATIONAL // Repairstate 0 is DESTROYED, 1 has the igniter applied but needs welding (IN_REPAIR), 2 is OPERATIONAL
var/locked = FALSE
var/open_sound = 'sound/items/deconstruct.ogg'
- new_attack_chain = TRUE
/obj/structure/crematorium/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm
index c7edc835230..67d21107983 100644
--- a/code/game/objects/structures/noticeboard.dm
+++ b/code/game/objects/structures/noticeboard.dm
@@ -103,20 +103,20 @@
paper.show_content(usr)
return
-/obj/structure/noticeboard/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/noticeboard/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/paper))
if(notices >= MAX_NOTICES)
to_chat(user, "You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.")
- return
+ return ITEM_INTERACT_COMPLETE
if(!user.drop_item())
- return
+ return ITEM_INTERACT_COMPLETE
I.forceMove(src)
notices++
to_chat(user, "You pin the paper to the noticeboard.")
update_icon(UPDATE_ICON_STATE)
add_fingerprint(user)
SStgui.update_uis(src)
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm
index 7b3075310e7..27e8ff37ca1 100644
--- a/code/game/objects/structures/railings.dm
+++ b/code/game/objects/structures/railings.dm
@@ -43,9 +43,9 @@
/obj/structure/railing/cap/reversed
icon_state = "railing_cap_reversed"
-/obj/structure/railing/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
- ..()
- add_fingerprint(user)
+/obj/structure/railing/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ . = ..()
+ add_fingerprint(user) // No clue why this is happening here
/obj/structure/railing/attack_animal(mob/living/simple_animal/M)
. = ..()
diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm
index 889c6a970a1..92ce2edecc2 100644
--- a/code/game/objects/structures/reflector.dm
+++ b/code/game/objects/structures/reflector.dm
@@ -39,8 +39,8 @@
new_dir = 0
return -1
-
-/obj/structure/reflector/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/reflector/item_interaction(mob/living/user, obj/item/W, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
//Finishing the frame
if(istype(W,/obj/item/stack/sheet))
if(finished)
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index 430584fb87d..da5949c0a85 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -187,30 +187,33 @@ GLOBAL_LIST_EMPTY(safes)
else
ui_interact(user)
-/obj/structure/safe/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/safe/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(open)
if(I.flags && ABSTRACT)
- return
+ return ITEM_INTERACT_COMPLETE
if(broken && istype(I, /obj/item/safe_internals) && do_after(user, 2 SECONDS, target = src))
to_chat(user, "You replace the broken mechanism.")
qdel(I)
broken = FALSE
locked = FALSE
update_icon()
+ return ITEM_INTERACT_COMPLETE
else if(I.w_class + space <= maxspace)
if(!user.drop_item())
to_chat(user, "\The [I] is stuck to your hand, you cannot put it in the safe!")
- return
+ return ITEM_INTERACT_COMPLETE
space += I.w_class
I.forceMove(src)
to_chat(user, "You put [I] in [src].")
SStgui.update_uis(src)
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "[I] won't fit in [src].")
+ return ITEM_INTERACT_COMPLETE
else
if(istype(I, /obj/item/clothing/neck/stethoscope))
attack_hand(user)
- return
+ return ITEM_INTERACT_COMPLETE
else if(istype(I, /obj/item/thermal_drill))
if(drill)
to_chat(user, "There is already a drill attached!")
@@ -222,9 +225,10 @@ GLOBAL_LIST_EMPTY(safes)
drill = I
time_to_drill = DRILL_TIME * drill.time_multiplier
update_icon()
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You can't put [I] into the safe while it is closed!")
- return
+ return ITEM_INTERACT_COMPLETE
/obj/structure/safe/ui_state(mob/user)
return GLOB.physical_state
diff --git a/code/game/objects/structures/shelves.dm b/code/game/objects/structures/shelves.dm
index 367ee254ed6..da3459403b4 100644
--- a/code/game/objects/structures/shelves.dm
+++ b/code/game/objects/structures/shelves.dm
@@ -27,7 +27,7 @@ GLOBAL_LIST_INIT(shelf_colors, list("basic", "sci", "sup", "serv", "med", "sec",
if(mapload)
SEND_SIGNAL(src, COMSIG_SHELF_ADDED_ON_MAPLOAD)
-/obj/structure/shelf/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
+/obj/structure/shelf/item_interaction(mob/living/user, obj/item/I, list/modifiers)
var/obj/item/toy/crayon/spraycan/spraycan = I
if(!istype(spraycan))
return ..()
@@ -41,7 +41,7 @@ GLOBAL_LIST_INIT(shelf_colors, list("basic", "sci", "sup", "serv", "med", "sec",
if(!COOLDOWN_FINISHED(src, spraypaint_cd))
to_chat(user, "The paint on [src] is still drying!")
- return
+ return ITEM_INTERACT_COMPLETE
var/cur_idx = GLOB.shelf_colors.Find(shelf_style)
if(!cur_idx)
@@ -54,6 +54,7 @@ GLOBAL_LIST_INIT(shelf_colors, list("basic", "sci", "sup", "serv", "med", "sec",
// Tiny cooldown to prevent constant spamming of the action
COOLDOWN_START(src, spraypaint_cd, 1 SECONDS)
+ return ITEM_INTERACT_COMPLETE
/obj/structure/shelf/proc/set_style(new_style)
if(shelf_style == new_style && !isnull(shelf_overlay))
@@ -73,7 +74,7 @@ GLOBAL_LIST_INIT(shelf_colors, list("basic", "sci", "sup", "serv", "med", "sec",
. = TRUE
if(user.a_intent == INTENT_HELP)
return FALSE
- if(!I.use_tool(src, user, 2.5 SECONDS, volume = I.tool_volume))
+ if(!I.use_tool(src, user, (2.5 SECONDS) * I.toolspeed, volume = I.tool_volume))
return
to_chat(user, "You disassemble [src].")
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index 0de8b0cee74..195d6e21a04 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -8,11 +8,11 @@
var/oreAmount = 5
var/material_drop_type = /obj/item/stack/sheet/metal
-/obj/structure/statue/attackby__legacy__attackchain(obj/item/W, mob/living/user, params)
+/obj/structure/statue/item_interaction(mob/living/user, obj/item/W, list/modifiers)
add_fingerprint(user)
if(!(flags & NODECONSTRUCT))
if(default_unfasten_wrench(user, W))
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/gun/energy/plasmacutter))
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] is slicing apart the [name]...", \
@@ -23,7 +23,7 @@
user.visible_message("[user] slices apart the [name].", \
"You slice apart the [name].")
deconstruct(TRUE)
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/statue/welder_act(mob/user, obj/item/I)
@@ -107,13 +107,13 @@
PlasmaBurn()
..()
-/obj/structure/statue/plasma/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/statue/plasma/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(W.get_heat() > 300)//If the temperature of the object is over 300, then ignite
message_admins("[key_name_admin(user)] ignited a plasma statue at [COORD(loc)]")
log_game("[key_name(user)] ignited plasma a statue at [COORD(loc)]")
investigate_log("[key_name(user)] ignited a plasma statue at [COORD(loc)]", INVESTIGATE_ATMOS)
ignite(W.get_heat())
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/statue/plasma/welder_act(mob/user, obj/item/I)
@@ -225,7 +225,7 @@
honk()
..()
-/obj/structure/statue/bananium/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/statue/bananium/item_interaction(mob/living/user, obj/item/used, list/modifiers)
honk()
return ..()
@@ -321,11 +321,12 @@
new /obj/item/grown/log(drop_location())
return ..()
-/obj/structure/snowman/built/attackby__legacy__attackchain(obj/item/I, mob/user)
+/obj/structure/snowman/built/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/snowball) && obj_integrity < max_integrity)
to_chat(user, "You patch some of the damage on [src] with [I].")
obj_integrity = max_integrity
qdel(I)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
index 698d29a04c0..b65bd249f8b 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
@@ -151,7 +151,7 @@
var/icon_down = "down"
var/folded = /obj/item/roller
-/obj/structure/bed/roller/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/bed/roller/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/roller_holder))
if(has_buckled_mobs())
if(length(buckled_mobs) > 1)
@@ -163,6 +163,8 @@
user.visible_message("[user] collapses \the [name].", "You collapse \the [name].")
new folded(get_turf(src))
qdel(src)
+
+ return ITEM_INTERACT_COMPLETE
else
return ..()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index be7597fe0c0..5e6eae29ff8 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -35,12 +35,12 @@
W.setDir(dir)
qdel(src)
-/obj/structure/chair/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
+/obj/structure/chair/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/assembly/shock_kit))
var/obj/item/assembly/shock_kit/SK = W
if(!SK.status)
to_chat(user, "[SK] is not ready to be attached!")
- return
+ return ITEM_INTERACT_COMPLETE
user.drop_item()
var/obj/structure/chair/e_chair/E = new /obj/structure/chair/e_chair(get_turf(src), SK)
playsound(src.loc, W.usesound, 50, 1)
@@ -48,8 +48,7 @@
SK.loc = E
SK.master = E
qdel(src)
- return
- return ..()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/chair/wrench_act(mob/user, obj/item/I)
. = TRUE
@@ -322,8 +321,7 @@
armrest.layer = ABOVE_MOB_LAYER
return ..()
-/obj/structure/chair/sofa/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
- . = ..()
+/obj/structure/chair/sofa/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(!colorable)
return
if(istype(I, /obj/item/toy/crayon))
@@ -332,11 +330,17 @@
var/list/hsl = rgb2hsl(hex2num(copytext(new_color, 2, 4)), hex2num(copytext(new_color, 4, 6)), hex2num(copytext(new_color, 6, 8)))
hsl[3] = max(hsl[3], 0.4)
var/list/rgb = hsl2rgb(arglist(hsl))
- color = "#[num2hex(rgb[1], 2)][num2hex(rgb[2], 2)][num2hex(rgb[3], 2)]"
- if(color)
- cut_overlay(armrest)
- armrest = GetArmrest()
- update_armrest()
+ set_color("#[num2hex(rgb[1], 2)][num2hex(rgb[2], 2)][num2hex(rgb[3], 2)]")
+ return ITEM_INTERACT_COMPLETE
+
+/obj/structure/chair/sofa/proc/set_color(new_color)
+ if(color == new_color)
+ return
+
+ color = new_color
+ cut_overlay(armrest)
+ armrest = GetArmrest()
+ update_armrest()
/obj/structure/chair/sofa/proc/GetArmrest()
return mutable_appearance('icons/obj/chairs.dmi', "[icon_state]_armrest")
@@ -437,13 +441,17 @@
/obj/structure/chair/sofa/bench/handle_layer()
return
-/obj/structure/chair/sofa/bench/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
- . = ..()
+/obj/structure/chair/sofa/bench/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = I
- cover_color = C.colour
- if(cover_color)
- GetCover()
+ set_cover_color(C.colour)
+ return ITEM_INTERACT_COMPLETE
+
+/obj/structure/chair/sofa/bench/proc/set_cover_color(new_color)
+ if(cover_color == new_color)
+ return
+
+ GetCover()
/obj/structure/chair/sofa/bench/left
icon_state = "bench_left_mapping"
diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm
index ee8ccf014d0..e4f1036a225 100644
--- a/code/game/objects/structures/table_frames.dm
+++ b/code/game/objects/structures/table_frames.dm
@@ -24,9 +24,11 @@
///What stacks can be used to make the table, and if it will result in a unique table
var/list/restrict_table_types = list() //ex: list(/obj/item/stack/tile/carpet = /obj/structure/table/wood/poker, /obj/item/stack/sheet/wood = /obj/item/stack/sheet/wood::table_type), carpet will make poker table, wood will result in standard table_type. If the list is empty, any material can be used for its default table_type.
-/obj/structure/table_frame/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- if(!try_make_table(I, user))
- return ..()
+/obj/structure/table_frame/item_interaction(mob/living/user, obj/item/I, list/modifiers)
+ if(try_make_table(I, user))
+ return ITEM_INTERACT_COMPLETE
+
+ return ..()
///Try to make a table with the item used to attack. FALSE if you can't make a table and should attack. TRUE does not necessarily mean a table was made.
/obj/structure/table_frame/proc/try_make_table(obj/item/stack/stack, mob/user)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 8dc548e7be8..22efeb134a2 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -227,30 +227,30 @@
return TRUE
qdel(G)
-/obj/structure/table/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/table/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/grab))
tablepush(I, user)
- return
+ return ITEM_INTERACT_COMPLETE
if(isrobot(user) && !istype(I.loc, /obj/item/gripper))
- return
+ return ITEM_INTERACT_COMPLETE
if(user.a_intent == INTENT_HELP && !(I.flags & ABSTRACT))
if(user.drop_item())
I.Move(loc)
- var/list/click_params = params2list(params)
//Center the icon where the user clicked.
- if(!click_params || !click_params["icon-x"] || !click_params["icon-y"])
+ if(!modifiers || !modifiers["icon-x"] || !modifiers["icon-y"])
return
//Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf)
- I.pixel_x = clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
- I.pixel_y = clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
+ I.pixel_x = clamp(text2num(modifiers["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
+ I.pixel_y = clamp(text2num(modifiers["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
if(slippery)
step_away(I, user)
visible_message("[I] slips right off [src]!")
playsound(loc, 'sound/misc/slip.ogg', 50, TRUE, -1)
else //Don't want slippery moving tables to have the item attached to them if it slides off.
item_placed(I)
+ return ITEM_INTERACT_COMPLETE
else
return ..()
@@ -944,15 +944,15 @@
step(O, get_dir(O, src))
return TRUE
-/obj/structure/rack/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/rack/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(isrobot(user) && !istype(W.loc, /obj/item/gripper))
return
if(user.a_intent == INTENT_HARM)
- return ..()
+ return
if(!(W.flags & ABSTRACT))
if(user.drop_item())
W.Move(loc)
- return
+ return ITEM_INTERACT_COMPLETE
/obj/structure/rack/wrench_act(mob/user, obj/item/I)
. = TRUE
diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm
index e86d23a5d35..a5958cc4bfe 100644
--- a/code/game/objects/structures/tank_dispenser.dm
+++ b/code/game/objects/structures/tank_dispenser.dm
@@ -95,14 +95,14 @@
add_fingerprint(usr)
return TRUE
-/obj/structure/dispenser/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/dispenser/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/tank/internals/oxygen) || istype(I, /obj/item/tank/internals/air) || istype(I, /obj/item/tank/internals/anesthetic))
try_insert_tank(user, stored_oxygen_tanks, I)
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(I, /obj/item/tank/internals/plasma))
try_insert_tank(user, stored_plasma_tanks, I)
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/dispenser/wrench_act(mob/living/user, obj/item/I)
diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm
index 625a8a8ba91..f9da361036b 100644
--- a/code/game/objects/structures/target_stake.dm
+++ b/code/game/objects/structures/target_stake.dm
@@ -22,7 +22,7 @@
pinned_target = null
density = TRUE
-/obj/structure/target_stake/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/target_stake/item_interaction(mob/living/user, obj/item/W, list/modifiers)
// Putting objects on the stake. Most importantly, targets
if(istype(W, /obj/item/target) && !pinned_target)
density = FALSE
@@ -32,7 +32,7 @@
W.layer = 3.1
pinned_target = W
to_chat(user, "You slide the target into the stake.")
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/target_stake/attack_hand(mob/user)
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index 8c9f729d30b..ae290e549d2 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -103,7 +103,7 @@
L.Weaken(10 SECONDS)
-/obj/structure/transit_tube/station/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/transit_tube/station/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/grab) && hatch_state == TRANSIT_TUBE_OPEN)
var/obj/item/grab/G = W
if(ismob(G.affecting) && G.state >= GRAB_AGGRESSIVE)
@@ -115,6 +115,7 @@
Bumped(GM)
qdel(G)
break
+ return ITEM_INTERACT_COMPLETE
/obj/structure/transit_tube/station/proc/open_hatch()
if(hatch_state == TRANSIT_TUBE_CLOSED)
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 8d24c2bb9fb..f40be4798b9 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -10,7 +10,6 @@
var/cistern = FALSE //if the cistern bit is open
var/w_items = 0 //the combined w_class of all the items in the cistern
var/mob/living/swirlie = null //the mob being given a swirlie
- new_attack_chain = TRUE
MAPPING_DIRECTIONAL_HELPERS_CUSTOM(/obj/structure/toilet, 8, -8, 0, 0)
@@ -237,7 +236,6 @@ MAPPING_DIRECTIONAL_HELPERS_CUSTOM(/obj/structure/toilet, 8, -8, 0, 0)
icon = 'icons/obj/watercloset.dmi'
icon_state = "urinal"
anchored = TRUE
- new_attack_chain = TRUE
/obj/structure/urinal/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(istype(used, /obj/item/grab))
@@ -520,7 +518,6 @@ MAPPING_DIRECTIONAL_HELPERS_CUSTOM(/obj/machinery/shower, 16, -5, 0, 0)
desc = "A sink used for washing one's hands and face."
anchored = TRUE
var/sink_flags = SINK_MOVEABLE
- new_attack_chain = TRUE
MAPPING_DIRECTIONAL_HELPERS_CUSTOM(/obj/structure/sink, 18, -4, 0, 0)
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 9177012a378..5a3c261d1a1 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -106,9 +106,10 @@
if(direction == dir && density)
return COMPONENT_ATOM_BLOCK_EXIT
-/obj/structure/windoor_assembly/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/windoor_assembly/item_interaction(mob/living/user, obj/item/W, list/modifiers)
//I really should have spread this out across more states but thin little windoors are hard to sprite.
add_fingerprint(user)
+ . = ITEM_INTERACT_COMPLETE
switch(state)
if(EMPTY_ASSEMBLY)
//Adding plasteel makes the assembly a secure windoor assembly. Step 2 (optional) complete.
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 22f2d6ffe88..2fdf19146a8 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -213,9 +213,10 @@
deconstruct(FALSE)
attacker.visible_message("[attacker] smashes through [src]!", "You smash through [src].", "You hear glass breaking.")
-/obj/structure/window/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
+/obj/structure/window/item_interaction(mob/living/user, obj/item/I, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
if(!can_be_reached(user))
- return 1 //skip the afterattack
+ return
add_fingerprint(user)
if(istype(I, /obj/item/stack/rods) && user.a_intent == INTENT_HELP)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index d28b16731bb..5e275530623 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -550,7 +550,7 @@
var/obj/item/stack/cable_coil/C = used
for(var/obj/structure/cable/LC in src)
if(LC.d1 == 0 || LC.d2 == 0)
- LC.attackby__legacy__attackchain(C, user)
+ LC.item_interaction(user, C)
return ITEM_INTERACT_COMPLETE
C.place_turf(src, user)
return ITEM_INTERACT_COMPLETE
@@ -559,7 +559,7 @@
if(R.loaded)
for(var/obj/structure/cable/LC in src)
if(LC.d1 == 0 || LC.d2 == 0)
- LC.attackby__legacy__attackchain(R, user)
+ LC.item_interaction(user, R)
return ITEM_INTERACT_COMPLETE
R.loaded.place_turf(src, user)
R.is_empty(user)
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index 50fd19bdadc..508819fde29 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -482,7 +482,7 @@
eater.say("Nom")
wither()
-/obj/structure/spacevine/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
+/obj/structure/spacevine/attacked_by(obj/item/I, mob/living/user)
var/damage_dealt = I.force
if(istype(I, /obj/item/scythe))
var/obj/item/scythe/S = I
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
index c24397bb2fb..f3c10dbcf64 100644
--- a/code/modules/hydroponics/beekeeping/beebox.dm
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -146,7 +146,8 @@
. += "there's no room for more honeycomb!"
-/obj/structure/beebox/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/beebox/item_interaction(mob/living/user, obj/item/I, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
if(istype(I, /obj/item/honey_frame))
var/obj/item/honey_frame/HF = I
if(length(honey_frames) < BEEBOX_MAX_FRAMES)
diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm
index 6f662730ea6..1147a39812e 100644
--- a/code/modules/hydroponics/fermenting_barrel.dm
+++ b/code/modules/hydroponics/fermenting_barrel.dm
@@ -38,22 +38,21 @@
qdel(G)
playsound(src, 'sound/effects/bubbles.ogg', 50, TRUE)
-/obj/structure/fermenting_barrel/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/fermenting_barrel/item_interaction(mob/living/user, obj/item/I, list/modifiers)
var/obj/item/food/grown/G = I
if(istype(G))
if(!G.can_distill)
to_chat(user, "You can't distill this into anything...")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
else if(!user.drop_item())
to_chat(user, "[G] is stuck to your hand!")
- return FALSE
+ return ITEM_INTERACT_COMPLETE
G.forceMove(src)
to_chat(user, "You place [G] into [src] to start the fermentation process.")
addtimer(CALLBACK(src, PROC_REF(makeWine), G), rand(80, 120) * speed_multiplier)
- else if(I.is_refillable())
- return FALSE // To refill via afterattack proc
- else
- return ..()
+ return ITEM_INTERACT_COMPLETE
+
+ return ..()
/obj/structure/fermenting_barrel/attack_hand(mob/user)
open = !open
diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm
index fd0e12b9cd6..c2e8397b803 100644
--- a/code/modules/hydroponics/grown/towercap.dm
+++ b/code/modules/hydroponics/grown/towercap.dm
@@ -129,7 +129,6 @@
var/light_strength = 6
light_color = "#ED9200"
anchored = TRUE
- new_attack_chain = TRUE
/obj/structure/lightable/proc/CheckOxygen()
var/turf/T = get_turf(src)
diff --git a/code/modules/library/library_equipment.dm b/code/modules/library/library_equipment.dm
index 935c91b656a..8a6e91ea7fc 100644
--- a/code/modules/library/library_equipment.dm
+++ b/code/modules/library/library_equipment.dm
@@ -39,13 +39,13 @@
I.forceMove(src)
update_icon(UPDATE_OVERLAYS)
-/obj/structure/bookcase/attackby__legacy__attackchain(obj/item/O, mob/user)
+/obj/structure/bookcase/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(is_type_in_list(O, allowed_books))
if(!user.drop_item())
- return
+ return ITEM_INTERACT_COMPLETE
O.forceMove(src)
update_icon(UPDATE_OVERLAYS)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
if(istype(O, /obj/item/storage/bag/books))
var/obj/item/storage/bag/books/B = O
for(var/obj/item/T in B.contents)
@@ -53,10 +53,10 @@
B.remove_from_storage(T, src)
to_chat(user, "You empty [O] into [src].")
update_icon(UPDATE_OVERLAYS)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
if(is_pen(O))
rename_interactive(user, O)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
return ..()
diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm
index aeb81165663..e5a505da8e0 100644
--- a/code/modules/mining/abandonedcrates.dm
+++ b/code/modules/mining/abandonedcrates.dm
@@ -39,11 +39,11 @@
else
return ..()
-/obj/structure/closet/crate/secure/loot/attackby__legacy__attackchain(obj/item/W, mob/user)
+/obj/structure/closet/crate/secure/loot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(locked)
if(istype(W, /obj/item/card/emag))
boom(user)
- return 1
+ return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/multitool))
to_chat(user, "DECA-CODE LOCK REPORT:")
if(attempts == 1)
@@ -67,7 +67,8 @@
++cows
to_chat(user, "Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions.")
- return 1
+ return ITEM_INTERACT_COMPLETE
+
return ..()
/obj/structure/closet/crate/secure/loot/emag_act(mob/user)
diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm
index e482243b6e9..b56c1aab579 100644
--- a/code/modules/mining/equipment/marker_beacons.dm
+++ b/code/modules/mining/equipment/marker_beacons.dm
@@ -125,7 +125,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
qdel(src)
-/obj/structure/marker_beacon/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/marker_beacon/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/stack/marker_beacon))
var/obj/item/stack/marker_beacon/M = I
to_chat(user, "You start picking [src] up...")
@@ -133,7 +133,8 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
M.add(1)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
qdel(src)
- return
+
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/marker_beacon/AltClick(mob/living/user)
@@ -154,11 +155,9 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
base_icon_state = "dockingmarker"
flags = NODECONSTRUCT
-/obj/structure/marker_beacon/dock_marker/update_icon_state()
- set_light(light_range, light_power, LIGHT_COLOR_BLUE)
-
-/obj/structure/marker_beacon/dock_marker/attackby__legacy__attackchain()
- return
+/obj/structure/marker_beacon/dock_marker/Initialize(mapload, set_color)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
/obj/structure/marker_beacon/dock_marker/attack_hand()
return
diff --git a/code/modules/mining/gravestones.dm b/code/modules/mining/gravestones.dm
index 816a5edc43f..c686f9d5d69 100644
--- a/code/modules/mining/gravestones.dm
+++ b/code/modules/mining/gravestones.dm
@@ -6,7 +6,6 @@
icon_state = "grave_basalt_open"
anchored = TRUE
layer = BELOW_OBJ_LAYER
- new_attack_chain = TRUE
/// What does the grave contain?
var/atom/buried
/// What does the headstone say?
diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm
index fb5b67dc397..6d9d74797bd 100644
--- a/code/modules/mining/lavaland/ash_flora.dm
+++ b/code/modules/mining/lavaland/ash_flora.dm
@@ -60,13 +60,15 @@
desc = initial(desc)
harvested = FALSE
-/obj/structure/flora/ash/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/flora/ash/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(!harvested && needs_sharp_harvest && W.sharp)
user.visible_message("[user] starts to harvest from [src] with [W].","You begin to harvest from [src] with [W].")
if(do_after(user, harvest_time, target = src))
harvest(user)
- else
- return ..()
+
+ return ITEM_INTERACT_COMPLETE
+
+ return ..()
/obj/structure/flora/ash/attack_hand(mob/user)
if(!harvested && !needs_sharp_harvest)
diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm
index 88b454e0037..b4ca1a1e92b 100644
--- a/code/modules/mining/satchel_ore_boxdm.dm
+++ b/code/modules/mining/satchel_ore_boxdm.dm
@@ -9,11 +9,11 @@
density = TRUE
pressure_resistance = 5 * ONE_ATMOSPHERE
-/obj/structure/ore_box/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/ore_box/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/stack/ore))
- if(!user.drop_item())
- return
- W.forceMove(src)
+ if(user.drop_item())
+ W.forceMove(src)
+ return ITEM_INTERACT_COMPLETE
else if(isstorage(W))
var/obj/item/storage/S = W
S.hide_from(user)
@@ -21,6 +21,7 @@
for(var/obj/item/stack/ore/O in S.contents)
S.remove_from_storage(O, src) //This will move the item to this item's contents
to_chat(user, "You empty the satchel into the box.")
+ return ITEM_INTERACT_COMPLETE
else
return ..()
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index 65a0c204701..f68b88dc320 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -764,12 +764,9 @@
cloth_golem = null
qdel(src)
-/obj/structure/cloth_pile/attackby__legacy__attackchain(obj/item/P, mob/living/carbon/human/user, params)
- . = ..()
-
- if(resistance_flags & ON_FIRE)
- return
-
- if(P.get_heat())
+/obj/structure/cloth_pile/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(!(resistance_flags & ON_FIRE) && used.get_heat())
visible_message("[src] bursts into flames!")
fire_act()
+ return ITEM_INTERACT_COMPLETE
+
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
index e902959a88e..9a8995b76ce 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
@@ -296,16 +296,15 @@ While using this makes the system rely on OnFire, it still gives options for tim
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild))
H.color = "#FF0000"
-/obj/structure/elite_tumor/attackby__legacy__attackchain(obj/item/attacking_item, mob/user, params)
- . = ..()
- if(istype(attacking_item, /obj/item/organ/internal/regenerative_core) && activity == TUMOR_INACTIVE && !boosted)
- var/obj/item/organ/internal/regenerative_core/core = attacking_item
+/obj/structure/elite_tumor/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/organ/internal/regenerative_core) && activity == TUMOR_INACTIVE && !boosted)
+ var/obj/item/organ/internal/regenerative_core/core = used
visible_message("As [user] drops the core into [src], [src] appears to swell.")
icon_state = "advanced_tumor"
boosted = TRUE
set_light(6)
qdel(core)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
/obj/structure/elite_tumor/examine(mob/user)
. = ..()
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index 59ef06398be..52bdf4bb76f 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -186,7 +186,8 @@
hud.screen_loc = UI_RHAND
else
hud.screen_loc = UI_LHAND
- assailant.client.screen += hud
+ if(assailant.client)
+ assailant.client.screen += hud
/obj/item/grab/process()
if(!confirm())
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index c62730cbde1..85ae2fd67b6 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -44,12 +44,12 @@
I.loc = src
-/obj/structure/filingcabinet/attackby__legacy__attackchain(obj/item/O, mob/user, params)
+/obj/structure/filingcabinet/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(insert(O, user))
- return
+ return ITEM_INTERACT_COMPLETE
if(user.a_intent != INTENT_HARM)
to_chat(user, "You can't put [O.name] in [src]!")
- return
+ return ITEM_INTERACT_COMPLETE
return ..()
/obj/structure/filingcabinet/wrench_act(mob/living/user, obj/item/I)
diff --git a/code/modules/power/cables/cable.dm b/code/modules/power/cables/cable.dm
index 2f878445e71..227deb40929 100644
--- a/code/modules/power/cables/cable.dm
+++ b/code/modules/power/cables/cable.dm
@@ -83,7 +83,8 @@ By design, d1 is the smallest direction and d2 is the highest
// - Cable coil : merge cables
// - Multitool : get the power currently passing through the cable
//
-/obj/structure/cable/attackby__legacy__attackchain(obj/item/W, mob/user)
+/obj/structure/cable/item_interaction(mob/living/user, obj/item/W, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
var/turf/T = get_turf(src)
if(T.transparent_floor || T.intact)
to_chat(user, "You can't interact with something that's under the floor!")
diff --git a/code/modules/power/engines/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/engines/singularity/particle_accelerator/particle_accelerator.dm
index c3f182a9d47..59336d0b51d 100644
--- a/code/modules/power/engines/singularity/particle_accelerator/particle_accelerator.dm
+++ b/code/modules/power/engines/singularity/particle_accelerator/particle_accelerator.dm
@@ -163,7 +163,7 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin
return 1
return 0
-/obj/structure/particle_accelerator/attackby__legacy__attackchain(obj/item/W, mob/user, params)
+/obj/structure/particle_accelerator/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(!iscoil(W))
return ..()
if(construction_state == ACCELERATOR_WRENCHED)
@@ -174,6 +174,7 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin
"You add some wires.")
construction_state = ACCELERATOR_WIRED
update_icon()
+ return ITEM_INTERACT_COMPLETE
/obj/structure/particle_accelerator/screwdriver_act(mob/user, obj/item/I)
if(construction_state != ACCELERATOR_WIRED && construction_state != ACCELERATOR_READY)
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index b0592986cd9..9766fc9411f 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -24,7 +24,7 @@
if(tank_volume && (damage_flag == BULLET || damage_flag == LASER))
boom(FALSE, TRUE)
-/obj/structure/reagent_dispensers/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/reagent_dispensers/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(I.is_refillable())
return FALSE //so we can refill them via their afterattack.
return ..()
@@ -176,11 +176,11 @@
lastrigger = null
overlays.Cut()
-/obj/structure/reagent_dispensers/fueltank/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/reagent_dispensers/fueltank/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/assembly_holder) && accepts_rig)
if(rig)
to_chat(user, "There is another device in the way.")
- return ..()
+ return ITEM_INTERACT_COMPLETE
user.visible_message("[user] begins rigging [I] to [src].", "You begin rigging [I] to [src]")
if(do_after(user, 20, target = src))
user.visible_message("[user] rigs [I] to [src].", "You rig [I] to [src].")
@@ -199,6 +199,7 @@
test.Shift(NORTH, 1)
test.Shift(EAST, 6)
overlays += test
+ return ITEM_INTERACT_COMPLETE
else
return ..()
@@ -299,8 +300,7 @@
/// If TRUE, prevents the player from inserting the disk again while it is currently exploding.
var/exploding = FALSE
-/obj/structure/reagent_dispensers/beerkeg/nuke/attackby__legacy__attackchain(obj/item/O, mob/user, params)
- . = ..()
+/obj/structure/reagent_dispensers/beerkeg/nuke/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(exploding)
return
if(!istype(O, /obj/item/disk/nuclear))
@@ -311,6 +311,7 @@
playsound(src, 'sound/machines/alarm.ogg', 100, FALSE, 0)
exploding = TRUE
addtimer(CALLBACK(src, PROC_REF(explode)), 13 SECONDS)
+ return ITEM_INTERACT_COMPLETE
/obj/structure/reagent_dispensers/beerkeg/nuke/proc/explode()
var/datum/reagents/R = new(100)
diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm
index 1877794ac40..6b56546b6f6 100644
--- a/code/modules/recycling/disposal-construction.dm
+++ b/code/modules/recycling/disposal-construction.dm
@@ -139,11 +139,11 @@
var/ispipe = is_pipe()
var/nicetype = get_nice_name()
var/turf/T = get_turf(src)
-
+
if(T.intact)
to_chat(user, "You can only attach the [nicetype] if the floor plating is removed.")
return
-
+
if(ispipe)
anchored = !anchored
level = anchored ? 1 : 2
@@ -184,7 +184,8 @@
nicetype = "sorting pipe"
return nicetype
-/obj/structure/disposalconstruct/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/disposalconstruct/item_interaction(mob/living/user, obj/item/I, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
var/nicetype = get_nice_name()
var/ispipe = is_pipe() // Indicates if we should change the level of this pipe
var/turf/T = get_turf(src)
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index 4e35c1efc60..88545327e74 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -1043,11 +1043,11 @@
//attack by item
//weldingtool: unfasten and convert to obj/disposalconstruct
-/obj/structure/disposalpipe/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/disposalpipe/item_interaction(mob/living/user, obj/item/used, list/modifiers)
var/turf/T = get_turf(src)
if(T.intact || T.transparent_floor)
to_chat(user, "You can't interact with something that's under the floor!")
- return // prevent interaction with T-scanner revealed pipes and pipes under glass
+ return ITEM_INTERACT_COMPLETE // prevent interaction with T-scanner revealed pipes and pipes under glass
add_fingerprint(user)
@@ -1221,9 +1221,9 @@
if(mapping_fail)
stack_trace("[src] mapped incorrectly at [x],[y],[z] - [mapping_fail]")
-/obj/structure/disposalpipe/sortjunction/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/disposalpipe/sortjunction/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(..())
- return
+ return ITEM_INTERACT_COMPLETE
if(istype(I, /obj/item/dest_tagger))
var/obj/item/dest_tagger/O = I
@@ -1244,6 +1244,7 @@
sort_type.Add(O.currTag)
to_chat(user, "Added [tag] to filter.")
update_appearance(UPDATE_NAME|UPDATE_DESC)
+ return ITEM_INTERACT_COMPLETE
/obj/structure/disposalpipe/sortjunction/update_name()
. = ..()
@@ -1423,18 +1424,18 @@
linked = D
D.linkedtrunk = src
- // Override attackby so we disallow trunkremoval when somethings ontop
-/obj/structure/disposalpipe/trunk/attackby__legacy__attackchain(obj/item/I, mob/user, params)
-
+/// Disallow trunkremoval when something's on top
+/obj/structure/disposalpipe/trunk/item_interaction(mob/living/user, obj/item/I, list/modifiers)
//Disposal bins or chutes
//Disposal constructors
var/obj/structure/disposalconstruct/C = locate() in src.loc
if(C && C.anchored)
- return
+ return ITEM_INTERACT_COMPLETE
var/turf/T = src.loc
if(T.intact || T.transparent_floor)
- return // prevent interaction with T-scanner revealed pipes
+ // prevent interaction with T-scanner revealed pipes
+ return ITEM_INTERACT_COMPLETE
src.add_fingerprint(user)
// would transfer to next pipe segment, but we are in a trunk
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index e6e61617921..101dceeab83 100644
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -35,7 +35,8 @@
qdel(src)
-/obj/structure/big_delivery/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
+/obj/structure/big_delivery/item_interaction(mob/living/user, obj/item/W, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/dest_tagger))
var/obj/item/dest_tagger/O = W
diff --git a/code/modules/ruins/lavalandruin_code/dead_ratvar.dm b/code/modules/ruins/lavalandruin_code/dead_ratvar.dm
index c67bd5df0b6..8941dc36fe3 100644
--- a/code/modules/ruins/lavalandruin_code/dead_ratvar.dm
+++ b/code/modules/ruins/lavalandruin_code/dead_ratvar.dm
@@ -92,7 +92,8 @@
return
default_unfasten_wrench(user, I, 10)
-/obj/structure/clockwork/wall_gear/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/obj/structure/clockwork/wall_gear/item_interaction(mob/living/user, obj/item/I, list/modifiers)
+ . = ITEM_INTERACT_COMPLETE
if(istype(I, /obj/item/stack/tile/brass))
var/obj/item/stack/tile/brass/W = I
if(W.get_amount() < 1)
@@ -122,7 +123,7 @@
qdel(src)
else
to_chat(user, "You need more brass to make a [anchored ? "false ":""]wall!")
- return 1
+ return
return ..()
/obj/structure/clockwork/wall_gear/deconstruct(disassembled = TRUE)
diff --git a/code/tests/_game_test_puppeteer.dm b/code/tests/_game_test_puppeteer.dm
index 05db0cbd286..130a6938158 100644
--- a/code/tests/_game_test_puppeteer.dm
+++ b/code/tests/_game_test_puppeteer.dm
@@ -48,6 +48,11 @@
origin_test.Fail("could not spawn obj [obj_type] near [src]")
+/datum/test_puppeteer/proc/spawn_fast_tool(item_type)
+ var/obj/item/fast_tool = spawn_obj_in_hand(item_type)
+ fast_tool.toolspeed = 0
+ return fast_tool
+
/datum/test_puppeteer/proc/use_item_in_hand()
var/obj/item/item = puppet.get_active_hand()
if(!item)
@@ -176,3 +181,6 @@
puppet.ClickOn(puppet)
puppet.next_click = world.time
puppet.next_move = world.time
+
+/datum/test_puppeteer/proc/drop_held_item()
+ puppet.drop_item_to_ground(puppet.get_active_hand())
diff --git a/code/tests/attack_chain/test_attack_chain_structures.dm b/code/tests/attack_chain/test_attack_chain_structures.dm
new file mode 100644
index 00000000000..0e41bfc85a3
--- /dev/null
+++ b/code/tests/attack_chain/test_attack_chain_structures.dm
@@ -0,0 +1,324 @@
+/datum/game_test/room_test/attack_chain_structures
+ testing_area_name = "test_attack_chain_structures.dmm"
+ var/list/structure_instances_by_type = list()
+
+/datum/game_test/room_test/attack_chain_structures/proc/teleport_to_first(datum/test_puppeteer/player, obj_type, dir=EAST)
+ if(length(structure_instances_by_type[obj_type]))
+ for(var/obj/object in structure_instances_by_type[obj_type])
+ if(!QDELETED(object))
+ player.puppet.forceMove(get_step(object, dir))
+ return object
+ TEST_FAIL("could not find [obj_type] to teleport puppet to")
+
+/datum/game_test/room_test/attack_chain_structures/New()
+ . = ..()
+ for(var/turf/T in available_turfs)
+ for(var/obj/structure/structure in T)
+ LAZYOR(structure_instances_by_type[structure.type], structure)
+
+/datum/game_test/room_test/attack_chain_structures/Run()
+ var/datum/test_puppeteer/player = new(src)
+ player.puppet.name = "Player"
+
+ player.puppet.mind.add_antag_datum(/datum/antagonist/cultist)
+ player.spawn_obj_in_hand(/obj/item/melee/cultblade/dagger)
+
+ var/forge = teleport_to_first(player, /obj/structure/cult/functional/forge)
+ player.click_on(forge)
+ TEST_ASSERT_LAST_CHATLOG(player, "You unsecure [forge] from the floor")
+ player.drop_held_item()
+
+ var/obj/structure/ai_core/core = teleport_to_first(player, /obj/structure/ai_core)
+ player.spawn_obj_in_hand(/obj/item/circuitboard/aicore)
+ player.click_on(core)
+ TEST_ASSERT_LAST_CHATLOG(player, "You place the circuit board inside the frame")
+
+ var/shell = teleport_to_first(player, /obj/structure/constructshell)
+ var/obj/item/soulstone/soulstone = player.spawn_obj_in_hand(/obj/item/soulstone)
+ soulstone.purified = TRUE
+ player.click_on(shell)
+ TEST_ASSERT_LAST_CHATLOG(player, "An overwhelming feeling of dread comes over you")
+ player.drop_held_item()
+ player.rejuvenate()
+
+ var/obj/structure/computerframe/frame = teleport_to_first(player, /obj/structure/computerframe)
+ var/obj/circuitboard = player.spawn_obj_in_hand(/obj/item/circuitboard/computer/sat_control)
+ player.click_on(frame)
+ TEST_ASSERT_LAST_CHATLOG(player, "You place [circuitboard] inside the computer frame")
+
+ var/barricade = teleport_to_first(player, /obj/structure/barricade/wooden)
+ player.spawn_obj_in_hand(/obj/item/stack/sheet/wood)
+ player.click_on(barricade)
+ TEST_ASSERT_LAST_CHATLOG(player, "You need at least five wooden planks to make a wall")
+ player.drop_held_item()
+
+ var/firelock_frame = teleport_to_first(player, /obj/structure/firelock_frame)
+ var/obj/item/firelock_electronics/electronics = player.spawn_fast_tool(/obj/item/firelock_electronics)
+ player.click_on(firelock_frame)
+ TEST_ASSERT_LAST_CHATLOG(player, "You insert and secure [electronics]")
+
+ var/machine_frame = teleport_to_first(player, /obj/structure/machine_frame)
+ player.spawn_fast_tool(/obj/item/stack/cable_coil{amount = 5})
+ player.click_on(machine_frame)
+ TEST_ASSERT_LAST_CHATLOG(player, "You add cables to the frame.")
+
+ var/obj/structure/largecrate/large_crate = teleport_to_first(player, /obj/structure/largecrate)
+ large_crate.manifest = new /obj/item/paper/manifest(null)
+ player.spawn_obj_in_hand(/obj/item/paper)
+ player.click_on(large_crate)
+ TEST_ASSERT_LAST_CHATLOG(player, "You tear the manifest off of the crate")
+ player.drop_held_item()
+
+ var/obj/structure/displaycase/displaycase = teleport_to_first(player, /obj/structure/displaycase)
+ var/obj/id_card = player.spawn_obj_in_hand(/obj/item/card/id/assistant)
+ player.click_on(displaycase)
+ TEST_ASSERT_LAST_CHATLOG(player, "You use [id_card] to open [displaycase]")
+ player.put_away(id_card)
+ var/obj/item/toy/crayon/crayon = player.spawn_obj_in_hand(/obj/item/toy/crayon)
+ player.click_on(displaycase)
+ TEST_ASSERT_LAST_CHATLOG(player, "You put [crayon] on display")
+ player.retrieve(id_card)
+ player.click_on(displaycase)
+ TEST_ASSERT_LAST_CHATLOG(player, "You use [id_card] to close [displaycase]")
+ player.put_away(id_card)
+ var/obj/baton = player.spawn_obj_in_hand(/obj/item/melee/baton/loaded)
+ player.set_intent(INTENT_HARM)
+ player.click_on(displaycase)
+ TEST_ASSERT_LAST_CHATLOG(player, "You hit [displaycase] with [baton]")
+ qdel(baton)
+
+ var/obj/assembly = teleport_to_first(player, /obj/structure/door_assembly)
+ player.spawn_fast_tool(/obj/item/wrench)
+ player.click_on(assembly)
+ TEST_ASSERT_LAST_CHATLOG(player, "You secure [assembly].")
+ player.drop_held_item()
+ player.spawn_fast_tool(/obj/item/stack/cable_coil)
+ player.click_on(assembly)
+ TEST_ASSERT_LAST_CHATLOG(player, "You wire the airlock assembly.")
+ player.drop_held_item()
+
+ var/obj/girder = teleport_to_first(player, /obj/structure/girder/cult)
+ player.puppet.mind.add_antag_datum(/datum/antagonist/cultist)
+ player.spawn_obj_in_hand(/obj/item/melee/cultblade/dagger)
+ player.click_on(girder)
+ TEST_ASSERT_LAST_CHATLOG(player, "You demolish [girder].")
+ player.drop_held_item()
+
+ girder = teleport_to_first(player, /obj/structure/girder)
+ player.spawn_fast_tool(/obj/item/stack/sheet/metal{amount = 2})
+ player.click_on(girder)
+ TEST_ASSERT_LAST_CHATLOG(player, "You add the plating.")
+
+ girder = teleport_to_first(player, /obj/structure/girder)
+ player.spawn_fast_tool(/obj/item/gun/energy/plasmacutter)
+ player.click_on(girder)
+ TEST_ASSERT_LAST_CHATLOG(player, "You slice apart the girder.")
+ player.drop_held_item()
+
+ var/obj/structure/guillotine/guillotine = teleport_to_first(player, /obj/structure/guillotine)
+ guillotine.blade_sharpness -= 1
+ player.spawn_fast_tool(/obj/item/whetstone)
+ player.click_on(guillotine)
+ TEST_ASSERT_LAST_CHATLOG(player, "You sharpen the large blade of [guillotine]")
+ player.drop_held_item()
+
+ var/obj/weldingtool = player.spawn_fast_tool(/obj/item/weldingtool)
+ player.use_item_in_hand()
+ player.set_intent(INTENT_HARM)
+ player.click_on(guillotine)
+ TEST_ASSERT_LAST_CHATLOG(player, "You slice clean through the guillotine!")
+ player.put_away(weldingtool)
+ player.set_intent(INTENT_HELP)
+
+ var/obj/structure/table_frame/table_frame = teleport_to_first(player, /obj/structure/table_frame)
+ table_frame.construction_time = 0
+ player.spawn_obj_in_hand(/obj/item/stack/sheet/metal)
+ player.click_on(table_frame)
+ TEST_ASSERT_LAST_CHATLOG(player, "You start adding the metal to [table_frame]")
+ player.spawn_fast_tool(/obj/item/wrench)
+ var/table = player.find_nearby(/obj/structure/table)
+ player.click_on(table)
+ TEST_ASSERT_LAST_CHATLOG(player, "You dismantle [table]")
+ player.drop_held_item()
+
+ var/obj/inflatable = teleport_to_first(player, /obj/structure/inflatable)
+ player.spawn_obj_in_hand(/obj/item/kitchen/knife)
+ player.click_on(inflatable)
+ TEST_ASSERT_LAST_CHATLOG(player, "[inflatable] rapidly deflates!")
+ player.drop_held_item()
+
+ var/obj/kitchenspike_frame = teleport_to_first(player, /obj/structure/kitchenspike_frame)
+ player.spawn_obj_in_hand(/obj/item/stack/rods/ten)
+ player.click_on(kitchenspike_frame)
+ TEST_ASSERT_LAST_CHATLOG(player, "You add spikes to the frame.")
+ player.drop_held_item()
+
+ var/obj/structure/kitchenspike/spike = teleport_to_first(player, /obj/structure/kitchenspike)
+ spike.impale_time = 0
+ var/mob/living/pig = player.spawn_mob_nearby(/mob/living/basic/pig)
+ pig.grabbedby(player.puppet)
+ player.click_on(spike)
+ TEST_ASSERT_LAST_CHATLOG(player, "[player.puppet] slams [pig] onto the meat spike!")
+
+ var/obj/structure/lattice/lattice = teleport_to_first(player, /obj/structure/lattice)
+ var/turf/space_turf = get_turf(lattice)
+ player.spawn_fast_tool(/obj/item/wirecutters)
+ player.click_on(lattice)
+ TEST_ASSERT_LAST_CHATLOG(player, "Slicing [lattice.name] joints...")
+ player.drop_held_item()
+ player.spawn_fast_tool(/obj/item/stack/rods/fifty)
+ player.click_on(space_turf)
+ TEST_ASSERT_LAST_CHATLOG(player, "Constructing support lattice...")
+ TEST_ASSERT_NOTNULL(locate(/obj/structure/lattice) in space_turf, "Could not find constructed lattice")
+ player.drop_held_item()
+
+ var/obj/structure/loom/loom = teleport_to_first(player, /obj/structure/loom)
+ loom.disassemble_speed = 0
+ var/obj/item/stack/sheet/cotton/cotton = player.spawn_obj_in_hand(/obj/item/stack/sheet/cotton)
+ cotton.amount = 4
+ cotton.pull_effort = 0
+ player.click_on(loom)
+ TEST_ASSERT_LAST_CHATLOG(player, "You weave [cotton] into a workable fabric.")
+ player.spawn_fast_tool(/obj/item/crowbar)
+ player.click_on(loom)
+ TEST_ASSERT_LAST_CHATLOG(player, "You dismantle [loom]")
+ player.drop_held_item()
+
+ var/obj/structure/mineral_door/iron/door = teleport_to_first(player, /obj/structure/mineral_door/iron)
+ player.spawn_fast_tool(/obj/item/pickaxe)
+ player.click_on(door)
+ TEST_ASSERT_LAST_CHATLOG(player, "You finished digging.")
+ player.drop_held_item()
+
+ var/obj/mirror = teleport_to_first(player, /obj/structure/mirror/magic)
+ var/starting_integrity = mirror.obj_integrity
+ player.spawn_fast_tool(/obj/item/weldingtool)
+ player.set_intent(INTENT_HARM)
+ player.click_on(mirror)
+ TEST_ASSERT_EQUAL(mirror.obj_integrity, starting_integrity, "magic mirror took damage")
+ player.drop_held_item()
+ player.set_intent(INTENT_HELP)
+
+ var/obj/noticeboard = teleport_to_first(player, /obj/structure/noticeboard)
+ player.spawn_obj_in_hand(/obj/item/paper)
+ player.click_on(noticeboard)
+ TEST_ASSERT_LAST_CHATLOG(player, "You pin the paper to the noticeboard.")
+
+ var/obj/structure/reflector/reflector = teleport_to_first(player, /obj/structure/reflector)
+ var/turf/T = get_turf(reflector)
+ player.spawn_fast_tool(/obj/item/stack/sheet/glass/fifty)
+ player.click_on(reflector)
+ // no chat messages for this construction apparently
+ TEST_ASSERT_NOTNULL(locate(/obj/structure/reflector/single) in T, "could not find constructed reflector")
+ player.drop_held_item()
+
+ var/obj/structure/safe/safe = teleport_to_first(player, /obj/structure/safe)
+ safe.open = TRUE
+ var/obj/disk = player.spawn_obj_in_hand(/obj/item/disk/design_disk)
+ player.click_on(safe)
+ TEST_ASSERT_LAST_CHATLOG(player, "You put [disk] in [safe].")
+ safe.open = FALSE
+ var/obj/gun = player.spawn_obj_in_hand(/obj/item/gun/energy/laser)
+ player.click_on(safe)
+ TEST_ASSERT_LAST_CHATLOG(player, "You can't put [gun] into the safe while it is closed!")
+ player.drop_held_item()
+
+ var/obj/structure/shelf/shelf = teleport_to_first(player, /obj/structure/shelf)
+ var/obj/box = player.spawn_obj_in_hand(/obj/item/storage/box/beakers)
+ player.click_on(shelf, "icon-x=8;icon-y=10")
+ TEST_ASSERT_LAST_CHATLOG(player, "You place [box] on [shelf].")
+ var/obj/wrench = player.spawn_fast_tool(/obj/item/wrench)
+ player.click_on(shelf, "icon-x=24;icon-y=10")
+ TEST_ASSERT_LAST_CHATLOG(player, "You place [wrench] on [shelf].")
+ player.spawn_fast_tool(/obj/item/wrench)
+ player.set_intent(INTENT_HARM)
+ player.click_on(shelf)
+ TEST_ASSERT_LAST_CHATLOG(player, "You disassemble [shelf].")
+ player.drop_held_item()
+
+ var/obj/structure/statue/hop_statue = teleport_to_first(player, /obj/structure/statue/gold/hop)
+ player.spawn_fast_tool(/obj/item/gun/energy/plasmacutter)
+ player.click_on(hop_statue)
+ TEST_ASSERT_LAST_CHATLOG(player, "You slice apart [hop_statue].")
+ player.drop_held_item()
+
+ var/obj/structure/snowman/built/snowman = teleport_to_first(player, /obj/structure/snowman/built)
+ var/old_integrity = snowman.obj_integrity
+ player.spawn_fast_tool(/obj/item/weldingtool)
+ player.set_intent(INTENT_HARM)
+ player.click_on(snowman)
+ TEST_ASSERT_NOTEQUAL(snowman.obj_integrity, old_integrity, "snowman didn't take damage")
+ player.drop_held_item()
+ player.spawn_obj_in_hand(/obj/item/snowball)
+ player.set_intent(INTENT_HELP)
+ player.click_on(snowman)
+ TEST_ASSERT_LAST_CHATLOG(player, "You patch some of the damage on [snowman]")
+
+ var/obj/structure/bed/roller/roller_bed = teleport_to_first(player, /obj/structure/bed/roller)
+ player.spawn_obj_in_hand(/obj/item/roller_holder)
+ player.click_on(roller_bed)
+ TEST_ASSERT_LAST_CHATLOG(player, "You collapse \the [roller_bed].")
+ player.drop_held_item()
+
+ var/obj/structure/big_delivery/delivery = teleport_to_first(player, /obj/structure/big_delivery)
+ var/obj/item/dest_tagger/tagger = player.spawn_obj_in_hand(/obj/item/dest_tagger)
+ tagger.currTag = 2
+ player.click_on(delivery)
+ TEST_ASSERT_LAST_CHATLOG(player, "*CARGO BAY*")
+ player.drop_held_item()
+
+ var/obj/structure/windoor_assembly/windoor_assembly = teleport_to_first(player, /obj/structure/windoor_assembly)
+ player.spawn_fast_tool(/obj/item/wrench)
+ player.click_on(windoor_assembly)
+ TEST_ASSERT_LAST_CHATLOG(player, "You secure the windoor assembly.")
+ player.drop_held_item()
+ player.spawn_fast_tool(/obj/item/stack/cable_coil)
+ player.click_on(windoor_assembly)
+ TEST_ASSERT_LAST_CHATLOG(player, "You wire the windoor.")
+ player.drop_held_item()
+
+ var/obj/crate = teleport_to_first(player, /obj/structure/closet/crate/secure/loot)
+ player.spawn_fast_tool(/obj/item/multitool)
+ player.click_on(crate)
+ TEST_ASSERT_LAST_CHATLOG(player, "Anti-Tamper Bomb will activate after 10 failed access attempts")
+ player.drop_held_item()
+
+ var/obj/structure/flora/ash/ashflora = teleport_to_first(player, /obj/structure/flora/ash)
+ ashflora.harvest_time = 0
+ ashflora.harvest_amount_high = 1 // so we always get the same chat message
+ player.spawn_fast_tool(/obj/item/kitchen/knife)
+ player.click_on(ashflora)
+ TEST_ASSERT_LAST_CHATLOG(player, "You pick a mushroom, but fail to collect many shavings from its cap.")
+ player.drop_held_item()
+
+ var/obj/orebox = teleport_to_first(player, /obj/structure/ore_box)
+ var/obj/item/storage/ore_bag = player.spawn_fast_tool(/obj/item/storage/bag/ore)
+ var/obj/item/stack/ore/iron/iron_ore = new(player.puppet.loc)
+ iron_ore.amount = 10
+ ore_bag.handle_item_insertion(iron_ore)
+ player.click_on(orebox)
+ TEST_ASSERT_LAST_CHATLOG(player, "You empty the satchel into the box.")
+ player.drop_held_item()
+
+ var/obj/filing_cabinet = teleport_to_first(player, /obj/structure/filingcabinet)
+ var/obj/paper = player.spawn_fast_tool(/obj/item/paper)
+ player.click_on(filing_cabinet)
+ TEST_ASSERT_LAST_CHATLOG(player, "You put [paper.name] in [filing_cabinet].")
+
+ var/obj/cable = teleport_to_first(player, /obj/structure/cable, dir = EAST)
+ player.spawn_fast_tool(/obj/item/stack/cable_coil/ten)
+ T = get_turf(cable)
+ TEST_ASSERT_EQUAL(length(T.contents), 1, "couldn't find one cable on tile")
+ player.click_on(get_turf(cable))
+ TEST_ASSERT_EQUAL(length(T.contents), 2, "didn't add cable to tile")
+ player.drop_held_item()
+
+ var/obj/structure/fermenting_barrel/barrel = teleport_to_first(player, /obj/structure/fermenting_barrel)
+ var/obj/item/reagent_containers/glass/bucket/bucket = player.spawn_obj_in_hand(/obj/item/reagent_containers/glass/bucket)
+ barrel.reagents.add_reagent("beer", 300)
+ player.click_on(barrel)
+ TEST_ASSERT_LAST_CHATLOG(player, "You fill [bucket] with 20 units of the contents of [barrel]")
+
+ var/obj/water_cooler = teleport_to_first(player, /obj/structure/reagent_dispensers/water_cooler)
+ player.click_on(water_cooler)
+ TEST_ASSERT_LAST_CHATLOG(player, "You fill [bucket] with 20 units of the contents of [water_cooler]")
diff --git a/code/tests/game_tests.dm b/code/tests/game_tests.dm
index 68b7879a366..464fa77b413 100644
--- a/code/tests/game_tests.dm
+++ b/code/tests/game_tests.dm
@@ -13,6 +13,8 @@
#include "attack_chain\test_attack_chain_borgs.dm"
#include "attack_chain\test_attack_chain_cult_dagger.dm"
#include "attack_chain\test_attack_chain_machinery.dm"
+#include "attack_chain\test_attack_chain_structures.dm"
+#include "attack_chain\test_attack_chain_stunbaton.dm"
#include "attack_chain\test_attack_chain_mobs.dm"
#include "attack_chain\test_attack_chain_reagent_containers.dm"
#include "attack_chain\test_attack_chain_stunbaton.dm"
diff --git a/tools/ci/check_legacy_attack_chain.py b/tools/ci/check_legacy_attack_chain.py
index be18a0a502e..b6d6818725c 100644
--- a/tools/ci/check_legacy_attack_chain.py
+++ b/tools/ci/check_legacy_attack_chain.py
@@ -37,10 +37,10 @@ class AttackChainCall:
def make_error_from_procdecl(proc_decl: ProcDecl, msg) -> str:
if os.getenv("GITHUB_ACTIONS") == "true":
- return f"::error file={proc_decl.source_info.file_path},line={proc_decl.source_info.line},title=Attack Chain::{proc_decl.source_info.file_path}:{proc_decl.source_info.line}: {RED}{msg}{NC}"
+ return f"::error file={proc_decl.source_loc.file_path},line={proc_decl.source_loc.line},title=Attack Chain::{proc_decl.source_loc.file_path}:{proc_decl.source_loc.line}: {RED}{msg}{NC}"
else:
- return f"{proc_decl.source_info.file_path}:{proc_decl.source_info.line}: {RED}{msg}{NC}"
+ return f"{proc_decl.source_loc.file_path}:{proc_decl.source_loc.line}: {RED}{msg}{NC}"
# Walker for determining if a proc contains any calls to a legacy attack chain
@@ -167,6 +167,9 @@ if __name__ == "__main__":
dme = DME.from_file("paradise.dme", parse_procs=True)
for pth in dme.subtypesof("/"):
+ if pth in IGNORED_TYPES:
+ continue
+
td = dme.types[pth]
if any(
[