thusd lung damage

This commit is contained in:
Janet Blackquill
2025-10-03 15:39:36 -04:00
parent 579ea90d49
commit 677b79979a
32 changed files with 598 additions and 2 deletions

View File

@@ -58,6 +58,9 @@
<Label Name="HeartHealthText" Text="{Loc 'health-analyzer-window-entity-heart-health-text'}" /> <Label Name="HeartHealthText" Text="{Loc 'health-analyzer-window-entity-heart-health-text'}" />
<RichTextLabel Name="HeartHealthLabel" /> <RichTextLabel Name="HeartHealthLabel" />
<TextureButton Name="HeartHealthButton" StyleClasses="SpeciesInfoDefault" Scale="0.3 0.3" VerticalAlignment="Center" /> <TextureButton Name="HeartHealthButton" StyleClasses="SpeciesInfoDefault" Scale="0.3 0.3" VerticalAlignment="Center" />
<Label Name="LungHealthText" Text="{Loc 'health-analyzer-window-entity-lung-health-text'}" />
<RichTextLabel Name="LungHealthLabel" />
<TextureButton Name="LungHealthButton" StyleClasses="SpeciesInfoDefault" Scale="0.3 0.3" VerticalAlignment="Center" />
<Label Name="BloodText" Text="{Loc 'health-analyzer-window-entity-blood-level-text'}" /> <Label Name="BloodText" Text="{Loc 'health-analyzer-window-entity-blood-level-text'}" />
<RichTextLabel Name="BloodLabel" /> <RichTextLabel Name="BloodLabel" />
<TextureButton Name="BloodButton" StyleClasses="SpeciesInfoDefault" Scale="0.3 0.3" VerticalAlignment="Center" /> <TextureButton Name="BloodButton" StyleClasses="SpeciesInfoDefault" Scale="0.3 0.3" VerticalAlignment="Center" />

View File

@@ -44,6 +44,7 @@ namespace Content.Client.HealthAnalyzer.UI
private readonly Tooltips.BloodOxygenationTooltip _bloodOxygenationTooltip = new(); private readonly Tooltips.BloodOxygenationTooltip _bloodOxygenationTooltip = new();
private readonly Tooltips.HeartRateTooltip _heartRateTooltip = new(); private readonly Tooltips.HeartRateTooltip _heartRateTooltip = new();
private readonly Tooltips.HeartHealthTooltip _heartHealthTooltip = new(); private readonly Tooltips.HeartHealthTooltip _heartHealthTooltip = new();
private readonly Tooltips.LungHealthTooltip _lungHealthTooltip = new();
private readonly Tooltips.BloodFlowTooltip _bloodFlowTooltip = new(); private readonly Tooltips.BloodFlowTooltip _bloodFlowTooltip = new();
private readonly Tooltips.BloodTooltip _bloodTooltip = new(); private readonly Tooltips.BloodTooltip _bloodTooltip = new();
private readonly Tooltips.TemperatureTooltip _temperatureTooltip = new(); private readonly Tooltips.TemperatureTooltip _temperatureTooltip = new();
@@ -71,6 +72,7 @@ namespace Content.Client.HealthAnalyzer.UI
TemperatureButton.TooltipSupplier = _ => _temperatureTooltip; TemperatureButton.TooltipSupplier = _ => _temperatureTooltip;
DamageButton.TooltipSupplier = _ => _damageTooltip; DamageButton.TooltipSupplier = _ => _damageTooltip;
BloodButton.TooltipSupplier = _ => _bloodTooltip; BloodButton.TooltipSupplier = _ => _bloodTooltip;
LungHealthButton.TooltipSupplier = _ => _lungHealthTooltip;
// End Offbrand // End Offbrand
} }
@@ -263,6 +265,11 @@ namespace Content.Client.HealthAnalyzer.UI
BloodPressureLabel.Text = Loc.GetString("health-analyzer-window-entity-blood-pressure-value", ("systolic", systolic), ("diastolic", diastolic), ("rating", woundable.BloodPressureRating)); BloodPressureLabel.Text = Loc.GetString("health-analyzer-window-entity-blood-pressure-value", ("systolic", systolic), ("diastolic", diastolic), ("rating", woundable.BloodPressureRating));
BloodPressureButton.Visible = true; BloodPressureButton.Visible = true;
LungHealthText.Visible = true;
LungHealthLabel.Visible = true;
LungHealthLabel.Text = Loc.GetString("health-analyzer-window-entity-lung-health-value", ("value", $"{woundable.LungHealth * 100:F1}"), ("rating", woundable.LungHealthRating));
LungHealthButton.Visible = true;
BloodLabel.Visible = false; BloodLabel.Visible = false;
BloodText.Visible = false; BloodText.Visible = false;
BloodButton.Visible = false; BloodButton.Visible = false;
@@ -275,18 +282,21 @@ namespace Content.Client.HealthAnalyzer.UI
HeartRateLabel.Visible = false; HeartRateLabel.Visible = false;
HeartHealthLabel.Visible = false; HeartHealthLabel.Visible = false;
BloodFlowLabel.Visible = false; BloodFlowLabel.Visible = false;
LungHealthLabel.Visible = false;
BrainHealthText.Visible = false; BrainHealthText.Visible = false;
BloodPressureText.Visible = false; BloodPressureText.Visible = false;
BloodOxygenationText.Visible = false; BloodOxygenationText.Visible = false;
BloodFlowText.Visible = false; BloodFlowText.Visible = false;
HeartRateText.Visible = false; HeartRateText.Visible = false;
HeartHealthText.Visible = false; HeartHealthText.Visible = false;
LungHealthText.Visible = false;
BrainHealthButton.Visible = false; BrainHealthButton.Visible = false;
BloodPressureButton.Visible = false; BloodPressureButton.Visible = false;
BloodOxygenationButton.Visible = false; BloodOxygenationButton.Visible = false;
BloodFlowButton.Visible = false; BloodFlowButton.Visible = false;
HeartRateButton.Visible = false; HeartRateButton.Visible = false;
HeartHealthButton.Visible = false; HeartHealthButton.Visible = false;
LungHealthButton.Visible = false;
BloodLabel.Visible = true; BloodLabel.Visible = true;
BloodText.Visible = true; BloodText.Visible = true;

View File

@@ -0,0 +1,8 @@
<PanelContainer xmlns="https://spacestation14.io" StyleClasses="tooltipBox">
<BoxContainer
Orientation="Vertical"
RectClipContent="True"
Margin="4">
<RichTextLabel Text="{Loc 'health-analyzer-lung-health-tooltip'}" HorizontalExpand="True" />
</BoxContainer>
</PanelContainer>

View File

@@ -0,0 +1,15 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Client.UserInterface;
namespace Content.Client.HealthAnalyzer.UI.Tooltips;
[GenerateTypedNameReferences]
public sealed partial class LungHealthTooltip : PanelContainer
{
public LungHealthTooltip()
{
RobustXamlLoader.Load(this);
}
}

View File

@@ -140,7 +140,15 @@ public sealed class RespiratorSystem : EntitySystem
if (ev.Gas is null) if (ev.Gas is null)
return; return;
var gas = ev.Gas.RemoveVolume(entity.Comp.BreathVolume); // Begin Offbrand
var breathEv = new Content.Shared._Offbrand.Wounds.BeforeBreathEvent(entity.Comp.BreathVolume);
RaiseLocalEvent(entity, ref breathEv);
var gas = ev.Gas.RemoveVolume(breathEv.BreathVolume);
var beforeEv = new Content.Shared._Offbrand.Wounds.BeforeInhaledGasEvent(gas);
RaiseLocalEvent(entity, ref beforeEv);
// End Offbrand
var inhaleEv = new InhaledGasEvent(gas); var inhaleEv = new InhaledGasEvent(gas);
RaiseLocalEvent(entity, ref inhaleEv); RaiseLocalEvent(entity, ref inhaleEv);

View File

@@ -170,6 +170,9 @@ public sealed partial class ZombieSystem
RemComp<CryostasisFactorComponent>(target); RemComp<CryostasisFactorComponent>(target);
RemComp<UniqueWoundOnDamageComponent>(target); RemComp<UniqueWoundOnDamageComponent>(target);
RemComp<IntrinsicPainComponent>(target); RemComp<IntrinsicPainComponent>(target);
RemComp<LungDamageComponent>(target);
RemComp<LungDamageOnInhaledAirTemperatureComponent>(target);
RemComp<LungDamageAlertsComponent>(target);
var entProto = _protoManager.Index(AddOnWoundableZombified); var entProto = _protoManager.Index(AddOnWoundableZombified);
EntityManager.RemoveComponents(target, entProto.Components); EntityManager.RemoveComponents(target, entProto.Components);

View File

@@ -0,0 +1,35 @@
using Content.Server.Temperature.Components;
using Content.Shared._Offbrand.Wounds;
namespace Content.Server._Offbrand.Wounds;
public sealed class LungDamageTemperatureSystem : EntitySystem
{
[Dependency] private readonly LungDamageSystem _lungDamage = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LungDamageOnInhaledAirTemperatureComponent, BeforeInhaledGasEvent>(OnBeforeInhaledGas);
}
private void OnBeforeInhaledGas(Entity<LungDamageOnInhaledAirTemperatureComponent> ent, ref BeforeInhaledGasEvent args)
{
var temperature = Comp<TemperatureComponent>(ent);
var heatDamageThreshold = temperature.ParentHeatDamageThreshold ?? temperature.HeatDamageThreshold;
var coldDamageThreshold = temperature.ParentColdDamageThreshold ?? temperature.ColdDamageThreshold;
if (args.Gas.Temperature >= heatDamageThreshold)
{
var damage = ent.Comp.HeatCoefficient * args.Gas.Temperature + ent.Comp.HeatConstant;
_lungDamage.TryModifyDamage(ent.Owner, damage);
}
else if (args.Gas.Temperature <= coldDamageThreshold)
{
var damage = ent.Comp.ColdCoefficient * args.Gas.Temperature + ent.Comp.ColdConstant;
_lungDamage.TryModifyDamage(ent.Owner, damage);
}
}
}

View File

@@ -0,0 +1,32 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class LungDamage : EntityEffectCondition
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public override bool Condition(EntityEffectBaseArgs args)
{
if (args.EntityManager.TryGetComponent<LungDamageComponent>(args.TargetEntity, out var lungDamage))
{
return lungDamage.Damage >= Min && lungDamage.Damage <= Max;
}
return false;
}
public override string GuidebookExplanation(IPrototypeManager prototype)
{
return Loc.GetString("reagent-effect-condition-guidebook-lung-damage",
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
("min", Min.Float()));
}
}

View File

@@ -0,0 +1,31 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.EntityEffects;
public sealed partial class ModifyLungDamage : EntityEffect
{
[DataField(required: true)]
public FixedPoint2 Amount;
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
{
if (Amount < FixedPoint2.Zero)
return Loc.GetString("reagent-effect-guidebook-modify-lung-damage-heals", ("chance", Probability), ("amount", -Amount));
else
return Loc.GetString("reagent-effect-guidebook-modify-lung-damage-deals", ("chance", Probability), ("amount", Amount));
}
public override void Effect(EntityEffectBaseArgs args)
{
var scale = FixedPoint2.New(1);
if (args is EntityEffectReagentArgs reagentArgs)
scale = reagentArgs.Scale;
args.EntityManager.System<LungDamageSystem>()
.TryModifyDamage(args.TargetEntity, Amount * scale);
}
}

View File

@@ -0,0 +1,17 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Construction;
using Content.Shared.FixedPoint;
namespace Content.Shared._Offbrand.Surgery;
[DataDefinition]
public sealed partial class ChangeLungDamage : IGraphAction
{
[DataField(required: true)]
public FixedPoint2 Amount;
public void PerformAction(EntityUid uid, EntityUid? userUid, IEntityManager entityManager)
{
entityManager.System<LungDamageSystem>().TryModifyDamage(uid, Amount);
}
}

View File

@@ -0,0 +1,47 @@
using Content.Shared._Offbrand.Wounds;
using Content.Shared.Construction;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.Surgery;
[DataDefinition]
public sealed partial class LungDamage : IGraphCondition
{
[DataField]
public FixedPoint2 Max = FixedPoint2.MaxValue;
[DataField]
public FixedPoint2 Min = FixedPoint2.Zero;
public bool Condition(EntityUid uid, IEntityManager entityManager)
{
if (!entityManager.TryGetComponent<LungDamageComponent>(uid, out var lungDamage))
return false;
return lungDamage.Damage >= Min && lungDamage.Damage <= Max;
}
public bool DoExamine(ExaminedEvent args)
{
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent<LungDamageComponent>(args.Examined, out var lungDamage))
return false;
if (lungDamage.Damage >= Min && lungDamage.Damage <= Max)
return false;
args.PushMarkup(Loc.GetString("construction-examine-lung-damage-range", ("min", Min.Float()), ("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float())));
return true;
}
public IEnumerable<ConstructionGuideEntry> GenerateGuideEntry()
{
yield return new ConstructionGuideEntry()
{
Localization = "construction-step-lung-damage-range",
Arguments =
[ ("min", Min.Float()), ("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()) ],
};
}
}

View File

@@ -0,0 +1,92 @@
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.FixedPoint;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._Offbrand.Wounds;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(LungDamageSystem))]
public sealed partial class LungDamageComponent : Component
{
/// <summary>
/// The maximum amount of damage this entity's lungs can take
/// </summary>
[DataField(required: true)]
public FixedPoint2 MaxDamage;
/// <summary>
/// The current amount of accrued damage
/// </summary>
[DataField(required: true), AutoNetworkedField]
public FixedPoint2 Damage;
}
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(LungDamageSystem))]
public sealed partial class LungDamageAlertsComponent : Component
{
/// <summary>
/// The alert to display depending on the amount of lung damage. Highest key is selected.
/// </summary>
[DataField(required: true)]
public SortedDictionary<FixedPoint2, ProtoId<AlertPrototype>> AlertThresholds;
/// <summary>
/// The alert category of the alerts.
/// </summary>
[DataField(required: true)]
public ProtoId<AlertCategoryPrototype> AlertCategory;
[DataField, AutoNetworkedField]
public ProtoId<AlertPrototype>? CurrentAlertThresholdState;
}
[RegisterComponent, NetworkedComponent]
public sealed partial class LungDamageOnInhaledAirTemperatureComponent : Component
{
/// <summary>
/// The coefficient for how much damage is taken when the air temperature is below <see cref="TemperatureComponent"/>'s ColdDamageThreshold
/// </summary>
[DataField(required: true)]
public float ColdCoefficient;
/// <summary>
/// The constant for how much damage is taken when the air temperature is below <see cref="TemperatureComponent"/>'s ColdDamageThreshold
/// </summary>
[DataField(required: true)]
public float ColdConstant;
/// <summary>
/// The coefficient for how much damage is taken when the air temperature is below <see cref="TemperatureComponent"/>'s HeatDamageThreshold
/// </summary>
[DataField(required: true)]
public float HeatCoefficient;
/// <summary>
/// The constant for how much damage is taken when the air temperature is below <see cref="TemperatureComponent"/>'s HeatDamageThreshold
/// </summary>
[DataField(required: true)]
public float HeatConstant;
}
/// <summary>
/// Event raised when an entity is about to take a breath
/// </summary>
/// <param name="BreathVolume">The volume to breathe in.</param>
[ByRefEvent]
public record struct BeforeBreathEvent(float BreathVolume);
/// <summary>
/// Event raised when an entity successfully inhales a gas, before storing the gas internally
/// </summary>
/// <param name="Gas">The gas we're inhaling.</param>
[ByRefEvent]
public record struct BeforeInhaledGasEvent(GasMixture Gas);
/// <summary>
/// Event raised when an entity's lung damage changes
/// </summary>
[ByRefEvent]
public record struct AfterLungDamageChangedEvent;

View File

@@ -0,0 +1,69 @@
using Content.Shared.Alert;
using Content.Shared.FixedPoint;
using Content.Shared.Rejuvenate;
namespace Content.Shared._Offbrand.Wounds;
public sealed class LungDamageSystem : EntitySystem
{
[Dependency] private readonly AlertsSystem _alerts = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LungDamageComponent, BeforeBreathEvent>(OnBeforeBreath);
SubscribeLocalEvent<LungDamageComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<LungDamageAlertsComponent, AfterLungDamageChangedEvent>(OnLungDamageChanged);
SubscribeLocalEvent<LungDamageAlertsComponent, ComponentShutdown>(OnAlertsShutdown);
}
private void OnBeforeBreath(Entity<LungDamageComponent> ent, ref BeforeBreathEvent args)
{
args.BreathVolume *= 1f - MathF.Pow(ent.Comp.Damage.Float() / ent.Comp.MaxDamage.Float(), 3f);
}
public void TryModifyDamage(Entity<LungDamageComponent?> ent, FixedPoint2 damage)
{
if (!Resolve(ent, ref ent.Comp))
return;
ent.Comp.Damage = FixedPoint2.Clamp(ent.Comp.Damage + damage, FixedPoint2.Zero, ent.Comp.MaxDamage);
Dirty(ent);
var evt = new AfterLungDamageChangedEvent();
RaiseLocalEvent(ent, ref evt);
}
private void OnRejuvenate(Entity<LungDamageComponent> ent, ref RejuvenateEvent args)
{
ent.Comp.Damage = FixedPoint2.Zero;
Dirty(ent);
var evt = new AfterLungDamageChangedEvent();
RaiseLocalEvent(ent, ref evt);
}
private void OnLungDamageChanged(Entity<LungDamageAlertsComponent> ent, ref AfterLungDamageChangedEvent args)
{
var lungDamage = Comp<LungDamageComponent>(ent);
var targetAlert = ent.Comp.AlertThresholds.HighestMatch(lungDamage.Damage);
if (targetAlert == ent.Comp.CurrentAlertThresholdState)
return;
if (targetAlert is { } alert)
{
_alerts.ShowAlert(ent.Owner, alert);
}
else
{
_alerts.ClearAlertCategory(ent.Owner, ent.Comp.AlertCategory);
}
}
private void OnAlertsShutdown(Entity<LungDamageAlertsComponent> ent, ref ComponentShutdown args)
{
_alerts.ClearAlertCategory(ent.Owner, ent.Comp.AlertCategory);
}
}

View File

@@ -45,6 +45,12 @@ public sealed partial class WoundableHealthAnalyzerData
[DataField] [DataField]
public AttributeRating HeartRateRating; public AttributeRating HeartRateRating;
[DataField]
public double LungHealth;
[DataField]
public AttributeRating LungHealthRating;
[DataField] [DataField]
public bool AnyVitalCritical; public bool AnyVitalCritical;
@@ -124,8 +130,12 @@ public abstract class SharedWoundableHealthAnalyzerSystem : EntitySystem
if (!TryComp<BrainDamageComponent>(uid, out var brainDamage)) if (!TryComp<BrainDamageComponent>(uid, out var brainDamage))
return null; return null;
if (!TryComp<LungDamageComponent>(uid, out var lungDamage))
return null;
var brainHealth = 1d - ((double)brainDamage.Damage / (double)brainDamage.MaxDamage); var brainHealth = 1d - ((double)brainDamage.Damage / (double)brainDamage.MaxDamage);
var heartHealth = 1d - ((double)heartrate.Damage / (double)heartrate.MaxDamage); var heartHealth = 1d - ((double)heartrate.Damage / (double)heartrate.MaxDamage);
var lungHealth = 1d - ((double)lungDamage.Damage / (double)lungDamage.MaxDamage);
var strain = _heart.HeartStrain((uid, heartrate)).Double() / 4d; var strain = _heart.HeartStrain((uid, heartrate)).Double() / 4d;
var (upper, lower) = _heart.BloodPressure((uid, heartrate)); var (upper, lower) = _heart.BloodPressure((uid, heartrate));
var oxygenation = _heart.BloodOxygenation((uid, heartrate)).Double(); var oxygenation = _heart.BloodOxygenation((uid, heartrate)).Double();
@@ -149,6 +159,8 @@ public abstract class SharedWoundableHealthAnalyzerSystem : EntitySystem
BloodFlowRating = RateHigherIsBetter(flow), BloodFlowRating = RateHigherIsBetter(flow),
HeartRate = _heart.HeartRate((uid, heartrate)).Int(), HeartRate = _heart.HeartRate((uid, heartrate)).Int(),
HeartRateRating = !heartrate.Running ? AttributeRating.Dangerous : RateHigherIsWorse(strain), HeartRateRating = !heartrate.Running ? AttributeRating.Dangerous : RateHigherIsWorse(strain),
LungHealth = lungHealth,
LungHealthRating = RateHigherIsBetter(lungHealth),
AnyVitalCritical = _shockThresholds.IsCritical(uid) || _brainDamage.IsCritical(uid) || _heart.IsCritical(uid), AnyVitalCritical = _shockThresholds.IsCritical(uid) || _brainDamage.IsCritical(uid) || _heart.IsCritical(uid),
Wounds = withWounds ? SampleWounds(uid) : null, Wounds = withWounds ? SampleWounds(uid) : null,
Reagents = reagents, Reagents = reagents,

View File

@@ -33,3 +33,12 @@ alerts-critical-brain-damage-desc = Your brain cannot control your body.
alerts-brain-death-name = [color=crimson]Brain Dead[/color] alerts-brain-death-name = [color=crimson]Brain Dead[/color]
alerts-brain-death-desc = Your brain has faded away into nothingness. alerts-brain-death-desc = Your brain has faded away into nothingness.
alerts-minor-lung-damage-name = [color=yellow]Minor Lung Damage[/color]
alerts-minor-lung-damage-desc = Your lungs have taken minor damage. Turn up the pressure on your internals and seek care.
alerts-severe-lung-damage-name = [color=red]Severe Lung Damage[/color]
alerts-severe-lung-damage-desc = Your lungs are struggling to breathe. Turn up the pressure on your internals and seek care promptly.
alerts-critical-lung-damage-name = [color=crimson]Lung Failure[/color]
alerts-critical-lung-damage-desc = You cannot breathe well if at all. Seek care promptly.

View File

@@ -21,4 +21,20 @@ construction-step-heart-damage-range = { $max ->
} }
} }
construction-examine-lung-damage-range = { $max ->
[2147483648] The target needs to have at least {NATURALFIXED($min, 2)} lung damage.
*[other] { $min ->
[0] The target needs to have at most {NATURALFIXED($max, 2)} lung damage.
*[other] The target needs to have between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} lung damage.
}
}
construction-step-lung-damage-range = { $max ->
[2147483648] The target needs to have at least {NATURALFIXED($min, 2)} lung damage.
*[other] { $min ->
[0] The target needs to have at most {NATURALFIXED($max, 2)} lung damage.
*[other] The target needs to have between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} lung damage.
}
}
construction-component-to-perform-header = To perform {$targetName}... construction-component-to-perform-header = To perform {$targetName}...

View File

@@ -24,6 +24,14 @@ reagent-effect-guidebook-modify-heart-damage-deals = { $chance ->
[1] Deals { $amount } heart damage [1] Deals { $amount } heart damage
*[other] deal { $amount } heart damage *[other] deal { $amount } heart damage
} }
reagent-effect-guidebook-modify-lung-damage-heals = { $chance ->
[1] Heals { $amount } lung health
*[other] heal { $amount } lung health
}
reagent-effect-guidebook-modify-lung-damage-deals = { $chance ->
[1] Deals { $amount } lung damage
*[other] deal { $amount } lung damage
}
reagent-effect-guidebook-clamp-wounds = { $probability -> reagent-effect-guidebook-clamp-wounds = { $probability ->
[1] Stops bleeding in wounds with { NATURALPERCENT($chance, 2) } chance per wound [1] Stops bleeding in wounds with { NATURALPERCENT($chance, 2) } chance per wound
*[other] stop bleeding in wounds with { NATURALPERCENT($chance, 2) } chance per wound *[other] stop bleeding in wounds with { NATURALPERCENT($chance, 2) } chance per wound
@@ -35,6 +43,13 @@ reagent-effect-condition-guidebook-heart-damage = { $max ->
*[other] it has between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} heart damage *[other] it has between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} heart damage
} }
} }
reagent-effect-condition-guidebook-lung-damage = { $max ->
[2147483648] it has at least {NATURALFIXED($min, 2)} lung damage
*[other] { $min ->
[0] it has at most {NATURALFIXED($max, 2)} lung damage
*[other] it has between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} lung damage
}
}
reagent-effect-condition-guidebook-brain-damage = { $max -> reagent-effect-condition-guidebook-brain-damage = { $max ->
[2147483648] it has at least {NATURALFIXED($min, 2)} brain damage [2147483648] it has at least {NATURALFIXED($min, 2)} brain damage
*[other] { $min -> *[other] { $min ->

View File

@@ -14,9 +14,11 @@ health-analyzer-window-entity-blood-oxygenation-text = Blood Saturation:
health-analyzer-window-entity-blood-flow-text = Blood Flow: health-analyzer-window-entity-blood-flow-text = Blood Flow:
health-analyzer-window-entity-heart-rate-text = Heart Rate: health-analyzer-window-entity-heart-rate-text = Heart Rate:
health-analyzer-window-entity-heart-health-text = Heart Health: health-analyzer-window-entity-heart-health-text = Heart Health:
health-analyzer-window-entity-lung-health-text = Lung Health:
health-analyzer-window-entity-brain-health-value = {$value}% { -health-analyzer-rating(rating: $rating) } health-analyzer-window-entity-brain-health-value = {$value}% { -health-analyzer-rating(rating: $rating) }
health-analyzer-window-entity-heart-health-value = {$value}% { -health-analyzer-rating(rating: $rating) } health-analyzer-window-entity-heart-health-value = {$value}% { -health-analyzer-rating(rating: $rating) }
health-analyzer-window-entity-lung-health-value = {$value}% { -health-analyzer-rating(rating: $rating) }
health-analyzer-window-entity-heart-rate-value = {$value}bpm { -health-analyzer-rating(rating: $rating) } health-analyzer-window-entity-heart-rate-value = {$value}bpm { -health-analyzer-rating(rating: $rating) }
health-analyzer-window-entity-blood-oxygenation-value = {$value}% { -health-analyzer-rating(rating: $rating) } health-analyzer-window-entity-blood-oxygenation-value = {$value}% { -health-analyzer-rating(rating: $rating) }
health-analyzer-window-entity-blood-pressure-value = {$systolic}/{$diastolic} { -health-analyzer-rating(rating: $rating) } health-analyzer-window-entity-blood-pressure-value = {$systolic}/{$diastolic} { -health-analyzer-rating(rating: $rating) }
@@ -101,6 +103,13 @@ health-analyzer-cryostasis-temperature-tooltip =
This temperature has a cryostasis factor of {$factor}%. This temperature has a cryostasis factor of {$factor}%.
health-analyzer-lung-health-tooltip =
The patient's lung health.
The lower this number, the more difficulty they have breathing.
If the lung health is low, consider putting the patient on higher-pressure internals.
health-analyzer-blood-tooltip = health-analyzer-blood-tooltip =
The patient's blood volume. The patient's blood volume.

View File

@@ -14,6 +14,12 @@ surgery-heart-treatment-suture-desc = Treats heart damage.
surgery-heart-treatment-medicated-suture-name = heart treatment (medicated sutures) surgery-heart-treatment-medicated-suture-name = heart treatment (medicated sutures)
surgery-heart-treatment-medicated-suture-desc = Treats heart damage. surgery-heart-treatment-medicated-suture-desc = Treats heart damage.
surgery-lung-treatment-suture-name = lung treatment (sutures)
surgery-lung-treatment-suture-desc = Treats lung damage.
surgery-lung-treatment-medicated-suture-name = lung treatment (medicated sutures)
surgery-lung-treatment-medicated-suture-desc = Treats lung damage.
surgery-husking-treatment-name = husking treatment surgery-husking-treatment-name = husking treatment
surgery-husking-treatment-desc = Reconstructs a husked body. surgery-husking-treatment-desc = Reconstructs a husked body.

View File

@@ -7,6 +7,7 @@
- category: Health - category: Health
- category: Pain # Offbrand - category: Pain # Offbrand
- category: BrainDamage # Offbrand - category: BrainDamage # Offbrand
- category: LungDamage # Offbrand
- category: Stamina - category: Stamina
- alertType: SuitPower - alertType: SuitPower
- category: Internals - category: Internals

View File

@@ -224,6 +224,7 @@
- BaseMobHeartrate # Offbrand - BaseMobHeartrate # Offbrand
- BaseMobBrain # Offbrand - BaseMobBrain # Offbrand
- BaseMobCryostasis # Offbrand - BaseMobCryostasis # Offbrand
- BaseMobLungDamage # Offbrand
id: BaseMobSpeciesOrganic id: BaseMobSpeciesOrganic
abstract: true abstract: true
components: components:

View File

@@ -202,6 +202,11 @@
conditions: conditions:
- !type:Temperature - !type:Temperature
max: 213.0 max: 213.0
- !type:ModifyLungDamage
amount: -0.3
conditions:
- !type:Temperature
max: 213.0
- !type:EvenHealthChange - !type:EvenHealthChange
conditions: conditions:
- !type:Temperature - !type:Temperature

View File

@@ -339,6 +339,8 @@
damage: damage:
groups: groups:
Airloss: 10 Airloss: 10
- !type:ModifyLungDamage # Offbrand
amount: 2
- type: reagent - type: reagent
id: MindbreakerToxin id: MindbreakerToxin
@@ -515,6 +517,11 @@
conditions: conditions:
- !type:MetaboliteThreshold - !type:MetaboliteThreshold
min: 15 min: 15
- !type:ModifyLungDamage
amount: 0.1
conditions:
- !type:MetaboliteThreshold
min: 15
- !type:AdjustTemperature - !type:AdjustTemperature
amount: 3000 amount: 3000
conditions: conditions:

View File

@@ -32,6 +32,36 @@
- type: alertCategory - type: alertCategory
id: BrainDamage id: BrainDamage
- type: alertCategory
id: LungDamage
- type: alert
id: MinorLungDamage
category: LungDamage
icons:
- sprite: /Textures/_Offbrand/Alerts/lung_damage.rsi
state: minor
name: alerts-minor-lung-damage-name
description: alerts-minor-lung-damage-desc
- type: alert
id: SevereLungDamage
category: LungDamage
icons:
- sprite: /Textures/_Offbrand/Alerts/lung_damage.rsi
state: severe
name: alerts-severe-lung-damage-name
description: alerts-severe-lung-damage-desc
- type: alert
id: CriticalLungDamage
category: LungDamage
icons:
- sprite: /Textures/_Offbrand/Alerts/lung_damage.rsi
state: critical
name: alerts-critical-lung-damage-name
description: alerts-critical-lung-damage-desc
- type: alert - type: alert
id: SuppressedPain id: SuppressedPain
category: Pain category: Pain

View File

@@ -297,3 +297,22 @@
- type: CryostasisFactor - type: CryostasisFactor
temperatureCoefficient: -0.059 temperatureCoefficient: -0.059
temperatureConstant: 19 temperatureConstant: 19
- type: entity
abstract: true
id: BaseMobLungDamage
components:
- type: LungDamage
damage: 0
maxDamage: 100
- type: LungDamageOnInhaledAirTemperature
heatCoefficient: 0.005
heatConstant: -1.375
coldCoefficient: -0.01
coldConstant: 3
- type: LungDamageAlerts
alertThresholds:
15: MinorLungDamage
40: SevereLungDamage
60: CriticalLungDamage
alertCategory: LungDamage

View File

@@ -169,6 +169,11 @@
conditions: conditions:
- !type:HeartDamage - !type:HeartDamage
max: 25 max: 25
- !type:ModifyLungDamage
amount: -0.2
conditions:
- !type:LungDamage
max: 50
- !type:HealthChange - !type:HealthChange
conditions: conditions:
- !type:ReagentThreshold - !type:ReagentThreshold
@@ -211,6 +216,11 @@
conditions: conditions:
- !type:Temperature - !type:Temperature
max: 170.0 max: 170.0
- !type:ModifyLungDamage
amount: -0.6
conditions:
- !type:Temperature
max: 170.0
- !type:EvenHealthChange - !type:EvenHealthChange
conditions: conditions:
- !type:Temperature - !type:Temperature
@@ -336,7 +346,7 @@
- !type:TotalGroupDamage - !type:TotalGroupDamage
group: Airloss group: Airloss
min: 4 min: 4
- !type:ModifyHeartDamage - !type:ModifyLungDamage
amount: 0.05 amount: 0.05
- type: reagent - type: reagent

View File

@@ -31,6 +31,28 @@
category: Surgery category: Surgery
objectType: NodeToNode objectType: NodeToNode
- type: construction
hide: true
id: LungTreatmentSuture
name: surgery-lung-treatment-suture-name
description: surgery-lung-treatment-suture-desc
graph: SurgeryGraph
startNode: Base
targetNode: LungTreatmentSuture
category: Surgery
objectType: NodeToNode
- type: construction
hide: true
id: LungTreatmentMedicatedSuture
name: surgery-lung-treatment-medicated-suture-name
description: surgery-lung-treatment-medicated-suture-desc
graph: SurgeryGraph
startNode: Base
targetNode: LungTreatmentMedicatedSuture
category: Surgery
objectType: NodeToNode
- type: construction - type: construction
hide: true hide: true
id: HuskingTreatment id: HuskingTreatment

View File

@@ -157,6 +157,36 @@
steps: steps:
- tool: Drilling - tool: Drilling
doAfter: 2 doAfter: 2
- to: OpenRibCageRecoupling
steps:
- tool: Recoupling
doAfter: 1
- node: OpenRibCageRecoupling
edges:
- to: OpenRibCage
steps:
- tool: Clamping
doAfter: 1
- to: LungTreatmentSuture
conditions: &lung-damage-conditions
- !type:LungDamage
min: 1
completed:
- !type:ChangeLungDamage
amount: -5
steps:
- material: Suture
amount: 1
doAfter: 5
- to: LungTreatmentMedicatedSuture
conditions: *lung-damage-conditions
completed:
- !type:ChangeLungDamage
amount: -10
steps:
- material: MedicatedSuture
amount: 1
doAfter: 3
- node: OpenRibCageMending - node: OpenRibCageMending
edges: edges:
- to: OpenRibCageSetting - to: OpenRibCageSetting
@@ -204,6 +234,20 @@
- !type:SetNode - !type:SetNode
node: OpenRibCage node: OpenRibCage
repeatConditions: *heart-damage-conditions repeatConditions: *heart-damage-conditions
- node: LungTreatmentSuture
header: construction-component-to-perform-header
localizedName: surgery-lung-treatment-suture-name
actions:
- !type:SetNode
node: OpenRibCageRecoupling
repeatConditions: *lung-damage-conditions
- node: LungTreatmentMedicatedSuture
header: construction-component-to-perform-header
localizedName: surgery-lung-treatment-medicated-suture-name
actions:
- !type:SetNode
node: OpenRibCageRecoupling
repeatConditions: *lung-damage-conditions
- node: HuskingTreatment - node: HuskingTreatment
header: construction-component-to-perform-header header: construction-component-to-perform-header
localizedName: surgery-husking-treatment-name localizedName: surgery-husking-treatment-name

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

View File

@@ -0,0 +1,20 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "sprites by sowelipililimute, inspired by sprites from /tg/station",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "minor"
},
{
"name": "severe"
},
{
"name": "critical"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B