diff --git a/auxmos.dll b/auxmos.dll index eb7e3b71fc..b83298b213 100644 Binary files a/auxmos.dll and b/auxmos.dll differ diff --git a/auxmos.pdb b/auxmos.pdb index 5d005d3689..9333dc07c1 100644 Binary files a/auxmos.pdb and b/auxmos.pdb differ diff --git a/code/__DEFINES/reactions.dm b/code/__DEFINES/reactions.dm index fad53e4830..d1329060eb 100644 --- a/code/__DEFINES/reactions.dm +++ b/code/__DEFINES/reactions.dm @@ -42,3 +42,5 @@ #define FUSION_RAD_MAX 2000 #define FUSION_RAD_COEFFICIENT (-1000) #define FUSION_INSTABILITY_ENDOTHERMALITY 2 +// Snowflake fire product types +#define FIRE_PRODUCT_PLASMA 0 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index cbfd8d7429..a07d9c1106 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -179,6 +179,8 @@ #define TRAIT_DWARF "dwarf" #define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance" #define TRAIT_AGEUSIA "ageusia" +#define TRAIT_ANOSMIA "anosmia" +#define TRAIT_GOODSMELL "super_smeller" #define TRAIT_HEAVY_SLEEPER "heavy_sleeper" #define TRAIT_NIGHT_VISION "night_vision" #define TRAIT_LIGHT_STEP "light_step" diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index 8f7d67abb8..dad5237aa5 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -205,6 +205,16 @@ synchronizer_coeff = 1 var/reek = 200 +/datum/mutation/human/olfaction/on_acquiring(mob/living/carbon/human/owner) + if(..() || HAS_TRAIT(owner, TRAIT_ANOSMIA)) + return TRUE + ADD_TRAIT(owner, TRAIT_GOODSMELL, GENETIC_MUTATION) + +/datum/mutation/human/olfaction/on_losing(mob/living/carbon/human/owner) + if(..()) + return + REMOVE_TRAIT(owner, TRAIT_GOODSMELL, GENETIC_MUTATION) + /datum/mutation/human/olfaction/modify() if(power) var/obj/effect/proc_holder/spell/targeted/olfaction/S = power diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 10f66fce0c..8958226ff4 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -416,3 +416,12 @@ GLOBAL_LIST_EMPTY(family_heirlooms) . = ..() var/mob/living/carbon/human/H = quirk_holder H?.cure_trauma_type(/datum/brain_trauma/severe/monophobia, TRAUMA_RESILIENCE_ABSOLUTE) + +/datum/quirk/no_smell + name = "Anosmia" + desc = "You can't smell anything! You won't be able to detect certain colorless gases." + value = -1 + mob_trait = TRAIT_ANOSMIA + gain_text = "You can't smell anything!" + lose_text = "You can smell again!" + medical_record_text = "Patient suffers from anosmia and is incapable of smelling gases or particulates." diff --git a/code/modules/atmospherics/auxgm/gas_types.dm b/code/modules/atmospherics/auxgm/gas_types.dm index 4e42b3392a..6c8939369d 100644 --- a/code/modules/atmospherics/auxgm/gas_types.dm +++ b/code/modules/atmospherics/auxgm/gas_types.dm @@ -7,6 +7,9 @@ heat_penalty = 1 transmit_modifier = 1.5 +/datum/gas/oxygen/generate_TLV() + return new/datum/tlv(16, 19, 40, 50) + /datum/gas/nitrogen id = GAS_N2 specific_heat = 20 @@ -48,6 +51,9 @@ fusion_power = 3 enthalpy = -393500 +/datum/gas/carbon_dioxide/generate_TLV() + return new/datum/tlv(-1, -1, 5, 10) + /datum/gas/plasma id = GAS_PLASMA specific_heat = 200 @@ -60,19 +66,16 @@ powermix = 1 fire_burn_rate = OXYGEN_BURN_RATE_BASE // named when plasma fires were the only fires, surely fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - fire_products = "plasma_fire" + fire_products = FIRE_PRODUCT_PLASMA enthalpy = FIRE_PLASMA_ENERGY_RELEASED // 3000000, 3 megajoules, 3000 kj -/datum/gas/plasma/New() - if(world.system_type == UNIX) - fire_temperature = null - /datum/gas/water_vapor id = GAS_H2O specific_heat = 40 name = "Water Vapor" gas_overlay = "water_vapor" moles_visible = MOLES_GAS_VISIBLE + flags = GAS_FLAG_DANGEROUS fusion_power = 8 heat_penalty = 8 enthalpy = -241800 // FIRE_HYDROGEN_ENERGY_RELEASED is actually what this was supposed to be @@ -92,10 +95,30 @@ enthalpy = 81600 heat_resistance = 6 +/datum/gas/tritium + id = GAS_TRITIUM + specific_heat = 10 + name = "Tritium" + gas_overlay = "tritium" + moles_visible = MOLES_GAS_VISIBLE + flags = GAS_FLAG_DANGEROUS + fusion_power = 1 + powermix = 1 + heat_penalty = 10 + transmit_modifier = 30 + fire_products = list(GAS_H2O = 1) + enthalpy = 300000 + fire_burn_rate = 2 + fire_radiation_released = 50 // arbitrary number, basically 60 moles of trit burning will just barely start to harm you + fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50 + /datum/gas/nitric_oxide id = GAS_NITRIC specific_heat = 20 name = "Nitric oxide" + flags = GAS_FLAG_DANGEROUS + odor = "sharp sweetness" + odor_strength = 1 fusion_power = 15 enthalpy = 91290 heat_resistance = 2 @@ -104,7 +127,7 @@ id = GAS_NITRYL specific_heat = 20 name = "Nitrogen dioxide" - gas_overlay = "nitryl" + color = "#963" moles_visible = MOLES_GAS_VISIBLE flags = GAS_FLAG_DANGEROUS fusion_power = 15 @@ -132,27 +155,6 @@ fire_burn_rate = 2 fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50 -/datum/gas/tritium - id = GAS_TRITIUM - specific_heat = 10 - name = "Tritium" - gas_overlay = "tritium" - moles_visible = MOLES_GAS_VISIBLE - flags = GAS_FLAG_DANGEROUS - fusion_power = 1 - powermix = 1 - heat_penalty = 10 - transmit_modifier = 30 - fire_products = list(GAS_H2O = 1) - enthalpy = 300000 - fire_burn_rate = 2 - fire_radiation_released = 50 // arbitrary number, basically 60 moles of trit burning will just barely start to harm you - fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50 - -/datum/gas/tritium/New() - if(world.system_type == UNIX) - fire_temperature = null - /datum/gas/bz id = GAS_BZ specific_heat = 20 @@ -168,6 +170,8 @@ /datum/gas/stimulum id = GAS_STIMULUM specific_heat = 5 + odor = "the color blue" // fast + odor_strength = 10 name = "Stimulum" fusion_power = 7 @@ -184,10 +188,15 @@ transmit_modifier = -5 heat_resistance = 3 +/datum/gas/pluoxium/generate_TLV() + return new/datum/tlv(-1, -1, 5, 6) + /datum/gas/miasma id = GAS_MIASMA specific_heat = 20 fusion_power = 50 + flags = GAS_FLAG_DANGEROUS + // snowflaked odor name = "Miasma" gas_overlay = "miasma" moles_visible = MOLES_GAS_VISIBLE * 60 @@ -196,6 +205,9 @@ id = GAS_METHANE specific_heat = 30 name = "Methane" + odor = "natural gas" + odor_strength = 2 + flags = GAS_FLAG_DANGEROUS powerloss_inhibition = 1 heat_resistance = 3 breath_results = GAS_METHYL_BROMIDE @@ -234,14 +246,18 @@ fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5, GAS_BROMINE = 0.5) enthalpy = -35400 fire_burn_rate = 4 / 7 // oh no - fire_temperature = 808 // its autoignition, it apparently doesn't spark readily, so i don't put it lower + fire_temperature = 808 // its autoignition; it apparently doesn't spark readily, so i don't put it lower /datum/gas/bromine id = GAS_BROMINE specific_heat = 76 name = "Bromine" - flags = GAS_FLAG_DANGEROUS + flags = GAS_FLAG_DANGEROUS | GAS_FLAG_CHEMICAL group = GAS_GROUP_CHEMICALS + color = "#6e1f00" + moles_visible = MOLES_GAS_VISIBLE + odor = "bromine" // it's a very recognizable smell + odor_strength = 0.1 enthalpy = 193 // yeah it's small but it's good to include it breath_reagent = /datum/reagent/bromine @@ -249,7 +265,9 @@ id = GAS_AMMONIA specific_heat = 35 name = "Ammonia" - flags = GAS_FLAG_DANGEROUS + odor = "ammonia" + odor_strength = 0.01 + flags = GAS_FLAG_DANGEROUS | GAS_FLAG_CHEMICAL group = GAS_GROUP_CHEMICALS enthalpy = -45900 breath_reagent = /datum/reagent/ammonia diff --git a/code/modules/atmospherics/gasmixtures/auxgm.dm b/code/modules/atmospherics/gasmixtures/auxgm.dm index 2e5dd716ed..3624b2fff3 100644 --- a/code/modules/atmospherics/gasmixtures/auxgm.dm +++ b/code/modules/atmospherics/gasmixtures/auxgm.dm @@ -25,6 +25,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA var/list/ids = list() var/list/typepaths = list() var/list/fusion_powers = list() + var/list/TLV = list() var/list/breathing_classes = list() var/list/breath_results = list() var/list/breath_reagents = list() @@ -39,13 +40,18 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA var/list/supermatter = list() var/list/groups_by_gas = list() var/list/groups = list() + var/list/TLVs = list() + var/list/odors = list() + var/list/odor_strengths = list() /datum/gas var/id = "" var/specific_heat = 0 var/name = "" - var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi - var/color = "#ffff" + var/gas_overlay = "generic" //icon_state in icons/effects/atmospherics.dmi + var/color = "#ffff" // Tints the overlay by this color. Use instead of gas_overlay, usually (but not necessarily). + var/odor = null // Odor string. Null means none; if not null, anyone who breathes the gas will smell it. + var/odor_strength = INFINITY // How strong the odor is; minimal partial pressure to smell, so lower = more. var/moles_visible = null var/flags = NONE //currently used by canisters var/group = null // groups for scrubber/filter listing @@ -68,6 +74,12 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA var/heat_resistance = 0 // makes the crystal more resistant against heat damage. var/powerloss_inhibition = 0 // Reduces how much power the supermatter loses each tick +/datum/gas/proc/generate_TLV() + if(flags & GAS_FLAG_DANGEROUS) + return new/datum/tlv/dangerous + else + return new/datum/tlv(-1, -1, 1000, 1000) + /datum/gas/proc/breath(partial_pressure, light_threshold, heavy_threshold, moles, mob/living/carbon/C, obj/item/organ/lungs/lungs) // This is only called on gases with the GAS_FLAG_BREATH_PROC flag. When possible, do NOT use this-- // greatly prefer just adding a reagent. This is mostly around for legacy reasons. @@ -79,11 +91,14 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA datums[g] = gas specific_heats[g] = gas.specific_heat names[g] = gas.name + TLVs[g] = gas.generate_TLV() if(gas.moles_visible) visibility[g] = gas.moles_visible overlays[g] = new /list(FACTOR_GAS_VISIBLE_MAX) for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX) - overlays[g][i] = new /obj/effect/overlay/gas(gas.gas_overlay, i * 255 / FACTOR_GAS_VISIBLE_MAX) + var/obj/effect/overlay/gas/overlay = new(gas.gas_overlay, i * 255 / FACTOR_GAS_VISIBLE_MAX) + overlay.color = gas.color + overlays[g][i] = overlay else visibility[g] = 0 overlays[g] = 0 @@ -114,8 +129,11 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA if(gas.group) if(!(gas.group in groups)) groups[gas.group] = list() - groups[gas.group] += gas + groups[gas.group] += g groups_by_gas[g] = gas.group + if(gas.odor) + odor_strengths[g] = gas.odor_strength + odors[g] = gas.odor add_supermatter_properties(gas) _auxtools_register_gas(gas) if(done_initializing) @@ -145,6 +163,17 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA done_initializing = TRUE finalize_gas_refs() +/datum/auxgm/proc/get_by_flag(flag) + var/static/list/gases_by_flag + if(!gases_by_flag) + gases_by_flag = list() + if(!(flag in gases_by_flag)) + gases_by_flag += flag + gases_by_flag[flag] = list() + for(var/g in flags) + if(flags[g] & flag) + gases_by_flag[flag] += g + return gases_by_flag[flag] GLOBAL_DATUM_INIT(gas_data, /datum/auxgm, new) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index b670baaae7..56820d2836 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -135,6 +135,7 @@ we use a hook instead /datum/gas_mixture/proc/set_temperature(new_temp) /datum/gas_mixture/proc/set_volume(new_volume) /datum/gas_mixture/proc/get_moles(gas_type) +/datum/gas_mixture/proc/get_by_flag(flag) /datum/gas_mixture/proc/set_moles(gas_type, moles) // VV WRAPPERS - EXTOOLS HOOKED PROCS DO NOT TAKE ARGUMENTS FROM CALL() FOR SOME REASON. @@ -152,13 +153,20 @@ we use a hook instead /datum/gas_mixture/proc/scrub_into(datum/gas_mixture/target, ratio, list/gases) /datum/gas_mixture/proc/mark_immutable() /datum/gas_mixture/proc/get_gases() +/datum/gas_mixture/proc/add(amt) +/datum/gas_mixture/proc/subtract(amt) /datum/gas_mixture/proc/multiply(factor) +/datum/gas_mixture/proc/divide(factor) /datum/gas_mixture/proc/get_last_share() /datum/gas_mixture/proc/clear() /datum/gas_mixture/proc/adjust_moles(gas_type, amt = 0) set_moles(gas_type, clamp(get_moles(gas_type) + amt,0,INFINITY)) +/datum/gas_mixture/proc/adjust_moles_temp(gas_type, amt, temperature) + +/datum/gas_mixture/proc/adjust_multi() + /datum/gas_mixture/proc/return_volume() //liters /datum/gas_mixture/proc/thermal_energy() //joules @@ -175,6 +183,10 @@ we use a hook instead //Removes amount of gas from the gas_mixture //Returns: gas_mixture with the gases removed +/datum/gas_mixture/proc/remove_by_flag(flag, amount) + //Removes amount of gas from the gas mixture by flag + //Returns: gas_mixture with gases that match the flag removed + /datum/gas_mixture/proc/transfer_to(datum/gas_mixture/target, amount) //Transfers amount of gas to target. Equivalent to target.merge(remove(amount)) but faster. @@ -235,6 +247,14 @@ we use a hook instead //Makes every gas in the given list have the same pressure, temperature and gas proportions. //Returns: null +/datum/gas_mixture/proc/__remove_by_flag() + +/datum/gas_mixture/remove_by_flag(flag, amount) + var/datum/gas_mixture/removed = new type + __remove_by_flag(removed, flag, amount) + + return removed + /datum/gas_mixture/proc/__remove() /datum/gas_mixture/remove(amount) var/datum/gas_mixture/removed = new type diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 85593cf0e0..122d30f33e 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -117,7 +117,6 @@ id = "tritfire" /datum/gas_reaction/tritfire/init_reqs() - exclude = world.system_type == MS_WINDOWS // temporary stopgap until generic fires work on linux min_requirements = list( "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST, GAS_TRITIUM = MINIMUM_MOLE_COUNT, @@ -199,7 +198,6 @@ id = "plasmafire" /datum/gas_reaction/plasmafire/init_reqs() - exclude = world.system_type == MS_WINDOWS // temporary stopgap until generic fires work on linux min_requirements = list( "TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST, GAS_PLASMA = MINIMUM_MOLE_COUNT, diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index d6e48daff0..66b8277273 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -90,7 +90,6 @@ var/frequency = FREQ_ATMOS_CONTROL var/alarm_frequency = FREQ_ATMOS_ALARMS var/datum/radio_frequency/radio_connection - var/list/TLV = list( // Breathable air. "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), @@ -108,9 +107,17 @@ GAS_NITRYL = new/datum/tlv/dangerous, GAS_PLUOXIUM = new/datum/tlv(-1, -1, 5, 6), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires GAS_METHANE = new/datum/tlv(-1, -1, 3, 6), - GAS_METHYL_BROMIDE = new/datum/tlv/dangerous + GAS_METHYL_BROMIDE = new/datum/tlv/dangerous, + GAS_AMMONIA = new/datum/tlv/dangerous, + GAS_BROMINE = new/datum/tlv/dangerous, + ) +/obj/machinery/airalarm/proc/regenerate_TLV() + var/list/TLVs = GLOB.gas_data.TLVs + for(var/g in TLVs) + TLV[g] = TLVs[g] + /obj/machinery/airalarm/server // No checks here. TLV = list( "pressure" = new/datum/tlv/no_checks, @@ -132,6 +139,11 @@ GAS_METHYL_BROMIDE = new/datum/tlv/no_checks ) +/obj/machinery/airalarm/server/regenerate_TLV() + var/list/TLVs = GLOB.gas_data.TLVs + for(var/g in TLVs) + TLV[g] = new/datum/tlv/no_checks + /obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures. TLV = list( "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa @@ -203,6 +215,8 @@ /obj/machinery/airalarm/Initialize(mapload, ndir, nbuild) . = ..() + regenerate_TLV() + RegisterSignal(SSdcs,COMSIG_GLOB_NEW_GAS,.proc/regenerate_TLV) wires = new /datum/wires/airalarm(src) if(ndir) @@ -535,7 +549,7 @@ for(var/device_id in A.air_scrub_names) send_signal(device_id, list( "power" = 1, - "set_filters" = list(GAS_CO2, GAS_METHANE, GAS_METHYL_BROMIDE, GAS_MIASMA, GAS_GROUP_CHEMICALS), + "set_filters" = list(GAS_CO2, GAS_MIASMA, GAS_GROUP_CHEMICALS), "scrubbing" = 1, "widenet" = 0, )) @@ -546,26 +560,11 @@ "set_external_pressure" = ONE_ATMOSPHERE )) if(AALARM_MODE_CONTAMINATED) + var/list/all_gases = GLOB.gas_data.get_by_flag(GAS_FLAG_DANGEROUS) for(var/device_id in A.air_scrub_names) send_signal(device_id, list( "power" = 1, - "set_filters" = list( - GAS_CO2, - GAS_MIASMA, - GAS_PLASMA, - GAS_H2O, - GAS_HYDROGEN, - GAS_HYPERNOB, - GAS_NITROUS, - GAS_NITRYL, - GAS_TRITIUM, - GAS_BZ, - GAS_STIMULUM, - GAS_PLUOXIUM, - GAS_METHANE, - GAS_METHYL_BROMIDE, - GAS_GROUP_CHEMICALS - ), + "set_filters" = all_gases, "scrubbing" = 1, "widenet" = 1, )) @@ -599,7 +598,7 @@ for(var/device_id in A.air_scrub_names) send_signal(device_id, list( "power" = 1, - "set_filters" = list(GAS_CO2, GAS_MIASMA), + "set_filters" = list(GAS_CO2, GAS_MIASMA, GAS_GROUP_CHEMICALS), "scrubbing" = 1, "widenet" = 0, )) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 025435929a..4ced6c0554 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -42,7 +42,7 @@ clean_filter_types = list() for(var/id in filter_types) if(id in GLOB.gas_data.groups) - clean_filter_types += GLOB.gas_data.groups[id] + clean_filter_types |= GLOB.gas_data.groups[id] else clean_filter_types += id diff --git a/code/modules/mob/living/smell.dm b/code/modules/mob/living/smell.dm new file mode 100644 index 0000000000..bc82fe5ccb --- /dev/null +++ b/code/modules/mob/living/smell.dm @@ -0,0 +1,62 @@ +#define DEFAULT_SMELL_SENSITIVITY 1 + +/mob/living + var/last_smell_time + var/last_smell_text + +/mob/living/proc/get_smell_sensitivity() + return DEFAULT_SMELL_SENSITIVITY + +/mob/living/carbon/get_smell_sensitivity() + . = DEFAULT_SMELL_SENSITIVITY + var/obj/item/organ/lungs/lungs = getorganslot(ORGAN_SLOT_LUNGS) // don't think about it too hard + if(istype(lungs)) + . = lungs.smell_sensitivity + if(HAS_TRAIT(src, TRAIT_ANOSMIA)) + . *= 0 + else if(HAS_TRAIT(src, TRAIT_GOODSMELL)) + . *= 2 + +/mob/living/proc/smell(datum/gas_mixture/from) + if(last_smell_time + 50 > world.time) + return FALSE + var/smell_sensitivity = get_smell_sensitivity() + + if(smell_sensitivity == 0) + return FALSE + + var/pressure = from.return_pressure() + var/total_moles = from.total_moles() + + #define PP_MOLES(X) ((X / total_moles) * pressure) + + #define PP(air, gas) PP_MOLES(air.get_moles(gas)) + + var/list/odors = GLOB.gas_data.odors + var/list/odor_strengths = GLOB.gas_data.odor_strengths + var/list/odors_found = list() + for(var/gas in from.get_gases()) + if(!(gas in odors)) + continue + var/pp = PP(from, gas) + var/strength = (odor_strengths[gas] / smell_sensitivity) + if(pp > 2*strength) + odors_found += "[odors[gas]]" + else if(pp > strength) + odors_found += "a hint of [odors[gas]]" + if(!length(odors_found)) + return FALSE + var/text_output = "" + if(hallucination > 50 && prob(25)) + text_output = pick("", "spiders","dreams","nightmares","the future","the past","victory",\ + "defeat","pain","bliss","chaos","revenge","cold","rotten glass","poison","time","space","death","life","truth","lies","justice","memory",\ + "regrets","your soul","suffering","magic","music","noise","blood","hunger","the american way") + else + text_output = english_list(odors_found, "something indescribable") + if(text_output != last_smell_text || last_smell_time + 100 < world.time) + to_chat(src, "You can smell [text_output].") + last_smell_time = world.time + last_smell_text = text_output + + #undef PP_MOLES + #undef PP diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 8d009ffb2e..0bb847a573 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -273,6 +273,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) G.color = color G.breath_reagent = src.type G.group = GAS_GROUP_CHEMICALS + G.moles_visible = MOLES_GAS_VISIBLE return G /datum/reagent/proc/create_gas() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index d4d3cf7e7e..abe3aef82d 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1497,6 +1497,13 @@ myseed.adjust_yield(1) myseed.adjust_instability(1) +/datum/reagent/ammonia/reaction_mob(mob/living/M, method=TOUCH, reac_volume, touch_protection) + if(method == VAPOR) + M.adjustOrganLoss(ORGAN_SLOT_LUNGS, ((100-touch_protection)/100)*reac_volume*REAGENTS_EFFECT_MULTIPLIER * 0.25) + if(prob(reac_volume)) + to_chat(M, "Your lungs hurt!") + return ..() + /datum/reagent/diethylamine name = "Diethylamine" description = "A secondary amine, mildly corrosive." @@ -1807,6 +1814,10 @@ boiling_point = 332 pH = 7.8 +/datum/reagent/bromine/on_mob_life(mob/living/carbon/C) + C.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2, 99) + ..() + /datum/reagent/phenol name = "Phenol" description = "An aromatic ring of carbon with a hydroxyl group. A useful precursor to some medicines, but has no healing properties on its own." diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index aad33c4e92..cb2c02fa7c 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -76,6 +76,8 @@ var/heat_level_3_damage = HEAT_GAS_DAMAGE_LEVEL_3 var/heat_damage_type = BURN + var/smell_sensitivity = 1 + var/crit_stabilizing_reagent = /datum/reagent/medicine/epinephrine /obj/item/organ/lungs/New() @@ -245,12 +247,16 @@ else if(alert_category) H.clear_alert(alert_category) var/list/breath_reagents = GLOB.gas_data.breath_reagents + var/static/datum/reagents/reagents_holder = new + reagents_holder.clear_reagents() + reagents_holder.chem_temp = breath.return_temperature() for(var/gas in breath.get_gases()) if(gas in breath_reagents) var/datum/reagent/R = breath_reagents[gas] - H.reagents.add_reagent(R, breath.get_moles(gas) * initial(R.molarity)) + reagents_holder.add_reagent(R, breath.get_moles(gas) * initial(R.molarity)) mole_adjustments[gas] = (gas in mole_adjustments) ? mole_adjustments[gas] - breath.get_moles(gas) : -breath.get_moles(gas) - + reagents_holder.reaction(H, VAPOR, from_gas = 1) + H.smell(breath) for(var/gas in mole_adjustments) breath.adjust_moles(gas, mole_adjustments[gas]) @@ -523,6 +529,7 @@ safe_breath_min = 13 safe_breath_max = 100 emp_vulnerability = 2 + smell_sensitivity = 1.5 /obj/item/organ/lungs/cybernetic/tier3 name = "upgraded cybernetic lungs" @@ -540,6 +547,7 @@ SA_sleep_min = 50 BZ_brain_damage_min = 30 emp_vulnerability = 3 + smell_sensitivity = 2 cold_level_1_threshold = 200 cold_level_2_threshold = 140 diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm index 1f4950eaa7..99c1236d9c 100644 --- a/code/modules/vore/eating/living.dm +++ b/code/modules/vore/eating/living.dm @@ -18,7 +18,7 @@ // Hook for generic creation of stuff on new creatures // /hook/living_new/proc/vore_setup(mob/living/M) - add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/smell, /mob/living/proc/escapeOOC)) + add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/smell_someone, /mob/living/proc/escapeOOC)) if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach. return TRUE @@ -394,7 +394,7 @@ // // Equally important as the above // -/mob/living/proc/smell() +/mob/living/proc/smell_someone() set name = "Smell Someone" set category = "Vore" set desc = "Smell someone nearby!" diff --git a/icons/effects/atmospherics.dmi b/icons/effects/atmospherics.dmi index acf48a0bd0..6c2412c04b 100644 Binary files a/icons/effects/atmospherics.dmi and b/icons/effects/atmospherics.dmi differ