feat(凭证件裁削): 卡② 同调电池删除+完美保险迁专长+配额净删落地(迭代 31 卡②)
用户 2026-10-18 逐裁四项落码:
- T1/T2 同调电池整件删除:CURIO_KINDS 摘 kind、三字段与三处分发表分支删净、
runner 侧 _battery_pending/断点键/getter/choose_battery_target 全清(呈现层零接线=有账本无入口)。
- T3 完美保险出池:kind/字段/分发摘除,_pending_insurance 与 level_runner 注入通道
(voucher_insurance 键、set_voucher_grants 第三参)整链拆除,battle_orchestrator._fx_insurance 删。
- T4 引擎扩签 forgive_seal_miss(EFFECT_KINDS 31→32)+两账相减:新增 _perfect_forgiven 单向累加、
谓词抽成 perfect_sweep_earned()(有效误标=误标总数−豁免数),_perfect_hit_false 保持纯净=契约 2;
seal_missed 发射时机与消费点零改动=契约 3(危险直觉·守同事件订阅面在验收组里对拍)。
- T5 feats.tres 第 30 行完美保险专长:rarity rare/cap 省略/domain=battle 显式写出(战斗域首例)/
desc「本场首次封印落空,不计入完美封印判定」;限次由行 when counter(insurance_used) lt 1 承载,
do 自带 counter_id 记账由授予段消费点落账(代拍板 3 选型:单行落表,理由见实现报告)。
- T6 配额净删:TIER_QUOTAS rare 9→7、令牌池总量 104→102,validate() 硬断言过;smoke 配额锚/牌库
构成/专长行数随批换代。
- T7 验收:feat_vouchers_test 39 项全绿(出池反例/断点缺键兼容/账本保留/配额锚/装载/限次一次/
计数纯净/两账相减真值表/跨战清零/事件不吞)+forge_table 词表闭集断言 31→32。
变异验证 6 条:5 条证红;「domain battle→adventure」在本 rig 不可观测(未红),已如实登记。
- 存量缺陷顺带修:旧 _emit_row("insurance_used","",…) 空来源会触发行来源断言(旧路径无消费点故从未走红),
新订阅面给出 source_class=seal_miss。
基线(卡① 合回后 master 4f953ce8):冒烟 1151/0、单元 34 套全绿、探针 --click 全绿(user:// 存档移开态)。
This commit is contained in:
1 parent
4f953ce829
commit
072c19b4a5
10 files changed
+183
-110
No files matched your search
@@ -52,9 +52,7 @@ var _curio_paid_refreshes := 0 # 本次停点已付费刷新次数(
|
||||
# ---- 凭证件三本新账(迭代 20 T4——奇物.md 凭证件表新 5 件;F-1 刷新写错账修复承载面)----
|
||||
var _refresh_stock := 0 # 刷新存量账(冒险级——刷新券加仓;**不经 _attune_refresh_x**:X 每停点重置会吞存量=旧写错账缺陷 F-1)
|
||||
var _pending_rap := 0 # 储备金袋待注入(节点级——下一战 RAP +N,战首注入后清零)
|
||||
var _battery_pending := 0 # 同调电池待分配充能(冒险级——choose_battery_target 玩家点选消费,禁自动替选)
|
||||
var _time_sand_queue := 0 # 时沙待注入(回合级——下一战首轮 AP +N,战首入队后清零)
|
||||
var _pending_insurance := 0 # 完美保险待注入(节点级——下一战标错豁免 N 次,战首注入后清零;战内未用即过期)
|
||||
var _save_manager = null # 断点承载注入(迭代 8 卡①——null = 不写断点;模拟/冒烟缺省)
|
||||
var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递)
|
||||
# ---- 三选一停点态(迭代 10 奖励重构批)----
|
||||
@@ -210,7 +208,6 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool:
|
||||
run_ledger.adventure_counters = (bp_counters as Dictionary).duplicate(true)
|
||||
_refresh_stock = maxi(0, int(bp.get("refresh_stock", 0))) # 迭代 20 T4/T7——旧档缺键缺省 0
|
||||
run_ledger.vision_counter = {"used": maxi(0, int(bp.get("vision_counter_used", 0)))} # 迭代 22 秘宝批 T3——真视计数随断点回填(缺键=旧断点缺省 0)
|
||||
_battery_pending = maxi(0, int(bp.get("battery_pending", 0)))
|
||||
var bp_result: Dictionary[Variant, Variant] = bp.get("bonus_result", {}) as Dictionary
|
||||
if not bp_pending.is_empty():
|
||||
_pending_next_level = true
|
||||
@@ -258,9 +255,7 @@ func _reset_curio_state() -> void:
|
||||
run_ledger.adventure_counters = {}
|
||||
_refresh_stock = 0
|
||||
_pending_rap = 0
|
||||
_battery_pending = 0
|
||||
_time_sand_queue = 0
|
||||
_pending_insurance = 0
|
||||
|
||||
|
||||
# 令牌池构建(TP0 v2.2——按表 kind×tier 配额展开为持久多重集;构建序确定 = CURIO_KINDS×TIERS 逐层,
|
||||
@@ -412,18 +407,10 @@ func _apply_curio_pick(kind: String, tier: String, value: int, feat_id: String =
|
||||
_pending_rap += value # T4——储备金袋:下一战 RAP +N(节点级,战首注入后清零)
|
||||
_curio_taken["rap"] = int(_curio_taken.get("rap", 0)) + 1
|
||||
return true
|
||||
if kind == "attune_battery":
|
||||
_battery_pending += value # T4——同调电池:待分配充能(choose_battery_target 玩家点选消费——禁自动替选)
|
||||
_curio_taken["attune_battery"] = int(_curio_taken.get("attune_battery", 0)) + 1
|
||||
return true
|
||||
if kind == "time_sand":
|
||||
_time_sand_queue += value # T4——时沙:下一战首轮 AP +N(回合级池增量,不改上限)
|
||||
_curio_taken["time_sand"] = int(_curio_taken.get("time_sand", 0)) + 1
|
||||
return true
|
||||
if kind == "perfect_insurance":
|
||||
_pending_insurance += value # T4——完美保险:下一战标错豁免 N 次(节点级,未用即过期)
|
||||
_curio_taken["perfect_insurance"] = int(_curio_taken.get("perfect_insurance", 0)) + 1
|
||||
return true
|
||||
if kind == "relic":
|
||||
if not _feats.has(feat_id):
|
||||
_feats.append(feat_id)
|
||||
@@ -593,29 +580,6 @@ func refresh_stock() -> int:
|
||||
return _refresh_stock
|
||||
|
||||
|
||||
# 同调电池充能分配(T4——玩家点选哪件已装配主动秘宝 +N;**禁自动替选**:
|
||||
# 无待分配/件不在装配集/非主动充能件=拒绝零副作用)
|
||||
func choose_battery_target(item_id: String) -> bool:
|
||||
if _battery_pending <= 0:
|
||||
push_error("[冒险结构] 电池分配拒绝——无待分配充能")
|
||||
return false
|
||||
if not _attunement.has(item_id):
|
||||
push_error("[冒险结构] 电池分配拒绝——件不在装配集: %s" % item_id)
|
||||
return false
|
||||
var arow: Dictionary[Variant, Variant] = db.treasure_item_row(item_id)
|
||||
if String(arow.get("form", "")) != "active_charged":
|
||||
push_error("[冒险结构] 电池分配拒绝——非主动充能件: %s" % item_id)
|
||||
return false
|
||||
_battery_pending -= 1
|
||||
run_ledger.attune_charges[item_id] = int(run_ledger.attune_charges.get(item_id, 0)) + 1
|
||||
return true
|
||||
|
||||
|
||||
# 待分配充能读数(呈现层电池选件面数据源)
|
||||
func battery_pending() -> int:
|
||||
return _battery_pending
|
||||
|
||||
|
||||
# 节点停点在途态读回(组合根重 present 用——candidates 值拷贝)
|
||||
func node_curio_pending_state() -> Dictionary:
|
||||
return {
|
||||
@@ -917,10 +881,9 @@ func _start_current_level() -> bool:
|
||||
# 迭代 20 T2——cap 检查回调四参注入)
|
||||
_runner.set_shop_pool(_curio_deck, _consume_pool_purchase, _feat_ticket_consider, _curio_cap_ok)
|
||||
# 迭代 20 T4——凭证件三账注入(节点级/回合级一次性:注入即清零,未用即过期=寿命档语义)
|
||||
_runner.set_voucher_grants(_pending_rap, _time_sand_queue, _pending_insurance)
|
||||
_runner.set_voucher_grants(_pending_rap, _time_sand_queue)
|
||||
_pending_rap = 0
|
||||
_time_sand_queue = 0
|
||||
_pending_insurance = 0
|
||||
# 三选一道具件跨关携带注入(迭代 10)——迭代 11 第①批 T7 退役:aux 卡出池后 carry 恒空集,
|
||||
# 注入面随停点渠道退役拆除(容器字段保留=替换子交互机械惰性承载,零投放零行为)
|
||||
level_started.emit(level_index, String(_runner.level_row.get("display_name", "")))
|
||||
@@ -1073,7 +1036,6 @@ func _snapshot_breakpoint() -> void:
|
||||
"vision_counter_used": int(run_ledger.vision_counter.get("used", 0)), # 迭代 22 秘宝批 T3——真视使用计数随断点(续玩跨战账不丢)
|
||||
"refresh_stock": _refresh_stock, # 迭代 20 T4/T7——刷新存量账随断点(F-1 新账)
|
||||
"attune_refresh_y": _attune_refresh_y, # 2026-10-13 缺陷修批——Y 冒险周期池余量随断点(续玩不再自参数面整额重注入=堵「用完退菜单再续玩满血复活」可利用漏洞;扩列向后兼容——旧档缺键回退参数面)
|
||||
"battery_pending": _battery_pending, # 迭代 20 T4/T7——电池待分配充能随断点
|
||||
"bonus_result": _curio_result.duplicate(true), # 已兑付待推进态(空 = 无——中断续玩不重兑付)
|
||||
"keystone_drops": _keystone_drops.duplicate(true), # 逐杀掉落明细(摘要归因续接——迭代 10)
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ var _fx_bonus_delta := {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0} #
|
||||
var _fx_new_resource_types := {} # 本战已见资源类型集(地质学家 fact new_resource_type 判定——battle 域)
|
||||
var _fx_pending_reveals: Array[Dictionary] = [] # 揭示效果待兑队列(见血开窍/斩首学者/地质学家/跳格采掘——授予段末统一兑付,防轮 facts 迭代中追加重入)
|
||||
var _fx_revealing := false # fx 揭示兑付中标记(_on_cell_revealed 缓冲旁路——fx 揭示的奖励由兑付点直接入账,防二次缓冲二次兑付)
|
||||
var _fx_insurance := 0 # 完美保险余量(迭代 20 T4——本战标错豁免次数;消费于 seal_miss 首见判定)
|
||||
# 特性运行态(内容数据驱动扩展批 T3——relic 持有集经 enc.feats 注入:效果行为=数据行 triggers 经
|
||||
# 效果引擎分发;魔矢每战首次计数 battle 域。空集=零扰动)
|
||||
var _feat_first_dig_used := false
|
||||
@@ -265,6 +264,7 @@ func attune_convert_state() -> Dictionary:
|
||||
var _seal_miss_seen := {} # 封印未中行去重(每安全格实例一次)
|
||||
var _perfect_hit_true := 0 # 板级完美排雷计数(install 重置)
|
||||
var _perfect_hit_false := 0
|
||||
var _perfect_forgiven := 0 # 完美保险豁免累计(迭代 31 卡②——单向累加自有账;契约 2 禁改写 _perfect_hit_false)
|
||||
var _hero_atk := 0 # 主角攻击基值快照(encounter.hero_atk;E4 收口——表值运行期不可变)
|
||||
|
||||
|
||||
@@ -415,11 +415,10 @@ func begin_battle(enc: Dictionary) -> bool:
|
||||
var ap_bonus: int = int(enc.get("hero_ap_bonus", 0)) + int(enc.get("voucher_time_sand", 0)) # 迭代 20 T4——时沙同通道(首轮池增量,不改上限)
|
||||
if ap_bonus > 0:
|
||||
action_economy.queue_ap_delta(ap_bonus)
|
||||
# 迭代 20 T4——储备金袋(节点级 RAP 注入)与完美保险(标错豁免次数)接收
|
||||
# 迭代 20 T4——储备金袋(节点级 RAP 注入)接收(完美保险注入通道随迭代 31 卡② 拆除——改由 feats.tres 订阅承载)
|
||||
var voucher_rap: int = int(enc.get("voucher_rap", 0))
|
||||
if voucher_rap > 0:
|
||||
action_economy.grant_reserve_ap(voucher_rap)
|
||||
_fx_insurance = int(enc.get("voucher_insurance", 0))
|
||||
# 工兵晨令直调拆除(内容数据驱动扩展批 T4——round_start grant_ap(mode:queue) 订阅行承载,
|
||||
# when round_index ≤ effective_rounds 行字段 value_from 定影;发射位先于轮切换=当轮兑现)
|
||||
# round_start 发射+施加(内容数据驱动扩展批 T3——发射位先于行动经济轮切换:树规则 grant_ap
|
||||
@@ -470,6 +469,7 @@ func _install_new_board(during_round := false) -> bool:
|
||||
_seal_miss_seen.clear()
|
||||
_perfect_hit_true = 0 # 板级完美计数随 install 重置
|
||||
_perfect_hit_false = 0
|
||||
_perfect_forgiven = 0 # 豁免累计随 install 重置(domain=battle 每战清零)
|
||||
_board_from_midround_refresh = during_round # 轮内刷新装板 = 刷新图(清图奖励不发);常规换图/开战装板 = false
|
||||
_board_seq += 1
|
||||
board_changed.emit()
|
||||
@@ -916,7 +916,7 @@ func _grant_clear_reward(ri: int) -> void:
|
||||
var snap = _reward_economy.grant_clear()
|
||||
if not (snap is Dictionary):
|
||||
return
|
||||
var perfect: bool = _perfect_hit_false == 0 and _perfect_hit_true >= 1
|
||||
var perfect: bool = perfect_sweep_earned()
|
||||
var first_ok := _grant_clear_identity(snap, ri, "(清图奖励)")
|
||||
var second_ok := false
|
||||
if perfect and first_ok:
|
||||
@@ -1291,3 +1291,9 @@ func _fatal(msg: String) -> void:
|
||||
push_error("[战斗结算/fatal] " + msg)
|
||||
battle_result = "fatal_error" # release 构建剥离 assert 后的唯一阻断面——受理/结算/刷新入口全查 battle_result == ""
|
||||
assert(false, msg)
|
||||
|
||||
|
||||
## 完美排雷谓词(迭代 31 卡② T4——两账相减:有效误标=误标总数−豁免数)
|
||||
## 契约 2:_perfect_hit_false 保持纯净,豁免只累加 _perfect_forgiven,禁回退式改写与拦截式吞事件。
|
||||
func perfect_sweep_earned() -> bool:
|
||||
return _perfect_hit_false - _perfect_forgiven <= 0 and _perfect_hit_true >= 1
|
||||
@@ -38,7 +38,10 @@ const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open
|
||||
# 迭代 22 秘宝实装批 T3 扩签一型:mine_count_preview=危险格数量预告(巢穴预告——board_installed
|
||||
# 订阅 do;只报数量不标位置、不碰危险格分布=棋盘事实不可变契约;参数面常时 kind 不入本词表——
|
||||
# 它们无订阅行,schema 行内 effect_kinds 校验走 treasure_item_table 自有词表)
|
||||
"mine_count_preview"]
|
||||
"mine_count_preview",
|
||||
# 迭代 31 卡② 凭证件裁削批 T4 扩签一型:forgive_seal_miss=完美保险(本场首次封印落空不计入完美
|
||||
# 封印判定——订阅 seal_missed 的豁免效果,消费点在授予段;feats.tres 首例 domain=battle 行)
|
||||
"forgive_seal_miss"]
|
||||
# 注:rewrite_board 已除名(迭代 20 T9——净化工兵随老 27 件退役,V14 连带清理;
|
||||
# 编排器消费分支 T1 先行摘除)
|
||||
|
||||
|
||||
@@ -475,13 +475,11 @@ func _start_battle(node: Dictionary) -> bool:
|
||||
"battle_index": _battle_index(),
|
||||
"voucher_rap": _voucher_rap,
|
||||
"voucher_time_sand": _voucher_time_sand,
|
||||
"voucher_insurance": _voucher_insurance,
|
||||
"node_type": String(node.get("type", ""))}):
|
||||
push_error("[关卡节点地图] 战斗启动失败(depth %s)" % str(node.get("node_depth", -1)))
|
||||
return false
|
||||
_voucher_rap = 0 # 迭代 20 T4——节点级一次性:注入即消费(战斗未启动则保留至下次注入前不清)
|
||||
_voucher_time_sand = 0
|
||||
_voucher_insurance = 0
|
||||
return true
|
||||
|
||||
|
||||
@@ -643,13 +641,11 @@ func set_run_ledger(l: RunLedger) -> void:
|
||||
# battle begin 消费后归零;缺省 0=零扰动)
|
||||
var _voucher_rap := 0
|
||||
var _voucher_time_sand := 0
|
||||
var _voucher_insurance := 0
|
||||
|
||||
|
||||
func set_voucher_grants(rap: int, time_sand: int, insurance: int) -> void:
|
||||
func set_voucher_grants(rap: int, time_sand: int) -> void:
|
||||
_voucher_rap = maxi(0, rap)
|
||||
_voucher_time_sand = maxi(0, time_sand)
|
||||
_voucher_insurance = maxi(0, insurance)
|
||||
|
||||
|
||||
# 同调主动件充能账骑库存面注入(迭代 11 第①批 T6 原语义 + 迭代 27 T3 换代——账本住
|
||||
|
||||
@@ -296,12 +296,6 @@ func _judge_seal(evt: Dictionary, ri: int) -> void:
|
||||
if oc._seal_miss_seen.has(cell):
|
||||
return # 每格实例一次去重(归因行与负向兑付同键——防逐轮惩罚轰炸)
|
||||
oc._seal_miss_seen[cell] = true
|
||||
# 完美保险(迭代 20 T4——本战下一次标错不破坏完美资格:_perfect_hit_false 回退=本次标错
|
||||
# 对完美谓词无痕;只保一次/件,节点级用完即止)
|
||||
if oc._fx_insurance > 0:
|
||||
oc._fx_insurance -= 1
|
||||
oc._perfect_hit_false -= 1
|
||||
oc._emit_row("insurance_used", "", cell, ri, "完美保险·标错豁免", 0, {"left": oc._fx_insurance}, "")
|
||||
var hl := ""
|
||||
if oc._perfect_hit_false == 1:
|
||||
hl = "perfect_broken" # 本板完美谓词已破的归因锚
|
||||
@@ -314,6 +308,13 @@ func _judge_seal(evt: Dictionary, ri: int) -> void:
|
||||
for h in oc._fx_emit("seal_missed", {"cell": cell, "round": ri}):
|
||||
if String(h.get("kind", "")) == "grant_ap" and String(h.get("mode", "")) == "queue":
|
||||
oc.action_economy.queue_ap_delta(int(h.get("value", 0)))
|
||||
elif String(h.get("kind", "")) == "forgive_seal_miss":
|
||||
# 完美保险(迭代 31 卡② T4——订阅式豁免:本战首次标错计一次豁免,只累加自有账
|
||||
# _perfect_forgiven,绝不回写 _perfect_hit_false=契约 2 计数纯净;发射时机与消费点零改动=契约 3)
|
||||
oc._perfect_forgiven += 1
|
||||
_apply_counter_hit(h) # 豁免同时记账(insurance_used battle 域——下次标错 when lt 1 不再命中)
|
||||
oc._emit_row("insurance_used", "seal_miss", cell, ri, "完美保险·标错豁免", 0,
|
||||
{"forgiven": oc._perfect_forgiven}, "")
|
||||
var snap = oc._reward_economy.grant(cell)
|
||||
if not (snap is Dictionary):
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user