Convert suicide to ecs (#8091)
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
using Content.Server.Chat.Managers;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.Act
|
||||
{
|
||||
[RequiresExplicitImplementation]
|
||||
public interface ISuicideAct
|
||||
{
|
||||
public SuicideKind Suicide(EntityUid victim, IChatManager chat);
|
||||
}
|
||||
|
||||
public enum SuicideKind
|
||||
{
|
||||
Special, //Doesn't damage the mob, used for "weird" suicides like gibbing
|
||||
|
||||
//Damage type suicides
|
||||
Blunt,
|
||||
Slash,
|
||||
Piercing,
|
||||
Heat,
|
||||
Shock,
|
||||
Cold,
|
||||
Poison,
|
||||
Radiation,
|
||||
Asphyxiation,
|
||||
Bloodloss
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
|
||||
@@ -36,122 +36,9 @@ namespace Content.Server.Chat.Commands
|
||||
|
||||
public string Help => Loc.GetString("suicide-command-help-text");
|
||||
|
||||
private void DealDamage(ISuicideAct suicide, IChatManager chat, EntityUid target)
|
||||
{
|
||||
var kind = suicide.Suicide(target, chat);
|
||||
if (kind != SuicideKind.Special)
|
||||
{
|
||||
// TODO SUICIDE ..heh.. anyway, someone should fix this mess.
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
DamageSpecifier damage = new(kind switch
|
||||
{
|
||||
SuicideKind.Blunt => prototypeManager.Index<DamageTypePrototype>("Blunt"),
|
||||
SuicideKind.Slash => prototypeManager.Index<DamageTypePrototype>("Slash"),
|
||||
SuicideKind.Piercing => prototypeManager.Index<DamageTypePrototype>("Piercing"),
|
||||
SuicideKind.Heat => prototypeManager.Index<DamageTypePrototype>("Heat"),
|
||||
SuicideKind.Shock => prototypeManager.Index<DamageTypePrototype>("Shock"),
|
||||
SuicideKind.Cold => prototypeManager.Index<DamageTypePrototype>("Cold"),
|
||||
SuicideKind.Poison => prototypeManager.Index<DamageTypePrototype>("Poison"),
|
||||
SuicideKind.Radiation => prototypeManager.Index<DamageTypePrototype>("Radiation"),
|
||||
SuicideKind.Asphyxiation => prototypeManager.Index<DamageTypePrototype>("Asphyxiation"),
|
||||
SuicideKind.Bloodloss => prototypeManager.Index<DamageTypePrototype>("Bloodloss"),
|
||||
_ => prototypeManager.Index<DamageTypePrototype>("Blunt")
|
||||
},
|
||||
200);
|
||||
EntitySystem.Get<DamageableSystem>().TryChangeDamage(target, damage, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (player == null)
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("shell-cannot-run-command-from-server"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
|
||||
return;
|
||||
|
||||
var chat = IoCManager.Resolve<IChatManager>();
|
||||
var mind = player.ContentData()?.Mind;
|
||||
|
||||
// This check also proves mind not-null for at the end when the mob is ghosted.
|
||||
if (mind?.OwnedComponent?.Owner is not {Valid: true} owner)
|
||||
{
|
||||
shell.WriteLine("You don't have a mind!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Checks to see if the player is dead.
|
||||
if(_entities.TryGetComponent<MobStateComponent>(owner, out var mobState) && mobState.IsDead())
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("suicide-command-already-dead"));
|
||||
return;
|
||||
}
|
||||
|
||||
//Checks to see if the CannotSuicide tag exits, ghosts instead.
|
||||
if(EntitySystem.Get<TagSystem>().HasTag(owner, "CannotSuicide"))
|
||||
{
|
||||
if (!EntitySystem.Get<GameTicker>().OnGhostAttempt(mind, true))
|
||||
{
|
||||
shell?.WriteLine("You can't ghost right now.");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: needs to check if the mob is actually alive
|
||||
//TODO: maybe set a suicided flag to prevent resurrection?
|
||||
|
||||
EntitySystem.Get<AdminLogSystem>().Add(LogType.Suicide,
|
||||
$"{_entities.ToPrettyString(player.AttachedEntity.Value):player} is committing suicide");
|
||||
|
||||
// Held item suicide
|
||||
if (_entities.TryGetComponent(owner, out HandsComponent handsComponent)
|
||||
&& handsComponent.ActiveHandEntity is EntityUid item)
|
||||
{
|
||||
var suicide = _entities.GetComponents<ISuicideAct>(item).FirstOrDefault();
|
||||
|
||||
if (suicide != null)
|
||||
{
|
||||
DealDamage(suicide, chat, owner);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get all entities in range of the suicider
|
||||
var entities = EntitySystem.Get<EntityLookupSystem>().GetEntitiesInRange(owner, 1, LookupFlags.Approximate | LookupFlags.Anchored).ToArray();
|
||||
|
||||
if (entities.Length > 0)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
if (_entities.HasComponent<SharedItemComponent>(entity))
|
||||
continue;
|
||||
var suicide = _entities.GetComponents<ISuicideAct>(entity).FirstOrDefault();
|
||||
if (suicide != null)
|
||||
{
|
||||
DealDamage(suicide, chat, owner);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default suicide, bite your tongue
|
||||
var othersMessage = Loc.GetString("suicide-command-default-text-others",("name", owner));
|
||||
owner.PopupMessageOtherClients(othersMessage);
|
||||
|
||||
var selfMessage = Loc.GetString("suicide-command-default-text-self");
|
||||
owner.PopupMessage(selfMessage);
|
||||
|
||||
DamageSpecifier damage = new(IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("Bloodloss"), 200);
|
||||
EntitySystem.Get<DamageableSystem>().TryChangeDamage(owner, damage, true);
|
||||
|
||||
// Prevent the player from returning to the body.
|
||||
// Note that mind cannot be null because otherwise owner would be null.
|
||||
EntitySystem.Get<GameTicker>().OnGhostAttempt(mind!, false);
|
||||
EntitySystem.Get<SuicideSystem>().Suicide(shell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
150
Content.Server/Chat/SuicideSystem.cs
Normal file
150
Content.Server/Chat/SuicideSystem.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using Content.Server.Act;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Hands.Components;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Chat
|
||||
{
|
||||
public sealed class SuicideSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
|
||||
[Dependency] private readonly AdminLogSystem _adminLogSystem = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public void Suicide(IConsoleShell shell)
|
||||
{
|
||||
//TODO: Make this work without the console shell
|
||||
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (player == null)
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("shell-cannot-run-command-from-server"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
|
||||
return;
|
||||
var mind = player.ContentData()?.Mind;
|
||||
|
||||
// This check also proves mind not-null for at the end when the mob is ghosted.
|
||||
if (mind?.OwnedComponent?.Owner is not { Valid: true } owner)
|
||||
{
|
||||
shell.WriteLine("You don't have a mind!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Checks to see if the player is dead.
|
||||
if (EntityManager.TryGetComponent<MobStateComponent>(owner, out var mobState) && mobState.IsDead())
|
||||
{
|
||||
shell.WriteLine(Loc.GetString("suicide-command-already-dead"));
|
||||
return;
|
||||
}
|
||||
|
||||
//Checks to see if the CannotSuicide tag exits, ghosts instead.
|
||||
if (_tagSystem.HasTag(owner, "CannotSuicide"))
|
||||
{
|
||||
if (!_gameTicker.OnGhostAttempt(mind, true))
|
||||
{
|
||||
shell?.WriteLine("You can't ghost right now.");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: needs to check if the mob is actually alive
|
||||
//TODO: maybe set a suicided flag to prevent resurrection?
|
||||
|
||||
_adminLogSystem.Add(LogType.Suicide,
|
||||
$"{EntityManager.ToPrettyString(player.AttachedEntity.Value):player} is committing suicide");
|
||||
|
||||
var suicideEvent = new SuicideEvent(owner);
|
||||
// Held item suicide
|
||||
if (EntityManager.TryGetComponent(owner, out HandsComponent handsComponent)
|
||||
&& handsComponent.ActiveHandEntity is EntityUid item)
|
||||
{
|
||||
RaiseLocalEvent(item, suicideEvent, false);
|
||||
|
||||
if (suicideEvent.Handled)
|
||||
{
|
||||
ApplyDeath(owner, suicideEvent.Kind!.Value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get all entities in range of the suicider
|
||||
var entities = _entityLookupSystem.GetEntitiesInRange(owner, 1, LookupFlags.Approximate | LookupFlags.Anchored).ToArray();
|
||||
|
||||
if (entities.Length > 0)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
if (EntityManager.HasComponent<SharedItemComponent>(entity))
|
||||
continue;
|
||||
RaiseLocalEvent(entity, suicideEvent, false);
|
||||
|
||||
if (suicideEvent.Handled)
|
||||
{
|
||||
ApplyDeath(owner, suicideEvent.Kind!.Value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default suicide, bite your tongue
|
||||
var othersMessage = Loc.GetString("suicide-command-default-text-others", ("name", owner));
|
||||
owner.PopupMessageOtherClients(othersMessage);
|
||||
|
||||
var selfMessage = Loc.GetString("suicide-command-default-text-self");
|
||||
owner.PopupMessage(selfMessage);
|
||||
|
||||
ApplyDeath(owner, SuicideKind.Bloodloss);
|
||||
|
||||
// Prevent the player from returning to the body.
|
||||
// Note that mind cannot be null because otherwise owner would be null.
|
||||
_gameTicker.OnGhostAttempt(mind!, false);
|
||||
}
|
||||
|
||||
private void ApplyDeath(EntityUid target, SuicideKind kind)
|
||||
{
|
||||
if (kind == SuicideKind.Special) return;
|
||||
// TODO SUICIDE ..heh.. anyway, someone should fix this mess.
|
||||
DamageSpecifier damage = new(kind switch
|
||||
{
|
||||
SuicideKind.Blunt => _prototypeManager.Index<DamageTypePrototype>("Blunt"),
|
||||
SuicideKind.Slash => _prototypeManager.Index<DamageTypePrototype>("Slash"),
|
||||
SuicideKind.Piercing => _prototypeManager.Index<DamageTypePrototype>("Piercing"),
|
||||
SuicideKind.Heat => _prototypeManager.Index<DamageTypePrototype>("Heat"),
|
||||
SuicideKind.Shock => _prototypeManager.Index<DamageTypePrototype>("Shock"),
|
||||
SuicideKind.Cold => _prototypeManager.Index<DamageTypePrototype>("Cold"),
|
||||
SuicideKind.Poison => _prototypeManager.Index<DamageTypePrototype>("Poison"),
|
||||
SuicideKind.Radiation => _prototypeManager.Index<DamageTypePrototype>("Radiation"),
|
||||
SuicideKind.Asphyxiation => _prototypeManager.Index<DamageTypePrototype>("Asphyxiation"),
|
||||
SuicideKind.Bloodloss => _prototypeManager.Index<DamageTypePrototype>("Bloodloss"),
|
||||
_ => _prototypeManager.Index<DamageTypePrototype>("Blunt")
|
||||
},
|
||||
200);
|
||||
|
||||
_damageableSystem.TryChangeDamage(target, damage, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,11 @@
|
||||
using Content.Server.Act;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.Kitchen.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using System.Threading;
|
||||
|
||||
namespace Content.Server.Kitchen.Components
|
||||
{
|
||||
[RegisterComponent, Friend(typeof(KitchenSpikeSystem))]
|
||||
public sealed class KitchenSpikeComponent : SharedKitchenSpikeComponent, ISuicideAct
|
||||
public sealed class KitchenSpikeComponent : SharedKitchenSpikeComponent
|
||||
{
|
||||
public List<string>? PrototypesToSpawn;
|
||||
|
||||
@@ -30,17 +22,5 @@ namespace Content.Server.Kitchen.Components
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// ECS this out!, Handleable SuicideEvent?
|
||||
SuicideKind ISuicideAct.Suicide(EntityUid victim, IChatManager chat)
|
||||
{
|
||||
var othersMessage = Loc.GetString("comp-kitchen-spike-suicide-other", ("victim", victim));
|
||||
victim.PopupMessageOtherClients(othersMessage);
|
||||
|
||||
var selfMessage = Loc.GetString("comp-kitchen-spike-suicide-self");
|
||||
victim.PopupMessage(selfMessage);
|
||||
|
||||
return SuicideKind.Piercing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ using Robust.Shared.Player;
|
||||
namespace Content.Server.Kitchen.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class MicrowaveComponent : SharedMicrowaveComponent, ISuicideAct
|
||||
public sealed class MicrowaveComponent : SharedMicrowaveComponent
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
|
||||
@@ -98,6 +98,12 @@ namespace Content.Server.Kitchen.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCookTime(uint cookTime)
|
||||
{
|
||||
_currentCookTimerTime = cookTime;
|
||||
UIDirty = true;
|
||||
}
|
||||
|
||||
private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage message)
|
||||
{
|
||||
if (!Powered || _busy)
|
||||
@@ -193,7 +199,7 @@ namespace Content.Server.Kitchen.Components
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
// ReSharper disable once IdentifierTypo
|
||||
private void Wzhzhzh()
|
||||
public void Wzhzhzh()
|
||||
{
|
||||
if (!HasContents)
|
||||
{
|
||||
@@ -439,60 +445,10 @@ namespace Content.Server.Kitchen.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ClickSound()
|
||||
public void ClickSound()
|
||||
{
|
||||
SoundSystem.Play(Filter.Pvs(Owner), _clickSound.GetSound(), Owner, AudioParams.Default.WithVolume(-2f));
|
||||
}
|
||||
|
||||
SuicideKind ISuicideAct.Suicide(EntityUid victim, IChatManager chat)
|
||||
{
|
||||
var headCount = 0;
|
||||
|
||||
if (_entities.TryGetComponent<SharedBodyComponent?>(victim, out var body))
|
||||
{
|
||||
var headSlots = body.GetSlotsOfType(BodyPartType.Head);
|
||||
|
||||
foreach (var slot in headSlots)
|
||||
{
|
||||
var part = slot.Part;
|
||||
|
||||
if (part == null ||
|
||||
!body.TryDropPart(slot, out var dropped))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var droppedPart in dropped.Values)
|
||||
{
|
||||
if (droppedPart.PartType != BodyPartType.Head)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Storage.Insert(droppedPart.Owner);
|
||||
headCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var othersMessage = headCount > 1
|
||||
? Loc.GetString("microwave-component-suicide-multi-head-others-message", ("victim", victim))
|
||||
: Loc.GetString("microwave-component-suicide-others-message", ("victim", victim));
|
||||
|
||||
victim.PopupMessageOtherClients(othersMessage);
|
||||
|
||||
var selfMessage = headCount > 1
|
||||
? Loc.GetString("microwave-component-suicide-multi-head-message")
|
||||
: Loc.GetString("microwave-component-suicide-message");
|
||||
|
||||
victim.PopupMessage(selfMessage);
|
||||
|
||||
_currentCookTimerTime = 10;
|
||||
ClickSound();
|
||||
UIDirty = true;
|
||||
Wzhzhzh();
|
||||
return SuicideKind.Heat;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BeingMicrowavedEvent : HandledEntityEventArgs
|
||||
|
||||
@@ -15,6 +15,8 @@ using System;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Shared.Random;
|
||||
using static Content.Shared.Kitchen.Components.SharedKitchenSpikeComponent;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Popups;
|
||||
|
||||
namespace Content.Server.Kitchen.EntitySystems
|
||||
{
|
||||
@@ -35,6 +37,20 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
//DoAfter
|
||||
SubscribeLocalEvent<KitchenSpikeComponent, SpikingFinishedEvent>(OnSpikingFinished);
|
||||
SubscribeLocalEvent<KitchenSpikeComponent, SpikingFailEvent>(OnSpikingFail);
|
||||
|
||||
SubscribeLocalEvent<KitchenSpikeComponent, SuicideEvent>(OnSuicide);
|
||||
}
|
||||
|
||||
private void OnSuicide(EntityUid uid, KitchenSpikeComponent component, SuicideEvent args)
|
||||
{
|
||||
if (args.Handled) return;
|
||||
args.SetHandled(SuicideKind.Piercing);
|
||||
var victim = args.Victim;
|
||||
var othersMessage = Loc.GetString("comp-kitchen-spike-suicide-other", ("victim", victim));
|
||||
victim.PopupMessageOtherClients(othersMessage);
|
||||
|
||||
var selfMessage = Loc.GetString("comp-kitchen-spike-suicide-self");
|
||||
victim.PopupMessage(selfMessage);
|
||||
}
|
||||
|
||||
private void OnSpikingFail(EntityUid uid, KitchenSpikeComponent component, SpikingFailEvent args)
|
||||
|
||||
@@ -7,6 +7,10 @@ using Content.Shared.Item;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using Robust.Shared.Player;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Popups;
|
||||
|
||||
namespace Content.Server.Kitchen.EntitySystems
|
||||
{
|
||||
@@ -21,6 +25,56 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
SubscribeLocalEvent<MicrowaveComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<MicrowaveComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<MicrowaveComponent, BreakageEventArgs>(OnBreak);
|
||||
SubscribeLocalEvent<MicrowaveComponent, SuicideEvent>(OnSuicide);
|
||||
}
|
||||
|
||||
private void OnSuicide(EntityUid uid, MicrowaveComponent component, SuicideEvent args)
|
||||
{
|
||||
if (args.Handled) return;
|
||||
args.SetHandled(SuicideKind.Heat);
|
||||
var victim = args.Victim;
|
||||
var headCount = 0;
|
||||
|
||||
if (TryComp<SharedBodyComponent?>(victim, out var body))
|
||||
{
|
||||
var headSlots = body.GetSlotsOfType(BodyPartType.Head);
|
||||
|
||||
foreach (var slot in headSlots)
|
||||
{
|
||||
var part = slot.Part;
|
||||
|
||||
if (part == null ||
|
||||
!body.TryDropPart(slot, out var dropped))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var droppedPart in dropped.Values)
|
||||
{
|
||||
if (droppedPart.PartType != BodyPartType.Head)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
component.Storage.Insert(droppedPart.Owner);
|
||||
headCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var othersMessage = headCount > 1
|
||||
? Loc.GetString("microwave-component-suicide-multi-head-others-message", ("victim", victim))
|
||||
: Loc.GetString("microwave-component-suicide-others-message", ("victim", victim));
|
||||
|
||||
victim.PopupMessageOtherClients(othersMessage);
|
||||
|
||||
var selfMessage = headCount > 1
|
||||
? Loc.GetString("microwave-component-suicide-multi-head-message")
|
||||
: Loc.GetString("microwave-component-suicide-message");
|
||||
|
||||
victim.PopupMessage(selfMessage);
|
||||
component.ClickSound();
|
||||
component.SetCookTime(10);
|
||||
component.Wzhzhzh();
|
||||
}
|
||||
|
||||
private void OnSolutionChange(EntityUid uid, MicrowaveComponent component, SolutionChangedEvent args)
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Content.Server.Morgue.Components
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
[ComponentReference(typeof(IStorageComponent))]
|
||||
#pragma warning disable 618
|
||||
public sealed class CrematoriumEntityStorageComponent : MorgueEntityStorageComponent, ISuicideAct
|
||||
public sealed class CrematoriumEntityStorageComponent : MorgueEntityStorageComponent
|
||||
#pragma warning restore 618
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
@@ -100,34 +100,5 @@ namespace Content.Server.Morgue.Components
|
||||
|
||||
}, _cremateCancelToken.Token);
|
||||
}
|
||||
|
||||
SuicideKind ISuicideAct.Suicide(EntityUid victim, IChatManager chat)
|
||||
{
|
||||
if (_entities.TryGetComponent(victim, out ActorComponent? actor) && actor.PlayerSession.ContentData()?.Mind is {} mind)
|
||||
{
|
||||
EntitySystem.Get<GameTicker>().OnGhostAttempt(mind, false);
|
||||
|
||||
if (mind.OwnedEntity is {Valid: true} entity)
|
||||
{
|
||||
entity.PopupMessage(Loc.GetString("crematorium-entity-storage-component-suicide-message"));
|
||||
}
|
||||
}
|
||||
|
||||
victim.PopupMessageOtherClients(Loc.GetString("crematorium-entity-storage-component-suicide-message-others", ("victim", victim)));
|
||||
|
||||
if (CanInsert(victim))
|
||||
{
|
||||
Insert(victim);
|
||||
EntitySystem.Get<StandingStateSystem>().Down(victim, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_entities.DeleteEntity(victim);
|
||||
}
|
||||
|
||||
Cremate();
|
||||
|
||||
return SuicideKind.Heat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,22 @@ using Content.Shared.Examine;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Standing;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Morgue
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class MorgueSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly StandingStateSystem _stando = default!;
|
||||
|
||||
private float _accumulatedFrameTime;
|
||||
|
||||
@@ -19,9 +29,44 @@ namespace Content.Server.Morgue
|
||||
|
||||
SubscribeLocalEvent<CrematoriumEntityStorageComponent, GetVerbsEvent<AlternativeVerb>>(AddCremateVerb);
|
||||
SubscribeLocalEvent<CrematoriumEntityStorageComponent, ExaminedEvent>(OnCrematoriumExamined);
|
||||
SubscribeLocalEvent<CrematoriumEntityStorageComponent, SuicideEvent>(OnSuicide);
|
||||
SubscribeLocalEvent<MorgueEntityStorageComponent, ExaminedEvent>(OnMorgueExamined);
|
||||
}
|
||||
|
||||
private void OnSuicide(EntityUid uid, CrematoriumEntityStorageComponent component, SuicideEvent args)
|
||||
{
|
||||
if (args.Handled) return;
|
||||
args.SetHandled(SuicideKind.Heat);
|
||||
var victim = args.Victim;
|
||||
if (TryComp(victim, out ActorComponent? actor) && actor.PlayerSession.ContentData()?.Mind is { } mind)
|
||||
{
|
||||
_ticker.OnGhostAttempt(mind, false);
|
||||
|
||||
if (mind.OwnedEntity is { Valid: true } entity)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("crematorium-entity-storage-component-suicide-message"), entity, Filter.Pvs(entity, entityManager: EntityManager));
|
||||
}
|
||||
}
|
||||
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString("crematorium-entity-storage-component-suicide-message-others", ("victim", victim)),
|
||||
victim,
|
||||
Filter.Pvs(victim, entityManager: EntityManager).RemoveWhereAttachedEntity(e => e == victim));
|
||||
|
||||
if (component.CanInsert(victim))
|
||||
{
|
||||
component.Insert(victim);
|
||||
_stando.Down(victim, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
EntityManager.DeleteEntity(victim);
|
||||
}
|
||||
|
||||
component.Cremate();
|
||||
}
|
||||
|
||||
private void AddCremateVerb(EntityUid uid, CrematoriumEntityStorageComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || component.Cooking || component.Open)
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Content.Server.Recycling.Components
|
||||
// TODO: Add sound and safe beep
|
||||
[RegisterComponent]
|
||||
[Friend(typeof(RecyclerSystem))]
|
||||
public sealed class RecyclerComponent : Component, ISuicideAct
|
||||
public sealed class RecyclerComponent : Component
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||
|
||||
@@ -44,27 +44,6 @@ namespace Content.Server.Recycling.Components
|
||||
}
|
||||
}
|
||||
|
||||
SuicideKind ISuicideAct.Suicide(EntityUid victim, IChatManager chat)
|
||||
{
|
||||
if (_entMan.TryGetComponent(victim, out ActorComponent? actor) &&
|
||||
actor.PlayerSession.ContentData()?.Mind is { } mind)
|
||||
{
|
||||
EntitySystem.Get<GameTicker>().OnGhostAttempt(mind, false);
|
||||
mind.OwnedEntity?.PopupMessage(Loc.GetString("recycler-component-suicide-message"));
|
||||
}
|
||||
|
||||
victim.PopupMessageOtherClients(Loc.GetString("recycler-component-suicide-message-others",
|
||||
("victim", victim)));
|
||||
|
||||
if (_entMan.TryGetComponent<SharedBodyComponent?>(victim, out var body))
|
||||
{
|
||||
body.Gib(true);
|
||||
}
|
||||
|
||||
EntitySystem.Get<RecyclerSystem>().Bloodstain(this);
|
||||
return SuicideKind.Bloodloss;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default sound to play when recycling
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Recycling.Components;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Recycling;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Player;
|
||||
@@ -17,6 +23,8 @@ namespace Content.Server.Recycling
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambience = default!;
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly TagSystem _tags = default!;
|
||||
|
||||
private const float RecyclerSoundCooldown = 0.8f;
|
||||
@@ -25,6 +33,34 @@ namespace Content.Server.Recycling
|
||||
{
|
||||
SubscribeLocalEvent<RecyclerComponent, StartCollideEvent>(OnCollide);
|
||||
SubscribeLocalEvent<RecyclerComponent, GotEmaggedEvent>(OnEmagged);
|
||||
SubscribeLocalEvent<RecyclerComponent, SuicideEvent>(OnSuicide);
|
||||
}
|
||||
|
||||
private void OnSuicide(EntityUid uid, RecyclerComponent component, SuicideEvent args)
|
||||
{
|
||||
if (args.Handled) return;
|
||||
args.SetHandled(SuicideKind.Bloodloss);
|
||||
var victim = args.Victim;
|
||||
if (TryComp(victim, out ActorComponent? actor) &&
|
||||
actor.PlayerSession.ContentData()?.Mind is { } mind)
|
||||
{
|
||||
_ticker.OnGhostAttempt(mind, false);
|
||||
if (mind.OwnedEntity is { Valid: true } entity)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), entity, Filter.Pvs(entity, entityManager: EntityManager));
|
||||
}
|
||||
}
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("recycler-component-suicide-message-others", ("victim", victim)),
|
||||
victim,
|
||||
Filter.Pvs(victim, entityManager: EntityManager).RemoveWhereAttachedEntity(e => e == victim));
|
||||
|
||||
if (TryComp<SharedBodyComponent?>(victim, out var body))
|
||||
{
|
||||
body.Gib(true);
|
||||
}
|
||||
|
||||
Bloodstain(component);
|
||||
}
|
||||
|
||||
public void EnableRecycler(RecyclerComponent component)
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
using Content.Server.Act;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Shared.Sound;
|
||||
using Content.Shared.Tools;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Toilet
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class ToiletComponent : Component, ISuicideAct
|
||||
public sealed class ToiletComponent : Component
|
||||
{
|
||||
[DataField("pryLidTime")]
|
||||
public float PryLidTime = 1f;
|
||||
@@ -23,12 +19,5 @@ namespace Content.Server.Toilet
|
||||
public bool LidOpen = false;
|
||||
public bool IsSeatUp = false;
|
||||
public bool IsPrying = false;
|
||||
|
||||
// todo: move me to ECS
|
||||
SuicideKind ISuicideAct.Suicide(EntityUid victim, IChatManager chat)
|
||||
{
|
||||
return EntitySystem.Get<ToiletSystem>().Suicide(Owner, victim, this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Toilet;
|
||||
using Content.Shared.Tools.Components;
|
||||
using Robust.Shared.Audio;
|
||||
@@ -35,10 +36,16 @@ namespace Content.Server.Toilet
|
||||
SubscribeLocalEvent<ToiletComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<ToiletComponent, InteractHandEvent>(OnInteractHand);
|
||||
SubscribeLocalEvent<ToiletComponent, ExaminedEvent>(OnExamine);
|
||||
SubscribeLocalEvent<ToiletComponent, SuicideEvent>(OnSuicide);
|
||||
SubscribeLocalEvent<ToiletPryFinished>(OnToiletPried);
|
||||
SubscribeLocalEvent<ToiletPryInterrupted>(OnToiletInterrupt);
|
||||
}
|
||||
|
||||
private void OnSuicide(EntityUid uid, ToiletComponent component, SuicideEvent args)
|
||||
{
|
||||
Suicide(component.Owner, uid, component);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, ToiletComponent component, ComponentInit args)
|
||||
{
|
||||
EntityManager.EnsureComponent<SecretStashComponent>(uid);
|
||||
|
||||
39
Content.Shared/Interaction/Events/SuicideEvent.cs
Normal file
39
Content.Shared/Interaction/Events/SuicideEvent.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace Content.Shared.Interaction.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised Directed at an entity to check whether they will handle the suicide.
|
||||
/// </summary>
|
||||
public sealed class SuicideEvent : EntityEventArgs
|
||||
{
|
||||
public SuicideEvent(EntityUid victim)
|
||||
{
|
||||
Victim = victim;
|
||||
}
|
||||
public void SetHandled(SuicideKind kind)
|
||||
{
|
||||
if (Handled) throw new InvalidOperationException("Suicide was already handled");
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public SuicideKind? Kind { get; private set; }
|
||||
public EntityUid Victim { get; private set; }
|
||||
public bool Handled => Kind != null;
|
||||
}
|
||||
|
||||
public enum SuicideKind
|
||||
{
|
||||
Special, //Doesn't damage the mob, used for "weird" suicides like gibbing
|
||||
|
||||
//Damage type suicides
|
||||
Blunt,
|
||||
Slash,
|
||||
Piercing,
|
||||
Heat,
|
||||
Shock,
|
||||
Cold,
|
||||
Poison,
|
||||
Radiation,
|
||||
Asphyxiation,
|
||||
Bloodloss
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user