mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-21 06:36:48 +01:00
- separates the composition of cyborgs into modules, iconsets, chassis, upgrades - modules / chassis atm can provide items, so can upgrades; in the future we will want to probably generalize the item API a bit so components can work - chassis now can (unimplemented) easily be made to give different stats - reorganizes all the cyborg sprites - adds generalized item mounts with redirection support and tears out legacy cyborg items - entirely rebalances modules & writes some new lawsets in for future use --------- Co-authored-by: silicons <silicons@silicons.dev>
350 lines
10 KiB
Plaintext
350 lines
10 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2024 Citadel Station Developers *//
|
|
|
|
/**
|
|
* Arbitrary provider for resources, management, etc.
|
|
*
|
|
* * Used to allow things like cyborgs to provide water to things
|
|
* that would usually require internal tanks; this is just an example.
|
|
* * Usage procs have 'item' and 'key'. This is so you can route things like air
|
|
* around.
|
|
* * Items don't actually need to be mounted to use things. That's why
|
|
* there's minimally stateful procs. Some stateful procs just gracefully
|
|
* reject the usage / check if an item isn't mounted.
|
|
*
|
|
* ## Relaying
|
|
*
|
|
* Item mounts have an inbuilt relay system as 'mount an item that will be used in a module in a cyborg
|
|
* or rigsuit or mech' is a common patern.
|
|
*
|
|
* * Please know what you're doing if you use it. For performance reasons, there's no infinite loop guards.
|
|
* * If you use this system, it's on you to unlink it as needed and not cause GC issues.
|
|
*/
|
|
/datum/item_mount
|
|
/// mounted items; lazy list
|
|
var/list/obj/item/mounted_items
|
|
/// relay to other item mount by default
|
|
var/datum/item_mount/relay_to_other
|
|
/// item mounts relaying to us
|
|
var/list/datum/item_mount/relay_to_self
|
|
|
|
/datum/item_mount/Destroy()
|
|
for(var/obj/item/mounted as anything in mounted_items)
|
|
unmount(mounted)
|
|
relay_unlink_all()
|
|
relay_clear()
|
|
return ..()
|
|
|
|
/datum/item_mount/proc/relay_to(datum/item_mount/other)
|
|
relay_to_other = other
|
|
LAZYADD(relay_to_other.relay_to_self, src)
|
|
|
|
/datum/item_mount/proc/relay_clear()
|
|
if(!relay_to_other)
|
|
return
|
|
LAZYREMOVE(relay_to_other.relay_to_self, src)
|
|
relay_to_other = null
|
|
|
|
/datum/item_mount/proc/relay_unlink_all()
|
|
for(var/datum/item_mount/mount as anything in relay_to_self)
|
|
mount.relay_clear()
|
|
|
|
/datum/item_mount/proc/mount(obj/item/item)
|
|
if(item.item_mount)
|
|
if(item.item_mount == src)
|
|
return TRUE
|
|
item.item_mount.unmount(item)
|
|
|
|
LAZYADD(mounted_items, item)
|
|
item.item_mount = src
|
|
on_item_mount(item)
|
|
return TRUE
|
|
|
|
/datum/item_mount/proc/unmount(obj/item/item)
|
|
if(item.item_mount != src)
|
|
return TRUE
|
|
LAZYREMOVE(mounted_items, item)
|
|
item.item_mount = null
|
|
on_item_unmount(item)
|
|
return TRUE
|
|
|
|
/datum/item_mount/proc/is_mounted(obj/item/item)
|
|
return item in mounted_items
|
|
|
|
/**
|
|
* Called when a mounted item is deleted.
|
|
*/
|
|
/datum/item_mount/proc/on_item_del(obj/item/being_deleted)
|
|
unmount(being_deleted)
|
|
|
|
/datum/item_mount/proc/on_item_mount(obj/item/item)
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
/datum/item_mount/proc/on_item_unmount(obj/item/item)
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
//* Gas *//
|
|
|
|
/**
|
|
* Get estimated gas pressure.
|
|
*
|
|
* @return null, or number
|
|
*/
|
|
/datum/item_mount/proc/gas_get_pressure(obj/item/item, key)
|
|
return relay_to_other?.gas_get_pressure(item, key)
|
|
|
|
/**
|
|
* Unsafe: Directly references a gas_mixture for a channel.
|
|
*
|
|
* @return null, or ref
|
|
*/
|
|
/datum/item_mount/proc/gas_mixture_ref(obj/item/item, key)
|
|
return relay_to_other?.gas_mixture_ref(item, key)
|
|
|
|
/**
|
|
* Returns a gas mixture by pulling a given liter amount.
|
|
*
|
|
* @return null, or ref
|
|
*/
|
|
/datum/item_mount/proc/gas_pull_volume(obj/item/item, key, liters)
|
|
return relay_to_other?.gas_pull_volume(item, key)
|
|
|
|
/**
|
|
* Fast: erases a given liter amount of gas. Usually used with [gas_mixture_ref]
|
|
* being used to check first.
|
|
*
|
|
* @return null, or moles deleted
|
|
*/
|
|
/datum/item_mount/proc/gas_erase_volume(obj/item/item, key, liters)
|
|
return relay_to_other?.gas_pull_volume(item, key)
|
|
|
|
//* Materials *//
|
|
|
|
/**
|
|
* Get the name of the provider.
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
*
|
|
* @return null, or name
|
|
*/
|
|
/datum/item_mount/proc/material_get_provider_name(obj/item/item, key, material_id)
|
|
return relay_to_other?.material_get_provider_name(item, key, material_id)
|
|
|
|
/**
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
* * Amount is in cm3
|
|
*
|
|
* @return null, or amount in cm3
|
|
*/
|
|
/datum/item_mount/proc/material_get_amount(obj/item/item, key, material_id)
|
|
return relay_to_other?.material_get_amount(item, key, material_id)
|
|
|
|
/**
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
* * Amount is in cm3
|
|
*
|
|
* @return null, or TRUE / FALSE.
|
|
*/
|
|
/datum/item_mount/proc/material_has_amount(obj/item/item, key, material_id, amount)
|
|
return relay_to_other?.material_has_amount(item, key, material_id, amount)
|
|
|
|
/**
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
* * Amount is in cm3.
|
|
*
|
|
* @return null, or amount used in cm3.
|
|
*/
|
|
/datum/item_mount/proc/material_use_amount(obj/item/item, key, material_id, amount)
|
|
return relay_to_other?.material_use_amount(item, key, material_id, amount)
|
|
|
|
/**
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
* * Amount is in cm3.
|
|
*
|
|
* @return null, or amount used.
|
|
*/
|
|
/datum/item_mount/proc/material_use_checked_amount(obj/item/item, key, material_id, amount)
|
|
return material_has_amount(item, key, material_id, amount) && material_use_amount(item, key, material_id, amount)
|
|
|
|
/**
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
* * Amount is in cm3.
|
|
*
|
|
* @return null, or amount given.
|
|
*/
|
|
/datum/item_mount/proc/material_give_amount(obj/item/item, key, material_id, amount, force)
|
|
return relay_to_other?.material_give_amount(item, key, material_id, amount, force)
|
|
|
|
/**
|
|
* * Material is any resolvable material, so ID, path, or instance.
|
|
* * Amount is in cm3.
|
|
*
|
|
* @return null, or max amount.
|
|
*/
|
|
/datum/item_mount/proc/material_get_capacity(obj/item/item, key, material_id)
|
|
return relay_to_other?.material_get_capacity(item, key, material_id)
|
|
|
|
//* Power *//
|
|
|
|
/**
|
|
* Lazy use-power-oneoff style thing
|
|
*
|
|
* @return null, or TRUE / FALSE for has that amount of energy
|
|
*/
|
|
/datum/item_mount/proc/lazy_energy_check(obj/item/item, key, joules)
|
|
return relay_to_other?.lazy_energy_check(item, key, joules)
|
|
|
|
/**
|
|
* Lazy use-power-oneoff style thing
|
|
*
|
|
* @return null, or joules supplied
|
|
*/
|
|
/datum/item_mount/proc/lazy_energy_use(obj/item/item, key, joules, minimum_reserve)
|
|
return relay_to_other?.lazy_energy_use(item, key, joules, minimum_reserve)
|
|
|
|
/**
|
|
* Lazy use-power-oneoff style thing
|
|
*
|
|
* @return null, or joules supplied
|
|
*/
|
|
/datum/item_mount/proc/lazy_energy_checked_use(obj/item/item, key, joules, minimum_reserve)
|
|
return lazy_energy_check(joules + minimum_reserve) && lazy_energy_use(joules, minimum_reserve)
|
|
|
|
//* Reagents - Direct *//
|
|
|
|
// TODO: notice how 'erase' and 'spawn' exists, but not 'push', and 'pull'?
|
|
// this is because reagents have data; they are not just described by the ID alone.
|
|
// thus an optimized uniform API for push/pull doesn't actually necessarily make sense,
|
|
// and as such implementation of such is left for when we need it (ergo mechs / rigsuits reagent routing).
|
|
|
|
/**
|
|
* Gets if an item mount has a reagent, and if it does, its amount.
|
|
* * Semantically, null means 'we can't store this'.
|
|
*
|
|
* @return null, or amount the item mount has
|
|
*/
|
|
/datum/item_mount/proc/reagent_get_amount(obj/item/item, key, datum/reagent/reagent)
|
|
return relay_to_other?.reagent_get_amount(item, key, reagent)
|
|
|
|
/**
|
|
* Checks if the item mount has a given amount of a reagent
|
|
* @return null, or TRUE / FALSE
|
|
*/
|
|
/datum/item_mount/proc/reagent_has_amount(obj/item/item, key, datum/reagent/reagent, amount)
|
|
. = reagent_get_amount(reagent)
|
|
if(.)
|
|
return . >= amount
|
|
|
|
/**
|
|
* @return null, or amount the item mount could to erase
|
|
*/
|
|
/datum/item_mount/proc/reagent_erase_amount(obj/item/item, key, datum/reagent/reagent, amount)
|
|
return relay_to_other?.reagent_erase_amount(item, key, reagent, amount)
|
|
|
|
/**
|
|
* @return null, or amount the item mount could give to erase
|
|
*/
|
|
/datum/item_mount/proc/reagent_erase_checked_amount(obj/item/item, key, datum/reagent/reagent, amount)
|
|
return reagent_has_amount(item, key, reagent, amount) && reagent_erase_amount(item, key, reagent, amount)
|
|
|
|
/**
|
|
* @return null, or amount the item mount could accept
|
|
*/
|
|
/datum/item_mount/proc/reagent_spawn_amount(obj/item/item, key, datum/reagent/reagent, amount, force)
|
|
return relay_to_other?.reagent_spawn_amount(item, key, reagent, amount, force)
|
|
|
|
//* Stacks *//
|
|
|
|
/**
|
|
* Get the name of the provider.
|
|
*
|
|
* @return null, or name
|
|
*/
|
|
/datum/item_mount/proc/stack_get_provider_name(obj/item/item, key, path)
|
|
return relay_to_other?.stack_get_provider_name(item, key, path)
|
|
|
|
/**
|
|
* Material stacks are invalid here.
|
|
*
|
|
* * Amount is in stack amount.
|
|
*
|
|
* @return null, or amount used.
|
|
*/
|
|
/datum/item_mount/proc/stack_use_checked_amount(obj/item/item, key, path, amount)
|
|
return stack_has_amount(item, key, path, amount) && stack_use_amount(item, key, path, amount)
|
|
|
|
/**
|
|
* Material stacks are invalid here.
|
|
*
|
|
* * Amount is in stack amount.
|
|
*
|
|
* @return null, or amount given.
|
|
*/
|
|
/datum/item_mount/proc/stack_give_amount(obj/item/item, key, path, amount, force)
|
|
return relay_to_other?.stack_give_amount(item, key, path, amount, force)
|
|
|
|
/**
|
|
* Material stacks are invalid here.
|
|
*
|
|
* @return null, or max amount.
|
|
*/
|
|
/datum/item_mount/proc/stack_get_capacity(obj/item/item, key, path)
|
|
return relay_to_other?.stack_get_capacity(item, key, path)
|
|
|
|
/**
|
|
* Material stacks are invalid here.
|
|
*
|
|
* * Amount is in stack amount.
|
|
*
|
|
* @return null, or amount remaining.
|
|
*/
|
|
/datum/item_mount/proc/stack_get_amount(obj/item/item, key, path)
|
|
return relay_to_other?.stack_get_amount(item, key, path)
|
|
|
|
/**
|
|
* Material stacks are invalid here.
|
|
*
|
|
* * Amount is in stack amount.
|
|
*
|
|
* @return null, or TRUE / FALSE.
|
|
*/
|
|
/datum/item_mount/proc/stack_has_amount(obj/item/item, key, path, amount)
|
|
. = stack_get_amount(item, key, path)
|
|
if(.)
|
|
return . >= amount
|
|
|
|
/**
|
|
* Material stacks are invalid here.
|
|
*
|
|
* * Amount is in stack amount.
|
|
*
|
|
* @return null, or amount used.
|
|
*/
|
|
/datum/item_mount/proc/stack_use_amount(obj/item/item, key, path, amount)
|
|
return relay_to_other?.stack_use_amount(item, key, path, amount)
|
|
|
|
//* ------ MISC BELOW HERE ------ *//
|
|
|
|
//* Misc - Extinguisher *//
|
|
|
|
/**
|
|
* @return null, or volume remaining
|
|
*/
|
|
/datum/item_mount/proc/extinguisher_get_volume(obj/item/extinguisher/extinguisher, key)
|
|
return relay_to_other?.extinguisher_get_volume(extinguisher, key)
|
|
|
|
/**
|
|
* @return null ,or TRUE / FALSE on if there's that much left
|
|
*/
|
|
/datum/item_mount/proc/extinguisher_has_volume(obj/item/extinguisher/extinguisher, key, requested)
|
|
. = extinguisher_get_volume(extinguisher)
|
|
if(.)
|
|
return . >= requested
|
|
|
|
/**
|
|
* @return null, or volume pulled
|
|
*/
|
|
/datum/item_mount/proc/extinguisher_transfer_volume(obj/item/extinguisher/extinguisher, key, requested, datum/reagent_holder/into_holder)
|
|
return relay_to_other?.extinguisher_transfer_volume(extinguisher, key, requested, into_holder)
|