From 310f6e14f1686a1e10a1d2caef144270d4dca2a4 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Tue, 8 Feb 2022 14:08:21 +1100 Subject: [PATCH] Portable flasher tweaks (#6517) --- Content.Client/Entry/IgnoredComponents.cs | 1 - .../Explosion/TriggerOnProximityComponent.cs | 6 ++ .../Explosion/TriggerSystem.Proximity.cs | 101 ++++++++++++++++++ Content.Client/Explosion/TriggerSystem.cs | 10 ++ .../Trigger/ProximityTriggerVisualizer.cs | 96 ----------------- .../Components/TriggerOnProximityComponent.cs | 3 +- .../EntitySystems/TriggerSystem.Proximity.cs | 29 ++--- .../SharedTriggerOnProximityComponent.cs | 6 ++ .../Entities/Objects/Weapons/security.yml | 8 +- 9 files changed, 145 insertions(+), 115 deletions(-) create mode 100644 Content.Client/Explosion/TriggerOnProximityComponent.cs create mode 100644 Content.Client/Explosion/TriggerSystem.Proximity.cs create mode 100644 Content.Client/Explosion/TriggerSystem.cs delete mode 100644 Content.Client/Trigger/ProximityTriggerVisualizer.cs create mode 100644 Content.Shared/Explosion/SharedTriggerOnProximityComponent.cs diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 828dfe6589..ec7baa6e5c 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -78,7 +78,6 @@ namespace Content.Client.Entry "BodyScanner", "Stunbaton", "Tool", - "TriggerOnProximity", "TilePrying", "RandomSpriteColor", "ConditionalSpawner", diff --git a/Content.Client/Explosion/TriggerOnProximityComponent.cs b/Content.Client/Explosion/TriggerOnProximityComponent.cs new file mode 100644 index 0000000000..e185c7948e --- /dev/null +++ b/Content.Client/Explosion/TriggerOnProximityComponent.cs @@ -0,0 +1,6 @@ +using Content.Shared.Explosion; + +namespace Content.Client.Explosion; + +[RegisterComponent, Friend(typeof(TriggerSystem))] +public sealed class TriggerOnProximityComponent : SharedTriggerOnProximityComponent {} diff --git a/Content.Client/Explosion/TriggerSystem.Proximity.cs b/Content.Client/Explosion/TriggerSystem.Proximity.cs new file mode 100644 index 0000000000..0e2142d8f2 --- /dev/null +++ b/Content.Client/Explosion/TriggerSystem.Proximity.cs @@ -0,0 +1,101 @@ +using Content.Client.Trigger; +using Content.Shared.Trigger; +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Shared.Animations; + +namespace Content.Client.Explosion; + +public sealed partial class TriggerSystem +{ + [Dependency] private readonly AnimationPlayerSystem _player = default!; + + /* + * Currently all of the appearance stuff is hardcoded for portable flashers + * If you ever add mines it shouldn't be hard to tweak it slightly + */ + + private const string AnimKey = "proximity"; + + private static readonly Animation _flasherAnimation = new Animation + { + Length = TimeSpan.FromSeconds(0.3f), + AnimationTracks = { + new AnimationTrackSpriteFlick + { + LayerKey = ProximityTriggerVisualLayers.Base, + KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame("flashing", 0f)} + }, + new AnimationTrackComponentProperty() + { + ComponentType = typeof(PointLightComponent), + InterpolationMode = AnimationInterpolationMode.Nearest, + Property = nameof(PointLightComponent.Radius), + KeyFrames = + { + new AnimationTrackProperty.KeyFrame(0.1f, 0), + new AnimationTrackProperty.KeyFrame(3f, 0.1f), + new AnimationTrackProperty.KeyFrame(0.1f, 0.5f) + } + } + } + }; + + private void InitializeProximity() + { + SubscribeLocalEvent(OnProximityInit); + SubscribeLocalEvent(OnProxAppChange); + SubscribeLocalEvent(OnProxAnimation); + } + + private void OnProxAnimation(EntityUid uid, TriggerOnProximityComponent component, AnimationCompletedEvent args) + { + if (!TryComp(uid, out var appearance)) return; + + // So animation doesn't get spammed if no server state comes in. + appearance.SetData(ProximityTriggerVisualState.State, ProximityTriggerVisuals.Inactive); + OnChangeData(uid, component, appearance); + } + + private void OnProximityInit(EntityUid uid, TriggerOnProximityComponent component, ComponentInit args) + { + EntityManager.EnsureComponent(uid); + } + + private void OnProxAppChange(EntityUid uid, TriggerOnProximityComponent component, AppearanceChangeEvent args) + { + OnChangeData(uid, component, args.Component); + } + + private void OnChangeData(EntityUid uid, TriggerOnProximityComponent component, AppearanceComponent appearance) + { + if (!TryComp(component.Owner, out var spriteComponent)) return; + + TryComp(component.Owner, out var player); + appearance.TryGetData(ProximityTriggerVisualState.State, out ProximityTriggerVisuals state); + + switch (state) + { + case ProximityTriggerVisuals.Inactive: + // Don't interrupt the flash animation + if (_player.HasRunningAnimation(uid, player, AnimKey)) return; + _player.Stop(uid, player, AnimKey); + spriteComponent.LayerSetState(ProximityTriggerVisualLayers.Base, "on"); + break; + case ProximityTriggerVisuals.Active: + if (_player.HasRunningAnimation(uid, player, AnimKey)) return; + _player.Play(uid, player, _flasherAnimation, AnimKey); + break; + case ProximityTriggerVisuals.Off: + default: + _player.Stop(uid, player, AnimKey); + spriteComponent.LayerSetState(ProximityTriggerVisualLayers.Base, "off"); + break; + } + } + + public enum ProximityTriggerVisualLayers : byte + { + Base, + } +} diff --git a/Content.Client/Explosion/TriggerSystem.cs b/Content.Client/Explosion/TriggerSystem.cs new file mode 100644 index 0000000000..e18569a18e --- /dev/null +++ b/Content.Client/Explosion/TriggerSystem.cs @@ -0,0 +1,10 @@ +namespace Content.Client.Explosion; + +public sealed partial class TriggerSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + InitializeProximity(); + } +} diff --git a/Content.Client/Trigger/ProximityTriggerVisualizer.cs b/Content.Client/Trigger/ProximityTriggerVisualizer.cs deleted file mode 100644 index b19cb06448..0000000000 --- a/Content.Client/Trigger/ProximityTriggerVisualizer.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using Content.Shared.Trigger; -using Robust.Client.Animations; -using Robust.Client.GameObjects; -using Robust.Shared.Animations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Serialization.Manager.Attributes; - -namespace Content.Client.Trigger -{ - public sealed class ProximityTriggerVisualizer : AppearanceVisualizer - { - [DataField("animationState")] - private string? _animationState; - - [DataField("duration")] - private float _animationDuration = 0.3f; - - private const string AnimKey = "proximity"; - - private static Animation _animation = default!; - - public override void InitializeEntity(EntityUid entityUid) - { - - base.InitializeEntity(entityUid); - - if (_animationState == null) return; - - IoCManager.Resolve().EnsureComponent(entityUid); - - _animation = new Animation - { - Length = TimeSpan.FromSeconds(_animationDuration), - AnimationTracks = {new AnimationTrackSpriteFlick - { - LayerKey = ProximityTriggerVisualLayers.Base, - KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(_animationState, 0f)} - - }, - new AnimationTrackComponentProperty() - { - ComponentType = typeof(PointLightComponent), - InterpolationMode = AnimationInterpolationMode.Nearest, - Property = nameof(PointLightComponent.Radius), - KeyFrames = - { - new AnimationTrackProperty.KeyFrame(0.1f, 0), - new AnimationTrackProperty.KeyFrame(3f, 0.1f), - new AnimationTrackProperty.KeyFrame(0.1f, 0.5f) - } - } - } - }; - } - - public override void OnChangeData(AppearanceComponent component) - { - base.OnChangeData(component); - var entityManager = IoCManager.Resolve(); - if (!entityManager.TryGetComponent(component.Owner, out SpriteComponent spriteComponent)) return; - - var animSystem = EntitySystem.Get(); - entityManager.TryGetComponent(component.Owner, out AnimationPlayerComponent? player); - component.TryGetData(ProximityTriggerVisualState.State, out ProximityTriggerVisuals state); - - switch (state) - { - case ProximityTriggerVisuals.Inactive: - if (player != null) - animSystem.Stop(player, AnimKey); - - spriteComponent.LayerSetState(ProximityTriggerVisualLayers.Base, "on"); - break; - case ProximityTriggerVisuals.Active: - /* TODO: Waiting on ECS OnChangeData so we can actually subscribe to the animation finishing properly. - if (_animationState == null || player == null || - animSystem.HasRunningAnimation(player, AnimKey)) return; - - animSystem.Play(player, _animation, AnimKey); - */ - break; - case ProximityTriggerVisuals.Off: - default: - spriteComponent.LayerSetState(ProximityTriggerVisualLayers.Base, "off"); - break; - } - } - } - - public enum ProximityTriggerVisualLayers : byte - { - Base, - } -} diff --git a/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs b/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs index f754b660d1..e174d853bd 100644 --- a/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs +++ b/Content.Server/Explosion/Components/TriggerOnProximityComponent.cs @@ -4,6 +4,7 @@ using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; using System.Collections.Generic; +using Content.Shared.Explosion; namespace Content.Server.Explosion.Components { @@ -12,7 +13,7 @@ namespace Content.Server.Explosion.Components /// Raises a whenever an entity collides with a fixture attached to the owner of this component. /// [RegisterComponent] - public sealed class TriggerOnProximityComponent : Component + public sealed class TriggerOnProximityComponent : SharedTriggerOnProximityComponent { public const string FixtureID = "trigger-on-proximity-fixture"; diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs index 0c38555d48..b1ed7eed33 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.Proximity.cs @@ -73,14 +73,11 @@ public sealed partial class TriggerSystem component.Colliding.Add(args.OtherFixture.Body); } - private void OnProximityEndCollide(EntityUid uid, TriggerOnProximityComponent component, EndCollideEvent args) + private static void OnProximityEndCollide(EntityUid uid, TriggerOnProximityComponent component, EndCollideEvent args) { if (args.OurFixture.ID != TriggerOnProximityComponent.FixtureID) return; component.Colliding.Remove(args.OtherFixture.Body); - - if (component.Colliding.Count == 0) - _activeProximities.Remove(component); } private void SetProximityAppearance(EntityUid uid, TriggerOnProximityComponent component) @@ -103,10 +100,14 @@ public sealed partial class TriggerSystem } else { - component.Accumulator = component.Cooldown; + component.Accumulator += component.Cooldown; + } + + if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComponent)) + { + appearanceComponent.SetData(ProximityTriggerVisualState.State, ProximityTriggerVisuals.Active); } - SetProximityAppearance(component.Owner, component); Trigger(component.Owner); } @@ -116,12 +117,6 @@ public sealed partial class TriggerSystem foreach (var comp in _activeProximities) { - if (!comp.Enabled) - { - toRemove.Add(comp); - continue; - } - MetaDataComponent? metadata = null; if (Deleted(comp.Owner, metadata)) @@ -130,12 +125,22 @@ public sealed partial class TriggerSystem continue; } + SetProximityAppearance(comp.Owner, comp); + if (Paused(comp.Owner, metadata)) continue; comp.Accumulator -= frameTime; if (comp.Accumulator > 0f) continue; + // Only remove it from accumulation when nothing colliding anymore. + if (!comp.Enabled || comp.Colliding.Count == 0) + { + comp.Accumulator = 0f; + toRemove.Add(comp); + continue; + } + // Alright now that we have no cd check everything in range. foreach (var colliding in comp.Colliding) diff --git a/Content.Shared/Explosion/SharedTriggerOnProximityComponent.cs b/Content.Shared/Explosion/SharedTriggerOnProximityComponent.cs new file mode 100644 index 0000000000..f3af003bf7 --- /dev/null +++ b/Content.Shared/Explosion/SharedTriggerOnProximityComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.Explosion; + +public abstract class SharedTriggerOnProximityComponent : Component +{ + +} diff --git a/Resources/Prototypes/Entities/Objects/Weapons/security.yml b/Resources/Prototypes/Entities/Objects/Weapons/security.yml index 6e9fd49400..346c5251bf 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/security.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/security.yml @@ -53,7 +53,7 @@ - type: entity name: portable flasher parent: BaseStructure - id: Portableflasher + id: PortableFlasher description: An ultrabright flashbulb with a proximity trigger, useful for making an area security-only. components: - type: SoundOnTrigger @@ -77,7 +77,7 @@ map: ["enum.ProximityTriggerVisualLayers.Base"] - type: InteractionOutline - type: Physics - - type: Fixtures + - type: Fixtures fixtures: - shape: !type:PhysShapeAabb @@ -90,9 +90,7 @@ - MobImpassable mass: 70 - type: Appearance - visuals: - - type: ProximityTriggerVisualizer - animationState: flashing + - type: AnimationPlayer - type: PointLight energy: 2.0 radius: 0