From 5ad0272d79807386451290cde0419eeb6ca0b898 Mon Sep 17 00:00:00 2001 From: chen Date: Sat, 8 Aug 2026 17:10:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=81=B5=E6=A0=B9=E6=94=B9=E4=B8=BA1~5?= =?UTF-8?q?=E6=A0=B9+=E5=AE=B9=E9=87=8F=E5=85=AC=E5=BC=8F(1=C3=B7=E6=A0=B9?= =?UTF-8?q?=E6=95=B0)=EF=BC=8C=E6=9D=83=E9=87=8D=E8=A1=A8=E8=BF=9B?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=9B=E6=96=87=E6=A1=A3=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/design/修炼系统设计.md | 14 +++++++------- doc/design/弟子系统设计.md | 26 ++++++++++++++------------ doc/开发计划表.md | 2 +- resources/game_config.cfg | 2 +- src/Character/Disciple.gd | 14 ++++++++------ src/Character/DiscipleManager.gd | 18 ++++++++++++++++-- src/Core/GameConfig.gd | 16 ++++++++-------- 7 files changed, 55 insertions(+), 37 deletions(-) diff --git a/doc/design/修炼系统设计.md b/doc/design/修炼系统设计.md index 3b418d1..360998f 100644 --- a/doc/design/修炼系统设计.md +++ b/doc/design/修炼系统设计.md @@ -9,7 +9,7 @@ ## 一、核心循环 ``` -每日推进 → 修为增长(资质×天灵根×灵气浓度)→ 达到层门槛 → 升层/突破判定 → 境界推进 +每日推进 → 修为增长(资质×灵根容量×天灵根×灵气浓度)→ 达到层门槛 → 升层/突破判定 → 境界推进 ``` - 纯挂机机制:弟子自动修炼,玩家无需操作 @@ -19,13 +19,13 @@ ## 二、修炼速度 -**每日修为增量 = 基础速度 × 资质倍率 × 灵根数量倍率 × 天灵根加成 × 灵气浓度** +**每日修为增量 = 基础速度 × 资质倍率 × 灵根容量倍率 × 天灵根加成 × 灵气浓度** | 因子 | 来源 | 说明 | |------|------|------| | 基础速度 | 配置 `base_speed`(默认 10) | 修为/游戏日 | | 资质倍率 | 配置 `aptitude_speed`([0.6, 1.0, 1.5, 2.0]) | 按下品/中品/上品/天骄索引 | -| 灵根数量倍率 | 配置 `root_count_speed`([1.0, 0.8, 0.6]) | 按根数索引(1根/2根/3根),根数越少修炼越快 | +| 灵根容量倍率 | 固定公式 `1 ÷ 根数`(无配置) | 1根=1.0、2根=0.5、3根=1/3、4根=0.25、5根=0.2 | | 天灵根加成 | 配置 `heavenly_bonus`(1.5) | 仅在 is_heavenly 时乘入 | | 灵气浓度 | 配置 `qi_concentration`(默认 1.0) | D5 固定值;D6 建筑系统接入后动态化 | @@ -34,10 +34,11 @@ ### 含义 - **资质定天赋上限**:决定倍率主体(0.6~2.0) -- **灵根数量定纯度**:根数越少越纯净(1根 ×1.0、2根 ×0.8、3根 ×0.6) -- **天灵根是稀缺加成**:强制单根 + 额外 ×1.5,三个维度独立掷骰 +- **灵根数量定灵气容量**:容量 = 1 ÷ 灵根数(硬规则,不提供配置)。单灵根 1 单位灵气即充满(×1.0),双灵根只充 1/2(×0.5),三灵根 1/3,四灵根 1/4,五灵根 1/5,根数越多同一单位灵气分摊越薄 +- **天灵根是稀缺加成**:强制单根(满容量)+ 额外 ×1.5,三个维度独立掷骰 +- **无灵根(体修路线预留)**:容量为 0,无法练气;暂不生成,待体修系统(炼体)接入后另行结算 -组合示例(天骄资质 + 三灵根 = 2.0 × 0.6 = 1.2,慢于 上品资质 + 单灵根 = 1.5 × 1.0 = 1.5) +组合示例(天骄资质 + 五灵根 = 2.0 × 0.2 = 0.4,慢于 上品资质 + 单灵根 = 1.5 × 1.0 = 1.5) 修为存储用 float(允许小数积累),显示时取整。 @@ -103,7 +104,6 @@ base_speed=10 ; 基础修为/日 qi_concentration=1.0 ; 宗门灵气浓度(D6 动态化) aptitude_speed=[0.6, 1.0, 1.5, 2.0] ; 资质倍率(下品/中品/上品/天骄) -root_count_speed=[1.0, 0.8, 0.6] ; 灵根数量倍率(1根/2根/3根) heavenly_bonus=1.5 ; 天灵根额外倍率 breakthrough_chance=0.8 ; 瓶颈突破成功率(待接入) level_thresholds=[100, 200, 350, 550, 800, 1100, 1500, 2000, 2600, 3300, 4100, 5000] ; 待接入 diff --git a/doc/design/弟子系统设计.md b/doc/design/弟子系统设计.md index f4c22af..58c9b0f 100644 --- a/doc/design/弟子系统设计.md +++ b/doc/design/弟子系统设计.md @@ -1,7 +1,7 @@ # 弟子系统设计(D3:生成 + 入宗分流 / D4:名录 UI) > 对应开发计划表 D3(8/5)与 D4(8/6)。本文档只描述设计,不包含代码。 -> 状态:D3 已实现;D4 设计稿,待审阅通过后实现 +> 状态:D3、D4 已实现 --- @@ -15,7 +15,7 @@ | `name` | String | 随机生成的姓名 | | `age` | int | 入宗年龄(12~18) | | `aptitude` | 枚举 Aptitude | 资质(入宗分流结果) | -| `roots` | 枚举数组 SpiritRoot | 灵根列表(普通弟子 1~3 根,互不重复) | +| `roots` | 枚举数组 SpiritRoot | 灵根列表(普通弟子 1~5 根,互不重复) | | `is_heavenly` | bool | 天灵根标记(稀有灵根,见枚举二) | | `join_year` | int | 入宗年份(0 = 未入宗/候选),accept 时快照 GameState | | `join_month` | int | 入宗月份 | @@ -36,7 +36,7 @@ ### 枚举二:灵根五行(SpiritRoot) -金、木、水、火、土 五种。灵根数量影响修炼速度(根数越少越快),元素种类影响日后生产效率匹配(D6 建筑/职能系统使用),此处只生成不消费。 +金、木、水、火、土 五种。灵根数量影响灵气容量(容量 = 1 ÷ 根数:单灵根充满、双灵根 1/2、三灵根 1/3……五灵根 1/5,修炼速度按比例折扣),元素种类影响日后生产效率匹配(D6 建筑/职能系统使用),此处只生成不消费。 ### 特殊灵根:天灵根 @@ -73,7 +73,7 @@ ### 1. 姓名 -- 姓氏池:24 个常用修仙风单姓(林、苏、叶、萧、顾、沈、楚、白……) +- 姓氏池:32 个常用修仙风单姓(林、苏、叶、萧、顾、沈、楚、白……) - 名用字池:24 个(清、玄、墨、尘、风、澜、霜、珏……) - 规则:随机 1 个姓 + 1~2 个字(50% 概率双字名) - 不保证唯一(同名弟子可共存,以 id 区分) @@ -84,9 +84,10 @@ ### 3. 灵根 -- 普通弟子:数量 1~3 根均匀随机,元素从五行中随机抽取、互不重复 +- 普通弟子:数量按配置权重随机(`root_count_weights`,1~5 根),元素从五行中随机抽取、概率均等、互不重复 - 天灵根:仅天骄资质再判(概率 `heavenly_root_chance`),灵根数量固定 1 根,修炼速度额外 +50% -- 含义:单灵根修炼最快,三灵根最慢(对应修仙世界观) +- 含义:单灵根修炼最快,五灵根最慢(对应修仙世界观) +- 无灵根暂不生成(体修路线预留,见修炼系统设计) ### 4. 资质(入宗分流) @@ -112,7 +113,7 @@ 招募**不是玩家随时点按钮**,而是"生成候选 → 暂停时间 → 弹窗选择": - **开局招募**:新游戏开始,生成 **5 名候选**,暂停时间弹窗,**必须选满 3 名**才能确定 -- **定期招募**:每满间隔(配置文件 `recruit_interval_years`,默认 0.1 年 = 36 天)生成 **3 名候选**,暂停时间弹窗 +- **定期招募**:每满间隔(配置文件 `recruit_interval_years`,当前 0.25 年 = 90 天)生成 **3 名候选**,暂停时间弹窗 - **选择方式**:每个候选独立勾选"入宗",可全部接受、可全部拒绝(定期招募可 0~3 个) - **结算**:点"确定" → 勾选的入宗、未勾选的拒绝 → 关闭弹窗 → **恢复时间** - 所有参数(候选数、必选数、间隔)来自 `resources/game_config.cfg`,改配置即改难度 @@ -161,9 +162,10 @@ difficulty="normal" ; 当前难度档位 opening_applicant_count=5 ; 开局候选人数 opening_pick_count=3 ; 开局必须选满数 -recruit_interval_years=0.1 ; 定期招募间隔(游戏年) +recruit_interval_years=0.25 ; 定期招募间隔(游戏年) recruit_applicant_count=3 ; 定期弹窗候选人数 heavenly_root_chance=0.5 ; 天灵根概率:仅天骄资质中再掷,50% +root_count_weights=[20, 20, 20, 20, 20] ; 灵根数量权重(1根~5根,和=100 即百分比概率) [recruitment_normal] ; 普通难度资质权重(下品/中品/上品/天骄) aptitude_weights=[45, 35, 15, 5] @@ -225,7 +227,7 @@ aptitude_weights=[60, 30, 8, 2] | 元素 | 说明 | |------|------| | 标题 | 弟子姓名 + 天灵根标记 | -| 信息区 | 静态展示:资质 / 年龄 / 灵根 / 境界 / 编号 / **入宗时间** | +| 信息区 | 静态展示:名字 / 资质 / 年龄 / 灵根 / 境界 / **入宗时间** | | 预留区 | 修炼进度、属性面板等 D5+ 扩展位置(本期留白) | | 底部 | "关闭"按钮 | @@ -262,7 +264,7 @@ src/UI/Panels/DisciplesPanel/ - [ ] 点顶部"管理"按钮弹出弟子名录面板,显示当前已入宗弟子 - [ ] 列表每行显示:姓名 / 资质(天灵根有标记)/ 灵根 / 境界 - [ ] 名录为空时显示"暂无弟子";招募入宗后列表实时刷新 -- [ ] 点条目"详情"弹出详情弹窗,显示姓名/资质/年龄/灵根/境界/编号 +- [ ] 点条目"详情"弹出详情弹窗,显示名字/资质/年龄/灵根/境界/入宗时间 - [ ] 关闭详情回到列表,关闭列表回到游戏,无报错 - [ ] 打开面板期间时间**暂停**,关闭面板后时间恢复推进 @@ -284,8 +286,8 @@ src/UI/Panels/DisciplesPanel/ - [ ] **开局**:进入游戏即暂停,弹出"弟子入宗(开局招募)",显示 5 名候选 - [ ] 开局模式确定按钮在选满 3 名前不可用;选满后可确定 - [ ] 确定后:勾选的 3 名入宗(控制台打印),时间恢复推进 -- [ ] **定期**:每 36 游戏日(0.1 年 @1x ≈ 18 秒)再次暂停弹窗,显示 3 名候选 +- [ ] **定期**:每 90 游戏日(0.25 年 @1x ≈ 45 秒)再次暂停弹窗,显示 3 名候选 - [ ] 定期模式可勾选 0~3 名,全部拒绝也可确定;时间正常恢复 -- [ ] 多次招募后能观察到天灵根弟子(约 3% 概率,弹窗/控制台有标记) +- [ ] 多次招募后能观察到天灵根弟子(仅天骄中再判 50%,总体概率约 2.5%,弹窗/控制台有标记) - [ ] 修改 `game_config.cfg` 中 `opening_applicant_count` 等参数,重启后开局候选数随之变化 - [ ] 返回主菜单再进入,名录已清空(reset 生效) diff --git a/doc/开发计划表.md b/doc/开发计划表.md index 6c8d999..ea380be 100644 --- a/doc/开发计划表.md +++ b/doc/开发计划表.md @@ -1,7 +1,7 @@ # 开发计划表 > 开始日期:2026-08-03(周一) 每日有效开发约 2 小时 -> 进度更新:2026-08-06  D1–D4 完成,D5(修炼循环)明日进行 +> 进度更新:2026-08-08  D1–D4 完成;D5(修炼循环)未启动,进度落后 1 天(设计文档已就绪,待实现) ## 一、每日作息模板(工作日) diff --git a/resources/game_config.cfg b/resources/game_config.cfg index dbf8e03..076a7bb 100644 --- a/resources/game_config.cfg +++ b/resources/game_config.cfg @@ -9,6 +9,7 @@ opening_pick_count=3 recruit_interval_years=0.25 recruit_applicant_count=3 heavenly_root_chance=0.5 ; 天灵根概率:仅天骄资质中再掷,50% +root_count_weights=[20, 20, 20, 20, 20] ; 灵根数量权重(1根/2根/3根/4根/5根,和=100 即百分比概率) ; 各难度资质权重表(下品/中品/上品/天骄,权重和=100 即百分比概率) ; 当前难度由 [recruitment] difficulty 指定 @@ -22,5 +23,4 @@ aptitude_weights=[60, 30, 8, 2] ; 60% / 30% / 8% / 2% base_speed=10 ; 基础修为/日 qi_concentration=1.0 ; 宗门灵气浓度 aptitude_speed=[0.6, 1.0, 1.5, 2.0] ; 资质倍率(下品/中品/上品/天骄) -root_count_speed=[1.0, 0.8, 0.6] ; 灵根数量倍率(1根/2根/3根) heavenly_bonus=1.5 ; 天灵根额外修炼速度倍率 diff --git a/src/Character/Disciple.gd b/src/Character/Disciple.gd index 2a10509..e3f3560 100644 --- a/src/Character/Disciple.gd +++ b/src/Character/Disciple.gd @@ -21,7 +21,7 @@ var id: int = 0 # 唯一编号(DiscipleManager 分配) var name: String = "" var age: int = 0 var aptitude: Aptitude = Aptitude.ORDINARY -var roots: Array[SpiritRoot] = [] # 普通弟子 1~3 根;天灵根固定 1 根 +var roots: Array[SpiritRoot] = [] # 普通弟子 1~5 根;天灵根固定 1 根 var is_heavenly: bool = false # 天灵根标记(仅天骄资质,概率见配置) var join_year: int = 0 # 入宗年份(0 = 未入宗/候选),accept 时快照 var join_month: int = 0 # 入宗月份 @@ -39,11 +39,13 @@ func get_roots_text() -> String: names.append(ROOT_NAMES[root]) return "、".join(names) -## 灵根数量修炼倍率(根数越少越快,D5 修炼循环消费)。 -## 数值来自 GameConfig.root_count_speed,按根数-1 索引,越界钳制。 -func get_root_count_speed() -> float: - var idx := clampi(roots.size() - 1, 0, GameConfig.root_count_speed.size() - 1) - return GameConfig.root_count_speed[idx] +## 灵根数量灵气容量倍率(根数越少灵气越纯、修炼越快,D5 修炼循环消费)。 +## 容量规则:单灵根 1 单位灵气充满,双灵根只充 1/2,三灵根 1/3,以此类推(容量 = 1 ÷ 根数)。 +## 无灵根无法练气,容量为 0(体修路线未来另行结算,暂不生成)。 +func get_root_count_capacity() -> float: + if roots.is_empty(): + return 0.0 + return 1.0 / roots.size() func get_realm_text() -> String: if realm_index == 0: diff --git a/src/Character/DiscipleManager.gd b/src/Character/DiscipleManager.gd index 143f731..21ef852 100644 --- a/src/Character/DiscipleManager.gd +++ b/src/Character/DiscipleManager.gd @@ -137,12 +137,13 @@ func _generate_name() -> String: return surname + given ## 随机生成灵根。 -## 天灵根:固定 1 根五行;普通弟子:1~3 根互不重复(根数越少修炼越快)。 +## 天灵根:固定 1 根五行;普通弟子:按配置权重掷 1~5 根,元素从五行中抽取、概率均等。 +## 无灵根暂不生成(体修路线预留)。 ## @param heavenly: 是否天灵根 func _generate_roots(heavenly: bool) -> Array[Disciple.SpiritRoot]: if heavenly: return [randi() % Disciple.SpiritRoot.size() as Disciple.SpiritRoot] - var count := randi_range(1, 3) + var count := _roll_root_count() var pool := Disciple.SpiritRoot.values() pool.shuffle() var result: Array[Disciple.SpiritRoot] = [] @@ -150,6 +151,19 @@ func _generate_roots(heavenly: bool) -> Array[Disciple.SpiritRoot]: result.append(pool[i]) return result +## 按配置权重掷灵根数量(1~5 根),权重来自 GameConfig.root_count_weights。 +func _roll_root_count() -> int: + var weights := GameConfig.root_count_weights + var total := 0 + for w in weights: + total += w + var roll := randi() % total + for i in weights.size(): + if roll < weights[i]: + return i + 1 + roll -= weights[i] + return 1 + ## 按权重掷资质(入宗分流),权重来自 GameConfig 当前难度配置。 func _roll_aptitude() -> Disciple.Aptitude: var weights := GameConfig.get_aptitude_weights() diff --git a/src/Core/GameConfig.gd b/src/Core/GameConfig.gd index 45b4992..4f3d77e 100644 --- a/src/Core/GameConfig.gd +++ b/src/Core/GameConfig.gd @@ -19,6 +19,8 @@ var recruit_interval_years := 0.1 var recruit_applicant_count := 3 ## 天灵根概率(仅天骄资质中再掷一次)。 var heavenly_root_chance := 0.5 +## 灵根数量权重(按根数-1 索引:1根~5根,和=100 即百分比概率)。 +var root_count_weights: Array[int] = [20, 20, 20, 20, 20] # —— 修炼系统(对应 cfg 的 [cultivation] 节)—— ## 基础修炼速度(修为/游戏日)。 @@ -27,8 +29,6 @@ var cultivation_base_speed := 10.0 var qi_concentration := 1.0 ## 资质修炼倍率(按下品/中品/上品/天骄索引)。 var aptitude_speed: Array[float] = [0.6, 1.0, 1.5, 2.0] -## 灵根数量修炼倍率(按根数-1 索引:1根/2根/3根)。 -var root_count_speed: Array[float] = [1.0, 0.8, 0.6] ## 天灵根额外修炼速度倍率。 var heavenly_bonus := 1.5 @@ -55,6 +55,12 @@ func _load_config() -> void: recruit_interval_years = cfg.get_value("recruitment", "recruit_interval_years", recruit_interval_years) recruit_applicant_count = cfg.get_value("recruitment", "recruit_applicant_count", recruit_applicant_count) heavenly_root_chance = cfg.get_value("recruitment", "heavenly_root_chance", heavenly_root_chance) + var root_raw: Variant = cfg.get_value("recruitment", "root_count_weights", []) + if root_raw is Array and root_raw.size() == root_count_weights.size(): + var arr_roots: Array[int] = [] + for w in root_raw: + arr_roots.append(int(w)) + root_count_weights = arr_roots # 修炼系统 cultivation_base_speed = cfg.get_value("cultivation", "base_speed", cultivation_base_speed) qi_concentration = cfg.get_value("cultivation", "qi_concentration", qi_concentration) @@ -65,12 +71,6 @@ func _load_config() -> void: for v in apt_raw: arr.append(float(v)) aptitude_speed = arr - var root_raw: Variant = cfg.get_value("cultivation", "root_count_speed", []) - if root_raw is Array and root_raw.size() == root_count_speed.size(): - var arr2: Array[float] = [] - for v in root_raw: - arr2.append(float(v)) - root_count_speed = arr2 # 逐档读取难度权重(INI 数组字面量,如 [45, 35, 15, 5]) for key in aptitude_weights_by_difficulty.keys(): var raw: Variant = cfg.get_value("recruitment_" + key, "aptitude_weights", [])