From 1c21f2c3b078bf9505e88169ce437ba5e01274f7 Mon Sep 17 00:00:00 2001 From: Julian Giebel Date: Sat, 22 Aug 2020 12:06:29 +0200 Subject: [PATCH] Rework emergency lights (#1830) * Implement emergency lights reacting to lost power * Add emergency light sprites Remove shared emergency light component * Remove unused import * Remove EmergencyLight NetID * Add rich description Change comments Add license Implement ExposeData Co-authored-by: Julian Giebel --- .../Components/EmergencyLightComponent.cs | 3 +- .../EmergencyLightComponent.cs | 143 ++++++++++++++++++ .../EntitySystems/EmergencyLightSystem.cs | 18 +++ Content.Server/IgnoredComponents.cs | 1 - .../Constructible/Walls/emergency_light.yml | 16 +- .../emergency_light_off.png | Bin 0 -> 336 bytes .../emergency_light_on.png | Bin 0 -> 1562 bytes .../Lighting/emergency_light.rsi/meta.json | 66 ++++++++ 8 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/EmergencyLightComponent.cs create mode 100644 Content.Server/GameObjects/EntitySystems/EmergencyLightSystem.cs create mode 100644 Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_off.png create mode 100644 Resources/Textures/Constructible/Lighting/emergency_light.rsi/emergency_light_on.png create mode 100644 Resources/Textures/Constructible/Lighting/emergency_light.rsi/meta.json 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 0000000000000000000000000000000000000000..6427384c2fe2b5141aa7382bc08e944ab57b0a09 GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zxjbDQLn`LH zy}hybkb%gtkNSelOBO6}>X;=oQ&!`KvZh31lb}WdKUbMWw~?t+h=}GU$8}yM1;=0Z z2<$uZKR)%R=CtJ9m6d)f?vF2S`K4QDC9izlu=dqXI|F0qwa>UcgN$aH{7s#gU3=qo ziQT@uvit{o7(DAQY&mUHFTo6S3gTe~DWM4f-js?e literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..364d44b505bce2369889774c5d09307085aef55d GIT binary patch literal 1562 zcmZuxc~BBq7{^S>BOTk)U5`B0V{%2>4m(8Y&_XM5O$$#vQnb}H6;YRvX)VXKGNn{V zM9nJ`j~#CVN;6NSw7?V6);w56K|w@xadzC8xjB{=&rBa015g-Ew&m+ce=&|1X#NJ-8}h z`^4Hgt*N4w;2N{`z{LH!y@8tPi4|4Ah->#ho8IjTNHuLs&NiD0x&m1-(TqTna@;et z_OaDkZAXe0bjOY{`9eCQOdwIFt!XE5o1_+&OqpYJu1`IQIiC;|pe+R7WZuFYLbvkU zijL}c-|(UFbI8yWl^!n!k3n@a5*(7&D;7q8rpWC4H$`RAMUSGsnn3MFQ#aBeY)=YlSP=b|UK)|bO)ICEt zkJ{Rl^kQ<=>7lZ^Egi7I;e-`frQmIkzc$^R{PZJcs^s0HgDy!eaBwwQ+CBo_8YP1B zO@#1;H8nG&?+^CISeJR8kBDF_6HFg)&t9SO=bJS2#C}(g%&pqezCv%3D6lnBio-r> zP!jglGO4ELndQE8)>Eck03n_;vymWR%qT%}E^DQnaT{BC_`t8BUy$B~vJnA~5E~f{ z%f%Bip3s2(DUv;O>E$YT`}Mv#)>0to9-~wo#L%{&H@!+Gjaf^a2i7mnbWDm&<@ho= z_M{&~yATaE{>E{Ww~*sMB7B%(4&-RaP5*IUs3LP25m`W{aUv%KqB0(}$}ggk`&}k$jmY2;Uh|hQ;{fh$ z!|B+T`@hb``*7qecX5*%?;~7mtPW9K61aBKkkTO# zgE~w6SZnxVW4(0I_~BQ^X7f~^-DMUO(`UfHA}a6W)8&%u6dofa3WUc-g;pK!kyM5_ zrozOlF+r?cb5u-41ij63wt~28hw>79mSN}346}&f=o}=+!>(HK^M2Rah;2IzF0bJj z*(aMf$fI#a@ZoN0+;dlpV1fT(kNs zcgax-0^^E3LnN_hzt=8GQF*c=Xb^~7cX=X&xm{h#EG_v@h4r#wdhN6T(g=oWnq2-F zf4CFSzF)b5DLU1j&j`z7mIp=!%+VCWWAcsCPVxjt)eY3-fB;wWqC&>{8BQLqmddQm z&SHP%i7qrKE5^oFEDxY7(f|1J^5izXJ=$=}U8-!ZO7sC&u%#6~0Y^=+(!@dto-L1O z%dz2LxbluubPO*Ib}996&IP9F^8#;q*CFbS#?U4rrJX|I+4nX}N@|C{xZ7b&2x?g0 zc_JkzLV-y(E?MV;pjg>;E@(?99499PCU3Sp1Ly3&t(tZd=}$+Cv)pko(>L>u`}&0o)ow77ZB1Jp;z`X^`&1$B0C1-;|FZ?Vldt(b$2D8Q zja6FI%Bm#1(~PXw8rIt_K&-qLopXZiW$k7DyVaW;b<8;5Fdv%$|lE414T`?=R(9yV7{C;!qSU({4ZzxnGIz_ Wy$`)>JsA_*P8Vl4r|NTocmDy0=oR1q literal 0 HcmV?d00001 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 + ] + ] + } + ] +}