]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Flash overlay rework and bugfixes (#27369)
authorslarticodefast <161409025+slarticodefast@users.noreply.github.com>
Sun, 2 Jun 2024 04:17:53 +0000 (06:17 +0200)
committerGitHub <noreply@github.com>
Sun, 2 Jun 2024 04:17:53 +0000 (00:17 -0400)
18 files changed:
Content.Client/Entry/EntryPoint.cs
Content.Client/Flash/FlashOverlay.cs
Content.Client/Flash/FlashSystem.cs
Content.Server/Flash/Components/DamagedByFlashingComponent.cs
Content.Server/Flash/Components/FlashImmunityComponent.cs
Content.Server/Flash/FlashSystem.cs
Content.Shared/Flash/Components/FlashComponent.cs
Content.Shared/Flash/Components/FlashedComponent.cs [new file with mode: 0644]
Content.Shared/Flash/FlashableComponent.cs [deleted file]
Content.Shared/Flash/SharedFlashSystem.cs
Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml
Resources/Prototypes/Entities/Mobs/NPCs/pets.yml
Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
Resources/Prototypes/Entities/Mobs/Species/base.yml
Resources/Prototypes/Entities/Objects/base_shadow.yml
Resources/Prototypes/status_effects.yml
Resources/Textures/Shaders/flashed_effect.swsl

index b28c6a11fbfbcb75d919f771c67e5791626e1ed1..51210a8a93d4660d236e182bf8dacf0424ce3066 100644 (file)
@@ -152,7 +152,6 @@ namespace Content.Client.Entry
             _parallaxManager.LoadDefaultParallax();
 
             _overlayManager.AddOverlay(new SingularityOverlay());
-            _overlayManager.AddOverlay(new FlashOverlay());
             _overlayManager.AddOverlay(new RadiationPulseOverlay());
             _chatManager.Initialize();
             _clientPreferencesManager.Initialize();
index fe9c888227ec34571884845a93a9798b6a2a61cf..9ea00275e842cc4d5b02931fcb50a4442d03a696 100644 (file)
@@ -1,12 +1,11 @@
-using System.Numerics;
+using Content.Shared.Flash;
+using Content.Shared.Flash.Components;
+using Content.Shared.StatusEffect;
 using Content.Client.Viewport;
 using Robust.Client.Graphics;
 using Robust.Client.State;
 using Robust.Client.Player;
 using Robust.Shared.Enums;
-using Robust.Shared.Graphics;
-using Robust.Shared.IoC;
-using Robust.Shared.Maths;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Timing;
 using SixLabors.ImageSharp.PixelFormats;
@@ -17,66 +16,87 @@ namespace Content.Client.Flash
     {
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
         [Dependency] private readonly IClyde _displayManager = default!;
-        [Dependency] private readonly IGameTiming _gameTiming = default!;
         [Dependency] private readonly IStateManager _stateManager = default!;
         [Dependency] private readonly IEntityManager _entityManager = default!;
         [Dependency] private readonly IPlayerManager _playerManager = default!;
+        [Dependency] private readonly IGameTiming _timing = default!;
+
+       private readonly StatusEffectsSystem _statusSys;
 
         public override OverlaySpace Space => OverlaySpace.WorldSpace;
         private readonly ShaderInstance _shader;
-        private double _startTime = -1;
-        private double _lastsFor = 1;
-        private Texture? _screenshotTexture;
+        public float PercentComplete = 0.0f;
+        public Texture? ScreenshotTexture;
 
         public FlashOverlay()
         {
             IoCManager.InjectDependencies(this);
-            _shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate();
+            _shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").InstanceUnique();
+            _statusSys = _entityManager.System<StatusEffectsSystem>();
         }
 
-        public void ReceiveFlash(double duration)
+        protected override void FrameUpdate(FrameEventArgs args)
+        {
+            var playerEntity = _playerManager.LocalEntity;
+
+            if (playerEntity == null)
+                return;
+
+            if (!_entityManager.HasComponent<FlashedComponent>(playerEntity)
+                || !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
+                return;
+
+            if (!_statusSys.TryGetTime(playerEntity.Value, SharedFlashSystem.FlashedKey, out var time, status))
+                return;
+
+            var curTime = _timing.CurTime;
+            var lastsFor = (float) (time.Value.Item2 - time.Value.Item1).TotalSeconds;
+            var timeDone = (float) (curTime - time.Value.Item1).TotalSeconds;
+
+            PercentComplete = timeDone / lastsFor;
+        }
+
+        public void ReceiveFlash()
         {
             if (_stateManager.CurrentState is IMainViewportState state)
             {
+                // take a screenshot
+                // note that the callback takes a while and ScreenshotTexture will be null the first few Draws
                 state.Viewport.Viewport.Screenshot(image =>
                 {
                     var rgba32Image = image.CloneAs<Rgba32>(SixLabors.ImageSharp.Configuration.Default);
-                    _screenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
+                    ScreenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
                 });
             }
-
-            _startTime = _gameTiming.CurTime.TotalSeconds;
-            _lastsFor = duration;
         }
 
-        protected override void Draw(in OverlayDrawArgs args)
+        protected override bool BeforeDraw(in OverlayDrawArgs args)
         {
             if (!_entityManager.TryGetComponent(_playerManager.LocalEntity, out EyeComponent? eyeComp))
-                return;
-
+                return false;
             if (args.Viewport.Eye != eyeComp.Eye)
-                return;
+                return false;
+
+            return PercentComplete < 1.0f;
+        }
 
-            var percentComplete = (float) ((_gameTiming.CurTime.TotalSeconds - _startTime) / _lastsFor);
-            if (percentComplete >= 1.0f)
+        protected override void Draw(in OverlayDrawArgs args)
+        {
+            if (ScreenshotTexture == null)
                 return;
 
             var worldHandle = args.WorldHandle;
+            _shader.SetParameter("percentComplete", PercentComplete);
             worldHandle.UseShader(_shader);
-            _shader.SetParameter("percentComplete", percentComplete);
-
-            if (_screenshotTexture != null)
-            {
-                worldHandle.DrawTextureRectRegion(_screenshotTexture, args.WorldBounds);
-            }
-
+            worldHandle.DrawTextureRectRegion(ScreenshotTexture, args.WorldBounds);
             worldHandle.UseShader(null);
         }
 
         protected override void DisposeBehavior()
         {
             base.DisposeBehavior();
-            _screenshotTexture = null;
+            ScreenshotTexture = null;
+            PercentComplete = 1.0f;
         }
     }
 }
index ad8f8b0b82bf5fddfbe2eacff61b296b550462e4..9a0579f6aa389696b63fb615a951ac78708f5985 100644 (file)
@@ -1,62 +1,67 @@
 using Content.Shared.Flash;
+using Content.Shared.Flash.Components;
+using Content.Shared.StatusEffect;
 using Robust.Client.Graphics;
 using Robust.Client.Player;
-using Robust.Shared.GameStates;
-using Robust.Shared.Timing;
+using Robust.Shared.Player;
 
-namespace Content.Client.Flash
+namespace Content.Client.Flash;
+
+public sealed class FlashSystem : SharedFlashSystem
 {
-    public sealed class FlashSystem : SharedFlashSystem
+    [Dependency] private readonly IPlayerManager _player = default!;
+    [Dependency] private readonly IOverlayManager _overlayMan = default!;
+
+    private FlashOverlay _overlay = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<FlashedComponent, ComponentInit>(OnInit);
+        SubscribeLocalEvent<FlashedComponent, ComponentShutdown>(OnShutdown);
+        SubscribeLocalEvent<FlashedComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
+        SubscribeLocalEvent<FlashedComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
+        SubscribeLocalEvent<FlashedComponent, StatusEffectAddedEvent>(OnStatusAdded);
+
+        _overlay = new();
+    }
+
+    private void OnPlayerAttached(EntityUid uid, FlashedComponent component, LocalPlayerAttachedEvent args)
     {
-        [Dependency] private readonly IGameTiming _gameTiming = default!;
-        [Dependency] private readonly IPlayerManager _playerManager = default!;
-        [Dependency] private readonly IOverlayManager _overlayManager = default!;
+        _overlayMan.AddOverlay(_overlay);
+    }
 
-        public override void Initialize()
+    private void OnPlayerDetached(EntityUid uid, FlashedComponent component, LocalPlayerDetachedEvent args)
+    {
+        _overlay.PercentComplete = 1.0f;
+        _overlay.ScreenshotTexture = null;
+        _overlayMan.RemoveOverlay(_overlay);
+    }
+
+    private void OnInit(EntityUid uid, FlashedComponent component, ComponentInit args)
+    {
+        if (_player.LocalEntity == uid)
         {
-            base.Initialize();
+            _overlayMan.AddOverlay(_overlay);
+        }
+    }
 
-            SubscribeLocalEvent<FlashableComponent, ComponentHandleState>(OnFlashableHandleState);
+    private void OnShutdown(EntityUid uid, FlashedComponent component, ComponentShutdown args)
+    {
+        if (_player.LocalEntity == uid)
+        {
+            _overlay.PercentComplete = 1.0f;
+            _overlay.ScreenshotTexture = null;
+            _overlayMan.RemoveOverlay(_overlay);
         }
+    }
 
-        private void OnFlashableHandleState(EntityUid uid, FlashableComponent component, ref ComponentHandleState args)
+    private void OnStatusAdded(EntityUid uid, FlashedComponent component, StatusEffectAddedEvent args)
+    {
+        if (_player.LocalEntity == uid && args.Key == FlashedKey)
         {
-            if (args.Current is not FlashableComponentState state)
-                return;
-
-            // Yes, this code is awful. I'm just porting it to an entity system so don't blame me.
-            if (_playerManager.LocalEntity != uid)
-            {
-                return;
-            }
-
-            if (state.Time == default)
-            {
-                return;
-            }
-
-            // Few things here:
-            // 1. If a shorter duration flash is applied then don't do anything
-            // 2. If the client-side time is later than when the flash should've ended don't do anything
-            var currentTime = _gameTiming.CurTime.TotalSeconds;
-            var newEndTime = state.Time.TotalSeconds + state.Duration;
-            var currentEndTime = component.LastFlash.TotalSeconds + component.Duration;
-
-            if (currentEndTime > newEndTime)
-            {
-                return;
-            }
-
-            if (currentTime > newEndTime)
-            {
-                return;
-            }
-
-            component.LastFlash = state.Time;
-            component.Duration = state.Duration;
-
-            var overlay = _overlayManager.GetOverlay<FlashOverlay>();
-            overlay.ReceiveFlash(component.Duration);
+            _overlay.ReceiveFlash();
         }
     }
 }
index 2a9024607d6a63c60b8e4356c56735bc047dbc18..ef33454295241235a752612fea0a5c83552aed2e 100644 (file)
@@ -3,7 +3,6 @@ using Robust.Shared.Prototypes;
 
 namespace Content.Server.Flash.Components;
 
-// Also needed FlashableComponent on entity to work
 [RegisterComponent, Access(typeof(DamagedByFlashingSystem))]
 public sealed partial class DamagedByFlashingComponent : Component
 {
@@ -11,5 +10,5 @@ public sealed partial class DamagedByFlashingComponent : Component
     /// damage from flashing
     /// </summary>
     [DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
-    public DamageSpecifier FlashDamage = new ();
+    public DamageSpecifier FlashDamage = new();
 }
index 80bbdd12828d710c24f3a75e7f4918fd53013210..a982a9059f0656f1190883ce672d93a40b8794cc 100644 (file)
@@ -1,10 +1,13 @@
-namespace Content.Server.Flash.Components
+namespace Content.Server.Flash.Components;
+
+/// <summary>
+///     Makes the entity immune to being flashed.
+///     When given to clothes in the "head", "eyes" or "mask" slot it protects the wearer.
+/// </summary>
+[RegisterComponent, Access(typeof(FlashSystem))]
+public sealed partial class FlashImmunityComponent : Component
 {
-    [RegisterComponent, Access(typeof(FlashSystem))]
-    public sealed partial class FlashImmunityComponent : Component
-    {
-        [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("enabled")]
-        public bool Enabled { get; set; } = true;
-    }
+    [ViewVariables(VVAccess.ReadWrite)]
+    [DataField("enabled")]
+    public bool Enabled { get; set; } = true;
 }
index dd8cdab426cbd16508c34c21350ec7887ff3b383..ccb58e94f81426ea49b35cc5f4c27d9e1389583b 100644 (file)
@@ -9,18 +9,17 @@ using Content.Shared.Charges.Systems;
 using Content.Shared.Eye.Blinding.Components;
 using Content.Shared.Flash;
 using Content.Shared.IdentityManagement;
-using Content.Shared.Interaction;
 using Content.Shared.Interaction.Events;
 using Content.Shared.Inventory;
-using Content.Shared.Physics;
 using Content.Shared.Tag;
 using Content.Shared.Traits.Assorted;
 using Content.Shared.Weapons.Melee.Events;
+using Content.Shared.StatusEffect;
+using Content.Shared.Examine;
 using Robust.Server.Audio;
 using Robust.Server.GameObjects;
 using Robust.Shared.Audio;
 using Robust.Shared.Random;
-using Robust.Shared.Timing;
 using InventoryComponent = Content.Shared.Inventory.InventoryComponent;
 
 namespace Content.Server.Flash
@@ -31,14 +30,14 @@ namespace Content.Server.Flash
         [Dependency] private readonly AudioSystem _audio = default!;
         [Dependency] private readonly SharedChargesSystem _charges = default!;
         [Dependency] private readonly EntityLookupSystem _entityLookup = default!;
-        [Dependency] private readonly IGameTiming _timing = default!;
         [Dependency] private readonly SharedTransformSystem _transform = default!;
-        [Dependency] private readonly SharedInteractionSystem _interaction = default!;
+        [Dependency] private readonly ExamineSystemShared _examine = default!;
         [Dependency] private readonly InventorySystem _inventory = default!;
         [Dependency] private readonly PopupSystem _popup = default!;
         [Dependency] private readonly StunSystem _stun = default!;
         [Dependency] private readonly TagSystem _tag = default!;
         [Dependency] private readonly IRobustRandom _random = default!;
+        [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
 
         public override void Initialize()
         {
@@ -46,7 +45,7 @@ namespace Content.Server.Flash
 
             SubscribeLocalEvent<FlashComponent, MeleeHitEvent>(OnFlashMeleeHit);
             // ran before toggling light for extra-bright lantern
-            SubscribeLocalEvent<FlashComponent, UseInHandEvent>(OnFlashUseInHand, before: new []{ typeof(HandheldLightSystem) });
+            SubscribeLocalEvent<FlashComponent, UseInHandEvent>(OnFlashUseInHand, before: new[] { typeof(HandheldLightSystem) });
             SubscribeLocalEvent<InventoryComponent, FlashAttemptEvent>(OnInventoryFlashAttempt);
             SubscribeLocalEvent<FlashImmunityComponent, FlashAttemptEvent>(OnFlashImmunityFlashAttempt);
             SubscribeLocalEvent<PermanentBlindnessComponent, FlashAttemptEvent>(OnPermanentBlindnessFlashAttempt);
@@ -114,31 +113,18 @@ namespace Content.Server.Flash
             float flashDuration,
             float slowTo,
             bool displayPopup = true,
-            FlashableComponent? flashable = null,
             bool melee = false,
             TimeSpan? stunDuration = null)
         {
-            if (!Resolve(target, ref flashable, false))
-                return;
-
             var attempt = new FlashAttemptEvent(target, user, used);
             RaiseLocalEvent(target, attempt, true);
 
             if (attempt.Cancelled)
                 return;
 
-            if (melee)
-            {
-                var ev = new AfterFlashedEvent(target, user, used);
-                if (user != null)
-                    RaiseLocalEvent(user.Value, ref ev);
-                if (used != null)
-                    RaiseLocalEvent(used.Value, ref ev);
-            }
-
-            flashable.LastFlash = _timing.CurTime;
-            flashable.Duration = flashDuration / 1000f; // TODO: Make this sane...
-            Dirty(target, flashable);
+            // don't paralyze, slowdown or convert to rev if the target is immune to flashes
+            if (!_statusEffectsSystem.TryAddStatusEffect<FlashedComponent>(target, FlashedKey, TimeSpan.FromSeconds(flashDuration / 1000f), true))
+                return;
 
             if (stunDuration != null)
             {
@@ -146,7 +132,7 @@ namespace Content.Server.Flash
             }
             else
             {
-                _stun.TrySlowdown(target, TimeSpan.FromSeconds(flashDuration/1000f), true,
+                _stun.TrySlowdown(target, TimeSpan.FromSeconds(flashDuration / 1000f), true,
                 slowTo, slowTo);
             }
 
@@ -155,28 +141,40 @@ namespace Content.Server.Flash
                 _popup.PopupEntity(Loc.GetString("flash-component-user-blinds-you",
                     ("user", Identity.Entity(user.Value, EntityManager))), target, target);
             }
+
+            if (melee)
+            {
+                var ev = new AfterFlashedEvent(target, user, used);
+                if (user != null)
+                    RaiseLocalEvent(user.Value, ref ev);
+                if (used != null)
+                    RaiseLocalEvent(used.Value, ref ev);
+            }
         }
 
         public void FlashArea(Entity<FlashComponent?> source, EntityUid? user, float range, float duration, float slowTo = 0.8f, bool displayPopup = false, float probability = 1f, SoundSpecifier? sound = null)
         {
             var transform = Transform(source);
             var mapPosition = _transform.GetMapCoordinates(transform);
-            var flashableQuery = GetEntityQuery<FlashableComponent>();
+            var statusEffectsQuery = GetEntityQuery<StatusEffectsComponent>();
+            var damagedByFlashingQuery = GetEntityQuery<DamagedByFlashingComponent>();
 
             foreach (var entity in _entityLookup.GetEntitiesInRange(transform.Coordinates, range))
             {
                 if (!_random.Prob(probability))
                     continue;
 
-                if (!flashableQuery.TryGetComponent(entity, out var flashable))
+                // Is the entity affected by the flash either through status effects or by taking damage?
+                if (!statusEffectsQuery.HasComponent(entity) && !damagedByFlashingQuery.HasComponent(entity))
                     continue;
 
-                // Check for unobstructed entities while ignoring the mobs with flashable components.
-                if (!_interaction.InRangeUnobstructed(entity, mapPosition, range, flashable.CollisionGroup, predicate: (e) => flashableQuery.HasComponent(e) || e == source.Owner))
+                // Check for entites in view
+                // put damagedByFlashingComponent in the predicate because shadow anomalies block vision.
+                if (!_examine.InRangeUnOccluded(entity, mapPosition, range, predicate: (e) => damagedByFlashingQuery.HasComponent(e)))
                     continue;
 
                 // They shouldn't have flash removed in between right?
-                Flash(entity, user, source, duration, slowTo, displayPopup, flashableQuery.GetComponent(entity));
+                Flash(entity, user, source, duration, slowTo, displayPopup);
             }
 
             _audio.PlayPvs(sound, source, AudioParams.Default.WithVolume(1f).WithMaxDistance(3f));
@@ -195,13 +193,15 @@ namespace Content.Server.Flash
 
         private void OnFlashImmunityFlashAttempt(EntityUid uid, FlashImmunityComponent component, FlashAttemptEvent args)
         {
-            if(component.Enabled)
+            if (component.Enabled)
                 args.Cancel();
         }
 
         private void OnPermanentBlindnessFlashAttempt(EntityUid uid, PermanentBlindnessComponent component, FlashAttemptEvent args)
         {
-            args.Cancel();
+            // check for total blindness
+            if (component.Blindness == 0)
+                args.Cancel();
         }
 
         private void OnTemporaryBlindnessFlashAttempt(EntityUid uid, TemporaryBlindnessComponent component, FlashAttemptEvent args)
@@ -210,6 +210,10 @@ namespace Content.Server.Flash
         }
     }
 
+    /// <summary>
+    ///     Called before a flash is used to check if the attempt is cancelled by blindness, items or FlashImmunityComponent.
+    ///     Raised on the target hit by the flash, the user of the flash and the flash used.
+    /// </summary>
     public sealed class FlashAttemptEvent : CancellableEntityEventArgs
     {
         public readonly EntityUid Target;
@@ -224,8 +228,8 @@ namespace Content.Server.Flash
         }
     }
     /// <summary>
-    /// Called after a flash is used via melee on another person to check for rev conversion.
-    /// Raised on the user of the flash, the target hit by the flash, and the flash used.
+    ///     Called after a flash is used via melee on another person to check for rev conversion.
+    ///     Raised on the target hit by the flash, the user of the flash and the flash used.
     /// </summary>
     [ByRefEvent]
     public readonly struct AfterFlashedEvent
@@ -241,6 +245,4 @@ namespace Content.Server.Flash
             Used = used;
         }
     }
-
-
 }
index a9098bc85a9752e44fd93232d934826ccbc356bf..29f92eb94fc51d2cbcce5989af27811fa91eda6d 100644 (file)
@@ -1,6 +1,6 @@
-using Content.Shared.Flash;
 using Robust.Shared.Audio;
 using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
 
 namespace Content.Shared.Flash.Components
 {
@@ -43,4 +43,13 @@ namespace Content.Shared.Flash.Components
         [DataField]
         public float Probability = 1f;
     }
+
+    [Serializable, NetSerializable]
+    public enum FlashVisuals : byte
+    {
+        BaseLayer,
+        LightLayer,
+        Burnt,
+        Flashing,
+    }
 }
diff --git a/Content.Shared/Flash/Components/FlashedComponent.cs b/Content.Shared/Flash/Components/FlashedComponent.cs
new file mode 100644 (file)
index 0000000..75bbb12
--- /dev/null
@@ -0,0 +1,9 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Flash.Components;
+
+/// <summary>
+///     Exists for use as a status effect. Adds a shader to the client that obstructs vision.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class FlashedComponent : Component { }
diff --git a/Content.Shared/Flash/FlashableComponent.cs b/Content.Shared/Flash/FlashableComponent.cs
deleted file mode 100644 (file)
index c4f8074..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-using Content.Shared.Physics;
-using Robust.Shared.GameStates;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Flash
-{
-    [RegisterComponent, NetworkedComponent]
-    public sealed partial class FlashableComponent : Component
-    {
-        public float Duration;
-        public TimeSpan LastFlash;
-
-        [DataField]
-        public CollisionGroup CollisionGroup = CollisionGroup.Opaque;
-
-        public override bool SendOnlyToOwner => true;
-    }
-
-    [Serializable, NetSerializable]
-    public sealed class FlashableComponentState : ComponentState
-    {
-        public float Duration { get; }
-        public TimeSpan Time { get; }
-
-        public FlashableComponentState(float duration, TimeSpan time)
-        {
-            Duration = duration;
-            Time = time;
-        }
-    }
-
-    [Serializable, NetSerializable]
-    public enum FlashVisuals : byte
-    {
-        BaseLayer,
-        LightLayer,
-        Burnt,
-        Flashing,
-    }
-}
index 16fdbfc2f3e5bb6f4f305bbdf0bad0aa7ce1e281..f83f02a310586b84263f0ef25f93e5109708239a 100644 (file)
@@ -1,19 +1,10 @@
-using Robust.Shared.GameStates;
+using Content.Shared.StatusEffect;
 
 namespace Content.Shared.Flash
 {
     public abstract class SharedFlashSystem : EntitySystem
     {
-        public override void Initialize()
-        {
-            base.Initialize();
-
-            SubscribeLocalEvent<FlashableComponent, ComponentGetState>(OnFlashableGetState);
-        }
-
-        private static void OnFlashableGetState(EntityUid uid, FlashableComponent component, ref ComponentGetState args)
-        {
-            args.State = new FlashableComponentState(component.Duration, component.LastFlash);
-        }
+        [ValidatePrototypeId<StatusEffectPrototype>]
+        public const string FlashedKey = "Flashed";
     }
 }
index 8bf55e48bd3e5142f8b407833e8d1f9385372cab..baea453cb88e881411453ae1636922e855b07e05 100644 (file)
     - Stun
     - KnockedDown
     - SlowedDown
+    - Flashed
   - type: TypingIndicator
     proto: robot
   - type: Speech
     locked: true
   - type: ActivatableUIRequiresLock
   - type: LockedWiresPanel
-  - type: Flashable
   - type: Damageable
     damageContainer: Silicon
   - type: Destructible
index 39e68b63a789a998ffd6508f4f8b6ea7913e9637..3b6c4e8ed92081f9881405f25976b717934995d9 100644 (file)
@@ -48,7 +48,6 @@
     sprite: Mobs/Effects/onfire.rsi
     normalState: Generic_mob_burning
   - type: Climbing
-  - type: Flashable
   - type: NameIdentifier
     group: GenericNumber
 
index 23eb462db18f3ba16bc95d99d0f5563448b7e623..c1cfa40836045f83fcece399d7e8408df78978e1 100644 (file)
       amount: 3
     - id: DrinkTequilaBottleFull
       amount: 1
-  - type: Flashable
   - type: Tag
     tags:
     - CannotSuicide
 #    name: ghost-role-information-tropico-name
 #    description: ghost-role-information-tropico-description
 #  - type: GhostTakeoverAvailable
-#  - type: Flashable
   - type: Tag
     tags:
     - VimPilot
index 12ea40b1e3c538d1dc43bdfbce95a3a306c8e7b0..4936d883e578c17659a00a45a40bd1f94e896eeb 100644 (file)
@@ -25,6 +25,7 @@
     - ForcedSleep
     - TemporaryBlindness
     - Pacified
+    - Flashed
   - type: Buckle
   - type: StandingState
   - type: Tag
       - TemporaryBlindness
       - Pacified
       - StaminaModifier
+      - Flashed
   - type: Bloodstream
     bloodMaxVolume: 150
   - type: MobPrice
index a49f8ff34c351abb1ce1318edf38f28d9d8e40fd..eeabecef8b2ce5963e9c079775df41e7effc9f4b 100644 (file)
     - TemporaryBlindness
     - Pacified
     - StaminaModifier
+    - Flashed
   - type: Reflect
     enabled: false
     reflectProb: 0
   id: BaseMobSpeciesOrganic
   abstract: true
   components:
-  - type: Flashable
   - type: Barotrauma
     damage:
       types:
         Heat: -0.07
       groups:
         Brute: -0.07
-  # Organs
-  - type: StatusEffects
-    allowed:
-    - Stun
-    - KnockedDown
-    - SlowedDown
-    - Stutter
-    - SeeingRainbows
-    - Electrocution
-    - ForcedSleep
-    - TemporaryBlindness
-    - Drunk
-    - SlurredSpeech
-    - RatvarianLanguage
-    - PressureImmunity
-    - Muted
-    - Pacified
-    - StaminaModifier
+
   - type: Blindable
   # Other
   - type: Temperature
index 2375855bf90b4a072f33bb234795c26010f72184..1cefef9e564868102161b5569681aecd9956023a 100644 (file)
@@ -15,9 +15,6 @@
               path: /Audio/Items/hiss.ogg
               params:
                 variation: 0.08
-  - type: Flashable
-    collisionGroup:
-    - None
   - type: DamagedByFlashing
     flashDamage:
       types:
index a991bf4035f8f4b8fcc654b953863b459a8f3297..27609b1bb542c9a39c3de2df419e04630beb38d9 100644 (file)
@@ -59,3 +59,6 @@
 
 - type: statusEffect
   id: StaminaModifier
+
+- type: statusEffect
+  id: Flashed
index ec486ab531304d5eb91f3e61eabede9a59b2050b..519a9fdd99a0346e655322c9281644ace673412a 100644 (file)
@@ -11,7 +11,7 @@ void fragment() {
 
     highp vec4 textureMix = mix(tex1, tex2, 0.5);
 
-    // Gradually mixes between the texture mix and a full-white texture, causing the "blinding" effect
+    // Gradually mixes between the texture mix and a full-black texture, causing the "blinding" effect
     highp vec4 mixed = mix(vec4(0.0, 0.0, 0.0, 1.0), textureMix, percentComplete);
 
     COLOR = vec4(mixed.rgb, remaining);