Fire damage (#2024)

* Moved the uplink creation code to the PresetSuspicion.Start method to ensure uplink created when we give the traitor role
Moved the starting TC balance to cvars

* Added component to handle interaction with Atmospheric system
Added damage from high and cold temperature

* renamed AtmoExposable to AtmosExposed
moved AtmosExposed updates to its own system
refactored TemperatureComponent
renamed fire to heat
added null check for Air
added self-heating and self-cooling to body system

* small refactoring for checking on airless tile in MetabolismComponent

* Added component to handle interaction with Atmospheric system
Added damage from high and cold temperature

* renamed AtmoExposable to AtmosExposed
moved AtmosExposed updates to its own system
refactored TemperatureComponent
renamed fire to heat
added null check for Air
added self-heating and self-cooling to body system

* small refactoring for checking on airless tile in MetabolismComponent

* Removed Pressure property from BarotraumaComponent
Changed CanShiver method to match style of other CanX method in ActionBlockerSystem

* Merged EntityCoordinates and changed components to reflect the change

* Fix typo

* Wrapped string to Loc.GetString
Added CanSweat
Refactored dead state check
This commit is contained in:
creadth
2020-09-09 18:03:27 +03:00
committed by GitHub
parent 5120627ca2
commit 7baa0a4391
16 changed files with 355 additions and 108 deletions

View File

@@ -12,6 +12,7 @@
"CloningPod",
"Destructible",
"Temperature",
"AtmosExposed",
"Explosive",
"OnUseTimerTrigger",
"ToolboxElectricalFill",

View File

@@ -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)

View File

@@ -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;
}
}
}

View File

@@ -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
{
/// <summary>
/// Represents that entity can be exposed to Atmo
/// </summary>
[RegisterComponent]
public class AtmosExposedComponent
: Component
{
public override string Name => "AtmosExposed";
public void Update(TileAtmosphere tile, float timeDelta)
{
if (Owner.TryGetComponent<TemperatureComponent>(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<BarotraumaComponent>(out var barotraumaComponent))
{
barotraumaComponent.Update(tile.Air?.Pressure ?? 0);
}
}
}
}

View File

@@ -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<AtmosphereSystem>().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)
{

View File

@@ -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<Gas, float> NeedsGases { get; set; }
@@ -34,6 +44,47 @@ namespace Content.Server.GameObjects.Components.Metabolism
[ViewVariables] public Dictionary<Gas, float> DeficitGases { get; set; }
/// <summary>
/// Heat generated due to metabolism. It's generated via metabolism
/// </summary>
[ViewVariables]
public float MetabolismHeat { get; private set; }
/// <summary>
/// Heat output via radiation.
/// </summary>
[ViewVariables]
public float RadiatedHeat { get; private set; }
/// <summary>
/// Maximum heat regulated via sweat
/// </summary>
[ViewVariables]
public float SweatHeatRegulation { get; private set; }
/// <summary>
/// Maximum heat regulated via shivering
/// </summary>
[ViewVariables]
public float ShiveringHeatRegulation { get; private set; }
/// <summary>
/// Amount of heat regulation that represents thermal regulation processes not
/// explicitly coded.
/// </summary>
public float ImplicitHeatRegulation { get; private set; }
/// <summary>
/// Normal body temperature
/// </summary>
[ViewVariables]
public float NormalBodyTemperature { get; private set; }
/// <summary>
/// Deviation from normal temperature for body to start thermal regulation
/// </summary>
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<Gas, float>());
serializer.DataField(this, b => b.ProducesGases, "producesGases", new Dictionary<Gas, float>());
serializer.DataField(this, b => b.DeficitGases, "deficitGases", new Dictionary<Gas, float>());
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();
}
/// <summary>
/// Process thermal regulation
/// </summary>
/// <param name="frameTime"></param>
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));
}
}
/// <summary>
/// Loops through each reagent in _internalSolution,
/// and calls <see cref="IMetabolizable.Metabolize"/> for each of them.
@@ -196,6 +325,12 @@ namespace Content.Server.GameObjects.Components.Metabolism
/// </param>
public void Update(float frameTime)
{
if (!Owner.TryGetComponent<IDamageableComponent>(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);
}

View File

@@ -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; }
}
/// <summary>
/// Handles changing temperature,
/// informing others of the current temperature,
/// and taking fire damage from high temperature.
/// </summary>
[RegisterComponent]
public class TemperatureComponent : Component, ITemperatureComponent
public class TemperatureComponent : Component
{
/// <inheritdoc />
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<ICollidableComponent>(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);
}
/// <inheritdoc />
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}");
}
/// <summary>
/// Forcefully give heat to this component
/// </summary>
/// <param name="heatAmount"></param>
public void ReceiveHeat(float heatAmount)
{
CurrentTemperature += heatAmount / HeatCapacity;
}
/// <summary>
/// Forcefully remove heat from this component
/// </summary>
/// <param name="heatAmount"></param>
public void RemoveHeat(float heatAmount)
{
CurrentTemperature -= heatAmount / HeatCapacity;
}
}
}

View File

@@ -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<AtmosphereSystem>();
// creadth: everything exposable by atmo should be updated as well
foreach (var atmosExposedComponent in EntityManager.ComponentManager.EntityQuery<AtmosExposedComponent>())
{
var tile = atmosExposedComponent.Owner.Transform.Coordinates.GetTileAtmosphere(_entityManager);
if (tile == null) continue;
atmosExposedComponent.Update(tile, _lastUpdate);
}
_lastUpdate = 0;
}
}
}

View File

@@ -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<IMapGridComponent, IGridAtmosphereComponent>())
{
if (_pauseManager.IsGridPaused(mapGridComponent.GridIndex))
continue;
if (_pauseManager.IsGridPaused(mapGridComponent.GridIndex)) continue;
gridAtmosphereComponent.Update(frameTime);
}

View File

@@ -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;
/// <inheritdoc />
public override void Update(float frameTime)
{
_timer += frameTime;
if (_timer < TimePerUpdate) return;
_timer = 0f;
foreach (var barotraumaComp in ComponentManager.EntityQuery<BarotraumaComponent>())
{
barotraumaComp.Update(frameTime);
}
}
}
}

View File

@@ -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<TemperatureComponent>())
{
comp.OnUpdate(frameTime);
}
}
}
}

View File

@@ -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]

View File

@@ -69,5 +69,8 @@ namespace Content.Shared.GameObjects.Components.Mobs.State
{
return false;
}
public bool CanShiver() => false;
public bool CanSweat() => false;
}
}

View File

@@ -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]

View File

@@ -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;
}
/// <summary>
@@ -35,10 +39,11 @@ namespace Content.Shared.GameObjects.EntitySystems
public static bool CanMove(IEntity entity)
{
bool canmove = true;
foreach(var actionblockercomponents in entity.GetAllComponents<IActionBlocker>())
foreach (var actionblockercomponents in entity.GetAllComponents<IActionBlocker>())
{
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,6 +98,7 @@ namespace Content.Shared.GameObjects.EntitySystems
{
candrop &= actionblockercomponents.CanDrop();
}
return candrop;
}
@@ -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<IActionBlocker>())
{
canShiver &= component.CanShiver();
}
return canShiver;
}
public static bool CanSweat(IEntity entity)
{
var canSweat = true;
foreach (var component in entity.GetAllComponents<IActionBlocker>())
{
canSweat &= component.CanSweat();
}
return canSweat;
}
}
}

View File

@@ -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: