From game-dev
Designs DAG-based skill trees, talent trees, ability progression systems, and unlock graphs for games. Includes server validation, cost scaling, respec mechanics, and Postgres modeling.
npx claudepluginhub fcsouza/agent-skills --plugin standalone-skillsThis skill uses the workspace's default tool permissions.
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.
Designs game progression systems covering XP curves, skill trees, loot progression, prestige mechanics, battle passes, and meta-progression. Activates on mentions of level up, XP curve, skill tree, etc.
Designs long-term and short-term player progression systems for growth, goals, and retention without complexity. Use when adding unlocks, levels, upgrades, or improving motivation.
Provides game design principles covering core loops, GDD structure, difficulty balancing, player psychology, and progression systems. Useful for prototyping engaging gameplay mechanics.
Share bugs, ideas, or general feedback.
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.