Emergency light goodies (#9352)
Co-authored-by: Jacob Tong <10494922+ShadowCommander@users.noreply.github.com>
This commit is contained in:
@@ -13,7 +13,7 @@ namespace Content.Client.Light
|
||||
{
|
||||
public sealed class EmergencyLightSystem : SharedEmergencyLightSystem
|
||||
{
|
||||
private const float DegreesPerSecond = 270;
|
||||
private const float DegreesPerSecond = 90;
|
||||
private static Animation Animation =>
|
||||
new()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,19 @@ namespace Content.Client.Light.Visualizers
|
||||
if (!component.TryGetData(EmergencyLightVisuals.On, out bool on))
|
||||
on = false;
|
||||
|
||||
sprite.LayerSetState(0, on ? "emergency_light_on" : "emergency_light_off");
|
||||
sprite.LayerSetState(EmergencyLightVisualLayers.Light, on ? "emergency_light_on" : "emergency_light_off");
|
||||
sprite.LayerSetShader(EmergencyLightVisualLayers.Light, on ? "unshaded" : "shaded");
|
||||
|
||||
if (component.TryGetData(EmergencyLightVisuals.Color, out Color color))
|
||||
{
|
||||
sprite.LayerSetColor(EmergencyLightVisualLayers.Light, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum EmergencyLightVisualLayers
|
||||
{
|
||||
Base,
|
||||
Light
|
||||
}
|
||||
|
||||
@@ -58,6 +58,16 @@ public sealed class AlertLevelDetail
|
||||
/// </summary>
|
||||
[DataField("color")] public Color Color { get; } = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// The color to turn emergency lights on this station when they are active.
|
||||
/// </summary>
|
||||
[DataField("emergencyLightColor")] public Color EmergencyLightColor { get; } = Color.FromHex("#FF4020");
|
||||
|
||||
/// <summary>
|
||||
/// Will this alert level force emergency lights on for the station that's active?
|
||||
/// </summary>
|
||||
[DataField("forceEnableEmergencyLights")] public bool ForceEnableEmergencyLights { get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// How long it takes for the shuttle to arrive when called.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,6 +12,12 @@ namespace Content.Server.Light.Components
|
||||
[ViewVariables]
|
||||
public EmergencyLightState State;
|
||||
|
||||
/// <summary>
|
||||
/// Is this emergency light forced on for some reason and cannot be disabled through normal means
|
||||
/// (i.e. delta alert level?)
|
||||
/// </summary>
|
||||
public bool ForciblyEnabled = false;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("wattage")]
|
||||
public float Wattage = 5;
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
using System.Drawing;
|
||||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Light.Components;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Light;
|
||||
using Content.Shared.Light.Component;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Color = Robust.Shared.Maths.Color;
|
||||
|
||||
namespace Content.Server.Light.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class EmergencyLightSystem : SharedEmergencyLightSystem
|
||||
{
|
||||
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
|
||||
private readonly HashSet<EmergencyLightComponent> _activeLights = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<EmergencyLightEvent>(HandleEmergencyLightMessage);
|
||||
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
|
||||
SubscribeLocalEvent<EmergencyLightComponent, ComponentGetState>(GetCompState);
|
||||
SubscribeLocalEvent<EmergencyLightComponent, PointLightToggleEvent>(HandleLightToggle);
|
||||
SubscribeLocalEvent<EmergencyLightComponent, ExaminedEvent>(OnEmergencyExamine);
|
||||
@@ -35,6 +45,24 @@ namespace Content.Server.Light.EntitySystems
|
||||
Loc.GetString("emergency-light-component-on-examine",
|
||||
("batteryStateText",
|
||||
Loc.GetString(component.BatteryStateText[component.State]))));
|
||||
|
||||
// Show alert level on the light itself.
|
||||
if (!TryComp<AlertLevelComponent>(_station.GetOwningStation(uid), out var alerts))
|
||||
return;
|
||||
|
||||
if (alerts.AlertLevels == null)
|
||||
return;
|
||||
|
||||
var name = alerts.CurrentLevel;
|
||||
|
||||
var color = Color.White;
|
||||
if (alerts.AlertLevels.Levels.TryGetValue(alerts.CurrentLevel, out var details))
|
||||
color = details.Color;
|
||||
|
||||
args.PushMarkup(
|
||||
Loc.GetString("emergency-light-component-on-examine-alert",
|
||||
("color", color.ToHex()),
|
||||
("level", name)));
|
||||
}
|
||||
|
||||
private void HandleLightToggle(EntityUid uid, EmergencyLightComponent component, PointLightToggleEvent args)
|
||||
@@ -66,6 +94,36 @@ namespace Content.Server.Light.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAlertLevelChanged(AlertLevelChangedEvent ev)
|
||||
{
|
||||
if (!TryComp<AlertLevelComponent>(ev.Station, out var alert))
|
||||
return;
|
||||
|
||||
if (alert.AlertLevels == null || !alert.AlertLevels.Levels.TryGetValue(ev.AlertLevel, out var details))
|
||||
return;
|
||||
|
||||
foreach (var (light, pointLight, appearance, xform) in EntityQuery<EmergencyLightComponent, PointLightComponent, AppearanceComponent, TransformComponent>())
|
||||
{
|
||||
if (CompOrNull<StationMemberComponent>(xform.GridUid)?.Station != ev.Station)
|
||||
continue;
|
||||
|
||||
pointLight.Color = details.EmergencyLightColor;
|
||||
appearance.SetData(EmergencyLightVisuals.Color, details.EmergencyLightColor);
|
||||
|
||||
if (details.ForceEnableEmergencyLights && !light.ForciblyEnabled)
|
||||
{
|
||||
light.ForciblyEnabled = true;
|
||||
TurnOn(light);
|
||||
}
|
||||
else if (!details.ForceEnableEmergencyLights && light.ForciblyEnabled)
|
||||
{
|
||||
// Previously forcibly enabled, and we went down an alert level.
|
||||
light.ForciblyEnabled = false;
|
||||
UpdateState(light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetState(EmergencyLightComponent component, EmergencyLightState state)
|
||||
{
|
||||
if (component.State == state) return;
|
||||
@@ -122,7 +180,7 @@ namespace Content.Server.Light.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
if (receiver.Powered)
|
||||
if (receiver.Powered && !component.ForciblyEnabled)
|
||||
{
|
||||
receiver.Load = (int) Math.Abs(component.Wattage);
|
||||
TurnOff(component);
|
||||
@@ -144,6 +202,8 @@ namespace Content.Server.Light.EntitySystems
|
||||
|
||||
if (TryComp(component.Owner, out AppearanceComponent? appearance))
|
||||
appearance.SetData(EmergencyLightVisuals.On, false);
|
||||
|
||||
_ambient.SetAmbience(component.Owner, false);
|
||||
}
|
||||
|
||||
private void TurnOn(EmergencyLightComponent component)
|
||||
@@ -154,7 +214,12 @@ namespace Content.Server.Light.EntitySystems
|
||||
}
|
||||
|
||||
if (TryComp(component.Owner, out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(EmergencyLightVisuals.On, true);
|
||||
}
|
||||
|
||||
_ambient.SetAmbience(component.Owner, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,5 +24,6 @@ namespace Content.Shared.Light.Component
|
||||
public enum EmergencyLightVisuals
|
||||
{
|
||||
On,
|
||||
Color
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Resources/Audio/Ambience/Objects/alarm.ogg
Normal file
BIN
Resources/Audio/Ambience/Objects/alarm.ogg
Normal file
Binary file not shown.
@@ -5,3 +5,4 @@ gas_vent - https://freesound.org/people/kyles/sounds/453642/ - CC0-1.0
|
||||
flowing_water_open - https://freesound.org/people/sterferny/sounds/382322/ - CC0-1.0
|
||||
server_fans - https://freesound.org/people/DeVern/sounds/610761/ - CC-BY-3.0
|
||||
drain.ogg - https://freesound.org/people/PhreaKsAccount/sounds/46266/ - CC-BY-3.0 (by PhreaKsAccount)
|
||||
alarm.ogg - https://github.com/Baystation12/Baystation12/commit/41b11ef289bccfdfa2940480beb9c1e3f50c3b93, fire_alarm.ogg CC-BY-SA-3.0
|
||||
@@ -1,5 +1,6 @@
|
||||
emergency-light-component-on-examine = The battery indicator displays: {$batteryStateText}.
|
||||
emergency-light-component-light-state-full = [color=darkgreen]Full[/color]
|
||||
emergency-light-component-light-state-empty = [color=darkgreen]Empty[/color]
|
||||
emergency-light-component-light-state-charging = [color=darkgreen]Charging[/color]
|
||||
emergency-light-component-light-state-on = [color=darkgreen]On[/color]
|
||||
emergency-light-component-on-examine-alert = The current station alert level is: [color={$color}]{$level}[/color].
|
||||
emergency-light-component-light-state-full = [color=darkgreen]full[/color]
|
||||
emergency-light-component-light-state-empty = [color=darkgreen]empty[/color]
|
||||
emergency-light-component-light-state-charging = [color=darkgreen]charging[/color]
|
||||
emergency-light-component-light-state-on = [color=darkgreen]on[/color]
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
announcement: alert-level-violet-announcement
|
||||
sound: /Audio/Misc/notice1.ogg
|
||||
color: Violet
|
||||
emergencyLightColor: Violet
|
||||
shuttleTime: 600
|
||||
yellow:
|
||||
announcement: alert-level-yellow-announcement
|
||||
sound: /Audio/Misc/notice1.ogg
|
||||
color: Yellow
|
||||
emergencyLightColor: Yellow
|
||||
shuttleTime: 400
|
||||
red:
|
||||
announcement: alert-level-red-announcement
|
||||
@@ -33,6 +35,8 @@
|
||||
volume: -2
|
||||
disableSelection: true
|
||||
color: PaleVioletRed
|
||||
emergencyLightColor: PaleVioletRed
|
||||
forceEnableEmergencyLights: true
|
||||
delta:
|
||||
announcement: alert-level-delta-announcement
|
||||
selectable: false
|
||||
@@ -42,6 +46,8 @@
|
||||
volume: -5
|
||||
disableSelection: true
|
||||
color: DarkRed
|
||||
emergencyLightColor: Orange
|
||||
forceEnableEmergencyLights: true
|
||||
shuttleTime: 1200
|
||||
epsilon:
|
||||
announcement: alert-level-epsilon-announcement
|
||||
@@ -52,4 +58,6 @@
|
||||
volume: -2
|
||||
disableSelection: true
|
||||
color: DarkViolet
|
||||
emergencyLightColor: DarkViolet
|
||||
forceEnableEmergencyLights: true
|
||||
shuttleTime: 1200
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
- type: entity
|
||||
id: EmergencyLight
|
||||
name: emergency light
|
||||
description: A small red light with an internal battery that turns on as soon as it stops receiving any power.
|
||||
description: A small light with an internal battery that turns on as soon as it stops receiving any power. Nanotrasen technology allows it to adapt its color to alert crew to the conditions of the station.
|
||||
parent: AlwaysPoweredWallLight
|
||||
suffix:
|
||||
components:
|
||||
@@ -283,6 +283,7 @@
|
||||
enabled: false
|
||||
radius: 10
|
||||
energy: 2.5
|
||||
offset: "0, 0.2"
|
||||
color: "#FF4020"
|
||||
mask: /Textures/Effects/LightMasks/cone.png
|
||||
- type: ApcPowerReceiver
|
||||
@@ -294,10 +295,19 @@
|
||||
- type: Sprite
|
||||
sprite: Structures/Wallmounts/Lighting/emergency_light.rsi
|
||||
layers:
|
||||
- state: base
|
||||
map: ["enum.EmergencyLightVisualLayers.Base"]
|
||||
- state: emergency_light_off
|
||||
map: ["enum.EmergencyLightVisualLayers.Light"]
|
||||
color: "#FF4020"
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: EmergencyLightVisualizer
|
||||
- type: AmbientSound
|
||||
sound:
|
||||
path: /Audio/Ambience/Objects/alarm.ogg
|
||||
volume: -18
|
||||
range: 5
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
snap:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 262 B |
Binary file not shown.
|
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 251 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -5,7 +5,12 @@
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "juliang, modified by mirrorcult",
|
||||
"states": [
|
||||
{
|
||||
"name": "base",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "emergency_light_off",
|
||||
"directions": 4,
|
||||
|
||||
Reference in New Issue
Block a user