diff --git a/Content.Client/GameObjects/Components/EmergencyLightComponent.cs b/Content.Client/GameObjects/Components/EmergencyLightComponent.cs index 3bf8879d02..3d893332f1 100644 --- a/Content.Client/GameObjects/Components/EmergencyLightComponent.cs +++ b/Content.Client/GameObjects/Components/EmergencyLightComponent.cs @@ -1,4 +1,4 @@ -using System; +using System; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Client.GameObjects.Components.Animations; @@ -13,6 +13,7 @@ namespace Content.Client.GameObjects.Components { public override string Name => "EmergencyLight"; + /// protected override void Startup() { base.Startup(); diff --git a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/EmergencyLightComponent.cs b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/EmergencyLightComponent.cs new file mode 100644 index 0000000000..3fa04af25a --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/EmergencyLightComponent.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using Content.Shared.GameObjects.EntitySystems; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using Robust.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerReceiverUsers +{ + /// + /// Component that represents an emergency light, it has an internal battery that charges when the power is on. + /// + [RegisterComponent] + public class EmergencyLightComponent : Component, IExamine + { + public override string Name => "EmergencyLight"; + + [ViewVariables] + private EmergencyLightState _lightState = EmergencyLightState.Charging; + + [ViewVariables] + private BatteryComponent Battery => Owner.GetComponent(); + [ViewVariables] + private PointLightComponent Light => Owner.GetComponent(); + [ViewVariables] + private PowerReceiverComponent PowerReceiver => Owner.GetComponent(); + private SpriteComponent Sprite => Owner.GetComponent(); + + [ViewVariables(VVAccess.ReadWrite)] + private float _wattage; + [ViewVariables(VVAccess.ReadWrite)] + private float _chargingWattage; + [ViewVariables(VVAccess.ReadWrite)] + private float _chargingEfficiency; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(ref _wattage, "wattage", 5); + serializer.DataField(ref _chargingWattage, "chargingWattage", 60); + serializer.DataField(ref _chargingEfficiency, "chargingEfficiency", 0.85f); + } + + /// + /// For attaching UpdateState() to events. + /// + public void UpdateState(object sender, EventArgs e) + { + UpdateState(); + } + + /// + /// Updates the light's power drain, battery drain, sprite and actual light state. + /// + public void UpdateState() + { + if (PowerReceiver.Powered) + { + PowerReceiver.Load = (int) Math.Abs(_wattage); + TurnOff(); + _lightState = EmergencyLightState.Charging; + } + else + { + TurnOn(); + _lightState = EmergencyLightState.On; + } + } + + public void OnUpdate(float frameTime) + { + if (_lightState == EmergencyLightState.Empty + || _lightState == EmergencyLightState.Full) return; + + if(_lightState == EmergencyLightState.On) + { + if (!Battery.TryUseCharge(_wattage * frameTime)) + { + _lightState = EmergencyLightState.Empty; + TurnOff(); + } + } + else + { + Battery.CurrentCharge += _chargingWattage * frameTime * _chargingEfficiency; + if (Battery.BatteryState == BatteryState.Full) + { + PowerReceiver.Load = 1; + _lightState = EmergencyLightState.Full; + } + } + } + + private void TurnOff() + { + Sprite.LayerSetState(0, "emergency_light_off"); + Light.Enabled = false; + } + + private void TurnOn() + { + Sprite.LayerSetState(0, "emergency_light_on"); + Light.Enabled = true; + } + + public override void Initialize() + { + base.Initialize(); + Owner.GetComponent().OnPowerStateChanged += UpdateState; + } + + public override void OnRemove() + { + Owner.GetComponent().OnPowerStateChanged -= UpdateState; + base.OnRemove(); + } + + void IExamine.Examine(FormattedMessage message, bool inDetailsRange) + { + message.AddMarkup(Loc.GetString($"The battery indicator displays: {BatteryStateText[_lightState]}.")); + } + + public enum EmergencyLightState + { + Charging, + Full, + Empty, + On + } + + public Dictionary BatteryStateText = new Dictionary + { + { EmergencyLightState.Full, "[color=darkgreen]Full[/color]"}, + { EmergencyLightState.Empty, "[color=darkred]Empty[/color]"}, + { EmergencyLightState.Charging, "[color=darkorange]Charging[/color]"}, + { EmergencyLightState.On, "[color=darkorange]Discharging[/color]"} + }; + } +} diff --git a/Content.Server/GameObjects/EntitySystems/EmergencyLightSystem.cs b/Content.Server/GameObjects/EntitySystems/EmergencyLightSystem.cs new file mode 100644 index 0000000000..59c83e724b --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/EmergencyLightSystem.cs @@ -0,0 +1,18 @@ +using Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerReceiverUsers; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + internal sealed class EmergencyLightSystem : EntitySystem + { + public override void Update(float frameTime) + { + foreach (var comp in ComponentManager.EntityQuery()) + { + comp.OnUpdate(frameTime); + } + } + } +} diff --git a/Content.Server/IgnoredComponents.cs b/Content.Server/IgnoredComponents.cs index cd9713f35d..518d680cf7 100644 --- a/Content.Server/IgnoredComponents.cs +++ b/Content.Server/IgnoredComponents.cs @@ -17,7 +17,6 @@ "AnimationsTest", "ItemStatus", "Marker", - "EmergencyLight", "Clickable", "RadiatingLight", }; diff --git a/Resources/Prototypes/Entities/Constructible/Walls/emergency_light.yml b/Resources/Prototypes/Entities/Constructible/Walls/emergency_light.yml index c3253d28d8..64a95e6bd5 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/emergency_light.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/emergency_light.yml @@ -1,17 +1,27 @@ -- type: entity +- 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. parent: WallLight components: - type: PointLight + enabled: false radius: 10 energy: 2.5 offset: "0.5, 0" color: "#FF4020" mask: /Textures/emergency_mask.png - - type: EmergencyLight - + - type: PowerReceiver + - type: Battery + maxCharge: 30000 + startingCharge: 0 + - type: Sprite + sprite: Constructible/Lighting/emergency_light.rsi + state: emergency_light_off + - type: Icon + sprite: Constructible/Lighting/emergency_light.rsi + state: emergency_light_off placement: snap: - Wallmount diff --git a/Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_off.png b/Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_off.png new file mode 100644 index 0000000000..6427384c2f Binary files /dev/null and b/Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_off.png differ diff --git a/Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_on.png b/Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_on.png new file mode 100644 index 0000000000..364d44b505 Binary files /dev/null and b/Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_on.png differ diff --git a/Resources/Textures/Constructible/Lighting/emergency_light.rsi/meta.json b/Resources/Textures/Constructible/Lighting/emergency_light.rsi/meta.json new file mode 100644 index 0000000000..5e722f0710 --- /dev/null +++ b/Resources/Textures/Constructible/Lighting/emergency_light.rsi/meta.json @@ -0,0 +1,66 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "states": [ + { + "name": "emergency_light_off", + "directions": 4, + "delays": [ + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ], + [ + 1.0 + ] + ] + }, + { + "name": "emergency_light_on", + "directions": 4, + "delays": [ + [ + 0.3, + 0.3, + 0.3, + 0.3, + 0.3, + 0.3 + ], + [ + 0.3, + 0.3, + 0.3, + 0.3, + 0.3, + 0.3 + ], + [ + 0.3, + 0.3, + 0.3, + 0.3, + 0.3, + 0.3 + ], + [ + 0.3, + 0.3, + 0.3, + 0.3, + 0.3, + 0.3 + ] + ] + } + ] +}