DamageableTest.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. using System.Linq;
  2. using Content.Shared.Damage;
  3. using Content.Shared.Damage.Prototypes;
  4. using Content.Shared.FixedPoint;
  5. using Robust.Shared.GameObjects;
  6. using Robust.Shared.IoC;
  7. using Robust.Shared.Map;
  8. using Robust.Shared.Prototypes;
  9. namespace Content.IntegrationTests.Tests.Damageable
  10. {
  11. [TestFixture]
  12. [TestOf(typeof(DamageableComponent))]
  13. [TestOf(typeof(DamageableSystem))]
  14. public sealed class DamageableTest
  15. {
  16. [TestPrototypes]
  17. private const string Prototypes = @"
  18. # Define some damage groups
  19. - type: damageType
  20. id: TestDamage1
  21. name: damage-type-blunt
  22. - type: damageType
  23. id: TestDamage2a
  24. name: damage-type-blunt
  25. - type: damageType
  26. id: TestDamage2b
  27. name: damage-type-blunt
  28. - type: damageType
  29. id: TestDamage3a
  30. name: damage-type-blunt
  31. - type: damageType
  32. id: TestDamage3b
  33. name: damage-type-blunt
  34. - type: damageType
  35. id: TestDamage3c
  36. name: damage-type-blunt
  37. # Define damage Groups with 1,2,3 damage types
  38. - type: damageGroup
  39. id: TestGroup1
  40. name: damage-group-brute
  41. damageTypes:
  42. - TestDamage1
  43. - type: damageGroup
  44. id: TestGroup2
  45. name: damage-group-brute
  46. damageTypes:
  47. - TestDamage2a
  48. - TestDamage2b
  49. - type: damageGroup
  50. id: TestGroup3
  51. name: damage-group-brute
  52. damageTypes:
  53. - TestDamage3a
  54. - TestDamage3b
  55. - TestDamage3c
  56. # This container should not support TestDamage1 or TestDamage2b
  57. - type: damageContainer
  58. id: testDamageContainer
  59. supportedGroups:
  60. - TestGroup3
  61. supportedTypes:
  62. - TestDamage2a
  63. - type: entity
  64. id: TestDamageableEntityId
  65. name: TestDamageableEntityId
  66. components:
  67. - type: Damageable
  68. damageContainer: testDamageContainer
  69. ";
  70. [Test]
  71. public async Task TestDamageableComponents()
  72. {
  73. await using var pair = await PoolManager.GetServerClient();
  74. var server = pair.Server;
  75. var sEntityManager = server.ResolveDependency<IEntityManager>();
  76. var sMapManager = server.ResolveDependency<IMapManager>();
  77. var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
  78. var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
  79. EntityUid sDamageableEntity = default;
  80. DamageableComponent sDamageableComponent = null;
  81. DamageableSystem sDamageableSystem = null;
  82. DamageGroupPrototype group1 = default!;
  83. DamageGroupPrototype group2 = default!;
  84. DamageGroupPrototype group3 = default!;
  85. DamageTypePrototype type1 = default!;
  86. DamageTypePrototype type2a = default!;
  87. DamageTypePrototype type2b = default!;
  88. DamageTypePrototype type3a = default!;
  89. DamageTypePrototype type3b = default!;
  90. DamageTypePrototype type3c = default!;
  91. FixedPoint2 typeDamage;
  92. var map = await pair.CreateTestMap();
  93. await server.WaitPost(() =>
  94. {
  95. var coordinates = map.MapCoords;
  96. sDamageableEntity = sEntityManager.SpawnEntity("TestDamageableEntityId", coordinates);
  97. sDamageableComponent = sEntityManager.GetComponent<DamageableComponent>(sDamageableEntity);
  98. sDamageableSystem = sEntitySystemManager.GetEntitySystem<DamageableSystem>();
  99. group1 = sPrototypeManager.Index<DamageGroupPrototype>("TestGroup1");
  100. group2 = sPrototypeManager.Index<DamageGroupPrototype>("TestGroup2");
  101. group3 = sPrototypeManager.Index<DamageGroupPrototype>("TestGroup3");
  102. type1 = sPrototypeManager.Index<DamageTypePrototype>("TestDamage1");
  103. type2a = sPrototypeManager.Index<DamageTypePrototype>("TestDamage2a");
  104. type2b = sPrototypeManager.Index<DamageTypePrototype>("TestDamage2b");
  105. type3a = sPrototypeManager.Index<DamageTypePrototype>("TestDamage3a");
  106. type3b = sPrototypeManager.Index<DamageTypePrototype>("TestDamage3b");
  107. type3c = sPrototypeManager.Index<DamageTypePrototype>("TestDamage3c");
  108. });
  109. await server.WaitRunTicks(5);
  110. await server.WaitAssertion(() =>
  111. {
  112. var uid = sDamageableEntity;
  113. // Check that the correct types are supported.
  114. Assert.Multiple(() =>
  115. {
  116. Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type1.ID), Is.False);
  117. Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type2a.ID), Is.True);
  118. Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type2b.ID), Is.False);
  119. Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3a.ID), Is.True);
  120. Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3b.ID), Is.True);
  121. Assert.That(sDamageableComponent.Damage.DamageDict.ContainsKey(type3c.ID), Is.True);
  122. });
  123. // Check that damage is evenly distributed over a group if its a nice multiple
  124. var types = group3.DamageTypes;
  125. var damageToDeal = FixedPoint2.New(types.Count * 5);
  126. DamageSpecifier damage = new(group3, damageToDeal);
  127. sDamageableSystem.TryChangeDamage(uid, damage, true);
  128. Assert.Multiple(() =>
  129. {
  130. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal));
  131. Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(damageToDeal));
  132. foreach (var type in types)
  133. {
  134. Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
  135. Assert.That(typeDamage, Is.EqualTo(damageToDeal / types.Count));
  136. }
  137. });
  138. // Heal
  139. sDamageableSystem.TryChangeDamage(uid, -damage);
  140. Assert.Multiple(() =>
  141. {
  142. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  143. Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.Zero));
  144. foreach (var type in types)
  145. {
  146. Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
  147. Assert.That(typeDamage, Is.EqualTo(FixedPoint2.Zero));
  148. }
  149. });
  150. // Check that damage works properly if it is NOT perfectly divisible among group members
  151. types = group3.DamageTypes;
  152. Assert.That(types, Has.Count.EqualTo(3));
  153. damage = new DamageSpecifier(group3, 14);
  154. sDamageableSystem.TryChangeDamage(uid, damage, true);
  155. Assert.Multiple(() =>
  156. {
  157. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(14)));
  158. Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.New(14)));
  159. Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(FixedPoint2.New(4.66f)));
  160. Assert.That(sDamageableComponent.Damage.DamageDict[type3b.ID], Is.EqualTo(FixedPoint2.New(4.67f)));
  161. Assert.That(sDamageableComponent.Damage.DamageDict[type3c.ID], Is.EqualTo(FixedPoint2.New(4.67f)));
  162. });
  163. // Heal
  164. sDamageableSystem.TryChangeDamage(uid, -damage);
  165. Assert.Multiple(() =>
  166. {
  167. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  168. Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.Zero));
  169. foreach (var type in types)
  170. {
  171. Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type, out typeDamage));
  172. Assert.That(typeDamage, Is.EqualTo(FixedPoint2.Zero));
  173. }
  174. // Test that unsupported groups return false when setting/getting damage (and don't change damage)
  175. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  176. });
  177. damage = new DamageSpecifier(group1, FixedPoint2.New(10)) + new DamageSpecifier(type2b, FixedPoint2.New(10));
  178. sDamageableSystem.TryChangeDamage(uid, damage, true);
  179. Assert.Multiple(() =>
  180. {
  181. Assert.That(sDamageableComponent.DamagePerGroup.TryGetValue(group1.ID, out _), Is.False);
  182. Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type1.ID, out typeDamage), Is.False);
  183. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  184. });
  185. // Test SetAll function
  186. sDamageableSystem.SetAllDamage(sDamageableEntity, sDamageableComponent, 10);
  187. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.New(10 * sDamageableComponent.Damage.DamageDict.Count)));
  188. sDamageableSystem.SetAllDamage(sDamageableEntity, sDamageableComponent, 0);
  189. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  190. // Test 'wasted' healing
  191. sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(type3a, 5));
  192. sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(type3b, 7));
  193. sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -11));
  194. Assert.Multiple(() =>
  195. {
  196. Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(FixedPoint2.New(1.34)));
  197. Assert.That(sDamageableComponent.Damage.DamageDict[type3b.ID], Is.EqualTo(FixedPoint2.New(3.33)));
  198. Assert.That(sDamageableComponent.Damage.DamageDict[type3c.ID], Is.EqualTo(FixedPoint2.New(0)));
  199. });
  200. // Test Over-Healing
  201. sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, FixedPoint2.New(-100)));
  202. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  203. // Test that if no health change occurred, returns false
  204. sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -100));
  205. Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
  206. });
  207. await pair.CleanReturnAsync();
  208. }
  209. }
  210. }