Files
tbd-station-14/Content.Shared/_Offbrand/Wounds/MaximumDamageSystem.cs
2025-09-28 22:12:35 -04:00

90 lines
2.7 KiB
C#

using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Shared._Offbrand.Wounds;
public sealed class MaximumDamageSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MaximumDamageComponent, BeforeDamageCommitEvent>(OnBeforeDamageCommit, before: [typeof(WoundableSystem)]);
}
private FixedPoint2 ComputeDelta(FixedPoint2 current, FixedPoint2 incoming, (FixedPoint2 Base, FixedPoint2 Factor) modifier)
{
DebugTools.Assert(incoming > 0);
if (current >= modifier.Base && modifier.Factor != FixedPoint2.Zero)
{
var factor = modifier.Factor.Double();
var @base = modifier.Base.Double();
Func<FixedPoint2, double> fn = x => Math.Log( Math.Abs(factor - @base + x.Double()) ) * factor;
var maximumFromNow = FixedPoint2.New(fn(incoming + current) - fn(current));
return FixedPoint2.Max(incoming - maximumFromNow, FixedPoint2.Zero);
}
else if (modifier.Factor != FixedPoint2.Zero)
{
var delta = FixedPoint2.Max((incoming + current) - modifier.Base, FixedPoint2.Zero);
if (delta <= 0)
return delta;
var adjustedIncoming = incoming - delta;
var adjustedCurrent = current + adjustedIncoming;
var adjustedRemainder = incoming - adjustedIncoming;
return FixedPoint2.Max( delta - ComputeDelta(adjustedCurrent, adjustedRemainder, modifier), FixedPoint2.Zero );
}
else
{
return FixedPoint2.Max((incoming + current) - modifier.Base, FixedPoint2.Zero);
}
}
private void OnBeforeDamageCommit(Entity<MaximumDamageComponent> ent, ref BeforeDamageCommitEvent args)
{
if (_timing.ApplyingState)
return;
var damageable = Comp<DamageableComponent>(ent);
var dict = damageable.Damage.DamageDict;
var hasCloned = false;
foreach (var (type, value) in args.Damage.DamageDict)
{
if (value <= 0)
continue;
if (!dict.TryGetValue(type, out var currentValue))
continue;
if (!ent.Comp.Damage.TryGetValue(type, out var maxValue))
continue;
var delta = ComputeDelta(currentValue, value, maxValue);
if (delta <= 0)
continue;
if (!hasCloned)
{
hasCloned = true;
args.Damage = new(args.Damage);
}
args.Damage.DamageDict[type] -= delta;
}
args.Damage.TrimZeros();
}
}