Files
Delta-v/Content.Server/Chat/SuicideSystem.cs
T
CorynandJanet Blackquill cb62b27fcf Nubody (2/3) - ShitMed removal (#5844)
* Reapply "Nubody Merge" (#5807)

This reverts commit d62f7cef10.

* Revert "Nubody Merge (#5670)"

This reverts commit b465cfb3fd.

* Revert "IPC fibers (#4968)"

This reverts commit c2b42211f0.

* Revert "IPC Polymorph fix (#4545)"

This reverts commit fa03d8c655.

* Revert "fix IPC not having humanoid emotes (#4445)"

This reverts commit 216fdf999f.

* Revert "ipc heat/cold (#4306)"

This reverts commit fafd5cf816.

* Revert "ipc cables (#4283)"

This reverts commit 54958039a1.

* Revert "feat: ipcs now have dynamic power draw based off movement speed (#3917)"

This reverts commit 71e8b7e64b.

* Revert "fix ipcs not being able to disarm (#3374)"

This reverts commit 764c4dcf54.

* Revert "make steel heal caustic for ipcs (#3206)"

This reverts commit 450ac82550.

* Revert "add missing ipc survival boxes (#3065)"

This reverts commit 888c9cdb00.

* Revert "make borgs use ipc repairing (#3064)"

This reverts commit f77a49dd0b.

* Revert "Update hud.yml to add ipcs to diagnostic hud (#3019)"

This reverts commit 7220643531.

* Revert "Tweak IPCs (#2979)"

This reverts commit 98b47476de.

* Revert "fix nukies ipc test fail (#2957)"

This reverts commit 4a1acbf863.

* Revert "fix ipc nukies not getting comms (#2884)"

This reverts commit 8a2254770e.

* Revert "fix ipc encryption key mispredict (#2879)"

This reverts commit f08726efc1.

* Revert "Merge pull request #2800 from Spielern/port-ipc"

This reverts commit 822fa4312c, reversing
changes made to fe4c23c702.

* Remove and Fix rest of IPC Hangons causing crashes

* Integration test Errors

* Expand migration file with removed IPC stuff

* IPC Leg was found and migrated to naught

* Revert "Merge pull request #2542 from deltanedas/shitmed-ops"

This reverts commit 83a8002922, reversing
changes made to baa89b0052.

* Revert "Set up surgical augments infrastructure & add tool panel augments (#3059)"

This reverts commit a40f0be6fd.

* Revert "Psionic Prosthetics (#4689)"

This reverts commit 2679bb238a.

* Revert "Add surgical cleanliness and sanitation (#2847)"

This reverts commit 64565ba4f7.

* Remove unremoved mentions

* Revert "Add autoclave to easily sanitize large amounts of items and faster (#2933)"

This reverts commit d0da90fa2e.

* Shit Med Removed

* Remove _ShitMed Folders and fix Errors in Console

* Add OrganAnimalBrain into the mirgraiton file

* Heads no Input Mover

* Monke

* Full migration file I guess

* oops

* shiv state fix

* Restore accidental deleted recipe

* Forgot one flt mention

* Fix more issues

* Comment out Damage Visual for motorkind for now

* Motorkind...

* Commenting stuff out for now

* thought there'd be more of this to gut

---------

Co-authored-by: Janet Blackquill <uhhadd@gmail.com>
2026-05-21 20:27:04 -04:00

180 lines
7.1 KiB
C#

using Content.Server.Ghost;
using Content.Server.Hands.Systems;
using Content.Shared.Administration.Logs;
using Content.Shared.Chat;
using Content.Shared.Damage.Components;
using Content.Shared.Database;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Events;
using Content.Shared.Item;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Server.Chat;
public sealed class SuicideSystem : EntitySystem
{
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly GhostSystem _ghostSystem = default!;
[Dependency] private readonly SharedSuicideSystem _suicide = default!;
private static readonly ProtoId<TagPrototype> CannotSuicideTag = "CannotSuicide";
// private static readonly ProtoId<TagPrototype> CannotSuicideAny = "CannotSuicideAny"; // DeltaV / Goob, ProtoID Tag
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DamageableComponent, SuicideEvent>(OnDamageableSuicide);
SubscribeLocalEvent<MobStateComponent, SuicideEvent>(OnEnvironmentalSuicide);
SubscribeLocalEvent<MindContainerComponent, SuicideGhostEvent>(OnSuicideGhost);
}
/// <summary>
/// Calling this function will attempt to kill the user by suiciding on objects in the surrounding area
/// or by applying a lethal amount of damage to the user with the default method.
/// Used when writing /suicide
/// </summary>
public bool Suicide(EntityUid victim)
{
// Can't suicide if we're already dead
if (!TryComp<MobStateComponent>(victim, out var mobState) || _mobState.IsDead(victim, mobState) /*|| _tagSystem.HasTag(victim, CannotSuicideAny*/) // Goobstation - DeltaV Use ProtoId
return false;
_adminLogger.Add(LogType.Mind, $"{ToPrettyString(victim):player} is attempting to suicide");
ICommonSession? session = null;
if (TryComp<ActorComponent>(victim, out var actor))
session = actor.PlayerSession;
var suicideGhostEvent = new SuicideGhostEvent(victim);
RaiseLocalEvent(victim, suicideGhostEvent);
// Suicide is considered a fail if the user wasn't able to ghost
// Suiciding with the CannotSuicide tag will ghost the player but not kill the body
if (!suicideGhostEvent.Handled || _tagSystem.HasTag(victim, CannotSuicideTag))
return false;
return false; // DeltaV - Prevent Suicide. We allow the event to go out anyways in case anything relies on the event for a message or whatever.
// TODO: fix this
// This is a handled event, but the result is never used
// It looks like TriggerOnMobstateChange is supposed to prevent you from suiciding
var suicideEvent = new SuicideEvent(victim);
RaiseLocalEvent(victim, suicideEvent);
// Since the player is already dead the log will not contain their username.
if (session != null)
{
_adminLogger.Add(LogType.Mind, $"{session:player} suicided.");
}
else
{
_adminLogger.Add(LogType.Mind, $"{ToPrettyString(victim):player} suicided.");
}
return true;
}
/// <summary>
/// Event subscription created to handle the ghosting aspect relating to suicides
/// Mainly useful when you can raise an event in Shared and can't call Suicide() directly
/// </summary>
private void OnSuicideGhost(Entity<MindContainerComponent> victim, ref SuicideGhostEvent args)
{
if (args.Handled)
return;
if (victim.Comp.Mind == null)
return;
if (!TryComp<MindComponent>(victim.Comp.Mind, out var mindComponent))
return;
// CannotSuicide tag will allow the user to ghost, but also return to their mind
// This is kind of weird, not sure what it applies to?
if (_tagSystem.HasTag(victim, CannotSuicideTag))
args.CanReturnToBody = true;
if (_ghostSystem.OnGhostAttempt(victim.Comp.Mind.Value, args.CanReturnToBody, mind: mindComponent))
args.Handled = true;
}
/// <summary>
/// Raise event to attempt to use held item, or surrounding entities to attempt to commit suicide
/// </summary>
private void OnEnvironmentalSuicide(Entity<MobStateComponent> victim, ref SuicideEvent args)
{
if (args.Handled || _mobState.IsCritical(victim))
return;
var suicideByEnvironmentEvent = new SuicideByEnvironmentEvent(victim);
// Try to suicide by raising an event on the held item
if (_hands.TryGetActiveItem(victim.Owner, out var item))
{
RaiseLocalEvent(item.Value, suicideByEnvironmentEvent);
if (suicideByEnvironmentEvent.Handled)
{
args.Handled = suicideByEnvironmentEvent.Handled;
return;
}
}
// Try to suicide by nearby entities, like Microwaves or Crematoriums, by raising an event on it
// Returns upon being handled by any entity
var itemQuery = GetEntityQuery<ItemComponent>();
foreach (var entity in _entityLookupSystem.GetEntitiesInRange(victim, 1, LookupFlags.Approximate | LookupFlags.Static))
{
// Skip any nearby items that can be picked up, we already checked the active held item above
if (itemQuery.HasComponent(entity))
continue;
RaiseLocalEvent(entity, suicideByEnvironmentEvent);
if (!suicideByEnvironmentEvent.Handled)
continue;
args.Handled = suicideByEnvironmentEvent.Handled;
return;
}
}
/// <summary>
/// Default suicide behavior for any kind of entity that can take damage
/// </summary>
private void OnDamageableSuicide(Entity<DamageableComponent> victim, ref SuicideEvent args)
{
if (args.Handled)
return;
var othersMessage = Loc.GetString("suicide-command-default-text-others", ("name", Identity.Entity(victim, EntityManager)));
_popup.PopupEntity(othersMessage, victim, Filter.PvsExcept(victim), true);
var selfMessage = Loc.GetString("suicide-command-default-text-self");
_popup.PopupEntity(selfMessage, victim, victim);
if (args.DamageSpecifier != null)
{
_suicide.ApplyLethalDamage(victim, args.DamageSpecifier);
args.Handled = true;
return;
}
args.DamageType ??= "Bloodloss";
_suicide.ApplyLethalDamage(victim, args.DamageType);
args.Handled = true;
}
}