Fix station events that use update loops (#15834)
This commit is contained in:
@@ -5,21 +5,36 @@ namespace Content.Server.StationEvents.Components;
|
|||||||
[RegisterComponent, Access(typeof(MeteorSwarmRule))]
|
[RegisterComponent, Access(typeof(MeteorSwarmRule))]
|
||||||
public sealed class MeteorSwarmRuleComponent : Component
|
public sealed class MeteorSwarmRuleComponent : Component
|
||||||
{
|
{
|
||||||
public float _cooldown;
|
[DataField("cooldown")]
|
||||||
|
public float Cooldown;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer.
|
/// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int _waveCounter;
|
[DataField("waveCounter")]
|
||||||
|
public int WaveCounter;
|
||||||
|
|
||||||
|
[DataField("minimumWaves")]
|
||||||
public int MinimumWaves = 3;
|
public int MinimumWaves = 3;
|
||||||
|
|
||||||
|
[DataField("maximumWaves")]
|
||||||
public int MaximumWaves = 8;
|
public int MaximumWaves = 8;
|
||||||
|
|
||||||
|
[DataField("minimumCooldown")]
|
||||||
public float MinimumCooldown = 10f;
|
public float MinimumCooldown = 10f;
|
||||||
|
|
||||||
|
[DataField("maximumCooldown")]
|
||||||
public float MaximumCooldown = 60f;
|
public float MaximumCooldown = 60f;
|
||||||
|
|
||||||
|
[DataField("meteorsPerWave")]
|
||||||
public int MeteorsPerWave = 5;
|
public int MeteorsPerWave = 5;
|
||||||
|
|
||||||
|
[DataField("meteorVelocity")]
|
||||||
public float MeteorVelocity = 10f;
|
public float MeteorVelocity = 10f;
|
||||||
|
|
||||||
|
[DataField("maxAngularVelocity")]
|
||||||
public float MaxAngularVelocity = 0.25f;
|
public float MaxAngularVelocity = 0.25f;
|
||||||
|
|
||||||
|
[DataField("minAngularVelocity")]
|
||||||
public float MinAngularVelocity = -0.25f;
|
public float MinAngularVelocity = -0.25f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public sealed class StationEventComponent : Component
|
|||||||
/// How long the event lasts.
|
/// How long the event lasts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("duration")]
|
[DataField("duration")]
|
||||||
public TimeSpan Duration = TimeSpan.FromSeconds(1);
|
public TimeSpan? Duration = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The max amount of time the event lasts.
|
/// The max amount of time the event lasts.
|
||||||
@@ -85,5 +85,5 @@ public sealed class StationEventComponent : Component
|
|||||||
/// When the station event starts.
|
/// When the station event starts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
[DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
public TimeSpan EndTime;
|
public TimeSpan? EndTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ public sealed class EventManagerSystem : EntitySystem
|
|||||||
private void OnUnpaused(EntityUid uid, StationEventComponent component, ref EntityUnpausedEvent args)
|
private void OnUnpaused(EntityUid uid, StationEventComponent component, ref EntityUnpausedEvent args)
|
||||||
{
|
{
|
||||||
component.StartTime += args.PausedTime;
|
component.StartTime += args.PausedTime;
|
||||||
component.EndTime += args.PausedTime;
|
if (component.EndTime != null)
|
||||||
|
component.EndTime = component.EndTime.Value + args.PausedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
|
|||||||
@@ -16,13 +16,12 @@ namespace Content.Server.StationEvents.Events
|
|||||||
base.Started(uid, component, gameRule, args);
|
base.Started(uid, component, gameRule, args);
|
||||||
|
|
||||||
var mod = Math.Sqrt(GetSeverityModifier());
|
var mod = Math.Sqrt(GetSeverityModifier());
|
||||||
component._waveCounter = (int) (RobustRandom.Next(component.MinimumWaves, component.MaximumWaves) * mod);
|
component.WaveCounter = (int) (RobustRandom.Next(component.MinimumWaves, component.MaximumWaves) * mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ActiveTick(EntityUid uid, MeteorSwarmRuleComponent component, GameRuleComponent gameRule, float frameTime)
|
protected override void ActiveTick(EntityUid uid, MeteorSwarmRuleComponent component, GameRuleComponent gameRule, float frameTime)
|
||||||
{
|
{
|
||||||
base.ActiveTick(uid, component, gameRule, frameTime);
|
if (component.WaveCounter <= 0)
|
||||||
if (component._waveCounter <= 0)
|
|
||||||
{
|
{
|
||||||
ForceEndSelf(uid, gameRule);
|
ForceEndSelf(uid, gameRule);
|
||||||
return;
|
return;
|
||||||
@@ -30,14 +29,14 @@ namespace Content.Server.StationEvents.Events
|
|||||||
|
|
||||||
var mod = GetSeverityModifier();
|
var mod = GetSeverityModifier();
|
||||||
|
|
||||||
component._cooldown -= frameTime;
|
component.Cooldown -= frameTime;
|
||||||
|
|
||||||
if (component._cooldown > 0f)
|
if (component.Cooldown > 0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component._waveCounter--;
|
component.WaveCounter--;
|
||||||
|
|
||||||
component._cooldown += (component.MaximumCooldown - component.MinimumCooldown) * RobustRandom.NextFloat() / mod + component.MinimumCooldown;
|
component.Cooldown += (component.MaximumCooldown - component.MinimumCooldown) * RobustRandom.NextFloat() / mod + component.MinimumCooldown;
|
||||||
|
|
||||||
Box2? playableArea = null;
|
Box2? playableArea = null;
|
||||||
var mapId = GameTicker.DefaultMap;
|
var mapId = GameTicker.DefaultMap;
|
||||||
@@ -64,7 +63,7 @@ namespace Content.Server.StationEvents.Events
|
|||||||
var angle = new Angle(RobustRandom.NextFloat() * MathF.Tau);
|
var angle = new Angle(RobustRandom.NextFloat() * MathF.Tau);
|
||||||
var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0));
|
var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0));
|
||||||
var spawnPosition = new MapCoordinates(center + offset, mapId);
|
var spawnPosition = new MapCoordinates(center + offset, mapId);
|
||||||
var meteor = EntityManager.SpawnEntity("MeteorLarge", spawnPosition);
|
var meteor = Spawn("MeteorLarge", spawnPosition);
|
||||||
var physics = EntityManager.GetComponent<PhysicsComponent>(meteor);
|
var physics = EntityManager.GetComponent<PhysicsComponent>(meteor);
|
||||||
_physics.SetBodyStatus(physics, BodyStatus.InAir);
|
_physics.SetBodyStatus(physics, BodyStatus.InAir);
|
||||||
_physics.SetLinearDamping(physics, 0f);
|
_physics.SetLinearDamping(physics, 0f);
|
||||||
|
|||||||
@@ -69,11 +69,15 @@ public abstract class StationEventSystem<T> : GameRuleSystem<T> where T : Compon
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
AdminLogManager.Add(LogType.EventStarted, LogImpact.High, $"Event started: {ToPrettyString(uid)}");
|
AdminLogManager.Add(LogType.EventStarted, LogImpact.High, $"Event started: {ToPrettyString(uid)}");
|
||||||
var duration = stationEvent.MaxDuration == null
|
|
||||||
? stationEvent.Duration
|
if (stationEvent.Duration != null)
|
||||||
: TimeSpan.FromSeconds(RobustRandom.NextDouble(stationEvent.Duration.TotalSeconds,
|
{
|
||||||
stationEvent.MaxDuration.Value.TotalSeconds));
|
var duration = stationEvent.MaxDuration == null
|
||||||
stationEvent.EndTime = _timing.CurTime + duration;
|
? stationEvent.Duration
|
||||||
|
: TimeSpan.FromSeconds(RobustRandom.NextDouble(stationEvent.Duration.Value.TotalSeconds,
|
||||||
|
stationEvent.MaxDuration.Value.TotalSeconds));
|
||||||
|
stationEvent.EndTime = _timing.CurTime + duration;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -101,6 +105,8 @@ public abstract class StationEventSystem<T> : GameRuleSystem<T> where T : Compon
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
var query = EntityQueryEnumerator<StationEventComponent, GameRuleComponent>();
|
var query = EntityQueryEnumerator<StationEventComponent, GameRuleComponent>();
|
||||||
while (query.MoveNext(out var uid, out var stationEvent, out var ruleData))
|
while (query.MoveNext(out var uid, out var stationEvent, out var ruleData))
|
||||||
{
|
{
|
||||||
@@ -111,7 +117,7 @@ public abstract class StationEventSystem<T> : GameRuleSystem<T> where T : Compon
|
|||||||
{
|
{
|
||||||
GameTicker.StartGameRule(uid, ruleData);
|
GameTicker.StartGameRule(uid, ruleData);
|
||||||
}
|
}
|
||||||
else if (GameTicker.IsGameRuleActive(uid, ruleData) && _timing.CurTime >= stationEvent.EndTime)
|
else if (stationEvent.EndTime != null && _timing.CurTime >= stationEvent.EndTime && GameTicker.IsGameRuleActive(uid, ruleData))
|
||||||
{
|
{
|
||||||
GameTicker.EndGameRule(uid, ruleData);
|
GameTicker.EndGameRule(uid, ruleData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,7 @@
|
|||||||
path: /Audio/Announcements/meteors.ogg
|
path: /Audio/Announcements/meteors.ogg
|
||||||
params:
|
params:
|
||||||
volume: -4
|
volume: -4
|
||||||
|
duration: null #ending is handled by MeteorSwarmRule
|
||||||
startAfter: 30
|
startAfter: 30
|
||||||
- type: MeteorSwarmRule
|
- type: MeteorSwarmRule
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user