Fix floating damages
This commit is contained in:
@@ -236,7 +236,7 @@ namespace Content.Shared.Damage
|
|||||||
damage = ApplyUniversalAllModifiers(damage);
|
damage = ApplyUniversalAllModifiers(damage);
|
||||||
|
|
||||||
// Begin Offbrand
|
// Begin Offbrand
|
||||||
var beforeCommit = new Content.Shared._Offbrand.Wounds.BeforeDamageCommitEvent(damage);
|
var beforeCommit = new Content.Shared._Offbrand.Wounds.BeforeDamageCommitEvent(damage, forceRefresh);
|
||||||
RaiseLocalEvent(uid.Value, ref beforeCommit);
|
RaiseLocalEvent(uid.Value, ref beforeCommit);
|
||||||
damage = beforeCommit.Damage;
|
damage = beforeCommit.Damage;
|
||||||
// End Offbrand
|
// End Offbrand
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Shared.Damage;
|
|||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared._Offbrand.Wounds;
|
namespace Content.Shared._Offbrand.Wounds;
|
||||||
|
|
||||||
@@ -60,6 +61,35 @@ public sealed partial class Damages : IEquatable<Damages>, IRobustCloneable<Dama
|
|||||||
return specifier;
|
return specifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Damages Heal(DamageSpecifier incoming)
|
||||||
|
{
|
||||||
|
var remainder = new Damages(incoming);
|
||||||
|
|
||||||
|
foreach (var (type, value) in remainder.DamageDict)
|
||||||
|
{
|
||||||
|
DebugTools.Assert(value <= 0);
|
||||||
|
|
||||||
|
if (!DamageDict.TryGetValue(type, out var existing))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var newValue = existing + value;
|
||||||
|
if (newValue <= 0)
|
||||||
|
{
|
||||||
|
remainder.DamageDict[type] = newValue;
|
||||||
|
newValue = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remainder.DamageDict[type] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DamageDict[type] = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
remainder.TrimZeros();
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
public static Damages operator +(Damages damages, DamageSpecifier specifier)
|
public static Damages operator +(Damages damages, DamageSpecifier specifier)
|
||||||
{
|
{
|
||||||
var newDamages = damages.Clone();
|
var newDamages = damages.Clone();
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ namespace Content.Shared._Offbrand.Wounds;
|
|||||||
|
|
||||||
public sealed class TendingSystem : EntitySystem
|
public sealed class TendingSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
|
||||||
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
@@ -137,10 +136,7 @@ public sealed class TendingSystem : EntitySystem
|
|||||||
if (!TryComp<TendingComponent>(args.Used, out var tending))
|
if (!TryComp<TendingComponent>(args.Used, out var tending))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_woundable.TendWound(ent, tending.Damage);
|
_woundable.TendWound(target, ent, tending.Damage);
|
||||||
|
|
||||||
if (tending.Damage is { } damage)
|
|
||||||
_damageable.TryChangeDamage(target, damage, true, origin: args.Args.User);
|
|
||||||
|
|
||||||
var hasMoreItems = true;
|
var hasMoreItems = true;
|
||||||
if (TryComp<StackComponent>(args.Used.Value, out var stackComp))
|
if (TryComp<StackComponent>(args.Used.Value, out var stackComp))
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public record struct WoundGetDamageEvent(DamageSpecifier Accumulator);
|
|||||||
/// Raised before damage is applied to a Damageable but after applying modifiers
|
/// Raised before damage is applied to a Damageable but after applying modifiers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct BeforeDamageCommitEvent(DamageSpecifier Damage);
|
public record struct BeforeDamageCommitEvent(DamageSpecifier Damage, bool ForceRefresh);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised when the values for a damage overlay may have changed
|
/// Raised when the values for a damage overlay may have changed
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Content.Shared.StatusEffectNew;
|
|||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared._Offbrand.Wounds;
|
namespace Content.Shared._Offbrand.Wounds;
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ public sealed class WoundableSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<WoundComponent, StatusEffectRelayedEvent<WoundGetDamageEvent>>(OnWoundGetDamage);
|
SubscribeLocalEvent<WoundComponent, StatusEffectRelayedEvent<WoundGetDamageEvent>>(OnWoundGetDamage);
|
||||||
SubscribeLocalEvent<WoundComponent, StatusEffectRelayedEvent<GetWoundsWithSpaceEvent>>(OnGetWoundsWithSpace);
|
SubscribeLocalEvent<WoundComponent, StatusEffectRelayedEvent<GetWoundsWithSpaceEvent>>(OnGetWoundsWithSpace);
|
||||||
|
SubscribeLocalEvent<WoundComponent, StatusEffectRemovedEvent>(OnWoundRemoved);
|
||||||
|
|
||||||
SubscribeLocalEvent<PainfulWoundComponent, StatusEffectRelayedEvent<GetPainEvent>>(OnGetPain);
|
SubscribeLocalEvent<PainfulWoundComponent, StatusEffectRelayedEvent<GetPainEvent>>(OnGetPain);
|
||||||
SubscribeLocalEvent<HealableWoundComponent, StatusEffectRelayedEvent<HealWoundsEvent>>(OnHealHealableWounds);
|
SubscribeLocalEvent<HealableWoundComponent, StatusEffectRelayedEvent<HealWoundsEvent>>(OnHealHealableWounds);
|
||||||
@@ -117,6 +119,31 @@ public sealed class WoundableSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ValidateWounds(EntityUid ent, DamageSpecifier? incoming)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
var damageable = Comp<DamageableComponent>(ent);
|
||||||
|
|
||||||
|
var evt = new WoundGetDamageEvent(new());
|
||||||
|
RaiseLocalEvent(ent, ref evt);
|
||||||
|
|
||||||
|
foreach (var (type, currentValue) in damageable.Damage.DamageDict)
|
||||||
|
{
|
||||||
|
if (!evt.Accumulator.DamageDict.TryGetValue(type, out var expectedValue))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (incoming is not null && incoming.DamageDict.TryGetValue(type, out var delta) && delta <= 0)
|
||||||
|
{
|
||||||
|
DebugTools.AssertEqual(currentValue + delta, expectedValue, "wounds and damageable after delta don't line up");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugTools.AssertEqual(currentValue, expectedValue, "wounds and damageable don't line up");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private void OnBeforeDamageCommit(Entity<WoundableComponent> ent, ref BeforeDamageCommitEvent args)
|
private void OnBeforeDamageCommit(Entity<WoundableComponent> ent, ref BeforeDamageCommitEvent args)
|
||||||
{
|
{
|
||||||
if (_timing.ApplyingState)
|
if (_timing.ApplyingState)
|
||||||
@@ -124,7 +151,7 @@ public sealed class WoundableSystem : EntitySystem
|
|||||||
|
|
||||||
var damageable = Comp<DamageableComponent>(ent);
|
var damageable = Comp<DamageableComponent>(ent);
|
||||||
|
|
||||||
if (args.Damage.AnyNegative())
|
if (args.Damage.AnyNegative() && !args.ForceRefresh)
|
||||||
OnHealed(ent, DamageSpecifier.GetNegative(args.Damage));
|
OnHealed(ent, DamageSpecifier.GetNegative(args.Damage));
|
||||||
|
|
||||||
var evt = new WoundGetDamageEvent(new());
|
var evt = new WoundGetDamageEvent(new());
|
||||||
@@ -155,6 +182,18 @@ public sealed class WoundableSystem : EntitySystem
|
|||||||
|
|
||||||
args.Damage.DamageDict[type] = deltaValue - delta;
|
args.Damage.DamageDict[type] = deltaValue - delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!args.ForceRefresh)
|
||||||
|
ValidateWounds(ent, args.Damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWoundRemoved(Entity<WoundComponent> ent, ref StatusEffectRemovedEvent args)
|
||||||
|
{
|
||||||
|
if (ent.Comp.Damage.Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_damageable.TryChangeDamage(args.Target, -ent.Comp.Damage.ToSpecifier(), true, false, null, null, forceRefresh: true);
|
||||||
|
ValidateWounds(args.Target, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDamaged(Entity<WoundableComponent> ent, DamageSpecifier overall)
|
private void OnDamaged(Entity<WoundableComponent> ent, DamageSpecifier overall)
|
||||||
@@ -235,23 +274,7 @@ public sealed class WoundableSystem : EntitySystem
|
|||||||
|
|
||||||
var comp = Comp<WoundComponent>(ent);
|
var comp = Comp<WoundComponent>(ent);
|
||||||
|
|
||||||
foreach (var (type, value) in args.Args.Damage.DamageDict)
|
args.Args = args.Args with { Damage = comp.Damage.Heal(args.Args.Damage).ToSpecifier() };
|
||||||
{
|
|
||||||
if (!comp.Damage.DamageDict.TryGetValue(type, out var existing))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var newValue = existing + value;
|
|
||||||
if (newValue <= 0)
|
|
||||||
{
|
|
||||||
args.Args.Damage.DamageDict[type] = newValue;
|
|
||||||
newValue = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
args.Args.Damage.DamageDict[type] = 0;
|
|
||||||
}
|
|
||||||
comp.Damage.DamageDict[type] = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
comp.Damage.TrimZeros();
|
comp.Damage.TrimZeros();
|
||||||
args.Args.Damage.TrimZeros();
|
args.Args.Damage.TrimZeros();
|
||||||
@@ -371,13 +394,31 @@ public sealed class WoundableSystem : EntitySystem
|
|||||||
Dirty(ent);
|
Dirty(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TendWound(Entity<TendableWoundComponent> ent, DamageSpecifier? specifier)
|
public void TendWound(Entity<WoundableComponent?> woundable, Entity<TendableWoundComponent> ent, DamageSpecifier? specifier)
|
||||||
{
|
{
|
||||||
var wound = Comp<WoundComponent>(ent);
|
var wound = Comp<WoundComponent>(ent);
|
||||||
|
|
||||||
ent.Comp.Tended = true;
|
ent.Comp.Tended = true;
|
||||||
if (specifier is { } damage)
|
if (specifier is { } damage)
|
||||||
wound.Damage += damage;
|
{
|
||||||
|
var remainder = wound.Damage.Heal(damage);
|
||||||
|
wound.Damage.TrimZeros();
|
||||||
|
Dirty(ent.Owner, wound);
|
||||||
|
|
||||||
|
if (wound.Damage.Empty)
|
||||||
|
PredictedQueueDel(ent);
|
||||||
|
|
||||||
|
var changeBy = damage - remainder.ToSpecifier();
|
||||||
|
changeBy.TrimZeros();
|
||||||
|
if (changeBy.AnyNegative())
|
||||||
|
{
|
||||||
|
var actualDelta = _damageable.TryChangeDamage(woundable, changeBy, true, false, null, null, forceRefresh: true);
|
||||||
|
DebugTools.Assert(actualDelta is not null);
|
||||||
|
DebugTools.Assert(changeBy.Equals(actualDelta!), $"{changeBy} == {actualDelta!}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidateWounds(woundable, null);
|
||||||
|
}
|
||||||
Dirty(ent);
|
Dirty(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user