From 4a63e18d62aa848e15f3d9a8f736af3dcb2aa20c Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Thu, 18 Mar 2021 23:48:36 +0100 Subject: [PATCH] [MIRROR] Fixes impurities on foam, smoke and cigs. Improves how impurities are handled. (#4234) * Fixes impurities on foam, smoke and cigs. Improves how impurities are handled. (#57435) Reworks the main handlier for impurities and adds it to the add_reagent proc instead. Adds an option to bypass the purity splitting too. This reduces the amount of add_reagent calls and will prevent any unintended on_mob_add() and delete calls for reagents that are removed from splitting. Fixes smoke, foam and cigarette issues too - since they used copy_to isntead of trans_to. * Fixes impurities on foam, smoke and cigs. Improves how impurities are handled. Co-authored-by: Thalpy <33956696+Thalpy@users.noreply.github.com> --- code/__DEFINES/reagents.dm | 2 + code/modules/mob/living/carbon/carbon.dm | 2 +- .../simple_animal/friendly/farm_animals.dm | 2 +- code/modules/reagents/chemistry/holder.dm | 74 ++++++++++--------- .../chemistry/machinery/chem_recipe_debug.dm | 2 +- code/modules/reagents/chemistry/reagents.dm | 2 +- .../chemistry/reagents/impure_reagents.dm | 3 +- code/modules/surgery/organs/stomach.dm | 4 +- 8 files changed, 50 insertions(+), 41 deletions(-) diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index eddf2e088e1..985986e575d 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -13,6 +13,8 @@ #define AMOUNT_VISIBLE (1<<6) // For non-transparent containers that still have the general amount of reagents in them visible. #define NO_REACT (1<<7) // Applied to a reagent holder, the contents will not react with each other. #define REAGENT_HOLDER_INSTANT_REACT (1<<8) // Applied to a reagent holder, all of the reactions in the reagents datum will be instant. Meant to be used for things like smoke effects where reactions aren't meant to occur +///If the holder is "alive" (i.e. mobs and organs) - If this flag is applied to a holder it will cause reagents to split upon addition to the object +#define REAGENT_HOLDER_ALIVE (1<<9) // Is an open container for all intents and purposes. #define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index f5dc4e30c91..0fe2fab358a 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1,6 +1,6 @@ /mob/living/carbon/Initialize(mapload) . = ..() - create_reagents(1000) + create_reagents(1000, REAGENT_HOLDER_ALIVE) assign_bodypart_ownership() update_body_parts() //to update the carbon's new bodyparts appearance diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 5621b103517..39745f6190d 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -402,7 +402,7 @@ name = "udder" /obj/item/udder/Initialize() - create_reagents(50) + create_reagents(50, REAGENT_HOLDER_ALIVE) reagents.add_reagent(/datum/reagent/consumable/milk, 20) . = ..() diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 0b2e2af5e45..f89fba3a5bb 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -155,8 +155,9 @@ * * added_purity - override to force a purity when added * * added_ph - override to force a pH when added * * override_base_ph - ingore the present pH of the reagent, and instead use the default (i.e. if buffers/reactions alter it) + * * ignore splitting - Don't call the process that handles reagent spliting in a mob (impure/inverse) - generally leave this false unless you care about REAGENTS_DONOTSPLIT flags (see reagent defines) */ -/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = DEFAULT_REAGENT_TEMPERATURE, added_purity = null, added_ph, no_react = 0, override_base_ph = FALSE) +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = DEFAULT_REAGENT_TEMPERATURE, added_purity = null, added_ph, no_react = FALSE, override_base_ph = FALSE, ignore_splitting = FALSE) if(!isnum(amount) || !amount) return FALSE @@ -167,13 +168,19 @@ if(!glob_reagent) stack_trace("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") return FALSE - - var/datum/reagent/D = GLOB.chemical_reagents_list[reagent] if(isnull(added_purity)) //Because purity additions can be 0 - added_purity = D.creation_purity //Usually 1 - + added_purity = glob_reagent.creation_purity //Usually 1 if(!added_ph) - added_ph = D.ph + added_ph = glob_reagent.ph + + //Split up the reagent if it's in a mob + var/has_split = FALSE + if(!ignore_splitting && (flags & REAGENT_HOLDER_ALIVE)) //Stomachs are a pain - they will constantly call on_mob_add unless we split on addition to stomachs, but we also want to make sure we don't double split + var/adjusted_vol = process_mob_reagent_purity(glob_reagent, amount, added_purity) + if(!adjusted_vol) //If we're inverse or FALSE cancel addition + return FALSE + amount = adjusted_vol + has_split = TRUE update_total() var/cached_total = total_volume @@ -230,6 +237,9 @@ if(isliving(my_atom)) new_reagent.on_mob_add(my_atom, amount) //Must occur before it could posibly run on_mob_delete + if(has_split) //prevent it from splitting again + new_reagent.chemical_flags |= REAGENT_DONOTSPLIT + update_total() if(reagtemp != cached_temp) var/new_heat_capacity = heat_capacity() @@ -466,7 +476,7 @@ trans_data = copy_data(reagent) if(reagent.intercept_reagents_transfer(R, cached_amount))//Use input amount instead. continue - R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //we only handle reaction after every reagent has been transfered. if(methods) if(istype(target_atom, /obj/item/organ)) R.expose_single(reagent, target, methods, part, show_message) @@ -475,8 +485,7 @@ reagent.on_transfer(target_atom, methods, transfer_amount * multiplier) remove_reagent(reagent.type, transfer_amount) transfer_log[reagent.type] = transfer_amount - if(is_type_in_list(target_atom, list(/mob/living/carbon, /obj/item/organ/stomach))) - R.process_mob_reagent_purity(reagent.type, transfer_amount * multiplier, reagent.purity) + else var/to_transfer = amount for(var/datum/reagent/reagent as anything in cached_reagents) @@ -491,7 +500,7 @@ transfer_amount = reagent.volume if(reagent.intercept_reagents_transfer(R, cached_amount))//Use input amount instead. continue - R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + R.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //we only handle reaction after every reagent has been transfered. to_transfer = max(to_transfer - transfer_amount , 0) if(methods) if(istype(target_atom, /obj/item/organ)) @@ -501,14 +510,11 @@ reagent.on_transfer(target_atom, methods, transfer_amount * multiplier) remove_reagent(reagent.type, transfer_amount) transfer_log[reagent.type] = transfer_amount - if(is_type_in_list(target_atom, list(/mob/living/carbon, /obj/item/organ/stomach))) - R.process_mob_reagent_purity(reagent.type, transfer_amount * multiplier, reagent.purity) if(transfered_by && target_atom) target_atom.add_hiddenprint(transfered_by) //log prints so admins can figure out who touched it last. log_combat(transfered_by, target_atom, "transferred reagents ([log_list(transfer_log)]) from [my_atom] to") - update_total() R.update_total() if(!no_react) @@ -545,7 +551,7 @@ if(current_reagent.intercept_reagents_transfer(holder, cached_amount))//Use input amount instead. break force_stop_reagent_reacting(current_reagent) - holder.add_reagent(current_reagent.type, amount, trans_data, chem_temp, current_reagent.purity, current_reagent.ph, no_react = TRUE) + holder.add_reagent(current_reagent.type, amount, trans_data, chem_temp, current_reagent.purity, current_reagent.ph, no_react = TRUE, ignore_splitting = current_reagent.chemical_flags & REAGENT_DONOTSPLIT) remove_reagent(current_reagent.type, amount, 1) break @@ -578,7 +584,7 @@ var/copy_amount = reagent.volume * part if(preserve_data) trans_data = reagent.data - R.add_reagent(reagent.type, copy_amount * multiplier, trans_data, added_purity = reagent.purity, added_ph = reagent.ph, no_react = TRUE) + R.add_reagent(reagent.type, copy_amount * multiplier, trans_data, added_purity = reagent.purity, added_ph = reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) //pass over previous ongoing reactions before handle_reactions is called transfer_reactions(R) @@ -597,7 +603,7 @@ var/change = (multiplier - 1) //Get the % change for(var/datum/reagent/reagent as anything in cached_reagents) if(change > 0) - add_reagent(reagent.type, reagent.volume * change, added_purity = reagent.purity) + add_reagent(reagent.type, reagent.volume * change, added_purity = reagent.purity, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) else remove_reagent(reagent.type, abs(reagent.volume * change)) //absolute value to prevent a double negative situation (removing -50% would be adding 50%) @@ -749,34 +755,32 @@ * * reagent - the added reagent datum/object * * added_volume - the volume of the reagent that was added (since it can already exist in a mob) * * added_purity - the purity of the added volume +* returns the volume of the current reagent to keep */ -/datum/reagents/proc/process_mob_reagent_purity(_reagent, added_volume, added_purity) - var/datum/reagent/reagent = has_reagent(_reagent) +/datum/reagents/proc/process_mob_reagent_purity(datum/reagent/reagent, added_volume, added_purity) if(!reagent) - stack_trace("Tried to process reagent purity for [_reagent], but 0 volume was found right after it was added!") //This can happen from smoking, where the volume is 0 after adding? - return - if (reagent.purity == 1) - return + stack_trace("Attempted to process a mob's reagent purity for a null reagent!") + return FALSE + if(added_purity == 1) + return added_volume if(reagent.chemical_flags & REAGENT_DONOTSPLIT) - return - if(reagent.purity < 0) - stack_trace("Purity below 0 for chem: [type]!") - reagent.purity = 0 + return added_volume + if(added_purity < 0) + stack_trace("Purity below 0 for chem on mob splitting: [reagent.type]!") + added_purity = 0 - if ((reagent.inverse_chem_val > reagent.purity) && (reagent.inverse_chem))//Turns all of a added reagent into the inverse chem - remove_reagent(reagent.type, added_volume, FALSE) + if((reagent.inverse_chem_val > added_purity) && (reagent.inverse_chem))//Turns all of a added reagent into the inverse chem add_reagent(reagent.inverse_chem, added_volume, FALSE, added_purity = 1-reagent.creation_purity) var/datum/reagent/inverse_reagent = has_reagent(reagent.inverse_chem) if(inverse_reagent.chemical_flags & REAGENT_SNEAKYNAME) inverse_reagent.name = reagent.name//Negative effects are hidden - if(inverse_reagent.chemical_flags & REAGENT_INVISIBLE) - inverse_reagent.chemical_flags |= (REAGENT_INVISIBLE) - else if (reagent.impure_chem) - var/impureVol = added_volume * (1 - reagent.purity) //turns impure ratio into impure chem + return FALSE //prevent addition + else if(reagent.impure_chem) + var/impure_vol = added_volume * (1 - added_purity) //turns impure ratio into impure chem + add_reagent(reagent.impure_chem, impure_vol, FALSE, added_purity = 1-reagent.creation_purity) if(!(reagent.chemical_flags & REAGENT_SPLITRETAINVOL)) - remove_reagent(reagent.type, impureVol, FALSE) - add_reagent(reagent.impure_chem, impureVol, FALSE, added_purity = 1-reagent.creation_purity) - reagent.chemical_flags |= REAGENT_DONOTSPLIT + return added_volume - impure_vol + return added_volume ///Processes any chems that have the REAGENT_IGNORE_STASIS bitflag ONLY /datum/reagents/proc/handle_stasis_chems(mob/living/carbon/owner, delta_time, times_fired) diff --git a/code/modules/reagents/chemistry/machinery/chem_recipe_debug.dm b/code/modules/reagents/chemistry/machinery/chem_recipe_debug.dm index d8ca6c4b6e5..6ea9292457f 100644 --- a/code/modules/reagents/chemistry/machinery/chem_recipe_debug.dm +++ b/code/modules/reagents/chemistry/machinery/chem_recipe_debug.dm @@ -57,7 +57,7 @@ ///Enable the machine /obj/machinery/chem_recipe_debug/attackby(obj/item/I, mob/user, params) - . = .() + . = ..() ui_interact(usr) ///Enable the machine diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 49a3d2fb461..bc17d24d72e 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -126,7 +126,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) if((methods & penetrates_skin) && exposed_mob.reagents) //smoke, foam, spray var/amount = round(reac_volume*clamp((1 - touch_protection), 0, 1), 0.1) if(amount >= 0.5) - exposed_mob.reagents.add_reagent(type, amount) + exposed_mob.reagents.add_reagent(type, amount, added_purity = purity) /// Applies this reagent to an [/obj] /datum/reagent/proc/expose_obj(obj/exposed_obj, reac_volume) diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents.dm index fcb44fbdb5b..f9e7c5f5e70 100644 --- a/code/modules/reagents/chemistry/reagents/impure_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/impure_reagents.dm @@ -11,6 +11,7 @@ ph = 3 impure_chem = null inverse_chem = null + inverse_chem_val = 0 failed_chem = null metabolization_rate = 0.1 * REM //default impurity is 0.75, so we get 25% converted. Default metabolisation rate is 0.4, so we're 4 times slower. var/liver_damage = 0.5 @@ -68,7 +69,7 @@ color = "#03dbfc" taste_description = "your tongue freezing, shortly followed by your thoughts. Brr!" ph = 14 - chemical_flags = REAGENT_DEAD_PROCESS | REAGENT_IGNORE_STASIS + chemical_flags = REAGENT_DEAD_PROCESS | REAGENT_IGNORE_STASIS | REAGENT_DONOTSPLIT metabolization_rate = 1 * REM ///The cube we're stasis'd in var/obj/structure/ice_stasis/cube diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm index 44e42cc2646..c5de95320c7 100755 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -34,7 +34,9 @@ . = ..() //None edible organs do not get a reagent holder by default if(!reagents) - create_reagents(reagent_vol) + create_reagents(reagent_vol, REAGENT_HOLDER_ALIVE) + else + reagents.flags |= REAGENT_HOLDER_ALIVE /obj/item/organ/stomach/on_life(delta_time, times_fired) . = ..()