ECS and cleanup body system, merge body templates and presets into body prototypes (#11991)
Co-authored-by: Jezithyr <Jezithyr@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
@@ -19,35 +19,28 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EntityUid.TryParse(args[0], out var entityUid))
|
||||
if (!EntityUid.TryParse(args[0], out var childId))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EntityUid.TryParse(args[1], out var storageUid))
|
||||
if (!EntityUid.TryParse(args[1], out var parentId))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
|
||||
return;
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
|
||||
if (entityManager.TryGetComponent<BodyComponent>(storageUid, out var storage)
|
||||
&& entityManager.TryGetComponent<BodyPartComponent>(entityUid, out var bodyPart))
|
||||
if (bodySystem.TryCreatePartSlotAndAttach(parentId, args[3], childId))
|
||||
{
|
||||
if (storage.TryAddPart(args[3], bodyPart))
|
||||
{
|
||||
shell.WriteLine($@"Added {entityUid} to {storageUid}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shell.WriteError($@"Could not add {entityUid} to {storageUid}.");
|
||||
}
|
||||
shell.WriteLine($@"Added {childId} to {parentId}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shell.WriteError("Could not insert.");
|
||||
shell.WriteError($@"Could not add {childId} to {parentId}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Body.Components;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Administration.Commands
|
||||
@@ -20,35 +19,28 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EntityUid.TryParse(args[0], out var entityUid))
|
||||
if (!EntityUid.TryParse(args[0], out var organId))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EntityUid.TryParse(args[1], out var storageUid))
|
||||
if (!EntityUid.TryParse(args[1], out var partId))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
|
||||
return;
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
|
||||
if (entityManager.TryGetComponent<BodyPartComponent>(storageUid, out var storage)
|
||||
&& entityManager.TryGetComponent<MechanismComponent>(entityUid, out var bodyPart))
|
||||
if (bodySystem.AddOrganToFirstValidSlot(organId, partId))
|
||||
{
|
||||
if (storage.TryAddMechanism(bodyPart))
|
||||
{
|
||||
shell.WriteLine($@"Added {entityUid} to {storageUid}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shell.WriteError($@"Could not add {entityUid} to {storageUid}.");
|
||||
}
|
||||
shell.WriteLine($@"Added {organId} to {partId}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shell.WriteError("Could not insert.");
|
||||
shell.WriteError($@"Could not add {organId} to {partId}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
@@ -26,16 +26,11 @@ namespace Content.Server.Administration.Commands
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
|
||||
if (!entityManager.TryGetComponent<TransformComponent>(entityUid, out var transform)) return;
|
||||
|
||||
var parent = transform.ParentUid;
|
||||
|
||||
if (entityManager.TryGetComponent<BodyComponent>(parent, out var body) &&
|
||||
entityManager.TryGetComponent<BodyPartComponent>(entityUid, out var part))
|
||||
if (bodySystem.DropPart(entityUid))
|
||||
{
|
||||
body.RemovePart(part);
|
||||
|
||||
shell.WriteLine($"Removed body part {entityManager.ToPrettyString(entityUid)}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Body.Components;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Administration.Commands
|
||||
@@ -27,15 +26,11 @@ namespace Content.Server.Administration.Commands
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
|
||||
if (!entityManager.TryGetComponent<TransformComponent>(entityUid, out var transform)) return;
|
||||
|
||||
var parent = transform.ParentUid;
|
||||
|
||||
if (entityManager.TryGetComponent<BodyPartComponent>(parent, out var body) &&
|
||||
entityManager.TryGetComponent<MechanismComponent>(entityUid, out var part))
|
||||
if (bodySystem.DropOrgan(entityUid))
|
||||
{
|
||||
body.RemoveMechanism(part);
|
||||
shell.WriteLine($"Removed organ {entityManager.ToPrettyString(entityUid)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -103,10 +103,7 @@ public sealed partial class AdminVerbSystem
|
||||
4, 1, 2, maxTileBreak: 0), // it gibs, damage doesn't need to be high.
|
||||
CancellationToken.None);
|
||||
|
||||
if (TryComp(args.Target, out SharedBodyComponent? body))
|
||||
{
|
||||
body.Gib();
|
||||
}
|
||||
_bodySystem.GibBody(args.Target);
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
Message = Loc.GetString("admin-smite-explode-description")
|
||||
@@ -308,15 +305,15 @@ public sealed partial class AdminVerbSystem
|
||||
Act = () =>
|
||||
{
|
||||
_vomitSystem.Vomit(args.Target, -1000, -1000); // You feel hollow!
|
||||
var organs = _bodySystem.GetComponentsOnMechanisms<TransformComponent>(args.Target, body);
|
||||
var organs = _bodySystem.GetBodyOrganComponents<TransformComponent>(args.Target, body);
|
||||
var baseXform = Transform(args.Target);
|
||||
foreach (var (xform, mechanism) in organs)
|
||||
foreach (var (xform, organ) in organs)
|
||||
{
|
||||
if (HasComp<BrainComponent>(xform.Owner) || HasComp<EyeComponent>(xform.Owner))
|
||||
continue;
|
||||
|
||||
mechanism.Part?.RemoveMechanism(mechanism);
|
||||
xform.Coordinates = baseXform.Coordinates.Offset(_random.NextVector2(0.5f,0.75f));
|
||||
var coordinates = baseXform.Coordinates.Offset(_random.NextVector2(0.5f, 0.75f));
|
||||
_bodySystem.DropOrganAt(organ.Owner, coordinates, organ);
|
||||
}
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("admin-smite-vomit-organs-self"), args.Target,
|
||||
@@ -337,10 +334,9 @@ public sealed partial class AdminVerbSystem
|
||||
Act = () =>
|
||||
{
|
||||
var baseXform = Transform(args.Target);
|
||||
foreach (var part in body.GetPartsOfType(BodyPartType.Hand))
|
||||
foreach (var part in _bodySystem.GetBodyChildrenOfType(args.Target, BodyPartType.Hand))
|
||||
{
|
||||
body.RemovePart(part);
|
||||
Transform(part.Owner).Coordinates = baseXform.Coordinates;
|
||||
_bodySystem.DropPartAt(part.Id, baseXform.Coordinates, part.Component);
|
||||
}
|
||||
_popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target,
|
||||
Filter.Entities(args.Target), PopupType.LargeCaution);
|
||||
@@ -360,10 +356,9 @@ public sealed partial class AdminVerbSystem
|
||||
Act = () =>
|
||||
{
|
||||
var baseXform = Transform(args.Target);
|
||||
foreach (var part in body.GetPartsOfType(BodyPartType.Hand))
|
||||
foreach (var part in _bodySystem.GetBodyChildrenOfType(body.Owner, BodyPartType.Hand, body))
|
||||
{
|
||||
body.RemovePart(part);
|
||||
Transform(part.Owner).Coordinates = baseXform.Coordinates;
|
||||
_bodySystem.DropPartAt(part.Id, baseXform.Coordinates, part.Component);
|
||||
break;
|
||||
}
|
||||
_popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target,
|
||||
@@ -383,13 +378,9 @@ public sealed partial class AdminVerbSystem
|
||||
IconTexture = "/Textures/Mobs/Species/Human/organs.rsi/stomach.png",
|
||||
Act = () =>
|
||||
{
|
||||
foreach (var part in body.Parts)
|
||||
foreach (var (component, _) in _bodySystem.GetBodyOrganComponents<StomachComponent>(args.Target, body))
|
||||
{
|
||||
foreach (var mechanism in part.Key.Mechanisms)
|
||||
{
|
||||
if (HasComp<StomachComponent>(mechanism.Owner))
|
||||
QueueDel(mechanism.Owner);
|
||||
}
|
||||
QueueDel(component.Owner);
|
||||
}
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("admin-smite-stomach-removal-self"), args.Target,
|
||||
@@ -407,13 +398,9 @@ public sealed partial class AdminVerbSystem
|
||||
IconTexture = "/Textures/Mobs/Species/Human/organs.rsi/lung-r.png",
|
||||
Act = () =>
|
||||
{
|
||||
foreach (var part in body.Parts)
|
||||
foreach (var (component, _) in _bodySystem.GetBodyOrganComponents<LungComponent>(args.Target, body))
|
||||
{
|
||||
foreach (var mechanism in part.Key.Mechanisms)
|
||||
{
|
||||
if (HasComp<LungComponent>(mechanism.Owner))
|
||||
QueueDel(mechanism.Owner);
|
||||
}
|
||||
QueueDel(component.Owner);
|
||||
}
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("admin-smite-lung-removal-self"), args.Target,
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Bed.Components;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Bed;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Server.Bed.Sleep;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.MobState;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.MobState;
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
using Content.Shared.Bed;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Server.Construction;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Bed
|
||||
@@ -26,6 +26,7 @@ namespace Content.Server.Bed
|
||||
[Dependency] private readonly SleepingSystem _sleepingSystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -94,7 +95,7 @@ namespace Content.Server.Bed
|
||||
{
|
||||
// In testing this also received an unbuckle event when the bed is destroyed
|
||||
// So don't worry about that
|
||||
if (!HasComp<SharedBodyComponent>(args.BuckledEntity))
|
||||
if (!HasComp<BodyComponent>(args.BuckledEntity))
|
||||
return;
|
||||
|
||||
if (!this.IsPowered(uid, EntityManager))
|
||||
@@ -143,4 +144,3 @@ namespace Content.Server.Bed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
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.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -118,7 +121,7 @@ namespace Content.Server.Body.Commands
|
||||
}
|
||||
}
|
||||
|
||||
if (!entityManager.TryGetComponent(entity, out SharedBodyComponent? body))
|
||||
if (!entityManager.TryGetComponent(entity, out BodyComponent? body) || body.Root == null)
|
||||
{
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
||||
@@ -127,14 +130,25 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entityManager.TryGetComponent(hand, out SharedBodyPartComponent? part))
|
||||
if (!entityManager.TryGetComponent(hand, out BodyPartComponent? part))
|
||||
{
|
||||
shell.WriteLine($"Hand entity {hand} does not have a {nameof(SharedBodyPartComponent)} component.");
|
||||
shell.WriteLine($"Hand entity {hand} does not have a {nameof(BodyPartComponent)} component.");
|
||||
return;
|
||||
}
|
||||
|
||||
var slot = part.GetHashCode().ToString();
|
||||
body.SetPart(slot, part);
|
||||
var bodySystem = entityManager.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, attachAt.Component, part))
|
||||
{
|
||||
shell.WriteError($"Couldn't create a slot with id {slotId} on entity {entityManager.ToPrettyString(entity)}");
|
||||
return;
|
||||
}
|
||||
|
||||
shell.WriteLine($"Added hand to entity {entityManager.GetComponent<MetaDataComponent>(entity).EntityName}");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
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.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
@@ -18,7 +21,7 @@ namespace Content.Server.Body.Commands
|
||||
var player = shell.Player as IPlayerSession;
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
EntityUid entity;
|
||||
EntityUid bodyId;
|
||||
EntityUid partUid;
|
||||
|
||||
switch (args.Length)
|
||||
@@ -42,7 +45,7 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
entity = player.AttachedEntity.Value;
|
||||
bodyId = player.AttachedEntity.Value;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
@@ -64,16 +67,16 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
entity = entityUid;
|
||||
bodyId = entityUid;
|
||||
break;
|
||||
default:
|
||||
shell.WriteLine(Help);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entityManager.TryGetComponent(entity, out SharedBodyComponent? body))
|
||||
if (!entityManager.TryGetComponent(bodyId, out BodyComponent? body))
|
||||
{
|
||||
shell.WriteLine($"Entity {entityManager.GetComponent<MetaDataComponent>(entity).EntityName} with uid {entity} does not have a {nameof(SharedBodyComponent)} component.");
|
||||
shell.WriteLine($"Entity {entityManager.GetComponent<MetaDataComponent>(bodyId).EntityName} with uid {bodyId} does not have a {nameof(BodyComponent)}.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,19 +86,39 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entityManager.TryGetComponent(partUid, out SharedBodyPartComponent? part))
|
||||
if (!entityManager.TryGetComponent(partUid, out BodyPartComponent? part))
|
||||
{
|
||||
shell.WriteLine($"Entity {entityManager.GetComponent<MetaDataComponent>(partUid).EntityName} with uid {args[0]} does not have a {nameof(SharedBodyPartComponent)} component.");
|
||||
shell.WriteLine($"Entity {entityManager.GetComponent<MetaDataComponent>(partUid).EntityName} with uid {args[0]} does not have a {nameof(BodyPartComponent)}.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (body.HasPart(part))
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
if (bodySystem.BodyHasChild(bodyId, partUid, body, part))
|
||||
{
|
||||
shell.WriteLine($"Body part {entityManager.GetComponent<MetaDataComponent>(partUid).EntityName} with uid {partUid} is already attached to entity {entityManager.GetComponent<MetaDataComponent>(entity).EntityName} with uid {entity}");
|
||||
shell.WriteLine($"Body part {entityManager.GetComponent<MetaDataComponent>(partUid).EntityName} with uid {partUid} is already attached to entity {entityManager.GetComponent<MetaDataComponent>(bodyId).EntityName} with uid {bodyId}");
|
||||
return;
|
||||
}
|
||||
|
||||
body.SetPart($"AttachBodyPartVerb-{partUid}", part);
|
||||
var slotId = $"AttachBodyPartVerb-{partUid}";
|
||||
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
if (bodySystem.TryCreateBodyRootSlot(bodyId, slotId, out var rootSlot, body))
|
||||
{
|
||||
bodySystem.DropPart(partUid, part);
|
||||
bodySystem.AttachPart(partUid, rootSlot, part);
|
||||
}
|
||||
else
|
||||
{
|
||||
var attachAt = bodySystem.GetBodyChildren(bodyId, body).First();
|
||||
|
||||
if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, partUid, attachAt.Component, part))
|
||||
{
|
||||
shell.WriteError($"Could not create slot {slotId} on entity {entityManager.ToPrettyString(bodyId)}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
shell.WriteLine($"Attached part {entityManager.ToPrettyString(partUid)} to {entityManager.ToPrettyString(bodyId)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Body.Components;
|
||||
using Robust.Server.Player;
|
||||
@@ -35,7 +36,8 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(attached, out SharedBodyComponent? body))
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entityManager.TryGetComponent(attached, out BodyComponent? body))
|
||||
{
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
||||
@@ -45,13 +47,13 @@ namespace Content.Server.Body.Commands
|
||||
}
|
||||
|
||||
var mechanismName = string.Join(" ", args).ToLowerInvariant();
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
|
||||
foreach (var (part, _) in body.Parts)
|
||||
foreach (var mechanism in part.Mechanisms)
|
||||
foreach (var organ in bodySystem.GetBodyOrgans(body.Owner, body))
|
||||
{
|
||||
if (mechanism.Name.ToLowerInvariant() == mechanismName)
|
||||
if (organ.Component.Name.ToLowerInvariant() == mechanismName)
|
||||
{
|
||||
part.DeleteMechanism(mechanism);
|
||||
bodySystem.DeleteOrgan(organ.Id, organ.Component);
|
||||
shell.WriteLine($"Mechanism with name {mechanismName} has been destroyed.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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;
|
||||
@@ -31,7 +32,8 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(player.AttachedEntity, out SharedBodyComponent? body))
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entityManager.TryGetComponent(player.AttachedEntity, out BodyComponent? body))
|
||||
{
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
var text = $"You have no body{(random.Prob(0.2f) ? " and you must scream." : ".")}";
|
||||
@@ -40,15 +42,16 @@ namespace Content.Server.Body.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var hand = body.GetPartsOfType(BodyPartType.Hand).FirstOrDefault();
|
||||
var bodySystem = entityManager.System<BodySystem>();
|
||||
var hand = bodySystem.GetBodyChildrenOfType(player.AttachedEntity, BodyPartType.Hand, body).FirstOrDefault();
|
||||
|
||||
if (hand == null)
|
||||
if (hand == default)
|
||||
{
|
||||
shell.WriteLine("You have no hands.");
|
||||
}
|
||||
else
|
||||
{
|
||||
body.RemovePart(hand);
|
||||
bodySystem.DropPart(hand.Id, hand.Component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
Content.Server/Body/Components/BeingGibbedEvent.cs
Normal file
11
Content.Server/Body/Components/BeingGibbedEvent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Content.Server.Body.Components;
|
||||
|
||||
public sealed class BeingGibbedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly HashSet<EntityUid> GibbedParts;
|
||||
|
||||
public BeingGibbedEvent(HashSet<EntityUid> gibbedParts)
|
||||
{
|
||||
GibbedParts = gibbedParts;
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Body.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedBodyComponent))]
|
||||
public sealed class BodyComponent : SharedBodyComponent
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
private Container _partContainer = default!;
|
||||
|
||||
[DataField("gibSound")] private SoundSpecifier _gibSound = new SoundCollectionSpecifier("gib");
|
||||
|
||||
protected override bool CanAddPart(string slotId, SharedBodyPartComponent part)
|
||||
{
|
||||
return base.CanAddPart(slotId, part) &&
|
||||
_partContainer.CanInsert(part.Owner);
|
||||
}
|
||||
|
||||
protected override void OnAddPart(BodyPartSlot slot, SharedBodyPartComponent part)
|
||||
{
|
||||
base.OnAddPart(slot, part);
|
||||
|
||||
_partContainer.Insert(part.Owner);
|
||||
|
||||
if (_entMan.TryGetComponent<HumanoidComponent>(Owner, out var humanoid))
|
||||
{
|
||||
var layer = part.ToHumanoidLayers();
|
||||
if (layer != null)
|
||||
{
|
||||
var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
|
||||
_entMan.System<HumanoidSystem>().SetLayersVisibility(Owner, layers, true, true, humanoid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRemovePart(BodyPartSlot slot, SharedBodyPartComponent part)
|
||||
{
|
||||
base.OnRemovePart(slot, part);
|
||||
|
||||
_partContainer.ForceRemove(part.Owner);
|
||||
part.Owner.RandomOffset(0.25f);
|
||||
|
||||
if (_entMan.TryGetComponent<HumanoidComponent>(Owner, out var humanoid))
|
||||
{
|
||||
var layer = part.ToHumanoidLayers();
|
||||
if (layer != null)
|
||||
{
|
||||
var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
|
||||
_entMan.System<HumanoidSystem>().SetLayersVisibility(Owner, layers, false, true, humanoid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_partContainer = Owner.EnsureContainer<Container>($"{Name}-{nameof(BodyComponent)}");
|
||||
var preset = Preset;
|
||||
|
||||
if (preset != null)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
// Using MapPosition instead of Coordinates here prevents
|
||||
// a crash within the character preview menu in the lobby
|
||||
var entity = _entMan.SpawnEntity(preset.PartIDs[slot.Id], _entMan.GetComponent<TransformComponent>(Owner).MapPosition);
|
||||
|
||||
if (!_entMan.TryGetComponent(entity, out SharedBodyPartComponent? part))
|
||||
{
|
||||
Logger.Error($"Entity {slot.Id} does not have a {nameof(SharedBodyPartComponent)} component.");
|
||||
continue;
|
||||
}
|
||||
|
||||
SetPart(slot.Id, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
// This is ran in Startup as entities spawned in Initialize
|
||||
// are not synced to the client since they are assumed to be
|
||||
// identical on it
|
||||
foreach (var (part, _) in Parts)
|
||||
{
|
||||
part.Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override HashSet<EntityUid> Gib(bool gibParts = false)
|
||||
{
|
||||
var gibs = base.Gib(gibParts);
|
||||
|
||||
var xform = _entMan.GetComponent<TransformComponent>(Owner);
|
||||
var coordinates = xform.Coordinates;
|
||||
|
||||
// These have already been forcefully removed from containers so run it here.
|
||||
foreach (var part in gibs)
|
||||
{
|
||||
_entMan.EventBus.RaiseLocalEvent(part, new PartGibbedEvent(Owner, gibs), true);
|
||||
}
|
||||
|
||||
SoundSystem.Play(_gibSound.GetSound(), Filter.Pvs(Owner, entityManager: _entMan), coordinates, AudioHelpers.WithVariation(0.025f));
|
||||
|
||||
if (_entMan.TryGetComponent(Owner, out ContainerManagerComponent? container))
|
||||
{
|
||||
foreach (var cont in container.GetAllContainers())
|
||||
{
|
||||
foreach (var ent in cont.ContainedEntities)
|
||||
{
|
||||
cont.ForceRemove(ent);
|
||||
_entMan.GetComponent<TransformComponent>(ent).Coordinates = coordinates;
|
||||
ent.RandomOffset(0.25f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_entMan.EventBus.RaiseLocalEvent(Owner, new BeingGibbedEvent(gibs), false);
|
||||
_entMan.QueueDeleteEntity(Owner);
|
||||
|
||||
return gibs;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BeingGibbedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly HashSet<EntityUid> GibbedParts;
|
||||
|
||||
public BeingGibbedEvent(HashSet<EntityUid> gibbedParts)
|
||||
{
|
||||
GibbedParts = gibbedParts;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event raised on all the parts of an entity when it's gibbed
|
||||
/// </summary>
|
||||
public sealed class PartGibbedEvent : EntityEventArgs
|
||||
{
|
||||
public EntityUid EntityToGib;
|
||||
public readonly HashSet<EntityUid> GibbedParts;
|
||||
|
||||
public PartGibbedEvent(EntityUid entityToGib, HashSet<EntityUid> gibbedParts)
|
||||
{
|
||||
EntityToGib = entityToGib;
|
||||
GibbedParts = gibbedParts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server.Body.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedBodyPartComponent))]
|
||||
public sealed class BodyPartComponent : SharedBodyPartComponent
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
private Container _mechanismContainer = default!;
|
||||
|
||||
public override bool CanAddMechanism(MechanismComponent mechanism)
|
||||
{
|
||||
return base.CanAddMechanism(mechanism) &&
|
||||
_mechanismContainer.CanInsert(mechanism.Owner);
|
||||
}
|
||||
|
||||
protected override void OnAddMechanism(MechanismComponent mechanism)
|
||||
{
|
||||
base.OnAddMechanism(mechanism);
|
||||
|
||||
_mechanismContainer.Insert(mechanism.Owner);
|
||||
}
|
||||
|
||||
protected override void OnRemoveMechanism(MechanismComponent mechanism)
|
||||
{
|
||||
base.OnRemoveMechanism(mechanism);
|
||||
|
||||
_mechanismContainer.Remove(mechanism.Owner);
|
||||
mechanism.Owner.RandomOffset(0.25f);
|
||||
}
|
||||
|
||||
public void MapInitialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_mechanismContainer = Owner.EnsureContainer<Container>(ContainerId);
|
||||
|
||||
// This is ran in Startup as entities spawned in Initialize
|
||||
// are not synced to the client since they are assumed to be
|
||||
// identical on it
|
||||
foreach (var mechanismId in MechanismIds)
|
||||
{
|
||||
var entity = _entMan.SpawnEntity(mechanismId, _entMan.GetComponent<TransformComponent>(Owner).MapPosition);
|
||||
|
||||
if (!_entMan.TryGetComponent(entity, out MechanismComponent? mechanism))
|
||||
{
|
||||
Logger.Error($"Entity {mechanismId} does not have a {nameof(MechanismComponent)} component.");
|
||||
continue;
|
||||
}
|
||||
|
||||
TryAddMechanism(mechanism, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace Content.Server.Body.Components
|
||||
/// <summary>
|
||||
/// Copy BodyTemplate and BodyPart data into a common data class that the client can read.
|
||||
/// </summary>
|
||||
private BodyScannerUIState InterfaceState(SharedBodyComponent body)
|
||||
private BodyScannerUIState InterfaceState(BodyComponent body)
|
||||
{
|
||||
return new(body.Owner);
|
||||
}
|
||||
|
||||
@@ -1,119 +1,148 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Body.Systems
|
||||
namespace Content.Server.Body.Systems;
|
||||
|
||||
public sealed class BodySystem : SharedBodySystem
|
||||
{
|
||||
public sealed class BodySystem : EntitySystem
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
[Dependency] private readonly HumanoidSystem _humanoidSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
base.Initialize();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<BodyComponent, MoveInputEvent>(OnRelayMoveInput);
|
||||
SubscribeLocalEvent<BodyComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||
SubscribeLocalEvent<BodyComponent, BeingMicrowavedEvent>(OnBeingMicrowaved);
|
||||
SubscribeLocalEvent<BodyPartComponent, MapInitEvent>((_, c, _) => c.MapInitialize());
|
||||
}
|
||||
SubscribeLocalEvent<BodyComponent, MoveInputEvent>(OnRelayMoveInput);
|
||||
SubscribeLocalEvent<BodyComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||
SubscribeLocalEvent<BodyComponent, BeingMicrowavedEvent>(OnBeingMicrowaved);
|
||||
}
|
||||
|
||||
private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args)
|
||||
private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<MobStateComponent>(uid, out var mobState) &&
|
||||
mobState.IsDead() &&
|
||||
EntityManager.TryGetComponent<MindComponent>(uid, out var mind) &&
|
||||
mind.HasMind)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<MobStateComponent>(uid, out var mobState) &&
|
||||
mobState.IsDead() &&
|
||||
EntityManager.TryGetComponent<MindComponent>(uid, out var mind) &&
|
||||
mind.HasMind)
|
||||
if (!mind.Mind!.TimeOfDeath.HasValue)
|
||||
{
|
||||
if (!mind.Mind!.TimeOfDeath.HasValue)
|
||||
{
|
||||
mind.Mind.TimeOfDeath = _gameTiming.RealTime;
|
||||
}
|
||||
|
||||
_ticker.OnGhostAttempt(mind.Mind!, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, BodyComponent component, ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
foreach (var (part, _) in component.Parts)
|
||||
foreach (var mechanism in part.Mechanisms)
|
||||
{
|
||||
RaiseLocalEvent(mechanism.Owner, args, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBeingMicrowaved(EntityUid uid, BodyComponent component, BeingMicrowavedEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
// Don't microwave animals, kids
|
||||
Transform(uid).AttachToGridOrMap();
|
||||
component.Gib();
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of ValueTuples of <see cref="T"/> and MechanismComponent on each mechanism
|
||||
/// in the given body.
|
||||
/// </summary>
|
||||
/// <param name="uid">The entity to check for the component on.</param>
|
||||
/// <param name="body">The body to check for mechanisms on.</param>
|
||||
/// <typeparam name="T">The component to check for.</typeparam>
|
||||
public List<(T Comp, MechanismComponent Mech)> GetComponentsOnMechanisms<T>(EntityUid uid,
|
||||
SharedBodyComponent? body=null) where T : Component
|
||||
{
|
||||
if (!Resolve(uid, ref body))
|
||||
return new();
|
||||
|
||||
var query = EntityManager.GetEntityQuery<T>();
|
||||
var list = new List<(T Comp, MechanismComponent Mech)>(3);
|
||||
foreach (var (part, _) in body.Parts)
|
||||
foreach (var mechanism in part.Mechanisms)
|
||||
{
|
||||
if (query.TryGetComponent(mechanism.Owner, out var comp))
|
||||
list.Add((comp, mechanism));
|
||||
mind.Mind.TimeOfDeath = _gameTiming.RealTime;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a list of ValueTuples of <see cref="T"/> and MechanismComponent on each mechanism
|
||||
/// in the given body.
|
||||
/// </summary>
|
||||
/// <param name="uid">The entity to check for the component on.</param>
|
||||
/// <param name="comps">The list of components.</param>
|
||||
/// <param name="body">The body to check for mechanisms on.</param>
|
||||
/// <typeparam name="T">The component to check for.</typeparam>
|
||||
/// <returns>Whether any were found.</returns>
|
||||
public bool TryGetComponentsOnMechanisms<T>(EntityUid uid,
|
||||
[NotNullWhen(true)] out List<(T Comp, MechanismComponent Mech)>? comps,
|
||||
SharedBodyComponent? body=null) where T: Component
|
||||
{
|
||||
if (!Resolve(uid, ref body))
|
||||
{
|
||||
comps = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
comps = GetComponentsOnMechanisms<T>(uid, body);
|
||||
|
||||
if (comps.Count == 0)
|
||||
{
|
||||
comps = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
_ticker.OnGhostAttempt(mind.Mind!, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, BodyComponent component,
|
||||
ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
foreach (var organ in GetBodyOrgans(uid, component))
|
||||
{
|
||||
RaiseLocalEvent(organ.Id, args);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBeingMicrowaved(EntityUid uid, BodyComponent component, BeingMicrowavedEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
// Don't microwave animals, kids
|
||||
Transform(uid).AttachToGridOrMap();
|
||||
GibBody(uid, false, component);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
public override bool AttachPart(
|
||||
EntityUid? partId,
|
||||
BodyPartSlot slot,
|
||||
[NotNullWhen(true)] BodyPartComponent? part = null)
|
||||
{
|
||||
if (!base.AttachPart(partId, slot, part))
|
||||
return false;
|
||||
|
||||
if (part.Body is { } body &&
|
||||
TryComp<HumanoidComponent>(body, out var humanoid))
|
||||
{
|
||||
var layer = part.ToHumanoidLayers();
|
||||
if (layer != null)
|
||||
{
|
||||
var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
|
||||
_humanoidSystem.SetLayersVisibility(body, layers, true, true, humanoid);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool DropPart(EntityUid? partId, BodyPartComponent? part = null)
|
||||
{
|
||||
var oldBody = CompOrNull<BodyPartComponent>(partId)?.Body;
|
||||
|
||||
if (!base.DropPart(partId, part))
|
||||
return false;
|
||||
|
||||
if (oldBody == null || !TryComp<HumanoidComponent>(oldBody, out var humanoid))
|
||||
return true;
|
||||
|
||||
var layer = part.ToHumanoidLayers();
|
||||
if (layer == null)
|
||||
return true;
|
||||
|
||||
var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
|
||||
_humanoidSystem.SetLayersVisibility(oldBody.Value, layers, false, true, humanoid);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override HashSet<EntityUid> GibBody(EntityUid? bodyId, bool gibOrgans = false, BodyComponent? body = null)
|
||||
{
|
||||
if (bodyId == null || !Resolve(bodyId.Value, ref body, false))
|
||||
return new HashSet<EntityUid>();
|
||||
|
||||
var gibs = base.GibBody(bodyId, gibOrgans, body);
|
||||
|
||||
var xform = Transform(bodyId.Value);
|
||||
var coordinates = xform.Coordinates;
|
||||
var filter = Filter.Pvs(bodyId.Value, entityManager: EntityManager);
|
||||
var audio = AudioParams.Default.WithVariation(0.025f);
|
||||
|
||||
_audio.Play(body.GibSound, filter, coordinates, audio);
|
||||
|
||||
if (TryComp(bodyId, out ContainerManagerComponent? container))
|
||||
{
|
||||
foreach (var cont in container.GetAllContainers())
|
||||
{
|
||||
foreach (var ent in cont.ContainedEntities)
|
||||
{
|
||||
cont.ForceRemove(ent);
|
||||
Transform(ent).Coordinates = coordinates;
|
||||
ent.RandomOffset(0.25f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RaiseLocalEvent(bodyId.Value, new BeingGibbedEvent(gibs));
|
||||
QueueDel(bodyId.Value);
|
||||
|
||||
return gibs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Ghost.Components;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Events;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Movement.Components;
|
||||
|
||||
namespace Content.Server.Body.Systems
|
||||
@@ -13,21 +14,22 @@ namespace Content.Server.Body.Systems
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<BrainComponent, AddedToBodyEvent>((uid, _, args) => HandleMind((args.Body).Owner, uid));
|
||||
SubscribeLocalEvent<BrainComponent, AddedToPartEvent>((uid, _, args) => HandleMind((args.Part).Owner, uid));
|
||||
SubscribeLocalEvent<BrainComponent, AddedToPartInBodyEvent>((uid, _, args) => HandleMind((args.Body).Owner, uid));
|
||||
SubscribeLocalEvent<BrainComponent, AddedToBodyEvent>((uid, _, args) => HandleMind(args.Body, uid));
|
||||
SubscribeLocalEvent<BrainComponent, AddedToPartEvent>((uid, _, args) => HandleMind(args.Part, uid));
|
||||
SubscribeLocalEvent<BrainComponent, AddedToPartInBodyEvent>((uid, _, args) => HandleMind(args.Body, uid));
|
||||
SubscribeLocalEvent<BrainComponent, RemovedFromBodyEvent>(OnRemovedFromBody);
|
||||
SubscribeLocalEvent<BrainComponent, RemovedFromPartEvent>((uid, _, args) => HandleMind(uid, (args.Old).Owner));
|
||||
SubscribeLocalEvent<BrainComponent, RemovedFromPartInBodyEvent>((uid, _, args) => HandleMind((args.OldBody).Owner, uid));
|
||||
SubscribeLocalEvent<BrainComponent, RemovedFromPartEvent>((uid, _, args) => HandleMind(uid, args.Old));
|
||||
SubscribeLocalEvent<BrainComponent, RemovedFromPartInBodyEvent>((uid, _, args) => HandleMind(args.OldBody, uid));
|
||||
}
|
||||
|
||||
private void OnRemovedFromBody(EntityUid uid, BrainComponent component, RemovedFromBodyEvent args)
|
||||
{
|
||||
// This one needs to be special, okay?
|
||||
if (!EntityManager.TryGetComponent(uid, out MechanismComponent? mech))
|
||||
if (!EntityManager.TryGetComponent(uid, out OrganComponent? organ) ||
|
||||
organ.ParentSlot is not {Parent: var parent})
|
||||
return;
|
||||
|
||||
HandleMind((mech.Part!).Owner, (args.Old).Owner);
|
||||
HandleMind(parent, args.Old);
|
||||
}
|
||||
|
||||
private void HandleMind(EntityUid newEntity, EntityUid oldEntity)
|
||||
|
||||
@@ -3,7 +3,7 @@ using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
@@ -18,6 +18,7 @@ namespace Content.Server.Body.Systems
|
||||
[UsedImplicitly]
|
||||
public sealed class MetabolizerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
@@ -37,30 +38,27 @@ namespace Content.Server.Body.Systems
|
||||
{
|
||||
_solutionContainerSystem.EnsureSolution(uid, component.SolutionName);
|
||||
}
|
||||
else
|
||||
else if (CompOrNull<OrganComponent>(uid)?.Body is { } body)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<MechanismComponent>(uid, out var mech))
|
||||
{
|
||||
if (mech.Body != null)
|
||||
{
|
||||
_solutionContainerSystem.EnsureSolution((mech.Body).Owner, component.SolutionName);
|
||||
}
|
||||
}
|
||||
_solutionContainerSystem.EnsureSolution(body, component.SolutionName);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, MetabolizerComponent component, ApplyMetabolicMultiplierEvent args)
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, MetabolizerComponent component,
|
||||
ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
if (args.Apply)
|
||||
{
|
||||
component.UpdateFrequency *= args.Multiplier;
|
||||
return;
|
||||
}
|
||||
|
||||
component.UpdateFrequency /= args.Multiplier;
|
||||
// Reset the accumulator properly
|
||||
if (component.AccumulatedFrametime >= component.UpdateFrequency)
|
||||
component.AccumulatedFrametime = component.UpdateFrequency;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
@@ -78,33 +76,27 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
}
|
||||
|
||||
private void TryMetabolize(EntityUid uid, MetabolizerComponent? meta=null, MechanismComponent? mech=null)
|
||||
private void TryMetabolize(EntityUid uid, MetabolizerComponent? meta = null, OrganComponent? organ = null)
|
||||
{
|
||||
if (!Resolve(uid, ref meta))
|
||||
return;
|
||||
|
||||
Resolve(uid, ref mech, false);
|
||||
Resolve(uid, ref organ, false);
|
||||
|
||||
// First step is get the solution we actually care about
|
||||
Solution? solution = null;
|
||||
EntityUid? solutionEntityUid = null;
|
||||
EntityUid? bodyEntityUid = mech?.Body?.Owner;
|
||||
|
||||
SolutionContainerManagerComponent? manager = null;
|
||||
|
||||
if (meta.SolutionOnBody)
|
||||
{
|
||||
if (mech != null)
|
||||
if (organ?.Body is { } body)
|
||||
{
|
||||
var body = mech.Body;
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
if (!Resolve((body).Owner, ref manager, false))
|
||||
return;
|
||||
_solutionContainerSystem.TryGetSolution((body).Owner, meta.SolutionName, out solution, manager);
|
||||
solutionEntityUid = body.Owner;
|
||||
}
|
||||
if (!Resolve(body, ref manager, false))
|
||||
return;
|
||||
_solutionContainerSystem.TryGetSolution(body, meta.SolutionName, out solution, manager);
|
||||
solutionEntityUid = body;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -133,7 +125,8 @@ namespace Content.Server.Body.Systems
|
||||
if (proto.Metabolisms == null)
|
||||
{
|
||||
if (meta.RemoveEmpty)
|
||||
_solutionContainerSystem.TryRemoveReagent(solutionEntityUid.Value, solution, reagent.ReagentId, FixedPoint2.New(1));
|
||||
_solutionContainerSystem.TryRemoveReagent(solutionEntityUid.Value, solution, reagent.ReagentId,
|
||||
FixedPoint2.New(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -170,7 +163,7 @@ namespace Content.Server.Body.Systems
|
||||
continue;
|
||||
}
|
||||
|
||||
var actualEntity = bodyEntityUid != null ? bodyEntityUid.Value : solutionEntityUid.Value;
|
||||
var actualEntity = organ?.Body ?? solutionEntityUid.Value;
|
||||
var args = new ReagentEffectArgs(actualEntity, (meta).Owner, solution, proto, mostToRemove,
|
||||
EntityManager, null, entry);
|
||||
|
||||
@@ -192,16 +185,20 @@ namespace Content.Server.Body.Systems
|
||||
|
||||
// remove a certain amount of reagent
|
||||
if (mostToRemove > FixedPoint2.Zero)
|
||||
_solutionContainerSystem.TryRemoveReagent(solutionEntityUid.Value, solution, reagent.ReagentId, mostToRemove);
|
||||
_solutionContainerSystem.TryRemoveReagent(solutionEntityUid.Value, solution, reagent.ReagentId,
|
||||
mostToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ApplyMetabolicMultiplierEvent : EntityEventArgs
|
||||
{
|
||||
// The entity whose metabolism is being modified
|
||||
public EntityUid Uid;
|
||||
public EntityUid Uid;
|
||||
|
||||
// What the metabolism's update rate will be multiplied by
|
||||
public float Multiplier;
|
||||
public float Multiplier;
|
||||
|
||||
// Apply this multiplier or ignore / reset it?
|
||||
public bool Apply;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using Content.Shared.Atmos;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.MobState.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Player;
|
||||
@@ -42,8 +41,7 @@ namespace Content.Server.Body.Systems
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var (respirator, body) in
|
||||
EntityManager.EntityQuery<RespiratorComponent, SharedBodyComponent>())
|
||||
foreach (var (respirator, body) in EntityManager.EntityQuery<RespiratorComponent, BodyComponent>())
|
||||
{
|
||||
var uid = respirator.Owner;
|
||||
|
||||
@@ -91,12 +89,13 @@ namespace Content.Server.Body.Systems
|
||||
respirator.SuffocationCycles = 0;
|
||||
}
|
||||
}
|
||||
public void Inhale(EntityUid uid, SharedBodyComponent? body=null)
|
||||
|
||||
public void Inhale(EntityUid uid, BodyComponent? body = null)
|
||||
{
|
||||
if (!Resolve(uid, ref body, false))
|
||||
return;
|
||||
|
||||
var organs = _bodySystem.GetComponentsOnMechanisms<LungComponent>(uid, body);
|
||||
var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid, body);
|
||||
|
||||
// Inhale gas
|
||||
var ev = new InhaleLocationEvent();
|
||||
@@ -121,12 +120,12 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
}
|
||||
|
||||
public void Exhale(EntityUid uid, SharedBodyComponent? body=null)
|
||||
public void Exhale(EntityUid uid, BodyComponent? body = null)
|
||||
{
|
||||
if (!Resolve(uid, ref body, false))
|
||||
return;
|
||||
|
||||
var organs = _bodySystem.GetComponentsOnMechanisms<LungComponent>(uid, body);
|
||||
var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid, body);
|
||||
|
||||
// exhale gas
|
||||
|
||||
@@ -187,7 +186,8 @@ namespace Content.Server.Body.Systems
|
||||
Math.Clamp(respirator.Saturation, respirator.MinSaturation, respirator.MaxSaturation);
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, RespiratorComponent component, ApplyMetabolicMultiplierEvent args)
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, RespiratorComponent component,
|
||||
ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
if (args.Apply)
|
||||
{
|
||||
@@ -197,6 +197,7 @@ namespace Content.Server.Body.Systems
|
||||
component.MinSaturation *= args.Multiplier;
|
||||
return;
|
||||
}
|
||||
|
||||
// This way we don't have to worry about it breaking if the stasis bed component is destroyed
|
||||
component.CycleDelay /= args.Multiplier;
|
||||
component.Saturation /= args.Multiplier;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Content.Server.Body.Systems
|
||||
{
|
||||
public sealed class StomachSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
|
||||
public const string DefaultSolutionName = "stomach";
|
||||
@@ -21,12 +22,8 @@ namespace Content.Server.Body.Systems
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
foreach (var (stomach, mech, sol)
|
||||
in EntityManager.EntityQuery<StomachComponent, MechanismComponent, SolutionContainerManagerComponent>(false))
|
||||
foreach (var (stomach, organ, sol)in EntityManager.EntityQuery<StomachComponent, OrganComponent, SolutionContainerManagerComponent>())
|
||||
{
|
||||
if (mech.Body == null)
|
||||
continue;
|
||||
|
||||
stomach.AccumulatedFrameTime += frameTime;
|
||||
|
||||
if (stomach.AccumulatedFrameTime < stomach.UpdateInterval)
|
||||
@@ -35,12 +32,11 @@ namespace Content.Server.Body.Systems
|
||||
stomach.AccumulatedFrameTime -= stomach.UpdateInterval;
|
||||
|
||||
// Get our solutions
|
||||
if (!_solutionContainerSystem.TryGetSolution((stomach).Owner, DefaultSolutionName,
|
||||
out var stomachSolution, sol))
|
||||
if (!_solutionContainerSystem.TryGetSolution(stomach.Owner, DefaultSolutionName,
|
||||
out var stomachSolution, sol))
|
||||
continue;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution((mech.Body).Owner, stomach.BodySolutionName,
|
||||
out var bodySolution))
|
||||
if (organ.Body is not { } body || !_solutionContainerSystem.TryGetSolution(body, stomach.BodySolutionName, out var bodySolution))
|
||||
continue;
|
||||
|
||||
var transferSolution = new Solution();
|
||||
@@ -71,23 +67,25 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
|
||||
// Transfer everything to the body solution!
|
||||
_solutionContainerSystem.TryAddSolution((mech.Body).Owner, bodySolution, transferSolution);
|
||||
_solutionContainerSystem.TryAddSolution(body, bodySolution, transferSolution);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, StomachComponent component, ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
if (args.Apply)
|
||||
private void OnApplyMetabolicMultiplier(EntityUid uid, StomachComponent component,
|
||||
ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
component.UpdateInterval *= args.Multiplier;
|
||||
return;
|
||||
if (args.Apply)
|
||||
{
|
||||
component.UpdateInterval *= args.Multiplier;
|
||||
return;
|
||||
}
|
||||
|
||||
// This way we don't have to worry about it breaking if the stasis bed component is destroyed
|
||||
component.UpdateInterval /= args.Multiplier;
|
||||
// Reset the accumulator properly
|
||||
if (component.AccumulatedFrameTime >= component.UpdateInterval)
|
||||
component.AccumulatedFrameTime = component.UpdateInterval;
|
||||
}
|
||||
// This way we don't have to worry about it breaking if the stasis bed component is destroyed
|
||||
component.UpdateInterval /= args.Multiplier;
|
||||
// Reset the accumulator properly
|
||||
if (component.AccumulatedFrameTime >= component.UpdateInterval)
|
||||
component.AccumulatedFrameTime = component.UpdateInterval;
|
||||
}
|
||||
|
||||
private void OnComponentInit(EntityUid uid, StomachComponent component, ComponentInit args)
|
||||
{
|
||||
@@ -96,7 +94,7 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
|
||||
public bool CanTransferSolution(EntityUid uid, Solution solution,
|
||||
SolutionContainerManagerComponent? solutions=null)
|
||||
SolutionContainerManagerComponent? solutions = null)
|
||||
{
|
||||
if (!Resolve(uid, ref solutions, false))
|
||||
return false;
|
||||
@@ -112,8 +110,8 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
|
||||
public bool TryTransferSolution(EntityUid uid, Solution solution,
|
||||
StomachComponent? stomach=null,
|
||||
SolutionContainerManagerComponent? solutions=null)
|
||||
StomachComponent? stomach = null,
|
||||
SolutionContainerManagerComponent? solutions = null)
|
||||
{
|
||||
if (!Resolve(uid, ref stomach, ref solutions, false))
|
||||
return false;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Containers;
|
||||
@@ -22,6 +23,8 @@ public sealed class PricingSystem : EntitySystem
|
||||
[Dependency] private readonly IConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -84,8 +87,8 @@ public sealed class PricingSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
var partList = body.Slots.ToList();
|
||||
var totalPartsPresent = partList.Sum(x => x.Part != null ? 1 : 0);
|
||||
var partList = _bodySystem.GetBodyAllSlots(uid, body).ToList();
|
||||
var totalPartsPresent = partList.Sum(x => x.Child != null ? 1 : 0);
|
||||
var totalParts = partList.Count;
|
||||
|
||||
var partRatio = totalPartsPresent / (double) totalParts;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Climbing.Components;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.Interaction.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
@@ -15,7 +14,6 @@ using Content.Shared.Damage;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
@@ -30,7 +28,6 @@ using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using SharpZstd.Interop;
|
||||
|
||||
namespace Content.Server.Climbing;
|
||||
|
||||
@@ -39,6 +36,7 @@ public sealed class ClimbSystem : SharedClimbSystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly FixtureSystem _fixtureSystem = default!;
|
||||
@@ -286,9 +284,9 @@ public sealed class ClimbSystem : SharedClimbSystem
|
||||
}
|
||||
|
||||
if (!HasComp<ClimbingComponent>(user)
|
||||
|| !TryComp(user, out SharedBodyComponent? body)
|
||||
|| !body.HasPartOfType(BodyPartType.Leg)
|
||||
|| !body.HasPartOfType(BodyPartType.Foot))
|
||||
|| !TryComp(user, out BodyComponent? body)
|
||||
|| !_bodySystem.BodyHasChildOfType(user, BodyPartType.Leg, body)
|
||||
|| !_bodySystem.BodyHasChildOfType(user, BodyPartType.Foot, body))
|
||||
{
|
||||
reason = Loc.GetString("comp-climbable-cant-climb");
|
||||
return false;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.Destructible.Thresholds;
|
||||
using Content.Server.Destructible.Thresholds.Behaviors;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.FixedPoint;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
|
||||
namespace Content.Server.Destructible
|
||||
{
|
||||
@@ -23,6 +24,7 @@ namespace Content.Server.Destructible
|
||||
public new IEntityManager EntityManager => base.EntityManager;
|
||||
|
||||
[Dependency] public readonly AudioSystem AudioSystem = default!;
|
||||
[Dependency] public readonly BodySystem BodySystem = default!;
|
||||
[Dependency] public readonly ConstructionSystem ConstructionSystem = default!;
|
||||
[Dependency] public readonly ExplosionSystem ExplosionSystem = default!;
|
||||
[Dependency] public readonly StackSystem StackSystem = default!;
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace Content.Server.Destructible.Thresholds.Behaviors
|
||||
|
||||
public void Execute(EntityUid owner, DestructibleSystem system)
|
||||
{
|
||||
if (system.EntityManager.TryGetComponent(owner, out SharedBodyComponent? body))
|
||||
if (system.EntityManager.TryGetComponent(owner, out BodyComponent? body))
|
||||
{
|
||||
body.Gib(_recursive);
|
||||
system.BodySystem.GibBody(owner, _recursive, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Disposal.Tube.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.Containers;
|
||||
@@ -74,7 +73,7 @@ namespace Content.Server.Disposal.Unit.Components
|
||||
}
|
||||
|
||||
return _entMan.HasComponent<ItemComponent>(entity) ||
|
||||
_entMan.HasComponent<SharedBodyComponent>(entity);
|
||||
_entMan.HasComponent<BodyComponent>(entity);
|
||||
}
|
||||
|
||||
public bool TryInsert(EntityUid entity)
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
using Content.Shared.Drone;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Drone.Components;
|
||||
using Content.Shared.MobState;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Interaction.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Emoting;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Ghost.Components;
|
||||
using Content.Server.Ghost.Roles.Components;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Tools.Innate;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Drone;
|
||||
using Content.Shared.Emoting;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction.Components;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.MobState;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -25,6 +26,7 @@ namespace Content.Server.Drone
|
||||
{
|
||||
public sealed class DroneSystem : SharedDroneSystem
|
||||
{
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
@@ -83,8 +85,8 @@ namespace Content.Server.Drone
|
||||
if (TryComp<InnateToolComponent>(uid, out var innate))
|
||||
_innateToolSystem.Cleanup(uid, innate);
|
||||
|
||||
if (TryComp<SharedBodyComponent>(uid, out var body))
|
||||
body.Gib();
|
||||
if (TryComp<BodyComponent>(uid, out var body))
|
||||
_bodySystem.GibBody(uid, body: body);
|
||||
Del(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
@@ -16,6 +16,8 @@ public sealed class ImmovableRodSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -96,7 +98,7 @@ public sealed class ImmovableRodSystem : EntitySystem
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("immovable-rod-penetrated-mob", ("rod", uid), ("mob", ent)), uid,
|
||||
Filter.Pvs(uid), PopupType.LargeCaution);
|
||||
body.Gib();
|
||||
_bodySystem.GibBody(ent, body: body);
|
||||
}
|
||||
|
||||
QueueDel(ent);
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Server.Temperature.Systems;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Kitchen;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Power;
|
||||
using Content.Shared.Tag;
|
||||
@@ -24,11 +24,13 @@ using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Kitchen.EntitySystems
|
||||
{
|
||||
public sealed class MicrowaveSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly RecipeManager _recipeManager = default!;
|
||||
@@ -182,29 +184,19 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
var victim = args.Victim;
|
||||
var headCount = 0;
|
||||
|
||||
if (TryComp<SharedBodyComponent>(victim, out var body))
|
||||
if (TryComp<BodyComponent>(victim, out var body))
|
||||
{
|
||||
var headSlots = body.GetSlotsOfType(BodyPartType.Head);
|
||||
var headSlots = _bodySystem.GetBodyChildrenOfType(victim, BodyPartType.Head, body);
|
||||
|
||||
foreach (var slot in headSlots)
|
||||
foreach (var part in headSlots)
|
||||
{
|
||||
var part = slot.Part;
|
||||
|
||||
if (part == null ||
|
||||
!body.TryDropPart(slot, out var dropped))
|
||||
if (!_bodySystem.OrphanPart(part.Id, part.Component))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var droppedPart in dropped.Values)
|
||||
{
|
||||
if (droppedPart.PartType != BodyPartType.Head)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
component.Storage.Insert(droppedPart.Owner);
|
||||
headCount++;
|
||||
}
|
||||
component.Storage.Insert(part.Id);
|
||||
headCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Server.MobState;
|
||||
using Content.Shared.Body.Components;
|
||||
@@ -16,6 +17,7 @@ namespace Content.Server.Kitchen.EntitySystems;
|
||||
|
||||
public sealed class SharpSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
||||
@@ -95,7 +97,7 @@ public sealed class SharpSystem : EntitySystem
|
||||
popupEnt = Spawn(proto, coords.Offset(_robustRandom.NextVector2(0.25f)));
|
||||
}
|
||||
|
||||
var hasBody = TryComp<SharedBodyComponent>(ev.Entity, out var body);
|
||||
var hasBody = TryComp<BodyComponent>(ev.Entity, out var body);
|
||||
|
||||
// only show a big popup when butchering living things.
|
||||
var popupType = PopupType.Small;
|
||||
@@ -107,7 +109,7 @@ public sealed class SharpSystem : EntitySystem
|
||||
|
||||
if (hasBody)
|
||||
{
|
||||
body!.Gib();
|
||||
_bodySystem.GibBody(body!.Owner, body: body);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System.Threading;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Coordinates.Helpers;
|
||||
using Content.Server.Decals;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Doors.Components;
|
||||
using Content.Server.Magic.Events;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Spawners.Components;
|
||||
using Content.Server.Weapons.Ranged.Systems;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
@@ -35,6 +33,7 @@ public sealed class MagicSystem : EntitySystem
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedDoorSystem _doorSystem = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||
@@ -281,7 +280,7 @@ public sealed class MagicSystem : EntitySystem
|
||||
if (!TryComp<BodyComponent>(ev.Target, out var body))
|
||||
return;
|
||||
|
||||
var ents = body.Gib(true);
|
||||
var ents = _bodySystem.GibBody(ev.Target, true, body);
|
||||
|
||||
if (!ev.DeleteNonBrainParts)
|
||||
return;
|
||||
@@ -289,8 +288,7 @@ public sealed class MagicSystem : EntitySystem
|
||||
foreach (var part in ents)
|
||||
{
|
||||
// just leaves a brain and clothes
|
||||
if ((HasComp<BodyPartComponent>(part) || HasComp<MechanismComponent>(part))
|
||||
&& !HasComp<BrainComponent>(part))
|
||||
if (HasComp<BodyComponent>(part) && !HasComp<BrainComponent>(part))
|
||||
{
|
||||
QueueDel(part);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.IdentityManagement;
|
||||
|
||||
namespace Content.Server.Medical
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace Content.Server.Medical
|
||||
public void Vomit(EntityUid uid, float thirstAdded = -40f, float hungerAdded = -40f)
|
||||
{
|
||||
/// Main requirement: You have a stomach
|
||||
var stomachList = _bodySystem.GetComponentsOnMechanisms<StomachComponent>(uid);
|
||||
var stomachList = _bodySystem.GetBodyOrganComponents<StomachComponent>(uid);
|
||||
if (stomachList.Count == 0)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Morgue.Components;
|
||||
using Content.Shared.Standing;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Standing;
|
||||
|
||||
namespace Content.Server.Morgue;
|
||||
|
||||
public sealed class EntityStorageLayingDownOverrideSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly StandingStateSystem _standing = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -16,10 +18,11 @@ public sealed class EntityStorageLayingDownOverrideSystem : EntitySystem
|
||||
SubscribeLocalEvent<EntityStorageLayingDownOverrideComponent, StorageBeforeCloseEvent>(OnBeforeClose);
|
||||
}
|
||||
|
||||
private void OnBeforeClose(EntityUid uid, EntityStorageLayingDownOverrideComponent component, StorageBeforeCloseEvent args)
|
||||
private void OnBeforeClose(EntityUid uid, EntityStorageLayingDownOverrideComponent component,
|
||||
StorageBeforeCloseEvent args)
|
||||
{
|
||||
foreach (var ent in args.Contents)
|
||||
if (HasComp<SharedBodyComponent>(ent) && !_standing.IsDown(ent))
|
||||
if (HasComp<BodyComponent>(ent) && !_standing.IsDown(ent))
|
||||
args.Contents.Remove(ent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Content.Server.Morgue.Components;
|
||||
using Content.Shared.Morgue;
|
||||
using Content.Shared.Examine;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Morgue;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.Morgue;
|
||||
|
||||
@@ -61,7 +61,7 @@ public sealed class MorgueSystem : EntitySystem
|
||||
|
||||
foreach (var ent in storage.Contents.ContainedEntities)
|
||||
{
|
||||
if (!hasMob && HasComp<SharedBodyComponent>(ent))
|
||||
if (!hasMob && HasComp<BodyComponent>(ent))
|
||||
hasMob = true;
|
||||
|
||||
if (HasComp<ActorComponent?>(ent))
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
SubscribeLocalEvent<DrinkComponent, GetVerbsEvent<AlternativeVerb>>(AddDrinkVerb);
|
||||
SubscribeLocalEvent<DrinkComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<DrinkComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
|
||||
SubscribeLocalEvent<SharedBodyComponent, DrinkEvent>(OnDrink);
|
||||
SubscribeLocalEvent<BodyComponent, DrinkEvent>(OnDrink);
|
||||
SubscribeLocalEvent<DrinkCancelledEvent>(OnDrinkCancelled);
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!EntityManager.HasComponent<SharedBodyComponent>(target))
|
||||
if (!EntityManager.HasComponent<BodyComponent>(target))
|
||||
return false;
|
||||
|
||||
if (!drink.Opened)
|
||||
@@ -286,7 +286,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
/// <summary>
|
||||
/// Raised directed at a victim when someone has force fed them a drink.
|
||||
/// </summary>
|
||||
private void OnDrink(EntityUid uid, SharedBodyComponent body, DrinkEvent args)
|
||||
private void OnDrink(EntityUid uid, BodyComponent body, DrinkEvent args)
|
||||
{
|
||||
if (args.Drink.Deleted)
|
||||
return;
|
||||
@@ -297,7 +297,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
|
||||
var forceDrink = uid != args.User;
|
||||
|
||||
if (!_bodySystem.TryGetComponentsOnMechanisms<StomachComponent>(uid, out var stomachs, body))
|
||||
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(uid, out var stomachs, body))
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
forceDrink ?
|
||||
@@ -380,8 +380,8 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
if (uid == ev.User ||
|
||||
!ev.CanInteract ||
|
||||
!ev.CanAccess ||
|
||||
!EntityManager.TryGetComponent(ev.User, out SharedBodyComponent? body) ||
|
||||
!_bodySystem.TryGetComponentsOnMechanisms<StomachComponent>(ev.User, out var stomachs, body))
|
||||
!EntityManager.TryGetComponent(ev.User, out BodyComponent? body) ||
|
||||
!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(ev.User, out var stomachs, body))
|
||||
return;
|
||||
|
||||
if (EntityManager.TryGetComponent<MobStateComponent>(uid, out var mobState) && mobState.IsAlive())
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Threading;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
@@ -20,7 +21,6 @@ using Content.Shared.Verbs;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Threading;
|
||||
|
||||
namespace Content.Server.Nutrition.EntitySystems
|
||||
{
|
||||
@@ -48,7 +48,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
SubscribeLocalEvent<FoodComponent, UseInHandEvent>(OnUseFoodInHand);
|
||||
SubscribeLocalEvent<FoodComponent, AfterInteractEvent>(OnFeedFood);
|
||||
SubscribeLocalEvent<FoodComponent, GetVerbsEvent<AlternativeVerb>>(AddEatVerb);
|
||||
SubscribeLocalEvent<SharedBodyComponent, FeedEvent>(OnFeed);
|
||||
SubscribeLocalEvent<BodyComponent, FeedEvent>(OnFeed);
|
||||
SubscribeLocalEvent<ForceFeedCancelledEvent>(OnFeedCancelled);
|
||||
SubscribeLocalEvent<InventoryComponent, IngestionAttemptEvent>(OnInventoryIngestAttempt);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
return false;
|
||||
|
||||
// Target can't be fed
|
||||
if (!EntityManager.HasComponent<SharedBodyComponent>(target))
|
||||
if (!EntityManager.HasComponent<BodyComponent>(target))
|
||||
return false;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution(food.Owner, food.SolutionName, out var foodSolution))
|
||||
@@ -145,14 +145,14 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
|
||||
}
|
||||
|
||||
private void OnFeed(EntityUid uid, SharedBodyComponent body, FeedEvent args)
|
||||
private void OnFeed(EntityUid uid, BodyComponent body, FeedEvent args)
|
||||
{
|
||||
if (args.Food.Deleted)
|
||||
return;
|
||||
|
||||
args.Food.CancelToken = null;
|
||||
|
||||
if (!_bodySystem.TryGetComponentsOnMechanisms<StomachComponent>(uid, out var stomachs, body))
|
||||
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(uid, out var stomachs, body))
|
||||
return;
|
||||
|
||||
var transferAmount = args.Food.TransferAmount != null
|
||||
@@ -243,8 +243,8 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
if (uid == ev.User ||
|
||||
!ev.CanInteract ||
|
||||
!ev.CanAccess ||
|
||||
!EntityManager.TryGetComponent(ev.User, out SharedBodyComponent? body) ||
|
||||
!_bodySystem.TryGetComponentsOnMechanisms<StomachComponent>(ev.User, out var stomachs, body))
|
||||
!EntityManager.TryGetComponent(ev.User, out BodyComponent? body) ||
|
||||
!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(ev.User, out var stomachs, body))
|
||||
return;
|
||||
|
||||
if (EntityManager.TryGetComponent<MobStateComponent>(uid, out var mobState) && mobState.IsAlive())
|
||||
@@ -279,7 +279,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, food.SolutionName, out var foodSolution))
|
||||
return;
|
||||
|
||||
if (!_bodySystem.TryGetComponentsOnMechanisms<StomachComponent>(target, out var stomachs, body))
|
||||
if (!_bodySystem.TryGetBodyOrganComponents<StomachComponent>(target, out var stomachs, body))
|
||||
return;
|
||||
|
||||
if (food.UsesRemaining <= 0)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Recycling.Components;
|
||||
using Content.Shared.Audio;
|
||||
@@ -14,7 +14,6 @@ using Content.Shared.Recycling;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -25,6 +24,7 @@ namespace Content.Server.Recycling
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambience = default!;
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly TagSystem _tags = default!;
|
||||
@@ -57,9 +57,9 @@ namespace Content.Server.Recycling
|
||||
victim,
|
||||
Filter.Pvs(victim, entityManager: EntityManager).RemoveWhereAttachedEntity(e => e == victim));
|
||||
|
||||
if (TryComp<SharedBodyComponent?>(victim, out var body))
|
||||
if (TryComp<BodyComponent?>(victim, out var body))
|
||||
{
|
||||
body.Gib(true);
|
||||
_bodySystem.GibBody(victim, true, body);
|
||||
}
|
||||
|
||||
Bloodstain(component);
|
||||
@@ -104,7 +104,7 @@ namespace Content.Server.Recycling
|
||||
// Mobs are a special case!
|
||||
if (CanGib(component, entity))
|
||||
{
|
||||
Comp<SharedBodyComponent>(entity).Gib(true);
|
||||
_bodySystem.GibBody(entity, true, Comp<BodyComponent>(entity));
|
||||
Bloodstain(component);
|
||||
return;
|
||||
}
|
||||
@@ -123,7 +123,7 @@ namespace Content.Server.Recycling
|
||||
|
||||
private bool CanGib(RecyclerComponent component, EntityUid entity)
|
||||
{
|
||||
return HasComp<SharedBodyComponent>(entity) && !component.Safe &&
|
||||
return HasComp<BodyComponent>(entity) && !component.Safe &&
|
||||
this.IsPowered(component.Owner, EntityManager);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.MobState;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Damage;
|
||||
|
||||
namespace Content.Server.Salvage;
|
||||
|
||||
public sealed class SalvageMobRestrictionsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -55,7 +58,7 @@ public sealed class SalvageMobRestrictionsSystem : EntitySystem
|
||||
if (bodyQuery.TryGetComponent(target, out var body))
|
||||
{
|
||||
// Just because.
|
||||
body.Gib();
|
||||
_bodySystem.GibBody(target, body: body);
|
||||
}
|
||||
else if (damageQuery.TryGetComponent(target, out var damageableComponent))
|
||||
{
|
||||
|
||||
@@ -326,7 +326,7 @@ public sealed class EntityStorageSystem : EntitySystem
|
||||
if (attemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
var targetIsMob = HasComp<SharedBodyComponent>(toInsert);
|
||||
var targetIsMob = HasComp<BodyComponent>(toInsert);
|
||||
var storageIsItem = HasComp<ItemComponent>(container);
|
||||
var allowedToEat = whitelist?.IsValid(toInsert) ?? HasComp<ItemComponent>(toInsert);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Buckle.Components;
|
||||
using Content.Server.Buckle.Systems;
|
||||
using Content.Server.Popups;
|
||||
@@ -24,6 +25,7 @@ namespace Content.Server.Toilet
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SecretStashSystem _secretStash = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
@@ -48,8 +50,8 @@ namespace Content.Server.Toilet
|
||||
return;
|
||||
|
||||
// Check that victim has a head
|
||||
if (EntityManager.TryGetComponent<SharedBodyComponent>(args.Victim, out var body) &&
|
||||
body.HasPartOfType(BodyPartType.Head))
|
||||
if (EntityManager.TryGetComponent<BodyComponent>(args.Victim, out var body) &&
|
||||
_bodySystem.BodyHasChildOfType(args.Victim, BodyPartType.Head, body))
|
||||
{
|
||||
var othersMessage = Loc.GetString("toilet-component-suicide-head-message-others",
|
||||
("victim", Identity.Entity(args.Victim, EntityManager)), ("owner", uid));
|
||||
|
||||
Reference in New Issue
Block a user