]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Decouple gibbing from the body system (#42405)
authorpathetic meowmeow <uhhadd@gmail.com>
Wed, 14 Jan 2026 05:57:08 +0000 (00:57 -0500)
committerGitHub <noreply@github.com>
Wed, 14 Jan 2026 05:57:08 +0000 (05:57 +0000)
* Decouple gibbing from the body system

* allow gibs that don't drop giblets

* pass through user

* prediction gon

* comment

* destructible

* playpvs

* very very very very very very very minor cleanup

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
37 files changed:
Content.IntegrationTests/Tests/Body/GibTest.cs [deleted file]
Content.IntegrationTests/Tests/Gibbing/GibTest.cs [new file with mode: 0644]
Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs
Content.Server/Anomaly/Effects/InnerBodyAnomalySystem.cs
Content.Server/Atmos/Rotting/RottingSystem.cs
Content.Server/Body/Systems/BodySystem.cs
Content.Server/Destructible/DestructibleSystem.cs
Content.Server/Destructible/Thresholds/Behaviors/GibBehavior.cs
Content.Server/Forensics/Systems/ForensicsSystem.cs
Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
Content.Server/Guardian/GuardianSystem.cs
Content.Server/ImmovableRod/ImmovableRodSystem.cs
Content.Server/Implants/ImplantedSystem.cs
Content.Server/Kitchen/EntitySystems/SharpSystem.cs
Content.Server/Materials/MaterialReclaimerSystem.cs
Content.Server/Mind/TransferMindOnGibSystem.cs
Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
Content.Server/Shuttles/Systems/ShuttleSystem.cs
Content.Server/Xenoarchaeology/Equipment/Systems/ArtifactCrusherSystem.cs
Content.Shared/Body/Events/BeingGibbedEvent.cs [deleted file]
Content.Shared/Body/Systems/SharedBloodstreamSystem.cs
Content.Shared/Body/Systems/SharedBodySystem.Body.cs
Content.Shared/Devour/DevourSystem.cs
Content.Shared/Gibbing/Components/GibbableComponent.cs [deleted file]
Content.Shared/Gibbing/Events/GibbingEvents.cs [deleted file]
Content.Shared/Gibbing/GibOnRoundEndComponent.cs [moved from Content.Shared/Gibbing/Components/GibOnRoundEndComponent.cs with 100% similarity]
Content.Shared/Gibbing/GibbingSystem.cs [new file with mode: 0644]
Content.Shared/Gibbing/Systems/GibbingSystem.cs [deleted file]
Content.Shared/Kitchen/SharedKitchenSpikeSystem.cs
Content.Shared/Magic/SharedMagicSystem.cs
Content.Shared/Silicons/Borgs/SharedBorgSystem.cs
Content.Shared/Species/Systems/GibActionSystem.cs
Content.Shared/Trigger/Systems/GibOnTriggerSystem.cs
Resources/Prototypes/Body/Organs/Animal/animal.yml
Resources/Prototypes/Body/Organs/human.yml
Resources/Prototypes/Body/Parts/animal.yml
Resources/Prototypes/Body/Parts/base.yml

diff --git a/Content.IntegrationTests/Tests/Body/GibTest.cs b/Content.IntegrationTests/Tests/Body/GibTest.cs
deleted file mode 100644 (file)
index 4627c79..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#nullable enable
-using Content.Server.Body.Systems;
-using Robust.Shared.GameObjects;
-
-namespace Content.IntegrationTests.Tests.Body;
-
-[TestFixture]
-public sealed class GibTest
-{
-    [Test]
-    public async Task TestGib()
-    {
-        await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true });
-        var (server, client) = (pair.Server, pair.Client);
-        var map = await pair.CreateTestMap();
-
-        EntityUid target1 = default;
-        EntityUid target2 = default;
-
-        await server.WaitAssertion(() => target1 = server.EntMan.Spawn("MobHuman", map.MapCoords));
-        await server.WaitAssertion(() => target2 = server.EntMan.Spawn("MobHuman", map.MapCoords));
-        await pair.WaitCommand($"setoutfit {server.EntMan.GetNetEntity(target1)} CaptainGear");
-        await pair.WaitCommand($"setoutfit {server.EntMan.GetNetEntity(target2)} CaptainGear");
-
-        await pair.RunTicksSync(5);
-        var nuid1 = pair.ToClientUid(target1);
-        var nuid2 = pair.ToClientUid(target2);
-        Assert.That(client.EntMan.EntityExists(nuid1));
-        Assert.That(client.EntMan.EntityExists(nuid2));
-
-        await server.WaitAssertion(() => server.System<BodySystem>().GibBody(target1, gibOrgans: false));
-        await server.WaitAssertion(() => server.System<BodySystem>().GibBody(target2, gibOrgans: true));
-
-        await pair.RunTicksSync(5);
-        await pair.WaitCommand("dirty");
-        await pair.RunTicksSync(5);
-
-        Assert.That(!client.EntMan.EntityExists(nuid1));
-        Assert.That(!client.EntMan.EntityExists(nuid2));
-
-        await pair.CleanReturnAsync();
-    }
-}
diff --git a/Content.IntegrationTests/Tests/Gibbing/GibTest.cs b/Content.IntegrationTests/Tests/Gibbing/GibTest.cs
new file mode 100644 (file)
index 0000000..ee0f7a7
--- /dev/null
@@ -0,0 +1,36 @@
+#nullable enable
+using Content.Shared.Gibbing;
+using Robust.Shared.GameObjects;
+
+namespace Content.IntegrationTests.Tests.Body;
+
+[TestFixture]
+public sealed class GibTest
+{
+    [Test]
+    public async Task TestGib()
+    {
+        await using var pair = await PoolManager.GetServerClient(new PoolSettings { Connected = true });
+        var (server, client) = (pair.Server, pair.Client);
+        var map = await pair.CreateTestMap();
+
+        EntityUid target = default;
+
+        await server.WaitAssertion(() => target = server.EntMan.Spawn("MobHuman", map.MapCoords));
+        await pair.WaitCommand($"setoutfit {server.EntMan.GetNetEntity(target)} CaptainGear");
+
+        await pair.RunTicksSync(5);
+        var nuid = pair.ToClientUid(target);
+        Assert.That(client.EntMan.EntityExists(nuid));
+
+        await server.WaitAssertion(() => server.System<GibbingSystem>().Gib(target));
+
+        await pair.RunTicksSync(5);
+        await pair.WaitCommand("dirty");
+        await pair.RunTicksSync(5);
+
+        Assert.That(!client.EntMan.EntityExists(nuid));
+
+        await pair.CleanReturnAsync();
+    }
+}
index f367acbd796d2631e3dbb5e61689abc08d2f192c..bae7776ef0691388fa6b64dcc6242065d2878818 100644 (file)
@@ -29,6 +29,7 @@ using Content.Shared.Damage.Components;
 using Content.Shared.Damage.Systems;
 using Content.Shared.Database;
 using Content.Shared.Electrocution;
+using Content.Shared.Gibbing;
 using Content.Shared.Gravity;
 using Content.Shared.Interaction.Components;
 using Content.Shared.Inventory;
@@ -92,6 +93,7 @@ public sealed partial class AdminVerbSystem
     [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
     [Dependency] private readonly SuperBonkSystem _superBonkSystem = default!;
     [Dependency] private readonly SlipperySystem _slipperySystem = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
 
     private readonly EntProtoId _actionViewLawsProtoId = "ActionViewLaws";
     private readonly ProtoId<SiliconLawsetPrototype> _crewsimovLawset = "Crewsimov";
@@ -128,7 +130,7 @@ public sealed partial class AdminVerbSystem
                         4, 1, 2, args.Target, maxTileBreak: 0), // it gibs, damage doesn't need to be high.
                     CancellationToken.None);
 
-                _bodySystem.GibBody(args.Target);
+                _gibbing.Gib(args.Target);
             },
             Impact = LogImpact.Extreme,
             Message = string.Join(": ", explodeName, Loc.GetString("admin-smite-explode-description")) // we do this so the description tells admins the Text to run it via console.
index d6039fac0158bae822609e7846a93d53ca5d8d96..9c671d4db23439f4a9f91f636b417ce2c6373408 100644 (file)
@@ -10,6 +10,7 @@ using Content.Shared.Anomaly.Effects;
 using Content.Shared.Body.Components;
 using Content.Shared.Chat;
 using Content.Shared.Database;
+using Content.Shared.Gibbing;
 using Content.Shared.Mobs;
 using Content.Shared.Popups;
 using Content.Shared.Whitelist;
@@ -25,7 +26,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
     [Dependency] private readonly IAdminLogManager _adminLog = default!;
     [Dependency] private readonly AnomalySystem _anomaly = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
-    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly IChatManager _chat = default!;
     [Dependency] private readonly ISharedPlayerManager _player = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
@@ -134,7 +135,7 @@ public sealed class InnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
         if (!TryComp<BodyComponent>(ent, out var body))
             return;
 
-        _body.GibBody(ent, true, body, splatModifier: 5f);
+        _gibbing.Gib(ent.Owner);
     }
 
     private void OnSeverityChanged(Entity<InnerBodyAnomalyComponent> ent, ref AnomalySeverityChangedEvent args)
index e83d80748b60a0e5b1f23bc07b2dd33925f70a26..ea45bf5ed69c72178ecd13c4f9c3d83a3b22713f 100644 (file)
@@ -3,6 +3,7 @@ using Content.Shared.Atmos;
 using Content.Shared.Atmos.Rotting;
 using Content.Shared.Body.Events;
 using Content.Shared.Damage.Systems;
+using Content.Shared.Gibbing;
 using Content.Shared.Temperature.Components;
 using Robust.Server.Containers;
 using Robust.Shared.Physics.Components;
@@ -21,12 +22,12 @@ public sealed class RottingSystem : SharedRottingSystem
     {
         base.Initialize();
 
-        SubscribeLocalEvent<RottingComponent, BeingGibbedEvent>(OnGibbed);
+        SubscribeLocalEvent<RottingComponent, GibbedBeforeDeletionEvent>(OnGibbed);
 
         SubscribeLocalEvent<TemperatureComponent, IsRottingEvent>(OnTempIsRotting);
     }
 
-    private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEvent args)
+    private void OnGibbed(EntityUid uid, RottingComponent component, GibbedBeforeDeletionEvent args)
     {
         if (!TryComp<PhysicsComponent>(uid, out var physics))
             return;
index 957dea9d41837204acd897a8c0fa010cec185235..2627e97982512133782d917f0b11e20f6af65662 100644 (file)
@@ -92,40 +92,4 @@ public sealed class BodySystem : SharedBodySystem
         var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
         _humanoidSystem.SetLayersVisibility((bodyEnt, humanoid), layers, visible: false);
     }
-
-    public override HashSet<EntityUid> GibBody(
-        EntityUid bodyId,
-        bool gibOrgans = false,
-        BodyComponent? body = null,
-        bool launchGibs = true,
-        Vector2? splatDirection = null,
-        float splatModifier = 1,
-        Angle splatCone = default,
-        SoundSpecifier? gibSoundOverride = null
-    )
-    {
-        if (!Resolve(bodyId, ref body, logMissing: false)
-            || TerminatingOrDeleted(bodyId)
-            || EntityManager.IsQueuedForDeletion(bodyId))
-        {
-            return new HashSet<EntityUid>();
-        }
-
-        if (HasComp<GodmodeComponent>(bodyId))
-            return new HashSet<EntityUid>();
-
-        var xform = Transform(bodyId);
-        if (xform.MapUid is null)
-            return new HashSet<EntityUid>();
-
-        var gibs = base.GibBody(bodyId, gibOrgans, body, launchGibs: launchGibs,
-            splatDirection: splatDirection, splatModifier: splatModifier, splatCone:splatCone);
-
-        var ev = new BeingGibbedEvent(gibs);
-        RaiseLocalEvent(bodyId, ref ev);
-
-        QueueDel(bodyId);
-
-        return gibs;
-    }
 }
index 7ed736fffd66e919861b0d3471b6001f5923d2e7..485ecdd9543b78c8f8f63b2982d351ad3322d2d6 100644 (file)
@@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Content.Server.Administration.Logs;
 using Content.Server.Atmos.EntitySystems;
-using Content.Server.Body.Systems;
 using Content.Server.Construction;
 using Content.Server.Destructible.Thresholds;
 using Content.Server.Destructible.Thresholds.Behaviors;
@@ -16,6 +15,7 @@ using Content.Shared.Database;
 using Content.Shared.Destructible;
 using Content.Shared.Destructible.Thresholds.Triggers;
 using Content.Shared.FixedPoint;
+using Content.Shared.Gibbing;
 using Content.Shared.Humanoid;
 using Content.Shared.Trigger.Systems;
 using JetBrains.Annotations;
@@ -34,7 +34,7 @@ namespace Content.Server.Destructible
 
         [Dependency] public readonly AtmosphereSystem AtmosphereSystem = default!;
         [Dependency] public readonly AudioSystem AudioSystem = default!;
-        [Dependency] public readonly BodySystem BodySystem = default!;
+        [Dependency] public readonly GibbingSystem Gibbing = default!;
         [Dependency] public readonly ConstructionSystem ConstructionSystem = default!;
         [Dependency] public readonly ExplosionSystem ExplosionSystem = default!;
         [Dependency] public readonly StackSystem StackSystem = default!;
index 9aa798a3d093385d11717d367e2b2f6263bf7154..1addf96b62aed356b6ee9ba415a95bbe8e953b95 100644 (file)
@@ -14,10 +14,7 @@ namespace Content.Server.Destructible.Thresholds.Behaviors
 
         public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
         {
-            if (system.EntityManager.TryGetComponent(owner, out BodyComponent? body))
-            {
-                system.BodySystem.GibBody(owner, _recursive, body);
-            }
+            system.Gibbing.Gib(owner, _recursive);
         }
     }
 }
index 8370014ad668f4333b5aaf27a7bbd61705f85e7a..078ce44e2b717bbdbfec3218f278272fec29a4db 100644 (file)
@@ -13,6 +13,7 @@ using Content.Shared.DoAfter;
 using Content.Shared.Forensics;
 using Content.Shared.Forensics.Components;
 using Content.Shared.Forensics.Systems;
+using Content.Shared.Gibbing;
 using Content.Shared.Interaction;
 using Content.Shared.Interaction.Events;
 using Content.Shared.Inventory;
@@ -39,7 +40,7 @@ namespace Content.Server.Forensics
             // The solution entities are spawned on MapInit as well, so we have to wait for that to be able to set the DNA in the bloodstream correctly without ResolveSolution failing
             SubscribeLocalEvent<DnaComponent, MapInitEvent>(OnDNAInit, after: new[] { typeof(BloodstreamSystem) });
 
-            SubscribeLocalEvent<ForensicsComponent, BeingGibbedEvent>(OnBeingGibbed);
+            SubscribeLocalEvent<ForensicsComponent, GibbedBeforeDeletionEvent>(OnBeingGibbed);
             SubscribeLocalEvent<ForensicsComponent, MeleeHitEvent>(OnMeleeHit);
             SubscribeLocalEvent<ForensicsComponent, GotRehydratedEvent>(OnRehydrated);
             SubscribeLocalEvent<CleansForensicsComponent, AfterInteractEvent>(OnAfterInteract, after: new[] { typeof(AbsorbentSystem) });
@@ -85,14 +86,14 @@ namespace Content.Server.Forensics
             }
         }
 
-        private void OnBeingGibbed(EntityUid uid, ForensicsComponent component, BeingGibbedEvent args)
+        private void OnBeingGibbed(Entity<ForensicsComponent> ent, ref GibbedBeforeDeletionEvent args)
         {
             string dna = Loc.GetString("forensics-dna-unknown");
 
-            if (TryComp(uid, out DnaComponent? dnaComp) && dnaComp.DNA != null)
+            if (TryComp(ent, out DnaComponent? dnaComp) && dnaComp.DNA != null)
                 dna = dnaComp.DNA;
 
-            foreach (EntityUid part in args.GibbedParts)
+            foreach (var part in args.Giblets)
             {
                 var partComp = EnsureComp<ForensicsComponent>(part);
                 partComp.DNAs.Add(dna);
index d23832984f8065ef5c944ff99ebd51d42dd3b667..8736908da630222e9a94b920b2d2131cc3016db8 100644 (file)
@@ -2,12 +2,12 @@
 using Content.Shared.Gibbing.Components;
 using Content.Shared.Mind;
 using Content.Shared.Objectives.Systems;
-using Content.Server.Body.Systems;
+using Content.Shared.Gibbing;
 
 namespace Content.Server.Gibbing.Systems;
 public sealed class GibOnRoundEndSystem : EntitySystem
 {
-    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly SharedMindSystem _mind = default!;
     [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
 
@@ -49,7 +49,7 @@ public sealed class GibOnRoundEndSystem : EntitySystem
             if (gibComp.SpawnProto != null)
                 SpawnAtPosition(gibComp.SpawnProto, Transform(uid).Coordinates);
 
-            _body.GibBody(uid, splatModifier: 5f);
+            _gibbing.Gib(uid);
         }
     }
 }
index 5f2597afef33a4811d21d93d53948cfaf2fd52de..16907dda8d143f91955c15602d09b2317d4291da 100644 (file)
@@ -1,9 +1,9 @@
-using Content.Server.Body.Systems;
 using Content.Server.Popups;
 using Content.Shared.Actions;
 using Content.Shared.Damage.Systems;
 using Content.Shared.DoAfter;
 using Content.Shared.Examine;
+using Content.Shared.Gibbing;
 using Content.Shared.Guardian;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
@@ -31,7 +31,7 @@ namespace Content.Server.Guardian
         [Dependency] private readonly SharedActionsSystem _actionSystem = default!;
         [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
         [Dependency] private readonly SharedAudioSystem _audio = default!;
-        [Dependency] private readonly BodySystem _bodySystem = default!;
+        [Dependency] private readonly GibbingSystem _gibbing = default!;
         [Dependency] private readonly SharedContainerSystem _container = default!;
         [Dependency] private readonly SharedTransformSystem _transform = default!;
 
@@ -130,7 +130,7 @@ namespace Content.Server.Guardian
 
             // Ensure held items are dropped before deleting guardian.
             if (HasComp<HandsComponent>(guardian))
-                _bodySystem.GibBody(component.HostedGuardian.Value);
+                _gibbing.Gib(component.HostedGuardian.Value);
 
             QueueDel(guardian);
             QueueDel(component.ActionEntity);
index 646b5c97bbdb4d294c2215a12b96369544e0d156..a06d521a3bef2ea8701dbbc1b5e2cfe2e07346c5 100644 (file)
@@ -5,6 +5,7 @@ using Content.Server.Popups;
 using Content.Shared.Body.Components;
 using Content.Shared.Damage.Systems;
 using Content.Shared.Examine;
+using Content.Shared.Gibbing;
 using Content.Shared.Popups;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Map;
@@ -20,7 +21,7 @@ public sealed class ImmovableRodSystem : EntitySystem
 {
     [Dependency] private readonly IRobustRandom _random = default!;
 
-    [Dependency] private readonly BodySystem _bodySystem = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly PopupSystem _popup = default!;
     [Dependency] private readonly SharedPhysicsSystem _physics = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
@@ -125,7 +126,7 @@ public sealed class ImmovableRodSystem : EntitySystem
                 return;
             }
 
-            _bodySystem.GibBody(ent, body: body);
+            _gibbing.Gib(ent);
             return;
         }
 
index 78517587302f4659835a62b062d8d079b8c1b738..be477119a038513f226ebe166465efde2026c301 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Shared.Body.Events;
+using Content.Shared.Gibbing;
 using Content.Shared.Implants.Components;
 using Content.Shared.Storage;
 using Robust.Shared.Containers;
@@ -11,7 +12,7 @@ public sealed partial class ImplanterSystem
     {
         SubscribeLocalEvent<ImplantedComponent, ComponentInit>(OnImplantedInit);
         SubscribeLocalEvent<ImplantedComponent, ComponentShutdown>(OnShutdown);
-        SubscribeLocalEvent<ImplantedComponent, BeingGibbedEvent>(OnGibbed);
+        SubscribeLocalEvent<ImplantedComponent, GibbedBeforeDeletionEvent>(OnGibbed);
     }
 
     private void OnImplantedInit(Entity<ImplantedComponent> ent, ref ComponentInit args)
@@ -26,7 +27,7 @@ public sealed partial class ImplanterSystem
         _container.CleanContainer(ent.Comp.ImplantContainer);
     }
 
-    private void OnGibbed(Entity<ImplantedComponent> ent, ref BeingGibbedEvent args)
+    private void OnGibbed(Entity<ImplantedComponent> ent, ref GibbedBeforeDeletionEvent args)
     {
         // Drop the storage implant contents before the implants are deleted by the body being gibbed
         foreach (var implant in ent.Comp.ImplantContainer.ContainedEntities)
index 39a3ecb7bb5ae5407bb92d098944fcfefce28bb7..29c4d65d5b2be17093e390d48401d15522f728c9 100644 (file)
@@ -1,9 +1,8 @@
-using Content.Server.Body.Systems;
-using Content.Shared.Administration.Logs;
-using Content.Shared.Body.Components;
+using Content.Shared.Administration.Logs;
 using Content.Shared.Database;
 using Content.Shared.Destructible;
 using Content.Shared.DoAfter;
+using Content.Shared.Gibbing;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Interaction;
 using Content.Shared.Kitchen;
@@ -24,7 +23,7 @@ namespace Content.Server.Kitchen.EntitySystems;
 
 public sealed class SharpSystem : EntitySystem
 {
-    [Dependency] private readonly BodySystem _bodySystem = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!;
     [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
@@ -134,7 +133,7 @@ public sealed class SharpSystem : EntitySystem
             args.Args.User,
             popupType);
 
-        _bodySystem.GibBody(args.Args.Target.Value); // does nothing if ent can't be gibbed
+        _gibbing.Gib(args.Args.Target.Value); // does nothing if ent can't be gibbed
         _destructibleSystem.DestroyEntity(args.Args.Target.Value);
 
         args.Handled = true;
index 15ff93833def115d5bc7bd671a3d9daed70c3d8b..7af39b84a1c5c30f711aca8d43729117ca2f7ce2 100644 (file)
@@ -4,7 +4,6 @@ using Content.Server.Ghost;
 using Content.Server.Popups;
 using Content.Server.Stack;
 using Content.Server.Wires;
-using Content.Shared.Body.Systems;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Chemistry.Components.SolutionManager;
 using Content.Shared.Chemistry.EntitySystems;
@@ -25,6 +24,7 @@ using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Utility;
 using System.Linq;
+using Content.Shared.Gibbing;
 using Content.Shared.Humanoid;
 
 namespace Content.Server.Materials;
@@ -39,7 +39,7 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
     [Dependency] private readonly OpenableSystem _openable = default!;
     [Dependency] private readonly PopupSystem _popup = default!;
     [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
-    [Dependency] private readonly SharedBodySystem _body = default!; //bobby
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly PuddleSystem _puddle = default!;
     [Dependency] private readonly StackSystem _stack = default!;
     [Dependency] private readonly SharedMindSystem _mind = default!;
@@ -112,7 +112,7 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
             Filter.PvsExcept(victim, entityManager: EntityManager),
             true);
 
-        _body.GibBody(victim, true);
+        _gibbing.Gib(victim);
         _appearance.SetData(entity.Owner, RecyclerVisuals.Bloody, true);
         args.Handled = true;
     }
@@ -193,7 +193,7 @@ public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
             _adminLogger.Add(LogType.Gib, logImpact, $"{ToPrettyString(item):victim} was gibbed by {ToPrettyString(uid):entity} ");
             if (component.ReclaimSolutions)
                 SpawnChemicalsFromComposition(uid, item, completion, false, component, xform);
-            _body.GibBody(item, true);
+            _gibbing.Gib(item);
             _appearance.SetData(uid, RecyclerVisuals.Bloody, true);
         }
         else
index ff71fa05609f1e63ec6f2373d307411b2964b025..81ebf96a87e5754196abe85bb66e4b7400ad8fde 100644 (file)
@@ -1,5 +1,5 @@
 using System.Linq;
-using Content.Shared.Body.Events;
+using Content.Shared.Gibbing;
 using Content.Shared.Mind;
 using Content.Shared.Mind.Components;
 using Content.Shared.Tag;
@@ -21,19 +21,19 @@ public sealed class TransferMindOnGibSystem : EntitySystem
     /// <inheritdoc/>
     public override void Initialize()
     {
-        SubscribeLocalEvent<TransferMindOnGibComponent, BeingGibbedEvent>(OnGib);
+        SubscribeLocalEvent<TransferMindOnGibComponent, GibbedBeforeDeletionEvent>(OnGib);
     }
 
-    private void OnGib(EntityUid uid, TransferMindOnGibComponent component, BeingGibbedEvent args)
+    private void OnGib(Entity<TransferMindOnGibComponent> ent, ref GibbedBeforeDeletionEvent args)
     {
-        if (!_mindSystem.TryGetMind(uid, out var mindId, out var mind))
+        if (!_mindSystem.TryGetMind(ent, out var mindId, out var mind))
             return;
 
-        var validParts = args.GibbedParts.Where(p => _tag.HasTag(p, component.TargetTag)).ToHashSet();
+        var validParts = args.Giblets.Where(p => _tag.HasTag(p, ent.Comp.TargetTag)).ToHashSet();
         if (!validParts.Any())
             return;
 
-        var ent = _random.Pick(validParts);
-        _mindSystem.TransferTo(mindId, ent, mind: mind);
+        var transfer = _random.Pick(validParts);
+        _mindSystem.TransferTo(mindId, transfer, mind: mind);
     }
 }
index 1441c2edc8c8cef6c28a026194cbeca0ff869555..766c3e18dcf9d4ed578bd81991a14767f57d6eb0 100644 (file)
@@ -1002,7 +1002,7 @@ public sealed partial class ShuttleSystem
                 {
                     _logger.Add(LogType.Gib, LogImpact.Extreme, $"{ToPrettyString(ent):player} got gibbed by the shuttle" +
                                                                 $" {ToPrettyString(uid)} arriving from FTL at {xform.Coordinates:coordinates}");
-                    var gibs = _bobby.GibBody(ent, body: mob);
+                    var gibs = _gibbing.Gib(ent);
                     _immuneEnts.UnionWith(gibs);
                     continue;
                 }
index 86b97c40a61d2295da66815fd45467c4018d4b62..43607ea1ea2202d07af48145571a5c5e237f051b 100644 (file)
@@ -1,5 +1,4 @@
 using Content.Server.Administration.Logs;
-using Content.Server.Body.Systems;
 using Content.Server.Buckle.Systems;
 using Content.Server.Parallax;
 using Content.Server.Procedural;
@@ -9,6 +8,7 @@ using Content.Server.Station.Systems;
 using Content.Server.Stunnable;
 using Content.Shared.Buckle.Components;
 using Content.Shared.Damage.Systems;
+using Content.Shared.Gibbing;
 using Content.Shared.Light.Components;
 using Content.Shared.Movement.Events;
 using Content.Shared.Salvage;
@@ -42,7 +42,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
     [Dependency] private readonly IPrototypeManager _protoManager = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
     [Dependency] private readonly BiomeSystem _biomes = default!;
-    [Dependency] private readonly BodySystem _bobby = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly BuckleSystem _buckle = default!;
     [Dependency] private readonly DamageableSystem _damageSys = default!;
     [Dependency] private readonly DockingSystem _dockSystem = default!;
index a2cd1eb7155ee0269b626276c6a2bcb8b10d5e8f..5db6ba78e94a6fe9c1861a2b23cdc8f3d318af24 100644 (file)
@@ -1,6 +1,7 @@
 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;
 using Content.Shared.Xenoarchaeology.Equipment;
@@ -14,7 +15,7 @@ namespace Content.Server.Xenoarchaeology.Equipment.Systems;
 public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem
 {
     [Dependency] private readonly IRobustRandom _random = default!;
-    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly StackSystem _stack = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
 
@@ -44,7 +45,7 @@ public sealed class ArtifactCrusherSystem : SharedArtifactCrusherSystem
             if (!TryComp<BodyComponent>(contained, out var body))
                 Del(contained);
 
-            var gibs = _body.GibBody(contained, body: body, gibOrgans: true);
+            var gibs = _gibbing.Gib(contained);
             foreach (var gib in gibs)
             {
                 ContainerSystem.Insert((gib, null, null, null), crusher.OutputContainer);
diff --git a/Content.Shared/Body/Events/BeingGibbedEvent.cs b/Content.Shared/Body/Events/BeingGibbedEvent.cs
deleted file mode 100644 (file)
index 7ab34f2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Content.Shared.Body.Events;
-
-/// <summary>
-/// Raised when a body gets gibbed, before it is deleted.
-/// </summary>
-[ByRefEvent]
-public readonly record struct BeingGibbedEvent(HashSet<EntityUid> GibbedParts);
index e86fd0c06b3bcd2ac382a9312715c9a18bd1dc38..2bce22c0454ddce481cfe4d22d539f763e3c7e43 100644 (file)
@@ -11,6 +11,7 @@ using Content.Shared.EntityEffects.Effects.Solution;
 using Content.Shared.FixedPoint;
 using Content.Shared.Fluids;
 using Content.Shared.Forensics.Components;
+using Content.Shared.Gibbing;
 using Content.Shared.HealthExaminable;
 using Content.Shared.Mobs.Systems;
 using Content.Shared.Popups;
@@ -50,7 +51,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
         SubscribeLocalEvent<BloodstreamComponent, SolutionRelayEvent<ReactionAttemptEvent>>(OnReactionAttempt);
         SubscribeLocalEvent<BloodstreamComponent, DamageChangedEvent>(OnDamageChanged);
         SubscribeLocalEvent<BloodstreamComponent, HealthBeingExaminedEvent>(OnHealthBeingExamined);
-        SubscribeLocalEvent<BloodstreamComponent, BeingGibbedEvent>(OnBeingGibbed);
+        SubscribeLocalEvent<BloodstreamComponent, GibbedBeforeDeletionEvent>(OnBeingGibbed);
         SubscribeLocalEvent<BloodstreamComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
         SubscribeLocalEvent<BloodstreamComponent, RejuvenateEvent>(OnRejuvenate);
         SubscribeLocalEvent<BloodstreamComponent, MetabolismExclusionEvent>(OnMetabolismExclusion);
@@ -262,7 +263,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
         }
     }
 
-    private void OnBeingGibbed(Entity<BloodstreamComponent> ent, ref BeingGibbedEvent args)
+    private void OnBeingGibbed(Entity<BloodstreamComponent> ent, ref GibbedBeforeDeletionEvent args)
     {
         SpillAllSolutions(ent.AsNullable());
     }
index 250f90db8f37e886dd8765e408b237a58dce0884..7750040a07e33afa108a26482b5057ddb25cfc1d 100644 (file)
@@ -5,11 +5,8 @@ using Content.Shared.Body.Organ;
 using Content.Shared.Body.Part;
 using Content.Shared.Body.Prototypes;
 using Content.Shared.DragDrop;
-using Content.Shared.Gibbing.Components;
-using Content.Shared.Gibbing.Events;
-using Content.Shared.Gibbing.Systems;
+using Content.Shared.Gibbing;
 using Content.Shared.Inventory;
-using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Containers;
 using Robust.Shared.Map;
@@ -27,7 +24,6 @@ public partial class SharedBodySystem
      */
 
     [Dependency] private readonly InventorySystem _inventory = default!;
-    [Dependency] private readonly GibbingSystem _gibbingSystem = default!;
     [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
 
     private const float GibletLaunchImpulse = 8;
@@ -42,6 +38,7 @@ public partial class SharedBodySystem
         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)
@@ -283,56 +280,22 @@ public partial class SharedBodySystem
         }
     }
 
-    public virtual HashSet<EntityUid> GibBody(
-        EntityUid bodyId,
-        bool gibOrgans = false,
-        BodyComponent? body = null,
-        bool launchGibs = true,
-        Vector2? splatDirection = null,
-        float splatModifier = 1,
-        Angle splatCone = default,
-        SoundSpecifier? gibSoundOverride = null)
+    private void OnBeingGibbed(Entity<BodyComponent> ent, ref BeingGibbedEvent args)
     {
-        var gibs = new HashSet<EntityUid>();
-
-        if (!Resolve(bodyId, ref body, logMissing: false))
-            return gibs;
-
-        var root = GetRootPartOrNull(bodyId, body);
-        if (root != null && TryComp(root.Value.Entity, out GibbableComponent? gibbable))
-        {
-            gibSoundOverride ??= gibbable.GibSound;
-        }
-        var parts = GetBodyChildren(bodyId, body).ToArray();
-        gibs.EnsureCapacity(parts.Length);
+        var parts = GetBodyChildren(ent, ent).ToArray();
+        args.Giblets.EnsureCapacity(args.Giblets.Capacity + parts.Length);
         foreach (var part in parts)
         {
-
-            _gibbingSystem.TryGibEntityWithRef(bodyId, part.Id, GibType.Gib, GibContentsOption.Skip, ref gibs,
-                playAudio: false, launchGibs:true, launchDirection:splatDirection, launchImpulse: GibletLaunchImpulse * splatModifier,
-                launchImpulseVariance:GibletLaunchImpulseVariance, launchCone: splatCone);
-
-            if (!gibOrgans)
-                continue;
-
             foreach (var organ in GetPartOrgans(part.Id, part.Component))
             {
-                _gibbingSystem.TryGibEntityWithRef(bodyId, organ.Id, GibType.Drop, GibContentsOption.Skip,
-                    ref gibs, playAudio: false, launchImpulse: GibletLaunchImpulse * splatModifier,
-                    launchImpulseVariance:GibletLaunchImpulseVariance, launchCone: splatCone);
+                args.Giblets.Add(organ.Id);
             }
+            PredictedQueueDel(part.Id);
         }
 
-        var bodyTransform = Transform(bodyId);
-        if (TryComp<InventoryComponent>(bodyId, out var inventory))
+        foreach (var item in _inventory.GetHandOrInventoryEntities(ent.Owner))
         {
-            foreach (var item in _inventory.GetHandOrInventoryEntities(bodyId))
-            {
-                SharedTransform.DropNextTo(item, (bodyId, bodyTransform));
-                gibs.Add(item);
-            }
+            args.Giblets.Add(item);
         }
-        _audioSystem.PlayPredicted(gibSoundOverride, bodyTransform.Coordinates, null);
-        return gibs;
     }
 }
index b0aca4f10d90c02c40b8e6cd9b8337661ea303b4..26313765b06a6d9b28d2e299cd420d7d1d0d9325 100644 (file)
@@ -1,9 +1,9 @@
 using Content.Shared.Actions;
-using Content.Shared.Body.Events;
 using Content.Shared.Body.Systems;
 using Content.Shared.Chemistry.Components;
 using Content.Shared.Devour.Components;
 using Content.Shared.DoAfter;
+using Content.Shared.Gibbing;
 using Content.Shared.Mobs;
 using Content.Shared.Mobs.Components;
 using Content.Shared.Popups;
@@ -33,7 +33,7 @@ public sealed class DevourSystem : EntitySystem
         SubscribeLocalEvent<DevourerComponent, ComponentShutdown>(OnShutdown);
         SubscribeLocalEvent<DevourerComponent, DevourActionEvent>(OnDevourAction);
         SubscribeLocalEvent<DevourerComponent, DevourDoAfterEvent>(OnDoAfter);
-        SubscribeLocalEvent<DevourerComponent, BeingGibbedEvent>(OnGibContents);
+        SubscribeLocalEvent<DevourerComponent, GibbedBeforeDeletionEvent>(OnGibContents);
     }
 
     private void OnStartup(Entity<DevourerComponent> ent, ref ComponentStartup args)
@@ -127,13 +127,11 @@ public sealed class DevourSystem : EntitySystem
         _audioSystem.PlayPredicted(ent.Comp.SoundDevour, ent.Owner, ent.Owner);
     }
 
-    private void OnGibContents(Entity<DevourerComponent> ent, ref BeingGibbedEvent args)
+    private void OnGibContents(Entity<DevourerComponent> ent, ref GibbedBeforeDeletionEvent args)
     {
         if (ent.Comp.StomachStorageWhitelist == null)
             return;
 
-        // For some reason we have two different systems that should handle gibbing,
-        // and for some another reason GibbingSystem, which should empty all containers, doesn't get involved in this process
         _containerSystem.EmptyContainer(ent.Comp.Stomach);
     }
 }
diff --git a/Content.Shared/Gibbing/Components/GibbableComponent.cs b/Content.Shared/Gibbing/Components/GibbableComponent.cs
deleted file mode 100644 (file)
index 9c7501f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-using Content.Shared.Gibbing.Systems;
-using Robust.Shared.Audio;
-using Robust.Shared.GameStates;
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Gibbing.Components;
-
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(GibbingSystem))]
-public sealed partial class GibbableComponent : Component
-{
-    /// <summary>
-    /// Giblet entity prototypes to randomly select from when spawning additional giblets
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public List<EntProtoId> GibPrototypes = new();
-
-    /// <summary>
-    /// Number of giblet entities to spawn in addition to entity contents
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public int GibCount;
-
-    /// <summary>
-    /// Sound to be played when this entity is gibbed, only played when playsound is true on the gibbing function
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public SoundSpecifier? GibSound = new SoundCollectionSpecifier("gib", AudioParams.Default.WithVariation(0.025f));
-
-    /// <summary>
-    /// Max distance giblets can be dropped from an entity when NOT using physics-based scattering
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public float GibScatterRange = 0.3f;
-}
diff --git a/Content.Shared/Gibbing/Events/GibbingEvents.cs b/Content.Shared/Gibbing/Events/GibbingEvents.cs
deleted file mode 100644 (file)
index 949b10e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Gibbing.Events;
-
-
-
-/// <summary>
-/// Called just before we actually gib the target entity
-/// </summary>
-/// <param name="Target">The entity being gibed</param>
-/// <param name="GibType">What type of gibbing is occuring</param>
-/// <param name="AllowedContainers">Containers we are allow to gib</param>
-/// <param name="ExcludedContainers">Containers we are allow not allowed to gib</param>
-[ByRefEvent] public record struct AttemptEntityContentsGibEvent(
-    EntityUid Target,
-    GibContentsOption GibType,
-    List<string>? AllowedContainers,
-    List<string>? ExcludedContainers
-    );
-
-
-/// <summary>
-/// Called just before we actually gib the target entity
-/// </summary>
-/// <param name="Target">The entity being gibed</param>
-/// <param name="GibletCount">how many giblets to spawn</param>
-/// <param name="GibType">What type of gibbing is occuring</param>
-[ByRefEvent] public record struct AttemptEntityGibEvent(EntityUid Target, int GibletCount, GibType GibType);
-
-/// <summary>
-/// Called immediately after we gib the target entity
-/// </summary>
-/// <param name="Target">The entity being gibbed</param>
-/// <param name="DroppedEntities">Any entities that are spilled out (if any)</param>
-[ByRefEvent] public record struct EntityGibbedEvent(EntityUid Target, List<EntityUid> DroppedEntities);
-
-[Serializable, NetSerializable]
-public enum GibType : byte
-{
-    Skip,
-    Drop,
-    Gib,
-}
-
-public enum GibContentsOption : byte
-{
-    Skip,
-    Drop,
-    Gib
-}
diff --git a/Content.Shared/Gibbing/GibbingSystem.cs b/Content.Shared/Gibbing/GibbingSystem.cs
new file mode 100644 (file)
index 0000000..08c8fc2
--- /dev/null
@@ -0,0 +1,84 @@
+using Content.Shared.Destructible;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Audio;
+using Robust.Shared.Network;
+using Robust.Shared.Physics.Systems;
+using Robust.Shared.Random;
+
+namespace Content.Shared.Gibbing;
+
+public sealed class GibbingSystem : EntitySystem
+{
+    [Dependency] private readonly INetManager _net = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly SharedDestructibleSystem _destructible = default!;
+    [Dependency] private readonly SharedPhysicsSystem _physics = default!;
+    [Dependency] private readonly SharedTransformSystem _transform = default!;
+
+    private static readonly SoundSpecifier? GibSound = new SoundCollectionSpecifier("gib", AudioParams.Default.WithVariation(0.025f));
+
+    /// <summary>
+    /// Gibs an entity.
+    /// </summary>
+    /// <param name="ent">The entity to gib.</param>
+    /// <param name="dropGiblets">Whether or not to drop giblets.</param>
+    /// <param name="user">The user gibbing the entity, if any.</param>
+    /// <returns>The set of giblets for this entity, if any.</returns>
+    public HashSet<EntityUid> Gib(EntityUid ent, bool dropGiblets = true, EntityUid? user = null)
+    {
+        // user is unused because of prediction woes, eventually it'll be used for audio
+
+        // BodySystem handles prediction rather poorly and causes client-sided bugs when we gib on the client
+        // This guard can be removed once it is gone and replaced by a prediction-safe system.
+        if (!_net.IsServer)
+            return new();
+
+        if (!_destructible.DestroyEntity(ent))
+            return new();
+
+        _audio.PlayPvs(GibSound, ent);
+
+        var gibbed = new HashSet<EntityUid>();
+        var beingGibbed = new BeingGibbedEvent(gibbed);
+        RaiseLocalEvent(ent, ref beingGibbed);
+
+        if (dropGiblets)
+        {
+            foreach (var giblet in gibbed)
+            {
+                _transform.DropNextTo(giblet, ent);
+                FlingDroppedEntity(giblet);
+            }
+        }
+
+        var beforeDeletion = new GibbedBeforeDeletionEvent(gibbed);
+        RaiseLocalEvent(ent, ref beforeDeletion);
+
+        return gibbed;
+    }
+
+    private const float GibletLaunchImpulse = 8;
+    private const float GibletLaunchImpulseVariance = 3;
+
+    private void FlingDroppedEntity(EntityUid target)
+    {
+        var impulse = GibletLaunchImpulse + _random.NextFloat(GibletLaunchImpulseVariance);
+        var scatterVec = _random.NextAngle().ToVec() * impulse;
+        _physics.ApplyLinearImpulse(target, scatterVec);
+    }
+}
+
+/// <summary>
+/// Raised on an entity when it is being gibbed.
+/// </summary>
+/// <param name="Giblets">If a component wants to provide giblets to scatter, add them to this hashset.</param>
+[ByRefEvent]
+public readonly record struct BeingGibbedEvent(HashSet<EntityUid> Giblets);
+
+/// <summary>
+/// Raised on an entity when it is about to be deleted after being gibbed.
+/// </summary>
+/// <param name="Giblets">The set of giblets this entity produced.</param>
+[ByRefEvent]
+public readonly record struct GibbedBeforeDeletionEvent(HashSet<EntityUid> Giblets);
diff --git a/Content.Shared/Gibbing/Systems/GibbingSystem.cs b/Content.Shared/Gibbing/Systems/GibbingSystem.cs
deleted file mode 100644 (file)
index 9eaadbb..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Numerics;
-using Content.Shared.Gibbing.Components;
-using Content.Shared.Gibbing.Events;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Containers;
-using Robust.Shared.Map;
-using Robust.Shared.Physics.Systems;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Random;
-
-namespace Content.Shared.Gibbing.Systems;
-
-public sealed class GibbingSystem : EntitySystem
-{
-    [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
-    [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
-    [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
-    [Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
-    [Dependency] private readonly IRobustRandom _random = default!;
-
-    //TODO: (future optimization) implement a system that "caps" giblet entities by deleting the oldest ones once we reach a certain limit, customizable via CVAR
-
-    /// <summary>
-    /// Attempt to gib a specified entity. That entity must have a gibable components. This method is NOT recursive will only
-    /// work on the target and any entities it contains (depending on gibContentsOption)
-    /// </summary>
-    /// <param name="outerEntity">The outermost entity we care about, used to place the dropped items</param>
-    /// <param name="gibbable">Target entity/comp we wish to gib</param>
-    /// <param name="gibType">What type of gibing are we performing</param>
-    /// <param name="gibContentsOption">What type of gibing do we perform on any container contents?</param>
-    /// <param name="droppedEntities">a hashset containing all the entities that have been dropped/created</param>
-    /// <param name="randomSpreadMod">How much to multiply the random spread on dropped giblets(if we are dropping them!)</param>
-    /// <param name="playAudio">Should we play audio</param>
-    /// <param name="allowedContainers">A list of containerIds on the target that permit gibing</param>
-    /// <param name="excludedContainers">A list of containerIds on the target that DO NOT permit gibing</param>
-    /// <param name="launchCone">The cone we are launching giblets in (if we are launching them!)</param>
-    /// <param name="launchGibs">Should we launch giblets or just drop them</param>
-    /// <param name="launchDirection">The direction to launch giblets (if we are launching them!)</param>
-    /// <param name="launchImpulse">The impluse to launch giblets at(if we are launching them!)</param>
-    /// /// <param name="logMissingGibable">Should we log if we are missing a gibbableComp when we call this function</param>
-    /// <param name="launchImpulseVariance">The variation in giblet launch impulse (if we are launching them!)</param>
-    /// <returns>True if successful, false if not</returns>
-    public bool TryGibEntity(Entity<TransformComponent?> outerEntity, Entity<GibbableComponent?> gibbable, GibType gibType,
-        GibContentsOption gibContentsOption,
-        out HashSet<EntityUid> droppedEntities, bool launchGibs = true,
-        Vector2 launchDirection = default, float launchImpulse = 0f, float launchImpulseVariance = 0f,
-        Angle launchCone = default,
-        float randomSpreadMod = 1.0f, bool playAudio = true, List<string>? allowedContainers = null,
-        List<string>? excludedContainers = null, bool logMissingGibable = false)
-    {
-        droppedEntities = new();
-        return TryGibEntityWithRef(outerEntity, gibbable, gibType, gibContentsOption, ref droppedEntities,
-            launchGibs, launchDirection, launchImpulse, launchImpulseVariance, launchCone, randomSpreadMod, playAudio,
-            allowedContainers, excludedContainers, logMissingGibable);
-    }
-
-
-    /// <summary>
-    /// Attempt to gib a specified entity. That entity must have a gibable components. This method is NOT recursive will only
-    /// work on the target and any entities it contains (depending on gibContentsOption)
-    /// </summary>
-    /// <param name="outerEntity">The outermost entity we care about, used to place the dropped items</param>
-    /// <param name="gibbable">Target entity/comp we wish to gib</param>
-    /// <param name="gibType">What type of gibing are we performing</param>
-    /// <param name="gibContentsOption">What type of gibing do we perform on any container contents?</param>
-    /// <param name="droppedEntities">a hashset containing all the entities that have been dropped/created</param>
-    /// <param name="randomSpreadMod">How much to multiply the random spread on dropped giblets(if we are dropping them!)</param>
-    /// <param name="playAudio">Should we play audio</param>
-    /// <param name="allowedContainers">A list of containerIds on the target that permit gibing</param>
-    /// <param name="excludedContainers">A list of containerIds on the target that DO NOT permit gibing</param>
-    /// <param name="launchCone">The cone we are launching giblets in (if we are launching them!)</param>
-    /// <param name="launchGibs">Should we launch giblets or just drop them</param>
-    /// <param name="launchDirection">The direction to launch giblets (if we are launching them!)</param>
-    /// <param name="launchImpulse">The impluse to launch giblets at(if we are launching them!)</param>
-    /// <param name="launchImpulseVariance">The variation in giblet launch impulse (if we are launching them!)</param>
-    /// <param name="logMissingGibable">Should we log if we are missing a gibbableComp when we call this function</param>
-    /// <returns>True if successful, false if not</returns>
-    public bool TryGibEntityWithRef(
-        Entity<TransformComponent?> outerEntity,
-        Entity<GibbableComponent?> gibbable,
-        GibType gibType,
-        GibContentsOption gibContentsOption,
-        ref HashSet<EntityUid> droppedEntities,
-        bool launchGibs = true,
-        Vector2? launchDirection = null,
-        float launchImpulse = 0f,
-        float launchImpulseVariance = 0f,
-        Angle launchCone = default,
-        float randomSpreadMod = 1.0f,
-        bool playAudio = true,
-        List<string>? allowedContainers = null,
-        List<string>? excludedContainers = null,
-        bool logMissingGibable = false)
-    {
-        if (!Resolve(gibbable, ref gibbable.Comp, logMissing: false))
-        {
-            DropEntity(gibbable, (outerEntity, Transform(outerEntity)), randomSpreadMod, ref droppedEntities,
-                launchGibs, launchDirection, launchImpulse, launchImpulseVariance, launchCone);
-            if (logMissingGibable)
-            {
-                Log.Warning($"{ToPrettyString(gibbable)} does not have a GibbableComponent! " +
-                            $"This is not required but may cause issues contained items to not be dropped.");
-            }
-
-            return false;
-        }
-
-        if (gibType == GibType.Skip && gibContentsOption == GibContentsOption.Skip)
-            return true;
-        if (launchGibs)
-        {
-            randomSpreadMod = 0;
-        }
-
-        HashSet<BaseContainer> validContainers = new();
-        var gibContentsAttempt =
-            new AttemptEntityContentsGibEvent(gibbable, gibContentsOption, allowedContainers, excludedContainers);
-        RaiseLocalEvent(gibbable, ref gibContentsAttempt);
-
-        foreach (var container in _containerSystem.GetAllContainers(gibbable))
-        {
-            var valid = true;
-            if (allowedContainers != null)
-                valid = allowedContainers.Contains(container.ID);
-            if (excludedContainers != null)
-                valid = valid && !excludedContainers.Contains(container.ID);
-            if (valid)
-                validContainers.Add(container);
-        }
-
-        switch (gibContentsOption)
-        {
-            case GibContentsOption.Skip:
-                break;
-            case GibContentsOption.Drop:
-            {
-                foreach (var container in validContainers)
-                {
-                    foreach (var ent in container.ContainedEntities)
-                    {
-                        DropEntity(new Entity<GibbableComponent?>(ent, null), outerEntity, randomSpreadMod,
-                            ref droppedEntities, launchGibs,
-                            launchDirection, launchImpulse, launchImpulseVariance, launchCone);
-                    }
-                }
-
-                break;
-            }
-            case GibContentsOption.Gib:
-            {
-                foreach (var container in validContainers)
-                {
-                    foreach (var ent in container.ContainedEntities)
-                    {
-                        GibEntity(new Entity<GibbableComponent?>(ent, null), outerEntity, randomSpreadMod,
-                            ref droppedEntities, launchGibs,
-                            launchDirection, launchImpulse, launchImpulseVariance, launchCone);
-                    }
-                }
-
-                break;
-            }
-        }
-
-        switch (gibType)
-        {
-            case GibType.Skip:
-                break;
-            case GibType.Drop:
-            {
-                DropEntity(gibbable, outerEntity, randomSpreadMod, ref droppedEntities, launchGibs,
-                    launchDirection, launchImpulse, launchImpulseVariance, launchCone);
-                break;
-            }
-            case GibType.Gib:
-            {
-                GibEntity(gibbable, outerEntity, randomSpreadMod, ref droppedEntities, launchGibs,
-                    launchDirection, launchImpulse, launchImpulseVariance, launchCone);
-                break;
-            }
-        }
-
-        if (playAudio)
-        {
-            _audioSystem.PlayPredicted(gibbable.Comp.GibSound, outerEntity, null);
-        }
-
-        if (gibType == GibType.Gib)
-            PredictedQueueDel(gibbable.Owner);
-        return true;
-    }
-
-    private void DropEntity(Entity<GibbableComponent?> gibbable, Entity<TransformComponent?> parent, float randomSpreadMod,
-        ref HashSet<EntityUid> droppedEntities, bool flingEntity, Vector2? scatterDirection, float scatterImpulse,
-        float scatterImpulseVariance, Angle scatterCone)
-    {
-        var gibCount = 0;
-        if (Resolve(gibbable, ref gibbable.Comp, logMissing: false))
-        {
-            gibCount = gibbable.Comp.GibCount;
-        }
-
-        if (!Resolve(parent, ref parent.Comp, logMissing: false))
-            return;
-
-        var gibAttemptEvent = new AttemptEntityGibEvent(gibbable, gibCount, GibType.Drop);
-        RaiseLocalEvent(gibbable, ref gibAttemptEvent);
-        switch (gibAttemptEvent.GibType)
-        {
-            case GibType.Skip:
-                return;
-            case GibType.Gib:
-                GibEntity(gibbable, parent, randomSpreadMod, ref droppedEntities, flingEntity, scatterDirection,
-                    scatterImpulse, scatterImpulseVariance, scatterCone, deleteTarget: false);
-                return;
-        }
-
-        _transformSystem.DropNextTo(gibbable.Owner, parent);
-        _transformSystem.SetWorldRotation(gibbable, _random.NextAngle());
-        droppedEntities.Add(gibbable);
-        if (flingEntity)
-        {
-            FlingDroppedEntity(gibbable, scatterDirection, scatterImpulse, scatterImpulseVariance, scatterCone);
-        }
-
-        var gibbedEvent = new EntityGibbedEvent(gibbable, new List<EntityUid> {gibbable});
-        RaiseLocalEvent(gibbable, ref gibbedEvent);
-    }
-
-    private List<EntityUid> GibEntity(Entity<GibbableComponent?> gibbable, Entity<TransformComponent?> parent,
-        float randomSpreadMod,
-        ref HashSet<EntityUid> droppedEntities, bool flingEntity, Vector2? scatterDirection, float scatterImpulse,
-        float scatterImpulseVariance, Angle scatterCone, bool deleteTarget = true)
-    {
-        var localGibs = new List<EntityUid>();
-        var gibCount = 0;
-        var gibProtoCount = 0;
-        if (Resolve(gibbable, ref gibbable.Comp, logMissing: false))
-        {
-            gibCount = gibbable.Comp.GibCount;
-            gibProtoCount = gibbable.Comp.GibPrototypes.Count;
-        }
-
-        if (!Resolve(parent, ref parent.Comp, logMissing: false))
-            return [];
-
-        var gibAttemptEvent = new AttemptEntityGibEvent(gibbable, gibCount, GibType.Drop);
-        RaiseLocalEvent(gibbable, ref gibAttemptEvent);
-        switch (gibAttemptEvent.GibType)
-        {
-            case GibType.Skip:
-                return localGibs;
-            case GibType.Drop:
-                DropEntity(gibbable, parent, randomSpreadMod, ref droppedEntities, flingEntity,
-                    scatterDirection, scatterImpulse, scatterImpulseVariance, scatterCone);
-                localGibs.Add(gibbable);
-                return localGibs;
-        }
-
-        if (gibbable.Comp != null && gibProtoCount > 0)
-        {
-            if (flingEntity)
-            {
-                for (var i = 0; i < gibAttemptEvent.GibletCount; i++)
-                {
-                    if (!TryCreateRandomGiblet(gibbable.Comp, parent.Comp.Coordinates, false, out var giblet,
-                            randomSpreadMod))
-                        continue;
-                    FlingDroppedEntity(giblet.Value, scatterDirection, scatterImpulse, scatterImpulseVariance,
-                        scatterCone);
-                    droppedEntities.Add(giblet.Value);
-                }
-            }
-            else
-            {
-                for (var i = 0; i < gibAttemptEvent.GibletCount; i++)
-                {
-                    if (TryCreateRandomGiblet(gibbable.Comp, parent.Comp.Coordinates, false, out var giblet,
-                            randomSpreadMod))
-                        droppedEntities.Add(giblet.Value);
-                }
-            }
-        }
-
-        _transformSystem.AttachToGridOrMap(gibbable, Transform(gibbable));
-        if (flingEntity)
-        {
-            FlingDroppedEntity(gibbable, scatterDirection, scatterImpulse, scatterImpulseVariance, scatterCone);
-        }
-
-        var gibbedEvent = new EntityGibbedEvent(gibbable, localGibs);
-        RaiseLocalEvent(gibbable, ref gibbedEvent);
-        if (deleteTarget)
-            PredictedQueueDel(gibbable.Owner);
-        return localGibs;
-    }
-
-
-    public bool TryCreateRandomGiblet(Entity<GibbableComponent?> gibbable, [NotNullWhen(true)] out EntityUid? gibletEntity,
-        float randomSpreadModifier = 1.0f, bool playSound = true)
-    {
-        gibletEntity = null;
-        return Resolve(gibbable, ref gibbable.Comp) && TryCreateRandomGiblet(gibbable.Comp, Transform(gibbable).Coordinates,
-            playSound, out gibletEntity, randomSpreadModifier);
-    }
-
-    public bool TryCreateAndFlingRandomGiblet(Entity<GibbableComponent?> gibbable, [NotNullWhen(true)] out EntityUid? gibletEntity,
-        Vector2 scatterDirection, float force, float scatterImpulseVariance, Angle scatterCone = default,
-        bool playSound = true)
-    {
-        gibletEntity = null;
-        if (!Resolve(gibbable, ref gibbable.Comp) ||
-            !TryCreateRandomGiblet(gibbable.Comp, Transform(gibbable).Coordinates, playSound, out gibletEntity))
-            return false;
-        FlingDroppedEntity(gibletEntity.Value, scatterDirection, force, scatterImpulseVariance, scatterCone);
-        return true;
-    }
-
-    private void FlingDroppedEntity(EntityUid target, Vector2? direction, float impulse, float impulseVariance,
-        Angle scatterConeAngle)
-    {
-        var scatterAngle = direction?.ToAngle() ?? _random.NextAngle();
-        var scatterVector = _random.NextAngle(scatterAngle - scatterConeAngle / 2, scatterAngle + scatterConeAngle / 2)
-            .ToVec() * (impulse + _random.NextFloat(impulseVariance));
-        _physicsSystem.ApplyLinearImpulse(target, scatterVector);
-    }
-
-    private bool TryCreateRandomGiblet(GibbableComponent gibbable, EntityCoordinates coords,
-        bool playSound, [NotNullWhen(true)] out EntityUid? gibletEntity, float? randomSpreadModifier = null)
-    {
-        gibletEntity = null;
-        if (gibbable.GibPrototypes.Count == 0)
-            return false;
-        gibletEntity = Spawn(gibbable.GibPrototypes[_random.Next(0, gibbable.GibPrototypes.Count)],
-            randomSpreadModifier == null
-                ? coords
-                : coords.Offset(_random.NextVector2(gibbable.GibScatterRange * randomSpreadModifier.Value)));
-        if (playSound)
-            _audioSystem.PlayPredicted(gibbable.GibSound, coords, null);
-        _transformSystem.SetWorldRotation(gibletEntity.Value, _random.NextAngle());
-        return true;
-    }
-}
index 938aefc60117774d30809e5b47a8dffffc584fad..800cd2de711830d582a1f5011d9b3c8152694b7e 100644 (file)
@@ -1,11 +1,11 @@
 using Content.Shared.Administration.Logs;
-using Content.Shared.Body.Systems;
 using Content.Shared.Damage.Systems;
 using Content.Shared.Database;
 using Content.Shared.Destructible;
 using Content.Shared.DoAfter;
 using Content.Shared.DragDrop;
 using Content.Shared.Examine;
+using Content.Shared.Gibbing;
 using Content.Shared.Hands;
 using Content.Shared.Humanoid;
 using Content.Shared.IdentityManagement;
@@ -41,7 +41,7 @@ public sealed class SharedKitchenSpikeSystem : EntitySystem
     [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
     [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
     [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
-    [Dependency] private readonly SharedBodySystem _bodySystem = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
     [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
     [Dependency] private readonly SharedInteractionSystem _interaction = default!;
@@ -317,7 +317,7 @@ public sealed class SharedKitchenSpikeSystem : EntitySystem
         // Gib the victim if there is nothing else to butcher.
         if (butcherable.SpawnedEntities.Count == 0)
         {
-            _bodySystem.GibBody(args.Target.Value, true);
+            _gibbing.Gib(args.Target.Value);
 
             var logSeverity = HasComp<HumanoidAppearanceComponent>(args.Target) ? LogImpact.Extreme : LogImpact.High;
 
index 50ef5f413a080f539b2117abca5984fbb9af5c98..82cae19ec104bfe8af146be5cade3cb93b121ee4 100644 (file)
@@ -1,12 +1,11 @@
 using System.Numerics;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Systems;
 using Content.Shared.Charges.Components;
 using Content.Shared.Charges.Systems;
 using Content.Shared.Coordinates.Helpers;
 using Content.Shared.Doors.Components;
 using Content.Shared.Doors.Systems;
 using Content.Shared.Examine;
+using Content.Shared.Gibbing;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
 using Content.Shared.Interaction;
@@ -53,7 +52,7 @@ public abstract class SharedMagicSystem : EntitySystem
     [Dependency] private readonly SharedPhysicsSystem _physics = default!;
     [Dependency] private readonly SharedTransformSystem _transform = default!;
     [Dependency] private readonly INetManager _net = default!;
-    [Dependency] private readonly SharedBodySystem _body = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly EntityLookupSystem _lookup = default!;
     [Dependency] private readonly SharedDoorSystem _door = default!;
     [Dependency] private readonly InventorySystem _inventory = default!;
@@ -390,11 +389,7 @@ public abstract class SharedMagicSystem : EntitySystem
         var impulseVector = direction * 10000;
 
         _physics.ApplyLinearImpulse(ev.Target, impulseVector);
-
-        if (!TryComp<BodyComponent>(ev.Target, out var body))
-            return;
-
-        _body.GibBody(ev.Target, true, body);
+        _gibbing.Gib(ev.Target);
     }
 
     // End Touch Spells
index 9c28f5eb0437f15c7d9dfcb0a08b3e5e95e8ec10..42da1c6d5d0f02de4ad9ad41a95b9dfacef58574 100644 (file)
@@ -4,6 +4,7 @@ using Content.Shared.Administration.Logs;
 using Content.Shared.Body.Events;
 using Content.Shared.Containers.ItemSlots;
 using Content.Shared.Database;
+using Content.Shared.Gibbing;
 using Content.Shared.Hands.EntitySystems;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Interaction;
@@ -88,7 +89,7 @@ public abstract partial class SharedBorgSystem : EntitySystem
         SubscribeLocalEvent<BorgChassisComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeedModifiers);
         SubscribeLocalEvent<BorgChassisComponent, ActivatableUIOpenAttemptEvent>(OnUIOpenAttempt);
         SubscribeLocalEvent<BorgChassisComponent, MobStateChangedEvent>(OnMobStateChanged);
-        SubscribeLocalEvent<BorgChassisComponent, BeingGibbedEvent>(OnBeingGibbed);
+        SubscribeLocalEvent<BorgChassisComponent, GibbedBeforeDeletionEvent>(OnBeingGibbed);
         SubscribeLocalEvent<BorgChassisComponent, GetCharactedDeadIcEvent>(OnGetDeadIC);
         SubscribeLocalEvent<BorgChassisComponent, GetCharacterUnrevivableIcEvent>(OnGetUnrevivableIC);
         SubscribeLocalEvent<BorgChassisComponent, PowerCellSlotEmptyEvent>(OnPowerCellSlotEmpty);
@@ -293,7 +294,7 @@ public abstract partial class SharedBorgSystem : EntitySystem
             SetActive(chassis, false, user: args.Origin);
     }
 
-    private void OnBeingGibbed(Entity<BorgChassisComponent> chassis, ref BeingGibbedEvent args)
+    private void OnBeingGibbed(Entity<BorgChassisComponent> chassis, ref GibbedBeforeDeletionEvent args)
     {
         // Don't use the ItemSlotsSystem eject method since we don't want to play a sound and want we to eject the battery even if the slot is locked.
         if (TryComp<PowerCellSlotComponent>(chassis, out var slotComp) &&
index bd7cb6baffa45d6315b45f40bd567cea7f331747..26c14f869904a92945d49b7774948ede2047d9de 100644 (file)
@@ -1,6 +1,7 @@
 using Content.Shared.Species.Components;
 using Content.Shared.Actions;
 using Content.Shared.Body.Systems;
+using Content.Shared.Gibbing;
 using Content.Shared.Mobs;
 using Content.Shared.Mobs.Components;
 using Content.Shared.Popups;
@@ -12,7 +13,7 @@ namespace Content.Shared.Species;
 public sealed partial class GibActionSystem : EntitySystem
 {
     [Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
-    [Dependency] private readonly SharedBodySystem _bodySystem = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly IPrototypeManager _protoManager = default!;
     [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
 
@@ -26,7 +27,7 @@ public sealed partial class GibActionSystem : EntitySystem
 
     private void OnMobStateChanged(EntityUid uid, GibActionComponent comp, MobStateChangedEvent args)
     {
-        // When the mob changes state, check if they're dead and give them the action if so. 
+        // When the mob changes state, check if they're dead and give them the action if so.
         if (!TryComp<MobStateComponent>(uid, out var mobState))
             return;
 
@@ -47,15 +48,15 @@ public sealed partial class GibActionSystem : EntitySystem
         // If they aren't given the action, remove it.
         _actionsSystem.RemoveAction(uid, comp.ActionEntity);
     }
-    
+
     private void OnGibAction(EntityUid uid, GibActionComponent comp, GibActionEvent args)
     {
         // When they use the action, gib them.
         _popupSystem.PopupClient(Loc.GetString(comp.PopupText, ("name", uid)), uid, uid);
-        _bodySystem.GibBody(uid, true);
+        _gibbing.Gib(uid, user: args.Performer);
     }
-       
 
 
-    public sealed partial class GibActionEvent : InstantActionEvent { } 
+
+    public sealed partial class GibActionEvent : InstantActionEvent { }
 }
index 237c9257168ec0773bda96c61e3cc57b7aff25c6..83b4790af9bd2f1e330767e5a3ee2f6f1649231c 100644 (file)
@@ -1,4 +1,4 @@
-using Content.Shared.Body.Systems;
+using Content.Shared.Gibbing;
 using Content.Shared.Inventory;
 using Content.Shared.Trigger.Components.Effects;
 
@@ -6,7 +6,7 @@ namespace Content.Shared.Trigger.Systems;
 
 public sealed class GibOnTriggerSystem : XOnTriggerSystem<GibOnTriggerComponent>
 {
-    [Dependency] private readonly SharedBodySystem _body = default!;
+    [Dependency] private readonly GibbingSystem _gibbing = default!;
     [Dependency] private readonly InventorySystem _inventory = default!;
 
     protected override void OnTrigger(Entity<GibOnTriggerComponent> ent, EntityUid target, ref TriggerEvent args)
@@ -20,7 +20,7 @@ public sealed class GibOnTriggerSystem : XOnTriggerSystem<GibOnTriggerComponent>
             }
         }
 
-        _body.GibBody(target, true);
+        _gibbing.Gib(target, user: args.User);
         args.Handled = true;
     }
 }
index 152c4c4112cf09f6c87885c9b7ae4b893eb84b69..b31904437e0fd13ee57754e172b712f10bec9271 100644 (file)
@@ -1,5 +1,5 @@
 - type: entity
-  id: BaseAnimalOrganUnGibbable
+  id: BaseAnimalOrgan
   parent: BaseItem
   abstract: true
   components:
     tags:
       - Meat
 
-- type: entity
-  id: BaseAnimalOrgan
-  parent: BaseAnimalOrganUnGibbable
-  abstract: true
-  components:
-  - type: Gibbable
-
 - type: entity
   id: OrganAnimalLungs
   parent: BaseAnimalOrgan
index 4ac5faf67bc945fa7e32b2de4793eb19ec82d7b3..c12df45411821287d78b2d52f769e6771d007408 100644 (file)
@@ -1,5 +1,5 @@
 - type: entity
-  id: BaseHumanOrganUnGibbable
+  id: BaseHumanOrgan
   parent: BaseItem
   abstract: true
   components:
     tags:
       - Meat
 
-- type: entity
-  id: BaseHumanOrgan
-  parent: BaseHumanOrganUnGibbable
-  abstract: true
-  components:
-  - type: Gibbable
-
 - type: entity
   id: OrganHumanBrain
-  parent: BaseHumanOrganUnGibbable
+  parent: BaseHumanOrgan
   name: brain
   description: "The source of incredible, unending intelligence. Honk."
   components:
index c9ea293cb6442e13debcb1a9dc18604ca3b7637d..9672b0971154453fcf83ffb0b4d896ad14bbf297 100644 (file)
@@ -23,7 +23,6 @@
   - type: Tag
     tags:
       - Trash
-  - type: Gibbable
   - type: Extractable
     juiceSolution:
       reagents:
index 331641f00bd62829d04e94805ccd9dbfb0039b22..8e41ba927d9860760948dd898cf5197d9f63252f 100644 (file)
@@ -9,7 +9,6 @@
   - type: Damageable
     damageContainer: Biological
   - type: BodyPart
-  - type: Gibbable
   - type: ContainerContainer
     containers:
       bodypart: !type:Container