| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- 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);
- }
- }
- }
- }
|