diff --git a/Content.Client/Overlays/StencilOverlay.Weather.cs b/Content.Client/Overlays/StencilOverlay.Weather.cs index 10a605fd93..31bc88af45 100644 --- a/Content.Client/Overlays/StencilOverlay.Weather.cs +++ b/Content.Client/Overlays/StencilOverlay.Weather.cs @@ -8,6 +8,8 @@ namespace Content.Client.Overlays; public sealed partial class StencilOverlay { + private List> _grids = new(); + private void DrawWeather(in OverlayDrawArgs args, WeatherPrototype weatherProto, float alpha, Matrix3 invMatrix) { var worldHandle = args.WorldHandle; @@ -21,15 +23,13 @@ public sealed partial class StencilOverlay // particularly for planet maps or stations. worldHandle.RenderInRenderTarget(_blep!, () => { - var bodyQuery = _entManager.GetEntityQuery(); var xformQuery = _entManager.GetEntityQuery(); - var weatherIgnoreQuery = _entManager.GetEntityQuery(); + _grids.Clear(); // idk if this is safe to cache in a field and clear sloth help - var grids = new List>(); - _mapManager.FindGridsIntersecting(mapId, worldAABB, ref grids); + _mapManager.FindGridsIntersecting(mapId, worldAABB, ref _grids); - foreach (var grid in grids) + foreach (var grid in _grids) { var matrix = _transform.GetWorldMatrix(grid, xformQuery); Matrix3.Multiply(in matrix, in invMatrix, out var matty); @@ -38,7 +38,7 @@ public sealed partial class StencilOverlay foreach (var tile in grid.Comp.GetTilesIntersecting(worldAABB)) { // Ignored tiles for stencil - if (_weather.CanWeatherAffect(grid, tile, weatherIgnoreQuery, bodyQuery)) + if (_weather.CanWeatherAffect(grid, tile)) { continue; } diff --git a/Content.Client/Weather/WeatherSystem.cs b/Content.Client/Weather/WeatherSystem.cs index df7ccce451..a9c29f96c9 100644 --- a/Content.Client/Weather/WeatherSystem.cs +++ b/Content.Client/Weather/WeatherSystem.cs @@ -5,6 +5,7 @@ using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; using Robust.Shared.GameStates; using Robust.Shared.Map; using Robust.Shared.Map.Components; @@ -24,9 +25,6 @@ public sealed class WeatherSystem : SharedWeatherSystem [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; - private const float OcclusionLerpRate = 4f; - private const float AlphaLerpRate = 4f; - public override void Initialize() { base.Initialize(); @@ -37,7 +35,7 @@ public sealed class WeatherSystem : SharedWeatherSystem { base.Run(uid, weather, weatherProto, frameTime); - var ent = _playerManager.LocalPlayer?.ControlledEntity; + var ent = _playerManager.LocalEntity; if (ent == null) return; @@ -48,8 +46,6 @@ public sealed class WeatherSystem : SharedWeatherSystem // Maybe have the viewports manage this? if (mapUid == null || entXform.MapUid != mapUid) { - weather.LastOcclusion = 0f; - weather.LastAlpha = 0f; weather.Stream = _audio.Stop(weather.Stream); return; } @@ -58,16 +54,10 @@ public sealed class WeatherSystem : SharedWeatherSystem return; weather.Stream ??= _audio.PlayGlobal(weatherProto.Sound, Filter.Local(), true).Value.Entity; - var volumeMod = MathF.Pow(10, weatherProto.Sound.Params.Volume / 10f); var stream = weather.Stream.Value; var comp = Comp(stream); - var alpha = weather.LastAlpha; - alpha = MathF.Pow(alpha, 2f) * volumeMod; - // TODO: Lerp this occlusion. var occlusion = 0f; - // TODO: Fade-out needs to be slower - // TODO: HELPER PLZ // Work out tiles nearby to determine volume. if (TryComp(entXform.GridUid, out var grid)) @@ -79,8 +69,6 @@ public sealed class WeatherSystem : SharedWeatherSystem frontier.Enqueue(seed); // If we don't have a nearest node don't play any sound. EntityCoordinates? nearestNode = null; - var bodyQuery = GetEntityQuery(); - var weatherIgnoreQuery = GetEntityQuery(); var visited = new HashSet(); while (frontier.TryDequeue(out var node)) @@ -88,7 +76,7 @@ public sealed class WeatherSystem : SharedWeatherSystem if (!visited.Add(node.GridIndices)) continue; - if (!CanWeatherAffect(grid, node, weatherIgnoreQuery, bodyQuery)) + if (!CanWeatherAffect(grid, node)) { // Add neighbors // TODO: Ideally we pick some deterministically random direction and use that @@ -112,50 +100,29 @@ public sealed class WeatherSystem : SharedWeatherSystem } nearestNode = new EntityCoordinates(entXform.GridUid.Value, - (Vector2) node.GridIndices + (grid.TileSizeHalfVector)); + node.GridIndices + grid.TileSizeHalfVector); break; } - if (nearestNode == null) - alpha = 0f; + // Get occlusion to the targeted node if it exists, otherwise set a default occlusion. + if (nearestNode != null) + { + var entPos = _transform.GetMapCoordinates(entXform); + var nodePosition = nearestNode.Value.ToMap(EntityManager, _transform).Position; + var delta = nodePosition - entPos.Position; + var distance = delta.Length(); + occlusion = _audio.GetOcclusion(entPos, delta, distance); + } else { - var entPos = _transform.GetWorldPosition(entXform); - var sourceRelative = nearestNode.Value.ToMap(EntityManager).Position - entPos; - - if (sourceRelative.LengthSquared() > 1f) - { - occlusion = _physics.IntersectRayPenetration(entXform.MapID, - new CollisionRay(entPos, sourceRelative.Normalized(), _audio.OcclusionCollisionMask), - sourceRelative.Length(), stream); - } + occlusion = 3f; } } - if (MathHelper.CloseTo(weather.LastOcclusion, occlusion, 0.01f)) - weather.LastOcclusion = occlusion; - else - weather.LastOcclusion += (occlusion - weather.LastOcclusion) * OcclusionLerpRate * frameTime; - - if (MathHelper.CloseTo(weather.LastAlpha, alpha, 0.01f)) - weather.LastAlpha = alpha; - else - weather.LastAlpha += (alpha - weather.LastAlpha) * AlphaLerpRate * frameTime; - - // Full volume if not on grid - comp.Gain = weather.LastAlpha; - comp.Occlusion = weather.LastOcclusion; - } - - protected override void EndWeather(EntityUid uid, WeatherComponent component, string proto) - { - base.EndWeather(uid, component, proto); - - if (!component.Weather.TryGetValue(proto, out var weather)) - return; - - weather.LastAlpha = 0f; - weather.LastOcclusion = 0f; + var alpha = GetPercent(weather, uid); + alpha *= SharedAudioSystem.VolumeToGain(weatherProto.Sound.Params.Volume); + _audio.SetGain(stream, alpha, comp); + comp.Occlusion = occlusion; } protected override bool SetState(WeatherState state, WeatherComponent comp, WeatherData weather, WeatherPrototype weatherProto) @@ -199,7 +166,6 @@ public sealed class WeatherSystem : SharedWeatherSystem // New weather StartWeather(component, ProtoMan.Index(proto), weather.EndTime); - weather.LastAlpha = 0f; } } } diff --git a/Content.Shared/Weather/SharedWeatherSystem.cs b/Content.Shared/Weather/SharedWeatherSystem.cs index d34893f8aa..c907137d84 100644 --- a/Content.Shared/Weather/SharedWeatherSystem.cs +++ b/Content.Shared/Weather/SharedWeatherSystem.cs @@ -19,9 +19,14 @@ public abstract class SharedWeatherSystem : EntitySystem [Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + private EntityQuery _ignoreQuery; + private EntityQuery _physicsQuery; + public override void Initialize() { base.Initialize(); + _ignoreQuery = GetEntityQuery(); + _physicsQuery = GetEntityQuery(); SubscribeLocalEvent(OnWeatherUnpaused); } @@ -38,9 +43,7 @@ public abstract class SharedWeatherSystem : EntitySystem public bool CanWeatherAffect( MapGridComponent grid, - TileRef tileRef, - EntityQuery weatherIgnoreQuery, - EntityQuery bodyQuery) + TileRef tileRef) { if (tileRef.Tile.IsEmpty) return true; @@ -54,8 +57,8 @@ public abstract class SharedWeatherSystem : EntitySystem while (anchoredEnts.MoveNext(out var ent)) { - if (!weatherIgnoreQuery.HasComponent(ent.Value) && - bodyQuery.TryGetComponent(ent, out var body) && + if (!_ignoreQuery.HasComponent(ent.Value) && + _physicsQuery.TryGetComponent(ent, out var body) && body.Hard && body.CanCollide) { diff --git a/Content.Shared/Weather/WeatherComponent.cs b/Content.Shared/Weather/WeatherComponent.cs index bdc7bfdbf9..df73109ac4 100644 --- a/Content.Shared/Weather/WeatherComponent.cs +++ b/Content.Shared/Weather/WeatherComponent.cs @@ -43,12 +43,6 @@ public sealed partial class WeatherData [DataField("state")] public WeatherState State = WeatherState.Invalid; - - [ViewVariables, NonSerialized] - public float LastAlpha; - - [ViewVariables, NonSerialized] - public float LastOcclusion; } public enum WeatherState : byte