[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>
This commit is contained in:
SkyratBot
2021-03-18 23:48:36 +01:00
committed by GitHub
parent 433243faa9
commit 4a63e18d62
8 changed files with 50 additions and 41 deletions
+2
View File
@@ -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)
+1 -1
View File
@@ -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
@@ -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)
. = ..()
+39 -35
View File
@@ -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)
@@ -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
+1 -1
View File
@@ -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)
@@ -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
+3 -1
View File
@@ -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)
. = ..()