From 59e72697cbef58b2527e5e0687b51912551f6d43 Mon Sep 17 00:00:00 2001 From: Alex Evgrashin Date: Sun, 7 Feb 2021 02:05:53 +0300 Subject: [PATCH] Buildable wall light (#2644) * Added empty light * Can build light fixture * Can construct and deconstruct small light * You can build bulbs only on walls * Playing with placement conditions * Refactored code a bit * Added check for north direction and snapping * Fixed all small light sprites (wrong directions order) * Fixed weird problem with bulb lights * Fixed rotation on all stations * Fixed map again * Much better placement mode * Deleted shared wall component and moved all logic to raycasts * Missing bracket * Better texture * Moved wallmount condition to tags * Removed station station * Added suffix and fixed on map init bug --- .../Placement/Modes/WallmountLight.cs | 68 ++++++++++++++++ .../PoweredLightComponent.cs | 20 +++-- .../WallmountCondition.cs | 55 +++++++++++++ Resources/Maps/saltern.yml | 73 ++++++++++-------- .../Entities/Constructible/Walls/lighting.yml | 59 +++++++++----- .../Entities/Constructible/Walls/walls.yml | 5 +- .../Recipes/Construction/Graphs/lighting.yml | 46 +++++++++++ .../Recipes/Construction/lighting.yml | 36 +++++++++ Resources/Prototypes/tags.yml | 3 + .../Lighting/light_small.rsi/broken.png | Bin 246 -> 1047 bytes .../Lighting/light_small.rsi/burned.png | Bin 274 -> 1069 bytes .../Lighting/light_small.rsi/empty.png | Bin 199 -> 1007 bytes .../Lighting/light_small.rsi/off.png | Bin 262 -> 1060 bytes .../Lighting/light_small.rsi/on.png | Bin 287 -> 440 bytes 14 files changed, 306 insertions(+), 59 deletions(-) create mode 100644 Content.Client/Placement/Modes/WallmountLight.cs create mode 100644 Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs create mode 100644 Resources/Prototypes/Recipes/Construction/Graphs/lighting.yml create mode 100644 Resources/Prototypes/Recipes/Construction/lighting.yml diff --git a/Content.Client/Placement/Modes/WallmountLight.cs b/Content.Client/Placement/Modes/WallmountLight.cs new file mode 100644 index 0000000000..ba01d7a293 --- /dev/null +++ b/Content.Client/Placement/Modes/WallmountLight.cs @@ -0,0 +1,68 @@ +#nullable enable +using Robust.Client.Placement; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Content.Client.Placement.Modes +{ + public class WallmountLight : PlacementMode + { + public WallmountLight(PlacementManager pMan) : base(pMan) + { + } + + public override void AlignPlacementMode(ScreenCoordinates mouseScreen) + { + MouseCoords = ScreenToCursorGrid(mouseScreen); + CurrentTile = GetTileRef(MouseCoords); + + if (pManager.CurrentPermission!.IsTile) + { + return; + } + + var tileCoordinates = new EntityCoordinates(MouseCoords.EntityId, CurrentTile.GridIndices); + + Vector2 offset; + switch (pManager.Direction) + { + case Direction.North: + offset = new Vector2(0.5f, 1f); + break; + case Direction.South: + offset = new Vector2(0.5f, 0f); + break; + case Direction.East: + offset = new Vector2(1f, 0.5f); + break; + case Direction.West: + offset = new Vector2(0f, 0.5f); + break; + default: + return; + } + + tileCoordinates = tileCoordinates.Offset(offset); + MouseCoords = tileCoordinates; + } + + public override bool IsValidPosition(EntityCoordinates position) + { + if (pManager.CurrentPermission!.IsTile) + { + return false; + } + else if (!RangeCheck(position)) + { + return false; + } + + return true; + } + } +} diff --git a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/PoweredLightComponent.cs b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/PoweredLightComponent.cs index cda8f1b7cd..de2bd96d16 100644 --- a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/PoweredLightComponent.cs +++ b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/PoweredLightComponent.cs @@ -38,6 +38,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece private static readonly TimeSpan _thunkDelay = TimeSpan.FromSeconds(2); private TimeSpan _lastThunk; + private bool _hasLampOnSpawn; [ViewVariables] private bool _on; @@ -148,6 +149,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece { serializer.DataField(ref BulbType, "bulb", LightBulbType.Tube); serializer.DataField(ref _on, "on", true); + serializer.DataField(ref _hasLampOnSpawn, "hasLampOnSpawn", true); } /// @@ -229,15 +231,19 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents.PowerRece void IMapInit.MapInit() { - var prototype = BulbType switch + if (_hasLampOnSpawn) { - LightBulbType.Bulb => "LightBulb", - LightBulbType.Tube => "LightTube", - _ => throw new ArgumentOutOfRangeException() - }; + var prototype = BulbType switch + { + LightBulbType.Bulb => "LightBulb", + LightBulbType.Tube => "LightTube", + _ => throw new ArgumentOutOfRangeException() + }; - var entity = Owner.EntityManager.SpawnEntity(prototype, Owner.Transform.Coordinates); - _lightBulbContainer.Insert(entity); + var entity = Owner.EntityManager.SpawnEntity(prototype, Owner.Transform.Coordinates); + _lightBulbContainer.Insert(entity); + UpdateLight(); + } } public void TriggerSignal(bool signal) diff --git a/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs b/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs new file mode 100644 index 0000000000..73087b1f40 --- /dev/null +++ b/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs @@ -0,0 +1,55 @@ +#nullable enable +using Content.Shared.GameObjects.Components.Tag; +using Content.Shared.Physics; +using JetBrains.Annotations; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Physics; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Serialization; +using System.Linq; + +namespace Content.Shared.Construction.ConstructionConditions +{ + [UsedImplicitly] + public class WallmountCondition : IConstructionCondition + { + public void ExposeData(ObjectSerializer serializer) { } + + public bool Condition(IEntity user, EntityCoordinates location, Direction direction) + { + var entManager = IoCManager.Resolve(); + + // get blueprint and user position + var userWorldPosition = user.Transform.WorldPosition; + var objWorldPosition = location.ToMap(entManager).Position; + + // find direction from user to blueprint + var userToObject = (objWorldPosition - userWorldPosition); + + // dot product will be positive if user direction and blueprint are co-directed + var dotProd = Vector2.Dot(direction.ToVec(), userToObject); + if (dotProd > 0) + return false; + + // now we need to check that user actually tries to build wallmount on a wall + var physics = IoCManager.Resolve(); + var rUserToObj = new CollisionRay(userWorldPosition, userToObject.Normalized, (int) CollisionGroup.Impassable); + var length = userToObject.Length; + var userToObjRaycastResults = physics.IntersectRayWithPredicate(user.Transform.MapID, rUserToObj, maxLength: length, + predicate: (e) => !e.HasTag("Wall")); + if (!userToObjRaycastResults.Any()) + return false; + + // get this wall entity + var targetWall = userToObjRaycastResults.First().HitEntity; + + // check that we didn't try to build wallmount that facing another adjacent wall + var rAdjWall = new CollisionRay(objWorldPosition, direction.ToVec(), (int) CollisionGroup.Impassable); + var adjWallRaycastResults = physics.IntersectRayWithPredicate(user.Transform.MapID, rAdjWall, maxLength: 0.5f, + predicate: (e) => e == targetWall || !e.HasTag("Wall")); + return !adjWallRaycastResults.Any(); + } + } +} diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index 6c744ecaf1..b5541b8aeb 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -20002,7 +20002,7 @@ entities: components: - parent: 853 pos: -12.5,-5 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -21324,7 +21324,7 @@ entities: components: - parent: 853 pos: -6.5,-26 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -21430,6 +21430,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: -7,-23.5 type: Transform - color: '#FFFFFFFF' @@ -22573,7 +22574,7 @@ entities: components: - parent: 853 pos: -29.5,15 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -22602,7 +22603,7 @@ entities: components: - parent: 853 pos: -34,-0.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -22616,6 +22617,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: -18,-4.5 type: Transform - color: '#FFFFFFFF' @@ -22700,7 +22702,7 @@ entities: components: - parent: 853 pos: -29.5,-9 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -22883,6 +22885,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: -19,9.5 type: Transform - color: '#FFFFFFFF' @@ -22912,7 +22915,7 @@ entities: components: - parent: 853 pos: -14.5,-16 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -22926,6 +22929,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: -7,-12.5 type: Transform - color: '#FFFFFFFF' @@ -22940,6 +22944,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: -11,-10.5 type: Transform - color: '#FFFFFFFF' @@ -23112,7 +23117,7 @@ entities: components: - parent: 853 pos: -19,16.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23127,7 +23132,7 @@ entities: components: - parent: 853 pos: -14.5,26 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23142,7 +23147,7 @@ entities: components: - parent: 853 pos: -19,22.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23157,7 +23162,7 @@ entities: components: - parent: 853 pos: -18,9.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23172,7 +23177,7 @@ entities: components: - parent: 853 pos: -0.5,-12 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23386,7 +23391,7 @@ entities: components: - parent: 853 pos: -1,8.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23401,7 +23406,7 @@ entities: components: - parent: 853 pos: -4,8.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23528,7 +23533,7 @@ entities: components: - parent: 853 pos: -7.5,26 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23550,7 +23555,7 @@ entities: components: - parent: 853 pos: -4,17.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -23783,6 +23788,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: 17,15.5 type: Transform - color: '#FFFFFFFF' @@ -23797,6 +23803,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: 14,16.5 type: Transform - color: '#FFFFFFFF' @@ -23812,7 +23819,7 @@ entities: components: - parent: 853 pos: 8.5,15 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24274,7 +24281,7 @@ entities: components: - parent: 853 pos: 30.5,-6 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24289,7 +24296,7 @@ entities: components: - parent: 853 pos: 25.5,-1 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24304,7 +24311,7 @@ entities: components: - parent: 853 pos: 9.5,-18 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24347,7 +24354,7 @@ entities: components: - parent: 853 pos: 12.5,-19 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24369,7 +24376,7 @@ entities: components: - parent: 853 pos: 25.5,-19 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24383,6 +24390,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: 28,-15.5 type: Transform - color: '#FFFFFFFF' @@ -24432,6 +24440,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: 28,-10.5 type: Transform - color: '#FFFFFFFF' @@ -24453,6 +24462,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: 24,0.5 type: Transform - color: '#FFFFFFFF' @@ -24468,7 +24478,7 @@ entities: components: - parent: 853 pos: 26,-4.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24483,7 +24493,7 @@ entities: components: - parent: 853 pos: 35.5,-6 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24498,7 +24508,7 @@ entities: components: - parent: 853 pos: 38.5,-3 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24513,7 +24523,7 @@ entities: components: - parent: 853 pos: 26,11.5 - rot: 3.141592653589793 rad + rot: 0 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -24709,6 +24719,7 @@ entities: type: PoweredSmallLight components: - parent: 853 + rot: 3.141592653589793 rad pos: 44,-1.5 type: Transform - color: '#FFFFFFFF' @@ -26432,7 +26443,7 @@ entities: components: - parent: 853 pos: -12.5,-6 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -26447,7 +26458,7 @@ entities: components: - parent: 853 pos: -25.5,-10 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - color: '#FFFFFFFF' type: PointLight @@ -42390,7 +42401,7 @@ entities: components: - parent: 853 pos: 22.528679,-9.003884 - rot: 1.5707963267948966 rad + rot: -1.5707963267948966 rad type: Transform - powerLoad: 0 type: PowerReceiver @@ -42772,7 +42783,7 @@ entities: components: - parent: 853 pos: -1.4929452,19.970068 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - powerLoad: 0 type: PowerReceiver @@ -42799,7 +42810,7 @@ entities: components: - parent: 853 pos: -15.494916,15.968084 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - powerLoad: 0 type: PowerReceiver @@ -44360,7 +44371,7 @@ entities: components: - parent: 853 pos: -22.5,-16 - rot: -1.5707963267948966 rad + rot: 1.5707963267948966 rad type: Transform - powerLoad: 0 type: PowerReceiver diff --git a/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml b/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml index 47a5cd08d5..ac9555174e 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml @@ -4,6 +4,9 @@ components: - type: Clickable - type: InteractionOutline + - type: Construction + graph: lightFixture + node: tubeLight - type: Physics shapes: - !type:PhysShapeAabb @@ -47,10 +50,39 @@ - !type:DoActsBehavior acts: ["Destruction"] +- type: entity + id: PoweredlightEmpty + suffix: Empty + parent: Poweredlight + components: + - type: Sprite + state: empty + - type: PoweredLight + hasLampOnSpawn: False + +- type: entity + name: unpowered small light + id: SmallLight + parent: WallLight + components: + - type: Sprite + sprite: Constructible/Lighting/light_small.rsi + state: on + - type: PointLight + energy: 1.0 + enabled: true + offset: "-0.5, 0" + - type: Destructible + deadThreshold: 25 + resistances: metallicResistances + - type: Construction + graph: lightFixture + node: bulbLight + - type: entity name: small light id: PoweredSmallLight - parent: WallLight + parent: SmallLight components: - type: Sprite sprite: Constructible/Lighting/light_small.rsi @@ -79,24 +111,11 @@ acts: ["Destruction"] - type: entity - name: unpowered small light - id: SmallLight - parent: WallLight + id: PoweredSmallLightEmpty + suffix: Empty + parent: PoweredSmallLight components: - type: Sprite - sprite: Constructible/Lighting/light_small.rsi - state: on - - type: PointLight - energy: 1.0 - enabled: true - offset: "-0.5, 0" - - type: Damageable - resistances: metallicResistances - - type: Destructible - thresholds: - - trigger: - !type:TotalDamageTrigger - damage: 25 - behaviors: - - !type:DoActsBehavior - acts: ["Destruction"] + state: empty + - type: PoweredLight + hasLampOnSpawn: False diff --git a/Resources/Prototypes/Entities/Constructible/Walls/walls.yml b/Resources/Prototypes/Entities/Constructible/Walls/walls.yml index 7b1f289dc2..80bdf95b40 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/walls.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/walls.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity id: base_wall name: basewall description: Keeps the air in and the greytide out. @@ -9,6 +9,9 @@ - Wall components: - type: RCDDeconstructWhitelist + - type: Tag + tags: + - Wall - type: Clickable - type: InteractionOutline - type: Sprite diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/lighting.yml b/Resources/Prototypes/Recipes/Construction/Graphs/lighting.yml new file mode 100644 index 0000000000..0d80074446 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/lighting.yml @@ -0,0 +1,46 @@ +- type: constructionGraph + id: lightFixture + start: start + graph: + - node: start + edges: + - to: bulbLight + steps: + - material: Metal + amount: 1 + doAfter: 2.0 + - to: tubeLight + steps: + - material: Metal + amount: 2 + doAfter: 2.0 + - node: tubeLight + entity: PoweredlightEmpty + edges: + - to: start + conditions: + - !type:ContainerEmpty + container: "light_bulb" + steps: + - tool: Screwing + doAfter: 2.0 + completed: + - !type:SpawnPrototype + prototype: SteelSheet1 + amount: 2 + - !type:DeleteEntity {} + - node: bulbLight + entity: PoweredSmallLightEmpty + edges: + - to: start + conditions: + - !type:ContainerEmpty + container: "light_bulb" + steps: + - tool: Screwing + doAfter: 2.0 + completed: + - !type:SpawnPrototype + prototype: SteelSheet1 + amount: 1 + - !type:DeleteEntity {} diff --git a/Resources/Prototypes/Recipes/Construction/lighting.yml b/Resources/Prototypes/Recipes/Construction/lighting.yml new file mode 100644 index 0000000000..6fc5ddc8b2 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/lighting.yml @@ -0,0 +1,36 @@ +- type: construction + name: wall light + id: LightTubeFixture + graph: lightFixture + startNode: start + targetNode: tubeLight + category: Structures + description: A wall light fixture. Use light tubes. + icon: + sprite: Constructible/Lighting/light_tube.rsi + state: off + objectType: Structure + placementMode: WallmountLight + canRotate: true + canBuildInImpassable: true + conditions: + - !type:WallmountCondition {} + +- type: construction + name: small wall light + id: LightSmallFixture + graph: lightFixture + startNode: start + targetNode: bulbLight + category: Structures + description: A wall light fixture. Use light bulbs. + icon: + sprite: Constructible/Lighting/light_small.rsi + state: off + objectType: Structure + placementMode: WallmountLight + canRotate: true + canBuildInImpassable: true + conditions: + - !type:WallmountCondition {} + diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 489d564aac..b8023a3ceb 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -1,2 +1,5 @@ - type: Tag id: ExplosivePassable + +- type: Tag + id: Wall diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/broken.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/broken.png index e0101a39dd6c55380d34c0840566d8b879bb3233..f10246f25055062fa09fd51c7b7acc93d7968495 100644 GIT binary patch delta 1017 zcmV004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}00093P)t-s0000P85ul0Jd=}?u(T}5#2)17jRyw@2nYxX z2?+`c3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85w^X z8X6lL8yp-Q9UUDW9v&YbA0QwgAt50mA|fLrBP1jwB_$;$CMG8*CnzW=DJdx`Dk>{0 zD=aK5EiElBE-o)GFEB7LF)=YRGBPtWGc+_bH8nLhHa0gmH#j&rIXO8xIyyT$J3Kr* zJv}`>K0ZG`KR`f0K|w)6LPA4BLqvZ>L`6kKMn*_~R#sM5S65hASXo(FT3T9LTU%UQTwPsVUS3{b zUteHgU}0flVq#)rV`F4wWMyS#W@ct*XJ=?=XlZF_YHDh0Yin$5Y;A3AZf<{WZ*OmK zaBy*PadL8Ub8~ZabaZufb#``kcXxMqczAhvd3t(!dwY9)e0+U< zlarH_l$4c~m6n#4mzS5An3#W=nVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAgu zq@<*!rKP5(rl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIf zwY9dkwzs#pxVX5vxw*Q!y1To(yu7@V!^FhI#l^+O z#>U6T$H>UY$;rve%F4^j%goHo&CSiu&d$%z&(P4&(b3V;($dq@)6~?|)z#J3*4Ee8 z*Vx$D+1c6J+S=RO+uYpT-QC^Z-rnEe-{9cj;o;%p;^O1ulq(=H}<;=jiC@ z>FMd}>gwz3>+J08?d^Z~$F2VZ<`Uga z_K*4Yn`%Ec`?*I%M8u`9cg{K>Jg2_vCZ+E^27&I~$b!U!dXZTB08$4{7^QtcH*iod nk^3dgRGoBC{IrP?;dl%HeQg2h5cQo^00000NkvXXu0mjff8pze delta 210 zcmV;@04@KQ2=)Px7zqRe00013M{MnpAsBxZP)t-s0000P85ul0Jd=}?u(T}5#2)17 zjhyphm;e9(0d!JMQvg8b*k%9#0D4J8K~zY`V_?7vm=%Q#81MmR6({@(7+g~sC{w@^ z78ZbCMJO8qD_9w*4hR}a$Wes7MRCXxj2wc|I|@d@C>XMUmBARnF=lYUP>>d?gy23X zxrAbxkmiWsh=isFpv#AaA}dG>z%U`y1=)(wGz0<8#;7zqdi0001;w}I@DAs8(nV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}00093kvbxO3JMAf3kwVk3=Itp4h{|v4-XI!5D^g(5)u*< z6B85^6crT}78Vv47Z(^97#SHE8X6iK8yg%P9334U9v&VaA0HqfAR!?kA|fIqBO@dv zBqb#!CMG5)CnqQ@~D=RE4EG;c9E-o%FFE21KFflPPGBPqVGcz=QG&D6e zH8wUjH#avpI5;^uIXXHzJ3Bi(JUl%;Jw84@KR-V}KtMr3K|(@8LqkJEL_|eJMMg$O zM@L6UNJvRZNlHpeOG`^kOiWEpO-@cuPft%!P*71(QBqP;Q&Uq^R8&<}RaRD3S65e9 zSXfzESz20JTU%RPTwGmUU0z;)USD5dU|?WjVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@ zX=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2Ta&vQYbaZreb#-=jc6WDoczAeud3kzz zdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyDgoK2Jg@uNOhKGlTh=_=PiHV7dii(Si zi;Rqnjg5_tj*gFykC2d%k&%&-l9H2?la!Q{m6es2mX?>7mzbECnVFfInwp!No1C1S zot>SYo}QndpP-Ll?si~=|s;aB2tE{Z7t*x!D zuCA}IuduMNv9YnTva+*(v$M3cw6(Rhwzjsnx3{>sxVgExy1Kf%ySu!+yuH1>zP`S{ zzrVo1z`?=6!otGC!^6bH#KpzM#>U3S$H&OX$jQmc%F4>i%gfBn%+1Zs&d$!y&(F}% z(9zM+($dn?)6>+{)YaA1*4Eb7*VowC*xA|H+S=ON+uPjS+}+)O-QM2b-{0Th;Naom z;o{=ruz*=jZ3>=;-O`>FVn0>+9?6?CkCB?e6aG@9*#M@bK~R@$&NW z^Yioc^z`-h_4fAm_xJbs`1twx`TF|$`}_O+{QUj>{r>*`|NsBCOW0Qc0004WQchC< zK<3zH0001*Nkl<^RCwC#ma!58AqYef7MA<}A5M`b#d%J$laALatE@0$_DRKBQT96( z-I9P^U@P&4Oepb5xO4@QaOnz!YaW>B;r|a%Q*EZ@ f+?qHHgTiY7qILrz{}vaA00000NkvXXu0mjfV}j-& delta 208 zcmV;>05AWo2$BMj7zqRe00013M{MnpAs7K3k!B))()n-Z00001bW%=J06^y0W&i*H zjY&j7R7l5TV89C4422UI@Buc9X8Z~m+CA~hGq{G}m**&Q55TK{MWws|zY$ID1l+(; zKuCa8BMCZ+ptlGH48fo!7&!!^cNC0*Q7~jdDMK29lg7}3F3(=>X^h|*w-hy?DJUrk zX+-chBuZ5@(2GH*aAXCp?&!rLhq?!{6;m)vMGsU*hL1+u5Cj09+8T43`4KSy0000< KMNUMnLSTY=*G`ZC diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/empty.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/empty.png index 781b969a684fcb88fc905499103bbdd6f0e8d908..2b8c7667fe6bbed5199c77e311608b76c54fde0d 100644 GIT binary patch delta 977 zcmV;?11|i>0q+Np7zqdi0001;w}I@DAsBxkV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}00093P)t-s0000P85ul0JZNWIlarIEbQ8aX6$b|g2nYxX z2?+`c3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85w^X z8X6lL8yp-Q9UUDW9v&YbA0QwgAt50mA|fLrBP1jwB_$;$CMG8*CnzW=DJdx`Dk>{0 zD=aK5EiElBE-o)GFEB7LF)=YRGBPtWGc+_bH8nLhHa0gmH#j&rIXO8xIyyT$J3Kr* zJv}`>K0ZG`KR`f0K|w)6LPA4BLqvZ>L`6kKMn*_~R#sM5S65hASXo(FT3T9LTU%UQTwPsVUS3{b zUteHgU}0flVq#)rV`F4wWMyS#W@ct*XJ=?=XlZF_YHDh0Yin$5Y;A3AZf<{WZ*OmK zaBy*PadL8Ub8~ZabaZufb#``kcXxMqczAhvd3t(!dwY9)e0+U< zlarH_l$4c~m6n#4mzS5An3#W=nVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAgu zq@<*!rKP5(rl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIf zwY9dkwzs#pxVX5vxw*Q!y1To(yu7@V!^FhI#l^+O z#>U6T$H>UY$;rve%F4^j%goHo&CSiu&d$%z&(P4&(b3V;($dq@)6~?|)z#J3*4Ee8 z*Vx$D+1c6J+S=RO+uYpT-QC^Z-rnEe-{9cj;o;%p;^O1ulq(=H}<;=jiC@ z>FMd}>gwz3>+J08?d^ZNw@W!J`3o{ZvyNV>`MgT*Z=?k|NjF3#|Z%0kUHN000000NkvXXu0mjfSliV5 delta 163 zcmaFQew=ZF1SbnK0|P^Zd(PX5iW2pr0X`wFK)$4;q>YVDMtbz*$&*)<2=8wZJs91= z4wPUl3GxeOaCmkj4ao8Kba4#vIG&tvfGa|zRYu|iqu5rJKU@+%&5~}6xeN;zs7hF} zEG`%6X$mxGY2*%5V=~ZIyy3+bA+kYD=|&Rc6Agt7R!8@~CP#h--?QwxiTq85EI@M^ NJYD@<);T3K0RUyTFWUeB diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/off.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/off.png index 1de87fbca1f1b337a3b755fe7c22d34ba4cc2adc..027251020c16155895dd4bcd02653657820ba037 100644 GIT binary patch delta 1030 zcmV+h1o``h0;C9#7zqdi0001;w}I@DAsBxkV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}00093P)t-s0000P85ul0Jd=}?u(T}5#2)17jRyw@2nYxX z2?+`c3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85w^X z8X6lL8yp-Q9UUDW9v&YbA0QwgAt50mA|fLrBP1jwB_$;$CMG8*CnzW=DJdx`Dk>{0 zD=aK5EiElBE-o)GFEB7LF)=YRGBPtWGc+_bH8nLhHa0gmH#j&rIXO8xIyyT$J3Kr* zJv}`>K0ZG`KR`f0K|w)6LPA4BLqvZ>L`6kKMn*_~R#sM5S65hASXo(FT3T9LTU%UQTwPsVUS3{b zUteHgU}0flVq#)rV`F4wWMyS#W@ct*XJ=?=XlZF_YHDh0Yin$5Y;A3AZf<{WZ*OmK zaBy*PadL8Ub8~ZabaZufb#``kcXxMqczAhvd3t(!dwY9)e0+U< zlarH_l$4c~m6n#4mzS5An3#W=nVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAgu zq@<*!rKP5(rl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIf zwY9dkwzs#pxVX5vxw*Q!y1To(yu7@V!^FhI#l^+O z#>U6T$H>UY$;rve%F4^j%goHo&CSiu&d$%z&(P4&(b3V;($dq@)6~?|)z#J3*4Ee8 z*Vx$D+1c6J+S=RO+uYpT-QC^Z-rnEe-{9cj;o;%p;^O1ulq(=H}<;=jiC@ z>FMd}>gwz3>+J08?d^Z%>EI= z?5C$d$y1;tcLdV}SHM0t``njhS(at_>g(-@IpmSg$_uJ)#7s(L)#Y14l0MHsN)qxQ zKu#g-Rg#AlfHA~@1P&{7M_`Olz|q8ISsWe%02hV=g{jd>j{pDw07*qoM6N<$g7^69 An*aa+ delta 226 zcmV<803H9N2!;ZX7zqRe00013M{MnpAsBxZP)t-s0000P85ul0Jd=}?u(T}5#2)17 zjhyphm;e9(0d!JMQvg8b*k%9#0E$UOK~xwS?ZLqbgfI|5(GM{Vhz%GlAdm*4#Jh(~ zI>_{2!rlVPGWT74kMG<%M=WkTBBoZcwTj7W&se-l#v~P+&)iKHwo@=oq8FB_>4i?| z?AXqZ$!$l(;?_CxdcFRVkQfregI5U*LGfq~J^)5S5Q;?|p6hJDQj0|CWaqVvr2d%$M3o`4c zEc?i(F!i4_1KUa!-^ELew*R#8OxkHL6JgKIC zjg$N22h0yEKZH(xaO}Y4U-#U@7Jgt@B=7J;Tf&xgcGTu19#{DJ9&KS$$cw@c3$P$@%tx3+Oo5^=G3njstr~z={|afA%SZGOC;M(j*X(A gaE5_~_}k|hu6yfeUEF*w86@cG>gTe~i7BB8096Q{OaK4? delta 251 zcmdnNJfCTT1SbnK0|P^Zd(PX5iW2qG0X`wFK>q*#J0VC?Qqso8X7c38|9>9@imY4P z^9d-;QWE4B%%J4lt(mf^3do=3>EamTaXdNU0M`wt7-5MIj2k~(a@oT*Mf+Cohm*!l zA{-9_52W0?7`Vn^7L%gupD+$h>4hr-jP%2j4yZS*W9**TC9-?gk%n|di7hS4?FnD{ zngR{D*w_rTI3GN0V(FRKdSS-`CAXb-EO-z48ta)mX{(*JKIJTU=fbDHB-brM%N8$Y xIavDsg@bk>hn7MHtE0Qn7qx>8Qmk9p8B7@TSq;6m?*KZJ!PC{xWt~$(69DW+WXk{m