merge: M-3迭代7魔法道具内容+元进度数值标定 T0-T8全落——AuxItemTable六行+掉落投放(解锁门控空集零投放)+库存四步受理+三选一奖励节点+HUD两步交互+叠加层呈现+工坊封存呈现+换算率复核读数(6/9/1 vs 实测1.7/4.1/0.0 U1呈报);重闸全绿(冒烟577/0+五探针+单测12套+doc三闸熵增零新增+机检11/11+MC剥additive 0/400逐位);出口=T9目检(检查单已交);台账259-263
# Conflicts: # game/presentation/views/node_overlay.gd
This commit is contained in:
commit
fd39a58aee
35 files changed
+1990
-19
No files matched your search
@@ -0,0 +1,109 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Validation Question: 挖掘期撞上推理断头时,玩家能否从掉落池捡到魔法道具、在关键时刻花掉买回情报或行动点(P0)
|
||||
# Date: 2026-09-29(迭代 7 T1 数据面——魔法道具内容批;设计权威 design/gdd/systems/排雷循环/魔法道具.md v0.4+
|
||||
# + registry aux_items 六行 mvp_content;2026-09-29 用户拍板:①乙 探宝罗盘退役留痕 ④甲 显影尘/地穴全图卷失义件
|
||||
# 六行全建零投放「已解锁·能力封存中」)
|
||||
# 数据配置 AuxItemTable schema(魔法道具 回填 owner)。
|
||||
# 行 = Dictionary,键 item_id(Rule 4 豁免:定义表——registry aux_items Rule 4 豁免先例)。
|
||||
# 七字段(registry fields 全量):item_id 主键 / display_name / dimension_tags ⊆ 五维 非空 /
|
||||
# effect_kinds ⊆ {mine_reveal, reward_preview, ap_grant}(活性校验见下)/ target ∈ {none, area_3x3, board_wide} /
|
||||
# magnitude [0,999](仅 ap_grant 行消费,加载校验 ≥1)/ use_phase ∈ {active_dig}。
|
||||
# additive 两标记(迭代 7 T1——拍板①④的表内表达,非 registry fields 预登记字段的扩列随批登记):
|
||||
# retired = 退役留痕行(loot_compass——未开格类型微光常显覆盖预读价值,2026-09-29 用户拍板退役;
|
||||
# 行名保留=meta.tres workshop_items 六件词表恰全校验兼容,存档 item_unlocks 旧键无害;
|
||||
# 免活性校验、不入投放校验、不入 F2 覆盖面、奖励节点/掉落池排除)
|
||||
# deferred = 效果失义待重定行(probe_dust/catacomb_scroll——原显影半边随雾格移除失义,效果与目标
|
||||
# 随魔法道具整体重设计归 Alpha(2026-09-20 用户拍板);免 effect_kinds 非空校验、不入投放与 F2)
|
||||
# 承重护栏(魔法道具 GDD §结构冻结,schema 校验强制不靠运行时拦截):
|
||||
# 真视窄域——effect_kinds 含 mine_reveal 的活行 target 必须 area_3x3(真视一次最多 3×3,禁全图看雷);
|
||||
# board_wide 仅恢复推理原料类——target=board_wide 的活行 effect_kinds 不得含 mine_reveal(现行无此类活行,
|
||||
# 显影载体待 Alpha 重定后落位)。
|
||||
class_name AuxItemTable
|
||||
extends Resource
|
||||
|
||||
@export var rows: Array = [] # Array[Dictionary] 键 item_id
|
||||
|
||||
const DIMENSIONS := ["info", "risk", "action", "plan", "counter"]
|
||||
const EFFECT_KINDS := ["mine_reveal", "reward_preview", "ap_grant"]
|
||||
const TARGETS := ["none", "area_3x3", "board_wide"]
|
||||
const USE_PHASES := ["active_dig"]
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array = []
|
||||
if rows.is_empty():
|
||||
# 空表合法态(2026-09-17 用户拍板——切片期无道具内容;F2 覆盖检查仅对非空清单执行)
|
||||
return errs
|
||||
var seen := {}
|
||||
for row in rows:
|
||||
var iid: String = row.get("item_id", "")
|
||||
if iid == "":
|
||||
errs.append({"category": "domain", "message": "item_id 空"})
|
||||
continue
|
||||
if seen.has(iid):
|
||||
errs.append({"category": "dup_key", "message": "item_id 重复: %s" % iid})
|
||||
continue
|
||||
seen[iid] = true
|
||||
if String(row.get("display_name", "")) == "":
|
||||
errs.append({"category": "domain", "message": "%s display_name 空" % iid})
|
||||
var retired: bool = bool(row.get("retired", false))
|
||||
var deferred: bool = bool(row.get("deferred", false))
|
||||
# dimension_tags:五维词表 + 非空(退役/失义行仍须登记维度——语义面保留)
|
||||
var tags: Array = row.get("dimension_tags", [])
|
||||
if tags.is_empty():
|
||||
errs.append({"category": "domain", "message": "%s dimension_tags 空" % iid})
|
||||
for tag in tags:
|
||||
if not DIMENSIONS.has(String(tag)):
|
||||
errs.append({"category": "enum", "message": "%s dimension_tag 出域 %s: %s" % [iid, str(DIMENSIONS), str(tag)]})
|
||||
var kinds: Array = row.get("effect_kinds", [])
|
||||
var target: String = String(row.get("target", "none"))
|
||||
if not TARGETS.has(target):
|
||||
errs.append({"category": "enum", "message": "%s target 出域 %s: %s" % [iid, str(TARGETS), target]})
|
||||
var phase: String = String(row.get("use_phase", "active_dig"))
|
||||
if not USE_PHASES.has(phase):
|
||||
errs.append({"category": "enum", "message": "%s use_phase 出域 %s: %s" % [iid, str(USE_PHASES), phase]})
|
||||
if retired or deferred:
|
||||
# 退役/失义行:免 effect_kinds 非空与承重护栏校验(登记面保留,不入投放与 F2)
|
||||
continue
|
||||
# ---- 活行校验 ----
|
||||
if kinds.is_empty():
|
||||
errs.append({"category": "domain", "message": "%s effect_kinds 空(活行;失义件应标 deferred)" % iid})
|
||||
var kind_seen := {}
|
||||
for k in kinds:
|
||||
var kind: String = String(k)
|
||||
if not EFFECT_KINDS.has(kind):
|
||||
errs.append({"category": "enum", "message": "%s effect_kind 出域 %s: %s" % [iid, str(EFFECT_KINDS), kind]})
|
||||
if kind_seen.has(kind):
|
||||
errs.append({"category": "dup_key", "message": "%s effect_kind 重复: %s" % [iid, kind]})
|
||||
kind_seen[kind] = true
|
||||
# 承重护栏①真视窄域:mine_reveal 活行 target 必须 area_3x3(一次最多 3×3,禁全图看雷)
|
||||
if kind_seen.has("mine_reveal") and target != "area_3x3":
|
||||
errs.append({"category": "load_bearing", "message": "%s 真视窄域护栏:mine_reveal 行 target 必须 area_3x3,实得 %s(魔法道具 GDD 结构冻结)" % [iid, target]})
|
||||
# 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果
|
||||
if target == "board_wide" and kind_seen.has("mine_reveal"):
|
||||
errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 mine_reveal(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid})
|
||||
# magnitude:仅 ap_grant 行消费(≥1);非 ap_grant 活行恒 0
|
||||
var mag: int = int(row.get("magnitude", 0))
|
||||
if mag < 0 or mag > 999:
|
||||
errs.append({"category": "domain", "message": "%s magnitude 越域 [0,999]: %d" % [iid, mag]})
|
||||
if kind_seen.has("ap_grant") and mag < 1:
|
||||
errs.append({"category": "cross_field", "message": "%s ap_grant 行 magnitude 应 ≥1,实得 %d" % [iid, mag]})
|
||||
if not kind_seen.has("ap_grant") and mag != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s 非 ap_grant 活行 magnitude 应 0,实得 %d" % [iid, mag]})
|
||||
return errs
|
||||
|
||||
|
||||
# 活行词表(非 retired 非 deferred)——投放校验/奖励节点池/F2 覆盖面的唯一取数口径
|
||||
func active_rows() -> Array:
|
||||
var out: Array = []
|
||||
for row in rows:
|
||||
if not bool(row.get("retired", false)) and not bool(row.get("deferred", false)):
|
||||
out.append(row)
|
||||
return out
|
||||
|
||||
|
||||
func row_by_id(item_id: String) -> Dictionary:
|
||||
for row in rows:
|
||||
if String(row.get("item_id", "")) == item_id:
|
||||
return row
|
||||
return {}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dfhjthkhkvsbj
|
||||
@@ -12,7 +12,8 @@ extends Resource
|
||||
|
||||
@export var rows: Array[Dictionary] = [] # Array[Dictionary]
|
||||
|
||||
const CELL_TYPES := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp"] # 九型封闭(格面资源九型批 2026-09-20 八→九,词表 v1.1)——清单外加载拒绝
|
||||
const CELL_TYPES := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp", "aux_item"] # 十型(迭代 7 T1 魔法道具内容批扩值——registry aux_items 词表;aux 行 effect_id = item_id 双表校验键)
|
||||
const AUX_ITEM_TYPE := "aux_item" # aux 行标识(掉落投放行:挖开→战斗结算 grant 路由关卡域库存,不入增益容器)
|
||||
const POLARITIES := ["positive", "negative"]
|
||||
const POOL_TAGS := ["cell", "clear_default"] # cell = 格面资源单一池;clear_<biome> 命名空间预留拒绝
|
||||
const CELL_TYPE_KEYS := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp"] # 字典完整性校验轴(类型 × 极性 = 十八格)
|
||||
@@ -43,7 +44,19 @@ func validate() -> Array:
|
||||
errs.append({"category": "enum", "message": "%s polarity 出域: %s" % [rid, pol]})
|
||||
var atk_type: String = String(row.get("attack_type", ""))
|
||||
if atk_type != "" and not ["normal", "pierce", "magic"].has(atk_type):
|
||||
errs.append({"category": "enum", "message": "%s attack_type 出域 {normal, pierce, magic}: %s" % [rid, atk_type]})
|
||||
errs.append({"category": "enum", "message": "%s attack_type 出域 {normal, pierce, magic}: %s" % [rid, atk_type]}) # aux 投放行专属校验(迭代 7 T1):极性恒正/加权入池/effect_id=item_id 非空(悬空在 config_db 跨表层
|
||||
# 对 aux_items 词表校验——reward_dangling_aux)/无 power 无区间(数值语义不复用,道具效果读 AuxItemTable)
|
||||
if ctype == AUX_ITEM_TYPE:
|
||||
# 负向行 = 雷格极性字典占位(雷安同池摇号下雷格可摇中 aux 身份——负路由零兑付兜底,
|
||||
# effect_id 空/power 0/weight 0 不入池;2026-09-29 T1)
|
||||
if pol == "negative":
|
||||
if String(row.get("effect_id", "")) != "" or int(row.get("power", 0)) != 0 or int(row.get("weight", 0)) != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s aux 负占位行仅允许 空effect_id/0power/0weight" % rid})
|
||||
continue
|
||||
if String(row.get("effect_id", "")) == "":
|
||||
errs.append({"category": "domain", "message": "%s aux 正行 effect_id 空(应=item_id)" % rid})
|
||||
if int(row.get("power", 0)) != 0 or row.has("power_min"):
|
||||
errs.append({"category": "cross_field", "message": "%s aux 正行禁 power/区间数值(道具数值读 AuxItemTable)" % rid})
|
||||
var pool: String = row.get("pool_tag", "")
|
||||
var pool_reserved: bool = pool.begins_with("clear_") and pool != "clear_default"
|
||||
if not POOL_TAGS.has(pool) and not pool_reserved:
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
[gd_resource type="Resource" script_class="AuxItemTable" load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://data/schemas/aux_item_table.gd" id="1"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1")
|
||||
rows = [{
|
||||
"item_id": "probe_dust",
|
||||
"display_name": "显影尘",
|
||||
"dimension_tags": ["info", "counter"],
|
||||
"effect_kinds": [],
|
||||
"target": "none",
|
||||
"magnitude": 0,
|
||||
"use_phase": "active_dig",
|
||||
"deferred": true
|
||||
}, {
|
||||
"item_id": "sapper_order",
|
||||
"display_name": "工兵令",
|
||||
"dimension_tags": ["action"],
|
||||
"effect_kinds": ["ap_grant"],
|
||||
"target": "none",
|
||||
"magnitude": 2,
|
||||
"use_phase": "active_dig"
|
||||
}, {
|
||||
"item_id": "loot_compass",
|
||||
"display_name": "探宝罗盘",
|
||||
"dimension_tags": ["plan"],
|
||||
"effect_kinds": ["reward_preview"],
|
||||
"target": "area_3x3",
|
||||
"magnitude": 0,
|
||||
"use_phase": "active_dig",
|
||||
"retired": true
|
||||
}, {
|
||||
"item_id": "nest_pendulum",
|
||||
"display_name": "探巢摆钟",
|
||||
"dimension_tags": ["risk"],
|
||||
"effect_kinds": ["mine_reveal"],
|
||||
"target": "area_3x3",
|
||||
"magnitude": 0,
|
||||
"use_phase": "active_dig"
|
||||
}, {
|
||||
"item_id": "catacomb_scroll",
|
||||
"display_name": "地穴全图卷",
|
||||
"dimension_tags": ["info", "plan"],
|
||||
"effect_kinds": [],
|
||||
"target": "board_wide",
|
||||
"magnitude": 0,
|
||||
"use_phase": "active_dig",
|
||||
"deferred": true
|
||||
}, {
|
||||
"item_id": "blast_kit",
|
||||
"display_name": "爆破工兵包",
|
||||
"dimension_tags": ["action", "risk"],
|
||||
"effect_kinds": ["ap_grant", "mine_reveal"],
|
||||
"target": "area_3x3",
|
||||
"magnitude": 4,
|
||||
"use_phase": "active_dig"
|
||||
}]
|
||||
@@ -200,6 +200,49 @@ rows = [{
|
||||
"weight": 0,
|
||||
"pool_tag": "cell",
|
||||
"tier": 1
|
||||
}, {
|
||||
|
||||
"reward_id": "aux_sapper_order",
|
||||
"cell_type": "aux_item",
|
||||
"polarity": "positive",
|
||||
"effect_id": "sapper_order",
|
||||
"display_name": "工兵令",
|
||||
"power": 0,
|
||||
"weight": 5,
|
||||
"pool_tag": "cell",
|
||||
"tier": 2
|
||||
}, {
|
||||
|
||||
"reward_id": "aux_nest_pendulum",
|
||||
"cell_type": "aux_item",
|
||||
"polarity": "positive",
|
||||
"effect_id": "nest_pendulum",
|
||||
"display_name": "探巢摆钟",
|
||||
"power": 0,
|
||||
"weight": 4,
|
||||
"pool_tag": "cell",
|
||||
"tier": 2
|
||||
}, {
|
||||
|
||||
"reward_id": "aux_blast_kit",
|
||||
"cell_type": "aux_item",
|
||||
"polarity": "positive",
|
||||
"effect_id": "blast_kit",
|
||||
"display_name": "爆破工兵包",
|
||||
"power": 0,
|
||||
"weight": 1,
|
||||
"pool_tag": "cell",
|
||||
"tier": 3
|
||||
}, {
|
||||
"reward_id": "aux_none",
|
||||
"cell_type": "aux_item",
|
||||
"polarity": "negative",
|
||||
"effect_id": "",
|
||||
"display_name": "惊扰的遗落物",
|
||||
"power": 0,
|
||||
"weight": 0,
|
||||
"pool_tag": "cell",
|
||||
"tier": 1
|
||||
}]
|
||||
|
||||
; 格面资源批(2026-09-15 用户拍板——registry reward_table 条目为现行 schema 事实源):
|
||||
|
||||
Reference in new issue
Block a user