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 e0101a39dd..f10246f250 100644 Binary files a/Resources/Textures/Constructible/Lighting/light_small.rsi/broken.png and b/Resources/Textures/Constructible/Lighting/light_small.rsi/broken.png differ diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/burned.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/burned.png index 18b937bffb..14edf57a5e 100644 Binary files a/Resources/Textures/Constructible/Lighting/light_small.rsi/burned.png and b/Resources/Textures/Constructible/Lighting/light_small.rsi/burned.png differ diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/empty.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/empty.png index 781b969a68..2b8c7667fe 100644 Binary files a/Resources/Textures/Constructible/Lighting/light_small.rsi/empty.png and b/Resources/Textures/Constructible/Lighting/light_small.rsi/empty.png differ diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/off.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/off.png index 1de87fbca1..027251020c 100644 Binary files a/Resources/Textures/Constructible/Lighting/light_small.rsi/off.png and b/Resources/Textures/Constructible/Lighting/light_small.rsi/off.png differ diff --git a/Resources/Textures/Constructible/Lighting/light_small.rsi/on.png b/Resources/Textures/Constructible/Lighting/light_small.rsi/on.png index adb120e1bb..8a553f8d3a 100644 Binary files a/Resources/Textures/Constructible/Lighting/light_small.rsi/on.png and b/Resources/Textures/Constructible/Lighting/light_small.rsi/on.png differ