Files
tbd-station-14/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs
2023-08-06 12:30:28 +10:00

244 lines
10 KiB
C#

using System.Linq;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.Damageable
{
[TestFixture]
[TestOf(typeof(DamageableComponent))]
[TestOf(typeof(DamageableSystem))]
public sealed class DamageableTest
{
[TestPrototypes]
private const string Prototypes = @"
# Define some damage groups
- type: damageType
id: TestDamage1
- type: damageType
id: TestDamage2a
- type: damageType
id: TestDamage2b
- type: damageType
id: TestDamage3a
- type: damageType
id: TestDamage3b
- type: damageType
id: TestDamage3c
# Define damage Groups with 1,2,3 damage types
- type: damageGroup
id: TestGroup1
damageTypes:
- TestDamage1
- type: damageGroup
id: TestGroup2
damageTypes:
- TestDamage2a
- TestDamage2b
- type: damageGroup
id: TestGroup3
damageTypes:
- TestDamage3a
- TestDamage3b
- TestDamage3c
# This container should not support TestDamage1 or TestDamage2b
- type: damageContainer
id: testDamageContainer
supportedGroups:
- TestGroup3
supportedTypes:
- TestDamage2a
- type: entity
id: TestDamageableEntityId
name: TestDamageableEntityId
components:
- type: Damageable
damageContainer: testDamageContainer
";
[Test]
public async Task TestDamageableComponents()
{
await using var pairTracker = await PoolManager.GetServerClient();
var server = pairTracker.Pair.Server;
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
EntityUid sDamageableEntity = default;
DamageableComponent sDamageableComponent = null;
DamageableSystem sDamageableSystem = null;
DamageGroupPrototype group1 = default!;
DamageGroupPrototype group2 = default!;
DamageGroupPrototype group3 = default!;
DamageTypePrototype type1 = default!;
DamageTypePrototype type2a = default!;
DamageTypePrototype type2b = default!;
DamageTypePrototype type3a = default!;
DamageTypePrototype type3b = default!;
DamageTypePrototype type3c = default!;
FixedPoint2 typeDamage;
await server.WaitPost(() =>
{
var map = sMapManager.CreateMap();
var coordinates = new MapCoordinates(0, 0, map);
sDamageableEntity = sEntityManager.SpawnEntity("TestDamageableEntityId", coordinates);
sDamageableComponent = sEntityManager.GetComponent<DamageableComponent>(sDamageableEntity);
sDamageableSystem = sEntitySystemManager.GetEntitySystem<DamageableSystem>();
group1 = sPrototypeManager.Index<DamageGroupPrototype>("TestGroup1");
group2 = sPrototypeManager.Index<DamageGroupPrototype>("TestGroup2");
group3 = sPrototypeManager.Index<DamageGroupPrototype>("TestGroup3");
type1 = sPrototypeManager.Index<DamageTypePrototype>("TestDamage1");
type2a = sPrototypeManager.Index<DamageTypePrototype>("TestDamage2a");
type2b = sPrototypeManager.Index<DamageTypePrototype>("TestDamage2b");
type3a = sPrototypeManager.Index<DamageTypePrototype>("TestDamage3a");
type3b = sPrototypeManager.Index<DamageTypePrototype>("TestDamage3b");
type3c = sPrototypeManager.Index<DamageTypePrototype>("TestDamage3c");
});
await server.WaitRunTicks(5);
await server.WaitAssertion(() =>
{
var uid = sDamageableEntity;
// Check that the correct types are supported.
Assert.Multiple(() =>
{
Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type1.ID), Is.False);
Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type2a.ID), Is.True);
Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type2b.ID), Is.False);
Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3a.ID), Is.True);
Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3b.ID), Is.True);
Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3c.ID), Is.True);
});
// Check that damage is evenly distributed over a group if its a nice multiple
var types = group3.DamageTypes;
var damageToDeal = FixedPoint2.New(types.Count * 5);
DamageSpecifier damage = new(group3, damageToDeal);
sDamageableSystem.TryChangeDamage(uid, damage, true);
Assert.Multiple(() =>
{
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(damageToDeal));
foreach (var type in types)
{
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
Assert.That(typeDamage, Is.EqualTo(damageToDeal / types.Count));
}
});
// Heal
sDamageableSystem.TryChangeDamage(uid, -damage);
Assert.Multiple(() =>
{
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.EqualTo(FixedPoint2.Zero));
}
});
// Check that damage works properly if it is NOT perfectly divisible among group members
types = group3.DamageTypes;
damageToDeal = FixedPoint2.New(types.Count * 5 - 1);
damage = new DamageSpecifier(group3, damageToDeal);
sDamageableSystem.TryChangeDamage(uid, damage, true);
Assert.Multiple(() =>
{
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(damageToDeal));
Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(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.Multiple(() =>
{
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.EqualTo(FixedPoint2.Zero));
}
// Test that unsupported groups return false when setting/getting damage (and don't change damage)
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.Multiple(() =>
{
Assert.That(sDamageableComponent.DamagePerGroup.TryGetValue(group1.ID, out _), Is.False);
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type1.ID, out typeDamage), Is.False);
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
});
// Test SetAll function
sDamageableSystem.SetAllDamage(sDamageableEntity, sDamageableComponent, 10);
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(10 * sDamageableComponent.Damage.DamageDict.Count)));
sDamageableSystem.SetAllDamage(sDamageableEntity, sDamageableComponent, 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.Multiple(() =>
{
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, FixedPoint2.New(-100)));
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(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
});
await pairTracker.CleanReturnAsync();
}
}
}