diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index e91874432f..3a37484c35 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -182,10 +182,10 @@ namespace Content.Client.Entry ContentContexts.SetupContexts(inputMan.Contexts); IoCManager.Resolve().Initialize(); - IoCManager.Resolve().LoadParallax(); // Have to do this later because prototypes are needed. + IoCManager.Resolve().LoadDefaultParallax(); // Have to do this later because prototypes are needed. var overlayMgr = IoCManager.Resolve(); - overlayMgr.AddOverlay(new ParallaxOverlay()); + overlayMgr.AddOverlay(new SingularityOverlay()); overlayMgr.AddOverlay(new FlashOverlay()); overlayMgr.AddOverlay(new RadiationPulseOverlay()); diff --git a/Content.Client/Gravity/GravitySystem.cs b/Content.Client/Gravity/GravitySystem.cs index 2bcf53d146..3efaa6ff96 100644 --- a/Content.Client/Gravity/GravitySystem.cs +++ b/Content.Client/Gravity/GravitySystem.cs @@ -2,7 +2,7 @@ using Content.Shared.Gravity; namespace Content.Client.Gravity { - internal sealed class GravitySystem : SharedGravitySystem + public sealed class GravitySystem : SharedGravitySystem { } diff --git a/Content.Client/Parallax/Data/IParallaxTextureSource.cs b/Content.Client/Parallax/Data/IParallaxTextureSource.cs index e40f924c74..99db736af1 100644 --- a/Content.Client/Parallax/Data/IParallaxTextureSource.cs +++ b/Content.Client/Parallax/Data/IParallaxTextureSource.cs @@ -1,7 +1,5 @@ using System.Threading; using System.Threading.Tasks; -using System.Collections.Generic; -using Robust.Shared.Serialization.Manager.Attributes; using Robust.Client.Graphics; namespace Content.Client.Parallax.Data diff --git a/Content.Client/Parallax/Data/ImageParallaxTextureSource.cs b/Content.Client/Parallax/Data/ImageParallaxTextureSource.cs index 359e2ee797..bbd49dd4c3 100644 --- a/Content.Client/Parallax/Data/ImageParallaxTextureSource.cs +++ b/Content.Client/Parallax/Data/ImageParallaxTextureSource.cs @@ -1,12 +1,9 @@ using System.Threading; using System.Threading.Tasks; -using System.Collections.Generic; using JetBrains.Annotations; using Content.Client.Resources; using Content.Client.IoC; using Robust.Client.Graphics; -using Robust.Client.ResourceManagement; -using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Utility; namespace Content.Client.Parallax.Data; diff --git a/Content.Client/Parallax/Data/ParallaxLayerConfig.cs b/Content.Client/Parallax/Data/ParallaxLayerConfig.cs index 4c6884781a..9d9db148f8 100644 --- a/Content.Client/Parallax/Data/ParallaxLayerConfig.cs +++ b/Content.Client/Parallax/Data/ParallaxLayerConfig.cs @@ -62,5 +62,12 @@ public sealed class ParallaxLayerConfig /// [DataField("slowness")] public float Slowness { get; set; } = 0.5f; + + /// + /// Should the parallax scroll at a specific rate per second. + /// + [DataField("scrolling")] public Vector2 Scrolling = Vector2.Zero; + + [DataField("shader")] public string? Shader = "unshaded"; } diff --git a/Content.Client/Parallax/Managers/IParallaxManager.cs b/Content.Client/Parallax/Managers/IParallaxManager.cs index 74606112b5..23b42bede2 100644 --- a/Content.Client/Parallax/Managers/IParallaxManager.cs +++ b/Content.Client/Parallax/Managers/IParallaxManager.cs @@ -1,35 +1,30 @@ -using System; -using Robust.Client.Graphics; -using Content.Client.Parallax; +using System.Threading.Tasks; +using Robust.Shared.Maths; namespace Content.Client.Parallax.Managers; public interface IParallaxManager { - /// - /// The current parallax. - /// Changing this causes a new parallax to be loaded (eventually). - /// Do not alter until prototype manager is available. - /// Useful "csi" input for testing new parallaxes: - /// using Content.Client.Parallax.Managers; IoCManager.Resolve().ParallaxName = "test"; - /// - string ParallaxName { get; set; } - /// /// All WorldHomePosition values are offset by this. /// Vector2 ParallaxAnchor { get; set; } - /// - /// The layers of the currently loaded parallax. - /// This will change on a whim without notification. - /// - ParallaxLayerPrepared[] ParallaxLayers { get; } + bool IsLoaded(string name); /// - /// Used to initialize the manager. + /// The layers of the selected parallax. + /// + ParallaxLayerPrepared[] GetParallaxLayers(string name); + + /// + /// Loads in the default parallax to use. /// Do not call until prototype manager is available. /// - void LoadParallax(); + void LoadDefaultParallax(); + + Task LoadParallaxByName(string name); + + void UnloadParallax(string name); } diff --git a/Content.Client/Parallax/Managers/ParallaxManager.cs b/Content.Client/Parallax/Managers/ParallaxManager.cs index ffa2d0237e..3b000a65ff 100644 --- a/Content.Client/Parallax/Managers/ParallaxManager.cs +++ b/Content.Client/Parallax/Managers/ParallaxManager.cs @@ -1,111 +1,103 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.IO; +using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; using Content.Client.Parallax.Data; -using Content.Shared; using Content.Shared.CCVar; -using Nett; -using Robust.Client.Graphics; -using Robust.Client.ResourceManagement; using Robust.Shared.Prototypes; using Robust.Shared.Configuration; -using Robust.Shared.ContentPack; -using Robust.Shared.IoC; -using Robust.Shared.Log; using Robust.Shared.Utility; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; namespace Content.Client.Parallax.Managers; -internal sealed class ParallaxManager : IParallaxManager +public sealed class ParallaxManager : IParallaxManager { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!; - private string _parallaxName = ""; - public string ParallaxName - { - get => _parallaxName; - set - { - LoadParallaxByName(value); - } - } + private ISawmill _sawmill = Logger.GetSawmill("parallax"); public Vector2 ParallaxAnchor { get; set; } - private CancellationTokenSource? _presentParallaxLoadCancel; + private readonly ConcurrentDictionary _parallaxesLQ = new(); + private readonly ConcurrentDictionary _parallaxesHQ = new(); - private ParallaxLayerPrepared[] _parallaxLayersHQ = {}; - private ParallaxLayerPrepared[] _parallaxLayersLQ = {}; + private readonly ConcurrentDictionary _loadingParallaxes = new(); - public ParallaxLayerPrepared[] ParallaxLayers => _configurationManager.GetCVar(CCVars.ParallaxLowQuality) ? _parallaxLayersLQ : _parallaxLayersHQ; + public bool IsLoaded(string name) => _parallaxesLQ.ContainsKey(name); - public async void LoadParallax() + public ParallaxLayerPrepared[] GetParallaxLayers(string name) { - await LoadParallaxByName("default"); + if (_configurationManager.GetCVar(CCVars.ParallaxLowQuality)) + { + return !_parallaxesLQ.TryGetValue(name, out var lq) ? Array.Empty() : lq; + } + + return !_parallaxesLQ.TryGetValue(name, out var hq) ? Array.Empty() : hq; } - private async Task LoadParallaxByName(string name) + public void UnloadParallax(string name) { - // Update _parallaxName - if (_parallaxName == name) + if (_loadingParallaxes.TryGetValue(name, out var loading)) { + loading.Cancel(); + _loadingParallaxes.Remove(name, out _); return; } - _parallaxName = name; + + if (!_parallaxesLQ.ContainsKey(name)) return; + _parallaxesLQ.Remove(name, out _); + _parallaxesHQ.Remove(name, out _); + } + + public async void LoadDefaultParallax() + { + await LoadParallaxByName("Default"); + } + + public async Task LoadParallaxByName(string name) + { + if (_parallaxesLQ.ContainsKey(name) || _loadingParallaxes.ContainsKey(name)) return; // Cancel any existing load and setup the new cancellation token - _presentParallaxLoadCancel?.Cancel(); - _presentParallaxLoadCancel = new CancellationTokenSource(); - var cancel = _presentParallaxLoadCancel.Token; - - // Empty parallax name = no layers (this is so that the initial "" parallax name is consistent) - if (_parallaxName == "") - { - _parallaxLayersHQ = _parallaxLayersLQ = new ParallaxLayerPrepared[] {}; - return; - } + var token = new CancellationTokenSource(); + _loadingParallaxes[name] = token; + var cancel = token.Token; // Begin (for real) - Logger.InfoS("parallax", $"Loading parallax {name}"); + _sawmill.Info($"Loading parallax {name}"); try { var parallaxPrototype = _prototypeManager.Index(name); - ParallaxLayerPrepared[] hq; - ParallaxLayerPrepared[] lq; + ParallaxLayerPrepared[][] layers; if (parallaxPrototype.LayersLQUseHQ) { - lq = hq = await LoadParallaxLayers(parallaxPrototype.Layers, cancel); + layers = new ParallaxLayerPrepared[2][]; + layers[0] = layers[1] = await LoadParallaxLayers(parallaxPrototype.Layers, cancel); } else { - var results = await Task.WhenAll( + layers = await Task.WhenAll( LoadParallaxLayers(parallaxPrototype.Layers, cancel), LoadParallaxLayers(parallaxPrototype.LayersLQ, cancel) ); - hq = results[0]; - lq = results[1]; } - // Still keeping this check just in case. - if (_parallaxName == name) - { - _parallaxLayersHQ = hq; - _parallaxLayersLQ = lq; - Logger.InfoS("parallax", $"Loaded parallax {name}"); - } + _loadingParallaxes.Remove(name, out _); + + if (token.Token.IsCancellationRequested) return; + + _parallaxesLQ[name] = layers[0]; + _parallaxesHQ[name] = layers[1]; + + _sawmill.Info($"Loaded parallax {name}"); + } catch (Exception ex) { - Logger.ErrorS("parallax", $"Failed to loaded parallax {name}: {ex}"); + _sawmill.Error($"Failed to loaded parallax {name}: {ex}"); } } diff --git a/Content.Client/Parallax/ParallaxControl.cs b/Content.Client/Parallax/ParallaxControl.cs index 8833dfb58c..0d2abe121a 100644 --- a/Content.Client/Parallax/ParallaxControl.cs +++ b/Content.Client/Parallax/ParallaxControl.cs @@ -1,10 +1,7 @@ using Content.Client.Parallax.Managers; using Robust.Client.Graphics; using Robust.Client.UserInterface; -using Robust.Shared.IoC; -using Robust.Shared.Maths; using Robust.Shared.Random; -using Robust.Shared.ViewVariables; namespace Content.Client.Parallax; @@ -28,7 +25,7 @@ public sealed class ParallaxControl : Control protected override void Draw(DrawingHandleScreen handle) { - foreach (var layer in _parallaxManager.ParallaxLayers) + foreach (var layer in _parallaxManager.GetParallaxLayers("Default")) { var tex = layer.Texture; var texSize = tex.Size * layer.Config.Scale.Floored(); diff --git a/Content.Client/Parallax/ParallaxOverlay.cs b/Content.Client/Parallax/ParallaxOverlay.cs index 89b2719426..1f401cde91 100644 --- a/Content.Client/Parallax/ParallaxOverlay.cs +++ b/Content.Client/Parallax/ParallaxOverlay.cs @@ -1,47 +1,55 @@ -using System; using Content.Client.Parallax.Managers; using Content.Shared.CCVar; using Robust.Client.Graphics; using Robust.Shared.Configuration; using Robust.Shared.Enums; -using Robust.Shared.IoC; -using Robust.Shared.Maths; +using Robust.Shared.Map; using Robust.Shared.Prototypes; +using Robust.Shared.Timing; namespace Content.Client.Parallax; public sealed class ParallaxOverlay : Overlay { - [Dependency] private readonly IParallaxManager _parallaxManager = default!; + [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IConfigurationManager _configurationManager = default!; + [Dependency] private readonly IParallaxManager _manager = default!; + private readonly ParallaxSystem _parallax; public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowWorld; - private readonly ShaderInstance _shader; public ParallaxOverlay() { IoCManager.InjectDependencies(this); - _shader = _prototypeManager.Index("unshaded").Instance(); + _parallax = IoCManager.Resolve().GetEntitySystem(); + } protected override void Draw(in OverlayDrawArgs args) { - if (args.Viewport.Eye == null) - { + if (args.MapId == MapId.Nullspace) return; - } if (!_configurationManager.GetCVar(CCVars.ParallaxEnabled)) - { return; - } + var position = args.Viewport.Eye?.Position.Position ?? Vector2.Zero; var screenHandle = args.WorldHandle; - screenHandle.UseShader(_shader); - foreach (var layer in _parallaxManager.ParallaxLayers) + var layers = _parallax.GetParallaxLayers(args.MapId); + var realTime = (float) _timing.RealTime.TotalSeconds; + + foreach (var layer in layers) { + ShaderInstance? shader; + + if (!string.IsNullOrEmpty(layer.Config.Shader)) + shader = _prototypeManager.Index(layer.Config.Shader).Instance(); + else + shader = null; + + screenHandle.UseShader(shader); var tex = layer.Texture; // Size of the texture in world units. @@ -52,10 +60,11 @@ public sealed class ParallaxOverlay : Overlay // The effects of this are such that a slowness of 1 anchors the layer to the centre of the screen, while a slowness of 0 anchors the layer to the world. // (For values 0.0 to 1.0 this is in effect a lerp, but it's deliberately unclamped.) // The ParallaxAnchor adapts the parallax for station positioning and possibly map-specific tweaks. - var home = layer.Config.WorldHomePosition + _parallaxManager.ParallaxAnchor; + var home = layer.Config.WorldHomePosition + _manager.ParallaxAnchor; + var scrolled = layer.Config.Scrolling * realTime; // Origin - start with the parallax shift itself. - var originBL = (args.Viewport.Eye.Position.Position - home) * layer.Config.Slowness; + var originBL = (position - home) * layer.Config.Slowness + scrolled; // Place at the home. originBL += home; @@ -90,6 +99,8 @@ public sealed class ParallaxOverlay : Overlay screenHandle.DrawTextureRect(tex, Box2.FromDimensions(originBL, size)); } } + + screenHandle.UseShader(null); } } diff --git a/Content.Client/Parallax/ParallaxSystem.cs b/Content.Client/Parallax/ParallaxSystem.cs new file mode 100644 index 0000000000..d3320ce1f9 --- /dev/null +++ b/Content.Client/Parallax/ParallaxSystem.cs @@ -0,0 +1,71 @@ +using Content.Client.Parallax.Managers; +using Content.Shared.Parallax; +using Robust.Client.Graphics; +using Robust.Shared.GameStates; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; + +namespace Content.Client.Parallax; + +public sealed class ParallaxSystem : SharedParallaxSystem +{ + [Dependency] private readonly IMapManager _map = default!; + [Dependency] private readonly IOverlayManager _overlay = default!; + [Dependency] private readonly IParallaxManager _parallax = default!; + [Dependency] private readonly IPrototypeManager _protoManager = default!; + + private const string Fallback = "Default"; + + public override void Initialize() + { + base.Initialize(); + _overlay.AddOverlay(new ParallaxOverlay()); + SubscribeLocalEvent(OnParallaxHandleState); + _protoManager.PrototypesReloaded += OnReload; + } + + private void OnReload(PrototypesReloadedEventArgs obj) + { + _parallax.UnloadParallax(Fallback); + _parallax.LoadDefaultParallax(); + + foreach (var comp in EntityQuery(true)) + { + _parallax.UnloadParallax(comp.Parallax); + _parallax.LoadParallaxByName(comp.Parallax); + } + } + + public override void Shutdown() + { + base.Shutdown(); + _overlay.RemoveOverlay(); + _protoManager.PrototypesReloaded -= OnReload; + } + + private void OnParallaxHandleState(EntityUid uid, ParallaxComponent component, ref ComponentHandleState args) + { + if (args.Current is not ParallaxComponentState state) return; + component.Parallax = state.Parallax; + + if (!_parallax.IsLoaded(component.Parallax)) + { + _parallax.LoadParallaxByName(component.Parallax); + } + } + + public ParallaxLayerPrepared[] GetParallaxLayers(MapId mapId) + { + return _parallax.GetParallaxLayers(GetParallax(_map.GetMapEntityId(mapId))); + } + + public string GetParallax(MapId mapId) + { + return GetParallax(_map.GetMapEntityId(mapId)); + } + + public string GetParallax(EntityUid mapUid) + { + return TryComp(mapUid, out var parallax) ? parallax.Parallax : Fallback; + } +} diff --git a/Content.IntegrationTests/DummyParallaxManager.cs b/Content.IntegrationTests/DummyParallaxManager.cs index 7477fb1adb..91c739fa74 100644 --- a/Content.IntegrationTests/DummyParallaxManager.cs +++ b/Content.IntegrationTests/DummyParallaxManager.cs @@ -1,3 +1,5 @@ +using System; +using System.Threading.Tasks; using Content.Client.Parallax.Managers; using Content.Client.Parallax; using Robust.Shared.Maths; @@ -6,13 +8,30 @@ namespace Content.IntegrationTests { public sealed class DummyParallaxManager : IParallaxManager { - public string ParallaxName { get; set; } = ""; public Vector2 ParallaxAnchor { get; set; } - public ParallaxLayerPrepared[] ParallaxLayers { get; } = {}; - - public void LoadParallax() + public bool IsLoaded(string name) { - ParallaxName = "default"; + return true; + } + + public ParallaxLayerPrepared[] GetParallaxLayers(string name) + { + return Array.Empty(); + } + + public void LoadDefaultParallax() + { + return; + } + + public Task LoadParallaxByName(string name) + { + return Task.CompletedTask; + } + + public void UnloadParallax(string name) + { + return; } } } diff --git a/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs b/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs index fd4fb903eb..caeab3c561 100644 --- a/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs +++ b/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs @@ -11,7 +11,7 @@ using Robust.Shared.Map; namespace Content.IntegrationTests.Tests.Gravity { [TestFixture] - [TestOf(typeof(WeightlessSystem))] + [TestOf(typeof(GravitySystem))] [TestOf(typeof(GravityGeneratorComponent))] public sealed class WeightlessStatusTests { @@ -21,6 +21,9 @@ namespace Content.IntegrationTests.Tests.Gravity id: HumanDummy components: - type: Alerts + - type: Physics + bodyType: Dynamic + - type: entity name: GravityGeneratorDummy id: GravityGeneratorDummy @@ -38,7 +41,6 @@ namespace Content.IntegrationTests.Tests.Gravity await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); var server = pairTracker.Pair.Server; - var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); var alertsSystem = server.ResolveDependency().GetEntitySystem(); diff --git a/Content.IntegrationTests/Tests/GravityGridTest.cs b/Content.IntegrationTests/Tests/GravityGridTest.cs index c09e9d4d61..d803118ec2 100644 --- a/Content.IntegrationTests/Tests/GravityGridTest.cs +++ b/Content.IntegrationTests/Tests/GravityGridTest.cs @@ -70,8 +70,8 @@ namespace Content.IntegrationTests.Tests var grid1Entity = grid1.GridEntityId; var grid2Entity = grid2.GridEntityId; - Assert.That(!entityMan.GetComponent(grid1Entity).Enabled); - Assert.That(entityMan.GetComponent(grid2Entity).Enabled); + Assert.That(!entityMan.GetComponent(grid1Entity).EnabledVV); + Assert.That(entityMan.GetComponent(grid2Entity).EnabledVV); // Re-enable needs power so it turns off again. // Charge rate is ridiculously high so it finishes in one tick. @@ -88,7 +88,7 @@ namespace Content.IntegrationTests.Tests var grid2Entity = grid2.GridEntityId; - Assert.That(entityMan.GetComponent(grid2Entity).Enabled, Is.False); + Assert.That(entityMan.GetComponent(grid2Entity).EnabledVV, Is.False); }); await pairTracker.CleanReturnAsync(); diff --git a/Content.Server/Gravity/EntitySystems/GravitySystem.cs b/Content.Server/Gravity/EntitySystems/GravitySystem.cs index 786b09e69b..be0ad2f851 100644 --- a/Content.Server/Gravity/EntitySystems/GravitySystem.cs +++ b/Content.Server/Gravity/EntitySystems/GravitySystem.cs @@ -4,16 +4,16 @@ using JetBrains.Annotations; namespace Content.Server.Gravity.EntitySystems { [UsedImplicitly] - internal sealed class GravitySystem : SharedGravitySystem + public sealed class GravitySystem : SharedGravitySystem { public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(HandleGravityInitialize); - SubscribeLocalEvent(HandleGravityShutdown); + SubscribeLocalEvent(OnGravityInit); + SubscribeLocalEvent(OnGravityShutdown); } - private void HandleGravityInitialize(EntityUid uid, GravityComponent component, ComponentInit args) + private void OnGravityInit(EntityUid uid, GravityComponent component, ComponentInit args) { // Incase there's already a generator on the grid we'll just set it now. var gridId = Transform(component.Owner).GridUid; @@ -21,25 +21,25 @@ namespace Content.Server.Gravity.EntitySystems if (gridId == null) return; - GravityChangedMessage message; + GravityChangedEvent message; foreach (var generator in EntityManager.EntityQuery()) { if (Transform(generator.Owner).GridUid == gridId && generator.GravityActive) { component.Enabled = true; - message = new GravityChangedMessage(gridId.Value, true); + message = new GravityChangedEvent(gridId.Value, true); RaiseLocalEvent(message); return; } } component.Enabled = false; - message = new GravityChangedMessage(gridId.Value, false); + message = new GravityChangedEvent(gridId.Value, false); RaiseLocalEvent(message); } - private void HandleGravityShutdown(EntityUid uid, GravityComponent component, ComponentShutdown args) + private void OnGravityShutdown(EntityUid uid, GravityComponent component, ComponentShutdown args) { DisableGravity(component); } @@ -53,7 +53,7 @@ namespace Content.Server.Gravity.EntitySystems return; comp.Enabled = true; - var message = new GravityChangedMessage(gridId.Value, true); + var message = new GravityChangedEvent(gridId.Value, true); RaiseLocalEvent(message); } @@ -66,7 +66,7 @@ namespace Content.Server.Gravity.EntitySystems if (gridId == null) return; - var message = new GravityChangedMessage(gridId.Value, false); + var message = new GravityChangedEvent(gridId.Value, false); RaiseLocalEvent(message); } } diff --git a/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs b/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs deleted file mode 100644 index 14d1c7c952..0000000000 --- a/Content.Server/Gravity/EntitySystems/WeightlessSystem.cs +++ /dev/null @@ -1,157 +0,0 @@ -using Content.Shared.Alert; -using Content.Shared.GameTicking; -using Content.Shared.Gravity; -using Content.Shared.Movement.Components; -using JetBrains.Annotations; -using Robust.Shared.Map; -using Robust.Shared.Utility; - -namespace Content.Server.Gravity.EntitySystems -{ - [UsedImplicitly] - public sealed class WeightlessSystem : EntitySystem - { - [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly AlertsSystem _alertsSystem = default!; - - private readonly Dictionary> _alerts = new(); - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(Reset); - SubscribeLocalEvent(GravityChanged); - SubscribeLocalEvent(EntParentChanged); - SubscribeLocalEvent(HandleAlertSyncEvent); - } - - public void Reset(RoundRestartCleanupEvent ev) - { - _alerts.Clear(); - } - - public void AddAlert(AlertsComponent status) - { - var xform = Transform(status.Owner); - if (xform.GridUid != null) - { - var alerts = _alerts.GetOrNew(xform.GridUid.Value); - alerts.Add(status); - } - - if (_mapManager.TryGetGrid(xform.GridUid, out var grid)) - { - var alerts = _alerts.GetOrNew(xform.GridUid.Value); - alerts.Add(status); - - if (EntityManager.GetComponent(grid.GridEntityId).Enabled) - { - RemoveWeightless(status.Owner); - } - else - { - AddWeightless(status.Owner); - } - } - else - { - AddWeightless(status.Owner); - } - } - - public void RemoveAlert(AlertsComponent status) - { - var grid = EntityManager.GetComponent(status.Owner).GridUid; - if (grid == null || !_alerts.TryGetValue(grid.Value, out var statuses)) - { - return; - } - - statuses.Remove(status); - } - - private void GravityChanged(GravityChangedMessage ev) - { - if (!_alerts.TryGetValue(ev.ChangedGridIndex, out var statuses)) - { - return; - } - - if (ev.HasGravity) - { - foreach (var status in statuses) - { - RemoveWeightless(status.Owner); - } - } - else - { - foreach (var status in statuses) - { - AddWeightless(status.Owner); - } - } - } - - private void AddWeightless(EntityUid euid) - { - _alertsSystem.ShowAlert(euid, AlertType.Weightless); - } - - private void RemoveWeightless(EntityUid euid) - { - _alertsSystem.ClearAlert(euid, AlertType.Weightless); - } - - private void EntParentChanged(EntityUid uid, AlertsComponent status, ref EntParentChangedMessage ev) - { - // First, update the `_alerts` dictionary - if (ev.OldParent is {Valid: true} old && - EntityManager.TryGetComponent(old, out IMapGridComponent? mapGrid)) - { - var oldGrid = mapGrid.Owner; - - if (_alerts.TryGetValue(oldGrid, out var oldStatuses)) - { - oldStatuses.Remove(status); - } - } - - if (ev.Transform.MapID == MapId.Nullspace) - return; - - - var newGrid = ev.Transform.GridUid; - if (newGrid != null) - { - var newStatuses = _alerts.GetOrNew(newGrid.Value); - newStatuses.Add(status); - } - - // then update the actual alert. The alert is only removed if either the player is on a grid with gravity, - // or if they ignore gravity-based movement altogether. - // TODO: update this when planets and the like are added. - // TODO: update alert when the ignore-gravity component is added or removed. - if (_mapManager.TryGetGrid(newGrid, out var grid) - && TryComp(grid.GridEntityId, out GravityComponent? gravity) - && gravity.Enabled) - RemoveWeightless(status.Owner); - else if (!HasComp(uid)) - AddWeightless(status.Owner); - } - - private void HandleAlertSyncEvent(EntityUid uid, AlertsComponent component, AlertSyncEvent args) - { - switch (component.LifeStage) - { - case ComponentLifeStage.Starting: - AddAlert(component); - break; - case ComponentLifeStage.Removing: - RemoveAlert(component); - break; - } - } - } -} diff --git a/Content.Server/Parallax/ParallaxSystem.cs b/Content.Server/Parallax/ParallaxSystem.cs new file mode 100644 index 0000000000..497e5bc4f5 --- /dev/null +++ b/Content.Server/Parallax/ParallaxSystem.cs @@ -0,0 +1,23 @@ +using Content.Shared.Parallax; +using Robust.Shared.GameStates; + +namespace Content.Server.Parallax; + +public sealed class ParallaxSystem : SharedParallaxSystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnParallaxGetState); + } + + private void OnParallaxGetState(EntityUid uid, ParallaxComponent component, ref ComponentGetState args) + { + args.State = new ParallaxComponentState + { + Parallax = component.Parallax + }; + } + +} diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index bd2cb3219b..1b6f420fbf 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -5,6 +5,7 @@ using Content.Server.Doors.Systems; using Content.Server.Shuttles.Components; using Content.Server.Station.Systems; using Content.Server.Stunnable; +using Content.Shared.Parallax; using Content.Shared.Shuttles.Systems; using Content.Shared.Sound; using Content.Shared.StatusEffect; @@ -195,6 +196,8 @@ public sealed partial class ShuttleSystem component = AddComp(uid); // TODO: Need BroadcastGrid to not be bad. SoundSystem.Play(_startupSound.GetSound(), Filter.Empty().AddInRange(Transform(uid).MapPosition, GetSoundRange(component.Owner)), _startupSound.Params); + // Make sure the map is setup before we leave to avoid pop-in (e.g. parallax). + SetupHyperspace(); return true; } @@ -217,7 +220,6 @@ public sealed partial class ShuttleSystem DoTheDinosaur(xform); comp.State = FTLState.Travelling; - SetupHyperspace(); var width = Comp(comp.Owner).Grid.LocalAABB.Width; xform.Coordinates = new EntityCoordinates(_mapManager.GetMapEntityId(_hyperSpaceMap!.Value), new Vector2(_index + width / 2f, 0f)); @@ -352,6 +354,8 @@ public sealed partial class ShuttleSystem _hyperSpaceMap = _mapManager.CreateMap(); _sawmill.Info($"Setup hyperspace map at {_hyperSpaceMap.Value}"); DebugTools.Assert(!_mapManager.IsMapPaused(_hyperSpaceMap.Value)); + var parallax = EnsureComp(_mapManager.GetMapEntityId(_hyperSpaceMap.Value)); + parallax.Parallax = "FastSpace"; } private void CleanupHyperspace() diff --git a/Content.Shared/Friction/SharedTileFrictionController.cs b/Content.Shared/Friction/SharedTileFrictionController.cs index fc0696741f..968f3633e6 100644 --- a/Content.Shared/Friction/SharedTileFrictionController.cs +++ b/Content.Shared/Friction/SharedTileFrictionController.cs @@ -25,6 +25,7 @@ namespace Content.Shared.Friction private float _stopSpeed; private float _frictionModifier; + private const float DefaultFriction = 0.3f; public override void Initialize() { @@ -168,15 +169,19 @@ namespace Content.Shared.Friction private float GetTileFriction(PhysicsComponent body, TransformComponent xform) { // TODO: Make IsWeightless event-based; we already have grid traversals tracked so just raise events - if (_gravity.IsWeightless(body.Owner, body, xform) || - !_mapManager.TryGetGrid(xform.GridUid, out var grid)) + if (_gravity.IsWeightless(body.Owner, body, xform)) return 0.0f; if (!xform.Coordinates.IsValid(EntityManager)) return 0.0f; - var tile = grid.GetTileRef(xform.Coordinates); - var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; - return tileDef.Friction; + if (_mapManager.TryGetGrid(xform.GridUid, out var grid)) + { + var tile = grid.GetTileRef(xform.Coordinates); + var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; + return tileDef.Friction; + } + + return TryComp(xform.MapUid, out var friction) ? friction.Modifier : DefaultFriction; } [NetSerializable, Serializable] diff --git a/Content.Shared/Gravity/GravityChangedMessage.cs b/Content.Shared/Gravity/GravityChangedEvent.cs similarity index 58% rename from Content.Shared/Gravity/GravityChangedMessage.cs rename to Content.Shared/Gravity/GravityChangedEvent.cs index 6ecd9473a4..4a697f6981 100644 --- a/Content.Shared/Gravity/GravityChangedMessage.cs +++ b/Content.Shared/Gravity/GravityChangedEvent.cs @@ -1,10 +1,8 @@ -using Robust.Shared.Map; - namespace Content.Shared.Gravity { - public sealed class GravityChangedMessage : EntityEventArgs + public sealed class GravityChangedEvent : EntityEventArgs { - public GravityChangedMessage(EntityUid changedGridIndex, bool newGravityState) + public GravityChangedEvent(EntityUid changedGridIndex, bool newGravityState) { HasGravity = newGravityState; ChangedGridIndex = changedGridIndex; diff --git a/Content.Shared/Gravity/GravityComponent.cs b/Content.Shared/Gravity/GravityComponent.cs index 52e83647b2..9c9641eaa1 100644 --- a/Content.Shared/Gravity/GravityComponent.cs +++ b/Content.Shared/Gravity/GravityComponent.cs @@ -12,48 +12,19 @@ namespace Content.Shared.Gravity public SoundSpecifier GravityShakeSound { get; set; } = new SoundPathSpecifier("/Audio/Effects/alert.ogg"); [ViewVariables(VVAccess.ReadWrite)] - public bool Enabled + public bool EnabledVV { - get => _enabled; + get => Enabled; set { - if (_enabled == value) return; - _enabled = value; - if (_enabled) - { - Logger.Info($"Enabled gravity for {Owner}"); - } - else - { - Logger.Info($"Disabled gravity for {Owner}"); - } + if (Enabled == value) return; + Enabled = value; + IoCManager.Resolve().EventBus.RaiseLocalEvent(Owner, new GravityChangedEvent(Owner, value)); Dirty(); } } - private bool _enabled; - - public override ComponentState GetComponentState() - { - return new GravityComponentState(_enabled); - } - - public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) - { - base.HandleComponentState(curState, nextState); - if (curState is not GravityComponentState state) return; - Enabled = state.Enabled; - } - - [Serializable, NetSerializable] - private sealed class GravityComponentState : ComponentState - { - public bool Enabled { get; } - - public GravityComponentState(bool enabled) - { - Enabled = enabled; - } - } + [DataField("enabled")] + public bool Enabled; } } diff --git a/Content.Shared/Gravity/SharedGravitySystem.cs b/Content.Shared/Gravity/SharedGravitySystem.cs index e6696b5263..a8600e839e 100644 --- a/Content.Shared/Gravity/SharedGravitySystem.cs +++ b/Content.Shared/Gravity/SharedGravitySystem.cs @@ -1,14 +1,17 @@ +using Content.Shared.Alert; using Content.Shared.Clothing; using Content.Shared.Inventory; using Content.Shared.Movement.Components; +using Robust.Shared.GameStates; using Robust.Shared.Map; using Robust.Shared.Physics; +using Robust.Shared.Serialization; namespace Content.Shared.Gravity { public abstract class SharedGravitySystem : EntitySystem { - [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly AlertsSystem _alerts = default!; [Dependency] private readonly InventorySystem _inventory = default!; public bool IsWeightless(EntityUid uid, PhysicsComponent? body = null, TransformComponent? xform = null) @@ -21,23 +24,16 @@ namespace Content.Shared.Gravity if (TryComp(uid, out var ignoreGravityComponent)) return ignoreGravityComponent.Weightless; - if (!Resolve(uid, ref xform)) return true; - - bool gravityEnabled = false; + if (!Resolve(uid, ref xform)) + return true; // If grid / map has gravity if ((TryComp(xform.GridUid, out var gravity) || TryComp(xform.MapUid, out gravity)) && gravity.Enabled) { - gravityEnabled = gravity.Enabled; - - if (gravityEnabled) return false; + return false; } - // On the map then always weightless (unless it has gravity comp obv). - if (!_mapManager.TryGetGrid(xform.GridUid, out var grid)) - return true; - // Something holding us down if (_inventory.TryGetSlotEntity(uid, "shoes", out var ent)) { @@ -45,21 +41,76 @@ namespace Content.Shared.Gravity return false; } - if (!gravityEnabled || !xform.Coordinates.IsValid(EntityManager)) return true; - - var tile = grid.GetTileRef(xform.Coordinates).Tile; - return tile.IsEmpty; + return true; } public override void Initialize() { base.Initialize(); SubscribeLocalEvent(HandleGridInitialize); + SubscribeLocalEvent(OnAlertsParentChange); + SubscribeLocalEvent(OnGravityChange); + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + } + + private void OnHandleState(EntityUid uid, GravityComponent component, ref ComponentHandleState args) + { + if (args.Current is not GravityComponentState state) return; + + if (component.EnabledVV == state.Enabled) return; + component.EnabledVV = state.Enabled; + RaiseLocalEvent(new GravityChangedEvent(uid, component.EnabledVV)); + } + + private void OnGetState(EntityUid uid, GravityComponent component, ref ComponentGetState args) + { + args.State = new GravityComponentState(component.EnabledVV); + } + + private void OnGravityChange(GravityChangedEvent ev) + { + foreach (var (comp, xform) in EntityQuery(true)) + { + if (xform.GridUid != ev.ChangedGridIndex) continue; + + if (!ev.HasGravity) + { + _alerts.ShowAlert(comp.Owner, AlertType.Weightless); + } + else + { + _alerts.ClearAlert(comp.Owner, AlertType.Weightless); + } + } + } + + private void OnAlertsParentChange(EntityUid uid, AlertsComponent component, ref EntParentChangedMessage args) + { + if (IsWeightless(component.Owner)) + { + _alerts.ShowAlert(uid, AlertType.Weightless); + } + else + { + _alerts.ClearAlert(uid, AlertType.Weightless); + } } private void HandleGridInitialize(GridInitializeEvent ev) { EntityManager.EnsureComponent(ev.EntityUid); } + + [Serializable, NetSerializable] + private sealed class GravityComponentState : ComponentState + { + public bool Enabled { get; } + + public GravityComponentState(bool enabled) + { + Enabled = enabled; + } + } } } diff --git a/Content.Shared/Movement/Components/FootstepModifierComponent.cs b/Content.Shared/Movement/Components/FootstepModifierComponent.cs index 54d20757fb..b20452f742 100644 --- a/Content.Shared/Movement/Components/FootstepModifierComponent.cs +++ b/Content.Shared/Movement/Components/FootstepModifierComponent.cs @@ -1,17 +1,15 @@ using Content.Shared.Sound; +using Robust.Shared.GameStates; namespace Content.Shared.Movement.Components { /// /// Changes footstep sound /// - [RegisterComponent] + [RegisterComponent, NetworkedComponent] public sealed class FootstepModifierComponent : Component { [DataField("footstepSoundCollection", required: true)] - public SoundSpecifier SoundCollection = default!; - - [DataField("variation")] - public float Variation = default; + public SoundSpecifier Sound = default!; } } diff --git a/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs b/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs index 212c420507..5761a7f929 100644 --- a/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs +++ b/Content.Shared/Movement/Components/MovementIgnoreGravityComponent.cs @@ -49,7 +49,7 @@ namespace Content.Shared.Movement.Components var gridId = transform.GridUid; if ((entityManager.TryGetComponent(transform.GridUid, out var gravity) || - entityManager.TryGetComponent(transform.MapUid, out gravity)) && gravity.Enabled) + entityManager.TryGetComponent(transform.MapUid, out gravity)) && gravity.EnabledVV) return false; if (gridId == null) @@ -67,7 +67,7 @@ namespace Content.Shared.Movement.Components return false; } - if (!entityManager.GetComponent(grid.GridEntityId).Enabled) + if (!entityManager.GetComponent(grid.GridEntityId).EnabledVV) { return true; } diff --git a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs index 7a1c9e19f9..2166cff2b2 100644 --- a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs +++ b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs @@ -36,7 +36,7 @@ public abstract class SharedJetpackSystem : EntitySystem SubscribeLocalEvent(OnJetpackUserGetState); SubscribeLocalEvent(OnJetpackUserHandleState); - SubscribeLocalEvent(OnJetpackUserGravityChanged); + SubscribeLocalEvent(OnJetpackUserGravityChanged); } private void OnJetpackCanWeightlessMove(EntityUid uid, JetpackComponent component, ref CanWeightlessMoveEvent args) @@ -44,7 +44,7 @@ public abstract class SharedJetpackSystem : EntitySystem args.CanMove = true; } - private void OnJetpackUserGravityChanged(GravityChangedMessage ev) + private void OnJetpackUserGravityChanged(GravityChangedEvent ev) { var gridUid = ev.ChangedGridIndex; var jetpackQuery = GetEntityQuery(); diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Footsteps.cs b/Content.Shared/Movement/Systems/SharedMoverController.Footsteps.cs new file mode 100644 index 0000000000..8f300c7c57 --- /dev/null +++ b/Content.Shared/Movement/Systems/SharedMoverController.Footsteps.cs @@ -0,0 +1,35 @@ +using Content.Shared.Movement.Components; +using Content.Shared.Sound; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Movement.Systems; + +public abstract partial class SharedMoverController +{ + private void InitializeFootsteps() + { + SubscribeLocalEvent(OnFootGetState); + SubscribeLocalEvent(OnFootHandleState); + } + + private void OnFootHandleState(EntityUid uid, FootstepModifierComponent component, ref ComponentHandleState args) + { + if (args.Current is not FootstepModifierComponentState state) return; + component.Sound = state.Sound; + } + + private void OnFootGetState(EntityUid uid, FootstepModifierComponent component, ref ComponentGetState args) + { + args.State = new FootstepModifierComponentState() + { + Sound = component.Sound, + }; + } + + [Serializable, NetSerializable] + private sealed class FootstepModifierComponentState : ComponentState + { + public SoundSpecifier Sound = default!; + } +} diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 984f8324bd..48e17108c4 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -10,6 +10,7 @@ using Content.Shared.MobState.EntitySystems; using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; using Content.Shared.Pulling.Components; +using Content.Shared.Sound; using Content.Shared.Tag; using Robust.Shared.Audio; using Robust.Shared.Configuration; @@ -61,6 +62,7 @@ namespace Content.Shared.Movement.Systems public override void Initialize() { base.Initialize(); + InitializeFootsteps(); InitializeInput(); InitializeMob(); InitializePushing(); @@ -215,12 +217,13 @@ namespace Content.Shared.Movement.Systems : worldTotal.ToWorldAngle(); rotateXform.DeferUpdates = false; - if (!weightless && TryComp(mover.Owner, out var mobMover) && TryGetSound(mover, mobMover, xform, out var variation, out var sound)) + if (!weightless && TryComp(mover.Owner, out var mobMover) && + TryGetSound(weightless, mover, mobMover, xform, out var sound)) { var soundModifier = mover.Sprinting ? 1.0f : FootstepWalkingAddedVolumeMultiplier; - SoundSystem.Play(sound, + SoundSystem.Play(sound.GetSound(), GetSoundPlayers(mover.Owner), - mover.Owner, AudioHelpers.WithVariation(variation).WithVolume(FootstepVolume * soundModifier)); + mover.Owner, sound.Params.WithVolume(FootstepVolume * soundModifier)); } } @@ -313,19 +316,17 @@ namespace Content.Shared.Movement.Systems protected abstract bool CanSound(); - private bool TryGetSound(InputMoverComponent mover, MobMoverComponent mobMover, TransformComponent xform, out float variation, [NotNullWhen(true)] out string? sound) + private bool TryGetSound(bool weightless, InputMoverComponent mover, MobMoverComponent mobMover, TransformComponent xform, [NotNullWhen(true)] out SoundSpecifier? sound) { sound = null; - variation = 0f; if (!CanSound() || !_tags.HasTag(mover.Owner, "FootstepSound")) return false; var coordinates = xform.Coordinates; - var gridId = coordinates.GetGridUid(EntityManager); var distanceNeeded = mover.Sprinting ? StepSoundMoveDistanceRunning : StepSoundMoveDistanceWalking; // Handle footsteps. - if (_mapManager.GridExists(gridId)) + if (!weightless) { // Can happen when teleporting between grids. if (!coordinates.TryDistance(EntityManager, mobMover.LastPosition, out var distance) || @@ -344,7 +345,6 @@ namespace Content.Shared.Movement.Systems return false; } - DebugTools.Assert(gridId != null); mobMover.LastPosition = coordinates; if (mobMover.StepSoundDistance < distanceNeeded) return false; @@ -354,19 +354,31 @@ namespace Content.Shared.Movement.Systems if (_inventory.TryGetSlotEntity(mover.Owner, "shoes", out var shoes) && EntityManager.TryGetComponent(shoes, out var modifier)) { - sound = modifier.SoundCollection.GetSound(); - variation = modifier.Variation; + sound = modifier.Sound; return true; } - return TryGetFootstepSound(gridId!.Value, coordinates, out variation, out sound); + return TryGetFootstepSound(coordinates, out sound); } - private bool TryGetFootstepSound(EntityUid gridId, EntityCoordinates coordinates, out float variation, [NotNullWhen(true)] out string? sound) + private bool TryGetFootstepSound(EntityCoordinates coordinates, [NotNullWhen(true)] out SoundSpecifier? sound) { - variation = 0f; sound = null; - var grid = _mapManager.GetGrid(gridId); + var gridUid = coordinates.GetGridUid(EntityManager); + + // Fallback to the map + if (gridUid == null) + { + if (TryComp(coordinates.GetMapUid(EntityManager), out var modifier)) + { + sound = modifier.Sound; + return true; + } + + return false; + } + + var grid = _mapManager.GetGrid(gridUid.Value); var tile = grid.GetTileRef(coordinates); if (tile.IsSpace(_tileDefinitionManager)) return false; @@ -377,18 +389,15 @@ namespace Content.Shared.Movement.Systems { if (EntityManager.TryGetComponent(maybeFootstep, out FootstepModifierComponent? footstep)) { - sound = footstep.SoundCollection.GetSound(); - variation = footstep.Variation; + sound = footstep.Sound; return true; } } // Walking on a tile. var def = (ContentTileDefinition) _tileDefinitionManager[tile.Tile.TypeId]; - sound = def.FootstepSounds?.GetSound(); - variation = FootstepVariation; - - return !string.IsNullOrEmpty(sound); + sound = def.FootstepSounds; + return sound != null; } } } diff --git a/Content.Shared/Parallax/ParallaxComponent.cs b/Content.Shared/Parallax/ParallaxComponent.cs new file mode 100644 index 0000000000..8566be2fc0 --- /dev/null +++ b/Content.Shared/Parallax/ParallaxComponent.cs @@ -0,0 +1,28 @@ +using JetBrains.Annotations; +using Robust.Shared.GameStates; + +namespace Content.Shared.Parallax; + +/// +/// Handles per-map parallax +/// +[RegisterComponent, NetworkedComponent] +public sealed class ParallaxComponent : Component +{ + // I wish I could use a typeserializer here but parallax is extremely client-dependent. + [DataField("parallax")] + public string Parallax = "Default"; + + [UsedImplicitly, ViewVariables(VVAccess.ReadWrite)] + // ReSharper disable once InconsistentNaming + public string ParallaxVV + { + get => Parallax; + set + { + if (value.Equals(Parallax)) return; + Parallax = value; + IoCManager.Resolve().Dirty(this); + } + } +} diff --git a/Content.Shared/Parallax/SharedParallaxSystem.cs b/Content.Shared/Parallax/SharedParallaxSystem.cs new file mode 100644 index 0000000000..abc4cd9935 --- /dev/null +++ b/Content.Shared/Parallax/SharedParallaxSystem.cs @@ -0,0 +1,16 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Parallax; + +/// +/// Handles per-map parallax in sim. Out of sim parallax is handled by ParallaxManager. +/// +public abstract class SharedParallaxSystem: EntitySystem +{ + [Serializable, NetSerializable] + protected sealed class ParallaxComponentState : ComponentState + { + public string Parallax = string.Empty; + } +} diff --git a/Resources/Maps/nukieplanet.yml b/Resources/Maps/nukieplanet.yml index df8590d4bc..1b26857348 100644 --- a/Resources/Maps/nukieplanet.yml +++ b/Resources/Maps/nukieplanet.yml @@ -89,8 +89,6 @@ grids: tiles: MAAAAC0AAAAtAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAALQAAAC0AAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAALQAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - ind: 1,-2 tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAwAAAAMAAAADAAAAAwAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAtAAAAMAAAADAAAAAtAAAAMAAAADAAAAAtAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAALQAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAALQAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAB4AAAAeAAAAHgAAAB4AAAAeAAAAHgAAAB4AAAAeAAAAMAAAADAAAAAwAAAALQAAADAAAAAwAAAAMAAAAA== - - ind: -2,-1 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - ind: -2,0 tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAtAAAALQAAAC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAAC0AAAAtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAtAAAALQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAAC0AAAAtAAAALQAAAC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAA== - ind: -2,1 @@ -107,12 +105,6 @@ grids: tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - ind: -3,-2 tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAAAALQAAAC0AAAAtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALQAAAC0AAAAtAAAALQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0AAAAtAAAALQAAAC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAAAALQAAAC0AAAAtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - - ind: -4,0 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - - ind: -4,1 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - - ind: -4,-1 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - ind: 0,2 tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== - ind: 1,2 @@ -221,8 +213,6 @@ entities: - pos: 3.9415665,-8.34479 parent: 104 type: Transform - - canCollide: False - type: Physics - solution: drink type: DrainableSolution - uid: 16 @@ -238,8 +228,6 @@ entities: - pos: 3.5882664,-8.344303 parent: 104 type: Transform - - canCollide: False - type: Physics - uid: 18 type: computerBodyScanner components: @@ -293,8 +281,6 @@ entities: - pos: -0.5303154,-6.2851996 parent: 104 type: Transform - - canCollide: False - type: Physics - solution: drink type: DrainableSolution - uid: 26 @@ -303,8 +289,6 @@ entities: - pos: 4.4214306,-6.3946886 parent: 104 type: Transform - - canCollide: False - type: Physics - uid: 27 type: Windoor components: @@ -792,7 +776,7 @@ entities: - name: Syndicate Outpost type: MetaData - pos: -23.318382,8.069332 - parent: null + parent: 1291 type: Transform - whitelist: tags: @@ -800,8 +784,8 @@ entities: type: FTLDestination - index: 0 type: MapGrid - - angularDamping: 100 - linearDamping: 50 + - angularDamping: 0.05 + linearDamping: 0.05 fixedRotation: False bodyType: Dynamic type: Physics @@ -1119,47 +1103,47 @@ entities: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-13 - 171: - color: '#FFFFFFFF' - id: WarnLineS - coordinates: -9,-15 - 170: + 166: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-14 - 173: + 167: color: '#FFFFFFFF' id: WarnLineS - coordinates: -9,-17 - 172: + coordinates: -9,-15 + 168: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-16 - 174: + 169: + color: '#FFFFFFFF' + id: WarnLineS + coordinates: -9,-17 + 170: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-18 - 175: + 171: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-19 - 176: + 172: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-20 - 177: + 173: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-21 - 178: + 174: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-22 - 179: + 175: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-23 - 180: + 176: color: '#FFFFFFFF' id: WarnLineS coordinates: -9,-24 @@ -1533,19 +1517,19 @@ entities: color: '#FFFFFFFF' id: Caution coordinates: -18,1 - 164: + 162: color: '#FFFFFFFF' id: WarningLine coordinates: -18,1 - 167: + 163: color: '#FFFFFFFF' id: Box coordinates: -14,1 - 168: + 164: color: '#FFFFFFFF' id: StandClear coordinates: -14,1 - 169: + 165: color: '#FFFFFFFF' id: WarnEnd coordinates: -6,21 @@ -5703,6 +5687,46 @@ entities: 18,32: 0 19,32: 0 20,32: 0 + -32,1: 1 + -32,2: 1 + -32,3: 1 + -32,4: 1 + -31,1: 1 + -31,2: 1 + -31,3: 1 + -31,4: 1 + -30,1: 1 + -30,2: 1 + -30,3: 1 + -30,4: 1 + -29,1: 1 + -29,2: 1 + -29,3: 1 + -29,4: 1 + -28,1: 1 + -28,2: 1 + -28,3: 1 + -28,4: 1 + -27,1: 1 + -27,2: 1 + -27,3: 1 + -27,4: 1 + -26,1: 1 + -26,2: 1 + -26,3: 1 + -26,4: 1 + -35,1: 1 + -35,2: 1 + -35,3: 1 + -35,4: 1 + -34,1: 1 + -34,2: 1 + -34,3: 1 + -34,4: 1 + -33,1: 1 + -33,2: 1 + -33,3: 1 + -33,4: 1 uniqueMixes: - volume: 2500 temperature: 293.15 @@ -5715,6 +5739,17 @@ entities: - 0 - 0 - 0 + - volume: 2500 + temperature: 293.15 + moles: + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 type: GridAtmosphere - uid: 105 type: WallRiveted @@ -13554,6 +13589,32 @@ entities: - pos: -10.5,-1.5 parent: 104 type: Transform +- uid: 1291 + components: + - index: 2 + type: Map + - footstepSoundCollection: + collection: footstep_snow + type: FootstepModifier + - gravityShakeSound: !type:SoundPathSpecifier + path: /Audio/Effects/alert.ogg + type: Gravity + - parallax: Sky + type: Parallax + - space: False + mixture: + volume: 2500 + temperature: 248.15 + moles: + - 21.824879 + - 82.10312 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + type: MapAtmosphere - uid: 1298 type: AsteroidRock components: diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml b/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml index 481e0f3845..b125267b52 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/misc.yml @@ -43,7 +43,6 @@ - type: Clothing sprite: Clothing/Shoes/Misc/duck-slippers.rsi - type: FootstepModifier - variation: 0.07 footstepSoundCollection: collection: footstep_duck diff --git a/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml b/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml index 2920f6f1ea..9b0749c73f 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/bike_horn.yml @@ -16,7 +16,6 @@ - type: EmitSoundOnUse sound: collection: BikeHorn - variation: 0.125 - type: UseDelay delay: 0.5 - type: EmitSoundOnTrigger diff --git a/Resources/Prototypes/Parallaxes/default.yml b/Resources/Prototypes/Parallaxes/default.yml index 103df902ab..05f5c1668e 100644 --- a/Resources/Prototypes/Parallaxes/default.yml +++ b/Resources/Prototypes/Parallaxes/default.yml @@ -1,5 +1,5 @@ - type: parallax - id: default + id: Default layers: - texture: !type:ImageParallaxTextureSource @@ -33,3 +33,41 @@ configPath: "/Prototypes/Parallaxes/parallax_config.toml" slowness: 0.875 layersLQUseHQ: false + +# Because hyperspace and the menu need their own. +- type: parallax + id: FastSpace + layers: + - texture: + !type:ImageParallaxTextureSource + path: "/Textures/Parallaxes/layer1.png" + slowness: 0.5 + scale: "1, 1" + - texture: + !type:GeneratedParallaxTextureSource + id: "hq_wizard_stars" + configPath: "/Prototypes/Parallaxes/parallax_config_stars.toml" + slowness: 0.25 + - texture: + !type:GeneratedParallaxTextureSource + id: "hq_wizards_star_slower" + configPath: "/Prototypes/Parallaxes/parallax_config_stars-2.toml" + slowness: 0.15 + - texture: + !type:GeneratedParallaxTextureSource + id: "hq_wizard_stars_dim" + configPath: "/Prototypes/Parallaxes/parallax_config_stars_dim.toml" + slowness: 0.375 + - texture: + !type:GeneratedParallaxTextureSource + id: "hq_wizard_stars_dim_faster" + configPath: "/Prototypes/Parallaxes/parallax_config_stars_dim-2.toml" + slowness: 0.125 + layersLQ: + - texture: + !type:GeneratedParallaxTextureSource + id: "" + configPath: "/Prototypes/Parallaxes/parallax_config.toml" + slowness: 0.5 + layersLQUseHQ: false + diff --git a/Resources/Prototypes/Parallaxes/planet.yml b/Resources/Prototypes/Parallaxes/planet.yml new file mode 100644 index 0000000000..df2373628e --- /dev/null +++ b/Resources/Prototypes/Parallaxes/planet.yml @@ -0,0 +1,24 @@ +- type: parallax + id: Sky + layers: + - texture: + !type:ImageParallaxTextureSource + path: "/Textures/Parallaxes/land.png" + slowness: 0.98 + scale: 1,1 + - texture: + !type:ImageParallaxTextureSource + path: "/Textures/Parallaxes/noise.png" + slowness: 0.95 + scale: "2, 2" + scrolling: "0.1, -0.05" + +- type: parallax + id: Snow + layers: + - texture: + !type:ImageParallaxTextureSource + path: "/Textures/Tiles/snow.png" + slowness: 0 + scale: "1, 1" + shader: "" diff --git a/Resources/Textures/Parallaxes/land.png b/Resources/Textures/Parallaxes/land.png new file mode 100644 index 0000000000..77e21295f5 Binary files /dev/null and b/Resources/Textures/Parallaxes/land.png differ diff --git a/Resources/Textures/Parallaxes/licences.txt b/Resources/Textures/Parallaxes/licences.txt new file mode 100644 index 0000000000..8e88338cb3 --- /dev/null +++ b/Resources/Textures/Parallaxes/licences.txt @@ -0,0 +1,4 @@ +land.png generated from https://cpetry.github.io/TextureGenerator-Online/ +Licensed under MIT at https://github.com/cpetry/TextureGenerator-Online/blob/gh-pages/LICENSE + +noise.png generated from https://giggster.com/guide/cloud-texture-generator/ \ No newline at end of file diff --git a/Resources/Textures/Parallaxes/noise.png b/Resources/Textures/Parallaxes/noise.png new file mode 100644 index 0000000000..b6541886f2 Binary files /dev/null and b/Resources/Textures/Parallaxes/noise.png differ