mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-25 17:12:12 +00:00
* Machines now transfer their local materials to silo during linking (#78263) ## About The Pull Request - Closes #78029 Rather than dumping their local materials as sheets on the turf, machines (protolathe, exosuit fab, component printer and others that can link to silo) now transfers their materials from local storage to silo during linking with multitool This way you don't have to pick up the sheets and manually put them in the silo yourself & this can also save you from a lot of manual labour of picking up sheets when you have a large amount of local materials stored inside. ## Changelog 🆑 qol: Machines now transfer their local materials to silo during linking with multitool /🆑 * Machines now transfer their local materials to silo during linking --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
253 lines
8.9 KiB
Plaintext
253 lines
8.9 KiB
Plaintext
/*
|
|
This component allows machines to connect remotely to a material container
|
|
(namely an /obj/machinery/ore_silo) elsewhere. It offers optional graceful
|
|
fallback to a local material storage in case remote storage is unavailable, and
|
|
handles linking back and forth.
|
|
*/
|
|
|
|
/datum/component/remote_materials
|
|
// Three possible states:
|
|
// 1. silo exists, materials is parented to silo
|
|
// 2. silo is null, materials is parented to parent
|
|
// 3. silo is null, materials is null
|
|
|
|
///The silo machine this container is connected to
|
|
var/obj/machinery/ore_silo/silo
|
|
///Material container. the value is either the silo or local
|
|
var/datum/component/material_container/mat_container
|
|
///Should we create a local storage if we can't connect to silo
|
|
var/allow_standalone
|
|
///Local size of container when silo = null
|
|
var/local_size = INFINITY
|
|
///Flags used when converting inserted materials into their component materials.
|
|
var/mat_container_flags = NONE
|
|
|
|
/datum/component/remote_materials/Initialize(mapload, allow_standalone = TRUE, force_connect = FALSE, mat_container_flags = NONE)
|
|
if (!isatom(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.allow_standalone = allow_standalone
|
|
src.mat_container_flags = mat_container_flags
|
|
|
|
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(OnMultitool))
|
|
|
|
var/turf/T = get_turf(parent)
|
|
var/connect_to_silo = FALSE
|
|
if(force_connect || (mapload && is_station_level(T.z)))
|
|
connect_to_silo = TRUE
|
|
RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, TYPE_PROC_REF(/datum/component/remote_materials, SiloAttackBy))
|
|
|
|
if(mapload) // wait for silo to initialize during mapload
|
|
addtimer(CALLBACK(src, PROC_REF(_PrepareStorage), connect_to_silo))
|
|
else //directly register in round
|
|
_PrepareStorage(connect_to_silo)
|
|
|
|
/**
|
|
* Internal proc. prepares local storage if onnect_to_silo = FALSE
|
|
*
|
|
* Arguments
|
|
* connect_to_silo- if true connect to global silo. If not successfull then go to local storage
|
|
* only if allow_standalone = TRUE, else you a null mat_container
|
|
*/
|
|
/datum/component/remote_materials/proc/_PrepareStorage(connect_to_silo)
|
|
if (connect_to_silo)
|
|
silo = GLOB.ore_silo_default
|
|
if (silo)
|
|
silo.ore_connected_machines += src
|
|
mat_container = silo.GetComponent(/datum/component/material_container)
|
|
if (!mat_container && allow_standalone)
|
|
_MakeLocal()
|
|
|
|
/datum/component/remote_materials/Destroy()
|
|
if (silo)
|
|
silo.ore_connected_machines -= src
|
|
silo.holds -= src
|
|
silo.updateUsrDialog()
|
|
silo = null
|
|
mat_container = null
|
|
return ..()
|
|
|
|
/datum/component/remote_materials/proc/_MakeLocal()
|
|
silo = null
|
|
|
|
var/static/list/allowed_mats = list(
|
|
/datum/material/iron,
|
|
/datum/material/glass,
|
|
/datum/material/silver,
|
|
/datum/material/gold,
|
|
/datum/material/diamond,
|
|
/datum/material/plasma,
|
|
/datum/material/uranium,
|
|
/datum/material/bananium,
|
|
/datum/material/titanium,
|
|
/datum/material/bluespace,
|
|
/datum/material/plastic,
|
|
)
|
|
|
|
mat_container = parent.AddComponent( \
|
|
/datum/component/material_container, \
|
|
allowed_mats, \
|
|
local_size, \
|
|
mat_container_flags, \
|
|
allowed_items = /obj/item/stack \
|
|
)
|
|
|
|
/datum/component/remote_materials/proc/toggle_holding(force_hold = FALSE)
|
|
if(isnull(silo))
|
|
return
|
|
|
|
if(force_hold)
|
|
silo.holds[src] = TRUE
|
|
else if(!silo.holds[src])
|
|
silo.holds[src] = TRUE
|
|
else
|
|
silo.holds -= src
|
|
|
|
/datum/component/remote_materials/proc/set_local_size(size)
|
|
local_size = size
|
|
if (!silo && mat_container)
|
|
mat_container.max_amount = size
|
|
|
|
/**
|
|
* Disconnect this component from the remote silo
|
|
*
|
|
* Arguments
|
|
* old_silo- The silo we are trying to disconnect from
|
|
*/
|
|
/datum/component/remote_materials/proc/disconnect_from(obj/machinery/ore_silo/old_silo)
|
|
if (!old_silo || silo != old_silo)
|
|
return
|
|
silo.ore_connected_machines -= src
|
|
silo = null
|
|
mat_container = null
|
|
if (allow_standalone)
|
|
_MakeLocal()
|
|
|
|
///Insert mats into silo
|
|
/datum/component/remote_materials/proc/SiloAttackBy(datum/source, obj/item/target, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(silo)
|
|
mat_container.user_insert(target, user, mat_container_flags, parent)
|
|
|
|
return COMPONENT_NO_AFTERATTACK
|
|
|
|
/datum/component/remote_materials/proc/OnMultitool(datum/source, mob/user, obj/item/I)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!I.multitool_check_buffer(user, I))
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
var/obj/item/multitool/M = I
|
|
if (!QDELETED(M.buffer) && istype(M.buffer, /obj/machinery/ore_silo))
|
|
if (silo == M.buffer)
|
|
to_chat(user, span_warning("[parent] is already connected to [silo]!"))
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
if(!check_z_level(M.buffer))
|
|
to_chat(user, span_warning("[parent] is too far away to get a connection signal!"))
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
var/obj/machinery/ore_silo/new_silo = M.buffer
|
|
var/datum/component/material_container/new_container = new_silo.GetComponent(/datum/component/material_container)
|
|
if (silo)
|
|
silo.ore_connected_machines -= src
|
|
silo.holds -= src
|
|
silo.updateUsrDialog()
|
|
else if (mat_container)
|
|
//transfer all mats to silo. whatever cannot be transfered is dumped out as sheets
|
|
if(mat_container.total_amount())
|
|
for(var/datum/material/mat as anything in mat_container.materials)
|
|
var/mat_amount = mat_container.materials[mat]
|
|
if(!mat_amount || !new_container.has_space(mat_amount) || !new_container.can_hold_material(mat))
|
|
continue
|
|
new_container.materials[mat] += mat_amount
|
|
mat_container.materials[mat] = 0
|
|
qdel(mat_container)
|
|
silo = new_silo
|
|
silo.ore_connected_machines += src
|
|
silo.updateUsrDialog()
|
|
mat_container = new_container
|
|
RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, TYPE_PROC_REF(/datum/component/remote_materials, SiloAttackBy))
|
|
to_chat(user, span_notice("You connect [parent] to [silo] from the multitool's buffer."))
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
/**
|
|
* Checks if the param silo is in the same level as this components parent i.e. connected machine, rcd, etc
|
|
*
|
|
* Arguments
|
|
* silo_to_check- Is this components parent in the same Z level as this param silo. If null
|
|
* then check this components connected silo
|
|
*
|
|
* Returns true if both are on the station or same z level
|
|
*/
|
|
/datum/component/remote_materials/proc/check_z_level(obj/silo_to_check = silo)
|
|
if(isnull(silo_to_check))
|
|
return FALSE
|
|
|
|
return is_valid_z_level(get_turf(silo_to_check), get_turf(parent))
|
|
|
|
/// returns TRUE if this connection put on hold by the silo
|
|
/datum/component/remote_materials/proc/on_hold()
|
|
return check_z_level() ? silo.holds[src] : FALSE
|
|
|
|
/**
|
|
* Internal proc to check if this connection can use any materials from the silo
|
|
* Returns true only if
|
|
* - The parent is of type movable atom
|
|
* - A mat container is actually present
|
|
* - The silo in not on hold
|
|
*/
|
|
/datum/component/remote_materials/proc/_can_use_resource()
|
|
var/atom/movable/movable_parent = parent
|
|
if (!istype(movable_parent))
|
|
return FALSE
|
|
if (!mat_container) //no silolink & local storage not supported
|
|
movable_parent.say("No access to material storage, please contact the quartermaster.")
|
|
return FALSE
|
|
if(on_hold()) //silo on hold
|
|
movable_parent.say("Mineral access is on hold, please contact the quartermaster.")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/**
|
|
* Use materials from either the silo(if connected) or from the local storage. If silo then this action
|
|
* is logged else not e.g. action="build" & name="matter bin" means you are trying to build an matter bin
|
|
*
|
|
* Arguments
|
|
* [mats][list]- list of materials to use
|
|
* coefficient- each mat unit is scaled by this value then rounded. This value if usually your machine efficiency e.g. upgraded protolathe has reduced costs
|
|
* multiplier- each mat unit is scaled by this value then rounded after it is scaled by coefficient. This value is your print quatity e.g. printing multiple items
|
|
* action- For logging only. e.g. build, create, i.e. the action you are trying to perform
|
|
* name- For logging only. the design you are trying to build e.g. matter bin, etc.
|
|
*/
|
|
/datum/component/remote_materials/proc/use_materials(list/mats, coefficient = 1, multiplier = 1, action = "build", name = "design")
|
|
if(!_can_use_resource())
|
|
return 0
|
|
|
|
var/amount_consumed = mat_container.use_materials(mats, coefficient, multiplier)
|
|
|
|
if (silo)//log only if silo is linked
|
|
var/list/scaled_mats = list()
|
|
for(var/i in mats)
|
|
scaled_mats[i] = OPTIMAL_COST(OPTIMAL_COST(mats[i] * coefficient) * multiplier)
|
|
silo.silo_log(parent, action, -multiplier, name, scaled_mats)
|
|
|
|
return amount_consumed
|
|
|
|
/**
|
|
* Ejects the given material ref and logs it
|
|
*
|
|
* Arguments
|
|
* [material_ref][datum/material]- The material type you are trying to eject
|
|
* eject_amount- how many sheets to eject
|
|
* [drop_target][atom]- optional where to drop the sheets. null means it is dropped at this components parent location
|
|
*/
|
|
/datum/component/remote_materials/proc/eject_sheets(datum/material/material_ref, eject_amount, atom/drop_target = null)
|
|
if(!_can_use_resource())
|
|
return 0
|
|
|
|
var/atom/movable/movable_parent = parent
|
|
if(isnull(drop_target))
|
|
drop_target = movable_parent.drop_location()
|
|
|
|
return mat_container.retrieve_sheets(eject_amount, material_ref, target = drop_target, context = parent)
|