using Content.Shared._Scp.Audio;
using Content.Shared._Scp.Audio.Components;
using Content.Shared._Scp.ScpCCVars;
using Content.Client._Scp.Audio.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Components;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client._Scp.Audio;
///
/// Система, накладывающая эффект эхо каждому неглобальному звуку.
/// Эффект может быть отключен игроком в настройках
///
public sealed class EchoEffectSystem : EntitySystem
{
[Dependency] private readonly AudioEffectsManagerSystem _effectsManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private static readonly ProtoId StandardEchoEffectPreset = "Bathroom";
private static readonly ProtoId StrongEchoEffectPreset = "SewerPipe";
private bool _isClientSideEnabled;
private bool _strongPresetPreferred;
public override void Initialize()
{
base.Initialize();
// Форсируем статическую инициализацию CVars ДО всех GetCVar (фикс проблемы с регистрацией)
var _ = ScpCCVars.EchoEnabled;
SubscribeLocalEvent(OnAudioAdd);
SubscribeLocalEvent(OnEffectedAudioStartup, after: [typeof(SharedAudioSystem)]);
_isClientSideEnabled = _cfg.GetCVar(ScpCCVars.EchoEnabled);
_strongPresetPreferred = _cfg.GetCVar(ScpCCVars.EchoStrongPresetPreferred);
_cfg.OnValueChanged(ScpCCVars.EchoEnabled, OnEnabledToggled);
_cfg.OnValueChanged(ScpCCVars.EchoStrongPresetPreferred, OnPreferredPresetToggled);
}
public override void Shutdown()
{
base.Shutdown();
_cfg.UnsubValueChanged(ScpCCVars.EchoEnabled, OnEnabledToggled);
_cfg.UnsubValueChanged(ScpCCVars.EchoStrongPresetPreferred, OnPreferredPresetToggled);
}
private void OnAudioAdd(Entity ent, ref ComponentAdd args)
{
if (!_isClientSideEnabled)
return;
EnsureComp(ent);
}
private void OnEffectedAudioStartup(Entity ent, ref ComponentStartup args)
{
if (!_isClientSideEnabled)
return;
if (!TryComp(ent.Owner, out var audio))
return;
TryApplyEcho((ent.Owner, audio));
}
///
/// Пытается применить эхо к данном звуку
///
/// Звук, к которому будет применен эффект
/// Пресет, если нужно выставить какой-то особенный
/// Получилось или не получилось применить эффект
public bool TryApplyEcho(Entity sound, ProtoId? preset = null)
{
if (TerminatingOrDeleted(sound) || Paused(sound))
return false;
// Фоновая музыка не должна подвергаться эффектам эха
if (sound.Comp.Global)
return false;
// Выбираем пресет для эха исходя из настроек игрока и возможного приоритетного эффекта при вызове извне системы
var clientPreferredPreset = _strongPresetPreferred ? StrongEchoEffectPreset : StandardEchoEffectPreset;
var targetPreset = preset ?? clientPreferredPreset;
_effectsManager.TryAddEffect(sound, targetPreset);
// Добавляем компонент-маркер к звуку, который будет хранить эффект эха
var echoComp = EnsureComp(sound);
echoComp.Preset = targetPreset;
return true;
}
///
/// Пытается убрать эффект эхо у выбранного звука
///
public bool TryRemoveEcho(Entity sound, AudioEchoEffectAffectedComponent? echoComp = null)
{
if (!Resolve(sound, ref echoComp))
return false;
if (!_effectsManager.TryRemoveEffect(sound, echoComp.Preset))
return false;
return true;
}
private void OnEnabledToggled(bool enabled)
{
_isClientSideEnabled = enabled;
if (!enabled)
RevertChanges();
}
private void OnPreferredPresetToggled(bool useStrong)
{
_strongPresetPreferred = useStrong;
var newPreferredPreset = useStrong ? StrongEchoEffectPreset : StandardEchoEffectPreset;
TogglePreset(newPreferredPreset);
}
///
/// Убирает эффекты эхо у всех звуков, что имеют его.
/// Вызывается при выключении эффекта эха игроком.
///
private void RevertChanges()
{
var query = AllEntityQuery();
while (query.MoveNext(out var uid, out var echoComp, out var audio))
{
TryRemoveEcho((uid, audio), echoComp);
}
}
private void TogglePreset(ProtoId newPreferredPreset)
{
var query = AllEntityQuery();
while (query.MoveNext(out var uid, out var echoComp, out var audio))
{
if (!TryRemoveEcho((uid, audio), echoComp))
continue;
TryApplyEcho((uid, audio), newPreferredPreset);
}
}
}