## VERTICAL SLICE - NOT FOR PRODUCTION ## 元进度表 schema:Boss 钥石两档/属性换算/Y 刷新升级三行族的类型化读取(行值 provisional;垂直切片验证:钥石换永久强化下局生效)。 ## 消费面一律走 ConfigDB.meta_* 访问器,禁直读行集。 ## 道具解锁条件不在本表:单一事实源住 treasure_items 行内(unlock_keystone_cost + unlock_requires)。 class_name MetaTable extends Resource @export var boss_keystone: Array[Dictionary] = [] # Array[Dictionary] 键 level_index @export var conversion: Array[Dictionary] = [] # Array[Dictionary] 键 attr @export var attune_refresh_upgrade: Array[Dictionary] = [] # Array[Dictionary] 键 level——Y 刷新升级行族 const FORGE_ATTRS := ["max_hp", "atk", "armor_class"] # 三属性轴词表(conversion 行键域=forge 词表名) func validate() -> Array: var errs: Array[Dictionary] = [] # 行族空护栏(三族皆为 ConfigDB 消费面——缺族即致命) for family in ["boss_keystone", "conversion", "attune_refresh_upgrade"]: if get(family).is_empty(): errs.append({"category": "empty_table", "message": "MetaTable 行族为空: %s" % family}) errs.append_array(_validate_boss_keystone()) errs.append_array(_validate_conversion()) errs.append_array(_validate_attune_refresh()) return errs ## boss_keystone 行族域:level_index 唯一 + 连续从 1 + 两档域 + first ≥ repeat(首杀全量、重复小额恒定) func _validate_boss_keystone() -> Array[Dictionary]: var errs: Array[Dictionary] = [] var seen_li := {} for row in boss_keystone: var li: int = int(row.get("level_index", 0)) if seen_li.has(li): errs.append({"category": "dup_key", "message": "boss_keystone level_index 重复: %d" % li}) seen_li[li] = true var first: int = int(row.get("first_kill", -1)) var rep: int = int(row.get("repeat_kill", -1)) if first < 1 or first > 999 or rep < 0 or rep > 999: errs.append({"category": "domain", "message": "boss_keystone L%d 两档金额越域 first [1,999] / repeat [0,999]: %d/%d" % [li, first, rep]}) if first < rep: errs.append({"category": "cross_field", "message": "boss_keystone L%d 违反 first_kill(%d) ≥ repeat_kill(%d)——首杀全量、重复杀小额" % [li, first, rep]}) for i in boss_keystone.size(): var li_at: int = int(boss_keystone[i].get("level_index", 0)) if li_at != i + 1: errs.append({"category": "structural", "message": "boss_keystone level_index 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, li_at]}) break return errs ## conversion 行族域(属性换算):attr 词表与 forge 一致 + 唯一 + 覆盖恰三 + 平移量域 [0,100] ## (无 workshop_items 行族——解锁混合制:条件谓词挂 treasure_items 行内;本表不校验秘宝解锁,单点=TreasureItemTable.validate) func _validate_conversion() -> Array[Dictionary]: var errs: Array[Dictionary] = [] var seen_conv := {} for row in conversion: var cattr: String = row.get("attr", "") if not FORGE_ATTRS.has(cattr): errs.append({"category": "enum", "message": "conversion attr 出域 {max_hp, atk, armor_class}: %s" % cattr}) if seen_conv.has(cattr): errs.append({"category": "dup_key", "message": "conversion attr 重复: %s" % cattr}) seen_conv[cattr] = true var shift: int = int(row.get("per_level_shift_pct", -1)) if shift < 0 or shift > 100: errs.append({"category": "domain", "message": "conversion %s per_level_shift_pct 越域 [0,100]: %d" % [cattr, shift]}) if not conversion.is_empty(): for conv_key in FORGE_ATTRS: if not seen_conv.has(conv_key): errs.append({"category": "coverage", "message": "conversion 缺属性行: %s(三行与 forge 词表一致)" % conv_key}) return errs ## attune_refresh_upgrade 行族域(Y 刷新升级):level 唯一 + 连续从 1 + charges/cost 域 func _validate_attune_refresh() -> Array[Dictionary]: var errs: Array[Dictionary] = [] var seen_al := {} for row in attune_refresh_upgrade: var al: int = int(row.get("level", -1)) if seen_al.has(al): errs.append({"category": "dup_key", "message": "attune_refresh_upgrade level 重复: %d" % al}) seen_al[al] = true var ach: int = int(row.get("refresh_charges", -1)) if ach < 1 or ach > 9: errs.append({"category": "domain", "message": "attune_refresh_upgrade L%d refresh_charges 越域 [1,9]: %d" % [al, ach]}) var acost: int = int(row.get("keystone_cost", -1)) if acost < 1 or acost > 999: errs.append({"category": "domain", "message": "attune_refresh_upgrade L%d keystone_cost 越域 [1,999]: %d" % [al, acost]}) for i in attune_refresh_upgrade.size(): var al_at: int = int(attune_refresh_upgrade[i].get("level", 0)) if al_at != i + 1: errs.append({"category": "structural", "message": "attune_refresh_upgrade level 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, al_at]}) break return errs # ---- 行族访问器(自 ConfigDB 归位——行集解析单点;消费面 db.crossrun.meta. 直连)---- ## Boss 钥石两档行单点(键 level_index;缺行=空字典) func boss_keystone_row(level_index: int) -> Dictionary: for row in boss_keystone: if int(row.get("level_index", -1)) == level_index: return row return {} ## Y 刷新升级行单点(键 = 等级,缺行返回空字典=未购/已满级合法态) func attune_refresh_row(level: int) -> Dictionary: for row in attune_refresh_upgrade: if int(row.get("level", -1)) == level: return row return {}