Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reagent filter backend #6866

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions code/__DEFINES/reagents/reagent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
34 changes: 24 additions & 10 deletions code/game/machinery/Sleeper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -178,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)
Expand Down Expand Up @@ -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.reagents?.filter_to_holder(
beaker.reagents,
min(
remaining_beaker_volume_for_dialysis * (3 / 4),
length(occupant.reagents.reagent_list) * 3,
),
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) * 3,
),
dialysis_reagent_filter_flags,
)
else
toggle_pump()

Expand Down
8 changes: 8 additions & 0 deletions code/modules/reagents/chemistry/reagent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
47 changes: 45 additions & 2 deletions code/modules/reagents/chemistry/reagent_holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,49 @@
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
return transfer_to_holder(transfer_to, filtering_ids, amount)

/**
* 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 *//

/**
Expand Down Expand Up @@ -620,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)
Expand All @@ -646,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)
Expand Down
Loading