From 34a5e8d7dd10f6bf5396c88f7d15f83d83db9a75 Mon Sep 17 00:00:00 2001 From: rebaserHEAD Date: Thu, 21 May 2026 23:02:27 -0400 Subject: [PATCH 1/6] Allow shutters to be rotated at placement ShuttersFrame had `noRot: true` on its Transform, which made Robust silently drop the placement rotation when the construction frame was spawned. Since the construction graph copies LocalRotation forward to each subsequent node, the finished shutter always ended up at the default facing regardless of how the player rotated the ghost. Commenting out `noRot: true` lets the frame keep its placement angle, which then propagates to the completed shutter. --- .../Prototypes/Entities/Structures/Doors/Shutter/shutters.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml b/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml index 890fb2ee66c..e3f61c4cd42 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml @@ -244,4 +244,4 @@ layer: - HighImpassable - type: Transform - noRot: true + # noRot: true # Triad - removed so shutter frames keep their placement rotation From a706bcc50f7eb64340342ef7fcdfd62672f28a1d Mon Sep 17 00:00:00 2001 From: rebaserHEAD Date: Thu, 21 May 2026 23:37:00 -0400 Subject: [PATCH 2/6] Anchor shutter frame on creation so it can't drift off-tile The Shutters construction graph's frame1 node had no actions, so the freshly-spawned ShuttersFrame - an unanchored Dynamic body inherited from BaseStructureDynamic - was never anchored. When a shutter was built on an impassable tile (e.g. over a window, which the recipe allows via canBuildInImpassable), physics ejected the loose frame off the tile during the first construction step. The BlastDoor graph already does this correctly: its frame1 node runs SnapToGrid + SetAnchor actions on creation. Mirror that on the Shutters graph so the frame is snapped and anchored the moment it spawns. --- .../Recipes/Construction/Graphs/structures/shutter.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/shutter.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/shutter.yml index 7086216cba3..511f9beb8af 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/shutter.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/shutter.yml @@ -15,6 +15,12 @@ - node: frame1 entity: ShuttersFrame + # Triad - snap and anchor the frame on creation so the unanchored dynamic body + # isn't shoved off impassable tiles (e.g. windows) by physics. Matches the BlastDoor graph. + actions: + - !type:SnapToGrid {} + - !type:SetAnchor {} + # End Triad edges: - to: frame2 conditions: From 619d4a5947b4a424f75b868f21eeff923d4abf4d Mon Sep 17 00:00:00 2001 From: rebaserHEAD Date: Thu, 21 May 2026 23:53:31 -0400 Subject: [PATCH 3/6] Let shutters be built and used on window tiles Interaction reach checks raycast from the user to the target and treat any anchored entity in the way as an obstruction. A reinforced window sharing the shutter's tile blocked that ray, so construction steps (e.g. adding cables to the frame) and later interactions silently failed when a shutter was built over a window. The engine already solves this for windows and firelocks with a WallMount component, whose only effect is to exempt intersecting anchored entities from interaction obstruction checks. BaseFirelock uses `arc: 360` for exactly this reason ("interact despite grilles"). Add the same WallMount (arc 360) to BaseShutter and ShuttersFrame so the whole construction lifecycle - frame, cable step, and finished shutter - is reachable when a window or grille shares the tile. --- .../Entities/Structures/Doors/Shutter/shutters.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml b/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml index e3f61c4cd42..2edaba9ce1f 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml @@ -101,6 +101,10 @@ interactSuccessSound: collection: FenceRattle - type: BlockWeather + # Triad - lets the shutter be interacted with even when a window/grille shares its tile (matches BaseFirelock) + - type: WallMount + arc: 360 + # End Triad # Mono - type: ShipRepairable repairTime: 3 @@ -218,6 +222,10 @@ containers: - board - type: InteractionOutline + # Triad - lets the frame be interacted with (cable step, etc.) even when a window/grille shares its tile + - type: WallMount + arc: 360 + # End Triad - type: Damageable damageContainer: StructuralInorganic damageModifierSet: Metallic From ba4d77cad68699a346ef0e442e7e08c7b3591de9 Mon Sep 17 00:00:00 2001 From: rebaserHEAD Date: Fri, 22 May 2026 00:02:55 -0400 Subject: [PATCH 4/6] Apply rotation and window fixes to blast door frames Bring BlastDoorFrame and BlastDoorXenoFrame in line with the shutter fixes: - Remove `noRot: true` so the frame keeps its placement rotation, which then propagates to the finished blast door. - Add WallMount (arc 360) so construction steps and interactions work when a window or grille shares the frame's tile. No anchor fix is needed here: the BlastDoor construction graph's frame1 node already runs SnapToGrid + SetAnchor on creation, and both frames are static bodies, so neither drifts. --- .../Entities/Structures/Doors/Shutter/blast_door.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml b/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml index 7d387782c9e..01ea95d6ce5 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml @@ -87,6 +87,10 @@ sprite: Structures/Doors/Shutters/blastdoor.rsi state: assembly - type: InteractionOutline + # Triad - lets the frame be interacted with (cable step, etc.) even when a window/grille shares its tile + - type: WallMount + arc: 360 + # End Triad - type: Damageable damageContainer: StructuralInorganic damageModifierSet: StructuralMetallicStrong @@ -113,7 +117,7 @@ layer: - HighImpassable - type: Transform - noRot: true + # noRot: true # Triad - removed so blast door frames keep their placement rotation - type: Construction graph: BlastDoor node: frame1 @@ -172,6 +176,10 @@ sprite: Structures/Doors/Shutters/xeno_blastdoor.rsi state: assembly - type: InteractionOutline + # Triad - lets the frame be interacted with (cable step, etc.) even when a window/grille shares its tile + - type: WallMount + arc: 360 + # End Triad - type: Damageable damageContainer: StructuralInorganic damageModifierSet: StructuralMetallicStrong @@ -198,7 +206,7 @@ layer: - HighImpassable - type: Transform - noRot: true + # noRot: true # Triad - removed so blast door frames keep their placement rotation - type: Construction graph: BlastDoor node: frame1 From 7a3691f1f14b86333308edd39183543cb0295127 Mon Sep 17 00:00:00 2001 From: rebaserHEAD Date: Sat, 23 May 2026 20:58:01 -0400 Subject: [PATCH 5/6] Declare ShuttersFrame Static to match runtime anchoring The Shutters construction graph's frame1 node now runs SetAnchor on ComponentStartup (a706bcc), which flips Transform.Anchored to true and the Physics body from Dynamic to Static. PrototypeSaveTest diffs the spawned Physics component against the prototype yaml (Transform is skipped, Physics is not), so the Dynamic -> Static delta failed CI. Mirror BlastDoorFrame and declare bodyType: Static on the prototype. Prototype and runtime now agree, and the static body also prevents the unanchored frame from being shoved off impassable tiles. --- .../Entities/Structures/Doors/Shutter/shutters.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml b/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml index 2edaba9ce1f..7b0b28b2183 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml @@ -237,8 +237,11 @@ behaviors: - !type:DoActsBehavior acts: ["Destruction"] + # Triad - Static (matches BlastDoorFrame): the construction graph anchors the frame on spawn, + # which would flip Dynamic -> Static and fail PrototypeSaveTest. Declaring Static here keeps + # prototype/runtime in sync and also prevents the unanchored body from being shoved by physics. - type: Physics - bodyType: Dynamic + bodyType: Static - type: Fixtures fixtures: fix1: From 8ef6083ffc4595bbfb2d48bb1b46f4bd6bbbf770 Mon Sep 17 00:00:00 2001 From: rebaserHEAD Date: Sun, 24 May 2026 11:04:54 -0400 Subject: [PATCH 6/6] Revert "Apply rotation and window fixes to blast door frames" This reverts commit ba4d77cad68699a346ef0e442e7e08c7b3591de9. --- .../Entities/Structures/Doors/Shutter/blast_door.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml b/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml index 01ea95d6ce5..7d387782c9e 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Shutter/blast_door.yml @@ -87,10 +87,6 @@ sprite: Structures/Doors/Shutters/blastdoor.rsi state: assembly - type: InteractionOutline - # Triad - lets the frame be interacted with (cable step, etc.) even when a window/grille shares its tile - - type: WallMount - arc: 360 - # End Triad - type: Damageable damageContainer: StructuralInorganic damageModifierSet: StructuralMetallicStrong @@ -117,7 +113,7 @@ layer: - HighImpassable - type: Transform - # noRot: true # Triad - removed so blast door frames keep their placement rotation + noRot: true - type: Construction graph: BlastDoor node: frame1 @@ -176,10 +172,6 @@ sprite: Structures/Doors/Shutters/xeno_blastdoor.rsi state: assembly - type: InteractionOutline - # Triad - lets the frame be interacted with (cable step, etc.) even when a window/grille shares its tile - - type: WallMount - arc: 360 - # End Triad - type: Damageable damageContainer: StructuralInorganic damageModifierSet: StructuralMetallicStrong @@ -206,7 +198,7 @@ layer: - HighImpassable - type: Transform - # noRot: true # Triad - removed so blast door frames keep their placement rotation + noRot: true - type: Construction graph: BlastDoor node: frame1