卡①T1+T2(拆件批wr1/wr2/wr3): BattleFxHost+RewardGrant两新件建件+fx/grant族迁移+use_treasure拆分+三触点分家——battle_fx_host.gd(14类变量:bundle7+grant_cb+engine+counters_ctx+ac/reveal两束;fx_emit/emit_round_start/apply_ac_bonus/enqueue_reveal/flush_pending_reveals取号序逐字/rebuild_subscriptions/mount_buckets/reset_battle_state/bonus_delta_drain/reveal_busy)+reward_grant.gd(15类变量:bundle11+escrow+defer+treasure_inventory+battle_ledger;grant_routed随att归因束改形/submit案C闸/use_treasure四步骨架+_charge_gate+_apply_use_kinds+_safe_dig_open+_cell_removal_open/grant_clear_reward三参形宿主态经参传入/reveal_redeem兑付回调面);宿主删fx族11成员+grant族3成员,组件出口fx_host()/reward_grant(),_fx_host_fact五事实单点+_attune_safe_seen_read读投影,treasure_inventory带setter转发,begin_battle七接线点改指,_battle_over改bonus_delta_drain,_roll_gp_drop读_reward_grant.escrow;两段三引用构造(与T4接口块同形先行)读写面改指(oc._submit实为7处G5清单漏1,oc._fx_bonus_delta axis/axis_f两形);treasure_interact_controller改ctx束8键+三现值同查+inventory_projection拆_projection_row/_auto_row;main_ui_build构造改束(grant_get=run_scope.settlement.reward_grant()现值);S7/S8登记两新件7→9;测试改址:adventure_feats 75+round_flow 8+treasure_effects 7(含G11漏载的ctrl4构造点)+settle_segments 3+seal_polarity 10(含G11漏载的_grant_clear_identity直调)+level_shop 4+forge 2,另修reward_grant内部_submit/_outcome_of旧名三处与adventure_feats orch._fx/orch0._fx.rebuild两残漏(脚本错误静默吞断言假绿形态,修后feats 138PASS/seal 73PASS恢复全额);代拍板:①RewardGrant bundle 12→11键(minesweeper改经fx_host同源引用)腾位battle_ledger独立成员(卡面15≤15算术缺口,16键=基线外NEW停卡不可取)②bind_grant落_reward_grant.reveal_redeem(query_full_snapshot唯授予件持有,D1「RewardGrant授予面」兑付回调口径)③续拆四私有(迁入形逐键过阈值义务)④grant_clear_reward测试改址传宿主态读(s._board_from_midround_refresh/perfect_sweep_earned)。验收:七套件直跑绿+零SCRIPT ERROR+gdstyle基线外新违规0(battle_orchestrator行数恶化键随拆件归绿989<1302;level_map_screen 22>21=iter38存量漏登记非本批触碰面)〔拆件批 V8〕

This commit is contained in:
DKChan committed 2026-10-27 06:07:15 +08:00
1 parent 8452162665
commit cc02bb9315
18 files changed
+903 -614

No files matched your search

@@ -1,8 +1,15 @@
## VERTICAL SLICE - NOT FOR PRODUCTION
## 秘宝两步交互控制器:C 区槽位选中/取消(toggle)→ 棋盘点格使用目标拾取的状态机 + 库存/叠加层只读投影装配。
## 写调用唯一经 settlement.use_treasure;信号连接只归组合根(info_panel.treasure_slot_clicked 接至 on_slot_clicked)。
## settlement/runner 随关卡逐关更替——经组合根现值回调注入。
## AP 类(target=none)调用面一律 attempt_use(handle)(cell 缺省=null=显式无目标)——哨兵坐标收口本类,不出控制器。
## 写调用分家(三触点):使用受理走 grant(RewardGrant.use_treasure——授予件面)、排雷玩法只读读与
## 积点进度读走 settlement(编排器面);写调用唯一经现值回调注入的协作件,控制器零核心写调用本体。
## 信号连接只归组合根(info_panel.treasure_slot_clicked 接至 on_slot_clicked)。
## settlement/runner/grant 随关卡/战斗逐次更替——经组合根现值回调注入(grant 每战新建编排器,
## 现值取件防悬挂)。AP 类(target=none)调用面一律 attempt_use(handle)(cell 缺省=null=显式无目标)
## ——哨兵坐标收口本类,不出控制器。
## ctx 引用束封闭键集(8 项,缺一键 assert):db/meta/info_panel:HeroInfoPanelView/toast:ToastStack/
## board_view:BoardView/settlement_get:Callable(编排器现值——minesweeper 读与 attune_convert_state
## 双取值面之一)/runner_get:Callable/grant_get:Callable(授予件现值——use_treasure 直注)。
## 禁实现期增删键。
extends RefCounted
const NO_TARGET := Vector2i(-9, -9) # core use_treasure 形参占位(仅 target=none 行到达——validate_use 忽略该值)
@@ -12,20 +19,23 @@ var meta # 解锁门控数据源(工坊解锁×活行交
var info_panel: HeroInfoPanelView
var toast: ToastStack # 反馈面(board_zone.toast 注入)
var board_view: BoardView
var _settlement_get: Callable # () → 当前战斗结算现值(组合根 lambda)
var _settlement_get: Callable # () → 当前战斗结算现值(组合根 lambda——双取值面之一)
var _runner_get: Callable # () → 当前关卡推进器现值(组合根 lambda)
var _grant_get: Callable # () → 当前奖励授予件现值(组合根 lambda——每战新建,防悬挂)
var _use_selection := 0 # 选中句柄(0=未选中;选中期棋盘点击=使用目标拾取)
func _init(db_ref, meta_ref, info_panel_ref: HeroInfoPanelView, toast_ref: ToastStack,
board_view_ref: BoardView, settlement_get: Callable, runner_get: Callable) -> void:
db = db_ref
meta = meta_ref
info_panel = info_panel_ref
toast = toast_ref
board_view = board_view_ref
_settlement_get = settlement_get
_runner_get = runner_get
func _init(ctx: Dictionary) -> void:
for k in ["db", "meta", "info_panel", "toast", "board_view", "settlement_get", "runner_get", "grant_get"]:
assert(ctx.has(k), "[秘宝交互] 引用束缺键: %s" % k)
db = ctx.db
meta = ctx.meta
info_panel = ctx.info_panel
toast = ctx.toast
board_view = ctx.board_view
_settlement_get = ctx.settlement_get
_runner_get = ctx.runner_get
_grant_get = ctx.grant_get
# aux 解锁门控集组装:工坊解锁 ∩ 过渡活行词表(treasure_transitional_rows 口径);
@@ -51,7 +61,9 @@ func active_selection() -> int:
func on_slot_clicked(slot_handle: int) -> void:
var settlement = _settlement_get.call()
var runner = _runner_get.call()
if settlement == null or runner == null or runner.treasure_inventory == null:
var grant = _grant_get.call()
# 三现值同查守卫(settlement/runner/grant 任一未就绪即静默 return——现值回调随更替时序)
if settlement == null or runner == null or grant == null or runner.treasure_inventory == null:
return
if slot_handle == 0:
_use_selection = 0
@@ -82,11 +94,11 @@ func on_slot_clicked(slot_handle: int) -> void:
# 使用受理(第二步;cell=空间类目标格,null=无目标;core 侧 use_treasure 四步编排——拒绝零消耗 toast 可辨认)
func attempt_use(handle: int, cell: Variant = null) -> void:
var settlement = _settlement_get.call()
if settlement == null:
var grant = _grant_get.call()
if grant == null:
return
var target: Vector2i = cell if cell != null else NO_TARGET
var v: Dictionary[Variant, Variant] = settlement.use_treasure(handle, target)
var v: Dictionary[Variant, Variant] = grant.use_treasure(handle, target)
if not bool(v.ok):
toast.show_toast(String(v.get("reason", "无法使用")), "warn")
return
@@ -98,7 +110,7 @@ func attempt_use(handle: int, cell: Variant = null) -> void:
toast.show_toast("已使用 %s" % String(arow.get("display_name", "")), "info")
# 库存投影(C 区四槽取数面——字形=名首字;usable=整图零信息预判回调接排雷玩法只读面)
# 库存投影(C 区四槽取数面——逐库存行装配 + 末尾自动兑付件合成行)
func inventory_projection() -> Array:
var runner = _runner_get.call()
if runner == null or runner.treasure_inventory == null:
@@ -111,41 +123,61 @@ func inventory_projection() -> Array:
return ms.has_unrevealed() # 只读查询面(排雷玩法 has_unrevealed——手搓全板双循环收口)
var out: Array[Variant] = []
var cs: Dictionary[Variant, Variant] = settlement.attune_convert_state() if settlement != null else {}
var auto_seen := false # 自动兑付件是否已随骑库存出现(恒否——charges=0 不入骑库存;守合成行重复)
for rec in runner.treasure_inventory.query_inventory(cb):
var arow: Dictionary[Variant, Variant] = db.treasure_item_row(String(rec.get("item_id", "")))
var dn := String(arow.get("display_name", ""))
# 积点进度浮窗行(自动兑付件 C 区悬停 tooltip 补 N/M 进度;件 id 锁定=装配行唯一)
var note := ""
if bool(cs.get("assembled", false)) and String(cs.get("item_id", "")) == String(rec.get("item_id", "")):
note = "积点 %d/%d" % [int(cs.get("points", 0)), int(cs.get("need", 0))]
auto_seen = true
out.append({
"handle": int(rec.get("handle", 0)),
"item_id": String(rec.get("item_id", "")),
"glyph": dn.left(1) if dn != "" else "?",
"name": dn,
"used": bool(rec.get("used", false)),
"usable": bool(rec.get("usable", true)),
"note": note,
})
out.append(_projection_row(rec, cs))
# 自动兑付件展示行(charges=0 不入骑库存〔_reseed_attune_charges 跳过注入〕,
# C 区四槽末尾补合成行承载悬停进度;handle=-1 非库存句柄:槽点击走说明 toast 分支不进两步交互)
# C 区四槽末尾补合成行承载悬停进度;handle=-1 非库存句柄:槽点击走说明 toast 分支不进两步交互)。
# 库存内已见同 id 行(恒否——charges=0 不入骑库存)则不重复补行,守合成行重复
var auto_seen := false
if bool(cs.get("assembled", false)):
for row_v in out:
if String(cs.get("item_id", "")) == String((row_v as Dictionary).get("item_id", "")):
auto_seen = true
break
if bool(cs.get("assembled", false)) and not auto_seen:
var adn := String(cs.get("display_name", ""))
if adn != "":
out.append({
"handle": -1,
"item_id": String(cs.get("item_id", "")),
"glyph": adn.left(1),
"name": adn,
"used": false,
"usable": true,
"note": "积点 %d/%d" % [int(cs.get("points", 0)), int(cs.get("need", 0))],
})
var auto := _auto_row(cs)
if not auto.is_empty():
out.append(auto)
return out
# 库存投影行(字形=名首字;usable=整图零信息预判回调接排雷玩法只读面)+
# 积点进度浮窗行(自动兑付件 C 区悬停 tooltip 补 N/M 进度;件 id 锁定=装配行唯一)
func _projection_row(rec: Dictionary, cs: Dictionary) -> Dictionary:
var arow: Dictionary[Variant, Variant] = db.treasure_item_row(String(rec.get("item_id", "")))
var dn := String(arow.get("display_name", ""))
var note := ""
if bool(cs.get("assembled", false)) and String(cs.get("item_id", "")) == String(rec.get("item_id", "")):
note = "积点 %d/%d" % [int(cs.get("points", 0)), int(cs.get("need", 0))]
return {
"handle": int(rec.get("handle", 0)),
"item_id": String(rec.get("item_id", "")),
"glyph": dn.left(1) if dn != "" else "?",
"name": dn,
"used": bool(rec.get("used", false)),
"usable": bool(rec.get("usable", true)),
"note": note,
}
# 自动兑付件合成展示行(未装配/无名行=空字典不补行)
func _auto_row(cs: Dictionary) -> Dictionary:
if not bool(cs.get("assembled", false)):
return {}
var adn := String(cs.get("display_name", ""))
if adn == "":
return {}
return {
"handle": -1,
"item_id": String(cs.get("item_id", "")),
"glyph": adn.left(1),
"name": adn,
"used": false,
"usable": true,
"note": "积点 %d/%d" % [int(cs.get("points", 0)), int(cs.get("need", 0))],
}
func refresh_slots() -> void:
info_panel.set_treasure_inventory(inventory_projection(), _use_selection)