plugins/game-dev/design/skill-progression-trees/SKILL.md
Use when designing or implementing skill trees, talent trees, ability progression systems, or unlock graphs. Triggers: skill tree, talent tree, ability tree, progression system, unlock, prestige, node, skill points.
npx skillsauth add fcsouza/agent-skills design-skill-progression-treesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
DAG-based progression systems for any game genre — skill trees, talent trees, ability unlocks, passive stat graphs, and prestige layers. Covers data modeling, server-authoritative validation, cost scaling, and respec mechanics.
Trigger: skill tree, talent tree, ability tree, progression system, unlock system, prestige, node graph, skill points, ability unlock, passive tree, talent build, respec, skill reset
game-design-fundamentals — core loop and reward system knowledgepostgres-game-schema — player and currency data modelsgame-economy-design — cost balancing and currency integrationChris Taylor (Supreme Commander): "A good tech tree gives the player the illusion of infinite choice while keeping every path viable." Will Wright (The Sims, Spore): "Emergent systems arise when simple rules interact — skill trees should compose, not prescribe." Jonathan Blow (Braid, The Witness): "Every unlock should feel like a genuine insight, not a checkbox."
cost = baseCost * tier^exponent (typically exponent 1.5-2.0).{ "stat": "attack", "modifier": "+10%" }). Apply server-side. Enables hot reload, A/B testing, and balance patches without deploys.Classify every node: active skills (abilities the player triggers), passive stats (always-on bonuses), unlocks (gates to content or mechanics), prestige (post-endgame reset bonuses).
Use an adjacency list stored in JSONB. Each node has a prerequisites array of node IDs. Validate acyclicity on every admin write.
Create skill_nodes (tree definition) and player_skills (player state) tables. See boilerplate for full implementation.
Endpoint: POST /skills/unlock/:nodeId. Flow: check prerequisites met, check currency available, atomic transaction (deduct currency + insert player_skills + snapshot).
Store unlocked node IDs in Redis per player session. Invalidate on unlock or respec. Tree lookups are frequent — database per-request is too slow.
Endpoint: POST /skills/respec. Flow: deduct respec fee (or check cooldown), delete all player_skills rows, refund skill points to player wallet, invalidate Redis cache.
Admin-only utilities: cycle detection (DFS on prerequisite graph), orphaned node detection (nodes with prerequisites referencing deleted nodes), unreachable node detection.
// skill_nodes — defines the tree structure (admin-managed)
export const skillNodes = pgTable("skill_nodes", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
name: text("name").notNull(),
description: text("description"),
category: text("category").notNull(), // 'active' | 'passive' | 'unlock' | 'prestige'
tier: integer("tier").notNull().default(1),
prerequisites: jsonb("prerequisites").$type<string[]>().default([]),
cost: integer("cost").notNull().default(1),
effects: jsonb("effects").$type<Record<string, unknown>[]>().default([]),
isVisible: boolean("is_visible").notNull().default(true),
metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
});
// player_skills — tracks which nodes each player has unlocked
export const playerSkills = pgTable("player_skills", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
playerId: text("player_id").notNull().references(() => players.id, { onDelete: "cascade" }),
nodeId: text("node_id").notNull().references(() => skillNodes.id),
unlockedAt: timestamp("unlocked_at").notNull().defaultNow(),
snapshot: jsonb("snapshot").$type<Record<string, unknown>>().default({}),
});
| Endpoint | Method | Description |
|----------|--------|-------------|
| /skills/tree | GET | Full tree with player unlock status per node |
| /skills/unlock/:nodeId | POST | Unlock node — validates prerequisites, deducts cost, atomic write |
| /skills/respec | POST | Full reset — deducts fee, deletes player_skills, refunds points |
game-economy-design — cost balancing, currency sinks for skill pointspostgres-game-schema — player and currency table schemasredis-game-patterns — caching unlocked node sets per sessiongame-design-fundamentals — core loop integration and progression pacingChris Taylor (Supreme Commander, Total Annihilation): Tech trees should give players the feeling of building toward something powerful. Every branch should feel like it opens new strategic possibilities. If a player looks at two branches and one is obviously better, the tree has failed.
Will Wright (The Sims, SimCity, Spore): The best progression systems are ones where simple rules interact to create emergent builds. Don't design 50 unique abilities — design 10 composable ones that combine in 50 ways.
Jonathan Blow (Braid, The Witness): Unlocking a skill should feel like understanding something new, not like filling a progress bar. If the player doesn't feel smarter or more capable after an unlock, the node is wasted.
tools
Use when implementing client-server state synchronization, delta compression, optimistic updates, rollback netcode, or real-time game state reconciliation. Triggers: state sync, netcode, delta, rollback, interpolation, prediction.
testing
Use when designing virtual economies, currencies, sink/faucet balance, loot tables, crafting systems, shops, or inflation control. Triggers: economy, currency, sinks, loot, inflation, crafting, shop.
development
Audits existing game code against design principles — checks server-authority, schema conventions, auth security, payment safety, narrative coherence, and MVP scope drift. Extract the optional component name or path from the user's message (defaults to entire src/). Use after building components or before committing.
testing
Designs a single quest end-to-end — coherence check, objective tree, quest brief, and registry entry. Extract the quest name from the user's message. Requires docs/world-lore.md and docs/quest-registry.md.