[MIRROR] Don't initialize stack components inside machines [MDB IGNORE] (#19043)

Don't initialize stack components inside machines (#72863)

## About The Pull Request

An attempt at the
[Initiative](https://github.com/tgstation/dev-cycles-initiative/issues/29)
all types/subtypes of `obj/item/stack` no longer exist inside any
machine. Only during deconstruction is the stack created from the
circuit boards requested components.

Also moved the component printer & module duplicator circuitboards into
`machine_circuitboards.dm` so they all are in one place

I was unable to do this for circuitboards because that still needs to
exist so we can use `apply_default_parts()` on the machine. I tried to
do the whole datum circuitboard approach just like with stock parts but
i'm unsure about it so maybe next time

## Changelog
🆑
refactor: stack components no longer exist inside a machine's
component_parts
refactor: move component printer & module duplicator circuitboards into
machine_circuitboards.dm
/🆑

Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-02-03 15:26:01 -05:00
committed by GitHub
co-authored by SyncIt21
parent a2ddf56e62
commit d6f1a76dea
6 changed files with 135 additions and 133 deletions
+95 -73
View File
@@ -119,6 +119,8 @@
var/is_operational = TRUE
var/wire_compatible = FALSE
/// stack components inside this machine. Will be initialized and cached only when displaying the parts
var/list/cached_stack_parts = null
var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
var/panel_open = FALSE
var/state_open = FALSE
@@ -205,6 +207,8 @@
component_parts.Cut()
LAZYCLEARLIST(cached_stack_parts)
QDEL_NULL(circuit)
unset_static_power()
return ..()
@@ -805,13 +809,28 @@
return ..() //we don't have any parts.
spawn_frame(disassembled)
for(var/datum/part in component_parts)
for(var/part in component_parts)
if(istype(part, /datum/stock_part))
var/datum/stock_part/datum_part = part
new datum_part.physical_object_type(loc)
else
var/obj/item/obj_part = part
obj_part.forceMove(loc)
if(istype(obj_part, /obj/item/circuitboard/machine))
// if the stack parts were initialized in display_parts() then just move them outside
if(cached_stack_parts)
for(var/stack_component in cached_stack_parts)
var/obj/item/stack/stack_ref = cached_stack_parts[stack_component]
stack_ref.forceMove(loc)
cached_stack_parts.Cut()
// else create the stack parts by infering them from the circuit board requested components
else
var/obj/item/circuitboard/machine/board = obj_part
for(var/component in board.req_components)
if(!ispath(component, /obj/item/stack))
continue
var/obj/item/stack/stack_path = component
new stack_path(loc, board.req_components[component])
LAZYCLEARLIST(component_parts)
return ..()
@@ -972,29 +991,33 @@
* if the rped first picked up a tier 3 part AND THEN a tier 4 part
* tier 3 would be installed and the loop would break and check for the next required component thus
* completly ignoring the tier 4 component inside
* we also ignore stack components inside the RPED cause we dont exchange that
*/
var/list/part_list = replacer_tool.get_sorted_parts()
for(var/datum/primary_part_base as anything in component_parts)
var/list/part_list = replacer_tool.get_sorted_parts(ignore_stacks = TRUE)
if(!part_list.len)
return FALSE
for(var/primary_part_base as anything in component_parts)
//we exchanged all we could time to bail
if(!part_list.len)
break
var/current_rating
var/required_type
if (istype(primary_part_base, /datum/stock_part))
//we dont exchange circuitboards cause thats dumb
if(istype(primary_part_base, /obj/item/circuitboard))
continue
else if(istype(primary_part_base, /datum/stock_part))
var/datum/stock_part/primary_stock_part = primary_part_base
current_rating = primary_stock_part.tier
required_type = primary_stock_part.physical_object_base_type
else
var/obj/item/primary_stock_part_item = primary_part_base
current_rating = primary_stock_part_item.get_part_rating()
for(var/design_type in machine_board.req_components)
if(!ispath(primary_stock_part_item.type, design_type))
continue
required_type = design_type
if (isnull(required_type))
// Not an error, happens with circuitboards.
continue
if(ispath(primary_stock_part_item.type, design_type))
required_type = design_type
break
for(var/obj/item/secondary_part in part_list)
if(!istype(secondary_part, required_type))
@@ -1006,28 +1029,22 @@
if(checked_cell.rigged || checked_cell.corrupted)
checked_cell.charge = checked_cell.maxcharge
checked_cell.explode()
break
if(secondary_part.get_part_rating() > current_rating)
if(istype(secondary_part,/obj/item/stack)) //conveniently this will mean primary_part is also a stack and I will kill the first person to prove me wrong
var/obj/item/stack/primary_stack = primary_part_base
var/obj/item/stack/secondary_stack = secondary_part
var/used_amt = primary_stack.get_amount()
if(!secondary_stack.use(used_amt))
continue //if we don't have the exact amount to replace we don't
var/obj/item/stack/secondary_inserted = new secondary_stack.merge_type(null,used_amt)
component_parts += secondary_inserted
else
if(replacer_tool.atom_storage.attempt_remove(secondary_part, src))
if (istype(primary_part_base, /datum/stock_part))
var/stock_part_datum = GLOB.stock_part_datums_per_object[secondary_part.type]
if (isnull(stock_part_datum))
CRASH("[secondary_part] ([secondary_part.type]) did not have a stock part datum (was trying to find [primary_part_base])")
component_parts += stock_part_datum
part_list -= secondary_part //have to manually remove cause we are no longer refering replacer_tool.contents
qdel(secondary_part)
else
component_parts += secondary_part
secondary_part.forceMove(src)
part_list -= secondary_part //have to manually remove cause we are no longer refering replacer_tool.contents
//store name of part incase we qdel it below
var/secondary_part_name = secondary_part.name
if(replacer_tool.atom_storage.attempt_remove(secondary_part, src))
if (istype(primary_part_base, /datum/stock_part))
var/stock_part_datum = GLOB.stock_part_datums_per_object[secondary_part.type]
if (isnull(stock_part_datum))
CRASH("[secondary_part] ([secondary_part.type]) did not have a stock part datum (was trying to find [primary_part_base])")
component_parts += stock_part_datum
part_list -= secondary_part //have to manually remove cause we are no longer refering replacer_tool.contents
qdel(secondary_part)
else
component_parts += secondary_part
secondary_part.forceMove(src)
part_list -= secondary_part //have to manually remove cause we are no longer refering replacer_tool.contents
component_parts -= primary_part_base
@@ -1040,7 +1057,7 @@
physical_part = primary_part_base
replacer_tool.atom_storage.attempt_insert(physical_part, user, TRUE)
to_chat(user, span_notice("[capitalize(physical_part.name)] replaced with [secondary_part.name]."))
to_chat(user, span_notice("[capitalize(physical_part.name)] replaced with [secondary_part_name]."))
shouldplaysound = TRUE //Only play the sound when parts are actually replaced!
break
@@ -1050,59 +1067,64 @@
replacer_tool.play_rped_sound()
return TRUE
/// get the physical ref of the stack component used in displaying the machine parts
/obj/machinery/proc/get_stack(obj/item/stack/component, amount)
if(!cached_stack_parts)
cached_stack_parts = list()
if(cached_stack_parts[component])
return cached_stack_parts[component]
cached_stack_parts[component] = new component(src, amount)
return cached_stack_parts[component]
/obj/machinery/proc/display_parts(mob/user)
var/list/part_count = list()
for(var/component_part in component_parts)
var/component_name
var/obj/item/component_ref
if (istype(component_part, /datum/stock_part))
var/datum/stock_part/stock_part = component_part
component_name = initial(stock_part.physical_object_type.name)
component_ref = stock_part.physical_object_reference
else
var/atom/stock_part = component_part
component_name = stock_part.name
component_ref = component_part
for(var/obj/item/counted_part in part_count)
//e.g. 2 beakers though they have the same type are still 2 different objects so component_ref wont keep them unique so we look for that type ourselves and increment it
if(istype(counted_part, component_ref.type))
part_count[counted_part]++
component_ref = null
break
//looks like we already counted an type of this obj reference, time to bail
if(!component_ref)
continue
if(part_count[component_name])
part_count[component_name]++
if(part_count[component_ref])
part_count[component_ref]++
continue
part_count[component_ref] = 1
if(isstack(component_part))
var/obj/item/stack/stack_part = component_part
part_count[component_name] = stack_part.amount
else
part_count[component_name] = 1
// we infer the required stack stuff inside the machine from the circuitboards requested components
if(istype(component_ref, /obj/item/circuitboard/machine))
var/obj/item/circuitboard/machine/board = component_ref
for(var/component as anything in board.req_components)
if(!ispath(component, /obj/item/stack))
continue
var/obj/item/stack/stack_path = component
var/obj/item/stack/stack_ref = get_stack(stack_path, board.req_components[component])
part_count[stack_ref] = stack_ref.amount
var/list/printed_components = list()
var/text = span_notice("It contains the following parts:")
for(var/component_part_base in component_parts)
var/atom/component_part
var/component_name
if (istype(component_part_base, /datum/stock_part))
var/datum/stock_part/stock_part = component_part_base
component_part = stock_part.physical_object_reference
component_name = initial(stock_part.physical_object_type.name)
for(var/component_part in part_count)
var/part_name
if(isstack(component_part))
var/obj/item/stack/stack_ref = component_part
part_name = stack_ref.singular_name
else
component_part = component_part_base
component_name = component_part.name
if (!istype(component_part))
stack_trace("[component_part_base] is not an /atom or a /datum/stock_part (or did not make one)")
continue
if(printed_components[component_name])
continue //already printed so skip
var/part_name = component_name
if (isstack(component_part))
var/obj/item/stack/stack_part = component_part
part_name = stack_part.singular_name
text += span_notice("[icon2html(component_part, user)] [part_count[component_name]] [part_name]\s.")
printed_components[component_name] = TRUE
var/obj/item/part = component_part
part_name = part.name
text += span_notice("[icon2html(component_part, user)] [part_count[component_part]] [part_name]\s.")
return text
/obj/machinery/examine(mob/user)
+16 -35
View File
@@ -297,9 +297,8 @@
return
var/obj/item/storage/part_replacer/replacer = P
var/list/added_components = list()
var/play_sound = FALSE
var/list/part_list = replacer.get_sorted_parts() //parts sorted in order of tier
for(var/path in req_components)
var/target_path
if(ispath(path, /datum/stock_part))
@@ -314,34 +313,25 @@
if(istype(part,/obj/item/stack))
var/obj/item/stack/S = part
var/used_amt = min(round(S.get_amount()), req_components[path])
var/stack_name = S.singular_name
if(!used_amt || !S.use(used_amt))
continue
var/NS = new S.merge_type(src, used_amt)
added_components[NS] = path
req_components[path] -= used_amt
else
added_components[part] = path
if(replacer.atom_storage.attempt_remove(part, src))
req_components[path]--
to_chat(user, span_notice("You add [used_amt] [stack_name] to [src]."))
play_sound = TRUE
else if(replacer.atom_storage.attempt_remove(part, src))
var/stock_part_datum = GLOB.stock_part_datums_per_object[part.type]
if (!isnull(stock_part_datum))
components += stock_part_datum
qdel(part)
else
components += part
part.forceMove(src)
req_components[path]--
to_chat(user, span_notice("You add [part] to [src]."))
play_sound = TRUE
for(var/obj/item/part in added_components)
if(istype(part,/obj/item/stack))
var/obj/item/stack/incoming_stack = part
for(var/obj/item/stack/merge_stack in components)
if(incoming_stack.can_merge(merge_stack))
incoming_stack.merge(merge_stack)
if(QDELETED(incoming_stack))
break
if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore
var/stock_part_datum = GLOB.stock_part_datums_per_object[part.type]
if (!isnull(stock_part_datum))
components += stock_part_datum
qdel(part)
else
components += part
part.forceMove(src)
to_chat(user, span_notice("You add [part] to [src]."))
if(added_components.len)
if(play_sound)
replacer.play_rped_sound()
return
@@ -366,16 +356,7 @@
if(isstack(P))
var/obj/item/stack/S = P
var/used_amt = min(round(S.get_amount()), req_components[stock_part_path])
if(used_amt && S.use(used_amt))
var/obj/item/stack/NS = locate(S.merge_type) in components
if(!NS)
NS = new S.merge_type(src, used_amt)
components += NS
else
NS.add(used_amt)
req_components[stock_part_path] -= used_amt
to_chat(user, span_notice("You add [P] to [src]."))
return
@@ -92,12 +92,12 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells.
comp_path = def_components[comp_path]
if(ispath(comp_path, /obj/item/stack))
machine.component_parts += new comp_path(machine, comp_amt)
continue
else if (ispath(comp_path, /datum/stock_part))
var/stock_part_datum = GLOB.stock_part_datums[comp_path]
if (isnull(stock_part_datum))
CRASH("[comp_path] didn't have a matching stock part datum")
for (var/_ in 1 to comp_amt)
var/stock_part_datum = GLOB.stock_part_datums[comp_path]
if (isnull(stock_part_datum))
CRASH("[comp_path] didn't have a matching stock part datum")
machine.component_parts += stock_part_datum
else
for(var/component in 1 to comp_amt)
@@ -365,6 +365,23 @@
/obj/item/stack/sheet/plasteel = 5)
//Generic
/obj/item/circuitboard/machine/component_printer
name = "\improper Component Printer (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_SCIENCE
build_path = /obj/machinery/component_printer
req_components = list(
/datum/stock_part/matter_bin = 2,
/datum/stock_part/manipulator = 2,
)
/obj/item/circuitboard/machine/module_duplicator
name = "\improper Module Duplicator (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_SCIENCE
build_path = /obj/machinery/module_duplicator
req_components = list(
/datum/stock_part/matter_bin = 2,
/datum/stock_part/manipulator = 2,
)
/obj/item/circuitboard/machine/circuit_imprinter
name = "Circuit Imprinter"
+3 -3
View File
@@ -219,12 +219,12 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
/obj/item/storage/part_replacer/proc/get_sorted_parts()
/obj/item/storage/part_replacer/proc/get_sorted_parts(ignore_stacks = FALSE)
var/list/part_list = list()
//Assemble a list of current parts, then sort them by their rating!
for(var/obj/item/component_part in contents)
//No need to put circuit boards in this list
if(istype(component_part, /obj/item/circuitboard))
//No need to put circuit boards in this list or stacks when exchanging parts
if(istype(component_part, /obj/item/circuitboard) || (ignore_stacks && istype(component_part, /obj/item/stack)))
continue
part_list += component_part
//Sort the parts. This ensures that higher tier items are applied first.
@@ -218,15 +218,6 @@
return data
/obj/item/circuitboard/machine/component_printer
name = "\improper Component Printer (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_SCIENCE
build_path = /obj/machinery/component_printer
req_components = list(
/datum/stock_part/matter_bin = 2,
/datum/stock_part/manipulator = 2,
)
/obj/machinery/debug_component_printer
name = "debug component printer"
desc = "Produces components for the creation of integrated circuits."
@@ -529,12 +520,3 @@
data[initial(material_type.name)] = materials[material_type] * efficiency_coeff
return data
/obj/item/circuitboard/machine/module_duplicator
name = "\improper Module Duplicator (Machine Board)"
greyscale_colors = CIRCUIT_COLOR_SCIENCE
build_path = /obj/machinery/module_duplicator
req_components = list(
/datum/stock_part/matter_bin = 2,
/datum/stock_part/manipulator = 2,
)