Files
Bubberstation/code/game/objects/structures/windoor_assembly.dm
Leland KembleandGitHub 06608081d2 Moves a greater manyer morer things from attackby() to item_interaction() (#96739)
## About The Pull Request

50 files, plus additonal file that was necessary because I slightly
refactored windoor construction. This ended up like three and a half
times larger than most of the other ones, I really wasn't meaning for
that to happen. Maybe its because I more vigorously enforced the empty
line after every return thing. The only way to find out is to read 1700
lines of changes, and I don't feel like doing that again. I pinky
promise it all works, and I've tested every item changed individually.

Changes beyond conversion:
You can't welder down reinforced falsewalls anymore, pretty sure it was
an oversight because they're supposed to be taken down by wirecutters
You can right click to close gun lockers with an empty hand, because
otherwise you can't close the lockers at all if there's a gun in them
Meatspikes no longer runtime on construction due to the old trick of
balloon alert + qdel
Windoor assembly no longer SUCKS DICK!!, it's no longer storing
essentially a boolean in an undocumented number in a string, it no
longer requires a VERB to flip its direction.
on a related note, the creator of the windoor assembly construction
steps has been sent to live on a farm far out in the country

Also, a quick note about how these prs are gonna fuck everything up
until they're all together. There's a lot more places where `attackby()`
is directly called than I would have assumed, and given as those are
being changed to call `item_interaction()` potentially(usually) in a
different pr than the pr in which that atom's `attackby()` is actually
converted, that function's not going to work at all until both are
merged. The good news is that almost every instance this is happening,
it's pure convenience, where the user would have access to both items
anyway and could just manually call the attack chain by clicking them
together. Instances where this is not the case are being skipped over
until they can be packaged together to avoid the issue, but I'm not
bothering to do this on ones where the desync won't make an interaction
actually unusable, because that would require me to turn a 1700 line pr
into a 3500 line pr and I really was aiming for like 500

## Why It's Good For The Game

Ignore the paragraph about how I expect this to create a hostage
situation where the only fix to the bugs I make is to merge my other
prs, and instead think about how cool swing combat would be and how much
you want it

## Changelog
🆑
fix: you now can only use a wirecutter to take down a reinforced
falsewall
fix: meatspikes no longer runtime on construction
fix: you no longer have to use a verb that you can't use to flip windoor
assemblies

qol: you can right click a gun locker to close it

code: 50 files have been moved from attackby() to item_interaction()
/🆑
2026-07-16 15:07:43 +02:00

412 lines
14 KiB
Plaintext

#define WINDOOR_LEFT "l"
#define WINDOOR_RIGHT "r"
/obj/structure/windoor_assembly
icon = 'icons/obj/doors/windoor.dmi'
name = "windoor Assembly"
icon_state = "l_windoor_assembly01"
desc = "A small glass and wire assembly for windoors."
anchored = FALSE
density = FALSE
dir = NORTH
obj_flags = CAN_BE_HIT | BLOCKS_CONSTRUCTION_DIR | UNIQUE_RENAME | RENAME_NO_DESC
set_dir_on_move = FALSE
can_atmos_pass = ATMOS_PASS_PROC
custom_materials = list(/datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5)
/// Reference to the airlock electronics inside for determining window access.
var/obj/item/electronics/airlock/electronics = null
/// Player generated name string from renaming.
var/created_name = null
//Vars to help with the icon's name
///Does the windoor open to the left or right?
var/facing = WINDOOR_LEFT
///Whether or not this creates a secure windoor
var/secure = FALSE
/**
* Windoor (window door) assembly -Nodrak ----------- with comments clarifying what's actually happening, and how we know what step we're on
* Step 1: Create a windoor out of rglass -no variables modified. Destroy via welder
* Step 2: Add r-glass to the assembly to make a secure windoor (Optional) -tracked by secure, can be done anytime before cables_added is TRUE. Cannot be undone
* Step 3: Rotate or Flip the assembly to face and open the way you want -tracked by facing, can be done any time before anchoring via wrench right click
* Step 4: Wrench the assembly in place -tracked by anchored, no requisites, undone with wrench as well if cabling not yet inserted
* Step 5: Add cables to the assembly -tracked by cables_added, requires being anchored, undoable with wirecutters with no requisites until full completion
* Step 6: Set access for the door. -tracked by electronics, requires cabling to install electronics, undoable with screwdriver requiring cabling to remain
* Step 7: Crowbar the door to complete -requires cabling & electronics, not undoable. obviously.
*/
var/cables_added = FALSE
/obj/structure/windoor_assembly/Initialize(mapload, set_dir)
. = ..()
if(set_dir)
setDir(set_dir)
air_update_turf(TRUE, TRUE)
var/static/list/loc_connections = list(
COMSIG_ATOM_EXIT = PROC_REF(on_exit),
)
AddElement(/datum/element/connect_loc, loc_connections)
AddElement(/datum/element/simple_rotation, ROTATION_NEEDS_ROOM)
/obj/structure/windoor_assembly/Destroy()
set_density(FALSE)
air_update_turf(TRUE, FALSE)
return ..()
/obj/structure/windoor_assembly/Move()
var/turf/T = loc
. = ..()
move_update_air(T)
/obj/structure/windoor_assembly/update_icon_state()
icon_state = "[facing]_[secure ? "secure_" : ""]windoor_assembly[cables_added ? "02" : "01"]"
return ..()
/obj/structure/windoor_assembly/CanAllowThrough(atom/movable/mover, border_dir)
. = ..()
if(border_dir == dir)
return
if(istype(mover, /obj/structure/window))
var/obj/structure/window/moved_window = mover
return valid_build_direction(loc, moved_window.dir, is_fulltile = moved_window.fulltile)
if(istype(mover, /obj/structure/windoor_assembly) || istype(mover, /obj/machinery/door/window))
return valid_build_direction(loc, mover.dir, is_fulltile = FALSE)
/obj/structure/windoor_assembly/can_atmos_pass(turf/T, vertical = FALSE)
if(get_dir(loc, T) == dir)
return !density
else
return TRUE
/obj/structure/windoor_assembly/proc/on_exit(datum/source, atom/movable/leaving, direction)
SIGNAL_HANDLER
if(leaving.movement_type & PHASING)
return
if(leaving == src)
return // Let's not block ourselves.
if (leaving.pass_flags & pass_flags_self)
return
if (direction == dir && density)
leaving.Bump(src)
return COMPONENT_ATOM_BLOCK_EXIT
/obj/structure/windoor_assembly/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
//I really should have spread this out across more states but thin little windoors are hard to sprite.
add_fingerprint(user)
if(!cables_added)
//Adding plasteel makes the assembly a secure windoor assembly. Step 2 (optional) complete.
if(istype(tool, /obj/item/stack/sheet/plasteel) && !secure)
var/obj/item/stack/sheet/plasteel/reinforcement = tool
if(reinforcement.get_amount() < 2)
to_chat(user, span_warning("You need more plasteel to do this!"))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You start to reinforce the windoor with plasteel..."))
if(!do_after(user, 4 SECONDS, target = src))
return ITEM_INTERACT_BLOCKING
if(!src || secure || reinforcement.get_amount() < 2)
return ITEM_INTERACT_BLOCKING
reinforcement.use(2)
to_chat(user, span_notice("You reinforce the windoor."))
secure = TRUE
if(anchored)
name = "secure anchored windoor assembly"
else
name = "secure windoor assembly"
update_appearance()
return ITEM_INTERACT_SUCCESS
//Adding cable to the assembly. Step 5 complete.
if(istype(tool, /obj/item/stack/cable_coil) && anchored)
user.visible_message(span_notice("[user] wires the windoor assembly."), span_notice("You start to wire the windoor assembly..."))
if(!do_after(user, 4 SECONDS, target = src))
return ITEM_INTERACT_BLOCKING
if(!anchored || cables_added)
return ITEM_INTERACT_BLOCKING
var/obj/item/stack/cable_coil/wiring = tool
if(!wiring.use(1))
to_chat(user, span_warning("You need more cable to do this!"))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You wire the windoor."))
cables_added = TRUE
if(secure)
name = "secure wired windoor assembly"
else
name = "wired windoor assembly"
update_appearance()
return ITEM_INTERACT_SUCCESS
return NONE
//cables_added TRUE beyond this point
//Adding airlock electronics for access. Step 6 complete.
if(istype(tool, /obj/item/electronics/airlock))
tool.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))
return ITEM_INTERACT_BLOCKING
if(!user.transferItemToLoc(tool, src))
return ITEM_INTERACT_BLOCKING
if(!src || electronics)
tool.forceMove(drop_location())
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You install the airlock electronics."))
name = "near finished windoor assembly"
electronics = tool
return ITEM_INTERACT_SUCCESS
return NONE
//dissasemble entirely unworked assembly
/obj/structure/windoor_assembly/welder_act(mob/living/user, obj/item/tool)
if(cables_added)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!anchored)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!tool.tool_start_check(user, amount=1))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] disassembles the windoor assembly."),
span_notice("You start to disassemble the windoor assembly..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume = 50))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You disassemble the windoor assembly."))
var/obj/item/stack/sheet/rglass/dropped_glass = new (get_turf(src), 5)
if(!QDELETED(dropped_glass))
dropped_glass.add_fingerprint(user)
if(secure)
var/obj/item/stack/rods/dropped_rods = new (get_turf(src), 4)
if(!QDELETED(dropped_rods))
dropped_rods.add_fingerprint(user)
qdel(src)
return ITEM_INTERACT_SUCCESS
//secure or unsecure unworked assembly
/obj/structure/windoor_assembly/wrench_act(mob/living/user, obj/item/tool)
if(cables_added)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!anchored)
for(var/obj/machinery/door/window/competitor in loc)
if(competitor.dir == dir)
to_chat(user, span_warning("There is already a windoor in that location!"))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] secures the windoor assembly to the floor."),
span_notice("You start to secure the windoor assembly to the floor..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume=100))
return ITEM_INTERACT_BLOCKING
if(anchored)
return ITEM_INTERACT_BLOCKING
for(var/obj/machinery/door/window/competitor in loc)
if(competitor.dir == dir)
to_chat(user, span_warning("There is already a windoor in that location!"))
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You secure the windoor assembly."))
set_anchored(TRUE)
if(secure)
name = "secure anchored windoor assembly"
else
name = "anchored windoor assembly"
return ITEM_INTERACT_SUCCESS
//Unwrenching an unsecure assembly un-anchors it. Step 4 undone
user.visible_message(span_notice("[user] unsecures the windoor assembly to the floor."),
span_notice("You start to unsecure the windoor assembly to the floor..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume=100))
return ITEM_INTERACT_BLOCKING
if(!anchored)
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You unsecure the windoor assembly."))
set_anchored(FALSE)
if(secure)
name = "secure windoor assembly"
else
name = "windoor assembly"
return ITEM_INTERACT_SUCCESS
//Flips the windoor assembly, determines whether the door opens to the left or the right
/obj/structure/windoor_assembly/wrench_act_secondary(mob/living/user, obj/item/tool)
if(anchored)
return NONE
if(facing == WINDOOR_LEFT)
to_chat(usr, span_notice("The windoor will now slide to the right."))
facing = WINDOOR_RIGHT
else
facing = WINDOOR_LEFT
to_chat(usr, span_notice("The windoor will now slide to the left."))
update_appearance()
return ITEM_INTERACT_SUCCESS
//remove cabling
/obj/structure/windoor_assembly/wirecutter_act(mob/living/user, obj/item/tool)
if(!cables_added)
return ITEM_INTERACT_SKIP_TO_ATTACK
user.visible_message(span_notice("[user] cuts the wires from the airlock assembly."), \
span_notice("You start to cut the wires from airlock assembly..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume=100))
return ITEM_INTERACT_BLOCKING
if(!cables_added)
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You cut the windoor wires."))
new/obj/item/stack/cable_coil(get_turf(user), 1)
cables_added = FALSE
if(secure)
name = "secure anchored windoor assembly"
else
name = "anchored windoor assembly"
update_appearance()
return ITEM_INTERACT_SUCCESS
//remove airlock electronics
/obj/structure/windoor_assembly/screwdriver_act(mob/living/user, obj/item/tool)
if(!cables_added)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!electronics)
return ITEM_INTERACT_SKIP_TO_ATTACK
user.visible_message(span_notice("[user] removes the electronics from the airlock assembly."),
span_notice("You start to uninstall electronics from the airlock assembly..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume=100) && electronics)
return ITEM_INTERACT_BLOCKING
to_chat(user, span_notice("You remove the airlock electronics."))
name = "wired windoor assembly"
var/obj/item/electronics/airlock/scrap
scrap = electronics
electronics = null
scrap.forceMove(drop_location())
return ITEM_INTERACT_SUCCESS
//finishes door
/obj/structure/windoor_assembly/crowbar_act(mob/living/user, obj/item/tool)
if(!cables_added)
return ITEM_INTERACT_SKIP_TO_ATTACK
if(!electronics)
to_chat(usr, span_warning("The assembly is missing electronics!"))
return ITEM_INTERACT_BLOCKING
user.visible_message(span_notice("[user] pries the windoor into the frame."),
span_notice("You start prying the windoor into the frame..."))
if(!tool.use_tool(src, user, 4 SECONDS, volume=100) || !electronics)
return ITEM_INTERACT_BLOCKING
set_density(TRUE) //Shouldn't matter but just incase <-- in case what?
to_chat(user, span_notice("You finish the windoor."))
finish_door()
return ITEM_INTERACT_SUCCESS
/obj/structure/windoor_assembly/examine(mob/user)
. = ..()
if(!anchored)
. += span_notice("\The [src] can be [span_boldnotice("wrenched")] down.")
. += span_notice("\The [src] could also be [span_boldnotice("cut apart")] with a [span_boldnotice("welder")].")
return .
if(!cables_added)
. += span_notice("\The [src] needs [span_boldnotice("wiring")], or could be [span_boldnotice("un-wrenched")] from the floor.")
return .
if(!electronics)
. += span_notice("\The [src] needs [span_boldnotice("airlock electronics")] to continue installation, or [span_boldnotice("wirecutters")] to take apart.")
return .
. += span_notice("\The [src] is ready to be [span_boldnotice("levered")] into place with a [span_boldnotice("crowbar")].")
/obj/structure/windoor_assembly/proc/finish_door()
var/obj/machinery/door/window/windoor
if(secure)
windoor = new /obj/machinery/door/window/brigdoor(loc)
if(facing == WINDOOR_LEFT)
windoor.icon_state = "leftsecureopen"
windoor.base_state = "leftsecure"
else
windoor.icon_state = "rightsecureopen"
windoor.base_state = "rightsecure"
else
windoor = new /obj/machinery/door/window(loc)
if(facing == WINDOOR_LEFT)
windoor.icon_state = "leftopen"
windoor.base_state = "left"
else
windoor.icon_state = "rightopen"
windoor.base_state = "right"
windoor.setDir(dir)
windoor.set_density(FALSE)
if(created_name)
windoor.name = created_name
else if(electronics.passed_name)
windoor.name = sanitize(electronics.passed_name)
if(electronics.one_access)
windoor.req_one_access = electronics.accesses
else
windoor.req_access = electronics.accesses
if(electronics.unres_sides)
windoor.unres_sides = electronics.unres_sides
switch(dir)
if(NORTH,SOUTH)
windoor.unres_sides &= ~EAST
windoor.unres_sides &= ~WEST
if(EAST,WEST)
windoor.unres_sides &= ~NORTH
windoor.unres_sides &= ~SOUTH
windoor.unres_latch = TRUE
electronics.forceMove(windoor)
windoor.electronics = electronics
windoor.autoclose = TRUE
windoor.close()
windoor.update_appearance()
qdel(src)
/obj/structure/windoor_assembly/nameformat(input, user)
created_name = input
return input
/obj/structure/windoor_assembly/rename_reset()
created_name = initial(created_name)
#undef WINDOOR_LEFT
#undef WINDOOR_RIGHT