diff --git a/Content.Server/Commands/Observer/Ghost.cs b/Content.Server/Commands/Observer/Ghost.cs index 2e1dcd027c..6aa887dd47 100644 --- a/Content.Server/Commands/Observer/Ghost.cs +++ b/Content.Server/Commands/Observer/Ghost.cs @@ -31,7 +31,7 @@ namespace Content.Server.Commands.Observer return; } - var mind = player!.ContentData()?.Mind; + var mind = player.ContentData()?.Mind; if (mind == null) { shell?.SendText(player, "You have no Mind, you can't ghost."); diff --git a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs index 0ba0ddd75d..1f22c0a91d 100644 --- a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs @@ -1,5 +1,9 @@ #nullable enable using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.Interfaces.Chat; +using Content.Server.Interfaces.GameObjects; +using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Morgue; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; @@ -11,9 +15,14 @@ using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Localization; -using Robust.Shared.Timers; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; +using System.Threading; +using Content.Server.Interfaces.GameTicking; +using Content.Server.Players; +using Robust.Server.Player; +using Robust.Shared.GameObjects.Components.Timers; +using Robust.Shared.IoC; namespace Content.Server.GameObjects.Components.Morgue { @@ -22,7 +31,7 @@ namespace Content.Server.GameObjects.Components.Morgue [ComponentReference(typeof(EntityStorageComponent))] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(IStorageComponent))] - public class CrematoriumEntityStorageComponent : MorgueEntityStorageComponent, IExamine + public class CrematoriumEntityStorageComponent : MorgueEntityStorageComponent, IExamine, ISuicideAct { public override string Name => "CrematoriumEntityStorage"; @@ -32,6 +41,8 @@ namespace Content.Server.GameObjects.Components.Morgue [ViewVariables(VVAccess.ReadWrite)] private int _burnMilis = 3000; + private CancellationTokenSource? _cremateCancelToken; + void IExamine.Examine(FormattedMessage message, bool inDetailsRange) { if (Appearance == null) return; @@ -64,16 +75,30 @@ namespace Content.Server.GameObjects.Components.Morgue return base.CanOpen(user, silent); } - public void Cremate() + public void TryCremate() { if (Cooking) return; if (Open) return; + Cremate(); + } + + public void Cremate() + { + if (Open) + CloseStorage(); + Appearance?.SetData(CrematoriumVisuals.Burning, true); Cooking = true; - Timer.Spawn(_burnMilis, () => + _cremateCancelToken?.Cancel(); + + _cremateCancelToken = new CancellationTokenSource(); + Owner.SpawnTimer(_burnMilis, () => { + if (Owner.Deleted) + return; + Appearance?.SetData(CrematoriumVisuals.Burning, false); Cooking = false; @@ -93,7 +118,34 @@ namespace Content.Server.GameObjects.Components.Morgue TryOpenStorage(Owner); EntitySystem.Get().PlayFromEntity("/Audio/Machines/ding.ogg", Owner); - }); + }, _cremateCancelToken.Token); + } + + public SuicideKind Suicide(IEntity victim, IChatManager chat) + { + var mind = victim.PlayerSession()?.ContentData()?.Mind; + + if (mind != null) + { + IoCManager.Resolve().OnGhostAttempt(mind, false); + mind.OwnedEntity.PopupMessage(Loc.GetString("You cremate yourself!")); + } + + victim.PopupMessageOtherClients(Loc.GetString("{0:theName} is cremating {0:themself}!", victim)); + EntitySystem.Get().Down(victim, false, false, true); + + if (CanInsert(victim)) + { + Insert(victim); + } + else + { + victim.Delete(); + } + + Cremate(); + + return SuicideKind.Heat; } [Verb] @@ -113,7 +165,7 @@ namespace Content.Server.GameObjects.Components.Morgue /// protected override void Activate(IEntity user, CrematoriumEntityStorageComponent component) { - component.Cremate(); + component.TryCremate(); } } } diff --git a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs index a9074492d5..dc0acb8636 100644 --- a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs +++ b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs @@ -3,15 +3,25 @@ using System.Collections.Generic; using Content.Server.GameObjects.Components.Conveyor; using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Power.ApcNetComponents; +using Content.Server.Interfaces.Chat; +using Content.Server.Interfaces.GameObjects; +using Content.Server.Interfaces.GameTicking; +using Content.Server.Players; +using Content.Server.Utility; using Content.Shared.GameObjects.Components.Body; +using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Recycling; +using Content.Shared.Interfaces; using Content.Shared.Physics; using Robust.Server.GameObjects; +using Robust.Server.Player; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components.Map; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -20,7 +30,7 @@ namespace Content.Server.GameObjects.Components.Recycling { // TODO: Add sound and safe beep [RegisterComponent] - public class RecyclerComponent : Component, ICollideBehavior + public class RecyclerComponent : Component, ICollideBehavior, ISuicideAct { public override string Name => "Recycler"; @@ -174,5 +184,27 @@ namespace Content.Server.GameObjects.Components.Recycling { Recycle(collidedWith); } + + public SuicideKind Suicide(IEntity victim, IChatManager chat) + { + var mind = victim.PlayerSession()?.ContentData()?.Mind; + + if (mind != null) + { + IoCManager.Resolve().OnGhostAttempt(mind, false); + mind.OwnedEntity.PopupMessage(Loc.GetString("You recycle yourself!")); + } + + victim.PopupMessageOtherClients(Loc.GetString("{0:theName} tries to recycle {0:themself}!", victim)); + + if (victim.TryGetComponent(out var body)) + { + body.Gib(true); + } + + Bloodstain(); + + return SuicideKind.Bloodloss; + } } }