From 4558110dfbd43e716050e06ef526849dcf217dfd Mon Sep 17 00:00:00 2001 From: Fermi Date: Mon, 11 Mar 2019 18:21:09 +0000 Subject: [PATCH 01/61] aaaa what did I doooo Github pains me greatly --- code/__DEFINES/reagents.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index f8f59a367f..ccfbd1a627 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -2,6 +2,11 @@ #define LIQUID 2 #define GAS 3 +#define REAGENT_NORMAL_PH 7.000 +#define REAGENT_PH_ACCURACY 0.001 +#define REAGENT_PURITY_ACCURACY 0.001 +#define DEFAULT_SPECIFIC_HEAT 200 + // container_type defines #define INJECTABLE (1<<0) // Makes it possible to add reagents through droppers and syringes. #define DRAWABLE (1<<1) // Makes it possible to remove reagents through syringes. From 8e2775bbe3baec8092790892f75b1bdfdf446c65 Mon Sep 17 00:00:00 2001 From: Fermi Date: Thu, 14 Mar 2019 03:27:25 +0000 Subject: [PATCH 02/61] A few changes (mix edit for Neko) MeowMeowMeowMeowMeowMeowMeow --- .../chemistry/Fermi_Chemistry_notes.txt | 54 +++++++++ code/modules/reagents/chemistry/holder.dm | 106 ++++++++++-------- .../reagents/chemistry/recipes/medicine.dm | 13 +++ tgstation.dme | 7 +- 4 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt diff --git a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt new file mode 100644 index 0000000000..36b4d169aa --- /dev/null +++ b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt @@ -0,0 +1,54 @@ +Cit/main/Chemistry notes + +SEE README.MD FOR FUNCTIONS + +~Main folder: \ss13\Citadel-Station-13\code\modules\reagents\chemistry~ + +~Recipies: \ss13\Citadel-Station-13\code\modules\reagents\chemistry\recipes~ +This contains the reaction recipies and thats it. +name, id, results, required_reagents, required_catalysts, mix_message, required_temp +To add: a lot + +eg:{ + /datum/chemical_reaction/charcoal + name = "Charcoal" + id = "charcoal" + results = list("charcoal" = 2) + required_reagents = list("ash" = 1, "sodiumchloride" = 1) + mix_message = "The mixture yields a fine black powder." + required_temp = 380 + required_catalysts = list("plasma" = 5) + } + +How the end state should look:{ + /datum/chemical_reaction/bicaridine + name = "Bicaridine" + id = "bicaridine" + results = list("bicaridine" = 3) + required_reagents = list("carbon" = 1, "oxygen" = 1, "sugar" = 1) + OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reations + OptimalTempMax = 500 // Upper end for above + ExplodeTemp = 550 //Temperature at which reaction explodes + OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reations (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + ThermicConstant = -2.5 //Temperature change per 1u produced + HIonRelease = 0.01 //pH change per 1u reaction + RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect + optional: + mix_message = "The mixture yields a fine black powder." + required_catalysts = list("plasma" = 5) + + edit: + required_temp = 380 +} + +~\ss13\Citadel-Station-13\code/modules/reagents/chemistry/holder.dm~ +Where the actual reaction takes place, main edit location. +About half way where I've commented (WHY IS THERE NO LINE NUMBERS?!) + + +~\ss13\Citadel-Station-13\tgui\src\interfaces~ +This contains the 4 scripts for generation of the UI for operation of the various chemical equipments. diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 252d0d0dc3..baf1df7788 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -48,6 +48,7 @@ var/maximum_volume = 100 var/atom/my_atom = null var/chem_temp = 150 + var/pH = REAGENT_NORMAL_PH var/last_tick = 1 var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() @@ -182,7 +183,9 @@ var/transfer_amount = T.volume * part if(preserve_data) trans_data = copy_data(T) - R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, no_react = 1) //we only handle reaction after every reagent has been transfered. + + //fermichem Added ph and T.purity + R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. remove_reagent(T.id, transfer_amount) update_total() @@ -242,7 +245,7 @@ if(current_reagent.id == reagent) if(preserve_data) trans_data = current_reagent.data - R.add_reagent(current_reagent.id, amount, trans_data, src.chem_temp) + R.add_reagent(current_reagent.id, amount, trans_data, src.chem_temp, pH, current_reagent.purity, no_react = TRUE) //Fermichem edit remove_reagent(current_reagent.id, amount, 1) break @@ -332,19 +335,19 @@ R.on_update (A) update_total() -/datum/reagents/proc/handle_reactions() - var/list/cached_reagents = reagent_list - var/list/cached_reactions = GLOB.chemical_reactions_list - var/datum/cached_my_atom = my_atom - if(reagents_holder_flags & REAGENT_NOREACT) +/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + var/list/cached_reagents = reagent_list //a list of the reagents? + var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? + var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! + if(reagents_holder_flags & REAGENT_NOREACT) //Not sure on reagents_holder_flags, but I think it checks to see if theres a reaction with current stuff. return //Yup, no reactions here. No siree. - var/reaction_occurred = 0 - do - var/list/possible_reactions = list() - reaction_occurred = 0 - for(var/reagent in cached_reagents) - var/datum/reagent/R = reagent + var/reaction_occurred = 0 // checks if reaction, binary variable + do //What does do do in byond? It sounds very redundant? is it a while loop? + var/list/possible_reactions = list() //init list + reaction_occurred = 0 // sets it back to 0? + for(var/reagent in cached_reagents) //for reagent in beaker/holder + var/datum/reagent/R = reagent //check to make sure that reagent is there for the reaction list for(var/reaction in cached_reactions[R.id]) // Was a big list but now it should be smaller since we filtered it with our reagent id if(!reaction) continue @@ -377,26 +380,30 @@ matching_container = 1 else - if(cached_my_atom.type == C.required_container) + if(cached_my_atom.type == C.required_container)//if the container requires a certain type, and if it equals what it needs? matching_container = 1 if (isliving(cached_my_atom) && !C.mob_react) //Makes it so certain chemical reactions don't occur in mobs return - if(!C.required_other) - matching_other = 1 + if(!C.required_other)//Checks for other things required + matching_other = 1//binary check passes - else if(istype(cached_my_atom, /obj/item/slime_extract)) + else if(istype(cached_my_atom, /obj/item/slime_extract))//if the object is a slime_extract. This might be complicated as to not break them via fermichem var/obj/item/slime_extract/M = cached_my_atom if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this matching_other = 1 else - if(!C.required_container) + if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? matching_container = 1 if(!C.required_other) matching_other = 1 - if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp)) - meets_temp_requirement = 1 + //FermiChem + if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + //explode function!! + + if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! + meets_temp_requirement = 1//binary pass if(!has_special_react || C.check_special_react(src)) can_special_react = 1 @@ -404,33 +411,44 @@ if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other && meets_temp_requirement && can_special_react) possible_reactions += C - if(possible_reactions.len) + if(possible_reactions.len)//does list exist? var/datum/chemical_reaction/selected_reaction = possible_reactions[1] //select the reaction with the most extreme temperature requirements - for(var/V in possible_reactions) - var/datum/chemical_reaction/competitor = V + for(var/V in possible_reactions)//why V, surely that would indicate volume? V is the reaction potential. + var/datum/chemical_reaction/competitor = V //competitor? I think this is theres two of them. Troubling..! if(selected_reaction.is_cold_recipe) //if there are no recipe conflicts, everything in possible_reactions will have this same value for is_cold_reaction. warranty void if assumption not met. - if(competitor.required_temp <= selected_reaction.required_temp) + if(competitor.required_temp <= selected_reaction.required_temp)//only returns with lower if reaction "is cold" var. selected_reaction = competitor else - if(competitor.required_temp >= selected_reaction.required_temp) + if(competitor.required_temp >= selected_reaction.required_temp) //will return with the hotter reacting first. selected_reaction = competitor - var/list/cached_required_reagents = selected_reaction.required_reagents - var/list/cached_results = selected_reaction.results - var/special_react_result = selected_reaction.check_special_react(src) - var/list/multiplier = INFINITY - for(var/B in cached_required_reagents) - multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B])) + var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list + var/list/cached_results = selected_reaction.results//resultant chemical list + var/list/multiplier = INFINITY //Wat + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + //FermiChem + if (purity != 1)//if purity of reaction isn't 1 + multiplierProd = multiplier * purity //adjusts multiplier to be in line with purity + multiplierTox = multiplier - multiplierProd // + for(var/B in cached_required_reagents) - remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - for(var/P in selected_reaction.results) + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P) - add_reagent(P, cached_results[P]*multiplier, null, chem_temp) + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + //add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: + //FermiChem + if (purity != 1)//if purity of reaction isn't 1 + add_reagent(P, cached_results[P]*multiplierProd, null, chem_temp)//add reagent function for product + add_reagent(P, cached_results[P]*multiplierTox, null, chem_temp)//add reagent function for product + else + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! - var/list/seen = viewers(4, get_turf(my_atom)) + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers var/iconhtml = icon2html(cached_my_atom, seen) if(cached_my_atom) if(!ismob(cached_my_atom)) // No bubbling mobs @@ -440,7 +458,7 @@ for(var/mob/M in seen) to_chat(M, "[iconhtml] [selected_reaction.mix_message]") - if(istype(cached_my_atom, /obj/item/slime_extract)) + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. var/obj/item/slime_extract/ME2 = my_atom ME2.Uses-- if(ME2.Uses <= 0) // give the notification that the slime core is dead @@ -452,9 +470,9 @@ selected_reaction.on_reaction(src, multiplier, special_react_result) reaction_occurred = 1 - while(reaction_occurred) - update_total() - return 0 + while(reaction_occurred)//while do nothing? + update_total()//Don't know waht this does. + return 0//end! /datum/reagents/proc/isolate_reagent(reagent) var/list/cached_reagents = reagent_list @@ -544,7 +562,7 @@ var/S = specific_heat() chem_temp = CLAMP(chem_temp + (J / (S * total_volume)), 2.7, 1000) -/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0) +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ if(!isnum(amount) || !amount) return FALSE @@ -555,7 +573,7 @@ if(!D) WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") return FALSE - + update_total() var/cached_total = total_volume if(cached_total + amount > maximum_volume) @@ -599,9 +617,9 @@ if(data) R.data = data R.on_new(data) - + if(isliving(my_atom)) - R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete + R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete update_total() if(my_atom) my_atom.on_reagent_change(ADD_REAGENT) diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index dc7c32d925..deccc47768 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -208,6 +208,19 @@ id = "bicaridine" results = list("bicaridine" = 3) required_reagents = list("carbon" = 1, "oxygen" = 1, "sugar" = 1) + //FermiChem vars: + OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 500 // Upper end for above + ExplodeTemp = 550 //Temperature at which reaction explodes + OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + ThermicConstant = -2.5 //Temperature change per 1u produced + HIonRelease = 0.01 //pH change per 1u reaction + RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect + FermiChem = 1 /datum/chemical_reaction/kelotane name = "Kelotane" diff --git a/tgstation.dme b/tgstation.dme index c43b1a7019..268d4f1ff9 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2528,15 +2528,10 @@ #include "code\modules\research\techweb\all_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" -#include "code\modules\research\xenobiology\crossbreeding\__corecross.dm" -#include "code\modules\research\xenobiology\crossbreeding\_clothing.dm" -#include "code\modules\research\xenobiology\crossbreeding\_misc.dm" -#include "code\modules\research\xenobiology\crossbreeding\_mobs.dm" +#include "code\modules\research\xenobiology\crossbreeding\_corecross.dm" #include "code\modules\research\xenobiology\crossbreeding\_status_effects.dm" -#include "code\modules\research\xenobiology\crossbreeding\_weapons.dm" #include "code\modules\research\xenobiology\crossbreeding\burning.dm" #include "code\modules\research\xenobiology\crossbreeding\charged.dm" -#include "code\modules\research\xenobiology\crossbreeding\chilling.dm" #include "code\modules\research\xenobiology\crossbreeding\consuming.dm" #include "code\modules\research\xenobiology\crossbreeding\industrial.dm" #include "code\modules\research\xenobiology\crossbreeding\prismatic.dm" From 1d9bf5b3b42e0e0a8e60dfccbcd21a0666a24107 Mon Sep 17 00:00:00 2001 From: JMFrench Date: Mon, 1 Apr 2019 18:01:39 +0100 Subject: [PATCH 03/61] Moonsugar Added Moonsugar effects --- code/modules/reagents/chemistry/reagents/other_reagents.dm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 4b4f118a9c..bb049e74d8 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1251,7 +1251,7 @@ L.remove_trait(TRAIT_SLEEPIMMUNE, id) ..() -/datum/reagent/stimulum/on_mob_life(mob/living/carbon/M) +/datum/reagent/stimulum/on_mob_life(mob/living/carbon/M) M.adjustStaminaLoss(-2*REM, 0) current_cycle++ holder.remove_reagent(id, 0.99) //Gives time for the next tick of life(). @@ -1863,3 +1863,8 @@ description = "The primary precursor for an ancient feline delicacy known as skooma. While it has no notable effects on it's own, mixing it with morphine in a chilled container may yield interesting results." color = "#FAEAFF" taste_description = "synthetic catnip" + +/datum/reagent/moonsugar/on_mob_life(mob/living/carbon/M) + if(prob(20)) + to_chat(M, "You find yourself unable to supress the desire to meow!") + M.emote("nya") From 5113b3aabc9af7f1801b9f324f699a59f809840b Mon Sep 17 00:00:00 2001 From: Fermi Date: Fri, 12 Apr 2019 00:42:01 +0100 Subject: [PATCH 04/61] Added eigenstate chem effects, need to add reaction vars. --- .../chemistry/reagents/fermi_reagents.dm | 101 ++++++++++++++++++ .../reagents/chemistry/recipes/fermi.dm | 18 ++++ .../code/datums/mood_events/chem_events.dm | 3 + .../chemistry/reagents/fermi_reagents.dm | 101 ++++++++++++++++++ .../reagents/chemistry/recipes/fermi.dm | 0 tgstation.dme | 4 +- 6 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 code/modules/reagents/chemistry/reagents/fermi_reagents.dm create mode 100644 code/modules/reagents/chemistry/recipes/fermi.dm create mode 100644 modular_citadel/code/datums/mood_events/chem_events.dm create mode 100644 modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm create mode 100644 modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm diff --git a/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/code/modules/reagents/chemistry/reagents/fermi_reagents.dm new file mode 100644 index 0000000000..dcf933c183 --- /dev/null +++ b/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -0,0 +1,101 @@ +//Fermichem!! +//Fun chems for all the family + +//MCchem +//BE PE chemical +//Angel/astral chemical + +//eigenstate Chem +//Teleports you to chemistry and back +//OD teleports you randomly around the Station +//Addiction send you on a wild ride and replaces you with an alternative reality version of yourself. + +/datum/reagent/fermi/eigenstate + name = "Eigenstasium" + id = "eigenstate" + description = "A strange mixture formed from a controlled reaction of bluespace with plasma, that causes localised eigenstate fluxuations within the patient" + color = "#60A584" // rgb: 96, 0, 255 + overdose_threshold = 20 + addiction_threshold = 30 + metabolization_rate = 0.5 * REAGENTS_METABOLISM + addiction_stage3_end = 40 + addiction_stage4_end = 55 //Incase it's too long + +/obj/item/reagent/fermi/eigenstate/Initialize() + //. = ..() Unneeded? + var/turf/open/T = get_turf(src)//Sets up coordinate of where it was created + +/datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! + if(holder.!has_reagent("eigenstate")) + var/turf/open/T2 = get_turf(src) //sets up return point + to_chat(M, "You feel your wavefunction split!") + do_sparks(5,FALSE,src) + src.forceMove(T) //Teleports to creation location + do_sparks(5,FALSE,src) + +/datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location + do_sparks(5,FALSE,src) + to_chat(M, "You feel your wavefunction collapse!") + src.forceMove(T2) //Teleports home + do_sparks(5,FALSE,src) + +/datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly + if(10) + to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") + M.Jitter(10) + + if(15 to INFINITY) + do_sparks(5,FALSE,src) + do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') + do_sparks(5,FALSE,src) + M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting + + + //..() //loop function + + +/datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride. + to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") + M.Jitter(10) + M.nutrition = M.nutrition - (M.nutrition/10) + +/datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M) + to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") + M.Jitter(50) + M.AdjustKnockdown(-40, 0) + for(var/obj/item/I in mob.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); + +/datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! + M.Jitter(100) + M.AdjustKnockdown(-40, 0) + to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") + + //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in + if(1) + var/typepath = owner.type + clone = new typepath(owner.loc) + var/mob/living/carbon/O = owner + var/mob/living/carbon/C = clone + if(istype(C) && istype(O)) + C.real_name = O.real_name + O.dna.transfer_identity(C) + C.updateappearance(mutcolor_update=1) + visible_message("[M] collapses in from an alternative reality!") + if(2) + do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + if(3) + qdel(C) //Deletes CLONE, or at least I hope it is. + visible_message("[M] is snapped across to a different alternative reality!") + .=1 //counter + + do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly + //..() //loop function + +/datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. + M.Jitter(50) + M.AdjustKnockdown(0, 0) + to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your pervious self, sent to god knows what universe.") + mob.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) + +//eigenstate END diff --git a/code/modules/reagents/chemistry/recipes/fermi.dm b/code/modules/reagents/chemistry/recipes/fermi.dm new file mode 100644 index 0000000000..cc9b5b1915 --- /dev/null +++ b/code/modules/reagents/chemistry/recipes/fermi.dm @@ -0,0 +1,18 @@ +/datum/chemical_reaction/eigenstate + name = "Eigenstasium" + id = "eigenstate" + results = list("Eigenstasium" = ``) + required_reagents = list("bluespace_" = 1, "oxygen" = 1, "sugar" = 1) + //FermiChem vars: + OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 500 // Upper end for above + ExplodeTemp = 550 //Temperature at which reaction explodes + OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + ThermicConstant = -2.5 //Temperature change per 1u produced + HIonRelease = 0.01 //pH change per 1u reaction + RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect + FermiChem = 1 diff --git a/modular_citadel/code/datums/mood_events/chem_events.dm b/modular_citadel/code/datums/mood_events/chem_events.dm new file mode 100644 index 0000000000..6748838f2f --- /dev/null +++ b/modular_citadel/code/datums/mood_events/chem_events.dm @@ -0,0 +1,3 @@ +/datum/mood_event/eigenstate + mood_change = -1 + description = "Where the hell am I? Is this an alternative reality?\n" diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm new file mode 100644 index 0000000000..dcf933c183 --- /dev/null +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -0,0 +1,101 @@ +//Fermichem!! +//Fun chems for all the family + +//MCchem +//BE PE chemical +//Angel/astral chemical + +//eigenstate Chem +//Teleports you to chemistry and back +//OD teleports you randomly around the Station +//Addiction send you on a wild ride and replaces you with an alternative reality version of yourself. + +/datum/reagent/fermi/eigenstate + name = "Eigenstasium" + id = "eigenstate" + description = "A strange mixture formed from a controlled reaction of bluespace with plasma, that causes localised eigenstate fluxuations within the patient" + color = "#60A584" // rgb: 96, 0, 255 + overdose_threshold = 20 + addiction_threshold = 30 + metabolization_rate = 0.5 * REAGENTS_METABOLISM + addiction_stage3_end = 40 + addiction_stage4_end = 55 //Incase it's too long + +/obj/item/reagent/fermi/eigenstate/Initialize() + //. = ..() Unneeded? + var/turf/open/T = get_turf(src)//Sets up coordinate of where it was created + +/datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! + if(holder.!has_reagent("eigenstate")) + var/turf/open/T2 = get_turf(src) //sets up return point + to_chat(M, "You feel your wavefunction split!") + do_sparks(5,FALSE,src) + src.forceMove(T) //Teleports to creation location + do_sparks(5,FALSE,src) + +/datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location + do_sparks(5,FALSE,src) + to_chat(M, "You feel your wavefunction collapse!") + src.forceMove(T2) //Teleports home + do_sparks(5,FALSE,src) + +/datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly + if(10) + to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") + M.Jitter(10) + + if(15 to INFINITY) + do_sparks(5,FALSE,src) + do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') + do_sparks(5,FALSE,src) + M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting + + + //..() //loop function + + +/datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride. + to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") + M.Jitter(10) + M.nutrition = M.nutrition - (M.nutrition/10) + +/datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M) + to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") + M.Jitter(50) + M.AdjustKnockdown(-40, 0) + for(var/obj/item/I in mob.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); + +/datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! + M.Jitter(100) + M.AdjustKnockdown(-40, 0) + to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") + + //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in + if(1) + var/typepath = owner.type + clone = new typepath(owner.loc) + var/mob/living/carbon/O = owner + var/mob/living/carbon/C = clone + if(istype(C) && istype(O)) + C.real_name = O.real_name + O.dna.transfer_identity(C) + C.updateappearance(mutcolor_update=1) + visible_message("[M] collapses in from an alternative reality!") + if(2) + do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + if(3) + qdel(C) //Deletes CLONE, or at least I hope it is. + visible_message("[M] is snapped across to a different alternative reality!") + .=1 //counter + + do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly + //..() //loop function + +/datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. + M.Jitter(50) + M.AdjustKnockdown(0, 0) + to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your pervious self, sent to god knows what universe.") + mob.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) + +//eigenstate END diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tgstation.dme b/tgstation.dme index 268d4f1ff9..b14ffbc44c 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2528,7 +2528,6 @@ #include "code\modules\research\techweb\all_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" -#include "code\modules\research\xenobiology\crossbreeding\_corecross.dm" #include "code\modules\research\xenobiology\crossbreeding\_status_effects.dm" #include "code\modules\research\xenobiology\crossbreeding\burning.dm" #include "code\modules\research\xenobiology\crossbreeding\charged.dm" @@ -2773,6 +2772,7 @@ #include "modular_citadel\code\datums\components\material_container.dm" #include "modular_citadel\code\datums\components\phantomthief.dm" #include "modular_citadel\code\datums\components\souldeath.dm" +#include "modular_citadel\code\datums\mood_events\chem_events.dm" #include "modular_citadel\code\datums\mood_events\generic_negative_events.dm" #include "modular_citadel\code\datums\mood_events\generic_positive_events.dm" #include "modular_citadel\code\datums\mood_events\moodular.dm" @@ -2954,7 +2954,9 @@ #include "modular_citadel\code\modules\projectiles\guns\energy\laser.dm" #include "modular_citadel\code\modules\projectiles\projectile\energy.dm" #include "modular_citadel\code\modules\projectiles\projectiles\reusable.dm" +#include "modular_citadel\code\modules\reagents\chemistry\reagents\fermi_reagents.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\other_reagents.dm" +#include "modular_citadel\code\modules\reagents\chemistry\recipies\fermi.dm" #include "modular_citadel\code\modules\reagents\reagent container\cit_kegs.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypospraymkii.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypovial.dm" From f059a19d8bcb91473b115239daa5c788195de41d Mon Sep 17 00:00:00 2001 From: Fermi Date: Fri, 12 Apr 2019 00:44:54 +0100 Subject: [PATCH 05/61] Made plastic&metamaterial beakers slightly larger cause no one uses them --- .../chemistry/reagents/fermi_reagents.dm | 101 ------------------ .../reagents/chemistry/recipes/fermi.dm | 18 ---- .../reagents/reagent_containers/glass.dm | 12 +-- 3 files changed, 6 insertions(+), 125 deletions(-) delete mode 100644 code/modules/reagents/chemistry/reagents/fermi_reagents.dm delete mode 100644 code/modules/reagents/chemistry/recipes/fermi.dm diff --git a/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/code/modules/reagents/chemistry/reagents/fermi_reagents.dm deleted file mode 100644 index dcf933c183..0000000000 --- a/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ /dev/null @@ -1,101 +0,0 @@ -//Fermichem!! -//Fun chems for all the family - -//MCchem -//BE PE chemical -//Angel/astral chemical - -//eigenstate Chem -//Teleports you to chemistry and back -//OD teleports you randomly around the Station -//Addiction send you on a wild ride and replaces you with an alternative reality version of yourself. - -/datum/reagent/fermi/eigenstate - name = "Eigenstasium" - id = "eigenstate" - description = "A strange mixture formed from a controlled reaction of bluespace with plasma, that causes localised eigenstate fluxuations within the patient" - color = "#60A584" // rgb: 96, 0, 255 - overdose_threshold = 20 - addiction_threshold = 30 - metabolization_rate = 0.5 * REAGENTS_METABOLISM - addiction_stage3_end = 40 - addiction_stage4_end = 55 //Incase it's too long - -/obj/item/reagent/fermi/eigenstate/Initialize() - //. = ..() Unneeded? - var/turf/open/T = get_turf(src)//Sets up coordinate of where it was created - -/datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! - if(holder.!has_reagent("eigenstate")) - var/turf/open/T2 = get_turf(src) //sets up return point - to_chat(M, "You feel your wavefunction split!") - do_sparks(5,FALSE,src) - src.forceMove(T) //Teleports to creation location - do_sparks(5,FALSE,src) - -/datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location - do_sparks(5,FALSE,src) - to_chat(M, "You feel your wavefunction collapse!") - src.forceMove(T2) //Teleports home - do_sparks(5,FALSE,src) - -/datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly - if(10) - to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") - M.Jitter(10) - - if(15 to INFINITY) - do_sparks(5,FALSE,src) - do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') - do_sparks(5,FALSE,src) - M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting - - - //..() //loop function - - -/datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride. - to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") - M.Jitter(10) - M.nutrition = M.nutrition - (M.nutrition/10) - -/datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M) - to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") - M.Jitter(50) - M.AdjustKnockdown(-40, 0) - for(var/obj/item/I in mob.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); - -/datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! - M.Jitter(100) - M.AdjustKnockdown(-40, 0) - to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") - - //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in - if(1) - var/typepath = owner.type - clone = new typepath(owner.loc) - var/mob/living/carbon/O = owner - var/mob/living/carbon/C = clone - if(istype(C) && istype(O)) - C.real_name = O.real_name - O.dna.transfer_identity(C) - C.updateappearance(mutcolor_update=1) - visible_message("[M] collapses in from an alternative reality!") - if(2) - do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! - if(3) - qdel(C) //Deletes CLONE, or at least I hope it is. - visible_message("[M] is snapped across to a different alternative reality!") - .=1 //counter - - do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly - //..() //loop function - -/datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. - M.Jitter(50) - M.AdjustKnockdown(0, 0) - to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your pervious self, sent to god knows what universe.") - mob.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) - -//eigenstate END diff --git a/code/modules/reagents/chemistry/recipes/fermi.dm b/code/modules/reagents/chemistry/recipes/fermi.dm deleted file mode 100644 index cc9b5b1915..0000000000 --- a/code/modules/reagents/chemistry/recipes/fermi.dm +++ /dev/null @@ -1,18 +0,0 @@ -/datum/chemical_reaction/eigenstate - name = "Eigenstasium" - id = "eigenstate" - results = list("Eigenstasium" = ``) - required_reagents = list("bluespace_" = 1, "oxygen" = 1, "sugar" = 1) - //FermiChem vars: - OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions - OptimalTempMax = 500 // Upper end for above - ExplodeTemp = 550 //Temperature at which reaction explodes - OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) - OptimalpHMax = 9.5 // Higest value for above - ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) - CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) - CurveSharp = 4 // How sharp the exponential curve is (to the power of value) - ThermicConstant = -2.5 //Temperature change per 1u produced - HIonRelease = 0.01 //pH change per 1u reaction - RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 1912e9fe9d..2dc5059eb2 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -167,12 +167,12 @@ /obj/item/reagent_containers/glass/beaker/plastic name = "x-large beaker" - desc = "An extra-large beaker. Can hold up to 120 units." + desc = "An extra-large beaker. Can hold up to 150 units." icon_state = "beakerwhite" materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000) - volume = 120 + volume = 150 amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(5,10,15,20,25,30,60,120) + possible_transfer_amounts = list(5,10,15,20,25,30,60,120, 150) /obj/item/reagent_containers/glass/beaker/plastic/update_icon() icon_state = "beakerlarge" // hack to lets us reuse the large beaker reagent fill states @@ -181,12 +181,12 @@ /obj/item/reagent_containers/glass/beaker/meta name = "metamaterial beaker" - desc = "A large beaker. Can hold up to 180 units." + desc = "A large beaker. Can hold up to 200 units." icon_state = "beakergold" materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000, MAT_GOLD=1000, MAT_TITANIUM=1000) - volume = 180 + volume = 200 amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(5,10,15,20,25,30,60,120,180) + possible_transfer_amounts = list(5,10,15,20,25,30,60,120,150,200) /obj/item/reagent_containers/glass/beaker/noreact name = "cryostasis beaker" From 28ffc996f72c4b9a68a07fbdc068df7cd6146233 Mon Sep 17 00:00:00 2001 From: Fermi Date: Fri, 12 Apr 2019 05:10:00 +0100 Subject: [PATCH 06/61] Added synthetic-derived growth factor amonst some bugfixes. --- .../chemistry/Fermi_Chemistry_notes.txt | 4 + .../reagents/reagent_containers/glass.dm | 2 +- .../code/datums/mood_events/chem_events.dm | 2 +- .../code/datums/status_effects/chems.dm | 25 ++++++ .../chemistry/reagents/fermi_reagents.dm | 84 +++++++++++++++++-- .../reagents/chemistry/recipes/fermi.dm | 46 ++++++++++ tgstation.dme | 1 + 7 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 modular_citadel/code/datums/status_effects/chems.dm diff --git a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt index 36b4d169aa..ac40b9ddd9 100644 --- a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt +++ b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt @@ -3,6 +3,7 @@ Cit/main/Chemistry notes SEE README.MD FOR FUNCTIONS ~Main folder: \ss13\Citadel-Station-13\code\modules\reagents\chemistry~ +~ADD NEW FILES TO tgstation.dme~ ~Recipies: \ss13\Citadel-Station-13\code\modules\reagents\chemistry\recipes~ This contains the reaction recipies and thats it. @@ -49,6 +50,9 @@ How the end state should look:{ Where the actual reaction takes place, main edit location. About half way where I've commented (WHY IS THERE NO LINE NUMBERS?!) +~\ss13\Citadel-Station-13\code/modules/reagents/chemistry/reagents~ +Where what the reactions do, the code that sets what they do. + ~\ss13\Citadel-Station-13\tgui\src\interfaces~ This contains the 4 scripts for generation of the UI for operation of the various chemical equipments. diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 2dc5059eb2..58085f3497 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -172,7 +172,7 @@ materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000) volume = 150 amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(5,10,15,20,25,30,60,120, 150) + possible_transfer_amounts = list(5,10,15,20,25,30,60,120,150) /obj/item/reagent_containers/glass/beaker/plastic/update_icon() icon_state = "beakerlarge" // hack to lets us reuse the large beaker reagent fill states diff --git a/modular_citadel/code/datums/mood_events/chem_events.dm b/modular_citadel/code/datums/mood_events/chem_events.dm index 6748838f2f..b1280c3559 100644 --- a/modular_citadel/code/datums/mood_events/chem_events.dm +++ b/modular_citadel/code/datums/mood_events/chem_events.dm @@ -1,3 +1,3 @@ /datum/mood_event/eigenstate mood_change = -1 - description = "Where the hell am I? Is this an alternative reality?\n" + description = "Where the hell am I? Is this an alternative dimension ?\n" diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm new file mode 100644 index 0000000000..8a7222d352 --- /dev/null +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -0,0 +1,25 @@ +/datum/status_effect/chem/SGDF + id = "SGDF" + var/mob/living/clone + +/datum/status_effect/chem/SGDF/on_apply() + var/typepath = owner.type + clone = new typepath(owner.loc) + var/mob/living/carbon/O = owner + var/mob/living/carbon/C = clone + if(istype(C) && istype(O)) + C.real_name = O.real_name + O.dna.transfer_identity(C) + C.updateappearance(mutcolor_update=1) + return ..() + +/datum/status_effect/chem/SGDF/tick() + if(owner.stat == DEAD) + if(clone && clone.stat != DEAD) + if(owner.mind) + owner.mind.transfer_to(clone) + owner.visible_message("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.") + clone = null + if(!clone || clone.stat == DEAD) + to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") + ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index dcf933c183..269bd86009 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -24,6 +24,7 @@ /obj/item/reagent/fermi/eigenstate/Initialize() //. = ..() Unneeded? var/turf/open/T = get_turf(src)//Sets up coordinate of where it was created + ..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! if(holder.!has_reagent("eigenstate")) @@ -32,12 +33,14 @@ do_sparks(5,FALSE,src) src.forceMove(T) //Teleports to creation location do_sparks(5,FALSE,src) + ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,src) to_chat(M, "You feel your wavefunction collapse!") src.forceMove(T2) //Teleports home do_sparks(5,FALSE,src) + ..() /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly if(10) @@ -49,6 +52,7 @@ do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') do_sparks(5,FALSE,src) M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting + ..() //..() //loop function @@ -58,12 +62,14 @@ to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") M.Jitter(10) M.nutrition = M.nutrition - (M.nutrition/10) + ..() /datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M) to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") M.Jitter(50) M.AdjustKnockdown(-40, 0) for(var/obj/item/I in mob.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); + ..() /datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! M.Jitter(100) @@ -72,15 +78,19 @@ //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in if(1) - var/typepath = owner.type - clone = new typepath(owner.loc) - var/mob/living/carbon/O = owner + var/typepath = M.type + clone = new typepath(M.loc) + //var/mob/living/carbon/O = M var/mob/living/carbon/C = clone - if(istype(C) && istype(O)) - C.real_name = O.real_name - O.dna.transfer_identity(C) - C.updateappearance(mutcolor_update=1) - visible_message("[M] collapses in from an alternative reality!") + C.appearance = M.appearance + + //Incase Kevin breaks my code: + //if(istype(C) && istype(O)) + // C.real_name = O.real_name + // O.dna.transfer_identity(C) + // C.updateappearance(mutcolor_update=1) + + visible_message("[M] collapses in from an alternative reality!") if(2) do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! if(3) @@ -89,7 +99,7 @@ .=1 //counter do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly - //..() //loop function + ..() //loop function /datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. M.Jitter(50) @@ -97,5 +107,61 @@ to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your pervious self, sent to god knows what universe.") mob.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) + ..() //eigenstate END + +//Clone serum #chemClone +/datum/reagent/fermi/SGDF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. + //Setup clone + + + var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + if(LAZYLEN(candidates)) + + //var/typepath = owner.type + //clone = new typepath(owner.loc) + var/typepath = M.type + clone = new typepath(M.loc) + //var/mob/living/carbon/O = owner + var/mob/living/carbon/O = M + var/mob/living/carbon/SM = clone + if(istype(SM) && istype(O)) + SM.real_name = O.real_name + O.dna.transfer_identity(SM) + SM.updateappearance(mutcolor_update=1) + + var/mob/dead/observer/C = pick(candidates) + SM.key = C.key + SM.mind.enslave_mind_to_creator(user) + SM.sentience_act() + to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") + to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independance, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") + to_chat(O, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") + visible_message("[O] suddenly shudders, and splits into two identical twins!") + SM.copy_known_languages_from(user, FALSE) + //after_success(user, SM) + //qdel(src) + else + if(20) + O.apply_status_effect(var/datum/status_effect/chem/SGDF) + + ..() + + +//Breast englargement +/datum/reagent/fermi/BElarger + name = "Eigenstasium" + id = "eigenstate" + description = "A volatile collodial mixture derived from milk that encourages mammary production via a potent estrogen mix." + color = "#60A584" // rgb: 96, 0, 255 + overdose_threshold = 12 + +/datum/reagent/fermi/BElarger/overdose_start(mob/living/M) //Turns you into a female if male and ODing + if(M.gender == MALE) + M.gender = FEMALE + M.visible_message("[user] suddenly looks more feminine!", "You suddenly feel more feminine!") + + if(M.gender == FEMALE) + M.gender = FEMALE + M.visible_message("[user] suddenly looks more masculine!", "You suddenly feel more masculine!") diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index e69de29bb2..fbfb09b355 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -0,0 +1,46 @@ +//TO TWEAK: + +/datum/chemical_reaction/eigenstate + name = "Eigenstasium" + id = "eigenstate" + results = list("eigenstate" = `1`) + required_reagents = list("bluespace" = 1, "stable_plasma" = 1, "sugar" = 1) + //FermiChem vars: + OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 500 // Upper end for above + ExplodeTemp = 550 //Temperature at which reaction explodes + OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + ThermicConstant = -2.5 //Temperature change per 1u produced + HIonRelease = 0.01 //pH change per 1u reaction + RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect + FermiChem = 1 + +//serum +/datum/chemical_reaction/SDGF + name = "synthetic-derived growth factor" + id = "SDGF" + results = list("SDGF" = `3`) + required_reagents = list("stable_plasma" = 5, "slimejelly" = 5, "synthflesh" = 10, "blood" = 10) + +/datum/chemical_reaction/BElarger + name = "" + id = "e" + results = list("Eigenstasium" = `6`) + required_reagents = list("salglu_solution" = 1, "milk" = 5, "synthflesh" = 2, "silicon" = 2, "crocin" = 2) + //FermiChem vars: + OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 500 // Upper end for above + ExplodeTemp = 550 //Temperature at which reaction explodes + OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + ThermicConstant = -2.5 //Temperature change per 1u produced + HIonRelease = 0.01 //pH change per 1u reaction + RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect + FermiChem = 1 diff --git a/tgstation.dme b/tgstation.dme index b14ffbc44c..107d86627a 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2777,6 +2777,7 @@ #include "modular_citadel\code\datums\mood_events\generic_positive_events.dm" #include "modular_citadel\code\datums\mood_events\moodular.dm" #include "modular_citadel\code\datums\mutations\hulk.dm" +#include "modular_citadel\code\datums\status_effects\chems.dm" #include "modular_citadel\code\datums\status_effects\debuffs.dm" #include "modular_citadel\code\datums\traits\neutral.dm" #include "modular_citadel\code\datums\wires\airlock.dm" From a86ef643b40f514916e3b3c4cc1e8c36f6faae42 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Fri, 12 Apr 2019 17:18:23 +0100 Subject: [PATCH 07/61] Mid progress through reaction mechanics. --- code/modules/reagents/chemistry/holder.dm | 11 ++++++----- code/modules/reagents/chemistry/recipes.dm | 6 ++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index baf1df7788..2efc135542 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -380,7 +380,7 @@ matching_container = 1 else - if(cached_my_atom.type == C.required_container)//if the container requires a certain type, and if it equals what it needs? + if(cached_my_atom.type == C.required_container)//if the suspected container is a container matching_container = 1 if (isliving(cached_my_atom) && !C.mob_react) //Makes it so certain chemical reactions don't occur in mobs return @@ -393,7 +393,7 @@ if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this matching_other = 1 else - if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? + if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? Oh, cyro. matching_container = 1 if(!C.required_other) matching_other = 1 @@ -429,9 +429,10 @@ multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) //FermiChem - if (purity != 1)//if purity of reaction isn't 1 - multiplierProd = multiplier * purity //adjusts multiplier to be in line with purity - multiplierTox = multiplier - multiplierProd // + + //if (purity != 1)//if purity of reaction isn't 1 + // multiplierProd = multiplier * purity //adjusts multiplier to be in line with purity + // multiplierTox = multiplier - multiplierProd // for(var/B in cached_required_reagents) diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 50006eef62..dba07ed875 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -17,6 +17,12 @@ var/mix_message = "The solution begins to bubble." //The message shown to nearby people upon mixing, if applicable var/mix_sound = 'sound/effects/bubbles.ogg' //The sound played upon mixing, if applicable + //FermiChem! + var/FermiChem = FALSE //If the chemical uses the Fermichem reaction mechanics + var/FermiExplode = FALSE //If the chemical explodes in a special way as a result of + var/ExplodeTemp = 900 //If any reaction is this hot, it explodes! + var/ImpureChem = "toxin" //What chemical is produced with an inpure reaction + /datum/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, specialreact) return //I recommend you set the result amount to the total volume of all components. From 8e9ea0b506bf63ab9f018e82a2c736549533301c Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 05:31:04 +0100 Subject: [PATCH 08/61] Main reaction loop set up!! (I hope!!) --- .../chemistry/Fermi_Chemistry_notes.txt | 2 +- code/modules/reagents/chemistry/holder.dm | 125 +++++++++++++++--- .../chemistry/reagents/fermi_reagents.dm | 6 +- .../reagents/chemistry/recipes/fermi.dm | 9 +- 4 files changed, 121 insertions(+), 21 deletions(-) diff --git a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt index ac40b9ddd9..541c3e71b3 100644 --- a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt +++ b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt @@ -33,7 +33,7 @@ How the end state should look:{ OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reations (Plateu phase) OptimalpHMax = 9.5 // Higest value for above ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) - CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + //CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) CurveSharp = 4 // How sharp the exponential curve is (to the power of value) ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 2efc135542..c58030797a 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -53,6 +53,9 @@ var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() var/reagents_holder_flags + //FermiChem + var/purity = 1 + var/ammoReacted = 0 /datum/reagents/New(maximum=100) maximum_volume = maximum @@ -367,6 +370,11 @@ var/has_special_react = C.special_react var/can_special_react = 0 + //FermiChem + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) break @@ -400,6 +408,10 @@ //FermiChem if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + if (C.FermiExplode == TRUE) + //To be added! + else + FermiExplode() //explode function!! if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! @@ -425,29 +437,104 @@ var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list var/list/cached_results = selected_reaction.results//resultant chemical list var/list/multiplier = INFINITY //Wat + for(var/B in cached_required_reagents) // multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - //FermiChem + //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. + //FermiChem relies on two additional properties; pH and impurity + //Temperature plays into a larger role too. + if (C.FermiChem == TRUE) + message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") + //FermiReact(C) + //B is Beaker + //P is product + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - //if (purity != 1)//if purity of reaction isn't 1 - // multiplierProd = multiplier * purity //adjusts multiplier to be in line with purity - // multiplierTox = multiplier - multiplierProd // + while (ammoReacted < multiplier) + //Begin Parse + + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + ChemExplosion() + + if (pH > 14) OR (pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + pHExplosion() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax) + deltaT = ((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT) + else if + (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = (C.ReactpHLim -((pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH) + + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 0 + + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + //TODO Add CatalystFact + + stepChemAmmount = multiplier * deltaT + P.purity = (P.purity + deltapH) /2 //This should add the purity to the product + + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + + // End + + selected_reaction.on_reaction(src, multiplier, special_react_result) + + for(var/B in cached_required_reagents) + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - for(var/B in cached_required_reagents) - remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + ammoReacted = ammoReacted + stepChemAmmount + + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log + //Standard reaction mechanics: + else: + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + for(var/B in cached_required_reagents) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log - //add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: - //FermiChem - if (purity != 1)//if purity of reaction isn't 1 - add_reagent(P, cached_results[P]*multiplierProd, null, chem_temp)//add reagent function for product - add_reagent(P, cached_results[P]*multiplierTox, null, chem_temp)//add reagent function for product - else - add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers var/iconhtml = icon2html(cached_my_atom, seen) @@ -475,6 +562,12 @@ update_total()//Don't know waht this does. return 0//end! +/datum/reagents/proc/FermiReact() + return + +/datum/reagents/proc/FermiExplode() + return + /datum/reagents/proc/isolate_reagent(reagent) var/list/cached_reagents = reagent_list for(var/_reagent in cached_reagents) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 269bd86009..9392e56d71 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -4,6 +4,8 @@ //MCchem //BE PE chemical //Angel/astral chemical +//And tips their hat +//Naninte chem //eigenstate Chem //Teleports you to chemistry and back @@ -109,6 +111,8 @@ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) ..() +/datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) + //eigenstate END //Clone serum #chemClone @@ -136,7 +140,7 @@ SM.mind.enslave_mind_to_creator(user) SM.sentience_act() to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") - to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independance, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") + to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") to_chat(O, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") visible_message("[O] suddenly shudders, and splits into two identical twins!") SM.copy_known_languages_from(user, FALSE) diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index fbfb09b355..bab77de811 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -13,11 +13,14 @@ OptimalpHMax = 9.5 // Higest value for above ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) - CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 + FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics + var/FermiExplode = FALSE //If the chemical explodes in a special way + var/ImpureChem = "toxin" //What chemical is produced with an inpure reaction //serum /datum/chemical_reaction/SDGF @@ -43,4 +46,4 @@ ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 + FermiChem = TRUE From ed27c5dfe4e4a476a2320da52b6982d20c6c512b Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 05:31:04 +0100 Subject: [PATCH 09/61] Main reaction loop set up!! (I hope!!) --- .../chemistry/Fermi_Chemistry_notes.txt | 2 +- code/modules/reagents/chemistry/holder.dm | 125 +++++++++++++++--- .../chemistry/reagents/fermi_reagents.dm | 6 +- .../reagents/chemistry/recipes/fermi.dm | 9 +- 4 files changed, 121 insertions(+), 21 deletions(-) diff --git a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt index ac40b9ddd9..541c3e71b3 100644 --- a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt +++ b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt @@ -33,7 +33,7 @@ How the end state should look:{ OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reations (Plateu phase) OptimalpHMax = 9.5 // Higest value for above ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) - CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + //CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) CurveSharp = 4 // How sharp the exponential curve is (to the power of value) ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 2efc135542..c58030797a 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -53,6 +53,9 @@ var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() var/reagents_holder_flags + //FermiChem + var/purity = 1 + var/ammoReacted = 0 /datum/reagents/New(maximum=100) maximum_volume = maximum @@ -367,6 +370,11 @@ var/has_special_react = C.special_react var/can_special_react = 0 + //FermiChem + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) break @@ -400,6 +408,10 @@ //FermiChem if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + if (C.FermiExplode == TRUE) + //To be added! + else + FermiExplode() //explode function!! if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! @@ -425,29 +437,104 @@ var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list var/list/cached_results = selected_reaction.results//resultant chemical list var/list/multiplier = INFINITY //Wat + for(var/B in cached_required_reagents) // multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - //FermiChem + //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. + //FermiChem relies on two additional properties; pH and impurity + //Temperature plays into a larger role too. + if (C.FermiChem == TRUE) + message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") + //FermiReact(C) + //B is Beaker + //P is product + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - //if (purity != 1)//if purity of reaction isn't 1 - // multiplierProd = multiplier * purity //adjusts multiplier to be in line with purity - // multiplierTox = multiplier - multiplierProd // + while (ammoReacted < multiplier) + //Begin Parse + + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + ChemExplosion() + + if (pH > 14) OR (pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + pHExplosion() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax) + deltaT = ((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT) + else if + (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = (C.ReactpHLim -((pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH) + + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 0 + + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + //TODO Add CatalystFact + + stepChemAmmount = multiplier * deltaT + P.purity = (P.purity + deltapH) /2 //This should add the purity to the product + + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + + // End + + selected_reaction.on_reaction(src, multiplier, special_react_result) + + for(var/B in cached_required_reagents) + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - for(var/B in cached_required_reagents) - remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + ammoReacted = ammoReacted + stepChemAmmount + + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log + //Standard reaction mechanics: + else: + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + for(var/B in cached_required_reagents) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log - //add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: - //FermiChem - if (purity != 1)//if purity of reaction isn't 1 - add_reagent(P, cached_results[P]*multiplierProd, null, chem_temp)//add reagent function for product - add_reagent(P, cached_results[P]*multiplierTox, null, chem_temp)//add reagent function for product - else - add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers var/iconhtml = icon2html(cached_my_atom, seen) @@ -475,6 +562,12 @@ update_total()//Don't know waht this does. return 0//end! +/datum/reagents/proc/FermiReact() + return + +/datum/reagents/proc/FermiExplode() + return + /datum/reagents/proc/isolate_reagent(reagent) var/list/cached_reagents = reagent_list for(var/_reagent in cached_reagents) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 269bd86009..9392e56d71 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -4,6 +4,8 @@ //MCchem //BE PE chemical //Angel/astral chemical +//And tips their hat +//Naninte chem //eigenstate Chem //Teleports you to chemistry and back @@ -109,6 +111,8 @@ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) ..() +/datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) + //eigenstate END //Clone serum #chemClone @@ -136,7 +140,7 @@ SM.mind.enslave_mind_to_creator(user) SM.sentience_act() to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") - to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independance, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") + to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") to_chat(O, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") visible_message("[O] suddenly shudders, and splits into two identical twins!") SM.copy_known_languages_from(user, FALSE) diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index fbfb09b355..bab77de811 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -13,11 +13,14 @@ OptimalpHMax = 9.5 // Higest value for above ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) - CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 + FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics + var/FermiExplode = FALSE //If the chemical explodes in a special way + var/ImpureChem = "toxin" //What chemical is produced with an inpure reaction //serum /datum/chemical_reaction/SDGF @@ -43,4 +46,4 @@ ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 + FermiChem = TRUE From a082b3c532491d3d71686935aded6014d6e0c087 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 05:56:38 +0100 Subject: [PATCH 10/61] Fixed purity calculation issue --- code/modules/reagents/chemistry/holder.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index c58030797a..5ede4924dc 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -498,8 +498,10 @@ //TODO Add CatalystFact stepChemAmmount = multiplier * deltaT - P.purity = (P.purity + deltapH) /2 //This should add the purity to the product - + if (ammoReacted > 0) + P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + P.purity = deltapH //Apply pH changes and thermal output of reaction to beaker chem_temp += (C.ThermicConstant * stepChemAmmount) pH += (C.HIonRelease * stepChemAmmount) From eac84788125480861bb5b3c69436f5464e79af0c Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 06:02:35 +0100 Subject: [PATCH 11/61] Minor deltapH tweaks --- code/modules/reagents/chemistry/holder.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 5ede4924dc..716d56d89c 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -488,13 +488,13 @@ deltapH = 0 else deltapH = (C.ReactpHLim -((pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH) - //Within mid range else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 0 - + deltapH = 1 + //This should never proc: else message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[reagent]' which broke for some reason! ([usr])") //TODO Add CatalystFact stepChemAmmount = multiplier * deltaT From 38aecfadd0c91ecc67dd5b288835fa7fd6c0c516 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 15:58:07 +0100 Subject: [PATCH 12/61] Fixed dme pointer --- tgstation.dme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tgstation.dme b/tgstation.dme index 107d86627a..3e6b10e9c2 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2957,7 +2957,7 @@ #include "modular_citadel\code\modules\projectiles\projectiles\reusable.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\fermi_reagents.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\other_reagents.dm" -#include "modular_citadel\code\modules\reagents\chemistry\recipies\fermi.dm" +#include "modular_citadel\code\modules\reagents\chemistry\recipes\fermi.dm" #include "modular_citadel\code\modules\reagents\reagent container\cit_kegs.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypospraymkii.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypovial.dm" From ccdd077a4c4926d4ad8691a6eef3ca12c384855e Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 16:31:26 +0100 Subject: [PATCH 13/61] Bugfixes --- code/modules/reagents/chemistry/holder.dm | 13 ++++--- .../code/datums/status_effects/chems.dm | 36 +++++++++---------- .../chemistry/reagents/fermi_reagents.dm | 12 +++---- tgstation.dme | 1 - 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 716d56d89c..b398c6ae18 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -457,20 +457,19 @@ //Check extremes first if (chem_temp > C.ExplodeTemp) //go to explode proc - ChemExplosion() + FermiExplode() if (pH > 14) OR (pH < 0) //Create chemical sludge eventually(for now just destroy the beaker I guess?) //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - pHExplosion() + FermiExplode() //For now, purity is handled elsewhere //Calculate DeltaT (Deviation of T from optimal) if (chem_temp < C.OptimalTempMax) - deltaT = ((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT) - else if - (chem_temp >= C.OptimalTempMax) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) deltaT = 1 else deltaT = 0 @@ -481,13 +480,13 @@ if (pH < (C.OptimalpHMin - C.ReactpHLim)) deltapH = 0 else - deltapH = ((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH) + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH)) //Upper range else if (pH > C.OptimalpHMin) if (pH > (C.OptimalpHMin + C.ReactpHLim)) deltapH = 0 else - deltapH = (C.ReactpHLim -((pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH) + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) //Within mid range else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) deltapH = 1 diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 8a7222d352..a42f5db07a 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -3,23 +3,23 @@ var/mob/living/clone /datum/status_effect/chem/SGDF/on_apply() - var/typepath = owner.type - clone = new typepath(owner.loc) - var/mob/living/carbon/O = owner - var/mob/living/carbon/C = clone - if(istype(C) && istype(O)) - C.real_name = O.real_name - O.dna.transfer_identity(C) - C.updateappearance(mutcolor_update=1) - return ..() + var/typepath = owner.type + clone = new typepath(owner.loc) + var/mob/living/carbon/O = owner + var/mob/living/carbon/C = clone + if(istype(C) && istype(O)) + C.real_name = O.real_name + O.dna.transfer_identity(C) + C.updateappearance(mutcolor_update=1) + return ..() /datum/status_effect/chem/SGDF/tick() - if(owner.stat == DEAD) - if(clone && clone.stat != DEAD) - if(owner.mind) - owner.mind.transfer_to(clone) - owner.visible_message("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.") - clone = null - if(!clone || clone.stat == DEAD) - to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") - ..() + if(owner.stat == DEAD) + if(clone && clone.stat != DEAD) + if(owner.mind) + owner.mind.transfer_to(clone) + owner.visible_message("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.") + clone = null + if(!clone || clone.stat == DEAD) + to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") + ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 9392e56d71..3d19514334 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -29,12 +29,12 @@ ..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! - if(holder.!has_reagent("eigenstate")) - var/turf/open/T2 = get_turf(src) //sets up return point - to_chat(M, "You feel your wavefunction split!") - do_sparks(5,FALSE,src) - src.forceMove(T) //Teleports to creation location - do_sparks(5,FALSE,src) + if (holder.!has_reagent("eigenstate")) + var/turf/open/T2 = get_turf(src) //sets up return point + to_chat(M, "You feel your wavefunction split!") + do_sparks(5,FALSE,src) + src.forceMove(T) //Teleports to creation location + do_sparks(5,FALSE,src) ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location diff --git a/tgstation.dme b/tgstation.dme index 3e6b10e9c2..d7df01ed59 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2957,7 +2957,6 @@ #include "modular_citadel\code\modules\projectiles\projectiles\reusable.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\fermi_reagents.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\other_reagents.dm" -#include "modular_citadel\code\modules\reagents\chemistry\recipes\fermi.dm" #include "modular_citadel\code\modules\reagents\reagent container\cit_kegs.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypospraymkii.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypovial.dm" From bf647c38e8177a87d2185cbe364faed90b7dd548 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 19:52:23 +0100 Subject: [PATCH 14/61] Variables don't work as I thought and it makes me sad. --- code/modules/reagents/chemistry/holder.dm | 25 ++++++++++++++++--- .../reagents/chemistry/recipes/medicine.dm | 13 ---------- .../chemistry/reagents/fermi_reagents.dm | 4 ++- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index d5c44315c5..dd519c638f 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -53,9 +53,6 @@ var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() var/reagents_holder_flags - //FermiChem - var/purity = 1 - var/ammoReacted = 0 /datum/reagents/New(maximum=100) maximum_volume = maximum @@ -369,8 +366,28 @@ var/meets_temp_requirement = 0 var/has_special_react = C.special_react var/can_special_react = 0 + //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad + var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions + var/OptimalTempMax = C.OptimalTempMax + var/ExplodeTemp = C.ExplodeTemp + var/OptimalpHMin = C.OptimalpHMin + var/OptimalpHMax = C.OptimalpHMax + var/ReactpHLim = C.ReactpHLim + //var/CatalystFact = C.CatalystFact + var/CurveSharpT = C.CurveSharpT + var/CurveSharppH = C.CurveSharppH + var/ThermicConstant = C.ThermicConstant + var/HIonRelease = C.HIonRelease + var/RateUpLim = C.RateUpLim + var/FermiChem = C.FermiChem + var/FermiExplod = C.FermiExplod + var/ImpureChem = C.ImpureChem + //FermiChem + var/purity = 1 + var/ammoReacted = 0 + var/deltaT = 0 var/deltapH = 0 var/stepChemAmmount = 0 @@ -459,7 +476,7 @@ //go to explode proc FermiExplode() - if (pH > 14) OR (pH < 0) + if (pH > 14 || pH < 0) //Create chemical sludge eventually(for now just destroy the beaker I guess?) //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) FermiExplode() diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index deccc47768..dc7c32d925 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -208,19 +208,6 @@ id = "bicaridine" results = list("bicaridine" = 3) required_reagents = list("carbon" = 1, "oxygen" = 1, "sugar" = 1) - //FermiChem vars: - OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions - OptimalTempMax = 500 // Upper end for above - ExplodeTemp = 550 //Temperature at which reaction explodes - OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) - OptimalpHMax = 9.5 // Higest value for above - ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) - CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) - CurveSharp = 4 // How sharp the exponential curve is (to the power of value) - ThermicConstant = -2.5 //Temperature change per 1u produced - HIonRelease = 0.01 //pH change per 1u reaction - RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 /datum/chemical_reaction/kelotane name = "Kelotane" diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 3d19514334..7eccf33083 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -29,7 +29,9 @@ ..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! - if (holder.!has_reagent("eigenstate")) + if (holder.has_reagent("eigenstate")) + do_sparks(5,FALSE,src) + else var/turf/open/T2 = get_turf(src) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,src) From 0cee082e81fc0c177513763c5f355040e1ddf887 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 22:57:08 +0100 Subject: [PATCH 15/61] Added default fermichemvals to recipies --- code/modules/reagents/chemistry/holder.dm | 28 +++++++++++++++---- code/modules/reagents/chemistry/recipes.dm | 14 +++++++++- .../reagents/chemistry/recipes/medicine.dm | 13 --------- .../chemistry/reagents/fermi_reagents.dm | 5 +++- 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index d5c44315c5..8d6c4cc102 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -370,6 +370,22 @@ var/has_special_react = C.special_react var/can_special_react = 0 + var/datum/chemical_reaction/C/OptimalTempMin = OptimalTempMin // Lower area of bell curve for determining heat based rate reactions + var/OptimalTempMax = C.OptimalTempMax + var/ExplodeTemp = C.ExplodeTemp + var/OptimalpHMin = C.OptimalpHMin + var/OptimalpHMax = C.OptimalpHMax + var/ReactpHLim = C.ReactpHLim + //var/CatalystFact = C.CatalystFact + var/CurveSharpT = C.CurveSharpT + var/CurveSharppH = C.CurveSharppH + var/ThermicConstant = C.ThermicConstant + var/HIonRelease = C.HIonRelease + var/RateUpLim = C.RateUpLim + var/FermiChem = C.FermiChem + var/FermiExplod = C.FermiExplod + var/ImpureChem = C.ImpureChem + //FermiChem var/deltaT = 0 var/deltapH = 0 @@ -407,8 +423,8 @@ matching_other = 1 //FermiChem - if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! - if (C.FermiExplode == TRUE) + if (chem_temp > ExplodeTemp)//Check to see if reaction is too hot! + if (FermiExplode == TRUE) //To be added! else FermiExplode() @@ -455,11 +471,11 @@ //Begin Parse //Check extremes first - if (chem_temp > C.ExplodeTemp) + if (chem_temp > ExplodeTemp) //go to explode proc FermiExplode() - if (pH > 14) OR (pH < 0) + if (pH > 14 || pH < 0) //Create chemical sludge eventually(for now just destroy the beaker I guess?) //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) FermiExplode() @@ -467,8 +483,8 @@ //For now, purity is handled elsewhere //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < C.OptimalTempMax) - deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) + if (chem_temp < OptimalTempMax) + deltaT = (((OptimalTempMin - chem_temp)**CurveSharpT)/((OptimalTempMax - OptimalTempMax)**CurveSharpT)) else if (chem_temp >= C.OptimalTempMax) deltaT = 1 else diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index dba07ed875..a3d70efd2d 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -18,9 +18,21 @@ var/mix_sound = 'sound/effects/bubbles.ogg' //The sound played upon mixing, if applicable //FermiChem! + + var/OptimalTempMin = 200 // Lower area of bell curve for determining heat based rate reactions + var/OptimalTempMax = 800 + var/ExplodeTemp = 900 //If any reaction is this hot, it explodes! + var/OptimalpHMin = 5 + var/OptimalpHMax = 10 + var/ReactpHLim = 3 + //var/CatalystFact = C.CatalystFact + var/CurveSharpT = 2 + var/CurveSharppH = 2 + var/ThermicConstant = 1 + var/HIonRelease = 0.1 + var/RateUpLim = 10 var/FermiChem = FALSE //If the chemical uses the Fermichem reaction mechanics var/FermiExplode = FALSE //If the chemical explodes in a special way as a result of - var/ExplodeTemp = 900 //If any reaction is this hot, it explodes! var/ImpureChem = "toxin" //What chemical is produced with an inpure reaction /datum/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, specialreact) diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index deccc47768..dc7c32d925 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -208,19 +208,6 @@ id = "bicaridine" results = list("bicaridine" = 3) required_reagents = list("carbon" = 1, "oxygen" = 1, "sugar" = 1) - //FermiChem vars: - OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions - OptimalTempMax = 500 // Upper end for above - ExplodeTemp = 550 //Temperature at which reaction explodes - OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) - OptimalpHMax = 9.5 // Higest value for above - ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) - CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) - CurveSharp = 4 // How sharp the exponential curve is (to the power of value) - ThermicConstant = -2.5 //Temperature change per 1u produced - HIonRelease = 0.01 //pH change per 1u reaction - RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - FermiChem = 1 /datum/chemical_reaction/kelotane name = "Kelotane" diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 3d19514334..4dc847150c 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -22,6 +22,7 @@ metabolization_rate = 0.5 * REAGENTS_METABOLISM addiction_stage3_end = 40 addiction_stage4_end = 55 //Incase it's too long + /obj/item/reagent/fermi/eigenstate/Initialize() //. = ..() Unneeded? @@ -29,7 +30,9 @@ ..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! - if (holder.!has_reagent("eigenstate")) + if (holder.has_reagent("eigenstate")) + do_sparks(5,FALSE,src) + else var/turf/open/T2 = get_turf(src) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,src) From 68813cf12a16c168f7182d1ba1c7076916afb6fc Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 23:11:55 +0100 Subject: [PATCH 16/61] fixed add_reagent --- code/modules/reagents/chemistry/holder.dm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index b24eb7d946..b7628182a0 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -184,8 +184,9 @@ if(preserve_data) trans_data = copy_data(T) - //fermichem Added ph and T.purity - R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + //fermichem Added ph TODO: add T.purity + R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + //R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. remove_reagent(T.id, transfer_amount) update_total() @@ -245,7 +246,8 @@ if(current_reagent.id == reagent) if(preserve_data) trans_data = current_reagent.data - R.add_reagent(current_reagent.id, amount, trans_data, src.chem_temp, pH, current_reagent.purity, no_react = TRUE) //Fermichem edit + R.add_reagent(current_reagent.id, amount, trans_data, src.chem_temp, pH, no_react = TRUE) //Fermichem edit TODO: add purity + //R.add_reagent(current_reagent.id, amount, trans_data, src.chem_temp, pH, current_reagent.purity, no_react = TRUE) //Fermichem edit remove_reagent(current_reagent.id, amount, 1) break @@ -690,7 +692,7 @@ var/S = specific_heat() chem_temp = CLAMP(chem_temp + (J / (S * total_volume)), 2.7, 1000) -/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, pH = 7, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ if(!isnum(amount) || !amount) return FALSE From 3d4245905aa29cbd77808e6242e66b5402659431 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 23:16:18 +0100 Subject: [PATCH 17/61] Accidental double vars --- code/modules/reagents/chemistry/holder.dm | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index b7628182a0..3afe6732eb 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -385,23 +385,6 @@ var/FermiExplod = C.FermiExplod var/ImpureChem = C.ImpureChem - - var/datum/chemical_reaction/C/OptimalTempMin = OptimalTempMin // Lower area of bell curve for determining heat based rate reactions - var/OptimalTempMax = C.OptimalTempMax - var/ExplodeTemp = C.ExplodeTemp - var/OptimalpHMin = C.OptimalpHMin - var/OptimalpHMax = C.OptimalpHMax - var/ReactpHLim = C.ReactpHLim - //var/CatalystFact = C.CatalystFact - var/CurveSharpT = C.CurveSharpT - var/CurveSharppH = C.CurveSharppH - var/ThermicConstant = C.ThermicConstant - var/HIonRelease = C.HIonRelease - var/RateUpLim = C.RateUpLim - var/FermiChem = C.FermiChem - var/FermiExplod = C.FermiExplod - var/ImpureChem = C.ImpureChem - //FermiChem var/purity = 1 var/ammoReacted = 0 From e2fb670314ea36cee067cd5c14826291e89e68fc Mon Sep 17 00:00:00 2001 From: Thalpy Date: Sun, 14 Apr 2019 23:21:59 +0100 Subject: [PATCH 18/61] Fixed spelling of explode --- code/modules/reagents/chemistry/holder.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 3afe6732eb..a959544e49 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -382,7 +382,7 @@ var/HIonRelease = C.HIonRelease var/RateUpLim = C.RateUpLim var/FermiChem = C.FermiChem - var/FermiExplod = C.FermiExplod + var/FermiExplode = C.FermiExplode var/ImpureChem = C.ImpureChem //FermiChem From 3aa92325cf1340e7ac26cc7740be263356b79a7b Mon Sep 17 00:00:00 2001 From: Thalpy Date: Mon, 15 Apr 2019 01:05:32 +0100 Subject: [PATCH 19/61] Jubiously day, I fixed the reaction, mostly and xeno broke --- code/modules/reagents/chemistry/holder.dm | 147 +-- .../reagents/chemistry/holderBackup.dm | 952 ++++++++++++++++++ 2 files changed, 1029 insertions(+), 70 deletions(-) create mode 100644 code/modules/reagents/chemistry/holderBackup.dm diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index a959544e49..ec8de8380f 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -338,6 +338,13 @@ update_total() /datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + //FermiChem + var/purity = 1 + var/ammoReacted = 0 + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/list/cached_reagents = reagent_list //a list of the reagents? var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! @@ -369,6 +376,7 @@ var/has_special_react = C.special_react var/can_special_react = 0 //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad + /* var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions var/OptimalTempMax = C.OptimalTempMax var/ExplodeTemp = C.ExplodeTemp @@ -384,14 +392,16 @@ var/FermiChem = C.FermiChem var/FermiExplode = C.FermiExplode var/ImpureChem = C.ImpureChem - + */ //FermiChem + /* var/purity = 1 var/ammoReacted = 0 var/deltaT = 0 var/deltapH = 0 var/stepChemAmmount = 0 + */ for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) @@ -425,12 +435,6 @@ matching_other = 1 //FermiChem - if (chem_temp > ExplodeTemp)//Check to see if reaction is too hot! - if (FermiExplode == TRUE) - //To be added! - else - FermiExplode() - //explode function!! if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! meets_temp_requirement = 1//binary pass @@ -454,6 +458,7 @@ selected_reaction = competitor var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list var/list/cached_results = selected_reaction.results//resultant chemical list + var/special_react_result = selected_reaction.check_special_react(src) var/list/multiplier = INFINITY //Wat for(var/B in cached_required_reagents) // @@ -462,84 +467,86 @@ //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. //FermiChem relies on two additional properties; pH and impurity //Temperature plays into a larger role too. - if (C.FermiChem == TRUE) - message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") - //FermiReact(C) - //B is Beaker - //P is product - multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + if(selected_reaction) + var/datum/chemical_reaction/C = selected_reaction + if (C.FermiChem == TRUE) + message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") + //FermiReact(C) + //B is Beaker + //P is product + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - while (ammoReacted < multiplier) - //Begin Parse + while (ammoReacted < multiplier) + //Begin Parse - //Check extremes first - if (chem_temp > ExplodeTemp) - //go to explode proc - FermiExplode() + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + FermiExplode() - if (pH > 14 || pH < 0) - //Create chemical sludge eventually(for now just destroy the beaker I guess?) - //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - FermiExplode() + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + FermiExplode() - //For now, purity is handled elsewhere + //For now, purity is handled elsewhere - //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < OptimalTempMax) - deltaT = (((OptimalTempMin - chem_temp)**CurveSharpT)/((OptimalTempMax - OptimalTempMax)**CurveSharpT)) - else if (chem_temp >= C.OptimalTempMax) - deltaT = 1 - else - deltaT = 0 - - //Calculate DeltapH (Deviation of pH from optimal) - //Lower range - if (pH < C.OptimalpHMin) - if (pH < (C.OptimalpHMin - C.ReactpHLim)) - deltapH = 0 + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 else - deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH)) - //Upper range - else if (pH > C.OptimalpHMin) - if (pH > (C.OptimalpHMin + C.ReactpHLim)) - deltapH = 0 + deltaT = 0 + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: else - deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) - //Within mid range - else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 1 - //This should never proc: - else - message_admins("Fermichem's pH broke!! Please let Fermis know!!") - WARNING("[my_atom] attempted to determine FermiChem pH for '[reagent]' which broke for some reason! ([usr])") - //TODO Add CatalystFact + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C]' which broke for some reason! ([usr])") + //TODO Add CatalystFact - stepChemAmmount = multiplier * deltaT - if (ammoReacted > 0) - P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - P.purity = deltapH - //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) + stepChemAmmount = multiplier * deltaT + if (ammoReacted > 0) + P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + P.purity = deltapH + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) - // End. + // End. - selected_reaction.on_reaction(src, multiplier, special_react_result) + selected_reaction.on_reaction(src, multiplier, special_react_result) - for(var/B in cached_required_reagents) - remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + for(var/B in cached_required_reagents) + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log - add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - ammoReacted = ammoReacted + stepChemAmmount + ammoReacted = ammoReacted + stepChemAmmount - reaction_occurred = 1 - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log //Standard reaction mechanics: else: diff --git a/code/modules/reagents/chemistry/holderBackup.dm b/code/modules/reagents/chemistry/holderBackup.dm new file mode 100644 index 0000000000..b434b348f0 --- /dev/null +++ b/code/modules/reagents/chemistry/holderBackup.dm @@ -0,0 +1,952 @@ + +/proc/build_chemical_reagent_list() + //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id + + if(GLOB.chemical_reagents_list) + return + + var/paths = subtypesof(/datum/reagent) + GLOB.chemical_reagents_list = list() + + for(var/path in paths) + var/datum/reagent/D = new path() + GLOB.chemical_reagents_list[D.id] = D + +/proc/build_chemical_reactions_list() + //Chemical Reactions - Initialises all /datum/chemical_reaction into a list + // It is filtered into multiple lists within a list. + // For example: + // chemical_reaction_list["plasma"] is a list of all reactions relating to plasma + + if(GLOB.chemical_reactions_list) + return + + var/paths = subtypesof(/datum/chemical_reaction) + GLOB.chemical_reactions_list = list() + + for(var/path in paths) + + var/datum/chemical_reaction/D = new path() + var/list/reaction_ids = list() + + if(D.required_reagents && D.required_reagents.len) + for(var/reaction in D.required_reagents) + reaction_ids += reaction + + // Create filters based on each reagent id in the required reagents list + for(var/id in reaction_ids) + if(!GLOB.chemical_reactions_list[id]) + GLOB.chemical_reactions_list[id] = list() + GLOB.chemical_reactions_list[id] += D + break // Don't bother adding ourselves to other reagent ids, it is redundant + +/////////////////////////////////////////////////////////////////////////////////// + +/datum/reagents + var/list/datum/reagent/reagent_list = new/list() + var/total_volume = 0 + var/maximum_volume = 100 + var/atom/my_atom = null + var/chem_temp = 150 + var/pH = REAGENT_NORMAL_PH + var/last_tick = 1 + var/addiction_tick = 1 + var/list/datum/reagent/addiction_list = new/list() + var/reagents_holder_flags + +/datum/reagents/New(maximum=100) + maximum_volume = maximum + + //I dislike having these here but map-objects are initialised before world/New() is called. >_> + if(!GLOB.chemical_reagents_list) + build_chemical_reagent_list() + if(!GLOB.chemical_reactions_list) + build_chemical_reactions_list() + +/datum/reagents/Destroy() + . = ..() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + qdel(R) + cached_reagents.Cut() + cached_reagents = null + if(my_atom && my_atom.reagents == src) + my_atom.reagents = null + my_atom = null + +// Used in attack logs for reagents in pills and such +/datum/reagents/proc/log_list() + if(!length(reagent_list)) + return "no reagents" + + var/list/data = list() + for(var/r in reagent_list) //no reagents will be left behind + var/datum/reagent/R = r + data += "[R.id] ([round(R.volume, 0.1)]u)" + //Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. + return english_list(data) + +/datum/reagents/proc/remove_any(amount = 1) + var/list/cached_reagents = reagent_list + var/total_transfered = 0 + var/current_list_element = 1 + + current_list_element = rand(1, cached_reagents.len) + + while(total_transfered != amount) + if(total_transfered >= amount) + break + if(total_volume <= 0 || !cached_reagents.len) + break + + if(current_list_element > cached_reagents.len) + current_list_element = 1 + + var/datum/reagent/R = cached_reagents[current_list_element] + remove_reagent(R.id, 1) + + current_list_element++ + total_transfered++ + update_total() + + handle_reactions() + return total_transfered + +/datum/reagents/proc/remove_all(amount = 1) + var/list/cached_reagents = reagent_list + if(total_volume > 0) + var/part = amount / total_volume + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + remove_reagent(R.id, R.volume * part) + + update_total() + handle_reactions() + return amount + +/datum/reagents/proc/get_master_reagent_name() + var/list/cached_reagents = reagent_list + var/name + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + name = R.name + + return name + +/datum/reagents/proc/get_master_reagent_id() + var/list/cached_reagents = reagent_list + var/id + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + id = R.id + + return id + +/datum/reagents/proc/get_master_reagent() + var/list/cached_reagents = reagent_list + var/datum/reagent/master + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + master = R + + return master + +/datum/reagents/proc/trans_to(obj/target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + if(amount < 0) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume) + var/part = amount / src.total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/transfer_amount = T.volume * part + if(preserve_data) + trans_data = copy_data(T) + + //fermichem Added ph TODO: add T.purity + R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + //R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + remove_reagent(T.id, transfer_amount) + + update_total() + R.update_total() + if(!no_react) + R.handle_reactions() + src.handle_reactions() + return amount + +/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1) + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + + if(amount < 0) + return + amount = min(min(amount, total_volume), R.maximum_volume-R.total_volume) + var/part = amount / total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/copy_amount = T.volume * part + if(preserve_data) + trans_data = T.data + R.add_reagent(T.id, copy_amount * multiplier, trans_data) + + src.update_total() + R.update_total() + R.handle_reactions() + 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 + var/list/cached_reagents = reagent_list + if (!target) + return + if (!target.reagents || src.total_volume<=0 || !src.get_reagent_amount(reagent)) + return + if(amount < 0) + return + + var/datum/reagents/R = target.reagents + if(src.get_reagent_amount(reagent)= R.overdose_threshold && !R.overdosed) + R.overdosed = 1 + need_mob_update += R.overdose_start(C) + if(R.addiction_threshold) + if(R.volume >= R.addiction_threshold && !is_type_in_list(R, cached_addictions)) + var/datum/reagent/new_reagent = new R.type() + cached_addictions.Add(new_reagent) + if(R.overdosed) + need_mob_update += R.overdose_process(C) + if(is_type_in_list(R,cached_addictions)) + for(var/addiction in cached_addictions) + var/datum/reagent/A = addiction + if(istype(R, A)) + A.addiction_stage = -15 // you're satisfied for a good while. + need_mob_update += R.on_mob_life(C) + + if(can_overdose) + if(addiction_tick == 6) + addiction_tick = 1 + for(var/addiction in cached_addictions) + var/datum/reagent/R = addiction + if(C && R) + R.addiction_stage++ + if(1 <= R.addiction_stage && R.addiction_stage <= R.addiction_stage1_end) + need_mob_update += R.addiction_act_stage1(C) + else if(R.addiction_stage1_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage2_end) + need_mob_update += R.addiction_act_stage2(C) + else if(R.addiction_stage2_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage3_end) + need_mob_update += R.addiction_act_stage3(C) + else if(R.addiction_stage3_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage4_end) + need_mob_update += R.addiction_act_stage4(C) + else if(R.addiction_stage4_end <= R.addiction_stage) + to_chat(C, "You feel like you've gotten over your need for [R.name].") + SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.id]_addiction") + cached_addictions.Remove(R) + addiction_tick++ + if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates. + C.updatehealth() + C.update_canmove() + C.update_stamina() + update_total() + + +/datum/reagents/proc/set_reacting(react = TRUE) + if(react) + reagents_holder_flags &= ~(REAGENT_NOREACT) + else + reagents_holder_flags |= REAGENT_NOREACT + +/datum/reagents/proc/conditional_update_move(atom/A, Running = 0) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_move (A, Running) + update_total() + +/datum/reagents/proc/conditional_update(atom/A) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_update (A) + update_total() + +/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + //FermiChem + var/purity = 1 + var/ammoReacted = 0 + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + + var/list/cached_reagents = reagent_list //a list of the reagents? + var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? + var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! + if(reagents_holder_flags & REAGENT_NOREACT) //Not sure on reagents_holder_flags, but I think it checks to see if theres a reaction with current stuff. + return //Yup, no reactions here. No siree. + + var/reaction_occurred = 0 // checks if reaction, binary variable + do //What does do do in byond? It sounds very redundant? is it a while loop? + var/list/possible_reactions = list() //init list + reaction_occurred = 0 // sets it back to 0? + for(var/reagent in cached_reagents) //for reagent in beaker/holder + var/datum/reagent/R = reagent //check to make sure that reagent is there for the reaction list + for(var/reaction in cached_reactions[R.id]) // Was a big list but now it should be smaller since we filtered it with our reagent id + if(!reaction) + continue + + var/datum/chemical_reaction/C = reaction + var/list/cached_required_reagents = C.required_reagents + var/total_required_reagents = cached_required_reagents.len + var/total_matching_reagents = 0 + var/list/cached_required_catalysts = C.required_catalysts + var/total_required_catalysts = cached_required_catalysts.len + var/total_matching_catalysts= 0 + var/matching_container = 0 + var/matching_other = 0 + var/required_temp = C.required_temp + var/is_cold_recipe = C.is_cold_recipe + var/meets_temp_requirement = 0 + var/has_special_react = C.special_react + var/can_special_react = 0 + //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad + var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions + var/OptimalTempMax = C.OptimalTempMax + var/ExplodeTemp = C.ExplodeTemp + var/OptimalpHMin = C.OptimalpHMin + var/OptimalpHMax = C.OptimalpHMax + var/ReactpHLim = C.ReactpHLim + //var/CatalystFact = C.CatalystFact + var/CurveSharpT = C.CurveSharpT + var/CurveSharppH = C.CurveSharppH + var/ThermicConstant = C.ThermicConstant + var/HIonRelease = C.HIonRelease + var/RateUpLim = C.RateUpLim + var/FermiChem = C.FermiChem + var/FermiExplode = C.FermiExplode + var/ImpureChem = C.ImpureChem + + //FermiChem + /* + var/purity = 1 + var/ammoReacted = 0 + + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + */ + + for(var/B in cached_required_reagents) + if(!has_reagent(B, cached_required_reagents[B])) + break + total_matching_reagents++ + for(var/B in cached_required_catalysts) + if(!has_reagent(B, cached_required_catalysts[B])) + break + total_matching_catalysts++ + if(cached_my_atom) + if(!C.required_container) + matching_container = 1 + + else + if(cached_my_atom.type == C.required_container)//if the suspected container is a container + matching_container = 1 + if (isliving(cached_my_atom) && !C.mob_react) //Makes it so certain chemical reactions don't occur in mobs + return + if(!C.required_other)//Checks for other things required + matching_other = 1//binary check passes + + else if(istype(cached_my_atom, /obj/item/slime_extract))//if the object is a slime_extract. This might be complicated as to not break them via fermichem + var/obj/item/slime_extract/M = cached_my_atom + + if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this + matching_other = 1 + else + if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? Oh, cyro. + matching_container = 1 + if(!C.required_other) + matching_other = 1 + + //FermiChem + + if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! + meets_temp_requirement = 1//binary pass + + if(!has_special_react || C.check_special_react(src)) + can_special_react = 1 + + if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other && meets_temp_requirement && can_special_react) + possible_reactions += C + + if(possible_reactions.len)//does list exist? + var/datum/chemical_reaction/selected_reaction = possible_reactions[1] + //select the reaction with the most extreme temperature requirements + for(var/V in possible_reactions)//why V, surely that would indicate volume? V is the reaction potential. + var/datum/chemical_reaction/competitor = V //competitor? I think this is theres two of them. Troubling..! + if(selected_reaction.is_cold_recipe) //if there are no recipe conflicts, everything in possible_reactions will have this same value for is_cold_reaction. warranty void if assumption not met. + if(competitor.required_temp <= selected_reaction.required_temp)//only returns with lower if reaction "is cold" var. + selected_reaction = competitor + else + if(competitor.required_temp >= selected_reaction.required_temp) //will return with the hotter reacting first. + selected_reaction = competitor + var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list + var/list/cached_results = selected_reaction.results//resultant chemical list + var/special_react_result = selected_reaction.check_special_react(src) + var/list/multiplier = INFINITY //Wat + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. + //FermiChem relies on two additional properties; pH and impurity + //Temperature plays into a larger role too. + if (C.FermiChem == TRUE) + message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") + //FermiReact(C) + //B is Beaker + //P is product + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + while (ammoReacted < multiplier) + //Begin Parse + + //Check extremes first + if (chem_temp > ExplodeTemp) + //go to explode proc + FermiExplode() + + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + FermiExplode() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[reagent]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + + stepChemAmmount = multiplier * deltaT + if (ammoReacted > 0) + P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + P.purity = deltapH + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + + // End. + + selected_reaction.on_reaction(src, multiplier, special_react_result) + + for(var/B in cached_required_reagents) + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + + + ammoReacted = ammoReacted + stepChemAmmount + + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log + //Standard reaction mechanics: + else: + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + for(var/B in cached_required_reagents) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: + + + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/iconhtml = icon2html(cached_my_atom, seen) + if(cached_my_atom) + if(!ismob(cached_my_atom)) // No bubbling mobs + if(selected_reaction.mix_sound) + playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + + for(var/mob/M in seen) + to_chat(M, "[iconhtml] [selected_reaction.mix_message]") + + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in seen) + to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." + + selected_reaction.on_reaction(src, multiplier, special_react_result) + reaction_occurred = 1 + + while(reaction_occurred)//while do nothing? + update_total()//Don't know waht this does. + return 0//end! + +/datum/reagents/proc/FermiReact() + return + +/datum/reagents/proc/FermiExplode() + return + +/datum/reagents/proc/isolate_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id != reagent) + del_reagent(R.id) + update_total() + +/datum/reagents/proc/del_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id == reagent) + if(my_atom && isliving(my_atom)) + var/mob/living/M = my_atom + R.on_mob_delete(M) + qdel(R) + reagent_list -= R + update_total() + if(my_atom) + my_atom.on_reagent_change(DEL_REAGENT) + return 1 + +/datum/reagents/proc/update_total() + var/list/cached_reagents = reagent_list + total_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume < 0.1) + del_reagent(R.id) + else + total_volume += R.volume + + return 0 + +/datum/reagents/proc/clear_reagents() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + del_reagent(R.id) + return 0 + +/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1) + var/react_type + if(isliving(A)) + react_type = "LIVING" + if(method == INGEST) + var/mob/living/L = A + L.taste(src) + else if(isturf(A)) + react_type = "TURF" + else if(isobj(A)) + react_type = "OBJ" + else + return + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + switch(react_type) + if("LIVING") + var/touch_protection = 0 + if(method == VAPOR) + var/mob/living/L = A + touch_protection = L.get_permeability_protection() + R.reaction_mob(A, method, R.volume * volume_modifier, show_message, touch_protection) + if("TURF") + R.reaction_turf(A, R.volume * volume_modifier, show_message) + if("OBJ") + R.reaction_obj(A, R.volume * volume_modifier, show_message) + +/datum/reagents/proc/holder_full() + if(total_volume >= maximum_volume) + return TRUE + return FALSE + +//Returns the average specific heat for all reagents currently in this holder. +/datum/reagents/proc/specific_heat() + . = 0 + var/cached_amount = total_volume //cache amount + var/list/cached_reagents = reagent_list //cache reagents + for(var/I in cached_reagents) + var/datum/reagent/R = I + . += R.specific_heat * (R.volume / cached_amount) + +/datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000) + var/S = specific_heat() + chem_temp = CLAMP(chem_temp + (J / (S * total_volume)), 2.7, 1000) + +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, pH = 7, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ + if(!isnum(amount) || !amount) + return FALSE + + if(amount <= 0) + return FALSE + + var/datum/reagent/D = GLOB.chemical_reagents_list[reagent] + if(!D) + WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") + return FALSE + + update_total() + var/cached_total = total_volume + if(cached_total + amount > maximum_volume) + amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. Shouldnt happen. Will happen. + if(amount <= 0) + return FALSE + var/new_total = cached_total + amount + var/cached_temp = chem_temp + var/list/cached_reagents = reagent_list + + //Equalize temperature - Not using specific_heat() because the new chemical isn't in yet. + var/specific_heat = 0 + var/thermal_energy = 0 + for(var/i in cached_reagents) + var/datum/reagent/R = i + specific_heat += R.specific_heat * (R.volume / new_total) + thermal_energy += R.specific_heat * R.volume * cached_temp + specific_heat += D.specific_heat * (amount / new_total) + thermal_energy += D.specific_heat * amount * reagtemp + chem_temp = thermal_energy / (specific_heat * new_total) + //// + + //add the reagent to the existing if it exists + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + R.volume += amount + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + R.on_merge(data, amount) + if(!no_react) + handle_reactions() + return TRUE + + //otherwise make a new one + var/datum/reagent/R = new D.type(data) + cached_reagents += R + R.holder = src + R.volume = amount + if(data) + R.data = data + R.on_new(data) + + if(isliving(my_atom)) + R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + if(!no_react) + handle_reactions() + return TRUE + +/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list("toxin" = 10, "beer" = 15) + for(var/r_id in list_reagents) + var/amt = list_reagents[r_id] + add_reagent(r_id, amt, data) + +/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to + + if(isnull(amount)) + amount = 0 + CRASH("null amount passed to reagent code") + return FALSE + + if(!isnum(amount)) + return FALSE + + if(amount < 0) + return FALSE + + var/list/cached_reagents = reagent_list + + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + //clamp the removal amount to be between current reagent amount + //and zero, to prevent removing more than the holder has stored + amount = CLAMP(amount, 0, R.volume) + R.volume -= amount + update_total() + if(!safety)//So it does not handle reactions when it need not to + handle_reactions() + if(my_atom) + my_atom.on_reagent_change(REM_REAGENT) + return TRUE + + return FALSE + +/datum/reagents/proc/has_reagent(reagent, amount = -1) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + if(!amount) + return R + else + if(R.volume >= amount) + return R + else + return 0 + + return 0 + +/datum/reagents/proc/get_reagent_amount(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + return R.volume + + return 0 + +/datum/reagents/proc/get_reagents() + var/list/names = list() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + names += R.name + + return jointext(names, ",") + +/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included. + if(!isnum(amount)) + return 1 + var/list/cached_reagents = reagent_list + var/has_removed_reagent = 0 + + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + var/matches = 0 + // Switch between how we check the reagent type + if(strict) + if(R.type == reagent_type) + matches = 1 + else + if(istype(R, reagent_type)) + matches = 1 + // We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type. + if(matches) + // Have our other proc handle removement + has_removed_reagent = remove_reagent(R.id, amount, safety) + + return has_removed_reagent + +//two helper functions to preserve data across reactions (needed for xenoarch) +/datum/reagents/proc/get_data(reagent_id) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + return R.data + +/datum/reagents/proc/set_data(reagent_id, new_data) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + R.data = new_data + +/datum/reagents/proc/copy_data(datum/reagent/current_reagent) + if(!current_reagent || !current_reagent.data) + return null + if(!istype(current_reagent.data, /list)) + return current_reagent.data + + var/list/trans_data = current_reagent.data.Copy() + + // We do this so that introducing a virus to a blood sample + // doesn't automagically infect all other blood samples from + // the same donor. + // + // Technically we should probably copy all data lists, but + // that could possibly eat up a lot of memory needlessly + // if most data lists are read-only. + if(trans_data["viruses"]) + var/list/v = trans_data["viruses"] + trans_data["viruses"] = v.Copy() + + return trans_data + +/datum/reagents/proc/get_reagent(type) + var/list/cached_reagents = reagent_list + . = locate(type) in cached_reagents + +/datum/reagents/proc/generate_taste_message(minimum_percent=15) + // the lower the minimum percent, the more sensitive the message is. + var/list/out = list() + var/list/tastes = list() //descriptor = strength + if(minimum_percent <= 100) + for(var/datum/reagent/R in reagent_list) + if(!R.taste_mult) + continue + + if(istype(R, /datum/reagent/consumable/nutriment)) + var/list/taste_data = R.data + for(var/taste in taste_data) + var/ratio = taste_data[taste] + var/amount = ratio * R.taste_mult * R.volume + if(taste in tastes) + tastes[taste] += amount + else + tastes[taste] = amount + else + var/taste_desc = R.taste_description + var/taste_amount = R.volume * R.taste_mult + if(taste_desc in tastes) + tastes[taste_desc] += taste_amount + else + tastes[taste_desc] = taste_amount + //deal with percentages + // TODO it would be great if we could sort these from strong to weak + var/total_taste = counterlist_sum(tastes) + if(total_taste > 0) + for(var/taste_desc in tastes) + var/percent = tastes[taste_desc]/total_taste * 100 + if(percent < minimum_percent) + continue + var/intensity_desc = "a hint of" + if(percent > minimum_percent * 2 || percent == 100) + intensity_desc = "" + else if(percent > minimum_percent * 3) + intensity_desc = "the strong flavor of" + if(intensity_desc != "") + out += "[intensity_desc] [taste_desc]" + else + out += "[taste_desc]" + + return english_list(out, "something indescribable") + +/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02) + var/temp_delta = (temperature - chem_temp) * coeff + if(temp_delta > 0) + chem_temp = min(chem_temp + max(temp_delta, 1), temperature) + else + chem_temp = max(chem_temp + min(temp_delta, -1), temperature) + chem_temp = round(chem_temp) + handle_reactions() + +/////////////////////////////////////////////////////////////////////////////////// + + +// Convenience proc to create a reagents holder for an atom +// Max vol is maximum volume of holder +/atom/proc/create_reagents(max_vol) + if(reagents) + qdel(reagents) + reagents = new/datum/reagents(max_vol) + reagents.my_atom = src + +/proc/get_random_reagent_id() // Returns a random reagent ID minus blacklisted reagents + var/static/list/random_reagents = list() + if(!random_reagents.len) + for(var/thing in subtypesof(/datum/reagent)) + var/datum/reagent/R = thing + if(initial(R.can_synth)) + random_reagents += initial(R.id) + var/picked_reagent = pick(random_reagents) + return picked_reagent From 02da3c524e76eeda9624aec4fb2896fdb35dce15 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Mon, 15 Apr 2019 22:08:00 +0100 Subject: [PATCH 20/61] Fixed reaction mechanics - pre status edits --- code/modules/reagents/chemistry/holder.dm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index ec8de8380f..2a56467651 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -474,7 +474,7 @@ //FermiReact(C) //B is Beaker //P is product - multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) while (ammoReacted < multiplier) //Begin Parse @@ -522,10 +522,6 @@ //TODO Add CatalystFact stepChemAmmount = multiplier * deltaT - if (ammoReacted > 0) - P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - P.purity = deltapH //Apply pH changes and thermal output of reaction to beaker chem_temp += (C.ThermicConstant * stepChemAmmount) pH += (C.HIonRelease * stepChemAmmount) @@ -538,15 +534,20 @@ remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + if (ammoReacted > 0) + P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + P.purity = deltapH multiplier = max(multiplier, 1) //this shouldnt happen ... SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: ammoReacted = ammoReacted + stepChemAmmount reaction_occurred = 1 - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log + //Standard reaction mechanics: else: From b4d1b0e9067d35104d1e8264b1edaae418f4238f Mon Sep 17 00:00:00 2001 From: Thalpy Date: Mon, 15 Apr 2019 22:59:19 +0100 Subject: [PATCH 21/61] Midfix of chem side of fermichem --- .../code/datums/status_effects/chems.dm | 36 ++++++++++--------- .../chemistry/reagents/fermi_reagents.dm | 32 +++++++++-------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index a42f5db07a..f4dea1eb6a 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -1,25 +1,27 @@ +#define fermiClone = null + /datum/status_effect/chem/SGDF id = "SGDF" - var/mob/living/clone + //var/mob/living/fermi_Clone -/datum/status_effect/chem/SGDF/on_apply() - var/typepath = owner.type - clone = new typepath(owner.loc) - var/mob/living/carbon/O = owner - var/mob/living/carbon/C = clone - if(istype(C) && istype(O)) +/datum/status_effect/chem/SGDF/on_apply(mob/living/M) + var/typepath = M.type + fermiClone = new typepath(M.loc) + //var/mob/living/carbon/M = owner + var/mob/living/carbon/C = fermi_Clone + if(istype(C) && istype(M)) C.real_name = O.real_name - O.dna.transfer_identity(C) + M.dna.transfer_identity(C) C.updateappearance(mutcolor_update=1) return ..() -/datum/status_effect/chem/SGDF/tick() - if(owner.stat == DEAD) - if(clone && clone.stat != DEAD) - if(owner.mind) - owner.mind.transfer_to(clone) - owner.visible_message("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.") - clone = null - if(!clone || clone.stat == DEAD) - to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") +/datum/status_effect/chem/SGDF/tick(mob/living/M) + if(M.stat == DEAD) + if(fermi_Clone && fermi_Clone.stat != DEAD) + if(M.mind) + M.mind.transfer_to(fermi_Clone) + M.visible_message("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.") + fermi_Clone = null + //if(!clone || clone.stat == DEAD) + // to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 4dc847150c..dd66122c7e 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -22,9 +22,10 @@ metabolization_rate = 0.5 * REAGENTS_METABOLISM addiction_stage3_end = 40 addiction_stage4_end = 55 //Incase it's too long - -/obj/item/reagent/fermi/eigenstate/Initialize() + +///obj/item/reagent/fermi/eigenstate/Initialize() +/datum/reagent/fermi/eigenstate/Initialize() //. = ..() Unneeded? var/turf/open/T = get_turf(src)//Sets up coordinate of where it was created ..() @@ -73,7 +74,7 @@ to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") M.Jitter(50) M.AdjustKnockdown(-40, 0) - for(var/obj/item/I in mob.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); + for(var/obj/item/I in M.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); ..() /datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! @@ -84,9 +85,9 @@ //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in if(1) var/typepath = M.type - clone = new typepath(M.loc) + fermi_Tclone = new typepath(M.loc) //var/mob/living/carbon/O = M - var/mob/living/carbon/C = clone + var/mob/living/carbon/C = fermi_Tclone C.appearance = M.appearance //Incase Kevin breaks my code: @@ -110,11 +111,12 @@ M.Jitter(50) M.AdjustKnockdown(0, 0) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your pervious self, sent to god knows what universe.") - mob.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) + M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) ..() /datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) + return //eigenstate END @@ -129,13 +131,13 @@ //var/typepath = owner.type //clone = new typepath(owner.loc) var/typepath = M.type - clone = new typepath(M.loc) - //var/mob/living/carbon/O = owner - var/mob/living/carbon/O = M - var/mob/living/carbon/SM = clone - if(istype(SM) && istype(O)) - SM.real_name = O.real_name - O.dna.transfer_identity(SM) + fermi_Gclone = new typepath(M.loc) + //var/mob/living/carbon/SM = owner + //var/mob/living/carbon/M = M + var/mob/living/carbon/SM = fermi_Gclone + if(istype(SM) && istype(M)) + SM.real_name = M.real_name + M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) var/mob/dead/observer/C = pick(candidates) @@ -144,8 +146,8 @@ SM.sentience_act() to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") - to_chat(O, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") - visible_message("[O] suddenly shudders, and splits into two identical twins!") + to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") + visible_message("[M] suddenly shudders, and splits into two identical twins!") SM.copy_known_languages_from(user, FALSE) //after_success(user, SM) //qdel(src) From 977462387c81c89785a572eea9a666c8a64584dd Mon Sep 17 00:00:00 2001 From: Useroth Date: Tue, 16 Apr 2019 00:11:53 +0200 Subject: [PATCH 22/61] A couple of bugfixes. Also testing if I can even push to this repo. --- code/modules/reagents/chemistry/recipes.dm | 1 + .../code/modules/reagents/chemistry/recipes/fermi.dm | 10 +++++----- tgstation.dme | 9 +++++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index a3d70efd2d..f5f5eda104 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -26,6 +26,7 @@ var/OptimalpHMax = 10 var/ReactpHLim = 3 //var/CatalystFact = C.CatalystFact + var/CatalystFact = 0 var/CurveSharpT = 2 var/CurveSharppH = 2 var/ThermicConstant = 1 diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index bab77de811..4e1a97d269 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -3,7 +3,7 @@ /datum/chemical_reaction/eigenstate name = "Eigenstasium" id = "eigenstate" - results = list("eigenstate" = `1`) + results = list("eigenstate" = 1) required_reagents = list("bluespace" = 1, "stable_plasma" = 1, "sugar" = 1) //FermiChem vars: OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions @@ -19,20 +19,20 @@ HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics - var/FermiExplode = FALSE //If the chemical explodes in a special way - var/ImpureChem = "toxin" //What chemical is produced with an inpure reaction + FermiExplode = FALSE //If the chemical explodes in a special way + ImpureChem = "toxin" //What chemical is produced with an inpure reaction //serum /datum/chemical_reaction/SDGF name = "synthetic-derived growth factor" id = "SDGF" - results = list("SDGF" = `3`) + results = list("SDGF" = 3) required_reagents = list("stable_plasma" = 5, "slimejelly" = 5, "synthflesh" = 10, "blood" = 10) /datum/chemical_reaction/BElarger name = "" id = "e" - results = list("Eigenstasium" = `6`) + results = list("Eigenstasium" = 6) required_reagents = list("salglu_solution" = 1, "milk" = 5, "synthflesh" = 2, "silicon" = 2, "crocin" = 2) //FermiChem vars: OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions diff --git a/tgstation.dme b/tgstation.dme index d7df01ed59..e84c616d64 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2528,9 +2528,15 @@ #include "code\modules\research\techweb\all_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" +#include "code\modules\research\xenobiology\crossbreeding\__corecross.dm" +#include "code\modules\research\xenobiology\crossbreeding\_clothing.dm" +#include "code\modules\research\xenobiology\crossbreeding\_misc.dm" +#include "code\modules\research\xenobiology\crossbreeding\_mobs.dm" #include "code\modules\research\xenobiology\crossbreeding\_status_effects.dm" +#include "code\modules\research\xenobiology\crossbreeding\_weapons.dm" #include "code\modules\research\xenobiology\crossbreeding\burning.dm" #include "code\modules\research\xenobiology\crossbreeding\charged.dm" +#include "code\modules\research\xenobiology\crossbreeding\chilling.dm" #include "code\modules\research\xenobiology\crossbreeding\consuming.dm" #include "code\modules\research\xenobiology\crossbreeding\industrial.dm" #include "code\modules\research\xenobiology\crossbreeding\prismatic.dm" @@ -2772,12 +2778,10 @@ #include "modular_citadel\code\datums\components\material_container.dm" #include "modular_citadel\code\datums\components\phantomthief.dm" #include "modular_citadel\code\datums\components\souldeath.dm" -#include "modular_citadel\code\datums\mood_events\chem_events.dm" #include "modular_citadel\code\datums\mood_events\generic_negative_events.dm" #include "modular_citadel\code\datums\mood_events\generic_positive_events.dm" #include "modular_citadel\code\datums\mood_events\moodular.dm" #include "modular_citadel\code\datums\mutations\hulk.dm" -#include "modular_citadel\code\datums\status_effects\chems.dm" #include "modular_citadel\code\datums\status_effects\debuffs.dm" #include "modular_citadel\code\datums\traits\neutral.dm" #include "modular_citadel\code\datums\wires\airlock.dm" @@ -2957,6 +2961,7 @@ #include "modular_citadel\code\modules\projectiles\projectiles\reusable.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\fermi_reagents.dm" #include "modular_citadel\code\modules\reagents\chemistry\reagents\other_reagents.dm" +#include "modular_citadel\code\modules\reagents\chemistry\recipes\fermi.dm" #include "modular_citadel\code\modules\reagents\reagent container\cit_kegs.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypospraymkii.dm" #include "modular_citadel\code\modules\reagents\reagent container\hypovial.dm" From f55b6ed18aee6ef64542a310ec316d24d773d2e0 Mon Sep 17 00:00:00 2001 From: Useroth Date: Tue, 16 Apr 2019 00:53:44 +0200 Subject: [PATCH 23/61] Another round of unspaghettifying the code. A lot still to go. --- code/modules/reagents/chemistry/holder.dm | 148 +++++++++--------- .../chemistry/reagents/fermi_reagents.dm | 23 +-- .../reagents/chemistry/recipes/fermi.dm | 2 +- 3 files changed, 84 insertions(+), 89 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 2a56467651..7fb78d6895 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -338,13 +338,6 @@ update_total() /datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar - //FermiChem - var/purity = 1 - var/ammoReacted = 0 - var/deltaT = 0 - var/deltapH = 0 - var/stepChemAmmount = 0 - var/list/cached_reagents = reagent_list //a list of the reagents? var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! @@ -376,7 +369,6 @@ var/has_special_react = C.special_react var/can_special_react = 0 //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad - /* var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions var/OptimalTempMax = C.OptimalTempMax var/ExplodeTemp = C.ExplodeTemp @@ -392,16 +384,14 @@ var/FermiChem = C.FermiChem var/FermiExplode = C.FermiExplode var/ImpureChem = C.ImpureChem - */ + //FermiChem - /* var/purity = 1 var/ammoReacted = 0 var/deltaT = 0 var/deltapH = 0 var/stepChemAmmount = 0 - */ for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) @@ -435,6 +425,12 @@ matching_other = 1 //FermiChem + if (chem_temp > ExplodeTemp)//Check to see if reaction is too hot! + if (FermiExplode == TRUE) + //To be added! + else + FermiExplode() + //explode function!! if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! meets_temp_requirement = 1//binary pass @@ -458,7 +454,6 @@ selected_reaction = competitor var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list var/list/cached_results = selected_reaction.results//resultant chemical list - var/special_react_result = selected_reaction.check_special_react(src) var/list/multiplier = INFINITY //Wat for(var/B in cached_required_reagents) // @@ -467,87 +462,84 @@ //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. //FermiChem relies on two additional properties; pH and impurity //Temperature plays into a larger role too. - if(selected_reaction) - var/datum/chemical_reaction/C = selected_reaction - if (C.FermiChem == TRUE) - message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") - //FermiReact(C) - //B is Beaker - //P is product - //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + if (C.FermiChem == TRUE) + message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") + //FermiReact(C) + //B is Beaker + //P is product + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - while (ammoReacted < multiplier) - //Begin Parse + while (ammoReacted < multiplier) + //Begin Parse - //Check extremes first - if (chem_temp > C.ExplodeTemp) - //go to explode proc - FermiExplode() + //Check extremes first + if (chem_temp > ExplodeTemp) + //go to explode proc + FermiExplode() - if (pH > 14 || pH < 0) - //Create chemical sludge eventually(for now just destroy the beaker I guess?) - //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - FermiExplode() + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + FermiExplode() - //For now, purity is handled elsewhere + //For now, purity is handled elsewhere - //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < C.OptimalTempMax) - deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) - else if (chem_temp >= C.OptimalTempMax) - deltaT = 1 + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < OptimalTempMax) + deltaT = (((OptimalTempMin - chem_temp)**CurveSharpT)/((OptimalTempMax - OptimalTempMax)**CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 else - deltaT = 0 - - //Calculate DeltapH (Deviation of pH from optimal) - //Lower range - if (pH < C.OptimalpHMin) - if (pH < (C.OptimalpHMin - C.ReactpHLim)) - deltapH = 0 - else - deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) - //Upper range - else if (pH > C.OptimalpHMin) - if (pH > (C.OptimalpHMin + C.ReactpHLim)) - deltapH = 0 - else - deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) - //Within mid range - else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 1 - //This should never proc: + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 else - message_admins("Fermichem's pH broke!! Please let Fermis know!!") - WARNING("[my_atom] attempted to determine FermiChem pH for '[C]' which broke for some reason! ([usr])") - //TODO Add CatalystFact + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[reagent]' which broke for some reason! ([usr])") + //TODO Add CatalystFact - stepChemAmmount = multiplier * deltaT - //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) + stepChemAmmount = multiplier * deltaT + if (ammoReacted > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) - // End. + // End. - selected_reaction.on_reaction(src, multiplier, special_react_result) + selected_reaction.on_reaction(src, multiplier, special_react_result) - for(var/B in cached_required_reagents) - remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + for(var/B in cached_required_reagents) + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - if (ammoReacted > 0) - P.purity = ((P.purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - P.purity = deltapH - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log - add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - ammoReacted = ammoReacted + stepChemAmmount - - reaction_occurred = 1 + ammoReacted = ammoReacted + stepChemAmmount + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log //Standard reaction mechanics: else: diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index dd66122c7e..26310a813b 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -22,29 +22,30 @@ metabolization_rate = 0.5 * REAGENTS_METABOLISM addiction_stage3_end = 40 addiction_stage4_end = 55 //Incase it's too long + var/turf/open/location_created = null + var/turf/open/location_return = null ///obj/item/reagent/fermi/eigenstate/Initialize() -/datum/reagent/fermi/eigenstate/Initialize() - //. = ..() Unneeded? - var/turf/open/T = get_turf(src)//Sets up coordinate of where it was created - ..() +/datum/reagent/fermi/eigenstate/New() + . = ..() //Unneeded? + location_created = get_turf(src) //Sets up coordinate of where it was created /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! if (holder.has_reagent("eigenstate")) do_sparks(5,FALSE,src) else - var/turf/open/T2 = get_turf(src) //sets up return point + location_return = get_turf(src) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,src) - src.forceMove(T) //Teleports to creation location + M.forceMove(location_created) //Teleports to creation location do_sparks(5,FALSE,src) ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,src) to_chat(M, "You feel your wavefunction collapse!") - src.forceMove(T2) //Teleports home + M.forceMove(location_return) //Teleports home do_sparks(5,FALSE,src) ..() @@ -74,7 +75,9 @@ to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") M.Jitter(50) M.AdjustKnockdown(-40, 0) - for(var/obj/item/I in M.get_contents()); do_teleport(I, get_turf(I), 5, no_effects=TRUE); + for(var/item in M.get_contents()) + var/obj/item/I = item + do_teleport(I, get_turf(I), 5, no_effects=TRUE); ..() /datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! @@ -85,7 +88,7 @@ //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in if(1) var/typepath = M.type - fermi_Tclone = new typepath(M.loc) + var/fermi_Tclone = new typepath(M.loc) //var/mob/living/carbon/O = M var/mob/living/carbon/C = fermi_Tclone C.appearance = M.appearance @@ -143,7 +146,7 @@ var/mob/dead/observer/C = pick(candidates) SM.key = C.key SM.mind.enslave_mind_to_creator(user) - SM.sentience_act() + //SM.sentience_act() to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 4e1a97d269..6456715a96 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -42,7 +42,7 @@ OptimalpHMax = 9.5 // Higest value for above ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) - CurveSharp = 4 // How sharp the exponential curve is (to the power of value) + CurveSharpT = 4 // How sharp the exponential curve is (to the power of value) ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect From a57dc622ef9333a24e7c527f7f126cdaed774b77 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Tue, 16 Apr 2019 17:28:49 +0100 Subject: [PATCH 24/61] holder.dm should be fixed!! --- code/modules/reagents/chemistry/holder.dm | 148 +++++++++--------- .../code/datums/status_effects/chems.dm | 2 - .../chemistry/reagents/fermi_reagents.dm | 11 +- tgstation.dme | 2 + 4 files changed, 88 insertions(+), 75 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 7fb78d6895..79b5df1991 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -369,6 +369,7 @@ var/has_special_react = C.special_react var/can_special_react = 0 //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad + /* var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions var/OptimalTempMax = C.OptimalTempMax var/ExplodeTemp = C.ExplodeTemp @@ -384,14 +385,8 @@ var/FermiChem = C.FermiChem var/FermiExplode = C.FermiExplode var/ImpureChem = C.ImpureChem - + */ //FermiChem - var/purity = 1 - var/ammoReacted = 0 - - var/deltaT = 0 - var/deltapH = 0 - var/stepChemAmmount = 0 for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) @@ -425,8 +420,8 @@ matching_other = 1 //FermiChem - if (chem_temp > ExplodeTemp)//Check to see if reaction is too hot! - if (FermiExplode == TRUE) + if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + if (C.FermiExplode == TRUE) //To be added! else FermiExplode() @@ -454,6 +449,7 @@ selected_reaction = competitor var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list var/list/cached_results = selected_reaction.results//resultant chemical list + var/special_react_result = selected_reaction.check_special_react(src) var/list/multiplier = INFINITY //Wat for(var/B in cached_required_reagents) // @@ -462,84 +458,92 @@ //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. //FermiChem relies on two additional properties; pH and impurity //Temperature plays into a larger role too. - if (C.FermiChem == TRUE) - message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") - //FermiReact(C) - //B is Beaker - //P is product - multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + if(selected_reaction) + var/datum/chemical_reaction/C = selected_reaction + if (C.FermiChem == TRUE) + message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") + //FermiReact(C) + //B is Beaker + //P is product + //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/ammoReacted = 0 - while (ammoReacted < multiplier) - //Begin Parse + var/purity = 1 - //Check extremes first - if (chem_temp > ExplodeTemp) - //go to explode proc - FermiExplode() - if (pH > 14 || pH < 0) - //Create chemical sludge eventually(for now just destroy the beaker I guess?) - //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - FermiExplode() + while (ammoReacted < multiplier) + //Begin Parse - //For now, purity is handled elsewhere + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + FermiExplode() - //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < OptimalTempMax) - deltaT = (((OptimalTempMin - chem_temp)**CurveSharpT)/((OptimalTempMax - OptimalTempMax)**CurveSharpT)) - else if (chem_temp >= C.OptimalTempMax) - deltaT = 1 - else - deltaT = 0 + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + FermiExplode() - //Calculate DeltapH (Deviation of pH from optimal) - //Lower range - if (pH < C.OptimalpHMin) - if (pH < (C.OptimalpHMin - C.ReactpHLim)) - deltapH = 0 + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 else - deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharp)/(C.ReactpHLim**C.CurveSharppH)) - //Upper range - else if (pH > C.OptimalpHMin) - if (pH > (C.OptimalpHMin + C.ReactpHLim)) - deltapH = 0 + deltaT = 0 + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: else - deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) - //Within mid range - else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 1 - //This should never proc: - else - message_admins("Fermichem's pH broke!! Please let Fermis know!!") - WARNING("[my_atom] attempted to determine FermiChem pH for '[reagent]' which broke for some reason! ([usr])") - //TODO Add CatalystFact + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact - stepChemAmmount = multiplier * deltaT - if (ammoReacted > 0) - purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - purity = deltapH - //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) + stepChemAmmount = multiplier * deltaT + if (ammoReacted > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) - // End. + // End. - selected_reaction.on_reaction(src, multiplier, special_react_result) + selected_reaction.on_reaction(src, multiplier, special_react_result) - for(var/B in cached_required_reagents) - remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + for(var/B in cached_required_reagents) + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log - add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + ammoReacted = ammoReacted + stepChemAmmount - ammoReacted = ammoReacted + stepChemAmmount - - reaction_occurred = 1 - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", cached_results[P]*ammoReacted, P)//log + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", ammoReacted, C.id)//log //Standard reaction mechanics: else: diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index f4dea1eb6a..55332b2f00 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -1,5 +1,3 @@ -#define fermiClone = null - /datum/status_effect/chem/SGDF id = "SGDF" //var/mob/living/fermi_Clone diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 26310a813b..b299677c68 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -28,7 +28,7 @@ ///obj/item/reagent/fermi/eigenstate/Initialize() /datum/reagent/fermi/eigenstate/New() - . = ..() //Unneeded? + . = ..() //Needed! location_created = get_turf(src) //Sets up coordinate of where it was created /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! @@ -124,6 +124,15 @@ //eigenstate END //Clone serum #chemClone +/datum/reagent/fermi/SDGF + name = "synthetic-derived growth factor" + id = "SDGF" + description = "A rapidly diving mass of Embryonic stem cells. These cells are missing a nucleus and quickly replicate a host’s DNA before growing to form an almost perfect clone of the host. In some cases neural replication takes longer, though the underlying reason underneath has yet to be determined." + color = "#60A584" // rgb: 96, 0, 255 + var/fClone_current_controller = OWNER + var/mob/living/split_personality/clone//there's two so they can swap without overwriting + var/mob/living/split_personality/owner + /datum/reagent/fermi/SGDF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone diff --git a/tgstation.dme b/tgstation.dme index e84c616d64..1610d0354d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2778,10 +2778,12 @@ #include "modular_citadel\code\datums\components\material_container.dm" #include "modular_citadel\code\datums\components\phantomthief.dm" #include "modular_citadel\code\datums\components\souldeath.dm" +#include "modular_citadel\code\datums\mood_events\chem_events.dm" #include "modular_citadel\code\datums\mood_events\generic_negative_events.dm" #include "modular_citadel\code\datums\mood_events\generic_positive_events.dm" #include "modular_citadel\code\datums\mood_events\moodular.dm" #include "modular_citadel\code\datums\mutations\hulk.dm" +#include "modular_citadel\code\datums\status_effects\chems.dm" #include "modular_citadel\code\datums\status_effects\debuffs.dm" #include "modular_citadel\code\datums\traits\neutral.dm" #include "modular_citadel\code\datums\wires\airlock.dm" From 887aad3bf35244a61f18b6528f54faf3265e77f0 Mon Sep 17 00:00:00 2001 From: Thalpy Date: Tue, 16 Apr 2019 18:02:44 +0100 Subject: [PATCH 25/61] Quick merge!! aaaa --- code/modules/reagents/chemistry/holder.dm | 2 +- .../chemistry/reagents/fermi_reagents.dm | 69 +++++++++++-------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 79b5df1991..9c188c4435 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -470,7 +470,7 @@ var/deltapH = 0 var/stepChemAmmount = 0 var/ammoReacted = 0 - + //get purity from combined beaker reactant purities. var/purity = 1 diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index b299677c68..98577f1218 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -7,6 +7,18 @@ //And tips their hat //Naninte chem +/datum/reagent/fermi + name = "Fermi" + id = "fermi" + taste_description = "If a petpat had a taste, this would be it." + +/datum/reagent/fermi/on_mob_life(mob/living/carbon/M) + current_cycle++ + holder.remove_reagent(src.id, metabolization_rate / M.metabolism_efficiency) //fermi reagents stay longer if you have a better metabolism + +/datum/reagent/fermi/overdose_start(mob/living/carbon/M) + current_cycle++ + //eigenstate Chem //Teleports you to chemistry and back //OD teleports you randomly around the Station @@ -24,6 +36,7 @@ addiction_stage4_end = 55 //Incase it's too long var/turf/open/location_created = null var/turf/open/location_return = null + addictCyc3 = 1 ///obj/item/reagent/fermi/eigenstate/Initialize() @@ -50,16 +63,17 @@ ..() /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly - if(10) - to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") - M.Jitter(10) + switch(current_cycle) + if(10) + to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") + M.Jitter(10) - if(15 to INFINITY) - do_sparks(5,FALSE,src) - do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') - do_sparks(5,FALSE,src) - M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting - ..() + if(15 to INFINITY) + do_sparks(5,FALSE,src) + do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') + do_sparks(5,FALSE,src) + M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting + ..() //..() //loop function @@ -86,26 +100,27 @@ to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in - if(1) - var/typepath = M.type - var/fermi_Tclone = new typepath(M.loc) - //var/mob/living/carbon/O = M - var/mob/living/carbon/C = fermi_Tclone - C.appearance = M.appearance + switch(src.addictCyc3) + if(1) + var/typepath = M.type + var/fermi_Tclone = new typepath(M.loc) + //var/mob/living/carbon/O = M + var/mob/living/carbon/C = fermi_Tclone + C.appearance = M.appearance - //Incase Kevin breaks my code: - //if(istype(C) && istype(O)) - // C.real_name = O.real_name - // O.dna.transfer_identity(C) - // C.updateappearance(mutcolor_update=1) + //Incase Kevin breaks my code: + //if(istype(C) && istype(O)) + // C.real_name = O.real_name + // O.dna.transfer_identity(C) + // C.updateappearance(mutcolor_update=1) - visible_message("[M] collapses in from an alternative reality!") - if(2) - do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! - if(3) - qdel(C) //Deletes CLONE, or at least I hope it is. - visible_message("[M] is snapped across to a different alternative reality!") - .=1 //counter + visible_message("[M] collapses in from an alternative reality!") + if(2) + do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + if(3) + qdel(C) //Deletes CLONE, or at least I hope it is. + visible_message("[M] is snapped across to a different alternative reality!") + src.addictCyc3 = 1 //counter do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly ..() //loop function From e038ba40c7da5c112b3e3b216fcb6915a2462009 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 16 Apr 2019 20:18:14 +0100 Subject: [PATCH 26/61] Fixing errors, down to one last error!! --- .../code/datums/status_effects/chems.dm | 14 +++--- .../chemistry/reagents/fermi_reagents.dm | 44 ++++++++++--------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 55332b2f00..df43c3432a 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -1,16 +1,16 @@ /datum/status_effect/chem/SGDF id = "SGDF" - //var/mob/living/fermi_Clone + var/mob/living/carbon/human/fermi_Clone = null /datum/status_effect/chem/SGDF/on_apply(mob/living/M) var/typepath = M.type - fermiClone = new typepath(M.loc) + fermi_Clone = new typepath(M.loc) //var/mob/living/carbon/M = owner - var/mob/living/carbon/C = fermi_Clone - if(istype(C) && istype(M)) - C.real_name = O.real_name - M.dna.transfer_identity(C) - C.updateappearance(mutcolor_update=1) + //var/mob/living/carbon/C = fermi_Clone + if(istype(fermi_Clone) && istype(M)) + fermi_Clone.real_name = M.real_name + M.dna.transfer_identity(fermi_Clone, transfer_SE=1) + fermi_Clone.updateappearance(mutcolor_update=1) return ..() /datum/status_effect/chem/SGDF/tick(mob/living/M) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 98577f1218..98d20188fe 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -36,7 +36,8 @@ addiction_stage4_end = 55 //Incase it's too long var/turf/open/location_created = null var/turf/open/location_return = null - addictCyc3 = 1 + var/addictCyc3 = 1 + var/mob/living/fermi_Tclone = null ///obj/item/reagent/fermi/eigenstate/Initialize() @@ -44,6 +45,7 @@ . = ..() //Needed! location_created = get_turf(src) //Sets up coordinate of where it was created + /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! if (holder.has_reagent("eigenstate")) do_sparks(5,FALSE,src) @@ -73,7 +75,7 @@ do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') do_sparks(5,FALSE,src) M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting - ..() + ..() //..() //loop function @@ -103,10 +105,10 @@ switch(src.addictCyc3) if(1) var/typepath = M.type - var/fermi_Tclone = new typepath(M.loc) + fermi_Tclone = new typepath(M.loc) //var/mob/living/carbon/O = M - var/mob/living/carbon/C = fermi_Tclone - C.appearance = M.appearance + //var/mob/living/carbon/C = fermi_Tclone + fermi_Tclone.appearance = M.appearance //Incase Kevin breaks my code: //if(istype(C) && istype(O)) @@ -114,13 +116,14 @@ // O.dna.transfer_identity(C) // C.updateappearance(mutcolor_update=1) - visible_message("[M] collapses in from an alternative reality!") + M.visible_message("[M] collapses in from an alternative reality!") if(2) - do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + do_teleport(fermi_Tclone, get_turf(fermi_Tclone), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! if(3) - qdel(C) //Deletes CLONE, or at least I hope it is. - visible_message("[M] is snapped across to a different alternative reality!") + qdel(fermi_Tclone) //Deletes CLONE, or at least I hope it is. + M.visible_message("[M] is snapped across to a different alternative reality!") src.addictCyc3 = 1 //counter + fermi_Tclone = null do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly ..() //loop function @@ -133,8 +136,8 @@ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) ..() -/datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) - return +///datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) +// return //eigenstate END @@ -144,21 +147,22 @@ id = "SDGF" description = "A rapidly diving mass of Embryonic stem cells. These cells are missing a nucleus and quickly replicate a host’s DNA before growing to form an almost perfect clone of the host. In some cases neural replication takes longer, though the underlying reason underneath has yet to be determined." color = "#60A584" // rgb: 96, 0, 255 - var/fClone_current_controller = OWNER + //var/fClone_current_controller = OWNER var/mob/living/split_personality/clone//there's two so they can swap without overwriting var/mob/living/split_personality/owner + //var/mob/living/carbon/SM /datum/reagent/fermi/SGDF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone - var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(LAZYLEN(candidates)) //var/typepath = owner.type //clone = new typepath(owner.loc) var/typepath = M.type - fermi_Gclone = new typepath(M.loc) + var/mob/living/carbon/fermi_Gclone = new typepath(M.loc) //var/mob/living/carbon/SM = owner //var/mob/living/carbon/M = M var/mob/living/carbon/SM = fermi_Gclone @@ -169,18 +173,18 @@ var/mob/dead/observer/C = pick(candidates) SM.key = C.key - SM.mind.enslave_mind_to_creator(user) + SM.mind.enslave_mind_to_creator(M) //SM.sentience_act() to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") - visible_message("[M] suddenly shudders, and splits into two identical twins!") - SM.copy_known_languages_from(user, FALSE) + M.visible_message("[M] suddenly shudders, and splits into two identical twins!") + SM.copy_known_languages_from(M, FALSE) //after_success(user, SM) //qdel(src) else if(20) - O.apply_status_effect(var/datum/status_effect/chem/SGDF) + M.apply_status_effect(/datum/status_effect/chem/SGDF) ..() @@ -196,8 +200,8 @@ /datum/reagent/fermi/BElarger/overdose_start(mob/living/M) //Turns you into a female if male and ODing if(M.gender == MALE) M.gender = FEMALE - M.visible_message("[user] suddenly looks more feminine!", "You suddenly feel more feminine!") + M.visible_message("[M] suddenly looks more feminine!", "You suddenly feel more feminine!") if(M.gender == FEMALE) M.gender = FEMALE - M.visible_message("[user] suddenly looks more masculine!", "You suddenly feel more masculine!") + M.visible_message("[M] suddenly looks more masculine!", "You suddenly feel more masculine!") From 5a7a068b6e400a445171f568d9e8245a68810ca0 Mon Sep 17 00:00:00 2001 From: Useroth Date: Tue, 16 Apr 2019 21:21:16 +0200 Subject: [PATCH 27/61] It compiles now. --- modular_citadel/code/datums/status_effects/chems.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index df43c3432a..65a644da34 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -2,7 +2,7 @@ id = "SGDF" var/mob/living/carbon/human/fermi_Clone = null -/datum/status_effect/chem/SGDF/on_apply(mob/living/M) +/datum/status_effect/chem/SGDF/on_apply(mob/living/carbon/M) var/typepath = M.type fermi_Clone = new typepath(M.loc) //var/mob/living/carbon/M = owner From 390f9a635fda0f09c4bfb5ff9046e2cfa063adc1 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 16 Apr 2019 23:03:24 +0100 Subject: [PATCH 28/61] Error message addition. --- code/modules/reagents/chemistry/holder.dm | 18 ++++++++++++++---- config/admins.txt | 1 + .../chemistry/reagents/fermi_reagents.dm | 1 + .../reagents/chemistry/recipes/fermi.dm | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 9c188c4435..3f559968ff 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -461,7 +461,6 @@ if(selected_reaction) var/datum/chemical_reaction/C = selected_reaction if (C.FermiChem == TRUE) - message_admins("Hee!!!! Someone is doing a Fermi reaction!!! I'm so excited!!") //FermiReact(C) //B is Beaker //P is product @@ -475,27 +474,32 @@ while (ammoReacted < multiplier) + message_admins("Loop beginning") //Begin Parse //Check extremes first if (chem_temp > C.ExplodeTemp) //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") FermiExplode() if (pH > 14 || pH < 0) //Create chemical sludge eventually(for now just destroy the beaker I guess?) //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") FermiExplode() //For now, purity is handled elsewhere //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < C.OptimalTempMax) - deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMax)**C.CurveSharpT)) + if (chem_temp < C.OptimalTempMax || chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + // 350 300 else if (chem_temp >= C.OptimalTempMax) deltaT = 1 else deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") //Calculate DeltapH (Deviation of pH from optimal) //Lower range @@ -518,21 +522,27 @@ message_admins("Fermichem's pH broke!! Please let Fermis know!!") WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") stepChemAmmount = multiplier * deltaT if (ammoReacted > 0) - purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /(2 * (ammoReacted + stepChemAmmount)) //This should add the purity to the product + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product else purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") //Apply pH changes and thermal output of reaction to beaker chem_temp += (C.ThermicConstant * stepChemAmmount) pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") // End. selected_reaction.on_reaction(src, multiplier, special_react_result) + message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") for(var/B in cached_required_reagents) + message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? diff --git a/config/admins.txt b/config/admins.txt index 27a2178e2c..ff2d1362e0 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -9,3 +9,4 @@ ############################################################################################### yourckeygoeshere = Host +Useroth = Game Master diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 98d20188fe..2913c2f2b4 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -44,6 +44,7 @@ /datum/reagent/fermi/eigenstate/New() . = ..() //Needed! location_created = get_turf(src) //Sets up coordinate of where it was created + ..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 6456715a96..5b07dd91c8 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -17,7 +17,7 @@ CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction - RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect + RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics FermiExplode = FALSE //If the chemical explodes in a special way ImpureChem = "toxin" //What chemical is produced with an inpure reaction From 5657fd8cde1d15860bf2e2c0fa28574a3b1e7164 Mon Sep 17 00:00:00 2001 From: Fermi Date: Sat, 20 Apr 2019 03:40:40 +0100 Subject: [PATCH 29/61] endless sadness and exhaustion --- code/modules/reagents/chemistry/holder.dm | 169 +-- code/modules/reagents/chemistry/holderbk3.dm | 961 ++++++++++++++++++ .../reagents/chemistry/holdersplitfail.dm | 958 +++++++++++++++++ 3 files changed, 2006 insertions(+), 82 deletions(-) create mode 100644 code/modules/reagents/chemistry/holderbk3.dm create mode 100644 code/modules/reagents/chemistry/holdersplitfail.dm diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 3f559968ff..c38f065383 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -1,4 +1,3 @@ - /proc/build_chemical_reagent_list() //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id @@ -458,102 +457,108 @@ //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. //FermiChem relies on two additional properties; pH and impurity //Temperature plays into a larger role too. - if(selected_reaction) - var/datum/chemical_reaction/C = selected_reaction - if (C.FermiChem == TRUE) - //FermiReact(C) - //B is Beaker - //P is product - //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - var/deltaT = 0 - var/deltapH = 0 - var/stepChemAmmount = 0 - var/ammoReacted = 0 - //get purity from combined beaker reactant purities. - var/purity = 1 + //if(selected_reaction) + var/datum/chemical_reaction/C = selected_reaction + if (C.FermiChem == TRUE) + //FermiReact(C) + //B is Beaker + //P is product + //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/ammoReacted = 0 + //get purity from combined beaker reactant purities. + var/purity = 1 - while (ammoReacted < multiplier) - message_admins("Loop beginning") - //Begin Parse + while (ammoReacted < multiplier) + message_admins("Loop beginning") + CHECK_TICK + //Begin Parse - //Check extremes first - if (chem_temp > C.ExplodeTemp) - //go to explode proc - message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") - FermiExplode() + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") + FermiExplode() - if (pH > 14 || pH < 0) - //Create chemical sludge eventually(for now just destroy the beaker I guess?) - //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - message_admins("pH is lover limit, cur pH: [pH]") - FermiExplode() + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") + FermiExplode() - //For now, purity is handled elsewhere + //For now, purity is handled elsewhere - //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < C.OptimalTempMax || chem_temp >= C.OptimalTempMin) - deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) - // 350 300 - else if (chem_temp >= C.OptimalTempMax) - deltaT = 1 + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax || chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + // 350 300 + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 else - deltaT = 0 - message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") - - //Calculate DeltapH (Deviation of pH from optimal) - //Lower range - if (pH < C.OptimalpHMin) - if (pH < (C.OptimalpHMin - C.ReactpHLim)) - deltapH = 0 - else - deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) - //Upper range - else if (pH > C.OptimalpHMin) - if (pH > (C.OptimalpHMin + C.ReactpHLim)) - deltapH = 0 - else - deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) - //Within mid range - else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 1 - //This should never proc: + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 else - message_admins("Fermichem's pH broke!! Please let Fermis know!!") - WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") - //TODO Add CatalystFact - message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") - stepChemAmmount = multiplier * deltaT - if (ammoReacted > 0) - purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - purity = deltapH - message_admins("purity: [purity], purity of beaker") - message_admins("Temp before change: [chem_temp], pH after change: [pH]") - //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) - message_admins("Temp after change: [chem_temp], pH after change: [pH]") + stepChemAmmount = multiplier * deltaT + if (stepChemAmmount > C.RateUpLim) + stepChemAmmount = C.RateUpLim + else if (stepChemAmmount < 0.01) + stepChemAmmount = 0.1 + if (ammoReacted > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") - // End. + // End. - selected_reaction.on_reaction(src, multiplier, special_react_result) + selected_reaction.on_reaction(src, multiplier, special_react_result) + message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") + for(var/B in cached_required_reagents) message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") - for(var/B in cached_required_reagents) - message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") - remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log - add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - ammoReacted = ammoReacted + stepChemAmmount + ammoReacted = ammoReacted + stepChemAmmount + CHECK_TICK - reaction_occurred = 1 - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", ammoReacted, C.id)//log + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", ammoReacted, C.id)//log //Standard reaction mechanics: else: @@ -959,4 +964,4 @@ if(initial(R.can_synth)) random_reagents += initial(R.id) var/picked_reagent = pick(random_reagents) - return picked_reagent + return picked_reagent \ No newline at end of file diff --git a/code/modules/reagents/chemistry/holderbk3.dm b/code/modules/reagents/chemistry/holderbk3.dm new file mode 100644 index 0000000000..06e99bac96 --- /dev/null +++ b/code/modules/reagents/chemistry/holderbk3.dm @@ -0,0 +1,961 @@ + +/proc/build_chemical_reagent_list() + //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id + + if(GLOB.chemical_reagents_list) + return + + var/paths = subtypesof(/datum/reagent) + GLOB.chemical_reagents_list = list() + + for(var/path in paths) + var/datum/reagent/D = new path() + GLOB.chemical_reagents_list[D.id] = D + +/proc/build_chemical_reactions_list() + //Chemical Reactions - Initialises all /datum/chemical_reaction into a list + // It is filtered into multiple lists within a list. + // For example: + // chemical_reaction_list["plasma"] is a list of all reactions relating to plasma + + if(GLOB.chemical_reactions_list) + return + + var/paths = subtypesof(/datum/chemical_reaction) + GLOB.chemical_reactions_list = list() + + for(var/path in paths) + + var/datum/chemical_reaction/D = new path() + var/list/reaction_ids = list() + + if(D.required_reagents && D.required_reagents.len) + for(var/reaction in D.required_reagents) + reaction_ids += reaction + + // Create filters based on each reagent id in the required reagents list + for(var/id in reaction_ids) + if(!GLOB.chemical_reactions_list[id]) + GLOB.chemical_reactions_list[id] = list() + GLOB.chemical_reactions_list[id] += D + break // Don't bother adding ourselves to other reagent ids, it is redundant + +/////////////////////////////////////////////////////////////////////////////////// + +/datum/reagents + var/list/datum/reagent/reagent_list = new/list() + var/total_volume = 0 + var/maximum_volume = 100 + var/atom/my_atom = null + var/chem_temp = 150 + var/pH = REAGENT_NORMAL_PH + var/last_tick = 1 + var/addiction_tick = 1 + var/list/datum/reagent/addiction_list = new/list() + var/reagents_holder_flags + +/datum/reagents/New(maximum=100) + maximum_volume = maximum + + //I dislike having these here but map-objects are initialised before world/New() is called. >_> + if(!GLOB.chemical_reagents_list) + build_chemical_reagent_list() + if(!GLOB.chemical_reactions_list) + build_chemical_reactions_list() + +/datum/reagents/Destroy() + . = ..() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + qdel(R) + cached_reagents.Cut() + cached_reagents = null + if(my_atom && my_atom.reagents == src) + my_atom.reagents = null + my_atom = null + +// Used in attack logs for reagents in pills and such +/datum/reagents/proc/log_list() + if(!length(reagent_list)) + return "no reagents" + + var/list/data = list() + for(var/r in reagent_list) //no reagents will be left behind + var/datum/reagent/R = r + data += "[R.id] ([round(R.volume, 0.1)]u)" + //Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. + return english_list(data) + +/datum/reagents/proc/remove_any(amount = 1) + var/list/cached_reagents = reagent_list + var/total_transfered = 0 + var/current_list_element = 1 + + current_list_element = rand(1, cached_reagents.len) + + while(total_transfered != amount) + if(total_transfered >= amount) + break + if(total_volume <= 0 || !cached_reagents.len) + break + + if(current_list_element > cached_reagents.len) + current_list_element = 1 + + var/datum/reagent/R = cached_reagents[current_list_element] + remove_reagent(R.id, 1) + + current_list_element++ + total_transfered++ + update_total() + + handle_reactions() + return total_transfered + +/datum/reagents/proc/remove_all(amount = 1) + var/list/cached_reagents = reagent_list + if(total_volume > 0) + var/part = amount / total_volume + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + remove_reagent(R.id, R.volume * part) + + update_total() + handle_reactions() + return amount + +/datum/reagents/proc/get_master_reagent_name() + var/list/cached_reagents = reagent_list + var/name + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + name = R.name + + return name + +/datum/reagents/proc/get_master_reagent_id() + var/list/cached_reagents = reagent_list + var/id + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + id = R.id + + return id + +/datum/reagents/proc/get_master_reagent() + var/list/cached_reagents = reagent_list + var/datum/reagent/master + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + master = R + + return master + +/datum/reagents/proc/trans_to(obj/target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + if(amount < 0) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume) + var/part = amount / src.total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/transfer_amount = T.volume * part + if(preserve_data) + trans_data = copy_data(T) + + //fermichem Added ph TODO: add T.purity + R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + //R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + remove_reagent(T.id, transfer_amount) + + update_total() + R.update_total() + if(!no_react) + R.handle_reactions() + src.handle_reactions() + return amount + +/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1) + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + + if(amount < 0) + return + amount = min(min(amount, total_volume), R.maximum_volume-R.total_volume) + var/part = amount / total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/copy_amount = T.volume * part + if(preserve_data) + trans_data = T.data + R.add_reagent(T.id, copy_amount * multiplier, trans_data) + + src.update_total() + R.update_total() + R.handle_reactions() + 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 + var/list/cached_reagents = reagent_list + if (!target) + return + if (!target.reagents || src.total_volume<=0 || !src.get_reagent_amount(reagent)) + return + if(amount < 0) + return + + var/datum/reagents/R = target.reagents + if(src.get_reagent_amount(reagent)= R.overdose_threshold && !R.overdosed) + R.overdosed = 1 + need_mob_update += R.overdose_start(C) + if(R.addiction_threshold) + if(R.volume >= R.addiction_threshold && !is_type_in_list(R, cached_addictions)) + var/datum/reagent/new_reagent = new R.type() + cached_addictions.Add(new_reagent) + if(R.overdosed) + need_mob_update += R.overdose_process(C) + if(is_type_in_list(R,cached_addictions)) + for(var/addiction in cached_addictions) + var/datum/reagent/A = addiction + if(istype(R, A)) + A.addiction_stage = -15 // you're satisfied for a good while. + need_mob_update += R.on_mob_life(C) + + if(can_overdose) + if(addiction_tick == 6) + addiction_tick = 1 + for(var/addiction in cached_addictions) + var/datum/reagent/R = addiction + if(C && R) + R.addiction_stage++ + if(1 <= R.addiction_stage && R.addiction_stage <= R.addiction_stage1_end) + need_mob_update += R.addiction_act_stage1(C) + else if(R.addiction_stage1_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage2_end) + need_mob_update += R.addiction_act_stage2(C) + else if(R.addiction_stage2_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage3_end) + need_mob_update += R.addiction_act_stage3(C) + else if(R.addiction_stage3_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage4_end) + need_mob_update += R.addiction_act_stage4(C) + else if(R.addiction_stage4_end <= R.addiction_stage) + to_chat(C, "You feel like you've gotten over your need for [R.name].") + SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.id]_addiction") + cached_addictions.Remove(R) + addiction_tick++ + if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates. + C.updatehealth() + C.update_canmove() + C.update_stamina() + update_total() + + +/datum/reagents/proc/set_reacting(react = TRUE) + if(react) + reagents_holder_flags &= ~(REAGENT_NOREACT) + else + reagents_holder_flags |= REAGENT_NOREACT + +/datum/reagents/proc/conditional_update_move(atom/A, Running = 0) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_move (A, Running) + update_total() + +/datum/reagents/proc/conditional_update(atom/A) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_update (A) + update_total() + +/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + var/list/cached_reagents = reagent_list //a list of the reagents? + var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? + var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! + if(reagents_holder_flags & REAGENT_NOREACT) //Not sure on reagents_holder_flags, but I think it checks to see if theres a reaction with current stuff. + return //Yup, no reactions here. No siree. + + var/reaction_occurred = 0 // checks if reaction, binary variable + do //What does do do in byond? It sounds very redundant? is it a while loop? + var/list/possible_reactions = list() //init list + reaction_occurred = 0 // sets it back to 0? + for(var/reagent in cached_reagents) //for reagent in beaker/holder + var/datum/reagent/R = reagent //check to make sure that reagent is there for the reaction list + for(var/reaction in cached_reactions[R.id]) // Was a big list but now it should be smaller since we filtered it with our reagent id + if(!reaction) + continue + + var/datum/chemical_reaction/C = reaction + var/list/cached_required_reagents = C.required_reagents + var/total_required_reagents = cached_required_reagents.len + var/total_matching_reagents = 0 + var/list/cached_required_catalysts = C.required_catalysts + var/total_required_catalysts = cached_required_catalysts.len + var/total_matching_catalysts= 0 + var/matching_container = 0 + var/matching_other = 0 + var/required_temp = C.required_temp + var/is_cold_recipe = C.is_cold_recipe + var/meets_temp_requirement = 0 + var/has_special_react = C.special_react + var/can_special_react = 0 + var/reactedVol = 0 + + for(var/B in cached_required_reagents) + if(!has_reagent(B, cached_required_reagents[B])) + break + total_matching_reagents++ + for(var/B in cached_required_catalysts) + if(!has_reagent(B, cached_required_catalysts[B])) + break + total_matching_catalysts++ + if(cached_my_atom) + if(!C.required_container) + matching_container = 1 + + else + if(cached_my_atom.type == C.required_container)//if the suspected container is a container + matching_container = 1 + if (isliving(cached_my_atom) && !C.mob_react) //Makes it so certain chemical reactions don't occur in mobs + return + if(!C.required_other)//Checks for other things required + matching_other = 1//binary check passes + + else if(istype(cached_my_atom, /obj/item/slime_extract))//if the object is a slime_extract. This might be complicated as to not break them via fermichem + var/obj/item/slime_extract/M = cached_my_atom + + if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this + matching_other = 1 + else + if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? Oh, cyro. + matching_container = 1 + if(!C.required_other) + matching_other = 1 + + //FermiChem + /* + if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + if (C.FermiExplode == TRUE) + //To be added! + else + FermiExplode() + //explode function!! + */ + + if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! + meets_temp_requirement = 1//binary pass + + if(!has_special_react || C.check_special_react(src)) + can_special_react = 1 + + if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other && meets_temp_requirement && can_special_react) + possible_reactions += C + + if(possible_reactions.len)//does list exist? + var/datum/chemical_reaction/selected_reaction = possible_reactions[1] + //select the reaction with the most extreme temperature requirements + for(var/V in possible_reactions)//why V, surely that would indicate volume? V is the reaction potential. + var/datum/chemical_reaction/competitor = V //competitor? I think this is theres two of them. Troubling..! + if(selected_reaction.is_cold_recipe) //if there are no recipe conflicts, everything in possible_reactions will have this same value for is_cold_reaction. warranty void if assumption not met. + if(competitor.required_temp <= selected_reaction.required_temp)//only returns with lower if reaction "is cold" var. + selected_reaction = competitor + else + if(competitor.required_temp >= selected_reaction.required_temp) //will return with the hotter reacting first. + selected_reaction = competitor + var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list + var/list/cached_results = selected_reaction.results//resultant chemical list + var/special_react_result = selected_reaction.check_special_react(src) + var/list/multiplier = INFINITY //Wat + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. + //FermiChem relies on two additional properties; pH and impurity + //Temperature plays into a larger role too. + //BRANCH HERE + if(selected_reaction) + var/datum/chemical_reaction/C = selected_reaction + + if (C.FermiChem == TRUE) + message_admins("FermiChem Proc'd") + + while (reaction_occurred < 1) + reaction_occurred, reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier) + CHECK_TICK + + //Standard reaction mechanics: + else + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + for(var/B in cached_required_reagents) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: + + + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/iconhtml = icon2html(cached_my_atom, seen) + if(cached_my_atom) + if(!ismob(cached_my_atom)) // No bubbling mobs + if(selected_reaction.mix_sound) + playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + + for(var/mob/M in seen) + to_chat(M, "[iconhtml] [selected_reaction.mix_message]") + + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in seen) + to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." + + selected_reaction.on_reaction(src, multiplier, special_react_result) + reaction_occurred = 1 + + while(reaction_occurred)//while do nothing? + update_total()//Don't know waht this does. + return 0//end! + +/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, totalVol) + var/datum/chemical_reaction/C = selected_reaction + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/ammoReacted = 0 + //get purity from combined beaker reactant purities HERE. + var/purity = 1 + //var/tempVol = totalVol + //var/list/multiplier = INFINITY + + message_admins("Loop beginning") + //Begin Parse + + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") + FermiExplode() + + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") + FermiExplode() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax && chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") + + stepChemAmmount = tempVol * deltaT + if (stepChemAmmount > C.RateUpLim) + stepChemAmmount = C.RateUpLim + else if (stepChemAmmount < 0.01) + stepChemAmmount = 0.01 + + if (ammoReacted > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") + + // End. + + selected_reaction.on_reaction(src, multiplier, special_react_result) + + for(var/B in cached_required_reagents) // + tempVol = min(totalVol, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + message_admins("cached_results: [cached_results], totalVol: [totalVol], stepChemAmmount [stepChemAmmount]") + for(var/B in cached_required_reagents) + message_admins("cached_required_reagents(B): [cached_required_reagents[B]], totalVol: [totalVol], base stepChemAmmount [stepChemAmmount]") + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + totalVol = max(totalVol, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + + ammoReacted = ammoReacted + stepChemAmmount + + if ammoReacted = totalVol + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", ammoReacted, C.id)//log + + CHECK_TICK + return (reaction_occurred, ammoReacted) + +/datum/reagents/proc/FermiExplode() + return + +/datum/reagents/proc/isolate_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id != reagent) + del_reagent(R.id) + update_total() + +/datum/reagents/proc/del_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id == reagent) + if(my_atom && isliving(my_atom)) + var/mob/living/M = my_atom + R.on_mob_delete(M) + qdel(R) + reagent_list -= R + update_total() + if(my_atom) + my_atom.on_reagent_change(DEL_REAGENT) + return 1 + +/datum/reagents/proc/update_total() + var/list/cached_reagents = reagent_list + total_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume < 0.1) + del_reagent(R.id) + else + total_volume += R.volume + + return 0 + +/datum/reagents/proc/clear_reagents() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + del_reagent(R.id) + return 0 + +/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1) + var/react_type + if(isliving(A)) + react_type = "LIVING" + if(method == INGEST) + var/mob/living/L = A + L.taste(src) + else if(isturf(A)) + react_type = "TURF" + else if(isobj(A)) + react_type = "OBJ" + else + return + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + switch(react_type) + if("LIVING") + var/touch_protection = 0 + if(method == VAPOR) + var/mob/living/L = A + touch_protection = L.get_permeability_protection() + R.reaction_mob(A, method, R.volume * volume_modifier, show_message, touch_protection) + if("TURF") + R.reaction_turf(A, R.volume * volume_modifier, show_message) + if("OBJ") + R.reaction_obj(A, R.volume * volume_modifier, show_message) + +/datum/reagents/proc/holder_full() + if(total_volume >= maximum_volume) + return TRUE + return FALSE + +//Returns the average specific heat for all reagents currently in this holder. +/datum/reagents/proc/specific_heat() + . = 0 + var/cached_amount = total_volume //cache amount + var/list/cached_reagents = reagent_list //cache reagents + for(var/I in cached_reagents) + var/datum/reagent/R = I + . += R.specific_heat * (R.volume / cached_amount) + +/datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000) + var/S = specific_heat() + chem_temp = CLAMP(chem_temp + (J / (S * total_volume)), 2.7, 1000) + +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, pH = 7, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ + if(!isnum(amount) || !amount) + return FALSE + + if(amount <= 0) + return FALSE + + var/datum/reagent/D = GLOB.chemical_reagents_list[reagent] + if(!D) + WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") + return FALSE + + update_total() + var/cached_total = total_volume + if(cached_total + amount > maximum_volume) + amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. Shouldnt happen. Will happen. + if(amount <= 0) + return FALSE + var/new_total = cached_total + amount + var/cached_temp = chem_temp + var/list/cached_reagents = reagent_list + + //Equalize temperature - Not using specific_heat() because the new chemical isn't in yet. + var/specific_heat = 0 + var/thermal_energy = 0 + for(var/i in cached_reagents) + var/datum/reagent/R = i + specific_heat += R.specific_heat * (R.volume / new_total) + thermal_energy += R.specific_heat * R.volume * cached_temp + specific_heat += D.specific_heat * (amount / new_total) + thermal_energy += D.specific_heat * amount * reagtemp + chem_temp = thermal_energy / (specific_heat * new_total) + //// + + //add the reagent to the existing if it exists + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + R.volume += amount + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + R.on_merge(data, amount) + if(!no_react) + handle_reactions() + return TRUE + + //otherwise make a new one + var/datum/reagent/R = new D.type(data) + cached_reagents += R + R.holder = src + R.volume = amount + if(data) + R.data = data + R.on_new(data) + + if(isliving(my_atom)) + R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + if(!no_react) + handle_reactions() + return TRUE + +/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list("toxin" = 10, "beer" = 15) + for(var/r_id in list_reagents) + var/amt = list_reagents[r_id] + add_reagent(r_id, amt, data) + +/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to + + if(isnull(amount)) + amount = 0 + CRASH("null amount passed to reagent code") + return FALSE + + if(!isnum(amount)) + return FALSE + + if(amount < 0) + return FALSE + + var/list/cached_reagents = reagent_list + + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + //clamp the removal amount to be between current reagent amount + //and zero, to prevent removing more than the holder has stored + amount = CLAMP(amount, 0, R.volume) + R.volume -= amount + update_total() + if(!safety)//So it does not handle reactions when it need not to + handle_reactions() + if(my_atom) + my_atom.on_reagent_change(REM_REAGENT) + return TRUE + + return FALSE + +/datum/reagents/proc/has_reagent(reagent, amount = -1) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + if(!amount) + return R + else + if(R.volume >= amount) + return R + else + return 0 + + return 0 + +/datum/reagents/proc/get_reagent_amount(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + return R.volume + + return 0 + +/datum/reagents/proc/get_reagents() + var/list/names = list() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + names += R.name + + return jointext(names, ",") + +/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included. + if(!isnum(amount)) + return 1 + var/list/cached_reagents = reagent_list + var/has_removed_reagent = 0 + + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + var/matches = 0 + // Switch between how we check the reagent type + if(strict) + if(R.type == reagent_type) + matches = 1 + else + if(istype(R, reagent_type)) + matches = 1 + // We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type. + if(matches) + // Have our other proc handle removement + has_removed_reagent = remove_reagent(R.id, amount, safety) + + return has_removed_reagent + +//two helper functions to preserve data across reactions (needed for xenoarch) +/datum/reagents/proc/get_data(reagent_id) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + return R.data + +/datum/reagents/proc/set_data(reagent_id, new_data) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + R.data = new_data + +/datum/reagents/proc/copy_data(datum/reagent/current_reagent) + if(!current_reagent || !current_reagent.data) + return null + if(!istype(current_reagent.data, /list)) + return current_reagent.data + + var/list/trans_data = current_reagent.data.Copy() + + // We do this so that introducing a virus to a blood sample + // doesn't automagically infect all other blood samples from + // the same donor. + // + // Technically we should probably copy all data lists, but + // that could possibly eat up a lot of memory needlessly + // if most data lists are read-only. + if(trans_data["viruses"]) + var/list/v = trans_data["viruses"] + trans_data["viruses"] = v.Copy() + + return trans_data + +/datum/reagents/proc/get_reagent(type) + var/list/cached_reagents = reagent_list + . = locate(type) in cached_reagents + +/datum/reagents/proc/generate_taste_message(minimum_percent=15) + // the lower the minimum percent, the more sensitive the message is. + var/list/out = list() + var/list/tastes = list() //descriptor = strength + if(minimum_percent <= 100) + for(var/datum/reagent/R in reagent_list) + if(!R.taste_mult) + continue + + if(istype(R, /datum/reagent/consumable/nutriment)) + var/list/taste_data = R.data + for(var/taste in taste_data) + var/ratio = taste_data[taste] + var/amount = ratio * R.taste_mult * R.volume + if(taste in tastes) + tastes[taste] += amount + else + tastes[taste] = amount + else + var/taste_desc = R.taste_description + var/taste_amount = R.volume * R.taste_mult + if(taste_desc in tastes) + tastes[taste_desc] += taste_amount + else + tastes[taste_desc] = taste_amount + //deal with percentages + // TODO it would be great if we could sort these from strong to weak + var/total_taste = counterlist_sum(tastes) + if(total_taste > 0) + for(var/taste_desc in tastes) + var/percent = tastes[taste_desc]/total_taste * 100 + if(percent < minimum_percent) + continue + var/intensity_desc = "a hint of" + if(percent > minimum_percent * 2 || percent == 100) + intensity_desc = "" + else if(percent > minimum_percent * 3) + intensity_desc = "the strong flavor of" + if(intensity_desc != "") + out += "[intensity_desc] [taste_desc]" + else + out += "[taste_desc]" + + return english_list(out, "something indescribable") + +/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02) + var/temp_delta = (temperature - chem_temp) * coeff + if(temp_delta > 0) + chem_temp = min(chem_temp + max(temp_delta, 1), temperature) + else + chem_temp = max(chem_temp + min(temp_delta, -1), temperature) + chem_temp = round(chem_temp) + handle_reactions() + +/////////////////////////////////////////////////////////////////////////////////// + + +// Convenience proc to create a reagents holder for an atom +// Max vol is maximum volume of holder +/atom/proc/create_reagents(max_vol) + if(reagents) + qdel(reagents) + reagents = new/datum/reagents(max_vol) + reagents.my_atom = src + +/proc/get_random_reagent_id() // Returns a random reagent ID minus blacklisted reagents + var/static/list/random_reagents = list() + if(!random_reagents.len) + for(var/thing in subtypesof(/datum/reagent)) + var/datum/reagent/R = thing + if(initial(R.can_synth)) + random_reagents += initial(R.id) + var/picked_reagent = pick(random_reagents) + return picked_reagent diff --git a/code/modules/reagents/chemistry/holdersplitfail.dm b/code/modules/reagents/chemistry/holdersplitfail.dm new file mode 100644 index 0000000000..be39ee3448 --- /dev/null +++ b/code/modules/reagents/chemistry/holdersplitfail.dm @@ -0,0 +1,958 @@ + +/proc/build_chemical_reagent_list() + //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id + + if(GLOB.chemical_reagents_list) + return + + var/paths = subtypesof(/datum/reagent) + GLOB.chemical_reagents_list = list() + + for(var/path in paths) + var/datum/reagent/D = new path() + GLOB.chemical_reagents_list[D.id] = D + +/proc/build_chemical_reactions_list() + //Chemical Reactions - Initialises all /datum/chemical_reaction into a list + // It is filtered into multiple lists within a list. + // For example: + // chemical_reaction_list["plasma"] is a list of all reactions relating to plasma + + if(GLOB.chemical_reactions_list) + return + + var/paths = subtypesof(/datum/chemical_reaction) + GLOB.chemical_reactions_list = list() + + for(var/path in paths) + + var/datum/chemical_reaction/D = new path() + var/list/reaction_ids = list() + + if(D.required_reagents && D.required_reagents.len) + for(var/reaction in D.required_reagents) + reaction_ids += reaction + + // Create filters based on each reagent id in the required reagents list + for(var/id in reaction_ids) + if(!GLOB.chemical_reactions_list[id]) + GLOB.chemical_reactions_list[id] = list() + GLOB.chemical_reactions_list[id] += D + break // Don't bother adding ourselves to other reagent ids, it is redundant + +/////////////////////////////////////////////////////////////////////////////////// + +/datum/reagents + var/list/datum/reagent/reagent_list = new/list() + var/total_volume = 0 + var/maximum_volume = 100 + var/atom/my_atom = null + var/chem_temp = 150 + var/pH = REAGENT_NORMAL_PH + var/last_tick = 1 + var/addiction_tick = 1 + var/list/datum/reagent/addiction_list = new/list() + var/reagents_holder_flags + +/datum/reagents/New(maximum=100) + maximum_volume = maximum + + //I dislike having these here but map-objects are initialised before world/New() is called. >_> + if(!GLOB.chemical_reagents_list) + build_chemical_reagent_list() + if(!GLOB.chemical_reactions_list) + build_chemical_reactions_list() + +/datum/reagents/Destroy() + . = ..() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + qdel(R) + cached_reagents.Cut() + cached_reagents = null + if(my_atom && my_atom.reagents == src) + my_atom.reagents = null + my_atom = null + +// Used in attack logs for reagents in pills and such +/datum/reagents/proc/log_list() + if(!length(reagent_list)) + return "no reagents" + + var/list/data = list() + for(var/r in reagent_list) //no reagents will be left behind + var/datum/reagent/R = r + data += "[R.id] ([round(R.volume, 0.1)]u)" + //Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. + return english_list(data) + +/datum/reagents/proc/remove_any(amount = 1) + var/list/cached_reagents = reagent_list + var/total_transfered = 0 + var/current_list_element = 1 + + current_list_element = rand(1, cached_reagents.len) + + while(total_transfered != amount) + if(total_transfered >= amount) + break + if(total_volume <= 0 || !cached_reagents.len) + break + + if(current_list_element > cached_reagents.len) + current_list_element = 1 + + var/datum/reagent/R = cached_reagents[current_list_element] + remove_reagent(R.id, 1) + + current_list_element++ + total_transfered++ + update_total() + + handle_reactions() + return total_transfered + +/datum/reagents/proc/remove_all(amount = 1) + var/list/cached_reagents = reagent_list + if(total_volume > 0) + var/part = amount / total_volume + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + remove_reagent(R.id, R.volume * part) + + update_total() + handle_reactions() + return amount + +/datum/reagents/proc/get_master_reagent_name() + var/list/cached_reagents = reagent_list + var/name + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + name = R.name + + return name + +/datum/reagents/proc/get_master_reagent_id() + var/list/cached_reagents = reagent_list + var/id + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + id = R.id + + return id + +/datum/reagents/proc/get_master_reagent() + var/list/cached_reagents = reagent_list + var/datum/reagent/master + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + master = R + + return master + +/datum/reagents/proc/trans_to(obj/target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + if(amount < 0) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume) + var/part = amount / src.total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/transfer_amount = T.volume * part + if(preserve_data) + trans_data = copy_data(T) + + //fermichem Added ph TODO: add T.purity + R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + //R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + remove_reagent(T.id, transfer_amount) + + update_total() + R.update_total() + if(!no_react) + R.handle_reactions() + src.handle_reactions() + return amount + +/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1) + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + + if(amount < 0) + return + amount = min(min(amount, total_volume), R.maximum_volume-R.total_volume) + var/part = amount / total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/copy_amount = T.volume * part + if(preserve_data) + trans_data = T.data + R.add_reagent(T.id, copy_amount * multiplier, trans_data) + + src.update_total() + R.update_total() + R.handle_reactions() + 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 + var/list/cached_reagents = reagent_list + if (!target) + return + if (!target.reagents || src.total_volume<=0 || !src.get_reagent_amount(reagent)) + return + if(amount < 0) + return + + var/datum/reagents/R = target.reagents + if(src.get_reagent_amount(reagent)= R.overdose_threshold && !R.overdosed) + R.overdosed = 1 + need_mob_update += R.overdose_start(C) + if(R.addiction_threshold) + if(R.volume >= R.addiction_threshold && !is_type_in_list(R, cached_addictions)) + var/datum/reagent/new_reagent = new R.type() + cached_addictions.Add(new_reagent) + if(R.overdosed) + need_mob_update += R.overdose_process(C) + if(is_type_in_list(R,cached_addictions)) + for(var/addiction in cached_addictions) + var/datum/reagent/A = addiction + if(istype(R, A)) + A.addiction_stage = -15 // you're satisfied for a good while. + need_mob_update += R.on_mob_life(C) + + if(can_overdose) + if(addiction_tick == 6) + addiction_tick = 1 + for(var/addiction in cached_addictions) + var/datum/reagent/R = addiction + if(C && R) + R.addiction_stage++ + if(1 <= R.addiction_stage && R.addiction_stage <= R.addiction_stage1_end) + need_mob_update += R.addiction_act_stage1(C) + else if(R.addiction_stage1_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage2_end) + need_mob_update += R.addiction_act_stage2(C) + else if(R.addiction_stage2_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage3_end) + need_mob_update += R.addiction_act_stage3(C) + else if(R.addiction_stage3_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage4_end) + need_mob_update += R.addiction_act_stage4(C) + else if(R.addiction_stage4_end <= R.addiction_stage) + to_chat(C, "You feel like you've gotten over your need for [R.name].") + SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.id]_addiction") + cached_addictions.Remove(R) + addiction_tick++ + if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates. + C.updatehealth() + C.update_canmove() + C.update_stamina() + update_total() + + +/datum/reagents/proc/set_reacting(react = TRUE) + if(react) + reagents_holder_flags &= ~(REAGENT_NOREACT) + else + reagents_holder_flags |= REAGENT_NOREACT + +/datum/reagents/proc/conditional_update_move(atom/A, Running = 0) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_move (A, Running) + update_total() + +/datum/reagents/proc/conditional_update(atom/A) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_update (A) + update_total() + +/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + var/list/cached_reagents = reagent_list //a list of the reagents? + var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? + var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! + if(reagents_holder_flags & REAGENT_NOREACT) //Not sure on reagents_holder_flags, but I think it checks to see if theres a reaction with current stuff. + return //Yup, no reactions here. No siree. + + var/reaction_occurred = 0 // checks if reaction, binary variable + do //What does do do in byond? It sounds very redundant? is it a while loop? + var/list/possible_reactions = list() //init list + reaction_occurred = 0 // sets it back to 0? + for(var/reagent in cached_reagents) //for reagent in beaker/holder + var/datum/reagent/R = reagent //check to make sure that reagent is there for the reaction list + for(var/reaction in cached_reactions[R.id]) // Was a big list but now it should be smaller since we filtered it with our reagent id + if(!reaction) + continue + + var/datum/chemical_reaction/C = reaction + var/list/cached_required_reagents = C.required_reagents + var/total_required_reagents = cached_required_reagents.len + var/total_matching_reagents = 0 + var/list/cached_required_catalysts = C.required_catalysts + var/total_required_catalysts = cached_required_catalysts.len + var/total_matching_catalysts= 0 + var/matching_container = 0 + var/matching_other = 0 + var/required_temp = C.required_temp + var/is_cold_recipe = C.is_cold_recipe + var/meets_temp_requirement = 0 + var/has_special_react = C.special_react + var/can_special_react = 0 + var/reactedVol = 0 + + for(var/B in cached_required_reagents) + if(!has_reagent(B, cached_required_reagents[B])) + break + total_matching_reagents++ + for(var/B in cached_required_catalysts) + if(!has_reagent(B, cached_required_catalysts[B])) + break + total_matching_catalysts++ + if(cached_my_atom) + if(!C.required_container) + matching_container = 1 + + else + if(cached_my_atom.type == C.required_container)//if the suspected container is a container + matching_container = 1 + if (isliving(cached_my_atom) && !C.mob_react) //Makes it so certain chemical reactions don't occur in mobs + return + if(!C.required_other)//Checks for other things required + matching_other = 1//binary check passes + + else if(istype(cached_my_atom, /obj/item/slime_extract))//if the object is a slime_extract. This might be complicated as to not break them via fermichem + var/obj/item/slime_extract/M = cached_my_atom + + if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this + matching_other = 1 + else + if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? Oh, cyro. + matching_container = 1 + if(!C.required_other) + matching_other = 1 + + //FermiChem + /* + if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + if (C.FermiExplode == TRUE) + //To be added! + else + FermiExplode() + //explode function!! + */ + + if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! + meets_temp_requirement = 1//binary pass + + if(!has_special_react || C.check_special_react(src)) + can_special_react = 1 + + if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other && meets_temp_requirement && can_special_react) + possible_reactions += C + + if(possible_reactions.len)//does list exist? + var/datum/chemical_reaction/selected_reaction = possible_reactions[1] + //select the reaction with the most extreme temperature requirements + for(var/V in possible_reactions)//why V, surely that would indicate volume? V is the reaction potential. + var/datum/chemical_reaction/competitor = V //competitor? I think this is theres two of them. Troubling..! + if(selected_reaction.is_cold_recipe) //if there are no recipe conflicts, everything in possible_reactions will have this same value for is_cold_reaction. warranty void if assumption not met. + if(competitor.required_temp <= selected_reaction.required_temp)//only returns with lower if reaction "is cold" var. + selected_reaction = competitor + else + if(competitor.required_temp >= selected_reaction.required_temp) //will return with the hotter reacting first. + selected_reaction = competitor + var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list + var/list/cached_results = selected_reaction.results//resultant chemical list + var/special_react_result = selected_reaction.check_special_react(src) + var/list/multiplier = INFINITY //Wat + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. + //FermiChem relies on two additional properties; pH and impurity + //Temperature plays into a larger role too. + //BRANCH HERE + //if(selected_reaction) + var/datum/chemical_reaction/C = selected_reaction + + if (C.FermiChem == TRUE) + message_admins("FermiChem Proc'd") + + while (reactedVol < multiplier) + reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, special_react_result, cached_required_reagents, cached_results, selected_reaction.results) + CHECK_TICK + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log + + //Standard reaction mechanics: + else + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + for(var/B in cached_required_reagents) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: + + + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/iconhtml = icon2html(cached_my_atom, seen) + if(cached_my_atom) + if(!ismob(cached_my_atom)) // No bubbling mobs + if(selected_reaction.mix_sound) + playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + + for(var/mob/M in seen) + to_chat(M, "[iconhtml] [selected_reaction.mix_message]") + + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in seen) + to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." + + selected_reaction.on_reaction(src, multiplier, special_react_result) + reaction_occurred = 1 + + while(reaction_occurred)//while do nothing? + update_total()//Don't know waht this does. + return 0//end! + +/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, multiplier, totalVol, special_react_result, cached_required_reagents, cached_results, selected_reaction.results) + var/datum/chemical_reaction/C = selected_reaction + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/ammoReacted = 0 + //get purity from combined beaker reactant purities HERE. + var/purity = 1 + var/tempVol = totalVol + //var/list/multiplier = INFINITY + + message_admins("Loop beginning") + //Begin Parse + + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") + FermiExplode() + + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") + FermiExplode() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax && chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") + + stepChemAmmount = tempVol * deltaT + if (stepChemAmmount > C.RateUpLim) + stepChemAmmount = C.RateUpLim + else if (stepChemAmmount < 0.01) + stepChemAmmount = 0.01 + + if (totalVol > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") + + // End. + /* + for(var/B in cached_required_reagents) // + tempVol = min(totalVol, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + */ + message_admins("cached_results: [cached_results], totalVol: [totalVol], stepChemAmmount [stepChemAmmount]") + for(var/B in cached_required_reagents) + message_admins("cached_required_reagents(B): [cached_required_reagents[B]], totalVol: [totalVol], base stepChemAmmount [stepChemAmmount]") + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + totalVol = max(totalVol, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + + totalVol = totalVol + stepChemAmmount + + + CHECK_TICK + return (totalVol) + +/datum/reagents/proc/FermiExplode() + return + +/datum/reagents/proc/isolate_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id != reagent) + del_reagent(R.id) + update_total() + +/datum/reagents/proc/del_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id == reagent) + if(my_atom && isliving(my_atom)) + var/mob/living/M = my_atom + R.on_mob_delete(M) + qdel(R) + reagent_list -= R + update_total() + if(my_atom) + my_atom.on_reagent_change(DEL_REAGENT) + return 1 + +/datum/reagents/proc/update_total() + var/list/cached_reagents = reagent_list + total_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume < 0.1) + del_reagent(R.id) + else + total_volume += R.volume + + return 0 + +/datum/reagents/proc/clear_reagents() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + del_reagent(R.id) + return 0 + +/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1) + var/react_type + if(isliving(A)) + react_type = "LIVING" + if(method == INGEST) + var/mob/living/L = A + L.taste(src) + else if(isturf(A)) + react_type = "TURF" + else if(isobj(A)) + react_type = "OBJ" + else + return + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + switch(react_type) + if("LIVING") + var/touch_protection = 0 + if(method == VAPOR) + var/mob/living/L = A + touch_protection = L.get_permeability_protection() + R.reaction_mob(A, method, R.volume * volume_modifier, show_message, touch_protection) + if("TURF") + R.reaction_turf(A, R.volume * volume_modifier, show_message) + if("OBJ") + R.reaction_obj(A, R.volume * volume_modifier, show_message) + +/datum/reagents/proc/holder_full() + if(total_volume >= maximum_volume) + return TRUE + return FALSE + +//Returns the average specific heat for all reagents currently in this holder. +/datum/reagents/proc/specific_heat() + . = 0 + var/cached_amount = total_volume //cache amount + var/list/cached_reagents = reagent_list //cache reagents + for(var/I in cached_reagents) + var/datum/reagent/R = I + . += R.specific_heat * (R.volume / cached_amount) + +/datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000) + var/S = specific_heat() + chem_temp = CLAMP(chem_temp + (J / (S * total_volume)), 2.7, 1000) + +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, pH = 7, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ + if(!isnum(amount) || !amount) + return FALSE + + if(amount <= 0) + return FALSE + + var/datum/reagent/D = GLOB.chemical_reagents_list[reagent] + if(!D) + WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") + return FALSE + + update_total() + var/cached_total = total_volume + if(cached_total + amount > maximum_volume) + amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. Shouldnt happen. Will happen. + if(amount <= 0) + return FALSE + var/new_total = cached_total + amount + var/cached_temp = chem_temp + var/list/cached_reagents = reagent_list + + //Equalize temperature - Not using specific_heat() because the new chemical isn't in yet. + var/specific_heat = 0 + var/thermal_energy = 0 + for(var/i in cached_reagents) + var/datum/reagent/R = i + specific_heat += R.specific_heat * (R.volume / new_total) + thermal_energy += R.specific_heat * R.volume * cached_temp + specific_heat += D.specific_heat * (amount / new_total) + thermal_energy += D.specific_heat * amount * reagtemp + chem_temp = thermal_energy / (specific_heat * new_total) + //// + + //add the reagent to the existing if it exists + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + R.volume += amount + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + R.on_merge(data, amount) + if(!no_react) + handle_reactions() + return TRUE + + //otherwise make a new one + var/datum/reagent/R = new D.type(data) + cached_reagents += R + R.holder = src + R.volume = amount + if(data) + R.data = data + R.on_new(data) + + if(isliving(my_atom)) + R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + if(!no_react) + handle_reactions() + return TRUE + +/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list("toxin" = 10, "beer" = 15) + for(var/r_id in list_reagents) + var/amt = list_reagents[r_id] + add_reagent(r_id, amt, data) + +/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to + + if(isnull(amount)) + amount = 0 + CRASH("null amount passed to reagent code") + return FALSE + + if(!isnum(amount)) + return FALSE + + if(amount < 0) + return FALSE + + var/list/cached_reagents = reagent_list + + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + //clamp the removal amount to be between current reagent amount + //and zero, to prevent removing more than the holder has stored + amount = CLAMP(amount, 0, R.volume) + R.volume -= amount + update_total() + if(!safety)//So it does not handle reactions when it need not to + handle_reactions() + if(my_atom) + my_atom.on_reagent_change(REM_REAGENT) + return TRUE + + return FALSE + +/datum/reagents/proc/has_reagent(reagent, amount = -1) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + if(!amount) + return R + else + if(R.volume >= amount) + return R + else + return 0 + + return 0 + +/datum/reagents/proc/get_reagent_amount(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + return R.volume + + return 0 + +/datum/reagents/proc/get_reagents() + var/list/names = list() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + names += R.name + + return jointext(names, ",") + +/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included. + if(!isnum(amount)) + return 1 + var/list/cached_reagents = reagent_list + var/has_removed_reagent = 0 + + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + var/matches = 0 + // Switch between how we check the reagent type + if(strict) + if(R.type == reagent_type) + matches = 1 + else + if(istype(R, reagent_type)) + matches = 1 + // We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type. + if(matches) + // Have our other proc handle removement + has_removed_reagent = remove_reagent(R.id, amount, safety) + + return has_removed_reagent + +//two helper functions to preserve data across reactions (needed for xenoarch) +/datum/reagents/proc/get_data(reagent_id) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + return R.data + +/datum/reagents/proc/set_data(reagent_id, new_data) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + R.data = new_data + +/datum/reagents/proc/copy_data(datum/reagent/current_reagent) + if(!current_reagent || !current_reagent.data) + return null + if(!istype(current_reagent.data, /list)) + return current_reagent.data + + var/list/trans_data = current_reagent.data.Copy() + + // We do this so that introducing a virus to a blood sample + // doesn't automagically infect all other blood samples from + // the same donor. + // + // Technically we should probably copy all data lists, but + // that could possibly eat up a lot of memory needlessly + // if most data lists are read-only. + if(trans_data["viruses"]) + var/list/v = trans_data["viruses"] + trans_data["viruses"] = v.Copy() + + return trans_data + +/datum/reagents/proc/get_reagent(type) + var/list/cached_reagents = reagent_list + . = locate(type) in cached_reagents + +/datum/reagents/proc/generate_taste_message(minimum_percent=15) + // the lower the minimum percent, the more sensitive the message is. + var/list/out = list() + var/list/tastes = list() //descriptor = strength + if(minimum_percent <= 100) + for(var/datum/reagent/R in reagent_list) + if(!R.taste_mult) + continue + + if(istype(R, /datum/reagent/consumable/nutriment)) + var/list/taste_data = R.data + for(var/taste in taste_data) + var/ratio = taste_data[taste] + var/amount = ratio * R.taste_mult * R.volume + if(taste in tastes) + tastes[taste] += amount + else + tastes[taste] = amount + else + var/taste_desc = R.taste_description + var/taste_amount = R.volume * R.taste_mult + if(taste_desc in tastes) + tastes[taste_desc] += taste_amount + else + tastes[taste_desc] = taste_amount + //deal with percentages + // TODO it would be great if we could sort these from strong to weak + var/total_taste = counterlist_sum(tastes) + if(total_taste > 0) + for(var/taste_desc in tastes) + var/percent = tastes[taste_desc]/total_taste * 100 + if(percent < minimum_percent) + continue + var/intensity_desc = "a hint of" + if(percent > minimum_percent * 2 || percent == 100) + intensity_desc = "" + else if(percent > minimum_percent * 3) + intensity_desc = "the strong flavor of" + if(intensity_desc != "") + out += "[intensity_desc] [taste_desc]" + else + out += "[taste_desc]" + + return english_list(out, "something indescribable") + +/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02) + var/temp_delta = (temperature - chem_temp) * coeff + if(temp_delta > 0) + chem_temp = min(chem_temp + max(temp_delta, 1), temperature) + else + chem_temp = max(chem_temp + min(temp_delta, -1), temperature) + chem_temp = round(chem_temp) + handle_reactions() + +/////////////////////////////////////////////////////////////////////////////////// + + +// Convenience proc to create a reagents holder for an atom +// Max vol is maximum volume of holder +/atom/proc/create_reagents(max_vol) + if(reagents) + qdel(reagents) + reagents = new/datum/reagents(max_vol) + reagents.my_atom = src + +/proc/get_random_reagent_id() // Returns a random reagent ID minus blacklisted reagents + var/static/list/random_reagents = list() + if(!random_reagents.len) + for(var/thing in subtypesof(/datum/reagent)) + var/datum/reagent/R = thing + if(initial(R.can_synth)) + random_reagents += initial(R.id) + var/picked_reagent = pick(random_reagents) + return picked_reagent From 744b1328e87b9551d61993802bf1ccf1a7bfc5ab Mon Sep 17 00:00:00 2001 From: Fermi Date: Mon, 22 Apr 2019 20:08:19 +0100 Subject: [PATCH 30/61] Fixing the main holder reaction loop - fermi is it's own proc --- ....dm => holder(nonProc.old.functional.).dm} | 267 +++++++++-------- code/modules/reagents/chemistry/holder.dm | 283 +++++++++--------- code/modules/reagents/chemistry/holderbk3.dm | 1 + .../chemistry/reagents/fermi_reagents.dm | 33 +- 4 files changed, 299 insertions(+), 285 deletions(-) rename code/modules/reagents/chemistry/{holdersplitfail.dm => holder(nonProc.old.functional.).dm} (81%) diff --git a/code/modules/reagents/chemistry/holdersplitfail.dm b/code/modules/reagents/chemistry/holder(nonProc.old.functional.).dm similarity index 81% rename from code/modules/reagents/chemistry/holdersplitfail.dm rename to code/modules/reagents/chemistry/holder(nonProc.old.functional.).dm index be39ee3448..c38f065383 100644 --- a/code/modules/reagents/chemistry/holdersplitfail.dm +++ b/code/modules/reagents/chemistry/holder(nonProc.old.functional.).dm @@ -1,4 +1,3 @@ - /proc/build_chemical_reagent_list() //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id @@ -368,7 +367,25 @@ var/meets_temp_requirement = 0 var/has_special_react = C.special_react var/can_special_react = 0 - var/reactedVol = 0 + //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad + /* + var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions + var/OptimalTempMax = C.OptimalTempMax + var/ExplodeTemp = C.ExplodeTemp + var/OptimalpHMin = C.OptimalpHMin + var/OptimalpHMax = C.OptimalpHMax + var/ReactpHLim = C.ReactpHLim + //var/CatalystFact = C.CatalystFact + var/CurveSharpT = C.CurveSharpT + var/CurveSharppH = C.CurveSharppH + var/ThermicConstant = C.ThermicConstant + var/HIonRelease = C.HIonRelease + var/RateUpLim = C.RateUpLim + var/FermiChem = C.FermiChem + var/FermiExplode = C.FermiExplode + var/ImpureChem = C.ImpureChem + */ + //FermiChem for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) @@ -402,14 +419,12 @@ matching_other = 1 //FermiChem - /* if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! if (C.FermiExplode == TRUE) //To be added! else FermiExplode() //explode function!! - */ if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! meets_temp_requirement = 1//binary pass @@ -442,21 +457,110 @@ //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. //FermiChem relies on two additional properties; pH and impurity //Temperature plays into a larger role too. - //BRANCH HERE //if(selected_reaction) var/datum/chemical_reaction/C = selected_reaction - if (C.FermiChem == TRUE) - message_admins("FermiChem Proc'd") + //FermiReact(C) + //B is Beaker + //P is product + //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/ammoReacted = 0 + //get purity from combined beaker reactant purities. + var/purity = 1 - while (reactedVol < multiplier) - reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, special_react_result, cached_required_reagents, cached_results, selected_reaction.results) + + while (ammoReacted < multiplier) + message_admins("Loop beginning") CHECK_TICK - reaction_occurred = 1 - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log + //Begin Parse - //Standard reaction mechanics: - else + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") + FermiExplode() + + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") + FermiExplode() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax || chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + // 350 300 + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") + + stepChemAmmount = multiplier * deltaT + if (stepChemAmmount > C.RateUpLim) + stepChemAmmount = C.RateUpLim + else if (stepChemAmmount < 0.01) + stepChemAmmount = 0.1 + if (ammoReacted > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") + + // End. + + selected_reaction.on_reaction(src, multiplier, special_react_result) + + message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") + for(var/B in cached_required_reagents) + message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + + ammoReacted = ammoReacted + stepChemAmmount + CHECK_TICK + + reaction_occurred = 1 + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", ammoReacted, C.id)//log + //Standard reaction mechanics: + else: for(var/B in cached_required_reagents) // multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) @@ -470,129 +574,34 @@ add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: - var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers - var/iconhtml = icon2html(cached_my_atom, seen) - if(cached_my_atom) - if(!ismob(cached_my_atom)) // No bubbling mobs - if(selected_reaction.mix_sound) - playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/iconhtml = icon2html(cached_my_atom, seen) + if(cached_my_atom) + if(!ismob(cached_my_atom)) // No bubbling mobs + if(selected_reaction.mix_sound) + playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + for(var/mob/M in seen) + to_chat(M, "[iconhtml] [selected_reaction.mix_message]") + + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead for(var/mob/M in seen) - to_chat(M, "[iconhtml] [selected_reaction.mix_message]") + to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." - if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. - var/obj/item/slime_extract/ME2 = my_atom - ME2.Uses-- - if(ME2.Uses <= 0) // give the notification that the slime core is dead - for(var/mob/M in seen) - to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") - ME2.name = "used slime extract" - ME2.desc = "This extract has been used up." - - selected_reaction.on_reaction(src, multiplier, special_react_result) - reaction_occurred = 1 + selected_reaction.on_reaction(src, multiplier, special_react_result) + reaction_occurred = 1 while(reaction_occurred)//while do nothing? update_total()//Don't know waht this does. return 0//end! -/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, multiplier, totalVol, special_react_result, cached_required_reagents, cached_results, selected_reaction.results) - var/datum/chemical_reaction/C = selected_reaction - var/deltaT = 0 - var/deltapH = 0 - var/stepChemAmmount = 0 - var/ammoReacted = 0 - //get purity from combined beaker reactant purities HERE. - var/purity = 1 - var/tempVol = totalVol - //var/list/multiplier = INFINITY - - message_admins("Loop beginning") - //Begin Parse - - //Check extremes first - if (chem_temp > C.ExplodeTemp) - //go to explode proc - message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") - FermiExplode() - - if (pH > 14 || pH < 0) - //Create chemical sludge eventually(for now just destroy the beaker I guess?) - //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - message_admins("pH is lover limit, cur pH: [pH]") - FermiExplode() - - //For now, purity is handled elsewhere - - //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < C.OptimalTempMax && chem_temp >= C.OptimalTempMin) - deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) - else if (chem_temp >= C.OptimalTempMax) - deltaT = 1 - else - deltaT = 0 - message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") - - //Calculate DeltapH (Deviation of pH from optimal) - //Lower range - if (pH < C.OptimalpHMin) - if (pH < (C.OptimalpHMin - C.ReactpHLim)) - deltapH = 0 - else - deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) - //Upper range - else if (pH > C.OptimalpHMin) - if (pH > (C.OptimalpHMin + C.ReactpHLim)) - deltapH = 0 - else - deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) - //Within mid range - else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 1 - //This should never proc: - else - message_admins("Fermichem's pH broke!! Please let Fermis know!!") - WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") - //TODO Add CatalystFact - message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") - - stepChemAmmount = tempVol * deltaT - if (stepChemAmmount > C.RateUpLim) - stepChemAmmount = C.RateUpLim - else if (stepChemAmmount < 0.01) - stepChemAmmount = 0.01 - - if (totalVol > 0) - purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - purity = deltapH - message_admins("purity: [purity], purity of beaker") - message_admins("Temp before change: [chem_temp], pH after change: [pH]") - //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) - message_admins("Temp after change: [chem_temp], pH after change: [pH]") - - // End. - /* - for(var/B in cached_required_reagents) // - tempVol = min(totalVol, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - */ - message_admins("cached_results: [cached_results], totalVol: [totalVol], stepChemAmmount [stepChemAmmount]") - for(var/B in cached_required_reagents) - message_admins("cached_required_reagents(B): [cached_required_reagents[B]], totalVol: [totalVol], base stepChemAmmount [stepChemAmmount]") - remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - totalVol = max(totalVol, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log - add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - - totalVol = totalVol + stepChemAmmount - - - CHECK_TICK - return (totalVol) +/datum/reagents/proc/FermiReact() + return /datum/reagents/proc/FermiExplode() return @@ -955,4 +964,4 @@ if(initial(R.can_synth)) random_reagents += initial(R.id) var/picked_reagent = pick(random_reagents) - return picked_reagent + return picked_reagent \ No newline at end of file diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index c38f065383..bafc1865dc 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -1,3 +1,4 @@ + /proc/build_chemical_reagent_list() //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id @@ -367,25 +368,8 @@ var/meets_temp_requirement = 0 var/has_special_react = C.special_react var/can_special_react = 0 - //FermiChem WHY ARE VARIBLES SO ESTRANGED it makes me sad - /* - var/OptimalTempMin = C.OptimalTempMin // Lower area of bell curve for determining heat based rate reactions - var/OptimalTempMax = C.OptimalTempMax - var/ExplodeTemp = C.ExplodeTemp - var/OptimalpHMin = C.OptimalpHMin - var/OptimalpHMax = C.OptimalpHMax - var/ReactpHLim = C.ReactpHLim - //var/CatalystFact = C.CatalystFact - var/CurveSharpT = C.CurveSharpT - var/CurveSharppH = C.CurveSharppH - var/ThermicConstant = C.ThermicConstant - var/HIonRelease = C.HIonRelease - var/RateUpLim = C.RateUpLim - var/FermiChem = C.FermiChem - var/FermiExplode = C.FermiExplode - var/ImpureChem = C.ImpureChem - */ - //FermiChem + var/reactedVol = 0 + va/continue_reacting = FALSE for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) @@ -419,12 +403,14 @@ matching_other = 1 //FermiChem + /* if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! if (C.FermiExplode == TRUE) //To be added! else FermiExplode() //explode function!! + */ if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! meets_temp_requirement = 1//binary pass @@ -457,110 +443,25 @@ //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. //FermiChem relies on two additional properties; pH and impurity //Temperature plays into a larger role too. + //BRANCH HERE //if(selected_reaction) var/datum/chemical_reaction/C = selected_reaction - if (C.FermiChem == TRUE) - //FermiReact(C) - //B is Beaker - //P is product - //multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) - var/deltaT = 0 - var/deltapH = 0 - var/stepChemAmmount = 0 - var/ammoReacted = 0 - //get purity from combined beaker reactant purities. - var/purity = 1 - - - while (ammoReacted < multiplier) - message_admins("Loop beginning") - CHECK_TICK - //Begin Parse - - //Check extremes first - if (chem_temp > C.ExplodeTemp) - //go to explode proc - message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") - FermiExplode() - - if (pH > 14 || pH < 0) - //Create chemical sludge eventually(for now just destroy the beaker I guess?) - //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) - message_admins("pH is lover limit, cur pH: [pH]") - FermiExplode() - - //For now, purity is handled elsewhere - - //Calculate DeltaT (Deviation of T from optimal) - if (chem_temp < C.OptimalTempMax || chem_temp >= C.OptimalTempMin) - deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) - // 350 300 - else if (chem_temp >= C.OptimalTempMax) - deltaT = 1 - else - deltaT = 0 - message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") - - //Calculate DeltapH (Deviation of pH from optimal) - //Lower range - if (pH < C.OptimalpHMin) - if (pH < (C.OptimalpHMin - C.ReactpHLim)) - deltapH = 0 - else - deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) - //Upper range - else if (pH > C.OptimalpHMin) - if (pH > (C.OptimalpHMin + C.ReactpHLim)) - deltapH = 0 - else - deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) - //Within mid range - else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) - deltapH = 1 - //This should never proc: - else - message_admins("Fermichem's pH broke!! Please let Fermis know!!") - WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") - //TODO Add CatalystFact - message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") - - stepChemAmmount = multiplier * deltaT - if (stepChemAmmount > C.RateUpLim) - stepChemAmmount = C.RateUpLim - else if (stepChemAmmount < 0.01) - stepChemAmmount = 0.1 - if (ammoReacted > 0) - purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product - else - purity = deltapH - message_admins("purity: [purity], purity of beaker") - message_admins("Temp before change: [chem_temp], pH after change: [pH]") - //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) - message_admins("Temp after change: [chem_temp], pH after change: [pH]") - - // End. - - selected_reaction.on_reaction(src, multiplier, special_react_result) - - message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") - for(var/B in cached_required_reagents) - message_admins("cached_results: [cached_results], multiplier: [multiplier], stepChemAmmount [stepChemAmmount]") - remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? - multiplier = max(multiplier, 1) //this shouldnt happen ... - SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log - add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: - - ammoReacted = ammoReacted + stepChemAmmount - CHECK_TICK + if (C.FermiChem == TRUE && !continue_reacting == TRUE) + message_admins("FermiChem Proc'd") reaction_occurred = 1 - SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", ammoReacted, C.id)//log - //Standard reaction mechanics: - else: + + for(var/P in selected_reaction.results) + var/targetVol = cached_results[P]*multiplier + + while (reactedVol < targetVol) + reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol cached_required_reagents, cached_results) + + + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log + + //Standard reaction mechanics: + else for(var/B in cached_required_reagents) // multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) @@ -574,34 +475,136 @@ add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: - var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers - var/iconhtml = icon2html(cached_my_atom, seen) - if(cached_my_atom) - if(!ismob(cached_my_atom)) // No bubbling mobs - if(selected_reaction.mix_sound) - playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/iconhtml = icon2html(cached_my_atom, seen) + if(cached_my_atom) + if(!ismob(cached_my_atom)) // No bubbling mobs + if(selected_reaction.mix_sound) + playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) - for(var/mob/M in seen) - to_chat(M, "[iconhtml] [selected_reaction.mix_message]") - - if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. - var/obj/item/slime_extract/ME2 = my_atom - ME2.Uses-- - if(ME2.Uses <= 0) // give the notification that the slime core is dead for(var/mob/M in seen) - to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") - ME2.name = "used slime extract" - ME2.desc = "This extract has been used up." + to_chat(M, "[iconhtml] [selected_reaction.mix_message]") - selected_reaction.on_reaction(src, multiplier, special_react_result) - reaction_occurred = 1 + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in seen) + to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." + + selected_reaction.on_reaction(src, multiplier, special_react_result) + reaction_occurred = 1 + continue_reacting = TRUE while(reaction_occurred)//while do nothing? update_total()//Don't know waht this does. return 0//end! -/datum/reagents/proc/FermiReact() - return +/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + var/datum/chemical_reaction/C = selected_reaction + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + var/ammoReacted = 0 + //get purity from combined beaker reactant purities HERE. + var/purity = 1 + var/tempVol = totalVol + //var/list/multiplier = INFINITY + + message_admins("Loop beginning") + //Begin Parse + + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") + FermiExplode() + + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") + FermiExplode() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax && chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") + + stepChemAmmount = targetVol * deltaT + if (stepChemAmmount > C.RateUpLim) + stepChemAmmount = C.RateUpLim + else if (stepChemAmmount < 0.01) + stepChemAmmount = 0.01 + + if ((reactedVol + stepChemAmmount) > targetVol) + stepChemAmmount = targetVol - reactedVol + message_admins("target volume reached. Reaction should stop after this loop") + + if (reactedVol > 0) + purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") + + // End. + /* + for(var/B in cached_required_reagents) // + tempVol = min(reactedVol, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + */ + message_admins("cached_results: [cached_results], reactedVol: [reactedVol], stepChemAmmount [stepChemAmmount]") + + + + for(var/B in cached_required_reagents) + message_admins("cached_required_reagents(B): [cached_required_reagents[B]], reactedVol: [reactedVol], base stepChemAmmount [stepChemAmmount]") + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + reactedVol = max(reactedVol, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + + reactedVol = reactedVol + stepChemAmmount + + + return (reactedVol) /datum/reagents/proc/FermiExplode() return @@ -964,4 +967,4 @@ if(initial(R.can_synth)) random_reagents += initial(R.id) var/picked_reagent = pick(random_reagents) - return picked_reagent \ No newline at end of file + return picked_reagent diff --git a/code/modules/reagents/chemistry/holderbk3.dm b/code/modules/reagents/chemistry/holderbk3.dm index 06e99bac96..6c2f5a9876 100644 --- a/code/modules/reagents/chemistry/holderbk3.dm +++ b/code/modules/reagents/chemistry/holderbk3.dm @@ -578,6 +578,7 @@ for(var/B in cached_required_reagents) // tempVol = min(totalVol, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + message_admins("cached_results: [cached_results], totalVol: [totalVol], stepChemAmmount [stepChemAmmount]") for(var/B in cached_required_reagents) message_admins("cached_required_reagents(B): [cached_required_reagents[B]], totalVol: [totalVol], base stepChemAmmount [stepChemAmmount]") diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 2913c2f2b4..0a12e40bd6 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -49,13 +49,13 @@ /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! if (holder.has_reagent("eigenstate")) - do_sparks(5,FALSE,src) + do_sparks(5,FALSE,M) else location_return = get_turf(src) //sets up return point to_chat(M, "You feel your wavefunction split!") - do_sparks(5,FALSE,src) + do_sparks(5,FALSE,M) M.forceMove(location_created) //Teleports to creation location - do_sparks(5,FALSE,src) + do_sparks(5,FALSE,M) ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location @@ -66,16 +66,17 @@ ..() /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly - switch(current_cycle) - if(10) - to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") - M.Jitter(10) + . = ..() + //switch(current_cycle) + // if(1) + to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") + M.Jitter(10) - if(15 to INFINITY) - do_sparks(5,FALSE,src) - do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') - do_sparks(5,FALSE,src) - M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting + //if(3 to INFINITY) + do_sparks(5,FALSE,src) + do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') + do_sparks(5,FALSE,src) + //M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting ..() @@ -132,7 +133,7 @@ /datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. M.Jitter(50) M.AdjustKnockdown(0, 0) - to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your pervious self, sent to god knows what universe.") + to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) ..() @@ -192,8 +193,8 @@ //Breast englargement /datum/reagent/fermi/BElarger - name = "Eigenstasium" - id = "eigenstate" + name = "Sucubus Draft" + id = "BEenlager" description = "A volatile collodial mixture derived from milk that encourages mammary production via a potent estrogen mix." color = "#60A584" // rgb: 96, 0, 255 overdose_threshold = 12 @@ -204,5 +205,5 @@ M.visible_message("[M] suddenly looks more feminine!", "You suddenly feel more feminine!") if(M.gender == FEMALE) - M.gender = FEMALE + M.gender = MALE M.visible_message("[M] suddenly looks more masculine!", "You suddenly feel more masculine!") From 53a93c410871d4430ee4b6afbf14076b64321508 Mon Sep 17 00:00:00 2001 From: Fermi Date: Mon, 22 Apr 2019 20:31:09 +0100 Subject: [PATCH 31/61] Few code fixes. --- code/modules/reagents/chemistry/holder.dm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index bafc1865dc..839c67eff9 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -345,6 +345,10 @@ return //Yup, no reactions here. No siree. var/reaction_occurred = 0 // checks if reaction, binary variable + var/continue_reacting = FALSE //Helps keep track what kind of reaction is occuring; standard or fermi. + var/targetVol = 0 + var/reactedVol = 0 + do //What does do do in byond? It sounds very redundant? is it a while loop? var/list/possible_reactions = list() //init list reaction_occurred = 0 // sets it back to 0? @@ -368,8 +372,7 @@ var/meets_temp_requirement = 0 var/has_special_react = C.special_react var/can_special_react = 0 - var/reactedVol = 0 - va/continue_reacting = FALSE + for(var/B in cached_required_reagents) if(!has_reagent(B, cached_required_reagents[B])) @@ -452,10 +455,10 @@ reaction_occurred = 1 for(var/P in selected_reaction.results) - var/targetVol = cached_results[P]*multiplier + targetVol = cached_results[P]*multiplier while (reactedVol < targetVol) - reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol cached_required_reagents, cached_results) + reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log @@ -510,7 +513,7 @@ var/ammoReacted = 0 //get purity from combined beaker reactant purities HERE. var/purity = 1 - var/tempVol = totalVol + //var/tempVol = totalVol //var/list/multiplier = INFINITY message_admins("Loop beginning") @@ -596,7 +599,7 @@ message_admins("cached_required_reagents(B): [cached_required_reagents[B]], reactedVol: [reactedVol], base stepChemAmmount [stepChemAmmount]") remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. - for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + for(var/P in cached_results)//Not sure how this works, what is selected_reaction.results? reactedVol = max(reactedVol, 1) //this shouldnt happen ... SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: From 95ed826faf17ebec220920d2262d603639ae3ce4 Mon Sep 17 00:00:00 2001 From: Fermi Date: Mon, 22 Apr 2019 20:39:35 +0100 Subject: [PATCH 32/61] quick fix to prevent unreactable reactions. --- code/modules/reagents/chemistry/holder.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 839c67eff9..6abb41cc79 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -457,8 +457,9 @@ for(var/P in selected_reaction.results) targetVol = cached_results[P]*multiplier - while (reactedVol < targetVol) - reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + if (chem_temp > C.C.OptimalTempMin)//To prevent pointless reactions + while (reactedVol < targetVol) + reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log From 3ba7f57cd1a89ab54a05524bbf59a069e0fdaf04 Mon Sep 17 00:00:00 2001 From: Fermi Date: Mon, 22 Apr 2019 23:53:16 +0100 Subject: [PATCH 33/61] Setting FermiReact to be part of a PROCESSING call. --- code/modules/reagents/chemistry/holder.dm | 41 +++++++++++++++---- code/modules/reagents/chemistry/reagents.dm | 1 + .../chemistry/reagents/fermi_reagents.dm | 21 +++++++--- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 6abb41cc79..42417acc39 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -53,6 +53,10 @@ var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() var/reagents_holder_flags + //var/targetVol = 0 + //var/reactedVol = 0 + var/fermiIsReacting = FALSE + var/fermiReactID = null /datum/reagents/New(maximum=100) maximum_volume = maximum @@ -346,8 +350,16 @@ var/reaction_occurred = 0 // checks if reaction, binary variable var/continue_reacting = FALSE //Helps keep track what kind of reaction is occuring; standard or fermi. - var/targetVol = 0 - var/reactedVol = 0 + + if(fermiIsReacting == TRUE) + if (reactedVol >= targetVol) + STOP_PROCESSING(SSprocessing, src) + fermiIsReacting = FALSE + message_admins("FermiChem processing stopped") + reaction_occurred = 1 + return + + do //What does do do in byond? It sounds very redundant? is it a while loop? var/list/possible_reactions = list() //init list @@ -450,16 +462,24 @@ //if(selected_reaction) var/datum/chemical_reaction/C = selected_reaction - if (C.FermiChem == TRUE && !continue_reacting == TRUE) + if (C.FermiChem == TRUE && !continue_reacting) message_admins("FermiChem Proc'd") reaction_occurred = 1 for(var/P in selected_reaction.results) targetVol = cached_results[P]*multiplier - if (chem_temp > C.C.OptimalTempMin)//To prevent pointless reactions - while (reactedVol < targetVol) - reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions + if (reactedVol < targetVol) + reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + START_PROCESSING(SSprocessing, src) + message_admins("FermiChem processing started") + fermiIsReacting = TRUE + else + fermiIsReacting = FALSE + STOP_PROCESSING(SSprocessing, src) + message_admins("FermiChem processing stopped, 2nd catch, this shouldn't appear.") + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log @@ -506,12 +526,15 @@ update_total()//Don't know waht this does. return 0//end! +/datum/reagents/process() + handle_reactions() + /datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) var/datum/chemical_reaction/C = selected_reaction var/deltaT = 0 var/deltapH = 0 var/stepChemAmmount = 0 - var/ammoReacted = 0 + //var/ammoReacted = 0 //get purity from combined beaker reactant purities HERE. var/purity = 1 //var/tempVol = totalVol @@ -577,7 +600,7 @@ message_admins("target volume reached. Reaction should stop after this loop") if (reactedVol > 0) - purity = ((purity * ammoReacted) + (deltapH * stepChemAmmount)) /((ammoReacted + stepChemAmmount)) //This should add the purity to the product + purity = ((purity * reactedVol) + (deltapH * stepChemAmmount)) /((reactedVol+ stepChemAmmount)) //This should add the purity to the product else purity = deltapH message_admins("purity: [purity], purity of beaker") @@ -608,7 +631,7 @@ reactedVol = reactedVol + stepChemAmmount - return (reactedVol) + return //(reactedVol) /datum/reagents/proc/FermiExplode() return diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index a52bb1ecfe..01810b9713 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -33,6 +33,7 @@ var/addiction_stage4_end = 40 var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick. var/self_consuming = FALSE + var/purity = 1 //Fermichem var /datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references . = ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 0a12e40bd6..d10fda80d1 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -32,15 +32,22 @@ overdose_threshold = 20 addiction_threshold = 30 metabolization_rate = 0.5 * REAGENTS_METABOLISM - addiction_stage3_end = 40 - addiction_stage4_end = 55 //Incase it's too long + addiction_stage2_end = 20 + addiction_stage3_end = 22 + addiction_stage4_end = 24 //Incase it's too long var/turf/open/location_created = null var/turf/open/location_return = null var/addictCyc3 = 1 var/mob/living/fermi_Tclone = null + var/teleBool = FALSE ///obj/item/reagent/fermi/eigenstate/Initialize() +/datum/reagent/fermi/eigenstate/on_new() + . = ..() //Needed! + location_created = get_turf(src) //Sets up coordinate of where it was created + ..() + /datum/reagent/fermi/eigenstate/New() . = ..() //Needed! location_created = get_turf(src) //Sets up coordinate of where it was created @@ -48,7 +55,7 @@ /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! - if (holder.has_reagent("eigenstate")) + if (teleBool == TRUE) do_sparks(5,FALSE,M) else location_return = get_turf(src) //sets up return point @@ -56,6 +63,7 @@ do_sparks(5,FALSE,M) M.forceMove(location_created) //Teleports to creation location do_sparks(5,FALSE,M) + teleBool = TRUE ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location @@ -63,6 +71,7 @@ to_chat(M, "You feel your wavefunction collapse!") M.forceMove(location_return) //Teleports home do_sparks(5,FALSE,src) + teleBool = FALSE ..() /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly @@ -95,8 +104,9 @@ M.AdjustKnockdown(-40, 0) for(var/item in M.get_contents()) var/obj/item/I = item + M.dropItemToGround(I, TRUE) do_teleport(I, get_turf(I), 5, no_effects=TRUE); - ..() + //..() /datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! M.Jitter(100) @@ -119,6 +129,7 @@ // C.updateappearance(mutcolor_update=1) M.visible_message("[M] collapses in from an alternative reality!") + message_admins("Fermi T Clone: [fermi_Tclone]") if(2) do_teleport(fermi_Tclone, get_turf(fermi_Tclone), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! if(3) @@ -136,7 +147,7 @@ to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) - ..() + //..() ///datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) // return From 879efcd63452b6c9d7f351c81ae72ac51114ec61 Mon Sep 17 00:00:00 2001 From: Fermi Date: Mon, 22 Apr 2019 23:58:39 +0100 Subject: [PATCH 34/61] Changed processing to be SSprocessing instead of SSfastprocess. --- code/modules/reagents/chemistry/holder.dm | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 42417acc39..3808b1e39b 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -53,8 +53,8 @@ var/addiction_tick = 1 var/list/datum/reagent/addiction_list = new/list() var/reagents_holder_flags - //var/targetVol = 0 - //var/reactedVol = 0 + var/targetVol = 0 + var/reactedVol = 0 var/fermiIsReacting = FALSE var/fermiReactID = null @@ -352,8 +352,8 @@ var/continue_reacting = FALSE //Helps keep track what kind of reaction is occuring; standard or fermi. if(fermiIsReacting == TRUE) - if (reactedVol >= targetVol) - STOP_PROCESSING(SSprocessing, src) + if (reactedVol >= targetVol && targetVol != 0) + STOP_PROCESSING(SSfastprocess, src) fermiIsReacting = FALSE message_admins("FermiChem processing stopped") reaction_occurred = 1 @@ -472,13 +472,12 @@ if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions if (reactedVol < targetVol) reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) - START_PROCESSING(SSprocessing, src) + START_PROCESSING(SSfastprocess, src) message_admins("FermiChem processing started") fermiIsReacting = TRUE else fermiIsReacting = FALSE - STOP_PROCESSING(SSprocessing, src) - message_admins("FermiChem processing stopped, 2nd catch, this shouldn't appear.") + STOP_PROCESSING(SSfastprocess, src) From 663b60fb15915c2c7202f521195722c90e8df503 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 01:08:30 +0100 Subject: [PATCH 35/61] Fermichem now reacts without hanging the server!! --- code/modules/reagents/chemistry/holder.dm | 62 +- .../reagents/chemistry/holderProcBackup.dm | 1003 +++++++++++++++++ .../chemistry/reagents/fermi_reagents.dm | 4 +- 3 files changed, 1051 insertions(+), 18 deletions(-) create mode 100644 code/modules/reagents/chemistry/holderProcBackup.dm diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 3808b1e39b..3b49c69626 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -342,6 +342,9 @@ update_total() /datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + if(fermiIsReacting == TRUE) + //reagents_holder_flags |= REAGENT_NOREACT unsure if this is needed + return var/list/cached_reagents = reagent_list //a list of the reagents? var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! @@ -351,14 +354,17 @@ var/reaction_occurred = 0 // checks if reaction, binary variable var/continue_reacting = FALSE //Helps keep track what kind of reaction is occuring; standard or fermi. - if(fermiIsReacting == TRUE) - if (reactedVol >= targetVol && targetVol != 0) - STOP_PROCESSING(SSfastprocess, src) + //if(fermiIsReacting == TRUE) + /* if (reactedVol >= targetVol && targetVol != 0) + STOP_PROCESSING(SSprocessing, src) fermiIsReacting = FALSE - message_admins("FermiChem processing stopped") + message_admins("FermiChem processing stopped in reaction handler") reaction_occurred = 1 return - + else + message_admins("FermiChem processing passed in reaction handler") + return + */ do //What does do do in byond? It sounds very redundant? is it a while loop? @@ -468,17 +474,23 @@ for(var/P in selected_reaction.results) targetVol = cached_results[P]*multiplier + message_admins("FermiChem target volume: [targetVol]") if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions if (reactedVol < targetVol) - reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) - START_PROCESSING(SSfastprocess, src) - message_admins("FermiChem processing started") - fermiIsReacting = TRUE - else - fermiIsReacting = FALSE - STOP_PROCESSING(SSfastprocess, src) - + if (fermiIsReacting == TRUE) + return + else + //reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + START_PROCESSING(SSprocessing, src) + message_admins("FermiChem processing started") + fermiIsReacting = TRUE + fermiReactID = selected_reaction + //else + // fermiIsReacting = FALSE + // STOP_PROCESSING(SSfastprocess, src) + else + return SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log @@ -526,9 +538,28 @@ return 0//end! /datum/reagents/process() - handle_reactions() + var/datum/chemical_reaction/C = fermiReactID + var/list/cached_required_reagents = C.required_reagents//update reagents list + var/list/cached_results = C.results//resultant chemical list -/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + + if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions + if (reactedVol < targetVol) + + reactedVol = FermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results) + message_admins("FermiChem tick activated started") + else + STOP_PROCESSING(SSprocessing, src) + fermiIsReacting = FALSE + return + else + STOP_PROCESSING(SSprocessing, src) + fermiIsReacting = FALSE + reactedVol = 0 + targetVol = 0 + //handle_reactions() + +/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results) var/datum/chemical_reaction/C = selected_reaction var/deltaT = 0 var/deltapH = 0 @@ -537,7 +568,6 @@ //get purity from combined beaker reactant purities HERE. var/purity = 1 //var/tempVol = totalVol - //var/list/multiplier = INFINITY message_admins("Loop beginning") //Begin Parse diff --git a/code/modules/reagents/chemistry/holderProcBackup.dm b/code/modules/reagents/chemistry/holderProcBackup.dm new file mode 100644 index 0000000000..02ebbc5096 --- /dev/null +++ b/code/modules/reagents/chemistry/holderProcBackup.dm @@ -0,0 +1,1003 @@ + +/proc/build_chemical_reagent_list() + //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id + + if(GLOB.chemical_reagents_list) + return + + var/paths = subtypesof(/datum/reagent) + GLOB.chemical_reagents_list = list() + + for(var/path in paths) + var/datum/reagent/D = new path() + GLOB.chemical_reagents_list[D.id] = D + +/proc/build_chemical_reactions_list() + //Chemical Reactions - Initialises all /datum/chemical_reaction into a list + // It is filtered into multiple lists within a list. + // For example: + // chemical_reaction_list["plasma"] is a list of all reactions relating to plasma + + if(GLOB.chemical_reactions_list) + return + + var/paths = subtypesof(/datum/chemical_reaction) + GLOB.chemical_reactions_list = list() + + for(var/path in paths) + + var/datum/chemical_reaction/D = new path() + var/list/reaction_ids = list() + + if(D.required_reagents && D.required_reagents.len) + for(var/reaction in D.required_reagents) + reaction_ids += reaction + + // Create filters based on each reagent id in the required reagents list + for(var/id in reaction_ids) + if(!GLOB.chemical_reactions_list[id]) + GLOB.chemical_reactions_list[id] = list() + GLOB.chemical_reactions_list[id] += D + break // Don't bother adding ourselves to other reagent ids, it is redundant + +/////////////////////////////////////////////////////////////////////////////////// + +/datum/reagents + var/list/datum/reagent/reagent_list = new/list() + var/total_volume = 0 + var/maximum_volume = 100 + var/atom/my_atom = null + var/chem_temp = 150 + var/pH = REAGENT_NORMAL_PH + var/last_tick = 1 + var/addiction_tick = 1 + var/list/datum/reagent/addiction_list = new/list() + var/reagents_holder_flags + var/targetVol = 0 + var/reactedVol = 0 + var/fermiIsReacting = FALSE + var/fermiReactID = null + +/datum/reagents/New(maximum=100) + maximum_volume = maximum + + //I dislike having these here but map-objects are initialised before world/New() is called. >_> + if(!GLOB.chemical_reagents_list) + build_chemical_reagent_list() + if(!GLOB.chemical_reactions_list) + build_chemical_reactions_list() + +/datum/reagents/Destroy() + . = ..() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + qdel(R) + cached_reagents.Cut() + cached_reagents = null + if(my_atom && my_atom.reagents == src) + my_atom.reagents = null + my_atom = null + +// Used in attack logs for reagents in pills and such +/datum/reagents/proc/log_list() + if(!length(reagent_list)) + return "no reagents" + + var/list/data = list() + for(var/r in reagent_list) //no reagents will be left behind + var/datum/reagent/R = r + data += "[R.id] ([round(R.volume, 0.1)]u)" + //Using IDs because SOME chemicals (I'm looking at you, chlorhydrate-beer) have the same names as other chemicals. + return english_list(data) + +/datum/reagents/proc/remove_any(amount = 1) + var/list/cached_reagents = reagent_list + var/total_transfered = 0 + var/current_list_element = 1 + + current_list_element = rand(1, cached_reagents.len) + + while(total_transfered != amount) + if(total_transfered >= amount) + break + if(total_volume <= 0 || !cached_reagents.len) + break + + if(current_list_element > cached_reagents.len) + current_list_element = 1 + + var/datum/reagent/R = cached_reagents[current_list_element] + remove_reagent(R.id, 1) + + current_list_element++ + total_transfered++ + update_total() + + handle_reactions() + return total_transfered + +/datum/reagents/proc/remove_all(amount = 1) + var/list/cached_reagents = reagent_list + if(total_volume > 0) + var/part = amount / total_volume + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + remove_reagent(R.id, R.volume * part) + + update_total() + handle_reactions() + return amount + +/datum/reagents/proc/get_master_reagent_name() + var/list/cached_reagents = reagent_list + var/name + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + name = R.name + + return name + +/datum/reagents/proc/get_master_reagent_id() + var/list/cached_reagents = reagent_list + var/id + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + id = R.id + + return id + +/datum/reagents/proc/get_master_reagent() + var/list/cached_reagents = reagent_list + var/datum/reagent/master + var/max_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume > max_volume) + max_volume = R.volume + master = R + + return master + +/datum/reagents/proc/trans_to(obj/target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + if(amount < 0) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume) + var/part = amount / src.total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/transfer_amount = T.volume * part + if(preserve_data) + trans_data = copy_data(T) + + //fermichem Added ph TODO: add T.purity + R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + //R.add_reagent(T.id, transfer_amount * multiplier, trans_data, chem_temp, pH, T.purity, no_react = TRUE) //we only handle reaction after every reagent has been transfered. + remove_reagent(T.id, transfer_amount) + + update_total() + R.update_total() + if(!no_react) + R.handle_reactions() + src.handle_reactions() + return amount + +/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1) + var/list/cached_reagents = reagent_list + if(!target || !total_volume) + return + + var/datum/reagents/R + if(istype(target, /datum/reagents)) + R = target + else + if(!target.reagents) + return + R = target.reagents + + if(amount < 0) + return + amount = min(min(amount, total_volume), R.maximum_volume-R.total_volume) + var/part = amount / total_volume + var/trans_data = null + for(var/reagent in cached_reagents) + var/datum/reagent/T = reagent + var/copy_amount = T.volume * part + if(preserve_data) + trans_data = T.data + R.add_reagent(T.id, copy_amount * multiplier, trans_data) + + src.update_total() + R.update_total() + R.handle_reactions() + 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 + var/list/cached_reagents = reagent_list + if (!target) + return + if (!target.reagents || src.total_volume<=0 || !src.get_reagent_amount(reagent)) + return + if(amount < 0) + return + + var/datum/reagents/R = target.reagents + if(src.get_reagent_amount(reagent)= R.overdose_threshold && !R.overdosed) + R.overdosed = 1 + need_mob_update += R.overdose_start(C) + if(R.addiction_threshold) + if(R.volume >= R.addiction_threshold && !is_type_in_list(R, cached_addictions)) + var/datum/reagent/new_reagent = new R.type() + cached_addictions.Add(new_reagent) + if(R.overdosed) + need_mob_update += R.overdose_process(C) + if(is_type_in_list(R,cached_addictions)) + for(var/addiction in cached_addictions) + var/datum/reagent/A = addiction + if(istype(R, A)) + A.addiction_stage = -15 // you're satisfied for a good while. + need_mob_update += R.on_mob_life(C) + + if(can_overdose) + if(addiction_tick == 6) + addiction_tick = 1 + for(var/addiction in cached_addictions) + var/datum/reagent/R = addiction + if(C && R) + R.addiction_stage++ + if(1 <= R.addiction_stage && R.addiction_stage <= R.addiction_stage1_end) + need_mob_update += R.addiction_act_stage1(C) + else if(R.addiction_stage1_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage2_end) + need_mob_update += R.addiction_act_stage2(C) + else if(R.addiction_stage2_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage3_end) + need_mob_update += R.addiction_act_stage3(C) + else if(R.addiction_stage3_end <= R.addiction_stage && R.addiction_stage <= R.addiction_stage4_end) + need_mob_update += R.addiction_act_stage4(C) + else if(R.addiction_stage4_end <= R.addiction_stage) + to_chat(C, "You feel like you've gotten over your need for [R.name].") + SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.id]_addiction") + cached_addictions.Remove(R) + addiction_tick++ + if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates. + C.updatehealth() + C.update_canmove() + C.update_stamina() + update_total() + + +/datum/reagents/proc/set_reacting(react = TRUE) + if(react) + reagents_holder_flags &= ~(REAGENT_NOREACT) + else + reagents_holder_flags |= REAGENT_NOREACT + +/datum/reagents/proc/conditional_update_move(atom/A, Running = 0) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_move (A, Running) + update_total() + +/datum/reagents/proc/conditional_update(atom/A) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + R.on_update (A) + update_total() + +/datum/reagents/proc/handle_reactions()//HERE EDIT HERE THE MAIN REACTION FERMICHEMS ASSEMBLE! I hope rp is similar + var/list/cached_reagents = reagent_list //a list of the reagents? + var/list/cached_reactions = GLOB.chemical_reactions_list //a list of the whole reactions? + var/datum/cached_my_atom = my_atom //It says my atom, but I didn't bring one with me!! + if(reagents_holder_flags & REAGENT_NOREACT) //Not sure on reagents_holder_flags, but I think it checks to see if theres a reaction with current stuff. + return //Yup, no reactions here. No siree. + + var/reaction_occurred = 0 // checks if reaction, binary variable + var/continue_reacting = FALSE //Helps keep track what kind of reaction is occuring; standard or fermi. + + if(fermiIsReacting == TRUE) + if (reactedVol >= targetVol && targetVol != 0) + STOP_PROCESSING(SSfastprocess, src) + fermiIsReacting = FALSE + message_admins("FermiChem processing stopped") + reaction_occurred = 1 + return + + + + do //What does do do in byond? It sounds very redundant? is it a while loop? + var/list/possible_reactions = list() //init list + reaction_occurred = 0 // sets it back to 0? + for(var/reagent in cached_reagents) //for reagent in beaker/holder + var/datum/reagent/R = reagent //check to make sure that reagent is there for the reaction list + for(var/reaction in cached_reactions[R.id]) // Was a big list but now it should be smaller since we filtered it with our reagent id + if(!reaction) + continue + + var/datum/chemical_reaction/C = reaction + var/list/cached_required_reagents = C.required_reagents + var/total_required_reagents = cached_required_reagents.len + var/total_matching_reagents = 0 + var/list/cached_required_catalysts = C.required_catalysts + var/total_required_catalysts = cached_required_catalysts.len + var/total_matching_catalysts= 0 + var/matching_container = 0 + var/matching_other = 0 + var/required_temp = C.required_temp + var/is_cold_recipe = C.is_cold_recipe + var/meets_temp_requirement = 0 + var/has_special_react = C.special_react + var/can_special_react = 0 + + + for(var/B in cached_required_reagents) + if(!has_reagent(B, cached_required_reagents[B])) + break + total_matching_reagents++ + for(var/B in cached_required_catalysts) + if(!has_reagent(B, cached_required_catalysts[B])) + break + total_matching_catalysts++ + if(cached_my_atom) + if(!C.required_container) + matching_container = 1 + + else + if(cached_my_atom.type == C.required_container)//if the suspected container is a container + matching_container = 1 + if (isliving(cached_my_atom) && !C.mob_react) //Makes it so certain chemical reactions don't occur in mobs + return + if(!C.required_other)//Checks for other things required + matching_other = 1//binary check passes + + else if(istype(cached_my_atom, /obj/item/slime_extract))//if the object is a slime_extract. This might be complicated as to not break them via fermichem + var/obj/item/slime_extract/M = cached_my_atom + + if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this + matching_other = 1 + else + if(!C.required_container)//I'm not sure why this is here twice, I think if it's not a beaker? Oh, cyro. + matching_container = 1 + if(!C.required_other) + matching_other = 1 + + //FermiChem + /* + if (chem_temp > C.ExplodeTemp)//Check to see if reaction is too hot! + if (C.FermiExplode == TRUE) + //To be added! + else + FermiExplode() + //explode function!! + */ + + if(required_temp == 0 || (is_cold_recipe && chem_temp <= required_temp) || (!is_cold_recipe && chem_temp >= required_temp))//Temperature check!! + meets_temp_requirement = 1//binary pass + + if(!has_special_react || C.check_special_react(src)) + can_special_react = 1 + + if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other && meets_temp_requirement && can_special_react) + possible_reactions += C + + if(possible_reactions.len)//does list exist? + var/datum/chemical_reaction/selected_reaction = possible_reactions[1] + //select the reaction with the most extreme temperature requirements + for(var/V in possible_reactions)//why V, surely that would indicate volume? V is the reaction potential. + var/datum/chemical_reaction/competitor = V //competitor? I think this is theres two of them. Troubling..! + if(selected_reaction.is_cold_recipe) //if there are no recipe conflicts, everything in possible_reactions will have this same value for is_cold_reaction. warranty void if assumption not met. + if(competitor.required_temp <= selected_reaction.required_temp)//only returns with lower if reaction "is cold" var. + selected_reaction = competitor + else + if(competitor.required_temp >= selected_reaction.required_temp) //will return with the hotter reacting first. + selected_reaction = competitor + var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list + var/list/cached_results = selected_reaction.results//resultant chemical list + var/special_react_result = selected_reaction.check_special_react(src) + var/list/multiplier = INFINITY //Wat + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + //Splits reactions into two types; FermiChem is advanced reaction mechanics, Other is default reaction. + //FermiChem relies on two additional properties; pH and impurity + //Temperature plays into a larger role too. + //BRANCH HERE + //if(selected_reaction) + var/datum/chemical_reaction/C = selected_reaction + + if (C.FermiChem == TRUE && !continue_reacting) + message_admins("FermiChem Proc'd") + reaction_occurred = 1 + + for(var/P in selected_reaction.results) + targetVol = cached_results[P]*multiplier + + if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions + if (reactedVol < targetVol) + //reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + START_PROCESSING(SSfastprocess, src) + message_admins("FermiChem processing started") + fermiIsReacting = TRUE + fermiReactID = selected_reaction + else + fermiIsReacting = FALSE + STOP_PROCESSING(SSfastprocess, src) + else + return + + + SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log + + //Standard reaction mechanics: + else + + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + + for(var/B in cached_required_reagents) + remove_reagent(B, (multiplier * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in selected_reaction.results)//Not sure how this works, what is selected_reaction.results? + multiplier = max(multiplier, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*multiplier, P)//log + add_reagent(P, cached_results[P]*multiplier, null, chem_temp)//add reagent function!! I THINK I can do this: + + + var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/iconhtml = icon2html(cached_my_atom, seen) + if(cached_my_atom) + if(!ismob(cached_my_atom)) // No bubbling mobs + if(selected_reaction.mix_sound) + playsound(get_turf(cached_my_atom), selected_reaction.mix_sound, 80, 1) + + for(var/mob/M in seen) + to_chat(M, "[iconhtml] [selected_reaction.mix_message]") + + if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in seen) + to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." + + selected_reaction.on_reaction(src, multiplier, special_react_result) + reaction_occurred = 1 + continue_reacting = TRUE + + while(reaction_occurred)//while do nothing? + update_total()//Don't know waht this does. + return 0//end! + +/datum/reagents/process() + if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions + if (reactedVol < targetVol) + reactedVol = FermiReact(fermiReactID, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + else + STOP_PROCESSING(SSfastprocess, src) + //handle_reactions() + +/datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + var/datum/chemical_reaction/C = selected_reaction + var/deltaT = 0 + var/deltapH = 0 + var/stepChemAmmount = 0 + //var/ammoReacted = 0 + //get purity from combined beaker reactant purities HERE. + var/purity = 1 + //var/tempVol = totalVol + //var/list/multiplier = INFINITY + + message_admins("Loop beginning") + //Begin Parse + + //Check extremes first + if (chem_temp > C.ExplodeTemp) + //go to explode proc + message_admins("temperature is over limit: [C.ExplodeTemp] Current temperature: [chem_temp]") + FermiExplode() + + if (pH > 14 || pH < 0) + //Create chemical sludge eventually(for now just destroy the beaker I guess?) + //TODO Strong acids eat glass, make it so you NEED plastic beakers for superacids(for some reactions) + message_admins("pH is lover limit, cur pH: [pH]") + FermiExplode() + + //For now, purity is handled elsewhere + + //Calculate DeltaT (Deviation of T from optimal) + if (chem_temp < C.OptimalTempMax && chem_temp >= C.OptimalTempMin) + deltaT = (((C.OptimalTempMin - chem_temp)**C.CurveSharpT)/((C.OptimalTempMax - C.OptimalTempMin)**C.CurveSharpT)) + else if (chem_temp >= C.OptimalTempMax) + deltaT = 1 + else + deltaT = 0 + message_admins("calculating temperature factor, min: [C.OptimalTempMin], max: [C.OptimalTempMax], Exponential: [C.CurveSharpT], deltaT: [deltaT]") + + //Calculate DeltapH (Deviation of pH from optimal) + //Lower range + if (pH < C.OptimalpHMin) + if (pH < (C.OptimalpHMin - C.ReactpHLim)) + deltapH = 0 + else + deltapH = (((pH - (C.OptimalpHMin - C.ReactpHLim))**C.CurveSharppH)/(C.ReactpHLim**C.CurveSharppH)) + //Upper range + else if (pH > C.OptimalpHMin) + if (pH > (C.OptimalpHMin + C.ReactpHLim)) + deltapH = 0 + else + deltapH = ((C.ReactpHLim -(pH - (C.OptimalpHMax + C.ReactpHLim))+C.ReactpHLim)/(C.ReactpHLim**C.CurveSharppH)) + //Within mid range + else if (pH >= C.OptimalpHMin && pH <= C.OptimalpHMax) + deltapH = 1 + //This should never proc: + else + message_admins("Fermichem's pH broke!! Please let Fermis know!!") + WARNING("[my_atom] attempted to determine FermiChem pH for '[C.id]' which broke for some reason! ([usr])") + //TODO Add CatalystFact + message_admins("calculating pH factor(purity), pH: [pH], min: [C.OptimalpHMin]-[C.ReactpHLim], max: [C.OptimalpHMax]+[C.ReactpHLim], deltapH: [deltapH]") + + stepChemAmmount = targetVol * deltaT + if (stepChemAmmount > C.RateUpLim) + stepChemAmmount = C.RateUpLim + else if (stepChemAmmount < 0.01) + stepChemAmmount = 0.01 + + if ((reactedVol + stepChemAmmount) > targetVol) + stepChemAmmount = targetVol - reactedVol + message_admins("target volume reached. Reaction should stop after this loop") + + if (reactedVol > 0) + purity = ((purity * reactedVol) + (deltapH * stepChemAmmount)) /((reactedVol+ stepChemAmmount)) //This should add the purity to the product + else + purity = deltapH + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") + + // End. + /* + for(var/B in cached_required_reagents) // + tempVol = min(reactedVol, round(get_reagent_amount(B) / cached_required_reagents[B]))//a simple one over the other? (Is this for multiplying end product? Useful for toxinsludge buildup) + */ + message_admins("cached_results: [cached_results], reactedVol: [reactedVol], stepChemAmmount [stepChemAmmount]") + + + + for(var/B in cached_required_reagents) + message_admins("cached_required_reagents(B): [cached_required_reagents[B]], reactedVol: [reactedVol], base stepChemAmmount [stepChemAmmount]") + remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. + + for(var/P in cached_results)//Not sure how this works, what is selected_reaction.results? + reactedVol = max(reactedVol, 1) //this shouldnt happen ... + SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log + add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + + reactedVol = reactedVol + stepChemAmmount + + + return //(reactedVol) + +/datum/reagents/proc/FermiExplode() + return + +/datum/reagents/proc/isolate_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id != reagent) + del_reagent(R.id) + update_total() + +/datum/reagents/proc/del_reagent(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if(R.id == reagent) + if(my_atom && isliving(my_atom)) + var/mob/living/M = my_atom + R.on_mob_delete(M) + qdel(R) + reagent_list -= R + update_total() + if(my_atom) + my_atom.on_reagent_change(DEL_REAGENT) + return 1 + +/datum/reagents/proc/update_total() + var/list/cached_reagents = reagent_list + total_volume = 0 + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.volume < 0.1) + del_reagent(R.id) + else + total_volume += R.volume + + return 0 + +/datum/reagents/proc/clear_reagents() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + del_reagent(R.id) + return 0 + +/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1) + var/react_type + if(isliving(A)) + react_type = "LIVING" + if(method == INGEST) + var/mob/living/L = A + L.taste(src) + else if(isturf(A)) + react_type = "TURF" + else if(isobj(A)) + react_type = "OBJ" + else + return + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + switch(react_type) + if("LIVING") + var/touch_protection = 0 + if(method == VAPOR) + var/mob/living/L = A + touch_protection = L.get_permeability_protection() + R.reaction_mob(A, method, R.volume * volume_modifier, show_message, touch_protection) + if("TURF") + R.reaction_turf(A, R.volume * volume_modifier, show_message) + if("OBJ") + R.reaction_obj(A, R.volume * volume_modifier, show_message) + +/datum/reagents/proc/holder_full() + if(total_volume >= maximum_volume) + return TRUE + return FALSE + +//Returns the average specific heat for all reagents currently in this holder. +/datum/reagents/proc/specific_heat() + . = 0 + var/cached_amount = total_volume //cache amount + var/list/cached_reagents = reagent_list //cache reagents + for(var/I in cached_reagents) + var/datum/reagent/R = I + . += R.specific_heat * (R.volume / cached_amount) + +/datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000) + var/S = specific_heat() + chem_temp = CLAMP(chem_temp + (J / (S * total_volume)), 2.7, 1000) + +/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, pH = 7, no_react = 0)//EDIT HERE TOO ~FERMICHEM~ + if(!isnum(amount) || !amount) + return FALSE + + if(amount <= 0) + return FALSE + + var/datum/reagent/D = GLOB.chemical_reagents_list[reagent] + if(!D) + WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])") + return FALSE + + update_total() + var/cached_total = total_volume + if(cached_total + amount > maximum_volume) + amount = (maximum_volume - cached_total) //Doesnt fit in. Make it disappear. Shouldnt happen. Will happen. + if(amount <= 0) + return FALSE + var/new_total = cached_total + amount + var/cached_temp = chem_temp + var/list/cached_reagents = reagent_list + + //Equalize temperature - Not using specific_heat() because the new chemical isn't in yet. + var/specific_heat = 0 + var/thermal_energy = 0 + for(var/i in cached_reagents) + var/datum/reagent/R = i + specific_heat += R.specific_heat * (R.volume / new_total) + thermal_energy += R.specific_heat * R.volume * cached_temp + specific_heat += D.specific_heat * (amount / new_total) + thermal_energy += D.specific_heat * amount * reagtemp + chem_temp = thermal_energy / (specific_heat * new_total) + //// + + //add the reagent to the existing if it exists + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + R.volume += amount + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + R.on_merge(data, amount) + if(!no_react) + handle_reactions() + return TRUE + + //otherwise make a new one + var/datum/reagent/R = new D.type(data) + cached_reagents += R + R.holder = src + R.volume = amount + if(data) + R.data = data + R.on_new(data) + + if(isliving(my_atom)) + R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete + update_total() + if(my_atom) + my_atom.on_reagent_change(ADD_REAGENT) + if(!no_react) + handle_reactions() + return TRUE + +/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data=null) // Like add_reagent but you can enter a list. Format it like this: list("toxin" = 10, "beer" = 15) + for(var/r_id in list_reagents) + var/amt = list_reagents[r_id] + add_reagent(r_id, amt, data) + +/datum/reagents/proc/remove_reagent(reagent, amount, safety)//Added a safety check for the trans_id_to + + if(isnull(amount)) + amount = 0 + CRASH("null amount passed to reagent code") + return FALSE + + if(!isnum(amount)) + return FALSE + + if(amount < 0) + return FALSE + + var/list/cached_reagents = reagent_list + + for(var/A in cached_reagents) + var/datum/reagent/R = A + if (R.id == reagent) + //clamp the removal amount to be between current reagent amount + //and zero, to prevent removing more than the holder has stored + amount = CLAMP(amount, 0, R.volume) + R.volume -= amount + update_total() + if(!safety)//So it does not handle reactions when it need not to + handle_reactions() + if(my_atom) + my_atom.on_reagent_change(REM_REAGENT) + return TRUE + + return FALSE + +/datum/reagents/proc/has_reagent(reagent, amount = -1) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + if(!amount) + return R + else + if(R.volume >= amount) + return R + else + return 0 + + return 0 + +/datum/reagents/proc/get_reagent_amount(reagent) + var/list/cached_reagents = reagent_list + for(var/_reagent in cached_reagents) + var/datum/reagent/R = _reagent + if (R.id == reagent) + return R.volume + + return 0 + +/datum/reagents/proc/get_reagents() + var/list/names = list() + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + names += R.name + + return jointext(names, ",") + +/datum/reagents/proc/remove_all_type(reagent_type, amount, strict = 0, safety = 1) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included. + if(!isnum(amount)) + return 1 + var/list/cached_reagents = reagent_list + var/has_removed_reagent = 0 + + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + var/matches = 0 + // Switch between how we check the reagent type + if(strict) + if(R.type == reagent_type) + matches = 1 + else + if(istype(R, reagent_type)) + matches = 1 + // We found a match, proceed to remove the reagent. Keep looping, we might find other reagents of the same type. + if(matches) + // Have our other proc handle removement + has_removed_reagent = remove_reagent(R.id, amount, safety) + + return has_removed_reagent + +//two helper functions to preserve data across reactions (needed for xenoarch) +/datum/reagents/proc/get_data(reagent_id) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + return R.data + +/datum/reagents/proc/set_data(reagent_id, new_data) + var/list/cached_reagents = reagent_list + for(var/reagent in cached_reagents) + var/datum/reagent/R = reagent + if(R.id == reagent_id) + R.data = new_data + +/datum/reagents/proc/copy_data(datum/reagent/current_reagent) + if(!current_reagent || !current_reagent.data) + return null + if(!istype(current_reagent.data, /list)) + return current_reagent.data + + var/list/trans_data = current_reagent.data.Copy() + + // We do this so that introducing a virus to a blood sample + // doesn't automagically infect all other blood samples from + // the same donor. + // + // Technically we should probably copy all data lists, but + // that could possibly eat up a lot of memory needlessly + // if most data lists are read-only. + if(trans_data["viruses"]) + var/list/v = trans_data["viruses"] + trans_data["viruses"] = v.Copy() + + return trans_data + +/datum/reagents/proc/get_reagent(type) + var/list/cached_reagents = reagent_list + . = locate(type) in cached_reagents + +/datum/reagents/proc/generate_taste_message(minimum_percent=15) + // the lower the minimum percent, the more sensitive the message is. + var/list/out = list() + var/list/tastes = list() //descriptor = strength + if(minimum_percent <= 100) + for(var/datum/reagent/R in reagent_list) + if(!R.taste_mult) + continue + + if(istype(R, /datum/reagent/consumable/nutriment)) + var/list/taste_data = R.data + for(var/taste in taste_data) + var/ratio = taste_data[taste] + var/amount = ratio * R.taste_mult * R.volume + if(taste in tastes) + tastes[taste] += amount + else + tastes[taste] = amount + else + var/taste_desc = R.taste_description + var/taste_amount = R.volume * R.taste_mult + if(taste_desc in tastes) + tastes[taste_desc] += taste_amount + else + tastes[taste_desc] = taste_amount + //deal with percentages + // TODO it would be great if we could sort these from strong to weak + var/total_taste = counterlist_sum(tastes) + if(total_taste > 0) + for(var/taste_desc in tastes) + var/percent = tastes[taste_desc]/total_taste * 100 + if(percent < minimum_percent) + continue + var/intensity_desc = "a hint of" + if(percent > minimum_percent * 2 || percent == 100) + intensity_desc = "" + else if(percent > minimum_percent * 3) + intensity_desc = "the strong flavor of" + if(intensity_desc != "") + out += "[intensity_desc] [taste_desc]" + else + out += "[taste_desc]" + + return english_list(out, "something indescribable") + +/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02) + var/temp_delta = (temperature - chem_temp) * coeff + if(temp_delta > 0) + chem_temp = min(chem_temp + max(temp_delta, 1), temperature) + else + chem_temp = max(chem_temp + min(temp_delta, -1), temperature) + chem_temp = round(chem_temp) + handle_reactions() + +/////////////////////////////////////////////////////////////////////////////////// + + +// Convenience proc to create a reagents holder for an atom +// Max vol is maximum volume of holder +/atom/proc/create_reagents(max_vol) + if(reagents) + qdel(reagents) + reagents = new/datum/reagents(max_vol) + reagents.my_atom = src + +/proc/get_random_reagent_id() // Returns a random reagent ID minus blacklisted reagents + var/static/list/random_reagents = list() + if(!random_reagents.len) + for(var/thing in subtypesof(/datum/reagent)) + var/datum/reagent/R = thing + if(initial(R.can_synth)) + random_reagents += initial(R.id) + var/picked_reagent = pick(random_reagents) + return picked_reagent diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index d10fda80d1..df034c41f7 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -61,7 +61,7 @@ location_return = get_turf(src) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,M) - M.forceMove(location_created) //Teleports to creation location + M.forceMove(location_created.loc) //Teleports to creation location do_sparks(5,FALSE,M) teleBool = TRUE ..() @@ -69,7 +69,7 @@ /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,src) to_chat(M, "You feel your wavefunction collapse!") - M.forceMove(location_return) //Teleports home + M.forceMove(location_return.loc) //Teleports home do_sparks(5,FALSE,src) teleBool = FALSE ..() From 0cbefc35ee56990f13c371c1a92728e845b0b61c Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 01:11:26 +0100 Subject: [PATCH 36/61] Quick test to fix. --- code/modules/reagents/chemistry/holder.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 3b49c69626..c354bd7026 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -543,11 +543,11 @@ var/list/cached_results = C.results//resultant chemical list - if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions + if (chem_temp > C.OptimalTempMin && fermiIsReacting == TRUE)//To prevent pointless reactions if (reactedVol < targetVol) reactedVol = FermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results) - message_admins("FermiChem tick activated started") + message_admins("FermiChem tick activated started, Reacted vol: [reactedVol] of [targetVol]") else STOP_PROCESSING(SSprocessing, src) fermiIsReacting = FALSE From 5e54cfd7398b48711829b0daa316059e18c0efb3 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 06:26:41 +0100 Subject: [PATCH 37/61] Fixed addition mechanics and reaction code. --- code/modules/reagents/chemistry/holder.dm | 64 ++++++--- .../chemistry/reagents/fermi_reagents.dm | 135 ++++++++++-------- .../reagents/chemistry/recipes/fermi.dm | 1 + 3 files changed, 122 insertions(+), 78 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index c354bd7026..4d9b541579 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -470,27 +470,27 @@ if (C.FermiChem == TRUE && !continue_reacting) message_admins("FermiChem Proc'd") - reaction_occurred = 1 for(var/P in selected_reaction.results) targetVol = cached_results[P]*multiplier message_admins("FermiChem target volume: [targetVol]") if (chem_temp > C.OptimalTempMin)//To prevent pointless reactions - if (reactedVol < targetVol) - if (fermiIsReacting == TRUE) - return - else - //reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) - START_PROCESSING(SSprocessing, src) - message_admins("FermiChem processing started") - fermiIsReacting = TRUE - fermiReactID = selected_reaction + //if (reactedVol < targetVol) + if (fermiIsReacting == TRUE) + return 0 + else + //reactedVol = FermiReact(selected_reaction, chem_temp, pH, multiplier, reactedVol, targetVol, cached_required_reagents, cached_results) + START_PROCESSING(SSprocessing, src) + message_admins("FermiChem processing started") + fermiIsReacting = TRUE + fermiReactID = selected_reaction + reaction_occurred = 1 //else // fermiIsReacting = FALSE // STOP_PROCESSING(SSfastprocess, src) else - return + return 0 SSblackbox.record_feedback("tally", "Fermi_chemical_reaction", reactedVol, C.id)//log @@ -541,22 +541,51 @@ var/datum/chemical_reaction/C = fermiReactID var/list/cached_required_reagents = C.required_reagents//update reagents list var/list/cached_results = C.results//resultant chemical list + var/multiplier = INFINITY + message_admins("updating targetVol from [targetVol]") + for(var/B in cached_required_reagents) // + multiplier = min(multiplier, round(get_reagent_amount(B) / cached_required_reagents[B])) + if (multiplier == 0) + STOP_PROCESSING(SSprocessing, src) + fermiIsReacting = FALSE + message_admins("FermiChem STOPPED due to reactant removal! Reacted vol: [reactedVol] of [targetVol]") + reactedVol = 0 + targetVol = 0 + handle_reactions() + update_total() + return + for(var/P in cached_results) + targetVol = cached_results[P]*multiplier + + message_admins("to [targetVol]") + + if (fermiIsReacting == FALSE) + message_admins("THIS SHOULD NEVER APPEAR!") if (chem_temp > C.OptimalTempMin && fermiIsReacting == TRUE)//To prevent pointless reactions if (reactedVol < targetVol) - reactedVol = FermiReact(fermiReactID, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results) message_admins("FermiChem tick activated started, Reacted vol: [reactedVol] of [targetVol]") else STOP_PROCESSING(SSprocessing, src) fermiIsReacting = FALSE + message_admins("FermiChem STOPPED due to volume reached! Reacted vol: [reactedVol] of [targetVol]") + reactedVol = 0 + targetVol = 0 + handle_reactions() + update_total() return else STOP_PROCESSING(SSprocessing, src) + message_admins("FermiChem STOPPED due to temperature! Reacted vol: [reactedVol] of [targetVol]") fermiIsReacting = FALSE reactedVol = 0 targetVol = 0 + handle_reactions() + update_total() + return + //handle_reactions() /datum/reagents/proc/FermiReact(selected_reaction, chem_temp, pH, reactedVol, targetVol, cached_required_reagents, cached_results) @@ -621,12 +650,13 @@ stepChemAmmount = targetVol * deltaT if (stepChemAmmount > C.RateUpLim) stepChemAmmount = C.RateUpLim - else if (stepChemAmmount < 0.01) - stepChemAmmount = 0.01 + else if (stepChemAmmount <= 0.01) + message_admins("stepChem underflow [stepChemAmmount]") + stepChemAmmount = 0.02 if ((reactedVol + stepChemAmmount) > targetVol) stepChemAmmount = targetVol - reactedVol - message_admins("target volume reached. Reaction should stop after this loop") + message_admins("target volume reached. Reaction should stop after this loop. stepChemAmmount: [stepChemAmmount] + reactedVol: [reactedVol] = targetVol [targetVol]") if (reactedVol > 0) purity = ((purity * reactedVol) + (deltapH * stepChemAmmount)) /((reactedVol+ stepChemAmmount)) //This should add the purity to the product @@ -653,14 +683,14 @@ remove_reagent(B, (stepChemAmmount * cached_required_reagents[B]), safety = 1)//safety? removes reagents from beaker using remove function. for(var/P in cached_results)//Not sure how this works, what is selected_reaction.results? - reactedVol = max(reactedVol, 1) //this shouldnt happen ... + //reactedVol = max(reactedVol, 1) //this shouldnt happen ... SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: reactedVol = reactedVol + stepChemAmmount - return //(reactedVol) + return (reactedVol) /datum/reagents/proc/FermiExplode() return diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index df034c41f7..a9af2fae4b 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -10,11 +10,12 @@ /datum/reagent/fermi name = "Fermi" id = "fermi" - taste_description = "If a petpat had a taste, this would be it." + taste_description = "If affection had a taste, this would be it." /datum/reagent/fermi/on_mob_life(mob/living/carbon/M) current_cycle++ - holder.remove_reagent(src.id, metabolization_rate / M.metabolism_efficiency) //fermi reagents stay longer if you have a better metabolism + holder.remove_reagent(src.id, metabolization_rate / M.metabolism_efficiency, FALSE) //fermi reagents stay longer if you have a better metabolism + return ..() /datum/reagent/fermi/overdose_start(mob/living/carbon/M) current_cycle++ @@ -28,16 +29,20 @@ name = "Eigenstasium" id = "eigenstate" description = "A strange mixture formed from a controlled reaction of bluespace with plasma, that causes localised eigenstate fluxuations within the patient" + taste_description = "." color = "#60A584" // rgb: 96, 0, 255 overdose_threshold = 20 addiction_threshold = 30 metabolization_rate = 0.5 * REAGENTS_METABOLISM - addiction_stage2_end = 20 - addiction_stage3_end = 22 - addiction_stage4_end = 24 //Incase it's too long + addiction_stage2_end = 30 + addiction_stage3_end = 40 + addiction_stage4_end = 45 //Incase it's too long var/turf/open/location_created = null var/turf/open/location_return = null + var/addictCyc1 = 1 + var/addictCyc2 = 1 var/addictCyc3 = 1 + var/addictCyc4 = 1 var/mob/living/fermi_Tclone = null var/teleBool = FALSE @@ -46,24 +51,27 @@ /datum/reagent/fermi/eigenstate/on_new() . = ..() //Needed! location_created = get_turf(src) //Sets up coordinate of where it was created - ..() + message_admins("Attempting to get creation location from on_new() [location_created]") + //..()s /datum/reagent/fermi/eigenstate/New() . = ..() //Needed! - location_created = get_turf(src) //Sets up coordinate of where it was created - ..() + //if(holder && holder.my_atom) + location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created + message_admins("Attempting to get creation location from New() [location_created]") + //..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! - if (teleBool == TRUE) + switch(current_cycle) + if(1) + location_return = get_turf(M.loc) //sets up return point + to_chat(M, "You feel your wavefunction split!") + do_sparks(5,FALSE,M) + M.forceMove(location_created) //Teleports to creation location + do_sparks(5,FALSE,M) + if(prob(20)) do_sparks(5,FALSE,M) - else - location_return = get_turf(src) //sets up return point - to_chat(M, "You feel your wavefunction split!") - do_sparks(5,FALSE,M) - M.forceMove(location_created.loc) //Teleports to creation location - do_sparks(5,FALSE,M) - teleBool = TRUE ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location @@ -71,83 +79,88 @@ to_chat(M, "You feel your wavefunction collapse!") M.forceMove(location_return.loc) //Teleports home do_sparks(5,FALSE,src) - teleBool = FALSE ..() /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly . = ..() - //switch(current_cycle) - // if(1) - to_chat(M, "Oh god, you feel like your wavefunction is about to hurl.") + to_chat(M, "Oh god, you feel like your wavefunction is about to tear.") M.Jitter(10) - //if(3 to INFINITY) +/datum/reagent/fermi/eigenstate/overdose_process(mob/living/M) //Overdose, makes you teleport randomly do_sparks(5,FALSE,src) - do_teleport(src, get_turf(src), 50, asoundin = 'sound/effects/phasein.ogg') + do_teleport(M, get_turf(M), 10, asoundin = 'sound/effects/phasein.ogg') do_sparks(5,FALSE,src) - //M.reagents.remove_reagent("eigenstate",1)//So you're not stuck for 10 minutes teleporting - ..() - - - //..() //loop function + M.reagents.remove_reagent("eigenstate",0.5)//So you're not stuck for 10 minutes teleporting + ..() //loop function /datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride. - to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") - M.Jitter(10) - M.nutrition = M.nutrition - (M.nutrition/10) + switch(src.addictCyc1) + if(1) + to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") + M.Jitter(10) + M.nutrition = M.nutrition - (M.nutrition/15) + src.addictCyc1++ ..() /datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M) - to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") - M.Jitter(50) - M.AdjustKnockdown(-40, 0) - for(var/item in M.get_contents()) - var/obj/item/I = item - M.dropItemToGround(I, TRUE) - do_teleport(I, get_turf(I), 5, no_effects=TRUE); - //..() + switch(src.addictCyc2) + if(1) + to_chat(M, "You start to convlse violently as you feel your consciousness split and merge across realities as your possessions fly wildy off your body.") + M.Jitter(50) + M.Knockdown(100) + M.Stun(40) + var/items = M.get_contents() + var/obj/item/I = pick(items) + M.dropItemToGround(I, TRUE) + do_sparks(5,FALSE,I) + do_teleport(I, get_turf(I), 5, no_effects=TRUE); + do_sparks(5,FALSE,I) + src.addictCyc2++ + ..() /datum/reagent/fermi/eigenstate/addiction_act_stage3(mob/living/M)//Pulls multiple copies of the character from alternative realities while teleporting them around! - M.Jitter(100) - M.AdjustKnockdown(-40, 0) - to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in switch(src.addictCyc3) if(1) + M.Jitter(100) + to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") + if(2) var/typepath = M.type fermi_Tclone = new typepath(M.loc) - //var/mob/living/carbon/O = M - //var/mob/living/carbon/C = fermi_Tclone + var/mob/living/carbon/C = fermi_Tclone fermi_Tclone.appearance = M.appearance - - //Incase Kevin breaks my code: - //if(istype(C) && istype(O)) - // C.real_name = O.real_name - // O.dna.transfer_identity(C) - // C.updateappearance(mutcolor_update=1) - + C.real_name = M.real_name M.visible_message("[M] collapses in from an alternative reality!") message_admins("Fermi T Clone: [fermi_Tclone]") - if(2) - do_teleport(fermi_Tclone, get_turf(fermi_Tclone), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + do_sparks(5,FALSE,C) + message_admins("Fermi T Clone: [fermi_Tclone] teleport attempt") if(3) - qdel(fermi_Tclone) //Deletes CLONE, or at least I hope it is. + var/mob/living/carbon/C = fermi_Tclone + do_sparks(5,FALSE,C) + qdel(C) //Deletes CLONE, or at least I hope it is. + message_admins("Fermi T Clone: [fermi_Tclone] deletion attempt") M.visible_message("[M] is snapped across to a different alternative reality!") src.addictCyc3 = 1 //counter fermi_Tclone = null - - do_teleport(src, get_turf(src), 3, no_effects=TRUE) //Teleports player randomly + message_admins("[src.addictCyc3]") + src.addictCyc3++ + do_teleport(M, get_turf(M), 3, no_effects=TRUE) //Teleports player randomly ..() //loop function /datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. - M.Jitter(50) - M.AdjustKnockdown(0, 0) - to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") - M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) - //..() + switch(src.addictCyc4) + if(1) + M.Jitter(50) + M.Knockdown(0) + to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") + M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) + src.addictCyc4++ + ..() + . = 1 ///datum/reagent/fermi/eigenstate/overheat_explode(mob/living/M) // return diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 5b07dd91c8..a7afff86cc 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -5,6 +5,7 @@ id = "eigenstate" results = list("eigenstate" = 1) required_reagents = list("bluespace" = 1, "stable_plasma" = 1, "sugar" = 1) + mix_message = "zaps brightly into existance, diffusing the energy from the localised gravity well as light" //FermiChem vars: OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions OptimalTempMax = 500 // Upper end for above From de5906b92d9503537174bef5127b1ad41ce85f07 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 06:37:02 +0100 Subject: [PATCH 38/61] Quick fixes --- .../modules/reagents/chemistry/reagents/fermi_reagents.dm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index a9af2fae4b..d7ab5f2c7c 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -134,7 +134,7 @@ C.real_name = M.real_name M.visible_message("[M] collapses in from an alternative reality!") message_admins("Fermi T Clone: [fermi_Tclone]") - do_teleport(C, get_turf(C), 3, no_effects=TRUE) //teleports clone so it's hard to find the real one! + do_teleport(C, get_turf(C), 2, no_effects=TRUE) //teleports clone so it's hard to find the real one! do_sparks(5,FALSE,C) message_admins("Fermi T Clone: [fermi_Tclone] teleport attempt") if(3) @@ -147,18 +147,22 @@ fermi_Tclone = null message_admins("[src.addictCyc3]") src.addictCyc3++ - do_teleport(M, get_turf(M), 3, no_effects=TRUE) //Teleports player randomly + do_teleport(M, get_turf(M), 2, no_effects=TRUE) //Teleports player randomly ..() //loop function /datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. switch(src.addictCyc4) if(1) + M.Sleeping(20, 0) M.Jitter(50) M.Knockdown(0) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) + if(prob(20)) + do_sparks(5,FALSE,M) src.addictCyc4++ + ..() . = 1 From 09cd6f8b2f986f594207df45dbacfcf4c69324b6 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 06:41:02 +0100 Subject: [PATCH 39/61] Added placeholders for SDGF --- .../reagents/chemistry/recipes/fermi.dm | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index a7afff86cc..37729ef21f 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -28,7 +28,25 @@ name = "synthetic-derived growth factor" id = "SDGF" results = list("SDGF" = 3) - required_reagents = list("stable_plasma" = 5, "slimejelly" = 5, "synthflesh" = 10, "blood" = 10) + required_reagents = list("plasma" = 1, "stable_plasma" = 1, "sugar" = 1) + //required_reagents = list("stable_plasma" = 5, "slimejelly" = 5, "synthflesh" = 10, "blood" = 10) + //FermiChem vars: + OptimalTempMin = 350 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 500 // Upper end for above + ExplodeTemp = 550 //Temperature at which reaction explodes + OptimalpHMin = 4 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 9.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) + ThermicConstant = +20 //Temperature change per 1u produced + HIonRelease = 0.01 //pH change per 1u reaction + RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect + FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics + FermiExplode = FALSE //If the chemical explodes in a special way + ImpureChem = "toxin" //What chemical is produced with an inpure reaction + /datum/chemical_reaction/BElarger name = "" From 45c4e0acaf73657fb38ad1822031d23b8e841917 Mon Sep 17 00:00:00 2001 From: Useroth Date: Tue, 23 Apr 2019 07:46:32 +0200 Subject: [PATCH 40/61] Let's try this approach --- .../chemistry/reagents/fermi_reagents.dm | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index d7ab5f2c7c..2b14bd9cfd 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -37,7 +37,7 @@ addiction_stage2_end = 30 addiction_stage3_end = 40 addiction_stage4_end = 45 //Incase it's too long - var/turf/open/location_created = null + //var/turf/open/location_created = null var/turf/open/location_return = null var/addictCyc1 = 1 var/addictCyc2 = 1 @@ -46,29 +46,36 @@ var/mob/living/fermi_Tclone = null var/teleBool = FALSE +/mob/living/carbon + var/turf/location_spawn = null + +/mob/living/carbon/New() + . = ..() + location_spawn = get_turf(src) ///obj/item/reagent/fermi/eigenstate/Initialize() /datum/reagent/fermi/eigenstate/on_new() . = ..() //Needed! - location_created = get_turf(src) //Sets up coordinate of where it was created - message_admins("Attempting to get creation location from on_new() [location_created]") + //location_created = get_turf(src) //Sets up coordinate of where it was created + //message_admins("Attempting to get creation location from on_new() [location_created]") //..()s /datum/reagent/fermi/eigenstate/New() . = ..() //Needed! //if(holder && holder.my_atom) - location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created - message_admins("Attempting to get creation location from New() [location_created]") + //location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created + //message_admins("Attempting to get creation location from New() [location_created]") //..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! switch(current_cycle) if(1) - location_return = get_turf(M.loc) //sets up return point + location_return = get_turf(M) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,M) - M.forceMove(location_created) //Teleports to creation location + //M.forceMove(location_created) //Teleports to creation location + M.forceMove(M.location_spawn) do_sparks(5,FALSE,M) if(prob(20)) do_sparks(5,FALSE,M) @@ -111,7 +118,7 @@ M.Knockdown(100) M.Stun(40) var/items = M.get_contents() - var/obj/item/I = pick(items) + var/obj/item/I = pick(items) M.dropItemToGround(I, TRUE) do_sparks(5,FALSE,I) do_teleport(I, get_turf(I), 5, no_effects=TRUE); From ac541ff9d272b865a480378513039072c547ab3f Mon Sep 17 00:00:00 2001 From: Useroth Date: Tue, 23 Apr 2019 08:17:25 +0200 Subject: [PATCH 41/61] Fuck if I know. --- .../reagents/chemistry/reagents/fermi_reagents.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 2b14bd9cfd..151d84bafb 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -38,7 +38,7 @@ addiction_stage3_end = 40 addiction_stage4_end = 45 //Incase it's too long //var/turf/open/location_created = null - var/turf/open/location_return = null + var/turf/location_return = null var/addictCyc1 = 1 var/addictCyc2 = 1 var/addictCyc3 = 1 @@ -49,12 +49,12 @@ /mob/living/carbon var/turf/location_spawn = null -/mob/living/carbon/New() +/mob/living/carbon/Initialize() . = ..() location_spawn = get_turf(src) ///obj/item/reagent/fermi/eigenstate/Initialize() -/datum/reagent/fermi/eigenstate/on_new() +/*/datum/reagent/fermi/eigenstate/on_new() . = ..() //Needed! //location_created = get_turf(src) //Sets up coordinate of where it was created //message_admins("Attempting to get creation location from on_new() [location_created]") @@ -66,7 +66,7 @@ //location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created //message_admins("Attempting to get creation location from New() [location_created]") //..() - +*/ /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! switch(current_cycle) @@ -84,7 +84,7 @@ /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,src) to_chat(M, "You feel your wavefunction collapse!") - M.forceMove(location_return.loc) //Teleports home + M.forceMove(location_return) //Teleports home do_sparks(5,FALSE,src) ..() From d6d6dc77f1a26b4718307771ae9937192541822a Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 07:32:56 +0100 Subject: [PATCH 42/61] Fixes and tweaks to try to get things to work. --- code/modules/reagents/chemistry/holder.dm | 5 ++- .../chemistry/reagents/fermi_reagents.dm | 42 +++++++++---------- .../reagents/chemistry/recipes/fermi.dm | 2 +- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 4d9b541579..0b76dcef5d 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -665,8 +665,6 @@ message_admins("purity: [purity], purity of beaker") message_admins("Temp before change: [chem_temp], pH after change: [pH]") //Apply pH changes and thermal output of reaction to beaker - chem_temp += (C.ThermicConstant * stepChemAmmount) - pH += (C.HIonRelease * stepChemAmmount) message_admins("Temp after change: [chem_temp], pH after change: [pH]") // End. @@ -687,6 +685,9 @@ SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + chem_temp += (C.ThermicConstant * stepChemAmmount) + pH += (C.HIonRelease * stepChemAmmount) + reactedVol = reactedVol + stepChemAmmount diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 151d84bafb..243ff10dad 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -37,8 +37,8 @@ addiction_stage2_end = 30 addiction_stage3_end = 40 addiction_stage4_end = 45 //Incase it's too long - //var/turf/open/location_created = null - var/turf/location_return = null + var/turf/open/location_created = null + var/turf/open/location_return = null var/addictCyc1 = 1 var/addictCyc2 = 1 var/addictCyc3 = 1 @@ -46,36 +46,29 @@ var/mob/living/fermi_Tclone = null var/teleBool = FALSE -/mob/living/carbon - var/turf/location_spawn = null - -/mob/living/carbon/Initialize() - . = ..() - location_spawn = get_turf(src) ///obj/item/reagent/fermi/eigenstate/Initialize() -/*/datum/reagent/fermi/eigenstate/on_new() +/datum/reagent/fermi/eigenstate/on_new() . = ..() //Needed! - //location_created = get_turf(src) //Sets up coordinate of where it was created - //message_admins("Attempting to get creation location from on_new() [location_created]") + location_created = get_turf(src) //Sets up coordinate of where it was created + message_admins("Attempting to get creation location from on_new() [location_created]") //..()s /datum/reagent/fermi/eigenstate/New() . = ..() //Needed! //if(holder && holder.my_atom) - //location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created - //message_admins("Attempting to get creation location from New() [location_created]") + location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created + message_admins("Attempting to get creation location from New() [location_created]") //..() -*/ + /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! switch(current_cycle) if(1) - location_return = get_turf(M) //sets up return point + location_return = get_turf(M.loc) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,M) - //M.forceMove(location_created) //Teleports to creation location - M.forceMove(M.location_spawn) + M.forceMove(location_created) //Teleports to creation location do_sparks(5,FALSE,M) if(prob(20)) do_sparks(5,FALSE,M) @@ -84,7 +77,7 @@ /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,src) to_chat(M, "You feel your wavefunction collapse!") - M.forceMove(location_return) //Teleports home + M.forceMove(location_return.loc) //Teleports home do_sparks(5,FALSE,src) ..() @@ -118,7 +111,7 @@ M.Knockdown(100) M.Stun(40) var/items = M.get_contents() - var/obj/item/I = pick(items) + var/obj/item/I = pick(items) M.dropItemToGround(I, TRUE) do_sparks(5,FALSE,I) do_teleport(I, get_turf(I), 5, no_effects=TRUE); @@ -192,10 +185,10 @@ /datum/reagent/fermi/SGDF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone - + message_admins("SGDF ingested") var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(LAZYLEN(candidates)) - + message_admins("Candidate found!") //var/typepath = owner.type //clone = new typepath(owner.loc) var/typepath = M.type @@ -220,7 +213,12 @@ //after_success(user, SM) //qdel(src) else - if(20) + message_admins("Failed to find clone Candidate") + if(M.has_status_effect(/datum/status_effect/chem/SGDF) + + else + switch(20) + if(1) M.apply_status_effect(/datum/status_effect/chem/SGDF) ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 37729ef21f..481c7925cf 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -40,7 +40,7 @@ CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) - ThermicConstant = +20 //Temperature change per 1u produced + ThermicConstant = 20 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics From 5f706f2f0973087ca120c845710d3a2806d52ea0 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 08:44:41 +0100 Subject: [PATCH 43/61] Added more the SDGF chem. --- .../code/datums/status_effects/chems.dm | 3 + .../chemistry/reagents/fermi_reagents.dm | 107 ++++++++++++------ .../reagents/chemistry/recipes/fermi.dm | 2 +- 3 files changed, 79 insertions(+), 33 deletions(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 65a644da34..54071bff27 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -3,6 +3,7 @@ var/mob/living/carbon/human/fermi_Clone = null /datum/status_effect/chem/SGDF/on_apply(mob/living/carbon/M) + message_admins("SGDF status appied") var/typepath = M.type fermi_Clone = new typepath(M.loc) //var/mob/living/carbon/M = owner @@ -14,7 +15,9 @@ return ..() /datum/status_effect/chem/SGDF/tick(mob/living/M) + message_admins("SDGF ticking") if(M.stat == DEAD) + message_admins("SGDF status swapping") if(fermi_Clone && fermi_Clone.stat != DEAD) if(M.mind) M.mind.transfer_to(fermi_Clone) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 243ff10dad..d4c6e93c2a 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -186,43 +186,86 @@ //Setup clone message_admins("SGDF ingested") - var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies - if(LAZYLEN(candidates)) - message_admins("Candidate found!") - //var/typepath = owner.type - //clone = new typepath(owner.loc) - var/typepath = M.type - var/mob/living/carbon/fermi_Gclone = new typepath(M.loc) - //var/mob/living/carbon/SM = owner - //var/mob/living/carbon/M = M - var/mob/living/carbon/SM = fermi_Gclone - if(istype(SM) && istype(M)) - SM.real_name = M.real_name - M.dna.transfer_identity(SM) - SM.updateappearance(mutcolor_update=1) + switch(current_cycle) + if(1) + var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + if(10 to INFINITY) + if(LAZYLEN(candidates)) + message_admins("Candidate found!") + //var/typepath = owner.type + //clone = new typepath(owner.loc) + var/typepath = M.type + var/mob/living/carbon/fermi_Gclone = new typepath(M.loc) + //var/mob/living/carbon/SM = owner + //var/mob/living/carbon/M = M + var/mob/living/carbon/SM = fermi_Gclone + if(istype(SM) && istype(M)) + SM.real_name = M.real_name + M.dna.transfer_identity(SM) + SM.updateappearance(mutcolor_update=1) - var/mob/dead/observer/C = pick(candidates) - SM.key = C.key - SM.mind.enslave_mind_to_creator(M) - //SM.sentience_act() - to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") - to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") - to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") - M.visible_message("[M] suddenly shudders, and splits into two identical twins!") - SM.copy_known_languages_from(M, FALSE) - //after_success(user, SM) - //qdel(src) - else - message_admins("Failed to find clone Candidate") - if(M.has_status_effect(/datum/status_effect/chem/SGDF) + if(M.getorganslot(ORGAN_SLOT_ZOMBIE))//sure, it "treats" it, but "you've" still got it. + var/obj/item/organ/zombie_infection/ZI = M.getorganslot(ORGAN_SLOT_ZOMBIE) + ZI.Remove(M) + ZI.Insert(C) - else - switch(20) - if(1) - M.apply_status_effect(/datum/status_effect/chem/SGDF) + var/mob/dead/observer/C = pick(candidates) + SM.key = C.key + SM.mind.enslave_mind_to_creator(M) + //SM.sentience_act() + to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") + to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") + to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") + M.visible_message("[M] suddenly shudders, and splits into two identical twins!") + SM.copy_known_languages_from(M, FALSE) + //BALANCE: should I make them a pacifist, or give them some cellular damage or weaknesses? + + //after_success(user, SM) + //qdel(src) + + else + message_admins("Failed to find clone Candidate") + if(M.has_status_effect(/datum/status_effect/chem/SGDF)) + to_chat(M, "The cells fail to catalyse around a nucleation event, instead merging with your cells.") //This stuff is hard enough to make to rob a user of some benefit. Shouldn't replace Rezadone as it requires the user to not only risk making a player controlled clone, but also requires them to have split in two (which also requires 30u of SGDF). + M.adjustCloneLoss(-0.5, 0) + M.adjustBruteLoss(-0.5, 0) + M.adjustFireLoss(-0.5, 0) + M.heal_bodypart_damage(1,1) + M.remove_trait(TRAIT_DISFIGURED, TRAIT_GENERIC) + else + switch(current_cycle) + message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") + if(10) + to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") + M.nutrition = M.nutrition + (M.nutrition/30) + if(15) + to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") + M.nutrition = M.nutrition + (M.nutrition/20) + if(20) + to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") + M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! + M.nutrition = M.nutrition + (M.nutrition/10) + if(28) + to_chat(M, "The cells begin to precipitate outwards of your body, you feel like you'll split soon...") + M.nutrition = 200 + if(30) + M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE + M.next_move_modifier = 1 + to_chat(M, "Your body splits away from the cell clone of yourself, leaving your with a drained and hollow feeling inside.") + M.apply_status_effect(/datum/status_effect/chem/SGDF) + M.reagents.del_reagent("SGDF")//removes SGDF on completion. ..() +/datum/reagent/fermi/SDGF/on_mob_delete(mob/living/M) //returns back to original location + if !(M.has_status_effect(/datum/status_effect/chem/SGDF) && M.next_move_modifier == 4) + to_chat(M, "You feel the cells begin to merge with your body, unable to reach nucleation, they instead merge with your body, healing any wounds.") + M.adjustCloneLoss(-10, 0) //I don't want to make Rezadone obsolete. + M.adjustBruteLoss(-50, 0) + M.adjustFireLoss(-50, 0) + M.heal_bodypart_damage(1,1) + M.next_move_modifier = 1 + //Breast englargement /datum/reagent/fermi/BElarger diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 481c7925cf..37729ef21f 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -40,7 +40,7 @@ CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) - ThermicConstant = 20 //Temperature change per 1u produced + ThermicConstant = +20 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics From 4c302a1aa3700405de9bb843e844173e1eabbacf Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 09:00:13 +0100 Subject: [PATCH 44/61] Small changes --- code/modules/reagents/chemistry/reagents.dm | 4 +++- .../code/modules/reagents/chemistry/recipes/fermi.dm | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 01810b9713..578904c096 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -33,7 +33,9 @@ var/addiction_stage4_end = 40 var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick. var/self_consuming = FALSE - var/purity = 1 //Fermichem var + //Fermichem vars: + var/purity = 1 + var/impureChem = "toxin" /datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references . = ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 37729ef21f..9683c61ecb 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -45,7 +45,7 @@ RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics FermiExplode = FALSE //If the chemical explodes in a special way - ImpureChem = "toxin" //What chemical is produced with an inpure reaction + ImpureChem = "SDZF" //What chemical is produced with an inpure reaction /datum/chemical_reaction/BElarger From 3ac2206f754a89b1f61b0fab04b1079f97c43127 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 09:41:58 +0100 Subject: [PATCH 45/61] Added SDGF's fail chem; SDZF. --- .../chemistry/reagents/fermi_reagents.dm | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index d4c6e93c2a..9df95d7492 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -178,8 +178,8 @@ description = "A rapidly diving mass of Embryonic stem cells. These cells are missing a nucleus and quickly replicate a host’s DNA before growing to form an almost perfect clone of the host. In some cases neural replication takes longer, though the underlying reason underneath has yet to be determined." color = "#60A584" // rgb: 96, 0, 255 //var/fClone_current_controller = OWNER - var/mob/living/split_personality/clone//there's two so they can swap without overwriting - var/mob/living/split_personality/owner + //var/mob/living/split_personality/clone//there's two so they can swap without overwriting + //var/mob/living/split_personality/owner //var/mob/living/carbon/SM /datum/reagent/fermi/SGDF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. @@ -251,7 +251,7 @@ if(30) M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE M.next_move_modifier = 1 - to_chat(M, "Your body splits away from the cell clone of yourself, leaving your with a drained and hollow feeling inside.") + to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") M.apply_status_effect(/datum/status_effect/chem/SGDF) M.reagents.del_reagent("SGDF")//removes SGDF on completion. @@ -266,6 +266,46 @@ M.heal_bodypart_damage(1,1) M.next_move_modifier = 1 +/datum/reagent/fermi/SDZF + name = "synthetic-derived zombie factor" + id = "SDGF" + description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. This message should never appear, how did you manage to get a hold of this?" + color = "#60A584" // rgb: 96, 0, 255 + +/datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. + message_admins("SGZF ingested") + switch(current_cycle)//Pretends to be normal + message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") + if(10) + to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") + M.nutrition = M.nutrition + (M.nutrition/30) + if(15) + to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") + M.nutrition = M.nutrition + (M.nutrition/20) + if(20) + to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") + M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! + M.nutrition = M.nutrition + (M.nutrition/10) + if(28) + to_chat(M, "The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...") + M.nutrition = 200 + M.adjustToxLoss(10, 0) + if(30) + message_admins("Zombie spawned at [M.loc]") + M.nutrition = 15//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE + M.next_move_modifier = 1 + to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") + /datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. + M.visible_message("[M] suddenly shudders, and splits herself into a funky smelling copy of themselves!") + M.emote("scream") + M.adjustToxLoss(30, 0) + fermi_Zombie = new typepath(M.loc) + var/mob/living/simple_animal/hostile/zombie/ZI = fermi_Zombie + ZI.damage_coeff = list(BRUTE = ((1 / M.reagents.volume)**0.5) , BURN = ((1 / M.reagents.volume)**0.25), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + ZI.real_name = M.real_name//Give your offspring a big old kiss. + M.reagents.del_reagent("SGZF")//removes SGZF on completion. + ..() + //Breast englargement /datum/reagent/fermi/BElarger From 0ad81b1bb011dff981f52e4ce2d5cc7dcc9d512b Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 12:23:03 +0100 Subject: [PATCH 46/61] The addiction handling is beautiful. --- code/modules/reagents/chemistry/holder.dm | 9 +- .../code/datums/status_effects/chems.dm | 4 +- .../chemistry/reagents/fermi_reagents.dm | 147 +++++++++++------- .../reagents/chemistry/recipes/fermi.dm | 4 +- 4 files changed, 97 insertions(+), 67 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 0b76dcef5d..986d2bce94 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -662,10 +662,6 @@ purity = ((purity * reactedVol) + (deltapH * stepChemAmmount)) /((reactedVol+ stepChemAmmount)) //This should add the purity to the product else purity = deltapH - message_admins("purity: [purity], purity of beaker") - message_admins("Temp before change: [chem_temp], pH after change: [pH]") - //Apply pH changes and thermal output of reaction to beaker - message_admins("Temp after change: [chem_temp], pH after change: [pH]") // End. /* @@ -685,8 +681,13 @@ SSblackbox.record_feedback("tally", "chemical_reaction", cached_results[P]*stepChemAmmount, P)//log add_reagent(P, cached_results[P]*stepChemAmmount, null, chem_temp)//add reagent function!! I THINK I can do this: + message_admins("purity: [purity], purity of beaker") + message_admins("Temp before change: [chem_temp], pH after change: [pH]") + //Apply pH changes and thermal output of reaction to beaker chem_temp += (C.ThermicConstant * stepChemAmmount) pH += (C.HIonRelease * stepChemAmmount) + message_admins("Temp after change: [chem_temp], pH after change: [pH]") + reactedVol = reactedVol + stepChemAmmount diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 54071bff27..5c218dfbe3 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -4,8 +4,8 @@ /datum/status_effect/chem/SGDF/on_apply(mob/living/carbon/M) message_admins("SGDF status appied") - var/typepath = M.type - fermi_Clone = new typepath(M.loc) + var/typepath + fermi_Clone = new typepath(get_turf(M.loc)) //var/mob/living/carbon/M = owner //var/mob/living/carbon/C = fermi_Clone if(istype(fermi_Clone) && istype(M)) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 9df95d7492..6f425f14df 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -35,8 +35,8 @@ addiction_threshold = 30 metabolization_rate = 0.5 * REAGENTS_METABOLISM addiction_stage2_end = 30 - addiction_stage3_end = 40 - addiction_stage4_end = 45 //Incase it's too long + addiction_stage3_end = 41 + addiction_stage4_end = 43 //Incase it's too long var/turf/open/location_created = null var/turf/open/location_return = null var/addictCyc1 = 1 @@ -110,8 +110,9 @@ M.Jitter(50) M.Knockdown(100) M.Stun(40) + var/items = M.get_contents() - var/obj/item/I = pick(items) + var/obj/item/I = pick(items) M.dropItemToGround(I, TRUE) do_sparks(5,FALSE,I) do_teleport(I, get_turf(I), 5, no_effects=TRUE); @@ -136,6 +137,9 @@ message_admins("Fermi T Clone: [fermi_Tclone]") do_teleport(C, get_turf(C), 2, no_effects=TRUE) //teleports clone so it's hard to find the real one! do_sparks(5,FALSE,C) + C.emote("spin") + M.emote("spin") + C.visible_message("[C] [pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")] [pick(""Bugger me, whats all this then?"", "Hot damn, where is this?", "sacre bleu! Où suis-je?!", "Yee haw!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "Ciekawe co na obiad?", "You fool! You took too much eigenstasium! You've doomed us all!", "Watashi no nihon'noanime no yona monodesu!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Detta är sista gången jag dricker beepsky smash.")]") message_admins("Fermi T Clone: [fermi_Tclone] teleport attempt") if(3) var/mob/living/carbon/C = fermi_Tclone @@ -145,19 +149,23 @@ M.visible_message("[M] is snapped across to a different alternative reality!") src.addictCyc3 = 1 //counter fermi_Tclone = null - message_admins("[src.addictCyc3]") src.addictCyc3++ + message_admins("[src.addictCyc3]") do_teleport(M, get_turf(M), 2, no_effects=TRUE) //Teleports player randomly + do_sparks(5,FALSE,M) ..() //loop function /datum/reagent/fermi/eigenstate/addiction_act_stage4(mob/living/M) //Thanks for riding Fermis' wild ride. Mild jitter and player buggery. switch(src.addictCyc4) if(1) - M.Sleeping(20, 0) + do_sparks(5,FALSE,M) + do_teleport(M, get_turf(M), 2, no_effects=TRUE) //teleports clone so it's hard to find the real one! + do_sparks(5,FALSE,M) + M.Sleeping(50, 0) M.Jitter(50) M.Knockdown(0) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") - M.emote("me",1,"gasps and gazes around in a bewildered and highly confused fashion!",TRUE) + M.emote("me",1,"flashes into reality suddenly, gasping as she gazes around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) if(prob(20)) do_sparks(5,FALSE,M) @@ -172,25 +180,29 @@ //eigenstate END //Clone serum #chemClone -/datum/reagent/fermi/SDGF +/datum/reagent/fermi/SDGF //vars, mostly only care about keeping track if there's a player in the clone or not. name = "synthetic-derived growth factor" id = "SDGF" description = "A rapidly diving mass of Embryonic stem cells. These cells are missing a nucleus and quickly replicate a host’s DNA before growing to form an almost perfect clone of the host. In some cases neural replication takes longer, though the underlying reason underneath has yet to be determined." color = "#60A584" // rgb: 96, 0, 255 + var/playerClone = FALSE + var/unitCheck = FALSE + var/list/candidates + //var/fClone_current_controller = OWNER //var/mob/living/split_personality/clone//there's two so they can swap without overwriting //var/mob/living/split_personality/owner //var/mob/living/carbon/SM -/datum/reagent/fermi/SGDF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. +/datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone - message_admins("SGDF ingested") + message_admins("SDGF ingested") switch(current_cycle) - if(1) - var/list/candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + if(1) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. + src.candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(10 to INFINITY) - if(LAZYLEN(candidates)) + if(LAZYLEN(src.candidates)) //If there's candidates, clone the person and put them in there! message_admins("Candidate found!") //var/typepath = owner.type //clone = new typepath(owner.loc) @@ -203,107 +215,124 @@ SM.real_name = M.real_name M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) - - if(M.getorganslot(ORGAN_SLOT_ZOMBIE))//sure, it "treats" it, but "you've" still got it. - var/obj/item/organ/zombie_infection/ZI = M.getorganslot(ORGAN_SLOT_ZOMBIE) - ZI.Remove(M) - ZI.Insert(C) - - var/mob/dead/observer/C = pick(candidates) + var/mob/dead/observer/C = pick(src.candidates) SM.key = C.key SM.mind.enslave_mind_to_creator(M) + + if(M.getorganslot(ORGAN_SLOT_ZOMBIE))//sure, it "treats" it, but "you've" still got it. Doesn't always work as well; needs a ghost. + var/obj/item/organ/zombie_infection/ZI = M.getorganslot(ORGAN_SLOT_ZOMBIE) + ZI.Remove(M) + ZI.Insert(SM) + //SM.sentience_act() to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself, or rather, your original self.") to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. [pick("However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original", "Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.")]") to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") M.visible_message("[M] suddenly shudders, and splits into two identical twins!") SM.copy_known_languages_from(M, FALSE) + src.playerClone = TRUE //BALANCE: should I make them a pacifist, or give them some cellular damage or weaknesses? //after_success(user, SM) //qdel(src) - else + else //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!). message_admins("Failed to find clone Candidate") - if(M.has_status_effect(/datum/status_effect/chem/SGDF)) + src.unitCheck = TRUE + if(M.has_status_effect(/datum/status_effect/chem/SGDF)) // Heal the user if they went to all this trouble to make it and can't get a clone, the poor fellow. to_chat(M, "The cells fail to catalyse around a nucleation event, instead merging with your cells.") //This stuff is hard enough to make to rob a user of some benefit. Shouldn't replace Rezadone as it requires the user to not only risk making a player controlled clone, but also requires them to have split in two (which also requires 30u of SGDF). - M.adjustCloneLoss(-0.5, 0) - M.adjustBruteLoss(-0.5, 0) - M.adjustFireLoss(-0.5, 0) + M.adjustCloneLoss(-2, 0) + M.adjustBruteLoss(-2, 0) + M.adjustFireLoss(-2, 0) M.heal_bodypart_damage(1,1) M.remove_trait(TRAIT_DISFIGURED, TRAIT_GENERIC) - else + else //If there's no ghosts, but they've made a large amount, then proceed to make flavourful clone, where you become fat and useless until you split. switch(current_cycle) - message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") if(10) to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") - M.nutrition = M.nutrition + (M.nutrition/30) - if(15) - to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") - M.nutrition = M.nutrition + (M.nutrition/20) - if(20) - to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") - M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! M.nutrition = M.nutrition + (M.nutrition/10) - if(28) + if(20) + to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") + M.nutrition = M.nutrition + (M.nutrition/5) + if(40) + to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") + M.next_move_modifier = 2//If this makes you fast then please fix it, it should make you slow!! + M.nutrition = M.nutrition + (M.nutrition/2) + if(65) to_chat(M, "The cells begin to precipitate outwards of your body, you feel like you'll split soon...") - M.nutrition = 200 - if(30) + M.nutrition = 2000 + if(75)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done. M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE M.next_move_modifier = 1 to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") M.apply_status_effect(/datum/status_effect/chem/SGDF) M.reagents.del_reagent("SGDF")//removes SGDF on completion. + message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 30") - ..() -/datum/reagent/fermi/SDGF/on_mob_delete(mob/living/M) //returns back to original location - if !(M.has_status_effect(/datum/status_effect/chem/SGDF) && M.next_move_modifier == 4) + //..() + +/datum/reagent/fermi/SDGF/on_mob_delete(mob/living/M) //When the chem is removed, a few things can happen. + if (playerClone == TRUE)//If the player made a clone with it, then thats all they get. + playerClone = FALSE + return + if (M.next_move_modifier == 4 && !M.has_status_effect(/datum/status_effect/chem/SGDF))//checks if they're ingested over 20u of the stuff, but fell short of the required 30u to make a clone. to_chat(M, "You feel the cells begin to merge with your body, unable to reach nucleation, they instead merge with your body, healing any wounds.") M.adjustCloneLoss(-10, 0) //I don't want to make Rezadone obsolete. - M.adjustBruteLoss(-50, 0) - M.adjustFireLoss(-50, 0) + M.adjustBruteLoss(-25, 0)// Note that this takes a long time to apply and makes you fat and useless when it's in you, I don't think this small burst of healing will be useful considering how long it takes to get there. + M.adjustFireLoss(-25, 0) + M.blood_volume += 250 M.heal_bodypart_damage(1,1) M.next_move_modifier = 1 + if (M.nutrition < 1500) + M.nutrition += 250 + else if (src.unitCheck == TRUE && !M.has_status_effect(/datum/status_effect/chem/SGDF))// If they're ingested a little bit (10u minimum), then give them a little healing. + src.unitCheck = FALSE + to_chat(M, "the cells fail to hold enough mass to generate a clone, instead diffusing into your system instead. you can fee") + M.adjustBruteLoss(-10, 0) + M.adjustFireLoss(-10, 0) + M.blood_volume += 100 + if (M.nutrition < 1500) + M.nutrition += 500 /datum/reagent/fermi/SDZF name = "synthetic-derived zombie factor" - id = "SDGF" + id = "SDZF" description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. This message should never appear, how did you manage to get a hold of this?" color = "#60A584" // rgb: 96, 0, 255 + var/fermi_Zombie /datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. message_admins("SGZF ingested") switch(current_cycle)//Pretends to be normal - message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") if(10) to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") - M.nutrition = M.nutrition + (M.nutrition/30) - if(15) - to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") - M.nutrition = M.nutrition + (M.nutrition/20) - if(20) - to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") - M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! M.nutrition = M.nutrition + (M.nutrition/10) - if(28) + if(20) + to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") + M.nutrition = M.nutrition + (M.nutrition/5) + if(40) + to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") + M.next_move_modifier = 2//If this makes you fast then please fix it, it should make you slow!! + M.nutrition = M.nutrition + (M.nutrition/2) + if(65) to_chat(M, "The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...") - M.nutrition = 200 - M.adjustToxLoss(10, 0) - if(30) + M.nutrition = 2000 + M.adjustToxLoss(1, 0) + if(75) message_admins("Zombie spawned at [M.loc]") M.nutrition = 15//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE M.next_move_modifier = 1 - to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") - /datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. + to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") M.visible_message("[M] suddenly shudders, and splits herself into a funky smelling copy of themselves!") M.emote("scream") M.adjustToxLoss(30, 0) - fermi_Zombie = new typepath(M.loc) - var/mob/living/simple_animal/hostile/zombie/ZI = fermi_Zombie - ZI.damage_coeff = list(BRUTE = ((1 / M.reagents.volume)**0.5) , BURN = ((1 / M.reagents.volume)**0.25), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + //fermi_Zombie = new typepath(M.loc) + var/mob/living/simple_animal/hostile/zombie/ZI = new(get_turf(M.loc)) + ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) ZI.real_name = M.real_name//Give your offspring a big old kiss. M.reagents.del_reagent("SGZF")//removes SGZF on completion. + message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 9683c61ecb..481c7925cf 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -40,12 +40,12 @@ CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) CurveSharppH = 2 // How sharp the pH exponential curve is (to the power of value) - ThermicConstant = +20 //Temperature change per 1u produced + ThermicConstant = 20 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics FermiExplode = FALSE //If the chemical explodes in a special way - ImpureChem = "SDZF" //What chemical is produced with an inpure reaction + ImpureChem = "toxin" //What chemical is produced with an inpure reaction /datum/chemical_reaction/BElarger From 10e9cd8b68426c01fff09622cab48bdb72f162d6 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 19:42:35 +0100 Subject: [PATCH 47/61] Minor tweaks and fixes to SDGF and Eigen. --- .../chemistry/reagents/fermi_reagents.dm | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 6f425f14df..81809d361c 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -13,7 +13,7 @@ taste_description = "If affection had a taste, this would be it." /datum/reagent/fermi/on_mob_life(mob/living/carbon/M) - current_cycle++ + //current_cycle++ holder.remove_reagent(src.id, metabolization_rate / M.metabolism_efficiency, FALSE) //fermi reagents stay longer if you have a better metabolism return ..() @@ -65,19 +65,21 @@ /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! switch(current_cycle) if(1) - location_return = get_turf(M.loc) //sets up return point + location_return = get_turf(M) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,M) - M.forceMove(location_created) //Teleports to creation location + do_teleport(M, location_created, 0, asoundin = 'sound/effects/phasein.ogg') + //M.forceMove(location_created) //Teleports to creation location do_sparks(5,FALSE,M) if(prob(20)) do_sparks(5,FALSE,M) + message_admins("eigenstate state: [current_cycle]") ..() /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,src) to_chat(M, "You feel your wavefunction collapse!") - M.forceMove(location_return.loc) //Teleports home + do_teleport(M, location_return, 0, asoundin = 'sound/effects/phasein.ogg') //Teleports home do_sparks(5,FALSE,src) ..() @@ -139,7 +141,8 @@ do_sparks(5,FALSE,C) C.emote("spin") M.emote("spin") - C.visible_message("[C] [pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")] [pick(""Bugger me, whats all this then?"", "Hot damn, where is this?", "sacre bleu! Où suis-je?!", "Yee haw!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "Ciekawe co na obiad?", "You fool! You took too much eigenstasium! You've doomed us all!", "Watashi no nihon'noanime no yona monodesu!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Detta är sista gången jag dricker beepsky smash.")]") + M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) + C.emote("me",1,"[pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")], \"[pick("Bugger me, whats all this then?", "Hot damn, where is this?", "sacre bleu! O� suis-je?!", "Yee haw!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "Ciekawe co na obiad?", "You fool! You took too much eigenstasium! You've doomed us all!", "Watashi no nihon'noanime no yona monodesu!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Detta �r sista g�ngen jag dricker beepsky smash.")]\"") message_admins("Fermi T Clone: [fermi_Tclone] teleport attempt") if(3) var/mob/living/carbon/C = fermi_Tclone @@ -165,7 +168,7 @@ M.Jitter(50) M.Knockdown(0) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") - M.emote("me",1,"flashes into reality suddenly, gasping as she gazes around in a bewildered and highly confused fashion!",TRUE) + M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) if(prob(20)) do_sparks(5,FALSE,M) @@ -250,27 +253,32 @@ switch(current_cycle) if(10) to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") + if(11 to 19) M.nutrition = M.nutrition + (M.nutrition/10) if(20) to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") + if(21 to 39) M.nutrition = M.nutrition + (M.nutrition/5) if(40) to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") - M.next_move_modifier = 2//If this makes you fast then please fix it, it should make you slow!! + M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! + if(41 to 69) M.nutrition = M.nutrition + (M.nutrition/2) - if(65) + if(70) to_chat(M, "The cells begin to precipitate outwards of your body, you feel like you'll split soon...") - M.nutrition = 2000 - if(75)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done. + if M.nutrition < 20000 + M.nutrition = 20000 + if(76)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done. M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE M.next_move_modifier = 1 to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") M.apply_status_effect(/datum/status_effect/chem/SGDF) - M.reagents.del_reagent("SGDF")//removes SGDF on completion. + if(71 to INFINITY) + M.reagents.remove_reagent("SGDF", 5)//removes SGDF on completion. message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 30") - //..() + ..() /datum/reagent/fermi/SDGF/on_mob_delete(mob/living/M) //When the chem is removed, a few things can happen. if (playerClone == TRUE)//If the player made a clone with it, then thats all they get. @@ -307,21 +315,26 @@ switch(current_cycle)//Pretends to be normal if(10) to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") + if(11 to 19) M.nutrition = M.nutrition + (M.nutrition/10) if(20) to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") + if(21 to 39) M.nutrition = M.nutrition + (M.nutrition/5) if(40) to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") - M.next_move_modifier = 2//If this makes you fast then please fix it, it should make you slow!! + M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! + if(41 to 61) M.nutrition = M.nutrition + (M.nutrition/2) - if(65) + if(62) to_chat(M, "The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...") - M.nutrition = 2000 - M.adjustToxLoss(1, 0) - if(75) + if M.nutrition < 20000 + M.nutrition = 20000 + if(63 to 75) + M.adjustToxLoss(1, 0)// the warning! + if(76 && if (!holder.has_reagent("pen_acid")))//Counterplay is pent. message_admins("Zombie spawned at [M.loc]") - M.nutrition = 15//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE + M.nutrition -= 10000//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE M.next_move_modifier = 1 to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") M.visible_message("[M] suddenly shudders, and splits herself into a funky smelling copy of themselves!") @@ -331,7 +344,15 @@ var/mob/living/simple_animal/hostile/zombie/ZI = new(get_turf(M.loc)) ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) ZI.real_name = M.real_name//Give your offspring a big old kiss. - M.reagents.del_reagent("SGZF")//removes SGZF on completion. + M.reagents.remove_reagent("SGZF", 20) + if(77 to INFINITY)//purges chemical fast, producing a "slime" for each one. Said slime is weak to fire. + M.nutrition -= 1000 + var/mob/living/simple_animal/slime/S = new(get_turf(M.loc),"grey") + S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + S.real_name = "rotting tumour." + M.reagents.remove_reagent("SGZF", 50) + M.adjustToxLoss(10, 0) + to_chat(M, "A large glob of the tumour suddenly splits itself from your body. You feel grossed out and slimey...") message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") ..() From 6ec913af78a9d8ba7008dac2ca6f649ac52b2893 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 20:55:59 +0100 Subject: [PATCH 48/61] Futher fixes --- .../code/datums/status_effects/chems.dm | 4 +- .../chemistry/reagents/fermi_reagents.dm | 70 ++++++++++--------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 5c218dfbe3..90eca8d7c8 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -2,10 +2,10 @@ id = "SGDF" var/mob/living/carbon/human/fermi_Clone = null -/datum/status_effect/chem/SGDF/on_apply(mob/living/carbon/M) +/datum/status_effect/chem/SGDF/on_apply(mob/living/M) message_admins("SGDF status appied") var/typepath - fermi_Clone = new typepath(get_turf(M.loc)) + fermi_Clone = new typepath(get_turf(M)) //var/mob/living/carbon/M = owner //var/mob/living/carbon/C = fermi_Clone if(istype(fermi_Clone) && istype(M)) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 81809d361c..9c7cedecbf 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -31,8 +31,8 @@ description = "A strange mixture formed from a controlled reaction of bluespace with plasma, that causes localised eigenstate fluxuations within the patient" taste_description = "." color = "#60A584" // rgb: 96, 0, 255 - overdose_threshold = 20 - addiction_threshold = 30 + overdose_threshold = 15 + addiction_threshold = 20 metabolization_rate = 0.5 * REAGENTS_METABOLISM addiction_stage2_end = 30 addiction_stage3_end = 41 @@ -57,12 +57,12 @@ /datum/reagent/fermi/eigenstate/New() . = ..() //Needed! //if(holder && holder.my_atom) - location_created = get_turf(holder.my_atom) //Sets up coordinate of where it was created + location_created = get_turf(mob/living/M) //Sets up coordinate of where it was created message_admins("Attempting to get creation location from New() [location_created]") //..() -/datum/reagent/fermi/eigenstate/on_mob_life(mob/living/carbon/M) //Teleports to chemistry! +/datum/reagent/fermi/eigenstate/on_mob_life(mob/living/M) //Teleports to chemistry! switch(current_cycle) if(1) location_return = get_turf(M) //sets up return point @@ -71,7 +71,7 @@ do_teleport(M, location_created, 0, asoundin = 'sound/effects/phasein.ogg') //M.forceMove(location_created) //Teleports to creation location do_sparks(5,FALSE,M) - if(prob(20)) + if(prob(20))s do_sparks(5,FALSE,M) message_admins("eigenstate state: [current_cycle]") ..() @@ -142,7 +142,7 @@ C.emote("spin") M.emote("spin") M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) - C.emote("me",1,"[pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")], \"[pick("Bugger me, whats all this then?", "Hot damn, where is this?", "sacre bleu! O� suis-je?!", "Yee haw!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "Ciekawe co na obiad?", "You fool! You took too much eigenstasium! You've doomed us all!", "Watashi no nihon'noanime no yona monodesu!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Detta �r sista g�ngen jag dricker beepsky smash.")]\"") + C.emote("me",1,"[pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")], \"[pick("Bugger me, whats all this then?", "Hot damn, where is this?", "sacre bleu! O� suis-je?!", "Yee haw!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "Ciekawe co na obiad?", "You fool! You took too much eigenstasium! You've doomed us all!", "Watashi no nihon'noanime no yona monodesu!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Detta �r sista g�ngen jag dricker beepsky smash.", "Now neither of us will be virgins!")]\"") message_admins("Fermi T Clone: [fermi_Tclone] teleport attempt") if(3) var/mob/living/carbon/C = fermi_Tclone @@ -190,7 +190,7 @@ color = "#60A584" // rgb: 96, 0, 255 var/playerClone = FALSE var/unitCheck = FALSE - var/list/candidates + var/list/candidates = list() //var/fClone_current_controller = OWNER //var/mob/living/split_personality/clone//there's two so they can swap without overwriting @@ -200,16 +200,18 @@ /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone - message_admins("SDGF ingested") + switch(current_cycle) if(1) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. - src.candidates = pollCandidatesForMob("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + message_admins("Attempting to poll") if(10 to INFINITY) + message_admins("Number of candidates [LAZYLEN(src.candidates)]") if(LAZYLEN(src.candidates)) //If there's candidates, clone the person and put them in there! message_admins("Candidate found!") //var/typepath = owner.type //clone = new typepath(owner.loc) - var/typepath = M.type + //var/typepath = M.type var/mob/living/carbon/fermi_Gclone = new typepath(M.loc) //var/mob/living/carbon/SM = owner //var/mob/living/carbon/M = M @@ -266,16 +268,17 @@ M.nutrition = M.nutrition + (M.nutrition/2) if(70) to_chat(M, "The cells begin to precipitate outwards of your body, you feel like you'll split soon...") - if M.nutrition < 20000 - M.nutrition = 20000 + if (M.nutrition < 20000) + M.nutrition = 20000 if(76)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done. M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE M.next_move_modifier = 1 to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") M.apply_status_effect(/datum/status_effect/chem/SGDF) - if(71 to INFINITY) + if(77 to INFINITY) M.reagents.remove_reagent("SGDF", 5)//removes SGDF on completion. - message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 30") + message_admins("Purging SGDF [volume]") + message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 77") ..() @@ -324,29 +327,32 @@ if(40) to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! - if(41 to 61) + if(41 to 63) M.nutrition = M.nutrition + (M.nutrition/2) - if(62) + if(64) to_chat(M, "The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...") - if M.nutrition < 20000 + if (M.nutrition < 20000) M.nutrition = 20000 - if(63 to 75) + if(65 to 75) M.adjustToxLoss(1, 0)// the warning! - if(76 && if (!holder.has_reagent("pen_acid")))//Counterplay is pent. - message_admins("Zombie spawned at [M.loc]") - M.nutrition -= 10000//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE - M.next_move_modifier = 1 - to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") - M.visible_message("[M] suddenly shudders, and splits herself into a funky smelling copy of themselves!") - M.emote("scream") - M.adjustToxLoss(30, 0) - //fermi_Zombie = new typepath(M.loc) - var/mob/living/simple_animal/hostile/zombie/ZI = new(get_turf(M.loc)) - ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) - ZI.real_name = M.real_name//Give your offspring a big old kiss. - M.reagents.remove_reagent("SGZF", 20) + if(76) + if (!holder.has_reagent("pen_acid"))//Counterplay is pent.) + message_admins("Zombie spawned at [M.loc]") + M.nutrition -= 18500//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE + M.next_move_modifier = 1 + to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") + M.visible_message("[M] suddenly shudders, and splits into a funky smelling copy of themselves!") + M.emote("scream") + M.adjustToxLoss(30, 0) + //fermi_Zombie = new typepath(M.loc) + var/mob/living/simple_animal/hostile/zombie/ZI = new(get_turf(M.loc)) + ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + ZI.real_name = M.real_name//Give your offspring a big old kiss. + M.reagents.remove_reagent("SGZF", 50) + else + to_chat(M, "The pentetic acid seems to have stopped the decay for now, clumping up the cells into a horrifying tumour.") if(77 to INFINITY)//purges chemical fast, producing a "slime" for each one. Said slime is weak to fire. - M.nutrition -= 1000 + M.nutrition -= 100 var/mob/living/simple_animal/slime/S = new(get_turf(M.loc),"grey") S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) S.real_name = "rotting tumour." From 51d7d6237974c0f2073f861069428f1096614889 Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 22:31:16 +0100 Subject: [PATCH 49/61] Midfix --- .../chemistry/Fermi_Chemistry_notes.txt | 6 +-- code/modules/reagents/chemistry/holder.dm | 3 +- .../code/datums/status_effects/chems.dm | 39 ++++++++------ .../chemistry/reagents/fermi_reagents.dm | 52 +++++++++++-------- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt index 541c3e71b3..efcd9b748f 100644 --- a/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt +++ b/code/modules/reagents/chemistry/Fermi_Chemistry_notes.txt @@ -38,9 +38,9 @@ How the end state should look:{ ThermicConstant = -2.5 //Temperature change per 1u produced HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect - optional: - mix_message = "The mixture yields a fine black powder." - required_catalysts = list("plasma" = 5) + //optional: + mix_message = "The mixture yields a fine black powder." + required_catalysts = list("plasma" = 5) edit: required_temp = 380 diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 986d2bce94..2ec63bd19d 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -839,7 +839,8 @@ R.volume = amount if(data) R.data = data - R.on_new(data) + R.on_new(data) + R.loc = holder.loc if(isliving(my_atom)) R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 90eca8d7c8..120f14317c 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -1,28 +1,35 @@ /datum/status_effect/chem/SGDF id = "SGDF" - var/mob/living/carbon/human/fermi_Clone = null + var/mob/living/fermi_Clone -/datum/status_effect/chem/SGDF/on_apply(mob/living/M) + +/datum/status_effect/chem/SGDF/on_apply() message_admins("SGDF status appied") - var/typepath - fermi_Clone = new typepath(get_turf(M)) - //var/mob/living/carbon/M = owner + var/typepath = owner.type + fermi_Clone = new typepath(owner.loc) + var/mob/living/carbon/M = owner + var/mob/living/carbon/C = fermi_Clone + + //fermi_Clone = new typepath(get_turf(M)) //var/mob/living/carbon/C = fermi_Clone - if(istype(fermi_Clone) && istype(M)) - fermi_Clone.real_name = M.real_name - M.dna.transfer_identity(fermi_Clone, transfer_SE=1) - fermi_Clone.updateappearance(mutcolor_update=1) + //var/mob/living/carbon/SM = fermi_Gclone + + if(istype(C) && istype(M)) + C.real_name = M.real_name + M.dna.transfer_identity(C, transfer_SE=1) + C.updateappearance(mutcolor_update=1) return ..() -/datum/status_effect/chem/SGDF/tick(mob/living/M) +/datum/status_effect/chem/SGDF/tick() message_admins("SDGF ticking") - if(M.stat == DEAD) + if(owner.stat == DEAD) message_admins("SGDF status swapping") if(fermi_Clone && fermi_Clone.stat != DEAD) - if(M.mind) - M.mind.transfer_to(fermi_Clone) - M.visible_message("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.") - fermi_Clone = null - //if(!clone || clone.stat == DEAD) + if(owner.mind) + owner.mind.transfer_to(fermi_Clone) + owner.visible_message("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.") + fermi_Clone.visible_message("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.") + fermi_Clone = null + owner.remove_status_effect(src) // to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 9c7cedecbf..343ec50578 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -35,7 +35,7 @@ addiction_threshold = 20 metabolization_rate = 0.5 * REAGENTS_METABOLISM addiction_stage2_end = 30 - addiction_stage3_end = 41 + addiction_stage3_end = 40 addiction_stage4_end = 43 //Incase it's too long var/turf/open/location_created = null var/turf/open/location_return = null @@ -45,33 +45,36 @@ var/addictCyc4 = 1 var/mob/living/fermi_Tclone = null var/teleBool = FALSE + mob/living/carbon/purgeBody -///obj/item/reagent/fermi/eigenstate/Initialize() -/datum/reagent/fermi/eigenstate/on_new() +/* +/datum/reagent/fermi/eigenstate/oew() . = ..() //Needed! location_created = get_turf(src) //Sets up coordinate of where it was created message_admins("Attempting to get creation location from on_new() [location_created]") //..()s - -/datum/reagent/fermi/eigenstate/New() +*/ +/datum/reagent/fermi/eigenstate/on_new() +//obj/item/reagent/fermi/eigenstate/Initialize() +//datum/reagent/fermi/eigenstate/Initialize() . = ..() //Needed! //if(holder && holder.my_atom) - location_created = get_turf(mob/living/M) //Sets up coordinate of where it was created - message_admins("Attempting to get creation location from New() [location_created]") + location_created = get_turf(holder) //Sets up coordinate of where it was created + message_admins("Attempting to get creation location from init() [location_created]") //..() /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/M) //Teleports to chemistry! switch(current_cycle) - if(1) + if(0) location_return = get_turf(M) //sets up return point to_chat(M, "You feel your wavefunction split!") do_sparks(5,FALSE,M) do_teleport(M, location_created, 0, asoundin = 'sound/effects/phasein.ogg') //M.forceMove(location_created) //Teleports to creation location do_sparks(5,FALSE,M) - if(prob(20))s + if(prob(20)) do_sparks(5,FALSE,M) message_admins("eigenstate state: [current_cycle]") ..() @@ -92,7 +95,7 @@ do_sparks(5,FALSE,src) do_teleport(M, get_turf(M), 10, asoundin = 'sound/effects/phasein.ogg') do_sparks(5,FALSE,src) - M.reagents.remove_reagent("eigenstate",0.5)//So you're not stuck for 10 minutes teleporting + holder.remove_reagent("eigenstate",0.5)//So you're not stuck for 10 minutes teleporting ..() //loop function @@ -126,10 +129,10 @@ //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in switch(src.addictCyc3) - if(1) + if(0) M.Jitter(100) to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") - if(2) + if(1) var/typepath = M.type fermi_Tclone = new typepath(M.loc) var/mob/living/carbon/C = fermi_Tclone @@ -144,13 +147,13 @@ M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) C.emote("me",1,"[pick("says", "cries", "mewls", "giggles", "shouts", "screams", "gasps", "moans", "whispers", "announces")], \"[pick("Bugger me, whats all this then?", "Hot damn, where is this?", "sacre bleu! O� suis-je?!", "Yee haw!", "WHAT IS HAPPENING?!", "Picnic!", "Das ist nicht deutschland. Das ist nicht akzeptabel!!!", "Ciekawe co na obiad?", "You fool! You took too much eigenstasium! You've doomed us all!", "Watashi no nihon'noanime no yona monodesu!", "What...what's with these teleports? It's like one of my Japanese animes...!", "Ik stond op het punt om mehki op tafel te zetten, en nu, waar ben ik?", "This must be the will of Stein's gate.", "Detta �r sista g�ngen jag dricker beepsky smash.", "Now neither of us will be virgins!")]\"") message_admins("Fermi T Clone: [fermi_Tclone] teleport attempt") - if(3) + if(2) var/mob/living/carbon/C = fermi_Tclone do_sparks(5,FALSE,C) qdel(C) //Deletes CLONE, or at least I hope it is. message_admins("Fermi T Clone: [fermi_Tclone] deletion attempt") M.visible_message("[M] is snapped across to a different alternative reality!") - src.addictCyc3 = 1 //counter + src.addictCyc3 = 0 //counter fermi_Tclone = null src.addictCyc3++ message_admins("[src.addictCyc3]") @@ -197,21 +200,26 @@ //var/mob/living/split_personality/owner //var/mob/living/carbon/SM +/datum/reagent/fermi/SDGF/on_mob_add(mob/living/carbon/M) + src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + message_admins("Attempting to poll") + + /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone switch(current_cycle) - if(1) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. - src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies - message_admins("Attempting to poll") + //if(0) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. + // src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + // message_admins("Attempting to poll") if(10 to INFINITY) message_admins("Number of candidates [LAZYLEN(src.candidates)]") - if(LAZYLEN(src.candidates)) //If there's candidates, clone the person and put them in there! + if(LAZYLEN(src.candidates) && src.playerClone == FALSE) //If there's candidates, clone the person and put them in there! message_admins("Candidate found!") //var/typepath = owner.type //clone = new typepath(owner.loc) - //var/typepath = M.type + var/typepath = M.type var/mob/living/carbon/fermi_Gclone = new typepath(M.loc) //var/mob/living/carbon/SM = owner //var/mob/living/carbon/M = M @@ -276,7 +284,7 @@ to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") M.apply_status_effect(/datum/status_effect/chem/SGDF) if(77 to INFINITY) - M.reagents.remove_reagent("SGDF", 5)//removes SGDF on completion. + holder.remove_reagent("SGDF", 5)//removes SGDF on completion. message_admins("Purging SGDF [volume]") message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 77") @@ -348,7 +356,7 @@ var/mob/living/simple_animal/hostile/zombie/ZI = new(get_turf(M.loc)) ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) ZI.real_name = M.real_name//Give your offspring a big old kiss. - M.reagents.remove_reagent("SGZF", 50) + holder.remove_reagent("SGZF", 50) else to_chat(M, "The pentetic acid seems to have stopped the decay for now, clumping up the cells into a horrifying tumour.") if(77 to INFINITY)//purges chemical fast, producing a "slime" for each one. Said slime is weak to fire. @@ -356,7 +364,7 @@ var/mob/living/simple_animal/slime/S = new(get_turf(M.loc),"grey") S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) S.real_name = "rotting tumour." - M.reagents.remove_reagent("SGZF", 50) + holder.remove_reagent("SGZF", 50) M.adjustToxLoss(10, 0) to_chat(M, "A large glob of the tumour suddenly splits itself from your body. You feel grossed out and slimey...") message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 20") From 492f3fde885955351ef4f6abf5008d4d3393849d Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 22:38:18 +0100 Subject: [PATCH 50/61] Commited uncompliedable code (oops) --- code/modules/reagents/chemistry/holder.dm | 5 +++-- code/modules/reagents/chemistry/reagents.dm | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 2ec63bd19d..fb14cab18f 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -837,10 +837,11 @@ cached_reagents += R R.holder = src R.volume = amount + R.loc = get_turf(my_atom) if(data) R.data = data - R.on_new(data) - R.loc = holder.loc + R.on_new(data) + if(isliving(my_atom)) R.on_mob_add(my_atom) //Must occur befor it could posibly run on_mob_delete diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 578904c096..1bf862bd5e 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -36,6 +36,7 @@ //Fermichem vars: var/purity = 1 var/impureChem = "toxin" + var/loc = null /datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references . = ..() From d4990d2823779b400a5dd7a4bc158272f68f915a Mon Sep 17 00:00:00 2001 From: Fermi Date: Tue, 23 Apr 2019 23:05:40 +0100 Subject: [PATCH 51/61] What --- .../chemistry/reagents/fermi_reagents.dm | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 343ec50578..b9177a5795 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -60,7 +60,7 @@ //datum/reagent/fermi/eigenstate/Initialize() . = ..() //Needed! //if(holder && holder.my_atom) - location_created = get_turf(holder) //Sets up coordinate of where it was created + location_created = get_turf(loc) //Sets up coordinate of where it was created message_admins("Attempting to get creation location from init() [location_created]") //..() @@ -200,19 +200,15 @@ //var/mob/living/split_personality/owner //var/mob/living/carbon/SM -/datum/reagent/fermi/SDGF/on_mob_add(mob/living/carbon/M) - src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies - message_admins("Attempting to poll") - - /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone - - switch(current_cycle) - //if(0) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. - // src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies - // message_admins("Attempting to poll") + if(0) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. + src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + message_admins("Attempting to poll") + if(15) + src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + message_admins("Attempting to poll2") if(10 to INFINITY) message_admins("Number of candidates [LAZYLEN(src.candidates)]") if(LAZYLEN(src.candidates) && src.playerClone == FALSE) //If there's candidates, clone the person and put them in there! @@ -244,6 +240,9 @@ M.visible_message("[M] suddenly shudders, and splits into two identical twins!") SM.copy_known_languages_from(M, FALSE) src.playerClone = TRUE + + M.next_move_modifier = 1 + M.nutrition = 150 //BALANCE: should I make them a pacifist, or give them some cellular damage or weaknesses? //after_success(user, SM) From f8ae8b325fdb29ee595e0258d2e537d9d33b3da8 Mon Sep 17 00:00:00 2001 From: Trilbyspaceclone <30435998+Trilbyspaceclone@users.noreply.github.com> Date: Tue, 23 Apr 2019 18:52:51 -0400 Subject: [PATCH 52/61] Update fermi_reagents.dm --- .../chemistry/reagents/fermi_reagents.dm | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index b9177a5795..da2206a1f1 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -386,3 +386,23 @@ if(M.gender == FEMALE) M.gender = MALE M.visible_message("[M] suddenly looks more masculine!", "You suddenly feel more masculine!") + +//Nanite removal +/datum/reagent/fermi/naninte_b_gone + name = "Naninte bain" + id = "naninte_b_gone" + description = "A rather simple toxin to small nano machines that will kill them off at a rapid rate well in system." + color = "#5a7267" // rgb: 90, 114, 103 + overdose_threshold = 25 + +/datum/reagent/fermi/naninte_b_gone/on_mob_life(mob/living/carbon/C) + if(C./datum/component/nanites) + regen_rate = -5.0 + else + retrun + +/datum/reagent/fermi/naninte_b_gone/overdose_start(mob/living/carbon/C) + if(C./datum/component/nanites) + regen_rate = -7.5 + else + retrun From 946191ae673f54b39c5921f257dfc2f711fa36f7 Mon Sep 17 00:00:00 2001 From: Trilbyspaceclone <30435998+Trilbyspaceclone@users.noreply.github.com> Date: Tue, 23 Apr 2019 19:08:11 -0400 Subject: [PATCH 53/61] Update fermi.dm --- .../reagents/chemistry/recipes/fermi.dm | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 481c7925cf..22814de64c 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -66,3 +66,27 @@ HIonRelease = 0.01 //pH change per 1u reaction RateUpLim = 50 //Optimal/max rate possible if all conditions are perfect FermiChem = TRUE + +//Nano-b-gone +/datum/chemical_reaction/naninte_b_gone + name = "Naninte bain" + id = "naninte_b_gone" + results = list("naninte_b_gone" = 5) + required_reagents = list("synthflesh" = 5, "blood" = 3, "sugar" = 1, "salglu_solution" = 3) + mix_message = "the blood and sugar mixes catalysting a hard coating around the synth flesh" + //FermiChem vars: + OptimalTempMin = 450 + OptimalTempMax = 600 + ExplodeTemp = 700 + OptimalpHMin = 6 + OptimalpHMax = 8 + ReactpHLim = 1 + CatalystFact = 1 + CurveSharpT = 4 + CurveSharppH = 2 + ThermicConstant = -2.5 + HIonRelease = 0.01 + RateUpLim = 5 + FermiChem = TRUE + FermiExplode = FALSE + ImpureChem = "carpotoxin" From 1ffc1414703aab2d437e37e4c5b5a512806a6168 Mon Sep 17 00:00:00 2001 From: Trilbyspaceclone <30435998+Trilbyspaceclone@users.noreply.github.com> Date: Tue, 23 Apr 2019 19:08:51 -0400 Subject: [PATCH 54/61] fixed --- .../code/modules/reagents/chemistry/recipes/fermi.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 22814de64c..966e1d4910 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -81,7 +81,7 @@ OptimalpHMin = 6 OptimalpHMax = 8 ReactpHLim = 1 - CatalystFact = 1 + CatalystFact = 0 //To do 1 CurveSharpT = 4 CurveSharppH = 2 ThermicConstant = -2.5 From 682bf09cd5cde614b9849cac2774ad6a6ed0c585 Mon Sep 17 00:00:00 2001 From: Fermi Date: Wed, 24 Apr 2019 00:31:14 +0100 Subject: [PATCH 55/61] Mintor tests --- .../chemistry/reagents/fermi_reagents.dm | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index b9177a5795..6413e6c58b 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -130,9 +130,11 @@ //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in switch(src.addictCyc3) if(0) + if(1) M.Jitter(100) to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") if(1) + if(2) var/typepath = M.type fermi_Tclone = new typepath(M.loc) var/mob/living/carbon/C = fermi_Tclone @@ -200,18 +202,19 @@ //var/mob/living/split_personality/owner //var/mob/living/carbon/SM +/datum/reagent/fermi/SDGF/New(mob/living/carbon/M) + candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies + message_admins("Attempting to poll") + /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone switch(current_cycle) - if(0) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. - src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies + if(1) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. + src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies message_admins("Attempting to poll") - if(15) - src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 300, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm, should allow admins to ban greifers or bullies - message_admins("Attempting to poll2") if(10 to INFINITY) message_admins("Number of candidates [LAZYLEN(src.candidates)]") - if(LAZYLEN(src.candidates) && src.playerClone == FALSE) //If there's candidates, clone the person and put them in there! + if(LAZYLEN(candidates) && src.playerClone == FALSE) //If there's candidates, clone the person and put them in there! message_admins("Candidate found!") //var/typepath = owner.type //clone = new typepath(owner.loc) @@ -224,7 +227,7 @@ SM.real_name = M.real_name M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) - var/mob/dead/observer/C = pick(src.candidates) + var/mob/dead/observer/C = pick(candidates) SM.key = C.key SM.mind.enslave_mind_to_creator(M) @@ -239,7 +242,7 @@ to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") M.visible_message("[M] suddenly shudders, and splits into two identical twins!") SM.copy_known_languages_from(M, FALSE) - src.playerClone = TRUE + playerClone = TRUE M.next_move_modifier = 1 M.nutrition = 150 @@ -271,6 +274,7 @@ if(40) to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! + candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(41 to 69) M.nutrition = M.nutrition + (M.nutrition/2) if(70) @@ -283,7 +287,7 @@ to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") M.apply_status_effect(/datum/status_effect/chem/SGDF) if(77 to INFINITY) - holder.remove_reagent("SGDF", 5)//removes SGDF on completion. + holder.remove_reagent("SGDF", 1)//removes SGDF on completion. message_admins("Purging SGDF [volume]") message_admins("Growth nucleation occuring (SDGF), step [current_cycle] of 77") From 120d8177ab613d98a87712ea45f4bfb5f252453e Mon Sep 17 00:00:00 2001 From: Fermi Date: Wed, 24 Apr 2019 00:57:42 +0100 Subject: [PATCH 56/61] aaaaa --- .../chemistry/reagents/fermi_reagents.dm | 22 ++++++++++--------- .../reagents/chemistry/recipes/fermi.dm | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index f1e7417f0d..c85a904c0c 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -201,11 +201,12 @@ //var/mob/living/split_personality/clone//there's two so they can swap without overwriting //var/mob/living/split_personality/owner //var/mob/living/carbon/SM - -/datum/reagent/fermi/SDGF/New(mob/living/carbon/M) - candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies +/* +/datum/reagent/fermi/SDGF/New() + candidates = pollGhostCandidates("Do you want to play as a clone and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies message_admins("Attempting to poll") - +^^^breaks everything +*/ /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone switch(current_cycle) @@ -274,13 +275,13 @@ if(40) to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! - candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies + //candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(41 to 69) M.nutrition = M.nutrition + (M.nutrition/2) if(70) to_chat(M, "The cells begin to precipitate outwards of your body, you feel like you'll split soon...") if (M.nutrition < 20000) - M.nutrition = 20000 + M.nutrition = 20000 //https://www.youtube.com/watch?v=Bj_YLenOlZI if(76)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done. M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE M.next_move_modifier = 1 @@ -343,7 +344,7 @@ if(64) to_chat(M, "The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...") if (M.nutrition < 20000) - M.nutrition = 20000 + M.nutrition = 20000 //https://www.youtube.com/watch?v=Bj_YLenOlZI if(65 to 75) M.adjustToxLoss(1, 0)// the warning! if(76) @@ -390,7 +391,7 @@ if(M.gender == FEMALE) M.gender = MALE M.visible_message("[M] suddenly looks more masculine!", "You suddenly feel more masculine!") - +/* //Nanite removal /datum/reagent/fermi/naninte_b_gone name = "Naninte bain" @@ -403,10 +404,11 @@ if(C./datum/component/nanites) regen_rate = -5.0 else - retrun + return /datum/reagent/fermi/naninte_b_gone/overdose_start(mob/living/carbon/C) if(C./datum/component/nanites) regen_rate = -7.5 else - retrun + return +*/ diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 966e1d4910..d4cbf6847a 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -72,7 +72,7 @@ name = "Naninte bain" id = "naninte_b_gone" results = list("naninte_b_gone" = 5) - required_reagents = list("synthflesh" = 5, "blood" = 3, "sugar" = 1, "salglu_solution" = 3) + required_reagents = list("synthflesh" = 5, "blood" = 3, "uranium" = 1, "salglu_solution" = 3) mix_message = "the blood and sugar mixes catalysting a hard coating around the synth flesh" //FermiChem vars: OptimalTempMin = 450 From 6ee338b66f65573e2cd4db9bead7f4be11012b42 Mon Sep 17 00:00:00 2001 From: Fermi Date: Wed, 24 Apr 2019 03:09:29 +0100 Subject: [PATCH 57/61] MONSTER, BUT FUNCTIONAl, SDGF CODE! --- .../code/datums/status_effects/chems.dm | 9 ++++ .../chemistry/reagents/fermi_reagents.dm | 54 +++++++++++++++---- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 120f14317c..6f3d4c99ae 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -33,3 +33,12 @@ owner.remove_status_effect(src) // to_chat(owner, "[linked_extract] desperately tries to move your soul to a living body, but can't find one!") ..() + +/datum/status_effect/chem/SDGF/candidates + id = "SGDFCandi" + var/mob/living/fermi_Clone + var/list/candies = list() + +/datum/status_effect/chem/SDGF/candidates/on_apply() + candies = pollGhostCandidates("Do you want to play as a clone and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies + return ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index c85a904c0c..1b761341f5 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -195,7 +195,12 @@ color = "#60A584" // rgb: 96, 0, 255 var/playerClone = FALSE var/unitCheck = FALSE - var/list/candidates = list() + metabolization_rate = 0.25 * REAGENTS_METABOLISM + //var/datum/status_effect/chem/SDGF/candidates/candies + var/list/candies = list() + var/polling = FALSE + var/list/result = list() + var/list/group = null //var/fClone_current_controller = OWNER //var/mob/living/split_personality/clone//there's two so they can swap without overwriting @@ -207,15 +212,37 @@ message_admins("Attempting to poll") ^^^breaks everything */ +/datum/reagent/fermi/proc/sepPoll() + var/list/procCandies = list() + procCandies = pollGhostCandidates("Do you want to play as a clone and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 20) // see poll_ignore.dm, should allow admins to ban greifers or bullies + return procCandies + + /*if(1) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. + M.apply_status_effect(/datum/status_effect/chem/SDGF/candidates) + /datum/status_effect/chem/SDGF/candidates/candies = new /datum/status_effect/chem/SDGF/candidates + ///datum/status_effect/chem/SDGF/candidates/candies = M.apply_status_effect(/datum/status_effect/chem/SDGF/candidates) + //candies = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies + message_admins("Attempting to poll")*/ + /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone + if(polling == FALSE) + for(var/mob/dead/observer/G in GLOB.player_list) + group += G + for(var/m in group) + var/mob/W = m + message_admins("Attempting to poll") + polling = TRUE + showCandidatePollWindow(M, 20, "Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you.", result, null, current_cycle, TRUE) switch(current_cycle) - if(1) //I'm not sure how pollCanditdates works, so I did this. Gives a chance for people to say yes. - src.candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies - message_admins("Attempting to poll") - if(10 to INFINITY) - message_admins("Number of candidates [LAZYLEN(src.candidates)]") - if(LAZYLEN(candidates) && src.playerClone == FALSE) //If there's candidates, clone the person and put them in there! + if(19) + for(var/mob/W in result) + if(!W.key || !W.client) + result -= W + candies = result + if(20 to INFINITY) + message_admins("Number of candidates [LAZYLEN(candies)]") + if(LAZYLEN(candies) && src.playerClone == FALSE) //If there's candidates, clone the person and put them in there! message_admins("Candidate found!") //var/typepath = owner.type //clone = new typepath(owner.loc) @@ -228,7 +255,7 @@ SM.real_name = M.real_name M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) - var/mob/dead/observer/C = pick(candidates) + var/mob/dead/observer/C = pick(candies) SM.key = C.key SM.mind.enslave_mind_to_creator(M) @@ -273,7 +300,7 @@ if(21 to 39) M.nutrition = M.nutrition + (M.nutrition/5) if(40) - to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") + to_chat(M, "The synthetic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! //candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(41 to 69) @@ -323,6 +350,7 @@ id = "SDZF" description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. This message should never appear, how did you manage to get a hold of this?" color = "#60A584" // rgb: 96, 0, 255 + metabolization_rate = 0.25 * REAGENTS_METABOLISM var/fermi_Zombie /datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. @@ -360,14 +388,18 @@ var/mob/living/simple_animal/hostile/zombie/ZI = new(get_turf(M.loc)) ZI.damage_coeff = list(BRUTE = ((1 / volume)**0.25) , BURN = ((1 / volume)**0.1), TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) ZI.real_name = M.real_name//Give your offspring a big old kiss. + ZI.name = M.real_name + //ZI.updateappearance(mutcolor_update=1) holder.remove_reagent("SGZF", 50) else to_chat(M, "The pentetic acid seems to have stopped the decay for now, clumping up the cells into a horrifying tumour.") if(77 to INFINITY)//purges chemical fast, producing a "slime" for each one. Said slime is weak to fire. M.nutrition -= 100 var/mob/living/simple_animal/slime/S = new(get_turf(M.loc),"grey") - S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) - S.real_name = "rotting tumour." + S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + S.name = "Living teratoma" + S.real_name = "Living teratoma" + //S.updateappearance(mutcolor_update=1) holder.remove_reagent("SGZF", 50) M.adjustToxLoss(10, 0) to_chat(M, "A large glob of the tumour suddenly splits itself from your body. You feel grossed out and slimey...") From 2e57f4dacf2724f99fdc9a14be52ae5e931ad76b Mon Sep 17 00:00:00 2001 From: Fermi Date: Wed, 24 Apr 2019 03:13:37 +0100 Subject: [PATCH 58/61] Quick test and fix --- .../reagents/chemistry/reagents/fermi_reagents.dm | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 1b761341f5..c2fcf8f94a 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -198,7 +198,7 @@ metabolization_rate = 0.25 * REAGENTS_METABOLISM //var/datum/status_effect/chem/SDGF/candidates/candies var/list/candies = list() - var/polling = FALSE + //var/polling = FALSE var/list/result = list() var/list/group = null @@ -226,15 +226,14 @@ /datum/reagent/fermi/SDGF/on_mob_life(mob/living/carbon/M) //Clones user, then puts a ghost in them! If that fails, makes a braindead clone. //Setup clone - if(polling == FALSE) + switch(current_cycle) + if(1) for(var/mob/dead/observer/G in GLOB.player_list) group += G for(var/m in group) var/mob/W = m message_admins("Attempting to poll") - polling = TRUE - showCandidatePollWindow(M, 20, "Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you.", result, null, current_cycle, TRUE) - switch(current_cycle) + showCandidatePollWindow(M, 190, "Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you.", result, null, current_cycle, TRUE) if(19) for(var/mob/W in result) if(!W.key || !W.client) From 06cabb1e0ad618f657c0bba440fed01692459e7e Mon Sep 17 00:00:00 2001 From: Fermi Date: Wed, 24 Apr 2019 03:14:24 +0100 Subject: [PATCH 59/61] Who said don't commit before compile testing? --- .../reagents/chemistry/reagents/fermi_reagents.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index c2fcf8f94a..1d1dbdefd6 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -228,12 +228,12 @@ //Setup clone switch(current_cycle) if(1) - for(var/mob/dead/observer/G in GLOB.player_list) - group += G - for(var/m in group) - var/mob/W = m - message_admins("Attempting to poll") - showCandidatePollWindow(M, 190, "Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you.", result, null, current_cycle, TRUE) + for(var/mob/dead/observer/G in GLOB.player_list) + group += G + for(var/m in group) + var/mob/W = m + message_admins("Attempting to poll") + showCandidatePollWindow(M, 190, "Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you.", result, null, current_cycle, TRUE) if(19) for(var/mob/W in result) if(!W.key || !W.client) From 52c9a9d6805c716df4d5fce3a462202a92e08b29 Mon Sep 17 00:00:00 2001 From: Fermi Date: Wed, 24 Apr 2019 04:35:38 +0100 Subject: [PATCH 60/61] Fixed dumb bugs --- .../modules/reagents/chemistry/reagents/fermi_reagents.dm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 1d1dbdefd6..9f13ac4d4c 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -130,11 +130,9 @@ //Clone function - spawns a clone then deletes it - simulates multiple copies of the player teleporting in switch(src.addictCyc3) if(0) - if(1) M.Jitter(100) to_chat(M, "Your eigenstate starts to rip apart, causing a localised collapsed field as you're ripped from alternative universes, trapped around the densisty of the eigenstate event horizon.") if(1) - if(2) var/typepath = M.type fermi_Tclone = new typepath(M.loc) var/mob/living/carbon/C = fermi_Tclone @@ -174,7 +172,12 @@ M.Knockdown(0) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself. This version of you feels more [pick("affectionate", "happy", "lusty", "radical", "shy", "ambitious", "frank", "voracious", "sensible", "witty")] than your previous self, sent to god knows what universe.") M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) + M.reagents.remove_all_type(/datum/reagent/toxin, 5*REM, 0, 1) + for(var/i in M.mood_events) + SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, i.id) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "Alternative dimension", /datum/mood_event/eigenstate) + + if(prob(20)) do_sparks(5,FALSE,M) src.addictCyc4++ From b21599a151e7ae34ccdf653068b389d578911f1a Mon Sep 17 00:00:00 2001 From: Thalpy <33956696+Thalpy@users.noreply.github.com> Date: Wed, 24 Apr 2019 17:35:07 +0100 Subject: [PATCH 61/61] Don't overwrite admins --- config/admins.txt | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 config/admins.txt diff --git a/config/admins.txt b/config/admins.txt deleted file mode 100644 index ff2d1362e0..0000000000 --- a/config/admins.txt +++ /dev/null @@ -1,12 +0,0 @@ -############################################################################################### -# Basically, ckey goes first. Rank goes after the "=" # -# Case is not important for ckey. # -# Case IS important for the rank. # -# All punctuation (spaces etc) EXCEPT '-', '_' and '@' will be stripped from rank names. # -# Ranks can be anything defined in admin_ranks.txt # -# NOTE: if the rank-name cannot be found in admin_ranks.txt, they will not be adminned! ~Carn # -# NOTE: syntax was changed to allow hyphenation of ranknames, since spaces are stripped. # -############################################################################################### - -yourckeygoeshere = Host -Useroth = Game Master