# VERTICAL SLICE - NOT FOR PRODUCTION # Validation Question: 玩家能否无指导在一场完整战斗中经历「开战→挖掘规划→轮末结算逐行兑现→胜/负」并逐行归因(P2) # Date: 2026-09-10 # 数据配置 StatusEffectTable schema(增益状态 回填值;行 = Dictionary,键 effect_id;Rule 4 豁免)。 # 依据 design/archive/gdd-2026-09-14/b3-status-effect.md "StatusEffectTable Schema 定稿"。 class_name StatusEffectTable extends Resource @export var rows: Array = [] # Array[Dictionary] const TARGET_SIDES := ["hero", "enemy"] const UNITS := ["percent", "flat", "ac"] # 2026-09-16 护甲等级掷点批增 ac——AC 阈值轴效果(ac_up),非池百分比非定点值 const STACK_POLICIES := ["stack", "refresh", "independent"] func validate() -> Array: var errs: Array = [] if rows.is_empty(): errs.append({"category": "empty_table", "message": "StatusEffectTable 为空"}) return errs var seen := {} for row in rows: var eid: String = row.get("effect_id", "") if eid == "": errs.append({"category": "domain", "message": "effect_id 缺失/空"}) continue if seen.has(eid): errs.append({"category": "dup_key", "message": "effect_id 重复: %s" % eid}) seen[eid] = true if String(row.get("display_name", "")) == "": errs.append({"category": "domain", "message": "%s display_name 空" % eid}) if not TARGET_SIDES.has(row.get("target_side", "")): errs.append({"category": "enum", "message": "%s target_side 出域" % eid}) var unit: String = row.get("unit", "") if not UNITS.has(unit): errs.append({"category": "enum", "message": "%s unit 出域" % eid}) if not STACK_POLICIES.has(row.get("stack_policy", "")): errs.append({"category": "enum", "message": "%s stack_policy 出域" % eid}) var m: int = int(row.get("magnitude", 0)) # 跨字段:percent ∈ [-100,100] 且 ≠0 / flat ≥ 1 / ac ∈ [-20,20] 且 ≠0(AC 阈值轴——幅度域独立,防呆上限 20) if unit == "percent" and (m == 0 or m < -100 or m > 100): errs.append({"category": "cross_field", "message": "%s percent magnitude 域错: %d" % [eid, m]}) if unit == "flat" and m < 1: errs.append({"category": "cross_field", "message": "%s flat magnitude 须 ≥1: %d" % [eid, m]}) if unit == "ac" and (m == 0 or m < -20 or m > 20): errs.append({"category": "cross_field", "message": "%s ac magnitude 域错([-20,20] 且 ≠0): %d" % [eid, m]}) var dur: int = int(row.get("duration_settlements", 0)) if dur < 1 or dur > 99: errs.append({"category": "domain", "message": "%s duration_settlements 越域 [1,99]: %d" % [eid, dur]}) var ms: int = int(row.get("max_stack", 0)) if ms < 1 or ms > 16: errs.append({"category": "domain", "message": "%s max_stack 越域 [1,16]: %d" % [eid, ms]}) return errs func row_by_id(effect_id: String) -> Dictionary: for row in rows: if row.get("effect_id", "") == effect_id: return row return {}