主卡T5(拆件批wr7): 转发属性25条撤除+测量面改址收口——adv 4条(_curio_taken/_curio_deck/_feat_ticket_pity/_feat_ticket_sold直指件成员改写后删)、level 7条白盒属性删(内部直指_shop)、board 13条删(内部消费约30处改直引_palette/_hero_sprite件成员);A类直读47处+ui_input_probe 6处改指件;C类方法面调用全仓改adventure.stop().X(委托壳退役——契约5纯转传清偿,adv删pick_curio/apply_node_curio/skip_empty/refresh族/pool_stock/凭证委托11个,ctx组包改直引_curio.deck/feat_ticket_consider/cap_ok);新件压默认阈值(hero_ledger删_gain_seq序派生15变量合规;curio_stop删_attunement改_refresh_x_cap预算注入——装配集冒险期间锁死契约8等价,start/resume双路注入);battle_orchestrator压行还债(begin_battle局部变量归位);验证集清单重生成(66源文件/1596调用点,标签cond计数三对齐零差异)。S13读数:三宿主全部改善——adventure_runner类变量42→23(-19)/公开方法23→≤20归零、level_runner 38→28(-10,达标约30)/54→50、board_view 45→32(-13,精确达标);存量红面=新件5条NEW(接口块公开面29/31方法+迁移函数既有超标形态,原基线adventure_runner同函数同值登记)+恶化4条(battle拆件接线3条+level_map_screen 1条iter38存量漏登记——本批零触碰),收口前呈报用户裁决〔拆件批 V7〕

This commit is contained in:
DKChan committed 2026-10-27 04:14:10 +08:00
1 parent fa1409f491
commit 659d59edd3
19 files changed
+431 -552

No files matched your search

+19 -68
View File
@@ -35,12 +35,6 @@ var _resume_bp := {} # 续玩快照暂存(resume_adventur
# ---- 三选一停点(编排迁 CurioStop 件——停点三态/刷新三源/凭证出箱/信号面)----
var _curio: CurioDeck = null # 令牌池件(_init 建;纯池——多重集/抽签/cap/凭证判定唯一宿主)
var _stop: CurioStop = null # 停点件(_init 建;每冒险一次——关卡换实例不换件)
var _curio_taken: Dictionary[Variant, Variant]: # 件获取次数计数(kind 维度派生账本——断点附随件与摘要读数承载)
get: return _curio.taken
set(v): _curio.taken = v
var _curio_deck: Array[Variant]: # 令牌池(TP0 v2.2——持久多重集,元素 {"kind","tier"};商店货架同库共账)
get: return _curio.deck
set(v): _curio.deck = v
var _tree_rules: Array[Variant] = [] # 树 rule 键集(Fork 激活侧 effects 透传;下传 enc.tree_rules 消费面)
var _shop_mode := "legacy" # 商店模式("legacy"=固定三件加定价〔off 对照承载,缺省零扰动〕/"pool"=共享池抽 3 买 1 重抽;真实入口 main.gd 显式投 pool)
@@ -87,7 +81,7 @@ func start_adventure(seed_val: int, params: Dictionary = {}) -> bool:
_shop_mode = "pool" if String(params.get("shop_mode", "legacy")) == "pool" else "legacy" # 缺省 legacy(off 对照零扰动)
_treasure_unlocked = params.get("treasure_unlocked", {}) if params.get("treasure_unlocked", {}) is Dictionary else {}
_attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive
_stop.set_attunement(_attunement) # 停点件 X 基数查询消费面(活引用)
_stop.set_refresh_x_cap(_attune_refresh_x_total()) # 停点件 X 基数预算注入(装配集冒险期间锁死)
_stop.set_refresh_y(maxi(0, int(params.get("attune_refresh_y", 0)))) # additive(Y 冒险周期池)
_seed_attune_charges() # 冒险开始充能账本按装备主动件重置(每冒险充能语义)
adventure_counters = {} # 冒险桶清零(效果引擎 adv_ 计数器宿主——冒险开始归零)
@@ -166,10 +160,10 @@ func _resume_ledger(bp: Dictionary, params: Dictionary) -> void:
func _resume_curio_state(bp: Dictionary) -> void:
_reset_curio_state()
var bp_taken: Dictionary[Variant, Variant] = bp.get("bonus_taken", {}) as Dictionary
for id in _curio_taken.keys():
_curio_taken[id] = maxi(0, int(bp_taken.get(id, 0)))
for id in _curio.taken.keys():
_curio.taken[id] = maxi(0, int(bp_taken.get(id, 0)))
for id in bp_taken.keys():
_curio_taken[String(id)] = maxi(0, int(bp_taken.get(id, 0))) # 身份维键(relic:<feat_id>)随快照还原
_curio.taken[String(id)] = maxi(0, int(bp_taken.get(id, 0))) # 身份维键(relic:<feat_id>)随快照还原
# 令牌池余库还原(TP0 v2.2——快照缺键 = 旧版断点,保持满库重建态:旧档只读一版周期的防御口径;
# relic 令牌 feat_id 随还原)
var bp_deck = _bp_read("bonus_deck", bp)
@@ -181,7 +175,7 @@ func _resume_curio_state(bp: Dictionary) -> void:
if String(rtok["kind"]) == "relic":
rtok["feat_id"] = String(tok.get("feat_id", "")) # relic 令牌 feat_id 随还原
restored.append(rtok)
_curio_deck = restored
_curio.deck = restored
# 特性持有集还原(缺键 = 旧版断点防御空集——主角账字段单点)
_hero.feats = []
for r in (bp.get("relics", []) as Array):
@@ -202,6 +196,7 @@ func _resume_params(bp: Dictionary, params: Dictionary) -> void:
_treasure_unlocked = params.get("treasure_unlocked", {}) if params.get("treasure_unlocked", {}) is Dictionary else {}
_attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive
_seed_attune_charges() # 冒险开始充能账本按装备主动件重置(每冒险充能语义)
_stop.set_refresh_x_cap(_attune_refresh_x_total()) # 停点件 X 基数预算注入(续玩参数面同 start)
_stop.restore_fragment(bp, params) # 停点件片段回填(凭证计数/刷新存量/Y 池——Y 缺键回退参数面 params_fallback 类)
_tree_rules = params.get("tree_rules", []) if params.get("tree_rules", []) is Array else [] # A/B 面 rule 键集(续玩参数面同 start_adventure 同式,消费面 set_tree_rules 下传)
@@ -263,10 +258,6 @@ func continue_to_next_level() -> bool:
# 停点空候选消化(池空=三选一环节整体跳过——呈现层跳开选择面;编排归停点件)
func skip_empty_curio() -> bool:
return _stop.skip_empty_curio()
# ---- 提升三选一(选择停点零自动推进、重复兑付被拒;兑付恰一件、未选项零生效)----
# 候选令牌匹配(身份键恒等——属性加成型特性 kind+tier、规则改写型特性 feat_id)
@@ -275,13 +266,6 @@ func _find_token(candidates: Array, kind: String, tier: String, feat_id: String
# 玩家点选兑付(state 守卫留应用层——编排归停点件;呈现层直调面 T5 改 stop())
func pick_curio(kind: String, tier: String = "", feat_id: String = "") -> bool:
if state != "running":
push_error("[冒险结构] pick_curio 拒绝——state=%s(非 running 不可兑付)" % state)
return false
return _stop.pick_curio(kind, tier, feat_id)
# 特性持有集读面(效果接线/求值/摘要唯一取数口——副本防外部改写)
func feats_held() -> Array:
return _hero.feats_held()
@@ -290,10 +274,6 @@ func feats_held() -> Array:
# ---- 商店共享池消费面(纯池——库存=牌库剩余令牌)----
# 库存余量(池消耗即上限;奖励摘牌与商店购买同库承载,全冒险一次性)
func pool_stock(kind: String) -> int:
return _stop.pool_stock(kind)
# 终局池快照(_settle 清账前调用——复位会重置计数,摘要 additive 键须在此前取数)
func _pool_stock_snapshot() -> Dictionary:
return _stop.pool_stock_snapshot()
@@ -312,8 +292,15 @@ func present_node_curio(candidates: Array) -> void:
# 点选兑付(节点域——编排归停点件;呈现层直调面 T5 改 stop())
func apply_node_curio(kind: String, tier: String = "", feat_id: String = "") -> bool:
return _stop.apply_node_curio(kind, tier, feat_id)
# 刷新件余量基数(kind 分发查询——装配集内 effect_kinds 含 bonus_refresh 的行 magnitude 合计;
# 刷新件类加件零 id 分支;停点件 X 重置基数经 start/resume 预算注入)
func _attune_refresh_x_total() -> int:
var total := 0
for iid_v in _attunement:
var arow: Dictionary[Variant, Variant] = db.treasure_item_row(String(iid_v))
if (arow.get("effect_kinds", []) as Array).has("bonus_refresh"):
total += int(arow.get("magnitude", 0))
return total
# 冒险开始充能账本重置(T6——装备 active_charged 件各回 charges_per_adventure;被动件不入账)
@@ -328,50 +315,14 @@ func _seed_attune_charges() -> void:
# ---- 三选一刷新与凭证(编排归停点件——本类留组合根委托读面)----
# 当前可刷新次数(X 优先 + Y 池 + 刷新存量账——呈现层余量读数口)
func attune_refresh_left() -> int:
return _stop.attune_refresh_left()
# 刷新存量账读数(T4——刷新券加仓余量单独读面;呈现层与断点消费)
func refresh_stock() -> int:
return _stop.refresh_stock()
# 节点停点在途态读回(组合根重 present 用——candidates 值拷贝)
func node_curio_pending_state() -> Dictionary:
return _stop.node_curio_pending_state()
# 三选一刷新(免费位 X/Y——组合根唯一调用口;无停点/无余量 false 零副作用)
func refresh_curio() -> bool:
return _stop.refresh_curio()
# 三选一 GP 付费刷新(对齐商店 MC-1——组合根先经 curio_stop_pending+钱包支出再调,本口只做计数与重抽)
func refresh_curio_paid() -> bool:
return _stop.refresh_curio_paid()
# 本次 GP 付费刷新价(与商店货架刷新同源——单点调参)
func curio_refresh_gp_cost() -> int:
return _stop.curio_refresh_gp_cost()
# 三选一停点在途谓词(付费路径扣费前置校验——无停点禁扣钱,防空转烧钱包)
func curio_stop_pending() -> bool:
return _stop.curio_stop_pending()
# —— 专长获取专长凭证四口径判定(实装归 CurioDeck 件:调用即一次展示判定与记账)——
func _feat_ticket_consider(rg: RandomNumberGenerator) -> bool:
return _curio.feat_ticket_consider(rg)
# 已拿上限判定(身份维度;缺省放行=白名单外 kind 兜底)
func _curio_cap_ok(kind: String, feat_id: String = "") -> bool:
return _curio.cap_ok(kind, feat_id)
# Boss 钥石逐杀掉落(掉落渠道 = Boss/精英击杀;首杀/复杀两档读 meta.tres boss_keystone;
# 首杀判据 = 存档 boss_first_kill 标记位〔断点未注入 = 恒首杀——模拟/冒烟零扰动;标记仍在收束
# apply_adventure_summary 逐关卡完成关次置位〕;末关 Boss 照常入账;明细随摘要 additive 键供结算面归因)
@@ -403,8 +354,8 @@ func _start_current_level() -> bool:
# 关卡对象构造注入一次给齐(拆件批 T3——ctx 键集见 LevelRunner._init 头注;
# 凭证出箱在组包时点取走〔节点级一次性——未用即过期语义不变〕)
var outbox: Dictionary[Variant, Variant] = _stop.voucher_outbox()
var pool_wiring: Dictionary[Variant, Variant] = {"deck": _curio_deck, "consume": _stop.consume_pool_purchase,
"ticket": _feat_ticket_consider, "cap": _curio_cap_ok} if _shop_mode == "pool" else {}
var pool_wiring: Dictionary[Variant, Variant] = {"deck": _curio.deck, "consume": _stop.consume_pool_purchase,
"ticket": _curio.feat_ticket_consider, "cap": _curio.cap_ok} if _shop_mode == "pool" else {}
var ctx: Dictionary[Variant, Variant] = {
"hero": _hero,
"ledger": run_ledger,
@@ -607,8 +558,8 @@ func _bp_parts() -> Dictionary[Variant, Variant]:
"keystone": int(hero_frag.get("keystone", 0)),
"visited_ids": level_frag.get("visited_ids", []),
"aux_items": level_frag.get("aux_items", []),
"bonus_taken": _curio_taken.duplicate(true), # 三选一件获取次数(kind 维度派生账本——断点附随件与读数承载)
"bonus_deck": _curio_deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原)
"bonus_taken": _curio.taken.duplicate(true), # 三选一件获取次数(kind 维度派生账本——断点附随件与读数承载)
"bonus_deck": _curio.deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原)
"relics": hero_frag.get("relics", []), # 特性持有集(局内随机渠道获得态续玩防丢失)
"bonus_pending": stop_frag.get("bonus_pending", {}), # 三选一停点态(空 = 无停点——选择停点可中断契约)
"feat_ticket_pity": int(stop_frag.get("feat_ticket_pity", 0)), # T5 专长凭证保底计数(扩列向后兼容——旧档缺键缺省 0)
+3 -5
View File
@@ -385,12 +385,10 @@ func begin_battle(enc: Dictionary) -> bool:
_fx_new_resource_types = {}
_fx_pending_reveals = []
_fx_bonus_delta = {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0}
var ledger_ref = enc.get("ledger", null)
var ledger_ref: Variant = enc.get("ledger", null)
_ledger = ledger_ref if ledger_ref is RunLedger else RunLedger.new() # 缺省新账=调试/单场零扰动面
var hero_ref = enc.get("hero", null)
_hero = hero_ref if hero_ref is HeroLedger else null # null=调试/单场直构——账面消费面跳过(空账守卫同语义)
var bucket_ref: Variant = enc.get("adv_bucket", null)
counters_ctx.adventure_bucket = bucket_ref if bucket_ref is Dictionary else {} # 挂冒险桶引用(归宿主字典——跨战持久=同一字典引用;直构兜底自有空字典)
_hero = enc.get("hero", null) if enc.get("hero", null) is HeroLedger else null # null=调试直构——账面消费跳过
counters_ctx.adventure_bucket = enc.get("adv_bucket", null) if enc.get("adv_bucket", null) is Dictionary else {} # 冒险桶宿主字典(直构兜底自有空字典)
var level_ref: Variant = enc.get("level_counters")
if level_ref is Dictionary:
counters_ctx.level_bucket = level_ref # 挂关卡桶引用(LevelRunner 每关 new 下传)
+6 -15
View File
@@ -257,26 +257,17 @@ func _redeem_feat_ticket() -> bool:
# Y=营地升级行冒险周期池〔用完即无〕;重抽消费 reward_pick 既有洗牌流,池规则全保留——不放回/
# 达上限剔牌/掷定前置直显;停点可中断)----
# 刷新件余量基数(kind 分发查询——装配集内 effect_kinds 含 bonus_refresh 的行 magnitude 合计;
# 刷新件类加件零 id 分支)
func _attune_refresh_x_total() -> int:
var total := 0
for iid_v in _attunement:
var arow: Dictionary[Variant, Variant] = db.treasure_item_row(String(iid_v))
if (arow.get("effect_kinds", []) as Array).has("bonus_refresh"):
total += int(arow.get("magnitude", 0))
return total
var _refresh_x_cap := 0 # 刷新件余量基数(装配集 effect_kinds 含 bonus_refresh 的行 magnitude 合计——
# 宿主冒险开始时预算注入;装配集冒险期间锁死〔契约 8〕故预算与逐停点查询等价)
var _attunement: Array[Variant] = [] # 同调装配集(活引用——宿主冒险开始注入,刷新件基数查询消费面)
func set_attunement(ids: Array[Variant]) -> void:
_attunement = ids
# 刷新件基数注入(宿主 start_adventure/resume 时点计算——X 每碰三选一重置回此基数)
func set_refresh_x_cap(total: int) -> void:
_refresh_x_cap = maxi(0, total)
func _reset_refresh_x() -> void:
_refresh_x = _attune_refresh_x_total()
_refresh_x = _refresh_x_cap
# 当前可刷新次数(X 优先 + Y 池 + 刷新存量账——呈现层余量读数口)
+3 -5
View File
@@ -21,7 +21,6 @@ var armor_type := "" # 甲类型轴快照(同上)
var _base_override: Dictionary[Variant, Variant] = {"atk": 0, "max_hp": 0, "armor_class": 0}
var _override: Array[int] = [0, 0] # 调试浮窗百分比通道 [atk_pct, hp_pct](每关新 runner 应用面)
var _gain_log: Array[Variant] = [] # 获得记录列表(三选一件/商店购买/战末奖励各一条)
var _gain_seq := 0 # 获得记录 id 发号(1 起)
var _bonus_detail: Array[Variant] = [] # 属性增益明细(带来源指回 gain_id)
var _bonus_total: Dictionary[Variant, Variant] = {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0}
var _keystone := 0 # 钥石入账累计(摘要第三件事的账面)
@@ -129,7 +128,6 @@ func reset_adventure_accounts() -> void:
gp = 0
_bonus_total = {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0}
_gain_log = []
_gain_seq = 0
_bonus_detail = []
_purchased = {}
_keystone = 0
@@ -144,11 +142,11 @@ func reset_adventure_accounts() -> void:
# 获得记录列表追加(三通道各一条——source_class 词表:curio_pick/shop_product/battle_export;
# 返回记录 id 供明细来源指回)
func record_gain(source_class: String, kind: String, detail: Dictionary) -> int:
_gain_seq += 1
var rec: Dictionary[Variant, Variant] = {"id": _gain_seq, "source_class": source_class, "kind": kind}
var rec_id := _gain_log.size() + 1 # 记录 id = 列表序派生(1 起——恢复面按 max(id) 校正)
var rec: Dictionary[Variant, Variant] = {"id": rec_id, "source_class": source_class, "kind": kind}
rec.merge(detail.duplicate(true))
_gain_log.append(rec)
return _gain_seq
return rec_id
# 统一冒险加算区单写原语(三通道统一入口:三选一属性件 source_class="curio_pick";
+1 -18
View File
@@ -49,23 +49,6 @@ var _attunement: Array[Variant] = [] # 同调装配集(adve
# 消费面:effective_ac 甲型基础 AC 层 + begin_battle enc 携带进 unit_container.spawn 英雄快照)
var _hero_attack_type := ""
var _hero_armor_type := ""
# ---- 商店共享池模式态(缺省 legacy=固定三件加定价 off 对照承载,零 RNG 零池消费;TP0 令牌池)----
# 件内状态白盒读面(断点写侧与既有取数面沿用原字段名;状态本体单点在 ShopSession)
var _shop_pool_mode: bool:
get: return _shop.pool_mode
var _pool_deck: Array[Variant]:
get: return _shop.pool_deck
var _pool_consume: Callable:
get: return _shop.pool_consume
var _pool_ticket: Callable:
get: return _shop.pool_ticket
var _shop_shelf: Array[Variant]:
get: return _shop.shelf
var _shop_visit_buys: int:
get: return _shop.visit_buys
var _shop_paid_refreshes: int:
get: return _shop.paid_refreshes
# ---- 关卡相位轴(显式 Phase enum:内部 enum + 守卫换算,对齐 行动经济 Phase 先例;
# level_result:String 与 awaiting_choice() 是 AdventureRunner/呈现层消费的外部契约面)----
enum Phase { IDLE, RUNNING, AWAITING_CHOICE, ENDED }
@@ -508,7 +491,7 @@ func _enter_node(node: Dictionary) -> bool:
"shop":
# 商店房兑付:到达即开店(覆盖层归呈现层),购买出账/
# 离开归玩家意图——零自动推进;离开确认经 continue_after_node 回选路口
if _shop_pool_mode:
if _shop.pool_mode:
_shop.open_pool() # 进店抽 3(恰一 shop_draw scope;买后全重抽同签)
node_entered.emit(node, {"gp": gp, "shelf": true})
return true