From 549d84174ce145e1d5cc90078dc26b7c113440d5 Mon Sep 17 00:00:00 2001 From: GraniteSidewalk <32942106+GraniteSidewalk@users.noreply.github.com> Date: Tue, 9 Mar 2021 04:33:41 -0600 Subject: [PATCH] Singularity Shaders and a lot of Shader Stuff (#2517) * Beginnings of singulo shader * LOTS of changes!! * Minor changes * Singulo stuff * Aesthetic changes to singulo * Combining singulo change * ShaderAura uses IEntities now, not IPlayerSession * Fixes? * Fixes draw order for atmos * using fix * Address reviews * nuget.config whaaa * nuget haha * nuget why are you so dum * happy now * Preparing for omegachange * Merge from seventh level of hell * woork * Ignorecomponents add * mmf * RobustToolbox? * Fixes * Fixes Robust? * adds sprite * Nullables * Crit overlay stuff * Commits Robust --- Content.Client/Atmos/AtmosDebugOverlay.cs | 4 +- Content.Client/Atmos/GasTileOverlay.cs | 7 +- Content.Client/EntryPoint.cs | 7 +- .../Singularity/ClientSingularityComponent.cs | 33 ++++ .../Components/Singularity/ISingularity.cs | 11 ++ .../Singularity/ToySingularityComponent.cs | 19 ++ .../Suspicion/SuspicionRoleComponent.cs | 6 +- .../Components/Suspicion/TraitorOverlay.cs | 2 +- .../Components/Weapons/FlashableComponent.cs | 8 +- .../AI/ClientPathfindingDebugSystem.cs | 5 +- .../EntitySystems/AtmosDebugOverlaySystem.cs | 9 +- .../EntitySystems/GasTileOverlaySystem.cs | 8 +- .../Graphics/Overlays/CircleMaskOverlay.cs | 7 +- .../Overlays/ColoredScreenBorderOverlay.cs | 33 ++++ .../{GradientCircleMask.cs => CritOverlay.cs} | 15 +- .../Graphics/Overlays/FlashOverlay.cs | 10 +- .../Graphics/Overlays/SingularityOverlay.cs | 174 ++++++++++++++++++ Content.Client/IgnoredComponents.cs | 1 - Content.Client/Parallax/ParallaxOverlay.cs | 6 +- .../StationEvents/RadiationPulseOverlay.cs | 3 +- .../PA/ParticleProjectileComponent.cs | 4 +- .../Singularity/ContainmentFieldConnection.cs | 2 +- ...onent.cs => ServerSingularityComponent.cs} | 49 +++-- .../Components/Weapon/Melee/FlashComponent.cs | 5 +- .../EntitySystems/SingularitySystem.cs | 9 +- Content.Server/IgnoredComponents.cs | 1 + .../Controllers/SingularityController.cs | 10 +- .../Singularity/SharedSingularityComponent.cs | 25 +++ .../Prototypes/Entities/Objects/Fun/toys.yml | 71 ++++--- Resources/Prototypes/Shaders/shaders.yml | 15 ++ .../Textures/Objects/Fun/toys.rsi/meta.json | 18 +- .../Objects/Fun/toys.rsi/singularitytoy.png | Bin 0 -> 11271 bytes .../Shaders/colored_screen_border.swsl | 21 +++ .../Shaders/gradient_circle_mask.swsl | 40 ++-- Resources/Textures/Shaders/singularity.swsl | 32 ++++ Resources/Textures/Shaders/texture.swsl | 23 +++ RobustToolbox | 2 +- 37 files changed, 562 insertions(+), 133 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Singularity/ClientSingularityComponent.cs create mode 100644 Content.Client/GameObjects/Components/Singularity/ISingularity.cs create mode 100644 Content.Client/GameObjects/Components/Singularity/ToySingularityComponent.cs create mode 100644 Content.Client/Graphics/Overlays/ColoredScreenBorderOverlay.cs rename Content.Client/Graphics/Overlays/{GradientCircleMask.cs => CritOverlay.cs} (76%) create mode 100644 Content.Client/Graphics/Overlays/SingularityOverlay.cs rename Content.Server/GameObjects/Components/Singularity/{SingularityComponent.cs => ServerSingularityComponent.cs} (88%) create mode 100644 Content.Shared/GameObjects/Components/Singularity/SharedSingularityComponent.cs create mode 100644 Resources/Textures/Objects/Fun/toys.rsi/singularitytoy.png create mode 100644 Resources/Textures/Shaders/colored_screen_border.swsl create mode 100644 Resources/Textures/Shaders/singularity.swsl create mode 100644 Resources/Textures/Shaders/texture.swsl diff --git a/Content.Client/Atmos/AtmosDebugOverlay.cs b/Content.Client/Atmos/AtmosDebugOverlay.cs index dacf02231e..728257d448 100644 --- a/Content.Client/Atmos/AtmosDebugOverlay.cs +++ b/Content.Client/Atmos/AtmosDebugOverlay.cs @@ -6,6 +6,8 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Enums; +using System; namespace Content.Client.Atmos { @@ -19,7 +21,7 @@ namespace Content.Client.Atmos public override OverlaySpace Space => OverlaySpace.WorldSpace; - public AtmosDebugOverlay() : base(nameof(AtmosDebugOverlay)) + public AtmosDebugOverlay() { IoCManager.InjectDependencies(this); diff --git a/Content.Client/Atmos/GasTileOverlay.cs b/Content.Client/Atmos/GasTileOverlay.cs index 4d71641ff4..296afc6527 100644 --- a/Content.Client/Atmos/GasTileOverlay.cs +++ b/Content.Client/Atmos/GasTileOverlay.cs @@ -1,4 +1,5 @@ -using Content.Client.GameObjects.EntitySystems; +using Content.Client.GameObjects.EntitySystems; +using Robust.Shared.Enums; using Robust.Client.Graphics; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -15,9 +16,9 @@ namespace Content.Client.Atmos [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IClyde _clyde = default!; - public override OverlaySpace Space => OverlaySpace.WorldSpace; + public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; - public GasTileOverlay() : base(nameof(GasTileOverlay)) + public GasTileOverlay() { IoCManager.InjectDependencies(this); diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index d77639501b..61bdc03b9f 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -1,4 +1,4 @@ -using System; +using System; using Content.Client.Administration; using Content.Client.Changelog; using Content.Client.Eui; @@ -152,12 +152,15 @@ namespace Content.Client IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + var overlayMgr = IoCManager.Resolve(); overlayMgr.AddOverlay(new ParallaxOverlay()); - overlayMgr.AddOverlay(new GradientCircleMaskOverlay()); + overlayMgr.AddOverlay(new SingularityOverlay()); + overlayMgr.AddOverlay(new CritOverlay()); //Hopefully we can cut down on this list... don't see why a death overlay needs to be instantiated here. overlayMgr.AddOverlay(new CircleMaskOverlay()); overlayMgr.AddOverlay(new FlashOverlay()); overlayMgr.AddOverlay(new RadiationPulseOverlay()); + IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); diff --git a/Content.Client/GameObjects/Components/Singularity/ClientSingularityComponent.cs b/Content.Client/GameObjects/Components/Singularity/ClientSingularityComponent.cs new file mode 100644 index 0000000000..2859fea072 --- /dev/null +++ b/Content.Client/GameObjects/Components/Singularity/ClientSingularityComponent.cs @@ -0,0 +1,33 @@ +using Content.Shared.GameObjects.Components.Singularity; +using Robust.Shared.GameObjects; + + +namespace Content.Client.GameObjects.Components.Singularity +{ + [RegisterComponent] + [ComponentReference(typeof(IClientSingularityInstance))] + class ClientSingularityComponent : SharedSingularityComponent, IClientSingularityInstance + { + public int Level + { + get + { + return _level; + } + set + { + _level = value; + } + } + private int _level; + + public override void HandleComponentState(ComponentState curState, ComponentState nextState) + { + if (curState is not SingularityComponentState state) + { + return; + } + _level = state.Level; + } + } +} diff --git a/Content.Client/GameObjects/Components/Singularity/ISingularity.cs b/Content.Client/GameObjects/Components/Singularity/ISingularity.cs new file mode 100644 index 0000000000..fe5d9b2be1 --- /dev/null +++ b/Content.Client/GameObjects/Components/Singularity/ISingularity.cs @@ -0,0 +1,11 @@ + + + + +namespace Content.Client.GameObjects.Components.Singularity +{ + interface IClientSingularityInstance + { + public int Level { get; set; } + } +} diff --git a/Content.Client/GameObjects/Components/Singularity/ToySingularityComponent.cs b/Content.Client/GameObjects/Components/Singularity/ToySingularityComponent.cs new file mode 100644 index 0000000000..4711d36c30 --- /dev/null +++ b/Content.Client/GameObjects/Components/Singularity/ToySingularityComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameObjects; + +namespace Content.Client.GameObjects.Components.Singularity +{ + + [RegisterComponent] + [ComponentReference(typeof(IClientSingularityInstance))] + public class ToySingularityComponent : Component, IClientSingularityInstance + { + public override string Name => "ToySingularity"; + public int Level { + get { + return 1; + } + set { + } + } + } +} diff --git a/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs b/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs index 949ef207df..508079b816 100644 --- a/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs +++ b/Content.Client/GameObjects/Components/Suspicion/SuspicionRoleComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System.Collections.Generic; using Content.Client.UserInterface; using Content.Client.UserInterface.Suspicion; @@ -68,7 +68,7 @@ namespace Content.Client.GameObjects.Components.Suspicion private void AddTraitorOverlay() { - if (_overlayManager.HasOverlay(nameof(TraitorOverlay))) + if (_overlayManager.HasOverlay()) { return; } @@ -85,7 +85,7 @@ namespace Content.Client.GameObjects.Components.Suspicion return; } - _overlayManager.RemoveOverlay(nameof(TraitorOverlay)); + _overlayManager.RemoveOverlay(); } public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) diff --git a/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs b/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs index be5c76a84d..331c56828e 100644 --- a/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs +++ b/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs @@ -2,6 +2,7 @@ using Content.Shared.GameObjects.EntitySystems; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Client.ResourceManagement; +using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; @@ -25,7 +26,6 @@ namespace Content.Client.GameObjects.Components.Suspicion IEntityManager entityManager, IResourceCache resourceCache, IEyeManager eyeManager) - : base(nameof(TraitorOverlay)) { _playerManager = IoCManager.Resolve(); diff --git a/Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs b/Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs index d1e932d0c4..86e31dd55f 100644 --- a/Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs +++ b/Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs @@ -1,8 +1,10 @@ -using System; +#nullable enable +using System; using Content.Client.Graphics.Overlays; using Content.Shared.GameObjects.Components.Weapons; using Robust.Client.Graphics; using Robust.Client.Player; +using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Timing; @@ -15,7 +17,7 @@ namespace Content.Client.GameObjects.Components.Weapons private TimeSpan _startTime; private double _duration; - public override void HandleComponentState(ComponentState curState, ComponentState nextState) + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { if (curState == null) { @@ -55,7 +57,7 @@ namespace Content.Client.GameObjects.Components.Weapons _duration = newState.Duration; var overlayManager = IoCManager.Resolve(); - var overlay = overlayManager.GetOverlay(nameof(FlashOverlay)); + var overlay = overlayManager.GetOverlay(); overlay.ReceiveFlash(_duration); } } diff --git a/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs b/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs index aba664bf0f..1484627b37 100644 --- a/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs @@ -4,6 +4,7 @@ using System.Linq; using Content.Shared.AI; using Robust.Client.Graphics; using Robust.Client.Player; +using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; @@ -106,7 +107,7 @@ namespace Content.Client.GameObjects.EntitySystems.AI _overlay.Modes = 0; var overlayManager = IoCManager.Resolve(); - overlayManager.RemoveOverlay(_overlay.ID); + overlayManager.RemoveOverlay(_overlay); _overlay = null; } @@ -205,7 +206,7 @@ namespace Content.Client.GameObjects.EntitySystems.AI public readonly List AStarRoutes = new(); public readonly List JpsRoutes = new(); - public DebugPathfindingOverlay() : base(nameof(DebugPathfindingOverlay)) + public DebugPathfindingOverlay() { _shader = IoCManager.Resolve().Index("unshaded").Instance(); _eyeManager = IoCManager.Resolve(); diff --git a/Content.Client/GameObjects/EntitySystems/AtmosDebugOverlaySystem.cs b/Content.Client/GameObjects/EntitySystems/AtmosDebugOverlaySystem.cs index 9c219c6600..54846755b2 100644 --- a/Content.Client/GameObjects/EntitySystems/AtmosDebugOverlaySystem.cs +++ b/Content.Client/GameObjects/EntitySystems/AtmosDebugOverlaySystem.cs @@ -1,4 +1,5 @@ -#nullable enable +#nullable enable +using System; using System.Collections.Generic; using Content.Client.Atmos; using Content.Shared.GameObjects.EntitySystems.Atmos; @@ -43,7 +44,7 @@ namespace Content.Client.GameObjects.EntitySystems _mapManager.OnGridRemoved += OnGridRemoved; var overlayManager = IoCManager.Resolve(); - if(!overlayManager.HasOverlay(nameof(AtmosDebugOverlay))) + if(!overlayManager.HasOverlay()) overlayManager.AddOverlay(new AtmosDebugOverlay()); } @@ -62,8 +63,8 @@ namespace Content.Client.GameObjects.EntitySystems base.Shutdown(); _mapManager.OnGridRemoved -= OnGridRemoved; var overlayManager = IoCManager.Resolve(); - if(!overlayManager.HasOverlay(nameof(GasTileOverlay))) - overlayManager.RemoveOverlay(nameof(GasTileOverlay)); + if(!overlayManager.HasOverlay()) + overlayManager.RemoveOverlay(); } public void Reset() diff --git a/Content.Client/GameObjects/EntitySystems/GasTileOverlaySystem.cs b/Content.Client/GameObjects/EntitySystems/GasTileOverlaySystem.cs index 608a446a9d..67698402b9 100644 --- a/Content.Client/GameObjects/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Client/GameObjects/EntitySystems/GasTileOverlaySystem.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; using Content.Client.Atmos; @@ -88,7 +88,7 @@ namespace Content.Client.GameObjects.EntitySystems } var overlayManager = IoCManager.Resolve(); - if(!overlayManager.HasOverlay(nameof(GasTileOverlay))) + if(!overlayManager.HasOverlay()) overlayManager.AddOverlay(new GasTileOverlay()); } @@ -126,8 +126,8 @@ namespace Content.Client.GameObjects.EntitySystems base.Shutdown(); _mapManager.OnGridRemoved -= OnGridRemoved; var overlayManager = IoCManager.Resolve(); - if(!overlayManager.HasOverlay(nameof(GasTileOverlay))) - overlayManager.RemoveOverlay(nameof(GasTileOverlay)); + if(!overlayManager.HasOverlay()) + overlayManager.RemoveOverlay(); } private void OnGridRemoved(GridId gridId) diff --git a/Content.Client/Graphics/Overlays/CircleMaskOverlay.cs b/Content.Client/Graphics/Overlays/CircleMaskOverlay.cs index fd01eeb1e2..580d7b90d8 100644 --- a/Content.Client/Graphics/Overlays/CircleMaskOverlay.cs +++ b/Content.Client/Graphics/Overlays/CircleMaskOverlay.cs @@ -1,5 +1,6 @@ -using Robust.Client.Graphics; +using Robust.Client.Graphics; using Robust.Client.Player; +using Robust.Shared.Enums; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Prototypes; @@ -15,7 +16,7 @@ namespace Content.Client.Graphics.Overlays public override OverlaySpace Space => OverlaySpace.WorldSpace; private readonly ShaderInstance _shader; - public CircleMaskOverlay() : base(nameof(CircleMaskOverlay)) + public CircleMaskOverlay() { IoCManager.InjectDependencies(this); _shader = _prototypeManager.Index("CircleMask").Instance(); @@ -23,7 +24,7 @@ namespace Content.Client.Graphics.Overlays protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) { - if (!GradientCircleMaskOverlay.LocalPlayerHasState(_playerManager, false, true)) + if (!CritOverlay.LocalPlayerHasState(_playerManager, false, true)) return; handle.UseShader(_shader); var worldHandle = (DrawingHandleWorld)handle; diff --git a/Content.Client/Graphics/Overlays/ColoredScreenBorderOverlay.cs b/Content.Client/Graphics/Overlays/ColoredScreenBorderOverlay.cs new file mode 100644 index 0000000000..da75dc46d2 --- /dev/null +++ b/Content.Client/Graphics/Overlays/ColoredScreenBorderOverlay.cs @@ -0,0 +1,33 @@ +#nullable enable +using Robust.Client.Graphics; +using Robust.Shared.Enums; +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; +using System; + +namespace Content.Client.Graphics.Overlays +{ + public class ColoredScreenBorderOverlay : Overlay + { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IEyeManager _eyeManager = default!; + + public override OverlaySpace Space => OverlaySpace.WorldSpace; + private readonly ShaderInstance _shader; + + public ColoredScreenBorderOverlay() + { + IoCManager.InjectDependencies(this); + _shader = _prototypeManager.Index("ColoredScreenBorder").Instance(); + } + + protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) + { + handle.UseShader(_shader); + var worldHandle = (DrawingHandleWorld)handle; + var viewport = _eyeManager.GetWorldViewport(); + worldHandle.DrawRect(viewport, Color.White); + } + } +} diff --git a/Content.Client/Graphics/Overlays/GradientCircleMask.cs b/Content.Client/Graphics/Overlays/CritOverlay.cs similarity index 76% rename from Content.Client/Graphics/Overlays/GradientCircleMask.cs rename to Content.Client/Graphics/Overlays/CritOverlay.cs index 4fb87c0882..75d09b9750 100644 --- a/Content.Client/Graphics/Overlays/GradientCircleMask.cs +++ b/Content.Client/Graphics/Overlays/CritOverlay.cs @@ -1,25 +1,26 @@ -using Content.Shared.GameObjects.Components.Mobs.State; +using Content.Shared.GameObjects.Components.Mobs.State; using Robust.Client.Graphics; using Robust.Client.Player; +using Robust.Shared.Enums; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Prototypes; namespace Content.Client.Graphics.Overlays { - public class GradientCircleMaskOverlay : Overlay + public class CritOverlay : Overlay { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; public override OverlaySpace Space => OverlaySpace.WorldSpace; - private readonly ShaderInstance _shader; + private readonly ShaderInstance _gradientCircleShader, _glowingBorderShader; - public GradientCircleMaskOverlay() : base(nameof(GradientCircleMaskOverlay)) + public CritOverlay() { IoCManager.InjectDependencies(this); - _shader = _prototypeManager.Index("GradientCircleMask").Instance(); + _gradientCircleShader = _prototypeManager.Index("GradientCircleMask").Instance(); } public static bool LocalPlayerHasState(IPlayerManager pm, bool critical, bool dead) { @@ -48,9 +49,9 @@ namespace Content.Client.Graphics.Overlays if (!LocalPlayerHasState(_playerManager, true, false)) return; - handle.UseShader(_shader); - var worldHandle = (DrawingHandleWorld)handle; + var worldHandle = (DrawingHandleWorld) handle; var viewport = _eyeManager.GetWorldViewport(); + handle.UseShader(_gradientCircleShader); worldHandle.DrawRect(viewport, Color.White); } } diff --git a/Content.Client/Graphics/Overlays/FlashOverlay.cs b/Content.Client/Graphics/Overlays/FlashOverlay.cs index 0e867b59c0..e25bbadefa 100644 --- a/Content.Client/Graphics/Overlays/FlashOverlay.cs +++ b/Content.Client/Graphics/Overlays/FlashOverlay.cs @@ -1,4 +1,5 @@ -using Robust.Client.Graphics; +using Robust.Client.Graphics; +using Robust.Shared.Enums; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Prototypes; @@ -20,7 +21,7 @@ namespace Content.Client.Graphics.Overlays private double _lastsFor = 1; private Texture _screenshotTexture; - public FlashOverlay() : base(nameof(FlashOverlay)) + public FlashOverlay() { IoCManager.InjectDependencies(this); _shader = _prototypeManager.Index("FlashedEffect").Instance().Duplicate(); @@ -54,10 +55,9 @@ namespace Content.Client.Graphics.Overlays } } - protected override void Dispose(bool disposing) + protected override void DisposeBehavior() { - base.Dispose(disposing); - + base.Dispose(); _screenshotTexture = null; } } diff --git a/Content.Client/Graphics/Overlays/SingularityOverlay.cs b/Content.Client/Graphics/Overlays/SingularityOverlay.cs new file mode 100644 index 0000000000..624cfae2e8 --- /dev/null +++ b/Content.Client/Graphics/Overlays/SingularityOverlay.cs @@ -0,0 +1,174 @@ +#nullable enable +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; +using System.Collections.Generic; +using Robust.Client.Graphics; +using System.Linq; +using Robust.Shared.Enums; +using Robust.Shared.GameObjects; +using Content.Client.GameObjects.Components.Singularity; +using Robust.Shared.Map; + +namespace Content.Client.Graphics.Overlays +{ + public class SingularityOverlay : Overlay + { + [Dependency] private readonly IComponentManager _componentManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IEyeManager _eyeManager = default!; + [Dependency] private readonly IClyde _displayManager = default!; + + public override OverlaySpace Space => OverlaySpace.WorldSpace; + public override bool RequestScreenTexture => true; + + private readonly ShaderInstance _shader; + + Dictionary _singularities = new Dictionary(); + + public SingularityOverlay() + { + IoCManager.InjectDependencies(this); + _shader = _prototypeManager.Index("Singularity").Instance().Duplicate(); + } + + public override bool OverwriteTargetFrameBuffer() + { + return _singularities.Count() > 0; + } + + protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) + { + SingularityQuery(); + + foreach (SingularityShaderInstance instance in _singularities.Values) + { + var tempCoords = _eyeManager.WorldToScreen(instance.CurrentMapCoords); + tempCoords.Y = _displayManager.ScreenSize.Y - tempCoords.Y; + _shader?.SetParameter("positionInput", tempCoords); + if (ScreenTexture != null) + _shader?.SetParameter("SCREEN_TEXTURE", ScreenTexture); + _shader?.SetParameter("intensity", LevelToIntensity(instance.Level)); + _shader?.SetParameter("falloff", LevelToFalloff(instance.Level)); + + handle.UseShader(_shader); + var worldHandle = (DrawingHandleWorld) handle; + var viewport = _eyeManager.GetWorldViewport(); + worldHandle.DrawRect(viewport, Color.White); + } + + } + + + + //Queries all singulos on the map and either adds or removes them from the list of singulos to render depending on their location and existence. + private float _maxDist = 15.0f; + private void SingularityQuery() + { + var currentEyeLoc = _eyeManager.CurrentEye.Position; + + var singuloComponents = _componentManager.EntityQuery(); + foreach (var singuloInterface in singuloComponents) + { + var singuloComponent = (Component)singuloInterface; + var singuloEntity = singuloComponent.Owner; + if (!_singularities.Keys.Contains(singuloEntity.Uid) && singuloEntity.Transform.Coordinates.InRange(_entityManager, EntityCoordinates.FromMap(_entityManager, singuloEntity.Transform.ParentUid, currentEyeLoc), _maxDist)) + { + _singularities.Add(singuloEntity.Uid, new SingularityShaderInstance(singuloEntity.Transform.MapPosition.Position, singuloInterface.Level)); + } + } + + var activeShaderUids = _singularities.Keys; + foreach (var activeSinguloUid in activeShaderUids) + { + if (_entityManager.TryGetEntity(activeSinguloUid, out IEntity? singuloEntity)) + { + if (!singuloEntity.Transform.Coordinates.InRange(_entityManager, EntityCoordinates.FromMap(_entityManager, singuloEntity.Transform.ParentUid, currentEyeLoc), _maxDist)) + { + _singularities.Remove(activeSinguloUid); + } + else + { + if (!singuloEntity.TryGetComponent(out var singuloInterface)) + { + _singularities.Remove(activeSinguloUid); + } + else + { + var shaderInstance = _singularities[activeSinguloUid]; + shaderInstance.CurrentMapCoords = singuloEntity.Transform.MapPosition.Position; + shaderInstance.Level = singuloInterface.Level; + } + } + + } + else + { + _singularities.Remove(activeSinguloUid); + } + } + + } + + + + + //I am lazy + private float LevelToIntensity(int level) + { + switch (level) + { + case 0: + return 0.0f; + case 1: + return 2.7f; + case 2: + return 14.4f; + case 3: + return 47.2f; + case 4: + return 180.0f; + case 5: + return 600.0f; + case 6: + return 800.0f; + + } + return -1.0f; + } + private float LevelToFalloff(int level) + { + switch (level) + { + case 0: + return 9999f; + case 1: + return 6.4f; + case 2: + return 7.0f; + case 3: + return 8.0f; + case 4: + return 10.0f; + case 5: + return 12.0f; + case 6: + return 12.0f; + } + return -1.0f; + } + + private sealed class SingularityShaderInstance + { + public Vector2 CurrentMapCoords; + public int Level; + public SingularityShaderInstance(Vector2 mapCoords, int level) + { + CurrentMapCoords = mapCoords; + Level = level; + } + } + } +} + diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 70905418b4..4c3502512c 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -194,7 +194,6 @@ namespace Content.Client "ContainmentFieldGenerator", "ContainmentField", "Emitter", - "Singularity", "SingularityGenerator", "EmitterBoltComponent", "ParticleProjectile", diff --git a/Content.Client/Parallax/ParallaxOverlay.cs b/Content.Client/Parallax/ParallaxOverlay.cs index 71e93d5d3c..01d49e3bc7 100644 --- a/Content.Client/Parallax/ParallaxOverlay.cs +++ b/Content.Client/Parallax/ParallaxOverlay.cs @@ -1,5 +1,6 @@ -using Content.Client.Interfaces.Parallax; +using Content.Client.Interfaces.Parallax; using Robust.Client.Graphics; +using Robust.Shared.Enums; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Prototypes; @@ -13,7 +14,6 @@ namespace Content.Client.Parallax [Dependency] private readonly IClyde _displayManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - public override bool AlwaysDirty => true; private const float Slowness = 0.5f; private Texture _parallaxTexture; @@ -21,7 +21,7 @@ namespace Content.Client.Parallax public override OverlaySpace Space => OverlaySpace.ScreenSpaceBelowWorld; private readonly ShaderInstance _shader; - public ParallaxOverlay() : base(nameof(ParallaxOverlay)) + public ParallaxOverlay() { IoCManager.InjectDependencies(this); _shader = _prototypeManager.Index("unshaded").Instance(); diff --git a/Content.Client/StationEvents/RadiationPulseOverlay.cs b/Content.Client/StationEvents/RadiationPulseOverlay.cs index c78ca07311..ecb4905f6d 100644 --- a/Content.Client/StationEvents/RadiationPulseOverlay.cs +++ b/Content.Client/StationEvents/RadiationPulseOverlay.cs @@ -6,6 +6,7 @@ using Content.Client.GameObjects.Components.StationEvents; using JetBrains.Annotations; using Robust.Client.Graphics; using Robust.Client.Player; +using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; @@ -44,7 +45,7 @@ namespace Content.Client.StationEvents // TODO: When worldHandle can do DrawCircle change this. public override OverlaySpace Space => OverlaySpace.ScreenSpace; - public RadiationPulseOverlay() : base(nameof(RadiationPulseOverlay)) + public RadiationPulseOverlay() { IoCManager.InjectDependencies(this); _lastTick = _gameTiming.CurTime; diff --git a/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs b/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs index 9f03ea0970..01578de9bd 100644 --- a/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs @@ -1,4 +1,4 @@ -using Content.Server.GameObjects.Components.Projectiles; +using Content.Server.GameObjects.Components.Projectiles; using Content.Server.GameObjects.Components.Singularity; using Content.Shared.GameObjects.Components; using Content.Shared.Physics; @@ -19,7 +19,7 @@ namespace Content.Server.GameObjects.Components.PA private ParticleAcceleratorPowerState _state; void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (otherBody.Entity.TryGetComponent(out var singularityComponent)) + if (otherBody.Entity.TryGetComponent(out var singularityComponent)) { var multiplier = _state switch { diff --git a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs index a127bfa5bb..48a3286922 100644 --- a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs +++ b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs @@ -75,7 +75,7 @@ namespace Content.Server.GameObjects.Components.Singularity public bool CanRepell(IEntity toRepell) { var powerNeeded = 1; - if (toRepell.TryGetComponent(out var singularityComponent)) + if (toRepell.TryGetComponent(out var singularityComponent)) { powerNeeded += 2*singularityComponent.Level; } diff --git a/Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs b/Content.Server/GameObjects/Components/Singularity/ServerSingularityComponent.cs similarity index 88% rename from Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs rename to Content.Server/GameObjects/Components/Singularity/ServerSingularityComponent.cs index 972c3bb3a1..1e16731abd 100644 --- a/Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/ServerSingularityComponent.cs @@ -1,34 +1,33 @@ #nullable enable +using Content.Server.GameObjects.Components.Observer; using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.StationEvents; -using Content.Server.GameObjects.Components.Observer; -using Content.Shared.GameObjects; using Content.Shared.Physics; -using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; -using Robust.Shared.Maths; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision; using Robust.Shared.Physics.Dynamics.Shapes; using Robust.Shared.Random; +using Robust.Server.GameObjects; +using Content.Shared.GameObjects.Components.Singularity; +using Robust.Shared.Players; using Robust.Shared.Timing; + namespace Content.Server.GameObjects.Components.Singularity { [RegisterComponent] - public class SingularityComponent : Component, IStartCollide + public class ServerSingularityComponent : SharedSingularityComponent, IStartCollide { [Dependency] private readonly IRobustRandom _random = default!; - public override uint? NetID => ContentNetIDs.SINGULARITY; - - public override string Name => "Singularity"; public int Energy { @@ -40,8 +39,6 @@ namespace Content.Server.GameObjects.Components.Singularity _energy = value; if (_energy <= 0) { - _spriteComponent?.LayerSetVisible(0, false); - Owner.Delete(); return; } @@ -76,10 +73,12 @@ namespace Content.Server.GameObjects.Components.Singularity _spriteComponent?.LayerSetRSI(0, "Constructible/Power/Singularity/singularity_" + _level + ".rsi"); _spriteComponent?.LayerSetState(0, "singularity_" + _level); - if(_collidableComponent != null && _collidableComponent.Fixtures.Any() && _collidableComponent.Fixtures[0].Shape is PhysShapeCircle circle) + if (_collidableComponent != null && _collidableComponent.Fixtures.Any() && _collidableComponent.Fixtures[0].Shape is PhysShapeCircle circle) { circle.Radius = _level - 0.5f; } + + Dirty(); } } private int _level; @@ -102,6 +101,11 @@ namespace Content.Server.GameObjects.Components.Singularity private AudioSystem _audioSystem = null!; private IPlayingAudioStream? _playingSound; + public override ComponentState GetComponentState(ICommonSession player) + { + return new SingularityComponentState(Level); + } + public override void Initialize() { base.Initialize(); @@ -114,26 +118,14 @@ namespace Content.Server.GameObjects.Components.Singularity _audioSystem.PlayFromEntity("/Audio/Effects/singularity_form.ogg", Owner); Timer.Spawn(5200,() => _playingSound = _audioSystem.PlayFromEntity("/Audio/Effects/singularity.ogg", Owner, audioParams)); - - if (!Owner.TryGetComponent(out _collidableComponent)) - { - Logger.Error("SingularityComponent was spawned without CollidableComponent"); - } - else - { - _collidableComponent.Hard = false; - } - if (!Owner.TryGetComponent(out _spriteComponent)) - { Logger.Error("SingularityComponent was spawned without SpriteComponent"); - } - if (!Owner.TryGetComponent(out _radiationPulseComponent)) - { Logger.Error("SingularityComponent was spawned without RadiationPulseComponent"); - } - + if (!Owner.TryGetComponent(out _collidableComponent)) + Logger.Error("SingularityComponent was spawned without CollidableComponent!"); + else + _collidableComponent.Hard = false; Level = 1; } @@ -161,7 +153,8 @@ namespace Content.Server.GameObjects.Components.Singularity return; } - if (otherEntity.IsInContainer()) return; + if (otherEntity.IsInContainer()) + return; otherEntity.Delete(); Energy++; diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/FlashComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/FlashComponent.cs index 5b0bf5a4c7..8197e4e488 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/FlashComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/FlashComponent.cs @@ -1,3 +1,4 @@ +#nullable enable using System.Collections.Generic; using Content.Server.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; @@ -115,12 +116,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee // TODO: Merge with the code in FlashableComponent private void Flash(IEntity entity, IEntity user, int flashDuration) { - if (entity.TryGetComponent(out FlashableComponent flashable)) + if (entity.TryGetComponent(out var flashable)) { flashable.Flash(flashDuration / 1000d); } - if (entity.TryGetComponent(out StunnableComponent stunnableComponent)) + if (entity.TryGetComponent(out var stunnableComponent)) { stunnableComponent.Slowdown(flashDuration / 1000f, _slowTo, _slowTo); } diff --git a/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs b/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs index bd29f6deff..9950fb9ff2 100644 --- a/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs +++ b/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs @@ -7,23 +7,24 @@ namespace Content.Server.GameObjects.EntitySystems [UsedImplicitly] public class SingularitySystem : EntitySystem { + private float _updateInterval = 1.0f; private float _accumulator; public override void Update(float frameTime) { base.Update(frameTime); - _accumulator += frameTime; - while (_accumulator > 1.0f) + while (_accumulator > _updateInterval) { - _accumulator -= 1.0f; + _accumulator -= _updateInterval; - foreach (var singularity in ComponentManager.EntityQuery()) + foreach (var singularity in ComponentManager.EntityQuery()) { singularity.Update(1); } } + } } } diff --git a/Content.Server/IgnoredComponents.cs b/Content.Server/IgnoredComponents.cs index 9003823e8c..86f6d25498 100644 --- a/Content.Server/IgnoredComponents.cs +++ b/Content.Server/IgnoredComponents.cs @@ -18,6 +18,7 @@ namespace Content.Server "RadiatingLight", "Icon", "ClientEntitySpawner", + "ToySingularity" }; } } diff --git a/Content.Server/Physics/Controllers/SingularityController.cs b/Content.Server/Physics/Controllers/SingularityController.cs index 9a0a6a1b86..7702bcd04d 100644 --- a/Content.Server/Physics/Controllers/SingularityController.cs +++ b/Content.Server/Physics/Controllers/SingularityController.cs @@ -32,7 +32,7 @@ namespace Content.Server.Physics.Controllers { _pullAccumulator -= 0.5f; - foreach (var singularity in ComponentManager.EntityQuery()) + foreach (var singularity in ComponentManager.EntityQuery()) { // TODO: Use colliders instead probably yada yada PullEntities(singularity); @@ -45,7 +45,7 @@ namespace Content.Server.Physics.Controllers { _moveAccumulator -= 1.0f; - foreach (var (singularity, physics) in ComponentManager.EntityQuery()) + foreach (var (singularity, physics) in ComponentManager.EntityQuery()) { if (singularity.Owner.HasComponent()) continue; @@ -57,7 +57,7 @@ namespace Content.Server.Physics.Controllers } } - private void MoveSingulo(SingularityComponent singularity, PhysicsComponent physics) + private void MoveSingulo(ServerSingularityComponent singularity, PhysicsComponent physics) { if (singularity.Level <= 1) return; // TODO: Could try gradual changes instead but for now just try to replicate @@ -70,7 +70,7 @@ namespace Content.Server.Physics.Controllers physics.LinearVelocity = pushVector.Normalized * 2; } - private void PullEntities(SingularityComponent component) + private void PullEntities(ServerSingularityComponent component) { var singularityCoords = component.Owner.Transform.Coordinates; // TODO: Maybe if we have named fixtures needs to pull out the outer circle collider (inner will be for deleting). @@ -89,7 +89,7 @@ namespace Content.Server.Physics.Controllers } } - private void DestroyTiles(SingularityComponent component) + private void DestroyTiles(ServerSingularityComponent component) { if (!component.Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) return; var worldBox = physicsComponent.GetWorldAABB(); diff --git a/Content.Shared/GameObjects/Components/Singularity/SharedSingularityComponent.cs b/Content.Shared/GameObjects/Components/Singularity/SharedSingularityComponent.cs new file mode 100644 index 0000000000..0d16c407b0 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Singularity/SharedSingularityComponent.cs @@ -0,0 +1,25 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using System; + +namespace Content.Shared.GameObjects.Components.Singularity +{ + + public abstract class SharedSingularityComponent : Component + { + public override string Name => "Singularity"; + public override uint? NetID => ContentNetIDs.SINGULARITY; + + + [Serializable, NetSerializable] + protected sealed class SingularityComponentState : ComponentState + { + public int Level { get; } + + public SingularityComponentState(int level) : base(ContentNetIDs.SINGULARITY) + { + Level = level; + } + } + } +} diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index 5353525ba6..acb6cf47b0 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -4,7 +4,7 @@ name: bee plushie parent: BaseItem id: PlushieBee - description: A cute toy that resembles an even cuter coder. + description: A cute toy that resembles an even cuter programmer. components: - type: Toys - type: LoopingSound @@ -49,7 +49,7 @@ name: nar'sie plushie parent: BaseItem id: PlushieNar - description: A small stuffed doll of the elder goddess Nar'Sie. Who thought this was a good children's toy? + description: A small stuffed doll of the elder goddess Nar'Sie. components: - type: Toys - type: LoopingSound @@ -64,7 +64,7 @@ name: carp plushie parent: BaseItem id: PlushieCarp - description: An adorable stuffed toy that resembles a space carp. + description: An adorable stuffed toy that resembles the monstrous space carp. components: - type: Toys - type: LoopingSound @@ -97,7 +97,7 @@ name: snake plushie parent: BaseItem id: PlushieSnake - description: An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing. + description: An adorable stuffed toy that resembles a snake. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -129,7 +129,7 @@ name: help me carving parent: BaseItem id: CarvingHelpMe - description: Help me... + description: Help me! components: - type: Sprite sprite: Objects/Misc/carvings.rsi @@ -191,7 +191,7 @@ name: very good carving parent: BaseItem id: CarvingVeryGood - description: Very Good! + description: Very good! components: - type: Sprite sprite: Objects/Misc/carvings.rsi @@ -211,7 +211,7 @@ name: sorry carving parent: BaseItem id: CarvingImSorry - description: I'm sorry... + description: I'm sorry. components: - type: Sprite sprite: Objects/Misc/carvings.rsi @@ -233,7 +233,7 @@ name: AI toy parent: BaseItem id: ToyAi - description: A little toy model AI core. + description: A scaled-down toy AI core. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -243,7 +243,7 @@ name: nuke toy parent: BaseItem id: ToyNuke - description: A plastic model of a Nuclear Fission Explosive. What child plays with this? + description: A plastic model of a Nuclear Fission Explosive. No uranium included... probably. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -276,7 +276,7 @@ name: h.o.n.k. toy parent: BaseItem id: ToyHonk - description: Mini-Mecha action figure! Collect them all! 6/12. + description: Mini-Mecha action figure! 'Mecha No. 6/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -286,7 +286,7 @@ name: ian toy parent: BaseItem id: ToyIan - description: Ian action figure. + description: Unable to eat, but just as fluffy as the real guy! components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -302,7 +302,7 @@ name: marauder toy parent: BaseItem id: ToyMarauder - description: Mini-Mecha action figure! Collect them all! 7/12. + description: Mini-Mecha action figure! 'Mecha No. 7/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -312,7 +312,7 @@ name: mauler toy parent: BaseItem id: ToyMauler - description: Mini-Mecha action figure! Collect them all! 9/12. + description: Mini-Mecha action figure! 'Mecha No. 9/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -322,7 +322,7 @@ name: gygax toy parent: BaseItem id: ToyGygax - description: Mini-Mecha action figure! Collect them all! 4/12. + description: Mini-Mecha action figure! 'Mecha No. 4/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -332,7 +332,7 @@ name: odysseus toy parent: BaseItem id: ToyOdysseus - description: Mini-Mecha action figure! Collect them all! 10/12. + description: Mini-Mecha action figure! 'Mecha No. 10/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -352,7 +352,7 @@ name: deathripley toy parent: BaseItem id: ToyDeathRipley - description: Mini-Mecha action figure! Collect them all! 3/12. + description: Mini-Mecha action figure! 'Mecha No. 3/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -362,7 +362,7 @@ name: phazon toy parent: BaseItem id: ToyPhazon - description: Mini-Mecha action figure! Collect them all! 11/12. + description: Mini-Mecha action figure! 'Mecha No. 11/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -372,7 +372,7 @@ name: fire ripley parent: BaseItem id: ToyFireRipley - description: Mini-Mecha action figure! Collect them all! 2/12. + description: Mini-Mecha action figure! 'Mecha No. 2/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -382,7 +382,7 @@ name: reticence toy parent: BaseItem id: ToyReticence - description: Mini-Mecha action figure! Collect them all! 12/12. + description: Mini-Mecha action figure! 'Mecha No. 12/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -392,7 +392,7 @@ name: ripley toy parent: BaseItem id: ToyRipley - description: Mini-Mecha action figure! Collect them all! 1/12. + description: Mini-Mecha action figure! 'Mecha No. 1/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -403,7 +403,7 @@ name: seraph toy parent: BaseItem id: ToySeraph - description: Mini-Mecha action figure! Collect them all! 8/12. + description: Mini-Mecha action figure! 'Mecha No. 8/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -414,7 +414,7 @@ name: durand toy parent: BaseItem id: ToyDurand - description: Mini-Mecha action figure! Collect them all! 5/12. + description: Mini-Mecha action figure! 'Mecha No. 5/12' is written on the back. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -427,7 +427,7 @@ name: skeleton toy parent: BaseItem id: ToySkeleton - description: Spooked yah! + description: Spooked ya! components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -567,7 +567,7 @@ name: football parent: BaseItem id: Football - description: Go Sports Go! + description: Otherwise known as a handegg. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -583,7 +583,7 @@ name: syndie balloon parent: BaseItem id: BalloonSyn - description: Loud and proud. + description: Handed out to the bravest souls who survived the "atomic twister" ride at Syndieland. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -598,7 +598,7 @@ name: corgi balloon parent: BaseItem id: BalloonCorgi - description: Cute. + description: Just like owning a real dog - but a lot floatier. components: - type: Sprite sprite: Objects/Fun/toys.rsi @@ -608,3 +608,22 @@ size: 24 sprite: Objects/Fun/toys.rsi HeldPrefix: corgib + +- type: entity + name: singuloth-brand toy + parent: BaseItem + id: SingularityToy + description: Mass-produced by a sadistic corporate conglomerate! + components: + - type: Sprite + sprite: Objects/Fun/toys.rsi + state: singularitytoy + - type: Icon + sprite: Objects/Fun/toys.rsi + state: singularitytoy + - type: ToySingularity + + - type: Item + size: 12 + sprite: Objects/Fun/toys.rsi + HeldPrefix: singularitytoy \ No newline at end of file diff --git a/Resources/Prototypes/Shaders/shaders.yml b/Resources/Prototypes/Shaders/shaders.yml index b02acfe811..0c0919abe7 100644 --- a/Resources/Prototypes/Shaders/shaders.yml +++ b/Resources/Prototypes/Shaders/shaders.yml @@ -7,8 +7,23 @@ id: GradientCircleMask kind: source path: "/Textures/Shaders/gradient_circle_mask.swsl" + +- type: shader + id: ColoredScreenBorder + kind: source + path: "/Textures/Shaders/colored_screen_border.swsl" - type: shader id: FlashedEffect kind: source path: "/Textures/Shaders/flashed_effect.swsl" + +- type: shader + id: Singularity + kind: source + path: "/Textures/Shaders/singularity.swsl" + +- type: shader + id: Texture + kind: source + path: "/Textures/Shaders/texture.swsl" diff --git a/Resources/Textures/Objects/Fun/toys.rsi/meta.json b/Resources/Textures/Objects/Fun/toys.rsi/meta.json index 25b565901c..140656e79e 100644 --- a/Resources/Textures/Objects/Fun/toys.rsi/meta.json +++ b/Resources/Textures/Objects/Fun/toys.rsi/meta.json @@ -261,6 +261,22 @@ 0.1 ] ] + }, + { + "name": "singularitytoy", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] } ] -} +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Fun/toys.rsi/singularitytoy.png b/Resources/Textures/Objects/Fun/toys.rsi/singularitytoy.png new file mode 100644 index 0000000000000000000000000000000000000000..b609db734fd6eb9dc0689b1da1453017589829a9 GIT binary patch literal 11271 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 x1+iADf;LMZv_9a&E FRAGCOORD.y){ + smallestLength = FRAGCOORD.y; + } + if(smallestLength > pixelSize.x-FRAGCOORD.x){ + smallestLength = pixelSize.x-FRAGCOORD.x; + } + if(smallestLength > pixelSize.y-FRAGCOORD.y){ + smallestLength = pixelSize.y-FRAGCOORD.y; + } + if(smallestLength <= borderSize){ + COLOR = vec4(borderColor.r, borderColor.g, borderColor.b, abs((1.0-(smallestLength/borderSize))*(abs(sin(TIME))*0.8+0.2))); + } +} \ No newline at end of file diff --git a/Resources/Textures/Shaders/gradient_circle_mask.swsl b/Resources/Textures/Shaders/gradient_circle_mask.swsl index f32fa4ce5f..a00a9d2d48 100644 --- a/Resources/Textures/Shaders/gradient_circle_mask.swsl +++ b/Resources/Textures/Shaders/gradient_circle_mask.swsl @@ -1,25 +1,25 @@ +//This shader defines two circles - everything inside the inner circle will be darkened, while everything outside the outer circle +//will be full black. Between the inner and outer circle it LERPs from the inner darkness to full black. + light_mode unshaded; -const highp float percentagedistanceshow = 0.05; -const highp float gradientfalloffwidth = 3.0; - -highp vec4 circle(in highp vec2 uv, in highp vec2 pos, highp float rad, in highp vec3 color) { - highp float d = length(pos - uv) - rad; - highp float t = clamp(d, 0.0, 1.0); - return vec4(color, t); -} +const highp float darknessAlphaInner = 0.6; +const highp float innerCircleRadius = 40; //Note: this is in pixels +const highp float outerCircleRadius = 80; void fragment() { - highp vec2 uv = FRAGCOORD.xy; - highp vec2 res_xy = vec2(1.0/SCREEN_PIXEL_SIZE.x, 1.0/SCREEN_PIXEL_SIZE.y); - highp vec2 center = res_xy*0.5; - highp float radius = percentagedistanceshow * res_xy.y; - - highp vec4 grad = vec4(0.8 - length( uv - center )/res_xy.y * gradientfalloffwidth); - - highp vec4 layer1 = vec4(vec3(255.0),0.0); - - highp vec4 layer2 = circle(uv, center, radius, grad.rgb); - - COLOR = mix(layer1, layer2, layer2.a); + highp vec2 pixelSize = vec2(1.0/SCREEN_PIXEL_SIZE.x, 1.0/SCREEN_PIXEL_SIZE.y); + highp vec2 pixelCenter = pixelSize*0.5; + highp float distance = length(FRAGCOORD.xy - pixelCenter); + if(distance > outerCircleRadius){ + COLOR = vec4(0.0, 0.0, 0.0, 1.0); + } + else if(distance < innerCircleRadius){ + COLOR = vec4(0.0, 0.0, 0.0, darknessAlphaInner); + } + else{ + highp float intensity = (distance-innerCircleRadius)/(outerCircleRadius-innerCircleRadius); + COLOR = vec4(0.0, 0.0, 0.0, (1-intensity)*darknessAlphaInner + intensity); + } } + diff --git a/Resources/Textures/Shaders/singularity.swsl b/Resources/Textures/Shaders/singularity.swsl new file mode 100644 index 0000000000..046df1afd0 --- /dev/null +++ b/Resources/Textures/Shaders/singularity.swsl @@ -0,0 +1,32 @@ +//Gravitational lensing effect. Edited from https://unionassets.com/blog/the-effect-of-the-gravitational-lens-195 to be Clyde based (based on what) + +uniform sampler2D SCREEN_TEXTURE; +uniform highp vec2 positionInput = vec2(0,0); +uniform highp float falloff = 5.0; +uniform highp float intensity = 5.0; + + + +void fragment() { + float distanceToCenter = length(FRAGCOORD.xy-positionInput); + + vec2 finalCoords = FRAGCOORD.xy - positionInput; + highp float deformation = (pow(intensity, 2)*500) / pow(distanceToCenter, pow(falloff, 0.5)); + if(deformation > 0.8) //Edit this for inward effect + deformation = pow(deformation, 0.3); + if(deformation > 0.001){ + finalCoords *= 1-deformation; //Change this to 1+deformation for inward effect + finalCoords += positionInput; + //float darkenCircleSize = 600; //Calculate optional darkening effect (darker the closer we are to the center of the singularity) + //float alph = (distanceToCenter-30)/(darkenCircleSize-30); + //float darkening = 0.9-(alph*0.9); + + //Darkening effect optional (Darker the closer you are to the center) + //COLOR = mix(texture(SCREEN_TEXTURE, finalCoords*SCREEN_PIXEL_SIZE), vec4(0.0, 0.0, 0.0, 1.0), darkening); + COLOR = texture(SCREEN_TEXTURE, finalCoords*SCREEN_PIXEL_SIZE); + } + else{ + COLOR = texture(SCREEN_TEXTURE, FRAGCOORD.xy*SCREEN_PIXEL_SIZE); + } + +} \ No newline at end of file diff --git a/Resources/Textures/Shaders/texture.swsl b/Resources/Textures/Shaders/texture.swsl new file mode 100644 index 0000000000..f92733058f --- /dev/null +++ b/Resources/Textures/Shaders/texture.swsl @@ -0,0 +1,23 @@ + +//Draws the given texture at the given screen coords. Useful in specific scenarios (i.e. this was made for drawing singularity sprites over the lensing effect but below FOV) +//Currently does not work with AtlasTextures, going to need some work. + +uniform sampler2D tex; +uniform highp vec2 positionInput = vec2(0,0); +uniform highp vec2 pixelSize = vec2(32, 32); +uniform highp float alphaCutoff = 0.0; +uniform bool removeTransparency = false; + +void fragment() { + float pixelLength = pixelSize.x*2; + float halvedLength = pixelLength/2; + if(FRAGCOORD.x > positionInput.x - halvedLength && FRAGCOORD.x < positionInput.x + halvedLength && FRAGCOORD.y > positionInput.y - halvedLength && FRAGCOORD.y < positionInput.y + halvedLength){ + vec2 finalCoords = (FRAGCOORD.xy-positionInput+(pixelLength/2))/pixelLength; + vec4 color = texture(tex, finalCoords); + if(color.a > alphaCutoff){ + if(removeTransparency) + color.a = 1.0; + COLOR = color; + } + } +} \ No newline at end of file diff --git a/RobustToolbox b/RobustToolbox index 4bc775c01c..a0d241e551 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 4bc775c01c1019686c8b3f42c571f1040765f69f +Subproject commit a0d241e551404cec586df5a7e1fe9ef3b5ec3eeb