From 2531d69ff47e4229f60cf2ccd3f705f7ef5538a2 Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Sun, 6 Oct 2024 21:56:20 +0200 Subject: [PATCH] refactoring how materials effects are added to atoms (#86901) ## About The Pull Request I'm "cooking" the materials system a bit, specifically the code responsible for applying and removing effects. My goal is to move most of the code to the objects-side, split it in smaller procs that can be more easily overriden or called for object-specific modifiers and effects, while also revamping things all around to better support items made from multiple materials (the cleric mace will most likely be one in this PR, with the handle and tip made of different materials). PR NO LONGER WIP, TESTED AND ALL, CLERIC MACES CAN NOW BE MADE OF TWO MATERIALS. ## Why It's Good For The Game One of the nastiest flaws with the materials system is that it's just unfeasable to have items made of multiple mats (with effects enabled) right now, as they easily tend to override each other, where some of the modifiers and effects should only be applied the main material. Beside, the system's starting to show signs of its time, from the several type checks used to apply different effects, the one letter variables to the the material flags that are still being passed down as arguments when you can access them from the atom/source arg anyway. It would be disonhest of me if I went ahead and coded material fishing rods or whatever fish fuckery with materials without ensuring it won't further the technical debt the feature currently has. ## Changelog :cl: refactor: Refactored materials code. report any issue. add: Cleric maces (The autolathe-printable weapon design from outer space) can now be made of two different materials. balance: Buffed cleric maces a little. fix: toolboxes' stats are now affected by materials again. /:cl: --------- Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> --- code/__DEFINES/construction/material.dm | 15 + code/controllers/subsystem/materials.dm | 2 +- .../components/material/material_container.dm | 2 +- code/datums/greyscale/_greyscale_config.dm | 2 +- .../json_configs/items/cleric_mace.json | 6 +- .../json_configs/items/cleric_mace_worn.json | 3 +- code/datums/materials/_material.dm | 163 ++-------- code/datums/materials/alloys.dm | 85 ++--- code/datums/materials/basemats.dm | 301 ++++++++++++------ code/datums/materials/hauntium.dm | 21 +- code/datums/materials/meat.dm | 44 +-- code/datums/materials/pizza.dm | 32 +- code/game/atom/atom_materials.dm | 271 +++++++++++++++- code/game/atom/atom_vv.dm | 6 + .../game/atom/atoms_initializing_EXPENSIVE.dm | 3 +- code/game/machinery/autolathe.dm | 6 +- code/game/machinery/flatpacker.dm | 2 +- .../anomalies/anomalies_dimensional_themes.dm | 2 +- code/game/objects/effects/material_insert.dm | 17 +- code/game/objects/items.dm | 50 +++ code/game/objects/items/melee/misc.dm | 24 +- code/game/objects/items/stacks/stack.dm | 50 ++- code/game/objects/items/storage/toolbox.dm | 2 +- code/game/objects/objs.dm | 25 ++ code/game/objects/structures/false_walls.dm | 5 +- code/game/objects/structures/tables_racks.dm | 9 +- code/game/turfs/closed/wall/material_walls.dm | 5 +- code/game/turfs/open/_open.dm | 9 + code/game/turfs/open/floor.dm | 2 +- code/game/turfs/turf.dm | 17 + .../atmospherics/machinery/components/tank.dm | 3 +- code/modules/cargo/materials_market.dm | 2 +- code/modules/mining/ores_coins.dm | 7 +- .../chemistry/reagents/other_reagents.dm | 2 +- .../research/designs/weapon_designs.dm | 2 +- .../modules/research/machinery/_production.dm | 2 +- icons/obj/weapons/cleric_mace.dmi | Bin 2664 -> 2712 bytes 37 files changed, 809 insertions(+), 390 deletions(-) diff --git a/code/__DEFINES/construction/material.dm b/code/__DEFINES/construction/material.dm index 57d55ab8042..2764c0bbfaf 100644 --- a/code/__DEFINES/construction/material.dm +++ b/code/__DEFINES/construction/material.dm @@ -21,6 +21,14 @@ #define MAT_CATEGORY_RIGID "rigid material" /// Materials that can be used to craft items #define MAT_CATEGORY_ITEM_MATERIAL "item material" +/** + * Materials that can also be used to craft items for designs that require two custom mats. + * This is mainly a work around to the fact we can't (easily) have the same category show + * multiple times in a list with different values, because list access operator [] will fetch the + * top-most value. + */ +#define MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY "item material complementary" + /// Use this flag on TRUE if you want the basic recipes #define MAT_CATEGORY_BASE_RECIPES "basic recipes" @@ -87,3 +95,10 @@ #define MATERIAL_RARITY_RARE 3 /// Is this material only going to spawn once in ore vents? (6% of vents on lavaland) #define MATERIAL_RARITY_UNDISCOVERED 1 + +///The key to access the 'optimal' amount of a material key from its assoc value list. +#define MATERIAL_LIST_OPTIMAL_AMOUNT "optimal_amount" +///The key to access the multiplier used to selectively control effects and modifiers of a material. +#define MATERIAL_LIST_MULTIPLIER "multiplier" +///A macro that ensures some multiplicative modifiers higher than 1 don't become lower than 1 and viceversa because of the multiplier. +#define GET_MATERIAL_MODIFIER(modifier, multiplier) (modifier >= 1 ? 1 + ((modifier) - 1) * (multiplier) : (modifier)**(multiplier)) diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index 673414ea3c2..f5af2853b94 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -148,7 +148,7 @@ 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) +/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(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. diff --git a/code/datums/components/material/material_container.dm b/code/datums/components/material/material_container.dm index 10544116ce5..912ae334116 100644 --- a/code/datums/components/material/material_container.dm +++ b/code/datums/components/material/material_container.dm @@ -725,7 +725,7 @@ "name" = material.name, "ref" = REF(material), "amount" = amount, - "color" = material.greyscale_colors + "color" = material.greyscale_color || material.color )) return data diff --git a/code/datums/greyscale/_greyscale_config.dm b/code/datums/greyscale/_greyscale_config.dm index 69f104d2f91..b922d2697d5 100644 --- a/code/datums/greyscale/_greyscale_config.dm +++ b/code/datums/greyscale/_greyscale_config.dm @@ -257,7 +257,7 @@ /datum/greyscale_config/proc/GenerateBundle(list/colors, list/render_steps, icon/last_external_icon) if(!istype(colors)) colors = SSgreyscale.ParseColorString(colors) - if(length(colors) != expected_colors) + if(length(colors) < expected_colors) CRASH("[DebugName()] expected [expected_colors] color arguments but only received [length(colors)]") var/list/generated_icons = list() diff --git a/code/datums/greyscale/json_configs/items/cleric_mace.json b/code/datums/greyscale/json_configs/items/cleric_mace.json index 781c790ea6a..5197ebc45a2 100644 --- a/code/datums/greyscale/json_configs/items/cleric_mace.json +++ b/code/datums/greyscale/json_configs/items/cleric_mace.json @@ -9,7 +9,8 @@ { "type": "icon_state", "icon_state": "handle", - "blend_mode": "overlay" + "blend_mode": "overlay", + "color_ids": [ 2 ] } ], "default_worn": [ @@ -22,7 +23,8 @@ { "type": "icon_state", "icon_state": "worn_handle", - "blend_mode": "overlay" + "blend_mode": "overlay", + "color_ids": [ 2 ] } ] } diff --git a/code/datums/greyscale/json_configs/items/cleric_mace_worn.json b/code/datums/greyscale/json_configs/items/cleric_mace_worn.json index c49a829aa2c..5725cfa689a 100644 --- a/code/datums/greyscale/json_configs/items/cleric_mace_worn.json +++ b/code/datums/greyscale/json_configs/items/cleric_mace_worn.json @@ -9,7 +9,8 @@ { "type": "icon_state", "icon_state": "worn_handle", - "blend_mode": "overlay" + "blend_mode": "overlay", + "color_ids": [ 2 ] } ] } diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 5dc8c26d0f6..cff0ea0e6d1 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -13,12 +13,20 @@ Simple datum which is instanced once per type and is used for every object of sa /// 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. - ///Deprecated, use greyscale_color instead. + /** + * Base color of the material, for items that don't have greyscale configs nor are made of multiple materials. Item isn't changed in color if this is null. + * This can be a RGB or color matrix, but it cannot be RGBA as alpha is automatically filled in. + */ var/color - ///Determines the color palette of the material. Formatted the same as atom/var/greyscale_colors - var/greyscale_colors - ///Base alpha of the material, is used for greyscale icons. + /** + * If the color is a color matrix and either the item uses greyscale configs or is made of multiple colored materials. This will be used instead because + * neither greyscale configs nor BlendRGB() support color matrices. + * Also this has to be RRGGBB, six characters, no alpha channel as it's automatically filled in. + * + * Basically, set this if the color is a color matrix (list) + */ + var/greyscale_color + /// Base alpha of the material var/alpha = 255 ///Starlight color of the material ///This is the color of light it'll emit if its turf is transparent and over space. Defaults to COLOR_STARLIGHT if not set @@ -67,6 +75,8 @@ Simple datum which is instanced once per type and is used for every object of sa var/mineral_rarity = MATERIAL_RARITY_COMMON /// How many points per units of ore does this grant? var/points_per_unit = 1 + /// The slowdown that is added to items. + var/added_slowdown = 0 /** Handles initializing the material. * @@ -85,84 +95,11 @@ Simple datum which is instanced once per type and is used for every object of sa return TRUE ///This proc is called when the material is added to an object. -/datum/material/proc/on_applied(atom/source, amount, material_flags) - if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example - if(color) //Do we have a custom color? - source.add_atom_colour(color, FIXED_COLOUR_PRIORITY) - if(alpha) - source.alpha = alpha - if(texture_layer_icon_state) - ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src)) - source.add_filter("material_texture_[name]",1,layering_filter(icon=cached_texture_filter_icon,blend_mode=BLEND_INSET_OVERLAY)) - - if(material_flags & MATERIAL_GREYSCALE) - var/config_path = get_greyscale_config_for(source.greyscale_config) - source.set_greyscale(greyscale_colors, config_path) - - if(alpha < 255) - source.opacity = FALSE - if(material_flags & MATERIAL_ADD_PREFIX) - source.name = "[name] [source.name]" - - if(beauty_modifier) - source.AddElement(/datum/element/beauty, beauty_modifier * amount) - - if(isobj(source)) //objs - on_applied_obj(source, amount, material_flags) - - else if(istype(source, /turf)) //turfs - on_applied_turf(source, amount, material_flags) - - source.mat_update_desc(src) - -///This proc is called when a material updates an object's description -/atom/proc/mat_update_desc(datum/material/mat) +/datum/material/proc/on_applied(atom/source, mat_amount, multiplier) return -///This proc is called when the material is added to an object specifically. -/datum/material/proc/on_applied_obj(obj/o, amount, material_flags) - if(material_flags & MATERIAL_AFFECT_STATISTICS) - var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1) - o.modify_max_integrity(new_max_integrity) - o.force *= strength_modifier - o.throwforce *= strength_modifier - o.set_armor(o.get_armor().generate_new_with_multipliers(armor_modifiers)) - - if(!isitem(o)) - return - var/obj/item/item = o - - if(material_flags & MATERIAL_GREYSCALE) - var/worn_path = get_greyscale_config_for(item.greyscale_config_worn) - var/lefthand_path = get_greyscale_config_for(item.greyscale_config_inhand_left) - var/righthand_path = get_greyscale_config_for(item.greyscale_config_inhand_right) - item.set_greyscale( - new_worn_config = worn_path, - new_inhand_left = lefthand_path, - new_inhand_right = righthand_path - ) - - if(!item_sound_override) - return - item.hitsound = item_sound_override - item.usesound = item_sound_override - item.mob_throw_hit_sound = item_sound_override - item.equip_sound = item_sound_override - item.pickup_sound = item_sound_override - item.drop_sound = item_sound_override - -/datum/material/proc/on_applied_turf(turf/T, amount, material_flags) - if(isopenturf(T)) - if(turf_sound_override) - var/turf/open/O = T - O.footstep = turf_sound_override - O.barefootstep = turf_sound_override + "barefoot" - O.clawfootstep = turf_sound_override + "claw" - O.heavyfootstep = FOOTSTEP_GENERIC_HEAVY - if(alpha < 255) - T.AddElement(/datum/element/turf_z_transparency) - setup_glow(T) - T.rust_resistance = mat_rust_resistance +///This proc is called when the material becomes the one the object is composed of the most +/datum/material/proc/on_main_applied(atom/source, mat_amount, multiplier) return /datum/material/proc/setup_glow(turf/on) @@ -183,61 +120,13 @@ Simple datum which is instanced once per type and is used for every object of sa /datum/material/proc/lit_turf_deleted(turf/source) source.set_light(0, 0, null) -/datum/material/proc/get_greyscale_config_for(datum/greyscale_config/config_path) - if(!config_path) - return - for(var/datum/greyscale_config/path as anything in subtypesof(config_path)) - if(type != initial(path.material_skin)) - continue - return path - ///This proc is called when the material is removed from an object. /datum/material/proc/on_removed(atom/source, amount, material_flags) - if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example - if(color) - source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color) - if(texture_layer_icon_state) - source.remove_filter("material_texture_[name]") - REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src)) - source.alpha = initial(source.alpha) + return - if(material_flags & MATERIAL_GREYSCALE) - source.set_greyscale(initial(source.greyscale_colors), initial(source.greyscale_config)) - - if(material_flags & MATERIAL_ADD_PREFIX) - source.name = initial(source.name) - - if(beauty_modifier) - source.RemoveElement(/datum/element/beauty, beauty_modifier * amount) - - if(isobj(source)) //objs - on_removed_obj(source, amount, material_flags) - - if(istype(source, /turf)) //turfs - on_removed_turf(source, amount, material_flags) - -///This proc is called when the material is removed from an object specifically. -/datum/material/proc/on_removed_obj(obj/o, amount, material_flags) - if(material_flags & MATERIAL_AFFECT_STATISTICS) - var/new_max_integrity = initial(o.max_integrity) - o.modify_max_integrity(new_max_integrity) - o.force = initial(o.force) - o.throwforce = initial(o.throwforce) - - if(isitem(o) && (material_flags & MATERIAL_GREYSCALE)) - var/obj/item/item = o - item.set_greyscale( - new_worn_config = initial(item.greyscale_config_worn), - new_inhand_left = initial(item.greyscale_config_inhand_left), - new_inhand_right = initial(item.greyscale_config_inhand_right) - ) - -/datum/material/proc/on_removed_turf(turf/T, amount, material_flags) - if(alpha < 255) - T.RemoveElement(/datum/element/turf_z_transparency) - // yeets glow - T.UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) - T.set_light(0, 0, null) +///This proc is called when the material is no longer the one the object is composed by the most +/datum/material/proc/on_main_removed(atom/source, mat_amount, multiplier) + return /** * This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption. @@ -258,3 +147,11 @@ Simple datum which is instanced once per type and is used for every object of sa /datum/material/proc/return_composition(amount = 1) // Yes we need the parenthesis, without them BYOND stringifies src into "src" and things break. return list((src) = amount) + +///Returns the list of armor modifiers, with each element having its assoc value multiplied by the multiplier arg +/datum/material/proc/get_armor_modifiers(multiplier) + SHOULD_NOT_OVERRIDE(TRUE) + var/list/return_list = list() + for(var/armor in armor_modifiers) + return_list[armor] = return_list[armor] * multiplier + return return_list diff --git a/code/datums/materials/alloys.dm b/code/datums/materials/alloys.dm index 8bfdf0b58d9..d13a88c49c3 100644 --- a/code/datums/materials/alloys.dm +++ b/code/datums/materials/alloys.dm @@ -27,31 +27,21 @@ name = "plasteel" desc = "The heavy duty result of infusing iron with plasma." color = "#706374" - greyscale_colors = "#706374" init_flags = MATERIAL_INIT_MAPLOAD value_per_unit = 0.135 strength_modifier = 1.25 integrity_modifier = 1.5 // Heavy duty. armor_modifiers = list(MELEE = 1.4, BULLET = 1.4, LASER = 1.1, ENERGY = 1.1, BOMB = 1.5, BIO = 1, FIRE = 1.1, ACID = 1) sheet_type = /obj/item/stack/sheet/plasteel - categories = list(MAT_CATEGORY_RIGID=TRUE, MAT_CATEGORY_BASE_RECIPES=TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) composition = list(/datum/material/iron=1, /datum/material/plasma=1) mat_rust_resistance = RUST_RESISTANCE_REINFORCED - -/datum/material/alloy/plasteel/on_applied_obj(obj/item/target_item, amount, material_flags) - . = ..() - if(!istype(target_item)) - return - - target_item.slowdown += MATERIAL_SLOWDOWN_PLASTEEL * amount / SHEET_MATERIAL_AMOUNT - -/datum/material/alloy/plasteel/on_removed_obj(obj/item/target_item, amount, material_flags) - . = ..() - - if(!istype(target_item)) - return - - target_item.slowdown -= MATERIAL_SLOWDOWN_PLASTEEL * amount / SHEET_MATERIAL_AMOUNT + added_slowdown = 0.05 /** Plastitanium * @@ -61,14 +51,18 @@ name = "plastitanium" desc = "The extremely heat resistant result of infusing titanium with plasma." color = "#3a313a" - greyscale_colors = "#3a313a" init_flags = MATERIAL_INIT_MAPLOAD value_per_unit = 0.225 strength_modifier = 0.9 // It's a lightweight alloy. integrity_modifier = 1.3 armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.4, ENERGY = 1.4, BOMB = 1.1, BIO = 1.2, FIRE = 1.5, ACID = 1) sheet_type = /obj/item/stack/sheet/mineral/plastitanium - categories = list(MAT_CATEGORY_RIGID=TRUE, MAT_CATEGORY_BASE_RECIPES=TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) composition = list(/datum/material/titanium=1, /datum/material/plasma=1) mat_rust_resistance = RUST_RESISTANCE_TITANIUM @@ -80,7 +74,6 @@ name = "plasmaglass" desc = "Plasma-infused silicate. It is much more durable and heat resistant than either of its component materials." color = "#ff80f4" - greyscale_colors = "#ff80f496" alpha = 150 starlight_color = COLOR_STRONG_MAGENTA init_flags = MATERIAL_INIT_MAPLOAD @@ -90,7 +83,12 @@ shard_type = /obj/item/shard/plasma debris_type = /obj/effect/decal/cleanable/glass/plasma value_per_unit = 0.075 - categories = list(MAT_CATEGORY_RIGID=TRUE, MAT_CATEGORY_BASE_RECIPES=TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) composition = list(/datum/material/glass=1, /datum/material/plasma=0.5) /** Titaniumglass @@ -101,7 +99,6 @@ name = "titanium glass" desc = "A specialized silicate-titanium alloy that is commonly used in shuttle windows." color = "#cfbee0" - greyscale_colors = "#cfbee096" alpha = 150 starlight_color = COLOR_COMMAND_BLUE init_flags = MATERIAL_INIT_MAPLOAD @@ -110,7 +107,12 @@ shard_type = /obj/item/shard/titanium debris_type = /obj/effect/decal/cleanable/glass/titanium value_per_unit = 0.04 - categories = list(MAT_CATEGORY_RIGID=TRUE, MAT_CATEGORY_BASE_RECIPES=TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) composition = list(/datum/material/glass=1, /datum/material/titanium=0.5) /** Plastitanium Glass @@ -121,7 +123,6 @@ name = "plastitanium glass" desc = "A specialized silicate-plastitanium alloy." color = "#5d3369" - greyscale_colors = "#5d336996" starlight_color = COLOR_CENTCOM_BLUE alpha = 150 init_flags = MATERIAL_INIT_MAPLOAD @@ -131,7 +132,12 @@ shard_type = /obj/item/shard/plastitanium debris_type = /obj/effect/decal/cleanable/glass/plastitanium value_per_unit = 0.125 - categories = list(MAT_CATEGORY_RIGID=TRUE, MAT_CATEGORY_BASE_RECIPES=TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) composition = list(/datum/material/glass=1, /datum/material/alloy/plastitanium=0.5) /** Alien Alloy @@ -144,30 +150,27 @@ name = "alien alloy" desc = "An extremely dense alloy similar to plasteel in composition. It requires exotic metallurgical processes to create." color = "#6041aa" - greyscale_colors = "#6041aa" init_flags = MATERIAL_INIT_MAPLOAD strength_modifier = 1.5 // It's twice the density of plasteel and just as durable. Getting hit with it is going to HURT. integrity_modifier = 1.5 armor_modifiers = list(MELEE = 1.4, BULLET = 1.4, LASER = 1.2, ENERGY = 1.2, BOMB = 1.5, BIO = 1.2, FIRE = 1.2, ACID = 1.2) sheet_type = /obj/item/stack/sheet/mineral/abductor value_per_unit = 0.4 - categories = list(MAT_CATEGORY_RIGID=TRUE, MAT_CATEGORY_BASE_RECIPES=TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) composition = list(/datum/material/iron=2, /datum/material/plasma=2) + added_slowdown = 0.1 -/datum/material/alloy/alien/on_applied_obj(obj/item/target_item, amount, material_flags) +/datum/material/alloy/alien/on_applied(atom/target, mat_amount, multiplier) . = ..() + if(isobj(target)) + target.AddElement(/datum/element/obj_regen, _rate=0.02) // 2% regen per tick. - target_item.AddElement(/datum/element/obj_regen, _rate=0.02) // 2% regen per tick. - if(!istype(target_item)) - return - - target_item.slowdown += MATERIAL_SLOWDOWN_ALIEN_ALLOY * amount / SHEET_MATERIAL_AMOUNT - -/datum/material/alloy/alien/on_removed_obj(obj/item/target_item, amount, material_flags) +/datum/material/alloy/alien/on_removed(atom/target, mat_amount, multiplier) . = ..() - - target_item.RemoveElement(/datum/element/obj_regen, _rate=0.02) - if(!istype(target_item)) - return - - target_item.slowdown -= MATERIAL_SLOWDOWN_ALIEN_ALLOY * amount / SHEET_MATERIAL_AMOUNT + if(isobj(target)) + target.RemoveElement(/datum/element/obj_regen, _rate=0.02) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 66f4bccbd6f..76d44c1f164 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -3,8 +3,13 @@ name = "iron" desc = "Common iron ore often found in sedimentary and igneous layers of the crust." color = "#B6BEC2" - greyscale_colors = "#B6BEC2" - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/iron ore_type = /obj/item/stack/ore/iron value_per_unit = 5 / SHEET_MATERIAL_AMOUNT @@ -24,9 +29,14 @@ name = "glass" desc = "Glass forged by melting sand." color = "#6292AF" - greyscale_colors = "#6292AF" alpha = 150 - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) integrity_modifier = 0.1 sheet_type = /obj/item/stack/sheet/glass ore_type = /obj/item/stack/ore/glass/basalt @@ -46,15 +56,15 @@ victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5, sharpness = TRUE) //cronch return TRUE -/datum/material/glass/on_applied_obj(atom/source, amount, material_flags) +/datum/material/glass/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - if(!isstack(source)) - source.AddElement(/datum/element/can_shatter, shard_type, round(amount / SHEET_MATERIAL_AMOUNT), SFX_SHATTER) + if(isobj(source) && !isstack(source)) + source.AddElement(/datum/element/can_shatter, shard_type, round(mat_amount / SHEET_MATERIAL_AMOUNT * multiplier), SFX_SHATTER) -/datum/material/glass/on_removed(atom/source, amount, material_flags) +/datum/material/glass/on_main_removed(atom/source, mat_amount, multiplier) . = ..() - - source.RemoveElement(/datum/element/can_shatter, shard_type) + if(isobj(source) && !isstack(source)) + source.RemoveElement(/datum/element/can_shatter, shard_type, round(mat_amount / SHEET_MATERIAL_AMOUNT * multiplier), SFX_SHATTER) /* Color matrices are like regular colors but unlike with normal colors, you can go over 255 on a channel. @@ -66,8 +76,13 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "silver" desc = "Silver" color = "#B5BCBB" - greyscale_colors = "#B5BCBB" - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/silver ore_type = /obj/item/stack/ore/silver value_per_unit = 50 / SHEET_MATERIAL_AMOUNT @@ -87,9 +102,14 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "gold" desc = "Gold" color = "#E6BB45" - greyscale_colors = "#E6BB45" strength_modifier = 1.2 - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/gold ore_type = /obj/item/stack/ore/gold value_per_unit = 125 / SHEET_MATERIAL_AMOUNT @@ -110,8 +130,13 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "diamond" desc = "Highly pressurized carbon" color = "#C9D8F2" - greyscale_colors = "#C9D8F2" - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/diamond ore_type = /obj/item/stack/ore/diamond alpha = 132 @@ -133,8 +158,13 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "uranium" desc = "Uranium" color = "#2C992C" - greyscale_colors = "#2C992C" - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/uranium ore_type = /obj/item/stack/ore/uranium value_per_unit = 100 / SHEET_MATERIAL_AMOUNT @@ -145,7 +175,7 @@ Unless you know what you're doing, only use the first three numbers. They're in mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS points_per_unit = 30 / SHEET_MATERIAL_AMOUNT -/datum/material/uranium/on_applied(atom/source, amount, material_flags) +/datum/material/uranium/on_applied(atom/source, mat_amount, multiplier) . = ..() // Uranium structures should irradiate, but not items, because item irradiation is a lot more annoying. @@ -153,15 +183,15 @@ Unless you know what you're doing, only use the first three numbers. They're in if (isitem(source)) return - source.AddElement(/datum/element/radioactive) + source.AddElement(/datum/element/radioactive, chance = URANIUM_IRRADIATION_CHANCE * multiplier) -/datum/material/uranium/on_removed(atom/source, amount, material_flags) +/datum/material/uranium/on_removed(atom/source, mat_amount, multiplier) . = ..() if (isitem(source)) return - source.RemoveElement(/datum/element/radioactive) + source.RemoveElement(/datum/element/radioactive, chance = URANIUM_IRRADIATION_CHANCE * multiplier) /datum/material/uranium/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.reagents.add_reagent(/datum/reagent/uranium, rand(4, 6)) @@ -173,8 +203,13 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "plasma" desc = "Isn't plasma a state of matter? Oh whatever." color = "#BA3692" - greyscale_colors = "#BA3692" - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/plasma ore_type = /obj/item/stack/ore/plasma value_per_unit = 200 / SHEET_MATERIAL_AMOUNT @@ -183,15 +218,15 @@ Unless you know what you're doing, only use the first three numbers. They're in mineral_rarity = MATERIAL_RARITY_PRECIOUS points_per_unit = 15 / SHEET_MATERIAL_AMOUNT -/datum/material/plasma/on_applied(atom/source, amount, material_flags) +/datum/material/plasma/on_applied(atom/source, mat_amount, multiplier) . = ..() if(ismovable(source)) - source.AddElement(/datum/element/firestacker, amount=1) - source.AddComponent(/datum/component/combustible_flooder, "plasma", amount*0.05) //Empty temp arg, fully dependent on whatever ignited it. + source.AddElement(/datum/element/firestacker, 1 * multiplier) + source.AddComponent(/datum/component/combustible_flooder, "plasma", mat_amount * 0.05 * multiplier) //Empty temp arg, fully dependent on whatever ignited it. -/datum/material/plasma/on_removed(atom/source, amount, material_flags) +/datum/material/plasma/on_removed(atom/source, mat_amount, multiplier) . = ..() - source.RemoveElement(/datum/element/firestacker, amount=1) + source.RemoveElement(/datum/element/firestacker, mat_amount = 1 * multiplier) qdel(source.GetComponent(/datum/component/combustible_flooder)) qdel(source.GetComponent(/datum/component/explodable)) @@ -205,10 +240,15 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "bluespace crystal" desc = "Crystals with bluespace properties" color = "#2E50B7" - greyscale_colors = "#2E50B7" alpha = 200 starlight_color = COLOR_BLUE - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_ITEM_MATERIAL = TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal ore_type = /obj/item/stack/ore/bluespace_crystal @@ -229,8 +269,14 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "bananium" desc = "Material with hilarious properties" color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow //It's literally perfect I can't change it - greyscale_colors = "#FFF269" - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + greyscale_color = "#FFF269" + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/bananium ore_type = /obj/item/stack/ore/bananium value_per_unit = 1000 / SHEET_MATERIAL_AMOUNT @@ -239,12 +285,12 @@ Unless you know what you're doing, only use the first three numbers. They're in mineral_rarity = MATERIAL_RARITY_UNDISCOVERED points_per_unit = 60 / SHEET_MATERIAL_AMOUNT -/datum/material/bananium/on_applied(atom/source, amount, material_flags) +/datum/material/bananium/on_applied(atom/source, mat_amount, multiplier) . = ..() - source.LoadComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50, falloff_exponent = 20) - source.AddComponent(/datum/component/slippery, min(amount / 10, 80)) + source.LoadComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50 * multiplier, falloff_exponent = 20) + source.AddComponent(/datum/component/slippery, min(mat_amount / 10 * multiplier, 80 * multiplier)) -/datum/material/bananium/on_removed(atom/source, amount, material_flags) +/datum/material/bananium/on_removed(atom/source, mat_amount, multiplier) . = ..() qdel(source.GetComponent(/datum/component/slippery)) qdel(source.GetComponent(/datum/component/squeak)) @@ -259,9 +305,14 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "titanium" desc = "Titanium" color = "#EFEFEF" - greyscale_colors = "#EFEFEF" strength_modifier = 1.3 - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/titanium ore_type = /obj/item/stack/ore/titanium value_per_unit = 125 / SHEET_MATERIAL_AMOUNT @@ -281,9 +332,13 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "runite" desc = "Runite" color = "#526F77" - greyscale_colors = "#526F77" strength_modifier = 1.3 - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/runite value_per_unit = 600 / SHEET_MATERIAL_AMOUNT beauty_modifier = 0.5 @@ -300,11 +355,16 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "plastic" desc = "Plastic" color = "#BFB9AC" - greyscale_colors = "#BFB9AC" strength_modifier = 0.85 sheet_type = /obj/item/stack/sheet/plastic ore_type = /obj/item/stack/ore/slag //No plastic or coal ore, so we use slag. - categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_SILO = TRUE, + MAT_CATEGORY_RIGID=TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) value_per_unit = 25 / SHEET_MATERIAL_AMOUNT beauty_modifier = -0.01 armor_modifiers = list(MELEE = 1.5, BULLET = 1.1, LASER = 0.3, ENERGY = 0.5, BOMB = 1, BIO = 1, FIRE = 1.1, ACID = 1) @@ -319,9 +379,8 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Force decrease and mushy sound effect. (Not yet implemented) /datum/material/biomass name = "biomass" - desc = "Organic matter" + desc = "Organic matter." color = "#735b4d" - greyscale_colors = "#735b4d" strength_modifier = 0.8 value_per_unit = 50 / SHEET_MATERIAL_AMOUNT @@ -329,24 +388,28 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "wood" desc = "Flexible, durable, but flamable. Hard to come across in space." color = "#855932" - greyscale_colors = "#855932" strength_modifier = 0.5 sheet_type = /obj/item/stack/sheet/mineral/wood - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) value_per_unit = 20 / SHEET_MATERIAL_AMOUNT beauty_modifier = 0.1 armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 0.4, ENERGY = 0.4, BOMB = 1, BIO = 0.2, ACID = 0.3) texture_layer_icon_state = "woodgrain" -/datum/material/wood/on_applied_obj(obj/source, amount, material_flags) +/datum/material/wood/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - if(material_flags & MATERIAL_AFFECT_STATISTICS) + if(source.material_flags & MATERIAL_AFFECT_STATISTICS && isobj(source)) var/obj/wooden = source wooden.resistance_flags |= FLAMMABLE -/datum/material/wood/on_removed_obj(obj/source, amount, material_flags) +/datum/material/wood/on_main_removed(atom/source, mat_amount, multiplier) . = ..() - if(material_flags & MATERIAL_AFFECT_STATISTICS) + if(source.material_flags & MATERIAL_AFFECT_STATISTICS && isobj(source)) var/obj/wooden = source wooden.resistance_flags &= ~FLAMMABLE @@ -362,9 +425,13 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "adamantine" desc = "A powerful material made out of magic, I mean science!" color = "#2B7A74" - greyscale_colors = "#2B7A74" strength_modifier = 1.5 - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/adamantine value_per_unit = 500 / SHEET_MATERIAL_AMOUNT beauty_modifier = 0.4 @@ -381,8 +448,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "mythril" desc = "How this even exists is byond me" color = "#f2d5d7" - greyscale_colors = "#f2d5d7" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/mythril value_per_unit = 1500 / SHEET_MATERIAL_AMOUNT strength_modifier = 1.2 @@ -391,13 +462,13 @@ Unless you know what you're doing, only use the first three numbers. They're in mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Doesn't naturally spawn on lavaland. points_per_unit = 100 / SHEET_MATERIAL_AMOUNT -/datum/material/mythril/on_applied_obj(atom/source, amount, material_flags) +/datum/material/mythril/on_applied(atom/source, mat_amount, multiplier) . = ..() if(isitem(source)) source.AddComponent(/datum/component/fantasy) ADD_TRAIT(source, TRAIT_INNATELY_FANTASTICAL_ITEM, REF(src)) // DO THIS LAST OR WE WILL NEVER GET OUR BONUSES!!! -/datum/material/mythril/on_removed_obj(atom/source, amount, material_flags) +/datum/material/mythril/on_removed(atom/source, mat_amount, multiplier) . = ..() if(isitem(source)) REMOVE_TRAIT(source, TRAIT_INNATELY_FANTASTICAL_ITEM, REF(src)) // DO THIS FIRST OR WE WILL NEVER GET OUR BONUSES DELETED!!! @@ -412,19 +483,23 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "hot ice" desc = "A weird kind of ice, feels warm to the touch" color = "#88cdf1" - greyscale_colors = "#88cdf196" alpha = 150 starlight_color = COLOR_BLUE_LIGHT - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/hot_ice value_per_unit = 400 / SHEET_MATERIAL_AMOUNT beauty_modifier = 0.2 -/datum/material/hot_ice/on_applied(atom/source, amount, material_flags) +/datum/material/hot_ice/on_applied(atom/source, mat_amount, multiplier) . = ..() - source.AddComponent(/datum/component/combustible_flooder, "plasma", amount*1.5, amount*0.2+300) + source.AddComponent(/datum/component/combustible_flooder, "plasma", mat_amount * 1.5 * multiplier, (mat_amount * 0.2 + 300) * multiplier) -/datum/material/hot_ice/on_removed(atom/source, amount, material_flags) +/datum/material/hot_ice/on_removed(atom/source, mat_amount, multiplier) qdel(source.GetComponent(/datum/component/combustible_flooder)) return ..() @@ -438,10 +513,14 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "Metal Hydrogen" desc = "Solid metallic hydrogen. Some say it should be impossible" color = "#62708A" - greyscale_colors = "#62708A" alpha = 150 starlight_color = COLOR_MODERATE_BLUE - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/metal_hydrogen value_per_unit = 700 / SHEET_MATERIAL_AMOUNT beauty_modifier = 0.35 @@ -457,8 +536,11 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "sand" desc = "You know, it's amazing just how structurally sound sand can be." color = "#EDC9AF" - greyscale_colors = "#EDC9AF" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/sandblock value_per_unit = 2 / SHEET_MATERIAL_AMOUNT strength_modifier = 0.5 @@ -477,8 +559,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "sandstone" desc = "Bialtaakid 'ant taerif ma hdha." color = "#ECD5A8" - greyscale_colors = "#ECD5A8" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/sandstone value_per_unit = 5 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 0.5, BULLET = 0.5, LASER = 1.25, ENERGY = 0.5, BOMB = 0.5, BIO = 0.25, FIRE = 1.5, ACID = 1.5) @@ -490,8 +576,11 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "snow" desc = "There's no business like snow business." color = COLOR_WHITE - greyscale_colors = COLOR_WHITE - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/snow value_per_unit = 5 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 0.25, BULLET = 0.25, LASER = 0.25, ENERGY = 0.25, BOMB = 0.25, BIO = 0.25, FIRE = 0.25, ACID = 1.5) @@ -507,8 +596,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "runed metal" desc = "Mir'ntrath barhah Nar'sie." color = "#504742" - greyscale_colors = "#504742" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/runed_metal value_per_unit = 1500 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 1.2, BULLET = 1.2, LASER = 1, ENERGY = 1, BOMB = 1.2, BIO = 1.2, FIRE = 1.5, ACID = 1.5) @@ -524,8 +617,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "bronze" desc = "Clock Cult? Never heard of it." color = "#876223" - greyscale_colors = "#876223" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/bronze value_per_unit = 50 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 1, BULLET = 1, LASER = 1, ENERGY = 1, BOMB = 1, BIO = 1, FIRE = 1.5, ACID = 1.5) @@ -535,8 +632,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "paper" desc = "Ten thousand folds of pure starchy power." color = "#E5DCD5" - greyscale_colors = "#E5DCD5" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/paperframes value_per_unit = 5 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 0.1, BULLET = 0.1, LASER = 0.1, ENERGY = 0.1, BOMB = 0.1, BIO = 0.1, ACID = 1.5) @@ -544,15 +645,15 @@ Unless you know what you're doing, only use the first three numbers. They're in turf_sound_override = FOOTSTEP_SAND texture_layer_icon_state = "paper" -/datum/material/paper/on_applied_obj(obj/source, amount, material_flags) +/datum/material/paper/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - if(material_flags & MATERIAL_AFFECT_STATISTICS) + if(isobj(source) && source.material_flags & MATERIAL_AFFECT_STATISTICS) var/obj/paper = source paper.resistance_flags |= FLAMMABLE paper.obj_flags |= UNIQUE_RENAME -/datum/material/paper/on_removed_obj(obj/source, amount, material_flags) - if(material_flags & MATERIAL_AFFECT_STATISTICS) +/datum/material/paper/on_main_removed(atom/source, mat_amount, multiplier) + if(isobj(source) && source.material_flags & MATERIAL_AFFECT_STATISTICS) var/obj/paper = source paper.resistance_flags &= ~FLAMMABLE return ..() @@ -561,22 +662,26 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "cardboard" desc = "They say cardboard is used by hobos to make incredible things." color = "#5F625C" - greyscale_colors = "#5F625C" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/cardboard value_per_unit = 6 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 0.25, BULLET = 0.25, LASER = 0.25, ENERGY = 0.25, BOMB = 0.25, BIO = 0.25, ACID = 1.5) beauty_modifier = -0.1 -/datum/material/cardboard/on_applied_obj(obj/source, amount, material_flags) +/datum/material/cardboard/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - if(material_flags & MATERIAL_AFFECT_STATISTICS) + if(isobj(source) && source.material_flags & MATERIAL_AFFECT_STATISTICS) var/obj/cardboard = source cardboard.resistance_flags |= FLAMMABLE cardboard.obj_flags |= UNIQUE_RENAME -/datum/material/cardboard/on_removed_obj(obj/source, amount, material_flags) - if(material_flags & MATERIAL_AFFECT_STATISTICS) +/datum/material/cardboard/on_main_removed(atom/source, mat_amount, multiplier) + if(isobj(source) && source.material_flags & MATERIAL_AFFECT_STATISTICS) var/obj/cardboard = source cardboard.resistance_flags &= ~FLAMMABLE return ..() @@ -585,8 +690,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "bone" desc = "Man, building with this will make you the coolest caveman on the block." color = "#e3dac9" - greyscale_colors = "#e3dac9" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/bone value_per_unit = 100 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 1.2, BULLET = 0.75, LASER = 0.75, ENERGY = 1.2, BOMB = 1, BIO = 1, FIRE = 1.5, ACID = 1.5) @@ -596,8 +705,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "bamboo" desc = "If it's good enough for pandas, it's good enough for you." color = "#87a852" - greyscale_colors = "#87a852" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/bamboo value_per_unit = 5 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 0.5, BULLET = 0.5, LASER = 0.5, ENERGY = 0.5, BOMB = 0.5, BIO = 0.51, FIRE = 0.5, ACID = 1.5) @@ -609,8 +722,12 @@ Unless you know what you're doing, only use the first three numbers. They're in name = "zaukerite" desc = "A light absorbing crystal" color = COLOR_ALMOST_BLACK - greyscale_colors = COLOR_ALMOST_BLACK - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/mineral/zaukerite value_per_unit = 900 / SHEET_MATERIAL_AMOUNT armor_modifiers = list(MELEE = 0.9, BULLET = 0.9, LASER = 1.75, ENERGY = 1.75, BOMB = 0.5, BIO = 1, FIRE = 0.1, ACID = 1) diff --git a/code/datums/materials/hauntium.dm b/code/datums/materials/hauntium.dm index 79e25441720..b8eee26a08f 100644 --- a/code/datums/materials/hauntium.dm +++ b/code/datums/materials/hauntium.dm @@ -2,10 +2,15 @@ name = "hauntium" desc = "very scary!" color = list(460/255, 464/255, 460/255, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) - greyscale_colors = "#FFFFFF64" + greyscale_color = "#FFFFFF" alpha = 100 starlight_color = COLOR_ALMOST_BLACK - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/hauntium value_per_unit = 0.05 beauty_modifier = 0.25 @@ -13,10 +18,14 @@ strength_modifier = 1.2 armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 1, ACID = 0.7) -/datum/material/hauntium/on_applied_obj(obj/o, amount, material_flags) +/datum/material/hauntium/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - o.make_haunted(INNATE_TRAIT, "#f8f8ff") + if(isobj(source)) + var/obj/obj = source + obj.make_haunted(INNATE_TRAIT, "#f8f8ff") -/datum/material/hauntium/on_removed_obj(obj/o, amount, material_flags) +/datum/material/hauntium/on_main_removed(atom/source, mat_amount, multiplier) . = ..() - o.remove_haunted(INNATE_TRAIT) + if(isobj(source)) + var/obj/obj = source + obj.remove_haunted(INNATE_TRAIT) diff --git a/code/datums/materials/meat.dm b/code/datums/materials/meat.dm index 552fa7a84cd..008099a526e 100644 --- a/code/datums/materials/meat.dm +++ b/code/datums/materials/meat.dm @@ -4,8 +4,12 @@ desc = "Meat" id = /datum/material/meat // So the bespoke versions are categorized under this color = rgb(214, 67, 67) - greyscale_colors = rgb(214, 67, 67) - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/meat value_per_unit = 0.05 beauty_modifier = -0.3 @@ -15,33 +19,28 @@ turf_sound_override = FOOTSTEP_MEAT texture_layer_icon_state = "meat" -/datum/material/meat/on_removed(atom/source, amount, material_flags) +/datum/material/meat/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - qdel(source.GetComponent(/datum/component/edible)) - qdel(source.GetComponent(/datum/component/blood_walk)) - qdel(source.GetComponent(/datum/component/bloody_spreader)) + if(!IS_EDIBLE(source)) + make_edible(source, mat_amount, multiplier) -/datum/material/meat/on_applied_obj(obj/O, amount, material_flags) +/datum/material/meat/on_applied(atom/source, mat_amount, multiplier) . = ..() - make_meaty(O, amount, material_flags) + if(IS_EDIBLE(source)) + make_edible(source, mat_amount, multiplier) -/datum/material/meat/on_applied_turf(turf/T, amount, material_flags) - . = ..() - make_meaty(T, amount, material_flags) - -/datum/material/meat/proc/make_meaty(atom/source, amount, material_flags) - var/nutriment_count = 3 * (amount / SHEET_MATERIAL_AMOUNT) - var/oil_count = 2 * (amount / SHEET_MATERIAL_AMOUNT) +/datum/material/meat/proc/make_edible(atom/source, mat_amount, multiplier) + var/nutriment_count = 3 * (mat_amount / SHEET_MATERIAL_AMOUNT) + var/oil_count = 2 * (mat_amount / SHEET_MATERIAL_AMOUNT) source.AddComponent(/datum/component/edible, \ initial_reagents = list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/nutriment/fat/oil = oil_count), \ foodtypes = RAW | MEAT | GROSS, \ eat_time = 3 SECONDS, \ tastes = list("Meaty")) - source.AddComponent( /datum/component/bloody_spreader,\ - blood_left = (nutriment_count + oil_count) * 0.3,\ + blood_left = (nutriment_count + oil_count) * 0.3 * multiplier,\ blood_dna = list("meaty DNA" = "MT-"),\ diseases = null,\ ) @@ -54,9 +53,18 @@ /datum/component/blood_walk,\ blood_type = /obj/effect/decal/cleanable/blood,\ blood_spawn_chance = 35,\ - max_blood = (nutriment_count + oil_count) * 0.3,\ + max_blood = (nutriment_count + oil_count) * 0.3 * multiplier,\ ) +/datum/material/meat/on_removed(atom/source, mat_amount, multiplier) + . = ..() + qdel(source.GetComponent(/datum/component/blood_walk)) + qdel(source.GetComponent(/datum/component/bloody_spreader)) + +/datum/material/meat/on_main_removed(atom/source, mat_amount, multiplier) + . = ..() + qdel(source.GetComponent(/datum/component/edible)) + /datum/material/meat/mob_meat init_flags = MATERIAL_INIT_BESPOKE var/subjectname = "" diff --git a/code/datums/materials/pizza.dm b/code/datums/materials/pizza.dm index 588018576be..1906e5786d2 100644 --- a/code/datums/materials/pizza.dm +++ b/code/datums/materials/pizza.dm @@ -2,8 +2,12 @@ name = "pizza" desc = "~Jamme, jamme, n'coppa, jamme ja! Jamme, jamme, n'coppa jamme ja, funi-culi funi-cala funi-culi funi-cala!! Jamme jamme ja funiculi funicula!~" color = "#FF9F23" - greyscale_colors = "#FF9F23" - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list( + MAT_CATEGORY_RIGID = TRUE, + MAT_CATEGORY_BASE_RECIPES = TRUE, + MAT_CATEGORY_ITEM_MATERIAL = TRUE, + MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE, + ) sheet_type = /obj/item/stack/sheet/pizza value_per_unit = 0.05 beauty_modifier = 0.1 @@ -13,23 +17,25 @@ turf_sound_override = FOOTSTEP_MEAT texture_layer_icon_state = "pizza" -/datum/material/pizza/on_removed(atom/source, amount, material_flags) +/datum/material/pizza/on_main_applied(atom/source, mat_amount, multiplier) . = ..() - qdel(source.GetComponent(/datum/component/edible)) + if(!IS_EDIBLE(source)) + make_edible(source, mat_amount) -/datum/material/pizza/on_applied_obj(obj/O, amount, material_flags) +/datum/material/pizza/on_applied(atom/source, mat_amount, multiplier) . = ..() - make_edible(O, amount, material_flags) + if(IS_EDIBLE(source)) + make_edible(source, mat_amount) -/datum/material/pizza/on_applied_turf(turf/T, amount, material_flags) - . = ..() - make_edible(T, amount, material_flags) - -/datum/material/pizza/proc/make_edible(atom/source, amount, material_flags) - var/nutriment_count = 3 * (amount / SHEET_MATERIAL_AMOUNT) - var/oil_count = 2 * (amount / SHEET_MATERIAL_AMOUNT) +/datum/material/pizza/proc/make_edible(atom/source, mat_amount) + var/nutriment_count = 3 * (mat_amount / SHEET_MATERIAL_AMOUNT) + var/oil_count = 2 * (mat_amount / SHEET_MATERIAL_AMOUNT) source.AddComponent(/datum/component/edible, \ initial_reagents = list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/nutriment/fat/oil = oil_count), \ foodtypes = GRAIN | MEAT | DAIRY | VEGETABLES, \ eat_time = 3 SECONDS, \ tastes = list("crust", "tomato", "cheese", "meat")) + +/datum/material/pizza/on_main_removed(atom/source, mat_amount, multiplier) + . = ..() + qdel(source.GetComponent(/datum/component/edible)) diff --git a/code/game/atom/atom_materials.dm b/code/game/atom/atom_materials.dm index 345a8486dd6..31ac1992a9b 100644 --- a/code/game/atom/atom_materials.dm +++ b/code/game/atom/atom_materials.dm @@ -7,23 +7,274 @@ ///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines. var/material_modifier = 1 -/// Sets the custom materials for an item. +/// Sets the custom materials for an atom. This is what you want to call, since most of the ones below are mainly internal. /atom/proc/set_custom_materials(list/materials, multiplier = 1) - if(custom_materials && material_flags & MATERIAL_EFFECTS) //Only runs if custom materials existed at first and affected src. - for(var/current_material in custom_materials) - var/datum/material/custom_material = GET_MATERIAL_REF(current_material) - custom_material.on_removed(src, OPTIMAL_COST(custom_materials[current_material] * material_modifier), material_flags) //Remove the current materials + SHOULD_NOT_OVERRIDE(TRUE) + if(length(custom_materials)) + remove_material_effects() if(!length(materials)) custom_materials = null return - if(material_flags & MATERIAL_EFFECTS) - for(var/current_material in materials) - var/datum/material/custom_material = GET_MATERIAL_REF(current_material) - custom_material.on_applied(src, OPTIMAL_COST(materials[current_material] * multiplier * material_modifier), material_flags) + initialize_materials(materials, multiplier) - custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) +/** + * The second part of set_custom_materials(), which handles applying the new materials + * It is a separate proc because Initialize calls may make use of this since they should've no prior materials to remove. + */ +/atom/proc/initialize_materials(list/materials, multiplier = 1) + SHOULD_NOT_OVERRIDE(TRUE) + if(multiplier != 1) + materials = materials.Copy() //avoid editing the list that was originally used as argument if it's ever going to be used again. + for(var/current_material in materials) + materials[current_material] *= multiplier + + apply_material_effects(materials) + custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials) + +///proc responsible for applying material effects when setting materials. +/atom/proc/apply_material_effects(list/materials) + SHOULD_CALL_PARENT(TRUE) + if(!materials || !(material_flags & MATERIAL_EFFECTS)) + return + var/list/material_effects = get_material_effects_list(materials) + finalize_material_effects(material_effects) + +/// Proc responsible for removing material effects when setting materials. +/atom/proc/remove_material_effects() + SHOULD_CALL_PARENT(TRUE) + //Only runs if custom materials existed at first and affected src. + if(!custom_materials || !(material_flags & MATERIAL_EFFECTS)) + return + var/list/material_effects = get_material_effects_list(custom_materials) + finalize_remove_material_effects(material_effects) + +/atom/proc/get_material_effects_list(list/materials) + SHOULD_NOT_OVERRIDE(TRUE) + var/list/material_effects = list() + var/index = 1 + for(var/current_material in materials) + var/datum/material/material = GET_MATERIAL_REF(current_material) + material_effects[material] = list( + MATERIAL_LIST_OPTIMAL_AMOUNT = OPTIMAL_COST(materials[current_material] * material_modifier), + MATERIAL_LIST_MULTIPLIER = get_material_multiplier(material, materials, index), + ) + index++ + return material_effects + +/** + * A proc that can be used to selectively control the statistics and affects from a material without affecting the others + * For example, we can have items made of two different materials, with the primary contributing a good 1.2 multiplier + * and the second a meager 0.3. + * The GET_MATERIAL_MODIFIER macro will handles some modifiers where the minimum should be 1 if above 1 and the maximum + * 1 if below 1, so you shouldn't worry about returning values between 0 and 1. Be ware about returning negative values tho. + */ +/atom/proc/get_material_multiplier(datum/material/custom_material, list/materials, index) + return 1 + +///Called by apply_material_effects(). It ACTUALLY handles applying effects common to all atoms (depending on material flags) +/atom/proc/finalize_material_effects(list/materials) + SHOULD_CALL_PARENT(TRUE) + var/total_alpha = 0 + var/list/colors = list() + var/mat_length = length(materials) + var/datum/material/main_material //the material with the highest amount (after calculations) + var/main_mat_amount + var/main_mat_mult + for(var/datum/material/custom_material as anything in materials) + var/list/deets = materials[custom_material] + var/mat_amount = deets[MATERIAL_LIST_OPTIMAL_AMOUNT] + var/multiplier = deets[MATERIAL_LIST_MULTIPLIER] + if(mat_amount > main_mat_amount) + main_material = custom_material + main_mat_amount = mat_amount + main_mat_mult = multiplier + + apply_single_mat_effect(custom_material, mat_amount, multiplier) + custom_material.on_applied(src, mat_amount, multiplier) + + //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example + if(material_flags & (MATERIAL_COLOR|MATERIAL_GREYSCALE)) + gather_material_color(custom_material, colors, mat_amount, multicolor = mat_length > 1) + var/added_alpha = custom_material.alpha * (custom_material.alpha / 255) + total_alpha += GET_MATERIAL_MODIFIER(added_alpha, multiplier) + if(custom_material.beauty_modifier) + AddElement(/datum/element/beauty, custom_material.beauty_modifier * mat_amount) + + apply_main_material_effects(main_material, main_mat_amount, main_mat_mult) + + if(material_flags & (MATERIAL_COLOR|MATERIAL_GREYSCALE)) + var/init_alpha = initial(alpha) + var/alpha_value = (total_alpha / length(materials)) * init_alpha + + if(alpha_value < init_alpha * 0.9) + opacity = FALSE + + if(material_flags & MATERIAL_GREYSCALE) + var/config_path = get_material_greyscale_config(main_material.type, greyscale_config) + //Make sure that we've no less than the expected amount + //expected_colors is zero for paths, the value is assigned when reading the json files. + var/datum/greyscale_config/config = SSgreyscale.configurations["[config_path || greyscale_config]"] + var/colors_len = length(colors) + if(config.expected_colors > colors_len) + var/list/filled_colors = colors.Copy() + for(var/index in colors_len to config.expected_colors - 1) + filled_colors += pick(colors) + colors = filled_colors + set_greyscale(colors, config_path) + else if(length(colors)) + mix_material_colors(colors) + + if(material_flags & MATERIAL_ADD_PREFIX) + var/prefixes = get_material_prefixes(materials) + name = "[prefixes] [name]" + +/** + * A proc used by both finalize_material_effects() and finalize_remove_material_effects() to get the colors + * that will later be applied to or removed from the atom + */ +/atom/proc/gather_material_color(datum/material/material, list/colors, amount, multicolor = FALSE) + SHOULD_CALL_PARENT(TRUE) + if(!material.color) //the material has no color. Nevermind + return + var/color_to_add = material.color + var/istext = istext(color_to_add) + if(istext) + if(material.alpha != 255) + color_to_add += num2hex(material.alpha, 2) + else + if(multicolor || material_flags & MATERIAL_GREYSCALE) + color_to_add = material.greyscale_color || color_matrix2color_hex(material.color) + if(material.greyscale_color) + color_to_add += num2hex(material.alpha, 2) + else + color_to_add = color_to_full_rgba_matrix(color_to_add) + color_to_add[20] *= (material.alpha / 255) // multiply the constant alpha of the color matrix + + colors[color_to_add] += amount + +/// Manages mixing, adding or removing the material colors from the atom in absence of the MATERIAL_GREYSCALE flag. +/atom/proc/mix_material_colors(list/colors, remove = FALSE) + SHOULD_NOT_OVERRIDE(TRUE) + var/color_len = length(colors) + if(!color_len) + return + var/mixcolor = colors[1] + var/amount_divisor = colors[mixcolor] + for(var/i in 2 to length(colors)) + var/color_to_add = colors[i] + if(islist(color_to_add)) + color_to_add = color_matrix2color_hex(color_to_add) + var/mix_amount = colors[color_to_add] + amount_divisor += mix_amount + mixcolor = BlendRGB(mixcolor, color_to_add, mix_amount/amount_divisor) + if(remove) + remove_atom_colour(FIXED_COLOUR_PRIORITY, mixcolor) + else + add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) + +///Returns the prefixes to attach to the atom when setting materials, from a list argument. +/atom/proc/get_material_prefixes(list/materials) + var/list/mat_names = list() + for(var/datum/material/material as anything in materials) + mat_names |= material.name + return mat_names.Join("-") + +///Returns a string like "plasma, paper and glass" from a list of materials +/atom/proc/get_material_english_list(list/materials) + var/list/mat_names = list() + for(var/datum/material/material as anything in materials) + mat_names += material.name + return english_list(mat_names) + +///Searches for a subtype of config_type that is to be used in its place for specific materials (like shimmering gold for cleric maces) +/atom/proc/get_material_greyscale_config(mat_type, config_type) + SHOULD_NOT_OVERRIDE(TRUE) + if(!config_type) + return + for(var/datum/greyscale_config/path as anything in subtypesof(config_type)) + if(mat_type != initial(path.material_skin)) + continue + return path + +///Apply material effects of a single material. +/atom/proc/apply_single_mat_effect(datum/material/custom_material, amount, multipier) + SHOULD_CALL_PARENT(TRUE) + return + +///A proc for material effects that only the main material (which the atom's primarly composed of) should apply. +/atom/proc/apply_main_material_effects(datum/material/main_material, amount, multipier) + SHOULD_CALL_PARENT(TRUE) + if(main_material.texture_layer_icon_state && material_flags & MATERIAL_COLOR) + ADD_KEEP_TOGETHER(src, MATERIAL_SOURCE(main_material)) + add_filter("material_texture_[main_material.name]", 1, layering_filter(icon = main_material.cached_texture_filter_icon, blend_mode = BLEND_INSET_OVERLAY)) + + main_material.on_main_applied(src, amount, multipier) + +///Called by remove_material_effects(). It ACTUALLY handles removing effects common to all atoms (depending on material flags) +/atom/proc/finalize_remove_material_effects(list/materials) + var/list/colors = list() + var/datum/material/main_material = get_master_material() + var/mat_length = length(materials) + var/main_mat_amount + var/main_mat_mult + for(var/datum/material/custom_material as anything in materials) + var/list/deets = materials[custom_material] + var/mat_amount = deets[MATERIAL_LIST_OPTIMAL_AMOUNT] + var/multiplier = deets[MATERIAL_LIST_MULTIPLIER] + if(custom_material == main_material) + main_mat_amount = mat_amount + main_mat_mult = multiplier + + remove_single_mat_effect(custom_material, mat_amount, multiplier) + custom_material.on_removed(src, mat_amount, multiplier) + if(material_flags & MATERIAL_COLOR) + gather_material_color(custom_material, colors, mat_amount, multicolor = mat_length > 1) + if(custom_material.beauty_modifier) + RemoveElement(/datum/element/beauty, custom_material.beauty_modifier * mat_amount) + + remove_main_material_effects(main_material, main_mat_amount, main_mat_mult) + + if(material_flags & (MATERIAL_GREYSCALE|MATERIAL_COLOR)) + if(material_flags & MATERIAL_COLOR) + mix_material_colors(colors, remove = TRUE) + else + set_greyscale(initial(greyscale_colors), initial(greyscale_config)) + alpha = initial(alpha) + opacity = initial(opacity) + + if(material_flags & MATERIAL_ADD_PREFIX) + name = initial(name) + +///Remove material effects of a single material. +/atom/proc/remove_single_mat_effect(datum/material/custom_material, amount, multipier) + SHOULD_CALL_PARENT(TRUE) + return + +///A proc to remove the material effects previously applied by the (ex-)main material +/atom/proc/remove_main_material_effects(datum/material/main_material, amount, multipier) + SHOULD_CALL_PARENT(TRUE) + if(main_material.texture_layer_icon_state) + remove_filter("material_texture_[main_material.name]") + REMOVE_KEEP_TOGETHER(src, MATERIAL_SOURCE(main_material)) + main_material.on_main_removed(src, amount, multipier) + +///Remove the old effects, change the material_modifier variable, and then reapply all the effects. +/atom/proc/change_material_modifier(new_value) + SHOULD_NOT_OVERRIDE(TRUE) + remove_material_effects() + material_modifier = new_value + apply_material_effects(custom_materials) + +///For enabling and disabling material effects from an item (mainly VV) +/atom/proc/toggle_material_flags(new_flags) + SHOULD_NOT_OVERRIDE(TRUE) + if(material_flags & MATERIAL_EFFECTS && !(new_flags & MATERIAL_EFFECTS)) + remove_material_effects() + else if(!(material_flags & MATERIAL_EFFECTS) && new_flags & MATERIAL_EFFECTS) + apply_material_effects() + material_flags = new_flags /** * Returns the material composition of the atom. diff --git a/code/game/atom/atom_vv.dm b/code/game/atom/atom_vv.dm index 10a6cbff24a..7a7dc8d3a87 100644 --- a/code/game/atom/atom_vv.dm +++ b/code/game/atom/atom_vv.dm @@ -270,6 +270,12 @@ if(NAMEOF(src, base_pixel_y)) set_base_pixel_y(var_value) . = TRUE + if(NAMEOF(src, material_flags)) + toggle_material_flags(var_value) + . = TRUE + if(NAMEOF(src, material_modifier)) + change_material_modifier(var_value) + . = TRUE light_flags = old_light_flags if(!isnull(.)) diff --git a/code/game/atom/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm index 4d539786537..3a8eaac4a45 100644 --- a/code/game/atom/atoms_initializing_EXPENSIVE.dm +++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm @@ -141,7 +141,8 @@ // This MUST come after atom_integrity is set above, as if old materials get removed, // atom_integrity is checked against max_integrity and can BREAK the atom. // The integrity to max_integrity ratio is still preserved. - set_custom_materials(custom_materials) + if(custom_materials) + initialize_materials(custom_materials) if(ispath(ai_controller)) ai_controller = new ai_controller(src) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 0a89c4e8b5b..06c88f4749e 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -112,7 +112,7 @@ highest_mat = present_mat highest_mat_ref = mat - flick_overlay_view(material_insertion_animation(highest_mat_ref.greyscale_colors), 1 SECONDS) + flick_overlay_view(material_insertion_animation(highest_mat_ref), 1 SECONDS) /obj/machinery/autolathe/ui_interact(mob/user, datum/tgui/ui) if(!is_operational) @@ -255,7 +255,7 @@ if(istext(material)) // category var/list/choices = list() for(var/datum/material/valid_candidate as anything in SSmaterials.materials_by_category[material]) - if(materials.get_material_amount(valid_candidate) < amount_needed) + if(materials.get_material_amount(valid_candidate) < (amount_needed + materials_needed[material])) continue choices[valid_candidate.name] = valid_candidate if(!length(choices)) @@ -274,7 +274,7 @@ if(isnull(material)) stack_trace("got passed an invalid material id: [material]") return - materials_needed[material] = amount_needed + materials_needed[material] += amount_needed //checks for available materials var/material_cost_coefficient = ispath(design.build_path, /obj/item/stack) ? 1 : creation_efficiency diff --git a/code/game/machinery/flatpacker.dm b/code/game/machinery/flatpacker.dm index 56fcc8a8ae7..6c90e45e4f6 100644 --- a/code/game/machinery/flatpacker.dm +++ b/code/game/machinery/flatpacker.dm @@ -124,7 +124,7 @@ highest_mat = present_mat highest_mat_ref = mat - flick_overlay_view(material_insertion_animation(highest_mat_ref.greyscale_colors), 1 SECONDS) + flick_overlay_view(material_insertion_animation(highest_mat_ref), 1 SECONDS) /** * Attempts to find the total material cost of a typepath (including our creation efficiency), modifying a list diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm index 2d92eaabb92..8f10717c771 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm @@ -36,7 +36,7 @@ /datum/dimension_theme/New() if (material) var/datum/material/using_mat = GET_MATERIAL_REF(material) - window_colour = using_mat.greyscale_colors + window_colour = using_mat.color /** * Applies themed transformation to the provided turf. diff --git a/code/game/objects/effects/material_insert.dm b/code/game/objects/effects/material_insert.dm index 9ca86226b24..3dcdd904a01 100644 --- a/code/game/objects/effects/material_insert.dm +++ b/code/game/objects/effects/material_insert.dm @@ -2,21 +2,18 @@ * Creates a mutable appearance with the material color applied for its insertion animation into an autolathe or techfab * Arguments * - * * color - the material color that will be applied + * * material - the material used to generate the overlay */ -/proc/material_insertion_animation(color) +/proc/material_insertion_animation(datum/material/material) RETURN_TYPE(/mutable_appearance) var/static/list/mutable_appearance/apps = list() - var/mutable_appearance/cached_app = apps[color] + var/mutable_appearance/cached_app = apps[material] if(isnull(cached_app)) - var/icon/modified_icon = icon('icons/obj/machines/research.dmi', "material_insertion") + cached_app = mutable_appearance('icons/obj/machines/research.dmi', "material_insertion") + cached_app.color = material.color + cached_app.alpha = material.alpha - //assuming most of the icon is white we find what ratio to scale the intensity of each part roughly - var/list/rgb_list = rgb2num(color) - modified_icon.SetIntensity(rgb_list[1] / 255, rgb_list[2] / 255, rgb_list[3] / 255) - cached_app = mutable_appearance(modified_icon, "material_insertion") - - apps[color] = cached_app + apps[material] = cached_app return cached_app diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index f9edb7952eb..f00c3d11fc5 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1872,6 +1872,56 @@ embed_data = ispath(embed) ? get_embed_by_type(embed) : embed SEND_SIGNAL(src, COMSIG_ITEM_EMBEDDING_UPDATE) +/obj/item/apply_main_material_effects(datum/material/main_material, amount, multipier) + . = ..() + if(material_flags & MATERIAL_GREYSCALE) + var/main_mat_type = main_material.type + var/worn_path = get_material_greyscale_config(main_mat_type, greyscale_config_worn) + var/lefthand_path = get_material_greyscale_config(main_mat_type, greyscale_config_inhand_left) + var/righthand_path = get_material_greyscale_config(main_mat_type, greyscale_config_inhand_right) + set_greyscale( + new_worn_config = worn_path, + new_inhand_left = lefthand_path, + new_inhand_right = righthand_path + ) + if(!main_material.item_sound_override) + return + hitsound = main_material.item_sound_override + usesound = main_material.item_sound_override + mob_throw_hit_sound = main_material.item_sound_override + equip_sound = main_material.item_sound_override + pickup_sound = main_material.item_sound_override + drop_sound = main_material.item_sound_override + +/obj/item/remove_main_material_effects(datum/material/main_material, amount, multipier) + . = ..() + if(material_flags & MATERIAL_GREYSCALE) + set_greyscale( + new_worn_config = initial(greyscale_config_worn), + new_inhand_left = initial(greyscale_config_inhand_left), + new_inhand_right = initial(greyscale_config_inhand_right) + ) + if(!main_material.item_sound_override) + return + hitsound = initial(hitsound) + usesound = initial(usesound) + mob_throw_hit_sound = initial(mob_throw_hit_sound) + equip_sound = initial(equip_sound) + pickup_sound = initial(pickup_sound) + drop_sound = initial(drop_sound) + +/obj/item/apply_single_mat_effect(datum/material/material, mat_amount, multiplier) + . = ..() + if(!(material_flags & MATERIAL_AFFECT_STATISTICS) || !slowdown) + return + slowdown += GET_MATERIAL_MODIFIER(material.added_slowdown * mat_amount, multiplier) + +/obj/item/remove_single_mat_effect(datum/material/material, mat_amount, multiplier) + . = ..() + if(!(material_flags & MATERIAL_AFFECT_STATISTICS) || !slowdown) + return + slowdown -= GET_MATERIAL_MODIFIER(material.added_slowdown * mat_amount, multiplier) + /** * Returns the atom(either itself or an internal module) that will interact/attack the target on behalf of us * For example an object can have different `tool_behaviours` (e.g borg omni tool) but will return an internal reference of that tool to attack for us diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 7703160bfdb..29df25d179c 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -514,10 +514,10 @@ greyscale_config_inhand_left = /datum/greyscale_config/cleric_mace_lefthand greyscale_config_inhand_right = /datum/greyscale_config/cleric_mace_righthand greyscale_config_worn = /datum/greyscale_config/cleric_mace - greyscale_colors = COLOR_WHITE + greyscale_colors = COLOR_WHITE + COLOR_BROWN material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_GREYSCALE | MATERIAL_AFFECT_STATISTICS //Material type changes the prefix as well as the color. - custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT*6) //Defaults to an Iron Mace. + custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 4.5, /datum/material/wood = SHEET_MATERIAL_AMOUNT * 1.5) //Defaults to an Iron Mace. slot_flags = ITEM_SLOT_BELT force = 14 w_class = WEIGHT_CLASS_BULKY @@ -528,6 +528,26 @@ attack_verb_continuous = list("smacks", "strikes", "cracks", "beats") attack_verb_simple = list("smack", "strike", "crack", "beat") +///Cleric maces are made of two custom materials: one is handle, and the other is the mace itself. +/obj/item/melee/cleric_mace/get_material_multiplier(datum/material/custom_material, list/materials, index) + if(length(materials) < 1) + return 1.2 + if(index == 1) + return 1 + else + return 0.3 + +/obj/item/melee/cleric_mace/get_material_prefixes(list/materials) + var/datum/material/material = materials[1] + return material.name //It only inherits the name of the main material it's made of. The secondary is in the description. + +/obj/item/melee/cleric_mace/finalize_material_effects(list/materials) + . = ..() + if(length(materials) == 1) + return + var/datum/material/material = materials[2] + desc = "[initial(desc)] Its handle is made of [material.name]." + /obj/item/melee/cleric_mace/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK) final_block_chance = 0 //Don't bring a...mace to a gunfight, and also you aren't going to really block someone full body tackling you with a mace diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index b5aa0a30c3c..0e995120c00 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -77,18 +77,19 @@ amount = new_amount while(amount > max_amount) amount -= max_amount - new type(loc, max_amount, FALSE) + new type(loc, max_amount, FALSE, mat_override, mat_amt) if(!merge_type) merge_type = type - 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) - . = ..() + + var/materials_mult = amount + if(LAZYLEN(mat_override)) + materials_mult *= mat_amt + mats_per_unit = mat_override + if(LAZYLEN(mats_per_unit)) + initialize_materials(mats_per_unit, materials_mult) + if(merge) for(var/obj/item/stack/item_stack in loc) if(item_stack == src) @@ -118,26 +119,15 @@ if(is_path_in_list(merge_type, GLOB.golem_stack_food_directory)) AddComponent(/datum/component/golem_food, golem_food_key = merge_type) -/** Sets the amount of materials per unit for this stack. - * - * Arguments: - * - [mats][/list]: The value to set the mats per unit to. - * - multiplier: The amount to multiply the mats per unit by. Defaults to 1. - */ -/obj/item/stack/proc/set_mats_per_unit(list/mats, multiplier=1) - mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats, multiplier) - update_custom_materials() - -/** Updates the custom materials list of this stack. - */ +///Called to lazily update the materials of the item whenever the used or if more is added /obj/item/stack/proc/update_custom_materials() - set_custom_materials(mats_per_unit, amount, is_update=TRUE) + if(length(mats_per_unit)) + set_custom_materials(mats_per_unit, amount) -/** - * Override to make things like metalgen accurately set custom materials - */ -/obj/item/stack/set_custom_materials(list/materials, multiplier=1, is_update=FALSE) - return is_update ? ..() : set_mats_per_unit(materials, multiplier/(amount || 1)) +/obj/item/stack/apply_material_effects(list/materials) + . = ..() + if(amount) + mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(materials, 1/amount) /obj/item/stack/blend_requirements() if(is_cyborg) @@ -440,7 +430,7 @@ if((recipe.crafting_flags & CRAFT_APPLIES_MATS) && LAZYLEN(mats_per_unit)) if(isstack(created)) var/obj/item/stack/crafted_stack = created - crafted_stack.set_mats_per_unit(mats_per_unit, recipe.req_amount / recipe.res_amount) + crafted_stack.set_custom_materials(mats_per_unit, (recipe.req_amount / recipe.res_amount) * crafted_stack.amount) else created.set_custom_materials(mats_per_unit, recipe.req_amount / recipe.res_amount) @@ -543,8 +533,7 @@ amount -= used if(check && is_zero_amount(delete_if_zero = TRUE)) return TRUE - if(length(mats_per_unit)) - update_custom_materials() + update_custom_materials() update_appearance() update_weight() return TRUE @@ -591,8 +580,7 @@ source.add_charge(_amount * cost) else amount += _amount - if(length(mats_per_unit)) - update_custom_materials() + update_custom_materials() update_appearance() update_weight() diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 56aef2176f8..bf1b37f0d98 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -19,7 +19,7 @@ hitsound = 'sound/items/weapons/smash.ogg' drop_sound = 'sound/items/handling/toolbox/toolbox_drop.ogg' pickup_sound = 'sound/items/handling/toolbox/toolbox_pickup.ogg' - material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR + material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS var/latches = "single_latch" var/has_latches = TRUE wound_bonus = 5 diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 0a88aade697..c51adf91b3b 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -291,3 +291,28 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) pixel_z = anchored_tabletop_offset else pixel_z = initial(pixel_z) + +/obj/apply_single_mat_effect(datum/material/material, mat_amount, multiplier) + . = ..() + if(!(material_flags & MATERIAL_AFFECT_STATISTICS)) + return + var/integrity_mod = GET_MATERIAL_MODIFIER(material.integrity_modifier, multiplier) + modify_max_integrity(ceil(max_integrity * integrity_mod)) + var/strength_mod = GET_MATERIAL_MODIFIER(material.strength_modifier, multiplier) + force *= strength_mod + throwforce *= strength_mod + var/list/armor_mods = material.get_armor_modifiers(multiplier) + set_armor(get_armor().generate_new_with_multipliers(armor_mods)) + +///This proc is called when the material is removed from an object specifically. +/obj/remove_single_mat_effect(datum/material/material, mat_amount, multiplier) + . = ..() + if(!(material_flags & MATERIAL_AFFECT_STATISTICS)) + return + var/integrity_mod = GET_MATERIAL_MODIFIER(material.integrity_modifier, multiplier) + modify_max_integrity(floor(max_integrity / integrity_mod)) + var/strength_mod = GET_MATERIAL_MODIFIER(material.strength_modifier, multiplier) + force /= strength_mod + throwforce /= strength_mod + var/list/armor_mods = material.get_armor_modifiers(1 / multiplier) + set_armor(get_armor().generate_new_with_multipliers(armor_mods)) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index a4d35f02e0c..5c2f1972c33 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -392,8 +392,9 @@ var/datum/material/material_datum = material new material_datum.sheet_type(loc, FLOOR(custom_materials[material_datum] / SHEET_MATERIAL_AMOUNT, 1)) -/obj/structure/falsewall/material/mat_update_desc(mat) - desc = "A huge chunk of [mat] used to separate rooms." +/obj/structure/falsewall/material/finalize_material_effects(list/materials) + . = ..() + desc = "A huge chunk of [get_material_english_list(materials)] used to separate rooms." /obj/structure/falsewall/material/toggle_open() if(!QDELETED(src)) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 72a3d861016..20164d3072f 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -361,13 +361,10 @@ material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS buildstack = null //No buildstack, so generate from mat datums -/obj/structure/table/greyscale/set_custom_materials(list/materials, multiplier) +/obj/structure/table/greyscale/finalize_material_effects(list/materials) . = ..() - var/list/materials_list = list() - for(var/custom_material in custom_materials) - var/datum/material/current_material = GET_MATERIAL_REF(custom_material) - materials_list += "[current_material.name]" - desc = "A square [(materials_list.len > 1) ? "amalgamation" : "piece"] of [english_list(materials_list)] on four legs. It can not move." + var/english_list = get_material_english_list(materials) + desc = "A square [(length(materials) > 1) ? "amalgamation" : "piece"] of [english_list] on four legs. It can not move." ///Table on wheels /obj/structure/table/rolling diff --git a/code/game/turfs/closed/wall/material_walls.dm b/code/game/turfs/closed/wall/material_walls.dm index 5f16a68584f..f8f9d58c220 100644 --- a/code/game/turfs/closed/wall/material_walls.dm +++ b/code/game/turfs/closed/wall/material_walls.dm @@ -22,6 +22,7 @@ var/datum/material/M = i new M.sheet_type(src, FLOOR(custom_materials[M] / SHEET_MATERIAL_AMOUNT, 1)) -/turf/closed/wall/material/mat_update_desc(mat) - desc = "A huge chunk of [mat] used to separate rooms." +/turf/closed/wall/material/finalize_material_effects(list/materials) + . = ..() + desc = "A huge chunk of [get_material_english_list(materials)] used to separate rooms." diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 68c3c1a1c77..a841db9265e 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -494,6 +494,15 @@ playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE) new used_tiles.tile_type(src) +/turf/open/apply_main_material_effects(datum/material/main_material, amount, multipier) + . = ..() + if(!main_material.turf_sound_override) + return + footstep = main_material.turf_sound_override + barefootstep = main_material.turf_sound_override + "barefoot" + clawfootstep = main_material.turf_sound_override + "claw" + heavyfootstep = FOOTSTEP_GENERIC_HEAVY + /// Very similar to build_with_rods, this exists to allow building transport/tram girders on openspace /turf/open/proc/build_with_titanium(obj/item/stack/sheet/mineral/titanium/used_stack, user) var/obj/structure/transport/linear/platform = locate(/obj/structure/transport/linear, src) diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index dad46fd8de6..c3ea3694043 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -382,4 +382,4 @@ . = ..() if(.) var/obj/item/stack/tile = . - tile.set_mats_per_unit(custom_materials, 1) + tile.set_custom_materials(custom_materials) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index c9256f2e0c8..db185ba38ec 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -772,6 +772,23 @@ GLOBAL_LIST_EMPTY(station_turfs) inherent_explosive_resistance = explosion_block explosive_resistance += get_explosive_block() +/turf/apply_main_material_effects(datum/material/main_material, amount, multipier) + . = ..() + if(alpha < 255) + AddElement(/datum/element/turf_z_transparency) + main_material.setup_glow(src) + rust_resistance = main_material.mat_rust_resistance + +/turf/remove_main_material_effects(datum/material/custom_material, amount, multipier) + . = ..() + rust_resistance = initial(rust_resistance) + if(alpha == 255) + return + RemoveElement(/datum/element/turf_z_transparency) + // yeets glow + UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) + set_light(0, 0, null) + /// Returns whether it is safe for an atom to move across this turf /turf/proc/can_cross_safely(atom/movable/crossing) return TRUE diff --git a/code/modules/atmospherics/machinery/components/tank.dm b/code/modules/atmospherics/machinery/components/tank.dm index f76f3dc470f..6aa23f84e93 100644 --- a/code/modules/atmospherics/machinery/components/tank.dm +++ b/code/modules/atmospherics/machinery/components/tank.dm @@ -88,7 +88,6 @@ air_contents = new air_contents.temperature = T20C air_contents.volume = volume - refresh_pressure_limit() if(gas_type) fill_to_pressure(gas_type) @@ -121,7 +120,7 @@ . += span_notice("The pipe port can be moved or closed with a [wrench_hint].") . += span_notice("A holographic sticker on it says that its maximum safe pressure is: [siunit_pressure(max_pressure, 0)].") -/obj/machinery/atmospherics/components/tank/set_custom_materials(list/materials, multiplier) +/obj/machinery/atmospherics/components/tank/finalize_material_effects(list/materials) . = ..() refresh_pressure_limit() diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm index 4037a51c691..dd3093a0aaf 100644 --- a/code/modules/cargo/materials_market.dm +++ b/code/modules/cargo/materials_market.dm @@ -143,7 +143,7 @@ trend_string = "down" //get mat color - var/initial_colors = initial(traded_mat.greyscale_colors) + var/initial_colors = initial(traded_mat.greyscale_color) || initial(traded_mat.color) if(initial_colors) color_string = splicetext(initial_colors, 7, length(initial_colors), "") //slice it to a standard 6 char hex else diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 7ad08083df3..0b051248a39 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -442,14 +442,13 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ pixel_x = base_pixel_x + rand(0, 16) - 8 pixel_y = base_pixel_y + rand(0, 8) - 8 -/obj/item/coin/set_custom_materials(list/materials, multiplier = 1) +/obj/item/coin/finalize_material_effects(list/materials) . = ..() if(override_material_worth) return value = 0 - for(var/i in custom_materials) - var/datum/material/M = i - value += M.value_per_unit * custom_materials[M] + for(var/datum/material/material as anything in materials) + value += material.value_per_unit * materials[material][MATERIAL_LIST_OPTIMAL_AMOUNT] /obj/item/coin/get_item_credit_value() return value diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 13ac09c9a52..b1758086444 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2709,7 +2709,7 @@ taste_mult = 0 // oderless and tasteless chemical_flags = REAGENT_NO_RANDOM_RECIPE /// The material flags used to apply the transmuted materials - var/applied_material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR + var/applied_material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS /// The amount of materials to apply to the transmuted objects if they don't contain materials var/default_material_amount = 100 diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index f0e0978a607..ebda0f1e3b4 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -434,7 +434,7 @@ desc = "A mace fit for a cleric. Useful for bypassing plate armor, but too bulky for much else." id = "cleric_mace" build_type = AUTOLATHE - materials = list(MAT_CATEGORY_ITEM_MATERIAL = SHEET_MATERIAL_AMOUNT * 6) + materials = list(MAT_CATEGORY_ITEM_MATERIAL = SHEET_MATERIAL_AMOUNT * 4.5, MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = SHEET_MATERIAL_AMOUNT * 1.5) build_path = /obj/item/melee/cleric_mace category = list(RND_CATEGORY_IMPORTED) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index 40725c6f198..57044fd831f 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -174,7 +174,7 @@ SHOULD_CALL_PARENT(FALSE) //first play the insertion animation - flick_overlay_view(material_insertion_animation(mat_ref.greyscale_colors), 1 SECONDS) + flick_overlay_view(material_insertion_animation(mat_ref), 1 SECONDS) //now play the progress bar animation flick_overlay_view(mutable_appearance('icons/obj/machines/research.dmi', "protolathe_progress"), 1 SECONDS) diff --git a/icons/obj/weapons/cleric_mace.dmi b/icons/obj/weapons/cleric_mace.dmi index 3dc90bf10c446bb63cce4a11832dc08f9196dc48..ad7fdbc09a22a835af06d34763d218bad86caa7f 100644 GIT binary patch literal 2712 zcmbtWdpy(o8~?6379%8c>loso910PdAx(-1XCx;ixs&^4m`g%SNg>x1rJZazu5+7m zS^eBEGq+r}YH2a6lg)L%Isg3r`2E=*pU?aCd0x-!^LgIS=XpP`C(GfYwYaE)C;$NB zHs`Dy1=zK>_6rMk$GISg0J`IyT_df0BD}->Z$|ouh5$fpNnTFB=$qq`XK8~jVk=h@ zB8#&d&dILmJ{q+(eXW+RHnR|ONlMBf+6c@Xk`DnicY28}Mg~@>s$6{4Yt{poqwPu?$c$d7`qQ{?ME=(`Sw%Tolb-#2;)O#F zF*44imd2iw8G_3$x!`@zchjF+)Q|jt&{F$hH`Zp+v zctb^JANaMM7FhI%j_7hr#CLOtoLlcKZ#7G{K5&pc>-ZsfB53Bga;v6Imc*SiZZFTE z3Qf|w2X5ZD6!PgeyNHK#5vwF-5`O{JP!z#l;gXqil}Q@kw>Kgle~2sliy9zbk){@# zFnfCV6)m7qHwbR+n0PHdd5g>T#$c`#Drw*u8Y#@Us98#mGYVYW(Lp$xCpzDm2n94@ zxW8Pr`_OlrD9r@&8e;gBzF5ayA`!ull?xBXOo10#zQZphcmlIcBFbR|xN1zZ%+dOm5pB?cs zF{^X0ISdNt+s6w(J`E~<2sd6y_roO2qDcK)*bIxQswfeIYF-%vb33{%yUPB_K0xVo zYG!)6^!5!ubBBj8qq5-5V{hr_#^&T>-$R7ByJ<3GnfI>XYXRi^}y}1 z993!U&U)YBKDPt`so;{-8yxOflTcAv*(z*dWwsdtTbP{8CoUZ{G9%gaAAB3bo=4;j zGsEaTBFAE`&I%|7Y4w=$J!ftt->Aob+c=FzqYoVNsGpuVX?u;*oGsD#a8wU$P;7V7 z)D)MOC)1AM9_ZT5RU?|#tZ;%ErP%NXNXQy4G&op%ItV6UvI?6UEH?T>rvPVS^=vQA zytH42FRQp$$}77j)YsP|dSxMd&sOvN4WyCaDIGJxsgF+ceg+8P*gIQXG;X1f*Hp** zA#V!o^cD;=2{7#3zb=6vG8P3v0$pg%w9-P8g+zn)?q^gHsA%xTCXZ7=r8gUQ1`}nl zRpXbQJHE?;8;Xf1dn9Psm-WodC`8A^5Dt+EoZtuo59ApaCl7@}GZj)D@s%c}_ePb) z#k&GH2{AYMLxH$#j$-z0>6p4otwW-PFI6=2&IfpTf%^OVTP12JBf}sxj!9)(?}`9Z zTS0vA^No#-DfTWeZAC@JFj++MP8&b(n2Wf+=UaONeCX>mQ}dNCU5f>9)B3?dMv4Un@+}X zbqY=wr4v{TcP=CfT)VzdvMGoXsO4SWMm;*OF0(Es>B|9w^UV+97ASP1evf(E%_!+s zq$r2HISkMft2Auf2rz-axWYQ@v!;iU1&c58TX;5Sb;Qc156JNo1G0V!l0jumD(Osx zVgsaneEDTSqr!zNZKpOV)>0>hbcD5ryeCiOuLIRJHAjjE-$d@Ge}N-Ke#QJ~Me}xS z;bbC>rj!ho)w#ZTrktg-LcT{Z%Vo$NO05l@DJL_>l7O!3OvF)X8pYMSI-v2dzo)e) zX*AGR$dNCBGoRsb>Zvx97ygiQ(#&i0li3KNEqxI1`vp}#QKG9*@IOfp540)1!1Gc@ zhcV7Ci1+INUcU?$wsz+DYWUk|KJTS)A|p*AGz0PWIY-_zHv>IRqr`@eEIMlbNAGQV z6#uvv3td3l>Hch@>qOJY|I|Va_+vR<_+}k1Q9!!83^eAvZT2VAhrZeK&BE2NnEK7c zaFgQHT8A*n>Vu~%kIDfDvq3)%mf)O!U>~mM<9?r^oG<`vLM)W}Lh*j_cTaIGGrdcc z3!vDEMI{A*c13D4(aH{XaSo%>BcIyP5FiG%um{|~kl`;JH1|@B(JE-_kQ}Q;ri4x; zipHCClcumpTfW{JA8DGeNNQaj&$b-%xMl5)b6RC{+e z8QzDyzqqlSgqvFan`OE{S>l*Yk97_75lh*h~1@cu7F#RrEHMe zWi8#f8f)Sv2!kEJzRaqbkRT5(Qjosofw0U8STDOt z##&!}_`5R!eIaO^I5=qc;|ukedwcAOI?7|=yz^%V2M3oX@J?>T`h5AWNVtu_bz%ehtMmN*C4-E6pANEEogA-IF|<10dhz*vF4S z4Tcmd)qB1-iVRO>(P~V?+KH`UjN9ku#3U=p3vLi@`w>IRuSk>^^XE`w9>isTt$$#6(lNmE0 z+@scXeRY)>jyE;*1?~)d+>w$4?r5I^KkE0XGOO?eH1!I6fll%B&%%U%S{whTut5^w zd{m~9L@I1q#|Ts^7%XPZ?lp`jmX<<+2NwnH?vr!qNI0oFIyyS10ad-@6iz^Iy_u}5 zEX-nkoe;~J(CK*{Dui1&EKQrn18R*DiEBeW5U&VZci*agUGnCJdv;$y^?gYZC^PbZ cwc9`jo(0-#y7xni1*0ZlbM~SY(b6;Zzh+GdY5)KL literal 2664 zcmbtWc{JPk7XJlpW0$E`(TcUBeI>O&l-QzLEvhEgQe9$SY7engt0g8v6;({CD8|;- z*h(y&MtDkTYip4#ri&E>SLl!_Dp z0J3MC9Na~`fA@g*im3Zs_&yQ)J=w!6&f$9O)tHdzxR9tw07xn?${&$>c~Su}J?be# z_s7JQ;eK;cqQmY_oUzN!?E_9igaU>4#ihy zTD$Q`)kR|EXZo;VYNwg8gJbQz`r3h&0?*?;YFqHTBx#*WG_zT_x~`;pXu93dbs^PR z(Jk?SM}(G|szyt8af%EG03hBl*hk zCl%ilQ6p%j&r3w3($|z&M%S`6<;|1vujMIgr}|RHDstW^qc>MeI~5TH^~eS-mwm(Q z++M^5j|OBz0M|ONaeIgjaMma#bb16Wxx6utu;+r}BnE1aG?(q)+-$G+IL=%eRfRx~ z9n5{=b>a!~=Uy_WscpSV_gBarl#AF&bMp`?wL6*p>tV};b6C=2WmVN!1HYv~PSd5z zi(Go@Diz_0L~85zHZ|#$mX<;w1!O#Qw1ko|H)c zVA7SsX)Zs7cK7c|3iR(w)4O=_;*|6Rhuh1JDZvY6Y-fVvCEwR`f3Z$I?(6Hz{4%^B z0zt2Ty2)-6A=WXy&5Vnhh-cSh#8;KCvux77t= z3Mx6-$ECtzadB)H%t9}#lhqLvvA1q|W!F+%Tr77Wfau?0at=l2;O>4H@G1p;XTK{%HEy~?v#mk$QjDo4UsPyl=!}M; zRc}-iiEttbmBqO85Oj}ZW?(SkfeBd`=_{~MqB2*xKXEs5Gb|xbm6TuJM>lI(YR1;)v{4lkygyPA`pJwOh+3x(_L5|*UR3(VFpWpr2S#M=i zi5mA|V-?w2+wX@mim0Sp12oGPnDwCRFYshDI2>*m4nA9Rue73~h(tnsygOY@;{g94 zvb+AlNR+&gQQy6u!?*7lBMZ#&1~*dxD9DiO0Vt zwL3L%5qaSLvm2uB-1+ip)Rl)z7Yc}I_V=O=DkoKde&-y>*{@h8XC;mi&X)}G_5CUQ zyYkRvB8z7&Je32zLZjvpq^Uw^`jz{9G;^(M%2>Qn5vIcG9&+v5sbP*zrwR1qeWz=? z7_JuJ{_lOYujS#Q^dA3V3DGS&`{bjM%|jCGElRR_=a1W@kuuwK#>;^gJAUnES@zeR zYJ1*RZRNYukBI!aJq^O6hrl=%W89_~0@OJIk5oVzp%TEae_iOmsf!I=9Y3^p1r%(o zf9YRkg7RA12wt%JQi zB_93lZB4(R%uDaMSWT;x!SJ z!{#l6)v)caPP`#4~@+ zvEc7AN>_wCkv=6i^v90DQZ&9aA-bJ7u@(>1R?X5j+@%lPDS;NG>x^a{JZh#Kc23jR0d_7I+%U} z$C5_FZuc-;6~YqJ&J)BIiNZ9MWwJjwFfbjc8(b5!H4y_Q!GMPr;D!Ti{;E(s*Bdi% zzppDl*Z-_HQm~ZSl}cKOKe~(M70vtC9@Yqj#$*v_&)3T3oyF z%tTsd@}Lf*y~xq1Mi+ao&1W?HT{8|R%VI7%cVV_-PYd9zm;nq(i(S~_3YrK~=T#BVjGujXJr<({k? z6o~Rx{(rvlpFR)UfN?1NNIQ=fMwS648znLX+;7nn&;ZL1kNdH1oYR*jC3cI&o8f@e zF~f|R?(XiR)r^_fz#*R@o|Xb2qh~IDe`N8Ib%o}x$_RkovNJ*by&3aoaQ_`rdz3QH z)?6_)H8q@0gJB>0C?ZTKD4VfT8x=pU0rpWQhCF;XtukY`5&J|_y+(0