From cfebb8dded8ec9995e84ce5ac2b04f9cdd1da6b1 Mon Sep 17 00:00:00 2001 From: chen Date: Thu, 6 Aug 2026 00:31:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B5=84=E8=B4=A8=E6=A6=82=E7=8E=87?= =?UTF-8?q?=E6=8C=89=E9=9A=BE=E5=BA=A6=E9=85=8D=E7=BD=AE=E5=8C=96=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=99=AE=E9=80=9A/=E5=9B=B0=E9=9A=BE?= =?UTF-8?q?=E4=B8=A4=E6=A1=A3=E6=9D=83=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - game_config.cfg 新增 difficulty 档位与 [recruitment_normal]/[recruitment_hard] 权重表 - GameConfig 解析各档权重,get_aptitude_weights() 按当前难度返回 - DiscipleManager 资质判定改读配置权重,删除代码常量 - 设计文档补充配置写法说明(VariantParser 数组字面量陷阱) - 计划表同步 D3 进度 --- doc/design/弟子系统设计.md | 32 ++++++++++++++++++++------------ doc/开发计划表.md | 4 ++-- resources/game_config.cfg | 8 ++++++++ src/Character/DiscipleManager.gd | 13 ++++++------- src/Core/GameConfig.gd | 28 +++++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/doc/design/弟子系统设计.md b/doc/design/弟子系统设计.md index b98d455..0959f0c 100644 --- a/doc/design/弟子系统设计.md +++ b/doc/design/弟子系统设计.md @@ -80,16 +80,16 @@ ### 4. 资质(入宗分流) -按权重表掷骰: +按权重表掷骰,权重**随难度档位变化**(配置驱动): -| 资质 | 权重 | 概率 | -|------|------|------| -| 下品 | 45 | 45% | -| 中品 | 35 | 35% | -| 上品 | 15 | 15% | -| 天骄 | 5 | 5% | +| 难度 | 下品 | 中品 | 上品 | 天骄 | +|------|------|------|------|------| +| 普通(normal) | 45 | 35 | 15 | 5 | +| 困难(hard) | 60 | 30 | 8 | 2 | -> 概率说明:开发阶段固定此分布,后期根据游戏难度测试调整权重即可,不改代码结构。 +- 当前难度由配置 `[recruitment] difficulty` 指定("normal"/"hard") +- 权重表在 `[recruitment_normal]` / `[recruitment_hard]` 节,INI 数组字面量写法:`aptitude_weights=[45, 35, 15, 5]` +- 改配置即调难度,后续可加更多档位(代码字典加一项 + 配置加一节) --- @@ -148,12 +148,20 @@ ```ini [recruitment] -opening_applicant_count=5 ; 开局候选人数 -opening_pick_count=3 ; 开局必须选满数 -recruit_interval_years=0.1 ; 定期招募间隔(游戏年) -recruit_applicant_count=3 ; 定期弹窗候选人数 +difficulty="normal" ; 当前难度档位 +opening_applicant_count=5 ; 开局候选人数 +opening_pick_count=3 ; 开局必须选满数 +recruit_interval_years=0.1 ; 定期招募间隔(游戏年) +recruit_applicant_count=3 ; 定期弹窗候选人数 + +[recruitment_normal] ; 普通难度资质权重(下品/中品/上品/天骄) +aptitude_weights=[45, 35, 15, 5] + +[recruitment_hard] ; 困难难度资质权重 +aptitude_weights=[60, 30, 8, 2] ``` +> 注意:ConfigFile 用 VariantParser 解析值,**数组必须写 `[45, 35, 15, 5]` 字面量**,字符串值必须加引号(如 `difficulty="normal"`);裸写 `45,35,15,5` 会被截断为 45 并破坏后续节解析。 > 以后所有可调参数(天赋权重、价格、境界门槛等)统一加到这里。 --- diff --git a/doc/开发计划表.md b/doc/开发计划表.md index 3fe101b..6fd0f5f 100644 --- a/doc/开发计划表.md +++ b/doc/开发计划表.md @@ -1,7 +1,7 @@ # 开发计划表 > 开始日期:2026-08-03(周一) 每日有效开发约 2 小时 -> 进度更新:2026-08-05  D1、D2、D3 完成,D4 进行中 +> 进度更新:2026-08-06  D1–D3 完成(D3 含弹窗招募与配置系统),D4 进行中 ## 一、每日作息模板(工作日) @@ -21,7 +21,7 @@ | ---- | -- | ---- | ---- | -------- | ---- | | 8/3 一 | D1 | TimeSystem | ① 日期变量(年月日) ② tick 推进 ③ 暂停/加速 | HUD 显示年月日,可调速度 | ✅ 完成(含月/年信号、Settings 持久化) | | 8/4 二 | D2 | SectManager 数据模型 | ① 单例 ② 灵石/灵气/声望 ③ 增减接口 | 控制台可读写资源 | ✅ 完成(灵石/声望增减+信号,HUD 实时绑定) | -| 8/5 三 | D3 | 弟子生成 + 入宗分流 | ① 随机名字/资质/灵根 ② 按资质分四类 ③ 招募按钮 | 点按钮生成弟子入列表 | ✅ 完成(改为每 30 游戏日定时自动招募,含天灵根 3%) | +| 8/5 三 | D3 | 弟子生成 + 入宗分流 | ① 随机名字/资质/灵根 ② 按资质分四类 ③ 招募流程 | 开局 5 选 3 必选满,定期弹窗可全拒/全收 | ✅ 完成(弹窗招募:开局5选3+定期3候选,配置驱动含天灵根3%;新增 GameConfig 配置系统) | | 8/6 四 | D4 | 弟子列表 UI | ① 列表条目场景 ② 姓名/资质/境界显示 ③ 点击详情 | 列表可浏览弟子 | ⬜ | | 8/7 五 | D5 | 修炼循环 | ① 修为随时间增长(资质×灵气) ② 境界门槛 ③ 突破判定 | 弟子自动修炼,可突破 | ⬜ | | 8/8 六 | D6 | 建筑系统基础 | ① 灵石矿场景 ② 建造→每时辰产出 ③ 升级 | 建筑产灵石,升级加速 | ⬜ | diff --git a/resources/game_config.cfg b/resources/game_config.cfg index f05476d..8bf3d89 100644 --- a/resources/game_config.cfg +++ b/resources/game_config.cfg @@ -3,7 +3,15 @@ ; 注释以 ; 开头,参数按系统分节 [recruitment] +difficulty="normal" opening_applicant_count=5 opening_pick_count=3 recruit_interval_years=0.1 recruit_applicant_count=3 + +; 各难度资质权重(下品/中品/上品/天骄) +[recruitment_normal] +aptitude_weights=[45, 35, 15, 5] + +[recruitment_hard] +aptitude_weights=[60, 30, 8, 2] diff --git a/src/Character/DiscipleManager.gd b/src/Character/DiscipleManager.gd index 76f76a8..e9f664b 100644 --- a/src/Character/DiscipleManager.gd +++ b/src/Character/DiscipleManager.gd @@ -14,8 +14,6 @@ var disciples: Array[Disciple] = [] ## 候选弟子池(未入宗,等待玩家选择)。 var applicants: Array[Disciple] = [] -## 入宗分流权重(按资质四类):下品 / 中品 / 上品 / 天骄。 -const APTITUDE_WEIGHTS: Array[int] = [45, 35, 15, 5] ## 天灵根生成概率(3%)。 const HEAVENLY_CHANCE := 0.03 @@ -149,14 +147,15 @@ func _generate_roots(heavenly: bool) -> Array[Disciple.SpiritRoot]: result.append(pool[i]) return result -## 按权重掷资质(入宗分流)。 +## 按权重掷资质(入宗分流),权重来自 GameConfig 当前难度配置。 func _roll_aptitude() -> Disciple.Aptitude: + var weights := GameConfig.get_aptitude_weights() var total := 0 - for w in APTITUDE_WEIGHTS: + for w in weights: total += w var roll := randi() % total - for i in APTITUDE_WEIGHTS.size(): - if roll < APTITUDE_WEIGHTS[i]: + for i in weights.size(): + if roll < weights[i]: return i as Disciple.Aptitude - roll -= APTITUDE_WEIGHTS[i] + roll -= weights[i] return Disciple.Aptitude.ORDINARY diff --git a/src/Core/GameConfig.gd b/src/Core/GameConfig.gd index f5389f1..a899a66 100644 --- a/src/Core/GameConfig.gd +++ b/src/Core/GameConfig.gd @@ -7,6 +7,8 @@ extends Node const CONFIG_PATH := "res://resources/game_config.cfg" # —— 招募系统(对应 cfg 的 [recruitment] 节)—— +## 当前难度档位(对应下方各难度节,如 "normal"/"hard")。 +var difficulty := "normal" ## 开局候选人数。 var opening_applicant_count := 5 ## 开局必须选满数。 @@ -16,6 +18,12 @@ var recruit_interval_years := 0.1 ## 定期弹窗候选人数。 var recruit_applicant_count := 3 +## 各难度资质权重表(键 = 难度档位,值 = 下品/中品/上品/天骄 权重)。 +var aptitude_weights_by_difficulty: Dictionary = { + "normal": [45, 35, 15, 5], + "hard": [60, 30, 8, 2], +} + func _ready() -> void: _load_config() @@ -23,10 +31,28 @@ func _ready() -> void: ## 读取配置文件;缺失的项保持代码默认值,不会报错。 func _load_config() -> void: var cfg := ConfigFile.new() - if cfg.load(CONFIG_PATH) != OK: + var err := cfg.load(CONFIG_PATH) + if err != OK: push_warning("GameConfig: 配置文件不存在,使用默认值") return + difficulty = cfg.get_value("recruitment", "difficulty", difficulty) opening_applicant_count = cfg.get_value("recruitment", "opening_applicant_count", opening_applicant_count) opening_pick_count = cfg.get_value("recruitment", "opening_pick_count", opening_pick_count) 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) + # 逐档读取难度权重(INI 数组字面量,如 [45, 35, 15, 5]) + for key in aptitude_weights_by_difficulty.keys(): + var raw: Variant = cfg.get_value("recruitment_" + key, "aptitude_weights", []) + if raw is Array and raw.size() > 0: + var arr: Array[int] = [] + for w in raw: + arr.append(int(w)) + aptitude_weights_by_difficulty[key] = arr + +## 当前难度下的资质权重(下品/中品/上品/天骄)。 +func get_aptitude_weights() -> Array[int]: + var raw: Array = aptitude_weights_by_difficulty.get(difficulty, aptitude_weights_by_difficulty["normal"]) + var result: Array[int] = [] + for w in raw: + result.append(int(w)) + return result