ECS damageable (#4529)
* ECS and damage Data * Comments and newlines * Added Comments * Make TryChangeDamageEvent immutable * Remove SetAllDamage event Use public SetAllDamage function instead * Undo destructible mistakes That was some shit code. * Rename DamageData to DamageSpecifier And misc small edits misc * Cache trigger prototypes. * Renaming destructible classes & functions * Revert "Cache trigger prototypes." This reverts commit 86bae15ba6616884dba75f552dfdfbe2d1fb6586. * Replace prototypes with prototype IDs. * Split damage.yml into individual files * move get/handle component state to system * Update HealthChange doc * Make godmode call Dirty() on damageable component * Add Initialize() to fix damage test * Make non-static * uncache resistance set prototype and trim DamageableComponentState * Remove unnecessary Dirty() calls during initialization * RemoveTryChangeDamageEvent * revert Dirty() * Fix MobState relying on DamageableComponent.Dirty() * Fix DisposalUnit Tests. These were previously failing, but because the async was not await-ed, this never raised the exception. After I fixed MobState component, this exception stopped happening and instead the assertions started being tested & failing * Disposal test 2: electric boogaloo * Fix typos/mistakes also add comments and fix spacing. * Use Uids instead of IEntity * fix merge * Comments, a merge issue, and making some damage ignore resistances * Extend DamageSpecifier and use it for DamageableComponent * fix master merge * Fix Disposal unit test. Again. Snapgrids were removed in master * Execute Exectute
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Damage;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.MobState;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -21,7 +21,7 @@ namespace Content.IntegrationTests.Tests.Commands
|
||||
id: DamageableDummy
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: biologicalDamageContainer
|
||||
damageContainer: Biological
|
||||
- type: MobState
|
||||
thresholds:
|
||||
0: !type:NormalMobState {}
|
||||
@@ -47,15 +47,17 @@ namespace Content.IntegrationTests.Tests.Commands
|
||||
var human = entityManager.SpawnEntity("DamageableDummy", MapCoordinates.Nullspace);
|
||||
|
||||
// Sanity check
|
||||
Assert.True(human.TryGetComponent(out IDamageableComponent damageable));
|
||||
Assert.True(human.TryGetComponent(out DamageableComponent damageable));
|
||||
Assert.True(human.TryGetComponent(out IMobStateComponent mobState));
|
||||
mobState.UpdateState(0);
|
||||
Assert.That(mobState.IsAlive, Is.True);
|
||||
Assert.That(mobState.IsCritical, Is.False);
|
||||
Assert.That(mobState.IsDead, Is.False);
|
||||
Assert.That(mobState.IsIncapacitated, Is.False);
|
||||
|
||||
// Kill the entity
|
||||
damageable.TryChangeDamage(prototypeManager.Index<DamageGroupPrototype>("Toxin"), 10000000, true);
|
||||
DamageSpecifier damage = new(prototypeManager.Index<DamageGroupPrototype>("Toxin"), 10000000);
|
||||
EntitySystem.Get<DamageableSystem>().TryChangeDamage(human.Uid, damage, true);
|
||||
|
||||
// Check that it is dead
|
||||
Assert.That(mobState.IsAlive, Is.False);
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Damageable
|
||||
{
|
||||
[TestFixture]
|
||||
[TestOf(typeof(DamageableComponent))]
|
||||
public class AllSupportDamageableTest : ContentIntegrationTest
|
||||
{
|
||||
private const string AllDamageDamageableEntityId = "TestAllDamageDamageableEntityId";
|
||||
|
||||
/// <summary>
|
||||
/// Test a damageContainer with all types supported.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As this should also loads in the damage groups & types in the actual damage.yml, this should also act as a basic test to see if damage.yml is set up properly.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task TestAllSupportDamageableComponent()
|
||||
{
|
||||
var server = StartServerDummyTicker();
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
|
||||
IEntity sFullyDamageableEntity;
|
||||
IDamageableComponent sFullyDamageableComponent = null;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var mapId = sMapManager.NextMapId();
|
||||
var coordinates = new MapCoordinates(0, 0, mapId);
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
// When prototypes are loaded using the ExtraPrototypes option, they seem to be loaded first?
|
||||
// Or at least, no damage prototypes were loaded in by the time that the damageContainer here is loaded.
|
||||
// So for now doing explicit loading of prototypes.
|
||||
// I have no idea what I am doing, but it works.
|
||||
sPrototypeManager.LoadString($@"
|
||||
# we want to test the all damage container
|
||||
- type: damageContainer
|
||||
id: testAllDamageContainer
|
||||
supportAll: true
|
||||
|
||||
# create entities
|
||||
- type: entity
|
||||
id: {AllDamageDamageableEntityId}
|
||||
name: {AllDamageDamageableEntityId}
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: testAllDamageContainer
|
||||
");
|
||||
|
||||
sFullyDamageableEntity = sEntityManager.SpawnEntity(AllDamageDamageableEntityId, coordinates);
|
||||
sFullyDamageableComponent = sFullyDamageableEntity.GetComponent<IDamageableComponent>();
|
||||
|
||||
});
|
||||
|
||||
await server.WaitRunTicks(5);
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
|
||||
// First check that there actually are any damage types/groups
|
||||
// This test depends on a non-empty damage.yml
|
||||
Assert.That(sPrototypeManager.EnumeratePrototypes<DamageTypePrototype>().ToList().Count, Is.GreaterThan(0));
|
||||
Assert.That(sPrototypeManager.EnumeratePrototypes<DamageGroupPrototype>().ToList().Count, Is.GreaterThan(0));
|
||||
|
||||
|
||||
// Can we set and get all damage.
|
||||
Assert.That(sFullyDamageableComponent.TrySetAllDamage(-10), Is.False);
|
||||
Assert.That(sFullyDamageableComponent.TrySetAllDamage(0), Is.True);
|
||||
|
||||
// Test that the all damage container supports every damage type, and that we can get, set, and change
|
||||
// every type with the expected results. Notable: if the damage does not change, they all return false
|
||||
var initialDamage = 10;
|
||||
foreach (var damageType in sPrototypeManager.EnumeratePrototypes<DamageTypePrototype>())
|
||||
{
|
||||
var damage = initialDamage;
|
||||
Assert.That(sFullyDamageableComponent.IsSupportedDamageType(damageType));
|
||||
Assert.That(sFullyDamageableComponent.TrySetDamage(damageType, -damage), Is.False);
|
||||
Assert.That(sFullyDamageableComponent.TrySetDamage(damageType, damage), Is.True);
|
||||
Assert.That(sFullyDamageableComponent.TrySetDamage(damageType, damage), Is.True); // intentional duplicate
|
||||
Assert.That(sFullyDamageableComponent.GetDamage(damageType), Is.EqualTo(damage));
|
||||
Assert.That(sFullyDamageableComponent.TryChangeDamage(damageType, -damage / 2, true), Is.True);
|
||||
Assert.That(sFullyDamageableComponent.TryGetDamage(damageType, out damage), Is.True);
|
||||
Assert.That(damage, Is.EqualTo(initialDamage/2));
|
||||
Assert.That(sFullyDamageableComponent.TryChangeDamage(damageType, damage, true), Is.True);
|
||||
Assert.That(sFullyDamageableComponent.GetDamage(damageType), Is.EqualTo(2* damage));
|
||||
Assert.That(sFullyDamageableComponent.TryChangeDamage(damageType, 0, true), Is.False);
|
||||
}
|
||||
// And again, for every group
|
||||
foreach (var damageGroup in sPrototypeManager.EnumeratePrototypes<DamageGroupPrototype>())
|
||||
{
|
||||
var damage = initialDamage;
|
||||
var groupSize = damageGroup.DamageTypes.Count();
|
||||
Assert.That(sFullyDamageableComponent.IsFullySupportedDamageGroup(damageGroup));
|
||||
Assert.That(sFullyDamageableComponent.IsApplicableDamageGroup(damageGroup));
|
||||
Assert.That(sFullyDamageableComponent.TrySetDamage(damageGroup, -damage), Is.False);
|
||||
Assert.That(sFullyDamageableComponent.TrySetDamage(damageGroup, damage), Is.True);
|
||||
Assert.That(sFullyDamageableComponent.TrySetDamage(damageGroup, damage), Is.True); // intentional duplicate
|
||||
Assert.That(sFullyDamageableComponent.GetDamage(damageGroup), Is.EqualTo(damage * groupSize));
|
||||
Assert.That(sFullyDamageableComponent.TryChangeDamage(damageGroup, -groupSize*damage / 2, true), Is.True);
|
||||
Assert.That(sFullyDamageableComponent.TryGetDamage(damageGroup, out damage), Is.True);
|
||||
Assert.That(damage, Is.EqualTo(groupSize* initialDamage/2));
|
||||
Assert.That(sFullyDamageableComponent.TryChangeDamage(damageGroup, damage, true), Is.True);
|
||||
Assert.That(sFullyDamageableComponent.GetDamage(damageGroup), Is.EqualTo(2*damage));
|
||||
Assert.That(sFullyDamageableComponent.TryChangeDamage(damageGroup, 0, true), Is.False);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
@@ -11,75 +11,76 @@ namespace Content.IntegrationTests.Tests.Damageable
|
||||
{
|
||||
[TestFixture]
|
||||
[TestOf(typeof(DamageableComponent))]
|
||||
[TestOf(typeof(DamageableSystem))]
|
||||
public class DamageableTest : ContentIntegrationTest
|
||||
{
|
||||
private const string DamageableEntityId = "TestDamageableEntityId";
|
||||
private const string Group1Id = "TestGroup1";
|
||||
private const string Group2Id = "TestGroup2";
|
||||
private const string Group3Id = "TestGroup3";
|
||||
private string Prototypes = $@"
|
||||
private const string Prototypes = @"
|
||||
# Define some damage groups
|
||||
- type: damageType
|
||||
id: TestDamage11
|
||||
id: TestDamage1
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage21
|
||||
id: TestDamage2a
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage22
|
||||
id: TestDamage2b
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage31
|
||||
id: TestDamage3a
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage32
|
||||
id: TestDamage3b
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage33
|
||||
id: TestDamage3c
|
||||
|
||||
# Define damage Groups with 1,2,3 damage types
|
||||
- type: damageGroup
|
||||
id: {Group1Id}
|
||||
id: TestGroup1
|
||||
damageTypes:
|
||||
- TestDamage11
|
||||
- TestDamage1
|
||||
|
||||
- type: damageGroup
|
||||
id: {Group2Id}
|
||||
id: TestGroup2
|
||||
damageTypes:
|
||||
- TestDamage21
|
||||
- TestDamage22
|
||||
- TestDamage2a
|
||||
- TestDamage2b
|
||||
|
||||
- type: damageGroup
|
||||
id: {Group3Id}
|
||||
id: TestGroup3
|
||||
damageTypes:
|
||||
- TestDamage31
|
||||
- TestDamage32
|
||||
- TestDamage33
|
||||
- TestDamage3a
|
||||
- TestDamage3b
|
||||
- TestDamage3c
|
||||
|
||||
# we want to test a container that supports only full groups
|
||||
# we will also give full support for group 2 IMPLICITLY by specifying all of its members are supported.
|
||||
- type: resistanceSet
|
||||
id: testResistances
|
||||
# this space is intentionally left blank
|
||||
|
||||
# This container should not support TestDamage1 or TestDamage2b
|
||||
- type: damageContainer
|
||||
id: testSomeDamageContainer
|
||||
id: testDamageContainer
|
||||
defaultResistanceSet: testResistances
|
||||
supportedGroups:
|
||||
- {Group3Id}
|
||||
- TestGroup3
|
||||
supportedTypes:
|
||||
- TestDamage21
|
||||
- TestDamage22
|
||||
- TestDamage2a
|
||||
|
||||
- type: entity
|
||||
id: {DamageableEntityId}
|
||||
name: {DamageableEntityId}
|
||||
id: TestDamageableEntityId
|
||||
name: TestDamageableEntityId
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: testSomeDamageContainer
|
||||
damageContainer: testDamageContainer
|
||||
";
|
||||
|
||||
/// <summary>
|
||||
/// Test a standard damageable components
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only test scenarios where each damage type is a member of exactly one group, and all damageable components support whole groups, not lone damage types.
|
||||
/// </remarks>
|
||||
// public bool & function to determine whether dealing damage resulted in actual damage change
|
||||
public bool DamageChanged = false;
|
||||
public void DamageChangedListener(EntityUid _, DamageableComponent comp, DamageChangedEvent args)
|
||||
{
|
||||
DamageChanged = true;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestDamageableComponents()
|
||||
{
|
||||
@@ -93,360 +94,150 @@ namespace Content.IntegrationTests.Tests.Damageable
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
IEntity sDamageableEntity;
|
||||
IDamageableComponent sDamageableComponent = null;
|
||||
sEntityManager.EventBus.SubscribeLocalEvent<DamageableComponent, DamageChangedEvent>(DamageChangedListener);
|
||||
|
||||
IEntity sDamageableEntity = null;
|
||||
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!;
|
||||
|
||||
int typeDamage, groupDamage;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var mapId = sMapManager.NextMapId();
|
||||
var coordinates = new MapCoordinates(0, 0, mapId);
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
sDamageableEntity = sEntityManager.SpawnEntity(DamageableEntityId, coordinates);
|
||||
sDamageableComponent = sDamageableEntity.GetComponent<IDamageableComponent>();
|
||||
sDamageableEntity = sEntityManager.SpawnEntity("TestDamageableEntityId", coordinates);
|
||||
sDamageableComponent = sDamageableEntity.GetComponent<DamageableComponent>();
|
||||
sDamageableSystem = sEntitySystemManager.GetEntitySystem<DamageableSystem>();
|
||||
|
||||
group1 = sPrototypeManager.Index<DamageGroupPrototype>(Group1Id);
|
||||
group2 = sPrototypeManager.Index<DamageGroupPrototype>(Group2Id);
|
||||
group3 = sPrototypeManager.Index<DamageGroupPrototype>(Group3Id);
|
||||
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(() =>
|
||||
{
|
||||
// Check that the correct groups are supported by the container
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(group1), Is.False);
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(group2), Is.True);
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(group3), Is.True);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group1), Is.False);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group2), Is.True);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group3), Is.True);
|
||||
var uid = sDamageableEntity.Uid;
|
||||
|
||||
// Check that the correct types are supported:
|
||||
foreach (var group in sPrototypeManager.EnumeratePrototypes<DamageGroupPrototype>())
|
||||
// Check that the correct types are supported.
|
||||
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 = types.Count() * 5;
|
||||
DamageSpecifier damage = new(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));
|
||||
foreach (var type in types)
|
||||
{
|
||||
foreach(var type in group.DamageTypes)
|
||||
{
|
||||
if (sDamageableComponent.IsFullySupportedDamageGroup(group))
|
||||
{
|
||||
Assert.That(sDamageableComponent.IsSupportedDamageType(type), Is.True);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.That(sDamageableComponent.IsSupportedDamageType(type), Is.False);
|
||||
}
|
||||
}
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
|
||||
Assert.That(typeDamage, Is.EqualTo(damageToDeal / types.Count()));
|
||||
}
|
||||
|
||||
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group1), Is.False);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group2), Is.True);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group3), Is.True);
|
||||
|
||||
// Check that damage works properly if perfectly divisible among group members
|
||||
int damageToDeal, groupDamage, typeDamage; ;
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
foreach (var damageGroup in sDamageableComponent.FullySupportedDamageGroups)
|
||||
// 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));
|
||||
foreach (var type in types)
|
||||
{
|
||||
var types = damageGroup.DamageTypes;
|
||||
|
||||
// Damage
|
||||
damageToDeal = types.Count() * 5;
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(damageGroup, damageToDeal, true), Is.True);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
|
||||
Assert.That(sDamageableComponent.TryGetDamage(damageGroup, out groupDamage), Is.True);
|
||||
Assert.That(groupDamage, Is.EqualTo(damageToDeal));
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.TryGetDamage(type, out typeDamage), Is.True);
|
||||
Assert.That(typeDamage, Is.EqualTo(damageToDeal / types.Count()));
|
||||
}
|
||||
|
||||
// Heal
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(damageGroup, -damageToDeal, true), Is.True);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.Zero);
|
||||
Assert.That(sDamageableComponent.TryGetDamage(damageGroup, out groupDamage), Is.True);
|
||||
Assert.That(groupDamage, Is.Zero);
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.TryGetDamage(type, out typeDamage), Is.True);
|
||||
Assert.That(typeDamage, Is.Zero);
|
||||
}
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
|
||||
Assert.That(typeDamage, Is.Zero);
|
||||
}
|
||||
|
||||
// Check that damage works properly if it is NOT perfectly divisible among group members
|
||||
foreach (var damageGroup in sDamageableComponent.FullySupportedDamageGroups)
|
||||
types = group3.DamageTypes;
|
||||
damageToDeal = 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()));
|
||||
|
||||
// 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));
|
||||
foreach (var type in types)
|
||||
{
|
||||
var types = damageGroup.DamageTypes;
|
||||
|
||||
// Damage
|
||||
damageToDeal = types.Count() * 5 - 1;
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(damageGroup, damageToDeal, true), Is.True);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
|
||||
Assert.That(sDamageableComponent.TryGetDamage(damageGroup, out groupDamage), Is.True);
|
||||
Assert.That(groupDamage, Is.EqualTo(damageToDeal));
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.TryGetDamage(type, out typeDamage), Is.True);
|
||||
float targetDamage = ((float) damageToDeal) / types.Count();
|
||||
Assert.That(typeDamage, Is.InRange(targetDamage - 1, targetDamage + 1));
|
||||
}
|
||||
|
||||
// Heal
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(damageGroup, -damageToDeal, true), Is.True);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.Zero);
|
||||
Assert.That(sDamageableComponent.TryGetDamage(damageGroup, out groupDamage), Is.True);
|
||||
Assert.That(groupDamage, Is.Zero);
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.TryGetDamage(type, out typeDamage), Is.True);
|
||||
Assert.That(typeDamage, Is.Zero);
|
||||
}
|
||||
Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
|
||||
Assert.That(typeDamage, Is.Zero);
|
||||
}
|
||||
|
||||
// Test that unsupported groups return false when setting/getting damage (and don't change damage)
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
foreach (var damageGroup in sPrototypeManager.EnumeratePrototypes<DamageGroupPrototype>())
|
||||
{
|
||||
if (sDamageableComponent.IsFullySupportedDamageGroup(damageGroup))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(damageGroup), Is.False);
|
||||
|
||||
var types = damageGroup.DamageTypes;
|
||||
damageToDeal = types.Count() * 5;
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.IsSupportedDamageType(type), Is.False);
|
||||
}
|
||||
;
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(damageGroup, damageToDeal, true), Is.False);
|
||||
Assert.That(sDamageableComponent.TryGetDamage(damageGroup, out groupDamage), Is.False);
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(type, damageToDeal, true), Is.False);
|
||||
Assert.That(sDamageableComponent.TryGetDamage(type, out typeDamage), Is.False);
|
||||
}
|
||||
}
|
||||
// Did damage change?
|
||||
damage = new DamageSpecifier(group1, 10) + new DamageSpecifier(type2b, 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));
|
||||
|
||||
|
||||
// Test total damage function
|
||||
damageToDeal = 10;
|
||||
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(group3, damageToDeal, true));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
|
||||
|
||||
var totalTypeDamage = 0;
|
||||
|
||||
foreach (var damageType in sDamageableComponent.SupportedDamageTypes)
|
||||
{
|
||||
Assert.True(sDamageableComponent.TryGetDamage(damageType, out typeDamage));
|
||||
Assert.That(typeDamage, Is.LessThanOrEqualTo(damageToDeal));
|
||||
|
||||
totalTypeDamage += typeDamage;
|
||||
}
|
||||
Assert.That(totalTypeDamage, Is.EqualTo(damageToDeal));
|
||||
|
||||
|
||||
// Test healing all damage
|
||||
Assert.That(sDamageableComponent.TrySetAllDamage(0));
|
||||
// Test SetAll function
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 10);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(10 * sDamageableComponent.Damage.DamageDict.Count()));
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
|
||||
// Test preferential healing
|
||||
damageToDeal = 12;
|
||||
var damageTypes = group3.DamageTypes.ToArray();
|
||||
// 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));
|
||||
|
||||
// Deal damage
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(damageTypes[0], 17));
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(damageTypes[1], 31));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(48));
|
||||
|
||||
// Heal group damage
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(group3, -11));
|
||||
|
||||
// Check healing (3 + 9)
|
||||
Assert.That(sDamageableComponent.GetDamage(damageTypes[0]), Is.EqualTo(14));
|
||||
Assert.That(sDamageableComponent.GetDamage(damageTypes[1]), Is.EqualTo(23));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(37));
|
||||
|
||||
// Heal group damage
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(group3, -36));
|
||||
|
||||
// Check healing (13 + 23)
|
||||
Assert.That(sDamageableComponent.GetDamage(damageTypes[0]), Is.EqualTo(1));
|
||||
Assert.That(sDamageableComponent.GetDamage(damageTypes[1]), Is.EqualTo(0));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(1));
|
||||
|
||||
//Check Damage
|
||||
Assert.True(sDamageableComponent.TryGetDamage(damageTypes[0], out typeDamage));
|
||||
Assert.That(typeDamage, Is.LessThanOrEqualTo(damageToDeal));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private const string SharedDamageTypeId = "TestSharedDamage";
|
||||
private const string UnsupportedDamageTypeId = "TestUnsupportedDamage";
|
||||
private string Prototypes2 = $@"
|
||||
- type: damageType
|
||||
id: {SharedDamageTypeId}
|
||||
|
||||
- type: damageType
|
||||
id: {UnsupportedDamageTypeId}
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage1
|
||||
|
||||
- type: damageType
|
||||
id: TestDamage2
|
||||
|
||||
- type: damageGroup
|
||||
id: {Group1Id}
|
||||
damageTypes:
|
||||
- {SharedDamageTypeId}
|
||||
|
||||
- type: damageGroup
|
||||
id: {Group2Id}
|
||||
damageTypes:
|
||||
- {SharedDamageTypeId}
|
||||
- TestDamage1
|
||||
|
||||
- type: damageGroup
|
||||
id: {Group3Id}
|
||||
damageTypes:
|
||||
- {SharedDamageTypeId}
|
||||
- TestDamage2
|
||||
- {UnsupportedDamageTypeId}
|
||||
|
||||
# we want to test a container that only partially supports a group:
|
||||
- type: damageContainer
|
||||
id: TestPartiallySupported
|
||||
supportedGroups:
|
||||
- {Group2Id}
|
||||
supportedTypes:
|
||||
- TestDamage2
|
||||
- TestDamage1
|
||||
# does NOT support type {UnsupportedDamageTypeId}, and thus does not fully support group {Group3Id}
|
||||
# TestDamage1 is added twice because it is also in {Group2Id}. This should not cause errors.
|
||||
|
||||
# create entities
|
||||
- type: entity
|
||||
id: {DamageableEntityId}
|
||||
name: {DamageableEntityId}
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: TestPartiallySupported
|
||||
";
|
||||
|
||||
/// <summary>
|
||||
/// Generalized damageable component tests.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Test scenarios where damage types are members of more than one group, or where a component only supports a subset of a group.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task TestGeneralizedDamageableComponent()
|
||||
{
|
||||
var server = StartServerDummyTicker(new ServerContentIntegrationOption
|
||||
{
|
||||
ExtraPrototypes = Prototypes2
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
|
||||
IEntity sDamageableEntity;
|
||||
IDamageableComponent sDamageableComponent = null;
|
||||
|
||||
DamageGroupPrototype group1 = default!;
|
||||
DamageGroupPrototype group2 = default!;
|
||||
DamageGroupPrototype group3 = default!;
|
||||
|
||||
DamageTypePrototype SharedDamageType = default!;
|
||||
DamageTypePrototype UnsupportedDamageType = default!;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
var mapId = sMapManager.NextMapId();
|
||||
var coordinates = new MapCoordinates(0, 0, mapId);
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
sDamageableEntity = sEntityManager.SpawnEntity(DamageableEntityId, coordinates);
|
||||
sDamageableComponent = sDamageableEntity.GetComponent<IDamageableComponent>();
|
||||
|
||||
group1 = sPrototypeManager.Index<DamageGroupPrototype>(Group1Id);
|
||||
group2 = sPrototypeManager.Index<DamageGroupPrototype>(Group2Id);
|
||||
group3 = sPrototypeManager.Index<DamageGroupPrototype>(Group3Id);
|
||||
|
||||
SharedDamageType = sPrototypeManager.Index<DamageTypePrototype>(SharedDamageTypeId);
|
||||
UnsupportedDamageType = sPrototypeManager.Index<DamageTypePrototype>(UnsupportedDamageTypeId);
|
||||
});
|
||||
|
||||
await server.WaitRunTicks(5);
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// All damage types should be applicable
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(group1), Is.True);
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(group2), Is.True);
|
||||
Assert.That(sDamageableComponent.IsApplicableDamageGroup(group3), Is.True);
|
||||
|
||||
// But not all should be fully supported
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group1), Is.True);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group2), Is.True);
|
||||
Assert.That(sDamageableComponent.IsFullySupportedDamageGroup(group3), Is.False);
|
||||
|
||||
// Check that the correct damage types are supported
|
||||
Assert.That(sDamageableComponent.IsSupportedDamageType(SharedDamageType), Is.True);
|
||||
|
||||
// Check that if we deal damage using a type appearing in multiple groups, nothing goes wrong.
|
||||
var damage = 12;
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(SharedDamageType, damage), Is.True);
|
||||
Assert.That(sDamageableComponent.GetDamage(SharedDamageType), Is.EqualTo(damage));
|
||||
Assert.That(sDamageableComponent.GetDamage(group1), Is.EqualTo(damage));
|
||||
Assert.That(sDamageableComponent.GetDamage(group2), Is.EqualTo(damage));
|
||||
Assert.That(sDamageableComponent.GetDamage(group3), Is.EqualTo(damage));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damage));
|
||||
|
||||
// Check that if we deal damage using a group that is not fully supported, the damage is reduced
|
||||
// Note that if damage2 were not neatly divisible by 3, the actual damage reduction would be subject to integer rounding.
|
||||
// How much exactly the damage gets reduced then would depend on the order that the groups were defined in the yaml file
|
||||
// Here we deal 9 damage. It should apply 3 damage to each type, but one type is ignored, resulting in 6 total damage.
|
||||
// However, the damage in group2 and group3 only changes because of one type that overlaps, so they only change by 3
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(group3, 9), Is.True);
|
||||
Assert.That(sDamageableComponent.GetDamage(group1), Is.EqualTo(damage + 3));
|
||||
Assert.That(sDamageableComponent.GetDamage(group2), Is.EqualTo(damage + 3));
|
||||
Assert.That(sDamageableComponent.GetDamage(group3), Is.EqualTo(damage + 6));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damage + 6));
|
||||
|
||||
// Now we check that when healing, no damage is wasted.
|
||||
// Because SharedDamageType has the most damage in group3 (15 vs 3), it will be healed more than the other.
|
||||
// Expect that, up to integer rounding, one is healed 5* more than the other.
|
||||
// We will use a number that does not divide nicely, there will be some integer rounding.
|
||||
Assert.That(sDamageableComponent.TryChangeDamage(group3, -7), Is.True);
|
||||
Assert.That(sDamageableComponent.GetDamage(group1), Is.EqualTo(damage + 3 - 5));
|
||||
Assert.That(sDamageableComponent.GetDamage(group2), Is.EqualTo(damage + 3 - 5));
|
||||
Assert.That(sDamageableComponent.GetDamage(group3), Is.EqualTo(damage + 6 - 7));
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damage + 6 - 7));
|
||||
// Test Over-Healing
|
||||
sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -100));
|
||||
Assert.That(DamageChanged);
|
||||
DamageChanged = false;
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
|
||||
// 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));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -21,11 +21,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
var server = StartServerDummyTicker(new ServerContentIntegrationOption
|
||||
{
|
||||
ExtraPrototypes = Prototypes,
|
||||
ContentBeforeIoC = () =>
|
||||
{
|
||||
IoCManager.Resolve<IComponentFactory>().RegisterClass<TestThresholdListenerComponent>();
|
||||
}
|
||||
ExtraPrototypes = Prototypes
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
@@ -33,10 +29,12 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
IEntity sDestructibleEntity;
|
||||
IDamageableComponent sDamageableComponent = null;
|
||||
TestThresholdListenerComponent sThresholdListenerComponent = null;
|
||||
IEntity sDestructibleEntity = null;
|
||||
DamageableComponent sDamageableComponent = null;
|
||||
TestDestructibleListenerSystem sTestThresholdListenerSystem = null;
|
||||
DamageableSystem sDamageableSystem = null;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
@@ -45,15 +43,16 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDamageGroupEntityId, coordinates);
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
|
||||
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<DamageableComponent>();
|
||||
sTestThresholdListenerSystem = sEntitySystemManager.GetEntitySystem<TestDestructibleListenerSystem>();
|
||||
sDamageableSystem = sEntitySystemManager.GetEntitySystem<DamageableSystem>();
|
||||
});
|
||||
|
||||
await server.WaitRunTicks(5);
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
@@ -61,26 +60,29 @@ 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);
|
||||
|
||||
// Raise brute damage to 5
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 5, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage, true);
|
||||
|
||||
// No thresholds reached yet, the earliest one is at 10 damage
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise brute damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 5, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage, true);
|
||||
|
||||
// No threshold reached, burn needs to be 10 as well
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise burn damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(burnDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, burnDamage * 2, true);
|
||||
|
||||
// One threshold reached, brute 10 + burn 10
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
// Threshold brute 10 + burn 10
|
||||
var msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
var msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
var threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -94,55 +96,55 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.IsInstanceOf<DamageGroupTrigger>(trigger.Triggers[0]);
|
||||
Assert.IsInstanceOf<DamageGroupTrigger>(trigger.Triggers[1]);
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Raise brute damage to 20
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise burn damage to 20
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(burnDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, burnDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Lower brute damage to 0
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, -20, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage * -10);
|
||||
Assert.That(sDamageableComponent.TotalDamage,Is.EqualTo(20));
|
||||
|
||||
// No new thresholds reached, healing should not trigger it
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise brute damage back up to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage * 2, true);
|
||||
|
||||
// 10 brute + 10 burn threshold reached, brute was healed and brought back to its threshold amount and burn stayed the same
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
// 10 brute + 10 burn threshold reached, brute was healed and brought back to its threshold amount and slash stayed the same
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Heal both classes of damage to 0
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, -10, true));
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(burnDamageGroup, -20, true));
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
|
||||
// No new thresholds reached, healing should not trigger it
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise brute damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise burn damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(burnDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, burnDamage * 2, true);
|
||||
|
||||
// Both classes of damage were healed and then raised again, the threshold should have been reached as triggers once is default false
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
// Threshold brute 10 + burn 10
|
||||
msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -156,29 +158,28 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.IsInstanceOf<DamageGroupTrigger>(trigger.Triggers[0]);
|
||||
Assert.IsInstanceOf<DamageGroupTrigger>(trigger.Triggers[1]);
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Change triggers once to true
|
||||
threshold.TriggersOnce = true;
|
||||
|
||||
// Heal brute and burn back to 0
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, -10, true));
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(burnDamageGroup, -10, true));
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
|
||||
// No new thresholds reached from healing
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise brute damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bruteDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise burn damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(burnDamageGroup, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, burnDamage * 2, true);
|
||||
|
||||
// No new thresholds reached as triggers once is set to true and it already triggered before
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -21,21 +21,19 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
var server = StartServerDummyTicker(new ServerContentIntegrationOption
|
||||
{
|
||||
ExtraPrototypes = Prototypes,
|
||||
ContentBeforeIoC = () =>
|
||||
{
|
||||
IoCManager.Resolve<IComponentFactory>().RegisterClass<TestThresholdListenerComponent>();
|
||||
}
|
||||
ExtraPrototypes = Prototypes
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
IEntity sDestructibleEntity;
|
||||
IDamageableComponent sDamageableComponent = null;
|
||||
TestThresholdListenerComponent sThresholdListenerComponent = null;
|
||||
IEntity sDestructibleEntity = null;
|
||||
DamageableComponent sDamageableComponent = null;
|
||||
TestDestructibleListenerSystem sTestThresholdListenerSystem = null;
|
||||
DamageableSystem sDamageableSystem = null;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
@@ -44,15 +42,16 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDamageTypeEntityId, coordinates);
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
|
||||
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<DamageableComponent>();
|
||||
sTestThresholdListenerSystem = sEntitySystemManager.GetEntitySystem<TestDestructibleListenerSystem>();
|
||||
sDamageableSystem = sEntitySystemManager.GetEntitySystem<DamageableSystem>();
|
||||
});
|
||||
|
||||
await server.WaitRunTicks(5);
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
@@ -60,26 +59,29 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
var bluntDamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("TestBlunt");
|
||||
var slashDamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("TestSlash");
|
||||
|
||||
var bluntDamage = new DamageSpecifier(bluntDamageType,5);
|
||||
var slashDamage = new DamageSpecifier(slashDamageType,5);
|
||||
|
||||
// Raise blunt damage to 5
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 5, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage, true);
|
||||
|
||||
// No thresholds reached yet, the earliest one is at 10 damage
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise blunt damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 5, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage, true);
|
||||
|
||||
// No threshold reached, slash needs to be 10 as well
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise slash damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(slashDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, slashDamage * 2, true);
|
||||
|
||||
// One threshold reached, blunt 10 + slash 10
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
// Threshold blunt 10 + slash 10
|
||||
var msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
var msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
var threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -93,55 +95,55 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.IsInstanceOf<DamageTypeTrigger>(trigger.Triggers[0]);
|
||||
Assert.IsInstanceOf<DamageTypeTrigger>(trigger.Triggers[1]);
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Raise blunt damage to 20
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise slash damage to 20
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(slashDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, slashDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Lower blunt damage to 0
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, -20, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * -4, true);
|
||||
|
||||
// No new thresholds reached, healing should not trigger it
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise blunt damage back up to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * 2, true);
|
||||
|
||||
// 10 blunt + 10 slash threshold reached, blunt was healed and brought back to its threshold amount and slash stayed the same
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Heal both types of damage to 0
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, -10, true));
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(slashDamageType, -20, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * -2, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, slashDamage * -4, true);
|
||||
|
||||
// No new thresholds reached, healing should not trigger it
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise blunt damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise slash damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(slashDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, slashDamage * 2, true);
|
||||
|
||||
// Both types of damage were healed and then raised again, the threshold should have been reached as triggers once is default false
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
// Threshold blunt 10 + slash 10
|
||||
msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -155,29 +157,29 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.IsInstanceOf<DamageTypeTrigger>(trigger.Triggers[0]);
|
||||
Assert.IsInstanceOf<DamageTypeTrigger>(trigger.Triggers[1]);
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Change triggers once to true
|
||||
threshold.TriggersOnce = true;
|
||||
|
||||
// Heal blunt and slash back to 0
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, -10, true));
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(slashDamageType, -10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * -2, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, slashDamage * -2, true);
|
||||
|
||||
// No new thresholds reached from healing
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise blunt damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage * 2, true);
|
||||
|
||||
// No new thresholds reached
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Raise slash damage to 10
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(slashDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, slashDamage * 2, true);
|
||||
|
||||
// No new thresholds reached as triggers once is set to true and it already triggered before
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Threading.Tasks;
|
||||
using Content.Server.Destructible.Thresholds;
|
||||
using Content.Server.Destructible.Thresholds.Behaviors;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -20,11 +20,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
var server = StartServerDummyTicker(new ServerContentIntegrationOption
|
||||
{
|
||||
ExtraPrototypes = Prototypes,
|
||||
ContentBeforeIoC = () =>
|
||||
{
|
||||
IoCManager.Resolve<IComponentFactory>().RegisterClass<TestThresholdListenerComponent>();
|
||||
}
|
||||
ExtraPrototypes = Prototypes
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
@@ -32,10 +28,11 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
IEntity sDestructibleEntity = null;
|
||||
IDamageableComponent sDamageableComponent = null;
|
||||
TestThresholdListenerComponent sThresholdListenerComponent = null;
|
||||
DamageableComponent sDamageableComponent = null;
|
||||
TestDestructibleListenerSystem sTestThresholdListenerSystem = null;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
@@ -44,23 +41,24 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDestructionEntityId, coordinates);
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
|
||||
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<DamageableComponent>();
|
||||
sTestThresholdListenerSystem = sEntitySystemManager.GetEntitySystem<TestDestructibleListenerSystem>();
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
var coordinates = sDestructibleEntity.Transform.Coordinates;
|
||||
var bruteDamageGroup = sPrototypeManager.Index<DamageGroupPrototype>("TestBrute");
|
||||
DamageSpecifier bruteDamage = new(bruteDamageGroup,50);
|
||||
|
||||
Assert.DoesNotThrow(() =>
|
||||
{
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bruteDamageGroup, 50, true));
|
||||
EntitySystem.Get<DamageableSystem>().TryChangeDamage(sDestructibleEntity.Uid, bruteDamage, true);
|
||||
});
|
||||
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
var threshold = sThresholdListenerComponent.ThresholdsReached[0].Threshold;
|
||||
var threshold = sTestThresholdListenerSystem.ThresholdsReached[0].Threshold;
|
||||
|
||||
Assert.That(threshold.Triggered, Is.True);
|
||||
Assert.That(threshold.Behaviors.Count, Is.EqualTo(3));
|
||||
|
||||
@@ -27,21 +27,6 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
- type: damageType
|
||||
id: TestCold
|
||||
|
||||
- type: damageType
|
||||
id: TestPoison
|
||||
|
||||
- type: damageType
|
||||
id: TestRadiation
|
||||
|
||||
- type: damageType
|
||||
id: TestAsphyxiation
|
||||
|
||||
- type: damageType
|
||||
id: TestBloodloss
|
||||
|
||||
- type: damageType
|
||||
id: TestCellular
|
||||
|
||||
- type: damageGroup
|
||||
id: TestBrute
|
||||
damageTypes:
|
||||
@@ -56,43 +41,6 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
- TestShock
|
||||
- TestCold
|
||||
|
||||
- type: damageGroup
|
||||
id: TestAirloss
|
||||
damageTypes:
|
||||
- TestAsphyxiation
|
||||
- TestBloodloss
|
||||
|
||||
- type: damageGroup
|
||||
id: TestToxin
|
||||
damageTypes:
|
||||
- TestPoison
|
||||
- TestRadiation
|
||||
|
||||
- type: damageGroup
|
||||
id: TestGenetic
|
||||
damageTypes:
|
||||
- TestCellular
|
||||
|
||||
- type: damageContainer
|
||||
id: TestAllDamageContainer
|
||||
supportAll: true
|
||||
|
||||
|
||||
- type: damageContainer
|
||||
id: TestBiologicalDamageContainer
|
||||
supportedGroups:
|
||||
- TestBrute
|
||||
- TestBurn
|
||||
- TestToxin
|
||||
- TestAirloss
|
||||
- TestGenetic
|
||||
|
||||
- type: damageContainer
|
||||
id: TestMetallicDamageContainer
|
||||
supportedGroups:
|
||||
- TestBrute
|
||||
- TestBurn
|
||||
|
||||
- type: entity
|
||||
id: {SpawnedEntityId}
|
||||
name: {SpawnedEntityId}
|
||||
@@ -102,7 +50,6 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
name: {DestructibleEntityId}
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: TestMetallicDamageContainer
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
@@ -124,14 +71,12 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
max: 1
|
||||
- !type:DoActsBehavior
|
||||
acts: [""Breakage""]
|
||||
- type: TestThresholdListener
|
||||
|
||||
- type: entity
|
||||
id: {DestructibleDestructionEntityId}
|
||||
name: {DestructibleDestructionEntityId}
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: TestMetallicDamageContainer
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
@@ -148,14 +93,12 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
max: 1
|
||||
- !type:DoActsBehavior # This must come last as it destroys the entity.
|
||||
acts: [""Destruction""]
|
||||
- type: TestThresholdListener
|
||||
|
||||
- type: entity
|
||||
id: {DestructibleDamageTypeEntityId}
|
||||
name: {DestructibleDamageTypeEntityId}
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: TestMetallicDamageContainer
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
@@ -167,14 +110,12 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
- !type:DamageTypeTrigger
|
||||
damageType: TestSlash
|
||||
damage: 10
|
||||
- type: TestThresholdListener
|
||||
|
||||
- type: entity
|
||||
id: {DestructibleDamageGroupEntityId}
|
||||
name: {DestructibleDamageGroupEntityId}
|
||||
components:
|
||||
- type: Damageable
|
||||
damageContainer: TestMetallicDamageContainer
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
@@ -185,7 +126,6 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
damage: 10
|
||||
- !type:DamageGroupTrigger
|
||||
damageGroup: TestBurn
|
||||
damage: 10
|
||||
- type: TestThresholdListener";
|
||||
damage: 10";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using Content.Server.Destructible.Thresholds;
|
||||
using Content.Server.Destructible.Thresholds.Behaviors;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -17,7 +17,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
[TestFixture]
|
||||
[TestOf(typeof(DestructibleComponent))]
|
||||
[TestOf(typeof(Threshold))]
|
||||
[TestOf(typeof(DamageThreshold))]
|
||||
public class DestructibleThresholdActivationTest : ContentIntegrationTest
|
||||
{
|
||||
[Test]
|
||||
@@ -25,11 +25,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
var server = StartServerDummyTicker(new ServerContentIntegrationOption
|
||||
{
|
||||
ExtraPrototypes = Prototypes,
|
||||
ContentBeforeIoC = () =>
|
||||
{
|
||||
IoCManager.Resolve<IComponentFactory>().RegisterClass<TestThresholdListenerComponent>();
|
||||
}
|
||||
ExtraPrototypes = Prototypes
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
@@ -37,11 +33,13 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
|
||||
|
||||
IEntity sDestructibleEntity;
|
||||
IDamageableComponent sDamageableComponent = null;
|
||||
IEntity sDestructibleEntity = null; ;
|
||||
DamageableComponent sDamageableComponent = null;
|
||||
DestructibleComponent sDestructibleComponent = null;
|
||||
TestThresholdListenerComponent sThresholdListenerComponent = null;
|
||||
TestDestructibleListenerSystem sTestThresholdListenerSystem = null;
|
||||
DamageableSystem sDamageableSystem = null;
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
@@ -50,34 +48,35 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
sMapManager.CreateMap(mapId);
|
||||
|
||||
sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleEntityId, coordinates);
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<IDamageableComponent>();
|
||||
sDamageableComponent = sDestructibleEntity.GetComponent<DamageableComponent>();
|
||||
sDestructibleComponent = sDestructibleEntity.GetComponent<DestructibleComponent>();
|
||||
sThresholdListenerComponent = sDestructibleEntity.GetComponent<TestThresholdListenerComponent>();
|
||||
sTestThresholdListenerSystem = sEntitySystemManager.GetEntitySystem<TestDestructibleListenerSystem>();
|
||||
sDamageableSystem = sEntitySystemManager.GetEntitySystem<DamageableSystem>();
|
||||
});
|
||||
|
||||
await server.WaitRunTicks(5);
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
var bluntDamageType = sPrototypeManager.Index<DamageTypePrototype>("TestBlunt");
|
||||
var bluntDamage = new DamageSpecifier(sPrototypeManager.Index<DamageTypePrototype>("TestBlunt"), 10);
|
||||
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage, true);
|
||||
|
||||
// No thresholds reached yet, the earliest one is at 20 damage
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage, true);
|
||||
|
||||
// Only one threshold reached, 20
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
// Threshold 20
|
||||
var msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
var msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
var threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -85,15 +84,15 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.NotNull(threshold.Trigger);
|
||||
Assert.That(threshold.Triggered, Is.True);
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 30, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*3, true);
|
||||
|
||||
// One threshold reached, 50, since 20 already triggered before and it has not been healed below that amount
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
// Threshold 50
|
||||
msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -113,50 +112,50 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.NotNull(threshold.Trigger);
|
||||
Assert.That(threshold.Triggered, Is.True);
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Damage for 50 again, up to 100 now
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 50, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*5, true);
|
||||
|
||||
// No thresholds reached as they weren't healed below the trigger amount
|
||||
Assert.IsEmpty(sThresholdListenerComponent.ThresholdsReached);
|
||||
Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached);
|
||||
|
||||
// Set damage to 0
|
||||
sDamageableComponent.TrySetAllDamage(0);
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
|
||||
// Damage for 100, up to 100
|
||||
Assert.True(sDamageableComponent.TryChangeDamage(bluntDamageType, 100, true));
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*10, true);
|
||||
|
||||
// Two thresholds reached as damage increased past the previous, 20 and 50
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(2));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(2));
|
||||
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Heal the entity for 40 damage, down to 60
|
||||
sDamageableComponent.TryChangeDamage(bluntDamageType, -40, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*-4, true);
|
||||
|
||||
// Thresholds don't work backwards
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
|
||||
// Damage for 10, up to 70
|
||||
sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage, true);
|
||||
|
||||
// Not enough healing to de-trigger a threshold
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
|
||||
// Heal by 30, down to 40
|
||||
sDamageableComponent.TryChangeDamage(bluntDamageType, -30, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*-3, true);
|
||||
|
||||
// Thresholds don't work backwards
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
|
||||
// Damage up to 50 again
|
||||
sDamageableComponent.TryChangeDamage(bluntDamageType, 10, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage, true);
|
||||
|
||||
// The 50 threshold should have triggered again, after being healed
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached.Count, Is.EqualTo(1));
|
||||
|
||||
msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
threshold = msg.Threshold;
|
||||
|
||||
// Check that it matches the YAML prototype
|
||||
@@ -178,22 +177,22 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.That(threshold.Triggered, Is.True);
|
||||
|
||||
// Reset thresholds reached
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Heal all damage
|
||||
sDamageableComponent.TrySetAllDamage(0);
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
|
||||
// Damage up to 50
|
||||
sDamageableComponent.TryChangeDamage(bluntDamageType, 50, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*5, true);
|
||||
|
||||
// Check that the total damage matches
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(50));
|
||||
|
||||
// Both thresholds should have triggered
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached, Has.Exactly(2).Items);
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Has.Exactly(2).Items);
|
||||
|
||||
// Verify the first one, should be the lowest one (20)
|
||||
msg = sThresholdListenerComponent.ThresholdsReached[0];
|
||||
msg = sTestThresholdListenerSystem.ThresholdsReached[0];
|
||||
var trigger = (DamageTrigger) msg.Threshold.Trigger;
|
||||
Assert.NotNull(trigger);
|
||||
Assert.That(trigger.Damage, Is.EqualTo(20));
|
||||
@@ -204,7 +203,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.That(threshold.Behaviors, Is.Empty);
|
||||
|
||||
// Verify the second one, should be the highest one (50)
|
||||
msg = sThresholdListenerComponent.ThresholdsReached[1];
|
||||
msg = sTestThresholdListenerSystem.ThresholdsReached[1];
|
||||
trigger = (DamageTrigger) msg.Threshold.Trigger;
|
||||
Assert.NotNull(trigger);
|
||||
Assert.That(trigger.Damage, Is.EqualTo(50));
|
||||
@@ -229,10 +228,10 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.That(threshold.Triggered, Is.True);
|
||||
|
||||
// Reset thresholds reached
|
||||
sThresholdListenerComponent.ThresholdsReached.Clear();
|
||||
sTestThresholdListenerSystem.ThresholdsReached.Clear();
|
||||
|
||||
// Heal the entity completely
|
||||
sDamageableComponent.TrySetAllDamage(0);
|
||||
sDamageableSystem.SetAllDamage(sDamageableComponent, 0);
|
||||
|
||||
// Check that the entity has 0 damage
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(0));
|
||||
@@ -245,13 +244,13 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
}
|
||||
|
||||
// Damage the entity up to 50 damage again
|
||||
sDamageableComponent.TryChangeDamage(bluntDamageType, 50, true);
|
||||
sDamageableSystem.TryChangeDamage(sDestructibleEntity.Uid, bluntDamage*5, true);
|
||||
|
||||
// Check that the total damage matches
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(50));
|
||||
|
||||
// No thresholds should have triggered as they were already triggered before, and they are set to only trigger once
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
|
||||
// Set both thresholds to trigger multiple times
|
||||
foreach (var destructibleThreshold in sDestructibleComponent.Thresholds)
|
||||
@@ -264,7 +263,7 @@ namespace Content.IntegrationTests.Tests.Destructible
|
||||
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(50));
|
||||
|
||||
// They shouldn't have been triggered by changing TriggersOnce
|
||||
Assert.That(sThresholdListenerComponent.ThresholdsReached, Is.Empty);
|
||||
Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using Content.Server.Destructible;
|
||||
using Robust.Shared.GameObjects;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
/// <summary>
|
||||
/// This is just a system for testing destructible thresholds. Whenever any threshold is reached, this will add that
|
||||
/// threshold to a list for checking during testing.
|
||||
/// </summary>
|
||||
public class TestDestructibleListenerSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<DestructibleComponent, DamageThresholdReached>(AddThresholdsToList);
|
||||
}
|
||||
|
||||
public void AddThresholdsToList(EntityUid _, DestructibleComponent comp, DamageThresholdReached args)
|
||||
{
|
||||
ThresholdsReached.Add(args);
|
||||
}
|
||||
|
||||
public List<DamageThresholdReached> ThresholdsReached = new();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Destructible;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Destructible
|
||||
{
|
||||
public class TestThresholdListenerComponent : Component
|
||||
{
|
||||
public override string Name => "TestThresholdListener";
|
||||
|
||||
public List<DestructibleThresholdReachedMessage> ThresholdsReached { get; } = new();
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent component)
|
||||
{
|
||||
base.HandleMessage(message, component);
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case DestructibleThresholdReachedMessage msg:
|
||||
ThresholdsReached.Add(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Disposal.Tube.Components;
|
||||
using Content.Server.Disposal.Unit.Components;
|
||||
using Content.Server.Disposal.Unit.EntitySystems;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Coordinates;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Disposal
|
||||
{
|
||||
@@ -19,13 +20,13 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
[TestOf(typeof(DisposalUnitComponent))]
|
||||
public class DisposalUnitTest : ContentIntegrationTest
|
||||
{
|
||||
private void UnitInsert(DisposalUnitComponent unit, bool result, params IEntity[] entities)
|
||||
private async Task UnitInsert(DisposalUnitComponent unit, bool result, params IEntity[] entities)
|
||||
{
|
||||
List<Task> insertionTasks = new();
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var insertTask = unit.TryInsert(entity);
|
||||
Assert.That(EntitySystem.Get<DisposalUnitSystem>().CanInsert(unit, entity), Is.EqualTo(result));
|
||||
insertTask.ContinueWith(task =>
|
||||
var insertTask = unit.TryInsert(entity).ContinueWith(task =>
|
||||
{
|
||||
Assert.That(task.Result, Is.EqualTo(result));
|
||||
if (result)
|
||||
@@ -34,7 +35,9 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
Assert.That(entity.Transform.Parent, Is.EqualTo(unit.Owner.Transform));
|
||||
}
|
||||
});
|
||||
insertionTasks.Add(insertTask);
|
||||
}
|
||||
Task.WaitAll(insertionTasks.ToArray());
|
||||
}
|
||||
|
||||
private void UnitContains(DisposalUnitComponent unit, bool result, params IEntity[] entities)
|
||||
@@ -45,9 +48,9 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
}
|
||||
}
|
||||
|
||||
private void UnitInsertContains(DisposalUnitComponent unit, bool result, params IEntity[] entities)
|
||||
private async void UnitInsertContains(DisposalUnitComponent unit, bool result, params IEntity[] entities)
|
||||
{
|
||||
UnitInsert(unit, result, entities);
|
||||
await UnitInsert(unit, result, entities);
|
||||
UnitContains(unit, result, entities);
|
||||
}
|
||||
|
||||
@@ -68,7 +71,9 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
- type: Body
|
||||
- type: MobState
|
||||
- type: Damageable
|
||||
damagePrototype: biologicalDamageContainer
|
||||
damageContainer: Biological
|
||||
- type: Physics
|
||||
bodyType: KinematicController
|
||||
|
||||
- type: entity
|
||||
name: WrenchDummy
|
||||
@@ -78,6 +83,8 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Anchoring
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
|
||||
- type: entity
|
||||
name: DisposalUnitDummy
|
||||
@@ -94,44 +101,78 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
id: DisposalTrunkDummy
|
||||
components:
|
||||
- type: DisposalEntry
|
||||
- type: Transform
|
||||
anchored: true
|
||||
";
|
||||
|
||||
[Test]
|
||||
public async Task Test()
|
||||
{
|
||||
var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes};
|
||||
var options = new ServerIntegrationOptions { ExtraPrototypes = Prototypes };
|
||||
var server = StartServerDummyTicker(options);
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
IEntity human;
|
||||
IEntity wrench;
|
||||
DisposalUnitComponent unit;
|
||||
IEntity human = default!;
|
||||
IEntity wrench = default!;
|
||||
IEntity disposalUnit = default!;
|
||||
IEntity disposalTrunk = default!;
|
||||
DisposalUnitComponent unit = default!;
|
||||
EntityCoordinates coordinates = default!;
|
||||
|
||||
server.Assert(async () =>
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var pauseManager = server.ResolveDependency<IPauseManager>();
|
||||
var componentFactory = server.ResolveDependency<IComponentFactory>();
|
||||
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
|
||||
|
||||
// Build up test environment
|
||||
server.Post(() =>
|
||||
{
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
// Create a one tile grid to anchor our disposal unit to.
|
||||
var mapId = mapManager.CreateMap();
|
||||
|
||||
mapManager.CreateNewMapEntity(MapId.Nullspace);
|
||||
pauseManager.AddUninitializedMap(mapId);
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var gridId = new GridId(1);
|
||||
|
||||
if (!mapManager.TryGetGrid(gridId, out var grid))
|
||||
{
|
||||
grid = mapManager.CreateGrid(mapId, gridId);
|
||||
}
|
||||
|
||||
var tileDefinition = tileDefinitionManager["underplating"];
|
||||
var tile = new Tile(tileDefinition.TileId);
|
||||
coordinates = grid.ToCoordinates();
|
||||
|
||||
grid.SetTile(coordinates, tile);
|
||||
|
||||
pauseManager.DoMapInitialize(mapId);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Spawn the entities
|
||||
human = entityManager.SpawnEntity("HumanDummy", MapCoordinates.Nullspace);
|
||||
wrench = entityManager.SpawnEntity("WrenchDummy", MapCoordinates.Nullspace);
|
||||
var disposalUnit = entityManager.SpawnEntity("DisposalUnitDummy", MapCoordinates.Nullspace);
|
||||
var disposalTrunk = entityManager.SpawnEntity("DisposalTrunkDummy", disposalUnit.Transform.MapPosition);
|
||||
human = entityManager.SpawnEntity("HumanDummy", coordinates);
|
||||
wrench = entityManager.SpawnEntity("WrenchDummy", coordinates);
|
||||
disposalUnit = entityManager.SpawnEntity("DisposalUnitDummy", coordinates);
|
||||
disposalTrunk = entityManager.SpawnEntity("DisposalTrunkDummy", disposalUnit.Transform.MapPosition);
|
||||
|
||||
// Check that we have a grid, so that we can anchor our unit
|
||||
Assert.That(mapManager.TryFindGridAt(disposalUnit.Transform.MapPosition, out var _));
|
||||
|
||||
// Test for components existing
|
||||
Assert.True(disposalUnit.TryGetComponent(out unit!));
|
||||
Assert.True(disposalTrunk.HasComponent<DisposalEntryComponent>());
|
||||
|
||||
// Can't insert, unanchored and unpowered
|
||||
var physics = disposalUnit.GetComponent<IPhysBody>();
|
||||
physics.BodyType = BodyType.Dynamic;
|
||||
Assert.False(unit.Owner.Transform.Anchored);
|
||||
unit.Owner.Transform.Anchored = false;
|
||||
UnitInsertContains(unit, false, human, wrench, disposalUnit, disposalTrunk);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Anchor the disposal unit
|
||||
physics.BodyType = BodyType.Static;
|
||||
unit.Owner.Transform.Anchored = true;
|
||||
|
||||
// No power
|
||||
Assert.False(unit.Powered);
|
||||
@@ -141,19 +182,28 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
|
||||
// Can insert mobs and items
|
||||
UnitInsertContains(unit, true, human, wrench);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Move the disposal trunk away
|
||||
disposalTrunk.Transform.WorldPosition += (1, 0);
|
||||
|
||||
// Fail to flush with a mob and an item
|
||||
Flush(unit, false, human, wrench);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Move the disposal trunk back
|
||||
disposalTrunk.Transform.WorldPosition -= (1, 0);
|
||||
|
||||
// Fail to flush with a mob and an item, no power
|
||||
Flush(unit, false, human, wrench);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Remove power need
|
||||
Assert.True(disposalUnit.TryGetComponent(out ApcPowerReceiverComponent? power));
|
||||
power!.NeedsPower = false;
|
||||
@@ -161,12 +211,13 @@ namespace Content.IntegrationTests.Tests.Disposal
|
||||
|
||||
// Flush with a mob and an item
|
||||
Flush(unit, true, human, wrench);
|
||||
});
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
// Re-pressurizing
|
||||
Flush(unit, false);
|
||||
});
|
||||
|
||||
await server.WaitIdleAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user