Makes reagent updates more event based, also makes plasma boil properly. (#54790)

Converts most on_reagent_change calls to signals.
Converts on_reagent_change to a signal handler.
Expands the reagent exposure signals
Add a setter proc and signal for reagent temperature
Fixes adjust_thermal_energy not sending a temperature change event
Makes min_temp and max_temp actually do something with adjust_thermal_energy
This commit is contained in:
TemporalOroboros
2020-12-22 14:20:00 -08:00
committed by GitHub
parent 6e8b04d3c1
commit 863977e5fa
32 changed files with 741 additions and 514 deletions
+329 -304
View File
@@ -90,38 +90,130 @@
my_atom.reagents = null
my_atom = null
/**
* Used in attack logs for reagents in pills and such
* Adds a reagent to this holder
*
* Arguments:
* * external_list - list of reagent types = amounts
* * reagent - The reagent id to add
* * amount - Amount to add
* * list/data - Any reagent data for this reagent, used for transferring data with reagents
* * reagtemp - Temperature of this reagent, will be equalized
* * no_react - prevents reactions being triggered by this addition
*/
/datum/reagents/proc/log_list(external_list)
if((external_list && !length(external_list)) || !length(reagent_list))
return "no reagents"
/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)
if(!isnum(amount) || !amount)
return FALSE
var/list/data = list()
if(external_list)
for(var/r in external_list)
data += "[r] ([round(external_list[r], 0.1)]u)"
else
for(var/r in reagent_list) //no reagents will be left behind
var/datum/reagent/R = r
data += "[R.type] ([round(R.volume, 0.1)]u)"
//Using types because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return english_list(data)
if(amount <= 0)
return FALSE
var/datum/reagent/glob_reagent = GLOB.chemical_reagents_list[reagent]
if(!glob_reagent)
WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
return FALSE
update_total()
var/cached_total = total_volume
if(cached_total + amount > maximum_volume)
amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. shouldn't happen. Will happen.
if(amount <= 0)
return FALSE
var/cached_temp = chem_temp
var/list/cached_reagents = reagent_list
//Equalize temperature - Not using specific_heat() because the new chemical isn't in yet.
var/old_heat_capacity = 0
if(reagtemp != cached_temp)
for(var/r in cached_reagents)
var/datum/reagent/iter_reagent = r
old_heat_capacity += iter_reagent.specific_heat * iter_reagent.volume
//add the reagent to the existing if it exists
for(var/r in cached_reagents)
var/datum/reagent/iter_reagent = r
if (iter_reagent.type == reagent)
iter_reagent.volume += amount
update_total()
iter_reagent.on_merge(data, amount)
if(reagtemp != cached_temp)
set_temperature(((old_heat_capacity * cached_temp) + (iter_reagent.specific_heat * amount * reagtemp)) / heat_capacity())
SEND_SIGNAL(src, COMSIG_REAGENTS_ADD_REAGENT, iter_reagent, amount, reagtemp, data, no_react)
if(!no_react)
handle_reactions()
return TRUE
//otherwise make a new one
var/datum/reagent/new_reagent = new reagent(data)
cached_reagents += new_reagent
new_reagent.holder = src
new_reagent.volume = amount
if(data)
new_reagent.data = data
new_reagent.on_new(data)
if(isliving(my_atom))
new_reagent.on_mob_add(my_atom) //Must occur before it could posibly run on_mob_delete
update_total()
if(reagtemp != cached_temp)
set_temperature(((old_heat_capacity * cached_temp) + (new_reagent.specific_heat * amount * reagtemp)) / heat_capacity())
SEND_SIGNAL(src, COMSIG_REAGENTS_NEW_REAGENT, new_reagent, amount, reagtemp, data, no_react)
if(!no_react)
handle_reactions()
return TRUE
/// Like add_reagent but you can enter a list. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15)
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null)
for(var/r_id in list_reagents)
var/amt = list_reagents[r_id]
add_reagent(r_id, amt, data)
/// Remove a specific reagent
/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to
if(isnull(amount))
amount = 0
CRASH("null amount passed to reagent code")
if(!isnum(amount))
return FALSE
if(amount < 0)
return FALSE
var/list/cached_reagents = reagent_list
for(var/A in cached_reagents)
var/datum/reagent/R = A
if (R.type == reagent)
//clamp the removal amount to be between current reagent amount
//and zero, to prevent removing more than the holder has stored
amount = clamp(amount, 0, R.volume)
R.volume -= amount
update_total()
SEND_SIGNAL(src, COMSIG_REAGENTS_REM_REAGENT, QDELING(R) ? reagent : R, amount)
if(!safety)//So it does not handle reactions when it need not to
handle_reactions()
return TRUE
return FALSE
/// Remove an amount of reagents without caring about what they are
/datum/reagents/proc/remove_any(amount = 1)
var/list/cached_reagents = reagent_list
var/total_transfered = 0
var/total_removed = 0
var/current_list_element = 1
var/initial_list_length = cached_reagents.len //stored here because removing can cause some reagents to be deleted, ergo length change.
current_list_element = rand(1, cached_reagents.len)
while(total_transfered != amount)
if(total_transfered >= amount)
while(total_removed != amount)
if(total_removed >= amount)
break
if(total_volume <= 0 || !cached_reagents.len)
break
@@ -130,16 +222,16 @@
current_list_element = 1
var/datum/reagent/R = cached_reagents[current_list_element]
var/remove_amt = min(amount-total_transfered,round(amount/rand(2,initial_list_length),round(amount/10,0.01))) //double round to keep it at a somewhat even spread relative to amount without getting funky numbers.
var/remove_amt = min(amount-total_removed,round(amount/rand(2,initial_list_length),round(amount/10,0.01))) //double round to keep it at a somewhat even spread relative to amount without getting funky numbers.
//min ensures we don't go over amount.
remove_reagent(R.type, remove_amt)
current_list_element++
total_transfered += remove_amt
total_removed += remove_amt
update_total()
handle_reactions()
return total_transfered //this should be amount unless the loop is prematurely broken, in which case it'll be lower. It shouldn't ever go OVER amount.
return total_removed //this should be amount unless the loop is prematurely broken, in which case it'll be lower. It shouldn't ever go OVER amount.
/// Removes all reagents from this holder
/datum/reagents/proc/remove_all(amount = 1)
@@ -154,44 +246,90 @@
handle_reactions()
return amount
/// Get the name of the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent_name()
/// Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included.
/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1)
if(!isnum(amount))
return 1
var/list/cached_reagents = reagent_list
var/name
var/max_volume = 0
var/has_removed_reagent = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
if(R.volume > max_volume)
max_volume = R.volume
name = R.name
var/matches = 0
// Switch between how we check the reagent type
if(strict)
if(R.type == reagent_type)
matches = 1
else
if(istype(R, reagent_type))
matches = 1
// We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type.
if(matches)
// Have our other proc handle removement
has_removed_reagent = remove_reagent(R.type, amount, safety)
return name
return has_removed_reagent
/// Get the id of the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent_id()
/// Fuck this one reagent
/datum/reagents/proc/del_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
var/datum/reagent/R = _reagent
if(R.type == reagent)
if(isliving(my_atom))
if(R.metabolizing)
R.metabolizing = FALSE
R.on_mob_end_metabolize(my_atom)
R.on_mob_delete(my_atom)
//Clear from relevant lists
LAZYREMOVE(addiction_list, R)
reagent_list -= R
qdel(R)
update_total()
SEND_SIGNAL(src, COMSIG_REAGENTS_DEL_REAGENT, reagent)
return TRUE
/// Remove every reagent except this one
/datum/reagents/proc/isolate_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
var/datum/reagent/R = _reagent
if(R.type != reagent)
del_reagent(R.type)
update_total()
/// Removes all reagents
/datum/reagents/proc/clear_reagents()
var/list/cached_reagents = reagent_list
var/max_type
var/max_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
if(R.volume > max_volume)
max_volume = R.volume
max_type = R.type
del_reagent(R.type)
SEND_SIGNAL(src, COMSIG_REAGENTS_CLEAR_REAGENTS)
return max_type
/// Get a reference to the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent()
/**
* Check if this holder contains this reagent.
* Reagent takes a PATH to a reagent.
* Amount checks for having a specific amount of that chemical.
* Needs matabolizing takes into consideration if the chemical is matabolizing when it's checked.
*/
/datum/reagents/proc/has_reagent(reagent, amount = -1, needs_metabolizing = FALSE)
var/list/cached_reagents = reagent_list
var/datum/reagent/master
var/max_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
if(R.volume > max_volume)
max_volume = R.volume
master = R
for(var/_reagent in cached_reagents)
var/datum/reagent/R = _reagent
if (R.type == reagent)
if(!amount)
if(needs_metabolizing && !R.metabolizing)
return FALSE
return R
else
if(round(R.volume, CHEMICAL_QUANTISATION_LEVEL) >= amount)
if(needs_metabolizing && !R.metabolizing)
return FALSE
return R
return FALSE
return master
/**
* Transfer some stuff from this holder to a target object
@@ -292,6 +430,35 @@
src.handle_reactions()
return amount
/// Transfer a specific reagent id to the target object
/datum/reagents/proc/trans_id_to(obj/target, reagent, amount=1, preserve_data=1)//Not sure why this proc didn't exist before. It does now! /N
var/list/cached_reagents = reagent_list
if (!target)
return
if (!target.reagents || src.total_volume<=0 || !src.get_reagent_amount(reagent))
return
if(amount < 0)
return
var/datum/reagents/R = target.reagents
if(src.get_reagent_amount(reagent)<amount)
amount = src.get_reagent_amount(reagent)
amount = min(amount, R.maximum_volume-R.total_volume)
var/trans_data = null
for (var/CR in cached_reagents)
var/datum/reagent/current_reagent = CR
if(current_reagent.type == reagent)
if(preserve_data)
trans_data = current_reagent.data
R.add_reagent(current_reagent.type, amount, trans_data, src.chem_temp)
remove_reagent(current_reagent.type, amount, 1)
break
src.update_total()
R.update_total()
R.handle_reactions()
return amount
/// Copies the reagents to the target object
/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1)
var/list/cached_reagents = reagent_list
@@ -340,34 +507,45 @@
update_total()
handle_reactions()
/// Transfer a specific reagent id to the target object
/datum/reagents/proc/trans_id_to(obj/target, reagent, amount=1, preserve_data=1)//Not sure why this proc didn't exist before. It does now! /N
/// Get the name of the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent_name()
var/list/cached_reagents = reagent_list
if (!target)
return
if (!target.reagents || src.total_volume<=0 || !src.get_reagent_amount(reagent))
return
if(amount < 0)
return
var/name
var/max_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
if(R.volume > max_volume)
max_volume = R.volume
name = R.name
var/datum/reagents/R = target.reagents
if(src.get_reagent_amount(reagent)<amount)
amount = src.get_reagent_amount(reagent)
amount = min(amount, R.maximum_volume-R.total_volume)
var/trans_data = null
for (var/CR in cached_reagents)
var/datum/reagent/current_reagent = CR
if(current_reagent.type == reagent)
if(preserve_data)
trans_data = current_reagent.data
R.add_reagent(current_reagent.type, amount, trans_data, src.chem_temp)
remove_reagent(current_reagent.type, amount, 1)
break
return name
src.update_total()
R.update_total()
R.handle_reactions()
return amount
/// Get the id of the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent_id()
var/list/cached_reagents = reagent_list
var/max_type
var/max_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
if(R.volume > max_volume)
max_volume = R.volume
max_type = R.type
return max_type
/// Get a reference to the reagent there is the most of in this holder
/datum/reagents/proc/get_master_reagent()
var/list/cached_reagents = reagent_list
var/datum/reagent/master
var/max_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
if(R.volume > max_volume)
max_volume = R.volume
master = R
return master
/**
* Triggers metabolizing the reagents in this holder
@@ -448,13 +626,6 @@
C.update_stamina()
update_total()
/// Removes addiction to a specific reagent on [/datum/reagents/var/my_atom]
/datum/reagents/proc/remove_addiction(datum/reagent/R)
to_chat(my_atom, "<span class='notice'>You feel like you've gotten over your need for [R.name].</span>")
SEND_SIGNAL(my_atom, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
LAZYREMOVE(addiction_list, R)
qdel(R)
/// Signals that metabolization has stopped, triggering the end of trait-based effects
/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
var/list/cached_reagents = reagent_list
@@ -470,6 +641,14 @@
R.metabolizing = FALSE
R.on_mob_end_metabolize(C)
/// Removes addiction to a specific reagent on [/datum/reagents/var/my_atom]
/datum/reagents/proc/remove_addiction(datum/reagent/R)
to_chat(my_atom, "<span class='notice'>You feel like you've gotten over your need for [R.name].</span>")
SEND_SIGNAL(my_atom, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
LAZYREMOVE(addiction_list, R)
qdel(R)
/**
* Calls [/datum/reagent/proc/on_move] on every reagent in this holder
*
@@ -481,7 +660,7 @@
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
R.on_move (A, Running)
R.on_move(A, Running)
update_total()
/**
@@ -494,22 +673,23 @@
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
R.on_update (A)
R.on_update(A)
update_total()
/// Handle any reactions possible in this holder
/datum/reagents/proc/handle_reactions()
if(flags & NO_REACT)
return //Yup, no reactions here. No siree.
return 0 //Yup, no reactions here. No siree.
var/list/cached_reagents = reagent_list
var/list/cached_reactions = GLOB.chemical_reactions_list
var/datum/cached_my_atom = my_atom
var/reaction_occurred = 0
. = 0
var/reaction_occurred
do
var/list/possible_reactions = list()
reaction_occurred = 0
reaction_occurred = FALSE
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
for(var/reaction in cached_reactions[R.type]) // Was a big list but now it should be smaller since we filtered it with our reagent id
@@ -610,40 +790,14 @@
ME2.desc = "This extract has been used up."
selected_reaction.on_reaction(src, multiplier)
reaction_occurred = 1
reaction_occurred = TRUE
.++
while(reaction_occurred)
update_total()
if(.)
SEND_SIGNAL(src, COMSIG_REAGENTS_REACTED, .)
/// Remove every reagent except this one
/datum/reagents/proc/isolate_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
var/datum/reagent/R = _reagent
if(R.type != reagent)
del_reagent(R.type)
update_total()
/// Fuck this one reagent
/datum/reagents/proc/del_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
var/datum/reagent/R = _reagent
if(R.type == reagent)
if(isliving(my_atom))
if(R.metabolizing)
R.metabolizing = FALSE
R.on_mob_end_metabolize(my_atom)
R.on_mob_delete(my_atom)
//Clear from relevant lists
LAZYREMOVE(addiction_list, R)
reagent_list -= R
qdel(R)
update_total()
if(my_atom)
my_atom.on_reagent_change(DEL_REAGENT)
return 1
/// Updates [/datum/reagents/var/total_volume]
/datum/reagents/proc/update_total()
@@ -656,16 +810,6 @@
else
total_volume += R.volume
/// Removes all reagents
/datum/reagents/proc/clear_reagents()
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
del_reagent(R.type)
if(my_atom)
my_atom.on_reagent_change(CLEAR_REAGENTS)
/**
* Applies the relevant expose_ proc for every reagent in this holder
* * [/datum/reagent/proc/expose_mob]
@@ -713,155 +857,6 @@
return TRUE
return FALSE
/// Returns the average specific heat for all reagents currently in this holder.
/datum/reagents/proc/specific_heat()
. = 0
var/cached_amount = total_volume //cache amount
var/list/cached_reagents = reagent_list //cache reagents
for(var/I in cached_reagents)
var/datum/reagent/R = I
. += R.specific_heat * (R.volume / cached_amount)
/datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000)
var/S = specific_heat()
chem_temp = clamp(chem_temp + (J / (S * total_volume)), 2.7, 1000)
/**
* Adds a reagent to this holder
*
* Arguments:
* * reagent - The reagent id to add
* * amount - Amount to add
* * list/data - Any reagent data for this reagent, used for transferring data with reagents
* * reagtemp - Temperature of this reagent, will be equalized
* * no_react - prevents reactions being triggered by this addition
*/
/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)
if(!isnum(amount) || !amount)
return FALSE
if(amount <= 0)
return FALSE
var/datum/reagent/D = GLOB.chemical_reagents_list[reagent]
if(!D)
WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
return FALSE
update_total()
var/cached_total = total_volume
if(cached_total + amount > maximum_volume)
amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. shouldn't happen. Will happen.
if(amount <= 0)
return FALSE
var/new_total = cached_total + amount
var/cached_temp = chem_temp
var/list/cached_reagents = reagent_list
//Equalize temperature - Not using specific_heat() because the new chemical isn't in yet.
var/specific_heat = 0
var/thermal_energy = 0
for(var/i in cached_reagents)
var/datum/reagent/R = i
specific_heat += R.specific_heat * (R.volume / new_total)
thermal_energy += R.specific_heat * R.volume * cached_temp
specific_heat += D.specific_heat * (amount / new_total)
thermal_energy += D.specific_heat * amount * reagtemp
chem_temp = thermal_energy / (specific_heat * new_total)
////
//add the reagent to the existing if it exists
for(var/A in cached_reagents)
var/datum/reagent/R = A
if (R.type == reagent)
R.volume += amount
update_total()
if(my_atom)
my_atom.on_reagent_change(ADD_REAGENT)
R.on_merge(data, amount)
if(!no_react)
handle_reactions()
return TRUE
//otherwise make a new one
var/datum/reagent/R = new D.type(data)
cached_reagents += R
R.holder = src
R.volume = amount
if(data)
R.data = data
R.on_new(data)
if(isliving(my_atom))
R.on_mob_add(my_atom) //Must occur before it could posibly run on_mob_delete
update_total()
if(my_atom)
my_atom.on_reagent_change(ADD_REAGENT)
if(!no_react)
handle_reactions()
return TRUE
/// Like add_reagent but you can enter a list. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15)
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null)
for(var/r_id in list_reagents)
var/amt = list_reagents[r_id]
add_reagent(r_id, amt, data)
/// Remove a specific reagent
/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to
if(isnull(amount))
amount = 0
CRASH("null amount passed to reagent code")
if(!isnum(amount))
return FALSE
if(amount < 0)
return FALSE
var/list/cached_reagents = reagent_list
for(var/A in cached_reagents)
var/datum/reagent/R = A
if (R.type == reagent)
//clamp the removal amount to be between current reagent amount
//and zero, to prevent removing more than the holder has stored
amount = clamp(amount, 0, R.volume)
R.volume -= amount
update_total()
if(!safety)//So it does not handle reactions when it need not to
handle_reactions()
if(my_atom)
my_atom.on_reagent_change(REM_REAGENT)
return TRUE
return FALSE
/*
Check if this holder contains this reagent.
Reagent takes a PATH to a reagent.
Amount checks for having a specific amount of that chemical.
Needs matabolizing takes into consideration if the chemical is matabolizing when it's checked.
*/
/datum/reagents/proc/has_reagent(reagent, amount = -1, needs_metabolizing = FALSE)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
var/datum/reagent/R = _reagent
if (R.type == reagent)
if(!amount)
if(needs_metabolizing && !R.metabolizing)
return FALSE
return R
else
if(round(R.volume, CHEMICAL_QUANTISATION_LEVEL) >= amount)
if(needs_metabolizing && !R.metabolizing)
return FALSE
return R
return FALSE
/// Get the amount of this reagent
/datum/reagents/proc/get_reagent_amount(reagent)
var/list/cached_reagents = reagent_list
@@ -871,8 +866,8 @@ Needs matabolizing takes into consideration if the chemical is matabolizing when
return round(R.volume, CHEMICAL_QUANTISATION_LEVEL)
return 0
/// Get a comma separated string of every reagent name in this holder
/datum/reagents/proc/get_reagents()
/// Get a comma separated string of every reagent name in this holder. UNUSED
/datum/reagents/proc/get_reagent_names()
var/list/names = list()
var/list/cached_reagents = reagent_list
for(var/reagent in cached_reagents)
@@ -881,30 +876,6 @@ Needs matabolizing takes into consideration if the chemical is matabolizing when
return jointext(names, ",")
/// Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included.
/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1)
if(!isnum(amount))
return 1
var/list/cached_reagents = reagent_list
var/has_removed_reagent = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
var/matches = 0
// Switch between how we check the reagent type
if(strict)
if(R.type == reagent_type)
matches = 1
else
if(istype(R, reagent_type))
matches = 1
// We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type.
if(matches)
// Have our other proc handle removement
has_removed_reagent = remove_reagent(R.type, amount, safety)
return has_removed_reagent
/// helper function to preserve data across reactions (needed for xenoarch)
/datum/reagents/proc/get_data(reagent_id)
var/list/cached_reagents = reagent_list
@@ -988,6 +959,26 @@ Needs matabolizing takes into consideration if the chemical is matabolizing when
return english_list(out, "something indescribable")
/// Returns the total heat capacity for all of the reagents currently in this holder.
/datum/reagents/proc/heat_capacity()
. = 0
var/list/cached_reagents = reagent_list //cache reagents
for(var/I in cached_reagents)
var/datum/reagent/R = I
. += R.specific_heat * R.volume
/** Adjusts the thermal energy of the reagents in this holder by an amount.
*
* Arguments:
* - delta_energy: The amount to change the thermal energy by.
* - min_temp: The minimum temperature that can be reached.
* - max_temp: The maximum temperature that can be reached.
*/
/datum/reagents/proc/adjust_thermal_energy(delta_energy, min_temp = 2.7, max_temp = 1000)
var/heat_capacity = heat_capacity()
set_temperature(clamp(chem_temp + (delta_energy / heat_capacity), min_temp, max_temp))
/// Applies heat to this holder
/datum/reagents/proc/expose_temperature(temperature, coeff=0.02)
if(istype(my_atom,/obj/item/reagent_containers))
@@ -999,12 +990,46 @@ Needs matabolizing takes into consideration if the chemical is matabolizing when
chem_temp = min(chem_temp + max(temp_delta, 1), temperature)
else
chem_temp = max(chem_temp + min(temp_delta, -1), temperature)
chem_temp = round(chem_temp)
for(var/i in reagent_list)
var/datum/reagent/R = i
R.on_temp_change()
set_temperature(round(chem_temp))
handle_reactions()
/** Sets the temperature of this reagent container to a new value.
*
* Handles setter signals.
*
* Arguments:
* - _temperature: The new temperature value.
*/
/datum/reagents/proc/set_temperature(_temperature)
if(_temperature == chem_temp)
return
. = chem_temp
chem_temp = _temperature
SEND_SIGNAL(src, COMSIG_REAGENTS_TEMP_CHANGE, _temperature, .)
/**
* Used in attack logs for reagents in pills and such
*
* Arguments:
* * external_list - list of reagent types = amounts
*/
/datum/reagents/proc/log_list(external_list)
if((external_list && !length(external_list)) || !length(reagent_list))
return "no reagents"
var/list/data = list()
if(external_list)
for(var/r in external_list)
data += "[r] ([round(external_list[r], 0.1)]u)"
else
for(var/r in reagent_list) //no reagents will be left behind
var/datum/reagent/R = r
data += "[R.type] ([round(R.volume, 0.1)]u)"
//Using types because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return english_list(data)
///////////////////////////////////////////////////////////////////////////////////
@@ -1024,7 +1049,7 @@ Needs matabolizing takes into consideration if the chemical is matabolizing when
/proc/get_random_reagent_id() // Returns a random reagent ID minus blacklisted reagents
var/static/list/random_reagents = list()
if(!random_reagents.len)
for(var/thing in subtypesof(/datum/reagent))
for(var/thing in subtypesof(/datum/reagent))
var/datum/reagent/R = thing
if(initial(R.can_synth))
random_reagents += R
@@ -14,9 +14,6 @@ Structure: /////////////////// //////////////////////////
reagents (datums) Reagents. I.e. Water , cryoxadone or mercury.
```
# Random important notes:
An objects on_reagent_change will be called every time the objects reagents change. Useful if you want to update the objects icon etc.
# About the Holder:
The holder (reagents datum) is the datum that holds a list of all reagents currently in the object.It also has all the procs needed to manipulate reagents
```
@@ -165,9 +165,6 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
/datum/reagent/proc/on_update(atom/A)
return
///called on expose_temperature
/datum/reagent/proc/on_temp_change()
return
/// Called when the reagent container is hit by an explosion
/datum/reagent/proc/on_ex_act(severity)
return
@@ -2028,8 +2028,6 @@ All effects don't start immediately, but rather get worse over time; the rate is
flavor += ", with a hint of "
flavor += english_list(secondary_tastes)
taste_description = flavor
if(holder.my_atom)
holder.my_atom.on_reagent_change()
/datum/reagent/consumable/ethanol/champagne //How the hell did we not have champagne already!?
@@ -73,19 +73,31 @@
material = /datum/material/plasma
penetrates_skin = NONE
/datum/reagent/toxin/plasma/on_new(data)
. = ..()
RegisterSignal(holder, COMSIG_REAGENTS_TEMP_CHANGE, .proc/on_temp_change)
/datum/reagent/toxin/plasma/Destroy()
UnregisterSignal(holder, COMSIG_REAGENTS_TEMP_CHANGE)
return ..()
/datum/reagent/toxin/plasma/on_mob_life(mob/living/carbon/C)
if(holder.has_reagent(/datum/reagent/medicine/epinephrine))
holder.remove_reagent(/datum/reagent/medicine/epinephrine, 2*REM)
C.adjustPlasma(20)
return ..()
/datum/reagent/toxin/plasma/on_temp_change()
/// Handles plasma boiling.
/datum/reagent/toxin/plasma/proc/on_temp_change(datum/reagents/_holder, old_temp)
SIGNAL_HANDLER
if(holder.chem_temp < LIQUID_PLASMA_BP)
return
if(holder.my_atom)
var/atom/A = holder.my_atom
A.atmos_spawn_air("plasma=[volume];TEMP=[holder.chem_temp]")
holder.del_reagent(type)
if(!holder.my_atom)
return
var/atom/A = holder.my_atom
A.atmos_spawn_air("plasma=[volume];TEMP=[holder.chem_temp]")
holder.del_reagent(type)
/datum/reagent/toxin/plasma/expose_turf(turf/open/exposed_turf, reac_volume)
if(!istype(exposed_turf))
+17 -1
View File
@@ -27,6 +27,19 @@
add_initial_reagents()
/obj/item/reagent_containers/create_reagents(max_vol, flags)
. = ..()
RegisterSignal(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT), .proc/on_reagent_change)
RegisterSignal(reagents, COMSIG_PARENT_QDELETING, .proc/on_reagents_del)
/obj/item/reagent_containers/Destroy()
return ..()
/obj/item/reagent_containers/proc/on_reagents_del(datum/reagents/reagents)
SIGNAL_HANDLER
UnregisterSignal(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT, COMSIG_PARENT_QDELETING))
return NONE
/obj/item/reagent_containers/proc/add_initial_reagents()
if(list_reagents)
reagents.add_reagent_list(list_reagents)
@@ -135,8 +148,11 @@
/obj/item/reagent_containers/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
reagents.expose_temperature(exposed_temperature)
/obj/item/reagent_containers/on_reagent_change(changetype)
/// Updates the icon of the container when the reagents change. Eats signal args
/obj/item/reagent_containers/proc/on_reagent_change(datum/reagents/holder, ...)
SIGNAL_HANDLER
update_icon()
return NONE
/obj/item/reagent_containers/update_overlays()
. = ..()
@@ -15,22 +15,21 @@
reagents.add_reagent(unique_blood ? unique_blood : /datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
update_icon()
/obj/item/reagent_containers/blood/on_reagent_change(changetype)
if(reagents)
var/datum/reagent/blood/B = reagents.has_reagent(/datum/reagent/blood)
if(B && B.data && B.data["blood_type"])
blood_type = B.data["blood_type"]
else
blood_type = null
/// Handles updating the container when the reagents change.
/obj/item/reagent_containers/blood/on_reagent_change(datum/reagents/holder, ...)
var/datum/reagent/blood/B = holder.has_reagent(/datum/reagent/blood)
if(B && B.data && B.data["blood_type"])
blood_type = B.data["blood_type"]
else
blood_type = null
update_pack_name()
update_icon()
return ..()
/obj/item/reagent_containers/blood/proc/update_pack_name()
if(!labelled)
if(blood_type)
name = "blood pack - [blood_type]"
else
name = "blood pack"
if(labelled)
return
name = "blood_pack[blood_type ? " - [blood_type]" : ""]"
/obj/item/reagent_containers/blood/random
icon_state = "random_bloodpack"
@@ -54,7 +54,6 @@ Borg Hypospray
regenerate_reagents()
charge_timer = 0
//update_icon()
return 1
// Use this to add more chemicals for the borghypo to produce.
@@ -144,18 +144,23 @@
reagents.expose(usr.loc)
src.reagents.clear_reagents()
/obj/item/reagent_containers/spray/on_reagent_change(changetype)
var/total_reagent_weight
var/amount_of_reagents
for (var/datum/reagent/R in reagents.reagent_list)
total_reagent_weight = total_reagent_weight + R.reagent_weight
amount_of_reagents++
/// Handles updating the spreay distance when the reagents change.
/obj/item/reagent_containers/spray/on_reagent_change(datum/reagents/holder, ...)
. = ..()
var/total_reagent_weight = 0
var/number_of_reagents = 0
var/amount_of_reagents = holder.total_volume
var/list/cached_reagents = holder.reagent_list
for(var/datum/reagent/reagent in cached_reagents)
total_reagent_weight += reagent.reagent_weight * reagent.volume
number_of_reagents++
if(total_reagent_weight && amount_of_reagents) //don't bother if the container is empty - DIV/0
if(total_reagent_weight && number_of_reagents && amount_of_reagents) //don't bother if the container is empty - DIV/0
var/average_reagent_weight = total_reagent_weight / amount_of_reagents
spray_range = clamp(round((initial(spray_range) / average_reagent_weight) - ((amount_of_reagents - 1) * 1)), 3, 5) //spray distance between 3 and 5 tiles rounded down; extra reagents lose a tile
spray_range = clamp(round((initial(spray_range) / average_reagent_weight) - ((number_of_reagents - 1) * 1)), 3, 5) //spray distance between 3 and 5 tiles rounded down; extra reagents lose a tile
else
spray_range = initial(spray_range)
if(stream_mode == 0)
current_range = spray_range
@@ -28,9 +28,6 @@
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
/obj/item/reagent_containers/syringe/on_reagent_change(changetype)
update_icon()
/obj/item/reagent_containers/syringe/pickup(mob/user)
..()
update_icon()