feat: add age-based event gating, event timer, and UI polish
- Add minAge/maxAge to events so infants can't go treasure hunting - Cache event panel DOM to prevent high-speed button destruction - Add 10s auto-select countdown for choice events - Fix event title/text field mapping (name/description → title/text) - Add rotating clock icon for time flow feedback - Fix speed/pause button active states - Fix shop affordability check (disable + show insufficient money) - Add red styling for unmet choice requirements - Fix log re-rendering on every tick
This commit is contained in:
@@ -0,0 +1,496 @@
|
||||
# 轮回录 - 配置驱动重构设计文档
|
||||
|
||||
## 目标
|
||||
|
||||
将《轮回录》从硬编码内容重构为**纯配置驱动框架**。
|
||||
- `engine/` 中零游戏内容字符串,全部从 `config/*.json` 加载
|
||||
- 职业系统改为**网状并行非转职**结构
|
||||
- 外族入侵从进度条改为**年龄触发剧情事件**
|
||||
- 新增银两经济 + 系统商铺(3 Tab)
|
||||
- 前几世不可能破局,通过多轮积累解锁后期内容
|
||||
|
||||
---
|
||||
|
||||
## 一、目录结构
|
||||
|
||||
```
|
||||
rebirth-incremental/
|
||||
├── index.html
|
||||
├── src/
|
||||
│ ├── main.js # 入口:加载配置 → 初始化引擎 → 启动
|
||||
│ ├── engine/ # 纯框架,零硬编码内容
|
||||
│ │ ├── state.js # 状态管理 + 序列化
|
||||
│ │ ├── tickLoop.js # 游戏主循环(speed控制、每日结算)
|
||||
│ │ ├── conditionEvaluator.js # 统一条件解析器(所有系统共用)
|
||||
│ │ ├── effectApplier.js # 统一效果执行器(所有系统共用)
|
||||
│ │ ├── careerEngine.js # 职业网引擎(解锁判定、经验计算、收入结算)
|
||||
│ │ ├── eventEngine.js # 事件引擎(触发判定、选择处理)
|
||||
│ │ ├── shopEngine.js # 商铺引擎(购买、生效、重置逻辑)
|
||||
│ │ ├── moneySystem.js # 银两系统(收入、支出、余额)
|
||||
│ │ ├── invasionEngine.js # 外族入侵引擎(年龄触发、破局判定)
|
||||
│ │ └── deathEngine.js # 死亡与重生引擎
|
||||
│ ├── config/ # 所有内容JSON
|
||||
│ │ ├── careers.json # 职业定义(含解锁条件、收入、经验曲线)
|
||||
│ │ ├── events.json # 普通事件 + 入侵事件
|
||||
│ │ ├── shop.json # 物品 + Buff + 神器
|
||||
│ │ ├── identities.json # 开局身份
|
||||
│ │ └── talents.json # 词条
|
||||
│ └── ui/
|
||||
│ ├── renderer.js # 主渲染调度
|
||||
│ └── components/ # UI组件(后续拆分)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、状态结构(state.js)
|
||||
|
||||
```javascript
|
||||
state = {
|
||||
// 时间
|
||||
day: 0,
|
||||
year: 0,
|
||||
age: 0,
|
||||
reincarnation: 0,
|
||||
|
||||
// 玩家基础
|
||||
alive: true,
|
||||
identity: null, // 开局身份ID
|
||||
stats: {
|
||||
body: 0, // 体质
|
||||
wisdom: 0, // 悟性
|
||||
charm: 0, // 魅力
|
||||
destiny: 0, // 天命
|
||||
business: 0, // 经商
|
||||
intelligence: 0 // 智力
|
||||
},
|
||||
talents: [], // 本轮抽到的词条ID数组
|
||||
|
||||
// 职业网(并行,每个职业独立等级)
|
||||
careers: {
|
||||
// "student": { level: 150, exp: 1234 }
|
||||
},
|
||||
|
||||
// 经济
|
||||
money: 0,
|
||||
|
||||
// 商铺(本轮有效)
|
||||
shopItems: {}, // { itemId: quantity }
|
||||
activeBuffs: {}, // { buffId: { expiresDay } }
|
||||
|
||||
// 神器(跨轮永久)
|
||||
artifacts: {}, // { artifactId: level }
|
||||
|
||||
// 世界状态
|
||||
worldFlags: {},
|
||||
npcs: {},
|
||||
|
||||
// 入侵状态
|
||||
invasionsTriggered: {
|
||||
military_40: false,
|
||||
spiritual_45: false,
|
||||
political_50: false,
|
||||
final_60: false
|
||||
},
|
||||
breakthroughRoute: null, // 'general' | 'minister' | 'immortal' | null
|
||||
|
||||
// 运行状态
|
||||
speed: 0,
|
||||
paused: false,
|
||||
logs: [],
|
||||
triggeredEvents: new Set(),
|
||||
|
||||
// 跨轮永久积累
|
||||
metaExp: {}, // { careerId: amount }
|
||||
memories: [],
|
||||
unlockedEntries: new Set(),
|
||||
history: [],
|
||||
unlockedShopPool: new Set(), // 已解锁的商铺物品资格(永久)
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、6属性加成系统
|
||||
|
||||
每点属性提供 **1%** 对应加成,**上限100%**(即属性最多生效到100点)。
|
||||
|
||||
| 属性 | 加成目标 |
|
||||
|------|---------|
|
||||
| 体质(body) | 军事/武将类职业经验获取 |
|
||||
| 悟性(wisdom) | 修仙/书生类职业经验获取 |
|
||||
| 魅力(charm) | 江湖/社交类职业经验获取 |
|
||||
| 天命(destiny) | 事件收益/随机暴击概率 |
|
||||
| 经商(business) | 银两收入 |
|
||||
| 智力(intelligence) | 政治/策略类职业经验获取 |
|
||||
|
||||
**计算公式:**
|
||||
```
|
||||
加成倍率 = 1 + min(属性值, 100) * 0.01
|
||||
|
||||
职业经验 = 基础每日经验 * (1 + 对应属性 * 0.01) * 元经验倍率 * 其他倍率
|
||||
银两收入 = 基础收入 * (1 + 经商 * 0.01) * 其他倍率
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、职业系统
|
||||
|
||||
### 4.1 核心规则
|
||||
|
||||
- **并行非转职**:所有已解锁职业同时存在,各自独立等级,不是替换关系
|
||||
- **解锁驱动**:满足条件后新职业加入可练池,旧职业继续升级
|
||||
- **收入/支出**:每日tick时所有已解锁职业的收入求和(负数为支出)
|
||||
- **经验曲线**:`needExp = base * factor^level`,无硬上限,等级可无限升
|
||||
- **属性加成**:职业JSON中标记`type`,对应属性提供经验加成
|
||||
|
||||
### 4.2 careers.json 格式
|
||||
|
||||
```json
|
||||
{
|
||||
"careers": [
|
||||
{
|
||||
"id": "student",
|
||||
"name": "学童",
|
||||
"type": "scholar",
|
||||
"unlockConditions": [
|
||||
{ "type": "age", "op": ">=", "value": 6 }
|
||||
],
|
||||
"dailyIncome": 1,
|
||||
"expCurve": { "base": 10, "factor": 1.15 }
|
||||
},
|
||||
{
|
||||
"id": "book_boy",
|
||||
"name": "书童",
|
||||
"type": "scholar",
|
||||
"unlockConditions": [
|
||||
{ "type": "careerLevel", "careerId": "student", "op": ">=", "value": 100 }
|
||||
],
|
||||
"dailyIncome": 2,
|
||||
"expCurve": { "base": 50, "factor": 1.2 }
|
||||
},
|
||||
{
|
||||
"id": "scholar",
|
||||
"name": "书生",
|
||||
"type": "scholar",
|
||||
"unlockConditions": [
|
||||
{ "type": "careerLevel", "careerId": "student", "op": ">=", "value": 250 },
|
||||
{ "type": "age", "op": ">=", "value": 14 }
|
||||
],
|
||||
"dailyIncome": -3,
|
||||
"expCurve": { "base": 100, "factor": 1.25 }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 职业type与属性映射
|
||||
|
||||
| type | 对应属性 |
|
||||
|------|---------|
|
||||
| military | 体质 |
|
||||
| scholar | 悟性 |
|
||||
| jianghu | 魅力 |
|
||||
| political | 智力 |
|
||||
| immortal | 悟性 |
|
||||
| business | 经商 |
|
||||
|
||||
---
|
||||
|
||||
## 五、系统商铺(3 Tab)
|
||||
|
||||
### 5.1 设计原则
|
||||
|
||||
| Tab | 是否重置 | 说明 |
|
||||
|-----|---------|------|
|
||||
| 物品 | 每轮清零 | 属性增强、解锁职业资格(如道碟)、消耗品 |
|
||||
| Buff | 每轮清零 | 属性加成、经验倍率加成,限时或永久(本轮) |
|
||||
| 神器 | 跨轮永久 | 属性+特殊效果,可用银两升级,需解锁资格后才能升级 |
|
||||
|
||||
### 5.2 shop.json 格式
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "taoist_license",
|
||||
"name": "道碟",
|
||||
"tab": "item",
|
||||
"cost": 500,
|
||||
"unlockConditions": [
|
||||
{ "type": "age", "op": ">=", "value": 10 },
|
||||
{ "type": "or", "conditions": [
|
||||
{ "type": "identity", "value": "taoist_orphan" },
|
||||
{ "type": "worldFlag", "flag": "met_taoist_priest", "value": true }
|
||||
]}
|
||||
],
|
||||
"effects": [
|
||||
{ "type": "unlockCareer", "careerId": "taoist_priest" },
|
||||
{ "type": "setFlag", "flag": "has_taoist_license", "value": true }
|
||||
],
|
||||
"resetOnRebirth": true
|
||||
}
|
||||
],
|
||||
"buffs": [
|
||||
{
|
||||
"id": "clever_brush",
|
||||
"name": "妙笔生花",
|
||||
"tab": "buff",
|
||||
"cost": 200,
|
||||
"unlockConditions": [],
|
||||
"effects": [
|
||||
{ "type": "addStat", "stat": "wisdom", "value": 5 }
|
||||
],
|
||||
"resetOnRebirth": true
|
||||
}
|
||||
],
|
||||
"artifacts": [
|
||||
{
|
||||
"id": "immortal_sword",
|
||||
"name": "仙剑",
|
||||
"tab": "artifact",
|
||||
"baseCost": 1000,
|
||||
"costGrowth": 1.5,
|
||||
"unlockConditions": [
|
||||
{ "type": "careerLevel", "careerId": "sword_immortal", "op": ">=", "value": 100 }
|
||||
],
|
||||
"effects": [
|
||||
{ "type": "addStat", "stat": "body", "value": 10 },
|
||||
{ "type": "multiplyExp", "careerType": "immortal", "value": 1.2 }
|
||||
],
|
||||
"resetOnRebirth": false,
|
||||
"maxLevel": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 神器升级公式
|
||||
|
||||
```
|
||||
升级所需银两 = baseCost * costGrowth^(当前等级)
|
||||
|
||||
例:baseCost=1000, costGrowth=1.5
|
||||
1→2级:1000
|
||||
2→3级:1500
|
||||
3→4级:2250
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、统一条件与效果系统
|
||||
|
||||
### 6.1 条件格式(conditionEvaluator.js)
|
||||
|
||||
所有条件统一JSON格式,引擎提供 `evaluateCondition(condition, state)` → boolean。
|
||||
|
||||
```json
|
||||
// 基础条件
|
||||
{ "type": "age", "op": ">=", "value": 14 }
|
||||
{ "type": "careerLevel", "careerId": "student", "op": ">=", "value": 100 }
|
||||
{ "type": "stat", "stat": "wisdom", "op": ">=", "value": 20 }
|
||||
{ "type": "money", "op": ">=", "value": 500 }
|
||||
{ "type": "hasItem", "itemId": "taoist_license" }
|
||||
{ "type": "identity", "value": "taoist_orphan" }
|
||||
{ "type": "worldFlag", "flag": "met_taoist", "value": true }
|
||||
{ "type": "reincarnation", "op": ">=", "value": 3 }
|
||||
{ "type": "hasArtifact", "artifactId": "immortal_sword", "op": ">=", "value": 3 }
|
||||
|
||||
// 组合条件
|
||||
{ "type": "and", "conditions": [...] }
|
||||
{ "type": "or", "conditions": [...] }
|
||||
{ "type": "not", "condition": {...} }
|
||||
```
|
||||
|
||||
### 6.2 效果格式(effectApplier.js)
|
||||
|
||||
所有效果统一JSON格式,引擎提供 `applyEffect(effect, state)` → 修改state。
|
||||
|
||||
```json
|
||||
{ "type": "addMoney", "value": 100 }
|
||||
{ "type": "addExp", "careerId": "student", "value": 10 }
|
||||
{ "type": "addStat", "stat": "wisdom", "value": 5 }
|
||||
{ "type": "setFlag", "flag": "x", "value": true }
|
||||
{ "type": "unlockCareer", "careerId": "taoist_priest" }
|
||||
{ "type": "addItem", "itemId": "taoist_license" }
|
||||
{ "type": "addBuff", "buffId": "clever_brush", "duration": -1 }
|
||||
{ "type": "upgradeArtifact", "artifactId": "immortal_sword" }
|
||||
{ "type": "addLog", "text": "...", "logType": "major" }
|
||||
{ "type": "die", "reason": "..." }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、事件系统
|
||||
|
||||
### 7.1 事件分类
|
||||
|
||||
| 类型 | 触发方式 | 说明 |
|
||||
|------|---------|------|
|
||||
| random | 权重随机池 | 普通日常事件,按密度触发 |
|
||||
| age | 到达指定年龄 | 入侵事件、关键剧情 |
|
||||
| flag | 世界Flag变化 | 连锁剧情 |
|
||||
|
||||
### 7.2 events.json 格式
|
||||
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"id": "daily_training",
|
||||
"trigger": { "type": "random", "pool": "normal", "weight": 100 },
|
||||
"text": "你进行了日常训练...",
|
||||
"effects": [
|
||||
{ "type": "addExp", "careerId": "student", "value": 5 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "invasion_military_40",
|
||||
"trigger": { "type": "age", "value": 40 },
|
||||
"isChoice": true,
|
||||
"title": "蛮族入侵",
|
||||
"text": "北方蛮族大举南下...",
|
||||
"choices": [
|
||||
{
|
||||
"text": "组织乡勇抵抗",
|
||||
"requirements": [
|
||||
{ "type": "careerLevel", "careerId": "soldier", "op": ">=", "value": 50 }
|
||||
],
|
||||
"effects": [
|
||||
{ "type": "setFlag", "flag": "invasion_military_resisted", "value": true },
|
||||
{ "type": "unlockCareer", "careerId": "general" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "逃往南方",
|
||||
"effects": [
|
||||
{ "type": "addStat", "stat": "body", "value": -2 }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、外族入侵与破局系统
|
||||
|
||||
### 8.1 入侵事件时间表
|
||||
|
||||
| 年龄 | 事件 | 入侵类型 |
|
||||
|------|------|---------|
|
||||
| 40岁 | 第一次入侵 | 军事(蛮族) |
|
||||
| 45岁 | 第二次入侵 | 精神(天魔) |
|
||||
| 50岁 | 第三次入侵 | 政治(王朝崩坏) |
|
||||
| 60岁 | 最终危机 | 三相汇聚,必须破局 |
|
||||
|
||||
### 8.2 破局路线
|
||||
|
||||
破局路线是极后期的职业系统,需要多世积累才能达到解锁条件:
|
||||
|
||||
| 破局路线 | 前置条件示例 | 对应入侵 |
|
||||
|---------|------------|---------|
|
||||
| 将军破局 | 士兵职业500级 + 体质>80 + 神器"虎符"Lv5 | 军事 |
|
||||
| 宰相破局 | 政治职业500级 + 智力>80 + 神器"玉玺"Lv5 | 政治 |
|
||||
| 修仙破局 | 修仙职业500级 + 悟性>80 + 神器"飞剑"Lv5 | 精神 |
|
||||
|
||||
**前几世不可能破局**——即使运气极好,属性和职业等级也远远不够。
|
||||
|
||||
---
|
||||
|
||||
## 九、游戏循环(每tick)
|
||||
|
||||
```
|
||||
for each day:
|
||||
1. 年龄增长检查(day % 365 === 0)
|
||||
2. 银两结算(所有已解锁职业的 dailyIncome 求和 * 经商加成)
|
||||
3. 职业经验结算(所有已解锁职业的每日经验 * 对应属性加成 * 元经验倍率)
|
||||
4. 检查职业解锁(遍历careers.json,条件满足则加入state.careers)
|
||||
5. 检查年龄触发事件(40/45/50/60岁入侵,只触发一次)
|
||||
6. 随机事件触发(按密度池抽取)
|
||||
7. 检查死亡条件(年龄、属性、入侵后果)
|
||||
8. 渲染UI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、前几世节奏设计
|
||||
|
||||
| 轮次 | 目标 | 解锁内容 |
|
||||
|------|------|---------|
|
||||
| 第1世 | 熟悉系统,解锁基础职业,赚少量银两买小Buff | 学童、农夫等 |
|
||||
| 第2世 | 词条/记忆开局+属性,解锁中级职业,买第一件神器 | 书童、猎户等 |
|
||||
| 第3世 | 神器等级提升,属性更高,解锁高级职业 | 书生、侠客等 |
|
||||
| 第4世+ | 接近破局门槛,尝试解锁破局职业 | 将军、宰相、修仙 |
|
||||
|
||||
---
|
||||
|
||||
## 十一、存档与跨轮继承
|
||||
|
||||
### 11.1 每轮重置
|
||||
- 年龄、天数、银两、世界Flag、NPC关系
|
||||
- 已购买的物品和Buff
|
||||
- 职业等级(但元经验保留,下轮加速)
|
||||
|
||||
### 11.2 跨轮永久保留
|
||||
- 元经验(metaExp)
|
||||
- 记忆(memories)
|
||||
- 已解锁词条池(unlockedEntries)
|
||||
- 神器及等级(artifacts)
|
||||
- 历史记录(history)
|
||||
- 解锁的商铺资格(unlockedShopPool)
|
||||
|
||||
---
|
||||
|
||||
## 十二、UI 面板
|
||||
|
||||
| 面板 | 内容 |
|
||||
|------|------|
|
||||
| 顶部信息 | 第N世、年月日、年龄、银两、6属性值 |
|
||||
| 入侵进度 | 三次入侵触发状态、破局路线 |
|
||||
| 控制按钮 | 速度、暂停、存档、读档 |
|
||||
| 事件面板 | 当前事件标题、文本、倒计时、选择按钮 |
|
||||
| 商铺面板 | 3 Tab(物品/Buff/神器),显示解锁状态和价格 |
|
||||
| 职业面板 | 所有已解锁职业列表,显示等级、经验条、每日收入 |
|
||||
| 日志流 | 事件记录 |
|
||||
| 词条面板 | 本轮抽到的词条 |
|
||||
| 神器面板 | 已拥有神器及等级 |
|
||||
| 死亡结算 | 死亡原因、本轮成就、新解锁内容、历史对比 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、实现优先级
|
||||
|
||||
1. **Phase 1:框架搭建**
|
||||
- 新建目录结构
|
||||
- 实现 `conditionEvaluator.js` + `effectApplier.js`
|
||||
- 实现 `state.js` + 序列化
|
||||
- 实现 `tickLoop.js`
|
||||
|
||||
2. **Phase 2:职业网 + 经济**
|
||||
- 实现 `careerEngine.js` + `moneySystem.js`
|
||||
- 编写 `careers.json` 框架(少量示例职业)
|
||||
|
||||
3. **Phase 3:事件系统**
|
||||
- 实现 `eventEngine.js`
|
||||
- 编写 `events.json` 框架
|
||||
|
||||
4. **Phase 4:商铺系统**
|
||||
- 实现 `shopEngine.js`
|
||||
- 编写 `shop.json` 框架(3 Tab示例)
|
||||
|
||||
5. **Phase 5:入侵与破局**
|
||||
- 实现 `invasionEngine.js`
|
||||
- 编写入侵事件JSON
|
||||
|
||||
6. **Phase 6:死亡重生 + 跨轮继承**
|
||||
- 实现 `deathEngine.js`
|
||||
- 完成跨轮状态过滤
|
||||
|
||||
7. **Phase 7:UI**
|
||||
- 重写 `renderer.js`
|
||||
- 新增商铺面板、神器面板
|
||||
|
||||
8. **Phase 8:内容填充**
|
||||
- 大量编写JSON内容(职业、事件、商铺、身份、词条)
|
||||
Reference in New Issue
Block a user