Rapid Piping Device 2: Atmosia's Revenge#124
Open
rebaserHEAD wants to merge 7 commits into
Open
Conversation
…criminator)
Brings in the funky-station RPD subsystem as the foundation for a coherent
RPD-as-feature port:
- RCDComponent.IsRpd / UseMirrorPrototype fields
- RCDDeconstructableComponent.RpdDeconstructable whitelist
- RCDPrototype.MirrorPrototype (flipped variants) and NoLayers
- RCDSystem deconstruct guards (RPD only chews RPD-whitelisted atmos
hardware; never tiles) and mirror-aware ConstructObject spawn
- RPD entity in tools.yml (parent: BaseItem, size: Huge, back/backStorage
slots, melee Blunt 12)
- RPD/Empty/Recharging variants and 27 construction recipes under
Resources/Prototypes/_Triad/RPD/rpd.yml
- RCDMenu.xaml piping/atmos/pumps/vents/sensors categories + locale
- RCDDeconstructable (rpd: true) added to gas pipes
- RPD seeded in the atmospherics locker fill
Adapted to Triad's no-CachedPrototype pattern (RCDSystem reads ProtoId via
_protoManager.Index directly). HeatPump and GasTemperatureGate omitted
because the upstream atmos prototypes aren't in this fork yet. Funky's
fractional cost: 0.5 rounded to 1; RPD maxCharges set to 45 to preserve
effective build count.
Color picker UI and quadrant-based pipe-layer placement land in the next
two commits. Sources: funky-station PRs Triad-Sector#62, #1244, #1289, #1338, #1345,
#1458, plus Monolith PR #3930 for distribution patterns.
Wraps the existing RCDMenu radial with a 13-color palette strip (waste, distro, air, mix, plus the basic primary/secondary palette). Selecting a color sends RCDColorChangeMessage to the server-side RCDSystem, which stores it on the per-tool RCDComponent.PipeColor. On ConstructObject the chosen color is applied to the spawned entity via PipeColorVisuals.Color so newly-built pipes inherit the operator's color choice. "default" leaves pipes unpainted. Adds: - RPDMenu / RPDMenu.xaml.cs / RPDMenuBoundUserInterface in Content.Client - RCDColorChangeMessage + RpdUiKey in Content.Shared/RCD/RCDEvents.cs - RCDComponent.PipeColor tuple field - OnColorChange handler + appearance application in RCDSystem - RPD entity now opens via RpdUiKey + RPDMenuBoundUserInterface (was RcdUiKey) Source: funky-station PR #1244.
Adds the cursor-quadrant-picks-layer UX from funky-station PR #1338.
Holding an RPD on a layer-capable recipe switches the placement ghost to
AlignRPDAtmosPipeLayers, which:
- Draws three guide circles (Primary/Secondary/Tertiary) on the cursor
tile so the operator can see which layer they're about to commit to.
- Computes the target layer from the cursor's offset inside the tile:
near-center → Primary, NE quadrant → Secondary, SW quadrant → Tertiary
(mirrored when the grid is rotated). The math accounts for grid
rotation and player eye rotation.
- Updates the placement ghost prototype via
SharedAtmosPipeLayersSystem.TryGetAlternativePrototype so the preview
matches what will spawn.
- Pushes the client eye rotation to the server via RPDEyeRotationEvent
because eye rotation isn't networked natively. Server reproduces the
same layer pick when the placement commits.
NoLayers-flagged prototypes (vents, scrubbers, alarms) skip the placement
mode swap entirely and place via the standard AlignRCDConstruction.
Adds:
- RCDComponent.LastKnownEyeRotation field
- RPDEyeRotationEvent in Content.Shared/RCD/RCDEvents.cs
- OnRPDEyeRotationEvent handler in RCDSystem
- Cursor-quadrant layer math in OnAfterInteract
- TryGetAlternativePrototype hook in ConstructObject spawn
- AlignRPDAtmosPipeLayers placement mode (Content.Client/RCD)
- RCDConstructionGhostSystem now picks per-tool placement mode
Source: funky-station PR #1338.
Adds the client-side flip key binding that activates the RCDComponent.UseMirrorPrototype state plumbed in earlier. Pressing EditorFlipObject (default R) while holding an RCD/RPD on a recipe with a MirrorPrototype defined toggles the variant, rebuilds the placement ghost with the flipped prototype, and mirrors the state to the server via RCDConstructionGhostFlipEvent so the next ConstructObject spawns the right entity. Recipes without a MirrorPrototype no-op. In practice this is the gas filter / gas mixer flip toggle ports already use upstream — placement was previously stuck on the non-mirrored variants because the field existed but had no input binding. Source: funky-station RPD subsystem (PR #1244).
Drops the `IsRpd: bool` discriminator and replaces the IsRpd branches in RCDSystem with three by-ref extensibility events (RCDDeconstructAttempt, RCDObjectSpawnAttempt, RCDObjectSpawned). RPDSystem subscribes to them plus AfterInteractEvent and contributes RPD-specific behavior without RCDSystem knowing it exists. Per-entity state (PipeColor, CurrentLayer, LastKnownEyeRotation) moves onto the new RPDComponent, closing the multi-user race where AlignRPDAtmosPipeLayers's _currentLayer was static on the client system. New shared module Content.Shared/RPD/ holds the component/system plus RPDLayerMath (single source of truth for cursor-quadrant -> AtmosPipeLayer math, called from both the client placement preview and the server spawn), RPDPalette (server-validated color palette), and RPDEvents. Client-side RPD files move from Content.Client/RCD/ to Content.Client/RPD/.
- ManifoldGas recipe sprite now points at manifold.rsi (its own RSI in this fork; Funky/upstream had it under pipe.rsi/pipeManifold). - RPD entity sprite gets `state: icon` so the picker shows the actual tool sprite instead of a blank cell. - Clothing slots changed from Back/BackStorage (Funky enum) to Back/SuitStorage (this fork's SlotFlags); equipped-BACKSTORAGE.png renamed to equipped-SUITSTORAGE.png and meta.json updated. - Replaces all 30 pre-rendered single-frame PNGs under Textures/Interface/Radial/RPD/ with code-driven Frame0 extracts from the actual entity RSIs. Recipe-spoke icons already used Frame0; the top-level category buttons in RCDMenu.xaml have their TextureRect children built in code (ApplyRPDCategoryIcons) for the same reason — XAML's TexturePath would render a multi-direction sprite sheet. Sprite swaps in the atmos hardware now propagate to the picker automatically. - Adds rpd-component-deconstruct-target-invalid locale string.
Two bugs that together caused every pipe placement to land on the Primary layer regardless of cursor position: 1. RPDSystem.OnAfterInteract bailed at `if (args.Handled)` because RCDSystem's handler ran first and set args.Handled = true after queueing the DoAfter. CurrentLayer stayed at its default (Primary), so RCDObjectSpawnAttemptEvent always picked the Primary variant. Subscribing with `before: typeof(RCDSystem)` lets us commit CurrentLayer onto the RPDComponent before RCDSystem captures the click; the DoAfter then completes against the right layer. 2. Server-side mouseDiff was `location.Position - tileCenter - (0.5, 0.5)`, biasing the cursor offset toward the SW quadrant by half a tile. Client-side AlignRPDAtmosPipeLayers.AlignPlacementMode used the correct `raw - tileCenter` formula. Drop the spurious offset so the server math matches the ghost.
Contributor
Author
|
Oh I guess I should add it to vending machines or something and give it an actual price. Whoops! Thanks arbitrage checker! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.





About the PR
Ports the Rapid Piping Device (RPD) from funky-station and generalizes a few RCD systems along the way:
RPDLayerMath.PickLayerso they can't disagree.PipeColorVisuals. The wire payload carries only the palette key — the server re-derives the color so a misbehaving client can't desync the (key, color) pair.MirrorPrototype(gas filter, mixer, future asymmetric airlocks) can be flipped before placement.RCDDeconstructAttemptEvent,RCDObjectSpawnAttemptEvent,RCDObjectSpawnedEventlet sibling systems gate deconstruction, rewrite the spawn prototype, and decorate freshly spawned entities withoutRCDSystemknowing about them. RPDSystem hangs off these.RCDDeconstructable { rpd: true, deconstructable: false }. RPDs can chew them; plain RCDs bounce (same behavior as before the PR, since these prototypes had noRCDDeconstructableat all).Why / Balance
What if Atmos was actually tolerable and dare I say fun? Now I don't have to accidentally ignite myself in the plasma tank trying to get my steel back after a botched pipe placement.
Also because ricky said "IsRCD" is bad, so I did this instead.
Media
Requirements
How to test
RPDand a stack of compressed matter. Load it.RCD. Confirm it cannot deconstruct any of the atmos targets in step 5 (popup: "not on the whitelist").Breaking changes
RCDDeconstructableComponent.RpdDeconstructable— new field, defaultsfalse. Existing prototypes are unaffected.RCDPrototype.MirrorPrototypeandNoLayers— new fields, optional. Existing recipes are unaffected.RCDComponent.UseMirrorPrototype— new networked field, defaultsfalse.Content.Shared.RPD.*namespaces, newRPDComponent/RPDSystem. Additive only.RCDSystem:RCDDeconstructAttemptEvent,RCDObjectSpawnAttemptEvent,RCDObjectSpawnedEvent. Additive; existing RCD consumers are unaffected.Changelog
🆑