diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 0976ed5ea3..f1de2ddd45 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -49,3 +49,11 @@ var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglyce
var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart.
var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional
+
+#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
+#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
+#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
+#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
+#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
+#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
+#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
\ No newline at end of file
diff --git a/code/controllers/subsystems/chemistry.dm b/code/controllers/subsystems/chemistry.dm
new file mode 100644
index 0000000000..148e975542
--- /dev/null
+++ b/code/controllers/subsystems/chemistry.dm
@@ -0,0 +1,58 @@
+SUBSYSTEM_DEF(chemistry)
+ name = "Chemistry"
+ wait = 20
+ flags = SS_NO_FIRE
+ init_order = INIT_ORDER_CHEMISTRY
+
+ var/list/chemical_reactions = list()
+ var/list/instant_reactions_by_reagent = list()
+ var/list/distilled_reactions_by_reagent = list()
+// var/list/fusion_reactions_by_reagent = list() // TODO: Fusion reactions as chemical reactions
+ var/list/chemical_reagents = list()
+
+/datum/controller/subsystem/chemistry/Recover()
+ log_debug("[name] subsystem Recover().")
+ chemical_reactions = SSchemistry.chemical_reactions
+ chemical_reagents = SSchemistry.chemical_reagents
+
+/datum/controller/subsystem/chemistry/Initialize()
+ initialize_chemical_reagents()
+ initialize_chemical_reactions()
+ ..()
+
+/datum/controller/subsystem/chemistry/stat_entry()
+ ..("C: [chemical_reagents.len] | R: [chemical_reactions.len]")
+
+//Chemical Reactions - Initialises all /decl/chemical_reaction into a list
+// It is filtered into multiple lists within a list.
+// For example:
+// chemical_reactions_by_reagent["phoron"] is a list of all reactions relating to phoron
+// Note that entries in the list are NOT duplicated. So if a reaction pertains to
+// more than one chemical it will still only appear in only one of the sublists.
+/datum/controller/subsystem/chemistry/proc/initialize_chemical_reactions()
+ var/list/paths = decls_repository.get_decls_of_subtype(/decl/chemical_reaction)
+
+ for(var/path in paths)
+ var/decl/chemical_reaction/D = paths[path]
+ chemical_reactions += D
+ if(D.required_reagents && D.required_reagents.len)
+ var/reagent_id = D.required_reagents[1]
+
+ var/list/add_to = instant_reactions_by_reagent // Default to instant reactions list, if something's gone wrong
+// if(istype(D, /decl/chemical_reaction/fusion)) // TODO: fusion reactions as chemical reactions
+// add_to = fusion_reactions_by_reagent
+ if(istype(D, /decl/chemical_reaction/distilling))
+ add_to = distilled_reactions_by_reagent
+
+ LAZYINITLIST(add_to[reagent_id])
+ add_to[reagent_id] += D
+
+//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
+/datum/controller/subsystem/chemistry/proc/initialize_chemical_reagents()
+ var/paths = subtypesof(/datum/reagent)
+ chemical_reagents = list()
+ for(var/path in paths)
+ var/datum/reagent/D = new path()
+ if(!D.name)
+ continue
+ chemical_reagents[D.id] = D
diff --git a/code/controllers/subsystems/processing/chemistry.dm b/code/controllers/subsystems/processing/chemistry.dm
deleted file mode 100644
index b4641ba7e0..0000000000
--- a/code/controllers/subsystems/processing/chemistry.dm
+++ /dev/null
@@ -1,54 +0,0 @@
-PROCESSING_SUBSYSTEM_DEF(chemistry)
- name = "Chemistry"
- wait = 20
- flags = SS_BACKGROUND|SS_POST_FIRE_TIMING
- init_order = INIT_ORDER_CHEMISTRY
- var/list/chemical_reactions = list()
- var/list/chemical_reactions_by_reagent = list()
- var/list/chemical_reagents = list()
-
-/datum/controller/subsystem/processing/chemistry/Recover()
- log_debug("[name] subsystem Recover().")
- if(SSchemistry.current_thing)
- log_debug("current_thing was: (\ref[SSchemistry.current_thing])[SSchemistry.current_thing]([SSchemistry.current_thing.type]) - currentrun: [SSchemistry.currentrun.len] vs total: [SSchemistry.processing.len]")
- var/list/old_processing = SSchemistry.processing.Copy()
- for(var/datum/D in old_processing)
- if(CHECK_BITFIELD(D.datum_flags, DF_ISPROCESSING))
- processing |= D
-
- chemical_reactions = SSchemistry.chemical_reactions
- chemical_reagents = SSchemistry.chemical_reagents
-
-/datum/controller/subsystem/processing/chemistry/Initialize()
- initialize_chemical_reactions()
- initialize_chemical_reagents()
- ..()
-
-//Chemical Reactions - Initialises all /datum/chemical_reaction into a list
-// It is filtered into multiple lists within a list.
-// For example:
-// chemical_reaction_list["phoron"] is a list of all reactions relating to phoron
-// Note that entries in the list are NOT duplicated. So if a reaction pertains to
-// more than one chemical it will still only appear in only one of the sublists.
-/datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reactions()
- var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction
- chemical_reactions = list()
- chemical_reactions_by_reagent = list()
-
- for(var/path in paths)
- var/datum/chemical_reaction/D = new path
- chemical_reactions += D
- if(D.required_reagents && D.required_reagents.len)
- var/reagent_id = D.required_reagents[1]
- LAZYINITLIST(chemical_reactions_by_reagent[reagent_id])
- chemical_reactions_by_reagent[reagent_id] += D
-
-//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
-/datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reagents()
- var/paths = typesof(/datum/reagent) - /datum/reagent
- chemical_reagents = list()
- for(var/path in paths)
- var/datum/reagent/D = new path()
- if(!D.name)
- continue
- chemical_reagents[D.id] = D
diff --git a/code/modules/blob2/core_chunk.dm b/code/modules/blob2/core_chunk.dm
index 4abc06843e..15db91e89e 100644
--- a/code/modules/blob2/core_chunk.dm
+++ b/code/modules/blob2/core_chunk.dm
@@ -118,19 +118,19 @@
return FALSE
-/datum/chemical_reaction/blob_reconstitution
+/decl/chemical_reaction/instant/blob_reconstitution
name = "Hostile Blob Revival"
id = "blob_revival"
result = null
required_reagents = list("phoron" = 60)
result_amount = 1
-/datum/chemical_reaction/blob_reconstitution/can_happen(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/blob_reconstitution/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, /obj/item/weapon/blobcore_chunk))
return ..()
return FALSE
-/datum/chemical_reaction/blob_reconstitution/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/blob_reconstitution/on_reaction(var/datum/reagents/holder)
var/obj/item/weapon/blobcore_chunk/chunk = holder.my_atom
if(chunk.can_genesis && chunk.regen())
chunk.visible_message("[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!")
@@ -138,14 +138,14 @@
else
chunk.visible_message("[chunk] shifts strangely, but falls still.")
-/datum/chemical_reaction/blob_reconstitution/domination
+/decl/chemical_reaction/instant/blob_reconstitution/domination
name = "Allied Blob Revival"
id = "blob_friend"
result = null
required_reagents = list("hydrophoron" = 40, "peridaxon" = 20, "mutagen" = 20)
result_amount = 1
-/datum/chemical_reaction/blob_reconstitution/domination/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/blob_reconstitution/domination/on_reaction(var/datum/reagents/holder)
var/obj/item/weapon/blobcore_chunk/chunk = holder.my_atom
if(chunk.can_genesis && chunk.regen("neutral"))
chunk.visible_message("[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!")
diff --git a/code/modules/economy/price_list.dm b/code/modules/economy/price_list.dm
index 9e3fb438d8..839148ebaf 100644
--- a/code/modules/economy/price_list.dm
+++ b/code/modules/economy/price_list.dm
@@ -13,7 +13,7 @@
//---Beverages---//
//***************//
-/datum/reagent/var/price_tag = null
+/datum/reagent/var/price_tag = 0
// Juices, soda and similar //
diff --git a/code/modules/food/recipe_dump.dm b/code/modules/food/recipe_dump.dm
index df0e6874aa..63dc510eb9 100644
--- a/code/modules/food/recipe_dump.dm
+++ b/code/modules/food/recipe_dump.dm
@@ -8,13 +8,11 @@
//////////////////////// DRINK
var/list/drink_recipes = list()
- for(var/path in typesof(/datum/chemical_reaction/drinks) - /datum/chemical_reaction/drinks)
- var/datum/chemical_reaction/drinks/CR = new path()
- drink_recipes[path] = list("Result" = CR.name,
+ for(var/decl/chemical_reaction/instant/drinks/CR in SSchemistry.chemical_reactions)
+ drink_recipes[CR.type] = list("Result" = CR.name,
"ResAmt" = CR.result_amount,
"Reagents" = CR.required_reagents,
"Catalysts" = CR.catalysts)
- qdel(CR)
//////////////////////// FOOD
var/list/food_recipes = typesof(/datum/recipe) - /datum/recipe
@@ -43,16 +41,14 @@
qdel(R)
//////////////////////// FOOD+ (basically condiments, tofu, cheese, soysauce, etc)
- for(var/path in typesof(/datum/chemical_reaction/food) - /datum/chemical_reaction/food)
- var/datum/chemical_reaction/food/CR = new path()
- food_recipes[path] = list("Result" = CR.name,
+ for(var/decl/chemical_reaction/instant/food/CR in SSchemistry.chemical_reactions)
+ food_recipes[CR.type] = list("Result" = CR.name,
"ResAmt" = CR.result_amount,
"Reagents" = CR.required_reagents,
"Catalysts" = CR.catalysts,
"Fruit" = list(),
"Ingredients" = list(),
"Image" = null)
- qdel(CR)
//////////////////////// PROCESSING
//Items needs further processing into human-readability.
diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm
index f822dc274b..e3e34474b5 100644
--- a/code/modules/organs/internal/brain.dm
+++ b/code/modules/organs/internal/brain.dm
@@ -272,19 +272,19 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
qdel(src)
return 1
-/datum/chemical_reaction/promethean_brain_revival
+/decl/chemical_reaction/instant/promethean_brain_revival
name = "Promethean Revival"
id = "prom_revival"
result = null
required_reagents = list("phoron" = 40)
result_amount = 1
-/datum/chemical_reaction/promethean_brain_revival/can_happen(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/promethean_brain_revival/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, /obj/item/organ/internal/brain/slime))
return ..()
return FALSE
-/datum/chemical_reaction/promethean_brain_revival/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/promethean_brain_revival/on_reaction(var/datum/reagents/holder)
var/obj/item/organ/internal/brain/slime/brain = holder.my_atom
if(brain.reviveBody())
brain.visible_message("[brain] bubbles, surrounding itself with a rapidly expanding mass of slime!")
diff --git a/code/modules/power/fusion/fuel_assembly/fuel_compressor.dm b/code/modules/power/fusion/fuel_assembly/fuel_compressor.dm
index 91c08513a5..89b11da6c1 100644
--- a/code/modules/power/fusion/fuel_assembly/fuel_compressor.dm
+++ b/code/modules/power/fusion/fuel_assembly/fuel_compressor.dm
@@ -1,3 +1,4 @@
+#define FUSION_ROD_SHEET_AMT 15
/obj/machinery/fusion_fuel_compressor
name = "fuel compressor"
icon = 'icons/obj/machines/power/fusion.dmi'
@@ -53,15 +54,17 @@
if(!mat.is_fusion_fuel)
to_chat(user, "It would be pointless to make a fuel rod out of [mat.use_name].")
return
- if(M.get_amount() < 15)
+ if(M.get_amount() < FUSION_ROD_SHEET_AMT)
to_chat(user, "You need at least 25 [mat.sheet_plural_name] to make a fuel rod.")
return
var/obj/item/weapon/fuel_assembly/F = new(get_turf(src), mat.name)
visible_message("\The [src] compresses the [mat.use_name] into a new fuel assembly.")
- M.use(15)
+ M.use(FUSION_ROD_SHEET_AMT)
user.put_in_hands(F)
else if(do_special_fuel_compression(thing, user))
return
- return ..()
\ No newline at end of file
+ return ..()
+
+#undef FUSION_ROD_SHEET_AMT
\ No newline at end of file
diff --git a/code/modules/power/fusion/fusion_reagents.dm b/code/modules/power/fusion/fusion_reagents.dm
deleted file mode 100644
index 80b1cbb336..0000000000
--- a/code/modules/power/fusion/fusion_reagents.dm
+++ /dev/null
@@ -1,18 +0,0 @@
-//Additional fusion reagents. These likely don't have any other use aside from the RUST, but if you want to make stuff with 'em, be my guest.
-
-/datum/reagent/helium3
- name = "helium-3"
- description = "A colorless, odorless, tasteless and generally inert gas used in fusion reactors. Non-radioactive."
- id = "helium-3"
- reagent_state = GAS
- color = "#808080"
-
-/obj/structure/reagent_dispensers/he3
- name = "fueltank"
- desc = "A fueltank."
- icon = 'icons/obj/objects.dmi'
- icon_state = "weldtank"
- amount_per_transfer_from_this = 10
- New()
- ..()
- reagents.add_reagent("helium-3",1000)
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Logging.dm b/code/modules/reagents/Chemistry-Logging.dm
index cccf37bb6f..4c7b2343ad 100644
--- a/code/modules/reagents/Chemistry-Logging.dm
+++ b/code/modules/reagents/Chemistry-Logging.dm
@@ -1,7 +1,7 @@
/var/list/chemical_reaction_logs = list()
-/proc/log_chemical_reaction(atom/A, datum/chemical_reaction/R, multiplier)
+/proc/log_chemical_reaction(atom/A, decl/chemical_reaction/R, multiplier)
if(!A || !R)
return
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
deleted file mode 100644
index f2f00ac350..0000000000
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ /dev/null
@@ -1,2667 +0,0 @@
-//helper that ensures the reaction rate holds after iterating
-//Ex. REACTION_RATE(0.3) means that 30% of the reagents will react each chemistry tick (~2 seconds by default).
-#define REACTION_RATE(rate) (1.0 - (1.0-rate)**(1.0/PROCESS_REACTION_ITER))
-
-//helper to define reaction rate in terms of half-life
-//Ex.
-//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.
-#define HALF_LIFE(ticks) (ticks? 1.0 - (0.5)**(1.0/(ticks*PROCESS_REACTION_ITER)) : 1.0)
-
-/datum/chemical_reaction
- var/name = null
- var/id = null
- var/result = null
- var/list/required_reagents = list()
- var/list/catalysts = list()
- var/list/inhibitors = list()
- var/result_amount = 0
-
- //how far the reaction proceeds each time it is processed. Used with either REACTION_RATE or HALF_LIFE macros.
- var/reaction_rate = HALF_LIFE(0)
-
- //if less than 1, the reaction will be inhibited if the ratio of products/reagents is too high.
- //0.5 = 50% yield -> reaction will only proceed halfway until products are removed.
- var/yield = 1.0
-
- //If limits on reaction rate would leave less than this amount of any reagent (adjusted by the reaction ratios),
- //the reaction goes to completion. This is to prevent reactions from going on forever with tiny reagent amounts.
- var/min_reaction = 2
-
- var/mix_message = "The solution begins to bubble."
- var/reaction_sound = 'sound/effects/bubbles.ogg'
-
- var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file.
-
-/datum/chemical_reaction/proc/can_happen(var/datum/reagents/holder)
- //check that all the required reagents are present
- if(!holder.has_all_reagents(required_reagents))
- return 0
-
- //check that all the required catalysts are present in the required amount
- if(!holder.has_all_reagents(catalysts))
- return 0
-
- //check that none of the inhibitors are present in the required amount
- if(holder.has_any_reagent(inhibitors))
- return 0
-
- return 1
-
-/datum/chemical_reaction/proc/calc_reaction_progress(var/datum/reagents/holder, var/reaction_limit)
- var/progress = reaction_limit * reaction_rate //simple exponential progression
-
- //calculate yield
- if(1-yield > 0.001) //if yield ratio is big enough just assume it goes to completion
- /*
- Determine the max amount of product by applying the yield condition:
- (max_product/result_amount) / reaction_limit == yield/(1-yield)
-
- We make use of the fact that:
- reaction_limit = (holder.get_reagent_amount(reactant) / required_reagents[reactant]) of the limiting reagent.
- */
- var/yield_ratio = yield/(1-yield)
- var/max_product = yield_ratio * reaction_limit * result_amount //rearrange to obtain max_product
- var/yield_limit = max(0, max_product - holder.get_reagent_amount(result))/result_amount
-
- progress = min(progress, yield_limit) //apply yield limit
-
- //apply min reaction progress - wasn't sure if this should go before or after applying yield
- //I guess people can just have their miniscule reactions go to completion regardless of yield.
- for(var/reactant in required_reagents)
- var/remainder = holder.get_reagent_amount(reactant) - progress*required_reagents[reactant]
- if(remainder <= min_reaction*required_reagents[reactant])
- progress = reaction_limit
- break
-
- return progress
-
-/datum/chemical_reaction/process(var/datum/reagents/holder)
- //determine how far the reaction can proceed
- var/list/reaction_limits = list()
- for(var/reactant in required_reagents)
- reaction_limits += holder.get_reagent_amount(reactant) / required_reagents[reactant]
-
- //determine how far the reaction proceeds
- var/reaction_limit = min(reaction_limits)
- var/progress_limit = calc_reaction_progress(holder, reaction_limit)
-
- var/reaction_progress = min(reaction_limit, progress_limit) //no matter what, the reaction progress cannot exceed the stoichiometric limit.
-
- //need to obtain the new reagent's data before anything is altered
- var/data = send_data(holder, reaction_progress)
-
- //remove the reactants
- for(var/reactant in required_reagents)
- var/amt_used = required_reagents[reactant] * reaction_progress
- 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)
-
- on_reaction(holder, amt_produced)
-
- return reaction_progress
-
-//called when a reaction processes
-/datum/chemical_reaction/proc/on_reaction(var/datum/reagents/holder, var/created_volume)
- 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))
- var/turf/T = get_turf(container)
- var/list/seen = viewers(4, T)
- for(var/mob/M in seen)
- M.show_message("[bicon(container)] [mix_message]", 1)
- 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.
-/datum/chemical_reaction/proc/send_data(var/datum/reagents/holder, var/reaction_limit)
- return null
-
-/* Common reactions */
-
-/datum/chemical_reaction/inaprovaline
- name = "Inaprovaline"
- id = "inaprovaline"
- result = "inaprovaline"
- required_reagents = list("oxygen" = 1, "carbon" = 1, "sugar" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/dylovene
- name = "Dylovene"
- id = "anti_toxin"
- result = "anti_toxin"
- required_reagents = list("silicon" = 1, "potassium" = 1, "nitrogen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/carthatoline
- name = "Carthatoline"
- id = "carthatoline"
- result = "carthatoline"
- required_reagents = list("anti_toxin" = 1, "carbon" = 2, "phoron" = 0.1)
- catalysts = list("phoron" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/paracetamol
- name = "Paracetamol"
- id = "paracetamol"
- result = "paracetamol"
- required_reagents = list("inaprovaline" = 1, "nitrogen" = 1, "water" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/tramadol
- name = "Tramadol"
- id = "tramadol"
- result = "tramadol"
- required_reagents = list("paracetamol" = 1, "ethanol" = 1, "oxygen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/oxycodone
- name = "Oxycodone"
- id = "oxycodone"
- result = "oxycodone"
- required_reagents = list("ethanol" = 1, "tramadol" = 1)
- catalysts = list("phoron" = 5)
- result_amount = 1
-
-/datum/chemical_reaction/sterilizine
- name = "Sterilizine"
- id = "sterilizine"
- result = "sterilizine"
- required_reagents = list("ethanol" = 1, "anti_toxin" = 1, "chlorine" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/silicate
- name = "Silicate"
- id = "silicate"
- result = "silicate"
- required_reagents = list("aluminum" = 1, "silicon" = 1, "oxygen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/mutagen
- name = "Unstable mutagen"
- id = "mutagen"
- result = "mutagen"
- required_reagents = list("radium" = 1, "phosphorus" = 1, "chlorine" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/water
- name = "Water"
- id = "water"
- result = "water"
- required_reagents = list("oxygen" = 1, "hydrogen" = 2)
- result_amount = 1
-
-/datum/chemical_reaction/thermite
- name = "Thermite"
- id = "thermite"
- result = "thermite"
- required_reagents = list("aluminum" = 1, "iron" = 1, "oxygen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/space_drugs
- name = "Space Drugs"
- id = "space_drugs"
- result = "space_drugs"
- required_reagents = list("mercury" = 1, "sugar" = 1, "lithium" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/lube
- name = "Space Lube"
- id = "lube"
- result = "lube"
- required_reagents = list("water" = 1, "silicon" = 1, "oxygen" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/pacid
- name = "Polytrinic acid"
- id = "pacid"
- result = "pacid"
- required_reagents = list("sacid" = 1, "chlorine" = 1, "potassium" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/synaptizine
- name = "Synaptizine"
- id = "synaptizine"
- result = "synaptizine"
- required_reagents = list("sugar" = 1, "lithium" = 1, "water" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/hyronalin
- name = "Hyronalin"
- id = "hyronalin"
- result = "hyronalin"
- required_reagents = list("radium" = 1, "anti_toxin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/arithrazine
- name = "Arithrazine"
- id = "arithrazine"
- result = "arithrazine"
- required_reagents = list("hyronalin" = 1, "hydrogen" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/impedrezene
- name = "Impedrezene"
- id = "impedrezene"
- result = "impedrezene"
- required_reagents = list("mercury" = 1, "oxygen" = 1, "sugar" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/kelotane
- name = "Kelotane"
- id = "kelotane"
- result = "kelotane"
- required_reagents = list("silicon" = 1, "carbon" = 1)
- result_amount = 2
- log_is_important = 1
-
-/datum/chemical_reaction/peridaxon
- name = "Peridaxon"
- id = "peridaxon"
- result = "peridaxon"
- required_reagents = list("bicaridine" = 2, "clonexadone" = 2)
- catalysts = list("phoron" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/osteodaxon
- name = "Osteodaxon"
- id = "osteodaxon"
- result = "osteodaxon"
- required_reagents = list("bicaridine" = 2, "phoron" = 0.1, "carpotoxin" = 1)
- catalysts = list("phoron" = 5)
- inhibitors = list("clonexadone" = 1) // Messes with cryox
- result_amount = 2
-
-/datum/chemical_reaction/respirodaxon
- name = "Respirodaxon"
- id = "respirodaxon"
- result = "respirodaxon"
- required_reagents = list("dexalinp" = 2, "biomass" = 2, "phoron" = 1)
- catalysts = list("phoron" = 5)
- inhibitors = list("dexalin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/gastirodaxon
- name = "Gastirodaxon"
- id = "gastirodaxon"
- result = "gastirodaxon"
- required_reagents = list("carthatoline" = 1, "biomass" = 2, "tungsten" = 2)
- catalysts = list("phoron" = 5)
- inhibitors = list("lithium" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/hepanephrodaxon
- name = "Hepanephrodaxon"
- id = "hepanephrodaxon"
- result = "hepanephrodaxon"
- required_reagents = list("carthatoline" = 2, "biomass" = 2, "lithium" = 1)
- catalysts = list("phoron" = 5)
- inhibitors = list("tungsten" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/cordradaxon
- name = "Cordradaxon"
- id = "cordradaxon"
- result = "cordradaxon"
- required_reagents = list("potassium_chlorophoride" = 1, "biomass" = 2, "bicaridine" = 2)
- catalysts = list("phoron" = 5)
- inhibitors = list("clonexadone" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/virus_food
- name = "Virus Food"
- id = "virusfood"
- result = "virusfood"
- required_reagents = list("water" = 1, "milk" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/leporazine
- name = "Leporazine"
- id = "leporazine"
- result = "leporazine"
- required_reagents = list("silicon" = 1, "copper" = 1)
- catalysts = list("phoron" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/cryptobiolin
- name = "Cryptobiolin"
- id = "cryptobiolin"
- result = "cryptobiolin"
- required_reagents = list("potassium" = 1, "oxygen" = 1, "sugar" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/tricordrazine
- name = "Tricordrazine"
- id = "tricordrazine"
- result = "tricordrazine"
- required_reagents = list("inaprovaline" = 1, "anti_toxin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/alkysine
- name = "Alkysine"
- id = "alkysine"
- result = "alkysine"
- required_reagents = list("chlorine" = 1, "nitrogen" = 1, "anti_toxin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/dexalin
- name = "Dexalin"
- id = "dexalin"
- result = "dexalin"
- required_reagents = list("oxygen" = 2, "phoron" = 0.1)
- catalysts = list("phoron" = 1)
- inhibitors = list("water" = 1) // Messes with cryox
- result_amount = 1
-
-/datum/chemical_reaction/dermaline
- name = "Dermaline"
- id = "dermaline"
- result = "dermaline"
- required_reagents = list("oxygen" = 1, "phosphorus" = 1, "kelotane" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/dexalinp
- name = "Dexalin Plus"
- id = "dexalinp"
- result = "dexalinp"
- required_reagents = list("dexalin" = 1, "carbon" = 1, "iron" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/bicaridine
- name = "Bicaridine"
- id = "bicaridine"
- result = "bicaridine"
- required_reagents = list("inaprovaline" = 1, "carbon" = 1)
- inhibitors = list("sugar" = 1) // Messes up with inaprovaline
- result_amount = 2
-
-/datum/chemical_reaction/myelamine
- name = "Myelamine"
- id = "myelamine"
- result = "myelamine"
- required_reagents = list("bicaridine" = 1, "iron" = 2, "spidertoxin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/hyperzine
- name = "Hyperzine"
- id = "hyperzine"
- result = "hyperzine"
- required_reagents = list("sugar" = 1, "phosphorus" = 1, "sulfur" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/stimm
- name = "Stimm"
- id = "stimm"
- result = "stimm"
- required_reagents = list("left4zed" = 1, "fuel" = 1)
- catalysts = list("fuel" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/ryetalyn
- name = "Ryetalyn"
- id = "ryetalyn"
- result = "ryetalyn"
- required_reagents = list("arithrazine" = 1, "carbon" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/cryoxadone
- name = "Cryoxadone"
- id = "cryoxadone"
- result = "cryoxadone"
- required_reagents = list("dexalin" = 1, "water" = 1, "oxygen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/clonexadone
- name = "Clonexadone"
- id = "clonexadone"
- result = "clonexadone"
- required_reagents = list("cryoxadone" = 1, "sodium" = 1, "phoron" = 0.1)
- catalysts = list("phoron" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/mortiferin
- name = "Mortiferin"
- id = "mortiferin"
- result = "mortiferin"
- required_reagents = list("cryptobiolin" = 1, "clonexadone" = 1, "corophizine" = 1)
- result_amount = 2
- catalysts = list("phoron" = 5)
-
-/datum/chemical_reaction/spaceacillin
- name = "Spaceacillin"
- id = "spaceacillin"
- result = "spaceacillin"
- required_reagents = list("cryptobiolin" = 1, "inaprovaline" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/corophizine
- name = "Corophizine"
- id = "corophizine"
- result = "corophizine"
- required_reagents = list("spaceacillin" = 1, "carbon" = 1, "phoron" = 0.1)
- catalysts = list("phoron" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/immunosuprizine
- name = "Immunosuprizine"
- id = "immunosuprizine"
- result = "immunosuprizine"
- required_reagents = list("corophizine" = 1, "tungsten" = 1, "sacid" = 1)
- catalysts = list("phoron" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/imidazoline
- name = "imidazoline"
- id = "imidazoline"
- result = "imidazoline"
- required_reagents = list("carbon" = 1, "hydrogen" = 1, "anti_toxin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/ethylredoxrazine
- name = "Ethylredoxrazine"
- id = "ethylredoxrazine"
- result = "ethylredoxrazine"
- required_reagents = list("oxygen" = 1, "anti_toxin" = 1, "carbon" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/calciumcarbonate
- name = "Calcium Carbonate"
- id = "calciumcarbonate"
- result = "calciumcarbonate"
- required_reagents = list("oxygen" = 3, "calcium" = 1, "carbon" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/soporific
- name = "Soporific"
- id = "stoxin"
- result = "stoxin"
- required_reagents = list("chloralhydrate" = 1, "sugar" = 4)
- inhibitors = list("phosphorus") // Messes with the smoke
- result_amount = 5
-
-/datum/chemical_reaction/chloralhydrate
- name = "Chloral Hydrate"
- id = "chloralhydrate"
- result = "chloralhydrate"
- required_reagents = list("ethanol" = 1, "chlorine" = 3, "water" = 1)
- result_amount = 1
-
-/datum/chemical_reaction/potassium_chloride
- name = "Potassium Chloride"
- id = "potassium_chloride"
- result = "potassium_chloride"
- required_reagents = list("sodiumchloride" = 1, "potassium" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/potassium_chlorophoride
- name = "Potassium Chlorophoride"
- id = "potassium_chlorophoride"
- result = "potassium_chlorophoride"
- required_reagents = list("potassium_chloride" = 1, "phoron" = 1, "chloralhydrate" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/zombiepowder
- name = "Zombie Powder"
- id = "zombiepowder"
- result = "zombiepowder"
- required_reagents = list("carpotoxin" = 5, "stoxin" = 5, "copper" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/carpotoxin
- name = "Carpotoxin"
- id = "carpotoxin"
- result = "carpotoxin"
- required_reagents = list("spidertoxin" = 2, "biomass" = 1, "sifsap" = 2)
- catalysts = list("sifsap" = 10)
- inhibitors = list("radium" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/mindbreaker
- name = "Mindbreaker Toxin"
- id = "mindbreaker"
- result = "mindbreaker"
- required_reagents = list("silicon" = 1, "hydrogen" = 1, "anti_toxin" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/lipozine
- name = "Lipozine"
- id = "Lipozine"
- result = "lipozine"
- required_reagents = list("sodiumchloride" = 1, "ethanol" = 1, "radium" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/surfactant
- name = "Foam surfactant"
- id = "foam surfactant"
- result = "fluorosurfactant"
- required_reagents = list("fluorine" = 2, "carbon" = 2, "sacid" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/ammonia
- name = "Ammonia"
- id = "ammonia"
- result = "ammonia"
- required_reagents = list("hydrogen" = 3, "nitrogen" = 1)
- inhibitors = list("phoron" = 1) // Messes with lexorin
- result_amount = 3
-
-/datum/chemical_reaction/diethylamine
- name = "Diethylamine"
- id = "diethylamine"
- result = "diethylamine"
- required_reagents = list ("ammonia" = 1, "ethanol" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/left4zed
- name = "Left4Zed"
- id = "left4zed"
- result = "left4zed"
- required_reagents = list ("diethylamine" = 2, "mutagen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/robustharvest
- name = "RobustHarvest"
- id = "robustharvest"
- result = "robustharvest"
- required_reagents = list ("ammonia" = 1, "calcium" = 1, "neurotoxic_protein" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/space_cleaner
- name = "Space cleaner"
- id = "cleaner"
- result = "cleaner"
- required_reagents = list("ammonia" = 1, "water" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/plantbgone
- name = "Plant-B-Gone"
- id = "plantbgone"
- result = "plantbgone"
- required_reagents = list("toxin" = 1, "water" = 4)
- result_amount = 5
-
-/datum/chemical_reaction/foaming_agent
- name = "Foaming Agent"
- id = "foaming_agent"
- result = "foaming_agent"
- required_reagents = list("lithium" = 1, "hydrogen" = 1)
- result_amount = 1
-
-/datum/chemical_reaction/glycerol
- name = "Glycerol"
- id = "glycerol"
- result = "glycerol"
- required_reagents = list("cornoil" = 3, "sacid" = 1)
- result_amount = 1
-
-/datum/chemical_reaction/sodiumchloride
- name = "Sodium Chloride"
- id = "sodiumchloride"
- result = "sodiumchloride"
- required_reagents = list("sodium" = 1, "chlorine" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/condensedcapsaicin
- name = "Condensed Capsaicin"
- id = "condensedcapsaicin"
- result = "condensedcapsaicin"
- required_reagents = list("capsaicin" = 2)
- catalysts = list("phoron" = 5)
- result_amount = 1
-
-/datum/chemical_reaction/coolant
- name = "Coolant"
- id = "coolant"
- result = "coolant"
- required_reagents = list("tungsten" = 1, "oxygen" = 1, "water" = 1)
- result_amount = 3
- log_is_important = 1
-
-/datum/chemical_reaction/rezadone
- name = "Rezadone"
- id = "rezadone"
- result = "rezadone"
- required_reagents = list("carpotoxin" = 1, "cryptobiolin" = 1, "copper" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/lexorin
- name = "Lexorin"
- id = "lexorin"
- result = "lexorin"
- required_reagents = list("phoron" = 1, "hydrogen" = 1, "nitrogen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/methylphenidate
- name = "Methylphenidate"
- id = "methylphenidate"
- result = "methylphenidate"
- required_reagents = list("mindbreaker" = 1, "hydrogen" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/citalopram
- name = "Citalopram"
- id = "citalopram"
- result = "citalopram"
- required_reagents = list("mindbreaker" = 1, "carbon" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/paroxetine
- name = "Paroxetine"
- id = "paroxetine"
- result = "paroxetine"
- required_reagents = list("mindbreaker" = 1, "oxygen" = 1, "inaprovaline" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/neurotoxin
- name = "Neurotoxin"
- id = "neurotoxin"
- result = "neurotoxin"
- required_reagents = list("gargleblaster" = 1, "stoxin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/luminol
- name = "Luminol"
- id = "luminol"
- result = "luminol"
- required_reagents = list("hydrogen" = 2, "carbon" = 2, "ammonia" = 2)
- result_amount = 6
-
-/* Solidification */
-
-/datum/chemical_reaction/solidification
- name = "Solid Iron"
- id = "solidiron"
- result = null
- required_reagents = list("frostoil" = 5, "iron" = REAGENTS_PER_SHEET)
- result_amount = 1
- var/sheet_to_give = /obj/item/stack/material/iron
-
-/datum/chemical_reaction/solidification/on_reaction(var/datum/reagents/holder, var/created_volume)
- new sheet_to_give(get_turf(holder.my_atom), created_volume)
- return
-
-
-/datum/chemical_reaction/solidification/phoron
- name = "Solid Phoron"
- id = "solidphoron"
- required_reagents = list("frostoil" = 5, "phoron" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/phoron
-
-
-/datum/chemical_reaction/solidification/silver
- name = "Solid Silver"
- id = "solidsilver"
- required_reagents = list("frostoil" = 5, "silver" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/silver
-
-
-/datum/chemical_reaction/solidification/gold
- name = "Solid Gold"
- id = "solidgold"
- required_reagents = list("frostoil" = 5, "gold" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/gold
-
-
-/datum/chemical_reaction/solidification/platinum
- name = "Solid Platinum"
- id = "solidplatinum"
- required_reagents = list("frostoil" = 5, "platinum" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/platinum
-
-
-/datum/chemical_reaction/solidification/uranium
- name = "Solid Uranium"
- id = "soliduranium"
- required_reagents = list("frostoil" = 5, "uranium" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/uranium
-
-
-/datum/chemical_reaction/solidification/hydrogen
- name = "Solid Hydrogen"
- id = "solidhydrogen"
- required_reagents = list("frostoil" = 100, "hydrogen" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/mhydrogen
-
-
-// These are from Xenobio.
-/datum/chemical_reaction/solidification/steel
- name = "Solid Steel"
- id = "solidsteel"
- required_reagents = list("frostoil" = 5, "steel" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/steel
-
-
-/datum/chemical_reaction/solidification/plasteel
- name = "Solid Plasteel"
- id = "solidplasteel"
- required_reagents = list("frostoil" = 10, "plasteel" = REAGENTS_PER_SHEET)
- sheet_to_give = /obj/item/stack/material/plasteel
-
-
-/datum/chemical_reaction/plastication
- name = "Plastic"
- id = "solidplastic"
- result = null
- required_reagents = list("pacid" = 1, "plasticide" = 2)
- result_amount = 1
-
-/datum/chemical_reaction/plastication/on_reaction(var/datum/reagents/holder, var/created_volume)
- new /obj/item/stack/material/plastic(get_turf(holder.my_atom), created_volume)
- return
-
-/* Grenade reactions */
-
-/datum/chemical_reaction/explosion_potassium
- name = "Explosion"
- id = "explosion_potassium"
- result = null
- required_reagents = list("water" = 1, "potassium" = 1)
- result_amount = 2
- mix_message = null
-
-/datum/chemical_reaction/explosion_potassium/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/datum/effect/effect/system/reagents_explosion/e = new()
- e.set_up(round (created_volume/10, 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
-
-/datum/chemical_reaction/flash_powder
- name = "Flash powder"
- id = "flash_powder"
- result = null
- required_reagents = list("aluminum" = 1, "potassium" = 1, "sulfur" = 1 )
- result_amount = null
-
-/datum/chemical_reaction/flash_powder/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(2, 1, location)
- s.start()
- for(var/mob/living/carbon/M in viewers(world.view, location))
- switch(get_dist(M, location))
- if(0 to 3)
- if(hasvar(M, "glasses"))
- if(istype(M:glasses, /obj/item/clothing/glasses/sunglasses))
- continue
-
- M.flash_eyes()
- M.Weaken(15)
-
- if(4 to 5)
- if(hasvar(M, "glasses"))
- if(istype(M:glasses, /obj/item/clothing/glasses/sunglasses))
- continue
-
- M.flash_eyes()
- M.Stun(5)
-
-/datum/chemical_reaction/emp_pulse
- name = "EMP Pulse"
- id = "emp_pulse"
- result = null
- required_reagents = list("uranium" = 1, "iron" = 1) // Yes, laugh, it's the best recipe I could think of that makes a little bit of sense
- result_amount = 2
-
-/datum/chemical_reaction/emp_pulse/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- // 100 created volume = 4 heavy range & 7 light range. A few tiles smaller than traitor EMP grandes.
- // 200 created volume = 8 heavy range & 14 light range. 4 tiles larger than traitor EMP grenades.
- empulse(location, round(created_volume / 24), round(created_volume / 20), round(created_volume / 18), round(created_volume / 14), 1)
- holder.clear_reagents()
- return
-
-/datum/chemical_reaction/nitroglycerin
- name = "Nitroglycerin"
- id = "nitroglycerin"
- result = "nitroglycerin"
- required_reagents = list("glycerol" = 1, "pacid" = 1, "sacid" = 1)
- result_amount = 2
- log_is_important = 1
-
-/datum/chemical_reaction/nitroglycerin/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/datum/effect/effect/system/reagents_explosion/e = new()
- e.set_up(round (created_volume/2, 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
-
-/datum/chemical_reaction/napalm
- name = "Napalm"
- id = "napalm"
- result = null
- required_reagents = list("aluminum" = 1, "phoron" = 1, "sacid" = 1 )
- result_amount = 1
-
-/datum/chemical_reaction/napalm/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/turf/location = get_turf(holder.my_atom.loc)
- for(var/turf/simulated/floor/target_tile in range(0,location))
- target_tile.assume_gas("volatile_fuel", created_volume, 400+T0C)
- spawn (0) target_tile.hotspot_expose(700, 400)
- holder.del_reagent("napalm")
- return
-
-/datum/chemical_reaction/chemsmoke
- name = "Chemsmoke"
- id = "chemsmoke"
- result = null
- required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1)
- result_amount = 0.4
-
-/datum/chemical_reaction/chemsmoke/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem
- S.attach(location)
- S.set_up(holder, created_volume, 0, location)
- playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
- spawn(0)
- S.start()
- holder.clear_reagents()
- return
-
-/datum/chemical_reaction/foam
- name = "Foam"
- id = "foam"
- result = null
- required_reagents = list("fluorosurfactant" = 1, "water" = 1)
- result_amount = 2
- mix_message = "The solution violently bubbles!"
-
-/datum/chemical_reaction/foam/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
-
- for(var/mob/M in viewers(5, location))
- to_chat(M, "The solution spews out foam!")
-
- var/datum/effect/effect/system/foam_spread/s = new()
- s.set_up(created_volume, location, holder, 0)
- s.start()
- holder.clear_reagents()
- return
-
-/datum/chemical_reaction/metalfoam
- name = "Metal Foam"
- id = "metalfoam"
- result = null
- required_reagents = list("aluminum" = 3, "foaming_agent" = 1, "pacid" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/metalfoam/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
-
- for(var/mob/M in viewers(5, location))
- to_chat(M, "The solution spews out a metalic foam!")
-
- var/datum/effect/effect/system/foam_spread/s = new()
- s.set_up(created_volume, location, holder, 1)
- s.start()
- return
-
-/datum/chemical_reaction/ironfoam
- name = "Iron Foam"
- id = "ironlfoam"
- result = null
- required_reagents = list("iron" = 3, "foaming_agent" = 1, "pacid" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/ironfoam/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
-
- for(var/mob/M in viewers(5, location))
- to_chat(M, "The solution spews out a metalic foam!")
-
- var/datum/effect/effect/system/foam_spread/s = new()
- s.set_up(created_volume, location, holder, 2)
- s.start()
- return
-
-/* Paint */
-
-/datum/chemical_reaction/red_paint
- name = "Red paint"
- id = "red_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_red" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/red_paint/send_data()
- return "#FE191A"
-
-/datum/chemical_reaction/orange_paint
- name = "Orange paint"
- id = "orange_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_orange" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/orange_paint/send_data()
- return "#FFBE4F"
-
-/datum/chemical_reaction/yellow_paint
- name = "Yellow paint"
- id = "yellow_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_yellow" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/yellow_paint/send_data()
- return "#FDFE7D"
-
-/datum/chemical_reaction/green_paint
- name = "Green paint"
- id = "green_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_green" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/green_paint/send_data()
- return "#18A31A"
-
-/datum/chemical_reaction/blue_paint
- name = "Blue paint"
- id = "blue_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_blue" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/blue_paint/send_data()
- return "#247CFF"
-
-/datum/chemical_reaction/purple_paint
- name = "Purple paint"
- id = "purple_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_purple" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/purple_paint/send_data()
- return "#CC0099"
-
-/datum/chemical_reaction/grey_paint //mime
- name = "Grey paint"
- id = "grey_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_grey" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/grey_paint/send_data()
- return "#808080"
-
-/datum/chemical_reaction/brown_paint
- name = "Brown paint"
- id = "brown_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_brown" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/brown_paint/send_data()
- return "#846F35"
-
-/datum/chemical_reaction/blood_paint
- name = "Blood paint"
- id = "blood_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "blood" = 2)
- result_amount = 5
-
-/datum/chemical_reaction/blood_paint/send_data(var/datum/reagents/T)
- var/t = T.get_data("blood")
- if(t && t["blood_colour"])
- return t["blood_colour"]
- return "#FE191A" // Probably red
-
-/datum/chemical_reaction/milk_paint
- name = "Milk paint"
- id = "milk_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "milk" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/milk_paint/send_data()
- return "#F0F8FF"
-
-/datum/chemical_reaction/orange_juice_paint
- name = "Orange juice paint"
- id = "orange_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "orangejuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/orange_juice_paint/send_data()
- return "#E78108"
-
-/datum/chemical_reaction/tomato_juice_paint
- name = "Tomato juice paint"
- id = "tomato_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "tomatojuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/tomato_juice_paint/send_data()
- return "#731008"
-
-/datum/chemical_reaction/lime_juice_paint
- name = "Lime juice paint"
- id = "lime_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "limejuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/lime_juice_paint/send_data()
- return "#365E30"
-
-/datum/chemical_reaction/carrot_juice_paint
- name = "Carrot juice paint"
- id = "carrot_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "carrotjuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/carrot_juice_paint/send_data()
- return "#973800"
-
-/datum/chemical_reaction/berry_juice_paint
- name = "Berry juice paint"
- id = "berry_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "berryjuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/berry_juice_paint/send_data()
- return "#990066"
-
-/datum/chemical_reaction/grape_juice_paint
- name = "Grape juice paint"
- id = "grape_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "grapejuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/grape_juice_paint/send_data()
- return "#863333"
-
-/datum/chemical_reaction/poisonberry_juice_paint
- name = "Poison berry juice paint"
- id = "poisonberry_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "poisonberryjuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/poisonberry_juice_paint/send_data()
- return "#863353"
-
-/datum/chemical_reaction/watermelon_juice_paint
- name = "Watermelon juice paint"
- id = "watermelon_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "watermelonjuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/watermelon_juice_paint/send_data()
- return "#B83333"
-
-/datum/chemical_reaction/lemon_juice_paint
- name = "Lemon juice paint"
- id = "lemon_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "lemonjuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/lemon_juice_paint/send_data()
- return "#AFAF00"
-
-/datum/chemical_reaction/banana_juice_paint
- name = "Banana juice paint"
- id = "banana_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "banana" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/banana_juice_paint/send_data()
- return "#C3AF00"
-
-/datum/chemical_reaction/potato_juice_paint
- name = "Potato juice paint"
- id = "potato_juice_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "potatojuice" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/potato_juice_paint/send_data()
- return "#302000"
-
-/datum/chemical_reaction/carbon_paint
- name = "Carbon paint"
- id = "carbon_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "carbon" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/carbon_paint/send_data()
- return "#333333"
-
-/datum/chemical_reaction/aluminum_paint
- name = "Aluminum paint"
- id = "aluminum_paint"
- result = "paint"
- required_reagents = list("plasticide" = 1, "water" = 3, "aluminum" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/aluminum_paint/send_data()
- return "#F0F8FF"
-
-/* Food */
-
-/datum/chemical_reaction/food/tofu
- name = "Tofu"
- id = "tofu"
- result = null
- required_reagents = list("soymilk" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 1
-
-/datum/chemical_reaction/food/tofu/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/tofu(location)
- return
-
-/datum/chemical_reaction/food/chocolate_bar
- name = "Chocolate Bar"
- id = "chocolate_bar"
- result = null
- required_reagents = list("soymilk" = 2, "coco" = 2, "sugar" = 2)
- result_amount = 1
-
-/datum/chemical_reaction/food/chocolate_bar/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatebar(location)
- return
-
-/datum/chemical_reaction/food/chocolate_bar2
- name = "Chocolate Bar"
- id = "chocolate_bar"
- result = null
- required_reagents = list("milk" = 2, "coco" = 2, "sugar" = 2)
- result_amount = 1
-
-/datum/chemical_reaction/food/chocolate_bar2/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatebar(location)
- return
-
-/datum/chemical_reaction/drinks/coffee
- name = "Coffee"
- id = "coffee"
- result = "coffee"
- required_reagents = list("water" = 5, "coffeepowder" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/tea
- name = "Black tea"
- id = "tea"
- result = "tea"
- required_reagents = list("water" = 5, "teapowder" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/hot_coco
- name = "Hot Coco"
- id = "hot_coco"
- result = "hot_coco"
- required_reagents = list("water" = 5, "coco" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/food/soysauce
- name = "Soy Sauce"
- id = "soysauce"
- result = "soysauce"
- required_reagents = list("soymilk" = 4, "sacid" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/grapejuice
- name = "Grape Juice"
- id = "grapejuice"
- result = "grapejuice"
- required_reagents = list("water" = 3, "instantgrape" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/orangejuice
- name = "Orange Juice"
- id = "orangejuice"
- result = "orangejuice"
- required_reagents = list("water" = 3, "instantorange" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/watermelonjuice
- name = "Watermelon Juice"
- id = "watermelonjuice"
- result = "watermelonjuice"
- required_reagents = list("water" = 3, "instantwatermelon" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/applejuice
- name = "Apple Juice"
- id = "applejuice"
- result = "applejuice"
- required_reagents = list("water" = 3, "instantapple" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/food/ketchup
- name = "Ketchup"
- id = "ketchup"
- result = "ketchup"
- required_reagents = list("tomatojuice" = 2, "water" = 1, "sugar" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/food/barbecue
- name = "Barbeque Sauce"
- id = "barbecue"
- result = "barbecue"
- required_reagents = list("tomatojuice" = 2, "applejuice" = 1, "sugar" = 1, "spacespice" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/food/peanutbutter
- name = "Peanut Butter"
- id = "peanutbutter"
- result = "peanutbutter"
- required_reagents = list("peanutoil" = 2, "sugar" = 1, "sodiumchloride" = 1)
- catalysts = list("enzyme" = 5)
- result_amount = 3
-
-/datum/chemical_reaction/food/mayonnaise
- name = "mayonnaise"
- id = "mayo"
- result = "mayo"
- required_reagents = list("egg" = 9, "cornoil" = 5, "lemonjuice" = 5, "sodiumchloride" = 1)
- result_amount = 15
-
-/datum/chemical_reaction/food/cheesewheel
- name = "Cheesewheel"
- id = "cheesewheel"
- result = null
- required_reagents = list("milk" = 40)
- catalysts = list("enzyme" = 5)
- result_amount = 1
-
-/datum/chemical_reaction/food/cheesewheel/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel(location)
- return
-
-/datum/chemical_reaction/food/meatball
- name = "Meatball"
- id = "meatball"
- result = null
- required_reagents = list("protein" = 3, "flour" = 5)
- result_amount = 3
-
-/datum/chemical_reaction/food/meatball/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/meatball(location)
- return
-
-/datum/chemical_reaction/food/dough
- name = "Dough"
- id = "dough"
- result = null
- required_reagents = list("egg" = 3, "flour" = 10)
- inhibitors = list("water" = 1, "beer" = 1) //To prevent it messing with batter recipes
- result_amount = 1
-
-/datum/chemical_reaction/food/dough/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/dough(location)
- return
-
-/datum/chemical_reaction/food/syntiflesh
- name = "Syntiflesh"
- id = "syntiflesh"
- result = null
- required_reagents = list("blood" = 5, "clonexadone" = 5)
- result_amount = 1
-
-/datum/chemical_reaction/food/syntiflesh/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh(location)
- return
-
-/datum/chemical_reaction/hot_ramen
- name = "Hot Ramen"
- id = "hot_ramen"
- result = "hot_ramen"
- required_reagents = list("water" = 1, "dry_ramen" = 3)
- result_amount = 3
-
-/datum/chemical_reaction/hell_ramen
- name = "Hell Ramen"
- id = "hell_ramen"
- result = "hell_ramen"
- required_reagents = list("capsaicin" = 1, "hot_ramen" = 6)
- result_amount = 6
-
-/* Alcohol */
-
-/datum/chemical_reaction/drinks/goldschlager
- name = "Goldschlager"
- id = "goldschlager"
- result = "goldschlager"
- required_reagents = list("vodka" = 10, "gold" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/patron
- name = "Patron"
- id = "patron"
- result = "patron"
- required_reagents = list("tequilla" = 10, "silver" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/bilk
- name = "Bilk"
- id = "bilk"
- result = "bilk"
- required_reagents = list("milk" = 1, "beer" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/icetea
- name = "Iced Tea"
- id = "icetea"
- result = "icetea"
- required_reagents = list("ice" = 1, "tea" = 2)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/icecoffee
- name = "Iced Coffee"
- id = "icecoffee"
- result = "icecoffee"
- required_reagents = list("ice" = 1, "coffee" = 2)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/nuka_cola
- name = "Nuclear Cola"
- id = "nuka_cola"
- result = "nuka_cola"
- required_reagents = list("uranium" = 1, "cola" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/moonshine
- name = "Moonshine"
- id = "moonshine"
- result = "moonshine"
- required_reagents = list("nutriment" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/grenadine
- name = "Grenadine Syrup"
- id = "grenadine"
- result = "grenadine"
- required_reagents = list("berryjuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/wine
- name = "Wine"
- id = "wine"
- result = "wine"
- required_reagents = list("grapejuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/pwine
- name = "Poison Wine"
- id = "pwine"
- result = "pwine"
- required_reagents = list("poisonberryjuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/melonliquor
- name = "Melon Liquor"
- id = "melonliquor"
- result = "melonliquor"
- required_reagents = list("watermelonjuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/bluecuracao
- name = "Blue Curacao"
- id = "bluecuracao"
- result = "bluecuracao"
- required_reagents = list("orangejuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/spacebeer
- name = "Space Beer"
- id = "spacebeer"
- result = "beer"
- required_reagents = list("cornoil" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/vodka
- name = "Vodka"
- id = "vodka"
- result = "vodka"
- required_reagents = list("potatojuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/cider
- name = "Cider"
- id = "cider"
- result = "cider"
- required_reagents = list("applejuice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-
-/datum/chemical_reaction/drinks/sake
- name = "Sake"
- id = "sake"
- result = "sake"
- required_reagents = list("rice" = 10)
- catalysts = list("enzyme" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/kahlua
- name = "Kahlua"
- id = "kahlua"
- result = "kahlua"
- required_reagents = list("coffee" = 5, "sugar" = 5)
- catalysts = list("enzyme" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/gin_tonic
- name = "Gin and Tonic"
- id = "gintonic"
- result = "gintonic"
- required_reagents = list("gin" = 2, "tonic" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/cuba_libre
- name = "Cuba Libre"
- id = "cubalibre"
- result = "cubalibre"
- required_reagents = list("rum" = 2, "cola" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/martini
- name = "Classic Martini"
- id = "martini"
- result = "martini"
- required_reagents = list("gin" = 2, "vermouth" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/vodkamartini
- name = "Vodka Martini"
- id = "vodkamartini"
- result = "vodkamartini"
- required_reagents = list("vodka" = 2, "vermouth" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/white_russian
- name = "White Russian"
- id = "whiterussian"
- result = "whiterussian"
- required_reagents = list("blackrussian" = 2, "cream" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/whiskey_cola
- name = "Whiskey Cola"
- id = "whiskeycola"
- result = "whiskeycola"
- required_reagents = list("whiskey" = 2, "cola" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/screwdriver
- name = "Screwdriver"
- id = "screwdrivercocktail"
- result = "screwdrivercocktail"
- required_reagents = list("vodka" = 2, "orangejuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/bloody_mary
- name = "Bloody Mary"
- id = "bloodymary"
- result = "bloodymary"
- required_reagents = list("vodka" = 2, "tomatojuice" = 3, "limejuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/gargle_blaster
- name = "Pan-Galactic Gargle Blaster"
- id = "gargleblaster"
- result = "gargleblaster"
- required_reagents = list("vodka" = 2, "gin" = 1, "whiskey" = 1, "cognac" = 1, "limejuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/brave_bull
- name = "Brave Bull"
- id = "bravebull"
- result = "bravebull"
- required_reagents = list("tequilla" = 2, "kahlua" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/tequilla_sunrise
- name = "Tequilla Sunrise"
- id = "tequillasunrise"
- result = "tequillasunrise"
- required_reagents = list("tequilla" = 2, "orangejuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/phoron_special
- name = "Toxins Special"
- id = "phoronspecial"
- result = "phoronspecial"
- required_reagents = list("rum" = 2, "vermouth" = 2, "phoron" = 2)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/beepsky_smash
- name = "Beepksy Smash"
- id = "beepksysmash"
- result = "beepskysmash"
- required_reagents = list("limejuice" = 1, "whiskey" = 1, "iron" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/doctor_delight
- name = "The Doctor's Delight"
- id = "doctordelight"
- result = "doctorsdelight"
- required_reagents = list("limejuice" = 1, "tomatojuice" = 1, "orangejuice" = 1, "cream" = 2, "tricordrazine" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/irish_cream
- name = "Irish Cream"
- id = "irishcream"
- result = "irishcream"
- required_reagents = list("whiskey" = 2, "cream" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/manly_dorf
- name = "The Manly Dorf"
- id = "manlydorf"
- result = "manlydorf"
- required_reagents = list ("beer" = 1, "ale" = 2)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/hooch
- name = "Hooch"
- id = "hooch"
- result = "hooch"
- required_reagents = list ("sugar" = 1, "ethanol" = 2, "fuel" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/irish_coffee
- name = "Irish Coffee"
- id = "irishcoffee"
- result = "irishcoffee"
- required_reagents = list("irishcream" = 1, "coffee" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/b52
- name = "B-52"
- id = "b52"
- result = "b52"
- required_reagents = list("irishcream" = 1, "kahlua" = 1, "cognac" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/atomicbomb
- name = "Atomic Bomb"
- id = "atomicbomb"
- result = "atomicbomb"
- required_reagents = list("b52" = 10, "uranium" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/margarita
- name = "Margarita"
- id = "margarita"
- result = "margarita"
- required_reagents = list("tequilla" = 2, "limejuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/longislandicedtea
- name = "Long Island Iced Tea"
- id = "longislandicedtea"
- result = "longislandicedtea"
- required_reagents = list("vodka" = 1, "gin" = 1, "tequilla" = 1, "cubalibre" = 3)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/icedtea
- name = "Long Island Iced Tea"
- id = "longislandicedtea"
- result = "longislandicedtea"
- required_reagents = list("vodka" = 1, "gin" = 1, "tequilla" = 1, "cubalibre" = 3)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/threemileisland
- name = "Three Mile Island Iced Tea"
- id = "threemileisland"
- result = "threemileisland"
- required_reagents = list("longislandicedtea" = 10, "uranium" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/whiskeysoda
- name = "Whiskey Soda"
- id = "whiskeysoda"
- result = "whiskeysoda"
- required_reagents = list("whiskey" = 2, "sodawater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/black_russian
- name = "Black Russian"
- id = "blackrussian"
- result = "blackrussian"
- required_reagents = list("vodka" = 2, "kahlua" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/manhattan
- name = "Manhattan"
- id = "manhattan"
- result = "manhattan"
- required_reagents = list("whiskey" = 2, "vermouth" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/manhattan_proj
- name = "Manhattan Project"
- id = "manhattan_proj"
- result = "manhattan_proj"
- required_reagents = list("manhattan" = 10, "uranium" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/vodka_tonic
- name = "Vodka and Tonic"
- id = "vodkatonic"
- result = "vodkatonic"
- required_reagents = list("vodka" = 2, "tonic" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/gin_fizz
- name = "Gin Fizz"
- id = "ginfizz"
- result = "ginfizz"
- required_reagents = list("gin" = 1, "sodawater" = 1, "limejuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/bahama_mama
- name = "Bahama mama"
- id = "bahama_mama"
- result = "bahama_mama"
- required_reagents = list("rum" = 2, "orangejuice" = 2, "limejuice" = 1, "ice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/singulo
- name = "Singulo"
- id = "singulo"
- result = "singulo"
- required_reagents = list("vodka" = 5, "radium" = 1, "wine" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/alliescocktail
- name = "Allies Cocktail"
- id = "alliescocktail"
- result = "alliescocktail"
- required_reagents = list("martini" = 1, "vodka" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/demonsblood
- name = "Demons Blood"
- id = "demonsblood"
- result = "demonsblood"
- required_reagents = list("rum" = 3, "spacemountainwind" = 1, "blood" = 1, "dr_gibb" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/booger
- name = "Booger"
- id = "booger"
- result = "booger"
- required_reagents = list("cream" = 2, "banana" = 1, "rum" = 1, "watermelonjuice" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/antifreeze
- name = "Anti-freeze"
- id = "antifreeze"
- result = "antifreeze"
- required_reagents = list("vodka" = 1, "cream" = 1, "ice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/barefoot
- name = "Barefoot"
- id = "barefoot"
- result = "barefoot"
- required_reagents = list("berryjuice" = 1, "cream" = 1, "vermouth" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/grapesoda
- name = "Grape Soda"
- id = "grapesoda"
- result = "grapesoda"
- required_reagents = list("grapejuice" = 2, "cola" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/sbiten
- name = "Sbiten"
- id = "sbiten"
- result = "sbiten"
- required_reagents = list("vodka" = 10, "capsaicin" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/red_mead
- name = "Red Mead"
- id = "red_mead"
- result = "red_mead"
- required_reagents = list("blood" = 1, "mead" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/mead
- name = "Mead"
- id = "mead"
- result = "mead"
- required_reagents = list("sugar" = 1, "water" = 1)
- catalysts = list("enzyme" = 5)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/iced_beer
- name = "Iced Beer"
- id = "iced_beer"
- result = "iced_beer"
- required_reagents = list("beer" = 10, "frostoil" = 1)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/iced_beer2
- name = "Iced Beer"
- id = "iced_beer"
- result = "iced_beer"
- required_reagents = list("beer" = 5, "ice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/grog
- name = "Grog"
- id = "grog"
- result = "grog"
- required_reagents = list("rum" = 1, "water" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/soy_latte
- name = "Soy Latte"
- id = "soy_latte"
- result = "soy_latte"
- required_reagents = list("coffee" = 1, "soymilk" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/cafe_latte
- name = "Cafe Latte"
- id = "cafe_latte"
- result = "cafe_latte"
- required_reagents = list("coffee" = 1, "milk" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/acidspit
- name = "Acid Spit"
- id = "acidspit"
- result = "acidspit"
- required_reagents = list("sacid" = 1, "wine" = 5)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/amasec
- name = "Amasec"
- id = "amasec"
- result = "amasec"
- required_reagents = list("iron" = 1, "wine" = 5, "vodka" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/changelingsting
- name = "Changeling Sting"
- id = "changelingsting"
- result = "changelingsting"
- required_reagents = list("screwdrivercocktail" = 1, "limejuice" = 1, "lemonjuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/aloe
- name = "Aloe"
- id = "aloe"
- result = "aloe"
- required_reagents = list("cream" = 1, "whiskey" = 1, "watermelonjuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/andalusia
- name = "Andalusia"
- id = "andalusia"
- result = "andalusia"
- required_reagents = list("rum" = 1, "whiskey" = 1, "lemonjuice" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/snowwhite
- name = "Snow White"
- id = "snowwhite"
- result = "snowwhite"
- required_reagents = list("beer" = 1, "lemon_lime" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/irishcarbomb
- name = "Irish Car Bomb"
- id = "irishcarbomb"
- result = "irishcarbomb"
- required_reagents = list("ale" = 1, "irishcream" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/syndicatebomb
- name = "Syndicate Bomb"
- id = "syndicatebomb"
- result = "syndicatebomb"
- required_reagents = list("beer" = 1, "whiskeycola" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/erikasurprise
- name = "Erika Surprise"
- id = "erikasurprise"
- result = "erikasurprise"
- required_reagents = list("ale" = 2, "limejuice" = 1, "whiskey" = 1, "banana" = 1, "ice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/devilskiss
- name = "Devils Kiss"
- id = "devilskiss"
- result = "devilskiss"
- required_reagents = list("blood" = 1, "kahlua" = 1, "rum" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/hippiesdelight
- name = "Hippies Delight"
- id = "hippiesdelight"
- result = "hippiesdelight"
- required_reagents = list("psilocybin" = 1, "gargleblaster" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/bananahonk
- name = "Banana Honk"
- id = "bananahonk"
- result = "bananahonk"
- required_reagents = list("banana" = 1, "cream" = 1, "sugar" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/silencer
- name = "Silencer"
- id = "silencer"
- result = "silencer"
- required_reagents = list("nothing" = 1, "cream" = 1, "sugar" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/driestmartini
- name = "Driest Martini"
- id = "driestmartini"
- result = "driestmartini"
- required_reagents = list("nothing" = 1, "gin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/lemonade
- name = "Lemonade"
- id = "lemonade"
- result = "lemonade"
- required_reagents = list("lemonjuice" = 1, "sugar" = 1, "water" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/melonade
- name = "Melonade"
- id = "melonade"
- result = "melonade"
- required_reagents = list("watermelonjuice" = 1, "sugar" = 1, "sodawater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/appleade
- name = "Appleade"
- id = "appleade"
- result = "appleade"
- required_reagents = list("applejuice" = 1, "sugar" = 1, "sodawater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/pineappleade
- name = "Pineappleade"
- id = "pineappleade"
- result = "pineappleade"
- required_reagents = list("pineapplejuice" = 2, "limejuice" = 1, "sodawater" = 2, "honey" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/driverspunch
- name = "Driver`s Punch"
- id = "driverspunch"
- result = "driverspunch"
- required_reagents = list("appleade" = 2, "orangejuice" = 1, "mint" = 1, "sodawater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/mintapplesparkle
- name = "Mint Apple Sparkle"
- id = "mintapplesparkle"
- result = "mintapplesparkle"
- required_reagents = list("appleade" = 2, "mint" = 1)
- inhibitors = list("sodawater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/berrycordial
- name = "Berry Cordial"
- id = "berrycordial"
- result = "berrycordial"
- required_reagents = list("berryjuice" = 4, "sugar" = 1, "lemonjuice" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/tropicalfizz
- name = "Tropical Fizz"
- id = "tropicalfizz"
- result = "tropicalfizz"
- required_reagents = list("sodawater" = 6, "berryjuice" = 1, "mint" = 1, "limejuice" = 1, "lemonjuice" = 1, "pineapplejuice" = 1)
- inhibitors = list("sugar" = 1)
- result_amount = 8
-
-/datum/chemical_reaction/drinks/melonspritzer
- name = "Melon Spritzer"
- id = "melonspritzer"
- result = "melonspritzer"
- required_reagents = list("watermelonjuice" = 2, "wine" = 2, "applejuice" = 1, "limejuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/fauxfizz
- name = "Faux Fizz"
- id = "fauxfizz"
- result = "fauxfizz"
- required_reagents = list("sodawater" = 2, "berryjuice" = 1, "applejuice" = 1, "limejuice" = 1, "honey" = 1)
- inhibitors = list("sugar" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/firepunch
- name = "Fire Punch"
- id = "firepunch"
- result = "firepunch"
- required_reagents = list("sugar" = 1, "rum" = 2)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/kiraspecial
- name = "Kira Special"
- id = "kiraspecial"
- result = "kiraspecial"
- required_reagents = list("orangejuice" = 1, "limejuice" = 1, "sodawater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/brownstar
- name = "Brown Star"
- id = "brownstar"
- result = "brownstar"
- required_reagents = list("orangejuice" = 2, "cola" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/milkshake
- name = "Milkshake"
- id = "milkshake"
- result = "milkshake"
- required_reagents = list("cream" = 1, "ice" = 2, "milk" = 2)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/peanutmilkshake
- name = "Peanutbutter Milkshake"
- id = "peanutmilkshake"
- result = "peanutmilkshake"
- required_reagents = list("cream" = 1, "ice" = 1, "peanutbutter" = 2, "milk" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/rewriter
- name = "Rewriter"
- id = "rewriter"
- result = "rewriter"
- required_reagents = list("spacemountainwind" = 1, "coffee" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/suidream
- name = "Sui Dream"
- id = "suidream"
- result = "suidream"
- required_reagents = list("space_up" = 1, "bluecuracao" = 1, "melonliquor" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/shirleytemple
- name = "Shirley Temple"
- id = "shirley_temple"
- result = "shirley_temple"
- required_reagents = list("gingerale" = 4, "grenadine" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/royrogers
- name = "Roy Rogers"
- id = "roy_rogers"
- result = "roy_rogers"
- required_reagents = list("shirley_temple" = 5, "lemon_lime" = 2)
- result_amount = 7
-
-/datum/chemical_reaction/drinks/collinsmix
- name = "Collins Mix"
- id = "collins_mix"
- result = "collins_mix"
- required_reagents = list("lemon_lime" = 3, "sodawater" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/arnoldpalmer
- name = "Arnold Palmer"
- id = "arnold_palmer"
- result = "arnold_palmer"
- required_reagents = list("icetea" = 1, "lemonade" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/minttea
- name = "Mint Tea"
- id = "minttea"
- result = "minttea"
- required_reagents = list("tea" = 5, "mint" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/lemontea
- name = "Lemon Tea"
- id = "lemontea"
- result = "lemontea"
- required_reagents = list("tea" = 5, "lemonjuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/limetea
- name = "Lime Tea"
- id = "limetea"
- result = "limetea"
- required_reagents = list("tea" = 5, "limejuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/orangetea
- name = "Orange Tea"
- id = "orangetea"
- result = "orangetea"
- required_reagents = list("tea" = 5, "orangejuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/berrytea
- name = "Berry Tea"
- id = "berrytea"
- result = "berrytea"
- required_reagents = list("tea" = 5, "berryjuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/sakebomb
- name = "Sake Bomb"
- id = "sakebomb"
- result = "sakebomb"
- required_reagents = list("beer" = 2, "sake" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/tamagozake
- name = "Tamagozake"
- id = "tamagozake"
- result = "tamagozake"
- required_reagents = list("sake" = 10, "sugar" = 5, "egg" = 3)
- result_amount = 15
-
-/datum/chemical_reaction/drinks/ginzamary
- name = "Ginza Mary"
- id = "ginzamary"
- result = "ginzamary"
- required_reagents = list("sake" = 2, "vodka" = 2, "tomatojuice" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/tokyorose
- name = "Tokyo Rose"
- id = "tokyorose"
- result = "tokyorose"
- required_reagents = list("sake" = 1, "berryjuice" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/saketini
- name = "Saketini"
- id = "saketini"
- result = "saketini"
- required_reagents = list("sake" = 1, "gin" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/elysiumfacepunch
- name = "Elysium Facepunch"
- id = "elysiumfacepunch"
- result = "elysiumfacepunch"
- required_reagents = list("kahlua" = 1, "lemonjuice" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/erebusmoonrise
- name = "Erebus Moonrise"
- id = "erebusmoonrise"
- result = "erebusmoonrise"
- required_reagents = list("whiskey" = 1, "vodka" = 1, "tequilla" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/balloon
- name = "Balloon"
- id = "balloon"
- result = "balloon"
- required_reagents = list("cream" = 1, "bluecuracao" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/natunabrandy
- name = "Natuna Brandy"
- id = "natunabrandy"
- result = "natunabrandy"
- required_reagents = list("beer" = 1, "sodawater" = 2)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/euphoria
- name = "Euphoria"
- id = "euphoria"
- result = "euphoria"
- required_reagents = list("specialwhiskey" = 1, "cognac" = 2)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/xanaducannon
- name = "Xanadu Cannon"
- id = "xanaducannon"
- result = "xanaducannon"
- required_reagents = list("ale" = 1, "dr_gibb" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/debugger
- name = "Debugger"
- id = "debugger"
- result = "debugger"
- required_reagents = list("fuel" = 1, "sugar" = 2, "cornoil" = 2)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/spacersbrew
- name = "Spacer's Brew"
- id = "spacersbrew"
- result = "spacersbrew"
- required_reagents = list("brownstar" = 4, "ethanol" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/binmanbliss
- name = "Binman Bliss"
- id = "binmanbliss"
- result = "binmanbliss"
- required_reagents = list("sake" = 1, "tequilla" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/chrysanthemum
- name = "Chrysanthemum"
- id = "chrysanthemum"
- result = "chrysanthemum"
- required_reagents = list("sake" = 1, "melonliquor" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/deathbell
- name = "Deathbell"
- id = "deathbell"
- result = "deathbell"
- required_reagents = list("antifreeze" = 1, "gargleblaster" = 1, "syndicatebomb" =1)
- result_amount = 3
-
-/datum/chemical_reaction/bitters
- name = "Bitters"
- id = "bitters"
- result = "bitters"
- required_reagents = list("mint" = 5)
- catalysts = list("enzyme" = 5)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/soemmerfire
- name = "Soemmer Fire"
- id = "soemmerfire"
- result = "soemmerfire"
- required_reagents = list("manhattan" = 2, "condensedcapsaicin" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/winebrandy
- name = "Wine brandy"
- id = "winebrandy"
- result = "winebrandy"
- required_reagents = list("wine" = 10)
- catalysts = list("enzyme" = 10) //10u enzyme so it requires more than is usually added. Stops overlap with wine recipe
- result_amount = 5
-
-/datum/chemical_reaction/drinks/lovepotion
- name = "Love Potion"
- id = "lovepotion"
- result = "lovepotion"
- required_reagents = list("cream" = 1, "berryjuice" = 1, "sugar" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/morningafter
- name = "Morning After"
- id = "morningafter"
- result = "morningafter"
- required_reagents = list("sbiten" = 1, "coffee" = 5)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/vesper
- name = "Vesper"
- id = "vesper"
- result = "vesper"
- required_reagents = list("gin" = 3, "vodka" = 1, "wine" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/rotgut
- name = "Rotgut Fever Dream"
- id = "rotgut"
- result = "rotgut"
- required_reagents = list("vodka" = 3, "rum" = 1, "whiskey" = 1, "cola" = 3)
- result_amount = 8
-
-/datum/chemical_reaction/drinks/entdraught
- name = "Ent's Draught"
- id = "entdraught"
- result = "entdraught"
- required_reagents = list("tonic" = 1, "holywater" = 1, "honey" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/voxdelight
- name = "Vox's Delight"
- id = "voxdelight"
- result = "voxdelight"
- required_reagents = list("phoron" = 3, "fuel" = 1, "water" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/screamingviking
- name = "Screaming Viking"
- id = "screamingviking"
- result = "screamingviking"
- required_reagents = list("martini" = 2, "vodkatonic" = 2, "limejuice" = 1, "rum" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/vilelemon
- name = "Vile Lemon"
- id = "vilelemon"
- result = "vilelemon"
- required_reagents = list("lemonade" = 5, "spacemountainwind" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/dreamcream
- name = "Dream Cream"
- id = "dreamcream"
- result = "dreamcream"
- required_reagents = list("milk" = 2, "cream" = 1, "honey" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/robustin
- name = "Robustin"
- id = "robustin"
- result = "robustin"
- required_reagents = list("antifreeze" = 1, "phoron" = 1, "fuel" = 1, "vodka" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/virginsip
- name = "Virgin Sip"
- id = "virginsip"
- result = "virginsip"
- required_reagents = list("driestmartini" = 1, "water" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/chocoshake
- name = "Chocolate Milkshake"
- id = "chocoshake"
- result = "chocoshake"
- required_reagents = list("milkshake" = 1, "coco" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/berryshake
- name = "Berry Milkshake"
- id = "berryshake"
- result = "berryshake"
- required_reagents = list("milkshake" = 1, "berryjuice" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/coffeeshake
- name = "Coffee Milkshake"
- id = "coffeeshake"
- result = "coffeeshake"
- required_reagents = list("milkshake" = 1, "coffee" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/jellyshot
- name = "Jelly Shot"
- id = "jellyshot"
- result = "jellyshot"
- required_reagents = list("cherryjelly" = 4, "vodka" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/slimeshot
- name = "Named Bullet"
- id = "slimeshot"
- result = "slimeshot"
- required_reagents = list("slimejelly" = 4, "vodka" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/negroni
- name = "Negroni"
- id = "negroni"
- result = "negroni"
- required_reagents = list("gin" = 1, "bitters" = 1, "vermouth" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/cloverclub
- name = "Clover Club"
- id = "cloverclub"
- result = "cloverclub"
- required_reagents = list("berryjuice" = 1, "lemonjuice" = 1, "gin" = 3)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/oldfashioned
- name = "Old Fashioned"
- id = "oldfashioned"
- result = "oldfashioned"
- required_reagents = list("whiskey" = 3, "bitters" = 1, "sugar" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/whiskeysour
- name = "Whiskey Sour"
- id = "whiskeysour"
- result = "whiskeysour"
- required_reagents = list("whiskey" = 2, "lemonjuice" = 1, "sugar" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/daiquiri
- name = "Daiquiri"
- id = "daiquiri"
- result = "daiquiri"
- required_reagents = list("rum" = 3, "limejuice" = 2, "sugar" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/mintjulep
- name = "Mint Julep"
- id = "mintjulep"
- result = "mintjulep"
- required_reagents = list("whiskey" = 2, "water" = 1, "mint" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/drinks/paloma
- name = "Paloma"
- id = "paloma"
- result = "paloma"
- required_reagents = list("orangejuice" = 1, "sodawater" = 1, "tequilla" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/mojito
- name = "Mojito"
- id = "mojito"
- result = "mojito"
- required_reagents = list("rum" = 3, "limejuice" = 1, "mint" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/virginmojito
- name = "Mojito"
- id = "virginmojito"
- result = "virginmojito"
- required_reagents = list("sodawater" = 3, "limejuice" = 1, "mint" = 1, "sugar" = 1)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/piscosour
- name = "Pisco Sour"
- id = "piscosour"
- result = "piscosour"
- required_reagents = list("winebrandy" = 1, "lemonjuice" = 1, "sugar" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/coldfront
- name = "Cold Front"
- id = "coldfront"
- result = "coldfront"
- required_reagents = list("icecoffee" = 1, "whiskey" = 1, "mint" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/godsake
- name = "Gods Sake"
- id = "godsake"
- result = "godsake"
- required_reagents = list("sake" = 2, "holywater" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/godka //Why you would put this in your body, I don't know.
- name = "Godka"
- id = "godka"
- result = "godka"
- required_reagents = list("vodka" = 1, "holywater" = 1, "ethanol" = 1, "carthatoline" = 1)
- catalysts = list("enzyme" = 5, "holywater" = 5)
- result_amount = 1
-
-/datum/chemical_reaction/drinks/holywine
- name = "Angel Ichor"
- id = "holywine"
- result = "holywine"
- required_reagents = list("grapejuice" = 5, "gold" = 5)
- catalysts = list("holywater" = 5)
- result_amount = 10
-
-/datum/chemical_reaction/drinks/holy_mary
- name = "Holy Mary"
- id = "holymary"
- result = "holymary"
- required_reagents = list("vodka" = 2, "holywine" = 3, "limejuice" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/angelskiss
- name = "Angels Kiss"
- id = "angelskiss"
- result = "angelskiss"
- required_reagents = list("holywine" = 1, "kahlua" = 1, "rum" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/angelswrath
- name = "Angels Wrath"
- id = "angelswrath"
- result = "angelswrath"
- required_reagents = list("rum" = 3, "spacemountainwind" = 1, "holywine" = 1, "dr_gibb" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/ichor_mead
- name = "Ichor Mead"
- id = "ichor_mead"
- result = "ichor_mead"
- required_reagents = list("holywine" = 1, "mead" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/oilslick
- name = "Oil Slick"
- id = "oilslick"
- result = "oilslick"
- required_reagents = list("cornoil" = 2, "honey" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/slimeslam
- name = "Slick Slime Slammer"
- id = "slimeslammer"
- result = "slimeslammer"
- required_reagents = list("cornoil" = 2, "peanutbutter" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/virginsexonthebeach
- name = "Virgin Sex On The Beach"
- id = "virginsexonthebeach"
- result = "virginsexonthebeach"
- required_reagents = list("orangejuice" = 3, "grenadine" = 2)
- result_amount = 5
-
-/datum/chemical_reaction/drinks/sexonthebeach
- name = "Sex On The Beach"
- id = "sexonthebeach"
- result = "sexonthebeach"
- required_reagents = list("virginsexonthebeach" = 5, "vodka" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/eggnog
- name = "Eggnog"
- id = "eggnog"
- result = "eggnog"
- required_reagents = list("milk" = 5, "cream" = 5, "sugar" = 5, "egg" = 3)
- result_amount = 15
-
-/datum/chemical_reaction/drinks/nuclearwaste_radium
- name = "Nuclear Waste"
- id = "nuclearwasterad"
- result = "nuclearwaste"
- required_reagents = list("oilslick" = 1, "radium" = 1, "limejuice" = 1)
- result_amount = 2
-
-/datum/chemical_reaction/drinks/nuclearwaste_uranium
- name = "Nuclear Waste"
- id = "nuclearwasteuran"
- result = "nuclearwaste"
- required_reagents = list("oilslick" = 2, "uranium" = 1)
- result_amount = 3
-
-/datum/chemical_reaction/drinks/sodaoil
- name = "Soda Oil"
- id = "sodaoil"
- result = "sodaoil"
- required_reagents = list("cornoil" = 4, "sodawater" = 1, "carbon" = 1, "tricordrazine" = 1)
- result_amount = 6
-
-/datum/chemical_reaction/drinks/fusionnaire
- name = "Fusionnaire"
- id = "fusionnaire"
- result = "fusionnaire"
- required_reagents = list("lemonjuice" = 3, "vodka" = 2, "schnapps_pep" = 1, "schnapps_lem" = 1, "rum" = 1, "ice" = 1)
- result_amount = 9
-
-//R-UST Port
-/datum/chemical_reaction/hyrdophoron
- name = "Hydrophoron"
- id = "hydrophoron"
- result = "hydrophoron"
- required_reagents = list("hydrogen" = 1, "phoron" = 1)
- inhibitors = list("nitrogen" = 1) //So it doesn't mess with lexorin
- result_amount = 2
-
-/datum/chemical_reaction/deuterium
- name = "Deuterium"
- id = "deuterium"
- result = null
- required_reagents = list("hydrophoron" = 5, "water" = 10)
- result_amount = 15
-
-/datum/chemical_reaction/deuterium/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/turf/T = get_turf(holder.my_atom)
- if(istype(T)) new /obj/item/stack/material/deuterium(T, created_volume)
- return
-
-//Skrellian crap.
-/datum/chemical_reaction/talum_quem
- name = "Talum-quem"
- id = "talum_quem"
- result = "talum_quem"
- required_reagents = list("space_drugs" = 2, "sugar" = 1, "amatoxin" = 1)
- result_amount = 4
-
-/datum/chemical_reaction/qerr_quem
- name = "Qerr-quem"
- id = "qerr_quem"
- result = "qerr_quem"
- required_reagents = list("nicotine" = 1, "carbon" = 1, "sugar" = 2)
- result_amount = 4
-
-/datum/chemical_reaction/malish_qualem
- name = "Malish-Qualem"
- id = "malish-qualem"
- result = "malish-qualem"
- required_reagents = list("immunosuprizine" = 1, "qerr_quem" = 1, "inaprovaline" = 1)
- catalysts = list("phoron" = 5)
- result_amount = 2
-
-// Biomass, for cloning and bioprinters
-/datum/chemical_reaction/biomass
- name = "Biomass"
- id = "biomass"
- result = "biomass"
- required_reagents = list("protein" = 1, "sugar" = 1, "phoron" = 1)
- result_amount = 1 // Roughly 20u per phoron sheet
-
-// Neutralization.
-
-/datum/chemical_reaction/neutralize_neurotoxic_protein
- name = "Neutralize Toxic Proteins"
- id = "neurotoxic_protein_neutral"
- result = "protein"
- required_reagents = list("anti_toxin" = 1, "neurotoxic_protein" = 2)
- result_amount = 2
-
-/datum/chemical_reaction/neutralize_carpotoxin
- name = "Neutralize Carpotoxin"
- id = "carpotoxin_neutral"
- result = "protein"
- required_reagents = list("radium" = 1, "carpotoxin" = 1, "sifsap" = 1)
- catalysts = list("sifsap" = 10)
- result_amount = 2
-
-/datum/chemical_reaction/neutralize_spidertoxin
- name = "Neutralize Spidertoxin"
- id = "spidertoxin_neutral"
- result = "protein"
- required_reagents = list("radium" = 1, "spidertoxin" = 1, "sifsap" = 1)
- catalysts = list("sifsap" = 10)
- result_amount = 2
-
-/*
-====================
- Aurora Food
-====================
-*/
-
-/datum/chemical_reaction/coating/batter
- name = "Batter"
- id = "batter"
- result = "batter"
- required_reagents = list("egg" = 3, "flour" = 10, "water" = 5, "sodiumchloride" = 2)
- result_amount = 20
-
-/datum/chemical_reaction/coating/beerbatter
- name = "Beer Batter"
- id = "beerbatter"
- result = "beerbatter"
- required_reagents = list("egg" = 3, "flour" = 10, "beer" = 5, "sodiumchloride" = 2)
- result_amount = 20
-
-/datum/chemical_reaction/browniemix
- name = "Brownie Mix"
- id = "browniemix"
- result = "browniemix"
- required_reagents = list("flour" = 5, "coco" = 5, "sugar" = 5)
- result_amount = 15
-
-/datum/chemical_reaction/butter
- name = "Butter"
- id = "butter"
- result = null
- required_reagents = list("cream" = 20, "sodiumchloride" = 1)
- result_amount = 1
-
-/datum/chemical_reaction/butter/on_reaction(var/datum/reagents/holder, var/created_volume)
- var/location = get_turf(holder.my_atom)
- for(var/i = 1, i <= created_volume, i++)
- new /obj/item/weapon/reagent_containers/food/snacks/spreads/butter(location)
- return
-
-/datum/chemical_reaction/browniemix
- name = "Brownie Mix"
- id = "browniemix"
- result = "browniemix"
- required_reagents = list("flour" = 5, "coco" = 5, "sugar" = 5)
- result_amount = 15
diff --git a/code/modules/reagents/holder/distilling.dm b/code/modules/reagents/holder/distilling.dm
new file mode 100644
index 0000000000..1599f395d9
--- /dev/null
+++ b/code/modules/reagents/holder/distilling.dm
@@ -0,0 +1,26 @@
+/datum/reagents/distilling/handle_reactions()
+ if(QDELETED(my_atom))
+ return FALSE
+ if(my_atom.flags & NOREACT)
+ return FALSE
+ var/reaction_occurred
+ var/list/eligible_reactions = list()
+ var/list/effect_reactions = list()
+ do
+ reaction_occurred = FALSE
+ for(var/i in reagent_list)
+ var/datum/reagent/R = i
+ if(SSchemistry.distilled_reactions_by_reagent[R.id])
+ eligible_reactions |= SSchemistry.distilled_reactions_by_reagent[R.id]
+
+ for(var/i in eligible_reactions)
+ var/decl/chemical_reaction/C = i
+ if(C.can_happen(src) && C.process(src))
+ effect_reactions |= C
+ reaction_occurred = TRUE
+ eligible_reactions.len = 0
+ while(reaction_occurred)
+ for(var/i in effect_reactions)
+ var/decl/chemical_reaction/C = i
+ C.post_reaction(src)
+ update_total()
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/holder/holder.dm
similarity index 94%
rename from code/modules/reagents/Chemistry-Holder.dm
rename to code/modules/reagents/holder/holder.dm
index aa50a4b79f..923ffb6bc9 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/holder/holder.dm
@@ -1,518 +1,519 @@
-#define PROCESS_REACTION_ITER 5 //when processing a reaction, iterate this many times
-
-/datum/reagents
- var/list/datum/reagent/reagent_list = list()
- var/total_volume = 0
- var/maximum_volume = 100
- var/atom/my_atom = null
-
-/datum/reagents/New(var/max = 100, atom/A = null)
- ..()
- maximum_volume = max
- my_atom = A
-
- //I dislike having these here but map-objects are initialised before world/New() is called. >_>
- if(!SSchemistry.chemical_reagents)
- //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
- var/paths = typesof(/datum/reagent) - /datum/reagent
- SSchemistry.chemical_reagents = list()
- for(var/path in paths)
- var/datum/reagent/D = new path()
- if(!D.name)
- continue
- SSchemistry.chemical_reagents[D.id] = D
-
-/datum/reagents/Destroy()
- STOP_PROCESSING(SSchemistry, src)
- for(var/datum/reagent/R in reagent_list)
- qdel(R)
- reagent_list = null
- if(my_atom && my_atom.reagents == src)
- my_atom.reagents = null
- return ..()
-
-/* Internal procs */
-
-/datum/reagents/proc/get_free_space() // Returns free space.
- return maximum_volume - total_volume
-
-/datum/reagents/proc/get_master_reagent() // Returns reference to the reagent with the biggest volume.
- var/the_reagent = null
- var/the_volume = 0
-
- for(var/datum/reagent/A in reagent_list)
- if(A.volume > the_volume)
- the_volume = A.volume
- the_reagent = A
-
- return the_reagent
-
-/datum/reagents/proc/get_master_reagent_name() // Returns the name of the reagent with the biggest volume.
- var/the_name = null
- var/the_volume = 0
- for(var/datum/reagent/A in reagent_list)
- if(A.volume > the_volume)
- the_volume = A.volume
- the_name = A.name
-
- return the_name
-
-/datum/reagents/proc/get_master_reagent_id() // Returns the id of the reagent with the biggest volume.
- var/the_id = null
- var/the_volume = 0
- for(var/datum/reagent/A in reagent_list)
- if(A.volume > the_volume)
- the_volume = A.volume
- the_id = A.id
-
- return the_id
-
-/datum/reagents/proc/update_total() // Updates volume.
- 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
-
-/datum/reagents/proc/handle_reactions()
- if(QDELETED(my_atom))
- return FALSE
- if(my_atom.flags & NOREACT)
- return FALSE
- var/reaction_occurred
- var/list/eligible_reactions = list()
- var/list/effect_reactions = list()
- do
- reaction_occurred = FALSE
- for(var/i in reagent_list)
- var/datum/reagent/R = i
- if(SSchemistry.chemical_reactions_by_reagent[R.id])
- eligible_reactions |= SSchemistry.chemical_reactions_by_reagent[R.id]
-
- for(var/i in eligible_reactions)
- var/datum/chemical_reaction/C = i
- if(C.can_happen(src) && C.process(src))
- effect_reactions |= C
- reaction_occurred = TRUE
- eligible_reactions.len = 0
- while(reaction_occurred)
- for(var/i in effect_reactions)
- var/datum/chemical_reaction/C = i
- C.post_reaction(src)
- update_total()
-
-/* Holder-to-chemical */
-
-/datum/reagents/proc/add_reagent(var/id, var/amount, var/data = null, var/safety = 0)
- if(!isnum(amount) || amount <= 0)
- return 0
-
- update_total()
- amount = min(amount, get_free_space())
-
- if(istype(my_atom,/obj/item/weapon/reagent_containers/food)) //The following code is targeted specifically at getting allergen reagents into food items, since for the most part they're not applied by default.
- var/list/add_reagents = list()
- var/totalnum = 0
-
- for(var/item in data) //Try to find the ID
- var/add_reagent_id = null
- if(item in SSchemistry.chemical_reagents)
- add_reagent_id = item
- else if("[item]juice" in SSchemistry.chemical_reagents)
- add_reagent_id = "[item]juice"
- if(add_reagent_id) //If we did find it, add it to our list of reagents to add, and add the number to our total.
- add_reagents[add_reagent_id] += data[item]
- totalnum += data[item]
-
- if(totalnum)
- var/multconst = amount/totalnum //We're going to add these extra reagents so that they share the ratio described, but only add up to 1x the existing amount at the most
- for(var/item in add_reagents)
- add_reagent(item,add_reagents[item]*multconst)
-
-
-
-
- for(var/datum/reagent/current in reagent_list)
- if(current.id == id)
- if(current.id == "blood")
- if(LAZYLEN(data) && !isnull(data["species"]) && !isnull(current.data["species"]) && data["species"] != current.data["species"]) // Species bloodtypes are already incompatible, this just stops it from mixing into the one already in a container.
- continue
-
- current.volume += 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()
- 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.initialize_data(data)
- update_total()
- if(!safety)
- handle_reactions()
- if(my_atom)
- my_atom.on_reagent_change()
- return 1
- else
- crash_with("[my_atom] attempted to add a reagent called '[id]' which doesn't exist. ([usr])")
- return 0
-
-/datum/reagents/proc/isolate_reagent(reagent)
- for(var/A in reagent_list)
- var/datum/reagent/R = A
- if(R.id != reagent)
- del_reagent(R.id)
- update_total()
-
-/datum/reagents/proc/remove_reagent(var/id, var/amount, var/safety = 0)
- if(!isnum(amount))
- return 0
- for(var/datum/reagent/current in reagent_list)
- if(current.id == id)
- 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()
- return 1
- return 0
-
-/datum/reagents/proc/del_reagent(var/id)
- for(var/datum/reagent/current in reagent_list)
- if (current.id == id)
- reagent_list -= current
- qdel(current)
- update_total()
- if(my_atom)
- my_atom.on_reagent_change()
- return 0
-
-/datum/reagents/proc/has_reagent(var/id, var/amount = 0)
- for(var/datum/reagent/current in reagent_list)
- if(current.id == id)
- if(current.volume >= amount)
- return 1
- else
- return 0
- return 0
-
-/datum/reagents/proc/has_any_reagent(var/list/check_reagents)
- for(var/datum/reagent/current in reagent_list)
- if(current.id in check_reagents)
- if(current.volume >= check_reagents[current.id])
- return 1
- else
- return 0
- return 0
-
-/datum/reagents/proc/has_all_reagents(var/list/check_reagents)
- //this only works if check_reagents has no duplicate entries... hopefully okay since it expects an associative list
- var/missing = check_reagents.len
- for(var/datum/reagent/current in reagent_list)
- if(current.id in check_reagents)
- if(current.volume >= check_reagents[current.id])
- missing--
- return !missing
-
-/datum/reagents/proc/clear_reagents()
- for(var/datum/reagent/current in reagent_list)
- del_reagent(current.id)
- return
-
-/datum/reagents/proc/get_reagent_amount(var/id)
- for(var/datum/reagent/current in reagent_list)
- if(current.id == id)
- return current.volume
- return 0
-
-/datum/reagents/proc/get_data(var/id)
- for(var/datum/reagent/current in reagent_list)
- if(current.id == id)
- return current.get_data()
- return 0
-
-/datum/reagents/proc/get_reagents()
- . = list()
- for(var/datum/reagent/current in reagent_list)
- . += "[current.id] ([current.volume])"
- return english_list(., "EMPTY", "", ", ", ", ")
-
-/* Holder-to-holder and similar procs */
-
-/datum/reagents/proc/remove_any(var/amount = 1) // Removes up to [amount] of reagents from [src]. Returns actual amount removed.
- amount = min(amount, total_volume)
-
- if(!amount)
- return
-
- var/part = amount / total_volume
-
- for(var/datum/reagent/current in reagent_list)
- var/amount_to_remove = current.volume * part
- remove_reagent(current.id, amount_to_remove, 1)
-
- update_total()
- handle_reactions()
- 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]).
- if(!target || !istype(target))
- return
-
- amount = max(0, min(amount, total_volume, target.get_free_space() / multiplier))
-
- if(!amount)
- return
-
- var/part = amount / total_volume
-
- 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(), safety = 1) // We don't react until everything is in place
- if(!copy)
- remove_reagent(current.id, amount_to_transfer, 1)
-
- if(!copy)
- handle_reactions()
- target.handle_reactions()
- return amount
-
-/* Holder-to-atom and similar procs */
-
-//The general proc for applying reagents to things. This proc assumes the reagents are being applied externally,
-//not directly injected into the contents. It first calls touch, then the appropriate trans_to_*() or splash_mob().
-//If for some reason touch effects are bypassed (e.g. injecting stuff directly into a reagent container or person),
-//call the appropriate trans_to_*() proc.
-/datum/reagents/proc/trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
- touch(target) //First, handle mere touch effects
-
- if(ismob(target))
- return splash_mob(target, amount, copy)
- if(isturf(target))
- return trans_to_turf(target, amount, multiplier, copy)
- if(isobj(target) && target.is_open_container())
- return trans_to_obj(target, amount, multiplier, copy)
- return 0
-
-//Splashing reagents is messier than trans_to, the target's loc gets some of the reagents as well.
-/datum/reagents/proc/splash(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0, var/min_spill=0, var/max_spill=60)
- var/spill = 0
- if(!isturf(target) && target.loc)
- spill = amount*(rand(min_spill, max_spill)/100)
- amount -= spill
- if(spill)
- splash(target.loc, spill, multiplier, copy, min_spill, max_spill)
-
- if(!trans_to(target, amount, multiplier, copy))
- touch(target, amount)
-
-/datum/reagents/proc/trans_type_to(var/target, var/rtype, var/amount = 1)
- if (!target)
- return
-
- var/datum/reagent/transfering_reagent = get_reagent(rtype)
-
- if (istype(target, /atom))
- var/atom/A = target
- if (!A.reagents || !A.simulated)
- return
-
- amount = min(amount, transfering_reagent.volume)
-
- if(!amount)
- return
-
-
- var/datum/reagents/F = new /datum/reagents(amount)
- var/tmpdata = get_data(rtype)
- F.add_reagent(rtype, amount, tmpdata)
- remove_reagent(rtype, amount)
-
-
- if (istype(target, /atom))
- return F.trans_to(target, amount) // Let this proc check the atom's type
- else if (istype(target, /datum/reagents))
- return F.trans_to_holder(target, amount)
-
-/datum/reagents/proc/trans_id_to(var/atom/target, var/id, var/amount = 1)
- if (!target || !target.reagents)
- return
-
- amount = min(amount, get_reagent_amount(id))
-
- if(!amount)
- return
-
- var/datum/reagents/F = new /datum/reagents(amount)
- var/tmpdata = get_data(id)
- F.add_reagent(id, amount, tmpdata)
- remove_reagent(id, amount)
-
- return F.trans_to(target, amount) // Let this proc check the atom's type
-
-// When applying reagents to an atom externally, touch() is called to trigger any on-touch effects of the reagent.
-// This does not handle transferring reagents to things.
-// For example, splashing someone with water will get them wet and extinguish them if they are on fire,
-// even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
-/datum/reagents/proc/touch(var/atom/target, var/amount)
- if(ismob(target))
- touch_mob(target, amount)
- if(isturf(target))
- touch_turf(target, amount)
- if(isobj(target))
- touch_obj(target, amount)
- return
-
-/datum/reagents/proc/touch_mob(var/mob/target)
- if(!target || !istype(target))
- return
-
- for(var/datum/reagent/current in reagent_list)
- current.touch_mob(target, current.volume)
-
- update_total()
-
-/datum/reagents/proc/touch_turf(var/turf/target, var/amount)
- if(!target || !istype(target))
- return
-
- for(var/datum/reagent/current in reagent_list)
- current.touch_turf(target, amount)
-
- update_total()
-
-/datum/reagents/proc/touch_obj(var/obj/target, var/amount)
- if(!target || !istype(target))
- return
-
- for(var/datum/reagent/current in reagent_list)
- current.touch_obj(target, amount)
-
- update_total()
-
-// Attempts to place a reagent on the mob's skin.
-// Reagents are not guaranteed to transfer to the target.
-// Do not call this directly, call trans_to() instead.
-/datum/reagents/proc/splash_mob(var/mob/target, var/amount = 1, var/copy = 0)
- var/perm = 1
- if(isliving(target)) //will we ever even need to tranfer reagents to non-living mobs?
- var/mob/living/L = target
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- if(H.check_shields(0, null, null, null, "the spray") == 1) //If they block the spray, it does nothing.
- amount = 0
- perm = L.reagent_permeability()
- return trans_to_mob(target, amount, CHEM_TOUCH, perm, copy)
-
-/datum/reagents/proc/trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0) // Transfer after checking into which holder...
- if(!target || !istype(target))
- return
- if(iscarbon(target))
- var/mob/living/carbon/C = target
- if(type == CHEM_BLOOD)
- var/datum/reagents/R = C.reagents
- return trans_to_holder(R, amount, multiplier, copy)
- if(type == CHEM_INGEST)
- var/datum/reagents/R = C.ingested
- return C.ingest(src, R, amount, multiplier, copy)
- if(type == CHEM_TOUCH)
- var/datum/reagents/R = C.touching
- return trans_to_holder(R, amount, multiplier, copy)
- else
- var/datum/reagents/R = new /datum/reagents(amount)
- . = trans_to_holder(R, amount, multiplier, copy)
- R.touch_mob(target)
-
-/datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Turfs don't have any reagents (at least, for now). Just touch it.
- if(!target)
- return
-
- var/datum/reagents/R = new /datum/reagents(amount * multiplier)
- . = trans_to_holder(R, amount, multiplier, copy)
- R.touch_turf(target, amount)
- return
-
-/datum/reagents/proc/trans_to_obj(var/obj/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)
- return
-
- if(!target.reagents)
- var/datum/reagents/R = new /datum/reagents(amount * multiplier)
- . = trans_to_holder(R, amount, multiplier, copy)
- R.touch_obj(target, amount)
- return
-
- return trans_to_holder(target.reagents, amount, multiplier, copy)
-
-/* Atom reagent creation - use it all the time */
-
-/atom/proc/create_reagents(var/max_vol)
- reagents = new/datum/reagents(max_vol, src)
-
-// Aurora Cooking Port
-/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)
- return A
-
- return null
-
-//Spreads the contents of this reagent holder all over the vicinity of the target turf.
-/datum/reagents/proc/splash_area(var/turf/epicentre, var/range = 3, var/portion = 1.0, var/multiplier = 1, var/copy = 0)
- var/list/things = dview(range, epicentre, INVISIBILITY_LIGHTING)
- var/list/turfs = list()
- for (var/turf/T in things)
- turfs += T
- if (!turfs.len)
- return//Nowhere to splash to, somehow
- //Create a temporary holder to hold all the amount that will be spread
- var/datum/reagents/R = new /datum/reagents(total_volume * portion * multiplier)
- trans_to_holder(R, total_volume * portion, multiplier, copy)
- //The exact amount that will be given to each turf
- var/turfportion = R.total_volume / turfs.len
- for (var/turf/T in turfs)
- var/datum/reagents/TR = new /datum/reagents(turfportion)
- R.trans_to_holder(TR, turfportion, 1, 0)
- TR.splash_turf(T)
- qdel(R)
-
-
-//Spreads the contents of this reagent holder all over the target turf, dividing among things in it.
-//50% is divided between mobs, 20% between objects, and whatever is left on the turf itself
-/datum/reagents/proc/splash_turf(var/turf/T, var/amount = null, var/multiplier = 1, var/copy = 0)
- if (isnull(amount))
- amount = total_volume
- else
- amount = min(amount, total_volume)
- if (amount <= 0)
- return
- var/list/mobs = list()
- for (var/mob/M in T)
- mobs += M
- var/list/objs = list()
- for (var/obj/O in T)
- objs += O
- if (objs.len)
- var/objportion = (amount * 0.2) / objs.len
- for (var/o in objs)
- var/obj/O = o
- trans_to(O, objportion, multiplier, copy)
- amount = min(amount, total_volume)
- if (mobs.len)
- var/mobportion = (amount * 0.5) / mobs.len
- for (var/m in mobs)
- var/mob/M = m
- trans_to(M, mobportion, multiplier, copy)
- trans_to(T, total_volume, multiplier, copy)
- if (total_volume <= 0)
+#define PROCESS_REACTION_ITER 5 //when processing a reaction, iterate this many times
+
+/datum/reagents
+ var/list/datum/reagent/reagent_list = list()
+ var/total_volume = 0
+ var/maximum_volume = 100
+ var/atom/my_atom = null
+
+/datum/reagents/New(var/max = 100, atom/A = null)
+ ..()
+ maximum_volume = max
+ my_atom = A
+
+ //I dislike having these here but map-objects are initialised before world/New() is called. >_>
+ if(!SSchemistry.chemical_reagents)
+ //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
+ var/paths = subtypesof(/datum/reagent)
+ SSchemistry.chemical_reagents = list()
+ for(var/path in paths)
+ var/datum/reagent/D = new path()
+ if(!D.name)
+ continue
+ SSchemistry.chemical_reagents[D.id] = D
+
+/datum/reagents/Destroy()
+ for(var/datum/reagent/R in reagent_list)
+ qdel(R)
+ reagent_list = null
+ if(my_atom && my_atom.reagents == src)
+ my_atom.reagents = null
+ return ..()
+
+/* Internal procs */
+
+/datum/reagents/proc/get_free_space() // Returns free space.
+ return maximum_volume - total_volume
+
+/datum/reagents/proc/get_master_reagent() // Returns reference to the reagent with the biggest volume.
+ var/the_reagent = null
+ var/the_volume = 0
+
+ for(var/datum/reagent/A in reagent_list)
+ if(A.volume > the_volume)
+ the_volume = A.volume
+ the_reagent = A
+
+ return the_reagent
+
+/datum/reagents/proc/get_master_reagent_name() // Returns the name of the reagent with the biggest volume.
+ var/the_name = null
+ var/the_volume = 0
+ for(var/datum/reagent/A in reagent_list)
+ if(A.volume > the_volume)
+ the_volume = A.volume
+ the_name = A.name
+
+ return the_name
+
+/datum/reagents/proc/get_master_reagent_id() // Returns the id of the reagent with the biggest volume.
+ var/the_id = null
+ var/the_volume = 0
+ for(var/datum/reagent/A in reagent_list)
+ if(A.volume > the_volume)
+ the_volume = A.volume
+ the_id = A.id
+
+ return the_id
+
+/datum/reagents/proc/update_total() // Updates volume.
+ 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
+
+/datum/reagents/proc/handle_reactions()
+ if(QDELETED(my_atom))
+ return FALSE
+ if(my_atom.flags & NOREACT)
+ return FALSE
+ var/reaction_occurred
+ var/list/eligible_reactions = list()
+ var/list/effect_reactions = list()
+ do
+ reaction_occurred = FALSE
+ for(var/i in reagent_list)
+ var/datum/reagent/R = i
+ if(SSchemistry.instant_reactions_by_reagent[R.id])
+ eligible_reactions |= SSchemistry.instant_reactions_by_reagent[R.id]
+
+ for(var/i in eligible_reactions)
+ var/decl/chemical_reaction/C = i
+ if(C.can_happen(src) && C.process(src))
+ effect_reactions |= C
+ reaction_occurred = TRUE
+ eligible_reactions.len = 0
+ while(reaction_occurred)
+ for(var/i in effect_reactions)
+ var/decl/chemical_reaction/C = i
+ C.post_reaction(src)
+ update_total()
+
+/* Holder-to-chemical */
+
+/datum/reagents/proc/add_reagent(var/id, var/amount, var/data = null, var/safety = 0)
+ if(!isnum(amount) || amount <= 0)
+ return 0
+
+ update_total()
+ amount = min(amount, get_free_space())
+
+ if(istype(my_atom,/obj/item/weapon/reagent_containers/food)) //The following code is targeted specifically at getting allergen reagents into food items, since for the most part they're not applied by default.
+ var/list/add_reagents = list()
+ var/totalnum = 0
+
+ for(var/item in data) //Try to find the ID
+ var/add_reagent_id = null
+ if(item in SSchemistry.chemical_reagents)
+ add_reagent_id = item
+ else if("[item]juice" in SSchemistry.chemical_reagents)
+ add_reagent_id = "[item]juice"
+ if(add_reagent_id) //If we did find it, add it to our list of reagents to add, and add the number to our total.
+ add_reagents[add_reagent_id] += data[item]
+ totalnum += data[item]
+
+ if(totalnum)
+ var/multconst = amount/totalnum //We're going to add these extra reagents so that they share the ratio described, but only add up to 1x the existing amount at the most
+ for(var/item in add_reagents)
+ add_reagent(item,add_reagents[item]*multconst)
+
+
+
+
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id == id)
+ if(current.id == "blood")
+ if(LAZYLEN(data) && !isnull(data["species"]) && !isnull(current.data["species"]) && data["species"] != current.data["species"]) // Species bloodtypes are already incompatible, this just stops it from mixing into the one already in a container.
+ continue
+
+ current.volume += 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()
+ 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.initialize_data(data)
+ update_total()
+ if(!safety)
+ handle_reactions()
+ if(my_atom)
+ my_atom.on_reagent_change()
+ return 1
+ else
+ crash_with("[my_atom] attempted to add a reagent called '[id]' which doesn't exist. ([usr])")
+ return 0
+
+/datum/reagents/proc/isolate_reagent(reagent)
+ for(var/A in reagent_list)
+ var/datum/reagent/R = A
+ if(R.id != reagent)
+ del_reagent(R.id)
+ update_total()
+
+/datum/reagents/proc/remove_reagent(var/id, var/amount, var/safety = 0)
+ if(!isnum(amount))
+ return 0
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id == id)
+ 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()
+ return 1
+ return 0
+
+/datum/reagents/proc/del_reagent(var/id)
+ for(var/datum/reagent/current in reagent_list)
+ if (current.id == id)
+ reagent_list -= current
+ qdel(current)
+ update_total()
+ if(my_atom)
+ my_atom.on_reagent_change()
+ return 0
+
+/datum/reagents/proc/has_reagent(var/id, var/amount = 0)
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id == id)
+ if(current.volume >= amount)
+ return 1
+ else
+ return 0
+ return 0
+
+/datum/reagents/proc/has_any_reagent(var/list/check_reagents)
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id in check_reagents)
+ if(current.volume >= check_reagents[current.id])
+ return 1
+ else
+ return 0
+ return 0
+
+/datum/reagents/proc/has_all_reagents(var/list/check_reagents)
+ //this only works if check_reagents has no duplicate entries... hopefully okay since it expects an associative list
+ var/missing = check_reagents.len
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id in check_reagents)
+ if(current.volume >= check_reagents[current.id])
+ missing--
+ return !missing
+
+/datum/reagents/proc/clear_reagents()
+ for(var/datum/reagent/current in reagent_list)
+ del_reagent(current.id)
+ return
+
+/datum/reagents/proc/get_reagent_amount(var/id)
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id == id)
+ return current.volume
+ return 0
+
+/datum/reagents/proc/get_data(var/id)
+ for(var/datum/reagent/current in reagent_list)
+ if(current.id == id)
+ return current.get_data()
+ return 0
+
+/datum/reagents/proc/get_reagents()
+ . = list()
+ for(var/datum/reagent/current in reagent_list)
+ . += "[current.id] ([current.volume])"
+ return english_list(., "EMPTY", "", ", ", ", ")
+
+/* Holder-to-holder and similar procs */
+
+/datum/reagents/proc/remove_any(var/amount = 1) // Removes up to [amount] of reagents from [src]. Returns actual amount removed.
+ amount = min(amount, total_volume)
+
+ if(!amount)
+ return
+
+ var/part = amount / total_volume
+
+ for(var/datum/reagent/current in reagent_list)
+ var/amount_to_remove = current.volume * part
+ remove_reagent(current.id, amount_to_remove, 1)
+
+ update_total()
+ handle_reactions()
+ 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]).
+ if(!target || !istype(target))
+ return
+
+ amount = max(0, min(amount, total_volume, target.get_free_space() / multiplier))
+
+ if(!amount)
+ return
+
+ var/part = amount / total_volume
+
+ 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(), safety = 1) // We don't react until everything is in place
+ if(!copy)
+ remove_reagent(current.id, amount_to_transfer, 1)
+
+ if(!copy)
+ handle_reactions()
+ target.handle_reactions()
+ return amount
+
+/* Holder-to-atom and similar procs */
+
+//The general proc for applying reagents to things. This proc assumes the reagents are being applied externally,
+//not directly injected into the contents. It first calls touch, then the appropriate trans_to_*() or splash_mob().
+//If for some reason touch effects are bypassed (e.g. injecting stuff directly into a reagent container or person),
+//call the appropriate trans_to_*() proc.
+/datum/reagents/proc/trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
+ touch(target) //First, handle mere touch effects
+
+ if(ismob(target))
+ return splash_mob(target, amount, copy)
+ if(isturf(target))
+ return trans_to_turf(target, amount, multiplier, copy)
+ if(isobj(target) && target.is_open_container())
+ return trans_to_obj(target, amount, multiplier, copy)
+ return 0
+
+//Splashing reagents is messier than trans_to, the target's loc gets some of the reagents as well.
+/datum/reagents/proc/splash(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0, var/min_spill=0, var/max_spill=60)
+ var/spill = 0
+ if(!isturf(target) && target.loc)
+ spill = amount*(rand(min_spill, max_spill)/100)
+ amount -= spill
+ if(spill)
+ splash(target.loc, spill, multiplier, copy, min_spill, max_spill)
+
+ if(!trans_to(target, amount, multiplier, copy))
+ touch(target, amount)
+
+/datum/reagents/proc/trans_type_to(var/target, var/rtype, var/amount = 1)
+ if (!target)
+ return
+
+ var/datum/reagent/transfering_reagent = get_reagent(rtype)
+
+ if (istype(target, /atom))
+ var/atom/A = target
+ if (!A.reagents || !A.simulated)
+ return
+
+ amount = min(amount, transfering_reagent.volume)
+
+ if(!amount)
+ return
+
+
+ var/datum/reagents/F = new /datum/reagents(amount)
+ var/tmpdata = get_data(rtype)
+ F.add_reagent(rtype, amount, tmpdata)
+ remove_reagent(rtype, amount)
+
+
+ if (istype(target, /atom))
+ return F.trans_to(target, amount) // Let this proc check the atom's type
+ else if (istype(target, /datum/reagents))
+ return F.trans_to_holder(target, amount)
+
+/datum/reagents/proc/trans_id_to(var/atom/target, var/id, var/amount = 1)
+ if (!target || !target.reagents)
+ return
+
+ amount = min(amount, get_reagent_amount(id))
+
+ if(!amount)
+ return
+
+ var/datum/reagents/F = new /datum/reagents(amount)
+ var/tmpdata = get_data(id)
+ F.add_reagent(id, amount, tmpdata)
+ remove_reagent(id, amount)
+
+ return F.trans_to(target, amount) // Let this proc check the atom's type
+
+// When applying reagents to an atom externally, touch() is called to trigger any on-touch effects of the reagent.
+// This does not handle transferring reagents to things.
+// For example, splashing someone with water will get them wet and extinguish them if they are on fire,
+// even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
+/datum/reagents/proc/touch(var/atom/target, var/amount)
+ if(ismob(target))
+ touch_mob(target, amount)
+ if(isturf(target))
+ touch_turf(target, amount)
+ if(isobj(target))
+ touch_obj(target, amount)
+ return
+
+/datum/reagents/proc/touch_mob(var/mob/target)
+ if(!target || !istype(target))
+ return
+
+ for(var/datum/reagent/current in reagent_list)
+ current.touch_mob(target, current.volume)
+
+ update_total()
+
+/datum/reagents/proc/touch_turf(var/turf/target, var/amount)
+ if(!target || !istype(target))
+ return
+
+ for(var/datum/reagent/current in reagent_list)
+ current.touch_turf(target, amount)
+
+ update_total()
+
+/datum/reagents/proc/touch_obj(var/obj/target, var/amount)
+ if(!target || !istype(target))
+ return
+
+ for(var/datum/reagent/current in reagent_list)
+ current.touch_obj(target, amount)
+
+ update_total()
+
+// Attempts to place a reagent on the mob's skin.
+// Reagents are not guaranteed to transfer to the target.
+// Do not call this directly, call trans_to() instead.
+/datum/reagents/proc/splash_mob(var/mob/target, var/amount = 1, var/copy = 0)
+ var/perm = 1
+ if(isliving(target)) //will we ever even need to tranfer reagents to non-living mobs?
+ var/mob/living/L = target
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ if(H.check_shields(0, null, null, null, "the spray") == 1) //If they block the spray, it does nothing.
+ amount = 0
+ perm = L.reagent_permeability()
+ return trans_to_mob(target, amount, CHEM_TOUCH, perm, copy)
+
+/datum/reagents/proc/trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0) // Transfer after checking into which holder...
+ if(!target || !istype(target))
+ return
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ if(type == CHEM_BLOOD)
+ var/datum/reagents/R = C.reagents
+ return trans_to_holder(R, amount, multiplier, copy)
+ if(type == CHEM_INGEST)
+ var/datum/reagents/R = C.ingested
+ return C.ingest(src, R, amount, multiplier, copy)
+ if(type == CHEM_TOUCH)
+ var/datum/reagents/R = C.touching
+ return trans_to_holder(R, amount, multiplier, copy)
+ else
+ var/datum/reagents/R = new /datum/reagents(amount)
+ . = trans_to_holder(R, amount, multiplier, copy)
+ R.touch_mob(target)
+
+/datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Turfs don't have any reagents (at least, for now). Just touch it.
+ if(!target)
+ return
+
+ var/datum/reagents/R = new /datum/reagents(amount * multiplier)
+ . = trans_to_holder(R, amount, multiplier, copy)
+ R.touch_turf(target, amount)
+ return
+
+/datum/reagents/proc/trans_to_obj(var/obj/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)
+ return
+
+ if(!target.reagents)
+ var/datum/reagents/R = new /datum/reagents(amount * multiplier)
+ . = trans_to_holder(R, amount, multiplier, copy)
+ R.touch_obj(target, amount)
+ return
+
+ return trans_to_holder(target.reagents, amount, multiplier, copy)
+
+/* Atom reagent creation - use it all the time */
+
+/atom/proc/create_reagents(var/max_vol, var/reagents_type = /datum/reagents)
+ if(!ispath(reagents_type))
+ reagents_type = /datum/reagents
+ reagents = new reagents_type(max_vol, src)
+
+// Aurora Cooking Port
+/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)
+ return A
+
+ return null
+
+//Spreads the contents of this reagent holder all over the vicinity of the target turf.
+/datum/reagents/proc/splash_area(var/turf/epicentre, var/range = 3, var/portion = 1.0, var/multiplier = 1, var/copy = 0)
+ var/list/things = dview(range, epicentre, INVISIBILITY_LIGHTING)
+ var/list/turfs = list()
+ for (var/turf/T in things)
+ turfs += T
+ if (!turfs.len)
+ return//Nowhere to splash to, somehow
+ //Create a temporary holder to hold all the amount that will be spread
+ var/datum/reagents/R = new /datum/reagents(total_volume * portion * multiplier)
+ trans_to_holder(R, total_volume * portion, multiplier, copy)
+ //The exact amount that will be given to each turf
+ var/turfportion = R.total_volume / turfs.len
+ for (var/turf/T in turfs)
+ var/datum/reagents/TR = new /datum/reagents(turfportion)
+ R.trans_to_holder(TR, turfportion, 1, 0)
+ TR.splash_turf(T)
+ qdel(R)
+
+
+//Spreads the contents of this reagent holder all over the target turf, dividing among things in it.
+//50% is divided between mobs, 20% between objects, and whatever is left on the turf itself
+/datum/reagents/proc/splash_turf(var/turf/T, var/amount = null, var/multiplier = 1, var/copy = 0)
+ if (isnull(amount))
+ amount = total_volume
+ else
+ amount = min(amount, total_volume)
+ if (amount <= 0)
+ return
+ var/list/mobs = list()
+ for (var/mob/M in T)
+ mobs += M
+ var/list/objs = list()
+ for (var/obj/O in T)
+ objs += O
+ if (objs.len)
+ var/objportion = (amount * 0.2) / objs.len
+ for (var/o in objs)
+ var/obj/O = o
+ trans_to(O, objportion, multiplier, copy)
+ amount = min(amount, total_volume)
+ if (mobs.len)
+ var/mobportion = (amount * 0.5) / mobs.len
+ for (var/m in mobs)
+ var/mob/M = m
+ trans_to(M, mobportion, multiplier, copy)
+ trans_to(T, total_volume, multiplier, copy)
+ if (total_volume <= 0)
qdel(src)
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/machinery/chem_master.dm
similarity index 58%
rename from code/modules/reagents/Chemistry-Machinery.dm
rename to code/modules/reagents/machinery/chem_master.dm
index 39ddc4ae04..be9288160f 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/machinery/chem_master.dm
@@ -1,856 +1,498 @@
-#define SOLID 1
-#define LIQUID 2
-#define GAS 3
-
-#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
-#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
-#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
-#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
-#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
-#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
-#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
-
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/obj/machinery/chem_master
- name = "ChemMaster 3000"
- desc = "Used to seperate and package chemicals in to patches, pills, or bottles. Warranty void if used to create Space Drugs."
- density = 1
- anchored = 1
- icon = 'icons/obj/chemical.dmi'
- icon_state = "mixer0"
- circuit = /obj/item/weapon/circuitboard/chem_master
- use_power = USE_POWER_IDLE
- idle_power_usage = 20
- var/obj/item/weapon/reagent_containers/beaker = null
- var/obj/item/weapon/storage/pill_bottle/loaded_pill_bottle = null
- var/mode = 0
- var/condi = 0
- var/useramount = 15 // Last used amount
- var/pillamount = 10
- var/list/bottle_styles
- var/bottlesprite = 1
- var/pillsprite = 1
- var/max_pill_count = 20
- var/printing = FALSE
- flags = OPENCONTAINER
- clicksound = "button"
-
-/obj/machinery/chem_master/New()
- ..()
- var/datum/reagents/R = new/datum/reagents(900) //Just a huge random number so the buffer should (probably) never dump your reagents.
- reagents = R //There should be a nano ui thingy to warn of this.
- R.my_atom = src
-
-/obj/machinery/chem_master/ex_act(severity)
- switch(severity)
- if(1.0)
- qdel(src)
- return
- if(2.0)
- if (prob(50))
- qdel(src)
- return
-
-/obj/machinery/chem_master/update_icon()
- icon_state = "mixer[beaker ? "1" : "0"]"
-
-/obj/machinery/chem_master/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob)
-
- if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B, /obj/item/weapon/reagent_containers/food))
-
- if(src.beaker)
- to_chat(user, "\A [beaker] is already loaded into the machine.")
- return
- src.beaker = B
- user.drop_item()
- B.loc = src
- to_chat(user, "You add \the [B] to the machine.")
- update_icon()
-
- else if(istype(B, /obj/item/weapon/storage/pill_bottle))
-
- if(src.loaded_pill_bottle)
- to_chat(user, "A \the [loaded_pill_bottle] s already loaded into the machine.")
- return
-
- src.loaded_pill_bottle = B
- user.drop_item()
- B.loc = src
- to_chat(user, "You add \the [loaded_pill_bottle] into the dispenser slot.")
-
- else if(default_unfasten_wrench(user, B, 20))
- return
- if(default_deconstruction_screwdriver(user, B))
- return
- if(default_deconstruction_crowbar(user, B))
- return
-
- return
-
-/obj/machinery/chem_master/attack_hand(mob/user as mob)
- if(stat & BROKEN)
- return
- user.set_machine(src)
- tgui_interact(user)
-
-/obj/machinery/chem_master/ui_assets(mob/user)
- return list(
- get_asset_datum(/datum/asset/chem_master),
- )
-
-/obj/machinery/chem_master/tgui_interact(mob/user, datum/tgui/ui = null)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "ChemMaster", name)
- ui.open()
-
-/**
- * Display the NanoUI window for the chem master.
- *
- * See NanoUI documentation for details.
- */
-/obj/machinery/chem_master/tgui_data(mob/user)
- var/list/data = list()
-
- data["condi"] = condi
-
- data["loaded_pill_bottle"] = !!loaded_pill_bottle
- if(loaded_pill_bottle)
- data["loaded_pill_bottle_name"] = loaded_pill_bottle.name
- data["loaded_pill_bottle_contents_len"] = loaded_pill_bottle.contents.len
- data["loaded_pill_bottle_storage_slots"] = loaded_pill_bottle.max_storage_space
-
- data["beaker"] = !!beaker
- if(beaker)
- var/list/beaker_reagents_list = list()
- data["beaker_reagents"] = beaker_reagents_list
- for(var/datum/reagent/R in beaker.reagents.reagent_list)
- beaker_reagents_list[++beaker_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "description" = R.description, "id" = R.id)
-
- var/list/buffer_reagents_list = list()
- data["buffer_reagents"] = buffer_reagents_list
- for(var/datum/reagent/R in reagents.reagent_list)
- buffer_reagents_list[++buffer_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "id" = R.id, "description" = R.description)
-
- data["pillsprite"] = pillsprite
- data["bottlesprite"] = bottlesprite
- data["mode"] = mode
- data["printing"] = printing
-
- // Transfer modal information if there is one
- data["modal"] = tgui_modal_data(src)
-
- return data
-
-/**
- * Called in tgui_act() to process modal actions
- *
- * Arguments:
- * * action - The action passed by tgui
- * * params - The params passed by tgui
- */
-/obj/machinery/chem_master/proc/tgui_act_modal(action, params, datum/tgui/ui, datum/tgui_state/state)
- . = TRUE
- var/id = params["id"] // The modal's ID
- var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
- switch(tgui_modal_act(src, action, params))
- if(TGUI_MODAL_OPEN)
- switch(id)
- if("analyze")
- var/idx = text2num(arguments["idx"]) || 0
- var/from_beaker = text2num(arguments["beaker"]) || FALSE
- var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
- if(idx < 1 || idx > length(reagent_list))
- return
-
- var/datum/reagent/R = reagent_list[idx]
- var/list/result = list("idx" = idx, "name" = R.name, "desc" = R.description)
- if(!condi && istype(R, /datum/reagent/blood))
- var/datum/reagent/blood/B = R
- result["blood_type"] = B.data["blood_type"]
- result["blood_dna"] = B.data["blood_DNA"]
-
- arguments["analysis"] = result
- tgui_modal_message(src, id, "", null, arguments)
- // if("change_pill_bottle_style")
- // if(!loaded_pill_bottle)
- // return
- // if(!pill_bottle_wrappers)
- // pill_bottle_wrappers = list(
- // "CLEAR" = "Default",
- // COLOR_RED = "Red",
- // COLOR_GREEN = "Green",
- // COLOR_PALE_BTL_GREEN = "Pale green",
- // COLOR_BLUE = "Blue",
- // COLOR_CYAN_BLUE = "Light blue",
- // COLOR_TEAL = "Teal",
- // COLOR_YELLOW = "Yellow",
- // COLOR_ORANGE = "Orange",
- // COLOR_PINK = "Pink",
- // COLOR_MAROON = "Brown"
- // )
- // var/current = pill_bottle_wrappers[loaded_pill_bottle.wrapper_color] || "Default"
- // tgui_modal_choice(src, id, "Please select a pill bottle wrapper:", null, arguments, current, pill_bottle_wrappers)
- if("addcustom")
- if(!beaker || !beaker.reagents.total_volume)
- return
- tgui_modal_input(src, id, "Please enter the amount to transfer to buffer:", null, arguments, useramount)
- if("removecustom")
- if(!reagents.total_volume)
- return
- tgui_modal_input(src, id, "Please enter the amount to transfer to [mode ? "beaker" : "disposal"]:", null, arguments, useramount)
- if("create_condi_pack")
- if(!condi || !reagents.total_volume)
- return
- tgui_modal_input(src, id, "Please name your new condiment pack:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN)
- if("create_pill")
- if(condi || !reagents.total_volume)
- return
- var/num = round(text2num(arguments["num"] || 1))
- if(!num)
- return
- arguments["num"] = num
- var/amount_per_pill = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_PILL)
- var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_pill]u)"
- var/pills_text = num == 1 ? "new pill" : "[num] new pills"
- tgui_modal_input(src, id, "Please name your [pills_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
- if("create_pill_multiple")
- if(condi || !reagents.total_volume)
- return
- tgui_modal_input(src, id, "Please enter the amount of pills to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
- if("change_pill_style")
- var/list/choices = list()
- for(var/i = 1 to MAX_PILL_SPRITE)
- choices += "pill[i].png"
- tgui_modal_bento(src, id, "Please select the new style for pills:", null, arguments, pillsprite, choices)
- if("create_patch")
- if(condi || !reagents.total_volume)
- return
- var/num = round(text2num(arguments["num"] || 1))
- if(!num)
- return
- arguments["num"] = num
- var/amount_per_patch = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_PATCH)
- var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_patch]u)"
- var/patches_text = num == 1 ? "new patch" : "[num] new patches"
- tgui_modal_input(src, id, "Please name your [patches_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
- if("create_patch_multiple")
- if(condi || !reagents.total_volume)
- return
- tgui_modal_input(src, id, "Please enter the amount of patches to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
- if("create_bottle")
- if(condi || !reagents.total_volume)
- return
- var/num = round(text2num(arguments["num"] || 1))
- if(!num)
- return
- arguments["num"] = num
- var/amount_per_bottle = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_BOTTLE)
- var/default_name = "[reagents.get_master_reagent_name()]"
- var/bottles_text = num == 1 ? "new bottle" : "[num] new bottles"
- tgui_modal_input(src, id, "Please name your [bottles_text] ([amount_per_bottle]u in bottle):", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
- if("create_bottle_multiple")
- if(condi || !reagents.total_volume)
- return
- tgui_modal_input(src, id, "Please enter the amount of bottles to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
- if("change_bottle_style")
- var/list/choices = list()
- for(var/i = 1 to MAX_BOTTLE_SPRITE)
- choices += "bottle-[i].png"
- tgui_modal_bento(src, id, "Please select the new style for bottles:", null, arguments, bottlesprite, choices)
- else
- return FALSE
- if(TGUI_MODAL_ANSWER)
- var/answer = params["answer"]
- switch(id)
- // if("change_pill_bottle_style")
- // if(!pill_bottle_wrappers || !loaded_pill_bottle) // wat?
- // return
- // var/color = "CLEAR"
- // for(var/col in pill_bottle_wrappers)
- // var/col_name = pill_bottle_wrappers[col]
- // if(col_name == answer)
- // color = col
- // break
- // if(length(color) && color != "CLEAR")
- // loaded_pill_bottle.wrapper_color = color
- // loaded_pill_bottle.apply_wrap()
- // else
- // loaded_pill_bottle.wrapper_color = null
- // loaded_pill_bottle.cut_overlays()
- if("addcustom")
- var/amount = isgoodnumber(text2num(answer))
- if(!amount || !arguments["id"])
- return
- tgui_act("add", list("id" = arguments["id"], "amount" = amount), ui, state)
- if("removecustom")
- var/amount = isgoodnumber(text2num(answer))
- if(!amount || !arguments["id"])
- return
- tgui_act("remove", list("id" = arguments["id"], "amount" = amount), ui, state)
- if("create_condi_pack")
- if(!condi || !reagents.total_volume)
- return
- if(!length(answer))
- answer = reagents.get_master_reagent_name()
- var/obj/item/weapon/reagent_containers/pill/P = new(loc)
- P.name = "[answer] pack"
- P.desc = "A small condiment pack. The label says it contains [answer]."
- P.icon_state = "bouilloncube"//Reskinned monkey cube
- reagents.trans_to_obj(P, 10)
- if("create_pill")
- if(condi || !reagents.total_volume)
- return
- var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
- if(!count)
- return
-
- if(!length(answer))
- answer = reagents.get_master_reagent_name()
- var/amount_per_pill = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_PILL)
- while(count--)
- if(reagents.total_volume <= 0)
- to_chat(usr, "Not enough reagents to create these pills!")
- return
-
- var/obj/item/weapon/reagent_containers/pill/P = new(loc)
- P.name = "[answer] pill"
- P.pixel_x = rand(-7, 7) // Random position
- P.pixel_y = rand(-7, 7)
- P.icon_state = "pill[pillsprite]"
- if(P.icon_state in list("pill1", "pill2", "pill3", "pill4")) // if using greyscale, take colour from reagent
- P.color = reagents.get_color()
- reagents.trans_to_obj(P, amount_per_pill)
- // Load the pills in the bottle if there's one loaded
- if(istype(loaded_pill_bottle) && length(loaded_pill_bottle.contents) < loaded_pill_bottle.max_storage_space)
- P.forceMove(loaded_pill_bottle)
- if("create_pill_multiple")
- if(condi || !reagents.total_volume)
- return
- tgui_act("modal_open", list("id" = "create_pill", "arguments" = list("num" = answer)), ui, state)
- if("change_pill_style")
- var/new_style = CLAMP(text2num(answer) || 0, 0, MAX_PILL_SPRITE)
- if(!new_style)
- return
- pillsprite = new_style
- if("create_patch")
- if(condi || !reagents.total_volume)
- return
- var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
- if(!count)
- return
-
- if(!length(answer))
- answer = reagents.get_master_reagent_name()
- var/amount_per_patch = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_PATCH)
- // var/is_medical_patch = chemical_safety_check(reagents)
- while(count--)
- if(reagents.total_volume <= 0)
- to_chat(usr, "Not enough reagents to create these patches!")
- return
-
- var/obj/item/weapon/reagent_containers/pill/patch/P = new(loc)
- P.name = "[answer] patch"
- P.pixel_x = rand(-7, 7) // random position
- P.pixel_y = rand(-7, 7)
- reagents.trans_to_obj(P, amount_per_patch)
- // if(is_medical_patch)
- // P.instant_application = TRUE
- // P.icon_state = "bandaid_med"
- if("create_patch_multiple")
- if(condi || !reagents.total_volume)
- return
- tgui_act("modal_open", list("id" = "create_patch", "arguments" = list("num" = answer)), ui, state)
- if("create_bottle")
- if(condi || !reagents.total_volume)
- return
- var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
- if(!count)
- return
-
- if(!length(answer))
- answer = reagents.get_master_reagent_name()
- var/amount_per_bottle = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_BOTTLE)
- while(count--)
- if(reagents.total_volume <= 0)
- to_chat(usr, "Not enough reagents to create these bottles!")
- return
- var/obj/item/weapon/reagent_containers/glass/bottle/P = new(loc)
- P.name = "[answer] bottle"
- P.pixel_x = rand(-7, 7) // random position
- P.pixel_y = rand(-7, 7)
- P.icon_state = "bottle-[bottlesprite]" || "bottle-1"
- reagents.trans_to_obj(P, amount_per_bottle)
- P.update_icon()
- if("create_bottle_multiple")
- if(condi || !reagents.total_volume)
- return
- tgui_act("modal_open", list("id" = "create_bottle", "arguments" = list("num" = answer)), ui, state)
- if("change_bottle_style")
- var/new_style = CLAMP(text2num(answer) || 0, 0, MAX_BOTTLE_SPRITE)
- if(!new_style)
- return
- bottlesprite = new_style
- else
- return FALSE
- else
- return FALSE
-
-/obj/machinery/chem_master/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
- if(..())
- return TRUE
-
- if(tgui_act_modal(action, params, ui, state))
- return TRUE
-
- add_fingerprint(usr)
- usr.set_machine(src)
-
- . = TRUE
- switch(action)
- if("toggle")
- mode = !mode
- if("ejectp")
- if(loaded_pill_bottle)
- loaded_pill_bottle.forceMove(get_turf(src))
- if(Adjacent(usr) && !issilicon(usr))
- usr.put_in_hands(loaded_pill_bottle)
- loaded_pill_bottle = null
- if("print")
- if(printing || condi)
- return
-
- var/idx = text2num(params["idx"]) || 0
- var/from_beaker = text2num(params["beaker"]) || FALSE
- var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
- if(idx < 1 || idx > length(reagent_list))
- return
-
- var/datum/reagent/R = reagent_list[idx]
-
- printing = TRUE
- visible_message("[src] rattles and prints out a sheet of paper.")
- // playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
-
- var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(loc)
- P.info = "
Chemical Analysis
"
- P.info += "Time of analysis: [worldtime2stationtime(world.time)]
"
- P.info += "Chemical name: [R.name]
"
- if(istype(R, /datum/reagent/blood))
- var/datum/reagent/blood/B = R
- P.info += "Description: N/A
Blood Type: [B.data["blood_type"]]
DNA: [B.data["blood_DNA"]]"
- else
- P.info += "Description: [R.description]"
- P.info += "
Notes:
"
- P.name = "Chemical Analysis - [R.name]"
- spawn(50)
- printing = FALSE
- else
- . = FALSE
-
- if(. || !beaker)
- return
-
- . = TRUE
- var/datum/reagents/R = beaker.reagents
- switch(action)
- if("add")
- var/id = params["id"]
- var/amount = text2num(params["amount"])
- if(!id || !amount)
- return
- R.trans_id_to(src, id, amount)
- if("remove")
- var/id = params["id"]
- var/amount = text2num(params["amount"])
- if(!id || !amount)
- return
- if(mode)
- reagents.trans_id_to(beaker, id, amount)
- else
- reagents.remove_reagent(id, amount)
- if("eject")
- if(!beaker)
- return
- beaker.forceMove(get_turf(src))
- if(Adjacent(usr) && !issilicon(usr))
- usr.put_in_hands(beaker)
- beaker = null
- reagents.clear_reagents()
- update_icon()
- if("create_condi_bottle")
- if(!condi || !reagents.total_volume)
- return
- var/obj/item/weapon/reagent_containers/food/condiment/P = new(loc)
- reagents.trans_to_obj(P, 50)
- else
- return FALSE
-
-/obj/machinery/chem_master/attack_ai(mob/user)
- return attack_hand(user)
-
-/obj/machinery/chem_master/proc/isgoodnumber(num)
- if(isnum(num))
- if(num > 200)
- num = 200
- else if(num < 0)
- num = 1
- return num
- else
- return FALSE
-
-// /obj/machinery/chem_master/proc/chemical_safety_check(datum/reagents/R)
-// var/all_safe = TRUE
-// for(var/datum/reagent/A in R.reagent_list)
-// if(!GLOB.safe_chem_list.Find(A.id))
-// all_safe = FALSE
-// return all_safe
-
-/obj/machinery/chem_master/condimaster
- name = "CondiMaster 3000"
- condi = 1
-
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-/obj/machinery/reagentgrinder
-
- name = "All-In-One Grinder"
- desc = "Grinds stuff into itty bitty bits."
- icon = 'icons/obj/kitchen.dmi'
- icon_state = "juicer1"
- density = 0
- anchored = 0
- use_power = USE_POWER_IDLE
- idle_power_usage = 5
- active_power_usage = 100
- circuit = /obj/item/weapon/circuitboard/grinder
- var/inuse = 0
- var/obj/item/weapon/reagent_containers/beaker = null
- var/limit = 10
- var/list/holdingitems = list()
- var/list/sheet_reagents = list( //have a number of reageents divisible by REAGENTS_PER_SHEET (default 20) unless you like decimals,
- /obj/item/stack/material/iron = list("iron"),
- /obj/item/stack/material/uranium = list("uranium"),
- /obj/item/stack/material/phoron = list("phoron"),
- /obj/item/stack/material/gold = list("gold"),
- /obj/item/stack/material/silver = list("silver"),
- /obj/item/stack/material/platinum = list("platinum"),
- /obj/item/stack/material/mhydrogen = list("hydrogen"),
- /obj/item/stack/material/steel = list("iron", "carbon"),
- /obj/item/stack/material/plasteel = list("iron", "iron", "carbon", "carbon", "platinum"), //8 iron, 8 carbon, 4 platinum,
- /obj/item/stack/material/snow = list("water"),
- /obj/item/stack/material/sandstone = list("silicon", "oxygen"),
- /obj/item/stack/material/glass = list("silicon"),
- /obj/item/stack/material/glass/phoronglass = list("platinum", "silicon", "silicon", "silicon"), //5 platinum, 15 silicon,
- )
-
- var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine")
- var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject")
- var/static/radial_grind = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_grind")
- // var/static/radial_juice = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_juice")
- // var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix")
-
-/obj/machinery/reagentgrinder/Initialize()
- . = ..()
- beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
- default_apply_parts()
-
-/obj/machinery/reagentgrinder/examine(mob/user)
- . = ..()
- if(!in_range(user, src) && !issilicon(user) && !isobserver(user))
- . += "You're too far away to examine [src]'s contents and display!"
- return
-
- if(inuse)
- . += "\The [src] is operating."
- return
-
- if(beaker || length(holdingitems))
- . += "\The [src] contains:"
- if(beaker)
- . += "- \A [beaker]."
- for(var/i in holdingitems)
- var/obj/item/O = i
- . += "- \A [O.name]."
-
- if(!(stat & (NOPOWER|BROKEN)))
- . += "The status display reads:\n"
- if(beaker)
- for(var/datum/reagent/R in beaker.reagents.reagent_list)
- . += "- [R.volume] units of [R.name]."
-
-/obj/machinery/reagentgrinder/update_icon()
- icon_state = "juicer"+num2text(!isnull(beaker))
- return
-
-/obj/machinery/reagentgrinder/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(beaker)
- if(default_deconstruction_screwdriver(user, O))
- return
- if(default_deconstruction_crowbar(user, O))
- return
-
- if (istype(O,/obj/item/weapon/reagent_containers/glass) || \
- istype(O,/obj/item/weapon/reagent_containers/food/drinks/glass2) || \
- istype(O,/obj/item/weapon/reagent_containers/food/drinks/shaker))
-
- if (beaker)
- return 1
- else
- src.beaker = O
- user.drop_item()
- O.loc = src
- update_icon()
- src.updateUsrDialog()
- return 0
-
- if(holdingitems && holdingitems.len >= limit)
- to_chat(user, "The machine cannot hold anymore items.")
- return 1
-
- if(!istype(O))
- return
-
- if(istype(O,/obj/item/weapon/storage/bag/plants))
- var/obj/item/weapon/storage/bag/plants/bag = O
- var/failed = 1
- for(var/obj/item/G in O.contents)
- if(!G.reagents || !G.reagents.total_volume)
- continue
- failed = 0
- bag.remove_from_storage(G, src)
- holdingitems += G
- if(holdingitems && holdingitems.len >= limit)
- break
-
- if(failed)
- to_chat(user, "Nothing in the plant bag is usable.")
- return 1
-
- if(!O.contents.len)
- to_chat(user, "You empty \the [O] into \the [src].")
- else
- to_chat(user, "You fill \the [src] from \the [O].")
-
- src.updateUsrDialog()
- return 0
-
- if(istype(O,/obj/item/weapon/gripper))
- var/obj/item/weapon/gripper/B = O //B, for Borg.
- if(!B.wrapped)
- to_chat(user, "\The [B] is not holding anything.")
- return 0
- else
- var/B_held = B.wrapped
- to_chat(user, "You use \the [B] to load \the [src] with \the [B_held].")
-
- return 0
-
- if(!sheet_reagents[O.type] && (!O.reagents || !O.reagents.total_volume))
- to_chat(user, "\The [O] is not suitable for blending.")
- return 1
-
- user.remove_from_mob(O)
- O.loc = src
- holdingitems += O
- return 0
-
-/obj/machinery/reagentgrinder/AltClick(mob/user)
- . = ..()
- if(user.incapacitated() || !Adjacent(user))
- return
- replace_beaker(user)
-
-/obj/machinery/reagentgrinder/attack_hand(mob/user as mob)
- interact(user)
-
-/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu //I am reasonably certain that this is not a microwave
- if(inuse || user.incapacitated())
- return
-
- var/list/options = list()
-
- if(beaker || length(holdingitems))
- options["eject"] = radial_eject
-
- if(isAI(user))
- if(stat & NOPOWER)
- return
- options["examine"] = radial_examine
-
- // if there is no power or it's broken, the procs will fail but the buttons will still show
- if(length(holdingitems))
- options["grind"] = radial_grind
-
- var/choice
- if(length(options) < 1)
- return
- if(length(options) == 1)
- for(var/key in options)
- choice = key
- else
- choice = show_radial_menu(user, src, options, require_near = !issilicon(user))
-
- // post choice verification
- if(inuse || (isAI(user) && stat & NOPOWER) || user.incapacitated())
- return
-
- switch(choice)
- if("eject")
- eject(user)
- if("grind")
- grind(user)
- if("examine")
- examine(user)
-
-/obj/machinery/reagentgrinder/proc/eject(mob/user)
- if(user.incapacitated())
- return
- for(var/obj/item/O in holdingitems)
- O.loc = src.loc
- holdingitems -= O
- holdingitems.Cut()
- if(beaker)
- replace_beaker(user)
-
-/obj/machinery/reagentgrinder/proc/grind()
-
- power_change()
- if(stat & (NOPOWER|BROKEN))
- return
-
- // Sanity check.
- if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume))
- return
-
- playsound(src, 'sound/machines/blender.ogg', 50, 1)
- inuse = 1
-
- // Reset the machine.
- spawn(60)
- inuse = 0
-
- // Process.
- for (var/obj/item/O in holdingitems)
-
- var/remaining_volume = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- if(remaining_volume <= 0)
- break
-
- if(sheet_reagents[O.type])
- var/obj/item/stack/stack = O
- if(istype(stack))
- var/list/sheet_components = sheet_reagents[stack.type]
- var/amount_to_take = max(0,min(stack.amount,round(remaining_volume/REAGENTS_PER_SHEET)))
- if(amount_to_take)
- stack.use(amount_to_take)
- if(QDELETED(stack))
- holdingitems -= stack
- if(islist(sheet_components))
- amount_to_take = (amount_to_take/(sheet_components.len))
- for(var/i in sheet_components)
- beaker.reagents.add_reagent(i, (amount_to_take*REAGENTS_PER_SHEET))
- else
- beaker.reagents.add_reagent(sheet_components, (amount_to_take*REAGENTS_PER_SHEET))
- continue
-
- if(O.reagents)
- O.reagents.trans_to_obj(beaker, min(O.reagents.total_volume, remaining_volume))
- if(O.reagents.total_volume == 0)
- holdingitems -= O
- qdel(O)
- if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
- break
-
-/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/weapon/reagent_containers/new_beaker)
- if(!user)
- return FALSE
- if(beaker)
- if(!user.incapacitated() && Adjacent(user))
- user.put_in_hands(beaker)
- else
- beaker.forceMove(drop_location())
- beaker = null
- if(new_beaker)
- beaker = new_beaker
- update_icon()
- return TRUE
-
-///////////////
-///////////////
-// Detects reagents inside most containers, and acts as an infinite identification system for reagent-based unidentified objects.
-
-/obj/machinery/chemical_analyzer
- name = "chem analyzer"
- desc = "Used to precisely scan chemicals and other liquids inside various containers. \
- It may also identify the liquid contents of unknown objects."
- description_info = "This machine will try to tell you what reagents are inside of something capable of holding reagents. \
- It is also used to 'identify' specific reagent-based objects with their properties obscured from inspection by normal means."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "chem_analyzer"
- density = TRUE
- anchored = TRUE
- use_power = TRUE
- idle_power_usage = 20
- clicksound = "button"
- var/analyzing = FALSE
-
-/obj/machinery/chemical_analyzer/update_icon()
- icon_state = "chem_analyzer[analyzing ? "-working":""]"
-
-/obj/machinery/chemical_analyzer/attackby(obj/item/I, mob/living/user)
- if(!istype(I))
- return ..()
-
- if(default_deconstruction_screwdriver(user, I))
- return
- if(default_deconstruction_crowbar(user, I))
- return
-
- if(istype(I,/obj/item/weapon/reagent_containers))
- analyzing = TRUE
- update_icon()
- to_chat(user, span("notice", "Analyzing \the [I], please stand by..."))
-
- if(!do_after(user, 2 SECONDS, src))
- to_chat(user, span("warning", "Sample moved outside of scan range, please try again and remain still."))
- analyzing = FALSE
- update_icon()
- return
-
- // First, identify it if it isn't already.
- if(!I.is_identified(IDENTITY_FULL))
- var/datum/identification/ID = I.identity
- if(ID.identification_type == IDENTITY_TYPE_CHEMICAL) // This only solves chemical-based mysteries.
- I.identify(IDENTITY_FULL, user)
-
- // Now tell us everything that is inside.
- if(I.reagents && I.reagents.reagent_list.len)
- to_chat(user, "
") // To add padding between regular chat and the output.
- for(var/datum/reagent/R in I.reagents.reagent_list)
- if(!R.name)
- continue
- to_chat(user, span("notice", "Contains [R.volume]u of [R.name].
[R.description]
"))
-
- // Last, unseal it if it's an autoinjector.
- if(istype(I,/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector) && !(I.flags & OPENCONTAINER))
- I.flags |= OPENCONTAINER
- to_chat(user, span("notice", "Sample container unsealed.
"))
-
- to_chat(user, span("notice", "Scanning of \the [I] complete."))
- analyzing = FALSE
- update_icon()
- return
-
-#undef MAX_PILL_SPRITE
-#undef MAX_BOTTLE_SPRITE
-#undef MAX_MULTI_AMOUNT
-#undef MAX_UNITS_PER_PILL
-#undef MAX_UNITS_PER_PATCH
-#undef MAX_UNITS_PER_BOTTLE
-#undef MAX_CUSTOM_NAME_LEN
+/obj/machinery/chem_master
+ name = "ChemMaster 3000"
+ desc = "Used to seperate and package chemicals in to patches, pills, or bottles. Warranty void if used to create Space Drugs."
+ density = 1
+ anchored = 1
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "mixer0"
+ circuit = /obj/item/weapon/circuitboard/chem_master
+ use_power = USE_POWER_IDLE
+ idle_power_usage = 20
+ var/obj/item/weapon/reagent_containers/beaker = null
+ var/obj/item/weapon/storage/pill_bottle/loaded_pill_bottle = null
+ var/mode = 0
+ var/condi = 0
+ var/useramount = 15 // Last used amount
+ var/pillamount = 10
+ var/list/bottle_styles
+ var/bottlesprite = 1
+ var/pillsprite = 1
+ var/max_pill_count = 20
+ var/printing = FALSE
+ flags = OPENCONTAINER
+ clicksound = "button"
+
+/obj/machinery/chem_master/New()
+ ..()
+ var/datum/reagents/R = new/datum/reagents(900) //Just a huge random number so the buffer should (probably) never dump your reagents.
+ reagents = R //There should be a nano ui thingy to warn of this.
+ R.my_atom = src
+
+/obj/machinery/chem_master/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ qdel(src)
+ return
+ if(2.0)
+ if (prob(50))
+ qdel(src)
+ return
+
+/obj/machinery/chem_master/update_icon()
+ icon_state = "mixer[beaker ? "1" : "0"]"
+
+/obj/machinery/chem_master/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob)
+
+ if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B, /obj/item/weapon/reagent_containers/food))
+
+ if(src.beaker)
+ to_chat(user, "\A [beaker] is already loaded into the machine.")
+ return
+ src.beaker = B
+ user.drop_item()
+ B.loc = src
+ to_chat(user, "You add \the [B] to the machine.")
+ update_icon()
+
+ else if(istype(B, /obj/item/weapon/storage/pill_bottle))
+
+ if(src.loaded_pill_bottle)
+ to_chat(user, "A \the [loaded_pill_bottle] s already loaded into the machine.")
+ return
+
+ src.loaded_pill_bottle = B
+ user.drop_item()
+ B.loc = src
+ to_chat(user, "You add \the [loaded_pill_bottle] into the dispenser slot.")
+
+ else if(default_unfasten_wrench(user, B, 20))
+ return
+ if(default_deconstruction_screwdriver(user, B))
+ return
+ if(default_deconstruction_crowbar(user, B))
+ return
+
+ return
+
+/obj/machinery/chem_master/attack_hand(mob/user as mob)
+ if(stat & BROKEN)
+ return
+ user.set_machine(src)
+ tgui_interact(user)
+
+/obj/machinery/chem_master/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/chem_master),
+ )
+
+/obj/machinery/chem_master/tgui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemMaster", name)
+ ui.open()
+
+/**
+ * Display the NanoUI window for the chem master.
+ *
+ * See NanoUI documentation for details.
+ */
+/obj/machinery/chem_master/tgui_data(mob/user)
+ var/list/data = list()
+
+ data["condi"] = condi
+
+ data["loaded_pill_bottle"] = !!loaded_pill_bottle
+ if(loaded_pill_bottle)
+ data["loaded_pill_bottle_name"] = loaded_pill_bottle.name
+ data["loaded_pill_bottle_contents_len"] = loaded_pill_bottle.contents.len
+ data["loaded_pill_bottle_storage_slots"] = loaded_pill_bottle.max_storage_space
+
+ data["beaker"] = !!beaker
+ if(beaker)
+ var/list/beaker_reagents_list = list()
+ data["beaker_reagents"] = beaker_reagents_list
+ for(var/datum/reagent/R in beaker.reagents.reagent_list)
+ beaker_reagents_list[++beaker_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "description" = R.description, "id" = R.id)
+
+ var/list/buffer_reagents_list = list()
+ data["buffer_reagents"] = buffer_reagents_list
+ for(var/datum/reagent/R in reagents.reagent_list)
+ buffer_reagents_list[++buffer_reagents_list.len] = list("name" = R.name, "volume" = R.volume, "id" = R.id, "description" = R.description)
+
+ data["pillsprite"] = pillsprite
+ data["bottlesprite"] = bottlesprite
+ data["mode"] = mode
+ data["printing"] = printing
+
+ // Transfer modal information if there is one
+ data["modal"] = tgui_modal_data(src)
+
+ return data
+
+/**
+ * Called in tgui_act() to process modal actions
+ *
+ * Arguments:
+ * * action - The action passed by tgui
+ * * params - The params passed by tgui
+ */
+/obj/machinery/chem_master/proc/tgui_act_modal(action, params, datum/tgui/ui, datum/tgui_state/state)
+ . = TRUE
+ var/id = params["id"] // The modal's ID
+ var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
+ switch(tgui_modal_act(src, action, params))
+ if(TGUI_MODAL_OPEN)
+ switch(id)
+ if("analyze")
+ var/idx = text2num(arguments["idx"]) || 0
+ var/from_beaker = text2num(arguments["beaker"]) || FALSE
+ var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
+ if(idx < 1 || idx > length(reagent_list))
+ return
+
+ var/datum/reagent/R = reagent_list[idx]
+ var/list/result = list("idx" = idx, "name" = R.name, "desc" = R.description)
+ if(!condi && istype(R, /datum/reagent/blood))
+ var/datum/reagent/blood/B = R
+ result["blood_type"] = B.data["blood_type"]
+ result["blood_dna"] = B.data["blood_DNA"]
+
+ arguments["analysis"] = result
+ tgui_modal_message(src, id, "", null, arguments)
+ // if("change_pill_bottle_style")
+ // if(!loaded_pill_bottle)
+ // return
+ // if(!pill_bottle_wrappers)
+ // pill_bottle_wrappers = list(
+ // "CLEAR" = "Default",
+ // COLOR_RED = "Red",
+ // COLOR_GREEN = "Green",
+ // COLOR_PALE_BTL_GREEN = "Pale green",
+ // COLOR_BLUE = "Blue",
+ // COLOR_CYAN_BLUE = "Light blue",
+ // COLOR_TEAL = "Teal",
+ // COLOR_YELLOW = "Yellow",
+ // COLOR_ORANGE = "Orange",
+ // COLOR_PINK = "Pink",
+ // COLOR_MAROON = "Brown"
+ // )
+ // var/current = pill_bottle_wrappers[loaded_pill_bottle.wrapper_color] || "Default"
+ // tgui_modal_choice(src, id, "Please select a pill bottle wrapper:", null, arguments, current, pill_bottle_wrappers)
+ if("addcustom")
+ if(!beaker || !beaker.reagents.total_volume)
+ return
+ tgui_modal_input(src, id, "Please enter the amount to transfer to buffer:", null, arguments, useramount)
+ if("removecustom")
+ if(!reagents.total_volume)
+ return
+ tgui_modal_input(src, id, "Please enter the amount to transfer to [mode ? "beaker" : "disposal"]:", null, arguments, useramount)
+ if("create_condi_pack")
+ if(!condi || !reagents.total_volume)
+ return
+ tgui_modal_input(src, id, "Please name your new condiment pack:", null, arguments, reagents.get_master_reagent_name(), MAX_CUSTOM_NAME_LEN)
+ if("create_pill")
+ if(condi || !reagents.total_volume)
+ return
+ var/num = round(text2num(arguments["num"] || 1))
+ if(!num)
+ return
+ arguments["num"] = num
+ var/amount_per_pill = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_PILL)
+ var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_pill]u)"
+ var/pills_text = num == 1 ? "new pill" : "[num] new pills"
+ tgui_modal_input(src, id, "Please name your [pills_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
+ if("create_pill_multiple")
+ if(condi || !reagents.total_volume)
+ return
+ tgui_modal_input(src, id, "Please enter the amount of pills to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
+ if("change_pill_style")
+ var/list/choices = list()
+ for(var/i = 1 to MAX_PILL_SPRITE)
+ choices += "pill[i].png"
+ tgui_modal_bento(src, id, "Please select the new style for pills:", null, arguments, pillsprite, choices)
+ if("create_patch")
+ if(condi || !reagents.total_volume)
+ return
+ var/num = round(text2num(arguments["num"] || 1))
+ if(!num)
+ return
+ arguments["num"] = num
+ var/amount_per_patch = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_PATCH)
+ var/default_name = "[reagents.get_master_reagent_name()] ([amount_per_patch]u)"
+ var/patches_text = num == 1 ? "new patch" : "[num] new patches"
+ tgui_modal_input(src, id, "Please name your [patches_text]:", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
+ if("create_patch_multiple")
+ if(condi || !reagents.total_volume)
+ return
+ tgui_modal_input(src, id, "Please enter the amount of patches to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
+ if("create_bottle")
+ if(condi || !reagents.total_volume)
+ return
+ var/num = round(text2num(arguments["num"] || 1))
+ if(!num)
+ return
+ arguments["num"] = num
+ var/amount_per_bottle = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_BOTTLE)
+ var/default_name = "[reagents.get_master_reagent_name()]"
+ var/bottles_text = num == 1 ? "new bottle" : "[num] new bottles"
+ tgui_modal_input(src, id, "Please name your [bottles_text] ([amount_per_bottle]u in bottle):", null, arguments, default_name, MAX_CUSTOM_NAME_LEN)
+ if("create_bottle_multiple")
+ if(condi || !reagents.total_volume)
+ return
+ tgui_modal_input(src, id, "Please enter the amount of bottles to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5)
+ if("change_bottle_style")
+ var/list/choices = list()
+ for(var/i = 1 to MAX_BOTTLE_SPRITE)
+ choices += "bottle-[i].png"
+ tgui_modal_bento(src, id, "Please select the new style for bottles:", null, arguments, bottlesprite, choices)
+ else
+ return FALSE
+ if(TGUI_MODAL_ANSWER)
+ var/answer = params["answer"]
+ switch(id)
+ // if("change_pill_bottle_style")
+ // if(!pill_bottle_wrappers || !loaded_pill_bottle) // wat?
+ // return
+ // var/color = "CLEAR"
+ // for(var/col in pill_bottle_wrappers)
+ // var/col_name = pill_bottle_wrappers[col]
+ // if(col_name == answer)
+ // color = col
+ // break
+ // if(length(color) && color != "CLEAR")
+ // loaded_pill_bottle.wrapper_color = color
+ // loaded_pill_bottle.apply_wrap()
+ // else
+ // loaded_pill_bottle.wrapper_color = null
+ // loaded_pill_bottle.cut_overlays()
+ if("addcustom")
+ var/amount = isgoodnumber(text2num(answer))
+ if(!amount || !arguments["id"])
+ return
+ tgui_act("add", list("id" = arguments["id"], "amount" = amount), ui, state)
+ if("removecustom")
+ var/amount = isgoodnumber(text2num(answer))
+ if(!amount || !arguments["id"])
+ return
+ tgui_act("remove", list("id" = arguments["id"], "amount" = amount), ui, state)
+ if("create_condi_pack")
+ if(!condi || !reagents.total_volume)
+ return
+ if(!length(answer))
+ answer = reagents.get_master_reagent_name()
+ var/obj/item/weapon/reagent_containers/pill/P = new(loc)
+ P.name = "[answer] pack"
+ P.desc = "A small condiment pack. The label says it contains [answer]."
+ P.icon_state = "bouilloncube"//Reskinned monkey cube
+ reagents.trans_to_obj(P, 10)
+ if("create_pill")
+ if(condi || !reagents.total_volume)
+ return
+ var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
+ if(!count)
+ return
+
+ if(!length(answer))
+ answer = reagents.get_master_reagent_name()
+ var/amount_per_pill = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_PILL)
+ while(count--)
+ if(reagents.total_volume <= 0)
+ to_chat(usr, "Not enough reagents to create these pills!")
+ return
+
+ var/obj/item/weapon/reagent_containers/pill/P = new(loc)
+ P.name = "[answer] pill"
+ P.pixel_x = rand(-7, 7) // Random position
+ P.pixel_y = rand(-7, 7)
+ P.icon_state = "pill[pillsprite]"
+ if(P.icon_state in list("pill1", "pill2", "pill3", "pill4")) // if using greyscale, take colour from reagent
+ P.color = reagents.get_color()
+ reagents.trans_to_obj(P, amount_per_pill)
+ // Load the pills in the bottle if there's one loaded
+ if(istype(loaded_pill_bottle) && length(loaded_pill_bottle.contents) < loaded_pill_bottle.max_storage_space)
+ P.forceMove(loaded_pill_bottle)
+ if("create_pill_multiple")
+ if(condi || !reagents.total_volume)
+ return
+ tgui_act("modal_open", list("id" = "create_pill", "arguments" = list("num" = answer)), ui, state)
+ if("change_pill_style")
+ var/new_style = CLAMP(text2num(answer) || 0, 0, MAX_PILL_SPRITE)
+ if(!new_style)
+ return
+ pillsprite = new_style
+ if("create_patch")
+ if(condi || !reagents.total_volume)
+ return
+ var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
+ if(!count)
+ return
+
+ if(!length(answer))
+ answer = reagents.get_master_reagent_name()
+ var/amount_per_patch = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_PATCH)
+ // var/is_medical_patch = chemical_safety_check(reagents)
+ while(count--)
+ if(reagents.total_volume <= 0)
+ to_chat(usr, "Not enough reagents to create these patches!")
+ return
+
+ var/obj/item/weapon/reagent_containers/pill/patch/P = new(loc)
+ P.name = "[answer] patch"
+ P.pixel_x = rand(-7, 7) // random position
+ P.pixel_y = rand(-7, 7)
+ reagents.trans_to_obj(P, amount_per_patch)
+ // if(is_medical_patch)
+ // P.instant_application = TRUE
+ // P.icon_state = "bandaid_med"
+ if("create_patch_multiple")
+ if(condi || !reagents.total_volume)
+ return
+ tgui_act("modal_open", list("id" = "create_patch", "arguments" = list("num" = answer)), ui, state)
+ if("create_bottle")
+ if(condi || !reagents.total_volume)
+ return
+ var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT)
+ if(!count)
+ return
+
+ if(!length(answer))
+ answer = reagents.get_master_reagent_name()
+ var/amount_per_bottle = CLAMP(reagents.total_volume / count, 0, MAX_UNITS_PER_BOTTLE)
+ while(count--)
+ if(reagents.total_volume <= 0)
+ to_chat(usr, "Not enough reagents to create these bottles!")
+ return
+ var/obj/item/weapon/reagent_containers/glass/bottle/P = new(loc)
+ P.name = "[answer] bottle"
+ P.pixel_x = rand(-7, 7) // random position
+ P.pixel_y = rand(-7, 7)
+ P.icon_state = "bottle-[bottlesprite]" || "bottle-1"
+ reagents.trans_to_obj(P, amount_per_bottle)
+ P.update_icon()
+ if("create_bottle_multiple")
+ if(condi || !reagents.total_volume)
+ return
+ tgui_act("modal_open", list("id" = "create_bottle", "arguments" = list("num" = answer)), ui, state)
+ if("change_bottle_style")
+ var/new_style = CLAMP(text2num(answer) || 0, 0, MAX_BOTTLE_SPRITE)
+ if(!new_style)
+ return
+ bottlesprite = new_style
+ else
+ return FALSE
+ else
+ return FALSE
+
+/obj/machinery/chem_master/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
+ if(..())
+ return TRUE
+
+ if(tgui_act_modal(action, params, ui, state))
+ return TRUE
+
+ add_fingerprint(usr)
+ usr.set_machine(src)
+
+ . = TRUE
+ switch(action)
+ if("toggle")
+ mode = !mode
+ if("ejectp")
+ if(loaded_pill_bottle)
+ loaded_pill_bottle.forceMove(get_turf(src))
+ if(Adjacent(usr) && !issilicon(usr))
+ usr.put_in_hands(loaded_pill_bottle)
+ loaded_pill_bottle = null
+ if("print")
+ if(printing || condi)
+ return
+
+ var/idx = text2num(params["idx"]) || 0
+ var/from_beaker = text2num(params["beaker"]) || FALSE
+ var/reagent_list = from_beaker ? beaker.reagents.reagent_list : reagents.reagent_list
+ if(idx < 1 || idx > length(reagent_list))
+ return
+
+ var/datum/reagent/R = reagent_list[idx]
+
+ printing = TRUE
+ visible_message("[src] rattles and prints out a sheet of paper.")
+ // playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
+
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(loc)
+ P.info = "Chemical Analysis
"
+ P.info += "Time of analysis: [worldtime2stationtime(world.time)]
"
+ P.info += "Chemical name: [R.name]
"
+ if(istype(R, /datum/reagent/blood))
+ var/datum/reagent/blood/B = R
+ P.info += "Description: N/A
Blood Type: [B.data["blood_type"]]
DNA: [B.data["blood_DNA"]]"
+ else
+ P.info += "Description: [R.description]"
+ P.info += "
Notes:
"
+ P.name = "Chemical Analysis - [R.name]"
+ spawn(50)
+ printing = FALSE
+ else
+ . = FALSE
+
+ if(. || !beaker)
+ return
+
+ . = TRUE
+ var/datum/reagents/R = beaker.reagents
+ switch(action)
+ if("add")
+ var/id = params["id"]
+ var/amount = text2num(params["amount"])
+ if(!id || !amount)
+ return
+ R.trans_id_to(src, id, amount)
+ if("remove")
+ var/id = params["id"]
+ var/amount = text2num(params["amount"])
+ if(!id || !amount)
+ return
+ if(mode)
+ reagents.trans_id_to(beaker, id, amount)
+ else
+ reagents.remove_reagent(id, amount)
+ if("eject")
+ if(!beaker)
+ return
+ beaker.forceMove(get_turf(src))
+ if(Adjacent(usr) && !issilicon(usr))
+ usr.put_in_hands(beaker)
+ beaker = null
+ reagents.clear_reagents()
+ update_icon()
+ if("create_condi_bottle")
+ if(!condi || !reagents.total_volume)
+ return
+ var/obj/item/weapon/reagent_containers/food/condiment/P = new(loc)
+ reagents.trans_to_obj(P, 50)
+ else
+ return FALSE
+
+/obj/machinery/chem_master/attack_ai(mob/user)
+ return attack_hand(user)
+
+/obj/machinery/chem_master/proc/isgoodnumber(num)
+ if(isnum(num))
+ if(num > 200)
+ num = 200
+ else if(num < 0)
+ num = 1
+ return num
+ else
+ return FALSE
+
+// /obj/machinery/chem_master/proc/chemical_safety_check(datum/reagents/R)
+// var/all_safe = TRUE
+// for(var/datum/reagent/A in R.reagent_list)
+// if(!GLOB.safe_chem_list.Find(A.id))
+// all_safe = FALSE
+// return all_safe
+
+/obj/machinery/chem_master/condimaster
+ name = "CondiMaster 3000"
+ condi = 1
\ No newline at end of file
diff --git a/code/modules/reagents/machinery/chemalyzer.dm b/code/modules/reagents/machinery/chemalyzer.dm
new file mode 100644
index 0000000000..ce8b1d6f12
--- /dev/null
+++ b/code/modules/reagents/machinery/chemalyzer.dm
@@ -0,0 +1,63 @@
+// Detects reagents inside most containers, and acts as an infinite identification system for reagent-based unidentified objects.
+
+/obj/machinery/chemical_analyzer
+ name = "chem analyzer"
+ desc = "Used to precisely scan chemicals and other liquids inside various containers. \
+ It may also identify the liquid contents of unknown objects."
+ description_info = "This machine will try to tell you what reagents are inside of something capable of holding reagents. \
+ It is also used to 'identify' specific reagent-based objects with their properties obscured from inspection by normal means."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "chem_analyzer"
+ density = TRUE
+ anchored = TRUE
+ use_power = TRUE
+ idle_power_usage = 20
+ clicksound = "button"
+ var/analyzing = FALSE
+
+/obj/machinery/chemical_analyzer/update_icon()
+ icon_state = "chem_analyzer[analyzing ? "-working":""]"
+
+/obj/machinery/chemical_analyzer/attackby(obj/item/I, mob/living/user)
+ if(!istype(I))
+ return ..()
+
+ if(default_deconstruction_screwdriver(user, I))
+ return
+ if(default_deconstruction_crowbar(user, I))
+ return
+
+ if(istype(I,/obj/item/weapon/reagent_containers))
+ analyzing = TRUE
+ update_icon()
+ to_chat(user, span("notice", "Analyzing \the [I], please stand by..."))
+
+ if(!do_after(user, 2 SECONDS, src))
+ to_chat(user, span("warning", "Sample moved outside of scan range, please try again and remain still."))
+ analyzing = FALSE
+ update_icon()
+ return
+
+ // First, identify it if it isn't already.
+ if(!I.is_identified(IDENTITY_FULL))
+ var/datum/identification/ID = I.identity
+ if(ID.identification_type == IDENTITY_TYPE_CHEMICAL) // This only solves chemical-based mysteries.
+ I.identify(IDENTITY_FULL, user)
+
+ // Now tell us everything that is inside.
+ if(I.reagents && I.reagents.reagent_list.len)
+ to_chat(user, "
") // To add padding between regular chat and the output.
+ for(var/datum/reagent/R in I.reagents.reagent_list)
+ if(!R.name)
+ continue
+ to_chat(user, span("notice", "Contains [R.volume]u of [R.name].
[R.description]
"))
+
+ // Last, unseal it if it's an autoinjector.
+ if(istype(I,/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector) && !(I.flags & OPENCONTAINER))
+ I.flags |= OPENCONTAINER
+ to_chat(user, span("notice", "Sample container unsealed.
"))
+
+ to_chat(user, span("notice", "Scanning of \the [I] complete."))
+ analyzing = FALSE
+ update_icon()
+ return
\ No newline at end of file
diff --git a/code/modules/reagents/dispenser/_defines.dm b/code/modules/reagents/machinery/dispenser/_defines.dm
similarity index 96%
rename from code/modules/reagents/dispenser/_defines.dm
rename to code/modules/reagents/machinery/dispenser/_defines.dm
index 60c12cdba6..8d52cf5cd0 100644
--- a/code/modules/reagents/dispenser/_defines.dm
+++ b/code/modules/reagents/machinery/dispenser/_defines.dm
@@ -1,8 +1,8 @@
-#define CARTRIDGE_VOLUME_LARGE 500
-#define CARTRIDGE_VOLUME_MEDIUM 250
-#define CARTRIDGE_VOLUME_SMALL 100
-
-// Chemistry dispenser starts with 21
-// ERT dispenser starts with 28
-#define DISPENSER_MAX_CARTRIDGES 30
-
+#define CARTRIDGE_VOLUME_LARGE 500
+#define CARTRIDGE_VOLUME_MEDIUM 250
+#define CARTRIDGE_VOLUME_SMALL 100
+
+// Chemistry dispenser starts with 21
+// ERT dispenser starts with 28
+#define DISPENSER_MAX_CARTRIDGES 30
+
diff --git a/code/modules/reagents/dispenser/cartridge.dm b/code/modules/reagents/machinery/dispenser/cartridge.dm
similarity index 97%
rename from code/modules/reagents/dispenser/cartridge.dm
rename to code/modules/reagents/machinery/dispenser/cartridge.dm
index 444577aaa5..0e2b09eb57 100644
--- a/code/modules/reagents/dispenser/cartridge.dm
+++ b/code/modules/reagents/machinery/dispenser/cartridge.dm
@@ -1,95 +1,95 @@
-/obj/item/weapon/reagent_containers/chem_disp_cartridge
- name = "chemical dispenser cartridge"
- desc = "This goes in a chemical dispenser."
- icon_state = "cartridge"
-
- w_class = ITEMSIZE_NORMAL
-
- volume = CARTRIDGE_VOLUME_LARGE
- amount_per_transfer_from_this = 50
- // Large, but inaccurate. Use a chem dispenser or beaker for accuracy.
- possible_transfer_amounts = list(50, 100, 250, 500)
- unacidable = 1
-
- var/spawn_reagent = null
- var/label = ""
-
-/obj/item/weapon/reagent_containers/chem_disp_cartridge/Initialize()
- . = ..()
- if(spawn_reagent)
- reagents.add_reagent(spawn_reagent, volume)
- var/datum/reagent/R = SSchemistry.chemical_reagents[spawn_reagent]
- setLabel(R.name)
-
-/obj/item/weapon/reagent_containers/chem_disp_cartridge/examine(mob/user)
- . = ..()
- . += "It has a capacity of [volume] units."
- if(reagents.total_volume <= 0)
- . += "It is empty."
- else
- . += "It contains [reagents.total_volume] units of liquid."
- if(!is_open_container())
- . += "The cap is sealed."
-
-/obj/item/weapon/reagent_containers/chem_disp_cartridge/verb/verb_set_label(L as text)
- set name = "Set Cartridge Label"
- set category = "Object"
- set src in view(usr, 1)
-
- setLabel(L, usr)
-
-/obj/item/weapon/reagent_containers/chem_disp_cartridge/proc/setLabel(L, mob/user = null)
- if(L)
- if(user)
- to_chat(user, "You set the label on \the [src] to '[L]'.")
-
- label = L
- name = "[initial(name)] - '[L]'"
- else
- if(user)
- to_chat(user, "You clear the label on \the [src].")
- label = ""
- name = initial(name)
-
-/obj/item/weapon/reagent_containers/chem_disp_cartridge/attack_self()
- ..()
- if (is_open_container())
- to_chat(usr, "You put the cap on \the [src].")
- flags ^= OPENCONTAINER
- else
- to_chat(usr, "You take the cap off \the [src].")
- flags |= OPENCONTAINER
-
-/obj/item/weapon/reagent_containers/chem_disp_cartridge/afterattack(obj/target, mob/user , flag)
- if (!is_open_container() || !flag)
- return
-
- else if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us.
- target.add_fingerprint(user)
-
- if(!target.reagents.total_volume && target.reagents)
- to_chat(user, "\The [target] is empty.")
- return
-
- if(reagents.total_volume >= reagents.maximum_volume)
- to_chat(user, "\The [src] is full.")
- return
-
- var/trans = target.reagents.trans_to(src, target:amount_per_transfer_from_this)
- to_chat(user, "You fill \the [src] with [trans] units of the contents of \the [target].")
-
- else if(target.is_open_container() && target.reagents) //Something like a glass. Player probably wants to transfer TO it.
-
- if(!reagents.total_volume)
- to_chat(user, "\The [src] is empty.")
- return
-
- if(target.reagents.total_volume >= target.reagents.maximum_volume)
- to_chat(user, "\The [target] is full.")
- return
-
- var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
- to_chat(user, "You transfer [trans] units of the solution to \the [target].")
-
- else
- return ..()
+/obj/item/weapon/reagent_containers/chem_disp_cartridge
+ name = "chemical dispenser cartridge"
+ desc = "This goes in a chemical dispenser."
+ icon_state = "cartridge"
+
+ w_class = ITEMSIZE_NORMAL
+
+ volume = CARTRIDGE_VOLUME_LARGE
+ amount_per_transfer_from_this = 50
+ // Large, but inaccurate. Use a chem dispenser or beaker for accuracy.
+ possible_transfer_amounts = list(50, 100, 250, 500)
+ unacidable = 1
+
+ var/spawn_reagent = null
+ var/label = ""
+
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/Initialize()
+ . = ..()
+ if(spawn_reagent)
+ reagents.add_reagent(spawn_reagent, volume)
+ var/datum/reagent/R = SSchemistry.chemical_reagents[spawn_reagent]
+ setLabel(R.name)
+
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/examine(mob/user)
+ . = ..()
+ . += "It has a capacity of [volume] units."
+ if(reagents.total_volume <= 0)
+ . += "It is empty."
+ else
+ . += "It contains [reagents.total_volume] units of liquid."
+ if(!is_open_container())
+ . += "The cap is sealed."
+
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/verb/verb_set_label(L as text)
+ set name = "Set Cartridge Label"
+ set category = "Object"
+ set src in view(usr, 1)
+
+ setLabel(L, usr)
+
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/proc/setLabel(L, mob/user = null)
+ if(L)
+ if(user)
+ to_chat(user, "You set the label on \the [src] to '[L]'.")
+
+ label = L
+ name = "[initial(name)] - '[L]'"
+ else
+ if(user)
+ to_chat(user, "You clear the label on \the [src].")
+ label = ""
+ name = initial(name)
+
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/attack_self()
+ ..()
+ if (is_open_container())
+ to_chat(usr, "You put the cap on \the [src].")
+ flags ^= OPENCONTAINER
+ else
+ to_chat(usr, "You take the cap off \the [src].")
+ flags |= OPENCONTAINER
+
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/afterattack(obj/target, mob/user , flag)
+ if (!is_open_container() || !flag)
+ return
+
+ else if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us.
+ target.add_fingerprint(user)
+
+ if(!target.reagents.total_volume && target.reagents)
+ to_chat(user, "\The [target] is empty.")
+ return
+
+ if(reagents.total_volume >= reagents.maximum_volume)
+ to_chat(user, "\The [src] is full.")
+ return
+
+ var/trans = target.reagents.trans_to(src, target:amount_per_transfer_from_this)
+ to_chat(user, "You fill \the [src] with [trans] units of the contents of \the [target].")
+
+ else if(target.is_open_container() && target.reagents) //Something like a glass. Player probably wants to transfer TO it.
+
+ if(!reagents.total_volume)
+ to_chat(user, "\The [src] is empty.")
+ return
+
+ if(target.reagents.total_volume >= target.reagents.maximum_volume)
+ to_chat(user, "\The [target] is full.")
+ return
+
+ var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
+ to_chat(user, "You transfer [trans] units of the solution to \the [target].")
+
+ else
+ return ..()
diff --git a/code/modules/reagents/dispenser/cartridge_presets.dm b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm
similarity index 97%
rename from code/modules/reagents/dispenser/cartridge_presets.dm
rename to code/modules/reagents/machinery/dispenser/cartridge_presets.dm
index eea22fff7e..21b321ad34 100644
--- a/code/modules/reagents/dispenser/cartridge_presets.dm
+++ b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm
@@ -1,108 +1,108 @@
-/obj/item/weapon/reagent_containers/chem_disp_cartridge
- small
- volume = CARTRIDGE_VOLUME_SMALL
-
- medium
- volume = CARTRIDGE_VOLUME_MEDIUM
-
- // Multiple
- water spawn_reagent = "water"
- sugar spawn_reagent = "sugar"
-
- // Chemistry
- hydrogen spawn_reagent = "hydrogen"
- lithium spawn_reagent = "lithium"
- carbon spawn_reagent = "carbon"
- nitrogen spawn_reagent = "nitrogen"
- oxygen spawn_reagent = "oxygen"
- fluorine spawn_reagent = "fluorine"
- sodium spawn_reagent = "sodium"
- aluminum spawn_reagent = "aluminum"
- silicon spawn_reagent = "silicon"
- phosphorus spawn_reagent = "phosphorus"
- sulfur spawn_reagent = "sulfur"
- chlorine spawn_reagent = "chlorine"
- potassium spawn_reagent = "potassium"
- iron spawn_reagent = "iron"
- copper spawn_reagent = "copper"
- mercury spawn_reagent = "mercury"
- radium spawn_reagent = "radium"
- ethanol spawn_reagent = "ethanol"
- sacid spawn_reagent = "sacid"
- tungsten spawn_reagent = "tungsten"
- calcium spawn_reagent = "calcium"
-
- // Bar, alcoholic
- beer spawn_reagent = "beer"
- kahlua spawn_reagent = "kahlua"
- whiskey spawn_reagent = "whiskey"
- wine spawn_reagent = "wine"
- vodka spawn_reagent = "vodka"
- gin spawn_reagent = "gin"
- rum spawn_reagent = "rum"
- tequila spawn_reagent = "tequilla"
- vermouth spawn_reagent = "vermouth"
- cognac spawn_reagent = "cognac"
- ale spawn_reagent = "ale"
- mead spawn_reagent = "mead"
- bitters spawn_reagent = "bitters"
- cider spawn_reagent = "cider"
-
- // Bar, soft
- ice spawn_reagent = "ice"
- tea spawn_reagent = "tea"
- icetea spawn_reagent = "icetea"
- cola spawn_reagent = "cola"
- smw spawn_reagent = "spacemountainwind"
- dr_gibb spawn_reagent = "dr_gibb"
- spaceup spawn_reagent = "space_up"
- tonic spawn_reagent = "tonic"
- sodawater spawn_reagent = "sodawater"
- lemon_lime spawn_reagent = "lemon_lime"
- orange spawn_reagent = "orangejuice"
- lime spawn_reagent = "limejuice"
- watermelon spawn_reagent = "watermelonjuice"
- lemon spawn_reagent = "lemonjuice"
-
- // Bar, coffee
- coffee spawn_reagent = "coffee"
- cafe_latte spawn_reagent = "cafe_latte"
- soy_latte spawn_reagent = "soy_latte"
- hot_coco spawn_reagent = "hot_coco"
- milk spawn_reagent = "milk"
- cream spawn_reagent = "cream"
- mint spawn_reagent = "mint"
- berry spawn_reagent = "berryjuice"
- greentea spawn_reagent = "greentea"
- decaf spawn_reagent = "decaf"
-
- // ERT
- inaprov spawn_reagent = "inaprovaline"
- ryetalyn spawn_reagent = "ryetalyn"
- paracetamol spawn_reagent = "paracetamol"
- tramadol spawn_reagent = "tramadol"
- oxycodone spawn_reagent = "oxycodone"
- sterilizine spawn_reagent = "sterilizine"
- leporazine spawn_reagent = "leporazine"
- kelotane spawn_reagent = "kelotane"
- dermaline spawn_reagent = "dermaline"
- dexalin spawn_reagent = "dexalin"
- dexalin/small volume = CARTRIDGE_VOLUME_SMALL // For the medicine cartridge crate, so it's not too easy to get large amounts of dexalin
- dexalin_p spawn_reagent = "dexalinp"
- tricord spawn_reagent = "tricordrazine"
- dylovene spawn_reagent = "anti_toxin"
- synaptizine spawn_reagent = "synaptizine"
- hyronalin spawn_reagent = "hyronalin"
- arithrazine spawn_reagent = "arithrazine"
- alkysine spawn_reagent = "alkysine"
- imidazoline spawn_reagent = "imidazoline"
- peridaxon spawn_reagent = "peridaxon"
- bicaridine spawn_reagent = "bicaridine"
- hyperzine spawn_reagent = "hyperzine"
- rezadone spawn_reagent = "rezadone"
- spaceacillin spawn_reagent = "spaceacillin"
- ethylredox spawn_reagent = "ethylredoxrazine"
- sleeptox spawn_reagent = "stoxin"
- chloral spawn_reagent = "chloralhydrate"
- cryoxadone spawn_reagent = "cryoxadone"
- clonexadone spawn_reagent = "clonexadone"
+/obj/item/weapon/reagent_containers/chem_disp_cartridge
+ small
+ volume = CARTRIDGE_VOLUME_SMALL
+
+ medium
+ volume = CARTRIDGE_VOLUME_MEDIUM
+
+ // Multiple
+ water spawn_reagent = "water"
+ sugar spawn_reagent = "sugar"
+
+ // Chemistry
+ hydrogen spawn_reagent = "hydrogen"
+ lithium spawn_reagent = "lithium"
+ carbon spawn_reagent = "carbon"
+ nitrogen spawn_reagent = "nitrogen"
+ oxygen spawn_reagent = "oxygen"
+ fluorine spawn_reagent = "fluorine"
+ sodium spawn_reagent = "sodium"
+ aluminum spawn_reagent = "aluminum"
+ silicon spawn_reagent = "silicon"
+ phosphorus spawn_reagent = "phosphorus"
+ sulfur spawn_reagent = "sulfur"
+ chlorine spawn_reagent = "chlorine"
+ potassium spawn_reagent = "potassium"
+ iron spawn_reagent = "iron"
+ copper spawn_reagent = "copper"
+ mercury spawn_reagent = "mercury"
+ radium spawn_reagent = "radium"
+ ethanol spawn_reagent = "ethanol"
+ sacid spawn_reagent = "sacid"
+ tungsten spawn_reagent = "tungsten"
+ calcium spawn_reagent = "calcium"
+
+ // Bar, alcoholic
+ beer spawn_reagent = "beer"
+ kahlua spawn_reagent = "kahlua"
+ whiskey spawn_reagent = "whiskey"
+ wine spawn_reagent = "wine"
+ vodka spawn_reagent = "vodka"
+ gin spawn_reagent = "gin"
+ rum spawn_reagent = "rum"
+ tequila spawn_reagent = "tequilla"
+ vermouth spawn_reagent = "vermouth"
+ cognac spawn_reagent = "cognac"
+ ale spawn_reagent = "ale"
+ mead spawn_reagent = "mead"
+ bitters spawn_reagent = "bitters"
+ cider spawn_reagent = "cider"
+
+ // Bar, soft
+ ice spawn_reagent = "ice"
+ tea spawn_reagent = "tea"
+ icetea spawn_reagent = "icetea"
+ cola spawn_reagent = "cola"
+ smw spawn_reagent = "spacemountainwind"
+ dr_gibb spawn_reagent = "dr_gibb"
+ spaceup spawn_reagent = "space_up"
+ tonic spawn_reagent = "tonic"
+ sodawater spawn_reagent = "sodawater"
+ lemon_lime spawn_reagent = "lemon_lime"
+ orange spawn_reagent = "orangejuice"
+ lime spawn_reagent = "limejuice"
+ watermelon spawn_reagent = "watermelonjuice"
+ lemon spawn_reagent = "lemonjuice"
+
+ // Bar, coffee
+ coffee spawn_reagent = "coffee"
+ cafe_latte spawn_reagent = "cafe_latte"
+ soy_latte spawn_reagent = "soy_latte"
+ hot_coco spawn_reagent = "hot_coco"
+ milk spawn_reagent = "milk"
+ cream spawn_reagent = "cream"
+ mint spawn_reagent = "mint"
+ berry spawn_reagent = "berryjuice"
+ greentea spawn_reagent = "greentea"
+ decaf spawn_reagent = "decaf"
+
+ // ERT
+ inaprov spawn_reagent = "inaprovaline"
+ ryetalyn spawn_reagent = "ryetalyn"
+ paracetamol spawn_reagent = "paracetamol"
+ tramadol spawn_reagent = "tramadol"
+ oxycodone spawn_reagent = "oxycodone"
+ sterilizine spawn_reagent = "sterilizine"
+ leporazine spawn_reagent = "leporazine"
+ kelotane spawn_reagent = "kelotane"
+ dermaline spawn_reagent = "dermaline"
+ dexalin spawn_reagent = "dexalin"
+ dexalin/small volume = CARTRIDGE_VOLUME_SMALL // For the medicine cartridge crate, so it's not too easy to get large amounts of dexalin
+ dexalin_p spawn_reagent = "dexalinp"
+ tricord spawn_reagent = "tricordrazine"
+ dylovene spawn_reagent = "anti_toxin"
+ synaptizine spawn_reagent = "synaptizine"
+ hyronalin spawn_reagent = "hyronalin"
+ arithrazine spawn_reagent = "arithrazine"
+ alkysine spawn_reagent = "alkysine"
+ imidazoline spawn_reagent = "imidazoline"
+ peridaxon spawn_reagent = "peridaxon"
+ bicaridine spawn_reagent = "bicaridine"
+ hyperzine spawn_reagent = "hyperzine"
+ rezadone spawn_reagent = "rezadone"
+ spaceacillin spawn_reagent = "spaceacillin"
+ ethylredox spawn_reagent = "ethylredoxrazine"
+ sleeptox spawn_reagent = "stoxin"
+ chloral spawn_reagent = "chloralhydrate"
+ cryoxadone spawn_reagent = "cryoxadone"
+ clonexadone spawn_reagent = "clonexadone"
diff --git a/code/modules/reagents/dispenser/cartridge_spawn.dm b/code/modules/reagents/machinery/dispenser/cartridge_spawn.dm
similarity index 100%
rename from code/modules/reagents/dispenser/cartridge_spawn.dm
rename to code/modules/reagents/machinery/dispenser/cartridge_spawn.dm
diff --git a/code/modules/reagents/dispenser/dispenser2.dm b/code/modules/reagents/machinery/dispenser/dispenser2.dm
similarity index 97%
rename from code/modules/reagents/dispenser/dispenser2.dm
rename to code/modules/reagents/machinery/dispenser/dispenser2.dm
index 7f2fb13f40..d53dac4ba5 100644
--- a/code/modules/reagents/dispenser/dispenser2.dm
+++ b/code/modules/reagents/machinery/dispenser/dispenser2.dm
@@ -1,205 +1,205 @@
-/obj/machinery/chemical_dispenser
- name = "chemical dispenser"
- desc = "Automagically fabricates chemicals from electricity."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "dispenser"
- clicksound = "switch"
-
- var/list/spawn_cartridges = null // Set to a list of types to spawn one of each on New()
-
- var/list/cartridges = list() // Associative, label -> cartridge
- var/obj/item/weapon/reagent_containers/container = null
-
- var/ui_title = "Chemical Dispenser"
-
- var/accept_drinking = 0
- var/amount = 30
-
- use_power = USE_POWER_IDLE
- idle_power_usage = 100
- anchored = 1
-
-/obj/machinery/chemical_dispenser/Initialize()
- . = ..()
- if(spawn_cartridges)
- for(var/type in spawn_cartridges)
- add_cartridge(new type(src))
-
-/obj/machinery/chemical_dispenser/examine(mob/user)
- . = ..()
- . += "It has [cartridges.len] cartridges installed, and has space for [DISPENSER_MAX_CARTRIDGES - cartridges.len] more."
-
-/obj/machinery/chemical_dispenser/verb/rotate_clockwise()
- set name = "Rotate Dispenser Clockwise"
- set category = "Object"
- set src in oview(1)
-
- if (src.anchored || usr:stat)
- to_chat(usr, "It is fastened down!")
- return 0
- src.set_dir(turn(src.dir, 270))
- return 1
-
-/obj/machinery/chemical_dispenser/proc/add_cartridge(obj/item/weapon/reagent_containers/chem_disp_cartridge/C, mob/user)
- if(!istype(C))
- if(user)
- to_chat(user, "\The [C] will not fit in \the [src]!")
- return
-
- if(cartridges.len >= DISPENSER_MAX_CARTRIDGES)
- if(user)
- to_chat(user, "\The [src] does not have any slots open for \the [C] to fit into!")
- return
-
- if(!C.label)
- if(user)
- to_chat(user, "\The [C] does not have a label!")
- return
-
- if(cartridges[C.label])
- if(user)
- to_chat(user, "\The [src] already contains a cartridge with that label!")
- return
-
- if(user)
- user.drop_from_inventory(C)
- to_chat(user, "You add \the [C] to \the [src].")
-
- C.loc = src
- cartridges[C.label] = C
- cartridges = sortAssoc(cartridges)
- SStgui.update_uis(src)
-
-/obj/machinery/chemical_dispenser/proc/remove_cartridge(label)
- . = cartridges[label]
- cartridges -= label
- SStgui.update_uis(src)
-
-/obj/machinery/chemical_dispenser/attackby(obj/item/weapon/W, mob/user)
- if(W.is_wrench())
- playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to [anchored ? "un" : ""]fasten \the [src].")
- if (do_after(user, 20 * W.toolspeed))
- user.visible_message(
- "\The [user] [anchored ? "un" : ""]fastens \the [src].",
- "You have [anchored ? "un" : ""]fastened \the [src].",
- "You hear a ratchet.")
- anchored = !anchored
- else
- to_chat(user, "You decide not to [anchored ? "un" : ""]fasten \the [src].")
-
- else if(istype(W, /obj/item/weapon/reagent_containers/chem_disp_cartridge))
- add_cartridge(W, user)
-
- else if(W.is_screwdriver())
- var/label = input(user, "Which cartridge would you like to remove?", "Chemical Dispenser") as null|anything in cartridges
- if(!label) return
- var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = remove_cartridge(label)
- if(C)
- to_chat(user, "You remove \the [C] from \the [src].")
- C.loc = loc
- playsound(src, W.usesound, 50, 1)
-
- else if(istype(W, /obj/item/weapon/reagent_containers/glass) || istype(W, /obj/item/weapon/reagent_containers/food))
- if(container)
- to_chat(user, "There is already \a [container] on \the [src]!")
- return
-
- var/obj/item/weapon/reagent_containers/RC = W
-
- if(!accept_drinking && istype(RC,/obj/item/weapon/reagent_containers/food))
- to_chat(user, "This machine only accepts beakers!")
- return
-
- if(!RC.is_open_container())
- to_chat(user, "You don't see how \the [src] could dispense reagents into \the [RC].")
- return
-
- container = RC
- user.drop_from_inventory(RC)
- RC.loc = src
- to_chat(user, "You set \the [RC] on \the [src].")
- else
- return ..()
-
-/obj/machinery/chemical_dispenser/tgui_interact(mob/user, datum/tgui/ui = null)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "ChemDispenser", ui_title) // 390, 655
- ui.open()
-
-/obj/machinery/chemical_dispenser/tgui_data(mob/user)
- var/data[0]
- data["amount"] = amount
- data["isBeakerLoaded"] = container ? 1 : 0
- data["glass"] = accept_drinking
-
- var/beakerContents[0]
- if(container && container.reagents && container.reagents.reagent_list.len)
- for(var/datum/reagent/R in container.reagents.reagent_list)
- beakerContents.Add(list(list("name" = R.name, "id" = R.id, "volume" = R.volume))) // list in a list because Byond merges the first list...
- data["beakerContents"] = beakerContents
-
- if(container)
- data["beakerCurrentVolume"] = container.reagents.total_volume
- data["beakerMaxVolume"] = container.reagents.maximum_volume
- else
- data["beakerCurrentVolume"] = null
- data["beakerMaxVolume"] = null
-
- var/chemicals[0]
- for(var/label in cartridges)
- var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
- chemicals.Add(list(list("title" = label, "id" = label, "amount" = C.reagents.total_volume))) // list in a list because Byond merges the first list...
- data["chemicals"] = chemicals
- return data
-
-/obj/machinery/chemical_dispenser/tgui_act(action, params)
- if(..())
- return TRUE
-
- . = TRUE
- switch(action)
- if("amount")
- amount = clamp(round(text2num(params["amount"]), 1), 0, 120) // round to nearest 1 and clamp 0 - 120
- if("dispense")
- var/label = params["reagent"]
- if(cartridges[label] && container && container.is_open_container())
- var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
- playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1)
- C.reagents.trans_to(container, amount)
- if("remove")
- var/amount = text2num(params["amount"])
- if(!container || !amount)
- return
- var/datum/reagents/R = container.reagents
- var/id = params["reagent"]
- if(amount > 0)
- R.remove_reagent(id, amount)
- else if(amount == -1) // Isolate
- R.isolate_reagent(id)
- if("ejectBeaker")
- if(container)
- container.forceMove(get_turf(src))
-
- if(Adjacent(usr)) // So the AI doesn't get a beaker somehow.
- usr.put_in_hands(container)
-
- container = null
- else
- return FALSE
-
- add_fingerprint(usr)
-
-/obj/machinery/chemical_dispenser/attack_ghost(mob/user)
- if(stat & BROKEN)
- return
- tgui_interact(user)
-
-/obj/machinery/chemical_dispenser/attack_ai(mob/user)
- attack_hand(user)
-
-/obj/machinery/chemical_dispenser/attack_hand(mob/user)
- if(stat & BROKEN)
- return
- tgui_interact(user)
+/obj/machinery/chemical_dispenser
+ name = "chemical dispenser"
+ desc = "Automagically fabricates chemicals from electricity."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "dispenser"
+ clicksound = "switch"
+
+ var/list/spawn_cartridges = null // Set to a list of types to spawn one of each on New()
+
+ var/list/cartridges = list() // Associative, label -> cartridge
+ var/obj/item/weapon/reagent_containers/container = null
+
+ var/ui_title = "Chemical Dispenser"
+
+ var/accept_drinking = 0
+ var/amount = 30
+
+ use_power = USE_POWER_IDLE
+ idle_power_usage = 100
+ anchored = 1
+
+/obj/machinery/chemical_dispenser/Initialize()
+ . = ..()
+ if(spawn_cartridges)
+ for(var/type in spawn_cartridges)
+ add_cartridge(new type(src))
+
+/obj/machinery/chemical_dispenser/examine(mob/user)
+ . = ..()
+ . += "It has [cartridges.len] cartridges installed, and has space for [DISPENSER_MAX_CARTRIDGES - cartridges.len] more."
+
+/obj/machinery/chemical_dispenser/verb/rotate_clockwise()
+ set name = "Rotate Dispenser Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.anchored || usr:stat)
+ to_chat(usr, "It is fastened down!")
+ return 0
+ src.set_dir(turn(src.dir, 270))
+ return 1
+
+/obj/machinery/chemical_dispenser/proc/add_cartridge(obj/item/weapon/reagent_containers/chem_disp_cartridge/C, mob/user)
+ if(!istype(C))
+ if(user)
+ to_chat(user, "\The [C] will not fit in \the [src]!")
+ return
+
+ if(cartridges.len >= DISPENSER_MAX_CARTRIDGES)
+ if(user)
+ to_chat(user, "\The [src] does not have any slots open for \the [C] to fit into!")
+ return
+
+ if(!C.label)
+ if(user)
+ to_chat(user, "\The [C] does not have a label!")
+ return
+
+ if(cartridges[C.label])
+ if(user)
+ to_chat(user, "\The [src] already contains a cartridge with that label!")
+ return
+
+ if(user)
+ user.drop_from_inventory(C)
+ to_chat(user, "You add \the [C] to \the [src].")
+
+ C.loc = src
+ cartridges[C.label] = C
+ cartridges = sortAssoc(cartridges)
+ SStgui.update_uis(src)
+
+/obj/machinery/chemical_dispenser/proc/remove_cartridge(label)
+ . = cartridges[label]
+ cartridges -= label
+ SStgui.update_uis(src)
+
+/obj/machinery/chemical_dispenser/attackby(obj/item/weapon/W, mob/user)
+ if(W.is_wrench())
+ playsound(src, W.usesound, 50, 1)
+ to_chat(user, "You begin to [anchored ? "un" : ""]fasten \the [src].")
+ if (do_after(user, 20 * W.toolspeed))
+ user.visible_message(
+ "\The [user] [anchored ? "un" : ""]fastens \the [src].",
+ "You have [anchored ? "un" : ""]fastened \the [src].",
+ "You hear a ratchet.")
+ anchored = !anchored
+ else
+ to_chat(user, "You decide not to [anchored ? "un" : ""]fasten \the [src].")
+
+ else if(istype(W, /obj/item/weapon/reagent_containers/chem_disp_cartridge))
+ add_cartridge(W, user)
+
+ else if(W.is_screwdriver())
+ var/label = input(user, "Which cartridge would you like to remove?", "Chemical Dispenser") as null|anything in cartridges
+ if(!label) return
+ var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = remove_cartridge(label)
+ if(C)
+ to_chat(user, "You remove \the [C] from \the [src].")
+ C.loc = loc
+ playsound(src, W.usesound, 50, 1)
+
+ else if(istype(W, /obj/item/weapon/reagent_containers/glass) || istype(W, /obj/item/weapon/reagent_containers/food))
+ if(container)
+ to_chat(user, "There is already \a [container] on \the [src]!")
+ return
+
+ var/obj/item/weapon/reagent_containers/RC = W
+
+ if(!accept_drinking && istype(RC,/obj/item/weapon/reagent_containers/food))
+ to_chat(user, "This machine only accepts beakers!")
+ return
+
+ if(!RC.is_open_container())
+ to_chat(user, "You don't see how \the [src] could dispense reagents into \the [RC].")
+ return
+
+ container = RC
+ user.drop_from_inventory(RC)
+ RC.loc = src
+ to_chat(user, "You set \the [RC] on \the [src].")
+ else
+ return ..()
+
+/obj/machinery/chemical_dispenser/tgui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemDispenser", ui_title) // 390, 655
+ ui.open()
+
+/obj/machinery/chemical_dispenser/tgui_data(mob/user)
+ var/data[0]
+ data["amount"] = amount
+ data["isBeakerLoaded"] = container ? 1 : 0
+ data["glass"] = accept_drinking
+
+ var/beakerContents[0]
+ if(container && container.reagents && container.reagents.reagent_list.len)
+ for(var/datum/reagent/R in container.reagents.reagent_list)
+ beakerContents.Add(list(list("name" = R.name, "id" = R.id, "volume" = R.volume))) // list in a list because Byond merges the first list...
+ data["beakerContents"] = beakerContents
+
+ if(container)
+ data["beakerCurrentVolume"] = container.reagents.total_volume
+ data["beakerMaxVolume"] = container.reagents.maximum_volume
+ else
+ data["beakerCurrentVolume"] = null
+ data["beakerMaxVolume"] = null
+
+ var/chemicals[0]
+ for(var/label in cartridges)
+ var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
+ chemicals.Add(list(list("title" = label, "id" = label, "amount" = C.reagents.total_volume))) // list in a list because Byond merges the first list...
+ data["chemicals"] = chemicals
+ return data
+
+/obj/machinery/chemical_dispenser/tgui_act(action, params)
+ if(..())
+ return TRUE
+
+ . = TRUE
+ switch(action)
+ if("amount")
+ amount = clamp(round(text2num(params["amount"]), 1), 0, 120) // round to nearest 1 and clamp 0 - 120
+ if("dispense")
+ var/label = params["reagent"]
+ if(cartridges[label] && container && container.is_open_container())
+ var/obj/item/weapon/reagent_containers/chem_disp_cartridge/C = cartridges[label]
+ playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1)
+ C.reagents.trans_to(container, amount)
+ if("remove")
+ var/amount = text2num(params["amount"])
+ if(!container || !amount)
+ return
+ var/datum/reagents/R = container.reagents
+ var/id = params["reagent"]
+ if(amount > 0)
+ R.remove_reagent(id, amount)
+ else if(amount == -1) // Isolate
+ R.isolate_reagent(id)
+ if("ejectBeaker")
+ if(container)
+ container.forceMove(get_turf(src))
+
+ if(Adjacent(usr)) // So the AI doesn't get a beaker somehow.
+ usr.put_in_hands(container)
+
+ container = null
+ else
+ return FALSE
+
+ add_fingerprint(usr)
+
+/obj/machinery/chemical_dispenser/attack_ghost(mob/user)
+ if(stat & BROKEN)
+ return
+ tgui_interact(user)
+
+/obj/machinery/chemical_dispenser/attack_ai(mob/user)
+ attack_hand(user)
+
+/obj/machinery/chemical_dispenser/attack_hand(mob/user)
+ if(stat & BROKEN)
+ return
+ tgui_interact(user)
diff --git a/code/modules/reagents/dispenser/dispenser2_energy.dm b/code/modules/reagents/machinery/dispenser/dispenser2_energy.dm
similarity index 100%
rename from code/modules/reagents/dispenser/dispenser2_energy.dm
rename to code/modules/reagents/machinery/dispenser/dispenser2_energy.dm
diff --git a/code/modules/reagents/dispenser/dispenser_presets.dm b/code/modules/reagents/machinery/dispenser/dispenser_presets.dm
similarity index 98%
rename from code/modules/reagents/dispenser/dispenser_presets.dm
rename to code/modules/reagents/machinery/dispenser/dispenser_presets.dm
index 6916903048..6b90357a2c 100644
--- a/code/modules/reagents/dispenser/dispenser_presets.dm
+++ b/code/modules/reagents/machinery/dispenser/dispenser_presets.dm
@@ -1,144 +1,144 @@
-/obj/machinery/chemical_dispenser/full
- spawn_cartridges = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/hydrogen,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lithium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/carbon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/nitrogen,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxygen,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/fluorine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/aluminum,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/silicon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/phosphorus,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sulfur,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/chlorine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/potassium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/iron,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/copper,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/mercury,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/radium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethanol,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sacid,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tungsten,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/calcium
- )
-
-/obj/machinery/chemical_dispenser/ert
- name = "medicine dispenser"
- spawn_cartridges = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/inaprov,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ryetalyn,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/paracetamol,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tramadol,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxycodone,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sterilizine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/leporazine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/kelotane,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/dermaline,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/dexalin,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/dexalin_p,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tricord,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/dylovene,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/synaptizine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/hyronalin,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/arithrazine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/alkysine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/imidazoline,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/peridaxon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/bicaridine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/hyperzine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/rezadone,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceacillin,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethylredox,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sleeptox,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/chloral,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cryoxadone,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/clonexadone
- )
-
-/obj/machinery/chemical_dispenser/bar_soft
- name = "soft drink dispenser"
- desc = "A soda machine."
- icon_state = "soda_dispenser"
- ui_title = "Soda Dispenser"
- accept_drinking = 1
-
-/obj/machinery/chemical_dispenser/bar_soft/full
- spawn_cartridges = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/icetea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cola,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/smw,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/dr_gibb,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceup,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/watermelon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon
- )
-
-/obj/machinery/chemical_dispenser/bar_alc
- name = "booze dispenser"
- desc = "A beer machine. Like a soda machine, but more fun!"
- icon_state = "booze_dispenser"
- ui_title = "Booze Dispenser"
- accept_drinking = 1
-
-/obj/machinery/chemical_dispenser/bar_alc/full
- spawn_cartridges = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/beer,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/kahlua,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/whiskey,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/wine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/vodka,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/gin,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/rum,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tequila,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/vermouth,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cognac,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cider,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ale,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/mead
- )
-
-/obj/machinery/chemical_dispenser/bar_coffee
- name = "coffee dispenser"
- desc = "Driving crack dealers out of employment since 2280."
- icon_state = "coffee_dispenser"
- ui_title = "Coffee Dispenser"
- accept_drinking = 1
-
-/obj/machinery/chemical_dispenser/bar_coffee/full
- spawn_cartridges = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cafe_latte,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/soy_latte,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/hot_coco,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/milk,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/mint,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/berry,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/greentea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf
- )
+/obj/machinery/chemical_dispenser/full
+ spawn_cartridges = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/hydrogen,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lithium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/carbon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/nitrogen,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxygen,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/fluorine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/aluminum,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/silicon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/phosphorus,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sulfur,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/chlorine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/potassium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/iron,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/copper,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/mercury,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/radium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethanol,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sacid,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tungsten,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/calcium
+ )
+
+/obj/machinery/chemical_dispenser/ert
+ name = "medicine dispenser"
+ spawn_cartridges = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/inaprov,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ryetalyn,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/paracetamol,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tramadol,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxycodone,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sterilizine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/leporazine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/kelotane,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/dermaline,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/dexalin,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/dexalin_p,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tricord,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/dylovene,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/synaptizine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/hyronalin,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/arithrazine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/alkysine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/imidazoline,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/peridaxon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/bicaridine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/hyperzine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/rezadone,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceacillin,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethylredox,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sleeptox,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/chloral,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cryoxadone,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/clonexadone
+ )
+
+/obj/machinery/chemical_dispenser/bar_soft
+ name = "soft drink dispenser"
+ desc = "A soda machine."
+ icon_state = "soda_dispenser"
+ ui_title = "Soda Dispenser"
+ accept_drinking = 1
+
+/obj/machinery/chemical_dispenser/bar_soft/full
+ spawn_cartridges = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/icetea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cola,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/smw,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/dr_gibb,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceup,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/watermelon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon
+ )
+
+/obj/machinery/chemical_dispenser/bar_alc
+ name = "booze dispenser"
+ desc = "A beer machine. Like a soda machine, but more fun!"
+ icon_state = "booze_dispenser"
+ ui_title = "Booze Dispenser"
+ accept_drinking = 1
+
+/obj/machinery/chemical_dispenser/bar_alc/full
+ spawn_cartridges = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/beer,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/kahlua,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/whiskey,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/wine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/vodka,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/gin,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/rum,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tequila,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/vermouth,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cognac,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cider,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ale,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/mead
+ )
+
+/obj/machinery/chemical_dispenser/bar_coffee
+ name = "coffee dispenser"
+ desc = "Driving crack dealers out of employment since 2280."
+ icon_state = "coffee_dispenser"
+ ui_title = "Coffee Dispenser"
+ accept_drinking = 1
+
+/obj/machinery/chemical_dispenser/bar_coffee/full
+ spawn_cartridges = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cafe_latte,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/soy_latte,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/hot_coco,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/milk,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/mint,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/berry,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/greentea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf
+ )
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/machinery/dispenser/reagent_tank.dm
similarity index 97%
rename from code/modules/reagents/reagent_dispenser.dm
rename to code/modules/reagents/machinery/dispenser/reagent_tank.dm
index ae6ecf8505..91f7a24a6b 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/machinery/dispenser/reagent_tank.dm
@@ -1,431 +1,442 @@
-
-
-/obj/structure/reagent_dispensers
- name = "Dispenser"
- desc = "..."
- icon = 'icons/obj/objects.dmi'
- icon_state = "watertank"
- layer = TABLE_LAYER
- density = 1
- anchored = 0
- pressure_resistance = 2*ONE_ATMOSPHERE
-
- var/obj/item/hose_connector/input/active/InputSocket
- var/obj/item/hose_connector/output/active/OutputSocket
-
- var/amount_per_transfer_from_this = 10
- var/possible_transfer_amounts = list(10,25,50,100)
-
-/obj/structure/reagent_dispensers/attackby(obj/item/weapon/W as obj, mob/user as mob)
- return
-
-/obj/structure/reagent_dispensers/Destroy()
- QDEL_NULL(InputSocket)
- QDEL_NULL(OutputSocket)
-
- ..()
-
-/obj/structure/reagent_dispensers/Initialize()
- var/datum/reagents/R = new/datum/reagents(5000)
- reagents = R
- R.my_atom = src
- if (!possible_transfer_amounts)
- src.verbs -= /obj/structure/reagent_dispensers/verb/set_APTFT
-
- InputSocket = new(src)
- InputSocket.carrier = src
- OutputSocket = new(src)
- OutputSocket.carrier = src
-
- . = ..()
-
-/obj/structure/reagent_dispensers/examine(mob/user)
- . = ..()
- if(get_dist(user, src) <= 2)
- . += "It contains:"
- if(reagents && reagents.reagent_list.len)
- for(var/datum/reagent/R in reagents.reagent_list)
- . += "[R.volume] units of [R.name]"
- else
- . += "Nothing."
-
-/obj/structure/reagent_dispensers/verb/set_APTFT() //set amount_per_transfer_from_this
- set name = "Set transfer amount"
- set category = "Object"
- set src in view(1)
- var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts
- if (N)
- amount_per_transfer_from_this = N
-
-/obj/structure/reagent_dispensers/ex_act(severity)
- switch(severity)
- if(1.0)
- qdel(src)
- return
- if(2.0)
- if (prob(50))
- new /obj/effect/effect/water(src.loc)
- qdel(src)
- return
- if(3.0)
- if (prob(5))
- new /obj/effect/effect/water(src.loc)
- qdel(src)
- return
- else
- return
-
-/obj/structure/reagent_dispensers/blob_act()
- qdel(src)
-
-
-
-//Dispensers
-/obj/structure/reagent_dispensers/watertank
- name = "watertank"
- desc = "A watertank."
- icon = 'icons/obj/objects.dmi'
- icon_state = "watertank"
- amount_per_transfer_from_this = 10
-
-/obj/structure/reagent_dispensers/watertank/Initialize()
- . = ..()
- reagents.add_reagent("water", 1000)
-
-/obj/structure/reagent_dispensers/watertank/high
- name = "high-capacity water tank"
- desc = "A highly-pressurized water tank made to hold vast amounts of water.."
- icon_state = "watertank_high"
-
-/obj/structure/reagent_dispensers/watertank/high/Initialize()
- . = ..()
- reagents.add_reagent("water", 4000)
-
-/obj/structure/reagent_dispensers/fueltank
- name = "fueltank"
- desc = "A fueltank."
- icon = 'icons/obj/objects.dmi'
- icon_state = "weldtank"
- amount_per_transfer_from_this = 10
- var/modded = 0
- var/obj/item/device/assembly_holder/rig = null
-
-/obj/structure/reagent_dispensers/fueltank/Initialize()
- . = ..()
- reagents.add_reagent("fuel",1000)
-
-/obj/structure/reagent_dispensers/fueltank/examine(mob/user)
- . = ..()
- if(get_dist(user, src) <= 2)
- if(modded)
- . += "Fuel faucet is wrenched open, leaking the fuel!"
- if(rig)
- . += "There is some kind of device rigged to the tank."
-
-/obj/structure/reagent_dispensers/fueltank/attack_hand()
- if (rig)
- usr.visible_message("[usr] begins to detach [rig] from \the [src].", "You begin to detach [rig] from \the [src]")
- if(do_after(usr, 20))
- usr.visible_message("[usr] detaches [rig] from \the [src].", "You detach [rig] from \the [src]")
- rig.loc = get_turf(usr)
- rig = null
- overlays = new/list()
-
-/obj/structure/reagent_dispensers/fueltank/attackby(obj/item/weapon/W as obj, mob/user as mob)
- src.add_fingerprint(user)
- if (W.is_wrench())
- user.visible_message("[user] wrenches [src]'s faucet [modded ? "closed" : "open"].", \
- "You wrench [src]'s faucet [modded ? "closed" : "open"]")
- modded = modded ? 0 : 1
- playsound(src, W.usesound, 75, 1)
- if (modded)
- message_admins("[key_name_admin(user)] opened fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]), leaking fuel. (JMP)")
- log_game("[key_name(user)] opened fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]), leaking fuel.")
- leak_fuel(amount_per_transfer_from_this)
- if (istype(W,/obj/item/device/assembly_holder))
- if (rig)
- to_chat(user, "There is another device in the way.")
- return ..()
- user.visible_message("[user] begins rigging [W] to \the [src].", "You begin rigging [W] to \the [src]")
- if(do_after(user, 20))
- user.visible_message("[user] rigs [W] to \the [src].", "You rig [W] to \the [src]")
-
- var/obj/item/device/assembly_holder/H = W
- if (istype(H.a_left,/obj/item/device/assembly/igniter) || istype(H.a_right,/obj/item/device/assembly/igniter))
- message_admins("[key_name_admin(user)] rigged fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) for explosion. (JMP)")
- log_game("[key_name(user)] rigged fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) for explosion.")
-
- rig = W
- user.drop_item()
- W.loc = src
-
- var/icon/test = getFlatIcon(W)
- test.Shift(NORTH,1)
- test.Shift(EAST,6)
- overlays += test
-
- return ..()
-
-
-/obj/structure/reagent_dispensers/fueltank/bullet_act(var/obj/item/projectile/Proj)
- if(Proj.get_structure_damage())
- if(istype(Proj.firer))
- message_admins("[key_name_admin(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) (JMP).")
- log_game("[key_name(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]).")
-
- if(!istype(Proj ,/obj/item/projectile/beam/lasertag) && !istype(Proj ,/obj/item/projectile/beam/practice) )
- explode()
-
-/obj/structure/reagent_dispensers/fueltank/ex_act()
- explode()
-
-/obj/structure/reagent_dispensers/fueltank/blob_act()
- explode()
-
-/obj/structure/reagent_dispensers/fueltank/proc/explode()
- if (reagents.total_volume > 500)
- explosion(src.loc,1,2,4)
- else if (reagents.total_volume > 100)
- explosion(src.loc,0,1,3)
- else if (reagents.total_volume > 50)
- explosion(src.loc,-1,1,2)
- if(src)
- qdel(src)
-
-/obj/structure/reagent_dispensers/fueltank/fire_act(datum/gas_mixture/air, temperature, volume)
- if (modded)
- explode()
- else if (temperature > T0C+500)
- explode()
- return ..()
-
-/obj/structure/reagent_dispensers/fueltank/Move()
- if (..() && modded)
- leak_fuel(amount_per_transfer_from_this/10.0)
-
-/obj/structure/reagent_dispensers/fueltank/proc/leak_fuel(amount)
- if (reagents.total_volume == 0)
- return
-
- amount = min(amount, reagents.total_volume)
- reagents.remove_reagent("fuel",amount)
- new /obj/effect/decal/cleanable/liquid_fuel(src.loc, amount,1)
-
-/obj/structure/reagent_dispensers/peppertank
- name = "Pepper Spray Refiller"
- desc = "Refills pepper spray canisters."
- icon = 'icons/obj/objects.dmi'
- icon_state = "peppertank"
- anchored = 1
- density = 0
- amount_per_transfer_from_this = 45
-
-/obj/structure/reagent_dispensers/peppertank/Initialize()
- . = ..()
- reagents.add_reagent("condensedcapsaicin",1000)
-
-
-/obj/structure/reagent_dispensers/water_cooler
- name = "Water-Cooler"
- desc = "A machine that dispenses water to drink."
- amount_per_transfer_from_this = 5
- icon = 'icons/obj/vending.dmi'
- icon_state = "water_cooler"
- possible_transfer_amounts = null
- anchored = 1
- var/bottle = 0
- var/cups = 0
- var/cupholder = 0
-
-/obj/structure/reagent_dispensers/water_cooler/full
- bottle = 1
- cupholder = 1
- cups = 10
-
-/obj/structure/reagent_dispensers/water_cooler/Initialize()
- . = ..()
- if(bottle)
- reagents.add_reagent("water",120)
- update_icon()
-
-/obj/structure/reagent_dispensers/water_cooler/examine(mob/user)
- . = ..()
- if(cupholder)
- . += "There are [cups] cups in the cup dispenser."
-
-/obj/structure/reagent_dispensers/water_cooler/verb/rotate_clockwise()
- set name = "Rotate Cooler Clockwise"
- set category = "Object"
- set src in oview(1)
-
- if (src.anchored || usr:stat)
- to_chat(usr, "It is fastened to the floor!")
- return 0
- src.set_dir(turn(src.dir, 270))
- return 1
-
-/obj/structure/reagent_dispensers/water_cooler/attackby(obj/item/I as obj, mob/user as mob)
- if(I.is_wrench())
- src.add_fingerprint(user)
- if(bottle)
- playsound(src, I.usesound, 50, 1)
- if(do_after(user, 20) && bottle)
- to_chat(user, "You unfasten the jug.")
- var/obj/item/weapon/reagent_containers/glass/cooler_bottle/G = new /obj/item/weapon/reagent_containers/glass/cooler_bottle( src.loc )
- for(var/datum/reagent/R in reagents.reagent_list)
- var/total_reagent = reagents.get_reagent_amount(R.id)
- G.reagents.add_reagent(R.id, total_reagent)
- reagents.clear_reagents()
- bottle = 0
- update_icon()
- else
- if(anchored)
- user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
- else
- user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
- if(do_after(user, 20 * I.toolspeed, src))
- if(!src) return
- to_chat(user, "You [anchored? "un" : ""]secured \the [src]!")
- anchored = !anchored
- playsound(src, I.usesound, 50, 1)
- return
-
- if(I.is_screwdriver())
- if(cupholder)
- playsound(src, I.usesound, 50, 1)
- to_chat(user, "You take the cup dispenser off.")
- new /obj/item/stack/material/plastic( src.loc )
- if(cups)
- for(var/i = 0 to cups)
- new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src.loc)
- cups = 0
- cupholder = 0
- update_icon()
- return
- if(!bottle && !cupholder)
- playsound(src, I.usesound, 50, 1)
- to_chat(user, "You start taking the water-cooler apart.")
- if(do_after(user, 20 * I.toolspeed) && !bottle && !cupholder)
- to_chat(user, "You take the water-cooler apart.")
- new /obj/item/stack/material/plastic( src.loc, 4 )
- qdel(src)
- return
-
- if(istype(I, /obj/item/weapon/reagent_containers/glass/cooler_bottle))
- src.add_fingerprint(user)
- if(!bottle)
- if(anchored)
- var/obj/item/weapon/reagent_containers/glass/cooler_bottle/G = I
- to_chat(user, "You start to screw the bottle onto the water-cooler.")
- if(do_after(user, 20) && !bottle && anchored)
- bottle = 1
- update_icon()
- to_chat(user, "You screw the bottle onto the water-cooler!")
- for(var/datum/reagent/R in G.reagents.reagent_list)
- var/total_reagent = G.reagents.get_reagent_amount(R.id)
- reagents.add_reagent(R.id, total_reagent)
- qdel(G)
- else
- to_chat(user, "You need to wrench down the cooler first.")
- else
- to_chat(user, "There is already a bottle there!")
- return 1
-
- if(istype(I, /obj/item/stack/material/plastic))
- if(!cupholder)
- if(anchored)
- var/obj/item/stack/material/plastic/P = I
- src.add_fingerprint(user)
- to_chat(user, "You start to attach a cup dispenser onto the water-cooler.")
- playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
- if(do_after(user, 20) && !cupholder && anchored)
- if (P.use(1))
- to_chat(user, "You attach a cup dispenser onto the water-cooler.")
- cupholder = 1
- update_icon()
- else
- to_chat(user, "You need to wrench down the cooler first.")
- else
- to_chat(user, "There is already a cup dispenser there!")
- return
-
-/obj/structure/reagent_dispensers/water_cooler/attack_hand(mob/user)
- if(cups)
- new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src.loc)
- cups--
- flick("[icon_state]-vend", src)
- return
-
-/obj/structure/reagent_dispensers/water_cooler/update_icon()
- icon_state = "water_cooler"
- overlays.Cut()
- var/image/I
- if(bottle)
- I = image(icon, "water_cooler_bottle")
- overlays += I
- return
-
-/obj/structure/reagent_dispensers/beerkeg
- name = "beer keg"
- desc = "A beer keg."
- icon = 'icons/obj/objects.dmi'
- icon_state = "beertankTEMP"
- amount_per_transfer_from_this = 10
-
-/obj/structure/reagent_dispensers/beerkeg/Initialize()
- . = ..()
- reagents.add_reagent("beer",1000)
-
-/obj/structure/reagent_dispensers/beerkeg/fakenuke
- name = "nuclear beer keg"
- desc = "A beer keg in the form of a nuclear bomb! An absolute blast at parties!"
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "nuclearbomb0"
-
-/obj/structure/reagent_dispensers/virusfood
- name = "Virus Food Dispenser"
- desc = "A dispenser of virus food. Yum."
- icon = 'icons/obj/objects.dmi'
- icon_state = "virusfoodtank"
- amount_per_transfer_from_this = 10
- anchored = 1
-
-/obj/structure/reagent_dispensers/virusfood/Initialize()
- . = ..()
- reagents.add_reagent("virusfood", 1000)
-
-/obj/structure/reagent_dispensers/acid
- name = "Sulphuric Acid Dispenser"
- desc = "A dispenser of acid for industrial processes."
- icon = 'icons/obj/objects.dmi'
- icon_state = "acidtank"
- amount_per_transfer_from_this = 10
- anchored = 1
-
-/obj/structure/reagent_dispensers/acid/Initialize()
- . = ..()
- reagents.add_reagent("sacid", 1000)
-
-//Cooking oil refill tank
-/obj/structure/reagent_dispensers/cookingoil
- name = "cooking oil tank"
- desc = "A fifty-litre tank of commercial-grade corn oil, intended for use in large scale deep fryers. Store in a cool, dark place"
- icon = 'icons/obj/objects.dmi'
- icon_state = "oiltank"
- amount_per_transfer_from_this = 120
-
-/obj/structure/reagent_dispensers/cookingoil/New()
- ..()
- reagents.add_reagent("cornoil",5000)
-
-/obj/structure/reagent_dispensers/cookingoil/bullet_act(var/obj/item/projectile/Proj)
- if(Proj.get_structure_damage())
- explode()
-
-/obj/structure/reagent_dispensers/cookingoil/ex_act()
- explode()
-
-/obj/structure/reagent_dispensers/cookingoil/proc/explode()
- reagents.splash_area(get_turf(src), 3)
- visible_message(span("danger", "The [src] bursts open, spreading oil all over the area."))
- qdel(src)
+
+
+/obj/structure/reagent_dispensers
+ name = "Dispenser"
+ desc = "..."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "watertank"
+ layer = TABLE_LAYER
+ density = 1
+ anchored = 0
+ pressure_resistance = 2*ONE_ATMOSPHERE
+
+ var/obj/item/hose_connector/input/active/InputSocket
+ var/obj/item/hose_connector/output/active/OutputSocket
+
+ var/amount_per_transfer_from_this = 10
+ var/possible_transfer_amounts = list(10,25,50,100)
+
+/obj/structure/reagent_dispensers/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ return
+
+/obj/structure/reagent_dispensers/Destroy()
+ QDEL_NULL(InputSocket)
+ QDEL_NULL(OutputSocket)
+
+ ..()
+
+/obj/structure/reagent_dispensers/Initialize()
+ var/datum/reagents/R = new/datum/reagents(5000)
+ reagents = R
+ R.my_atom = src
+ if (!possible_transfer_amounts)
+ src.verbs -= /obj/structure/reagent_dispensers/verb/set_APTFT
+
+ InputSocket = new(src)
+ InputSocket.carrier = src
+ OutputSocket = new(src)
+ OutputSocket.carrier = src
+
+ . = ..()
+
+/obj/structure/reagent_dispensers/examine(mob/user)
+ . = ..()
+ if(get_dist(user, src) <= 2)
+ . += "It contains:"
+ if(reagents && reagents.reagent_list.len)
+ for(var/datum/reagent/R in reagents.reagent_list)
+ . += "[R.volume] units of [R.name]"
+ else
+ . += "Nothing."
+
+/obj/structure/reagent_dispensers/verb/set_APTFT() //set amount_per_transfer_from_this
+ set name = "Set transfer amount"
+ set category = "Object"
+ set src in view(1)
+ var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts
+ if (N)
+ amount_per_transfer_from_this = N
+
+/obj/structure/reagent_dispensers/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ qdel(src)
+ return
+ if(2.0)
+ if (prob(50))
+ new /obj/effect/effect/water(src.loc)
+ qdel(src)
+ return
+ if(3.0)
+ if (prob(5))
+ new /obj/effect/effect/water(src.loc)
+ qdel(src)
+ return
+ else
+ return
+
+/obj/structure/reagent_dispensers/blob_act()
+ qdel(src)
+
+
+
+//Dispensers
+/obj/structure/reagent_dispensers/watertank
+ name = "watertank"
+ desc = "A watertank."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "watertank"
+ amount_per_transfer_from_this = 10
+
+/obj/structure/reagent_dispensers/watertank/Initialize()
+ . = ..()
+ reagents.add_reagent("water", 1000)
+
+/obj/structure/reagent_dispensers/watertank/high
+ name = "high-capacity water tank"
+ desc = "A highly-pressurized water tank made to hold vast amounts of water.."
+ icon_state = "watertank_high"
+
+/obj/structure/reagent_dispensers/watertank/high/Initialize()
+ . = ..()
+ reagents.add_reagent("water", 4000)
+
+/obj/structure/reagent_dispensers/fueltank
+ name = "fueltank"
+ desc = "A fueltank."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "weldtank"
+ amount_per_transfer_from_this = 10
+ var/modded = 0
+ var/obj/item/device/assembly_holder/rig = null
+
+/obj/structure/reagent_dispensers/fueltank/Initialize()
+ . = ..()
+ reagents.add_reagent("fuel",1000)
+
+/obj/structure/reagent_dispensers/fueltank/examine(mob/user)
+ . = ..()
+ if(get_dist(user, src) <= 2)
+ if(modded)
+ . += "Fuel faucet is wrenched open, leaking the fuel!"
+ if(rig)
+ . += "There is some kind of device rigged to the tank."
+
+/obj/structure/reagent_dispensers/fueltank/attack_hand()
+ if (rig)
+ usr.visible_message("[usr] begins to detach [rig] from \the [src].", "You begin to detach [rig] from \the [src]")
+ if(do_after(usr, 20))
+ usr.visible_message("[usr] detaches [rig] from \the [src].", "You detach [rig] from \the [src]")
+ rig.loc = get_turf(usr)
+ rig = null
+ overlays = new/list()
+
+/obj/structure/reagent_dispensers/fueltank/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ src.add_fingerprint(user)
+ if (W.is_wrench())
+ user.visible_message("[user] wrenches [src]'s faucet [modded ? "closed" : "open"].", \
+ "You wrench [src]'s faucet [modded ? "closed" : "open"]")
+ modded = modded ? 0 : 1
+ playsound(src, W.usesound, 75, 1)
+ if (modded)
+ message_admins("[key_name_admin(user)] opened fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]), leaking fuel. (JMP)")
+ log_game("[key_name(user)] opened fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]), leaking fuel.")
+ leak_fuel(amount_per_transfer_from_this)
+ if (istype(W,/obj/item/device/assembly_holder))
+ if (rig)
+ to_chat(user, "There is another device in the way.")
+ return ..()
+ user.visible_message("[user] begins rigging [W] to \the [src].", "You begin rigging [W] to \the [src]")
+ if(do_after(user, 20))
+ user.visible_message("[user] rigs [W] to \the [src].", "You rig [W] to \the [src]")
+
+ var/obj/item/device/assembly_holder/H = W
+ if (istype(H.a_left,/obj/item/device/assembly/igniter) || istype(H.a_right,/obj/item/device/assembly/igniter))
+ message_admins("[key_name_admin(user)] rigged fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) for explosion. (JMP)")
+ log_game("[key_name(user)] rigged fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) for explosion.")
+
+ rig = W
+ user.drop_item()
+ W.loc = src
+
+ var/icon/test = getFlatIcon(W)
+ test.Shift(NORTH,1)
+ test.Shift(EAST,6)
+ overlays += test
+
+ return ..()
+
+
+/obj/structure/reagent_dispensers/fueltank/bullet_act(var/obj/item/projectile/Proj)
+ if(Proj.get_structure_damage())
+ if(istype(Proj.firer))
+ message_admins("[key_name_admin(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) (JMP).")
+ log_game("[key_name(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]).")
+
+ if(!istype(Proj ,/obj/item/projectile/beam/lasertag) && !istype(Proj ,/obj/item/projectile/beam/practice) )
+ explode()
+
+/obj/structure/reagent_dispensers/fueltank/ex_act()
+ explode()
+
+/obj/structure/reagent_dispensers/fueltank/blob_act()
+ explode()
+
+/obj/structure/reagent_dispensers/fueltank/proc/explode()
+ if (reagents.total_volume > 500)
+ explosion(src.loc,1,2,4)
+ else if (reagents.total_volume > 100)
+ explosion(src.loc,0,1,3)
+ else if (reagents.total_volume > 50)
+ explosion(src.loc,-1,1,2)
+ if(src)
+ qdel(src)
+
+/obj/structure/reagent_dispensers/fueltank/fire_act(datum/gas_mixture/air, temperature, volume)
+ if (modded)
+ explode()
+ else if (temperature > T0C+500)
+ explode()
+ return ..()
+
+/obj/structure/reagent_dispensers/fueltank/Move()
+ if (..() && modded)
+ leak_fuel(amount_per_transfer_from_this/10.0)
+
+/obj/structure/reagent_dispensers/fueltank/proc/leak_fuel(amount)
+ if (reagents.total_volume == 0)
+ return
+
+ amount = min(amount, reagents.total_volume)
+ reagents.remove_reagent("fuel",amount)
+ new /obj/effect/decal/cleanable/liquid_fuel(src.loc, amount,1)
+
+/obj/structure/reagent_dispensers/peppertank
+ name = "Pepper Spray Refiller"
+ desc = "Refills pepper spray canisters."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "peppertank"
+ anchored = 1
+ density = 0
+ amount_per_transfer_from_this = 45
+
+/obj/structure/reagent_dispensers/peppertank/Initialize()
+ . = ..()
+ reagents.add_reagent("condensedcapsaicin",1000)
+
+
+/obj/structure/reagent_dispensers/water_cooler
+ name = "Water-Cooler"
+ desc = "A machine that dispenses water to drink."
+ amount_per_transfer_from_this = 5
+ icon = 'icons/obj/vending.dmi'
+ icon_state = "water_cooler"
+ possible_transfer_amounts = null
+ anchored = 1
+ var/bottle = 0
+ var/cups = 0
+ var/cupholder = 0
+
+/obj/structure/reagent_dispensers/water_cooler/full
+ bottle = 1
+ cupholder = 1
+ cups = 10
+
+/obj/structure/reagent_dispensers/water_cooler/Initialize()
+ . = ..()
+ if(bottle)
+ reagents.add_reagent("water",120)
+ update_icon()
+
+/obj/structure/reagent_dispensers/water_cooler/examine(mob/user)
+ . = ..()
+ if(cupholder)
+ . += "There are [cups] cups in the cup dispenser."
+
+/obj/structure/reagent_dispensers/water_cooler/verb/rotate_clockwise()
+ set name = "Rotate Cooler Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.anchored || usr:stat)
+ to_chat(usr, "It is fastened to the floor!")
+ return 0
+ src.set_dir(turn(src.dir, 270))
+ return 1
+
+/obj/structure/reagent_dispensers/water_cooler/attackby(obj/item/I as obj, mob/user as mob)
+ if(I.is_wrench())
+ src.add_fingerprint(user)
+ if(bottle)
+ playsound(src, I.usesound, 50, 1)
+ if(do_after(user, 20) && bottle)
+ to_chat(user, "You unfasten the jug.")
+ var/obj/item/weapon/reagent_containers/glass/cooler_bottle/G = new /obj/item/weapon/reagent_containers/glass/cooler_bottle( src.loc )
+ for(var/datum/reagent/R in reagents.reagent_list)
+ var/total_reagent = reagents.get_reagent_amount(R.id)
+ G.reagents.add_reagent(R.id, total_reagent)
+ reagents.clear_reagents()
+ bottle = 0
+ update_icon()
+ else
+ if(anchored)
+ user.visible_message("\The [user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.")
+ else
+ user.visible_message("\The [user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.")
+ if(do_after(user, 20 * I.toolspeed, src))
+ if(!src) return
+ to_chat(user, "You [anchored? "un" : ""]secured \the [src]!")
+ anchored = !anchored
+ playsound(src, I.usesound, 50, 1)
+ return
+
+ if(I.is_screwdriver())
+ if(cupholder)
+ playsound(src, I.usesound, 50, 1)
+ to_chat(user, "You take the cup dispenser off.")
+ new /obj/item/stack/material/plastic( src.loc )
+ if(cups)
+ for(var/i = 0 to cups)
+ new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src.loc)
+ cups = 0
+ cupholder = 0
+ update_icon()
+ return
+ if(!bottle && !cupholder)
+ playsound(src, I.usesound, 50, 1)
+ to_chat(user, "You start taking the water-cooler apart.")
+ if(do_after(user, 20 * I.toolspeed) && !bottle && !cupholder)
+ to_chat(user, "You take the water-cooler apart.")
+ new /obj/item/stack/material/plastic( src.loc, 4 )
+ qdel(src)
+ return
+
+ if(istype(I, /obj/item/weapon/reagent_containers/glass/cooler_bottle))
+ src.add_fingerprint(user)
+ if(!bottle)
+ if(anchored)
+ var/obj/item/weapon/reagent_containers/glass/cooler_bottle/G = I
+ to_chat(user, "You start to screw the bottle onto the water-cooler.")
+ if(do_after(user, 20) && !bottle && anchored)
+ bottle = 1
+ update_icon()
+ to_chat(user, "You screw the bottle onto the water-cooler!")
+ for(var/datum/reagent/R in G.reagents.reagent_list)
+ var/total_reagent = G.reagents.get_reagent_amount(R.id)
+ reagents.add_reagent(R.id, total_reagent)
+ qdel(G)
+ else
+ to_chat(user, "You need to wrench down the cooler first.")
+ else
+ to_chat(user, "There is already a bottle there!")
+ return 1
+
+ if(istype(I, /obj/item/stack/material/plastic))
+ if(!cupholder)
+ if(anchored)
+ var/obj/item/stack/material/plastic/P = I
+ src.add_fingerprint(user)
+ to_chat(user, "You start to attach a cup dispenser onto the water-cooler.")
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(do_after(user, 20) && !cupholder && anchored)
+ if (P.use(1))
+ to_chat(user, "You attach a cup dispenser onto the water-cooler.")
+ cupholder = 1
+ update_icon()
+ else
+ to_chat(user, "You need to wrench down the cooler first.")
+ else
+ to_chat(user, "There is already a cup dispenser there!")
+ return
+
+/obj/structure/reagent_dispensers/water_cooler/attack_hand(mob/user)
+ if(cups)
+ new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src.loc)
+ cups--
+ flick("[icon_state]-vend", src)
+ return
+
+/obj/structure/reagent_dispensers/water_cooler/update_icon()
+ icon_state = "water_cooler"
+ overlays.Cut()
+ var/image/I
+ if(bottle)
+ I = image(icon, "water_cooler_bottle")
+ overlays += I
+ return
+
+/obj/structure/reagent_dispensers/beerkeg
+ name = "beer keg"
+ desc = "A beer keg."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "beertankTEMP"
+ amount_per_transfer_from_this = 10
+
+/obj/structure/reagent_dispensers/beerkeg/Initialize()
+ . = ..()
+ reagents.add_reagent("beer",1000)
+
+/obj/structure/reagent_dispensers/beerkeg/fakenuke
+ name = "nuclear beer keg"
+ desc = "A beer keg in the form of a nuclear bomb! An absolute blast at parties!"
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "nuclearbomb0"
+
+/obj/structure/reagent_dispensers/virusfood
+ name = "Virus Food Dispenser"
+ desc = "A dispenser of virus food. Yum."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "virusfoodtank"
+ amount_per_transfer_from_this = 10
+ anchored = 1
+
+/obj/structure/reagent_dispensers/virusfood/Initialize()
+ . = ..()
+ reagents.add_reagent("virusfood", 1000)
+
+/obj/structure/reagent_dispensers/acid
+ name = "Sulphuric Acid Dispenser"
+ desc = "A dispenser of acid for industrial processes."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "acidtank"
+ amount_per_transfer_from_this = 10
+ anchored = 1
+
+/obj/structure/reagent_dispensers/acid/Initialize()
+ . = ..()
+ reagents.add_reagent("sacid", 1000)
+
+//Cooking oil refill tank
+/obj/structure/reagent_dispensers/cookingoil
+ name = "cooking oil tank"
+ desc = "A fifty-litre tank of commercial-grade corn oil, intended for use in large scale deep fryers. Store in a cool, dark place"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "oiltank"
+ amount_per_transfer_from_this = 120
+
+/obj/structure/reagent_dispensers/cookingoil/New()
+ ..()
+ reagents.add_reagent("cornoil",5000)
+
+/obj/structure/reagent_dispensers/cookingoil/bullet_act(var/obj/item/projectile/Proj)
+ if(Proj.get_structure_damage())
+ explode()
+
+/obj/structure/reagent_dispensers/cookingoil/ex_act()
+ explode()
+
+/obj/structure/reagent_dispensers/cookingoil/proc/explode()
+ reagents.splash_area(get_turf(src), 3)
+ visible_message(span("danger", "The [src] bursts open, spreading oil all over the area."))
+ qdel(src)
+
+/obj/structure/reagent_dispensers/he3
+ name = "fueltank"
+ desc = "A fueltank."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "weldtank"
+ amount_per_transfer_from_this = 10
+
+/obj/structure/reagent_dispenser/he3/Initialize()
+ ..()
+ reagents.add_reagent("helium3",1000)
\ No newline at end of file
diff --git a/code/modules/reagents/dispenser/supply.dm b/code/modules/reagents/machinery/dispenser/supply.dm
similarity index 98%
rename from code/modules/reagents/dispenser/supply.dm
rename to code/modules/reagents/machinery/dispenser/supply.dm
index 228c5dfeef..30b1c3c0f6 100644
--- a/code/modules/reagents/dispenser/supply.dm
+++ b/code/modules/reagents/machinery/dispenser/supply.dm
@@ -1,238 +1,238 @@
-/datum/supply_pack/chemistry_dispenser
- name = "Reagent dispenser"
- contains = list(
- /obj/machinery/chemical_dispenser{anchored = 0}
- )
- cost = 25
- containertype = /obj/structure/largecrate
- containername = "reagent dispenser crate"
- group = "Reagents"
-
-/datum/supply_pack/beer_dispenser
- name = "Booze dispenser"
- contains = list(
- /obj/machinery/chemical_dispenser/bar_alc{anchored = 0}
- )
- cost = 25
- containertype = /obj/structure/largecrate
- containername = "booze dispenser crate"
- group = "Reagents"
-
-/datum/supply_pack/soda_dispenser
- name = "Soda dispenser"
- contains = list(
- /obj/machinery/chemical_dispenser/bar_soft{anchored = 0}
- )
- cost = 25
- containertype = /obj/structure/largecrate
- containername = "soda dispenser crate"
- group = "Reagents"
-
-/datum/supply_pack/reagents
- name = "Chemistry dispenser refill"
- contains = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/hydrogen,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lithium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/carbon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/nitrogen,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxygen,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/fluorine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/aluminum,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/silicon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/phosphorus,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sulfur,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/chlorine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/potassium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/iron,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/copper,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/mercury,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/radium,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethanol,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sacid,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tungsten
- )
- cost = 150
- containertype = /obj/structure/closet/crate/secure
- containername = "chemical crate"
- access = list(access_chemistry)
- group = "Reagents"
-
-/datum/supply_pack/alcohol_reagents
- name = "Bar alcoholic dispenser refill"
- contains = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/beer,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/kahlua,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/whiskey,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/wine,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/vodka,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/gin,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/rum,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tequila,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/vermouth,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cognac,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ale,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/mead,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/bitters
- )
- cost = 50
- containertype = /obj/structure/closet/crate/secure
- containername = "alcoholic drinks crate"
- access = list(access_bar)
- group = "Reagents"
-
-/datum/supply_pack/softdrink_reagents
- name = "Bar soft drink dispenser refill"
- contains = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/icetea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cola,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/smw,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/dr_gibb,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceup,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/watermelon,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon
- )
- cost = 50
- containertype = /obj/structure/closet/crate
- containername = "soft drinks crate"
- group = "Reagents"
-
-/datum/supply_pack/coffee_reagents
- name = "Coffee machine dispenser refill"
- contains = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cafe_latte,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/soy_latte,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/hot_coco,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/milk,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice
- )
- cost = 50
- containertype = /obj/structure/closet/crate
- containername = "coffee drinks crate"
- group = "Reagents"
-
-/datum/supply_pack/dispenser_cartridges
- name = "Empty dispenser cartridges"
- contains = list(
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge
- )
- cost = 15
- containertype = /obj/structure/closet/crate
- containername = "dispenser cartridge crate"
- group = "Reagents"
-
-#define SEC_PACK(_tname, _type, _name, _cname, _cost, _access)\
- datum/supply_pack/dispenser_cartridges{\
- _tname {\
- name = _name ;\
- containername = _cname ;\
- containertype = /obj/structure/closet/crate/secure;\
- access = list( _access );\
- cost = _cost ;\
- contains = list( _type , _type );\
- group = "Reagent Cartridges"\
- }\
- }
-#define PACK(_tname, _type, _name, _cname, _cost)\
- datum/supply_pack/dispenser_cartridges{\
- _tname {\
- name = _name ;\
- containername = _cname ;\
- containertype = /obj/structure/closet/crate;\
- cost = _cost ;\
- contains = list( _type , _type );\
- group = "Reagent Cartridges"\
- }\
- }
-
-// Chemistry-restricted (raw reagents excluding sugar/water)
-// Datum path Contents type Supply pack name Container name Cost Container access
-SEC_PACK(hydrogen, /obj/item/weapon/reagent_containers/chem_disp_cartridge/hydrogen, "Reagent refill - Hydrogen", "hydrogen reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(lithium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lithium, "Reagent refill - Lithium", "lithium reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(carbon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/carbon, "Reagent refill - Carbon", "carbon reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(nitrogen, /obj/item/weapon/reagent_containers/chem_disp_cartridge/nitrogen, "Reagent refill - Nitrogen", "nitrogen reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(oxygen, /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxygen, "Reagent refill - Oxygen", "oxygen reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(fluorine, /obj/item/weapon/reagent_containers/chem_disp_cartridge/fluorine, "Reagent refill - Fluorine", "fluorine reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(sodium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodium, "Reagent refill - Sodium", "sodium reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(aluminium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/aluminum, "Reagent refill - Aluminum", "aluminum reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(silicon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/silicon, "Reagent refill - Silicon", "silicon reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(phosphorus,/obj/item/weapon/reagent_containers/chem_disp_cartridge/phosphorus, "Reagent refill - Phosphorus", "phosphorus reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(sulfur, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sulfur, "Reagent refill - Sulfur", "sulfur reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(chlorine, /obj/item/weapon/reagent_containers/chem_disp_cartridge/chlorine, "Reagent refill - Chlorine", "chlorine reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(potassium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/potassium, "Reagent refill - Potassium", "potassium reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(iron, /obj/item/weapon/reagent_containers/chem_disp_cartridge/iron, "Reagent refill - Iron", "iron reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(copper, /obj/item/weapon/reagent_containers/chem_disp_cartridge/copper, "Reagent refill - Copper", "copper reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(mercury, /obj/item/weapon/reagent_containers/chem_disp_cartridge/mercury, "Reagent refill - Mercury", "mercury reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(radium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/radium, "Reagent refill - Radium", "radium reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(ethanol, /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethanol, "Reagent refill - Ethanol", "ethanol reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(sacid, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sacid, "Reagent refill - Sulfuric Acid", "sulfuric acid reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(tungsten, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tungsten, "Reagent refill - Tungsten", "tungsten reagent cartridge crate", 15, access_chemistry)
-SEC_PACK(calcium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/calcium, "Reagent refill - Calcium", "calcium reagent cartridge crate", 15, access_chemistry)
-
-// Bar-restricted (alcoholic drinks)
-// Datum path Contents type Supply pack name Container name Cost Container access
-SEC_PACK(beer, /obj/item/weapon/reagent_containers/chem_disp_cartridge/beer, "Reagent refill - Beer", "beer reagent cartridge crate", 15, access_bar)
-SEC_PACK(kahlua, /obj/item/weapon/reagent_containers/chem_disp_cartridge/kahlua, "Reagent refill - Kahlua", "kahlua reagent cartridge crate", 15, access_bar)
-SEC_PACK(whiskey, /obj/item/weapon/reagent_containers/chem_disp_cartridge/whiskey, "Reagent refill - Whiskey", "whiskey reagent cartridge crate", 15, access_bar)
-SEC_PACK(wine, /obj/item/weapon/reagent_containers/chem_disp_cartridge/wine, "Reagent refill - Wine", "wine reagent cartridge crate", 15, access_bar)
-SEC_PACK(vodka, /obj/item/weapon/reagent_containers/chem_disp_cartridge/vodka, "Reagent refill - Vodka", "vodka reagent cartridge crate", 15, access_bar)
-SEC_PACK(gin, /obj/item/weapon/reagent_containers/chem_disp_cartridge/gin, "Reagent refill - Gin", "gin reagent cartridge crate", 15, access_bar)
-SEC_PACK(rum, /obj/item/weapon/reagent_containers/chem_disp_cartridge/rum, "Reagent refill - Rum", "rum reagent cartridge crate", 15, access_bar)
-SEC_PACK(tequila, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tequila, "Reagent refill - Tequila", "tequila reagent cartridge crate", 15, access_bar)
-SEC_PACK(vermouth, /obj/item/weapon/reagent_containers/chem_disp_cartridge/vermouth, "Reagent refill - Vermouth", "vermouth reagent cartridge crate", 15, access_bar)
-SEC_PACK(cognac, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cognac, "Reagent refill - Cognac", "cognac reagent cartridge crate", 15, access_bar)
-SEC_PACK(ale, /obj/item/weapon/reagent_containers/chem_disp_cartridge/ale, "Reagent refill - Ale", "ale reagent cartridge crate", 15, access_bar)
-SEC_PACK(mead, /obj/item/weapon/reagent_containers/chem_disp_cartridge/mead, "Reagent refill - Mead", "mead reagent cartridge crate", 15, access_bar)
-
-// Unrestricted (water, sugar, non-alcoholic drinks)
-// Datum path Contents type Supply pack name Container name Cost
-PACK(water, /obj/item/weapon/reagent_containers/chem_disp_cartridge/water, "Reagent refill - Water", "water reagent cartridge crate", 15)
-PACK(sugar, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar, "Reagent refill - Sugar", "sugar reagent cartridge crate", 15)
-PACK(ice, /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice, "Reagent refill - Ice", "ice reagent cartridge crate", 15)
-PACK(tea, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea, "Reagent refill - Tea", "tea reagent cartridge crate", 15)
-PACK(icetea, /obj/item/weapon/reagent_containers/chem_disp_cartridge/icetea, "Reagent refill - Iced Tea", "iced tea reagent cartridge crate", 15)
-PACK(cola, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cola, "Reagent refill - Space Cola", "\improper Space Cola reagent cartridge crate", 15)
-PACK(smw, /obj/item/weapon/reagent_containers/chem_disp_cartridge/smw, "Reagent refill - Space Mountain Wind", "\improper Space Mountain Wind reagent cartridge crate", 15)
-PACK(dr_gibb, /obj/item/weapon/reagent_containers/chem_disp_cartridge/dr_gibb, "Reagent refill - Dr. Gibb", "\improper Dr. Gibb reagent cartridge crate", 15)
-PACK(spaceup, /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceup, "Reagent refill - Space-Up", "\improper Space-Up reagent cartridge crate", 15)
-PACK(tonic, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic, "Reagent refill - Tonic Water", "tonic water reagent cartridge crate", 15)
-PACK(sodawater, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater, "Reagent refill - Soda Water", "soda water reagent cartridge crate", 15)
-PACK(lemon_lime, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime, "Reagent refill - Lemon-Lime Juice", "lemon-lime juice reagent cartridge crate", 15)
-PACK(orange, /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange, "Reagent refill - Orange Juice", "orange juice reagent cartridge crate", 15)
-PACK(lime, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime, "Reagent refill - Lime Juice", "lime juice reagent cartridge crate", 15)
-PACK(lemon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon, "Reagent refill - Lemon Juice", "lemon juice reagent cartridge crate", 15)
-PACK(watermelon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/watermelon, "Reagent refill - Watermelon Juice", "watermelon juice reagent cartridge crate", 15)
-PACK(coffee, /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee, "Reagent refill - Coffee", "coffee reagent cartridge crate", 15)
-PACK(cafe_latte, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cafe_latte, "Reagent refill - Cafe Latte", "cafe latte reagent cartridge crate", 15)
-PACK(soy_latte, /obj/item/weapon/reagent_containers/chem_disp_cartridge/soy_latte, "Reagent refill - Soy Latte", "soy latte reagent cartridge crate", 15)
-PACK(hot_coco, /obj/item/weapon/reagent_containers/chem_disp_cartridge/hot_coco, "Reagent refill - Hot Coco", "hot coco reagent cartridge crate", 15)
-PACK(milk, /obj/item/weapon/reagent_containers/chem_disp_cartridge/milk, "Reagent refill - Milk", "milk reagent cartridge crate", 15)
-PACK(cream, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream, "Reagent refill - Cream", "cream reagent cartridge crate", 15)
-
-#undef SEC_PACK
-#undef PACK
+/datum/supply_pack/chemistry_dispenser
+ name = "Reagent dispenser"
+ contains = list(
+ /obj/machinery/chemical_dispenser{anchored = 0}
+ )
+ cost = 25
+ containertype = /obj/structure/largecrate
+ containername = "reagent dispenser crate"
+ group = "Reagents"
+
+/datum/supply_pack/beer_dispenser
+ name = "Booze dispenser"
+ contains = list(
+ /obj/machinery/chemical_dispenser/bar_alc{anchored = 0}
+ )
+ cost = 25
+ containertype = /obj/structure/largecrate
+ containername = "booze dispenser crate"
+ group = "Reagents"
+
+/datum/supply_pack/soda_dispenser
+ name = "Soda dispenser"
+ contains = list(
+ /obj/machinery/chemical_dispenser/bar_soft{anchored = 0}
+ )
+ cost = 25
+ containertype = /obj/structure/largecrate
+ containername = "soda dispenser crate"
+ group = "Reagents"
+
+/datum/supply_pack/reagents
+ name = "Chemistry dispenser refill"
+ contains = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/hydrogen,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lithium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/carbon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/nitrogen,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxygen,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/fluorine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/aluminum,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/silicon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/phosphorus,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sulfur,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/chlorine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/potassium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/iron,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/copper,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/mercury,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/radium,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethanol,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sacid,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tungsten
+ )
+ cost = 150
+ containertype = /obj/structure/closet/crate/secure
+ containername = "chemical crate"
+ access = list(access_chemistry)
+ group = "Reagents"
+
+/datum/supply_pack/alcohol_reagents
+ name = "Bar alcoholic dispenser refill"
+ contains = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/beer,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/kahlua,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/whiskey,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/wine,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/vodka,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/gin,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/rum,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tequila,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/vermouth,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cognac,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ale,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/mead,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/bitters
+ )
+ cost = 50
+ containertype = /obj/structure/closet/crate/secure
+ containername = "alcoholic drinks crate"
+ access = list(access_bar)
+ group = "Reagents"
+
+/datum/supply_pack/softdrink_reagents
+ name = "Bar soft drink dispenser refill"
+ contains = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/water,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/icetea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cola,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/smw,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/dr_gibb,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceup,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/watermelon,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon
+ )
+ cost = 50
+ containertype = /obj/structure/closet/crate
+ containername = "soft drinks crate"
+ group = "Reagents"
+
+/datum/supply_pack/coffee_reagents
+ name = "Coffee machine dispenser refill"
+ contains = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cafe_latte,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/soy_latte,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/hot_coco,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/milk,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice
+ )
+ cost = 50
+ containertype = /obj/structure/closet/crate
+ containername = "coffee drinks crate"
+ group = "Reagents"
+
+/datum/supply_pack/dispenser_cartridges
+ name = "Empty dispenser cartridges"
+ contains = list(
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge
+ )
+ cost = 15
+ containertype = /obj/structure/closet/crate
+ containername = "dispenser cartridge crate"
+ group = "Reagents"
+
+#define SEC_PACK(_tname, _type, _name, _cname, _cost, _access)\
+ datum/supply_pack/dispenser_cartridges{\
+ _tname {\
+ name = _name ;\
+ containername = _cname ;\
+ containertype = /obj/structure/closet/crate/secure;\
+ access = list( _access );\
+ cost = _cost ;\
+ contains = list( _type , _type );\
+ group = "Reagent Cartridges"\
+ }\
+ }
+#define PACK(_tname, _type, _name, _cname, _cost)\
+ datum/supply_pack/dispenser_cartridges{\
+ _tname {\
+ name = _name ;\
+ containername = _cname ;\
+ containertype = /obj/structure/closet/crate;\
+ cost = _cost ;\
+ contains = list( _type , _type );\
+ group = "Reagent Cartridges"\
+ }\
+ }
+
+// Chemistry-restricted (raw reagents excluding sugar/water)
+// Datum path Contents type Supply pack name Container name Cost Container access
+SEC_PACK(hydrogen, /obj/item/weapon/reagent_containers/chem_disp_cartridge/hydrogen, "Reagent refill - Hydrogen", "hydrogen reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(lithium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lithium, "Reagent refill - Lithium", "lithium reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(carbon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/carbon, "Reagent refill - Carbon", "carbon reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(nitrogen, /obj/item/weapon/reagent_containers/chem_disp_cartridge/nitrogen, "Reagent refill - Nitrogen", "nitrogen reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(oxygen, /obj/item/weapon/reagent_containers/chem_disp_cartridge/oxygen, "Reagent refill - Oxygen", "oxygen reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(fluorine, /obj/item/weapon/reagent_containers/chem_disp_cartridge/fluorine, "Reagent refill - Fluorine", "fluorine reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(sodium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodium, "Reagent refill - Sodium", "sodium reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(aluminium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/aluminum, "Reagent refill - Aluminum", "aluminum reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(silicon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/silicon, "Reagent refill - Silicon", "silicon reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(phosphorus,/obj/item/weapon/reagent_containers/chem_disp_cartridge/phosphorus, "Reagent refill - Phosphorus", "phosphorus reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(sulfur, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sulfur, "Reagent refill - Sulfur", "sulfur reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(chlorine, /obj/item/weapon/reagent_containers/chem_disp_cartridge/chlorine, "Reagent refill - Chlorine", "chlorine reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(potassium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/potassium, "Reagent refill - Potassium", "potassium reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(iron, /obj/item/weapon/reagent_containers/chem_disp_cartridge/iron, "Reagent refill - Iron", "iron reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(copper, /obj/item/weapon/reagent_containers/chem_disp_cartridge/copper, "Reagent refill - Copper", "copper reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(mercury, /obj/item/weapon/reagent_containers/chem_disp_cartridge/mercury, "Reagent refill - Mercury", "mercury reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(radium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/radium, "Reagent refill - Radium", "radium reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(ethanol, /obj/item/weapon/reagent_containers/chem_disp_cartridge/ethanol, "Reagent refill - Ethanol", "ethanol reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(sacid, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sacid, "Reagent refill - Sulfuric Acid", "sulfuric acid reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(tungsten, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tungsten, "Reagent refill - Tungsten", "tungsten reagent cartridge crate", 15, access_chemistry)
+SEC_PACK(calcium, /obj/item/weapon/reagent_containers/chem_disp_cartridge/calcium, "Reagent refill - Calcium", "calcium reagent cartridge crate", 15, access_chemistry)
+
+// Bar-restricted (alcoholic drinks)
+// Datum path Contents type Supply pack name Container name Cost Container access
+SEC_PACK(beer, /obj/item/weapon/reagent_containers/chem_disp_cartridge/beer, "Reagent refill - Beer", "beer reagent cartridge crate", 15, access_bar)
+SEC_PACK(kahlua, /obj/item/weapon/reagent_containers/chem_disp_cartridge/kahlua, "Reagent refill - Kahlua", "kahlua reagent cartridge crate", 15, access_bar)
+SEC_PACK(whiskey, /obj/item/weapon/reagent_containers/chem_disp_cartridge/whiskey, "Reagent refill - Whiskey", "whiskey reagent cartridge crate", 15, access_bar)
+SEC_PACK(wine, /obj/item/weapon/reagent_containers/chem_disp_cartridge/wine, "Reagent refill - Wine", "wine reagent cartridge crate", 15, access_bar)
+SEC_PACK(vodka, /obj/item/weapon/reagent_containers/chem_disp_cartridge/vodka, "Reagent refill - Vodka", "vodka reagent cartridge crate", 15, access_bar)
+SEC_PACK(gin, /obj/item/weapon/reagent_containers/chem_disp_cartridge/gin, "Reagent refill - Gin", "gin reagent cartridge crate", 15, access_bar)
+SEC_PACK(rum, /obj/item/weapon/reagent_containers/chem_disp_cartridge/rum, "Reagent refill - Rum", "rum reagent cartridge crate", 15, access_bar)
+SEC_PACK(tequila, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tequila, "Reagent refill - Tequila", "tequila reagent cartridge crate", 15, access_bar)
+SEC_PACK(vermouth, /obj/item/weapon/reagent_containers/chem_disp_cartridge/vermouth, "Reagent refill - Vermouth", "vermouth reagent cartridge crate", 15, access_bar)
+SEC_PACK(cognac, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cognac, "Reagent refill - Cognac", "cognac reagent cartridge crate", 15, access_bar)
+SEC_PACK(ale, /obj/item/weapon/reagent_containers/chem_disp_cartridge/ale, "Reagent refill - Ale", "ale reagent cartridge crate", 15, access_bar)
+SEC_PACK(mead, /obj/item/weapon/reagent_containers/chem_disp_cartridge/mead, "Reagent refill - Mead", "mead reagent cartridge crate", 15, access_bar)
+
+// Unrestricted (water, sugar, non-alcoholic drinks)
+// Datum path Contents type Supply pack name Container name Cost
+PACK(water, /obj/item/weapon/reagent_containers/chem_disp_cartridge/water, "Reagent refill - Water", "water reagent cartridge crate", 15)
+PACK(sugar, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sugar, "Reagent refill - Sugar", "sugar reagent cartridge crate", 15)
+PACK(ice, /obj/item/weapon/reagent_containers/chem_disp_cartridge/ice, "Reagent refill - Ice", "ice reagent cartridge crate", 15)
+PACK(tea, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tea, "Reagent refill - Tea", "tea reagent cartridge crate", 15)
+PACK(icetea, /obj/item/weapon/reagent_containers/chem_disp_cartridge/icetea, "Reagent refill - Iced Tea", "iced tea reagent cartridge crate", 15)
+PACK(cola, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cola, "Reagent refill - Space Cola", "\improper Space Cola reagent cartridge crate", 15)
+PACK(smw, /obj/item/weapon/reagent_containers/chem_disp_cartridge/smw, "Reagent refill - Space Mountain Wind", "\improper Space Mountain Wind reagent cartridge crate", 15)
+PACK(dr_gibb, /obj/item/weapon/reagent_containers/chem_disp_cartridge/dr_gibb, "Reagent refill - Dr. Gibb", "\improper Dr. Gibb reagent cartridge crate", 15)
+PACK(spaceup, /obj/item/weapon/reagent_containers/chem_disp_cartridge/spaceup, "Reagent refill - Space-Up", "\improper Space-Up reagent cartridge crate", 15)
+PACK(tonic, /obj/item/weapon/reagent_containers/chem_disp_cartridge/tonic, "Reagent refill - Tonic Water", "tonic water reagent cartridge crate", 15)
+PACK(sodawater, /obj/item/weapon/reagent_containers/chem_disp_cartridge/sodawater, "Reagent refill - Soda Water", "soda water reagent cartridge crate", 15)
+PACK(lemon_lime, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon_lime, "Reagent refill - Lemon-Lime Juice", "lemon-lime juice reagent cartridge crate", 15)
+PACK(orange, /obj/item/weapon/reagent_containers/chem_disp_cartridge/orange, "Reagent refill - Orange Juice", "orange juice reagent cartridge crate", 15)
+PACK(lime, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime, "Reagent refill - Lime Juice", "lime juice reagent cartridge crate", 15)
+PACK(lemon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/lemon, "Reagent refill - Lemon Juice", "lemon juice reagent cartridge crate", 15)
+PACK(watermelon, /obj/item/weapon/reagent_containers/chem_disp_cartridge/watermelon, "Reagent refill - Watermelon Juice", "watermelon juice reagent cartridge crate", 15)
+PACK(coffee, /obj/item/weapon/reagent_containers/chem_disp_cartridge/coffee, "Reagent refill - Coffee", "coffee reagent cartridge crate", 15)
+PACK(cafe_latte, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cafe_latte, "Reagent refill - Cafe Latte", "cafe latte reagent cartridge crate", 15)
+PACK(soy_latte, /obj/item/weapon/reagent_containers/chem_disp_cartridge/soy_latte, "Reagent refill - Soy Latte", "soy latte reagent cartridge crate", 15)
+PACK(hot_coco, /obj/item/weapon/reagent_containers/chem_disp_cartridge/hot_coco, "Reagent refill - Hot Coco", "hot coco reagent cartridge crate", 15)
+PACK(milk, /obj/item/weapon/reagent_containers/chem_disp_cartridge/milk, "Reagent refill - Milk", "milk reagent cartridge crate", 15)
+PACK(cream, /obj/item/weapon/reagent_containers/chem_disp_cartridge/cream, "Reagent refill - Cream", "cream reagent cartridge crate", 15)
+
+#undef SEC_PACK
+#undef PACK
diff --git a/code/modules/reagents/distilling/distilling.dm b/code/modules/reagents/machinery/distillery.dm
similarity index 92%
rename from code/modules/reagents/distilling/distilling.dm
rename to code/modules/reagents/machinery/distillery.dm
index 4bd8bd163e..d64d8b3211 100644
--- a/code/modules/reagents/distilling/distilling.dm
+++ b/code/modules/reagents/machinery/distillery.dm
@@ -53,31 +53,16 @@
var/image/overlay_dumping
var/image/overlay_connected
-// Our unique beaker, used in its unique recipes to ensure things can only react inside this machine and minimize oddities from trying to transfer to a machine and back.
- var/obj/item/weapon/reagent_containers/glass/distilling/Reservoir
-
var/obj/item/weapon/reagent_containers/glass/InputBeaker
var/obj/item/weapon/reagent_containers/glass/OutputBeaker
// A multiplier for the production amount. This should really only ever be lower than one, otherwise you end up with duping.
var/efficiency = 1
-/obj/item/weapon/reagent_containers/glass/distilling
- name = "distilling chamber"
- desc = "You should not be seeing this."
- volume = 600
-
- var/obj/machinery/portable_atmospherics/powered/reagent_distillery/Master
-
-/obj/item/weapon/reagent_containers/glass/distilling/Destroy()
- Master = null
- ..()
-
/obj/machinery/portable_atmospherics/powered/reagent_distillery/Initialize()
. = ..()
- Reservoir = new (src)
- Reservoir.Master = src
+ create_reagents(600, /datum/reagents/distilling)
if(!base_state)
base_state = icon_state
@@ -107,8 +92,6 @@
overlay_connected = image(icon = src.icon, icon_state = "[base_state]-connector")
/obj/machinery/portable_atmospherics/powered/reagent_distillery/Destroy()
- qdel(Reservoir)
- Reservoir = null
if(InputBeaker)
qdel(InputBeaker)
InputBeaker = null
@@ -134,8 +117,8 @@
else
. += "\The [src]'s input beaker is empty!"
- if(Reservoir.reagents.reagent_list.len)
- . += "\The [src]'s internal buffer holds [Reservoir.reagents.total_volume] units of liquid."
+ if(reagents.reagent_list.len)
+ . += "\The [src]'s internal buffer holds [reagents.total_volume] units of liquid."
else
. += "\The [src]'s internal buffer is empty!"
@@ -164,7 +147,7 @@
to_chat(user, "You press \the [src]'s chamber agitator button.")
if(on)
visible_message("\The [src] rattles to life.")
- Reservoir.reagents.handle_reactions()
+ reagents.handle_reactions()
else
spawn(1 SECOND)
to_chat(user, "Nothing happens..")
@@ -341,12 +324,12 @@
visible_message("\The [src]'s motors wind down.")
on = FALSE
- if(InputBeaker && Reservoir.reagents.total_volume < Reservoir.reagents.maximum_volume)
- InputBeaker.reagents.trans_to_holder(Reservoir.reagents, amount = rand(10,20))
+ if(InputBeaker && reagents.total_volume < reagents.maximum_volume)
+ InputBeaker.reagents.trans_to_holder(reagents, amount = rand(10,20))
if(OutputBeaker && OutputBeaker.reagents.total_volume < OutputBeaker.reagents.maximum_volume)
use_power(power_rating * CELLRATE * 0.5)
- Reservoir.reagents.trans_to_holder(OutputBeaker.reagents, amount = rand(1, 5))
+ reagents.trans_to_holder(OutputBeaker.reagents, amount = rand(1, 5))
update_icon()
diff --git a/code/modules/reagents/machinery/grinder.dm b/code/modules/reagents/machinery/grinder.dm
new file mode 100644
index 0000000000..6be08f67e7
--- /dev/null
+++ b/code/modules/reagents/machinery/grinder.dm
@@ -0,0 +1,263 @@
+/obj/machinery/reagentgrinder
+
+ name = "All-In-One Grinder"
+ desc = "Grinds stuff into itty bitty bits."
+ icon = 'icons/obj/kitchen.dmi'
+ icon_state = "juicer1"
+ density = 0
+ anchored = 0
+ use_power = USE_POWER_IDLE
+ idle_power_usage = 5
+ active_power_usage = 100
+ circuit = /obj/item/weapon/circuitboard/grinder
+ var/inuse = 0
+ var/obj/item/weapon/reagent_containers/beaker = null
+ var/limit = 10
+ var/list/holdingitems = list()
+ var/list/sheet_reagents = list( //have a number of reageents divisible by REAGENTS_PER_SHEET (default 20) unless you like decimals,
+ /obj/item/stack/material/iron = list("iron"),
+ /obj/item/stack/material/uranium = list("uranium"),
+ /obj/item/stack/material/phoron = list("phoron"),
+ /obj/item/stack/material/gold = list("gold"),
+ /obj/item/stack/material/silver = list("silver"),
+ /obj/item/stack/material/platinum = list("platinum"),
+ /obj/item/stack/material/mhydrogen = list("hydrogen"),
+ /obj/item/stack/material/steel = list("iron", "carbon"),
+ /obj/item/stack/material/plasteel = list("iron", "iron", "carbon", "carbon", "platinum"), //8 iron, 8 carbon, 4 platinum,
+ /obj/item/stack/material/snow = list("water"),
+ /obj/item/stack/material/sandstone = list("silicon", "oxygen"),
+ /obj/item/stack/material/glass = list("silicon"),
+ /obj/item/stack/material/glass/phoronglass = list("platinum", "silicon", "silicon", "silicon"), //5 platinum, 15 silicon,
+ )
+
+ var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine")
+ var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject")
+ var/static/radial_grind = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_grind")
+ // var/static/radial_juice = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_juice")
+ // var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix")
+
+/obj/machinery/reagentgrinder/Initialize()
+ . = ..()
+ beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
+ default_apply_parts()
+
+/obj/machinery/reagentgrinder/examine(mob/user)
+ . = ..()
+ if(!in_range(user, src) && !issilicon(user) && !isobserver(user))
+ . += "You're too far away to examine [src]'s contents and display!"
+ return
+
+ if(inuse)
+ . += "\The [src] is operating."
+ return
+
+ if(beaker || length(holdingitems))
+ . += "\The [src] contains:"
+ if(beaker)
+ . += "- \A [beaker]."
+ for(var/i in holdingitems)
+ var/obj/item/O = i
+ . += "- \A [O.name]."
+
+ if(!(stat & (NOPOWER|BROKEN)))
+ . += "The status display reads:\n"
+ if(beaker)
+ for(var/datum/reagent/R in beaker.reagents.reagent_list)
+ . += "- [R.volume] units of [R.name]."
+
+/obj/machinery/reagentgrinder/update_icon()
+ icon_state = "juicer"+num2text(!isnull(beaker))
+ return
+
+/obj/machinery/reagentgrinder/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(beaker)
+ if(default_deconstruction_screwdriver(user, O))
+ return
+ if(default_deconstruction_crowbar(user, O))
+ return
+
+ if (istype(O,/obj/item/weapon/reagent_containers/glass) || \
+ istype(O,/obj/item/weapon/reagent_containers/food/drinks/glass2) || \
+ istype(O,/obj/item/weapon/reagent_containers/food/drinks/shaker))
+
+ if (beaker)
+ return 1
+ else
+ src.beaker = O
+ user.drop_item()
+ O.loc = src
+ update_icon()
+ src.updateUsrDialog()
+ return 0
+
+ if(holdingitems && holdingitems.len >= limit)
+ to_chat(user, "The machine cannot hold anymore items.")
+ return 1
+
+ if(!istype(O))
+ return
+
+ if(istype(O,/obj/item/weapon/storage/bag/plants))
+ var/obj/item/weapon/storage/bag/plants/bag = O
+ var/failed = 1
+ for(var/obj/item/G in O.contents)
+ if(!G.reagents || !G.reagents.total_volume)
+ continue
+ failed = 0
+ bag.remove_from_storage(G, src)
+ holdingitems += G
+ if(holdingitems && holdingitems.len >= limit)
+ break
+
+ if(failed)
+ to_chat(user, "Nothing in the plant bag is usable.")
+ return 1
+
+ if(!O.contents.len)
+ to_chat(user, "You empty \the [O] into \the [src].")
+ else
+ to_chat(user, "You fill \the [src] from \the [O].")
+
+ src.updateUsrDialog()
+ return 0
+
+ if(istype(O,/obj/item/weapon/gripper))
+ var/obj/item/weapon/gripper/B = O //B, for Borg.
+ if(!B.wrapped)
+ to_chat(user, "\The [B] is not holding anything.")
+ return 0
+ else
+ var/B_held = B.wrapped
+ to_chat(user, "You use \the [B] to load \the [src] with \the [B_held].")
+
+ return 0
+
+ if(!sheet_reagents[O.type] && (!O.reagents || !O.reagents.total_volume))
+ to_chat(user, "\The [O] is not suitable for blending.")
+ return 1
+
+ user.remove_from_mob(O)
+ O.loc = src
+ holdingitems += O
+ return 0
+
+/obj/machinery/reagentgrinder/AltClick(mob/user)
+ . = ..()
+ if(user.incapacitated() || !Adjacent(user))
+ return
+ replace_beaker(user)
+
+/obj/machinery/reagentgrinder/attack_hand(mob/user as mob)
+ interact(user)
+
+/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu //I am reasonably certain that this is not a microwave
+ if(inuse || user.incapacitated())
+ return
+
+ var/list/options = list()
+
+ if(beaker || length(holdingitems))
+ options["eject"] = radial_eject
+
+ if(isAI(user))
+ if(stat & NOPOWER)
+ return
+ options["examine"] = radial_examine
+
+ // if there is no power or it's broken, the procs will fail but the buttons will still show
+ if(length(holdingitems))
+ options["grind"] = radial_grind
+
+ var/choice
+ if(length(options) < 1)
+ return
+ if(length(options) == 1)
+ for(var/key in options)
+ choice = key
+ else
+ choice = show_radial_menu(user, src, options, require_near = !issilicon(user))
+
+ // post choice verification
+ if(inuse || (isAI(user) && stat & NOPOWER) || user.incapacitated())
+ return
+
+ switch(choice)
+ if("eject")
+ eject(user)
+ if("grind")
+ grind(user)
+ if("examine")
+ examine(user)
+
+/obj/machinery/reagentgrinder/proc/eject(mob/user)
+ if(user.incapacitated())
+ return
+ for(var/obj/item/O in holdingitems)
+ O.loc = src.loc
+ holdingitems -= O
+ holdingitems.Cut()
+ if(beaker)
+ replace_beaker(user)
+
+/obj/machinery/reagentgrinder/proc/grind()
+
+ power_change()
+ if(stat & (NOPOWER|BROKEN))
+ return
+
+ // Sanity check.
+ if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume))
+ return
+
+ playsound(src, 'sound/machines/blender.ogg', 50, 1)
+ inuse = 1
+
+ // Reset the machine.
+ spawn(60)
+ inuse = 0
+
+ // Process.
+ for (var/obj/item/O in holdingitems)
+
+ var/remaining_volume = beaker.reagents.maximum_volume - beaker.reagents.total_volume
+ if(remaining_volume <= 0)
+ break
+
+ if(sheet_reagents[O.type])
+ var/obj/item/stack/stack = O
+ if(istype(stack))
+ var/list/sheet_components = sheet_reagents[stack.type]
+ var/amount_to_take = max(0,min(stack.amount,round(remaining_volume/REAGENTS_PER_SHEET)))
+ if(amount_to_take)
+ stack.use(amount_to_take)
+ if(QDELETED(stack))
+ holdingitems -= stack
+ if(islist(sheet_components))
+ amount_to_take = (amount_to_take/(sheet_components.len))
+ for(var/i in sheet_components)
+ beaker.reagents.add_reagent(i, (amount_to_take*REAGENTS_PER_SHEET))
+ else
+ beaker.reagents.add_reagent(sheet_components, (amount_to_take*REAGENTS_PER_SHEET))
+ continue
+
+ if(O.reagents)
+ O.reagents.trans_to_obj(beaker, min(O.reagents.total_volume, remaining_volume))
+ if(O.reagents.total_volume == 0)
+ holdingitems -= O
+ qdel(O)
+ if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
+ break
+
+/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/weapon/reagent_containers/new_beaker)
+ if(!user)
+ return FALSE
+ if(beaker)
+ if(!user.incapacitated() && Adjacent(user))
+ user.put_in_hands(beaker)
+ else
+ beaker.forceMove(drop_location())
+ beaker = null
+ if(new_beaker)
+ beaker = new_beaker
+ update_icon()
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/reagents/reactions/_reactions.dm b/code/modules/reagents/reactions/_reactions.dm
new file mode 100644
index 0000000000..d63967d900
--- /dev/null
+++ b/code/modules/reagents/reactions/_reactions.dm
@@ -0,0 +1,128 @@
+//helper that ensures the reaction rate holds after iterating
+//Ex. REACTION_RATE(0.3) means that 30% of the reagents will react each chemistry tick (~2 seconds by default).
+#define REACTION_RATE(rate) (1.0 - (1.0-rate)**(1.0/PROCESS_REACTION_ITER))
+
+//helper to define reaction rate in terms of half-life
+//Ex.
+//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.
+#define HALF_LIFE(ticks) (ticks? 1.0 - (0.5)**(1.0/(ticks*PROCESS_REACTION_ITER)) : 1.0)
+
+/decl/chemical_reaction
+ var/name = null
+ var/id = null
+ var/result = null
+ var/list/required_reagents = list()
+ var/list/catalysts = list()
+ var/list/inhibitors = list()
+ var/result_amount = 0
+
+ //how far the reaction proceeds each time it is processed. Used with either REACTION_RATE or HALF_LIFE macros.
+ var/reaction_rate = HALF_LIFE(0)
+
+ //if less than 1, the reaction will be inhibited if the ratio of products/reagents is too high.
+ //0.5 = 50% yield -> reaction will only proceed halfway until products are removed.
+ var/yield = 1.0
+
+ //If limits on reaction rate would leave less than this amount of any reagent (adjusted by the reaction ratios),
+ //the reaction goes to completion. This is to prevent reactions from going on forever with tiny reagent amounts.
+ var/min_reaction = 2
+
+ var/mix_message = "The solution begins to bubble."
+ var/reaction_sound = 'sound/effects/bubbles.ogg'
+
+ var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file.
+
+/decl/chemical_reaction/proc/can_happen(var/datum/reagents/holder)
+ //check that all the required reagents are present
+ if(!holder.has_all_reagents(required_reagents))
+ return FALSE
+
+ //check that all the required catalysts are present in the required amount
+ if(!holder.has_all_reagents(catalysts))
+ return FALSE
+
+ //check that none of the inhibitors are present in the required amount
+ if(holder.has_any_reagent(inhibitors))
+ return FALSE
+
+ return TRUE
+
+/decl/chemical_reaction/proc/calc_reaction_progress(var/datum/reagents/holder, var/reaction_limit)
+ var/progress = reaction_limit * reaction_rate //simple exponential progression
+
+ //calculate yield
+ if(1-yield > 0.001) //if yield ratio is big enough just assume it goes to completion
+ /*
+ Determine the max amount of product by applying the yield condition:
+ (max_product/result_amount) / reaction_limit == yield/(1-yield)
+
+ We make use of the fact that:
+ reaction_limit = (holder.get_reagent_amount(reactant) / required_reagents[reactant]) of the limiting reagent.
+ */
+ var/yield_ratio = yield/(1-yield)
+ var/max_product = yield_ratio * reaction_limit * result_amount //rearrange to obtain max_product
+ var/yield_limit = max(0, max_product - holder.get_reagent_amount(result))/result_amount
+
+ progress = min(progress, yield_limit) //apply yield limit
+
+ //apply min reaction progress - wasn't sure if this should go before or after applying yield
+ //I guess people can just have their miniscule reactions go to completion regardless of yield.
+ for(var/reactant in required_reagents)
+ var/remainder = holder.get_reagent_amount(reactant) - progress*required_reagents[reactant]
+ if(remainder <= min_reaction*required_reagents[reactant])
+ progress = reaction_limit
+ break
+
+ return progress
+
+/decl/chemical_reaction/process(var/datum/reagents/holder)
+ //determine how far the reaction can proceed
+ var/list/reaction_limits = list()
+ for(var/reactant in required_reagents)
+ reaction_limits += holder.get_reagent_amount(reactant) / required_reagents[reactant]
+
+ //determine how far the reaction proceeds
+ var/reaction_limit = min(reaction_limits)
+ var/progress_limit = calc_reaction_progress(holder, reaction_limit)
+
+ var/reaction_progress = min(reaction_limit, progress_limit) //no matter what, the reaction progress cannot exceed the stoichiometric limit.
+
+ //need to obtain the new reagent's data before anything is altered
+ var/data = send_data(holder, reaction_progress)
+
+ //remove the reactants
+ for(var/reactant in required_reagents)
+ var/amt_used = required_reagents[reactant] * reaction_progress
+ 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)
+
+ on_reaction(holder, amt_produced)
+
+ return reaction_progress
+
+//called when a reaction processes
+/decl/chemical_reaction/proc/on_reaction(var/datum/reagents/holder, var/created_volume)
+ return
+
+//called after processing reactions, if they occurred
+/decl/chemical_reaction/proc/post_reaction(var/datum/reagents/holder)
+ var/atom/container = holder.my_atom
+ if(mix_message && container && !ismob(container))
+ var/turf/T = get_turf(container)
+ var/list/seen = viewers(4, T)
+ for(var/mob/M in seen)
+ if(M.client)
+ M.show_message("[bicon(container)] [mix_message]", 1)
+ 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.
+/decl/chemical_reaction/proc/send_data(var/datum/reagents/holder, var/reaction_limit)
+ return null
\ No newline at end of file
diff --git a/code/modules/reagents/distilling/Distilling-Recipes.dm b/code/modules/reagents/reactions/distilling/distilling.dm
similarity index 74%
rename from code/modules/reagents/distilling/Distilling-Recipes.dm
rename to code/modules/reagents/reactions/distilling/distilling.dm
index 0736ac7e61..5944a75846 100644
--- a/code/modules/reagents/distilling/Distilling-Recipes.dm
+++ b/code/modules/reagents/reactions/distilling/distilling.dm
@@ -1,4 +1,4 @@
-/datum/chemical_reaction/distilling
+/decl/chemical_reaction/distilling
// name = null
// id = null
// result = null
@@ -26,32 +26,19 @@
var/list/temp_range = list(T0C, T20C)
var/temp_shift = 0 // How much the temperature changes when the reaction occurs.
-/datum/chemical_reaction/distilling/can_happen(var/datum/reagents/holder)
- //check that all the required reagents are present
- if(!holder.has_all_reagents(required_reagents))
- return 0
+/decl/chemical_reaction/distilling/can_happen(var/datum/reagents/holder)
+ if(!istype(holder, /datum/reagents/distilling) || !istype(holder.my_atom, /obj/machinery/portable_atmospherics/powered/reagent_distillery))
+ return FALSE
- //check that all the required catalysts are present in the required amount
- if(!holder.has_all_reagents(catalysts))
- return 0
+ // Super special temperature check.
+ var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = holder.my_atom
+ if(RD.current_temp < temp_range[1] || RD.current_temp > temp_range[2])
+ return FALSE
- //check that none of the inhibitors are present in the required amount
- if(holder.has_any_reagent(inhibitors))
- return 0
-
- if(!istype(holder.my_atom, /obj/item/weapon/reagent_containers/glass/distilling))
- return 0
-
- else // Super special temperature check.
- var/obj/item/weapon/reagent_containers/glass/distilling/D = holder.my_atom
- var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = D.Master
- if(RD.current_temp < temp_range[1] || RD.current_temp > temp_range[2])
- return 0
-
- return 1
+ return ..()
/*
-/datum/chemical_reaction/distilling/on_reaction(var/datum/reagents/holder, var/created_volume)
+/decl/chemical_reaction/distilling/on_reaction(var/datum/reagents/holder, var/created_volume)
if(istype(holder.my_atom, /obj/item/weapon/reagent_containers/glass/distilling))
var/obj/item/weapon/reagent_containers/glass/distilling/D = holder.my_atom
var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = D.Master
@@ -62,7 +49,7 @@
// Subtypes //
// Biomass
-/datum/chemical_reaction/distilling/biomass
+/decl/chemical_reaction/distilling/biomass
name = "Distilling Biomass"
id = "distill_biomass"
result = "biomass"
@@ -73,7 +60,7 @@
temp_shift = -2
// Medicinal
-/datum/chemical_reaction/distilling/inaprovalaze
+/decl/chemical_reaction/distilling/inaprovalaze
name = "Distilling Inaprovalaze"
id = "distill_inaprovalaze"
result = "inaprovalaze"
@@ -84,7 +71,7 @@
temp_range = list(T0C + 100, T0C + 120)
-/datum/chemical_reaction/distilling/bicaridaze
+/decl/chemical_reaction/distilling/bicaridaze
name = "Distilling Bicaridaze"
id = "distill_bicaridaze"
result = "bicaridaze"
@@ -95,7 +82,7 @@
temp_range = list(T0C + 110, T0C + 130)
-/datum/chemical_reaction/distilling/dermalaze
+/decl/chemical_reaction/distilling/dermalaze
name = "Distilling Dermalaze"
id = "distill_dermalaze"
result = "dermalaze"
@@ -106,7 +93,7 @@
temp_range = list(T0C + 115, T0C + 130)
-/datum/chemical_reaction/distilling/spacomycaze
+/decl/chemical_reaction/distilling/spacomycaze
name = "Distilling Spacomycaze"
id = "distill_spacomycaze"
result = "spacomycaze"
@@ -117,7 +104,7 @@
temp_range = list(T0C + 100, T0C + 120)
-/datum/chemical_reaction/distilling/tricorlidaze
+/decl/chemical_reaction/distilling/tricorlidaze
name = "Distilling Tricorlidaze"
id = "distill_tricorlidaze"
result = "tricorlidaze"
@@ -128,7 +115,7 @@
temp_range = list(T0C + 100, T0C + 120)
-/datum/chemical_reaction/distilling/synthplas
+/decl/chemical_reaction/distilling/synthplas
name = "Distilling Synthplas"
id = "distill_synthplas"
result = "synthblood_dilute"
@@ -140,7 +127,7 @@
temp_range = list(T0C + 110, T0C + 130)
// Alcohol
-/datum/chemical_reaction/distilling/beer
+/decl/chemical_reaction/distilling/beer
name = "Distilling Beer"
id = "distill_beer"
result = "beer"
@@ -151,7 +138,7 @@
temp_range = list(T20C, T20C + 2)
-/datum/chemical_reaction/distilling/ale
+/decl/chemical_reaction/distilling/ale
name = "Distilling Ale"
id = "distill_ale"
result = "ale"
@@ -165,7 +152,7 @@
temp_range = list(T0C + 7, T0C + 13)
// Unique
-/datum/chemical_reaction/distilling/berserkjuice
+/decl/chemical_reaction/distilling/berserkjuice
name = "Distilling Brute Juice"
id = "distill_brutejuice"
result = "berserkmed"
@@ -175,7 +162,7 @@
temp_range = list(T0C + 600, T0C + 700)
temp_shift = 4
-/datum/chemical_reaction/distilling/berserkjuice/on_reaction(var/datum/reagents/holder, var/created_volume)
+/decl/chemical_reaction/distilling/berserkjuice/on_reaction(var/datum/reagents/holder, var/created_volume)
..()
if(prob(1))
@@ -183,7 +170,7 @@
explosion(T, -1, rand(-1, 1), rand(1,2), rand(3,5))
return
-/datum/chemical_reaction/distilling/cryogel
+/decl/chemical_reaction/distilling/cryogel
name = "Distilling Cryogellatin"
id = "distill_cryoslurry"
result = "cryoslurry"
@@ -194,7 +181,7 @@
temp_range = list(0, 15)
temp_shift = 20
-/datum/chemical_reaction/distilling/cryogel/on_reaction(var/datum/reagents/holder, var/created_volume)
+/decl/chemical_reaction/distilling/cryogel/on_reaction(var/datum/reagents/holder, var/created_volume)
..()
if(prob(1))
@@ -204,7 +191,7 @@
F.start()
return
-/datum/chemical_reaction/distilling/lichpowder
+/decl/chemical_reaction/distilling/lichpowder
name = "Distilling Lichpowder"
id = "distill_lichpowder"
result = "lichpowder"
@@ -215,7 +202,7 @@
temp_range = list(T0C + 100, T0C + 150)
-/datum/chemical_reaction/distilling/necroxadone
+/decl/chemical_reaction/distilling/necroxadone
name = "Distilling Necroxadone"
id = "distill_necroxadone"
result = "necroxadone"
diff --git a/code/modules/reagents/reactions/fusion/fusion.dm b/code/modules/reagents/reactions/fusion/fusion.dm
new file mode 100644
index 0000000000..7b0acfec96
--- /dev/null
+++ b/code/modules/reagents/reactions/fusion/fusion.dm
@@ -0,0 +1,6 @@
+// TDOD: Port R-UST fusion reactions to the chemistry system.
+//They'll operate in a similar manner to distillery reactions,
+// but will have distinct behaviours (mostly relating to the fusion field) that warrants a separate type
+/*
+/decl/chemical_reaction/fusion
+ name = "Fusion"*/
\ No newline at end of file
diff --git a/code/modules/reagents/reactions/instant/drinks.dm b/code/modules/reagents/reactions/instant/drinks.dm
new file mode 100644
index 0000000000..75de64b284
--- /dev/null
+++ b/code/modules/reagents/reactions/instant/drinks.dm
@@ -0,0 +1,1223 @@
+/decl/chemical_reaction/instant/drinks/coffee
+ name = "Coffee"
+ id = "coffee"
+ result = "coffee"
+ required_reagents = list("water" = 5, "coffeepowder" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/tea
+ name = "Black tea"
+ id = "tea"
+ result = "tea"
+ required_reagents = list("water" = 5, "teapowder" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/hot_coco
+ name = "Hot Coco"
+ id = "hot_coco"
+ result = "hot_coco"
+ required_reagents = list("water" = 5, "coco" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/grapejuice
+ name = "Grape Juice"
+ id = "grapejuice"
+ result = "grapejuice"
+ required_reagents = list("water" = 3, "instantgrape" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/orangejuice
+ name = "Orange Juice"
+ id = "orangejuice"
+ result = "orangejuice"
+ required_reagents = list("water" = 3, "instantorange" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/watermelonjuice
+ name = "Watermelon Juice"
+ id = "watermelonjuice"
+ result = "watermelonjuice"
+ required_reagents = list("water" = 3, "instantwatermelon" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/applejuice
+ name = "Apple Juice"
+ id = "applejuice"
+ result = "applejuice"
+ required_reagents = list("water" = 3, "instantapple" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/goldschlager
+ name = "Goldschlager"
+ id = "goldschlager"
+ result = "goldschlager"
+ required_reagents = list("vodka" = 10, "gold" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/patron
+ name = "Patron"
+ id = "patron"
+ result = "patron"
+ required_reagents = list("tequilla" = 10, "silver" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/bilk
+ name = "Bilk"
+ id = "bilk"
+ result = "bilk"
+ required_reagents = list("milk" = 1, "beer" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/icetea
+ name = "Iced Tea"
+ id = "icetea"
+ result = "icetea"
+ required_reagents = list("ice" = 1, "tea" = 2)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/icecoffee
+ name = "Iced Coffee"
+ id = "icecoffee"
+ result = "icecoffee"
+ required_reagents = list("ice" = 1, "coffee" = 2)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/nuka_cola
+ name = "Nuclear Cola"
+ id = "nuka_cola"
+ result = "nuka_cola"
+ required_reagents = list("uranium" = 1, "cola" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/moonshine
+ name = "Moonshine"
+ id = "moonshine"
+ result = "moonshine"
+ required_reagents = list("nutriment" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/grenadine
+ name = "Grenadine Syrup"
+ id = "grenadine"
+ result = "grenadine"
+ required_reagents = list("berryjuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/wine
+ name = "Wine"
+ id = "wine"
+ result = "wine"
+ required_reagents = list("grapejuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/pwine
+ name = "Poison Wine"
+ id = "pwine"
+ result = "pwine"
+ required_reagents = list("poisonberryjuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/melonliquor
+ name = "Melon Liquor"
+ id = "melonliquor"
+ result = "melonliquor"
+ required_reagents = list("watermelonjuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/bluecuracao
+ name = "Blue Curacao"
+ id = "bluecuracao"
+ result = "bluecuracao"
+ required_reagents = list("orangejuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/spacebeer
+ name = "Space Beer"
+ id = "spacebeer"
+ result = "beer"
+ required_reagents = list("cornoil" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/vodka
+ name = "Vodka"
+ id = "vodka"
+ result = "vodka"
+ required_reagents = list("potatojuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/cider
+ name = "Cider"
+ id = "cider"
+ result = "cider"
+ required_reagents = list("applejuice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+
+/decl/chemical_reaction/instant/drinks/sake
+ name = "Sake"
+ id = "sake"
+ result = "sake"
+ required_reagents = list("rice" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/kahlua
+ name = "Kahlua"
+ id = "kahlua"
+ result = "kahlua"
+ required_reagents = list("coffee" = 5, "sugar" = 5)
+ catalysts = list("enzyme" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/gin_tonic
+ name = "Gin and Tonic"
+ id = "gintonic"
+ result = "gintonic"
+ required_reagents = list("gin" = 2, "tonic" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/cuba_libre
+ name = "Cuba Libre"
+ id = "cubalibre"
+ result = "cubalibre"
+ required_reagents = list("rum" = 2, "cola" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/martini
+ name = "Classic Martini"
+ id = "martini"
+ result = "martini"
+ required_reagents = list("gin" = 2, "vermouth" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/vodkamartini
+ name = "Vodka Martini"
+ id = "vodkamartini"
+ result = "vodkamartini"
+ required_reagents = list("vodka" = 2, "vermouth" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/white_russian
+ name = "White Russian"
+ id = "whiterussian"
+ result = "whiterussian"
+ required_reagents = list("blackrussian" = 2, "cream" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/whiskey_cola
+ name = "Whiskey Cola"
+ id = "whiskeycola"
+ result = "whiskeycola"
+ required_reagents = list("whiskey" = 2, "cola" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/screwdriver
+ name = "Screwdriver"
+ id = "screwdrivercocktail"
+ result = "screwdrivercocktail"
+ required_reagents = list("vodka" = 2, "orangejuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/bloody_mary
+ name = "Bloody Mary"
+ id = "bloodymary"
+ result = "bloodymary"
+ required_reagents = list("vodka" = 2, "tomatojuice" = 3, "limejuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/gargle_blaster
+ name = "Pan-Galactic Gargle Blaster"
+ id = "gargleblaster"
+ result = "gargleblaster"
+ required_reagents = list("vodka" = 2, "gin" = 1, "whiskey" = 1, "cognac" = 1, "limejuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/brave_bull
+ name = "Brave Bull"
+ id = "bravebull"
+ result = "bravebull"
+ required_reagents = list("tequilla" = 2, "kahlua" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/tequilla_sunrise
+ name = "Tequilla Sunrise"
+ id = "tequillasunrise"
+ result = "tequillasunrise"
+ required_reagents = list("tequilla" = 2, "orangejuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/phoron_special
+ name = "Toxins Special"
+ id = "phoronspecial"
+ result = "phoronspecial"
+ required_reagents = list("rum" = 2, "vermouth" = 2, "phoron" = 2)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/beepsky_smash
+ name = "Beepksy Smash"
+ id = "beepksysmash"
+ result = "beepskysmash"
+ required_reagents = list("limejuice" = 1, "whiskey" = 1, "iron" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/doctor_delight
+ name = "The Doctor's Delight"
+ id = "doctordelight"
+ result = "doctorsdelight"
+ required_reagents = list("limejuice" = 1, "tomatojuice" = 1, "orangejuice" = 1, "cream" = 2, "tricordrazine" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/irish_cream
+ name = "Irish Cream"
+ id = "irishcream"
+ result = "irishcream"
+ required_reagents = list("whiskey" = 2, "cream" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/manly_dorf
+ name = "The Manly Dorf"
+ id = "manlydorf"
+ result = "manlydorf"
+ required_reagents = list ("beer" = 1, "ale" = 2)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/hooch
+ name = "Hooch"
+ id = "hooch"
+ result = "hooch"
+ required_reagents = list ("sugar" = 1, "ethanol" = 2, "fuel" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/irish_coffee
+ name = "Irish Coffee"
+ id = "irishcoffee"
+ result = "irishcoffee"
+ required_reagents = list("irishcream" = 1, "coffee" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/b52
+ name = "B-52"
+ id = "b52"
+ result = "b52"
+ required_reagents = list("irishcream" = 1, "kahlua" = 1, "cognac" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/atomicbomb
+ name = "Atomic Bomb"
+ id = "atomicbomb"
+ result = "atomicbomb"
+ required_reagents = list("b52" = 10, "uranium" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/margarita
+ name = "Margarita"
+ id = "margarita"
+ result = "margarita"
+ required_reagents = list("tequilla" = 2, "limejuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/longislandicedtea
+ name = "Long Island Iced Tea"
+ id = "longislandicedtea"
+ result = "longislandicedtea"
+ required_reagents = list("vodka" = 1, "gin" = 1, "tequilla" = 1, "cubalibre" = 3)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/icedtea
+ name = "Long Island Iced Tea"
+ id = "longislandicedtea"
+ result = "longislandicedtea"
+ required_reagents = list("vodka" = 1, "gin" = 1, "tequilla" = 1, "cubalibre" = 3)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/threemileisland
+ name = "Three Mile Island Iced Tea"
+ id = "threemileisland"
+ result = "threemileisland"
+ required_reagents = list("longislandicedtea" = 10, "uranium" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/whiskeysoda
+ name = "Whiskey Soda"
+ id = "whiskeysoda"
+ result = "whiskeysoda"
+ required_reagents = list("whiskey" = 2, "sodawater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/black_russian
+ name = "Black Russian"
+ id = "blackrussian"
+ result = "blackrussian"
+ required_reagents = list("vodka" = 2, "kahlua" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/manhattan
+ name = "Manhattan"
+ id = "manhattan"
+ result = "manhattan"
+ required_reagents = list("whiskey" = 2, "vermouth" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/manhattan_proj
+ name = "Manhattan Project"
+ id = "manhattan_proj"
+ result = "manhattan_proj"
+ required_reagents = list("manhattan" = 10, "uranium" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/vodka_tonic
+ name = "Vodka and Tonic"
+ id = "vodkatonic"
+ result = "vodkatonic"
+ required_reagents = list("vodka" = 2, "tonic" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/gin_fizz
+ name = "Gin Fizz"
+ id = "ginfizz"
+ result = "ginfizz"
+ required_reagents = list("gin" = 1, "sodawater" = 1, "limejuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/bahama_mama
+ name = "Bahama mama"
+ id = "bahama_mama"
+ result = "bahama_mama"
+ required_reagents = list("rum" = 2, "orangejuice" = 2, "limejuice" = 1, "ice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/singulo
+ name = "Singulo"
+ id = "singulo"
+ result = "singulo"
+ required_reagents = list("vodka" = 5, "radium" = 1, "wine" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/alliescocktail
+ name = "Allies Cocktail"
+ id = "alliescocktail"
+ result = "alliescocktail"
+ required_reagents = list("martini" = 1, "vodka" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/demonsblood
+ name = "Demons Blood"
+ id = "demonsblood"
+ result = "demonsblood"
+ required_reagents = list("rum" = 3, "spacemountainwind" = 1, "blood" = 1, "dr_gibb" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/booger
+ name = "Booger"
+ id = "booger"
+ result = "booger"
+ required_reagents = list("cream" = 2, "banana" = 1, "rum" = 1, "watermelonjuice" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/antifreeze
+ name = "Anti-freeze"
+ id = "antifreeze"
+ result = "antifreeze"
+ required_reagents = list("vodka" = 1, "cream" = 1, "ice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/barefoot
+ name = "Barefoot"
+ id = "barefoot"
+ result = "barefoot"
+ required_reagents = list("berryjuice" = 1, "cream" = 1, "vermouth" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/grapesoda
+ name = "Grape Soda"
+ id = "grapesoda"
+ result = "grapesoda"
+ required_reagents = list("grapejuice" = 2, "cola" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/sbiten
+ name = "Sbiten"
+ id = "sbiten"
+ result = "sbiten"
+ required_reagents = list("vodka" = 10, "capsaicin" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/red_mead
+ name = "Red Mead"
+ id = "red_mead"
+ result = "red_mead"
+ required_reagents = list("blood" = 1, "mead" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/mead
+ name = "Mead"
+ id = "mead"
+ result = "mead"
+ required_reagents = list("sugar" = 1, "water" = 1)
+ catalysts = list("enzyme" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/iced_beer
+ name = "Iced Beer"
+ id = "iced_beer"
+ result = "iced_beer"
+ required_reagents = list("beer" = 10, "frostoil" = 1)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/iced_beer2
+ name = "Iced Beer"
+ id = "iced_beer"
+ result = "iced_beer"
+ required_reagents = list("beer" = 5, "ice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/grog
+ name = "Grog"
+ id = "grog"
+ result = "grog"
+ required_reagents = list("rum" = 1, "water" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/soy_latte
+ name = "Soy Latte"
+ id = "soy_latte"
+ result = "soy_latte"
+ required_reagents = list("coffee" = 1, "soymilk" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/cafe_latte
+ name = "Cafe Latte"
+ id = "cafe_latte"
+ result = "cafe_latte"
+ required_reagents = list("coffee" = 1, "milk" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/acidspit
+ name = "Acid Spit"
+ id = "acidspit"
+ result = "acidspit"
+ required_reagents = list("sacid" = 1, "wine" = 5)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/amasec
+ name = "Amasec"
+ id = "amasec"
+ result = "amasec"
+ required_reagents = list("iron" = 1, "wine" = 5, "vodka" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/changelingsting
+ name = "Changeling Sting"
+ id = "changelingsting"
+ result = "changelingsting"
+ required_reagents = list("screwdrivercocktail" = 1, "limejuice" = 1, "lemonjuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/aloe
+ name = "Aloe"
+ id = "aloe"
+ result = "aloe"
+ required_reagents = list("cream" = 1, "whiskey" = 1, "watermelonjuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/andalusia
+ name = "Andalusia"
+ id = "andalusia"
+ result = "andalusia"
+ required_reagents = list("rum" = 1, "whiskey" = 1, "lemonjuice" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/snowwhite
+ name = "Snow White"
+ id = "snowwhite"
+ result = "snowwhite"
+ required_reagents = list("beer" = 1, "lemon_lime" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/irishcarbomb
+ name = "Irish Car Bomb"
+ id = "irishcarbomb"
+ result = "irishcarbomb"
+ required_reagents = list("ale" = 1, "irishcream" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/syndicatebomb
+ name = "Syndicate Bomb"
+ id = "syndicatebomb"
+ result = "syndicatebomb"
+ required_reagents = list("beer" = 1, "whiskeycola" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/erikasurprise
+ name = "Erika Surprise"
+ id = "erikasurprise"
+ result = "erikasurprise"
+ required_reagents = list("ale" = 2, "limejuice" = 1, "whiskey" = 1, "banana" = 1, "ice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/devilskiss
+ name = "Devils Kiss"
+ id = "devilskiss"
+ result = "devilskiss"
+ required_reagents = list("blood" = 1, "kahlua" = 1, "rum" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/hippiesdelight
+ name = "Hippies Delight"
+ id = "hippiesdelight"
+ result = "hippiesdelight"
+ required_reagents = list("psilocybin" = 1, "gargleblaster" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/bananahonk
+ name = "Banana Honk"
+ id = "bananahonk"
+ result = "bananahonk"
+ required_reagents = list("banana" = 1, "cream" = 1, "sugar" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/silencer
+ name = "Silencer"
+ id = "silencer"
+ result = "silencer"
+ required_reagents = list("nothing" = 1, "cream" = 1, "sugar" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/driestmartini
+ name = "Driest Martini"
+ id = "driestmartini"
+ result = "driestmartini"
+ required_reagents = list("nothing" = 1, "gin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/lemonade
+ name = "Lemonade"
+ id = "lemonade"
+ result = "lemonade"
+ required_reagents = list("lemonjuice" = 1, "sugar" = 1, "water" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/melonade
+ name = "Melonade"
+ id = "melonade"
+ result = "melonade"
+ required_reagents = list("watermelonjuice" = 1, "sugar" = 1, "sodawater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/appleade
+ name = "Appleade"
+ id = "appleade"
+ result = "appleade"
+ required_reagents = list("applejuice" = 1, "sugar" = 1, "sodawater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/pineappleade
+ name = "Pineappleade"
+ id = "pineappleade"
+ result = "pineappleade"
+ required_reagents = list("pineapplejuice" = 2, "limejuice" = 1, "sodawater" = 2, "honey" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/driverspunch
+ name = "Driver`s Punch"
+ id = "driverspunch"
+ result = "driverspunch"
+ required_reagents = list("appleade" = 2, "orangejuice" = 1, "mint" = 1, "sodawater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/mintapplesparkle
+ name = "Mint Apple Sparkle"
+ id = "mintapplesparkle"
+ result = "mintapplesparkle"
+ required_reagents = list("appleade" = 2, "mint" = 1)
+ inhibitors = list("sodawater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/berrycordial
+ name = "Berry Cordial"
+ id = "berrycordial"
+ result = "berrycordial"
+ required_reagents = list("berryjuice" = 4, "sugar" = 1, "lemonjuice" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/tropicalfizz
+ name = "Tropical Fizz"
+ id = "tropicalfizz"
+ result = "tropicalfizz"
+ required_reagents = list("sodawater" = 6, "berryjuice" = 1, "mint" = 1, "limejuice" = 1, "lemonjuice" = 1, "pineapplejuice" = 1)
+ inhibitors = list("sugar" = 1)
+ result_amount = 8
+
+/decl/chemical_reaction/instant/drinks/melonspritzer
+ name = "Melon Spritzer"
+ id = "melonspritzer"
+ result = "melonspritzer"
+ required_reagents = list("watermelonjuice" = 2, "wine" = 2, "applejuice" = 1, "limejuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/fauxfizz
+ name = "Faux Fizz"
+ id = "fauxfizz"
+ result = "fauxfizz"
+ required_reagents = list("sodawater" = 2, "berryjuice" = 1, "applejuice" = 1, "limejuice" = 1, "honey" = 1)
+ inhibitors = list("sugar" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/firepunch
+ name = "Fire Punch"
+ id = "firepunch"
+ result = "firepunch"
+ required_reagents = list("sugar" = 1, "rum" = 2)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/kiraspecial
+ name = "Kira Special"
+ id = "kiraspecial"
+ result = "kiraspecial"
+ required_reagents = list("orangejuice" = 1, "limejuice" = 1, "sodawater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/brownstar
+ name = "Brown Star"
+ id = "brownstar"
+ result = "brownstar"
+ required_reagents = list("orangejuice" = 2, "cola" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/milkshake
+ name = "Milkshake"
+ id = "milkshake"
+ result = "milkshake"
+ required_reagents = list("cream" = 1, "ice" = 2, "milk" = 2)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/peanutmilkshake
+ name = "Peanutbutter Milkshake"
+ id = "peanutmilkshake"
+ result = "peanutmilkshake"
+ required_reagents = list("cream" = 1, "ice" = 1, "peanutbutter" = 2, "milk" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/rewriter
+ name = "Rewriter"
+ id = "rewriter"
+ result = "rewriter"
+ required_reagents = list("spacemountainwind" = 1, "coffee" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/suidream
+ name = "Sui Dream"
+ id = "suidream"
+ result = "suidream"
+ required_reagents = list("space_up" = 1, "bluecuracao" = 1, "melonliquor" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/shirleytemple
+ name = "Shirley Temple"
+ id = "shirley_temple"
+ result = "shirley_temple"
+ required_reagents = list("gingerale" = 4, "grenadine" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/royrogers
+ name = "Roy Rogers"
+ id = "roy_rogers"
+ result = "roy_rogers"
+ required_reagents = list("shirley_temple" = 5, "lemon_lime" = 2)
+ result_amount = 7
+
+/decl/chemical_reaction/instant/drinks/collinsmix
+ name = "Collins Mix"
+ id = "collins_mix"
+ result = "collins_mix"
+ required_reagents = list("lemon_lime" = 3, "sodawater" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/arnoldpalmer
+ name = "Arnold Palmer"
+ id = "arnold_palmer"
+ result = "arnold_palmer"
+ required_reagents = list("icetea" = 1, "lemonade" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/minttea
+ name = "Mint Tea"
+ id = "minttea"
+ result = "minttea"
+ required_reagents = list("tea" = 5, "mint" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/lemontea
+ name = "Lemon Tea"
+ id = "lemontea"
+ result = "lemontea"
+ required_reagents = list("tea" = 5, "lemonjuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/limetea
+ name = "Lime Tea"
+ id = "limetea"
+ result = "limetea"
+ required_reagents = list("tea" = 5, "limejuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/orangetea
+ name = "Orange Tea"
+ id = "orangetea"
+ result = "orangetea"
+ required_reagents = list("tea" = 5, "orangejuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/berrytea
+ name = "Berry Tea"
+ id = "berrytea"
+ result = "berrytea"
+ required_reagents = list("tea" = 5, "berryjuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/sakebomb
+ name = "Sake Bomb"
+ id = "sakebomb"
+ result = "sakebomb"
+ required_reagents = list("beer" = 2, "sake" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/tamagozake
+ name = "Tamagozake"
+ id = "tamagozake"
+ result = "tamagozake"
+ required_reagents = list("sake" = 10, "sugar" = 5, "egg" = 3)
+ result_amount = 15
+
+/decl/chemical_reaction/instant/drinks/ginzamary
+ name = "Ginza Mary"
+ id = "ginzamary"
+ result = "ginzamary"
+ required_reagents = list("sake" = 2, "vodka" = 2, "tomatojuice" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/tokyorose
+ name = "Tokyo Rose"
+ id = "tokyorose"
+ result = "tokyorose"
+ required_reagents = list("sake" = 1, "berryjuice" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/saketini
+ name = "Saketini"
+ id = "saketini"
+ result = "saketini"
+ required_reagents = list("sake" = 1, "gin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/elysiumfacepunch
+ name = "Elysium Facepunch"
+ id = "elysiumfacepunch"
+ result = "elysiumfacepunch"
+ required_reagents = list("kahlua" = 1, "lemonjuice" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/erebusmoonrise
+ name = "Erebus Moonrise"
+ id = "erebusmoonrise"
+ result = "erebusmoonrise"
+ required_reagents = list("whiskey" = 1, "vodka" = 1, "tequilla" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/balloon
+ name = "Balloon"
+ id = "balloon"
+ result = "balloon"
+ required_reagents = list("cream" = 1, "bluecuracao" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/natunabrandy
+ name = "Natuna Brandy"
+ id = "natunabrandy"
+ result = "natunabrandy"
+ required_reagents = list("beer" = 1, "sodawater" = 2)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/euphoria
+ name = "Euphoria"
+ id = "euphoria"
+ result = "euphoria"
+ required_reagents = list("specialwhiskey" = 1, "cognac" = 2)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/xanaducannon
+ name = "Xanadu Cannon"
+ id = "xanaducannon"
+ result = "xanaducannon"
+ required_reagents = list("ale" = 1, "dr_gibb" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/debugger
+ name = "Debugger"
+ id = "debugger"
+ result = "debugger"
+ required_reagents = list("fuel" = 1, "sugar" = 2, "cornoil" = 2)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/spacersbrew
+ name = "Spacer's Brew"
+ id = "spacersbrew"
+ result = "spacersbrew"
+ required_reagents = list("brownstar" = 4, "ethanol" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/binmanbliss
+ name = "Binman Bliss"
+ id = "binmanbliss"
+ result = "binmanbliss"
+ required_reagents = list("sake" = 1, "tequilla" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/chrysanthemum
+ name = "Chrysanthemum"
+ id = "chrysanthemum"
+ result = "chrysanthemum"
+ required_reagents = list("sake" = 1, "melonliquor" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/deathbell
+ name = "Deathbell"
+ id = "deathbell"
+ result = "deathbell"
+ required_reagents = list("antifreeze" = 1, "gargleblaster" = 1, "syndicatebomb" =1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/bitters
+ name = "Bitters"
+ id = "bitters"
+ result = "bitters"
+ required_reagents = list("mint" = 5)
+ catalysts = list("enzyme" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/soemmerfire
+ name = "Soemmer Fire"
+ id = "soemmerfire"
+ result = "soemmerfire"
+ required_reagents = list("manhattan" = 2, "condensedcapsaicin" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/winebrandy
+ name = "Wine brandy"
+ id = "winebrandy"
+ result = "winebrandy"
+ required_reagents = list("wine" = 10)
+ catalysts = list("enzyme" = 10) //10u enzyme so it requires more than is usually added. Stops overlap with wine recipe
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/lovepotion
+ name = "Love Potion"
+ id = "lovepotion"
+ result = "lovepotion"
+ required_reagents = list("cream" = 1, "berryjuice" = 1, "sugar" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/morningafter
+ name = "Morning After"
+ id = "morningafter"
+ result = "morningafter"
+ required_reagents = list("sbiten" = 1, "coffee" = 5)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/vesper
+ name = "Vesper"
+ id = "vesper"
+ result = "vesper"
+ required_reagents = list("gin" = 3, "vodka" = 1, "wine" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/rotgut
+ name = "Rotgut Fever Dream"
+ id = "rotgut"
+ result = "rotgut"
+ required_reagents = list("vodka" = 3, "rum" = 1, "whiskey" = 1, "cola" = 3)
+ result_amount = 8
+
+/decl/chemical_reaction/instant/drinks/entdraught
+ name = "Ent's Draught"
+ id = "entdraught"
+ result = "entdraught"
+ required_reagents = list("tonic" = 1, "holywater" = 1, "honey" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/voxdelight
+ name = "Vox's Delight"
+ id = "voxdelight"
+ result = "voxdelight"
+ required_reagents = list("phoron" = 3, "fuel" = 1, "water" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/screamingviking
+ name = "Screaming Viking"
+ id = "screamingviking"
+ result = "screamingviking"
+ required_reagents = list("martini" = 2, "vodkatonic" = 2, "limejuice" = 1, "rum" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/vilelemon
+ name = "Vile Lemon"
+ id = "vilelemon"
+ result = "vilelemon"
+ required_reagents = list("lemonade" = 5, "spacemountainwind" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/dreamcream
+ name = "Dream Cream"
+ id = "dreamcream"
+ result = "dreamcream"
+ required_reagents = list("milk" = 2, "cream" = 1, "honey" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/robustin
+ name = "Robustin"
+ id = "robustin"
+ result = "robustin"
+ required_reagents = list("antifreeze" = 1, "phoron" = 1, "fuel" = 1, "vodka" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/virginsip
+ name = "Virgin Sip"
+ id = "virginsip"
+ result = "virginsip"
+ required_reagents = list("driestmartini" = 1, "water" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/chocoshake
+ name = "Chocolate Milkshake"
+ id = "chocoshake"
+ result = "chocoshake"
+ required_reagents = list("milkshake" = 1, "coco" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/berryshake
+ name = "Berry Milkshake"
+ id = "berryshake"
+ result = "berryshake"
+ required_reagents = list("milkshake" = 1, "berryjuice" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/coffeeshake
+ name = "Coffee Milkshake"
+ id = "coffeeshake"
+ result = "coffeeshake"
+ required_reagents = list("milkshake" = 1, "coffee" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/jellyshot
+ name = "Jelly Shot"
+ id = "jellyshot"
+ result = "jellyshot"
+ required_reagents = list("cherryjelly" = 4, "vodka" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/slimeshot
+ name = "Named Bullet"
+ id = "slimeshot"
+ result = "slimeshot"
+ required_reagents = list("slimejelly" = 4, "vodka" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/negroni
+ name = "Negroni"
+ id = "negroni"
+ result = "negroni"
+ required_reagents = list("gin" = 1, "bitters" = 1, "vermouth" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/cloverclub
+ name = "Clover Club"
+ id = "cloverclub"
+ result = "cloverclub"
+ required_reagents = list("berryjuice" = 1, "lemonjuice" = 1, "gin" = 3)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/oldfashioned
+ name = "Old Fashioned"
+ id = "oldfashioned"
+ result = "oldfashioned"
+ required_reagents = list("whiskey" = 3, "bitters" = 1, "sugar" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/whiskeysour
+ name = "Whiskey Sour"
+ id = "whiskeysour"
+ result = "whiskeysour"
+ required_reagents = list("whiskey" = 2, "lemonjuice" = 1, "sugar" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/daiquiri
+ name = "Daiquiri"
+ id = "daiquiri"
+ result = "daiquiri"
+ required_reagents = list("rum" = 3, "limejuice" = 2, "sugar" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/mintjulep
+ name = "Mint Julep"
+ id = "mintjulep"
+ result = "mintjulep"
+ required_reagents = list("whiskey" = 2, "water" = 1, "mint" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/drinks/paloma
+ name = "Paloma"
+ id = "paloma"
+ result = "paloma"
+ required_reagents = list("orangejuice" = 1, "sodawater" = 1, "tequilla" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/mojito
+ name = "Mojito"
+ id = "mojito"
+ result = "mojito"
+ required_reagents = list("rum" = 3, "limejuice" = 1, "mint" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/virginmojito
+ name = "Mojito"
+ id = "virginmojito"
+ result = "virginmojito"
+ required_reagents = list("sodawater" = 3, "limejuice" = 1, "mint" = 1, "sugar" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/piscosour
+ name = "Pisco Sour"
+ id = "piscosour"
+ result = "piscosour"
+ required_reagents = list("winebrandy" = 1, "lemonjuice" = 1, "sugar" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/coldfront
+ name = "Cold Front"
+ id = "coldfront"
+ result = "coldfront"
+ required_reagents = list("icecoffee" = 1, "whiskey" = 1, "mint" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/godsake
+ name = "Gods Sake"
+ id = "godsake"
+ result = "godsake"
+ required_reagents = list("sake" = 2, "holywater" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/godka //Why you would put this in your body, I don't know.
+ name = "Godka"
+ id = "godka"
+ result = "godka"
+ required_reagents = list("vodka" = 1, "holywater" = 1, "ethanol" = 1, "carthatoline" = 1)
+ catalysts = list("enzyme" = 5, "holywater" = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/drinks/holywine
+ name = "Angel Ichor"
+ id = "holywine"
+ result = "holywine"
+ required_reagents = list("grapejuice" = 5, "gold" = 5)
+ catalysts = list("holywater" = 5)
+ result_amount = 10
+
+/decl/chemical_reaction/instant/drinks/holy_mary
+ name = "Holy Mary"
+ id = "holymary"
+ result = "holymary"
+ required_reagents = list("vodka" = 2, "holywine" = 3, "limejuice" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/angelskiss
+ name = "Angels Kiss"
+ id = "angelskiss"
+ result = "angelskiss"
+ required_reagents = list("holywine" = 1, "kahlua" = 1, "rum" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/angelswrath
+ name = "Angels Wrath"
+ id = "angelswrath"
+ result = "angelswrath"
+ required_reagents = list("rum" = 3, "spacemountainwind" = 1, "holywine" = 1, "dr_gibb" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/ichor_mead
+ name = "Ichor Mead"
+ id = "ichor_mead"
+ result = "ichor_mead"
+ required_reagents = list("holywine" = 1, "mead" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/oilslick
+ name = "Oil Slick"
+ id = "oilslick"
+ result = "oilslick"
+ required_reagents = list("cornoil" = 2, "honey" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/slimeslam
+ name = "Slick Slime Slammer"
+ id = "slimeslammer"
+ result = "slimeslammer"
+ required_reagents = list("cornoil" = 2, "peanutbutter" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/virginsexonthebeach
+ name = "Virgin Sex On The Beach"
+ id = "virginsexonthebeach"
+ result = "virginsexonthebeach"
+ required_reagents = list("orangejuice" = 3, "grenadine" = 2)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/drinks/sexonthebeach
+ name = "Sex On The Beach"
+ id = "sexonthebeach"
+ result = "sexonthebeach"
+ required_reagents = list("virginsexonthebeach" = 5, "vodka" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/eggnog
+ name = "Eggnog"
+ id = "eggnog"
+ result = "eggnog"
+ required_reagents = list("milk" = 5, "cream" = 5, "sugar" = 5, "egg" = 3)
+ result_amount = 15
+
+/decl/chemical_reaction/instant/drinks/nuclearwaste_radium
+ name = "Nuclear Waste"
+ id = "nuclearwasterad"
+ result = "nuclearwaste"
+ required_reagents = list("oilslick" = 1, "radium" = 1, "limejuice" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/drinks/nuclearwaste_uranium
+ name = "Nuclear Waste"
+ id = "nuclearwasteuran"
+ result = "nuclearwaste"
+ required_reagents = list("oilslick" = 2, "uranium" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/drinks/sodaoil
+ name = "Soda Oil"
+ id = "sodaoil"
+ result = "sodaoil"
+ required_reagents = list("cornoil" = 4, "sodawater" = 1, "carbon" = 1, "tricordrazine" = 1)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/drinks/fusionnaire
+ name = "Fusionnaire"
+ id = "fusionnaire"
+ result = "fusionnaire"
+ required_reagents = list("lemonjuice" = 3, "vodka" = 2, "schnapps_pep" = 1, "schnapps_lem" = 1, "rum" = 1, "ice" = 1)
+ result_amount = 9
diff --git a/code/modules/reagents/reactions/instant/food.dm b/code/modules/reagents/reactions/instant/food.dm
new file mode 100644
index 0000000000..952af8014b
--- /dev/null
+++ b/code/modules/reagents/reactions/instant/food.dm
@@ -0,0 +1,183 @@
+/decl/chemical_reaction/instant/food/hot_ramen
+ name = "Hot Ramen"
+ id = "hot_ramen"
+ result = "hot_ramen"
+ required_reagents = list("water" = 1, "dry_ramen" = 3)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/food/hell_ramen
+ name = "Hell Ramen"
+ id = "hell_ramen"
+ result = "hell_ramen"
+ required_reagents = list("capsaicin" = 1, "hot_ramen" = 6)
+ result_amount = 6
+
+/decl/chemical_reaction/instant/food/tofu
+ name = "Tofu"
+ id = "tofu"
+ result = null
+ required_reagents = list("soymilk" = 10)
+ catalysts = list("enzyme" = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/tofu/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/tofu(location)
+ return
+
+/decl/chemical_reaction/instant/food/chocolate_bar
+ name = "Chocolate Bar"
+ id = "chocolate_bar"
+ result = null
+ required_reagents = list("soymilk" = 2, "coco" = 2, "sugar" = 2)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/chocolate_bar/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/chocolatebar(location)
+ return
+
+/decl/chemical_reaction/instant/food/chocolate_bar2
+ name = "Chocolate Bar"
+ id = "chocolate_bar"
+ result = null
+ required_reagents = list("milk" = 2, "coco" = 2, "sugar" = 2)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/chocolate_bar2/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/chocolatebar(location)
+ return
+
+/decl/chemical_reaction/instant/food/soysauce
+ name = "Soy Sauce"
+ id = "soysauce"
+ result = "soysauce"
+ required_reagents = list("soymilk" = 4, "sacid" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/food/ketchup
+ name = "Ketchup"
+ id = "ketchup"
+ result = "ketchup"
+ required_reagents = list("tomatojuice" = 2, "water" = 1, "sugar" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/food/barbecue
+ name = "Barbeque Sauce"
+ id = "barbecue"
+ result = "barbecue"
+ required_reagents = list("tomatojuice" = 2, "applejuice" = 1, "sugar" = 1, "spacespice" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/food/peanutbutter
+ name = "Peanut Butter"
+ id = "peanutbutter"
+ result = "peanutbutter"
+ required_reagents = list("peanutoil" = 2, "sugar" = 1, "sodiumchloride" = 1)
+ catalysts = list("enzyme" = 5)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/food/mayonnaise
+ name = "mayonnaise"
+ id = "mayo"
+ result = "mayo"
+ required_reagents = list("egg" = 9, "cornoil" = 5, "lemonjuice" = 5, "sodiumchloride" = 1)
+ result_amount = 15
+
+/decl/chemical_reaction/instant/food/cheesewheel
+ name = "Cheesewheel"
+ id = "cheesewheel"
+ result = null
+ required_reagents = list("milk" = 40)
+ catalysts = list("enzyme" = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/cheesewheel/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel(location)
+ return
+
+/decl/chemical_reaction/instant/food/meatball
+ name = "Meatball"
+ id = "meatball"
+ result = null
+ required_reagents = list("protein" = 3, "flour" = 5)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/food/meatball/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/meatball(location)
+ return
+
+/decl/chemical_reaction/instant/food/dough
+ name = "Dough"
+ id = "dough"
+ result = null
+ required_reagents = list("egg" = 3, "flour" = 10)
+ inhibitors = list("water" = 1, "beer" = 1) //To prevent it messing with batter recipes
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/dough/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/dough(location)
+ return
+
+/decl/chemical_reaction/instant/food/syntiflesh
+ name = "Syntiflesh"
+ id = "syntiflesh"
+ result = null
+ required_reagents = list("blood" = 5, "clonexadone" = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/syntiflesh/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh(location)
+ return
+
+/*
+====================
+ Aurora Food
+====================
+*/
+
+/decl/chemical_reaction/instant/food/coating/batter
+ name = "Batter"
+ id = "batter"
+ result = "batter"
+ required_reagents = list("egg" = 3, "flour" = 10, "water" = 5, "sodiumchloride" = 2)
+ result_amount = 20
+
+/decl/chemical_reaction/instant/food/coating/beerbatter
+ name = "Beer Batter"
+ id = "beerbatter"
+ result = "beerbatter"
+ required_reagents = list("egg" = 3, "flour" = 10, "beer" = 5, "sodiumchloride" = 2)
+ result_amount = 20
+
+/decl/chemical_reaction/instant/food/browniemix
+ name = "Brownie Mix"
+ id = "browniemix"
+ result = "browniemix"
+ required_reagents = list("flour" = 5, "coco" = 5, "sugar" = 5)
+ result_amount = 15
+
+/decl/chemical_reaction/instant/food/butter
+ name = "Butter"
+ id = "butter"
+ result = null
+ required_reagents = list("cream" = 20, "sodiumchloride" = 1)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/food/butter/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/weapon/reagent_containers/food/snacks/spreads/butter(location)
+ return
\ No newline at end of file
diff --git a/code/modules/reagents/reactions/instant/instant.dm b/code/modules/reagents/reactions/instant/instant.dm
new file mode 100644
index 0000000000..4a6c25898d
--- /dev/null
+++ b/code/modules/reagents/reactions/instant/instant.dm
@@ -0,0 +1,1118 @@
+// These reactions happen instantaneously, when added to a container that has all other necessary reagents
+// They are a subtype of chemical_reaction so that such containers can iterate over only these reactions, and not have to skip other reaction types
+
+/* Common reactions */
+
+/decl/chemical_reaction/instant/inaprovaline
+ name = "Inaprovaline"
+ id = "inaprovaline"
+ result = "inaprovaline"
+ required_reagents = list("oxygen" = 1, "carbon" = 1, "sugar" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/dylovene
+ name = "Dylovene"
+ id = "anti_toxin"
+ result = "anti_toxin"
+ required_reagents = list("silicon" = 1, "potassium" = 1, "nitrogen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/carthatoline
+ name = "Carthatoline"
+ id = "carthatoline"
+ result = "carthatoline"
+ required_reagents = list("anti_toxin" = 1, "carbon" = 2, "phoron" = 0.1)
+ catalysts = list("phoron" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/paracetamol
+ name = "Paracetamol"
+ id = "paracetamol"
+ result = "paracetamol"
+ required_reagents = list("inaprovaline" = 1, "nitrogen" = 1, "water" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/tramadol
+ name = "Tramadol"
+ id = "tramadol"
+ result = "tramadol"
+ required_reagents = list("paracetamol" = 1, "ethanol" = 1, "oxygen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/oxycodone
+ name = "Oxycodone"
+ id = "oxycodone"
+ result = "oxycodone"
+ required_reagents = list("ethanol" = 1, "tramadol" = 1)
+ catalysts = list("phoron" = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/sterilizine
+ name = "Sterilizine"
+ id = "sterilizine"
+ result = "sterilizine"
+ required_reagents = list("ethanol" = 1, "anti_toxin" = 1, "chlorine" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/silicate
+ name = "Silicate"
+ id = "silicate"
+ result = "silicate"
+ required_reagents = list("aluminum" = 1, "silicon" = 1, "oxygen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/mutagen
+ name = "Unstable mutagen"
+ id = "mutagen"
+ result = "mutagen"
+ required_reagents = list("radium" = 1, "phosphorus" = 1, "chlorine" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/water
+ name = "Water"
+ id = "water"
+ result = "water"
+ required_reagents = list("oxygen" = 1, "hydrogen" = 2)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/thermite
+ name = "Thermite"
+ id = "thermite"
+ result = "thermite"
+ required_reagents = list("aluminum" = 1, "iron" = 1, "oxygen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/space_drugs
+ name = "Space Drugs"
+ id = "space_drugs"
+ result = "space_drugs"
+ required_reagents = list("mercury" = 1, "sugar" = 1, "lithium" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/lube
+ name = "Space Lube"
+ id = "lube"
+ result = "lube"
+ required_reagents = list("water" = 1, "silicon" = 1, "oxygen" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/pacid
+ name = "Polytrinic acid"
+ id = "pacid"
+ result = "pacid"
+ required_reagents = list("sacid" = 1, "chlorine" = 1, "potassium" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/synaptizine
+ name = "Synaptizine"
+ id = "synaptizine"
+ result = "synaptizine"
+ required_reagents = list("sugar" = 1, "lithium" = 1, "water" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/hyronalin
+ name = "Hyronalin"
+ id = "hyronalin"
+ result = "hyronalin"
+ required_reagents = list("radium" = 1, "anti_toxin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/arithrazine
+ name = "Arithrazine"
+ id = "arithrazine"
+ result = "arithrazine"
+ required_reagents = list("hyronalin" = 1, "hydrogen" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/impedrezene
+ name = "Impedrezene"
+ id = "impedrezene"
+ result = "impedrezene"
+ required_reagents = list("mercury" = 1, "oxygen" = 1, "sugar" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/kelotane
+ name = "Kelotane"
+ id = "kelotane"
+ result = "kelotane"
+ required_reagents = list("silicon" = 1, "carbon" = 1)
+ result_amount = 2
+ log_is_important = 1
+
+/decl/chemical_reaction/instant/peridaxon
+ name = "Peridaxon"
+ id = "peridaxon"
+ result = "peridaxon"
+ required_reagents = list("bicaridine" = 2, "clonexadone" = 2)
+ catalysts = list("phoron" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/osteodaxon
+ name = "Osteodaxon"
+ id = "osteodaxon"
+ result = "osteodaxon"
+ required_reagents = list("bicaridine" = 2, "phoron" = 0.1, "carpotoxin" = 1)
+ catalysts = list("phoron" = 5)
+ inhibitors = list("clonexadone" = 1) // Messes with cryox
+ result_amount = 2
+
+/decl/chemical_reaction/instant/respirodaxon
+ name = "Respirodaxon"
+ id = "respirodaxon"
+ result = "respirodaxon"
+ required_reagents = list("dexalinp" = 2, "biomass" = 2, "phoron" = 1)
+ catalysts = list("phoron" = 5)
+ inhibitors = list("dexalin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/gastirodaxon
+ name = "Gastirodaxon"
+ id = "gastirodaxon"
+ result = "gastirodaxon"
+ required_reagents = list("carthatoline" = 1, "biomass" = 2, "tungsten" = 2)
+ catalysts = list("phoron" = 5)
+ inhibitors = list("lithium" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/hepanephrodaxon
+ name = "Hepanephrodaxon"
+ id = "hepanephrodaxon"
+ result = "hepanephrodaxon"
+ required_reagents = list("carthatoline" = 2, "biomass" = 2, "lithium" = 1)
+ catalysts = list("phoron" = 5)
+ inhibitors = list("tungsten" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/cordradaxon
+ name = "Cordradaxon"
+ id = "cordradaxon"
+ result = "cordradaxon"
+ required_reagents = list("potassium_chlorophoride" = 1, "biomass" = 2, "bicaridine" = 2)
+ catalysts = list("phoron" = 5)
+ inhibitors = list("clonexadone" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/virus_food
+ name = "Virus Food"
+ id = "virusfood"
+ result = "virusfood"
+ required_reagents = list("water" = 1, "milk" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/leporazine
+ name = "Leporazine"
+ id = "leporazine"
+ result = "leporazine"
+ required_reagents = list("silicon" = 1, "copper" = 1)
+ catalysts = list("phoron" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/cryptobiolin
+ name = "Cryptobiolin"
+ id = "cryptobiolin"
+ result = "cryptobiolin"
+ required_reagents = list("potassium" = 1, "oxygen" = 1, "sugar" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/tricordrazine
+ name = "Tricordrazine"
+ id = "tricordrazine"
+ result = "tricordrazine"
+ required_reagents = list("inaprovaline" = 1, "anti_toxin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/alkysine
+ name = "Alkysine"
+ id = "alkysine"
+ result = "alkysine"
+ required_reagents = list("chlorine" = 1, "nitrogen" = 1, "anti_toxin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/dexalin
+ name = "Dexalin"
+ id = "dexalin"
+ result = "dexalin"
+ required_reagents = list("oxygen" = 2, "phoron" = 0.1)
+ catalysts = list("phoron" = 1)
+ inhibitors = list("water" = 1) // Messes with cryox
+ result_amount = 1
+
+/decl/chemical_reaction/instant/dermaline
+ name = "Dermaline"
+ id = "dermaline"
+ result = "dermaline"
+ required_reagents = list("oxygen" = 1, "phosphorus" = 1, "kelotane" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/dexalinp
+ name = "Dexalin Plus"
+ id = "dexalinp"
+ result = "dexalinp"
+ required_reagents = list("dexalin" = 1, "carbon" = 1, "iron" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/bicaridine
+ name = "Bicaridine"
+ id = "bicaridine"
+ result = "bicaridine"
+ required_reagents = list("inaprovaline" = 1, "carbon" = 1)
+ inhibitors = list("sugar" = 1) // Messes up with inaprovaline
+ result_amount = 2
+
+/decl/chemical_reaction/instant/myelamine
+ name = "Myelamine"
+ id = "myelamine"
+ result = "myelamine"
+ required_reagents = list("bicaridine" = 1, "iron" = 2, "spidertoxin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/hyperzine
+ name = "Hyperzine"
+ id = "hyperzine"
+ result = "hyperzine"
+ required_reagents = list("sugar" = 1, "phosphorus" = 1, "sulfur" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/stimm
+ name = "Stimm"
+ id = "stimm"
+ result = "stimm"
+ required_reagents = list("left4zed" = 1, "fuel" = 1)
+ catalysts = list("fuel" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/ryetalyn
+ name = "Ryetalyn"
+ id = "ryetalyn"
+ result = "ryetalyn"
+ required_reagents = list("arithrazine" = 1, "carbon" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/cryoxadone
+ name = "Cryoxadone"
+ id = "cryoxadone"
+ result = "cryoxadone"
+ required_reagents = list("dexalin" = 1, "water" = 1, "oxygen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/clonexadone
+ name = "Clonexadone"
+ id = "clonexadone"
+ result = "clonexadone"
+ required_reagents = list("cryoxadone" = 1, "sodium" = 1, "phoron" = 0.1)
+ catalysts = list("phoron" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/mortiferin
+ name = "Mortiferin"
+ id = "mortiferin"
+ result = "mortiferin"
+ required_reagents = list("cryptobiolin" = 1, "clonexadone" = 1, "corophizine" = 1)
+ result_amount = 2
+ catalysts = list("phoron" = 5)
+
+/decl/chemical_reaction/instant/spaceacillin
+ name = "Spaceacillin"
+ id = "spaceacillin"
+ result = "spaceacillin"
+ required_reagents = list("cryptobiolin" = 1, "inaprovaline" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/corophizine
+ name = "Corophizine"
+ id = "corophizine"
+ result = "corophizine"
+ required_reagents = list("spaceacillin" = 1, "carbon" = 1, "phoron" = 0.1)
+ catalysts = list("phoron" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/immunosuprizine
+ name = "Immunosuprizine"
+ id = "immunosuprizine"
+ result = "immunosuprizine"
+ required_reagents = list("corophizine" = 1, "tungsten" = 1, "sacid" = 1)
+ catalysts = list("phoron" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/imidazoline
+ name = "imidazoline"
+ id = "imidazoline"
+ result = "imidazoline"
+ required_reagents = list("carbon" = 1, "hydrogen" = 1, "anti_toxin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/ethylredoxrazine
+ name = "Ethylredoxrazine"
+ id = "ethylredoxrazine"
+ result = "ethylredoxrazine"
+ required_reagents = list("oxygen" = 1, "anti_toxin" = 1, "carbon" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/calciumcarbonate
+ name = "Calcium Carbonate"
+ id = "calciumcarbonate"
+ result = "calciumcarbonate"
+ required_reagents = list("oxygen" = 3, "calcium" = 1, "carbon" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/soporific
+ name = "Soporific"
+ id = "stoxin"
+ result = "stoxin"
+ required_reagents = list("chloralhydrate" = 1, "sugar" = 4)
+ inhibitors = list("phosphorus") // Messes with the smoke
+ result_amount = 5
+
+/decl/chemical_reaction/instant/chloralhydrate
+ name = "Chloral Hydrate"
+ id = "chloralhydrate"
+ result = "chloralhydrate"
+ required_reagents = list("ethanol" = 1, "chlorine" = 3, "water" = 1)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/potassium_chloride
+ name = "Potassium Chloride"
+ id = "potassium_chloride"
+ result = "potassium_chloride"
+ required_reagents = list("sodiumchloride" = 1, "potassium" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/potassium_chlorophoride
+ name = "Potassium Chlorophoride"
+ id = "potassium_chlorophoride"
+ result = "potassium_chlorophoride"
+ required_reagents = list("potassium_chloride" = 1, "phoron" = 1, "chloralhydrate" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/zombiepowder
+ name = "Zombie Powder"
+ id = "zombiepowder"
+ result = "zombiepowder"
+ required_reagents = list("carpotoxin" = 5, "stoxin" = 5, "copper" = 5)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/carpotoxin
+ name = "Carpotoxin"
+ id = "carpotoxin"
+ result = "carpotoxin"
+ required_reagents = list("spidertoxin" = 2, "biomass" = 1, "sifsap" = 2)
+ catalysts = list("sifsap" = 10)
+ inhibitors = list("radium" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/mindbreaker
+ name = "Mindbreaker Toxin"
+ id = "mindbreaker"
+ result = "mindbreaker"
+ required_reagents = list("silicon" = 1, "hydrogen" = 1, "anti_toxin" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/lipozine
+ name = "Lipozine"
+ id = "Lipozine"
+ result = "lipozine"
+ required_reagents = list("sodiumchloride" = 1, "ethanol" = 1, "radium" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/surfactant
+ name = "Foam surfactant"
+ id = "foam surfactant"
+ result = "fluorosurfactant"
+ required_reagents = list("fluorine" = 2, "carbon" = 2, "sacid" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/ammonia
+ name = "Ammonia"
+ id = "ammonia"
+ result = "ammonia"
+ required_reagents = list("hydrogen" = 3, "nitrogen" = 1)
+ inhibitors = list("phoron" = 1) // Messes with lexorin
+ result_amount = 3
+
+/decl/chemical_reaction/instant/diethylamine
+ name = "Diethylamine"
+ id = "diethylamine"
+ result = "diethylamine"
+ required_reagents = list ("ammonia" = 1, "ethanol" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/left4zed
+ name = "Left4Zed"
+ id = "left4zed"
+ result = "left4zed"
+ required_reagents = list ("diethylamine" = 2, "mutagen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/robustharvest
+ name = "RobustHarvest"
+ id = "robustharvest"
+ result = "robustharvest"
+ required_reagents = list ("ammonia" = 1, "calcium" = 1, "neurotoxic_protein" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/space_cleaner
+ name = "Space cleaner"
+ id = "cleaner"
+ result = "cleaner"
+ required_reagents = list("ammonia" = 1, "water" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/plantbgone
+ name = "Plant-B-Gone"
+ id = "plantbgone"
+ result = "plantbgone"
+ required_reagents = list("toxin" = 1, "water" = 4)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/foaming_agent
+ name = "Foaming Agent"
+ id = "foaming_agent"
+ result = "foaming_agent"
+ required_reagents = list("lithium" = 1, "hydrogen" = 1)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/glycerol
+ name = "Glycerol"
+ id = "glycerol"
+ result = "glycerol"
+ required_reagents = list("cornoil" = 3, "sacid" = 1)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/sodiumchloride
+ name = "Sodium Chloride"
+ id = "sodiumchloride"
+ result = "sodiumchloride"
+ required_reagents = list("sodium" = 1, "chlorine" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/condensedcapsaicin
+ name = "Condensed Capsaicin"
+ id = "condensedcapsaicin"
+ result = "condensedcapsaicin"
+ required_reagents = list("capsaicin" = 2)
+ catalysts = list("phoron" = 5)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/coolant
+ name = "Coolant"
+ id = "coolant"
+ result = "coolant"
+ required_reagents = list("tungsten" = 1, "oxygen" = 1, "water" = 1)
+ result_amount = 3
+ log_is_important = 1
+
+/decl/chemical_reaction/instant/rezadone
+ name = "Rezadone"
+ id = "rezadone"
+ result = "rezadone"
+ required_reagents = list("carpotoxin" = 1, "cryptobiolin" = 1, "copper" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/lexorin
+ name = "Lexorin"
+ id = "lexorin"
+ result = "lexorin"
+ required_reagents = list("phoron" = 1, "hydrogen" = 1, "nitrogen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/methylphenidate
+ name = "Methylphenidate"
+ id = "methylphenidate"
+ result = "methylphenidate"
+ required_reagents = list("mindbreaker" = 1, "hydrogen" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/citalopram
+ name = "Citalopram"
+ id = "citalopram"
+ result = "citalopram"
+ required_reagents = list("mindbreaker" = 1, "carbon" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/paroxetine
+ name = "Paroxetine"
+ id = "paroxetine"
+ result = "paroxetine"
+ required_reagents = list("mindbreaker" = 1, "oxygen" = 1, "inaprovaline" = 1)
+ result_amount = 3
+
+/decl/chemical_reaction/instant/neurotoxin
+ name = "Neurotoxin"
+ id = "neurotoxin"
+ result = "neurotoxin"
+ required_reagents = list("gargleblaster" = 1, "stoxin" = 1)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/luminol
+ name = "Luminol"
+ id = "luminol"
+ result = "luminol"
+ required_reagents = list("hydrogen" = 2, "carbon" = 2, "ammonia" = 2)
+ result_amount = 6
+
+/* Solidification */
+
+/decl/chemical_reaction/instant/solidification
+ name = "Solid Iron"
+ id = "solidiron"
+ result = null
+ required_reagents = list("frostoil" = 5, "iron" = REAGENTS_PER_SHEET)
+ result_amount = 1
+ var/sheet_to_give = /obj/item/stack/material/iron
+
+/decl/chemical_reaction/instant/solidification/on_reaction(var/datum/reagents/holder, var/created_volume)
+ new sheet_to_give(get_turf(holder.my_atom), created_volume)
+ return
+
+
+/decl/chemical_reaction/instant/solidification/phoron
+ name = "Solid Phoron"
+ id = "solidphoron"
+ required_reagents = list("frostoil" = 5, "phoron" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/phoron
+
+
+/decl/chemical_reaction/instant/solidification/silver
+ name = "Solid Silver"
+ id = "solidsilver"
+ required_reagents = list("frostoil" = 5, "silver" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/silver
+
+
+/decl/chemical_reaction/instant/solidification/gold
+ name = "Solid Gold"
+ id = "solidgold"
+ required_reagents = list("frostoil" = 5, "gold" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/gold
+
+
+/decl/chemical_reaction/instant/solidification/platinum
+ name = "Solid Platinum"
+ id = "solidplatinum"
+ required_reagents = list("frostoil" = 5, "platinum" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/platinum
+
+
+/decl/chemical_reaction/instant/solidification/uranium
+ name = "Solid Uranium"
+ id = "soliduranium"
+ required_reagents = list("frostoil" = 5, "uranium" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/uranium
+
+
+/decl/chemical_reaction/instant/solidification/hydrogen
+ name = "Solid Hydrogen"
+ id = "solidhydrogen"
+ required_reagents = list("frostoil" = 100, "hydrogen" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/mhydrogen
+
+
+// These are from Xenobio.
+/decl/chemical_reaction/instant/solidification/steel
+ name = "Solid Steel"
+ id = "solidsteel"
+ required_reagents = list("frostoil" = 5, "steel" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/steel
+
+
+/decl/chemical_reaction/instant/solidification/plasteel
+ name = "Solid Plasteel"
+ id = "solidplasteel"
+ required_reagents = list("frostoil" = 10, "plasteel" = REAGENTS_PER_SHEET)
+ sheet_to_give = /obj/item/stack/material/plasteel
+
+
+/decl/chemical_reaction/instant/plastication
+ name = "Plastic"
+ id = "solidplastic"
+ result = null
+ required_reagents = list("pacid" = 1, "plasticide" = 2)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/plastication/on_reaction(var/datum/reagents/holder, var/created_volume)
+ new /obj/item/stack/material/plastic(get_turf(holder.my_atom), created_volume)
+ return
+
+/* Grenade reactions */
+
+/decl/chemical_reaction/instant/explosion_potassium
+ name = "Explosion"
+ id = "explosion_potassium"
+ result = null
+ required_reagents = list("water" = 1, "potassium" = 1)
+ result_amount = 2
+ mix_message = null
+
+/decl/chemical_reaction/instant/explosion_potassium/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/datum/effect/effect/system/reagents_explosion/e = new()
+ e.set_up(round (created_volume/10, 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
+
+/decl/chemical_reaction/instant/flash_powder
+ name = "Flash powder"
+ id = "flash_powder"
+ result = null
+ required_reagents = list("aluminum" = 1, "potassium" = 1, "sulfur" = 1 )
+ result_amount = null
+
+/decl/chemical_reaction/instant/flash_powder/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(2, 1, location)
+ s.start()
+ for(var/mob/living/carbon/M in viewers(world.view, location))
+ switch(get_dist(M, location))
+ if(0 to 3)
+ if(hasvar(M, "glasses"))
+ if(istype(M:glasses, /obj/item/clothing/glasses/sunglasses))
+ continue
+
+ M.flash_eyes()
+ M.Weaken(15)
+
+ if(4 to 5)
+ if(hasvar(M, "glasses"))
+ if(istype(M:glasses, /obj/item/clothing/glasses/sunglasses))
+ continue
+
+ M.flash_eyes()
+ M.Stun(5)
+
+/decl/chemical_reaction/instant/emp_pulse
+ name = "EMP Pulse"
+ id = "emp_pulse"
+ result = null
+ required_reagents = list("uranium" = 1, "iron" = 1) // Yes, laugh, it's the best recipe I could think of that makes a little bit of sense
+ result_amount = 2
+
+/decl/chemical_reaction/instant/emp_pulse/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ // 100 created volume = 4 heavy range & 7 light range. A few tiles smaller than traitor EMP grandes.
+ // 200 created volume = 8 heavy range & 14 light range. 4 tiles larger than traitor EMP grenades.
+ empulse(location, round(created_volume / 24), round(created_volume / 20), round(created_volume / 18), round(created_volume / 14), 1)
+ holder.clear_reagents()
+ return
+
+/decl/chemical_reaction/instant/nitroglycerin
+ name = "Nitroglycerin"
+ id = "nitroglycerin"
+ result = "nitroglycerin"
+ required_reagents = list("glycerol" = 1, "pacid" = 1, "sacid" = 1)
+ result_amount = 2
+ log_is_important = 1
+
+/decl/chemical_reaction/instant/nitroglycerin/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/datum/effect/effect/system/reagents_explosion/e = new()
+ e.set_up(round (created_volume/2, 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
+
+/decl/chemical_reaction/instant/napalm
+ name = "Napalm"
+ id = "napalm"
+ result = null
+ required_reagents = list("aluminum" = 1, "phoron" = 1, "sacid" = 1 )
+ result_amount = 1
+
+/decl/chemical_reaction/instant/napalm/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/turf/location = get_turf(holder.my_atom.loc)
+ for(var/turf/simulated/floor/target_tile in range(0,location))
+ target_tile.assume_gas("volatile_fuel", created_volume, 400+T0C)
+ spawn (0) target_tile.hotspot_expose(700, 400)
+ holder.del_reagent("napalm")
+ return
+
+/decl/chemical_reaction/instant/chemsmoke
+ name = "Chemsmoke"
+ id = "chemsmoke"
+ result = null
+ required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1)
+ result_amount = 0.4
+
+/decl/chemical_reaction/instant/chemsmoke/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+ var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem
+ S.attach(location)
+ S.set_up(holder, created_volume, 0, location)
+ playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
+ spawn(0)
+ S.start()
+ holder.clear_reagents()
+ return
+
+/decl/chemical_reaction/instant/foam
+ name = "Foam"
+ id = "foam"
+ result = null
+ required_reagents = list("fluorosurfactant" = 1, "water" = 1)
+ result_amount = 2
+ mix_message = "The solution violently bubbles!"
+
+/decl/chemical_reaction/instant/foam/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+
+ for(var/mob/M in viewers(5, location))
+ to_chat(M, "The solution spews out foam!")
+
+ var/datum/effect/effect/system/foam_spread/s = new()
+ s.set_up(created_volume, location, holder, 0)
+ s.start()
+ holder.clear_reagents()
+ return
+
+/decl/chemical_reaction/instant/metalfoam
+ name = "Metal Foam"
+ id = "metalfoam"
+ result = null
+ required_reagents = list("aluminum" = 3, "foaming_agent" = 1, "pacid" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/metalfoam/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+
+ for(var/mob/M in viewers(5, location))
+ to_chat(M, "The solution spews out a metalic foam!")
+
+ var/datum/effect/effect/system/foam_spread/s = new()
+ s.set_up(created_volume, location, holder, 1)
+ s.start()
+ return
+
+/decl/chemical_reaction/instant/ironfoam
+ name = "Iron Foam"
+ id = "ironlfoam"
+ result = null
+ required_reagents = list("iron" = 3, "foaming_agent" = 1, "pacid" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/ironfoam/on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/location = get_turf(holder.my_atom)
+
+ for(var/mob/M in viewers(5, location))
+ to_chat(M, "The solution spews out a metalic foam!")
+
+ var/datum/effect/effect/system/foam_spread/s = new()
+ s.set_up(created_volume, location, holder, 2)
+ s.start()
+ return
+
+/* Paint */
+
+/decl/chemical_reaction/instant/red_paint
+ name = "Red paint"
+ id = "red_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_red" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/red_paint/send_data()
+ return "#FE191A"
+
+/decl/chemical_reaction/instant/orange_paint
+ name = "Orange paint"
+ id = "orange_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_orange" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/orange_paint/send_data()
+ return "#FFBE4F"
+
+/decl/chemical_reaction/instant/yellow_paint
+ name = "Yellow paint"
+ id = "yellow_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_yellow" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/yellow_paint/send_data()
+ return "#FDFE7D"
+
+/decl/chemical_reaction/instant/green_paint
+ name = "Green paint"
+ id = "green_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_green" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/green_paint/send_data()
+ return "#18A31A"
+
+/decl/chemical_reaction/instant/blue_paint
+ name = "Blue paint"
+ id = "blue_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_blue" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/blue_paint/send_data()
+ return "#247CFF"
+
+/decl/chemical_reaction/instant/purple_paint
+ name = "Purple paint"
+ id = "purple_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_purple" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/purple_paint/send_data()
+ return "#CC0099"
+
+/decl/chemical_reaction/instant/grey_paint //mime
+ name = "Grey paint"
+ id = "grey_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_grey" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/grey_paint/send_data()
+ return "#808080"
+
+/decl/chemical_reaction/instant/brown_paint
+ name = "Brown paint"
+ id = "brown_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "marker_ink_brown" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/brown_paint/send_data()
+ return "#846F35"
+
+/decl/chemical_reaction/instant/blood_paint
+ name = "Blood paint"
+ id = "blood_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "blood" = 2)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/blood_paint/send_data(var/datum/reagents/T)
+ var/t = T.get_data("blood")
+ if(t && t["blood_colour"])
+ return t["blood_colour"]
+ return "#FE191A" // Probably red
+
+/decl/chemical_reaction/instant/milk_paint
+ name = "Milk paint"
+ id = "milk_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "milk" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/milk_paint/send_data()
+ return "#F0F8FF"
+
+/decl/chemical_reaction/instant/orange_juice_paint
+ name = "Orange juice paint"
+ id = "orange_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "orangejuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/orange_juice_paint/send_data()
+ return "#E78108"
+
+/decl/chemical_reaction/instant/tomato_juice_paint
+ name = "Tomato juice paint"
+ id = "tomato_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "tomatojuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/tomato_juice_paint/send_data()
+ return "#731008"
+
+/decl/chemical_reaction/instant/lime_juice_paint
+ name = "Lime juice paint"
+ id = "lime_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "limejuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/lime_juice_paint/send_data()
+ return "#365E30"
+
+/decl/chemical_reaction/instant/carrot_juice_paint
+ name = "Carrot juice paint"
+ id = "carrot_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "carrotjuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/carrot_juice_paint/send_data()
+ return "#973800"
+
+/decl/chemical_reaction/instant/berry_juice_paint
+ name = "Berry juice paint"
+ id = "berry_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "berryjuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/berry_juice_paint/send_data()
+ return "#990066"
+
+/decl/chemical_reaction/instant/grape_juice_paint
+ name = "Grape juice paint"
+ id = "grape_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "grapejuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/grape_juice_paint/send_data()
+ return "#863333"
+
+/decl/chemical_reaction/instant/poisonberry_juice_paint
+ name = "Poison berry juice paint"
+ id = "poisonberry_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "poisonberryjuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/poisonberry_juice_paint/send_data()
+ return "#863353"
+
+/decl/chemical_reaction/instant/watermelon_juice_paint
+ name = "Watermelon juice paint"
+ id = "watermelon_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "watermelonjuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/watermelon_juice_paint/send_data()
+ return "#B83333"
+
+/decl/chemical_reaction/instant/lemon_juice_paint
+ name = "Lemon juice paint"
+ id = "lemon_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "lemonjuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/lemon_juice_paint/send_data()
+ return "#AFAF00"
+
+/decl/chemical_reaction/instant/banana_juice_paint
+ name = "Banana juice paint"
+ id = "banana_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "banana" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/banana_juice_paint/send_data()
+ return "#C3AF00"
+
+/decl/chemical_reaction/instant/potato_juice_paint
+ name = "Potato juice paint"
+ id = "potato_juice_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "potatojuice" = 5)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/potato_juice_paint/send_data()
+ return "#302000"
+
+/decl/chemical_reaction/instant/carbon_paint
+ name = "Carbon paint"
+ id = "carbon_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "carbon" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/carbon_paint/send_data()
+ return "#333333"
+
+/decl/chemical_reaction/instant/aluminum_paint
+ name = "Aluminum paint"
+ id = "aluminum_paint"
+ result = "paint"
+ required_reagents = list("plasticide" = 1, "water" = 3, "aluminum" = 1)
+ result_amount = 5
+
+/decl/chemical_reaction/instant/aluminum_paint/send_data()
+ return "#F0F8FF"
+
+//R-UST Port
+/decl/chemical_reaction/instant/hydrophoron
+ name = "Hydrophoron"
+ id = "hydrophoron"
+ result = "hydrophoron"
+ required_reagents = list("hydrogen" = 1, "phoron" = 1)
+ inhibitors = list("nitrogen" = 1) //So it doesn't mess with lexorin
+ result_amount = 2
+
+/decl/chemical_reaction/instant/deuterium
+ name = "Deuterium"
+ id = "deuterium"
+ result = "deuterium"
+ required_reagents = list("hydrophoron" = 1, "water" = 2)
+ result_amount = 3
+
+//Skrellian crap.
+/decl/chemical_reaction/instant/talum_quem
+ name = "Talum-quem"
+ id = "talum_quem"
+ result = "talum_quem"
+ required_reagents = list("space_drugs" = 2, "sugar" = 1, "amatoxin" = 1)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/qerr_quem
+ name = "Qerr-quem"
+ id = "qerr_quem"
+ result = "qerr_quem"
+ required_reagents = list("nicotine" = 1, "carbon" = 1, "sugar" = 2)
+ result_amount = 4
+
+/decl/chemical_reaction/instant/malish_qualem
+ name = "Malish-Qualem"
+ id = "malish-qualem"
+ result = "malish-qualem"
+ required_reagents = list("immunosuprizine" = 1, "qerr_quem" = 1, "inaprovaline" = 1)
+ catalysts = list("phoron" = 5)
+ result_amount = 2
+
+// Biomass, for cloning and bioprinters
+/decl/chemical_reaction/instant/biomass
+ name = "Biomass"
+ id = "biomass"
+ result = "biomass"
+ required_reagents = list("protein" = 1, "sugar" = 1, "phoron" = 1)
+ result_amount = 1 // Roughly 20u per phoron sheet
+
+// Neutralization.
+
+/decl/chemical_reaction/instant/neutralize_neurotoxic_protein
+ name = "Neutralize Toxic Proteins"
+ id = "neurotoxic_protein_neutral"
+ result = "protein"
+ required_reagents = list("anti_toxin" = 1, "neurotoxic_protein" = 2)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/neutralize_carpotoxin
+ name = "Neutralize Carpotoxin"
+ id = "carpotoxin_neutral"
+ result = "protein"
+ required_reagents = list("radium" = 1, "carpotoxin" = 1, "sifsap" = 1)
+ catalysts = list("sifsap" = 10)
+ result_amount = 2
+
+/decl/chemical_reaction/instant/neutralize_spidertoxin
+ name = "Neutralize Spidertoxin"
+ id = "spidertoxin_neutral"
+ result = "protein"
+ required_reagents = list("radium" = 1, "spidertoxin" = 1, "sifsap" = 1)
+ catalysts = list("sifsap" = 10)
+ result_amount = 2
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Readme.dm b/code/modules/reagents/readme.md
similarity index 97%
rename from code/modules/reagents/Chemistry-Readme.dm
rename to code/modules/reagents/readme.md
index 2b7e3a832a..f9dac66b08 100644
--- a/code/modules/reagents/Chemistry-Readme.dm
+++ b/code/modules/reagents/readme.md
@@ -1,305 +1,305 @@
-/*
-NOTE: IF YOU UPDATE THE REAGENT-SYSTEM, ALSO UPDATE THIS README.
-
-Structure: /////////////////// //////////////////////////
- // Mob or object // -------> // Reagents var (datum) // Is a reference to the datum that holds the reagents.
- /////////////////// //////////////////////////
- | |
- The object that holds everything. V
- reagent_list var (list) A List of datums, each datum is a reagent.
-
- | | |
- V V V
-
- reagents (datums) Reagents. I.e. Water , antitoxins or mercury.
-
-
-Random important notes:
-
- An objects on_reagent_change will be called every time the objects reagents change.
- Useful if you want to update the objects icon etc.
-
-About the Holder:
-
- The holder (reagents datum) is the datum that holds a list of all reagents
- currently in the object.It also has all the procs needed to manipulate reagents
-
- Vars:
- list/datum/reagent/reagent_list
- List of reagent datums.
-
- total_volume
- Total volume of all reagents.
-
- maximum_volume
- Maximum volume.
-
- atom/my_atom
- Reference to the object that contains this.
-
- Procs:
-
- get_free_space()
- Returns the remaining free volume in the holder.
-
- get_master_reagent()
- Returns the reference to the reagent with the largest volume
-
- get_master_reagent_name()
- Ditto, but returns the name.
-
- get_master_reagent_id()
- Ditto, but returns ID.
-
- update_total()
- Updates total volume, called automatically.
-
- handle_reactions()
- Checks reagents and triggers any reactions that happen. Usually called automatically.
-
- add_reagent(var/id, var/amount, var/data = null, var/safety = 0)
- Adds [amount] units of [id] reagent. [data] will be passed to reagent's mix_data() or initialize_data(). If [safety] is 0, handle_reactions() will be called. Returns 1 if successful, 0 otherwise.
-
- remove_reagent(var/id, var/amount, var/safety = 0)
- Ditto, but removes reagent. Returns 1 if successful, 0 otherwise.
-
- del_reagent(var/id)
- Removes all of the reagent.
-
- has_reagent(var/id, var/amount = 0)
- Checks if holder has at least [amount] of [id] reagent. Returns 1 if the reagent is found and volume is above [amount]. Returns 0 otherwise.
-
- clear_reagents()
- Removes all reagents.
-
- get_reagent_amount(var/id)
- Returns reagent volume. Returns 0 if reagent is not found.
-
- get_data(var/id)
- Returns get_data() of the reagent.
-
- get_reagents()
- Returns a string containing all reagent ids and volumes, e.g. "carbon(4),nittrogen(5)".
-
- remove_any(var/amount = 1)
- Removes up to [amount] of reagents from [src]. Returns actual amount removed.
-
- 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]). If [copy] is 1, copies reagents instead.
-
- touch(var/atom/target)
- When applying reagents to an atom externally, touch() is called to trigger any on-touch effects of the reagent.
- This does not handle transferring reagents to things.
- For example, splashing someone with water will get them wet and extinguish them if they are on fire,
- even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
- Basically just defers to touch_mob(target), touch_turf(target), or touch_obj(target), depending on target's type.
- Not recommended to use this directly, since trans_to() calls it before attempting to transfer.
-
- touch_mob(var/mob/target)
- Calls each reagent's touch_mob(target).
-
- touch_turf(var/turf/target)
- Calls each reagent's touch_turf(target).
-
- touch_obj(var/obj/target)
- Calls each reagent's touch_obj(target).
-
- trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
- The general proc for applying reagents to things externally (as opposed to directly injected into the contents).
- It first calls touch, then the appropriate trans_to_*() or splash_mob().
- If for some reason you want touch effects to be bypassed (e.g. injecting stuff directly into a reagent container or person), call the appropriate trans_to_*() proc.
-
- Calls touch() before checking the type of [target], calling splash_mob(target, amount), trans_to_turf(target, amount, multiplier, copy), or trans_to_obj(target, amount, multiplier, copy).
-
- trans_id_to(var/atom/target, var/id, var/amount = 1)
- Transfers [amount] of [id] to [target]. Returns amount transferred.
-
- splash_mob(var/mob/target, var/amount = 1, var/clothes = 1)
- Checks mob's clothing if [clothes] is 1 and transfers [amount] reagents to mob's skin.
- Don't call this directly. Call apply_to() instead.
-
- trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0)
- Transfers [amount] reagents to the mob's appropriate holder, depending on [type]. Ignores protection.
-
- trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
- Turfs don't currently have any reagents. Puts [amount] reagents into a temporary holder, calls touch_turf(target) from it, and deletes it.
-
- trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
- If target has reagents, transfers [amount] to it. Otherwise, same as trans_to_turf().
-
- atom/proc/create_reagents(var/max_vol)
- Creates a new reagent datum.
-
-About Reagents:
-
- Reagents are all the things you can mix and fille in bottles etc. This can be anything from
- rejuvs over water to... iron.
-
- Vars:
-
- name
- Name that shows up in-game.
-
- id
- ID that is used for internal tracking. MUST BE UNIQUE.
-
- description
- Description that shows up in-game.
-
- datum/reagents/holder
- Reference to holder.
-
- reagent_state
- Could be GAS, LIQUID, or SOLID. Affects nothing. Reserved for future use.
-
- list/data
- Use varies by reagent. Custom variable. For example, blood stores blood group and viruses.
-
- volume
- Current volume.
-
- metabolism
- How quickly reagent is processed in mob's bloodstream; by default aslo affects ingest and touch metabolism.
-
- ingest_met
- How quickly reagent is processed when ingested; [metabolism] is used if zero.
-
- touch_met
- Ditto when touching.
-
- dose
- How much of the reagent has been processed, limited by [max_dose]. Used for reagents with varying effects (e.g. ethanol or rezadone) and overdosing.
-
- max_dose
- Maximum amount of reagent that has ever been in a mob. Exists so dose won't grow infinitely when small amounts of reagent are added over time.
-
- overdose
- If [dose] is bigger than [overdose], overdose() proc is called every tick.
-
- scannable
- If set to 1, will show up on health analyzers by name.
-
- affects_dead
- If set to 1, will affect dead players. Used by Adminordrazine.
-
- glass_icon_state
- Used by drinks. icon_state of the glass when this reagent is the master reagent.
-
- glass_name
- Ditto for glass name.
-
- glass_desc
- Ditto for glass desciption.
-
- glass_center_of_mass
- Used for glass placement on tables.
-
- color
- "#RRGGBB" or "#RRGGBBAA" where A is alpha channel.
-
- color_weight
- How much reagent affects color of holder. Used by paint.
-
- Procs:
-
- remove_self(var/amount)
- Removes [amount] of itself.
-
- touch_mob(var/mob/M)
- Called when reagent is in another holder and not splashing the mob. Can be used with noncarbons.
-
- touch_obj(var/obj/O)
- How reagent reacts with objects.
-
- touch_turf(var/turf/T)
- How reagent reacts with turfs.
-
- on_mob_life(var/mob/living/carbon/M, var/alien, var/location)
- Makes necessary checks and calls one of affect procs.
-
- affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
- How reagent affects mob when injected. [removed] is the amount of reagent that has been removed this tick. [alien] is the mob's reagent flag.
-
- affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
- Ditto, ingested. Defaults to affect_blood with halved dose.
-
- affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
- Ditto, touching.
-
- overdose(var/mob/living/carbon/M, var/alien)
- Called when dose is above overdose. Defaults to M.adjustToxLoss(REM).
-
- initialize_data(var/newdata)
- Called when reagent is created. Defaults to setting [data] to [newdata].
-
- mix_data(var/newdata, var/newamount)
- Called when [newamount] of reagent with [newdata] data is added to the current reagent. Used by paint.
-
- get_data()
- Returns data. Can be overriden.
-
-About Recipes:
-
- Recipes are simple datums that contain a list of required reagents and a result.
- They also have a proc that is called when the recipe is matched.
-
- Vars:
-
- name
- Name of the reaction, currently unused.
-
- id
- ID of the reaction, must be unique.
-
- result
- ID of the resulting reagent. Can be null.
-
- list/required_reagents
- Reagents that are required for the reaction and are used up during it.
-
- list/catalysts
- Ditto, but not used up.
-
- list/inhibitors
- Opposite, prevent the reaction from happening.
-
- result_amount
- Amount of resulting reagent.
-
- mix_message
- Message that is shown to mobs when reaction happens.
-
- Procs:
-
- can_happen(var/datum/reagents/holder)
- Customizable. If it returns 0, reaction will not happen. Defaults to always returning 1. Used by slime core reactions.
-
- on_reaction(var/datum/reagents/holder, var/created_volume)
- Called when reaction happens. Used by explosives.
-
- send_data(var/datum/reagents/T)
- Sets resulting reagent's data. Used by blood paint.
-
-About the Tools:
-
- By default, all atom have a reagents var - but its empty. if you want to use an object for the chem.
- system you'll need to add something like this in its new proc:
-
- atom/proc/create_reagents(var/max_volume)
-
- Other important stuff:
-
- amount_per_transfer_from_this var
- This var is mostly used by beakers and bottles.
- It simply tells us how much to transfer when
- 'pouring' our reagents into something else.
-
- atom/proc/is_open_container()
- Checks atom/var/flags & OPENCONTAINER.
- If this returns 1 , you can use syringes, beakers etc
- to manipulate the contents of this object.
- If it's 0, you'll need to write your own custom reagent
- transfer code since you will not be able to use the standard
- tools to manipulate it.
-
+/*
+NOTE: IF YOU UPDATE THE REAGENT-SYSTEM, ALSO UPDATE THIS README.
+
+Structure: /////////////////// //////////////////////////
+ // Mob or object // -------> // Reagents var (datum) // Is a reference to the datum that holds the reagents.
+ /////////////////// //////////////////////////
+ | |
+ The object that holds everything. V
+ reagent_list var (list) A List of datums, each datum is a reagent.
+
+ | | |
+ V V V
+
+ reagents (datums) Reagents. I.e. Water , antitoxins or mercury.
+
+
+Random important notes:
+
+ An objects on_reagent_change will be called every time the objects reagents change.
+ Useful if you want to update the objects icon etc.
+
+About the Holder:
+
+ The holder (reagents datum) is the datum that holds a list of all reagents
+ currently in the object.It also has all the procs needed to manipulate reagents
+
+ Vars:
+ list/datum/reagent/reagent_list
+ List of reagent datums.
+
+ total_volume
+ Total volume of all reagents.
+
+ maximum_volume
+ Maximum volume.
+
+ atom/my_atom
+ Reference to the object that contains this.
+
+ Procs:
+
+ get_free_space()
+ Returns the remaining free volume in the holder.
+
+ get_master_reagent()
+ Returns the reference to the reagent with the largest volume
+
+ get_master_reagent_name()
+ Ditto, but returns the name.
+
+ get_master_reagent_id()
+ Ditto, but returns ID.
+
+ update_total()
+ Updates total volume, called automatically.
+
+ handle_reactions()
+ Checks reagents and triggers any reactions that happen. Usually called automatically.
+
+ add_reagent(var/id, var/amount, var/data = null, var/safety = 0)
+ Adds [amount] units of [id] reagent. [data] will be passed to reagent's mix_data() or initialize_data(). If [safety] is 0, handle_reactions() will be called. Returns 1 if successful, 0 otherwise.
+
+ remove_reagent(var/id, var/amount, var/safety = 0)
+ Ditto, but removes reagent. Returns 1 if successful, 0 otherwise.
+
+ del_reagent(var/id)
+ Removes all of the reagent.
+
+ has_reagent(var/id, var/amount = 0)
+ Checks if holder has at least [amount] of [id] reagent. Returns 1 if the reagent is found and volume is above [amount]. Returns 0 otherwise.
+
+ clear_reagents()
+ Removes all reagents.
+
+ get_reagent_amount(var/id)
+ Returns reagent volume. Returns 0 if reagent is not found.
+
+ get_data(var/id)
+ Returns get_data() of the reagent.
+
+ get_reagents()
+ Returns a string containing all reagent ids and volumes, e.g. "carbon(4),nittrogen(5)".
+
+ remove_any(var/amount = 1)
+ Removes up to [amount] of reagents from [src]. Returns actual amount removed.
+
+ 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]). If [copy] is 1, copies reagents instead.
+
+ touch(var/atom/target)
+ When applying reagents to an atom externally, touch() is called to trigger any on-touch effects of the reagent.
+ This does not handle transferring reagents to things.
+ For example, splashing someone with water will get them wet and extinguish them if they are on fire,
+ even if they are wearing an impermeable suit that prevents the reagents from contacting the skin.
+ Basically just defers to touch_mob(target), touch_turf(target), or touch_obj(target), depending on target's type.
+ Not recommended to use this directly, since trans_to() calls it before attempting to transfer.
+
+ touch_mob(var/mob/target)
+ Calls each reagent's touch_mob(target).
+
+ touch_turf(var/turf/target)
+ Calls each reagent's touch_turf(target).
+
+ touch_obj(var/obj/target)
+ Calls each reagent's touch_obj(target).
+
+ trans_to(var/atom/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
+ The general proc for applying reagents to things externally (as opposed to directly injected into the contents).
+ It first calls touch, then the appropriate trans_to_*() or splash_mob().
+ If for some reason you want touch effects to be bypassed (e.g. injecting stuff directly into a reagent container or person), call the appropriate trans_to_*() proc.
+
+ Calls touch() before checking the type of [target], calling splash_mob(target, amount), trans_to_turf(target, amount, multiplier, copy), or trans_to_obj(target, amount, multiplier, copy).
+
+ trans_id_to(var/atom/target, var/id, var/amount = 1)
+ Transfers [amount] of [id] to [target]. Returns amount transferred.
+
+ splash_mob(var/mob/target, var/amount = 1, var/clothes = 1)
+ Checks mob's clothing if [clothes] is 1 and transfers [amount] reagents to mob's skin.
+ Don't call this directly. Call apply_to() instead.
+
+ trans_to_mob(var/mob/target, var/amount = 1, var/type = CHEM_BLOOD, var/multiplier = 1, var/copy = 0)
+ Transfers [amount] reagents to the mob's appropriate holder, depending on [type]. Ignores protection.
+
+ trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
+ Turfs don't currently have any reagents. Puts [amount] reagents into a temporary holder, calls touch_turf(target) from it, and deletes it.
+
+ trans_to_obj(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0)
+ If target has reagents, transfers [amount] to it. Otherwise, same as trans_to_turf().
+
+ atom/proc/create_reagents(var/max_vol)
+ Creates a new reagent datum.
+
+About Reagents:
+
+ Reagents are all the things you can mix and fille in bottles etc. This can be anything from
+ rejuvs over water to... iron.
+
+ Vars:
+
+ name
+ Name that shows up in-game.
+
+ id
+ ID that is used for internal tracking. MUST BE UNIQUE.
+
+ description
+ Description that shows up in-game.
+
+ datum/reagents/holder
+ Reference to holder.
+
+ reagent_state
+ Could be GAS, LIQUID, or SOLID. Affects nothing. Reserved for future use.
+
+ list/data
+ Use varies by reagent. Custom variable. For example, blood stores blood group and viruses.
+
+ volume
+ Current volume.
+
+ metabolism
+ How quickly reagent is processed in mob's bloodstream; by default aslo affects ingest and touch metabolism.
+
+ ingest_met
+ How quickly reagent is processed when ingested; [metabolism] is used if zero.
+
+ touch_met
+ Ditto when touching.
+
+ dose
+ How much of the reagent has been processed, limited by [max_dose]. Used for reagents with varying effects (e.g. ethanol or rezadone) and overdosing.
+
+ max_dose
+ Maximum amount of reagent that has ever been in a mob. Exists so dose won't grow infinitely when small amounts of reagent are added over time.
+
+ overdose
+ If [dose] is bigger than [overdose], overdose() proc is called every tick.
+
+ scannable
+ If set to 1, will show up on health analyzers by name.
+
+ affects_dead
+ If set to 1, will affect dead players. Used by Adminordrazine.
+
+ glass_icon_state
+ Used by drinks. icon_state of the glass when this reagent is the master reagent.
+
+ glass_name
+ Ditto for glass name.
+
+ glass_desc
+ Ditto for glass desciption.
+
+ glass_center_of_mass
+ Used for glass placement on tables.
+
+ color
+ "#RRGGBB" or "#RRGGBBAA" where A is alpha channel.
+
+ color_weight
+ How much reagent affects color of holder. Used by paint.
+
+ Procs:
+
+ remove_self(var/amount)
+ Removes [amount] of itself.
+
+ touch_mob(var/mob/M)
+ Called when reagent is in another holder and not splashing the mob. Can be used with noncarbons.
+
+ touch_obj(var/obj/O)
+ How reagent reacts with objects.
+
+ touch_turf(var/turf/T)
+ How reagent reacts with turfs.
+
+ on_mob_life(var/mob/living/carbon/M, var/alien, var/location)
+ Makes necessary checks and calls one of affect procs.
+
+ affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
+ How reagent affects mob when injected. [removed] is the amount of reagent that has been removed this tick. [alien] is the mob's reagent flag.
+
+ affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
+ Ditto, ingested. Defaults to affect_blood with halved dose.
+
+ affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
+ Ditto, touching.
+
+ overdose(var/mob/living/carbon/M, var/alien)
+ Called when dose is above overdose. Defaults to M.adjustToxLoss(REM).
+
+ initialize_data(var/newdata)
+ Called when reagent is created. Defaults to setting [data] to [newdata].
+
+ mix_data(var/newdata, var/newamount)
+ Called when [newamount] of reagent with [newdata] data is added to the current reagent. Used by paint.
+
+ get_data()
+ Returns data. Can be overriden.
+
+About Recipes:
+
+ Recipes are simple datums that contain a list of required reagents and a result.
+ They also have a proc that is called when the recipe is matched.
+
+ Vars:
+
+ name
+ Name of the reaction, currently unused.
+
+ id
+ ID of the reaction, must be unique.
+
+ result
+ ID of the resulting reagent. Can be null.
+
+ list/required_reagents
+ Reagents that are required for the reaction and are used up during it.
+
+ list/catalysts
+ Ditto, but not used up.
+
+ list/inhibitors
+ Opposite, prevent the reaction from happening.
+
+ result_amount
+ Amount of resulting reagent.
+
+ mix_message
+ Message that is shown to mobs when reaction happens.
+
+ Procs:
+
+ can_happen(var/datum/reagents/holder)
+ Customizable. If it returns 0, reaction will not happen. Defaults to always returning 1. Used by slime core reactions.
+
+ on_reaction(var/datum/reagents/holder, var/created_volume)
+ Called when reaction happens. Used by explosives.
+
+ send_data(var/datum/reagents/T)
+ Sets resulting reagent's data. Used by blood paint.
+
+About the Tools:
+
+ By default, all atom have a reagents var - but its empty. if you want to use an object for the chem.
+ system you'll need to add something like this in its new proc:
+
+ atom/proc/create_reagents(var/max_volume)
+
+ Other important stuff:
+
+ amount_per_transfer_from_this var
+ This var is mostly used by beakers and bottles.
+ It simply tells us how much to transfer when
+ 'pouring' our reagents into something else.
+
+ atom/proc/is_open_container()
+ Checks atom/var/flags & OPENCONTAINER.
+ If this returns 1 , you can use syringes, beakers etc
+ to manipulate the contents of this object.
+ If it's 0, you'll need to write your own custom reagent
+ transfer code since you will not be able to use the standard
+ tools to manipulate it.
+
*/
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers/_reagent_containers.dm
similarity index 97%
rename from code/modules/reagents/reagent_containers.dm
rename to code/modules/reagents/reagent_containers/_reagent_containers.dm
index 7a6927f49d..64dd2622d2 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers/_reagent_containers.dm
@@ -1,145 +1,145 @@
-/obj/item/weapon/reagent_containers
- name = "Container"
- desc = "..."
- icon = 'icons/obj/chemical.dmi'
- icon_state = null
- w_class = ITEMSIZE_SMALL
- var/amount_per_transfer_from_this = 5
- var/possible_transfer_amounts = list(5,10,15,25,30)
- var/volume = 30
-
-/obj/item/weapon/reagent_containers/verb/set_APTFT() //set amount_per_transfer_from_this
- set name = "Set transfer amount"
- set category = "Object"
- set src in range(0)
- var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts
- if(N)
- amount_per_transfer_from_this = N
-
-/obj/item/weapon/reagent_containers/Initialize()
- . = ..()
- if(!possible_transfer_amounts)
- src.verbs -= /obj/item/weapon/reagent_containers/verb/set_APTFT
- create_reagents(volume)
-
-/obj/item/weapon/reagent_containers/attack_self(mob/user as mob)
- return
-
-/obj/item/weapon/reagent_containers/afterattack(obj/target, mob/user, flag)
- return
-
-/obj/item/weapon/reagent_containers/proc/reagentlist() // For attack logs
- if(reagents)
- return reagents.get_reagents()
- return "No reagent holder"
-
-/obj/item/weapon/reagent_containers/proc/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target) // This goes into afterattack
- if(!istype(target))
- return 0
-
- if(!target.reagents || !target.reagents.total_volume)
- to_chat(user, "[target] is empty.")
- return 1
-
- if(reagents && !reagents.get_free_space())
- to_chat(user, "[src] is full.")
- return 1
-
- var/trans = target.reagents.trans_to_obj(src, target:amount_per_transfer_from_this)
- to_chat(user, "You fill [src] with [trans] units of the contents of [target].")
- return 1
-
-/obj/item/weapon/reagent_containers/proc/standard_splash_mob(var/mob/user, var/mob/target) // This goes into afterattack
- if(!istype(target))
- return
-
- if(!reagents || !reagents.total_volume)
- to_chat(user, "[src] is empty.")
- return 1
-
- if(target.reagents && !target.reagents.get_free_space())
- to_chat(user, "[target] is full.")
- return 1
-
- var/contained = reagentlist()
- add_attack_logs(user,target,"Splashed with [src.name] containing [contained]")
- user.visible_message("[target] has been splashed with something by [user]!", "You splash the solution onto [target].")
- reagents.splash(target, reagents.total_volume)
- return 1
-
-/obj/item/weapon/reagent_containers/proc/self_feed_message(var/mob/user)
- to_chat(user, "You eat \the [src]")
-
-/obj/item/weapon/reagent_containers/proc/other_feed_message_start(var/mob/user, var/mob/target)
- user.visible_message("[user] is trying to feed [target] \the [src]!")
-
-/obj/item/weapon/reagent_containers/proc/other_feed_message_finish(var/mob/user, var/mob/target)
- user.visible_message("[user] has fed [target] \the [src]!")
-
-/obj/item/weapon/reagent_containers/proc/feed_sound(var/mob/user)
- return
-
-/obj/item/weapon/reagent_containers/proc/standard_feed_mob(var/mob/user, var/mob/target) // This goes into attack
- if(!istype(target))
- return 0
-
- if(!reagents || !reagents.total_volume)
- to_chat(user, "\The [src] is empty.")
- return 1
-
- if(target == user)
- if(istype(user, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- if(!H.check_has_mouth())
- to_chat(user, "Where do you intend to put \the [src]? You don't have a mouth!")
- return
- var/obj/item/blocked = H.check_mouth_coverage()
- if(blocked)
- to_chat(user, "\The [blocked] is in the way!")
- return
-
- user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things
- self_feed_message(user)
- reagents.trans_to_mob(user, issmall(user) ? CEILING(amount_per_transfer_from_this/2, 1) : amount_per_transfer_from_this, CHEM_INGEST)
- feed_sound(user)
- return 1
- else
- if(istype(target, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = target
- if(!H.check_has_mouth())
- to_chat(user, "Where do you intend to put \the [src]? \The [H] doesn't have a mouth!")
- return
- var/obj/item/blocked = H.check_mouth_coverage()
- if(blocked)
- to_chat(user, "\The [blocked] is in the way!")
- return
-
- other_feed_message_start(user, target)
-
- user.setClickCooldown(user.get_attack_speed(src))
- if(!do_mob(user, target))
- return
-
- other_feed_message_finish(user, target)
-
- var/contained = reagentlist()
- add_attack_logs(user,target,"Fed from [src.name] containing [contained]")
- reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INGEST)
- feed_sound(user)
- return 1
-
-/obj/item/weapon/reagent_containers/proc/standard_pour_into(var/mob/user, var/atom/target) // This goes into afterattack and yes, it's atom-level
- if(!target.is_open_container() || !target.reagents)
- return 0
-
- if(!reagents || !reagents.total_volume)
- to_chat(user, "[src] is empty.")
- return 1
-
- if(!target.reagents.get_free_space())
- to_chat(user, "[target] is full.")
- return 1
-
- var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
- to_chat(user, "You transfer [trans] units of the solution to [target].")
- return 1
+/obj/item/weapon/reagent_containers
+ name = "Container"
+ desc = "..."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = null
+ w_class = ITEMSIZE_SMALL
+ var/amount_per_transfer_from_this = 5
+ var/possible_transfer_amounts = list(5,10,15,25,30)
+ var/volume = 30
+
+/obj/item/weapon/reagent_containers/verb/set_APTFT() //set amount_per_transfer_from_this
+ set name = "Set transfer amount"
+ set category = "Object"
+ set src in range(0)
+ var/N = input("Amount per transfer from this:","[src]") as null|anything in possible_transfer_amounts
+ if(N)
+ amount_per_transfer_from_this = N
+
+/obj/item/weapon/reagent_containers/Initialize()
+ . = ..()
+ if(!possible_transfer_amounts)
+ src.verbs -= /obj/item/weapon/reagent_containers/verb/set_APTFT
+ create_reagents(volume)
+
+/obj/item/weapon/reagent_containers/attack_self(mob/user as mob)
+ return
+
+/obj/item/weapon/reagent_containers/afterattack(obj/target, mob/user, flag)
+ return
+
+/obj/item/weapon/reagent_containers/proc/reagentlist() // For attack logs
+ if(reagents)
+ return reagents.get_reagents()
+ return "No reagent holder"
+
+/obj/item/weapon/reagent_containers/proc/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target) // This goes into afterattack
+ if(!istype(target))
+ return 0
+
+ if(!target.reagents || !target.reagents.total_volume)
+ to_chat(user, "[target] is empty.")
+ return 1
+
+ if(reagents && !reagents.get_free_space())
+ to_chat(user, "[src] is full.")
+ return 1
+
+ var/trans = target.reagents.trans_to_obj(src, target:amount_per_transfer_from_this)
+ to_chat(user, "You fill [src] with [trans] units of the contents of [target].")
+ return 1
+
+/obj/item/weapon/reagent_containers/proc/standard_splash_mob(var/mob/user, var/mob/target) // This goes into afterattack
+ if(!istype(target))
+ return
+
+ if(!reagents || !reagents.total_volume)
+ to_chat(user, "[src] is empty.")
+ return 1
+
+ if(target.reagents && !target.reagents.get_free_space())
+ to_chat(user, "[target] is full.")
+ return 1
+
+ var/contained = reagentlist()
+ add_attack_logs(user,target,"Splashed with [src.name] containing [contained]")
+ user.visible_message("[target] has been splashed with something by [user]!", "You splash the solution onto [target].")
+ reagents.splash(target, reagents.total_volume)
+ return 1
+
+/obj/item/weapon/reagent_containers/proc/self_feed_message(var/mob/user)
+ to_chat(user, "You eat \the [src]")
+
+/obj/item/weapon/reagent_containers/proc/other_feed_message_start(var/mob/user, var/mob/target)
+ user.visible_message("[user] is trying to feed [target] \the [src]!")
+
+/obj/item/weapon/reagent_containers/proc/other_feed_message_finish(var/mob/user, var/mob/target)
+ user.visible_message("[user] has fed [target] \the [src]!")
+
+/obj/item/weapon/reagent_containers/proc/feed_sound(var/mob/user)
+ return
+
+/obj/item/weapon/reagent_containers/proc/standard_feed_mob(var/mob/user, var/mob/target) // This goes into attack
+ if(!istype(target))
+ return 0
+
+ if(!reagents || !reagents.total_volume)
+ to_chat(user, "\The [src] is empty.")
+ return 1
+
+ if(target == user)
+ if(istype(user, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ if(!H.check_has_mouth())
+ to_chat(user, "Where do you intend to put \the [src]? You don't have a mouth!")
+ return
+ var/obj/item/blocked = H.check_mouth_coverage()
+ if(blocked)
+ to_chat(user, "\The [blocked] is in the way!")
+ return
+
+ user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things
+ self_feed_message(user)
+ reagents.trans_to_mob(user, issmall(user) ? CEILING(amount_per_transfer_from_this/2, 1) : amount_per_transfer_from_this, CHEM_INGEST)
+ feed_sound(user)
+ return 1
+ else
+ if(istype(target, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = target
+ if(!H.check_has_mouth())
+ to_chat(user, "Where do you intend to put \the [src]? \The [H] doesn't have a mouth!")
+ return
+ var/obj/item/blocked = H.check_mouth_coverage()
+ if(blocked)
+ to_chat(user, "\The [blocked] is in the way!")
+ return
+
+ other_feed_message_start(user, target)
+
+ user.setClickCooldown(user.get_attack_speed(src))
+ if(!do_mob(user, target))
+ return
+
+ other_feed_message_finish(user, target)
+
+ var/contained = reagentlist()
+ add_attack_logs(user,target,"Fed from [src.name] containing [contained]")
+ reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INGEST)
+ feed_sound(user)
+ return 1
+
+/obj/item/weapon/reagent_containers/proc/standard_pour_into(var/mob/user, var/atom/target) // This goes into afterattack and yes, it's atom-level
+ if(!target.is_open_container() || !target.reagents)
+ return 0
+
+ if(!reagents || !reagents.total_volume)
+ to_chat(user, "[src] is empty.")
+ return 1
+
+ if(!target.reagents.get_free_space())
+ to_chat(user, "[target] is full.")
+ return 1
+
+ var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
+ to_chat(user, "You transfer [trans] units of the solution to [target].")
+ return 1
diff --git a/code/modules/reagents/Chemistry-Reagents-Helpers.dm b/code/modules/reagents/reagents/_helpers.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents-Helpers.dm
rename to code/modules/reagents/reagents/_helpers.dm
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/reagents/_reagents.dm
similarity index 97%
rename from code/modules/reagents/Chemistry-Reagents.dm
rename to code/modules/reagents/reagents/_reagents.dm
index 3d32c00663..00bb509b7f 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/reagents/_reagents.dm
@@ -1,237 +1,237 @@
-
-
-
-/datum/reagent
- var/name = "Reagent"
- var/id = "reagent"
- var/description = "A non-descript chemical."
- var/taste_description = "bitterness"
- var/taste_mult = 1 //how this taste compares to others. Higher values means it is more noticable
- var/datum/reagents/holder = null
- var/reagent_state = SOLID
- var/list/data = null
- var/volume = 0
- var/metabolism = REM // This would be 0.2 normally
- var/list/filtered_organs = list() // Organs that will slow the processing of this chemical.
- var/mrate_static = FALSE //If the reagent should always process at the same speed, regardless of species, make this TRUE
- var/ingest_met = 0
- var/touch_met = 0
- var/dose = 0
- var/max_dose = 0
- var/overdose = 0 //Amount at which overdose starts
- var/overdose_mod = 1 //Modifier to overdose damage
- var/can_overdose_touch = FALSE // Can the chemical OD when processing on touch?
- var/scannable = 0 // Shows up on health analyzers.
-
- var/affects_dead = 0 // Does this chem process inside a corpse?
- var/affects_robots = 0 // Does this chem process inside a Synth?
-
- var/allergen_type = GENERIC // What potential allergens does this contain?
- var/allergen_factor = 1 // If the potential allergens are mixed and low-volume, they're a bit less dangerous. Needed for drinks because they're a single reagent compared to food which contains multiple seperate reagents.
-
- var/cup_icon_state = null
- var/cup_name = null
- var/cup_desc = null
- var/cup_center_of_mass = null
-
- var/color = "#000000"
- var/color_weight = 1
-
- var/glass_icon = DRINK_ICON_DEFAULT
- var/glass_name = "something"
- var/glass_desc = "It's a glass of... what, exactly?"
- var/list/glass_special = null // null equivalent to list()
-
-/datum/reagent/proc/remove_self(var/amount) // Shortcut
- if(holder)
- 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)
- return
-
-/datum/reagent/proc/touch_obj(var/obj/O, var/amount) // Acid melting, cleaner cleaning, etc
- return
-
-/datum/reagent/proc/touch_turf(var/turf/T, var/amount) // Cleaner cleaning, lube lubbing, etc, all go here
- return
-
-/datum/reagent/proc/on_mob_life(var/mob/living/carbon/M, var/alien, var/datum/reagents/metabolism/location) // Currently, on_mob_life is called on carbons. Any interaction with non-carbon mobs (lube) will need to be done in touch_mob.
- if(!istype(M))
- return
- if(!affects_dead && M.stat == DEAD)
- return
- if(!affects_robots && M.isSynthetic())
- return
- if(!istype(location))
- return
-
- var/datum/reagents/metabolism/active_metab = location
- var/removed = metabolism
-
- var/ingest_rem_mult = 1
- var/ingest_abs_mult = 1
-
- if(!mrate_static == TRUE)
- // Modifiers
- for(var/datum/modifier/mod in M.modifiers)
- if(!isnull(mod.metabolism_percent))
- removed *= mod.metabolism_percent
- ingest_rem_mult *= mod.metabolism_percent
- // Species
- removed *= M.species.metabolic_rate
- ingest_rem_mult *= M.species.metabolic_rate
- // Metabolism
- removed *= active_metab.metabolism_speed
- ingest_rem_mult *= active_metab.metabolism_speed
-
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(!H.isSynthetic())
- if(H.species.has_organ[O_HEART] && (active_metab.metabolism_class == CHEM_BLOOD))
- var/obj/item/organ/internal/heart/Pump = H.internal_organs_by_name[O_HEART]
- if(!Pump)
- removed *= 0.1
- else if(Pump.standard_pulse_level == PULSE_NONE) // No pulse normally means chemicals process a little bit slower than normal.
- removed *= 0.8
- else // Otherwise, chemicals process as per percentage of your current pulse, or, if you have no pulse but are alive, by a miniscule amount.
- removed *= max(0.1, H.pulse / Pump.standard_pulse_level)
-
- if(H.species.has_organ[O_STOMACH] && (active_metab.metabolism_class == CHEM_INGEST))
- var/obj/item/organ/internal/stomach/Chamber = H.internal_organs_by_name[O_STOMACH]
- if(Chamber)
- ingest_rem_mult *= max(0.1, 1 - (Chamber.damage / Chamber.max_damage))
- else
- ingest_rem_mult = 0.1
-
- if(H.species.has_organ[O_INTESTINE] && (active_metab.metabolism_class == CHEM_INGEST))
- var/obj/item/organ/internal/intestine/Tube = H.internal_organs_by_name[O_INTESTINE]
- if(Tube)
- ingest_abs_mult *= max(0.1, 1 - (Tube.damage / Tube.max_damage))
- else
- ingest_abs_mult = 0.1
-
- else
- var/obj/item/organ/internal/heart/machine/Pump = H.internal_organs_by_name[O_PUMP]
- var/obj/item/organ/internal/stomach/machine/Cycler = H.internal_organs_by_name[O_CYCLER]
-
- if(active_metab.metabolism_class == CHEM_BLOOD)
- if(Pump)
- removed *= 1.1 - Pump.damage / Pump.max_damage
- else
- removed *= 0.1
-
- else if(active_metab.metabolism_class == CHEM_INGEST) // If the pump is damaged, we waste chems from the tank.
- if(Pump)
- ingest_abs_mult *= max(0.25, 1 - Pump.damage / Pump.max_damage)
-
- else
- ingest_abs_mult *= 0.2
-
- if(Cycler) // If we're damaged, we empty our tank slower.
- ingest_rem_mult = max(0.1, 1 - (Cycler.damage / Cycler.max_damage))
-
- else
- ingest_rem_mult = 0.1
-
- else if(active_metab.metabolism_class == CHEM_TOUCH) // Machines don't exactly absorb chemicals.
- removed *= 0.5
-
- if(filtered_organs && filtered_organs.len)
- for(var/organ_tag in filtered_organs)
- var/obj/item/organ/internal/O = H.internal_organs_by_name[organ_tag]
- if(O && !O.is_broken() && prob(max(0, O.max_damage - O.damage)))
- removed *= 0.8
- if(active_metab.metabolism_class == CHEM_INGEST)
- ingest_rem_mult *= 0.8
-
- if(ingest_met && (active_metab.metabolism_class == CHEM_INGEST))
- removed = ingest_met * ingest_rem_mult
- if(touch_met && (active_metab.metabolism_class == CHEM_TOUCH))
- removed = touch_met
- removed = min(removed, volume)
- max_dose = max(volume, max_dose)
- dose = min(dose + removed, max_dose)
- if(removed >= (metabolism * 0.1) || removed >= 0.1) // If there's too little chemical, don't affect the mob, just remove it
- switch(active_metab.metabolism_class)
- if(CHEM_BLOOD)
- affect_blood(M, alien, removed)
- if(CHEM_INGEST)
- affect_ingest(M, alien, removed * ingest_abs_mult)
- if(CHEM_TOUCH)
- affect_touch(M, alien, removed)
- if(overdose && (volume > overdose * M?.species.chemOD_threshold) && (active_metab.metabolism_class != CHEM_TOUCH && !can_overdose_touch))
- overdose(M, alien, removed)
- if(M.species.allergens & allergen_type) //uhoh, we can't handle this!
- var/damage_severity = M.species.allergen_damage_severity*allergen_factor
- var/disable_severity = M.species.allergen_disable_severity*allergen_factor
- if(M.species.allergen_reaction & AG_TOX_DMG)
- M.adjustToxLoss(damage_severity)
- if(M.species.allergen_reaction & AG_OXY_DMG)
- M.adjustOxyLoss(damage_severity)
- if(prob(2.5*disable_severity))
- M.emote(pick("cough","gasp","choke"))
- if(M.species.allergen_reaction & AG_EMOTE)
- if(prob(2.5*disable_severity)) //this has a higher base chance, but not *too* high
- M.emote(pick("pale","shiver","twitch"))
- if(M.species.allergen_reaction & AG_PAIN)
- M.adjustHalLoss(disable_severity)
- if(M.species.allergen_reaction & AG_WEAKEN)
- M.Weaken(disable_severity)
- if(M.species.allergen_reaction & AG_BLURRY)
- M.eye_blurry = max(M.eye_blurry, disable_severity)
- if(M.species.allergen_reaction & AG_SLEEPY)
- M.drowsyness = max(M.drowsyness, disable_severity)
- remove_self(removed)
- return
-
-/datum/reagent/proc/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
- return
-
-/datum/reagent/proc/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
- M.bloodstr.add_reagent(id, removed)
- return
-
-/datum/reagent/proc/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
- return
-
-/datum/reagent/proc/overdose(var/mob/living/carbon/M, var/alien, var/removed) // Overdose effect.
- if(alien == IS_DIONA)
- return
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- overdose_mod *= H.species.chemOD_mod
- // 6 damage per unit at minimum, scales with excessive reagents. Rounding should help keep damage consistent between ingest / inject, but isn't perfect.
- // Hardcapped at 3.6 damage per tick, or 18 damage per unit at 0.2 metabolic rate so that you can't instakill people with overdoses by feeding them infinite periadaxon.
- // Overall, max damage is slightly less effective than hydrophoron, and 1/5 as effective as cyanide.
- M.adjustToxLoss(min(removed * overdose_mod * round(3 + 3 * volume / overdose), 3.6))
-
-/datum/reagent/proc/initialize_data(var/newdata) // Called when the reagent is created.
- if(!isnull(newdata))
- data = newdata
- return
-
-/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
-
-/datum/reagent/proc/get_data() // Just in case you have a reagent that handles data differently.
- if(data && istype(data, /list))
- return data.Copy()
- else if(data)
- return data
- return null
-
-/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
- holder = null
- . = ..()
-
-/* DEPRECATED - TODO: REMOVE EVERYWHERE */
-
-/datum/reagent/proc/reaction_turf(var/turf/target)
- touch_turf(target)
-
-/datum/reagent/proc/reaction_obj(var/obj/target)
- touch_obj(target)
-
-/datum/reagent/proc/reaction_mob(var/mob/target)
- touch_mob(target)
+
+
+
+/datum/reagent
+ var/name = "Reagent"
+ var/id = "reagent"
+ var/description = "A non-descript chemical."
+ var/taste_description = "bitterness"
+ var/taste_mult = 1 //how this taste compares to others. Higher values means it is more noticable
+ var/datum/reagents/holder = null
+ var/reagent_state = SOLID
+ var/list/data = null
+ var/volume = 0
+ var/metabolism = REM // This would be 0.2 normally
+ var/list/filtered_organs = list() // Organs that will slow the processing of this chemical.
+ var/mrate_static = FALSE //If the reagent should always process at the same speed, regardless of species, make this TRUE
+ var/ingest_met = 0
+ var/touch_met = 0
+ var/dose = 0
+ var/max_dose = 0
+ var/overdose = 0 //Amount at which overdose starts
+ var/overdose_mod = 1 //Modifier to overdose damage
+ var/can_overdose_touch = FALSE // Can the chemical OD when processing on touch?
+ var/scannable = 0 // Shows up on health analyzers.
+
+ var/affects_dead = 0 // Does this chem process inside a corpse?
+ var/affects_robots = 0 // Does this chem process inside a Synth?
+
+ var/allergen_type = GENERIC // What potential allergens does this contain?
+ var/allergen_factor = 1 // If the potential allergens are mixed and low-volume, they're a bit less dangerous. Needed for drinks because they're a single reagent compared to food which contains multiple seperate reagents.
+
+ var/cup_icon_state = null
+ var/cup_name = null
+ var/cup_desc = null
+ var/cup_center_of_mass = null
+
+ var/color = "#000000"
+ var/color_weight = 1
+
+ var/glass_icon = DRINK_ICON_DEFAULT
+ var/glass_name = "something"
+ var/glass_desc = "It's a glass of... what, exactly?"
+ var/list/glass_special = null // null equivalent to list()
+
+/datum/reagent/proc/remove_self(var/amount) // Shortcut
+ if(holder)
+ 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)
+ return
+
+/datum/reagent/proc/touch_obj(var/obj/O, var/amount) // Acid melting, cleaner cleaning, etc
+ return
+
+/datum/reagent/proc/touch_turf(var/turf/T, var/amount) // Cleaner cleaning, lube lubbing, etc, all go here
+ return
+
+/datum/reagent/proc/on_mob_life(var/mob/living/carbon/M, var/alien, var/datum/reagents/metabolism/location) // Currently, on_mob_life is called on carbons. Any interaction with non-carbon mobs (lube) will need to be done in touch_mob.
+ if(!istype(M))
+ return
+ if(!affects_dead && M.stat == DEAD)
+ return
+ if(!affects_robots && M.isSynthetic())
+ return
+ if(!istype(location))
+ return
+
+ var/datum/reagents/metabolism/active_metab = location
+ var/removed = metabolism
+
+ var/ingest_rem_mult = 1
+ var/ingest_abs_mult = 1
+
+ if(!mrate_static == TRUE)
+ // Modifiers
+ for(var/datum/modifier/mod in M.modifiers)
+ if(!isnull(mod.metabolism_percent))
+ removed *= mod.metabolism_percent
+ ingest_rem_mult *= mod.metabolism_percent
+ // Species
+ removed *= M.species.metabolic_rate
+ ingest_rem_mult *= M.species.metabolic_rate
+ // Metabolism
+ removed *= active_metab.metabolism_speed
+ ingest_rem_mult *= active_metab.metabolism_speed
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(!H.isSynthetic())
+ if(H.species.has_organ[O_HEART] && (active_metab.metabolism_class == CHEM_BLOOD))
+ var/obj/item/organ/internal/heart/Pump = H.internal_organs_by_name[O_HEART]
+ if(!Pump)
+ removed *= 0.1
+ else if(Pump.standard_pulse_level == PULSE_NONE) // No pulse normally means chemicals process a little bit slower than normal.
+ removed *= 0.8
+ else // Otherwise, chemicals process as per percentage of your current pulse, or, if you have no pulse but are alive, by a miniscule amount.
+ removed *= max(0.1, H.pulse / Pump.standard_pulse_level)
+
+ if(H.species.has_organ[O_STOMACH] && (active_metab.metabolism_class == CHEM_INGEST))
+ var/obj/item/organ/internal/stomach/Chamber = H.internal_organs_by_name[O_STOMACH]
+ if(Chamber)
+ ingest_rem_mult *= max(0.1, 1 - (Chamber.damage / Chamber.max_damage))
+ else
+ ingest_rem_mult = 0.1
+
+ if(H.species.has_organ[O_INTESTINE] && (active_metab.metabolism_class == CHEM_INGEST))
+ var/obj/item/organ/internal/intestine/Tube = H.internal_organs_by_name[O_INTESTINE]
+ if(Tube)
+ ingest_abs_mult *= max(0.1, 1 - (Tube.damage / Tube.max_damage))
+ else
+ ingest_abs_mult = 0.1
+
+ else
+ var/obj/item/organ/internal/heart/machine/Pump = H.internal_organs_by_name[O_PUMP]
+ var/obj/item/organ/internal/stomach/machine/Cycler = H.internal_organs_by_name[O_CYCLER]
+
+ if(active_metab.metabolism_class == CHEM_BLOOD)
+ if(Pump)
+ removed *= 1.1 - Pump.damage / Pump.max_damage
+ else
+ removed *= 0.1
+
+ else if(active_metab.metabolism_class == CHEM_INGEST) // If the pump is damaged, we waste chems from the tank.
+ if(Pump)
+ ingest_abs_mult *= max(0.25, 1 - Pump.damage / Pump.max_damage)
+
+ else
+ ingest_abs_mult *= 0.2
+
+ if(Cycler) // If we're damaged, we empty our tank slower.
+ ingest_rem_mult = max(0.1, 1 - (Cycler.damage / Cycler.max_damage))
+
+ else
+ ingest_rem_mult = 0.1
+
+ else if(active_metab.metabolism_class == CHEM_TOUCH) // Machines don't exactly absorb chemicals.
+ removed *= 0.5
+
+ if(filtered_organs && filtered_organs.len)
+ for(var/organ_tag in filtered_organs)
+ var/obj/item/organ/internal/O = H.internal_organs_by_name[organ_tag]
+ if(O && !O.is_broken() && prob(max(0, O.max_damage - O.damage)))
+ removed *= 0.8
+ if(active_metab.metabolism_class == CHEM_INGEST)
+ ingest_rem_mult *= 0.8
+
+ if(ingest_met && (active_metab.metabolism_class == CHEM_INGEST))
+ removed = ingest_met * ingest_rem_mult
+ if(touch_met && (active_metab.metabolism_class == CHEM_TOUCH))
+ removed = touch_met
+ removed = min(removed, volume)
+ max_dose = max(volume, max_dose)
+ dose = min(dose + removed, max_dose)
+ if(removed >= (metabolism * 0.1) || removed >= 0.1) // If there's too little chemical, don't affect the mob, just remove it
+ switch(active_metab.metabolism_class)
+ if(CHEM_BLOOD)
+ affect_blood(M, alien, removed)
+ if(CHEM_INGEST)
+ affect_ingest(M, alien, removed * ingest_abs_mult)
+ if(CHEM_TOUCH)
+ affect_touch(M, alien, removed)
+ if(overdose && (volume > overdose * M?.species.chemOD_threshold) && (active_metab.metabolism_class != CHEM_TOUCH && !can_overdose_touch))
+ overdose(M, alien, removed)
+ if(M.species.allergens & allergen_type) //uhoh, we can't handle this!
+ var/damage_severity = M.species.allergen_damage_severity*allergen_factor
+ var/disable_severity = M.species.allergen_disable_severity*allergen_factor
+ if(M.species.allergen_reaction & AG_TOX_DMG)
+ M.adjustToxLoss(damage_severity)
+ if(M.species.allergen_reaction & AG_OXY_DMG)
+ M.adjustOxyLoss(damage_severity)
+ if(prob(2.5*disable_severity))
+ M.emote(pick("cough","gasp","choke"))
+ if(M.species.allergen_reaction & AG_EMOTE)
+ if(prob(2.5*disable_severity)) //this has a higher base chance, but not *too* high
+ M.emote(pick("pale","shiver","twitch"))
+ if(M.species.allergen_reaction & AG_PAIN)
+ M.adjustHalLoss(disable_severity)
+ if(M.species.allergen_reaction & AG_WEAKEN)
+ M.Weaken(disable_severity)
+ if(M.species.allergen_reaction & AG_BLURRY)
+ M.eye_blurry = max(M.eye_blurry, disable_severity)
+ if(M.species.allergen_reaction & AG_SLEEPY)
+ M.drowsyness = max(M.drowsyness, disable_severity)
+ remove_self(removed)
+ return
+
+/datum/reagent/proc/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
+ return
+
+/datum/reagent/proc/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
+ M.bloodstr.add_reagent(id, removed)
+ return
+
+/datum/reagent/proc/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
+ return
+
+/datum/reagent/proc/overdose(var/mob/living/carbon/M, var/alien, var/removed) // Overdose effect.
+ if(alien == IS_DIONA)
+ return
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ overdose_mod *= H.species.chemOD_mod
+ // 6 damage per unit at minimum, scales with excessive reagents. Rounding should help keep damage consistent between ingest / inject, but isn't perfect.
+ // Hardcapped at 3.6 damage per tick, or 18 damage per unit at 0.2 metabolic rate so that you can't instakill people with overdoses by feeding them infinite periadaxon.
+ // Overall, max damage is slightly less effective than hydrophoron, and 1/5 as effective as cyanide.
+ M.adjustToxLoss(min(removed * overdose_mod * round(3 + 3 * volume / overdose), 3.6))
+
+/datum/reagent/proc/initialize_data(var/newdata) // Called when the reagent is created.
+ if(!isnull(newdata))
+ data = newdata
+ return
+
+/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
+
+/datum/reagent/proc/get_data() // Just in case you have a reagent that handles data differently.
+ if(data && istype(data, /list))
+ return data.Copy()
+ else if(data)
+ return data
+ return null
+
+/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
+ holder = null
+ . = ..()
+
+/* DEPRECATED - TODO: REMOVE EVERYWHERE */
+
+/datum/reagent/proc/reaction_turf(var/turf/target)
+ touch_turf(target)
+
+/datum/reagent/proc/reaction_obj(var/obj/target)
+ touch_obj(target)
+
+/datum/reagent/proc/reaction_mob(var/mob/target)
+ touch_mob(target)
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/reagents/core.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm
rename to code/modules/reagents/reagents/core.dm
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/reagents/dispenser.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
rename to code/modules/reagents/reagents/dispenser.dm
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/reagents/food_drinks.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
rename to code/modules/reagents/reagents/food_drinks.dm
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/reagents/medicine.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm
rename to code/modules/reagents/reagents/medicine.dm
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm b/code/modules/reagents/reagents/modifiers.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm
rename to code/modules/reagents/reagents/modifiers.dm
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/reagents/other.dm
similarity index 90%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
rename to code/modules/reagents/reagents/other.dm
index 5c1c9cf427..9e83c720bc 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
+++ b/code/modules/reagents/reagents/other.dm
@@ -238,14 +238,6 @@
reagent_state = SOLID
color = "#D0D0D0"
-/datum/reagent/uranium
- name ="Uranium"
- id = "uranium"
- description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive."
- taste_description = "metal"
- reagent_state = SOLID
- color = "#B8B8C0"
-
/datum/reagent/platinum
name = "Platinum"
id = "platinum"
@@ -254,6 +246,14 @@
reagent_state = SOLID
color = "#777777"
+/datum/reagent/uranium
+ name ="Uranium"
+ id = "uranium"
+ description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive."
+ taste_description = "metal"
+ reagent_state = SOLID
+ color = "#B8B8C0"
+
/datum/reagent/uranium/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
affect_ingest(M, alien, removed)
@@ -268,6 +268,55 @@
new /obj/effect/decal/cleanable/greenglow(T)
return
+/datum/reagent/hydrogen/deuterium
+ name = "Deuterium"
+ id = "deuterium"
+ description = "A isotope of hydrogen. It has one extra neutron, and shares all chemical characteristics with hydrogen."
+
+/datum/reagent/hydrogen/tritium
+ name = "Tritium"
+ id = "tritium"
+ description = "A radioactive isotope of hydrogen. It has two extra neutrons, and shares all other chemical characteristics with hydrogen."
+
+/datum/reagent/lithium/lithium6
+ name = "Lithium-6"
+ id = "lithium6"
+ description = "An isotope of lithium. It has 3 neutrons, but shares all chemical characteristics with regular lithium."
+
+/datum/reagent/helium/helium3
+ name = "Helium-3"
+ id = "helium3"
+ description = "An isotope of helium. It only has one neutron, but shares all chemical characteristics with regular helium."
+ taste_mult = 0
+ reagent_state = GAS
+ color = "#808080"
+
+/datum/reagent/boron/boron11
+ name = "Boron-11"
+ id = "boron11"
+ description = "An isotope of boron. It has 6 neutrons."
+ taste_description = "metallic" // Apparently noone on the internet knows what boron tastes like. Or at least they won't share
+
+/datum/reagent/supermatter
+ name = "Supermatter"
+ id = "supermatter"
+ description = "The immense power of a supermatter crystal, in liquid form. You're not entirely sure how that's possible, but it's probably best handled with care."
+ taste_description = "taffy" // 0. The supermatter is tasty, tasty taffy.
+
+// Same as if you boop it wrong. It touches you, you die
+/datum/reagent/supermatter/affect_touch(mob/living/carbon/M, alien, removed)
+ . = ..()
+ M.ash()
+
+/datum/reagent/supermatter/affect_ingest(mob/living/carbon/M, alien, removed)
+ . = ..()
+ M.ash()
+
+/datum/reagent/supermatter/affect_blood(mob/living/carbon/M, alien, removed)
+ . = ..()
+ M.ash()
+
+
/datum/reagent/adrenaline
name = "Adrenaline"
id = "adrenaline"
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/reagents/toxins.dm
similarity index 100%
rename from code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
rename to code/modules/reagents/reagents/toxins.dm
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index d6b9c373d5..4b3a9c09ad 100755
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -72,14 +72,9 @@ won't update every console in existence) but it's more of a hassle to do. Also,
/obj/machinery/computer/rdconsole/proc/CallReagentName(var/ID)
var/return_name = ID
- var/datum/reagent/temp_reagent
- for(var/R in (typesof(/datum/reagent) - /datum/reagent))
- temp_reagent = null
- temp_reagent = new R()
- if(temp_reagent.id == ID)
- return_name = temp_reagent.name
- qdel(temp_reagent)
- temp_reagent = null
+ for(var/datum/reagent/R in SSchemistry.chemical_reagents)
+ if(R.id == ID)
+ return_name = R.name
break
return return_name
diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm
index 159bb0f151..f810b9f68b 100644
--- a/code/modules/xenobio/items/extracts.dm
+++ b/code/modules/xenobio/items/extracts.dm
@@ -39,17 +39,17 @@
else
. += "This extract is inert."
-/datum/chemical_reaction/slime
+/decl/chemical_reaction/instant/slime
var/required = null
-/datum/chemical_reaction/slime/can_happen(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, required))
var/obj/item/slime_extract/T = holder.my_atom
if(T.uses > 0)
return ..()
return FALSE
-/datum/chemical_reaction/slime/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/on_reaction(var/datum/reagents/holder)
var/obj/item/slime_extract/T = holder.my_atom
T.uses--
if(T.uses <= 0)
@@ -67,7 +67,7 @@
icon_state = "grey slime extract"
description_info = "This extract will create a new grey baby slime if injected with phoron, or some new monkey cubes if injected with blood."
-/datum/chemical_reaction/slime/grey_new_slime
+/decl/chemical_reaction/instant/slime/grey_new_slime
name = "Slime Spawn"
id = "m_spawn"
result = null
@@ -75,12 +75,12 @@
result_amount = 1
required = /obj/item/slime_extract/grey
-/datum/chemical_reaction/slime/grey_new_slime/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/grey_new_slime/on_reaction(var/datum/reagents/holder)
holder.my_atom.visible_message("Infused with phoron, the core begins to quiver and grow, and soon a new baby slime emerges from it!")
new /mob/living/simple_mob/slime/xenobio(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/grey_monkey
+/decl/chemical_reaction/instant/slime/grey_monkey
name = "Slime Monkey"
id = "m_monkey"
result = null
@@ -88,12 +88,12 @@
result_amount = 1
required = /obj/item/slime_extract/grey
-/datum/chemical_reaction/slime/grey_monkey/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/grey_monkey/on_reaction(var/datum/reagents/holder)
for(var/i = 1 to 4)
new /obj/item/weapon/reagent_containers/food/snacks/monkeycube(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/grey_slimejelly
+/decl/chemical_reaction/instant/slime/grey_slimejelly
name = "Slime Jelly"
id = "m_jelly"
result = "slimejelly"
@@ -123,7 +123,7 @@
color = "#666666"
strength = 20
-/datum/chemical_reaction/slime/metal_metamorphic
+/decl/chemical_reaction/instant/slime/metal_metamorphic
name = "Slime Metal"
id = "m_metal"
required_reagents = list("phoron" = 5)
@@ -132,7 +132,7 @@
required = /obj/item/slime_extract/metal
-/datum/chemical_reaction/metamorphic
+/decl/chemical_reaction/instant/metamorphic
result_amount = REAGENTS_PER_SHEET * 2
@@ -145,42 +145,42 @@
// This is kind of a waste since iron is in the chem dispenser but it would be inconsistent if this wasn't here.
-/datum/chemical_reaction/metamorphic/iron
+/decl/chemical_reaction/instant/metamorphic/iron
name = "Morph into Iron"
id = "morph_iron"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "iron" = REAGENTS_PER_SHEET)
result = "iron"
-/datum/chemical_reaction/metamorphic/silver
+/decl/chemical_reaction/instant/metamorphic/silver
name = "Morph into Silver"
id = "morph_silver"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "silver" = REAGENTS_PER_SHEET)
result = "silver"
-/datum/chemical_reaction/metamorphic/gold
+/decl/chemical_reaction/instant/metamorphic/gold
name = "Morph into Gold"
id = "morph_gold"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "gold" = REAGENTS_PER_SHEET)
result = "gold"
-/datum/chemical_reaction/metamorphic/platinum
+/decl/chemical_reaction/instant/metamorphic/platinum
name = "Morph into Platinum"
id = "morph_platinum"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "platinum" = REAGENTS_PER_SHEET)
result = "platinum"
-/datum/chemical_reaction/metamorphic/uranium
+/decl/chemical_reaction/instant/metamorphic/uranium
name = "Morph into Uranium"
id = "morph_uranium"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "uranium" = REAGENTS_PER_SHEET)
result = "uranium"
-/datum/chemical_reaction/metamorphic/phoron
+/decl/chemical_reaction/instant/metamorphic/phoron
name = "Morph into Phoron"
id = "morph_phoron"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "phoron" = REAGENTS_PER_SHEET)
@@ -188,7 +188,7 @@
// Creates 'alloys' which can be finalized with frost oil.
-/datum/chemical_reaction/slime/metal_binding
+/decl/chemical_reaction/instant/slime/metal_binding
name = "Slime Binding"
id = "m_binding"
required_reagents = list("water" = 5)
@@ -215,7 +215,7 @@
prefill = list("binding" = 60)
-/datum/chemical_reaction/binding
+/decl/chemical_reaction/instant/binding
name = "Bind into Steel"
id = "bind_steel"
result = "steel"
@@ -231,7 +231,7 @@
color = "#888888"
-/datum/chemical_reaction/binding/plasteel // Two parts 'steel', one part platnium matches the smelter alloy recipe.
+/decl/chemical_reaction/instant/binding/plasteel // Two parts 'steel', one part platnium matches the smelter alloy recipe.
name = "Bind into Plasteel"
id = "bind_plasteel"
required_reagents = list("binding" = REAGENTS_PER_SHEET, "steel" = REAGENTS_PER_SHEET * 2, "platinum" = REAGENTS_PER_SHEET)
@@ -258,7 +258,7 @@
The extract can also create a slime stability agent when injected with blood, which reduces the odds of newly created slimes mutating into \
a different color when a slime reproduces."
-/datum/chemical_reaction/slime/blue_frostoil
+/decl/chemical_reaction/instant/slime/blue_frostoil
name = "Slime Frost Oil"
id = "m_frostoil"
result = "frostoil"
@@ -267,14 +267,14 @@
required = /obj/item/slime_extract/blue
-/datum/chemical_reaction/slime/blue_stability
+/decl/chemical_reaction/instant/slime/blue_stability
name = "Slime Stability"
id = "m_stability"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/blue
-/datum/chemical_reaction/slime/blue_stability/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/blue_stability/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/stabilizer(get_turf(holder.my_atom))
..()
@@ -291,14 +291,14 @@
can extract from a slime specimen."
-/datum/chemical_reaction/slime/purple_steroid
+/decl/chemical_reaction/instant/slime/purple_steroid
name = "Slime Steroid"
id = "m_steroid"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/purple
-/datum/chemical_reaction/slime/purple_steroid/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/purple_steroid/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/steroid(get_turf(holder.my_atom))
..()
@@ -313,14 +313,14 @@
icon_state = "orange slime extract"
description_info = "This extract creates a fire when injected with phoron, after a five second delay."
-/datum/chemical_reaction/slime/orange_fire
+/decl/chemical_reaction/instant/slime/orange_fire
name = "Slime Fire"
id = "m_fire"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/orange
-/datum/chemical_reaction/slime/orange_fire/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/orange_fire/on_reaction(var/datum/reagents/holder)
log_and_message_admins("Orange extract reaction (fire) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
holder.my_atom.visible_message("\The [src] begins to vibrate violently!")
playsound(holder.my_atom, 'sound/effects/phasein.ogg', 75, 1)
@@ -350,14 +350,14 @@
description_info = "This extract will create a special 10k capacity power cell that self recharges slowly over time, when injected with phoron. \
When injected with blood, it will create a glob of slime which glows brightly. If injected with water, it will emit a strong EMP, after a five second delay."
-/datum/chemical_reaction/slime/yellow_emp
+/decl/chemical_reaction/instant/slime/yellow_emp
name = "Slime EMP"
id = "m_emp"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/yellow
-/datum/chemical_reaction/slime/yellow_emp/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/yellow_emp/on_reaction(var/datum/reagents/holder)
log_and_message_admins("Yellow extract reaction (emp) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
holder.my_atom.visible_message("\The [src] begins to vibrate violently!")
playsound(holder.my_atom, 'sound/effects/phasein.ogg', 75, 1)
@@ -368,26 +368,26 @@
..()
-/datum/chemical_reaction/slime/yellow_battery
+/decl/chemical_reaction/instant/slime/yellow_battery
name = "Slime Cell"
id = "m_cell"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/yellow
-/datum/chemical_reaction/slime/yellow_battery/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/yellow_battery/on_reaction(var/datum/reagents/holder)
new /obj/item/weapon/cell/slime(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/yellow_flashlight
+/decl/chemical_reaction/instant/slime/yellow_flashlight
name = "Slime Flashlight"
id = "m_flashlight"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/yellow
-/datum/chemical_reaction/slime/yellow_flashlight/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/yellow_flashlight/on_reaction(var/datum/reagents/holder)
new /obj/item/device/flashlight/slime(get_turf(holder.my_atom))
..()
@@ -401,7 +401,7 @@
description_info = "This extract will create 5u liquid gold when injected with phoron."
-/datum/chemical_reaction/slime/gold_gold
+/decl/chemical_reaction/instant/slime/gold_gold
name = "Slime Gold"
id = "m_gold"
result = "gold"
@@ -420,7 +420,7 @@
description_info = "This extract will create 5u liquid silver when injected with phoron."
-/datum/chemical_reaction/slime/silver_silver
+/decl/chemical_reaction/instant/slime/silver_silver
name = "Slime Silver"
id = "m_silver"
result = "silver"
@@ -440,7 +440,7 @@
description_info = "This extract will create 40u liquid phoron when injected with water."
-/datum/chemical_reaction/slime/dark_purple_phoron
+/decl/chemical_reaction/instant/slime/dark_purple_phoron
name = "Slime Phoron"
id = "m_phoron_harvest"
result = "phoron"
@@ -462,7 +462,7 @@
cold-resistant armor like winter coats can protect from this. Note that the user is not immune to the extract's effects."
-/datum/chemical_reaction/slime/dark_blue_cold_snap
+/decl/chemical_reaction/instant/slime/dark_blue_cold_snap
name = "Slime Cold Snap"
id = "m_cold_snap"
required_reagents = list("phoron" = 5)
@@ -470,7 +470,7 @@
required = /obj/item/slime_extract/dark_blue
// This iterates over a ZAS zone's contents, so that things seperated in other zones aren't subjected to the temperature drop.
-/datum/chemical_reaction/slime/dark_blue_cold_snap/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/dark_blue_cold_snap/on_reaction(var/datum/reagents/holder)
var/turf/simulated/T = get_turf(holder.my_atom)
if(!T) // Nullspace lacks zones.
return
@@ -544,14 +544,14 @@
out of control."
-/datum/chemical_reaction/slime/red_enrage
+/decl/chemical_reaction/instant/slime/red_enrage
name = "Slime Enrage"
id = "m_enrage"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/red
-/datum/chemical_reaction/slime/red_enrage/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/red_enrage/on_reaction(var/datum/reagents/holder)
for(var/mob/living/simple_mob/slime/S in view(get_turf(holder.my_atom)))
if(S.stat)
continue
@@ -580,14 +580,14 @@
-/datum/chemical_reaction/slime/red_mutation
+/decl/chemical_reaction/instant/slime/red_mutation
name = "Slime Mutation"
id = "m_mutation"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/red
-/datum/chemical_reaction/slime/red_mutation/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/red_mutation/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/mutator(get_turf(holder.my_atom))
..()
@@ -600,7 +600,7 @@
icon_state = "green slime extract"
description_info = "This extract will create 5u of liquid uranium when injected with phoron."
-/datum/chemical_reaction/slime/green_uranium
+/decl/chemical_reaction/instant/slime/green_uranium
name = "Slime Uranium"
id = "m_uranium"
result = "uranium"
@@ -620,7 +620,7 @@
with phoron. When injected with water, it will create an organ-mending agent. The slime medications have a very low threshold for overdosage, however."
-/datum/chemical_reaction/slime/pink_clotting
+/decl/chemical_reaction/instant/slime/pink_clotting
name = "Slime Clotting Med"
id = "m_clotting"
result = "slime_bleed_fixer"
@@ -629,7 +629,7 @@
required = /obj/item/slime_extract/pink
-/datum/chemical_reaction/slime/pink_bone_fix
+/decl/chemical_reaction/instant/slime/pink_bone_fix
name = "Slime Bone Med"
id = "m_bone_fixer"
result = "slime_bone_fixer"
@@ -638,7 +638,7 @@
required = /obj/item/slime_extract/pink
-/datum/chemical_reaction/slime/pink_organ_fix
+/decl/chemical_reaction/instant/slime/pink_organ_fix
name = "Slime Organ Med"
id = "m_organ_fixer"
result = "slime_organ_fixer"
@@ -680,7 +680,7 @@
increase the power of the explosion instead of allowing for multiple explosions."
-/datum/chemical_reaction/slime/oil_griff
+/decl/chemical_reaction/instant/slime/oil_griff
name = "Slime Explosion"
id = "m_boom"
required_reagents = list("blood" = 5)
@@ -688,7 +688,7 @@
required = /obj/item/slime_extract/oil
-/datum/chemical_reaction/slime/oil_griff/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/oil_griff/on_reaction(var/datum/reagents/holder)
..()
var/obj/item/slime_extract/E = holder.my_atom
var/power = 1
@@ -718,26 +718,26 @@
short ranged, random teleporting. When injected with phoron, it creates one 'greater' slime crystal, which allows for a one time precise teleport to \
a specific area."
-/datum/chemical_reaction/slime/bluespace_lesser
+/decl/chemical_reaction/instant/slime/bluespace_lesser
name = "Slime Lesser Tele"
id = "m_tele_lesser"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/bluespace
-/datum/chemical_reaction/slime/bluespace_lesser/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/bluespace_lesser/on_reaction(var/datum/reagents/holder)
for(var/i = 1 to 5)
new /obj/item/slime_crystal(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/bluespace_greater
+/decl/chemical_reaction/instant/slime/bluespace_greater
name = "Slime Greater Tele"
id = "m_tele_lesser"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/bluespace
-/datum/chemical_reaction/slime/bluespace_greater/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/bluespace_greater/on_reaction(var/datum/reagents/holder)
new /obj/item/weapon/disposable_teleporter/slime(get_turf(holder.my_atom))
..()
@@ -752,14 +752,14 @@
'charges' before it goes inert."
-/datum/chemical_reaction/slime/cerulean_enhancer
+/decl/chemical_reaction/instant/slime/cerulean_enhancer
name = "Slime Enhancer"
id = "m_enhancer"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/cerulean
-/datum/chemical_reaction/slime/cerulean_enhancer/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/cerulean_enhancer/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/enhancer(get_turf(holder.my_atom))
..()
@@ -774,26 +774,26 @@
injected with water, it will create a very delicious and filling product."
-/datum/chemical_reaction/slime/amber_slimefood
+/decl/chemical_reaction/instant/slime/amber_slimefood
name = "Slime Feeding"
id = "m_slime_food"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/amber
-/datum/chemical_reaction/slime/amber_slimefood/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/amber_slimefood/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/feeding(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/amber_peoplefood
+/decl/chemical_reaction/instant/slime/amber_peoplefood
name = "Slime Food"
id = "m_people_food"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/amber
-/datum/chemical_reaction/slime/amber_peoplefood/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/amber_peoplefood/on_reaction(var/datum/reagents/holder)
new /obj/item/weapon/reagent_containers/food/snacks/slime(get_turf(holder.my_atom))
..()
@@ -809,14 +809,14 @@
description_info = "This extract will create one 'slime cube' when injected with phoron. The slime cube is needed to create a Promethean."
-/datum/chemical_reaction/slime/sapphire_promethean
+/decl/chemical_reaction/instant/slime/sapphire_promethean
name = "Slime Promethean"
id = "m_promethean"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/sapphire
-/datum/chemical_reaction/slime/sapphire_promethean/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/sapphire_promethean/on_reaction(var/datum/reagents/holder)
new /obj/item/slime_cube(get_turf(holder.my_atom))
..()
@@ -830,14 +830,14 @@
description_info = "This extract will cause all entities close to the extract to become stronger for ten minutes, when injected with phoron. \
When injected with blood, makes a slime loyalty agent which will make the slime fight other dangerous entities but not station crew."
-/datum/chemical_reaction/slime/ruby_swole
+/decl/chemical_reaction/instant/slime/ruby_swole
name = "Slime Strength"
id = "m_strength"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/ruby
-/datum/chemical_reaction/slime/ruby_swole/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/ruby_swole/on_reaction(var/datum/reagents/holder)
for(var/mob/living/L in range(1, holder.my_atom))
L.add_modifier(/datum/modifier/slime_strength, 10 MINUTES, src)
..()
@@ -858,14 +858,14 @@
incoming_damage_percent = 0.75
-/datum/chemical_reaction/slime/ruby_loyalty
+/decl/chemical_reaction/instant/slime/ruby_loyalty
name = "Slime Loyalty"
id = "m_strength"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/ruby
-/datum/chemical_reaction/slime/ruby_loyalty/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/ruby_loyalty/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/loyalty(get_turf(holder.my_atom))
..()
@@ -879,14 +879,14 @@
icon_state = "emerald slime extract"
description_info = "This extract will cause all entities close to the extract to become more agile for ten minutes, when injected with phoron."
-/datum/chemical_reaction/slime/emerald_fast
+/decl/chemical_reaction/instant/slime/emerald_fast
name = "Slime Agility"
id = "m_agility"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/emerald
-/datum/chemical_reaction/slime/emerald_fast/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/emerald_fast/on_reaction(var/datum/reagents/holder)
for(var/mob/living/L in range(1, holder.my_atom))
L.add_modifier(/datum/modifier/slime_agility, 10 MINUTES, src)
..()
@@ -916,26 +916,26 @@
When injected with phoron, it instead creates a slime friendship agent, which makes the slime consider the user their ally. The agent \
might be useful on other specimens as well."
-/datum/chemical_reaction/slime/light_pink_docility
+/decl/chemical_reaction/instant/slime/light_pink_docility
name = "Slime Docility"
id = "m_docile"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/light_pink
-/datum/chemical_reaction/slime/light_pink_docility/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/light_pink_docility/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/docility(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/light_pink_friendship
+/decl/chemical_reaction/instant/slime/light_pink_friendship
name = "Slime Friendship"
id = "m_friendship"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/light_pink
-/datum/chemical_reaction/slime/light_pink_friendship/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/light_pink_friendship/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/friendship(get_turf(holder.my_atom))
..()
@@ -952,7 +952,7 @@
which makes slimes stop attacking other slime colors."
-/datum/chemical_reaction/slime/rainbow_random_slime
+/decl/chemical_reaction/instant/slime/rainbow_random_slime
name = "Slime Random Slime"
id = "m_rng_slime"
required_reagents = list("phoron" = 5)
@@ -960,7 +960,7 @@
required = /obj/item/slime_extract/rainbow
-/datum/chemical_reaction/slime/rainbow_random_slime/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/rainbow_random_slime/on_reaction(var/datum/reagents/holder)
var/mob/living/simple_mob/slime/xenobio/S
var/list/slime_types = typesof(/mob/living/simple_mob/slime/xenobio)
@@ -976,14 +976,14 @@
new S(get_turf(holder.my_atom))
..()
-/datum/chemical_reaction/slime/rainbow_unity
+/decl/chemical_reaction/instant/slime/rainbow_unity
name = "Slime Unity"
id = "m_unity"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/rainbow
-/datum/chemical_reaction/slime/rainbow_unity/on_reaction(var/datum/reagents/holder)
+/decl/chemical_reaction/instant/slime/rainbow_unity/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/unity(get_turf(holder.my_atom))
..()
diff --git a/polaris.dme b/polaris.dme
index 5a15acac7a..f02eb408fd 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -214,6 +214,7 @@
#include "code\controllers\subsystems\atoms.dm"
#include "code\controllers\subsystems\character_setup.dm"
#include "code\controllers\subsystems\chat.dm"
+#include "code\controllers\subsystems\chemistry.dm"
#include "code\controllers\subsystems\circuits.dm"
#include "code\controllers\subsystems\dcs.dm"
#include "code\controllers\subsystems\events.dm"
@@ -246,7 +247,6 @@
#include "code\controllers\subsystems\timer.dm"
#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\xenoarch.dm"
-#include "code\controllers\subsystems\processing\chemistry.dm"
#include "code\controllers\subsystems\processing\fastprocess.dm"
#include "code\controllers\subsystems\processing\obj.dm"
#include "code\controllers\subsystems\processing\processing.dm"
@@ -2710,7 +2710,6 @@
#include "code\modules\power\fusion\fusion_circuits.dm"
#include "code\modules\power\fusion\fusion_particle_catcher.dm"
#include "code\modules\power\fusion\fusion_reactions.dm"
-#include "code\modules\power\fusion\fusion_reagents.dm"
#include "code\modules\power\fusion\magpower.dm"
#include "code\modules\power\fusion\core\_core.dm"
#include "code\modules\power\fusion\core\core_control.dm"
@@ -2832,36 +2831,33 @@
#include "code\modules\random_map\noise\ore.dm"
#include "code\modules\random_map\noise\tundra.dm"
#include "code\modules\reagents\Chemistry-Colours.dm"
-#include "code\modules\reagents\Chemistry-Holder.dm"
#include "code\modules\reagents\Chemistry-Logging.dm"
-#include "code\modules\reagents\Chemistry-Machinery.dm"
#include "code\modules\reagents\Chemistry-Metabolism.dm"
-#include "code\modules\reagents\Chemistry-Readme.dm"
-#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\reagent_containers.dm"
-#include "code\modules\reagents\reagent_dispenser.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Core.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Dispenser.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Food-Drinks.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Medicine.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Modifiers.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Other.dm"
-#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Toxins.dm"
-#include "code\modules\reagents\dispenser\_defines.dm"
-#include "code\modules\reagents\dispenser\cartridge.dm"
-#include "code\modules\reagents\dispenser\cartridge_presets.dm"
-#include "code\modules\reagents\dispenser\cartridge_spawn.dm"
-#include "code\modules\reagents\dispenser\dispenser2.dm"
-#include "code\modules\reagents\dispenser\dispenser2_energy.dm"
-#include "code\modules\reagents\dispenser\dispenser_presets.dm"
-#include "code\modules\reagents\dispenser\supply.dm"
-#include "code\modules\reagents\distilling\Distilling-Recipes.dm"
-#include "code\modules\reagents\distilling\distilling.dm"
+#include "code\modules\reagents\holder\holder.dm"
+#include "code\modules\reagents\holder\distilling.dm"
#include "code\modules\reagents\hoses\connector.dm"
#include "code\modules\reagents\hoses\hose.dm"
#include "code\modules\reagents\hoses\hose_connector.dm"
+#include "code\modules\reagents\machinery\chem_master.dm"
+#include "code\modules\reagents\machinery\chemalyzer.dm"
+#include "code\modules\reagents\machinery\distillery.dm"
+#include "code\modules\reagents\machinery\grinder.dm"
+#include "code\modules\reagents\machinery\dispenser\_defines.dm"
+#include "code\modules\reagents\machinery\dispenser\cartridge.dm"
+#include "code\modules\reagents\machinery\dispenser\cartridge_presets.dm"
+#include "code\modules\reagents\machinery\dispenser\cartridge_spawn.dm"
+#include "code\modules\reagents\machinery\dispenser\dispenser2.dm"
+#include "code\modules\reagents\machinery\dispenser\dispenser2_energy.dm"
+#include "code\modules\reagents\machinery\dispenser\dispenser_presets.dm"
+#include "code\modules\reagents\machinery\dispenser\reagent_tank.dm"
+#include "code\modules\reagents\machinery\dispenser\supply.dm"
+#include "code\modules\reagents\reactions\_reactions.dm"
+#include "code\modules\reagents\reactions\distilling\distilling.dm"
+#include "code\modules\reagents\reactions\fusion\fusion.dm"
+#include "code\modules\reagents\reactions\instant\drinks.dm"
+#include "code\modules\reagents\reactions\instant\food.dm"
+#include "code\modules\reagents\reactions\instant\instant.dm"
+#include "code\modules\reagents\reagent_containers\_reagent_containers.dm"
#include "code\modules\reagents\reagent_containers\blood_pack.dm"
#include "code\modules\reagents\reagent_containers\borghypo.dm"
#include "code\modules\reagents\reagent_containers\dropper.dm"
@@ -2872,6 +2868,15 @@
#include "code\modules\reagents\reagent_containers\spray.dm"
#include "code\modules\reagents\reagent_containers\syringes.dm"
#include "code\modules\reagents\reagent_containers\unidentified_hypospray.dm"
+#include "code\modules\reagents\reagents\_helpers.dm"
+#include "code\modules\reagents\reagents\_reagents.dm"
+#include "code\modules\reagents\reagents\core.dm"
+#include "code\modules\reagents\reagents\dispenser.dm"
+#include "code\modules\reagents\reagents\food_drinks.dm"
+#include "code\modules\reagents\reagents\medicine.dm"
+#include "code\modules\reagents\reagents\modifiers.dm"
+#include "code\modules\reagents\reagents\other.dm"
+#include "code\modules\reagents\reagents\toxins.dm"
#include "code\modules\recycling\conveyor2.dm"
#include "code\modules\recycling\disposal-construction.dm"
#include "code\modules\recycling\disposal.dm"