Skip to content

Commit

Permalink
Basemats: Alloy Support (#10859)
Browse files Browse the repository at this point in the history
* tgstation/tgstation#53623

* tgstation/tgstation#54863

* Hmmm. Need to get alien structures to use the element aswell, maybe?

* 515

* .

* merge skew
  • Loading branch information
Tsar-Salat authored Jul 14, 2024
1 parent f00cd51 commit 36e1cd5
Show file tree
Hide file tree
Showing 31 changed files with 491 additions and 85 deletions.
2 changes: 2 additions & 0 deletions beestation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\mechanical_repair.dm"
#include "code\datums\elements\mirage_border.dm"
#include "code\datums\elements\obj_regen.dm"
#include "code\datums\elements\openspace_item_click_handler.dm"
#include "code\datums\elements\pet_bonus.dm"
#include "code\datums\elements\point_of_interest.dm"
Expand Down Expand Up @@ -890,6 +891,7 @@
#include "code\datums\martial\tribal_claw.dm"
#include "code\datums\martial\wrestling.dm"
#include "code\datums\materials\_material.dm"
#include "code\datums\materials\alloys.dm"
#include "code\datums\materials\basemats.dm"
#include "code\datums\materials\meat.dm"
#include "code\datums\mocking\client.dm"
Expand Down
7 changes: 6 additions & 1 deletion code/__DEFINES/dcs/signals/signals_obj/signals_object.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
// All signals send the source datum of the signal as the first argument

// /obj signals
#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench"

///from base of [/obj/proc/take_damage]: (damage_amount, damage_type, damage_flag, sound_effect, attack_dir, aurmor_penetration)
#define COMSIG_OBJ_TAKE_DAMAGE "obj_take_damage"
/// Return bitflags for the above signal which prevents the object taking any damage.
#define COMPONENT_NO_TAKE_DAMAGE (1<<0)
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //! from base of obj/deconstruct(): (disassembled)
#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench"
#define COMSIG_OBJ_HIDE "obj_hide" //from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide

/// from /obj/proc/make_unfrozen()
Expand Down
34 changes: 34 additions & 0 deletions code/__DEFINES/materials.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,34 @@
///Use this flag on TRUE if you want the basic recipes
#define MAT_CATEGORY_BASE_RECIPES "basic recipes"

/// Used to make a material initialize at roundstart.
#define MATERIAL_INIT_MAPLOAD (1<<0)

//Material Container Flags.
///If the container shows the amount of contained materials on examine.
#define MATCONTAINER_EXAMINE (1<<0)
///If the container cannot have materials inserted through attackby().
#define MATCONTAINER_NO_INSERT (1<<1)
///if the user can insert mats into the container despite the intent.
#define MATCONTAINER_ANY_INTENT (1<<2)
///if the user won't receive a warning when attacking the container with an unallowed item.
#define MATCONTAINER_SILENT (1<<3)
// The following flags are for decomposing alloys. Should be expanded upon and diversified once someone gets around to reworking recycling.
/// Can reduce an alloy into its component materials.
#define BREAKDOWN_ALLOYS (1<<4)
/// Breakdown flags used by techfabs and circuit printers.
#define BREAKDOWN_FLAGS_LATHE (BREAKDOWN_ALLOYS)
/// Breakdown flags used by the ORM.
#define BREAKDOWN_FLAGS_ORM (BREAKDOWN_ALLOYS)
/// Breakdown flags used by the recycler.
#define BREAKDOWN_FLAGS_RECYCLER (BREAKDOWN_ALLOYS)
/// Breakdown flags used by the sheetifier.
#define BREAKDOWN_FLAGS_SHEETIFIER (BREAKDOWN_ALLOYS)
/// Breakdown flags used by the ore processor.
#define BREAKDOWN_FLAGS_ORE_PROCESSOR (BREAKDOWN_ALLOYS)
/// Breakdown flags used by the drone dispenser.
#define BREAKDOWN_FLAGS_DRONE_DISPENSER (BREAKDOWN_ALLOYS)

/// Whether a material's mechanical effects should apply to the atom. This is necessary for other flags to work.
#define MATERIAL_EFFECTS (1<<0)
/// Applies the material color to the atom's color. Deprecated, use MATERIAL_GREYSCALE instead
Expand All @@ -20,6 +48,12 @@

#define MATERIAL_SOURCE(mat) "[mat.name]_material"

// Slowdown values.
/// The slowdown value of one [MINERAL_MATERIAL_AMOUNT] of plasteel.
#define MATERIAL_SLOWDOWN_PLASTEEL (0.05)
/// The slowdown value of one [MINERAL_MATERIAL_AMOUNT] of alien alloy.
#define MATERIAL_SLOWDOWN_ALIEN_ALLOY (0.1)

/// Create standardized stack sizes.

#define STACKSIZE_MACRO(Path)\
Expand Down
8 changes: 8 additions & 0 deletions code/_globalvars/bitfields.dm
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ DEFINE_BITFIELD(movement_type, list(
"PHASING" = PHASING
))

DEFINE_BITFIELD(mat_container_flags, list(
"MATCONTAINER_EXAMINE" = MATCONTAINER_EXAMINE,
"MATCONTAINER_NO_INSERT" = MATCONTAINER_NO_INSERT,
"MATCONTAINER_ANY_INTENT" = MATCONTAINER_ANY_INTENT,
"MATCONTAINER_SILENT" = MATCONTAINER_SILENT,
"BREAKDOWN_ALLOYS" = BREAKDOWN_ALLOYS,
))

DEFINE_BITFIELD(resistance_flags, list(
"LAVA_PROOF" = LAVA_PROOF,
"FIRE_PROOF" = FIRE_PROOF,
Expand Down
6 changes: 5 additions & 1 deletion code/controllers/subsystem/materials.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ SUBSYSTEM_DEF(materials)
materialtypes_by_category = list()
material_combos = list()
for(var/type in subtypesof(/datum/material))
var/datum/material/ref = new type
var/datum/material/ref = type
if(!(initial(ref.init_flags) & MATERIAL_INIT_MAPLOAD))
continue // Do not initialize

ref = new ref
materials[type] = ref
for(var/c in ref.categories)
materials_by_category[c] += list(ref)
Expand Down
90 changes: 54 additions & 36 deletions code/datums/components/material_container.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@
var/max_amount
var/sheet_type
var/list/materials //Map of key = material ref | Value = amount
var/show_on_examine
var/disable_attackby
var/list/allowed_typecache
var/last_inserted_id
var/precise_insertion = FALSE
var/datum/callback/precondition
var/datum/callback/after_insert
///The material container flags. See __DEFINES/materials.dm.
var/mat_container_flags

/// Sets up the proper signals and fills the list of materials with the appropriate references.
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _mat_container_flags=NONE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert)
materials = list()
max_amount = max(0, max_amt)
show_on_examine = _show_on_examine
disable_attackby = _disable_attackby
mat_container_flags = _mat_container_flags

if(allowed_types)
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
Expand All @@ -38,67 +38,82 @@
precondition = _precondition
after_insert = _after_insert

RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(OnAttackBy))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(OnExamine))
if(!(mat_container_flags & MATCONTAINER_NO_INSERT))
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(on_attackby))
if(mat_container_flags & MATCONTAINER_EXAMINE)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))

for(var/mat in mat_list) //Make the assoc list ref | amount
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
materials[M] = 0

/datum/component/material_container/proc/OnExamine(datum/source, mob/user)
/datum/component/material_container/vv_edit_var(var_name, var_value)
var/old_flags = mat_container_flags
. = ..()
if(var_name == NAMEOF(src, mat_container_flags) && parent)
if(!(old_flags & MATCONTAINER_EXAMINE) && mat_container_flags & MATCONTAINER_EXAMINE)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
else if(old_flags & MATCONTAINER_EXAMINE && !(mat_container_flags & MATCONTAINER_EXAMINE))
UnregisterSignal(parent, COMSIG_PARENT_EXAMINE)

if(old_flags & MATCONTAINER_NO_INSERT && !(mat_container_flags & MATCONTAINER_NO_INSERT))
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(on_attackby))
else if(!(old_flags & MATCONTAINER_NO_INSERT) && mat_container_flags & MATCONTAINER_NO_INSERT)
UnregisterSignal(parent, COMSIG_PARENT_ATTACKBY)


/datum/component/material_container/proc/on_examine(datum/source, mob/user, list/examine_texts)
SIGNAL_HANDLER

if(show_on_examine)
for(var/I in materials)
var/datum/material/M = I
var/amt = materials[I]
if(amt)
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
for(var/I in materials)
var/datum/material/M = I
var/amt = materials[I]
if(amt)
examine_texts += "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>"

/// Proc that allows players to fill the parent with mats
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
/datum/component/material_container/proc/on_attackby(datum/source, obj/item/I, mob/living/user)
SIGNAL_HANDLER

var/list/tc = allowed_typecache
if(disable_attackby)
return
if(user.a_intent != INTENT_HELP)
if(!(mat_container_flags & MATCONTAINER_ANY_INTENT) && user.a_intent != INTENT_HELP)
return
if(I.item_flags & ABSTRACT)
return
if((I.flags_1 & HOLOGRAM_1) || (I.item_flags & NO_MAT_REDEMPTION) || (tc && !is_type_in_typecache(I, tc)))
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
if(!(mat_container_flags & MATCONTAINER_SILENT))
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
return
. = COMPONENT_NO_AFTERATTACK
var/datum/callback/pc = precondition
if(pc && !pc.Invoke(user))
return
var/material_amount = get_item_material_amount(I)
var/material_amount = get_item_material_amount(I, mat_container_flags)
if(!material_amount)
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [parent].</span>")
return
if(!has_space(material_amount))
to_chat(user, "<span class='warning'>[parent] is full. Please remove materials from [parent] in order to insert more.</span>")
return
user_insert(I, user)
user_insert(I, user, mat_container_flags)

/// Proc used for when player inserts materials
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user)
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user, breakdown_flags = mat_container_flags)
set waitfor = FALSE
var/requested_amount
var/active_held = user.get_active_held_item() // differs from I when using TK
if(istype(I, /obj/item/stack) && precise_insertion)
if(isstack(I) && precise_insertion)
var/atom/current_parent = parent
var/obj/item/stack/S = I
requested_amount = input(user, "How much do you want to insert?", "Inserting [S.singular_name]s") as num|null
if(isnull(requested_amount) || (requested_amount <= 0))
requested_amount = tgui_input_number(user, "How much do you want to insert?", "Inserting [S.singular_name]s", S.amount, S.amount)
if(!requested_amount || QDELETED(I) || QDELETED(user) || QDELETED(src))
return
if(QDELETED(I) || QDELETED(user) || QDELETED(src) || parent != current_parent || user.physical_can_use_topic(current_parent) < UI_INTERACTIVE || user.get_active_held_item() != active_held)
if(parent != current_parent || user.get_active_held_item() != active_held)
return
if(!user.temporarilyRemoveItemFromInventory(I))
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
return
var/inserted = insert_item(I, stack_amt = requested_amount)
var/inserted = insert_item(I, stack_amt = requested_amount, breakdown_flags= mat_container_flags)
if(inserted)
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
qdel(I)
Expand All @@ -108,26 +123,28 @@
user.put_in_active_hand(I)

/// Proc specifically for inserting items, returns the amount of materials entered.
/datum/component/material_container/proc/insert_item(obj/item/I, var/multiplier = 1, stack_amt)
/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1, stack_amt, breakdown_flags = mat_container_flags)
if(QDELETED(I))
return FALSE

multiplier = CEILING(multiplier, 0.01)

var/material_amount = get_item_material_amount(I)
var/material_amount = get_item_material_amount(I, breakdown_flags)
if(!material_amount || !has_space(material_amount))
return FALSE

last_inserted_id = insert_item_materials(I, multiplier)
last_inserted_id = insert_item_materials(I, multiplier, breakdown_flags)
return material_amount

/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1)
/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1, breakdown_flags = mat_container_flags)
var/primary_mat
var/max_mat_value = 0
var/list/item_materials = I.get_material_composition(breakdown_flags)
for(var/MAT in materials)
materials[MAT] += I.custom_materials[MAT] * multiplier
total_amount += I.custom_materials[MAT] * multiplier
if(I.custom_materials[MAT] > max_mat_value)
materials[MAT] += item_materials[MAT] * multiplier
total_amount += item_materials[MAT] * multiplier
if(item_materials[MAT] > max_mat_value)
max_mat_value = item_materials[MAT]
primary_mat = MAT
if(primary_mat)
SEND_SIGNAL(parent, COMSIG_MATERIAL_CONTAINER_CHANGED)
Expand Down Expand Up @@ -318,12 +335,13 @@


///returns the amount of material relevant to this container; if this container does not support glass, any glass in 'I' will not be taken into account
/datum/component/material_container/proc/get_item_material_amount(obj/item/I)
/datum/component/material_container/proc/get_item_material_amount(obj/item/I, breakdown_flags = mat_container_flags)
if(!istype(I) || !I.custom_materials)
return FALSE
return 0 //Not Boolean, dont make FALSE
var/material_amount = 0
var/list/item_materials = I.get_material_composition(breakdown_flags)
for(var/MAT in materials)
material_amount += I.custom_materials[MAT]
material_amount += item_materials[MAT]
return material_amount

/// Returns the amount of a specific material in this container.
Expand Down
9 changes: 6 additions & 3 deletions code/datums/components/remote_materials.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ handles linking back and forth.
var/category
var/allow_standalone
var/local_size = INFINITY
///Flags used when converting inserted materials into their component materials.
var/mat_container_flags = NONE

/datum/component/remote_materials/Initialize(category, mapload, allow_standalone = TRUE, force_connect = FALSE)
/datum/component/remote_materials/Initialize(category, mapload, allow_standalone = TRUE, force_connect = FALSE, mat_container_flags=NONE)
if (!isatom(parent))
return COMPONENT_INCOMPATIBLE

src.category = category
src.allow_standalone = allow_standalone
src.mat_container_flags = mat_container_flags

RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(OnAttackBy))
RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(check_z_disconnect))
Expand Down Expand Up @@ -71,7 +74,7 @@ handles linking back and forth.
/datum/material/plastic,
)

mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, allowed_types=/obj/item/stack)
mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, mat_container_flags, /obj/item/stack)

/datum/component/remote_materials/proc/set_local_size(size)
local_size = size
Expand Down Expand Up @@ -115,7 +118,7 @@ handles linking back and forth.
SIGNAL_HANDLER

if (silo && istype(I, /obj/item/stack))
if (silo.remote_attackby(parent, user, I))
if (silo.remote_attackby(parent, user, I, mat_container_flags))
return COMPONENT_NO_AFTERATTACK

/datum/component/remote_materials/proc/recieve_buffer(datum/source, mob/user, datum/buffer, obj/item/buffer_parent)
Expand Down
Loading

0 comments on commit 36e1cd5

Please sign in to comment.