feat: 资质概率按难度配置化,新增普通/困难两档权重
- game_config.cfg 新增 difficulty 档位与 [recruitment_normal]/[recruitment_hard] 权重表 - GameConfig 解析各档权重,get_aptitude_weights() 按当前难度返回 - DiscipleManager 资质判定改读配置权重,删除代码常量 - 设计文档补充配置写法说明(VariantParser 数组字面量陷阱) - 计划表同步 D3 进度
This commit is contained in:
+16
-8
@@ -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]
|
||||
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 并破坏后续节解析。
|
||||
> 以后所有可调参数(天赋权重、价格、境界门槛等)统一加到这里。
|
||||
|
||||
---
|
||||
|
||||
+2
-2
@@ -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 | 建筑系统基础 | ① 灵石矿场景 ② 建造→每时辰产出 ③ 升级 | 建筑产灵石,升级加速 | ⬜ |
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
+27
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user