From 7f2ea1c1b7ffb8028530f7072b94666907193b39 Mon Sep 17 00:00:00 2001 From: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Date: Fri, 20 Oct 2023 08:53:52 -0400 Subject: [PATCH] Machines now store components in contents + dumping inventory cleanup (#9314) * main pr * https://github.com/tgstation/tgstation/pull/60417 * fixes call to parent * remove unused argument * removecomment * circuit deletion * fix missing circuits * https://github.com/tgstation/tgstation/pull/55126 * crossed removal modernization --- code/game/machinery/_machinery.dm | 105 +++++++++++++----- code/game/machinery/computer/_computer.dm | 10 +- code/game/machinery/computer/arcade.dm | 11 +- .../game/machinery/computer/buildandrepair.dm | 42 ++++++- code/game/machinery/constructable_frame.dm | 46 +++++--- code/game/machinery/suit_storage_unit.dm | 24 ++-- code/game/machinery/teleporter.dm | 4 +- .../items/circuitboards/circuitboard.dm | 29 ++++- code/game/objects/objs.dm | 4 + .../structures/crates_lockers/closets.dm | 2 +- code/modules/antagonists/swarmer/swarmer.dm | 2 +- .../atmospherics/machinery/atmosmachinery.dm | 1 - .../components/binary_devices/circulator.dm | 5 +- .../kitchen_machinery/deep_fryer.dm | 5 +- .../kitchen_machinery/gibber.dm | 2 +- .../kitchen_machinery/microwave.dm | 7 +- .../kitchen_machinery/processor.dm | 11 +- .../kitchen_machinery/smartfridge.dm | 52 ++++++--- code/modules/power/generator.dm | 3 +- .../chemistry/machinery/chem_dispenser.dm | 2 +- code/modules/research/server.dm | 2 - code/modules/vending/cola.dm | 5 +- code/modules/vending/snack.dm | 5 +- 23 files changed, 258 insertions(+), 121 deletions(-) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index fb713dc6abe30..e277af71f3dcb 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -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) @@ -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() @@ -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) @@ -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 @@ -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) @@ -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, "[capitalize(A.name)] replaced with [B.name].") @@ -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. diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index cde2b1c065c68..6c9a9abf01450 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -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 ..() @@ -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) @@ -164,7 +161,6 @@ to_chat(user, "You disconnect the monitor.") A.state = 4 A.icon_state = "4" - circuit = null for(var/obj/C in src) C.forceMove(loc) qdel(src) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 758be27d3c8da..bdfa906a18bd7 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -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) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index af5eb0246e729..e8c647db1ec4b 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -109,9 +109,45 @@ if(P.tool_behaviour == TOOL_SCREWDRIVER) P.play_tool_sound(src) to_chat(user, "You connect the monitor.") - 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) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index fe67fb7878ebf..caac7581b2adf 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -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 @@ -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, "You add [part] to [src].") if(added_components.len) replacer.play_rped_sound() diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 08df28c3d5b42..3f286fac82848 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -173,7 +173,7 @@ /obj/machinery/suit_storage_unit/Destroy() QDEL_NULL(wires) - dump_contents() + dump_inventory_contents() return ..() /obj/machinery/suit_storage_unit/update_overlays() @@ -212,7 +212,7 @@ . = ..() if(!is_operational && state_open) open_machine() - dump_contents() + dump_inventory_contents() update_appearance() /obj/machinery/suit_storage_unit/RefreshParts() @@ -222,8 +222,8 @@ laser_strength_hacked = 15 + (5 * (calculated_laser_rating)) //20 on T1, 35 on T4 laser_strength = 12 - (2 * (calculated_laser_rating)) //10 on T1, 4 on T4 -/obj/machinery/suit_storage_unit/proc/dump_contents() - dropContents() +/obj/machinery/suit_storage_unit/dump_inventory_contents() + . = ..() helmet = null suit = null mask = null @@ -246,7 +246,7 @@ /obj/machinery/suit_storage_unit/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) open_machine() - dump_contents() + dump_inventory_contents() spawn_frame(disassembled) for(var/obj/item/I in component_parts) I.forceMove(loc) @@ -456,7 +456,7 @@ qdel(contamination) open_machine(FALSE) if(mob_occupant) - dump_contents() + dump_inventory_contents() /obj/machinery/suit_storage_unit/proc/shock(mob/user, prb) if(!prob(prb)) @@ -473,12 +473,12 @@ to_chat(user, "[src]'s door won't budge!") return open_machine() - dump_contents() + dump_inventory_contents() /obj/machinery/suit_storage_unit/container_resist(mob/living/user) if(!locked) open_machine() - dump_contents() + dump_inventory_contents() return user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT @@ -492,7 +492,7 @@ "You successfully break out of [src]!") locked = FALSE open_machine() - dump_contents() + dump_inventory_contents() add_fingerprint(user) @@ -512,8 +512,8 @@ else I.play_tool_sound(src, 50) visible_message("[user] pulls out the contents of [src] outside!", "You pull [src]'s contents outside!") - dump_contents() - update_appearance() + dump_inventory_contents() + update_icon() return if(state_open && is_operational) if(istype(I, /obj/item/clothing/suit)) @@ -559,7 +559,7 @@ if(default_deconstruction_crowbar(I)) return if(default_pry_open(I)) - dump_contents() + dump_inventory_contents() return return ..() diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 7588bd6d19a83..b88c15bb69f28 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -103,10 +103,10 @@ /obj/machinery/teleport/hub/syndicate/Initialize(mapload) . = ..() - component_parts += new /obj/item/stock_parts/matter_bin/super(null) + var/obj/item/stock_parts/matter_bin/super/super_bin = new(src) + LAZYADD(component_parts, super_bin) RefreshParts() - /obj/machinery/teleport/station name = "teleporter station" desc = "The power control station for a bluespace teleporter. Used for toggling power, and can activate a test-fire to prevent malfunctions." diff --git a/code/game/objects/items/circuitboards/circuitboard.dm b/code/game/objects/items/circuitboards/circuitboard.dm index 8c1b92172b827..aa09a4dac3d94 100644 --- a/code/game/objects/items/circuitboards/circuitboard.dm +++ b/code/game/objects/items/circuitboards/circuitboard.dm @@ -16,6 +16,28 @@ var/build_path = null /obj/item/circuitboard/proc/apply_default_parts(obj/machinery/M) + if(LAZYLEN(M.component_parts)) + // This really shouldn't happen. If it somehow does, print out a stack trace and gracefully handle it. + stack_trace("apply_defauly_parts called on machine that already had component_parts: [M]") + + // Move to nullspace so you don't trigger handle_atom_del logic and remove existing parts. + for(var/obj/item/part in M.component_parts) + part.moveToNullspace(loc) + qdel(part) + + // List of components always contains the circuit board used to build it. + M.component_parts = list(src) + forceMove(M) + + if(M.circuit != src) + // This really shouldn't happen. If it somehow does, print out a stack trace and gracefully handle it. + stack_trace("apply_default_parts called from a circuit board that does not belong to machine: [M]") + + // Move to nullspace so you don't trigger handle_atom_del logic, remove old circuit, add new circuit. + M.circuit.moveToNullspace() + qdel(M.circuit) + M.circuit = src + return // Circuitboard/machine @@ -36,8 +58,7 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. if(!req_components) return - M.component_parts = list(src) // List of components always contains a board - moveToNullspace() + . = ..() for(var/comp_path in req_components) var/comp_amt = req_components[comp_path] @@ -48,10 +69,10 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. comp_path = def_components[comp_path] if(ispath(comp_path, /obj/item/stack)) - M.component_parts += new comp_path(null, comp_amt) + M.component_parts += new comp_path(M, comp_amt) else for(var/i in 1 to comp_amt) - M.component_parts += new comp_path(null) + M.component_parts += new comp_path(M) M.RefreshParts() diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 167899620ac9c..2b46d8dc41960 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -419,6 +419,10 @@ /obj/proc/on_object_saved(var/depth = 0) return "" +// Should move all contained objects to it's location. +/obj/proc/dump_contents() + CRASH("Unimplemented.") + /obj/handle_ricochet(obj/projectile/P) . = ..() if(. && ricochet_damage_mod) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 0c2d20f5d8344..d70ade784ac5b 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -173,7 +173,7 @@ return FALSE return TRUE -/obj/structure/closet/proc/dump_contents() +/obj/structure/closet/dump_contents() // Generate the contents if we haven't already if (!contents_initialised) PopulateContents() diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index 4a67870fee818..82d5f97117944 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -528,7 +528,7 @@ N.pixel_x = target.pixel_x N.pixel_y = target.pixel_y N.pixel_z = target.pixel_z - target.dropContents() + target.dump_contents() if(istype(target, /obj/machinery/computer)) var/obj/machinery/computer/C = target if(C.circuit) diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 73e6fb5c1b596..2a7638cd6222a 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -70,7 +70,6 @@ SSair.stop_processing_machine(src) SSair.pipenets_needing_rebuilt -= src - dropContents() if(pipe_vision_img) qdel(pipe_vision_img) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm index 467773a175272..f00ab5cd9f7c6 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm @@ -15,6 +15,7 @@ density = TRUE + circuit = /obj/item/circuitboard/machine/circulator var/flipped = 0 var/mode = CIRCULATOR_HOT @@ -24,10 +25,6 @@ /obj/machinery/atmospherics/components/binary/circulator/cold mode = CIRCULATOR_COLD -/obj/machinery/atmospherics/components/binary/circulator/Initialize(mapload) - .=..() - component_parts = list(new /obj/item/circuitboard/machine/circulator) - /obj/machinery/atmospherics/components/binary/circulator/ComponentInitialize() . = ..() AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS ) diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index 6f275fc30bd10..8a32770671cbe 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -32,6 +32,7 @@ God bless America. use_power = IDLE_POWER_USE idle_power_usage = 5 layer = BELOW_OBJ_LAYER + circuit = /obj/item/circuitboard/machine/deep_fryer var/obj/item/food/deepfryholder/frying //What's being fried RIGHT NOW? var/cook_time = 0 var/oil_use = 0.025 //How much cooking oil is used per second @@ -58,10 +59,6 @@ God bless America. . = ..() create_reagents(50, OPENCONTAINER) reagents.add_reagent(/datum/reagent/consumable/cooking_oil, 25) - component_parts = list() - component_parts += new /obj/item/circuitboard/machine/deep_fryer(null) - component_parts += new /obj/item/stock_parts/micro_laser(null) - RefreshParts() fry_loop = new(src, FALSE) /obj/machinery/deepfryer/Destroy() diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 4ac915e0d52c1..e835d08b41dbe 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -132,7 +132,7 @@ return /obj/machinery/gibber/proc/go_out() - dropContents() + dump_inventory_contents() update_icon() /obj/machinery/gibber/proc/startgibbing(mob/user) diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index 06b94e2fe9941..1a6f1a78569fc 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -324,11 +324,14 @@ if(prob(max(iron / 2, 33))) explosion(loc, 0, 1, 2) else - dropContents(ingredients) - ingredients.Cut() + dump_inventory_contents() after_finish_loop() +/obj/machinery/microwave/dump_inventory_contents() + . = ..() + ingredients.Cut() + /obj/machinery/microwave/proc/pre_fail() broken = 2 spark() diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index 7d4456178bf34..1661c45a71e72 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -138,28 +138,21 @@ var/mob/living/L = usr if(!(L.mobility_flags & MOBILITY_UI)) return - empty() + dump_inventory_contents() add_fingerprint(usr) /obj/machinery/processor/container_resist(mob/living/user) user.forceMove(drop_location()) user.visible_message("[user] crawls free of the processor!") -/obj/machinery/processor/proc/empty() - for (var/obj/O in src) - O.forceMove(drop_location()) - for (var/mob/M in src) - M.forceMove(drop_location()) - /obj/machinery/processor/slime name = "slime processor" desc = "An industrial grinder with a sticker saying appropriated for science department. Keep hands clear of intake area while operating." + circuit = /obj/item/circuitboard/machine/processor/slime var/sbacklogged = FALSE /obj/machinery/processor/slime/Initialize(mapload) . = ..() - var/obj/item/circuitboard/machine/B = new /obj/item/circuitboard/machine/processor/slime(null) - B.apply_default_parts(src) proximity_monitor = new(src, 1) /obj/machinery/processor/slime/adjust_item_drop_location(atom/movable/AM) diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 465028e272219..58ba0a587ac31 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -207,11 +207,15 @@ var/listofitems = list() for (var/I in src) + // We do not vend our own components. + if(I in component_parts) + continue + var/atom/movable/O = I if (!QDELETED(O)) - var/md5name = rustg_hash_string(RUSTG_HASH_MD5, O.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744 - if (listofitems[md5name]) // which is fixed in a version we cannot use due to ie8 incompatibility - listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating + var/md5name = rustg_hash_string(RUSTG_HASH_MD5, O.name) + if (listofitems[md5name]) + listofitems[md5name]["amount"]++ else listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1) sort_list(listofitems) @@ -240,23 +244,28 @@ if (params["amount"]) desired = text2num(params["amount"]) else - desired = input("How many items?", "How many items would you like to take out?", 1) as null|num - - if(!isnum_safe(desired) || desired <= 0) - return + desired = tgui_input_number(usr, "How many items would you like to take out?", "Release", max_value = 50) + if(!desired) + return FALSE if(QDELETED(src) || QDELETED(usr) || !usr.Adjacent(src)) // Sanity checkin' in case stupid stuff happens while we wait for input() - return + return FALSE - for(var/obj/item/O in src) - if(O.name == params["name"]) - dispense(O, usr) + for(var/obj/item/dispensed_item in src) + if(desired <= 0) + break + // Grab the first item in contents which name matches our passed name. + // format_text() is used here to strip \improper and \proper from both names, + // which is required for correct string comparison between them. + if(format_text(dispensed_item.name) == format_text(params["name"])) + if(dispensed_item in component_parts) + CRASH("Attempted removal of [dispensed_item] component_part from smartfridge via smartfridge interface.") + dispense(dispensed_item, usr) desired-- - . = TRUE - if(desired <= 0) - break - if (visible_contents && .) - update_icon() + + if (visible_contents) + update_appearance() + return TRUE // ---------------------------- @@ -273,9 +282,16 @@ /obj/machinery/smartfridge/drying_rack/Initialize(mapload) . = ..() - if(component_parts?.len) - component_parts.Cut() + + // Cache the old_parts first, we'll delete it after we've changed component_parts to a new list. + // This stops handle_atom_del being called on every part when not necessary. + var/list/old_parts = component_parts + component_parts = null + circuit = null + + QDEL_LIST(old_parts) + RefreshParts() /obj/machinery/smartfridge/drying_rack/on_deconstruction() new /obj/item/stack/sheet/wood(drop_location(), 10) diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index c946ed48ea494..d63902f719e78 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -5,6 +5,8 @@ density = TRUE use_power = NO_POWER_USE + circuit = /obj/item/circuitboard/machine/generator + var/obj/machinery/atmospherics/components/binary/circulator/cold_circ var/obj/machinery/atmospherics/components/binary/circulator/hot_circ @@ -19,7 +21,6 @@ connect_to_network() SSair.start_processing_machine(src) update_appearance() - component_parts = list(new /obj/item/circuitboard/machine/generator) /obj/machinery/power/generator/examine() . = ..() diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 8f1e9728edaba..3c48bb80900bc 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -483,7 +483,7 @@ /datum/reagent/toxin/staminatoxin ) -/obj/machinery/chem_dispenser/drinks/fullupgrade //fully ugpraded stock parts, emagged +/obj/machinery/chem_dispenser/drinks/fullupgrade //fully upgraded stock parts, emagged desc = "Contains a large reservoir of soft drinks. This model has had its safeties shorted out." obj_flags = CAN_BE_HIT | EMAGGED flags_1 = NODECONSTRUCT_1 diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index 0acd6edf9a73c..2ea70ed407f99 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -47,8 +47,6 @@ name += " [uppertext(num2hex(server_id, -1))]" //gives us a random four-digit hex number as part of the name. Y'know, for fluff. SSresearch.servers |= src stored_research = SSresearch.science_tech - var/obj/item/circuitboard/machine/B = new /obj/item/circuitboard/machine/rdserver(null) - B.apply_default_parts(src) // The +10 is so the sparks work RefreshParts() diff --git a/code/modules/vending/cola.dm b/code/modules/vending/cola.dm index 132e1053efe64..5c42add675a49 100644 --- a/code/modules/vending/cola.dm +++ b/code/modules/vending/cola.dm @@ -32,9 +32,12 @@ name = "\improper Random Drinkies" icon_state = "random_cola" desc = "Uh oh!" + circuit = null /obj/machinery/vending/cola/random/Initialize(mapload) - ..() + // No need to call parent, we're not doing anything with this machine. Just picking a new type of machine to use, spawning it and deleting ourselves. + SHOULD_CALL_PARENT(FALSE) + var/T = pick(subtypesof(/obj/machinery/vending/cola) - /obj/machinery/vending/cola/random) new T(loc) return INITIALIZE_HINT_QDEL diff --git a/code/modules/vending/snack.dm b/code/modules/vending/snack.dm index 2da0dfe0a006d..981f8110d34db 100644 --- a/code/modules/vending/snack.dm +++ b/code/modules/vending/snack.dm @@ -92,9 +92,12 @@ name = "\improper Random Snackies" icon_state = "random_snack" desc = "Uh oh!" + circuit = null /obj/machinery/vending/snack/random/Initialize(mapload) - ..() + // No need to call parent, we're not doing anything with this machine. Just picking a new type of machine to use, spawning it and deleting ourselves. + SHOULD_CALL_PARENT(FALSE) + var/T = pick(subtypesof(/obj/machinery/vending/snack) - /obj/machinery/vending/snack/random) new T(loc) return INITIALIZE_HINT_QDEL