按 code-conventions §1.4.1 第三轮定稿执行:core 22+schemas 18+presentation 根 14+views 28,全部头注 #→##、删日期/变更叙事/GDD 与架构反向链接/字段与域清单/机制描述,保留职责摘要+真实使用约束(防事故禁令/单一入口/信号契约每信号一行)。main.gd 31→5 行、save_manager 45→5 行、adventure_runner 37→5 行为最大单件。子代理分模块执行(波一 core+schemas、波二 presentation+views,并发≤2)。验收=tools/verify_comment_only_change.py 逐字节校验(82 文件头注区外逐行一致=零行为变更)+audit_file_headers 全绿;纯注释批免冒烟(先例 5843270)
56 lines
2.5 KiB
GDScript
56 lines
2.5 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||
## 专长(奇物·Feat)定义表 schema:逐 feat_id 行订阅式效果声明的类型化读取(空表合法态;垂直切片验证:订阅行经效果引擎统一解释执行)。
|
||
## 🔴 层级纪律:专长只走局内随机渠道(Boss 三选一/凭证开启)——本表行永不入同调位表/局外树。
|
||
## triggers 订阅行四词表封闭校验单点在 EffectEngine.validate_trigger_row——本表不自建第二套校验。
|
||
## 事件族命名仅系设计侧分组工具:不上数据行、不上卡面。
|
||
class_name FeatTable
|
||
extends Resource
|
||
|
||
@export var rows: Array[Variant] = [] # Array[Dictionary] 键 feat_id
|
||
|
||
## 稀有度词表(四级——与令牌池 TIERS 同名词族;令牌档 = rarity 直映射)
|
||
const RARITIES := ["common", "excellent", "rare", "legendary"]
|
||
|
||
## 行键白名单(🔴 零裸 flat 同族护栏——键出域=加载致命)
|
||
const ROW_KEYS := ["feat_id", "display_name", "rarity", "cap", "triggers", "desc", "note"]
|
||
|
||
## trigger 行键(订阅行三字段:on/when?/do)
|
||
const TRIGGER_KEYS := ["on", "when", "do"]
|
||
|
||
|
||
func validate() -> Array:
|
||
var errs: Array[Variant] = []
|
||
if rows.is_empty():
|
||
return errs # 空表合法态(T1 基建先行——逐件填行)
|
||
var seen := {}
|
||
for row in rows:
|
||
var rid: String = row.get("feat_id", "")
|
||
if rid == "":
|
||
errs.append({"category": "domain", "message": "feat_id 空"})
|
||
continue
|
||
if seen.has(rid):
|
||
errs.append({"category": "dup_key", "message": "feat_id 重复: %s" % rid})
|
||
continue
|
||
seen[rid] = true
|
||
if String(row.get("display_name", "")) == "":
|
||
errs.append({"category": "domain", "message": "%s display_name 空" % rid})
|
||
if not RARITIES.has(String(row.get("rarity", ""))):
|
||
errs.append({"category": "enum", "message": "%s rarity 出域 %s" % [rid, str(RARITIES)]})
|
||
if row.has("cap") and int(row.get("cap", 1)) < 1:
|
||
errs.append({"category": "domain", "message": "%s cap 出域 [1,∞): %d" % [rid, int(row.get("cap", 1))]})
|
||
if not row.has("triggers"):
|
||
errs.append({"category": "domain", "message": "%s 缺 triggers(订阅形态唯一合法行形)" % rid})
|
||
else:
|
||
EffectEngine.validate_trigger_row(rid, row, row.get("triggers", []) as Array, errs)
|
||
for k in row.keys():
|
||
if not ROW_KEYS.has(String(k)):
|
||
errs.append({"category": "zero_flat", "message": "%s 行键出白名单: %s" % [rid, String(k)]})
|
||
return errs
|
||
|
||
|
||
func row_by_id(feat_id: String) -> Dictionary:
|
||
for row in rows:
|
||
if String(row.get("feat_id", "")) == feat_id:
|
||
return row
|
||
return {}
|