| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- using Content.Shared.Damage;
- using Content.Shared.Damage.Prototypes;
- using NUnit.Framework;
- using Robust.Shared.IoC;
- using Robust.Shared.Prototypes;
- using Robust.Shared.Serialization.Manager;
- using System.Collections.Generic;
- using Content.Shared.FixedPoint;
- namespace Content.Tests.Shared
- {
- // Basic tests of various damage prototypes and classes.
- [TestFixture]
- [TestOf(typeof(DamageSpecifier))]
- [TestOf(typeof(DamageModifierSetPrototype))]
- [TestOf(typeof(DamageGroupPrototype))]
- public sealed class DamageTest : ContentUnitTest
- {
- private static Dictionary<string, float> _resistanceCoefficientDict = new()
- {
- // "missing" blunt entry
- { "Piercing", -2 },// Turn Piercing into Healing
- { "Slash", 3 },
- { "Radiation", 1.5f },
- };
- private static Dictionary<string, float> _resistanceReductionDict = new()
- {
- { "Blunt", - 5 },
- // "missing" piercing entry
- { "Slash", 8 },
- { "Radiation", 0.5f }, // Fractional adjustment
- };
- private IPrototypeManager _prototypeManager;
- private DamageSpecifier _damageSpec;
- [OneTimeSetUp]
- public void OneTimeSetup()
- {
- IoCManager.Resolve<ISerializationManager>().Initialize();
- _prototypeManager = IoCManager.Resolve<IPrototypeManager>();
- _prototypeManager.Initialize();
- _prototypeManager.LoadString(_damagePrototypes);
- _prototypeManager.ResolveResults();
- // Create a damage data set
- _damageSpec = new(_prototypeManager.Index<DamageGroupPrototype>("Brute"), 6);
- _damageSpec += new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Radiation"), 3);
- _damageSpec += new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Slash"), -1); // already exists in brute
- }
- //Check that DamageSpecifier will split groups and can do arithmetic operations
- [Test]
- public void DamageSpecifierTest()
- {
- // Create a copy of the damage data
- DamageSpecifier damageSpec = new(_damageSpec);
- // Check that it properly split up the groups into types
- FixedPoint2 damage;
- Assert.That(damageSpec.GetTotal(), Is.EqualTo(FixedPoint2.New(8)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Blunt", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(2)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(2)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Slash", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(1)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Radiation", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(3)));
- // check that integer multiplication works
- damageSpec = damageSpec * 2;
- Assert.That(damageSpec.GetTotal(), Is.EqualTo(FixedPoint2.New(16)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Blunt", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(4)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(4)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Slash", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(2)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Radiation", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(6)));
- // check that float multiplication works
- damageSpec = damageSpec * 2.2f;
- Assert.That(damageSpec.DamageDict.TryGetValue("Blunt", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(8.8)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(8.8)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Slash", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(4.4)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Radiation", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(13.2)));
- Assert.That(damageSpec.GetTotal(), Is.EqualTo(FixedPoint2.New(8.8 + 8.8 + 4.4 + 13.2)));
- // check that integer division works
- damageSpec = damageSpec / 2;
- Assert.That(damageSpec.DamageDict.TryGetValue("Blunt", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(4.4)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(4.4)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Slash", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(2.2)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Radiation", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(6.6)));
- // check that float division works
- damageSpec = damageSpec / 2.2f;
- Assert.That(damageSpec.DamageDict.TryGetValue("Blunt", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(2)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(2)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Slash", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(1)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Radiation", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(3)));
- // Lets also test the constructor with damage types and damage groups works properly.
- damageSpec = new(_prototypeManager.Index<DamageGroupPrototype>("Brute"), 4);
- Assert.That(damageSpec.DamageDict.TryGetValue("Blunt", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(1.33)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Slash", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(1.33)));
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(1.34))); // doesn't divide evenly, so the 0.01 goes to the last one
- damageSpec = new(_prototypeManager.Index<DamageTypePrototype>("Piercing"), 4);
- Assert.That(damageSpec.DamageDict.TryGetValue("Piercing", out damage));
- Assert.That(damage, Is.EqualTo(FixedPoint2.New(4)));
- }
- //Check that DamageSpecifier will be properly adjusted by a resistance set
- [Test]
- public void ModifierSetTest()
- {
- // Create a copy of the damage data
- DamageSpecifier damageSpec = 10 * new DamageSpecifier(_damageSpec);
- // Create a modifier set
- DamageModifierSetPrototype modifierSet = new()
- {
- Coefficients = _resistanceCoefficientDict,
- FlatReduction = _resistanceReductionDict
- };
- //damage is initially 20 / 20 / 10 / 30
- //Each time we subtract -5 / 0 / 8 / 0.5
- //then multiply by 1 / -2 / 3 / 1.5
- // Apply once
- damageSpec = DamageSpecifier.ApplyModifierSet(damageSpec, modifierSet);
- Assert.That(damageSpec.DamageDict["Blunt"], Is.EqualTo(FixedPoint2.New(25)));
- Assert.That(damageSpec.DamageDict["Piercing"], Is.EqualTo(FixedPoint2.New(-40))); // became healing
- Assert.That(damageSpec.DamageDict["Slash"], Is.EqualTo(FixedPoint2.New(6)));
- Assert.That(damageSpec.DamageDict["Radiation"], Is.EqualTo(FixedPoint2.New(44.25)));
- // And again, checking for some other behavior
- damageSpec = DamageSpecifier.ApplyModifierSet(damageSpec, modifierSet);
- Assert.That(damageSpec.DamageDict["Blunt"], Is.EqualTo(FixedPoint2.New(30)));
- Assert.That(damageSpec.DamageDict["Piercing"], Is.EqualTo(FixedPoint2.New(-40))); // resistances don't apply to healing
- Assert.That(!damageSpec.DamageDict.ContainsKey("Slash")); // Reduction reduced to 0, and removed from specifier
- Assert.That(damageSpec.DamageDict["Radiation"], Is.EqualTo(FixedPoint2.New(65.62)));
- }
- // Default damage Yaml
- private string _damagePrototypes = @"
- - type: damageType
- id: Blunt
- name: damage-type-blunt
- - type: damageType
- id: Slash
- name: damage-type-slash
- - type: damageType
- id: Piercing
- name: damage-type-piercing
- - type: damageType
- id: TestArrow
- name: damage-type-arrow
- - type: damageType
- id: Heat
- name: damage-type-heat
- - type: damageType
- id: Shock
- name: damage-type-shock
- - type: damageType
- id: Cold
- name: damage-type-cold
- # Poison damage. Generally caused by various reagents being metabolised.
- - type: damageType
- id: Poison
- name: damage-type-poison
- - type: damageType
- id: Radiation
- name: damage-type-radiation
- # Damage due to being unable to breathe.
- # Represents not enough oxygen (or equivalent) getting to the blood.
- # Usually healed automatically if entity can breathe
- - type: damageType
- id: Asphyxiation
- name: damage-type-asphyxiation
- # Damage representing not having enough blood.
- # Represents there not enough blood to supply oxygen (or equivalent).
- - type: damageType
- id: Bloodloss
- name: damage-type-bloodloss
- - type: damageType
- id: Cellular
- name: damage-type-cellular
- - type: damageGroup
- id: Brute
- name: damage-group-brute
- damageTypes:
- - Blunt
- - Slash
- - Piercing
- - type: damageGroup
- id: Burn
- name: damage-group-burn
- damageTypes:
- - Heat
- - Shock
- - Cold
- # Airloss (sometimes called oxyloss)
- # Caused by asphyxiation or bloodloss.
- # Note that most medicine and damaging effects should probably modify either asphyxiation or
- # bloodloss, not this whole group, unless you have a wonder drug that affects both.
- - type: damageGroup
- id: Airloss
- name: damage-group-airloss
- damageTypes:
- - Asphyxiation
- - Bloodloss
- # As with airloss, most medicine and damage effects should probably modify either poison or radiation.
- # Though there are probably some radioactive poisons.
- - type: damageGroup
- id: Toxin
- name: damage-group-toxin
- damageTypes:
- - Poison
- - Radiation
- - type: damageGroup
- id: Genetic
- name: damage-group-genetic
- damageTypes:
- - Cellular
- - type: damageModifierSet
- id: Metallic
- coefficients:
- Blunt: 0.7
- Slash: 0.5
- Piercing: 0.7
- Shock: 1.2
- flatReductions:
- Blunt: 5
- - type: damageModifierSet
- id: Inflatable
- coefficients:
- Blunt: 0.5
- Piercing: 2.0
- Heat: 0.5
- Shock: 0
- flatReductions:
- Blunt: 5
- - type: damageModifierSet
- id: Glass
- coefficients:
- Blunt: 0.5
- Slash: 0.5
- Piercing: 0.5
- Heat: 0
- Shock: 0
- flatReductions:
- Blunt: 5
- - type: damageContainer
- id: Biological
- supportedGroups:
- - Brute
- - Burn
- - Toxin
- - Airloss
- - Genetic
- - type: damageContainer
- id: Inorganic
- supportedGroups:
- - Brute
- supportedTypes:
- - Heat
- - Shock
- ";
- }
- }
|