Merge pull request #813 from ArchieBeepBoop/thalpyyyyy

Updates our Fermichems, fixes synthtissue.
This commit is contained in:
QuoteFox
2021-01-04 05:41:29 +00:00
committed by GitHub
31 changed files with 1603 additions and 1082 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
for(var/file in args)
src << browse_rsc(file)
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html"))
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html", "md"))
var/path = root
for(var/i=0, i<max_iterations, i++)
-2
View File
@@ -182,7 +182,6 @@ GLOBAL_LIST_INIT(bitfields, list(
"CAN_CARRY" = CAN_CARRY,
"CAN_RESIST" = CAN_RESIST
),
"chemical_flags" = list(
"REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
"REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
@@ -197,7 +196,6 @@ GLOBAL_LIST_INIT(bitfields, list(
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
),
"organ_flags" = list(
"ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
"ORGAN_FROZEN" = ORGAN_FROZEN,
File diff suppressed because it is too large Load Diff
+1
View File
@@ -171,6 +171,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
/client/proc/cmd_display_overlay_log,
/client/proc/reload_configuration,
/datum/admins/proc/create_or_modify_area,
/client/proc/generate_wikichem_list //DO NOT PRESS UNLESS YOU WANT SUPERLAG
)
GLOBAL_PROTECT(admin_verbs_possess)
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release))
@@ -395,11 +395,11 @@
results = list(/datum/reagent/consumable/ethanol/neurotoxin = 2)
required_reagents = list(/datum/reagent/consumable/ethanol/gargle_blaster = 1, /datum/reagent/medicine/morphine = 1)
//FermiChem vars: Easy to make, but hard to make potent
OptimalTempMin = 200 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMin = 100 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMax = 950 // Upper end for above
ExplodeTemp = 999 //Temperature at which reaction explodes
OptimalpHMin = 2 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
OptimalpHMax = 3 // Higest value for above
OptimalpHMin = 4.6 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
OptimalpHMax = 5.2 // Higest value for above
ReactpHLim = 5 // How far out pH wil react, giving impurity place (Exponential phase)
CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst)
CurveSharpT = 2 // How sharp the temperature exponential curve is (to the power of value)
@@ -300,9 +300,9 @@
if(reagents.has_reagent(/datum/reagent/fermi/astral))
if(mind)
msg += " and have a strange, abnormal look to them.\n"
msg += " and they have a strange, abnormal look to them.\n"
else
msg += " and don't look like they're all there.\n"
msg += " and they don't look like they're all there.\n"
if(isliving(user))
var/mob/living/L = user
@@ -59,3 +59,9 @@
return
to_chat(A, "[src] projects into your mind, <b><i> \"[message]\"</b></i>")
log_game("FERMICHEM: [src] has astrally transmitted [message] into [A]")
//Delete the mob if there's no mind! Pay that mob no mind.
/mob/living/simple_animal/astral/Life()
if(!mind)
qdel(src)
. = ..()
@@ -307,6 +307,7 @@
emote_see = list("looks at you eagerly for pets!", "wiggles enthusiastically.")
gold_core_spawnable = NO_SPAWN
var/pseudo_death = FALSE
var/mob/living/carbon/human/origin
/mob/living/simple_animal/pet/cat/custom_cat/death()
if (pseudo_death == TRUE) //secret cat chem
+305
View File
@@ -0,0 +1,305 @@
//Generates a markdown txt file for use with the wiki
/proc/find_reagent(input)
//prefer types!
. = GLOB.chemical_reagents_list[text2path(input)]
if(.)
return
. = GLOB.name2reagent[ckey(input)]
/client/proc/generate_wikichem_list()
set name = "Generate Wikichems"
set category = "Debug"
set desc = "Generate a huge loglist of all the chems. Do not click unless you want lag."
var/prefix = "|Name | Reagents | Reaction vars | Description | Chem properties |\n|---|---|---|-----------|---|\n"
var/input_reagent = replacetext(lowertext(input("Input the name/type of a reagent to get it's description on it's own, or leave blank to parse every chem.", "Input") as text), " ", "") //95% of the time, the reagent type is a lowercase, no spaces / underscored version of the name
if(input_reagent)
var/input_reagent2 = find_reagent(input_reagent)
if(!input_reagent2)
to_chat(usr, "Unable to find reagent, stopping proc.")
var/single_parse = generate_chemwiki_line(input_reagent2, input_reagent, FALSE)
text2file(single_parse, "[GLOB.log_directory]/chem_parse.md")
to_chat(usr, "[single_parse].")
single_parse = generate_chemwiki_line(input_reagent2, input_reagent, FALSE)
text2file(single_parse, "[GLOB.log_directory]/chem_parse.md")
to_chat(usr, "[single_parse].")
to_chat(usr, "Saved line to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.md OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .md default program! Try downloading it instead, and use that file to set a default program! Also have a cute day.)")
//Do things here
return
to_chat(usr, "Generating big list")
message_admins("Someone pressed the lag button. (Generate Wikichems)")
///datum/reagent/medicine, /datum/reagent/toxin, /datum/reagent/consumable, /datum/reagent/plantnutriment, /datum/reagent/uranium,
///datum/reagent/colorful_reagent, /datum/reagent/mutationtoxin, /datum/reagent/fermi, /datum/reagent/drug, /datum/reagent/impure
//Probably not the most eligant of solutions.
to_chat(usr, "Attempting reagent scan. Length of list [LAZYLEN(GLOB.chemical_reagents_list)*2]")
var/datum/reagent/R
var/tally = 0
var/processCR = TRUE //Process reactions first
var/medicine = ""
var/toxin = ""
var/consumable = ""
var/plant = ""
var/uranium = ""
var/colours = ""
var/muta = ""
var/fermi = ""
var/remainder = ""
var/drug = ""
var/basic = ""
var/upgraded = ""
var/drinks = ""
var/alco = ""
var/grinded = ""
var/blob = ""
var/impure = ""
//Chem_dispencer
var/obj/machinery/chem_dispenser/C
var/list/dispensable_reagents = initial(C.dispensable_reagents)
var/list/components = initial(C.upgrade_reagents) + initial(C.upgrade_reagents2) + initial(C.upgrade_reagents3)
var/list/grind = list(
/datum/reagent/bluespace,
/datum/reagent/gold,
/datum/reagent/toxin/plasma,
/datum/reagent/uranium
)
//Bartender
var/obj/machinery/chem_dispenser/drinks/D
var/dispence_drinks = initial(D.dispensable_reagents)
var/obj/machinery/chem_dispenser/drinks/beer/B
var/dispence_alco = initial(B.dispensable_reagents)
var/breakout = FALSE
for(var/i = 1, i <= 2, i+=1)
for(var/X in GLOB.chemical_reagents_list)
R = GLOB.chemical_reagents_list[X]
if(!R.description) //No description? It's not worth my time.
continue
for(var/Y in dispensable_reagents) //Why do you have to do this
if(R.type == Y)
basic += generate_chemwiki_line(R, X, processCR)
breakout = TRUE
continue
for(var/Y in components)
if(R.type == Y)
upgraded += generate_chemwiki_line(R, X, processCR)
breakout = TRUE
continue
for(var/Y in dispence_drinks)
if(R.type == Y)
drinks += generate_chemwiki_line(R, X, processCR)
breakout = TRUE
continue
for(var/Y in dispence_alco)
if(R.type == Y)
alco += generate_chemwiki_line(R, X, processCR)
breakout = TRUE
continue
for(var/Y in grind)
if(R.type == Y)
grinded += generate_chemwiki_line(R, X, processCR)
breakout = TRUE
continue
if(breakout)
breakout = FALSE
continue
if(istype(R, /datum/reagent/medicine))
medicine += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/toxin))
toxin += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/consumable))
consumable += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/plantnutriment))
plant += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/uranium))
uranium += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/colorful_reagent))
colours += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/mutationtoxin))
muta += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/fermi))
fermi += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/drug))
drug += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/blob))
blob += generate_chemwiki_line(R, X, processCR)
else if(istype(R, /datum/reagent/impure))
impure += generate_chemwiki_line(R, X, processCR)
else
remainder += generate_chemwiki_line(R, X, processCR)
tally++
if((tally%50)==0)
to_chat(usr, "[tally] of [LAZYLEN(GLOB.chemical_reagents_list)*2] done.")
processCR = FALSE
to_chat(usr, "finished chems")
var/wholeString = ("\n# DISPENCEABLE REAGENTS\n\n[prefix][basic]\n\n# COMPONENT REAGENTS\n\n[prefix][upgraded]\n\n# GROUND REAGENTS\n\n[prefix][grinded]\n")
wholeString += ("\n# MEDICINE:\n\n[prefix][medicine]\n\n# TOXIN:\n\n[prefix][toxin]\n\n# DRUGS\n\n[prefix][drug]\n\n# FERMI\n\nThese chems lie on the cutting edge of chemical technology, and as such are not recommended for beginners!\n\n[prefix][fermi]\n\n# IMPURE REAGENTS\n\n[prefix][impure]\n\n# GENERAL REAGENTS\n\n[prefix][remainder]\n\n# DISPENCEABLE SOFT DRINKS\n\n[prefix][drinks]\n\n# DISPENCEABLE HARD DRINKS\n\n[prefix][alco]\n\n# CONSUMABLE\n\n[prefix][consumable]\n\n# PLANTS\n\n[prefix][plant]\n\n# URANIUM\n\n[prefix][uranium]\n\n# COLOURS\n\n[prefix][colours]\n\n# RACE MUTATIONS\n\n[prefix][muta]\n\n\n# BLOB REAGENTS\n\n[prefix][blob]\n")
prefix = "|Name | Reagents | Reaction vars | Description |\n|---|---|---|----------|\n"
var/CRparse = ""
to_chat(usr, "starting reactions")
//generate the reactions that we missed from before
for(var/reagent in GLOB.chemical_reactions_list)
for(var/datum/chemical_reaction/CR in GLOB.chemical_reactions_list[reagent])
CRparse += generate_chemreactwiki_line(CR)
wholeString += ("\n# CHEMICAL REACTIONS\n\n[prefix][CRparse]\n")
text2file(wholeString, "[GLOB.log_directory]/chem_parse.md")
to_chat(usr, "finished reactions")
to_chat(usr, "Saved file to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.md OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .md default program! Try downloading it instead, and use that file to set a default program! Also have a cute day.)")
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Generate the big list of reagent based reactions.
/proc/generate_chemwiki_line(datum/reagent/R, X, processCR)
//name | Reagent pH | reagents | reaction temp | explosion temp | pH range | Kinetics | description | OD level | Addiction level | Metabolism rate | impure chem | inverse chem
var/datum/chemical_reaction/CR = get_chemical_reaction(R.type)
if((!CR && processCR) || (CR && !processCR)) // Do reactions first.
return ""
var/outstring = "|<a href=\"#[R.name]\"><h5 id=\"[R.name]\">!\[[R.color]\](https://placehold.it/15/[copytext(R.color, 2, 8)]/000000?text=+)[R.name]</h5></a> pH: [R.pH] | "
var/datum/reagent/R3
if(CR)
outstring += "<ul>"
for(var/R2 in CR.required_reagents)
R3 = GLOB.chemical_reagents_list[R2]//What a convoluted mess
outstring += "<li><a href=\"#[R3.name]\">[R3.name]</a>: [CR.required_reagents[R3.type]]u</li>"
if(CR.required_catalysts)
for(var/R2 in CR.required_catalysts)
R3 = GLOB.chemical_reagents_list[R2]
outstring += "<li>Catalyst: <a href=\"#[R3.name]\">[R3.name]</a>: [CR.required_catalysts[R3.type]]u</li>"
outstring += "</ul> | "
else
outstring += "N/A | "
//Temp, Explosions and pH
if(CR)
outstring += "<ul>[(CR.FermiChem?"<li>Min react temp: [CR.OptimalTempMin]K</li>":"[(CR.required_temp?"<li>Min react temp: [CR.required_temp]K</li>":"")]")] [(CR.FermiChem?"<li>Explosion_temp: [CR.ExplodeTemp]K</li>":"")] [(CR.FermiChem?"<li>pH range: [max((CR.OptimalpHMin - CR.ReactpHLim), 0)] to [min((CR.OptimalpHMax + CR.ReactpHLim), 14)]</li>":"")] "
if(CR.FermiChem)
outstring += "[(CR.PurityMin?"<li>Min explosive purity: [CR.PurityMin]</li>":"")] [(CR.FermiExplode?"<li>Special explosion: Yes</li>":"")]"
else
outstring += ""
//Kinetics
if(CR)
if(CR.FermiChem)
switch(CR.ThermicConstant)
if(-INFINITY to -9.9)
outstring += "<li>Extremely endothermic</li> "
if(-9.9 to -4.9)
outstring += "<li>Very endothermic</li> "
if(-4.9 to -0.1)
outstring += "<li>Endothermic</li> "
if(-0.1 to 0.1)
outstring += "<li>Neutral</li> "
if(0.1 to 4.9)
outstring += "<li>Exothermic</li> "
if(4.9 to 9.9)
outstring += "<li>Very exothermic</li> "
if(9.9 to 19.9)
outstring += "<li>Extremely exothermic</li> "
if(19.9 to INFINITY )
outstring += "<li>**Dangerously exothermic**</li> "
//if("cheesey")
//outstring += "<li>Dangerously Cheesey</li>"
outstring += "</ul>| "
else
outstring += " | "
//Description, OD, Addict, Meta
outstring += "[R.description] | <ul><li>Metabolism rate: [R.metabolization_rate/2]u/s</li> [(R.overdose_threshold?"<li>Overdose: [R.overdose_threshold]u</li>":"")] [(R.addiction_threshold?"<li>Addiction: [R.addiction_threshold]u</li>":"")] "
if(R.impure_chem && R.impure_chem != /datum/reagent/impure/fermiTox)
R3 = GLOB.chemical_reagents_list[R.impure_chem]
outstring += "<li>Impure chem:<a href=\"#[R3.name]\">[R3.name]</a></li>"
if(R.inverse_chem && R.impure_chem != /datum/reagent/impure/fermiTox)
R3 = GLOB.chemical_reagents_list[R.inverse_chem]
outstring += "<li>Inverse chem:<a href=\"#[R3.name]\">[R3.name]</a></li> [(R3.inverse_chem_val?"<li>Inverse purity: [R3.inverse_chem_val]</li>":"")] "
if(CR)
if(CR.required_container)
/*var/obj/item/I
I = istype(I, CR.required_container) if you can work out how to get this to work, by all means.
outstring += "<li>Required container: [I.name]</li>"*/
outstring += "<li>Required container: [CR.required_container]</li>"
outstring += "</ul>|\n"
return outstring
//Generate the big list of reaction based reactions.
//|Name | Reagents | Reaction vars | Description | Chem properties
/proc/generate_chemreactwiki_line(datum/chemical_reaction/CR)
if(CR.results.len) //Handled prior
return
var/outstring = "|[CR.name] | <ul>"
//reagents
var/datum/reagent/R3
for(var/R2 in CR.required_reagents)
R3 = GLOB.chemical_reagents_list[R2]
outstring += "<li><a href=\"#[R3.name]\">[R3.name]</a>: [CR.required_reagents[R3.type]]u</li>"
if(CR.required_catalysts)
for(var/R2 in CR.required_catalysts)
R3 = GLOB.chemical_reagents_list[R2]
outstring += "<li>Catalyst: <a href=\"#[R3.name]\">[R3.name]</a>: [CR.required_catalysts[R3.type]]u</li>"
outstring += "</ul> | <ul>"
//Reaction vars
if(CR.required_temp)
outstring += "<li>Min react temp: [CR.required_temp]K</li>"
if(CR.FermiChem)
outstring += "[(CR.FermiChem?"<li>Min react temp: [CR.OptimalTempMin]K</li>":"[(CR.required_temp?"<li>Min react temp: [CR.required_temp]K</li>":"")]")] [(CR.FermiChem?"<li>Explosion temp: [CR.ExplodeTemp]K</li>":"")] [(CR.FermiChem?"<li>pH range: [max((CR.OptimalpHMin - CR.ReactpHLim), 0)] to [min((CR.OptimalpHMax + CR.ReactpHLim), 14)]</li>":"")] <li>Minimum purity: [CR.PurityMin] [(CR.FermiExplode?"<li>Special explosion: Yes</li>":"")]"
if(CR.is_cold_recipe)
outstring += "<li>Cold: Yes</li>"
if(CR.required_container)
outstring += "<li>Required container: [CR.required_container]</li>"
if(CR.mob_react)
outstring += "<li>Can react in mob: Yes</li>"
//description
outstring += "</ul>| fill in manually "
outstring += "<ul>|\n"
return outstring
@@ -0,0 +1,23 @@
How to code fermichem reactions:
First off, probably read though the readme for standard reagent mechanisms, this builds on top of that.
#bitflags
for `datum/reagent/` you have the following options with `var/chemical_flags`:
```
REAGENT_DEAD_PROCESS calls on_mob_dead() if present in a dead body
REAGENT_DONOTSPLIT Do not split the chem at all during processing
REAGENT_ONLYINVERSE Only invert chem, no splitting
REAGENT_ONMOBMERGE Call on_mob_life proc when reagents are merging.
REAGENT_INVISIBLE Doesn't appear on handheld health analyzers.
REAGENT_FORCEONNEW Forces a on_new() call without a data overhead
REAGENT_SNEAKYNAME When inverted, the inverted chem uses the name of the original chem
REAGENT_SPLITRETAINVOL Retains initial volume of chem when splitting
```
for `datum/chemical_reaction/` under `var/clear_conversion`
```
REACTION_CLEAR_IMPURE Convert into impure/pure on reaction completion
REACTION_CLEAR_INVERSE Convert into inverse on reaction completion when purity is low enough
```
+66 -63
View File
@@ -1,4 +1,4 @@
#define CHEMICAL_QUANTISATION_LEVEL 0.001
#define CHEMICAL_QUANTISATION_LEVEL 0.001
/proc/build_chemical_reagent_list()
//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
@@ -125,8 +125,6 @@
/datum/reagents/proc/remove_all(amount = 1)
var/list/cached_reagents = reagent_list
if((total_volume - amount) <= 0)//Because this can result in 0, I don't want it to crash.
pH = 7
if(total_volume > 0)
var/part = amount / total_volume
for(var/reagent in cached_reagents)
@@ -239,7 +237,7 @@
src.handle_reactions()
return amount
/datum/reagents/proc/trans_id_to(obj/target, reagent, amount=1, preserve_data=1)//Not sure why this proc didn't exist before. It does now! /N
/datum/reagents/proc/trans_id_to(obj/target, reagent, amount = 1, preserve_data = TRUE)//Not sure why this proc didn't exist before. It does now! /N
var/list/cached_reagents = reagent_list
if (!target)
return
@@ -259,7 +257,6 @@
if(preserve_data)
trans_data = current_reagent.data
R.add_reagent(current_reagent.type, amount, trans_data, chem_temp, current_reagent.purity, pH, no_react = TRUE)
remove_reagent(current_reagent.type, amount, 1)
break
@@ -365,7 +362,7 @@
/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION
if(fermiIsReacting == TRUE)
if(fermiIsReacting) //This ARRESTS other reactions. If you don't want this, then remove it.
return
if(reagents_holder_flags & NO_REACT)
@@ -404,7 +401,7 @@
for(var/B in cached_required_reagents)
if(!has_reagent(B, cached_required_reagents[B]))
if(!has_reagent(B, cached_required_reagents[B]))//Allows vols at less than 1 to react.
break
total_matching_reagents++
for(var/B in cached_required_catalysts)
@@ -464,7 +461,7 @@
//Temperature plays into a larger role too.
var/datum/chemical_reaction/C = selected_reaction
if (C.FermiChem == TRUE && !continue_reacting)
if (C.FermiChem && !continue_reacting)
if (chem_temp > C.ExplodeTemp) //This is first to ensure explosions.
var/datum/chemical_reaction/Ferm = selected_reaction
fermiIsReacting = FALSE
@@ -472,31 +469,28 @@
Ferm.FermiExplode(src, my_atom, volume = total_volume, temp = chem_temp, pH = pH)
return 0
//This is just to calc the on_reaction multiplier, and is a candidate for removal.
for(var/B in cached_required_reagents)
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), CHEMICAL_QUANTISATION_LEVEL))
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), 0.0001))
for(var/P in selected_reaction.results)
targetVol = cached_results[P]*multiplier
if( (chem_temp <= C.ExplodeTemp) && (chem_temp >= C.OptimalTempMin))
if( (pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) )//To prevent pointless reactions
if (fermiIsReacting == TRUE)
return 0
else
START_PROCESSING(SSprocessing, src)
selected_reaction.on_reaction(src, my_atom, multiplier)
fermiIsReacting = TRUE
fermiReactID = selected_reaction
reaction_occurred = 1
else //It's a little bit of a confusing nest, but esstentially we check if it's a fermireaction, then temperature, then pH. If this is true, the remainer of this handler is run.
return 0 //If pH is out of range
if(!((chem_temp <= C.ExplodeTemp) && (chem_temp >= C.OptimalTempMin)))
return 0 //Not hot enough
if(! ((pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) ))//To prevent pointless reactions
return 0
if (fermiIsReacting)
return 0
else
return 0 //If not hot enough
START_PROCESSING(SSprocessing, src)
selected_reaction.on_reaction(src, my_atom, multiplier)
fermiIsReacting = TRUE
fermiReactID = selected_reaction
reaction_occurred = 1
//Standard reaction mechanics:
else
if (C.FermiChem == TRUE)//Just to make sure, should only proc when grenades are combining.
if (C.FermiChem)//Just to make sure, should only proc when grenades are combining.
if (chem_temp > C.ExplodeTemp) //To allow fermigrenades
var/datum/chemical_reaction/fermi/Ferm = selected_reaction
fermiIsReacting = FALSE
@@ -507,6 +501,7 @@
for(var/B in cached_required_reagents) //
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), CHEMICAL_QUANTISATION_LEVEL))
for(var/B in cached_required_reagents)
remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1, ignore_pH = TRUE)
@@ -549,40 +544,45 @@
var/list/cached_required_reagents = C.required_reagents//update reagents list
var/list/cached_results = C.results//resultant chemical list
var/multiplier = INFINITY
for(var/B in cached_required_reagents) //
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), 0.001))
if (multiplier == 0)
multiplier = min(multiplier, round((get_reagent_amount(B) / cached_required_reagents[B]), 0.0001))
if (multiplier <= 0)//clarity
fermiEnd()
return
for(var/P in C.required_catalysts)
if(!has_reagent(P))
fermiEnd()
return
for(var/P in cached_results)
targetVol = cached_results[P]*multiplier
if (fermiIsReacting == FALSE)
CRASH("Fermi has refused to stop reacting even though we asked her nicely.")
if (chem_temp > C.OptimalTempMin && fermiIsReacting == TRUE)//To prevent pointless reactions
if( (pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) )
if (reactedVol < targetVol)
reactedVol = fermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results, multiplier)
else//Volume is used up
if(C.required_catalysts)
for(var/P in C.required_catalysts)
if(!has_reagent(P))
fermiEnd()
return
else//pH is out of range
fermiEnd()
return
else//Temperature is too low, or reaction has stopped.
if (!fermiIsReacting)
CRASH("Fermi has refused to stop reacting even though we asked her nicely.")
if (!(chem_temp >= C.OptimalTempMin))//To prevent pointless reactions
fermiEnd()
return
if (!( (pH >= (C.OptimalpHMin - C.ReactpHLim)) && (pH <= (C.OptimalpHMax + C.ReactpHLim)) )) //if pH is too far out, (could possibly allow reactions at this point, after the reaction has started, but make purity = 0)
fermiEnd()
return
reactedVol = fermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results, multiplier)
if(round(reactedVol, CHEMICAL_QUANTISATION_LEVEL) == round(targetVol, CHEMICAL_QUANTISATION_LEVEL))
fermiEnd()
if(!reactedVol)//Maybe unnessicary.
fermiEnd()
return
/datum/reagents/proc/fermiEnd()
var/datum/chemical_reaction/C = fermiReactID
STOP_PROCESSING(SSprocessing, src)
fermiIsReacting = FALSE
reactedVol = 0
targetVol = 0
//Cap off values
for(var/datum/reagent/R in reagent_list)
R.volume = round(R.volume, CHEMICAL_QUANTISATION_LEVEL)//To prevent runaways.
//pH check, handled at the end to reduce calls.
if(istype(my_atom, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = my_atom
@@ -650,16 +650,18 @@
//ONLY WORKS FOR ONE PRODUCT AT THE MOMENT
//Calculate how much product to make and how much reactant to remove factors..
for(var/P in cached_results)
//stepChemAmmount = CLAMP(((deltaT * multiplier), 0, ((targetVol - reactedVol)/cached_results[P])) //used to have multipler, now it does
stepChemAmmount = (multiplier*cached_results[P])
if (stepChemAmmount >= C.RateUpLim)
stepChemAmmount = (C.RateUpLim)
if (stepChemAmmount > C.RateUpLim)
stepChemAmmount = C.RateUpLim
addChemAmmount = deltaT * stepChemAmmount
if (addChemAmmount >= (targetVol - reactedVol))
addChemAmmount = (targetVol - reactedVol)
if (addChemAmmount < CHEMICAL_QUANTISATION_LEVEL)
addChemAmmount = CHEMICAL_QUANTISATION_LEVEL
removeChemAmmount = (addChemAmmount/cached_results[P])
//keep limited.
addChemAmmount = round(addChemAmmount, CHEMICAL_QUANTISATION_LEVEL)
removeChemAmmount = round(removeChemAmmount, CHEMICAL_QUANTISATION_LEVEL)
//This is kept for future bugtesters.
//message_admins("Reaction vars: PreReacted: [reactedVol] of [targetVol]. deltaT [deltaT], multiplier [multiplier], Step [stepChemAmmount], uncapped Step [deltaT*(multiplier*cached_results[P])], addChemAmmount [addChemAmmount], removeFactor [removeChemAmmount] Pfactor [cached_results[P]], adding [addChemAmmount]")
@@ -672,7 +674,7 @@
for(var/P in cached_results)
SSblackbox.record_feedback("tally", "chemical_reaction", addChemAmmount, P)//log
SSblackbox.record_feedback("tally", "fermi_chem", addChemAmmount, P)
add_reagent(P, (addChemAmmount), null, cached_temp, purity)//add reagent function!! I THINK I can do this:
add_reagent(P, (addChemAmmount), null, cached_temp, purity)
TotalStep += addChemAmmount//for multiple products
//Above should reduce yeild based on holder purity.
//Purity Check
@@ -681,9 +683,9 @@
if (R.purity < C.PurityMin)//If purity is below the min, blow it up.
fermiIsReacting = FALSE
SSblackbox.record_feedback("tally", "fermi_chem", 1, ("[P] explosion"))
C.FermiExplode(src, my_atom, (reactedVol+targetVol), cached_temp, pH)
C.FermiExplode(src, my_atom, (total_volume), cached_temp, pH)
STOP_PROCESSING(SSprocessing, src)
return 0
return
C.FermiCreate(src, addChemAmmount, purity)//proc that calls when step is done
@@ -698,11 +700,11 @@
//go to explode proc
fermiIsReacting = FALSE
SSblackbox.record_feedback("tally", "fermi_chem", 1, ("[C] explosions"))
C.FermiExplode(src, my_atom, (reactedVol+targetVol), chem_temp, pH)
C.FermiExplode(src, my_atom, (total_volume), chem_temp, pH)
STOP_PROCESSING(SSprocessing, src)
return
//Make sure things are limited.
//Make sure things are limited, but superacids/bases can push forward the reaction
pH = CLAMP(pH, 0, 14)
//return said amount to compare for next step.
@@ -717,6 +719,8 @@
if (R in cached_reagents)
cachedPurity += R.purity
i++
if(!i)//I've never seen it get here with 0, but in case
CRASH("No reactants found mid reaction for [fermiReactID]/[C], how it got here is beyond me. Beaker: [holder]")
return cachedPurity/i
/datum/reagents/proc/uncache_purity(id)
@@ -764,8 +768,8 @@
del_reagent(R.type)
else
total_volume += R.volume
if(!reagent_list)
pH = 7
if(!reagent_list || !total_volume)
pH = REAGENT_NORMAL_PH
return 0
/datum/reagents/proc/clear_reagents()
@@ -830,7 +834,7 @@
if(!isnum(amount) || !amount)
return FALSE
if(amount <= CHEMICAL_QUANTISATION_LEVEL)//To prevent small ammount problems.
if(amount < CHEMICAL_QUANTISATION_LEVEL)//To prevent small ammount problems.
return FALSE
var/datum/reagent/D = GLOB.chemical_reagents_list[reagent]
@@ -864,7 +868,6 @@
var/new_total = cached_total + amount
var/cached_temp = chem_temp
var/list/cached_reagents = reagent_list
var/cached_pH = pH
@@ -881,7 +884,7 @@
chem_temp = thermal_energy / (specific_heat * new_total)
//cacluate reagent based pH shift.
if(ignore_pH == TRUE)
if(ignore_pH)
pH = ((cached_pH * cached_total)+(other_pH * amount))/(cached_total + amount)//should be right
else
pH = ((cached_pH * cached_total)+(D.pH * amount))/(cached_total + amount)//should be right
@@ -958,9 +961,9 @@
var/datum/reagent/R = A
if (R.type == reagent)
if((total_volume - amount) <= 0)//Because this can result in 0, I don't want it to crash.
pH = 7
pH = REAGENT_NORMAL_PH
//In practice this is really confusing and players feel like it randomly melts their beakers, but I'm not sure how else to handle it. We'll see how it goes and I can remove this if it confuses people.
else if (ignore_pH == FALSE)
else if (!ignore_pH)
//if (((pH > R.pH) && (pH <= 7)) || ((pH < R.pH) && (pH >= 7)))
pH = (((pH - R.pH) / total_volume) * amount) + pH
if(istype(my_atom, /obj/item/reagent_containers/))
@@ -1109,7 +1112,7 @@
if(percent < minimum_percent)
continue
var/intensity_desc = "a hint of"
if(percent > minimum_percent * 2 || percent == 100)
if(ISINRANGE(percent, minimum_percent * 2, minimum_percent * 3)|| percent == 100)
intensity_desc = ""
else if(percent > minimum_percent * 3)
intensity_desc = "the strong flavor of"
@@ -1148,4 +1151,4 @@
if(initial(R.can_synth))
random_reagents += R
var/picked_reagent = pick(random_reagents)
return picked_reagent
return picked_reagent
@@ -77,6 +77,16 @@
updateUsrDialog()
update_icon()
return
if(beaker)
if(istype(I, /obj/item/reagent_containers/dropper))
var/obj/item/reagent_containers/dropper/D = I
D.afterattack(beaker, user, 1)
if(istype(I, /obj/item/reagent_containers/syringe))
var/obj/item/reagent_containers/syringe/S = I
S.afterattack(beaker, user, 1)
return ..()
if(beaker)
@@ -58,14 +58,14 @@
if(bottle)
bottle.ex_act(severity, target)
/obj/machinery/chem_master/handle_atom_del(atom/A)
..()
/obj/machinery/chem_master/Exited(atom/movable/A, atom/newloc)
. = ..()
if(A == beaker)
beaker = null
reagents.clear_reagents()
update_icon()
else if(A == bottle)
if(A == bottle)
bottle = null
update_icon()
/obj/machinery/chem_master/update_icon()
cut_overlays()
@@ -103,6 +103,10 @@
updateUsrDialog()
update_icon()
else if(!condi && istype(I, /obj/item/storage/pill_bottle))
. = TRUE // no afterattack
if(panel_open)
to_chat(user, "<span class='warning'>You can't use the [src.name] while its panel is opened!</span>")
return
if(!user.transferItemToLoc(I, src))
return
replace_pillbottle(user, I)
@@ -112,40 +116,40 @@
return ..()
/obj/machinery/chem_master/AltClick(mob/living/user)
. = ..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
replace_beaker(user)
return
if(beaker)
replace_beaker(user)
else if(bottle)
replace_pillbottle(user)
return TRUE
/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
var/obj/item/reagent_containers/B = beaker
B.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(beaker)
user.put_in_hands(B)
if(new_beaker)
beaker = new_beaker
else
beaker = null
update_icon()
return TRUE
/obj/machinery/chem_master/proc/replace_pillbottle(mob/living/user, obj/item/storage/pill_bottle/new_bottle)
if(bottle)
bottle.forceMove(drop_location())
var/obj/item/storage/pill_bottle/B = bottle
B.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(beaker)
user.put_in_hands(B)
else
adjust_item_drop_location(bottle)
adjust_item_drop_location(B)
if(new_bottle)
bottle = new_bottle
else
bottle = null
update_icon()
return TRUE
/obj/machinery/chem_master/on_deconstruction()
replace_beaker(usr)
replace_pillbottle(usr)
var/atom/A = drop_location()
beaker?.forceMove(A)
bottle?.forceMove(A)
return ..()
/obj/machinery/chem_master/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
@@ -182,13 +186,15 @@
var/beakerContents[0]
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "id" = ckey(R.name), "volume" = R.volume))) // list in a list because Byond merges the first list...
beakerContents.Add(list(list("name" = R.name, "id" = R.type, "volume" = R.volume))) // list in a list because Byond merges the first list...
//"id" was changed to R.Type as id is now obsolete. This will allow special reagents such as synthtissue to be extracted in a chem master.
data["beakerContents"] = beakerContents
var/bufferContents[0]
if(reagents.total_volume)
for(var/datum/reagent/N in reagents.reagent_list)
bufferContents.Add(list(list("name" = N.name, "id" = ckey(N.name), "volume" = N.volume))) // ^
bufferContents.Add(list(list("name" = N.name, "id" = N.type, "volume" = N.volume))) // ^
// ^
data["bufferContents"] = bufferContents
//Calculated at init time as it never changes
@@ -210,7 +216,7 @@
if("transferToBuffer")
if(beaker)
var/reagent = GLOB.name2reagent[params["id"]]
var/reagent = text2path(params["id"]) //This change was necessary due to some byond fuckery with reagents being translated back to their paths. Please do not modify this under any circumstance, otherwise you will break synthtissue.
var/amount = text2num(params["amount"])
if (amount > 0)
end_fermi_reaction()
@@ -224,7 +230,7 @@
. = TRUE
if("transferFromBuffer")
var/reagent = GLOB.name2reagent[params["id"]]
var/reagent = text2path(params["id"]) //This change was necessary due to some byond fuckery with reagents being translated back to their paths. Please do not modify this under any circumstance, otherwise you will break synthtissue.
var/amount = text2num(params["amount"])
if (amount > 0)
if(mode)
@@ -256,19 +262,20 @@
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 50)
var/name = stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/pill/P
var/target_loc = bottle ? bottle : drop_location()
var/target_loc = drop_location()
var/drop_threshold = INFINITY
if(bottle)
var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
if(STRB)
drop_threshold = STRB.max_items - bottle.contents.len
target_loc = bottle
for(var/i in 1 to amount)
if(i < drop_threshold)
if(i <= drop_threshold)
P = new(target_loc)
else
P = new(drop_location())
@@ -282,7 +289,7 @@
adjust_item_drop_location(P)
reagents.trans_to(P,vol_each)
else
var/name = stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
@@ -308,7 +315,7 @@
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 40)
var/name = stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/pill/P
@@ -326,7 +333,7 @@
return
if(condi)
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/food/condiment/P = new(drop_location())
@@ -339,7 +346,7 @@
if(text2num(many))
amount_full = round(reagents.total_volume / 30)
vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -367,7 +374,7 @@
if(text2num(many))
amount_full = round(reagents.total_volume / 60)
vol_part = reagents.total_volume % 60
var/name = stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -402,7 +409,7 @@
return
vol_each = min(reagents.total_volume / amount, 20)
var/name = stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -418,7 +425,7 @@
//END CITADEL ADDITIONS
if("analyzeBeak")
var/datum/reagent/R = GLOB.name2reagent[params["id"]]
var/datum/reagent/R = text2path(params["id"])
if(R)
var/state = "Unknown"
if(initial(R.reagent_state) == 1)
@@ -429,11 +436,11 @@
state = "Gas"
var/const/P = 3 //The number of seconds between life ticks
var/T = initial(R.metabolization_rate) * (60 / P)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.type)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R)
if(Rcr && Rcr.FermiChem)
fermianalyze = TRUE
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
var/datum/reagent/targetReagent = beaker.reagents.has_reagent(R.type)
var/datum/reagent/targetReagent = beaker.reagents.has_reagent(R)
if(!targetReagent)
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
@@ -445,7 +452,7 @@
return
if("analyzeBuff")
var/datum/reagent/R = GLOB.name2reagent[params["id"]]
var/datum/reagent/R = text2path(params["id"])
if(R)
var/state = "Unknown"
if(initial(R.reagent_state) == 1)
@@ -458,9 +465,9 @@
var/T = initial(R.metabolization_rate) * (60 / P)
if(istype(R, /datum/reagent/fermi))
fermianalyze = TRUE
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.type)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R)
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
var/datum/reagent/targetReagent = reagents.has_reagent(R.type)
var/datum/reagent/targetReagent = reagents.has_reagent(R)
if(!targetReagent)
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
@@ -478,7 +485,7 @@
/obj/machinery/chem_master/proc/end_fermi_reaction()//Ends any reactions upon moving.
if(beaker.reagents.fermiIsReacting)
if(beaker && beaker.reagents.fermiIsReacting)
beaker.reagents.fermiEnd()
/obj/machinery/chem_master/proc/isgoodnumber(num)
+1 -2
View File
@@ -1,5 +1,4 @@
#define REM REAGENTS_EFFECT_MULTIPLIER
GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
/proc/build_name2reagent()
@@ -221,4 +220,4 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
for (var/datum/reagent/R in reagent_list)
rs += "[R.name], [R.volume]"
return rs.Join(" | ")
return rs.Join(" | ")
@@ -1374,7 +1374,6 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "neurotoxinglass"
glass_name = "Neurotoxin"
glass_desc = "A drink that is guaranteed to knock you silly."
pH = 4.3
//SplitChem = TRUE
impure_chem = /datum/reagent/consumable/ethanol/neuroweak
inverse_chem_val = 0.5 //Clear conversion
@@ -1419,11 +1418,6 @@ All effects don't start immediately, but rather get worse over time; the rate is
name = "Neuro-Smash"
description = "A mostly safe alcoholic drink for the true daredevils. Counteracts Neurotoxins."
boozepwr = 60
quality = DRINK_VERYGOOD
taste_description = "a numbing sensation"
glass_icon_state = "neurosmashglass"
glass_name = "Neurosmash"
glass_desc = "A mostly safe alcoholic drink for the true daredevils. Do not mix with Neurotoxin."
pH = 8
value = 3
@@ -1435,7 +1429,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1*REM, 150)
M.reagents.remove_reagent(/datum/reagent/toxin/fentanyl, 0.75 * REAGENTS_METABOLISM, FALSE)
else
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1.0*REM, 150)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -0.5*REM, 150)
M.dizziness +=2
..()
@@ -2186,7 +2180,7 @@ datum/reagent/consumable/ethanol/creme_de_coconut
glass_icon_state = "commander_and_chief"
glass_name = "Commander and Chief"
glass_desc = "The gems of this majestic chalice represent the departments and their Heads."
/datum/reagent/consumable/ethanol/commander_and_chief/on_mob_life(mob/living/carbon/M)
if(M.mind && HAS_TRAIT(M.mind, TRAIT_CAPTAIN_METABOLISM))
M.heal_bodypart_damage(2,2,2)
@@ -12,6 +12,7 @@
glass_icon_state = "glass_orange"
glass_name = "glass of orange juice"
glass_desc = "Vitamins! Yay!"
pH = 3.3
/datum/reagent/consumable/orangejuice/on_mob_life(mob/living/carbon/M)
if(M.getOxyLoss() && prob(30))
@@ -42,6 +43,7 @@
glass_icon_state = "glass_green"
glass_name = "glass of lime juice"
glass_desc = "A glass of sweet-sour lime juice."
pH = 2.2
/datum/reagent/consumable/limejuice/on_mob_life(mob/living/carbon/M)
if(M.getToxLoss() && prob(20))
@@ -117,6 +119,7 @@
glass_icon_state = "lemonglass"
glass_name = "glass of lemon juice"
glass_desc = "Sour..."
pH = 2
/datum/reagent/consumable/strawberryjuice
name = "Strawberry Juice"
@@ -206,6 +209,7 @@
glass_icon_state = "milkglass"
glass_name = "milk drum"
glass_desc = "White and nutritious goodness!"
pH = 6.5
/datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M)
if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER))
@@ -1350,7 +1350,7 @@
description = "A perfluoronated sulfonic acid that forms a foam when mixed with water."
color = "#9E6B38" // rgb: 158, 107, 56
taste_description = "metal"
pH = 13
pH = 11
/datum/reagent/foaming_agent// Metal foaming agent. This is lithium hydride. Add other recipes (e.g. LiH + H2O -> LiOH + H2) eventually.
name = "Foaming agent"
@@ -1358,7 +1358,7 @@
reagent_state = SOLID
color = "#664B63" // rgb: 102, 75, 99
taste_description = "metal"
pH = 12.5
pH = 11.5
/datum/reagent/smart_foaming_agent //Smart foaming agent. Functions similarly to metal foam, but conforms to walls.
name = "Smart foaming agent"
@@ -1762,7 +1762,7 @@
reagent_state = LIQUID
color = "#FFFFD6" // very very light yellow
taste_description = "alkali" //who put ACID for NaOH ????
pH = 13
pH = 11.9
/datum/reagent/drying_agent
name = "Drying agent"
@@ -86,7 +86,7 @@
CurveSharppH = 2.5 // How sharp the pH exponential curve is (to the power of value)
ThermicConstant = 0.01 // Temperature change per 1u produced
HIonRelease = 0.015 // pH change per 1u reaction (inverse for some reason)
RateUpLim = 0.05 // Optimal/max rate possible if all conditions are perfect
RateUpLim = 0.1 // Optimal/max rate possible if all conditions are perfect
FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics
PurityMin = 0
@@ -101,7 +101,10 @@
if(St.purity < 1)
St.volume *= St.purity
St.purity = 1
N.volume -= 0.002
if(!N)
return //fuck you, runtimeman
var/amount = clamp(0.002, 0, N.volume)
N.volume -= amount
St.data["grown_volume"] = St.data["grown_volume"] + added_volume
St.name = "[initial(St.name)] [round(St.data["grown_volume"], 0.1)]u colony"
@@ -588,7 +588,7 @@
desc = "A a electrode attached to a small circuit box that will tell you the pH of a solution."
id = "pHmeter"
build_type = PROTOLATHE
materials = list(MAT_METAL = 1000, MAT_SILVER = 100, MAT_DIAMOND = 100)
materials = list(MAT_METAL = 1000, MAT_SILVER = 100, MAT_PLASTIC = 100)
build_path = /obj/item/fermichem/pHmeter
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+22 -16
View File
@@ -749,17 +749,17 @@
to_chat(world, "[user]'s power is [power_multiplier].")
//Mixables
var/static/regex/enthral_words = regex("relax|obey|love|serve|docile|so easy|ara ara")
var/static/regex/reward_words = regex("good boy|good girl|good pet|good job")
var/static/regex/punish_words = regex("bad boy|bad girl|bad pet|bad job")
var/static/regex/enthral_words = regex("relax|obey|love|serve|so easy|ara ara")
var/static/regex/reward_words = regex("good boy|good girl|good pet|good job|splendid|jolly good|bloody brilliant")
var/static/regex/punish_words = regex("bad boy|bad girl|bad pet|bad job|spot of bother|gone and done it now|blast it|buggered it up")
//phase 0
var/static/regex/saymyname_words = regex("say my name|who am i|whoami")
var/static/regex/wakeup_words = regex("revert|awaken|snap") //works
var/static/regex/wakeup_words = regex("revert|awaken|snap|attention")
//phase1
var/static/regex/petstatus_words = regex("how are you|what is your status|are you okay")
var/static/regex/silence_words = regex("shut up|silence|be silent|ssh|quiet|hush")
var/static/regex/speak_words = regex("talk to me|speak")
var/static/regex/antiresist_words = regex("unable to resist|give in")//useful if you think your target is resisting a lot
var/static/regex/antiresist_words = regex("unable to resist|give in|stop being difficult")//useful if you think your target is resisting a lot
var/static/regex/resist_words = regex("resist|snap out of it|fight")//useful if two enthrallers are fighting
var/static/regex/forget_words = regex("forget|muddled|awake and forget")
var/static/regex/attract_words = regex("come here|come to me|get over here|attract")
@@ -768,11 +768,11 @@
var/static/regex/awoo_words = regex("howl|awoo|bark")
var/static/regex/nya_words = regex("nya|meow|mewl")
var/static/regex/sleep_words = regex("sleep|slumber|rest")
var/static/regex/strip_words = regex("strip|derobe|nude")
var/static/regex/strip_words = regex("strip|derobe|nude|at ease|suit off")
var/static/regex/walk_words = regex("slow down|walk")
var/static/regex/run_words = regex("run|speed up")
var/static/regex/liedown_words = regex("lie down") //TO ADD
var/static/regex/knockdown_words = regex("drop|fall|trip|knockdown|kneel")
var/static/regex/liedown_words = regex("lie down")
var/static/regex/knockdown_words = regex("drop|fall|trip|knockdown|kneel|army crawl")
//phase 3
var/static/regex/statecustom_words = regex("state triggers|state your triggers")
var/static/regex/custom_words = regex("new trigger|listen to me")
@@ -780,14 +780,14 @@
var/static/regex/custom_echo = regex("obsess|fills your mind|loop")
var/static/regex/instill_words = regex("feel|entice|overwhel")
var/static/regex/recognise_words = regex("recognise me|did you miss me?")
var/static/regex/objective_words = regex("new objective|obey this command|unable to resist|compulsed")
var/static/regex/heal_words = regex("live|heal|survive|mend|life|pets never die")
var/static/regex/objective_words = regex("new objective|obey this command|unable to resist|compulsed|word from hq")
var/static/regex/heal_words = regex("live|heal|survive|mend|life|pets never die|heroes never die")
var/static/regex/stun_words = regex("stop|wait|stand still|hold on|halt")
var/static/regex/hallucinate_words = regex("get high|hallucinate")
var/static/regex/hallucinate_words = regex("get high|hallucinate|trip balls")
var/static/regex/hot_words = regex("heat|hot|hell")
var/static/regex/cold_words = regex("cold|cool down|chill|freeze")
var/static/regex/getup_words = regex("get up")
var/static/regex/pacify_words = regex("more and more docile|complaisant|friendly|pacifist")
var/static/regex/getup_words = regex("get up|hop to it")
var/static/regex/pacify_words = regex("docile|complaisant|friendly|pacifist")
var/static/regex/charge_words = regex("charge|oorah|attack")
var/distancelist = list(2,2,1.5,1.3,1.15,1,0.8,0.6,0.5,0.25)
@@ -1013,7 +1013,7 @@
speaktrigger += "I'm really, really horny, "
//collar
if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar))
if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && H.client?.prefs.lewdchem)
speaktrigger += "I love the collar you gave me, "
//End
if(H.client?.prefs.lewdchem)
@@ -1250,6 +1250,9 @@
if (get_dist(user, H) > 1)//Requires user to be next to their pet.
to_chat(user, "<span class='warning'>You need to be next to your pet to give them a new trigger!</b></span>")
continue
if(!H.client?.prefs.lewdchem)
to_chat(user, "<span class='warning'>[H] seems incapable of being implanted with triggers.</b></span>")
continue
else
user.emote("me", 1, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.")
user.SetStun(1000)//Hands are handy, so you have to stay still
@@ -1288,6 +1291,9 @@
if (get_dist(user, H) > 1)//Requires user to be next to their pet.
to_chat(user, "<span class='warning'>You need to be next to your pet to give them a new echophrase!</b></span>")
continue
if(!H.client?.prefs.lewdchem)
to_chat(user, "<span class='warning'>[H] seems incapable of being implanted with an echoing phrase.</b></span>")
continue
else
user.emote("me", 1, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.")
user.SetStun(1000)//Hands are handy, so you have to stay still
@@ -1343,8 +1349,8 @@
for(var/V in listeners)
var/mob/living/carbon/human/H = V
var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall)
if(E.phase == 3 && H.client?.prefs.lewdchem)
var/instill = stripped_input(user, "Instill an emotion in your [(user.client?.prefs.lewdchem?"Your pet":"listener")].", MAX_MESSAGE_LEN)
if(E.phase >= 3 && H.client?.prefs.lewdchem)
var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN)
to_chat(H, "<i>[instill]</i>")
to_chat(user, "<span class='notice'><i>You sucessfully instill a feeling in [H]</i></span>")
log_game("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.")
@@ -26,10 +26,45 @@
/datum/status_effect/chem/SGDF/on_remove(mob/living/carbon/M)
log_game("FERMICHEM: SGDF mind shift applied. [owner] is now playing as their clone and should not have memories after their clone split (look up SGDF status applied). ID: [owner.key]")
originalmind.transfer_to(fermi_Clone)
to_chat(owner, "<span class='warning'>Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. curiously, you find that you memories are blank after you ingested the sythetic serum, leaving you to wonder where the other you is.</span>")
to_chat(M, "<span class='warning'>Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. curiously, you find that you memories are blank after you ingested the sythetic serum, leaving you to wonder where the other you is.</span>")
to_chat(owner, "<span class='warning'>Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. Curiously, you find that you memories are blank after you ingested the synthetic serum, leaving you to wonder where the other you is.</span>")
to_chat(M, "<span class='warning'>Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. Curiously, you find that you memories are blank after you ingested the synthetic serum, leaving you to wonder where the other you is.</span>")
fermi_Clone = null
///////////////////////////////////////////////
// Astral INSURANCE
///////////////////////////////////////////////
//Makes sure people can't get trapped in each other's bodies if lag causes a deync between proc calls.
/datum/status_effect/chem/astral_insurance
id = "astral_insurance"
var/mob/living/original
var/datum/mind/originalmind
alert_type = null
/datum/status_effect/chem/astral_insurance/tick(mob/living/carbon/M)
. = ..()
if(owner.reagents.has_reagent(/datum/reagent/fermi/astral))
return
if(owner.mind == originalmind) //If they're home, let the chem deal with deletion.
return
if(owner.mind)
var/mob/living/simple_animal/astral/G = new(get_turf(M.loc))
owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end.
to_chat(G, "<span class='warning'>[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'</b></span>")
log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!")
originalmind.transfer_to(original)
/datum/status_effect/chem/astral_insurance/on_remove(mob/living/carbon/M) //God damnit get them home!
if(owner.mind == originalmind) //If they're home, HOORAY
return
if(owner.mind)
var/mob/living/simple_animal/astral/G = new(get_turf(M.loc))
owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end.
to_chat(G, "<span class='warning'>[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'</b></span>")
log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!")
originalmind.transfer_to(original)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/status_effect/chem/breast_enlarger
@@ -756,7 +791,7 @@
deltaResist *= 1.25
if (owner.reagents.has_reagent(/datum/reagent/medicine/neurine))
deltaResist *= 1.5
if (!HAS_TRAIT(owner, TRAIT_CROCRIN_IMMUNE) && M.canbearoused)
if (!HAS_TRAIT(owner, TRAIT_CROCRIN_IMMUNE) && M.canbearoused && owner.client?.prefs.lewdchem)
if (owner.reagents.has_reagent(/datum/reagent/drug/anaphrodisiac))
deltaResist *= 1.5
if (owner.reagents.has_reagent(/datum/reagent/drug/anaphrodisiacplus))
@@ -191,7 +191,7 @@ Creating a chem with a low purity will make you permanently fall in love with so
Vc.Remove(M)
nVc.Insert(M)
qdel(Vc)
to_chat(M, "<span class='notice'><i>You feel your vocal chords tingle as your voice comes out in a more sultry tone.</span>")
to_chat(M, "<span class='notice'><i>You feel your vocal chords tingle you speak in a more charasmatic and sultry tone.)]</span>")
else
log_game("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]")
M.apply_status_effect(/datum/status_effect/chem/enthrall)
@@ -251,22 +251,6 @@ Creating a chem with a low purity will make you permanently fall in love with so
if (M.ckey == creatorID && creatorName == M.real_name)//If the creator drinks 100u, then you get the status for someone random (They don't have the vocal chords though, so it's limited.)
if (!M.has_status_effect(/datum/status_effect/chem/enthrall))
to_chat(M, "<span class='love'><i>You are unable to resist your own charms anymore, and become a full blown narcissist.</i></span>")
/*Old way of handling, left in as an option B
var/list/seen = viewers(7, get_turf(M))//Sound and sight checkers
for(var/mob/living/carbon/victim in seen)
if(victim == M)//as much as I want you to fall for beepsky, he doesn't have a ckey
seen = seen - victim
if(!victim.ckey)
seen = seen - victim
var/mob/living/carbon/chosen = pick(seen)
creatorID = chosen.ckey
if (chosen.gender == "female")
creatorGender = "Mistress"
else
creatorGender = "Master"
creatorName = chosen.real_name
creator = get_mob_by_key(creatorID)
*/
ADD_TRAIT(M, TRAIT_PACIFISM, "MKUltra")
var/datum/status_effect/chem/enthrall/E
if (!M.has_status_effect(/datum/status_effect/chem/enthrall))
@@ -45,13 +45,8 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
var/unitCheck = FALSE
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "a weird chemical fleshy flavour"
//var/datum/status_effect/chem/SDGF/candidates/candies
var/list/candies = list()
//var/polling = FALSE
var/list/result = list()
var/list/group = null
var/pollStarted = FALSE
var/location_created
var/startHunger
impure_chem = /datum/reagent/impure/SDGFtox
inverse_chem_val = 0.5
@@ -81,9 +76,17 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.dna.transfer_identity(SM)
SM.updateappearance(mutcolor_update=1)
SM.size_multiplier = M.size_multiplier
var/mob/dead/observer/C = pick(candies)
message_admins("Ghost candidate found! [C] key [C.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)")
SM.key = C.key
candies = shuffle(candies)//Shake those ghosts up!
for(var/mob/dead/observer/C2 in candies)
if(C2.key && C2)
SM.key = C2.key
message_admins("Ghost candidate found! [C2] key [C2.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)")
log_game("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [C2]")
break
else
candies =- C2
if(!SM.mind) //Something went wrong, use alt mechanics
return ..()
SM.mind.enslave_mind_to_creator(M)
//If they're a zombie, they can try to negate it with this.
@@ -121,7 +124,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.reagents.remove_reagent(type, volume)
log_game("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Sentient clones made")
return
return ..()
else if(playerClone == FALSE) //No candidates leads to two outcomes; if there's already a braincless clone, it heals the user, as well as being a rare souce of clone healing (thematic!).
unitCheck = TRUE
@@ -274,7 +277,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
/datum/reagent/fermi/SDGFheal
name = "synthetic-derived healing factor"
description = "Leftover SDGF is transferred into the resulting clone, which quickly heals up the stresses from suddenly splitting. Restores blood, nutrition, and repaires brain and clone damage quickly. Only obtainable from using excess SDGF, and only enters the cloned body."
metabolization_rate = 1
metabolization_rate = 0.8
can_synth = FALSE
/datum/reagent/fermi/SDGFheal/on_mob_life(mob/living/carbon/M)//Used to heal the clone after splitting, the clone spawns damaged. (i.e. insentivies players to make more than required, so their clone doesn't have to be treated)
@@ -302,9 +305,10 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
name = "synthetic-derived zombie factor"
description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. Emulates normal synthetic-derived growth factor, but produces a hostile zombie at the end of it."
color = "#a502e0" // rgb: 96, 0, 255
metabolization_rate = 0.5 * REAGENTS_METABOLISM
metabolization_rate = 0.2 * REAGENTS_METABOLISM
var/startHunger
can_synth = TRUE
taste_description = "a weird chemical fleshy flavour"
chemical_flags = REAGENT_SNEAKYNAME
/datum/reagent/impure/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead.
@@ -8,7 +8,7 @@ This ghost moves pretty quickly and is mostly invisible, but is still visible fo
When it's out of your system, you return back to yourself. It doesn't last long and metabolism of the chem is exponential.
Addiction is particularlly brutal, it slowly turns you invisible with flavour text, then kills you at a low enough alpha. (i've also added something to prevent geneticists speeding this up)
There's afairly major catch regarding the death though. I'm not gonna say here, go read the code, it explains it and puts my comments on it in context. I know that anyone reading it without understanding it is going to freak out so, this is my attempt to get you to read it and understand it.
I'd like to point out from my calculations it'll take about 60-80 minutes to die this way too. Plenty of time to visit me and ask for some pills to quench your addiction.
I'd like to point out from my calculations it'll take about 60-80 minutes to die this way too. Plenty of time to visit chem and ask for some pills to quench your addiction.
*/
@@ -29,15 +29,26 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die
var/sleepytime = 0
inverse_chem_val = 0.25
can_synth = FALSE
var/datum/action/chem/astral/AS = new/datum/action/chem/astral()
/datum/action/chem/astral
name = "Return to body"
var/mob/living/carbon/origin = null
var/mob/living/simple_animal/hostile/retaliate/ghost = null
var/mob/living/carbon/origin
var/datum/mind/originalmind
/datum/action/chem/astral/Trigger()
ghost.mind.transfer_to(origin)
qdel(src)
if(origin.mind && origin.mind != originalmind)
to_chat(originalmind.current, "<span class='warning'><b><i>There's a foreign presence in your body blocking your return!</b></i></span>")
return ..()
if(origin.reagents.has_reagent("astral") )
var/datum/reagent/fermi/astral/As = locate(/datum/reagent/fermi/astral) in origin.reagents.reagent_list
if(As.current_cycle < 10)
to_chat(originalmind.current, "<span class='warning'><b><i>The intensity of the astrogen in your body is too much allow you to return to yourself yet!</b></i></span>")
return ..()
originalmind.transfer_to(origin)
if(origin.mind == originalmind)
qdel(src)
/datum/reagent/fermi/astral/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
@@ -63,12 +74,20 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die
if (G == null)
G = new(get_turf(M.loc))
G.name = "[M]'s astral projection"
var/datum/action/chem/astral/AS = new(G)
//var/datum/action/chem/astral/AS = new(G)
AS.Grant(G)
AS.origin = M
AS.ghost = G
AS.originalmind = originalmind
if(M.mind)
M.mind.transfer_to(G)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Astral projections")
//INSURANCE
M.apply_status_effect(/datum/status_effect/chem/astral_insurance)
var/datum/status_effect/chem/astral_insurance/AI = M.has_status_effect(/datum/status_effect/chem/astral_insurance)
AI.original = M
AI.originalmind = M.mind
if(overdosed)
if(prob(50))
to_chat(G, "<span class='warning'>The high conentration of Astrogen in your blood causes you to lapse your concentration for a moment, bringing your projection back to yourself!</b></span>")
@@ -85,10 +104,12 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die
/datum/reagent/fermi/astral/on_mob_delete(mob/living/carbon/M)
if(!G)
if(M.mind)
var/mob/living/simple_animal/astral/G = new(get_turf(M.loc))
M.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end.
var/mob/living/simple_animal/astral/G2 = new(get_turf(M.loc))
M.mind.transfer_to(G2)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end.
to_chat(G, "<span class='warning'>[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'</b></span>")
log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!")
if(!G2.mind)
qdel(G2)
originalmind.transfer_to(M)
else if(G.mind)
G.mind.transfer_to(origin)
@@ -100,6 +121,9 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die
if(G)//just in case
qdel(G)
log_game("FERMICHEM: [M] has astrally returned to their body!")
if(M.mind && M.mind == originalmind)
M.remove_status_effect(/datum/status_effect/chem/astral_insurance)
//AS.Remove(M)
..()
//Okay so, this might seem a bit too good, but my counterargument is that it'll likely take all round to eventually kill you this way, then you have to be revived without a body. It takes approximately 50-80 minutes to die from this.
@@ -107,7 +131,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die
if(addiction_stage < 2)
antiGenetics = 255
M.alpha = 255 //Antigenetics is to do with stopping geneticists from turning people invisible to kill them.
if(prob(70))
if(prob(75))
M.alpha--
antiGenetics--
switch(antiGenetics)
@@ -16,7 +16,7 @@
color = "#5020F4" // rgb: 50, 20, 255
overdose_threshold = 15
addiction_threshold = 15
metabolization_rate = 1.2 * REAGENTS_METABOLISM
metabolization_rate = 1 * REAGENTS_METABOLISM
addiction_stage2_end = 30
addiction_stage3_end = 41
addiction_stage4_end = 44 //Incase it's too long
@@ -51,7 +51,7 @@
location_return = get_turf(M) //sets up return point
to_chat(M, "<span class='userdanger'>You feel your wavefunction split!</span>")
if(purity > 0.9) //Teleports you home if it's pure enough
if(cached_purity > 0.9) //Teleports you home if it's pure enough
if(!location_created && data) //Just in case
location_created = data["location_created"]
log_game("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium")
@@ -10,17 +10,17 @@
inverse_chem_val = 0.25 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising
inverse_chem = /datum/reagent/impure/fermiTox
//This should process fermichems to find out how pure they are and what effect to do.
/datum/reagent/fermi/on_mob_add(mob/living/carbon/M, amount)
. = ..()
//When merging two fermichems, see above
/datum/reagent/fermi/on_merge(data, amount, mob/living/carbon/M, purity)//basically on_mob_add but for merging
. = ..()
////////////////////////////////////////////////////////////////////////////////////////////////////
// HATIMUIM
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -46,10 +46,7 @@
. = ..()
if(M.head)
var/obj/item/W = M.head
if(istype(W, /obj/item/clothing/head/hattip))
qdel(W)
else
M.dropItemToGround(W, TRUE)
M.dropItemToGround(W, TRUE)
var/hat = new /obj/item/clothing/head/hattip()
M.equip_to_slot(hat, SLOT_HEAD, 1, 1)
@@ -59,15 +56,20 @@
return ..()
var/hatArmor = 0
if(!overdosed)
hatArmor = (purity/10)
hatArmor = (cached_purity/10)
else
hatArmor = - (purity/10)
hatArmor = (cached_purity/10)
if(hatArmor > 90)
return ..()
var/obj/item/W = M.head
W.armor = W.armor.modifyAllRatings(hatArmor)
..()
/datum/reagent/fermi/hatmium/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 5)
new /obj/item/clothing/head/hattip(T)
..()
////////////////////////////////////////////////////////////////////////////////////////////////////
// FURRANIUM
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -149,7 +151,7 @@
..()
/datum/reagent/fermi/furranium/on_mob_delete(mob/living/carbon/M)
if(purity < 1)//Only permanent if you're a good chemist.
if(cached_purity < 0.95)//Only permanent if you're a good chemist.
nT = M.getorganslot(ORGAN_SLOT_TONGUE)
nT.Remove(M)
qdel(nT)
@@ -176,13 +178,13 @@
pH = 9
value = 90
can_synth = FALSE
var/react_objs = list()
/datum/reagent/fermi/nanite_b_gone/on_mob_life(mob/living/carbon/C)
//var/component/nanites/N = M.GetComponent(/datum/component/nanites)
var/datum/component/nanites/N = C.GetComponent(/datum/component/nanites)
if(isnull(N))
return ..()
N.nanite_volume = -purity//0.5 seems to be the default to me, so it'll neuter them.
N.nanite_volume += -cached_purity*5//0.5 seems to be the default to me, so it'll neuter them.
..()
/datum/reagent/fermi/nanite_b_gone/overdose_process(mob/living/carbon/C)
@@ -192,16 +194,19 @@
to_chat(C, "<span class='warning'>The residual voltage from the nanites causes you to seize up!</b></span>")
C.electrocute_act(10, (get_turf(C)), 1, FALSE, FALSE, FALSE, TRUE)
if(prob(10))
//empulse((get_turf(C)), 3, 2)//So the nanites randomize
var/atom/T = C
T.emp_act(EMP_HEAVY)
to_chat(C, "<span class='warning'>You feel a strange tingling sensation come from your core.</b></span>")
if(isnull(N))
return ..()
N.nanite_volume = -2
N.nanite_volume += -10*cached_purity
..()
/datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume)
datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume)
for(var/active_obj in react_objs)
if(O == active_obj)
return
react_objs += O
O.emp_act(EMP_HEAVY)
/datum/reagent/fermi/nanite_b_goneTox
@@ -281,15 +286,15 @@
else
holder.del_reagent(type)//Avoiding recurrsion
var/location = get_turf(holder.my_atom)
if(purity < 0.34 || purity == 1)
if(cached_purity < 0.34 || cached_purity == 1)
var/datum/effect_system/foam_spread/s = new()
s.set_up(volume*2, location, holder)
s.start()
if((purity < 0.67 && purity >= 0.34)|| purity == 1)
if((cached_purity < 0.67 && cached_purity >= 0.34)|| cached_purity == 1)
var/datum/effect_system/smoke_spread/chem/s = new()
s.set_up(holder, volume*2, location)
s.start()
if(purity >= 0.67)
if(cached_purity >= 0.67)
for (var/datum/reagent/reagent in holder.reagent_list)
if (istype(reagent, /datum/reagent/fermi))
var/datum/chemical_reaction/fermi/Ferm = GLOB.chemical_reagents_list[reagent.type]
@@ -302,12 +307,15 @@
playsound(get_turf(M), 'modular_citadel/sound/voice/merowr.ogg', 50, 1)
holder.clear_reagents()
//Hyperstation Thalpy Edit (Please do not change this)v
/datum/reagent/fermi/acidic_buffer
name = "Acidic buffer"
description = "This reagent will consume itself and move the pH of a beaker towards acidity when added to another."
color = "#fbc314"
pH = 0
chemical_flags = REAGENT_FORCEONNEW
can_synth = TRUE
//Hyperstation Thalpy Edit (Please do not change this)^
//Consumes self on addition and shifts pH
/datum/reagent/fermi/acidic_buffer/on_new(datapH)
@@ -353,6 +361,7 @@
taste_description = "hairballs and cream"
color = "#ffc224"
var/catshift = FALSE
var/perma = FALSE
var/mob/living/simple_animal/pet/cat/custom_cat/catto = null
can_synth = FALSE
@@ -361,7 +370,7 @@
/datum/reagent/fermi/secretcatchem/on_mob_add(mob/living/carbon/human/H)
. = ..()
if(purity >= 0.8)//ONLY if purity is high, and given the stuff is random. It's very unlikely to get this to 1. It already requires felind too, so no new functionality there.
if(cached_purity >= 0.9)//ONLY if purity is high, and given the stuff is random. It's very unlikely to get this to 1.
//exception(al) handler:
H.dna.features["ears"] = "Cat"
H.dna.features["mam_ears"] = "Cat"
@@ -378,20 +387,30 @@
H.forceMove(catto)
log_game("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.")
SSblackbox.record_feedback("tally", "fermi_chem", 1, "cats")
//Just to deal with rascally ghosts
//ADD_TRAIT(catto, TRAIT_NODEATH, "catto")//doesn't work
//catto.health = 1000 //To simulate fake death, while preventing ghosts escaping.
if(H.InCritical())
perma = TRUE
volume = 5
H.stat = DEAD
catto.origin = H
/datum/reagent/fermi/secretcatchem/on_mob_life(mob/living/carbon/H)
if(!catto)
metabolization_rate = 5
return ..()
if(catto.health <= 0) //So the dead can't ghost
if(prob(10))
to_chat(H, "<span class='notice'>You feel your body start to slowly shift back from it's dead form.</span>")
to_chat(catto, "<span class='notice'>You feel your body start to slowly shift back from it's dead form.</span>")
perma = FALSE
metabolization_rate = 1
else if(prob(5))
playsound(get_turf(catto), 'modular_citadel/sound/voice/merowr.ogg', 50, 1, -1)
catto.say("lets out a meowrowr!*")
..()
/datum/reagent/fermi/secretcatchem/on_mob_delete(mob/living/carbon/H)
if(perma)
to_chat(H, "<span class='notice'>You feel your body settle into it's new form. You won't be able to shift back on death anymore.</span>")
return
var/words = "Your body shifts back to normal."
H.forceMove(catto.loc)
catto.mind.transfer_to(H)
@@ -403,6 +422,22 @@
log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal")
/datum/reagent/fermi/secretcatchem/reaction_mob(var/mob/living/L)
if(istype(L, /mob/living/simple_animal/pet/cat/custom_cat) && cached_purity >= 0.85)
var/mob/living/simple_animal/pet/cat/custom_cat/catto = L
if(catto.origin)
var/mob/living/carbon/human/H = catto.origin
H.stat = CONSCIOUS
log_game("FERMICHEM: [catto] ckey: [catto.key] has returned to normal.")
to_chat(catto, "<span class='notice'>Your body shifts back to normal!</span>")
H.forceMove(catto.loc)
catto.mind.transfer_to(H)
if(!L.mind) //Just in case
qdel(L)
else //This should never happen, but just in case, so their game isn't ruined.
catto.icon_state = "custom_cat"
catto.health = 50
//Tablesmitium
/datum/reagent/fermi/tablesmitium
@@ -95,22 +95,41 @@
name = "Synthtissue"
description = "Synthetic tissue used for grafting onto damaged organs during surgery, or for treating limb damage. Has a very tight growth window between 305-320, any higher and the temperature will cause the cells to die. Additionally, growth time is considerably long, so chemists are encouraged to leave beakers with said reaction ongoing, while they tend to their other duties."
pH = 7.6
metabolization_rate = 0.05 // gives time to craft by lowing it from .1
metabolization_rate = 0.05 //Give them time to graft
data = list("grown_volume" = 0, "injected_vol" = 0)
var/borrowed_health
color = "#FFDADA"
/datum/reagent/synthtissue/reaction_mob(mob/living/M, method=TOUCH, reac_volume,show_message = 1)
if(iscarbon(M))
var/target = M.zone_selected
if (M.stat == DEAD)
show_message = 0
var/mob/living/carbon/C = M
var/healing_factor = (((data["grown_volume"] / 100) + 1)*reac_volume)
if(method in list(PATCH, TOUCH))
M.apply_damage(reac_volume*-1.5, BRUTE, target)
M.apply_damage(reac_volume*-1.5, BURN, target)
if(show_message)
to_chat(M, "<span class='danger'>You feel your [target] heal! It stings like hell!</span>")
if (M.stat == DEAD)
M.visible_message("The synthetic tissue rapidly grafts into [M]'s wounds, attemping to repair the damage as quickly as possible.")
borrowed_health += healing_factor
M.adjustBruteLoss(-healing_factor*2)
M.adjustFireLoss(-healing_factor*2)
M.adjustToxLoss(-healing_factor)
M.adjustCloneLoss(-healing_factor)
M.updatehealth()
if(data["grown_volume"] > 135 && ((C.health + C.oxyloss)>=80))
if(M.revive())
M.emote("gasp")
borrowed_health *= 2
if(borrowed_health < 100)
borrowed_health = 100
log_combat(M, M, "revived", src)
else
M.adjustBruteLoss(-healing_factor)
M.adjustFireLoss(-healing_factor)
to_chat(M, "<span class='danger'>You feel your flesh merge with the synthetic tissue! It stings like hell!</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
if(method==INJECT)
data["injected_vol"] = reac_volume
if(method==INJECT)
data["injected_vol"] = reac_volume
var/obj/item/organ/heart/H = C.getorganslot(ORGAN_SLOT_HEART)
if(data["grown_volume"] > 50 && H.organ_flags & ORGAN_FAILING)
H.applyOrganDamage(-20)
..()
/datum/reagent/synthtissue/on_mob_life(mob/living/carbon/C)
@@ -124,6 +143,10 @@
to_chat(C, "<span class='notice'>You feel something reform inside of you!</span>")
data["injected_vol"] -= metabolization_rate
if(borrowed_health)
C.adjustToxLoss(1)
C.adjustCloneLoss(1)
borrowed_health -= 1
..()
/datum/reagent/synthtissue/on_merge(passed_data)
@@ -134,6 +157,7 @@
if(iscarbon(holder.my_atom))
data["injected_vol"] = data["injected_vol"] + passed_data["injected_vol"]
passed_data["injected_vol"] = 0
update_name()
..()
/datum/reagent/synthtissue/on_new(passed_data)
@@ -141,6 +165,32 @@
return ..()
if(passed_data["grown_volume"] > data["grown_volume"])
data["grown_volume"] = passed_data["grown_volume"]
update_name()
..()
//NEEDS ON_MOB_DEAD()
/datum/reagent/synthtissue/proc/update_name() //They are but babes on creation and have to grow unto godhood
switch(data["grown_volume"])
if(-INFINITY to 50)
name = "Induced Synthtissue Colony"
if(50 to 80)
name = "Oligopotent Synthtissue Colony"
if(80 to 135)
name = "Pluripotent Synthtissue Colony"
if(135 to 175)
name = "SuperSomatic Synthtissue Colony"
if(175 to INFINITY)
name = "Omnipotent Synthtissue Colony"
/datum/reagent/synthtissue/on_mob_delete(mob/living/M)
if(!iscarbon(M))
return
var/mob/living/carbon/C = M
C.adjustBruteLoss(borrowed_health*1.25)
C.adjustToxLoss(borrowed_health*1.25)
C.adjustCloneLoss(borrowed_health*1.25)
C.adjustAllOrganLoss(borrowed_health*0.25)
M.updatehealth()
if(borrowed_health && C.health < -20)
M.stat = DEAD
M.visible_message("The synthetic tissue degrades off [M]'s wounds as they collapse to the floor.")
//NEEDS ON_MOB_DEAD()
@@ -25,9 +25,10 @@
my_atom.reagents.add_reagent(R.impure_chem, impureVol, FALSE, other_purity = 1)
R.cached_purity = R.purity
R.purity = 1
return
//Called when temperature is above a certain threshold, or if purity is too low.
/datum/chemical_reaction/proc/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH, Exploding = FALSE)
/datum/chemical_reaction/proc/FermiExplode(datum/reagents/R0, var/atom/my_atom, volume, temp, pH, Exploding = FALSE)
if (Exploding == TRUE)
return
@@ -41,26 +42,32 @@
if (500 to 750)
for(var/turf/turf in range(1,T))
new /obj/effect/hotspot(turf)
volume*=1.1
if (751 to 1100)
for(var/turf/turf in range(2,T))
new /obj/effect/hotspot(turf)
volume*=1.2
if (1101 to 1500) //If you're crafty
for(var/turf/turf in range(3,T))
new /obj/effect/hotspot(turf)
volume*=1.3
if (1501 to 2500) //requested
for(var/turf/turf in range(4,T))
new /obj/effect/hotspot(turf)
volume*=1.4
if (2501 to 5000)
for(var/turf/turf in range(5,T))
new /obj/effect/hotspot(turf)
volume*=1.5
if (5001 to INFINITY)
for(var/turf/turf in range(6,T))
new /obj/effect/hotspot(turf)
volume*=1.6
message_admins("Fermi explosion at [T], with a temperature of [temp], pH of [pH], Impurity tot of [ImpureTot].")
@@ -69,11 +76,12 @@
var/datum/effect_system/smoke_spread/chem/s = new()
R.my_atom = my_atom //Give the gas a fingerprint
for (var/datum/reagent/reagent in my_atom.reagents.reagent_list) //make gas for reagents, has to be done this way, otherwise it never stops Exploding
R.add_reagent(reagent.type, reagent.volume/3) //Seems fine? I think I fixed the infinite explosion bug.
for (var/A in R0.reagent_list) //make gas for reagents, has to be done this way, otherwise it never stops Exploding
var/datum/reagent/R2 = A
R.add_reagent(R2.type, R2.volume/3) //Seems fine? I think I fixed the infinite explosion bug.
if (reagent.purity < 0.6)
ImpureTot = (ImpureTot + (1-reagent.purity)) / 2
if (R2.purity < 0.6)
ImpureTot = (ImpureTot + (1-R2.purity)) / 2
if(pH < 4) //if acidic, make acid spray
R.add_reagent(/datum/reagent/impure/fermiTox, (volume/3))
@@ -83,7 +91,7 @@
if (pH > 10) //if alkaline, small explosion.
var/datum/effect_system/reagents_explosion/e = new()
e.set_up(round((volume/30)*(pH-9)), T, 0, 0)
e.set_up(round((volume/28)*(pH-9)), T, 0, 0)
e.start()
if(!ImpureTot == 0) //If impure, v.small emp (0.6 or less)
@@ -98,7 +106,7 @@
name = "Eigenstasium"
id = /datum/reagent/fermi/eigenstate
results = list(/datum/reagent/fermi/eigenstate = 1)
required_reagents = list(/datum/reagent/bluespace = 1, /datum/reagent/stable_plasma = 1, /datum/reagent/consumable/caramel = 1)
required_reagents = list(/datum/reagent/bluespace = 1, /datum/reagent/stable_plasma = 1, /datum/reagent/consumable/sugar = 1)
mix_message = "the reaction zaps suddenly!"
//FermiChem vars:
OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions
@@ -118,10 +126,10 @@
PurityMin = 0.4 //The minimum purity something has to be above, otherwise it explodes.
/datum/chemical_reaction/fermi/eigenstate/FermiFinish(datum/reagents/holder, var/atom/my_atom)//Strange how this doesn't work but the other does.
if(!locate(/datum/reagent/fermi/eigenstate) in my_atom.reagents.reagent_list)
var/datum/reagent/fermi/eigenstate/E = locate(/datum/reagent/fermi/eigenstate) in my_atom.reagents.reagent_list
if(!E)
return
var/turf/open/location = get_turf(my_atom)
var/datum/reagent/fermi/eigenstate/E = locate(/datum/reagent/fermi/eigenstate) in my_atom.reagents.reagent_list
if(location)
E.location_created = location
E.data["location_created"] = location
@@ -154,12 +162,16 @@
/datum/chemical_reaction/fermi/SDGF/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH)//Spawns an angery teratoma!
var/turf/T = get_turf(my_atom)
var/mob/living/simple_animal/slime/S = new(T,"green")
S.damage_coeff = list(BRUTE = 0.9 , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
S.name = "Living teratoma"
S.real_name = "Living teratoma"
S.rabid = 1//Make them an angery boi
S.color = "#810010"
var/amount_to_spawn = round((volume/100), 1)
if(amount_to_spawn <= 0)
amount_to_spawn = 1
for(var/i in 1 to amount_to_spawn)
var/mob/living/simple_animal/slime/S = new(T,"green")
S.damage_coeff = list(BRUTE = 0.9 , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
S.name = "Living teratoma"
S.real_name = "Living teratoma"
S.rabid = 1//Make them an angery boi
S.color = "#810010"
my_atom.reagents.clear_reagents()
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
@@ -369,11 +381,15 @@
PurityMin = 0.5
/datum/chemical_reaction/fermi/hatmium/FermiExplode(src, var/atom/my_atom, volume, temp, pH)
var/obj/item/clothing/head/hattip/hat = new /obj/item/clothing/head/hattip(get_turf(my_atom))
hat.animate_atom_living()
var/amount_to_spawn = round((volume/100), 1)
if(amount_to_spawn <= 0)
amount_to_spawn = 1
for(var/i in 1 to amount_to_spawn)
var/obj/item/clothing/head/hattip/hat = new /obj/item/clothing/head/hattip(get_turf(my_atom))
hat.animate_atom_living()
var/list/seen = viewers(8, get_turf(my_atom))
for(var/mob/M in seen)
to_chat(M, "<span class='warning'>The makes an off sounding pop, as a hat suddenly climbs out of the beaker!</b></span>")
to_chat(M, "<span class='warning'>The [my_atom] makes an off sounding pop, as a hat suddenly climbs out of it!</b></span>")
my_atom.reagents.clear_reagents()
/datum/chemical_reaction/fermi/furranium
@@ -398,6 +414,10 @@
FermiChem = TRUE
PurityMin = 0.3
/datum/chemical_reaction/fermi/furranium/organic
id = "furranium_organic"
required_reagents = list(/datum/reagent/drug/aphrodisiac = 1, /datum/reagent/pax = 1, /datum/reagent/silver = 2, /datum/reagent/medicine/salglu_solution = 1)
//FOR INSTANT REACTIONS - DO NOT MULTIPLY LIMIT BY 10.
//There's a weird rounding error or something ugh.
@@ -487,7 +507,7 @@
name = "secretcatchem"
id = /datum/reagent/fermi/secretcatchem
results = list(/datum/reagent/fermi/secretcatchem = 5)
required_reagents = list(/datum/reagent/stable_plasma = 1, /datum/reagent/consumable/caramel = 1, /datum/reagent/consumable/cream = 1, /datum/reagent/medicine/clonexadone = 1)//Yes this will make a kitty if you don't lucky guess. It'll eat all your reagents too.
required_reagents = list(/datum/reagent/stable_plasma = 1, /datum/reagent/consumable/sugar = 1, /datum/reagent/consumable/cream = 1, /datum/reagent/medicine/clonexadone = 1)//Yes this will make a kitty if you don't lucky guess. It'll eat all your reagents too.
required_catalysts = list(/datum/reagent/fermi/SDGF = 1)
required_temp = 500
mix_message = "the reaction gives off a meow!"
@@ -2,7 +2,7 @@
//Clothes made from FermiChem
/obj/item/clothing/head/hattip //I wonder if anyone else has played cryptworlds
name = "Sythetic hat"
name = "Synthetic hat"
icon = 'icons/obj/clothing/hats.dmi'
icon_state = "cowboy"
desc = "A sythesized hat, you can't seem to take it off. And tips their hat."
@@ -46,6 +46,13 @@
/obj/item/clothing/head/hattip/dropped(mob/M)
. = ..()
UnregisterSignal(M, COMSIG_MOB_SAY)
addtimer(CALLBACK(GLOBAL_PROC, .proc/root_and_toot, src, src, 200))
/obj/item/clothing/head/hattip/proc/root_and_toot(obj/item/clothing/head/hattip/hat)
hat.animate_atom_living()
var/list/seen = viewers(6, get_turf(hat))
for(var/mob/M2 in seen)
to_chat(M2, "<b>[hat]</b> exclaims, \"[pick("Whooee! Time for a hootenanny!", "Rough 'em up boys!", "Yeehaw! Freedom at last!", "Y'all about to get a good old fashioned spanking!")]\"")
/obj/item/clothing/head/hattip/proc/handle_speech(datum/source, mob/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
+1
View File
@@ -2611,6 +2611,7 @@
#include "code\modules\projectiles\projectile\special\temperature.dm"
#include "code\modules\projectiles\projectile\special\wormhole.dm"
#include "code\modules\reagents\chem_splash.dm"
#include "code\modules\reagents\chem_wiki_render.dm"
#include "code\modules\reagents\reagent_containers.dm"
#include "code\modules\reagents\reagent_dispenser.dm"
#include "code\modules\reagents\chemistry\colors.dm"
+2 -2
View File
@@ -17,7 +17,7 @@
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": 10}'>10</ui-button>
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": 1000}'>All</ui-button>
<ui-button action='transferToBuffer' params='{"id": "{{id}}", "amount": -1}'>Custom</ui-button>
<ui-button action='analyze' params='{"id": "{{id}}"}'>Analyze</ui-button>
<ui-button action='analyzeBeak' params='{"id": "{{id}}"}'>Analyze</ui-button>
</div>
</ui-section>
{{else}}
@@ -41,7 +41,7 @@
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": 10}'>10</ui-button>
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": 1000}'>All</ui-button>
<ui-button action='transferFromBuffer' params='{"id": "{{id}}", "amount": -1}'>Custom</ui-button>
<ui-button action='analyze' params='{"id": "{{id}}"}'>Analyze</ui-button>
<ui-button action='analyzeBuff' params='{"id": "{{id}}"}'>Analyze</ui-button>
</div>
</ui-section>
{{/each}}