Files
wwdpublic/Content.Client/Weather/WeatherSystem.cs
Spatison 1cd5b0ac0a [Fix] Massive Bug Fixes / Массовое Исправление Багов (#131)
* fix

* fix

* fix

* fix

* fix

* Fix Bug with Opening Storage Containers (#1292)

<!--
This is a semi-strict format, you can add/remove sections as needed but
the order/format should be kept the same
Remove these comments before submitting
-->

# Description

<!--
Explain this PR in as much detail as applicable

Some example prompts to consider:
How might this affect the game? The codebase?
What might be some alternatives to this?
How/Who does this benefit/hurt [the game/codebase]?
-->

Fixes the bug with opening storage containers while there's already one
opened.

---

# Changelog

<!--
You can add an author after the `🆑` to change the name that appears
in the changelog (ex: `🆑 Death`)
Leaving it blank will default to your GitHub display name
This includes all available types for the changelog
-->

🆑
- fix: Fixed the bug with opening storage containers while there's
already one open.

(cherry picked from commit b0407604ced2859ccbdc417345dadc29656f71f0)

* Automatic Changelog Update (#1292)

(cherry picked from commit 9a40c3783eb0d0e622badc2febcaf0794f6f8ddd)

* possible test fix

* possible test fix

* fix

---------

Co-authored-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com>
Co-authored-by: SimpleStation Changelogs <simplestation14@users.noreply.github.com>
2024-12-01 20:41:08 +07:00

168 lines
5.9 KiB
C#

using System.Numerics;
using Content.Shared.Weather;
using Robust.Client.Audio;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Shared.Audio.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Player;
using AudioComponent = Robust.Shared.Audio.Components.AudioComponent;
namespace Content.Client.Weather;
public sealed class WeatherSystem : SharedWeatherSystem
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly MapSystem _mapSystem = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<WeatherComponent, ComponentHandleState>(OnWeatherHandleState);
}
protected override void Run(EntityUid uid, WeatherData weather, WeatherPrototype weatherProto, float frameTime)
{
base.Run(uid, weather, weatherProto, frameTime);
var ent = _playerManager.LocalEntity;
if (ent == null)
return;
var mapUid = Transform(uid).MapUid;
var entXform = Transform(ent.Value);
// Maybe have the viewports manage this?
if (mapUid == null || entXform.MapUid != mapUid)
{
weather.Stream = _audio.Stop(weather.Stream);
return;
}
if (!Timing.IsFirstTimePredicted || weatherProto.Sound == null)
return;
// WD EDIT START
weather.Stream ??= _audio.PlayGlobal(weatherProto.Sound, Filter.Local(), true)?.Entity;
if (!TryComp(weather.Stream, out AudioComponent? comp))
return;
// WD EDIT END
var occlusion = 0f;
// Work out tiles nearby to determine volume.
if (TryComp<MapGridComponent>(entXform.GridUid, out var grid))
{
var gridId = entXform.GridUid.Value;
// Floodfill to the nearest tile and use that for audio.
var seed = _mapSystem.GetTileRef(gridId, grid, entXform.Coordinates);
var frontier = new Queue<TileRef>();
frontier.Enqueue(seed);
// If we don't have a nearest node don't play any sound.
EntityCoordinates? nearestNode = null;
var visited = new HashSet<Vector2i>();
while (frontier.TryDequeue(out var node))
{
if (!visited.Add(node.GridIndices))
continue;
if (!CanWeatherAffect(grid, node))
{
// Add neighbors
// TODO: Ideally we pick some deterministically random direction and use that
// We can't just do that naively here because it will flicker between nearby tiles.
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (Math.Abs(x) == 1 && Math.Abs(y) == 1 ||
x == 0 && y == 0 ||
(new Vector2(x, y) + node.GridIndices - seed.GridIndices).Length() > 3)
{
continue;
}
frontier.Enqueue(_mapSystem.GetTileRef(gridId, grid, new Vector2i(x, y) + node.GridIndices));
}
}
continue;
}
nearestNode = new EntityCoordinates(entXform.GridUid.Value,
node.GridIndices + grid.TileSizeHalfVector);
break;
}
// 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
{
occlusion = 3f;
}
}
var alpha = GetPercent(weather, uid);
alpha *= SharedAudioSystem.VolumeToGain(weatherProto.Sound.Params.Volume);
_audio.SetGain(weather.Stream, alpha, comp); // WD EDIR
comp.Occlusion = occlusion;
}
protected override bool SetState(EntityUid uid, WeatherState state, WeatherComponent comp, WeatherData weather, WeatherPrototype weatherProto)
{
if (!base.SetState(uid, state, comp, weather, weatherProto))
return false;
if (!Timing.IsFirstTimePredicted)
return true;
// TODO: Fades (properly)
weather.Stream = _audio.Stop(weather.Stream);
weather.Stream = _audio.PlayGlobal(weatherProto.Sound, Filter.Local(), true)?.Entity;
return true;
}
private void OnWeatherHandleState(EntityUid uid, WeatherComponent component, ref ComponentHandleState args)
{
if (args.Current is not WeatherComponentState state)
return;
foreach (var (proto, weather) in component.Weather)
{
// End existing one
if (!state.Weather.TryGetValue(proto, out var stateData))
{
EndWeather(uid, component, proto);
continue;
}
// Data update?
weather.StartTime = stateData.StartTime;
weather.EndTime = stateData.EndTime;
weather.State = stateData.State;
}
foreach (var (proto, weather) in state.Weather)
{
if (component.Weather.ContainsKey(proto))
continue;
// New weather
StartWeather(uid, component, ProtoMan.Index<WeatherPrototype>(proto), weather.EndTime);
}
}
}