[MIRROR] Fermichem 2.4 - C2 medicine recipe adaptations and atunements to the new mechanics (#3701)

* Fermichem 2.4 - C2 medicine recipe adaptations and atunements to the new mechanics

* Update human_defense.dm

Co-authored-by: Thalpy <33956696+Thalpy@users.noreply.github.com>
Co-authored-by: Gandalf2k15 <jzo123@hotmail.com>
This commit is contained in:
SkyratBot
2021-02-28 15:21:34 +00:00
committed by GitHub
co-authored by Thalpy Gandalf2k15
parent 9b408206ec
commit 4032c73891
47 changed files with 2010 additions and 243 deletions
+8
View File
@@ -135,6 +135,14 @@
#define SCREWYHUD_DEAD 2
#define SCREWYHUD_HEALTHY 3
//Health doll screws for human mobs
#define SCREWYDOLL_HEAD /obj/item/bodypart/head
#define SCREWYDOLL_CHEST /obj/item/bodypart/chest
#define SCREWYDOLL_L_ARM /obj/item/bodypart/l_arm
#define SCREWYDOLL_R_ARM /obj/item/bodypart/r_arm
#define SCREWYDOLL_L_LEG /obj/item/bodypart/l_leg
#define SCREWYDOLL_R_LEG /obj/item/bodypart/r_leg
//Threshold levels for beauty for humans
#define BEAUTY_LEVEL_HORRID -66
#define BEAUTY_LEVEL_BAD -33
+12
View File
@@ -55,6 +55,9 @@
///Default pH for reagents datum
#define CHEMICAL_NORMAL_PH 7.000
///The default purity of all non reacted reagents
#define REAGENT_STANDARD_PUIRTY 0.75
//reagent bitflags, used for altering how they works
///allows on_mob_dead() if present in a dead body
#define REAGENT_DEAD_PROCESS (1<<0)
@@ -82,6 +85,10 @@
#define REACTION_HEAT_ARBITARY (1<<4)
///Used to bypass the chem_master transfer block (This is needed for competitive reactions unless you have an end state programmed). More stuff might be added later. When defining this, please add in the comments the associated reactions that it competes with
#define REACTION_COMPETITIVE (1<<5)
///Used to force pH changes to be constant regardless of volume
#define REACTION_PH_VOL_CONSTANT (1<<6)
///If a reaction will generate it's impure/inverse reagents in the middle of a reaction, as apposed to being determined on ingestion/on reaction completion
#define REACTION_REAL_TIME_SPLIT (1<<7)
///Used for overheat_temp - This sets the overheat so high it effectively has no overheat temperature.
#define NO_OVERHEAT 99999
@@ -144,3 +151,8 @@
#define REACTION_TAG_PLANT (1<<20)
/// This reaction is produces a product that affects plants
#define REACTION_TAG_COMPETITIVE (1<<21)
/// Below are defines used for reagent associated machines only
/// For the pH meter flashing method
#define ENABLE_FLASHING -1
#define DISABLE_FLASHING 14
+4
View File
@@ -309,4 +309,8 @@ DEFINE_BITFIELD(reaction_flags, list(
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE,
"REACTION_CLEAR_RETAIN" = REACTION_CLEAR_RETAIN,
"REACTION_INSTANT" = REACTION_INSTANT,
"REACTION_HEAT_ARBITARY" = REACTION_HEAT_ARBITARY,
"REACTION_COMPETITIVE" = REACTION_COMPETITIVE,
"REACTION_PH_VOL_CONSTANT" = REACTION_PH_VOL_CONSTANT,
"REACTION_REAL_TIME_SPLIT" = REACTION_REAL_TIME_SPLIT,
))
+1
View File
@@ -21,6 +21,7 @@ GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction datu
GLOBAL_LIST(chemical_reactions_list_product_index) //list of all /datum/chemical_reaction datums. Used for the reaction lookup UI. Indexed by PRODUCT type
GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
GLOBAL_LIST(chemical_reactions_results_lookup_list) //List of all reactions with their associated product and result ids. Used for reaction lookups
GLOBAL_LIST(fake_reagent_blacklist) //List of all reagents that are parent types used to define a bunch of children - but aren't used themselves as anything.
GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id.
GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path.
GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes
@@ -14,10 +14,12 @@ PROCESSING_SUBSYSTEM_DEF(reagents)
. = ..()
//So our first step isn't insane
previous_world_time = world.time
///Blacklists these reagents from being added to the master list. the exact type only. Children are not blacklisted.
GLOB.fake_reagent_blacklist = list(/datum/reagent/medicine/c2, /datum/reagent/medicine, /datum/reagent/reaction_agent)
//Build GLOB lists - see holder.dm
build_chemical_reagent_list()
build_chemical_reactions_lists()
return
return
/datum/controller/subsystem/processing/reagents/fire(resumed = FALSE)
if (!resumed)
+12 -3
View File
@@ -170,6 +170,8 @@ GENE SCANNER
var/mob/living/carbon/human/H = M
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
render_list += "<span class='alert'>Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!</span>\n"
if(H.has_reagent(/datum/reagent/inverse/technetium))
advanced = TRUE
render_list += "<span class='info'>Analyzing results for [M]:</span>\n<span class='info ml-1'>Overall status: [mob_status]</span>\n"
@@ -324,9 +326,16 @@ GENE SCANNER
for(var/obj/item/organ/organ in H.internal_organs)
var/status = ""
if (organ.organ_flags & ORGAN_FAILING) status = "<font color='#cc3333'>Non-Functional</font>"
else if (organ.damage > organ.high_threshold) status = "<font color='#ff9933'>Severely Damaged</font>"
else if (organ.damage > organ.low_threshold) status = "<font color='#ffcc33'>Mildly Damaged</font>"
if(H.has_reagent(/datum/reagent/inverse/technetium))
if(organ.damage)
status = "<font color='#E42426'> organ is [round((organ.damage/organ.maxHealth)*100, 1)]% damaged.</font>"
else
if (organ.organ_flags & ORGAN_FAILING)
status = "<font color='#cc3333'>Non-Functional</font>"
else if (organ.damage > organ.high_threshold)
status = "<font color='#ff9933'>Severely Damaged</font>"
else if (organ.damage > organ.low_threshold)
status = "<font color='#ffcc33'>Mildly Damaged</font>"
if (status != "")
render = TRUE
toReport += "<tr><td><font color='#cc3333'>[organ.name]:</font></td>\
@@ -3,3 +3,6 @@
/datum/actionspeed_modifier/blunt_wound
variable = TRUE
/datum/actionspeed_modifier/nooartrium
multiplicative_slowdown = 0.5
+57
View File
@@ -7,6 +7,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
/datum/hallucination/battle = 20,
/datum/hallucination/dangerflash = 15,
/datum/hallucination/hudscrew = 12,
/datum/hallucination/fake_health_doll = 12,
/datum/hallucination/fake_alert = 12,
/datum/hallucination/weird_sounds = 8,
/datum/hallucination/stationmessage = 7,
@@ -1152,6 +1153,62 @@ GLOBAL_LIST_INIT(hallucination_list, list(
target.clear_alert(alert_type, clear_override = TRUE)
qdel(src)
///Causes the target to see incorrect health damages on the healthdoll
/datum/hallucination/fake_health_doll
var/timer_id = null
///Creates a specified doll hallucination, or picks one randomly
/datum/hallucination/fake_health_doll/New(mob/living/carbon/human/human_mob, forced = TRUE, specific_limb, severity, duration = 500)
. = ..()
if(!specific_limb)
specific_limb = pick(list(SCREWYDOLL_HEAD, SCREWYDOLL_CHEST, SCREWYDOLL_L_ARM, SCREWYDOLL_R_ARM, SCREWYDOLL_L_LEG, SCREWYDOLL_R_LEG))
if(!severity)
severity = rand(1, 5)
LAZYSET(human_mob.hal_screwydoll, specific_limb, severity)
human_mob.update_health_hud()
timer_id = addtimer(CALLBACK(src, .proc/cleanup), duration, TIMER_STOPPABLE)
///Increments the severity of the damage seen on the doll
/datum/hallucination/fake_health_doll/proc/increment_fake_damage()
if(!ishuman(target))
stack_trace("Somehow [target] managed to get a fake health doll hallucination, while not being a human mob.")
var/mob/living/carbon/human/human_mob = target
for(var/entry in human_mob.hal_screwydoll)
human_mob.hal_screwydoll[entry] = clamp(human_mob.hal_screwydoll[entry]+1, 1, 5)
human_mob.update_health_hud()
///Adds a fake limb to the hallucination datum effect
/datum/hallucination/fake_health_doll/proc/add_fake_limb(specific_limb, severity)
if(!specific_limb)
specific_limb = pick(list(SCREWYDOLL_HEAD, SCREWYDOLL_CHEST, SCREWYDOLL_L_ARM, SCREWYDOLL_R_ARM, SCREWYDOLL_L_LEG, SCREWYDOLL_R_LEG))
if(!severity)
severity = rand(1, 5)
var/mob/living/carbon/human/human_mob = target
LAZYSET(human_mob.hal_screwydoll, specific_limb, severity)
target.update_health_hud()
/datum/hallucination/fake_health_doll/target_deleting()
if(isnull(timer_id))
return
deltimer(timer_id)
timer_id = null
..()
///Cleans up the hallucinations - this deletes any overlap, but that shouldn't happen.
/datum/hallucination/fake_health_doll/proc/cleanup()
qdel(src)
//So that the associated addition proc cleans it up correctly
/datum/hallucination/fake_health_doll/Destroy()
if(!ishuman(target))
stack_trace("Somehow [target] managed to get a fake health doll hallucination, while not being a human mob.")
var/mob/living/carbon/human/human_mob = target
LAZYNULL(human_mob.hal_screwydoll)
human_mob.update_health_hud()
..()
/datum/hallucination/items/New(mob/living/carbon/C, forced = TRUE)
set waitfor = FALSE
..()
@@ -181,6 +181,18 @@
required_reagents = list(/datum/reagent/consumable/nutriment/protein = 0.5)
required_catalysts = list(/datum/reagent/medicine/metafactor = 0.5)
/datum/chemical_reaction/food/failed_nutriconversion
results = list(/datum/reagent/peptides_failed = 0.5)
required_reagents = list(/datum/reagent/consumable/nutriment/ = 0.5)
required_catalysts = list(/datum/reagent/impurity/probital_failed = 0.5)
thermic_constant = 100 // a tell
/datum/chemical_reaction/food/failed_protein_peptide
results = list(/datum/reagent/peptides_failed = 0.5)
required_reagents = list(/datum/reagent/consumable/nutriment/protein = 0.5)
required_catalysts = list(/datum/reagent/impurity/probital_failed = 0.5)
thermic_constant = 100 // a tell
/datum/chemical_reaction/food/bbqsauce
results = list(/datum/reagent/consumable/bbqsauce = 5)
required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/tomatojuice = 1, /datum/reagent/medicine/salglu_solution = 3, /datum/reagent/consumable/blackpepper = 1)
+1 -1
View File
@@ -49,7 +49,7 @@
/mob/living/brain/get_ear_protection()//no ears
return 2
/mob/living/brain/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/brain/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, length = 25)
return // no eyes, no flashing
/mob/living/brain/can_be_revived()
@@ -597,7 +597,7 @@
return embeds
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, length = 25)
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
if(!eyes) //can't flash what can't see!
return
@@ -148,8 +148,6 @@
if(get_bodypart(BODY_ZONE_HEAD) && !getorgan(/obj/item/organ/brain))
. += "<span class='deadsay'>It appears that [t_his] brain is missing...</span>"
var/temp = getBruteLoss() //no need to calculate each of these twice
var/list/msg = list()
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
@@ -202,6 +200,11 @@
msg += "[t_He] [p_do()]n't seem all there.\n"
if(!(user == src && src.hal_screwyhud == SCREWYHUD_HEALTHY)) //fake healthy
var/temp
if(user == src && src.hal_screwyhud == SCREWYHUD_CRIT)//fake damage
temp = 50
else
temp = getBruteLoss()
if(temp)
if(temp < 25)
msg += "[t_He] [t_has] minor bruising.\n"
+10 -5
View File
@@ -879,11 +879,16 @@
hud_used.healthdoll.cut_overlays()
if(stat != DEAD)
hud_used.healthdoll.icon_state = "healthdoll_OVERLAY"
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
var/damage = BP.burn_dam + BP.brute_dam
var/comparison = (BP.max_damage/5)
for(var/obj/item/bodypart/body_part as anything in bodyparts)
var/icon_num = 0
//Hallucinations
if(body_part.type in hal_screwydoll)
icon_num = hal_screwydoll[body_part.type]
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[body_part.body_zone][icon_num]"))
continue
//Not hallucinating
var/damage = body_part.burn_dam + body_part.brute_dam
var/comparison = (body_part.max_damage/5)
if(damage)
icon_num = 1
if(damage > (comparison))
@@ -897,7 +902,7 @@
if(hal_screwyhud == SCREWYHUD_HEALTHY)
icon_num = 0
if(icon_num)
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[BP.body_zone][icon_num]"))
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[body_part.body_zone][icon_num]"))
for(var/t in get_missing_limbs()) //Missing limbs
hud_used.healthdoll.add_overlay(mutable_appearance('icons/hud/screen_gen.dmi', "[t]6"))
for(var/t in get_disabled_limbs()) //Disabled limbs
@@ -688,18 +688,17 @@
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
for(var/X in bodyparts)
var/obj/item/bodypart/LB = X
missing -= LB.body_zone
if(LB.is_pseudopart) //don't show injury text for fake bodyparts; ie chainsaw arms or synthetic armblades
for(var/obj/item/bodypart/body_part as anything in bodyparts)
missing -= body_part.body_zone
if(body_part.is_pseudopart) //don't show injury text for fake bodyparts; ie chainsaw arms or synthetic armblades
continue
var/self_aware = FALSE
if(HAS_TRAIT(src, TRAIT_SELF_AWARE))
self_aware = TRUE
var/limb_max_damage = LB.max_damage
var/limb_max_damage = body_part.max_damage
var/status = ""
var/brutedamage = LB.brute_dam
var/burndamage = LB.burn_dam
var/brutedamage = body_part.brute_dam
var/burndamage = body_part.burn_dam
if(hallucination)
if(prob(30))
brutedamage += rand(30,40)
@@ -712,21 +711,24 @@
status = "no damage"
else
if(body_part.type in hal_screwydoll)//Are we halucinating?
brutedamage = (hal_screwydoll[body_part.type] * 0.2)*limb_max_damage
if(brutedamage > 0)
status = LB.light_brute_msg
status = body_part.light_brute_msg
if(brutedamage > (limb_max_damage*0.4))
status = LB.medium_brute_msg
status = body_part.medium_brute_msg
if(brutedamage > (limb_max_damage*0.8))
status = LB.heavy_brute_msg
status = body_part.heavy_brute_msg
if(brutedamage > 0 && burndamage > 0)
status += " and "
if(burndamage > (limb_max_damage*0.8))
status += LB.heavy_burn_msg
status += body_part.heavy_burn_msg
else if(burndamage > (limb_max_damage*0.2))
status += LB.medium_burn_msg
status += body_part.medium_burn_msg
else if(burndamage > 0)
status += LB.light_burn_msg
status += body_part.light_burn_msg
if(status == "")
status = "OK"
@@ -734,45 +736,45 @@
if(status == "OK" || status == "no damage")
no_damage = TRUE
var/isdisabled = ""
if(LB.bodypart_disabled)
if(body_part.bodypart_disabled)
isdisabled = " is disabled"
if(no_damage)
isdisabled += " but otherwise"
else
isdisabled += " and"
combined_msg += "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name][isdisabled][self_aware ? " has " : " is "][status].</span>"
combined_msg += "\t <span class='[no_damage ? "notice" : "warning"]'>Your [body_part.name][isdisabled][self_aware ? " has " : " is "][status].</span>"
for(var/thing in LB.wounds)
for(var/thing in body_part.wounds)
var/datum/wound/W = thing
var/msg
switch(W.severity)
if(WOUND_SEVERITY_TRIVIAL)
//msg = "\t <span class='danger'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)].</span>" //ORIGINAL
msg = "\t <span class='danger'>Your [LB.name] is suffering [W.a_or_from] [W.get_topic_name(src)].</span>" //SKYRAT EDIT CHANGE - MEDICAL
msg = "\t <span class='danger'>Your [body_part.name] is suffering [W.a_or_from] [W.get_topic_name(src)].</span>" //SKYRAT EDIT CHANGE - MEDICAL
if(WOUND_SEVERITY_MODERATE)
//msg = "\t <span class='warning'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</span>" //ORIGINAL
msg = "\t <span class='warning'>Your [LB.name] is suffering [W.a_or_from] [W.get_topic_name(src)]!</span>" //SKYRAT EDIT CHANGE - MEDICAL
msg = "\t <span class='warning'>Your [body_part.name] is suffering [W.a_or_from] [W.get_topic_name(src)]!</span>" //SKYRAT EDIT CHANGE - MEDICAL
if(WOUND_SEVERITY_SEVERE)
//msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</b></span>" //ORIGINAL
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [W.get_topic_name(src)]!</b></span>" //SKYRAT EDIT CHANGE - MEDICAL
msg = "\t <span class='warning'><b>Your [body_part.name] is suffering [W.a_or_from] [W.get_topic_name(src)]!</b></span>" //SKYRAT EDIT CHANGE - MEDICAL
if(WOUND_SEVERITY_CRITICAL)
//msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!</b></span>" //ORIGINAL
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [W.get_topic_name(src)]!!</b></span>" //SKYRAT EDIT CHANGE - MEDICAL
msg = "\t <span class='warning'><b>Your [body_part.name] is suffering [W.a_or_from] [W.get_topic_name(src)]!!</b></span>" //SKYRAT EDIT CHANGE - MEDICAL
combined_msg += msg
for(var/obj/item/I in LB.embedded_objects)
for(var/obj/item/I in body_part.embedded_objects)
if(I.isEmbedHarmless())
combined_msg += "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>"
combined_msg += "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(body_part)]' class='warning'>There is \a [I] stuck to your [body_part.name]!</a>"
else
combined_msg += "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>"
combined_msg += "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(body_part)]' class='warning'>There is \a [I] embedded in your [body_part.name]!</a>"
//SKYRAT EDIT ADDITION BEGIN - MEDICAL
if(LB.current_gauze)
var/datum/bodypart_aid/current_gauze = LB.current_gauze
combined_msg += "\t <span class='notice'>Your [LB.name] is [current_gauze.desc_prefix] with <a href='?src=[REF(current_gauze)];remove=1'>[current_gauze.get_description()]</a>.</span>"
if(LB.current_splint)
var/datum/bodypart_aid/current_splint = LB.current_splint
combined_msg += "\t <span class='notice'>Your [LB.name] is [current_splint.desc_prefix] with <a href='?src=[REF(current_splint)];remove=1'>[current_splint.get_description()]</a>.</span>"
if(body_part.current_gauze)
var/datum/bodypart_aid/current_gauze = body_part.current_gauze
combined_msg += "\t <span class='notice'>Your [body_part.name] is [current_gauze.desc_prefix] with <a href='?src=[REF(current_gauze)];remove=1'>[current_gauze.get_description()]</a>.</span>"
if(body_part.current_splint)
var/datum/bodypart_aid/current_splint = body_part.current_splint
combined_msg += "\t <span class='notice'>Your [body_part.name] is [current_splint.desc_prefix] with <a href='?src=[REF(current_splint)];remove=1'>[current_splint.get_description()]</a>.</span>"
//SKYRAT EDIT END
for(var/t in missing)
@@ -77,3 +77,6 @@
///Exposure to damaging heat levels increases stacks, stacks clean over time when temperatures are lower. Stack is consumed to add a wound.
var/heat_exposure_stacks = 0
///human specific screwyhuds from hallucinations (define key (bodypart) to int value (severity)) - see /datum/hallucination/fake_health_doll
var/hal_screwydoll
+2 -2
View File
@@ -414,12 +414,12 @@
return TRUE
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash)
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, length = 25)
if(HAS_TRAIT(src, TRAIT_NOFLASH))
return FALSE
if(get_eye_protection() < intensity && (override_blindness_check || !is_blind()))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", length), length)
return TRUE
return FALSE
@@ -57,5 +57,5 @@
. = ..(Proj)
updatehealth()
/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, length = 25)
return // no eyes, no flashing
@@ -123,6 +123,6 @@
Proj.on_hit(src, 0, piercing_hit)
return BULLET_ACT_HIT
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/static)
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/static, length = 25)
if(affect_silicon)
return ..()
@@ -302,7 +302,7 @@
if(cleared)
to_chat(src, "--- [class] alarm in [A.name] has been cleared.")
/mob/living/simple_animal/drone/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/simple_animal/drone/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, length = 25)
if(affect_silicon)
return ..()
@@ -33,3 +33,6 @@
/datum/movespeed_modifier/reagent/nuka_cola
multiplicative_slowdown = -0.35
/datum/movespeed_modifier/reagent/nooartrium
multiplicative_slowdown = 2
+36 -9
View File
@@ -44,6 +44,8 @@
var/thermic_mod = 1
///Allow us to deal with lag by "charging" up our reactions to react faster over a period - this means that the reaction doesn't suddenly mass react - which can cause explosions
var/time_deficit
///Used to store specific data needed for a reaction, usually used to keep track of things between explosion calls. CANNOT be used as a part of chemical_recipe - those vars are static lookup tables.
var/data = list()
/*
* Creates and sets up a new equlibrium object
@@ -203,16 +205,16 @@
* This was moved from the start, to the end - after a reaction, so post reaction temperature changes aren't ignored.
* overheated() is first - so double explosions can't happen (i.e. explosions that blow up the holder)
*/
/datum/equilibrium/proc/check_fail_states()
/datum/equilibrium/proc/check_fail_states(vol_added)
//Are we overheated?
if(reaction.is_cold_recipe)
if(holder.chem_temp < reaction.overheat_temp) //This is before the process - this is here so that overly_impure and overheated() share the same code location (and therefore vars) for calls.
if(holder.chem_temp < reaction.overheat_temp && reaction.overheat_temp != NO_OVERHEAT) //This is before the process - this is here so that overly_impure and overheated() share the same code location (and therefore vars) for calls.
SSblackbox.record_feedback("tally", "chemical_reaction", 1, "[reaction.type] overheated reaction steps")
reaction.overheated(holder, src)
reaction.overheated(holder, src, vol_added)
else
if(holder.chem_temp > reaction.overheat_temp)
SSblackbox.record_feedback("tally", "chemical_reaction", 1, "[reaction.type] overheated reaction steps")
reaction.overheated(holder, src)
reaction.overheated(holder, src, vol_added)
//is our product too impure?
for(var/product in reaction.results)
@@ -221,7 +223,7 @@
continue
if (reagent.purity < reaction.purity_min)//If purity is below the min, call the proc
SSblackbox.record_feedback("tally", "chemical_reaction", 1, "[reaction.type] overly impure reaction steps")
reaction.overly_impure(holder, src)
reaction.overly_impure(holder, src, vol_added)
//did we explode?
if(!holder.my_atom || holder.reagent_list.len == 0)
@@ -331,15 +333,40 @@
for(var/reagent in reaction.required_reagents)
holder.remove_reagent(reagent, (delta_chem_factor * reaction.required_reagents[reagent]), safety = TRUE)
//Apply pH changes
holder.adjust_specific_reagent_ph(reagent, (delta_chem_factor * reaction.required_reagents[reagent])*(reaction.H_ion_release*h_ion_mod))
var/pH_adjust
if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT)
pH_adjust = ((delta_chem_factor * reaction.required_reagents[reagent])/target_vol)*(reaction.H_ion_release*h_ion_mod)
else //Default adds pH independant of volume
pH_adjust = (delta_chem_factor * reaction.required_reagents[reagent])*(reaction.H_ion_release*h_ion_mod)
holder.adjust_specific_reagent_ph(reagent, pH_adjust)
var/step_add
for(var/product in reaction.results)
//create the products
step_add = delta_chem_factor * reaction.results[product]
holder.add_reagent(product, step_add, null, cached_temp, purity, override_base_ph = TRUE)
//If we make purities in real time
if(reaction.reaction_flags & REACTION_REAL_TIME_SPLIT && purity < 1)
var/datum/reagent/product_ref = GLOB.chemical_reagents_list[product]
if(purity < reaction.purity_min && product_ref.failed_chem) //If we're failed
holder.add_reagent(product_ref.failed_chem, step_add, null, cached_temp, (1-purity), override_base_ph = TRUE)
else if(purity < product_ref.inverse_chem_val && product_ref.inverse_chem) //If we're inverse
holder.add_reagent(product_ref.inverse_chem, step_add, null, cached_temp, (1-purity), override_base_ph = TRUE)
else if(product_ref.impure_chem && product_ref.impure_chem) //if we're impure
holder.add_reagent(product*purity, step_add, null, cached_temp, purity, override_base_ph = TRUE)
holder.add_reagent(product_ref.impure_chem*(1-purity), step_add, null, cached_temp, (1-purity), override_base_ph = TRUE)
else //We can get here if the flag is set, but there's no associated impure_chem assigned. In some cases this is desired (i.e. multiver only wants to real time split it's inverse chem)
holder.add_reagent(product, step_add, null, cached_temp, purity, override_base_ph = TRUE)
//Default handiling
else
holder.add_reagent(product, step_add, null, cached_temp, purity, override_base_ph = TRUE)
//Apply pH changes
holder.adjust_specific_reagent_ph(product, step_add*reaction.H_ion_release)
var/pH_adjust
if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT)
pH_adjust = (step_add/target_vol)*(reaction.H_ion_release*h_ion_mod)
else
pH_adjust = step_add*(reaction.H_ion_release*h_ion_mod)
holder.adjust_specific_reagent_ph(product, pH_adjust)
reacted_vol += step_add
total_step_added += step_add
@@ -367,7 +394,7 @@
reaction_quality = purity
//post reaction checks
if(!(check_fail_states()))
if(!(check_fail_states(total_step_added)))
to_delete = TRUE
//end reactions faster so plumbing is faster
+6 -8
View File
@@ -13,6 +13,8 @@
GLOB.chemical_reagents_list = list()
for(var/path in paths)
if(path in GLOB.fake_reagent_blacklist)
continue
var/datum/reagent/D = new path()
GLOB.chemical_reagents_list[path] = D
@@ -32,9 +34,9 @@
//Randomized need to go last since they need to check against conflicts with normal recipes
var/paths = subtypesof(/datum/chemical_reaction) - typesof(/datum/chemical_reaction/randomized) + subtypesof(/datum/chemical_reaction/randomized)
GLOB.chemical_reactions_list = list()
GLOB.chemical_reactions_results_lookup_list = list()
GLOB.chemical_reactions_list_product_index = list()
GLOB.chemical_reactions_list = list() //reagents to reaction list
GLOB.chemical_reactions_results_lookup_list = list() //UI glob
GLOB.chemical_reactions_list_product_index = list() //product to reaction list
for(var/path in paths)
var/datum/chemical_reaction/D = new path()
@@ -529,7 +531,6 @@
return
if(amount < 0)
return
var/cached_amount = amount
if(get_reagent_amount(reagent) < amount)
amount = get_reagent_amount(reagent)
@@ -904,7 +905,6 @@
mix_message += temp_mix_message
continue
SSblackbox.record_feedback("tally", "chemical_reaction", 1, "[equilibrium.reaction.type] total reaction steps")
if(num_reactions)
SEND_SIGNAL(src, COMSIG_REAGENTS_REACTION_STEP, num_reactions, delta_time)
@@ -1022,7 +1022,6 @@
target.previous_reagent_list = LAZYLISTDUPLICATE(previous_reagent_list)
target.is_reacting = is_reacting
///Checks to see if the reagents has a difference in reagents_list and previous_reagent_list (I.e. if there's a difference between the previous call and the last)
///Also checks to see if the saved reactions in failed_but_capable_reactions can start as a result of temp/pH change
/datum/reagents/proc/has_changed_state()
@@ -1126,7 +1125,6 @@
if (R.purity == 1)
return
if(R.chemical_flags & REAGENT_DONOTSPLIT)
R.purity = 1
return
if(R.purity < 0)
stack_trace("Purity below 0 for chem: [type]!")
@@ -1145,7 +1143,7 @@
if(!(R.chemical_flags & REAGENT_SPLITRETAINVOL))
remove_reagent(R.type, impureVol, FALSE)
add_reagent(R.impure_chem, impureVol, FALSE, added_purity = 1-R.creation_purity)
R.purity = 1 //prevent this process from repeating (this is why creation_purity exists)
R.chemical_flags |= REAGENT_DONOTSPLIT
/// Updates [/datum/reagents/var/total_volume]
/datum/reagents/proc/update_total()
@@ -1,5 +1,3 @@
#define ENABLE_FLASHING -1
///Tutorial states
#define TUT_NO_BUFFER 50
#define TUT_START 1
@@ -26,7 +24,6 @@
var/heater_coefficient = 0.05
var/on = FALSE
var/dispense_volume = 1
//The list of active clients using this heater, so that we can update the UI on a reaction_step. I assume there are multiple clients possible.
var/list/ui_client_list
///If the user has the tutorial enabled
@@ -107,7 +104,6 @@
return
if(beaker?.reagents.has_reagent(/datum/reagent/mercury, 10) || beaker?.reagents.has_reagent(/datum/reagent/chlorine, 10))
tutorial_state = TUT_HAS_REAGENTS
if(TUT_HAS_REAGENTS)
if(!(beaker?.reagents.has_reagent(/datum/reagent/mercury, 9)) || !(beaker?.reagents.has_reagent(/datum/reagent/chlorine, 9)))
tutorial_state = TUT_MISSING
@@ -175,7 +171,6 @@
var/obj/item/reagent_containers/syringe/S = I
S.afterattack(beaker, user, 1)
return
return ..()
/obj/machinery/chem_heater/on_deconstruction()
@@ -253,7 +248,7 @@
data["beakerContents"] = beaker_contents
var/list/active_reactions = list()
var/flashing = 14 //for use with alertAfter - since there is no alertBefore, I set the after to 0 if true, or to the max value if false
var/flashing = DISABLE_FLASHING //for use with alertAfter - since there is no alertBefore, I set the after to 0 if true, or to the max value if false
for(var/_reaction in beaker?.reagents.reaction_list)
var/datum/equilibrium/equilibrium = _reaction
if(!length(beaker.reagents.reaction_list))//I'm not sure why when it explodes it causes the gui to fail (it's missing danger (?) )
@@ -275,7 +270,7 @@
if(equilibrium.reaction.optimal_ph_min > beaker?.reagents.ph || equilibrium.reaction.optimal_ph_max < beaker?.reagents.ph)
flashing = ENABLE_FLASHING
if(equilibrium.reaction.is_cold_recipe)
if(equilibrium.reaction.overheat_temp > beaker?.reagents.chem_temp)
if(equilibrium.reaction.overheat_temp > beaker?.reagents.chem_temp && equilibrium.reaction.overheat_temp != NO_OVERHEAT)
danger = TRUE
overheat = TRUE
else
@@ -494,3 +489,12 @@ To continue set your target temperature to 390K."}
. = ..()
reagents.add_reagent(/datum/reagent/reaction_agent/basic_buffer, 20)
reagents.add_reagent(/datum/reagent/reaction_agent/acidic_buffer, 20)
#undef TUT_NO_BUFFER
#undef TUT_START
#undef TUT_HAS_REAGENTS
#undef TUT_IS_ACTIVE
#undef TUT_IS_REACTING
#undef TUT_FAIL
#undef TUT_COMPLETE
#undef TUT_MISSING
@@ -24,23 +24,41 @@
var/minorImpurity
///The count of reactions that resolve below 0.9 purity
var/majorImpurity
///If we failed to react this current chem so use a lower temp
///If we failed to react this current chem so use a lower temp - all reactions only
var/failed = 0
///If we're forcing optimal conditions
var/should_force_temp = FALSE
var/should_force_ph = FALSE
///Forced values
var/force_temp = 300
var/force_ph = 7
///Multiplier of product
var/vol_multiplier = 20
///If we're reacting
var/react = FALSE
///Number of delta times taken to react
var/react_time = 0
///IF we're doing EVERY reaction
var/process_all = FALSE
///The name
var/list/reaction_names = list()
///If it's started
var/reaction_stated = FALSE
///If we spawn a beaker at the end of a reaction or not
var/beaker_spawn = FALSE
///If we force min temp on reaction setup
var/min_temp = FALSE
///Create reagents datum
/obj/machinery/chem_recipe_debug/Initialize()
. = ..()
create_reagents(9000)//I want to make sure everything fits
end_processing()
///Enable the machine
/obj/machinery/chem_recipe_debug/attackby(obj/item/I, mob/user, params)
. = .()
if(processing)
say("currently processing reaction [index]: [cached_reactions[index]] of [cached_reactions.len]")
return
say("Starting processing")
setup_reactions()
begin_processing()
ui_interact(usr)
///Enable the machine
/obj/machinery/chem_recipe_debug/AltClick(mob/living/user)
@@ -48,6 +66,7 @@
if(processing)
say("currently processing reaction [index]: [cached_reactions[index]] of [cached_reactions.len]")
return
process_all = TRUE
say("Starting processing")
setup_reactions()
begin_processing()
@@ -55,10 +74,13 @@
///Resets the index, and creates the cached_reaction list from all possible reactions
/obj/machinery/chem_recipe_debug/proc/setup_reactions()
cached_reactions = list()
for(var/V in GLOB.chemical_reactions_list)
if(is_type_in_list(GLOB.chemical_reactions_list[V], cached_reactions))
continue
cached_reactions += GLOB.chemical_reactions_list[V]
if(process_all)
for(var/reaction in GLOB.chemical_reactions_list)
if(is_type_in_list(GLOB.chemical_reactions_list[reaction], cached_reactions))
continue
cached_reactions += GLOB.chemical_reactions_list[reaction]
else
cached_reactions = reaction_names
reagents.clear_reagents()
index = 1
processing = TRUE
@@ -70,60 +92,261 @@
/obj/machinery/chem_recipe_debug/process(delta_time)
if(processing == FALSE)
setup_reactions()
if(should_force_ph)
reagents.ph = force_ph
if(should_force_temp)
reagents.chem_temp = force_temp
if(reagents.is_reacting == TRUE)
react_time += delta_time
return
if(index >= cached_reactions.len)
say("Completed testing, missing reactions products (may have exploded) are:")
say("[problem_string]")
say("Problem with results are:")
say("[impure_string]")
say("Reactions with minor impurity: [minorImpurity], reactions with major impurity: [majorImpurity]")
processing = FALSE
end_processing()
if(reagents.reagent_list)
say("Reaction completed for [cached_reactions[index]] final temperature = [reagents.chem_temp], ph = [reagents.ph].")
var/datum/chemical_reaction/C = cached_reactions[index]
for(var/R in C.results)
var/datum/reagent/R2 = reagents.get_reagent(R)
if(!R2)
say("<span class='warning'>Unable to find product [R] in holder after reaction! reagents found are:</span>")
for(var/R3 in reagents.reagent_list)
say("[R3]")
var/obj/item/reagent_containers/glass/beaker/bluespace/B = new /obj/item/reagent_containers/glass/beaker/bluespace(loc)
reagents.trans_to(B)
B.name = "[cached_reactions[index]]"
if(failed > 0)
problem_string += "[cached_reactions[index]] <span class='warning'>Unable to find product [R] in holder after reaction! index:[index]</span>\n"
failed++
continue
say("Reaction has a product [R] [R2.volume]u purity of [R2.purity]")
if(R2.purity < 0.9)
impure_string += "Reaction [cached_reactions[index]] has a product [R] [R2.volume]u <span class='boldwarning'>purity of [R2.purity]</span> index:[index]\n"
majorImpurity++
else if (R2.purity < 1)
impure_string += "Reaction [cached_reactions[index]] has a product [R] [R2.volume]u <span class='warning'>purity of [R2.purity]</span> index:[index]\n"
minorImpurity++
if(R2.volume < C.results[R])
impure_string += "Reaction [cached_reactions[index]] has a product [R] <span class='warning'>[R2.volume]u</span> purity of [R2.purity] index:[index]\n"
reagents.clear_reagents()
if(failed > 1)
index++
failed = 0
if(failed == 0)
index++
var/datum/chemical_reaction/C = cached_reactions[index]
if(!C)
say("Unable to find reaction on index: [index]")
for(var/R in C.required_reagents)
reagents.add_reagent(R, C.required_reagents[R]*20)
for(var/cat in C.required_catalysts)
reagents.add_reagent(cat, C.required_catalysts[cat])
if(failed == 0)
reagents.chem_temp = C.optimal_temp
if(failed == 1)
reagents.chem_temp = C.required_temp+25
failed++
say("Reacting <span class='nicegreen'>[cached_reactions[index]]</span> starting pH: [reagents.ph] index [index] of [cached_reactions.len]")
if(C.reaction_flags & REACTION_INSTANT)
say("This reaction is instant")
if(reaction_stated == TRUE)
reaction_stated = FALSE
relay_ended_reaction()
if(index > cached_reactions.len)
relay_all_reactions()
return
setup_reaction()
reaction_stated = TRUE
/obj/machinery/chem_recipe_debug/proc/relay_all_reactions()
say("Completed testing, missing reactions products (may have exploded) are:")
say("[problem_string]")
say("Problem with results are:")
say("[impure_string]")
say("Reactions with minor impurity: [minorImpurity], reactions with major impurity: [majorImpurity]")
processing = FALSE
problem_string = null
impure_string = null
minorImpurity = null
majorImpurity = null
end_processing()
/obj/machinery/chem_recipe_debug/proc/relay_ended_reaction()
if(reagents.reagent_list)
var/cached_purity
say("Reaction completed for [cached_reactions[index]] final temperature = [reagents.chem_temp], ph = [reagents.ph], time taken = [react_time]s.")
var/datum/chemical_reaction/reaction = cached_reactions[index]
for(var/reagent_type in reaction.results)
var/datum/reagent/reagent = reagents.get_reagent(reagent_type)
if(!reagent)
say("<span class='warning'>Unable to find product [reagent_type] in holder after reaction! reagents found are:</span>")
for(var/other_reagent in reagents.reagent_list)
say("[other_reagent]")
var/obj/item/reagent_containers/glass/beaker/bluespace/beaker = new /obj/item/reagent_containers/glass/beaker/bluespace(loc)
reagents.trans_to(beaker)
beaker.name = "[cached_reactions[index]] failed"
if(!failed)
problem_string += "[cached_reactions[index]] <span class='warning'>Unable to find product [reagent_type] in holder after reaction! Trying alternative setup. index:[index]</span>\n"
failed++
return
say("Reaction has a product [reagent_type] [reagent.volume]u purity of [reagent.purity]")
if(reagent.purity < 0.9)
impure_string += "Reaction [cached_reactions[index]] has a product [reagent_type] [reagent.volume]u <span class='boldwarning'>purity of [reagent.purity]</span> index:[index]\n"
majorImpurity++
else if (reagent.purity < 1)
impure_string += "Reaction [cached_reactions[index]] has a product [reagent_type] [reagent.volume]u <span class='warning'>purity of [reagent.purity]</span> index:[index]\n"
minorImpurity++
if(reagent.volume < reaction.results[reagent_type])
impure_string += "Reaction [cached_reactions[index]] has a product [reagent_type] <span class='warning'>[reagent.volume]u</span> purity of [reagent.purity] index:[index]\n"
cached_purity = reagent.purity
if(beaker_spawn && reagents.total_volume)
var/obj/item/reagent_containers/glass/beaker/bluespace/beaker = new /obj/item/reagent_containers/glass/beaker/bluespace(loc)
reagents.trans_to(beaker)
beaker.name = "[cached_reactions[index]] purity: [cached_purity]"
reagents.clear_reagents()
reagents.chem_temp = 300
index++
failed = 0
else
say("No reagents left in beaker!")
index++
/obj/machinery/chem_recipe_debug/proc/setup_reaction()
react_time = 0
if(!length(cached_reactions))
return FALSE
var/datum/chemical_reaction/reaction = cached_reactions[index]
if(!reaction)
say("Unable to find reaction on index: [index]")
say("Using forced temperatures.")
if(reaction.reaction_flags & REACTION_INSTANT)
say("This reaction is instant")
for(var/reagent_type in reaction.required_reagents)
reagents.add_reagent(reagent_type, reaction.required_reagents[reagent_type]*vol_multiplier)
for(var/catalyst_type in reaction.required_catalysts)
reagents.add_reagent(catalyst_type, reaction.required_catalysts[catalyst_type])
if(should_force_temp && !min_temp)
say("Using forced temperatures.")
reagents.chem_temp = force_temp ? force_temp : reaction.optimal_temp
if(should_force_ph)
say("Using forced pH.")
reagents.ph = force_ph ? force_ph : (reaction.optimal_ph_max + reaction.optimal_ph_min)/2
if(failed == 0 && !should_force_temp)
reagents.chem_temp = reaction.optimal_temp
if(failed == 1 && !should_force_temp)
reagents.chem_temp = reaction.required_temp+25
failed++
if(min_temp)
say("Overriding temperature to required temp.")
reagents.chem_temp = reaction.is_cold_recipe ? reaction.required_temp - 1 : reaction.required_temp + 1
say("Reacting <span class='nicegreen'>[cached_reactions[index]]</span> starting pH: [reagents.ph] index [index] of [cached_reactions.len]")
/obj/machinery/chem_recipe_debug/ui_data(mob/user)
var/data = list()
data["targetTemp"] = force_temp
data["targatpH"] = force_ph
data["isActive"] = reagents.is_reacting
data["forcepH"] = should_force_ph
data["forceTemp"] = should_force_temp
data["targetVol"] = vol_multiplier
data["processAll"] = process_all
data["currentTemp"] = reagents.chem_temp
data["currentpH"] = round(reagents.ph, 0.01)
data["processing"] = processing
data["index"] = index
data["endIndex"] = cached_reactions.len
data["beakerSpawn"] = beaker_spawn
data["minTemp"] = min_temp
var/list/beaker_contents = list()
for(var/datum/reagent/reagent as anything in reagents.reagent_list)
beaker_contents.len++
beaker_contents[length(beaker_contents)] = list("name" = reagent.name, "volume" = round(reagent.volume, 0.01), "purity" = round(reagent.purity))
data["chamberContents"] = beaker_contents
var/list/queued_reactions = list()
for(var/datum/chemical_reaction/reaction as anything in reaction_names)
var/datum/reagent/reagent = find_reagent_object_from_type(reaction.results[1])
queued_reactions.len++
queued_reactions[length(queued_reactions)] = list("name" = reagent.name)
data["queuedReactions"] = queued_reactions
var/list/active_reactions = list()
var/flashing = DISABLE_FLASHING //for use with alertAfter - since there is no alertBefore, I set the after to 0 if true, or to the max value if false
for(var/datum/equilibrium/equilibrium as anything in reagents.reaction_list)
if(!length(reagents.reaction_list))//I'm not sure why when it explodes it causes the gui to fail (it's missing danger (?) )
stack_trace("Chem debug managed to find an equilibrium in a location where there should be none (skipping this entry and continuing). This is usually because of an ill timed explosion.")
continue
if(!equilibrium.reaction.results)//Incase of no result reactions
continue
var/datum/reagent/reagent = reagents.get_reagent(equilibrium.reaction.results[1]) //Reactions are named after their primary products
if(!reagent)
continue
var/overheat = FALSE
var/danger = FALSE
var/purity_alert = 2 //same as flashing
if(reagent.purity < equilibrium.reaction.purity_min)
purity_alert = ENABLE_FLASHING//Because 0 is seen as null
danger = TRUE
if(flashing != ENABLE_FLASHING)//So that the pH meter flashes for ANY reactions out of optimal
if(equilibrium.reaction.optimal_ph_min > reagents.ph || equilibrium.reaction.optimal_ph_max < reagents.ph)
flashing = ENABLE_FLASHING
if(equilibrium.reaction.is_cold_recipe)
if(equilibrium.reaction.overheat_temp > reagents.chem_temp && equilibrium.reaction.overheat_temp != NO_OVERHEAT)
danger = TRUE
overheat = TRUE
else
if(equilibrium.reaction.overheat_temp < reagents.chem_temp)
danger = TRUE
overheat = TRUE
if(equilibrium.reaction.reaction_flags & REACTION_COMPETITIVE) //We have a compeitive reaction - concatenate the results for the different reactions
for(var/entry in active_reactions)
if(entry["name"] == reagent.name) //If we have multiple reaction methods for the same result - combine them
entry["reactedVol"] = equilibrium.reacted_vol
entry["targetVol"] = round(equilibrium.target_vol, 1)//Use the first result reagent to name the reaction detected
entry["quality"] = (entry["quality"] + equilibrium.reaction_quality) /2
continue
active_reactions.len++
active_reactions[length(active_reactions)] = list("name" = reagent.name, "danger" = danger, "purityAlert" = purity_alert, "quality" = equilibrium.reaction_quality, "overheat" = overheat, "inverse" = reagent.inverse_chem_val, "minPure" = equilibrium.reaction.purity_min, "reactedVol" = equilibrium.reacted_vol, "targetVol" = round(equilibrium.target_vol, 1))//Use the first result reagent to name the reaction detected
data["activeReactions"] = active_reactions
data["isFlashing"] = flashing
return data
/obj/machinery/chem_recipe_debug/ui_act(action, params)
. = ..()
if(.)
return
switch(action)
if("power")
return
if("temperature")
var/target = params["target"]
if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
force_temp = clamp(target, 0, 1000)
if("pH")
var/target = params["target"]
if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
force_ph = target
if("forceTemp")
should_force_temp = ! should_force_temp
. = TRUE
if("forcepH")
should_force_ph = ! should_force_ph
. = TRUE
if("react")
react = TRUE
return TRUE
if("all")
process_all = !process_all
return TRUE
if("beakerSpawn")
beaker_spawn = !beaker_spawn
return TRUE
if("setTargetList")
var/text = stripped_input(usr,"List","Enter a list of Recipe product names separated by commas", "Recipe", MAX_MESSAGE_LEN)
reaction_names = list()
if(!text)
say("Could not find reaction")
var/list/names = splittext("[text]", ",")
for(var/name in names)
var/datum/reagent/reagent = find_reagent_object_from_type(get_chem_id(name))
if(!reagent)
say("Could not find [name]")
continue
var/datum/chemical_reaction/reaction = GLOB.chemical_reactions_list_product_index[reagent.type]
if(!reaction)
say("Could not find [name] reaction!")
continue
reaction_names += reaction
if("vol")
var/target = params["target"]
if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
vol_multiplier = clamp(target, 1, 200)
if("start")
if(processing)
say("currently processing reaction [index]: [cached_reactions[index]] of [cached_reactions.len]")
return
say("Starting processing")
index = 1
setup_reactions()
begin_processing()
return TRUE
if("stop")
relay_all_reactions()
if("minTemp")
min_temp = !min_temp
/obj/machinery/chem_recipe_debug/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ChemRecipeDebug", name)
ui.open()
///Moves a type of buffer from the heater to the beaker,
/obj/machinery/chem_recipe_debug/ui_status(mob/user)
return UI_INTERACTIVE
/obj/machinery/chem_recipe_debug/ui_state(mob/user)
return GLOB.physical_state
@@ -11,6 +11,8 @@
var/static/list/shortcuts = list(
"meth" = /datum/reagent/drug/methamphetamine
)
///The purity of the created reagent in % (purity uses 0-1 values)
var/purity = 100
/obj/machinery/chem_dispenser/chem_synthesizer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -39,7 +41,7 @@
return
else if(!beaker.reagents && !QDELETED(beaker))
beaker.create_reagents(beaker.volume)
beaker.reagents.add_reagent(input_reagent, amount)
beaker.reagents.add_reagent(input_reagent, amount, added_purity = (purity/100))
if("makecup")
if(beaker)
return
@@ -49,8 +51,17 @@
var/input = text2num(params["amount"])
if(input)
amount = input
if("purity")
var/input = text2num(params["amount"])
if(input)
purity = input
update_appearance()
/obj/machinery/chem_dispenser/chem_synthesizer/ui_data(mob/user)
. = ..()
.["purity"] = purity
return .
/obj/machinery/chem_dispenser/chem_synthesizer/proc/find_reagent(input)
. = FALSE
if(GLOB.chemical_reagents_list[input]) //prefer IDs!
+18 -1
View File
@@ -84,7 +84,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
/// If the impurity is below 0.5, replace ALL of the chem with inverse_chem upon metabolising
var/inverse_chem_val = 0.25
/// What chem is metabolised when purity is below inverse_chem_val
var/inverse_chem = /datum/reagent/impurity/toxic
var/inverse_chem = /datum/reagent/inverse
///what chem is made at the end of a reaction IF the purity is below the recipies purity_min at the END of a reaction only
var/failed_chem = /datum/reagent/consumable/failed_reaction
///Thermodynamic vars
@@ -160,6 +160,7 @@ Primarily used in reagents/reaction_agents
/// Called when this reagent is first added to a mob
/datum/reagent/proc/on_mob_add(mob/living/L, amount)
overdose_threshold /= max(normalise_creation_purity(), 1) //Maybe??? Seems like it would help pure chems be even better but, if I normalised this to 1, then everything would take a 25% reduction
return
/// Called when this reagent is removed while inside a mob
@@ -227,6 +228,20 @@ Primarily used in reagents/reaction_agents
/datum/reagent/proc/get_taste_description(mob/living/taster)
return list("[taste_description]" = 1)
/**
* Used when you want the default reagents purity to be equal to the normal effects
* (i.e. if default purity is 0.75, and your reacted purity is 1, then it will return 1.33)
*
* Arguments
* * normalise_num_to - what number/purity value you're normalising to. If blank it will default to the compile value of purity for this chem
* * creation_purity - creation_purity override, if desired. This is the purity of the reagent that you're normalising from.
*/
/datum/reagent/proc/normalise_creation_purity(normalise_num_to, creation_purity)
if(!normalise_num_to)
normalise_num_to = initial(purity)
if(!creation_purity)
creation_purity = src.creation_purity
return creation_purity / normalise_num_to
/proc/pretty_string_from_reagent_list(list/reagent_list)
//Convert reagent list to a printable string for logging etc
@@ -235,3 +250,5 @@ Primarily used in reagents/reaction_agents
rs += "[R.name], [R.volume]"
return rs.Join(" | ")
@@ -2,6 +2,14 @@
/datum/reagent/medicine/c2
harmful = TRUE
metabolization_rate = 0.5 * REAGENTS_METABOLISM
impure_chem = null //Very few of these have impure effects, they're all baked in by creation_purity
inverse_chem = null //Some of these use inverse chems - we're just defining them all to null here to avoid repetition, eventually this will be moved up to parent
creation_purity = REAGENT_STANDARD_PUIRTY//All sources by default are 0.75 - reactions are primed to resolve to roughly the same with no intervention for these.
purity = REAGENT_STANDARD_PUIRTY
inverse_chem_val = 0
inverse_chem = null
failed_chem = /datum/reagent/impurity/healing/medicine_failure
chemical_flags = REAGENT_SPLITRETAINVOL
/******BRUTE******/
/*Suffix: -bital*/
@@ -11,15 +19,19 @@
description = "Named after the norse goddess Hel, this medicine heals the patient's bruises the closer they are to death. Patients will find the medicine 'aids' their healing if not near death by causing asphyxiation."
color = "#9400D3"
taste_description = "cold and lifeless"
ph = 8
overdose_threshold = 35
reagent_state = SOLID
inverse_chem_val = 0.3
inverse_chem = /datum/reagent/inverse/helgrasp
failed_chem = null
var/helbent = FALSE
var/reaping = FALSE
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/helbital/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
. = TRUE
var/death_is_coming = (M.getToxLoss() + M.getOxyLoss() + M.getFireLoss() + M.getBruteLoss())
var/death_is_coming = (M.getToxLoss() + M.getOxyLoss() + M.getFireLoss() + M.getBruteLoss())*normalise_creation_purity()
var/thou_shall_heal = 0
var/good_kind_of_healing = FALSE
switch(M.stat)
@@ -83,13 +95,15 @@
name = "Libital"
description = "A bruise reliever. Does minor liver damage."
color = "#ECEC8D" // rgb: 236 236 141
ph = 8.2
taste_description = "bitter with a hint of alcohol"
reagent_state = SOLID
impure_chem = /datum/reagent/impurity/libitoil
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/libital/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.3 * REM * delta_time)
M.adjustBruteLoss(-3 * REM * delta_time)
M.adjustBruteLoss(-3 * REM * normalise_creation_purity() * delta_time)
..()
return TRUE
@@ -98,11 +112,15 @@
description = "Originally developed as a prototype-gym supliment for those looking for quick workout turnover, this oral medication quickly repairs broken muscle tissue but causes lactic acid buildup, tiring the patient. Overdosing can cause extreme drowsiness. An Influx of nutrients promotes the muscle repair even further."
reagent_state = SOLID
color = "#FFFF6B"
ph = 5.5
overdose_threshold = 20
inverse_chem_val = 0.5//Though it's tough to get
inverse_chem = /datum/reagent/medicine/metafactor //Seems thematically intact
failed_chem = /datum/reagent/impurity/probital_failed
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/probital/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjustBruteLoss(-2.25 * REM * delta_time, FALSE)
M.adjustBruteLoss(-2.25 * REM * normalise_creation_purity() * delta_time, FALSE)
var/ooo_youaregettingsleepy = 3.5
switch(round(M.getStaminaLoss()))
if(10 to 40)
@@ -142,35 +160,32 @@
description = "Used to treat burns. Makes you move slower while it is in your system. Applies stomach damage when it leaves your system."
reagent_state = LIQUID
color = "#6171FF"
var/resetting_probability = 0
ph = 4.7
impure_chem = /datum/reagent/impurity/lentslurri
failed_chem = /datum/reagent/inverse/ichiyuri //I do hope cobby won't take this personally
var/resetting_probability = 0 //What are these for?? Can I remove them?
var/spammer = 0
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/lenturi/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjustFireLoss(-3 * REM * delta_time)
M.adjustFireLoss(-3 * REM * normalise_creation_purity() * delta_time)
M.adjustOrganLoss(ORGAN_SLOT_STOMACH, 0.4 * REM * delta_time)
..()
return TRUE
/datum/reagent/medicine/c2/lenturi/on_mob_metabolize(mob/living/carbon/M)
M.add_movespeed_modifier(/datum/movespeed_modifier/reagent/lenturi)
return ..()
/datum/reagent/medicine/c2/lenturi/on_mob_end_metabolize(mob/living/carbon/M)
M.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/lenturi)
return ..()
/datum/reagent/medicine/c2/aiuri
name = "Aiuri"
description = "Used to treat burns. Does minor eye damage."
reagent_state = LIQUID
color = "#8C93FF"
var/resetting_probability = 0
ph = 4
impure_chem = /datum/reagent/impurity/aiuri //blurriness
var/resetting_probability = 0 //same with this? Old legacy vars that should be removed?
var/message_cd = 0
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/aiuri/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjustFireLoss(-2 * REM * delta_time)
M.adjustFireLoss(-2 * REM * normalise_creation_purity() * delta_time)
M.adjustOrganLoss(ORGAN_SLOT_EYES, 0.25 * REM * delta_time)
..()
return TRUE
@@ -182,13 +197,16 @@
color = "#F7FFA5"
overdose_threshold = 25
reagent_weight = 0.6
ph = 8.9
inverse_chem = /datum/reagent/inverse/hercuri
inverse_chem_val = 0.3
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/hercuri/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
if(M.getFireLoss() > 50)
M.adjustFireLoss(-2 * REM * delta_time, FALSE)
M.adjustFireLoss(-2 * REM * delta_time * normalise_creation_purity(), FALSE)
else
M.adjustFireLoss(-1.25 * REM * delta_time, FALSE)
M.adjustFireLoss(-1.25 * REM * delta_time * normalise_creation_purity(), FALSE)
M.adjust_bodytemperature(rand(-25,-5) * TEMPERATURE_DAMAGE_COEFFICIENT * REM * delta_time, 50)
if(ishuman(M))
var/mob/living/carbon/human/humi = M
@@ -226,13 +244,16 @@
reagent_state = LIQUID
color = "#FF6464"
overdose_threshold = 35 // at least 2 full syringes +some, this stuff is nasty if left in for long
ph = 5.6
inverse_chem_val = 0.4
inverse_chem = /datum/reagent/inverse/healing/convermol
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/convermol/on_mob_life(mob/living/carbon/human/M, delta_time, times_fired)
var/oxycalc = 2.5 * REM * current_cycle
if(!overdosed)
oxycalc = min(oxycalc, M.getOxyLoss() + 0.5) //if NOT overdosing, we lower our toxdamage to only the damage we actually healed with a minimum of 0.1*current_cycle. IE if we only heal 10 oxygen damage but we COULD have healed 20, we will only take toxdamage for the 10. We would take the toxdamage for the extra 10 if we were overdosing.
M.adjustOxyLoss(-oxycalc * delta_time, 0)
M.adjustOxyLoss(-oxycalc * delta_time * normalise_creation_purity(), 0)
M.adjustToxLoss(oxycalc * delta_time / CONVERMOL_RATIO, 0)
if(DT_PROB(current_cycle / 2, delta_time) && M.losebreath)
M.losebreath--
@@ -250,12 +271,16 @@
name = "Tirimol"
description = "An oxygen deprivation medication that causes fatigue. Prolonged exposure causes the patient to fall asleep once the medicine metabolizes."
color = "#FF6464"
ph = 5.6
inverse_chem = /datum/reagent/inverse/healing/tirimol
inverse_chem_val = 0.4
/// A cooldown for spacing bursts of stamina damage
COOLDOWN_DECLARE(drowsycd)
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/tirimol/on_mob_life(mob/living/carbon/human/M, delta_time, times_fired)
M.adjustOxyLoss(-3 * REM * delta_time)
M.adjustOxyLoss(-3 * REM * delta_time * normalise_creation_purity())
M.adjustStaminaLoss(2 * REM * delta_time)
if(drowsycd && COOLDOWN_FINISHED(src, drowsycd))
M.drowsyness += 10
@@ -277,6 +302,11 @@
name = "Seiver"
description = "A medicine that shifts functionality based on temperature. Colder temperatures incurs radiation removal while hotter temperatures promote antitoxicity. Damages the heart." //CHEM HOLDER TEMPS, NOT AIR TEMPS
var/radbonustemp = (T0C - 100) //being below this number gives you 10% off rads.
inverse_chem_val = 0.3
ph = 3.7
inverse_chem = /datum/reagent/inverse/technetium
inverse_chem_val = 0.45
failed_chem = null
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/seiver/on_mob_metabolize(mob/living/carbon/human/M)
@@ -289,9 +319,9 @@
var/healypoints = 0 //5 healypoints = 1 heart damage; 5 rads = 1 tox damage healed for the purpose of healypoints
//you're hot
var/toxcalc = min(round(5 + ((chemtemp-1000)/175), 0.1), 5) * REM * delta_time //max 2.5 tox healing per second
var/toxcalc = min(round(5 + ((chemtemp-1000)/175), 0.1), 5) * REM * delta_time * normalise_creation_purity() //max 2.5 tox healing per second
if(toxcalc > 0)
M.adjustToxLoss(-toxcalc)
M.adjustToxLoss(-toxcalc * delta_time * normalise_creation_purity())
healypoints += toxcalc
//and you're cold
@@ -302,7 +332,7 @@
M.radiation = round(M.radiation * (0.75**(REM * delta_time)))
else if(chemtemp < radbonustemp)//else if you're under the chill-zone, it takes off 10% of your current rads
M.radiation = round(M.radiation * (0.90**(REM * delta_time)))
M.radiation -= radcalc
M.radiation -= radcalc * normalise_creation_purity()
healypoints += (radcalc / 5)
//you're yes and... oh no!
@@ -314,6 +344,10 @@
/datum/reagent/medicine/c2/multiver //enhanced with MULTIple medicines
name = "Multiver"
description = "A chem-purger that becomes more effective the more unique medicines present. Slightly heals toxicity but causes lung damage (mitigatable by unique medicines)."
inverse_chem = /datum/reagent/inverse/healing/monover
inverse_chem_val = 0.35
failed_chem = null //Reaction uses a special method - so we don't want this for now.
ph = 9.2
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/multiver/on_mob_life(mob/living/carbon/human/M, delta_time, times_fired)
@@ -322,7 +356,8 @@
var/datum/reagent/the_reagent = r
if(istype(the_reagent, /datum/reagent/medicine))
medibonus += 1
if(creation_purity > 1) //Perfectly pure multivers gives a bonus of 2!
medibonus += 1
M.adjustToxLoss(-0.5 * min(medibonus, 3) * REM * delta_time) //not great at healing but if you have nothing else it will work
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.5 * REM * delta_time) //kills at 40u
for(var/r2 in M.reagents.reagent_list)
@@ -330,7 +365,7 @@
if(the_reagent2 == src)
continue
var/amount2purge = 3
if(medibonus >= 3 && istype(the_reagent2, /datum/reagent/medicine)) //3 unique meds (2+multiver) will make it not purge medicines
if(medibonus >= 3 && istype(the_reagent2, /datum/reagent/medicine)) //3 unique meds (2+multiver) | (1 + pure multiver) will make it not purge medicines
continue
M.reagents.remove_reagent(the_reagent2.type, amount2purge * REM * delta_time)
..()
@@ -339,7 +374,7 @@
// Antitoxin binds plants pretty well. So the tox goes significantly down
/datum/reagent/medicine/c2/multiver/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user)
. = ..()
mytray.adjustToxic(-round(chems.get_reagent_amount(type) * 2))
mytray.adjustToxic(-(round(chems.get_reagent_amount(type) * 2)*normalise_creation_purity())) //0-2.66, 2 by default (0.75 purity).
#define issyrinormusc(A) (istype(A,/datum/reagent/medicine/c2/syriniver) || istype(A,/datum/reagent/medicine/c2/musiver)) //musc is metab of syrin so let's make sure we're not purging either
@@ -350,6 +385,8 @@
color = "#8CDF24" // heavy saturation to make the color blend better
metabolization_rate = 0.75 * REAGENTS_METABOLISM
overdose_threshold = 6
impure_chem = /datum/reagent/inverse/healing/syriniver
ph = 8.6
var/conversion_amount
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
@@ -358,11 +395,11 @@
return
var/mob/living/carbon/C = A
if(trans_volume >= 0.6) //prevents cheesing with ultralow doses.
C.adjustToxLoss(-1.5 * min(2, trans_volume) * REM, 0) //This is to promote iv pole use for that chemotherapy feel.
C.adjustToxLoss((-1.5 * min(2, trans_volume) * REM) * normalise_creation_purity(), 0) //This is to promote iv pole use for that chemotherapy feel.
var/obj/item/organ/liver/L = C.internal_organs_slot[ORGAN_SLOT_LIVER]
if((L.organ_flags & ORGAN_FAILING) || !L)
return
conversion_amount = trans_volume * (min(100 -C.getOrganLoss(ORGAN_SLOT_LIVER), 80) / 100) //the more damaged the liver the worse we metabolize.
conversion_amount = (trans_volume * (min(100 -C.getOrganLoss(ORGAN_SLOT_LIVER), 80) / 100)*normalise_creation_purity()) //the more damaged the liver the worse we metabolize.
C.reagents.remove_reagent(/datum/reagent/medicine/c2/syriniver, conversion_amount)
C.reagents.add_reagent(/datum/reagent/medicine/c2/musiver, conversion_amount)
..()
@@ -392,12 +429,13 @@
color = "#DFD54E"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
overdose_threshold = 25
ph = 9.1
var/datum/brain_trauma/mild/muscle_weakness/U
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/musiver/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.1 * REM * delta_time)
M.adjustToxLoss(-1 * REM * delta_time, 0)
M.adjustToxLoss(-1 * REM * delta_time * normalise_creation_purity(), 0)
for(var/datum/reagent/R in M.reagents.reagent_list)
if(issyrinormusc(R))
continue
@@ -429,6 +467,7 @@
description = "Heals brute and burn damage at the cost of toxicity (66% of damage healed). 100u or more can restore corpses husked by burns. Touch application only."
reagent_state = LIQUID
color = "#FFEBEB"
ph = 7.2
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/synthflesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE)
@@ -445,7 +484,7 @@
for(var/i in carbies.all_wounds)
var/datum/wound/iter_wound = i
iter_wound.on_synthflesh(reac_volume)
carbies.adjustToxLoss((harmies+burnies)*0.66)
carbies.adjustToxLoss((harmies+burnies)*(0.5 + (0.25*(1-creation_purity)))) //0.5 - 0.75
if(show_message)
to_chat(carbies, "<span class='danger'>You feel your burns and bruises healing! It stings like hell!</span>")
SEND_SIGNAL(carbies, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
@@ -470,6 +509,10 @@
description = "An expensive medicine that aids with pumping blood around the body even without a heart, and prevents the heart from slowing down. Mixing it with epinephrine or atropine will cause an explosion."
color = "#F5F5F5"
overdose_threshold = 50
ph = 12.7
inverse_chem = /datum/reagent/inverse/penthrite
inverse_chem_val = 0.25
failed_chem = null //We don't want to accidentally crash it out (see reaction)
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/c2/penthrite/on_mob_metabolize(mob/living/M)
@@ -483,7 +526,7 @@
/datum/reagent/medicine/c2/penthrite/on_mob_life(mob/living/carbon/human/H, delta_time, times_fired)
H.adjustStaminaLoss(-25 * REM) //SKYRAT EDIT ADDITION - COMBAT - makes your heart beat faster, fills you with energy. For miners
H.adjustOrganLoss(ORGAN_SLOT_STOMACH, 0.25 * REM * delta_time)
if(H.health <= HEALTH_THRESHOLD_CRIT && H.health > (H.crit_threshold + HEALTH_THRESHOLD_FULLCRIT*2)) //we cannot save someone below our lowered crit threshold.
if(H.health <= HEALTH_THRESHOLD_CRIT && H.health > (H.crit_threshold + HEALTH_THRESHOLD_FULLCRIT * (2 * normalise_creation_purity()))) //we cannot save someone below our lowered crit threshold.
H.adjustToxLoss(-2 * REM * delta_time, 0)
H.adjustBruteLoss(-2 * REM * delta_time, 0)
@@ -500,7 +543,7 @@
if(DT_PROB(18, delta_time))
to_chat(H,"<span class='danger'>Your body is trying to give up, but your heart is still beating!</span>")
if(H.health <= (H.crit_threshold + HEALTH_THRESHOLD_FULLCRIT*2)) //certain death below this threshold
if(H.health <= (H.crit_threshold + HEALTH_THRESHOLD_FULLCRIT*(2*normalise_creation_purity()))) //certain death below this threshold
REMOVE_TRAIT(H, TRAIT_STABLEHEART, type) //we have to remove the stable heart trait before we give them a heart attack
to_chat(H,"<span class='danger'>You feel something rupturing inside your chest!</span>")
H.emote("scream")
+3 -1
View File
@@ -13,7 +13,7 @@
taste_mult = 4
impure_chem = /datum/reagent/water
inverse_chem_val = 0.1
inverse_chem = /datum/reagent/water
inverse_chem = null
failed_chem = /datum/reagent/consumable/nutriment
/// How much nutrition this reagent supplies
var/nutriment_factor = 1 * REAGENTS_METABOLISM
@@ -871,6 +871,8 @@
nutriment_factor = 10 * REAGENTS_METABOLISM // 33% less than nutriment to reduce weight gain
brute_heal = 3
burn_heal = 1
inverse_chem = /datum/reagent/peptides_failed//should be impossible, but it's so it appears in the chemical lookup gui
inverse_chem_val = 0.2
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/consumable/caramel
@@ -7,27 +7,41 @@
name = "Chemical Isomers"
description = "Impure chemical isomers made from inoptimal reactions. Causes mild liver damage"
//by default, it will stay hidden on splitting, but take the name of the source on inverting. Cannot be fractioned down either if the reagent is somehow isolated.
chemical_flags = REAGENT_INVISIBLE | REAGENT_SNEAKYNAME | REAGENT_DONOTSPLIT | REAGENT_CAN_BE_SYNTHESIZED
chemical_flags = REAGENT_SNEAKYNAME | REAGENT_DONOTSPLIT | REAGENT_CAN_BE_SYNTHESIZED //impure can be synthed, and is one of the only ways to get almost pure impure
ph = 3
overdose_threshold = 0 //So that they're shown as a problem (?)
impure_chem = null
inverse_chem = null
failed_chem = null
metabolization_rate = 0.1 * REM //default impurity is 0.75, so we get 25% converted. Default metabolisation rate is 0.4, so we're 4 times slower.
var/liver_damage = 0.5
/datum/reagent/impurity/on_mob_life(mob/living/carbon/C, delta_time, times_fired)
var/obj/item/organ/liver/L = C.getorganslot(ORGAN_SLOT_LIVER)
if(!L)//Though, lets be safe
C.adjustToxLoss(1 * REM * delta_time, FALSE)//Incase of no liver!
return ..()
C.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.5 * REM * delta_time)
C.adjustOrganLoss(ORGAN_SLOT_LIVER, liver_damage * REM * delta_time)
return ..()
/datum/reagent/impurity/toxic
name = "Toxic sludge"
description = "Toxic chemical isomers made from impure reactions. Causes toxin damage"
//Basically just so people don't forget to adjust metabolization_rate
/datum/reagent/inverse
name = "Toxic monomers"
description = "Inverse reagents are created when a reagent's purity is below it's inverse threshold. The are created either during ingestion - which will then replace their associated reagent, or some can be created during the reaction process."
ph = 2
chemical_flags = REAGENT_SNEAKYNAME | REAGENT_DONOTSPLIT //Inverse generally cannot be synthed - they're difficult to get
//Mostly to be safe - but above flags will take care of this. Also prevents it from showing these on reagent lookups in the ui
impure_chem = null
inverse_chem = null
failed_chem = null
///how much this reagent does for tox damage too
var/tox_damage = 1
/datum/reagent/impurity/toxic/on_mob_life(mob/living/carbon/C, delta_time, times_fired)
C.adjustToxLoss(1 * REM * delta_time, FALSE)
/datum/reagent/inverse/on_mob_life(mob/living/carbon/C, delta_time, times_fired)
C.adjustToxLoss(tox_damage * REM * delta_time, FALSE)
return ..()
//Failed chems - generally use inverse if you want to use a impure subtype for it
//technically not a impure chem, but it's here because it can only be made with a failed impure reaction
/datum/reagent/consumable/failed_reaction
name = "Viscous sludge"
@@ -0,0 +1,521 @@
//Reagents produced by metabolising/reacting fermichems inoptimally these specifically are for medicines
//Inverse = Splitting
//Invert = Whole conversion
//Failed = End reaction below purity_min
//START SUBTYPES
//We don't want these to hide - they're helpful!
/datum/reagent/impurity/healing
name = "Healing impure reagent"
description = "Not all impure reagents are bad! Sometimes you might want to specifically make these!"
chemical_flags = REAGENT_DONOTSPLIT
addiction_types = list(/datum/addiction/medicine = 3.5)
liver_damage = 0
/datum/reagent/inverse/healing
name = "Healing inverse reagent"
description = "Not all impure reagents are bad! Sometimes you might want to specifically make these!"
chemical_flags = REAGENT_DONOTSPLIT
addiction_types = list(/datum/addiction/medicine = 3)
tox_damage = 0
// END SUBTYPES
////////////////////MEDICINES///////////////////////////
//Catch all failed reaction for medicines - supposed to be non punishing
/datum/reagent/impurity/healing/medicine_failure
name = "Insolvent medicinal precipitate"
description = "A viscous mess of various medicines. Will heal a damage type at random"
metabolization_rate = 1 * REM//This is fast
addiction_types = list(/datum/addiction/medicine = 7.5)
ph = 11
//Random healing of the 4 main groups
/datum/reagent/impurity/healing/medicine_failure/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
var/pick = pick("brute", "burn", "tox", "oxy")
switch(pick)
if("brute")
owner.adjustBruteLoss(-0.5)
if("burn")
owner.adjustFireLoss(-0.5)
if("tox")
owner.adjustToxLoss(-0.5)
if("oxy")
owner.adjustOxyLoss(-0.5)
..()
// C2 medications
// Helbital
//Inverse:
/datum/reagent/inverse/helgrasp
name = "Helgrasp"
description = "This rare and forbidden concoction is thought to bring you closer to the grasp of the Norse goddess Hel."
metabolization_rate = 1*REM //This is fast
tox_damage = 0.25
ph = 14
//Compensates for delta_time lag by spawning multiple hands at the end
var/lag_compensate = 0
//Warns you about the impenting hands
/datum/reagent/inverse/helgrasp/on_mob_add(mob/living/L, amount)
to_chat(L, "<span class='hierophant'>You hear laughter as malevolent hands apparate before you, eager to drag you down to hell...! Look out!</span>")
playsound(L.loc, 'sound/chemistry/ahaha.ogg', 80, TRUE, -1) //Very obvious tell so people can be ready
. = ..()
//Sends hands after you for your hubris
/datum/reagent/inverse/helgrasp/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
spawn_hands(owner)
lag_compensate += 1 - max(delta_time, 1)
. = ..()
/datum/reagent/inverse/helgrasp/proc/spawn_hands(mob/living/carbon/owner)
if(!owner)//Unit test has a very strange interation where hands spawned will no longer have a target causing the beam to runtime
return
//Adapted from the end of the curse - but lasts a short time
var/grab_dir = turn(owner.dir, pick(-90, 90, 180, 180)) //grab them from a random direction other than the one faced, favoring grabbing from behind
var/turf/spawn_turf = get_ranged_target_turf(owner, grab_dir, 8)//Larger range so you have more time to dodge
if(!spawn_turf)
return
new/obj/effect/temp_visual/dir_setting/curse/grasp_portal(spawn_turf, owner.dir)
playsound(spawn_turf, 'sound/effects/curse2.ogg', 80, TRUE, -1)
var/obj/projectile/curse_hand/hel/hand = new (spawn_turf)
hand.preparePixelProjectile(owner, spawn_turf)
hand.fire()
/datum/reagent/inverse/helgrasp/on_mob_delete(mob/living/owner)
var/hands = 0
while(lag_compensate > hands)
spawn_hands(owner)
hands++
. = ..()
//libital
//Impure
//Simply reduces your alcohol tolerance, kinda simular to prohol
/datum/reagent/impurity/libitoil
name = "Libitoil"
description = "Temporarilly interferes a patient's ability to process alcohol."
chemical_flags = REAGENT_DONOTSPLIT
ph = 13.5
liver_damage = 0.1
addiction_types = list(/datum/addiction/medicine = 4)
/datum/reagent/impurity/libitoil/on_mob_add(mob/living/L, amount)
. = ..()
var/mob/living/carbon/consumer = L
if(!consumer)
return
RegisterSignal(consumer, COMSIG_CARBON_LOSE_ORGAN, .proc/on_removed_organ)
var/obj/item/organ/liver/this_liver = consumer.getorganslot(ORGAN_SLOT_LIVER)
this_liver.alcohol_tolerance *= 2
/datum/reagent/impurity/libitoil/proc/on_removed_organ(mob/prev_owner, obj/item/organ/organ)
if(!istype(organ, /obj/item/organ/liver))
return
var/obj/item/organ/liver/this_liver = organ
this_liver.alcohol_tolerance /= 2
/datum/reagent/impurity/libitoil/on_mob_delete(mob/living/L)
. = ..()
var/mob/living/carbon/consumer = L
UnregisterSignal(consumer, COMSIG_CARBON_LOSE_ORGAN)
var/obj/item/organ/liver/this_liver = consumer.getorganslot(ORGAN_SLOT_LIVER)
if(!this_liver)
return
this_liver.alcohol_tolerance /= 2
//probital
/datum/reagent/impurity/probital_failed//Basically crashed out failed metafactor
name = "Metabolic Inhibition Factor"
description = "This enzyme catalyzes crashes the conversion of nutricious food into healing peptides."
metabolization_rate = 0.0625 * REAGENTS_METABOLISM //slow metabolism rate so the patient can self heal with food even after the troph has metabolized away for amazing reagent efficency.
reagent_state = SOLID
color = "#b3ff00"
overdose_threshold = 10
ph = 1
addiction_types = list(/datum/addiction/medicine = 5)
liver_damage = 0
/datum/reagent/impurity/probital_failed/overdose_start(mob/living/carbon/M)
metabolization_rate = 4 * REAGENTS_METABOLISM
..()
/datum/reagent/peptides_failed
name = "Prion peptides"
taste_description = "spearmint frosting"
description = "These inhibitory peptides cause cellular damage and cost nutrition to the patient!"
ph = 2.1
/datum/reagent/peptides_failed/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
owner.adjustCloneLoss(0.25 * delta_time)
owner.adjust_nutrition(-5 * REAGENTS_METABOLISM * delta_time)
. = ..()
//Lenturi
//impure
/datum/reagent/impurity/lentslurri //Okay maybe I should outsource names for these
name = "Lentslurri"//This is a really bad name please replace
description = "A highly addicitive muscle relaxant that is made when Lenturi reactions go wrong."
addiction_types = list(/datum/addiction/medicine = 8)
liver_damage = 0
/datum/reagent/impurity/lentslurri/on_mob_metabolize(mob/living/carbon/owner)
owner.add_movespeed_modifier(/datum/movespeed_modifier/reagent/lenturi)
return ..()
/datum/reagent/impurity/lentslurri/on_mob_end_metabolize(mob/living/carbon/owner)
owner.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/lenturi)
return ..()
//failed
/datum/reagent/inverse/ichiyuri
name = "Ichiyuri"
description = "Prolonged exposure to this chemical can cause an overwhelming urge to itch oneself."
reagent_state = LIQUID
color = "#C8A5DC"
ph = 1.7
addiction_types = list(/datum/addiction/medicine = 2.5)
tox_damage = 0.1
///Probability of scratch - increases as a function of time
var/resetting_probability = 0
///Prevents message spam
var/spammer = 0
//Just the removed itching mechanism - omage to it's origins.
/datum/reagent/inverse/ichiyuri/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
if(prob(resetting_probability) && !(HAS_TRAIT(owner, TRAIT_RESTRAINED) || owner.incapacitated()))
if(spammer < world.time)
to_chat(owner,"<span class='warning'>You can't help but itch yourself.</span>")
spammer = world.time + (10 SECONDS)
var/scab = rand(1,7)
owner.adjustBruteLoss(scab*REM)
owner.bleed(scab)
resetting_probability = 0
resetting_probability += (5*(current_cycle/10) * delta_time) // 10 iterations = >51% to itch
..()
return TRUE
//Aiuri
//impure
/datum/reagent/impurity/aiuri
name = "Aivime"
description = "This reagent is known to interfere with the eyesight of a patient."
ph = 3.1
addiction_types = list(/datum/addiction/medicine = 1.5)
liver_damage = 0.1
//blurriness at the start of taking the med
var/cached_blurriness
/datum/reagent/impurity/aiuri/on_mob_add(mob/living/owner, amount)
. = ..()
cached_blurriness = owner.eye_blurry
owner.set_blurriness(((creation_purity*10)*(volume/metabolization_rate)) + cached_blurriness)
/datum/reagent/impurity/aiuri/on_mob_delete(mob/living/owner, amount)
. = ..()
if(owner.eye_blurry <= cached_blurriness)
return
owner.set_blurriness(cached_blurriness)
//Hercuri
//inverse
/datum/reagent/inverse/hercuri
name = "Herignis"
description = "This reagent causes a dramatic raise in a patient's body temperature."
ph = 0.8
tox_damage = 0
color = "#ff1818"
taste_description = "heat! Ouch!"
addiction_types = list(/datum/addiction/medicine = 2.5)
data = list("method" = TOUCH)
///The method in which the reagent was exposed
var/method
/datum/reagent/inverse/hercuri/expose_mob(mob/living/carbon/exposed_mob, methods=VAPOR, reac_volume)
method |= methods
data["method"] |= methods
..()
/datum/reagent/inverse/hercuri/on_new(data)
method |= data["method"]
..()
/datum/reagent/inverse/hercuri/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
var/heating = rand(creation_purity * REM * 3, creation_purity * REM * 6)
if(method & INGEST)
owner.reagents?.chem_temp += heating * REM * delta_time
if(method & VAPOR)
owner.adjust_bodytemperature(heating * REM * delta_time * TEMPERATURE_DAMAGE_COEFFICIENT, 50)
if(method & INJECT)
if(!ishuman(owner))
return ..()
var/mob/living/carbon/human/human_mob = owner
human_mob.adjust_coretemperature(heating * REM * delta_time * TEMPERATURE_DAMAGE_COEFFICIENT, 50)
else
owner.adjust_fire_stacks(heating * 0.05)
..()
/datum/reagent/inverse/healing/tirimol
name = "Super Melatonin"//It's melatonin, but super!
description = "This will send the patient to sleep, adding a bonus to the efficacy of all reagents administered."
ph = 12.5 //sleeping is a basic need of all lifeformsa
self_consuming = TRUE //No pesky liver shenanigans
chemical_flags = REAGENT_DONOTSPLIT | REAGENT_DEAD_PROCESS
var/cached_reagent_list = list()
addiction_types = list(/datum/addiction/medicine = 5)
//Makes patients fall asleep, then boosts the purirty of their medicine reagents if they're asleep
/datum/reagent/inverse/healing/tirimol/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
switch(current_cycle)
if(1 to 10)//same delay as chloral hydrate
if(prob(50))
owner.emote("yawn")
if(10 to INFINITY)
owner.Sleeping(40)
. = 1
if(owner.IsSleeping())
for(var/datum/reagent/reagent as anything in owner.reagents.reagent_list)
if(reagent in cached_reagent_list)
continue
if(!istype(reagent, /datum/reagent/medicine))
continue
reagent.creation_purity *= 1.25
cached_reagent_list += reagent
else if(!owner.IsSleeping() && length(cached_reagent_list))
for(var/datum/reagent/reagent as anything in cached_reagent_list)
if(!reagent)
continue
reagent.creation_purity *= 0.8
cached_reagent_list = list()
..()
/datum/reagent/inverse/healing/tirimol/on_mob_delete(mob/living/owner)
if(owner.IsSleeping())
owner.visible_message("<span class='notice'>[icon2html(owner, viewers(DEFAULT_MESSAGE_RANGE, src))] [owner] lets out a hearty snore!</span>")//small way of letting people know the supersnooze is ended
for(var/datum/reagent/reagent as anything in cached_reagent_list)
if(!reagent)
continue
reagent.creation_purity *= 0.8
cached_reagent_list = list()
..()
//convermol
//inverse
/datum/reagent/inverse/healing/convermol
name = "Coveroli"
description = "This reagent is known to coat the inside of a patient's lungs, providing greater protection against hot or cold air."
ph = 3.82
tox_damage = 0
addiction_types = list(/datum/addiction/medicine = 2.3)
//The heat damage levels of lungs when added (i.e. heat_level_1_threshold on lungs)
var/cached_heat_level_1
var/cached_heat_level_2
var/cached_heat_level_3
//The cold damage levels of lungs when added (i.e. cold_level_1_threshold on lungs)
var/cached_cold_level_1
var/cached_cold_level_2
var/cached_cold_level_3
/datum/reagent/inverse/healing/convermol/on_mob_add(mob/living/owner, amount)
. = ..()
RegisterSignal(owner, COMSIG_CARBON_LOSE_ORGAN, .proc/on_removed_organ)
var/obj/item/organ/lungs/lungs = owner.getorganslot(ORGAN_SLOT_LUNGS)
if(!lungs)
return
cached_heat_level_1 = lungs.heat_level_1_threshold
cached_heat_level_2 = lungs.heat_level_2_threshold
cached_heat_level_3 = lungs.heat_level_3_threshold
cached_cold_level_1 = lungs.cold_level_1_threshold
cached_cold_level_2 = lungs.cold_level_2_threshold
cached_cold_level_3 = lungs.cold_level_3_threshold
//Heat threshold is increased
lungs.heat_level_1_threshold *= creation_purity * 1.5
lungs.heat_level_2_threshold *= creation_purity * 1.5
lungs.heat_level_3_threshold *= creation_purity * 1.5
//Cold threshold is decreased
lungs.cold_level_1_threshold *= creation_purity * 0.5
lungs.cold_level_2_threshold *= creation_purity * 0.5
lungs.cold_level_3_threshold *= creation_purity * 0.5
/datum/reagent/inverse/healing/convermol/proc/on_removed_organ(mob/prev_owner, obj/item/organ/organ)
if(!istype(organ, /obj/item/organ/lungs))
return
var/obj/item/organ/lungs/lungs = organ
restore_lung_levels(lungs)
/datum/reagent/inverse/healing/convermol/proc/restore_lung_levels(obj/item/organ/lungs/lungs)
lungs.heat_level_1_threshold = cached_heat_level_1
lungs.heat_level_2_threshold = cached_heat_level_2
lungs.heat_level_3_threshold = cached_heat_level_3
lungs.cold_level_1_threshold = cached_cold_level_1
lungs.cold_level_2_threshold = cached_cold_level_2
lungs.cold_level_3_threshold = cached_cold_level_3
/datum/reagent/inverse/healing/convermol/on_mob_delete(mob/living/owner)
. = ..()
UnregisterSignal(owner, COMSIG_CARBON_LOSE_ORGAN)
var/obj/item/organ/lungs/lungs = owner.getorganslot(ORGAN_SLOT_LUNGS)
if(!lungs)
return
restore_lung_levels(lungs)
//seiver
//Inverse
//Allows the scanner to detect organ health to the nearest 1% (similar use to irl) and upgrates the scan to advanced
/datum/reagent/inverse/technetium
name = "Technetium 99"
description = "A radioactive tracer agent that can improve a scanner's ability to detect internal organ damage. Will irradiate the patient when present very slowly, purging or using a low dose is recommended after use."
metabolization_rate = 0.3 * REM
chemical_flags = REAGENT_DONOTSPLIT //Do show this on scanner
tox_damage = 0
///Accumulates radiation, then adds it as a whole number to the owner
var/radiation_ticker
/datum/reagent/inverse/technetium/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
//for some reason radiation doesn't work when small
owner.radiation += creation_purity * delta_time * 0.5
..()
//Kind of a healing effect, Presumably you're using syrinver to purge so this helps that
/datum/reagent/inverse/healing/syriniver
name = "Syrinifergus"
description = "This reagent reduces the impurity of all non medicines within the patient, reducing their negative effects."
self_consuming = TRUE //No pesky liver shenanigans
chemical_flags = REAGENT_DONOTSPLIT | REAGENT_DEAD_PROCESS
///The list of reagents we've affected
var/cached_reagent_list = list()
addiction_types = list(/datum/addiction/medicine = 1.75)
/datum/reagent/inverse/healing/syriniver/on_mob_add(mob/living/living_mob)
if(!(iscarbon(living_mob)))
return ..()
var/mob/living/carbon/owner = living_mob
for(var/datum/reagent/reagent as anything in owner.reagents.reagent_list)
if(reagent in cached_reagent_list)
continue
if(istype(reagent, /datum/reagent/medicine))
continue
reagent.creation_purity *= 0.8
cached_reagent_list += reagent
..()
/datum/reagent/inverse/healing/syriniver/on_mob_delete(mob/living/living_mob)
. = ..()
if(!(iscarbon(living_mob)))
return
if(!cached_reagent_list)
return
for(var/datum/reagent/reagent as anything in cached_reagent_list)
if(!reagent)
continue
reagent.creation_purity *= 1.25
cached_reagent_list = null
//Multiver
//Inverse
//Reaction product when between 0.2 and 0.35 purity.
/datum/reagent/inverse/healing/monover
name = "Monover"
description = "A toxin treating reagent, that only is effective if it's the only reagent present in the patient."
ph = 0.5
addiction_types = list(/datum/addiction/medicine = 3.5)
//Heals toxins if it's the only thing present - kinda the oposite of multiver! Maybe that's why it's inverse!
/datum/reagent/inverse/healing/monover/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
if(length(owner.reagents.reagent_list) > 1)
owner.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.5 * delta_time) //Hey! It's everyone's favourite drawback from multiver!
return ..()
owner.adjustToxLoss(-2 * REM * creation_purity * delta_time, 0)
..()
return TRUE
///Can bring a corpse back to life temporarily (if heart is intact)
///Makes wounds bleed more, if it brought someone back, they take additional brute and heart damage
///They can't die during this, but if they're past crit then take increasing stamina damage
///If they're past fullcrit, their movement is slowed by half
///If they OD, their heart explodes (if they were brought back from the dead)
/datum/reagent/inverse/penthrite
name = "Nooartrium"
description = "A reagent that is known to stimulate the heart in a dead patient, temporarily bringing back recently dead patients at great cost to their heart."
ph = 14
metabolization_rate = 0.05 * REM
addiction_types = list(/datum/addiction/medicine = 12)
overdose_threshold = 20
self_consuming = TRUE //No pesky liver shenanigans
chemical_flags = REAGENT_DONOTSPLIT | REAGENT_DEAD_PROCESS
///If we brought someone back from the dead
var/back_from_the_dead = FALSE
/datum/reagent/inverse/penthrite/on_mob_dead(mob/living/carbon/owner)
var/obj/item/organ/heart/heart = owner.getorganslot(ORGAN_SLOT_HEART)
if(!heart || heart.organ_flags & ORGAN_FAILING)
return ..()
metabolization_rate = 0.35
ADD_TRAIT(owner, TRAIT_STABLEHEART, type)
ADD_TRAIT(owner, TRAIT_NOHARDCRIT, type)
ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, type)
ADD_TRAIT(owner, TRAIT_NOCRITDAMAGE, type)
ADD_TRAIT(owner, TRAIT_NODEATH, type)
owner.set_stat(CONSCIOUS) //This doesn't touch knocked out
owner.updatehealth()
REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, STAT_TRAIT)
REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT) //Because these are normally updated using set_health() - but we don't want to adjust health, and the addition of NOHARDCRIT blocks it being added after, but doesn't remove it if it was added before
owner.set_resting(FALSE)//Please get up, no one wants a deaththrows juggernaught that lies on the floor all the time
owner.SetAllImmobility(0)
back_from_the_dead = TRUE
owner.emote("gasp")
owner.playsound_local(owner, 'sound/health/fastbeat.ogg', 65)
..()
/datum/reagent/inverse/penthrite/on_mob_life(mob/living/carbon/owner, delta_time, times_fired)
if(!back_from_the_dead)
return ..()
REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, CRIT_HEALTH_TRAIT)
//Following is for those brought back from the dead only
for(var/datum/wound/iter_wound as anything in owner.all_wounds)
iter_wound.blood_flow += (1-creation_purity)
owner.adjustBruteLoss(5 * (1-creation_purity) * delta_time)
owner.adjustOrganLoss(ORGAN_SLOT_HEART, (1 + (1-creation_purity)) * delta_time)
if(owner.health < HEALTH_THRESHOLD_CRIT)
owner.add_movespeed_modifier(/datum/movespeed_modifier/reagent/nooartrium)
if(owner.health < HEALTH_THRESHOLD_FULLCRIT)
owner.add_actionspeed_modifier(/datum/actionspeed_modifier/nooartrium)
var/obj/item/organ/heart/heart = owner.getorganslot(ORGAN_SLOT_HEART)
if(!heart || heart.organ_flags & ORGAN_FAILING)
remove_buffs(owner)
..()
/datum/reagent/inverse/penthrite/on_mob_delete(mob/living/carbon/owner)
remove_buffs(owner)
var/obj/item/organ/heart/heart = owner.getorganslot(ORGAN_SLOT_HEART)
if(owner.health < -500 || heart.organ_flags & ORGAN_FAILING)//Honestly commendable if you get -500
explosion(owner, 0, 0, 1)
qdel(heart)
owner.visible_message("<span class='boldwarning'>[owner]'s heart explodes!</span>")
return ..()
/datum/reagent/inverse/penthrite/overdose_start(mob/living/carbon/owner)
if(!back_from_the_dead)
return ..()
var/obj/item/organ/heart/heart = owner.getorganslot(ORGAN_SLOT_HEART)
if(!heart) //No heart? No life!
REMOVE_TRAIT(owner, TRAIT_NODEATH, type)
owner.stat = DEAD
return ..()
explosion(owner, 0, 0, 1)
qdel(heart)
owner.visible_message("<span class='boldwarning'>[owner]'s heart explodes!</span>")
return..()
/datum/reagent/inverse/penthrite/proc/remove_buffs(mob/living/carbon/owner)
REMOVE_TRAIT(owner, TRAIT_STABLEHEART, type)
REMOVE_TRAIT(owner, TRAIT_NOHARDCRIT, type)
REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, type)
REMOVE_TRAIT(owner, TRAIT_NOCRITDAMAGE, type)
REMOVE_TRAIT(owner, TRAIT_NODEATH, type)
owner.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/nooartrium)
owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/nooartrium)
@@ -870,7 +870,6 @@
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
addiction_types = list(/datum/addiction/stimulants = 4) //0.8 per 2 seconds
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants)
@@ -1267,6 +1266,8 @@
reagent_state = SOLID
color = "#FFBE00"
overdose_threshold = 10
inverse_chem_val = 0.1 //Shouldn't happen - but this is so looking up the chem will point to the failed type
inverse_chem = /datum/reagent/impurity/probital_failed
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
/datum/reagent/medicine/metafactor/overdose_start(mob/living/carbon/M)
+171 -43
View File
@@ -143,6 +143,8 @@
* * reagent - the target reagent to convert
*/
/datum/chemical_reaction/proc/convert_into_failed(datum/reagent/reagent, datum/reagents/holder)
if(!reagent.failed_chem)
return
if(reagent.purity < purity_min)
var/cached_volume = reagent.volume
holder.remove_reagent(reagent.type, cached_volume, FALSE)
@@ -164,17 +166,19 @@
return
var/cached_volume = reagent.volume
var/cached_purity = reagent.purity
if((reaction_flags & REACTION_CLEAR_INVERSE) && reagent.inverse_chem)
if(reagent.inverse_chem_val > reagent.purity)
holder.remove_reagent(reagent.type, cached_volume, FALSE)
holder.add_reagent(reagent.inverse_chem, cached_volume, FALSE, added_purity = 1)
holder.add_reagent(reagent.inverse_chem, cached_volume, FALSE, added_purity = 1-cached_purity)
return
if((reaction_flags & REACTION_CLEAR_IMPURE) && reagent.impure_chem)
var/impureVol = cached_volume * (1 - reagent.purity)
holder.remove_reagent(reagent.type, (impureVol), FALSE)
holder.add_reagent(reagent.impure_chem, impureVol, FALSE, added_purity = 1)
reagent.creation_purity = reagent.purity
reagent.purity = 1
holder.add_reagent(reagent.impure_chem, impureVol, FALSE, added_purity = 1-cached_purity)
reagent.creation_purity = cached_purity
reagent.chemical_flags = reagent.chemical_flags | REAGENT_DONOTSPLIT
/**
* Occurs when a reation is overheated (i.e. past it's overheatTemp)
@@ -187,7 +191,7 @@
* * holder - the datum that holds this reagent, be it a beaker or anything else
* * equilibrium - the equilibrium datum that contains the equilibrium reaction properties and methods
*/
/datum/chemical_reaction/proc/overheated(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/proc/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
for(var/id in results)
var/datum/reagent/reagent = holder.get_reagent(id)
if(!reagent)
@@ -205,7 +209,7 @@
* * holder - the datum that holds this reagent, be it a beaker or anything else
* * equilibrium - the equilibrium datum that contains the equilibrium reaction properties and methods
*/
/datum/chemical_reaction/proc/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/proc/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
var/affected_list = results + required_reagents
for(var/_reagent in affected_list)
var/datum/reagent/reagent = holder.get_reagent(_reagent)
@@ -295,7 +299,7 @@
//Spews out the inverse of the chems in the beaker of the products/reactants only
/datum/chemical_reaction/proc/explode_invert_smoke(datum/reagents/holder, datum/equilibrium/equilibrium, clear_products = TRUE, clear_reactants = TRUE)
/datum/chemical_reaction/proc/explode_invert_smoke(datum/reagents/holder, datum/equilibrium/equilibrium, force_range = 0, clear_products = TRUE, clear_reactants = TRUE, accept_impure = TRUE)
var/datum/reagents/invert_reagents = new (2100, NO_REACT)//I think the biggest size we can get is 2100?
var/datum/effect_system/smoke_spread/chem/smoke = new()
var/sum_volume = 0
@@ -307,11 +311,17 @@
invert_reagents.add_reagent(reagent.inverse_chem, reagent.volume, no_react = TRUE)
holder.remove_reagent(reagent.type, reagent.volume)
continue
else if (reagent.impure_chem && accept_impure)
invert_reagents.add_reagent(reagent.impure_chem, reagent.volume, no_react = TRUE)
holder.remove_reagent(reagent.type, reagent.volume)
continue
invert_reagents.add_reagent(reagent.type, reagent.volume, added_purity = reagent.purity, no_react = TRUE)
sum_volume += reagent.volume
holder.remove_reagent(reagent.type, reagent.volume)
if(!force_range)
force_range = sum_volume/5
if(invert_reagents.reagent_list)
smoke.set_up(invert_reagents, (sum_volume/5), holder.my_atom)
smoke.set_up(invert_reagents, force_range, holder.my_atom)
smoke.start()
holder.my_atom.audible_message("The [holder.my_atom] suddenly explodes, launching the aerosolized reagents into the air!")
if(clear_reactants)
@@ -339,56 +349,174 @@
clear_products(holder)
//Pushes everything out, and damages mobs with 10 brute damage.
/datum/chemical_reaction/proc/explode_shockwave(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/proc/explode_shockwave(datum/reagents/holder, datum/equilibrium/equilibrium, range = 3, damage = 5, sound_and_text = TRUE, implosion = FALSE)
var/turf/this_turf = get_turf(holder.my_atom)
holder.my_atom.audible_message("The [holder.my_atom] suddenly explodes, sending a shockwave rippling through the air!")
playsound(this_turf, 'sound/chemistry/shockwave_explosion.ogg', 80, TRUE)
if(sound_and_text)
holder.my_atom.audible_message("The [holder.my_atom] suddenly explodes, sending a shockwave rippling through the air!")
playsound(this_turf, 'sound/chemistry/shockwave_explosion.ogg', 80, TRUE)
//Modified goonvortex
for(var/atom/movable/movey in orange(3, this_turf))
if(isliving(movey))
for(var/atom/movable/movey as anything in orange(range, this_turf))
if(!istype(movey, /atom/movable))
continue
if(isliving(movey) && damage)
var/mob/living/live = movey
live.apply_damage(5)//Since this can be called multiple times
live.apply_damage(damage)//Since this can be called multiple times
if(movey.anchored)
continue
if(iseffect(movey) || iscameramob(movey) || isdead(movey))
continue
var/distance = get_dist(movey, this_turf)
var/moving_power = max(4 - distance, 1)//Make sure we're thrown out of range of the next one
var/atom/throw_target = get_edge_target_turf(movey, get_dir(movey, get_step_away(movey, this_turf)))
movey.throw_at(throw_target, moving_power, 1)
if(implosion)
var/distance = get_dist(movey, this_turf)
var/moving_power = max(4 - distance, 1)
var/turf/target = get_turf(holder.my_atom)
movey.throw_at(target, moving_power, 1)
else
var/distance = get_dist(movey, this_turf)
var/moving_power = max(3 - distance, 1)//Make sure we're thrown out of range of the next one
var/atom/throw_target = get_edge_target_turf(movey, get_dir(movey, get_step_away(movey, this_turf)))
movey.throw_at(throw_target, moving_power, 1)
//Creates a ring of fire in a set range around the beaker location
/datum/chemical_reaction/proc/explode_fire(datum/reagents/holder, datum/equilibrium/equilibrium, range)
explosion(holder.my_atom, 0, 0, 0, 0, flame_range = 3)
////////BEGIN FIRE BASED EXPLOSIONS
//Calls the default explosion subsystem handiler to explode with fire (random firespots and noise)
/datum/chemical_reaction/proc/explode_fire(datum/reagents/holder, datum/equilibrium/equilibrium, range = 3)
explosion(holder.my_atom, 0, 0, 0, 0, flame_range = range)
holder.my_atom.audible_message("The [holder.my_atom] suddenly errupts in flames!")
//Clears the beaker of the reagents only
/datum/chemical_reaction/proc/clear_reactants(datum/reagents/holder, volume = null)
if(!holder)
return FALSE
for(var/datum/reagent/reagent as anything in holder.reagent_list)
if(!(reagent.type in required_reagents))
continue
if(!volume)
holder.remove_reagent(reagent.type, reagent.volume)
//Creates a ring of fire in a set range around the beaker location
/datum/chemical_reaction/proc/explode_fire_vortex(datum/reagents/holder, datum/equilibrium/equilibrium, x_offset = 1, y_offset = 1, reverse = FALSE, id = "f_vortex", )
var/increment = reverse ? -1 : 1
if(isnull(equilibrium.data["[id]_tar"]))
equilibrium.data = list("[id]_x" = x_offset, "[id]_y" = y_offset, "[id]_tar" = "[id]_y")//tar is the current movement direction the cyclone is moving in
if(equilibrium.data["[id]_tar"] == "[id]_x")
if(equilibrium.data["[id]_x"] >= x_offset)
equilibrium.data["[id]_tar"] = "[id]_y"
equilibrium.data["[id]_y"] += increment
else if(equilibrium.data["[id]_x"] <= -x_offset)
equilibrium.data["[id]_tar"] = "[id]_y"
equilibrium.data["[id]_y"] -= increment
else
holder.remove_reagent(reagent.type, volume)
if(equilibrium.data["[id]_y"] < 0)
equilibrium.data["[id]_x"] += increment
else if(equilibrium.data["[id]_y"] > 0)
equilibrium.data["[id]_x"] -= increment
//Clears the beaker of the product only
/datum/chemical_reaction/proc/clear_products(datum/reagents/holder, volume = null)
if(!holder)
return FALSE
for(var/datum/reagent/reagent as anything in holder.reagent_list)
if(!(reagent.type in results))
continue
if(!volume)
holder.remove_reagent(reagent.type, reagent.volume)
else if (equilibrium.data["[id]_tar"] == "[id]_y")
if(equilibrium.data["[id]_y"] >= y_offset)
equilibrium.data["[id]_tar"] = "[id]_x"
equilibrium.data["[id]_x"] -= increment
else if(equilibrium.data["[id]_y"] <= -y_offset)
equilibrium.data["[id]_tar"] = "[id]_x"
equilibrium.data["[id]_x"] += increment
else
holder.remove_reagent(reagent.type, volume)
if(equilibrium.data["[id]_x"] < 0)
equilibrium.data["[id]_y"] -= increment
else if(equilibrium.data["[id]_x"] > 0)
equilibrium.data["[id]_y"] += increment
var/turf/holder_turf = get_turf(holder.my_atom)
var/turf/target = locate(holder_turf.x + equilibrium.data["[id]_x"], holder_turf.y + equilibrium.data["[id]_y"], holder_turf.z)
new /obj/effect/hotspot(target)
debug_world("X: [equilibrium.data["[id]_x"]], Y: [equilibrium.data["[id]_x"]]")
//Clears the beaker of ALL reagents inside
/datum/chemical_reaction/proc/clear_reagents(datum/reagents/holder, volume = null)
/*
* Creates a square of fire in a fire_range radius,
* fire_range = 0 will be on the exact spot of the holder,
* fire_range = 1 or more will be additional tiles around the holder. Every tile will be heated this way.
* How clf3 works, you know!
*/
/datum/chemical_reaction/proc/explode_fire_square(datum/reagents/holder, datum/equilibrium/equilibrium, fire_range = 1)
var/turf/location = get_turf(holder.my_atom)
if(fire_range == 0)
new /obj/effect/hotspot(location)
return
for(var/turf/turf as anything in range(fire_range, location))
new /obj/effect/hotspot(turf)
///////////END FIRE BASED EXPLOSIONS
/*
* Freezes in a circle around the holder location
* Arguments:
* * temp - the temperature to set the air to
* * radius - the range of the effect
* * freeze_duration - how long the icey spots remain for
*/
/datum/chemical_reaction/proc/freeze_radius(datum/reagents/holder, datum/equilibrium/equilibrium, temp, radius = 2, freeze_duration = 50)
for(var/any_turf in circlerangeturfs(center = get_turf(holder.my_atom), radius = radius))
if(!istype(any_turf, /turf/open))
continue
var/turf/open/open_turf = any_turf
open_turf.MakeSlippery(TURF_WET_PERMAFROST, 10, freeze_duration, freeze_duration)
open_turf.temperature = temp
///Clears the beaker of the reagents only
///if volume is not set, it will remove all of the reactant
/datum/chemical_reaction/proc/clear_reactants(datum/reagents/holder, volume = 1000)
if(!holder)
return FALSE
for(var/reagent in required_reagents)
holder.remove_reagent(reagent, volume)
///Clears the beaker of the product only
/datum/chemical_reaction/proc/clear_products(datum/reagents/holder, volume = 1000)
if(!holder)
return FALSE
for(var/reagent in results)
holder.remove_reagent(reagent, volume)
///Clears the beaker of ALL reagents inside
/datum/chemical_reaction/proc/clear_reagents(datum/reagents/holder, volume = 1000)
if(!holder)
return FALSE
if(!volume)
volume = holder.total_volume
holder.remove_all(volume)
/*
* "Attacks" all mobs within range with a specified reagent
* Will be blocked if they're wearing proper protective equipment unless disabled
* Arguments
* * reagent - the reagent typepath that will be added
* * vol - how much will be added
* * range - the range that this will affect mobs for
* * ignore_mask - if masks block the effect, making this true will affect someone regardless
* * ignore_eyes - if glasses block the effect, making this true will affect someone regardless
*/
/datum/chemical_reaction/proc/explode_attack_chem(datum/reagents/holder, datum/equilibrium/equilibrium, reagent, vol, range = 3, ignore_mask = FALSE, ignore_eyes = FALSE)
if(istype(reagent, /datum/reagent))
var/datum/reagent/temp_reagent = reagent
reagent = temp_reagent.type
for(var/mob/living/carbon/target in orange(range, get_turf(holder.my_atom)))
if(target.has_smoke_protection() && !ignore_mask)
continue
if(target.get_eye_protection() && !ignore_eyes)
continue
to_chat(target, "The [holder.my_atom.name] launches some of [holder.p_their()] contents at you!")
target.reagents.add_reagent(reagent, vol)
/*
* Applys a cooldown to the reaction
* Returns false if time is below required, true if it's above required
* Time is kept in eqilibrium data
*
* Arguments:
* * seconds - the amount of time in server seconds to delay between true returns, will ceiling to the nearest 0.25
* * id - a string phrase so that multiple cooldowns can be applied if needed
* * initial_delay - The number of seconds of delay to add on creation
*/
/datum/chemical_reaction/proc/off_cooldown(datum/reagents/holder, datum/equilibrium/equilibrium, seconds = 1, id = "default", initial_delay = 0)
id = id+"_cooldown"
if(isnull(equilibrium.data[id]))
equilibrium.data[id] = 0
if(initial_delay)
equilibrium.data[id] += initial_delay
return FALSE
return TRUE//first time we know we can go
equilibrium.data[id] += equilibrium.time_deficit ? 0.5 : 0.25 //sync to lag compensator
if(equilibrium.data[id] >= seconds)
equilibrium.data[id] = 0
return TRUE
return FALSE
@@ -1,79 +1,369 @@
/*****BRUTE*****/
//oops no theme - standard reactions with no whistles
/datum/chemical_reaction/medicine/helbital
results = list(/datum/reagent/medicine/c2/helbital = 3)
required_reagents = list(/datum/reagent/consumable/sugar = 1, /datum/reagent/fluorine = 1, /datum/reagent/carbon = 1)
mix_message = "The mixture turns into a thick, yellow powder."
//FermiChem vars:
required_temp = 250
optimal_temp = 1000
overheat_temp = 550
optimal_ph_min = 5
optimal_ph_max = 9.5
determin_ph_range = 4
temp_exponent_factor = 1
ph_exponent_factor = 4
thermic_constant = 100
H_ion_release = 4
rate_up_lim = 55
purity_min = 0.55
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BRUTE
/datum/chemical_reaction/medicine/helbital/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
explode_fire_vortex(holder, equilibrium, 1, 1, "impure")
holder.chem_temp += 2.5
var/datum/reagent/helbital = holder.get_reagent(/datum/reagent/medicine/c2/helbital)
if(!helbital)
return
if(helbital.purity <= 0.25)
if(prob(25))
new /obj/effect/hotspot(holder.my_atom.loc)
holder.remove_reagent(/datum/reagent/medicine/c2/helbital, 2)
holder.chem_temp += 5
holder.my_atom.audible_message("<span class='notice'>[icon2html(holder.my_atom, viewers(DEFAULT_MESSAGE_RANGE, src))] The impurity of the reacting helbital is too great causing the [src] to let out a hearty burst of flame, evaporating part of the product!</span>")
/datum/chemical_reaction/medicine/helbital/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()//drains product
explode_fire_vortex(holder, equilibrium, 2, 2, "overheat", TRUE)
/datum/chemical_reaction/medicine/helbital/reaction_finish(datum/reagents/holder, react_vol)
. = ..()
var/datum/reagent/helbital = holder.get_reagent(/datum/reagent/medicine/c2/helbital)
if(!helbital)
return
if(helbital.purity <= 0.1) //So people don't ezmode this by keeping it at min
explode_fire(holder, null, 3)
clear_products(holder)
/datum/chemical_reaction/medicine/libital
results = list(/datum/reagent/medicine/c2/libital = 3)
required_reagents = list(/datum/reagent/phenol = 1, /datum/reagent/oxygen = 1, /datum/reagent/nitrogen = 1)
required_temp = 225
optimal_temp = 700
overheat_temp = 840
optimal_ph_min = 6
optimal_ph_max = 10
determin_ph_range = 4
temp_exponent_factor = 1.75
ph_exponent_factor = 1
thermic_constant = 75
H_ion_release = -6.5
rate_up_lim = 40
purity_min = 0.2
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BRUTE
/datum/chemical_reaction/medicine/probital
results = list(/datum/reagent/medicine/c2/probital = 4)
required_reagents = list(/datum/reagent/copper = 1, /datum/reagent/acetone = 2, /datum/reagent/phosphorus = 1)
required_temp = 225
optimal_temp = 700
overheat_temp = 750
optimal_ph_min = 4.5
optimal_ph_max = 12
determin_ph_range = 2
temp_exponent_factor = 0.75
ph_exponent_factor = 4
thermic_constant = 50
H_ion_release = -2.5
rate_up_lim = 30
purity_min = 0.35//15% window
reaction_flags = REACTION_CLEAR_INVERSE | REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BRUTE
/*****BURN*****/
//These are all endothermic!
//This is a relatively simple demonstration have splitting negatives/having purity based negatives
//Since it requires silver - I don't want to make it too hard
/datum/chemical_reaction/medicine/lenturi
results = list(/datum/reagent/medicine/c2/lenturi = 5)
required_reagents = list(/datum/reagent/ammonia = 1, /datum/reagent/silver = 1, /datum/reagent/sulfur = 1, /datum/reagent/oxygen = 1, /datum/reagent/chlorine = 1)
required_temp = 200
optimal_temp = 300
overheat_temp = 500
optimal_ph_min = 6
optimal_ph_max = 11
determin_ph_range = 6
temp_exponent_factor = 1
ph_exponent_factor = 2
thermic_constant = -175 //Though, it is a test in endothermicity
H_ion_release = -2.5
rate_up_lim = 30
purity_min = 0.25
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BURN
/datum/chemical_reaction/medicine/aiuri
results = list(/datum/reagent/medicine/c2/aiuri = 4)
required_reagents = list(/datum/reagent/ammonia = 1, /datum/reagent/toxin/acid = 1, /datum/reagent/hydrogen = 2)
required_temp = 50
optimal_temp = 300
overheat_temp = 315
optimal_ph_min = 4.8
optimal_ph_max = 9
determin_ph_range = 3
temp_exponent_factor = 5
ph_exponent_factor = 2
thermic_constant = -400
H_ion_release = 3
rate_up_lim = 35
purity_min = 0.25
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BURN
/datum/chemical_reaction/medicine/aiuri/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
for(var/mob/living/living_mob in orange(3, get_turf(holder.my_atom)))
if(living_mob.flash_act(1, length = 5))
living_mob.set_blurriness(10)
holder.my_atom.audible_message("<span class='notice'>[icon2html(holder.my_atom, viewers(DEFAULT_MESSAGE_RANGE, src))] The [holder.my_atom] lets out a loud bang!</span>")
playsound(holder.my_atom, 'sound/effects/explosion1.ogg', 50, 1)
/datum/chemical_reaction/medicine/hercuri
results = list(/datum/reagent/medicine/c2/hercuri = 5)
required_reagents = list(/datum/reagent/cryostylane = 3, /datum/reagent/bromine = 1, /datum/reagent/lye = 1)
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BURN
required_temp = 47
is_cold_recipe = TRUE
required_temp = 47
optimal_temp = 10
overheat_temp = 5
thermic_constant = -50
optimal_ph_min = 6
optimal_ph_max = 10
determin_ph_range = 1
temp_exponent_factor = 3
thermic_constant = -40
H_ion_release = 3.7
rate_up_lim = 50
purity_min = 0.15
reaction_flags = REACTION_PH_VOL_CONSTANT | REACTION_CLEAR_INVERSE
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BURN
/datum/chemical_reaction/medicine/hercuri/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
if(off_cooldown(holder, equilibrium, 2, "hercuri_freeze"))
return
playsound(holder.my_atom, 'sound/magic/ethereal_exit.ogg', 50, 1)
holder.my_atom.visible_message("The reaction frosts over, releasing it's chilly contents!")
var/radius = max((equilibrium.step_target_vol/50), 1)
freeze_radius(holder, equilibrium, 200, radius, 50) //drying agent exists
explode_shockwave(holder, equilibrium, sound_and_text = FALSE)
/*****OXY*****/
//These react faster with optional oxygen, and have blastback effects! (the oxygen makes their fail states deadlier)
/datum/chemical_reaction/medicine/convermol
results = list(/datum/reagent/medicine/c2/convermol = 3)
required_reagents = list(/datum/reagent/hydrogen = 1, /datum/reagent/fluorine = 1, /datum/reagent/fuel/oil = 1)
required_temp = 370
mix_message = "The mixture rapidly turns into a dense pink liquid."
optimal_temp = 420
overheat_temp = 570 //Ash will be created before this - so it's pretty rare that overheat is actually triggered
optimal_ph_min = 3.045 //Rigged to blow once without oxygen
optimal_ph_max = 8.5
determin_ph_range = 2
temp_exponent_factor = 0.75
ph_exponent_factor = 1.25
thermic_constant = 15
H_ion_release = -1
rate_up_lim = 50
purity_min = 0.4
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_OXY
/datum/chemical_reaction/medicine/convermol/reaction_step(datum/equilibrium/reaction, datum/reagents/holder, delta_t, delta_ph, step_reaction_vol)
. = ..()
var/datum/reagent/oxy = holder.has_reagent(/datum/reagent/oxygen)
if(oxy)
holder.remove_reagent(/datum/reagent/oxygen, 0.25)
else
reaction.delta_t = delta_t/10 //slow without oxygen
/datum/chemical_reaction/medicine/convermol/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, impure = FALSE)
var/range = impure ? 4 : 3
if(holder.has_reagent(/datum/reagent/oxygen))
explode_shockwave(holder, equilibrium, range) //damage 5
else
explode_shockwave(holder, equilibrium, range, damage = 2)
/datum/chemical_reaction/medicine/convermol/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
overheated(holder, equilibrium, impure = TRUE)
clear_reactants(holder, vol_added*2)
/datum/chemical_reaction/medicine/tirimol
results = list(/datum/reagent/medicine/c2/tirimol = 5)
required_reagents = list(/datum/reagent/nitrogen = 3, /datum/reagent/acetone = 2)
required_catalysts = list(/datum/reagent/toxin/acid = 1)
mix_message = "The mixture turns into a tired reddish pink liquid."
optimal_temp = 1
optimal_temp = 900
overheat_temp = 720
optimal_ph_min = 2
optimal_ph_max = 7.1
determin_ph_range = 2
temp_exponent_factor = 4
ph_exponent_factor = 1.8
thermic_constant = -20
H_ion_release = 3
rate_up_lim = 50
purity_min = 0.2
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_OXY
/datum/chemical_reaction/medicine/tirimol/reaction_step(datum/equilibrium/reaction, datum/reagents/holder, delta_t, delta_ph, step_reaction_vol)
. = ..()
var/datum/reagent/oxy = holder.has_reagent(/datum/reagent/oxygen)
if(oxy)
holder.remove_reagent(/datum/reagent/oxygen, 0.25)
else
holder.adjust_all_reagents_ph(-0.05*step_reaction_vol)//pH drifts faster
//Sleepytime for chem
/datum/chemical_reaction/medicine/tirimol/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, impure = FALSE)
var/bonus = impure ? 2 : 1
if(holder.has_reagent(/datum/reagent/oxygen))
explode_attack_chem(holder, equilibrium, /datum/reagent/inverse/healing/tirimol, 7.5*bonus, 2, ignore_eyes = TRUE) //since we're smoke/air based
clear_products(holder, 5)//since we attacked
explode_invert_smoke(holder, equilibrium, 3)
else
explode_invert_smoke(holder, equilibrium, 3)
/datum/chemical_reaction/medicine/tirimol/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
overheated(holder, equilibrium, TRUE)
clear_reactants(holder, 2)
/*****TOX*****/
//These all care about purity in their reactions
/datum/chemical_reaction/medicine/seiver
results = list(/datum/reagent/medicine/c2/seiver = 3)
required_reagents = list(/datum/reagent/nitrogen = 1, /datum/reagent/potassium = 1, /datum/reagent/aluminium = 1)
mix_message = "The mixture gives out a goopy slorp."
is_cold_recipe = TRUE
required_temp = 320
optimal_temp = 280
overheat_temp = NO_OVERHEAT
optimal_ph_min = 5
optimal_ph_max = 8
determin_ph_range = 6
temp_exponent_factor = 1
ph_exponent_factor = 0.5
thermic_constant = -500
H_ion_release = -6
rate_up_lim = 15
purity_min = 0.2
reaction_flags = REACTION_PH_VOL_CONSTANT | REACTION_CLEAR_INVERSE
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_TOXIN
/datum/chemical_reaction/medicine/seiver/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
if(off_cooldown(holder, equilibrium, 1, "seiver_rads"))
return
var/modifier = max((100 - holder.chem_temp)*0.025, 0)*vol_added //0 - 5 * volume based off temperature(colder is more)
radiation_pulse(holder.my_atom, modifier, 0.5, can_contaminate=FALSE) //Please advise on this, I don't have a good handle on the numbers
/datum/chemical_reaction/medicine/multiver
results = list(/datum/reagent/medicine/c2/multiver = 2)
required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/salt = 1)
mix_message = "The mixture yields a fine black powder."
required_temp = 380
optimal_temp = 400
overheat_temp = 410
optimal_ph_min = 2.5
optimal_ph_max = 7
determin_ph_range = 4
temp_exponent_factor = 0.5
ph_exponent_factor = 1
thermic_constant = 0
H_ion_release = 0
rate_up_lim = 25
purity_min = 0.1 //Fire is our worry for now
reaction_flags = REACTION_REAL_TIME_SPLIT | REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_PLANT | REACTION_TAG_TOXIN
//You get nothing! I'm serious about staying under the heating requirements!
/datum/chemical_reaction/medicine/multiver/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
var/datum/reagent/monover = holder.has_reagent(/datum/reagent/inverse/healing/monover)
if(monover)
holder.remove_reagent(/datum/reagent/inverse/healing/monover, monover.volume)
holder.my_atom.audible_message("<span class='notice'>[icon2html(holder.my_atom, viewers(DEFAULT_MESSAGE_RANGE, src))] The Monover bursts into flames from the heat!</span>")
explode_fire_square(holder, equilibrium, 1)
holder.my_atom.fire_act(holder.chem_temp, monover.volume)//I'm kinda banking on this setting the thing on fire. If you see this, then it didn't!
/datum/chemical_reaction/medicine/multiver/reaction_step(datum/equilibrium/reaction, datum/reagents/holder, delta_t, delta_ph, step_reaction_vol)
. = ..()
if(delta_ph < 0.35)
//normalise delta_ph
var/norm_d_ph = 1-(delta_ph/0.35)
holder.chem_temp += norm_d_ph*12 //0 - 48 per second)
if(delta_ph < 0.1)
holder.my_atom.visible_message("<span class='notice'>[icon2html(holder.my_atom, viewers(DEFAULT_MESSAGE_RANGE, src))] The Monover begins to glow!</span>")
/datum/chemical_reaction/medicine/syriniver
results = list(/datum/reagent/medicine/c2/syriniver = 5)
required_reagents = list(/datum/reagent/sulfur = 1, /datum/reagent/fluorine = 1, /datum/reagent/toxin = 1, /datum/reagent/nitrous_oxide = 2)
required_temp = 250
optimal_temp = 310
overheat_temp = NO_OVERHEAT
optimal_ph_min = 6.5
optimal_ph_max = 9
determin_ph_range = 6
temp_exponent_factor = 2
ph_exponent_factor = 0.5
thermic_constant = -20
H_ion_release = -5.5
rate_up_lim = 20 //affected by pH too
purity_min = 0.3
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_TOXIN
/datum/chemical_reaction/medicine/syriniver/reaction_step(datum/equilibrium/reaction, datum/reagents/holder, delta_t, delta_ph, step_reaction_vol)
. = ..()
reaction.delta_t = delta_t * delta_ph
/datum/chemical_reaction/medicine/penthrite
results = list(/datum/reagent/medicine/c2/penthrite = 3)
required_reagents = list(/datum/reagent/pentaerythritol = 1, /datum/reagent/acetone = 1, /datum/reagent/toxin/acid/nitracid = 1 , /datum/reagent/wittel = 1)
required_temp = 255
optimal_temp = 350
overheat_temp = 450
optimal_ph_min = 5
optimal_ph_max = 9
determin_ph_range = 3
temp_exponent_factor = 1
ph_exponent_factor = 1
thermic_constant = 150
H_ion_release = -0.5
rate_up_lim = 15
purity_min = 0.55
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_TOXIN
//overheat beats like a heart! (or is it overbeat?)
/datum/chemical_reaction/medicine/penthrite/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
if(off_cooldown(holder, equilibrium, 1, "lub"))
explode_shockwave(holder, equilibrium, 3, 2)
playsound(holder.my_atom, 'sound/health/slowbeat.ogg', 50, 1) // this is 2 mintues long (!) cut it up!
if(off_cooldown(holder, equilibrium, 1, "dub", 0.5))
explode_shockwave(holder, equilibrium, 3, 2, implosion = TRUE)
playsound(holder.my_atom, 'sound/health/slowbeat.ogg', 50, 1)
explode_fire_vortex(holder, equilibrium, 1, 1)
//enabling hardmode
/datum/chemical_reaction/medicine/penthrite/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
holder.chem_temp += 15
@@ -9,7 +9,7 @@
reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_UNIQUE | REACTION_TAG_CHEMICAL
required_temp = 320
optimal_temp = 600
overheat_temp = 800
overheat_temp = 800
optimal_ph_min = 5
optimal_ph_max = 6
determin_ph_range = 5
@@ -20,8 +20,8 @@
rate_up_lim = 1
purity_min = 0
/datum/chemical_reaction/medical_speed_catalyst/overheated(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/medical_speed_catalyst/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
explode_invert_smoke(holder, equilibrium) //Will be better when the inputs have proper invert chems
/datum/chemical_reaction/medical_speed_catalyst/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/medical_speed_catalyst/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
explode_invert_smoke(holder, equilibrium)
@@ -22,19 +22,19 @@
required_reagents = list(/datum/reagent/medicine/ephedrine = 1, /datum/reagent/iodine = 1, /datum/reagent/phosphorus = 1, /datum/reagent/hydrogen = 1)
required_temp = 372
optimal_temp = 376//Wow this is tight
overheat_temp = 380
overheat_temp = 380
optimal_ph_min = 6.5
optimal_ph_max = 7.5
determin_ph_range = 5
temp_exponent_factor = 1
ph_exponent_factor = 1.4
thermic_constant = 0.1 //exothermic nature is equal to impurty
H_ion_release = -0.025
H_ion_release = -0.025
rate_up_lim = 12.5
purity_min = 0.5 //100u will natrually just dip under this w/ no buffer
reaction_flags = REACTION_HEAT_ARBITARY //Heating up is arbitary because of submechanics of this reaction.
reaction_tags = REACTION_TAG_MODERATE | REACTION_TAG_EXPLOSIVE | REACTION_TAG_DRUG | REACTION_TAG_DANGEROUS
//The less pure it is, the faster it heats up. tg please don't hate me for making your meth even more dangerous
/datum/chemical_reaction/methamphetamine/reaction_step(datum/equilibrium/reaction, datum/reagents/holder, delta_t, delta_ph, step_reaction_vol)
var/datum/reagent/meth = holder.get_reagent(/datum/reagent/drug/methamphetamine)
@@ -43,11 +43,11 @@
return
reaction.thermic_mod = (1-meth.purity)*5
/datum/chemical_reaction/methamphetamine/overheated(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/methamphetamine/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
temp_meth_explosion(holder, equilibrium.reacted_vol)
/datum/chemical_reaction/methamphetamine/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/methamphetamine/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
temp_meth_explosion(holder, equilibrium.reacted_vol)
@@ -60,6 +60,19 @@
/datum/chemical_reaction/medicine/synthflesh
results = list(/datum/reagent/medicine/c2/synthflesh = 3)
required_reagents = list(/datum/reagent/blood = 1, /datum/reagent/carbon = 1, /datum/reagent/medicine/c2/libital = 1)
required_temp = 250
optimal_temp = 310
overheat_temp = 325
optimal_ph_min = 5.5
optimal_ph_max = 9.5
determin_ph_range = 3
temp_exponent_factor = 1
ph_exponent_factor = 2
thermic_constant = 10
H_ion_release = -3.5
rate_up_lim = 20 //affected by pH too
purity_min = 0.3
reaction_flags = REACTION_PH_VOL_CONSTANT
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_HEALING | REACTION_TAG_BRUTE | REACTION_TAG_BURN
/datum/chemical_reaction/medicine/calomel
@@ -151,7 +151,7 @@
rate_up_lim = 25 //Give a chance to pull back
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL
/datum/chemical_reaction/nitrous_oxide/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/nitrous_oxide/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
var/turf/exposed_turf = get_turf(holder.my_atom)
if(!exposed_turf)
@@ -159,7 +159,7 @@
exposed_turf.atmos_spawn_air("n2o=[equilibrium.step_target_vol/2];TEMP=[holder.chem_temp]")
clear_products(holder, equilibrium.step_target_vol)
/datum/chemical_reaction/nitrous_oxide/overheated(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/nitrous_oxide/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
return //This is empty because the explosion reaction will occur instead (see pyrotechnics.dm). This is just here to update the lookup ui.
@@ -738,7 +738,7 @@
required_reagents = list(/datum/reagent/consumable/ice = 1)
required_temp = 275
optimal_temp = 350
overheat_temp = 99999
overheat_temp = NO_OVERHEAT
optimal_ph_min = 0
optimal_ph_max = 14
thermic_constant = 0
@@ -754,7 +754,7 @@
required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/ethanol = 1, /datum/reagent/iodine = 1)
required_temp = 274
optimal_temp = 350
overheat_temp = 99999
overheat_temp = NO_OVERHEAT
optimal_ph_min = 0
optimal_ph_max = 14
thermic_constant = 0
@@ -466,7 +466,7 @@
required_reagents = list(/datum/reagent/stable_plasma = 1, /datum/reagent/uranium/radium = 1, /datum/reagent/phosphorus = 1)
required_temp = 0
optimal_temp = 20
overheat_temp = 9999//Replace with NO_OVERHEAT when part 2 is in
overheat_temp = NO_OVERHEAT
temp_exponent_factor = 10
thermic_constant = 0
reaction_tags = REACTION_TAG_EASY | REACTION_TAG_UNIQUE
@@ -86,13 +86,13 @@
holder.remove_reagent(/datum/reagent/bluespace, 1)
reaction.delta_t *= 5
/datum/chemical_reaction/prefactor_b/overheated(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/prefactor_b/overheated(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
. = ..()
explode_shockwave(holder, equilibrium)
var/vol = max(20, holder.total_volume/5) //Not letting you have more than 5
clear_reagents(holder, vol)//Lest we explode forever
/datum/chemical_reaction/prefactor_b/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium)
/datum/chemical_reaction/prefactor_b/overly_impure(datum/reagents/holder, datum/equilibrium/equilibrium, vol_added)
explode_fire(holder, equilibrium)
var/vol = max(20, holder.total_volume/5) //Not letting you have more than 5
clear_reagents(holder, vol)
@@ -113,7 +113,7 @@
/// Called when addiction is in stage 2 every process
/datum/addiction/proc/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, delta_time)
if(DT_PROB(10, delta_time))
if(DT_PROB(10, delta_time) )
to_chat(affected_carbon, "<span class='danger'>[withdrawal_stage_messages[2]]</span>")
@@ -154,3 +154,77 @@
REMOVE_TRAIT(affected_human, TRAIT_NIGHT_VISION, type)
var/obj/item/organ/eyes/eyes = affected_human.getorgan(/obj/item/organ/eyes)
eyes.refresh()
///Makes you a hypochondriac - I'd like to call it hypochondria, but "I could use some hypochondria" doesn't work
/datum/addiction/medicine
name = "medicine"
withdrawal_stage_messages = list("", "", "")
var/datum/hallucination/fake_alert/hallucination
var/datum/hallucination/fake_health_doll/hallucination2
/datum/addiction/medicine/withdrawal_enters_stage_1(mob/living/carbon/affected_carbon)
. = ..()
if(!ishuman(affected_carbon))
return
var/mob/living/carbon/human/human_mob = affected_carbon
hallucination2 = new(human_mob, TRUE, severity = 1, duration = 120 MINUTES)
/datum/addiction/medicine/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, delta_time)
. = ..()
if(DT_PROB(10, delta_time))
affected_carbon.emote("cough")
/datum/addiction/medicine/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon)
. = ..()
var/list/possibilities = list()
if(!HAS_TRAIT(affected_carbon, TRAIT_RESISTHEAT))
possibilities += "temphot"
if(!HAS_TRAIT(affected_carbon, TRAIT_RESISTCOLD))
possibilities += "tempcold"
var/obj/item/organ/lungs/lungs = affected_carbon.getorganslot(ORGAN_SLOT_LUNGS)
if(lungs)
if(lungs.safe_oxygen_min)
possibilities += "not_enough_oxy"
if(lungs.safe_oxygen_max)
possibilities += "too_much_oxy"
var/type = pick(possibilities)
hallucination = new(affected_carbon, TRUE, type, 120 MINUTES)//last for a while basically
/datum/addiction/medicine/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, delta_time)
. = ..()
if(DT_PROB(10, delta_time))
hallucination2.add_fake_limb(severity = 1)
return
if(DT_PROB(5, delta_time))
hallucination2.increment_fake_damage()
/datum/addiction/medicine/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon)
. = ..()
affected_carbon.hal_screwyhud = SCREWYHUD_CRIT
/datum/addiction/medicine/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, delta_time)
. = ..()
if(DT_PROB(5, delta_time))
hallucination2.increment_fake_damage()
return
if(DT_PROB(15, delta_time))
affected_carbon.emote("cough")
return
if(DT_PROB(65, delta_time))
return
var/obj/item/organ/organ = pick(affected_carbon.internal_organs)
if(organ.low_threshold)
to_chat(affected_carbon, organ.low_threshold_passed)
return
else if (organ.high_threshold_passed)
to_chat(affected_carbon, organ.high_threshold_passed)
return
to_chat(affected_carbon, "<span class='warning'>You feel a dull pain in your [organ.name].</span>")
/datum/addiction/medicine/lose_addiction(datum/mind/victim_mind)
. = ..()
if(iscarbon(victim_mind.current))
var/mob/living/carbon/affected_carbon = victim_mind.current
affected_carbon.hal_screwyhud = SCREWYHUD_NONE
hallucination.cleanup()
QDEL_NULL(hallucination2)
+2
View File
@@ -5,6 +5,8 @@
var/mob/living/carbon/human/human = allocate(/mob/living/carbon/human)
for (var/reagent_type in subtypesof(/datum/reagent))
if(reagent_type in GLOB.fake_reagent_blacklist)
continue
test_reagent(human, reagent_type)
/datum/unit_test/metabolization/proc/test_reagent(mob/living/carbon/C, reagent_type)