From 3e504a77ae134ba55c076dbd866f5bdb0d6726ac Mon Sep 17 00:00:00 2001
From: RikuTheKiller <88713943+RikuTheKiller@users.noreply.github.com>
Date: Mon, 26 Jan 2026 18:36:16 +0200
Subject: [PATCH] Refactor girders and wall construction (#94364)
## About The Pull Request
This PR refactors wall construction on girders, wooden barricades and
metal foam to use a centralized element, which listens to item
interaction signals and attempts to make any available wall recipe.
This change is an atomized prerequisite to my blueprinting system, since
that system requires a sane way to dynamically change the speed at which
walls are built.
This PR will later be expanded to refactor girder construction steps in
general.
I also added `proc/valid_typesof(base_type)` as a side effect of my
previous attempts at refactoring this stuff. There's now what amounts to
a code comment easter egg in the same file, because DM is wacko and
you're going to get cursed now too. :)
## Why It's Good For The Game
The old system had ~20 bespoke yet highly similar wall construction
steps. Some of the wall recipes were also concatenated from a string on
the used stack type. To put it bluntly, the code was fucking horrible.
Same thing goes for the rest of the girder construction steps, they were
all bespoke.
## Changelog
:cl:
refactor: Refactored girders and wall construction. Report any bugs.
tweak: Some niche wall types might have their wall delay changed by like
2 seconds. This doesn't affect normal walls, reinforced walls,
falsewalls or any other important wall types.
/:cl:
---
code/__HELPERS/abstract_types.dm | 7 +
code/_globalvars/lists/girder_wall_recipes.dm | 121 ++++
.../elements/uses_girder_wall_recipes.dm | 130 ++++
code/datums/girder_wall_recipe.dm | 27 +
code/game/machinery/deployable.dm | 27 +-
.../fluid_spread/effects_foam.dm | 32 +-
code/game/objects/structures/girders.dm | 560 ++++--------------
code/game/turfs/closed/wall/mineral_walls.dm | 2 +
code/game/turfs/closed/wall/reinf_walls.dm | 2 +
code/game/turfs/closed/walls.dm | 15 +-
tgstation.dme | 3 +
11 files changed, 427 insertions(+), 499 deletions(-)
create mode 100644 code/_globalvars/lists/girder_wall_recipes.dm
create mode 100644 code/datums/elements/uses_girder_wall_recipes.dm
create mode 100644 code/datums/girder_wall_recipe.dm
diff --git a/code/__HELPERS/abstract_types.dm b/code/__HELPERS/abstract_types.dm
index ecf8fb35bb4..e2013ad4bbe 100644
--- a/code/__HELPERS/abstract_types.dm
+++ b/code/__HELPERS/abstract_types.dm
@@ -10,6 +10,13 @@
return abstracts
+// The time complexity of these two procs is really bad, sitting at O(n * m).
+// And yet, the overhead is ridiculously small for some reason. We never figured out why.
+// So doing list subtraction instead of filtering is faster in all cases, at least for now.
+// If we ever breach like 3000-5000 abstract types, that will likely change.
+// As of right now we're at 272 or so, with subtraction being ~10x faster.
+// Curse this language, for you shall live in hell alongside me.
+
/// Like subtypesof, but automatically excludes abstract typepaths
/proc/valid_subtypesof(datum/sometype)
return subtypesof(sometype) - get_abstract_types()
diff --git a/code/_globalvars/lists/girder_wall_recipes.dm b/code/_globalvars/lists/girder_wall_recipes.dm
new file mode 100644
index 00000000000..d4a015c6a4e
--- /dev/null
+++ b/code/_globalvars/lists/girder_wall_recipes.dm
@@ -0,0 +1,121 @@
+GLOBAL_LIST_INIT(main_girder_wall_recipes, init_main_girder_wall_recipes())
+GLOBAL_LIST_INIT(material_girder_wall_recipes, init_material_girder_wall_recipes())
+
+/// Initializes the main, false and tram wall types using three lists of wall types.
+/proc/init_main_girder_wall_recipes()
+ return create_girder_wall_recipes(
+ wall_types = list(
+ /turf/closed/wall,
+ /turf/closed/wall/metal_foam_base,
+ /turf/closed/wall/r_wall,
+ /turf/closed/wall/r_wall/plastitanium,
+ /turf/closed/wall/mineral/gold,
+ /turf/closed/wall/mineral/silver,
+ /turf/closed/wall/mineral/diamond,
+ /turf/closed/wall/mineral/bananium,
+ /turf/closed/wall/mineral/sandstone,
+ /turf/closed/wall/mineral/uranium,
+ /turf/closed/wall/mineral/plasma,
+ /turf/closed/wall/mineral/wood,
+ /turf/closed/wall/mineral/wood/nonmetal,
+ /turf/closed/wall/mineral/bamboo,
+ /turf/closed/wall/mineral/iron,
+ /turf/closed/wall/mineral/snow,
+ /turf/closed/wall/mineral/abductor,
+ /turf/closed/wall/mineral/titanium,
+ /turf/closed/wall/mineral/plastitanium,
+ /turf/closed/wall/mineral/cult,
+ /turf/closed/wall/mineral/bronze,
+ /turf/closed/wall/material,
+ ),
+ falsewall_types = list(
+ /obj/structure/falsewall,
+ /obj/structure/falsewall/reinforced,
+ /obj/structure/falsewall/gold,
+ /obj/structure/falsewall/silver,
+ /obj/structure/falsewall/diamond,
+ /obj/structure/falsewall/bananium,
+ /obj/structure/falsewall/sandstone,
+ /obj/structure/falsewall/uranium,
+ /obj/structure/falsewall/plasma,
+ /obj/structure/falsewall/wood,
+ /obj/structure/falsewall/bamboo,
+ /obj/structure/falsewall/iron,
+ /obj/structure/falsewall/abductor,
+ /obj/structure/falsewall/titanium,
+ /obj/structure/falsewall/plastitanium,
+ /obj/structure/falsewall/material,
+ ),
+ tram_types = list(
+ /obj/structure/tram,
+ /obj/structure/tram/alt/gold,
+ /obj/structure/tram/alt/silver,
+ /obj/structure/tram/alt/diamond,
+ /obj/structure/tram/alt/bananium,
+ /obj/structure/tram/alt/sandstone,
+ /obj/structure/tram/alt/uranium,
+ /obj/structure/tram/alt/plasma,
+ /obj/structure/tram/alt/wood,
+ /obj/structure/tram/alt/bamboo,
+ /obj/structure/tram/alt/iron,
+ /obj/structure/tram/alt/abductor,
+ /obj/structure/tram/alt/titanium,
+ /obj/structure/tram/alt/plastitanium,
+ )
+ )
+
+/// Initializes the normal and false girder material wall recipes using two lists of material wall types.
+/proc/init_material_girder_wall_recipes()
+ return create_girder_wall_recipes(
+ wall_types = list(/turf/closed/wall/material),
+ falsewall_types = list(/obj/structure/falsewall/material)
+ )
+
+/// Returns a list of newly created [/datum/girder_wall_recipe] instances from the given wall type lists.
+/proc/create_girder_wall_recipes(list/wall_types, list/falsewall_types, list/tram_types)
+ var/list/recipes = list()
+
+ for (var/turf/closed/wall/wall_type as anything in wall_types)
+ add_girder_wall_recipe(
+ recipes = recipes,
+ wall_type = wall_type,
+ stack_type = wall_type::sheet_type,
+ stack_amount = wall_type::sheet_amount,
+ girder_type = wall_type::girder_type,
+ girder_state = wall_type::girder_state,
+ make_delay = wall_type::make_delay,
+ start_alert = "adding plating..."
+ )
+
+ for (var/obj/structure/falsewall/falsewall_type as anything in falsewall_types)
+ add_girder_wall_recipe(
+ recipes = recipes,
+ wall_type = falsewall_type,
+ stack_type = falsewall_type::mineral,
+ stack_amount = falsewall_type::mineral_amount,
+ girder_type = falsewall_type::girder_type,
+ girder_state = GIRDER_DISPLACED,
+ make_delay = 2 SECONDS,
+ start_alert = "concealing entrance..."
+ )
+
+ for (var/obj/structure/tram/tram_type as anything in tram_types)
+ add_girder_wall_recipe(
+ recipes = recipes,
+ wall_type = tram_type,
+ stack_type = tram_type::mineral,
+ stack_amount = tram_type::mineral_amount,
+ girder_type = tram_type::girder_type,
+ girder_state = GIRDER_TRAM,
+ make_delay = 4 SECONDS,
+ start_alert = "adding plating..."
+ )
+
+ return recipes
+
+/// Adds a new [/datum/girder_wall_recipe] instance to the given recipe list from the given recipe arguments.
+/proc/add_girder_wall_recipe(list/recipes, wall_type, stack_type, stack_amount, girder_type, girder_state, make_delay, start_alert)
+ if (!ispath(stack_type, /obj/item/stack))
+ CRASH("Attempted to create a girder wall recipe for wall type ([wall_type]) with an invalid stack type ([stack_type])")
+
+ recipes += new /datum/girder_wall_recipe(wall_type, stack_type, stack_amount, girder_type, girder_state, make_delay, start_alert)
diff --git a/code/datums/elements/uses_girder_wall_recipes.dm b/code/datums/elements/uses_girder_wall_recipes.dm
new file mode 100644
index 00000000000..b313f78200e
--- /dev/null
+++ b/code/datums/elements/uses_girder_wall_recipes.dm
@@ -0,0 +1,130 @@
+/// An element for girders, wall barricades, etc. that makes them use wall construction recipes.
+/// Only really meant for recipes where you click on the girder with a stack of materials to make a wall.
+/datum/element/uses_girder_wall_recipes
+
+/datum/element/uses_girder_wall_recipes/Attach(datum/target)
+ . = ..()
+ if (!isstructure(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignals(target, list(COMSIG_ATOM_ITEM_INTERACTION, COMSIG_ATOM_ITEM_INTERACTION_SECONDARY), PROC_REF(on_item_interaction))
+
+/datum/element/uses_girder_wall_recipes/Detach(datum/target, ...)
+ UnregisterSignal(target, list(COMSIG_ATOM_ITEM_INTERACTION, COMSIG_ATOM_ITEM_INTERACTION_SECONDARY))
+ return ..()
+
+/datum/element/uses_girder_wall_recipes/proc/on_item_interaction(obj/structure/structure, mob/living/user, obj/item/stack/stack, list/modifiers)
+ SIGNAL_HANDLER
+ if (!isstack(stack))
+ return NONE
+ if (!stack.usable_for_construction)
+ structure.balloon_alert(user, "unusable material!")
+ return ITEM_INTERACT_BLOCKING
+
+ var/datum/girder_wall_recipe/main_recipe = get_main_recipe(structure, stack)
+
+ if (main_recipe)
+ INVOKE_ASYNC(src, PROC_REF(attempt_recipe), structure, user, stack, main_recipe, is_material_recipe = FALSE)
+ return ITEM_INTERACT_BLOCKING
+
+ if (stack.has_unique_girder)
+ structure.balloon_alert(user, "needs a different girder!")
+ return ITEM_INTERACT_BLOCKING
+
+ // Plasteel is used for reinforcing girders.
+ if (istype(structure, /obj/structure/girder) && istype(stack, /obj/item/stack/sheet/plasteel))
+ return NONE
+
+ var/datum/girder_wall_recipe/material_recipe = get_material_recipe(structure, stack)
+
+ if (material_recipe)
+ INVOKE_ASYNC(src, PROC_REF(attempt_recipe), structure, user, stack, material_recipe, is_material_recipe = TRUE)
+ return ITEM_INTERACT_BLOCKING
+
+/// Returns the main wall recipe of the stack for the structure, if any.
+/datum/element/uses_girder_wall_recipes/proc/get_main_recipe(obj/structure/structure, obj/item/stack/stack)
+ for (var/datum/girder_wall_recipe/recipe as anything in GLOB.main_girder_wall_recipes)
+ if (!istype(stack, recipe.stack_type))
+ continue
+ if (!istype(structure, recipe.girder_type))
+ continue
+ if (!check_girder_state(structure, recipe))
+ continue
+ return recipe
+
+/// Returns the material wall recipe of the stack for the structure, if any.
+/datum/element/uses_girder_wall_recipes/proc/get_material_recipe(obj/structure/structure, obj/item/stack/stack)
+ for (var/datum/girder_wall_recipe/recipe as anything in GLOB.material_girder_wall_recipes)
+ if (!istype(structure, recipe.girder_type))
+ continue
+ if (!check_girder_state(structure, recipe))
+ continue
+ return recipe
+
+/// Has the user attempt the wall recipe asynchronously.
+/// Assumes that the structure and stack are of valid types for the recipe.
+/datum/element/uses_girder_wall_recipes/proc/attempt_recipe_async(obj/structure/structure, mob/living/user, obj/item/stack/stack, datum/girder_wall_recipe/recipe, is_material_recipe)
+ INVOKE_ASYNC(src, PROC_REF(attempt_recipe), structure, user, stack, recipe, is_material_recipe)
+
+/// Has the user attempt the wall recipe.
+/// Assumes that the structure and stack are of valid types for the recipe.
+/datum/element/uses_girder_wall_recipes/proc/attempt_recipe(obj/structure/structure, mob/living/user, obj/item/stack/stack, datum/girder_wall_recipe/recipe, is_material_recipe)
+ if (!check_recipe(structure, user, recipe))
+ return
+ if (!stack.tool_start_check(user, recipe.stack_amount))
+ return
+
+ user.visible_message(
+ message = span_notice("\The [user] start[user.p_s()] building a wall on \the [structure]."),
+ self_message = span_notice("You start building a wall on \the [structure]."),
+ blind_message = span_hear("You hear a series of clangs."),
+ )
+
+ structure.add_fingerprint(user)
+ stack.add_fingerprint(user)
+
+ if (!stack.use_tool(structure, user, recipe.make_delay, recipe.stack_amount, extra_checks = CALLBACK(src, PROC_REF(check_recipe), structure, user, recipe)))
+ return
+
+ var/atom/wall
+ if (ispath(recipe.wall_type, /turf))
+ var/turf/structure_turf = get_turf(structure)
+ wall = structure_turf.place_on_top(recipe.wall_type)
+ else if (ispath(recipe.wall_type, /obj))
+ wall = new recipe.wall_type(structure.drop_location())
+ else
+ CRASH("Attempted a girder wall recipe with an invalid wall type ([recipe.wall_type])")
+
+ user.visible_message(
+ message = span_notice("\The [user] finish[user.p_es()] building \a [wall] on \the [structure]."),
+ self_message = span_notice("You finish building \a [wall] on \the [structure]."),
+ )
+
+ structure.transfer_fingerprints_to(wall)
+ qdel(structure)
+
+ if (is_material_recipe)
+ wall.set_custom_materials(stack.mats_per_unit, recipe.stack_amount)
+
+/// Checks if the user can do the wall recipe.
+/datum/element/uses_girder_wall_recipes/proc/check_recipe(obj/structure/structure, mob/living/user, datum/girder_wall_recipe/recipe)
+ if(iswallturf(structure.loc) || (locate(/obj/structure/falsewall) in structure.loc.contents))
+ structure.balloon_alert(user, "wall already present!")
+ return FALSE
+ if (!ispath(recipe.wall_type, /obj/structure/tram))
+ if (!isfloorturf(structure.loc))
+ structure.balloon_alert(user, "need floor!")
+ return FALSE
+ else if (!(locate(/obj/structure/transport/linear/tram) in structure.loc.contents))
+ structure.balloon_alert(user, "need tram floor!")
+ return FALSE
+ if (!check_girder_state(structure, recipe))
+ return FALSE
+ return TRUE
+
+/// Checks if the girder state of the structure matches the required girder state of the wall recipe.
+/datum/element/uses_girder_wall_recipes/proc/check_girder_state(obj/structure/structure, datum/girder_wall_recipe/recipe)
+ if (istype(structure, /obj/structure/girder))
+ var/obj/structure/girder/girder = structure
+ if (girder.state != recipe.girder_state)
+ return FALSE
+ return TRUE
diff --git a/code/datums/girder_wall_recipe.dm b/code/datums/girder_wall_recipe.dm
new file mode 100644
index 00000000000..4e0845ffc35
--- /dev/null
+++ b/code/datums/girder_wall_recipe.dm
@@ -0,0 +1,27 @@
+/// Contains recipe data for constructing a specific type of wall on a girder.
+/// Only the [/datum/element/uses_girder_wall_recipes] should be using these.
+/datum/girder_wall_recipe
+ /// The wall type this recipe is for. Can be a turf or an object.
+ var/wall_type
+ /// The type of stack required for this recipe.
+ var/stack_type
+ /// The amount of stack items required for this recipe.
+ var/stack_amount
+ /// The [/obj/structure] type required for this recipe.
+ var/girder_type
+ /// The [/obj/structure/girder/var/state] required for this recipe.
+ /// Ignored if [var/girder] is not of type [/obj/structure/girder].
+ var/girder_state
+ /// The amount of time it takes to make this recipe in deciseconds.
+ var/make_delay
+ /// The starting balloon alert text for this recipe.
+ var/start_alert
+
+/datum/girder_wall_recipe/New(wall_type, stack_type, stack_amount, girder_type, girder_state, make_delay, start_alert)
+ src.wall_type = wall_type
+ src.stack_type = stack_type
+ src.stack_amount = stack_amount
+ src.girder_type = girder_type
+ src.girder_state = girder_state
+ src.make_delay = make_delay
+ src.start_alert = start_alert
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 2fea89c4605..1601626e044 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -81,32 +81,7 @@
AddElement(/datum/element/contextual_screentip_tools, tool_behaviors)
register_context()
-/obj/structure/barricade/wooden/item_interaction(mob/living/user, obj/item/stack/sheet/mineral/wood/our_wood, list/modifiers)
- if(user.combat_mode)
- return ITEM_INTERACT_SKIP_TO_ATTACK
-
- if(!istype(our_wood, /obj/item/stack/sheet/mineral/wood))
- return NONE
-
- if(our_wood.amount < 5)
- balloon_alert(user, "not enough wood!")
- to_chat(user, span_warning("You need at least five wooden planks to make a barricade!"))
- return ITEM_INTERACT_BLOCKING
-
-
- to_chat(user, span_notice("You start adding [our_wood] to [src]..."))
- playsound(src, 'sound/items/hammering_wood.ogg', 50, vary = TRUE)
- if(!do_after(user, 5 SECONDS, target=src))
- balloon_alert(user, "interrupted!")
- return ITEM_INTERACT_BLOCKING
-
- if(!our_wood.use(drop_amount))
- return ITEM_INTERACT_BLOCKING
-
- var/turf/cur_turf = get_turf(src)
- cur_turf.place_on_top(/turf/closed/wall/mineral/wood/nonmetal)
- qdel(src)
- return ITEM_INTERACT_SUCCESS
+ AddElement(/datum/element/uses_girder_wall_recipes)
/obj/structure/barricade/wooden/crowbar_act(mob/living/user, obj/item/tool)
balloon_alert(user, "deconstructing barricade...")
diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm
index f3394e21e19..0f96caf617e 100644
--- a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm
@@ -324,6 +324,7 @@
/obj/structure/foamedmetal/Initialize(mapload)
. = ..()
air_update_turf(TRUE, TRUE)
+ AddElement(/datum/element/uses_girder_wall_recipes)
/obj/structure/foamedmetal/Destroy()
air_update_turf(TRUE, FALSE)
@@ -349,37 +350,6 @@
to_chat(user, span_warning("You hit [src] but bounce off it!"))
playsound(src.loc, 'sound/items/weapons/tap.ogg', 100, TRUE)
-/obj/structure/foamedmetal/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
- ///A speed modifier for how fast the wall is build
- var/platingmodifier = 1
- if(HAS_TRAIT(user, TRAIT_QUICK_BUILD))
- platingmodifier = 0.7
- if(next_beep <= world.time)
- next_beep = world.time + 1 SECONDS
- playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
- add_fingerprint(user)
-
- if(!istype(W, /obj/item/stack/sheet))
- return ..()
-
- var/obj/item/stack/sheet/sheet_for_plating = W
- if(istype(sheet_for_plating, /obj/item/stack/sheet/iron))
- if(sheet_for_plating.get_amount() < 2)
- to_chat(user, span_warning("You need two sheets of iron to finish a wall on [src]!"))
- return
- to_chat(user, span_notice("You start adding plating to the foam structure..."))
- if (do_after(user, 40 * platingmodifier, target = src))
- if(!sheet_for_plating.use(2))
- return
- to_chat(user, span_notice("You add the plating."))
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall/metal_foam_base)
- transfer_fingerprints_to(T)
- qdel(src)
- return
-
- add_hiddenprint(user)
-
/// A metal foam variant which produces slightly sturdier walls.
/obj/effect/particle_effect/fluid/foam/metal/iron
name = "iron foam"
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index f51bfafa2e5..d8fde1fa91e 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -12,20 +12,27 @@
smoothing_groups = SMOOTH_GROUP_GIRDER
canSmoothWith = SMOOTH_GROUP_GIRDER + SMOOTH_GROUP_WALLS
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2)
+
+ /// The stack type required to construct and dropped upon deconstructing the girder.
+ var/stack_type = /obj/item/stack/sheet/iron
+ /// The stack amount required to construct and dropped upon deconstructing the girder.
+ var/stack_amount = 2
+ /// Always drops the stack in full, even when demolished rather than disassembled.
+ var/always_drop_stack = FALSE
+
+ /// The current state of the girder. Used for construction.
var/state = GIRDER_NORMAL
- var/girderpasschance = 20 // percentage chance that a projectile passes through the girder.
- var/can_displace = TRUE //If the girder can be moved around by wrenching it
- var/next_beep = 0 //Prevents spamming of the construction sound
- /// The material cost to construct something on the girder
- var/static/list/construction_cost = list(
- /obj/item/stack/sheet/iron = 2,
- /obj/item/stack/rods = 5,
- /obj/item/stack/sheet/plasteel = 2,
- /obj/item/stack/sheet/bronze = 2,
- /obj/item/stack/sheet/runed_metal = 1,
- /obj/item/stack/sheet/titaniumglass = 2,
- exotic_material = 2 // this needs to be refactored properly
- )
+ /// Whether the girder can be unanchored by wrenching it.
+ var/can_displace = TRUE
+ /// Whether the girder can be welded apart. (for cult and bronze girders)
+ var/can_weld_apart = FALSE
+
+ /// The percentage chance (0-100) that a projectile passes through the girder.
+ var/projectile_pass_chance = 20
+
+/obj/structure/girder/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/uses_girder_wall_recipes)
/obj/structure/girder/examine(mob/user)
. = ..()
@@ -39,378 +46,106 @@
. += span_notice("The bolts are wrenched in place.")
if(GIRDER_DISPLACED)
. += span_notice("The bolts are loosened, but the screws are holding [src] together.")
- if(GIRDER_DISASSEMBLED)
- . += span_notice("[src] is disassembled! You probably shouldn't be able to see this examine message.")
if(GIRDER_TRAM)
. += span_notice("[src] is designed for tram usage. Deconstructed with a screwdriver!")
+ if (can_weld_apart)
+ . += span_notice("The frame looks weak enough to be welded apart.")
+ else
+ . += span_notice("The frame could be sliced apart with a plasmacutter.")
-/obj/structure/girder/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
-
- add_fingerprint(user)
-
- if(istype(W, /obj/item/gun/energy/plasmacutter))
- balloon_alert(user, "slicing apart...")
- if(W.use_tool(src, user, 40, volume=100))
- if(state == GIRDER_TRAM)
- var/obj/item/stack/sheet/mineral/titanium/M = new (user.loc, 2)
- if(!QDELETED(M))
- M.add_fingerprint(user)
- else
- var/obj/item/stack/sheet/iron/M = new (loc, 2)
- if(!QDELETED(M))
- M.add_fingerprint(user)
- qdel(src)
+/obj/structure/girder/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if (user.combat_mode)
return
+ if (istype(tool, /obj/item/stack/sheet/plasteel))
+ if (try_construction_step(user, tool, 5 SECONDS, req_state = GIRDER_NORMAL, start_alert = "reinforcing frame..."))
+ replace_girder(/obj/structure/girder/reinforced)
+ return ITEM_INTERACT_SUCCESS
+ return ITEM_INTERACT_BLOCKING
- if(isstack(W))
- var/obj/item/stack/stack = W
- if(!stack.usable_for_construction)
- balloon_alert(user, "can't make walls with it!")
- return
-
- if(iswallturf(loc) || (locate(/obj/structure/falsewall) in src.loc.contents))
- balloon_alert(user, "wall already present!")
- return
- if(!isfloorturf(src.loc) && state != GIRDER_TRAM)
- balloon_alert(user, "need floor!")
- return
- if(state == GIRDER_TRAM)
- if(!locate(/obj/structure/transport/linear/tram) in src.loc.contents)
- balloon_alert(user, "need tram floors!")
- return
-
- make_wall(stack, user)
- return
-
- if(istype(W, /obj/item/pipe))
- var/obj/item/pipe/P = W
- if (P.pipe_type in list(0, 1, 5)) //simple pipes, simple bends, and simple manifolds.
- if(!user.transfer_item_to_turf(P, drop_location()))
- return
- balloon_alert(user, "inserted pipe")
- return
-
- return ..()
-
-/obj/structure/girder/proc/make_wall(obj/item/stack/stack, mob/user)
- var/speed_modifier = 1
- if(HAS_TRAIT(user, TRAIT_QUICK_BUILD))
- speed_modifier = 0.7
- if(next_beep <= world.time)
- next_beep = world.time + 10
- playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
-
- if(istype(stack, /obj/item/stack/rods))
- var/obj/item/stack/rods/rod = stack
- var/amount = construction_cost[rod.type]
- if(state == GIRDER_DISPLACED)
- if(rod.get_amount() < amount)
- balloon_alert(user, "need [amount] rods!")
- return
- balloon_alert(user, "concealing entrance...")
- if(do_after(user, 2 SECONDS, target = src))
- if(rod.get_amount() < amount)
- return
- rod.use(amount)
- var/obj/structure/falsewall/iron/FW = new (loc)
- transfer_fingerprints_to(FW)
- qdel(src)
- return
-
- if(state == GIRDER_REINF)
- balloon_alert(user, "need plasteel sheet!")
- return
-
- if(rod.get_amount() < amount)
- balloon_alert(user, "need [amount] rods!")
- return
- balloon_alert(user, "adding rods...")
- if(do_after(user, 4 SECONDS, target = src))
- if(rod.get_amount() < amount)
- return
- rod.use(amount)
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall/mineral/iron)
- transfer_fingerprints_to(T)
- qdel(src)
- return
-
- else if(istype(stack, /obj/item/stack/sheet/iron))
- var/amount = construction_cost[/obj/item/stack/sheet/iron]
- if(state == GIRDER_DISPLACED)
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "concealing entrance...")
- if(do_after(user, 20 * speed_modifier, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/obj/structure/falsewall/F = new (loc)
- transfer_fingerprints_to(F)
- qdel(src)
- return
- else if(state == GIRDER_REINF)
- balloon_alert(user, "need plasteel sheet!")
- return
- else if(state == GIRDER_TRAM)
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "adding plating...")
- if (do_after(user, 4 SECONDS, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/obj/structure/tram/alt/iron/tram_wall = new(loc)
- transfer_fingerprints_to(tram_wall)
- qdel(src)
- return
- else
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "adding plating...")
- if (do_after(user, 40 * speed_modifier, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall)
- transfer_fingerprints_to(T)
- qdel(src)
- return
-
- else if(istype(stack, /obj/item/stack/sheet/titaniumglass) && state == GIRDER_TRAM)
- var/amount = construction_cost[/obj/item/stack/sheet/titaniumglass]
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "adding panel...")
- if (do_after(user, 2 SECONDS, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/obj/structure/tram/tram_wall = new(loc)
- transfer_fingerprints_to(tram_wall)
- qdel(src)
- return
-
- else if(istype(stack, /obj/item/stack/sheet/plasteel))
- var/amount = construction_cost[/obj/item/stack/sheet/plasteel]
- if(state == GIRDER_DISPLACED)
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "concealing entrance...")
- if(do_after(user, 2 SECONDS, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/obj/structure/falsewall/reinforced/FW = new (loc)
- transfer_fingerprints_to(FW)
- qdel(src)
- return
- else if(state == GIRDER_REINF)
- amount = 1 // hur dur let's make plasteel have different construction amounts 4norasin
- if(stack.get_amount() < amount)
- return
- balloon_alert(user, "adding plating...")
- if(do_after(user, 50 * speed_modifier, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall/r_wall)
- transfer_fingerprints_to(T)
- qdel(src)
- return
- else
- amount = 1 // hur dur x2
- if(stack.get_amount() < amount)
- return
- balloon_alert(user, "reinforcing frame...")
- if(do_after(user, 60 * speed_modifier, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/obj/structure/girder/reinforced/R = new (loc)
- transfer_fingerprints_to(R)
- qdel(src)
- return
-
- else if(istype(stack, /obj/item/stack/sheet/mineral/plastitanium))
- if(state == GIRDER_REINF)
- if(stack.get_amount() < 1)
- return
- balloon_alert(user, "adding plating...")
- if(do_after(user, 50 * speed_modifier, target = src))
- if(stack.get_amount() < 1)
- return
- stack.use(1)
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall/r_wall/plastitanium)
- transfer_fingerprints_to(T)
- qdel(src)
- return
- // No return here because generic material construction handles making normal plastitanium walls
-
- else if(!stack.has_unique_girder && stack.material_type)
- if(istype(src, /obj/structure/girder/reinforced))
- balloon_alert(user, "need plasteel or plastitanium!")
- return
-
- var/material
- if(istype(stack, /obj/item/stack/sheet))
- var/obj/item/stack/sheet/sheet = stack
- material = sheet.construction_path_type
- var/amount = construction_cost["exotic_material"]
- if(state == GIRDER_TRAM)
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- var/tram_wall_type = text2path("/obj/structure/tram/alt/[material]")
- if(!tram_wall_type)
- balloon_alert(user, "need titanium glass or mineral!")
- return
- balloon_alert(user, "adding plating...")
- if (do_after(user, 4 SECONDS, target = src))
- if(stack.get_amount() < amount)
- return
- var/obj/structure/tram/tram_wall
- tram_wall = new tram_wall_type(loc)
- stack.use(amount)
- transfer_fingerprints_to(tram_wall)
- qdel(src)
- return
- if(state == GIRDER_DISPLACED)
- var/falsewall_type = text2path("/obj/structure/falsewall/[material]")
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "concealing entrance...")
- if(do_after(user, 2 SECONDS, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/obj/structure/falsewall/falsewall
- if(falsewall_type)
- falsewall = new falsewall_type (loc)
- else
- var/obj/structure/falsewall/material/mat_falsewall = new(loc)
- var/list/material_list = list()
- material_list[GET_MATERIAL_REF(stack.material_type)] = SHEET_MATERIAL_AMOUNT * 2
- if(material_list)
- mat_falsewall.set_custom_materials(material_list)
- falsewall = mat_falsewall
- transfer_fingerprints_to(falsewall)
- qdel(src)
- return
- else
- if(stack.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "adding plating...")
- if (do_after(user, 4 SECONDS, target = src))
- if(stack.get_amount() < amount)
- return
- stack.use(amount)
- var/turf/T = get_turf(src)
- if(stack.walltype)
- T.place_on_top(stack.walltype)
- else
- var/turf/newturf = T.place_on_top(/turf/closed/wall/material)
- var/list/material_list = list()
- material_list[GET_MATERIAL_REF(stack.material_type)] = SHEET_MATERIAL_AMOUNT * 2
- if(material_list)
- newturf.set_custom_materials(material_list)
-
- transfer_fingerprints_to(T)
- qdel(src)
- return
-
-// Screwdriver behavior for girders
/obj/structure/girder/screwdriver_act(mob/user, obj/item/tool)
- if(..())
- return TRUE
+ . = ITEM_INTERACT_BLOCKING
+ switch (state)
+ if (GIRDER_TRAM)
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_TRAM, start_alert = "disassembling frame..."))
+ deconstruct(disassembled = TRUE)
+ return ITEM_INTERACT_SUCCESS
+ if (GIRDER_DISPLACED)
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_DISPLACED, start_alert = "disassembling frame..."))
+ deconstruct(disassembled = TRUE)
+ return ITEM_INTERACT_SUCCESS
+ if (GIRDER_REINF)
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_REINF, start_alert = "unsecuring support struts..."))
+ state = GIRDER_REINF_STRUTS
+ return ITEM_INTERACT_SUCCESS
+ if (GIRDER_REINF_STRUTS)
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_REINF_STRUTS, start_alert = "securing support struts..."))
+ state = GIRDER_REINF
+ return ITEM_INTERACT_SUCCESS
- . = FALSE
- if(state == GIRDER_TRAM)
- balloon_alert(user, "disassembling frame...")
- if(tool.use_tool(src, user, 4 SECONDS, volume=100))
- if(state != GIRDER_TRAM)
- return
- state = GIRDER_DISASSEMBLED
- var/obj/item/stack/sheet/mineral/titanium/material = new (user.loc, 2)
- if (!QDELETED(material))
- material.add_fingerprint(user)
- qdel(src)
- return TRUE
-
- if(state == GIRDER_DISPLACED)
- balloon_alert(user, "disassembling frame...")
- if(tool.use_tool(src, user, 40, volume=100))
- if(state != GIRDER_DISPLACED)
- return
- state = GIRDER_DISASSEMBLED
- var/obj/item/stack/sheet/iron/M = new (loc, 2)
- if (!QDELETED(M))
- M.add_fingerprint(user)
- qdel(src)
- return TRUE
-
- else if(state == GIRDER_REINF)
- balloon_alert(user, "unsecuring support struts...")
- if(tool.use_tool(src, user, 40, volume=100))
- if(state != GIRDER_REINF)
- return
- state = GIRDER_REINF_STRUTS
- return TRUE
-
- else if(state == GIRDER_REINF_STRUTS)
- balloon_alert(user, "securing support struts...")
- if(tool.use_tool(src, user, 40, volume=100))
- if(state != GIRDER_REINF_STRUTS)
- return
- state = GIRDER_REINF
- return TRUE
-
-// Wirecutter behavior for girders
/obj/structure/girder/wirecutter_act(mob/user, obj/item/tool)
- . = ..()
- if(state == GIRDER_REINF_STRUTS)
- balloon_alert(user, "removing inner grille...")
- if(tool.use_tool(src, user, 40, volume=100))
- new /obj/item/stack/sheet/plasteel(get_turf(src))
- var/obj/structure/girder/G = new (loc)
- transfer_fingerprints_to(G)
- qdel(src)
- return TRUE
+ . = ITEM_INTERACT_BLOCKING
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_REINF_STRUTS, start_alert = "removing inner grille..."))
+ new /obj/item/stack/sheet/plasteel(get_turf(src))
+ replace_girder(/obj/structure/girder)
+ return ITEM_INTERACT_SUCCESS
/obj/structure/girder/wrench_act(mob/user, obj/item/tool)
- . = ..()
- if(state == GIRDER_DISPLACED)
- if(!isfloorturf(loc))
- balloon_alert(user, "needs floor!")
+ . = ITEM_INTERACT_BLOCKING
+ if (!can_displace)
+ balloon_alert(user, "no bolts!")
+ return
+ switch (state)
+ if (GIRDER_NORMAL)
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_NORMAL, start_alert = "unsecuring frame..."))
+ replace_girder(/obj/structure/girder/displaced)
+ return ITEM_INTERACT_SUCCESS
+ if (GIRDER_DISPLACED)
+ if (try_construction_step(user, tool, 4 SECONDS, req_state = GIRDER_DISPLACED, start_alert = "securing frame..."))
+ replace_girder(/obj/structure/girder)
+ return ITEM_INTERACT_SUCCESS
- balloon_alert(user, "securing frame...")
- if(tool.use_tool(src, user, 40, volume=100))
- var/obj/structure/girder/G = new (loc)
- transfer_fingerprints_to(G)
- qdel(src)
- return TRUE
- else if(state == GIRDER_NORMAL && can_displace)
- balloon_alert(user, "unsecuring frame...")
- if(tool.use_tool(src, user, 40, volume=100))
- var/obj/structure/girder/displaced/D = new (loc)
- transfer_fingerprints_to(D)
- qdel(src)
- return TRUE
+/obj/structure/girder/welder_act(mob/living/user, obj/item/tool)
+ . = ITEM_INTERACT_BLOCKING
+ // Plasmacutters can always slice apart girders.
+ if (!can_weld_apart && !istype(tool, /obj/item/gun/energy/plasmacutter))
+ balloon_alert(user, "can't weld apart!")
+ return
+ if (try_construction_step(user, tool, 4 SECONDS, start_alert = "slicing apart..."))
+ deconstruct(disassembled = TRUE)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/structure/girder/proc/try_construction_step(mob/living/user, obj/item/tool, delay, req_state, req_floor, start_alert, volume = 100)
+ if (!check_state(user, req_state, req_floor))
+ return FALSE
+
+ balloon_alert(user, start_alert)
+
+ add_fingerprint(user)
+ tool.add_fingerprint(user)
+
+ return tool.use_tool(src, user, delay, volume = volume, extra_checks = CALLBACK(src, PROC_REF(check_state), user, req_state, req_floor))
+
+/obj/structure/girder/proc/check_state(mob/living/user, req_state, req_anchored, req_floor)
+ if (!isnull(req_state) && req_state != state)
+ return FALSE
+ if (req_floor && !isfloorturf(loc))
+ balloon_alert(user, "needs a floor!")
+ return FALSE
+ return TRUE
+
+// We do this instead of state handling because of the large number of variables we would otherwise need to keep track of.
+// That said, ultimately, it would be a better solution for all of it to just be [/obj/structure/girder] at base.
+// For example right now if you paint a girder and use a wrench on it, it will magically lose that paint.
+/obj/structure/girder/proc/replace_girder(girder_type)
+ var/obj/structure/girder/new_girder = new girder_type(loc)
+ transfer_fingerprints_to(new_girder)
+ new_girder.update_integrity(new_girder.max_integrity * (atom_integrity / max_integrity))
+ qdel(src)
/obj/structure/girder/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
if((mover.pass_flags & PASSGRILLE) || isprojectile(mover))
- return prob(girderpasschance)
+ return prob(projectile_pass_chance)
/obj/structure/girder/CanAStarPass(to_dir, datum/can_pass_info/pass_info)
if(!density)
@@ -420,12 +155,14 @@
return FALSE
/obj/structure/girder/atom_deconstruct(disassembled = TRUE)
- var/remains = pick(/obj/item/stack/rods, /obj/item/stack/sheet/iron)
- new remains(loc)
+ if (disassembled || always_drop_stack)
+ new stack_type(drop_location(), stack_amount)
+ else
+ var/remains = pick(/obj/item/stack/rods, stack_type)
+ new remains(drop_location())
/obj/structure/girder/narsie_act()
- new /obj/structure/girder/cult(loc)
- qdel(src)
+ replace_girder(/obj/structure/girder/cult)
/obj/structure/girder/displaced
name = "displaced girder"
@@ -433,7 +170,7 @@
icon_state = "displaced"
anchored = FALSE
state = GIRDER_DISPLACED
- girderpasschance = 25
+ projectile_pass_chance = 25
max_integrity = 120
smoothing_flags = NONE
smoothing_groups = null
@@ -445,7 +182,7 @@
icon_state = "reinforced-0"
base_icon_state = "reinforced"
state = GIRDER_REINF
- girderpasschance = 0
+ projectile_pass_chance = 0
max_integrity = 350
/obj/structure/girder/tram
@@ -458,6 +195,7 @@
smoothing_flags = NONE
smoothing_groups = null
canSmoothWith = null
+ stack_type = /obj/item/stack/sheet/mineral/titanium
/obj/structure/girder/tram/corner
name = "tram frame corner"
@@ -474,43 +212,14 @@
smoothing_groups = null
canSmoothWith = null
custom_materials = list(/datum/material/runedmetal = SHEET_MATERIAL_AMOUNT)
-
-/obj/structure/girder/cult/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
- add_fingerprint(user)
- if(W.tool_behaviour == TOOL_WELDER)
- if(!W.tool_start_check(user, amount=1))
- return
-
- balloon_alert(user, "slicing apart...")
- if(W.use_tool(src, user, 40, volume=50))
- var/obj/item/stack/sheet/runed_metal/R = new(drop_location(), 1)
- transfer_fingerprints_to(R)
- qdel(src)
-
- else if(istype(W, /obj/item/stack/sheet/runed_metal))
- var/obj/item/stack/sheet/runed_metal/R = W
- var/amount = construction_cost[R.type]
- if(R.get_amount() < amount)
- balloon_alert(user, "need [amount] sheet!")
- return
- balloon_alert(user, "adding plating...")
- if(do_after(user, 5 SECONDS, target = src))
- if(R.get_amount() < amount)
- return
- R.use(amount)
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall/mineral/cult)
- qdel(src)
-
- else
- return ..()
+ stack_type = /obj/item/stack/sheet/runed_metal
+ stack_amount = 1
+ always_drop_stack = TRUE
+ can_weld_apart = TRUE
/obj/structure/girder/cult/narsie_act()
return
-/obj/structure/girder/cult/atom_deconstruct(disassembled = TRUE)
- new /obj/item/stack/sheet/runed_metal(drop_location())
-
/obj/structure/girder/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
switch(the_rcd.mode)
if(RCD_TURF)
@@ -550,32 +259,7 @@
smoothing_groups = null
canSmoothWith = null
custom_materials = list(/datum/material/bronze = SHEET_MATERIAL_AMOUNT * 2)
-
-/obj/structure/girder/bronze/attackby(obj/item/W, mob/living/user, list/modifiers, list/attack_modifiers)
- add_fingerprint(user)
- if(W.tool_behaviour == TOOL_WELDER)
- if(!W.tool_start_check(user, amount = 0, heat_required = HIGH_TEMPERATURE_REQUIRED))
- return
- balloon_alert(user, "slicing apart...")
- if(W.use_tool(src, user, 40, volume=50))
- var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2)
- transfer_fingerprints_to(B)
- qdel(src)
-
- else if(istype(W, /obj/item/stack/sheet/bronze))
- var/obj/item/stack/sheet/bronze/B = W
- var/amount = construction_cost[B.type]
- if(B.get_amount() < amount)
- balloon_alert(user, "need [amount] sheets!")
- return
- balloon_alert(user, "adding plating...")
- if(do_after(user, 5 SECONDS, target = src))
- if(B.get_amount() < amount)
- return
- B.use(amount)
- var/turf/T = get_turf(src)
- T.place_on_top(/turf/closed/wall/mineral/bronze)
- qdel(src)
-
- else
- return ..()
+ stack_type = /obj/item/stack/sheet/bronze
+ stack_amount = 1
+ always_drop_stack = TRUE
+ can_weld_apart = TRUE
diff --git a/code/game/turfs/closed/wall/mineral_walls.dm b/code/game/turfs/closed/wall/mineral_walls.dm
index d06f83e6853..02e40a4054e 100644
--- a/code/game/turfs/closed/wall/mineral_walls.dm
+++ b/code/game/turfs/closed/wall/mineral_walls.dm
@@ -190,6 +190,8 @@
desc = "A solidly wooden wall. It's a bit weaker than a wall made with metal."
girder_type = /obj/structure/barricade/wooden
hardness = 67 //a bit weaker than iron (60)
+ sheet_amount = 5
+ make_delay = 5 SECONDS
/turf/closed/wall/mineral/bamboo
name = "bamboo wall"
diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm
index 525b9540b65..2fd14fda880 100644
--- a/code/game/turfs/closed/wall/reinf_walls.dm
+++ b/code/game/turfs/closed/wall/reinf_walls.dm
@@ -12,6 +12,8 @@
sheet_type = /obj/item/stack/sheet/plasteel
sheet_amount = 1
girder_type = /obj/structure/girder/reinforced
+ girder_state = GIRDER_REINF
+ make_delay = 5 SECONDS
explosive_resistance = 2
rad_insulation = RAD_HEAVY_INSULATION
rust_resistance = RUST_RESISTANCE_REINFORCED
diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm
index ed29d3cebe4..2501b3767b3 100644
--- a/code/game/turfs/closed/walls.dm
+++ b/code/game/turfs/closed/walls.dm
@@ -24,16 +24,23 @@
///lower numbers are harder. Used to determine the probability of a hulk smashing through.
var/hardness = 40
var/slicing_duration = 100 //default time taken to slice the wall
- var/sheet_type = /obj/item/stack/sheet/iron
- var/sheet_amount = 2
- var/girder_type = /obj/structure/girder
/// A turf that will replace this turf when this turf is destroyed
var/decon_type
/// If we added a leaning component to ourselves
var/added_leaning = FALSE
-
var/list/dent_decals
+ /// The type of sheet this wall requires for construction and drops upon deconstruction.
+ var/sheet_type = /obj/item/stack/sheet/iron
+ /// The amount of sheets this wall requires for construction and drops upon deconstruction.
+ var/sheet_amount = 2
+ /// The type of girder this wall requires for construction and drops upon deconstruction.
+ var/girder_type = /obj/structure/girder
+ /// The girder state this wall requires for construction and drops upon deconstruction.
+ var/girder_state = GIRDER_NORMAL
+ /// How long this wall takes to make by using its sheet type on a girder.
+ var/make_delay = 4 SECONDS
+
/turf/closed/wall/Initialize(mapload)
. = ..()
if(!can_engrave)
diff --git a/tgstation.dme b/tgstation.dme
index d0fc3aa433b..88350149c0e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -573,6 +573,7 @@
#include "code\_globalvars\lists\disposals.dm"
#include "code\_globalvars\lists\engineering.dm"
#include "code\_globalvars\lists\ghost.dm"
+#include "code\_globalvars\lists\girder_wall_recipes.dm"
#include "code\_globalvars\lists\icons.dm"
#include "code\_globalvars\lists\keybindings.dm"
#include "code\_globalvars\lists\languages.dm"
@@ -844,6 +845,7 @@
#include "code\datums\embedding.dm"
#include "code\datums\emotes.dm"
#include "code\datums\ert.dm"
+#include "code\datums\girder_wall_recipe.dm"
#include "code\datums\hailer_phrase.dm"
#include "code\datums\holocall.dm"
#include "code\datums\hotkeys_help.dm"
@@ -1689,6 +1691,7 @@
#include "code\datums\elements\update_icon_blocker.dm"
#include "code\datums\elements\update_icon_updates_onmob.dm"
#include "code\datums\elements\uplink_reimburse.dm"
+#include "code\datums\elements\uses_girder_wall_recipes.dm"
#include "code\datums\elements\venomous.dm"
#include "code\datums\elements\volatile_gas_storage.dm"
#include "code\datums\elements\voucher_redeemer.dm"