Files
SectSimulator/src/Character/Disciple.gd
T

138 lines
5.9 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 弟子数据模型(纯数据,不挂在场景树上)。
## 生成时决定的属性(姓名/资质/灵根)不可变,成长属性(境界)由 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]