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
@@ -6,7 +6,7 @@
icon_state = "improvshell"
caliber = CALIBER_JUNK
projectile_type = /obj/projectile/bullet/junk
custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*2, /datum/material/glass=SMALL_MATERIAL_AMOUNT*1)
custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 2, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 1)
// Junk Shell Spawner; used to spawn in our random shells upon crafting
@@ -64,6 +64,7 @@
base_icon_state = "rod_sharp"
projectile_type = /obj/projectile/bullet/rebar
newtonian_force = 1.5
custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT)
/obj/item/ammo_casing/rebar/Initialize(mapload)
. = ..()
@@ -104,6 +105,7 @@
icon_state = "rod_healium"
base_icon_state = "rod_healium"
projectile_type = /obj/projectile/bullet/rebar/healium
custom_materials = null
/// How many seconds of healing/sleeping action we have left, once all are spent the bolt dissolves
var/heals_left = 6 SECONDS
@@ -181,3 +183,4 @@
base_icon_state = "paperball"
projectile_type = /obj/projectile/bullet/paperball
newtonian_force = 0.5
custom_materials = list(/datum/material/paper = HALF_SHEET_MATERIAL_AMOUNT / 2)
@@ -66,6 +66,7 @@
desc = "A shotgun shell rigged with CMC technology, which launches a massive slug when fired."
icon_state = "mshell"
projectile_type = /obj/projectile/bullet/cannonball/meteorslug
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 8, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 4)
/obj/item/ammo_casing/shotgun/pulseslug
name = "pulse slug"
@@ -74,6 +75,7 @@
would have difficulty with."
icon_state = "pshell"
projectile_type = /obj/projectile/beam/pulse/shotgun
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.1, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 1.2)
/obj/item/ammo_casing/shotgun/frag12
name = "FRAG-12 slug"
@@ -161,6 +163,7 @@
pellets = 4
variance = 15
randomspread = TRUE
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 0.7)
/obj/item/ammo_casing/shotgun/scatterlaser
name = "scatter laser shell"
@@ -45,9 +45,16 @@
/obj/item/ammo_box/Initialize(mapload)
. = ..()
custom_materials = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1)
if(!start_empty)
top_off(starting=TRUE)
else if(custom_materials && !(item_flags & ABSTRACT)) //internal magazines are abstract
var/obj/item/ammo_casing/prototype = new ammo_type
var/list/new_materials = custom_materials?.Copy()
for(var/mat in prototype.custom_materials)
new_materials[mat] -= prototype.custom_materials[mat] * max_ammo
qdel(prototype)
set_custom_materials(new_materials)
update_icon_state()
/obj/item/ammo_box/Destroy(force)
@@ -64,6 +71,11 @@
/obj/item/ammo_box/proc/remove_from_stored_ammo(atom/movable/gone)
stored_ammo -= gone
if(gone.custom_materials && custom_materials && !(item_flags & ABSTRACT))
var/list/new_materials = custom_materials?.Copy()
for(var/mat in gone.custom_materials)
new_materials[mat] -= gone.custom_materials[mat]
set_custom_materials(new_materials)
update_appearance()
/obj/item/ammo_box/add_weapon_description()
@@ -108,8 +120,21 @@
stack_trace("Tried loading unsupported ammocasing type [load_type] into ammo box [type].")
return
var/list/new_materials = null
if(!(item_flags & ABSTRACT))
new_materials = custom_materials?.Copy() || list()
for(var/i in max(1, stored_ammo.len + 1) to max_ammo)
stored_ammo += starting ? round_check : new round_check(src)
var/obj/item/ammo_casing/casing = round_check
if(!starting)
casing = new round_check(src)
if(new_materials)
for(var/mat in casing.custom_materials)
new_materials[mat] += casing.custom_materials[mat]
stored_ammo += casing
if(!starting && length(new_materials))
set_custom_materials(new_materials)
update_appearance()
///gets a round from the magazine
@@ -141,6 +166,11 @@
if (stored_ammo.len < max_ammo)
stored_ammo += new_round
new_round.forceMove(src)
if(new_round.custom_materials && !(item_flags & ABSTRACT))
var/list/new_materials = custom_materials?.Copy() || list()
for(var/mat in new_round.custom_materials)
new_materials[mat] += new_round.custom_materials[mat]
set_custom_materials(new_materials)
return TRUE
if(!replace_spent)
@@ -104,6 +104,12 @@
max_ammo = 8
multiple_sprites = AMMO_BOX_PER_BULLET
multiple_sprite_use_base = TRUE
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 10,
/datum/material/gold = SHEET_MATERIAL_AMOUNT * 10,
/datum/material/silver = SHEET_MATERIAL_AMOUNT * 10,
/datum/material/plasma = SHEET_MATERIAL_AMOUNT * 10,
)
// M1911 (.45) //
+1 -1
View File
@@ -24,7 +24,7 @@
ammo_type = /obj/item/ammo_casing/c38
caliber = CALIBER_38
custom_materials = list(
/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT * 3,
/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT * 4,
/datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT * 1,
)
max_ammo = 15
@@ -4,6 +4,7 @@
spawn_blacklisted = TRUE
obj_flags = CONDUCTS_ELECTRICITY
item_flags = ABSTRACT
custom_materials = null //we are never gonna be recycled anyway
//internals magazines are accessible, so replace spent ammo if full when trying to put a live one in
/obj/item/ammo_box/magazine/internal/give_round(obj/item/ammo_casing/R)
@@ -11,6 +11,7 @@
throwforce = 1
firing_effect_type = null
caliber = CALIBER_ARROW
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT, /datum/material/iron = SHEET_MATERIAL_AMOUNT)
///Whether the bullet type spawns another casing of the same type or not.
var/reusable = TRUE
@@ -131,6 +132,7 @@
base_icon_state = "plastic_arrow"
projectile_type = /obj/projectile/bullet/arrow/plastic
reusable = FALSE //cheap shit
custom_materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT)
/// plastic arrow projectile
/obj/projectile/bullet/arrow/plastic
@@ -179,6 +181,7 @@
inhand_icon_state = "ashen_arrow"
base_icon_state = "ashen_arrow"
projectile_type = /obj/projectile/bullet/arrow/ashen
custom_materials = list(/datum/material/bone = SHEET_MATERIAL_AMOUNT)
/// ashen arrow projectile
/obj/projectile/bullet/arrow/ashen
@@ -10,6 +10,7 @@
desc = "A simple homemade shortbow. Great for LARPing. Or poking out someones eye."
obj_flags = UNIQUE_RENAME
projectile_damage_multiplier = 0.5
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 4, /datum/material/iron = SHEET_MATERIAL_AMOUNT)
///chaplain's divine archer bow
/obj/item/gun/ballistic/bow/divine
@@ -49,3 +50,4 @@
slot_flags = ITEM_SLOT_BACK
obj_flags = UNIQUE_RENAME
projectile_damage_multiplier = 0.5
custom_materials = list(/datum/material/bone = SHEET_MATERIAL_AMOUNT * 6)
@@ -187,6 +187,7 @@
accepted_magazine_type = /obj/item/ammo_box/magazine/r10mm
actions_types = list(/datum/action/item_action/toggle_firemode)
obj_flags = UNIQUE_RENAME // if you did the sidequest, you get the customization
custom_materials = list(/datum/material/gold = SHEET_MATERIAL_AMOUNT * 30, /datum/material/silver = SHEET_MATERIAL_AMOUNT * 25, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 11.5)
/obj/item/gun/ballistic/automatic/pistol/aps
name = "\improper Stechkin APS machine pistol"
@@ -217,6 +217,7 @@
fire_sound = 'sound/items/xbow_lock.ogg'
can_be_sawn_off = FALSE
tac_reloads = FALSE
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 3.1, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 1.2)
var/draw_time = 3 SECONDS
SET_BASE_PIXEL(0, 0)
@@ -298,6 +299,7 @@
inhand_icon_state = "pipegun"
worn_icon_state = "pipegun"
fire_sound = 'sound/items/weapons/gun/sniper/shot.ogg'
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 8, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 8, /datum/material/cardboard = SHEET_MATERIAL_AMOUNT)
accepted_magazine_type = /obj/item/ammo_box/magazine/internal/boltaction/pipegun
projectile_damage_multiplier = 1.35
@@ -336,6 +338,7 @@
icon_state = "pipepistol"
inhand_icon_state = "pipepistol"
worn_icon_state = "gun"
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 4, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 7, /datum/material/cardboard = SHEET_MATERIAL_AMOUNT)
accepted_magazine_type = /obj/item/ammo_box/magazine/internal/boltaction/pipegun/pistol
projectile_damage_multiplier = 0.50
spread = 15 //kinda inaccurate
@@ -360,6 +363,13 @@
worn_icon_state = "regal_pipegun"
accepted_magazine_type = /obj/item/ammo_box/magazine/internal/boltaction/pipegun/prime
projectile_damage_multiplier = 2
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 9.15,
/datum/material/wood = SHEET_MATERIAL_AMOUNT *8,
/datum/material/gold = SHEET_MATERIAL_AMOUNT * 5,
/datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.15,
/datum/material/cardboard = SHEET_MATERIAL_AMOUNT,
)
/obj/item/gun/ballistic/rifle/boltaction/pipegun/pistol/prime
name = "regal pipe pistol"
@@ -485,6 +495,7 @@
semi_auto = TRUE
slot_flags = ITEM_SLOT_BACK
projectile_damage_multiplier = 0.5
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 8, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5.5, /datum/material/cardboard = SHEET_MATERIAL_AMOUNT)
SET_BASE_PIXEL(-8, 0)
@@ -21,6 +21,14 @@
selfcharge = TRUE
light_color = COLOR_STRONG_BLUE
self_charge_amount = STANDARD_ENERGY_GUN_SELF_CHARGE_RATE * 10
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
/datum/material/uranium = SHEET_MATERIAL_AMOUNT * 4,
/datum/material/glass = SHEET_MATERIAL_AMOUNT * 2.5,
/datum/material/diamond = SHEET_MATERIAL_AMOUNT * 2.5,
/datum/material/gold = SHEET_MATERIAL_AMOUNT * 2.5,
/datum/material/silver = SHEET_MATERIAL_AMOUNT * 2.25,
)
/obj/item/gun/energy/event_horizon/Initialize(mapload)
. = ..()
@@ -7,6 +7,7 @@
ammo_type = list(/obj/item/ammo_casing/energy/laser/musket)
slot_flags = ITEM_SLOT_BACK
obj_flags = UNIQUE_RENAME
custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 8, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.2, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.2)
light_color = COLOR_PURPLE
/obj/item/gun/energy/laser/musket/add_bayonet_point()
@@ -35,6 +36,13 @@
inhand_icon_state = "musket_prime"
worn_icon_state = "las_musket_prime"
ammo_type = list(/obj/item/ammo_casing/energy/laser/musket/prime)
custom_materials = list(
/datum/material/wood = SHEET_MATERIAL_AMOUNT * 8,
/datum/material/silver = SHEET_MATERIAL_AMOUNT * 5,
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.4,
/datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.35,
/datum/material/plastic = SMALL_MATERIAL_AMOUNT * 2,
)
/obj/item/gun/energy/disabler/smoothbore
@@ -46,6 +54,12 @@
charge_sections = 1
spread = 22.5
obj_flags = UNIQUE_RENAME
custom_materials = list(
/datum/material/wood = SHEET_MATERIAL_AMOUNT * 8,
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.25,
/datum/material/cardboard = SHEET_MATERIAL_AMOUNT,
/datum/material/glass = SMALL_MATERIAL_AMOUNT * 1.2,
)
/obj/item/gun/energy/disabler/smoothbore/Initialize(mapload)
. = ..()
@@ -75,6 +89,12 @@
ammo_type = list(/obj/item/ammo_casing/energy/disabler/smoothbore/prime)
charge_sections = 2
spread = 0 //could be like 5, but having just very tiny spread kinda feels like bullshit
custom_materials = list(
/datum/material/wood = SHEET_MATERIAL_AMOUNT * 8,
/datum/material/gold = SHEET_MATERIAL_AMOUNT * 5,
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.25,
/datum/material/cardboard = SHEET_MATERIAL_AMOUNT,
/datum/material/glass = SMALL_MATERIAL_AMOUNT * 5.2)
//Inferno and Cryo Pistols
@@ -157,6 +157,12 @@
ammo_x_offset = 1
ammo_type = list(/obj/item/ammo_casing/energy/laser, /obj/item/ammo_casing/energy/disabler)
selfcharge = 1
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6,
/datum/material/uranium = SHEET_MATERIAL_AMOUNT * 1.5,
/datum/material/glass = SHEET_MATERIAL_AMOUNT,
/datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
)
var/reactor_overloaded
var/fail_tick = 0
var/fail_chance = 0
@@ -235,6 +235,13 @@
inhand_icon_state = null
ammo_type = list(/obj/item/ammo_casing/energy/xray)
ammo_x_offset = 3
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 3.5,
/datum/material/gold = SHEET_MATERIAL_AMOUNT * 2.5,
/datum/material/uranium = SHEET_MATERIAL_AMOUNT * 2,
/datum/material/titanium = SHEET_MATERIAL_AMOUNT,
/datum/material/bluespace = SHEET_MATERIAL_AMOUNT,
)
shaded_charge = FALSE
light_color = LIGHT_COLOR_GREEN
@@ -105,7 +105,12 @@
inhand_icon_state = "crossbow"
no_charge_state = "crossbow_empty"
w_class = WEIGHT_CLASS_SMALL
custom_materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT)
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT,
/datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 0.5,
/datum/material/uranium = HALF_SHEET_MATERIAL_AMOUNT * 0.5,
/datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 0.5,
)
suppressed = SUPPRESSED_QUIET
ammo_type = list(/obj/item/ammo_casing/energy/bolt)
recharge_time = 2 SECONDS
@@ -130,7 +135,12 @@
base_icon_state = "crossbowlarge"
no_charge_state = "crossbowlarge_empty"
w_class = WEIGHT_CLASS_BULKY
custom_materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*2)
custom_materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 3.5,
/datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 1.5,
/datum/material/uranium = HALF_SHEET_MATERIAL_AMOUNT * 1.5,
/datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 1.5,
)
suppressed = SUPPRESSED_NONE
ammo_type = list(/obj/item/ammo_casing/energy/bolt/large)
@@ -9,6 +9,7 @@
obj_flags = CONDUCTS_ELECTRICITY
slot_flags = ITEM_SLOT_BACK
ammo_type = list(/obj/item/ammo_casing/energy/ion)
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/silver = SHEET_MATERIAL_AMOUNT * 3, /datum/material/uranium = SHEET_MATERIAL_AMOUNT)
light_color = LIGHT_COLOR_BLUE
/obj/item/gun/energy/ionrifle/Initialize(mapload)
@@ -323,6 +324,7 @@
ammo_type = list(/obj/item/ammo_casing/energy/temp, /obj/item/ammo_casing/energy/temp/hot)
cell_type = /obj/item/stock_parts/power_store/cell/high
pin = null
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 3.5, /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1.5, /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT)
/obj/item/gun/energy/temperature/security
name = "security temperature gun"
@@ -389,6 +391,7 @@ it is often confused with the mech weapon of the same name, since it is a bit mo
weapon_weight = WEAPON_HEAVY
w_class = WEIGHT_CLASS_BULKY
///if our stpck is extended and we are ready to fire.
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, /datum/material/silver = SHEET_MATERIAL_AMOUNT * 5)
var/ready_to_fire = FALSE
/obj/item/gun/energy/tesla_cannon/Initialize(mapload)
@@ -503,6 +506,7 @@ it is often confused with the mech weapon of the same name, since it is a bit mo
light_system = OVERLAY_LIGHT
light_power = 2
light_range = 1
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 3, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 7, /datum/material/gold = SHEET_MATERIAL_AMOUNT * 5)
/obj/item/gun/energy/photon/Initialize(mapload)
. = ..()
@@ -224,6 +224,7 @@
pixel_x = 0
force = 4
trigger_guard = TRIGGER_GUARD_ALLOW_ALL
custom_materials = list(/datum/material/bamboo = SHEET_MATERIAL_AMOUNT * 10)
/obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
. = ..()