From b5cf3cf2da78b26adc3a41c7115c480d475602ed Mon Sep 17 00:00:00 2001 From: zumorica Date: Thu, 14 May 2020 17:26:08 +0200 Subject: [PATCH] Adds stun status effect --- .../Components/Mobs/SpeciesVisualizer2D.cs | 4 +- .../Components/Mobs/StunnableComponent.cs | 67 ++++++++++++++++-- .../Weapon/Melee/StunbatonComponent.cs | 4 +- .../GameObjects/EntitySystems/StunSystem.cs | 1 + .../Mobs/SharedStatusEffectsComponent.cs | 1 + Resources/Audio/weapons/egloves.ogg | Bin 7045 -> 10878 bytes 6 files changed, 69 insertions(+), 8 deletions(-) diff --git a/Content.Client/GameObjects/Components/Mobs/SpeciesVisualizer2D.cs b/Content.Client/GameObjects/Components/Mobs/SpeciesVisualizer2D.cs index 1f80e7cbc6..2ea49471de 100644 --- a/Content.Client/GameObjects/Components/Mobs/SpeciesVisualizer2D.cs +++ b/Content.Client/GameObjects/Components/Mobs/SpeciesVisualizer2D.cs @@ -1,5 +1,6 @@ using System; using Content.Shared.GameObjects.Components.Mobs; +using Microsoft.CodeAnalysis.Completion; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Client.GameObjects.Components.Animations; @@ -39,7 +40,8 @@ namespace Content.Client.GameObjects.Components.Mobs return; } - animation.Stop("rotate"); + if (animation.HasRunningAnimation("rotate")) + animation.Stop("rotate"); animation.Play(new Animation { diff --git a/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs b/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs index 55cfce3e1f..11cc8a765d 100644 --- a/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs @@ -12,7 +12,9 @@ using Robust.Shared.Audio; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Timers; +using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; +using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; using Timer = Robust.Shared.Timers.Timer; @@ -22,11 +24,26 @@ namespace Content.Server.GameObjects.Components.Mobs [RegisterComponent] public class StunnableComponent : Component, IActionBlocker, IAttackHand, IMoveSpeedModifier { + public override string Name => "Stunnable"; + +#pragma warning disable 649 [Dependency] private IEntitySystemManager _entitySystemManager; - [Dependency] private ITimerManager _timerManager; + [Dependency] private IGameTiming _gameTiming; +#pragma warning restore 649 + + private TimeSpan? _lastStun; + + [ViewVariables] + public TimeSpan? StunStart => _lastStun; + + [ViewVariables] + public TimeSpan? StunEnd => _lastStun == null + ? (TimeSpan?) null + : _gameTiming.CurTime + TimeSpan.FromSeconds(_stunnedTimer + _knockdownTimer + _slowdownTimer); + + private const int StunLevels = 8; private bool _canHelp = true; - private float _stunCap = 20f; private float _knockdownCap = 20f; private float _slowdownCap = 20f; @@ -39,8 +56,7 @@ namespace Content.Server.GameObjects.Components.Mobs private float _walkModifierOverride = 0f; private float _runModifierOverride = 0f; - - public override string Name => "Stunnable"; + private readonly string[] _texturesStunOverlay = new string[StunLevels]; [ViewVariables] public bool Stunned => _stunnedTimer > 0f; [ViewVariables] public bool KnockedDown => _knockdownTimer > 0f; @@ -59,6 +75,16 @@ namespace Content.Server.GameObjects.Components.Mobs serializer.DataField(ref _helpKnockdownRemove, "helpKnockdownRemove", 1f); } + public override void Initialize() + { + base.Initialize(); + + for (var i = 0; i < StunLevels; i++) + { + _texturesStunOverlay[i] = $"/Textures/UserInterface/Inventory/cooldown-{i}.png"; + } + } + public void Stun(float seconds) { seconds = Math.Min(seconds + _stunnedTimer, _stunCap); @@ -66,6 +92,7 @@ namespace Content.Server.GameObjects.Components.Mobs StandingStateHelper.DropAllItemsInHands(Owner); _stunnedTimer = seconds; + _lastStun = _gameTiming.CurTime; } public void Knockdown(float seconds) @@ -75,6 +102,7 @@ namespace Content.Server.GameObjects.Components.Mobs StandingStateHelper.Down(Owner); _knockdownTimer = seconds; + _lastStun = _gameTiming.CurTime; } public void Paralyze(float seconds) @@ -91,6 +119,7 @@ namespace Content.Server.GameObjects.Components.Mobs _runModifierOverride = runModifierOverride; _slowdownTimer = seconds; + _lastStun = _gameTiming.CurTime; if(Owner.TryGetComponent(out MovementSpeedModifierComponent movement)) movement.RefreshMovementSpeedModifiers(); @@ -113,7 +142,7 @@ namespace Content.Server.GameObjects.Components.Mobs _canHelp = false; Timer.Spawn(((int)_helpInterval*1000), () => _canHelp = true); - IoCManager.Resolve().GetEntitySystem() + _entitySystemManager.GetEntitySystem() .Play("/Audio/effects/thudswoosh.ogg", Owner, AudioHelpers.WithVariation(0.25f)); _knockdownTimer -= _helpKnockdownRemove; @@ -157,6 +186,34 @@ namespace Content.Server.GameObjects.Components.Mobs movement.RefreshMovementSpeedModifiers(); } } + + if (!_lastStun.HasValue || !StunEnd.HasValue || !Owner.TryGetComponent(out ServerStatusEffectsComponent status)) + return; + + var start = _lastStun.Value; + var end = StunEnd.Value; + + var length = (end - start).TotalSeconds; + var progress = (_gameTiming.CurTime - start).TotalSeconds; + var ratio = (float)(progress / length); + + var textureIndex = CalculateStunLevel(ratio); + if (textureIndex == StunLevels) + { + _lastStun = null; + status.RemoveStatus(StatusEffect.Stun); + } + else + { + status.ChangeStatus(StatusEffect.Stun, _texturesStunOverlay[textureIndex]); + } + } + + private static int CalculateStunLevel(float stunValue) + { + var val = stunValue.Clamp(0, 1); + val *= StunLevels; + return (int)Math.Floor(val); } #region ActionBlockers diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs index 0e1fd5c599..9fccf2c3ad 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs @@ -51,7 +51,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee return; _entitySystemManager.GetEntitySystem() - .Play("/Audio/weapons/egloves.ogg", Owner, AudioHelpers.WithVariation(0.25f)); + .Play("/Audio/weapons/egloves.ogg", Owner.Transform.GridPosition, AudioHelpers.WithVariation(0.25f)); foreach (var entity in entities) { @@ -78,7 +78,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee else { _entitySystemManager.GetEntitySystem() - .Play(AudioHelpers.GetRandomFileFromSoundCollection("sparks"), Owner, AudioHelpers.WithVariation(0.25f)); + .Play(AudioHelpers.GetRandomFileFromSoundCollection("sparks"), Owner.Transform.GridPosition, AudioHelpers.WithVariation(0.25f)); item.EquippedPrefix = "on"; sprite.LayerSetState(0, "stunbaton_on"); diff --git a/Content.Server/GameObjects/EntitySystems/StunSystem.cs b/Content.Server/GameObjects/EntitySystems/StunSystem.cs index 8f742b8092..fea2a19502 100644 --- a/Content.Server/GameObjects/EntitySystems/StunSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/StunSystem.cs @@ -1,4 +1,5 @@ using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.GameObjects.Components.Mobs; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs index 48c2e1c2fd..482b24fc17 100644 --- a/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs @@ -32,5 +32,6 @@ namespace Content.Shared.GameObjects.Components.Mobs Health, Hunger, Thirst, + Stun, } } diff --git a/Resources/Audio/weapons/egloves.ogg b/Resources/Audio/weapons/egloves.ogg index 5df3a1498f1f0a444674093bd313cfeee428c1b5..bd92ec294e58929819eb872f8ca899c036e026d6 100644 GIT binary patch literal 10878 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 C*LVH^ literal 7045 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