using Content.Shared.Bed.Sleep; using Content.Shared.Emoting; using Content.Shared.Hands; using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Mobs.Components; using Content.Shared.Movement.Events; using Content.Shared.Pulling.Events; using Content.Shared.Speech; using Content.Shared.Standing; using Content.Shared.Strip.Components; using Content.Shared.Throwing; using Robust.Shared.Physics.Components; namespace Content.Shared.Mobs.Systems; public partial class MobStateSystem { //General purpose event subscriptions. If you can avoid it register these events inside their own systems private void SubscribeEvents() { SubscribeLocalEvent(OnGettingStripped); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(OnEquipAttempt); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(OnUnequipAttempt); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(OnSleepAttempt); } private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state) { switch (state) { case MobState.Alive: //unused break; case MobState.Critical: _standing.Stand(target); break; case MobState.Dead: RemComp(target); _standing.Stand(target); if (!_standing.IsDown(target) && TryComp(target, out var physics)) { _physics.SetCanCollide(target, true, body: physics); } break; case MobState.Invalid: //unused break; default: throw new NotImplementedException(); } } private void OnStateEnteredSubscribers(EntityUid target, MobStateComponent component, MobState state) { _blocker.UpdateCanMove(target); //update movement anytime a state changes switch (state) { case MobState.Alive: _standing.Stand(target); _appearance.SetData(target, MobStateVisuals.State, MobState.Alive); break; case MobState.Critical: _standing.Down(target); _appearance.SetData(target, MobStateVisuals.State, MobState.Critical); break; case MobState.Dead: EnsureComp(target); _standing.Down(target); if (_standing.IsDown(target) && TryComp(target, out var physics)) { _physics.SetCanCollide(target, false, body: physics); } _appearance.SetData(target, MobStateVisuals.State, MobState.Dead); break; case MobState.Invalid: //unused; break; default: throw new NotImplementedException(); } } #region Event Subscribers private void OnSleepAttempt(EntityUid target, MobStateComponent component, ref TryingToSleepEvent args) { if (IsDead(target, component)) args.Cancelled = true; } private void OnGettingStripped(EntityUid target, MobStateComponent component, BeforeGettingStrippedEvent args) { // Incapacitated or dead targets get stripped two or three times as fast. Makes stripping corpses less tedious. if (IsDead(target, component)) args.Multiplier /= 3; else if (IsCritical(target, component)) args.Multiplier /= 2; } private void CheckAct(EntityUid target, MobStateComponent component, CancellableEntityEventArgs args) { switch (component.CurrentState) { case MobState.Dead: case MobState.Critical: args.Cancel(); break; } } private void OnEquipAttempt(EntityUid target, MobStateComponent component, IsEquippingAttemptEvent args) { // is this a self-equip, or are they being stripped? if (args.Equipee == target) CheckAct(target, component, args); } private void OnUnequipAttempt(EntityUid target, MobStateComponent component, IsUnequippingAttemptEvent args) { // is this a self-equip, or are they being stripped? if (args.Unequipee == target) CheckAct(target, component, args); } #endregion }