mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-18 14:07:53 +03:00
# Description Replaces every instance of station announcements with an announcer system meant to handle audio and messages for various announcers defined in prototypes instead of each server replacing the scattered files inconsistently with whatever singular thing they want to hear announce messages. # TODO - [x] Systems - [x] CVars - [x] Sounds - [x] Client volume slider - [x] Collections - [x] Prototypes - [x] Events - [x] Commands - [x] PR media - [x] Deglobalize - [x] Passthrough localization parameters to overrides - [x] Make every announcer follow the template - [x] Move sounds into subdirectories - [x] Make announcement IDs camelCased - [x] Test announcement localizations - [x] Weighted announcer lists --- <details><summary><h1>Media</h1></summary> <p> https://github.com/Simple-Station/Parkstation-Friendly-Chainsaw/assets/77995199/caf5805d-acb0-4140-b344-875a8f79e5ee </p> </details> --- # Changelog 🆑 - add: Added 4 new announcers that will randomly be selected every shift
137 lines
5.6 KiB
C#
137 lines
5.6 KiB
C#
using Content.Server.Explosion.EntitySystems;
|
|
using Content.Server.Power.Components;
|
|
using Content.Shared.Examine;
|
|
using Robust.Shared.Utility;
|
|
using Content.Server.Chat.Systems;
|
|
using Content.Server.Station.Systems;
|
|
using Robust.Shared.Timing;
|
|
using Robust.Shared.Audio;
|
|
using Robust.Shared.Audio.Systems;
|
|
using Content.Server.Power.EntitySystems;
|
|
using Content.Server.Announcements.Systems;
|
|
|
|
namespace Content.Server.PowerSink
|
|
{
|
|
public sealed class PowerSinkSystem : EntitySystem
|
|
{
|
|
/// <summary>
|
|
/// Percentage of battery full to trigger the announcement warning at.
|
|
/// </summary>
|
|
private const float WarningMessageThreshold = 0.70f;
|
|
|
|
private readonly float[] _warningSoundThresholds = new[] { .80f, .90f, .95f, .98f };
|
|
|
|
/// <summary>
|
|
/// Length of time to delay explosion from battery full state -- this is used to play
|
|
/// a brief SFX winding up the explosion.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private readonly TimeSpan _explosionDelayTime = TimeSpan.FromSeconds(1.465);
|
|
|
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
[Dependency] private readonly ChatSystem _chat = default!;
|
|
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
|
[Dependency] private readonly StationSystem _station = default!;
|
|
[Dependency] private readonly BatterySystem _battery = default!;
|
|
[Dependency] private readonly AnnouncerSystem _announcer = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<PowerSinkComponent, ExaminedEvent>(OnExamine);
|
|
}
|
|
|
|
private void OnExamine(EntityUid uid, PowerSinkComponent component, ExaminedEvent args)
|
|
{
|
|
if (!args.IsInDetailsRange || !TryComp<PowerConsumerComponent>(uid, out var consumer))
|
|
return;
|
|
|
|
var drainAmount = (int) consumer.NetworkLoad.ReceivingPower / 1000;
|
|
args.PushMarkup(
|
|
Loc.GetString(
|
|
"powersink-examine-drain-amount",
|
|
("amount", drainAmount),
|
|
("markupDrainColor", "orange"))
|
|
);
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
var toRemove = new RemQueue<(EntityUid Entity, PowerSinkComponent Sink)>();
|
|
var query = EntityQueryEnumerator<PowerSinkComponent, PowerConsumerComponent, BatteryComponent, TransformComponent>();
|
|
|
|
// Realistically it's gonna be like <5 per station.
|
|
while (query.MoveNext(out var entity, out var component, out var networkLoad, out var battery, out var transform))
|
|
{
|
|
if (!transform.Anchored)
|
|
continue;
|
|
|
|
_battery.SetCharge(entity, battery.CurrentCharge + networkLoad.NetworkLoad.ReceivingPower / 1000, battery);
|
|
|
|
var currentBatteryThreshold = battery.CurrentCharge / battery.MaxCharge;
|
|
|
|
// Check for warning message threshold
|
|
if (!component.SentImminentExplosionWarningMessage &&
|
|
currentBatteryThreshold >= WarningMessageThreshold)
|
|
{
|
|
NotifyStationOfImminentExplosion(entity, component);
|
|
}
|
|
|
|
// Check for warning sound threshold
|
|
foreach (var testThreshold in _warningSoundThresholds)
|
|
{
|
|
if (currentBatteryThreshold >= testThreshold &&
|
|
testThreshold > component.HighestWarningSoundThreshold)
|
|
{
|
|
component.HighestWarningSoundThreshold = currentBatteryThreshold; // Don't re-play in future until next threshold hit
|
|
_audio.PlayPvs(component.ElectricSound, entity); // Play SFX
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check for explosion
|
|
if (battery.CurrentCharge < battery.MaxCharge)
|
|
continue;
|
|
|
|
if (component.ExplosionTime == null)
|
|
{
|
|
// Set explosion sequence to start soon
|
|
component.ExplosionTime = _gameTiming.CurTime.Add(_explosionDelayTime);
|
|
|
|
// Wind-up SFX
|
|
_audio.PlayPvs(component.ChargeFireSound, entity); // Play SFX
|
|
}
|
|
else if (_gameTiming.CurTime >= component.ExplosionTime)
|
|
{
|
|
// Explode!
|
|
toRemove.Add((entity, component));
|
|
}
|
|
}
|
|
|
|
foreach (var (entity, component) in toRemove)
|
|
{
|
|
_explosionSystem.QueueExplosion(entity, "PowerSink", 2000f, 4f, 20f, canCreateVacuum: true);
|
|
EntityManager.RemoveComponent(entity, component);
|
|
}
|
|
}
|
|
|
|
private void NotifyStationOfImminentExplosion(EntityUid uid, PowerSinkComponent powerSinkComponent)
|
|
{
|
|
if (powerSinkComponent.SentImminentExplosionWarningMessage)
|
|
return;
|
|
|
|
powerSinkComponent.SentImminentExplosionWarningMessage = true;
|
|
var station = _station.GetOwningStation(uid);
|
|
|
|
if (station == null)
|
|
return;
|
|
|
|
_announcer.SendAnnouncement(_announcer.GetAnnouncementId("PowerSinkExplosion"),
|
|
_station.GetInOwningStation(station.Value), "powersink-immiment-explosion-announcement",
|
|
colorOverride: Color.Yellow, station: station.Value);
|
|
}
|
|
}
|
|
}
|