feat: Disciple 增加入宗时间快照,D4 名录 UI 设计文档

This commit is contained in:
2026-08-06 22:49:29 +08:00
parent cb9b73dd76
commit 03c765ced8
3 changed files with 107 additions and 6 deletions
+93 -5
View File
@@ -1,7 +1,7 @@
# 弟子系统设计(D3:生成 + 入宗分流)
# 弟子系统设计(D3:生成 + 入宗分流 / D4:名录 UI
> 对应开发计划表 D3(8/5)。本文档只描述设计,不包含代码。
> 状态:设计稿,待审阅通过后实现
> 对应开发计划表 D38/5与 D48/6。本文档只描述设计,不包含代码。
> 状态:D3 已实现;D4 设计稿,待审阅通过后实现
---
@@ -17,6 +17,9 @@
| `aptitude` | 枚举 Aptitude | 资质(入宗分流结果) |
| `roots` | 枚举数组 SpiritRoot | 灵根列表(普通弟子 1~3 根,互不重复) |
| `is_heavenly` | bool | 天灵根标记(稀有灵根,见枚举二) |
| `join_year` | int | 入宗年份(0 = 未入宗/候选),accept 时快照 GameState |
| `join_month` | int | 入宗月份 |
| `join_day` | int | 入宗日 |
| `realm_index` | int | 大境界索引(0=练气),D5 修炼系统推进 |
| `sub_realm_index` | int | 小境界索引(练气层数-1),D5 修炼系统推进 |
@@ -57,6 +60,12 @@
境界的成长、突破门槛、寿元计算全部留给 D5 修炼循环,D3 只负责初始状态。
### 入宗时间字段说明
- `join_year/month/day` 在**入宗瞬间**accept_applicant)快照 GameState 当前日期
- 候选池弟子不设(0),拒绝入宗不产生记录
- 本期只存不消费;入门天数换算(D5 修炼结算)、按入宗排序(列表)、资历事件(W8)后续使用
---
## 二、生成规则(随机性)
@@ -173,7 +182,7 @@ aptitude_weights=[60, 30, 8, 2]
- 每个候选一行:姓名/年龄/资质(天灵根标记)/灵根/境界 + "入宗"勾选框
- 底部:全部接受 / 全部拒绝 / 确定
- 开局模式确定按钮在选满 3 名前禁用;确定后关闭弹窗并恢复时间
- 名录的可视化列表属于 D4弟子列表 UI,届时由 `disciples_changed` 信号驱动
- 名录的可视化列表见**第七节(D4 弟子名录 UI**
---
@@ -188,7 +197,86 @@ aptitude_weights=[60, 30, 8, 2]
---
## 七、验收清单(D3 交付标准
## 七、弟子名录 UID4
> 对应开发计划表 D4(8/6):① 列表条目场景 ② 姓名/资质/境界显示 ③ 点击详情。交付标准:列表可浏览弟子。
### 1. 入口
- TopBar 顶部栏"**管理**"按钮(Button_StaffManagement,当前无功能)→ 打开弟子名录面板
- 打开面板**不暂停时间**(浏览操作,不打断挂机节奏;招募弹窗优先级更高,弹出时覆盖其上)
### 2. 面板结构(两层弹窗,复用青绿仙侠配色)
**第一层:名录列表面板(DisciplesPanel**
| 元素 | 说明 |
|------|------|
| 标题 | "弟子名录(N 人)"N = 当前名录人数 |
| 列表区 | ScrollContainer 动态条目,一个弟子一行,按入宗顺序 |
| 条目内容 | 姓名 / 资质(含天灵根标记)/ 灵根 / 境界 + "详情"按钮 |
| 空状态 | 名录为空时显示"暂无弟子"提示 |
| 底部 | "关闭"按钮(也可点遮罩关闭) |
**第二层:弟子详情弹窗(DiscipleDetailPanel**
| 元素 | 说明 |
|------|------|
| 标题 | 弟子姓名 + 天灵根标记 |
| 信息区 | 静态展示:资质 / 年龄 / 灵根 / 境界 / 编号 / **入宗时间** |
| 预留区 | 修炼进度、属性面板等 D5+ 扩展位置(本期留白) |
| 底部 | "关闭"按钮 |
### 3. 数据驱动
- 面板监听 `DiscipleManager.disciples_changed` → 重建列表
- 打开面板时也主动刷新一次(保证与名录同步)
- 条目与弟子数据一一对应:动态生成时把 Disciple 引用绑定到条目上,点"详情"直接取用
### 4. 文件与场景结构
```
src/UI/Panels/DisciplesPanel/
├── DisciplesPanel.tscn # 名录列表弹窗
├── disciples_panel.gd
├── DiscipleDetailPanel.tscn # 弟子详情弹窗
└── disciple_detail_panel.gd
```
- 两个弹窗都挂在 MainGame 下(默认隐藏),详情弹窗作为列表面板的子层(显示时盖在列表之上)
- 条目在代码中动态生成(与 RecruitPanel 同套路),不单独做条目场景(D4 拆解的"列表条目场景"用动态行实现即可)
- TopBar"管理"按钮在 `top_bar_hud.gd` 接线,调 `DisciplesPanel.show_panel()`
### 5. 交互细节
- 详情弹窗从列表面板打开;关闭详情回到列表;关闭列表回到游戏
- 列表浏览期间名录变化(如定期招募入宗)→ 列表实时刷新
- 资质文字可用颜色区分(天骄金色、上品亮青),其余默认——视觉提示,本期可选
---
## 八、验收清单(D4 交付标准)
- [ ] 点顶部"管理"按钮弹出弟子名录面板,显示当前已入宗弟子
- [ ] 列表每行显示:姓名 / 资质(天灵根有标记)/ 灵根 / 境界
- [ ] 名录为空时显示"暂无弟子";招募入宗后列表实时刷新
- [ ] 点条目"详情"弹出详情弹窗,显示姓名/资质/年龄/灵根/境界/编号
- [ ] 关闭详情回到列表,关闭列表回到游戏,无报错
- [ ] 面板打开期间时间照常推进(不暂停)
---
## 九、与后续任务衔接(D4 补充)
| 后续任务 | 衔接方式 |
|----------|----------|
| D5 修炼循环 | 详情弹窗预留区填充:修为进度、突破按钮、寿元 |
| D6 建筑/职能系统 | 列表条目可扩展"职位/职能"列 |
| D8 存档接入 | 名录数据来源不变,仅序列化方式接入 |
---
## 十、验收清单(D3 交付标准)
- [ ] 项目能正常启动,无脚本报错
- [ ] **开局**:进入游戏即暂停,弹出"弟子入宗(开局招募)",显示 5 名候选
+9
View File
@@ -23,6 +23,9 @@ var age: int = 0
var aptitude: Aptitude = Aptitude.ORDINARY
var roots: Array[SpiritRoot] = [] # 普通弟子 1~3 根;天灵根固定 1 根
var is_heavenly: bool = false # 天灵根标记(3% 概率)
var join_year: int = 0 # 入宗年份(0 = 未入宗/候选),accept 时快照
var join_month: int = 0 # 入宗月份
var join_day: int = 0 # 入宗日
var realm_index: int = 0 # 大境界索引(0=练气)
var sub_realm_index: int = 0 # 小境界索引(练气层数-1
@@ -40,3 +43,9 @@ func get_realm_text() -> String:
if realm_index == 0:
return "%s%d" % [REALM_NAMES[realm_index], sub_realm_index + 1]
return "%s%s" % [REALM_NAMES[realm_index], ["初期", "中期", "后期", "圆满"][sub_realm_index]]
## 入宗时间文本,如 "1年2月3日";未入宗返回空串。
func get_join_date_text() -> String:
if join_year <= 0:
return ""
return "%d%d%d" % [join_year, join_month, join_day]
+5 -1
View File
@@ -22,6 +22,7 @@ const SURNAMES: Array[String] = [
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
]
## 名用字池(修仙风)。
@@ -65,7 +66,7 @@ func generate_applicants(count: int, is_opening := false) -> void:
applicants.append(_create_applicant())
applicants_generated.emit(is_opening)
## 接受一名候选弟子:分配 ID 并移入名录(候选池 → 名录)。
## 接受一名候选弟子:分配 ID、快照入宗时间并移入名录(候选池 → 名录)。
## @param d: 要接受的候选
func accept_applicant(d: Disciple) -> void:
if not applicants.has(d):
@@ -73,6 +74,9 @@ func accept_applicant(d: Disciple) -> void:
applicants.erase(d)
d.id = _next_id
_next_id += 1
d.join_year = GameState.year
d.join_month = GameState.month
d.join_day = GameState.day
disciples.append(d)
disciples_changed.emit()
print("弟子入宗:%s %d岁 | %s资质%s | %s灵根 | %s" % [