Generalize ReagentUnit into FixedPoint2 and use it for damage calculations (#5151)
* Damage units * sum ext method
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Reflection;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
@@ -9,18 +10,18 @@ using Robust.UnitTesting.Shared.Serialization;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Chemistry
|
||||
{
|
||||
public class ReagentUnitSerializationTest : SerializationTest
|
||||
public class FixedPoint2SerializationTest : SerializationTest
|
||||
{
|
||||
protected override Assembly[] Assemblies => new[]
|
||||
{
|
||||
typeof(ReagentUnitSerializationTest).Assembly
|
||||
typeof(FixedPoint2SerializationTest).Assembly
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void DeserializeNullTest()
|
||||
{
|
||||
var node = new ValueDataNode("null");
|
||||
var unit = Serialization.ReadValue<ReagentUnit?>(node);
|
||||
var unit = Serialization.ReadValue<FixedPoint2?>(node);
|
||||
|
||||
Assert.That(unit, Is.Null);
|
||||
}
|
||||
@@ -29,15 +30,15 @@ namespace Content.IntegrationTests.Tests.Chemistry
|
||||
public void DeserializeNullDefinitionTest()
|
||||
{
|
||||
var node = new MappingDataNode().Add("unit", "null");
|
||||
var definition = Serialization.ReadValueOrThrow<ReagentUnitTestDefinition>(node);
|
||||
var definition = Serialization.ReadValueOrThrow<FixedPoint2TestDefinition>(node);
|
||||
|
||||
Assert.That(definition.Unit, Is.Null);
|
||||
}
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public class ReagentUnitTestDefinition
|
||||
public class FixedPoint2TestDefinition
|
||||
{
|
||||
[DataField("unit")] public ReagentUnit? Unit { get; set; } = ReagentUnit.New(5);
|
||||
[DataField("unit")] public FixedPoint2? Unit { get; set; } = FixedPoint2.New(5);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Commands;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.MobState;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -56,7 +57,8 @@ namespace Content.IntegrationTests.Tests.Commands
|
||||
Assert.That(mobState.IsIncapacitated, Is.False);
|
||||
|
||||
// Kill the entity
|
||||
DamageSpecifier damage = new(prototypeManager.Index<DamageGroupPrototype>("Toxin"), 10000000);
|
||||
DamageSpecifier damage = new(prototypeManager.Index<DamageGroupPrototype>("Toxin"),
|
||||
FixedPoint2.New(10000000));
|
||||
EntitySystem.Get<DamageableSystem>().TryChangeDamage(human.Uid, damage, true);
|
||||
|
||||
// Check that it is dead
|
||||
@@ -74,7 +76,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
||||
Assert.That(mobState.IsDead, Is.False);
|
||||
Assert.That(mobState.IsIncapacitated, Is.False);
|
||||
|
||||
Assert.That(damageable.TotalDamage, Is.Zero);
|
||||
Assert.That(damageable.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
@@ -108,7 +109,7 @@ namespace Content.IntegrationTests.Tests.Damageable
|
||||
DamageTypePrototype type3b = default!;
|
||||
DamageTypePrototype type3c = default!;
|
||||
|
||||
int typeDamage, groupDamage;
|
||||
FixedPoint2 typeDamage, groupDamage;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
@@ -148,7 +149,7 @@ namespace Content.IntegrationTests.Tests.Damageable
|
||||
|
||||
// Check that damage is evenly distributed over a group if its a nice multiple
|
||||
var types = group3.DamageTypes;
|
||||
var damageToDeal = types.Count() * 5;
|
||||
var damageToDeal = FixedPoint2.New(types.Count() * 5);
|
||||
DamageSpecifier damage = new(group3, damageToDeal);
|
||||
|
||||
sDamageableSystem.TryChangeDamage(uid, damage, true);
|
||||
@@ -166,73 +167,74 @@ namespace Content.IntegrationTests.Tests.Damageable
|
||||
sDamageableSystem.TryChangeDamage(uid, -damage);
|
||||
Assert.That(DamageChanged);
|
||||
DamageChanged = false;
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.Zero);
|
||||
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.Zero));
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
|
||||
Assert.That(typeDamage, Is.Zero);
|
||||
Assert.That(typeDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
}
|
||||
|
||||
// Check that damage works properly if it is NOT perfectly divisible among group members
|
||||
types = group3.DamageTypes;
|
||||
damageToDeal = types.Count() * 5 - 1;
|
||||
damageToDeal = FixedPoint2.New(types.Count() * 5 - 1);
|
||||
damage = new DamageSpecifier(group3, damageToDeal);
|
||||
sDamageableSystem.TryChangeDamage(uid, damage, true);
|
||||
Assert.That(DamageChanged);
|
||||
DamageChanged = false;
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
|
||||
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(damageToDeal));
|
||||
// integer rounding. In this case, first member gets 1 less than others.
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(damageToDeal / types.Count()));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3b.ID], Is.EqualTo(1 + damageToDeal / types.Count()));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3c.ID], Is.EqualTo(1 + damageToDeal / types.Count()));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3b.ID], Is.EqualTo(damageToDeal / types.Count()));
|
||||
|
||||
// last one will get 0.01 less, since its not perfectly divisble by 3
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3c.ID], Is.EqualTo(damageToDeal / types.Count() - 0.01));
|
||||
|
||||
// Heal
|
||||
sDamageableSystem.TryChangeDamage(uid, -damage);
|
||||
Assert.That(DamageChanged);
|
||||
DamageChanged = false;
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.Zero);
|
||||
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.Zero));
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
|
||||
Assert.That(typeDamage, Is.Zero);
|
||||
Assert.That(typeDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
}
|
||||
|
||||
// Test that unsupported groups return false when setting/getting damage (and don't change damage)
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
damage = new DamageSpecifier(group1, 10) + new DamageSpecifier(type2b, 10);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
damage = new DamageSpecifier(group1, FixedPoint2.New(10)) + new DamageSpecifier(type2b, FixedPoint2.New(10));
|
||||
sDamageableSystem.TryChangeDamage(uid, damage, true);
|
||||
Assert.That(DamageChanged, Is.False);
|
||||
Assert.That(sDamageableComponent.DamagePerGroup.TryGetValue(group1.ID, out groupDamage), Is.False);
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type1.ID, out typeDamage), Is.False);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
|
||||
// Test SetAll function
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 10);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(10 * sDamageableComponent.Damage.DamageDict.Count()));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(10 * sDamageableComponent.Damage.DamageDict.Count())));
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
|
||||
// Test 'wasted' healing
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(type3a, 5));
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(type3b, 7));
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -11));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(2));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3b.ID], Is.EqualTo(3));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3c.ID], Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(FixedPoint2.New(1.33)));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3b.ID], Is.EqualTo(FixedPoint2.New(3.33)));
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict[type3c.ID], Is.EqualTo(FixedPoint2.New(0)));
|
||||
|
||||
// Test Over-Healing
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -100));
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, FixedPoint2.New(-100)));
|
||||
Assert.That(DamageChanged);
|
||||
DamageChanged = false;
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
|
||||
// Test that if no health change occurred, returns false
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -100));
|
||||
Assert.That(DamageChanged, Is.False);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Threading.Tasks;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -60,8 +61,8 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
var bruteDamageGroup = sPrototypeManager.Index<DamageGroupPrototype>("TestBrute");
|
||||
var burnDamageGroup = sPrototypeManager.Index<DamageGroupPrototype>("TestBurn");
|
||||
|
||||
DamageSpecifier bruteDamage = new(bruteDamageGroup,5);
|
||||
DamageSpecifier burnDamage = new(burnDamageGroup,5);
|
||||
DamageSpecifier bruteDamage = new(bruteDamageGroup, FixedPoint2.New(5));
|
||||
DamageSpecifier burnDamage = new(burnDamageGroup, FixedPoint2.New(5));
|
||||
|
||||
// Raise brute damage to 5
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage, true);
|
||||
@@ -112,7 +113,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
|
||||
// Lower brute damage to 0
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage * -10);
|
||||
Assert.That(sDamageableComponent.TotalDamage,Is.EqualTo(20));
|
||||
Assert.That(sDamageableComponent.TotalDamage,Is.EqualTo(FixedPoint2.New(20)));
|
||||
|
||||
// No new thresholds reached, healing should not trigger it
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Server.Destructible.Thresholds.Behaviors;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.FixedPoint;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -186,7 +187,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*5, true);
|
||||
|
||||
// Check that the total damage matches
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(50));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(50)));
|
||||
|
||||
// Both thresholds should have triggered
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Exactly(2).Items);
|
||||
@@ -234,7 +235,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
|
||||
// Check that the entity has 0 damage
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
|
||||
|
||||
// Set both thresholds to only trigger once
|
||||
foreach (var destructibleThreshold in sDestructibleComponent.Thresholds)
|
||||
@@ -247,7 +248,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*5, true);
|
||||
|
||||
// Check that the total damage matches
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(50));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(50)));
|
||||
|
||||
// No thresholds should have triggered as they were already triggered before, and they are set to only trigger once
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
@@ -260,7 +261,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
}
|
||||
|
||||
// Check that the total damage matches
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(50));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(50)));
|
||||
|
||||
// They shouldn't have been triggered by changing TriggersOnce
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server.Fluids.Components;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Coordinates;
|
||||
using Content.Shared.FixedPoint;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
@@ -56,7 +57,7 @@ namespace Content.IntegrationTests.Tests.Fluids
|
||||
|
||||
server.Assert(() =>
|
||||
{
|
||||
var solution = new Solution("water", ReagentUnit.New(20));
|
||||
var solution = new Solution("water", FixedPoint2.New(20));
|
||||
var puddle = solution.SpillAt(coordinates, "PuddleSmear");
|
||||
Assert.NotNull(puddle);
|
||||
});
|
||||
@@ -94,7 +95,7 @@ namespace Content.IntegrationTests.Tests.Fluids
|
||||
server.Assert(() =>
|
||||
{
|
||||
var coordinates = grid.ToCoordinates();
|
||||
var solution = new Solution("water", ReagentUnit.New(20));
|
||||
var solution = new Solution("water", FixedPoint2.New(20));
|
||||
var puddle = solution.SpillAt(coordinates, "PuddleSmear");
|
||||
Assert.Null(puddle);
|
||||
});
|
||||
@@ -154,7 +155,7 @@ namespace Content.IntegrationTests.Tests.Fluids
|
||||
// Spawn a puddle
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
var solution = new Solution("water", ReagentUnit.New(amount));
|
||||
var solution = new Solution("water", FixedPoint2.New(amount));
|
||||
puddle = solution.SpillAt(sCoordinates, "PuddleSmear");
|
||||
|
||||
// Check that the puddle was created
|
||||
|
||||
Reference in New Issue
Block a user