From 6c77801d906aaef15efeeca37866a503f71399ee Mon Sep 17 00:00:00 2001 From: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> Date: Mon, 8 Mar 2021 05:00:50 +0100 Subject: [PATCH] StunnableComponent cleanup, proper prediction for stuns and slips. (#3552) --- .../HUD/Inventory/ClientInventoryComponent.cs | 9 +- .../Components/Movement/SlipperyComponent.cs | 10 +- Content.Client/IgnoredComponents.cs | 1 - .../Components/GUI/InventoryComponent.cs | 11 +- .../Components/Mobs/StunnableComponent.cs | 87 ++-------- .../Components/Movement/SlipperyComponent.cs | 73 +------- .../Inventory/SharedInventoryComponent.cs | 1 + .../Mobs/SharedStunnableComponent.cs | 161 ++++++++++++++---- .../Components/Movement/NoSlipComponent.cs | 2 +- .../Movement/SharedSlipperyComponent.cs | 87 +++++++--- .../GameObjects/EntitySystems/StunSystem.cs | 6 +- .../Entities/Objects/Specific/janitor.yml | 14 +- Resources/Prototypes/Entities/puddle.yml | 7 +- 13 files changed, 243 insertions(+), 226 deletions(-) rename {Content.Server => Content.Shared}/GameObjects/Components/Movement/NoSlipComponent.cs (83%) rename {Content.Server => Content.Shared}/GameObjects/EntitySystems/StunSystem.cs (74%) diff --git a/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs b/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs index 26fea3fe28..1937dd4f2b 100644 --- a/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs +++ b/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Client.GameObjects.Components.Clothing; +using Content.Client.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Preferences.Appearance; using Robust.Client.GameObjects; using Robust.Shared.GameObjects; @@ -20,7 +22,7 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory /// [RegisterComponent] [ComponentReference(typeof(SharedInventoryComponent))] - public class ClientInventoryComponent : SharedInventoryComponent + public class ClientInventoryComponent : SharedInventoryComponent, IEffectBlocker { private readonly Dictionary _slots = new(); @@ -286,5 +288,10 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory return false; } + + bool IEffectBlocker.CanSlip() + { + return !TryGetSlot(Slots.SHOES, out var shoes) || shoes == null || EffectBlockerSystem.CanSlip(shoes); + } } } diff --git a/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs b/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs index fb1048fd17..d4cb93bd7e 100644 --- a/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs +++ b/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs @@ -14,11 +14,11 @@ namespace Content.Client.GameObjects.Components.Movement if (curState is not SlipperyComponentState state) return; - Slippery = state.Slippery; - IntersectPercentage = state.IntersectPercentage; - ParalyzeTime = state.ParalyzeTime; - RequiredSlipSpeed = state.RequiredSlipSpeed; - LaunchForwardsMultiplier = state.LaunchForwardsMultiplier; + _slippery = state.Slippery; + _intersectPercentage = state.IntersectPercentage; + _paralyzeTime = state.ParalyzeTime; + _requiredSlipSpeed = state.RequiredSlipSpeed; + _launchForwardsMultiplier = state.LaunchForwardsMultiplier; } } } diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index c2bb6cfe98..5800574408 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -114,7 +114,6 @@ namespace Content.Client "EmitSoundOnThrow", "Flash", "DamageOnToolInteract", - "NoSlip", "TrashSpawner", "Pill", "RCD", diff --git a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs index c338708ffa..790dae375b 100644 --- a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs @@ -32,7 +32,7 @@ namespace Content.Server.GameObjects.Components.GUI { [RegisterComponent] [ComponentReference(typeof(SharedInventoryComponent))] - public class InventoryComponent : SharedInventoryComponent, IExAct, IEffectBlocker, IPressureProtection + public class InventoryComponent : SharedInventoryComponent, IExAct, IPressureProtection, IEffectBlocker { [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; @@ -145,14 +145,7 @@ namespace Content.Server.GameObjects.Components.GUI bool IEffectBlocker.CanSlip() { - if (Owner.TryGetComponent(out InventoryComponent inventoryComponent) && - inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent shoes) - ) - { - return EffectBlockerSystem.CanSlip(shoes.Owner); - } - - return true; + return !TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent shoes) || EffectBlockerSystem.CanSlip(shoes.Owner); } public override void OnRemove() diff --git a/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs b/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs index 5c8593ff7d..5178385050 100644 --- a/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs @@ -7,6 +7,8 @@ using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Interfaces; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; @@ -29,17 +31,23 @@ namespace Content.Server.GameObjects.Components.Mobs EntitySystem.Get().Down(Owner); } + protected override void OnKnockdownEnd() + { + if(Owner.TryGetComponent(out IMobStateComponent? mobState) && !mobState.IsIncapacitated()) + EntitySystem.Get().Standing(Owner); + } + public void CancelAll() { - KnockdownTimer = 0f; - StunnedTimer = 0f; + KnockdownTimer = null; + StunnedTimer = null; Dirty(); } public void ResetStuns() { - StunnedTimer = 0f; - SlowdownTimer = 0f; + StunnedTimer = null; + SlowdownTimer = null; if (KnockedDown && Owner.TryGetComponent(out IMobStateComponent? mobState) && !mobState.IsIncapacitated()) @@ -47,85 +55,16 @@ namespace Content.Server.GameObjects.Components.Mobs EntitySystem.Get().Standing(Owner); } - KnockdownTimer = 0f; + KnockdownTimer = null; Dirty(); } - public void Update(float delta) - { - if (Stunned) - { - StunnedTimer -= delta; - - if (StunnedTimer <= 0) - { - StunnedTimer = 0f; - Dirty(); - } - } - - if (KnockedDown) - { - KnockdownTimer -= delta; - - if (KnockdownTimer <= 0f - && Owner.TryGetComponent(out IMobStateComponent? mobState) && !mobState.IsIncapacitated()) - { - EntitySystem.Get().Standing(Owner); - - KnockdownTimer = 0f; - Dirty(); - } - } - - if (SlowedDown) - { - SlowdownTimer -= delta; - - if (SlowdownTimer <= 0f) - { - SlowdownTimer = 0f; - - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement)) - { - movement.RefreshMovementSpeedModifiers(); - } - - Dirty(); - } - } - - if (!StunStart.HasValue || !StunEnd.HasValue || - !Owner.TryGetComponent(out ServerAlertsComponent? status)) - { - return; - } - - var start = StunStart.Value; - var end = StunEnd.Value; - - var length = (end - start).TotalSeconds; - var progress = (_gameTiming.CurTime - start).TotalSeconds; - - if (progress >= length) - { - Owner.SpawnTimer(250, () => status.ClearAlert(AlertType.Stun), StatusRemoveCancellation.Token); - LastStun = null; - } - } - protected override void OnInteractHand() { EntitySystem.Get() .PlayFromEntity("/Audio/Effects/thudswoosh.ogg", Owner, AudioHelpers.WithVariation(0.05f)); } - public override ComponentState GetComponentState(ICommonSession player) - { - return new StunnableComponentState(StunnedTimer, KnockdownTimer, SlowdownTimer, WalkModifierOverride, - RunModifierOverride); - } - bool IDisarmedAct.Disarmed(DisarmedActEventArgs eventArgs) { if (!IoCManager.Resolve().Prob(eventArgs.PushProbability)) diff --git a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs index 13914e77ca..98ec258aa6 100644 --- a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs @@ -12,81 +12,12 @@ namespace Content.Server.GameObjects.Components.Movement [ComponentReference(typeof(SharedSlipperyComponent))] public class SlipperyComponent : SharedSlipperyComponent { - private float _paralyzeTime = 2f; - private float _intersectPercentage = 0.3f; - private float _requiredSlipSpeed = 0f; - private bool _slippery; - private float _launchForwardsMultiplier = 1f; - /// /// Path to the sound to be played when a mob slips. /// [ViewVariables] [DataField("slipSound")] - private string SlipSound { get; set; } = "/Audio/Effects/slip.ogg"; - - /// - /// How many seconds the mob will be paralyzed for. - /// - [ViewVariables(VVAccess.ReadWrite)] - public override float ParalyzeTime - { - get => _paralyzeTime; - set - { - _paralyzeTime = value; - Dirty(); - } - } - - /// - /// Percentage of shape intersection for a slip to occur. - /// - [ViewVariables(VVAccess.ReadWrite)] - public override float IntersectPercentage - { - get => _intersectPercentage; - set - { - _intersectPercentage = value; - Dirty(); - } - } - - /// - /// Entities will only be slipped if their speed exceeds this limit. - /// - [ViewVariables(VVAccess.ReadWrite)] - public override float RequiredSlipSpeed - { - get => _requiredSlipSpeed; - set - { - _requiredSlipSpeed = value; - Dirty(); - } - } - - /// - /// Whether or not this component will try to slip entities. - /// - [ViewVariables(VVAccess.ReadWrite)] - public override bool Slippery - { - get => _slippery; - set - { - _slippery = value; - Dirty(); - } - } - - [ViewVariables(VVAccess.ReadWrite)] - public override float LaunchForwardsMultiplier - { - get => _launchForwardsMultiplier; - set => _launchForwardsMultiplier = value; - } + public string SlipSound { get; set; } = "/Audio/Effects/slip.ogg"; protected override void OnSlip() { @@ -99,7 +30,7 @@ namespace Content.Server.GameObjects.Components.Movement public override ComponentState GetComponentState(ICommonSession player) { - return new SlipperyComponentState(_paralyzeTime, _intersectPercentage, _requiredSlipSpeed, _launchForwardsMultiplier, _slippery); + return new SlipperyComponentState(ParalyzeTime, IntersectPercentage, RequiredSlipSpeed, LaunchForwardsMultiplier, Slippery); } } } diff --git a/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs b/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs index 9f1f27d911..e41b25f150 100644 --- a/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs +++ b/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Reflection; diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs index f38259cd0c..44ddbc7086 100644 --- a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs @@ -1,12 +1,15 @@ #nullable enable using System; +using System.Collections.Generic; using System.Threading; using Content.Shared.Alert; +using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Timing; @@ -22,17 +25,21 @@ namespace Content.Shared.GameObjects.Components.Mobs public sealed override string Name => "Stunnable"; public override uint? NetID => ContentNetIDs.STUNNABLE; - protected TimeSpan? LastStun; + public (TimeSpan Start, TimeSpan End)? StunnedTimer { get; protected set; } + public (TimeSpan Start, TimeSpan End)? KnockdownTimer { get; protected set; } + public (TimeSpan Start, TimeSpan End)? SlowdownTimer { get; protected set; } - [ViewVariables] protected TimeSpan? StunStart => LastStun; + [ViewVariables] public float StunnedSeconds => + StunnedTimer == null ? 0f : (float)(StunnedTimer.Value.End - StunnedTimer.Value.Start).TotalSeconds; + [ViewVariables] public float KnockdownSeconds => + KnockdownTimer == null ? 0f : (float)(KnockdownTimer.Value.End - KnockdownTimer.Value.Start).TotalSeconds; + [ViewVariables] public float SlowdownSeconds => + SlowdownTimer == null ? 0f : (float)(SlowdownTimer.Value.End - SlowdownTimer.Value.Start).TotalSeconds; - [ViewVariables] - protected TimeSpan? StunEnd => LastStun == null - ? (TimeSpan?) null - : _gameTiming.CurTime + - (TimeSpan.FromSeconds(Math.Max(StunnedTimer, Math.Max(KnockdownTimer, SlowdownTimer)))); - - private bool _canHelp = true; + [ViewVariables] public bool AnyStunActive => Stunned || KnockedDown || SlowedDown; + [ViewVariables] public bool Stunned => StunnedTimer != null; + [ViewVariables] public bool KnockedDown => KnockdownTimer != null; + [ViewVariables] public bool SlowedDown => SlowdownTimer != null; [DataField("stunCap")] protected float _stunCap = 20f; @@ -48,21 +55,15 @@ namespace Content.Shared.GameObjects.Components.Mobs [DataField("helpInterval")] private float _helpInterval = 1f; - protected float StunnedTimer; - protected float KnockdownTimer; - protected float SlowdownTimer; - [DataField("stunAlertId")] private string _stunAlertId = "stun"; + private bool _canHelp = true; + protected CancellationTokenSource StatusRemoveCancellation = new(); [ViewVariables] protected float WalkModifierOverride = 0f; [ViewVariables] protected float RunModifierOverride = 0f; - [ViewVariables] public bool Stunned => StunnedTimer > 0f; - [ViewVariables] public bool KnockedDown => KnockdownTimer > 0f; - [ViewVariables] public bool SlowedDown => SlowdownTimer > 0f; - private float StunTimeModifier { get @@ -118,15 +119,14 @@ namespace Content.Shared.GameObjects.Components.Mobs /// Whether or not the owner was stunned. public bool Stun(float seconds) { - seconds = MathF.Min(StunnedTimer + (seconds * StunTimeModifier), _stunCap); + seconds = MathF.Min(StunnedSeconds + (seconds * StunTimeModifier), _stunCap); if (seconds <= 0f) { return false; } - StunnedTimer = seconds; - LastStun = _gameTiming.CurTime; + StunnedTimer = (_gameTiming.CurTime, _gameTiming.CurTime.Add(TimeSpan.FromSeconds(seconds))); SetAlert(); OnStun(); @@ -145,15 +145,14 @@ namespace Content.Shared.GameObjects.Components.Mobs /// Whether or not the owner was knocked down. public bool Knockdown(float seconds) { - seconds = MathF.Min(KnockdownTimer + (seconds * KnockdownTimeModifier), _knockdownCap); + seconds = MathF.Min(KnockdownSeconds + (seconds * KnockdownTimeModifier), _knockdownCap); if (seconds <= 0f) { return false; } - KnockdownTimer = seconds; - LastStun = _gameTiming.CurTime; + KnockdownTimer = (_gameTiming.CurTime, _gameTiming.CurTime.Add(TimeSpan.FromSeconds(seconds)));; SetAlert(); OnKnockdown(); @@ -183,7 +182,7 @@ namespace Content.Shared.GameObjects.Components.Mobs /// Run speed modifier. Set to 0 or negative for default value. (0.5f) public void Slowdown(float seconds, float walkModifierOverride = 0f, float runModifierOverride = 0f) { - seconds = MathF.Min(SlowdownTimer + (seconds * SlowdownTimeModifier), _slowdownCap); + seconds = MathF.Min(SlowdownSeconds + (seconds * SlowdownTimeModifier), _slowdownCap); if (seconds <= 0f) return; @@ -191,8 +190,7 @@ namespace Content.Shared.GameObjects.Components.Mobs WalkModifierOverride = walkModifierOverride; RunModifierOverride = runModifierOverride; - SlowdownTimer = seconds; - LastStun = _gameTiming.CurTime; + SlowdownTimer = (_gameTiming.CurTime, _gameTiming.CurTime.Add(TimeSpan.FromSeconds(seconds))); if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement)) movement.RefreshMovementSpeedModifiers(); @@ -201,6 +199,44 @@ namespace Content.Shared.GameObjects.Components.Mobs Dirty(); } + private (TimeSpan, TimeSpan)? GetTimers() + { + // Don't do anything if no stuns are applied. + if (!AnyStunActive) + return null; + + TimeSpan start = TimeSpan.MaxValue, end = TimeSpan.MinValue; + + if (StunnedTimer != null) + { + if (StunnedTimer.Value.Start < start) + start = StunnedTimer.Value.Start; + + if (StunnedTimer.Value.End > end) + end = StunnedTimer.Value.End; + } + + if (KnockdownTimer != null) + { + if (KnockdownTimer.Value.Start < start) + start = KnockdownTimer.Value.Start; + + if (KnockdownTimer.Value.End > end) + end = KnockdownTimer.Value.End; + } + + if (SlowdownTimer != null) + { + if (SlowdownTimer.Value.Start < start) + start = SlowdownTimer.Value.Start; + + if (SlowdownTimer.Value.End > end) + end = SlowdownTimer.Value.End; + } + + return (start, end); + } + private void SetAlert() { if (!Owner.TryGetComponent(out SharedAlertsComponent? status)) @@ -208,8 +244,12 @@ namespace Content.Shared.GameObjects.Components.Mobs return; } - status.ShowAlert(AlertType.Stun, cooldown: - (StunStart == null || StunEnd == null) ? default : (StunStart.Value, StunEnd.Value)); + var timers = GetTimers(); + + if (timers == null) + return; + + status.ShowAlert(AlertType.Stun, cooldown:timers); StatusRemoveCancellation.Cancel(); StatusRemoveCancellation = new CancellationTokenSource(); } @@ -226,7 +266,7 @@ namespace Content.Shared.GameObjects.Components.Mobs _canHelp = false; Owner.SpawnTimer((int) _helpInterval * 1000, () => _canHelp = true); - KnockdownTimer -= _helpKnockdownRemove; + KnockdownTimer = (KnockdownTimer!.Value.Start, KnockdownTimer.Value.End.Subtract(TimeSpan.FromSeconds(_helpInterval))); OnInteractHand(); @@ -236,6 +276,59 @@ namespace Content.Shared.GameObjects.Components.Mobs return true; } + public override ComponentState GetComponentState(ICommonSession player) + { + return new StunnableComponentState(StunnedTimer, KnockdownTimer, SlowdownTimer, WalkModifierOverride, RunModifierOverride); + } + + protected virtual void OnKnockdownEnd() + { + } + + public void Update(float delta) + { + var curTime = _gameTiming.CurTime; + + if (StunnedTimer != null) + { + if (StunnedTimer.Value.End <= curTime) + { + StunnedTimer = null; + Dirty(); + } + } + + if (KnockdownTimer != null) + { + if (KnockdownTimer.Value.End <= curTime) + { + OnKnockdownEnd(); + + KnockdownTimer = null; + Dirty(); + } + } + + if (SlowdownTimer != null) + { + if (SlowdownTimer.Value.End <= curTime) + { + if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement)) + { + movement.RefreshMovementSpeedModifiers(); + } + + SlowdownTimer = null; + Dirty(); + } + } + + if (AnyStunActive || !Owner.TryGetComponent(out SharedAlertsComponent? status) || !status.IsShowingAlert(AlertType.Stun)) + return; + + status.ClearAlert(AlertType.Stun); + } + #region ActionBlockers public bool CanMove() => (!Stunned); @@ -273,13 +366,15 @@ namespace Content.Shared.GameObjects.Components.Mobs [Serializable, NetSerializable] protected sealed class StunnableComponentState : ComponentState { - public float StunnedTimer { get; } - public float KnockdownTimer { get; } - public float SlowdownTimer { get; } + public (TimeSpan Start, TimeSpan End)? StunnedTimer { get; } + public (TimeSpan Start, TimeSpan End)? KnockdownTimer { get; } + public (TimeSpan Start, TimeSpan End)? SlowdownTimer { get; } public float WalkModifierOverride { get; } public float RunModifierOverride { get; } - public StunnableComponentState(float stunnedTimer, float knockdownTimer, float slowdownTimer, float walkModifierOverride, float runModifierOverride) : base(ContentNetIDs.STUNNABLE) + public StunnableComponentState( + (TimeSpan Start, TimeSpan End)? stunnedTimer, (TimeSpan Start, TimeSpan End)? knockdownTimer, + (TimeSpan Start, TimeSpan End)? slowdownTimer, float walkModifierOverride, float runModifierOverride) : base(ContentNetIDs.STUNNABLE) { StunnedTimer = stunnedTimer; KnockdownTimer = knockdownTimer; diff --git a/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs b/Content.Shared/GameObjects/Components/Movement/NoSlipComponent.cs similarity index 83% rename from Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs rename to Content.Shared/GameObjects/Components/Movement/NoSlipComponent.cs index 57991581e4..d9ac35e5d8 100644 --- a/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/NoSlipComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Robust.Shared.GameObjects; -namespace Content.Server.GameObjects.Components.Movement +namespace Content.Shared.GameObjects.Components.Movement { [RegisterComponent] public class NoSlipComponent : Component, IEffectBlocker diff --git a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs index a336ea1674..64619da459 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs @@ -7,6 +7,7 @@ using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Physics; using Robust.Shared.Containers; using Robust.Shared.GameObjects; +using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision; using Robust.Shared.Serialization; @@ -19,6 +20,12 @@ namespace Content.Shared.GameObjects.Components.Movement { public sealed override string Name => "Slippery"; + protected float _paralyzeTime = 3f; + protected float _intersectPercentage = 0.3f; + protected float _requiredSlipSpeed = 0.1f; + protected float _launchForwardsMultiplier = 1f; + protected bool _slippery = true; + /// /// The list of entities that have been slipped by this component, /// and which have not stopped colliding with its owner yet. @@ -30,35 +37,85 @@ namespace Content.Shared.GameObjects.Components.Movement /// [ViewVariables(VVAccess.ReadWrite)] [DataField("paralyzeTime")] - public virtual float ParalyzeTime { get; set; } = 3f; + public float ParalyzeTime + { + get => _paralyzeTime; + set + { + if (MathHelper.CloseTo(_paralyzeTime, value)) return; + + _paralyzeTime = value; + Dirty(); + } + } /// /// Percentage of shape intersection for a slip to occur. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("intersectPercentage")] - public virtual float IntersectPercentage { get; set; } = 0.3f; + public float IntersectPercentage + { + get => _intersectPercentage; + set + { + if (MathHelper.CloseTo(_intersectPercentage, value)) return; + + _intersectPercentage = value; + Dirty(); + } + } /// /// Entities will only be slipped if their speed exceeds this limit. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("requiredSlipSpeed")] - public virtual float RequiredSlipSpeed { get; set; } = 0.1f; + public float RequiredSlipSpeed + { + get => _requiredSlipSpeed; + set + { + if (MathHelper.CloseTo(_requiredSlipSpeed, value)) return; + + _requiredSlipSpeed = value; + Dirty(); + } + } /// /// The entity's speed will be multiplied by this to slip it forwards. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("launchForwardsMultiplier")] - public virtual float LaunchForwardsMultiplier { get; set; } = 1f; + public float LaunchForwardsMultiplier + { + get => _launchForwardsMultiplier; + set + { + if (MathHelper.CloseTo(_launchForwardsMultiplier, value)) return; + + _launchForwardsMultiplier = value; + Dirty(); + } + } /// /// Whether or not this component will try to slip entities. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("slippery")] - public virtual bool Slippery { get; set; } = true; + public bool Slippery + { + get => _slippery; + set + { + if (_slippery == value) return; + + _slippery = value; + Dirty(); + } + } private bool TrySlip(IPhysBody ourBody, IPhysBody otherBody) { @@ -106,6 +163,9 @@ namespace Content.Shared.GameObjects.Components.Movement public void Update() { + if (!Slippery) + return; + foreach (var uid in _slipped.ToArray()) { if (!uid.IsValid() || !Owner.EntityManager.EntityExists(uid)) @@ -124,23 +184,6 @@ namespace Content.Shared.GameObjects.Components.Movement } } } - - public override void Initialize() - { - base.Initialize(); - - var physics = Owner.EnsureComponent(); - - physics.Hard = false; - - var fixtures = physics.Fixtures.FirstOrDefault(); - - if (fixtures != null) - { - fixtures.CollisionLayer |= (int) CollisionGroup.SmallImpassable; - fixtures.CollisionMask = (int) CollisionGroup.None; - } - } } [Serializable, NetSerializable] diff --git a/Content.Server/GameObjects/EntitySystems/StunSystem.cs b/Content.Shared/GameObjects/EntitySystems/StunSystem.cs similarity index 74% rename from Content.Server/GameObjects/EntitySystems/StunSystem.cs rename to Content.Shared/GameObjects/EntitySystems/StunSystem.cs index 7b76d61b05..c610538d4f 100644 --- a/Content.Server/GameObjects/EntitySystems/StunSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/StunSystem.cs @@ -1,8 +1,8 @@ -using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.GameObjects.Components.Mobs; using JetBrains.Annotations; using Robust.Shared.GameObjects; -namespace Content.Server.GameObjects.EntitySystems +namespace Content.Shared.GameObjects.EntitySystems { [UsedImplicitly] internal sealed class StunSystem : EntitySystem @@ -11,7 +11,7 @@ namespace Content.Server.GameObjects.EntitySystems { base.Update(frameTime); - foreach (var component in ComponentManager.EntityQuery(true)) + foreach (var component in ComponentManager.EntityQuery(true)) { component.Update(frameTime); } diff --git a/Resources/Prototypes/Entities/Objects/Specific/janitor.yml b/Resources/Prototypes/Entities/Objects/Specific/janitor.yml index 1a43a49a61..d0c944b33c 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/janitor.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/janitor.yml @@ -106,12 +106,18 @@ - type: Slippery paralyzeTime: 2.5 - type: Physics + bodyType: Dynamic + mass: 5 fixtures: - - shape: - !type:PhysShapeAabb + - shape: + !type:PhysShapeAabb bounds: "-0.3,-0.4,0.3,0.4" - layer: - - MobImpassable + layer: + - SmallImpassable + mask: + - SmallImpassable + - MobImpassable + hard: false - type: entity name: soap diff --git a/Resources/Prototypes/Entities/puddle.yml b/Resources/Prototypes/Entities/puddle.yml index e6df04d03b..9528e5c805 100644 --- a/Resources/Prototypes/Entities/puddle.yml +++ b/Resources/Prototypes/Entities/puddle.yml @@ -20,9 +20,12 @@ - shape: !type:PhysShapeAabb bounds: "-0.4,-0.4,0.4,0.4" - hard: false layer: - - MobImpassable + - SmallImpassable + mask: + - SmallImpassable + - MobImpassable + hard: false - type: entity name: puddle