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

@@ -507,6 +507,7 @@
#include "code\game\machinery\CableLayer.dm"
#include "code\game\machinery\case_button.dm"
#include "code\game\machinery\cell_charger.dm"
#include "code\game\machinery\chem_heater.dm"
#include "code\game\machinery\cloning.dm"
#include "code\game\machinery\constructable_frame.dm"
#include "code\game\machinery\crusher_piston.dm"
@@ -845,6 +846,7 @@
#include "code\game\objects\items\weapons\circuitboards\computer\station_alert.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\telecomms.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\biogenerator.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\chem_heater.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\cloning.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\commsantenna.dm"
#include "code\game\objects\items\weapons\circuitboards\machinery\mech_recharger.dm"
@@ -2102,6 +2104,7 @@
#include "code\modules\reagents\Chemistry-Reagents-Helpers.dm"
#include "code\modules\reagents\Chemistry-Reagents.dm"
#include "code\modules\reagents\Chemistry-Recipes.dm"
#include "code\modules\reagents\Chemistry-Temperature.dm"
#include "code\modules\reagents\reagent_containers.dm"
#include "code\modules\reagents\reagent_dispenser.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Core.dm"
@@ -2387,6 +2390,7 @@
#include "code\modules\web_interface\webint_procs.dm"
#include "code\modules\xgm\xgm_gas_data.dm"
#include "code\modules\xgm\xgm_gas_mixture.dm"
#include "code\unit_tests\chemistry_tests.dm"
#include "code\unit_tests\equipment_tests.dm"
#include "code\unit_tests\foundation_tests.dm"
#include "code\unit_tests\map_tests.dm"

View File

@@ -17,6 +17,12 @@
#define REAGENTS_OVERDOSE 30
#define REAGENTS_BURNING_TEMP_HIGH T0C + 65 //Temperature at which high temperature burns occur
#define REAGENTS_BURNING_TEMP_HIGH_DAMAGE 0.01 //Damage per celcius above the REAGENTS_BURNING_TEMP_HIGH define per unit.
#define REAGENTS_BURNING_TEMP_LOW T0C - 80 //Temperature at which low temperature burns occur
#define REAGENTS_BURNING_TEMP_LOW_DAMAGE 0.005 //Damage per celcius below the REAGENTS_BURNING_TEMP_LOW define per unit.
#define CHEM_SYNTH_ENERGY 500 // How much energy does it take to synthesize 1 unit of chemical, in Joules.
// Some on_mob_life() procs check for alien races.

View File

@@ -7,9 +7,64 @@ var/datum/controller/subsystem/chemistry/SSchemistry
var/list/active_holders = list()
var/list/chemical_reactions
var/list/chemical_reactions_clean = list()
var/list/chemical_reagents
var/tmp/list/processing_holders = list()
/datum/controller/subsystem/chemistry/proc/has_valid_specific_heat(var/datum/reagent/R) //Used for unit tests
if(R.specific_heat > 0)
return TRUE
if(chemical_reagents[R.id].specific_heat > 0) //Don't think this will happen but you never know.
return TRUE
var/datum/chemical_reaction/recipe = find_recipe_by_result(R.id)
if(recipe)
for(var/chem in recipe.required_reagents)
if(!has_valid_specific_heat(chemical_reagents[chem]))
return FALSE
if(R.fallback_specific_heat)
return TRUE
return FALSE
/datum/controller/subsystem/chemistry/proc/check_specific_heat(var/datum/reagent/R)
if(R.specific_heat > 0)
return R.specific_heat
if(chemical_reagents[R.id].specific_heat > 0) //Don't think this will happen but you never know.
return chemical_reagents[R.id].specific_heat
var/datum/chemical_reaction/recipe = find_recipe_by_result(R.id)
if(recipe)
var/final_heat = 0
var/result_amount = recipe.result_amount
for(var/chem in recipe.required_reagents)
var/chem_specific_heat = check_specific_heat(chemical_reagents[chem])
if(!chem_specific_heat)
log_ss("chemistry", "ERROR: [R.type] does not have a specific heat value set, and there is no associated recipe for it! Please fix this by giving it a specific_heat value!")
final_heat += chem_specific_heat * (recipe.required_reagents[chem]/result_amount)
if(final_heat > 0)
chemical_reagents[R.id].specific_heat = final_heat
return final_heat
if(R.fallback_specific_heat)
chemical_reagents[R.id].specific_heat = R.fallback_specific_heat
return R.fallback_specific_heat
log_ss("chemistry", "ERROR: [R.type] does not have a specific heat value set, and there is no associated recipe for it! Please fix this by giving it a specific_heat value!")
chemical_reagents[R.id].specific_heat = 1
return 1
/datum/controller/subsystem/chemistry/proc/find_recipe_by_result(var/result_id)
for(var/key in chemical_reactions_clean)
var/datum/chemical_reaction/CR = chemical_reactions_clean[key]
if(CR.result == result_id && CR.result_amount > 0)
return CR
/datum/controller/subsystem/chemistry/stat_entry()
..("AH:[active_holders.len]")
@@ -46,7 +101,7 @@ var/datum/controller/subsystem/chemistry/SSchemistry
if (MC_TICK_CHECK)
return
/datum/controller/subsystem/chemistry/proc/mark_for_update(var/datum/reagents/holder)
if (holder in active_holders)
return
@@ -122,3 +177,5 @@ var/datum/controller/subsystem/chemistry/SSchemistry
if(!chemical_reactions[reagent_id])
chemical_reactions[reagent_id] = list()
chemical_reactions[reagent_id] += D
if(D.id)
chemical_reactions_clean[D.id] = D

View File

@@ -1,14 +1,16 @@
/datum/wires/smartfridge
holder_type = /obj/machinery/smartfridge
wire_count = 3
wire_count = 5
/datum/wires/smartfridge/secure
random = 1
wire_count = 4
wire_count = 6
var/const/SMARTFRIDGE_WIRE_ELECTRIFY = 1
var/const/SMARTFRIDGE_WIRE_THROW = 2
var/const/SMARTFRIDGE_WIRE_IDSCAN = 4
var/const/SMARTFRIDGE_WIRE_COOLING = 8
var/const/SMARTFRIDGE_WIRE_HEATING = 16
/datum/wires/smartfridge/CanUse(var/mob/living/L)
var/obj/machinery/smartfridge/S = holder
@@ -26,6 +28,8 @@ var/const/SMARTFRIDGE_WIRE_IDSCAN = 4
. += "<BR>The orange light is [S.seconds_electrified ? "off" : "on"].<BR>"
. += "The red light is [S.shoot_inventory ? "off" : "blinking"].<BR>"
. += "A [S.scan_id ? "purple" : "yellow"] light is on.<BR>"
. += "The cyan light is [S.cooling ? "on" : "off"].<BR>"
. += "The blue light is [S.heating ? "on" : "off"].<BR>"
/datum/wires/smartfridge/UpdatePulsed(var/index)
var/obj/machinery/smartfridge/S = holder
@@ -36,6 +40,12 @@ var/const/SMARTFRIDGE_WIRE_IDSCAN = 4
S.seconds_electrified = 30
if(SMARTFRIDGE_WIRE_IDSCAN)
S.scan_id = !S.scan_id
if(SMARTFRIDGE_WIRE_COOLING)
S.cooling = !S.cooling
S.heating = FALSE
if(SMARTFRIDGE_WIRE_HEATING)
S.heating = !S.cooling
S.cooling = FALSE
/datum/wires/smartfridge/UpdateCut(var/index, var/mended)
var/obj/machinery/smartfridge/S = holder
@@ -49,3 +59,11 @@ var/const/SMARTFRIDGE_WIRE_IDSCAN = 4
S.seconds_electrified = -1
if(SMARTFRIDGE_WIRE_IDSCAN)
S.scan_id = 1
if(SMARTFRIDGE_WIRE_COOLING)
S.cooling = mended
S.heating = FALSE
if(SMARTFRIDGE_WIRE_HEATING)
S.heating = mended
S.cooling = FALSE

View File

@@ -2,12 +2,14 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
wire_count = 4
wire_count = 6
var/const/VENDING_WIRE_THROW = 1
var/const/VENDING_WIRE_CONTRABAND = 2
var/const/VENDING_WIRE_ELECTRIFY = 4
var/const/VENDING_WIRE_IDSCAN = 8
var/const/VENDING_WIRE_COOLING = 16
var/const/VENDING_WIRE_HEATING = 32
/datum/wires/vending/CanUse(var/mob/living/L)
var/obj/machinery/vending/V = holder
@@ -26,6 +28,8 @@ var/const/VENDING_WIRE_IDSCAN = 8
. += "The red light is [V.shoot_inventory ? "off" : "blinking"].<BR>"
. += "The green light is [(V.categories & CAT_HIDDEN) ? "on" : "off"].<BR>"
. += "The [V.scan_id ? "purple" : "yellow"] light is on.<BR>"
. += "The cyan light is [V.temperature_setting == -1 ? "on" : "off"].<BR>"
. += "The blue light is [V.temperature_setting == 1 ? "on" : "off"].<BR>"
/datum/wires/vending/UpdatePulsed(var/index)
var/obj/machinery/vending/V = holder
@@ -38,6 +42,10 @@ var/const/VENDING_WIRE_IDSCAN = 8
V.seconds_electrified = 30
if(VENDING_WIRE_IDSCAN)
V.scan_id = !V.scan_id
if(VENDING_WIRE_COOLING)
V.temperature_setting = V.temperature_setting != -1 ? -1 : 0
if(VENDING_WIRE_HEATING)
V.temperature_setting = V.temperature_setting != 1 ? 1 : 0
/datum/wires/vending/UpdateCut(var/index, var/mended)
var/obj/machinery/vending/V = holder
@@ -53,3 +61,7 @@ var/const/VENDING_WIRE_IDSCAN = 8
V.seconds_electrified = -1
if(VENDING_WIRE_IDSCAN)
V.scan_id = 1
if(VENDING_WIRE_COOLING)
V.temperature_setting = mended && V.temperature_setting != 1 ? -1 : 0
if(VENDING_WIRE_HEATING)
V.temperature_setting = mended && V.temperature_setting != -1 ? 1 : 0

View File

@@ -0,0 +1,156 @@
/obj/machinery/chem_heater
name = "chemical heater"
icon = 'icons/obj/chemical.dmi'
icon_state = "mixer0b"
use_power = 0
idle_power_usage = 100
density = 1
anchored = 1
var/obj/item/weapon/reagent_containers/container
var/target_temperature = 300 //Measured in kelvin.
var/accept_drinking = FALSE
var/machine_strength = 0 //How much joules to add per process. Controlled by manipulators.
var/should_heat = TRUE
var/min_temperature = 50
var/max_temperature = 1000
component_types = list(
/obj/item/weapon/circuitboard/chem_heater,
/obj/item/weapon/stock_parts/manipulator,
/obj/item/weapon/stock_parts/manipulator,
/obj/item/weapon/stock_parts/manipulator
)
/obj/machinery/chem_heater/attack_hand(mob/user)
user.set_machine(src)
interact(user)
/obj/machinery/chem_heater/attackby(obj/item/O, mob/user)
if(default_deconstruction_screwdriver(user, O))
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(istype(O, /obj/item/weapon/reagent_containers/glass) || istype(O, /obj/item/weapon/reagent_containers/food))
if(container)
to_chat(user,span("warning","There is already \a [container] on \the [src]!"))
return
var/obj/item/weapon/reagent_containers/RC = O
if(!RC.is_open_container())
to_chat(user,span("warning","You don't see how \the [src] could heat up the reagents in \the [RC]."))
return
container = RC
user.drop_from_inventory(RC,src)
to_chat(user,span("notice","You set \the [RC] in \the [src]."))
updateUsrDialog()
return
/obj/machinery/chem_heater/interact(mob/user as mob)
if(stat & BROKEN)
return
user.set_machine(src)
var/dat ="<html>"
dat += "<head><TITLE>Chem Heater MKI</TITLE><style>body{font-family:Garamond}</style></head>"
dat += "<body><H1>Chem Heater MKI</H1>"
dat += "<p>Power: <a href='?src=\ref[src];action=togglepower'>[use_power ? "On" : "Off"]</a></p>"
dat += "<p>Target Temp: [round(target_temperature)]K / [round(target_temperature - T0C,0.1)]C<br> "
dat += "("
dat += "<a href='?src=\ref[src];action=adjusttemp;power=-100'>----</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=-25'>---</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=-5'>--</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=-1'>-</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=1'>+</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=5'>++</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=25'>+++</a>|"
dat += "<a href='?src=\ref[src];action=adjusttemp;power=100'>++++</a>"
dat += ")</p>"
if(container)
dat += "<p>Beaker Temp: [round(container.get_temperature(),0.01)]K / [round(container.get_temperature() - T0C,0.1)]C (<a href='?src=\ref[src];action=removebeaker'>Remove</a>)</p>"
else
dat += "<p>No container loaded!</p>"
dat += "</body><html>"
user << browse(dat, "window=chem_heater")
onclose(user, "chem_heater")
/obj/machinery/chem_heater/Topic(href, href_list)
if(stat & BROKEN) return
if(usr.stat || usr.restrained()) return
if(!in_range(src, usr)) return
usr.set_machine(src)
switch(href_list["action"])
if("togglepower")
use_power = !use_power
if(container)
should_heat = target_temperature >= container.get_temperature()
if("removebeaker")
if(container)
container.forceMove(src.loc)
container = null
update_icon()
if("adjusttemp")
target_temperature = max(min_temperature,min(target_temperature + text2num(href_list["power"]),max_temperature))
if(container)
should_heat = target_temperature >= container.get_temperature()
updateUsrDialog()
/obj/machinery/chem_heater/machinery_process()
..()
if(!use_power)
return
if(container && container.reagents)
var/current_temperature = container.reagents.get_temperature()
if(should_heat && current_temperature >= target_temperature)
use_power = 0
updateUsrDialog()
return
else if(!should_heat && current_temperature <= target_temperature)
use_power = 0
updateUsrDialog()
return
var/joules_to_use = machine_strength * 1000
var/mod = should_heat ? 1 : -1
var/thermal_energy_change = 0
var/thermal_energy_limit = container.reagents.get_thermal_energy_change(current_temperature,target_temperature) //Don't go over the target temperature
var/thermal_energy_limit2 = container.reagents.get_thermal_energy_change(current_temperature,current_temperature + machine_strength*mod*5) //So small reagents don't go from 0 to 1000 in a few seconds.
if(mod > 0) //GOING UP
thermal_energy_change = min(joules_to_use,thermal_energy_limit,thermal_energy_limit2)
else //GOING DOWN
thermal_energy_change = max(-joules_to_use,thermal_energy_limit,thermal_energy_limit2)
container.reagents.add_thermal_energy(thermal_energy_change)
container.reagents.handle_reactions()
use_power(joules_to_use)
updateUsrDialog()
else
use_power = 0
updateUsrDialog()
return
return 1
/obj/machinery/chem_heater/RefreshParts()
machine_strength = initial(machine_strength)
for(var/obj/item/weapon/stock_parts/P in component_parts)
if(ismanipulator(P))
machine_strength += P.rating

View File

@@ -21,6 +21,12 @@
var/locked = 0
var/scan_id = 1
var/is_secure = 0
var/cooling = 0 //Whether or not to vend products at the cooling temperature
var/heating = 0 //Whether or not to vend products at the heating temperature
var/cooling_temperature = T0C + 5 //Best temp for soda.
var/heating_temperature = T0C + 57 //Best temp for coffee.
var/datum/wires/smartfridge/wires = null
atmos_canpass = CANPASS_NEVER
@@ -131,6 +137,7 @@
/obj/machinery/smartfridge/drinks
name = "\improper Drink Showcase"
desc = "A refrigerated storage unit for tasty tasty alcohol."
cooling = TRUE
/obj/machinery/smartfridge/drinks/accept_check(var/obj/item/O as obj)
if(istype(O,/obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks) || istype(O,/obj/item/weapon/reagent_containers/food/condiment))
@@ -176,6 +183,33 @@
src.seconds_electrified--
if(src.shoot_inventory && prob(2))
src.throw_item()
if(cooling || heating)
var/mod = cooling ? -1 : 1
for(var/obj/item/I in contents)
if(!I.reagents)
continue
var/r_temperature = I.reagents.get_temperature()
if(mod == 1 && r_temperature <= heating_temperature)
continue
else if(mod == -1 && r_temperature <= cooling_temperature)
continue
var/thermal_energy_change = 0
if(mod == 1) //GOING UP
thermal_energy_change = min(active_power_usage,I.reagents.get_thermal_energy_change(r_temperature,heating_temperature))
else if (mod == -1) //GOING DOWN
thermal_energy_change = max(-active_power_usage,I.reagents.get_thermal_energy_change(r_temperature,cooling_temperature))
I.reagents.add_thermal_energy(thermal_energy_change)
use_power(active_power_usage)
/obj/machinery/smartfridge/power_change()
var/old_stat = stat

View File

@@ -103,6 +103,11 @@
var/list/restock_blocked_items = list() //Items that can not be restocked if restock_items is enabled
var/random_itemcount = 1 //If the number of items should be randomized
var/temperature_setting = 0 //-1 means cooling, 1 means heating, 0 means doing nothing.
var/cooling_temperature = T0C + 5 //Best temp for soda.
var/heating_temperature = T0C + 57 //Best temp for coffee.
/obj/machinery/vending/Initialize()
. = ..()
wires = new(src)
@@ -569,8 +574,6 @@
src.status_error = 0
SSnanoui.update_uis(src)
if (R.category & CAT_COIN)
if(!coin)
user << "<span class='notice'>You need to insert a coin to get this item.</span>"
@@ -606,12 +609,20 @@
flick(src.icon_vend,src)
spawn(src.vend_delay)
playsound(src.loc, 'sound/machines/vending.ogg', 35, 1)
new R.product_path(get_turf(src))
var/obj/vended = new R.product_path(get_turf(src))
src.status_message = ""
src.status_error = 0
src.vend_ready = 1
currently_vending = null
SSnanoui.update_uis(src)
if(istype(vended,/obj/item/weapon/reagent_containers/))
var/obj/item/weapon/reagent_containers/RC = vended
if(RC.reagents)
switch(temperature_setting)
if(-1)
use_power(RC.reagents.set_temperature(cooling_temperature))
if(1)
use_power(RC.reagents.set_temperature(heating_temperature))
/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
user << "<span class='notice'>You insert \the [R.product_name] in the product receptor.</span>"

View File

@@ -129,7 +129,6 @@
icon_vend = "coffee-vend"
vend_delay = 34
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee
vend_id = "coffee"
products = list(
/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,
@@ -148,6 +147,9 @@
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 22,
/obj/item/weapon/reagent_containers/food/snacks/donut/normal = 6
)
cooling_temperature = T0C + 57 //Optimal coffee temperature
heating_temperature = T0C + 100 //ULTRA HOT COFFEE
temperature_setting = -1
/obj/machinery/vending/snack
name = "Getmore Chocolate Corp"
@@ -247,6 +249,7 @@
/obj/item/weapon/reagent_containers/food/drinks/cans/koispunch = 50
)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
temperature_setting = -1
//This one's from bay12
/obj/machinery/vending/cart
@@ -328,6 +331,7 @@
)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
random_itemcount = 0
temperature_setting = -1
//This one's from bay12
/obj/machinery/vending/phoronresearch
@@ -369,6 +373,7 @@
/obj/item/weapon/reagent_containers/pill/tox = 1
)
random_itemcount = 0
temperature_setting = -1
/obj/machinery/vending/wallmed2
name = "NanoMed"
@@ -389,6 +394,7 @@
/obj/item/weapon/reagent_containers/pill/tox = 3
)
random_itemcount = 0
temperature_setting = -1
/obj/machinery/vending/security
name = "SecTech"
@@ -649,6 +655,7 @@
)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
random_itemcount = 0
temperature_setting = -1
/obj/machinery/vending/tool
name = "YouTool"
@@ -861,6 +868,7 @@
/obj/item/weapon/reagent_containers/food/drinks/cans/zoradrone = 30,
)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
temperature_setting = -1
/obj/machinery/vending/battlemonsters
name = "\improper Battlemonsters vendor"

View File

@@ -0,0 +1,12 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/chem_heater
name = T_BOARD("chem heater")
build_path = "/obj/machinery/chem_heater"
board_type = "machine"
origin_tech = list(TECH_DATA = 1, TECH_BIO = 2)
req_components = list(
"/obj/item/weapon/stock_parts/manipulator" = 3
)

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)

View File

@@ -0,0 +1,29 @@
/*
*
* Specific Heat Chemistry Test
* Checks if a reagent has a specific heat value.
*
*/
datum/unit_test/specific_heat
name = "Chemistry Test - Specific Heat"
datum/unit_test/specific_heat/start_test()
var/error_count = 0
for(var/type_found in subtypesof(/datum/reagent/))
var/datum/reagent/R = new type_found
if(istype(R) && R.id && R.name)
if(!SSchemistry.has_valid_specific_heat(R))
log_unit_test("[ascii_red][R.type] lacks a proper specific heat value![ascii_reset]")
error_count++
qdel(R)
if(error_count)
fail("[error_count] reagents(s) found without a proper specific heat value. Assign a specific heat value or make a recipe with these reagents as the final product.")
else
pass("All reagents have a specific heat value.")
return 1

View File

@@ -0,0 +1,43 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# wip (For works in progress)
# tweak
# soundadd
# sounddel
# rscadd (general adding of nice things)
# rscdel (general deleting of nice things)
# imageadd
# imagedel
# maptweak
# spellcheck (typo fixes)
# experiment
# balance
#################################
# Your name.
author: BurgerBB
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
changes:
- experiment: "Added a new system that allows reagents to have their own temperatures. Includes a new unit test for devs."
- rscadd: "Added a few new reagents; phoron salts, cryosufacant, pyrosilicate. Ice can be created by cooling water, and water can be created by heating ice."
- rscadd: "Added a new chemistry heater that can cool or heat reagents between a range of a temperature. Vending machines and smartfridges have a temperature setting that can either heat or cool reagents; affected by manipulating wires. Ovens and microwaves automatically heat up the reagents to the recipe's requirement."
- tweak: "Crewmembers can spawn with either a heated or cooled vacuum flask."
- rscadd: "Consuming hot reagents raise your body temperature. Cold reagents lower it. Extremely hot or extremely cold reagents can burn you when splashed."
- tweak: "Tricordrazine heals more brute and less burn when hot, and heals more burn and less brute when cold."
- bugfix: "Updated clonexadone description to accurately describe what it does. Updated Peridaxon recipe to fix odd recipe logic."

View File

@@ -5959,10 +5959,20 @@
"alF" = (
/obj/effect/floor_decal/corner/mauve{
icon_state = "corner_white";
dir = 5
dir = 10
},
/obj/structure/table/standard,
/obj/item/weapon/packageWrap,
/obj/item/weapon/packageWrap,
/obj/item/device/destTagger,
/obj/machinery/light{
dir = 2;
icon_state = "tube1";
pixel_y = 0
},
/obj/item/weapon/hand_labeler,
/turf/simulated/floor/tiled/white,
/area/rnd/misc_lab)
/area/medical/chemistry)
"alG" = (
/obj/structure/table/standard,
/obj/structure/cable/green,
@@ -33680,26 +33690,17 @@
icon_state = "corner_white";
dir = 10
},
/obj/structure/table/standard,
/obj/item/weapon/packageWrap,
/obj/item/weapon/packageWrap,
/obj/item/device/destTagger,
/obj/machinery/light{
dir = 2;
icon_state = "tube1";
pixel_y = 0
},
/obj/machinery/chem_heater,
/turf/simulated/floor/tiled/white,
/area/medical/chemistry)
"bgD" = (
/obj/effect/floor_decal/corner/mauve{
icon_state = "corner_white";
dir = 10
dir = 5
},
/obj/structure/table/standard,
/obj/item/weapon/hand_labeler,
/obj/machinery/chem_heater,
/turf/simulated/floor/tiled/white,
/area/medical/chemistry)
/area/rnd/misc_lab)
"bgE" = (
/obj/effect/floor_decal/corner/mauve/full{
icon_state = "corner_white_full";
@@ -89467,7 +89468,7 @@ bBv
bCv
bDo
aeD
alF
bgD
afW
akL
aoP
@@ -95872,7 +95873,7 @@ bbd
kqR
bjV
bfp
bgC
alF
bfJ
xIT
mRk
@@ -96129,7 +96130,7 @@ bbe
bcC
pyh
bfp
bgD
bgC
bfJ
bjw
bcL