Temperature Reagent System (#5423)

Overview
This is the github WIP PR for the reagent system project. This is for other developers and users to track progress of the code if they're curious about it, as well as to show that it actually works.
This commit is contained in:
BurgerLUA
2018-11-03 15:17:40 -07:00
committed by Erki
parent 581f9c6153
commit 1b10bb1fe5
39 changed files with 1000 additions and 172 deletions

View File

@@ -39,13 +39,15 @@ proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var
for(var/mob/victim in victims)
admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message)
proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amount_transferred, violent=0)
proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, temperature, amount_transferred, violent=0)
if(violent)
violent = "violently "
else
violent = ""
var/temperature_text = "Temperature: ([temperature]K/[temperature]C)"
admin_attack_log(attacker,
victim,
"used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred",
"was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred",
"used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into")
"used \the [weapon] to [violent]inject - [reagents] [temperature_text] - [amount_transferred]u transferred",
"was [violent]injected with \the [weapon] - [reagents] [temperature_text] - [amount_transferred]u transferred",
"used \the [weapon] to [violent]inject [reagents] [temperature_text] ([amount_transferred]u transferred) into")

View File

@@ -246,4 +246,4 @@ var/list/global/random_stock_large = list()
name = "Large Stock Marker"
desc = "This marks a place where a large object could spawn in cargo"
icon = 'icons/mob/screen/generic.dmi'
icon_state = "x3"
icon_state = "x3"

View File

@@ -38,14 +38,34 @@
..()
gear_tweaks += new/datum/gear_tweak/reagents(lunchables_alcohol_reagents())
/datum/gear/vacflask
display_name = "vacuum-flask"
/datum/gear/vacflask_cold
display_name = "cold vacuum-flask"
path = /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask
/datum/gear/vacflask/New()
/datum/gear/vacflask_cold/New()
..()
gear_tweaks += new/datum/gear_tweak/reagents(lunchables_drink_reagents())
/datum/gear/vacflask_cold/spawn_item(var/location, var/metadata)
. = ..()
var/obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask/spawned_flask = .
if(istype(spawned_flask) && spawned_flask.reagents)
spawned_flask.reagents.set_temperature(T0C + 5)
/datum/gear/vacflask_hot
display_name = "hot vacuum-flask"
path = /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask
/datum/gear/vacflask_hot/New()
..()
gear_tweaks += new/datum/gear_tweak/reagents(lunchables_drink_reagents())
/datum/gear/vacflask_hot/spawn_item(var/location, var/metadata)
. = ..()
var/obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask/spawned_flask = .
if(istype(spawned_flask) && spawned_flask.reagents)
spawned_flask.reagents.set_temperature(T0C + 45)
/datum/gear/lunchbox
display_name = "lunchbox"
description = "A little lunchbox."
@@ -102,7 +122,6 @@
flags["flag, Democratic People's Republic of Adhomai"] = /obj/item/weapon/flag/dpra/l
gear_tweaks += new/datum/gear_tweak/path(flags)
/datum/gear/towel
display_name = "towel"
path = /obj/item/weapon/towel

View File

@@ -30,7 +30,7 @@
if(H.reagents)
var/contained_reagents = reagents.get_reagents()
var/trans = reagents.trans_to_mob(H, 15, CHEM_BLOOD)
admin_inject_log(usr, H, src, contained_reagents, trans)
admin_inject_log(usr, H, src, contained_reagents, reagents.get_temperature(), trans)
return
//Sleepy Ring

View File

@@ -54,6 +54,8 @@
var/reagent_mix = RECIPE_REAGENT_MAX //How to handle reagent differences between the ingredients and the results
var/finished_temperature = T0C + 40 //The temperature of the reagents of the final product.Only affects nutrient type.
var/appliance = MICROWAVE//Which apppliances this recipe can be made in.
//List of defines is in _defines/misc.dm. But for reference they are:
/*
@@ -163,6 +165,10 @@
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
for(var/datum/reagent/R in result_obj.reagents)
if(istype(R,/datum/reagent/nutriment/) && R.get_temperature() < finished_temperature)
R.set_temperature(finished_temperature)
return result_obj
// food-related

View File

@@ -60,4 +60,32 @@ calculate text size per text.
else
out += "[intensity_desc] [taste_desc]"
return "[english_list(out, "something indescribable")]."
var/temp_text = ""
switch(get_temperature())
if(-INFINITY to T0C - 50)
temp_text = "lethally freezing"
if(T0C - 50 to T0C - 25)
temp_text = "freezing"
if(T0C - 25 to T0C - 10)
temp_text = "very cold"
if(T0C - 10 to T0C)
temp_text = "cold"
if(T0C to T0C + 15)
temp_text = "cool"
if(T0C + 15 to T0C + 25)
temp_text = "lukewarm"
if(T0C + 25 to T0C + 40)
temp_text = "warm"
if(T0C + 40 to T0C + 70)
temp_text = "hot"
if(T0C + 70 to T0C + 90)
temp_text = "scolding hot"
if(T0C + 90 to T0C + 120)
temp_text = "burning hot"
if(T0C + 120 to T0C + 150)
temp_text = "molten hot"
if(T0C + 150 to INFINITY)
temp_text = "lethally hot"
return "[temp_text] [english_list(out, "something indescribable")]."

View File

@@ -93,7 +93,7 @@
if(M.reagents)
var/contained_reagents = reagents.get_reagents()
var/trans = reagents.trans_to_mob(M, 30, CHEM_BLOOD)
admin_inject_log(user, M, src, contained_reagents, trans)
admin_inject_log(user, M, src, contained_reagents, reagents.get_temperature(), trans)
/*
* Sleepy Pens

View File

@@ -53,7 +53,7 @@
if(L.can_inject() && syringe.reagents)
var/reagent_log = syringe.reagents.get_reagents()
syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD)
admin_inject_log(thrower, L, src, reagent_log, 15, violent=1)
admin_inject_log(thrower, L, src, reagent_log, reagents.get_temperature(), 15, violent=1)
syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null)
syringe.update_icon()

View File

@@ -39,7 +39,6 @@
return the_reagent
/datum/reagents/proc/get_reagent(var/id) // Returns reference to reagent matching passed ID
for(var/datum/reagent/A in reagent_list)
if (A.id == id)
@@ -67,14 +66,24 @@
return the_id
/datum/reagents/proc/update_total() // Updates volume.
/datum/reagents/proc/update_total() // Updates volume and temperature.
total_volume = 0
for(var/datum/reagent/R in reagent_list)
if(R.volume < MINIMUM_CHEMICAL_VOLUME)
del_reagent(R.id)
else
total_volume += R.volume
return
return max(total_volume,0)
/datum/reagents/proc/update_holder(var/reactions = TRUE)
if(update_total() && reactions)
handle_reactions()
if(my_atom)
my_atom.on_reagent_change()
/datum/reagents/proc/delete()
for(var/datum/reagent/R in reagent_list)
@@ -88,11 +97,8 @@
//returns 1 if the holder should continue reactiong, 0 otherwise.
/datum/reagents/proc/process_reactions()
if(!my_atom) // No reactions in temporary holders
return 0
if(!my_atom.loc) //No reactions inside GC'd containers
return 0
if(my_atom.flags & NOREACT) // No reactions here
if(!my_atom || !my_atom.loc || my_atom.flags & NOREACT)
equalize_temperature()
return 0
var/reaction_occured
@@ -118,42 +124,48 @@
for(var/datum/chemical_reaction/C in effect_reactions)
C.post_reaction(src)
update_total()
equalize_temperature()
update_holder(FALSE)
return reaction_occured
/* Holder-to-chemical */
/datum/reagents/proc/add_reagent(var/id, var/amount, var/data = null, var/safety = 0)
/datum/reagents/proc/add_reagent(var/id, var/amount, var/data = null, var/safety = 0, var/temperature = 0, var/thermal_energy = 0)
if(!isnum(amount) || amount <= 0)
return 0
update_total()
update_total() //Does this need to be here? It's called in update_holder.
amount = min(amount, get_free_space())
for(var/datum/reagent/current in reagent_list)
if(current.id == id)
if(current.id == id) //Existing reagent
current.volume += amount
if(thermal_energy > 0)
current.add_thermal_energy(thermal_energy)
else
if(temperature <= 0)
temperature = current.default_temperature
current.add_thermal_energy(temperature * current.specific_heat * amount)
if(!isnull(data)) // For all we know, it could be zero or empty string and meaningful
current.mix_data(data, amount)
update_total()
if(!safety)
handle_reactions()
if(my_atom)
my_atom.on_reagent_change()
update_holder(!safety)
return 1
var/datum/reagent/D = SSchemistry.chemical_reagents[id]
if(D)
var/datum/reagent/R = new D.type()
reagent_list += R
R.holder = src
R.volume = amount
R.specific_heat = SSchemistry.check_specific_heat(R)
if(thermal_energy > 0)
R.thermal_energy = thermal_energy
else
if(temperature <= 0)
temperature = R.default_temperature
R.set_temperature(temperature)
R.initialize_data(data)
update_total()
if(!safety)
handle_reactions()
if(my_atom)
my_atom.on_reagent_change()
update_holder(!safety)
return 1
else
warning("[my_atom] attempted to add a reagent called '[id]' which doesn't exist. ([usr])")
@@ -164,12 +176,10 @@
return 0
for(var/datum/reagent/current in reagent_list)
if(current.id == id)
var/old_volume = current.volume
current.volume -= amount // It can go negative, but it doesn't matter
update_total() // Because this proc will delete it then
if(!safety)
handle_reactions()
if(my_atom)
my_atom.on_reagent_change()
current.add_thermal_energy( -(current.thermal_energy * (amount/old_volume)) )
update_holder(!safety)
return 1
return 0
@@ -178,9 +188,7 @@
if (current.id == id)
reagent_list -= current
qdel(current)
update_total()
if(my_atom)
my_atom.on_reagent_change()
update_holder(FALSE)
return 0
/datum/reagents/proc/has_reagent(var/id, var/amount = 0)
@@ -247,8 +255,7 @@
var/amount_to_remove = current.volume * part
remove_reagent(current.id, amount_to_remove, 1)
update_total()
handle_reactions()
update_holder()
return amount
/datum/reagents/proc/trans_to_holder(var/datum/reagents/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Transfers [amount] reagents from [src] to [target], multiplying them by [multiplier]. Returns actual amount removed from [src] (not amount transferred to [target]).
@@ -268,7 +275,8 @@
for(var/datum/reagent/current in reagent_list)
var/amount_to_transfer = current.volume * part
target.add_reagent(current.id, amount_to_transfer * multiplier, current.get_data(), 1) // We don't react until everything is in place
var/energy_to_transfer = amount_to_transfer * current.get_thermal_energy_per_unit()
target.add_reagent(current.id, amount_to_transfer * multiplier, current.get_data(), 1, thermal_energy = energy_to_transfer * multiplier) // We don't react until everything is in place
if(!copy)
remove_reagent(current.id, amount_to_transfer, 1)
@@ -311,12 +319,14 @@
if (!target)
return
var/datum/reagent/transfering_reagent = get_reagent(id)
if (istype(target, /atom))
var/atom/A = target
if (!A.reagents || !A.simulated)
return
amount = min(amount, get_reagent_amount(id))
amount = min(amount, transfering_reagent.volume)
if(!amount)
return
@@ -324,7 +334,8 @@
var/datum/reagents/F = new /datum/reagents(amount)
var/tmpdata = get_data(id)
F.add_reagent(id, amount, tmpdata)
var/transfering_thermal_energy = transfering_reagent.get_thermal_energy() * (amount/transfering_reagent.volume)
F.add_reagent(id, amount, tmpdata, thermal_energy = transfering_thermal_energy)
remove_reagent(id, amount)
@@ -346,14 +357,23 @@
touch_obj(target)
return
/datum/reagents/proc/touch_mob(var/mob/target)
/datum/reagents/proc/touch_mob(var/mob/living/target)
if(!target || !istype(target) || !target.simulated)
return
var/temperature = src.get_temperature()
if(temperature >= REAGENTS_BURNING_TEMP_HIGH)
var/burn_damage = Clamp(total_volume*(temperature - REAGENTS_BURNING_TEMP_HIGH)*REAGENTS_BURNING_TEMP_HIGH_DAMAGE,0,20)
target.adjustFireLoss(burn_damage)
target.visible_message(span("danger","\The hot liquid burns \the [target]!"))
else if(temperature <= REAGENTS_BURNING_TEMP_LOW)
var/burn_damage = Clamp(total_volume*(REAGENTS_BURNING_TEMP_LOW - temperature)*REAGENTS_BURNING_TEMP_LOW_DAMAGE,0,20)
target.adjustFireLoss(burn_damage)
target.visible_message(span("danger","\The freezing cold liquid burns \the [target]!"))
for(var/datum/reagent/current in reagent_list)
current.touch_mob(target, current.volume)
update_total()
update_holder()
/datum/reagents/proc/touch_turf(var/turf/target)
if(!target || !istype(target) || !target.simulated)
@@ -362,7 +382,7 @@
for(var/datum/reagent/current in reagent_list)
current.touch_turf(target, current.volume)
update_total()
update_holder()
/datum/reagents/proc/touch_obj(var/obj/target)
if(!target || !istype(target) || !target.simulated)
@@ -371,7 +391,7 @@
for(var/datum/reagent/current in reagent_list)
current.touch_obj(target, current.volume)
update_total()
update_holder()
// Attempts to place a reagent on the mob's skin.
// Reagents are not guaranteed to transfer to the target.
@@ -421,7 +441,7 @@
var/datum/reagents/R = new /datum/reagents(amount * multiplier)
. = trans_to_holder(R, amount, multiplier, copy)
R.touch_turf(target)
/datum/reagents/proc/trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch.
if(!target || !target.simulated)

View File

@@ -20,4 +20,5 @@
for(var/datum/reagent/current in reagent_list)
current.on_mob_life(parent, metabolism_type, metabolism_class)
update_total()

View File

@@ -30,6 +30,16 @@
var/metabolism_min = 0.01 //How much for the medicine to be present in the system to actually have an effect.
var/conflicting_reagent //Reagents that conflict with this medicine, and cause adverse effects when in the blood.
var/default_temperature = T0C + 20 //This is it's default spawning temperature, if none is provided.
var/thermal_energy = 0 //Internal value, should never change.
var/specific_heat = -1 //The higher, the more difficult it is to change its difficult. 0 or lower values indicate that the specific heat has yet to be assigned.
var/fallback_specific_heat = -1 //Setting this value above 0 will set the specific heat to this value only if the system could not find an appropriate specific heat to assign using the recipe system.
//Never ever ever ever change this value for datum/reagent. This should only be used for massive, yet specific things like drinks or food where it is infeasible to assign a specific heat value.
/datum/reagent/proc/initialize_data(var/newdata) // Called when the reagent is created.
if(!isnull(newdata))
data = newdata
/datum/reagent/proc/remove_self(var/amount) // Shortcut
if (!holder)
//PROCLOG_WEIRD("Null holder found. Name: [name], id: [id]")
@@ -38,7 +48,7 @@
holder.remove_reagent(id, amount)
// This doesn't apply to skin contact - this is for, e.g. extinguishers and sprays. The difference is that reagent is not directly on the mob's skin - it might just be on their clothing.
/datum/reagent/proc/touch_mob(var/mob/M, var/amount)
/datum/reagent/proc/touch_mob(var/mob/living/M, var/amount)
return
/datum/reagent/proc/touch_obj(var/obj/O, var/amount) // Acid melting, cleaner cleaning, etc
@@ -55,9 +65,6 @@
if(alien & unaffected_species && location != CHEM_TOUCH)
return
if(!dose && volume)//If dose is currently zero, we do the first effect
initial_effect(M, alien)
var/removed = metabolism
if(ingest_met && (location == CHEM_INGEST))
removed = ingest_met
@@ -74,6 +81,12 @@
dose = min(dose + removed, max_dose)
//There is no science here. It's just pure gameplay balance.
//Every degree above/below room temp increases/decreases body temperature by 0.2 * removed.
//Drinking 1u of a 100 celcius mix will increase your body temperature by 16 celcius.
//Drinking 1u of a 1000 celcius mix will increase your body temperature by 160 celcius.
M.bodytemperature += (get_temperature() - (T0C + 20)) * removed * 0.2
for(var/datum/reagent/R in M.bloodstr.reagent_list)
if(istype(R, conflicting_reagent))
affect_conflicting(M,alien,removed,R)
@@ -87,6 +100,7 @@
affect_touch(M, alien, removed)
if(CHEM_BREATHE)
affect_breathe(M, alien, removed)
remove_self(removed)
//Initial effect is called once when the reagent first starts affecting a mob.
@@ -114,10 +128,6 @@
/datum/reagent/proc/overdose(var/mob/living/carbon/M, var/alien, var/removed = 0, var/scale = 1) // Overdose effect. Doesn't happen instantly.
M.adjustToxLoss(REM)
/datum/reagent/proc/initialize_data(var/newdata) // Called when the reagent is created.
if(!isnull(newdata))
data = newdata
/datum/reagent/proc/mix_data(var/newdata, var/newamount) // You have a reagent with data, and new reagent with its own data get added, how do you deal with that?
return
@@ -141,3 +151,7 @@
/datum/reagent/proc/reaction_mob(var/mob/target)
touch_mob(target)

View File

@@ -175,6 +175,8 @@
unaffected_species = IS_MACHINE
specific_heat = 1.541
/datum/reagent/water/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if(!istype(M))
return
@@ -222,6 +224,7 @@
cube.Expand()
/datum/reagent/water/touch_mob(var/mob/M, var/amount)
. = ..()
if(istype(M) && isliving(M))
var/mob/living/L = M
var/needed = L.fire_stacks * 10
@@ -259,6 +262,8 @@
glass_name = "glass of welder fuel"
glass_desc = "Unless you are an industrial tool, this is probably not safe for consumption."
specific_heat = 0.605
/datum/reagent/fuel/touch_turf(var/turf/T)
new /obj/effect/decal/cleanable/liquid_fuel(T, volume)
remove_self(volume)
@@ -268,6 +273,7 @@
M.adjustToxLoss(2 * removed)
/datum/reagent/fuel/touch_mob(var/mob/living/L, var/amount)
. = ..()
if(istype(L))
L.adjust_fire_stacks(amount / 10) // Splashing people with welding fuel to make them easy to ignite!
@@ -289,6 +295,7 @@
return
/datum/reagent/fuel/touch_mob(var/mob/living/L, var/amount)
. = ..()
if(istype(L))
L.adjust_fire_stacks(amount / 10) // Splashing people with welding fuel to make them easy to ignite!
new /obj/effect/decal/cleanable/liquid_fuel/napalm(get_turf(L), amount/3)

View File

@@ -6,6 +6,7 @@
color = "#808080"
metabolism = REM * 0.2
taste_description = "acid"
specific_heat = 0.567
/datum/reagent/acetone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.adjustToxLoss(removed * 3)
@@ -35,6 +36,7 @@
color = "#A8A8A8"
taste_description = "metal"
taste_mult = 1.1
specific_heat = 0.811
/datum/reagent/ammonia
name = "Ammonia"
@@ -47,6 +49,7 @@
taste_mult = 2
breathe_mul = 2
breathe_met = REM * 0.25
specific_heat = 1.048
/datum/reagent/ammonia/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_VOX)
@@ -63,6 +66,7 @@
ingest_met = REM * 5
taste_description = "sour chalk"
taste_mult = 1.5
specific_heat = 0.018
/datum/reagent/carbon/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if(M.ingested && M.ingested.reagent_list.len > 1) // Need to have at least 2 reagents - cabon and something to remove
@@ -87,6 +91,7 @@
description = "A highly ductile metal."
color = "#6E3B08"
taste_description = "copper"
specific_heat = 1.148
/datum/reagent/alcohol //Parent class for all alcoholic reagents, though this one shouldn't be used anywhere.
name = null // This null name should prevent alcohol from being added to global lists.
@@ -126,6 +131,7 @@
return ..()
/datum/reagent/alcohol/touch_mob(mob/living/L, amount)
. = ..()
if (istype(L) && strength > 40)
L.adjust_fire_stacks((amount / (flammability_divisor || 1)) * (strength / 100))
@@ -165,6 +171,8 @@
glass_name = "glass of ethanol"
glass_desc = "A well-known alcohol with a variety of applications."
specific_heat = 0.605
/datum/reagent/alcohol/ethanol/affect_ingest(var/mob/living/carbon/human/M, var/alien, var/removed)
if(!istype(M))
return
@@ -215,6 +223,8 @@
glass_name = "glass of butanol"
glass_desc = "A fairly harmless alcohol that has intoxicating effects on certain species."
specific_heat = 0.549
/datum/reagent/alcohol/butanol/affect_ingest(var/mob/living/carbon/human/M, var/alien, var/removed)
if(!istype(M))
return
@@ -240,6 +250,8 @@
touch_met = 5
taste_description = "sweet tasting metal"
specific_heat = 0.549 //Unknown
/datum/reagent/hydrazine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.adjustToxLoss(4 * removed)
@@ -260,6 +272,8 @@
color = "#353535"
taste_description = "metal"
specific_heat = 1.181
/datum/reagent/iron/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
M.add_chemical_effect(CE_BLOODRESTORE, 8 * removed)
@@ -271,6 +285,8 @@
color = "#808080"
taste_description = "metal"
specific_heat = 0.633
/datum/reagent/lithium/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(M.canmove && !M.restrained() && !(istype(M.loc, /turf/space)))
step(M, pick(cardinal))
@@ -286,6 +302,8 @@
ingest_met = REM*0.2
taste_mult = 0 //mercury apparently is tasteless
specific_heat = 0.631
/datum/reagent/mercury/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(M.canmove && !M.restrained() && !(istype(M.loc, /turf/space)))
step(M, pick(cardinal))
@@ -302,6 +320,8 @@
color = "#832828"
taste_description = "vinegar"
specific_heat = 0.569
/datum/reagent/potassium
name = "Potassium"
id = "potassium"
@@ -310,6 +330,8 @@
color = "#A0A0A0"
taste_description = "sweetness" //potassium is bitter in higher doses but sweet in lower ones.
specific_heat = 0.214
/datum/reagent/radium
name = "Radium"
id = "radium"
@@ -319,6 +341,8 @@
taste_description = "the color blue, and regret"
unaffected_species = IS_MACHINE
specific_heat = 0.220
/datum/reagent/radium/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.apply_effect(10 * removed, IRRADIATE, blocked = 0) // Radium may increase your chances to cure a disease
if(M.is_diona())
@@ -361,6 +385,8 @@
var/meltdose = 10 // How much is needed to melt
taste_description = "acid"
specific_heat = 0.815
/datum/reagent/acid/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.take_organ_damage(0, removed * power)
@@ -452,6 +478,8 @@
meltdose = 8
taste_description = "stomach acid"
specific_heat = 1.710
/datum/reagent/acid/polyacid //Not in dispensers, but it should be here
name = "Polytrinic acid"
id = "pacid"
@@ -469,6 +497,7 @@
reagent_state = SOLID
color = "#A8A8A8"
taste_description = "metal"
specific_heat = 2.650
/datum/reagent/sodium
name = "Sodium"
@@ -477,6 +506,7 @@
reagent_state = SOLID
color = "#808080"
taste_description = "salty metal"
specific_heat = 0.483
/datum/reagent/sugar
name = "Sugar"
@@ -491,6 +521,8 @@
glass_name = "glass of sugar"
glass_desc = "The organic compound commonly known as table sugar and sometimes called saccharose. This white, odorless, crystalline powder has a pleasing, sweet taste."
specific_heat = 0.332
/datum/reagent/sugar/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.adjustNutritionLoss(-removed*3)
@@ -500,7 +532,9 @@
description = "A chemical element with a pungent smell."
reagent_state = SOLID
color = "#BF8C00"
taste_description = "old eggs"
taste_description = "rotten eggs"
specific_heat = 0.503
/datum/reagent/tungsten
name = "Tungsten"
@@ -509,3 +543,6 @@
reagent_state = SOLID
color = "#DCDCDC"
taste_mult = 0 //no taste
specific_heat = 18
specific_heat = 0.859

View File

@@ -10,6 +10,7 @@
taste_description = "boiled cabbage"
unaffected_species = IS_MACHINE
var/kois_type = 1
specific_heat = 0.75
/datum/reagent/kois/affect_ingest(var/mob/living/carbon/human/M, var/alien, var/removed)
if(!istype(M))
@@ -45,6 +46,7 @@
color = "#ece9dd"
taste_description = "cabbage soup"
kois_type = 0
specific_heat = 1
/datum/reagent/kois/black
name = "Modified K'ois"
@@ -53,6 +55,7 @@
color = "#31004A"
taste_description = "tar"
kois_type = 2
specific_heat = 0.5
/* Food */
/datum/reagent/nutriment
@@ -72,6 +75,7 @@
color = "#664330"
unaffected_species = IS_MACHINE
taste_description = "food"
fallback_specific_heat = 1.25
/datum/reagent/nutriment/synthetic
name = "Synthetic Nutriment"
@@ -537,12 +541,15 @@
/datum/reagent/frostoil
name = "Frost Oil"
id = "frostoil"
description = "A special oil that noticably chills the body. Extracted from Ice Peppers."
description = "A special oil that chemically chills the body. Extracted from Ice Peppers."
reagent_state = LIQUID
color = "#B31008"
taste_description = "mint"
taste_mult = 1.5
specific_heat = 15
default_temperature = T0C - 20
/datum/reagent/frostoil/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.bodytemperature = max(M.bodytemperature - 10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
if(prob(1))
@@ -704,11 +711,12 @@
var/adj_dizzy = 0 // Per tick
var/adj_drowsy = 0
var/adj_sleepy = 0
var/adj_temp = 0
var/adj_temp = 0 //do NOT use for temp changes based on the temperature of the drinks, only for things such as spices.
var/caffeine = 0 // strength of stimulant effect, since so many drinks use it
var/datum/modifier/modifier = null
unaffected_species = IS_MACHINE
var/blood_to_ingest_scale = 2
fallback_specific_heat = 1.75
/datum/reagent/drink/Destroy()
if (modifier)
@@ -930,6 +938,8 @@
glass_name = "glass of milk"
glass_desc = "White and nutritious goodness!"
default_temperature = T0C + 5
/datum/reagent/drink/milk/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
..()
if(alien != IS_DIONA)
@@ -965,7 +975,6 @@
adj_dizzy = -2
adj_drowsy = -1
adj_sleepy = -3
adj_temp = 20
taste_description = "tart black tea"
glass_icon_state = "bigteacup"
@@ -979,7 +988,6 @@
id = "icetea"
description = "No relation to a certain rap artist/ actor."
color = "#104038" // rgb: 16, 64, 56
adj_temp = -5
taste_description = "sweet tea"
glass_icon_state = "icedteaglass"
@@ -996,7 +1004,6 @@
adj_dizzy = -5
adj_drowsy = -3
adj_sleepy = -2
adj_temp = 25
overdose = 45
caffeine = 0.3
taste_description = "coffee"
@@ -1029,7 +1036,6 @@
id = "icecoffee"
description = "Coffee and ice, refreshing and cool."
color = "#102838"
adj_temp = -5
glass_icon_state = "frappe"
glass_name = "glass of frappe coffee"
@@ -1040,7 +1046,6 @@
id = "soy_latte"
description = "A nice and tasty beverage while you are reading your hippie books."
color = "#664300"
adj_temp = 5
taste_description = "creamy coffee"
glass_icon_state = "soy_latte"
@@ -1053,7 +1058,6 @@
id = "cafe_latte"
description = "A nice, strong and tasty beverage while you are reading."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "bitter cream"
glass_icon_state = "cafe_latte"
@@ -1066,7 +1070,6 @@
id = "espresso"
description = "A strong coffee made by passing nearly boiling water through coffee seeds at high pressure."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "bitter coffee"
glass_icon_state = "hot_coffee"
@@ -1079,7 +1082,6 @@
id = "freddo_espresso"
description = "Espresso with ice cubes poured over ice."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "cold and bitter coffee"
glass_icon_state = "hot_coffee"
@@ -1092,7 +1094,6 @@
id = "caffe_americano"
description = "Espresso diluted with hot water."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "delicious coffee"
glass_icon_state = "hot_coffee"
@@ -1105,7 +1106,6 @@
id = "flat_white"
description = "Espresso with a bit of steamy hot milk."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "bitter coffee and milk"
glass_icon_state = "cafe_latte"
@@ -1118,7 +1118,6 @@
id = "latte"
description = "A nice, strong and refreshing beverage while you are reading."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "bitter cream"
glass_icon_state = "cafe_latte"
@@ -1131,7 +1130,6 @@
id = "cappuccino"
description = "Espresso with steamed milk foam."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "bitter milk foam"
glass_icon_state = "hot_coffee"
@@ -1144,7 +1142,6 @@
id = "freddo_cappuccino"
description = "Espresso with steamed milk foam, on ice."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "cold and bitter milk foam"
glass_icon_state = "hot_coffee"
@@ -1157,7 +1154,6 @@
id = "macchiato"
description = "Espresso with milk foam."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "bitter milk foam"
glass_icon_state = "hot_coffee"
@@ -1170,7 +1166,6 @@
id = "mocacchino"
description = "Espresso with hot milk and chocolate."
color = "#664300" // rgb: 102, 67, 0
adj_temp = 5
taste_description = "sweet milk and bitter coffee"
glass_icon_state = "cafe_latte"
@@ -1218,7 +1213,6 @@
reagent_state = LIQUID
color = "#403010"
nutrition = 2
adj_temp = 5
taste_description = "creamy chocolate"
glass_icon_state = "chocolateglass"
@@ -1232,7 +1226,6 @@
color = "#619494"
adj_dizzy = -5
adj_drowsy = -3
adj_temp = -5
taste_description = "carbonated water"
glass_icon_state = "glass_clear"
@@ -1259,7 +1252,6 @@
adj_dizzy = -5
adj_drowsy = -3
adj_sleepy = -2
adj_temp = -5
taste_description = "tart and fresh"
glass_icon_state = "glass_clear"
@@ -1271,7 +1263,6 @@
description = "Oh the nostalgia..."
id = "lemonade"
color = "#FFFF00"
adj_temp = -5
taste_description = "tartness"
glass_icon_state = "lemonadeglass"
@@ -1283,7 +1274,6 @@
description = "Long live the guy who everyone had mistaken for a girl. Baka!"
id = "kiraspecial"
color = "#CCCC99"
adj_temp = -5
taste_description = "fruity sweetness"
glass_icon_state = "kiraspecial"
@@ -1296,7 +1286,6 @@
description = "It's not what it sounds like..."
id = "brownstar"
color = "#9F3400"
adj_temp = -2
taste_description = "orange and cola soda"
glass_icon_state = "brownstar"
@@ -1320,7 +1309,6 @@
description = "Glorious brainfreezing mixture."
id = "milkshake"
color = "#AEE5E4"
adj_temp = -9
taste_description = "creamy vanilla"
glass_icon_state = "milkshake"
@@ -1333,7 +1321,6 @@
description = "The secret of the sanctuary of the Libarian..."
id = "rewriter"
color = "#485000"
adj_temp = -5
caffeine = 0.4
taste_description = "soda and coffee"
@@ -1352,7 +1339,6 @@
id = "nuka_cola"
description = "Cola, cola never changes."
color = "#100800"
adj_temp = -5
adj_sleepy = -2
caffeine = 1
taste_description = "cola"
@@ -1390,7 +1376,6 @@
reagent_state = LIQUID
color = "#100800"
adj_drowsy = -3
adj_temp = -5
taste_description = "cola"
glass_icon_state = "glass_brown"
@@ -1404,7 +1389,6 @@
color = "#102000"
adj_drowsy = -7
adj_sleepy = -1
adj_temp = -5
taste_description = "sweet citrus soda"
glass_icon_state = "Space_mountain_wind_glass"
@@ -1417,7 +1401,6 @@
description = "A delicious blend of 42 different flavours"
color = "#102000"
adj_drowsy = -6
adj_temp = -5
taste_description = "cherry soda"
glass_icon_state = "dr_gibb_glass"
@@ -1430,7 +1413,6 @@
description = "A classic Earth drink from the United Americas province."
color = "#211100"
adj_drowsy = -6
adj_temp = -5
taste_description = "sassafras and anise soda"
glass_icon_state = "root_beer_glass"
@@ -1442,7 +1424,6 @@
id = "space_up"
description = "Tastes like a hull breach in your mouth."
color = "#202800"
adj_temp = -8
taste_description = "a hull breach"
glass_icon_state = "space-up_glass"
@@ -1454,7 +1435,6 @@
description = "A tangy substance made of 0.5% natural citrus!"
id = "lemon_lime"
color = "#878F00"
adj_temp = -8
taste_description = "tangy lime and lemon soda"
glass_icon_state = "lemonlime"
@@ -1517,10 +1497,7 @@
nutrition = 5
hydration = 5
taste_description = "wet and cheap noodles on fire"
/datum/reagent/drink/hell_ramen/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
..()
M.bodytemperature += 10 * TEMPERATURE_DAMAGE_COEFFICIENT
adj_temp = 20
/datum/reagent/drink/ice
name = "Ice"
@@ -1528,7 +1505,6 @@
description = "Frozen water, your dentist wouldn't like you chewing this."
reagent_state = SOLID
color = "#619494"
adj_temp = -5
taste_description = "ice"
taste_mult = 1.5
hydration = 8
@@ -1537,6 +1513,8 @@
glass_name = "glass of ice"
glass_desc = "Generally, you're supposed to put something else in there too..."
default_temperature = T0C - 10
/datum/reagent/drink/nothing
name = "Nothing"
id = "nothing"
@@ -2342,7 +2320,6 @@
description = "A beer which is so cold the air around it freezes."
color = "#664300"
strength = 5
adj_temp = -20
targ_temp = 270
taste_description = "refreshingly cold"
@@ -2868,8 +2845,6 @@
id = "dr_gibb_diet"
description = "A delicious blend of 42 different flavours, one of which is water."
color = "#102000"
adj_temp = -5
taste_description = "watered down liquid sunshine"
glass_icon_state = "dr_gibb_glass"
@@ -2881,7 +2856,6 @@
id = "dr_daniels"
description = "A limited edition tallboy of Dr. Gibb's Infusions."
color = "#8e6227"
adj_temp = -5
caffeine = 0.2
overdose = 80
strength = 20
@@ -3468,7 +3442,6 @@
color = "#664300"
strength = 15
taste_description = "cold oily gin"
adj_temp = -15
targ_temp = 270
glass_icon_state = "winter_offensive"
@@ -3692,7 +3665,6 @@
id = "zora_cherry"
description = "Zo'ra Soda, cherry edition. All good drinks come in cherry."
color = "#102000"
adj_temp = -5
adj_sleepy = -2
caffeine = 0.2
taste_description = "electric cherry"
@@ -3702,7 +3674,6 @@
id = "zora_phoron"
description = "Reported to taste nothing like phoron, but everything like grapes."
color = "#863333"
adj_temp = -5
adj_sleepy = -2
caffeine = 0.2
taste_description = "electric grape"
@@ -3712,7 +3683,6 @@
id = "zora_kois"
description = "Whoever approved this in marketing needs to be drawn and quartered."
color = "#dcd9cd"
adj_temp = -5
adj_sleepy = -2
caffeine = 0.2
taste_description = "sugary cabbage"
@@ -3727,7 +3697,6 @@
id = "zora_hozm"
description = "It feels like someone is just driving a freezing cold spear through the bottom of your mouth."
color = "#365000"
adj_temp = -5
adj_sleepy = -3
caffeine = 0.3
taste_description = "a full-body bite into an acidic lemon"
@@ -3744,7 +3713,6 @@
id = "zora_venom"
description = "The 'diet' version of High Energy Zorane Might, still tastes like a cloud of stinging polytrinic bees."
color = "#100800"
adj_temp = -5
adj_sleepy = -3
caffeine = 0.1
taste_description = "fizzy nettles"
@@ -3759,7 +3727,6 @@
id = "zora_klax"
description = "An orange, cream soda. It's a wonder it got here."
color = "#E78108"
adj_temp = -5
adj_sleepy = -3
caffeine = 0.2
unaffected_species = IS_MACHINE
@@ -3775,7 +3742,6 @@
id = "zora_cthur"
description = "A raspberry concoction you're pretty sure is already on recall."
color = "#0000CD"
adj_temp = -5
adj_sleepy = -3
caffeine = 0.2
taste_description = "flat raspberry"
@@ -3790,7 +3756,6 @@
id = "zora_drone"
description = "It's thick as syrup and smells of gas. Why."
color = "#31004A"
adj_temp = -5
adj_sleepy = -3
taste_description = "viscous cola"
@@ -3815,7 +3780,6 @@
id = "zora_jelly"
description = "It looks of mucus, but tastes like Heaven."
color = "#FFFF00"
adj_temp = -5
adj_sleepy = -3
caffeine = 0.2
taste_description = "a reassuring spectrum of color"

View File

@@ -142,7 +142,7 @@
/datum/reagent/tricordrazine
name = "Tricordrazine"
id = "tricordrazine"
description = "Tricordrazine is a highly potent stimulant, originally derived from cordrazine. Can be used to treat a wide range of injuries, however it does not work when inhaled."
description = "Tricordrazine is a highly potent stimulant, originally derived from cordrazine. Can be used to treat a wide range of injuries, however it does not work when inhaled. Has different healing properties depending on the chemical's temperature."
reagent_state = LIQUID
color = "#8040FF"
scannable = 1
@@ -150,8 +150,11 @@
breathe_mul = 0
/datum/reagent/tricordrazine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
var/power = 1 + Clamp((get_temperature() - (T0C + 20))*0.1,-0.5,0.5)
//Heals 10% more brute and less burn for every 1 celcius above 20 celcius, up 50% more/less.
//Heals 10% more burn and less brute for every 1 celcius below 20 celcius, up to 50% more/less.
M.adjustOxyLoss(-6 * removed)
M.heal_organ_damage(3 * removed, 3 * removed)
M.heal_organ_damage(3 * removed * power,3 * removed * power)
M.adjustToxLoss(-3 * removed)
/datum/reagent/cryoxadone
@@ -174,7 +177,7 @@
/datum/reagent/clonexadone
name = "Clonexadone"
id = "clonexadone"
description = "A liquid compound similar to that used in the cloning process. Can be used to 'finish' the cloning process when used in conjunction with a cryo tube."
description = "A liquid compound similar to that used in the cloning process. Can be used to 'finish' the cloning process when used in conjunction with a cryo tube. Its main limitation is that the targets body temperature must be under 170K for it to metabolise correctly."
reagent_state = LIQUID
color = "#80BFFF"
metabolism = REM * 0.5

View File

@@ -8,6 +8,7 @@
color = "#888888"
overdose = 5
taste_description = "the back of class"
specific_heat = 0.4
/datum/reagent/crayon_dust/red
name = "Red crayon dust"
@@ -58,6 +59,7 @@
overdose = REAGENTS_OVERDOSE * 0.5
color_weight = 20
taste_description = "chalk"
specific_heat = 0.2
/datum/reagent/paint/touch_turf(var/turf/T)
if(istype(T) && !istype(T, /turf/space))
@@ -82,6 +84,7 @@
O.color = color
/datum/reagent/paint/touch_mob(var/mob/M)
. = ..()
if(istype(M) && !istype(M, /mob/abstract)) //painting ghosts: not allowed
M.color = color //maybe someday change this to paint only clothes and exposed body parts for human mobs.
@@ -123,7 +126,7 @@
/datum/reagent/adminordrazine //An OP chemical for admins
name = "Adminordrazine"
id = "adminordrazine"
description = "It's magic. We don't have to explain it."
description = "It's magic, I ain't gotta explain shit."
reagent_state = LIQUID
color = "#C8A5DC"
affects_dead = 1 //This can even heal dead people.
@@ -131,7 +134,10 @@
glass_icon_state = "golden_cup"
glass_name = "golden cup"
glass_desc = "It's magic. We don't have to explain it."
glass_desc = "It's magic, I ain't gotta explain shit."
specific_heat = 10 //Magical.
/datum/reagent/adminordrazine/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
affect_blood(M, alien, removed)
@@ -172,6 +178,7 @@
reagent_state = SOLID
color = "#F7C430"
taste_description = "expensive metal"
specific_heat = 2.511
/datum/reagent/silver
name = "Silver"
@@ -180,6 +187,7 @@
reagent_state = SOLID
color = "#D0D0D0"
taste_description = "expensive yet reasonable metal"
specific_heat = 0.241
/datum/reagent/uranium
name ="Uranium"
@@ -188,6 +196,7 @@
reagent_state = SOLID
color = "#B8B8C0"
taste_description = "the inside of a reactor"
specific_heat = 2.286
/datum/reagent/uranium/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
affect_ingest(M, alien, removed)
@@ -210,6 +219,7 @@
reagent_state = SOLID
color = "#E0E0E0"
taste_description = "salty metalic miner tears"
specific_heat = 0.2971
/datum/reagent/adrenaline
name = "Adrenaline"
@@ -218,6 +228,7 @@
reagent_state = LIQUID
color = "#C8A5DC"
taste_description = "bitterness"
specific_heat = 0.75
/datum/reagent/adrenaline/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.SetParalysis(0)
@@ -290,6 +301,7 @@
taste_description = "sweet tasting metal"
/datum/reagent/thermite/touch_turf(var/turf/T)
. = ..()
if(volume >= 5)
if(istype(T, /turf/simulated/wall))
var/turf/simulated/wall/W = T
@@ -422,6 +434,7 @@
description = "An extremely powerful bonding agent."
color = "#FFFFCC"
taste_description = "a special education class"
fallback_specific_heat = 1.5
/datum/reagent/woodpulp
name = "Wood Pulp"
@@ -430,6 +443,7 @@
reagent_state = LIQUID
color = "#B97A57"
taste_description = "wood"
fallback_specific_heat = 1.9
/datum/reagent/luminol
name = "Luminol"
@@ -439,10 +453,27 @@
color = "#F2F3F4"
taste_description = "metal"
/datum/reagent/pyrosilicate
name = "Pyrosilicate"
id = "pyrosilicate"
description = "A bright orange powder consisting of strange self-heating properties that reacts when exposed to sodium chloride."
reagent_state = SOLID
color = "#FFFF00"
taste_description = "chalk"
/datum/reagent/cryosurfactant
name = "Cryosurfactant"
id = "cryosurfactant"
description = "A bright cyan liquid consisting of strange self-cooling properties that reacts when exposed to water."
reagent_state = LIQUID
color = "#00FFFF"
taste_description = "needles"
/datum/reagent/luminol/touch_obj(var/obj/O)
O.reveal_blood()
/datum/reagent/luminol/touch_mob(var/mob/living/L)
. = ..()
L.reveal_blood()
/datum/reagent/estus
@@ -455,6 +486,7 @@
metabolism = REM * 0.25
taste_description = "bottled fire"
var/datum/modifier/modifier
fallback_specific_heat = 2.75
/datum/reagent/estus/affect_blood(var/mob/living/carbon/M, var/removed)
if (!modifier)
@@ -482,8 +514,10 @@
color = "#E25822"
touch_met = 5
taste_description = "metal"
fallback_specific_heat = 20 //This holds a ton of heat.
/datum/reagent/liquid_fire/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
. = ..()
if(istype(M))
M.adjust_fire_stacks(10)
M.IgniteMob()
@@ -499,6 +533,7 @@
description = "A pitch black blend of cosmic origins, handle with care."
color = "#000000"
taste_description = "emptyness"
fallback_specific_heat = 100 //Yeah...
/datum/reagent/black_matter/touch_turf(var/turf/T)
var/obj/effect/portal/P = new /obj/effect/portal(T)
@@ -522,6 +557,7 @@
description = "A dust composed of microscopic bluespace crystals."
color = "#1f8999"
taste_description = "fizzling blue"
fallback_specific_heat = 0.1
/datum/reagent/bluespace_dust/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(prob(25))
@@ -532,6 +568,7 @@
do_teleport(M, get_turf(M), 5, asoundin = 'sound/effects/phasein.ogg')
/datum/reagent/bluespace_dust/touch_mob(var/mob/living/L, var/amount)
. = ..()
do_teleport(L, get_turf(L), amount, asoundin = 'sound/effects/phasein.ogg')
/datum/reagent/philosopher_stone
@@ -540,6 +577,7 @@
description = "A mythical compound, rumored to be the catalyst of fantastic reactions."
color = "#f4c430"
taste_description = "heavenly knowledge"
fallback_specific_heat = 1.25
/datum/reagent/sglue
name = "Sovereign Glue"
@@ -548,6 +586,7 @@
reagent_state = LIQUID
color = "#EDE8E2"
taste_description = "horses"
fallback_specific_heat = 1.25
/datum/reagent/sglue/touch_obj(var/obj/O)
if((istype(O, /obj/item) && !istype(O, /obj/item/weapon/reagent_containers)) && (volume > 10*O.w_class))
@@ -564,6 +603,7 @@
reagent_state = LIQUID
color = "#EDE8E2"
taste_description = "alcohol"
fallback_specific_heat = 1.75
/datum/reagent/usolve/touch_obj(var/obj/O)
if((istype(O, /obj/item) && !istype(O, /obj/item/weapon/reagent_containers)) && (volume > 10*O.w_class))
@@ -580,6 +620,7 @@
reagent_state = SOLID
color = "#c2b280"
taste_description = "sand"
fallback_specific_heat = 0.75
/datum/reagent/shapesand/touch_obj(var/obj/O)
if((istype(O, /obj/item) && !istype(O, /obj/item/weapon/reagent_containers)) && (volume > 10*O.w_class))
@@ -616,6 +657,7 @@
reagent_state = LIQUID
color = "#ff69b4"
taste_description = "sickly sweet candy"
fallback_specific_heat = 2 //Thicc
/datum/reagent/love_potion/affect_blood(var/mob/living/carbon/human/H, var/alien, var/removed)
@@ -633,6 +675,7 @@
reagent_state = LIQUID
color = "#70838A"
taste_description = "metal"
fallback_specific_heat = 10
/datum/reagent/bottle_lightning/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(prob(25))

View File

@@ -10,6 +10,7 @@
var/strength = 4 // How much damage it deals per unit
taste_description = "bitterness"
taste_mult = 1.2
fallback_specific_heat = 0.75
/datum/reagent/toxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(strength)
@@ -69,6 +70,7 @@
touch_met = 5
taste_mult = 1.5
breathe_mul = 2
specific_heat = 2 //Phoron is very dense and can hold a lot of energy.
/datum/reagent/toxin/phoron/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(ishuman(M))
@@ -101,10 +103,8 @@
else
..()
/datum/reagent/toxin/phoron/touch_mob(var/mob/living/L, var/amount)
. = ..()
if(istype(L))
L.adjust_fire_stacks(amount / 5)
@@ -125,6 +125,14 @@
T.assume_gas("phoron", volume, T20C)
remove_self(volume)
/datum/reagent/toxin/phoron_salt //Remember to exclude in RNG chems.
name = "Phoron Salts"
id = "phoron_salt"
description = "A mysterious molten mixture with strange chemical properties."
reagent_state = SOLID
color = "#7C4876"
strength = 30
/datum/reagent/toxin/cardox
name = "Cardox"
id = "cardox"
@@ -305,6 +313,7 @@
return
/datum/reagent/toxin/fertilizer/monoammoniumphosphate/touch_mob(var/mob/living/L, var/amount)
. = ..()
if(istype(L))
var/needed = L.fire_stacks * 10
if(amount > needed)

View File

@@ -7,7 +7,7 @@
//HALF_LIFE(0) -> Reaction completes immediately (default chems)
//HALF_LIFE(1) -> Half of the reagents react immediately, the rest over the following ticks.
//HALF_LIFE(2) -> Half of the reagents are consumed after 2 chemistry ticks.
//HALF_LIFE(3) -> Half of the reagents are consumed after 3 chemistry ticks.
//HALF_LIFE(2.2) -> Half of the reagents are consumed after 2.2 chemistry ticks.
#define HALF_LIFE(ticks) (ticks? 1.0 - (0.5)**(1.0/(ticks*PROCESS_REACTION_ITER)) : 1.0)
/datum/chemical_reaction
@@ -15,6 +15,8 @@
var/id = null
var/result = null
var/list/required_reagents = list()
var/list/required_temperatures_min = list() //Format: reagent name = required_kelvin. Temperatures must exceed this value to trigger.
var/list/required_temperatures_max = list() //Format: reagent name = required_kelvin. Temperatures must be less than this value to trigger.
var/list/catalysts = list()
var/list/inhibitors = list()
var/result_amount = 0
@@ -47,6 +49,9 @@
if(holder.has_any_reagent(inhibitors))
return 0
if(!holder.has_all_temperatures(required_temperatures_min, required_temperatures_max))
return 0
return 1
/datum/chemical_reaction/proc/calc_reaction_progress(var/datum/reagents/holder, var/reaction_limit)
@@ -93,32 +98,37 @@
var/data = send_data(holder, reaction_progress)
//remove the reactants
var/total_thermal_energy = 0
for(var/reactant in required_reagents)
var/amt_used = required_reagents[reactant] * reaction_progress
var/datum/reagent/removing_reagent = holder.get_reagent(reactant)
total_thermal_energy += removing_reagent.get_thermal_energy() * (amt_used / removing_reagent.volume)
holder.remove_reagent(reactant, amt_used, safety = 1)
//add the product
var/amt_produced = result_amount * reaction_progress
if(result)
holder.add_reagent(result, amt_produced, data, safety = 1)
holder.add_reagent(result, amt_produced, data, safety = 1, thermal_energy = total_thermal_energy)
on_reaction(holder, amt_produced)
on_reaction(holder, amt_produced, total_thermal_energy)
return reaction_progress
//called when a reaction processes
/datum/chemical_reaction/proc/on_reaction(var/datum/reagents/holder, var/created_volume)
/datum/chemical_reaction/proc/on_reaction(var/datum/reagents/holder, var/created_volume, var/created_thermal_energy)
return
//called after processing reactions, if they occurred
/datum/chemical_reaction/proc/post_reaction(var/datum/reagents/holder)
var/atom/container = holder.my_atom
if(mix_message && container && !ismob(container))
if(container && !ismob(container))
var/turf/T = get_turf(container)
var/list/seen = viewers(4, T)
for(var/mob/M in seen)
M.show_message("<span class='notice'>\icon[container] [mix_message]</span>", 1)
playsound(T, reaction_sound, 80, 1)
if(mix_message)
var/list/seen = viewers(4, T)
for(var/mob/M in seen)
M.show_message("<span class='notice'>\icon[container] [mix_message]</span>", 1)
if(reaction_sound)
playsound(T, reaction_sound, 80, 1)
//obtains any special data that will be provided to the reaction products
//this is called just before reactants are removed.
@@ -252,9 +262,9 @@
name = "Peridaxon"
id = "peridaxon"
result = "peridaxon"
required_reagents = list("bicaridine" = 2, "clonexadone" = 2)
required_reagents = list("bicaridine" = 1, "clonexadone" = 1)
catalysts = list("phoron" = 5)
result_amount = 2
result_amount = 1
/datum/chemical_reaction/virus_food
name = "Virus Food"
@@ -2815,14 +2825,14 @@
id = "psfrappe"
result = "psfrappe"
required_reagents = list("icecoffee" = 6, "pumpkinspice" = 2, "cream" = 2)
result_amount = 10
result_amount = 10
/datum/chemical_reaction/pslatte
name = "Pumpkin Spice Latte"
id = "pslatte"
result = "pslatte"
required_reagents = list("coffee" = 6, "pumpkinspice" = 2, "cream" = 2)
result_amount = 10
result_amount = 10
//transmutation
@@ -2867,3 +2877,125 @@
for(var/i = 1, i <= created_volume, i++)
new /obj/item/stack/material/diamond(location)
return
//Temperature Additions
/datum/chemical_reaction/water_to_ice
name = "Water to Ice"
id = "water_to_ice"
result = "ice"
required_reagents = list("water" = 1)
required_temperatures_max = list("water" = T0C - 1)
result_amount = 0.5
mix_message = ""
reaction_sound = ""
/datum/chemical_reaction/ice_to_water
name = "Ice to Water"
id = "ice_to_water"
result = "water"
required_reagents = list("ice" = 1)
required_temperatures_min = list("ice" = T0C + 1)
result_amount = 2
reaction_rate = HALF_LIFE(4) //CONFIRMED?
mix_message = ""
reaction_sound = ""
/datum/chemical_reaction/phoron_salt //Safe temperatures for phoron salt is between 0 degress celcius and 200 celcius.
name = "Phoron Salt"
id = "phoron_salt"
result = "phoron_salt"
required_reagents = list("sodiumchloride" = 1, "phoron" = 2)
required_temperatures_min = list("sodiumchloride" = T0C + 200, "phoron" = T0C - 200)
required_temperatures_max = list("phoron" = T0C - 5)
result_amount = 1
/datum/chemical_reaction/pyrosilicate
name = "Pyrosilicate"
id = "pyrosilicate"
result = "pyrosilicate"
result_amount = 4
required_reagents = list("silicate" = 1, "sacid" = 1, "hydrazine" = 1, "iron" = 1)
/datum/chemical_reaction/cryosurfactant
name = "Cryosurfactant"
id = "cryosurfactant"
result = "cryosurfactant"
result_amount = 3
required_reagents = list("surfactant" = 1, "ice" = 1, "sodium" = 1)
/datum/chemical_reaction/cryosurfactant_cooling
name = "Cryosurfactant Cooling"
id = "cryosurfactant_cooling"
result = null
result_amount = 1
required_reagents = list("cryosurfactant" = 1)
inhibitors = list("pyrosilicate" = 1)
catalysts = list("water" = 1)
/datum/chemical_reaction/cryosurfactant_cooling/on_reaction(var/datum/reagents/holder, var/created_volume)
holder.add_thermal_energy(-created_volume*500)
/datum/chemical_reaction/pyrosilicate_heating
name = "Pyrosilicate Heating"
id = "pyrosilicate_heating"
result = null
result_amount = 1
required_reagents = list("pyrosilicate" = 1)
inhibitors = list("cryosurfactant" = 1)
catalysts = list("sodiumchloride" = 1)
/datum/chemical_reaction/pyrosilicate_heating/on_reaction(var/datum/reagents/holder, var/created_volume)
holder.add_thermal_energy(created_volume*1000)
/datum/chemical_reaction/pyrosilicate_cryosurfactant
name = "Pyrosilicate Cryosurfactant Reaction"
id = "pyrosilicate_cryosurfactant"
result = null
required_reagents = list("pyrosilicate" = 1, "cryosurfactant" = 1)
required_temperatures_min = list("pyrosilicate" = T0C, "cryosurfactant" = T0C) //Does not react when below these temperatures.
result_amount = 1
/datum/chemical_reaction/pyrosilicate_cryosurfactant/on_reaction(var/datum/reagents/holder, var/created_volume, var/created_thermal_energy)
if(created_volume)
var/turf/simulated/floor/T = get_turf(holder.my_atom.loc)
if(istype(T))
T.assume_gas("oxygen", created_volume*10, (created_thermal_energy/created_volume) )
/datum/chemical_reaction/phoron_salt_fire
name = "Phoron Salt Fire"
id = "phoron_salt_fire"
result = "carbon"
result_amount = 1
required_reagents = list("phoron_salt" = 1)
required_temperatures_min = list("phoron_salt" = T0C + 200)
/datum/chemical_reaction/phoron_salt_fire/on_reaction(var/datum/reagents/holder, var/created_volume, var/created_thermal_energy)
var/turf/location = get_turf(holder.my_atom.loc)
for(var/turf/simulated/floor/target_tile in range(0,location))
target_tile.assume_gas("phoron", created_volume*0.5, created_thermal_energy/created_volume) //The goal here is to hold as much thermal energy as possible with a large amount of volume.
target_tile.assume_gas("carbon_dioxide", created_volume*0.5, (created_thermal_energy/created_volume) )
addtimer(CALLBACK(target_tile, /turf/simulated/floor/.proc/hotspot_expose, 700, 400), 1)
holder.del_reagent("phoron_salt")
return
/datum/chemical_reaction/phoron_salt_coldfire
name = "Phoron Salt Coldfire"
id = "phoron_salt_coldfire"
result = "hydrazine"
result_amount = 1
required_reagents = list("phoron_salt" = 1)
required_temperatures_max = list("phoron_salt" = T0C + 0)
/datum/chemical_reaction/phoron_salt_coldfire/on_reaction(var/datum/reagents/holder, var/created_volume, var/created_thermal_energy)
var/datum/effect/effect/system/reagents_explosion/e = new()
var/explosion_mod = (holder.get_thermal_energy() + created_thermal_energy) * 0.001 //The more thermal energy inside a container, the bigger the explosion.
explosion_mod = Clamp(explosion_mod,1,32) //Let it be known that not even the dev who made this knows the full destuctive potential of this fuckery, so a maxcap of 32 is implemented.
e.set_up(round (explosion_mod, 1), holder.my_atom, 0, 0)
if(isliving(holder.my_atom))
e.amount *= 0.5
var/mob/living/L = holder.my_atom
if(L.stat != DEAD)
e.amount *= 0.5
e.start()
holder.clear_reagents()
return

View File

@@ -0,0 +1,125 @@
//Everything to do with reagents having temperature. Override reagent procs to make your own snowflake special reagent with mystical properties.
// https://www.aqua-calc.com/calculate/volume-to-weight/substance/
// https://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html USE THE TABLE ON THE LEFT
// https://www.engineeringtoolbox.com/specific-heat-solids-d_154.html USE THE TABLE ON THE RIGHT
// http://www2.ucdsb.on.ca/tiss/stretton/database/specific_heat_capacity_table.html
// https://www.nuclear-power.net/radium-specific-heat-latent-heat-vaporization-fusion/
/datum/reagents/proc/get_thermal_energy()
var/returning = 0
for(var/datum/reagent/R in reagent_list)
returning += R.get_thermal_energy()
return returning
/datum/reagent/proc/get_thermal_energy()
return thermal_energy
/datum/reagents/proc/get_heat_capacity()
var/returning = 0
for(var/datum/reagent/R in reagent_list)
if(total_volume)
returning += R.get_heat_capacity()
return returning
/datum/reagent/proc/get_heat_capacity()
return specific_heat * volume
/datum/reagents/proc/get_temperature()
var/HC = get_heat_capacity()
if(HC)
return get_thermal_energy() / (HC)
else
return T0C + 20
/datum/reagent/proc/get_temperature()
var/HC = get_heat_capacity()
if(HC)
return get_thermal_energy() / (HC)
else
return T0C + 20
/datum/reagents/proc/get_thermal_energy_change(var/old_temperature, var/new_temperature)
return get_heat_capacity()*(max(new_temperature, TCMB) - old_temperature)
/datum/reagent/proc/get_thermal_energy_change(var/old_temperature, var/new_temperature)
return get_heat_capacity()*(max(new_temperature, TCMB) - old_temperature)
/datum/reagent/proc/get_thermal_energy_per_unit()
return get_thermal_energy() / volume
/datum/reagent/proc/add_thermal_energy(var/added_energy)
thermal_energy += added_energy
return added_energy
/datum/reagent/proc/set_thermal_energy(var/set_energy)
return add_thermal_energy(-get_thermal_energy() + set_energy)
/datum/reagents/proc/set_thermal_energy(var/set_energy)
return add_thermal_energy(-get_thermal_energy() + set_energy)
/datum/reagent/proc/set_temperature(var/new_temperature)
return add_thermal_energy(-get_thermal_energy() + get_thermal_energy_change(0,new_temperature) )
/datum/reagents/proc/set_temperature(var/new_temperature)
return add_thermal_energy(-get_thermal_energy() + get_thermal_energy_change(0,new_temperature) )
/datum/reagents/proc/equalize_thermal_energy()
var/thermal_energy_to_add = get_thermal_energy()
for(var/datum/reagent/R in reagent_list)
R.add_thermal_energy(-R.get_thermal_energy() + (thermal_energy_to_add * (1/reagent_list.len)) )
/datum/reagents/proc/equalize_temperature()
var/total_thermal_energy = 0
var/total_heat_capacity = 0
for(var/datum/reagent/R in reagent_list)
total_thermal_energy += R.get_thermal_energy()
total_heat_capacity += R.get_heat_capacity()
for(var/datum/reagent/R in reagent_list)
R.set_thermal_energy( total_thermal_energy * (R.get_heat_capacity()/total_heat_capacity) )
/datum/reagents/proc/add_thermal_energy(var/thermal_energy_to_add)
var/total_energy_added = 0
for(var/datum/reagent/R in reagent_list)
total_energy_added += R.add_thermal_energy(thermal_energy_to_add * (1/reagent_list.len))
return total_energy_added
/*
/datum/reagents/proc/add_thermal_energy(var/thermal_energy_to_add)
if (total_volume == 0)
return 0
var/returning_energy_used = 0
for(var/datum/reagent/R in reagent_list)
var/local_thermal_energy = thermal_energy_to_add / reagent_list.len
if (local_thermal_energy < 0)
if (R.get_temperature() < TCMB)
return 0
var/thermal_energy_limit = -(R.get_temperature() - TCMB) * R.get_heat_capacity() //ensure temperature does not go below TCMB
local_thermal_energy = max( local_thermal_energy, thermal_energy_limit ) //thermal_energy and thermal_energy_limit are negative here.
returning_energy_used += R.add_thermal_energy(local_thermal_energy)
return returning_energy_used
*/
/datum/reagents/proc/has_all_temperatures(var/list/required_temperatures_min, var/list/required_temperatures_max)
for(var/datum/reagent/current in reagent_list)
if(current.id in required_temperatures_min) //The current temperature must be greater than this temperature
var/current_temperature = current.get_temperature()
var/required_temperature = required_temperatures_min[current.id]
if(current_temperature < required_temperature) //Current temperature is less than the required temperature,
return FALSE
if(current.id in required_temperatures_max) //The current temperature must be less than this temperature.
var/current_temperature = current.get_temperature()
var/required_temperature = required_temperatures_max[current.id]
if(current_temperature > required_temperature) //Current temperature is greater than the required temperature.
return FALSE
return TRUE

View File

@@ -93,6 +93,11 @@
return
/obj/item/weapon/reagent_containers/proc/get_temperature()
if(reagents)
return reagents.get_temperature()
return T0C + 20
/obj/item/weapon/reagent_containers/proc/reagentlist() // For attack logs
if(reagents)
return reagents.get_reagents()
@@ -143,8 +148,10 @@
return 1
var/contained = reagentlist()
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been splashed with [name] by [user.name] ([user.ckey]). Reagents: [contained]</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [name] to splash [target.name] ([target.key]). Reagents: [contained]</font>")
var/temperature = reagents.get_temperature()
var/temperature_text = "Temperature: ([temperature]K/[temperature]C)"
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been splashed with [name] by [user.name] ([user.ckey]). Reagents: [contained] [temperature_text].</font>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [name] to splash [target.name] ([target.key]). Reagents: [contained] [temperature_text].</font>")
msg_admin_attack("[user.name] ([user.ckey]) splashed [target.name] ([target.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(target))
user.visible_message("<span class='danger'>\The [target] has been splashed with something by \the [user]!</span>", "<span class = 'warning'>You splash the solution onto \the [target].</span>")

View File

@@ -83,7 +83,7 @@
var/t = min(amount_per_transfer_from_this, reagent_volumes[reagent_ids[mode]])
M.reagents.add_reagent(reagent_ids[mode], t)
reagent_volumes[reagent_ids[mode]] -= t
admin_inject_log(user, M, src, reagent_ids[mode], t)
admin_inject_log(user, M, src, reagent_ids[mode], reagents.get_temperature(), t)
to_chat(user,"<span class='notice'>[t] units injected. [reagent_volumes[reagent_ids[mode]]] units remaining.</span>")
return

View File

@@ -372,3 +372,25 @@
. = ..()
reagents.add_reagent("frostoil", 60)
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/pyrosilicate
name = "pyrosilicate bottle"
desc = "A small bottle. Contains pyrosilicate - used to heat up reagents."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
Initialize()
. = ..()
reagents.add_reagent("pyrosilicate", 60)
update_icon()
/obj/item/weapon/reagent_containers/glass/bottle/cryosurfactant
name = "cryosurfactant bottle"
desc = "A small bottle. Contains cryosurfactant - used to cool down reagents."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
Initialize()
. = ..()
reagents.add_reagent("cryosurfactant", 60)
update_icon()

View File

@@ -49,7 +49,7 @@
if(M.reagents)
var/contained = reagentlist()
var/trans = reagents.trans_to_mob(M, amount_per_transfer_from_this, CHEM_BLOOD)
admin_inject_log(user, M, src, contained, trans)
admin_inject_log(user, M, src, contained, reagents.get_temperature(), trans)
to_chat(user,"<span class='notice'>[trans] units injected. [reagents.total_volume] units remaining in \the [src].</span>")
update_icon()

View File

@@ -33,7 +33,7 @@
if(H.reagents)
var/contained = reagentlist()
var/trans = reagents.trans_to_mob(H, amount_per_transfer_from_this, CHEM_TOUCH)
admin_inject_log(user, H, src, contained, trans)
admin_inject_log(user, H, src, contained, reagents.get_temperature(), trans)
playsound(src.loc, 'sound/items/stimpack.ogg', 50, 1)
user.visible_message("<span class='notice'>[user] accidentally sticks the [src] in [H]'s eyes!</span>","<span class='notice'>You accidentally stick the [src] in [H]'s eyes!</span>")
to_chat(user,"<span class='notice'>[trans] units injected. [reagents.total_volume] units remaining in \the [src].</span>")
@@ -65,7 +65,7 @@
if(H.reagents)
var/contained = reagentlist()
var/trans = reagents.trans_to_mob(H, amount_per_transfer_from_this, CHEM_BREATHE, bypass_checks = TRUE)
var/trans = reagents.trans_to_mob(H, amount_per_transfer_from_this, reagents.get_temperature(), CHEM_BREATHE, bypass_checks = TRUE)
admin_inject_log(user, H, src, contained, trans)
playsound(src.loc, 'sound/items/stimpack.ogg', 50, 1)
to_chat(user,"<span class='notice'>[trans] units injected. [reagents.total_volume] units remaining in \the [src].</span>")

View File

@@ -141,7 +141,7 @@
if(M.reagents)
var/contained = stored_cartridge.reagentlist()
var/trans = stored_cartridge.reagents.trans_to_mob(M, transfer_amount, CHEM_BREATHE, bypass_checks = TRUE)
admin_inject_log(user, M, src, contained, trans)
admin_inject_log(user, M, src, contained, reagents.get_temperature(), trans)
playsound(M.loc, 'sound/items/stimpack.ogg', 50, 1)
if(eject_when_empty)
to_chat(user,"<span class='notice'>\The [stored_cartridge] automatically ejects from \the [src].</span>")

View File

@@ -194,7 +194,7 @@
if(ismob(target))
var/contained = reagentlist()
trans = reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_BLOOD)
admin_inject_log(user, target, src, contained, trans)
admin_inject_log(user, target, src, contained, reagents.get_temperature(), trans)
else
trans = reagents.trans_to(target, amount_per_transfer_from_this)
user << "<span class='notice'>You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units.</span>"
@@ -269,13 +269,11 @@
user.visible_message("<span class='danger'>[user] stabs [target] with [src.name]!</span>")
target.take_organ_damage(3)// 7 is the same as crowbar punch
var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand
var/contained_reagents = reagents.get_reagents()
var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD)
if(isnull(trans)) trans = 0
admin_inject_log(user, target, src, contained_reagents, trans, violent=1)
admin_inject_log(user, target, src, contained_reagents, reagents.get_temperature(), trans, violent=1)
break_syringe(target, user)
/obj/item/weapon/reagent_containers/syringe/proc/break_syringe(mob/living/carbon/target, mob/living/carbon/user)