## 弟子数据模型(纯数据,不挂在场景树上)。 ## 生成时决定的属性(姓名/资质/灵根)不可变,成长属性(境界)由 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 ROOT_NAMES: Array[String] = ["金", "木", "水", "火", "土"] const REALM_NAMES: Array[String] = ["练气", "筑基", "金丹", "元婴", "化神"] # 按 realm_index 索引 # —— 修炼数值一律读 GameConfig(资质倍率/天灵根加成/速度等)—— # —— 实例字段 —— var id: int = 0 # 唯一编号(DiscipleManager 分配) var name: String = "" var age: int = 0 var aptitude: Aptitude = Aptitude.ORDINARY # 资质(入宗分流结果) var roots: Array[SpiritRoot] = [] # 普通弟子 1~5 根;天灵根固定 1 根 var is_heavenly: bool = false # 天灵根标记(仅天骄资质,概率见配置) var join_year: int = 0 # 入宗年份(0 = 未入宗/候选),accept 时快照 var join_month: int = 0 # 入宗月份 var join_day: int = 0 # 入宗日 var realm_index: int = 0 # 大境界索引(0=练气) var sub_realm_index: int = 0 # 小境界索引(练气层数-1) var cultivation_exp: float = 0.0 # 修为(float 可积累小数,D5 每日结算) var hunger_days: int = 0 # 断粮累计天数(≥阈值离宗,方案 B) # —— 辅助函数:把数据翻译成给人看的文本 —— 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) ## 灵根数量灵气容量倍率(根数越少灵气越纯、修炼越快,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() ## 境界显示文本,如 "练气5层"、"筑基初期"。 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年2月3日";未入宗返回空串。 func get_join_date_text() -> String: if join_year <= 0: return "" return "%d年%d月%d日" % [join_year, join_month, join_day] ## 序列化为字典(D8 存档用,枚举转 int)。 func to_dict() -> Dictionary: var roots_data: Array[int] = [] for r in roots: roots_data.append(int(r)) return { "id": id, "name": name, "age": age, "aptitude": int(aptitude), "roots": roots_data, "is_heavenly": is_heavenly, "join_year": join_year, "join_month": join_month, "join_day": join_day, "realm_index": realm_index, "sub_realm_index": sub_realm_index, "cultivation_exp": cultivation_exp, "hunger_days": hunger_days, } ## 从字典还原(D8 读档用)。 ## @param data: to_dict 产生的字典 static func from_dict(data: Dictionary) -> Disciple: var d := Disciple.new() d.id = int(data["id"]) d.name = str(data["name"]) d.age = int(data["age"]) d.aptitude = int(data["aptitude"]) as Aptitude d.roots = [] for r in data["roots"]: d.roots.append(int(r) as SpiritRoot) d.is_heavenly = bool(data["is_heavenly"]) d.join_year = int(data["join_year"]) d.join_month = int(data["join_month"]) d.join_day = int(data["join_day"]) d.realm_index = int(data["realm_index"]) d.sub_realm_index = int(data["sub_realm_index"]) d.cultivation_exp = float(data["cultivation_exp"]) d.hunger_days = int(data["hunger_days"]) return d ## 本层修炼进度文本,如 "1234 / 2000"(当前修为 / 本层门槛)。 ## 练气圆满(13 层)返回"练气圆满";筑基及以上返回 "1234 / 6000"(小境门槛),圆满返回"筑基圆满"。 func get_cultivation_progress_text() -> String: if realm_index == 0: if sub_realm_index >= GameConfig.level_thresholds.size(): return "练气圆满" return "%d / %d" % [int(cultivation_exp), int(GameConfig.level_thresholds[sub_realm_index])] if sub_realm_index >= GameConfig.realm_sub_thresholds.size(): return REALM_NAMES[realm_index] + "圆满" return "%d / %d" % [int(cultivation_exp), int(GameConfig.realm_sub_thresholds[sub_realm_index])] ## 当前大境界是否修为圆满(练气 = 13 层;筑基及以上 = 4 小境修满)。 ## 圆满后解锁"大境界突破"(玩家手动花费灵石)。 func is_realm_peak() -> bool: if realm_index == 0: return sub_realm_index >= GameConfig.level_thresholds.size() return sub_realm_index >= GameConfig.realm_sub_thresholds.size() \ and cultivation_exp >= GameConfig.realm_sub_thresholds[GameConfig.realm_sub_thresholds.size() - 1] ## 目标大境界索引(realm_index+1);化神圆满(最高)返回 -1 表示无可突破。 func get_next_realm_index() -> int: if realm_index + 1 >= REALM_NAMES.size(): return -1 return realm_index + 1 ## 大境界突破所需灵石(按目标大境界索引读配置);无可突破返回 -1。 func get_realm_breakthrough_cost() -> int: var next := get_next_realm_index() if next < 0: return -1 return GameConfig.realm_breakthrough_costs[next - 1]