Cached barotrauma resistance and immunity values instead of computing them each Update() (#15055)
This commit is contained in:
parent
6492315344
commit
76903dd145
|
|
@ -26,6 +26,25 @@ namespace Content.Server.Atmos.Components
|
|||
/// These are the inventory slots that are checked for pressure protection. If a slot is missing protection, no protection is applied.
|
||||
/// </summary>
|
||||
[DataField("protectionSlots")]
|
||||
public List<string> ProtectionSlots = new() { "head", "outerClothing" };
|
||||
public List<string> ProtectionSlots = new() { "head", "outerClothing" };
|
||||
|
||||
/// <summary>
|
||||
/// Cached pressure protection values
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public float HighPressureMultiplier = 1f;
|
||||
[ViewVariables]
|
||||
public float HighPressureModifier = 0f;
|
||||
[ViewVariables]
|
||||
public float LowPressureMultiplier = 1f;
|
||||
[ViewVariables]
|
||||
public float LowPressureModifier = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the entity is immuned to pressure (i.e possess the PressureImmunity component)
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public bool HasImmunity = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using Content.Shared.Damage;
|
|||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server.Atmos.EntitySystems
|
||||
|
|
@ -23,124 +24,136 @@ namespace Content.Server.Atmos.EntitySystems
|
|||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<PressureProtectionComponent, HighPressureEvent>(OnHighPressureEvent);
|
||||
SubscribeLocalEvent<PressureProtectionComponent, LowPressureEvent>(OnLowPressureEvent);
|
||||
|
||||
SubscribeLocalEvent<PressureImmunityComponent, HighPressureEvent>(OnHighPressureImmuneEvent);
|
||||
SubscribeLocalEvent<PressureImmunityComponent, LowPressureEvent>(OnLowPressureImmuneEvent);
|
||||
SubscribeLocalEvent<PressureProtectionComponent, GotEquippedEvent>(OnPressureProtectionEquipped);
|
||||
SubscribeLocalEvent<PressureProtectionComponent, GotUnequippedEvent>(OnPressureProtectionUnequipped);
|
||||
SubscribeLocalEvent<PressureProtectionComponent, ComponentInit>(OnUpdateResistance);
|
||||
SubscribeLocalEvent<PressureProtectionComponent, ComponentRemove>(OnUpdateResistance);
|
||||
|
||||
SubscribeLocalEvent<PressureImmunityComponent, ComponentInit>(OnPressureImmuneInit);
|
||||
SubscribeLocalEvent<PressureImmunityComponent, ComponentRemove>(OnPressureImmuneRemove);
|
||||
}
|
||||
|
||||
private void OnHighPressureEvent(EntityUid uid, PressureProtectionComponent component, HighPressureEvent args)
|
||||
private void OnPressureImmuneInit(EntityUid uid, PressureImmunityComponent pressureImmunity, ComponentInit args)
|
||||
{
|
||||
args.Modifier += component.HighPressureModifier;
|
||||
args.Multiplier *= component.HighPressureMultiplier;
|
||||
if (TryComp<BarotraumaComponent>(uid, out var barotrauma))
|
||||
{
|
||||
barotrauma.HasImmunity = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLowPressureEvent(EntityUid uid, PressureProtectionComponent component, LowPressureEvent args)
|
||||
private void OnPressureImmuneRemove(EntityUid uid, PressureImmunityComponent pressureImmunity, ComponentRemove args)
|
||||
{
|
||||
args.Modifier += component.LowPressureModifier;
|
||||
args.Multiplier *= component.LowPressureMultiplier;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Completely prevent high pressure damage
|
||||
/// </summary>
|
||||
private void OnHighPressureImmuneEvent(EntityUid uid, PressureImmunityComponent component, HighPressureEvent args)
|
||||
{
|
||||
args.Multiplier = 0;
|
||||
if (TryComp<BarotraumaComponent>(uid, out var barotrauma))
|
||||
{
|
||||
barotrauma.HasImmunity = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completely prevent low pressure damage
|
||||
/// Generic method for updating resistance on component Lifestage events
|
||||
/// </summary>
|
||||
private void OnLowPressureImmuneEvent(EntityUid uid, PressureImmunityComponent component, LowPressureEvent args)
|
||||
private void OnUpdateResistance(EntityUid uid, PressureProtectionComponent pressureProtection, EntityEventArgs args)
|
||||
{
|
||||
args.Modifier = 100;
|
||||
args.Multiplier = 10000;
|
||||
if (TryComp<BarotraumaComponent>(uid, out var barotrauma))
|
||||
{
|
||||
UpdateCachedResistances(uid, barotrauma);
|
||||
}
|
||||
}
|
||||
|
||||
public float GetFeltLowPressure(EntityUid uid, BarotraumaComponent baro, float environmentPressure)
|
||||
private void OnPressureProtectionEquipped(EntityUid uid, PressureProtectionComponent pressureProtection, GotEquippedEvent args)
|
||||
{
|
||||
var modifier = float.MaxValue;
|
||||
var multiplier = float.MaxValue;
|
||||
|
||||
TryComp(uid, out InventoryComponent? inv);
|
||||
TryComp(uid, out ContainerManagerComponent? contMan);
|
||||
|
||||
// TODO: cache this & update when equipment changes?
|
||||
// This continuously raises events for every player in space.
|
||||
|
||||
if (baro.ProtectionSlots.Count == 0)
|
||||
if (TryComp<BarotraumaComponent>(args.Equipee, out var barotrauma) && barotrauma.ProtectionSlots.Contains(args.Slot))
|
||||
{
|
||||
modifier = 0;
|
||||
multiplier = 1;
|
||||
UpdateCachedResistances(args.Equipee, barotrauma);
|
||||
}
|
||||
|
||||
// First, check if for protective equipment
|
||||
foreach (var slot in baro.ProtectionSlots)
|
||||
{
|
||||
if (!_inventorySystem.TryGetSlotEntity(uid, slot, out var equipment, inv, contMan)
|
||||
|| ! TryComp(equipment, out PressureProtectionComponent? protection))
|
||||
{
|
||||
// Missing protection, skin is exposed.
|
||||
modifier = 0;
|
||||
multiplier = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
modifier = Math.Min(protection.LowPressureModifier, modifier);
|
||||
multiplier = Math.Min(protection.LowPressureMultiplier, multiplier);
|
||||
}
|
||||
|
||||
// Then apply any generic, non-clothing related modifiers.
|
||||
var lowPressureEvent = new LowPressureEvent(environmentPressure);
|
||||
RaiseLocalEvent(uid, lowPressureEvent);
|
||||
|
||||
return (environmentPressure + modifier + lowPressureEvent.Modifier)
|
||||
* (multiplier * lowPressureEvent.Multiplier);
|
||||
}
|
||||
|
||||
public float GetFeltHighPressure(EntityUid uid, BarotraumaComponent baro, float environmentPressure)
|
||||
private void OnPressureProtectionUnequipped(EntityUid uid, PressureProtectionComponent pressureProtection, GotUnequippedEvent args)
|
||||
{
|
||||
var modifier = float.MinValue;
|
||||
var multiplier = float.MinValue;
|
||||
|
||||
TryComp(uid, out InventoryComponent? inv);
|
||||
TryComp(uid, out ContainerManagerComponent? contMan);
|
||||
|
||||
// TODO: cache this & update when equipment changes?
|
||||
// Not as import and as low-pressure, but probably still useful.
|
||||
|
||||
if (baro.ProtectionSlots.Count == 0)
|
||||
if (TryComp<BarotraumaComponent>(args.Equipee, out var barotrauma) && barotrauma.ProtectionSlots.Contains(args.Slot))
|
||||
{
|
||||
modifier = 0;
|
||||
multiplier = 1;
|
||||
UpdateCachedResistances(args.Equipee, barotrauma);
|
||||
}
|
||||
}
|
||||
|
||||
// First, check if for protective equipment
|
||||
foreach (var slot in baro.ProtectionSlots)
|
||||
/// <summary>
|
||||
/// Computes the pressure resistance for the entity coming from the equipment and any innate resistance.
|
||||
/// The ProtectionSlots field of the Barotrauma component specifies which parts must be protected for the protection to have any effet.
|
||||
/// </summary>
|
||||
private void UpdateCachedResistances(EntityUid uid, BarotraumaComponent barotrauma)
|
||||
{
|
||||
|
||||
if (barotrauma.ProtectionSlots.Count != 0)
|
||||
{
|
||||
if (!_inventorySystem.TryGetSlotEntity(uid, slot, out var equipment, inv, contMan)
|
||||
|| !TryComp(equipment, out PressureProtectionComponent? protection))
|
||||
if (!TryComp(uid, out InventoryComponent? inv) || !TryComp(uid, out ContainerManagerComponent? contMan))
|
||||
{
|
||||
// Missing protection, skin is exposed.
|
||||
modifier = 0;
|
||||
multiplier = 1;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
var hPModifier = float.MinValue;
|
||||
var hPMultiplier = float.MinValue;
|
||||
var lPModifier = float.MaxValue;
|
||||
var lPMultiplier = float.MaxValue;
|
||||
|
||||
foreach (var slot in barotrauma.ProtectionSlots)
|
||||
{
|
||||
if (!_inventorySystem.TryGetSlotEntity(uid, slot, out var equipment, inv, contMan)
|
||||
|| !TryComp(equipment, out PressureProtectionComponent? protection))
|
||||
{
|
||||
// Missing protection, skin is exposed.
|
||||
hPModifier = 0f;
|
||||
hPMultiplier = 1f;
|
||||
lPModifier = 0f;
|
||||
lPMultiplier = 1f;
|
||||
break;
|
||||
}
|
||||
|
||||
// The entity is as protected as its weakest part protection
|
||||
hPModifier = Math.Max(hPModifier, protection.HighPressureModifier);
|
||||
hPMultiplier = Math.Max(hPMultiplier, protection.HighPressureMultiplier);
|
||||
lPModifier = Math.Min(lPModifier, protection.LowPressureModifier);
|
||||
lPMultiplier = Math.Min(lPMultiplier, protection.LowPressureMultiplier);
|
||||
}
|
||||
|
||||
modifier = Math.Max(protection.HighPressureModifier, modifier);
|
||||
multiplier = Math.Max(protection.HighPressureMultiplier, multiplier);
|
||||
barotrauma.HighPressureModifier = hPModifier;
|
||||
barotrauma.HighPressureMultiplier = hPMultiplier;
|
||||
barotrauma.LowPressureModifier = lPModifier;
|
||||
barotrauma.LowPressureMultiplier = lPMultiplier;
|
||||
}
|
||||
|
||||
// Then apply any generic, non-clothing related modifiers.
|
||||
var highPressureEvent = new HighPressureEvent(environmentPressure);
|
||||
RaiseLocalEvent(uid, highPressureEvent);
|
||||
// any innate pressure resistance ?
|
||||
if (TryComp<PressureProtectionComponent>(uid, out var innatePressureProtection))
|
||||
{
|
||||
barotrauma.HighPressureModifier += innatePressureProtection.HighPressureModifier;
|
||||
barotrauma.HighPressureMultiplier *= innatePressureProtection.HighPressureMultiplier;
|
||||
barotrauma.LowPressureModifier += innatePressureProtection.LowPressureModifier;
|
||||
barotrauma.LowPressureMultiplier *= innatePressureProtection.LowPressureMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
return (environmentPressure + modifier + highPressureEvent.Modifier)
|
||||
* (multiplier * highPressureEvent.Multiplier);
|
||||
/// <summary>
|
||||
/// Returns adjusted pressure after having applied resistances from equipment and innate (if any), to check against a low pressure hazard threshold
|
||||
/// </summary>
|
||||
public float GetFeltLowPressure(EntityUid uid, BarotraumaComponent barotrauma, float environmentPressure)
|
||||
{
|
||||
if (barotrauma.HasImmunity)
|
||||
{
|
||||
return Atmospherics.OneAtmosphere;
|
||||
}
|
||||
|
||||
return (environmentPressure + barotrauma.LowPressureModifier) * (barotrauma.LowPressureMultiplier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns adjusted pressure after having applied resistances from equipment and innate (if any), to check against a high pressure hazard threshold
|
||||
/// </summary>
|
||||
public float GetFeltHighPressure(EntityUid uid, BarotraumaComponent barotrauma, float environmentPressure)
|
||||
{
|
||||
if (barotrauma.HasImmunity)
|
||||
{
|
||||
return Atmospherics.OneAtmosphere;
|
||||
}
|
||||
|
||||
return (environmentPressure + barotrauma.HighPressureModifier) * (barotrauma.HighPressureMultiplier);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
|
|
@ -203,7 +216,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||
case >= Atmospherics.WarningHighPressure:
|
||||
pressure = GetFeltHighPressure(uid, barotrauma, pressure);
|
||||
|
||||
if(pressure < Atmospherics.WarningHighPressure)
|
||||
if (pressure < Atmospherics.WarningHighPressure)
|
||||
goto default;
|
||||
|
||||
var damageScale = MathF.Min((pressure / Atmospherics.HazardHighPressure) * Atmospherics.PressureDamageCoefficient, Atmospherics.MaxHighPressureDamage);
|
||||
|
|
|
|||
Loading…
Reference in New Issue