From 1dc78ec88aa377e0d993e21391b2d80f1b43eb61 Mon Sep 17 00:00:00 2001 From: Rane <60792108+Elijahrane@users.noreply.github.com> Date: Fri, 17 Jun 2022 03:00:23 -0400 Subject: [PATCH] Port miasma from nyano (#8926) Co-authored-by: Kara --- Content.Server/Atmos/Miasma/MiasmaSystem.cs | 92 ++++++++++++ .../Atmos/Miasma/NoRotContainerComponent.cs | 9 ++ .../Atmos/Miasma/PerishableComponent.cs | 42 ++++++ .../Atmos/Miasma/RottingComponent.cs | 9 ++ .../ReagentEffects/ChemCauseRandomDisease.cs | 32 +++++ .../StationEvents/Events/GasLeak.cs | 1 + .../StationEvents/Events/RadiationStorm.cs | 136 ------------------ .../Components/GasArtifactComponent.cs | 3 +- .../Components/ArtifactGasTriggerComponent.cs | 3 +- Content.Shared/Atmos/Atmospherics.cs | 3 +- .../Components/SharedVentScrubberComponent.cs | 1 + .../Locale/en-US/reagents/meta/gases.ftl | 3 + Resources/Prototypes/Atmospherics/gases.yml | 11 ++ .../Entities/Mobs/NPCs/simplemob.yml | 1 + .../Entities/Mobs/Species/human.yml | 1 + .../Objects/Specific/Medical/morgue.yml | 1 + .../Storage/Canisters/gas_canisters.yml | 46 ++++++ .../Storage/Closets/Lockers/lockers.yml | 5 +- .../Entities/Structures/Storage/morgue.yml | 3 +- .../Structures/Wallmounts/air_alarm.yml | 1 + Resources/Prototypes/Reagents/gases.yml | 40 ++++++ 21 files changed, 301 insertions(+), 142 deletions(-) create mode 100644 Content.Server/Atmos/Miasma/MiasmaSystem.cs create mode 100644 Content.Server/Atmos/Miasma/NoRotContainerComponent.cs create mode 100644 Content.Server/Atmos/Miasma/PerishableComponent.cs create mode 100644 Content.Server/Atmos/Miasma/RottingComponent.cs create mode 100644 Content.Server/Chemistry/ReagentEffects/ChemCauseRandomDisease.cs delete mode 100644 Content.Server/StationEvents/Events/RadiationStorm.cs diff --git a/Content.Server/Atmos/Miasma/MiasmaSystem.cs b/Content.Server/Atmos/Miasma/MiasmaSystem.cs new file mode 100644 index 0000000000..e189984a12 --- /dev/null +++ b/Content.Server/Atmos/Miasma/MiasmaSystem.cs @@ -0,0 +1,92 @@ +using Content.Shared.MobState; +using Content.Shared.Damage; +using Content.Shared.Atmos; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Temperature.Components; +using Content.Server.Body.Components; +using Robust.Shared.Containers; + +namespace Content.Server.Atmos.Miasma +{ + public sealed class MiasmaSystem : EntitySystem + { + [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + + public override void Update(float frameTime) + { + base.Update(frameTime); + foreach (var (rotting, perishable) in EntityQuery()) + { + if (!perishable.Progressing) + continue; + + if (TryComp(perishable.Owner, out var temp) && temp.CurrentTemperature < 274f) + continue; + + perishable.DeathAccumulator += frameTime; + if (perishable.DeathAccumulator < perishable.RotAfter.TotalSeconds) + continue; + + perishable.RotAccumulator += frameTime; + if (perishable.RotAccumulator < 1f) + continue; + + perishable.RotAccumulator -= 1f; + + DamageSpecifier damage = new(); + damage.DamageDict.Add("Blunt", 0.25); // Slowly accumulate enough to gib after like half an hour + damage.DamageDict.Add("Cellular", 0.25); // Cloning rework might use this eventually + + _damageableSystem.TryChangeDamage(perishable.Owner, damage, true, true); + + if (!TryComp(perishable.Owner, out var physics)) + continue; + // We need a way to get the mass of the mob alone without armor etc in the future + + var tileMix = _atmosphereSystem.GetTileMixture(Transform(perishable.Owner).Coordinates); + if (tileMix != null) + tileMix.AdjustMoles(Gas.Miasma, perishable.MolsPerSecondPerUnitMass * physics.FixturesMass); + } + } + + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnGibbed); + SubscribeLocalEvent(OnEntInserted); + SubscribeLocalEvent(OnEntRemoved); + } + + private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args) + { + if (args.Component.IsDead()) + EnsureComp(uid); + } + + private void OnGibbed(EntityUid uid, PerishableComponent component, BeingGibbedEvent args) + { + if (!TryComp(uid, out var physics)) + return; + + var molsToDump = (component.MolsPerSecondPerUnitMass * physics.FixturesMass) * component.DeathAccumulator; + var tileMix = _atmosphereSystem.GetTileMixture(Transform(uid).Coordinates); + if (tileMix != null) + tileMix.AdjustMoles(Gas.Miasma, molsToDump); + } + + private void OnEntInserted(EntityUid uid, AntiRottingContainerComponent component, EntInsertedIntoContainerMessage args) + { + if (TryComp(args.Entity, out var perishable)) + perishable.Progressing = false; + } + + private void OnEntRemoved(EntityUid uid, AntiRottingContainerComponent component, EntRemovedFromContainerMessage args) + { + if (TryComp(args.Entity, out var perishable)) + perishable.Progressing = true; + } + } +} diff --git a/Content.Server/Atmos/Miasma/NoRotContainerComponent.cs b/Content.Server/Atmos/Miasma/NoRotContainerComponent.cs new file mode 100644 index 0000000000..668d870cac --- /dev/null +++ b/Content.Server/Atmos/Miasma/NoRotContainerComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Atmos.Miasma +{ + [RegisterComponent] + /// + /// Entities inside this container will not rot. + /// + public sealed class AntiRottingContainerComponent : Component + {} +} diff --git a/Content.Server/Atmos/Miasma/PerishableComponent.cs b/Content.Server/Atmos/Miasma/PerishableComponent.cs new file mode 100644 index 0000000000..de8c45b9ca --- /dev/null +++ b/Content.Server/Atmos/Miasma/PerishableComponent.cs @@ -0,0 +1,42 @@ +namespace Content.Server.Atmos.Miasma +{ + [RegisterComponent] + /// + /// This makes mobs eventually start rotting when they die. + /// It may be expanded to food at some point, but it's just for mobs right now. + /// + public sealed class PerishableComponent : Component + { + /// + /// Is this progressing? + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool Progressing = true; + + /// + /// How long this creature has been dead. + /// + [DataField("deathAccumulator")] + [ViewVariables(VVAccess.ReadWrite)] + public float DeathAccumulator = 0f; + + /// + /// When DeathAccumulator is greater than this, start rotting. + /// + public TimeSpan RotAfter = TimeSpan.FromMinutes(3); + + /// + /// Gasses are released every second. + /// + [DataField("rotAccumulator")] + public float RotAccumulator = 0f; + + /// + /// How many moles of gas released per second, adjusted for mass. + /// Humans have a mass of 70. I am aiming for ten mols a minute, so + /// 1/6 of a minute, divided by 70 as a baseline. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float MolsPerSecondPerUnitMass = 0.0025f; + } +} diff --git a/Content.Server/Atmos/Miasma/RottingComponent.cs b/Content.Server/Atmos/Miasma/RottingComponent.cs new file mode 100644 index 0000000000..ae9dbe78a2 --- /dev/null +++ b/Content.Server/Atmos/Miasma/RottingComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Atmos.Miasma +{ + [RegisterComponent] + /// + /// Tracking component for stuff that has started to rot. + /// + public sealed class RottingComponent : Component + {} +} diff --git a/Content.Server/Chemistry/ReagentEffects/ChemCauseRandomDisease.cs b/Content.Server/Chemistry/ReagentEffects/ChemCauseRandomDisease.cs new file mode 100644 index 0000000000..acb3b87b3f --- /dev/null +++ b/Content.Server/Chemistry/ReagentEffects/ChemCauseRandomDisease.cs @@ -0,0 +1,32 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Server.Disease; +using Content.Shared.Disease.Components; +using Robust.Shared.Random; +using JetBrains.Annotations; + +namespace Content.Server.Chemistry.ReagentEffects +{ + /// + /// Default metabolism for medicine reagents. + /// + [UsedImplicitly] + public sealed class ChemCauseRandomDisease : ReagentEffect + { + /// + /// A disease to choose from. + /// + [DataField("diseases", required: true)] + [ViewVariables(VVAccess.ReadWrite)] + public List Diseases = default!; + + public override void Effect(ReagentEffectArgs args) + { + if (args.EntityManager.TryGetComponent(args.SolutionEntity, out var diseased)) + return; + + var random = IoCManager.Resolve(); + + EntitySystem.Get().TryAddDisease(args.SolutionEntity, random.Pick(Diseases)); + } + } +} diff --git a/Content.Server/StationEvents/Events/GasLeak.cs b/Content.Server/StationEvents/Events/GasLeak.cs index ab59f6a91b..cfe80c6711 100644 --- a/Content.Server/StationEvents/Events/GasLeak.cs +++ b/Content.Server/StationEvents/Events/GasLeak.cs @@ -20,6 +20,7 @@ namespace Content.Server.StationEvents.Events protected override string EndAnnouncement => Loc.GetString("station-event-gas-leak-end-announcement"); private static readonly Gas[] LeakableGases = { + Gas.Miasma, Gas.Plasma, Gas.Tritium, }; diff --git a/Content.Server/StationEvents/Events/RadiationStorm.cs b/Content.Server/StationEvents/Events/RadiationStorm.cs deleted file mode 100644 index a573ca0f56..0000000000 --- a/Content.Server/StationEvents/Events/RadiationStorm.cs +++ /dev/null @@ -1,136 +0,0 @@ -using Content.Server.Radiation; -using Content.Server.Station.Components; -using Content.Server.Station.Systems; -using Content.Shared.Coordinates; -using Content.Shared.Sound; -using JetBrains.Annotations; -using Robust.Shared.Map; -using Robust.Shared.Random; - -namespace Content.Server.StationEvents.Events -{ - [UsedImplicitly] - public sealed class RadiationStorm : StationEvent - { - // Based on Goonstation style radiation storm with some TG elements (announcer, etc.) - - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly IRobustRandom _robustRandom = default!; - - private StationSystem _stationSystem = default!; - - public override string Name => "RadiationStorm"; - public override string StartAnnouncement => Loc.GetString("station-event-radiation-storm-start-announcement"); - protected override string EndAnnouncement => Loc.GetString("station-event-radiation-storm-end-announcement"); - public override SoundSpecifier? StartAudio => new SoundPathSpecifier("/Audio/Announcements/radiation.ogg"); - protected override float StartAfter => 10.0f; - - // Event specific details - private float _timeUntilPulse; - private const float MinPulseDelay = 0.2f; - private const float MaxPulseDelay = 0.8f; - private EntityUid _target = EntityUid.Invalid; - - private void ResetTimeUntilPulse() - { - _timeUntilPulse = _robustRandom.NextFloat() * (MaxPulseDelay - MinPulseDelay) + MinPulseDelay; - } - - public override void Announce() - { - base.Announce(); - EndAfter = _robustRandom.Next(30, 80) + StartAfter; // We want to be forgiving about the radstorm. - } - - public override void Startup() - { - _entityManager.EntitySysManager.Resolve(ref _stationSystem); - ResetTimeUntilPulse(); - - if (_stationSystem.Stations.Count == 0) - { - Running = false; - return; - } - - _target = _robustRandom.Pick(_stationSystem.Stations); - base.Startup(); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - if (!Started || !Running) return; - if (_target.Valid == false) - { - Running = false; - return; - } - - _timeUntilPulse -= frameTime; - - if (_timeUntilPulse <= 0.0f) - { - var mapManager = IoCManager.Resolve(); - // Account for split stations by just randomly picking a piece of it. - var possibleTargets = _entityManager.GetComponent(_target).Grids; - if (possibleTargets.Count == 0) - { - Running = false; - return; - } - - var stationEnt = _robustRandom.Pick(possibleTargets); - - if (!_entityManager.TryGetComponent(stationEnt, out var grid)) - return; - - if (mapManager.IsGridPaused(grid.Owner)) - return; - - SpawnPulse(grid.Grid); - } - } - - private void SpawnPulse(IMapGrid mapGrid) - { - if (!TryFindRandomGrid(mapGrid, out var coordinates)) - return; - - var pulse = _entityManager.SpawnEntity("RadiationPulse", coordinates); - _entityManager.GetComponent(pulse).DoPulse(); - ResetTimeUntilPulse(); - } - - public void SpawnPulseAt(EntityCoordinates at) - { - var pulse = IoCManager.Resolve() - .SpawnEntity("RadiationPulse", at); - _entityManager.GetComponent(pulse).DoPulse(); - } - - private bool TryFindRandomGrid(IMapGrid mapGrid, out EntityCoordinates coordinates) - { - if (!(mapGrid.GridEntityId).IsValid()) - { - coordinates = default; - return false; - } - - var bounds = mapGrid.LocalAABB; - var randomX = _robustRandom.Next((int) bounds.Left, (int) bounds.Right); - var randomY = _robustRandom.Next((int) bounds.Bottom, (int) bounds.Top); - - coordinates = mapGrid.ToCoordinates(randomX, randomY); - - // TODO: Need to get valid tiles? (maybe just move right if the tile we chose is invalid?) - if (!coordinates.IsValid(_entityManager)) - { - coordinates = default; - return false; - } - return true; - } - } -} diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/GasArtifactComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/GasArtifactComponent.cs index aa80af0697..e68254d0b3 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/GasArtifactComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Components/GasArtifactComponent.cs @@ -26,7 +26,8 @@ public sealed class GasArtifactComponent : Component Gas.Plasma, Gas.Nitrogen, Gas.CarbonDioxide, - Gas.Tritium + Gas.Tritium, + Gas.Miasma, }; /// diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactGasTriggerComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactGasTriggerComponent.cs index d1bcea62b2..620ad91978 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactGasTriggerComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Components/ArtifactGasTriggerComponent.cs @@ -17,7 +17,8 @@ public sealed class ArtifactGasTriggerComponent : Component Gas.Oxygen, Gas.Plasma, Gas.Nitrogen, - Gas.CarbonDioxide + Gas.CarbonDioxide, + Gas.Miasma }; /// diff --git a/Content.Shared/Atmos/Atmospherics.cs b/Content.Shared/Atmos/Atmospherics.cs index f1a3f21c50..61d57ef892 100644 --- a/Content.Shared/Atmos/Atmospherics.cs +++ b/Content.Shared/Atmos/Atmospherics.cs @@ -168,7 +168,7 @@ namespace Content.Shared.Atmos /// /// Total number of gases. Increase this if you want to add more! /// - public const int TotalNumberOfGases = 6; + public const int TotalNumberOfGases = 7; /// /// This is the actual length of the gases arrays in mixtures. @@ -285,5 +285,6 @@ namespace Content.Shared.Atmos Plasma = 3, Tritium = 4, WaterVapor = 5, + Miasma = 6 } } diff --git a/Content.Shared/Atmos/Piping/Unary/Components/SharedVentScrubberComponent.cs b/Content.Shared/Atmos/Piping/Unary/Components/SharedVentScrubberComponent.cs index c8c4c2cc90..08b7db440a 100644 --- a/Content.Shared/Atmos/Piping/Unary/Components/SharedVentScrubberComponent.cs +++ b/Content.Shared/Atmos/Piping/Unary/Components/SharedVentScrubberComponent.cs @@ -20,6 +20,7 @@ namespace Content.Shared.Atmos.Piping.Unary.Components Gas.Plasma, Gas.Tritium, Gas.WaterVapor, + Gas.Miasma }; // Presets for 'dumb' air alarm modes diff --git a/Resources/Locale/en-US/reagents/meta/gases.ftl b/Resources/Locale/en-US/reagents/meta/gases.ftl index 2567ef441f..f92a0b6ca4 100644 --- a/Resources/Locale/en-US/reagents/meta/gases.ftl +++ b/Resources/Locale/en-US/reagents/meta/gases.ftl @@ -12,3 +12,6 @@ reagent-desc-carbon-dioxide = You have genuinely no idea what this is. reagent-name-nitrogen = nitrogen reagent-desc-nitrogen = A colorless, odorless unreactive gas. Highly stable. + +reagent-name-miasma = miasma +reagent-desc-miasma = Uh oh, stinky! diff --git a/Resources/Prototypes/Atmospherics/gases.yml b/Resources/Prototypes/Atmospherics/gases.yml index 2ff48cede3..bb2bbe5675 100644 --- a/Resources/Prototypes/Atmospherics/gases.yml +++ b/Resources/Prototypes/Atmospherics/gases.yml @@ -57,3 +57,14 @@ gasOverlayState: water_vapor color: bffffd reagent: Water + +- type: gas + id: 6 + name: Miasma + specificHeat: 20 + heatCapacityRatio: 1.4 + molarMass: 44 + gasOverlaySprite: /Textures/Effects/atmospherics.rsi + gasOverlayState: miasma + color: 56941E + reagent: Miasma \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index 6a02178987..fff1391f47 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -152,6 +152,7 @@ 90: 0.2 - type: MobPrice price: 1000 # Living critters are valuable in space. + - type: Perishable - type: entity save: false diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 4f3129b534..5e0bb2ff1c 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -326,6 +326,7 @@ - type: MobPrice price: 1500 # Kidnapping a living person and selling them for cred is a good move. deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. + - type: Perishable - type: entity save: false diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml index 883faa53f7..3c141613c7 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/morgue.yml @@ -60,6 +60,7 @@ key: bag - type: BodyBagVisualizer - type: Pullable + - type: AntiRottingContainer - type: entity id: BodyBag_Folded diff --git a/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml b/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml index bd60492a3f..1a29d4a95a 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml @@ -338,6 +338,43 @@ - !type:DoActsBehavior acts: [ "Destruction" ] +- type: entity + parent: GasCanister + id: MiasmaCanister + name: miasma canister + components: + - type: Sprite + state: redws + - type: GasCanister + gasMixture: + volume: 1000 + moles: + - 0 # oxygen + - 0 # nitrogen + - 0 # CO2 + - 0 # Plasma + - 0 # Tritium + - 0 # Water vapor + - 1871.71051 # Miasma + temperature: 293.15 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 300 + behaviors: + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/metalbreak.ogg + - !type:SpawnEntitiesBehavior + spawn: + MiasmaCanisterBroken: + min: 1 + max: 1 + - !type:DoActsBehavior + acts: [ "Destruction" ] + + # Broke Entities - type: entity @@ -453,3 +490,12 @@ components: - type: Sprite state: water_vapor-1 + +- type: entity + parent: GasCanisterBrokenBase + id: MiasmaCanisterBroken + name: broken miasma canister + noSpawn: true + components: + - type: Sprite + state: redws-1 diff --git a/Resources/Prototypes/Entities/Structures/Storage/Closets/Lockers/lockers.yml b/Resources/Prototypes/Entities/Structures/Storage/Closets/Lockers/lockers.yml index 705ae11d9b..6e1bfd514a 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Closets/Lockers/lockers.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Closets/Lockers/lockers.yml @@ -47,8 +47,8 @@ state_open: mining_open state_closed: mining_door - type: AccessReader - access: [["Salvage"]] - + access: [["Salvage"]] + # Command - type: entity id: LockerCaptain @@ -169,6 +169,7 @@ access: [ [ "Kitchen" ] ] - type: ExplosionResistance resistance: 0.90 + - type: AntiRottingContainer # Botanist - type: entity diff --git a/Resources/Prototypes/Entities/Structures/Storage/morgue.yml b/Resources/Prototypes/Entities/Structures/Storage/morgue.yml index 38d64ee7de..efec0f2224 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/morgue.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/morgue.yml @@ -49,6 +49,7 @@ light_soul: morgue_soul_light - type: Transform anchored: true + - type: AntiRottingContainer - type: entity id: MorgueTray @@ -72,7 +73,7 @@ - type: Clickable - type: InteractionOutline - type: MorgueTray - + - type: AntiRottingContainer - type: entity id: Crematorium diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml index ee01601bce..d07ac4ecee 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml @@ -26,6 +26,7 @@ Plasma: danger # everything below is usually bad Tritium: danger WaterVapor: danger + Miasma: danger - type: AtmosAlarmable alarmedBy: ["AirAlarm"] - type: AtmosDevice diff --git a/Resources/Prototypes/Reagents/gases.yml b/Resources/Prototypes/Reagents/gases.yml index 02ec854791..da7c940a3a 100644 --- a/Resources/Prototypes/Reagents/gases.yml +++ b/Resources/Prototypes/Reagents/gases.yml @@ -144,3 +144,43 @@ CarbonDioxide: 1.0 Nitrogen: -1.0 +- type: reagent + id: Miasma + name: reagent-name-miasma + desc: reagent-desc-miasma + physicalDesc: reagent-physical-desc-gaseous + color: "#56941E" + boilingPoint: -195.8 + meltingPoint: -210.0 + metabolisms: + Gas: + effects: + - !type:ChemCauseRandomDisease + conditions: + - !type:ReagentThreshold + reagent: Miasma + min: 1 + diseases: + - VentCough + - AMIV + - SpaceCold + - SpaceFlu + - Bird Flew + - VanAusdallsRobovirus + - BleedersBite + - !type:HealthChange + conditions: + - !type:ReagentThreshold + reagent: Miasma + min: 1 + scaleByQuantity: true + ignoreResistances: true + damage: + types: + Poison: 0.25 + - !type:ChemVomit + probability: 0.12 + conditions: + - !type:ReagentThreshold + reagent: Miasma + min: 0.8