using Content.Server.Administration.Logs; using Content.Server.Chat.Systems; using Content.Server.Station.Systems; using Content.Server.StationEvents.Components; using Content.Shared.Database; using Content.Shared.GameTicking.Components; using Content.Shared.GameTicking.Rules; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; namespace Content.Server.StationEvents.Events; /// /// An abstract entity system inherited by all station events for their behavior. /// public abstract partial class StationEventSystem : GameRuleSystem where T : IComponent { [Dependency] protected IAdminLogManager AdminLogManager = default!; [Dependency] protected ChatSystem ChatSystem = default!; [Dependency] protected SharedAudioSystem Audio = default!; [Dependency] protected ServerStationSystem Station = default!; protected ISawmill Sawmill = default!; public override void Initialize() { base.Initialize(); Sawmill = LogManager.GetSawmill("stationevents"); } /// protected override void Added(Entity ent, ref GameRuleAddedEvent args) { base.Added(ent, ref args); if (!TryComp(ent, out var stationEvent)) return; AdminLogManager.Add(LogType.EventAnnounced, $"Event added / announced: {ToPrettyString(ent)}"); // we don't want to send to players who aren't in game (i.e. in the lobby) Filter allPlayersInGame = Filter.Empty().AddWhere(GameTicker.UserHasJoinedGame); if (stationEvent.StartAnnouncement != null) ChatSystem.DispatchFilteredAnnouncement(allPlayersInGame, Loc.GetString(stationEvent.StartAnnouncement), playSound: false, colorOverride: stationEvent.StartAnnouncementColor); Audio.PlayGlobal(stationEvent.StartAudio, allPlayersInGame, true); } /// protected override void Started(Entity ent, ref GameRuleStartedEvent args) { base.Started(ent, ref args); if (!TryComp(ent, out var stationEvent)) return; AdminLogManager.Add(LogType.EventStarted, LogImpact.High, $"Event started: {ToPrettyString(ent)}"); if (stationEvent.Duration != null) { var duration = stationEvent.MaxDuration == null ? stationEvent.Duration : TimeSpan.FromSeconds(RobustRandom.NextDouble(stationEvent.Duration.Value.TotalSeconds, stationEvent.MaxDuration.Value.TotalSeconds)); stationEvent.EndTime = Timing.CurTime + duration; } } /// protected override void Ended(Entity rule, ref GameRuleEndedEvent args) { base.Ended(rule, ref args); if (!TryComp(rule, out var stationEvent)) return; AdminLogManager.Add(LogType.EventStopped, $"Event ended: {ToPrettyString(rule)}"); // we don't want to send to players who aren't in game (i.e. in the lobby) Filter allPlayersInGame = Filter.Empty().AddWhere(GameTicker.UserHasJoinedGame); if (stationEvent.EndAnnouncement != null) ChatSystem.DispatchFilteredAnnouncement(allPlayersInGame, Loc.GetString(stationEvent.EndAnnouncement), playSound: false, colorOverride: stationEvent.EndAnnouncementColor); Audio.PlayGlobal(stationEvent.EndAudio, allPlayersInGame, true); } /// /// Called every tick when this event is running. /// Events are responsible for their own lifetime, so this handles starting and ending after time. /// /// public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var stationEvent, out var ruleData)) { if (!GameTicker.IsGameRuleAdded((uid, ruleData))) continue; if (!GameTicker.IsGameRuleActive((uid, ruleData)) && !HasComp(uid)) { GameTicker.StartGameRule((uid, ruleData)); } else if (stationEvent.EndTime != null && Timing.CurTime >= stationEvent.EndTime && GameTicker.IsGameRuleActive((uid, ruleData))) { GameTicker.EndGameRule((uid, ruleData)); } } } }