Unit test material checks are now performed on all crafting recipes by default. All stack recipes now transfer mats to the results (#92620)

## About The Pull Request
Extends the part of the crafting unit test that ensures consistency
between the total mats of the components of a recipe (or rather, the
result of said recipe) and a generic instance of the same type as its
result, previously only implemented on food recipes.

## Why It's Good For The Game
This ensures a degree of consistency with the material composition of
various objects in the game. I couldn't do it in the original PR as that
one was too big already and it took months to get it merged, and have
the relative bugs fixed.

Currently a WIP as I slowly deal with the unit test reports.

## Changelog

🆑
refactor: Follow-up to the crafting/material refactor from months ago.
All objects crafted with stacks now inherit their mat composition (not
necessarily the effects and color) by default, while previously only a
few things like chair, sinks and toilets did. Report any object looking
or behaving weirdly as a result.
fix: The material composition of ammo boxes is no longer a 1/10 of what
it's supposed to be. It was a shitty hack to make it harder to recycle
empty ammo boxes. Instead, they lose materials as they're emptied now.
/🆑
This commit is contained in:
Ghom
2025-12-02 18:29:01 -05:00
committed by GitHub
parent 085007eae1
commit 0b0c5ea91e
272 changed files with 850 additions and 280 deletions
+28 -20
View File
@@ -94,12 +94,11 @@
if(merge)
. = INITIALIZE_HINT_LATELOAD
var/materials_mult = amount
if(LAZYLEN(mat_override))
materials_mult *= mat_amt
mats_per_unit = mat_override
if(LAZYLEN(mats_per_unit))
initialize_materials(mats_per_unit, materials_mult)
mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats_per_unit, mat_amt)
initialize_materials(mats_per_unit, amount)
recipes = get_main_recipes().Copy()
if(material_type)
@@ -120,6 +119,10 @@
/obj/item/stack/LateInitialize()
merge_with_loc()
/obj/item/stack/Destroy()
mats_per_unit = null
return ..()
/obj/item/stack/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
if((!throwing || throwing.target_turf == loc) && old_loc != loc && (flags_1 & INITIALIZED_1))
@@ -160,11 +163,6 @@
other_stack = find_other_stack(already_found, TRUE)
return TRUE
/obj/item/stack/apply_material_effects(list/materials)
. = ..()
if(amount)
mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(materials, 1/amount)
/obj/item/stack/blend_requirements()
if(is_cyborg)
to_chat(usr, span_warning("[src] is too integrated into your chassis and can't be ground up!"))
@@ -417,7 +415,7 @@
#undef FULL_LIST
/// Makes the item with the given recipe.
/obj/item/stack/proc/make_item(mob/builder, datum/stack_recipe/recipe, multiplier)
/obj/item/stack/proc/make_item(mob/builder, datum/stack_recipe/recipe, multiplier = 1)
if(get_amount() < 1 && !is_cyborg) //sanity check as this shouldn't happen
qdel(src)
return
@@ -456,8 +454,6 @@
return
created = covered_turf.place_on_top(recipe.result_type, flags = CHANGETURF_INHERIT_AIR)
builder.balloon_alert(builder, "placed [ispath(recipe.result_type, /turf/open) ? "floor" : "wall"]")
if((recipe.crafting_flags & CRAFT_APPLIES_MATS) && LAZYLEN(mats_per_unit))
created.set_custom_materials(mats_per_unit, recipe.req_amount / recipe.res_amount)
else
created = new recipe.result_type(builder.drop_location())
@@ -468,17 +464,30 @@
if(ismovable(created))
created.setDir(builder.dir)
created.on_craft_completion(list(used_stack), null, builder)
qdel(used_stack) //you've outlived your purpose
builder.investigate_log("crafted [recipe.title]", INVESTIGATE_CRAFTING)
// Apply mat datums
if((recipe.crafting_flags & CRAFT_APPLIES_MATS) && LAZYLEN(mats_per_unit))
if(LAZYLEN(mats_per_unit) && !(recipe.crafting_flags & CRAFT_NO_MATERIALS))
var/list/result_mats = mats_per_unit.Copy()
for(var/mat in recipe.removed_mats)
var/to_remove = recipe.removed_mats[mat]
var/datum/material/ref_mat = locate(mat) in result_mats
if(!ref_mat)
continue
if(result_mats[ref_mat] < to_remove)
result_mats -= ref_mat
else
result_mats[ref_mat] -= to_remove
if(isstack(created))
var/obj/item/stack/crafted_stack = created
crafted_stack.set_custom_materials(mats_per_unit, (recipe.req_amount / recipe.res_amount) * crafted_stack.amount)
crafted_stack.mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(result_mats)
update_custom_materials()
else
created.set_custom_materials(mats_per_unit, recipe.req_amount / recipe.res_amount)
created.set_custom_materials(result_mats, recipe.req_amount * multiplier)
qdel(used_stack) //you've outlived your purpose
// We could be qdeleted - like if it's a stack and has already been merged
if(QDELETED(created))
@@ -573,11 +582,10 @@
if (amount < used)
return FALSE
amount -= used
if(check && is_zero_amount(delete_if_zero = TRUE))
return TRUE
update_custom_materials()
update_appearance()
update_weight()
if(!is_zero_amount(delete_if_zero = check))
update_custom_materials()
update_appearance()
update_weight()
return TRUE
/obj/item/stack/tool_use_check(mob/living/user, amount, heat_required)