diff --git a/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs b/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs index 673c82b20f6..282ee5b612a 100644 --- a/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs +++ b/Content.Server/StationEvents/Components/RampingStationEventSchedulerComponent.cs @@ -4,50 +4,38 @@ public sealed partial class RampingStationEventSchedulerComponent : Component { /// - /// Multiplies the End Time of the Ramping Event curve. Lower this number for shorter, hectic shifts, increase this number for longer shifts. + /// The maximum number by which the event rate will be multiplied when shift time reaches the end time. /// [DataField] - public float ShiftChaosModifier = 1f; + public float ChaosModifier = 3f; /// - /// The number by which all event delays will be multiplied. Unlike chaos, remains constant throughout the shift. + /// The minimum number by which the event rate will be multiplied when the shift has just begun. /// [DataField] - public float EventDelayModifier = 1f; - + public float StartingChaosRatio = 0.1f; /// - /// Shift Length(in Minutes) is directly reduced by this value. - /// - [DataField] - public float ShiftLengthOffset = 0f; - - /// - /// Minimum time between events is decreased by this value. + /// The number by which all event delays will be multiplied. Unlike chaos, remains constant throughout the shift. /// [DataField] - public float MinimumEventTimeOffset = 0f; + public float EventDelayModifier = 1f; /// - /// Maximum time between events is decreased by this value. + /// The number by which average expected shift length is multiplied. Higher values lead to slower chaos growth. /// - - [DataField] - public float MaximumEventTimeOffset = 0f; - - [DataField] - public bool IgnoreMinimumTimes = false; + public float ShiftLengthModifier = 1f; // Everything below is overridden in the RampingStationEventSchedulerSystem based on CVars - [DataField] + [DataField("endTime"), ViewVariables(VVAccess.ReadWrite)] public float EndTime; - [DataField] + [DataField("maxChaos"), ViewVariables(VVAccess.ReadWrite)] public float MaxChaos; - [DataField] + [DataField("startingChaos"), ViewVariables(VVAccess.ReadWrite)] public float StartingChaos; - [DataField] + [DataField("timeUntilNextEvent"), ViewVariables(VVAccess.ReadWrite)] public float TimeUntilNextEvent; } diff --git a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs index e24578fdac9..aa0c9b214b4 100644 --- a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs +++ b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs @@ -2,10 +2,10 @@ using Content.Server.GameTicking.Rules; using Content.Server.GameTicking.Rules.Components; using Content.Server.StationEvents.Components; +using Content.Server.StationEvents.Events; using Content.Shared.CCVar; using Robust.Shared.Configuration; using Robust.Shared.Random; -using Robust.Shared.Utility; namespace Content.Server.StationEvents; @@ -16,35 +16,30 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem - /// A logistic curve equation used to smooth out the transition between event times at shift start, vs. shift end. - /// Depending on the settings used, the end time might not necessarily be the point at which timers hit the floor. - /// It is after all, an asymptote. - /// - /// - /// - /// - /// - public float RampingEventTimeEquation(RampingStationEventSchedulerComponent component, float startTime, float endTimeOffset = 0) + public float GetChaosModifier(EntityUid uid, RampingStationEventSchedulerComponent component) { - var endTime = Math.Clamp(endTimeOffset, 0.1f, startTime - 1); - var shiftLength = Math.Max(1, _cfg.GetCVar(CCVars.EventsRampingAverageEndTime) - component.ShiftLengthOffset); - return 2 * endTime - / (1 - + MathF.Exp(_cfg.GetCVar(CCVars.EventsRampingAverageChaos) - * component.ShiftChaosModifier - / shiftLength - * endTime - * (float) _gameTicker.RoundDuration().TotalSeconds - / 60)) - + (startTime - endTime); + var roundTime = (float) _gameTicker.RoundDuration().TotalSeconds; + if (roundTime > component.EndTime) + return component.MaxChaos; + + return component.MaxChaos / component.EndTime * roundTime + component.StartingChaos; } protected override void Started(EntityUid uid, RampingStationEventSchedulerComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) { base.Started(uid, component, gameRule, args); - PickNextEventTime(component); + var avgChaos = _cfg.GetCVar(CCVars.EventsRampingAverageChaos) * component.ChaosModifier; + var avgTime = _cfg.GetCVar(CCVars.EventsRampingAverageEndTime) * component.ShiftLengthModifier; + + // Worlds shittiest probability distribution + // Got a complaint? Send them to + component.MaxChaos = avgChaos * _random.NextFloat(0.75f, 1.25f); + // This is in minutes, so *60 for seconds (for the chaos calc) + component.EndTime = avgTime * _random.NextFloat(0.75f, 1.25f) * 60f; + component.StartingChaos = component.MaxChaos * component.StartingChaosRatio; + + PickNextEventTime(uid, component); } public override void Update(float frameTime) @@ -66,31 +61,17 @@ public override void Update(float frameTime) return; } - PickNextEventTime(scheduler); + PickNextEventTime(uid, scheduler); _event.RunRandomEvent(); } } - private void PickNextEventTime(RampingStationEventSchedulerComponent component) + private void PickNextEventTime(EntityUid uid, RampingStationEventSchedulerComponent component) { - // In case of server hosts being silly and setting maximum time to be lower than minimum time, sanity check the scheduler inputs and sort them by Min/Max - var minimumTime = MathF.Min(_cfg.GetCVar(CCVars.GameEventsRampingMinimumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMinimumTimeOffset) - - component.MinimumEventTimeOffset, _cfg.GetCVar(CCVars.GameEventsRampingMaximumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMaximumTimeOffset) - - component.MaximumEventTimeOffset); - - var maximumTime = MathF.Max(_cfg.GetCVar(CCVars.GameEventsRampingMinimumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMinimumTimeOffset) - - component.MinimumEventTimeOffset, _cfg.GetCVar(CCVars.GameEventsRampingMaximumTime) - - _cfg.GetCVar(CCVars.GameEventsRampingMaximumTimeOffset) - - component.MaximumEventTimeOffset); - - // Just in case someone messed up their math, set it to between 6 and 12 seconds. This absolutely isn't ideal component.TimeUntilNextEvent = _random.NextFloat( - RampingEventTimeEquation(component, MathF.Max(0.1f, minimumTime)), - RampingEventTimeEquation(component, MathF.Max(0.2f, maximumTime))); + _cfg.GetCVar(CCVars.GameEventsRampingMinimumTime), + _cfg.GetCVar(CCVars.GameEventsRampingMaximumTime)); - component.TimeUntilNextEvent *= component.EventDelayModifier; + component.TimeUntilNextEvent *= component.EventDelayModifier / GetChaosModifier(uid, component); } } diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 0d09dd59f74..985d9da1a18 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -119,7 +119,7 @@ public static readonly CVarDef /// Max chaos chosen for a round will deviate from this /// public static readonly CVarDef - EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 0.8f, CVar.ARCHIVE | CVar.SERVERONLY); + EventsRampingAverageChaos = CVarDef.Create("events.ramping_average_chaos", 6f, CVar.ARCHIVE | CVar.SERVERONLY); /* * Game @@ -186,29 +186,16 @@ public static readonly CVarDef // 25 Minutes GameEventsBasicMaximumTime = CVarDef.Create("game.events_basic_maximum_time", 1500, CVar.SERVERONLY); /// - /// Minimum time between Ramping station events in minutes + /// Minimum time between Ramping station events in seconds /// - public static readonly CVarDef // 8 Minutes - GameEventsRampingMinimumTime = CVarDef.Create("game.events_ramping_minimum_time", 8f, CVar.SERVERONLY); + public static readonly CVarDef // 4 Minutes + GameEventsRampingMinimumTime = CVarDef.Create("game.events_ramping_minimum_time", 240, CVar.SERVERONLY); /// - /// After the shift's desired "Endpoint" is reached, the minimum time between events is RampingMinimumTime - Offset. + /// Maximum time between Ramping station events in seconds /// - - public static readonly CVarDef - GameEventsRampingMinimumTimeOffset = CVarDef.Create("game.events_ramping_minimum_time_offset", 6f, CVar.SERVERONLY); - - /// - /// Maximum time between Ramping station events in minutes - /// - public static readonly CVarDef // 16 Minutes - GameEventsRampingMaximumTime = CVarDef.Create("game.events_ramping_maximum_time", 16f, CVar.SERVERONLY); - - /// - /// After the shift's desired "Endpoint" is reached, the maximum time between events is RampingMaximumTime - Offset. - /// - public static readonly CVarDef - GameEventsRampingMaximumTimeOffset = CVarDef.Create("game.events_ramping_maximum_time_offset", 10f, CVar.SERVERONLY); + public static readonly CVarDef // 12 Minutes + GameEventsRampingMaximumTime = CVarDef.Create("game.events_ramping_maximum_time", 720, CVar.SERVERONLY); /// /// diff --git a/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl b/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl index 10e6a4a24f2..0b8fa83ae8b 100644 --- a/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl +++ b/Resources/Locale/en-US/game-ticking/game-presets/preset-survival.ftl @@ -3,6 +3,3 @@ survival-description = No internal threats, but how long can the station survive hellshift-title = Hellshift hellshift-description = The station rolled a "one" in a luck check. Can the crew make it to the end? - -longsurvival-title = Long Survival -longsurvival-description = Survival, but two hours longer. Event growth is stretched over a vastly greater length of time. diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index e046b871fa7..0af55a7f9d0 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -132,21 +132,15 @@ components: - type: RampingStationEventScheduler -- type: entity - id: LongSurvivalStationEventScheduler - parent: BaseGameRule - noSpawn: true - components: - - type: RampingStationEventScheduler - shiftLengthOffset: -120 - - type: entity id: HellshiftStationEventScheduler parent: BaseGameRule noSpawn: true components: - type: RampingStationEventScheduler - shiftChaosModifier: 4 #30 minute HELL SHIFT + chaosModifier: 4 # By default, one event each 30-10 seconds after two hours. Changing CVars will cause this to deviate. + startingChaosRatio: 0.025 # Starts as slow as survival, but quickly ramps up + shiftLengthModifier: 2.5 # variation passes - type: entity diff --git a/Resources/Prototypes/game_presets.yml b/Resources/Prototypes/game_presets.yml index 7e83f224433..7d7169bf10a 100644 --- a/Resources/Prototypes/game_presets.yml +++ b/Resources/Prototypes/game_presets.yml @@ -20,17 +20,6 @@ - HellshiftStationEventScheduler - BasicRoundstartVariation -- type: gamePreset - id: SurvivalLonger - alias: - - longsurvival - showInVote: true - name: longsurvival-title - description: longsurvival-description - rules: - - LongSurvivalStationEventScheduler - - BasicRoundstartVariation - - type: gamePreset id: AllAtOnce name: all-at-once-title