Merge branch 'dev_弟子系统' into dev
This commit is contained in:
+124
@@ -0,0 +1,124 @@
|
||||
# 弟子属性设计
|
||||
|
||||
本文件定义弟子(Disciple)的属性体系、境界规则与派生逻辑,是 `src/Data/Models/Disciple.gd` 的实现依据。关联:`doc/弟子管理.md`(模块设计)、`doc/模块联动.md`(联动规范)、`doc/Roadmap.md`(P1 核心循环)。
|
||||
|
||||
## 1. 属性列表(权威定义)
|
||||
|
||||
| 名称 | 范围 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| metal | [0, 100] | 金属性值 |
|
||||
| wood | [0, 100] | 木属性值 |
|
||||
| water | [0, 100] | 水属性值 |
|
||||
| fire | [0, 100] | 火属性值 |
|
||||
| earth | [0, 100] | 土属性值 |
|
||||
| efficiency | [1, 100] | 灵气吸收效率,决定修炼速度,隐藏属性 |
|
||||
| realm_level | [0, 5] | 大境界,凡人、练气、筑基、金丹、元婴、化神 |
|
||||
| sub_realm_level | [1, 13] | 凡人只有一个小境界;练气 13 个小境界,其他各有前、中、后、大圆满四个小境界 |
|
||||
| cultivation_exp | [0, 2147483647] | 修炼经验 |
|
||||
| farming_exp | [0, 2147483647] | 耕作技能经验 |
|
||||
| farming_level | [0, 10] | 耕作技能等级 |
|
||||
| herb_exp | [0, 2147483647] | 药草耕作技能经验 |
|
||||
| herb_level | [0, 10] | 药草耕作技能等级 |
|
||||
| alchemy_exp | [0, 2147483647] | 炼丹技能经验 |
|
||||
| alchemy_level | [0, 10] | 炼丹技能等级 |
|
||||
| loyalty | [0, 100] | 忠诚度 |
|
||||
|
||||
> 字段说明:`id` 只读,由管理器分配;`name` 普通字符串。原设计中的 `is_mortal`、`cultivation_skill`、`alchemy_skill` 单值字段由下述规则取代,不单独存字段。
|
||||
|
||||
## 2. 境界体系
|
||||
|
||||
大境界 `realm_level` 与显示名、小境界 `sub_realm_level` 数量:
|
||||
|
||||
| realm | 名称 | sub 范围 | 小境界显示 |
|
||||
| --- | --- | --- | --- |
|
||||
| 0 | 凡人 | 固定 1 | 凡人 |
|
||||
| 1 | 练气 | 1~13 | 练气X层(1~13 层) |
|
||||
| 2 | 筑基 | 1~4 | 筑基前期 / 中期 / 后期 / 大圆满 |
|
||||
| 3 | 金丹 | 1~4 | 金丹前期 / 中期 / 后期 / 大圆满 |
|
||||
| 4 | 元婴 | 1~4 | 元婴前期 / 中期 / 后期 / 大圆满 |
|
||||
| 5 | 化神 | 1~4 | 化神前期 / 中期 / 后期 / 大圆满 |
|
||||
|
||||
## 3. 灵根(五行推导,不存字段)
|
||||
|
||||
有灵根的凡人才能修炼破境。**任一五行属性 ≥ 阈值(占位 20,待调参)即具灵根**:
|
||||
|
||||
- 有灵根 → 可修炼:凡人期积累修炼经验,满后破境入练气
|
||||
- 无灵根 → 终生为凡,永不涨修炼经验(且大境界 0)
|
||||
|
||||
派生:`has_spiritual_root()`;凡俗判定 `is_mortal() = (realm_level == 0) 且 无灵根`。
|
||||
|
||||
## 4. 经验规则
|
||||
|
||||
### 4.1 修炼经验(cultivation_exp)
|
||||
|
||||
- 每个小境界有经验上限(曲线表配置,见 §5)
|
||||
- **跨小境界**:经验满自动突破 sub+1,溢出部分**继承**到下一个小境界
|
||||
- **跨大境界**:sub 到顶(练气 13 / 其他 4)再满,realm+1 且 sub=1,溢出部分**清零**
|
||||
- 化神大圆满封顶,不再获得修炼经验
|
||||
- 突破自动进行(回合结算时处理),暂不设额外条件
|
||||
|
||||
### 4.2 技能经验(farming / herb_farming / alchemy 三套相同规则)
|
||||
|
||||
- 每跨一级,溢出的经验**继承**到下一级,直到升满(10 级)为止
|
||||
- 满级后继续获得的经验**不再累积**(经验不会提升)
|
||||
- 每个等级所需经验由配置文件给出(曲线表,见 §5)
|
||||
|
||||
### 4.3 效率的作用
|
||||
|
||||
`efficiency` 决定修炼速度(隐藏属性),不直接改变经验上限;具体月收益公式由管理器结算实现,数值待调参。
|
||||
|
||||
## 5. 经验曲线表(放 Disciple.gd 内部 const,占位待调参)
|
||||
|
||||
> 存储决策:曲线表先以常量写在 `Disciple.gd` 内部,自包含易调;静态内容层方案(CSV/Resource)落地后再迁移。
|
||||
|
||||
### 5.1 修炼曲线 CULTIVATION_EXP_CAPS
|
||||
|
||||
键为 `"{realm}_{sub}"`,共 30 条(凡人 1 + 练气 13 + 筑基/金丹/元婴/化神 各 4)。凡人期条目(`0_1`)供有灵根凡人积累经验破境用;化神大圆满(`5_4`)无上限(哨兵)。
|
||||
|
||||
```
|
||||
{"0_1": 100, "1_1": 100, "1_2": 110, ... 占位递增,待调参}
|
||||
```
|
||||
|
||||
### 5.2 技能曲线 SKILL_EXP_CAPS
|
||||
|
||||
10 条,表示 level N → N+1 所需经验(N = 0~9)。三套技能暂共用一张表,将来可拆分。
|
||||
|
||||
```
|
||||
[100, 120, 140, ...] 占位,待调参
|
||||
```
|
||||
|
||||
## 6. 读写与派生接口(数据类 API)
|
||||
|
||||
数值属性读写统一走键名接口(RANGES 为合法键与夹取范围的唯一权威):
|
||||
|
||||
```gdscript
|
||||
func has_attr(key: String) -> bool # key 是否为登记表中的数值属性
|
||||
func get_attr(key: String) -> int # 读数值属性(未知键 push_error 返回 0)
|
||||
func set_attr(key: String, value: int) -> bool # 写数值属性(夹取 + 境界/小境界联动约束)
|
||||
```
|
||||
|
||||
> 说明:`id` 只读语义(由 `create()` 分配),`name` 为字符串不入 RANGES;两者直接字段访问。`total_amount` 为只读属性(实时由五行之和计算)。
|
||||
|
||||
派生只读方法(境界体系相关,实现时见 §2):
|
||||
|
||||
| 方法 | 逻辑 |
|
||||
| --- | --- |
|
||||
| `total_amount`(只读属性) | 五行之和(实时派生) |
|
||||
| `has_spiritual_root() -> bool` | 任一五行 ≥ 灵根阈值 |
|
||||
| `can_cultivate() -> bool` | 有灵根 且 未满级 |
|
||||
| `is_mortal() -> bool` | realm 0 且无灵根 |
|
||||
| `sub_realm_max() -> int` | 当前大境界的小境界上限(查 SUB_MAX_BY_REALM) |
|
||||
| `exp_cap() -> int` | 当前 (realm, sub) 修炼经验上限(查曲线);满级返哨兵 |
|
||||
| `realm_name() -> String` | 完整显示名:凡人 / 练气5层 / 筑基后期 / 化神大圆满 |
|
||||
|
||||
> 状态迁移(突破、升级、经验增减)属领域操作,归 DiscipleManager(见 `doc/弟子管理.md`),数据类只提供纯查询。
|
||||
|
||||
## 7. 夹取与写入约束
|
||||
|
||||
- `RANGES` 常量表为 17 个属性的合法范围唯一权威,`create()` 与管理器 `set_attr()` 共用
|
||||
- 属性全部普通字段(每属性 1 行声明),不带 setter 样板;夹取收口在两处写入口
|
||||
- 直接写字段不夹取,依赖 `doc/弟子管理.md` "修改只走管理器"纪律
|
||||
|
||||
## 8. 变更记录
|
||||
|
||||
- 2026-09-07:确立属性列表、境界体系(0~5 + sub)、灵根五行推导、经验曲线表结构;本文档由与 opencode 的讨论结论整理(本文件前身为占位草稿)
|
||||
+33
@@ -83,3 +83,36 @@ func load_from_dict(d) -> void
|
||||
- `settle_month` → 境界提升/灵石消耗正确
|
||||
- `to_dict / load_from_dict` 往返一致
|
||||
3. `print` 输出 PASS/FAIL,编辑器直接运行场景验证
|
||||
|
||||
# 弟子属性
|
||||
|
||||
## 属性列表
|
||||
|名称|范围|说明|
|
||||
|:---|:---|:---|
|
||||
|metal|[0, 100]|金属性值|
|
||||
|wood|[0, 100]|木属性值|
|
||||
|water|[0, 100]|水属性值|
|
||||
|fire|[0, 100]|火属性值|
|
||||
|earth|[0, 100]|土属性值|
|
||||
|efficiency|[1, 100]|灵气吸收效率,决定修炼速度,隐藏属性|
|
||||
|realm_level|[0, 5]|大境界,凡人、练气、筑基、金丹、元婴、化神|
|
||||
|sub_realm_level|[1, 13]|凡人只有一个小境界;练气13个小境界,其他各有前、中、后、大圆满四个小境界|
|
||||
|cultivation_exp|[0, 2147483647]|修炼经验|
|
||||
|farming_skill_exp|[0, 2147483647]|耕作技能经验|
|
||||
|farming_skill_level|[0, 10]|炼丹技能等级|
|
||||
|herb_farming_skill_exp|[0, 2147483647]|药草耕作技能经验|
|
||||
|herb_farming_skill_level|[0, 10]|炼丹技能等级|
|
||||
|alchemy_skill_exp|[0, 2147483647]|炼丹技能经验|
|
||||
|alchemy_skill_level|[0, 10]|炼丹技能等级|
|
||||
|loyalty|[0, 100]|忠诚度|
|
||||
|
||||
- **修炼经验说明**:每个小境界都有一个经验上限,跨越小境界,溢出部分会继承到下一个小境界。跨越大境界,溢出部分清零。
|
||||
|
||||
- **技能经验说明**:耕作技能经验、药草耕作技能经验、炼丹技能经验,每跨越一个等级,溢出的经验会继承到下一个等级,直到升满为止,不会有任何经验提升。每个等级所需的经验为需要在文件中配置。
|
||||
|
||||
|
||||
## 初始分配方式
|
||||
```mermaid
|
||||
graph TD
|
||||
A[分配属性总量,按正正态分布] --> B[随机分配5种属性,属性之和为1] --> C[分配灵气利用率]
|
||||
```
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
# 模块联动规范
|
||||
|
||||
本文档定义模块间联动逻辑的处理方案:谁调用谁、变更怎么传播、如何保证一致性。联动场景包括「建筑需要弟子才有产出」「炼丹需输入药材→产出丹药」「消耗药材→库存减少」等跨系统交互。
|
||||
|
||||
## 1. 方案组合结论
|
||||
|
||||
| 层 | 选择 | 理由 |
|
||||
| --- | --- | --- |
|
||||
| 主动操作联动(炼丹/交货/种植) | 直接调用 + 依赖注入 | 逻辑显式、可断点调试、单测零成本 |
|
||||
| 回合结算顺序 | 固定管线(MainGame 依次调用) | 消除时间耦合,顺序可预期 |
|
||||
| 状态变更通知(UI/统计/音效) | 信号广播(观察者,单向) | 不引入依赖,加监听者零改动 |
|
||||
| 全局事件总线 / 规则引擎 | 不做,数据形状预留 | P1~P3 联动类型仅个位数,通用引擎成本大于收益 |
|
||||
|
||||
**明确不用的方案**:
|
||||
|
||||
- 不用事件总线处理权威状态变更(如扣库存):请求-响应型联动需要双向信号,代码量反超直接调用,且结算顺序难追踪。事件广播只用于通知,不用于变更。
|
||||
- 不用规则引擎全量执行联动:为 4 类联动(种植收获/炼丹/交货/修炼)写通用执行器是净亏损。P4 功法/术法批量进场(联动类型持续增长)时再评估抽成引擎。
|
||||
|
||||
## 2. 联动场景的本质
|
||||
|
||||
| 场景 | 本质 | 参与方 |
|
||||
| --- | --- | --- |
|
||||
| 建筑需要弟子才有产出 | 前置条件检查(人手占用) | 生产系统 ↔ 弟子系统 |
|
||||
| 炼丹需输入药材→产出丹药 | 资源转换(事务) | 炼丹系统 ↔ 库存系统 |
|
||||
| 消耗药材→库存减少 | 库存变更 + 广播 | 调用方 → 库存 → UI/统计 |
|
||||
|
||||
统一模式:**A 向 B 提需求(检查)→ B 执行变更 → 变更通知所有关心者**。
|
||||
|
||||
## 3. 依赖管理铁律
|
||||
|
||||
### 3.1 依赖图无环(DAG)
|
||||
|
||||
库存、经济是叶子节点,谁也不依赖;生产类依赖库存/弟子;订单依赖库存+经济。**任何 Manager 不得依赖其上层**,出现环即设计错误。
|
||||
|
||||
```
|
||||
OrderManager ──→ InventoryManager(叶子)
|
||||
└──→ EconomyManager(叶子)
|
||||
AlchemyManager ─→ InventoryManager
|
||||
FieldManager ───→ InventoryManager
|
||||
DiscipleManager ─→ EconomyManager(修炼扣灵石)
|
||||
FoodManager ─────→ InventoryManager
|
||||
└─→ DiscipleManager
|
||||
```
|
||||
|
||||
**已知隐患**(P2 启动前必须复查):
|
||||
|
||||
- 忠诚/抽成:弟子抽成 → 经济结算方向仍是 弟子→经济,不构成环;但若经济系统反过来查询弟子(按忠诚发分红)会成环,届时改走信号通知。
|
||||
- 收徒拜师礼:一次性收入走 EconomyManager,同向,无环。
|
||||
|
||||
### 3.2 注入点唯一
|
||||
|
||||
所有 `setup()` 集中在 MainGame 一处,Manager 自身零 autoload 引用(TimeSystem/SaveSystem 除外按需)。这是依赖可管理的根源:
|
||||
|
||||
```gdscript
|
||||
# MainGame._ready() 中:
|
||||
economy_manager.setup()
|
||||
inventory_manager.setup()
|
||||
field_manager.setup(inventory_manager)
|
||||
alchemy_manager.setup(inventory_manager)
|
||||
food_manager.setup(disciple_manager, inventory_manager)
|
||||
order_manager.setup(inventory_manager, economy_manager)
|
||||
disciple_manager.setup(economy_manager)
|
||||
```
|
||||
|
||||
好处:测试场景只注入 Mock 依赖即可单独运行;依赖关系读一遍 MainGame 全貌可见。
|
||||
|
||||
### 3.3 结算顺序管线化
|
||||
|
||||
`month_passed` 固定按序调用各 Manager 的 `settle_month()`,消除时间耦合:
|
||||
|
||||
```
|
||||
灵田(收获入库存) → 炼丹(自动生产) → 弟子(修炼结算)
|
||||
→ 口粮(凡人弟子消耗) → 订单(过期检查) → 经济(固定收入)
|
||||
```
|
||||
|
||||
顺序依据:口粮必须在收获后扣(吃的是新粮);经济最后(汇总本月收支)。新增系统只插入管线,不改变既有顺序。
|
||||
|
||||
## 4. 原子事务约定(check-take-give)
|
||||
|
||||
联动变更必须原子:先检查所有前置条件与材料,全部通过后再执行扣除与产出,**不允许扣一半失败**。
|
||||
|
||||
### 4.1 收敛到库存层
|
||||
|
||||
「先检查后扣除」的手工纪律收敛为库存层的两个方法,调用方不可能写错:
|
||||
|
||||
```gdscript
|
||||
# InventoryManager
|
||||
func try_take(items: Dictionary) -> bool # 全量检查,够则返回 true
|
||||
func take(items: Dictionary) -> void # 实际扣除(try_take 通过后调用)
|
||||
func add_item(item_id: String, count: int) -> void
|
||||
func has_items(items: Dictionary) -> bool # 只查不扣(供 UI 显示可用性)
|
||||
```
|
||||
|
||||
### 4.2 调用方模板
|
||||
|
||||
```gdscript
|
||||
# AlchemyManager.refine() —— 主动操作联动标准写法
|
||||
func refine(recipe_id: String, disciple: Disciple) -> bool:
|
||||
var r: Dictionary = ContentDB.get_recipe(recipe_id)
|
||||
if disciple.alchemy_skill < r["skill_req"]:
|
||||
return false
|
||||
if not inventory.try_take(r["inputs"]):
|
||||
return false
|
||||
inventory.take(r["inputs"])
|
||||
inventory.add_item(r["output_id"], r["output_count"])
|
||||
pill_refined.emit(r["output_id"])
|
||||
return true
|
||||
```
|
||||
|
||||
## 5. 单一写入口
|
||||
|
||||
每种数据只允许其归属 Manager 变更:
|
||||
|
||||
| 数据 | 唯一写入口 | 外部只能 |
|
||||
| --- | --- | --- |
|
||||
| 库存物品 | `InventoryManager.take/add_item` | 调用这两个方法 |
|
||||
| 灵石余额 | `EconomyManager.spend/earn` | 调用这两个方法 |
|
||||
| 弟子属性 | `DiscipleManager.set_attr` | 调用该方法 |
|
||||
| 弟子增删 | `DiscipleManager.add/remove_disciple` | 调用该方法 |
|
||||
|
||||
违反此规则的直接后果:数据被谁改的不可追踪,信号漏发,UI 不同步。
|
||||
|
||||
## 6. 信号分工
|
||||
|
||||
| 信号类型 | 用途 | 方向 |
|
||||
| --- | --- | --- |
|
||||
| Manager 发出的领域信号(`inventory_changed`/`pill_refined`…) | UI 刷新、统计、音效 | 后端 → 前端/其他监听者,单向 |
|
||||
| TimeSystem 的 `month_passed` 等 | 回合结算管线入口 | 已定,不改 |
|
||||
| UI 调用 Manager 公开方法 | 玩家操作 | 前端 → 后端,直接调用不走信号 |
|
||||
|
||||
原则:**信号只通知,不携带状态变更职责**。UI 收到信号后从后端读最新值,不依赖信号参数里的数据(参数仅作提示)。
|
||||
|
||||
## 7. 规则引擎的预留(P4 退路)
|
||||
|
||||
P1 定义配方数据时,形状直接写成 `requires / consumes / produces` 三段(逻辑在代码手写):
|
||||
|
||||
```gdscript
|
||||
{
|
||||
"id": "refine_peiyuan",
|
||||
"requires": [{"type": "disciple_skill", "skill": "alchemy", "min": 3}],
|
||||
"consumes": [{"item": "herb_lingzhi", "count": 2}],
|
||||
"produces": [{"item": "pill_peiyuan", "count": 1}],
|
||||
}
|
||||
```
|
||||
|
||||
将来联动类型膨胀(P4 功法/术法、炼丹失败率、双产出等)时,把各 Manager 手写逻辑抽成通用执行器(检查 requires → 扣 consumes → 给 produces,天然原子),**数据文件一行不用改**。
|
||||
|
||||
评估时机:新增联动类型需要改多个 Manager 的代码时,即考虑抽取。当前(P1)不抽取。
|
||||
|
||||
## 8. 违背规范的常见症状
|
||||
|
||||
| 症状 | 根因 | 对应规范 |
|
||||
| --- | --- | --- |
|
||||
| 库存数量莫名变化 | 绕过 InventoryManager 直接改 | §5 单一写入口 |
|
||||
| 扣了一半材料失败 | 未先 try_take 全量检查 | §4 原子事务 |
|
||||
| 结算结果依赖按钮点击顺序 | 未走固定管线 | §3.3 结算顺序 |
|
||||
| Manager 互相调用成环 | 依赖方向失控 | §3.1 DAG |
|
||||
| 换 UI 后数据不刷新 | 变更未发信号 | §6 信号分工 |
|
||||
Reference in New Issue
Block a user