diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 05a0a7f1883..a02cbb6419f 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -2820,5 +2820,28 @@ public static readonly CVarDef /// public static readonly CVarDef UseDynamicHostname = CVarDef.Create("game.use_dynamic_hostname", false, CVar.SERVERONLY); + + #region SoftCrit + + /// + /// Used for basic Soft-Crit implementation. Entities are allowed to crawl when in crit, as this CVar intercepts the mover controller check for incapacitation, + /// and prevents it from stopping movement if this CVar is set to true and the user is Crit but Not Dead. This is only for movement, + /// you still can't stand up while crit, and you're still more or less helpless. + /// + public static readonly CVarDef AllowMovementWhileCrit = + CVarDef.Create("mobstate.allow_movement_while_crit", true, CVar.REPLICATED); + + public static readonly CVarDef AllowTalkingWhileCrit = + CVarDef.Create("mobstate.allow_talking_while_crit", true, CVar.REPLICATED); + + /// + /// Currently does nothing because I would have to figure out WHERE I would even put this check, and the mover controller is fairly complicated. + /// The goal is to make it so that attempting to move while in 'soft crit' can potentially cause further injury, causing you to die faster. Ideally there would be special + /// actions that can be performed in soft crit, such as applying pressure to your own injuries to slow down the bleedout, or other varieties of "Will To Live". + /// + public static readonly CVarDef DamageWhileCritMove = + CVarDef.Create("mobstate.damage_while_crit_move", false, CVar.REPLICATED); + + #endregion } } diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index 2088bd4161e..3728813406c 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -1,5 +1,6 @@ using Content.Shared.Bed.Sleep; using Content.Shared.Buckle.Components; +using Content.Shared.CCVar; using Content.Shared.CombatMode.Pacification; using Content.Shared.Damage.ForceSay; using Content.Shared.Emoting; @@ -16,17 +17,20 @@ using Content.Shared.Standing; using Content.Shared.Strip.Components; using Content.Shared.Throwing; +using Robust.Shared.Configuration; using Robust.Shared.Physics.Components; namespace Content.Shared.Mobs.Systems; public partial class MobStateSystem { + [Dependency] private readonly IConfigurationManager _configurationManager = default!; + //General purpose event subscriptions. If you can avoid it register these events inside their own systems private void SubscribeEvents() { SubscribeLocalEvent(OnGettingStripped); - SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(OnDirectionAttempt); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); @@ -38,7 +42,7 @@ private void SubscribeEvents() SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); - SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(OnMoveAttempt); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(OnSleepAttempt); @@ -48,6 +52,23 @@ private void SubscribeEvents() SubscribeLocalEvent(OnUnbuckleAttempt); } + private void OnDirectionAttempt(Entity ent, ref ChangeDirectionAttemptEvent args) + { + if (ent.Comp.CurrentState is MobState.Critical && _configurationManager.GetCVar(CCVars.AllowMovementWhileCrit)) + return; + + CheckAct(ent.Owner, ent.Comp, args); + } + + private void OnMoveAttempt(Entity ent, ref UpdateCanMoveEvent args) + { + if (ent.Comp.CurrentState is MobState.Critical && _configurationManager.GetCVar(CCVars.AllowMovementWhileCrit)) + return; + + CheckAct(ent.Owner, ent.Comp, args); + } + + private void OnUnbuckleAttempt(Entity ent, ref UnbuckleAttemptEvent args) { // TODO is this necessary? @@ -145,6 +166,9 @@ private void OnSpeakAttempt(EntityUid uid, MobStateComponent component, SpeakAtt return; } + if (component.CurrentState is MobState.Critical && _configurationManager.GetCVar(CCVars.AllowTalkingWhileCrit)) + return; + CheckAct(uid, component, args); } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index 1c097ce17bc..2ea60155570 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -305,8 +305,11 @@ private void HandleDirChange(EntityUid entity, Direction dir, ushort subTick, bo if (MoverQuery.TryGetComponent(entity, out var mover)) SetMoveInput(mover, MoveButtons.None); - if (!_mobState.IsIncapacitated(entity)) - HandleDirChange(relayMover.RelayEntity, dir, subTick, state); + if (_mobState.IsDead(entity) + || _mobState.IsCritical(entity) && !_configManager.GetCVar(CCVars.AllowMovementWhileCrit)) + return; + + HandleDirChange(relayMover.RelayEntity, dir, subTick, state); return; } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 43a63068cf2..46ee949a4e2 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -125,9 +125,10 @@ protected void HandleMobMovement( var canMove = mover.CanMove; if (RelayTargetQuery.TryGetComponent(uid, out var relayTarget)) { - if (_mobState.IsIncapacitated(relayTarget.Source) || - TryComp(relayTarget.Source, out _) || - !MoverQuery.TryGetComponent(relayTarget.Source, out var relayedMover)) + if (_mobState.IsDead(relayTarget.Source) + || TryComp(relayTarget.Source, out _) + || !MoverQuery.TryGetComponent(relayTarget.Source, out var relayedMover) + || _mobState.IsCritical(relayTarget.Source) && !_configManager.GetCVar(CCVars.AllowMovementWhileCrit)) { canMove = false; } diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 95604a1e21c..1e832dea293 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -8787,3 +8787,13 @@ Entries: id: 6591 time: '2024-12-22T19:57:10.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/1334 +- author: VMSolidus + changes: + - type: Add + message: >- + Added server config options for basic "Soft-Crit". When enabled, + characters who are critically injured can still slowly crawl, but are + otherwise still helpless and dying. + id: 6592 + time: '2024-12-26T03:50:10.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/1370