#nullable enable using Content.Server.Interfaces.Chat; using Robust.Shared.GameObjects.Systems; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.Audio; using Robust.Shared.IoC; namespace Content.Server.StationEvents { public abstract class StationEvent { public const float WeightVeryLow = 0.0f; public const float WeightLow = 5.0f; public const float WeightNormal = 10.0f; public const float WeightHigh = 15.0f; public const float WeightVeryHigh = 20.0f; /// /// If the event has started and is currently running. /// public bool Running { get; set; } /// /// Human-readable name for the event. /// public abstract string Name { get; } /// /// The weight this event has in the random-selection process. /// public virtual float Weight => WeightNormal; /// /// What should be said in chat when the event starts (if anything). /// public virtual string? StartAnnouncement { get; set; } = null; /// /// What should be said in chat when the event ends (if anything). /// protected virtual string? EndAnnouncement { get; } = null; /// /// Starting audio of the event. /// public virtual string? StartAudio { get; set; } = null; /// /// Ending audio of the event. /// public virtual string? EndAudio { get; } = null; /// /// In minutes, when is the first round time this event can start /// public virtual int EarliestStart { get; } = 5; /// /// When in the lifetime to call Start(). /// protected virtual float StartAfter { get; } = 0.0f; /// /// When in the lifetime the event should end. /// protected virtual float EndAfter { get; set; } = 0.0f; /// /// How long has the event existed. Do not change this. /// private float Elapsed { get; set; } = 0.0f; /// /// How many players need to be present on station for the event to run /// /// /// To avoid running deadly events with low-pop /// public virtual int MinimumPlayers { get; } = 0; /// /// How many times this event has run this round /// public int Occurrences { get; set; } = 0; /// /// How many times this even can occur in a single round /// public virtual int? MaxOccurrences { get; } = null; /// /// Has the startup time elapsed? /// protected bool Started { get; set; } = false; /// /// Has this event commenced (announcement may or may not be used)? /// private bool Announced { get; set; } = false; /// /// Called once to setup the event after StartAfter has elapsed. /// public virtual void Startup() { Started = true; Occurrences += 1; } /// /// Called once as soon as an event is active. /// Can also be used for some initial setup. /// public virtual void Announce() { if (StartAnnouncement != null) { var chatManager = IoCManager.Resolve(); chatManager.DispatchStationAnnouncement(StartAnnouncement); } if (StartAudio != null) { EntitySystem.Get().PlayGlobal(StartAudio, AudioParams.Default.WithVolume(-10f)); } Announced = true; Running = true; } /// /// Called once when the station event ends for any reason. /// public virtual void Shutdown() { if (EndAnnouncement != null) { var chatManager = IoCManager.Resolve(); chatManager.DispatchStationAnnouncement(EndAnnouncement); } if (EndAudio != null) { EntitySystem.Get().PlayGlobal(EndAudio, AudioParams.Default.WithVolume(-10f)); } Started = false; Announced = false; Elapsed = 0; } /// /// Called every tick when this event is running. /// /// public virtual void Update(float frameTime) { Elapsed += frameTime; if (!Started && Elapsed >= StartAfter) { Startup(); } if (EndAfter <= Elapsed) { Running = false; } } } }