mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 14:08:31 +01:00
[READY] Bespoke Datum Mats (#55296)
* Bespoke Material Backend - Adds support for bespoke materials: - Reimplements [/datum/material/var/id] - Ports GetIdFromArguments from SSdcs - Adds a wrapper define for GetMaterialRef - Adds [MATERIAL_INIT_BESPOKE] - Adds [/datum/material/proc/Initialize] - Does not actually add any bespoke materials - [ ] TODO: Code docs - [ ] TODO: Actually adding bespoke materials * Some has_material procs and cleaning up some spaghetti - Adds a pair of has_material procs for use in checking whether a given atom has a given material * Adds meat - Adds bespoke meat variants - Does not make them accessible - Shuts up the linter * Implements bespoke meat - Makes the material container preserve bespoke materials - Makes the sheetifier accept bespoke materials - Makes the autolathe accept bespoke materials - Makes the gibber produce bespoke meats * Makes butchering produce bespoke meats This is jank and really needs to be folded into a unified butchering and gibbing system * Material documentation - Adds, fixes, and touches up some documentation * Material container insertion callback - Changes the proc used to expand the material container's material list ot a proc used to check whether a material fits into a material container - Instantiating new materials is no longer O(n) relative to the number of autolathes in existence. * Makes processing meat conserve materials - Makes bespoke meat carry over into meatballs * Makes preserving custom materials an option - Implements the ability to turn preserving custom materials _off_ for processor recipes * Fixes all bespoke materials of the same type using the same singleton - We use ids now, not just types. * Makes the fat sucker produce bespoke meats - Because consistency is good. * Fixes autolathes merging bespoke stacks into normal stacks. * Makes the callback to test materials for holdibility optional - @Floyd * GetMaterialRef -> GET_MATERIAL_REF - We capitalize macros. * Removes an extraneous callback - Makes the sheetifier use functionality I didn't notice I implemented a few commits ago. * Makes mob and species meat null compatible * Fixes the ore silo - The ore silo had really snowflake material handling that has been brought in line with the rest. - The materials should show up in the correct order. * Fixes minor lathe bugs - Fixes stack_traces caused when lathes tried to fetch materials using reagent typepaths - Fixed the selective reagent disposal topic. I have no idea how long this has been broken. * Various documentation fixes - Clarified a couple comments - Removes an extraneous ?. operator - Fixed mat floor tiles having bugged reagent temperatures * More fixes -/datum/material/meat/mob -> /datum/material/meat/mob_meat - Adds atom typecheck to material containers. * Fixes old typepaths
This commit is contained in:
@@ -183,6 +183,9 @@
|
||||
///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume)
|
||||
#define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf"
|
||||
|
||||
///from base of [/datum/controller/subsystem/materials/proc/InitializeMaterial]: (/datum/material)
|
||||
#define COMSIG_MATERIALS_INIT_MAT "SSmaterials_init_mat"
|
||||
|
||||
///from base of [/datum/reagents/proc/add_reagent]: (/datum/reagent, amount, reagtemp, data, no_react)
|
||||
#define COMSIG_REAGENTS_NEW_REAGENT "reagents_new_reagent"
|
||||
///from base of [/datum/reagents/proc/add_reagent]: (/datum/reagent, amount, reagtemp, data, no_react)
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
/// Used to make a material initialize at roundstart.
|
||||
#define MATERIAL_INIT_MAPLOAD (1<<0)
|
||||
/// Used to make a material type able to be instantiated on demand after roundstart.
|
||||
#define MATERIAL_INIT_BESPOKE (1<<1)
|
||||
|
||||
//Material Container Flags.
|
||||
///If the container shows the amount of contained materials on examine.
|
||||
@@ -46,6 +48,9 @@
|
||||
#define MATERIAL_NO_EFFECTS (1<<2)
|
||||
#define MATERIAL_AFFECT_STATISTICS (1<<3)
|
||||
|
||||
/// Wrapper for fetching material references. Exists exclusively so that people don't need to wrap everything in a list every time.
|
||||
#define GET_MATERIAL_REF(arguments...) SSmaterials._GetMaterialRef(list(##arguments))
|
||||
|
||||
#define MATERIAL_SOURCE(mat) "[mat.name]_material"
|
||||
|
||||
|
||||
|
||||
@@ -8,12 +8,16 @@ 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.type || material ref
|
||||
///Dictionary of material.id || material ref
|
||||
var/list/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 types, mostly used by rnd machines like autolathes.
|
||||
var/list/materialtypes_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
|
||||
var/list/list/material_combos
|
||||
///List of stackcrafting recipes for materials using base recipes
|
||||
@@ -31,40 +35,131 @@ SUBSYSTEM_DEF(materials)
|
||||
///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials()
|
||||
materials = list()
|
||||
materials_by_type = list()
|
||||
materialids_by_type = list()
|
||||
materials_by_category = list()
|
||||
materialtypes_by_category = list()
|
||||
materialids_by_category = list()
|
||||
material_combos = list()
|
||||
for(var/type in subtypesof(/datum/material))
|
||||
var/datum/material/ref = type
|
||||
if(!(initial(ref.init_flags) & MATERIAL_INIT_MAPLOAD))
|
||||
continue // Do not initialize
|
||||
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))
|
||||
|
||||
ref = new ref
|
||||
materials[type] = ref
|
||||
for(var/c in ref.categories)
|
||||
materials_by_category[c] += list(ref)
|
||||
materialtypes_by_category[c] += list(type)
|
||||
/** Creates and caches a material datum.
|
||||
*
|
||||
* Arugments:
|
||||
* - [arguments][/list]: The arguments to use to create the material datum
|
||||
* - The first element is the type of material to initialize.
|
||||
*/
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterial(list/arguments)
|
||||
var/datum/material/mat_type = arguments[1]
|
||||
if(initial(mat_type.init_flags) & MATERIAL_INIT_BESPOKE)
|
||||
arguments[1] = GetIdFromArguments(arguments)
|
||||
|
||||
/datum/controller/subsystem/materials/proc/GetMaterialRef(datum/material/fakemat)
|
||||
var/datum/material/mat_ref = new mat_type
|
||||
if(!mat_ref.Initialize(arglist(arguments)))
|
||||
return null
|
||||
|
||||
var/mat_id = mat_ref.id
|
||||
materials[mat_id] = 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
/datum/controller/subsystem/materials/proc/_GetMaterialRef(list/arguments)
|
||||
if(!materials)
|
||||
InitializeMaterials()
|
||||
return materials[fakemat] || fakemat
|
||||
|
||||
///Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters.
|
||||
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(istext(key)) // Handle text id
|
||||
. = materials[key]
|
||||
if(!.)
|
||||
WARNING("Attempted to fetch material ref with invalid text id '[key]'")
|
||||
return
|
||||
|
||||
if(!ispath(key, /datum/material))
|
||||
CRASH("Attempted to fetch material ref with invalid key [key]")
|
||||
|
||||
if(!(initial(key.init_flags) & MATERIAL_INIT_BESPOKE))
|
||||
. = materials[key]
|
||||
if(!.)
|
||||
WARNING("Attempted to fetch reference to an abstract material with key [key]")
|
||||
return
|
||||
|
||||
key = GetIdFromArguments(arguments)
|
||||
return materials[key] || InitializeMaterial(arguments)
|
||||
|
||||
/** 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
|
||||
* Generating the id here is a bit complex because we need to support named arguments
|
||||
* 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]")
|
||||
var/list/named_arguments = list()
|
||||
for(var/i in 2 to length(arguments))
|
||||
var/key = arguments[i]
|
||||
var/value
|
||||
if(istext(key))
|
||||
value = arguments[key]
|
||||
if(!(istext(key) || isnum(key)))
|
||||
key = REF(key)
|
||||
key = "[key]" // Key is stringified so numbers dont break things
|
||||
if(!isnull(value))
|
||||
if(!(istext(value) || isnum(value)))
|
||||
value = REF(value)
|
||||
named_arguments["[key]"] = value
|
||||
else
|
||||
fullid += "[key]"
|
||||
|
||||
if(length(named_arguments))
|
||||
named_arguments = sortList(named_arguments)
|
||||
fullid += named_arguments
|
||||
return list2params(fullid)
|
||||
|
||||
|
||||
/// 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)
|
||||
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()
|
||||
var/list/combo_params = list()
|
||||
for(var/x in materials_declaration)
|
||||
var/datum/material/mat = x
|
||||
var/path_name = ispath(mat) ? "[mat]" : "[mat.type]"
|
||||
combo_params += "[path_name]=[materials_declaration[mat] * multiplier]"
|
||||
combo_params += "[istype(mat) ? mat.id : mat]=[materials_declaration[mat] * multiplier]"
|
||||
sortTim(combo_params, /proc/cmp_text_asc) // We have to sort now in case the declaration was not in order
|
||||
var/combo_index = combo_params.Join("-")
|
||||
var/list/combo = material_combos[combo_index]
|
||||
if(!combo)
|
||||
combo = list()
|
||||
for(var/mat in materials_declaration)
|
||||
combo[GetMaterialRef(mat)] = materials_declaration[mat] * multiplier
|
||||
combo[GET_MATERIAL_REF(mat)] = materials_declaration[mat] * multiplier
|
||||
material_combos[combo_index] = combo
|
||||
return combo
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
/datum/component/butchering
|
||||
var/speed = 80 //time in deciseconds taken to butcher something
|
||||
var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops
|
||||
var/bonus_modifier = 0 //percentage increase to bonus item chance
|
||||
var/butcher_sound = 'sound/effects/butcher.ogg' //sound played when butchering
|
||||
/// Time in deciseconds taken to butcher something
|
||||
var/speed = 8 SECONDS
|
||||
/// Percentage effectiveness; numbers above 100 yield extra drops
|
||||
var/effectiveness = 100
|
||||
/// Percentage increase to bonus item chance
|
||||
var/bonus_modifier = 0
|
||||
/// Sound played when butchering
|
||||
var/butcher_sound = 'sound/effects/butcher.ogg'
|
||||
/// Whether or not this component can be used to butcher currently. Used to temporarily disable butchering
|
||||
var/butchering_enabled = TRUE
|
||||
/// Whether or not this component is compatible with blunt tools.
|
||||
var/can_be_blunt = FALSE
|
||||
|
||||
/datum/component/butchering/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt)
|
||||
@@ -77,7 +83,15 @@
|
||||
screaming_through_a_slit_throat.apply_wound(slit_throat)
|
||||
H.apply_status_effect(/datum/status_effect/neck_slice)
|
||||
|
||||
/**
|
||||
* Handles a user butchering a target
|
||||
*
|
||||
* Arguments:
|
||||
* - [butcher][/mob/living]: The mob doing the butchering
|
||||
* - [meat][/mob/living]: The mob being butchered
|
||||
*/
|
||||
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
|
||||
var/list/results = list()
|
||||
var/turf/T = meat.drop_location()
|
||||
var/final_effectiveness = effectiveness - meat.butcher_difficulty
|
||||
var/bonus_chance = max(0, (final_effectiveness - 100) + bonus_modifier) //so 125 total effectiveness = 25% extra chance
|
||||
@@ -88,20 +102,29 @@
|
||||
if(!prob(final_effectiveness))
|
||||
if(butcher)
|
||||
to_chat(butcher, "<span class='warning'>You fail to harvest some of the [initial(bones.name)] from [meat].</span>")
|
||||
else if(prob(bonus_chance))
|
||||
continue
|
||||
|
||||
if(prob(bonus_chance))
|
||||
if(butcher)
|
||||
to_chat(butcher, "<span class='info'>You harvest some extra [initial(bones.name)] from [meat]!</span>")
|
||||
for(var/i in 1 to 2)
|
||||
new bones (T)
|
||||
else
|
||||
new bones (T)
|
||||
results += new bones (T)
|
||||
results += new bones (T)
|
||||
|
||||
meat.butcher_results.Remove(bones) //in case you want to, say, have it drop its results on gib
|
||||
|
||||
for(var/V in meat.guaranteed_butcher_results)
|
||||
var/obj/sinew = V
|
||||
var/amount = meat.guaranteed_butcher_results[sinew]
|
||||
for(var/i in 1 to amount)
|
||||
new sinew (T)
|
||||
results += new sinew (T)
|
||||
meat.guaranteed_butcher_results.Remove(sinew)
|
||||
|
||||
for(var/obj/item/carrion in results)
|
||||
var/list/meat_mats = carrion.has_material_type(/datum/material/meat)
|
||||
if(!length(meat_mats))
|
||||
continue
|
||||
carrion.set_custom_materials((carrion.custom_materials - meat_mats) + list(GET_MATERIAL_REF(/datum/material/meat/mob_meat, meat) = counterlist_sum(meat_mats)))
|
||||
|
||||
if(butcher)
|
||||
butcher.visible_message("<span class='notice'>[butcher] butchers [meat].</span>", \
|
||||
"<span class='notice'>You butcher [meat].</span>")
|
||||
|
||||
@@ -10,42 +10,78 @@
|
||||
*/
|
||||
|
||||
/datum/component/material_container
|
||||
/// The total amount of materials this material container contains
|
||||
var/total_amount = 0
|
||||
/// The maximum amount of materials this material container can contain
|
||||
var/max_amount
|
||||
var/sheet_type
|
||||
/// Map of material ref -> amount
|
||||
var/list/materials //Map of key = material ref | Value = amount
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
/// The list of materials that this material container can accept
|
||||
var/list/allowed_materials
|
||||
/// The typecache of things that this material container can accept
|
||||
var/list/allowed_item_typecache
|
||||
/// The last main material that was inserted into this container
|
||||
var/last_inserted_id
|
||||
/// Whether or not this material container allows specific amounts from sheets to be inserted
|
||||
var/precise_insertion = FALSE
|
||||
/// A callback for checking wheter we can insert a material into this container
|
||||
var/datum/callback/insertion_check
|
||||
/// A callback invoked before materials are inserted into this container
|
||||
var/datum/callback/precondition
|
||||
/// A callback invoked after materials are inserted into this container
|
||||
var/datum/callback/after_insert
|
||||
///The material container flags. See __DEFINES/materials.dm.
|
||||
/// The material container flags. See __DEFINES/materials.dm.
|
||||
var/mat_container_flags
|
||||
|
||||
/// Sets up the proper signals and fills the list of materials with the appropriate references.
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _mat_container_flags=NONE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert)
|
||||
/datum/component/material_container/Initialize(list/init_mats, max_amt = 0, _mat_container_flags=NONE, list/allowed_mats=init_mats, list/allowed_items, datum/callback/_insertion_check, datum/callback/_precondition, datum/callback/_after_insert)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
mat_container_flags = _mat_container_flags
|
||||
|
||||
if(allowed_types)
|
||||
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
|
||||
allowed_typecache = GLOB.typecache_stack
|
||||
allowed_materials = allowed_mats || list()
|
||||
if(allowed_items)
|
||||
if(ispath(allowed_items) && allowed_items == /obj/item/stack)
|
||||
allowed_item_typecache = GLOB.typecache_stack
|
||||
else
|
||||
allowed_typecache = typecacheof(allowed_types)
|
||||
allowed_item_typecache = typecacheof(allowed_items)
|
||||
|
||||
insertion_check = _insertion_check
|
||||
precondition = _precondition
|
||||
after_insert = _after_insert
|
||||
|
||||
for(var/mat in init_mats) //Make the assoc list material reference -> amount
|
||||
var/mat_ref = GET_MATERIAL_REF(mat)
|
||||
if(isnull(mat_ref))
|
||||
continue
|
||||
var/mat_amt = init_mats[mat]
|
||||
if(isnull(mat_amt))
|
||||
mat_amt = 0
|
||||
materials[mat_ref] += mat_amt
|
||||
|
||||
/datum/component/material_container/Destroy(force, silent)
|
||||
materials = null
|
||||
allowed_materials = null
|
||||
if(insertion_check)
|
||||
QDEL_NULL(insertion_check)
|
||||
if(precondition)
|
||||
QDEL_NULL(precondition)
|
||||
if(after_insert)
|
||||
QDEL_NULL(after_insert)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/component/material_container/RegisterWithParent()
|
||||
. = ..()
|
||||
|
||||
if(!(mat_container_flags & MATCONTAINER_NO_INSERT))
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
|
||||
if(mat_container_flags & MATCONTAINER_EXAMINE)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
|
||||
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
|
||||
materials[M] = 0
|
||||
|
||||
/datum/component/material_container/vv_edit_var(var_name, var_value)
|
||||
var/old_flags = mat_container_flags
|
||||
@@ -75,7 +111,7 @@
|
||||
/datum/component/material_container/proc/on_attackby(datum/source, obj/item/I, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/list/tc = allowed_typecache
|
||||
var/list/tc = allowed_item_typecache
|
||||
if(!(mat_container_flags & MATCONTAINER_ANY_INTENT) && user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if(I.item_flags & ABSTRACT)
|
||||
@@ -136,54 +172,91 @@
|
||||
last_inserted_id = insert_item_materials(I, multiplier, breakdown_flags)
|
||||
return material_amount
|
||||
|
||||
/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1, breakdown_flags = mat_container_flags)
|
||||
/**
|
||||
* Inserts the relevant materials from an item into this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [source][/obj/item]: The source of the materials we are inserting.
|
||||
* - multiplier: The multiplier for the materials being inserted.
|
||||
* - breakdown_flags: The breakdown bitflags that will be used to retrieve the materials from the source
|
||||
*/
|
||||
/datum/component/material_container/proc/insert_item_materials(obj/item/source, multiplier = 1, breakdown_flags = mat_container_flags)
|
||||
var/primary_mat
|
||||
var/max_mat_value = 0
|
||||
var/list/item_materials = I.get_material_composition(breakdown_flags)
|
||||
for(var/MAT in materials)
|
||||
var/list/item_materials = source.get_material_composition(breakdown_flags)
|
||||
for(var/MAT in item_materials)
|
||||
if(!can_hold_material(MAT))
|
||||
continue
|
||||
materials[MAT] += item_materials[MAT] * multiplier
|
||||
total_amount += item_materials[MAT] * multiplier
|
||||
if(item_materials[MAT] > max_mat_value)
|
||||
max_mat_value = item_materials[MAT]
|
||||
primary_mat = MAT
|
||||
|
||||
return primary_mat
|
||||
|
||||
/**
|
||||
* The default check for whether we can add materials to this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [mat][/atom/material]: The material we are checking for insertability.
|
||||
*/
|
||||
/datum/component/material_container/proc/can_hold_material(datum/material/mat)
|
||||
if(mat in allowed_materials)
|
||||
return TRUE
|
||||
if(istype(mat) && ((mat.id in allowed_materials) || (mat.type in allowed_materials)))
|
||||
allowed_materials += mat // This could get messy with passing lists by ref... but if you're doing that the list expansion is probably being taken care of elsewhere anyway...
|
||||
return TRUE
|
||||
if(insertion_check?.Invoke(mat))
|
||||
allowed_materials += mat
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
if(amt > 0 && has_space(amt))
|
||||
var/total_amount_saved = total_amount
|
||||
if(mat)
|
||||
materials[mat] += amt
|
||||
else
|
||||
for(var/i in materials)
|
||||
materials[i] += amt
|
||||
total_amount += amt
|
||||
return (total_amount - total_amount_saved)
|
||||
return FALSE
|
||||
if(amt <= 0 || !has_space(amt))
|
||||
return 0
|
||||
|
||||
var/total_amount_saved = total_amount
|
||||
if(mat)
|
||||
if(!istype(mat))
|
||||
mat = GET_MATERIAL_REF(mat)
|
||||
materials[mat] += amt
|
||||
else
|
||||
var/num_materials = length(materials)
|
||||
if(!num_materials)
|
||||
return 0
|
||||
|
||||
amt /= num_materials
|
||||
for(var/i in materials)
|
||||
materials[i] += amt
|
||||
total_amount += amt
|
||||
return (total_amount - total_amount_saved)
|
||||
|
||||
/// Uses an amount of a specific material, effectively removing it.
|
||||
/datum/component/material_container/proc/use_amount_mat(amt, datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
mat = GET_MATERIAL_REF(mat)
|
||||
|
||||
if(!mat)
|
||||
return 0
|
||||
var/amount = materials[mat]
|
||||
if(mat)
|
||||
if(amount >= amt)
|
||||
materials[mat] -= amt
|
||||
total_amount -= amt
|
||||
return amt
|
||||
return FALSE
|
||||
if(amount < amt)
|
||||
return 0
|
||||
|
||||
materials[mat] -= amt
|
||||
total_amount -= amt
|
||||
return amt
|
||||
|
||||
/// Proc for transfering materials to another container.
|
||||
/datum/component/material_container/proc/transer_amt_to(datum/component/material_container/T, amt, datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
mat = GET_MATERIAL_REF(mat)
|
||||
if((amt==0)||(!T)||(!mat))
|
||||
return FALSE
|
||||
if(amt<0)
|
||||
return T.transer_amt_to(src, -amt, mat)
|
||||
var/tr = min(amt, materials[mat],T.can_insert_amount_mat(amt, mat))
|
||||
var/tr = min(amt, materials[mat], T.can_insert_amount_mat(amt, mat))
|
||||
if(tr)
|
||||
use_amount_mat(tr, mat)
|
||||
T.insert_amount_mat(tr, mat)
|
||||
@@ -191,14 +264,14 @@
|
||||
return FALSE
|
||||
|
||||
/// Proc for checking if there is room in the component, returning the amount or else the amount lacking.
|
||||
/datum/component/material_container/proc/can_insert_amount_mat(amt, mat)
|
||||
if(amt && mat)
|
||||
var/datum/material/M = mat
|
||||
if(M)
|
||||
if((total_amount + amt) <= max_amount)
|
||||
return amt
|
||||
else
|
||||
return (max_amount-total_amount)
|
||||
/datum/component/material_container/proc/can_insert_amount_mat(amt, datum/material/mat)
|
||||
if(!amt || !mat)
|
||||
return 0
|
||||
|
||||
if((total_amount + amt) <= max_amount)
|
||||
return amt
|
||||
else
|
||||
return (max_amount - total_amount)
|
||||
|
||||
|
||||
/// For consuming a dictionary of materials. mats is the map of materials to use and the corresponding amounts, example: list(M/datum/material/glass =100, datum/material/iron=200)
|
||||
@@ -211,7 +284,7 @@
|
||||
for(var/x in mats) //Loop through all required materials
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
req_mat = SSmaterials.GetMaterialRef(req_mat) //Get the ref if necesary
|
||||
req_mat = GET_MATERIAL_REF(req_mat) //Get the ref if necesary
|
||||
if(!materials[req_mat]) //Do we have the resource?
|
||||
return FALSE //Can't afford it
|
||||
var/amount_required = mats[x] * multiplier
|
||||
@@ -228,24 +301,25 @@
|
||||
return total_amount_save - total_amount
|
||||
|
||||
/// For spawning mineral sheets at a specific location. Used by machines to output sheets.
|
||||
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, datum/material/M, target = null)
|
||||
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, datum/material/M, atom/target = null)
|
||||
if(!M.sheet_type)
|
||||
return 0 //Add greyscale sheet handling here later
|
||||
if(sheet_amt <= 0)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
target = get_turf(parent)
|
||||
var/atom/parent_atom = parent
|
||||
target = parent_atom.drop_location()
|
||||
if(materials[M] < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
|
||||
sheet_amt = round(materials[M] / MINERAL_MATERIAL_AMOUNT)
|
||||
var/count = 0
|
||||
while(sheet_amt > MAX_STACK_SIZE)
|
||||
new M.sheet_type(target, MAX_STACK_SIZE)
|
||||
new M.sheet_type(target, MAX_STACK_SIZE, null, list((M) = MINERAL_MATERIAL_AMOUNT))
|
||||
count += MAX_STACK_SIZE
|
||||
use_amount_mat(sheet_amt * MINERAL_MATERIAL_AMOUNT, M)
|
||||
sheet_amt -= MAX_STACK_SIZE
|
||||
if(sheet_amt >= 1)
|
||||
new M.sheet_type(target, sheet_amt)
|
||||
new M.sheet_type(target, sheet_amt, null, list((M) = MINERAL_MATERIAL_AMOUNT))
|
||||
count += sheet_amt
|
||||
use_amount_mat(sheet_amt * MINERAL_MATERIAL_AMOUNT, M)
|
||||
return count
|
||||
@@ -272,7 +346,7 @@
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
if(ispath(req_mat)) //Is this an actual material, or is it a category?
|
||||
req_mat = SSmaterials.GetMaterialRef(req_mat) //Get the ref
|
||||
req_mat = GET_MATERIAL_REF(req_mat) //Get the ref
|
||||
|
||||
else // Its a category. (For example MAT_CATEGORY_RIGID)
|
||||
if(!has_enough_of_category(req_mat, mats[x], multiplier)) //Do we have enough of this category?
|
||||
@@ -294,7 +368,6 @@
|
||||
categories += x
|
||||
return categories
|
||||
|
||||
|
||||
/// Returns TRUE if you have enough of the specified material.
|
||||
/datum/component/material_container/proc/has_enough_of_material(datum/material/req_mat, amount, multiplier=1)
|
||||
if(!materials[req_mat]) //Do we have the resource?
|
||||
@@ -331,12 +404,14 @@
|
||||
return 0
|
||||
var/material_amount = 0
|
||||
var/list/item_materials = I.get_material_composition(breakdown_flags)
|
||||
for(var/MAT in materials)
|
||||
for(var/MAT in item_materials)
|
||||
if(!can_hold_material(MAT))
|
||||
continue
|
||||
material_amount += item_materials[MAT]
|
||||
return material_amount
|
||||
|
||||
/// Returns the amount of a specific material in this container.
|
||||
/datum/component/material_container/proc/get_material_amount(datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
return(materials[mat])
|
||||
mat = GET_MATERIAL_REF(mat)
|
||||
return materials[mat]
|
||||
|
||||
@@ -72,7 +72,7 @@ handles linking back and forth.
|
||||
/datum/material/plastic,
|
||||
)
|
||||
|
||||
mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, mat_container_flags, /obj/item/stack)
|
||||
mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, mat_container_flags, allowed_items=/obj/item/stack)
|
||||
|
||||
/datum/component/remote_materials/proc/set_local_size(size)
|
||||
local_size = size
|
||||
|
||||
@@ -6,8 +6,13 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
|
||||
/datum/material
|
||||
/// What the material is referred to as IC.
|
||||
var/name = "material"
|
||||
/// A short description of the material. Not used anywhere, yet...
|
||||
var/desc = "its..stuff."
|
||||
/// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material.
|
||||
var/id
|
||||
|
||||
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
|
||||
var/color
|
||||
///Base alpha of the material, is used for greyscale icons.
|
||||
@@ -39,12 +44,21 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
///What type of shard the material will shatter to
|
||||
var/obj/item/shard_type
|
||||
|
||||
/datum/material/New()
|
||||
. = ..()
|
||||
/** Handles initializing the material.
|
||||
*
|
||||
* Arugments:
|
||||
* - _id: The ID the material should use. Overrides the existing ID.
|
||||
*/
|
||||
/datum/material/proc/Initialize(_id, ...)
|
||||
if(_id)
|
||||
id = _id
|
||||
else if(isnull(id))
|
||||
id = type
|
||||
|
||||
if(texture_layer_icon_state)
|
||||
cached_texture_filter_icon = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
. = list()
|
||||
var/list/cached_comp = composition
|
||||
for(var/comp_mat in cached_comp)
|
||||
var/datum/material/component_material = SSmaterials.GetMaterialRef(comp_mat)
|
||||
var/datum/material/component_material = GET_MATERIAL_REF(comp_mat)
|
||||
var/list/component_composition = component_material.return_composition(cached_comp[comp_mat], breakdown_flags)
|
||||
for(var/comp_comp_mat in component_composition)
|
||||
.[comp_comp_mat] += component_composition[comp_comp_mat] * amount
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/datum/material/meat
|
||||
name = "meat"
|
||||
desc = "Meat"
|
||||
id = /datum/material/meat // So the bespoke versions are categorized under this
|
||||
color = rgb(214, 67, 67)
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/meat
|
||||
@@ -19,7 +20,6 @@
|
||||
|
||||
/datum/material/meat/on_applied_obj(obj/O, amount, material_flags)
|
||||
. = ..()
|
||||
O.obj_flags |= UNIQUE_RENAME //So you can name it after the person its made from, a depressing comprimise.
|
||||
make_edible(O, amount, material_flags)
|
||||
|
||||
/datum/material/meat/on_applied_turf(turf/T, amount, material_flags)
|
||||
@@ -31,3 +31,23 @@
|
||||
var/oil_count = 2 * (amount / MINERAL_MATERIAL_AMOUNT)
|
||||
source.AddComponent(/datum/component/edible, list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/cooking_oil = oil_count), null, RAW | MEAT | GROSS, null, 30, list("Fleshy"))
|
||||
|
||||
|
||||
/datum/material/meat/mob_meat
|
||||
init_flags = MATERIAL_INIT_BESPOKE
|
||||
|
||||
/datum/material/meat/mob_meat/Initialize(_id, mob/living/source)
|
||||
if(!istype(source))
|
||||
return FALSE
|
||||
|
||||
name = "[source?.name ? "[source.name]'s" : "mystery"] [initial(name)]"
|
||||
return ..()
|
||||
|
||||
/datum/material/meat/species_meat
|
||||
init_flags = MATERIAL_INIT_BESPOKE
|
||||
|
||||
/datum/material/meat/species_meat/Initialize(_id, datum/species/source)
|
||||
if(!istype(source))
|
||||
return FALSE
|
||||
|
||||
name = "[source?.name || "mystery"] [initial(name)]"
|
||||
return ..()
|
||||
|
||||
+102
-26
@@ -1576,11 +1576,11 @@
|
||||
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
|
||||
|
||||
///Sets the custom materials for an item.
|
||||
/// Sets the custom materials for an item.
|
||||
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
|
||||
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
|
||||
var/datum/material/custom_material = GET_MATERIAL_REF(i)
|
||||
custom_material.on_removed(src, custom_materials[i], material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
@@ -1589,11 +1589,110 @@
|
||||
|
||||
if(!(material_flags & MATERIAL_NO_EFFECTS))
|
||||
for(var/x in materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(x)
|
||||
var/datum/material/custom_material = GET_MATERIAL_REF(x)
|
||||
custom_material.on_applied(src, materials[x] * multiplier * material_modifier, material_flags)
|
||||
|
||||
custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier)
|
||||
|
||||
/**
|
||||
* Returns the material composition of the atom.
|
||||
*
|
||||
* Used when recycling items, specifically to turn alloys back into their component mats.
|
||||
*
|
||||
* Exists because I'd need to add a way to un-alloy alloys or otherwise deal
|
||||
* with people converting the entire stations material supply into alloys.
|
||||
*
|
||||
* Arguments:
|
||||
* - flags: A set of flags determining how exactly the materials are broken down.
|
||||
*/
|
||||
/atom/proc/get_material_composition(breakdown_flags=NONE)
|
||||
. = list()
|
||||
if(!(breakdown_flags & BREAKDOWN_INCLUDE_ALCHEMY) && HAS_TRAIT(src, TRAIT_MAT_TRANSMUTED))
|
||||
return
|
||||
|
||||
var/list/cached_materials = custom_materials
|
||||
for(var/mat in cached_materials)
|
||||
var/datum/material/material = GET_MATERIAL_REF(mat)
|
||||
var/list/material_comp = material.return_composition(cached_materials[mat], breakdown_flags)
|
||||
for(var/comp_mat in material_comp)
|
||||
.[comp_mat] += material_comp[comp_mat]
|
||||
|
||||
/**
|
||||
* Fetches a list of all of the materials this object has of the desired type
|
||||
*
|
||||
* Arguments:
|
||||
* - [mat_type][/datum/material]: The type of material we are checking for
|
||||
* - exact: Whether to search for the _exact_ material type
|
||||
* - mat_amount: The minimum required amount of material
|
||||
*/
|
||||
/atom/proc/has_material_type(datum/material/mat_type, exact=FALSE, mat_amount=0)
|
||||
var/list/cached_materials = custom_materials
|
||||
if(!length(cached_materials))
|
||||
return null
|
||||
|
||||
. = list()
|
||||
for(var/m in cached_materials)
|
||||
if(cached_materials[m] < mat_amount)
|
||||
continue
|
||||
var/datum/material/material = GET_MATERIAL_REF(m)
|
||||
if(exact ? material.type != m : !istype(material, mat_type))
|
||||
continue
|
||||
.[material] = cached_materials[m]
|
||||
|
||||
/**
|
||||
* Fetches a list of all of the materials this object has with the desired material category.
|
||||
*
|
||||
* Arguments:
|
||||
* - category: The category to check for
|
||||
* - any_flags: Any bitflags that must be present for the category
|
||||
* - all_flags: All bitflags that must be present for the category
|
||||
* - no_flags: Any bitflags that must not be present for the category
|
||||
* - mat_amount: The minimum amount of materials that must be present
|
||||
*/
|
||||
/atom/proc/has_material_category(category, any_flags=0, all_flags=0, no_flags=0, mat_amount=0)
|
||||
var/list/cached_materials = custom_materials
|
||||
if(!length(cached_materials))
|
||||
return null
|
||||
|
||||
. = list()
|
||||
for(var/m in cached_materials)
|
||||
if(cached_materials[m] < mat_amount)
|
||||
continue
|
||||
var/datum/material/material = GET_MATERIAL_REF(m)
|
||||
var/category_flags = material?.categories[category]
|
||||
if(isnull(category_flags))
|
||||
continue
|
||||
if(any_flags && !(category_flags & any_flags))
|
||||
continue
|
||||
if(all_flags && (all_flags != (category_flags & all_flags)))
|
||||
continue
|
||||
if(no_flags && (category_flags & no_flags))
|
||||
continue
|
||||
.[material] = cached_materials[m]
|
||||
|
||||
/**
|
||||
* Gets the most common material in the object.
|
||||
*/
|
||||
/atom/proc/get_master_material()
|
||||
var/list/cached_materials = custom_materials
|
||||
if(!length(cached_materials))
|
||||
return null
|
||||
|
||||
var/most_common_material = null
|
||||
var/max_amount = 0
|
||||
for(var/m in cached_materials)
|
||||
if(cached_materials[m] > max_amount)
|
||||
most_common_material = m
|
||||
max_amount = cached_materials[m]
|
||||
|
||||
if(most_common_material)
|
||||
return GET_MATERIAL_REF(most_common_material)
|
||||
|
||||
/**
|
||||
* Gets the total amount of materials in this atom.
|
||||
*/
|
||||
/atom/proc/get_custom_material_amount()
|
||||
return isnull(custom_materials) ? 0 : counterlist_sum(custom_materials)
|
||||
|
||||
///Setter for the `base_pixel_x` variable to append behavior related to its changing.
|
||||
/atom/proc/set_base_pixel_x(new_value)
|
||||
@@ -1614,29 +1713,6 @@
|
||||
|
||||
pixel_y = pixel_y + base_pixel_y - .
|
||||
|
||||
|
||||
/**Returns the material composition of the atom.
|
||||
*
|
||||
* Used when recycling items, specifically to turn alloys back into their component mats.
|
||||
*
|
||||
* Exists because I'd need to add a way to un-alloy alloys or otherwise deal
|
||||
* with people converting the entire stations material supply into alloys.
|
||||
*
|
||||
* Arguments:
|
||||
* - flags: A set of flags determining how exactly the materials are broken down.
|
||||
*/
|
||||
/atom/proc/get_material_composition(breakdown_flags=NONE)
|
||||
. = list()
|
||||
if(!(breakdown_flags & BREAKDOWN_INCLUDE_ALCHEMY) && HAS_TRAIT(src, TRAIT_MAT_TRANSMUTED))
|
||||
return
|
||||
|
||||
var/list/cached_materials = custom_materials
|
||||
for(var/mat in cached_materials)
|
||||
var/datum/material/material = SSmaterials.GetMaterialRef(mat)
|
||||
var/list/material_comp = material.return_composition(cached_materials[material], breakdown_flags)
|
||||
for(var/comp_mat in material_comp)
|
||||
.[comp_mat] += material_comp[comp_mat]
|
||||
|
||||
/**
|
||||
* Returns true if this atom has gravity for the passed in turf
|
||||
*
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
)
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, MATCONTAINER_EXAMINE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
AddComponent(/datum/component/material_container, SSmaterials.materials_by_category[MAT_CATEGORY_RIGID], 0, MATCONTAINER_EXAMINE, _after_insert = CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
@@ -123,14 +123,13 @@
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
||||
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
|
||||
else if(item_inserted.has_material_type(/datum/material/glass))
|
||||
flick("autolathe_r", src)//plays glass insertion animation by default otherwise
|
||||
else
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
|
||||
flick("autolathe_o", src)//plays metal insertion animation
|
||||
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
updateUsrDialog()
|
||||
@@ -222,7 +221,7 @@
|
||||
materials.use_materials(materials_used)
|
||||
|
||||
if(is_stack)
|
||||
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
|
||||
var/obj/item/stack/N = new being_built.build_path(A, multiplier, FALSE)
|
||||
N.update_icon()
|
||||
N.autolathe_crafted(src)
|
||||
else
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
/obj/machinery/drone_dispenser/Initialize()
|
||||
. = ..()
|
||||
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, MATCONTAINER_EXAMINE|BREAKDOWN_FLAGS_DRONE_DISPENSER, /obj/item/stack)
|
||||
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, MATCONTAINER_EXAMINE|BREAKDOWN_FLAGS_DRONE_DISPENSER, allowed_items=/obj/item/stack)
|
||||
materials.insert_amount_mat(starting_amount)
|
||||
materials.precise_insertion = TRUE
|
||||
using_materials = list(/datum/material/iron = metal_cost, /datum/material/glass = glass_cost)
|
||||
|
||||
@@ -179,10 +179,12 @@
|
||||
C.put_in_hands(new /obj/item/food/cookie, del_on_fail = TRUE)
|
||||
while(nutrients >= nutrient_to_meat)
|
||||
nutrients -= nutrient_to_meat
|
||||
new C.type_of_meat (drop_location())
|
||||
var/atom/meat = new C.type_of_meat (drop_location())
|
||||
meat.set_custom_materials(list(GET_MATERIAL_REF(/datum/material/meat/mob_meat, C) = MINERAL_MATERIAL_AMOUNT * 4))
|
||||
while(nutrients >= nutrient_to_meat / 3)
|
||||
nutrients -= nutrient_to_meat / 3
|
||||
new /obj/item/food/meat/rawcutlet/plain (drop_location())
|
||||
var/atom/meat = new /obj/item/food/meat/rawcutlet/plain (drop_location())
|
||||
meat.set_custom_materials(list(GET_MATERIAL_REF(/datum/material/meat/mob_meat, C) = round(MINERAL_MATERIAL_AMOUNT * (4/3))))
|
||||
nutrients = 0
|
||||
|
||||
/obj/machinery/fat_sucker/screwdriver_act(mob/living/user, obj/item/I)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
/obj/machinery/sheetifier/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/meat), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, MATCONTAINER_EXAMINE|BREAKDOWN_FLAGS_SHEETIFIER, /obj/item/food/meat/slab, CALLBACK(src, .proc/CanInsertMaterials), CALLBACK(src, .proc/AfterInsertMaterials))
|
||||
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/meat), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, MATCONTAINER_EXAMINE|BREAKDOWN_FLAGS_SHEETIFIER, typesof(/datum/material/meat), /obj/item/food/meat, null, CALLBACK(src, .proc/CanInsertMaterials), CALLBACK(src, .proc/AfterInsertMaterials))
|
||||
|
||||
/obj/machinery/sheetifier/update_overlays()
|
||||
. = ..()
|
||||
|
||||
@@ -1065,7 +1065,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
found_mats++
|
||||
|
||||
//if there's glass in it and the glass is more than 60% of the item, then we can shatter it
|
||||
if(custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)] >= total_material_amount * 0.60)
|
||||
if(custom_materials[GET_MATERIAL_REF(/datum/material/glass)] >= total_material_amount * 0.60)
|
||||
if(prob(66)) //66% chance to break it
|
||||
/// The glass shard that is spawned into the source item
|
||||
var/obj/item/shard/broken_glass = new /obj/item/shard(loc)
|
||||
|
||||
@@ -161,7 +161,7 @@ RLD
|
||||
return FALSE
|
||||
|
||||
var/list/materials = list()
|
||||
materials[SSmaterials.GetMaterialRef(/datum/material/iron)] = 500
|
||||
materials[GET_MATERIAL_REF(/datum/material/iron)] = 500
|
||||
silo_mats.mat_container.use_materials(materials, amount)
|
||||
silo_mats.silo_log(src, "consume", -amount, "build", materials)
|
||||
return TRUE
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
if(iswallturf(T))
|
||||
T.attackby(src, user, params)
|
||||
|
||||
var/metal_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]/MINERAL_MATERIAL_AMOUNT) //Replace this shit later
|
||||
var/glass_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]/MINERAL_MATERIAL_AMOUNT) //Replace this shit later
|
||||
var/metal_amt = round(custom_materials[GET_MATERIAL_REF(/datum/material/iron)]/MINERAL_MATERIAL_AMOUNT) //Replace this shit later
|
||||
var/glass_amt = round(custom_materials[GET_MATERIAL_REF(/datum/material/glass)]/MINERAL_MATERIAL_AMOUNT) //Replace this shit later
|
||||
|
||||
if(W.tool_behaviour == TOOL_WRENCH && (metal_amt || glass_amt))
|
||||
to_chat(user, "<span class='notice'>You dismantle [src].</span>")
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
refined_type = null
|
||||
merge_type = /obj/item/stack/ore/bluespace_crystal/refined
|
||||
|
||||
/obj/item/stack/ore/bluespace_crystal/Initialize()
|
||||
/obj/item/stack/ore/bluespace_crystal/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
pixel_x = rand(-5, 5)
|
||||
pixel_y = rand(-5, 5)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
var/value = 0
|
||||
grind_results = list(/datum/reagent/cellulose = 10)
|
||||
|
||||
/obj/item/stack/spacecash/Initialize()
|
||||
/obj/item/stack/spacecash/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
update_desc()
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
|
||||
merge_type = /obj/item/stack/medical/mesh
|
||||
|
||||
/obj/item/stack/medical/mesh/Initialize()
|
||||
/obj/item/stack/medical/mesh/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
if(amount == max_amount) //only seal full mesh packs
|
||||
is_open = FALSE
|
||||
|
||||
@@ -36,7 +36,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
|
||||
user.visible_message("<span class='suicide'>[user] begins to stuff \the [src] down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide!</span>")//it looks like theyre ur mum
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/stack/rods/Initialize(mapload, new_amount, merge = TRUE)
|
||||
/obj/item/stack/rods/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ GLOBAL_LIST_INIT(xeno_recipes, list ( \
|
||||
/// Kelvin to start drying
|
||||
var/drying_threshold_temperature = 500
|
||||
|
||||
/obj/item/stack/sheet/wethide/Initialize(mapload, new_amount, merge)
|
||||
/obj/item/stack/sheet/wethide/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
AddElement(/datum/element/dryable, /obj/item/stack/sheet/leather)
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
|
||||
. = ..()
|
||||
. += GLOB.bronze_recipes
|
||||
|
||||
/obj/item/stack/sheet/paperframes/Initialize()
|
||||
/obj/item/stack/sheet/paperframes/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
///What type of wall does this sheet spawn
|
||||
var/walltype
|
||||
|
||||
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge)
|
||||
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
pixel_x = rand(-4, 4)
|
||||
pixel_y = rand(-4, 4)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/// Amount of matter for RCD
|
||||
var/matter_amount = 0
|
||||
|
||||
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
|
||||
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
if(new_amount != null)
|
||||
amount = new_amount
|
||||
while(amount > max_amount)
|
||||
@@ -49,7 +49,9 @@
|
||||
if(!merge_type)
|
||||
merge_type = type
|
||||
|
||||
if(LAZYLEN(mats_per_unit))
|
||||
if(LAZYLEN(mat_override))
|
||||
set_mats_per_unit(mat_override, mat_amt)
|
||||
else if(LAZYLEN(mats_per_unit))
|
||||
set_mats_per_unit(mats_per_unit, 1)
|
||||
else if(LAZYLEN(custom_materials))
|
||||
set_mats_per_unit(custom_materials, amount ? 1/amount : 1)
|
||||
@@ -62,7 +64,7 @@
|
||||
var/list/temp_recipes = get_main_recipes()
|
||||
recipes = temp_recipes.Copy()
|
||||
if(material_type)
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(material_type) //First/main material
|
||||
var/datum/material/M = GET_MATERIAL_REF(material_type) //First/main material
|
||||
for(var/i in M.categories)
|
||||
switch(i)
|
||||
if(MAT_CATEGORY_BASE_RECIPES)
|
||||
@@ -477,9 +479,8 @@
|
||||
/obj/item/stack/proc/split_stack(mob/user, amount)
|
||||
if(!use(amount, TRUE, FALSE))
|
||||
return null
|
||||
var/obj/item/stack/F = new type(user? user : drop_location(), amount, FALSE)
|
||||
var/obj/item/stack/F = new type(user? user : drop_location(), amount, FALSE, mats_per_unit)
|
||||
. = F
|
||||
F.set_mats_per_unit(mats_per_unit, 1) // Required for greyscale sheets and tiles.
|
||||
F.copy_evidences(src)
|
||||
if(user)
|
||||
if(!user.put_in_hands(F, merge_stacks = FALSE))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
max_amount = 30
|
||||
merge_type = /obj/item/stack/arcadeticket
|
||||
|
||||
/obj/item/stack/arcadeticket/Initialize(mapload, new_amount, merge = TRUE)
|
||||
/obj/item/stack/arcadeticket/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
var/list/tile_reskin_types
|
||||
|
||||
|
||||
/obj/item/stack/tile/Initialize(mapload, amount)
|
||||
/obj/item/stack/tile/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
pixel_x = rand(-3, 3)
|
||||
pixel_y = rand(-3, 3) //randomize a little
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
if(remaining_mats)
|
||||
for(var/M=1 to remaining_mats)
|
||||
new stack_type(get_turf(loc))
|
||||
else if(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)])
|
||||
else if(custom_materials[GET_MATERIAL_REF(/datum/material/iron)])
|
||||
new /obj/item/stack/rods(get_turf(loc), 2)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
var/turf/newturf = T.PlaceOnTop(/turf/closed/wall/material)
|
||||
var/list/material_list = list()
|
||||
if(S.material_type)
|
||||
material_list[SSmaterials.GetMaterialRef(S.material_type)] = MINERAL_MATERIAL_AMOUNT * 2
|
||||
material_list[GET_MATERIAL_REF(S.material_type)] = MINERAL_MATERIAL_AMOUNT * 2
|
||||
if(material_list)
|
||||
newturf.set_custom_materials(material_list)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
var/amount_mod = disassembled ? 0 : -2
|
||||
for(var/mat in custom_materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(mat)
|
||||
var/datum/material/custom_material = GET_MATERIAL_REF(mat)
|
||||
var/amount = max(0,round(custom_materials[mat]/MINERAL_MATERIAL_AMOUNT) + amount_mod)
|
||||
if(amount > 0)
|
||||
new custom_material.sheet_type(drop_location(),amount)
|
||||
@@ -520,7 +520,7 @@ Moving interrupts
|
||||
var/list/carving_cost = statue_costs[statue_path]
|
||||
var/enough_materials = TRUE
|
||||
for(var/required_material in carving_cost)
|
||||
if(!custom_materials[required_material] || custom_materials[required_material] < carving_cost[required_material])
|
||||
if(!has_material_type(required_material, TRUE, carving_cost[required_material]))
|
||||
enough_materials = FALSE
|
||||
break
|
||||
if(enough_materials)
|
||||
|
||||
@@ -545,6 +545,6 @@
|
||||
return FALSE // didnt pass the bar check, no point in continuing to loop
|
||||
var/obj/machinery/ore_silo/S = GLOB.ore_silo_default
|
||||
var/datum/component/material_container/mat_container = S.GetComponent(/datum/component/material_container)
|
||||
if(mat_container.materials[SSmaterials.GetMaterialRef(/datum/material/gold)] >= 2000) // if theres at least 1 bar of gold left in the silo, they've failed to heist all of it
|
||||
if(mat_container.materials[GET_MATERIAL_REF(/datum/material/gold)] >= 2000) // if theres at least 1 bar of gold left in the silo, they've failed to heist all of it
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
var/obj/item/I = O
|
||||
var/list/mat_comp = I.get_material_composition(BREAKDOWN_FLAGS_EXPORT)
|
||||
if(isnull(mat_comp[SSmaterials.GetMaterialRef(material_id)]))
|
||||
var/datum/material/mat_ref = ispath(material_id) ? locate(material_id) in mat_comp : GET_MATERIAL_REF(material_id)
|
||||
if(isnull(mat_comp[mat_ref]))
|
||||
return 0
|
||||
|
||||
var/amount = mat_comp[SSmaterials.GetMaterialRef(material_id)]
|
||||
var/amount = mat_comp[mat_ref]
|
||||
if(istype(I, /obj/item/stack/ore))
|
||||
amount *= 0.8 // Station's ore redemption equipment is really goddamn good.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/obj/item/clothing/shoes/clown_shoes/banana_shoes/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/bananium), 200000, MATCONTAINER_EXAMINE|MATCONTAINER_ANY_INTENT|MATCONTAINER_SILENT, /obj/item/stack)
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/bananium), 100 * MINERAL_MATERIAL_AMOUNT, MATCONTAINER_EXAMINE|MATCONTAINER_ANY_INTENT|MATCONTAINER_SILENT, allowed_items=/obj/item/stack)
|
||||
AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 75, falloff_exponent = 20)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/banana_shoes/step_action()
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
*/
|
||||
/obj/item/reagent_containers/food/drinks/on_accidental_consumption(mob/living/carbon/M, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE)
|
||||
if(isGlass && !custom_materials)
|
||||
set_custom_materials(list(SSmaterials.GetMaterialRef(/datum/material/glass) = 5))
|
||||
set_custom_materials(list(GET_MATERIAL_REF(/datum/material/glass) = 5))
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity)
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
if(!occupant)
|
||||
audible_message("<span class='hear'>You hear a loud metallic grinding sound.</span>")
|
||||
return
|
||||
|
||||
use_power(1000)
|
||||
audible_message("<span class='hear'>You hear a loud squelchy grinding sound.</span>")
|
||||
playsound(loc, 'sound/machines/juicer.ogg', 50, TRUE)
|
||||
@@ -174,12 +175,14 @@
|
||||
gibtype = C.gib_type
|
||||
if(isalien(C))
|
||||
typeofskin = /obj/item/stack/sheet/animalhide/xeno
|
||||
|
||||
var/occupant_volume
|
||||
if(occupant?.reagents)
|
||||
occupant_volume = occupant.reagents.total_volume
|
||||
for (var/i=1 to meat_produced)
|
||||
var/obj/item/food/meat/slab/newmeat = new typeofmeat
|
||||
newmeat.name = "[sourcename] [newmeat.name]"
|
||||
newmeat.set_custom_materials(list(GET_MATERIAL_REF(/datum/material/meat/mob_meat, occupant) = 4 * MINERAL_MATERIAL_AMOUNT))
|
||||
if(istype(newmeat))
|
||||
newmeat.subjectname = sourcename
|
||||
newmeat.reagents.add_reagent (/datum/reagent/consumable/nutriment, sourcenutriment / meat_produced) // Thehehe. Fat guys go first
|
||||
|
||||
@@ -319,9 +319,9 @@
|
||||
var/metal = 0
|
||||
for(var/obj/item/O in ingredients)
|
||||
O.microwave_act(src)
|
||||
if(O.custom_materials && length(O.custom_materials))
|
||||
if(O.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)])
|
||||
metal += O.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
|
||||
if(LAZYLEN(O.custom_materials))
|
||||
if(O.custom_materials[GET_MATERIAL_REF(/datum/material/iron)])
|
||||
metal += O.custom_materials[GET_MATERIAL_REF(/datum/material/iron)]
|
||||
|
||||
if(metal)
|
||||
spark()
|
||||
|
||||
@@ -28,10 +28,15 @@
|
||||
. += "<span class='notice'>The status display reads: Outputting <b>[rating_amount]</b> item(s) at <b>[rating_speed*100]%</b> speed.</span>"
|
||||
|
||||
/obj/machinery/processor/proc/process_food(datum/food_processor_process/recipe, atom/movable/what)
|
||||
if (recipe.output && loc && !QDELETED(src))
|
||||
for(var/i = 0, i < (rating_amount * recipe.multiplier), i++)
|
||||
new recipe.output(drop_location())
|
||||
if (isliving(what))
|
||||
if(recipe.output && loc && !QDELETED(src))
|
||||
var/list/cached_mats = recipe.preserve_materials && what.custom_materials
|
||||
var/cached_multiplier = recipe.multiplier
|
||||
for(var/i in 1 to cached_multiplier)
|
||||
var/atom/processed_food = new recipe.output(drop_location())
|
||||
if(cached_mats)
|
||||
processed_food.set_custom_materials(cached_mats, 1 / cached_multiplier)
|
||||
|
||||
if(isliving(what))
|
||||
var/mob/living/themob = what
|
||||
themob.gib(TRUE,TRUE,TRUE)
|
||||
else
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
/datum/food_processor_process
|
||||
/// What this recipe takes
|
||||
var/input
|
||||
/// What this recipe creates
|
||||
var/output
|
||||
/// The amount of time this recipe takes.
|
||||
var/time = 40
|
||||
/// The machine required to do this recipe
|
||||
var/required_machine = /obj/machinery/processor
|
||||
/// The number of products this recipe creates.
|
||||
var/multiplier = 1 //This multiplies the number of products produced per object processed.
|
||||
/// Whether to copy the materials from the input to the output
|
||||
var/preserve_materials = TRUE
|
||||
|
||||
/datum/food_processor_process/meat
|
||||
input = /obj/item/food/meat/slab
|
||||
@@ -100,3 +107,4 @@
|
||||
input = /obj/item/grown/log
|
||||
output = /obj/item/popsicle_stick
|
||||
multiplier = 3
|
||||
preserve_materials = FALSE
|
||||
|
||||
@@ -188,13 +188,13 @@
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/biogenerator/proc/check_cost(list/materials, multiplier = 1, remove_points = TRUE)
|
||||
if(materials.len != 1 || materials[1] != SSmaterials.GetMaterialRef(/datum/material/biomass))
|
||||
if(materials.len != 1 || materials[1] != GET_MATERIAL_REF(/datum/material/biomass))
|
||||
return FALSE
|
||||
if (materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency > points)
|
||||
if (materials[GET_MATERIAL_REF(/datum/material/biomass)]*multiplier/efficiency > points)
|
||||
return FALSE
|
||||
else
|
||||
if(remove_points)
|
||||
points -= materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency
|
||||
points -= materials[GET_MATERIAL_REF(/datum/material/biomass)]*multiplier/efficiency
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
@@ -297,7 +297,7 @@
|
||||
cat["items"] += list(list(
|
||||
"id" = D.id,
|
||||
"name" = D.name,
|
||||
"cost" = D.materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]/efficiency,
|
||||
"cost" = D.materials[GET_MATERIAL_REF(/datum/material/biomass)]/efficiency,
|
||||
))
|
||||
data["categories"] += list(cat)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sortList(list(
|
||||
/obj/item/stack/marker_beacon/thirty //and they're bought in stacks of 1, 10, or 30
|
||||
amount = 30
|
||||
|
||||
/obj/item/stack/marker_beacon/Initialize(mapload)
|
||||
/obj/item/stack/marker_beacon/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -144,9 +144,9 @@
|
||||
/datum/material/titanium,
|
||||
/datum/material/bluespace
|
||||
)
|
||||
AddComponent(/datum/component/material_container, allowed_materials, INFINITY, MATCONTAINER_EXAMINE|BREAKDOWN_FLAGS_ORE_PROCESSOR, /obj/item/stack)
|
||||
AddComponent(/datum/component/material_container, allowed_materials, INFINITY, MATCONTAINER_EXAMINE|BREAKDOWN_FLAGS_ORE_PROCESSOR, allowed_items=/obj/item/stack)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/smelter
|
||||
selected_material = SSmaterials.GetMaterialRef(/datum/material/iron)
|
||||
selected_material = GET_MATERIAL_REF(/datum/material/iron)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/Destroy()
|
||||
CONSOLE = null
|
||||
|
||||
@@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
|
||||
/datum/material/bluespace,
|
||||
/datum/material/plastic,
|
||||
)
|
||||
AddComponent(/datum/component/material_container, materials_list, INFINITY, MATCONTAINER_NO_INSERT, /obj/item/stack)
|
||||
AddComponent(/datum/component/material_container, materials_list, INFINITY, MATCONTAINER_NO_INSERT, allowed_items=/obj/item/stack)
|
||||
if (!GLOB.ore_silo_default && mapload && is_station_level(z))
|
||||
GLOB.ore_silo_default = src
|
||||
|
||||
@@ -57,8 +57,8 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
|
||||
if(!istype(I) || (I.flags_1 & HOLOGRAM_1) || (I.item_flags & NO_MAT_REDEMPTION))
|
||||
to_chat(user, "<span class='warning'>[M] won't accept [I]!</span>")
|
||||
return
|
||||
var/item_mats = I.get_material_composition(breakdown_flags) & materials.materials
|
||||
if(!length(item_mats))
|
||||
var/item_mats = materials.get_item_material_amount(I, breakdown_flags)
|
||||
if(!item_mats)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [M].</span>")
|
||||
return
|
||||
// assumes unlimited space...
|
||||
|
||||
@@ -326,7 +326,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
|
||||
explosion(src,0,1,3,adminlog = notify_admins)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/stack/ore/Initialize()
|
||||
/obj/item/stack/ore/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
pixel_x = base_pixel_x + rand(0, 16) - 8
|
||||
pixel_y = base_pixel_y + rand(0, 8) - 8
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
/mob/living/simple_animal/hostile/retaliate/goose/vomit/handle_automated_action()
|
||||
if(length(nummies))
|
||||
var/obj/item/E = pick(nummies)
|
||||
if(!(E.custom_materials && E.custom_materials[SSmaterials.GetMaterialRef(/datum/material/plastic)]))
|
||||
if(!E.has_material_type(/datum/material/plastic))
|
||||
nummies -= E // remove non-plastic item from queue
|
||||
E = locate(/obj/item/reagent_containers/food) in nummies // find food
|
||||
if(E && E.loc == loc)
|
||||
@@ -70,7 +70,7 @@
|
||||
/mob/living/simple_animal/hostile/retaliate/goose/proc/feed(obj/item/suffocator)
|
||||
if(stat == DEAD || choking) // plapatin I swear to god
|
||||
return FALSE
|
||||
if(suffocator.custom_materials && suffocator.custom_materials[SSmaterials.GetMaterialRef(/datum/material/plastic)]) // dumb goose'll swallow food or drink with plastic in it
|
||||
if(suffocator.has_material_type(/datum/material/plastic)) // dumb goose'll swallow food or drink with plastic in it
|
||||
visible_message("<span class='danger'>[src] hungrily gobbles up \the [suffocator]! </span>")
|
||||
visible_message("<span class='boldwarning'>[src] is choking on \the [suffocator]! </span>")
|
||||
suffocator.forceMove(src)
|
||||
|
||||
@@ -414,7 +414,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri
|
||||
var/obj/structure/cable/target_type = /obj/structure/cable
|
||||
var/target_layer = CABLE_LAYER_2
|
||||
|
||||
/obj/item/stack/cable_coil/Initialize(mapload, new_amount = null)
|
||||
/obj/item/stack/cable_coil/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
. = ..()
|
||||
pixel_x = base_pixel_x + rand(-2, 2)
|
||||
pixel_y = base_pixel_y + rand(-2, 2)
|
||||
@@ -591,7 +591,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri
|
||||
icon_state = "coil2"
|
||||
worn_icon_state = "coil"
|
||||
|
||||
/obj/item/stack/cable_coil/cut/Initialize(mapload)
|
||||
/obj/item/stack/cable_coil/cut/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
||||
if(!amount)
|
||||
amount = rand(1,2)
|
||||
. = ..()
|
||||
|
||||
@@ -81,9 +81,9 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
d2 = text2num(copytext(icon_state, dash + length(icon_state[dash])))
|
||||
|
||||
if(d1)
|
||||
stored = new/obj/item/stack/pipe_cleaner_coil(null, 2, color)
|
||||
stored = new/obj/item/stack/pipe_cleaner_coil(null, 2, null, null, null, color)
|
||||
else
|
||||
stored = new/obj/item/stack/pipe_cleaner_coil(null, 1, color)
|
||||
stored = new/obj/item/stack/pipe_cleaner_coil(null, 1, null, null, null, color)
|
||||
|
||||
color = param_color || color
|
||||
if(!color)
|
||||
@@ -234,10 +234,11 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
user.visible_message("<span class='suicide'>[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return(OXYLOSS)
|
||||
|
||||
/obj/item/stack/pipe_cleaner_coil/Initialize(mapload, new_amount = null, param_color = null)
|
||||
/obj/item/stack/pipe_cleaner_coil/Initialize(mapload, new_amount = null, list/mat_override=null, mat_amt=1, param_color = null)
|
||||
. = ..()
|
||||
|
||||
color = param_color || color
|
||||
if(param_color)
|
||||
color = param_color
|
||||
if(!color)
|
||||
var/list/pipe_cleaner_colors = GLOB.pipe_cleaner_colors
|
||||
var/random_color = pick(pipe_cleaner_colors)
|
||||
|
||||
@@ -35,14 +35,9 @@
|
||||
|
||||
/obj/item/ammo_box/Initialize()
|
||||
. = ..()
|
||||
if (!bullet_cost)
|
||||
for (var/material in custom_materials)
|
||||
var/material_amount = custom_materials[material]
|
||||
LAZYSET(base_cost, material, (material_amount * 0.10))
|
||||
|
||||
material_amount *= 0.90 // 10% for the container
|
||||
material_amount /= max_ammo
|
||||
LAZYSET(bullet_cost, material, material_amount)
|
||||
if(!bullet_cost)
|
||||
base_cost = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.1)
|
||||
bullet_cost = SSmaterials.FindOrCreateMaterialCombo(custom_materials, 0.9 / max_ammo)
|
||||
if(!start_empty)
|
||||
top_off(starting=TRUE)
|
||||
update_icon()
|
||||
|
||||
@@ -139,7 +139,11 @@
|
||||
|
||||
iter_reagent.on_merge(data, amount)
|
||||
if(reagtemp != cached_temp)
|
||||
set_temperature(((old_heat_capacity * cached_temp) + (iter_reagent.specific_heat * amount * reagtemp)) / heat_capacity())
|
||||
var/new_heat_capacity = heat_capacity()
|
||||
if(new_heat_capacity)
|
||||
set_temperature(((old_heat_capacity * cached_temp) + (iter_reagent.specific_heat * amount * reagtemp)) / new_heat_capacity)
|
||||
else
|
||||
set_temperature(reagtemp)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_REAGENTS_ADD_REAGENT, iter_reagent, amount, reagtemp, data, no_react)
|
||||
if(!no_react)
|
||||
@@ -160,7 +164,11 @@
|
||||
|
||||
update_total()
|
||||
if(reagtemp != cached_temp)
|
||||
set_temperature(((old_heat_capacity * cached_temp) + (new_reagent.specific_heat * amount * reagtemp)) / heat_capacity())
|
||||
var/new_heat_capacity = heat_capacity()
|
||||
if(new_heat_capacity)
|
||||
set_temperature(((old_heat_capacity * cached_temp) + (new_reagent.specific_heat * amount * reagtemp)) / new_heat_capacity)
|
||||
else
|
||||
set_temperature(reagtemp)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_REAGENTS_NEW_REAGENT, new_reagent, amount, reagtemp, data, no_react)
|
||||
if(!no_react)
|
||||
@@ -978,6 +986,8 @@
|
||||
*/
|
||||
/datum/reagents/proc/adjust_thermal_energy(delta_energy, min_temp = 2.7, max_temp = 1000)
|
||||
var/heat_capacity = heat_capacity()
|
||||
if(!heat_capacity)
|
||||
return // no div/0 please
|
||||
set_temperature(clamp(chem_temp + (delta_energy / heat_capacity), min_temp, max_temp))
|
||||
|
||||
/// Applies heat to this holder
|
||||
|
||||
@@ -85,7 +85,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
addiction_type = type
|
||||
|
||||
if(material)
|
||||
material = SSmaterials.GetMaterialRef(material)
|
||||
material = GET_MATERIAL_REF(material)
|
||||
|
||||
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
|
||||
. = ..()
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
*/
|
||||
/obj/item/reagent_containers/glass/on_accidental_consumption(mob/living/carbon/M, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE)
|
||||
if(!custom_materials)
|
||||
set_custom_materials(list(SSmaterials.GetMaterialRef(/datum/material/glass) = 5))//sets it to glass so, later on, it gets picked up by the glass catch (hope it doesn't 'break' things lol)
|
||||
set_custom_materials(list(GET_MATERIAL_REF(/datum/material/glass) = 5))//sets it to glass so, later on, it gets picked up by the glass catch (hope it doesn't 'break' things lol)
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker
|
||||
|
||||
@@ -175,7 +175,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
"<span class='notice'>You struggle to pry up \the [src] with \the [I].</span>")
|
||||
if(I.use_tool(src, user, 40, volume=40))
|
||||
if(!(machine_stat & BROKEN))
|
||||
var/obj/item/stack/conveyor/C = new /obj/item/stack/conveyor(loc, 1, TRUE, id)
|
||||
var/obj/item/stack/conveyor/C = new /obj/item/stack/conveyor(loc, 1, TRUE, null, null, id)
|
||||
transfer_fingerprints_to(C)
|
||||
to_chat(user, "<span class='notice'>You remove the conveyor belt.</span>")
|
||||
qdel(src)
|
||||
@@ -425,7 +425,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
///id for linking
|
||||
var/id = ""
|
||||
|
||||
/obj/item/stack/conveyor/Initialize(mapload, new_amount, merge = TRUE, _id)
|
||||
/obj/item/stack/conveyor/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1, _id)
|
||||
. = ..()
|
||||
id = _id
|
||||
|
||||
|
||||
@@ -21,23 +21,41 @@ other types of metals and chemistry for reagents).
|
||||
//DO NOT REFERENCE OUTSIDE OF SSRESEARCH. USE THE PROCS IN SSRESEARCH TO OBTAIN A REFERENCE.
|
||||
|
||||
/datum/design //Datum for object designs, used in construction
|
||||
var/name = "Name" //Name of the created object.
|
||||
var/desc = "Desc" //Description of the created object.
|
||||
var/id = DESIGN_ID_IGNORE //ID of the created object for easy refernece. Alphanumeric, lower-case, no symbols
|
||||
var/build_type = null //Flag as to what kind machine the design is built in. See defines.
|
||||
var/list/materials = list() //List of materials. Format: "id" = amount.
|
||||
var/construction_time //Amount of time required for building the object
|
||||
var/build_path = null //The file path of the object that gets created
|
||||
var/list/make_reagents = list() //Reagents produced. Format: "id" = amount. Currently only supported by the biogenerator.
|
||||
var/list/category = null //Primarily used for Mech Fabricators, but can be used for anything
|
||||
var/list/reagents_list = list() //List of reagents. Format: "id" = amount.
|
||||
/// Name of the created object
|
||||
var/name = "Name"
|
||||
/// Description of the created object
|
||||
var/desc = "Desc"
|
||||
/// The ID of the design. Used for quick reference. Alphanumeric, lower-case, no symbols
|
||||
var/id = DESIGN_ID_IGNORE
|
||||
/// Bitflags indicating what machines this design is compatable with. ([IMPRINTER]|[PROTOLATHE]|[AUTOLATHE]|[CRAFTLATHE]|[MECHFAB]|[BIOGENERATOR]|[LIMBGROWER]|[SMELTER]|[NANITE_COMPILER])
|
||||
var/build_type = null
|
||||
/// List of materials required to create one unit of the product. Format is (typepath or caregory) -> amount
|
||||
var/list/materials = list()
|
||||
/// The amount of time required to create one unit of the product.
|
||||
var/construction_time
|
||||
/// The typepath of the object produced by this design
|
||||
var/build_path = null
|
||||
/// List of reagents produced by this design. Currently only supported by the biogenerator.
|
||||
var/list/make_reagents = list()
|
||||
/// What category this design falls under. Used for sorting in production machines, mostly the mechfab.
|
||||
var/list/category = null
|
||||
/// List of reagents required to create one unit of the product.
|
||||
var/list/reagents_list = list()
|
||||
/// The maximum number of units of whatever is produced by this can be produced in one go.
|
||||
var/maxstack = 1
|
||||
var/lathe_time_factor = 1 //How many times faster than normal is this to build on the protolathe
|
||||
var/dangerous_construction = FALSE //notify and log for admin investigations if this is printed.
|
||||
var/departmental_flags = ALL //bitflags for deplathes.
|
||||
/// How many times faster than normal is this to build on the protolathe
|
||||
var/lathe_time_factor = 1
|
||||
/// If this is [TRUE] the admins get notified whenever anyone prints this. Currently only used by the BoH.
|
||||
var/dangerous_construction = FALSE
|
||||
/// Bitflags indicating what departmental lathes should be allowed to process this design.
|
||||
var/departmental_flags = ALL
|
||||
/// What techwebs nodes unlock this design. Constructed by SSresearch
|
||||
var/list/datum/techweb_node/unlocked_by = list()
|
||||
var/research_icon //Replaces the item icon in the research console
|
||||
/// Override for the automatic icon generation used for the research console.
|
||||
var/research_icon
|
||||
/// Override for the automatic icon state generation used for the research console.
|
||||
var/research_icon_state
|
||||
/// Appears to be unused.
|
||||
var/icon_cache
|
||||
/// Optional string that interfaces can use as part of search filters. See- item/borg/upgrade/ai and the Exosuit Fabs.
|
||||
var/search_metadata
|
||||
@@ -55,7 +73,7 @@ other types of metals and chemistry for reagents).
|
||||
for(var/i in materials) //Go through all of our materials, get the subsystem instance, and then replace the list.
|
||||
var/amount = materials[i]
|
||||
if(!istext(i)) //Not a category, so get the ref the normal way
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(i)
|
||||
var/datum/material/M = GET_MATERIAL_REF(i)
|
||||
temp_list[M] = amount
|
||||
else
|
||||
temp_list[i] = amount
|
||||
|
||||
@@ -83,19 +83,45 @@
|
||||
I.set_custom_materials(matlist)
|
||||
SSblackbox.record_feedback("nested tally", "item_printed", amount, list("[type]", "[path]"))
|
||||
|
||||
/obj/machinery/rnd/production/proc/check_mat(datum/design/being_built, mat) // now returns how many times the item can be built with the material
|
||||
if (!materials.mat_container) // no connected silo
|
||||
/**
|
||||
* Returns how many times over the given material requirement for the given design is satisfied.
|
||||
*
|
||||
* Arguments:
|
||||
* - [being_built][/datum/design]: The design being referenced.
|
||||
* - material: The material being checked.
|
||||
*/
|
||||
/obj/machinery/rnd/production/proc/check_material_req(datum/design/being_built, material)
|
||||
if(!materials.mat_container) // no connected silo
|
||||
return 0
|
||||
var/list/all_materials = being_built.reagents_list + being_built.materials
|
||||
|
||||
var/A = materials.mat_container.get_material_amount(mat)
|
||||
if(!A)
|
||||
A = reagents.get_reagent_amount(mat)
|
||||
var/mat_amt = materials.mat_container.get_material_amount(material)
|
||||
if(!mat_amt)
|
||||
return 0
|
||||
|
||||
// these types don't have their .materials set in do_print, so don't allow
|
||||
// them to be constructed efficiently
|
||||
var/ef = efficient_with(being_built.build_path) ? efficiency_coeff : 1
|
||||
return round(A / max(1, all_materials[mat] / ef))
|
||||
var/efficiency = efficient_with(being_built.build_path) ? efficiency_coeff : 1
|
||||
return round(mat_amt / max(1, being_built.materials[material] / efficiency))
|
||||
|
||||
/**
|
||||
* Returns how many times over the given reagent requirement for the given design is satisfied.
|
||||
*
|
||||
* Arguments:
|
||||
* - [being_built][/datum/design]: The design being referenced.
|
||||
* - reagent: The reagent being checked.
|
||||
*/
|
||||
/obj/machinery/rnd/production/proc/check_reagent_req(datum/design/being_built, reagent)
|
||||
if(!reagents) // no reagent storage
|
||||
return 0
|
||||
|
||||
var/chem_amt = reagents.get_reagent_amount(reagent)
|
||||
if(!chem_amt)
|
||||
return 0
|
||||
|
||||
// these types don't have their .materials set in do_print, so don't allow
|
||||
// them to be constructed efficiently
|
||||
var/efficiency = efficient_with(being_built.build_path) ? efficiency_coeff : 1
|
||||
return round(chem_amt / max(1, being_built.reagents_list[reagent] / efficiency))
|
||||
|
||||
/obj/machinery/rnd/production/proc/efficient_with(path)
|
||||
return !ispath(path, /obj/item/stack/sheet) && !ispath(path, /obj/item/stack/ore/bluespace_crystal)
|
||||
@@ -239,35 +265,47 @@
|
||||
/obj/machinery/rnd/production/proc/design_menu_entry(datum/design/D, coeff)
|
||||
if(!istype(D))
|
||||
return
|
||||
if(!coeff)
|
||||
coeff = efficiency_coeff
|
||||
if(!efficient_with(D.build_path))
|
||||
coeff = 1
|
||||
var/list/l = list()
|
||||
var/temp_material
|
||||
var/c = 50
|
||||
var/t
|
||||
var/all_materials = D.materials + D.reagents_list
|
||||
for(var/M in all_materials)
|
||||
t = check_mat(D, M)
|
||||
temp_material += " | "
|
||||
if (t < 1)
|
||||
temp_material += "<span class='bad'>[all_materials[M]/coeff] [CallMaterialName(M)]</span>"
|
||||
else
|
||||
temp_material += " [all_materials[M]/coeff] [CallMaterialName(M)]"
|
||||
c = min(c,t)
|
||||
else if(!coeff)
|
||||
coeff = efficiency_coeff
|
||||
|
||||
if (c >= 1)
|
||||
l += "<A href='?src=[REF(src)];build=[D.id];amount=1'>[D.name]</A>[RDSCREEN_NOBREAK]"
|
||||
if(c >= 5)
|
||||
l += "<A href='?src=[REF(src)];build=[D.id];amount=5'>x5</A>[RDSCREEN_NOBREAK]"
|
||||
if(c >= 10)
|
||||
l += "<A href='?src=[REF(src)];build=[D.id];amount=10'>x10</A>[RDSCREEN_NOBREAK]"
|
||||
l += "[temp_material][RDSCREEN_NOBREAK]"
|
||||
var/list/entry_text = list()
|
||||
var/temp_material
|
||||
var/max_production = 50
|
||||
var/list/cached_mats = D.materials
|
||||
for(var/material in cached_mats)
|
||||
var/enough_mats = check_material_req(D, material)
|
||||
max_production = min(max_production, enough_mats)
|
||||
|
||||
temp_material += " | "
|
||||
if (enough_mats < 1)
|
||||
temp_material += "<span class='bad'>[cached_mats[material]/coeff] [CallMaterialName(material)]</span>"
|
||||
else
|
||||
temp_material += " [cached_mats[material]/coeff] [CallMaterialName(material)]"
|
||||
|
||||
var/list/cached_reagents = D.reagents_list
|
||||
for(var/reagent in cached_reagents)
|
||||
var/enough_chems = check_reagent_req(D, reagent)
|
||||
max_production = min(max_production, enough_chems)
|
||||
|
||||
temp_material += " | "
|
||||
if (enough_chems < 1)
|
||||
temp_material += "<span class='bad'>[cached_reagents[reagent]/coeff] [CallMaterialName(reagent)]</span>"
|
||||
else
|
||||
temp_material += " [cached_reagents[reagent]/coeff] [CallMaterialName(reagent)]"
|
||||
|
||||
if (max_production >= 1)
|
||||
entry_text += "<A href='?src=[REF(src)];build=[D.id];amount=1'>[D.name]</A>[RDSCREEN_NOBREAK]"
|
||||
if(max_production >= 5)
|
||||
entry_text += "<A href='?src=[REF(src)];build=[D.id];amount=5'>x5</A>[RDSCREEN_NOBREAK]"
|
||||
if(max_production >= 10)
|
||||
entry_text += "<A href='?src=[REF(src)];build=[D.id];amount=10'>x10</A>[RDSCREEN_NOBREAK]"
|
||||
entry_text += "[temp_material][RDSCREEN_NOBREAK]"
|
||||
else
|
||||
l += "<span class='linkOff'>[D.name]</span>[temp_material][RDSCREEN_NOBREAK]"
|
||||
l += ""
|
||||
return l
|
||||
entry_text += "<span class='linkOff'>[D.name]</span>[temp_material][RDSCREEN_NOBREAK]"
|
||||
entry_text += ""
|
||||
return entry_text
|
||||
|
||||
/obj/machinery/rnd/production/Topic(raw, ls)
|
||||
if(..())
|
||||
@@ -290,7 +328,11 @@
|
||||
if(ls["category"])
|
||||
selected_category = ls["category"]
|
||||
if(ls["dispose"]) //Causes the protolathe to dispose of a single reagent (all of it)
|
||||
reagents.del_reagent(ls["dispose"])
|
||||
var/reagent_path = text2path(ls["dispose"])
|
||||
if(!ispath(reagent_path, /datum/reagent))
|
||||
stack_trace("Invalid reagent typepath - [ls["dispose"]] - returned in reagent disposal topic call")
|
||||
else
|
||||
reagents.del_reagent(reagent_path)
|
||||
if(ls["disposeall"]) //Causes the protolathe to dispose of all it's reagents.
|
||||
reagents.clear_reagents()
|
||||
if(ls["ejectsheet"]) //Causes the protolathe to eject a sheet of material
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
/obj/item/integrate_amount() //returns the amount of resources gained when eating this item
|
||||
var/list/mats = get_material_composition(ALL) // Ensures that items made from plasteel, and plas/titanium/plastitaniumglass get integrated correctly.
|
||||
if(length(mats) && (mats[SSmaterials.GetMaterialRef(/datum/material/iron)] || mats[SSmaterials.GetMaterialRef(/datum/material/glass)]))
|
||||
if(length(mats) && (mats[GET_MATERIAL_REF(/datum/material/iron)] || mats[GET_MATERIAL_REF(/datum/material/glass)]))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -1202,8 +1202,7 @@
|
||||
to_chat(user, "<span class='notice'>You add [ammo_needed] [A.round_term][ammo_needed > 1?"s":""] to the [gun.name]</span>")
|
||||
A.rounds = A.rounds - ammo_needed
|
||||
if(A.custom_materials)
|
||||
for(var/i in A.custom_materials)
|
||||
A.custom_materials[i] = A.custom_materials[i] * (A.rounds/initial(A.rounds))
|
||||
A.set_custom_materials(A.custom_materials, A.rounds / initial(A.rounds))
|
||||
A.update_name()
|
||||
return TRUE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user