Oops, I refactored Chemistry! (#8013)

Reorganizes Reagents dir structure
Refactors reactions to /decl
SSChemistry is no longer processing

Optimization isn't so optimized
Updates to distillery
New decl repository methods
Further tweaks
This commit is contained in:
Atermonera
2021-04-20 20:31:49 -07:00
committed by GitHub
parent 1574e4c766
commit 0c0dcb1738
46 changed files with 6235 additions and 6226 deletions

View File

@@ -49,3 +49,11 @@ var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglyce
var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart.
var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional
#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever

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

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

@@ -272,19 +272,19 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
qdel(src)
return 1
/datum/chemical_reaction/promethean_brain_revival
/decl/chemical_reaction/instant/promethean_brain_revival
name = "Promethean Revival"
id = "prom_revival"
result = null
required_reagents = list("phoron" = 40)
result_amount = 1
/datum/chemical_reaction/promethean_brain_revival/can_happen(var/datum/reagents/holder)
/decl/chemical_reaction/instant/promethean_brain_revival/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, /obj/item/organ/internal/brain/slime))
return ..()
return FALSE
/datum/chemical_reaction/promethean_brain_revival/on_reaction(var/datum/reagents/holder)
/decl/chemical_reaction/instant/promethean_brain_revival/on_reaction(var/datum/reagents/holder)
var/obj/item/organ/internal/brain/slime/brain = holder.my_atom
if(brain.reviveBody())
brain.visible_message("<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
name = "fuel compressor"
icon = 'icons/obj/machines/power/fusion.dmi'
@@ -53,15 +54,17 @@
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)
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(15)
M.use(FUSION_ROD_SHEET_AMT)
user.put_in_hands(F)
else if(do_special_fuel_compression(thing, user))
return
return ..()
#undef FUSION_ROD_SHEET_AMT

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

File diff suppressed because it is too large Load Diff

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

View File

@@ -14,7 +14,7 @@
//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
var/paths = subtypesof(/datum/reagent)
SSchemistry.chemical_reagents = list()
for(var/path in paths)
var/datum/reagent/D = new path()
@@ -23,7 +23,6 @@
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
@@ -88,18 +87,18 @@
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]
if(SSchemistry.instant_reactions_by_reagent[R.id])
eligible_reactions |= SSchemistry.instant_reactions_by_reagent[R.id]
for(var/i in eligible_reactions)
var/datum/chemical_reaction/C = i
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/datum/chemical_reaction/C = i
var/decl/chemical_reaction/C = i
C.post_reaction(src)
update_total()
@@ -456,8 +455,10 @@
/* Atom reagent creation - use it all the time */
/atom/proc/create_reagents(var/max_vol)
reagents = new/datum/reagents(max_vol, src)
/atom/proc/create_reagents(var/max_vol, var/reagents_type = /datum/reagents)
if(!ispath(reagents_type))
reagents_type = /datum/reagents
reagents = new reagents_type(max_vol, src)
// Aurora Cooking Port
/datum/reagents/proc/get_reagent(var/id) // Returns reference to reagent matching passed ID

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,343 +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
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

View File

@@ -429,3 +429,14 @@
reagents.splash_area(get_turf(src), 3)
visible_message(span("danger", "The [src] bursts open, spreading oil all over the area."))
qdel(src)
/obj/structure/reagent_dispensers/he3
name = "fueltank"
desc = "A fueltank."
icon = 'icons/obj/objects.dmi'
icon_state = "weldtank"
amount_per_transfer_from_this = 10
/obj/structure/reagent_dispenser/he3/Initialize()
..()
reagents.add_reagent("helium3",1000)

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,263 @@
/obj/machinery/reagentgrinder
name = "All-In-One Grinder"
desc = "Grinds stuff into itty bitty bits."
icon = 'icons/obj/kitchen.dmi'
icon_state = "juicer1"
density = 0
anchored = 0
use_power = USE_POWER_IDLE
idle_power_usage = 5
active_power_usage = 100
circuit = /obj/item/weapon/circuitboard/grinder
var/inuse = 0
var/obj/item/weapon/reagent_containers/beaker = null
var/limit = 10
var/list/holdingitems = list()
var/list/sheet_reagents = list( //have a number of reageents divisible by REAGENTS_PER_SHEET (default 20) unless you like decimals,
/obj/item/stack/material/iron = list("iron"),
/obj/item/stack/material/uranium = list("uranium"),
/obj/item/stack/material/phoron = list("phoron"),
/obj/item/stack/material/gold = list("gold"),
/obj/item/stack/material/silver = list("silver"),
/obj/item/stack/material/platinum = list("platinum"),
/obj/item/stack/material/mhydrogen = list("hydrogen"),
/obj/item/stack/material/steel = list("iron", "carbon"),
/obj/item/stack/material/plasteel = list("iron", "iron", "carbon", "carbon", "platinum"), //8 iron, 8 carbon, 4 platinum,
/obj/item/stack/material/snow = list("water"),
/obj/item/stack/material/sandstone = list("silicon", "oxygen"),
/obj/item/stack/material/glass = list("silicon"),
/obj/item/stack/material/glass/phoronglass = list("platinum", "silicon", "silicon", "silicon"), //5 platinum, 15 silicon,
)
var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine")
var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject")
var/static/radial_grind = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_grind")
// var/static/radial_juice = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_juice")
// var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix")
/obj/machinery/reagentgrinder/Initialize()
. = ..()
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
default_apply_parts()
/obj/machinery/reagentgrinder/examine(mob/user)
. = ..()
if(!in_range(user, src) && !issilicon(user) && !isobserver(user))
. += "<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
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
// Super special temperature check.
var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = holder.my_atom
if(RD.current_temp < temp_range[1] || RD.current_temp > temp_range[2])
return FALSE
//check that none of the inhibitors are present in the required amount
if(holder.has_any_reagent(inhibitors))
return 0
if(!istype(holder.my_atom, /obj/item/weapon/reagent_containers/glass/distilling))
return 0
else // Super special temperature check.
var/obj/item/weapon/reagent_containers/glass/distilling/D = holder.my_atom
var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = D.Master
if(RD.current_temp < temp_range[1] || RD.current_temp > temp_range[2])
return 0
return 1
return ..()
/*
/datum/chemical_reaction/distilling/on_reaction(var/datum/reagents/holder, var/created_volume)
/decl/chemical_reaction/distilling/on_reaction(var/datum/reagents/holder, var/created_volume)
if(istype(holder.my_atom, /obj/item/weapon/reagent_containers/glass/distilling))
var/obj/item/weapon/reagent_containers/glass/distilling/D = holder.my_atom
var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = D.Master
@@ -62,7 +49,7 @@
// Subtypes //
// Biomass
/datum/chemical_reaction/distilling/biomass
/decl/chemical_reaction/distilling/biomass
name = "Distilling Biomass"
id = "distill_biomass"
result = "biomass"
@@ -73,7 +60,7 @@
temp_shift = -2
// Medicinal
/datum/chemical_reaction/distilling/inaprovalaze
/decl/chemical_reaction/distilling/inaprovalaze
name = "Distilling Inaprovalaze"
id = "distill_inaprovalaze"
result = "inaprovalaze"
@@ -84,7 +71,7 @@
temp_range = list(T0C + 100, T0C + 120)
/datum/chemical_reaction/distilling/bicaridaze
/decl/chemical_reaction/distilling/bicaridaze
name = "Distilling Bicaridaze"
id = "distill_bicaridaze"
result = "bicaridaze"
@@ -95,7 +82,7 @@
temp_range = list(T0C + 110, T0C + 130)
/datum/chemical_reaction/distilling/dermalaze
/decl/chemical_reaction/distilling/dermalaze
name = "Distilling Dermalaze"
id = "distill_dermalaze"
result = "dermalaze"
@@ -106,7 +93,7 @@
temp_range = list(T0C + 115, T0C + 130)
/datum/chemical_reaction/distilling/spacomycaze
/decl/chemical_reaction/distilling/spacomycaze
name = "Distilling Spacomycaze"
id = "distill_spacomycaze"
result = "spacomycaze"
@@ -117,7 +104,7 @@
temp_range = list(T0C + 100, T0C + 120)
/datum/chemical_reaction/distilling/tricorlidaze
/decl/chemical_reaction/distilling/tricorlidaze
name = "Distilling Tricorlidaze"
id = "distill_tricorlidaze"
result = "tricorlidaze"
@@ -128,7 +115,7 @@
temp_range = list(T0C + 100, T0C + 120)
/datum/chemical_reaction/distilling/synthplas
/decl/chemical_reaction/distilling/synthplas
name = "Distilling Synthplas"
id = "distill_synthplas"
result = "synthblood_dilute"
@@ -140,7 +127,7 @@
temp_range = list(T0C + 110, T0C + 130)
// Alcohol
/datum/chemical_reaction/distilling/beer
/decl/chemical_reaction/distilling/beer
name = "Distilling Beer"
id = "distill_beer"
result = "beer"
@@ -151,7 +138,7 @@
temp_range = list(T20C, T20C + 2)
/datum/chemical_reaction/distilling/ale
/decl/chemical_reaction/distilling/ale
name = "Distilling Ale"
id = "distill_ale"
result = "ale"
@@ -165,7 +152,7 @@
temp_range = list(T0C + 7, T0C + 13)
// Unique
/datum/chemical_reaction/distilling/berserkjuice
/decl/chemical_reaction/distilling/berserkjuice
name = "Distilling Brute Juice"
id = "distill_brutejuice"
result = "berserkmed"
@@ -175,7 +162,7 @@
temp_range = list(T0C + 600, T0C + 700)
temp_shift = 4
/datum/chemical_reaction/distilling/berserkjuice/on_reaction(var/datum/reagents/holder, var/created_volume)
/decl/chemical_reaction/distilling/berserkjuice/on_reaction(var/datum/reagents/holder, var/created_volume)
..()
if(prob(1))
@@ -183,7 +170,7 @@
explosion(T, -1, rand(-1, 1), rand(1,2), rand(3,5))
return
/datum/chemical_reaction/distilling/cryogel
/decl/chemical_reaction/distilling/cryogel
name = "Distilling Cryogellatin"
id = "distill_cryoslurry"
result = "cryoslurry"
@@ -194,7 +181,7 @@
temp_range = list(0, 15)
temp_shift = 20
/datum/chemical_reaction/distilling/cryogel/on_reaction(var/datum/reagents/holder, var/created_volume)
/decl/chemical_reaction/distilling/cryogel/on_reaction(var/datum/reagents/holder, var/created_volume)
..()
if(prob(1))
@@ -204,7 +191,7 @@
F.start()
return
/datum/chemical_reaction/distilling/lichpowder
/decl/chemical_reaction/distilling/lichpowder
name = "Distilling Lichpowder"
id = "distill_lichpowder"
result = "lichpowder"
@@ -215,7 +202,7 @@
temp_range = list(T0C + 100, T0C + 150)
/datum/chemical_reaction/distilling/necroxadone
/decl/chemical_reaction/distilling/necroxadone
name = "Distilling Necroxadone"
id = "distill_necroxadone"
result = "necroxadone"

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

File diff suppressed because it is too large Load Diff

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

@@ -72,14 +72,9 @@ won't update every console in existence) but it's more of a hassle to do. Also,
/obj/machinery/computer/rdconsole/proc/CallReagentName(var/ID)
var/return_name = ID
var/datum/reagent/temp_reagent
for(var/R in (typesof(/datum/reagent) - /datum/reagent))
temp_reagent = null
temp_reagent = new R()
if(temp_reagent.id == ID)
return_name = temp_reagent.name
qdel(temp_reagent)
temp_reagent = null
for(var/datum/reagent/R in SSchemistry.chemical_reagents)
if(R.id == ID)
return_name = R.name
break
return return_name

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

@@ -214,6 +214,7 @@
#include "code\controllers\subsystems\atoms.dm"
#include "code\controllers\subsystems\character_setup.dm"
#include "code\controllers\subsystems\chat.dm"
#include "code\controllers\subsystems\chemistry.dm"
#include "code\controllers\subsystems\circuits.dm"
#include "code\controllers\subsystems\dcs.dm"
#include "code\controllers\subsystems\events.dm"
@@ -246,7 +247,6 @@
#include "code\controllers\subsystems\timer.dm"
#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\xenoarch.dm"
#include "code\controllers\subsystems\processing\chemistry.dm"
#include "code\controllers\subsystems\processing\fastprocess.dm"
#include "code\controllers\subsystems\processing\obj.dm"
#include "code\controllers\subsystems\processing\processing.dm"
@@ -2710,7 +2710,6 @@
#include "code\modules\power\fusion\fusion_circuits.dm"
#include "code\modules\power\fusion\fusion_particle_catcher.dm"
#include "code\modules\power\fusion\fusion_reactions.dm"
#include "code\modules\power\fusion\fusion_reagents.dm"
#include "code\modules\power\fusion\magpower.dm"
#include "code\modules\power\fusion\core\_core.dm"
#include "code\modules\power\fusion\core\core_control.dm"
@@ -2832,36 +2831,33 @@
#include "code\modules\random_map\noise\ore.dm"
#include "code\modules\random_map\noise\tundra.dm"
#include "code\modules\reagents\Chemistry-Colours.dm"
#include "code\modules\reagents\Chemistry-Holder.dm"
#include "code\modules\reagents\Chemistry-Logging.dm"
#include "code\modules\reagents\Chemistry-Machinery.dm"
#include "code\modules\reagents\Chemistry-Metabolism.dm"
#include "code\modules\reagents\Chemistry-Readme.dm"
#include "code\modules\reagents\Chemistry-Reagents-Helpers.dm"
#include "code\modules\reagents\Chemistry-Reagents.dm"
#include "code\modules\reagents\Chemistry-Recipes.dm"
#include "code\modules\reagents\reagent_containers.dm"
#include "code\modules\reagents\reagent_dispenser.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Core.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Dispenser.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Food-Drinks.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Medicine.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Modifiers.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Other.dm"
#include "code\modules\reagents\Chemistry-Reagents\Chemistry-Reagents-Toxins.dm"
#include "code\modules\reagents\dispenser\_defines.dm"
#include "code\modules\reagents\dispenser\cartridge.dm"
#include "code\modules\reagents\dispenser\cartridge_presets.dm"
#include "code\modules\reagents\dispenser\cartridge_spawn.dm"
#include "code\modules\reagents\dispenser\dispenser2.dm"
#include "code\modules\reagents\dispenser\dispenser2_energy.dm"
#include "code\modules\reagents\dispenser\dispenser_presets.dm"
#include "code\modules\reagents\dispenser\supply.dm"
#include "code\modules\reagents\distilling\Distilling-Recipes.dm"
#include "code\modules\reagents\distilling\distilling.dm"
#include "code\modules\reagents\holder\holder.dm"
#include "code\modules\reagents\holder\distilling.dm"
#include "code\modules\reagents\hoses\connector.dm"
#include "code\modules\reagents\hoses\hose.dm"
#include "code\modules\reagents\hoses\hose_connector.dm"
#include "code\modules\reagents\machinery\chem_master.dm"
#include "code\modules\reagents\machinery\chemalyzer.dm"
#include "code\modules\reagents\machinery\distillery.dm"
#include "code\modules\reagents\machinery\grinder.dm"
#include "code\modules\reagents\machinery\dispenser\_defines.dm"
#include "code\modules\reagents\machinery\dispenser\cartridge.dm"
#include "code\modules\reagents\machinery\dispenser\cartridge_presets.dm"
#include "code\modules\reagents\machinery\dispenser\cartridge_spawn.dm"
#include "code\modules\reagents\machinery\dispenser\dispenser2.dm"
#include "code\modules\reagents\machinery\dispenser\dispenser2_energy.dm"
#include "code\modules\reagents\machinery\dispenser\dispenser_presets.dm"
#include "code\modules\reagents\machinery\dispenser\reagent_tank.dm"
#include "code\modules\reagents\machinery\dispenser\supply.dm"
#include "code\modules\reagents\reactions\_reactions.dm"
#include "code\modules\reagents\reactions\distilling\distilling.dm"
#include "code\modules\reagents\reactions\fusion\fusion.dm"
#include "code\modules\reagents\reactions\instant\drinks.dm"
#include "code\modules\reagents\reactions\instant\food.dm"
#include "code\modules\reagents\reactions\instant\instant.dm"
#include "code\modules\reagents\reagent_containers\_reagent_containers.dm"
#include "code\modules\reagents\reagent_containers\blood_pack.dm"
#include "code\modules\reagents\reagent_containers\borghypo.dm"
#include "code\modules\reagents\reagent_containers\dropper.dm"
@@ -2872,6 +2868,15 @@
#include "code\modules\reagents\reagent_containers\spray.dm"
#include "code\modules\reagents\reagent_containers\syringes.dm"
#include "code\modules\reagents\reagent_containers\unidentified_hypospray.dm"
#include "code\modules\reagents\reagents\_helpers.dm"
#include "code\modules\reagents\reagents\_reagents.dm"
#include "code\modules\reagents\reagents\core.dm"
#include "code\modules\reagents\reagents\dispenser.dm"
#include "code\modules\reagents\reagents\food_drinks.dm"
#include "code\modules\reagents\reagents\medicine.dm"
#include "code\modules\reagents\reagents\modifiers.dm"
#include "code\modules\reagents\reagents\other.dm"
#include "code\modules\reagents\reagents\toxins.dm"
#include "code\modules\recycling\conveyor2.dm"
#include "code\modules\recycling\disposal-construction.dm"
#include "code\modules\recycling\disposal.dm"