mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 07:08:00 +01:00
Material Science 1: A bunch of math (#95090)
This commit is contained in:
@@ -7,19 +7,15 @@ These materials call on_applied() on whatever item they are applied to, common e
|
||||
SUBSYSTEM_DEF(materials)
|
||||
name = "Materials"
|
||||
flags = SS_NO_FIRE | SS_NO_INIT
|
||||
///Dictionary of material.id || material ref
|
||||
/// Dictionary of material.id || material ref
|
||||
var/list/materials
|
||||
///Dictionary of type || list of material refs
|
||||
/// Flat list of materials
|
||||
var/list/flat_materials
|
||||
/// Dictionary of type || list of material refs
|
||||
var/list/materials_by_type
|
||||
///Dictionary of type || list of material ids
|
||||
var/list/materialids_by_type
|
||||
///Dictionary of category || list of material refs
|
||||
var/list/materials_by_category
|
||||
///Dictionary of category || list of material ids, mostly used by rnd machines like autolathes.
|
||||
var/list/materialids_by_category
|
||||
///A cache of all material combinations that have been used
|
||||
/// A cache of all material combinations that have been used
|
||||
var/list/list/material_combos
|
||||
///List of stackcrafting recipes for materials using base recipes
|
||||
/// List of stackcrafting recipes for materials using base recipes
|
||||
var/list/base_stack_recipes = list(
|
||||
new /datum/stack_recipe("Chair", /obj/structure/chair/greyscale, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND | CRAFT_SKIP_MATERIALS_PARITY, category = CAT_FURNITURE),
|
||||
new /datum/stack_recipe("Toilet", /obj/structure/toilet/greyscale, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND | CRAFT_SKIP_MATERIALS_PARITY, category = CAT_FURNITURE),
|
||||
@@ -28,95 +24,123 @@ SUBSYSTEM_DEF(materials)
|
||||
new /datum/stack_recipe("Material airlock assembly", /obj/structure/door_assembly/door_assembly_material, 4, time = 5 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND | CRAFT_SKIP_MATERIALS_PARITY, category = CAT_DOORS),
|
||||
new /datum/stack_recipe("Material platform", /obj/structure/platform/material, 2, time = 3 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND | CRAFT_SKIP_MATERIALS_PARITY, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75, category = CAT_STRUCTURE), \
|
||||
)
|
||||
///List of stackcrafting recipes for materials using rigid recipes
|
||||
/// List of stackcrafting recipes for materials using rigid recipes
|
||||
var/list/rigid_stack_recipes = list(
|
||||
new /datum/stack_recipe("Carving block", /obj/structure/carving_block, 5, time = 3 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND | CRAFT_SKIP_MATERIALS_PARITY, category = CAT_STRUCTURE),
|
||||
)
|
||||
|
||||
///A list of dimensional themes used by the dimensional anomaly and other things, most of which require materials to function.
|
||||
/// A list of dimensional themes used by the dimensional anomaly and other things, most of which require materials to function.
|
||||
var/list/datum/dimension_theme/dimensional_themes
|
||||
/// An ID -> instance list of material properties
|
||||
var/list/datum/material_property/properties
|
||||
/// A typepath -> instance list of material requirements
|
||||
var/list/datum/material_requirement/requirements
|
||||
|
||||
///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropriate vars (See these variables for more info)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials()
|
||||
///Ran on initialize, populated the materials and material dictionaries with their appropriate vars (See these variables for more info)
|
||||
/datum/controller/subsystem/materials/proc/initialize_materials()
|
||||
materials = list()
|
||||
flat_materials = list()
|
||||
materials_by_type = list()
|
||||
materialids_by_type = list()
|
||||
materials_by_category = list()
|
||||
materialids_by_category = list()
|
||||
material_combos = list()
|
||||
for(var/type in subtypesof(/datum/material))
|
||||
var/datum/material/mat_type = type
|
||||
if(!(initial(mat_type.init_flags) & MATERIAL_INIT_MAPLOAD))
|
||||
continue // Do not initialize at mapload
|
||||
InitializeMaterial(list(mat_type))
|
||||
|
||||
properties = list()
|
||||
for(var/datum/material_property/property_type as anything in valid_subtypesof(/datum/material_property))
|
||||
properties[property_type::id] = new property_type()
|
||||
|
||||
requirements = list()
|
||||
for(var/datum/material_requirement/requirement_type as anything in valid_subtypesof(/datum/material_requirement))
|
||||
requirements[requirement_type] = new requirement_type()
|
||||
|
||||
for(var/datum/material/mat_type as anything in valid_subtypesof(/datum/material))
|
||||
if(initial(mat_type.init_flags) & MATERIAL_INIT_MAPLOAD)
|
||||
initialize_material(mat_type)
|
||||
|
||||
dimensional_themes = init_subtypes_w_path_keys(/datum/dimension_theme)
|
||||
|
||||
/** Creates and caches a material datum.
|
||||
*
|
||||
* Arguments:
|
||||
* - [arguments][/list]: The arguments to use to create the material datum
|
||||
* - The first element is the type of material to initialize.
|
||||
* The first argument is the type of material to initialize, the rest are passed to the material's init
|
||||
*/
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterial(list/arguments)
|
||||
var/datum/material/mat_type = arguments[1]
|
||||
/datum/controller/subsystem/materials/proc/initialize_material(datum/material/mat_type, ...)
|
||||
var/mat_id = mat_type
|
||||
if(initial(mat_type.init_flags) & MATERIAL_INIT_BESPOKE)
|
||||
arguments[1] = GetIdFromArguments(arguments)
|
||||
mat_id = get_id_from_args(arglist(list(mat_type) + args.Copy(2)))
|
||||
|
||||
var/datum/material/mat_ref = new mat_type
|
||||
if(!mat_ref.Initialize(arglist(arguments)))
|
||||
if(!mat_ref.Initialize(arglist(list(mat_id) + args.Copy(2))))
|
||||
return null
|
||||
|
||||
var/mat_id = mat_ref.id
|
||||
mat_id = mat_ref.id
|
||||
materials[mat_id] = mat_ref
|
||||
flat_materials += mat_ref
|
||||
materials_by_type[mat_type] += list(mat_ref)
|
||||
materialids_by_type[mat_type] += list(mat_id)
|
||||
for(var/category in mat_ref.categories)
|
||||
materials_by_category[category] += list(mat_ref)
|
||||
materialids_by_category[category] += list(mat_id)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MATERIALS_INIT_MAT, mat_ref)
|
||||
return mat_ref
|
||||
|
||||
/** Fetches a cached material singleton when passed sufficient arguments.
|
||||
*
|
||||
/**
|
||||
* Fetches a cached material singleton when passed sufficient arguments.
|
||||
* Arguments:
|
||||
* - [arguments][/list]: The list of arguments used to fetch the material ref.
|
||||
* - The first element is a material datum, text string, or material type.
|
||||
* - [Material datums][/datum/material] are assumed to be references to the cached datum and are returned
|
||||
* - Text is assumed to be the text ID of a material and the corresponding material is fetched from the cache
|
||||
* - A material type is checked for bespokeness:
|
||||
* - If the material type is not bespoke the type is assumed to be the id for a material and the corresponding material is loaded from the cache.
|
||||
* - If the material type is bespoke a text ID is generated from the arguments list and used to load a material datum from the cache.
|
||||
* - The following elements are used to generate bespoke IDs
|
||||
* - The first argument is a material datum, text string, or material type.
|
||||
* - [Material datums][/datum/material] are assumed to be references to the cached datum and are returned
|
||||
* - Text is assumed to be the text ID of a material and the corresponding material is fetched from the cache
|
||||
* - A material type is checked for bespokeness:
|
||||
* - If the material type is not bespoke the type is assumed to be the id for a material and the corresponding material is loaded from the cache.
|
||||
* - If the material type is bespoke a text ID is generated from the arguments list and used to load a material datum from the cache.
|
||||
* - The following elements are used to generate bespoke IDs
|
||||
*/
|
||||
/datum/controller/subsystem/materials/proc/_GetMaterialRef(list/arguments)
|
||||
/datum/controller/subsystem/materials/proc/get_material(datum/material/material_type, ...)
|
||||
RETURN_TYPE(/datum/material)
|
||||
|
||||
if(!materials)
|
||||
InitializeMaterials()
|
||||
initialize_materials()
|
||||
|
||||
var/datum/material/key = arguments[1]
|
||||
if(istype(key))
|
||||
return key // We are assuming here that the only thing allowed to create material datums is [/datum/controller/subsystem/materials/proc/InitializeMaterial]
|
||||
if(istype(material_type))
|
||||
return material_type // We are assuming here that the only thing allowed to create material datums is [/datum/controller/subsystem/materials/proc/initialize_material]
|
||||
|
||||
if(istext(key)) // Handle text id
|
||||
. = materials[key]
|
||||
if(istext(material_type)) // Handle text id
|
||||
. = materials[material_type]
|
||||
if(!.)
|
||||
WARNING("Attempted to fetch material ref with invalid text id '[key]'")
|
||||
WARNING("Attempted to fetch material ref with invalid text id '[material_type]'")
|
||||
return
|
||||
|
||||
if(!ispath(key, /datum/material))
|
||||
CRASH("Attempted to fetch material ref with invalid key [key]")
|
||||
if(!ispath(material_type, /datum/material))
|
||||
CRASH("Attempted to fetch material ref with invalid key [material_type]")
|
||||
|
||||
if(!(initial(key.init_flags) & MATERIAL_INIT_BESPOKE))
|
||||
. = materials[key]
|
||||
if(!(initial(material_type.init_flags) & MATERIAL_INIT_BESPOKE))
|
||||
. = materials[material_type]
|
||||
if(!.)
|
||||
WARNING("Attempted to fetch reference to an abstract material with key [key]")
|
||||
WARNING("Attempted to fetch reference to an abstract material with key [material_type]")
|
||||
return
|
||||
|
||||
key = GetIdFromArguments(arguments)
|
||||
return materials[key] || InitializeMaterial(arguments)
|
||||
var/material_id = get_id_from_args(arglist(list(material_type) + args.Copy(2)))
|
||||
return materials[material_id] || initialize_material(arglist(list(material_type) + args.Copy(2)))
|
||||
|
||||
/** I'm not going to lie, this was swiped from [SSdcs][/datum/controller/subsystem/processing/dcs].
|
||||
/// Fetches all materials that match a flag, or that don't have a flag if the passed flag is negative
|
||||
/datum/controller/subsystem/materials/proc/get_materials_by_flag(mat_flag)
|
||||
if (isnull(mat_flag) || mat_flag == MATERIAL_CLASS_ANY) // Wildcard for "any" material
|
||||
return flat_materials
|
||||
|
||||
// Lazy cache for access speed on repeated calls
|
||||
var/static/list/materials_by_flag
|
||||
if (!materials_by_flag)
|
||||
materials_by_flag = list()
|
||||
|
||||
var/list/result = materials_by_flag["[mat_flag]"]
|
||||
if (result)
|
||||
return result
|
||||
|
||||
result = list()
|
||||
for (var/datum/material/material as anything in flat_materials)
|
||||
if (mat_flag > 0)
|
||||
if (material.mat_flags & mat_flag)
|
||||
result += material
|
||||
else if (!(material.mat_flags & (-mat_flag)))
|
||||
result += material
|
||||
|
||||
materials_by_flag["[mat_flag]"] = result
|
||||
return result
|
||||
|
||||
/**
|
||||
* I'm not going to lie, this was swiped from [SSdcs][/datum/controller/subsystem/processing/dcs].
|
||||
* Credit does to ninjanomnom
|
||||
*
|
||||
* Generates an id for bespoke ~~elements~~ materials when given the argument list
|
||||
@@ -124,15 +148,14 @@ SUBSYSTEM_DEF(materials)
|
||||
* Named arguments can appear in any order and we need them to appear after ordered arguments
|
||||
* We assume that no one will pass in a named argument with a value of null
|
||||
**/
|
||||
/datum/controller/subsystem/materials/proc/GetIdFromArguments(list/arguments)
|
||||
var/datum/material/mattype = arguments[1]
|
||||
var/list/fullid = list("[initial(mattype.id) || mattype]")
|
||||
/datum/controller/subsystem/materials/proc/get_id_from_args(datum/material/mat_type, ...)
|
||||
var/list/fullid = list("[initial(mat_type.id) || mat_type]")
|
||||
var/list/named_arguments = list()
|
||||
for(var/i in 2 to length(arguments))
|
||||
var/key = arguments[i]
|
||||
for(var/i in 2 to length(args))
|
||||
var/key = args[i]
|
||||
var/value
|
||||
if(istext(key))
|
||||
value = arguments[key]
|
||||
value = args[key]
|
||||
if(!(istext(key) || isnum(key)))
|
||||
key = REF(key)
|
||||
key = "[key]" // Key is stringified so numbers don't break things
|
||||
@@ -150,12 +173,12 @@ SUBSYSTEM_DEF(materials)
|
||||
|
||||
|
||||
/// Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters.
|
||||
/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier = 1)
|
||||
/datum/controller/subsystem/materials/proc/get_material_set_cache(list/materials_declaration, multiplier = 1)
|
||||
if(!LAZYLEN(materials_declaration))
|
||||
return null // If we get a null we pass it right back, we don't want to generate stack traces just because something is clearing out its materials list.
|
||||
|
||||
if(!material_combos)
|
||||
InitializeMaterials()
|
||||
initialize_materials()
|
||||
var/list/combo_params = list()
|
||||
for(var/datum/material/mat as anything in materials_declaration)
|
||||
combo_params += "[istype(mat) ? mat.id : mat]=[OPTIMAL_COST(materials_declaration[mat] * multiplier)]"
|
||||
@@ -165,6 +188,18 @@ SUBSYSTEM_DEF(materials)
|
||||
if(!combo)
|
||||
combo = list()
|
||||
for(var/mat in materials_declaration)
|
||||
combo[GET_MATERIAL_REF(mat)] = OPTIMAL_COST(materials_declaration[mat] * multiplier)
|
||||
combo[SSmaterials.get_material(mat)] = OPTIMAL_COST(materials_declaration[mat] * multiplier)
|
||||
material_combos[combo_index] = combo
|
||||
return combo
|
||||
|
||||
/// Returns all materials that fit a requirement datum
|
||||
/datum/controller/subsystem/materials/proc/get_materials_by_req(datum/material_requirement/requirement)
|
||||
if (ispath(requirement))
|
||||
if (!requirements[requirement])
|
||||
CRASH("Invalid material requirement passed into get_materials_by_req: [requirement]")
|
||||
requirement = requirements[requirement]
|
||||
|
||||
. = list()
|
||||
for (var/datum/material/material as anything in get_materials_by_flag(requirement.required_flags)) // If none are set, this returns all materials
|
||||
if (requirement.valid_material(material))
|
||||
. += material
|
||||
|
||||
@@ -34,7 +34,7 @@ SUBSYSTEM_DEF(stock_market)
|
||||
|
||||
///Adjust the price of a material(either through buying or selling) ensuring it stays within limits
|
||||
/datum/controller/subsystem/stock_market/proc/adjust_material_price(datum/material/mat, delta)
|
||||
mat = GET_MATERIAL_REF(mat)
|
||||
mat = SSmaterials.get_material(mat)
|
||||
|
||||
//adjust the price
|
||||
var/new_price = materials_prices[mat.type] + delta
|
||||
@@ -51,7 +51,7 @@ SUBSYSTEM_DEF(stock_market)
|
||||
|
||||
///Adjust the amount of material(either through buying or selling) ensuring it stays within limits
|
||||
/datum/controller/subsystem/stock_market/proc/adjust_material_quantity(datum/material/mat, delta)
|
||||
mat = GET_MATERIAL_REF(mat)
|
||||
mat = SSmaterials.get_material(mat)
|
||||
|
||||
//adjust the quantity
|
||||
var/new_quantity = materials_quantity[mat.type] + delta
|
||||
|
||||
Reference in New Issue
Block a user