Skip to content

Commit

Permalink
Make crew monitors beep when someone dies / crits (#2930)
Browse files Browse the repository at this point in the history
* Make the crew monitors beep when someone dies or crits

* Cleanup

* Fix a comment that was not updated earlier.

Signed-off-by: Quanteey <61941975+Quanteey@users.noreply.github.com>

* Switch frame time tracking to using timespans

* use timestamps of next alert instead of frame time tracking

* Fix outdated docs

---------

Signed-off-by: Quanteey <61941975+Quanteey@users.noreply.github.com>
  • Loading branch information
Quanteey authored Feb 11, 2025
1 parent 5c67453 commit ca4db5d
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Content.Shared.Medical.SuitSensor;
using Robust.Shared.Audio; // DeltaV
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; // DeltaV

namespace Content.Server.Medical.CrewMonitoring;

[RegisterComponent]
[RegisterComponent, AutoGenerateComponentPause] // DeltaV - add AutoGenerateComponentPause
[Access(typeof(CrewMonitoringConsoleSystem))]
public sealed partial class CrewMonitoringConsoleComponent : Component
{
Expand All @@ -16,4 +18,35 @@ public sealed partial class CrewMonitoringConsoleComponent : Component
/// </summary>
[DataField("sensorTimeout"), ViewVariables(VVAccess.ReadWrite)]
public float SensorTimeout = 10f;

// DeltaV - start of alert system code
/// <summary>
/// Should the component beep if someone goes critical or dies
/// </summary>
[DataField]
public bool AlertsEnabled = true;

/// <summary>
/// Track sensors that have triggered the crew member critical alert.
/// </summary>
public HashSet<string> AlertedSensors = [];

/// <summary>
/// Timestamp of the next possible alert (alert cooldown)
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan NextAlert;

/// <summary>
/// Time between alerts
/// </summary>
[DataField]
public TimeSpan AlertCooldown = TimeSpan.FromSeconds(15);

/// <summary>
/// Alert sound that is played when a crew member goes into critical / dies.
/// </summary>
[DataField]
public SoundSpecifier AlertSound = new SoundPathSpecifier("/Audio/_DV/Medical/CrewMonitoring/crew_alert.ogg");
// DeltaV - end of alert system code
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
using System.Linq;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Power.EntitySystems; // DeltaV
using Content.Server.PowerCell;
using Content.Shared.Medical.CrewMonitoring;
using Content.Shared.Medical.SuitSensor;
using Content.Shared.Pinpointer;
using Robust.Server.GameObjects;
using Robust.Shared.Audio; // DeltaV
using Robust.Shared.Audio.Systems; // DeltaV
using Robust.Shared.Timing; // DeltaV

namespace Content.Server.Medical.CrewMonitoring;

public sealed class CrewMonitoringConsoleSystem : EntitySystem
{
[Dependency] private readonly PowerCellSystem _cell = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; // DeltaV
[Dependency] private readonly IGameTiming _timing = default!; // DeltaV

public override void Initialize()
{
Expand Down Expand Up @@ -43,6 +49,48 @@ private void OnPacketReceived(EntityUid uid, CrewMonitoringConsoleComponent comp

component.ConnectedSensors = sensorStatus;
UpdateUserInterface(uid, component);

// DeltaV - start of alert system code
if (!component.AlertsEnabled)
return;

// station power (for the machine version)
if (!this.IsPowered(uid, EntityManager))
return;

// cell power (for the handheld)
if (!_cell.HasActivatableCharge(uid))
return;

foreach (var (sensorId, status) in sensorStatus)
{
// DamagePercentage above 1f is considered critical. It is null when sensor vitals are off.
var isCritical = status.DamagePercentage is >= 1f;

// Skip crew members that we have already alerted about
if (component.AlertedSensors.Contains(sensorId))
{
if (status.IsAlive && !isCritical)
component.AlertedSensors.Remove(sensorId);
continue;
}

if (!status.IsAlive || isCritical)
{
if (_timing.CurTime >= component.NextAlert)
{
var audioParams = AudioParams.Default.WithVolume(-2f).WithMaxDistance(4f);
_audio.PlayPvs(component.AlertSound, uid, audioParams);
component.NextAlert = _timing.CurTime + component.AlertCooldown;
}

// We are doing this outside the cooldown check to avoid "alert queues"
// If two people die at the same time and remain dead for longer, we want to alert once for both people
// instead of alerting once for the first one, waiting the cooldown, and then alerting again for the second one.
component.AlertedSensors.Add(sensorId);
}
}
// DeltaV - end of alert system code
}

private void OnUIOpened(EntityUid uid, CrewMonitoringConsoleComponent component, BoundUIOpenedEvent args)
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
price: 750
- type: Tag # DeltaV - Let it be put in storage implants by removing HighRiskItem
tags: []
- type: CrewMonitoringConsole # DeltaV - disable crew crit / dead beeping alerts
alertsEnabled: false

- type: entity
id: SpyCrewMonitorEmpty
Expand All @@ -85,6 +87,8 @@
sprite: Objects/Specific/Medical/syndihandheldcrewmonitor.rsi
- type: PowerCellDraw
useRate: 0 # DeltaV - Changed to zero with the removal of the microreactor in observations kit
- type: CrewMonitoringConsole # DeltaV - disable crew crit / dead beeping alerts
alertsEnabled: false

- type: entity
id: SyndiCrewMonitorEmpty
Expand Down

0 comments on commit ca4db5d

Please sign in to comment.