From 6f38eed9d9b056ce6b4bcba2f8693cf889cdd65b Mon Sep 17 00:00:00 2001 From: TemporalOroboros Date: Tue, 23 Dec 2025 22:37:11 -0800 Subject: [PATCH] Splits temperature damage processing into its own component (#30515) * Creates TemperatureDamageThresholdsComponent * Obsolete TemperatureComponent fields * Use TemperatureDamageThresholdsComponent Moves all the uses of the relocated TemperatureComponent fields to use the TDTC versions * Removes the obsolete TemperatureComponent fields * Update YAML definitions * Update doc comments * Split TemperatureSystem Creates TemperatureDamageSystem and moves the damage handling from TemperatureSystem * Cull unused using statements * Use component-based damage tick scheduling * Fix temperature damage processing Check was inverted resulting in things never starting to take temperature damage * Poke tests * Add TemperatureDamageThresholds to new prototypes * Move TemperatureDamageThresholdsComponent to Shared Parity with TemperatureComponent * While I'm here Fixes warning regarding obsolete ProtoId validator attribute * Fix YAML errors * Fix merge errors * Rename TemperatureDamageThresholdsComponent -> TemperatureDamageComponent * Use ContentHelpers.RoundToLevels for temperature alerts * Fix YML * A fuckton of cleanup * working cleanup * fix * misc additions --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> --- .../ContainerTemperatureComponent.cs | 11 + ...nerTemperatureDamageThresholdsComponent.cs | 11 - .../Systems/TemperatureSystem.Damage.cs | 279 ++++++++++++++++ .../Temperature/Systems/TemperatureSystem.cs | 310 +----------------- .../Zombies/ZombieSystem.Transform.cs | 2 +- .../Components/TemperatureComponent.cs | 52 +-- .../Components/TemperatureDamageComponent.cs | 94 ++++++ .../Systems/SharedTemperatureSystem.cs | 6 +- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 16 +- .../Prototypes/Entities/Mobs/NPCs/carp.yml | 1 + .../Prototypes/Entities/Mobs/NPCs/pets.yml | 1 + .../Prototypes/Entities/Mobs/NPCs/scurret.yml | 5 +- .../Prototypes/Entities/Mobs/NPCs/space.yml | 2 + .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 6 +- .../Entities/Mobs/Player/dragon.yml | 1 + .../Prototypes/Entities/Mobs/Species/base.yml | 5 +- .../Prototypes/Entities/Mobs/Species/moth.yml | 7 +- .../Entities/Mobs/Species/reptilian.yml | 5 +- .../Entities/Mobs/Species/vulpkanin.yml | 3 +- Resources/Prototypes/Entities/Mobs/base.yml | 10 +- .../Entities/Objects/Consumable/Food/egg.yml | 8 + .../Entities/Objects/Consumable/Food/meat.yml | 1 + .../Entities/Objects/Misc/ice_crust.yml | 1 + .../Entities/Objects/Misc/kudzu.yml | 2 + .../Entities/Objects/Misc/spaceshroom.yml | 1 + .../Structures/Machines/Medical/cryo_pod.yml | 2 +- .../Entities/Structures/spider_web.yml | 1 + 27 files changed, 461 insertions(+), 382 deletions(-) create mode 100644 Content.Server/Temperature/Components/ContainerTemperatureComponent.cs delete mode 100644 Content.Server/Temperature/Components/ContainerTemperatureDamageThresholdsComponent.cs create mode 100644 Content.Server/Temperature/Systems/TemperatureSystem.Damage.cs create mode 100644 Content.Shared/Temperature/Components/TemperatureDamageComponent.cs diff --git a/Content.Server/Temperature/Components/ContainerTemperatureComponent.cs b/Content.Server/Temperature/Components/ContainerTemperatureComponent.cs new file mode 100644 index 0000000000..7c7b1e81e8 --- /dev/null +++ b/Content.Server/Temperature/Components/ContainerTemperatureComponent.cs @@ -0,0 +1,11 @@ +namespace Content.Server.Temperature.Components; + +[RegisterComponent] +public sealed partial class ContainerTemperatureComponent : Component +{ + [DataField] + public float? HeatDamageThreshold; + + [DataField] + public float? ColdDamageThreshold; +} diff --git a/Content.Server/Temperature/Components/ContainerTemperatureDamageThresholdsComponent.cs b/Content.Server/Temperature/Components/ContainerTemperatureDamageThresholdsComponent.cs deleted file mode 100644 index 024b8a013b..0000000000 --- a/Content.Server/Temperature/Components/ContainerTemperatureDamageThresholdsComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Content.Server.Temperature.Components; - -[RegisterComponent] -public sealed partial class ContainerTemperatureDamageThresholdsComponent: Component -{ - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float? HeatDamageThreshold; - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float? ColdDamageThreshold; -} diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.Damage.cs b/Content.Server/Temperature/Systems/TemperatureSystem.Damage.cs new file mode 100644 index 0000000000..d436977daf --- /dev/null +++ b/Content.Server/Temperature/Systems/TemperatureSystem.Damage.cs @@ -0,0 +1,279 @@ +using Content.Server.Administration.Logs; +using Content.Server.Body.Components; +using Content.Server.Temperature.Components; +using Content.Shared.Alert; +using Content.Shared.Damage.Components; +using Content.Shared.Damage.Systems; +using Content.Shared.Database; +using Content.Shared.Rounding; +using Content.Shared.Temperature; +using Content.Shared.Temperature.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Server.Temperature.Systems; + +/// +/// Handles entities taking damage from being too hot or too cold. +/// Also handles alerts relevant to the same. +/// +public sealed partial class TemperatureSystem +{ + [Dependency] private readonly AlertsSystem _alerts = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + + private EntityQuery _tempDamageQuery; + private EntityQuery _containerTemperatureQuery; + private EntityQuery _thermalRegulatorQuery; + + /// + /// All the components that will have their damage updated at the end of the tick. + /// This is done because both AtmosExposed and Flammable call ChangeHeat in the same tick, meaning + /// that we need some mechanism to ensure it doesn't double-dip on damage for both calls. + /// + public HashSet> ShouldUpdateDamage = new(); + + /// + /// Alert prototype for Temperature. + /// + public static readonly ProtoId TemperatureAlertCategory = "Temperature"; + + /// + /// The maximum severity applicable to temperature alerts. + /// + public static readonly short MaxTemperatureAlertSeverity = 3; + + /// + /// On a scale of 0. to 1. where 0. is the ideal temperature and 1. is a temperature damage threshold this is the point where the component starts raising temperature alerts. + /// + public static readonly float MinAlertTemperatureScale = 0.33f; + + private void InitializeDamage() + { + SubscribeLocalEvent(ServerAlert); + + SubscribeLocalEvent(EnqueueDamage); + SubscribeLocalEvent(OnUnpaused); + + // Allows overriding thresholds based on the parent's thresholds. + SubscribeLocalEvent(OnParentChange); + SubscribeLocalEvent(OnParentThresholdStartup); + SubscribeLocalEvent(OnParentThresholdShutdown); + + _tempDamageQuery = GetEntityQuery(); + _containerTemperatureQuery = GetEntityQuery(); + _thermalRegulatorQuery = GetEntityQuery(); + } + + private void UpdateDamage() + { + foreach (var entity in ShouldUpdateDamage) + { + if (Deleted(entity) || Paused(entity)) + continue; + + var deltaTime = _gameTiming.CurTime - entity.Comp.LastUpdate; + if (entity.Comp.TakingDamage && deltaTime < entity.Comp.UpdateInterval) + continue; + + ChangeDamage(entity, deltaTime); + } + + ShouldUpdateDamage.Clear(); + } + + private void ChangeDamage(Entity entity, TimeSpan deltaTime) + { + entity.Comp.LastUpdate = _gameTiming.CurTime; + + if (!HasComp(entity) || !TemperatureQuery.TryComp(entity, out var temperature)) + return; + + // See this link for where the scaling func comes from: + // https://www.desmos.com/calculator/0vknqtdvq9 + // Based on a logistic curve, which caps out at MaxDamage + var heatK = 0.005; + var a = 1; + var y = entity.Comp.DamageCap; + var c = y * 2; + + var heatDamageThreshold = entity.Comp.ParentHeatDamageThreshold ?? entity.Comp.HeatDamageThreshold; + var coldDamageThreshold = entity.Comp.ParentColdDamageThreshold ?? entity.Comp.ColdDamageThreshold; + + if (temperature.CurrentTemperature >= heatDamageThreshold) + { + if (!entity.Comp.TakingDamage) + { + _adminLogger.Add(LogType.Temperature, $"{ToPrettyString(entity):entity} started taking high temperature damage"); + entity.Comp.TakingDamage = true; + } + + var diff = Math.Abs(temperature.CurrentTemperature - heatDamageThreshold); + var tempDamage = c / (1 + a * Math.Pow(Math.E, -heatK * diff)) - y; + _damageable.TryChangeDamage(entity.Owner, entity.Comp.HeatDamage * tempDamage * deltaTime.TotalSeconds, ignoreResistances: true, interruptsDoAfters: false); + } + else if (temperature.CurrentTemperature <= coldDamageThreshold) + { + if (!entity.Comp.TakingDamage) + { + _adminLogger.Add(LogType.Temperature, $"{ToPrettyString(entity):entity} started taking low temperature damage"); + entity.Comp.TakingDamage = true; + } + + var diff = Math.Abs(temperature.CurrentTemperature - coldDamageThreshold); + var tempDamage = + Math.Sqrt(diff * (Math.Pow(entity.Comp.DamageCap.Double(), 2) / coldDamageThreshold)); + _damageable.TryChangeDamage(entity.Owner, entity.Comp.ColdDamage * tempDamage * deltaTime.TotalSeconds, ignoreResistances: true, interruptsDoAfters: false); + } + else if (entity.Comp.TakingDamage) + { + _adminLogger.Add(LogType.Temperature, $"{ToPrettyString(entity):entity} stopped taking temperature damage"); + entity.Comp.TakingDamage = false; + } + } + + private void ServerAlert(Entity entity, ref OnTemperatureChangeEvent args) + { + ProtoId type; + float threshold; + float idealTemp; + + if (!_tempDamageQuery.TryComp(entity, out var thresholds)) + { + _alerts.ClearAlertCategory(entity.Owner, TemperatureAlertCategory); + return; + } + + if (_thermalRegulatorQuery.TryComp(entity, out var regulator) && + regulator.NormalBodyTemperature > thresholds.ColdDamageThreshold && + regulator.NormalBodyTemperature < thresholds.HeatDamageThreshold) + { + idealTemp = regulator.NormalBodyTemperature; + } + else + { + idealTemp = (thresholds.ColdDamageThreshold + thresholds.HeatDamageThreshold) / 2; + } + + if (args.CurrentTemperature <= idealTemp) + { + type = thresholds.ColdAlert; + threshold = thresholds.ColdDamageThreshold; + } + else + { + type = thresholds.HotAlert; + threshold = thresholds.HeatDamageThreshold; + } + + // Calculates a scale where 0.0 is the ideal temperature and 1.0 is where temperature damage begins + // The cold and hot scales will differ in their range if the ideal temperature is not exactly halfway between the thresholds + var tempScale = (args.CurrentTemperature - idealTemp) / (threshold - idealTemp); + var alertLevel = (short)ContentHelpers.RoundToLevels(tempScale - MinAlertTemperatureScale, 1.00f - MinAlertTemperatureScale, MaxTemperatureAlertSeverity + 1); + + if (alertLevel > 0) + _alerts.ShowAlert(entity.AsNullable(), type, alertLevel); + else + _alerts.ClearAlertCategory(entity.AsNullable(), TemperatureAlertCategory); + } + + private void EnqueueDamage(Entity ent, ref OnTemperatureChangeEvent args) + { + if (ShouldUpdateDamage.Add(ent) && !ent.Comp.TakingDamage) + ent.Comp.LastUpdate = _gameTiming.CurTime; + } + + private void OnUnpaused(Entity ent, ref EntityUnpausedEvent args) + { + ent.Comp.LastUpdate += args.PausedTime; + } + + private void OnParentChange(Entity entity, ref EntParentChangedMessage args) + { + // We only need to update thresholds if the thresholds changed for the entity's ancestors. + var oldThresholds = args.OldParent != null + ? RecalculateParentThresholds(args.OldParent.Value) + : (null, null); + var xform = Transform(entity.Owner); + var newThresholds = RecalculateParentThresholds(xform.ParentUid); + + if (oldThresholds != newThresholds) + RecursiveThresholdUpdate((entity, entity.Comp, xform)); + } + + private void OnParentThresholdStartup(Entity entity, ref ComponentStartup args) + { + RecursiveThresholdUpdate(entity.Owner); + } + + private void OnParentThresholdShutdown(Entity entity, ref ComponentShutdown args) + { + RecursiveThresholdUpdate(entity.Owner); + } + + /// + /// Recalculate and apply parent thresholds for the root entity and all its children. + /// + /// The root entity we're currently updating + private void RecursiveThresholdUpdate(Entity root) + { + RecalculateAndApplyParentThresholds(root); + + var xform = root.Comp2 ?? Transform(root); + var enumerator = xform.ChildEnumerator; + while (enumerator.MoveNext(out var child)) + { + RecursiveThresholdUpdate(child); + } + } + + /// + /// Recalculate parent thresholds and apply them on the uid temperature component. + /// + /// The entity whose temperature damage thresholds we're updating + private void RecalculateAndApplyParentThresholds(Entity entity) + { + if (!_tempDamageQuery.Resolve(entity, ref entity.Comp, logMissing: false)) + return; + + var newThresholds = RecalculateParentThresholds(Transform(entity).ParentUid); + entity.Comp.ParentHeatDamageThreshold = newThresholds.Item1; + entity.Comp.ParentColdDamageThreshold = newThresholds.Item2; + } + + /// + /// Recalculate Parent Heat/Cold DamageThreshold by recursively checking each ancestor and fetching the + /// maximum HeatDamageThreshold and the minimum ColdDamageThreshold if any exists (aka the best value for each). + /// + /// parent we start with + private (float?, float?) RecalculateParentThresholds(EntityUid initialParentUid) + { + // Recursively check parents for the best threshold available + var parentUid = initialParentUid; + float? newHeatThreshold = null; + float? newColdThreshold = null; + while (parentUid.IsValid()) + { + if (_containerTemperatureQuery.TryComp(parentUid, out var newThresholds)) + { + if (newThresholds.HeatDamageThreshold != null) + { + newHeatThreshold = Math.Max(newThresholds.HeatDamageThreshold.Value, + newHeatThreshold ?? 0); + } + + if (newThresholds.ColdDamageThreshold != null) + { + newColdThreshold = Math.Min(newThresholds.ColdDamageThreshold.Value, + newColdThreshold ?? float.MaxValue); + } + } + + parentUid = Transform(parentUid).ParentUid; + } + + return (newHeatThreshold, newColdThreshold); + } +} diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs index 928b6ae9b5..484912c780 100644 --- a/Content.Server/Temperature/Systems/TemperatureSystem.cs +++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs @@ -1,64 +1,32 @@ -using System.Linq; -using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; -using Content.Server.Body.Components; using Content.Server.Temperature.Components; -using Content.Shared.Alert; using Content.Shared.Atmos; -using Content.Shared.Damage.Components; -using Content.Shared.Damage.Systems; -using Content.Shared.Database; using Content.Shared.Inventory; using Content.Shared.Rejuvenate; using Content.Shared.Temperature; -using Robust.Shared.Prototypes; using Content.Shared.Projectiles; using Content.Shared.Temperature.Components; using Content.Shared.Temperature.Systems; namespace Content.Server.Temperature.Systems; -public sealed class TemperatureSystem : SharedTemperatureSystem +public sealed partial class TemperatureSystem : SharedTemperatureSystem { - [Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly AtmosphereSystem _atmosphere = default!; - [Dependency] private readonly DamageableSystem _damageable = default!; - [Dependency] private readonly IAdminLogManager _adminLogger = default!; - [Dependency] private readonly TemperatureSystem _temperature = default!; - - /// - /// All the components that will have their damage updated at the end of the tick. - /// This is done because both AtmosExposed and Flammable call ChangeHeat in the same tick, meaning - /// that we need some mechanism to ensure it doesn't double dip on damage for both calls. - /// - public HashSet> ShouldUpdateDamage = new(); - - public float UpdateInterval = 1.0f; - - private float _accumulatedFrametime; - - public static readonly ProtoId TemperatureAlertCategory = "Temperature"; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(EnqueueDamage); SubscribeLocalEvent(OnAtmosExposedUpdate); SubscribeLocalEvent(OnRejuvenate); - SubscribeLocalEvent(ServerAlert); Subs.SubscribeWithRelay(OnTemperatureChangeAttempt, held: false); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(ChangeTemperatureOnCollide); - // Allows overriding thresholds based on the parent's thresholds. - SubscribeLocalEvent(OnParentChange); - SubscribeLocalEvent( - OnParentThresholdStartup); - SubscribeLocalEvent( - OnParentThresholdShutdown); + InitializeDamage(); } public override void Update(float frameTime) @@ -88,49 +56,23 @@ public sealed class TemperatureSystem : SharedTemperatureSystem ForceChangeTemperature(uid, temp.CurrentTemperature - degrees, temp); } - UpdateDamage(frameTime); - } - - private void UpdateDamage(float frameTime) - { - _accumulatedFrametime += frameTime; - - if (_accumulatedFrametime < UpdateInterval) - return; - _accumulatedFrametime -= UpdateInterval; - - if (!ShouldUpdateDamage.Any()) - return; - - foreach (var comp in ShouldUpdateDamage) - { - MetaDataComponent? metaData = null; - - var uid = comp.Owner; - if (Deleted(uid, metaData) || Paused(uid, metaData)) - continue; - - ChangeDamage(uid, comp); - } - - ShouldUpdateDamage.Clear(); + UpdateDamage(); } public void ForceChangeTemperature(EntityUid uid, float temp, TemperatureComponent? temperature = null) { - if (!Resolve(uid, ref temperature)) + if (!TemperatureQuery.Resolve(uid, ref temperature)) return; - float lastTemp = temperature.CurrentTemperature; - float delta = temperature.CurrentTemperature - temp; + var lastTemp = temperature.CurrentTemperature; + var delta = temperature.CurrentTemperature - temp; temperature.CurrentTemperature = temp; - RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta), - true); + RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta), broadcast: true); } public override void ChangeHeat(EntityUid uid, float heatAmount, bool ignoreHeatResistance = false, TemperatureComponent? temperature = null) { - if (!Resolve(uid, ref temperature, false)) + if (!TemperatureQuery.Resolve(uid, ref temperature, false)) return; if (!ignoreHeatResistance) @@ -144,11 +86,10 @@ public sealed class TemperatureSystem : SharedTemperatureSystem temperature.CurrentTemperature += heatAmount / GetHeatCapacity(uid, temperature); float delta = temperature.CurrentTemperature - lastTemp; - RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta), true); + RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta), broadcast: true); } - private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperature, - ref AtmosExposedUpdateEvent args) + private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperature, ref AtmosExposedUpdateEvent args) { var transform = args.Transform; @@ -158,17 +99,18 @@ public sealed class TemperatureSystem : SharedTemperatureSystem var temperatureDelta = args.GasMixture.Temperature - temperature.CurrentTemperature; var airHeatCapacity = _atmosphere.GetHeatCapacity(args.GasMixture, false); var heatCapacity = GetHeatCapacity(uid, temperature); + // TODO ATMOS: This heat transfer formula is really really wrong, it needs to be pulled out. Pending on HeatContainers. var heat = temperatureDelta * (airHeatCapacity * heatCapacity / (airHeatCapacity + heatCapacity)); ChangeHeat(uid, heat * temperature.AtmosTemperatureTransferEfficiency, temperature: temperature); } - private void OnInit(EntityUid uid, InternalTemperatureComponent comp, MapInitEvent args) + private void OnInit(Entity entity, ref MapInitEvent args) { - if (!TryComp(uid, out var temp)) + if (!TemperatureQuery.TryComp(entity, out var temp)) return; - comp.Temperature = temp.CurrentTemperature; + entity.Comp.Temperature = temp.CurrentTemperature; } private void OnRejuvenate(EntityUid uid, TemperatureComponent comp, RejuvenateEvent args) @@ -176,116 +118,6 @@ public sealed class TemperatureSystem : SharedTemperatureSystem ForceChangeTemperature(uid, Atmospherics.T20C, comp); } - private void ServerAlert(EntityUid uid, AlertsComponent status, OnTemperatureChangeEvent args) - { - ProtoId type; - float threshold; - float idealTemp; - - if (!TryComp(uid, out var temperature)) - { - _alerts.ClearAlertCategory(uid, TemperatureAlertCategory); - return; - } - - if (TryComp(uid, out var regulator) && - regulator.NormalBodyTemperature > temperature.ColdDamageThreshold && - regulator.NormalBodyTemperature < temperature.HeatDamageThreshold) - { - idealTemp = regulator.NormalBodyTemperature; - } - else - { - idealTemp = (temperature.ColdDamageThreshold + temperature.HeatDamageThreshold) / 2; - } - - if (args.CurrentTemperature <= idealTemp) - { - type = temperature.ColdAlert; - threshold = temperature.ColdDamageThreshold; - } - else - { - type = temperature.HotAlert; - threshold = temperature.HeatDamageThreshold; - } - - // Calculates a scale where 1.0 is the ideal temperature and 0.0 is where temperature damage begins - // The cold and hot scales will differ in their range if the ideal temperature is not exactly halfway between the thresholds - var tempScale = (args.CurrentTemperature - threshold) / (idealTemp - threshold); - switch (tempScale) - { - case <= 0f: - _alerts.ShowAlert(uid, type, 3); - break; - - case <= 0.4f: - _alerts.ShowAlert(uid, type, 2); - break; - - case <= 0.66f: - _alerts.ShowAlert(uid, type, 1); - break; - - case > 0.66f: - _alerts.ClearAlertCategory(uid, TemperatureAlertCategory); - break; - } - } - - private void EnqueueDamage(Entity temperature, ref OnTemperatureChangeEvent args) - { - ShouldUpdateDamage.Add(temperature); - } - - private void ChangeDamage(EntityUid uid, TemperatureComponent temperature) - { - if (!HasComp(uid)) - return; - - // See this link for where the scaling func comes from: - // https://www.desmos.com/calculator/0vknqtdvq9 - // Based on a logistic curve, which caps out at MaxDamage - var heatK = 0.005; - var a = 1; - var y = temperature.DamageCap; - var c = y * 2; - - var heatDamageThreshold = temperature.ParentHeatDamageThreshold ?? temperature.HeatDamageThreshold; - var coldDamageThreshold = temperature.ParentColdDamageThreshold ?? temperature.ColdDamageThreshold; - - if (temperature.CurrentTemperature >= heatDamageThreshold) - { - if (!temperature.TakingDamage) - { - _adminLogger.Add(LogType.Temperature, $"{ToPrettyString(uid):entity} started taking high temperature damage"); - temperature.TakingDamage = true; - } - - var diff = Math.Abs(temperature.CurrentTemperature - heatDamageThreshold); - var tempDamage = c / (1 + a * Math.Pow(Math.E, -heatK * diff)) - y; - _damageable.TryChangeDamage(uid, temperature.HeatDamage * tempDamage, ignoreResistances: true, interruptsDoAfters: false); - } - else if (temperature.CurrentTemperature <= coldDamageThreshold) - { - if (!temperature.TakingDamage) - { - _adminLogger.Add(LogType.Temperature, $"{ToPrettyString(uid):entity} started taking low temperature damage"); - temperature.TakingDamage = true; - } - - var diff = Math.Abs(temperature.CurrentTemperature - coldDamageThreshold); - var tempDamage = - Math.Sqrt(diff * (Math.Pow(temperature.DamageCap.Double(), 2) / coldDamageThreshold)); - _damageable.TryChangeDamage(uid, temperature.ColdDamage * tempDamage, ignoreResistances: true, interruptsDoAfters: false); - } - else if (temperature.TakingDamage) - { - _adminLogger.Add(LogType.Temperature, $"{ToPrettyString(uid):entity} stopped taking temperature damage"); - temperature.TakingDamage = false; - } - } - private void OnTemperatureChangeAttempt(EntityUid uid, TemperatureProtectionComponent component, ModifyChangedTemperatureEvent args) { var coefficient = args.TemperatureDelta < 0 @@ -300,118 +132,6 @@ public sealed class TemperatureSystem : SharedTemperatureSystem private void ChangeTemperatureOnCollide(Entity ent, ref ProjectileHitEvent args) { - _temperature.ChangeHeat(args.Target, ent.Comp.Heat, ent.Comp.IgnoreHeatResistance);// adjust the temperature - } - - private void OnParentChange(EntityUid uid, TemperatureComponent component, - ref EntParentChangedMessage args) - { - var temperatureQuery = GetEntityQuery(); - var transformQuery = GetEntityQuery(); - var thresholdsQuery = GetEntityQuery(); - // We only need to update thresholds if the thresholds changed for the entity's ancestors. - var oldThresholds = args.OldParent != null - ? RecalculateParentThresholds(args.OldParent.Value, transformQuery, thresholdsQuery) - : (null, null); - var newThresholds = RecalculateParentThresholds(transformQuery.GetComponent(uid).ParentUid, transformQuery, thresholdsQuery); - - if (oldThresholds != newThresholds) - { - RecursiveThresholdUpdate(uid, temperatureQuery, transformQuery, thresholdsQuery); - } - } - - private void OnParentThresholdStartup(EntityUid uid, ContainerTemperatureDamageThresholdsComponent component, - ComponentStartup args) - { - RecursiveThresholdUpdate(uid, GetEntityQuery(), GetEntityQuery(), - GetEntityQuery()); - } - - private void OnParentThresholdShutdown(EntityUid uid, ContainerTemperatureDamageThresholdsComponent component, - ComponentShutdown args) - { - RecursiveThresholdUpdate(uid, GetEntityQuery(), GetEntityQuery(), - GetEntityQuery()); - } - - /// - /// Recalculate and apply parent thresholds for the root entity and all its descendant. - /// - /// - /// - /// - /// - private void RecursiveThresholdUpdate(EntityUid root, EntityQuery temperatureQuery, - EntityQuery transformQuery, - EntityQuery tempThresholdsQuery) - { - RecalculateAndApplyParentThresholds(root, temperatureQuery, transformQuery, tempThresholdsQuery); - - var enumerator = Transform(root).ChildEnumerator; - while (enumerator.MoveNext(out var child)) - { - RecursiveThresholdUpdate(child, temperatureQuery, transformQuery, tempThresholdsQuery); - } - } - - /// - /// Recalculate parent thresholds and apply them on the uid temperature component. - /// - /// - /// - /// - /// - private void RecalculateAndApplyParentThresholds(EntityUid uid, - EntityQuery temperatureQuery, EntityQuery transformQuery, - EntityQuery tempThresholdsQuery) - { - if (!temperatureQuery.TryGetComponent(uid, out var temperature)) - { - return; - } - - var newThresholds = RecalculateParentThresholds(transformQuery.GetComponent(uid).ParentUid, transformQuery, tempThresholdsQuery); - temperature.ParentHeatDamageThreshold = newThresholds.Item1; - temperature.ParentColdDamageThreshold = newThresholds.Item2; - } - - /// - /// Recalculate Parent Heat/Cold DamageThreshold by recursively checking each ancestor and fetching the - /// maximum HeatDamageThreshold and the minimum ColdDamageThreshold if any exists (aka the best value for each). - /// - /// - /// - /// - private (float?, float?) RecalculateParentThresholds( - EntityUid initialParentUid, - EntityQuery transformQuery, - EntityQuery tempThresholdsQuery) - { - // Recursively check parents for the best threshold available - var parentUid = initialParentUid; - float? newHeatThreshold = null; - float? newColdThreshold = null; - while (parentUid.IsValid()) - { - if (tempThresholdsQuery.TryGetComponent(parentUid, out var newThresholds)) - { - if (newThresholds.HeatDamageThreshold != null) - { - newHeatThreshold = Math.Max(newThresholds.HeatDamageThreshold.Value, - newHeatThreshold ?? 0); - } - - if (newThresholds.ColdDamageThreshold != null) - { - newColdThreshold = Math.Min(newThresholds.ColdDamageThreshold.Value, - newColdThreshold ?? float.MaxValue); - } - } - - parentUid = transformQuery.GetComponent(parentUid).ParentUid; - } - - return (newHeatThreshold, newColdThreshold); + ChangeHeat(args.Target, ent.Comp.Heat, ent.Comp.IgnoreHeatResistance);// adjust the temperature } } diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index b4aee77cef..f39487bb24 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -242,7 +242,7 @@ public sealed partial class ZombieSystem _mind.MakeSentient(target); //Make the zombie not die in the cold. Good for space zombies - if (TryComp(target, out var tempComp)) + if (TryComp(target, out var tempComp)) tempComp.ColdDamage.ClampMax(0); //Heals the zombie from all the damage it took while human diff --git a/Content.Shared/Temperature/Components/TemperatureComponent.cs b/Content.Shared/Temperature/Components/TemperatureComponent.cs index b73d1f77d1..fd79c4b4b2 100644 --- a/Content.Shared/Temperature/Components/TemperatureComponent.cs +++ b/Content.Shared/Temperature/Components/TemperatureComponent.cs @@ -1,15 +1,10 @@ -using Content.Shared.Alert; using Content.Shared.Atmos; -using Content.Shared.Damage; -using Content.Shared.FixedPoint; -using Robust.Shared.Prototypes; namespace Content.Shared.Temperature.Components; /// /// Handles changing temperature, -/// informing others of the current temperature, -/// and taking fire damage from high temperature. +/// informing others of the current temperature. /// [RegisterComponent] public sealed partial class TemperatureComponent : Component @@ -20,24 +15,6 @@ public sealed partial class TemperatureComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public float CurrentTemperature = Atmospherics.T20C; - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float HeatDamageThreshold = 360f; - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float ColdDamageThreshold = 260f; - - /// - /// Overrides HeatDamageThreshold if the entity's within a parent with the TemperatureDamageThresholdsComponent component. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float? ParentHeatDamageThreshold; - - /// - /// Overrides ColdDamageThreshold if the entity's within a parent with the TemperatureDamageThresholdsComponent component. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float? ParentColdDamageThreshold; - /// /// Heat capacity per kg of mass. /// @@ -49,31 +26,4 @@ public sealed partial class TemperatureComponent : Component /// [DataField, ViewVariables(VVAccess.ReadWrite)] public float AtmosTemperatureTransferEfficiency = 0.1f; - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public DamageSpecifier ColdDamage = new(); - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public DamageSpecifier HeatDamage = new(); - - /// - /// Temperature won't do more than this amount of damage per second. - /// - /// - /// Okay it genuinely reaches this basically immediately for a plasma fire. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 DamageCap = FixedPoint2.New(8); - - /// - /// Used to keep track of when damage starts/stops. Useful for logs. - /// - [DataField] - public bool TakingDamage; - - [DataField] - public ProtoId HotAlert = "Hot"; - - [DataField] - public ProtoId ColdAlert = "Cold"; } diff --git a/Content.Shared/Temperature/Components/TemperatureDamageComponent.cs b/Content.Shared/Temperature/Components/TemperatureDamageComponent.cs new file mode 100644 index 0000000000..a9543e3046 --- /dev/null +++ b/Content.Shared/Temperature/Components/TemperatureDamageComponent.cs @@ -0,0 +1,94 @@ +using Content.Shared.Alert; +using Content.Shared.Damage; +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Temperature.Components; + +/// +/// Handles taking damage from being excessively hot/cold. +/// Also handles alerts about being too hot or too cold. +/// +[RegisterComponent] +public sealed partial class TemperatureDamageComponent : Component +{ + /// + /// The temperature above which the entity will start taking damage from being too hot. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float HeatDamageThreshold = 360f; + + /// + /// The temperature below which the entity will start taking damage from being too cold. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ColdDamageThreshold = 260f; + + /// + /// Overrides HeatDamageThreshold if the entity's within a parent with the ContainerTemperatureDamageThresholdsComponent component. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float? ParentHeatDamageThreshold; + + /// + /// Overrides ColdDamageThreshold if the entity's within a parent with the ContainerTemperatureDamageThresholdsComponent component. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float? ParentColdDamageThreshold; + + /// + /// The base damage that this entity will take if it's too cold. + /// Will be scaled according to how cold it is. + /// The scaling maxes out at times this damage per second. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier ColdDamage = new(); + + /// + /// The base damage that this entity will take per second if it's too hot. + /// Will be scaled according to how hot it is. + /// The scaling maxes out at times this damage per second. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier HeatDamage = new(); + + /// + /// Temperature won't do more than this multiple of the base overheating/overcooling damage per seond. + /// + /// + /// Okay it genuinely reaches this basically immediately for a plasma fire. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public FixedPoint2 DamageCap = FixedPoint2.New(8); + + /// + /// Used to keep track of when damage starts/stops. Useful for logs. + /// + [DataField] + public bool TakingDamage; + + /// + /// The id of the alert thrown when the entity is too hot. + /// + [DataField] + public ProtoId HotAlert = "Hot"; + + /// + /// The id of the alert thrown when the entity is too cold. + /// + [DataField] + public ProtoId ColdAlert = "Cold"; + + /// + /// The last time this entity processed temperature damage. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + public TimeSpan LastUpdate; + + /// + /// The time interval between temperature damage ticks for this entity. + /// + [DataField] + public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1.0); +} diff --git a/Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs b/Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs index 9561c6dfe1..216349d6f5 100644 --- a/Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs +++ b/Content.Shared/Temperature/Systems/SharedTemperatureSystem.cs @@ -16,6 +16,8 @@ public abstract class SharedTemperatureSystem : EntitySystem [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; + protected EntityQuery TemperatureQuery; + /// /// Band-aid for unpredicted atmos. Delays the application for a short period so that laggy clients can get the replicated temperature. /// @@ -27,6 +29,8 @@ public abstract class SharedTemperatureSystem : EntitySystem SubscribeLocalEvent(OnTemperatureChanged); SubscribeLocalEvent(OnRefreshMovementSpeedModifiers); + + TemperatureQuery = GetEntityQuery(); } private void OnTemperatureChanged(Entity ent, ref OnTemperatureChangeEvent args) @@ -87,7 +91,7 @@ public abstract class SharedTemperatureSystem : EntitySystem public float GetHeatCapacity(EntityUid uid, TemperatureComponent? comp = null, PhysicsComponent? physics = null) { - if (!Resolve(uid, ref comp) || !Resolve(uid, ref physics, false) || physics.FixturesMass <= 0) + if (!TemperatureQuery.Resolve(uid, ref comp) || !Resolve(uid, ref physics, false) || physics.FixturesMass <= 0) { return Atmospherics.MinimumHeatCapacity; } diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 3685f891b6..39c319f068 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1610,10 +1610,11 @@ Slash: 5 Piercing: 4 - type: Temperature - heatDamageThreshold: 360 - coldDamageThreshold: 285 currentTemperature: 310.15 specificHeat: 42 + - type: TemperatureDamage + heatDamageThreshold: 360 + coldDamageThreshold: 285 - type: Sprite drawdepth: Mobs layers: @@ -2368,10 +2369,11 @@ factions: - Passive - type: Temperature - heatDamageThreshold: 335 - coldDamageThreshold: 230 currentTemperature: 310.15 specificHeat: 46 + - type: TemperatureDamage + heatDamageThreshold: 335 + coldDamageThreshold: 230 coldDamage: types: Cold : 0.05 #per second, scales with temperature & other constants @@ -3055,13 +3057,14 @@ damageContainer: BiologicalMetaphysical damageModifierSet: Infernal - type: Temperature + currentTemperature: 310.15 + specificHeat: 42 + - type: TemperatureDamage heatDamageThreshold: 4000 #They come from hell, so.. coldDamageThreshold: 260 - currentTemperature: 310.15 coldDamage: types: Cold : 1 #per second, scales with temperature & other constants - specificHeat: 42 heatDamage: types: Heat : 1 #per second, scales with temperature & other constants @@ -3256,6 +3259,7 @@ Dead: Base: spacecat_dead - type: Temperature + - type: TemperatureDamage heatDamageThreshold: 423 coldDamageThreshold: 0 - type: Tag diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml index 1547e36339..1eb22649e7 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml @@ -185,6 +185,7 @@ damage: types: {} - type: Temperature + - type: TemperatureDamage heatDamageThreshold: 1200 - type: entity id: MobCarpDungeon diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index ccb5c3aebb..b6e53b794d 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -833,6 +833,7 @@ Bloodloss: -0.8 - type: Temperature + - type: TemperatureDamage heatDamageThreshold: 800 coldDamageThreshold: 0 - type: MeleeWeapon diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/scurret.yml b/Resources/Prototypes/Entities/Mobs/NPCs/scurret.yml index 8f84e1496a..883103adcc 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/scurret.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/scurret.yml @@ -36,10 +36,11 @@ 60: Critical 125: Dead - type: Temperature - heatDamageThreshold: 360 - coldDamageThreshold: 285 currentTemperature: 310.15 specificHeat: 42 + - type: TemperatureDamage + heatDamageThreshold: 360 + coldDamageThreshold: 285 # Good eatin', you monster. - type: Butcherable butcheringType: Spike diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml index 7a51d257ef..e57e0d3d97 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml @@ -45,6 +45,7 @@ Quantity: 300 - type: CombatMode - type: Temperature + - type: TemperatureDamage heatDamageThreshold: 500 coldDamageThreshold: 0 - type: MeleeWeapon @@ -512,6 +513,7 @@ sprite: Mobs/Effects/onfire.rsi normalState: Mouse_burning - type: Temperature + - type: TemperatureDamage heatDamageThreshold: 500 coldDamageThreshold: 0 - type: Reactive diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index 58e0088828..33653ed207 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -107,9 +107,10 @@ - type: TypingIndicator proto: alien - type: Temperature + currentTemperature: 310.15 + - type: TemperatureDamage heatDamageThreshold: 360 coldDamageThreshold: -150 - currentTemperature: 310.15 - type: Tag tags: - CannotSuicide @@ -524,9 +525,10 @@ - type: TypingIndicator proto: alien - type: Temperature + currentTemperature: 310.15 + - type: TemperatureDamage heatDamageThreshold: 360 coldDamageThreshold: -150 - currentTemperature: 310.15 - type: NoSlip - type: Perishable #Ummmm the acid kills a lot of the bacteria or something molsPerSecondPerUnitMass: 0.0005 diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index 07bff11974..5aa7f05f0e 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -109,6 +109,7 @@ - RadiationProtection - Adrenaline - type: Temperature + - type: TemperatureDamage heatDamageThreshold: 2400 - type: Metabolizer solutionOnBody: false diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index a0ace57c47..4df9ddcaac 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -239,10 +239,11 @@ - type: Blindable # Other - type: Temperature - heatDamageThreshold: 325 - coldDamageThreshold: 260 currentTemperature: 310.15 specificHeat: 42 + - type: TemperatureDamage + heatDamageThreshold: 325 + coldDamageThreshold: 260 coldDamage: types: Cold: 0.1 #per second, scales with temperature & other constants diff --git a/Resources/Prototypes/Entities/Mobs/Species/moth.yml b/Resources/Prototypes/Entities/Mobs/Species/moth.yml index 83031d61d9..6d7ba02f5f 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/moth.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/moth.yml @@ -58,11 +58,12 @@ damage: types: Heat: 2.5 # moths burn more easily - - type: Temperature # Moths hate the heat and thrive in the cold. - heatDamageThreshold: 320 - coldDamageThreshold: 230 + - type: Temperature currentTemperature: 310.15 specificHeat: 46 + - type: TemperatureDamage # Moths hate the heat and thrive in the cold. + heatDamageThreshold: 320 + coldDamageThreshold: 230 coldDamage: types: Cold : 0.05 #per second, scales with temperature & other constants diff --git a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml index 67d0cfba80..55bb32e3a3 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml @@ -54,10 +54,11 @@ types: Slash: 5 - type: Temperature - heatDamageThreshold: 400 - coldDamageThreshold: 285 currentTemperature: 310.15 specificHeat: 42 + - type: TemperatureDamage + heatDamageThreshold: 400 + coldDamageThreshold: 285 coldDamage: types: Cold : 0.1 #per second, scales with temperature & other constants diff --git a/Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml index a80d20627f..535d3ba327 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml @@ -34,9 +34,10 @@ Piercing: 2 Slash: 3 - type: Temperature # Same as moth temperatures until below is solved. + specificHeat: 44 + - type: TemperatureDamage heatDamageThreshold: 320 # TODO: 315 when there is a way to make the temperature alert not blink to the side of the screen and disappear when you "sweat" at 39C. coldDamageThreshold: 230 # TODO: 220 when the above is solved. - specificHeat: 44 coldDamage: types: Cold: 0.05 # Per second, scales with temperature & other constants diff --git a/Resources/Prototypes/Entities/Mobs/base.yml b/Resources/Prototypes/Entities/Mobs/base.yml index a21ca14c5d..26f9215247 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -169,13 +169,14 @@ components: - type: AtmosExposed - type: Temperature + currentTemperature: 310.15 + specificHeat: 42 + - type: TemperatureDamage heatDamageThreshold: 325 coldDamageThreshold: 0 - currentTemperature: 310.15 coldDamage: #per second, scales with temperature & other constants types: Cold : 0.1 - specificHeat: 42 heatDamage: #per second, scales with temperature & other constants types: Heat : 1.5 @@ -204,10 +205,11 @@ normalBodyTemperature: 310.15 thermalRegulationTemperatureThreshold: 2 - type: Temperature - heatDamageThreshold: 325 - coldDamageThreshold: 260 currentTemperature: 310.15 specificHeat: 42 + - type: TemperatureDamage + heatDamageThreshold: 325 + coldDamageThreshold: 260 coldDamage: types: Cold: 1 #per second, scales with temperature & other constants diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml index 25e40d12dc..e19859f16e 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml @@ -61,6 +61,13 @@ # all below are for egg cooking/exploding - type: AtmosExposed - type: Temperature + - type: TemperatureDamage + - type: InternalTemperature + # ~1mm shell and ~1cm of albumen + thickness: 0.011 + area: 0.04 + # conductivity of egg shell based on a paper from Romanoff and Romanoff (1949) + conductivity: 0.456 # Splat - type: entity @@ -128,3 +135,4 @@ - type: Temperature # preserve temperature from the boiling step currentTemperature: 344 + - type: TemperatureDamage diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml index adc3b373d4..41c8f65885 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml @@ -42,6 +42,7 @@ - type: AtmosExposed - type: Temperature currentTemperature: 290 + - type: TemperatureDamage # required for cooking to work - type: InternalTemperature thickness: 0.02 diff --git a/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml b/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml index ccca7d1af1..514443f9a1 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/ice_crust.yml @@ -45,6 +45,7 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: Temperature + - type: TemperatureDamage heatDamage: types: Heat: 5 diff --git a/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml b/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml index 157a9616ab..1f1b9a9c6a 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/kudzu.yml @@ -56,6 +56,7 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: Temperature + - type: TemperatureDamage heatDamage: types: Heat: 5 @@ -226,6 +227,7 @@ Cold: -1.0 Blunt: -0.5 # Needs to be balanced (approx 3x) with vacuum damage to stall but not kill Kudzu - type: Temperature + - type: TemperatureDamage heatDamage: types: Heat: 10 diff --git a/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml b/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml index e73d13e2cb..6e96dbbadc 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml @@ -89,6 +89,7 @@ - type: AtmosExposed - type: Temperature currentTemperature: 290 + - type: TemperatureDamage - type: InternalTemperature thickness: 0.02 area: 0.02 diff --git a/Resources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.yml b/Resources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.yml index d147417f9e..4d50a8b6ed 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Medical/cryo_pod.yml @@ -111,7 +111,7 @@ - type: CryoPodAir - type: Climbable # so that ejected bodies don't get stuck vaultable: false - - type: ContainerTemperatureDamageThresholds + - type: ContainerTemperature coldDamageThreshold: 10 - type: GuideHelp guides: diff --git a/Resources/Prototypes/Entities/Structures/spider_web.yml b/Resources/Prototypes/Entities/Structures/spider_web.yml index 73e5f5f032..b09e022a3b 100644 --- a/Resources/Prototypes/Entities/Structures/spider_web.yml +++ b/Resources/Prototypes/Entities/Structures/spider_web.yml @@ -24,6 +24,7 @@ - type: Damageable damageModifierSet: Wood - type: Temperature + - type: TemperatureDamage heatDamage: types: Heat: 5 -- 2.52.0