schema 校验换代,数据行迁移前共存过渡(旧 hook/effect_kinds 校验保留,行为零变——冒烟 783 项 0 失败):
FeatTable:
- 行字段换代目标 hook/effects → triggers:[{on,when,do}](订阅哪个事件/什么条件/什么效果)
- triggers 校验收口 EffectEngine.validate_trigger_row 静态方法(单一事实源——事件/效果/fact/算子
四词表全引用 EffectEngine 闭集常量,禁本表复抄)
- 行键白名单扩 triggers/desc(文案表值化预留)
- 悬空引用校验:do.value_from/delta_from/mult_from/cap_from 引用的行字段不存在=加载致命
- 🔴 流派扫雷触发铁律新形态:每流派 ≥1 行订阅扫雷侧事件(MINE_EVENTS=dig_reveal/dig_paid/
flag_hit/mine_hit/flag_settle/round_end/reward_roll)或旧形态 hook∈MINE_HOOKS——流派级聚合判定
- triggers 与 hook 禁并存(换代单形态);缺两者=行错误
TreasureItemTable:
- 行键白名单扩 triggers/desc;passive 行 triggers 与 effect_kinds 禁并存
- 主动件 kind 词族换代挂账:新词 reveal_tiles/preview/grant_ap/remove_mines/refresh_pick
(效果引擎 ACTIVE_KINDS 同名闭集)入 EFFECT_KINDS 与旧词共存至 T4 迁移完成
EffectEngine 补 validate_trigger_row 静态校验面(schema 共用)。
fact 条件词汇 9 项封闭落码核对:迁移设计全部现状条件可装入 9 项(matchup/is_first_dig_of_battle/
terrain_kind/target_armor_class/flags_count/charge_layers/nest_count/round_index/counter)——
未触发闭集缺口停机点。
158 lines
9.9 KiB
GDScript
158 lines
9.9 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||
# Validation Question: 七核心流派各 ≥3 件入局内随机渠道后,标签+档位激活引擎能否机械判「成型」、
|
||
# 专长带能否挂进令牌池稀有/罕见档随机投放(P0——迭代 12 双层 BD 实施批 T1)
|
||
# Date: 2026-10-04(双层 BD 实施批 T1——任务书五裁定稿;设计权威 双层BD体系-整合定稿-2026-10-03 v3)
|
||
# 概念指路:本表的专长,与 adventure.tres 的属性值提升、资源,同属一个对象——
|
||
# 「奇物」(一次冒险内各渠道给予玩家的增益总称)。定义见 design/gdd/systems/冒险循环/奇物.md。
|
||
# 它们是它分类轴上的枚举(专长 / 属性值提升 / 资源),不是三套系统;本表承载「专长」(专长 Feat)的逐项定义。
|
||
# (2026-10-05 命名统一 + 分类重构:旧称「流派件」→「规则改写型特性」→ 现定名「专长」;
|
||
# 表名与 feat_id 沿用历史命名,与统一词族对齐归后续批次——见 06-待办清单「命名统一」条目。
|
||
# 目标渠道:专长走关底 Boss 击败后专属三选一(不新增节点类型),见奇物文档 2.1 节。)
|
||
# 数据配置 FeatTable schema(奇物·专长定义表;行 = Dictionary 键 feat_id,Rule 4 豁免
|
||
# 定义表——TreasureItemTable 先例)。
|
||
# 行字段:feat_id 主键 / display_name / rarity ∈ {common, rare, rarest}(对齐令牌池三档命名——
|
||
# 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档=「挂稀有/罕见档」
|
||
# 追认 b 接线口径)/ archetype ∈ ARCHETYPES 七流派标签 / hook ∈ HOOKS 挂点枚举(结算段槽——整合定稿
|
||
# §2.1 哈迪斯恩赐槽同构)/ effects Dictionary(hook 消费参数,provisional 投值)。
|
||
# 正负双修(整合定稿 B2 判据):effects 允许负向键(cost_* 族)——纯增益件须专项论证(反例 B-3),加载期
|
||
# 仅校验键域不禁纯增益(专项论证件以 positive_only 批注登记,人工清单呈报)。
|
||
# 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二
|
||
# (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 FeatsEngine。
|
||
# 🔴 层级纪律(任务书红线 2):专长只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
|
||
# (treasure_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
|
||
# 违反=红线①触碰面)。
|
||
class_name FeatTable
|
||
extends Resource
|
||
|
||
@export var rows: Array = [] # Array[Dictionary] 键 feat_id
|
||
|
||
## 流派标签词表(七核心——喂雷/淘金不在本批,R5 甲/缓议)
|
||
const ARCHETYPES := ["magic", "pierce", "normal", "dig", "flag", "charge", "devour"]
|
||
|
||
## 稀有度词表(对齐令牌池三档;投放档映射 relic→rare / rarest→rarest)
|
||
const RARITIES := ["common", "rare", "rarest"]
|
||
|
||
## 挂点枚举(结算段槽——首批 23 点位;每 hook 恰一流派域消费,T2-T6 接线)
|
||
## 内容数据驱动扩展批 T2 挂账:hook 词族随 T3 专长迁移退役(triggers 事件订阅形态取代——
|
||
## 旧字段校验保留共存至迁移完成,过渡期两形态同行校验)。
|
||
const HOOKS := [
|
||
# 魔法流
|
||
"hero_attack_rider", # 普攻命中后追加必中魔法伤(奥术余烬/魔能共鸣)
|
||
"clamp_modifier", # 克制点直调(魔网织者/湛蓝誓约/猎手刺剑)
|
||
"first_dig_spell", # 每关首次开格必出魔法矢(魔能共鸣第二效果)
|
||
# 穿刺流
|
||
"kill_overflow", # 击杀溢出弹射(贯穿射击)
|
||
"dig_count_segments", # 开格计数转攻击段数(连珠矢)
|
||
"roll_discount", # 折扣档改写(猎弱本能前移一档)
|
||
# 普攻流
|
||
"round_dig_bonus", # 轮内安全开格数转攻击加成(矿工的执拗;踩雷清零=mine_hit 监听同口)
|
||
"hit_trade", # 命中交换(矿工重锤——正负双修原生形态)
|
||
"armor_roll_rewrite", # 免掷骰恒折扣(专注)
|
||
"heavy_debuff", # 命中重甲附加护甲裂解(碎甲震击)
|
||
# 开格流
|
||
"dig_yield_mult", # 开格产出乘区(贪婪矿灯/矿脉直觉/赌徒的血签——正负双向)
|
||
"deep_dig", # 深层资源掘取(深挖钻头——R4 甲非信息税形态:开掘额外 AP 代价)
|
||
# 标旗流
|
||
"flag_resource", # 标中雷获格面资源(雷区图谱)
|
||
"nest_aura", # 控制巢穴数转伤害光环(猎巢人)
|
||
"flag_all_hit", # 同轮全中旗伤倍增(完美布防)
|
||
"flag_strike", # 轮末旗伤开单(战旗军规——复用 board_typed)
|
||
# 蓄力流
|
||
"ap_carry", # 轮末 AP 结转蓄力(整备军备——改写 cleared 作废口径)
|
||
"charge_shield", # 蓄力层转减伤(铁壁整备)
|
||
"charge_spike", # 满层 spike(厚积薄发)
|
||
# 吞噬流
|
||
"terrain_refund", # 受地形伤掉落资源补偿(地脉采撷——伤害仍发生)
|
||
"terrain_dig_double", # 挖开伤害型地形格双产出(荆棘编织者)
|
||
"flag_neutralize", # 标中旗中和相邻伤害型地形格(净化工兵——🔴 R4 甲仅限伤害型)
|
||
"variant_counter", # 受地形伤积层轮末反打(熔火之躯——触发键不按地形种类特化)
|
||
]
|
||
|
||
## 扫雷结算触发点 hook 集(🔴 红线①承载:每流派 ≥1 行 hook 命中本集——加载校验)
|
||
const MINE_HOOKS := ["first_dig_spell", "dig_count_segments", "round_dig_bonus", "dig_yield_mult",
|
||
"deep_dig", "flag_resource", "nest_aura", "flag_all_hit", "flag_strike", "ap_carry",
|
||
"terrain_refund", "terrain_dig_double", "flag_neutralize", "variant_counter"]
|
||
|
||
## effects 键白名单(🔴 零裸 flat 同族护栏——机制轴禁无条件属性加项;键出域=加载致命)
|
||
## 全部条件触发/机制修正参数;cost_* 族=正负双修负向面
|
||
const EFFECT_KEYS := ["value", "value2", "tier_value", "per_stack", "cap", "ap_cost", "chance",
|
||
"mult", "cost_mult", "cost_flat", "polarity", "spell_kind", "segment_cap", "discount_shift",
|
||
"trade_atk", "trade_hit", "shield_per_layer", "spike_mult", "layers_to_shield",
|
||
"neutralize_range", "counter_damage", "resource_kind", "rider_kind", "note"]
|
||
|
||
## ---- 内容数据驱动扩展批 T2 新形态词汇(triggers 事件订阅行)----
|
||
## 行字段换代目标:hook/effects → triggers: [{on, when?, do}]——订阅哪个事件/什么条件/什么效果。
|
||
## 事件/效果/fact/算子四词表全部引用 EffectEngine 闭集常量(单一事实源,禁本表复抄)。
|
||
const TRIGGER_KEYS := ["on", "when", "do"]
|
||
|
||
|
||
func _validate_triggers(rid: String, row: Dictionary, triggers: Array, errs: Array) -> bool:
|
||
return EffectEngine.validate_trigger_row(rid, row, triggers, errs)
|
||
|
||
|
||
func validate() -> Array:
|
||
var errs: Array = []
|
||
if rows.is_empty():
|
||
return errs # 空表合法态(T1 基建先行——T2 起逐流派填行)
|
||
var seen := {}
|
||
# 流派扫雷覆盖聚合(🔴 红线①铁律——两形态共存判定:triggers 行按扫雷侧事件、hook 行按 MINE_HOOKS)
|
||
var arch_mine := {} # archetype → bool
|
||
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)]})
|
||
var arch := String(row.get("archetype", ""))
|
||
if not ARCHETYPES.has(arch):
|
||
errs.append({"category": "enum", "message": "%s archetype 出域 %s" % [rid, str(ARCHETYPES)]})
|
||
var has_triggers: bool = row.has("triggers")
|
||
var has_hook: bool = row.has("hook")
|
||
if has_triggers:
|
||
if String(row.get("hook", "")) != "":
|
||
errs.append({"category": "domain", "message": "%s triggers 与 hook 并存(换代单形态——迁移期禁双挂)" % rid})
|
||
if _validate_triggers(rid, row, row.get("triggers", []) as Array, errs):
|
||
arch_mine[arch] = true
|
||
elif has_hook:
|
||
var hook := String(row.get("hook", ""))
|
||
if not HOOKS.has(hook):
|
||
errs.append({"category": "enum", "message": "%s hook 出域(挂点枚举封闭): %s" % [rid, hook]})
|
||
if MINE_HOOKS.has(hook):
|
||
arch_mine[arch] = true
|
||
else:
|
||
errs.append({"category": "domain", "message": "%s 缺 triggers/hook(换代后行必须声明订阅)" % rid})
|
||
for k in row.keys():
|
||
if not ["feat_id", "display_name", "rarity", "archetype", "hook", "effects", "triggers", "desc", "note"].has(String(k)):
|
||
errs.append({"category": "zero_flat", "message": "%s 行键出白名单: %s" % [rid, String(k)]})
|
||
var fx: Dictionary = row.get("effects", {}) as Dictionary
|
||
for ek in fx.keys():
|
||
if not EFFECT_KEYS.has(String(ek)):
|
||
errs.append({"category": "zero_flat", "message": "%s effects 键出白名单: %s(机制轴禁无条件属性加项)" % [rid, String(ek)]})
|
||
# 🔴 红线① 扫雷触发点铁律:**有行的流派**各 ≥1 行订阅扫雷侧事件(triggers 新形态)或
|
||
# hook ∈ MINE_HOOKS(旧形态过渡)
|
||
for arch in archs_with_rows():
|
||
if not bool(arch_mine.get(arch, false)):
|
||
errs.append({"category": "load_bearing", "message": "流派 %s 无扫雷结算触发点行(🔴 红线①铁律——每流派 ≥1 件挂扫雷端)" % String(arch)})
|
||
return errs
|
||
|
||
|
||
func archs_with_rows() -> Array:
|
||
var out := {}
|
||
for row in rows:
|
||
out[String(row.get("archetype", ""))] = true
|
||
return out.keys()
|
||
|
||
|
||
func row_by_id(feat_id: String) -> Dictionary:
|
||
for row in rows:
|
||
if String(row.get("feat_id", "")) == feat_id:
|
||
return row
|
||
return {}
|