From 3db86c80ac8b6ebd494c7a1eda2ccb747e2de729 Mon Sep 17 00:00:00 2001 From: warriorstar-orion Date: Fri, 10 Jan 2025 16:15:19 -0500 Subject: [PATCH] Attack Chain Migration: /turf (#27530) * Attack Chain Migration: /turf * don't clobber component/signal vars when copying holodeck turfs * Attack Chain Migration: /turf * don't clobber component/signal vars when copying holodeck turfs * Fixes from first round of testing * rename signals, add afterattack skip * Update code/game/turfs/simulated/minerals.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: warriorstar-orion * Add some tests. * Update code/game/turfs/simulated/minerals.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: warriorstar-orion * fix TM issues * make soap instantaneous and remove hardcoded sleep * add sentinel value for obj placement direction choice * fix tests --------- Signed-off-by: warriorstar-orion Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> --- code/__HELPERS/unsorted.dm | 23 ++++- .../machinery/computer/HolodeckControl.dm | 8 +- code/game/objects/structures/lattice.dm | 3 +- code/game/turfs/simulated/floor.dm | 24 +++--- .../turfs/simulated/floor/asteroid_floors.dm | 23 +++-- code/game/turfs/simulated/floor/chasm.dm | 22 +++-- .../game/turfs/simulated/floor/fancy_floor.dm | 7 +- .../turfs/simulated/floor/indestructible.dm | 7 +- code/game/turfs/simulated/floor/lava.dm | 36 ++++---- .../turfs/simulated/floor/mineral_floors.dm | 30 ++++--- code/game/turfs/simulated/floor/plating.dm | 81 +++++++++--------- code/game/turfs/simulated/minerals.dm | 85 ++++++++----------- code/game/turfs/simulated/walls.dm | 30 ++++--- .../turfs/simulated/walls_indestructible.dm | 7 +- code/game/turfs/simulated/walls_mineral.dm | 34 +++++--- code/game/turfs/simulated/walls_reinforced.dm | 27 +++--- code/game/turfs/space/space_turf.dm | 22 +++-- code/game/turfs/space/transit.dm | 7 +- code/game/turfs/turf.dm | 21 +++-- code/modules/events/spacevine.dm | 7 +- code/tests/_game_test_puppeteer.dm | 32 ++++++- .../attack_chain/test_attack_chain_turf.dm | 47 ++++++++++ code/tests/game_tests.dm | 1 + 23 files changed, 349 insertions(+), 235 deletions(-) create mode 100644 code/tests/attack_chain/test_attack_chain_turf.dm 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"