| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- using System.Linq;
- using Content.Server.Chat.Systems;
- using Content.Server.Station.Systems;
- using Content.Shared.CCVar;
- using Robust.Shared.Audio;
- using Robust.Shared.Audio.Systems;
- using Robust.Shared.Configuration;
- using Robust.Shared.Prototypes;
- namespace Content.Server.AlertLevel;
- public sealed class AlertLevelSystem : EntitySystem
- {
- [Dependency] private readonly IConfigurationManager _cfg = default!;
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly ChatSystem _chatSystem = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
- [Dependency] private readonly StationSystem _stationSystem = default!;
- // Until stations are a prototype, this is how it's going to have to be.
- public const string DefaultAlertLevelSet = "stationAlerts";
- public override void Initialize()
- {
- SubscribeLocalEvent<StationInitializedEvent>(OnStationInitialize);
- SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypeReload);
- }
- public override void Update(float time)
- {
- var query = EntityQueryEnumerator<AlertLevelComponent>();
- while (query.MoveNext(out var station, out var alert))
- {
- if (alert.CurrentDelay <= 0)
- {
- if (alert.ActiveDelay)
- {
- RaiseLocalEvent(new AlertLevelDelayFinishedEvent());
- alert.ActiveDelay = false;
- }
- continue;
- }
- alert.CurrentDelay -= time;
- }
- }
- private void OnStationInitialize(StationInitializedEvent args)
- {
- if (!TryComp<AlertLevelComponent>(args.Station, out var alertLevelComponent))
- return;
- if (!_prototypeManager.TryIndex(alertLevelComponent.AlertLevelPrototype, out AlertLevelPrototype? alerts))
- {
- return;
- }
- alertLevelComponent.AlertLevels = alerts;
- var defaultLevel = alertLevelComponent.AlertLevels.DefaultLevel;
- if (string.IsNullOrEmpty(defaultLevel))
- {
- defaultLevel = alertLevelComponent.AlertLevels.Levels.Keys.First();
- }
- SetLevel(args.Station, defaultLevel, false, false, true);
- }
- private void OnPrototypeReload(PrototypesReloadedEventArgs args)
- {
- if (!args.ByType.TryGetValue(typeof(AlertLevelPrototype), out var alertPrototypes)
- || !alertPrototypes.Modified.TryGetValue(DefaultAlertLevelSet, out var alertObject)
- || alertObject is not AlertLevelPrototype alerts)
- {
- return;
- }
- var query = EntityQueryEnumerator<AlertLevelComponent>();
- while (query.MoveNext(out var uid, out var comp))
- {
- comp.AlertLevels = alerts;
- if (!comp.AlertLevels.Levels.ContainsKey(comp.CurrentLevel))
- {
- var defaultLevel = comp.AlertLevels.DefaultLevel;
- if (string.IsNullOrEmpty(defaultLevel))
- {
- defaultLevel = comp.AlertLevels.Levels.Keys.First();
- }
- SetLevel(uid, defaultLevel, true, true, true);
- }
- }
- RaiseLocalEvent(new AlertLevelPrototypeReloadedEvent());
- }
- public string GetLevel(EntityUid station, AlertLevelComponent? alert = null)
- {
- if (!Resolve(station, ref alert))
- {
- return string.Empty;
- }
- return alert.CurrentLevel;
- }
- public float GetAlertLevelDelay(EntityUid station, AlertLevelComponent? alert = null)
- {
- if (!Resolve(station, ref alert))
- {
- return float.NaN;
- }
- return alert.CurrentDelay;
- }
- /// <summary>
- /// Set the alert level based on the station's entity ID.
- /// </summary>
- /// <param name="station">Station entity UID.</param>
- /// <param name="level">Level to change the station's alert level to.</param>
- /// <param name="playSound">Play the alert level's sound.</param>
- /// <param name="announce">Say the alert level's announcement.</param>
- /// <param name="force">Force the alert change. This applies if the alert level is not selectable or not.</param>
- /// <param name="locked">Will it be possible to change level by crew.</param>
- public void SetLevel(EntityUid station, string level, bool playSound, bool announce, bool force = false,
- bool locked = false, MetaDataComponent? dataComponent = null, AlertLevelComponent? component = null)
- {
- if (!Resolve(station, ref component, ref dataComponent)
- || component.AlertLevels == null
- || !component.AlertLevels.Levels.TryGetValue(level, out var detail)
- || component.CurrentLevel == level)
- {
- return;
- }
- if (!force)
- {
- if (!detail.Selectable
- || component.CurrentDelay > 0
- || component.IsLevelLocked)
- {
- return;
- }
- component.CurrentDelay = _cfg.GetCVar(CCVars.GameAlertLevelChangeDelay);
- component.ActiveDelay = true;
- }
- component.CurrentLevel = level;
- component.IsLevelLocked = locked;
- var stationName = dataComponent.EntityName;
- var name = level.ToLower();
- if (Loc.TryGetString($"alert-level-{level}", out var locName))
- {
- name = locName.ToLower();
- }
- // Announcement text. Is passed into announcementFull.
- var announcement = detail.Announcement;
- if (Loc.TryGetString(detail.Announcement, out var locAnnouncement))
- {
- announcement = locAnnouncement;
- }
- // The full announcement to be spat out into chat.
- var announcementFull = Loc.GetString("alert-level-announcement", ("name", name), ("announcement", announcement));
- var playDefault = false;
- if (playSound)
- {
- if (detail.Sound != null)
- {
- var filter = _stationSystem.GetInOwningStation(station);
- _audio.PlayGlobal(detail.Sound, filter, true, detail.Sound.Params);
- }
- else
- {
- playDefault = true;
- }
- }
- if (announce)
- {
- _chatSystem.DispatchStationAnnouncement(station, announcementFull, playDefaultSound: playDefault,
- colorOverride: detail.Color, sender: stationName);
- }
- RaiseLocalEvent(new AlertLevelChangedEvent(station, level));
- }
- }
- public sealed class AlertLevelDelayFinishedEvent : EntityEventArgs
- {}
- public sealed class AlertLevelPrototypeReloadedEvent : EntityEventArgs
- {}
- public sealed class AlertLevelChangedEvent : EntityEventArgs
- {
- public EntityUid Station { get; }
- public string AlertLevel { get; }
- public AlertLevelChangedEvent(EntityUid station, string alertLevel)
- {
- Station = station;
- AlertLevel = alertLevel;
- }
- }
|