59 lines
2.7 KiB
GDScript
59 lines
2.7 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||
## 增益状态表 schema:逐 effect_id 行的类型化读取(垂直切片验证:完整战斗逐行归因)。
|
||
## validate() 违例加载期致命(fail-fast);表运行期只读,调参只走 data/tables 表值。
|
||
class_name StatusEffectTable
|
||
extends Resource
|
||
|
||
@export var rows: Array[Dictionary] = [] # Array[Dictionary]
|
||
|
||
const TARGET_SIDES := ["hero", "enemy"]
|
||
const UNITS := ["percent", "flat", "ac"] # ac——AC 阈值轴效果(ac_up),非池百分比非定点值
|
||
const STACK_POLICIES := ["stack", "refresh", "independent"]
|
||
|
||
|
||
func validate() -> Array:
|
||
var errs: Array[Dictionary] = []
|
||
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 {}
|