Merge pull request #4368 from mirrorcult/2021-07-16/windoors

Windoors
This commit is contained in:
ShadowCommander
2021-08-05 23:09:38 -07:00
committed by GitHub
26 changed files with 735 additions and 25 deletions

View File

@@ -17,9 +17,26 @@ namespace Content.Client.Doors
{
private const string AnimationKey = "airlock_animation";
[DataField("animation_time")]
[DataField("animationTime")]
private float _delay = 0.8f;
[DataField("denyAnimationTime")]
private float _denyDelay = 0.3f;
/// <summary>
/// Whether the maintenance panel is animated or stays static.
/// False for windoors.
/// </summary>
[DataField("animatedPanel")]
private bool _animatedPanel = true;
/// <summary>
/// Whether the BaseUnlit layer should still be visible when the airlock
/// is opened.
/// </summary>
[DataField("openUnlitVisible")]
private bool _openUnlitVisible = false;
private Animation CloseAnimation = default!;
private Animation OpenAnimation = default!;
private Animation DenyAnimation = default!;
@@ -38,10 +55,13 @@ namespace Content.Client.Doors
flickUnlit.LayerKey = DoorVisualLayers.BaseUnlit;
flickUnlit.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("closing_unlit", 0f));
var flickMaintenancePanel = new AnimationTrackSpriteFlick();
CloseAnimation.AnimationTracks.Add(flickMaintenancePanel);
flickMaintenancePanel.LayerKey = WiresVisualizer.WiresVisualLayers.MaintenancePanel;
flickMaintenancePanel.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("panel_closing", 0f));
if (_animatedPanel)
{
var flickMaintenancePanel = new AnimationTrackSpriteFlick();
CloseAnimation.AnimationTracks.Add(flickMaintenancePanel);
flickMaintenancePanel.LayerKey = WiresVisualizer.WiresVisualLayers.MaintenancePanel;
flickMaintenancePanel.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("panel_closing", 0f));
}
}
OpenAnimation = new Animation {Length = TimeSpan.FromSeconds(_delay)};
@@ -56,24 +76,21 @@ namespace Content.Client.Doors
flickUnlit.LayerKey = DoorVisualLayers.BaseUnlit;
flickUnlit.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("opening_unlit", 0f));
var flickMaintenancePanel = new AnimationTrackSpriteFlick();
OpenAnimation.AnimationTracks.Add(flickMaintenancePanel);
flickMaintenancePanel.LayerKey = WiresVisualizer.WiresVisualLayers.MaintenancePanel;
flickMaintenancePanel.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("panel_opening", 0f));
var sound = new AnimationTrackPlaySound();
OpenAnimation.AnimationTracks.Add(sound);
if (_animatedPanel)
{
var flickMaintenancePanel = new AnimationTrackSpriteFlick();
OpenAnimation.AnimationTracks.Add(flickMaintenancePanel);
flickMaintenancePanel.LayerKey = WiresVisualizer.WiresVisualLayers.MaintenancePanel;
flickMaintenancePanel.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("panel_opening", 0f));
}
}
DenyAnimation = new Animation {Length = TimeSpan.FromSeconds(0.3f)};
DenyAnimation = new Animation {Length = TimeSpan.FromSeconds(_denyDelay)};
{
var flick = new AnimationTrackSpriteFlick();
DenyAnimation.AnimationTracks.Add(flick);
flick.LayerKey = DoorVisualLayers.BaseUnlit;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("deny_unlit", 0f));
var sound = new AnimationTrackPlaySound();
DenyAnimation.AnimationTracks.Add(sound);
}
}
@@ -108,13 +125,16 @@ namespace Content.Client.Doors
{
case DoorVisualState.Open:
sprite.LayerSetState(DoorVisualLayers.Base, "open");
unlitVisible = false;
unlitVisible = _openUnlitVisible;
if (_openUnlitVisible)
{
sprite.LayerSetState(DoorVisualLayers.BaseUnlit, "open_unlit");
}
break;
case DoorVisualState.Closed:
sprite.LayerSetState(DoorVisualLayers.Base, "closed");
sprite.LayerSetState(DoorVisualLayers.BaseUnlit, "closed_unlit");
sprite.LayerSetState(DoorVisualLayers.BaseBolted, "bolted_unlit");
sprite.LayerSetState(WiresVisualizer.WiresVisualLayers.MaintenancePanel, "panel_open");
break;
case DoorVisualState.Opening:
animPlayer.Play(OpenAnimation, AnimationKey);

View File

@@ -59,6 +59,12 @@ namespace Content.Server.Doors.Components
[DataField("powerWiresTimeout")]
public float PowerWiresTimeout = 5.0f;
/// <summary>
/// Whether the maintenance panel should be visible even if the airlock is opened.
/// </summary>
[DataField("openPanelVisible")]
public bool OpenPanelVisible = false;
private CancellationTokenSource _powerWiresPulsedTimerCancel = new();
private bool _powerWiresPulsed;

View File

@@ -42,7 +42,9 @@ namespace Content.Server.Doors.Systems
// Only show the maintenance panel if the airlock is closed
if (component.WiresComponent != null)
{
component.WiresComponent.IsPanelVisible = args.State != SharedDoorComponent.DoorState.Open;
component.WiresComponent.IsPanelVisible =
component.OpenPanelVisible
|| args.State != SharedDoorComponent.DoorState.Open;
}
// If the door is closed, we should look if the bolt was locked while closing
component.UpdateBoltLightStatus();

Binary file not shown.

View File

@@ -64,7 +64,7 @@
- type: Appearance
visuals:
- type: AirlockVisualizer
animation_time: 0.6
animationTime: 0.6
- type: WiresVisualizer
- type: Wires
BoardName: "Firelock Control"
@@ -113,7 +113,7 @@
fixtures:
- shape:
!type:PhysShapeRect
bounds: "0.49,-0.49,-0.49,-0.2" # don't want this colliding with walls or they won't close
bounds: "-0.2,-0.49,-0.49,0.49" # don't want this colliding with walls or they won't close
mask:
- MobImpassable
layer:

View File

@@ -0,0 +1,76 @@
- type: entity
id: WindoorAssembly
name: windoor assembly
description: It opens, it closes, and you can see through it!
parent: BaseStructure
components:
- type: InteractionOutline
- type: Sprite
netsync: false
drawdepth: FloorObjects
sprite: Structures/Doors/Windoors/windoor.rsi
layers:
- state: assembly
- type: Physics
fixtures:
- shape:
!type:PhysShapeAabb
bounds: "-0.2,-0.49,-0.49,0.49"
mass: 30
mask:
- Impassable
- VaultImpassable
- type: Anchorable
- type: Pullable
- type: Rotatable
- type: Damageable
resistances: metallicResistances
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 300
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel1:
min: 1
max: 3
- type: Construction
graph: windoor
node: assembly
placement:
mode: SnapgridCenter
- type: entity
id: WindoorAssemblySecure
name: secure windoor assembly
description: It opens, it closes, and you can see through it! This one looks tough.
parent: WindoorAssembly
components:
- type: Sprite
netsync: false
drawdepth: Mobs
sprite: Structures/Doors/Windoors/windoor.rsi
layers:
- state: secure_underlay
- state: assembly
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 600
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
SheetPlasteel1:
min: 1
max: 2
- type: Construction
graph: windoor
node: assemblySecure

View File

@@ -0,0 +1,135 @@
- type: entity
id: BaseWindoor
parent: BaseStructure
abstract: true
placement:
mode: SnapgridCenter
components:
- type: InteractionOutline
- type: Physics
fixtures:
- shape:
!type:PhysShapeAabb
bounds: "-0.2,-0.49,-0.49,0.49"
mass: 50
layer:
- Impassable
- MobImpassable
- VaultImpassable
- SmallImpassable
mask:
- VaultImpassable
- type: Sprite
netsync: false
drawdepth: FloorObjects
sprite: Structures/Doors/Windoors/windoor.rsi
layers:
- state: closed
map: ["enum.DoorVisualLayers.Base"]
- state: closed_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseUnlit"]
- state: welded
map: ["enum.DoorVisualLayers.BaseWelded"]
- state: bolted_unlit
shader: unshaded
map: ["enum.DoorVisualLayers.BaseBolted"]
- state: panel_open
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- type: ApcPowerReceiver
- type: Damageable
resistances: glassResistances
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1
max: 2
SheetSteel1:
min: 2
max: 4
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: AccessReader
- type: Airlock
openPanelVisible: true
- type: Door
weldable: false
openSound:
path: /Audio/Machines/windoor_open.ogg
closeSound:
path: /Audio/Machines/windoor_open.ogg
denySound:
path: /Audio/Machines/airlock_deny.ogg
- type: Wires
BoardName: "Windoor Control"
LayoutId: Airlock
- type: UserInterface
interfaces:
- key: enum.WiresUiKey.Key
type: WiresBoundUserInterface
- type: Appearance
visuals:
- type: AirlockVisualizer
animationTime: 0.9
denyAnimationTime: 0.4
animatedPanel: false
openUnlitVisible: true
- type: WiresVisualizer
- type: Construction
graph: windoor
node: windoor
- type: entity
id: BaseSecureWindoor
parent: BaseWindoor
abstract: true
components:
- type: Airtight
fixVacuum: true
noAirWhenFullyAirBlocked: false
airBlockedDirection:
- South
- type: Sprite
netsync: false
drawdepth: FloorObjects
sprite: Structures/Doors/Windoors/windoor.rsi
layers:
- state: secure_underlay
- state: closed
map: [ "enum.DoorVisualLayers.Base" ]
- state: closed_unlit
shader: unshaded
map: [ "enum.DoorVisualLayers.BaseUnlit" ]
- state: welded
map: [ "enum.DoorVisualLayers.BaseWelded" ]
- state: bolted_unlit
shader: unshaded
map: [ "enum.DoorVisualLayers.BaseBolted" ]
- state: panel_open
map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
visible: false
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 400
behaviors:
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1
max: 2
SheetPlasteel1:
min: 1
max: 2
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: Construction
graph: windoor
node: windoorSecure

View File

@@ -0,0 +1,48 @@
- type: entity
id: Windoor
parent: BaseWindoor
name: windoor
description: It's a window and a sliding door. Wow!
- type: entity
id: WindoorSecure
parent: BaseSecureWindoor
name: secure windoor
description: It's a sturdy window and a sliding door. Wow!
# TODO remove these with parameterized prototypes/whatever we end up doing
# Bar windoor
- type: entity
parent: Windoor
id: WindoorBarLocked
suffix: Bar, Locked
components:
- type: AccessReader
access: [["Bar"]]
# Chemistry windoor
- type: entity
parent: WindoorSecure
id: WindoorMedicalLocked
suffix: Medical, Locked
components:
- type: AccessReader
access: [["Medical"]]
# HOP's office windoor
- type: entity
parent: WindoorSecure
id: WindoorCommandLocked
suffix: Command, Locked
components:
- type: AccessReader
access: [["Command"]]
# Cargo windoor
- type: entity
parent: Windoor
id: WindoorCargoLocked
suffix: Cargo, Locked
components:
- type: AccessReader
access: [["Cargo"]]

View File

@@ -0,0 +1,221 @@
- type: constructionGraph
id: windoor
start: start
graph:
- node: start
edges:
- to: assembly
completed:
- !type:SetAnchor
value: false
steps:
- material: Steel
amount: 4
doAfter: 2
- to: assemblySecure
completed:
- !type:SetAnchor
value: false
steps:
- material: Plasteel
amount: 4
doAfter: 2
- node: assembly
entity: WindoorAssembly
actions:
- !type:SnapToGrid {}
- !type:SetAnchor {}
edges:
- to: glass
conditions:
- !type:EntityAnchored {}
steps:
- material: Glass
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: glass
entity: WindoorAssembly
edges:
- to: wired
conditions:
- !type:EntityAnchored { }
steps:
- material: Cable
amount: 5
doAfter: 1
- to: assembly
conditions:
- !type:EntityAnchored
anchored: false
completed:
- !type:SpawnPrototype
prototype: SheetGlass1
amount: 5
- !type:DeleteEntity { }
steps:
- tool: Screwing
doAfter: 2
- node: wired
entity: WindoorAssembly
edges:
- to: electronics
conditions:
- !type:EntityAnchored {}
steps:
- tag: DoorElectronics
store: board
name: "door electronics circuit board"
icon:
sprite: "Objects/Misc/module.rsi"
state: "door_electronics"
doAfter: 1
- to: glass
completed:
- !type:SpawnPrototype
prototype: CableApcStack1
amount: 5
steps:
- tool: Cutting
doAfter: 1
- node: electronics
entity: WindoorAssembly
edges:
- to: windoor
conditions:
- !type:EntityAnchored {}
steps:
- tool: Screwing
doAfter: 2
- node: windoor
entity: Windoor
edges:
- to: wired
conditions:
- !type:EntityAnchored {}
- !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
- node: assemblySecure
entity: WindoorAssemblySecure
actions:
- !type:SnapToGrid { }
- !type:SetAnchor { }
edges:
- to: glassSecure
conditions:
- !type:EntityAnchored { }
steps:
- material: ReinforcedGlass
amount: 5
doAfter: 1
- to: start
conditions:
- !type:EntityAnchored
anchored: false
completed:
- !type:SpawnPrototype
prototype: SheetPlasteel1
amount: 4
- !type:DeleteEntity { }
steps:
- tool: Welding
doAfter: 10
- node: glassSecure
entity: WindoorAssemblySecure
edges:
- to: wiredSecure
conditions:
- !type:EntityAnchored { }
steps:
- material: Cable
amount: 5
doAfter: 1
- to: assemblySecure
conditions:
- !type:EntityAnchored
anchored: false
completed:
- !type:SpawnPrototype
prototype: SheetRGlass1
amount: 5
- !type:DeleteEntity { }
steps:
- tool: Screwing
doAfter: 4
- node: wiredSecure
entity: WindoorAssemblySecure
edges:
- to: electronicsSecure
conditions:
- !type:EntityAnchored { }
steps:
- tag: DoorElectronics
store: board
name: "door electronics circuit board"
icon:
sprite: "Objects/Misc/module.rsi"
state: "door_electronics"
doAfter: 1
- to: glassSecure
completed:
- !type:SpawnPrototype
prototype: CableApcStack1
amount: 5
steps:
- tool: Cutting
doAfter: 3
- node: electronicsSecure
entity: WindoorAssemblySecure
edges:
- to: windoorSecure
conditions:
- !type:EntityAnchored { }
steps:
- tool: Screwing
doAfter: 4
- node: windoorSecure
entity: WindoorSecure
edges:
- to: wired
conditions:
- !type:EntityAnchored {}
- !type:AirlockBolted
value: false
- !type:WirePanel {}
- !type:ContainerNotEmpty # TODO ShadowCommander: Remove when map gets updated
container: board
completed:
- !type:EmptyAllContainers {}
steps:
- tool: Prying
doAfter: 4

View File

@@ -125,7 +125,7 @@
canRotate: false
- type: construction
name: Firelock
name: firelock
id: Firelock
graph: Firelock
startNode: start
@@ -142,7 +142,7 @@
- !type:TileNotBlocked {}
- type: construction
name: Catwalk
name: catwalk
id: Catwalk
graph: Catwalk
startNode: start
@@ -164,7 +164,7 @@
canBuildInImpassable: false
- type: construction
name: Wooden Barricade
name: wooden barricade
id: Barricade
graph: barricade
startNode: start
@@ -181,7 +181,7 @@
- !type:TileNotBlocked {}
- type: construction
name: Airlock
name: airlock
id: airlock
graph: airlock
startNode: start
@@ -196,3 +196,37 @@
canBuildInImpassable: false
conditions:
- !type:TileNotBlocked {}
- type: construction
name: windoor
id: windoor
graph: windoor
startNode: start
targetNode: windoor
category: Structures
description: It opens, it closes, and you can see through it!
icon:
sprite: Structures/Doors/Windoors/windoor.rsi
state: closed
objectType: Structure
placementMode: SnapgridCenter
canBuildInImpassable: false
conditions:
- !type:TileNotBlocked {}
- type: construction
name: secure windoor
id: secureWindoor
graph: windoor
startNode: start
targetNode: windoorSecure
category: Structures
description: It opens, it closes, and you can see through it! This one looks tough.
icon:
sprite: Structures/Doors/Windoors/windoor.rsi
state: closed
objectType: Structure
placementMode: SnapgridCenter
canBuildInImpassable: false
conditions:
- !type:TileNotBlocked {}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

View File

@@ -0,0 +1,168 @@
{
"version":1,
"license":"CC-BY-SA-3.0",
"copyright":"Taken from tgstation at https://github.com/tgstation/tgstation/blob/3681006d7102045e334e8eddb23a8685fcdb258a/icons/obj/doors/windoor.dmi",
"size": {
"x":32,
"y":32
},
"states":[
{
"name":"assembly",
"directions":4,
"delays":[
[
0.3,0.3
],
[
0.3,0.3
],
[
0.3,0.3
],
[
0.3,0.3
]
]
},
{
"name":"closed",
"directions":4
},
{
"name":"closed_unlit",
"directions":4
},
{
"name":"closing",
"directions":4,
"delays":[
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
]
]
},
{
"name":"closing_unlit",
"directions":4,
"delays":[
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1]
]
},
{
"name":"open",
"directions":4
},
{
"name":"open_unlit",
"directions":4
},
{
"name":"opening",
"directions":4,
"delays":[
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
]
]
},
{
"name":"opening_unlit",
"directions":4,
"delays":[
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1,0.1
]
]
},
{
"name":"deny_unlit",
"directions":4,
"delays":[
[
0.1,0.2,0.1
],
[
0.1,0.2,0.1
],
[
0.1,0.2,0.1
],
[
0.1,0.2,0.1
]
]
},
{
"name":"spark",
"directions":4,
"delays":[
[
0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1
],
[
0.1,0.1,0.1,0.1,0.1,0.1
]
]
},
{
"name":"panel_open",
"directions":4
},
{
"name":"bolted_unlit",
"directions":4
},
{
"name":"welded",
"directions":4
},
{
"name":"secure_underlay",
"directions":4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B