秘宝批T5组B-2:ConfigDB注册键treasure_items/持有变量/五访问器全族+调用方+桩表+loaded取键同步(冒烟755/0;run_all对照基线零新增——reward_overlay_test红系②批遗留基线红,treasure_items_test由红转绿系本批修复T4桩回退行漏改)

This commit is contained in:
DKChan committed 2026-10-05 08:34:57 +08:00
1 parent 2532c8fceb
commit 7e5b6d99b4
14 files changed
+52 -52

No files matched your search

+3 -3
View File
@@ -606,7 +606,7 @@ func _resolve_node_replace(discard_handle: int) -> bool:
func _seed_attune_charges() -> void:
attune_charges = {}
for iid in _attunement:
var arow: Dictionary = db.aux_item_row(String(iid))
var arow: Dictionary = db.treasure_item_row(String(iid))
if String(arow.get("form", "")) == "active_charged":
attune_charges[String(iid)] = maxi(0, int(arow.get("charges_per_adventure", 0)))
@@ -616,7 +616,7 @@ func _seed_attune_charges() -> void:
# 达上限剔牌/掷定前置直显;停点可中断)----
func _attune_refresh_x_total() -> int:
return int(db.aux_item_row("pick_refresh").get("magnitude", 0)) if _attunement.has("pick_refresh") else 0
return int(db.treasure_item_row("pick_refresh").get("magnitude", 0)) if _attunement.has("pick_refresh") else 0
func _reset_refresh_x() -> void:
@@ -752,7 +752,7 @@ func _roll_from(rg: RandomNumberGenerator) -> String:
# 三选一道具件随机池(与投放门控同源:aux 活行 ∩ 解锁门控集——空集 = 道具件不入牌库)
func _bonus_aux_pool() -> Array:
var out: Array = []
var live: Dictionary = db.aux_live_ids()
var live: Dictionary = db.treasure_live_ids()
for iid in live.keys():
if _aux_unlocked.has(String(iid)):
out.append(String(iid))
+1 -1
View File
@@ -4,7 +4,7 @@
# Date: 2026-10-03(迭代 11 第①批 秘宝同调实施批 T3——任务书 v1.1 §六 T3;设计权威底稿 proposal §2)
# 同调位求值服务:计数源组装(save 账本 → 计数字典)与实时求值,纯函数零副作用。
# 读数源切换(迭代 10 欠账③):装配面消费方(营地装配覆盖层 T4/冒险开始装配注入 T6)一律经本服务取
# Slots;过渡键 adventure.transitional_sync_slots 的在途读取面(aux_items 持有上限 gate/战斗内沉没/
# Slots;过渡键 adventure.transitional_sync_slots 的在途读取面(treasure_items 持有上限 gate/战斗内沉没/
# 停点替换交互/main 同调位呈现)系过渡渠道承载——T7 退役面切换时随渠道一并消亡(该批读数源切换的
# 正主落点,06 欠账③销账注记随 T7/T9)。过渡期切早 = off 态 MC 对 81000 锚添新扰动(fresh 档计数全零
# → Slots=0 ≠ 过渡键 1),违「attune=off 逐位一致」🔴 契约——故本服务先立、在途面 T7 切。
+4 -4
View File
@@ -87,7 +87,7 @@ func _attune_has(item_id: String) -> bool:
# 装备件表值读取(magnitude/effective_rounds 等——TreasureItemTable 行;未装配不读表)
func _attune_row(item_id: String) -> Dictionary:
return db.aux_item_row(item_id) if _attune_has(item_id) else {}
return db.treasure_item_row(item_id) if _attune_has(item_id) else {}
func _attune_mag(item_id: String) -> int:
@@ -493,7 +493,7 @@ func _settle() -> void:
# 掘进蓄能计数(迭代 11 同调批 T6——battle 域安全开格计数,每 charge_n 格积 1 点)
if _attune_has("dig_charge"):
_attune_safe_seen += 1
var cn_b: int = int(db.aux_item_row("dig_charge").get("charge_n", 999))
var cn_b: int = int(db.treasure_item_row("dig_charge").get("charge_n", 999))
if cn_b > 0 and _attune_safe_seen % cn_b == 0:
_attune_bank += 1
elif evt.kind == "mine":
@@ -642,7 +642,7 @@ func use_aux(handle: int, target: Vector2i) -> Dictionary:
# 掘进蓄能受理闸(迭代 11 同调批 T6——bank>0 才可发起,一行一点;积点不足拒绝零消耗)
if String(v.item_id) == "dig_charge" and _attune_has("dig_charge"):
if _attune_bank <= 0:
var cn_info: int = int(db.aux_item_row("dig_charge").get("charge_n", 0))
var cn_info: int = int(db.treasure_item_row("dig_charge").get("charge_n", 0))
return {"ok": false, "reason": "掘进蓄能:安全格积点未达(%d/%d)" % [_attune_safe_seen % cn_info if cn_info > 0 else 0, cn_info]}
_attune_bank -= 1
var kinds: Array = v.kinds
@@ -1086,7 +1086,7 @@ func _exit_distribution() -> void:
_fatal("换图编排失败")
return
# 工兵晨令续队(迭代 11 同调批 T5——upcoming 轮号 = round_index+1 ≤ effective_rounds 才续,P4 甲表值化)
if _attune_has("dawn_order") and round_index + 1 <= int(db.aux_item_row("dawn_order").get("effective_rounds", 0)):
if _attune_has("dawn_order") and round_index + 1 <= int(db.treasure_item_row("dawn_order").get("effective_rounds", 0)):
action_economy.queue_ap_delta(_attune_mag("dawn_order"))
action_economy.notify_settlement_done(mode)
action_economy.notify_round_start()
+13 -13
View File
@@ -24,7 +24,7 @@ const TABLE_MANIFEST := {
"shop": "shop.tres", # GP+商店房实施批 2026-09-21(表与 schema 落籍归并行数据面——本批只接线加载与消费)
"meta": "meta.tres", # 元进度实现批 2026-09-21(MetaTable 四行族——schema 与表同批落籍)
"meta_tree": "meta_tree.tres", # 迭代 12 T8 双层 BD 天赋树(MetaTreeTable 定义表 Rule 4 豁免——R1 甲融合案 33 节点)
"aux_items": "treasure_items.tres", # 迭代 7 T1 秘宝内容批(TreasureItemTable 六行——定义表 Rule 4 豁免;罗盘 retired/失义件 deferred 标记见 schema 头注)
"treasure_items": "treasure_items.tres", # 迭代 7 T1 秘宝内容批(TreasureItemTable 六行——定义表 Rule 4 豁免;罗盘 retired/失义件 deferred 标记见 schema 头注)
"adventure": "adventure.tres", # 冒险结构实现批 2026-09-21(AdventureTable 建表——大奖励与钥石行值单点)
"attunement_growth": "attunement_growth.tres", # 迭代 11 第①批 同调实施批 T1(AttunementGrowthTable 单行全局——同调位里程碑谓词表;单行先例 Rule 4 豁免)
"relics": "relics.tres", # 迭代 12 T1 双层 BD 规则改写型特性基建(RelicTable 定义表 Rule 4 豁免——TreasureItemTable 先例;空表合法态=主时间线零扰动)
@@ -47,7 +47,7 @@ var shop: ShopTable = null
# 元进度实现批(2026-09-21):MetaTable 类型化持用(schema 与表同批落籍,无 shop 先例的落籍间隙问题)
var meta: MetaTable
var meta_tree: MetaTreeTable # 迭代 12 T8 类型化持用(消费面走 tree_node 访问器)
var aux_items: TreasureItemTable # 迭代 7 T1 类型化持用(消费面走 aux_* 访问器)
var treasure_items: TreasureItemTable # 迭代 7 T1 类型化持用(消费面走 treasure_* 访问器)
var adventure: AdventureTable
var attunement_growth: AttunementGrowthTable # 迭代 11 第①批 T1 类型化持用(消费面走 attunement_* 访问器)
var relics: RelicTable # 迭代 12 T1 类型化持用(消费面走 relic_* 访问器)
@@ -139,7 +139,7 @@ func load_tables(root: String, collect_only: bool) -> bool:
difficulty = loaded.get("difficulty")
shop = loaded.get("shop")
meta = loaded.get("meta")
aux_items = loaded.get("aux_items")
treasure_items = loaded.get("treasure_items")
adventure = loaded.get("adventure")
attunement_growth = loaded.get("attunement_growth")
relics = loaded.get("relics")
@@ -250,29 +250,29 @@ func level_count() -> int:
# ---- GP+商店房实施批(2026-09-21):ShopTable 消费面(行集解析单点——runner/战斗编排禁自扫表)----
# ── 秘宝访问器(迭代 7 T1——消费面一律走访问器,禁直读行集)──
# 活行集(非 retired 非 deferred)——投放校验/奖励节点池/呈现可用性的唯一取数口径
func aux_active_rows() -> Array:
return aux_items.active_rows() if aux_items != null else []
func treasure_active_rows() -> Array:
return treasure_items.active_rows() if treasure_items != null else []
func aux_item_row(item_id: String) -> Dictionary:
return aux_items.row_by_id(item_id) if aux_items != null else {}
func treasure_item_row(item_id: String) -> Dictionary:
return treasure_items.row_by_id(item_id) if treasure_items != null else {}
# 过渡渠道活行(form 空 = 切片期过渡形态)——掉落投放/停点池/工坊解锁取数口径;同调行(form 非空)
# 永不入过渡渠道(迭代 11 第①批 T1;T7 退役面切换后本口径随渠道消亡)
func aux_transitional_rows() -> Array:
return aux_items.transitional_rows() if aux_items != null else []
func treasure_transitional_rows() -> Array:
return treasure_items.transitional_rows() if treasure_items != null else []
# 同调行集(form 非空——装配覆盖层/效果接线的取数口径,迭代 11 第①批 T1/T4)
func aux_attunement_rows() -> Array:
return aux_items.attunement_rows() if aux_items != null else []
func treasure_attunement_rows() -> Array:
return treasure_items.attunement_rows() if treasure_items != null else []
# 活行词表(掉落投放 effect_id 白名单——过渡渠道口径)
func aux_live_ids() -> Dictionary:
func treasure_live_ids() -> Dictionary:
var out := {}
for row in aux_transitional_rows():
for row in treasure_transitional_rows():
out[String(row.get("item_id", ""))] = true
return out
+6 -6
View File
@@ -33,18 +33,18 @@ func cross_validate(loaded: Dictionary, push_diag: Callable) -> void:
# ①b RewardTable aux 投放行双表校验(迭代 7 T1——reward_dangling_treasure):aux 行 effect_id = item_id,
# 须命中 TreasureItemTable 活行(非 retired 非 deferred——罗盘退役/失义件不投放)。retired 行被引用=退役
# 后仍投放(连带错误),同拦。
var aux_live := {}
var aux_tab = loaded.get("aux_items")
if aux_tab != null:
for arow in aux_tab.active_rows():
aux_live[String(arow.get("item_id", ""))] = true
var treasure_live := {}
var treasure_tab = loaded.get("treasure_items")
if treasure_tab != null:
for arow in treasure_tab.active_rows():
treasure_live[String(arow.get("item_id", ""))] = true
for row in rt.rows:
if String(row.get("cell_type", "")) != RewardTable.TREASURE_ITEM_TYPE:
continue
var aux_eff: String = String(row.get("effect_id", ""))
if aux_eff == "": # 负占位行(雷格极性字典兜底,零兑付)——不入投放词表校验
continue
if not aux_live.has(aux_eff):
if not treasure_live.has(aux_eff):
push_diag.call("error", "reward_dangling_treasure", "RewardTable %s aux 行引用无效道具 %s(retired/deferred/不存在): %s" % [row.get("reward_id"), aux_eff, "双表校验"])
# ①c F2 投放维度覆盖(秘宝 GDD——五维度各 ≥1 掉落权重为正的活行):豁免面 {plan, info, counter}
# = 罗盘退役(plan,2026-09-29 拍板①乙)+显影件 Alpha 重定(info/counter 悬置)——豁免随 Alpha 重定批消减
+5 -5
View File
@@ -91,7 +91,7 @@ func workshop_status() -> Array:
var out: Array[Dictionary] = []
for row in db.meta_workshop_items():
var iid := String(row.get("item_id", ""))
var arow: Dictionary = db.aux_item_row(iid) # 迭代 7 T5——失义/退役状态面(呈现「能力封存/已退役」)
var arow: Dictionary = db.treasure_item_row(iid) # 迭代 7 T5——失义/退役状态面(呈现「能力封存/已退役」)
out.append({
"item_id": iid,
"display_name": String(row.get("display_name", "")),
@@ -326,12 +326,12 @@ func migrate_tree() -> Dictionary:
save.set_tree_level(String(pair[0]), lvl)
migrated["forge"] += 1
var any_unlock := false
for iid in db.aux_live_ids().keys():
for iid in db.treasure_live_ids().keys():
if save.item_unlocked(String(iid)):
any_unlock = true
break
if not any_unlock:
for row in db.aux_attunement_rows():
for row in db.treasure_attunement_rows():
if save.item_unlocked(String(row.get("item_id", ""))):
any_unlock = true
break
@@ -354,7 +354,7 @@ func migrate_tree() -> Dictionary:
func toggle_attunement(item_id: String) -> bool:
var equipped: Array = save.attunement_equipped()
if not equipped.has(item_id):
var arow: Dictionary = db.aux_item_row(item_id)
var arow: Dictionary = db.treasure_item_row(item_id)
if arow.is_empty() or String(arow.get("form", "")) == "":
return false # 非同调行(过渡/退役行)禁装配
if equipped.size() >= Attunement.slots(db, save):
@@ -370,7 +370,7 @@ func toggle_attunement(item_id: String) -> bool:
func attune_camp_status() -> Dictionary:
var equipped: Array = save.attunement_equipped()
var items: Array[Dictionary] = []
for row in db.aux_attunement_rows():
for row in db.treasure_attunement_rows():
var iid := String(row.get("item_id", ""))
items.append({
"item_id": iid,
+3 -3
View File
@@ -112,9 +112,9 @@ func _usable_now(item_id: String, board_has_preview_info: Callable) -> bool:
func _item_row(item_id: String) -> Dictionary:
if _db == null:
return {}
if _db.has_method("aux_item_row"):
return _db.aux_item_row(item_id) # 表访问收口(2026-10-02——正式面走 ConfigDB 访问器)
return _db.aux_items.row_by_id(item_id) # 桩表面(单测 StubDB 无访问器——直读保留,随测试面演进退役)
if _db.has_method("treasure_item_row"):
return _db.treasure_item_row(item_id) # 表访问收口(2026-10-02——正式面走 ConfigDB 访问器)
return _db.treasure_items.row_by_id(item_id) # 桩表面(单测 StubDB 无访问器——直读保留,随测试面演进退役)
# 不标具体类型原因:单元测试注入 StubDB 桩表(aux_items_test.gd)——typed 赋值会运行期拒收,保守保持 null 注
var _db = null # ConfigDB(行定义读取——_init 注入;测试可注入桩表)
+3 -3
View File
@@ -8,7 +8,7 @@
# 投值语言锁定 flat 整数;几何定价 tier 级价格 = 迭代 p = floor(p × price_ratio_pct/100),tier 0 = base_price)。
# boss_keystone = Boss 钥石两档行(level_index 连续从 1;first_kill ≥ repeat_kill——首杀全量、
# 重复杀固定小额恒定不递减,两档数值归元进度设计批配读数)。
# workshop_items = 道具工坊行(item_id = registry aux_items 六件词表封闭恰全;首版解锁渠道 = 总通关次数
# workshop_items = 道具工坊行(item_id = 秘宝六件词表封闭恰全;首版解锁渠道 = 总通关次数
# 达标 clear_threshold——2026-09-20 排期裁决;局内效果整体归 Alpha 秘宝重设计批,本表只有解锁状态面)。
# conversion = 区间平移换算率行(attr 与 forge 词表一致恰三;per_level_shift_pct ∈ [0,100]——
# registry 键 meta_progression_conversion_table;护甲行强条目:验收读数必须按解锁后参数重测)。
@@ -80,12 +80,12 @@ func validate() -> Array:
if li_at != i + 1:
errs.append({"category": "structural", "message": "boss_keystone level_index 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, li_at]})
break
# workshop_items:item_id 词表封闭 + 唯一 + 覆盖恰六(registry aux_items 词表)+ 阈值域 [1,99]
# workshop_items:item_id 词表封闭 + 唯一 + 覆盖恰六(秘宝词表)+ 阈值域 [1,99]
var seen_item := {}
for row in workshop_items:
var iid: String = row.get("item_id", "")
if not WORKSHOP_ITEM_IDS.has(iid):
errs.append({"category": "enum", "message": "workshop_items item_id 出域 aux_items 六件词表: %s" % iid})
errs.append({"category": "enum", "message": "workshop_items item_id 出域秘宝六件词表: %s" % iid})
if seen_item.has(iid):
errs.append({"category": "dup_key", "message": "workshop_items item_id 重复: %s" % iid})
seen_item[iid] = true
+1 -1
View File
@@ -19,7 +19,7 @@
# 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二
# (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 RelicsEngine。
# 🔴 层级纪律(任务书红线 2):专长只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
# (aux_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
# (treasure_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
# 违反=红线①触碰面)。
class_name RelicTable
extends Resource
+1 -1
View File
@@ -269,6 +269,6 @@ rows = [{
; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派的件面)。
; 稀有度→投放档映射:common/rare → 稀有令牌档、rarest → 罕见令牌档(relic 永不入普通令牌档
; ——「规则改写型特性带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。
; 🔴 层级纪律:本表行永不入同调位(aux_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。
; 🔴 层级纪律:本表行永不入同调位(treasure_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。
; 数值全 provisional 归 M-4 数值批;effects 键白名单封闭(零裸 flat 同族护栏)。
@@ -138,7 +138,7 @@ func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array:
func _aux_card_line(iid: String) -> String:
if iid == "":
return ""
var row: Dictionary = db.aux_item_row(iid)
var row: Dictionary = db.treasure_item_row(iid)
if row.is_empty():
return ""
var parts: Array[String] = []
@@ -35,12 +35,12 @@ func _init(db_ref, meta_ref, info_panel_ref: HeroInfoPanelView, toast_ref: Toast
# aux 解锁门控集组装(迭代 7 T5——拍板③甲:工坊解锁 ∩ 过渡活行词表;罗盘退役/失义件/同调行不入集
# ——迭代 11 第①批 T1 切 aux_transitional_rows 口径,同调行永不入过渡渠道)
# ——迭代 11 第①批 T1 切 treasure_transitional_rows 口径,同调行永不入过渡渠道)
func unlocked_set() -> Dictionary:
var out := {}
if meta == null:
return out
for row in db.aux_transitional_rows():
for row in db.treasure_transitional_rows():
var iid := String(row.get("item_id", ""))
if meta.is_item_unlocked(iid):
out[iid] = true
@@ -69,7 +69,7 @@ func on_slot_clicked(slot_handle: int) -> void:
break
if rec.is_empty() or bool(rec.get("used", false)):
return
var arow: Dictionary = db.aux_item_row(String(rec.get("item_id", "")))
var arow: Dictionary = db.treasure_item_row(String(rec.get("item_id", "")))
if String(arow.get("target", "none")) == "none":
attempt_use(slot_handle) # AP 类:显式无目标即用(不再伪造哨兵坐标)
return
@@ -96,7 +96,7 @@ func attempt_use(handle: int, cell: Variant = null) -> void:
refresh_slots()
refresh_overlays()
board_view.refresh() # 迭代 13 T8/D6——移除格即时落图(无移除态的件 diff 零变化幂等)
var arow: Dictionary = db.aux_item_row(String(v.get("item_id", "")))
var arow: Dictionary = db.treasure_item_row(String(v.get("item_id", "")))
toast.show_toast("已使用 %s" % String(arow.get("display_name", "")), "info")
@@ -113,7 +113,7 @@ func inventory_projection() -> Array:
return ms.has_unrevealed() # 只读查询面(排雷玩法 has_unrevealed——手搓全板双循环收口)
var out: Array = []
for rec in runner.aux_inventory.query_inventory(cb):
var arow: Dictionary = db.aux_item_row(String(rec.get("item_id", "")))
var arow: Dictionary = db.treasure_item_row(String(rec.get("item_id", "")))
var dn := String(arow.get("display_name", ""))
out.append({
"handle": int(rec.get("handle", 0)),
+1 -1
View File
@@ -72,7 +72,7 @@ func _initialize() -> void:
var slots: int = db.attunement_growth.slots({"clear_count": 3, "boss_kill_count": 6})
var passives: Array = []
var actives: Array = []
for r in db.aux_attunement_rows():
for r in db.treasure_attunement_rows():
if String(r.get("form", "")) == "passive":
passives.append(String(r.get("item_id", "")))
elif String(r.get("form", "")) == "active_charged":
+5 -5
View File
@@ -1,8 +1,8 @@
# VERTICAL SLICE - NOT FOR PRODUCTION
# 秘宝 TreasureItems 类单测(迭代 7 T7——结构冻结断言面;设计权威 秘宝.md + registry aux_items)。
# 秘宝 TreasureItems 类单测(迭代 7 T7——结构冻结断言面;设计权威 秘宝.md + registry treasure_items)。
# 覆盖:授予归因 / Used 不可逆 / 真视恒可用 / 预读点击级零信息拒绝 / 3×3 边缘窗口∩板 /
# 叠加层三清(retire_overlays 不动库存)/ 关卡末 reset / 零随机(同操作序列重放两遍投影逐位)。
# 运行:godot --headless --path game --script res://tests/unit/core/aux_items_test.gd(expect 0)
# 运行:godot --headless --path game --script res://tests/unit/core/treasure_items_test.gd(expect 0)
extends SceneTree
const TreasureItemsScript := preload("res://core/treasure_items.gd")
@@ -18,7 +18,7 @@ class StubTable:
class StubDB:
var aux_items: StubTable
var treasure_items: StubTable
func _stub_db() -> StubDB:
@@ -32,7 +32,7 @@ func _stub_db() -> StubDB:
"effect_kinds": ["reward_preview"], "target": "area_3x3", "magnitude": 0, "use_phase": "active_dig"},
}
var db := StubDB.new()
db.aux_items = t
db.treasure_items = t
return db
@@ -103,4 +103,4 @@ func _init() -> void:
Kit.check_quiet(str(replay_a) == str(replay_b), "零随机重放:库存+叠加层+探针投影逐位相同")
# ---- 汇总 ----
quit(Kit.finish("aux_items_test", "PASS — 授予归因/Used 不可逆/真视恒可用/零信息拒绝/边缘窗口/三清/零随机重放 全过"))
quit(Kit.finish("treasure_items_test", "PASS — 授予归因/Used 不可逆/真视恒可用/零信息拒绝/边缘窗口/三清/零随机重放 全过"))