Skip to content

Commit

Permalink
Machines now store components in contents + dumping inventory cleanup (
Browse files Browse the repository at this point in the history
…#9314)

* main pr

* tgstation/tgstation#60417

* fixes call to parent

* remove unused argument

* removecomment

* circuit deletion

* fix missing circuits

* tgstation/tgstation#55126

* crossed removal modernization
  • Loading branch information
Tsar-Salat authored Oct 20, 2023
1 parent ac3a600 commit 7f2ea1c
Show file tree
Hide file tree
Showing 23 changed files with 258 additions and 121 deletions.
105 changes: 80 additions & 25 deletions code/game/machinery/_machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Class Procs:
GLOB.machines += src

if(ispath(circuit, /obj/item/circuitboard))
circuit = new circuit
circuit = new circuit(src)
circuit.apply_default_parts(src)

if(processing_flags & START_PROCESSING_ON_INIT)
Expand Down Expand Up @@ -192,11 +192,9 @@ Class Procs:
GLOB.machines.Remove(src)
if(datum_flags & DF_ISPROCESSING) // A sizeable portion of machines stops processing before qdel
end_processing()
dropContents()
if(length(component_parts))
for(var/atom/A in component_parts)
qdel(A)
component_parts.Cut()
dump_inventory_contents()
QDEL_LIST(component_parts)
QDEL_NULL(circuit)
return ..()

/obj/machinery/proc/locate_machinery()
Expand Down Expand Up @@ -240,26 +238,65 @@ Class Procs:
//Update power
power_change()

/**
* Opens the machine.
*
* Will update the machine icon and any user interfaces currently open.
* Arguments:
* * drop - Boolean. Whether to drop any stored items in the machine. Does not include components.
*/
/obj/machinery/proc/open_machine(drop = TRUE)
SEND_SIGNAL(src, COMSIG_MACHINE_OPEN, drop)
state_open = TRUE
set_density(FALSE)
if(drop)
dropContents()
dump_inventory_contents()
update_icon()
updateUsrDialog()
ui_update()

/obj/machinery/proc/dropContents(list/subset = null)
var/turf/T = get_turf(src)
for(var/atom/movable/A in contents)
if(subset && !(A in subset))
continue
A.forceMove(T)
if(isliving(A))
var/mob/living/L = A
L.update_mobility()
/**
* Drop every movable atom in the machine's contents list, including any components and circuit.
*/
/obj/machinery/dump_contents()
// Start by calling the dump_inventory_contents proc. Will allow machines with special contents
// to handle their dropping.
dump_inventory_contents()

// Then we can clean up and drop everything else.
var/turf/this_turf = get_turf(src)
for(var/atom/movable/movable_atom in contents)
movable_atom.forceMove(this_turf)

// We'll have dropped the occupant, circuit and component parts as part of this.
set_occupant(null)
circuit = null
LAZYCLEARLIST(component_parts)

/**
* Drop every movable atom in the machine's contents list that is not a component_part.
*
* Proc does not drop components and will skip over anything in the component_parts list.
* Call dump_contents() to drop all contents including components.
* Arguments:
* * subset - If this is not null, only atoms that are also contained within the subset list will be dropped.
*/
/obj/machinery/proc/dump_inventory_contents(list/subset = null)
var/turf/this_turf = get_turf(src)
for(var/atom/movable/movable_atom in contents)
if(subset && !(movable_atom in subset))
continue

if(movable_atom in component_parts)
continue

movable_atom.forceMove(this_turf)
if(isliving(movable_atom))
var/mob/living/living_mob = movable_atom
living_mob.update_mobility()

if(occupant == movable_atom)
occupant = null

/obj/machinery/proc/can_be_occupant(atom/movable/am)
return occupant_typecache ? is_type_in_typecache(am, occupant_typecache) : isliving(am)
Expand Down Expand Up @@ -461,14 +498,18 @@ Class Procs:
deconstruct(TRUE)

/obj/machinery/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
on_deconstruction()
if(component_parts?.len)
spawn_frame(disassembled)
for(var/obj/item/I in component_parts)
I.forceMove(loc)
component_parts.Cut()
qdel(src)
if(flags_1 & NODECONSTRUCT_1)
return ..()

on_deconstruction()
if(!LAZYLEN(component_parts))
return ..() //We have no parts
spawn_frame(disassembled)

for(var/obj/item/I in component_parts)
I.forceMove(loc)
LAZYCLEARLIST(component_parts)
return ..()

/**
* Spawns a frame where this machine is. If the machine was not disassmbled, the
Expand Down Expand Up @@ -514,6 +555,17 @@ Class Procs:
if(A == occupant)
set_occupant(null)
update_icon()
updateUsrDialog()
return ..()

// The circuit should also be in component parts, so don't early return.
if(A == circuit)
circuit = null
if((A in component_parts) && !QDELETED(src))
component_parts.Remove(A)
// It would be unusual for a component_part to be qdel'd ordinarily.
deconstruct(FALSE)
return ..()

/obj/machinery/run_obj_armor(damage_amount, damage_type, damage_flag = NONE, attack_dir)
if(damage_flag == MELEE && damage_amount < damage_deflection)
Expand Down Expand Up @@ -632,7 +684,7 @@ Class Procs:
else
if(SEND_SIGNAL(W, COMSIG_TRY_STORAGE_TAKE, B, src))
component_parts += B
B.moveToNullspace()
B.forceMove(src)
SEND_SIGNAL(W, COMSIG_TRY_STORAGE_INSERT, A, null, null, TRUE)
component_parts -= A
to_chat(user, "<span class='notice'>[capitalize(A.name)] replaced with [B.name].</span>")
Expand Down Expand Up @@ -697,6 +749,9 @@ Class Procs:
. = ..()
if (gone == occupant)
set_occupant(null)
if(gone == circuit)
LAZYREMOVE(component_parts, gone)
circuit = null

/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
var/md5 = rustg_hash_string(RUSTG_HASH_MD5, AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
Expand Down
10 changes: 3 additions & 7 deletions code/game/machinery/computer/_computer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,13 @@
///Should the [icon_state]_broken overlay be shown as an emissive or regular overlay?
var/broken_overlay_emissive = FALSE

/obj/machinery/computer/Initialize(mapload, obj/item/circuitboard/C)
/obj/machinery/computer/Initialize(mapload)
. = ..()
QUEUE_SMOOTH(src)
QUEUE_SMOOTH_NEIGHBORS(src)
power_change()
if(!QDELETED(C))
qdel(circuit)
circuit = C
C.moveToNullspace()

/obj/machinery/computer/Destroy()
QDEL_NULL(circuit)
QUEUE_SMOOTH_NEIGHBORS(src)
return ..()

Expand Down Expand Up @@ -149,6 +144,8 @@
var/obj/structure/frame/computer/A = new /obj/structure/frame/computer(src.loc)
A.setDir(dir)
A.circuit = circuit
// Circuit removal code is handled in /obj/machinery/Exited()
circuit.forceMove(A)
A.setAnchored(TRUE)
if(machine_stat & BROKEN)
if(user)
Expand All @@ -164,7 +161,6 @@
to_chat(user, "<span class='notice'>You disconnect the monitor.</span>")
A.state = 4
A.icon_state = "4"
circuit = null
for(var/obj/C in src)
C.forceMove(loc)
qdel(src)
11 changes: 5 additions & 6 deletions code/game/machinery/computer/arcade.dm
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,16 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
return

/obj/machinery/computer/arcade/Initialize(mapload)
. = ..()
// If it's a generic arcade machine, pick a random arcade
// circuit board for it and make the new machine
// circuit board for it
if(!circuit)
var/list/gameodds = list(/obj/item/circuitboard/computer/arcade/battle = 49,
/obj/item/circuitboard/computer/arcade/orion_trail = 49,
/obj/item/circuitboard/computer/arcade/amputation = 2)
var/thegame = pick_weight(gameodds)
var/obj/item/circuitboard/CB = new thegame()
new CB.build_path(loc, CB)
return INITIALIZE_HINT_QDEL
circuit = pick_weight(gameodds)

. = ..()

Reset()

/obj/machinery/computer/arcade/proc/prizevend(mob/user)
Expand Down
42 changes: 39 additions & 3 deletions code/game/machinery/computer/buildandrepair.dm
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,45 @@
if(P.tool_behaviour == TOOL_SCREWDRIVER)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
var/obj/B = new circuit.build_path (loc, circuit)
B.setDir(dir)
transfer_fingerprints_to(B)

var/obj/machinery/new_machine = new circuit.build_path(loc)
new_machine.setDir(dir)
transfer_fingerprints_to(new_machine)

if(istype(new_machine, /obj/machinery/computer))
var/obj/machinery/computer/new_computer = new_machine

// Machines will init with a set of default components.
// Triggering handle_atom_del will make the machine realise it has lost a component_parts and then deconstruct.
// Move to nullspace so we don't trigger handle_atom_del, then qdel.
// Finally, replace new machine's parts with this frame's parts.
if(new_computer.circuit)
// Move to nullspace and delete.
new_computer.circuit.moveToNullspace()
QDEL_NULL(new_computer.circuit)
for(var/old_part in new_computer.component_parts)
var/atom/movable/movable_part = old_part
// Move to nullspace and delete.
movable_part.moveToNullspace()
qdel(movable_part)

// Set anchor state and move the frame's parts over to the new machine.
// Then refresh parts and call on_construction().
new_computer.anchored = anchored
new_computer.component_parts = list()

circuit.forceMove(new_computer)
new_computer.component_parts += circuit
new_computer.circuit = circuit

for(var/new_part in src)
var/atom/movable/movable_part = new_part
movable_part.forceMove(new_computer)
new_computer.component_parts += movable_part

new_computer.RefreshParts()
new_computer.on_construction()

qdel(src)
return
if(user.a_intent == INTENT_HARM)
Expand Down
46 changes: 31 additions & 15 deletions code/game/machinery/constructable_frame.dm
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,42 @@
return

if(P.tool_behaviour == TOOL_SCREWDRIVER)
var/component_check = 1
var/component_check = TRUE
for(var/R in req_components)
if(req_components[R] > 0)
component_check = 0
component_check = FALSE
break
if(component_check)
P.play_tool_sound(src)
var/obj/machinery/new_machine = new circuit.build_path(loc)
if(new_machine.circuit)
QDEL_NULL(new_machine.circuit)
new_machine.circuit = circuit
new_machine.setAnchored(anchored)
new_machine.on_construction()
for(var/obj/O in new_machine.component_parts)
qdel(O)
new_machine.component_parts = list()
for(var/obj/O in src)
O.moveToNullspace()
new_machine.component_parts += O
circuit.moveToNullspace()
new_machine.RefreshParts()
if(istype(new_machine))
// Machines will init with a set of default components. Move to nullspace so we don't trigger handle_atom_del, then qdel.
// Finally, replace with this frame's parts.
if(new_machine.circuit)
// Move to nullspace and delete.
new_machine.circuit.moveToNullspace()
QDEL_NULL(new_machine.circuit)
for(var/obj/old_part in new_machine.component_parts)
// Move to nullspace and delete.
old_part.moveToNullspace()
qdel(old_part)

// Set anchor state and move the frame's parts over to the new machine.
// Then refresh parts and call on_construction().

new_machine.anchored = anchored
new_machine.component_parts = list()

circuit.forceMove(new_machine)
new_machine.component_parts += circuit
new_machine.circuit = circuit

for(var/obj/new_part in src)
new_part.forceMove(new_machine)
new_machine.component_parts += new_part
new_machine.RefreshParts()

new_machine.on_construction()
qdel(src)
return

Expand Down Expand Up @@ -232,6 +247,7 @@
S.merge(NS)
if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore
components += part
part.forceMove(src)
to_chat(user, "<span class='notice'>You add [part] to [src].</span>")
if(added_components.len)
replacer.play_rped_sound()
Expand Down
Loading

0 comments on commit 7f2ea1c

Please sign in to comment.