diff --git a/Content.Shared/Mobs/Components/MobStateComponent.cs b/Content.Shared/Mobs/Components/MobStateComponent.cs index 80a0674c96..29cf0fb5ad 100644 --- a/Content.Shared/Mobs/Components/MobStateComponent.cs +++ b/Content.Shared/Mobs/Components/MobStateComponent.cs @@ -2,31 +2,37 @@ using Content.Shared.Damage.Components; using Content.Shared.Mobs.Systems; using Robust.Shared.GameStates; -namespace Content.Shared.Mobs.Components +namespace Content.Shared.Mobs.Components; + +/// +/// When attached to an , +/// this component will handle critical and death behaviors for mobs. +/// Additionally, it handles sending effects to clients +/// (such as blur effect for unconsciousness) and managing the health HUD. +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(true)] +[Access(typeof(MobStateSystem), typeof(MobThresholdSystem))] +public sealed partial class MobStateComponent : Component { /// - /// When attached to an , - /// this component will handle critical and death behaviors for mobs. - /// Additionally, it handles sending effects to clients - /// (such as blur effect for unconsciousness) and managing the health HUD. + /// The current mob state the entity is in. /// - [RegisterComponent] - [NetworkedComponent] - [AutoGenerateComponentState] - [Access(typeof(MobStateSystem), typeof(MobThresholdSystem))] - public sealed partial class MobStateComponent : Component - { - //default mobstate is always the lowest state level - [AutoNetworkedField, ViewVariables] - public MobState CurrentState { get; set; } = MobState.Alive; + [DataField, AutoNetworkedField] + public MobState CurrentState = MobState.Alive; //default mobstate is always the lowest state level - [DataField] - [AutoNetworkedField] - public HashSet AllowedStates = new() - { - MobState.Alive, - MobState.Critical, - MobState.Dead - }; - } + /// + /// The last state that was received by the client + /// + [ViewVariables] + public MobState LastReceivedState = MobState.Alive; + + [DataField] + [AutoNetworkedField] + public HashSet AllowedStates = new() + { + MobState.Alive, + MobState.Critical, + MobState.Dead + }; } diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs b/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs index b389d67275..31942e57ac 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs @@ -33,7 +33,7 @@ public partial class MobStateSystem if (!_mobStateQuery.Resolve(entity, ref component)) return; - var ev = new UpdateMobStateEvent {Target = entity, Component = component, Origin = origin}; + var ev = new UpdateMobStateEvent { Target = entity, Component = component, Origin = origin }; RaiseLocalEvent(entity, ref ev); ChangeState(entity, component, ev.State, origin: origin); } diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index dcc9871af4..c876fb30ed 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -28,34 +28,20 @@ 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(CheckConcious); SubscribeLocalEvent(CheckAct); - SubscribeLocalEvent(OnSpeakAttempt); - SubscribeLocalEvent(OnEquipAttempt); SubscribeLocalEvent(CheckAct); - SubscribeLocalEvent(OnUnequipAttempt); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); - SubscribeLocalEvent(OnSleepAttempt); - SubscribeLocalEvent(OnCombatModeShouldHandInteract); - SubscribeLocalEvent(OnAttemptPacifiedAttack); - SubscribeLocalEvent(OnDamageModify); - SubscribeLocalEvent(OnAttemptToolRefine); - - SubscribeLocalEvent(OnUnbuckleAttempt); - - // Actions - SubscribeLocalEvent(OnMobStateActionAttempt); } + [SubscribeLocalEvent] private void OnUnbuckleAttempt(Entity ent, ref UnbuckleAttemptEvent args) { // TODO is this necessary? @@ -71,6 +57,7 @@ public partial class MobStateSystem RaiseLocalEvent(target, ref ev); } + [SubscribeLocalEvent] private void CheckConcious(Entity ent, ref ConsciousAttemptEvent args) { switch (ent.Comp.CurrentState) @@ -145,6 +132,7 @@ public partial class MobStateSystem } } + [SubscribeLocalEvent] private void OnAttemptToolRefine(Entity ent, ref AttemptToolRefineEvent args) { if (!IsDead(ent, ent)) @@ -155,12 +143,26 @@ public partial class MobStateSystem #region Event Subscribers + [SubscribeLocalEvent] + private void OnAfterAutoHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + if (ent.Comp.LastReceivedState == ent.Comp.CurrentState) + return; + + var ev = new MobStateChangedEvent(ent, ent.Comp, ent.Comp.LastReceivedState, ent.Comp.CurrentState); + OnStateChanged(ent, ent.Comp, ent.Comp.LastReceivedState, ent.Comp.CurrentState); + RaiseLocalEvent(ent, ev, true); + ent.Comp.LastReceivedState = ent.Comp.CurrentState; + } + + [SubscribeLocalEvent] private void OnSleepAttempt(EntityUid target, MobStateComponent component, ref TryingToSleepEvent args) { if (IsDead(target, component)) args.Cancelled = true; } + [SubscribeLocalEvent] 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. @@ -170,6 +172,7 @@ public partial class MobStateSystem args.Multiplier /= 2; } + [SubscribeLocalEvent] private void OnSpeakAttempt(EntityUid uid, MobStateComponent component, SpeakAttemptEvent args) { if (HasComp(uid)) @@ -192,6 +195,7 @@ public partial class MobStateSystem } } + [SubscribeLocalEvent] private void OnEquipAttempt(EntityUid target, MobStateComponent component, IsEquippingAttemptEvent args) { // is this a self-equip, or are they being stripped? @@ -199,6 +203,7 @@ public partial class MobStateSystem CheckAct(target, component, args); } + [SubscribeLocalEvent] private void OnUnequipAttempt(EntityUid target, MobStateComponent component, IsUnequippingAttemptEvent args) { // is this a self-equip, or are they being stripped? @@ -206,6 +211,7 @@ public partial class MobStateSystem CheckAct(target, component, args); } + [SubscribeLocalEvent] private void OnCombatModeShouldHandInteract(EntityUid uid, MobStateComponent component, ref CombatModeShouldHandInteractEvent args) { // Disallow empty-hand-interacting in combat mode @@ -214,16 +220,19 @@ public partial class MobStateSystem args.Cancelled = true; } + [SubscribeLocalEvent] private void OnAttemptPacifiedAttack(Entity ent, ref AttemptPacifiedAttackEvent args) { args.Cancelled = true; } + [SubscribeLocalEvent] private void OnDamageModify(Entity ent, ref DamageModifyEvent args) { args.Damage *= _damageable.UniversalMobDamageModifier; } + [SubscribeLocalEvent] private void OnMobStateActionAttempt(Entity ent, ref ActionAttemptEvent args) { if (_mobStateQuery.TryComp(args.User, out var mobState) && diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.cs b/Content.Shared/Mobs/Systems/MobStateSystem.cs index e5b516b54f..6fb08ba7a0 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.cs @@ -18,13 +18,11 @@ public partial class MobStateSystem : EntitySystem [Dependency] private IGameTiming _timing = default!; [Dependency] private DamageableSystem _damageable = default!; [Dependency] private SharedPopupSystem _popup = default!; - private ISawmill _sawmill = default!; [Dependency] private EntityQuery _mobStateQuery = default!; public override void Initialize() { - _sawmill = LogManager.GetSawmill("MobState"); base.Initialize(); SubscribeEvents(); }