Files
tbd-station-14/Content.Server/StationEvents/Events/GasLeakRule.cs
deltanedas a3a1538d32 move gamerule components to shared (#28572)
* move MinMax to shared

* cleanup MinMax

* move other ticking components to shared just because

* remove unused prototype file

* update everything to use shared components

* test

* test 2

* test 3

---------

Co-authored-by: deltanedas <@deltanedas:kde.org>
2024-06-04 21:53:24 +10:00

91 lines
4.1 KiB
C#

using Content.Server.Atmos.EntitySystems;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.GameTicking.Components;
using Robust.Shared.Audio;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.StationEvents.Events
{
internal sealed class GasLeakRule : StationEventSystem<GasLeakRuleComponent>
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
protected override void Started(EntityUid uid, GasLeakRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
if (!TryComp<StationEventComponent>(uid, out var stationEvent))
return;
// Essentially we'll pick out a target amount of gas to leak, then a rate to leak it at, then work out the duration from there.
if (TryFindRandomTile(out component.TargetTile, out var target, out component.TargetGrid, out component.TargetCoords))
{
component.TargetStation = target.Value;
component.FoundTile = true;
component.LeakGas = RobustRandom.Pick(component.LeakableGases);
// Was 50-50 on using normal distribution.
var totalGas = RobustRandom.Next(component.MinimumGas, component.MaximumGas);
component.MolesPerSecond = RobustRandom.Next(component.MinimumMolesPerSecond, component.MaximumMolesPerSecond);
if (gameRule.Delay is {} startAfter)
stationEvent.EndTime = _timing.CurTime + TimeSpan.FromSeconds(totalGas / component.MolesPerSecond + startAfter.Next(RobustRandom));
}
// Look technically if you wanted to guarantee a leak you'd do this in announcement but having the announcement
// there just to fuck with people even if there is no valid tile is funny.
}
protected override void ActiveTick(EntityUid uid, GasLeakRuleComponent component, GameRuleComponent gameRule, float frameTime)
{
base.ActiveTick(uid, component, gameRule, frameTime);
component.TimeUntilLeak -= frameTime;
if (component.TimeUntilLeak > 0f)
return;
component.TimeUntilLeak += component.LeakCooldown;
if (!component.FoundTile ||
component.TargetGrid == default ||
Deleted(component.TargetGrid) ||
!_atmosphere.IsSimulatedGrid(component.TargetGrid))
{
ForceEndSelf(uid, gameRule);
return;
}
var environment = _atmosphere.GetTileMixture(component.TargetGrid, null, component.TargetTile, true);
environment?.AdjustMoles(component.LeakGas, component.LeakCooldown * component.MolesPerSecond);
}
protected override void Ended(EntityUid uid, GasLeakRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
{
base.Ended(uid, component, gameRule, args);
Spark(uid, component);
}
private void Spark(EntityUid uid, GasLeakRuleComponent component)
{
if (RobustRandom.NextFloat() <= component.SparkChance)
{
if (!component.FoundTile ||
component.TargetGrid == default ||
(!Exists(component.TargetGrid) ? EntityLifeStage.Deleted : MetaData(component.TargetGrid).EntityLifeStage) >= EntityLifeStage.Deleted ||
!_atmosphere.IsSimulatedGrid(component.TargetGrid))
{
return;
}
// Don't want it to be so obnoxious as to instantly murder anyone in the area but enough that
// it COULD start potentially start a bigger fire.
_atmosphere.HotspotExpose(component.TargetGrid, component.TargetTile, 700f, 50f, null, true);
Audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/sparks4.ogg"), component.TargetCoords);
}
}
}
}