diff --git a/Content.IntegrationTests/Tests/Nyanotrasen/Metempsychosis/MetempsychosisTest.cs b/Content.IntegrationTests/Tests/Nyanotrasen/Metempsychosis/MetempsychosisTest.cs new file mode 100644 index 00000000000..d2091a4404b --- /dev/null +++ b/Content.IntegrationTests/Tests/Nyanotrasen/Metempsychosis/MetempsychosisTest.cs @@ -0,0 +1,68 @@ +using System.Linq; +using Content.Server.Nyanotrasen.Cloning; +using Content.Shared.Random; +using Robust.Shared.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests.DeltaV; + +[TestFixture] +[TestOf(typeof(MetempsychoticMachineSystem))] +public sealed class MetempsychosisTest +{ + private readonly IPrototypeManager _prototypeManager = default!; + + [Test] + public async Task AllHumanoidPoolSpeciesExist() + { + await using var pair = await PoolManager.GetServerClient(); + var server = pair.Server; + // Per RobustIntegrationTest.cs, wait until state is settled to access it. + await server.WaitIdleAsync(); + + var mapManager = server.ResolveDependency(); + var prototypeManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); + var entitySystemManager = server.ResolveDependency(); + + var metemSystem = entitySystemManager.GetEntitySystem(); + var metemComponent = new MetempsychoticMachineComponent(); + + var testMap = await pair.CreateTestMap(); + + await server.WaitAssertion(() => + { + _prototypeManager.TryIndex(metemComponent.MetempsychoticHumanoidPool, out var humanoidPool); + _prototypeManager.TryIndex(metemComponent.MetempsychoticNonHumanoidPool, out var nonHumanoidPool); + + var coordinates = testMap.GridCoords; + + Assert.That(humanoidPool.Weights.Any(), "MetempsychoticHumanoidPool has no valid prototypes!"); + Assert.That(nonHumanoidPool.Weights.Any(), "MetempsychoticNonHumanoidPool has no valid prototypes!"); + + foreach (var (key, weight) in humanoidPool.Weights) + { + Assert.That(prototypeManager.TryIndex(key, out var _), + $"MetempsychoticHumanoidPool has invalid prototype {key}!"); + + var spawned = entityManager.SpawnEntity(key, coordinates); + } + + foreach (var (key, weight) in nonHumanoidPool.Weights) + { + Assert.That(prototypeManager.TryIndex(key, out var _), + $"MetempsychoticNonHumanoidPool has invalid prototype {key}!"); + + var spawned = entityManager.SpawnEntity(key, coordinates); + } + + // Because Server/Client pairs can be re-used between Tests, we + // need to clean up anything that might affect other tests, + // otherwise this pair cannot be considered clean, and the + // CleanReturnAsync call would need to be removed. + mapManager.DeleteMap(testMap.MapId); + }); + await pair.CleanReturnAsync(); + } +} diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index d6b99184193..f9025fa3354 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -45,6 +45,7 @@ using Content.Server.Nyanotrasen.Cloning; using Content.Shared.Humanoid.Prototypes; using Robust.Shared.GameObjects.Components.Localization; //DeltaV End Metem Usings +using Content.Server.EntityList; namespace Content.Server.Cloning { @@ -265,7 +266,7 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity(uid); - // TODO: Ideally, components like this should be on a mind entity so this isn't neccesary. + // TODO: Ideally, components like this should be components on the mind entity so this isn't necessary. // Add on special job components to the mob. if (_jobs.MindTryGetJob(mindEnt, out _, out var prototype)) { @@ -384,7 +385,7 @@ private EntityUid FetchAndSpawnMob(CloningPodComponent clonePod, HumanoidCharact if (TryComp(clonePod.Owner, out var metem)) { - toSpawn = _metem.GetSpawnEntity(clonePod.Owner, karmaBonus, speciesPrototype, out var newSpecies, oldKarma?.Score, metem); + toSpawn = _metem.GetSpawnEntity(clonePod.Owner, karmaBonus, metem, speciesPrototype, out var newSpecies, oldKarma?.Score); applyKarma = true; if (newSpecies != null) diff --git a/Content.Server/Medical/Components/MedicalScannerComponent.cs b/Content.Server/Medical/Components/MedicalScannerComponent.cs index c03a6ae7234..96de6499875 100644 --- a/Content.Server/Medical/Components/MedicalScannerComponent.cs +++ b/Content.Server/Medical/Components/MedicalScannerComponent.cs @@ -17,12 +17,6 @@ public sealed partial class MedicalScannerComponent : SharedMedicalScannerCompon public float CloningFailChanceMultiplier = 1f; // Nyano, needed for Metem Machine. - public float MetemKarmaBonus = 0.25f; - - [DataField("machinePartCloningFailChance", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string MachinePartCloningFailChance = "Capacitor"; - - [DataField("partRatingCloningFailChanceMultiplier")] - public float PartRatingFailMultiplier = 0.75f; + public float MetemKarmaBonus = 0.25f; } } diff --git a/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineComponent.cs b/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineComponent.cs index ccd0ae46d23..0adcc9b5b25 100644 --- a/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineComponent.cs +++ b/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineComponent.cs @@ -1,3 +1,5 @@ +using Content.Shared.Random; + namespace Content.Server.Nyanotrasen.Cloning { [RegisterComponent] @@ -8,5 +10,13 @@ public sealed partial class MetempsychoticMachineComponent : Component /// [DataField("humanoidBaseChance")] public float HumanoidBaseChance = 0.75f; + + [ValidatePrototypeId] + [DataField("metempsychoticHumanoidPool")] + public string MetempsychoticHumanoidPool = "MetempsychoticHumanoidPool"; + + [ValidatePrototypeId] + [DataField("metempsychoticNonHumanoidPool")] + public string MetempsychoticNonHumanoidPool = "MetempsychoticNonhumanoidPool"; } } diff --git a/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs b/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs index efbfa189d10..62dc1b078e0 100644 --- a/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs +++ b/Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs @@ -8,26 +8,13 @@ namespace Content.Server.Nyanotrasen.Cloning { public sealed class MetempsychoticMachineSystem : EntitySystem { - [ValidatePrototypeId] - public const string MetempsychoticHumanoidPool = "MetempsychoticHumanoidPool"; - - [ValidatePrototypeId] - public const string MetempsychoticNonHumanoidPool = "MetempsychoticNonhumanoidPool"; - [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private ISawmill _sawmill = default!; - public string GetSpawnEntity(EntityUid uid, float karmaBonus, SpeciesPrototype oldSpecies, out SpeciesPrototype? species, int? karma = null, MetempsychoticMachineComponent? component = null) + public string GetSpawnEntity(EntityUid uid, float karmaBonus, MetempsychoticMachineComponent component, SpeciesPrototype oldSpecies, out SpeciesPrototype? species, int? karma = null) { - if (!Resolve(uid, ref component)) - { - Logger.Error("Tried to get a spawn target from someone that was not a metempsychotic machine..."); - species = null; - return "MobHuman"; - } - var chance = component.HumanoidBaseChance + karmaBonus; if (karma != null) @@ -42,9 +29,8 @@ public string GetSpawnEntity(EntityUid uid, float karmaBonus, SpeciesPrototype o chance = 1; chance = Math.Clamp(chance, 0, 1); - if (_random.Prob(chance) && - _prototypeManager.TryIndex(MetempsychoticHumanoidPool, out var humanoidPool) && + _prototypeManager.TryIndex(component.MetempsychoticHumanoidPool, out var humanoidPool) && _prototypeManager.TryIndex(humanoidPool.Pick(), out var speciesPrototype)) { species = speciesPrototype; diff --git a/Resources/Prototypes/Nyanotrasen/metempsychoticHumanoids.yml b/Resources/Prototypes/Nyanotrasen/metempsychoticHumanoids.yml index 20c52548b77..891067b1c1f 100644 --- a/Resources/Prototypes/Nyanotrasen/metempsychoticHumanoids.yml +++ b/Resources/Prototypes/Nyanotrasen/metempsychoticHumanoids.yml @@ -7,9 +7,7 @@ Arachnid: 1 Harpy: 1 Moth: 1 + Diona: 0.5 Reptilian: 0.5 - Dwarf: 0.5 SlimePerson: 0.5 Vulpkanin: 0.5 - Vox: 0.1 - Skeleton: 0.05