Files
crystall-punk-14/Content.Server/StationEvents/Events/MeteorSwarm.cs
Kara b9a0894d7c Event refactor (#9589)
* Station event refactor

* Remove clientside `IStationEventManager`

we can just use prototypes

* Basic API idea

* Cruft

* first attempt at epicness

* okay yeah this shit is really clean

* sort out minor stuff

* Convert `BreakerFlip`

* `BureaucraticError` + general cleanup

* `DiseaseOutbreak`

* `FalseAlarm`

* `GasLeak`

* `KudzuGrowth`

* `MeteorSwarm`

* `MouseMigration`

* misc errors

* `PowerGridCheck`

* `RandomSentience`

* `VentClog`

* `VentCritters`

* `ZombieOutbreak`

* Rewrite basic event scheduler

* Minor fixes and logging

* ooooops

* errors + fix

* linter

* completions, `RuleStarted` property, update loop fixes

* Tweaks

* Fix #9462

* Basic scheduler update fix, and fixes #8174

* Add test

* UI cleanup

* really this was just for testing
2022-07-10 20:48:41 -05:00

109 lines
3.8 KiB
C#

using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.Projectiles.Components;
using Content.Shared.Sound;
using Content.Shared.Spawners.Components;
using Robust.Shared.Map;
using Robust.Shared.Random;
namespace Content.Server.StationEvents.Events
{
public sealed class MeteorSwarm : StationEventSystem
{
public override string Prototype => "MeteorSwarm";
private float _cooldown;
/// <summary>
/// We'll send a specific amount of waves of meteors towards the station per ending rather than using a timer.
/// </summary>
private int _waveCounter;
private const int MinimumWaves = 3;
private const int MaximumWaves = 8;
private const float MinimumCooldown = 10f;
private const float MaximumCooldown = 60f;
private const int MeteorsPerWave = 5;
private const float MeteorVelocity = 10f;
private const float MaxAngularVelocity = 0.25f;
private const float MinAngularVelocity = -0.25f;
public override void Started()
{
base.Started();
_waveCounter = RobustRandom.Next(MinimumWaves, MaximumWaves);
}
public override void Ended()
{
base.Ended();
_waveCounter = 0;
_cooldown = 0f;
}
public override void Update(float frameTime)
{
base.Update(frameTime);
if (!RuleStarted)
return;
if (_waveCounter <= 0)
{
ForceEndSelf();
return;
}
_cooldown -= frameTime;
if (_cooldown > 0f) return;
_waveCounter--;
_cooldown += (MaximumCooldown - MinimumCooldown) * RobustRandom.NextFloat() + MinimumCooldown;
Box2? playableArea = null;
var mapId = GameTicker.DefaultMap;
foreach (var grid in MapManager.GetAllGrids())
{
if (grid.ParentMapId != mapId || !EntityManager.TryGetComponent(grid.GridEntityId, out PhysicsComponent? gridBody)) continue;
var aabb = gridBody.GetWorldAABB();
playableArea = playableArea?.Union(aabb) ?? aabb;
}
if (playableArea == null)
{
ForceEndSelf();
return;
}
var minimumDistance = (playableArea.Value.TopRight - playableArea.Value.Center).Length + 50f;
var maximumDistance = minimumDistance + 100f;
var center = playableArea.Value.Center;
for (var i = 0; i < MeteorsPerWave; i++)
{
var angle = new Angle(RobustRandom.NextFloat() * MathF.Tau);
var offset = angle.RotateVec(new Vector2((maximumDistance - minimumDistance) * RobustRandom.NextFloat() + minimumDistance, 0));
var spawnPosition = new MapCoordinates(center + offset, mapId);
var meteor = EntityManager.SpawnEntity("MeteorLarge", spawnPosition);
var physics = EntityManager.GetComponent<PhysicsComponent>(meteor);
physics.BodyStatus = BodyStatus.InAir;
physics.LinearDamping = 0f;
physics.AngularDamping = 0f;
physics.ApplyLinearImpulse(-offset.Normalized * MeteorVelocity * physics.Mass);
physics.ApplyAngularImpulse(
// Get a random angular velocity.
physics.Mass * ((MaxAngularVelocity - MinAngularVelocity) * RobustRandom.NextFloat() +
MinAngularVelocity));
// TODO: God this disgusts me but projectile needs a refactor.
EnsureComp<TimedDespawnComponent>(meteor).Lifetime = 120f;
}
}
}
}