npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@storyboard-os/rpg-domain

v1.1.0

Published

RPG game-authoring contract — frame types, content fields, templates, validation rules, and demo data for rpg-storyboard.

Downloads

523

Readme


@storyboard-os/rpg-domain

RPG 游戏创作领域包。 包含 RPG 游戏设计师、作者或开发者所需的所有内容,用于设计可执行的任务和场景叙事,包括:框架类型、内容模式、模板、验证规则、画布信号、准备状态模型、交付生成以及项目持久化辅助功能。

目标用户: 正在开发 RPG 电子游戏的,需要设计具有足够深度的游戏流程,以便传递给游戏引擎或进行制作的 游戏设计师或开发者。

不适用于: 桌游准备、游戏主持人工具、虚拟桌面工具、战役笔记或仅用于对话编辑。 验证器会强制执行这一点——包含桌游相关术语的框架将无法通过验证。


安装

npm install @storyboard-os/rpg-domain
# or
pnpm add @storyboard-os/rpg-domain

框架类型

七种类型。 每种类型代表可玩 RPG 任务或场景中的一个特定功能。

| 类型 | 功能 | 建议颜色 | |---|---|---| | hook | 起始点或开放线索——任务的开端或未来发展的线索 | #EAB308 | | scene | 叙事或场景——“在哪里”和“是什么” | #3B82F6 | | choice | 玩家决策点——分支流程,设置状态标志 | #8B5CF6 | | encounter | 战斗、谜题、社交冲突或高风险障碍 | #EF4444 | | reveal | 提供信息、转折、线索或游戏状态解锁 | #F97316 | | npc_beat | 角色互动,包含对话分支逻辑 | #22C55E | | consequence | 世界状态结果——选择或事件发生后,发生了什么变化 | #6B7280 |

validateRpgStoryboard 验证器强制执行的规则:

  • choice(选择)和 consequence(结果)框架必须包含至少一个 stateChanges(状态变化)条目。
  • reveal(揭示)框架必须包含至少一个 entryCondition(进入条件)或 stateChange(状态变化)。
  • 框架内容不得包含桌游相关术语。

内容模式

每个 RPG 框架都包含一个 FrameContent 对象,其中包含实现细节,而不仅仅是故事笔记。

interface FrameContent {
  designerNotes?: string;          // Intent, tone, design rationale — author-facing
  playerVisibleText?: string;      // What the player actually sees or hears
  authorOnlyNotes?: string;        // Spoilers, hidden logic — never shown in-game
  stakes?: string;                 // What is at risk if this beat fails or is skipped
  entryConditions?: string[];      // Game-state flags that must be true before this fires
  exitConditions?: string[];       // What must be true for this beat to resolve
  stateChanges?: string[];         // Flags / variables / world-state this beat sets
  involvedCharacters?: string[];   // Named characters present or referenced
  involvedFactions?: string[];     // Factions with stakes in this beat
  possibleOutcomes?: string[];     // All distinct results this beat can produce
  requiredAssets?: string[];       // Art, audio, props, dialogue, animations needed
  testCriteria?: string[];         // Pass/fail checks that verify correct implementation
  implementationChecklist?: string[]; // Ordered task list for the dev or production pass
}

如果没有 entryConditions(进入条件)、stateChanges(状态变化)、requiredAssets(所需资源)和 testCriteria(测试标准),一个框架就只是一个故事笔记,而不是游戏规范。 模板生成的每个框架都会进行这些检查。


模板

三个 RPG 制作的起始模板。 每个模板生成的框架都包含进入条件、状态变化、所需资源和测试标准。 模板是思考结构,而不是空白的起始点。

import { STORYBOARD_TEMPLATES, createStoryboardFromTemplate } from '@storyboard-os/rpg-domain';

const template = STORYBOARD_TEMPLATES.find(t => t.id === 'quest_flow');
console.log(template.name);       // 'Quest Flow'
console.log(template.frameCount); // 8
console.log(template.bestFor);    // 'First draft of any new quest...'

const storyboard = createStoryboardFromTemplate('quest_flow', {
  id: 'my-quest',
  title: 'The Ruined Tollhouse',
  description: 'Three factions want the same ledger.',
});

任务流程 (quest_flow) — 8 个框架

Opening Hook → Establishing Scene → Character Contact → Key Choice
  → The Obstacle → The Reveal → The Consequence → Future Thread

线性任务,包含一个主要由玩家驱动的分支。 适用于初稿——强制每个环节从一开始就包含状态逻辑。

任务分支 (quest_branch) — 7 个框架

Inciting Situation → Decision Point → [Path A | Path B | Path C]
  → Convergence Point → Fallout Thread

三个不同的路径,具有不同的成本和收益。 适用于玩家决策,旨在创造真正不同的游戏体验,而不是仅仅改变外观。

过场动画片段 (cutscene_beat) — 5 个框架

Establishing Frame → Character Beat → The Revelation
  → Player Response → The Shift

一个精心设计的、保留玩家自主性的戏剧性时刻。 玩家响应框架是强制性的——如果没有它,这个序列就变成了最糟糕的过场动画。


验证

import { validateStoryboard, validateRpgStoryboard } from '@storyboard-os/rpg-domain';

// Structural validation only (from @storyboard-os/core)
const structural = validateStoryboard(storyboard);

// RPG domain rules layered on top
const rpg = validateRpgStoryboard(storyboard);

if (!rpg.valid) {
  rpg.errors.forEach(e => console.error(e.code, e.message, e.frameId));
}

RPG 相关的错误代码包括:CHOICE_MISSING_STATE_CHANGES(选择缺少状态变化)、CONSEQUENCE_MISSING_STATE_CHANGES(结果缺少状态变化)、REVEAL_MISSING_ENTRY_OR_STATE(揭示缺少进入条件或状态变化)以及 TABLETOP_DRIFT_TERM(包含桌游相关术语)。


画布信号

这些函数可以从框架内容中生成显示数据,而无需任何画布或 React 代码。 画布组件负责渲染结果;领域负责计算结果。

import { getFrameSignal, getFrameBadges, getChoiceBranchCount } from '@storyboard-os/rpg-domain';

const signal = getFrameSignal(frame);
signal.stateChangeSummary;     // e.g. "Sets 2 flags"
signal.branchConditionSummary; // e.g. "3 outgoing branches"
signal.readiness;              // 'full' | 'partial' | 'none'
signal.hasStateChanges;        // boolean
signal.specScore;              // 0–4

const badges = getFrameBadges(frame, connections);
// → [{ text: 'STATE', color: '#3B82F6' }, { text: 'SPEC', color: '#22C55E' }]
// Rendered by @storyboard-os/canvas without needing to know what they mean

实现准备状态模型

getBeatStatus 是确定“已准备好”的权威来源。 应用程序会显示结果;领域决定其状态。

import { getBeatStatus, getStoryboardReadiness, BLOCKING_REASONS } from '@storyboard-os/rpg-domain';

const status = getBeatStatus(frame);

status.level;             // 'ready' | 'partial' | 'draft' | 'blocked'
status.missing;           // MissingSpecReason[]
status.assetCount;        // number of requiredAssets entries
status.testCriteriaCount; // number of testCriteria entries
status.checklistCount;    // number of implementationChecklist entries

// Distinguish domain violations (blockers) from spec gaps
const blockers = status.missing.filter(r => BLOCKING_REASONS.has(r));
const gaps     = status.missing.filter(r => !BLOCKING_REASONS.has(r));

状态级别

| 级别 | 含义 | |---|---| | ready | 所有规范部分都已呈现。规范评分 ≥ 3(包括:设计说明、所需资源、测试标准、实施检查清单)。没有违反任何领域规则。 | | partial | 部分规范已呈现,但内容不完整。规范评分 1–2。 | | draft | 没有规范(评分 = 0)。框架结构存在,但缺乏实施细节。 | | blocked | 领域违规:choice/consequence 缺少 stateChanges,或者 reveal 缺少 entryConditionsstateChanges。 |

// Board-level readiness summary
const summary = getStoryboardReadiness(storyboard);
summary.total;         // total frame count
summary.ready;         // frames at 'ready'
summary.partial;       // frames at 'partial'
summary.draft;         // frames at 'draft'
summary.blocked;       // frames at 'blocked'
summary.readyFraction; // ready / total (0–1)
summary.byFrame;       // Map<frameId, BeatStatus>

交付导出

import { generateHandoff, generateMarkdown } from '@storyboard-os/rpg-domain';

// For template preview boards — static storyboard data
const handoff = generateHandoff(storyboard);
const markdown = generateMarkdown(handoff);

流程节点按照拓扑顺序排列,使用 Kahn 算法,即先处理依赖于当前节点的节点,再处理当前节点影响的节点。循环会被检测到,剩余的流程节点会被追加,而不会导致程序崩溃。

每个 HandoffBeat 包含:状态、缺失原因、所有规范字段、所有出站分支(包括类型和标签)、以及所有入站流程节点 ID。交付头信息显示总数、已完成数、部分完成数、草稿数和被阻塞数,以及 blockedBeatIds / partialBeatIds,方便快速评估。


项目领域辅助工具

对于需要长期维护的项目,可以创建项目,分别编辑规范内容和跟踪进度,从而实现独立管理。

import {
  createProject,
  updateFrameBasics,
  updateFrameContent,
  updateFramePosition,
  setChecklistItemComplete,
  setTestCriterionComplete,
  getFrameProgress,
  getProjectProgress,
} from '@storyboard-os/rpg-domain';

// Create a project from a template
const project = createProject({
  title: 'The Ruined Tollhouse',
  description: 'Three factions want the same ledger.',
  sourceTemplateId: 'quest_flow',
});

// All update functions are pure — they return a new project object
const updated = updateFrameBasics(project, 'hook-1', { title: 'The Caravan Arrives' });
const edited  = updateFrameContent(updated, 'hook-1', {
  designerNotes: 'Environmental storytelling — no dialogue in this beat.',
  entryConditions: ['quest_tollhouse_active === true'],
  requiredAssets: ['ruined tollhouse exterior', 'abandoned caravan prop'],
});

// Track progress separately from spec text (spec strings are never modified)
const p1 = setChecklistItemComplete(edited, 'hook-1', 0, true);
const p2 = setTestCriterionComplete(p1, 'hook-1', 0, true);

// Read back progress
const frameProgress = getFrameProgress(p2, 'hook-1');
frameProgress.checklist;    // { "0": true, ... }
frameProgress.testCriteria; // { "0": true, ... }

const summary = getProjectProgress(p2);
summary.totalChecklist; // total checklist items across all frames
summary.doneChecklist;  // completed items
summary.totalTests;     // total test criteria across all frames
summary.doneTests;      // completed criteria

进度不变性: implementationChecklisttestCriteria 规范字符串永远不会被进度函数修改。完成状态独立存储在 project.progress.frames 中。规范可以独立于进度进行编辑,并且可以随时从当前状态重新生成交付文件。

项目交付

import { generateProjectHandoff, generateProjectMarkdown } from '@storyboard-os/rpg-domain';

// For durable projects — includes edited content + progress
const handoff = generateProjectHandoff(project);

handoff.projectId;       // project.id
handoff.title;           // project.title
handoff.sourceTemplateId;
handoff.generatedAt;
handoff.progress;        // ProjectProgressSummary
handoff.beats;           // ProjectHandoffBeat[] — spec + completion arrays

// Each ProjectHandoffBeat extends HandoffBeat with:
// checklistProgress: boolean[]   — one entry per checklist item
// testProgress: boolean[]        — one entry per test criterion

const markdown = generateProjectMarkdown(handoff);
// Produces Markdown with [x]/[ ] per item, project identity header, progress summary

演示任务:The Tollhouse Ledger

这是一个包含 8 个流程节点的完整规范任务。每个流程节点都包含特定的标志名称、资源需求和测试标准,可以作为参考实现或演示示例。

import { tollhouseLedgerProject } from '@storyboard-os/rpg-domain';

const storyboard = tollhouseLedgerProject.storyboard;
console.log(storyboard.frames.length); // 8

const hook = storyboard.frames[0];
hook.content.stateChanges;   // ['Sets: quest_tollhouse_active = true']
hook.content.requiredAssets; // ['Ruined tollhouse exterior environment', ...]
hook.content.testCriteria;   // ['Player can observe the abandoned caravan without dialogue trigger', ...]

场景: 玩家到达一座饱受战争摧残的收费站。三个派系都想要同一本隐藏的账簿。玩家决定谁能得到它,谁会失去它,以及该地区接下来会变成什么样子。包含 8 个流程节点,以及两个结果分支。


信任模型

@storyboard-os/rpg-domain 是一个纯 TypeScript 库。它没有运行时副作用,没有 I/O 操作,没有网络访问,也没有浏览器或 Node.js API。所有函数都接受数据并返回数据。此包不会存储、记录或传输任何数据,持久化是调用应用程序的责任。