Airlock construction (#3609)
* Add construction and deconstsruction of airlocks * Change name to door electronics * Rearrange things * Fix errors * Fix physics error from bumping * Prevent editing the map for now * Address reviews * Change switch to if * Fix newlines
This commit is contained in:
43
Content.Server/Construction/Conditions/AirlockBolted.cs
Normal file
43
Content.Server/Construction/Conditions/AirlockBolted.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#nullable enable
|
||||||
|
using Content.Server.GameObjects.Components.Doors;
|
||||||
|
using Content.Shared.Construction;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Content.Server.Construction.Conditions
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
[DataDefinition]
|
||||||
|
public class AirlockBolted : IEdgeCondition
|
||||||
|
{
|
||||||
|
[DataField("value")]
|
||||||
|
public bool Value { get; private set; } = true;
|
||||||
|
|
||||||
|
public async Task<bool> Condition(IEntity entity)
|
||||||
|
{
|
||||||
|
if (!entity.TryGetComponent(out AirlockComponent? airlock)) return true;
|
||||||
|
|
||||||
|
return airlock.BoltsDown == Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DoExamine(IEntity entity, FormattedMessage message, bool inDetailsRange)
|
||||||
|
{
|
||||||
|
if (!entity.TryGetComponent(out AirlockComponent? airlock)) return false;
|
||||||
|
|
||||||
|
if (airlock.BoltsDown != Value)
|
||||||
|
{
|
||||||
|
if (Value == true)
|
||||||
|
message.AddMarkup(Loc.GetString("construction-condition-airlock-bolt", ("entityName", entity.Name)) + "\n");
|
||||||
|
else
|
||||||
|
message.AddMarkup(Loc.GetString("construction-condition-airlock-unbolt", ("entityName", entity.Name)) + "\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
#nullable enable
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Content.Server.GameObjects.Components.Doors;
|
using Content.Server.GameObjects.Components.Doors;
|
||||||
using Content.Shared.Construction;
|
using Content.Shared.Construction;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -14,29 +15,30 @@ namespace Content.Server.Construction.Conditions
|
|||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public class DoorWelded : IEdgeCondition
|
public class DoorWelded : IEdgeCondition
|
||||||
{
|
{
|
||||||
[DataField("welded")] public bool Welded { get; private set; } = true;
|
[DataField("welded")]
|
||||||
|
public bool Welded { get; private set; } = true;
|
||||||
|
|
||||||
public async Task<bool> Condition(IEntity entity)
|
public async Task<bool> Condition(IEntity entity)
|
||||||
{
|
{
|
||||||
if (!entity.TryGetComponent(out ServerDoorComponent? doorComponent)) return false;
|
if (!entity.TryGetComponent(out ServerDoorComponent? doorComponent)) return false;
|
||||||
|
|
||||||
return doorComponent.IsWeldedShut == Welded;
|
return doorComponent.IsWeldedShut == Welded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DoExamine(IEntity entity, FormattedMessage message, bool inDetailsRange)
|
public bool DoExamine(IEntity entity, FormattedMessage message, bool inDetailsRange)
|
||||||
{
|
{
|
||||||
if (!entity.TryGetComponent(out ServerDoorComponent? doorComponent)) return false;
|
if (!entity.TryGetComponent(out ServerDoorComponent? door)) return false;
|
||||||
|
|
||||||
if (doorComponent.State == DoorState.Closed && Welded)
|
if (door.IsWeldedShut != Welded)
|
||||||
{
|
{
|
||||||
message.AddMarkup(Loc.GetString("First, weld the door.\n"));
|
if (Welded == true)
|
||||||
|
message.AddMarkup(Loc.GetString("construction-condition-door-weld", ("entityName", entity.Name)) + "\n");
|
||||||
|
else
|
||||||
|
message.AddMarkup(Loc.GetString("construction-condition-door-unweld", ("entityName", entity.Name)) + "\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doorComponent.IsWeldedShut || Welded) return false;
|
return false;
|
||||||
|
|
||||||
message.AddMarkup(Loc.GetString("First, unweld the door.\n"));
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -31,6 +31,8 @@ using Robust.Shared.Physics.Collision;
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
using Timer = Robust.Shared.Timing.Timer;
|
using Timer = Robust.Shared.Timing.Timer;
|
||||||
|
using Content.Server.GameObjects.Components.Construction;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Doors
|
namespace Content.Server.GameObjects.Components.Doors
|
||||||
{
|
{
|
||||||
@@ -42,6 +44,10 @@ namespace Content.Server.GameObjects.Components.Doors
|
|||||||
[ComponentDependency]
|
[ComponentDependency]
|
||||||
private readonly IDoorCheck? _doorCheck = null;
|
private readonly IDoorCheck? _doorCheck = null;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("board")]
|
||||||
|
private string? _boardPrototype;
|
||||||
|
|
||||||
public override DoorState State
|
public override DoorState State
|
||||||
{
|
{
|
||||||
get => base.State;
|
get => base.State;
|
||||||
@@ -164,6 +170,8 @@ namespace Content.Server.GameObjects.Components.Doors
|
|||||||
}
|
}
|
||||||
SetAppearance(DoorVisualState.Welded);
|
SetAppearance(DoorVisualState.Welded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreateDoorElectronicsBoard();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnRemove()
|
public override void OnRemove()
|
||||||
@@ -185,6 +193,8 @@ namespace Content.Server.GameObjects.Components.Doors
|
|||||||
}
|
}
|
||||||
QuickOpen();
|
QuickOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreateDoorElectronicsBoard();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||||
@@ -638,6 +648,39 @@ namespace Content.Server.GameObjects.Components.Doors
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the corresponding door electronics board on the door.
|
||||||
|
/// This exists so when you deconstruct doors that were serialized with the map,
|
||||||
|
/// you can retrieve the door electronics board.
|
||||||
|
/// </summary>
|
||||||
|
private void CreateDoorElectronicsBoard()
|
||||||
|
{
|
||||||
|
// Ensure that the construction component is aware of the board container.
|
||||||
|
if (Owner.TryGetComponent(out ConstructionComponent? construction))
|
||||||
|
construction.AddContainer("board");
|
||||||
|
|
||||||
|
// We don't do anything if this is null or empty.
|
||||||
|
if (string.IsNullOrEmpty(_boardPrototype))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var container = Owner.EnsureContainer<Container>("board", out var existed);
|
||||||
|
|
||||||
|
return;
|
||||||
|
/* // TODO ShadowCommander: Re-enable when access is added to boards. Requires map update.
|
||||||
|
if (existed)
|
||||||
|
{
|
||||||
|
// We already contain a board. Note: We don't check if it's the right one!
|
||||||
|
if (container.ContainedEntities.Count != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var board = Owner.EntityManager.SpawnEntity(_boardPrototype, Owner.Transform.Coordinates);
|
||||||
|
|
||||||
|
if(!container.Insert(board))
|
||||||
|
Logger.Warning($"Couldn't insert board {board} into door {Owner}!");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
public override ComponentState GetComponentState(ICommonSession player)
|
public override ComponentState GetComponentState(ICommonSession player)
|
||||||
{
|
{
|
||||||
return new DoorComponentState(State, StateChangeStartTime, CurrentlyCrushing, GameTiming.CurTime);
|
return new DoorComponentState(State, StateChangeStartTime, CurrentlyCrushing, GameTiming.CurTime);
|
||||||
|
|||||||
7
Resources/Locale/en-US/construction/conditions.ftl
Normal file
7
Resources/Locale/en-US/construction/conditions.ftl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# DoorWelded
|
||||||
|
construction-condition-door-weld = First, weld the {$entityName}.
|
||||||
|
construction-condition-door-unweld = First, unweld the {$entityName}.
|
||||||
|
|
||||||
|
# AirlockBolted
|
||||||
|
construction-condition-airlock-bolt = First, bolt the {$entityName}.
|
||||||
|
construction-condition-airlock-unbolt = First, unbolt the {$entityName}.
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
- state: panel_open
|
- state: panel_open
|
||||||
map: ["enum.WiresVisualLayers.MaintenancePanel"]
|
map: ["enum.WiresVisualLayers.MaintenancePanel"]
|
||||||
- type: Physics
|
- type: Physics
|
||||||
|
mass: 100
|
||||||
fixtures:
|
fixtures:
|
||||||
- shape:
|
- shape:
|
||||||
!type:PhysShapeAabb
|
!type:PhysShapeAabb
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
- VaultImpassable
|
- VaultImpassable
|
||||||
- SmallImpassable
|
- SmallImpassable
|
||||||
- type: Door
|
- type: Door
|
||||||
|
board: DoorElectronics
|
||||||
- type: Airlock
|
- type: Airlock
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
visuals:
|
||||||
@@ -68,8 +70,58 @@
|
|||||||
behaviors:
|
behaviors:
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: ["Destruction"]
|
acts: ["Destruction"]
|
||||||
|
- type: Construction
|
||||||
|
graph: airlock
|
||||||
|
node: airlock
|
||||||
- type: IconSmooth
|
- type: IconSmooth
|
||||||
key: walls
|
key: walls
|
||||||
mode: NoSprite
|
mode: NoSprite
|
||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: AirlockAssembly
|
||||||
|
name: airlock assembly
|
||||||
|
description: It opens, it closes, and maybe crushes you.
|
||||||
|
components:
|
||||||
|
- type: Clickable
|
||||||
|
- type: RCDDeconstructWhitelist
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
|
drawdepth: Mobs
|
||||||
|
sprite: Constructible/Structures/Doors/Standard/basic.rsi
|
||||||
|
state: "assembly"
|
||||||
|
- type: Physics
|
||||||
|
mass: 100
|
||||||
|
fixtures:
|
||||||
|
- shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.49,-0.49,0.49,0.49"
|
||||||
|
mask:
|
||||||
|
- MobImpassable
|
||||||
|
layer:
|
||||||
|
- MobImpassable
|
||||||
|
- VaultImpassable
|
||||||
|
- type: Anchorable
|
||||||
|
snap: true
|
||||||
|
- type: Pullable
|
||||||
|
- type: SnapGrid
|
||||||
|
offset: Center
|
||||||
|
- type: Damageable
|
||||||
|
resistances: metallicResistances
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 300
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: ["Destruction"]
|
||||||
|
- type: Construction
|
||||||
|
graph: airlock
|
||||||
|
node: assembly
|
||||||
|
placement:
|
||||||
|
mode: SnapgridCenter
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
- type: entity
|
||||||
|
id: DoorElectronics
|
||||||
|
parent: BaseItem
|
||||||
|
name: door electronics
|
||||||
|
components:
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- DoorElectronics
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Constructible/Misc/module.rsi
|
||||||
|
state: door_electronics
|
||||||
|
- type: AccessReader
|
||||||
@@ -79,6 +79,10 @@
|
|||||||
- coillv-10
|
- coillv-10
|
||||||
- coillv-20
|
- coillv-20
|
||||||
- coillv-30
|
- coillv-30
|
||||||
|
- type: Material
|
||||||
|
materials:
|
||||||
|
- key: enum.MaterialKeys.Stack
|
||||||
|
mat: Cable
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ApcExtensionCableStack
|
parent: ApcExtensionCableStack
|
||||||
@@ -90,7 +94,6 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
size: 3
|
size: 3
|
||||||
- type: Stack
|
- type: Stack
|
||||||
stackType: ApcExtensionCableStack1
|
|
||||||
count: 1
|
count: 1
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
107
Resources/Prototypes/Recipes/Construction/Graphs/airlock.yml
Normal file
107
Resources/Prototypes/Recipes/Construction/Graphs/airlock.yml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: airlock
|
||||||
|
start: start
|
||||||
|
graph:
|
||||||
|
- node: start
|
||||||
|
edges:
|
||||||
|
- to: assembly
|
||||||
|
completed:
|
||||||
|
- !type:SetAnchor
|
||||||
|
value: false
|
||||||
|
steps:
|
||||||
|
- material: Steel
|
||||||
|
amount: 4
|
||||||
|
doAfter: 2
|
||||||
|
|
||||||
|
- node: assembly
|
||||||
|
entity: AirlockAssembly
|
||||||
|
actions:
|
||||||
|
- !type:SpriteStateChange
|
||||||
|
state: assembly
|
||||||
|
- !type:SnapToGrid {}
|
||||||
|
- !type:SetAnchor {}
|
||||||
|
edges:
|
||||||
|
- to: wired
|
||||||
|
conditions:
|
||||||
|
- !type:EntityAnchored {}
|
||||||
|
steps:
|
||||||
|
- material: Cable
|
||||||
|
amount: 5
|
||||||
|
doAfter: 1
|
||||||
|
- to: start
|
||||||
|
conditions:
|
||||||
|
- !type:EntityAnchored
|
||||||
|
anchored: false
|
||||||
|
completed:
|
||||||
|
- !type:SpawnPrototype
|
||||||
|
prototype: SheetSteel1
|
||||||
|
amount: 4
|
||||||
|
- !type:DeleteEntity {}
|
||||||
|
steps:
|
||||||
|
- tool: Welding
|
||||||
|
doAfter: 2
|
||||||
|
|
||||||
|
- node: wired
|
||||||
|
entity: AirlockAssembly
|
||||||
|
edges:
|
||||||
|
- to: electronics
|
||||||
|
conditions:
|
||||||
|
- !type:EntityAnchored {}
|
||||||
|
steps:
|
||||||
|
- tag: DoorElectronics
|
||||||
|
store: board
|
||||||
|
name: "door electronics circuit board"
|
||||||
|
icon:
|
||||||
|
sprite: "Constructible/Misc/module.rsi"
|
||||||
|
state: "door_electronics"
|
||||||
|
doAfter: 1
|
||||||
|
- to: assembly
|
||||||
|
completed:
|
||||||
|
- !type:SpawnPrototype
|
||||||
|
prototype: ApcExtensionCableStack1
|
||||||
|
amount: 5
|
||||||
|
steps:
|
||||||
|
- tool: Cutting
|
||||||
|
doAfter: 1
|
||||||
|
|
||||||
|
- node: electronics
|
||||||
|
edges:
|
||||||
|
- to: airlock
|
||||||
|
conditions:
|
||||||
|
- !type:EntityAnchored {}
|
||||||
|
steps:
|
||||||
|
- tool: Screwing
|
||||||
|
doAfter: 2
|
||||||
|
|
||||||
|
- node: airlock
|
||||||
|
entity: Airlock
|
||||||
|
edges:
|
||||||
|
- to: wired
|
||||||
|
conditions:
|
||||||
|
- !type:EntityAnchored {}
|
||||||
|
- !type:DoorWelded {}
|
||||||
|
- !type:AirlockBolted
|
||||||
|
value: false
|
||||||
|
- !type:WirePanel {}
|
||||||
|
- !type:ContainerNotEmpty # TODO ShadowCommander: Remove when map gets updated
|
||||||
|
container: board
|
||||||
|
completed:
|
||||||
|
- !type:EmptyAllContainers {}
|
||||||
|
steps:
|
||||||
|
- tool: Prying
|
||||||
|
doAfter: 1
|
||||||
|
- to: wired # TODO ShadowCommander: Remove when board spawning is implemented in ServerDoorComponent.cs. Needs a map update.
|
||||||
|
conditions:
|
||||||
|
- !type:EntityAnchored {}
|
||||||
|
- !type:DoorWelded {}
|
||||||
|
- !type:AirlockBolted
|
||||||
|
value: false
|
||||||
|
- !type:WirePanel {}
|
||||||
|
- !type:ContainerEmpty
|
||||||
|
container: board
|
||||||
|
completed:
|
||||||
|
- !type:SpawnPrototype
|
||||||
|
prototype: DoorElectronics
|
||||||
|
steps:
|
||||||
|
- tool: Prying
|
||||||
|
doAfter: 1
|
||||||
@@ -213,3 +213,20 @@
|
|||||||
canBuildInImpassable: false
|
canBuildInImpassable: false
|
||||||
conditions:
|
conditions:
|
||||||
- !type:TileNotBlocked {}
|
- !type:TileNotBlocked {}
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: Airlock
|
||||||
|
id: airlock
|
||||||
|
graph: airlock
|
||||||
|
startNode: start
|
||||||
|
targetNode: airlock
|
||||||
|
category: Structures
|
||||||
|
description: It opens, it closes, and maybe crushes you.
|
||||||
|
icon:
|
||||||
|
sprite: Constructible/Structures/Doors/Standard/basic.rsi
|
||||||
|
state: assembly
|
||||||
|
objectType: Structure
|
||||||
|
placementMode: SnapgridCenter
|
||||||
|
canBuildInImpassable: false
|
||||||
|
conditions:
|
||||||
|
- !type:TileNotBlocked {}
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: ConveyorAssembly
|
id: ConveyorAssembly
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: DoorElectronics
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: ExplosivePassable
|
id: ExplosivePassable
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user