167 lines
6.6 KiB
C#
167 lines
6.6 KiB
C#
using Content.Server.Atmos.EntitySystems;
|
|
using Content.Server.Temperature.Components;
|
|
using Content.Shared.Atmos;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.Rejuvenate;
|
|
using Content.Shared.Temperature;
|
|
using Content.Shared.Projectiles;
|
|
using Content.Shared._Goobstation.Temperature.Components;
|
|
using Content.Shared._Goobstation.Temperature;
|
|
using Content.Shared.Temperature.Components;
|
|
using Content.Shared.Temperature.Systems;
|
|
|
|
namespace Content.Server.Temperature.Systems;
|
|
|
|
public sealed partial class TemperatureSystem : SharedTemperatureSystem
|
|
{
|
|
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<TemperatureComponent, AtmosExposedUpdateEvent>(OnAtmosExposedUpdate);
|
|
SubscribeLocalEvent<TemperatureComponent, RejuvenateEvent>(OnRejuvenate);
|
|
Subs.SubscribeWithRelay<TemperatureProtectionComponent, ModifyChangedTemperatureEvent>(OnTemperatureChangeAttempt, held: false);
|
|
|
|
SubscribeLocalEvent<InternalTemperatureComponent, MapInitEvent>(OnInit);
|
|
|
|
SubscribeLocalEvent<ChangeTemperatureOnCollideComponent, ProjectileHitEvent>(ChangeTemperatureOnCollide);
|
|
|
|
SubscribeLocalEvent<SpecialLowTempImmunityComponent, TemperatureImmunityEvent>(OnCheckLowTemperatureImmunity); // Goob edit
|
|
SubscribeLocalEvent<SpecialHighTempImmunityComponent, TemperatureImmunityEvent>(OnCheckHighTemperatureImmunity); // Goob edit
|
|
|
|
InitializeDamage();
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
|
|
// conduct heat from the surface to the inside of entities with internal temperatures
|
|
var query = EntityQueryEnumerator<InternalTemperatureComponent, TemperatureComponent>();
|
|
while (query.MoveNext(out var uid, out var comp, out var temp))
|
|
{
|
|
// don't do anything if they equalised
|
|
var diff = Math.Abs(temp.CurrentTemperature - comp.Temperature);
|
|
if (diff < 0.1f)
|
|
continue;
|
|
|
|
// heat flow in W/m^2 as per fourier's law in 1D.
|
|
var q = comp.Conductivity * diff / comp.Thickness;
|
|
|
|
// convert to J then K
|
|
var joules = q * comp.Area * frameTime;
|
|
var degrees = joules / GetHeatCapacity(uid, temp);
|
|
if (temp.CurrentTemperature < comp.Temperature)
|
|
degrees *= -1;
|
|
|
|
// exchange heat between inside and surface
|
|
comp.Temperature += degrees;
|
|
ForceChangeTemperature(uid, temp.CurrentTemperature - degrees, temp);
|
|
}
|
|
|
|
UpdateDamage();
|
|
}
|
|
|
|
// Goob start
|
|
private void OnCheckLowTemperatureImmunity(Entity<SpecialLowTempImmunityComponent> ent, ref TemperatureImmunityEvent args)
|
|
{
|
|
if (args.CurrentTemperature < args.IdealTemperature)
|
|
args.CurrentTemperature = args.IdealTemperature;
|
|
}
|
|
|
|
private void OnCheckHighTemperatureImmunity(Entity<SpecialHighTempImmunityComponent> ent, ref TemperatureImmunityEvent args)
|
|
{
|
|
if (args.CurrentTemperature > args.IdealTemperature)
|
|
args.CurrentTemperature = args.IdealTemperature;
|
|
}
|
|
// Goob end
|
|
|
|
public void ForceChangeTemperature(EntityUid uid, float temp, TemperatureComponent? temperature = null)
|
|
{
|
|
if (!TemperatureQuery.Resolve(uid, ref temperature))
|
|
return;
|
|
|
|
var lastTemp = temperature.CurrentTemperature;
|
|
|
|
// Goob start
|
|
temperature.CurrentTemperature = temp;
|
|
|
|
var tempEv = new TemperatureImmunityEvent(temperature.CurrentTemperature);
|
|
RaiseLocalEvent(uid, tempEv);
|
|
temperature.CurrentTemperature = tempEv.CurrentTemperature;
|
|
|
|
float delta = temperature.CurrentTemperature - temp;
|
|
// Goob end
|
|
|
|
temperature.CurrentTemperature = temp;
|
|
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 (!TemperatureQuery.Resolve(uid, ref temperature, false))
|
|
return;
|
|
|
|
if (!ignoreHeatResistance)
|
|
{
|
|
var ev = new ModifyChangedTemperatureEvent(heatAmount);
|
|
RaiseLocalEvent(uid, ev);
|
|
heatAmount = ev.TemperatureDelta;
|
|
}
|
|
|
|
float lastTemp = temperature.CurrentTemperature;
|
|
temperature.CurrentTemperature += heatAmount / GetHeatCapacity(uid, temperature);
|
|
float delta = temperature.CurrentTemperature - lastTemp;
|
|
|
|
RaiseLocalEvent(uid, new OnTemperatureChangeEvent(temperature.CurrentTemperature, lastTemp, delta), broadcast: true);
|
|
}
|
|
|
|
private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperature, ref AtmosExposedUpdateEvent args)
|
|
{
|
|
var transform = args.Transform;
|
|
|
|
if (transform.MapUid == null)
|
|
return;
|
|
|
|
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(Entity<InternalTemperatureComponent> entity, ref MapInitEvent args)
|
|
{
|
|
if (!TemperatureQuery.TryComp(entity, out var temp))
|
|
return;
|
|
|
|
entity.Comp.Temperature = temp.CurrentTemperature;
|
|
}
|
|
|
|
private void OnRejuvenate(EntityUid uid, TemperatureComponent comp, RejuvenateEvent args)
|
|
{
|
|
ForceChangeTemperature(uid, Atmospherics.T20C, comp);
|
|
}
|
|
|
|
private void OnTemperatureChangeAttempt(EntityUid uid, TemperatureProtectionComponent component, ModifyChangedTemperatureEvent args)
|
|
{
|
|
var coefficient = args.TemperatureDelta < 0
|
|
? component.CoolingCoefficient
|
|
: component.HeatingCoefficient;
|
|
|
|
var ev = new GetTemperatureProtectionEvent(coefficient);
|
|
RaiseLocalEvent(uid, ref ev);
|
|
|
|
args.TemperatureDelta *= ev.Coefficient;
|
|
}
|
|
|
|
private void ChangeTemperatureOnCollide(Entity<ChangeTemperatureOnCollideComponent> ent, ref ProjectileHitEvent args)
|
|
{
|
|
ChangeHeat(args.Target, ent.Comp.Heat, ent.Comp.IgnoreHeatResistance);// adjust the temperature
|
|
}
|
|
}
|