[MIRROR] Oops, I refactored Chemistry!

This commit is contained in:
Chompstation Bot
2021-04-24 02:25:47 +00:00
committed by Darlantan
parent 1f33d5696f
commit ca996648dd
62 changed files with 9109 additions and 3845 deletions

View File

@@ -50,3 +50,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

View File

@@ -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

View File

@@ -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

View File

@@ -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("<span class='notice'>[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!</span>")
@@ -138,14 +138,14 @@
else
chunk.visible_message("<span class='warning'>[chunk] shifts strangely, but falls still.</span>")
/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("<span class='notice'>[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!</span>")

View File

@@ -13,7 +13,7 @@
//---Beverages---//
//***************//
/datum/reagent/var/price_tag = null
/datum/reagent/var/price_tag = 0
// Juices, soda and similar //

View File

@@ -274,8 +274,7 @@
/datum/event/supply_demand/proc/choose_chemistry_items(var/differentTypes)
// Checking if they show up in health analyzer is good huristic for it being a drug
var/list/medicineReagents = list()
for(var/path in typesof(/datum/chemical_reaction) - /datum/chemical_reaction)
var/datum/chemical_reaction/CR = path // Stupid casting required for reading
for(var/decl/chemical_reaction/instant/CR in SSchemistry.chemical_reactions)
var/datum/reagent/R = SSchemistry.chemical_reagents[initial(CR.result)]
if(R && R.scannable)
medicineReagents += R
@@ -288,8 +287,7 @@
/datum/event/supply_demand/proc/choose_bar_items(var/differentTypes)
var/list/drinkReagents = list()
for(var/path in typesof(/datum/chemical_reaction) - /datum/chemical_reaction)
var/datum/chemical_reaction/CR = path // Stupid casting required for reading
for(var/decl/chemical_reaction/instant/drinks/CR in SSchemistry.chemical_reactions)
var/datum/reagent/R = SSchemistry.chemical_reagents[initial(CR.result)]
if(istype(R, /datum/reagent/drink) || istype(R, /datum/reagent/ethanol))
drinkReagents += R

View File

@@ -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.

View File

@@ -276,19 +276,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("<span class='notice'>[brain] bubbles, surrounding itself with a rapidly expanding mass of slime!</span>")

View File

@@ -1,3 +1,4 @@
#define FUSION_ROD_SHEET_AMT 15
/obj/machinery/fusion_fuel_compressor
var/blitzprogress = 0 //CHOMPEdit
name = "fuel compressor"
@@ -51,6 +52,7 @@
if(istype(thing, /obj/item/stack/material))
var/obj/item/stack/material/M = thing
var/datum/material/mat = M.get_material()
<<<<<<< HEAD
if(!blitzprogress)
if(!mat.is_fusion_fuel)
to_chat(user, "<span class='warning'>It would be pointless to make a fuel rod out of [mat.use_name].</span>")
@@ -82,10 +84,34 @@
else
to_chat(user, "<span class='warning'>A blitz rod is currently in progress! Either add 25 phoron sheets to complete it, or eject the supermatter sheet!</span>")
return
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
if(!mat.is_fusion_fuel)
to_chat(user, "<span class='warning'>It would be pointless to make a fuel rod out of [mat.use_name].</span>")
return
if(M.get_amount() < 15)
to_chat(user, "<span class='warning'>You need at least 25 [mat.sheet_plural_name] to make a fuel rod.</span>")
return
var/obj/item/weapon/fuel_assembly/F = new(get_turf(src), mat.name)
visible_message("<span class='notice'>\The [src] compresses the [mat.use_name] into a new fuel assembly.</span>")
M.use(15)
user.put_in_hands(F)
=======
if(!mat.is_fusion_fuel)
to_chat(user, "<span class='warning'>It would be pointless to make a fuel rod out of [mat.use_name].</span>")
return
if(M.get_amount() < FUSION_ROD_SHEET_AMT)
to_chat(user, "<span class='warning'>You need at least 25 [mat.sheet_plural_name] to make a fuel rod.</span>")
return
var/obj/item/weapon/fuel_assembly/F = new(get_turf(src), mat.name)
visible_message("<span class='notice'>\The [src] compresses the [mat.use_name] into a new fuel assembly.</span>")
M.use(FUSION_ROD_SHEET_AMT)
user.put_in_hands(F)
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
else if(do_special_fuel_compression(thing, user))
return
<<<<<<< HEAD
return ..()
/obj/machinery/fusion_fuel_compressor/verb/eject_sheet()
@@ -98,3 +124,10 @@
verbs -= /obj/machinery/fusion_fuel_compressor/verb/eject_sheet
blitzprogress = 0
//CHOMPEdit End
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
return ..()
=======
return ..()
#undef FUSION_ROD_SHEET_AMT
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013

View File

@@ -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)

View File

@@ -1,519 +0,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 = 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)
current.on_remove(my_atom) //YW Edit: Calls on_remove before the last of the thing is done, used in phorochemistry
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)
qdel(src)

View File

@@ -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

View File

@@ -1,250 +0,0 @@
/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
. = ..()
// Called when reagents are removed from a container, most likely after metabolizing in a mob
/datum/reagent/proc/on_remove(var/atom/A)
return
// Called when a mob dies
/datum/reagent/proc/on_mob_death(var/mob/M)
return
//on transfer to new container, return 1 to allow it to continue
/datum/reagent/proc/on_transfer(var/volume)
return 1
/* 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)

View File

@@ -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()

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,3 @@
#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."
@@ -514,349 +496,3 @@
/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))
. += "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>"
return
if(inuse)
. += "<span class='warning'>\The [src] is operating.</span>"
return
if(beaker || length(holdingitems))
. += "<span class='notice'>\The [src] contains:</span>"
if(beaker)
. += "<span class='notice'>- \A [beaker].</span>"
for(var/i in holdingitems)
var/obj/item/O = i
. += "<span class='notice'>- \A [O.name].</span>"
if(!(stat & (NOPOWER|BROKEN)))
. += "<span class='notice'>The status display reads:</span>\n"
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
. += "<span class='notice'>- [R.volume] units of [R.name].</span>"
/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
//vorestation edit start - for solargrubs
if (istype(O, /obj/item/device/multitool))
return ..()
//vorestation edit end
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, "<br>") // 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 <b>[R.name]</b>.<br>[R.description]<br>"))
// 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.<br>"))
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

View File

@@ -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, "<br>") // 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 <b>[R.name]</b>.<br>[R.description]<br>"))
// 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.<br>"))
to_chat(user, span("notice", "Scanning of \the [I] complete."))
analyzing = FALSE
update_icon()
return

File diff suppressed because it is too large Load Diff

View File

@@ -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
. += "<span class='notice'>\The [src]'s input beaker is empty!</span>"
if(Reservoir.reagents.reagent_list.len)
. += "<span class='notice'>\The [src]'s internal buffer holds [Reservoir.reagents.total_volume] units of liquid.</span>"
if(reagents.reagent_list.len)
. += "<span class='notice'>\The [src]'s internal buffer holds [reagents.total_volume] units of liquid.</span>"
else
. += "<span class='notice'>\The [src]'s internal buffer is empty!</span>"
@@ -164,7 +147,7 @@
to_chat(user, "<span class='notice'>You press \the [src]'s chamber agitator button.</span>")
if(on)
visible_message("<span class='notice'>\The [src] rattles to life.</span>")
Reservoir.reagents.handle_reactions()
reagents.handle_reactions()
else
spawn(1 SECOND)
to_chat(user, "<span class='notice'>Nothing happens..</span>")
@@ -341,12 +324,12 @@
visible_message("<span class='notice'>\The [src]'s motors wind down.</span>")
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()

View File

@@ -0,0 +1,268 @@
/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))
. += "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>"
return
if(inuse)
. += "<span class='warning'>\The [src] is operating.</span>"
return
if(beaker || length(holdingitems))
. += "<span class='notice'>\The [src] contains:</span>"
if(beaker)
. += "<span class='notice'>- \A [beaker].</span>"
for(var/i in holdingitems)
var/obj/item/O = i
. += "<span class='notice'>- \A [O.name].</span>"
if(!(stat & (NOPOWER|BROKEN)))
. += "<span class='notice'>The status display reads:</span>\n"
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
. += "<span class='notice'>- [R.volume] units of [R.name].</span>"
/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
//VOREStation edit start - for solargrubs
if (istype(O, /obj/item/device/multitool))
return ..()
//VOREStation edit end
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

View File

@@ -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("<span class='notice'>[bicon(container)] [mix_message]</span>", 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

View File

@@ -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
//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
// 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 0
return FALSE
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"

View File

@@ -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"*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
///////////////////////////////////////////////////////////////////////////////////
/// Special drinks
/decl/chemical_reaction/instant/drinks/grubshake
name = "Grub protein drink"
id = "grubshake"
result = "grubshake"
required_reagents = list("shockchem" = 5, "water" = 25)
result_amount = 30
/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/monstertamer
name = "Monster Tamer"
id = "monstertamer"
result = "monstertamer"
required_reagents = list("whiskey" = 1, "protein" = 1)
result_amount = 2
/decl/chemical_reaction/instant/drinks/bigbeer
name = "Giant Beer"
id = "bigbeer"
result = "bigbeer"
required_reagents = list("syndicatebomb" = 1, "manlydorf" = 1, "grog" =1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/sweettea
name = "Sweetened Tea"
id = "sweettea"
result = "sweettea"
required_reagents = list("icetea" = 2, "sugar" = 1,)
result_amount = 3
/decl/chemical_reaction/instant/drinks/unsweettea
name = "Unsweetened Tea"
id = "unsweettea"
result = "unsweettea"
required_reagents = list("sweettea" = 3, "phoron" = 1)
result_amount = 2
/decl/chemical_reaction/instant/drinks/galacticpanic
name = "Galactic Panic Attack"
id = "galacticpanic"
result = "galacticpanic"
required_reagents = list("gargleblaster" = 1, "singulo" = 1, "phoronspecial" =1, "neurotoxin" = 1, "atomicbomb" = 1, "hippiesdelight" = 1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/bulldog
name = "Space Bulldog"
id = "bulldog"
result = "bulldog"
required_reagents = list("whiterussian" = 4, "cola" =1)
result_amount = 4
/decl/chemical_reaction/instant/drinks/sbagliato
name = "Negroni Sbagliato"
id = "sbagliato"
result = "sbagliato"
required_reagents = list("wine" = 1, "vermouth" = 1, "sodawater" =1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/italiancrisis
name = "Italian Crisis"
id = "italiancrisis"
result = "italiancrisis"
required_reagents = list("bulldog" = 1, "sbagliato" = 1)
result_amount = 2
/decl/chemical_reaction/instant/drinks/sugarrush
name = "Sweet Rush"
id = "sugarrush"
result = "sugarrush"
required_reagents = list("sugar" = 1, "sodawater" = 1, "vodka" =1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/lotus
name = "Lotus"
id = "lotus"
result = "lotus"
required_reagents = list("sbagliato" = 1, "sugarrush" = 1)
result_amount = 2
/decl/chemical_reaction/instant/drinks/shroomjuice
name = "Dumb Shroom Juice"
id = "shroomjuice"
result = "shroomjuice"
required_reagents = list("psilocybin" = 1, "applejuice" = 1, "limejuice" =1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/russianroulette
name = "Russian Roulette"
id = "russianroulette"
result = "russianroulette"
required_reagents = list("whiterussian" = 5, "iron" = 1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/lovemaker
name = "The Love Maker"
id = "lovemaker"
result = "lovemaker"
required_reagents = list("honey" = 1, "sexonthebeach" = 5)
result_amount = 6
/decl/chemical_reaction/instant/drinks/honeyshot
name = "Honey Shot"
id = "honeyshot"
result = "honeyshot"
required_reagents = list("honey" = 1, "vodka" = 1, "grenadine" =1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/appletini
name = "Appletini"
id = "appletini"
result = "appletini"
required_reagents = list("applejuice" = 2, "vodka" = 1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/glowingappletini
name = "Glowing Appletini"
id = "glowingappletini"
result = "glowingappletini"
required_reagents = list("appletini" = 5, "uranium" = 1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/scsatw
name = "Slow Comfortable Screw Against the Wall"
id = "scsatw"
result = "scsatw"
required_reagents = list("screwdrivercocktail" = 3, "rum" =1, "whiskey" =1, "gin" =1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/choccymilk
name = "Choccy Milk"
id = "choccymilk"
result = "choccymilk"
required_reagents = list("milk" = 3, "coco" = 1)
result_amount = 4
/decl/chemical_reaction/instant/drinks/redspaceflush
name = "Redspace Flush"
id = "redspaceflush"
result = "redspaceflush"
required_reagents = list("rum" = 2, "whiskey" = 2, "blood" =1, "phoron" =1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/graveyard
name = "Graveyard"
id = "graveyard"
result = "graveyard"
required_reagents = list("cola" = 1, "spacemountainwind" = 1, "dr_gibb" =1, "space_up" = 1)
result_amount = 4
/decl/chemical_reaction/instant/drinks/hairoftherat
name = "Hair of the Rat"
id = "hairoftherat"
result = "hairoftherat"
required_reagents = list("monstertamer" = 2, "nutriment" = 1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/pink_moo
name = "Pink Moo"
id = "pinkmoo"
result = "pinkmoo"
required_reagents = list("blackrussian" = 2, "berryshake" = 1)
result_amount = 3
/decl/chemical_reaction/instant/drinks/originalsin
name = "Original Sin"
id = "originalsin"
result = "originalsin"
required_reagents = list("holywine" = 1)
catalysts = list("applejuice" = 1)
result_amount = 1
/decl/chemical_reaction/instant/drinks/windgarita
name = "WND-Garita"
id = "windgarita"
result = "windgarita"
required_reagents = list("margarita" = 3, "spacemountainwind" = 2, "melonliquor" = 1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/newyorksour
name = "New York Sour"
id = "newyorksour"
result = "newyorksour"
required_reagents = list("whiskeysour" = 3, "wine" = 2, "egg" = 1)
result_amount = 6
/decl/chemical_reaction/instant/drinks/mudslide
name = "Mudslide"
id = "mudslide"
result = "mudslide"
required_reagents = list("blackrussian" = 1, "irishcream" = 1)
result_amount = 2

View File

@@ -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

View File

@@ -0,0 +1,2 @@
/decl/chemical_reaction/instant/food/syntiflesh
required_reagents = list("blood" = 5, "clonexadone" = 1)

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////////
/// Micro/Macro chemicals
/datum/chemical_reaction/sizeoxadone
/decl/chemical_reaction/instant/sizeoxadone
name = "sizeoxadone"
id = "sizeoxadone"
result = "sizeoxadone"
@@ -9,7 +9,7 @@
catalysts = list("phoron" = 5)
result_amount = 5
/datum/chemical_reaction/macrocillin
/decl/chemical_reaction/instant/macrocillin
name = "Macrocillin"
id = "macrocillin"
result = "macrocillin"
@@ -17,7 +17,7 @@
required_reagents = list("sizeoxadone" = 20, "diethylamine" = 20)
result_amount = 1
/datum/chemical_reaction/microcillin
/decl/chemical_reaction/instant/microcillin
name = "Microcillin"
id = "microcillin"
result = "microcillin"
@@ -25,7 +25,7 @@
required_reagents = list("sizeoxadone" = 20, "sodiumchloride" = 20)
result_amount = 1
/datum/chemical_reaction/normalcillin
/decl/chemical_reaction/instant/normalcillin
name = "Normalcillin"
id = "normalcillin"
result = "normalcillin"
@@ -33,13 +33,13 @@
required_reagents = list("sizeoxadone" = 20, "leporazine" = 20)
result_amount = 1
/datum/chemical_reaction/dontcrossthebeams
/decl/chemical_reaction/instant/dontcrossthebeams
name = "Don't Cross The Beams"
id = "dontcrossthebeams"
result = null
required_reagents = list("microcillin" = 1, "macrocillin" = 1)
/datum/chemical_reaction/dontcrossthebeams/on_reaction(var/datum/reagents/holder, var/created_volume)
/decl/chemical_reaction/instant/dontcrossthebeams/on_reaction(var/datum/reagents/holder, var/created_volume)
var/location = get_turf(holder.my_atom)
playsound(location, 'sound/weapons/gauss_shoot.ogg', 50, 1)
var/datum/effect/effect/system/grav_pull/s = new /datum/effect/effect/system/grav_pull
@@ -50,13 +50,13 @@
///////////////////////////////////////////////////////////////////////////////////
/// Miscellaneous Reactions
/datum/chemical_reaction/xenolazarus
/decl/chemical_reaction/instant/xenolazarus
name = "Discount Lazarus"
id = "discountlazarus"
result = null
required_reagents = list("monstertamer" = 5, "clonexadone" = 5)
/datum/chemical_reaction/xenolazarus/on_reaction(var/datum/reagents/holder, var/created_volume) //literally all this does is mash the regenerate button
/decl/chemical_reaction/instant/xenolazarus/on_reaction(var/datum/reagents/holder, var/created_volume) //literally all this does is mash the regenerate button
if(ishuman(holder.my_atom))
var/mob/living/carbon/human/H = holder.my_atom
if(H.stat == DEAD && (/mob/living/carbon/human/proc/reconstitute_form in H.verbs)) //no magical regen for non-regenners, and can't force the reaction on live ones
@@ -75,10 +75,10 @@
H.visible_message("<span class='info'>[H] twitches for a moment, but remains still.</span>") // no nutriment
/datum/chemical_reaction/foam/softdrink
/decl/chemical_reaction/instant/foam/softdrink
required_reagents = list("cola" = 1, "mint" = 1)
/datum/chemical_reaction/firefightingfoam //TODO: Make it so we can add this to the foam tanks to refill them
/decl/chemical_reaction/instant/firefightingfoam //TODO: Make it so we can add this to the foam tanks to refill them
name = "Firefighting Foam"
id = "firefighting foam"
result = "firefoam"
@@ -86,7 +86,7 @@
catalysts = list("fluorine" = 10)
result_amount = 1
/datum/chemical_reaction/firefightingfoamqol //Please don't abuse this and make us remove it. Seriously.
/decl/chemical_reaction/instant/firefightingfoamqol //Please don't abuse this and make us remove it. Seriously.
name = "Firefighting Foam EZ"
id = "firefighting foam ez"
result = "firefoam"
@@ -98,14 +98,14 @@
///////////////////////////////////////////////////////////////////////////////////
/// Vore Drugs
/datum/chemical_reaction/ickypak
/decl/chemical_reaction/instant/ickypak
name = "Ickypak"
id = "ickypak"
result = "ickypak"
required_reagents = list("hyperzine" = 4, "fluorosurfactant" = 1)
result_amount = 5
/datum/chemical_reaction/unsorbitol
/decl/chemical_reaction/instant/unsorbitol
name = "Unsorbitol"
id = "unsorbitol"
result = "unsorbitol"
@@ -114,14 +114,14 @@
///////////////////////////////////////////////////////////////////////////////////
/// Other Drugs
/datum/chemical_reaction/adranol
/decl/chemical_reaction/instant/adranol
name = "Adranol"
id = "adranol"
result = "adranol"
required_reagents = list("milk" = 2, "hydrogen" = 1, "potassium" = 1)
result_amount = 3
/datum/chemical_reaction/vermicetol
/decl/chemical_reaction/instant/vermicetol
name = "Vermicetol"
id = "vermicetol"
result = "vermicetol"
@@ -129,215 +129,16 @@
catalysts = list("phoron" = 5)
result_amount = 3
///////////////////////////////////////////////////////////////////////////////////
/// Special drinks
/datum/chemical_reaction/drinks/grubshake
name = "Grub protein drink"
id = "grubshake"
result = "grubshake"
required_reagents = list("shockchem" = 5, "water" = 25)
result_amount = 30
/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/drinks/monstertamer
name = "Monster Tamer"
id = "monstertamer"
result = "monstertamer"
required_reagents = list("whiskey" = 1, "protein" = 1)
result_amount = 2
/datum/chemical_reaction/drinks/bigbeer
name = "Giant Beer"
id = "bigbeer"
result = "bigbeer"
required_reagents = list("syndicatebomb" = 1, "manlydorf" = 1, "grog" =1)
result_amount = 3
/datum/chemical_reaction/drinks/sweettea
name = "Sweetened Tea"
id = "sweettea"
result = "sweettea"
required_reagents = list("icetea" = 2, "sugar" = 1,)
result_amount = 3
/datum/chemical_reaction/drinks/unsweettea
name = "Unsweetened Tea"
id = "unsweettea"
result = "unsweettea"
required_reagents = list("sweettea" = 3, "phoron" = 1)
result_amount = 2
/datum/chemical_reaction/drinks/galacticpanic
name = "Galactic Panic Attack"
id = "galacticpanic"
result = "galacticpanic"
required_reagents = list("gargleblaster" = 1, "singulo" = 1, "phoronspecial" =1, "neurotoxin" = 1, "atomicbomb" = 1, "hippiesdelight" = 1)
result_amount = 6
/datum/chemical_reaction/drinks/bulldog
name = "Space Bulldog"
id = "bulldog"
result = "bulldog"
required_reagents = list("whiterussian" = 4, "cola" =1)
result_amount = 4
/datum/chemical_reaction/drinks/sbagliato
name = "Negroni Sbagliato"
id = "sbagliato"
result = "sbagliato"
required_reagents = list("wine" = 1, "vermouth" = 1, "sodawater" =1)
result_amount = 3
/datum/chemical_reaction/drinks/italiancrisis
name = "Italian Crisis"
id = "italiancrisis"
result = "italiancrisis"
required_reagents = list("bulldog" = 1, "sbagliato" = 1)
result_amount = 2
/datum/chemical_reaction/drinks/sugarrush
name = "Sweet Rush"
id = "sugarrush"
result = "sugarrush"
required_reagents = list("sugar" = 1, "sodawater" = 1, "vodka" =1)
result_amount = 3
/datum/chemical_reaction/drinks/lotus
name = "Lotus"
id = "lotus"
result = "lotus"
required_reagents = list("sbagliato" = 1, "sugarrush" = 1)
result_amount = 2
/datum/chemical_reaction/drinks/shroomjuice
name = "Dumb Shroom Juice"
id = "shroomjuice"
result = "shroomjuice"
required_reagents = list("psilocybin" = 1, "applejuice" = 1, "limejuice" =1)
result_amount = 3
/datum/chemical_reaction/drinks/russianroulette
name = "Russian Roulette"
id = "russianroulette"
result = "russianroulette"
required_reagents = list("whiterussian" = 5, "iron" = 1)
result_amount = 6
/datum/chemical_reaction/drinks/lovemaker
name = "The Love Maker"
id = "lovemaker"
result = "lovemaker"
required_reagents = list("honey" = 1, "sexonthebeach" = 5)
result_amount = 6
/datum/chemical_reaction/drinks/honeyshot
name = "Honey Shot"
id = "honeyshot"
result = "honeyshot"
required_reagents = list("honey" = 1, "vodka" = 1, "grenadine" =1)
result_amount = 3
/datum/chemical_reaction/drinks/appletini
name = "Appletini"
id = "appletini"
result = "appletini"
required_reagents = list("applejuice" = 2, "vodka" = 1)
result_amount = 3
/datum/chemical_reaction/drinks/glowingappletini
name = "Glowing Appletini"
id = "glowingappletini"
result = "glowingappletini"
required_reagents = list("appletini" = 5, "uranium" = 1)
result_amount = 6
/datum/chemical_reaction/drinks/scsatw
name = "Slow Comfortable Screw Against the Wall"
id = "scsatw"
result = "scsatw"
required_reagents = list("screwdrivercocktail" = 3, "rum" =1, "whiskey" =1, "gin" =1)
result_amount = 6
/datum/chemical_reaction/drinks/choccymilk
name = "Choccy Milk"
id = "choccymilk"
result = "choccymilk"
required_reagents = list("milk" = 3, "coco" = 1)
result_amount = 4
/datum/chemical_reaction/drinks/redspaceflush
name = "Redspace Flush"
id = "redspaceflush"
result = "redspaceflush"
required_reagents = list("rum" = 2, "whiskey" = 2, "blood" =1, "phoron" =1)
result_amount = 6
/datum/chemical_reaction/drinks/graveyard
name = "Graveyard"
id = "graveyard"
result = "graveyard"
required_reagents = list("cola" = 1, "spacemountainwind" = 1, "dr_gibb" =1, "space_up" = 1)
result_amount = 4
/datum/chemical_reaction/drinks/hairoftherat
name = "Hair of the Rat"
id = "hairoftherat"
result = "hairoftherat"
required_reagents = list("monstertamer" = 2, "nutriment" = 1)
result_amount = 3
/datum/chemical_reaction/drinks/pink_moo
name = "Pink Moo"
id = "pinkmoo"
result = "pinkmoo"
required_reagents = list("blackrussian" = 2, "berryshake" = 1)
result_amount = 3
/datum/chemical_reaction/drinks/originalsin
name = "Original Sin"
id = "originalsin"
result = "originalsin"
required_reagents = list("holywine" = 1)
catalysts = list("applejuice" = 1)
result_amount = 1
/datum/chemical_reaction/drinks/windgarita
name = "WND-Garita"
id = "windgarita"
result = "windgarita"
required_reagents = list("margarita" = 3, "spacemountainwind" = 2, "melonliquor" = 1)
result_amount = 6
/datum/chemical_reaction/drinks/newyorksour
name = "New York Sour"
id = "newyorksour"
result = "newyorksour"
required_reagents = list("whiskeysour" = 3, "wine" = 2, "egg" = 1)
result_amount = 6
/datum/chemical_reaction/drinks/mudslide
name = "Mudslide"
id = "mudslide"
result = "mudslide"
required_reagents = list("blackrussian" = 1, "irishcream" = 1)
result_amount = 2
///////////////////////////////////////////////////////////////////////////////////
/// Reagent colonies.
/datum/chemical_reaction/meatcolony
/decl/chemical_reaction/instant/meatcolony
name = "protein"
id = "meatcolony"
result = "protein"
required_reagents = list("meatcolony" = 5, "virusfood" = 5)
result_amount = 60
/datum/chemical_reaction/plantcolony
/decl/chemical_reaction/instant/plantcolony
name = "nutriment"
id = "plantcolony"
result = "nutriment"
@@ -350,7 +151,7 @@
/datum/chemical_reaction/slime_food
/decl/chemical_reaction/instant/slime_food
name = "Slime Bork"
id = "m_tele2"
result = null
@@ -378,7 +179,7 @@
/datum/chemical_reaction/materials
/decl/chemical_reaction/instant/materials
name = "Slime materials"
id = "slimematerial"
result = null
@@ -435,7 +236,7 @@
C.loc = get_turf(holder.my_atom)
/datum/chemical_reaction/slimelight
/decl/chemical_reaction/instant/slimelight
name = "Slime Glow"
id = "m_glow"
result = null
@@ -448,7 +249,7 @@
F.loc = get_turf(holder.my_atom)
/datum/chemical_reaction/slimephoron
/decl/chemical_reaction/instant/slimephoron
name = "Slime Phoron"
id = "m_plasma"
result = null
@@ -459,7 +260,7 @@
P.amount = 10
P.loc = get_turf(holder.my_atom)
/datum/chemical_reaction/slimefreeze
/decl/chemical_reaction/instant/slimefreeze
name = "Slime Freeze"
id = "m_freeze"
result = null
@@ -477,7 +278,7 @@
/datum/chemical_reaction/slimefrost
/decl/chemical_reaction/instant/slimefrost
name = "Slime Frost Oil"
id = "m_frostoil"
result = "frostoil"
@@ -487,7 +288,7 @@
/datum/chemical_reaction/slimefire
/decl/chemical_reaction/instant/slimefire
name = "Slime fire"
id = "m_fire"
result = null
@@ -503,7 +304,7 @@
spawn (0) target_tile.hotspot_expose(700, 400)
/datum/chemical_reaction/slimeify
/decl/chemical_reaction/instant/slimeify
name = "Advanced Mutation Toxin"
id = "advmutationtoxin2"
result = "advmutationtoxin"
@@ -514,7 +315,7 @@
/datum/chemical_reaction/slimeheal //A slime healing mixture. Why not.
/decl/chemical_reaction/instant/slimeheal //A slime healing mixture. Why not.
name = "Slime Health"
id = "slimeheal"
result = "null"
@@ -530,14 +331,14 @@
C.adjustCloneLoss(-25)
C.updatehealth()
/datum/chemical_reaction/slimejelly
/decl/chemical_reaction/instant/slimejelly
name = "Slime Jam"
id = "m_jam"
result = "slimejelly"
required_reagents = list("phoron" = 20, "sugar" = 50, "lithium" = 50) //In case a xenobiologist is impatient and is willing to drain their dispenser resources, along with plasma!
result_amount = 5
/datum/chemical_reaction/slimevore
/decl/chemical_reaction/instant/slimevore
name = "Slime Vore" // Hostile vore mobs only
id = "m_tele"
result = null
@@ -600,9 +401,27 @@
for(var/j = 1, j <= rand(1, 3), j++)
step(C, pick(NORTH,SOUTH,EAST,WEST))
/decl/chemical_reaction/instant/slime/sapphire_mutation
name = "Slime Mutation Toxins"
id = "slime_mutation_tox"
result = "mutationtoxin"
required_reagents = list("blood" = 5)
result_amount = 30
required = /obj/item/slime_extract/sapphire
<<<<<<< HEAD:code/modules/reagents/Chemistry-Recipes_vr.dm
/datum/chemical_reaction/food/syntiflesh
required_reagents = list("blood" = 5, "clonexadone" = 1)
/datum/chemical_reaction/biomass
result_amount = 6 // Roughly 120u per phoron sheet
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013:code/modules/reagents/Chemistry-Recipes_vr.dm
/datum/chemical_reaction/food/syntiflesh
required_reagents = list("blood" = 5, "clonexadone" = 1)
/datum/chemical_reaction/biomass
result_amount = 6 // Roughly 120u per phoron sheet
=======
/decl/chemical_reaction/instant/biomass
result_amount = 6 // Roughly 120u per phoron sheet
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013:code/modules/reagents/reactions/instant/instant_vr.dm

View File

@@ -1,486 +0,0 @@
/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)
. += "<span class='notice'>It contains:</span>"
if(reagents && reagents.reagent_list.len)
for(var/datum/reagent/R in reagents.reagent_list)
. += "<span class='notice'>[R.volume] units of [R.name]</span>"
else
. += "<span class='notice'>Nothing.</span>"
/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_vr.dmi' //VOREStation Edit
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_vr.dmi' //VOREStation Edit
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)
//VOREStation Add
/obj/structure/reagent_dispensers/fueltank/high
name = "high-capacity fuel tank"
desc = "A highly-pressurized fuel tank made to hold vast amounts of fuel."
icon_state = "weldtank_high"
/obj/structure/reagent_dispensers/fueltank/high/Initialize()
. = ..()
reagents.add_reagent("fuel",4000)
/obj/structure/reagent_dispensers/foam
name = "foamtank"
desc = "A foam tank."
icon = 'icons/obj/objects_vr.dmi' //VOREStation Edit
icon_state = "foamtank"
amount_per_transfer_from_this = 10
/obj/structure/reagent_dispensers/foam/Initialize()
. = ..()
reagents.add_reagent("firefoam",1000)
/obj/structure/reagent_dispensers/fueltank/barrel
name = "hazardous barrel"
desc = "An open-topped barrel full of nasty-looking liquid."
icon_state = "barrel"
modded = TRUE
/obj/structure/reagent_dispensers/fueltank/barrel/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (W.is_wrench()) //can't wrench it shut, it's always open
return
return ..()
//VOREStation Add End
/obj/structure/reagent_dispensers/fueltank/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 2)
if(modded)
. += "<span class='warning'>Fuel faucet is wrenched open, leaking the fuel!</span>"
if(rig)
. += "<span class='notice'>There is some kind of device rigged to the tank.</span>"
/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("<span class='notice'>[usr] detaches [rig] from \the [src].</span>", "<span class='notice'>You detach [rig] from \the [src]</span>")
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. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[loc.x];Y=[loc.y];Z=[loc.z]'>JMP</a>)")
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, "<span class='warning'>There is another device in the way.</span>")
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("<span class='notice'>[user] rigs [W] to \the [src].</span>", "<span class='notice'>You rig [W] to \the [src]</span>")
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. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[loc.x];Y=[loc.y];Z=[loc.z]'>JMP</a>)")
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]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[loc.x];Y=[loc.y];Z=[loc.z]'>JMP</a>).")
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)
. += "<span class='notice'>There are [cups] cups in the cup dispenser.</span>"
/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, "<span class='notice'>You unfasten the jug.</span>")
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, "<span class='notice'>You [anchored? "un" : ""]secured \the [src]!</span>")
anchored = !anchored
playsound(src, I.usesound, 50, 1)
return
if(I.is_screwdriver())
if(cupholder)
playsound(src, I.usesound, 50, 1)
to_chat(user, "<span class='notice'>You take the cup dispenser off.</span>")
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, "<span class='notice'>You start taking the water-cooler apart.</span>")
if(do_after(user, 20 * I.toolspeed) && !bottle && !cupholder)
to_chat(user, "<span class='notice'>You take the water-cooler apart.</span>")
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, "<span class='notice'>You start to screw the bottle onto the water-cooler.</span>")
if(do_after(user, 20) && !bottle && anchored)
bottle = 1
update_icon()
to_chat(user, "<span class='notice'>You screw the bottle onto the water-cooler!</span>")
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, "<span class='warning'>You need to wrench down the cooler first.</span>")
else
to_chat(user, "<span class='warning'>There is already a bottle there!</span>")
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, "<span class='notice'>You start to attach a cup dispenser onto the water-cooler.</span>")
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, 20) && !cupholder && anchored)
if (P.use(1))
to_chat(user, "<span class='notice'>You attach a cup dispenser onto the water-cooler.</span>")
cupholder = 1
update_icon()
else
to_chat(user, "<span class='warning'>You need to wrench down the cooler first.</span>")
else
to_chat(user, "<span class='warning'>There is already a cup dispenser there!</span>")
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/vat
name = "Beer vat"
desc = "A vat of beer."
icon = 'icons/obj/objects.dmi'
icon_state = "vat"
amount_per_transfer_from_this = 15
anchored = 1
/obj/structure/reagent_dispensers/winevat
name = "Wine vat"
desc = "A vat of wine."
icon = 'icons/obj/objects.dmi'
icon_state = "vat"
amount_per_transfer_from_this = 10
anchored = 1
/obj/structure/reagent_dispensers/winevat/Initialize()
..()
reagents.add_reagent("wine",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)

View File

@@ -0,0 +1,728 @@
<<<<<<< HEAD:code/modules/reagents/Chemistry-Reagents.dm
/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
. = ..()
// Called when reagents are removed from a container, most likely after metabolizing in a mob
/datum/reagent/proc/on_remove(var/atom/A)
return
// Called when a mob dies
/datum/reagent/proc/on_mob_death(var/mob/M)
return
//on transfer to new container, return 1 to allow it to continue
/datum/reagent/proc/on_transfer(var/volume)
return 1
/* 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)
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013:code/modules/reagents/Chemistry-Reagents.dm
/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)
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013:code/modules/reagents/reagents/_reagents.dm

View File

@@ -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"

View File

@@ -28,14 +28,6 @@
BI.forceMove(torso)
torso.implants += BI
/datum/chemical_reaction/slime/sapphire_mutation
name = "Slime Mutation Toxins"
id = "slime_mutation_tox"
result = "mutationtoxin"
required_reagents = list("blood" = 5)
result_amount = 30
required = /obj/item/slime_extract/sapphire
/datum/reagent/nif_repair_nanites
name = "Programmed Nanomachines"
id = "nifrepairnanites"

View File

@@ -70,10 +70,12 @@ won't update every console in existence) but it's more of a hassle to do. Also,
return return_name
/obj/machinery/computer/rdconsole/proc/CallReagentName(var/ID)
var/datum/reagent/R = SSchemistry.chemical_reagents["[ID]"]
if(!R)
return ID
return R.name
var/return_name = ID
for(var/datum/reagent/R in SSchemistry.chemical_reagents)
if(R.id == ID)
return_name = R.name
break
return return_name
/obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any).
for(var/obj/machinery/r_n_d/D in range(3, src))

View File

@@ -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("<span class='warning'>Infused with phoron, the core begins to quiver and grow, and soon a new baby slime emerges from it!</span>")
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("<span class='danger'>\The [src] begins to vibrate violently!</span>")
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("<span class='danger'>\The [src] begins to vibrate violently!</span>")
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))
..()

View File

@@ -267,6 +267,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\dbcore.dm"
#include "code\controllers\subsystems\dcs.dm"
@@ -304,7 +305,6 @@
#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\xenoarch.dm"
#include "code\controllers\subsystems\processing\bellies_vr.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"
@@ -3550,7 +3550,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"
@@ -3725,12 +3724,16 @@
#include "code\modules\random_map\noise\ore.dm"
#include "code\modules\random_map\noise\tundra.dm"
#include "code\modules\reagents\Chemistry-Colours.dm"
<<<<<<< HEAD
#include "code\modules\reagents\Chemistry-Holder.dm"
#include "code\modules\reagents\Chemistry-Holder_ch.dm"
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
#include "code\modules\reagents\Chemistry-Holder.dm"
=======
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
#include "code\modules\reagents\Chemistry-Logging.dm"
#include "code\modules\reagents\Chemistry-Machinery.dm"
#include "code\modules\reagents\Chemistry-Machinery_vr.dm"
#include "code\modules\reagents\Chemistry-Metabolism.dm"
<<<<<<< HEAD
#include "code\modules\reagents\Chemistry-Readme.dm"
#include "code\modules\reagents\Chemistry-Reagents-Helpers.dm"
#include "code\modules\reagents\Chemistry-Reagents.dm"
@@ -3769,9 +3772,70 @@
#include "code\modules\reagents\dispenser\supply.dm"
#include "code\modules\reagents\distilling\Distilling-Recipes.dm"
#include "code\modules\reagents\distilling\distilling.dm"
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
#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-Reagents_vr.dm"
#include "code\modules\reagents\Chemistry-Recipes.dm"
#include "code\modules\reagents\Chemistry-Recipes_vr.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-Food-Drinks_vr.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Medicine.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Medicine_vr.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\Chemistry-Reagents\Chemistry-Reagents-Vore_vr.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_presets_vr.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\dispenser_presets_vr.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\distilling.dm"
#include "code\modules\reagents\holder\holder.dm"
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
#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\chem_master_vr.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_presets_vr.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\dispenser_presets_vr.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\drinks_vr.dm"
#include "code\modules\reagents\reactions\instant\food.dm"
#include "code\modules\reagents\reactions\instant\food_vr.dm"
#include "code\modules\reagents\reactions\instant\instant.dm"
#include "code\modules\reagents\reactions\instant\instant_vr.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\blood_pack_vr.dm"
#include "code\modules\reagents\reagent_containers\borghypo.dm"
@@ -3788,7 +3852,24 @@
#include "code\modules\reagents\reagent_containers\syringes.dm"
#include "code\modules\reagents\reagent_containers\syringes_vr.dm"
#include "code\modules\reagents\reagent_containers\unidentified_hypospray.dm"
<<<<<<< HEAD
#include "code\modules\reagents\reagent_containers\food\drinks\bluespacecoffee.dm"
||||||| parent of 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
=======
#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\food_drinks_vr.dm"
#include "code\modules\reagents\reagents\medicine.dm"
#include "code\modules\reagents\reagents\medicine_vr.dm"
#include "code\modules\reagents\reagents\modifiers.dm"
#include "code\modules\reagents\reagents\other.dm"
#include "code\modules\reagents\reagents\other_vr.dm"
#include "code\modules\reagents\reagents\toxins.dm"
#include "code\modules\reagents\reagents\vore_vr.dm"
>>>>>>> 828f6a31bb... Merge pull request #10179 from VOREStation/upstream-merge-8013
#include "code\modules\recycling\conveyor2.dm"
#include "code\modules\recycling\disposal-construction.dm"
#include "code\modules\recycling\disposal.dm"