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
This commit is contained in:
GraniteSidewalk
2021-03-09 04:33:41 -06:00
committed by GitHub
parent edb9bff91c
commit 549d84174c
37 changed files with 562 additions and 133 deletions

View File

@@ -6,6 +6,8 @@ using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Enums;
using System;
namespace Content.Client.Atmos namespace Content.Client.Atmos
{ {
@@ -19,7 +21,7 @@ namespace Content.Client.Atmos
public override OverlaySpace Space => OverlaySpace.WorldSpace; public override OverlaySpace Space => OverlaySpace.WorldSpace;
public AtmosDebugOverlay() : base(nameof(AtmosDebugOverlay)) public AtmosDebugOverlay()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);

View File

@@ -1,4 +1,5 @@
using Content.Client.GameObjects.EntitySystems; using Content.Client.GameObjects.EntitySystems;
using Robust.Shared.Enums;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -15,9 +16,9 @@ namespace Content.Client.Atmos
[Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IClyde _clyde = 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); IoCManager.InjectDependencies(this);

View File

@@ -1,4 +1,4 @@
using System; using System;
using Content.Client.Administration; using Content.Client.Administration;
using Content.Client.Changelog; using Content.Client.Changelog;
using Content.Client.Eui; using Content.Client.Eui;
@@ -152,12 +152,15 @@ namespace Content.Client
IoCManager.Resolve<IGameHud>().Initialize(); IoCManager.Resolve<IGameHud>().Initialize();
IoCManager.Resolve<IClientNotifyManager>().Initialize(); IoCManager.Resolve<IClientNotifyManager>().Initialize();
IoCManager.Resolve<IClientGameTicker>().Initialize(); IoCManager.Resolve<IClientGameTicker>().Initialize();
var overlayMgr = IoCManager.Resolve<IOverlayManager>(); var overlayMgr = IoCManager.Resolve<IOverlayManager>();
overlayMgr.AddOverlay(new ParallaxOverlay()); 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 CircleMaskOverlay());
overlayMgr.AddOverlay(new FlashOverlay()); overlayMgr.AddOverlay(new FlashOverlay());
overlayMgr.AddOverlay(new RadiationPulseOverlay()); overlayMgr.AddOverlay(new RadiationPulseOverlay());
IoCManager.Resolve<IChatManager>().Initialize(); IoCManager.Resolve<IChatManager>().Initialize();
IoCManager.Resolve<ISandboxManager>().Initialize(); IoCManager.Resolve<ISandboxManager>().Initialize();
IoCManager.Resolve<IClientPreferencesManager>().Initialize(); IoCManager.Resolve<IClientPreferencesManager>().Initialize();

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
namespace Content.Client.GameObjects.Components.Singularity
{
interface IClientSingularityInstance
{
public int Level { get; set; }
}
}

View File

@@ -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 {
}
}
}
}

View File

@@ -1,4 +1,4 @@
#nullable enable #nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.UserInterface; using Content.Client.UserInterface;
using Content.Client.UserInterface.Suspicion; using Content.Client.UserInterface.Suspicion;
@@ -68,7 +68,7 @@ namespace Content.Client.GameObjects.Components.Suspicion
private void AddTraitorOverlay() private void AddTraitorOverlay()
{ {
if (_overlayManager.HasOverlay(nameof(TraitorOverlay))) if (_overlayManager.HasOverlay<TraitorOverlay>())
{ {
return; return;
} }
@@ -85,7 +85,7 @@ namespace Content.Client.GameObjects.Components.Suspicion
return; return;
} }
_overlayManager.RemoveOverlay(nameof(TraitorOverlay)); _overlayManager.RemoveOverlay<TraitorOverlay>();
} }
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)

View File

@@ -2,6 +2,7 @@ using Content.Shared.GameObjects.EntitySystems;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Client.ResourceManagement; using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
@@ -25,7 +26,6 @@ namespace Content.Client.GameObjects.Components.Suspicion
IEntityManager entityManager, IEntityManager entityManager,
IResourceCache resourceCache, IResourceCache resourceCache,
IEyeManager eyeManager) IEyeManager eyeManager)
: base(nameof(TraitorOverlay))
{ {
_playerManager = IoCManager.Resolve<IPlayerManager>(); _playerManager = IoCManager.Resolve<IPlayerManager>();

View File

@@ -1,8 +1,10 @@
using System; #nullable enable
using System;
using Content.Client.Graphics.Overlays; using Content.Client.Graphics.Overlays;
using Content.Shared.GameObjects.Components.Weapons; using Content.Shared.GameObjects.Components.Weapons;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Timing; using Robust.Shared.Timing;
@@ -15,7 +17,7 @@ namespace Content.Client.GameObjects.Components.Weapons
private TimeSpan _startTime; private TimeSpan _startTime;
private double _duration; private double _duration;
public override void HandleComponentState(ComponentState curState, ComponentState nextState) public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{ {
if (curState == null) if (curState == null)
{ {
@@ -55,7 +57,7 @@ namespace Content.Client.GameObjects.Components.Weapons
_duration = newState.Duration; _duration = newState.Duration;
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
var overlay = overlayManager.GetOverlay<FlashOverlay>(nameof(FlashOverlay)); var overlay = overlayManager.GetOverlay<FlashOverlay>();
overlay.ReceiveFlash(_duration); overlay.ReceiveFlash(_duration);
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Content.Shared.AI; using Content.Shared.AI;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
@@ -106,7 +107,7 @@ namespace Content.Client.GameObjects.EntitySystems.AI
_overlay.Modes = 0; _overlay.Modes = 0;
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
overlayManager.RemoveOverlay(_overlay.ID); overlayManager.RemoveOverlay(_overlay);
_overlay = null; _overlay = null;
} }
@@ -205,7 +206,7 @@ namespace Content.Client.GameObjects.EntitySystems.AI
public readonly List<SharedAiDebug.AStarRouteMessage> AStarRoutes = new(); public readonly List<SharedAiDebug.AStarRouteMessage> AStarRoutes = new();
public readonly List<SharedAiDebug.JpsRouteMessage> JpsRoutes = new(); public readonly List<SharedAiDebug.JpsRouteMessage> JpsRoutes = new();
public DebugPathfindingOverlay() : base(nameof(DebugPathfindingOverlay)) public DebugPathfindingOverlay()
{ {
_shader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("unshaded").Instance(); _shader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("unshaded").Instance();
_eyeManager = IoCManager.Resolve<IEyeManager>(); _eyeManager = IoCManager.Resolve<IEyeManager>();

View File

@@ -1,4 +1,5 @@
#nullable enable #nullable enable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.Atmos; using Content.Client.Atmos;
using Content.Shared.GameObjects.EntitySystems.Atmos; using Content.Shared.GameObjects.EntitySystems.Atmos;
@@ -43,7 +44,7 @@ namespace Content.Client.GameObjects.EntitySystems
_mapManager.OnGridRemoved += OnGridRemoved; _mapManager.OnGridRemoved += OnGridRemoved;
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
if(!overlayManager.HasOverlay(nameof(AtmosDebugOverlay))) if(!overlayManager.HasOverlay<AtmosDebugOverlay>())
overlayManager.AddOverlay(new AtmosDebugOverlay()); overlayManager.AddOverlay(new AtmosDebugOverlay());
} }
@@ -62,8 +63,8 @@ namespace Content.Client.GameObjects.EntitySystems
base.Shutdown(); base.Shutdown();
_mapManager.OnGridRemoved -= OnGridRemoved; _mapManager.OnGridRemoved -= OnGridRemoved;
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
if(!overlayManager.HasOverlay(nameof(GasTileOverlay))) if(!overlayManager.HasOverlay<GasTileOverlay>())
overlayManager.RemoveOverlay(nameof(GasTileOverlay)); overlayManager.RemoveOverlay<GasTileOverlay>();
} }
public void Reset() public void Reset()

View File

@@ -1,4 +1,4 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Client.Atmos; using Content.Client.Atmos;
@@ -88,7 +88,7 @@ namespace Content.Client.GameObjects.EntitySystems
} }
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
if(!overlayManager.HasOverlay(nameof(GasTileOverlay))) if(!overlayManager.HasOverlay<GasTileOverlay>())
overlayManager.AddOverlay(new GasTileOverlay()); overlayManager.AddOverlay(new GasTileOverlay());
} }
@@ -126,8 +126,8 @@ namespace Content.Client.GameObjects.EntitySystems
base.Shutdown(); base.Shutdown();
_mapManager.OnGridRemoved -= OnGridRemoved; _mapManager.OnGridRemoved -= OnGridRemoved;
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
if(!overlayManager.HasOverlay(nameof(GasTileOverlay))) if(!overlayManager.HasOverlay<GasTileOverlay>())
overlayManager.RemoveOverlay(nameof(GasTileOverlay)); overlayManager.RemoveOverlay<GasTileOverlay>();
} }
private void OnGridRemoved(GridId gridId) private void OnGridRemoved(GridId gridId)

View File

@@ -1,5 +1,6 @@
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -15,7 +16,7 @@ namespace Content.Client.Graphics.Overlays
public override OverlaySpace Space => OverlaySpace.WorldSpace; public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _shader; private readonly ShaderInstance _shader;
public CircleMaskOverlay() : base(nameof(CircleMaskOverlay)) public CircleMaskOverlay()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance(); _shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance();
@@ -23,7 +24,7 @@ namespace Content.Client.Graphics.Overlays
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{ {
if (!GradientCircleMaskOverlay.LocalPlayerHasState(_playerManager, false, true)) if (!CritOverlay.LocalPlayerHasState(_playerManager, false, true))
return; return;
handle.UseShader(_shader); handle.UseShader(_shader);
var worldHandle = (DrawingHandleWorld)handle; var worldHandle = (DrawingHandleWorld)handle;

View File

@@ -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<ShaderPrototype>("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);
}
}
}

View File

@@ -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.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Client.Graphics.Overlays namespace Content.Client.Graphics.Overlays
{ {
public class GradientCircleMaskOverlay : Overlay public class CritOverlay : Overlay
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
public override OverlaySpace Space => OverlaySpace.WorldSpace; 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); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance(); _gradientCircleShader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance();
} }
public static bool LocalPlayerHasState(IPlayerManager pm, bool critical, bool dead) { public static bool LocalPlayerHasState(IPlayerManager pm, bool critical, bool dead) {
@@ -48,9 +49,9 @@ namespace Content.Client.Graphics.Overlays
if (!LocalPlayerHasState(_playerManager, true, false)) if (!LocalPlayerHasState(_playerManager, true, false))
return; return;
handle.UseShader(_shader); var worldHandle = (DrawingHandleWorld) handle;
var worldHandle = (DrawingHandleWorld)handle;
var viewport = _eyeManager.GetWorldViewport(); var viewport = _eyeManager.GetWorldViewport();
handle.UseShader(_gradientCircleShader);
worldHandle.DrawRect(viewport, Color.White); worldHandle.DrawRect(viewport, Color.White);
} }
} }

View File

@@ -1,4 +1,5 @@
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -20,7 +21,7 @@ namespace Content.Client.Graphics.Overlays
private double _lastsFor = 1; private double _lastsFor = 1;
private Texture _screenshotTexture; private Texture _screenshotTexture;
public FlashOverlay() : base(nameof(FlashOverlay)) public FlashOverlay()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate(); _shader = _prototypeManager.Index<ShaderPrototype>("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; _screenshotTexture = null;
} }
} }

View File

@@ -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<EntityUid, SingularityShaderInstance> _singularities = new Dictionary<EntityUid, SingularityShaderInstance>();
public SingularityOverlay()
{
IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("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<IClientSingularityInstance>();
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<IClientSingularityInstance>(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;
}
}
}
}

View File

@@ -194,7 +194,6 @@ namespace Content.Client
"ContainmentFieldGenerator", "ContainmentFieldGenerator",
"ContainmentField", "ContainmentField",
"Emitter", "Emitter",
"Singularity",
"SingularityGenerator", "SingularityGenerator",
"EmitterBoltComponent", "EmitterBoltComponent",
"ParticleProjectile", "ParticleProjectile",

View File

@@ -1,5 +1,6 @@
using Content.Client.Interfaces.Parallax; using Content.Client.Interfaces.Parallax;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -13,7 +14,6 @@ namespace Content.Client.Parallax
[Dependency] private readonly IClyde _displayManager = default!; [Dependency] private readonly IClyde _displayManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override bool AlwaysDirty => true;
private const float Slowness = 0.5f; private const float Slowness = 0.5f;
private Texture _parallaxTexture; private Texture _parallaxTexture;
@@ -21,7 +21,7 @@ namespace Content.Client.Parallax
public override OverlaySpace Space => OverlaySpace.ScreenSpaceBelowWorld; public override OverlaySpace Space => OverlaySpace.ScreenSpaceBelowWorld;
private readonly ShaderInstance _shader; private readonly ShaderInstance _shader;
public ParallaxOverlay() : base(nameof(ParallaxOverlay)) public ParallaxOverlay()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("unshaded").Instance(); _shader = _prototypeManager.Index<ShaderPrototype>("unshaded").Instance();

View File

@@ -6,6 +6,7 @@ using Content.Client.GameObjects.Components.StationEvents;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Map; using Robust.Shared.Map;
@@ -44,7 +45,7 @@ namespace Content.Client.StationEvents
// TODO: When worldHandle can do DrawCircle change this. // TODO: When worldHandle can do DrawCircle change this.
public override OverlaySpace Space => OverlaySpace.ScreenSpace; public override OverlaySpace Space => OverlaySpace.ScreenSpace;
public RadiationPulseOverlay() : base(nameof(RadiationPulseOverlay)) public RadiationPulseOverlay()
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_lastTick = _gameTiming.CurTime; _lastTick = _gameTiming.CurTime;

View File

@@ -1,4 +1,4 @@
using Content.Server.GameObjects.Components.Projectiles; using Content.Server.GameObjects.Components.Projectiles;
using Content.Server.GameObjects.Components.Singularity; using Content.Server.GameObjects.Components.Singularity;
using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components;
using Content.Shared.Physics; using Content.Shared.Physics;
@@ -19,7 +19,7 @@ namespace Content.Server.GameObjects.Components.PA
private ParticleAcceleratorPowerState _state; private ParticleAcceleratorPowerState _state;
void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold)
{ {
if (otherBody.Entity.TryGetComponent<SingularityComponent>(out var singularityComponent)) if (otherBody.Entity.TryGetComponent<ServerSingularityComponent>(out var singularityComponent))
{ {
var multiplier = _state switch var multiplier = _state switch
{ {

View File

@@ -75,7 +75,7 @@ namespace Content.Server.GameObjects.Components.Singularity
public bool CanRepell(IEntity toRepell) public bool CanRepell(IEntity toRepell)
{ {
var powerNeeded = 1; var powerNeeded = 1;
if (toRepell.TryGetComponent<SingularityComponent>(out var singularityComponent)) if (toRepell.TryGetComponent<ServerSingularityComponent>(out var singularityComponent))
{ {
powerNeeded += 2*singularityComponent.Level; powerNeeded += 2*singularityComponent.Level;
} }

View File

@@ -1,34 +1,33 @@
#nullable enable #nullable enable
using Content.Server.GameObjects.Components.Observer;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Server.GameObjects.Components.StationEvents; using Content.Server.GameObjects.Components.StationEvents;
using Content.Server.GameObjects.Components.Observer;
using Content.Shared.GameObjects;
using Content.Shared.Physics; using Content.Shared.Physics;
using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Physics; using Robust.Shared.Physics;
using Robust.Shared.Physics.Collision; using Robust.Shared.Physics.Collision;
using Robust.Shared.Physics.Dynamics.Shapes; using Robust.Shared.Physics.Dynamics.Shapes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Server.GameObjects;
using Content.Shared.GameObjects.Components.Singularity;
using Robust.Shared.Players;
using Robust.Shared.Timing; using Robust.Shared.Timing;
namespace Content.Server.GameObjects.Components.Singularity namespace Content.Server.GameObjects.Components.Singularity
{ {
[RegisterComponent] [RegisterComponent]
public class SingularityComponent : Component, IStartCollide public class ServerSingularityComponent : SharedSingularityComponent, IStartCollide
{ {
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
public override uint? NetID => ContentNetIDs.SINGULARITY;
public override string Name => "Singularity";
public int Energy public int Energy
{ {
@@ -40,8 +39,6 @@ namespace Content.Server.GameObjects.Components.Singularity
_energy = value; _energy = value;
if (_energy <= 0) if (_energy <= 0)
{ {
_spriteComponent?.LayerSetVisible(0, false);
Owner.Delete(); Owner.Delete();
return; return;
} }
@@ -76,10 +73,12 @@ namespace Content.Server.GameObjects.Components.Singularity
_spriteComponent?.LayerSetRSI(0, "Constructible/Power/Singularity/singularity_" + _level + ".rsi"); _spriteComponent?.LayerSetRSI(0, "Constructible/Power/Singularity/singularity_" + _level + ".rsi");
_spriteComponent?.LayerSetState(0, "singularity_" + _level); _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; circle.Radius = _level - 0.5f;
} }
Dirty();
} }
} }
private int _level; private int _level;
@@ -102,6 +101,11 @@ namespace Content.Server.GameObjects.Components.Singularity
private AudioSystem _audioSystem = null!; private AudioSystem _audioSystem = null!;
private IPlayingAudioStream? _playingSound; private IPlayingAudioStream? _playingSound;
public override ComponentState GetComponentState(ICommonSession player)
{
return new SingularityComponentState(Level);
}
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -114,26 +118,14 @@ namespace Content.Server.GameObjects.Components.Singularity
_audioSystem.PlayFromEntity("/Audio/Effects/singularity_form.ogg", Owner); _audioSystem.PlayFromEntity("/Audio/Effects/singularity_form.ogg", Owner);
Timer.Spawn(5200,() => _playingSound = _audioSystem.PlayFromEntity("/Audio/Effects/singularity.ogg", Owner, audioParams)); 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)) if (!Owner.TryGetComponent(out _spriteComponent))
{
Logger.Error("SingularityComponent was spawned without SpriteComponent"); Logger.Error("SingularityComponent was spawned without SpriteComponent");
}
if (!Owner.TryGetComponent(out _radiationPulseComponent)) if (!Owner.TryGetComponent(out _radiationPulseComponent))
{
Logger.Error("SingularityComponent was spawned without 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; Level = 1;
} }
@@ -161,7 +153,8 @@ namespace Content.Server.GameObjects.Components.Singularity
return; return;
} }
if (otherEntity.IsInContainer()) return; if (otherEntity.IsInContainer())
return;
otherEntity.Delete(); otherEntity.Delete();
Energy++; Energy++;

View File

@@ -1,3 +1,4 @@
#nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems;
@@ -115,12 +116,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
// TODO: Merge with the code in FlashableComponent // TODO: Merge with the code in FlashableComponent
private void Flash(IEntity entity, IEntity user, int flashDuration) private void Flash(IEntity entity, IEntity user, int flashDuration)
{ {
if (entity.TryGetComponent(out FlashableComponent flashable)) if (entity.TryGetComponent<FlashableComponent>(out var flashable))
{ {
flashable.Flash(flashDuration / 1000d); flashable.Flash(flashDuration / 1000d);
} }
if (entity.TryGetComponent(out StunnableComponent stunnableComponent)) if (entity.TryGetComponent<StunnableComponent>(out var stunnableComponent))
{ {
stunnableComponent.Slowdown(flashDuration / 1000f, _slowTo, _slowTo); stunnableComponent.Slowdown(flashDuration / 1000f, _slowTo, _slowTo);
} }

View File

@@ -7,23 +7,24 @@ namespace Content.Server.GameObjects.EntitySystems
[UsedImplicitly] [UsedImplicitly]
public class SingularitySystem : EntitySystem public class SingularitySystem : EntitySystem
{ {
private float _updateInterval = 1.0f;
private float _accumulator; private float _accumulator;
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
base.Update(frameTime); base.Update(frameTime);
_accumulator += frameTime; _accumulator += frameTime;
while (_accumulator > 1.0f) while (_accumulator > _updateInterval)
{ {
_accumulator -= 1.0f; _accumulator -= _updateInterval;
foreach (var singularity in ComponentManager.EntityQuery<SingularityComponent>()) foreach (var singularity in ComponentManager.EntityQuery<ServerSingularityComponent>())
{ {
singularity.Update(1); singularity.Update(1);
} }
} }
} }
} }
} }

View File

@@ -18,6 +18,7 @@ namespace Content.Server
"RadiatingLight", "RadiatingLight",
"Icon", "Icon",
"ClientEntitySpawner", "ClientEntitySpawner",
"ToySingularity"
}; };
} }
} }

View File

@@ -32,7 +32,7 @@ namespace Content.Server.Physics.Controllers
{ {
_pullAccumulator -= 0.5f; _pullAccumulator -= 0.5f;
foreach (var singularity in ComponentManager.EntityQuery<SingularityComponent>()) foreach (var singularity in ComponentManager.EntityQuery<ServerSingularityComponent>())
{ {
// TODO: Use colliders instead probably yada yada // TODO: Use colliders instead probably yada yada
PullEntities(singularity); PullEntities(singularity);
@@ -45,7 +45,7 @@ namespace Content.Server.Physics.Controllers
{ {
_moveAccumulator -= 1.0f; _moveAccumulator -= 1.0f;
foreach (var (singularity, physics) in ComponentManager.EntityQuery<SingularityComponent, PhysicsComponent>()) foreach (var (singularity, physics) in ComponentManager.EntityQuery<ServerSingularityComponent, PhysicsComponent>())
{ {
if (singularity.Owner.HasComponent<BasicActorComponent>()) continue; if (singularity.Owner.HasComponent<BasicActorComponent>()) 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; if (singularity.Level <= 1) return;
// TODO: Could try gradual changes instead but for now just try to replicate // 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; physics.LinearVelocity = pushVector.Normalized * 2;
} }
private void PullEntities(SingularityComponent component) private void PullEntities(ServerSingularityComponent component)
{ {
var singularityCoords = component.Owner.Transform.Coordinates; 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). // 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; if (!component.Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) return;
var worldBox = physicsComponent.GetWorldAABB(); var worldBox = physicsComponent.GetWorldAABB();

View File

@@ -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;
}
}
}
}

View File

@@ -4,7 +4,7 @@
name: bee plushie name: bee plushie
parent: BaseItem parent: BaseItem
id: PlushieBee id: PlushieBee
description: A cute toy that resembles an even cuter coder. description: A cute toy that resembles an even cuter programmer.
components: components:
- type: Toys - type: Toys
- type: LoopingSound - type: LoopingSound
@@ -49,7 +49,7 @@
name: nar'sie plushie name: nar'sie plushie
parent: BaseItem parent: BaseItem
id: PlushieNar 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: components:
- type: Toys - type: Toys
- type: LoopingSound - type: LoopingSound
@@ -64,7 +64,7 @@
name: carp plushie name: carp plushie
parent: BaseItem parent: BaseItem
id: PlushieCarp id: PlushieCarp
description: An adorable stuffed toy that resembles a space carp. description: An adorable stuffed toy that resembles the monstrous space carp.
components: components:
- type: Toys - type: Toys
- type: LoopingSound - type: LoopingSound
@@ -97,7 +97,7 @@
name: snake plushie name: snake plushie
parent: BaseItem parent: BaseItem
id: PlushieSnake 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -129,7 +129,7 @@
name: help me carving name: help me carving
parent: BaseItem parent: BaseItem
id: CarvingHelpMe id: CarvingHelpMe
description: Help me... description: Help me!
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Misc/carvings.rsi sprite: Objects/Misc/carvings.rsi
@@ -191,7 +191,7 @@
name: very good carving name: very good carving
parent: BaseItem parent: BaseItem
id: CarvingVeryGood id: CarvingVeryGood
description: Very Good! description: Very good!
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Misc/carvings.rsi sprite: Objects/Misc/carvings.rsi
@@ -211,7 +211,7 @@
name: sorry carving name: sorry carving
parent: BaseItem parent: BaseItem
id: CarvingImSorry id: CarvingImSorry
description: I'm sorry... description: I'm sorry.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Misc/carvings.rsi sprite: Objects/Misc/carvings.rsi
@@ -233,7 +233,7 @@
name: AI toy name: AI toy
parent: BaseItem parent: BaseItem
id: ToyAi id: ToyAi
description: A little toy model AI core. description: A scaled-down toy AI core.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -243,7 +243,7 @@
name: nuke toy name: nuke toy
parent: BaseItem parent: BaseItem
id: ToyNuke 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -276,7 +276,7 @@
name: h.o.n.k. toy name: h.o.n.k. toy
parent: BaseItem parent: BaseItem
id: ToyHonk 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -286,7 +286,7 @@
name: ian toy name: ian toy
parent: BaseItem parent: BaseItem
id: ToyIan id: ToyIan
description: Ian action figure. description: Unable to eat, but just as fluffy as the real guy!
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -302,7 +302,7 @@
name: marauder toy name: marauder toy
parent: BaseItem parent: BaseItem
id: ToyMarauder 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -312,7 +312,7 @@
name: mauler toy name: mauler toy
parent: BaseItem parent: BaseItem
id: ToyMauler 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -322,7 +322,7 @@
name: gygax toy name: gygax toy
parent: BaseItem parent: BaseItem
id: ToyGygax 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -332,7 +332,7 @@
name: odysseus toy name: odysseus toy
parent: BaseItem parent: BaseItem
id: ToyOdysseus 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -352,7 +352,7 @@
name: deathripley toy name: deathripley toy
parent: BaseItem parent: BaseItem
id: ToyDeathRipley 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -362,7 +362,7 @@
name: phazon toy name: phazon toy
parent: BaseItem parent: BaseItem
id: ToyPhazon 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -372,7 +372,7 @@
name: fire ripley name: fire ripley
parent: BaseItem parent: BaseItem
id: ToyFireRipley 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -382,7 +382,7 @@
name: reticence toy name: reticence toy
parent: BaseItem parent: BaseItem
id: ToyReticence 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -392,7 +392,7 @@
name: ripley toy name: ripley toy
parent: BaseItem parent: BaseItem
id: ToyRipley 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -403,7 +403,7 @@
name: seraph toy name: seraph toy
parent: BaseItem parent: BaseItem
id: ToySeraph 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -414,7 +414,7 @@
name: durand toy name: durand toy
parent: BaseItem parent: BaseItem
id: ToyDurand 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: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -427,7 +427,7 @@
name: skeleton toy name: skeleton toy
parent: BaseItem parent: BaseItem
id: ToySkeleton id: ToySkeleton
description: Spooked yah! description: Spooked ya!
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -567,7 +567,7 @@
name: football name: football
parent: BaseItem parent: BaseItem
id: Football id: Football
description: Go Sports Go! description: Otherwise known as a handegg.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -583,7 +583,7 @@
name: syndie balloon name: syndie balloon
parent: BaseItem parent: BaseItem
id: BalloonSyn id: BalloonSyn
description: Loud and proud. description: Handed out to the bravest souls who survived the "atomic twister" ride at Syndieland.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -598,7 +598,7 @@
name: corgi balloon name: corgi balloon
parent: BaseItem parent: BaseItem
id: BalloonCorgi id: BalloonCorgi
description: Cute. description: Just like owning a real dog - but a lot floatier.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
@@ -608,3 +608,22 @@
size: 24 size: 24
sprite: Objects/Fun/toys.rsi sprite: Objects/Fun/toys.rsi
HeldPrefix: corgib 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

View File

@@ -7,8 +7,23 @@
id: GradientCircleMask id: GradientCircleMask
kind: source kind: source
path: "/Textures/Shaders/gradient_circle_mask.swsl" path: "/Textures/Shaders/gradient_circle_mask.swsl"
- type: shader
id: ColoredScreenBorder
kind: source
path: "/Textures/Shaders/colored_screen_border.swsl"
- type: shader - type: shader
id: FlashedEffect id: FlashedEffect
kind: source kind: source
path: "/Textures/Shaders/flashed_effect.swsl" 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"

View File

@@ -261,6 +261,22 @@
0.1 0.1
] ]
] ]
},
{
"name": "singularitytoy",
"directions": 1,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
} }
] ]
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,21 @@
//Creates a border on the edges of the screen of the specified color and of the specified size (no uniforms yet cause I'm lazy)
const highp vec4 borderColor = vec4(230.0, 0.0, 0.0, 1.0);
const highp float borderSize = 30; //Pixel size of border
void fragment() {
highp vec2 pixelSize = vec2(1.0/SCREEN_PIXEL_SIZE.x, 1.0/SCREEN_PIXEL_SIZE.y);
highp float smallestLength = FRAGCOORD.x;
if(smallestLength > 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)));
}
}

View File

@@ -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; light_mode unshaded;
const highp float percentagedistanceshow = 0.05; const highp float darknessAlphaInner = 0.6;
const highp float gradientfalloffwidth = 3.0; const highp float innerCircleRadius = 40; //Note: this is in pixels
const highp float outerCircleRadius = 80;
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);
}
void fragment() { void fragment() {
highp vec2 uv = FRAGCOORD.xy; highp vec2 pixelSize = vec2(1.0/SCREEN_PIXEL_SIZE.x, 1.0/SCREEN_PIXEL_SIZE.y);
highp vec2 res_xy = vec2(1.0/SCREEN_PIXEL_SIZE.x, 1.0/SCREEN_PIXEL_SIZE.y); highp vec2 pixelCenter = pixelSize*0.5;
highp vec2 center = res_xy*0.5; highp float distance = length(FRAGCOORD.xy - pixelCenter);
highp float radius = percentagedistanceshow * res_xy.y; if(distance > outerCircleRadius){
COLOR = vec4(0.0, 0.0, 0.0, 1.0);
highp vec4 grad = vec4(0.8 - length( uv - center )/res_xy.y * gradientfalloffwidth); }
else if(distance < innerCircleRadius){
highp vec4 layer1 = vec4(vec3(255.0),0.0); COLOR = vec4(0.0, 0.0, 0.0, darknessAlphaInner);
}
highp vec4 layer2 = circle(uv, center, radius, grad.rgb); else{
highp float intensity = (distance-innerCircleRadius)/(outerCircleRadius-innerCircleRadius);
COLOR = mix(layer1, layer2, layer2.a); COLOR = vec4(0.0, 0.0, 0.0, (1-intensity)*darknessAlphaInner + intensity);
}
} }

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}