Files
Bubberstation/code/game/objects/structures/door_assembly.dm
Ghom a28575aa82 [NO GBP] Fixing more issues with sand (you can make sand walls again, also ghost glass sheets?) (#93215)
## About The Pull Request
Apparently wall construction code is snowflaked and indented as fuck
(and the same goes for door assemblies). I'm not bothering refactoring
everything with them, only to reduce the indentation, changing a couple
vars and overall making it easier to work with them later. This includes
wall construction not being hardcoded to sheets but include the
possibility to use other kind of stacks as well (if you don't count the
snowflake interaction with iron rods). In layman's terms, this means you
can make walls made out of sand (distinct from sandstone) again.

Also I've done some small changes to the materials storage, so that it
can eject ores too if the material doesn't have a sheet type.

Also, I've been told there may be issues with broken, uninteractable
(probably not properly initialized) glass sheets beside the ORM. I'm not
100% sure about the deets, but it may have something to do with spawning
the glass on the same turf the ORM is listening to, when smelting sand,
causing some race conditions, so let's spawn it in nullspace

## Why It's Good For The Game
While I'm sure there may be more elegant solutions (just take a look at
the wall and door construction code, they both use text2path oh god!),
I'm just here to make things a lil' cleaner and be done with issues with
the fact that sand is made of sand.

## Changelog

🆑
fix: You can once again make sand walls.
fix: Deconstructing an autolathe with sand in it should now drop sand.
/🆑
2025-10-02 19:12:11 +03:00

391 lines
15 KiB
Plaintext

/obj/structure/door_assembly
name = "airlock assembly"
icon = 'icons/obj/doors/airlocks/station/public.dmi'
icon_state = "construction"
var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
anchored = FALSE
density = TRUE
max_integrity = 200
/// Airlock's current construction state
var/state = AIRLOCK_ASSEMBLY_NEEDS_WIRES
var/base_name = "Airlock"
var/created_name = null
var/mineral = null
var/obj/item/electronics/airlock/electronics = null
/// Do we perform the extra checks required for multi-tile (large) airlocks
var/multi_tile = FALSE
/// The type path of the airlock once completed (solid version)
var/airlock_type = /obj/machinery/door/airlock
/// The type path of the airlock once completed (glass version)
var/glass_type = /obj/machinery/door/airlock/glass
/// FALSE = glass can be installed. TRUE = glass is already installed.
var/glass = FALSE
/// Whether to heat-proof the finished airlock
var/heat_proof_finished = FALSE
/// If you're changing the airlock material, what is the previous type
var/previous_assembly = /obj/structure/door_assembly
/// Airlocks with no glass version, also cannot be modified with sheets
var/noglass = FALSE
/// Airlock with glass version, but cannot be modified with sheets
var/nomineral = FALSE
/// What type of material the airlock drops when deconstructed
var/material_type = /obj/item/stack/sheet/iron
/// Amount of material the airlock drops when deconstructed
var/material_amt = 4
/obj/structure/door_assembly/multi_tile
name = "large airlock assembly"
icon = 'icons/obj/doors/airlocks/multi_tile/public/glass.dmi'
overlays_file = 'icons/obj/doors/airlocks/multi_tile/public/overlays.dmi'
base_name = "large airlock"
glass_type = /obj/machinery/door/airlock/multi_tile/public/glass
airlock_type = /obj/machinery/door/airlock/multi_tile/public/glass
dir = EAST
multi_tile = TRUE
glass = TRUE
nomineral = TRUE
material_amt = 8
/obj/structure/door_assembly/Initialize(mapload)
. = ..()
update_appearance()
update_name()
/obj/structure/door_assembly/multi_tile/Initialize(mapload)
. = ..()
set_bounds()
update_overlays()
/obj/structure/door_assembly/multi_tile/Move()
. = ..()
set_bounds()
/obj/structure/door_assembly/examine(mob/user)
. = ..()
switch(state)
if(AIRLOCK_ASSEMBLY_NEEDS_WIRES)
if(anchored)
. += span_notice("The anchoring bolts are <b>wrenched</b> in place, but the maintenance panel lacks <i>wiring</i>.")
else
. += span_notice("The assembly is <b>welded together</b>, but the anchoring bolts are <i>unwrenched</i>.")
if(AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS)
. += span_notice("The maintenance panel is <b>wired</b>, but the circuit slot is <i>empty</i>.")
if(AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER)
. += span_notice("The circuit is <b>connected loosely</b> to its slot, but the maintenance panel is <i>unscrewed and open</i>.")
if(!mineral && !nomineral && !glass && !noglass)
. += span_notice("There are <i>empty</i> slots for glass windows and mineral covers.")
else if(!mineral && !nomineral && glass && !noglass)
. += span_notice("There are <i>empty</i> slots for mineral covers.")
else if(!glass && !noglass)
. += span_notice("There are <i>empty</i> slots for glass windows.")
if(created_name)
. += span_notice("There is a small <i>paper</i> placard on the assembly, written on it is '[created_name]'.")
/obj/structure/door_assembly/attackby(obj/item/W, mob/living/user, list/modifiers, list/attack_modifiers)
if(IS_WRITING_UTENSIL(W) && !user.combat_mode)
var/t = tgui_input_text(user, "Enter the name for the door", "Airlock Renaming", created_name, max_length = MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
else if((W.tool_behaviour == TOOL_WELDER) && (mineral || glass || !anchored ))
if(!W.tool_start_check(user, amount=1))
return
if(mineral)
var/obj/item/stack/sheet/mineral/mineral_path = text2path("/obj/item/stack/sheet/mineral/[mineral]")
user.visible_message(span_notice("[user] welds the [mineral] plating off the airlock assembly."), span_notice("You start to weld the [mineral] plating off the airlock assembly..."))
if(W.use_tool(src, user, 40, volume=50))
to_chat(user, span_notice("You weld the [mineral] plating off."))
new mineral_path(loc, 2)
var/obj/structure/door_assembly/PA = new previous_assembly(loc)
transfer_assembly_vars(src, PA)
else if(glass)
user.visible_message(span_notice("[user] welds the glass panel out of the airlock assembly."), span_notice("You start to weld the glass panel out of the airlock assembly..."))
if(W.use_tool(src, user, 40, volume=50))
to_chat(user, span_notice("You weld the glass panel out."))
if(heat_proof_finished)
new /obj/item/stack/sheet/rglass(get_turf(src))
heat_proof_finished = FALSE
else
new /obj/item/stack/sheet/glass(get_turf(src))
glass = 0
else if(!anchored)
user.visible_message(span_warning("[user] disassembles the airlock assembly."), \
span_notice("You start to disassemble the airlock assembly..."))
if(W.use_tool(src, user, 40, volume=50))
to_chat(user, span_notice("You disassemble the airlock assembly."))
deconstruct(TRUE)
else if(W.tool_behaviour == TOOL_WRENCH)
if(!anchored )
var/door_check = 1
for(var/obj/machinery/door/D in loc)
if(!D.sub_door)
door_check = 0
break
if(door_check)
user.visible_message(span_notice("[user] secures the airlock assembly to the floor."), \
span_notice("You start to secure the airlock assembly to the floor..."), \
span_hear("You hear wrenching."))
if(W.use_tool(src, user, 40, volume=100))
if(anchored)
return
to_chat(user, span_notice("You secure the airlock assembly."))
name = "secured airlock assembly"
set_anchored(TRUE)
else
to_chat(user, "There is another door here!")
else
user.visible_message(span_notice("[user] unsecures the airlock assembly from the floor."), \
span_notice("You start to unsecure the airlock assembly from the floor..."), \
span_hear("You hear wrenching."))
if(W.use_tool(src, user, 40, volume=100))
if(!anchored)
return
to_chat(user, span_notice("You unsecure the airlock assembly."))
name = "airlock assembly"
set_anchored(FALSE)
else if(istype(W, /obj/item/stack/cable_coil) && state == AIRLOCK_ASSEMBLY_NEEDS_WIRES && anchored )
if(!W.tool_start_check(user, amount=1))
return
user.visible_message(span_notice("[user] wires the airlock assembly."), \
span_notice("You start to wire the airlock assembly..."))
if(W.use_tool(src, user, 40, amount=1))
if(state != AIRLOCK_ASSEMBLY_NEEDS_WIRES)
return
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
to_chat(user, span_notice("You wire the airlock assembly."))
name = "wired airlock assembly"
else if((W.tool_behaviour == TOOL_WIRECUTTER) && state == AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS )
user.visible_message(span_notice("[user] cuts the wires from the airlock assembly."), \
span_notice("You start to cut the wires from the airlock assembly..."))
if(W.use_tool(src, user, 40, volume=100))
if(state != AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS)
return
to_chat(user, span_notice("You cut the wires from the airlock assembly."))
new/obj/item/stack/cable_coil(get_turf(user), 1)
state = AIRLOCK_ASSEMBLY_NEEDS_WIRES
name = "secured airlock assembly"
else if(istype(W, /obj/item/electronics/airlock) && state == AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS )
W.play_tool_sound(src, 100)
user.visible_message(span_notice("[user] installs the electronics into the airlock assembly."), \
span_notice("You start to install electronics into the airlock assembly..."))
if(do_after(user, 4 SECONDS, target = src))
if( state != AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS )
return
if(!user.transferItemToLoc(W, src))
return
to_chat(user, span_notice("You install the airlock electronics."))
state = AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER
name = "near finished airlock assembly"
electronics = W
else if((W.tool_behaviour == TOOL_CROWBAR) && state == AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER )
user.visible_message(span_notice("[user] removes the electronics from the airlock assembly."), \
span_notice("You start to remove electronics from the airlock assembly..."))
if(W.use_tool(src, user, 40, volume=100))
if(state != AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER)
return
to_chat(user, span_notice("You remove the airlock electronics."))
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
name = "wired airlock assembly"
var/obj/item/electronics/airlock/ae
if (!electronics)
ae = new/obj/item/electronics/airlock( loc )
else
ae = electronics
electronics = null
ae.forceMove(src.loc)
else if(istype(W, /obj/item/stack/sheet))
var/obj/item/stack/sheet/sheet = W
if(!glass && (istype(sheet, /obj/item/stack/sheet/rglass) || istype(sheet, /obj/item/stack/sheet/glass)))
if(noglass)
to_chat(user, span_warning("You cannot add [sheet] to [src]!"))
return
playsound(src, 'sound/items/tools/crowbar.ogg', 100, TRUE)
user.visible_message(span_notice("[user] adds [sheet.name] to the airlock assembly."), \
span_notice("You start to install [sheet.name] into the airlock assembly..."))
if(do_after(user, 4 SECONDS, target = src))
if(sheet.get_amount() < 1 || glass)
return
if(sheet.type == /obj/item/stack/sheet/rglass)
to_chat(user, span_notice("You install [sheet.name] windows into the airlock assembly."))
heat_proof_finished = 1 //reinforced glass makes the airlock heat-proof
name = "near finished heat-proofed window airlock assembly"
else
to_chat(user, span_notice("You install regular glass windows into the airlock assembly."))
name = "near finished window airlock assembly"
sheet.use(1)
glass = TRUE
return
if(istype(sheet, /obj/item/stack/sheet/mineral) && sheet.construction_path_type)
if(nomineral || mineral)
to_chat(user, span_warning("You cannot add [sheet] to [src]!"))
return
var/M = sheet.construction_path_type
var/mineralassembly = text2path("/obj/structure/door_assembly/door_assembly_[M]")
if(!ispath(mineralassembly))
to_chat(user, span_warning("You cannot add [sheet] to [src]!"))
return
if(sheet.get_amount() < 2)
to_chat(user, span_warning("You need at least two sheets add a mineral cover!"))
return
playsound(src, 'sound/items/tools/crowbar.ogg', 100, TRUE)
user.visible_message(span_notice("[user] adds [sheet.name] to the airlock assembly."), \
span_notice("You start to install [sheet.name] into the airlock assembly..."))
if(!do_after(user, 4 SECONDS, target = src) || sheet.get_amount() < 2 || mineral)
return
to_chat(user, span_notice("You install [M] plating into the airlock assembly."))
sheet.use(2)
var/obj/structure/door_assembly/MA = new mineralassembly(loc)
if(MA.noglass && glass) //in case the new door doesn't support glass. prevents the new one from reverting to a normal airlock after being constructed.
var/obj/item/stack/sheet/dropped_glass
if(heat_proof_finished)
dropped_glass = new /obj/item/stack/sheet/rglass(drop_location())
heat_proof_finished = FALSE
else
dropped_glass = new /obj/item/stack/sheet/glass(drop_location())
glass = FALSE
to_chat(user, span_notice("As you finish, a [dropped_glass.singular_name] falls out of [MA]'s frame."))
transfer_assembly_vars(src, MA, TRUE)
else if((W.tool_behaviour == TOOL_SCREWDRIVER) && state == AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER )
user.visible_message(span_notice("[user] finishes the airlock."), \
span_notice("You start finishing the airlock..."))
if(W.use_tool(src, user, 40, volume=100))
if(loc && state == AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER)
to_chat(user, span_notice("You finish the airlock."))
finish_door()
else
return ..()
update_name()
update_appearance()
/obj/structure/door_assembly/proc/finish_door()
var/obj/machinery/door/airlock/door
if(glass)
door = new glass_type( loc )
else
door = new airlock_type( loc )
door.setDir(dir)
door.unres_sides = electronics.unres_sides
door.electronics = electronics
door.heat_proof = heat_proof_finished
door.security_level = 0
if(electronics.shell)
door.AddComponent( \
/datum/component/shell, \
unremovable_circuit_components = list(new /obj/item/circuit_component/airlock, new /obj/item/circuit_component/airlock_access_event, new /obj/item/circuit_component/remotecam/airlock), \
capacity = SHELL_CAPACITY_LARGE, \
shell_flags = SHELL_FLAG_ALLOW_FAILURE_ACTION|SHELL_FLAG_REQUIRE_ANCHOR \
)
if(electronics.one_access)
door.req_one_access = electronics.accesses
else
door.req_access = electronics.accesses
if(created_name)
door.name = created_name
else if(electronics.passed_name)
door.name = sanitize(electronics.passed_name)
else
door.name = base_name
if(electronics.passed_cycle_id)
door.closeOtherId = electronics.passed_cycle_id
door.update_other_id()
if(door.unres_sides)
door.unres_sensor = TRUE
door.previous_airlock = previous_assembly
electronics.forceMove(door)
door.autoclose = TRUE
door.close()
door.update_appearance()
qdel(src)
return door
/obj/structure/door_assembly/update_overlays()
. = ..()
if(!glass)
. += get_airlock_overlay("fill_construction", icon, src, TRUE)
else
. += get_airlock_overlay("glass_construction", overlays_file, src, TRUE)
. += get_airlock_overlay("panel_c[state+1]", overlays_file, src, TRUE)
/obj/structure/door_assembly/update_name()
name = ""
switch(state)
if(AIRLOCK_ASSEMBLY_NEEDS_WIRES)
if(anchored)
name = "secured "
if(AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS)
name = "wired "
if(AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER)
name = "near finished "
name += "[heat_proof_finished ? "heat-proofed " : ""][glass ? "window " : ""][base_name] assembly"
return ..()
/obj/structure/door_assembly/proc/transfer_assembly_vars(obj/structure/door_assembly/source, obj/structure/door_assembly/target, previous = FALSE)
target.glass = source.glass
target.heat_proof_finished = source.heat_proof_finished
target.created_name = source.created_name
target.state = source.state
target.set_anchored(source.anchored)
if(previous)
target.previous_assembly = source.type
if(electronics)
target.electronics = source.electronics
source.electronics.forceMove(target)
target.update_appearance()
target.update_name()
qdel(source)
/obj/structure/door_assembly/atom_deconstruct(disassembled = TRUE)
var/turf/target_turf = get_turf(src)
if(!disassembled)
material_amt = rand(2,4)
new material_type(target_turf, material_amt)
if(glass)
if(disassembled)
if(heat_proof_finished)
new /obj/item/stack/sheet/rglass(target_turf)
else
new /obj/item/stack/sheet/glass(target_turf)
else
new /obj/item/shard(target_turf)
if(mineral)
var/obj/item/stack/sheet/mineral/mineral_path = text2path("/obj/item/stack/sheet/mineral/[mineral]")
new mineral_path(target_turf, 2)
/obj/structure/door_assembly/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
if(the_rcd.mode == RCD_DECONSTRUCT)
return list("delay" = 5 SECONDS, "cost" = 16)
return FALSE
/obj/structure/door_assembly/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data)
if(rcd_data["[RCD_DESIGN_MODE]"] == RCD_DECONSTRUCT)
qdel(src)
return TRUE
return FALSE