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.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -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-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
|
||||
|
||||
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
|
||||
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 {}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
- type: Tag
|
||||
id: ConveyorAssembly
|
||||
|
||||
- type: Tag
|
||||
id: DoorElectronics
|
||||
|
||||
- type: Tag
|
||||
id: ExplosivePassable
|
||||
|
||||
|
||||
Reference in New Issue
Block a user