+++ /dev/null
-using Content.Shared.Body.Systems;
-
-namespace Content.Client.Body.Systems;
-
-public sealed class BodySystem : SharedBodySystem
-{
-}
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;
continue;
//these bloat the hell out of blood/fat
- if (entProto.HasComponent<BodyPartComponent>())
+ if (entProto.HasComponent<OrganComponent>())
continue;
//these feel obvious...
+++ /dev/null
-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;
- }
- }
- }
-}
+++ /dev/null
-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);
- }
- }
-}
--- /dev/null
+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();
+ }
+}
--- /dev/null
+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();
+ }
+}
+++ /dev/null
-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();
- }
- }
-}
+++ /dev/null
-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();
- }
- }
-}
+++ /dev/null
-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();
- }
-}
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;
EntityUid human = default;
BuckleComponent buckle = null;
HandsComponent hands = null;
- BodyComponent body = null;
await server.WaitIdleAsync();
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
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
--- /dev/null
+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();
+ }
+}
+++ /dev/null
-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}.");
- }
-}
+++ /dev/null
-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}.");
- }
- }
- }
-}
+using System.Linq;
using System.Numerics;
using System.Threading;
using Content.Server.Atmos.EntitySystems;
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;
args.Verbs.Add(bloodRemoval);
}
- // bobby...
if (TryComp<BodyComponent>(args.Target, out var body))
{
var vomitOrgansName = Loc.GetString("admin-smite-vomit-organs-name").ToLowerInvariant();
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,
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);
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,
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);
}
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);
}
private void OnAnomalySupercritical(Entity<InnerBodyAnomalyComponent> ent, ref AnomalySupercriticalEvent args)
{
- if (!TryComp<BodyComponent>(ent, out var body))
- return;
-
_gibbing.Gib(ent.Owner);
}
-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;
[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)
{
}
entity = player.AttachedEntity.Value;
- hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
break;
case 1:
{
}
entity = uid.Value;
- hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
}
else
{
}
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:
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}");
}
+++ /dev/null
-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)}");
- }
- }
-}
+++ /dev/null
-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)));
- }
- }
-}
+++ /dev/null
-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);
- }
- }
- }
-}
+++ /dev/null
-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);
- }
-}
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;
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)
}
}
- 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)
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;
[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!;
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)
/// <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>
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)
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
+ };
}
}
[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>
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;
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;
{
[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!;
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)
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;
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;
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);
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)
-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;
}
// 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);
using Content.Server.Administration.Logs;
-using Content.Server.Body.Systems;
using Content.Server.Construction;
using Content.Server.Explosion.EntitySystems;
using Content.Server.DeviceLinking.Systems;
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;
{
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!;
_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);
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;
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;
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;
{
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))
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
using System.Linq;
-using Content.Shared.Body.Part;
using Content.Shared.Destructible;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
-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;
}
}
- if (!TryComp<BodyComponent>(contained, out var body))
- Del(contained);
-
var gibs = _gibbing.Gib(contained);
foreach (var gib in gibs)
{
--- /dev/null
+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);
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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);
--- /dev/null
+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;
+ }
+}
+++ /dev/null
-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();
-}
+++ /dev/null
-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);
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Body;
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(GibbableOrganSystem))]
+public sealed partial class GibbableOrganComponent : Component;
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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;
+}
--- /dev/null
+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);
+ }
+}
+++ /dev/null
-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;
-}
--- /dev/null
+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!;
+}
--- /dev/null
+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;
+}
+++ /dev/null
-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;
- }
-};
+++ /dev/null
-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);
+++ /dev/null
-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
- }
-}
+++ /dev/null
-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
- }
-}
+++ /dev/null
-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);
+++ /dev/null
-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);
- }
-}
using Content.Shared.Body.Components;
-using Content.Shared.Body.Events;
using Content.Shared.Ghost;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
{
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);
}
+++ /dev/null
-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);
- }
- }
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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
-}
+++ /dev/null
-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;
- }
-}
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;
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;
using System.Linq;
-using Content.Shared.Body.Systems;
using Content.Shared.Clothing.Components;
using Content.Shared.Humanoid;
using Content.Shared.Preferences;
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)
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
-
namespace Content.Shared.Humanoid
{
public static class HumanoidVisualLayersExtension
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;
- }
}
}
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;
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;
+using Content.Shared.Body;
using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Content.Shared.Chemistry.Components;
[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!;
{
base.Initialize();
- SubscribeLocalEvent<BodyComponent, TryVomitEvent>(TryBodyVomitSolution);
+ SubscribeLocalEvent<StomachComponent, BodyRelayedEvent<TryVomitEvent>>(TryVomitSolution);
}
private const float ChemMultiplier = 0.1f;
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>
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;
[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!;
/// <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();
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;
}
}
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;
}
}
/// </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);
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;
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?
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;
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)
-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;
{
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
[Dependency] private readonly StandingStateSystem _standingSystem = default!;
- [Dependency] private readonly SharedBodySystem _bodySystem = default!;
public override void Initialize()
{
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)
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!
- 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:
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- type: entity
+ id: BaseMobSlimes
+ abstract: true
+ components:
+ - type: Body
+ - type: EntityTableContainerFill
+ containers:
+ body_organs: !type:AllSelector
+ children:
+ - id: OrganSlimePersonCore
+ - id: OrganSlimePersonLungs
+++ /dev/null
-- 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
+++ /dev/null
-- 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 ]
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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]
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- type: entity
- id: OrganVulpkaninStomach
- parent: OrganAnimalStomach
- categories: [ HideSpawnMenu ]
- components:
- - type: SolutionContainerManager
- solutions:
- stomach:
- maxVol: 50
- food:
- maxVol: 5
- reagents:
- - ReagentId: UncookedAnimalProteins
- Quantity: 5
+++ /dev/null
-# 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
+++ /dev/null
-# 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"
+++ /dev/null
-# 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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"
+++ /dev/null
-# 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"
+++ /dev/null
-# 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"
+++ /dev/null
-# 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
+++ /dev/null
-# 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"
+++ /dev/null
-- 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
+++ /dev/null
-# 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
+++ /dev/null
-# 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"
+++ /dev/null
-# 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"
+++ /dev/null
-# 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- type: body
- id: Mothroach
- name: "mothroach"
- root: torso
- slots:
- torso:
- part: TorsoAnimal
- organs:
- lungs: OrganAnimalLungs
- stomach: OrganMothStomach
- liver: OrganAnimalLiver
- heart: OrganAnimalHeart
- kidneys: OrganAnimalKidneys
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
- 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:
color: "#555555AA"
Burn:
sprite: Mobs/Effects/burn_damage.rsi
- - type: MobState
- type: MobThresholds
thresholds:
0: Alive
!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
--- /dev/null
+- 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
-- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
--- /dev/null
+- 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
- 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
- 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
- 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
- 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.
damage:
types:
Slash: 5
- - type: Body
- prototype: Animal
- type: Flammable
fireSpread: true
canResistFire: true
- MobDamageable
- MobAtmosExposed
- MobCombat
+ - BaseMobAnimal
abstract: true
components:
- type: Reactive
Flammable: [Touch]
Extinguish: [Touch]
Acidic: [Touch, Ingestion]
- - type: Body
- prototype: Animal
- type: Climbing
- type: NameIdentifier
group: GenericNumber
- 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
+++ /dev/null
-- 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
- BaseSimpleMob
- MobCombat
- MobBloodstream
+ - BaseMobAnimal
id: MobHellspawn
description: An unstoppable force of carnage.
components:
- type: NpcFactionMember
factions:
- SimpleHostile
- - type: Body
- prototype: Animal
- type: Damageable
damageContainer: BiologicalMetaphysical
damageModifierSet: HellSpawn
- type: entity
name: civilian
- parent: BaseMobHuman
+ parent: MobHuman
id: MobCivilian
description: A miserable pile of secrets.
components:
- type: entity
name: salvager
- parent: BaseMobHuman
+ parent: MobHuman
id: MobSalvager
components:
- type: NpcFactionMember
- type: entity
name: spirate
- parent: BaseMobHuman
+ parent: MobHuman
id: MobSpirate
description: Yarr!
components:
- type: entity
name: syndicate footsoldier
- parent: BaseMobHuman
+ parent: MobHuman
id: MobSyndicateFootsoldier
components:
- type: NpcFactionMember
id: MobSyndicateFootsoldierPilot
- type: entity
- parent: BaseMobHuman
+ parent: MobHuman
suffix: Dead
save: false # mobs are currently not saveable.
id: SalvageHumanCorpse
- 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
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
- 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
- MobCombat
- MobBloodstream
- MobFlammable
+ - BaseMobAnimal
id: SimpleSpaceMobBase # Mob without barotrauma, freezing and asphyxiation (for space carps!?)
suffix: AI
components:
- type: MeleeWeapon
angle: 0
animation: WeaponArcBite
- - type: Body
- prototype: Animal
- type: Climbing
- type: NameIdentifier
group: GenericNumber
- 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:
type: Local
messages: [ "slime-hurt-by-water-popup" ]
probability: 0.25
- - type: Body
- prototype: Slimes
- requiredLegs: 1
- type: MeleeWeapon
altDisarm: false
soundHit:
- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- type: entity
- save: false
- name: Urist McHands The Dwarf
- parent: BaseMobDwarf
- id: MobDwarf
+++ /dev/null
-- 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
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:
-- type: entity
- save: false
- name: Urist McHands
- parent: BaseMobHuman
- id: MobHuman
-
#Syndie
- type: entity
parent: MobHuman
+++ /dev/null
-- type: entity
- save: false
- name: Urist McFluff
- parent: BaseMobMoth
- id: MobMoth
+++ /dev/null
-- type: entity
- save: false
- name: Urist McScales
- suffix: Urisst' Mzhand
- parent: BaseMobReptilian
- id: MobReptilian
-
-#Weh
-- 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
+++ /dev/null
-- type: entity
- save: false
- parent: BaseMobSlimePerson
- id: MobSlimePerson
+++ /dev/null
-- type: entity
- save: false
- name: Uristititi McVox
- parent: BaseMobVox
- id: MobVox
+++ /dev/null
-- type: entity
- save: false
- name: Urist McBark
- parent: BaseMobVulpkanin
- id: MobVulpkanin
+++ /dev/null
-- 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<
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-# 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
+++ /dev/null
-- 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
- 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
weight: 0.0008
- id: ClothingOuterDogi
weight: 0.00001
- - id: HeadHuman
+ - id: OrganHumanHead
weight: 0.00001
- id: OrganHumanKidneys
weight: 0.00001
- !type:Oxygenate
conditions:
- !type:MetabolizerTypeCondition
- type: [ Human, Animal, Rat, Plant ]
+ type: [ Human, Animal, Rat, Plant, Arachnid, Moth ]
# Convert Oxygen into CO2.
- !type:ModifyLungGas
conditions:
- to: chairRitual
completed:
- !type:SpawnPrototype
- prototype: HeadSkeleton
+ prototype: OrganSkeletonPersonHead
amount: 1
steps:
- tool: Prying
sprites: MobArachnidSprites
defaultSkinTone: "#385878"
markingLimits: MobArachnidMarkingLimits
- dollPrototype: MobArachnidDummy
+ dollPrototype: AppearanceArachnid
skinColoration: Hues
maleFirstNames: NamesArachnidFirst
femaleFirstNames: NamesArachnidFirst
sprites: MobDionaSprites
defaultSkinTone: "#cdb369"
markingLimits: MobDionaMarkingLimits
- dollPrototype: MobDionaDummy
+ dollPrototype: AppearanceDiona
skinColoration: Hues
maleFirstNames: NamesDionaFirst
femaleFirstNames: NamesDionaFirst
prototype: MobDwarf
sprites: MobHumanSprites
markingLimits: MobHumanMarkingLimits
- dollPrototype: MobDwarfDummy
+ dollPrototype: AppearanceDwarf
skinColoration: HumanToned
prototype: MobGingerbread
sprites: MobGingerbreadSprites
markingLimits: MobHumanMarkingLimits
- dollPrototype: MobGingerbreadDummy
+ dollPrototype: AppearanceGingerbread
skinColoration: HumanToned
defaultSkinTone: "#9a7c5a"
prototype: MobHuman
sprites: MobHumanSprites
markingLimits: MobHumanMarkingLimits
- dollPrototype: MobHumanDummy
+ dollPrototype: AppearanceHuman
skinColoration: HumanToned
# The lack of a layer means that
sprites: MobMothSprites
defaultSkinTone: "#ffda93"
markingLimits: MobMothMarkingLimits
- dollPrototype: MobMothDummy
+ dollPrototype: AppearanceMoth
skinColoration: Hues
maleFirstNames: NamesMothFirstMale
femaleFirstNames: NamesMothFirstFemale
sprites: MobReptilianSprites
defaultSkinTone: "#34a223"
markingLimits: MobReptilianMarkingLimits
- dollPrototype: MobReptilianDummy
+ dollPrototype: AppearanceReptilian
skinColoration: Hues
maleFirstNames: NamesReptilianMale
femaleFirstNames: NamesReptilianFemale
markingLimits: MobHumanMarkingLimits
maleFirstNames: NamesSkeletonFirst
femaleFirstNames: NamesSkeletonFirst
- dollPrototype: MobSkeletonPersonDummy
+ dollPrototype: AppearanceSkeletonPerson
skinColoration: TintedHues
- type: speciesBaseSprites
sprites: MobSlimeSprites
defaultSkinTone: "#b8b8b8"
markingLimits: MobSlimeMarkingLimits
- dollPrototype: MobSlimePersonDummy
+ dollPrototype: AppearanceSlimePerson
skinColoration: Hues
- type: speciesBaseSprites
prototype: MobVox
sprites: MobVoxSprites
markingLimits: MobVoxMarkingLimits
- dollPrototype: MobVoxDummy
+ dollPrototype: AppearanceVox
skinColoration: VoxFeathers
defaultSkinTone: "#6c741d"
maleFirstNames: NamesVox
sprites: MobVulpkaninSprites
defaultSkinTone: "#5a3f2d"
markingLimits: MobVulpkaninMarkingLimits
- dollPrototype: MobVulpkaninDummy
+ dollPrototype: AppearanceVulpkanin
skinColoration: VulpkaninColors
maleFirstNames: names_vulpkanin_male
femaleFirstNames: names_vulpkanin_female
# 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.
# 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.
# 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.
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>
},
"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"
}
]
}
#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