Files
Aurora.3/code/modules/reagents/Chemistry-Reagents.dm
T
BatrachophrenoandGitHub af0312c7d4 Bugfix batch (Pesticide Edition) (#21556)
Fixes https://github.com/Aurorastation/Aurora.3/issues/18504
Fixes https://github.com/Aurorastation/Aurora.3/issues/21064
Fixes https://github.com/Aurorastation/Aurora.3/issues/21267
Fixes https://github.com/Aurorastation/Aurora.3/issues/21455
Fixes https://github.com/Aurorastation/Aurora.3/issues/21535

Miscellaneous bugfixes, code cleanup, etc. Smaller batches this time.

changes:
  - spellcheck: "Renames 'gibber' to 'autobutcher'."
  - code_imp: "Cleans up a lot of old autobutcher code."
- code_imp: "Simplifies and unifies a lot of circuit board naming code."
  - code_imp: "Updates various code comments to DMDocs format."
- balance: "Slightly increased damage of beating someone with a ladder."
- bugfix: "Fixes foreign speech displaying the translated versions in
langchat for non-fluent listeners."
- bugfix: "Fixes whispered speech langchat; whispers are now correctly
italicized."
- bugfix: "Fixes shouted speech langchat; shouts are now correctly
biggified."
  - bugfix: "Adds missing Omni Gas Mixer, Gas Meter options from RFD-P."
- bugfix: "Adds missing circuit boards for bioballistic delivery system,
lysis-isolation centrifuge, and autobutcher to allow for construction
and deconstruction."
- bugfix: "Fixes empty algae chips bag having description set for its
name."
- bugfix: "Adds fallback_specific_heat values to several reagents that
were missing them."
- bugfix: "Fixes antimateriel projectiles being erroneously
damage-capped when hitting walls."
- bugfix: "Fixes laser beam effects not using the base colors of their
beam VFX."
- qol: "Added helpful feedback hint to move closer when someone speaks
aloud within 4 tiles while you're in vacuum (as features go, this one
felt more like a bug to experience)."
  - qol: "Updated various examine hints."

---------

Signed-off-by: Batrachophreno <Batrochophreno@gmail.com>
2025-11-11 10:56:12 +00:00

202 lines
8.9 KiB
Plaintext

/singleton/reagent
var/name = "Reagent"
var/description = "A non-descript chemical."
var/taste_description = "old rotten bandaids"
var/list/species_taste_description
/// How this taste compares to others. Higher values means it is more noticable.
var/taste_mult = 1
var/reagent_state = SOLID
/// Default value is 0.2.
var/metabolism = REM
var/ingest_met = 0
var/touch_met = 0
var/breathe_met = 0
var/ingest_mul = 0.5
var/touch_mul = 0
var/breathe_mul = 0.75
/// Volume of a chemical required in the blood to meet overdose criteria.
var/overdose = 0
/// Metabolised dose of a chemical required to meet overdose criteria.
var/od_minimum_dose = 5
/// Shows up on health analyzers.
var/scannable = 0
/// Doesn't show up on basic mass spectrometers, only shows on the advanced variant
var/spectro_hidden = FALSE
var/affects_dead = 0
var/glass_icon_state = null
var/glass_name = null
var/glass_desc = null
var/glass_center_of_mass = null
var/condiment_icon = null
var/condiment_icon_state = null
var/condiment_name = null
var/condiment_desc = null
var/condiment_center_of_mass = null
var/color = "#000000"
var/color_weight = 1
/// Species that aren't affected by this reagent. Does not prevent affect_touch.
var/unaffected_species = IS_DIONA | IS_MACHINE
/// How much for the medicine to be present in the system to actually have an effect.
var/metabolism_min = 0.01
/// Reagents that conflict with this medicine, and cause adverse effects when in the blood.
var/conflicting_reagent
/// This is its default spawning temperature, if none is provided.
var/default_temperature = T0C + 20
/// The higher, the more difficult it is to change its temperature. 0 or lower values indicate that the specific heat has yet to be assigned.
var/specific_heat = -1
/// Setting this value above 0 will set the specific heat to this value only if the system could not find an appropriate specific heat to assign using the recipe system.
/// Never ever ever ever change this value for singleton/reagent. This should only be used for massive, yet specific things like drinks or food where it is infeasible to assign a specific heat value.
var/fallback_specific_heat = -1
/// For makeshift bandages/disinfectant
var/germ_adjust = 0
/// If it's carbonated or not.
var/carbonated = FALSE
/// Adds to the value of whatever container's holding it, value * units of reagents
var/value = 1
/// Called when the reagent is created.
/singleton/reagent/proc/initialize_data(var/newdata, var/datum/reagents/holder)
if(!isnull(newdata))
return newdata
/singleton/reagent/proc/remove_self(var/amount, var/datum/reagents/holder) // Shortcut
holder.remove_reagent(type, amount) // Don't typecheck this, fix anywhere this is called with a null holder.
if(ishuman(holder.my_atom))
var/mob/living/carbon/human/H = holder.my_atom
if(H.vessel && (/singleton/reagent/blood in H.vessel.reagent_data))
if(H.vessel.reagent_data[/singleton/reagent/blood]["trace_chem"][type])
H.vessel.reagent_data[/singleton/reagent/blood]["trace_chem"][type] += amount
else
H.vessel.reagent_data[/singleton/reagent/blood]["trace_chem"][type] = amount
/// This doesn't apply to skin contact - this is for, e.g. extinguishers and sprays. The difference is that reagent is not directly on the mob's skin - it might just be on their clothing.
/singleton/reagent/proc/touch_mob(var/mob/living/M, var/amount, var/datum/reagents/holder)
return
/singleton/reagent/proc/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder) // Acid melting, cleaner cleaning, etc
return
/singleton/reagent/proc/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) // Cleaner cleaning, lube lubbing, etc, all go here
return
/singleton/reagent/proc/get_overdose(mob/living/carbon/M, location, datum/reagents/holder)
return overdose
/singleton/reagent/proc/get_od_min_dose(mob/living/carbon/M, location, datum/reagents/holder)
return od_minimum_dose
/singleton/reagent/proc/is_overdosing(mob/living/carbon/M, location, datum/reagents/holder)
var/OD = get_overdose(M, location, holder)
var/OD_min = get_od_min_dose(M, location, holder)
return OD && (REAGENT_VOLUME(holder, type) > OD) && (LAZYACCESS(M.chem_doses, type) > OD_min) && (!location || (location != CHEM_TOUCH)) //OD based on volume in blood, but waits for a small amount of the drug to metabolise before kicking in.
/// Currently, on_mob_life is called on carbons. Any interaction with non-carbon mobs (lube) will need to be done in touch_mob.
/singleton/reagent/proc/on_mob_life(var/mob/living/carbon/M, var/alien, var/location, var/datum/reagents/holder)
if(!istype(M))
return
if(!affects_dead && M.stat == DEAD)
return
if(alien & unaffected_species && location != CHEM_TOUCH)
return
var/removed = metabolism
if(ingest_met && (location == CHEM_INGEST))
removed = ingest_met
if(touch_met && (location == CHEM_TOUCH))
removed = touch_met
if(breathe_met && (location == CHEM_BREATHE))
removed = breathe_met
removed = M.get_metabolism(removed)
// ctual overdose threshold now = overdose + od_minimum_dose. ie. Synaptizine; 5u OD threshold + 1 unit min. metab'd dose = 6u actual OD threshold.
if(is_overdosing(M, location, holder))
overdose(M, alien, removed, LAZYACCESS(M.chem_doses, type)/get_overdose(M, location, holder), holder)
if(LAZYACCESS(M.chem_doses, type) <= 0)
initial_effect(M,alien, holder)
LAZYSET(M.chem_doses, type, LAZYACCESS(M.chem_doses, type) + removed)
var/bodytempchange = clamp((holder.get_temperature() - M.bodytemperature) * removed * REAGENTS_BODYTEMP,-REAGENTS_BODYTEMP_MAX * removed, REAGENTS_BODYTEMP_MAX * removed)
if(abs(bodytempchange) >= REAGENTS_BODYTEMP_MIN)
M.bodytemperature += round(bodytempchange,REAGENTS_BODYTEMP_MIN)
holder.set_temperature(holder.get_temperature() - round(bodytempchange,REAGENTS_BODYTEMP_MIN))
for(var/_R in M.bloodstr.reagent_volumes)
var/singleton/reagent/R = GET_SINGLETON(_R)
if(istype(R, conflicting_reagent))
affect_conflicting(M,alien,removed,R, holder)
if(removed >= metabolism_min)
switch(location)
if(CHEM_BLOOD)
affect_blood(M, alien, removed, holder)
if(CHEM_INGEST)
affect_ingest(M, alien, removed, holder)
if(CHEM_TOUCH)
affect_touch(M, alien, removed, holder)
if(CHEM_BREATHE)
affect_breathe(M, alien, removed, holder)
remove_self(removed, holder)
/// Called when a beaker is thrown or something is hit with it, AND the beaker doesn't break.
/singleton/reagent/proc/apply_force(var/force, var/datum/reagents/holder)
return force
/// Initial effect is called once when the reagent first starts affecting a mob.
/singleton/reagent/proc/initial_effect(var/mob/living/carbon/M, var/alien, var/datum/reagents/holder)
return
/// Final effect is called once when the reagent finishes affecting a mob.
/singleton/reagent/proc/final_effect(var/mob/living/carbon/M, var/datum/reagents/holder)
return
/singleton/reagent/proc/affect_blood(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
return
/// If your chem directly affects other chems, use this to make sure all the chem_effects are applied before the standard chem affect_thing is run
/singleton/reagent/proc/affect_chem_effect(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
if(!istype(M))
return FALSE
if(!affects_dead && M.stat == DEAD)
return FALSE
if(alien & unaffected_species)
return FALSE
return TRUE
/singleton/reagent/proc/affect_conflicting(var/mob/living/carbon/M, var/alien, var/removed, var/singleton/reagent/conflicting_reagent, var/datum/reagents/holder)
M.adjustToxLoss(removed)
/singleton/reagent/proc/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
if(ingest_mul)
affect_blood(M, alien, removed * ingest_mul, holder)
/singleton/reagent/proc/affect_touch(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
if(touch_mul)
affect_blood(M, alien, removed * touch_mul, holder)
/singleton/reagent/proc/affect_breathe(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder)
if(breathe_mul)
affect_blood(M, alien, removed * breathe_mul, holder)
/// Overdose effect. Doesn't happen instantly.
/singleton/reagent/proc/overdose(var/mob/living/carbon/M, var/alien, var/removed = 0, var/scale = 1, var/datum/reagents/holder)
M.adjustToxLoss(REM)
/// You have a reagent with data, and new reagent with its own data get added, how do you deal with that?
/singleton/reagent/proc/mix_data(var/newdata, var/newamount, var/datum/reagents/holder)
return REAGENT_DATA(holder, type)
/// Check to use when seeing if the person has the minimum dose of the reagent. Useful for stopping minimum transfer rate IV drips from applying chem effects
/singleton/reagent/proc/check_min_dose(var/mob/living/carbon/M, var/min_dose = 1)
var/dose = REAGENT_VOLUME(M.reagents, type) >= min_dose
var/obj/item/organ/internal/stomach/S = M.internal_organs_by_name[BP_STOMACH]
if(S)
dose += REAGENT_VOLUME(S.ingested, type) >= min_dose
return dose