feat: 弟子定时招募+入宗分流,完成 D3(Disciple/DiscipleManager)

This commit is contained in:
2026-08-05 23:50:30 +08:00
parent cda7a09a09
commit df52a0b22f
7 changed files with 330 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
## 弟子数据模型(纯数据,不挂在场景树上)。
## 生成时决定的属性(姓名/资质/灵根)不可变,成长属性(境界)由 D5 修炼系统推进。
class_name Disciple # 全局类名:全项目可直接用 Disciple.new()
extends Resource # Resource = 轻量纯数据对象,可序列化(D8 存档用)
## 资质四类(入宗分流结果)。
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 用)
# —— 实例字段 ——
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 is_heavenly: bool = false # 天灵根标记(3% 概率)
var realm_index: int = 0 # 大境界索引(0=练气)
var sub_realm_index: int = 0 # 小境界索引(练气层数-1
# —— 辅助函数:把数据翻译成给人看的文本 ——
func get_aptitude_name() -> String:
return APTITUDE_NAMES[aptitude]
func get_roots_text() -> String:
var names: Array[String] = []
for root in roots:
names.append(ROOT_NAMES[root])
return "".join(names)
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
View File
@@ -0,0 +1 @@
uid://cuybveud5w308
+116
View File
@@ -0,0 +1,116 @@
## 弟子管理器(Autoload 单例)。
## 负责弟子定时招募、入宗分流与宗门名录维护。
extends Node
## 名录变化时发出(增删/重置)。
signal disciples_changed
## 宗门弟子名录。
var disciples: Array[Disciple] = []
## 招募间隔(游戏天数,每满间隔自动招募一名弟子)。
const RECRUIT_INTERVAL_DAYS := 30
## 入宗分流权重(按资质四类):下品 / 中品 / 上品 / 天骄。
const APTITUDE_WEIGHTS: Array[int] = [45, 35, 15, 5]
## 天灵根生成概率(3%)。
const HEAVENLY_CHANCE := 0.03
## 姓氏池。
const SURNAMES: Array[String] = [
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
]
## 名用字池(修仙风)。
const GIVEN_CHARS: Array[String] = [
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "屿", "", "", "", "",
]
## 距下次招募的剩余游戏天数。
var _days_until_recruit := RECRUIT_INTERVAL_DAYS
## 下一位弟子的 ID(自增,重置归零)。
var _next_id := 1
func _ready() -> void:
# 挂到时间系统上:每日推进时倒计时,满间隔自动招募
TimeSystem.day_passed.connect(_on_day_passed)
## 每日推进:招募倒计时减 1,归零时自动招募一名弟子。
func _on_day_passed(_year: int, _month: int, _day: int) -> void:
_days_until_recruit -= 1
if _days_until_recruit <= 0:
_days_until_recruit = RECRUIT_INTERVAL_DAYS
recruit()
## 招募一名弟子:随机生成属性、按资质分流后加入名录,返回该弟子。
func recruit() -> Disciple:
var d := Disciple.new()
d.id = _next_id
_next_id += 1
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()
disciples.append(d)
disciples_changed.emit()
print("弟子入宗:%s %d岁 | %s资质%s | %s灵根 | %s" % [
d.name, d.age, d.get_aptitude_name(),
"·天灵根" if d.is_heavenly else "",
d.get_roots_text(), d.get_realm_text(),
])
return d
## 移除弟子(逐出/陨落)。
## @param d: 要移除的弟子
func remove_disciple(d: Disciple) -> void:
disciples.erase(d)
disciples_changed.emit()
## 清空名录(新游戏开局调用),招募倒计时复位。
func reset() -> void:
disciples.clear()
_next_id = 1
_days_until_recruit = RECRUIT_INTERVAL_DAYS
disciples_changed.emit()
## 随机生成姓名:单姓 + 1~2 个名用字。
func _generate_name() -> String:
var surname := SURNAMES[randi() % SURNAMES.size()]
var given := GIVEN_CHARS[randi() % GIVEN_CHARS.size()]
if randf() < 0.5:
given += GIVEN_CHARS[randi() % GIVEN_CHARS.size()]
return surname + given
## 随机生成灵根。
## 天灵根:固定 1 根五行;普通弟子:1~3 根互不重复(根数越少修炼越快)。
## @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 pool := Disciple.SpiritRoot.values()
pool.shuffle()
var result: Array[Disciple.SpiritRoot] = []
for i in count:
result.append(pool[i])
return result
## 按权重掷资质(入宗分流)。
func _roll_aptitude() -> Disciple.Aptitude:
var total := 0
for w in APTITUDE_WEIGHTS:
total += w
var roll := randi() % total
for i in APTITUDE_WEIGHTS.size():
if roll < APTITUDE_WEIGHTS[i]:
return i as Disciple.Aptitude
roll -= APTITUDE_WEIGHTS[i]
return Disciple.Aptitude.ORDINARY
+1
View File
@@ -0,0 +1 @@
uid://d2aj0gbvb6p4w
+2
View File
@@ -7,6 +7,8 @@ func _ready() -> void:
add_to_group("game_scene")
# 应用用户设置中的默认流速
TimeSystem.apply_default_speed()
# 新游戏清空弟子名录与招募倒计时(读档流程接入后由存档还原)
DiscipleManager.reset()
## 顶部 HUD 的返回主菜单请求。
func _on_top_bar_hud_sign_return_mainmenu() -> void: