]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Nubody (#42419)
authorpathetic meowmeow <uhhadd@gmail.com>
Sat, 17 Jan 2026 00:39:35 +0000 (19:39 -0500)
committerGitHub <noreply@github.com>
Sat, 17 Jan 2026 00:39:35 +0000 (00:39 +0000)
* Nubody

* fix test fails

* gibbing

* lung test returns

* doc comment

* hand organ test

* giblet test

* yaml formatting

* returning

* relocate

* trimming

* re-smite

* oops thusd tweak

* arachnids have slower metabolism i guess

* never mind the old behaviour is bad actually

* rider whyyy

* style changes and allat

* fix collision

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
198 files changed:
Content.Client/Body/Systems/BodySystem.cs [deleted file]
Content.Client/Chemistry/EntitySystems/ChemistryGuideDataSystem.cs
Content.Client/Commands/HideMechanismsCommand.cs [deleted file]
Content.Client/Commands/ShowMechanismsCommand.cs [deleted file]
Content.IntegrationTests/Tests/Body/GibbingTest.cs [new file with mode: 0644]
Content.IntegrationTests/Tests/Body/HandOrganTest.cs [new file with mode: 0644]
Content.IntegrationTests/Tests/Body/LegTest.cs [deleted file]
Content.IntegrationTests/Tests/Body/LungTest.cs [deleted file]
Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs [deleted file]
Content.IntegrationTests/Tests/Buckle/BuckleTest.cs
Content.IntegrationTests/Tests/Respirator/LungTest.cs [new file with mode: 0644]
Content.Server/Administration/Commands/AddBodyPartCommand.cs [deleted file]
Content.Server/Administration/Commands/AddMechanismCommand.cs [deleted file]
Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs
Content.Server/Anomaly/Effects/InnerBodyAnomalySystem.cs
Content.Server/Body/Commands/AddHandCommand.cs
Content.Server/Body/Commands/AttachBodyPartCommand.cs [deleted file]
Content.Server/Body/Commands/DestroyMechanismCommand.cs [deleted file]
Content.Server/Body/Commands/RemoveHandCommand.cs [deleted file]
Content.Server/Body/Systems/BodySystem.cs [deleted file]
Content.Server/Body/Systems/MetabolizerSystem.cs
Content.Server/Body/Systems/RespiratorSystem.cs
Content.Server/Cargo/Components/MobPriceComponent.cs
Content.Server/Cargo/Systems/PricingSystem.cs
Content.Server/Disposal/Unit/DisposableSystem.cs
Content.Server/Hands/Systems/HandsSystem.cs
Content.Server/ImmovableRod/ImmovableRodSystem.cs
Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs
Content.Server/Medical/MedicalScannerSystem.cs
Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
Content.Server/Species/Systems/NymphSystem.cs
Content.Server/Tools/Innate/InnateToolSystem.cs
Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactCrusherSystem.cs
Content.Shared/Body/BodyComponent.cs [new file with mode: 0644]
Content.Shared/Body/BodySystem.Compatibility.cs [new file with mode: 0644]
Content.Shared/Body/BodySystem.Relay.cs [new file with mode: 0644]
Content.Shared/Body/BodySystem.cs [new file with mode: 0644]
Content.Shared/Body/Components/BodyComponent.cs [deleted file]
Content.Shared/Body/Events/MechanismBodyEvents.cs [deleted file]
Content.Shared/Body/GibbableOrganComponent.cs [new file with mode: 0644]
Content.Shared/Body/GibbableOrganSystem.cs [new file with mode: 0644]
Content.Shared/Body/HandOrganComponent.cs [new file with mode: 0644]
Content.Shared/Body/HandOrganSystem.cs [new file with mode: 0644]
Content.Shared/Body/Organ/OrganComponent.cs [deleted file]
Content.Shared/Body/OrganCategoryPrototype.cs [new file with mode: 0644]
Content.Shared/Body/OrganComponent.cs [new file with mode: 0644]
Content.Shared/Body/Part/BodyPartComponent.cs [deleted file]
Content.Shared/Body/Part/BodyPartEvents.cs [deleted file]
Content.Shared/Body/Part/BodyPartSymmetry.cs [deleted file]
Content.Shared/Body/Part/BodyPartType.cs [deleted file]
Content.Shared/Body/Prototypes/BodyPrototype.cs [deleted file]
Content.Shared/Body/Prototypes/BodyPrototypeSerializer.cs [deleted file]
Content.Shared/Body/Systems/BrainSystem.cs
Content.Shared/Body/Systems/SharedBodySystem.Body.cs [deleted file]
Content.Shared/Body/Systems/SharedBodySystem.Organs.cs [deleted file]
Content.Shared/Body/Systems/SharedBodySystem.Parts.cs [deleted file]
Content.Shared/Body/Systems/SharedBodySystem.cs [deleted file]
Content.Shared/Body/Systems/StomachSystem.cs
Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs
Content.Shared/Clothing/LoadoutSystem.cs
Content.Shared/Humanoid/HumanoidVisualLayersExtension.cs
Content.Shared/Materials/SharedMaterialReclaimerSystem.cs
Content.Shared/Medical/Cryogenics/SharedCryoPodSystem.cs
Content.Shared/Medical/VomitSystem.cs
Content.Shared/Nutrition/EntitySystems/IngestionSystem.cs
Content.Shared/Traits/Assorted/LegsParalyzedSystem.cs
Resources/Locale/en-US/kitchen/components/microwave-component.ftl
Resources/Maps/Salvage/ruin-cargo-salvage.yml
Resources/Prototypes/Body/Animals/animal.yml [new file with mode: 0644]
Resources/Prototypes/Body/Animals/bloodsucker.yml [new file with mode: 0644]
Resources/Prototypes/Body/Animals/hemocyanin.yml [new file with mode: 0644]
Resources/Prototypes/Body/Animals/mothroach.yml [new file with mode: 0644]
Resources/Prototypes/Body/Animals/rat.yml [new file with mode: 0644]
Resources/Prototypes/Body/Animals/ruminant.yml [new file with mode: 0644]
Resources/Prototypes/Body/Animals/slimes.yml [new file with mode: 0644]
Resources/Prototypes/Body/Organs/Animal/animal.yml [deleted file]
Resources/Prototypes/Body/Organs/Animal/bloodsucker.yml [deleted file]
Resources/Prototypes/Body/Organs/Animal/ruminant.yml [deleted file]
Resources/Prototypes/Body/Organs/Animal/slimes.yml [deleted file]
Resources/Prototypes/Body/Organs/arachnid.yml [deleted file]
Resources/Prototypes/Body/Organs/diona.yml [deleted file]
Resources/Prototypes/Body/Organs/dwarf.yml [deleted file]
Resources/Prototypes/Body/Organs/human.yml [deleted file]
Resources/Prototypes/Body/Organs/moth.yml [deleted file]
Resources/Prototypes/Body/Organs/rat.yml [deleted file]
Resources/Prototypes/Body/Organs/reptilian.yml [deleted file]
Resources/Prototypes/Body/Organs/slime.yml [deleted file]
Resources/Prototypes/Body/Organs/vox.yml [deleted file]
Resources/Prototypes/Body/Organs/vulpkanin.yml [deleted file]
Resources/Prototypes/Body/Parts/animal.yml [deleted file]
Resources/Prototypes/Body/Parts/arachnid.yml [deleted file]
Resources/Prototypes/Body/Parts/base.yml [deleted file]
Resources/Prototypes/Body/Parts/diona.yml [deleted file]
Resources/Prototypes/Body/Parts/gingerbread.yml [deleted file]
Resources/Prototypes/Body/Parts/human.yml [deleted file]
Resources/Prototypes/Body/Parts/moth.yml [deleted file]
Resources/Prototypes/Body/Parts/rat.yml [deleted file]
Resources/Prototypes/Body/Parts/reptilian.yml [deleted file]
Resources/Prototypes/Body/Parts/silicon.yml [deleted file]
Resources/Prototypes/Body/Parts/skeleton.yml [deleted file]
Resources/Prototypes/Body/Parts/slime.yml [deleted file]
Resources/Prototypes/Body/Parts/vox.yml [deleted file]
Resources/Prototypes/Body/Parts/vulpkanin.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Animal/animal.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Animal/bloodsucker.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Animal/hemocyanin.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Animal/nymph.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Animal/ruminant.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Animal/slimes.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Specific/mothroach.yml [deleted file]
Resources/Prototypes/Body/Prototypes/Specific/smartcorgi.yml [deleted file]
Resources/Prototypes/Body/Prototypes/arachnid.yml [deleted file]
Resources/Prototypes/Body/Prototypes/bot.yml [deleted file]
Resources/Prototypes/Body/Prototypes/diona.yml [deleted file]
Resources/Prototypes/Body/Prototypes/dwarf.yml [deleted file]
Resources/Prototypes/Body/Prototypes/gingerbread.yml [deleted file]
Resources/Prototypes/Body/Prototypes/human.yml [deleted file]
Resources/Prototypes/Body/Prototypes/moth.yml [deleted file]
Resources/Prototypes/Body/Prototypes/primate.yml [deleted file]
Resources/Prototypes/Body/Prototypes/rat.yml [deleted file]
Resources/Prototypes/Body/Prototypes/reptilian.yml [deleted file]
Resources/Prototypes/Body/Prototypes/skeleton.yml [deleted file]
Resources/Prototypes/Body/Prototypes/slime.yml [deleted file]
Resources/Prototypes/Body/Prototypes/vox.yml [deleted file]
Resources/Prototypes/Body/Prototypes/vulpkanin.yml [deleted file]
Resources/Prototypes/Body/Species/arachnid.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/diona.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/dwarf.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/gingerbread.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/human.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/moth.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/reptilian.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/skeleton.yml [moved from Resources/Prototypes/Entities/Mobs/Species/skeleton.yml with 59% similarity]
Resources/Prototypes/Body/Species/slime.yml [new file with mode: 0644]
Resources/Prototypes/Body/Species/vox.yml [moved from Resources/Prototypes/Entities/Mobs/Species/vox.yml with 52% similarity]
Resources/Prototypes/Body/Species/vulpkanin.yml [new file with mode: 0644]
Resources/Prototypes/Body/base_organs.yml [new file with mode: 0644]
Resources/Prototypes/Body/organ_categories.yml [new file with mode: 0644]
Resources/Prototypes/Body/species_appearance.yml [new file with mode: 0644]
Resources/Prototypes/Body/species_base.yml [moved from Resources/Prototypes/Entities/Mobs/Species/base.yml with 53% similarity]
Resources/Prototypes/Catalog/Fills/Lockers/heads.yml
Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml
Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml
Resources/Prototypes/Entities/Mobs/NPCs/carp.yml
Resources/Prototypes/Entities/Mobs/NPCs/dummy_npcs.yml [deleted file]
Resources/Prototypes/Entities/Mobs/NPCs/hellspawn.yml
Resources/Prototypes/Entities/Mobs/NPCs/human.yml
Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml
Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml
Resources/Prototypes/Entities/Mobs/NPCs/space.yml
Resources/Prototypes/Entities/Mobs/Player/arachnid.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/diona.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/dwarf.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/gingerbread.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/guardian.yml
Resources/Prototypes/Entities/Mobs/Player/human.yml
Resources/Prototypes/Entities/Mobs/Player/moth.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/reptilian.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/skeleton.yml
Resources/Prototypes/Entities/Mobs/Player/slime.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/vox.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Player/vulpkanin.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/arachnid.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/diona.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/dwarf.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/human.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/moth.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/reptilian.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/slime.yml [deleted file]
Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml [deleted file]
Resources/Prototypes/Entities/Objects/Misc/botparts.yml
Resources/Prototypes/Entities/Structures/Furniture/dresser.yml
Resources/Prototypes/Reagents/gases.yml
Resources/Prototypes/Recipes/Construction/Graphs/furniture/ritualseat.yml
Resources/Prototypes/Species/arachnid.yml
Resources/Prototypes/Species/diona.yml
Resources/Prototypes/Species/dwarf.yml
Resources/Prototypes/Species/gingerbread.yml
Resources/Prototypes/Species/human.yml
Resources/Prototypes/Species/moth.yml
Resources/Prototypes/Species/reptilian.yml
Resources/Prototypes/Species/skeleton.yml
Resources/Prototypes/Species/slime.yml
Resources/Prototypes/Species/vox.yml
Resources/Prototypes/Species/vulpkanin.yml
Resources/ServerInfo/Guidebook/Mobs/Human.xml
Resources/ServerInfo/Guidebook/Mobs/Moth.xml
Resources/ServerInfo/Guidebook/Mobs/Reptilian.xml
Resources/ServerInfo/Guidebook/Mobs/Species.xml
Resources/Textures/Mobs/Species/Slime/organs.rsi/brain.png [moved from Resources/Textures/Mobs/Species/Slime/organs.rsi/brain-slime.png with 100% similarity]
Resources/Textures/Mobs/Species/Slime/organs.rsi/lung-l.png [moved from Resources/Textures/Mobs/Species/Slime/organs.rsi/lung-l-slime.png with 100% similarity]
Resources/Textures/Mobs/Species/Slime/organs.rsi/lung-r.png [moved from Resources/Textures/Mobs/Species/Slime/organs.rsi/lung-r-slime.png with 100% similarity]
Resources/Textures/Mobs/Species/Slime/organs.rsi/meta.json
Resources/migration.yml

diff --git a/Content.Client/Body/Systems/BodySystem.cs b/Content.Client/Body/Systems/BodySystem.cs
deleted file mode 100644 (file)
index bab7855..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-using Content.Shared.Body.Systems;
-
-namespace Content.Client.Body.Systems;
-
-public sealed class BodySystem : SharedBodySystem
-{
-}
index 3392545be8a6477d4dfbe541c7944cd3ae59fa98..4b449b96cbb2b643044808c0872eede3b7d0ba2b 100644 (file)
@@ -1,7 +1,7 @@
 using System.Linq;
 using Content.Shared.Chemistry.EntitySystems;
 using Content.Shared.Atmos.Prototypes;
-using Content.Shared.Body.Part;
+using Content.Shared.Body;
 using Content.Shared.Chemistry;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Components.SolutionManager;
@@ -94,7 +94,7 @@ public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
                 continue;
 
             //these bloat the hell out of blood/fat
-            if (entProto.HasComponent<BodyPartComponent>())
+            if (entProto.HasComponent<OrganComponent>())
                 continue;
 
             //these feel obvious...
diff --git a/Content.Client/Commands/HideMechanismsCommand.cs b/Content.Client/Commands/HideMechanismsCommand.cs
deleted file mode 100644 (file)
index 00e024a..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-using Content.Shared.Body.Organ;
-using Robust.Client.GameObjects;
-using Robust.Shared.Console;
-using Robust.Shared.Containers;
-
-namespace Content.Client.Commands;
-
-public sealed class HideMechanismsCommand : LocalizedEntityCommands
-{
-    [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
-    [Dependency] private readonly SpriteSystem _spriteSystem = default!;
-
-    public override string Command => "hidemechanisms";
-
-    public override void Execute(IConsoleShell shell, string argStr, string[] args)
-    {
-        var query = EntityManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
-
-        while (query.MoveNext(out var uid, out _, out var sprite))
-        {
-            _spriteSystem.SetContainerOccluded((uid, sprite), false);
-
-            var tempParent = uid;
-            while (_containerSystem.TryGetContainingContainer((tempParent, null, null), out var container))
-            {
-                if (!container.ShowContents)
-                {
-                    _spriteSystem.SetContainerOccluded((uid, sprite), true);
-                    break;
-                }
-
-                tempParent = container.Owner;
-            }
-        }
-    }
-}
diff --git a/Content.Client/Commands/ShowMechanismsCommand.cs b/Content.Client/Commands/ShowMechanismsCommand.cs
deleted file mode 100644 (file)
index 091fe05..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-using Content.Shared.Body.Organ;
-using Robust.Client.GameObjects;
-using Robust.Shared.Console;
-
-namespace Content.Client.Commands;
-
-public sealed class ShowMechanismsCommand : LocalizedEntityCommands
-{
-    [Dependency] private readonly SpriteSystem _spriteSystem = default!;
-
-    public override string Command => "showmechanisms";
-
-    public override void Execute(IConsoleShell shell, string argStr, string[] args)
-    {
-        var query = EntityManager.AllEntityQueryEnumerator<OrganComponent, SpriteComponent>();
-
-        while (query.MoveNext(out var uid, out _, out var sprite))
-        {
-            _spriteSystem.SetContainerOccluded((uid, sprite), false);
-        }
-    }
-}
diff --git a/Content.IntegrationTests/Tests/Body/GibbingTest.cs b/Content.IntegrationTests/Tests/Body/GibbingTest.cs
new file mode 100644 (file)
index 0000000..a727487
--- /dev/null
@@ -0,0 +1,60 @@
+using Content.Shared.Body;
+using Content.Shared.Gibbing;
+using Robust.Shared.GameObjects;
+
+namespace Content.IntegrationTests.Tests.Body;
+
+[TestFixture]
+[TestOf(typeof(GibbableOrganSystem))]
+public sealed class GibletTest
+{
+    [TestPrototypes]
+    private const string Prototypes = @"
+- type: entity
+  id: GibbingBody
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: Giblet
+        - id: Giblet
+        - id: Giblet
+
+- type: entity
+  id: Giblet
+  components:
+  - type: Organ
+  - type: GibbableOrgan
+  - type: Physics
+";
+
+    [Test]
+    public async Task GibletCountTest()
+    {
+        await using var pair = await PoolManager.GetServerClient();
+        var server = pair.Server;
+
+        await server.WaitIdleAsync();
+
+        var entityManager = server.ResolveDependency<IEntityManager>();
+        var mapData = await pair.CreateTestMap();
+
+        await server.WaitAssertion(() =>
+        {
+            var body = entityManager.SpawnEntity("GibbingBody", mapData.GridCoords);
+            var gibbing = entityManager.System<GibbingSystem>();
+            var giblets = gibbing.Gib(body);
+
+            Assert.That(giblets.Count, Is.EqualTo(3));
+
+            foreach (var giblet in giblets)
+            {
+                Assert.That(entityManager.HasComponent<GibbableOrganComponent>(giblet), Is.True);
+            }
+        });
+
+        await pair.CleanReturnAsync();
+    }
+}
diff --git a/Content.IntegrationTests/Tests/Body/HandOrganTest.cs b/Content.IntegrationTests/Tests/Body/HandOrganTest.cs
new file mode 100644 (file)
index 0000000..560dfbf
--- /dev/null
@@ -0,0 +1,87 @@
+using System.Collections.Generic;
+using System.Linq;
+using Content.Shared.Body;
+using Content.Shared.Hands.Components;
+using Robust.Shared.Containers;
+using Robust.Shared.GameObjects;
+
+namespace Content.IntegrationTests.Tests.Body;
+
+[TestFixture]
+[TestOf(typeof(HandOrganSystem))]
+public sealed class HandOrganTest
+{
+    [TestPrototypes]
+    private const string Prototypes = @"
+- type: entity
+  id: TheBody
+  components:
+  - type: Body
+  - type: Hands
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: LeftHand
+        - id: RightHand
+
+- type: entity
+  id: LeftHand
+  components:
+  - type: Organ
+  - type: HandOrgan
+    handID: left
+    data:
+      location: Left
+
+- type: entity
+  id: RightHand
+  components:
+  - type: Organ
+  - type: HandOrgan
+    handID: right
+    data:
+      location: Right
+";
+    [Test]
+    public async Task HandInsertionAndRemovalTest()
+    {
+        await using var pair = await PoolManager.GetServerClient();
+        var server = pair.Server;
+
+        await server.WaitIdleAsync();
+
+        var entityManager = server.ResolveDependency<IEntityManager>();
+        var mapData = await pair.CreateTestMap();
+
+        await server.WaitAssertion(() =>
+        {
+            var container = entityManager.System<SharedContainerSystem>();
+            var body = entityManager.SpawnEntity("TheBody", mapData.GridCoords);
+            var hands = entityManager.GetComponent<HandsComponent>(body);
+
+            Assert.That(hands.Count, Is.EqualTo(2));
+
+            var handsContainer = container.GetContainer(body, BodyComponent.ContainerID);
+
+            var expectedCount = 2;
+            var contained = handsContainer.ContainedEntities.ToList();
+            foreach (var hand in contained)
+            {
+                expectedCount--;
+                container.Remove(hand, handsContainer);
+                Assert.That(hands.Count, Is.EqualTo(expectedCount));
+            }
+
+            var protos = new List<string>() { "LeftHand", "RightHand" };
+            foreach (var proto in protos)
+            {
+                expectedCount++;
+                entityManager.SpawnInContainerOrDrop(proto, body, BodyComponent.ContainerID);
+                Assert.That(hands.Count, Is.EqualTo(expectedCount));
+            }
+        });
+
+        await pair.CleanReturnAsync();
+    }
+}
diff --git a/Content.IntegrationTests/Tests/Body/LegTest.cs b/Content.IntegrationTests/Tests/Body/LegTest.cs
deleted file mode 100644 (file)
index 7b49bbe..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-using System.Numerics;
-using Content.Server.Body.Systems;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
-using Content.Shared.Rotation;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Map;
-
-namespace Content.IntegrationTests.Tests.Body
-{
-    [TestFixture]
-    [TestOf(typeof(BodyPartComponent))]
-    [TestOf(typeof(BodyComponent))]
-    public sealed class LegTest
-    {
-        [TestPrototypes]
-        private const string Prototypes = @"
-- type: entity
-  name: HumanBodyAndAppearanceDummy
-  id: HumanBodyAndAppearanceDummy
-  components:
-  - type: Appearance
-  - type: Body
-    prototype: Human
-  - type: StandingState
-";
-
-        [Test]
-        public async Task RemoveLegsFallTest()
-        {
-            await using var pair = await PoolManager.GetServerClient();
-            var server = pair.Server;
-
-            EntityUid human = default!;
-            AppearanceComponent appearance = null;
-
-            var entityManager = server.ResolveDependency<IEntityManager>();
-            var mapManager = server.ResolveDependency<IMapManager>();
-            var appearanceSystem = entityManager.System<SharedAppearanceSystem>();
-            var xformSystem = entityManager.System<SharedTransformSystem>();
-
-            var map = await pair.CreateTestMap();
-
-            await server.WaitAssertion(() =>
-            {
-                BodyComponent body = null;
-
-                human = entityManager.SpawnEntity("HumanBodyAndAppearanceDummy",
-                    new MapCoordinates(Vector2.Zero, map.MapId));
-
-                Assert.Multiple(() =>
-                {
-                    Assert.That(entityManager.TryGetComponent(human, out body));
-                    Assert.That(entityManager.TryGetComponent(human, out appearance));
-                });
-
-                Assert.That(!appearanceSystem.TryGetData(human, RotationVisuals.RotationState, out RotationState _, appearance));
-
-                var bodySystem = entityManager.System<BodySystem>();
-                var legs = bodySystem.GetBodyChildrenOfType(human, BodyPartType.Leg, body);
-
-                foreach (var leg in legs)
-                {
-                    xformSystem.DetachEntity(leg.Id, entityManager.GetComponent<TransformComponent>(leg.Id));
-                }
-            });
-
-            await server.WaitAssertion(() =>
-            {
-#pragma warning disable NUnit2045
-                // Interdependent assertions.
-                Assert.That(appearanceSystem.TryGetData(human, RotationVisuals.RotationState, out RotationState state, appearance));
-                Assert.That(state, Is.EqualTo(RotationState.Horizontal));
-#pragma warning restore NUnit2045
-            });
-            await pair.CleanReturnAsync();
-        }
-    }
-}
diff --git a/Content.IntegrationTests/Tests/Body/LungTest.cs b/Content.IntegrationTests/Tests/Body/LungTest.cs
deleted file mode 100644 (file)
index 584eb58..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-using Content.Server.Atmos.Components;
-using Content.Server.Atmos.EntitySystems;
-using Content.Server.Body.Components;
-using Content.Shared.Body.Systems;
-using Content.Shared.Body.Components;
-using Robust.Server.GameObjects;
-using Robust.Shared;
-using Robust.Shared.Configuration;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Map;
-using Robust.Shared.Map.Components;
-using System.Linq;
-using System.Numerics;
-using Robust.Shared.EntitySerialization.Systems;
-using Robust.Shared.Utility;
-
-namespace Content.IntegrationTests.Tests.Body
-{
-    [TestFixture]
-    [TestOf(typeof(LungSystem))]
-    public sealed class LungTest
-    {
-        [TestPrototypes]
-        private const string Prototypes = @"
-- type: entity
-  name: HumanLungDummy
-  id: HumanLungDummy
-  components:
-  - type: SolutionContainerManager
-  - type: Body
-    prototype: Human
-  - type: MobState
-    allowedStates:
-      - Alive
-  - type: Damageable
-  - type: ThermalRegulator
-    metabolismHeat: 5000
-    radiatedHeat: 400
-    implicitHeatRegulation: 5000
-    sweatHeatRegulation: 5000
-    shiveringHeatRegulation: 5000
-    normalBodyTemperature: 310.15
-    thermalRegulationTemperatureThreshold: 25
-  - type: Respirator
-    damage:
-      types:
-        Asphyxiation: 1.5
-    damageRecovery:
-      types:
-        Asphyxiation: -1.5
-";
-
-        [Test]
-        public async Task AirConsistencyTest()
-        {
-            // --- Setup
-            await using var pair = await PoolManager.GetServerClient();
-            var server = pair.Server;
-
-            await server.WaitIdleAsync();
-
-            var entityManager = server.ResolveDependency<IEntityManager>();
-            var mapLoader = entityManager.System<MapLoaderSystem>();
-            var mapSys = entityManager.System<SharedMapSystem>();
-
-            EntityUid? grid = null;
-            BodyComponent body = default;
-            RespiratorComponent resp = default;
-            EntityUid human = default;
-            GridAtmosphereComponent relevantAtmos = default;
-            var startingMoles = 0.0f;
-
-            var testMapName = new ResPath("Maps/Test/Breathing/3by3-20oxy-80nit.yml");
-
-            await server.WaitPost(() =>
-            {
-                mapSys.CreateMap(out var mapId);
-                Assert.That(mapLoader.TryLoadGrid(mapId, testMapName, out var gridEnt));
-                grid = gridEnt!.Value.Owner;
-            });
-
-            Assert.That(grid, Is.Not.Null, $"Test blueprint {testMapName} not found.");
-
-            float GetMapMoles()
-            {
-                var totalMapMoles = 0.0f;
-                foreach (var tile in relevantAtmos.Tiles.Values)
-                {
-                    totalMapMoles += tile.Air?.TotalMoles ?? 0.0f;
-                }
-
-                return totalMapMoles;
-            }
-
-            await server.WaitAssertion(() =>
-            {
-                var center = new Vector2(0.5f, 0.5f);
-                var coordinates = new EntityCoordinates(grid.Value, center);
-                human = entityManager.SpawnEntity("HumanLungDummy", coordinates);
-                relevantAtmos = entityManager.GetComponent<GridAtmosphereComponent>(grid.Value);
-                startingMoles = 100f; // Hardcoded because GetMapMoles returns 900 here for some reason.
-
-#pragma warning disable NUnit2045
-                Assert.That(entityManager.TryGetComponent(human, out body), Is.True);
-                Assert.That(entityManager.TryGetComponent(human, out resp), Is.True);
-#pragma warning restore NUnit2045
-            });
-
-            // --- End setup
-
-            var inhaleCycles = 100;
-            for (var i = 0; i < inhaleCycles; i++)
-            {
-                // Breathe in
-                await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Exhaling);
-                Assert.That(
-                    GetMapMoles(), Is.LessThan(startingMoles),
-                    "Did not inhale in any gas"
-                );
-
-                // Breathe out
-                await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Inhaling);
-                Assert.That(
-                    GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002),
-                    "Did not exhale as much gas as was inhaled"
-                );
-            }
-
-            await pair.CleanReturnAsync();
-        }
-
-        [Test]
-        public async Task NoSuffocationTest()
-        {
-            await using var pair = await PoolManager.GetServerClient();
-            var server = pair.Server;
-
-            var mapManager = server.ResolveDependency<IMapManager>();
-            var entityManager = server.ResolveDependency<IEntityManager>();
-            var cfg = server.ResolveDependency<IConfigurationManager>();
-            var mapLoader = entityManager.System<MapLoaderSystem>();
-            var mapSys = entityManager.System<SharedMapSystem>();
-
-            EntityUid? grid = null;
-            RespiratorComponent respirator = null;
-            EntityUid human = default;
-
-            var testMapName = new ResPath("Maps/Test/Breathing/3by3-20oxy-80nit.yml");
-
-            await server.WaitPost(() =>
-            {
-                mapSys.CreateMap(out var mapId);
-                Assert.That(mapLoader.TryLoadGrid(mapId, testMapName, out var gridEnt));
-                grid = gridEnt!.Value.Owner;
-            });
-
-            Assert.That(grid, Is.Not.Null, $"Test blueprint {testMapName} not found.");
-
-            await server.WaitAssertion(() =>
-            {
-                var center = new Vector2(0.5f, 0.5f);
-
-                var coordinates = new EntityCoordinates(grid.Value, center);
-                human = entityManager.SpawnEntity("HumanLungDummy", coordinates);
-
-                var mixture = entityManager.System<AtmosphereSystem>().GetContainingMixture(human);
-#pragma warning disable NUnit2045
-                Assert.That(mixture.TotalMoles, Is.GreaterThan(0));
-                Assert.That(entityManager.HasComponent<BodyComponent>(human), Is.True);
-                Assert.That(entityManager.TryGetComponent(human, out respirator), Is.True);
-                Assert.That(respirator.SuffocationCycles, Is.LessThanOrEqualTo(respirator.SuffocationCycleThreshold));
-#pragma warning restore NUnit2045
-            });
-
-            var increment = 10;
-
-            // 20 seconds
-            var total = 20 * cfg.GetCVar(CVars.NetTickrate);
-
-            for (var tick = 0; tick < total; tick += increment)
-            {
-                await server.WaitRunTicks(increment);
-                await server.WaitAssertion(() =>
-                {
-                    Assert.That(respirator.SuffocationCycles, Is.LessThanOrEqualTo(respirator.SuffocationCycleThreshold),
-                        $"Entity {entityManager.GetComponent<MetaDataComponent>(human).EntityName} is suffocating on tick {tick}");
-                });
-            }
-
-            await pair.CleanReturnAsync();
-        }
-    }
-}
diff --git a/Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs b/Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs
deleted file mode 100644 (file)
index 67163d0..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Systems;
-using Robust.Shared.Containers;
-using Robust.Shared.EntitySerialization.Systems;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Map;
-using Robust.Shared.Utility;
-
-namespace Content.IntegrationTests.Tests.Body;
-
-[TestFixture]
-public sealed class SaveLoadReparentTest
-{
-    [TestPrototypes]
-    private const string Prototypes = @"
-- type: entity
-  name: HumanBodyDummy
-  id: HumanBodyDummy
-  components:
-  - type: Body
-    prototype: Human
-";
-
-    [Test]
-    public async Task Test()
-    {
-        await using var pair = await PoolManager.GetServerClient();
-        var server = pair.Server;
-
-        var entities = server.ResolveDependency<IEntityManager>();
-        var maps = server.ResolveDependency<IMapManager>();
-        var mapLoader = entities.System<MapLoaderSystem>();
-        var bodySystem = entities.System<SharedBodySystem>();
-        var containerSystem = entities.System<SharedContainerSystem>();
-        var mapSys = entities.System<SharedMapSystem>();
-
-        await server.WaitAssertion(() =>
-        {
-            mapSys.CreateMap(out var mapId);
-            maps.CreateGrid(mapId);
-            var human = entities.SpawnEntity("HumanBodyDummy", new MapCoordinates(0, 0, mapId));
-
-            Assert.That(entities.HasComponent<BodyComponent>(human), Is.True);
-
-            var parts = bodySystem.GetBodyChildren(human).Skip(1).ToArray();
-            var organs = bodySystem.GetBodyOrgans(human).ToArray();
-
-            Assert.Multiple(() =>
-            {
-                Assert.That(parts, Is.Not.Empty);
-                Assert.That(organs, Is.Not.Empty);
-            });
-
-            foreach (var (id, component) in parts)
-            {
-                Assert.Multiple(() =>
-                {
-                    Assert.That(component.Body, Is.EqualTo(human));
-                    Assert.That(component.Body, Is.Not.Null);
-                    var parent = bodySystem.GetParentPartOrNull(id);
-                    Assert.That(parent, Is.Not.EqualTo(default(EntityUid)));
-                    if (!bodySystem.IsPartRoot(component.Body.Value, id, null, component))
-                    {
-                        Assert.That(parent, Is.Not.Null);
-                    }
-                    else
-                    {
-                        Assert.That(parent, Is.Null);
-                    }
-                });
-
-                foreach (var (slotId, slot) in component.Children)
-                {
-                    Assert.Multiple(() =>
-                    {
-                        Assert.That(slot.Id, Is.EqualTo(slotId));
-                        var container =
-                            containerSystem.GetContainer(id, SharedBodySystem.GetPartSlotContainerId(slotId));
-                        Assert.That(container.ContainedEntities, Is.Not.Empty);
-                    });
-                }
-            }
-
-            foreach (var (id, component) in organs)
-            {
-                var parent = bodySystem.GetParentPartOrNull(id);
-
-                Assert.Multiple(() =>
-                {
-                    Assert.That(component.Body, Is.EqualTo(human));
-                    Assert.That(parent, Is.Not.Null);
-                    Assert.That(parent.Value, Is.Not.EqualTo(default(EntityUid)));
-                });
-            }
-
-            // Converts an entity query enumerator to an enumerable.
-            static IEnumerable<(EntityUid Uid, TComp Comp)> EnumerateQueryEnumerator<TComp>(EntityQueryEnumerator<TComp> query)
-                where TComp : Component
-            {
-                while (query.MoveNext(out var uid, out var comp))
-                    yield return (uid, comp);
-            }
-
-            Assert.That(
-                EnumerateQueryEnumerator(
-                    entities.EntityQueryEnumerator<BodyComponent>()
-                ).Where((e) =>
-                    entities.GetComponent<MetaDataComponent>(e.Uid).EntityPrototype!.Name == "HumanBodyDummy"
-                ),
-                Is.Not.Empty
-            );
-
-            var mapPath = new ResPath($"/{nameof(SaveLoadReparentTest)}{nameof(Test)}map.yml");
-
-            Assert.That(mapLoader.TrySaveMap(mapId, mapPath));
-            mapSys.DeleteMap(mapId);
-
-            Assert.That(mapLoader.TryLoadMap(mapPath, out var map, out _), Is.True);
-
-            var query = EnumerateQueryEnumerator(
-                    entities.EntityQueryEnumerator<BodyComponent>()
-                ).Where((e) =>
-                    entities.GetComponent<MetaDataComponent>(e.Uid).EntityPrototype!.Name == "HumanBodyDummy"
-                ).ToArray();
-
-            Assert.That(query, Is.Not.Empty);
-            foreach (var (uid, body) in query)
-            {
-                human = uid;
-                parts = bodySystem.GetBodyChildren(human).Skip(1).ToArray();
-                organs = bodySystem.GetBodyOrgans(human).ToArray();
-
-                Assert.Multiple(() =>
-                {
-                    Assert.That(parts, Is.Not.Empty);
-                    Assert.That(organs, Is.Not.Empty);
-                });
-
-                foreach (var (id, component) in parts)
-                {
-                    var parent = bodySystem.GetParentPartOrNull(id);
-
-                    Assert.Multiple(() =>
-                    {
-                        Assert.That(component.Body, Is.EqualTo(human));
-                        Assert.That(parent, Is.Not.Null);
-                        Assert.That(parent.Value, Is.Not.EqualTo(default(EntityUid)));
-                    });
-
-                    foreach (var (slotId, slot) in component.Children)
-                    {
-                        Assert.Multiple(() =>
-                        {
-                            Assert.That(slot.Id, Is.EqualTo(slotId));
-                            var container =
-                                containerSystem.GetContainer(id, SharedBodySystem.GetPartSlotContainerId(slotId));
-                            Assert.That(container.ContainedEntities, Is.Not.Empty);
-                        });
-                    }
-                }
-
-                foreach (var (id, component) in organs)
-                {
-                    var parent = bodySystem.GetParentPartOrNull(id);
-
-                    Assert.Multiple(() =>
-                    {
-                        Assert.That(component.Body, Is.EqualTo(human));
-                        Assert.That(parent, Is.Not.Null);
-                        Assert.That(parent.Value, Is.Not.EqualTo(default(EntityUid)));
-                    });
-                }
-
-                entities.DeleteEntity(map);
-            }
-        });
-
-        await pair.CleanReturnAsync();
-    }
-}
index bbc8b67c53bdfede149a3254f3269773c86c565d..b42f42922a4090435d5592fb13dcbf4e6bfd78ff 100644 (file)
@@ -1,9 +1,6 @@
 using System.Numerics;
-using Content.Server.Body.Systems;
 using Content.Shared.Buckle;
 using Content.Shared.ActionBlocker;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
 using Content.Shared.Buckle.Components;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
@@ -247,7 +244,6 @@ namespace Content.IntegrationTests.Tests.Buckle
             EntityUid human = default;
             BuckleComponent buckle = null;
             HandsComponent hands = null;
-            BodyComponent body = null;
 
             await server.WaitIdleAsync();
 
@@ -267,7 +263,6 @@ namespace Content.IntegrationTests.Tests.Buckle
                     Assert.That(entityManager.TryGetComponent(human, out buckle));
                     Assert.That(entityManager.HasComponent<StrapComponent>(chair));
                     Assert.That(entityManager.TryGetComponent(human, out hands));
-                    Assert.That(entityManager.TryGetComponent(human, out body));
                 });
 
                 // Buckle
@@ -289,29 +284,6 @@ namespace Content.IntegrationTests.Tests.Buckle
 
             await server.WaitRunTicks(10);
 
-            await server.WaitAssertion(() =>
-            {
-                // Still buckled
-                Assert.That(buckle.Buckled);
-
-                // With items in all hands
-                foreach (var hand in hands.Hands.Keys)
-                {
-                    Assert.That(handsSys.GetHeldItem((human, hands), hand), Is.Not.Null);
-                }
-
-                var bodySystem = entityManager.System<BodySystem>();
-                var legs = bodySystem.GetBodyChildrenOfType(human, BodyPartType.Leg, body);
-
-                // Break our guy's kneecaps
-                foreach (var leg in legs)
-                {
-                    entityManager.DeleteEntity(leg.Id);
-                }
-            });
-
-            await server.WaitRunTicks(10);
-
             await server.WaitAssertion(() =>
             {
                 // Still buckled
diff --git a/Content.IntegrationTests/Tests/Respirator/LungTest.cs b/Content.IntegrationTests/Tests/Respirator/LungTest.cs
new file mode 100644 (file)
index 0000000..a4ad733
--- /dev/null
@@ -0,0 +1,189 @@
+using Content.Server.Atmos.Components;
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Body.Components;
+using Content.Shared.Body.Systems;
+using Robust.Shared;
+using Robust.Shared.Configuration;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Map;
+using System.Numerics;
+using Robust.Shared.EntitySerialization.Systems;
+using Robust.Shared.Utility;
+
+namespace Content.IntegrationTests.Tests.Respirator;
+
+[TestFixture]
+[TestOf(typeof(LungSystem))]
+public sealed class LungTest
+{
+    [TestPrototypes]
+    private const string Prototypes = @"
+- type: entity
+  name: HumanLungDummy
+  id: HumanLungDummy
+  components:
+  - type: SolutionContainerManager
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganHumanLungs
+  - type: MobState
+    allowedStates:
+      - Alive
+  - type: Damageable
+  - type: ThermalRegulator
+    metabolismHeat: 5000
+    radiatedHeat: 400
+    implicitHeatRegulation: 5000
+    sweatHeatRegulation: 5000
+    shiveringHeatRegulation: 5000
+    normalBodyTemperature: 310.15
+    thermalRegulationTemperatureThreshold: 25
+  - type: Respirator
+    damage:
+      types:
+        Asphyxiation: 1.5
+    damageRecovery:
+      types:
+        Asphyxiation: -1.5
+";
+
+    [Test]
+    public async Task AirConsistencyTest()
+    {
+        // --- Setup
+        await using var pair = await PoolManager.GetServerClient();
+        var server = pair.Server;
+
+        await server.WaitIdleAsync();
+
+        var entityManager = server.ResolveDependency<IEntityManager>();
+        var mapLoader = entityManager.System<MapLoaderSystem>();
+        var mapSys = entityManager.System<SharedMapSystem>();
+
+        EntityUid? grid = null;
+        RespiratorComponent resp = default;
+        EntityUid human = default;
+        GridAtmosphereComponent relevantAtmos = default;
+        var startingMoles = 0.0f;
+
+        var testMapName = new ResPath("Maps/Test/Breathing/3by3-20oxy-80nit.yml");
+
+        await server.WaitPost(() =>
+        {
+            mapSys.CreateMap(out var mapId);
+            Assert.That(mapLoader.TryLoadGrid(mapId, testMapName, out var gridEnt));
+            grid = gridEnt!.Value.Owner;
+        });
+
+        Assert.That(grid, Is.Not.Null, $"Test blueprint {testMapName} not found.");
+
+        float GetMapMoles()
+        {
+            var totalMapMoles = 0.0f;
+            foreach (var tile in relevantAtmos.Tiles.Values)
+            {
+                totalMapMoles += tile.Air?.TotalMoles ?? 0.0f;
+            }
+
+            return totalMapMoles;
+        }
+
+        await server.WaitAssertion(() =>
+        {
+            var center = new Vector2(0.5f, 0.5f);
+            var coordinates = new EntityCoordinates(grid.Value, center);
+            human = entityManager.SpawnEntity("HumanLungDummy", coordinates);
+            relevantAtmos = entityManager.GetComponent<GridAtmosphereComponent>(grid.Value);
+            startingMoles = 100f; // Hardcoded because GetMapMoles returns 900 here for some reason.
+
+#pragma warning disable NUnit2045
+            Assert.That(entityManager.TryGetComponent(human, out resp), Is.True);
+#pragma warning restore NUnit2045
+        });
+
+        // --- End setup
+
+        var inhaleCycles = 100;
+        for (var i = 0; i < inhaleCycles; i++)
+        {
+            // Breathe in
+            await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Exhaling);
+            Assert.That(
+                GetMapMoles(), Is.LessThan(startingMoles),
+                "Did not inhale in any gas"
+            );
+
+            // Breathe out
+            await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Inhaling);
+            Assert.That(
+                GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002),
+                "Did not exhale as much gas as was inhaled"
+            );
+        }
+
+        await pair.CleanReturnAsync();
+    }
+
+    [Test]
+    public async Task NoSuffocationTest()
+    {
+        await using var pair = await PoolManager.GetServerClient();
+        var server = pair.Server;
+
+        var mapManager = server.ResolveDependency<IMapManager>();
+        var entityManager = server.ResolveDependency<IEntityManager>();
+        var cfg = server.ResolveDependency<IConfigurationManager>();
+        var mapLoader = entityManager.System<MapLoaderSystem>();
+        var mapSys = entityManager.System<SharedMapSystem>();
+
+        EntityUid? grid = null;
+        RespiratorComponent respirator = null;
+        EntityUid human = default;
+
+        var testMapName = new ResPath("Maps/Test/Breathing/3by3-20oxy-80nit.yml");
+
+        await server.WaitPost(() =>
+        {
+            mapSys.CreateMap(out var mapId);
+            Assert.That(mapLoader.TryLoadGrid(mapId, testMapName, out var gridEnt));
+            grid = gridEnt!.Value.Owner;
+        });
+
+        Assert.That(grid, Is.Not.Null, $"Test blueprint {testMapName} not found.");
+
+        await server.WaitAssertion(() =>
+        {
+            var center = new Vector2(0.5f, 0.5f);
+
+            var coordinates = new EntityCoordinates(grid.Value, center);
+            human = entityManager.SpawnEntity("HumanLungDummy", coordinates);
+
+            var mixture = entityManager.System<AtmosphereSystem>().GetContainingMixture(human);
+#pragma warning disable NUnit2045
+            Assert.That(mixture.TotalMoles, Is.GreaterThan(0));
+            Assert.That(entityManager.TryGetComponent(human, out respirator), Is.True);
+            Assert.That(respirator.SuffocationCycles, Is.LessThanOrEqualTo(respirator.SuffocationCycleThreshold));
+#pragma warning restore NUnit2045
+        });
+
+        var increment = 10;
+
+        // 20 seconds
+        var total = 20 * cfg.GetCVar(CVars.NetTickrate);
+
+        for (var tick = 0; tick < total; tick += increment)
+        {
+            await server.WaitRunTicks(increment);
+            await server.WaitAssertion(() =>
+            {
+                Assert.That(respirator.SuffocationCycles, Is.LessThanOrEqualTo(respirator.SuffocationCycleThreshold),
+                    $"Entity {entityManager.GetComponent<MetaDataComponent>(human).EntityName} is suffocating on tick {tick}");
+            });
+        }
+
+        await pair.CleanReturnAsync();
+    }
+}
diff --git a/Content.Server/Administration/Commands/AddBodyPartCommand.cs b/Content.Server/Administration/Commands/AddBodyPartCommand.cs
deleted file mode 100644 (file)
index a28fa93..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-using Content.Server.Body.Systems;
-using Content.Shared.Administration;
-using Content.Shared.Body.Part;
-using Robust.Shared.Console;
-
-namespace Content.Server.Administration.Commands;
-
-[AdminCommand(AdminFlags.Admin)]
-public sealed class AddBodyPartCommand : LocalizedEntityCommands
-{
-    [Dependency] private readonly BodySystem _bodySystem = default!;
-
-    public override string Command => "addbodypart";
-
-    public override void Execute(IConsoleShell shell, string argStr, string[] args)
-    {
-        if (args.Length != 4)
-        {
-            shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
-            return;
-        }
-
-        if (!NetEntity.TryParse(args[0], out var childNetId) || !EntityManager.TryGetEntity(childNetId, out var childId))
-        {
-            shell.WriteError(Loc.GetString("shell-invalid-entity-uid", ("uid", args[0])));
-            return;
-        }
-
-        if (!NetEntity.TryParse(args[1], out var parentNetId) || !EntityManager.TryGetEntity(parentNetId, out var parentId))
-        {
-            shell.WriteError(Loc.GetString("shell-invalid-entity-uid", ("uid", args[1])));
-            return;
-        }
-
-        if (Enum.TryParse<BodyPartType>(args[3], out var partType) &&
-            _bodySystem.TryCreatePartSlotAndAttach(parentId.Value, args[2], childId.Value, partType))
-        {
-            shell.WriteLine($@"Added {childId} to {parentId}.");
-        }
-        else
-            shell.WriteError($@"Could not add {childId} to {parentId}.");
-    }
-}
diff --git a/Content.Server/Administration/Commands/AddMechanismCommand.cs b/Content.Server/Administration/Commands/AddMechanismCommand.cs
deleted file mode 100644 (file)
index e62ddea..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-using Content.Server.Body.Systems;
-using Content.Shared.Administration;
-using Robust.Shared.Console;
-
-namespace Content.Server.Administration.Commands
-{
-    [AdminCommand(AdminFlags.Admin)]
-    public sealed class AddMechanismCommand : IConsoleCommand
-    {
-        [Dependency] private readonly IEntityManager _entManager = default!;
-
-        public string Command => "addmechanism";
-        public string Description => "Adds a given entity to a containing body.";
-        public string Help => "Usage: addmechanism <entity uid> <bodypart uid>";
-
-        public void Execute(IConsoleShell shell, string argStr, string[] args)
-        {
-            if (args.Length != 2)
-            {
-                shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
-                return;
-            }
-
-            if (!NetEntity.TryParse(args[0], out var organIdNet) || !_entManager.TryGetEntity(organIdNet, out var organId))
-            {
-                shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
-                return;
-            }
-
-            if (!NetEntity.TryParse(args[1], out var partIdNet) || !_entManager.TryGetEntity(partIdNet, out var partId))
-            {
-                shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
-                return;
-            }
-
-            var bodySystem = _entManager.System<BodySystem>();
-
-            if (bodySystem.AddOrganToFirstValidSlot(partId.Value, organId.Value))
-            {
-                shell.WriteLine($@"Added {organId} to {partId}.");
-            }
-            else
-            {
-                shell.WriteError($@"Could not add {organId} to {partId}.");
-            }
-        }
-    }
-}
index bae7776ef0691388fa6b64dcc6242065d2878818..dab886f81050ef06def226287d7eadff8e93875b 100644 (file)
@@ -1,3 +1,4 @@
+using System.Linq;
 using System.Numerics;
 using System.Threading;
 using Content.Server.Atmos.EntitySystems;
@@ -20,8 +21,8 @@ using Content.Shared.Administration;
 using Content.Shared.Administration.Components;
 using Content.Shared.Administration.Systems;
 using Content.Shared.Atmos.Components;
+using Content.Shared.Body;
 using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
 using Content.Shared.Clothing.Components;
 using Content.Shared.Clumsy;
 using Content.Shared.Cluwne;
@@ -307,7 +308,6 @@ public sealed partial class AdminVerbSystem
             args.Verbs.Add(bloodRemoval);
         }
 
-        // bobby...
         if (TryComp<BodyComponent>(args.Target, out var body))
         {
             var vomitOrgansName = Loc.GetString("admin-smite-vomit-organs-name").ToLowerInvariant();
@@ -319,14 +319,14 @@ public sealed partial class AdminVerbSystem
                 Act = () =>
                 {
                     _vomitSystem.Vomit(args.Target, -1000, -1000); // You feel hollow!
-                    var organs = _bodySystem.GetBodyOrganEntityComps<TransformComponent>((args.Target, body));
+                    _bodySystem.TryGetOrgansWithComponent<TransformComponent>((args.Target, body), out var organs);
                     var baseXform = Transform(args.Target);
                     foreach (var organ in organs)
                     {
                         if (HasComp<BrainComponent>(organ.Owner) || HasComp<EyeComponent>(organ.Owner))
                             continue;
 
-                        _transformSystem.PlaceNextTo((organ.Owner, organ.Comp1), (args.Target, baseXform));
+                        _transformSystem.PlaceNextTo((organ.Owner, organ.Comp), (args.Target, baseXform));
                     }
 
                     _popupSystem.PopupEntity(Loc.GetString("admin-smite-vomit-organs-self"), args.Target,
@@ -348,9 +348,11 @@ public sealed partial class AdminVerbSystem
                 Act = () =>
                 {
                     var baseXform = Transform(args.Target);
-                    foreach (var part in _bodySystem.GetBodyChildrenOfType(args.Target, BodyPartType.Hand))
+                    var parts = new HashSet<ProtoId<OrganCategoryPrototype>>() { "HandRight", "HandLeft" };
+                    _bodySystem.TryGetOrgansWithComponent<OrganComponent>((args.Target, body), out var organs);
+                    foreach (var organ in organs.Where(it => it.Comp.Category is { } category && parts.Contains(category)))
                     {
-                        _transformSystem.AttachToGridOrMap(part.Id);
+                        _transformSystem.AttachToGridOrMap(organ);
                     }
                     _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target,
                         args.Target, PopupType.LargeCaution);
@@ -371,9 +373,11 @@ public sealed partial class AdminVerbSystem
                 Act = () =>
                 {
                     var baseXform = Transform(args.Target);
-                    foreach (var part in _bodySystem.GetBodyChildrenOfType(args.Target, BodyPartType.Hand, body))
+                    var parts = new HashSet<ProtoId<OrganCategoryPrototype>>() { "HandRight", "HandLeft" };
+                    _bodySystem.TryGetOrgansWithComponent<OrganComponent>((args.Target, body), out var organs);
+                    foreach (var organ in organs.Where(it => it.Comp.Category is { } category && parts.Contains(category)))
                     {
-                        _transformSystem.AttachToGridOrMap(part.Id);
+                        _transformSystem.AttachToGridOrMap(organ);
                         break;
                     }
                     _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target,
@@ -394,7 +398,8 @@ public sealed partial class AdminVerbSystem
                 Icon = new SpriteSpecifier.Rsi(new("/Textures/Mobs/Species/Human/organs.rsi"), "stomach"),
                 Act = () =>
                 {
-                    foreach (var entity in _bodySystem.GetBodyOrganEntityComps<StomachComponent>((args.Target, body)))
+                    _bodySystem.TryGetOrgansWithComponent<StomachComponent>((args.Target, body), out var organs);
+                    foreach (var entity in organs)
                     {
                         QueueDel(entity.Owner);
                     }
@@ -415,7 +420,8 @@ public sealed partial class AdminVerbSystem
                 Icon = new SpriteSpecifier.Rsi(new("/Textures/Mobs/Species/Human/organs.rsi"), "lung-r"),
                 Act = () =>
                 {
-                    foreach (var entity in _bodySystem.GetBodyOrganEntityComps<LungComponent>((args.Target, body)))
+                    _bodySystem.TryGetOrgansWithComponent<LungComponent>((args.Target, body), out var organs);
+                    foreach (var entity in organs)
                     {
                         QueueDel(entity.Owner);
                     }
index 9c671d4db23439f4a9f91f636b417ce2c6373408..3cfb9c70253e25e64ff8fc2a241853aebd04fc5c 100644 (file)
@@ -132,9 +132,6 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
 
     private void OnAnomalySupercritical(Entity<InnerBodyAnomalyComponent> ent, ref AnomalySupercriticalEvent args)
     {
-        if (!TryComp<BodyComponent>(ent, out var body))
-            return;
-
         _gibbing.Gib(ent.Owner);
     }
 
index 4d2805333a7d18b0e353c6162c0c4e994160132c..5d02d19155efa7b45927f85319e927c920149d65 100644 (file)
@@ -1,10 +1,6 @@
-using System.Linq;
 using Content.Server.Administration;
-using Content.Server.Body.Systems;
 using Content.Server.Hands.Systems;
 using Content.Shared.Administration;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
 using Content.Shared.Hands.Components;
 using Robust.Shared.Console;
 using Robust.Shared.Prototypes;
@@ -17,19 +13,17 @@ namespace Content.Server.Body.Commands
         [Dependency] private readonly IEntityManager _entManager = default!;
         [Dependency] private readonly IPrototypeManager _protoManager = default!;
 
-        private static readonly EntProtoId DefaultHandPrototype = "LeftHandHuman";
         private static int _handIdAccumulator;
 
         public string Command => "addhand";
         public string Description => "Adds a hand to your entity.";
-        public string Help => $"Usage: {Command} <entityUid> <handPrototypeId> / {Command} <entityUid> / {Command} <handPrototypeId> / {Command}";
+        public string Help => $"Usage: {Command} <entityUid>";
 
         public void Execute(IConsoleShell shell, string argStr, string[] args)
         {
             var player = shell.Player;
 
             EntityUid entity;
-            EntityUid hand;
 
             switch (args.Length)
             {
@@ -47,7 +41,6 @@ namespace Content.Server.Body.Commands
                     }
 
                     entity = player.AttachedEntity.Value;
-                    hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
                     break;
                 case 1:
                     {
@@ -60,7 +53,6 @@ namespace Content.Server.Body.Commands
                             }
 
                             entity = uid.Value;
-                            hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
                         }
                         else
                         {
@@ -77,35 +69,8 @@ namespace Content.Server.Body.Commands
                             }
 
                             entity = player.AttachedEntity.Value;
-                            hand = _entManager.SpawnEntity(args[0], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
                         }
 
-                        break;
-                    }
-                case 2:
-                    {
-                        if (!NetEntity.TryParse(args[0], out var netEnt) || !_entManager.TryGetEntity(netEnt, out var uid))
-                        {
-                            shell.WriteLine($"{args[0]} is not a valid entity uid.");
-                            return;
-                        }
-
-                        if (!_entManager.EntityExists(uid))
-                        {
-                            shell.WriteLine($"No entity exists with uid {uid}.");
-                            return;
-                        }
-
-                        entity = uid.Value;
-
-                        if (!_protoManager.HasIndex<EntityPrototype>(args[1]))
-                        {
-                            shell.WriteLine($"No hand entity exists with id {args[1]}.");
-                            return;
-                        }
-
-                        hand = _entManager.SpawnEntity(args[1], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
-
                         break;
                     }
                 default:
@@ -113,41 +78,7 @@ namespace Content.Server.Body.Commands
                     return;
             }
 
-            if (!_entManager.TryGetComponent(entity, out BodyComponent? body) || body.RootContainer.ContainedEntity == null)
-            {
-                var location = _entManager.GetComponentOrNull<BodyPartComponent>(hand)?.Symmetry switch
-                {
-                    BodyPartSymmetry.None => HandLocation.Middle,
-                    BodyPartSymmetry.Left => HandLocation.Left,
-                    BodyPartSymmetry.Right => HandLocation.Right,
-                    _ => HandLocation.Right
-                };
-                _entManager.DeleteEntity(hand);
-
-                // You have no body and you must scream.
-                _entManager.System<HandsSystem>().AddHand(entity, $"{hand}-cmd-{_handIdAccumulator++}", location);
-                return;
-            }
-
-            if (!_entManager.TryGetComponent(hand, out BodyPartComponent? part))
-            {
-                shell.WriteLine($"Hand entity {hand} does not have a {nameof(BodyPartComponent)} component.");
-                return;
-            }
-
-            var bodySystem = _entManager.System<BodySystem>();
-
-            var attachAt = bodySystem.GetBodyChildrenOfType(entity, BodyPartType.Arm, body).FirstOrDefault();
-            if (attachAt == default)
-                attachAt = bodySystem.GetBodyChildren(entity, body).First();
-
-            var slotId = part.GetHashCode().ToString();
-
-            if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand, attachAt.Component, part))
-            {
-                shell.WriteError($"Couldn't create a slot with id {slotId} on entity {_entManager.ToPrettyString(entity)}");
-                return;
-            }
+            _entManager.System<HandsSystem>().AddHand(entity, $"cmd-{_handIdAccumulator++}", HandLocation.Middle);
 
             shell.WriteLine($"Added hand to entity {_entManager.GetComponent<MetaDataComponent>(entity).EntityName}");
         }
diff --git a/Content.Server/Body/Commands/AttachBodyPartCommand.cs b/Content.Server/Body/Commands/AttachBodyPartCommand.cs
deleted file mode 100644 (file)
index 9172e9e..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-using Content.Server.Administration;
-using Content.Server.Body.Systems;
-using Content.Shared.Administration;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
-using Robust.Shared.Console;
-
-namespace Content.Server.Body.Commands
-{
-    [AdminCommand(AdminFlags.Fun)]
-    public sealed class AttachBodyPartCommand : IConsoleCommand
-    {
-        [Dependency] private readonly IEntityManager _entManager = default!;
-
-        public string Command => "attachbodypart";
-        public string Description => "Attaches a body part to you or someone else.";
-        public string Help => $"{Command} <partEntityUid> / {Command} <entityUid> <partEntityUid>";
-
-        public void Execute(IConsoleShell shell, string argStr, string[] args)
-        {
-            var player = shell.Player;
-
-            EntityUid bodyId;
-            EntityUid? partUid;
-
-            switch (args.Length)
-            {
-                case 1:
-                    if (player == null)
-                    {
-                        shell.WriteLine($"You need to specify an entity to attach the part to if you aren't a player.\n{Help}");
-                        return;
-                    }
-
-                    if (player.AttachedEntity == null)
-                    {
-                        shell.WriteLine($"You need to specify an entity to attach the part to if you aren't attached to an entity.\n{Help}");
-                        return;
-                    }
-
-                    if (!NetEntity.TryParse(args[0], out var partNet) || !_entManager.TryGetEntity(partNet, out partUid))
-                    {
-                        shell.WriteLine($"{args[0]} is not a valid entity uid.");
-                        return;
-                    }
-
-                    bodyId = player.AttachedEntity.Value;
-
-                    break;
-                case 2:
-                    if (!NetEntity.TryParse(args[0], out var entityNet) || !_entManager.TryGetEntity(entityNet, out var entityUid))
-                    {
-                        shell.WriteLine($"{args[0]} is not a valid entity uid.");
-                        return;
-                    }
-
-                    if (!NetEntity.TryParse(args[1], out partNet) || !_entManager.TryGetEntity(partNet, out partUid))
-                    {
-                        shell.WriteLine($"{args[1]} is not a valid entity uid.");
-                        return;
-                    }
-
-                    if (!_entManager.EntityExists(entityUid))
-                    {
-                        shell.WriteLine($"{entityUid} is not a valid entity.");
-                        return;
-                    }
-
-                    bodyId = entityUid.Value;
-                    break;
-                default:
-                    shell.WriteLine(Help);
-                    return;
-            }
-
-            if (!_entManager.TryGetComponent(bodyId, out BodyComponent? body))
-            {
-                shell.WriteLine($"Entity {_entManager.GetComponent<MetaDataComponent>(bodyId).EntityName} with uid {bodyId} does not have a {nameof(BodyComponent)}.");
-                return;
-            }
-
-            if (!_entManager.EntityExists(partUid))
-            {
-                shell.WriteLine($"{partUid} is not a valid entity.");
-                return;
-            }
-
-            if (!_entManager.TryGetComponent(partUid, out BodyPartComponent? part))
-            {
-                shell.WriteLine($"Entity {_entManager.GetComponent<MetaDataComponent>(partUid.Value).EntityName} with uid {args[0]} does not have a {nameof(BodyPartComponent)}.");
-                return;
-            }
-
-            var bodySystem = _entManager.System<BodySystem>();
-            if (bodySystem.BodyHasChild(bodyId, partUid.Value, body, part))
-            {
-                shell.WriteLine($"Body part {_entManager.GetComponent<MetaDataComponent>(partUid.Value).EntityName} with uid {partUid} is already attached to entity {_entManager.GetComponent<MetaDataComponent>(bodyId).EntityName} with uid {bodyId}");
-                return;
-            }
-
-            var slotId = $"AttachBodyPartVerb-{partUid}";
-
-            if (body.RootContainer.ContainedEntity is null && !bodySystem.AttachPartToRoot(bodyId, partUid.Value, body, part))
-            {
-                shell.WriteError("Body container does not have a root entity to attach to the body part!");
-                return;
-            }
-
-            var (rootPartId, rootPart) = bodySystem.GetRootPartOrNull(bodyId, body)!.Value;
-            if (!bodySystem.TryCreatePartSlotAndAttach(rootPartId,
-                    slotId,
-                    partUid.Value,
-                    part.PartType,
-                    rootPart,
-                    part))
-            {
-                shell.WriteError($"Could not create slot {slotId} on entity {_entManager.ToPrettyString(bodyId)}");
-                return;
-            }
-            shell.WriteLine($"Attached part {_entManager.ToPrettyString(partUid.Value)} to {_entManager.ToPrettyString(bodyId)}");
-        }
-    }
-}
diff --git a/Content.Server/Body/Commands/DestroyMechanismCommand.cs b/Content.Server/Body/Commands/DestroyMechanismCommand.cs
deleted file mode 100644 (file)
index e3278fd..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-using Content.Server.Administration;
-using Content.Server.Body.Systems;
-using Content.Shared.Administration;
-using Content.Shared.Body.Components;
-using Robust.Shared.Console;
-
-namespace Content.Server.Body.Commands
-{
-    [AdminCommand(AdminFlags.Fun)]
-    internal sealed class DestroyMechanismCommand : LocalizedEntityCommands
-    {
-        [Dependency] private readonly IComponentFactory _compFactory = default!;
-        [Dependency] private readonly BodySystem _bodySystem = default!;
-
-        public override string Command => "destroymechanism";
-
-        public override void Execute(IConsoleShell shell, string argStr, string[] args)
-        {
-            var player = shell.Player;
-            if (player == null)
-            {
-                shell.WriteLine(Loc.GetString($"shell-only-players-can-run-this-command"));
-                return;
-            }
-
-            if (args.Length == 0)
-            {
-                shell.WriteLine(Help);
-                return;
-            }
-
-            if (player.AttachedEntity is not {} attached)
-            {
-                shell.WriteLine(Loc.GetString($"shell-must-be-attached-to-entity"));
-                return;
-            }
-
-            if (!EntityManager.TryGetComponent(attached, out BodyComponent? body))
-            {
-                shell.WriteLine(Loc.GetString($"shell-must-have-body"));
-                return;
-            }
-
-            var mechanismName = string.Join(" ", args).ToLowerInvariant();
-
-            foreach (var organ in _bodySystem.GetBodyOrgans(attached, body))
-            {
-                if (_compFactory.GetComponentName(organ.Component.GetType()).ToLowerInvariant() == mechanismName)
-                {
-                    EntityManager.QueueDeleteEntity(organ.Id);
-                    shell.WriteLine(Loc.GetString($"cmd-destroymechanism-success", ("name", mechanismName)));
-                    return;
-                }
-            }
-
-            shell.WriteLine(Loc.GetString($"cmd-destroymechanism-no-mechanism-found", ("name", mechanismName)));
-        }
-    }
-}
diff --git a/Content.Server/Body/Commands/RemoveHandCommand.cs b/Content.Server/Body/Commands/RemoveHandCommand.cs
deleted file mode 100644 (file)
index 4a2956a..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-using System.Linq;
-using Content.Server.Administration;
-using Content.Server.Body.Systems;
-using Content.Shared.Administration;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
-using Robust.Shared.Console;
-using Robust.Shared.Random;
-
-namespace Content.Server.Body.Commands
-{
-    [AdminCommand(AdminFlags.Fun)]
-    public sealed class RemoveHandCommand : IConsoleCommand
-    {
-        [Dependency] private readonly IEntityManager _entManager = default!;
-        [Dependency] private readonly IRobustRandom _random = default!;
-
-        public string Command => "removehand";
-        public string Description => "Removes a hand from your entity.";
-        public string Help => $"Usage: {Command}";
-
-        public void Execute(IConsoleShell shell, string argStr, string[] args)
-        {
-            var player = shell.Player;
-            if (player == null)
-            {
-                shell.WriteLine("Only a player can run this command.");
-                return;
-            }
-
-            if (player.AttachedEntity == null)
-            {
-                shell.WriteLine("You have no entity.");
-                return;
-            }
-
-            if (!_entManager.TryGetComponent(player.AttachedEntity, out BodyComponent? body))
-            {
-                var text = $"You have no body{(_random.Prob(0.2f) ? " and you must scream." : ".")}";
-
-                shell.WriteLine(text);
-                return;
-            }
-
-            var bodySystem = _entManager.System<BodySystem>();
-            var hand = bodySystem.GetBodyChildrenOfType(player.AttachedEntity.Value, BodyPartType.Hand, body).FirstOrDefault();
-
-            if (hand == default)
-            {
-                shell.WriteLine("You have no hands.");
-            }
-            else
-            {
-                _entManager.System<SharedTransformSystem>().AttachToGridOrMap(hand.Id);
-            }
-        }
-    }
-}
diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs
deleted file mode 100644 (file)
index 2627e97..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-using System.Numerics;
-using Content.Server.Ghost;
-using Content.Server.Humanoid;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Events;
-using Content.Shared.Body.Part;
-using Content.Shared.Body.Systems;
-using Content.Shared.Damage.Components;
-using Content.Shared.Humanoid;
-using Content.Shared.Mind;
-using Content.Shared.Mobs.Systems;
-using Content.Shared.Movement.Events;
-using Content.Shared.Movement.Systems;
-using Robust.Shared.Audio;
-using Robust.Shared.Timing;
-
-namespace Content.Server.Body.Systems;
-
-public sealed class BodySystem : SharedBodySystem
-{
-    [Dependency] private readonly GhostSystem _ghostSystem = default!;
-    [Dependency] private readonly IGameTiming _gameTiming = default!;
-    [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
-    [Dependency] private readonly MobStateSystem _mobState = default!;
-    [Dependency] private readonly SharedMindSystem _mindSystem = default!;
-
-    public override void Initialize()
-    {
-        base.Initialize();
-
-        SubscribeLocalEvent<BodyComponent, MoveInputEvent>(OnRelayMoveInput);
-        SubscribeLocalEvent<BodyComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
-    }
-
-    private void OnRelayMoveInput(Entity<BodyComponent> ent, ref MoveInputEvent args)
-    {
-        // If they haven't actually moved then ignore it.
-        if ((args.Entity.Comp.HeldMoveButtons &
-             (MoveButtons.Down | MoveButtons.Left | MoveButtons.Up | MoveButtons.Right)) == 0x0)
-        {
-            return;
-        }
-
-        if (_mobState.IsDead(ent) && _mindSystem.TryGetMind(ent, out var mindId, out var mind))
-        {
-            mind.TimeOfDeath ??= _gameTiming.RealTime;
-            _ghostSystem.OnGhostAttempt(mindId, canReturnGlobal: true, mind: mind);
-        }
-    }
-
-    private void OnApplyMetabolicMultiplier(
-        Entity<BodyComponent> ent,
-        ref ApplyMetabolicMultiplierEvent args)
-    {
-        foreach (var organ in GetBodyOrgans(ent, ent))
-        {
-            RaiseLocalEvent(organ.Id, ref args);
-        }
-    }
-
-    protected override void AddPart(
-        Entity<BodyComponent?> bodyEnt,
-        Entity<BodyPartComponent> partEnt,
-        string slotId)
-    {
-        // TODO: Predict this probably.
-        base.AddPart(bodyEnt, partEnt, slotId);
-
-        var layer = partEnt.Comp.ToHumanoidLayers();
-        if (layer != null)
-        {
-            var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
-            _humanoidSystem.SetLayersVisibility(bodyEnt.Owner, layers, visible: true);
-        }
-    }
-
-    protected override void RemovePart(
-        Entity<BodyComponent?> bodyEnt,
-        Entity<BodyPartComponent> partEnt,
-        string slotId)
-    {
-        base.RemovePart(bodyEnt, partEnt, slotId);
-
-        if (!TryComp<HumanoidAppearanceComponent>(bodyEnt, out var humanoid))
-            return;
-
-        var layer = partEnt.Comp.ToHumanoidLayers();
-
-        if (layer is null)
-            return;
-
-        var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
-        _humanoidSystem.SetLayersVisibility((bodyEnt, humanoid), layers, visible: false);
-    }
-}
index 8e329bc420825f7b1c24a438b8b4376af0d5b1da..3e01b05feb3e8f1de228c751a8224bbb2bcbc2cc 100644 (file)
@@ -1,7 +1,7 @@
 using System.Linq;
 using Content.Server.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.Body.Events;
-using Content.Shared.Body.Organ;
 using Content.Shared.Body.Prototypes;
 using Content.Shared.Body.Systems;
 using Content.Shared.Chemistry.Components;
@@ -47,7 +47,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
 
         SubscribeLocalEvent<MetabolizerComponent, ComponentInit>(OnMetabolizerInit);
         SubscribeLocalEvent<MetabolizerComponent, MapInitEvent>(OnMapInit);
-        SubscribeLocalEvent<MetabolizerComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
+        SubscribeLocalEvent<MetabolizerComponent, BodyRelayedEvent<ApplyMetabolicMultiplierEvent>>(OnApplyMetabolicMultiplier);
     }
 
     private void OnMapInit(Entity<MetabolizerComponent> ent, ref MapInitEvent args)
@@ -67,9 +67,9 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
         }
     }
 
-    private void OnApplyMetabolicMultiplier(Entity<MetabolizerComponent> ent, ref ApplyMetabolicMultiplierEvent args)
+    private void OnApplyMetabolicMultiplier(Entity<MetabolizerComponent> ent, ref BodyRelayedEvent<ApplyMetabolicMultiplierEvent> args)
     {
-        ent.Comp.UpdateIntervalMultiplier = args.Multiplier;
+        ent.Comp.UpdateIntervalMultiplier = args.Args.Multiplier;
     }
 
     public override void Update(float frameTime)
index 208208025be61a9c9fa109e56308480daf74e7fe..4a761c518d0aeeb8f9fd336f514f8072db09ca7c 100644 (file)
@@ -5,6 +5,7 @@ using Content.Server.Chat.Systems;
 using Content.Shared.Body.Systems;
 using Content.Shared.Alert;
 using Content.Shared.Atmos;
+using Content.Shared.Body;
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Events;
 using Content.Shared.Body.Prototypes;
@@ -34,7 +35,7 @@ public sealed class RespiratorSystem : EntitySystem
     [Dependency] private readonly IPrototypeManager _protoMan = default!;
     [Dependency] private readonly AlertsSystem _alertsSystem = default!;
     [Dependency] private readonly AtmosphereSystem _atmosSys = default!;
-    [Dependency] private readonly BodySystem _bodySystem = default!;
+    [Dependency] private readonly BodySystem _body = default!;
     [Dependency] private readonly ChatSystem _chat = default!;
     [Dependency] private readonly DamageableSystem _damageableSys = default!;
     [Dependency] private readonly LungSystem _lungSystem = default!;
@@ -54,11 +55,17 @@ public sealed class RespiratorSystem : EntitySystem
         SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
 
         // BodyComp stuff
-        SubscribeLocalEvent<BodyComponent, InhaledGasEvent>(OnGasInhaled);
-        SubscribeLocalEvent<BodyComponent, ExhaledGasEvent>(OnGasExhaled);
-        SubscribeLocalEvent<BodyComponent, CanMetabolizeGasEvent>(CanBodyMetabolizeGas);
-        SubscribeLocalEvent<BodyComponent, SuffocationEvent>(OnSuffocation);
-        SubscribeLocalEvent<BodyComponent, StopSuffocatingEvent>(OnStopSuffocating);
+        SubscribeLocalEvent<BodyComponent, InhaledGasEvent>(_body.RelayEvent);
+        SubscribeLocalEvent<BodyComponent, ExhaledGasEvent>(_body.RelayEvent);
+        SubscribeLocalEvent<BodyComponent, CanMetabolizeGasEvent>(_body.RelayEvent);
+        SubscribeLocalEvent<BodyComponent, SuffocationEvent>(_body.RelayEvent);
+        SubscribeLocalEvent<BodyComponent, StopSuffocatingEvent>(_body.RelayEvent);
+
+        SubscribeLocalEvent<LungComponent, BodyRelayedEvent<InhaledGasEvent>>(OnGasInhaled);
+        SubscribeLocalEvent<LungComponent, BodyRelayedEvent<ExhaledGasEvent>>(OnGasExhaled);
+        SubscribeLocalEvent<LungComponent, BodyRelayedEvent<CanMetabolizeGasEvent>>(CanBodyMetabolizeGas);
+        SubscribeLocalEvent<LungComponent, BodyRelayedEvent<SuffocationEvent>>(OnSuffocation);
+        SubscribeLocalEvent<LungComponent, BodyRelayedEvent<StopSuffocatingEvent>>(OnStopSuffocating);
     }
 
     private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
@@ -236,72 +243,22 @@ public sealed class RespiratorSystem : EntitySystem
     /// <summary>
     /// Tries to safely metabolize the current solutions in a body's lungs.
     /// </summary>
-    private void CanBodyMetabolizeGas(Entity<BodyComponent> ent, ref CanMetabolizeGasEvent args)
+    private void CanBodyMetabolizeGas(Entity<LungComponent> ent, ref BodyRelayedEvent<CanMetabolizeGasEvent> args)
     {
-        if (args.Handled)
+        if (args.Args.Handled)
             return;
 
-        var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
-        if (organs.Count == 0)
-            return;
-
-        var solution = _lungSystem.GasToReagent(args.Gas);
+        var solution = _lungSystem.GasToReagent(args.Args.Gas);
 
         var saturation = 0f;
-        foreach (var organ in organs)
-        {
-            saturation += GetSaturation(solution, organ.Owner, out var toxic);
-            if (!toxic)
-                continue;
-
-            args.Handled = true;
-            args.Toxic = true;
-            return;
-        }
-
-        args.Handled = true;
-        args.Saturation = saturation;
-    }
-
-    public bool TryInhaleGasToBody(Entity<BodyComponent?> entity, GasMixture gas)
-    {
-        if (!Resolve(entity, ref entity.Comp))
-            return false;
-
-        var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((entity, entity.Comp));
-        if (organs.Count == 0)
-            return false;
-
-        var lungRatio = 1.0f / organs.Count;
-        var splitGas = organs.Count == 1 ? gas : gas.RemoveRatio(lungRatio);
-        foreach (var (organUid, lung, _) in organs)
-        {
-            // Merge doesn't remove gas from the giver.
-            _atmosSys.Merge(lung.Air, splitGas);
-            _lungSystem.GasToReagent(organUid, lung);
-        }
-
-        return true;
-    }
-
-    public void RemoveGasFromBody(Entity<BodyComponent> ent, GasMixture gas)
-    {
-        var outGas = new GasMixture(gas.Volume);
-
-        var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, ent.Comp));
-        if (organs.Count == 0)
-            return;
+        saturation += GetSaturation(solution, ent.Owner, out var toxic);
 
-        foreach (var (organUid, lung, _) in organs)
+        args.Args = args.Args with
         {
-            _atmosSys.Merge(outGas, lung.Air);
-            lung.Air.Clear();
-
-            if (_solutionContainerSystem.ResolveSolution(organUid, lung.SolutionName, ref lung.Solution))
-                _solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
-        }
-
-        _atmosSys.Merge(gas, outGas);
+            Saturation = saturation,
+            Toxic = toxic,
+            Handled = true
+        };
     }
 
     /// <summary>
@@ -387,24 +344,14 @@ public sealed class RespiratorSystem : EntitySystem
         RaiseLocalEvent(ent, ref ev);
     }
 
-    private void OnSuffocation(Entity<BodyComponent> ent, ref SuffocationEvent args)
+    private void OnSuffocation(Entity<LungComponent> ent, ref BodyRelayedEvent<SuffocationEvent> args)
     {
-        // TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
-        var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
-        foreach (var entity in organs)
-        {
-            _alertsSystem.ShowAlert(ent.Owner, entity.Comp1.Alert);
-        }
+        _alertsSystem.ShowAlert(args.Body.Owner, ent.Comp.Alert);
     }
 
-    private void OnStopSuffocating(Entity<BodyComponent> ent, ref StopSuffocatingEvent args)
+    private void OnStopSuffocating(Entity<LungComponent> ent, ref BodyRelayedEvent<StopSuffocatingEvent> args)
     {
-        // TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
-        var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
-        foreach (var entity in organs)
-        {
-            _alertsSystem.ClearAlert(ent.Owner, entity.Comp1.Alert);
-        }
+        _alertsSystem.ClearAlert(args.Body.Owner, ent.Comp.Alert);
     }
 
     public void UpdateSaturation(EntityUid uid, float amount, RespiratorComponent? respirator = null)
@@ -422,24 +369,33 @@ public sealed class RespiratorSystem : EntitySystem
         ent.Comp.UpdateIntervalMultiplier = args.Multiplier;
     }
 
-    private void OnGasInhaled(Entity<BodyComponent> entity, ref InhaledGasEvent args)
+    private void OnGasInhaled(Entity<LungComponent> ent, ref BodyRelayedEvent<InhaledGasEvent> args)
     {
-        if (args.Handled)
+        if (args.Args.Handled)
             return;
 
-        args.Handled = true;
+        _atmosSys.Merge(ent.Comp.Air, args.Args.Gas);
+        _lungSystem.GasToReagent(ent, ent);
 
-        args.Succeeded = TryInhaleGasToBody((entity, entity.Comp), args.Gas);
+        args.Args = args.Args with
+        {
+            Handled = true,
+            Succeeded = true
+        };
     }
 
-    private void OnGasExhaled(Entity<BodyComponent> entity, ref ExhaledGasEvent args)
+    private void OnGasExhaled(Entity<LungComponent> ent, ref BodyRelayedEvent<ExhaledGasEvent> args)
     {
-        if (args.Handled)
-            return;
+        _atmosSys.Merge(args.Args.Gas, ent.Comp.Air);
+        ent.Comp.Air.Clear();
 
-        args.Handled = true;
+        if (_solutionContainerSystem.ResolveSolution(ent.Owner, ent.Comp.SolutionName, ref ent.Comp.Solution))
+            _solutionContainerSystem.RemoveAllSolution(ent.Comp.Solution.Value);
 
-        RemoveGasFromBody(entity, args.Gas);
+        args.Args = args.Args with
+        {
+            Handled = true
+        };
     }
 }
 
index ee9f53d0871ef7e384eadc5dd0b820788a17cd74..ec4bb51487442808fe355ad66522306f2005d787 100644 (file)
@@ -6,12 +6,6 @@
 [RegisterComponent]
 public sealed partial class MobPriceComponent : Component
 {
-    /// <summary>
-    /// How much of a penalty per part there should be. This is a multiplier for a multiplier, the penalty for each body part is calculated from the total number of slots, and then multiplied by this.
-    /// </summary>
-    [DataField("missingBodyPartPenalty")]
-    public double MissingBodyPartPenalty = 1.0f;
-
     /// <summary>
     /// The base price this mob should fetch.
     /// </summary>
index 24ee4ffaf2f9eae6e1307624c8862f298f192ba9..0101b913d6a9fa9c445625ad342c6c0de64c39e3 100644 (file)
@@ -1,9 +1,7 @@
 using Content.Server.Administration;
-using Content.Server.Body.Systems;
 using Content.Server.Cargo.Components;
 using Content.Shared.Chemistry.EntitySystems;
 using Content.Shared.Administration;
-using Content.Shared.Body.Components;
 using Content.Shared.Cargo;
 using Content.Shared.Chemistry.Components.SolutionManager;
 using Content.Shared.Chemistry.Reagent;
@@ -16,7 +14,6 @@ using Robust.Shared.Containers;
 using Robust.Shared.Map.Components;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Utility;
-using System.Linq;
 using Content.Shared.Research.Prototypes;
 
 namespace Content.Server.Cargo.Systems;
@@ -28,7 +25,6 @@ public sealed class PricingSystem : EntitySystem
 {
     [Dependency] private readonly IConsoleHost _consoleHost = default!;
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
-    [Dependency] private readonly BodySystem _bodySystem = default!;
     [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
     [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
 
@@ -96,18 +92,7 @@ public sealed class PricingSystem : EntitySystem
             return;
         }
 
-        var partPenalty = 0.0;
-        if (TryComp<BodyComponent>(uid, out var body))
-        {
-            var partList = _bodySystem.GetBodyChildren(uid, body).ToList();
-            var totalPartsPresent = partList.Sum(_ => 1);
-            var totalParts = partList.Count;
-
-            var partRatio = totalPartsPresent / (double) totalParts;
-            partPenalty = component.Price * (1 - partRatio) * component.MissingBodyPartPenalty;
-        }
-
-        args.Price += (component.Price - partPenalty) * (_mobStateSystem.IsAlive(uid, state) ? 1.0 : component.DeathPenalty);
+        args.Price += component.Price * (_mobStateSystem.IsAlive(uid, state) ? 1.0 : component.DeathPenalty);
     }
 
     private double GetSolutionPrice(Entity<SolutionContainerManagerComponent> entity)
index 73365c4f62e4e47afb51778f533c5b2307ba2aac..993545b9dca060ac14a9bc0e496019c9a9039f23 100644 (file)
@@ -1,6 +1,6 @@
 using Content.Server.Atmos.EntitySystems;
 using Content.Server.Disposal.Tube;
-using Content.Shared.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.Damage.Systems;
 using Content.Shared.Disposal.Components;
 using Content.Shared.Item;
index 7688d14ada40b8538714fbf313209e3e0f49dcfe..99225f451ee63a6a3551ad4bdf8a31db6062976c 100644 (file)
@@ -2,7 +2,6 @@ using System.Numerics;
 using Content.Server.Stack;
 using Content.Server.Stunnable;
 using Content.Shared.ActionBlocker;
-using Content.Shared.Body.Part;
 using Content.Shared.CombatMode;
 using Content.Shared.Damage.Systems;
 using Content.Shared.Explosion;
@@ -49,9 +48,6 @@ namespace Content.Server.Hands.Systems
 
             SubscribeLocalEvent<HandsComponent, DisarmedEvent>(OnDisarmed, before: new[] {typeof(StunSystem), typeof(SharedStaminaSystem)});
 
-            SubscribeLocalEvent<HandsComponent, BodyPartAddedEvent>(HandleBodyPartAdded);
-            SubscribeLocalEvent<HandsComponent, BodyPartRemovedEvent>(HandleBodyPartRemoved);
-
             SubscribeLocalEvent<HandsComponent, ComponentGetState>(GetComponentState);
 
             SubscribeLocalEvent<HandsComponent, BeforeExplodeEvent>(OnExploded);
@@ -107,32 +103,6 @@ namespace Content.Server.Hands.Systems
             args.Handled = true; // no shove/stun.
         }
 
-        private void HandleBodyPartAdded(Entity<HandsComponent> ent, ref BodyPartAddedEvent args)
-        {
-            if (args.Part.Comp.PartType != BodyPartType.Hand)
-                return;
-
-            // If this annoys you, which it should.
-            // Ping Smugleaf.
-            var location = args.Part.Comp.Symmetry switch
-            {
-                BodyPartSymmetry.None => HandLocation.Middle,
-                BodyPartSymmetry.Left => HandLocation.Left,
-                BodyPartSymmetry.Right => HandLocation.Right,
-                _ => throw new ArgumentOutOfRangeException(nameof(args.Part.Comp.Symmetry))
-            };
-
-            AddHand(ent.AsNullable(), args.Slot, location);
-        }
-
-        private void HandleBodyPartRemoved(EntityUid uid, HandsComponent component, ref BodyPartRemovedEvent args)
-        {
-            if (args.Part.Comp.PartType != BodyPartType.Hand)
-                return;
-
-            RemoveHand(uid, args.Slot);
-        }
-
         #region interactions
 
         private bool HandleThrowItem(ICommonSession? playerSession, EntityCoordinates coordinates, EntityUid entity)
index a06d521a3bef2ea8701dbbc1b5e2cfe2e07346c5..860dac1a84d579a7e882d4d2394757ec2dd2d817 100644 (file)
@@ -1,8 +1,7 @@
-using Content.Server.Body.Systems;
 using Content.Server.Destructible;
 using Content.Server.Polymorph.Components;
 using Content.Server.Popups;
-using Content.Shared.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.Damage.Systems;
 using Content.Shared.Examine;
 using Content.Shared.Gibbing;
@@ -112,7 +111,7 @@ public sealed class ImmovableRodSystem : EntitySystem
         }
 
         // gib or damage em
-        if (TryComp<BodyComponent>(ent, out var body))
+        if (HasComp<BodyComponent>(ent))
         {
             component.MobCount++;
             _popup.PopupEntity(Loc.GetString("immovable-rod-penetrated-mob", ("rod", uid), ("mob", ent)), uid, PopupType.LargeCaution);
index 1c6ed26d48817417b1bdd4ef585ff1ac5d1c9f42..6f3d39320903237695287f4e831b5e9ec1662a56 100644 (file)
@@ -1,5 +1,4 @@
 using Content.Server.Administration.Logs;
-using Content.Server.Body.Systems;
 using Content.Server.Construction;
 using Content.Server.Explosion.EntitySystems;
 using Content.Server.DeviceLinking.Systems;
@@ -8,8 +7,6 @@ using Content.Server.Kitchen.Components;
 using Content.Server.Power.Components;
 using Content.Server.Power.EntitySystems;
 using Content.Server.Temperature.Systems;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
 using Content.Shared.Chemistry.Components.SolutionManager;
 using Content.Shared.Chemistry.EntitySystems;
 using Content.Shared.Chemistry.Reaction;
@@ -46,7 +43,6 @@ namespace Content.Server.Kitchen.EntitySystems
 {
     public sealed class MicrowaveSystem : EntitySystem
     {
-        [Dependency] private readonly BodySystem _bodySystem = default!;
         [Dependency] private readonly DeviceLinkSystem _deviceLink = default!;
         [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
         [Dependency] private readonly PowerReceiverSystem _power = default!;
@@ -305,26 +301,9 @@ namespace Content.Server.Kitchen.EntitySystems
             _suicide.ApplyLethalDamage((args.Victim, damageableComponent), "Heat");
 
             var victim = args.Victim;
-            var headCount = 0;
 
-            if (TryComp<BodyComponent>(victim, out var body))
-            {
-                var headSlots = _bodySystem.GetBodyChildrenOfType(victim, BodyPartType.Head, body);
-
-                foreach (var part in headSlots)
-                {
-                    _container.Insert(part.Id, ent.Comp.Storage);
-                    headCount++;
-                }
-            }
-
-            var othersMessage = headCount > 1
-                ? Loc.GetString("microwave-component-suicide-multi-head-others-message", ("victim", victim))
-                : Loc.GetString("microwave-component-suicide-others-message", ("victim", victim));
-
-            var selfMessage = headCount > 1
-                ? Loc.GetString("microwave-component-suicide-multi-head-message")
-                : Loc.GetString("microwave-component-suicide-message");
+            var othersMessage = Loc.GetString("microwave-component-suicide-others-message", ("victim", victim));
+            var selfMessage = Loc.GetString("microwave-component-suicide-message");
 
             _popupSystem.PopupEntity(othersMessage, victim, Filter.PvsExcept(victim), true);
             _popupSystem.PopupEntity(selfMessage, victim, victim);
index b24690e204a96188fb801b06f6c9f256ddba3dff..82bbfd9c6d9d00075b0d6c55b877b3e308428672 100644 (file)
@@ -10,7 +10,7 @@ using Content.Server.Cloning.Components;
 using Content.Server.DeviceLinking.Systems;
 using Content.Shared.DeviceLinking.Events;
 using Content.Server.Power.EntitySystems;
-using Content.Shared.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.Climbing.Systems;
 using Content.Shared.Mobs.Components;
 using Content.Shared.Mobs.Systems;
index 766c3e18dcf9d4ed578bd81991a14767f57d6eb0..0705944c35d8a32e80106f509048113fdb361bb4 100644 (file)
@@ -4,11 +4,9 @@ using System.Numerics;
 using Content.Server.Shuttles.Components;
 using Content.Server.Shuttles.Events;
 using Content.Server.Station.Events;
-using Content.Shared.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.CCVar;
 using Content.Shared.Database;
-using Content.Shared.Ghost;
-using Content.Shared.Maps;
 using Content.Shared.Parallax;
 using Content.Shared.Shuttles.Components;
 using Content.Shared.Shuttles.Systems;
index f6477a7c8bb9591420c0b508a7cb2e0c3e03b572..0d56e3da2568ad5a2f46b9908c14dfad5901b03f 100644 (file)
@@ -1,8 +1,8 @@
 using Content.Server.Mind;
+using Content.Server.Zombies;
+using Content.Shared.Body;
 using Content.Shared.Species.Components;
-using Content.Shared.Body.Events;
 using Content.Shared.Zombies;
-using Content.Server.Zombies;
 using Robust.Shared.Prototypes;
 
 namespace Content.Server.Species.Systems;
@@ -17,12 +17,12 @@ public sealed partial class NymphSystem : EntitySystem
     {
         base.Initialize();
 
-        SubscribeLocalEvent<NymphComponent, OrganRemovedFromBodyEvent>(OnRemovedFromPart);
+        SubscribeLocalEvent<NymphComponent, OrganGotRemovedEvent>(OnRemovedFromPart);
     }
 
-    private void OnRemovedFromPart(EntityUid uid, NymphComponent comp, ref OrganRemovedFromBodyEvent args)
+    private void OnRemovedFromPart(EntityUid uid, NymphComponent comp, ref OrganGotRemovedEvent args)
     {
-        if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.OldBody))
+        if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.Target))
             return;
 
         if (!_protoManager.TryIndex<EntityPrototype>(comp.EntityPrototype, out var entityProto))
@@ -32,11 +32,11 @@ public sealed partial class NymphSystem : EntitySystem
         var coords = Transform(uid).Coordinates;
         var nymph = SpawnAtPosition(entityProto.ID, coords);
 
-        if (HasComp<ZombieComponent>(args.OldBody)) // Zombify the new nymph if old one is a zombie
+        if (HasComp<ZombieComponent>(args.Target)) // Zombify the new nymph if old one is a zombie
             _zombie.ZombifyEntity(nymph);
 
         // Move the mind if there is one and it's supposed to be transferred
-        if (comp.TransferMind == true && _mindSystem.TryGetMind(args.OldBody, out var mindId, out var mind))
+        if (comp.TransferMind == true && _mindSystem.TryGetMind(args.Target, out var mindId, out var mind))
             _mindSystem.TransferTo(mindId, nymph, mind: mind);
 
         // Delete the old organ
index 6afe886303349635be48a7f046f0162b96e07aa7..7b7cc2a8aa77b84cd635fee77bec8969606e70dd 100644 (file)
@@ -1,5 +1,4 @@
 using System.Linq;
-using Content.Shared.Body.Part;
 using Content.Shared.Destructible;
 using Content.Shared.Hands;
 using Content.Shared.Hands.Components;
index 5db6ba78e94a6fe9c1861a2b23cdc8f3d318af24..7087499c93aebcc62764de0e34bccb912d1e8b9e 100644 (file)
@@ -1,6 +1,4 @@
-using Content.Server.Body.Systems;
 using Content.Server.Stack;
-using Content.Shared.Body.Components;
 using Content.Shared.Gibbing;
 using Content.Shared.Storage.Components;
 using Content.Shared.Whitelist;
@@ -42,9 +40,6 @@ public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem
                 }
             }
 
-            if (!TryComp<BodyComponent>(contained, out var body))
-                Del(contained);
-
             var gibs = _gibbing.Gib(contained);
             foreach (var gib in gibs)
             {
diff --git a/Content.Shared/Body/BodyComponent.cs b/Content.Shared/Body/BodyComponent.cs
new file mode 100644 (file)
index 0000000..0b32657
--- /dev/null
@@ -0,0 +1,41 @@
+using Robust.Shared.Containers;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Body;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(BodySystem))]
+public sealed partial class BodyComponent : Component
+{
+    public const string ContainerID = "body_organs";
+
+    /// <summary>
+    /// The actual container with entities with <see cref="OrganComponent" /> in it
+    /// </summary>
+    [ViewVariables]
+    public Container? Organs;
+}
+
+/// <summary>
+/// Raised on organ entity, when it is inserted into a body
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganGotInsertedEvent(EntityUid Target);
+
+/// <summary>
+/// Raised on organ entity, when it is removed from a body
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganGotRemovedEvent(EntityUid Target);
+
+/// <summary>
+/// Raised on body entity, when an organ is inserted into it
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganInsertedIntoEvent(EntityUid Organ);
+
+/// <summary>
+/// Raised on body entity, when an organ is removed from it
+/// </summary>
+[ByRefEvent]
+public readonly record struct OrganRemovedFromEvent(EntityUid Organ);
diff --git a/Content.Shared/Body/BodySystem.Compatibility.cs b/Content.Shared/Body/BodySystem.Compatibility.cs
new file mode 100644 (file)
index 0000000..c6dd2bc
--- /dev/null
@@ -0,0 +1,20 @@
+namespace Content.Shared.Body;
+
+public sealed partial class BodySystem
+{
+    [Obsolete("Use an event-relay based approach instead")]
+    public bool TryGetOrgansWithComponent<TComp>(Entity<BodyComponent?> ent, out List<Entity<TComp>> organs) where TComp : Component
+    {
+        organs = new();
+        if (!_bodyQuery.Resolve(ent, ref ent.Comp))
+            return false;
+
+        foreach (var organ in ent.Comp.Organs?.ContainedEntities ?? [])
+        {
+            if (TryComp<TComp>(organ, out var comp))
+                organs.Add((organ, comp));
+        }
+
+        return organs.Count != 0;
+    }
+}
diff --git a/Content.Shared/Body/BodySystem.Relay.cs b/Content.Shared/Body/BodySystem.Relay.cs
new file mode 100644 (file)
index 0000000..c6a025a
--- /dev/null
@@ -0,0 +1,50 @@
+using Content.Shared.Body.Events;
+using Content.Shared.Gibbing;
+using Content.Shared.Medical;
+
+namespace Content.Shared.Body;
+
+public sealed partial class BodySystem
+{
+    private void InitializeRelay()
+    {
+        SubscribeLocalEvent<BodyComponent, ApplyMetabolicMultiplierEvent>(RefRelayBodyEvent);
+        SubscribeLocalEvent<BodyComponent, TryVomitEvent>(RefRelayBodyEvent);
+        SubscribeLocalEvent<BodyComponent, BeingGibbedEvent>(RefRelayBodyEvent);
+    }
+
+    private void RefRelayBodyEvent<T>(EntityUid uid, BodyComponent component, ref T args) where T : struct
+    {
+        RelayEvent((uid, component), ref args);
+    }
+
+    private void RelayBodyEvent<T>(EntityUid uid, BodyComponent component, T args) where T : class
+    {
+        RelayEvent((uid, component), args);
+    }
+
+    public void RelayEvent<T>(Entity<BodyComponent> ent, ref T args) where T : struct
+    {
+        var ev = new BodyRelayedEvent<T>(ent, args);
+        foreach (var organ in ent.Comp.Organs?.ContainedEntities ?? [])
+        {
+            RaiseLocalEvent(organ, ref ev);
+        }
+        args = ev.Args;
+    }
+
+    public void RelayEvent<T>(Entity<BodyComponent> ent, T args) where T : class
+    {
+        var ev = new BodyRelayedEvent<T>(ent, args);
+        foreach (var organ in ent.Comp.Organs?.ContainedEntities ?? [])
+        {
+            RaiseLocalEvent(organ, ref ev);
+        }
+    }
+}
+
+/// <summary>
+/// Event wrapper for relayed events.
+/// </summary>
+[ByRefEvent]
+public record struct BodyRelayedEvent<TEvent>(Entity<BodyComponent> Body, TEvent Args);
diff --git a/Content.Shared/Body/BodySystem.cs b/Content.Shared/Body/BodySystem.cs
new file mode 100644 (file)
index 0000000..c53ab22
--- /dev/null
@@ -0,0 +1,89 @@
+using Content.Shared.DragDrop;
+using Robust.Shared.Containers;
+
+namespace Content.Shared.Body;
+
+public sealed partial class BodySystem : EntitySystem
+{
+    [Dependency] private readonly SharedContainerSystem _container = default!;
+
+    private EntityQuery<BodyComponent> _bodyQuery;
+    private EntityQuery<OrganComponent> _organQuery;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<BodyComponent, ComponentInit>(OnBodyInit);
+        SubscribeLocalEvent<BodyComponent, ComponentShutdown>(OnBodyShutdown);
+
+        SubscribeLocalEvent<BodyComponent, CanDragEvent>(OnCanDrag);
+
+        SubscribeLocalEvent<BodyComponent, EntInsertedIntoContainerMessage>(OnBodyEntInserted);
+        SubscribeLocalEvent<BodyComponent, EntRemovedFromContainerMessage>(OnBodyEntRemoved);
+
+        _bodyQuery = GetEntityQuery<BodyComponent>();
+        _organQuery = GetEntityQuery<OrganComponent>();
+
+        InitializeRelay();
+    }
+
+    private void OnBodyInit(Entity<BodyComponent> ent, ref ComponentInit args)
+    {
+        ent.Comp.Organs =
+            _container.EnsureContainer<Container>(ent, BodyComponent.ContainerID);
+    }
+
+    private void OnBodyShutdown(Entity<BodyComponent> ent, ref ComponentShutdown args)
+    {
+        if (ent.Comp.Organs is { } organs)
+            _container.ShutdownContainer(organs);
+    }
+
+    private void OnBodyEntInserted(Entity<BodyComponent> ent, ref EntInsertedIntoContainerMessage args)
+    {
+        if (args.Container.ID != BodyComponent.ContainerID)
+            return;
+
+        if (!_organQuery.TryComp(args.Entity, out var organ))
+            return;
+
+        var body = new OrganInsertedIntoEvent(args.Entity);
+        RaiseLocalEvent(ent, ref body);
+
+        var ev = new OrganGotInsertedEvent(ent);
+        RaiseLocalEvent(args.Entity, ref ev);
+
+        if (organ.Body != ent)
+        {
+            organ.Body = ent;
+            Dirty(args.Entity, organ);
+        }
+    }
+
+    private void OnBodyEntRemoved(Entity<BodyComponent> ent, ref EntRemovedFromContainerMessage args)
+    {
+        if (args.Container.ID != BodyComponent.ContainerID)
+            return;
+
+        if (!_organQuery.TryComp(args.Entity, out var organ))
+            return;
+
+        var body = new OrganRemovedFromEvent(args.Entity);
+        RaiseLocalEvent(ent, ref body);
+
+        var ev = new OrganGotRemovedEvent(ent);
+        RaiseLocalEvent(args.Entity, ref ev);
+
+        if (organ.Body == null)
+            return;
+
+        organ.Body = null;
+        Dirty(args.Entity, organ);
+    }
+
+    private void OnCanDrag(Entity<BodyComponent> ent, ref CanDragEvent args)
+    {
+        args.Handled = true;
+    }
+}
diff --git a/Content.Shared/Body/Components/BodyComponent.cs b/Content.Shared/Body/Components/BodyComponent.cs
deleted file mode 100644 (file)
index 481e221..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-using Content.Shared.Body.Prototypes;
-using Content.Shared.Body.Systems;
-using Robust.Shared.Audio;
-using Robust.Shared.Containers;
-using Robust.Shared.GameStates;
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Body.Components;
-
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-[Access(typeof(SharedBodySystem))]
-public sealed partial class BodyComponent : Component
-{
-    /// <summary>
-    /// Relevant template to spawn for this body.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public ProtoId<BodyPrototype>? Prototype;
-
-    /// <summary>
-    /// Container that holds the root body part.
-    /// </summary>
-    /// <remarks>
-    /// Typically is the torso.
-    /// </remarks>
-    [ViewVariables] public ContainerSlot RootContainer = default!;
-
-    [ViewVariables]
-    public string RootPartSlot => RootContainer.ID;
-
-    [DataField, AutoNetworkedField]
-    public SoundSpecifier GibSound = new SoundCollectionSpecifier("gib");
-
-    /// <summary>
-    /// The amount of legs required to move at full speed.
-    /// If 0, then legs do not impact speed.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public int RequiredLegs;
-
-    [ViewVariables]
-    [DataField, AutoNetworkedField]
-    public HashSet<EntityUid> LegEntities = new();
-}
diff --git a/Content.Shared/Body/Events/MechanismBodyEvents.cs b/Content.Shared/Body/Events/MechanismBodyEvents.cs
deleted file mode 100644 (file)
index 968b172..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace Content.Shared.Body.Events;
-
-// All of these events are raised on a mechanism entity when added/removed to a body in different
-// ways.
-
-/// <summary>
-/// Raised on a mechanism when it is added to a body part.
-/// </summary>
-[ByRefEvent]
-public readonly record struct OrganAddedEvent(EntityUid Part);
-
-/// <summary>
-/// Raised on a mechanism when it is added to a body part within a body.
-/// </summary>
-[ByRefEvent]
-public readonly record struct OrganAddedToBodyEvent(EntityUid Body, EntityUid Part);
-
-/// <summary>
-/// Raised on a mechanism when it is removed from a body part.
-/// </summary>
-[ByRefEvent]
-public readonly record struct OrganRemovedEvent(EntityUid OldPart);
-
-/// <summary>
-/// Raised on a mechanism when it is removed from a body part within a body.
-/// </summary>
-[ByRefEvent]
-public readonly record struct OrganRemovedFromBodyEvent(EntityUid OldBody, EntityUid OldPart);
diff --git a/Content.Shared/Body/GibbableOrganComponent.cs b/Content.Shared/Body/GibbableOrganComponent.cs
new file mode 100644 (file)
index 0000000..fd81304
--- /dev/null
@@ -0,0 +1,7 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Body;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(GibbableOrganSystem))]
+public sealed partial class GibbableOrganComponent : Component;
diff --git a/Content.Shared/Body/GibbableOrganSystem.cs b/Content.Shared/Body/GibbableOrganSystem.cs
new file mode 100644 (file)
index 0000000..56b0af1
--- /dev/null
@@ -0,0 +1,18 @@
+using Content.Shared.Gibbing;
+
+namespace Content.Shared.Body;
+
+public sealed class GibbableOrganSystem : EntitySystem
+{
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<GibbableOrganComponent, BodyRelayedEvent<BeingGibbedEvent>>(OnBeingGibbed);
+    }
+
+    private void OnBeingGibbed(Entity<GibbableOrganComponent> ent, ref BodyRelayedEvent<BeingGibbedEvent> args)
+    {
+        args.Args.Giblets.Add(ent);
+    }
+}
diff --git a/Content.Shared/Body/HandOrganComponent.cs b/Content.Shared/Body/HandOrganComponent.cs
new file mode 100644 (file)
index 0000000..78cdea4
--- /dev/null
@@ -0,0 +1,15 @@
+using Content.Shared.Hands.Components;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Body;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(HandOrganSystem))]
+public sealed partial class HandOrganComponent : Component
+{
+    [DataField(required: true)]
+    public string HandID;
+
+    [DataField(required: true)]
+    public Hand Data;
+}
diff --git a/Content.Shared/Body/HandOrganSystem.cs b/Content.Shared/Body/HandOrganSystem.cs
new file mode 100644 (file)
index 0000000..0c3a0b0
--- /dev/null
@@ -0,0 +1,30 @@
+using Content.Shared.Hands.EntitySystems;
+
+namespace Content.Shared.Body;
+
+public sealed class HandOrganSystem : EntitySystem
+{
+    [Dependency] private readonly SharedHandsSystem _hands = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<HandOrganComponent, OrganGotInsertedEvent>(OnGotInserted);
+        SubscribeLocalEvent<HandOrganComponent, OrganGotRemovedEvent>(OnGotRemoved);
+    }
+
+    private void OnGotInserted(Entity<HandOrganComponent> ent, ref OrganGotInsertedEvent args)
+    {
+        _hands.AddHand(args.Target, ent.Comp.HandID, ent.Comp.Data);
+    }
+
+    private void OnGotRemoved(Entity<HandOrganComponent> ent, ref OrganGotRemovedEvent args)
+    {
+        // prevent a recursive double-delete bug
+        if (LifeStage(args.Target) >= EntityLifeStage.Terminating)
+            return;
+
+        _hands.RemoveHand(args.Target, ent.Comp.HandID);
+    }
+}
diff --git a/Content.Shared/Body/Organ/OrganComponent.cs b/Content.Shared/Body/Organ/OrganComponent.cs
deleted file mode 100644 (file)
index 3048927..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-using Content.Shared.Body.Systems;
-using Robust.Shared.Containers;
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Body.Organ;
-
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-[Access(typeof(SharedBodySystem))]
-public sealed partial class OrganComponent : Component
-{
-    /// <summary>
-    /// Relevant body this organ is attached to.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public EntityUid? Body;
-}
diff --git a/Content.Shared/Body/OrganCategoryPrototype.cs b/Content.Shared/Body/OrganCategoryPrototype.cs
new file mode 100644 (file)
index 0000000..40bf139
--- /dev/null
@@ -0,0 +1,13 @@
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Body;
+
+/// <summary>
+/// Marker prototype that defines well-known types of organs, e.g. "kidneys" or "left arm".
+/// </summary>
+[Prototype]
+public sealed partial class OrganCategoryPrototype : IPrototype
+{
+    [IdDataField]
+    public string ID { get; private set; } = default!;
+}
diff --git a/Content.Shared/Body/OrganComponent.cs b/Content.Shared/Body/OrganComponent.cs
new file mode 100644 (file)
index 0000000..4126c19
--- /dev/null
@@ -0,0 +1,21 @@
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Body;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[Access(typeof(BodySystem))]
+public sealed partial class OrganComponent : Component
+{
+    /// <summary>
+    /// The body entity containing this organ, if any
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public EntityUid? Body;
+
+    /// <summary>
+    /// What kind of organ is this, if any
+    /// </summary>
+    [DataField]
+    public ProtoId<OrganCategoryPrototype>? Category;
+}
diff --git a/Content.Shared/Body/Part/BodyPartComponent.cs b/Content.Shared/Body/Part/BodyPartComponent.cs
deleted file mode 100644 (file)
index c4e65c0..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Systems;
-using Robust.Shared.Containers;
-using Robust.Shared.GameStates;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Body.Part;
-
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-[Access(typeof(SharedBodySystem))]
-public sealed partial class BodyPartComponent : Component
-{
-    // Need to set this on container changes as it may be several transform parents up the hierarchy.
-    /// <summary>
-    /// Parent body for this part.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public EntityUid? Body;
-
-    [DataField, AutoNetworkedField]
-    public BodyPartType PartType = BodyPartType.Other;
-
-    // TODO BODY Replace with a simulation of organs
-    /// <summary>
-    ///     Whether or not the owning <see cref="Body"/> will die if all
-    ///     <see cref="BodyComponent"/>s of this type are removed from it.
-    /// </summary>
-    [DataField("vital"), AutoNetworkedField]
-    public bool IsVital;
-
-    [DataField, AutoNetworkedField]
-    public BodyPartSymmetry Symmetry = BodyPartSymmetry.None;
-
-    /// <summary>
-    /// Child body parts attached to this body part.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public Dictionary<string, BodyPartSlot> Children = new();
-
-    /// <summary>
-    /// Organs attached to this body part.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public Dictionary<string, OrganSlot> Organs = new();
-
-    /// <summary>
-    /// These are only for VV/Debug do not use these for gameplay/systems
-    /// </summary>
-    [ViewVariables]
-    private List<ContainerSlot> BodyPartSlotsVV
-    {
-        get
-        {
-            List<ContainerSlot> temp = new();
-            var containerSystem = IoCManager.Resolve<IEntityManager>().System<SharedContainerSystem>();
-
-            foreach (var slotId in Children.Keys)
-            {
-                temp.Add((ContainerSlot) containerSystem.GetContainer(Owner, SharedBodySystem.PartSlotContainerIdPrefix+slotId));
-            }
-
-            return temp;
-        }
-    }
-
-    [ViewVariables]
-    private List<ContainerSlot> OrganSlotsVV
-    {
-        get
-        {
-            List<ContainerSlot> temp = new();
-            var containerSystem = IoCManager.Resolve<IEntityManager>().System<SharedContainerSystem>();
-
-            foreach (var slotId in Organs.Keys)
-            {
-                temp.Add((ContainerSlot) containerSystem.GetContainer(Owner, SharedBodySystem.OrganSlotContainerIdPrefix+slotId));
-            }
-
-            return temp;
-        }
-    }
-}
-
-/// <summary>
-/// Contains metadata about a body part in relation to its slot.
-/// </summary>
-[NetSerializable, Serializable]
-[DataRecord]
-public partial struct BodyPartSlot
-{
-    public string Id;
-    public BodyPartType Type;
-
-    public BodyPartSlot(string id, BodyPartType type)
-    {
-        Id = id;
-        Type = type;
-    }
-};
-
-/// <summary>
-/// Contains metadata about an organ part in relation to its slot.
-/// </summary>
-[NetSerializable, Serializable]
-[DataRecord]
-public partial struct OrganSlot
-{
-    public string Id;
-
-    public OrganSlot(string id)
-    {
-        Id = id;
-    }
-};
diff --git a/Content.Shared/Body/Part/BodyPartEvents.cs b/Content.Shared/Body/Part/BodyPartEvents.cs
deleted file mode 100644 (file)
index 0d8d2c8..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Content.Shared.Body.Part;
-
-[ByRefEvent]
-public readonly record struct BodyPartAddedEvent(string Slot, Entity<BodyPartComponent> Part);
-
-[ByRefEvent]
-public readonly record struct BodyPartRemovedEvent(string Slot, Entity<BodyPartComponent> Part);
diff --git a/Content.Shared/Body/Part/BodyPartSymmetry.cs b/Content.Shared/Body/Part/BodyPartSymmetry.cs
deleted file mode 100644 (file)
index aa00869..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-using Content.Shared.Body.Components;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Body.Part
-{
-    /// <summary>
-    ///     Defines the symmetry of a <see cref="BodyComponent"/>.
-    /// </summary>
-    [Serializable, NetSerializable]
-    public enum BodyPartSymmetry
-    {
-        None = 0,
-        Left,
-        Right
-    }
-}
diff --git a/Content.Shared/Body/Part/BodyPartType.cs b/Content.Shared/Body/Part/BodyPartType.cs
deleted file mode 100644 (file)
index acaee76..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-using Content.Shared.Body.Components;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Body.Part
-{
-    /// <summary>
-    ///     Defines the type of a <see cref="BodyComponent"/>.
-    /// </summary>
-    [Serializable, NetSerializable]
-    public enum BodyPartType
-    {
-        Other = 0,
-        Torso,
-        Head,
-        Arm,
-        Hand,
-        Leg,
-        Foot,
-        Tail
-    }
-}
diff --git a/Content.Shared/Body/Prototypes/BodyPrototype.cs b/Content.Shared/Body/Prototypes/BodyPrototype.cs
deleted file mode 100644 (file)
index 45ad6df..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Body.Prototypes;
-
-[Prototype]
-public sealed partial class BodyPrototype : IPrototype
-{
-    [IdDataField] public string ID { get; private set; } = default!;
-
-    [DataField("name")]
-    public string Name { get; private set; } = "";
-
-    [DataField("root")] public string Root { get; private set; } = string.Empty;
-
-    [DataField("slots")] public Dictionary<string, BodyPrototypeSlot> Slots { get; private set; } = new();
-
-    private BodyPrototype() { }
-
-    public BodyPrototype(string id, string name, string root, Dictionary<string, BodyPrototypeSlot> slots)
-    {
-        ID = id;
-        Name = name;
-        Root = root;
-        Slots = slots;
-    }
-}
-
-[DataRecord]
-public sealed partial record BodyPrototypeSlot(EntProtoId? Part, HashSet<string> Connections, Dictionary<string, string> Organs);
diff --git a/Content.Shared/Body/Prototypes/BodyPrototypeSerializer.cs b/Content.Shared/Body/Prototypes/BodyPrototypeSerializer.cs
deleted file mode 100644 (file)
index 338e6c8..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-using System.Linq;
-using Content.Shared.Body.Organ;
-using Content.Shared.Prototypes;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization;
-using Robust.Shared.Serialization.Manager;
-using Robust.Shared.Serialization.Markdown.Mapping;
-using Robust.Shared.Serialization.Markdown.Sequence;
-using Robust.Shared.Serialization.Markdown.Validation;
-using Robust.Shared.Serialization.Markdown.Value;
-using Robust.Shared.Serialization.TypeSerializers.Interfaces;
-
-namespace Content.Shared.Body.Prototypes;
-
-[TypeSerializer]
-public sealed class BodyPrototypeSerializer : ITypeReader<BodyPrototype, MappingDataNode>
-{
-    private (ValidationNode Node, List<string> Connections) ValidateSlot(MappingDataNode slot, IDependencyCollection dependencies)
-    {
-        var nodes = new List<ValidationNode>();
-        var prototypes = dependencies.Resolve<IPrototypeManager>();
-        var factory = dependencies.Resolve<IComponentFactory>();
-
-        var connections = new List<string>();
-        if (slot.TryGet("connections", out SequenceDataNode? connectionsNode))
-        {
-            foreach (var node in connectionsNode)
-            {
-                if (node is not ValueDataNode connection)
-                {
-                    nodes.Add(new ErrorNode(node, $"Connection is not a value data node"));
-                    continue;
-                }
-
-                connections.Add(connection.Value);
-            }
-        }
-
-        if (slot.TryGet("organs", out MappingDataNode? organsNode))
-        {
-            foreach (var (key, value) in organsNode)
-            {
-                if (value is not ValueDataNode organ)
-                {
-                    nodes.Add(new ErrorNode(value, $"Value is not a value data node"));
-                    continue;
-                }
-
-                if (!prototypes.TryIndex(organ.Value, out EntityPrototype? organPrototype))
-                {
-                    nodes.Add(new ErrorNode(value, $"No organ entity prototype found with id {organ.Value}"));
-                    continue;
-                }
-
-                if (!organPrototype.HasComponent<OrganComponent>(factory))
-                {
-                    nodes.Add(new ErrorNode(value, $"Organ {organ.Value} does not have a body component"));
-                }
-            }
-        }
-
-        var validation = new ValidatedSequenceNode(nodes);
-        return (validation, connections);
-    }
-
-    public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node,
-        IDependencyCollection dependencies, ISerializationContext? context = null)
-    {
-        var nodes = new List<ValidationNode>();
-
-        if (!node.TryGet("root", out ValueDataNode? root))
-            nodes.Add(new ErrorNode(node, $"No root value data node found"));
-
-        if (!node.TryGet("slots", out MappingDataNode? slots))
-        {
-            nodes.Add(new ErrorNode(node, $"No slots mapping data node found"));
-        }
-        else if (root != null)
-        {
-            if (!slots.TryGet(root.Value, out MappingDataNode? _))
-            {
-                nodes.Add(new ErrorNode(slots, $"No slot found with id {root.Value}"));
-                return new ValidatedSequenceNode(nodes);
-            }
-
-            foreach (var (key, value) in slots)
-            {
-                if (value is not MappingDataNode slot)
-                {
-                    nodes.Add(new ErrorNode(value, $"Slot is not a mapping data node"));
-                    continue;
-                }
-
-                var result = ValidateSlot(slot, dependencies);
-                nodes.Add(result.Node);
-
-                foreach (var connection in result.Connections)
-                {
-                    if (!slots.TryGet(connection, out MappingDataNode? _))
-                        nodes.Add(new ErrorNode(slots, $"No slot found with id {connection}"));
-                }
-            }
-        }
-
-        return new ValidatedSequenceNode(nodes);
-    }
-
-    public BodyPrototype Read(ISerializationManager serializationManager, MappingDataNode node,
-        IDependencyCollection dependencies,
-        SerializationHookContext hookCtx, ISerializationContext? context = null,
-        ISerializationManager.InstantiationDelegate<BodyPrototype>? instanceProvider = null)
-    {
-        var id = node.Get<ValueDataNode>("id").Value;
-        var name = node.Get<ValueDataNode>("name").Value;
-        var root = node.Get<ValueDataNode>("root").Value;
-        var slotNodes = node.Get<MappingDataNode>("slots");
-        var allConnections = new Dictionary<string, (string? Part, HashSet<string>? Connections, Dictionary<string, string>? Organs)>();
-
-        foreach (var (slotId, valueNode) in slotNodes)
-        {
-            var slot = (MappingDataNode) valueNode;
-
-            string? part = null;
-            if (slot.TryGet<ValueDataNode>("part", out var value))
-            {
-                part = value.Value;
-            }
-
-            HashSet<string>? connections = null;
-            if (slot.TryGet("connections", out SequenceDataNode? slotConnectionsNode))
-            {
-                connections = new HashSet<string>();
-
-                foreach (var connection in slotConnectionsNode.Cast<ValueDataNode>())
-                {
-                    connections.Add(connection.Value);
-                }
-            }
-
-            Dictionary<string, string>? organs = null;
-            if (slot.TryGet("organs", out MappingDataNode? slotOrgansNode))
-            {
-                organs = new Dictionary<string, string>();
-
-                foreach (var (organKey, organValueNode) in slotOrgansNode)
-                {
-                    organs.Add(organKey, ((ValueDataNode) organValueNode).Value);
-                }
-            }
-
-            allConnections.Add(slotId, (part, connections, organs));
-        }
-
-        foreach (var (slotId, (_, connections, _)) in allConnections)
-        {
-            if (connections == null)
-                continue;
-
-            foreach (var connection in connections)
-            {
-                var other = allConnections[connection];
-                other.Connections ??= new HashSet<string>();
-                other.Connections.Add(slotId);
-                allConnections[connection] = other;
-            }
-        }
-
-        var slots = new Dictionary<string, BodyPrototypeSlot>();
-
-        foreach (var (slotId, (part, connections, organs)) in allConnections)
-        {
-            var slot = new BodyPrototypeSlot(part, connections ?? new HashSet<string>(), organs ?? new Dictionary<string, string>());
-            slots.Add(slotId, slot);
-        }
-
-        return new BodyPrototype(id, name, root, slots);
-    }
-}
index 55abcbb868797856807642657677bed2cb4c3b22..41eea8e111224abea90ed379264745ddb0657c9e 100644 (file)
@@ -1,5 +1,4 @@
 using Content.Shared.Body.Components;
-using Content.Shared.Body.Events;
 using Content.Shared.Ghost;
 using Content.Shared.Mind;
 using Content.Shared.Mind.Components;
@@ -16,8 +15,8 @@ public sealed class BrainSystem : EntitySystem
     {
         base.Initialize();
 
-        SubscribeLocalEvent<BrainComponent, OrganAddedToBodyEvent>((uid, _, args) => HandleMind(args.Body, uid));
-        SubscribeLocalEvent<BrainComponent, OrganRemovedFromBodyEvent>((uid, _, args) => HandleMind(uid, args.OldBody));
+        SubscribeLocalEvent<BrainComponent, OrganGotInsertedEvent>((uid, _, args) => HandleMind(args.Target, uid));
+        SubscribeLocalEvent<BrainComponent, OrganGotRemovedEvent>((uid, _, args) => HandleMind(uid, args.Target));
         SubscribeLocalEvent<BrainComponent, PointAttemptEvent>(OnPointAttempt);
     }
 
diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs
deleted file mode 100644 (file)
index 22d1feb..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-using System.Linq;
-using System.Numerics;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Organ;
-using Content.Shared.Body.Part;
-using Content.Shared.Body.Prototypes;
-using Content.Shared.DragDrop;
-using Content.Shared.Gibbing;
-using Content.Shared.Inventory;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Containers;
-using Robust.Shared.Map;
-using Robust.Shared.Utility;
-
-namespace Content.Shared.Body.Systems;
-
-public partial class SharedBodySystem
-{
-    /*
-     * tl;dr of how bobby works
-     * - BodyComponent uses a BodyPrototype as a template.
-     * - On MapInit we spawn the root entity in the prototype and spawn all connections outwards from here
-     * - Each "connection" is a body part (e.g. arm, hand, etc.) and each part can also contain organs.
-     */
-
-    [Dependency] private readonly InventorySystem _inventory = default!;
-
-    private const float GibletLaunchImpulse = 8;
-    private const float GibletLaunchImpulseVariance = 3;
-
-    private void InitializeBody()
-    {
-        // Body here to handle root body parts.
-        SubscribeLocalEvent<BodyComponent, EntInsertedIntoContainerMessage>(OnBodyInserted);
-        SubscribeLocalEvent<BodyComponent, EntRemovedFromContainerMessage>(OnBodyRemoved);
-
-        SubscribeLocalEvent<BodyComponent, ComponentInit>(OnBodyInit);
-        SubscribeLocalEvent<BodyComponent, MapInitEvent>(OnBodyMapInit);
-        SubscribeLocalEvent<BodyComponent, CanDragEvent>(OnBodyCanDrag);
-        SubscribeLocalEvent<BodyComponent, BeingGibbedEvent>(OnBeingGibbed);
-    }
-
-    private void OnBodyInserted(Entity<BodyComponent> ent, ref EntInsertedIntoContainerMessage args)
-    {
-        // Root body part?
-        var slotId = args.Container.ID;
-
-        if (slotId != BodyRootContainerId)
-            return;
-
-        var insertedUid = args.Entity;
-
-        if (TryComp(insertedUid, out BodyPartComponent? part))
-        {
-            AddPart((ent, ent), (insertedUid, part), slotId);
-            RecursiveBodyUpdate((insertedUid, part), ent);
-        }
-
-        if (TryComp(insertedUid, out OrganComponent? organ))
-        {
-            AddOrgan((insertedUid, organ), ent, ent);
-        }
-    }
-
-    private void OnBodyRemoved(Entity<BodyComponent> ent, ref EntRemovedFromContainerMessage args)
-    {
-        // Root body part?
-        var slotId = args.Container.ID;
-
-        if (slotId != BodyRootContainerId)
-            return;
-
-        var removedUid = args.Entity;
-        DebugTools.Assert(!TryComp(removedUid, out BodyPartComponent? b) || b.Body == ent);
-        DebugTools.Assert(!TryComp(removedUid, out OrganComponent? o) || o.Body == ent);
-
-        if (TryComp(removedUid, out BodyPartComponent? part))
-        {
-            RemovePart((ent, ent), (removedUid, part), slotId);
-            RecursiveBodyUpdate((removedUid, part), null);
-        }
-
-        if (TryComp(removedUid, out OrganComponent? organ))
-            RemoveOrgan((removedUid, organ), ent);
-    }
-
-    private void OnBodyInit(Entity<BodyComponent> ent, ref ComponentInit args)
-    {
-        // Setup the initial container.
-        ent.Comp.RootContainer = Containers.EnsureContainer<ContainerSlot>(ent, BodyRootContainerId);
-    }
-
-    private void OnBodyMapInit(Entity<BodyComponent> ent, ref MapInitEvent args)
-    {
-        if (ent.Comp.Prototype is null)
-            return;
-
-        // One-time setup
-        // Obviously can't run in Init to avoid double-spawns on save / load.
-        var prototype = Prototypes.Index(ent.Comp.Prototype.Value);
-        MapInitBody(ent, prototype);
-    }
-
-    private void MapInitBody(EntityUid bodyEntity, BodyPrototype prototype)
-    {
-        var protoRoot = prototype.Slots[prototype.Root];
-        if (protoRoot.Part is null)
-            return;
-
-        // This should already handle adding the entity to the root.
-        var rootPartUid = SpawnInContainerOrDrop(protoRoot.Part, bodyEntity, BodyRootContainerId);
-        var rootPart = Comp<BodyPartComponent>(rootPartUid);
-        rootPart.Body = bodyEntity;
-        Dirty(rootPartUid, rootPart);
-
-        // Setup the rest of the body entities.
-        SetupOrgans((rootPartUid, rootPart), protoRoot.Organs);
-        MapInitParts(rootPartUid, prototype);
-    }
-
-    private void OnBodyCanDrag(Entity<BodyComponent> ent, ref CanDragEvent args)
-    {
-        args.Handled = true;
-    }
-
-    /// <summary>
-    /// Sets up all of the relevant body parts for a particular body entity and root part.
-    /// </summary>
-    private void MapInitParts(EntityUid rootPartId, BodyPrototype prototype)
-    {
-        // Start at the root part and traverse the body graph, setting up parts as we go.
-        // Basic BFS pathfind.
-        var rootSlot = prototype.Root;
-        var frontier = new Queue<string>();
-        frontier.Enqueue(rootSlot);
-
-        // Child -> Parent connection.
-        var cameFrom = new Dictionary<string, string>();
-        cameFrom[rootSlot] = rootSlot;
-        // Maps slot to its relevant entity.
-        var cameFromEntities = new Dictionary<string, EntityUid>();
-        cameFromEntities[rootSlot] = rootPartId;
-
-        while (frontier.TryDequeue(out var currentSlotId))
-        {
-            var currentSlot = prototype.Slots[currentSlotId];
-
-            foreach (var connection in currentSlot.Connections)
-            {
-                // Already been handled
-                if (!cameFrom.TryAdd(connection, currentSlotId))
-                    continue;
-
-                // Setup part
-                var connectionSlot = prototype.Slots[connection];
-                var parentEntity = cameFromEntities[currentSlotId];
-                var parentPartComponent = Comp<BodyPartComponent>(parentEntity);
-
-                // Spawn the entity on the target
-                // then get the body part type, create the slot, and finally
-                // we can insert it into the container.
-                var childPart = Spawn(connectionSlot.Part, new EntityCoordinates(parentEntity, Vector2.Zero));
-                cameFromEntities[connection] = childPart;
-
-                var childPartComponent = Comp<BodyPartComponent>(childPart);
-                var partSlot = CreatePartSlot(parentEntity, connection, childPartComponent.PartType, parentPartComponent);
-                var cont = Containers.GetContainer(parentEntity, GetPartSlotContainerId(connection));
-
-                if (partSlot is null || !Containers.Insert(childPart, cont))
-                {
-                    Log.Error($"Could not create slot for connection {connection} in body {prototype.ID}");
-                    QueueDel(childPart);
-                    continue;
-                }
-
-                // Add organs
-                SetupOrgans((childPart, childPartComponent), connectionSlot.Organs);
-
-                // Enqueue it so we can also get its neighbors.
-                frontier.Enqueue(connection);
-            }
-        }
-    }
-
-    private void SetupOrgans(Entity<BodyPartComponent> ent, Dictionary<string, string> organs)
-    {
-        foreach (var (organSlotId, organProto) in organs)
-        {
-            var slot = CreateOrganSlot((ent, ent), organSlotId);
-            SpawnInContainerOrDrop(organProto, ent, GetOrganContainerId(organSlotId));
-
-            if (slot is null)
-            {
-                Log.Error($"Could not create organ for slot {organSlotId} in {ToPrettyString(ent)}");
-            }
-        }
-    }
-
-    /// <summary>
-    /// Gets all body containers on this entity including the root one.
-    /// </summary>
-    public IEnumerable<BaseContainer> GetBodyContainers(
-        EntityUid id,
-        BodyComponent? body = null,
-        BodyPartComponent? rootPart = null)
-    {
-        if (!Resolve(id, ref body, logMissing: false)
-            || body.RootContainer.ContainedEntity is null
-            || !Resolve(body.RootContainer.ContainedEntity.Value, ref rootPart))
-        {
-            yield break;
-        }
-
-        yield return body.RootContainer;
-
-        foreach (var childContainer in GetPartContainers(body.RootContainer.ContainedEntity.Value, rootPart))
-        {
-            yield return childContainer;
-        }
-    }
-
-    /// <summary>
-    /// Gets all child body parts of this entity, including the root entity.
-    /// </summary>
-    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyChildren(
-        EntityUid? id,
-        BodyComponent? body = null,
-        BodyPartComponent? rootPart = null)
-    {
-        if (id is null
-            || !Resolve(id.Value, ref body, logMissing: false)
-            || body.RootContainer.ContainedEntity is null
-            || !Resolve(body.RootContainer.ContainedEntity.Value, ref rootPart))
-        {
-            yield break;
-        }
-
-        foreach (var child in GetBodyPartChildren(body.RootContainer.ContainedEntity.Value, rootPart))
-        {
-            yield return child;
-        }
-    }
-
-    public IEnumerable<(EntityUid Id, OrganComponent Component)> GetBodyOrgans(
-        EntityUid? bodyId,
-        BodyComponent? body = null)
-    {
-        if (bodyId is null || !Resolve(bodyId.Value, ref body, logMissing: false))
-            yield break;
-
-        foreach (var part in GetBodyChildren(bodyId, body))
-        {
-            foreach (var organ in GetPartOrgans(part.Id, part.Component))
-            {
-                yield return organ;
-            }
-        }
-    }
-
-    /// <summary>
-    /// Returns all body part slots for this entity.
-    /// </summary>
-    /// <param name="bodyId"></param>
-    /// <param name="body"></param>
-    /// <returns></returns>
-    public IEnumerable<BodyPartSlot> GetBodyAllSlots(
-        EntityUid bodyId,
-        BodyComponent? body = null)
-    {
-        if (!Resolve(bodyId, ref body, logMissing: false)
-            || body.RootContainer.ContainedEntity is null)
-        {
-            yield break;
-        }
-
-        foreach (var slot in GetAllBodyPartSlots(body.RootContainer.ContainedEntity.Value))
-        {
-            yield return slot;
-        }
-    }
-
-    private void OnBeingGibbed(Entity<BodyComponent> ent, ref BeingGibbedEvent args)
-    {
-        var parts = GetBodyChildren(ent, ent).ToArray();
-        args.Giblets.EnsureCapacity(args.Giblets.Capacity + parts.Length);
-        foreach (var part in parts)
-        {
-            foreach (var organ in GetPartOrgans(part.Id, part.Component))
-            {
-                args.Giblets.Add(organ.Id);
-            }
-            PredictedQueueDel(part.Id);
-        }
-
-        foreach (var item in _inventory.GetHandOrInventoryEntities(ent.Owner))
-        {
-            args.Giblets.Add(item);
-        }
-    }
-}
diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs
deleted file mode 100644 (file)
index f83dd50..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Events;
-using Content.Shared.Body.Organ;
-using Content.Shared.Body.Part;
-using Robust.Shared.Containers;
-
-namespace Content.Shared.Body.Systems;
-
-public partial class SharedBodySystem
-{
-    private void AddOrgan(
-        Entity<OrganComponent> organEnt,
-        EntityUid bodyUid,
-        EntityUid parentPartUid)
-    {
-        organEnt.Comp.Body = bodyUid;
-        var addedEv = new OrganAddedEvent(parentPartUid);
-        RaiseLocalEvent(organEnt, ref addedEv);
-
-        if (organEnt.Comp.Body is not null)
-        {
-            var addedInBodyEv = new OrganAddedToBodyEvent(bodyUid, parentPartUid);
-            RaiseLocalEvent(organEnt, ref addedInBodyEv);
-        }
-
-        Dirty(organEnt, organEnt.Comp);
-    }
-
-    private void RemoveOrgan(Entity<OrganComponent> organEnt, EntityUid parentPartUid)
-    {
-        var removedEv = new OrganRemovedEvent(parentPartUid);
-        RaiseLocalEvent(organEnt, ref removedEv);
-
-        if (organEnt.Comp.Body is { Valid: true } bodyUid)
-        {
-            var removedInBodyEv = new OrganRemovedFromBodyEvent(bodyUid, parentPartUid);
-            RaiseLocalEvent(organEnt, ref removedInBodyEv);
-        }
-
-        organEnt.Comp.Body = null;
-        Dirty(organEnt, organEnt.Comp);
-    }
-
-    /// <summary>
-    /// Creates the specified organ slot on the parent entity.
-    /// </summary>
-    private OrganSlot? CreateOrganSlot(Entity<BodyPartComponent?> parentEnt, string slotId)
-    {
-        if (!Resolve(parentEnt, ref parentEnt.Comp, logMissing: false))
-            return null;
-
-        Containers.EnsureContainer<ContainerSlot>(parentEnt, GetOrganContainerId(slotId));
-        var slot = new OrganSlot(slotId);
-        parentEnt.Comp.Organs.Add(slotId, slot);
-        return slot;
-    }
-
-    /// <summary>
-    /// Attempts to create the specified organ slot on the specified parent if it exists.
-    /// </summary>
-    public bool TryCreateOrganSlot(
-        EntityUid? parent,
-        string slotId,
-        [NotNullWhen(true)] out OrganSlot? slot,
-        BodyPartComponent? part = null)
-    {
-        slot = null;
-
-        if (parent is null || !Resolve(parent.Value, ref part, logMissing: false))
-        {
-            return false;
-        }
-
-        Containers.EnsureContainer<ContainerSlot>(parent.Value, GetOrganContainerId(slotId));
-        slot = new OrganSlot(slotId);
-        return part.Organs.TryAdd(slotId, slot.Value);
-    }
-
-    /// <summary>
-    /// Returns whether the slotId exists on the partId.
-    /// </summary>
-    public bool CanInsertOrgan(
-        EntityUid partId,
-        string slotId,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(partId, ref part) && part.Organs.ContainsKey(slotId);
-    }
-
-    /// <summary>
-    /// Returns whether the specified organ slot exists on the partId.
-    /// </summary>
-    public bool CanInsertOrgan(
-        EntityUid partId,
-        OrganSlot slot,
-        BodyPartComponent? part = null)
-    {
-        return CanInsertOrgan(partId, slot.Id, part);
-    }
-
-    public bool InsertOrgan(
-        EntityUid partId,
-        EntityUid organId,
-        string slotId,
-        BodyPartComponent? part = null,
-        OrganComponent? organ = null)
-    {
-        if (!Resolve(organId, ref organ, logMissing: false)
-            || !Resolve(partId, ref part, logMissing: false)
-            || !CanInsertOrgan(partId, slotId, part))
-        {
-            return false;
-        }
-
-        var containerId = GetOrganContainerId(slotId);
-
-        return Containers.TryGetContainer(partId, containerId, out var container)
-            && Containers.Insert(organId, container);
-    }
-
-    /// <summary>
-    /// Removes the organ if it is inside of a body part.
-    /// </summary>
-    public bool RemoveOrgan(EntityUid organId, OrganComponent? organ = null)
-    {
-        if (!Containers.TryGetContainingContainer((organId, null, null), out var container))
-            return false;
-
-        var parent = container.Owner;
-
-        return HasComp<BodyPartComponent>(parent)
-            && Containers.Remove(organId, container);
-    }
-
-    /// <summary>
-    /// Tries to add this organ to any matching slot on this body part.
-    /// </summary>
-    public bool AddOrganToFirstValidSlot(
-        EntityUid partId,
-        EntityUid organId,
-        BodyPartComponent? part = null,
-        OrganComponent? organ = null)
-    {
-        if (!Resolve(partId, ref part, logMissing: false)
-            || !Resolve(organId, ref organ, logMissing: false))
-        {
-            return false;
-        }
-
-        foreach (var slotId in part.Organs.Keys)
-        {
-            InsertOrgan(partId, organId, slotId, part, organ);
-            return true;
-        }
-
-        return false;
-    }
-
-    /// <summary>
-    /// Returns a list of Entity<<see cref="T"/>, <see cref="OrganComponent"/>>
-    /// for each organ of the body
-    /// </summary>
-    /// <typeparam name="T">The component that we want to return</typeparam>
-    /// <param name="entity">The body to check the organs of</param>
-    public List<Entity<T, OrganComponent>> GetBodyOrganEntityComps<T>(
-        Entity<BodyComponent?> entity)
-        where T : IComponent
-    {
-        if (!Resolve(entity, ref entity.Comp))
-            return new List<Entity<T, OrganComponent>>();
-
-        var query = GetEntityQuery<T>();
-        var list = new List<Entity<T, OrganComponent>>(3);
-        foreach (var organ in GetBodyOrgans(entity.Owner, entity.Comp))
-        {
-            if (query.TryGetComponent(organ.Id, out var comp))
-                list.Add((organ.Id, comp, organ.Component));
-        }
-
-        return list;
-    }
-
-    /// <summary>
-    ///     Tries to get a list of ValueTuples of <see cref="T"/> and OrganComponent on each organs
-    ///     in the given body.
-    /// </summary>
-    /// <param name="uid">The body entity id to check on.</param>
-    /// <param name="comps">The list of components.</param>
-    /// <param name="body">The body to check for organs on.</param>
-    /// <typeparam name="T">The component to check for.</typeparam>
-    /// <returns>Whether any were found.</returns>
-    public bool TryGetBodyOrganEntityComps<T>(
-        Entity<BodyComponent?> entity,
-        [NotNullWhen(true)] out List<Entity<T, OrganComponent>>? comps)
-        where T : IComponent
-    {
-        if (!Resolve(entity.Owner, ref entity.Comp))
-        {
-            comps = null;
-            return false;
-        }
-
-        comps = GetBodyOrganEntityComps<T>(entity);
-
-        if (comps.Count != 0)
-            return true;
-
-        comps = null;
-        return false;
-    }
-}
diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs
deleted file mode 100644 (file)
index f787650..0000000
+++ /dev/null
@@ -1,803 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Events;
-using Content.Shared.Body.Organ;
-using Content.Shared.Body.Part;
-using Content.Shared.Damage;
-using Content.Shared.Damage.Prototypes;
-using Content.Shared.Movement.Components;
-using Content.Shared.Standing;
-using Robust.Shared.Containers;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
-
-namespace Content.Shared.Body.Systems;
-
-public partial class SharedBodySystem
-{
-    private static readonly ProtoId<DamageTypePrototype> BloodlossDamageType = "Bloodloss";
-    private void InitializeParts()
-    {
-        // TODO: This doesn't handle comp removal on child ents.
-
-        // If you modify this also see the Body partial for root parts.
-        SubscribeLocalEvent<BodyPartComponent, EntInsertedIntoContainerMessage>(OnBodyPartInserted);
-        SubscribeLocalEvent<BodyPartComponent, EntRemovedFromContainerMessage>(OnBodyPartRemoved);
-    }
-
-    private void OnBodyPartInserted(Entity<BodyPartComponent> ent, ref EntInsertedIntoContainerMessage args)
-    {
-        // Body part inserted into another body part.
-        var insertedUid = args.Entity;
-        var slotId = args.Container.ID;
-
-        if (ent.Comp.Body is null)
-            return;
-
-        if (TryComp(insertedUid, out BodyPartComponent? part))
-        {
-            AddPart(ent.Comp.Body.Value, (insertedUid, part), slotId);
-            RecursiveBodyUpdate((insertedUid, part), ent.Comp.Body.Value);
-        }
-
-        if (TryComp(insertedUid, out OrganComponent? organ))
-            AddOrgan((insertedUid, organ), ent.Comp.Body.Value, ent);
-    }
-
-    private void OnBodyPartRemoved(Entity<BodyPartComponent> ent, ref EntRemovedFromContainerMessage args)
-    {
-        // Body part removed from another body part.
-        var removedUid = args.Entity;
-        var slotId = args.Container.ID;
-
-        DebugTools.Assert(!TryComp(removedUid, out BodyPartComponent? b) || b.Body == ent.Comp.Body);
-        DebugTools.Assert(!TryComp(removedUid, out OrganComponent? o) || o.Body == ent.Comp.Body);
-
-        if (TryComp(removedUid, out BodyPartComponent? part) && part.Body is not null)
-        {
-            RemovePart(part.Body.Value, (removedUid, part), slotId);
-            RecursiveBodyUpdate((removedUid, part), null);
-        }
-
-        if (TryComp(removedUid, out OrganComponent? organ))
-            RemoveOrgan((removedUid, organ), ent);
-    }
-
-    private void RecursiveBodyUpdate(Entity<BodyPartComponent> ent, EntityUid? bodyUid)
-    {
-        ent.Comp.Body = bodyUid;
-        Dirty(ent, ent.Comp);
-
-        foreach (var slotId in ent.Comp.Organs.Keys)
-        {
-            if (!Containers.TryGetContainer(ent, GetOrganContainerId(slotId), out var container))
-                continue;
-
-            foreach (var organ in container.ContainedEntities)
-            {
-                if (!TryComp(organ, out OrganComponent? organComp))
-                    continue;
-
-                Dirty(organ, organComp);
-
-                if (organComp.Body is { Valid: true } oldBodyUid)
-                {
-                    var removedEv = new OrganRemovedFromBodyEvent(oldBodyUid, ent);
-                    RaiseLocalEvent(organ, ref removedEv);
-                }
-
-                organComp.Body = bodyUid;
-                if (bodyUid is not null)
-                {
-                    var addedEv = new OrganAddedToBodyEvent(bodyUid.Value, ent);
-                    RaiseLocalEvent(organ, ref addedEv);
-                }
-            }
-        }
-
-        foreach (var slotId in ent.Comp.Children.Keys)
-        {
-            if (!Containers.TryGetContainer(ent, GetPartSlotContainerId(slotId), out var container))
-                continue;
-
-            foreach (var containedUid in container.ContainedEntities)
-            {
-                if (TryComp(containedUid, out BodyPartComponent? childPart))
-                    RecursiveBodyUpdate((containedUid, childPart), bodyUid);
-            }
-        }
-    }
-
-    protected virtual void AddPart(
-        Entity<BodyComponent?> bodyEnt,
-        Entity<BodyPartComponent> partEnt,
-        string slotId)
-    {
-        Dirty(partEnt, partEnt.Comp);
-        partEnt.Comp.Body = bodyEnt;
-
-        var ev = new BodyPartAddedEvent(slotId, partEnt);
-        RaiseLocalEvent(bodyEnt, ref ev);
-
-        AddLeg(partEnt, bodyEnt);
-    }
-
-    protected virtual void RemovePart(
-        Entity<BodyComponent?> bodyEnt,
-        Entity<BodyPartComponent> partEnt,
-        string slotId)
-    {
-        Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false);
-        Dirty(partEnt, partEnt.Comp);
-        partEnt.Comp.Body = null;
-
-        var ev = new BodyPartRemovedEvent(slotId, partEnt);
-        RaiseLocalEvent(bodyEnt, ref ev);
-
-        RemoveLeg(partEnt, bodyEnt);
-        PartRemoveDamage(bodyEnt, partEnt);
-    }
-
-    private void AddLeg(Entity<BodyPartComponent> legEnt, Entity<BodyComponent?> bodyEnt)
-    {
-        if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
-            return;
-
-        if (legEnt.Comp.PartType == BodyPartType.Leg)
-        {
-            bodyEnt.Comp.LegEntities.Add(legEnt);
-            UpdateMovementSpeed(bodyEnt);
-            Dirty(bodyEnt, bodyEnt.Comp);
-        }
-    }
-
-    private void RemoveLeg(Entity<BodyPartComponent> legEnt, Entity<BodyComponent?> bodyEnt)
-    {
-        if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
-            return;
-
-        if (legEnt.Comp.PartType != BodyPartType.Leg)
-            return;
-
-        bodyEnt.Comp.LegEntities.Remove(legEnt);
-        UpdateMovementSpeed(bodyEnt);
-        Dirty(bodyEnt, bodyEnt.Comp);
-
-        if (bodyEnt.Comp.LegEntities.Count != 0)
-            return;
-
-        if (!TryComp<StandingStateComponent>(bodyEnt, out var standingState)
-            || !standingState.Standing
-            || !Standing.Down(bodyEnt, standingState: standingState))
-            return;
-
-        var ev = new DropHandItemsEvent();
-        RaiseLocalEvent(bodyEnt, ref ev);
-    }
-
-    private void PartRemoveDamage(Entity<BodyComponent?> bodyEnt, Entity<BodyPartComponent> partEnt)
-    {
-        if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
-            return;
-
-        if (!_timing.ApplyingState
-            && partEnt.Comp.IsVital
-            && !GetBodyChildrenOfType(bodyEnt, partEnt.Comp.PartType, bodyEnt.Comp).Any()
-        )
-        {
-            // TODO BODY SYSTEM KILL : remove this when wounding and required parts are implemented properly
-            var damage = new DamageSpecifier(Prototypes.Index(BloodlossDamageType), 300);
-            Damageable.ChangeDamage(bodyEnt.Owner, damage);
-        }
-    }
-
-    /// <summary>
-    /// Tries to get the parent body part to this if applicable.
-    /// Doesn't validate if it's a part of body system.
-    /// </summary>
-    public EntityUid? GetParentPartOrNull(EntityUid uid)
-    {
-        if (!Containers.TryGetContainingContainer((uid, null, null), out var container))
-            return null;
-
-        var parent = container.Owner;
-
-        if (!HasComp<BodyPartComponent>(parent))
-            return null;
-
-        return parent;
-    }
-
-    /// <summary>
-    /// Tries to get the parent body part and slot to this if applicable.
-    /// </summary>
-    public (EntityUid Parent, string Slot)? GetParentPartAndSlotOrNull(EntityUid uid)
-    {
-        if (!Containers.TryGetContainingContainer((uid, null, null), out var container))
-            return null;
-
-        var slotId = GetPartSlotContainerIdFromContainer(container.ID);
-
-        if (string.IsNullOrEmpty(slotId))
-            return null;
-
-        var parent = container.Owner;
-
-        if (!TryComp<BodyPartComponent>(parent, out var parentBody)
-            || !parentBody.Children.ContainsKey(slotId))
-            return null;
-
-        return (parent, slotId);
-    }
-
-    /// <summary>
-    /// Tries to get the relevant parent body part to this if it exists.
-    /// It won't exist if this is the root body part or if it's not in a body.
-    /// </summary>
-    public bool TryGetParentBodyPart(
-        EntityUid partUid,
-        [NotNullWhen(true)] out EntityUid? parentUid,
-        [NotNullWhen(true)] out BodyPartComponent? parentComponent)
-    {
-        DebugTools.Assert(HasComp<BodyPartComponent>(partUid));
-        parentUid = null;
-        parentComponent = null;
-
-        if (Containers.TryGetContainingContainer((partUid, null, null), out var container) &&
-            TryComp(container.Owner, out parentComponent))
-        {
-            parentUid = container.Owner;
-            return true;
-        }
-
-        return false;
-    }
-
-    #region Slots
-
-    /// <summary>
-    /// Creates a BodyPartSlot on the specified partUid.
-    /// </summary>
-    private BodyPartSlot? CreatePartSlot(
-        EntityUid partUid,
-        string slotId,
-        BodyPartType partType,
-        BodyPartComponent? part = null)
-    {
-        if (!Resolve(partUid, ref part, logMissing: false))
-            return null;
-
-        Containers.EnsureContainer<ContainerSlot>(partUid, GetPartSlotContainerId(slotId));
-        var partSlot = new BodyPartSlot(slotId, partType);
-        part.Children.Add(slotId, partSlot);
-        Dirty(partUid, part);
-        return partSlot;
-    }
-
-    /// <summary>
-    /// Tries to create a BodyPartSlot on the specified partUid.
-    /// </summary>
-    /// <returns>false if not relevant or can't add it.</returns>
-    public bool TryCreatePartSlot(
-        EntityUid? partId,
-        string slotId,
-        BodyPartType partType,
-        [NotNullWhen(true)] out BodyPartSlot? slot,
-        BodyPartComponent? part = null)
-    {
-        slot = null;
-
-        if (partId is null
-            || !Resolve(partId.Value, ref part, logMissing: false))
-        {
-            return false;
-        }
-
-        Containers.EnsureContainer<ContainerSlot>(partId.Value, GetPartSlotContainerId(slotId));
-        slot = new BodyPartSlot(slotId, partType);
-
-        if (!part.Children.TryAdd(slotId, slot.Value))
-            return false;
-
-        Dirty(partId.Value, part);
-        return true;
-    }
-
-    public bool TryCreatePartSlotAndAttach(
-        EntityUid parentId,
-        string slotId,
-        EntityUid childId,
-        BodyPartType partType,
-        BodyPartComponent? parent = null,
-        BodyPartComponent? child = null)
-    {
-        return TryCreatePartSlot(parentId, slotId, partType, out _, parent)
-               && AttachPart(parentId, slotId, childId, parent, child);
-    }
-
-    #endregion
-
-    #region RootPartManagement
-
-    /// <summary>
-    /// Returns true if the partId is the root body container for the specified bodyId.
-    /// </summary>
-    public bool IsPartRoot(
-        EntityUid bodyId,
-        EntityUid partId,
-        BodyComponent? body = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(partId, ref part)
-            && Resolve(bodyId, ref body)
-            && Containers.TryGetContainingContainer(bodyId, partId, out var container)
-            && container.ID == BodyRootContainerId;
-    }
-
-    /// <summary>
-    /// Returns true if we can attach the partId to the bodyId as the root entity.
-    /// </summary>
-    public bool CanAttachToRoot(
-        EntityUid bodyId,
-        EntityUid partId,
-        BodyComponent? body = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(bodyId, ref body)
-            && Resolve(partId, ref part)
-            && body.RootContainer.ContainedEntity is null
-            && bodyId != part.Body;
-    }
-
-    /// <summary>
-    /// Returns the root part of this body if it exists.
-    /// </summary>
-    public (EntityUid Entity, BodyPartComponent BodyPart)? GetRootPartOrNull(EntityUid bodyId, BodyComponent? body = null)
-    {
-        if (!Resolve(bodyId, ref body)
-            || body.RootContainer.ContainedEntity is null)
-        {
-            return null;
-        }
-
-        return (body.RootContainer.ContainedEntity.Value,
-            Comp<BodyPartComponent>(body.RootContainer.ContainedEntity.Value));
-    }
-
-    /// <summary>
-    /// Returns true if the partId can be attached to the parentId in the specified slot.
-    /// </summary>
-    public bool CanAttachPart(
-        EntityUid parentId,
-        BodyPartSlot slot,
-        EntityUid partId,
-        BodyPartComponent? parentPart = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(partId, ref part, logMissing: false)
-            && Resolve(parentId, ref parentPart, logMissing: false)
-            && CanAttachPart(parentId, slot.Id, partId, parentPart, part);
-    }
-
-    /// <summary>
-    /// Returns true if we can attach the specified partId to the parentId in the specified slot.
-    /// </summary>
-    public bool CanAttachPart(
-        EntityUid parentId,
-        string slotId,
-        EntityUid partId,
-        BodyPartComponent? parentPart = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(partId, ref part, logMissing: false)
-            && Resolve(parentId, ref parentPart, logMissing: false)
-            && parentPart.Children.TryGetValue(slotId, out var parentSlotData)
-            && part.PartType == parentSlotData.Type
-            && Containers.TryGetContainer(parentId, GetPartSlotContainerId(slotId), out var container)
-            && Containers.CanInsert(partId, container);
-    }
-
-    public bool AttachPartToRoot(
-        EntityUid bodyId,
-        EntityUid partId,
-        BodyComponent? body = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(bodyId, ref body)
-            && Resolve(partId, ref part)
-            && CanAttachToRoot(bodyId, partId, body, part)
-            && Containers.Insert(partId, body.RootContainer);
-    }
-
-    #endregion
-
-    #region Attach/Detach
-
-    /// <summary>
-    /// Attaches a body part to the specified body part parent.
-    /// </summary>
-    public bool AttachPart(
-        EntityUid parentPartId,
-        string slotId,
-        EntityUid partId,
-        BodyPartComponent? parentPart = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(parentPartId, ref parentPart, logMissing: false)
-            && parentPart.Children.TryGetValue(slotId, out var slot)
-            && AttachPart(parentPartId, slot, partId, parentPart, part);
-    }
-
-    /// <summary>
-    /// Attaches a body part to the specified body part parent.
-    /// </summary>
-    public bool AttachPart(
-        EntityUid parentPartId,
-        BodyPartSlot slot,
-        EntityUid partId,
-        BodyPartComponent? parentPart = null,
-        BodyPartComponent? part = null)
-    {
-        if (!Resolve(parentPartId, ref parentPart, logMissing: false)
-            || !Resolve(partId, ref part, logMissing: false)
-            || !CanAttachPart(parentPartId, slot.Id, partId, parentPart, part)
-            || !parentPart.Children.ContainsKey(slot.Id))
-        {
-            return false;
-        }
-
-        if (!Containers.TryGetContainer(parentPartId, GetPartSlotContainerId(slot.Id), out var container))
-        {
-            DebugTools.Assert($"Unable to find body slot {slot.Id} for {ToPrettyString(parentPartId)}");
-            return false;
-        }
-
-        return Containers.Insert(partId, container);
-    }
-
-    #endregion
-
-    #region Misc
-
-    public void UpdateMovementSpeed(
-        EntityUid bodyId,
-        BodyComponent? body = null,
-        MovementSpeedModifierComponent? movement = null)
-    {
-        if (!Resolve(bodyId, ref body, ref movement, logMissing: false)
-            || body.RequiredLegs <= 0)
-        {
-            return;
-        }
-
-        var walkSpeed = 0f;
-        var sprintSpeed = 0f;
-        var acceleration = 0f;
-        foreach (var legEntity in body.LegEntities)
-        {
-            if (!TryComp<MovementBodyPartComponent>(legEntity, out var legModifier))
-                continue;
-
-            walkSpeed += legModifier.WalkSpeed;
-            sprintSpeed += legModifier.SprintSpeed;
-            acceleration += legModifier.Acceleration;
-        }
-        walkSpeed /= body.RequiredLegs;
-        sprintSpeed /= body.RequiredLegs;
-        acceleration /= body.RequiredLegs;
-        Movement.ChangeBaseSpeed(bodyId, walkSpeed, sprintSpeed, acceleration, movement);
-    }
-
-    #endregion
-
-    #region Queries
-
-    /// <summary>
-    /// Get all organs for the specified body part.
-    /// </summary>
-    public IEnumerable<(EntityUid Id, OrganComponent Component)> GetPartOrgans(EntityUid partId, BodyPartComponent? part = null)
-    {
-        if (!Resolve(partId, ref part, logMissing: false))
-            yield break;
-
-        foreach (var slotId in part.Organs.Keys)
-        {
-            var containerSlotId = GetOrganContainerId(slotId);
-
-            if (!Containers.TryGetContainer(partId, containerSlotId, out var container))
-                continue;
-
-            foreach (var containedEnt in container.ContainedEntities)
-            {
-                if (!TryComp(containedEnt, out OrganComponent? organ))
-                    continue;
-
-                yield return (containedEnt, organ);
-            }
-        }
-    }
-
-    /// <summary>
-    /// Gets all BaseContainers for body parts on this entity and its child entities.
-    /// </summary>
-    public IEnumerable<BaseContainer> GetPartContainers(EntityUid id, BodyPartComponent? part = null)
-    {
-        if (!Resolve(id, ref part, logMissing: false) ||
-            part.Children.Count == 0)
-        {
-            yield break;
-        }
-
-        foreach (var slotId in part.Children.Keys)
-        {
-            var containerSlotId = GetPartSlotContainerId(slotId);
-
-            if (!Containers.TryGetContainer(id, containerSlotId, out var container))
-                continue;
-
-            yield return container;
-
-            foreach (var ent in container.ContainedEntities)
-            {
-                foreach (var childContainer in GetPartContainers(ent))
-                {
-                    yield return childContainer;
-                }
-            }
-        }
-    }
-
-    /// <summary>
-    /// Returns all body part components for this entity including itself.
-    /// </summary>
-    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyPartChildren(
-        EntityUid partId,
-        BodyPartComponent? part = null)
-    {
-        if (!Resolve(partId, ref part, logMissing: false))
-            yield break;
-
-        yield return (partId, part);
-
-        foreach (var slotId in part.Children.Keys)
-        {
-            var containerSlotId = GetPartSlotContainerId(slotId);
-
-            if (Containers.TryGetContainer(partId, containerSlotId, out var container))
-            {
-                foreach (var containedEnt in container.ContainedEntities)
-                {
-                    if (!TryComp(containedEnt, out BodyPartComponent? childPart))
-                        continue;
-
-                    foreach (var value in GetBodyPartChildren(containedEnt, childPart))
-                    {
-                        yield return value;
-                    }
-                }
-            }
-        }
-    }
-
-    /// <summary>
-    /// Returns all body part slots for this entity.
-    /// </summary>
-    public IEnumerable<BodyPartSlot> GetAllBodyPartSlots(
-        EntityUid partId,
-        BodyPartComponent? part = null)
-    {
-        if (!Resolve(partId, ref part, logMissing: false))
-            yield break;
-
-        foreach (var (slotId, slot) in part.Children)
-        {
-            yield return slot;
-
-            var containerSlotId = GetOrganContainerId(slotId);
-
-            if (Containers.TryGetContainer(partId, containerSlotId, out var container))
-            {
-                foreach (var containedEnt in container.ContainedEntities)
-                {
-                    if (!TryComp(containedEnt, out BodyPartComponent? childPart))
-                        continue;
-
-                    foreach (var subSlot in GetAllBodyPartSlots(containedEnt, childPart))
-                    {
-                        yield return subSlot;
-                    }
-                }
-            }
-        }
-    }
-
-    /// <summary>
-    /// Returns true if the bodyId has any parts of this type.
-    /// </summary>
-    public bool BodyHasPartType(
-        EntityUid bodyId,
-        BodyPartType type,
-        BodyComponent? body = null)
-    {
-        return GetBodyChildrenOfType(bodyId, type, body).Any();
-    }
-
-    /// <summary>
-    /// Returns true if the parentId has the specified childId.
-    /// </summary>
-    public bool PartHasChild(
-        EntityUid parentId,
-        EntityUid childId,
-        BodyPartComponent? parent,
-        BodyPartComponent? child)
-    {
-        if (!Resolve(parentId, ref parent, logMissing: false)
-            || !Resolve(childId, ref child, logMissing: false))
-        {
-            return false;
-        }
-
-        foreach (var (foundId, _) in GetBodyPartChildren(parentId, parent))
-        {
-            if (foundId == childId)
-                return true;
-        }
-        return false;
-    }
-
-    /// <summary>
-    /// Returns true if the bodyId has the specified partId.
-    /// </summary>
-    public bool BodyHasChild(
-        EntityUid bodyId,
-        EntityUid partId,
-        BodyComponent? body = null,
-        BodyPartComponent? part = null)
-    {
-        return Resolve(bodyId, ref body, logMissing: false)
-            && body.RootContainer.ContainedEntity is not null
-            && Resolve(partId, ref part, logMissing: false)
-            && TryComp(body.RootContainer.ContainedEntity, out BodyPartComponent? rootPart)
-            && PartHasChild(body.RootContainer.ContainedEntity.Value, partId, rootPart, part);
-    }
-
-    public IEnumerable<(EntityUid Id, BodyPartComponent Component)> GetBodyChildrenOfType(
-        EntityUid bodyId,
-        BodyPartType type,
-        BodyComponent? body = null)
-    {
-        foreach (var part in GetBodyChildren(bodyId, body))
-        {
-            if (part.Component.PartType == type)
-                yield return part;
-        }
-    }
-
-    /// <summary>
-    ///     Returns a list of ValueTuples of <see cref="T"/> and OrganComponent on each organ
-    ///     in the given part.
-    /// </summary>
-    /// <param name="uid">The part entity id to check on.</param>
-    /// <param name="part">The part to check for organs on.</param>
-    /// <typeparam name="T">The component to check for.</typeparam>
-    public List<(T Comp, OrganComponent Organ)> GetBodyPartOrganComponents<T>(
-        EntityUid uid,
-        BodyPartComponent? part = null)
-        where T : IComponent
-    {
-        if (!Resolve(uid, ref part))
-            return new List<(T Comp, OrganComponent Organ)>();
-
-        var query = GetEntityQuery<T>();
-        var list = new List<(T Comp, OrganComponent Organ)>();
-
-        foreach (var organ in GetPartOrgans(uid, part))
-        {
-            if (query.TryGetComponent(organ.Id, out var comp))
-                list.Add((comp, organ.Component));
-        }
-
-        return list;
-    }
-
-    /// <summary>
-    ///     Tries to get a list of ValueTuples of <see cref="T"/> and OrganComponent on each organs
-    ///     in the given part.
-    /// </summary>
-    /// <param name="uid">The part entity id to check on.</param>
-    /// <param name="comps">The list of components.</param>
-    /// <param name="part">The part to check for organs on.</param>
-    /// <typeparam name="T">The component to check for.</typeparam>
-    /// <returns>Whether any were found.</returns>
-    public bool TryGetBodyPartOrganComponents<T>(
-        EntityUid uid,
-        [NotNullWhen(true)] out List<(T Comp, OrganComponent Organ)>? comps,
-        BodyPartComponent? part = null)
-        where T : IComponent
-    {
-        if (!Resolve(uid, ref part))
-        {
-            comps = null;
-            return false;
-        }
-
-        comps = GetBodyPartOrganComponents<T>(uid, part);
-
-        if (comps.Count != 0)
-            return true;
-
-        comps = null;
-        return false;
-    }
-
-    /// <summary>
-    /// Gets the parent body part and all immediate child body parts for the partId.
-    /// </summary>
-    public IEnumerable<EntityUid> GetBodyPartAdjacentParts(
-        EntityUid partId,
-        BodyPartComponent? part = null)
-    {
-        if (!Resolve(partId, ref part, logMissing: false))
-            yield break;
-
-        if (TryGetParentBodyPart(partId, out var parentUid, out _))
-            yield return parentUid.Value;
-
-        foreach (var slotId in part.Children.Keys)
-        {
-            var container = Containers.GetContainer(partId, GetPartSlotContainerId(slotId));
-
-            foreach (var containedEnt in container.ContainedEntities)
-            {
-                yield return containedEnt;
-            }
-        }
-    }
-
-    public IEnumerable<(EntityUid AdjacentId, T Component)> GetBodyPartAdjacentPartsComponents<T>(
-        EntityUid partId,
-        BodyPartComponent? part = null)
-        where T : IComponent
-    {
-        if (!Resolve(partId, ref part, logMissing: false))
-            yield break;
-
-        var query = GetEntityQuery<T>();
-        foreach (var adjacentId in GetBodyPartAdjacentParts(partId, part))
-        {
-            if (query.TryGetComponent(adjacentId, out var component))
-                yield return (adjacentId, component);
-        }
-    }
-
-    public bool TryGetBodyPartAdjacentPartsComponents<T>(
-        EntityUid partId,
-        [NotNullWhen(true)] out List<(EntityUid AdjacentId, T Component)>? comps,
-        BodyPartComponent? part = null)
-        where T : IComponent
-    {
-        if (!Resolve(partId, ref part, logMissing: false))
-        {
-            comps = null;
-            return false;
-        }
-
-        var query = GetEntityQuery<T>();
-        comps = new List<(EntityUid AdjacentId, T Component)>();
-
-        foreach (var adjacentId in GetBodyPartAdjacentParts(partId, part))
-        {
-            if (query.TryGetComponent(adjacentId, out var component))
-                comps.Add((adjacentId, component));
-        }
-
-        if (comps.Count != 0)
-            return true;
-
-        comps = null;
-        return false;
-    }
-
-    #endregion
-}
diff --git a/Content.Shared/Body/Systems/SharedBodySystem.cs b/Content.Shared/Body/Systems/SharedBodySystem.cs
deleted file mode 100644 (file)
index f359ebc..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-using Content.Shared.Damage.Systems;
-using Content.Shared.Movement.Systems;
-using Content.Shared.Standing;
-using Robust.Shared.Containers;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Timing;
-
-namespace Content.Shared.Body.Systems;
-
-public abstract partial class SharedBodySystem : EntitySystem
-{
-    /*
-     * See the body partial for how this works.
-     */
-
-    /// <summary>
-    /// Container ID prefix for any body parts.
-    /// </summary>
-    public const string PartSlotContainerIdPrefix = "body_part_slot_";
-
-    /// <summary>
-    /// Container ID for the ContainerSlot on the body entity itself.
-    /// </summary>
-    public const string BodyRootContainerId = "body_root_part";
-
-    /// <summary>
-    /// Container ID prefix for any body organs.
-    /// </summary>
-    public const string OrganSlotContainerIdPrefix = "body_organ_slot_";
-
-    [Dependency] private   readonly IGameTiming _timing = default!;
-    [Dependency] protected readonly IPrototypeManager Prototypes = default!;
-    [Dependency] protected readonly DamageableSystem Damageable = default!;
-    [Dependency] protected readonly MovementSpeedModifierSystem Movement = default!;
-    [Dependency] protected readonly SharedContainerSystem Containers = default!;
-    [Dependency] protected readonly SharedTransformSystem SharedTransform = default!;
-    [Dependency] protected readonly StandingStateSystem Standing = default!;
-
-    public override void Initialize()
-    {
-        base.Initialize();
-
-        InitializeBody();
-        InitializeParts();
-    }
-
-    /// <summary>
-    /// Inverse of <see cref="GetPartSlotContainerId"/>
-    /// </summary>
-    protected static string? GetPartSlotContainerIdFromContainer(string containerSlotId)
-    {
-        // This is blursed
-        var slotIndex = containerSlotId.IndexOf(PartSlotContainerIdPrefix, StringComparison.Ordinal);
-
-        if (slotIndex < 0)
-            return null;
-
-        var slotId = containerSlotId.Remove(slotIndex, PartSlotContainerIdPrefix.Length);
-        return slotId;
-    }
-
-    /// <summary>
-    /// Gets the container Id for the specified slotId.
-    /// </summary>
-    public static string GetPartSlotContainerId(string slotId)
-    {
-        return PartSlotContainerIdPrefix + slotId;
-    }
-
-    /// <summary>
-    /// Gets the container Id for the specified slotId.
-    /// </summary>
-    public static string GetOrganContainerId(string slotId)
-    {
-        return OrganSlotContainerIdPrefix + slotId;
-    }
-}
index 3d8647b14d98ffc163303789b2f724436954c197..ef258d3fe01bd5e012cfd4497e73ffdf5a8163de 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Events;
-using Content.Shared.Body.Organ;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Components.SolutionManager;
 using Content.Shared.Chemistry.EntitySystems;
index a30387a807eacf0745a8bcbb9562fb302b140da0..3b5b07d3f94a35a80f1475500334a925283639ff 100644 (file)
@@ -2,7 +2,7 @@ using Content.Shared.Actions;
 using Content.Shared.Administration.Logs;
 using Content.Shared.Armor;
 using Content.Shared.Atmos.Rotting;
-using Content.Shared.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.Changeling.Components;
 using Content.Shared.Damage.Components;
 using Content.Shared.Damage.Systems;
index dfe6d1377ba9eb69c87672af630f851cfb64fc7c..760c9f39d8b30764fe7fd6925dab8f2fda2e939c 100644 (file)
@@ -1,5 +1,4 @@
 using System.Linq;
-using Content.Shared.Body.Systems;
 using Content.Shared.Clothing.Components;
 using Content.Shared.Humanoid;
 using Content.Shared.Preferences;
@@ -29,7 +28,7 @@ public sealed class LoadoutSystem : EntitySystem
         base.Initialize();
 
         // Wait until the character has all their organs before we give them their loadout
-        SubscribeLocalEvent<LoadoutComponent, MapInitEvent>(OnMapInit, after: [typeof(SharedBodySystem)]);
+        SubscribeLocalEvent<LoadoutComponent, MapInitEvent>(OnMapInit);
     }
 
     public static string GetJobPrototype(string? loadout)
index 1365c488d88324ca1e219534eebf34ad851d801b..c493ca2c04d895717edbfb50cad0280a436b5208 100644 (file)
@@ -1,6 +1,3 @@
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
-
 namespace Content.Shared.Humanoid
 {
     public static class HumanoidVisualLayersExtension
@@ -72,72 +69,5 @@ namespace Content.Shared.Humanoid
                     yield break;
             }
         }
-
-        public static HumanoidVisualLayers? ToHumanoidLayers(this BodyPartComponent part)
-        {
-            switch (part.PartType)
-            {
-                case BodyPartType.Other:
-                    break;
-                case BodyPartType.Torso:
-                    return HumanoidVisualLayers.Chest;
-                case BodyPartType.Tail:
-                    return HumanoidVisualLayers.Tail;
-                case BodyPartType.Head:
-                    // use the Sublayers method to hide the rest of the parts,
-                    // if that's what you're looking for
-                    return HumanoidVisualLayers.Head;
-                case BodyPartType.Arm:
-                    switch (part.Symmetry)
-                    {
-                        case BodyPartSymmetry.None:
-                            break;
-                        case BodyPartSymmetry.Left:
-                            return HumanoidVisualLayers.LArm;
-                        case BodyPartSymmetry.Right:
-                            return HumanoidVisualLayers.RArm;
-                    }
-
-                    break;
-                case BodyPartType.Hand:
-                    switch (part.Symmetry)
-                    {
-                        case BodyPartSymmetry.None:
-                            break;
-                        case BodyPartSymmetry.Left:
-                            return HumanoidVisualLayers.LHand;
-                        case BodyPartSymmetry.Right:
-                            return HumanoidVisualLayers.RHand;
-                    }
-
-                    break;
-                case BodyPartType.Leg:
-                    switch (part.Symmetry)
-                    {
-                        case BodyPartSymmetry.None:
-                            break;
-                        case BodyPartSymmetry.Left:
-                            return HumanoidVisualLayers.LLeg;
-                        case BodyPartSymmetry.Right:
-                            return HumanoidVisualLayers.RLeg;
-                    }
-
-                    break;
-                case BodyPartType.Foot:
-                    switch (part.Symmetry)
-                    {
-                        case BodyPartSymmetry.None:
-                            break;
-                        case BodyPartSymmetry.Left:
-                            return HumanoidVisualLayers.LFoot;
-                        case BodyPartSymmetry.Right:
-                            return HumanoidVisualLayers.RFoot;
-                    }
-
-                    break;
-            }
-
-            return null;
-        }
     }
 }
index 7c2a3532fd49bc25320fd0697745cc19cc6f47dc..77f157fcddcfbb5b607d06f77be9dd3674302392 100644 (file)
@@ -1,9 +1,8 @@
 using System.Linq;
 using Content.Shared.Administration.Logs;
 using Content.Shared.Audio;
-using Content.Shared.Body.Components;
+using Content.Shared.Body;
 using Content.Shared.Database;
-using Content.Shared.Emag.Components;
 using Content.Shared.Emag.Systems;
 using Content.Shared.Examine;
 using Content.Shared.Mobs.Components;
index fe9db1896082b6cae9e715b8f6656868f4bf118c..ac1a00d5798e1784c67f80d12a9200769d31235d 100644 (file)
@@ -1,5 +1,6 @@
 using System.Linq;
 using Content.Shared.Administration.Logs;
+using Content.Shared.Body;
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Systems;
 using Content.Shared.Chemistry;
index bdde1f0c98b694cdf95506c44f535c53b39e71fa..75d3f116bdfb3a2ce3d131c3f84f3f84d15e1fbd 100644 (file)
@@ -1,3 +1,4 @@
+using Content.Shared.Body;
 using Content.Shared.Body.Components;
 using Content.Shared.Body.Systems;
 using Content.Shared.Chemistry.Components;
@@ -28,7 +29,6 @@ public sealed class VomitSystem : EntitySystem
     [Dependency] private readonly ThirstSystem _thirst = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly SharedBloodstreamSystem _bloodstream = default!;
-    [Dependency] private readonly SharedBodySystem _body = default!;
     [Dependency] private readonly SharedForensicsSystem _forensics = default!;
     [Dependency] private readonly SharedPopupSystem _popup = default!;
     [Dependency] private readonly SharedPuddleSystem _puddle = default!;
@@ -38,7 +38,7 @@ public sealed class VomitSystem : EntitySystem
     {
         base.Initialize();
 
-        SubscribeLocalEvent<BodyComponent, TryVomitEvent>(TryBodyVomitSolution);
+        SubscribeLocalEvent<StomachComponent, BodyRelayedEvent<TryVomitEvent>>(TryVomitSolution);
     }
 
     private const float ChemMultiplier = 0.1f;
@@ -50,24 +50,12 @@ public sealed class VomitSystem : EntitySystem
     private readonly SoundSpecifier _vomitSound = new SoundCollectionSpecifier(VomitCollection,
         AudioParams.Default.WithVariation(0.2f).WithVolume(-4f));
 
-    private void TryBodyVomitSolution(Entity<BodyComponent> ent, ref TryVomitEvent args)
+    private void TryVomitSolution(Entity<StomachComponent> ent, ref BodyRelayedEvent<TryVomitEvent> args)
     {
-        if (args.Handled)
-            return;
-
-        // Main requirement: You have a stomach
-        var stomachList = _body.GetBodyOrganEntityComps<StomachComponent>((ent, null));
-        if (stomachList.Count == 0)
-            return;
-
-        // Empty the stomach out into it
-        foreach (var stomach in stomachList)
-        {
-            if (_solutionContainer.ResolveSolution(stomach.Owner, StomachSystem.DefaultSolutionName, ref stomach.Comp1.Solution, out var sol))
-                _solutionContainer.TryTransferSolution(stomach.Comp1.Solution.Value, args.Sol, sol.AvailableVolume);
-        }
+        if (_solutionContainer.ResolveSolution(ent.Owner, StomachSystem.DefaultSolutionName, ref ent.Comp.Solution, out var sol))
+            _solutionContainer.TryTransferSolution(ent.Comp.Solution.Value, args.Args.Sol, sol.AvailableVolume);
 
-        args.Handled = true;
+        args.Args = args.Args with { Handled = true };
     }
 
     /// <summary>
index ae10110ebc2736539f01496840d89cb95f713e3d..586c4f5bfdc1bb7bfea7a99e9528ff3dc9c57ac8 100644 (file)
@@ -1,6 +1,6 @@
 using Content.Shared.Administration.Logs;
+using Content.Shared.Body;
 using Content.Shared.Body.Components;
-using Content.Shared.Body.Organ;
 using Content.Shared.Body.Systems;
 using Content.Shared.Chemistry;
 using Content.Shared.Chemistry.Components;
@@ -57,7 +57,7 @@ public sealed partial class IngestionSystem : EntitySystem
     [Dependency] private readonly SharedTransformSystem _transform = default!;
 
     // Body Component Dependencies
-    [Dependency] private readonly SharedBodySystem _body = default!;
+    [Dependency] private readonly BodySystem _body = default!;
     [Dependency] private readonly ReactiveSystem _reaction = default!;
     [Dependency] private readonly StomachSystem _stomach = default!;
 
@@ -178,7 +178,7 @@ public sealed partial class IngestionSystem : EntitySystem
     /// <param name="food">Entity being eaten</param>
     /// <param name="stomachs">Stomachs available to digest</param>
     /// <param name="popup">Should we also display popup text if it exists?</param>
-    public bool IsDigestibleBy(EntityUid food, List<Entity<StomachComponent, OrganComponent>> stomachs, out bool popup)
+    public bool IsDigestibleBy(EntityUid food, List<Entity<StomachComponent>> stomachs, out bool popup)
     {
         popup = false;
         var ev = new IsDigestibleEvent();
@@ -195,7 +195,7 @@ public sealed partial class IngestionSystem : EntitySystem
             foreach (var ent in stomachs)
             {
                 // We need one stomach that can digest our special food.
-                if (_whitelistSystem.IsWhitelistPass(ent.Comp1.SpecialDigestible, food))
+                if (_whitelistSystem.IsWhitelistPass(ent.Comp.SpecialDigestible, food))
                     return true;
             }
         }
@@ -204,9 +204,9 @@ public sealed partial class IngestionSystem : EntitySystem
             foreach (var ent in stomachs)
             {
                 // We need one stomach that can digest normal food.
-                if (ent.Comp1.SpecialDigestible == null
-                    || !ent.Comp1.IsSpecialDigestibleExclusive
-                    || _whitelistSystem.IsWhitelistPass(ent.Comp1.SpecialDigestible, food))
+                if (ent.Comp.SpecialDigestible == null
+                    || !ent.Comp.IsSpecialDigestibleExclusive
+                    || _whitelistSystem.IsWhitelistPass(ent.Comp.SpecialDigestible, food))
                     return true;
             }
         }
@@ -221,7 +221,7 @@ public sealed partial class IngestionSystem : EntitySystem
     /// </summary>
     /// <param name="food">Entity being eaten</param>
     /// <param name="stomach">Stomachs that is attempting to digest.</param>
-    public bool IsDigestibleBy(EntityUid food, Entity<StomachComponent, OrganComponent> stomach)
+    public bool IsDigestibleBy(EntityUid food, Entity<StomachComponent> stomach)
     {
         var ev = new IsDigestibleEvent();
         RaiseLocalEvent(food, ref ev);
@@ -233,9 +233,9 @@ public sealed partial class IngestionSystem : EntitySystem
             return true;
 
         if (ev.SpecialDigestion)
-            return _whitelistSystem.IsWhitelistPass(stomach.Comp1.SpecialDigestible, food);
+            return _whitelistSystem.IsWhitelistPass(stomach.Comp.SpecialDigestible, food);
 
-        if (stomach.Comp1.SpecialDigestible == null || !stomach.Comp1.IsSpecialDigestibleExclusive || _whitelistSystem.IsWhitelistPass(stomach.Comp1.SpecialDigestible, food))
+        if (stomach.Comp.SpecialDigestible == null || !stomach.Comp.IsSpecialDigestibleExclusive || _whitelistSystem.IsWhitelistPass(stomach.Comp.SpecialDigestible, food))
             return true;
 
         return false;
@@ -246,7 +246,7 @@ public sealed partial class IngestionSystem : EntitySystem
         var food = args.Ingested;
         var forceFed = args.User != entity.Owner;
 
-        if (!_body.TryGetBodyOrganEntityComps<StomachComponent>(entity!, out var stomachs))
+        if (!_body.TryGetOrgansWithComponent<StomachComponent>(entity!, out var stomachs))
             return;
 
         // Can we digest the specific item we're trying to eat?
@@ -311,7 +311,7 @@ public sealed partial class IngestionSystem : EntitySystem
         if (!CanConsume(args.User, entity, food, out var solution, out _))
             return;
 
-        if (!_body.TryGetBodyOrganEntityComps<StomachComponent>(entity!, out var stomachs))
+        if (!_body.TryGetOrgansWithComponent<StomachComponent>(entity!, out var stomachs))
             return;
 
         var forceFed = args.User != entity.Owner;
@@ -321,7 +321,7 @@ public sealed partial class IngestionSystem : EntitySystem
         foreach (var ent in stomachs)
         {
             var owner = ent.Owner;
-            if (!_solutionContainer.ResolveSolution(owner, StomachSystem.DefaultSolutionName, ref ent.Comp1.Solution, out var stomachSol))
+            if (!_solutionContainer.ResolveSolution(owner, StomachSystem.DefaultSolutionName, ref ent.Comp.Solution, out var stomachSol))
                 continue;
 
             if (stomachSol.AvailableVolume <= highestAvailable)
index 929ee3a19fb79ee654bb1f9579c2a5248a7b039b..0ab661dce9748dd7db502125ebad857e9e4d4734 100644 (file)
@@ -1,5 +1,4 @@
-using Content.Shared.Body.Systems;
-using Content.Shared.Buckle.Components;
+using Content.Shared.Buckle.Components;
 using Content.Shared.Movement.Events;
 using Content.Shared.Movement.Systems;
 using Content.Shared.Standing;
@@ -11,7 +10,6 @@ public sealed class LegsParalyzedSystem : EntitySystem
 {
     [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
     [Dependency] private readonly StandingStateSystem _standingSystem = default!;
-    [Dependency] private readonly SharedBodySystem _bodySystem = default!;
 
     public override void Initialize()
     {
@@ -32,7 +30,6 @@ public sealed class LegsParalyzedSystem : EntitySystem
     private void OnShutdown(EntityUid uid, LegsParalyzedComponent component, ComponentShutdown args)
     {
         _standingSystem.Stand(uid);
-        _bodySystem.UpdateMovementSpeed(uid);
     }
 
     private void OnBuckled(EntityUid uid, LegsParalyzedComponent component, ref BuckledEvent args)
index 0603b3c8463f550a6399e240987d1edc28340e38..8d30ea1a5f3b7af9dbe659d53b80e93d0e192269 100644 (file)
@@ -5,9 +5,7 @@ microwave-component-interact-using-broken = It's broken!
 microwave-component-interact-using-container-full = Container is full
 microwave-component-interact-using-transfer-success = Transferred {$amount}u
 microwave-component-interact-using-transfer-fail = That won't work!
-microwave-component-suicide-multi-head-others-message = {$victim} is trying to cook their heads!
 microwave-component-suicide-others-message = {$victim} is trying to cook their head!
-microwave-component-suicide-multi-head-message = You cook your heads!
 microwave-component-suicide-message = You cook your head!
 microwave-component-interact-full = It's full.
 microwave-component-interact-item-too-big = { CAPITALIZE(THE($item)) } is too big to fit in the microwave!
index cbc2bdd9edbe01daec9b202c85b16e96430402d4..b44f212b9ed845df8c85afb286d84e3167e28ca2 100644 (file)
@@ -1983,14 +1983,14 @@ entities:
     - type: Transform
       pos: 7.5,6.5
       parent: 16
-- proto: LeftArmSkeleton
+- proto: OrganSkeletonPersonArmLeft
   entities:
   - uid: 175
     components:
     - type: Transform
       pos: 6.8180027,-5.7761726
       parent: 16
-- proto: LeftHandSkeleton
+- proto: OrganSkeletonPersonHandLeft
   entities:
   - uid: 174
     components:
diff --git a/Resources/Prototypes/Body/Animals/animal.yml b/Resources/Prototypes/Body/Animals/animal.yml
new file mode 100644 (file)
index 0000000..bf8d15c
--- /dev/null
@@ -0,0 +1,55 @@
+- type: entity
+  id: OrganAnimalMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Animal ]
+
+- type: entity
+  parent: OrganBase
+  id: OrganAnimal
+  abstract: true
+  suffix: Animal
+
+- type: entity
+  parent: OrganAnimal
+  id: OrganAnimalInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/organs.rsi
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganAnimalInternal, OrganAnimalMetabolizer ]
+  id: OrganAnimalLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganAnimalInternal, OrganAnimalMetabolizer ]
+  id: OrganAnimalHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganAnimalInternal, OrganAnimalMetabolizer ]
+  id: OrganAnimalStomach
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganAnimalInternal, OrganAnimalMetabolizer ]
+  id: OrganAnimalLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganAnimalInternal, OrganAnimalMetabolizer ]
+  id: OrganAnimalKidneys
+
+- type: entity
+  id: BaseMobAnimal
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganAnimalLungs
+        - id: OrganAnimalHeart
+        - id: OrganAnimalStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Animals/bloodsucker.yml b/Resources/Prototypes/Body/Animals/bloodsucker.yml
new file mode 100644 (file)
index 0000000..cfe8c1b
--- /dev/null
@@ -0,0 +1,34 @@
+- type: entity
+  id: OrganBloodsucker
+  abstract: true
+  suffix: bloodsucker
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Bloodsucker ]
+
+- type: entity
+  id: OrganBloodsuckerStomach
+  parent: [ OrganBloodsucker, OrganAnimalStomach ]
+
+- type: entity
+  id: OrganBloodsuckerLiver
+  parent: [ OrganBloodsucker, OrganAnimalLiver ]
+
+- type: entity
+  id: OrganBloodsuckerHeart
+  parent: [ OrganBloodsucker, OrganAnimalHeart ]
+
+- type: entity
+  id: BaseMobBloodsucker
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganAnimalLungs
+        - id: OrganBloodsuckerHeart
+        - id: OrganBloodsuckerStomach
+        - id: OrganBloodsuckerLiver
+        - id: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Animals/hemocyanin.yml b/Resources/Prototypes/Body/Animals/hemocyanin.yml
new file mode 100644 (file)
index 0000000..aa30930
--- /dev/null
@@ -0,0 +1,14 @@
+- type: entity
+  id: BaseMobHemocyanin
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganAnimalLungs
+        - id: OrganArachnidHeart
+        - id: OrganAnimalStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Animals/mothroach.yml b/Resources/Prototypes/Body/Animals/mothroach.yml
new file mode 100644 (file)
index 0000000..679639b
--- /dev/null
@@ -0,0 +1,14 @@
+- type: entity
+  id: BaseMobMothroach
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganAnimalLungs
+        - id: OrganAnimalHeart
+        - id: OrganMothStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Animals/rat.yml b/Resources/Prototypes/Body/Animals/rat.yml
new file mode 100644 (file)
index 0000000..e8bf585
--- /dev/null
@@ -0,0 +1,22 @@
+- type: entity
+  parent: OrganAnimalLungs
+  id: OrganRatLungs
+  suffix: Rat
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Rat ]
+
+- type: entity
+  id: BaseMobRat
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganRatLungs
+        - id: OrganAnimalHeart
+        - id: OrganAnimalStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Animals/ruminant.yml b/Resources/Prototypes/Body/Animals/ruminant.yml
new file mode 100644 (file)
index 0000000..a6ca809
--- /dev/null
@@ -0,0 +1,30 @@
+- type: entity
+  parent: [ OrganBaseStomach, OrganAnimalInternal, OrganAnimalMetabolizer ]
+  id: OrganRuminantStomach
+  suffix: Ruminant
+  components:
+  - type: Stomach
+    specialDigestible:
+      tags:
+      - Ruminant
+      - Wheat
+      - BananaPeel
+  - type: SolutionContainerManager
+    solutions:
+      stomach:
+        maxVol: 80
+
+- type: entity
+  id: BaseMobRuminant
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganAnimalLungs
+        - id: OrganAnimalHeart
+        - id: OrganRuminantStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Animals/slimes.yml b/Resources/Prototypes/Body/Animals/slimes.yml
new file mode 100644 (file)
index 0000000..6d02864
--- /dev/null
@@ -0,0 +1,11 @@
+- type: entity
+  id: BaseMobSlimes
+  abstract: true
+  components:
+  - type: Body
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganSlimePersonCore
+        - id: OrganSlimePersonLungs
diff --git a/Resources/Prototypes/Body/Organs/Animal/animal.yml b/Resources/Prototypes/Body/Organs/Animal/animal.yml
deleted file mode 100644 (file)
index b319044..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-- type: entity
-  id: BaseAnimalOrgan
-  parent: BaseItem
-  abstract: true
-  components:
-  - type: Organ
-  - type: Edible
-  - type: Sprite
-    sprite: Mobs/Species/Human/organs.rsi
-  - type: StaticPrice
-    price: 50
-  - type: SolutionContainerManager
-    solutions:
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: FlavorProfile
-    flavors:
-      - chicken # everything kinda tastes like chicken
-  - type: Tag
-    tags:
-      - Meat
-
-- type: entity
-  id: OrganAnimalLungs
-  parent: BaseAnimalOrgan
-  name: animal lungs
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: lung-l
-    - state: lung-r
-  - type: Organ
-  - type: Lung
-  - type: Metabolizer
-    removeEmpty: true
-    solutionOnBody: false
-    solution: "Lung"
-    metabolizerTypes: [ Animal ]
-    groups:
-    - id: Gas
-      rateModifier: 100.0
-  - type: SolutionContainerManager
-    solutions:
-      Lung:
-        maxVol: 100.0
-        canReact: false
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Item
-    size: Small
-    heldPrefix: lungs
-
-- type: entity
-  id: OrganAnimalStomach
-  parent: BaseAnimalOrgan
-  name: animal stomach
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    state: stomach
-  - type: Organ
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 40
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Stomach
-  - type: Metabolizer
-    maxReagents: 3
-    metabolizerTypes: [ Animal ]
-    groups:
-    - id: Food
-    - id: Drink
-  - type: Item
-    size: Small
-    heldPrefix: stomach
-
-- type: entity
-  id: OrganMouseStomach
-  parent: OrganAnimalStomach
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 30
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Item
-    size: Small
-    heldPrefix: stomach
-
-- type: entity
-  id: OrganAnimalLiver
-  parent: BaseAnimalOrgan
-  name: animal liver
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    state: liver
-  - type: Organ
-  - type: Metabolizer
-    maxReagents: 1
-    metabolizerTypes: [ Animal ]
-    groups:
-    - id: Alcohol
-  - type: Item
-    size: Small
-    heldPrefix: liver
-
-- type: entity
-  id: OrganAnimalHeart
-  parent: BaseAnimalOrgan
-  name: animal heart
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    state: heart-on
-  - type: Organ
-  - type: Metabolizer
-    maxReagents: 2
-    metabolizerTypes: [ Animal ]
-    groups:
-    - id: Medicine
-    - id: Poison
-    - id: Narcotic
-  - type: Item
-    size: Small
-    heldPrefix: heart
-
-- type: entity
-  id: OrganAnimalKidneys
-  parent: BaseAnimalOrgan
-  name: animal kidneys
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: kidney-l
-    - state: kidney-r
-  - type: Organ
-  - type: Metabolizer
-    maxReagents: 5
-    metabolizerTypes: [ Animal ]
-    removeEmpty: true
-  - type: Item
-    size: Small
-    heldPrefix: kidneys
diff --git a/Resources/Prototypes/Body/Organs/Animal/bloodsucker.yml b/Resources/Prototypes/Body/Organs/Animal/bloodsucker.yml
deleted file mode 100644 (file)
index 6e9b4d5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-- type: entity
-  id: OrganBloodsuckerStomach
-  parent: OrganAnimalStomach
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [ Bloodsucker ]
-
-- type: entity
-  id: OrganBloodsuckerLiver
-  parent: OrganAnimalLiver
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [ Bloodsucker ]
-
-- type: entity
-  id: OrganBloodsuckerHeart
-  parent: OrganAnimalHeart
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [ Bloodsucker ]
diff --git a/Resources/Prototypes/Body/Organs/Animal/ruminant.yml b/Resources/Prototypes/Body/Organs/Animal/ruminant.yml
deleted file mode 100644 (file)
index 3dd34f1..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-- type: entity
-  id: OrganAnimalRuminantStomach
-  parent: OrganAnimalStomach
-  name: ruminant stomach
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Stomach
-    specialDigestible:
-      tags:
-      - Ruminant
-      - Wheat
-      - BananaPeel
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 80
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
diff --git a/Resources/Prototypes/Body/Organs/Animal/slimes.yml b/Resources/Prototypes/Body/Organs/Animal/slimes.yml
deleted file mode 100644 (file)
index 0c72945..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-- type: entity
-  id: SentientSlimesCore
-  parent: [BaseItem, OrganHumanBrain]
-  name: sentient slimes core
-  description: "The source of incredible, unending gooeyness."
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/organs.rsi
-      state: brain-slime
-    - type: Stomach
-    - type: Metabolizer
-      maxReagents: 3
-      metabolizerTypes: [ Slime ]
-      removeEmpty: true
-      groups:
-        - id: Food
-        - id: Drink
-        - id: Medicine
-        - id: Poison
-        - id: Narcotic
-        - id: Alcohol
-          rateModifier: 2
-    - type: SolutionContainerManager
-      solutions:
-        stomach:
-          maxVol: 30.0
-        food:
-          maxVol: 5
-          reagents:
-          - ReagentId: GreyMatter
-            Quantity: 5
-
-- type: entity
-  id: OrganSlimesLungs
-  parent: BaseHumanOrgan
-  name: slimes gas sacs
-  description: "Collects nitrogen, which slime cells use for maintenance."
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/organs.rsi
-      layers:
-        - state: lung-l-slime
-        - state: lung-r-slime
-    - type: Lung
-      alert: LowNitrogen
-    - type: Metabolizer
-      removeEmpty: true
-      solutionOnBody: false
-      solution: "Lung"
-      metabolizerTypes: [ Slime ]
-      groups:
-      - id: Gas
-        rateModifier: 100.0
-    - type: SolutionContainerManager
-      solutions:
-        organ:
-          reagents:
-          - ReagentId: Nutriment
-            Quantity: 10
-        Lung:
-          maxVol: 100.0
-          canReact: false
-        food:
-          maxVol: 5
-          reagents:
-          - ReagentId: Slime
-            Quantity: 5
diff --git a/Resources/Prototypes/Body/Organs/arachnid.yml b/Resources/Prototypes/Body/Organs/arachnid.yml
deleted file mode 100644 (file)
index 337ead6..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-- type: entity
-  id: BaseArachnidOrgan
-  parent: BaseItem
-  abstract: true
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/organs.rsi
-  - type: Organ
-  - type: Edible
-  - type: Extractable
-    grindableSolutionName: organ
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        maxVol: 10
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Tag
-    tags:
-      - Meat
-
-- type: entity
-  id: OrganArachnidStomach
-  parent: OrganAnimalStomach
-  description: "Gross. This is hard to stomach."
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/organs.rsi
-    state: stomach
-  - type: Item
-    size: Small
-    heldPrefix: stomach
-  - type: Stomach
-    digestionDelay: 30
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Metabolizer
-    updateInterval: 1.5
-
-- type: entity
-  id: OrganArachnidLungs
-  parent: BaseArachnidOrgan
-  name: lungs
-  description: "Filters oxygen from an atmosphere... just more greedily."
-  components:
-  - type: Sprite
-    layers:
-      - state: lung-l
-      - state: lung-r
-  - type: Lung
-  - type: Metabolizer
-    updateInterval: 1.5
-    removeEmpty: true
-    solutionOnBody: false
-    solution: "Lung"
-    metabolizerTypes: [ Human ]
-    groups:
-    - id: Gas
-      rateModifier: 100.0
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      Lung:
-        maxVol: 100.0
-        canReact: false
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-
-- type: entity
-  id: OrganArachnidHeart
-  parent: BaseArachnidOrgan
-  name: heart
-  description: "A disgustingly persistent little biological pump made for spiders."
-  components:
-  - type: Sprite
-    state: heart-on
-  - type: Item
-    size: Small
-    heldPrefix: heart
-  - type: Metabolizer
-    updateInterval: 1.5
-    maxReagents: 2
-    metabolizerTypes: [Arachnid]
-    groups:
-    - id: Medicine
-    - id: Poison
-    - id: Narcotic
-
-- type: entity
-  id: OrganArachnidLiver
-  parent: BaseHumanOrgan
-  name: liver
-  description: "Pairing suggestion: chianti and fava beans."
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Item
-    size: Small
-    heldPrefix: liver
-  - type: Sprite
-    state: liver
-  - type: Metabolizer # The liver metabolizes certain chemicals only, like alcohol.
-    updateInterval: 1.5
-    maxReagents: 1
-    metabolizerTypes: [Animal]
-    groups:
-    - id: Alcohol
-
-- type: entity
-  id: OrganArachnidKidneys
-  parent: BaseHumanOrgan
-  name: kidneys
-  description: "Filters toxins from the bloodstream."
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-      - state: kidney-l
-      - state: kidney-r
-  # The kidneys just remove anything that doesn't currently have any metabolisms, as a stopgap.
-  - type: Item
-    size: Small
-    heldPrefix: kidneys
-  - type: Metabolizer
-    updateInterval: 1.5
-    maxReagents: 5
-    metabolizerTypes: [Animal]
-    removeEmpty: true
-
-- type: entity
-  id: OrganArachnidEyes
-  parent: BaseArachnidOrgan
-  name: eyes
-  description: "Two was already too many."
-  components:
-  - type: Sprite
-    layers:
-      - state: eyeball-l
-      - state: eyeball-r
-  - type: Item
-    size: Small
-    heldPrefix: eyeballs
-
-- type: entity
-  id: OrganArachnidTongue
-  parent: BaseArachnidOrgan
-  name: tongue
-  description: "A fleshy muscle mostly used for lying."
-  components:
-  - type: Sprite
-    state: tongue
diff --git a/Resources/Prototypes/Body/Organs/diona.yml b/Resources/Prototypes/Body/Organs/diona.yml
deleted file mode 100644 (file)
index 81cee7c..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-- type: entity
-  id: BaseDionaOrgan
-  parent: BaseItem
-  abstract: true
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Diona/organs.rsi
-  - type: Organ
-  - type: Edible
-  - type: Extractable
-    grindableSolutionName: organ
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        maxVol: 10
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: Cellulose
-          Quantity: 5
-  - type: FlavorProfile
-    flavors:
-      - people
-
-- type: entity
-  id: OrganDionaBrain
-  parent: [BaseDionaOrgan, OrganHumanBrain]
-  name: brain
-  description: "The central hub of a diona's pseudo-neurological activity, its root-like tendrils search for its former body."
-  components:
-  - type: Item
-    size: Small
-    heldPrefix: brain
-  - type: Sprite
-    state: brain
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        maxVol: 10
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      Lung:
-        maxVol: 100
-        canReact: False
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: GreyMatter
-          Quantity: 5
-
-- type: entity
-  id: OrganDionaEyes
-  parent: BaseDionaOrgan
-  name: eyes
-  description: "I see you!"
-  components:
-  - type: Sprite
-    layers:
-      - state: eyeball-l
-      - state: eyeball-r
-
-- type: entity
-  id: OrganDionaStomach
-  parent: BaseDionaOrgan
-  name: stomach
-  description: "The diona's equivalent of a stomach, it reeks of asparagus and vinegar."
-  components:
-  - type: Sprite
-    state: stomach
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: Cellulose
-          Quantity: 5
-  - type: Stomach
-  - type: Metabolizer
-    maxReagents: 6
-    metabolizerTypes: [ Plant ]
-    removeEmpty: true
-    groups:
-      - id: Food
-      - id: Drink
-      - id: Medicine
-      - id: Poison
-      - id: Narcotic
-      - id: Alcohol
-  - type: Item
-    size: Small
-    heldPrefix: stomach
-
-- type: entity
-  id: OrganDionaLungs
-  parent: BaseDionaOrgan
-  name: lungs
-  description: "A spongy mess of slimy, leaf-like structures. Capable of breathing both carbon dioxide and oxygen."
-  components:
-  - type: Sprite
-    state: lungs
-  - type: Item
-    size: Small
-    heldPrefix: lungs
-  - type: Lung
-  - type: Metabolizer
-    removeEmpty: true
-    solutionOnBody: false
-    solution: "Lung"
-    metabolizerTypes: [ Plant ]
-    groups:
-    - id: Gas
-      rateModifier: 100.0
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        maxVol: 10
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      Lung:
-        maxVol: 100
-        canReact: False
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: Cellulose
-          Quantity: 5
-
-# Organs that turn into nymphs on removal
-- type: entity
-  id: OrganDionaBrainNymph
-  parent: OrganDionaBrain
-  categories: [ HideSpawnMenu ]
-  name: brain
-  description: "The source of incredible, unending intelligence. Honk."
-  components:
-  - type: Brain
-  - type: Nymph # This will make the organs turn into a nymph when they're removed.
-    entityPrototype: OrganDionaNymphBrain
-    transferMind: true
-
-- type: entity
-  id: OrganDionaStomachNymph
-  parent: OrganDionaStomach
-  categories: [ HideSpawnMenu ]
-  name: stomach
-  description: "Gross. This is hard to stomach."
-  components:
-  - type: Nymph
-    entityPrototype: OrganDionaNymphStomach
-
-- type: entity
-  id: OrganDionaLungsNymph
-  parent: OrganDionaLungs
-  categories: [ HideSpawnMenu ]
-  name: lungs
-  description: "Filters oxygen from an atmosphere, which is then sent into the bloodstream to be used as an electron carrier."
-  components:
-  - type: Nymph
-    entityPrototype: OrganDionaNymphLungs
-
-# Nymphs that the organs will turn into
-- type: entity
-  id: OrganDionaNymphBrain
-  parent: MobDionaNymph
-  categories: [ HideSpawnMenu ]
-  name: diona nymph
-  suffix: Brain
-  description: Contains the brain of a formerly fully-formed Diona. Killing this would kill the Diona forever. You monster.
-  components:
-  - type: IsDeadIC
-  - type: Body
-    prototype: AnimalNymphBrain
-
-- type: entity
-  id: OrganDionaNymphStomach
-  parent: MobDionaNymphAccent
-  categories: [ HideSpawnMenu ]
-  name: diona nymph
-  suffix: Stomach
-  description: Contains the stomach of a formerly fully-formed Diona. It doesn't taste any better for it.
-  components:
-  - type: IsDeadIC
-  - type: Body
-    prototype: AnimalNymphStomach
-
-- type: entity
-  id: OrganDionaNymphLungs
-  parent: MobDionaNymphAccent
-  categories: [ HideSpawnMenu ]
-  name: diona nymph
-  suffix: Lungs
-  description: Contains the lungs of a formerly fully-formed Diona. Breathtaking.
-  components:
-  - type: IsDeadIC
-  - type: Body
-    prototype: AnimalNymphLungs
diff --git a/Resources/Prototypes/Body/Organs/dwarf.yml b/Resources/Prototypes/Body/Organs/dwarf.yml
deleted file mode 100644 (file)
index 8da0cb1..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-- type: entity
-  id: OrganDwarfHeart
-  parent: OrganHumanHeart
-  name: dwarf heart
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [Dwarf]
-
-- type: entity
-  id: OrganDwarfLiver
-  parent: OrganHumanLiver
-  name: dwarf liver
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [Dwarf]
-
-- type: entity
-  id: OrganDwarfStomach
-  parent: OrganHumanStomach
-  name: dwarf stomach
-  components:
-  - type: Sprite
-    state: stomach
-  - type: Organ
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 75
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Stomach
-  - type: Metabolizer
-    # mm very yummy
-    maxReagents: 5
-    metabolizerTypes: [Dwarf]
diff --git a/Resources/Prototypes/Body/Organs/human.yml b/Resources/Prototypes/Body/Organs/human.yml
deleted file mode 100644 (file)
index c12df45..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-- type: entity
-  id: BaseHumanOrgan
-  parent: BaseItem
-  abstract: true
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/organs.rsi
-  - type: Organ
-  - type: Edible
-  - type: Extractable
-    grindableSolutionName: organ
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: FlavorProfile
-    flavors:
-      - people
-  - type: Tag
-    tags:
-      - Meat
-
-- type: entity
-  id: OrganHumanBrain
-  parent: BaseHumanOrgan
-  name: brain
-  description: "The source of incredible, unending intelligence. Honk."
-  components:
-  - type: Sprite
-    state: brain
-  - type: Organ
-  - type: Input
-    context: "ghost"
-  - type: Brain
-  - type: InputMover
-  - type: Examiner
-  - type: BlockMovement
-  - type: BadFood
-  - type: Tag
-    tags:
-      - Meat
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: GreyMatter
-          Quantity: 5
-  - type: FlavorProfile
-    flavors:
-      - people
-  - type: FoodSequenceElement
-    entries:
-      Burger: Brain
-      Taco: Brain
-  - type: Item
-    size: Small
-    heldPrefix: brain
-
-- type: entity
-  id: OrganHumanEyes
-  parent: BaseHumanOrgan
-  name: eyes
-  description: "I see you!"
-  components:
-  - type: Sprite
-    layers:
-      - state: eyeball-l
-      - state: eyeball-r
-  - type: Item
-    size: Small
-    heldPrefix: eyeballs
-
-- type: entity
-  id: OrganHumanTongue
-  parent: BaseHumanOrgan
-  name: tongue
-  description: "A fleshy muscle mostly used for lying."
-  components:
-  - type: Sprite
-    state: tongue
-
-- type: entity
-  id: OrganHumanAppendix
-  parent: BaseHumanOrgan
-  name: appendix
-  components:
-  - type: Sprite
-    layers:
-    - state: appendix
-    - state: appendix-inflamed
-      visible: false
-
-- type: entity
-  id: OrganHumanEars
-  parent: BaseHumanOrgan
-  name: ears
-  description: "There are three parts to the ear. Inner, middle and outer. Only one of these parts should normally be visible."
-  components:
-  - type: Sprite
-    state: ears
-
-- type: entity
-  id: OrganHumanLungs
-  parent: BaseHumanOrgan
-  name: lungs
-  description: "Filters oxygen from an atmosphere, which is then sent into the bloodstream to be used as an electron carrier."
-  components:
-  - type: Sprite
-    layers:
-      - state: lung-l
-      - state: lung-r
-  - type: Item
-    size: Small
-    heldPrefix: lungs
-  - type: Lung
-  - type: Metabolizer
-    removeEmpty: true
-    solutionOnBody: false
-    solution: "Lung"
-    metabolizerTypes: [ Human ]
-    groups:
-    - id: Gas
-      rateModifier: 100.0
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        reagents:
-        - ReagentId: Nutriment
-          Quantity: 10
-      Lung:
-        maxVol: 100.0
-        canReact: false
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-
-- type: entity
-  id: OrganHumanHeart
-  parent: BaseHumanOrgan
-  name: heart
-  description: "I feel bad for the heartless bastard who lost this."
-  components:
-  - type: Sprite
-    state: heart-on
-  # The heart 'metabolizes' medicines and poisons that aren't filtered out by other organs.
-  # This is done because these chemicals need to have some effect even if they aren't being filtered out of your body.
-  # You're technically 'immune to poison' without a heart, but.. uhh, you'll have bigger problems on your hands.
-  - type: Metabolizer
-    maxReagents: 2
-    metabolizerTypes: [Human]
-    groups:
-    - id: Medicine
-    - id: Poison
-    - id: Narcotic
-  - type: Item
-    size: Small
-    heldPrefix: heart
-
-- type: entity
-  id: OrganHumanStomach
-  parent: BaseHumanOrgan
-  name: stomach
-  description: "Gross. This is hard to stomach."
-  components:
-  - type: Sprite
-    state: stomach
-  - type: Item
-    size: Small
-    heldPrefix: stomach
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Stomach
-  # The stomach metabolizes stuff like foods and drinks.
-  # TODO: Have it work off of the ent's solution container, and move this
-  # to intestines instead.
-  - type: Metabolizer
-    # mm yummy
-    maxReagents: 3
-    metabolizerTypes: [Human]
-    groups:
-    - id: Food
-    - id: Drink
-
-- type: entity
-  id: OrganHumanLiver
-  parent: BaseHumanOrgan
-  name: liver
-  description: "Pairing suggestion: chianti and fava beans."
-  components:
-  - type: Sprite
-    state: liver
-  - type: Item
-    size: Small
-    heldPrefix: liver
-  - type: Metabolizer # The liver metabolizes certain chemicals only, like alcohol.
-    maxReagents: 1
-    metabolizerTypes: [Human]
-    groups:
-    - id: Alcohol
-
-- type: entity
-  id: OrganHumanKidneys
-  parent: BaseHumanOrgan
-  name: kidneys
-  description: "Filters toxins from the bloodstream."
-  components:
-  - type: Sprite
-    layers:
-      - state: kidney-l
-      - state: kidney-r
-  - type: Item
-    size: Small
-    heldPrefix: kidneys
-  # The kidneys just remove anything that doesn't currently have any metabolisms, as a stopgap.
-  - type: Metabolizer
-    maxReagents: 5
-    metabolizerTypes: [Human]
-    removeEmpty: true
diff --git a/Resources/Prototypes/Body/Organs/moth.yml b/Resources/Prototypes/Body/Organs/moth.yml
deleted file mode 100644 (file)
index 4bbe151..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-- type: entity
-  id: OrganMothStomach
-  parent: [OrganAnimalStomach, OrganHumanStomach]
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Stomach
-    specialDigestible:
-      tags:
-      - ClothMade
-      - Paper
-      - Pill
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Metabolizer
-    maxReagents: 3
-    metabolizerTypes: [ Moth ]
-    removeEmpty: true
-    groups:
-      - id: Food
-      - id: Drink
diff --git a/Resources/Prototypes/Body/Organs/rat.yml b/Resources/Prototypes/Body/Organs/rat.yml
deleted file mode 100644 (file)
index 9d1352c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-- type: entity
-  id: OrganRatLungs
-  parent: OrganHumanLungs
-  suffix: "rat"
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [ Rat ]
-
-- type: entity
-  id: OrganRatStomach
-  parent: OrganAnimalStomach
-  suffix: "rat"
-  components:
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Sprite
-    state: stomach
diff --git a/Resources/Prototypes/Body/Organs/reptilian.yml b/Resources/Prototypes/Body/Organs/reptilian.yml
deleted file mode 100644 (file)
index 34c736a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-- type: entity
-  id: OrganReptilianStomach
-  parent: OrganAnimalStomach
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Stomach
-    specialDigestible:
-      tags:
-      - Fruit
-      - ReptilianFood
-      - Meat
-      - Pill
-      - Crayon
-      - Paper
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
diff --git a/Resources/Prototypes/Body/Organs/slime.yml b/Resources/Prototypes/Body/Organs/slime.yml
deleted file mode 100644 (file)
index 7f1a96a..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-- type: entity
-  id: SentientSlimeCore
-  parent: [BaseItem, OrganHumanBrain]
-  name: sentient slime core
-  description: "The source of incredible, unending gooeyness."
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/organs.rsi
-      state: brain-slime
-    - type: Stomach
-    - type: Metabolizer
-      maxReagents: 6
-      metabolizerTypes: [ Slime ]
-      removeEmpty: true
-      groups:
-        - id: Food
-        - id: Drink
-        - id: Medicine
-        - id: Poison
-        - id: Narcotic
-        - id: Alcohol
-          rateModifier: 2.5
-    - type: SolutionContainerManager
-      solutions:
-        stomach:
-          maxVol: 50.0
-        food:
-          maxVol: 5
-          reagents:
-          - ReagentId: GreyMatter
-            Quantity: 5
-        organ:
-          reagents:
-          - ReagentId: Slime
-            Quantity: 10
-    - type: Item
-      size: Small
-      heldPrefix: brain
-
-
-- type: entity
-  id: OrganSlimeLungs
-  parent: BaseHumanOrgan
-  name: slime gas sacs
-  description: "Collects nitrogen, which slime cells use for maintenance."
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Slime/organs.rsi
-    layers:
-      - state: lung-l-slime
-      - state: lung-r-slime
-  - type: Lung
-    alert: LowNitrogen
-  - type: Metabolizer
-    removeEmpty: true
-    solutionOnBody: false
-    solution: "Lung"
-    metabolizerTypes: [ Slime ]
-    groups:
-    - id: Gas
-      rateModifier: 100.0
-  - type: SolutionContainerManager
-    solutions:
-      organ:
-        reagents:
-        - ReagentId: Slime
-          Quantity: 10
-      Lung:
-        maxVol: 100.0
-        canReact: false
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
-  - type: Item
-    size: Small
-    heldPrefix: lungs
diff --git a/Resources/Prototypes/Body/Organs/vox.yml b/Resources/Prototypes/Body/Organs/vox.yml
deleted file mode 100644 (file)
index 4658300..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-- type: entity
-  id: OrganVoxLungs
-  parent: OrganHumanLungs
-  description: "The blue, anaerobic lungs of a vox, they intake nitrogen to breathe. Any form of gaseous oxygen is lethally toxic if breathed in."
-  suffix: "vox"
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-  - type: Metabolizer
-    metabolizerTypes: [ Vox ]
-  - type: Lung
-    alert: LowNitrogen
-  - type: Item
-    size: Small
-    heldPrefix: lungs
-
-- type: entity
-  parent: OrganHumanStomach
-  id: OrganVoxStomach
-  name: stomach
-  description: "A stomach that smells of ammonia."
-  components:
-  - type: Metabolizer #Skreeeee!
-    metabolizerTypes: [Vox]
-  - type: Stomach
-#Bird vs tags
-    specialDigestible:
-      tags:
-      - Trash
-    isSpecialDigestibleExclusive: false
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-
-- type: entity
-  parent: OrganHumanLiver
-  id: OrganVoxLiver
-  name: liver
-  description: "Smells flammable."
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [Vox]
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-
-- type: entity
-  parent: OrganHumanHeart
-  id: OrganVoxHeart
-  name: heart
-  description: "The strange heart of a vox."
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [Vox]
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-
-- type: entity
-  parent: OrganHumanKidneys
-  id: OrganVoxKidneys
-  name: kidney
-  description: "Smells flammable."
-  components:
-  - type: Metabolizer
-    metabolizerTypes: [Vox]
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-
-- type: entity
-  id: OrganVoxEyes
-  parent: OrganHumanEyes
-  name: eyes
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-  - type: Item
-    size: Small
-    heldPrefix: eyeballs
-
-- type: entity
-  id: OrganVoxTongueA
-  parent: OrganHumanTongue
-  name: tongue
-  description: "A fleshy muscle mostly used for screaming."
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-  - type: Item
-    size: Small
-
-- type: entity
-  id: OrganVoxTongueB
-  parent: OrganHumanTongue
-  name: tongue
-  description: "A fleshy muscle mostly used for screaming."
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Vox/organs.rsi
-  - type: Item
-    size: Small
diff --git a/Resources/Prototypes/Body/Organs/vulpkanin.yml b/Resources/Prototypes/Body/Organs/vulpkanin.yml
deleted file mode 100644 (file)
index a689262..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-- type: entity
-  id: OrganVulpkaninStomach
-  parent: OrganAnimalStomach
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: SolutionContainerManager
-    solutions:
-      stomach:
-        maxVol: 50
-      food:
-        maxVol: 5
-        reagents:
-        - ReagentId: UncookedAnimalProteins
-          Quantity: 5
diff --git a/Resources/Prototypes/Body/Parts/animal.yml b/Resources/Prototypes/Body/Parts/animal.yml
deleted file mode 100644 (file)
index 9672b09..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-# Just copypasta of some human basic body parts for interaction,
-# only differences for now is that limbs work in pairs,
-# they are unextractable and can't be spawned (no surgery on Animals!?).
-
-- type: entity
-  id: PartAnimal
-  parent: BaseItem
-  name: "animal body part"
-  abstract: true
-  components:
-  # yes these sprites dont make sense i dont care its better than them being invisible
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-  - type: Damageable
-    damageContainer: Biological
-  - type: BodyPart
-  - type: ContainerContainer
-    containers:
-      bodypart: !type:Container
-        ents: []
-  - type: StaticPrice
-    price: 50
-  - type: Tag
-    tags:
-      - Trash
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 3
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: HandsAnimal
-  name: animal hands
-  parent: PartAnimal
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: l_hand
-    - state: r_hand
-  - type: BodyPart
-    partType: Hand
-    symmetry: Left
-
-- type: entity
-  id: LegsAnimal
-  name: animal legs
-  parent: PartAnimal
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: l_leg
-    - state: r_leg
-  - type: BodyPart
-    partType: Leg
-  - type: MovementBodyPart
-
-- type: entity
-  id: FeetAnimal
-  name: animal feet
-  parent: PartAnimal
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: r_foot
-    - state: l_foot
-  - type: BodyPart
-    partType: Foot
-
-- type: entity
-  id: TorsoAnimal
-  name: animal torso
-  parent: PartAnimal
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: torso_m
-  - type: BodyPart
-    partType: Torso
-  - type: Damageable
-    damageContainer: Biological
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 10
-      - ReagentId: Blood
-        Quantity: 20
-
-- type: entity
-  parent: PartAnimal
-  id: LeftHandSmartCorgi
-  name: corgi hand
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: l_hand
-  - type: BodyPart
-    partType: Hand
-    symmetry: Left
-
-- type: entity
-  parent: PartAnimal
-  id: RightHandSmartCorgi
-  name: corgi hand
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Sprite
-    layers:
-    - state: r_hand
-  - type: BodyPart
-    partType: Hand
-    symmetry: Right
diff --git a/Resources/Prototypes/Body/Parts/arachnid.yml b/Resources/Prototypes/Body/Parts/arachnid.yml
deleted file mode 100644 (file)
index d275bd9..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-# TODO: Add descriptions (many)
-# TODO BODY: Part damage
-- type: entity
-  id: PartArachnid
-  parent: [BaseItem, BasePart]
-  name: "arachnid body part"
-  abstract: true
-  components:
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 3
-      - ReagentId: CopperBlood
-        Quantity: 10
-
-- type: entity
-  id: TorsoArachnid
-  name: "arachnid torso"
-  parent: [PartArachnid, BaseTorso]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "torso_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 10
-      - ReagentId: CopperBlood
-        Quantity: 20
-
-- type: entity
-  id: HeadArachnid
-  name: "arachnid head"
-  parent: [PartArachnid, BaseHead]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "head_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 5
-      - ReagentId: CopperBlood
-        Quantity: 10
-
-- type: entity
-  id: LeftArmArachnid
-  name: "left arachnid arm"
-  parent: [PartArachnid, BaseLeftArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "l_arm"
-
-- type: entity
-  id: RightArmArachnid
-  name: "right arachnid arm"
-  parent: [PartArachnid, BaseRightArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "r_arm"
-
-- type: entity
-  id: LeftHandArachnid
-  name: "left arachnid hand"
-  parent: [PartArachnid, BaseLeftHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "l_hand"
-
-- type: entity
-  id: RightHandArachnid
-  name: "right arachnid hand"
-  parent: [PartArachnid, BaseRightHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "r_hand"
-
-- type: entity
-  id: LeftLegArachnid
-  name: "left arachnid leg"
-  parent: [PartArachnid, BaseLeftLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "l_leg"
-  - type: MovementBodyPart
-
-- type: entity
-  id: RightLegArachnid
-  name: "right arachnid leg"
-  parent: [PartArachnid, BaseRightLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "r_leg"
-  - type: MovementBodyPart
-
-- type: entity
-  id: LeftFootArachnid
-  name: "left arachnid foot"
-  parent: [PartArachnid, BaseLeftFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "l_foot"
-
-- type: entity
-  id: RightFootArachnid
-  name: "right arachnid foot"
-  parent: [PartArachnid, BaseRightFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Arachnid/parts.rsi
-    state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/base.yml b/Resources/Prototypes/Body/Parts/base.yml
deleted file mode 100644 (file)
index 8e41ba9..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-# TODO: Add descriptions (many)
-# TODO BODY: Part damage
-- type: entity
-  id: BasePart
-  parent: BaseItem
-  name: "body part"
-  abstract: true
-  components:
-  - type: Damageable
-    damageContainer: Biological
-  - type: BodyPart
-  - type: ContainerContainer
-    containers:
-      bodypart: !type:Container
-        ents: []
-  - type: StaticPrice
-    price: 100
-  - type: Tag
-    tags:
-      - Trash
-
-- type: entity
-  id: BaseTorso
-  name: "torso"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Torso
-
-- type: entity
-  id: BaseHead
-  name: "head"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Head
-    vital: true
-  - type: Input
-    context: "ghost"
-
-- type: entity
-  id: BaseLeftArm
-  name: "left arm"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Arm
-    symmetry: Left
-
-- type: entity
-  id: BaseRightArm
-  name: "right arm"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Arm
-    symmetry: Right
-
-- type: entity
-  id: BaseLeftHand
-  name: "left hand"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Hand
-    symmetry: Left
-
-- type: entity
-  id: BaseRightHand
-  name: "right hand"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Hand
-    symmetry: Right
-
-- type: entity
-  id: BaseLeftLeg
-  name: "left leg"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Leg
-    symmetry: Left
-  - type: MovementBodyPart
-
-- type: entity
-  id: BaseRightLeg
-  name: "right leg"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Leg
-    symmetry: Right
-  - type: MovementBodyPart
-
-- type: entity
-  id: BaseLeftFoot
-  name: "left foot"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Foot
-    symmetry: Left
-
-- type: entity
-  id: BaseRightFoot
-  name: "right foot"
-  parent: BasePart
-  abstract: true
-  components:
-  - type: BodyPart
-    partType: Foot
-    symmetry: Right
diff --git a/Resources/Prototypes/Body/Parts/diona.yml b/Resources/Prototypes/Body/Parts/diona.yml
deleted file mode 100644 (file)
index 5257512..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-- type: entity
-  id: PartDiona
-  parent: [BaseItem, BasePart]
-  name: "diona body part"
-  abstract: true
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Diona/parts.rsi
-
-- type: entity
-  id: TorsoDiona
-  name: "diona torso"
-  parent: [PartDiona, BaseTorso]
-  components:
-  - type: Sprite
-    state: "torso_m"
-
-- type: entity
-  id: HeadDiona
-  name: "diona head"
-  parent: [PartDiona, BaseHead]
-  components:
-  - type: Sprite
-    state: "head_m"
-
-- type: entity
-  id: LeftArmDiona
-  name: "left diona arm"
-  parent: [PartDiona, BaseLeftArm]
-  components:
-  - type: Sprite
-    state: "l_arm"
-
-- type: entity
-  id: RightArmDiona
-  name: "right diona arm"
-  parent: [PartDiona, BaseRightArm]
-  components:
-  - type: Sprite
-    state: "r_arm"
-
-- type: entity
-  id: LeftHandDiona
-  name: "left diona hand"
-  parent: [PartDiona, BaseLeftHand]
-  components:
-  - type: Sprite
-    state: "l_hand"
-
-- type: entity
-  id: RightHandDiona
-  name: "right diona hand"
-  parent: [PartDiona, BaseRightHand]
-  components:
-  - type: Sprite
-    state: "r_hand"
-
-- type: entity
-  id: LeftLegDiona
-  name: "left diona leg"
-  parent: [PartDiona, BaseLeftLeg]
-  components:
-  - type: Sprite
-    state: "l_leg"
-
-- type: entity
-  id: RightLegDiona
-  name: "right diona leg"
-  parent: [PartDiona, BaseRightLeg]
-  components:
-  - type: Sprite
-    state: "r_leg"
-  - type: BodyPart
-    partType: Leg
-    symmetry: Right
-
-- type: entity
-  id: LeftFootDiona
-  name: "left diona foot"
-  parent: [PartDiona, BaseLeftFoot]
-  components:
-  - type: Sprite
-    state: "l_foot"
-  - type: BodyPart
-    partType: Foot
-    symmetry: Left
-
-- type: entity
-  id: RightFootDiona
-  name: "right diona foot"
-  parent: [PartDiona, BaseRightFoot]
-  components:
-  - type: Sprite
-    state: "r_foot"
-  - type: BodyPart
-    partType: Foot
-    symmetry: Right
diff --git a/Resources/Prototypes/Body/Parts/gingerbread.yml b/Resources/Prototypes/Body/Parts/gingerbread.yml
deleted file mode 100644 (file)
index f95e661..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-- type: entity
-  id: PartGingerbread
-  parent: [BaseItem, BasePart]
-  name: "gingerbread body part"
-  abstract: true
-  components:
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Nutriment
-        Quantity: 3
-      - ReagentId: Sugar
-        Quantity: 10
-
-- type: entity
-  id: TorsoGingerbread
-  name: "gingerbread torso"
-  parent: [PartGingerbread, BaseTorso]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "torso_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Nutriment
-        Quantity: 10
-      - ReagentId: Sugar
-        Quantity: 20
-
-- type: entity
-  id: HeadGingerbread
-  name: "gingerbread head"
-  parent: [PartGingerbread, BaseHead]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "head_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Nutriment
-        Quantity: 5
-      - ReagentId: Sugar
-        Quantity: 10
-
-- type: entity
-  id: LeftArmGingerbread
-  name: "left gingerbread arm"
-  parent: [PartGingerbread, BaseLeftArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "l_arm"
-
-- type: entity
-  id: RightArmGingerbread
-  name: "right gingerbread arm"
-  parent: [PartGingerbread, BaseRightArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "r_arm"
-
-- type: entity
-  id: LeftHandGingerbread
-  name: "left gingerbread hand"
-  parent: [PartGingerbread, BaseLeftHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "l_hand"
-
-- type: entity
-  id: RightHandGingerbread
-  name: "right gingerbread hand"
-  parent: [PartGingerbread, BaseRightHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "r_hand"
-
-- type: entity
-  id: LeftLegGingerbread
-  name: "left gingerbread leg"
-  parent: [PartGingerbread, BaseLeftLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "l_leg"
-
-- type: entity
-  id: RightLegGingerbread
-  name: "right gingerbread leg"
-  parent: [PartGingerbread, BaseRightLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "r_leg"
-
-- type: entity
-  id: LeftFootGingerbread
-  name: "left gingerbread foot"
-  parent: [PartGingerbread, BaseLeftFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "l_foot"
-
-- type: entity
-  id: RightFootGingerbread
-  name: "right gingerbread foot"
-  parent: [PartGingerbread, BaseRightFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/human.yml b/Resources/Prototypes/Body/Parts/human.yml
deleted file mode 100644 (file)
index a1510fc..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-# TODO: Add descriptions (many)
-# TODO BODY: Part damage
-- type: entity
-  id: PartHuman
-  parent: [BaseItem, BasePart]
-  name: "human body part"
-  abstract: true
-  components:
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 3
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: TorsoHuman
-  name: "human torso"
-  parent: [PartHuman, BaseTorso]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "torso_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 10
-      - ReagentId: Blood
-        Quantity: 20
-
-- type: entity
-  id: HeadHuman
-  name: "human head"
-  parent: [PartHuman, BaseHead]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "head_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 5
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: LeftArmHuman
-  name: "left human arm"
-  parent: [PartHuman, BaseLeftArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "l_arm"
-
-- type: entity
-  id: RightArmHuman
-  name: "right human arm"
-  parent: [PartHuman, BaseRightArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "r_arm"
-
-- type: entity
-  id: LeftHandHuman
-  name: "left human hand"
-  parent: [PartHuman, BaseLeftHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "l_hand"
-
-- type: entity
-  id: RightHandHuman
-  name: "right human hand"
-  parent: [PartHuman, BaseRightHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "r_hand"
-
-- type: entity
-  id: LeftLegHuman
-  name: "left human leg"
-  parent: [PartHuman, BaseLeftLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "l_leg"
-
-- type: entity
-  id: RightLegHuman
-  name: "right human leg"
-  parent: [PartHuman, BaseRightLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "r_leg"
-
-- type: entity
-  id: LeftFootHuman
-  name: "left human foot"
-  parent: [PartHuman, BaseLeftFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "l_foot"
-
-- type: entity
-  id: RightFootHuman
-  name: "right human foot"
-  parent: [PartHuman, BaseRightFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Human/parts.rsi
-    state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/moth.yml b/Resources/Prototypes/Body/Parts/moth.yml
deleted file mode 100644 (file)
index bb96430..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-# TODO: Add descriptions (many)
-# TODO BODY: Part damage
-- type: entity
-  id: PartMoth
-  parent: [BaseItem, BasePart]
-  name: "moth body part"
-  abstract: true
-  components:
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 3
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: TorsoMoth
-  name: "moth torso"
-  parent: [PartMoth, BaseTorso]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "torso_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 10
-      - ReagentId: Blood
-        Quantity: 20
-
-
-- type: entity
-  id: HeadMoth
-  name: "moth head"
-  parent: [PartMoth, BaseHead]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "head_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 5
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: LeftArmMoth
-  name: "left moth arm"
-  parent: [PartMoth, BaseLeftArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "l_arm"
-
-- type: entity
-  id: RightArmMoth
-  name: "right moth arm"
-  parent: [PartMoth, BaseRightArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "r_arm"
-
-- type: entity
-  id: LeftHandMoth
-  name: "left moth hand"
-  parent: [PartMoth, BaseLeftHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "l_hand"
-
-- type: entity
-  id: RightHandMoth
-  name: "right moth hand"
-  parent: [PartMoth, BaseRightHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "r_hand"
-
-- type: entity
-  id: LeftLegMoth
-  name: "left moth leg"
-  parent: [PartMoth, BaseLeftLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "l_leg"
-
-- type: entity
-  id: RightLegMoth
-  name: "right moth leg"
-  parent: [PartMoth, BaseRightLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "r_leg"
-
-- type: entity
-  id: LeftFootMoth
-  name: "left moth foot"
-  parent: [PartMoth, BaseLeftFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "l_foot"
-
-- type: entity
-  id: RightFootMoth
-  name: "right moth foot"
-  parent: [PartMoth, BaseRightFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/rat.yml b/Resources/Prototypes/Body/Parts/rat.yml
deleted file mode 100644 (file)
index bd51e00..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Just copypasta of some animal basic body parts for interaction,
-# It's basically as animals except a different torso with different organs
-- type: entity
-  id: TorsoRat
-  name: "animal torso"
-  parent: PartAnimal
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: BodyPart
-    partType: Torso
-  - type: Damageable
-    damageContainer: Biological
-  - type: Tag
-    tags:
-      - Trash
-  # TODO get a proper rat king & servant torso sprite.
-  # currently their torso is just a small dead rat....
-  - type: Sprite
-    sprite: Mobs/Animals/mouse.rsi
-    state: splat-0
diff --git a/Resources/Prototypes/Body/Parts/reptilian.yml b/Resources/Prototypes/Body/Parts/reptilian.yml
deleted file mode 100644 (file)
index a299636..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-# TODO: Add descriptions (many)
-# TODO BODY: Part damage
-- type: entity
-  id: PartReptilian
-  parent: [BaseItem, BasePart]
-  name: "reptilian body part"
-  abstract: true
-  components:
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 3
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: TorsoReptilian
-  name: "reptilian torso"
-  parent: [PartReptilian, BaseTorso]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "torso_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 10
-      - ReagentId: Blood
-        Quantity: 20
-
-- type: entity
-  id: HeadReptilian
-  name: "reptilian head"
-  parent: [PartReptilian, BaseHead]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "head_m"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 5
-      - ReagentId: Blood
-        Quantity: 10
-
-- type: entity
-  id: LeftArmReptilian
-  name: "left reptilian arm"
-  parent: [PartReptilian, BaseLeftArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "l_arm"
-
-- type: entity
-  id: RightArmReptilian
-  name: "right reptilian arm"
-  parent: [PartReptilian, BaseRightArm]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "r_arm"
-
-- type: entity
-  id: LeftHandReptilian
-  name: "left reptilian hand"
-  parent: [PartReptilian, BaseLeftHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "l_hand"
-
-- type: entity
-  id: RightHandReptilian
-  name: "right reptilian hand"
-  parent: [PartReptilian, BaseRightHand]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "r_hand"
-
-- type: entity
-  id: LeftLegReptilian
-  name: "left reptilian leg"
-  parent: [PartReptilian, BaseLeftLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "l_leg"
-
-- type: entity
-  id: RightLegReptilian
-  name: "right reptilian leg"
-  parent: [PartReptilian, BaseRightLeg]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "r_leg"
-
-- type: entity
-  id: LeftFootReptilian
-  name: "left reptilian foot"
-  parent: [PartReptilian, BaseLeftFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "l_foot"
-
-- type: entity
-  id: RightFootReptilian
-  name: "right reptilian foot"
-  parent: [PartReptilian, BaseRightFoot]
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/silicon.yml b/Resources/Prototypes/Body/Parts/silicon.yml
deleted file mode 100644 (file)
index 9e6d826..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-- type: entity
-  id: PartSilicon
-  parent: BaseItem
-  abstract: true
-  components:
-  - type: Sprite
-    sprite: Objects/Specific/Robotics/cyborg_parts.rsi
-  - type: Icon
-    sprite: Objects/Specific/Robotics/cyborg_parts.rsi
-  - type: Damageable
-    damageContainer: Inorganic
-  - type: BodyPart
-  - type: ContainerContainer
-    containers:
-      bodypart: !type:Container
-        ents: []
-  - type: StaticPrice
-    price: 5
-  - type: Tag
-    tags:
-      - Trash
-  - type: PhysicalComposition
-    materialComposition:
-      Steel: 25
-  - type: GuideHelp
-    guides:
-    - Cyborgs
-    - Robotics
-
-- type: entity
-  id: LeftArmBorg
-  parent: PartSilicon
-  name: cyborg left arm
-  components:
-  - type: BodyPart
-    partType: Hand
-    symmetry: Left
-  - type: Sprite
-    state: borg_l_arm
-  - type: Icon
-    state: borg_l_arm
-  - type: Tag
-    tags:
-    - Trash
-    - BorgArm
-    - BorgLArm
-  - type: Item
-    heldPrefix: borg-arm
-
-- type: entity
-  id: RightArmBorg
-  parent: PartSilicon
-  name: cyborg right arm
-  components:
-  - type: BodyPart
-    partType: Hand
-    symmetry: Right
-  - type: Sprite
-    state: borg_r_arm
-  - type: Icon
-    state: borg_r_arm
-  - type: Tag
-    tags:
-    - Trash
-    - BorgArm
-    - BorgRArm
-  - type: Item
-    heldPrefix: borg-arm
-
-- type: entity
-  id: LeftLegBorg
-  parent: PartSilicon
-  name: cyborg left leg
-  components:
-  - type: BodyPart
-    partType: Leg
-    symmetry: Left
-  - type: Sprite
-    state: borg_l_leg
-  - type: Icon
-    state: borg_l_leg
-  - type: Tag
-    tags:
-    - Trash
-    - BorgLeg
-    - BorgLLeg
-  - type: Item
-    heldPrefix: borg-leg
-
-- type: entity
-  id: RightLegBorg
-  parent: PartSilicon
-  name: cyborg right leg
-  components:
-  - type: BodyPart
-    partType: Leg
-    symmetry: Right
-  - type: Sprite
-    state: borg_r_leg
-  - type: Icon
-    state: borg_r_leg
-  - type: Tag
-    tags:
-    - Trash
-    - BorgLeg
-    - BorgRLeg
-  - type: Item
-    heldPrefix: borg-leg
-
-- type: entity
-  id: LightHeadBorg
-  parent: PartSilicon
-  name: cyborg head
-  components:
-  - type: BodyPart
-    partType: Head
-  - type: Sprite
-    state: borg_head
-  - type: Icon
-    state: borg_head
-  - type: Tag
-    tags:
-    - Trash
-    - BorgHead
-  - type: Item
-    heldPrefix: borg-head
-
-- type: entity
-  id: TorsoBorg
-  parent: PartSilicon
-  name: cyborg torso
-  components:
-  - type: BodyPart
-    partType: Torso
-  - type: Sprite
-    state: borg_chest
-  - type: Icon
-    state: borg_chest
-  - type: Tag
-    tags:
-    - Trash
-    - BorgTorso
-  - type: Item
-    heldPrefix: borg-chest
diff --git a/Resources/Prototypes/Body/Parts/skeleton.yml b/Resources/Prototypes/Body/Parts/skeleton.yml
deleted file mode 100644 (file)
index 378c426..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-# TODO BODY: Part damage
-- type: entity
-  id: PartSkeleton
-  parent: BaseItem
-  name: "skeleton body part"
-  abstract: true
-  components:
-  - type: Damageable
-    damageContainer: Biological
-  - type: BodyPart
-  - type: ContainerContainer
-    containers:
-      bodypart: !type:Container
-        ents: []
-  - type: StaticPrice
-    price: 20
-  - type: Tag
-    tags:
-      - Trash
-
-- type: entity
-  id: TorsoSkeleton
-  name: "skeleton torso"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "torso_m"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "torso_m"
-    - type: BodyPart
-      partType: Torso
-
-- type: entity
-  id: HeadSkeleton
-  name: "skull"
-  description: Alas poor Yorick...
-  parent: [ PartSkeleton, BaseMob ]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "skull_icon"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "skull_icon"
-    - type: BodyPart
-      partType: Head
-    - type: BlockMovement
-    - type: Input
-      context: "human"
-    - type: Speech
-      speechVerb: Skeleton
-      speechSounds: Alto
-    - type: SkeletonAccent
-    - type: Actions
-    - type: Vocal
-      sounds:
-        Male: Skeleton
-        Female: Skeleton
-        Unsexed: Skeleton
-    - type: Emoting
-    - type: Grammar
-      attributes:
-        proper: true
-    - type: Examiner
-    - type: DoAfter
-    - type: MobState
-      allowedStates:
-        - Alive
-    - type: Tag
-      tags:
-        - MindTransferTarget
-        - Head
-
-- type: entity
-  id: LeftArmSkeleton
-  name: "left skeleton arm"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_arm"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_arm"
-    - type: BodyPart
-      partType: Arm
-      symmetry: Left
-
-- type: entity
-  id: RightArmSkeleton
-  name: "right skeleton arm"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_arm"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_arm"
-    - type: BodyPart
-      partType: Arm
-      symmetry: Right
-
-- type: entity
-  id: LeftHandSkeleton
-  name: "left skeleton hand"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_hand"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_hand"
-    - type: BodyPart
-      partType: Hand
-      symmetry: Left
-
-- type: entity
-  id: RightHandSkeleton
-  name: "right skeleton hand"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_hand"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_hand"
-    - type: BodyPart
-      partType: Hand
-      symmetry: Right
-
-- type: entity
-  id: LeftLegSkeleton
-  name: "left skeleton leg"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_leg"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_leg"
-    - type: BodyPart
-      partType: Leg
-      symmetry: Left
-    - type: MovementBodyPart
-
-- type: entity
-  id: RightLegSkeleton
-  name: "right skeleton leg"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_leg"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_leg"
-    - type: BodyPart
-      partType: Leg
-      symmetry: Right
-    - type: MovementBodyPart
-
-- type: entity
-  id: LeftFootSkeleton
-  name: "left skeleton foot"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_foot"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "l_foot"
-    - type: BodyPart
-      partType: Foot
-      symmetry: Left
-
-- type: entity
-  id: RightFootSkeleton
-  name: "right skeleton foot"
-  parent: PartSkeleton
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_foot"
-    - type: Icon
-      sprite: Mobs/Species/Skeleton/parts.rsi
-      state: "r_foot"
-    - type: BodyPart
-      partType: Foot
-      symmetry: Right
diff --git a/Resources/Prototypes/Body/Parts/slime.yml b/Resources/Prototypes/Body/Parts/slime.yml
deleted file mode 100644 (file)
index 4b0e94b..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-# TODO BODY: Part damage
-- type: entity
-  id: PartSlime
-  parent: [BaseItem, BasePart]
-  name: "slime body part"
-  abstract: true
-
-- type: entity
-  id: TorsoSlime
-  name: "slime torso"
-  parent: [PartSlime, BaseTorso]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "torso_m"
-
-- type: entity
-  id: HeadSlime
-  name: "slime head"
-  parent: [PartSlime, BaseHead]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "head_m"
-  
-- type: entity
-  id: LeftArmSlime
-  name: "left slime arm"
-  parent: [PartSlime, BaseLeftArm]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "l_arm"
-
-- type: entity
-  id: RightArmSlime
-  name: "right slime arm"
-  parent: [PartSlime, BaseRightArm]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "r_arm"
-
-- type: entity
-  id: LeftHandSlime
-  name: "left slime hand"
-  parent: [PartSlime, BaseLeftHand]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "l_hand"
-
-- type: entity
-  id: RightHandSlime
-  name: "right slime hand"
-  parent: [PartSlime, BaseRightHand]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "r_hand"
-
-- type: entity
-  id: LeftLegSlime
-  name: "left slime leg"
-  parent: [PartSlime, BaseLeftLeg]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "l_leg"
-
-- type: entity
-  id: RightLegSlime
-  name: "right slime leg"
-  parent: [PartSlime, BaseRightLeg]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "r_leg"
-
-- type: entity
-  id: LeftFootSlime
-  name: "left slime foot"
-  parent: [PartSlime, BaseLeftFoot]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "l_foot"
-
-- type: entity
-  id: RightFootSlime
-  name: "right slime foot"
-  parent: [PartSlime, BaseRightFoot]
-  components:
-    - type: Sprite
-      sprite: Mobs/Species/Slime/parts.rsi
-      state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/vox.yml b/Resources/Prototypes/Body/Parts/vox.yml
deleted file mode 100644 (file)
index ee767f3..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-# TODO: Add descriptions (many)
-# TODO BODY: Part damage
-- type: entity
-  abstract: true
-  parent: [ BaseItem, BasePart ]
-  id: PartVox
-  name: "vox body part"
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Vox/parts.rsi
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 3
-      - ReagentId: AmmoniaBlood
-        Quantity: 10
-
-- type: entity
-  parent: [PartVox, BaseTorso]
-  id: TorsoVox
-  name: "vox torso"
-  components:
-  - type: Sprite
-    state: "torso"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 10
-      - ReagentId: AmmoniaBlood
-        Quantity: 20
-
-- type: entity
-  parent: [ PartVox, BaseHead ]
-  id: HeadVox
-  name: "vox head"
-  components:
-  - type: Sprite
-    state: "head"
-  - type: Extractable
-    juiceSolution:
-      reagents:
-      - ReagentId: Fat
-        Quantity: 5
-      - ReagentId: AmmoniaBlood
-        Quantity: 10
-
-- type: entity
-  parent: [ PartVox, BaseLeftArm ]
-  id: LeftArmVox
-  name: "left vox arm"
-  components:
-  - type: Sprite
-    state: "l_arm"
-
-- type: entity
-  parent: [ PartVox, BaseRightArm ]
-  id: RightArmVox
-  name: "right vox arm"
-  components:
-  - type: Sprite
-    state: "r_arm"
-
-- type: entity
-  parent: [ PartVox, BaseLeftHand ]
-  id: LeftHandVox
-  name: "left vox hand"
-  components:
-  - type: Sprite
-    state: "l_hand"
-
-- type: entity
-  parent: [ PartVox, BaseRightHand ]
-  id: RightHandVox
-  name: "right vox hand"
-  components:
-  - type: Sprite
-    state: "r_hand"
-
-- type: entity
-  parent:  [ PartVox, BaseLeftLeg ]
-  id: LeftLegVox
-  name: "left vox leg"
-  components:
-  - type: Sprite
-    state: "l_leg"
-
-- type: entity
-  parent:  [ PartVox, BaseRightLeg ]
-  id: RightLegVox
-  name: "right vox leg"
-  components:
-  - type: Sprite
-    state: "r_leg"
-
-- type: entity
-  parent: [ PartVox, BaseLeftFoot ]
-  id: LeftFootVox
-  name: "left vox foot"
-  components:
-  - type: Sprite
-    state: "l_foot"
-
-- type: entity
-  parent: [ PartVox, BaseRightFoot ]
-  id: RightFootVox
-  name: "right vox foot"
-  components:
-  - type: Sprite
-    state: "r_foot"
diff --git a/Resources/Prototypes/Body/Parts/vulpkanin.yml b/Resources/Prototypes/Body/Parts/vulpkanin.yml
deleted file mode 100644 (file)
index d563a64..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-# Limbs that spawn when gibbed should get descriptions.
-- type: entity
-  abstract: true
-  parent: [ BasePart ]
-  id: PartVulpkanin
-  name: vulpkanin body part
-  components:
-  - type: Sprite
-    sprite: Mobs/Species/Vulpkanin/parts.rsi
-
-- type: entity
-  parent: [ PartVulpkanin, BaseTorso ]
-  id: TorsoVulpkanin
-  name: vulpkanin torso
-  components:
-  - type: Sprite
-    state: torso_m
-
-- type: entity
-  parent: [ PartVulpkanin, BaseHead ]
-  id: HeadVulpkanin
-  name: vulpkanin head
-  components:
-  - type: Sprite
-    state: head_m
-
-- type: entity
-  parent: [ PartVulpkanin, BaseLeftArm ]
-  id: LeftArmVulpkanin
-  name: left vulpkanin arm
-  components:
-  - type: Sprite
-    state: l_arm
-
-- type: entity
-  parent: [ PartVulpkanin, BaseRightArm ]
-  id: RightArmVulpkanin
-  name: right vulpkanin arm
-  components:
-  - type: Sprite
-    state: r_arm
-
-- type: entity
-  parent: [ PartVulpkanin, BaseLeftHand ]
-  id: LeftHandVulpkanin
-  name: left vulpkanin hand
-  components:
-  - type: Sprite
-    state: l_hand
-
-- type: entity
-  parent: [ PartVulpkanin, BaseRightHand ]
-  id: RightHandVulpkanin
-  name: right vulpkanin hand
-  components:
-  - type: Sprite
-    state: r_hand
-
-- type: entity
-  parent: [ PartVulpkanin, BaseLeftLeg ]
-  id: LeftLegVulpkanin
-  name: left vulpkanin leg
-  components:
-  - type: Sprite
-    state: l_leg
-
-- type: entity
-  parent: [ PartVulpkanin, BaseRightLeg ]
-  id: RightLegVulpkanin
-  name: right vulpkanin leg
-  components:
-  - type: Sprite
-    state: r_leg
-
-- type: entity
-  parent: [ PartVulpkanin, BaseLeftFoot ]
-  id: LeftFootVulpkanin
-  name: left vulpkanin foot
-  components:
-  - type: Sprite
-    state: l_foot
-
-- type: entity
-  parent: [ PartVulpkanin, BaseRightFoot ]
-  id: RightFootVulpkanin
-  name: right vulpkanin foot
-  components:
-  - type: Sprite
-    state: r_foot
diff --git a/Resources/Prototypes/Body/Prototypes/Animal/animal.yml b/Resources/Prototypes/Body/Prototypes/Animal/animal.yml
deleted file mode 100644 (file)
index a8c81f9..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-- type: body
-  id: Animal
-  name: "animal"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganAnimalStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
-
-- type: body
-  id: Mouse
-  name: "mouse"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganMouseStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
\ No newline at end of file
diff --git a/Resources/Prototypes/Body/Prototypes/Animal/bloodsucker.yml b/Resources/Prototypes/Body/Prototypes/Animal/bloodsucker.yml
deleted file mode 100644 (file)
index dd87507..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-- type: body
-  id: Bloodsucker
-  name: "bloodsucker"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganBloodsuckerStomach
-        liver: OrganBloodsuckerLiver
-        heart: OrganBloodsuckerHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/Animal/hemocyanin.yml b/Resources/Prototypes/Body/Prototypes/Animal/hemocyanin.yml
deleted file mode 100644 (file)
index b29edad..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-- type: body
-  id: AnimalHemocyanin
-  name: "hemocyanin"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganAnimalStomach
-        liver: OrganAnimalLiver
-        heart: OrganArachnidHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/Animal/nymph.yml b/Resources/Prototypes/Body/Prototypes/Animal/nymph.yml
deleted file mode 100644 (file)
index 21aafe2..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-- type: body
-  id: AnimalNymphBrain
-  name: "nymph"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        brain: OrganDionaBrain
-        lungs: OrganAnimalLungs
-        stomach: OrganAnimalStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
-
-- type: body
-  id: AnimalNymphLungs
-  name: "nymph"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganDionaLungs
-        stomach: OrganAnimalStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
-
-- type: body
-  id: AnimalNymphStomach
-  name: "nymph"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganDionaStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
\ No newline at end of file
diff --git a/Resources/Prototypes/Body/Prototypes/Animal/ruminant.yml b/Resources/Prototypes/Body/Prototypes/Animal/ruminant.yml
deleted file mode 100644 (file)
index 3a213e3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-- type: body
-  id: AnimalRuminant
-  name: "ruminant"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganAnimalRuminantStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/Animal/slimes.yml b/Resources/Prototypes/Body/Prototypes/Animal/slimes.yml
deleted file mode 100644 (file)
index 8d9827e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-- type: body
-  id: Slimes
-  name: "slimes"
-  root: torso
-  slots:
-    torso:
-      part: TorsoSlime
-      connections:
-      - legs
-      organs:
-        core: SentientSlimesCore
-        lungs: OrganSlimesLungs
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/Specific/mothroach.yml b/Resources/Prototypes/Body/Prototypes/Specific/mothroach.yml
deleted file mode 100644 (file)
index ef5df76..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-- type: body
-  id: Mothroach
-  name: "mothroach"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganMothStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
diff --git a/Resources/Prototypes/Body/Prototypes/Specific/smartcorgi.yml b/Resources/Prototypes/Body/Prototypes/Specific/smartcorgi.yml
deleted file mode 100644 (file)
index 89c374c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-- type: body
-  id: SmartCorgi
-  name: corgi
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - righthand
-      - lefthand
-      - legs
-      organs:
-        brain: OrganHumanBrain # feels strange but it is what it is
-        lungs: OrganAnimalLungs
-        stomach: OrganAnimalStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    lefthand:
-      part: LeftHandSmartCorgi
-    righthand:
-      part: RightHandSmartCorgi
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/arachnid.yml b/Resources/Prototypes/Body/Prototypes/arachnid.yml
deleted file mode 100644 (file)
index e198f79..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Arachnid
-  name: "arachnid"
-  root: torso
-  slots:
-    head:
-      part: HeadArachnid
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganArachnidEyes
-    torso:
-      part: TorsoArachnid
-      organs:
-        heart: OrganArachnidHeart
-        lungs: OrganArachnidLungs
-        stomach: OrganArachnidStomach
-        liver: OrganArachnidLiver
-        kidneys: OrganArachnidKidneys
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-    right arm:
-      part: RightArmArachnid
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmArachnid
-      connections:
-      - left hand
-    right hand:
-      part: RightHandArachnid
-    left hand:
-      part: LeftHandArachnid
-    right leg:
-      part: RightLegArachnid
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegArachnid
-      connections:
-      - left foot
-    right foot:
-      part: RightFootArachnid
-    left foot:
-      part: LeftFootArachnid
diff --git a/Resources/Prototypes/Body/Prototypes/bot.yml b/Resources/Prototypes/Body/Prototypes/bot.yml
deleted file mode 100644 (file)
index ae9bd4a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-- type: body
-  id: Bot
-  name: "bot"
-  root: hand 1
-  slots:
-    hand 1:
-      part: LeftArmBorg
-
-# It's like a medibot or a cleanbot except it has two arms to hug :)
-- type: body
-  id: HugBot
-  name: "hugBot"
-  root: box
-  slots:
-    box:
-      part: TorsoBorg
-      connections:
-      - right_arm
-      - left_arm
-    right_arm:
-      part: RightArmBorg
-    left_arm:
-      part: LeftArmBorg
diff --git a/Resources/Prototypes/Body/Prototypes/diona.yml b/Resources/Prototypes/Body/Prototypes/diona.yml
deleted file mode 100644 (file)
index 12ca203..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-- type: body
-  id: Diona
-  name: diona
-  root: torso
-  slots:
-    head:
-      part: HeadDiona
-      connections:
-      - torso
-      organs:
-        brain: OrganDionaBrainNymph
-    torso:
-      part: TorsoDiona
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-      organs:
-        stomach: OrganDionaStomachNymph
-        lungs: OrganDionaLungsNymph
-    right arm:
-      part: RightArmDiona
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmDiona
-      connections:
-      - left hand
-    right hand:
-      part: RightHandDiona
-    left hand:
-      part: LeftHandDiona
-    right leg:
-      part: RightLegDiona
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegDiona
-      connections:
-      - left foot
-    right foot:
-      part: RightFootDiona
-    left foot:
-      part: LeftFootDiona
diff --git a/Resources/Prototypes/Body/Prototypes/dwarf.yml b/Resources/Prototypes/Body/Prototypes/dwarf.yml
deleted file mode 100644 (file)
index 5924926..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Dwarf
-  name: "dwarf"
-  root: torso
-  slots:
-    head:
-      part: HeadHuman
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganHumanEyes
-    torso:
-      part: TorsoHuman
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-      organs:
-        heart: OrganDwarfHeart
-        lungs: OrganHumanLungs
-        stomach: OrganDwarfStomach
-        liver: OrganDwarfLiver
-        kidneys: OrganHumanKidneys
-    right arm:
-      part: RightArmHuman
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmHuman
-      connections:
-      - left hand
-    right hand:
-      part: RightHandHuman
-    left hand:
-      part: LeftHandHuman
-    right leg:
-      part: RightLegHuman
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegHuman
-      connections:
-      - left foot
-    right foot:
-      part: RightFootHuman
-    left foot:
-      part: LeftFootHuman
diff --git a/Resources/Prototypes/Body/Prototypes/gingerbread.yml b/Resources/Prototypes/Body/Prototypes/gingerbread.yml
deleted file mode 100644 (file)
index d5355be..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Gingerbread
-  name: gingerbread
-  root: torso
-  slots:
-    head:
-      part: HeadGingerbread
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganHumanEyes
-    torso:
-      part: TorsoGingerbread
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-      organs:
-        heart: OrganHumanHeart
-        lungs: OrganHumanLungs
-        stomach: OrganHumanStomach
-        liver: OrganHumanLiver
-        kidneys: OrganHumanKidneys
-    right arm:
-      part: RightArmGingerbread
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmGingerbread
-      connections:
-      - left hand
-    right hand:
-      part: RightHandGingerbread
-    left hand:
-      part: LeftHandGingerbread
-    right leg:
-      part: RightLegGingerbread
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegGingerbread
-      connections:
-      - left foot
-    right foot:
-      part: RightFootGingerbread
-    left foot:
-      part: LeftFootGingerbread
diff --git a/Resources/Prototypes/Body/Prototypes/human.yml b/Resources/Prototypes/Body/Prototypes/human.yml
deleted file mode 100644 (file)
index 94c77a2..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Human
-  name: "human"
-  root: torso
-  slots:
-    head:
-      part: HeadHuman
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganHumanEyes
-    torso:
-      part: TorsoHuman
-      connections:
-      - right_arm
-      - left_arm
-      - right_leg
-      - left_leg
-      organs:
-        heart: OrganHumanHeart
-        lungs: OrganHumanLungs
-        stomach: OrganHumanStomach
-        liver: OrganHumanLiver
-        kidneys: OrganHumanKidneys
-    right_arm:
-      part: RightArmHuman
-      connections:
-      - right_hand
-    left_arm:
-      part: LeftArmHuman
-      connections:
-      - left_hand
-    right_hand:
-      part: RightHandHuman
-    left_hand:
-      part: LeftHandHuman
-    right_leg:
-      part: RightLegHuman
-      connections:
-      - right_foot
-    left_leg:
-      part: LeftLegHuman
-      connections:
-      - left_foot
-    right_foot:
-      part: RightFootHuman
-    left_foot:
-      part: LeftFootHuman
diff --git a/Resources/Prototypes/Body/Prototypes/moth.yml b/Resources/Prototypes/Body/Prototypes/moth.yml
deleted file mode 100644 (file)
index b327183..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Moth
-  name: "moth"
-  root: torso
-  slots:
-    head:
-      part: HeadMoth
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganHumanEyes
-    torso:
-      part: TorsoMoth
-      organs:
-        heart: OrganAnimalHeart
-        lungs: OrganHumanLungs
-        stomach: OrganMothStomach
-        liver: OrganAnimalLiver
-        kidneys: OrganHumanKidneys
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-    right arm:
-      part: RightArmMoth
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmMoth
-      connections:
-      - left hand
-    right hand:
-      part: RightHandMoth
-    left hand:
-      part: LeftHandMoth
-    right leg:
-      part: RightLegMoth
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegMoth
-      connections:
-      - left foot
-    right foot:
-      part: RightFootMoth
-    left foot:
-      part: LeftFootMoth
diff --git a/Resources/Prototypes/Body/Prototypes/primate.yml b/Resources/Prototypes/Body/Prototypes/primate.yml
deleted file mode 100644 (file)
index 2af9273..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-- type: body
-  id: Primate
-  name: "primate"
-  root: torso
-  slots:
-    torso:
-      part: TorsoAnimal
-      connections:
-      - hands
-      - legs
-      organs:
-        lungs: OrganAnimalLungs
-        stomach: OrganAnimalStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    hands:
-      part: HandsAnimal
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/rat.yml b/Resources/Prototypes/Body/Prototypes/rat.yml
deleted file mode 100644 (file)
index fe77288..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-- type: body
-  id: Rat
-  name: "animal"
-  root: torso
-  slots:
-    torso:
-      part: TorsoRat
-      connections:
-      - legs
-      organs:
-        lungs: OrganRatLungs
-        stomach: OrganRatStomach
-        liver: OrganAnimalLiver
-        heart: OrganAnimalHeart
-        kidneys: OrganAnimalKidneys
-    legs:
-      part: LegsAnimal
-      connections:
-      - feet
-    feet:
-      part: FeetAnimal
diff --git a/Resources/Prototypes/Body/Prototypes/reptilian.yml b/Resources/Prototypes/Body/Prototypes/reptilian.yml
deleted file mode 100644 (file)
index 1e9ebd5..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  name: "reptilian"
-  id: Reptilian
-  root: torso
-  slots:
-    head:
-      part: HeadReptilian
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganHumanEyes
-    torso:
-      part: TorsoReptilian
-      organs:
-        heart: OrganAnimalHeart
-        lungs: OrganHumanLungs
-        stomach: OrganReptilianStomach
-        liver: OrganAnimalLiver
-        kidneys: OrganHumanKidneys
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-    right arm:
-      part: RightArmReptilian
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmReptilian
-      connections:
-      - left hand
-    right hand:
-      part: RightHandReptilian
-    left hand:
-      part: LeftHandReptilian
-    right leg:
-      part: RightLegReptilian
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegReptilian
-      connections:
-      - left foot
-    right foot:
-      part: RightFootReptilian
-    left foot:
-      part: LeftFootReptilian
diff --git a/Resources/Prototypes/Body/Prototypes/skeleton.yml b/Resources/Prototypes/Body/Prototypes/skeleton.yml
deleted file mode 100644 (file)
index 16d0836..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-- type: body
-  id: Skeleton
-  name: "skeleton"
-  root: torso
-  slots:
-    head:
-      part: HeadSkeleton
-      connections:
-      - torso
-    torso:
-      part: TorsoSkeleton
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-    right arm:
-      part: RightArmSkeleton
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmSkeleton
-      connections:
-      - left hand
-    right hand:
-      part: RightHandSkeleton
-    left hand:
-      part: LeftHandSkeleton
-    right leg:
-      part: RightLegSkeleton
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegSkeleton
-      connections:
-      - left foot
-    right foot:
-      part: RightFootSkeleton
-    left foot:
-      part: LeftFootSkeleton
diff --git a/Resources/Prototypes/Body/Prototypes/slime.yml b/Resources/Prototypes/Body/Prototypes/slime.yml
deleted file mode 100644 (file)
index b57c5ec..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-- type: body
-  id: Slime
-  name: "slime"
-  root: torso
-  slots:
-    head:
-      part: HeadSlime
-      connections:
-      - torso
-    torso:
-      part: TorsoSlime
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-      organs:
-        core: SentientSlimeCore
-        lungs: OrganSlimeLungs
-    right arm:
-      part: RightArmSlime
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmSlime
-      connections:
-      - left hand
-    right hand:
-      part: RightHandSlime
-    left hand:
-      part: LeftHandSlime
-    right leg:
-      part: RightLegSlime
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegSlime
-      connections:
-      - left foot
-    right foot:
-      part: RightFootSlime
-    left foot:
-      part: LeftFootSlime
diff --git a/Resources/Prototypes/Body/Prototypes/vox.yml b/Resources/Prototypes/Body/Prototypes/vox.yml
deleted file mode 100644 (file)
index 0062149..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Vox
-  name: "vox"
-  root: torso
-  slots:
-    head:
-      part: HeadVox
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganVoxEyes
-    torso:
-      part: TorsoVox
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-      organs:
-        heart: OrganVoxHeart
-        lungs: OrganVoxLungs
-        stomach: OrganVoxStomach
-        liver: OrganVoxLiver
-        kidneys: OrganVoxKidneys
-    right arm:
-      part: RightArmVox
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmVox
-      connections:
-      - left hand
-    right hand:
-      part: RightHandVox
-    left hand:
-      part: LeftHandVox
-    right leg:
-      part: RightLegVox
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegVox
-      connections:
-      - left foot
-    right foot:
-      part: RightFootVox
-    left foot:
-      part: LeftFootVox
diff --git a/Resources/Prototypes/Body/Prototypes/vulpkanin.yml b/Resources/Prototypes/Body/Prototypes/vulpkanin.yml
deleted file mode 100644 (file)
index e939e3a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-- type: body
-  id: Vulpkanin
-  name: vulpkanin
-  root: torso
-  slots:
-    head:
-      part: HeadVulpkanin
-      connections:
-      - torso
-      organs:
-        brain: OrganHumanBrain
-        eyes: OrganHumanEyes
-    torso:
-      part: TorsoVulpkanin
-      connections:
-      - right arm
-      - left arm
-      - right leg
-      - left leg
-      organs:
-        heart: OrganAnimalHeart
-        lungs: OrganHumanLungs
-        stomach: OrganVulpkaninStomach
-        liver: OrganAnimalLiver
-        kidneys: OrganHumanKidneys
-    right arm:
-      part: RightArmVulpkanin
-      connections:
-      - right hand
-    left arm:
-      part: LeftArmVulpkanin
-      connections:
-      - left hand
-    right hand:
-      part: RightHandVulpkanin
-    left hand:
-      part: LeftHandVulpkanin
-    right leg:
-      part: RightLegVulpkanin
-      connections:
-      - right foot
-    left leg:
-      part: LeftLegVulpkanin
-      connections:
-      - left foot
-    right foot:
-      part: RightFootVulpkanin
-    left foot:
-      part: LeftFootVulpkanin
diff --git a/Resources/Prototypes/Body/Species/arachnid.yml b/Resources/Prototypes/Body/Species/arachnid.yml
new file mode 100644 (file)
index 0000000..10c7623
--- /dev/null
@@ -0,0 +1,215 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceArachnid
+  name: arachnid appearance
+  components:
+  - type: Inventory
+    templateId: arachnid
+    speciesId: arachnid
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganArachnidTorso
+        - id: OrganArachnidHead
+        - id: OrganArachnidArmLeft
+        - id: OrganArachnidArmRight
+        - id: OrganArachnidHandRight
+        - id: OrganArachnidHandLeft
+        - id: OrganArachnidLegLeft
+        - id: OrganArachnidLegRight
+        - id: OrganArachnidFootLeft
+        - id: OrganArachnidFootRight
+        - id: OrganArachnidBrain
+        - id: OrganArachnidEyes
+        - id: OrganArachnidTongue
+        - id: OrganArachnidAppendix
+        - id: OrganArachnidEars
+        - id: OrganArachnidLungs
+        - id: OrganArachnidHeart
+        - id: OrganArachnidStomach
+        - id: OrganArachnidLiver
+        - id: OrganArachnidKidneys
+  - type: HumanoidAppearance
+    species: Arachnid
+
+- type: entity
+  parent:
+  - AppearanceArachnid
+  - BaseSpeciesMobOrganic
+  id: MobArachnid
+  name: Urist McWebs
+  components:
+  - type: Respirator
+    damage:
+      types:
+        Asphyxiation: 1.5 # This makes space and crit more lethal to arachnids.
+    damageRecovery:
+      types:
+        Asphyxiation: -0.5
+  - type: Sericulture
+    productionLength: 2
+    entityProduced: MaterialWebSilk1
+    hungerCost: 4 # Should total to 25 total silk on full hunger
+  - type: Tag
+    tags:
+    - CanPilot
+    - FootstepSound
+    - DoorBumpOpener
+    - SpiderCraft
+    - AnomalyHost
+  - type: Butcherable
+    spawned:
+    - id: FoodMeatSpider
+      amount: 5
+  - type: Reactive
+    reactions:
+    - reagents: [Water]
+      methods: [Touch]
+      effects:
+      - !type:SpawnEntityInInventory
+        slot: head
+        entity: WaterDropletHat
+    - reagents: [Water, SpaceCleaner]
+      methods: [Touch]
+      effects:
+      - !type:WashCreamPie
+  - type: Bloodstream
+    bloodReferenceSolution:
+      reagents:
+      - ReagentId: CopperBlood
+        Quantity: 300
+  - type: MeleeWeapon
+    animation: WeaponArcBite
+    soundHit:
+      path: /Audio/Effects/bite.ogg
+    damage:
+      types:
+        Piercing: 5
+  - type: DamageVisuals
+    damageOverlayGroups:
+      Brute:
+        sprite: Mobs/Effects/brute_damage.rsi
+        color: "#162581"
+      Burn:
+        sprite: Mobs/Effects/burn_damage.rsi
+  - type: Speech
+    speechVerb: Arachnid
+    speechSounds: Arachnid
+    allowedEmotes: ['Click', 'Chitter']
+  - type: Vocal
+    sounds:
+      Male: UnisexArachnid
+      Female: UnisexArachnid
+      Unsexed: UnisexArachnid
+  - type: TypingIndicator
+    proto: spider
+
+- type: entity
+  parent: OrganBase
+  id: OrganArachnid
+  abstract: true
+  suffix: Arachnid
+
+- type: entity
+  id: OrganArachnidMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Arachnid ]
+
+- type: entity
+  parent: OrganArachnid
+  id: OrganArachnidInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Arachnid/organs.rsi
+
+- type: entity
+  parent: OrganArachnid
+  id: OrganArachnidExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Arachnid/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganArachnidExternal ]
+  id: OrganArachnidTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganArachnidExternal ]
+  id: OrganArachnidHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganArachnidExternal ]
+  id: OrganArachnidArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganArachnidExternal ]
+  id: OrganArachnidArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganArachnidExternal ]
+  id: OrganArachnidHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganArachnidExternal ]
+  id: OrganArachnidHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganArachnidExternal ]
+  id: OrganArachnidLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganArachnidExternal ]
+  id: OrganArachnidLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganArachnidExternal ]
+  id: OrganArachnidFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganArachnidExternal ]
+  id: OrganArachnidFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganSpriteHumanInternal, OrganArachnidInternal ]
+  id: OrganArachnidBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganArachnidInternal ]
+  id: OrganArachnidEyes
+
+- type: entity
+  parent: [ OrganBaseTongue, OrganArachnidInternal ]
+  id: OrganArachnidTongue
+
+- type: entity
+  parent: [ OrganBaseAppendix, OrganSpriteHumanInternal, OrganArachnidInternal ]
+  id: OrganArachnidAppendix
+
+- type: entity
+  parent: [ OrganBaseEars, OrganSpriteHumanInternal, OrganArachnidInternal ]
+  id: OrganArachnidEars
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganArachnidInternal, OrganArachnidMetabolizer ]
+  id: OrganArachnidLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganArachnidInternal, OrganArachnidMetabolizer ]
+  id: OrganArachnidHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganArachnidInternal, OrganArachnidMetabolizer ]
+  id: OrganArachnidStomach
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganSpriteHumanInternal, OrganArachnidInternal, OrganArachnidMetabolizer ]
+  id: OrganArachnidLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganSpriteHumanInternal, OrganArachnidInternal, OrganArachnidMetabolizer ]
+  id: OrganArachnidKidneys
diff --git a/Resources/Prototypes/Body/Species/diona.yml b/Resources/Prototypes/Body/Species/diona.yml
new file mode 100644 (file)
index 0000000..630fd73
--- /dev/null
@@ -0,0 +1,321 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceDiona
+  name: diona appearance
+  components:
+  - type: Inventory
+    templateId: diona
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganDionaTorso
+        - id: OrganDionaHead
+        - id: OrganDionaArmLeft
+        - id: OrganDionaArmRight
+        - id: OrganDionaHandRight
+        - id: OrganDionaHandLeft
+        - id: OrganDionaLegLeft
+        - id: OrganDionaLegRight
+        - id: OrganDionaFootLeft
+        - id: OrganDionaFootRight
+        - id: OrganDionaBrainNymphing
+        - id: OrganDionaEyes
+        - id: OrganDionaLungsNymphing
+        - id: OrganDionaStomachNymphing
+  - type: HumanoidAppearance
+    species: Diona
+
+- type: entity
+  parent:
+  - AppearanceDiona
+  - BaseSpeciesMobOrganic
+  id: MobDiona
+  name: McUrist Plants
+  components:
+  - type: Respirator
+    damage:
+      types:
+        Asphyxiation: 0.5
+    damageRecovery:
+      types:
+        Asphyxiation: -1.0
+  - type: Hunger
+    baseDecayRate: 0.0083
+  - type: Thirst
+    baseDecayRate: 0.0083
+  - type: Damageable
+    damageModifierSet: Diona
+  - type: DamageVisuals
+    damageOverlayGroups:
+      Brute:
+        sprite: Mobs/Effects/brute_damage.rsi
+        color: "#cd7314"
+      Burn:
+        sprite: Mobs/Effects/burn_damage.rsi
+  - type: Butcherable
+    butcheringType: Spike
+    spawned:
+      - id: FoodMeatPlant
+        amount: 5
+  - type: Bloodstream
+    bloodReferenceSolution:
+      reagents:
+      - ReagentId: Sap
+        Quantity: 300
+  - type: Reactive
+    groups:
+      Flammable: [ Touch ]
+      Extinguish: [ Touch ]
+      Acidic: [Touch, Ingestion]
+    reactions:
+    - reagents: [Water, SpaceCleaner]
+      methods: [Touch]
+      effects:
+      - !type:WashCreamPie
+    - reagents: [ PlantBGone ]
+      methods: [ Touch ]
+      effects:
+      - !type:HealthChange
+        damage:
+          types:
+            Blunt: 0.05
+            Slash: 0.05
+            Piercing: 0.075
+      - !type:PopupMessage
+        type: Local
+        visualType: Large
+        messages: [ "diona-hurt-by-herbicide-popup" ]
+        probability: 0.66
+    - reagents: [ WeedKiller ]
+      methods: [ Touch ]
+      effects:
+      - !type:HealthChange
+        damage:
+          types:
+            Poison: 0.125
+      - !type:PopupMessage
+        type: Local
+        visualType: Large
+        messages: [ "diona-hurt-by-herbicide-popup" ]
+        probability: 0.66
+  - type: Fixtures
+    fixtures:
+      fix1:
+        shape:
+          !type:PhysShapeCircle
+          radius: 0.35
+        density: 300 #weighs more than humans because wood
+        restitution: 0.0
+        mask:
+          - MobMask
+        layer:
+          - MobLayer
+  - type: Speech
+    speechVerb: Plant
+    allowedEmotes: ['Chirp']
+  - type: Vocal
+    sounds:
+      Male: UnisexDiona
+      Female: UnisexDiona
+      Unsexed: UnisexDiona
+  - type: TypingIndicator
+    proto: diona
+  - type: BodyEmotes
+    soundsId: DionaBodyEmotes
+  - type: IgnoreKudzu
+  - type: IgniteOnHeatDamage
+    fireStacks: 1
+    threshold: 12
+  - type: GibAction
+    actionPrototype: DionaGibAction
+    allowedStates:
+    - Dead
+  - type: Rootable
+
+- type: entity
+  parent: OrganBase
+  id: OrganDiona
+  abstract: true
+  suffix: Diona
+
+- type: entity
+  id: OrganDionaMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Plant ]
+
+- type: entity
+  parent: OrganDiona
+  id: OrganDionaInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Diona/organs.rsi
+
+- type: entity
+  parent: OrganDiona
+  id: OrganDionaExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Diona/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganDionaExternal ]
+  id: OrganDionaTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganDionaExternal ]
+  id: OrganDionaHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganDionaExternal ]
+  id: OrganDionaArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganDionaExternal ]
+  id: OrganDionaArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganDionaExternal ]
+  id: OrganDionaHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganDionaExternal ]
+  id: OrganDionaHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganDionaExternal ]
+  id: OrganDionaLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganDionaExternal ]
+  id: OrganDionaLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganDionaExternal ]
+  id: OrganDionaFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganDionaExternal ]
+  id: OrganDionaFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganDionaInternal ]
+  id: OrganDionaBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganDionaInternal ]
+  id: OrganDionaEyes
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganDionaInternal, OrganDionaMetabolizer ]
+  id: OrganDionaLungs
+  components:
+  - type: Sprite
+    layers:
+    - state: lungs
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganDionaInternal, OrganDionaMetabolizer ]
+  id: OrganDionaStomach
+  components:
+  - type: Metabolizer
+    maxReagents: 6
+    removeEmpty: true
+    groups:
+    - id: Food
+    - id: Drink
+    - id: Medicine
+    - id: Poison
+    - id: Narcotic
+    - id: Alcohol
+
+- type: entity
+  parent: OrganDionaBrain
+  suffix: "Diona, Nymphing"
+  id: OrganDionaBrainNymphing
+  components:
+  - type: Nymph
+    entityPrototype: OrganDionaNymphBrain
+
+- type: entity
+  parent: OrganDionaLungs
+  suffix: "Diona, Nymphing"
+  id: OrganDionaLungsNymphing
+  components:
+  - type: Nymph
+    entityPrototype: OrganDionaNymphLungs
+
+- type: entity
+  parent: OrganDionaStomach
+  suffix: "Diona, Nymphing"
+  id: OrganDionaStomachNymphing
+  components:
+  - type: Nymph
+    entityPrototype: OrganDionaNymphStomach
+
+- type: entity
+  parent: MobDionaNymph
+  id: OrganDionaNymphBrain
+  suffix: brain
+  components:
+  - type: IsDeadIC
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganDionaBrain
+        - id: OrganAnimalLungs
+        - id: OrganAnimalStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalHeart
+        - id: OrganAnimalKidneys
+
+- type: entity
+  parent: MobDionaNymph
+  id: OrganDionaNymphStomach
+  suffix: stomach
+  components:
+  - type: IsDeadIC
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganDionaLungs
+        - id: OrganAnimalStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalHeart
+        - id: OrganAnimalKidneys
+
+- type: entity
+  parent: MobDionaNymph
+  id: OrganDionaNymphLungs
+  suffix: lungs
+  components:
+  - type: IsDeadIC
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganAnimalLungs
+        - id: OrganDionaStomach
+        - id: OrganAnimalLiver
+        - id: OrganAnimalHeart
+        - id: OrganAnimalKidneys
+
+- type: entity
+  parent: MobDiona
+  id: MobDionaReformed
+  categories: [ HideSpawnMenu ]
+  components:
+  - type: IsDeadIC
+  - type: RandomHumanoidAppearance
diff --git a/Resources/Prototypes/Body/Species/dwarf.yml b/Resources/Prototypes/Body/Species/dwarf.yml
new file mode 100644 (file)
index 0000000..cfc9e43
--- /dev/null
@@ -0,0 +1,98 @@
+- type: entity
+  parent: AppearanceHuman
+  id: AppearanceDwarf
+  name: dwarf appearance
+  components:
+  - type: Inventory
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganHumanTorso
+        - id: OrganHumanHead
+        - id: OrganHumanArmLeft
+        - id: OrganHumanArmRight
+        - id: OrganHumanHandRight
+        - id: OrganHumanHandLeft
+        - id: OrganHumanLegLeft
+        - id: OrganHumanLegRight
+        - id: OrganHumanFootLeft
+        - id: OrganHumanFootRight
+        - id: OrganHumanBrain
+        - id: OrganHumanEyes
+        - id: OrganHumanTongue
+        - id: OrganHumanAppendix
+        - id: OrganHumanEars
+        - id: OrganHumanLungs
+        - id: OrganDwarfHeart
+        - id: OrganDwarfStomach
+        - id: OrganDwarfLiver
+        - id: OrganHumanKidneys
+  - type: HumanoidAppearance
+    species: Dwarf
+  - type: ScaleVisuals
+    scale: 1, 0.8
+
+- type: entity
+  parent:
+  - AppearanceDwarf
+  - MobHuman
+  id: MobDwarf
+  name: Urist McHands The Dwarf
+  components:
+  - type: Fixtures
+    fixtures: # TODO: This needs a second fixture just for mob collisions.
+      fix1:
+        shape:
+          !type:PhysShapeCircle
+          radius: 0.35
+        # they r smaller
+        density: 120
+        restitution: 0.0
+        mask:
+        - MobMask
+        layer:
+        - MobLayer
+  - type: Vocal
+    sounds:
+      Male: UnisexDwarf
+      Female: FemaleDwarf
+      Unsexed: UnisexDwarf
+  - type: ReplacementAccent
+    accent: dwarf
+  - type: Speech
+    speechSounds: Bass
+
+- type: entity
+  parent: OrganBase
+  id: OrganDwarf
+  abstract: true
+  suffix: Dwarf
+
+- type: entity
+  id: OrganDwarfMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Dwarf ]
+
+- type: entity
+  parent: [ OrganDwarfMetabolizer, OrganHumanStomach ]
+  id: OrganDwarfStomach
+  components:
+  - type: Metabolizer
+    maxReagents: 5
+
+- type: entity
+  parent: [ OrganDwarfMetabolizer, OrganHumanLiver ]
+  id: OrganDwarfLiver
+
+- type: entity
+  parent: [ OrganDwarfMetabolizer, OrganHumanHeart ]
+  id: OrganDwarfHeart
diff --git a/Resources/Prototypes/Body/Species/gingerbread.yml b/Resources/Prototypes/Body/Species/gingerbread.yml
new file mode 100644 (file)
index 0000000..6b528e9
--- /dev/null
@@ -0,0 +1,153 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceGingerbread
+  name: gingerbread appearance
+  components:
+  - type: Inventory
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganGingerbreadTorso
+        - id: OrganGingerbreadHead
+        - id: OrganGingerbreadArmLeft
+        - id: OrganGingerbreadArmRight
+        - id: OrganGingerbreadHandRight
+        - id: OrganGingerbreadHandLeft
+        - id: OrganGingerbreadLegLeft
+        - id: OrganGingerbreadLegRight
+        - id: OrganGingerbreadFootLeft
+        - id: OrganGingerbreadFootRight
+        - id: OrganHumanBrain
+        - id: OrganHumanEyes
+        - id: OrganHumanTongue
+        - id: OrganHumanAppendix
+        - id: OrganHumanEars
+        - id: OrganHumanLungs
+        - id: OrganHumanHeart
+        - id: OrganHumanStomach
+        - id: OrganHumanLiver
+        - id: OrganHumanKidneys
+  - type: HumanoidAppearance
+    species: Gingerbread
+
+- type: entity
+  parent:
+  - AppearanceGingerbread
+  - BaseSpeciesMobOrganic
+  id: MobGingerbread
+  name: Urist McCookie
+  components:
+  - type: Butcherable
+    spawned:
+    - id: FoodBakedCookie
+      amount: 5
+  - type: Damageable
+    damageModifierSet: Gingerbread
+  - type: DamageVisuals
+    damageOverlayGroups:
+      Brute:
+        sprite: Mobs/Effects/brute_damage.rsi
+        color: "#896e55"
+      Burn:
+        sprite: Mobs/Effects/burn_damage.rsi
+  - type: Bloodstream
+    bloodReferenceSolution:
+      reagents:
+      - ReagentId: Sugar
+        Quantity: 100
+      - ReagentId: Butter
+        Quantity: 200
+  - type: Fixtures
+    fixtures:
+      fix1:
+        shape:
+          !type:PhysShapeCircle
+          radius: 0.35
+        density: 100 #fairly light
+        restitution: 0.0
+        mask:
+          - MobMask
+        layer:
+          - MobLayer
+  - type: TypingIndicator
+    proto: gingerbread
+
+- type: entity
+  parent: OrganBase
+  id: OrganGingerbread
+  abstract: true
+  suffix: gingerbread
+
+- type: entity
+  parent: OrganGingerbread
+  id: OrganGingerbreadExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Gingerbread/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganGingerbreadExternal ]
+  id: OrganGingerbreadTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganGingerbreadExternal ]
+  id: OrganGingerbreadHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganGingerbreadExternal ]
+  id: OrganGingerbreadArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganGingerbreadExternal ]
+  id: OrganGingerbreadArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganGingerbreadExternal ]
+  id: OrganGingerbreadHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganGingerbreadExternal ]
+  id: OrganGingerbreadHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganGingerbreadExternal ]
+  id: OrganGingerbreadLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganGingerbreadExternal ]
+  id: OrganGingerbreadLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganGingerbreadExternal ]
+  id: OrganGingerbreadFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganGingerbreadExternal ]
+  id: OrganGingerbreadFootRight
+
+- type: entity
+  name: gingerbread man
+  id: MobGingerbreadAI
+  parent: [ MobGingerbread, MobCombat ]
+  components:
+  - type: GhostRole
+    name: ghost-role-information-gingerbread-name
+    description: ghost-role-information-gingerbread-description
+    rules: ghost-role-information-nonantagonist-rules
+  - type: GhostTakeoverAvailable
+  - type: NPCRetaliation
+  - type: FactionException
+  - type: NpcFactionMember
+    factions:
+    - Passive
+  - type: HTN
+    rootTask:
+      task: SimpleHostileCompound
diff --git a/Resources/Prototypes/Body/Species/human.yml b/Resources/Prototypes/Body/Species/human.yml
new file mode 100644 (file)
index 0000000..5f4d65d
--- /dev/null
@@ -0,0 +1,162 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceHuman
+  name: human appearance
+  components:
+  - type: Inventory
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganHumanTorso
+        - id: OrganHumanHead
+        - id: OrganHumanArmLeft
+        - id: OrganHumanArmRight
+        - id: OrganHumanHandRight
+        - id: OrganHumanHandLeft
+        - id: OrganHumanLegLeft
+        - id: OrganHumanLegRight
+        - id: OrganHumanFootLeft
+        - id: OrganHumanFootRight
+        - id: OrganHumanBrain
+        - id: OrganHumanEyes
+        - id: OrganHumanTongue
+        - id: OrganHumanAppendix
+        - id: OrganHumanEars
+        - id: OrganHumanLungs
+        - id: OrganHumanHeart
+        - id: OrganHumanStomach
+        - id: OrganHumanLiver
+        - id: OrganHumanKidneys
+  - type: HumanoidAppearance
+    species: Human
+    hideLayersOnEquip:
+    - Hair
+    - Snout
+
+- type: entity
+  parent:
+  - AppearanceHuman
+  - BaseSpeciesMobOrganic
+  id: MobHuman
+  name: Urist McHands
+  components:
+  - type: Butcherable
+    spawned:
+    - id: FoodMeatHuman
+      amount: 5
+
+- type: entity
+  parent: OrganBase
+  id: OrganHuman
+  abstract: true
+  suffix: human
+
+- type: entity
+  id: OrganHumanMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Human ]
+
+- type: entity
+  parent: OrganHuman
+  id: OrganHumanInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/organs.rsi
+
+- type: entity
+  parent: OrganHuman
+  id: OrganHumanExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganHumanExternal ]
+  id: OrganHumanTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganHumanExternal ]
+  id: OrganHumanHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganHumanExternal ]
+  id: OrganHumanArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganHumanExternal ]
+  id: OrganHumanArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganHumanExternal ]
+  id: OrganHumanHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganHumanExternal ]
+  id: OrganHumanHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganHumanExternal ]
+  id: OrganHumanLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganHumanExternal ]
+  id: OrganHumanLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganHumanExternal ]
+  id: OrganHumanFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganHumanExternal ]
+  id: OrganHumanFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganHumanInternal ]
+  id: OrganHumanBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganHumanInternal ]
+  id: OrganHumanEyes
+
+- type: entity
+  parent: [ OrganBaseTongue, OrganHumanInternal ]
+  id: OrganHumanTongue
+
+- type: entity
+  parent: [ OrganBaseAppendix, OrganHumanInternal ]
+  id: OrganHumanAppendix
+
+- type: entity
+  parent: [ OrganBaseEars, OrganHumanInternal ]
+  id: OrganHumanEars
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganHumanInternal, OrganHumanMetabolizer ]
+  id: OrganHumanLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganHumanInternal, OrganHumanMetabolizer ]
+  id: OrganHumanHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganHumanInternal, OrganHumanMetabolizer ]
+  id: OrganHumanStomach
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganHumanInternal, OrganHumanMetabolizer ]
+  id: OrganHumanLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganHumanInternal, OrganHumanMetabolizer ]
+  id: OrganHumanKidneys
diff --git a/Resources/Prototypes/Body/Species/moth.yml b/Resources/Prototypes/Body/Species/moth.yml
new file mode 100644 (file)
index 0000000..d274a06
--- /dev/null
@@ -0,0 +1,261 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceMoth
+  name: moth appearance
+  components:
+  - type: Inventory
+    speciesId: moth
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: jumpsuit-female
+      back:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: back
+      outerClothing:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: outerclothing
+      gloves:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: hand
+      shoes:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: shoes
+    displacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: jumpsuit-male
+      back:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: back
+      outerClothing:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: outerclothing
+      gloves:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: hand
+      shoes:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Moth/displacement.rsi
+            state: shoes
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganMothTorso
+        - id: OrganMothHead
+        - id: OrganMothArmLeft
+        - id: OrganMothArmRight
+        - id: OrganMothHandRight
+        - id: OrganMothHandLeft
+        - id: OrganMothLegLeft
+        - id: OrganMothLegRight
+        - id: OrganMothFootLeft
+        - id: OrganMothFootRight
+        - id: OrganMothBrain
+        - id: OrganMothEyes
+        - id: OrganMothTongue
+        - id: OrganMothAppendix
+        - id: OrganMothEars
+        - id: OrganMothLungs
+        - id: OrganMothHeart
+        - id: OrganMothStomach
+        - id: OrganMothLiver
+        - id: OrganMothKidneys
+  - type: HumanoidAppearance
+    species: Moth
+
+- type: entity
+  parent:
+  - AppearanceMoth
+  - BaseSpeciesMobOrganic
+  id: MobMoth
+  name: Urist McFluff
+  components:
+  - type: Damageable
+    damageModifierSet: Moth
+  - type: ZombieAccentOverride
+    accent: zombieMoth
+  - type: Speech
+    speechVerb: Moth
+    allowedEmotes: ['Chitter', 'Squeak']
+  - type: TypingIndicator
+    proto: moth
+  - type: Bloodstream
+    bloodReferenceSolution:
+      reagents:
+      - ReagentId: InsectBlood
+        Quantity: 300
+  - type: DamageVisuals
+    damageOverlayGroups:
+      Brute:
+        sprite: Mobs/Effects/brute_damage.rsi
+        color: "#808A51"
+      Burn:
+        sprite: Mobs/Effects/burn_damage.rsi
+  - type: MothAccent
+  - type: Vocal
+    sounds:
+      Male: UnisexMoth
+      Female: UnisexMoth
+      Unsexed: UnisexMoth
+  - type: MovementSpeedModifier
+    baseWeightlessAcceleration: 1.5 # Move around more easily in space.
+    baseWeightlessFriction: 1
+    baseWeightlessModifier: 1
+  - type: Flammable
+    damage:
+      types:
+        Heat: 2.5 # moths burn more easily
+  - type: Temperature
+    currentTemperature: 310.15
+    specificHeat: 46
+  - type: TemperatureDamage # Moths hate the heat and thrive in the cold.
+    heatDamageThreshold: 320
+    coldDamageThreshold: 230
+    coldDamage:
+      types:
+        Cold: 0.05 # per second, scales with temperature & other constants
+    heatDamage:
+      types:
+        Heat: 3 # per second, scales with temperature & other constants
+  - type: TemperatureSpeed
+    thresholds:
+      289: 0.9
+      275: 0.8
+      250: 0.7
+
+- type: entity
+  parent: OrganBase
+  id: OrganMoth
+  abstract: true
+  suffix: Moth
+
+- type: entity
+  id: OrganMothMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Moth ]
+
+- type: entity
+  parent: OrganMoth
+  id: OrganMothInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/organs.rsi
+
+- type: entity
+  parent: OrganMoth
+  id: OrganMothExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Moth/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganMothExternal ]
+  id: OrganMothTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganMothExternal ]
+  id: OrganMothHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganMothExternal ]
+  id: OrganMothArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganMothExternal ]
+  id: OrganMothArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganMothExternal ]
+  id: OrganMothHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganMothExternal ]
+  id: OrganMothHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganMothExternal ]
+  id: OrganMothLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganMothExternal ]
+  id: OrganMothLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganMothExternal ]
+  id: OrganMothFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganMothExternal ]
+  id: OrganMothFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganSpriteHumanInternal, OrganMothInternal ]
+  id: OrganMothBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganMothInternal ]
+  id: OrganMothEyes
+
+- type: entity
+  parent: [ OrganBaseTongue, OrganMothInternal ]
+  id: OrganMothTongue
+
+- type: entity
+  parent: [ OrganBaseAppendix, OrganSpriteHumanInternal, OrganMothInternal ]
+  id: OrganMothAppendix
+
+- type: entity
+  parent: [ OrganBaseEars, OrganSpriteHumanInternal, OrganMothInternal ]
+  id: OrganMothEars
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganMothInternal, OrganMothMetabolizer ]
+  id: OrganMothLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganMothInternal, OrganAnimalMetabolizer ]
+  id: OrganMothHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganMothInternal, OrganMothMetabolizer ]
+  id: OrganMothStomach
+  components:
+  - type: Stomach
+    specialDigestible:
+      tags:
+      - ClothMade
+      - Paper
+      - Pill
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganSpriteHumanInternal, OrganMothInternal, OrganAnimalMetabolizer ]
+  id: OrganMothLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganSpriteHumanInternal, OrganMothInternal, OrganMothMetabolizer ]
+  id: OrganMothKidneys
diff --git a/Resources/Prototypes/Body/Species/reptilian.yml b/Resources/Prototypes/Body/Species/reptilian.yml
new file mode 100644 (file)
index 0000000..4a7a4f2
--- /dev/null
@@ -0,0 +1,242 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceReptilian
+  name: reptilian appearance
+  components:
+  - type: Inventory
+    speciesId: reptilian
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+      head:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Reptilian/displacement.rsi
+            state: head
+      mask:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Reptilian/displacement.rsi
+            state: mask
+    displacements:
+      head:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Reptilian/displacement.rsi
+            state: head
+      mask:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Reptilian/displacement.rsi
+            state: mask
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganReptilianTorso
+        - id: OrganReptilianHead
+        - id: OrganReptilianArmLeft
+        - id: OrganReptilianArmRight
+        - id: OrganReptilianHandRight
+        - id: OrganReptilianHandLeft
+        - id: OrganReptilianLegLeft
+        - id: OrganReptilianLegRight
+        - id: OrganReptilianFootLeft
+        - id: OrganReptilianFootRight
+        - id: OrganReptilianBrain
+        - id: OrganReptilianEyes
+        - id: OrganReptilianTongue
+        - id: OrganReptilianAppendix
+        - id: OrganReptilianEars
+        - id: OrganReptilianLungs
+        - id: OrganReptilianHeart
+        - id: OrganReptilianStomach
+        - id: OrganReptilianLiver
+        - id: OrganReptilianKidneys
+  - type: HumanoidAppearance
+    species: Reptilian
+    hideLayersOnEquip:
+    - Snout
+    - HeadTop
+    - HeadSide
+    - Tail
+    undergarmentBottom: UndergarmentBottomBoxersReptilian
+
+- type: entity
+  parent:
+  - AppearanceReptilian
+  - BaseSpeciesMobOrganic
+  id: MobReptilian
+  name: Urissst Mz'Hand
+  components:
+  - type: Puller
+    needsHands: false
+  - type: Butcherable
+    butcheringType: Spike
+    spawned:
+    - id: FoodMeatLizard
+      amount: 5
+  - type: LizardAccent
+  - type: Speech
+    speechSounds: Lizard
+    speechVerb: Reptilian
+    allowedEmotes: ['Thump']
+  - type: TypingIndicator
+    proto: lizard
+  - type: Vocal
+    sounds:
+      Male: MaleReptilian
+      Female: FemaleReptilian
+      Unsexed: MaleReptilian
+  - type: BodyEmotes
+    soundsId: ReptilianBodyEmotes
+  - type: Damageable
+    damageModifierSet: Scale
+  - type: MeleeWeapon
+    soundHit:
+      collection: AlienClaw
+    angle: 30
+    animation: WeaponArcClaw
+    damage:
+      types:
+        Slash: 5
+  - type: Temperature
+    currentTemperature: 310.15
+    specificHeat: 42
+  - type: TemperatureDamage
+    heatDamageThreshold: 400
+    coldDamageThreshold: 285
+    coldDamage:
+      types:
+        Cold : 0.1 #per second, scales with temperature & other constants
+    heatDamage:
+      types:
+        Heat : 1.5 #per second, scales with temperature & other constants
+  - type: TemperatureSpeed
+    thresholds:
+      301: 0.9
+      295: 0.8
+      285: 0.7
+  - type: Wagging
+
+- type: entity
+  parent: OrganBase
+  id: OrganReptilian
+  abstract: true
+  suffix: Reptilian
+
+- type: entity
+  id: OrganReptilianMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Animal ]
+
+- type: entity
+  parent: OrganReptilian
+  id: OrganReptilianInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/organs.rsi
+
+- type: entity
+  parent: OrganReptilian
+  id: OrganReptilianExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Reptilian/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganReptilianExternal ]
+  id: OrganReptilianTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganReptilianExternal ]
+  id: OrganReptilianHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganReptilianExternal ]
+  id: OrganReptilianArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganReptilianExternal ]
+  id: OrganReptilianArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganReptilianExternal ]
+  id: OrganReptilianHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganReptilianExternal ]
+  id: OrganReptilianHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganReptilianExternal ]
+  id: OrganReptilianLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganReptilianExternal ]
+  id: OrganReptilianLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganReptilianExternal ]
+  id: OrganReptilianFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganReptilianExternal ]
+  id: OrganReptilianFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganSpriteHumanInternal, OrganReptilianInternal ]
+  id: OrganReptilianBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganReptilianInternal ]
+  id: OrganReptilianEyes
+
+- type: entity
+  parent: [ OrganBaseTongue, OrganReptilianInternal ]
+  id: OrganReptilianTongue
+
+- type: entity
+  parent: [ OrganBaseAppendix, OrganSpriteHumanInternal, OrganReptilianInternal ]
+  id: OrganReptilianAppendix
+
+- type: entity
+  parent: [ OrganBaseEars, OrganSpriteHumanInternal, OrganReptilianInternal ]
+  id: OrganReptilianEars
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganReptilianInternal, OrganReptilianMetabolizer ]
+  id: OrganReptilianLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganReptilianInternal, OrganReptilianMetabolizer ]
+  id: OrganReptilianHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganReptilianInternal, OrganReptilianMetabolizer ]
+  id: OrganReptilianStomach
+  components:
+  - type: Stomach
+    specialDigestible:
+      tags:
+      - Fruit
+      - ReptilianFood
+      - Meat
+      - Pill
+      - Crayon
+      - Paper
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganSpriteHumanInternal, OrganReptilianInternal, OrganReptilianMetabolizer ]
+  id: OrganReptilianLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganSpriteHumanInternal, OrganReptilianInternal, OrganReptilianMetabolizer ]
+  id: OrganReptilianKidneys
similarity index 59%
rename from Resources/Prototypes/Entities/Mobs/Species/skeleton.yml
rename to Resources/Prototypes/Body/Species/skeleton.yml
index a03a5476e26bb763d8edf2df24387a8878daeec0..5cddd68e1ad5f477b9d1215309e42de25ada0bac 100644 (file)
@@ -1,24 +1,42 @@
 - type: entity
-  save: false
-  name: Urist McSkelly
-  parent:
-  - MobFlammable
-  - BaseMobSpecies
-  id: BaseMobSkeletonPerson
-  abstract: true
+  parent: BaseSpeciesAppearance
+  id: AppearanceSkeletonPerson
+  name: skeletonperson appearance
   components:
+  - type: Inventory
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganSkeletonPersonTorso
+        - id: OrganSkeletonPersonHead
+        - id: OrganSkeletonPersonArmLeft
+        - id: OrganSkeletonPersonArmRight
+        - id: OrganSkeletonPersonHandRight
+        - id: OrganSkeletonPersonHandLeft
+        - id: OrganSkeletonPersonLegLeft
+        - id: OrganSkeletonPersonLegRight
+        - id: OrganSkeletonPersonFootLeft
+        - id: OrganSkeletonPersonFootRight
   - type: HumanoidAppearance
     species: Skeleton
-  - type: Icon
-    sprite: Mobs/Species/Skeleton/parts.rsi
-    state: full
-  - type: Body
-    prototype: Skeleton
-    requiredLegs: 2
-    gibSound: /Audio/Effects/bone_rattle.ogg
+
+- type: entity
+  parent:
+  - AppearanceSkeletonPerson
+  - BaseSpeciesMob
+  id: MobSkeletonPerson
+  name: Urist McSkelly
+  components:
   - type: Damageable
-    damageContainer: BiologicalMetaphysical # Allows them to take Holy damage
-    damageModifierSet: Skeleton # If we get non-Holy metaphysical damage types in the future, the Skeleton set might need to be adjusted to provide immunity to them (depends on what exactly the new types are)
+    damageContainer: BiologicalMetaphysical
+    damageModifierSet: Skeleton
   - type: DamageVisuals
     damageOverlayGroups:
       Brute:
@@ -26,7 +44,6 @@
         color: "#555555AA"
       Burn:
         sprite: Mobs/Effects/burn_damage.rsi
-  - type: MobState
   - type: MobThresholds
     thresholds:
       0: Alive
@@ -39,8 +56,8 @@
         !type:DamageTrigger
         damage: 150
       behaviors:
-      - !type:GibBehavior { }
-  - type: SlowOnDamage #modified speeds because they're so weak
+      - !type:GibBehavior
+  - type: SlowOnDamage
     speedModifierThresholds:
       60: 0.9
       80: 0.7
     alternateState: Standing
   - type: FlashImmunity
     showInExamine: false
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
   - type: Instrument
     program: 13 # Xylophone. Woodblock is 115 (another good option)
   - type: ActivatableUI
         type: HumanoidMarkingModifierBoundUserInterface
       enum.StrippingUiKey.Key:
         type: StrippableBoundUserInterface
+  - type: InteractionPopup
+    successChance: 1
+    interactSuccessString: hugging-success-generic
+    interactSuccessSound: /Audio/Effects/thudswoosh.ogg
+    messagePerceivedByOthers: hugging-success-generic-others
+
+- type: entity
+  parent: OrganBase
+  id: OrganSkeletonPerson
+  abstract: true
+  suffix: SkeletonPerson
 
 - type: entity
-  parent: BaseSpeciesDummy
-  id: MobSkeletonPersonDummy
-  categories: [ HideSpawnMenu ]
+  parent: OrganSkeletonPerson
+  id: OrganSkeletonPersonExternal
+  abstract: true
   components:
-  - type: HumanoidAppearance
-    species: Skeleton
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
+  - type: Sprite
+    sprite: Mobs/Species/Skeleton/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganSkeletonPersonExternal ]
+  id: OrganSkeletonPersonFootRight
diff --git a/Resources/Prototypes/Body/Species/slime.yml b/Resources/Prototypes/Body/Species/slime.yml
new file mode 100644 (file)
index 0000000..4d596c0
--- /dev/null
@@ -0,0 +1,232 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceSlimePerson
+  name: SlimePerson appearance
+  components:
+  - type: Inventory
+    femaleDisplacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Human/displacement.rsi
+            state: jumpsuit-female
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganSlimePersonTorso
+        - id: OrganSlimePersonHead
+        - id: OrganSlimePersonArmLeft
+        - id: OrganSlimePersonArmRight
+        - id: OrganSlimePersonHandRight
+        - id: OrganSlimePersonHandLeft
+        - id: OrganSlimePersonLegLeft
+        - id: OrganSlimePersonLegRight
+        - id: OrganSlimePersonFootLeft
+        - id: OrganSlimePersonFootRight
+        - id: OrganSlimePersonCore
+        - id: OrganSlimePersonLungs
+  - type: HumanoidAppearance
+    species: SlimePerson
+
+- type: entity
+  parent:
+  - AppearanceSlimePerson
+  - BaseSpeciesMobOrganic
+  id: MobSlimePerson
+  name: Urist McWobble
+  components:
+  - type: Storage
+    clickInsert: false
+    grid:
+    - 0,0,1,2
+    maxItemSize: Large
+    storageInsertSound:
+      path: /Audio/Voice/Slime/slime_squish.ogg
+  - type: ContainerContainer
+    containers:
+      storagebase: !type:Container
+        ents: []
+  - type: UserInterface
+    interfaces:
+      enum.StorageUiKey.Key:
+        type: StorageBoundUserInterface
+      enum.HumanoidMarkingModifierKey.Key:
+        type: HumanoidMarkingModifierBoundUserInterface
+      enum.StrippingUiKey.Key:
+        type: StrippableBoundUserInterface
+  - type: UseDelay
+    delay: 0.5
+  - type: Speech
+    speechVerb: Slime
+    speechSounds: Slime
+    allowedEmotes: ['Squish']
+  - type: TypingIndicator
+    proto: slime
+  - type: Vocal
+    sounds:
+      Male: MaleSlime
+      Female: FemaleSlime
+      Unsexed: MaleSlime
+  - type: Damageable
+    damageModifierSet: Slime
+  - type: PassiveDamage # Around 8 damage a minute healed
+    allowedStates:
+    - Alive
+    damageCap: 65
+    damage:
+      types:
+        Heat: -0.14
+      groups:
+        Brute: -0.14
+  - type: DamageVisuals
+    damageOverlayGroups:
+      Brute:
+        sprite: Mobs/Effects/brute_damage.rsi
+        color: "#2cf274"
+      Burn:
+        sprite: Mobs/Effects/burn_damage.rsi
+  - type: Bloodstream
+    bloodReferenceSolution: # TODO Color slime blood based on their slime color or smth
+      reagents:
+      - ReagentId: Slime
+        Quantity: 300
+  - type: Barotrauma
+    damage:
+      types:
+        Blunt: 0.50 #per second, scales with pressure and other constants.
+        Heat: 0.2 # 0.1 more than humans, i feel like low pressure would make slime boil more than blunt stretch them so i decided on this instead.
+  - type: Reactive
+    groups:
+      Flammable: [ Touch ]
+      Extinguish: [ Touch ]
+    reactions:
+    - reagents: [ Water, SpaceCleaner ]
+      methods: [ Touch ]
+      effects:
+      - !type:WashCreamPie
+    - reagents: [ Water ]
+      methods: [ Touch ]
+      effects:
+      - !type:HealthChange
+        damage:
+          types:
+            Heat: 0.05
+      - !type:PopupMessage
+        type: Local
+        visualType: Large
+        messages: [ "slime-hurt-by-water-popup" ]
+        probability: 0.25
+  - type: Butcherable
+    butcheringType: Spike
+    spawned:
+    - id: FoodMeatSlime
+      amount: 5
+  - type: Respirator
+    damage:
+      types:
+        Asphyxiation: 0.2
+    damageRecovery:
+      types:
+        Asphyxiation: -1.0
+    maxSaturation: 15
+
+- type: entity
+  parent: OrganBase
+  id: OrganSlimePerson
+  abstract: true
+  suffix: slime person
+
+- type: entity
+  id: OrganSlimePersonMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Slime ]
+
+- type: entity
+  parent: OrganSlimePerson
+  id: OrganSlimePersonInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Slime/organs.rsi
+
+- type: entity
+  parent: OrganSlimePerson
+  id: OrganSlimePersonExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Slime/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganSlimePersonExternal ]
+  id: OrganSlimePersonTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganSlimePersonExternal ]
+  id: OrganSlimePersonHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganSlimePersonExternal ]
+  id: OrganSlimePersonArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganSlimePersonExternal ]
+  id: OrganSlimePersonArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganSlimePersonExternal ]
+  id: OrganSlimePersonHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganSlimePersonExternal ]
+  id: OrganSlimePersonHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganSlimePersonExternal ]
+  id: OrganSlimePersonLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganSlimePersonExternal ]
+  id: OrganSlimePersonLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganSlimePersonExternal ]
+  id: OrganSlimePersonFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganSlimePersonExternal ]
+  id: OrganSlimePersonFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganSlimePersonInternal, OrganSlimePersonMetabolizer ]
+  id: OrganSlimePersonCore
+  name: sentient slime core
+  components:
+  - type: SolutionContainerManager
+    solutions:
+      stomach:
+        maxVol: 50.0
+  - type: Stomach
+  - type: Metabolizer
+    maxReagents: 6
+    metabolizerTypes: [ Slime ]
+    removeEmpty: true
+    groups:
+    - id: Food
+    - id: Drink
+    - id: Medicine
+    - id: Poison
+    - id: Narcotic
+    - id: Alcohol
+      rateModifier: 2.5
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganSlimePersonInternal, OrganSlimePersonMetabolizer ]
+  id: OrganSlimePersonLungs
+  name: gas sacs
+  components:
+  - type: Lung
+    alert: LowNitrogen
similarity index 52%
rename from Resources/Prototypes/Entities/Mobs/Species/vox.yml
rename to Resources/Prototypes/Body/Species/vox.yml
index f9ef0a357d6a72cf82c6687be99a3188cc8f687e..e25d17395592e5c0f9d09c2e19240671c7dc01da 100644 (file)
-- type: entity
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobVox
-  abstract: true
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceVox
+  name: vox appearance
   components:
-  - type: Hunger
-  - type: Thirst
-  - type: Icon
-    sprite: Mobs/Species/Vox/parts.rsi
-    state: vox_m
-  - type: Body
-    prototype: Vox
-    requiredLegs: 2
-    #- type: VoxAccent # Not yet coded
+  - type: Inventory
+    speciesId: vox
+    displacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: jumpsuit
+      eyes:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: eyes
+      gloves:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: hand
+      head:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: head
+      neck:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: neck
+      back:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: back
+      ears:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: ears
+      shoes:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: shoes
+  - type: Hands
+    leftHandDisplacement:
+      sizeMaps:
+        32:
+          sprite: Mobs/Species/Vox/displacement.rsi
+          state: hand_l
+    rightHandDisplacement:
+      sizeMaps:
+        32:
+          sprite: Mobs/Species/Vox/displacement.rsi
+          state: hand_r
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganVoxTorso
+        - id: OrganVoxHead
+        - id: OrganVoxArmLeft
+        - id: OrganVoxArmRight
+        - id: OrganVoxHandRight
+        - id: OrganVoxHandLeft
+        - id: OrganVoxLegLeft
+        - id: OrganVoxLegRight
+        - id: OrganVoxFootLeft
+        - id: OrganVoxFootRight
+        - id: OrganVoxBrain
+        - id: OrganVoxEyes
+        - id: OrganVoxTongue
+        - id: OrganVoxAppendix
+        - id: OrganVoxEars
+        - id: OrganVoxLungs
+        - id: OrganVoxHeart
+        - id: OrganVoxStomach
+        - id: OrganVoxLiver
+        - id: OrganVoxKidneys
+  - type: HumanoidAppearance
+    species: Vox
+    undergarmentTop: UndergarmentTopTanktopVox
+    undergarmentBottom: UndergarmentBottomBoxersVox
+    markingsDisplacement:
+      Hair:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vox/displacement.rsi
+            state: hair
+
+- type: entity
+  parent:
+  - AppearanceVox
+  - BaseSpeciesMobOrganic
+  id: MobVox
+  name: Uristititi McVox
+  components:
+  - type: Damageable
+    damageModifierSet: Vox
   - type: Speech
     speechVerb: Vox
     speechSounds: Vox
     spawned:
     - id: FoodMeatChicken
       amount: 5
-  - type: Damageable
-    damageContainer: Biological
-    damageModifierSet: Vox
   - type: Destructible
     thresholds:
     - trigger:
     damage:
       types:
         Slash: 5 # Reduce?
-  - type: Sprite # Need to redefine the whole order to draw the tail over their gas tank
-    layers:
-    - map: [ "enum.HumanoidVisualLayers.Chest" ]
-    - map: [ "enum.HumanoidVisualLayers.Head" ]
-    - map: [ "enum.HumanoidVisualLayers.Snout" ]
-    - map: [ "enum.HumanoidVisualLayers.Eyes" ]
-    - map: [ "enum.HumanoidVisualLayers.RArm" ]
-    - map: [ "enum.HumanoidVisualLayers.LArm" ]
-    - map: [ "enum.HumanoidVisualLayers.RLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.LLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
-    - map: [ "jumpsuit" ]
-    - map: [ "enum.HumanoidVisualLayers.LFoot" ]
-    - map: [ "enum.HumanoidVisualLayers.RFoot" ]
-    - map: [ "enum.HumanoidVisualLayers.LHand" ]
-    - map: [ "enum.HumanoidVisualLayers.RHand" ]
-    - map: [ "gloves" ]
-    - map: [ "shoes" ]
-    - map: [ "ears" ]
-    - map: [ "eyes" ]
-    - map: [ "belt" ]
-    - map: [ "id" ]
-    - map: [ "outerClothing" ]
-    - map: [ "back" ]
-    - map: [ "neck" ]
-    - map: [ "suitstorage" ] # This is not in the default order
-    - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
-    - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
-    - map: [ "enum.HumanoidVisualLayers.Hair" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
-    - map: [ "enum.HumanoidVisualLayers.Tail" ]
-    - map: [ "mask" ]
-    - map: [ "head" ]
-    - map: [ "pocket1" ]
-    - map: [ "pocket2" ]
-    - map: [ "enum.HumanoidVisualLayers.Handcuffs" ]
-      color: "#ffffff"
-      sprite: Objects/Misc/handcuffs.rsi
-      state: body-overlay-2
-      visible: false
-    - map: [ "clownedon" ]
-      sprite: "Effects/creampie.rsi"
-      state: "creampie_vox" # Not default
-      visible: false
-  - type: HumanoidAppearance
-    species: Vox
-    undergarmentTop: UndergarmentTopTanktopVox
-    undergarmentBottom: UndergarmentBottomBoxersVox
-    markingsDisplacement:
-      Hair:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: hair
-  - type: Inventory
-    speciesId: vox
-    displacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: jumpsuit
-      eyes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: eyes
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: hand
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: head
-      neck:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: neck
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: back
-      ears:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: ears
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: shoes
-  - type: Hands
-    leftHandDisplacement:
-      sizeMaps:
-        32:
-          sprite: Mobs/Species/Vox/displacement.rsi
-          state: hand_l
-    rightHandDisplacement:
-      sizeMaps:
-        32:
-          sprite: Mobs/Species/Vox/displacement.rsi
-          state: hand_r
 
 - type: entity
-  parent: BaseSpeciesDummy
-  id: MobVoxDummy
-  categories: [ HideSpawnMenu ]
+  parent: OrganBase
+  id: OrganVox
+  abstract: true
+  suffix: Vox
+
+- type: entity
+  id: OrganVoxMetabolizer
+  abstract: true
   components:
-  - type: HumanoidAppearance
-    species: Vox
-    undergarmentTop: UndergarmentTopTanktopVox
-    undergarmentBottom: UndergarmentBottomBoxersVox
-    markingsDisplacement:
-      Hair:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: hair
-  - type: Body
-    prototype: Vox
-  - type: Inventory
-    speciesId: vox
-    displacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: jumpsuit
-      eyes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: eyes
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: hand
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: head
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: back
-      ears:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: ears
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vox/displacement.rsi
-            state: shoes
-  - type: Hands
-    leftHandDisplacement:
-      sizeMaps:
-        32:
-          sprite: Mobs/Species/Vox/displacement.rsi
-          state: hand_l
-    rightHandDisplacement:
-      sizeMaps:
-        32:
-          sprite: Mobs/Species/Vox/displacement.rsi
-          state: hand_r
+  - type: Metabolizer
+    metabolizerTypes: [ Vox ]
+
+- type: entity
+  parent: OrganVox
+  id: OrganVoxInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Vox/organs.rsi
+
+- type: entity
+  parent: OrganVox
+  id: OrganVoxExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Vox/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganVoxExternal ]
+  id: OrganVoxTorso
+  components:
+  - type: Sprite
+    state: torso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganVoxExternal ]
+  id: OrganVoxHead
+  components:
+  - type: Sprite
+    state: head
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganVoxExternal ]
+  id: OrganVoxArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganVoxExternal ]
+  id: OrganVoxArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganVoxExternal ]
+  id: OrganVoxHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganVoxExternal ]
+  id: OrganVoxHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganVoxExternal ]
+  id: OrganVoxLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganVoxExternal ]
+  id: OrganVoxLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganVoxExternal ]
+  id: OrganVoxFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganVoxExternal ]
+  id: OrganVoxFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganSpriteHumanInternal, OrganVoxInternal ]
+  id: OrganVoxBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganVoxInternal ]
+  id: OrganVoxEyes
+
+- type: entity
+  parent: [ OrganBaseTongue, OrganVoxInternal ]
+  id: OrganVoxTongue
+
+- type: entity
+  parent: [ OrganBaseAppendix, OrganSpriteHumanInternal, OrganVoxInternal ]
+  id: OrganVoxAppendix
+
+- type: entity
+  parent: [ OrganBaseEars, OrganSpriteHumanInternal, OrganVoxInternal ]
+  id: OrganVoxEars
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganVoxInternal, OrganVoxMetabolizer ]
+  id: OrganVoxLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganVoxInternal, OrganVoxMetabolizer ]
+  id: OrganVoxHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganVoxInternal, OrganVoxMetabolizer ]
+  id: OrganVoxStomach
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganSpriteHumanInternal, OrganVoxInternal, OrganVoxMetabolizer ]
+  id: OrganVoxLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganSpriteHumanInternal, OrganVoxInternal, OrganVoxMetabolizer ]
+  id: OrganVoxKidneys
diff --git a/Resources/Prototypes/Body/Species/vulpkanin.yml b/Resources/Prototypes/Body/Species/vulpkanin.yml
new file mode 100644 (file)
index 0000000..6a3b657
--- /dev/null
@@ -0,0 +1,258 @@
+- type: entity
+  parent: BaseSpeciesAppearance
+  id: AppearanceVulpkanin
+  name: vulpkanin appearance
+  components:
+  - type: EntityTableContainerFill
+    containers:
+      body_organs: !type:AllSelector
+        children:
+        - id: OrganVulpkaninTorso
+        - id: OrganVulpkaninHead
+        - id: OrganVulpkaninArmLeft
+        - id: OrganVulpkaninArmRight
+        - id: OrganVulpkaninHandRight
+        - id: OrganVulpkaninHandLeft
+        - id: OrganVulpkaninLegLeft
+        - id: OrganVulpkaninLegRight
+        - id: OrganVulpkaninFootLeft
+        - id: OrganVulpkaninFootRight
+        - id: OrganVulpkaninBrain
+        - id: OrganVulpkaninEyes
+        - id: OrganVulpkaninTongue
+        - id: OrganVulpkaninAppendix
+        - id: OrganVulpkaninEars
+        - id: OrganVulpkaninLungs
+        - id: OrganVulpkaninHeart
+        - id: OrganVulpkaninStomach
+        - id: OrganVulpkaninLiver
+        - id: OrganVulpkaninKidneys
+  - type: HumanoidAppearance
+    species: Vulpkanin
+    undergarmentTop: UndergarmentTopTanktopVulpkanin
+    undergarmentBottom: UndergarmentBottomBoxersVulpkanin
+    hideLayersOnEquip:
+    - Snout
+    - SnoutCover
+    - HeadTop
+    - HeadSide
+    - FacialHair
+    - Hair
+    markingsDisplacement:
+      Hair:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: hair
+  - type: Inventory
+    speciesId: vulpkanin
+    displacements:
+      jumpsuit:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: jumpsuit
+      back:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: back
+      outerClothing:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: outerwear
+      gloves:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: hand
+      shoes:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: shoes
+      head:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: head
+      neck:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: neck
+      eyes:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: eyes
+      belt:
+        sizeMaps:
+          32:
+            sprite: Mobs/Species/Vulpkanin/displacement.rsi
+            state: belt
+
+- type: entity
+  parent:
+  - AppearanceVulpkanin
+  - BaseSpeciesMobOrganic
+  id: MobVulpkanin
+  name: Urist McArfArf
+  components:
+  - type: MessyDrinker
+    spillChance: 0.33
+  - type: Speech
+    speechSounds: Vulpkanin
+    speechVerb: Vulpkanin
+    allowedEmotes: [ 'Bark', 'Snarl', 'Whine', 'Howl', 'Growl' ]
+  - type: Vocal
+    sounds:
+      Male: MaleVulpkanin
+      Female: FemaleVulpkanin
+      Unsexed: MaleVulpkanin
+  - type: Damageable
+    damageModifierSet: Vulpkanin
+  - type: MeleeWeapon
+    soundHit:
+      path: /Audio/Weapons/pierce.ogg
+    animation: WeaponArcClaw
+    damage:
+      types:
+        Piercing: 2
+        Slash: 3
+  - type: Temperature # Same as moth temperatures until below is solved.
+    specificHeat: 44
+  - type: TemperatureDamage
+    heatDamageThreshold: 320 # TODO: 315 when there is a way to make the temperature alert not blink to the side of the screen and disappear when you "sweat" at 39C.
+    coldDamageThreshold: 230 # TODO: 220 when the above is solved.
+    coldDamage:
+      types:
+        Cold: 0.05 # Per second, scales with temperature & other constants
+    heatDamage:
+      types:
+        Heat: 2.5 # Per second, scales with temperature & other constants
+  # - type: Wagging TODO: Add back once we have animated tails again. Were removed due to the sprite rework, causing all of them to not fit anymore.
+  #   action: ActionToggleWaggingVulpkanin
+  - type: TemperatureProtection
+    heatingCoefficient: 1.2
+    coolingCoefficient: 0.3
+  - type: JumpAbility
+    action: ActionVulpkaninGravityJump
+    canCollide: true
+    jumpDistance: 3
+    jumpSound:
+      path: /Audio/Weapons/punchmiss.ogg
+      params:
+        pitch: 1.33
+        volume: -5
+        variation: 0.05
+
+- type: entity
+  parent: OrganBase
+  id: OrganVulpkanin
+  abstract: true
+  suffix: vulpkanin
+
+- type: entity
+  id: OrganVulpkaninMetabolizer
+  abstract: true
+  components:
+  - type: Metabolizer
+    metabolizerTypes: [ Animal ]
+
+- type: entity
+  parent: OrganVulpkanin
+  id: OrganVulpkaninInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/organs.rsi
+
+- type: entity
+  parent: OrganVulpkanin
+  id: OrganVulpkaninExternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Vulpkanin/parts.rsi
+
+- type: entity
+  parent: [ OrganBaseTorso, OrganVulpkaninExternal ]
+  id: OrganVulpkaninTorso
+
+- type: entity
+  parent: [ OrganBaseHead, OrganVulpkaninExternal ]
+  id: OrganVulpkaninHead
+
+- type: entity
+  parent: [ OrganBaseArmLeft, OrganVulpkaninExternal ]
+  id: OrganVulpkaninArmLeft
+
+- type: entity
+  parent: [ OrganBaseArmRight, OrganVulpkaninExternal ]
+  id: OrganVulpkaninArmRight
+
+- type: entity
+  parent: [ OrganBaseHandLeft, OrganVulpkaninExternal ]
+  id: OrganVulpkaninHandLeft
+
+- type: entity
+  parent: [ OrganBaseHandRight, OrganVulpkaninExternal ]
+  id: OrganVulpkaninHandRight
+
+- type: entity
+  parent: [ OrganBaseLegLeft, OrganVulpkaninExternal ]
+  id: OrganVulpkaninLegLeft
+
+- type: entity
+  parent: [ OrganBaseLegRight, OrganVulpkaninExternal ]
+  id: OrganVulpkaninLegRight
+
+- type: entity
+  parent: [ OrganBaseFootLeft, OrganVulpkaninExternal ]
+  id: OrganVulpkaninFootLeft
+
+- type: entity
+  parent: [ OrganBaseFootRight, OrganVulpkaninExternal ]
+  id: OrganVulpkaninFootRight
+
+- type: entity
+  parent: [ OrganBaseBrain, OrganSpriteHumanInternal, OrganVulpkaninInternal ]
+  id: OrganVulpkaninBrain
+
+- type: entity
+  parent: [ OrganBaseEyes, OrganVulpkaninInternal ]
+  id: OrganVulpkaninEyes
+
+- type: entity
+  parent: [ OrganBaseTongue, OrganVulpkaninInternal ]
+  id: OrganVulpkaninTongue
+
+- type: entity
+  parent: [ OrganBaseAppendix, OrganSpriteHumanInternal, OrganVulpkaninInternal ]
+  id: OrganVulpkaninAppendix
+
+- type: entity
+  parent: [ OrganBaseEars, OrganSpriteHumanInternal, OrganVulpkaninInternal ]
+  id: OrganVulpkaninEars
+
+- type: entity
+  parent: [ OrganBaseLungs, OrganVulpkaninInternal, OrganVulpkaninMetabolizer ]
+  id: OrganVulpkaninLungs
+
+- type: entity
+  parent: [ OrganBaseHeart, OrganVulpkaninInternal, OrganVulpkaninMetabolizer ]
+  id: OrganVulpkaninHeart
+
+- type: entity
+  parent: [ OrganBaseStomach, OrganVulpkaninInternal, OrganVulpkaninMetabolizer ]
+  id: OrganVulpkaninStomach
+
+- type: entity
+  parent: [ OrganBaseLiver, OrganSpriteHumanInternal, OrganVulpkaninInternal, OrganVulpkaninMetabolizer ]
+  id: OrganVulpkaninLiver
+
+- type: entity
+  parent: [ OrganBaseKidneys, OrganSpriteHumanInternal, OrganVulpkaninInternal, OrganVulpkaninMetabolizer ]
+  id: OrganVulpkaninKidneys
diff --git a/Resources/Prototypes/Body/base_organs.yml b/Resources/Prototypes/Body/base_organs.yml
new file mode 100644 (file)
index 0000000..2101cef
--- /dev/null
@@ -0,0 +1,322 @@
+- type: entity
+  id: OrganBase
+  name: organ
+  abstract: true
+  parent: BaseItem
+  components:
+  - type: Organ
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseTorso
+  name: torso
+  abstract: true
+  components:
+  - type: Organ
+    category: Torso
+  - type: Sprite
+    state: torso_m
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseHead
+  name: head
+  abstract: true
+  components:
+  - type: Organ
+    category: Head
+  - type: Sprite
+    state: head_m
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseArmLeft
+  name: left arm
+  abstract: true
+  components:
+  - type: Organ
+    category: ArmLeft
+  - type: Sprite
+    state: l_arm
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseArmRight
+  name: right arm
+  abstract: true
+  components:
+  - type: Organ
+    category: ArmRight
+  - type: Sprite
+    state: r_arm
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseHandLeft
+  name: left hand
+  abstract: true
+  components:
+  - type: Organ
+    category: HandLeft
+  - type: HandOrgan
+    handID: left
+    data:
+      location: Left
+  - type: Sprite
+    state: l_hand
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseHandRight
+  name: right hand
+  abstract: true
+  components:
+  - type: Organ
+    category: HandRight
+  - type: HandOrgan
+    handID: right
+    data:
+      location: Right
+  - type: Sprite
+    state: r_hand
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseLegLeft
+  name: left leg
+  abstract: true
+  components:
+  - type: Organ
+    category: LegLeft
+  - type: Sprite
+    state: l_leg
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseLegRight
+  name: right leg
+  abstract: true
+  components:
+  - type: Organ
+    category: LegRight
+  - type: Sprite
+    state: r_leg
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseFootLeft
+  name: left foot
+  abstract: true
+  components:
+  - type: Organ
+    category: FootLeft
+  - type: Sprite
+    state: l_foot
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseFootRight
+  name: right foot
+  abstract: true
+  components:
+  - type: Organ
+    category: FootRight
+  - type: Sprite
+    state: r_foot
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseBrain
+  name: brain
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Brain
+  - type: Sprite
+    layers:
+    - state: brain
+  - type: Item
+    heldPrefix: brain
+  - type: Input
+    context: "ghost"
+  - type: Brain
+  - type: InputMover
+  - type: Examiner
+  - type: BlockMovement
+  - type: BadFood
+  - type: FoodSequenceElement
+    entries:
+      Burger: Brain
+      Taco: Brain
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseEyes
+  name: eyes
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Eyes
+  - type: Sprite
+    layers:
+    - state: eyeball-l
+    - state: eyeball-r
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseTongue
+  name: tongue
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Tongue
+  - type: Sprite
+    layers:
+    - state: tongue
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseAppendix
+  name: appendix
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Appendix
+  - type: Sprite
+    layers:
+    - state: appendix
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseEars
+  name: ears
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Ears
+  - type: Sprite
+    layers:
+    - state: ears
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseLungs
+  name: lungs
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Lungs
+  - type: Lung
+  - type: Metabolizer
+    removeEmpty: true
+    solutionOnBody: false
+    solution: "Lung"
+    groups:
+    - id: Gas
+      rateModifier: 100.0
+  - type: SolutionContainerManager
+    solutions:
+      Lung:
+        maxVol: 100.0
+        canReact: false
+  - type: Sprite
+    layers:
+    - state: lung-l
+    - state: lung-r
+  - type: Item
+    heldPrefix: lungs
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseHeart
+  name: heart
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Heart
+  - type: Sprite
+    layers:
+    - state: heart-on
+  - type: Metabolizer
+    maxReagents: 2
+    groups:
+    - id: Medicine
+    - id: Poison
+    - id: Narcotic
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseStomach
+  name: stomach
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Stomach
+  - type: Stomach
+  - type: SolutionContainerManager
+    solutions:
+      stomach:
+        maxVol: 50
+  - type: Metabolizer
+    maxReagents: 3
+    groups:
+    - id: Food
+    - id: Drink
+  - type: Sprite
+    layers:
+    - state: stomach
+  - type: Item
+    heldPrefix: stomach
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseLiver
+  name: liver
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Liver
+  - type: Sprite
+    layers:
+    - state: liver
+  - type: Item
+    heldPrefix: liver
+  - type: Metabolizer
+    maxReagents: 1
+    groups:
+    - id: Alcohol
+
+- type: entity
+  parent: OrganBase
+  id: OrganBaseKidneys
+  name: kidneys
+  abstract: true
+  components:
+  - type: GibbableOrgan
+  - type: Organ
+    category: Kidneys
+  - type: Sprite
+    layers:
+      - state: kidney-l
+      - state: kidney-r
+  - type: Item
+    heldPrefix: kidneys
+  - type: Metabolizer
+    maxReagents: 5
+    removeEmpty: true
+
+- type: entity
+  id: OrganSpriteHumanInternal
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Mobs/Species/Human/organs.rsi
diff --git a/Resources/Prototypes/Body/organ_categories.yml b/Resources/Prototypes/Body/organ_categories.yml
new file mode 100644 (file)
index 0000000..9816aeb
--- /dev/null
@@ -0,0 +1,59 @@
+- type: organCategory
+  id: Torso
+
+- type: organCategory
+  id: Head
+
+- type: organCategory
+  id: ArmLeft
+
+- type: organCategory
+  id: ArmRight
+
+- type: organCategory
+  id: HandRight
+
+- type: organCategory
+  id: HandLeft
+
+- type: organCategory
+  id: LegLeft
+
+- type: organCategory
+  id: LegRight
+
+- type: organCategory
+  id: FootLeft
+
+- type: organCategory
+  id: FootRight
+
+- type: organCategory
+  id: Brain
+
+- type: organCategory
+  id: Eyes
+
+- type: organCategory
+  id: Tongue
+
+- type: organCategory
+  id: Appendix
+
+- type: organCategory
+  id: Ears
+
+- type: organCategory
+  id: Lungs
+
+- type: organCategory
+  id: Heart
+
+- type: organCategory
+  id: Stomach
+
+- type: organCategory
+  id: Liver
+
+- type: organCategory
+  id: Kidneys
diff --git a/Resources/Prototypes/Body/species_appearance.yml b/Resources/Prototypes/Body/species_appearance.yml
new file mode 100644 (file)
index 0000000..91f7370
--- /dev/null
@@ -0,0 +1,87 @@
+- type: entity
+  abstract: true
+  id: BaseSpeciesLayers
+  components:
+  - type: Sprite
+    layers:
+    # Torso
+    - map: [ "enum.HumanoidVisualLayers.Chest" ]
+
+    # Head
+    - map: [ "enum.HumanoidVisualLayers.Head" ]
+    - map: [ "enum.HumanoidVisualLayers.Snout" ]
+    - map: [ "enum.HumanoidVisualLayers.Eyes" ]
+
+    # Limbs
+    - map: [ "enum.HumanoidVisualLayers.RArm" ]
+    - map: [ "enum.HumanoidVisualLayers.LArm" ]
+    - map: [ "enum.HumanoidVisualLayers.RLeg" ]
+    - map: [ "enum.HumanoidVisualLayers.LLeg" ]
+
+    # Underwear & clothing
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
+    - map: ["jumpsuit"]
+
+    # Extremities
+    - map: ["enum.HumanoidVisualLayers.LFoot"]
+    - map: ["enum.HumanoidVisualLayers.RFoot"]
+    - map: ["enum.HumanoidVisualLayers.LHand"]
+    - map: ["enum.HumanoidVisualLayers.RHand"]
+
+    # More equipment
+    - map: [ "gloves" ]
+    - map: [ "shoes" ]
+    - map: [ "ears" ]
+    - map: [ "eyes" ]
+    - map: [ "belt" ]
+    - map: [ "id" ]
+    - map: [ "outerClothing" ]
+    - map: [ "back" ]
+    - map: [ "neck" ]
+
+    # Stuff that goes in front of equipment
+    - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
+    - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
+    - map: [ "enum.HumanoidVisualLayers.Hair" ]
+    - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
+    - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
+    - map: [ "enum.HumanoidVisualLayers.Tail" ]
+
+    # Stuff that goes in front of stuff that goes in front of equipment
+    - map: [ "mask" ]
+    - map: [ "head" ]
+    - map: [ "pocket1" ]
+    - map: [ "pocket2" ]
+
+    # Extra stuff
+    - map: ["enum.HumanoidVisualLayers.Handcuffs"]
+      color: "#ffffff"
+      sprite: Objects/Misc/handcuffs.rsi
+      state: body-overlay-2
+      visible: false
+
+    - map: [ "clownedon" ] # Dynamically generated
+      sprite: "Effects/creampie.rsi"
+      state: "creampie_human"
+      visible: false
+
+- type: entity
+  id: BaseSpeciesAppearance
+  parent:
+  - InventoryBase
+  - BaseSpeciesLayers
+  abstract: true
+  save: false
+  components:
+  - type: Body
+  - type: Hands
+  - type: ComplexInteraction
+  - type: ContainerContainer
+  - type: Appearance
+  - type: UserInterface
+    interfaces:
+      enum.HumanoidMarkingModifierKey.Key:
+        type: HumanoidMarkingModifierBoundUserInterface
+      enum.StrippingUiKey.Key:
+        type: StrippableBoundUserInterface
similarity index 53%
rename from Resources/Prototypes/Entities/Mobs/Species/base.yml
rename to Resources/Prototypes/Body/species_base.yml
index 335b9c7a5de136a7ec71b370ed7aa635f284f597..7caa300bc99dee56a8ce1ad1f40c236d5cecf2a7 100644 (file)
@@ -1,59 +1,15 @@
 - type: entity
-  save: false
+  abstract: true
   parent:
   - BaseMob
+  - MobCombat
   - MobDamageable
   - MobPolymorphable
-  - MobCombat
   - StripableInventoryBase
-  id: BaseMobSpecies
-  abstract: true
+  - BaseSpeciesAppearance
+  id: BaseSpeciesMob
+  save: false
   components:
-  - type: Sprite
-    layers:
-    - map: [ "enum.HumanoidVisualLayers.Chest" ]
-    - map: [ "enum.HumanoidVisualLayers.Head" ]
-    - map: [ "enum.HumanoidVisualLayers.Snout" ]
-    - map: [ "enum.HumanoidVisualLayers.Eyes" ]
-    - map: [ "enum.HumanoidVisualLayers.RArm" ]
-    - map: [ "enum.HumanoidVisualLayers.LArm" ]
-    - map: [ "enum.HumanoidVisualLayers.RLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.LLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
-    - map: ["jumpsuit"]
-    - map: ["enum.HumanoidVisualLayers.LFoot"]
-    - map: ["enum.HumanoidVisualLayers.RFoot"]
-    - map: ["enum.HumanoidVisualLayers.LHand"]
-    - map: ["enum.HumanoidVisualLayers.RHand"]
-    - map: [ "gloves" ]
-    - map: [ "shoes" ]
-    - map: [ "ears" ]
-    - map: [ "eyes" ]
-    - map: [ "belt" ]
-    - map: [ "id" ]
-    - map: [ "outerClothing" ]
-    - map: [ "back" ]
-    - map: [ "neck" ]
-    - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
-    - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
-    - map: [ "enum.HumanoidVisualLayers.Hair" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
-    - map: [ "enum.HumanoidVisualLayers.Tail" ]
-    - map: [ "mask" ]
-    - map: [ "head" ]
-    - map: [ "pocket1" ]
-    - map: [ "pocket2" ]
-    - map: ["enum.HumanoidVisualLayers.Handcuffs"]
-      color: "#ffffff"
-      sprite: Objects/Misc/handcuffs.rsi
-      state: body-overlay-2
-      visible: false
-    - map: [ "clownedon" ] # Dynamically generated
-      sprite: "Effects/creampie.rsi"
-      state: "creampie_human"
-      visible: false
   - type: DamageVisuals
     thresholds: [ 10, 20, 30, 50, 70, 100 ]
     targetLayers:
   - type: GenericVisualizer
     visuals:
       enum.CreamPiedVisuals.Creamed:
-        clownedon: # Not 'creampied' bc I can already see Skyrat complaining about conflicts.
-          True: {visible: true}
-          False: {visible: false}
+        clownedon:
+          True: { visible: true }
+          False: { visible: false }
   - type: StatusIcon
     bounds: -0.5,-0.5,0.5,0.5
   - type: RotationVisuals
     defaultRotation: 90
     horizontalRotation: 90
   - type: HumanoidAppearance
-    species: Human
   - type: TypingIndicator
   - type: SlowOnDamage
     speedModifierThresholds:
     - Flashed
     - RadiationProtection
     - Adrenaline
-  - type: Body
-    prototype: Human
-    requiredLegs: 2
   - type: Identity
   - type: IdExaminable
-  - type: Hands
-  - type: ComplexInteraction
   - type: Internals
   - type: FloatingVisuals
   - type: Climbing
     - AnomalyHost
 
 - type: entity
-  save: false
+  abstract: true
   parent:
   - MobBloodstream
   - MobRespirator
   - MobAtmosStandard
   - MobFlammable
-  - BaseMobSpecies
-  id: BaseMobSpeciesOrganic
-  abstract: true
+  - BaseSpeciesMob
+  id: BaseSpeciesMobOrganic
+  save: false
   components:
+  - type: Hunger
+  - type: Thirst
   - type: Barotrauma
     damage:
       types:
-        Blunt: 0.50 #per second, scales with pressure and other constants.
+        Blunt: 0.50
         Heat: 0.1
-  - type: PassiveDamage # Slight passive regen. Assuming one damage type, comes out to about 4 damage a minute.
+  - type: PassiveDamage
     allowedStates:
     - Alive
     damageCap: 20
         Brute: -0.07
   - type: Fingerprint
   - type: Blindable
-  # Other
   - type: Temperature
     currentTemperature: 310.15
     specificHeat: 42
     thermalRegulationTemperatureThreshold: 2
   - type: Perishable
   - type: Butcherable
-    butcheringType: Spike # TODO human.
+    butcheringType: Spike
     spawned:
-      - id: FoodMeat
-        amount: 5
+    - id: FoodMeat
+      amount: 5
   - type: Respirator
     damage:
       types:
   - type: FireVisuals
     alternateState: Standing
   - type: StunVisuals
-
-- type: entity
-  save: false
-  id: BaseSpeciesDummy
-  parent: InventoryBase
-  abstract: true
-  components:
-  - type: Hands
-  - type: ComplexInteraction
-  - type: ContainerContainer
-  - type: Icon
-    sprite: Mobs/Species/Human/parts.rsi
-    state: full
-  - type: Sprite
-    drawdepth: Mobs
-    noRot: true
-    # TODO BODY Turn these into individual body parts?
-    layers:
-    - map: [ "enum.HumanoidVisualLayers.Chest" ]
-    - map: [ "enum.HumanoidVisualLayers.Head" ]
-    - map: [ "enum.HumanoidVisualLayers.Snout" ]
-    - map: [ "enum.HumanoidVisualLayers.Eyes" ]
-    - map: [ "enum.HumanoidVisualLayers.RArm" ]
-    - map: [ "enum.HumanoidVisualLayers.LArm" ]
-    - map: [ "enum.HumanoidVisualLayers.RLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.LLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
-    - map: ["jumpsuit"]
-    - map: ["enum.HumanoidVisualLayers.LFoot"]
-    - map: ["enum.HumanoidVisualLayers.RFoot"]
-    - map: ["enum.HumanoidVisualLayers.LHand"]
-    - map: ["enum.HumanoidVisualLayers.RHand"]
-    - map: ["enum.HumanoidVisualLayers.Handcuffs"]
-      color: "#ffffff"
-      sprite: Objects/Misc/handcuffs.rsi
-      state: body-overlay-2
-      visible: false
-    - map: [ "gloves" ]
-    - map: [ "shoes" ]
-    - map: [ "ears" ]
-    - map: [ "eyes" ]
-    - map: [ "belt" ]
-    - map: [ "id" ]
-    - map: [ "outerClothing" ]
-    - map: [ "back" ]
-    - map: [ "neck" ]
-    - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
-    - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
-    - map: [ "enum.HumanoidVisualLayers.Hair" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
-    - map: [ "enum.HumanoidVisualLayers.Tail" ]
-    - map: [ "mask" ]
-    - map: [ "head" ]
-    - map: [ "pocket1" ]
-    - map: [ "pocket2" ]
-  - type: Appearance
-  - type: HumanoidAppearance
-    species: Human
-  - type: Body
-    prototype: Human
-    requiredLegs: 2
-  - type: UserInterface
-    interfaces:
-      enum.HumanoidMarkingModifierKey.Key: # sure, this can go here too
-        type: HumanoidMarkingModifierBoundUserInterface
index 57da7446902b0514ddf3e19225411442f943fa80..23ee84bd3c7db3ba4d0e2aebcfd5fddf6dbd8f59 100644 (file)
@@ -45,7 +45,7 @@
     - id: SpaceCash1000
     - id: WeaponDisabler
     - id: ClothingEyesGlassesCommand
-    - id: HeadSkeleton # A skull to accompany your skeleton crew
+    - id: OrganSkeletonPersonHead # A skull to accompany your skeleton crew
       conditions:
       - !type:PlayerCountCondition
         max: 15
index 3248ea053559f7fd2ffa153bb55a80b3a82f6649..66d3549b440ba860e389b3d6f66612f5612884a0 100644 (file)
 
 - type: entity
   name: mothroach
-  parent: MobCockroach
+  parent: [ BaseMobMothroach, MobCockroach ]
   id: MobMothroach
   description: This is the adorable by-product of multiple attempts at genetically mixing mothpeople with cockroaches.
   components:
   - type: NpcFactionMember
     factions:
     - Mouse
-  - type: Body
-    prototype: Mothroach
   - type: TypingIndicator
     proto: moth
   - type: Destructible
 
 - type: entity
   name: cow
-  parent: SimpleMobBase
+  parent: [ SimpleMobBase, BaseMobRuminant ]
   id: MobCow
   description: Moo.
   components:
   - type: NpcFactionMember
     factions:
     - Passive
-  - type: Body
-    prototype: AnimalRuminant
   - type: HTN
     rootTask:
       task: RuminantCompound
 
 - type: entity
   name: crab
-  parent: SimpleMobBase
+  parent: [ SimpleMobBase, BaseMobHemocyanin ]
   id: MobCrab
   description: A folk legend goes around that his claw snaps spacemen out of existence over distasteful remarks. Be polite and tolerant for your own safety.
   components:
   - type: HTN
     rootTask:
       task: RuminantCompound
-  - type: Body
-    prototype: AnimalHemocyanin
 
 - type: entity
   name: goat
-  parent: SimpleMobBase
+  parent: [ SimpleMobBase, BaseMobRuminant ]
   id: MobGoat
   description: Her spine consists of long sharp segments, no wonder she is so grumpy.
   components:
   - type: NpcFactionMember
     factions:
     - Passive
-  - type: Body
-    prototype: AnimalRuminant
   - type: NPCRetaliation
     attackMemoryLength: 5
   - type: FactionException
 - type: entity
   name: genetic ancestor
   id: MobBaseAncestor
-  parent: [SimpleMobBase, StripableInventoryBase]
+  parent: [BaseMobAnimal, SimpleMobBase, StripableInventoryBase]
   description: The genetic bipedal ancestor of... Uh... Something. Yeah, there's definitely something on the station that descended from whatever this is.
   abstract: true
   components:
       state: "creampie_human"
       visible: false
   - type: Hands
+    activeHandId: Hand
+    hands:
+      Hand:
+        location: Left
   - type: ComplexInteraction
   - type: GenericVisualizer
     visuals:
         clownedon:
           True: {visible: true}
           False: {visible: false}
-  - type: Body
-    prototype: Primate
-    requiredLegs: 1 # TODO: More than 1 leg
   - type: CreamPied
   - type: FireVisuals
     sprite: Mobs/Effects/onfire.rsi
 
 - type: entity
   name: mouse
-  parent: SimpleMobBase
+  parent:
+  - SimpleMobBase
+  - BaseMobAnimal
   id: MobMouse
   description: Squeak!
   components:
-  - type: Body
-    prototype: Mouse
   - type: GhostRole
     makeSentient: true
     allowSpeech: true
 # Code unique spider prototypes or combine them all into one spider and get a
 # random sprite state when you spawn it.
 - type: entity
-  parent: [ SimpleMobBase, MobCombat ]
+  parent: [ SimpleMobBase, BaseMobHemocyanin, MobCombat ]
   id: MobSpiderBase
   abstract: true
   components:
     - id: FoodMeatSpider
       amount: 2
   - type: CombatMode
-  - type: Body
-    prototype: AnimalHemocyanin
   - type: MobThresholds
     thresholds:
       0: Alive
 
 - type: entity
   name: diona nymph
-  parent: [SimpleMobBase, StripableInventoryBase]
+  parent: [BaseMobAnimal, SimpleMobBase, StripableInventoryBase]
   id: MobDionaNymph
   description: It's like a cat, only.... branch-ier.
   components:
             sprite: Mobs/Pets/displacements.rsi
             state: corgi_head_displacement
   - type: Hands # HANDS!
+    activeHandId: Right
+    hands:
+      Right:
+        location: Right
+      Left:
+        location: Left
   - type: Puller
   - type: Cuffable # bad dog!
   - type: BlockWriting # dogs can't write, paws unwieldy; mouth-writing is a myth
   - type: Stripping
   - type: ComplexInteraction
   # Implement custom borgi body type
-  - type: Body
-    prototype: SmartCorgi
   - type: RotationVisuals
     defaultRotation: 90
     horizontalRotation: 180
index ddb7b5f68c27d5ab9531a1772c6fdb4cf4a49416..921f88de36817f6cb64619e8a96ed24a23e7b639 100644 (file)
@@ -1,6 +1,6 @@
 - type: entity
   save: false
-  parent: [ BaseSimpleMob, MobCombat ]
+  parent: [ BaseSimpleMob, BaseMobAnimal, MobCombat ]
   id: BaseMobArgocyte
   suffix: AI
   description: A dangerous alien found on the wrong side of planets, known for their propensity for munching on ruins.
@@ -38,8 +38,6 @@
     damage:
       types:
         Slash: 5
-  - type: Body
-    prototype: Animal
   - type: Flammable
     fireSpread: true
     canResistFire: true
index f0a48a6577214d97615a58d3dbbc80cca0cb3537..894c317d7fda0f33ae3262f5b901c7ace27e9538 100644 (file)
@@ -5,6 +5,7 @@
   - MobDamageable
   - MobAtmosExposed
   - MobCombat
+  - BaseMobAnimal
   abstract: true
   components:
   - type: Reactive
@@ -12,8 +13,6 @@
       Flammable: [Touch]
       Extinguish: [Touch]
       Acidic: [Touch, Ingestion]
-  - type: Body
-    prototype: Animal
   - type: Climbing
   - type: NameIdentifier
     group: GenericNumber
index 1eb22649e7db87cc1d39c5daf6d5d10066a4acbb..a0a6d978fa9d7a7462a01a26b062b6242fceaf53 100644 (file)
 
 - type: entity
   name: sharkminnow
-  parent: BaseMobCarp
+  parent: [ BaseMobBloodsucker, BaseMobCarp ]
   id: MobShark
   description: A dangerous shark from the blackness of endless space, who loves to drink blood.
   components:
         Dead:
           Base: dead
           BaseUnshaded: dead_mouth
-    - type: Body
-      prototype: Bloodsucker
-      requiredLegs: 1
     - type: Butcherable
       spawned:
         - id: FoodMeatFish
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/dummy_npcs.yml b/Resources/Prototypes/Entities/Mobs/NPCs/dummy_npcs.yml
deleted file mode 100644 (file)
index 245d422..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-- type: entity
-  save: false
-  name: pathfinding dummy
-  parent: BaseMobHuman
-  id: MobHumanPathDummy
-  description: A miserable pile of secrets.
-  suffix: AI
-  components:
-  - type: InputMover
-  - type: MobMover
\ No newline at end of file
index bcf10eb8f61f28b3c3c33ba6c098172a3294c99d..2cdbad7924e9fa51c15a182d599364c72b79e70d 100644 (file)
@@ -4,6 +4,7 @@
   - BaseSimpleMob
   - MobCombat
   - MobBloodstream
+  - BaseMobAnimal
   id: MobHellspawn
   description: An unstoppable force of carnage.
   components:
@@ -27,8 +28,6 @@
   - type: NpcFactionMember
     factions:
       - SimpleHostile
-  - type: Body
-    prototype: Animal
   - type: Damageable
     damageContainer: BiologicalMetaphysical
     damageModifierSet: HellSpawn
index ec2ed5070d392fb77b2c7fd64bfa61a4fac84d6e..dbd092579fecd17d91bd401e0178046fddb2f48f 100644 (file)
@@ -1,6 +1,6 @@
 - type: entity
   name: civilian
-  parent: BaseMobHuman
+  parent: MobHuman
   id: MobCivilian
   description: A miserable pile of secrets.
   components:
@@ -14,7 +14,7 @@
 
 - type: entity
   name: salvager
-  parent: BaseMobHuman
+  parent: MobHuman
   id: MobSalvager
   components:
     - type: NpcFactionMember
@@ -31,7 +31,7 @@
 
 - type: entity
   name: spirate
-  parent: BaseMobHuman
+  parent: MobHuman
   id: MobSpirate
   description: Yarr!
   components:
@@ -49,7 +49,7 @@
 
 - type: entity
   name: syndicate footsoldier
-  parent: BaseMobHuman
+  parent: MobHuman
   id: MobSyndicateFootsoldier
   components:
     - type: NpcFactionMember
@@ -70,7 +70,7 @@
   id: MobSyndicateFootsoldierPilot
 
 - type: entity
-  parent: BaseMobHuman
+  parent: MobHuman
   suffix: Dead
   save: false # mobs are currently not saveable.
   id: SalvageHumanCorpse
index 3e0edee084b3a938c05be8edc36ead576c5e3874..111500eca557c589e58b2ad010d4df829416f74e 100644 (file)
@@ -1,7 +1,7 @@
 - type: entity
   name: rat king
   id: MobRatKing
-  parent: [ SimpleMobBase, MobCombat ]
+  parent: [ BaseMobRat, SimpleMobBase, MobCombat ]
   description: He's da rat. He make da roolz.
   components:
   - type: CombatMode
@@ -59,9 +59,6 @@
       types:
         Slash: 12
         Piercing: 8
-  - type: Body
-    prototype: Rat
-    requiredLegs: 0 # TODO: Make more than 1 leg, set to 0 to avoid sprint speed being reset by the body system
   - type: Hunger # probably should be prototyped
     thresholds:
       Overfed: 200
 - type: entity
   name: rat servant
   id: MobRatServant
-  parent: [ SimpleMobBase, MobCombat ]
+  parent: [ BaseMobRat, SimpleMobBase, MobCombat ]
   description: He's da mini rat. He don't make da roolz.
   categories: [ HideSpawnMenu ] #Must be configured to a King or the AI breaks.
   components:
       types:
         Slash: 5
         Piercing: 3
-  - type: Body
-    prototype: Rat
-    requiredLegs: 0 # TODO: Make more than 1 leg, set to 0 to avoid sprint speed being reset by the body system
   - type: Hunger # probably should be prototyped
     thresholds:
       Overfed: 200
index 7c9f3ca95c56ba16f723728f8cd599fd771aa3a9..7c1ad84ca29e187e2e914950463c5b3ba6ea7cf2 100644 (file)
     - SiliconEmotes
     - Bot
     - Unimplantable
-  - type: Body
-    prototype: Bot
   - type: Speech
     speechVerb: Robotic
     speechSounds: Pai #couldn't decide if this should be borg or pai sounds so I flipped a coin.
   - type: Hands # This probably REALLY needs hand whitelisting, but we NEED hands for hugs, so...
   - type: ComplexInteraction # Hugging is a complex interaction, apparently.
   - type: HugBot
-  - type: Body
-    prototype: HugBot
   - type: HTN
     rootTask:
       task: HugBotCompound
index 906675045b04e10936ddbd21a7d429ca3e64da09..597674af59ef7b0287d8afbcbe96eca9e10bb7b6 100644 (file)
@@ -41,6 +41,7 @@
   - MobCombat
   - MobBloodstream
   - MobFlammable
+  - BaseMobAnimal
   id: SimpleSpaceMobBase # Mob without barotrauma, freezing and asphyxiation (for space carps!?)
   suffix: AI
   components:
@@ -53,8 +54,6 @@
   - type: MeleeWeapon
     angle: 0
     animation: WeaponArcBite
-  - type: Body
-    prototype: Animal
   - type: Climbing
   - type: NameIdentifier
     group: GenericNumber
index 80269feef37499a27624b508adfd00955279edb2..8d8b4f763e7fe380812b32ef6f5629b33cf9a991 100644 (file)
@@ -1,7 +1,7 @@
 - type: entity
   name: basic slime
   id: BaseMobAdultSlimes
-  parent: [ SimpleMobBase, MobCombat ]
+  parent: [ BaseMobSlimes, SimpleMobBase, MobCombat ]
   abstract: true
   description: It looks so much like jelly. I wonder what it tastes like?
   components:
@@ -89,9 +89,6 @@
         type: Local
         messages: [ "slime-hurt-by-water-popup" ]
         probability: 0.25
-  - type: Body
-    prototype: Slimes
-    requiredLegs: 1
   - type: MeleeWeapon
     altDisarm: false
     soundHit:
index e57e0d3d97a865f355439a1de101ad73968c1666..1cffe9cb7107b7d5ba8b82dcc8e9ca15a9ad5cf1 100644 (file)
     - type: SalvageMobRestrictions
 
 - type: entity
-  parent: SimpleSpaceMobBase
+  parent:
+  - SimpleSpaceMobBase
+  - BaseMobAnimal
   id: MobSnail
   name: snail
   description: Revolting unless you're french.
   components:
-  - type: Body
-    prototype: Mouse
   - type: GhostRole
     makeSentient: true
     allowSpeech: false
   - type: MovementAlwaysTouching
 
 - type: entity
-  parent: MobSnail
+  parent: [ BaseMobMothroach, MobSnail ]
   id: MobSnailMoth
   name: Snoth
   components:
-  - type: Body
-    prototype: Mothroach
   - type: GhostRole
     name: ghost-role-information-snoth-name
     description: ghost-role-information-snoth-description
diff --git a/Resources/Prototypes/Entities/Mobs/Player/arachnid.yml b/Resources/Prototypes/Entities/Mobs/Player/arachnid.yml
deleted file mode 100644 (file)
index d9dea3c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McWeb
-  parent: BaseMobArachnid
-  id: MobArachnid
-  components:
-  - type: Respirator
-    damage:
-      types:
-        Asphyxiation: 1.5 # This makes space and crit more lethal to arachnids.
-    damageRecovery:
-      types:
-        Asphyxiation: -0.5
diff --git a/Resources/Prototypes/Entities/Mobs/Player/diona.yml b/Resources/Prototypes/Entities/Mobs/Player/diona.yml
deleted file mode 100644 (file)
index bcb602b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McPlants
-  parent: BaseMobDiona
-  id: MobDiona
-  components:
-    - type: Respirator
-      damage:
-        types:
-          Asphyxiation: 0.5
-      damageRecovery:
-        types:
-          Asphyxiation: -1.0
-
-# Reformed Diona
-- type: entity
-  parent: MobDiona
-  categories: [ HideSpawnMenu ]
-  id: MobDionaReformed
-  name: Reformed Diona
-  components:
-    - type: IsDeadIC
-    - type: RandomHumanoidAppearance 
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Player/dwarf.yml
deleted file mode 100644 (file)
index d1de65d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McHands The Dwarf
-  parent: BaseMobDwarf
-  id: MobDwarf
diff --git a/Resources/Prototypes/Entities/Mobs/Player/gingerbread.yml b/Resources/Prototypes/Entities/Mobs/Player/gingerbread.yml
deleted file mode 100644 (file)
index e7cbd37..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McCookie
-  parent: BaseMobGingerbread
-  id: MobGingerbread
-  components:
-    - type: Respirator
-      damage:
-        types:
-          Asphyxiation: 0.5
-      damageRecovery:
-        types:
-          Asphyxiation: -1.0
-
-- type: entity
-  name: gingerbread man
-  id: MobGingerbreadAI
-  parent: [ MobGingerbread, MobCombat]
-  components:
-  - type: GhostRole
-    name: ghost-role-information-gingerbread-name
-    description: ghost-role-information-gingerbread-description
-    rules: ghost-role-information-nonantagonist-rules
-  - type: GhostTakeoverAvailable
-  - type: NPCRetaliation
-  - type: FactionException
-  - type: NpcFactionMember
-    factions:
-    - Passive
-  - type: HTN
-    rootTask:
-      task: SimpleHostileCompound
-  
\ No newline at end of file
index 10ef8311ea179fcb8031aa760a3863d3feb99c99..558fe84607833b1c2f1e124bbe5f8e12bddf7bc1 100644 (file)
           map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
           color: "#8adaff"
           shader: unshaded
-    - type: Body
-      prototype: Primate
     - type: Tag
       tags:
         - CannotSuicide
     - type: Inventory
       templateId: holoclown
     - type: Hands
+      activeHandId: Hand
+      hands:
+        Hand:
+          location: Left
     - type: ComplexInteraction
     - type: Clumsy
       gunShootFailDamage:
index 8b677c49f705e87576ed88420abc1b39f53f587d..e99d7b75247774fbe28ee13379e96037acecf420 100644 (file)
@@ -1,9 +1,3 @@
-- type: entity
-  save: false
-  name: Urist McHands
-  parent: BaseMobHuman
-  id: MobHuman
-
 #Syndie
 - type: entity
   parent: MobHuman
diff --git a/Resources/Prototypes/Entities/Mobs/Player/moth.yml b/Resources/Prototypes/Entities/Mobs/Player/moth.yml
deleted file mode 100644 (file)
index ea01677..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McFluff
-  parent: BaseMobMoth
-  id: MobMoth
diff --git a/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Player/reptilian.yml
deleted file mode 100644 (file)
index b332f57..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McScales
-  suffix: Urisst' Mzhand
-  parent: BaseMobReptilian
-  id: MobReptilian
-
-#Weh
index f5b5f6ac197e8151e954726e3dc993715de4213f..eac588c26c86c9abf23a2d76d58394dbdfe9f431 100644 (file)
@@ -1,14 +1,3 @@
-- type: entity
-  save: false
-  parent: BaseMobSkeletonPerson
-  id: MobSkeletonPerson
-  components:
-  - type: InteractionPopup
-    successChance: 1
-    interactSuccessString: hugging-success-generic
-    interactSuccessSound: /Audio/Effects/thudswoosh.ogg
-    messagePerceivedByOthers: hugging-success-generic-others
-
 - type: entity
   name: skeleton pirate
   parent: MobSkeletonPerson
diff --git a/Resources/Prototypes/Entities/Mobs/Player/slime.yml b/Resources/Prototypes/Entities/Mobs/Player/slime.yml
deleted file mode 100644 (file)
index 4e5974b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-- type: entity
-  save: false
-  parent: BaseMobSlimePerson
-  id: MobSlimePerson
diff --git a/Resources/Prototypes/Entities/Mobs/Player/vox.yml b/Resources/Prototypes/Entities/Mobs/Player/vox.yml
deleted file mode 100644 (file)
index 2890658..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-- type: entity
-  save: false
-  name: Uristititi McVox
-  parent: BaseMobVox
-  id: MobVox
diff --git a/Resources/Prototypes/Entities/Mobs/Player/vulpkanin.yml b/Resources/Prototypes/Entities/Mobs/Player/vulpkanin.yml
deleted file mode 100644 (file)
index 52a839d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McBark
-  parent: BaseMobVulpkanin
-  id: MobVulpkanin
diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml
deleted file mode 100644 (file)
index 43c87f8..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McWebs
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobArachnid
-  abstract: true
-  components:
-  - type: Body
-    prototype: Arachnid
-    requiredLegs: 2 # It would be funny if arachnids could use their little back limbs to move around once they lose their legs, but just something to consider post-woundmed
-  - type: HumanoidAppearance
-    species: Arachnid
-  - type: Hunger
-  - type: Thirst
-  - type: Sericulture
-    productionLength: 2
-    entityProduced: MaterialWebSilk1
-    hungerCost: 4 # Should total to 25 total silk on full hunger
-  - type: Tag
-    tags:
-    - CanPilot
-    - FootstepSound
-    - DoorBumpOpener
-    - SpiderCraft
-    - AnomalyHost
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-      - id: FoodMeatSpider
-        amount: 5
-  - type: Reactive
-    reactions:
-    - reagents: [Water]
-      methods: [Touch]
-      effects:
-      - !type:SpawnEntityInInventory
-        slot: head
-        entity: WaterDropletHat
-    - reagents: [Water, SpaceCleaner]
-      methods: [Touch]
-      effects:
-      - !type:WashCreamPie
-  # Damage (Self)
-  - type: Bloodstream
-    bloodReferenceSolution:
-      reagents:
-      - ReagentId: CopperBlood
-        Quantity: 300
-  # Damage (Others)
-  - type: MeleeWeapon
-    animation: WeaponArcBite
-    soundHit:
-      path: /Audio/Effects/bite.ogg
-    damage:
-      types:
-        Piercing: 5
-  # Visual & Audio
-  - type: DamageVisuals
-    damageOverlayGroups:
-      Brute:
-        sprite: Mobs/Effects/brute_damage.rsi
-        color: "#162581"
-      Burn:
-        sprite: Mobs/Effects/burn_damage.rsi
-  - type: Speech
-    speechVerb: Arachnid
-    speechSounds: Arachnid
-    allowedEmotes: ['Click', 'Chitter']
-  - type: Vocal
-    sounds:
-      Male: UnisexArachnid
-      Female: UnisexArachnid
-      Unsexed: UnisexArachnid
-  - type: TypingIndicator
-    proto: spider
-  - type: Sprite # I'd prefer if these maps were better. Insert map pun here.
-    layers:
-      - map: [ "enum.HumanoidVisualLayers.Chest" ]
-      - map: [ "enum.HumanoidVisualLayers.Head" ]
-      - map: [ "enum.HumanoidVisualLayers.Snout" ]
-      - map: [ "enum.HumanoidVisualLayers.Eyes" ]
-      - map: [ "enum.HumanoidVisualLayers.RArm" ]
-      - map: [ "enum.HumanoidVisualLayers.LArm" ]
-      - map: [ "enum.HumanoidVisualLayers.RLeg" ]
-      - map: [ "enum.HumanoidVisualLayers.LLeg" ]
-      - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
-      - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
-      - map: ["jumpsuit"]
-      - map: ["enum.HumanoidVisualLayers.LFoot"]
-      - map: ["enum.HumanoidVisualLayers.RFoot"]
-      - map: ["enum.HumanoidVisualLayers.LHand"]
-      - map: ["enum.HumanoidVisualLayers.RHand"]
-      - map: [ "gloves" ]
-      - map: [ "shoes" ]
-      - map: [ "belt" ]
-      - map: [ "id" ]
-      - map: [ "outerClothing" ]
-      - map: [ "enum.HumanoidVisualLayers.Tail" ] # Mentioned in moth code: This needs renaming lol.
-      - map: [ "back" ]
-      - map: [ "neck" ]
-      - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
-      - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
-      - map: [ "enum.HumanoidVisualLayers.Hair" ] # Do these need to be here? (arachnid hair arachnid hair)
-      - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
-      - map: [ "ears" ]
-      - map: [ "eyes" ]
-      - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
-      - map: [ "mask" ]
-      - map: [ "head" ]
-      - map: [ "pocket1" ]
-      - map: [ "pocket2" ]
-      - map: ["enum.HumanoidVisualLayers.Handcuffs"]
-        color: "#ffffff"
-        sprite: Objects/Misc/handcuffs.rsi
-        state: body-overlay-2
-        visible: false
-      - map: [ "clownedon" ] # Dynamically generated
-        sprite: "Effects/creampie.rsi"
-        state: "creampie_arachnid"
-        visible: false
-  - type: Inventory
-    templateId: arachnid
-    speciesId: arachnid
-
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobArachnidDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: HumanoidAppearance
-    species: Arachnid
-  - type: Inventory
-    speciesId: arachnid
-
-
-#>88w88<
diff --git a/Resources/Prototypes/Entities/Mobs/Species/diona.yml b/Resources/Prototypes/Entities/Mobs/Species/diona.yml
deleted file mode 100644 (file)
index 1e9d7ea..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McPlants
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobDiona
-  abstract: true
-  components:
-  - type: HumanoidAppearance
-    species: Diona
-  - type: Hunger
-    baseDecayRate: 0.0083
-  - type: Thirst
-    baseDecayRate: 0.0083
-  - type: Icon
-    sprite: Mobs/Species/Diona/parts.rsi
-    state: full
-  - type: Body
-    prototype: Diona
-    requiredLegs: 2
-  - type: Damageable
-    damageContainer: Biological
-    damageModifierSet: Diona
-  - type: DamageVisuals
-    damageOverlayGroups:
-      Brute:
-        sprite: Mobs/Effects/brute_damage.rsi
-        color: "#cd7314"
-      Burn:
-        sprite: Mobs/Effects/burn_damage.rsi
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-      - id: FoodMeatPlant
-        amount: 5
-  - type: Bloodstream
-    bloodReferenceSolution:
-      reagents:
-      - ReagentId: Sap
-        Quantity: 300
-  - type: Reactive
-    groups:
-      Flammable: [ Touch ]
-      Extinguish: [ Touch ]
-      Acidic: [Touch, Ingestion]
-    reactions:
-    - reagents: [Water, SpaceCleaner]
-      methods: [Touch]
-      effects:
-      - !type:WashCreamPie
-    - reagents: [ PlantBGone ]
-      methods: [ Touch ]
-      effects:
-      - !type:HealthChange
-        damage:
-          types:
-            Blunt: 0.05
-            Slash: 0.05
-            Piercing: 0.075
-      - !type:PopupMessage
-        type: Local
-        visualType: Large
-        messages: [ "diona-hurt-by-herbicide-popup" ]
-        probability: 0.66
-    - reagents: [ WeedKiller ]
-      methods: [ Touch ]
-      effects:
-      - !type:HealthChange
-        damage:
-          types:
-            Poison: 0.125
-      - !type:PopupMessage
-        type: Local
-        visualType: Large
-        messages: [ "diona-hurt-by-herbicide-popup" ]
-        probability: 0.66
-  - type: Fixtures
-    fixtures:
-      fix1:
-        shape:
-          !type:PhysShapeCircle
-          radius: 0.35
-        density: 300 #weighs more than humans because wood
-        restitution: 0.0
-        mask:
-          - MobMask
-        layer:
-          - MobLayer
-  - type: Speech
-    speechVerb: Plant
-    allowedEmotes: ['Chirp']
-  - type: Vocal
-    sounds:
-      Male: UnisexDiona
-      Female: UnisexDiona
-      Unsexed: UnisexDiona
-  - type: TypingIndicator
-    proto: diona
-  - type: BodyEmotes
-    soundsId: DionaBodyEmotes
-  - type: IgnoreKudzu
-  - type: IgniteOnHeatDamage
-    fireStacks: 1
-    threshold: 12
-  - type: GibAction
-    actionPrototype: DionaGibAction
-    allowedStates:
-    - Dead
-  - type: Inventory
-    templateId: diona
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
-  - type: Rootable
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobDionaDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: HumanoidAppearance
-    species: Diona
-  - type: Inventory
-    templateId: diona
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
diff --git a/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml b/Resources/Prototypes/Entities/Mobs/Species/dwarf.yml
deleted file mode 100644 (file)
index 14a43ce..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McHands The Dwarf
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobDwarf
-  abstract: true
-  components:
-  - type: Hunger
-  - type: Thirst
-  - type: Icon
-    sprite: Mobs/Species/Human/parts.rsi
-    state: full
-  - type: Respirator
-    damage:
-      types:
-        Asphyxiation: 2
-    damageRecovery:
-      types:
-        Asphyxiation: -1.0
-  - type: ScaleVisuals
-    scale: 1, 0.8
-  - type: Body
-    prototype: Dwarf
-    requiredLegs: 2
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-    - id: FoodMeatHuman
-      amount: 5
-  - type: Fixtures
-    fixtures: # TODO: This needs a second fixture just for mob collisions.
-      fix1:
-        shape:
-          !type:PhysShapeCircle
-          radius: 0.35
-        # they r smaller
-        density: 120
-        restitution: 0.0
-        mask:
-        - MobMask
-        layer:
-        - MobLayer
-  - type: Vocal
-    sounds:
-      Male: UnisexDwarf
-      Female: FemaleDwarf
-      Unsexed: UnisexDwarf
-  - type: ReplacementAccent
-    accent: dwarf
-  - type: Speech
-    speechSounds: Bass
-  - type: HumanoidAppearance
-    species: Dwarf
-    hideLayersOnEquip:
-    - Hair
-    - Snout
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobDwarfDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: ScaleVisuals
-    scale: 1, 0.8
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
diff --git a/Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml b/Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml
deleted file mode 100644 (file)
index 7943174..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McCookie
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobGingerbread
-  abstract: true
-  components:
-  - type: HumanoidAppearance
-    species: Gingerbread
-  - type: Icon
-    sprite: Mobs/Species/Gingerbread/parts.rsi
-    state: full
-  - type: Body
-    prototype: Gingerbread
-    requiredLegs: 2
-  - type: Damageable
-    damageContainer: Biological
-    damageModifierSet: Gingerbread
-  - type: DamageVisuals
-    damageOverlayGroups:
-      Brute:
-        sprite: Mobs/Effects/brute_damage.rsi
-        color: "#896e55"
-      Burn:
-        sprite: Mobs/Effects/burn_damage.rsi
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-      - id: FoodBakedCookie #should be replaced with gingerbread sheets or something... provided you're willing to make a full spriteset of those.
-        amount: 5
-  - type: Bloodstream
-    bloodReferenceSolution:
-      reagents:
-      - ReagentId: Sugar
-        Quantity: 100
-      - ReagentId: Butter
-        Quantity: 200
-  - type: Fixtures
-    fixtures:
-      fix1:
-        shape:
-          !type:PhysShapeCircle
-          radius: 0.35
-        density: 100 #fairly light
-        restitution: 0.0
-        mask:
-          - MobMask
-        layer:
-          - MobLayer
-  - type: TypingIndicator
-    proto: gingerbread
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
-
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobGingerbreadDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: HumanoidAppearance
-    species: Gingerbread
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml
deleted file mode 100644 (file)
index bf357e1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# Anything human specific (e.g. UI, input) goes under MobHuman
-- type: entity
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobHuman
-  name: Urist McHands
-  abstract: true
-  components:
-  - type: Hunger
-  - type: Icon # It will not have an icon in the adminspawn menu without this. Body parts seem fine for whatever reason.
-    sprite: Mobs/Species/Human/parts.rsi
-    state: full
-  - type: Thirst
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-    - id: FoodMeatHuman
-      amount: 5
-  - type: HumanoidAppearance
-    species: Human
-    hideLayersOnEquip:
-    - Hair
-    - Snout
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
-
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobHumanDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Mobs/Species/moth.yml b/Resources/Prototypes/Entities/Mobs/Species/moth.yml
deleted file mode 100644 (file)
index 6d7ba02..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-- type: entity
-  save: false
-  name: Urist McFluff
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobMoth
-  abstract: true
-  components:
-  - type: HumanoidAppearance
-    species: Moth
-    hideLayersOnEquip:
-    - HeadTop
-  - type: Hunger
-  - type: Thirst
-  - type: Icon
-    sprite: Mobs/Species/Moth/parts.rsi
-    state: full
-  - type: Body
-    prototype: Moth
-    requiredLegs: 2
-  - type: Damageable
-    damageContainer: Biological
-    damageModifierSet: Moth
-  - type: ZombieAccentOverride
-    accent: zombieMoth
-  - type: Speech
-    speechVerb: Moth
-    allowedEmotes: ['Chitter', 'Squeak']
-  - type: TypingIndicator
-    proto: moth
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-    - id: FoodMeat
-      amount: 5
-  - type: Bloodstream
-    bloodReferenceSolution:
-      reagents:
-      - ReagentId: InsectBlood
-        Quantity: 300
-  - type: DamageVisuals
-    damageOverlayGroups:
-      Brute:
-        sprite: Mobs/Effects/brute_damage.rsi
-        color: "#808A51"
-      Burn:
-        sprite: Mobs/Effects/burn_damage.rsi
-  - type: MothAccent
-  - type: Vocal
-    sounds:
-      Male: UnisexMoth
-      Female: UnisexMoth
-      Unsexed: UnisexMoth
-  - type: MovementSpeedModifier
-    baseWeightlessAcceleration: 1.5 # Move around more easily in space.
-    baseWeightlessFriction: 1
-    baseWeightlessModifier: 1
-  - type: Flammable
-    damage:
-      types:
-        Heat: 2.5 # moths burn more easily
-  - type: Temperature
-    currentTemperature: 310.15
-    specificHeat: 46
-  - type: TemperatureDamage # Moths hate the heat and thrive in the cold.
-    heatDamageThreshold: 320
-    coldDamageThreshold: 230
-    coldDamage:
-      types:
-        Cold : 0.05 #per second, scales with temperature & other constants
-    heatDamage:
-      types:
-        Heat : 3 #per second, scales with temperature & other constants
-  - type: TemperatureSpeed
-    thresholds:
-      289: 0.9
-      275: 0.8
-      250: 0.7
-  - type: Sprite # sprite again because we want different layer ordering
-    noRot: true
-    drawdepth: Mobs
-    layers:
-      - map: [ "enum.HumanoidVisualLayers.Chest" ]
-      - map: [ "enum.HumanoidVisualLayers.Head" ]
-      - map: [ "enum.HumanoidVisualLayers.Snout" ]
-      - map: [ "enum.HumanoidVisualLayers.Eyes" ]
-      - map: [ "enum.HumanoidVisualLayers.RArm" ]
-      - map: [ "enum.HumanoidVisualLayers.LArm" ]
-      - map: [ "enum.HumanoidVisualLayers.RLeg" ]
-      - map: [ "enum.HumanoidVisualLayers.LLeg" ]
-      - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
-      - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
-      - map: [ "jumpsuit" ]
-      - map: [ "enum.HumanoidVisualLayers.LHand" ]
-      - map: [ "enum.HumanoidVisualLayers.RHand" ]
-      - map: [ "enum.HumanoidVisualLayers.LFoot" ]
-      - map: [ "enum.HumanoidVisualLayers.RFoot" ]
-      - map: [ "enum.HumanoidVisualLayers.Handcuffs" ]
-        color: "#ffffff"
-        sprite: Objects/Misc/handcuffs.rsi
-        state: body-overlay-2
-        visible: false
-      - map: [ "gloves" ]
-      - map: [ "shoes" ]
-      - map: [ "ears" ]
-      - map: [ "eyes" ]
-      - map: [ "belt" ]
-      - map: [ "id" ]
-      - map: [ "outerClothing" ]
-      - map: [ "enum.HumanoidVisualLayers.Tail" ] #in the utopian future we should probably have a wings enum inserted here so everyhting doesn't break
-      - map: [ "back" ]
-      - map: [ "neck" ]
-      - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
-      - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
-      - map: [ "enum.HumanoidVisualLayers.Hair" ]
-      - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
-      - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
-      - map: [ "mask" ]
-      - map: [ "head" ]
-      - map: [ "pocket1" ]
-      - map: [ "pocket2" ]
-      - map: [ "clownedon" ] # Dynamically generated
-        sprite: "Effects/creampie.rsi"
-        state: "creampie_moth"
-        visible: false
-  - type: Inventory
-    speciesId: moth
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: jumpsuit-female
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: back
-      outerClothing:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: outerclothing
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: hand
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: shoes
-    displacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: jumpsuit-male
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: back
-      outerClothing:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: outerclothing
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: hand
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: shoes
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobMothDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: HumanoidAppearance
-    species: Moth
-  - type: Inventory
-    speciesId: moth
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: jumpsuit-female
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: back
-      outerClothing:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: outerclothing
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: hand
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: shoes
-    displacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: jumpsuit-male
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: back
-      outerClothing:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: outerclothing
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: hand
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Moth/displacement.rsi
-            state: shoes
diff --git a/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml b/Resources/Prototypes/Entities/Mobs/Species/reptilian.yml
deleted file mode 100644 (file)
index 55bb32e..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-- type: entity
-  save: false
-  name: Urisst' Mzhand
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobReptilian
-  abstract: true
-  components:
-  - type: HumanoidAppearance
-    species: Reptilian
-    hideLayersOnEquip:
-    - Snout
-    - HeadTop
-    - HeadSide
-    - Tail
-    undergarmentBottom: UndergarmentBottomBoxersReptilian
-  - type: Hunger
-  - type: Puller
-    needsHands: false
-  - type: Thirst
-  - type: Icon
-    sprite: Mobs/Species/Reptilian/parts.rsi
-    state: full
-  - type: Body
-    prototype: Reptilian
-    requiredLegs: 2
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-    - id: FoodMeatLizard
-      amount: 5
-  - type: LizardAccent
-  - type: Speech
-    speechSounds: Lizard
-    speechVerb: Reptilian
-    allowedEmotes: ['Thump']
-  - type: TypingIndicator
-    proto: lizard
-  - type: Vocal
-    sounds:
-      Male: MaleReptilian
-      Female: FemaleReptilian
-      Unsexed: MaleReptilian
-  - type: BodyEmotes
-    soundsId: ReptilianBodyEmotes
-  - type: Damageable
-    damageContainer: Biological
-    damageModifierSet: Scale
-  - type: MeleeWeapon
-    soundHit:
-      collection: AlienClaw
-    angle: 30
-    animation: WeaponArcClaw
-    damage:
-      types:
-        Slash: 5
-  - type: Temperature
-    currentTemperature: 310.15
-    specificHeat: 42
-  - type: TemperatureDamage
-    heatDamageThreshold: 400
-    coldDamageThreshold: 285
-    coldDamage:
-      types:
-        Cold : 0.1 #per second, scales with temperature & other constants
-    heatDamage:
-      types:
-        Heat : 1.5 #per second, scales with temperature & other constants
-  - type: TemperatureSpeed
-    thresholds:
-      301: 0.9
-      295: 0.8
-      285: 0.7
-  - type: Wagging
-  - type: Inventory
-    speciesId: reptilian
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: head
-      mask:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: mask
-    displacements:
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: head
-      mask:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: mask
-
-- type: entity
-  parent: BaseSpeciesDummy
-  id: MobReptilianDummy
-  categories: [ HideSpawnMenu ]
-  description: A dummy reptilian meant to be used in character setup.
-  components:
-  - type: HumanoidAppearance
-    species: Reptilian
-    hideLayersOnEquip:
-    - Snout
-    - HeadTop
-    - HeadSide
-    undergarmentBottom: UndergarmentBottomBoxersReptilian
-  - type: Inventory
-    speciesId: reptilian
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: jumpsuit-female
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: head
-      mask:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: mask
-    displacements:
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: head
-      mask:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Reptilian/displacement.rsi
-            state: mask
-
-#Weh
diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml
deleted file mode 100644 (file)
index 6b777f8..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-- type: entity
-  name: Urist McSlime
-  parent: BaseMobSpeciesOrganic
-  id: BaseMobSlimePerson
-  abstract: true
-  components:
-  - type: Hunger
-  - type: Thirst
-  - type: Icon
-    sprite: Mobs/Species/Slime/parts.rsi
-    state: full
-  - type: Body
-    prototype: Slime
-    requiredLegs: 2
-  # they like eat it idk lol
-  - type: Storage
-    clickInsert: false
-    grid:
-    - 0,0,1,2
-    maxItemSize: Large
-    storageInsertSound:
-      path: /Audio/Voice/Slime/slime_squish.ogg
-  - type: ContainerContainer
-    containers:
-      storagebase: !type:Container
-        ents: []
-  - type: UserInterface
-    interfaces:
-      enum.StorageUiKey.Key:
-        type: StorageBoundUserInterface
-      enum.HumanoidMarkingModifierKey.Key:
-        type: HumanoidMarkingModifierBoundUserInterface
-      enum.StrippingUiKey.Key:
-        type: StrippableBoundUserInterface
-  # to prevent bag open/honk spam
-  - type: UseDelay
-    delay: 0.5
-  - type: HumanoidAppearance
-    species: SlimePerson
-  - type: Speech
-    speechVerb: Slime
-    speechSounds: Slime
-    allowedEmotes: ['Squish']
-  - type: TypingIndicator
-    proto: slime
-  - type: Vocal
-    sounds:
-      Male: MaleSlime
-      Female: FemaleSlime
-      Unsexed: MaleSlime
-  - type: Damageable
-    damageContainer: Biological
-    damageModifierSet: Slime
-  - type: PassiveDamage # Around 8 damage a minute healed
-    allowedStates:
-    - Alive
-    damageCap: 65
-    damage:
-      types:
-        Heat: -0.14
-      groups:
-        Brute: -0.14
-  - type: DamageVisuals
-    damageOverlayGroups:
-      Brute:
-        sprite: Mobs/Effects/brute_damage.rsi
-        color: "#2cf274"
-      Burn:
-        sprite: Mobs/Effects/burn_damage.rsi
-  - type: Bloodstream
-    bloodReferenceSolution: # TODO Color slime blood based on their slime color or smth
-      reagents:
-      - ReagentId: Slime
-        Quantity: 300
-  - type: Barotrauma
-    damage:
-      types:
-        Blunt: 0.50 #per second, scales with pressure and other constants.
-        Heat: 0.2 # 0.1 more than humans, i feel like low pressure would make slime boil more than blunt stretch them so i decided on this instead.
-  - type: Reactive
-    groups:
-      Flammable: [ Touch ]
-      Extinguish: [ Touch ]
-    reactions:
-    - reagents: [ Water, SpaceCleaner ]
-      methods: [ Touch ]
-      effects:
-      - !type:WashCreamPie
-    - reagents: [ Water ]
-      methods: [ Touch ]
-      effects:
-      - !type:HealthChange
-        damage:
-          types:
-            Heat: 0.05
-      - !type:PopupMessage
-        type: Local
-        visualType: Large
-        messages: [ "slime-hurt-by-water-popup" ]
-        probability: 0.25
-  - type: Butcherable
-    butcheringType: Spike
-    spawned:
-    - id: FoodMeatSlime
-      amount: 5
-  - type: Respirator
-    damage:
-      types:
-        Asphyxiation: 0.2
-    damageRecovery:
-      types:
-        Asphyxiation: -1.0
-    maxSaturation: 15
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
-
-- type: entity
-  parent: MobHumanDummy
-  id: MobSlimePersonDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: HumanoidAppearance
-    species: SlimePerson
-  - type: Inventory
-    femaleDisplacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Human/displacement.rsi
-            state: jumpsuit-female
diff --git a/Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml b/Resources/Prototypes/Entities/Mobs/Species/vulpkanin.yml
deleted file mode 100644 (file)
index 535d3ba..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-- type: entity
-  abstract: true
-  save: false
-  parent: [BaseMobSpeciesOrganic]
-  id: BaseMobVulpkanin
-  name: Urist McBark
-  components:
-  - type: Hunger
-  - type: Thirst
-  - type: MessyDrinker
-    spillChance: 0.33
-  - type: Icon
-    sprite: Mobs/Species/Vulpkanin/parts.rsi
-    state: full
-  - type: Body
-    prototype: Vulpkanin
-  - type: Speech
-    speechSounds: Vulpkanin
-    speechVerb: Vulpkanin
-    allowedEmotes: [ 'Bark', 'Snarl', 'Whine', 'Howl', 'Growl' ]
-  - type: Vocal
-    sounds:
-      Male: MaleVulpkanin
-      Female: FemaleVulpkanin
-      Unsexed: MaleVulpkanin
-  - type: Damageable
-    damageModifierSet: Vulpkanin
-  - type: MeleeWeapon
-    soundHit:
-      path: /Audio/Weapons/pierce.ogg
-    animation: WeaponArcClaw
-    damage:
-      types:
-        Piercing: 2
-        Slash: 3
-  - type: Temperature # Same as moth temperatures until below is solved.
-    specificHeat: 44
-  - type: TemperatureDamage
-    heatDamageThreshold: 320 # TODO: 315 when there is a way to make the temperature alert not blink to the side of the screen and disappear when you "sweat" at 39C.
-    coldDamageThreshold: 230 # TODO: 220 when the above is solved.
-    coldDamage:
-      types:
-        Cold: 0.05 # Per second, scales with temperature & other constants
-    heatDamage:
-      types:
-        Heat: 2.5 # Per second, scales with temperature & other constants
-  # - type: Wagging TODO: Add back once we have animated tails again. Were removed due to the sprite rework, causing all of them to not fit anymore.
-  #   action: ActionToggleWaggingVulpkanin
-  - type: TemperatureProtection
-    heatingCoefficient: 1.2
-    coolingCoefficient: 0.3
-  - type: JumpAbility
-    action: ActionVulpkaninGravityJump
-    canCollide: true
-    jumpDistance: 3
-    jumpSound:
-      path: /Audio/Weapons/punchmiss.ogg
-      params:
-        pitch: 1.33
-        volume: -5
-        variation: 0.05
-  - type: Sprite # Drawlayers. Top to bottom in order I believe.
-    netsync: false
-    layers:
-    - map: [ "enum.HumanoidVisualLayers.Chest" ]
-    - map: [ "enum.HumanoidVisualLayers.Head" ]
-    - map: [ "enum.HumanoidVisualLayers.Snout" ]
-    - map: [ "enum.HumanoidVisualLayers.Eyes" ]
-    - map: [ "enum.HumanoidVisualLayers.RArm" ]
-    - map: [ "enum.HumanoidVisualLayers.LArm" ]
-    - map: [ "enum.HumanoidVisualLayers.RLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.LLeg" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
-    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
-    - map: [ "jumpsuit" ]
-    - map: [ "enum.HumanoidVisualLayers.LHand" ]
-    - map: [ "enum.HumanoidVisualLayers.RHand" ]
-    - map: [ "enum.HumanoidVisualLayers.LFoot" ]
-    - map: [ "enum.HumanoidVisualLayers.RFoot" ]
-    - map: [ "enum.HumanoidVisualLayers.Handcuffs" ]
-      color: "#ffffff"
-      sprite: Objects/Misc/handcuffs.rsi
-      state: body-overlay-2
-      visible: false
-    - map: [ "id" ]
-    - map: [ "gloves" ]
-    - map: [ "shoes" ]
-    - map: [ "ears" ]
-    - map: [ "outerClothing" ]
-    - map: [ "eyes" ]
-    - map: [ "belt" ]
-    - map: [ "neck" ]
-    - map: [ "back" ]
-    - map: [ "enum.HumanoidVisualLayers.SnoutCover" ]
-    - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
-    - map: [ "enum.HumanoidVisualLayers.Hair" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadSide" ]
-    - map: [ "enum.HumanoidVisualLayers.HeadTop" ]
-    - map: [ "enum.HumanoidVisualLayers.Tail" ]
-    - map: [ "mask" ]
-    - map: [ "head" ]
-    - map: [ "pocket1" ]
-    - map: [ "pocket2" ]
-    - map: [ "clownedon" ]
-      sprite: "Effects/creampie.rsi"
-      state: "creampie_vulpkanin"
-      visible: false
-  - type: HumanoidAppearance
-    species: Vulpkanin
-    undergarmentTop: UndergarmentTopTanktopVulpkanin
-    undergarmentBottom: UndergarmentBottomBoxersVulpkanin
-    hideLayersOnEquip:
-    - Snout
-    - SnoutCover
-    - HeadTop
-    - HeadSide
-    - FacialHair
-    - Hair
-    markingsDisplacement:
-      Hair:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: hair
-  - type: Inventory
-    speciesId: vulpkanin
-    displacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: jumpsuit
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: back
-      outerClothing:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: outerwear
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: hand
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: shoes
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: head
-      neck:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: neck
-      eyes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: eyes
-      belt:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: belt
-
-- type: entity
-  parent: [BaseSpeciesDummy]
-  id: MobVulpkaninDummy
-  categories: [ HideSpawnMenu ]
-  components:
-  - type: HumanoidAppearance
-    species: Vulpkanin
-    hideLayersOnEquip:
-    - Snout
-    - HeadTop
-    - HeadSide
-    markingsDisplacement:
-      Hair:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: hair
-  - type: Inventory
-    speciesId: vulpkanin
-    displacements:
-      jumpsuit:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: jumpsuit
-      back:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: back
-      outerClothing:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: outerwear
-      gloves:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: hand
-      shoes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: shoes
-      head:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: head
-      neck:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: neck
-      eyes:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: eyes
-      belt:
-        sizeMaps:
-          32:
-            sprite: Mobs/Species/Vulpkanin/displacement.rsi
-            state: belt
index fbbdca390919f80fe64498fe4d4211b55c596648..b12eaa0552a8f15ee75e863e5d0e175fa648a760 100644 (file)
       - ProximitySensor
   - type: StaticPrice
     price: 40
+
+- type: entity
+  id: PartSilicon
+  parent: BaseItem
+  abstract: true
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Robotics/cyborg_parts.rsi
+  - type: StaticPrice
+    price: 5
+  - type: Tag
+    tags:
+    - Trash
+  - type: PhysicalComposition
+    materialComposition:
+      Steel: 25
+  - type: GuideHelp
+    guides:
+    - Cyborgs
+    - Robotics
+
+- type: entity
+  id: LeftArmBorg
+  parent: PartSilicon
+  name: cyborg left arm
+  components:
+  - type: Sprite
+    state: borg_l_arm
+  - type: Tag
+    tags:
+    - Trash
+    - BorgArm
+    - BorgLArm
+  - type: Item
+    heldPrefix: borg-arm
+
+- type: entity
+  id: RightArmBorg
+  parent: PartSilicon
+  name: cyborg right arm
+  components:
+  - type: Sprite
+    state: borg_r_arm
+  - type: Tag
+    tags:
+    - Trash
+    - BorgArm
+    - BorgRArm
+  - type: Item
+    heldPrefix: borg-arm
+
+- type: entity
+  id: LeftLegBorg
+  parent: PartSilicon
+  name: cyborg left leg
+  components:
+  - type: Sprite
+    state: borg_l_leg
+  - type: Tag
+    tags:
+    - Trash
+    - BorgLeg
+    - BorgLLeg
+  - type: Item
+    heldPrefix: borg-leg
+
+- type: entity
+  id: RightLegBorg
+  parent: PartSilicon
+  name: cyborg right leg
+  components:
+  - type: Sprite
+    state: borg_r_leg
+  - type: Tag
+    tags:
+    - Trash
+    - BorgLeg
+    - BorgRLeg
+  - type: Item
+    heldPrefix: borg-leg
+
+- type: entity
+  id: LightHeadBorg
+  parent: PartSilicon
+  name: cyborg head
+  components:
+  - type: Sprite
+    state: borg_head
+  - type: Tag
+    tags:
+    - Trash
+    - BorgHead
+  - type: Item
+    heldPrefix: borg-head
+
+- type: entity
+  id: TorsoBorg
+  parent: PartSilicon
+  name: cyborg torso
+  components:
+  - type: Sprite
+    state: borg_chest
+  - type: Tag
+    tags:
+    - Trash
+    - BorgTorso
+  - type: Item
+    heldPrefix: borg-chest
index 4bc1e0d6eae7709d6cdef9d6c3cdc9a92df8c4ef..b1293ea1ef7bbbbe6f293a304fea24f0001d3b30 100644 (file)
       weight: 0.0008
     - id: ClothingOuterDogi
       weight: 0.00001
-    - id: HeadHuman
+    - id: OrganHumanHead
       weight: 0.00001
     - id: OrganHumanKidneys
       weight: 0.00001
index 140ca47938dfb1f83abf99c07f069d78e7f4046e..111d83b5d9c6f3b5283d725f5608d9a7484eecc5 100644 (file)
@@ -47,7 +47,7 @@
       - !type:Oxygenate
         conditions:
         - !type:MetabolizerTypeCondition
-          type: [ Human, Animal, Rat, Plant ]
+          type: [ Human, Animal, Rat, Plant, Arachnid, Moth ]
       # Convert Oxygen into CO2.
       - !type:ModifyLungGas
         conditions:
index a5ff7128067f3bb2152d84fa88eda68eb5439e77..c5aedc119ccb5e7a67c2ad29afb7583f9d90fdc2 100644 (file)
@@ -42,7 +42,7 @@
         - to: chairRitual
           completed:
             - !type:SpawnPrototype
-              prototype: HeadSkeleton
+              prototype: OrganSkeletonPersonHead
               amount: 1
           steps:
             - tool: Prying
index 7c9a8d12ed02bb1639b9fcd9115b0c58afd1b3ff..ad576b8b60b84cfd4b3715254d9a0b2d9cb2c1d7 100644 (file)
@@ -6,7 +6,7 @@
   sprites: MobArachnidSprites
   defaultSkinTone: "#385878"
   markingLimits: MobArachnidMarkingLimits
-  dollPrototype: MobArachnidDummy
+  dollPrototype: AppearanceArachnid
   skinColoration: Hues
   maleFirstNames: NamesArachnidFirst
   femaleFirstNames: NamesArachnidFirst
index cfb42a460fa23a4da39fbce85b7f947af2ca969e..e08d476ee384777f9f65bfbe805a8df978e85e65 100644 (file)
@@ -6,7 +6,7 @@
   sprites: MobDionaSprites
   defaultSkinTone: "#cdb369"
   markingLimits: MobDionaMarkingLimits
-  dollPrototype: MobDionaDummy
+  dollPrototype: AppearanceDiona
   skinColoration: Hues
   maleFirstNames: NamesDionaFirst
   femaleFirstNames: NamesDionaFirst
index fc800213c19f960c87b8234fe9d89d869a9eb8dd..8d1d41d89211d8bcf8e01743f228be6c1b37ac2c 100644 (file)
@@ -5,5 +5,5 @@
   prototype: MobDwarf
   sprites: MobHumanSprites
   markingLimits: MobHumanMarkingLimits
-  dollPrototype: MobDwarfDummy
+  dollPrototype: AppearanceDwarf
   skinColoration: HumanToned
index bcce8d6ca98bfe399fe49a4f6ce67c558de1d248..e8f9fc0754614912d1e3c85ea2aa51f759892bf0 100644 (file)
@@ -5,7 +5,7 @@
   prototype: MobGingerbread
   sprites: MobGingerbreadSprites
   markingLimits: MobHumanMarkingLimits
-  dollPrototype: MobGingerbreadDummy
+  dollPrototype: AppearanceGingerbread
   skinColoration: HumanToned
   defaultSkinTone: "#9a7c5a"
 
index aef1c95fee76985d45cd38b54b064bf6c5d6a1fb..249e5d5a7413e8b2309f7a4fc95a2f981aaebe3d 100644 (file)
@@ -5,7 +5,7 @@
   prototype: MobHuman
   sprites: MobHumanSprites
   markingLimits: MobHumanMarkingLimits
-  dollPrototype: MobHumanDummy
+  dollPrototype: AppearanceHuman
   skinColoration: HumanToned
 
 # The lack of a layer means that
index ccb75d22c866d71ff319890f401d863799792bfd..aacb6fe57129329ff7813222dd5880785c329c9d 100644 (file)
@@ -6,7 +6,7 @@
   sprites: MobMothSprites
   defaultSkinTone: "#ffda93"
   markingLimits: MobMothMarkingLimits
-  dollPrototype: MobMothDummy
+  dollPrototype: AppearanceMoth
   skinColoration: Hues
   maleFirstNames: NamesMothFirstMale
   femaleFirstNames: NamesMothFirstFemale
index 737c368320f15446b8fe92b3fc67fcbfb2e1183e..cbcc2715a4fddaedb632b1cdaa8de91742c133a4 100644 (file)
@@ -6,7 +6,7 @@
   sprites: MobReptilianSprites
   defaultSkinTone: "#34a223"
   markingLimits: MobReptilianMarkingLimits
-  dollPrototype: MobReptilianDummy
+  dollPrototype: AppearanceReptilian
   skinColoration: Hues
   maleFirstNames: NamesReptilianMale
   femaleFirstNames: NamesReptilianFemale
index bbe2b6196f87f72363fa897ad66e2b20e30aae79..e04f44da5ec2185cccabd27b421f1baf0cdce1c4 100644 (file)
@@ -8,7 +8,7 @@
   markingLimits: MobHumanMarkingLimits
   maleFirstNames: NamesSkeletonFirst
   femaleFirstNames: NamesSkeletonFirst
-  dollPrototype: MobSkeletonPersonDummy
+  dollPrototype: AppearanceSkeletonPerson
   skinColoration: TintedHues
 
 - type: speciesBaseSprites
index 4227efe4f26c56ddcc340ea99b0d20c51b54a367..50961b619c9044670855f9f798d635d33ce4e729 100644 (file)
@@ -6,7 +6,7 @@
   sprites: MobSlimeSprites
   defaultSkinTone: "#b8b8b8"
   markingLimits: MobSlimeMarkingLimits
-  dollPrototype: MobSlimePersonDummy
+  dollPrototype: AppearanceSlimePerson
   skinColoration: Hues
 
 - type: speciesBaseSprites
index b29709b0f2515551ad555e917643706a50b37ac8..22ed5c0461eb903d1f86e272d6fafd7bbc28fc96 100644 (file)
@@ -5,7 +5,7 @@
   prototype: MobVox
   sprites: MobVoxSprites
   markingLimits: MobVoxMarkingLimits
-  dollPrototype: MobVoxDummy
+  dollPrototype: AppearanceVox
   skinColoration: VoxFeathers
   defaultSkinTone: "#6c741d"
   maleFirstNames: NamesVox
index 6f8acfa73eff2813a5925854936ad50de6dff854..f57278ab5ae5c27151aaed8d4226c5fcc2bdef52 100644 (file)
@@ -6,7 +6,7 @@
   sprites: MobVulpkaninSprites
   defaultSkinTone: "#5a3f2d"
   markingLimits: MobVulpkaninMarkingLimits
-  dollPrototype: MobVulpkaninDummy
+  dollPrototype: AppearanceVulpkanin
   skinColoration: VulpkaninColors
   maleFirstNames: names_vulpkanin_male
   femaleFirstNames: names_vulpkanin_female
index 7e0d989e55edcca0d911c96ca6dde35c2bc67e7d..d4b1a99fe8309be9c954445fda4a23cfc6619a5c 100644 (file)
@@ -2,7 +2,7 @@
   # Humans
 
   <Box>
-    <GuideEntityEmbed Entity="MobHumanDummy" Caption=""/>
+    <GuideEntityEmbed Entity="AppearanceHuman" Caption=""/>
   </Box>
 
   Depending on who you ask, humans are either unremarkable or the universal standard to which everything else is compared.
index d407d7abc750694a818d081cdc083c0478fd1b47..2f136801f4d983ea50eea64e2dea0f2bd47933a8 100644 (file)
@@ -2,7 +2,7 @@
   # Moth People
 
   <Box>
-    <GuideEntityEmbed Entity="MobMoth" Caption=""/>
+    <GuideEntityEmbed Entity="AppearanceMoth" Caption=""/>
   </Box>
 
   They can eat cotton, fabrics and clothing, but virtually none of the food that others would consider "edible". They prefer a somewhat lower temperature range than humans.
index 936cd9f5e2df41991e46d44a21cf49c2145e45aa..00680c5106a12a4cc2222f4e024ab7db40a6f502 100644 (file)
@@ -2,7 +2,7 @@
   # Reptilians
 
   <Box>
-    <GuideEntityEmbed Entity="MobReptilian" Caption=""/>
+    <GuideEntityEmbed Entity="AppearanceReptilian" Caption=""/>
   </Box>
 
   They can ONLY eat fruits and meat, but can eat raw meat and drink blood without any ill effects.
index fc9c5db710c2b2172df1e671727dc49843ff639d..a10b5fc4af9ade2faa03fd98287254060ee7da98 100644 (file)
@@ -4,19 +4,19 @@
   Nanotrasen employs a variety of sapient species.
 
   <Box>
-  <GuideEntityEmbed Entity="MobArachnid" Caption="Arachnid"/>
-  <GuideEntityEmbed Entity="MobDiona" Caption="Diona"/>
-  <GuideEntityEmbed Entity="MobDwarf" Caption="Dwarf"/>
-  <GuideEntityEmbed Entity="MobHuman" Caption="Human"/>
+  <GuideEntityEmbed Entity="AppearanceArachnid" Caption="Arachnid"/>
+  <GuideEntityEmbed Entity="AppearanceDiona" Caption="Diona"/>
+  <GuideEntityEmbed Entity="AppearanceDwarf" Caption="Dwarf"/>
+  <GuideEntityEmbed Entity="AppearanceHuman" Caption="Human"/>
   </Box>
   <Box>
-  <GuideEntityEmbed Entity="MobMoth" Caption="Moth Person"/>
-  <GuideEntityEmbed Entity="MobReptilian" Caption="Reptilian"/>
-  <GuideEntityEmbed Entity="MobSlimePerson" Caption="Slime Person"/>
-  <GuideEntityEmbed Entity="MobVox" Caption="Vox"/>
+  <GuideEntityEmbed Entity="AppearanceMoth" Caption="Moth Person"/>
+  <GuideEntityEmbed Entity="AppearanceReptilian" Caption="Reptilian"/>
+  <GuideEntityEmbed Entity="AppearanceSlimePerson" Caption="Slime Person"/>
+  <GuideEntityEmbed Entity="AppearanceVox" Caption="Vox"/>
   </Box>
   <Box>
-    <GuideEntityEmbed Entity="MobVulpkanin" Caption="Vulpkanin"/>
+    <GuideEntityEmbed Entity="AppearanceVulpkanin" Caption="Vulpkanin"/>
   </Box>
 
 </Document>
index 451ab138dfa9f20ccdd03984bfaec808da81adfb..25a0c60180b0c3e88d546d7e7b88b0bf0426f662 100644 (file)
@@ -8,7 +8,7 @@
   },
   "states": [
     {
-      "name": "brain-slime"
+      "name": "brain"
     },
     {
       "name": "brain-inhand-left",
         "directions": 4
     },
     {
-      "name": "lung-l-slime"
+      "name": "lung-l"
     },
     {
-      "name": "lung-r-slime"
+      "name": "lung-r"
     }
   ]
 }
index 08d552452af8f55344c7a852c78d3547e76f631a..daab17ef73ba22f6ebdb9e673824f0ea4e0625d0 100644 (file)
@@ -769,3 +769,17 @@ HandheldHealthAnalyzerEmpty: HandheldHealthAnalyzer
 
 #2026-01-09
 BorgModuleAdvancedChemical: BorgModuleAdvancedTopical
+
+# 2026-01-14
+HeadHuman: OrganHumanHead
+HeadSkeleton: OrganSkeletonPersonHead
+LeftArmHuman: OrganHumanArmLeft
+LeftArmSkeleton: OrganSkeletonPersonArmLeft
+LeftHandSkeleton: OrganSkeletonPersonHandLeft
+LeftLegHuman: OrganHumanLegLeft
+LeftLegSkeleton: OrganSkeletonPersonLegLeft
+RightArmHuman: OrganHumanArmRight
+RightHandSkeleton: OrganSkeletonPersonHandRight
+RightLegHuman: OrganHumanLegRight
+TorsoSkeleton: OrganSkeletonPersonTorso
+RightArmSkeleton: OrganSkeletonPersonArmRight