diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index af320568fa..7dea6c8738 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -12,6 +12,7 @@ "CloningPod", "Destructible", "Temperature", + "AtmosExposed", "Explosive", "OnUseTimerTrigger", "ToolboxElectricalFill", diff --git a/Content.Server/Atmos/AtmosHelpers.cs b/Content.Server/Atmos/AtmosHelpers.cs index 4e0d313d89..e7e8371804 100644 --- a/Content.Server/Atmos/AtmosHelpers.cs +++ b/Content.Server/Atmos/AtmosHelpers.cs @@ -19,9 +19,9 @@ namespace Content.Server.Atmos return gridAtmos?.GetTile(coordinates); } - public static GasMixture? GetTileAir(this EntityCoordinates coordinates) + public static GasMixture? GetTileAir(this EntityCoordinates coordinates, IEntityManager? entityManager = null) { - return coordinates.GetTileAtmosphere()?.Air; + return coordinates.GetTileAtmosphere(entityManager)?.Air; } public static bool TryGetTileAtmosphere(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out TileAtmosphere atmosphere) @@ -30,10 +30,10 @@ namespace Content.Server.Atmos return !Equals(atmosphere = coordinates.GetTileAtmosphere()!, default); } - public static bool TryGetTileAir(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out GasMixture air) + public static bool TryGetTileAir(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out GasMixture air, IEntityManager? entityManager = null) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return !Equals(air = coordinates.GetTileAir()!, default); + return !Equals(air = coordinates.GetTileAir(entityManager)!, default); } public static TileAtmosphere? GetTileAtmosphere(this MapIndices indices, GridId gridId) diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 04186e3686..6b11195176 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -48,7 +48,7 @@ namespace Content.Server.Atmos public int AtmosCooldown { get; set; } = 0; [ViewVariables] - private float _temperature = Atmospherics.T20C; + public float Temperature {get; private set; } = Atmospherics.T20C; [ViewVariables] private float _temperatureArchived = Atmospherics.T20C; @@ -132,7 +132,7 @@ namespace Content.Server.Atmos { Air?.Archive(); _archivedCycle = fireCount; - _temperatureArchived = _temperature; + _temperatureArchived = Temperature; } public void HotspotExpose(float exposedTemperature, float exposedVolume, bool soh = false) @@ -869,10 +869,10 @@ namespace Content.Server.Atmos // Conduct with air on my tile if I have it if (!BlocksAir) { - _temperature = Air.TemperatureShare(ThermalConductivity, _temperature, HeatCapacity); + Temperature = Air.TemperatureShare(ThermalConductivity, Temperature, HeatCapacity); } - FinishSuperconduction(BlocksAir ? _temperature : Air.Temperature); + FinishSuperconduction(BlocksAir ? Temperature : Air.Temperature); } private void FinishSuperconduction(float temperature) @@ -897,7 +897,7 @@ namespace Content.Server.Atmos other.TemperatureShareMutualSolid(this, ThermalConductivity); } - TemperatureExpose(null, _temperature, _gridAtmosphereComponent.GetVolumeForCells(1)); + TemperatureExpose(null, Temperature, _gridAtmosphereComponent.GetVolumeForCells(1)); return; } @@ -915,8 +915,8 @@ namespace Content.Server.Atmos private void TemperatureShareOpenToSolid(TileAtmosphere other) { - other._temperature = - Air.TemperatureShare(other.ThermalConductivity, other._temperature, other.HeatCapacity); + other.Temperature = + Air.TemperatureShare(other.ThermalConductivity, other.Temperature, other.HeatCapacity); } private void TemperatureShareMutualSolid(TileAtmosphere other, float conductionCoefficient) @@ -928,15 +928,15 @@ namespace Content.Server.Atmos var heat = conductionCoefficient * deltaTemperature * (HeatCapacity * other.HeatCapacity / (HeatCapacity + other.HeatCapacity)); - _temperature -= heat / HeatCapacity; - other._temperature += heat / other.HeatCapacity; + Temperature -= heat / HeatCapacity; + other.Temperature += heat / other.HeatCapacity; } } public void RadiateToSpace() { // Considering 0ºC as the break even point for radiation in and out. - if (_temperature > Atmospherics.T0C) + if (Temperature > Atmospherics.T0C) { // Hardcoded space temperature. var deltaTemperature = (_temperatureArchived - Atmospherics.TCMB); @@ -945,7 +945,7 @@ namespace Content.Server.Atmos var heat = ThermalConductivity * deltaTemperature * (HeatCapacity * Atmospherics.HeatCapacityVacuum / (HeatCapacity + Atmospherics.HeatCapacityVacuum)); - _temperature -= heat; + Temperature -= heat; } } } diff --git a/Content.Server/GameObjects/Components/Atmos/AtmosExposedComponent.cs b/Content.Server/GameObjects/Components/Atmos/AtmosExposedComponent.cs new file mode 100644 index 0000000000..f5bfde7271 --- /dev/null +++ b/Content.Server/GameObjects/Components/Atmos/AtmosExposedComponent.cs @@ -0,0 +1,38 @@ +using Content.Server.Atmos; +using Content.Server.GameObjects.Components.Temperature; +using Content.Shared.Atmos; +using Robust.Shared.GameObjects; + +namespace Content.Server.GameObjects.Components.Atmos +{ + /// + /// Represents that entity can be exposed to Atmo + /// + [RegisterComponent] + public class AtmosExposedComponent + : Component + { + public override string Name => "AtmosExposed"; + + public void Update(TileAtmosphere tile, float timeDelta) + { + if (Owner.TryGetComponent(out var temperatureComponent)) + { + if (tile.Air != null) + { + var temperatureDelta = tile.Air.Temperature - temperatureComponent.CurrentTemperature; + var heat = temperatureDelta * (tile.Air.HeatCapacity * temperatureComponent.HeatCapacity / (tile.Air.HeatCapacity + temperatureComponent.HeatCapacity)); + temperatureComponent.ReceiveHeat(heat); + } + temperatureComponent.Update(); + } + + if (Owner.TryGetComponent(out var barotraumaComponent)) + { + barotraumaComponent.Update(tile.Air?.Pressure ?? 0); + } + + } + + } +} diff --git a/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs b/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs index d877165791..249df1639f 100644 --- a/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs @@ -1,14 +1,12 @@ using System; using System.Runtime.CompilerServices; using Content.Server.GameObjects.Components.Mobs; -using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.GameObjects; using Content.Shared.Atmos; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Mobs; using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; namespace Content.Server.GameObjects.Components.Atmos @@ -19,21 +17,14 @@ namespace Content.Server.GameObjects.Components.Atmos [RegisterComponent] public class BarotraumaComponent : Component { - [Robust.Shared.IoC.Dependency] private readonly IEntityManager _entityManager = default!; - public override string Name => "Barotrauma"; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(float frameTime) + public void Update(float airPressure) { if (!Owner.TryGetComponent(out IDamageableComponent damageable)) return; Owner.TryGetComponent(out ServerStatusEffectsComponent status); - var coordinates = Owner.Transform.Coordinates; - var gridAtmos = EntitySystem.Get().GetGridAtmosphere(coordinates.GetGridId(_entityManager)); - var tile = gridAtmos?.GetTile(coordinates); - - var pressure = 1f; var highPressureMultiplier = 1f; var lowPressureMultiplier = 1f; @@ -43,8 +34,7 @@ namespace Content.Server.GameObjects.Components.Atmos lowPressureMultiplier *= protection.LowPressureMultiplier; } - if (tile?.Air != null) - pressure = MathF.Max(tile.Air.Pressure, 1f); + var pressure = MathF.Max(airPressure, 1f); switch (pressure) { diff --git a/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs b/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs index d9c1051e27..45fb5e2e11 100644 --- a/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs +++ b/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs @@ -2,15 +2,20 @@ using System.Collections.Generic; using System.Linq; using Content.Server.Atmos; -using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Body.Circulatory; +using Content.Server.GameObjects.Components.Temperature; +using Content.Server.GameObjects.EntitySystems; using Content.Shared.Atmos; using Content.Shared.Chemistry; -using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces; using Content.Shared.Interfaces.Chemistry; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -21,11 +26,16 @@ namespace Content.Server.GameObjects.Components.Metabolism public class MetabolismComponent : Component { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + public override string Name => "Metabolism"; private float _accumulatedFrameTime; + private bool _isShivering; + private bool _isSweating; + [ViewVariables(VVAccess.ReadWrite)] private int _suffocationDamage; [ViewVariables] public Dictionary NeedsGases { get; set; } @@ -34,6 +44,47 @@ namespace Content.Server.GameObjects.Components.Metabolism [ViewVariables] public Dictionary DeficitGases { get; set; } + /// + /// Heat generated due to metabolism. It's generated via metabolism + /// + [ViewVariables] + public float MetabolismHeat { get; private set; } + + /// + /// Heat output via radiation. + /// + [ViewVariables] + public float RadiatedHeat { get; private set; } + + /// + /// Maximum heat regulated via sweat + /// + [ViewVariables] + public float SweatHeatRegulation { get; private set; } + + /// + /// Maximum heat regulated via shivering + /// + [ViewVariables] + public float ShiveringHeatRegulation { get; private set; } + + /// + /// Amount of heat regulation that represents thermal regulation processes not + /// explicitly coded. + /// + public float ImplicitHeatRegulation { get; private set; } + + /// + /// Normal body temperature + /// + [ViewVariables] + public float NormalBodyTemperature { get; private set; } + + /// + /// Deviation from normal temperature for body to start thermal regulation + /// + public float ThermalRegulationTemperatureThreshold { get; private set; } + [ViewVariables] public bool Suffocating => SuffocatingPercentage() > 0; public override void ExposeData(ObjectSerializer serializer) @@ -43,6 +94,14 @@ namespace Content.Server.GameObjects.Components.Metabolism serializer.DataField(this, b => b.NeedsGases, "needsGases", new Dictionary()); serializer.DataField(this, b => b.ProducesGases, "producesGases", new Dictionary()); serializer.DataField(this, b => b.DeficitGases, "deficitGases", new Dictionary()); + serializer.DataField(this, b => b.MetabolismHeat, "metabolismHeat", 0); + serializer.DataField(this, b => b.RadiatedHeat, "radiatedHeat", 0); + serializer.DataField(this, b => b.SweatHeatRegulation, "sweatHeatRegulation", 0); + serializer.DataField(this, b => b.ShiveringHeatRegulation, "shiveringHeatRegulation", 0); + serializer.DataField(this, b => b.ImplicitHeatRegulation, "implicitHeatRegulation", 0); + serializer.DataField(this, b => b.NormalBodyTemperature, "normalBodyTemperature", 0); + serializer.DataField(this, b => b.ThermalRegulationTemperatureThreshold, + "thermalRegulationTemperatureThreshold", 0); serializer.DataField(ref _suffocationDamage, "suffocationDamage", 1); } @@ -152,6 +211,76 @@ namespace Content.Server.GameObjects.Components.Metabolism ClampDeficit(); } + /// + /// Process thermal regulation + /// + /// + private void ProcessThermalRegulation(float frameTime) + { + if (!Owner.TryGetComponent(out TemperatureComponent temperatureComponent)) return; + temperatureComponent.ReceiveHeat(MetabolismHeat); + temperatureComponent.RemoveHeat(RadiatedHeat); + + // implicit heat regulation + var tempDiff = Math.Abs(temperatureComponent.CurrentTemperature - NormalBodyTemperature); + var targetHeat = tempDiff * temperatureComponent.HeatCapacity; + if (temperatureComponent.CurrentTemperature > NormalBodyTemperature) + { + temperatureComponent.RemoveHeat(Math.Min(targetHeat, ImplicitHeatRegulation)); + } + else + { + temperatureComponent.ReceiveHeat(Math.Min(targetHeat, ImplicitHeatRegulation)); + } + + // recalc difference and target heat + tempDiff = Math.Abs(temperatureComponent.CurrentTemperature - NormalBodyTemperature); + targetHeat = tempDiff * temperatureComponent.HeatCapacity; + + // if body temperature is not within comfortable, thermal regulation + // processes starts + if (tempDiff < ThermalRegulationTemperatureThreshold) + { + if (_isShivering || _isSweating) + { + Owner.PopupMessage(Loc.GetString("You feel comfortable")); + } + + _isShivering = false; + _isSweating = false; + return; + } + + + if (temperatureComponent.CurrentTemperature > NormalBodyTemperature) + { + if (!ActionBlockerSystem.CanSweat(Owner)) return; + if (!_isSweating) + { + Owner.PopupMessage(Loc.GetString("You are sweating")); + _isSweating = true; + } + + // creadth: sweating does not help in airless environment + if (Owner.Transform.Coordinates.TryGetTileAir(out _, _entityManager)) + { + temperatureComponent.RemoveHeat(Math.Min(targetHeat, SweatHeatRegulation)); + } + } + else + { + if (!ActionBlockerSystem.CanShiver(Owner)) return; + if (!_isShivering) + { + Owner.PopupMessage(Loc.GetString("You are shivering")); + _isShivering = true; + } + + temperatureComponent.ReceiveHeat(Math.Min(targetHeat, ShiveringHeatRegulation)); + } + } + + /// /// Loops through each reagent in _internalSolution, /// and calls for each of them. @@ -196,6 +325,12 @@ namespace Content.Server.GameObjects.Components.Metabolism /// public void Update(float frameTime) { + if (!Owner.TryGetComponent(out var damageable) || + damageable.CurrentDamageState == DamageState.Dead) + { + return; + } + _accumulatedFrameTime += frameTime; if (_accumulatedFrameTime < 1) @@ -207,9 +342,9 @@ namespace Content.Server.GameObjects.Components.Metabolism ProcessGases(frameTime); ProcessNutrients(frameTime); + ProcessThermalRegulation(frameTime); - if (Suffocating && - Owner.TryGetComponent(out IDamageableComponent damageable)) + if (Suffocating) { // damageable.ChangeDamage(DamageClass.Airloss, _suffocationDamage, false); } diff --git a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs index 3c80f17bca..4828df6dee 100644 --- a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs +++ b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs @@ -1,61 +1,103 @@ using System; +using System.Diagnostics; +using Content.Shared.Atmos; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.Maths; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Temperature { - public interface ITemperatureComponent : IComponent - { - float CurrentTemperature { get; } - } - /// /// Handles changing temperature, /// informing others of the current temperature, /// and taking fire damage from high temperature. /// [RegisterComponent] - public class TemperatureComponent : Component, ITemperatureComponent + public class TemperatureComponent : Component { /// public override string Name => "Temperature"; - //TODO: should be programmatic instead of how it currently is - [ViewVariables] public float CurrentTemperature { get; private set; } = PhysicalConstants.ZERO_CELCIUS; + [ViewVariables] public float CurrentTemperature { get => _currentTemperature; set => _currentTemperature = value; } - float _fireDamageThreshold = 0; - float _fireDamageCoefficient = 1; + [ViewVariables] public float HeatDamageThreshold => _heatDamageThreshold; + [ViewVariables] public float ColdDamageThreshold => _coldDamageThreshold; + [ViewVariables] public float TempDamageCoefficient => _tempDamageCoefficient; + [ViewVariables] public float HeatCapacity { + get + { + if (Owner.TryGetComponent(out var physics)) + { + return SpecificHeat * physics.Mass; + } - float _secondsSinceLastDamageUpdate = 0; + return Atmospherics.MinimumHeatCapacity; + } + } + + [ViewVariables] public float SpecificHeat => _specificHeat; + + private float _heatDamageThreshold; + private float _coldDamageThreshold; + private float _tempDamageCoefficient; + private float _currentTemperature; + private float _specificHeat; public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - serializer.DataField(ref _fireDamageThreshold, "firedamagethreshold", 0); - serializer.DataField(ref _fireDamageCoefficient, "firedamagecoefficient", 1); + serializer.DataField(ref _heatDamageThreshold, "heatDamageThreshold", 0); + serializer.DataField(ref _coldDamageThreshold, "coldDamageThreshold", 0); + serializer.DataField(ref _tempDamageCoefficient, "tempDamageCoefficient", 1); + serializer.DataField(ref _currentTemperature, "currentTemperature", Atmospherics.T20C); + serializer.DataField(ref _specificHeat, "specificHeat", Atmospherics.MinimumHeatCapacity); } - /// - public void OnUpdate(float frameTime) + public void Update() { - var fireDamage = - (int) Math.Floor(Math.Max(0, CurrentTemperature - _fireDamageThreshold) / _fireDamageCoefficient); - - _secondsSinceLastDamageUpdate += frameTime; - - Owner.TryGetComponent(out IDamageableComponent component); - - while (_secondsSinceLastDamageUpdate >= 1) + var tempDamage = 0; + DamageType? damageType = null; + if (CurrentTemperature >= _heatDamageThreshold) { - component?.ChangeDamage(DamageType.Heat, fireDamage, false, null); - _secondsSinceLastDamageUpdate -= 1; + tempDamage = (int) Math.Floor((CurrentTemperature - _heatDamageThreshold) * _tempDamageCoefficient); + damageType = DamageType.Heat; } + else if (CurrentTemperature <= _coldDamageThreshold) + { + tempDamage = (int) Math.Floor((_coldDamageThreshold - CurrentTemperature) * _tempDamageCoefficient); + damageType = DamageType.Cold; + } + + if (!damageType.HasValue) return; + + if (!Owner.TryGetComponent(out IDamageableComponent component)) return; + component.ChangeDamage(damageType.Value, tempDamage, false); + Debug.Write($"Temp is: {CurrentTemperature}"); } + + /// + /// Forcefully give heat to this component + /// + /// + public void ReceiveHeat(float heatAmount) + { + CurrentTemperature += heatAmount / HeatCapacity; + } + + /// + /// Forcefully remove heat from this component + /// + /// + public void RemoveHeat(float heatAmount) + { + CurrentTemperature -= heatAmount / HeatCapacity; + } + } } diff --git a/Content.Server/GameObjects/EntitySystems/AtmosExposedSystem.cs b/Content.Server/GameObjects/EntitySystems/AtmosExposedSystem.cs new file mode 100644 index 0000000000..7f620ad222 --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/AtmosExposedSystem.cs @@ -0,0 +1,34 @@ +using Content.Server.Atmos; +using Content.Server.GameObjects.Components.Atmos; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class AtmosExposedSystem + : EntitySystem + { + [Dependency] private readonly IEntityManager _entityManager = default!; + + private const float UpdateDelay = 3f; + private float _lastUpdate; + public override void Update(float frameTime) + { + _lastUpdate += frameTime; + if (_lastUpdate < UpdateDelay) return; + var atmoSystem = EntitySystemManager.GetEntitySystem(); + // creadth: everything exposable by atmo should be updated as well + foreach (var atmosExposedComponent in EntityManager.ComponentManager.EntityQuery()) + { + var tile = atmosExposedComponent.Owner.Transform.Coordinates.GetTileAtmosphere(_entityManager); + if (tile == null) continue; + atmosExposedComponent.Update(tile, _lastUpdate); + } + + _lastUpdate = 0; + } + } +} diff --git a/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs b/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs index 84bce7a646..309d8e02ca 100644 --- a/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using Content.Server.Atmos; using Content.Server.Atmos.Reactions; +using Content.Server.GameObjects.Components.Atmos; using Content.Server.Interfaces; using Content.Shared.GameObjects.EntitySystems.Atmos; using JetBrains.Annotations; @@ -64,8 +65,7 @@ namespace Content.Server.GameObjects.EntitySystems foreach (var (mapGridComponent, gridAtmosphereComponent) in EntityManager.ComponentManager.EntityQuery()) { - if (_pauseManager.IsGridPaused(mapGridComponent.GridIndex)) - continue; + if (_pauseManager.IsGridPaused(mapGridComponent.GridIndex)) continue; gridAtmosphereComponent.Update(frameTime); } diff --git a/Content.Server/GameObjects/EntitySystems/BarotraumaSystem.cs b/Content.Server/GameObjects/EntitySystems/BarotraumaSystem.cs deleted file mode 100644 index d607c3d984..0000000000 --- a/Content.Server/GameObjects/EntitySystems/BarotraumaSystem.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Content.Server.GameObjects.Components.Atmos; -using JetBrains.Annotations; -using Robust.Shared.GameObjects.Systems; - -namespace Content.Server.GameObjects.EntitySystems -{ - [UsedImplicitly] - public class BarotraumaSystem : EntitySystem - { - private const float TimePerUpdate = 3f; - - private float _timer = 0f; - - /// - public override void Update(float frameTime) - { - _timer += frameTime; - - if (_timer < TimePerUpdate) return; - - _timer = 0f; - - foreach (var barotraumaComp in ComponentManager.EntityQuery()) - { - barotraumaComp.Update(frameTime); - } - } - } -} diff --git a/Content.Server/GameObjects/EntitySystems/TemperatureSystem.cs b/Content.Server/GameObjects/EntitySystems/TemperatureSystem.cs deleted file mode 100644 index f03b240a0b..0000000000 --- a/Content.Server/GameObjects/EntitySystems/TemperatureSystem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Server.GameObjects.Components.Temperature; -using JetBrains.Annotations; -using Robust.Shared.GameObjects.Systems; - -namespace Content.Server.GameObjects.EntitySystems -{ - [UsedImplicitly] - internal sealed class TemperatureSystem : EntitySystem - { - public override void Update(float frameTime) - { - foreach (var comp in ComponentManager.EntityQuery()) - { - comp.OnUpdate(frameTime); - } - } - } -} diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs index 1d324ba7d4..cfa2268d2b 100644 --- a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs @@ -260,6 +260,10 @@ namespace Content.Shared.GameObjects.Components.Mobs public bool CanUnequip() => (!Stunned); public bool CanChangeDirection() => true; + + public bool CanShiver() => !Stunned; + public bool CanSweat() => true; + #endregion [ViewVariables] diff --git a/Content.Shared/GameObjects/Components/Mobs/State/SharedDeadState.cs b/Content.Shared/GameObjects/Components/Mobs/State/SharedDeadState.cs index 6dc85a07cf..43887b878b 100644 --- a/Content.Shared/GameObjects/Components/Mobs/State/SharedDeadState.cs +++ b/Content.Shared/GameObjects/Components/Mobs/State/SharedDeadState.cs @@ -69,5 +69,8 @@ namespace Content.Shared.GameObjects.Components.Mobs.State { return false; } + + public bool CanShiver() => false; + public bool CanSweat() => false; } } diff --git a/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs b/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs index e9a029271c..797a1ac08d 100644 --- a/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs +++ b/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs @@ -17,6 +17,8 @@ namespace Content.Shared.GameObjects.Components.Observer public bool CanPickup() => false; public bool CanEmote() => false; public bool CanAttack() => false; + public bool CanShiver() => false; + public bool CanSweat() => false; } [Serializable, NetSerializable] diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs index e7a32bf4fe..f3db58a623 100644 --- a/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs @@ -1,4 +1,5 @@ -using Robust.Shared.GameObjects.Systems; +using System.Linq; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; namespace Content.Shared.GameObjects.EntitySystems @@ -24,6 +25,9 @@ namespace Content.Shared.GameObjects.EntitySystems bool CanUnequip() => true; bool CanChangeDirection() => true; + + bool CanShiver() => true; + bool CanSweat() => true; } /// @@ -35,10 +39,11 @@ namespace Content.Shared.GameObjects.EntitySystems public static bool CanMove(IEntity entity) { bool canmove = true; - foreach(var actionblockercomponents in entity.GetAllComponents()) + foreach (var actionblockercomponents in entity.GetAllComponents()) { canmove &= actionblockercomponents.CanMove(); // Sets var to false if false } + return canmove; } @@ -49,6 +54,7 @@ namespace Content.Shared.GameObjects.EntitySystems { caninteract &= actionblockercomponents.CanInteract(); } + return caninteract; } @@ -59,6 +65,7 @@ namespace Content.Shared.GameObjects.EntitySystems { canuse &= actionblockercomponents.CanUse(); } + return canuse; } @@ -69,6 +76,7 @@ namespace Content.Shared.GameObjects.EntitySystems { canthrow &= actionblockercomponents.CanThrow(); } + return canthrow; } @@ -79,6 +87,7 @@ namespace Content.Shared.GameObjects.EntitySystems { canspeak &= actionblockercomponents.CanSpeak(); } + return canspeak; } @@ -89,8 +98,9 @@ namespace Content.Shared.GameObjects.EntitySystems { candrop &= actionblockercomponents.CanDrop(); } + return candrop; - } + } public static bool CanPickup(IEntity entity) { @@ -99,6 +109,7 @@ namespace Content.Shared.GameObjects.EntitySystems { canpickup &= actionblockercomponents.CanPickup(); } + return canpickup; } @@ -161,5 +172,25 @@ namespace Content.Shared.GameObjects.EntitySystems return canchangedirection; } + + public static bool CanShiver(IEntity entity) + { + var canShiver = true; + foreach (var component in entity.GetAllComponents()) + { + canShiver &= component.CanShiver(); + } + return canShiver; + } + + public static bool CanSweat(IEntity entity) + { + var canSweat = true; + foreach (var component in entity.GetAllComponents()) + { + canSweat &= component.CanSweat(); + } + return canSweat; + } } } diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index e672beebd5..24a01b43c6 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -128,12 +128,26 @@ layer: - Opaque - MobImpassable + - type: AtmosExposed + - type: Temperature + heatDamageThreshold: 360 + coldDamageThreshold: 260 + currentTemperature: 310.15 + specificHeat: 42 + tempDamageCoefficient: 0.1 - type: BodyManager criticalThreshold: 100 deadThreshold: 200 baseTemplate: bodyTemplate.Humanoid basePreset: bodyPreset.BasicHuman - type: Metabolism + metabolismHeat: 5000 + radiatedHeat: 400 + implicitHeatRegulation: 5000 + sweatHeatRegulation: 5000 + shiveringHeatRegulation: 5000 + normalBodyTemperature: 310.15 + thermalRegulationTemperatureThreshold: 25 needsGases: Oxygen: 0.006365740 producesGases: