diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 92f0da413b4..6d91ffdc969 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1013,7 +1013,28 @@ Returns 1 if the chain up to the area contains the given typepath
copied_objects += newmobs
for(var/V in T.vars)
- if(!(V in list("type", "loc", "locs", "vars", "parent", "parent_type", "verbs", "ckey", "key", "x", "y", "z", "destination_z", "destination_x", "destination_y", "contents", "luminosity", "group")))
+ if(!(V in list(
+ "ckey",
+ "comp_lookup",
+ "contents",
+ "destination_x",
+ "destination_y",
+ "destination_z",
+ "group",
+ "key",
+ "loc",
+ "locs",
+ "luminosity",
+ "parent_type",
+ "parent",
+ "signal_procs",
+ "type",
+ "vars",
+ "verbs",
+ "x",
+ "y",
+ "z",
+ )))
X.vars[V] = T.vars[V]
to_update += X
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index 6628f3577fd..5794a99269b 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -228,6 +228,10 @@
thermal_conductivity = 0
icon_state = "plating"
+/turf/simulated/floor/holofloor/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
+
/turf/simulated/floor/holofloor/carpet
name = "carpet"
icon = 'icons/turf/floors/carpet.dmi'
@@ -266,10 +270,6 @@
pixel_y = -9
layer = ABOVE_OPEN_TURF_LAYER
-/turf/simulated/floor/holofloor/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
- return
- // HOLOFLOOR DOES NOT GIVE A FUCK
-
/turf/simulated/floor/holofloor/space
name = "\proper space"
icon = 'icons/turf/space.dmi'
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index b92d65247ad..5ba070de0e8 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -38,8 +38,9 @@
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.attackby__legacy__attackchain(C, user) //hand this off to the turf instead (for building plating, catwalks, etc)
+ return T.attack_by(C, user, params)
/obj/structure/lattice/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index e0864966cd6..a8165ed0882 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -156,19 +156,16 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
W.update_icon()
return W
-/turf/simulated/floor/attackby__legacy__attackchain(obj/item/C as obj, mob/user as mob, params)
- if(!C || !user)
- return TRUE
+/turf/simulated/floor/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(..() || QDELETED(used) || QDELETED(user))
+ return ITEM_INTERACT_COMPLETE
- if(..())
- return TRUE
+ if((intact || transparent_floor) && istype(used, /obj/item/stack/tile))
+ try_replace_tile(used, user, modifiers)
+ return ITEM_INTERACT_COMPLETE
- if((intact || transparent_floor) && istype(C, /obj/item/stack/tile))
- try_replace_tile(C, user, params)
- return TRUE
-
- if(istype(C, /obj/item/pipe))
- var/obj/item/pipe/P = C
+ if(istype(used, /obj/item/pipe))
+ var/obj/item/pipe/P = used
if(P.pipe_type != -1) // ANY PIPE
user.visible_message( \
"[user] starts sliding [P] along \the [src].", \
@@ -191,8 +188,7 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
P.y = src.y
P.z = src.z
P.forceMove(src)
- return TRUE
- return FALSE
+ return ITEM_INTERACT_COMPLETE
/turf/simulated/floor/crowbar_act(mob/user, obj/item/I)
if(!intact)
@@ -211,7 +207,7 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
var/turf/simulated/floor/plating/P = pry_tile(thing, user, TRUE)
if(!istype(P))
return
- P.attackby__legacy__attackchain(T, user, params)
+ P.item_interaction(user, T, params)
/turf/simulated/floor/proc/pry_tile(obj/item/C, mob/user, silent = FALSE)
if(!silent)
diff --git a/code/game/turfs/simulated/floor/asteroid_floors.dm b/code/game/turfs/simulated/floor/asteroid_floors.dm
index 6f547b8d070..4d093eaf171 100644
--- a/code/game/turfs/simulated/floor/asteroid_floors.dm
+++ b/code/game/turfs/simulated/floor/asteroid_floors.dm
@@ -57,7 +57,7 @@
if(1)
getDug()
-/turf/simulated/floor/plating/asteroid/proc/attempt_ore_pickup(obj/item/storage/bag/ore/S, mob/user, params)
+/turf/simulated/floor/plating/asteroid/proc/attempt_ore_pickup(obj/item/storage/bag/ore/S, mob/user)
if(!istype(S))
return
@@ -66,12 +66,11 @@
O.attackby__legacy__attackchain(S, user)
return
-/turf/simulated/floor/plating/asteroid/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- //note that this proc does not call ..()
- if(!I|| !user)
- return FALSE
+/turf/simulated/floor/plating/asteroid/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(QDELETED(user)|| QDELETED(used))
+ return ITEM_INTERACT_COMPLETE
- if((istype(I, /obj/item/shovel) || istype(I, /obj/item/pickaxe)))
+ if((istype(used, /obj/item/shovel) || istype(used, /obj/item/pickaxe)))
if(!can_dig(user))
return TRUE
@@ -81,19 +80,19 @@
to_chat(user, "You start digging...")
- playsound(src, I.usesound, 50, TRUE)
- if(do_after(user, 40 * I.toolspeed, target = src))
+ playsound(src, used.usesound, 50, TRUE)
+ if(do_after(user, 40 * used.toolspeed, target = src))
if(!can_dig(user))
return TRUE
to_chat(user, "You dig a hole.")
getDug()
return TRUE
- else if(istype(I, /obj/item/storage/bag/ore))
- attempt_ore_pickup(I, user, params)
+ else if(istype(used, /obj/item/storage/bag/ore))
+ attempt_ore_pickup(used, user)
- else if(istype(I, /obj/item/stack/tile))
- var/obj/item/stack/tile/Z = I
+ else if(istype(used, /obj/item/stack/tile))
+ var/obj/item/stack/tile/Z = used
if(!Z.use(1))
return
if(istype(Z, /obj/item/stack/tile/plasteel)) // Turn asteroid floors into plating by default
diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm
index 5202acf5b66..a4d2da39fad 100644
--- a/code/game/turfs/simulated/floor/chasm.dm
+++ b/code/game/turfs/simulated/floor/chasm.dm
@@ -62,9 +62,11 @@
underlay_appearance.icon_state = "basalt"
return TRUE
-/turf/simulated/floor/chasm/attackby__legacy__attackchain(obj/item/C, mob/user, params, area/area_restriction)
- ..()
- if(istype(C, /obj/item/stack/rods))
+/turf/simulated/floor/chasm/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(..())
+ return ITEM_INTERACT_COMPLETE
+
+ if(istype(used, /obj/item/stack/rods))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(!L)
var/obj/item/inactive = user.get_inactive_hand()
@@ -77,19 +79,21 @@
if(!inactive || inactive.tool_behaviour != TOOL_SCREWDRIVER)
to_chat(user, "You need to hold a screwdriver in your other hand to secure this lattice.")
- return
- var/obj/item/stack/rods/R = C
+ return ITEM_INTERACT_COMPLETE
+ var/obj/item/stack/rods/R = used
if(R.use(1))
to_chat(user, "You construct a lattice.")
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
ReplaceWithLattice()
else
to_chat(user, "You need one rod to build a lattice.")
- return
- if(istype(C, /obj/item/stack/tile/plasteel))
+
+ return ITEM_INTERACT_COMPLETE
+
+ if(istype(used, /obj/item/stack/tile/plasteel))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
- var/obj/item/stack/tile/plasteel/S = C
+ var/obj/item/stack/tile/plasteel/S = used
if(S.use(1))
qdel(L)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
@@ -100,6 +104,8 @@
else
to_chat(user, "The plating is going to need some support! Place metal rods first.")
+ return ITEM_INTERACT_COMPLETE
+
/turf/simulated/floor/chasm/is_safe()
if(find_safeties() && ..())
return TRUE
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index 617bbd6092c..9d586666558 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -83,13 +83,12 @@
/turf/simulated/floor/grass/get_broken_states()
return list("damaged")
-/turf/simulated/floor/grass/attackby__legacy__attackchain(obj/item/C, mob/user, params)
- if(..())
- return
- if(istype(C, /obj/item/shovel))
+/turf/simulated/floor/grass/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/shovel))
to_chat(user, "You shovel the grass.")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
remove_tile()
+ return ITEM_INTERACT_COMPLETE
/turf/simulated/floor/grass/jungle
name = "jungle grass"
diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm
index 02d7a526c23..74f4142ef5a 100644
--- a/code/game/turfs/simulated/floor/indestructible.dm
+++ b/code/game/turfs/simulated/floor/indestructible.dm
@@ -1,5 +1,9 @@
/turf/simulated/floor/indestructible
+/turf/simulated/floor/indestructible/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
+
/turf/simulated/floor/indestructible/ex_act(severity)
return
@@ -18,9 +22,6 @@
/turf/simulated/floor/indestructible/burn_down()
return
-/turf/simulated/floor/indestructible/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- return
-
/turf/simulated/floor/indestructible/attack_hand(mob/user)
return
diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm
index 4c139cc7ded..f480fbecb7c 100644
--- a/code/game/turfs/simulated/floor/lava.dm
+++ b/code/game/turfs/simulated/floor/lava.dm
@@ -118,34 +118,38 @@
L.adjust_fire_stacks(20)
L.IgniteMob()
-
-/turf/simulated/floor/lava/attackby__legacy__attackchain(obj/item/C, mob/user, params) //Lava isn't a good foundation to build on
- if(istype(C, /obj/item/stack/rods/lava))
- var/obj/item/stack/rods/lava/R = C
+/// Lava isn't a good foundation to build on.
+/turf/simulated/floor/lava/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/stack/rods/lava))
+ var/obj/item/stack/rods/lava/R = used
var/obj/structure/lattice/lava/H = locate(/obj/structure/lattice/lava, src)
if(H)
to_chat(user, "There is already a lattice here!")
- return
+ return ITEM_INTERACT_COMPLETE
if(R.use(1))
to_chat(user, "You construct a lattice.")
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
new /obj/structure/lattice/lava(locate(x, y, z))
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You need one rod to build a heatproof lattice.")
- return
- if(istype(C, /obj/item/stack/tile/plasteel))
+ return ITEM_INTERACT_COMPLETE
+
+ if(istype(used, /obj/item/stack/tile/plasteel))
var/obj/structure/lattice/L = locate(/obj/structure/lattice/lava, src)
if(!L)
to_chat(user, "The plating is going to need some support! Place metal rods first.")
- return
- var/obj/item/stack/tile/plasteel/S = C
+ return ITEM_INTERACT_COMPLETE
+ var/obj/item/stack/tile/plasteel/S = used
if(S.use(1))
qdel(L)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
to_chat(user, "You build a floor.")
ChangeTurf(/turf/simulated/floor/plating, keep_icon = FALSE)
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You need one floor tile to build a floor!")
+ return ITEM_INTERACT_COMPLETE
/turf/simulated/floor/lava/screwdriver_act()
return
@@ -183,13 +187,15 @@
. = ..()
. += "Some liquid plasma could probably be scooped up with a container."
-/turf/simulated/floor/lava/lava_land_surface/plasma/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- if(!I.is_open_container())
+/turf/simulated/floor/lava/lava_land_surface/plasma/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(!used.is_open_container())
return ..()
- if(!I.reagents.add_reagent("plasma", 10))
- to_chat(user, "[I] is full.")
- return
- to_chat(user, "You scoop out some plasma from the [src] using [I].")
+ if(!used.reagents.add_reagent("plasma", 10))
+ to_chat(user, "[used] is full.")
+ return ITEM_INTERACT_COMPLETE
+
+ to_chat(user, "You scoop out some plasma from the [src] using [used].")
+ return ITEM_INTERACT_COMPLETE
/turf/simulated/floor/lava/lava_land_surface/plasma/burn_stuff(AM)
. = FALSE
diff --git a/code/game/turfs/simulated/floor/mineral_floors.dm b/code/game/turfs/simulated/floor/mineral_floors.dm
index d3ffe5a854c..c7d99f19ddc 100644
--- a/code/game/turfs/simulated/floor/mineral_floors.dm
+++ b/code/game/turfs/simulated/floor/mineral_floors.dm
@@ -34,14 +34,16 @@
if(exposed_temperature > 300)
PlasmaBurn()
-/turf/simulated/floor/mineral/plasma/attackby__legacy__attackchain(obj/item/W, mob/user, params)
- if(W.get_heat() > 300)//If the temperature of the object is over 300, then ignite
+/turf/simulated/floor/mineral/plasma/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
+ if(attacking.get_heat() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma flooring was ignited by [key_name_admin(user)]([ADMIN_QUE(user,"?")]) ([ADMIN_FLW(user,"FLW")]) in ([x],[y],[z] - JMP)",0,1)
log_game("Plasma flooring was ignited by [key_name(user)] in ([x],[y],[z])")
investigate_log("was ignited by [key_name(user)]","atmos")
- ignite(W.get_heat())
- return
- ..()
+ ignite(attacking.get_heat())
+ return FINISH_ATTACK
/turf/simulated/floor/mineral/plasma/welder_act(mob/user, obj/item/I)
if(I.use_tool(src, user, volume = I.tool_volume))
@@ -174,10 +176,11 @@
if(istype(M))
squeek()
-/turf/simulated/floor/mineral/bananium/attackby__legacy__attackchain(obj/item/W, mob/user, params)
- .=..()
- if(!.)
- honk()
+/turf/simulated/floor/mineral/bananium/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
+ honk()
/turf/simulated/floor/mineral/bananium/attack_hand(mob/user)
.=..()
@@ -250,10 +253,11 @@
if(istype(AM))
radiate()
-/turf/simulated/floor/mineral/uranium/attackby__legacy__attackchain(obj/item/W, mob/user, params)
- .=..()
- if(!.)
- radiate()
+/turf/simulated/floor/mineral/uranium/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
+ radiate()
/turf/simulated/floor/mineral/uranium/attack_hand(mob/user)
.=..()
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 820d5bc0eb7..3ddc3948d46 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -48,73 +48,70 @@
if(unfastened)
. += "It has been unfastened."
-/turf/simulated/floor/plating/attackby__legacy__attackchain(obj/item/C, mob/user, params)
- if(..())
- return TRUE
-
- if(istype(C, /obj/item/stack/rods))
+/turf/simulated/floor/plating/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/stack/rods))
if(broken || burnt)
to_chat(user, "Repair the plating first!")
- return TRUE
- var/obj/item/stack/rods/R = C
+ return ITEM_INTERACT_COMPLETE
+ var/obj/item/stack/rods/R = used
if(R.get_amount() < 2)
to_chat(user, "You need two rods to make a reinforced floor!")
- return TRUE
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You begin reinforcing the floor...")
- if(do_after(user, 30 * C.toolspeed, target = src))
+ if(do_after(user, 30 * used.toolspeed, target = src))
if(R.get_amount() >= 2 && !istype(src, /turf/simulated/floor/engine))
ChangeTurf(/turf/simulated/floor/engine)
- playsound(src, C.usesound, 80, 1)
+ playsound(src, used.usesound, 80, 1)
R.use(2)
to_chat(user, "You reinforce the floor.")
- return TRUE
+ return ITEM_INTERACT_COMPLETE
- else if(istype(C, /obj/item/stack/tile))
+ else if(istype(used, /obj/item/stack/tile))
if(!broken && !burnt)
- var/obj/item/stack/tile/W = C
+ var/obj/item/stack/tile/W = used
if(!W.use(1))
- return
+ return ITEM_INTERACT_COMPLETE
ChangeTurf(W.turf_type)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "This section is too damaged to support a tile! Use a welder to fix the damage.")
- return TRUE
-
- else if(is_glass_sheet(C))
+ return ITEM_INTERACT_COMPLETE
+ else if(is_glass_sheet(used))
if(broken || burnt)
to_chat(user, "Repair the plating first!")
- return TRUE
- var/obj/item/stack/sheet/R = C
+ return ITEM_INTERACT_COMPLETE
+ var/obj/item/stack/sheet/R = used
if(R.get_amount() < 2)
- to_chat(user, "You need two sheets to build a [C.name] floor!")
- return TRUE
- to_chat(user, "You begin swapping the plating for [C]...")
- if(do_after(user, 3 SECONDS * C.toolspeed, target = src))
+ to_chat(user, "You need two sheets to build a [used.name] floor!")
+ return ITEM_INTERACT_COMPLETE
+ to_chat(user, "You begin swapping the plating for [used]...")
+ if(do_after(user, 3 SECONDS * used.toolspeed, target = src))
if(R.get_amount() >= 2 && !transparent_floor)
- if(istype(C, /obj/item/stack/sheet/plasmaglass)) //So, what type of glass floor do we want today?
+ if(istype(used, /obj/item/stack/sheet/plasmaglass)) //So, what type of glass floor do we want today?
ChangeTurf(/turf/simulated/floor/transparent/glass/plasma)
- else if(istype(C, /obj/item/stack/sheet/plasmarglass))
+ else if(istype(used, /obj/item/stack/sheet/plasmarglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/reinforced/plasma)
- else if(istype(C, /obj/item/stack/sheet/glass))
+ else if(istype(used, /obj/item/stack/sheet/glass))
ChangeTurf(/turf/simulated/floor/transparent/glass)
- else if(istype(C, /obj/item/stack/sheet/rglass))
+ else if(istype(used, /obj/item/stack/sheet/rglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/reinforced)
- else if(istype(C, /obj/item/stack/sheet/titaniumglass))
+ else if(istype(used, /obj/item/stack/sheet/titaniumglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/titanium)
- else if(istype(C, /obj/item/stack/sheet/plastitaniumglass))
+ else if(istype(used, /obj/item/stack/sheet/plastitaniumglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/titanium/plasma)
- playsound(src, C.usesound, 80, TRUE)
+ playsound(src, used.usesound, 80, TRUE)
R.use(2)
- to_chat(user, "You swap the plating for [C].")
+ to_chat(user, "You swap the plating for [used].")
new /obj/item/stack/sheet/metal(src, 2)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
- else if(istype(C, /obj/item/storage/backpack/satchel_flat)) //if you click plating with a smuggler satchel, place it on the plating please
+ else if(istype(used, /obj/item/storage/backpack/satchel_flat)) //if you click plating with a smuggler satchel, place it on the plating please
if(user.drop_item())
- C.forceMove(src)
+ used.forceMove(src)
- return TRUE
+ return ITEM_INTERACT_COMPLETE
/turf/simulated/floor/plating/screwdriver_act(mob/user, obj/item/I)
if(!I.tool_use_check(user, 0))
@@ -393,20 +390,22 @@
if(METAL_FOAM_IRON)
icon_state = "ironfoam"
-/turf/simulated/floor/plating/metalfoam/attackby__legacy__attackchain(obj/item/C, mob/user, params)
+/turf/simulated/floor/plating/metalfoam/attack_by(obj/item/attacking, mob/user, params)
if(..())
- return TRUE
+ return FINISH_ATTACK
- if(istype(C) && C.force)
+ if(istype(attacking) && attacking.force)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
- var/smash_prob = max(0, C.force * 17 - metal_kind * 25) // A crowbar will have a 60% chance of a breakthrough on alum, 35% on iron
+ var/smash_prob = max(0, attacking.force * 17 - metal_kind * 25) // A crowbar will have a 60% chance of a breakthrough on alum, 35% on iron
if(prob(smash_prob))
// YAR BE CAUSIN A HULL BREACH
- visible_message("[user] smashes through \the [src] with \the [C]!")
+ visible_message("[user] smashes through \the [src] with \the [attacking]!")
smash()
+ return FINISH_ATTACK
else
- visible_message("[user]'s [C.name] bounces against \the [src]!")
+ visible_message("[user]'s [attacking.name] bounces against \the [src]!")
+ return FINISH_ATTACK
/turf/simulated/floor/plating/metalfoam/attack_animal(mob/living/simple_animal/M)
M.do_attack_animation(src)
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
index 48ce133374e..ce008def807 100644
--- a/code/game/turfs/simulated/minerals.dm
+++ b/code/game/turfs/simulated/minerals.dm
@@ -62,24 +62,32 @@
/turf/simulated/mineral/shuttleRotate(rotation)
QUEUE_SMOOTH(src)
-/turf/simulated/mineral/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- // TODO: Just sticking this here for now because attack chain refactor is coming later
- // No point in threading this through everything right now
- if(SEND_SIGNAL(src, COMSIG_ATTACK_BY, I, user, params) & COMPONENT_SKIP_AFTERATTACK)
- return
+/turf/simulated/mineral/proc/invalid_tool(mob/user, obj/item/pickaxe/axe)
+ if(!istype(axe))
+ return TRUE
+
+ return FALSE
+
+/turf/simulated/mineral/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
if(!user.IsAdvancedToolUser())
to_chat(usr, "You don't have the dexterity to do this!")
- return
+ return FINISH_ATTACK
+
+ if(istype(attacking, /obj/item/pickaxe))
+ var/obj/item/pickaxe/P = attacking
+ if(invalid_tool(user, P))
+ return FINISH_ATTACK
- if(istype(I, /obj/item/pickaxe))
- var/obj/item/pickaxe/P = I
var/turf/T = user.loc
if(!isturf(T))
- return
+ return FINISH_ATTACK
if(last_act + (mine_time * P.toolspeed) > world.time) // Prevents message spam
- return
+ return FINISH_ATTACK
+
last_act = world.time
to_chat(user, "You start picking...")
P.playDigSound()
@@ -89,6 +97,8 @@
to_chat(user, "You finish cutting into the rock.")
gets_drilled(user)
SSblackbox.record_feedback("tally", "pick_used_mining", 1, P.name)
+
+ return FINISH_ATTACK
else
return attack_hand(user)
@@ -126,15 +136,15 @@
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if((istype(H.l_hand,/obj/item/pickaxe)) && (!H.hand))
- attackby__legacy__attackchain(H.l_hand,H)
+ attack_by(H.l_hand, H)
else if((istype(H.r_hand,/obj/item/pickaxe)) && H.hand)
- attackby__legacy__attackchain(H.r_hand,H)
+ attack_by(H.r_hand, H)
return
else if(isrobot(AM))
var/mob/living/silicon/robot/R = AM
if(istype(R.module_active, /obj/item/pickaxe))
- attackby__legacy__attackchain(R.module_active, R)
+ attack_by(R.module_active, R)
else if(ismecha(AM))
var/obj/mecha/M = AM
@@ -192,31 +202,6 @@
should_reset_color = FALSE
baseturf = /turf/simulated/floor/plating/asteroid/ancient
-/turf/simulated/mineral/ancient/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- if(!user.IsAdvancedToolUser())
- to_chat(usr, "You don't have the dexterity to do this!")
- return
-
- if(istype(I, /obj/item/pickaxe))
- var/obj/item/pickaxe/P = I
- var/turf/T = user.loc
- if(!isturf(T))
- return
-
- if(last_act + (mine_time * P.toolspeed) > world.time) // Prevents message spam
- return
- last_act = world.time
- to_chat(user, "You start picking...")
- P.playDigSound()
-
- if(do_after(user, mine_time * P.toolspeed, target = src))
- if(ismineralturf(src)) //sanity check against turf being deleted during digspeed delay
- to_chat(user, "You finish cutting into the rock.")
- gets_drilled(user)
- SSblackbox.record_feedback("tally", "pick_used_mining", 1, P.name)
- else
- return attack_hand(user)
-
/turf/simulated/mineral/ancient/blob_act(obj/structure/blob/B)
if(prob(50))
blob_destruction()
@@ -250,11 +235,13 @@
/obj/item/pickaxe/drill/diamonddrill,
))
-/turf/simulated/mineral/ancient/outer/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/pickaxe) && !(is_type_in_typecache(I, allowed_picks_typecache)))
- to_chat(user, "Only a diamond tools or a sonic jackhammer can break this rock.")
- return
- return ..()
+/turf/simulated/mineral/ancient/outer/invalid_tool(mob/user, obj/item/pickaxe/axe)
+ if(..())
+ return TRUE
+
+ if(!(is_type_in_typecache(axe, allowed_picks_typecache)))
+ to_chat(user, "Only diamond tools or a sonic jackhammer can break this rock.")
+ return TRUE
/turf/simulated/mineral/ancient/lava_land_surface_hard
name = "hardened volcanic rock"
@@ -278,11 +265,13 @@
/obj/item/pickaxe/drill/diamonddrill,
))
-/turf/simulated/mineral/ancient/lava_land_surface_hard/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/pickaxe) && !(is_type_in_typecache(I, allowed_picks_typecache)))
- to_chat(user, "Only a diamond tools or a sonic jackhammer can break this rock.")
- return
- return ..()
+/turf/simulated/mineral/ancient/lava_land_surface_hard/invalid_tool(mob/user, obj/item/pickaxe/axe)
+ if(..())
+ return TRUE
+
+ if(!(is_type_in_typecache(axe, allowed_picks_typecache)))
+ to_chat(user, "Only diamond tools or a sonic jackhammer can break this rock.")
+ return TRUE
/turf/simulated/mineral/random/high_chance
color = COLOR_YELLOW
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index c59f8e5220f..f7050f5af93 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -342,28 +342,30 @@
add_fingerprint(user)
return ..()
-/turf/simulated/wall/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/turf/simulated/wall/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
user.changeNext_move(CLICK_CD_MELEE)
if(!isturf(user.loc))
- return // No touching walls unless you're on a turf (pretty sure attackby can't be called anyways but whatever)
+ return FINISH_ATTACK // No touching walls unless you're on a turf (pretty sure attackby can't be called anyways but whatever)
- if(rotting && try_rot(I, user, params))
- return
+ if(rotting && try_rot(attacking, user, params))
+ return FINISH_ATTACK
- if(try_decon(I, user, params))
- return
+ if(try_decon(attacking, user, params))
+ return FINISH_ATTACK
- if(try_destroy(I, user, params))
- return
+ if(try_destroy(attacking, user, params))
+ return FINISH_ATTACK
+
+ if(try_wallmount(attacking, user, params))
+ return CONTINUE_ATTACK
- if(try_wallmount(I, user, params))
- return
// The cyborg gripper does a separate attackby, so bail from this one
- if(istype(I, /obj/item/gripper))
- return
-
- return ..()
+ if(istype(attacking, /obj/item/gripper))
+ return CONTINUE_ATTACK
/turf/simulated/wall/welder_act(mob/user, obj/item/I)
. = TRUE
diff --git a/code/game/turfs/simulated/walls_indestructible.dm b/code/game/turfs/simulated/walls_indestructible.dm
index b4d822bb10e..6fdf37f2d1e 100644
--- a/code/game/turfs/simulated/walls_indestructible.dm
+++ b/code/game/turfs/simulated/walls_indestructible.dm
@@ -3,6 +3,10 @@
desc = "Effectively impervious to conventional methods of destruction."
explosion_block = 50
+/turf/simulated/wall/indestructible/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
+
/turf/simulated/wall/indestructible/dismantle_wall(devastated = 0, explode = 0)
return
@@ -34,9 +38,6 @@
/turf/simulated/wall/indestructible/burn_down()
return
-/turf/simulated/wall/indestructible/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- return
-
/turf/simulated/wall/indestructible/attack_hand(mob/user)
return
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index 97a2c674a16..1d9d726abd0 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -87,9 +87,11 @@
radiate()
..()
-/turf/simulated/wall/mineral/uranium/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
+/turf/simulated/wall/mineral/uranium/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
radiate()
- ..()
/turf/simulated/wall/mineral/uranium/Bumped(AM as mob|obj)
radiate()
@@ -106,14 +108,17 @@
smoothing_groups = list(SMOOTH_GROUP_SIMULATED_TURFS, SMOOTH_GROUP_WALLS, SMOOTH_GROUP_PLASMA_WALLS)
canSmoothWith = list(SMOOTH_GROUP_PLASMA_WALLS)
-/turf/simulated/wall/mineral/plasma/attackby__legacy__attackchain(obj/item/W, mob/user)
- if(W.get_heat() > 300)//If the temperature of the object is over 300, then ignite
+/turf/simulated/wall/mineral/plasma/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
+ if(attacking.get_heat() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma wall ignited by [key_name_admin(user)] in ([x], [y], [z] - JMP)",0,1)
log_game("Plasma wall ignited by [key_name(user)] in ([x], [y], [z])")
investigate_log("was ignited by [key_name(user)]","atmos")
- ignite(W.get_heat())
- return
- ..()
+ ignite(attacking.get_heat())
+
+ return FINISH_ATTACK
/turf/simulated/wall/mineral/plasma/welder_act(mob/user, obj/item/I)
if(I.tool_enabled)
@@ -171,15 +176,18 @@
smoothing_groups = list(SMOOTH_GROUP_SIMULATED_TURFS, SMOOTH_GROUP_WALLS, SMOOTH_GROUP_WOOD_WALLS)
canSmoothWith = list(SMOOTH_GROUP_WOOD_WALLS)
-/turf/simulated/wall/mineral/wood/attackby__legacy__attackchain(obj/item/W, mob/user)
- if(W.sharp && W.force)
- var/duration = (48 / W.force) * 2 //In seconds, for now.
- if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/fireaxe))
+/turf/simulated/wall/mineral/wood/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
+ if(attacking.sharp && attacking.force)
+ var/duration = (48 / attacking.force) * 2 //In seconds, for now.
+ if(istype(attacking, /obj/item/hatchet) || istype(attacking, /obj/item/fireaxe))
duration /= 4 //Much better with hatchets and axes.
if(do_after(user, duration * 10, target = src)) //Into deciseconds.
dismantle_wall(FALSE, FALSE)
- return
- return ..()
+ return FINISH_ATTACK
+
/turf/simulated/wall/mineral/wood/nonmetal
desc = "A solidly wooden wall. It's a bit weaker than a wall made with metal."
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index a922b664583..56b033487d8 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -40,37 +40,38 @@
if(RWALL_SHEATH)
. += "The support rods have been sliced through, and the outer sheath is connected loosely to the girder."
-/turf/simulated/wall/r_wall/attackby__legacy__attackchain(obj/item/I, mob/user, params)
- if(d_state == RWALL_COVER && istype(I, /obj/item/gun/energy/plasmacutter))
+/turf/simulated/wall/r_wall/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return FINISH_ATTACK
+
+ if(d_state == RWALL_COVER && istype(attacking, /obj/item/gun/energy/plasmacutter))
to_chat(user, "You begin slicing through the metal cover...")
- if(I.use_tool(src, user, 40, volume = I.tool_volume) && d_state == RWALL_COVER)
+ if(attacking.use_tool(src, user, 40, volume = attacking.tool_volume) && d_state == RWALL_COVER)
d_state = RWALL_CUT_COVER
update_icon()
to_chat(user, "You press firmly on the cover, dislodging it.")
- return
- else if(d_state == RWALL_SUPPORT_RODS && istype(I, /obj/item/gun/energy/plasmacutter))
+ return FINISH_ATTACK
+ else if(d_state == RWALL_SUPPORT_RODS && istype(attacking, /obj/item/gun/energy/plasmacutter))
to_chat(user, "You begin slicing through the support rods...")
- if(I.use_tool(src, user, 70, volume = I.tool_volume) && d_state == RWALL_SUPPORT_RODS)
+ if(attacking.use_tool(src, user, 70, volume = attacking.tool_volume) && d_state == RWALL_SUPPORT_RODS)
d_state = RWALL_SHEATH
update_icon()
- return
+ return FINISH_ATTACK
else if(d_state)
// Repairing
- if(istype(I, /obj/item/stack/sheet/metal))
- var/obj/item/stack/sheet/metal/MS = I
+ if(istype(attacking, /obj/item/stack/sheet/metal))
+ var/obj/item/stack/sheet/metal/MS = attacking
to_chat(user, "You begin patching-up the wall with [MS]...")
if(do_after(user, max(20 * d_state, 100) * MS.toolspeed, target = src) && d_state)
if(!MS.use(1))
to_chat(user, "You don't have enough [MS.name] for that!")
- return
+ return FINISH_ATTACK
d_state = RWALL_INTACT
update_icon()
QUEUE_SMOOTH_NEIGHBORS(src)
to_chat(user, "You repair the last of the damage.")
- return
- else
- return ..()
+ return FINISH_ATTACK
/turf/simulated/wall/r_wall/welder_act(mob/user, obj/item/I)
if(reagents?.get_reagent_amount("thermite") && I.use_tool(src, user, volume = I.tool_volume))
diff --git a/code/game/turfs/space/space_turf.dm b/code/game/turfs/space/space_turf.dm
index 712aed9a41c..42d95de6061 100644
--- a/code/game/turfs/space/space_turf.dm
+++ b/code/game/turfs/space/space_turf.dm
@@ -74,44 +74,48 @@
return
set_light(0)
-/turf/space/attackby__legacy__attackchain(obj/item/C as obj, mob/user as mob, params)
- ..()
- if(istype(C, /obj/item/stack/rods))
- var/obj/item/stack/rods/R = C
+/turf/space/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/stack/rods))
+ var/obj/item/stack/rods/R = used
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
var/obj/structure/lattice/catwalk/W = locate(/obj/structure/lattice/catwalk, src)
if(W)
to_chat(user, "There is already a catwalk here!")
- return
+ return ITEM_INTERACT_COMPLETE
if(L)
if(R.use(1))
to_chat(user, "You construct a catwalk.")
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
new/obj/structure/lattice/catwalk(src)
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You need two rods to build a catwalk!")
- return
+ return ITEM_INTERACT_COMPLETE
if(R.use(1))
to_chat(user, "Constructing support lattice...")
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
ReplaceWithLattice()
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You need one rod to build a lattice.")
- return
+ return ITEM_INTERACT_COMPLETE
- if(istype(C, /obj/item/stack/tile/plasteel))
+ if(istype(used, /obj/item/stack/tile/plasteel))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
- var/obj/item/stack/tile/plasteel/S = C
+ var/obj/item/stack/tile/plasteel/S = used
if(S.use(1))
qdel(L)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
to_chat(user, "You build a floor.")
ChangeTurf(/turf/simulated/floor/plating)
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "You need one floor tile to build a floor!")
+ return ITEM_INTERACT_COMPLETE
else
to_chat(user, "The plating is going to need some support! Place metal rods first.")
+ return ITEM_INTERACT_COMPLETE
/turf/space/Entered(atom/movable/A as mob|obj, atom/OL, ignoreRest = 0)
..()
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index 07fc46f73f9..e6c64041d4a 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -4,9 +4,10 @@
icon_state = "black"
dir = SOUTH
-//Overwrite because we dont want people building rods in space.
-/turf/space/transit/attackby__legacy__attackchain(obj/O as obj, mob/user as mob, params)
- return
+/turf/space/transit/Initialize(mapload)
+ . = ..()
+ // We don't want people building rods in space.
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
/// moving to the north
/turf/space/transit/north
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index d4bf9702dab..c8d6fe4feb9 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -93,6 +93,8 @@
OPEN_HEAT_TRANSFER_COEFFICIENT)
var/list/milla_data = list()
+ new_attack_chain = TRUE
+
/turf/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
if(initialized)
@@ -482,28 +484,29 @@
if(SSticker)
GLOB.cameranet.updateVisibility(src)
-/turf/attackby__legacy__attackchain(obj/item/I, mob/user, params)
+/turf/attack_by(obj/item/attacking, mob/user, params)
+ if(..())
+ return TRUE
+
if(can_lay_cable())
- if(istype(I, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = I
+ if(istype(attacking, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = attacking
for(var/obj/structure/cable/LC in src)
if(LC.d1 == 0 || LC.d2 == 0)
LC.attackby__legacy__attackchain(C, user)
- return
+ return TRUE
C.place_turf(src, user)
return TRUE
- else if(istype(I, /obj/item/rcl))
- var/obj/item/rcl/R = I
+ else if(istype(attacking, /obj/item/rcl))
+ var/obj/item/rcl/R = attacking
if(R.loaded)
for(var/obj/structure/cable/LC in src)
if(LC.d1 == 0 || LC.d2 == 0)
LC.attackby__legacy__attackchain(R, user)
- return
+ return TRUE
R.loaded.place_turf(src, user)
R.is_empty(user)
- return FALSE
-
/turf/proc/can_have_cabling()
return TRUE
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index 6dbcc309c77..fc2d81c0488 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -82,14 +82,15 @@
color = "#aa77aa"
icon_state = "vinefloor"
+/turf/simulated/floor/vines/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ATTACK_BY, TYPE_PROC_REF(/datum, signal_cancel_attack_by))
+
/turf/simulated/floor/vines/get_broken_states()
return list()
//All of this shit is useless for vines
-/turf/simulated/floor/vines/attackby__legacy__attackchain()
- return
-
/turf/simulated/floor/vines/burn_tile()
return
diff --git a/code/tests/_game_test_puppeteer.dm b/code/tests/_game_test_puppeteer.dm
index 2eb85778e28..10e39706602 100644
--- a/code/tests/_game_test_puppeteer.dm
+++ b/code/tests/_game_test_puppeteer.dm
@@ -34,10 +34,17 @@
origin_test.Fail("could not spawn obj [obj_type] in hand of [puppet]")
-/datum/test_puppeteer/proc/spawn_obj_nearby(obj_type)
- for(var/turf/T in RANGE_TURFS(1, puppet.loc))
- if(!is_blocked_turf(T, exclude_mobs = FALSE))
- return origin_test.allocate(obj_type, T)
+/datum/test_puppeteer/proc/spawn_obj_nearby(obj_type, direction = -1)
+ var/turf/T
+ if(direction >= 0)
+ T = get_step(puppet, direction)
+ else
+ for(var/turf/nearby in RANGE_TURFS(1, puppet.loc))
+ if(!is_blocked_turf(nearby, exclude_mobs = FALSE))
+ T = nearby
+
+ if(T)
+ return origin_test.allocate(obj_type, T)
origin_test.Fail("could not spawn obj [obj_type] near [src]")
@@ -56,6 +63,23 @@
var/mob/new_mob = origin_test.allocate(mob_type, T)
return new_mob
+/datum/test_puppeteer/proc/change_turf_nearby(turf_type, direction = -1)
+ var/turf/T
+ if(direction >= 0)
+ T = get_step(puppet, direction)
+ else
+ // just check for any contents, not blocked_turf which includes turf density
+ // (which we don't really care about)
+ for(var/turf/nearby in RANGE_TURFS(1, puppet))
+ if(!length(nearby.contents))
+ T = nearby
+
+ if(T)
+ T.ChangeTurf(turf_type)
+ return T
+
+ origin_test.Fail("could not spawn turf [turf_type] near [src]")
+
/datum/test_puppeteer/proc/check_attack_log(snippet)
for(var/log_text in puppet.attack_log_old)
if(findtextEx(log_text, snippet))
diff --git a/code/tests/attack_chain/test_attack_chain_turf.dm b/code/tests/attack_chain/test_attack_chain_turf.dm
new file mode 100644
index 00000000000..ee7e2aaca2e
--- /dev/null
+++ b/code/tests/attack_chain/test_attack_chain_turf.dm
@@ -0,0 +1,47 @@
+/datum/game_test/attack_chain_turf/Run()
+ var/datum/test_puppeteer/player = new(src)
+ var/area/admin_area = get_area(player.puppet)
+
+ // So we can actually place a mounted frame here
+ admin_area.requires_power = TRUE
+ var/turf/wall = player.change_turf_nearby(/turf/simulated/wall, EAST)
+ player.spawn_obj_in_hand(/obj/item/mounted/frame/alarm_frame)
+ player.click_on(wall)
+ TEST_ASSERT(locate(/obj/machinery/alarm) in player.puppet.loc, "Did not find built air alarm frame")
+ admin_area.requires_power = FALSE
+
+ var/turf/plating = player.change_turf_nearby(/turf/simulated/floor/plating)
+ var/obj/item/stack/rods/rods = player.spawn_obj_in_hand(/obj/item/stack/rods/fifty)
+ rods.toolspeed = 0 // Don't want to try waiting this out in a test
+ player.click_on(plating)
+ var/turf/engine = get_turf(plating)
+ TEST_ASSERT(istype(engine, /turf/simulated/floor/engine), "Did not find plating converted to engine floor")
+ player.puppet.drop_item_to_ground(rods, force = TRUE)
+
+ var/obj/item/storage/bag/ore/ore_bag = player.spawn_obj_in_hand(/obj/item/storage/bag/ore)
+ var/obj/item/stack/ore/gold/gold = player.spawn_obj_nearby(/obj/item/stack/ore/gold, SOUTH)
+ var/turf/asteroid = player.change_turf_nearby(/turf/simulated/floor/plating/asteroid, SOUTH)
+ player.click_on(asteroid)
+ TEST_ASSERT(gold in ore_bag, "Did not find gold in ore bag")
+ qdel(ore_bag)
+
+ plating = player.change_turf_nearby(/turf/simulated/floor/plating)
+ var/obj/rpd = player.spawn_obj_in_hand(/obj/item/rpd)
+ player.click_on(plating)
+ TEST_ASSERT(locate(/obj/machinery/atmospherics/pipe) in plating, "Did not find pipe placed with RPD")
+ qdel(rpd)
+
+ var/obj/resonator = player.spawn_obj_in_hand(/obj/item/resonator)
+ var/turf/mineral_wall = player.change_turf_nearby(/turf/simulated/mineral/ancient)
+ player.click_on(mineral_wall)
+ sleep(3 SECONDS)
+ TEST_ASSERT(istype(get_turf(mineral_wall), /turf/simulated/floor/plating/asteroid), "Did not find mineral wall dug with resonator")
+ qdel(resonator)
+
+ var/obj/item/soap/soap = player.spawn_obj_in_hand(/obj/item/soap)
+ soap.cleanspeed = 0
+ var/turf/T = get_turf(player.puppet)
+ new/obj/effect/spawner/themed_mess/bloody(T)
+ TEST_ASSERT(locate(/obj/effect/decal/cleanable) in T, "Did not find any mess decal on turf")
+ player.click_on(T)
+ TEST_ASSERT_NOT(locate(/obj/effect/decal/cleanable) in T, "Mess decal remained on turf after soap use")
diff --git a/code/tests/game_tests.dm b/code/tests/game_tests.dm
index 254673e8b34..0bbe3fff14c 100644
--- a/code/tests/game_tests.dm
+++ b/code/tests/game_tests.dm
@@ -6,6 +6,7 @@
#include "_game_test.dm"
#include "atmos\test_ventcrawl.dm"
#include "attack_chain\test_attack_chain_cult_dagger.dm"
+#include "attack_chain\test_attack_chain_turf.dm"
#include "attack_chain\test_attack_chain_vehicles.dm"
#include "games\test_cards.dm"
#include "jobs\test_job_globals.dm"