Files
Bubberstation/code/game/objects/structures/door_assembly.dm
SyncIt21 66f726dfe3 General code maintenance for rcd devices and their DEFINE file (#78443)
## About The Pull Request
The changes made can be best summarized into points

**1. Cleans up `code/_DEFINES/construction.dm`**

Looking at the top comment of this file 

0fb8b8b218/code/__DEFINES/construction.dm (L1)

One would expect stuff related to materials, rcd, and other construction
related stuff. Well this file is anything but

Why is there stuff related to food & crafting over here then?

0fb8b8b218/code/__DEFINES/construction.dm (L91-L94)

It gets worse why are global lists declared here?

0fb8b8b218/code/__DEFINES/construction.dm (L115)
There is a dedicated folder to store global lists i.e.
`code/_globalvars/lists` for lists like these. These clearly don't
belong here

On top of that a lot of construction related defines has been just
dumped here making it too large for it's purposes. which is why this
file has been scraped and it's
1. crafting related stuff have been moved to its
`code/_DEFINES/crafting.dm`
2. global lists for crafting moved to
`code/_globalvars/lists/crafting.dm`
3. Finally remaining construction related defines split apart into 4
file types under the new `code/_DEFINES/construction` folder
- `code/_DEFINES/construction/actions.dm` -> for wrench act or other
construction related actions
- `code/_DEFINES/construction/material.dm` -> contains your sheet
defines and cable & stack related values. Also merged
`code/_DEFINES/material.dm` with this file so it belongs in one place
- `code/_DEFINES/construction/rcd.dm` -> dedicated file for everything
rcd related
- `code/_DEFINES/construction/structures.dm` -> contains the
construction states for various stuff like walls, girders, floodlight
etc

By splitting this file into multiple meaningful define file names will
help in reducing merge conflicts and will aid in faster navigation so
this is the 1st part of this PR

**2. Debloats the `RCD.dm` file(Part 1)**

This uses the same concepts as above. i.e. moving defines into their
appropriate files for e.g.

0fb8b8b218/code/game/objects/items/rcd/RCD.dm (L170)

1. Global vars belong in the `code/_globalvars` folder so these vars and
their related functions to initialize them are moved into the
`code/_globalvars/rcd.dm` file
2. See this proc

0fb8b8b218/code/game/objects/items/rcd/RCD.dm (L200)
This proc does not belong to the `obj/item/construction/rcd` type it's a
global "helper function" this is an effect proc as it creates rcd
holograms so it has been moved to the `code/game/objects/effects/rcd.dm`
file which is a global effect that can be used by anyone

And with that we have moved these vars & procs into their correct places
& reduced the size of this file . We can go even further

**3. Debloats the `RCD.dm` file(Part 2)**
This deals with the large list which contains all the designs supported
by the RCD

0fb8b8b218/code/game/objects/items/rcd/RCD.dm (L42)

This list contains a lot of local defines. We can scrape some of them
and reduce the overall bulkiness & memory requirements of this list and
so the following defines

```
#define WINDOW_TYPE "window_type"
#define COMPUTER_DIR "computer_dir"
#define WALLFRAME_TYPE "wallframe_type"
#define FURNISH_TYPE "furnish_type"
#define AIRLOCK_TYPE "airlock_type"
#define TITLE "title"
#define ICON "icon"
#define CATEGORY_ICON_STATE  "category_icon_state"
#define CATEGORY_ICON_SUFFIX "category_icon_suffix"
#define TITLE_ICON "ICON=TITLE"
```

Have all been removed making this list a lot more cleaner. Why? because
a lot of these are just semantic sugar, we can infer the value of a lot
of these defines if we just know the type path of the structure the rcd
is trying to build for e.g. take these 2 defines

0fb8b8b218/code/game/objects/items/rcd/RCD.dm (L13-L15)

These defines tell the rcd UI the name and the icon it should display.
Rather than specifying these manually in the design we can infer them
like this

```
var/obj/design = /obj/structure/window  //let's say the rcd is trying to build an window
var/name = initial(design.name)         //we have inferred the name of the design without requiring TITLE define
var/icon = initial(design.icon_state)   //we have inferred the icon of the design without requiring ICON define
```

And so by using similar logic to the remaining defines we can eliminate
a lot of these local defines and reduce the overall size of this list.

The same logic applies to the different modes of construction, the
following defines

0fb8b8b218/code/__DEFINES/construction.dm (L186-L192)
Have all been removed and replaced with a single value `RCD_STRUCTURE`

All these modes follow the same principle when building them
1. First check the turf if the structure exists. If it does early return
2. If not create a new structure there and that's it

So rather than creating a new construction mode every time you want to
add a new design we can use this mode to apply this general approach
every time

The design list has also now been made into a global list rather than a
private static list. The big advantage to this is that the rcd asset
cache can now access this list and load the correct icons from the list
directly. This means you no longer have to manually specify what icons
you want to load which is the case currently.

0fb8b8b218/code/modules/asset_cache/assets/rcd.dm (L8-L9)
This has lead to the UI icons breaking twice now in the past
- #74194
- #77217

Hopefully this should never repeat itself again

**4. Other RCD like device changes**
- Fixed the broken silo link icon when the radial menu of the RLD was
opened
- replaced a lot of vars inside RLD with defines to save memory
- Small changes to `ui_act` across RCD, Plumbing RCD and RTD
- Removed unused vars in RCD and snowflaked code
- Moved a large majority of `ui_data()` to `ui_static_data()` making the
experience much faster

Just some general clean up going on here

**5. The Large majority of other code changes**
These are actually small code changes spread across multiple files.
These effect the `rcd_act()` & the `rcd_vals()` procs across all items.
Basically it
- Removes a large majority of `to_chat()` & `visible_message()` calls.
This was done because we already have enough visual feedback of what's
going on. When we construct a wall we don't need a `to_chat()` to tell
us you have a built a wall, we can clearly see that
- replaces the static string `"mode"` with a predefined constant
`RCD_DESIGN_MODE` to bring some standard to use across all cases

Should reduce chat spam and improve readability of code. 

**6. Airlock & Window names**
The rcd asset cache relies on the design name to be unique. So i filled
in the missing names for some airlocks & windows which are subjective
and open to change but must have some value

**7 Removes Microwave PDA upgrade**
The RCD should not be allowed to build this microwave considering how
quickly it can spawn multiple structures and more importantly as it's a
special multipurpose machine so you should spend some effort in printing
it's parts and acquiring tools to complete it. This upgrade makes
obsolete the need to carry an
- A RPED to install the parts
- A screwdriver to complete the frame
- The circuit board for the microwave 

The most important point to note here is that whenever an RPED/circuit
board is printed at an lathe it charges you "Lathe Tax". The RCD with
this upgrade would essentially bypass the need to "Pay Taxes" at these
lathes as you are just creating a circuit board from thin air. This
causes economy imbalance(10 cr per print) which scales up the more of
these machines you make so to avoid this let's end the problem here

Not to mention people would not find the need to print the circuit board
for a regular microwave now if they have an RCD because they can just
make this microwave type making the need for a regular microwave
completely pointless.

Just build a machine frame with the RCD and complete the microwave from
there

## Changelog
🆑
code: moved global vars, lists and helper procs for construction related
stuff to their appropriate files
code: reduced overall code size & memory of rcd design list and removed
unused defines
refactor: removed a ton of chat alerts for rcd related actions to help
reduce chat spam
refactor: some airlock & window default names have changed
fix: broken icon in radial menu of rld silo link
remove: removes microwave pda upgrade from RCD. It's a special machine
so spend some time in building it rather than shitting them out for free
with the RCD. Use the RCD upgrade to spawn a machine frame instead & go
from there
/🆑

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
2023-10-12 19:46:41 +02:00

395 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
/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)
. = ..()
var/doorname = ""
if(created_name)
doorname = ", written on it is '[created_name]'"
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(doorname)
. += span_notice("There is a small <i>paper</i> placard on the assembly labelled \"[doorname]\".")
/obj/structure/door_assembly/attackby(obj/item/W, mob/living/user, params)
if(istype(W, /obj/item/pen) && !user.combat_mode)
var/t = tgui_input_text(user, "Enter the name for the door", "Airlock Renaming", created_name, 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, 40, 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) && (!glass || !mineral))
var/obj/item/stack/sheet/G = W
if(G)
if(G.get_amount() >= 1)
if(!noglass)
if(!glass)
if(istype(G, /obj/item/stack/sheet/rglass) || istype(G, /obj/item/stack/sheet/glass))
playsound(src, 'sound/items/crowbar.ogg', 100, TRUE)
user.visible_message(span_notice("[user] adds [G.name] to the airlock assembly."), \
span_notice("You start to install [G.name] into the airlock assembly..."))
if(do_after(user, 40, target = src))
if(G.get_amount() < 1 || glass)
return
if(G.type == /obj/item/stack/sheet/rglass)
to_chat(user, span_notice("You install [G.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"
G.use(1)
glass = TRUE
if(!nomineral && !mineral)
if(istype(G, /obj/item/stack/sheet/mineral) && G.sheettype)
var/M = G.sheettype
var/mineralassembly = text2path("/obj/structure/door_assembly/door_assembly_[M]")
if(!ispath(mineralassembly))
to_chat(user, span_warning("You cannot add [G] to [src]!"))
return
if(G.get_amount() >= 2)
playsound(src, 'sound/items/crowbar.ogg', 100, TRUE)
user.visible_message(span_notice("[user] adds [G.name] to the airlock assembly."), \
span_notice("You start to install [G.name] into the airlock assembly..."))
if(do_after(user, 40, target = src))
if(G.get_amount() < 2 || mineral)
return
to_chat(user, span_notice("You install [M] plating into the airlock assembly."))
G.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
to_chat(user, span_warning("You need at least two sheets add a mineral cover!"))
else
to_chat(user, span_warning("You cannot add [G] to [src]!"))
else
to_chat(user, span_warning("You cannot add [G] to [src]!"))
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), \
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)
/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/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
var/turf/T = get_turf(src)
if(!disassembled)
material_amt = rand(2,4)
new material_type(T, material_amt)
if(glass)
if(disassembled)
if(heat_proof_finished)
new /obj/item/stack/sheet/rglass(T)
else
new /obj/item/stack/sheet/glass(T)
else
new /obj/item/shard(T)
if(mineral)
var/obj/item/stack/sheet/mineral/mineral_path = text2path("/obj/item/stack/sheet/mineral/[mineral]")
new mineral_path(T, 2)
qdel(src)
/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