feat: audit phase 6 (T4) — node allocation, the Path of Exile payoff
The site borrowed PoE's visual language — passive-tree layout, plasma connections, an RPG stats panel — without any of its mechanic. Nodes were purely decorative. This is the interaction the concept was promising. - New utils/allocation.ts: path-to-root walking, allocate/deallocate, edge state, and URL encode/decode. Pure, 17 unit tests. - Allocation is path-connected like the game: allocating a leaf brings its whole path, and deallocating a node removes its descendants so nothing is ever orphaned. pathToRoot is cycle-safe, and a test asserts every real node reaches the origin. - New pixi/allocation.ts: the path reads as "lit" by dimming everything else rather than brightening the selection — the tree is already near its brightness ceiling, so recession is the only headroom. Nodes dim via alpha (nothing tweens it after the entrance); connections dim via tint, because their alpha is driven by the permanent plasma pulse and writing to it would fight the animation every frame. - Shareable via ?build=. Encoded as node ids, not indices: a bitset would be shorter, but any edit to data.ts would silently re-point every previously shared link at the wrong nodes. Decoding re-derives each path, so a hand-edited or partially-stale link can't produce a broken build, and unknown ids are dropped rather than throwing. - Allocation hangs off a button in the modal rather than the node click, which already opens that modal. BuildBar shows the count with share/reset; share falls back to rewriting the address bar when the clipboard is blocked. Two bugs found while verifying: - Both deep links (?build and ?tour) had ended up nested inside the first-visit coach-hint setTimeout, so a shared link did nothing at all for a returning visitor and waited out the whole intro for everyone else — backwards, since a shared link is precisely the cold-arrival case. Hoisted to run immediately, unconditionally. A ?tour link now also skips the intro. - A restored ?build= was wiped by the entrance, which tweens every node's alpha to 1 after the deep link applies. The result was a full-brightness tree with a counter claiming 4 allocated. Now re-applied once the entrance finishes. Verified in the production build: allocating TypeScript lights origin -> Skills -> Languages -> TypeScript and dims the rest; the counter reads 4; the generated link restores exactly that state on a cold load; Reset clears it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
aa1cda8245
commit
85086e31b2
6 files changed
+448
-10
No files matched your search
@@ -0,0 +1,40 @@
|
||||
// Visual treatment for allocated nodes.
|
||||
//
|
||||
// The path reads as "lit" by dimming everything else rather than brightening
|
||||
// the selection — the tree is already near its brightness ceiling, so
|
||||
// recession is the only headroom available.
|
||||
import { isEdgeAllocated } from '$lib/utils/allocation';
|
||||
import type { SkillTreeController } from './controller';
|
||||
|
||||
/** Alpha for nodes outside the current build. */
|
||||
const DIMMED_NODE_ALPHA = 0.22;
|
||||
/** Tint applied to connections outside the current build. */
|
||||
const DIMMED_LINE_TINT = 0x2a2a35;
|
||||
|
||||
/**
|
||||
* Apply (or clear) allocation styling.
|
||||
*
|
||||
* Nodes are dimmed via `alpha`, which nothing tweens after the entrance
|
||||
* finishes. Connections are dimmed via `tint` instead — their alpha is driven
|
||||
* by the permanent plasma-beam pulse, so writing to it here would fight the
|
||||
* animation every frame.
|
||||
*/
|
||||
export function updateAllocation(ctrl: SkillTreeController, allocated: ReadonlySet<string>) {
|
||||
const active = allocated.size > 0;
|
||||
|
||||
for (const obj of ctrl.nodeObjects) {
|
||||
const lit = !active || allocated.has(obj.node.id);
|
||||
const alpha = lit ? 1 : DIMMED_NODE_ALPHA;
|
||||
obj.graphics.alpha = alpha;
|
||||
obj.glowGraphics.alpha = lit ? 1 : DIMMED_NODE_ALPHA * 0.5;
|
||||
if (obj.label) obj.label.alpha = alpha;
|
||||
}
|
||||
|
||||
for (const line of ctrl.lineObjects) {
|
||||
const lit = !active || isEdgeAllocated(allocated, line.node);
|
||||
const tint = lit ? 0xffffff : DIMMED_LINE_TINT;
|
||||
line.graphics.tint = tint;
|
||||
line.glowGraphics.tint = tint;
|
||||
line.plasmaBeam.tint = tint;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user