From 6011d11c6f857d7115184239151a7838f9891723 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 15 Nov 2024 23:33:48 -0500 Subject: [PATCH 1/4] filter backend --- code/__DEFINES/reagents/reagent.dm | 10 +++++ code/game/machinery/Sleeper.dm | 34 +++++++++----- code/modules/reagents/chemistry/reagent.dm | 8 ++++ .../reagents/chemistry/reagent_holder.dm | 44 +++++++++++++++++++ 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/code/__DEFINES/reagents/reagent.dm b/code/__DEFINES/reagents/reagent.dm index 834f06b97eeb..a4050c3d658c 100644 --- a/code/__DEFINES/reagents/reagent.dm +++ b/code/__DEFINES/reagents/reagent.dm @@ -18,3 +18,13 @@ DEFINE_SHARED_BITFIELD(reagent_guidebook_flags, list( BITFIELD(REAGENT_GUIDEBOOK_UNLISTED), BITFIELD(REAGENT_GUIDEBOOK_HIDDEN), )) + +//* flags for /datum/reagent/var/reagent_filter_flags *// + +/// the default flag that reagents have by default. +#define REAGENT_FILTER_GENERIC (1<<0) + +/// **disallow** from common medical machinery, like sleepers. +/// +/// * high-end reagents filtration / systems should be able to hit this +#define REAGENT_FILTER_NO_COMMON_BIOANALYSIS (1<<23) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 080b7d55293b..f5c819908f1a 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -11,6 +11,9 @@ interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_ALLOW_SILICON circuit = /obj/item/circuitboard/sleeper_console + /// filter flags we use for dialysis + var/dialysis_reagent_filter_flags = ~REAGENT_FILTER_NO_COMMON_BIOANALYSIS + /obj/machinery/sleep_console/Initialize(mapload, newdir) . = ..() return INITIALIZE_HINT_LATELOAD @@ -243,21 +246,32 @@ if(filtering > 0) if(beaker) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - var/pumped = 0 - for(var/datum/reagent/x in occupant.reagents.reagent_list) - occupant.reagents.trans_to_obj(beaker, 3) - pumped++ - if(ishuman(occupant)) - occupant.vessel.trans_to_obj(beaker, pumped + 1) + // filter 3 units per chem-type inside them, or remaining volume, whichever is lesser + // we will also pump out 1/3 of that volume as their blood. + var/remaining_beaker_volume_for_dialysis = beaker.reagents.maximum_volume - beaker.reagents.total_volume + var/filtered_volume = occupant.ingested?.filter_to_holder( + beaker.reagents, + min( + remaining_beaker_volume_for_dialysis * (3 / 4), + length(occupant.ingested.reagent_list) + ), + dialysis_reagent_filter_flags, + ) + occupant.vessel.trans_to_holder(beaker.reagents, filtered_volume * (1 / 3)) else toggle_filter() if(pumping > 0) if(beaker) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - for(var/datum/reagent/x in occupant.ingested.reagent_list) - occupant.ingested.trans_to_obj(beaker, 3) + // filter 3 units per chem-type inside them, or remaining volume, whichever is lesser + occupant.ingested?.filter_to_holder( + beaker.reagents, + min( + beaker.reagents.maximum_volume - beaker.reagents.total_volume, + length(occupant.ingested.reagent_list) + ), + dialysis_reagent_filter_flags, + ) else toggle_pump() diff --git a/code/modules/reagents/chemistry/reagent.dm b/code/modules/reagents/chemistry/reagent.dm index a84786770768..2b8dc3122323 100644 --- a/code/modules/reagents/chemistry/reagent.dm +++ b/code/modules/reagents/chemistry/reagent.dm @@ -17,6 +17,14 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) /// reagent flags - see [code/__DEFINES/reagents/flags.dm] var/reagent_flags = NONE + //* Filtering *// + /// reagent filter flags - dynamic flags used for simulations of filtration/identification/detection + /// + /// * used for a lot of things + /// * REAGENT_FILTER_GENERIC is a default because this allows us to have a single 'flags' on filter, + /// instead of a 'include flags' and 'exclude flags'. + var/reagent_filter_flags = REAGENT_FILTER_GENERIC + //* Identity /// our name - visible from guidebooks and to admins var/name = "Reagent" diff --git a/code/modules/reagents/chemistry/reagent_holder.dm b/code/modules/reagents/chemistry/reagent_holder.dm index f054e2c452e4..7d2bb37e9517 100644 --- a/code/modules/reagents/chemistry/reagent_holder.dm +++ b/code/modules/reagents/chemistry/reagent_holder.dm @@ -539,6 +539,50 @@ R.on_update (A) update_total() +//* Filtering *// + +/** + * Filters chemicals by `reagent_filter_flags` + * + * @params + * * transfer_to - where to transfer to + * * amount - volume limit + * * flags - only these flags are allowed + */ +/datum/reagent_holder/proc/filter_to_holder(datum/reagent_holder/transfer_to, amount = INFINITY, flags) + if(amount <= 0) + return + var/list/filtering_ids = list() + for(var/datum/reagent/reagent in reagent_list) + if(!(reagent.reagent_filter_flags & flags)) + continue + filtering_ids += reagent.id + transfer_to_holder(transfer_to, filtering_ids, amount) + return min(amount, total_filterable) + +/** + * Filters chemicals by `reagent_filter_flags` + * + * @params + * * amount - volume limit + * * flags - only these flags are allowed + */ +/datum/reagent_holder/proc/filter_to_void(amount = INFINITY, flags) + if(amount <= 0) + return + var/total_filterable = 0 + var/list/datum/reagent/filtering = list() + for(var/datum/reagent/reagent in reagent_list) + if(!(reagent.reagent_filter_flags & flags)) + continue + total_filterable += reagent.volume + filtering += reagent + var/ratio = amount / total_filterable + for(var/datum/reagent/to_filter in filtering) + remove_reagent(to_filter.id, to_filter.volume * ratio, TRUE) + reconsider_reactions() + return min(amount, total_filterable) + //* Queries *// /** From 3df6f308c4199d6fae6a7d1d2233b01f93504c7d Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 15 Nov 2024 23:35:40 -0500 Subject: [PATCH 2/4] that --- code/game/machinery/Sleeper.dm | 6 +++--- code/modules/reagents/chemistry/reagent_holder.dm | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index f5c819908f1a..f1bfb011c78d 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -11,9 +11,6 @@ interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_ALLOW_SILICON circuit = /obj/item/circuitboard/sleeper_console - /// filter flags we use for dialysis - var/dialysis_reagent_filter_flags = ~REAGENT_FILTER_NO_COMMON_BIOANALYSIS - /obj/machinery/sleep_console/Initialize(mapload, newdir) . = ..() return INITIALIZE_HINT_LATELOAD @@ -181,6 +178,9 @@ idle_power_usage = 15 active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors. + /// filter flags we use for dialysis + var/dialysis_reagent_filter_flags = ~REAGENT_FILTER_NO_COMMON_BIOANALYSIS + /obj/machinery/sleeper/Initialize(mapload) . = ..() beaker = new /obj/item/reagent_containers/glass/beaker/large(src) diff --git a/code/modules/reagents/chemistry/reagent_holder.dm b/code/modules/reagents/chemistry/reagent_holder.dm index 7d2bb37e9517..9f8e114a7c65 100644 --- a/code/modules/reagents/chemistry/reagent_holder.dm +++ b/code/modules/reagents/chemistry/reagent_holder.dm @@ -557,8 +557,7 @@ if(!(reagent.reagent_filter_flags & flags)) continue filtering_ids += reagent.id - transfer_to_holder(transfer_to, filtering_ids, amount) - return min(amount, total_filterable) + return transfer_to_holder(transfer_to, filtering_ids, amount) /** * Filters chemicals by `reagent_filter_flags` From aa68d6a7ecd41ff7482bce9aed7ff387126af6f1 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 15 Nov 2024 23:58:06 -0500 Subject: [PATCH 3/4] Fix --- code/game/machinery/Sleeper.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index f1bfb011c78d..a5ef1d2ae3b2 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -249,11 +249,11 @@ // filter 3 units per chem-type inside them, or remaining volume, whichever is lesser // we will also pump out 1/3 of that volume as their blood. var/remaining_beaker_volume_for_dialysis = beaker.reagents.maximum_volume - beaker.reagents.total_volume - var/filtered_volume = occupant.ingested?.filter_to_holder( + var/filtered_volume = occupant.reagents?.filter_to_holder( beaker.reagents, min( remaining_beaker_volume_for_dialysis * (3 / 4), - length(occupant.ingested.reagent_list) + length(occupant.reagents.reagent_list) ), dialysis_reagent_filter_flags, ) From 132e3dc7530670ebc83ee22dd9714b54a8c3a16f Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sat, 16 Nov 2024 08:24:25 -0500 Subject: [PATCH 4/4] Fix --- code/game/machinery/Sleeper.dm | 4 ++-- code/modules/reagents/chemistry/reagent_holder.dm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index a5ef1d2ae3b2..14d54e5a7a68 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -253,7 +253,7 @@ beaker.reagents, min( remaining_beaker_volume_for_dialysis * (3 / 4), - length(occupant.reagents.reagent_list) + length(occupant.reagents.reagent_list) * 3, ), dialysis_reagent_filter_flags, ) @@ -268,7 +268,7 @@ beaker.reagents, min( beaker.reagents.maximum_volume - beaker.reagents.total_volume, - length(occupant.ingested.reagent_list) + length(occupant.ingested.reagent_list) * 3, ), dialysis_reagent_filter_flags, ) diff --git a/code/modules/reagents/chemistry/reagent_holder.dm b/code/modules/reagents/chemistry/reagent_holder.dm index 9f8e114a7c65..7ee0d420823b 100644 --- a/code/modules/reagents/chemistry/reagent_holder.dm +++ b/code/modules/reagents/chemistry/reagent_holder.dm @@ -663,7 +663,7 @@ if(!total_volume) return if(!reagents) - var/ratio = min(1, (target.maximum_volume - target.total_volume) / total_volume) + var/ratio = min(1, min(amount, target.maximum_volume - target.total_volume) / total_volume) . = total_volume * ratio if(!copy) for(var/datum/reagent/R as anything in reagent_list) @@ -689,7 +689,7 @@ reagents_transferring += R if(!total_transferable) return 0 - var/ratio = min(1, (target.maximum_volume - target.total_volume) / total_transferable) + var/ratio = min(1, min(amount, target.maximum_volume - target.total_volume) / total_transferable) . = total_transferable * ratio if(!copy) for(var/datum/reagent/R as anything in reagents_transferring)