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