feat: 修炼数值配置化,天灵根规则重构,更新主菜单背景

- GameConfig 新增 [cultivation] 修炼系统配置(基础速度/灵气浓度/资质及灵根倍率/天灵根加成)
- 天灵根改为仅天骄资质再掷(heavenly_root_chance=50%),移入 GameConfig 可配置
- Disciple 修炼倍率常量改为从 GameConfig 读取,新增灵根数量倍率方法
- 主菜单背景更换为"图片大门",新增"宗门全景"资源,删除旧 BG1.png
- 同步更新弟子系统设计文档及新增修炼系统设计文档
This commit is contained in:
2026-08-08 14:32:17 +08:00
parent e283f6b2b7
commit b13c20a313
12 changed files with 260 additions and 25 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 MiB

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://caeqoc6wx8toy"
path="res://.godot/imported/BG1.png-6bf4b9c36da6bbdf71bd2c8203f4cb53.ctex"
uid="uid://c6bthhmao5fyh"
path="res://.godot/imported/图片大门.png-03ea66f8e1eb82ba7952374321f00064.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/sprites/ui/BG1.png"
dest_files=["res://.godot/imported/BG1.png-6bf4b9c36da6bbdf71bd2c8203f4cb53.ctex"]
source_file="res://assets/sprites/ui/图片大门.png"
dest_files=["res://.godot/imported/图片大门.png-03ea66f8e1eb82ba7952374321f00064.ctex"]
[params]
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

+40
View File
@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cewfc3vetgbfx"
path="res://.godot/imported/宗门全景.png-d969df84bf06c400df6e36c494864bbe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/sprites/ui/宗门全景.png"
dest_files=["res://.godot/imported/宗门全景.png-d969df84bf06c400df6e36c494864bbe.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
+146
View File
@@ -0,0 +1,146 @@
# 修炼系统设计(D5:修炼循环)
> 对应开发计划表 D5(8/7):① 修为随时间增长(资质×灵气)② 境界门槛 ③ 突破判定。
> 交付标准:弟子自动修炼,可突破。本文档只描述设计,不包含代码。
> 状态:设计稿,待审阅通过后实现
---
## 一、核心循环
```
每日推进 → 修为增长(资质×天灵根×灵气浓度)→ 达到层门槛 → 升层/突破判定 → 境界推进
```
- 纯挂机机制:弟子自动修炼,玩家无需操作
- 修炼只在游戏时间推进时进行(TimeSystem.day_passed),暂停/弹窗期间冻结
---
## 二、修炼速度
**每日修为增量 = 基础速度 × 资质倍率 × 灵根数量倍率 × 天灵根加成 × 灵气浓度**
| 因子 | 来源 | 说明 |
|------|------|------|
| 基础速度 | 配置 `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根),根数越少修炼越快 |
| 天灵根加成 | 配置 `heavenly_bonus`1.5 | 仅在 is_heavenly 时乘入 |
| 灵气浓度 | 配置 `qi_concentration`(默认 1.0) | D5 固定值;D6 建筑系统接入后动态化 |
> 所有修炼数值统一从 GameConfig 读取(Disciple 不内置倍率常量),避免双份数值漂移。
### 含义
- **资质定天赋上限**:决定倍率主体(0.6~2.0)
- **灵根数量定纯度**:根数越少越纯净(1根 ×1.0、2根 ×0.8、3根 ×0.6
- **天灵根是稀缺加成**:强制单根 + 额外 ×1.5,三个维度独立掷骰
组合示例(天骄资质 + 三灵根 = 2.0 × 0.6 = 1.2,慢于 上品资质 + 单灵根 = 1.5 × 1.0 = 1.5
修为存储用 float(允许小数积累),显示时取整。
---
## 三、境界门槛(本期:练气 1–13 层)
| 层 | 需求修为(配置 `level_thresholds` | 是否瓶颈 |
|----|----------------------------------|---------|
| 1→2 | 100 | 否 |
| 2→3 | 200 | 否 |
| 3→4 | 350 | **是** |
| 4→5 | 550 | 否 |
| 5→6 | 800 | 否 |
| 6→7 | 1100 | **是** |
| 7→8 | 1500 | 否 |
| 8→9 | 2000 | 否 |
| 9→10 | 2600 | **是** |
| 10→11 | 3300 | 否 |
| 11→12 | 4100 | 否 |
| 12→13 | 5000 | **是** |
- **非瓶颈层**:修为满门槛 → 自动升层(无失败)
- **瓶颈层**3→4 / 6→7 / 9→10 / 12→13):修为满后进入突破判定
- 13 层圆满:修为封顶,显示"练气圆满";筑基以上大境界需丹药/灵石资源,**本期不做**(后续 P2 接入)
> 数值均为示例,正式数值在 D9 平衡调整,只改配置不动代码。
---
## 四、突破判定(瓶颈层)
1. 修为 ≥ 瓶颈层门槛时,每日结算后自动尝试突破
2. 掷骰:成功概率 = 配置 `breakthrough_chance`(默认 0.8
3. **成功** → 升层,控制台打印"X 突破至 练气4层"
4. **失败** → 修为扣减 20%(冲关损耗),次日再尝试;控制台打印失败信息
5. 失败不连续重试(每天最多判定一次)
**设计意图**:挂机友好(全自动),但瓶颈制造节奏感与"卡关→等积累"的经营反馈;损耗惩罚避免无脑挂到顶。
---
## 五、CultivationManager(新 Autoload
存放位置:`src/Character/CultivationManager.gd`(与 DiscipleManager 同域,注册顺序在 DiscipleManager 之后、声明于 project.godot
| 接口 | 说明 |
|------|------|
| 监听 `TimeSystem.day_passed` | 每日结算全体弟子 |
| 私有 `_gain_exp(d)` | 按公式累计修为 |
| 私有 `_check_breakthrough(d)` | 门槛判定 + 瓶颈掷骰 |
| 信号 `realm_changed(d)` | 境界变化(详情面板刷新用) |
| 信号 `cultivation_log(text)` | 修炼日志文本(控制台打印/后续日志系统) |
**注意**:只在 `disciples` 名录内结算,候选池不修炼。
---
## 六、配置节(game_config.cfg 新增 [cultivation]
```ini
[cultivation]
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] ; 待接入
bottleneck_levels=[4, 7, 10, 13] ; 待接入
```
- `aptitude_speed`:与资质枚举一一对应,必须 4 项
- `level_thresholds`:练气 1→2 到 12→13 共 12 个门槛值
- `bottleneck_levels`:升到这些层时需要突破判定
---
## 七、UI 接入(D4 预留区填充)
- **详情弹窗**:信息区追加"修为:1234 / 2000"(当前/本层门槛;13 层显示 练气圆满)
- **名录列表**:境界列实时变化(realm_changed 后自动刷新,现有 disciples_changed 不触发,需详情面板监听 realm_changed
- 修炼日志:控制台 print(本期不做日志界面)
---
## 八、实现拆解(小步可验证)
1. 配置节 [cultivation] + GameConfig 读取
2. Disciple 加 `cultivation_exp: float` 字段 + 门槛查询辅助
3. CultivationManager 骨架:每日结算修为
4. 非瓶颈自动升层
5. 瓶颈突破判定(成功/失败/损耗)
6. 详情面板修为显示 + realm_changed 刷新
7. 挂机验证(加速时间观察多轮突破)+ 提交
---
## 九、验收清单(D5 交付标准)
- [ ] 挂机时弟子修为逐日增长,速度随资质/天灵根不同(下品慢、天骄快)
- [ ] 非瓶颈层修为满自动升层,无失败
- [ ] 瓶颈层(4/7/10/13 层)需突破判定,控制台有成败日志,失败扣 20% 修为
- [ ] 练气 13 层圆满后修为封顶,显示"练气圆满"
- [ ] 详情面板显示修为进度,突破后实时刷新
- [ ] 修改配置(速度/概率/门槛)重启生效
+8 -6
View File
@@ -32,7 +32,7 @@
| 2 | 上品 | 1.5x | 天赋尚可 |
| 3 | 天骄 | 2.0x | 万中无一 |
> 倍率由 D5 修炼循环使用,此处只定义不消费
> 倍率由 D5 修炼循环使用,数值存于 GameConfig(配置 `aptitude_speed`),此处仅为参考展示
### 枚举二:灵根五行(SpiritRoot
@@ -44,12 +44,13 @@
| 项目 | 设定 |
|------|------|
| 生成概率 | 3%(远低于四类资质中"天骄"的 5%,天灵根可叠加于任意资质之上) |
| 出现规则 | **仅天骄资质**Aptitude.HEAVENLY)中再掷一次,非天骄弟子不可能有天灵根 |
| 天骄内概率 | 配置 `heavenly_root_chance`(默认 0.5 = 50%);总体概率 = 天骄概率 × 天骄内概率(普通难度 5% × 50% ≈ 2.5% |
| 灵根构成 | 仅一系灵根(五行之一),纯净单灵根 |
| 修炼速度 | 在资质倍率基础上**额外 +50%**(乘法叠加,D5 修炼循环消费) |
| 修炼速度 | 在资质倍率基础上**额外 +50%**(乘法叠加,数值存于 GameConfig `heavenly_bonus`D5 修炼循环消费) |
| 地位 | 宗门争抢的种子弟子,日后可挂靠特殊培养事件(W8 预留) |
> 天灵根与资质是两个独立维度:资质定天赋底子,天灵根是稀缺加成,二者随机独立
> 天灵根与资质是**嵌套关系**:先掷资质,天骄之后再判天灵根。天灵根 = 天骄 + 单灵根 + 1.5x 加成,是最稀缺组合
### 境界字段说明
@@ -84,7 +85,7 @@
### 3. 灵根
- 普通弟子:数量 1~3 根均匀随机,元素从五行中随机抽取、互不重复
- 天灵根:3% 概率判定为天灵根,灵根数量固定 1 根,修炼速度额外 +50%
- 天灵根:仅天骄资质再判(概率 `heavenly_root_chance`,灵根数量固定 1 根,修炼速度额外 +50%
- 含义:单灵根修炼最快,三灵根最慢(对应修仙世界观)
### 4. 资质(入宗分流)
@@ -119,7 +120,7 @@
### 招募流程(文字时序)
1. 开局(MainGame 调用 `start_new_game()`)或倒计时归零(`_on_day_passed`
2. 生成候选弟子(判天灵根 3% → 生成灵根 → 按权重掷资质 → 组名字),进入候选池
2. 生成候选弟子(按权重掷资质 → 天骄再判天灵根 → 生成灵根 → 组名字),进入候选池
3. `applicants_generated(is_opening)` 信号发出 → 弹窗显示候选列表
4. 玩家勾选(开局模式:确定按钮在选满 3 名前禁用)
5. 点"确定" → `finish_recruitment(selected)` 结算 → 恢复时间
@@ -162,6 +163,7 @@ opening_applicant_count=5 ; 开局候选人数
opening_pick_count=3 ; 开局必须选满数
recruit_interval_years=0.1 ; 定期招募间隔(游戏年)
recruit_applicant_count=3 ; 定期弹窗候选人数
heavenly_root_chance=0.5 ; 天灵根概率:仅天骄资质中再掷,50%
[recruitment_normal] ; 普通难度资质权重(下品/中品/上品/天骄)
aptitude_weights=[45, 35, 15, 5]
+12 -3
View File
@@ -8,10 +8,19 @@ opening_applicant_count=5
opening_pick_count=3
recruit_interval_years=1
recruit_applicant_count=3
heavenly_root_chance=0.5 ; 天灵根概率:仅天骄资质中再掷,50%
; 各难度资质权重(下品/中品/上品/天骄)
; 各难度资质权重(下品/中品/上品/天骄,权重和=100 即百分比概率
; 当前难度由 [recruitment] difficulty 指定
[recruitment_normal]
aptitude_weights=[45, 35, 15, 5]
aptitude_weights=[45, 35, 15, 5] ; 45% / 35% / 15% / 5%
[recruitment_hard]
aptitude_weights=[60, 30, 8, 2]
aptitude_weights=[60, 30, 8, 2] ; 60% / 30% / 8% / 2%
[cultivation] ; 修炼系统
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 ; 天灵根额外修炼速度倍率
+10 -4
View File
@@ -9,12 +9,12 @@ enum Aptitude { ORDINARY, MEDIUM, SUPERIOR, HEAVENLY } # 下品/中品/上品/
## 灵根五行。
enum SpiritRoot { GOLD, WOOD, WATER, FIRE, EARTH }
# —— 常量表:枚举值 → 显示文本 / 倍率(按索引一一对应)——
# —— 常量表:枚举值 → 显示文本(按索引一一对应)——
const APTITUDE_NAMES: Array[String] = ["下品", "中品", "上品", "天骄"]
const APTITUDE_SPEED: Array[float] = [0.6, 1.0, 1.5, 2.0] # D5 用
const ROOT_NAMES: Array[String] = ["", "", "", "", ""]
const REALM_NAMES: Array[String] = ["练气", "筑基", "金丹", "元婴", "化神"] # 按 realm_index 索引
const HEAVENLY_BONUS := 1.5 # 天灵根额外修炼速度倍率(D5 用)
# —— 修炼数值一律读 GameConfig(资质倍率/天灵根加成/速度等)——
# —— 实例字段 ——
var id: int = 0 # 唯一编号(DiscipleManager 分配)
@@ -22,7 +22,7 @@ var name: String = ""
var age: int = 0
var aptitude: Aptitude = Aptitude.ORDINARY
var roots: Array[SpiritRoot] = [] # 普通弟子 1~3 根;天灵根固定 1 根
var is_heavenly: bool = false # 天灵根标记(3% 概率
var is_heavenly: bool = false # 天灵根标记(仅天骄资质,概率见配置
var join_year: int = 0 # 入宗年份(0 = 未入宗/候选),accept 时快照
var join_month: int = 0 # 入宗月份
var join_day: int = 0 # 入宗日
@@ -39,6 +39,12 @@ 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]
func get_realm_text() -> String:
if realm_index == 0:
return "%s%d" % [REALM_NAMES[realm_index], sub_realm_index + 1]
+5 -6
View File
@@ -14,9 +14,6 @@ var disciples: Array[Disciple] = []
## 候选弟子池(未入宗,等待玩家选择)。
var applicants: Array[Disciple] = []
## 天灵根生成概率(3%)。
const HEAVENLY_CHANCE := 0.03
## 姓氏池。
const SURNAMES: Array[String] = [
"", "", "", "", "", "", "", "",
@@ -118,15 +115,17 @@ func _get_interval_days() -> int:
var days_per_year := TimeSystem.MONTHS_PER_YEAR * TimeSystem.DAYS_PER_MONTH
return maxi(1, roundi(GameConfig.recruit_interval_years * days_per_year))
## 创建一名候选弟子:随机生成属性(姓名/年龄/灵根/资质),
## 创建一名候选弟子:随机生成属性(姓名/年龄/资质/天灵根/灵根)。
## 天灵根规则:仅天骄资质中再掷一次(概率来自 GameConfig.heavenly_root_chance)。
## 不分配 ID——ID 在入宗时由 accept_applicant 分配,保证连续且无浪费。
func _create_applicant() -> Disciple:
var d := Disciple.new()
d.name = _generate_name()
d.age = randi_range(12, 18)
d.is_heavenly = randf() < HEAVENLY_CHANCE
d.roots = _generate_roots(d.is_heavenly)
d.aptitude = _roll_aptitude()
d.is_heavenly = d.aptitude == Disciple.Aptitude.HEAVENLY \
and randf() < GameConfig.heavenly_root_chance
d.roots = _generate_roots(d.is_heavenly)
return d
## 随机生成姓名:单姓 + 1~2 个名用字。
+31
View File
@@ -17,6 +17,20 @@ var opening_pick_count := 3
var recruit_interval_years := 0.1
## 定期弹窗候选人数。
var recruit_applicant_count := 3
## 天灵根概率(仅天骄资质中再掷一次)。
var heavenly_root_chance := 0.5
# —— 修炼系统(对应 cfg 的 [cultivation] 节)——
## 基础修炼速度(修为/游戏日)。
var cultivation_base_speed := 10.0
## 宗门灵气浓度(修炼速度系数,D6 建筑系统接入后动态化)。
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
## 各难度资质权重表(键 = 难度档位,值 = 下品/中品/上品/天骄 权重)。
var aptitude_weights_by_difficulty: Dictionary = {
@@ -40,6 +54,23 @@ func _load_config() -> void:
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)
heavenly_root_chance = cfg.get_value("recruitment", "heavenly_root_chance", heavenly_root_chance)
# 修炼系统
cultivation_base_speed = cfg.get_value("cultivation", "base_speed", cultivation_base_speed)
qi_concentration = cfg.get_value("cultivation", "qi_concentration", qi_concentration)
heavenly_bonus = cfg.get_value("cultivation", "heavenly_bonus", heavenly_bonus)
var apt_raw: Variant = cfg.get_value("cultivation", "aptitude_speed", [])
if apt_raw is Array and apt_raw.size() == aptitude_speed.size():
var arr: Array[float] = []
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", [])
+4 -2
View File
@@ -1,7 +1,7 @@
[gd_scene format=3 uid="uid://d1odycoaqhhyg"]
[ext_resource type="Script" uid="uid://drfyh36my6gj2" path="res://src/UI/Panels/MainMenu/MainMenu.gd" id="1_cwvg5"]
[ext_resource type="Texture2D" uid="uid://caeqoc6wx8toy" path="res://assets/sprites/ui/BG1.png" id="1_hrti0"]
[ext_resource type="Texture2D" uid="uid://c6bthhmao5fyh" path="res://assets/sprites/ui/图片大门.png" id="2_q7typ"]
[ext_resource type="FontFile" uid="uid://drt448qncx27p" path="res://assets/fonts/dingliezhuhaifont-20240831GengXinBan)-2.ttf" id="3_q7typ"]
[ext_resource type="PackedScene" uid="uid://dj7b5vssydifa" path="res://src/UI/Panels/SavePanel.tscn" id="3_wrf65"]
@@ -21,7 +21,9 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("1_hrti0")
expand_mode = 1
stretch_mode = 6
texture = ExtResource("2_q7typ")
[node name="Logo" type="TextureRect" parent="." unique_id=1485724026]
layout_mode = 1