mcpField
D
design-skill-progression-trees

design-skill-progression-trees

github.com/fcsouzaDevelopment2462 installsUpdated 1w ago
Repository

About design-skill-progression-trees

A design guide for game developers building skill and progression systems as directed acyclic graphs. It covers server-side unlock validation, cost scaling, respecs, and data-driven node effects.

Key features

  1. 01Model prerequisites as a DAG
  2. 02Validate unlocks server-side
  3. 03Plan progressive cost curves
  4. 04Design respec mechanics
  5. 05Store effects as JSONB data
  6. 06Check cycles and unreachable nodes

Use cases

  1. 01Design skill or talent unlock graphs
  2. 02Implement validated player unlock APIs
  3. 03Plan respec fees and refunds
  4. 04Find structural issues in progression graphs

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/fcsouza/agent-skills --skill design-skill-progression-trees

After installing, type/design-skill-progression-treesin Claude Code to confirm it loaded.

Bundled filesboilerplate/skill-tree.tstemplates/skill-tree-template.md

Details

From the project README

Skill & Progression Trees

Purpose

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.

When to Use

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

Prerequisites

  • game-design-fundamentals — core loop and reward system knowledge
  • postgres-game-schema — player and currency data models
  • game-economy-design — cost balancing and currency integration

Core Principles

Chris 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."

  1. DAG not tree — prerequisites form a directed acyclic graph; cycles break validation, break rollback, break everything. Enforce acyclicity at admin write time.
  2. Server-authoritative unlock validation — never trust client unlock requests. Validate prerequisites, currency, and cooldowns server-side before writing.
  3. Prerequisite snapshot for rollback — store the full prerequisite state at unlock time. If a respec or patch changes the graph, you can audit what was valid when the player unlocked it.
  4. Cost scaling follows exponential curve — flat costs make endgame nodes trivially cheap relative to player income. Use cost = baseCost * tier^exponent (typically exponent 1.5-2.0).
  5. Respec is player-friendly — always provide a reset mechanism. Free with cooldown, or paid with soft currency. Never lock players into permanent bad choices.
  6. Effects are data, not code — store effects as JSONB ({ "stat": "attack", "modifier": "+10%" }). Apply server-side. Enables hot reload, A/B testing, and balance patches without deploys.
  7. Progressive reveal — don't show all nodes at once. Reveal nodes as prerequisites are met. Reduces overwhelm and creates discovery moments (Jonathan Blow).

Step-by-Step Instructions

1. Define Node Categories

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).

2. Model the DAG

Use an adjacency list stored in JSONB. Each node has a prerequisites array of node IDs. Validate acyclicity on every admin write.

3. Write Drizzle Schema

Create skill_nodes (tree definition) and player_skills (player state) tables. See boilerplate for full implementation.

4. Implement Unlock API

Endpoint: POST /skills/unlock/:nodeId. Flow: check prerequisites met, check currency available, atomic transaction (deduct currency + insert player_skills + snapshot).

5. Cache Unlocked Nodes

Store unlocked node IDs in Redis per player session. Invalidate on unlock or respec. Tree lookups are frequent — database per-request is too slow.

6. Add Respec Endpoint

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.

7. Add Tree Health Checks

Admin-only utilities: cycle detection (DFS on prerequisite graph), orphaned node detection (nodes with prerequisites referencing deleted nodes), unreachable node detection.

Drizzle Schema

// 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({}),
});

API Patterns

EndpointMethodDescription
/skills/treeGETFull tree with player unlock status per node
/skills/unlock/:nodeIdPOSTUnlock node — validates prerequisites, deducts cost, atomic write
/skills/respecPOSTFull reset — deducts fee, deletes player_skills, refunds points

Cross-References

  • game-economy-design — cost balancing, currency sinks for skill points
  • postgres-game-schema — player and currency table schemas
  • redis-game-patterns — caching unlocked node sets per session
  • game-design-fundamentals — core loop integration and progression pacing

Pitfalls & Anti-Patterns

  • "Client-side tree state" — storing unlock state in the client; trivially hackable, desync guaranteed
  • "No respec mechanic" — players who make bad choices quit; always provide a reset path
  • "Flat cost curves" — every node costs the same; endgame nodes become trivially cheap as income scales
  • "Missing cycle detection" — one circular prerequisite creates infinite loops in validation; enforce DAG at write time
  • "Hardcoded effects" — effects baked into code instead of JSONB data; every balance change requires a deploy
  • "All nodes visible" — showing the entire tree upfront overwhelms new players and spoils discovery

Designer Philosophy

Chris 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.

Sources

  • "Designing Tech Trees and Progression Systems" — GDC 2016, Chris Taylor
  • "The Art of Game Design" — Jesse Schell, Chapters on Skill and Chance
  • "Balancing Ability Systems in Multiplayer Games" — GDC 2019
  • "Emergent Gameplay from Simple Systems" — Will Wright, GDC Classic
  • "Player Agency in Progression Design" — GDC 2020

Comments

Markdown supported