Emergency light goodies (#9352)

Co-authored-by: Jacob Tong <10494922+ShadowCommander@users.noreply.github.com>
This commit is contained in:
Kara
2022-07-07 09:16:48 -07:00
committed by GitHub
parent 4e0a1e4291
commit 7e34124244
15 changed files with 127 additions and 8 deletions

View File

@@ -13,7 +13,7 @@ namespace Content.Client.Light
{ {
public sealed class EmergencyLightSystem : SharedEmergencyLightSystem public sealed class EmergencyLightSystem : SharedEmergencyLightSystem
{ {
private const float DegreesPerSecond = 270; private const float DegreesPerSecond = 90;
private static Animation Animation => private static Animation Animation =>
new() new()
{ {

View File

@@ -20,7 +20,19 @@ namespace Content.Client.Light.Visualizers
if (!component.TryGetData(EmergencyLightVisuals.On, out bool on)) if (!component.TryGetData(EmergencyLightVisuals.On, out bool on))
on = false; 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
}

View File

@@ -58,6 +58,16 @@ public sealed class AlertLevelDetail
/// </summary> /// </summary>
[DataField("color")] public Color Color { get; } = Color.White; [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> /// <summary>
/// How long it takes for the shuttle to arrive when called. /// How long it takes for the shuttle to arrive when called.
/// </summary> /// </summary>

View File

@@ -12,6 +12,12 @@ namespace Content.Server.Light.Components
[ViewVariables] [ViewVariables]
public EmergencyLightState State; 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)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("wattage")] [DataField("wattage")]
public float Wattage = 5; public float Wattage = 5;

View File

@@ -1,23 +1,33 @@
using System.Drawing;
using Content.Server.AlertLevel;
using Content.Server.Audio;
using Content.Server.Light.Components; using Content.Server.Light.Components;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Light; using Content.Shared.Light;
using Content.Shared.Light.Component; using Content.Shared.Light.Component;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Color = Robust.Shared.Maths.Color;
namespace Content.Server.Light.EntitySystems namespace Content.Server.Light.EntitySystems
{ {
[UsedImplicitly] [UsedImplicitly]
public sealed class EmergencyLightSystem : SharedEmergencyLightSystem public sealed class EmergencyLightSystem : SharedEmergencyLightSystem
{ {
[Dependency] private readonly AmbientSoundSystem _ambient = default!;
[Dependency] private readonly StationSystem _station = default!;
private readonly HashSet<EmergencyLightComponent> _activeLights = new(); private readonly HashSet<EmergencyLightComponent> _activeLights = new();
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<EmergencyLightEvent>(HandleEmergencyLightMessage); SubscribeLocalEvent<EmergencyLightEvent>(HandleEmergencyLightMessage);
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
SubscribeLocalEvent<EmergencyLightComponent, ComponentGetState>(GetCompState); SubscribeLocalEvent<EmergencyLightComponent, ComponentGetState>(GetCompState);
SubscribeLocalEvent<EmergencyLightComponent, PointLightToggleEvent>(HandleLightToggle); SubscribeLocalEvent<EmergencyLightComponent, PointLightToggleEvent>(HandleLightToggle);
SubscribeLocalEvent<EmergencyLightComponent, ExaminedEvent>(OnEmergencyExamine); SubscribeLocalEvent<EmergencyLightComponent, ExaminedEvent>(OnEmergencyExamine);
@@ -35,6 +45,24 @@ namespace Content.Server.Light.EntitySystems
Loc.GetString("emergency-light-component-on-examine", Loc.GetString("emergency-light-component-on-examine",
("batteryStateText", ("batteryStateText",
Loc.GetString(component.BatteryStateText[component.State])))); 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) 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) public void SetState(EmergencyLightComponent component, EmergencyLightState state)
{ {
if (component.State == state) return; if (component.State == state) return;
@@ -122,7 +180,7 @@ namespace Content.Server.Light.EntitySystems
return; return;
} }
if (receiver.Powered) if (receiver.Powered && !component.ForciblyEnabled)
{ {
receiver.Load = (int) Math.Abs(component.Wattage); receiver.Load = (int) Math.Abs(component.Wattage);
TurnOff(component); TurnOff(component);
@@ -144,6 +202,8 @@ namespace Content.Server.Light.EntitySystems
if (TryComp(component.Owner, out AppearanceComponent? appearance)) if (TryComp(component.Owner, out AppearanceComponent? appearance))
appearance.SetData(EmergencyLightVisuals.On, false); appearance.SetData(EmergencyLightVisuals.On, false);
_ambient.SetAmbience(component.Owner, false);
} }
private void TurnOn(EmergencyLightComponent component) private void TurnOn(EmergencyLightComponent component)
@@ -154,7 +214,12 @@ namespace Content.Server.Light.EntitySystems
} }
if (TryComp(component.Owner, out AppearanceComponent? appearance)) if (TryComp(component.Owner, out AppearanceComponent? appearance))
{
appearance.SetData(EmergencyLightVisuals.On, true); appearance.SetData(EmergencyLightVisuals.On, true);
}
_ambient.SetAmbience(component.Owner, true);
} }
} }
} }

View File

@@ -24,5 +24,6 @@ namespace Content.Shared.Light.Component
public enum EmergencyLightVisuals public enum EmergencyLightVisuals
{ {
On, On,
Color
} }
} }

Binary file not shown.

View File

@@ -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 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 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) 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

View File

@@ -1,5 +1,6 @@
emergency-light-component-on-examine = The battery indicator displays: {$batteryStateText}. emergency-light-component-on-examine = The battery indicator displays: {$batteryStateText}.
emergency-light-component-light-state-full = [color=darkgreen]Full[/color] emergency-light-component-on-examine-alert = The current station alert level is: [color={$color}]{$level}[/color].
emergency-light-component-light-state-empty = [color=darkgreen]Empty[/color] emergency-light-component-light-state-full = [color=darkgreen]full[/color]
emergency-light-component-light-state-charging = [color=darkgreen]Charging[/color] emergency-light-component-light-state-empty = [color=darkgreen]empty[/color]
emergency-light-component-light-state-on = [color=darkgreen]On[/color] emergency-light-component-light-state-charging = [color=darkgreen]charging[/color]
emergency-light-component-light-state-on = [color=darkgreen]on[/color]

View File

@@ -14,11 +14,13 @@
announcement: alert-level-violet-announcement announcement: alert-level-violet-announcement
sound: /Audio/Misc/notice1.ogg sound: /Audio/Misc/notice1.ogg
color: Violet color: Violet
emergencyLightColor: Violet
shuttleTime: 600 shuttleTime: 600
yellow: yellow:
announcement: alert-level-yellow-announcement announcement: alert-level-yellow-announcement
sound: /Audio/Misc/notice1.ogg sound: /Audio/Misc/notice1.ogg
color: Yellow color: Yellow
emergencyLightColor: Yellow
shuttleTime: 400 shuttleTime: 400
red: red:
announcement: alert-level-red-announcement announcement: alert-level-red-announcement
@@ -33,6 +35,8 @@
volume: -2 volume: -2
disableSelection: true disableSelection: true
color: PaleVioletRed color: PaleVioletRed
emergencyLightColor: PaleVioletRed
forceEnableEmergencyLights: true
delta: delta:
announcement: alert-level-delta-announcement announcement: alert-level-delta-announcement
selectable: false selectable: false
@@ -42,6 +46,8 @@
volume: -5 volume: -5
disableSelection: true disableSelection: true
color: DarkRed color: DarkRed
emergencyLightColor: Orange
forceEnableEmergencyLights: true
shuttleTime: 1200 shuttleTime: 1200
epsilon: epsilon:
announcement: alert-level-epsilon-announcement announcement: alert-level-epsilon-announcement
@@ -52,4 +58,6 @@
volume: -2 volume: -2
disableSelection: true disableSelection: true
color: DarkViolet color: DarkViolet
emergencyLightColor: DarkViolet
forceEnableEmergencyLights: true
shuttleTime: 1200 shuttleTime: 1200

View File

@@ -275,7 +275,7 @@
- type: entity - type: entity
id: EmergencyLight id: EmergencyLight
name: emergency light 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 parent: AlwaysPoweredWallLight
suffix: suffix:
components: components:
@@ -283,6 +283,7 @@
enabled: false enabled: false
radius: 10 radius: 10
energy: 2.5 energy: 2.5
offset: "0, 0.2"
color: "#FF4020" color: "#FF4020"
mask: /Textures/Effects/LightMasks/cone.png mask: /Textures/Effects/LightMasks/cone.png
- type: ApcPowerReceiver - type: ApcPowerReceiver
@@ -294,10 +295,19 @@
- type: Sprite - type: Sprite
sprite: Structures/Wallmounts/Lighting/emergency_light.rsi sprite: Structures/Wallmounts/Lighting/emergency_light.rsi
layers: layers:
- state: base
map: ["enum.EmergencyLightVisualLayers.Base"]
- state: emergency_light_off - state: emergency_light_off
map: ["enum.EmergencyLightVisualLayers.Light"]
color: "#FF4020"
- type: Appearance - type: Appearance
visuals: visuals:
- type: EmergencyLightVisualizer - type: EmergencyLightVisualizer
- type: AmbientSound
sound:
path: /Audio/Ambience/Objects/alarm.ogg
volume: -18
range: 5
placement: placement:
mode: SnapgridCenter mode: SnapgridCenter
snap: 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

View File

@@ -5,7 +5,12 @@
"y": 32 "y": 32
}, },
"license": "CC-BY-SA-3.0", "license": "CC-BY-SA-3.0",
"copyright": "juliang, modified by mirrorcult",
"states": [ "states": [
{
"name": "base",
"directions": 4
},
{ {
"name": "emergency_light_off", "name": "emergency_light_off",
"directions": 4, "directions": 4,