Files
Aurora.3/code/modules/reagents/Chemistry-Reagents.dm
Cody Brittain 9b5f89a717 Ports Turf Fires (#21659)
Adds turf fires (ported from Baystation, which ported them from
Shiptest), which are now used instead of ZAS fires for fuel decals and
flamethrowers. They also supplement ZAS fires in especially bad atmos
fires.

This makes flamethrowers and related objects more suitable for AOE
denial, rather than cooking the room (including yourself). They still do
the latter, but less so than a gaseous fire.

To make flamethrowers actually useful against them, simple mobs now take
brute damage when on fire.

### Asset Licenses
The following assets that **have not** been created by myself are
included in this PR:

| Path | Original Author | License |
| --- | --- | --- |
| sound/weapons/flamethrower/flamethrower1.ogg |
[rye-rice](https://github.com/rye-rice) (Shiptest) | CC-BY-SA 3.0 |
| sound/weapons/flamethrower/flamethrower2.ogg |
[rye-rice](https://github.com/rye-rice) (Shiptest) | CC-BY-SA 3.0 |
| sound/weapons/flamethrower/flamethrower3.ogg |
[rye-rice](https://github.com/rye-rice) (Shiptest) | CC-BY-SA 3.0 |
| sound/weapons/flamethrower/flamethrower_empty.ogg |
[rye-rice](https://github.com/rye-rice) (Shiptest) | CC-BY-SA 3.0 |
| icons/effects/particles/smoke.dmi |
[rye-rice](https://github.com/shiptest-ss13/Shiptest/commits?author=rye-rice)
(Shiptest) | CC-BY-SA 3.0 |
| icons/effects/turf_fire.dmi | CM Dev (cmss13) | CC-BY-SA 3.0 |
2026-01-31 01:41:11 +00:00

207 lines
9.0 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
///How effective this chemical is in a flamethrower.
var/accelerant_quality = 0
///Should this reagent burn a different color?
var/fire_color = null
/// 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