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:
ShadowCommander
2021-03-17 05:07:49 -07:00
committed by GitHub
parent 0c0c66ff6f
commit 51178b9ae7
10 changed files with 301 additions and 12 deletions

View 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;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks;
#nullable enable
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Doors;
using Content.Shared.Construction;
using JetBrains.Annotations;
@@ -14,29 +15,30 @@ namespace Content.Server.Construction.Conditions
[DataDefinition]
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)
{
if (!entity.TryGetComponent(out ServerDoorComponent? doorComponent)) return false;
return doorComponent.IsWeldedShut == Welded;
}
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;
}
if (!doorComponent.IsWeldedShut || Welded) return false;
message.AddMarkup(Loc.GetString("First, unweld the door.\n"));
return true;
return false;
}
}
}

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using System;
using System.Linq;
using System.Threading;
@@ -31,6 +31,8 @@ using Robust.Shared.Physics.Collision;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using Timer = Robust.Shared.Timing.Timer;
using Content.Server.GameObjects.Components.Construction;
using Robust.Shared.Containers;
namespace Content.Server.GameObjects.Components.Doors
{
@@ -42,6 +44,10 @@ namespace Content.Server.GameObjects.Components.Doors
[ComponentDependency]
private readonly IDoorCheck? _doorCheck = null;
[ViewVariables]
[DataField("board")]
private string? _boardPrototype;
public override DoorState State
{
get => base.State;
@@ -164,6 +170,8 @@ namespace Content.Server.GameObjects.Components.Doors
}
SetAppearance(DoorVisualState.Welded);
}
CreateDoorElectronicsBoard();
}
public override void OnRemove()
@@ -185,6 +193,8 @@ namespace Content.Server.GameObjects.Components.Doors
}
QuickOpen();
}
CreateDoorElectronicsBoard();
}
void IActivate.Activate(ActivateEventArgs eventArgs)
@@ -638,6 +648,39 @@ namespace Content.Server.GameObjects.Components.Doors
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)
{
return new DoorComponentState(State, StateChangeStartTime, CurrentlyCrushing, GameTiming.CurTime);

View 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}.

View File

@@ -24,6 +24,7 @@
- state: panel_open
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: Physics
mass: 100
fixtures:
- shape:
!type:PhysShapeAabb
@@ -37,6 +38,7 @@
- VaultImpassable
- SmallImpassable
- type: Door
board: DoorElectronics
- type: Airlock
- type: Appearance
visuals:
@@ -68,8 +70,58 @@
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Construction
graph: airlock
node: airlock
- type: IconSmooth
key: walls
mode: NoSprite
placement:
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

View File

@@ -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

View File

@@ -79,6 +79,10 @@
- coillv-10
- coillv-20
- coillv-30
- type: Material
materials:
- key: enum.MaterialKeys.Stack
mat: Cable
- type: entity
parent: ApcExtensionCableStack
@@ -90,7 +94,6 @@
- type: Item
size: 3
- type: Stack
stackType: ApcExtensionCableStack1
count: 1
- type: entity

View 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

View File

@@ -213,3 +213,20 @@
canBuildInImpassable: false
conditions:
- !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 {}

View File

@@ -4,6 +4,9 @@
- type: Tag
id: ConveyorAssembly
- type: Tag
id: DoorElectronics
- type: Tag
id: ExplosivePassable