feat(T2-T6): 五词注释换代——完美排雷→完美封印/板级→整图/门票→专长凭证/正主→现行事实源/落籍→已入库
全局 sed 替换 89 处命中清零(S11 绿)。修复: - 移交 3 处保留原词(shop.tres:86 display_name、curio_controller:165-166 玩家文案) - 豁免 enemy.tres:653 历史注记保持"已落籍" - static_scan.sh 词表追加行与头注恢复禁「」引举句式 - S11 规则文件自身不被自身规则误伤(闸门自指豁免生效)
This commit is contained in:
1 parent
85dce2c77d
commit
b6629d6848
39 files changed
+118
-118
No files matched your search
@@ -56,7 +56,7 @@ var _time_sand_queue := 0 # 时沙待注入(回合级——下
|
||||
var _save_manager = null # 断点承载注入(null = 不写断点;模拟/冒烟缺省)
|
||||
var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递)
|
||||
# ---- 三选一停点态 ----
|
||||
var _curio_taken := {} # 件获取次数计数(kind 维度派生账本——断点附随件与摘要读数承载;池库存正主=_curio_deck)
|
||||
var _curio_taken := {} # 件获取次数计数(kind 维度派生账本——断点附随件与摘要读数承载;池库存现行事实源=_curio_deck)
|
||||
var _curio_deck: Array[Variant] = [] # 令牌池(TP0 v2.2——持久多重集,元素 {"kind","tier"};洗牌抽候选/选中踢池未选回池/池耗即枯竭;商店货架同库共账;规则改写型特性带=relic 令牌随表追加)
|
||||
var _feats: Array[String] = [] # 特性持有集(局内随机渠道获得、冒险级跨关携带、收束清零;🔴 层级纪律承载面:不入同调位不入局外树)
|
||||
var _tree_rules: Array[Variant] = [] # 树 rule 键集(Fork 激活侧 effects 透传;下传 enc.tree_rules 消费面)
|
||||
@@ -64,9 +64,9 @@ var _curio_pending := {} # 停点态:{"candidates": Array, "p
|
||||
var _curio_result := {} # 已兑付待推进态(curio_resolved 载荷副本——中断续玩不重兑付)
|
||||
var _keystone_drops: Array[Variant] = [] # Boss 逐杀掉落明细(additive 摘要键 keystone_drops——结算明细/复盘归因数据源)
|
||||
var _node_curio_pending := {} # 奖励节点三选一停点态(共享池;断点不载:续玩重建到选路停点重走,恢复的计数器保证同候选重抽)
|
||||
var _feat_ticket_pity := 0 # 门票保底计数(T5——展示次数:节点开面/货架抽签/刷新重展各计一次;触发清零)
|
||||
var _feat_ticket_sold := 0 # 门票限购计数(T5——选中/买下即 +1;拿到即开不进持有集)
|
||||
var _feat_ticket_appeared := 0 # 门票出现计数(T5——quota 上限面)
|
||||
var _feat_ticket_pity := 0 # 专长凭证保底计数(T5——展示次数:节点开面/货架抽签/刷新重展各计一次;触发清零)
|
||||
var _feat_ticket_sold := 0 # 专长凭证限购计数(T5——选中/买下即 +1;拿到即开不进持有集)
|
||||
var _feat_ticket_appeared := 0 # 专长凭证出现计数(T5——quota 上限面)
|
||||
var _shop_mode := "legacy" # 商店模式("legacy"=固定三件加定价〔off 对照承载,缺省零扰动〕/"pool"=共享池抽 3 买 1 重抽;真实入口 main.gd 显式投 pool)
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@ func pool_stock(kind: String) -> int:
|
||||
# 未知 kind 拒绝(货架词表封闭的前置防御)。
|
||||
func _consume_pool_purchase(kind: String, tier: String) -> bool:
|
||||
if kind == "feat_ticket":
|
||||
return _redeem_feat_ticket() # T5——门票买下即开(零摘牌不进持有集;临时停点开专长三选一面)
|
||||
return _redeem_feat_ticket() # T5——专长凭证买下即开(零摘牌不进持有集;临时停点开专长三选一面)
|
||||
if not db.adventure.CURIO_KINDS.has(kind):
|
||||
push_error("[冒险结构] 商店购买消费拒绝——件不在池词表: %s" % kind)
|
||||
return false
|
||||
@@ -659,7 +659,7 @@ func _finish_node_bonus(picked: String, value: int, tier: String = "", feat_id:
|
||||
# 自动回池;池耗即枯竭——余库不足 N kind 时出齐剩余,空库 = 零候选合法态)。候选 = 令牌字典
|
||||
# {"kind","tier"}。消费 reward_pick 封闭流——一次停点恰一 scope,同种子同候选。
|
||||
# 渠道白名单过滤(渠道轴定位:关底 Boss 击败=通关渠道只出专长(feat 令牌);
|
||||
# 奖励节点/商店只出属性值提升+资源(非 relic 令牌),专长在非 Boss 渠道只以门票形态出现(T5)。
|
||||
# 奖励节点/商店只出属性值提升+资源(非 relic 令牌),专长在非 Boss 渠道只以专长凭证形态出现(T5)。
|
||||
# 过滤式而非物理拆池:deck 物理结构/存档键 bonus_deck 混编余库/消耗语义(选中踢池未选回池)原样,
|
||||
# 白名单在候选视图层生效——配额结构锚 TIER_QUOTAS 70/25/3=98 零改动(专长令牌本系活行追加面,在锚外)。
|
||||
# 曝光槽:非 Boss 渠道三选一 = **2 格全池 + 1 格优秀档以上子池**
|
||||
@@ -746,7 +746,7 @@ func _draw_curio_candidates(channel: String = "reward_node") -> Array:
|
||||
sub = [] # 子池枯竭——曝光槽回退全池续取
|
||||
continue
|
||||
break # 全池枯竭——出齐剩余(池空直通同族兜底)
|
||||
# T5 门票注入(非 Boss 渠道唯一专长入口——替换末位候选占一席,候选数不变;判定含 pity 清零记账)
|
||||
# T5 专长凭证注入(非 Boss 渠道唯一专长入口——替换末位候选占一席,候选数不变;判定含 pity 清零记账)
|
||||
if channel == "reward_node" and not out.is_empty() and _feat_ticket_consider(rg):
|
||||
out[out.size() - 1] = {"kind": "feat_ticket", "tier": "excellent"}
|
||||
return out
|
||||
@@ -766,7 +766,7 @@ func _curio_cap_ok(kind: String, feat_id: String = "") -> bool:
|
||||
return int(_curio_taken.get(kind, 0)) < cap
|
||||
|
||||
|
||||
# —— 专长获取门票(T5——非 Boss 渠道的专长入口;四口径契约④:拿到即开不可囤积/
|
||||
# —— 专长获取专长凭证(T5——非 Boss 渠道的专长入口;四口径契约④:拿到即开不可囤积/
|
||||
# 罕见只在概率不在价格/一局限购一次/计步保底连续 5 展示未出第 6 必出——计数=展示次数、刷新
|
||||
# 重展计入、节点与商店共享、触发清零、限购满不再触发。调用即一次展示判定与记账)——
|
||||
func _feat_ticket_consider(rg: RandomNumberGenerator) -> bool:
|
||||
@@ -783,7 +783,7 @@ func _feat_ticket_consider(rg: RandomNumberGenerator) -> bool:
|
||||
return offer
|
||||
|
||||
|
||||
# 门票兑付(拿到即开——停点候选替换为专长三选一;不进持有集/零摘牌;限购计数 +1):
|
||||
# 专长凭证兑付(拿到即开——停点候选替换为专长三选一;不进持有集/零摘牌;限购计数 +1):
|
||||
# 节点停点=本地替换(呈现层读在途态重绘);店内无停点=临时停点 + payload.context 标记(呈现层
|
||||
# 重 present 无胜利总结面,确认后只关面回店)。
|
||||
func _redeem_feat_ticket() -> bool:
|
||||
@@ -791,7 +791,7 @@ func _redeem_feat_ticket() -> bool:
|
||||
_feat_ticket_pity = 0
|
||||
var cands: Array[Variant] = _draw_curio_candidates("level_clear") # 专长池(与通关渠道同白名单)
|
||||
if cands.is_empty():
|
||||
push_error("[冒险结构] 门票兑付失败——专长池空集")
|
||||
push_error("[冒险结构] 专长凭证兑付失败——专长池空集")
|
||||
_feat_ticket_sold -= 1
|
||||
return false
|
||||
if not _node_curio_pending.is_empty():
|
||||
@@ -1028,8 +1028,8 @@ func _snapshot_breakpoint() -> void:
|
||||
"bonus_deck": _curio_deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原)
|
||||
"relics": _feats.duplicate(), # 特性持有集(局内随机渠道获得态续玩防丢失)
|
||||
"bonus_pending": _curio_pending.duplicate(true), # 三选一停点态(空 = 无停点——选择停点可中断契约)
|
||||
"feat_ticket_pity": _feat_ticket_pity, # T5 门票保底计数(扩列向后兼容——旧档缺键缺省 0)
|
||||
"feat_ticket_sold": _feat_ticket_sold, # T5 门票限购计数(同上)
|
||||
"feat_ticket_pity": _feat_ticket_pity, # T5 专长凭证保底计数(扩列向后兼容——旧档缺键缺省 0)
|
||||
"feat_ticket_sold": _feat_ticket_sold, # T5 专长凭证限购计数(同上)
|
||||
"adventure_counters": run_ledger.adventure_counters.duplicate(true), # adventure 域计数器随断点(续玩跨战账不丢)
|
||||
"vision_counter_used": int(run_ledger.vision_counter.get("used", 0)), # 真视使用计数随断点(续玩跨战账不丢)
|
||||
"refresh_stock": _refresh_stock, # 刷新存量账随断点
|
||||
|
||||
@@ -62,7 +62,7 @@ var _verdict_seg = null # VerdictSegment(⑤判定段——返回裁定,
|
||||
var _refresh_used_this_round := 0 # 每轮刷新计数(Active 相位合计,兜底上限 = ActionEconomyTable.refresh_cap_per_round)
|
||||
var _board_seq := 0 # 板序号(本战斗第几张板——快照归因用)
|
||||
var _board_from_midround_refresh := false # 装板 provenance:轮内刷新换来的图 = true(清图奖励守卫——刷新图不发清图奖励)
|
||||
var _seal_consumed := {} # 兑付资格以危险格实例为键(板级;换图重置)
|
||||
var _seal_consumed := {} # 兑付资格以危险格实例为键(整图;换图重置)
|
||||
# 同调装配运行态(begin_battle 经 enc.attunement 注入;off=空集全部效果零扰动)
|
||||
var attunement: Array[Variant] = [] # 装备中同调件 item_id 集
|
||||
var _ledger: RunLedger = null # 共享四本账(begin_battle 经 enc["ledger"] 持引用;缺省新账=调试面)
|
||||
@@ -259,7 +259,7 @@ func attune_convert_state() -> Dictionary:
|
||||
# 流派档位质变=FeatsEngine 纯函数求值
|
||||
# (档位机制本身系引擎基建非内容效果),两运行态注伤害控制器:档一 rider+1 / 档二 rider 可暴击)
|
||||
var _seal_miss_seen := {} # 封印未中行去重(每安全格实例一次)
|
||||
var _perfect_hit_true := 0 # 板级完美排雷计数(install 重置)
|
||||
var _perfect_hit_true := 0 # 整图完美封印计数(install 重置)
|
||||
var _perfect_hit_false := 0
|
||||
var _perfect_forgiven := 0 # 完美保险豁免累计(单向累加自有账;契约 2 禁改写 _perfect_hit_false)
|
||||
var _hero_atk := 0 # 主角攻击基值快照(encounter.hero_atk;E4 收口——表值运行期不可变)
|
||||
@@ -439,7 +439,7 @@ func _install_new_board(during_round := false) -> bool:
|
||||
# 全局作用域变异决议(装板序内前置于 roll_board:图级偏斜旋钮须在资源
|
||||
# 摇号前定型;全局门控与板无关〔节点身份+unlock+board_types〕,确定性取用零取号)。
|
||||
# boss/elite 图命中全局型 → 写 board_variants(_place_variants 见非空即跳 region=替换制);
|
||||
# 全局池空 → 板级字段留空(_place_variants 原路走 region=兜底回落合法态)。
|
||||
# 全局池空 → 整图字段留空(_place_variants 原路走 region=兜底回落合法态)。
|
||||
_resolve_global_variant(board)
|
||||
var res: Dictionary[Variant, Variant] = minesweeper.install_board(board, during_round)
|
||||
if not res.accepted:
|
||||
@@ -464,7 +464,7 @@ func _install_new_board(during_round := false) -> bool:
|
||||
_place_variants(board)
|
||||
_seal_consumed.clear() # 换图新雷 = 新实例,资格自然重置(行动经济 Rule 8)
|
||||
_seal_miss_seen.clear()
|
||||
_perfect_hit_true = 0 # 板级完美计数随 install 重置
|
||||
_perfect_hit_true = 0 # 整图完美计数随 install 重置
|
||||
_perfect_hit_false = 0
|
||||
_perfect_forgiven = 0 # 豁免累计随 install 重置(domain=battle 每战清零)
|
||||
_board_from_midround_refresh = during_round # 轮内刷新装板 = 刷新图(清图奖励不发);常规换图/开战装板 = false
|
||||
@@ -476,7 +476,7 @@ func _install_new_board(during_round := false) -> bool:
|
||||
|
||||
|
||||
# ---- 全局作用域变异 决议(装板序内 roll_board 之前)----
|
||||
# boss/elite 图命中全局型:写板级 board_variants(恰一行)+ 注入资源面偏斜旋钮(图级投影在
|
||||
# boss/elite 图命中全局型:写整图 board_variants(恰一行)+ 注入资源面偏斜旋钮(图级投影在
|
||||
# RewardEconomy.roll_board 消费);不消费 variant_place 流(全局取用确定性——零取号合法态)。
|
||||
# 全局池空(含 L1 Boss 免疫/unlock 门控未达):字段留空、旋钮归零——_place_variants 原路走
|
||||
# region 布置 = 兜底回落(保守向后兼容,防配置缺行静默裸奔——provisional)。
|
||||
@@ -500,8 +500,8 @@ func _resolve_global_variant(board: BoardData) -> void:
|
||||
# (关卡序号−1)×per_level_bonus——基数为候选池而非总格数(初始展开
|
||||
# 占全板 56–67%,总格数基数使有效密度膨胀 4–6 倍、L1 小板极端全池覆盖;percent 语义 = 占可挖格比例,
|
||||
# 关卡递增由 per_level_bonus 绝对格数承载);连通片生长(8 邻),单片 ≤ pack_max(2×2 / 1×4 / 1×3+1 等形)。
|
||||
# 替换制(全局作用域变异):板级 board_variants 非空 = 本图已带全局型,跳过 region
|
||||
# 布置(每图一型的板级推广:普通图=region,Boss/精英图=global);空 = 原路径(含 Boss 图全局池空回落)。
|
||||
# 替换制(全局作用域变异):整图 board_variants 非空 = 本图已带全局型,跳过 region
|
||||
# 布置(每图一型的整图推广:普通图=region,Boss/精英图=global);空 = 原路径(含 Boss 图全局池空回落)。
|
||||
func _place_variants(board: BoardData) -> void:
|
||||
if not board.board_variants.is_empty():
|
||||
return
|
||||
@@ -905,7 +905,7 @@ func _submit_flat_hero(source_class: String, display: String, power: int, cell:
|
||||
|
||||
# 封印判定批:标中 = 该危险格资源的正向兑付(每雷实例一次;高光 = 强制检查点);
|
||||
# 标空 = "封印未中"归因行 + 该安全格资源的负向兑付(同键去重——每格实例一次)。
|
||||
# 清图批:清图奖励对象恰好发一次;完美排雷追加第二份同身份兑付(grant_clear 本身恰一次)。
|
||||
# 清图批:清图奖励对象恰好发一次;完美封印追加第二份同身份兑付(grant_clear 本身恰一次)。
|
||||
# 高光行 value = 实际有效兑付份数(禁记名义值;首份零兑付 → 降级不发)。
|
||||
func _grant_clear_reward(ri: int) -> void:
|
||||
if _board_from_midround_refresh:
|
||||
@@ -919,10 +919,10 @@ func _grant_clear_reward(ri: int) -> void:
|
||||
if perfect and first_ok:
|
||||
second_ok = _grant_clear_identity(snap, ri, "(完美第二份)")
|
||||
if perfect and first_ok:
|
||||
_emit_row("highlight", "clear_reward", Vector2i(-1, -1), ri, "完美排雷!清图奖励 ×2", (2 if second_ok else 1), {}, "perfect_sweep")
|
||||
_emit_row("highlight", "clear_reward", Vector2i(-1, -1), ri, "完美封印!清图奖励 ×2", (2 if second_ok else 1), {}, "perfect_sweep")
|
||||
|
||||
|
||||
# 清图奖励 = 板级独立对象(不属于任何一格):兑付形态按其 cell_type 的正向字典形态走,
|
||||
# 清图奖励 = 整图独立对象(不属于任何一格):兑付形态按其 cell_type 的正向字典形态走,
|
||||
# 行值全部取快照(身份批 roll 值)。返回实际有效兑付。
|
||||
# 同步开单(sync)——完美第二份与高光份数的流程依赖需要同步读数(开单权归流程);
|
||||
# 同步路径内先按序结清段内排队单据(B 模式保序),随后本批无视结账政策当场兑现。
|
||||
@@ -1206,7 +1206,7 @@ func presentation_snapshot() -> Dictionary:
|
||||
"hero": hero,
|
||||
"enemies": enemies,
|
||||
"hero_effects": _status_effects.query_active("hero").duplicate(true), # 值拷贝出户(快照消费方直改不渗入状态容器)
|
||||
# 板级变异投影(呈现横幅/常驻角标唯一读取面;
|
||||
# 整图变异投影(呈现横幅/常驻角标唯一读取面;
|
||||
# 空数组 = 无全局型合法态:普通图与全局池空回落图恒空)
|
||||
"board_variants": (minesweeper.current_board().board_variant_ids().duplicate()
|
||||
if minesweeper.current_board() != null else ([] as Array[String])),
|
||||
@@ -1289,7 +1289,7 @@ func _fatal(msg: String) -> void:
|
||||
assert(false, msg)
|
||||
|
||||
|
||||
## 完美排雷谓词(两账相减:有效误标=误标总数−豁免数)
|
||||
## 完美封印谓词(两账相减:有效误标=误标总数−豁免数)
|
||||
## 契约 2:_perfect_hit_false 保持纯净,豁免只累加 _perfect_forgiven,禁回退式改写与拦截式吞事件。
|
||||
func perfect_sweep_earned() -> bool:
|
||||
return _perfect_hit_false - _perfect_forgiven <= 0 and _perfect_hit_true >= 1
|
||||
@@ -14,7 +14,7 @@ var spawn_center := Vector2i.ZERO
|
||||
var mines := {} # Vector2i → true
|
||||
var digits := {} # Vector2i → int(安全格恒有值;数字恒真 = 8 邻雷数)
|
||||
var variants := {} # Vector2i → Array[String](生成期快照,抗表重载)
|
||||
var board_variants: Array[String] = [] # 板级变异 id 集(scope=global 整图作用域——
|
||||
var board_variants: Array[String] = [] # 整图变异 id 集(scope=global 整图作用域——
|
||||
# 战斗编排装板决议写入,随图生灭同 variants;普通图恒空)
|
||||
var board_type := "" # 图类型标签(词表 v1.0:dungeon/underdark;玩家侧显示名「地图类型」)
|
||||
var level_index: int = 1
|
||||
@@ -50,7 +50,7 @@ func variant_ids(c: Vector2i) -> Array:
|
||||
return variants.get(c, [])
|
||||
|
||||
|
||||
# 板级变异只读出口(scope=global 行集——呈现快照/断言消费;空 = 无全局型合法态)
|
||||
# 整图变异只读出口(scope=global 行集——呈现快照/断言消费;空 = 无全局型合法态)
|
||||
func board_variant_ids() -> Array[String]:
|
||||
return board_variants
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ const TABLE_MANIFEST := {
|
||||
"settlement": "settlement.tres",
|
||||
"level": "level.tres",
|
||||
"difficulty": "difficulty.tres",
|
||||
"shop": "shop.tres", # ShopTable(表与 schema 落籍归数据面——本处只接线加载与消费)
|
||||
"meta": "meta.tres", # MetaTable 四行族(schema 与表同源落籍)
|
||||
"shop": "shop.tres", # ShopTable(表与 schema 已入库归数据面——本处只接线加载与消费)
|
||||
"meta": "meta.tres", # MetaTable 四行族(schema 与表同源已入库)
|
||||
"meta_tree": "meta_tree.tres", # MetaTreeTable 12 节点(定义表 Rule 4 豁免——天赋树.md v0.8 结构事实源)
|
||||
"treasure_items": "treasure_items.tres", # TreasureItemTable 六行(定义表 Rule 4 豁免;罗盘 retired/失义件 deferred 标记见 schema 头注)
|
||||
"adventure": "adventure.tres", # AdventureTable(大奖励与钥石行值单点)
|
||||
@@ -39,10 +39,10 @@ var reward: RewardTable
|
||||
var settlement: SettlementTable
|
||||
var level: LevelTable
|
||||
var difficulty: DifficultyTable
|
||||
# ShopTable 类型化持用(schema class_name 已落籍;
|
||||
# ShopTable 类型化持用(schema class_name 已已入库;
|
||||
# 消费面一律走下方 shop_* 访问器,禁直读行集)
|
||||
var shop: ShopTable = null
|
||||
# MetaTable 类型化持用(schema 与表同源落籍)
|
||||
# MetaTable 类型化持用(schema 与表同源已入库)
|
||||
var meta: MetaTable
|
||||
var meta_tree: MetaTreeTable # 类型化持用(消费面走 tree_node 访问器)
|
||||
var treasure_items: TreasureItemTable # 类型化持用(消费面走 treasure_* 访问器)
|
||||
@@ -277,7 +277,7 @@ func treasure_attunement_rows() -> Array:
|
||||
# 行族四轴(数据契约,行集归 shop.tres):gp_drops {tier, mean, roll_min, roll_max} ·
|
||||
# level_gp_bonus {level_index, bonus} · products {product_id, display_name, attr, flat_value,
|
||||
# base_price, price_increment} · price_level_bonus {level_index, bonus}。
|
||||
# 行族经 ShopTable 同名数组属性读取(.get 容缺——表落籍前查询恒空,掉落按 0 兑付的兜底在调用方)。
|
||||
# 行族经 ShopTable 同名数组属性读取(.get 容缺——表已入库前查询恒空,掉落按 0 兑付的兜底在调用方)。
|
||||
|
||||
func shop_gp_drop_row(tier: String) -> Dictionary:
|
||||
for row in _shop_rows("gp_drops"):
|
||||
@@ -334,7 +334,7 @@ func shop_price_b() -> float:
|
||||
return float(shop.price_b) if shop != null else 0.0
|
||||
|
||||
|
||||
# 行族数组读取(ShopTable 属性名 = 行族名;表未落籍/属性缺失 = 空集非错误态)
|
||||
# 行族数组读取(ShopTable 属性名 = 行族名;表未已入库/属性缺失 = 空集非错误态)
|
||||
func _shop_rows(family: String) -> Array:
|
||||
if shop == null:
|
||||
return []
|
||||
@@ -387,7 +387,7 @@ func _meta_rows(family: String) -> Array:
|
||||
# 设计权威 design/gdd/systems/跨局循环/锻造工坊.md v0.6:默认值归本表常驻持有(hero.tres 两轴已删——
|
||||
# 契约 2);路线行族=攻防数值成长唯一数据面(契约 1)。数值全 provisional 归 M4。
|
||||
|
||||
# 两根类型轴默认值(表未落籍=裸体态兜底 normal/light——与 ForgeTable 缺省值同口径)
|
||||
# 两根类型轴默认值(表未已入库=裸体态兜底 normal/light——与 ForgeTable 缺省值同口径)
|
||||
func forge_default_attack_type() -> String:
|
||||
return String(forge.default_attack_type) if forge != null else "normal"
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ func cross_validate(loaded: Dictionary, push_diag: Callable) -> void:
|
||||
for row in shp.pool_shelf:
|
||||
var kind: String = String(row.get("kind_id", ""))
|
||||
if kind == "feat_ticket":
|
||||
continue # 门票豁免——货架专属机制种(非 deck 池种,零摘牌拿到即开),不入 CURIO_KINDS
|
||||
continue # 专长凭证豁免——货架专属机制种(非 deck 池种,零摘牌拿到即开),不入 CURIO_KINDS
|
||||
if not adv.CURIO_KINDS.has(kind):
|
||||
push_diag.call("error", "shelf_dangling_kind", "ShopTable.pool_shelf kind %s 不在 AdventureTable.CURIO_KINDS(共享池牌库外种)" % kind)
|
||||
continue
|
||||
|
||||
@@ -48,7 +48,7 @@ var _hero_armor_type := ""
|
||||
var _shop_pool_mode := false # pool 模式封印(set_shop_pool 注入时置位——AdventureRunner 按 params.shop_mode 下传)
|
||||
var _pool_deck: Array[Variant] = [] # 共享池令牌库共享引用(AdventureRunner._curio_deck——库存=剩余令牌数单点)
|
||||
var _pool_consume := Callable() # 池消费 handler(AdventureRunner._consume_pool_purchase——_apply_curio_pick 同口写加算区+账本+摘牌)
|
||||
var _pool_ticket := Callable() # 门票展示判定 handler(T5——AdventureRunner._feat_ticket_consider;节点与商店共享计数)
|
||||
var _pool_ticket := Callable() # 专长凭证展示判定 handler(T5——AdventureRunner._feat_ticket_consider;节点与商店共享计数)
|
||||
var _pool_cap_check := Callable() # cap 检查回调(AdventureRunner._curio_cap_ok;cap 满剔出货架候选视图)
|
||||
var _shop_shelf: Array[Variant] = [] # 当前货架(进店抽 3/买后全重抽——令牌字典 {"kind","tier"} 序,同 kind 去重每 kind 至多一卡)
|
||||
var _shop_visit_buys := 0 # 本次进店已购次数(A 链定价输入——离开清零)
|
||||
@@ -775,7 +775,7 @@ func player_request_refresh() -> bool:
|
||||
func set_shop_pool(deck_ref: Array, consume_handler: Callable, ticket_consider: Callable = Callable(), cap_check: Callable = Callable()) -> void:
|
||||
_pool_deck = deck_ref
|
||||
_pool_consume = consume_handler
|
||||
_pool_ticket = ticket_consider # T5——门票展示判定(AdventureRunner._feat_ticket_consider;同流取数复用 shop_draw scope)
|
||||
_pool_ticket = ticket_consider # T5——专长凭证展示判定(AdventureRunner._feat_ticket_consider;同流取数复用 shop_draw scope)
|
||||
_pool_cap_check = cap_check
|
||||
_shop_pool_mode = true
|
||||
|
||||
@@ -820,12 +820,12 @@ func _shop_draw_shelf() -> void:
|
||||
_shop_shelf.append(tok)
|
||||
if _shop_shelf.size() >= 3:
|
||||
break
|
||||
# T5 门票注入(非 Boss 渠道唯一专长入口——货架与节点共享保底计数;判定含 pity 记账,替换末位占一席。
|
||||
# T5 专长凭证注入(非 Boss 渠道唯一专长入口——货架与节点共享保底计数;判定含 pity 记账,替换末位占一席。
|
||||
# 取数复用本函数 shop_draw scope 的 stream——零新 scope,确定性序列不漂移)
|
||||
if _pool_ticket.is_valid() and not _shop_shelf.is_empty() and bool(_pool_ticket.call(stream)):
|
||||
_shop_shelf[_shop_shelf.size() - 1] = {"kind": "feat_ticket", "tier": "excellent"} # 门票占位档名 = excellent
|
||||
_shop_shelf[_shop_shelf.size() - 1] = {"kind": "feat_ticket", "tier": "excellent"} # 专长凭证占位档名 = excellent
|
||||
# 商店渠道无专长直接投放(渠道白名单:商店渠道只出属性值提升+资源,专长在非 Boss
|
||||
# 渠道只以门票形态出现——奇物.md v2.7/A4 断言;专长商店入口=T5 门票)。
|
||||
# 渠道只以专长凭证形态出现——奇物.md v2.7/A4 断言;专长商店入口=T5 专长凭证)。
|
||||
|
||||
|
||||
# 库存余量(TP0——令牌库内该 kind 剩余枚数单点读;未注入/防御读 = 0)
|
||||
|
||||
@@ -123,7 +123,7 @@ func install_board(b: BoardData, during_round := false) -> Dictionary:
|
||||
_spawn = {}
|
||||
for c in b.spawn_cells():
|
||||
_spawn[c] = true
|
||||
# 初始展开:O₀ = R₀ 恰等(免费/计入清图/无格面资源/永不触雷);板级一次跨轮不重放
|
||||
# 初始展开:O₀ = R₀ 恰等(免费/计入清图/无格面资源/永不触雷);整图一次跨轮不重放
|
||||
for c in _initial_expansion_order(b):
|
||||
_revealed[c] = {"kind": "safe", "digit": b.digit_of(c)}
|
||||
cell_revealed.emit({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
## 秘宝关卡域库存+板级叠加层:全程零随机零特判,同操作序列重放库存与叠加层投影逐位相同(垂直切片验证:道具全程确定性)。
|
||||
## 秘宝关卡域库存+整图叠加层:全程零随机零特判,同操作序列重放库存与叠加层投影逐位相同(垂直切片验证:道具全程确定性)。
|
||||
## Used 不可逆——consume 后保留只读,枚举序=受理序;库存关卡域跨战斗延续、关卡末清空,叠加层随图消亡(清空编排归调用方,本类只供 clear/reset/retire_overlays)。
|
||||
## 零特判纪律:本类不写任何其他系统状态,排雷玩法代码零本系统分支;相位检查归战斗编排 use_treasure——validate_use 是纯谓词零消耗。
|
||||
class_name TreasureItems
|
||||
@@ -38,7 +38,7 @@ func add_item(item_id: String, source_class: String, cell: Vector2i, round_index
|
||||
|
||||
# ---- 库存读面(C 区槽位常读)----
|
||||
|
||||
# 枚举序=受理序;Used 保留只读;逐件含 usable 板级零信息预判(调用方喂板面回调)
|
||||
# 枚举序=受理序;Used 保留只读;逐件含 usable 整图零信息预判(调用方喂板面回调)
|
||||
func query_inventory(board_has_preview_info: Callable) -> Array:
|
||||
var out: Array[Variant] = []
|
||||
for rec in _items:
|
||||
@@ -54,13 +54,13 @@ func inventory_count() -> int:
|
||||
|
||||
# 持有数(同调位上限判定读数:只计未消耗件;Used 不可逆即不再持有)
|
||||
# 同调位守卫谓词(读取源 transitional_sync_slots 过渡键已随表退役;
|
||||
# 容量闸正主 = 营地装配面 Attunement.slots 满位禁选。函数体保留空壳防四散引用误删遗漏——
|
||||
# 容量闸现行事实源 = 营地装配面 Attunement.slots 满位禁选。函数体保留空壳防四散引用误删遗漏——
|
||||
# 冒烟「过渡键读取点归零」断言覆盖)
|
||||
|
||||
|
||||
# 持有件记录(奖励节点替换子交互数据源:只列未消耗件,handle 定位丢弃目标)
|
||||
# 丢弃(同调位替换交互节点渠道——腾位收新;与 Used 消费分轨的一次性移除,快照不再含)
|
||||
# 板级零信息可用性预判(图标置灰/入口禁用判据——GDD「整张图都没东西可看」级):
|
||||
# 整图零信息可用性预判(图标置灰/入口禁用判据——GDD「整张图都没东西可看」级):
|
||||
# 真视恒可用(零雷窗口=信息非空);AP 类恒可用(组合判据取 OR——任一效果有信息即可用);
|
||||
# 纯预读行 = 板上还有未开格才可用。(积点件不入使用面——自动兑付无玩家入口)
|
||||
func _usable_now(item_id: String, board_has_preview_info: Callable) -> bool:
|
||||
|
||||
@@ -89,12 +89,12 @@ const TIER_QUOTAS := {"common": 70, "excellent": 25, "rare": 7, "legendary": 0}
|
||||
@export var curio_cap_rap: int = 99 # [1,99]
|
||||
@export var curio_cap_time_sand: int = 99 # [1,99]
|
||||
|
||||
# —— 专长获取门票(非 Boss 渠道的专长入口形态,奇物.md v2.7 渠道轴定位;
|
||||
# —— 专长获取专长凭证(非 Boss 渠道的专长入口形态,奇物.md v2.7 渠道轴定位;
|
||||
# 四口径契约④:拿到即开不可囤积/罕见只在概率不在价格/一局限购一次/计步保底连续 5 展示未出
|
||||
# 第 6 必出(计数=展示次数、刷新重展计入、节点与商店共享、触发清零、限购满不再触发)。
|
||||
# 四参数全部 provisional 归曲线调参;limit/pity_step 系口径定死值,调参可复议)——
|
||||
@export var feat_ticket_chance: int = 20 # [0,100] knob(provisional)——每次非 Boss 渠道展示门票出现概率 %
|
||||
@export var feat_ticket_quota: int = 2 # [0,9] knob(provisional)——每局门票出现次数上限
|
||||
@export var feat_ticket_chance: int = 20 # [0,100] knob(provisional)——每次非 Boss 渠道展示专长凭证出现概率 %
|
||||
@export var feat_ticket_quota: int = 2 # [0,9] knob(provisional)——每局专长凭证出现次数上限
|
||||
@export var feat_ticket_limit: int = 1 # [1,9] knob(口径定死=1)——一局限购(选中/买下)次数
|
||||
@export var feat_ticket_pity_step: int = 5 # [1,99] knob(口径定死=5)——保底步数(连续未出展示次数)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ class_name SettlementTable
|
||||
extends Resource
|
||||
|
||||
@export var equivalence_ref_damage: int = 12 # [1,999] knob——当量参考敞口 D_ref
|
||||
@export var p_perfect: int = 200 # {100,200} percent——完美排雷第二份兑付触发(载体域)
|
||||
@export var p_perfect: int = 200 # {100,200} percent——完美封印第二份兑付触发(载体域)
|
||||
@export var seal_hit_premium: int = 100 # [100,999] percent knob——封印命中兑付溢价 ×(1+(n−100)/100):125=×1.25(条款3 条件二封印溢价形态 a,provisional);100=无溢价直通零扰动。只乘封印命中正向兑付(flat power/percent 幅度/gp 缓冲三形态),标空/挖格/清图不乘;雷安同池冻结不动
|
||||
@export var segment_order: PackedStringArray = [] # 结构冻结——段序恒等校验违例致命
|
||||
@export var source_label_map: Dictionary[String, Variant] = {} # 结构冻结——source_class→文案键
|
||||
|
||||
@@ -15,7 +15,7 @@ extends Resource
|
||||
|
||||
const GP_TIERS := ["normal", "elite", "boss"]
|
||||
const PRODUCT_ATTRS := ["atk", "max_hp", "armor_class"]
|
||||
const SHELF_KINDS := ["attack", "max_hp", "armor", "ap", "feat_ticket", "heal"] # 货架候选词表(四切边后种 + 门票行 + heal 补回复〔默认原则:分类内成员都入该渠道池〕)
|
||||
const SHELF_KINDS := ["attack", "max_hp", "armor", "ap", "feat_ticket", "heal"] # 货架候选词表(四切边后种 + 专长凭证行 + heal 补回复〔默认原则:分类内成员都入该渠道池〕)
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
|
||||
@@ -17,7 +17,7 @@ const SCOPES := ["region", "global"]
|
||||
# resource_face = 资源面偏斜(全局作用域变异——整图修摇号分布:生存族按 effect_value%
|
||||
# 下调、进攻族等比上浮重归一,不动任何格子数据;effect_value 语义随行域切换,不适用 flat_damage [1,9])
|
||||
const EFFECTS := ["none", "flat_damage", "hide_number", "resource_face"] # 效果词表:直伤 / 数字遮蔽 / 资源面偏斜(可扩充)
|
||||
const TRIGGERS := ["on_open", "on_number_shown", "always"] # 触发词表:被打开即触发 / 打开且显示数字时触发 / 板级恒在无触发时机(可扩充)
|
||||
const TRIGGERS := ["on_open", "on_number_shown", "always"] # 触发词表:被打开即触发 / 打开且显示数字时触发 / 整图恒在无触发时机(可扩充)
|
||||
const PLACEMENTS := ["closed_only", "any"] # 布置约束词表:只落布置时未开格 / 任意格(可扩充)
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ func validate() -> Array:
|
||||
if row.get("placement", "") != "any":
|
||||
errs.append({"category": "cross_field", "message": "%s scope=global ⇒ placement 必为 any(整图无格子布置域)" % vid})
|
||||
if row.get("trigger", "") != "always":
|
||||
errs.append({"category": "cross_field", "message": "%s scope=global ⇒ trigger 必为 always(板级恒在,无触发时机)" % vid})
|
||||
errs.append({"category": "cross_field", "message": "%s scope=global ⇒ trigger 必为 always(整图恒在,无触发时机)" % vid})
|
||||
return errs
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ price_b = 1.1
|
||||
; (4+2)+(2+2)+(4+2)=16、全购欲望 ≈ 26–34——取舍空间成立;量级与方差全部 provisional-pending-曲线调参批
|
||||
;(用户拍板骨架先行、数值整体后置,行值归 难度曲线与Boss)。
|
||||
; GP 商店房重构批(M-4 迭代 11 第②批 T1,2026-10-03——需求卡片 v1.3 全裁 P1 共享池/P4 ceil/P5 甲):
|
||||
; pool_shelf 行族 = 共享池货架(kind_id 词表 attack/max_hp/armor/ap/feat_ticket/heal 六行——heal 系 T6 商店补回复〔默认原则:分类内成员都要在它该出现的渠道池里,现行缺〕、GP 袋负交易切边计价物不自售、feat_ticket 系 T5 门票行〔非 Boss 渠道专长入口,价与其他商品相当=契约④口径②〕、
|
||||
; pool_shelf 行族 = 共享池货架(kind_id 词表 attack/max_hp/armor/ap/feat_ticket/heal 六行——heal 系 T6 商店补回复〔默认原则:分类内成员都要在它该出现的渠道池里,现行缺〕、GP 袋负交易切边计价物不自售、feat_ticket 系 T5 专长凭证行〔非 Boss 渠道专长入口,价与其他商品相当=契约④口径②〕、
|
||||
; 规则改写型特性三轴 doctrine 切边;库存=上限即库存,账本在 冒险结构 _bonus_taken 单点共享,行族不记库存);
|
||||
; 价格公式换代(pool 模式)= ceil(base_price × b^(关序−1) × A^(本次进店已购次数)),price_a=1.8/price_b=1.1
|
||||
; provisional 投值(零人工令改 provisional+后置追认,原 P5 甲研究拍板后置);products 行族 + 加法定价
|
||||
|
||||
@@ -86,7 +86,7 @@ func _skip_empty_stop() -> bool:
|
||||
# 增量行在其上),确认后进三选一面(level-clear.md v2);续玩停点恢复同入口(零自动推进契约)
|
||||
func on_presented(payload: Dictionary) -> void:
|
||||
if String(payload.get("context", "")) == "feat_ticket":
|
||||
# T5 店内门票兑付——临时停点开专长三选一面(零胜利总结面;确认后只关面回店)
|
||||
# T5 店内专长凭证兑付——临时停点开专长三选一面(零胜利总结面;确认后只关面回店)
|
||||
_pending_curio = payload.duplicate(true)
|
||||
_curio_context = "feat_ticket"
|
||||
if (_pending_curio.get("candidates", []) as Array).is_empty():
|
||||
@@ -214,7 +214,7 @@ func on_pick_confirmed(item_id: String) -> void:
|
||||
if not ok:
|
||||
push_error("[bonus_interact] 三选一兑付被拒——见输出日志")
|
||||
return
|
||||
# T5——节点渠道门票拿到即开:候选已被替换为专长面,本地读在途态重绘(零 emit——context 保持 reward_node,
|
||||
# T5——节点渠道专长凭证拿到即开:候选已被替换为专长面,本地读在途态重绘(零 emit——context 保持 reward_node,
|
||||
# 后续兑付/确认仍走节点路径回图选路)
|
||||
if _curio_context == "reward_node" and kind == "feat_ticket":
|
||||
var st2: Dictionary[Variant, Variant] = adventure.node_curio_pending_state()
|
||||
@@ -234,7 +234,7 @@ func on_continue() -> void:
|
||||
curio_overlay.close_pick()
|
||||
var adventure = _adventure_get.call()
|
||||
if _curio_context == "feat_ticket":
|
||||
return # T5 店内门票面——专长兑付完成后关面回店(无推进/无回图)
|
||||
return # T5 店内专长凭证面——专长兑付完成后关面回店(无推进/无回图)
|
||||
if _curio_context == "reward_node":
|
||||
var runner = _runner_get.call()
|
||||
if runner != null:
|
||||
|
||||
@@ -37,7 +37,7 @@ static func refresh(stage: BattleStageView, info: HeroInfoPanelView, ap_bar: ApB
|
||||
_refresh_out_of_battle(stage, info, ap_bar, runner, level_active, db)
|
||||
return
|
||||
var s: Dictionary[Variant, Variant] = settlement.presentation_snapshot()
|
||||
# 地形变异常驻角标投影(板级变异快照 → 文案行;
|
||||
# 地形变异常驻角标投影(整图变异快照 → 文案行;
|
||||
# 空态隐藏=特性段先例;战斗全程常驻防中局遗忘)
|
||||
info.set_board_variants(board_variant_lines(db, s.get("board_variants", [])))
|
||||
var hero: Dictionary[Variant, Variant] = s.hero
|
||||
@@ -102,7 +102,7 @@ static func feat_holdings_lines(db, held: Array) -> Array[String]:
|
||||
return rlines
|
||||
|
||||
|
||||
# 地形变异常驻角标文案(板级变异 id → 文案行;
|
||||
# 地形变异常驻角标文案(整图变异 id → 文案行;
|
||||
# 空集 = 空数组=空态隐藏。三行制:变异名+两行效果说明(C 区 240px 宽防裁切)。
|
||||
# 文案用常规表述,不用俚语
|
||||
static func board_variant_lines(db, ids: Array) -> Array[String]:
|
||||
|
||||
@@ -911,7 +911,7 @@ func _on_round_started(ri: int) -> void:
|
||||
# 巢穴预告呈现(装板报数量读数口消费:≥0=本战装配命中,toast 一次性提示)
|
||||
if run_scope.settlement != null and int(run_scope.settlement.nest_preview_count) >= 0:
|
||||
board_zone.toast.show_toast("巢穴预告——本板危险格共 %d 个" % int(run_scope.settlement.nest_preview_count), "info")
|
||||
# 开战横幅——板级地形变异预告:首轮快照 board_variants
|
||||
# 开战横幅——整图地形变异预告:首轮快照 board_variants
|
||||
# 非空才发射(Boss 图恒带一型=替换制;普通图空快照零发射);轮横幅下方叠行,view 内判减动效。
|
||||
if ri == 1 and run_scope.settlement != null:
|
||||
var bvs: Array[Variant] = run_scope.settlement.presentation_snapshot().get("board_variants", [])
|
||||
|
||||
@@ -89,7 +89,7 @@ func _consume_row(row: Dictionary) -> void:
|
||||
stage.on_step_row_fx(row)
|
||||
_play_cross_zone_fx(row) # 跨区因果演出(结算演出链批):开格之因 → 站桩之果
|
||||
_play_settlement_mark(row) # 三轮 #3——逐条标出:Buff/Debuff 色环脉冲 → 伤害/治疗数字浮现
|
||||
# 高光演出(战斗结算×3①② 占位):完美排雷横幅 / 封印命中加重弹道
|
||||
# 高光演出(战斗结算×3①② 占位):完美封印横幅 / 封印命中加重弹道
|
||||
if String(row.get("type", "")) == "highlight" and String(row.get("highlight", "")) != "skill_unlock":
|
||||
board_zone.fx.play_perfect_sweep()
|
||||
elif String(row.get("highlight", "")) == "seal_hit":
|
||||
|
||||
@@ -98,7 +98,7 @@ func attempt_use(handle: int, cell: Variant = null) -> void:
|
||||
toast.show_toast("已使用 %s" % String(arow.get("display_name", "")), "info")
|
||||
|
||||
|
||||
# 库存投影(C 区四槽取数面——字形=名首字;usable=板级零信息预判回调接排雷玩法只读面)
|
||||
# 库存投影(C 区四槽取数面——字形=名首字;usable=整图零信息预判回调接排雷玩法只读面)
|
||||
func inventory_projection() -> Array:
|
||||
var runner = _runner_get.call()
|
||||
if runner == null or runner.treasure_inventory == null:
|
||||
|
||||
@@ -189,7 +189,7 @@ func _format_row(row: Dictionary, agg_count := -1) -> String:
|
||||
var n := (" ×%d" % agg_count) if agg_count > 1 else ""
|
||||
return prefix + "[s][color=#%s]⚠ %s%s[/color][/s]%s" % [UiKit.HEX_LOG_VOIDED, name_, n, suffix]
|
||||
"seal_miss":
|
||||
var body := "✗ %s%s" % [name_, "(本板完美排雷已破——归因此封印)" if hl == "perfect_broken" else ""]
|
||||
var body := "✗ %s%s" % [name_, "(本板完美封印已破——归因此封印)" if hl == "perfect_broken" else ""]
|
||||
return prefix + (_gold_frame(body) if hl == "perfect_broken" else "[color=#%s]%s[/color]" % [UiKit.HEX_LOG_ROUND, body])
|
||||
"cast":
|
||||
# 施放行:增益技 0 伤害施放,具名技能
|
||||
|
||||
@@ -94,7 +94,7 @@ var facade_strip := false: # E 格开关(BoardView paint 按「已开
|
||||
|
||||
# 变异角标(程序化,tex_mutation 纹带槽暂留):
|
||||
# "flat_damage" = 未开格伤害型变异,左下角危险红三角(开格有代价的策略纹理标记)
|
||||
# 叠加层标记(秘宝板级叠加层的格面呈现;派生信息层零回写):
|
||||
# 叠加层标记(秘宝整图叠加层的格面呈现;派生信息层零回写):
|
||||
# "mine_reveal" = 真视格(危险红内缩框——「这格是雷」的确定决策标记,封印照常计费);
|
||||
# "reward_preview" 格不复用本字段——预读徽章走 badge_glyph 注入(board_view refresh 注入 REWARD_BADGE 字形)
|
||||
var treasure_mark := "":
|
||||
@@ -108,8 +108,8 @@ var mutation_mark := "":
|
||||
mutation_mark = v
|
||||
queue_redraw()
|
||||
|
||||
# ── 视野迷雾呈现态(纯呈现零逻辑;规格=art-bible §6.5 v3.5,正主=HUD框架「视野迷雾」节)──
|
||||
# 0=正常(灯光区内)/ 1=全黑(区外未开格——正主「区外未开格=全黑不渲染」不透明档)/ 2=记忆态(区外已开格灰显可读)
|
||||
# ── 视野迷雾呈现态(纯呈现零逻辑;规格=art-bible §6.5 v3.5,现行事实源=HUD框架「视野迷雾」节)──
|
||||
# 0=正常(灯光区内)/ 1=全黑(区外未开格——现行事实源「区外未开格=全黑不渲染」不透明档)/ 2=记忆态(区外已开格灰显可读)
|
||||
var fog_state := 0:
|
||||
set(v):
|
||||
if fog_state != v:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
## D 区演出层:清图喷泉/Boss 影子/完美排雷光带/封印命中弹道/挥铲三帧等一次性占位演出。
|
||||
## D 区演出层:清图喷泉/Boss 影子/完美封印光带/封印命中弹道/挥铲三帧等一次性占位演出。
|
||||
## 组合根按核心信号直调 play_*;素材缺位静默回退(演出层不设断言面)。
|
||||
class_name BoardFxView
|
||||
extends Control
|
||||
@@ -87,7 +87,7 @@ func play_boss_shadow() -> void:
|
||||
tw.tween_callback(shadow.queue_free)
|
||||
|
||||
|
||||
# 完美排雷:金光带加倍扫射 + 横幅占位(§2.2 最高档)
|
||||
# 完美封印:金光带加倍扫射 + 横幅占位(§2.2 最高档)
|
||||
func play_perfect_sweep() -> void:
|
||||
for i in 2:
|
||||
var band := ColorRect.new()
|
||||
@@ -99,7 +99,7 @@ func play_perfect_sweep() -> void:
|
||||
var tw := band.create_tween()
|
||||
tw.tween_property(band, "position:x", size.x + 8.0, UiKit.motion(0.5 + 0.15 * i))
|
||||
tw.tween_callback(band.queue_free)
|
||||
_show_banner("完美排雷 ×2")
|
||||
_show_banner("完美封印 ×2")
|
||||
|
||||
|
||||
# 封印命中:封印化暴击弹道加重占位(自棋盘上缘飞向 B 区敌人卡方向——越界即收)
|
||||
|
||||
@@ -117,7 +117,7 @@ var _digit_dark_ink := true # 数字墨族按板自适应(true=深墨
|
||||
var _digit_plate := false # 数字色牌垫底模式(双峰纹理板——直画两族皆不过门槛时落牌,
|
||||
# 素牌+深墨 12:1 纹理免疫;渲染帧取证 underdark 系深墨直画隐形,故启用色牌)
|
||||
|
||||
# ---- 视野迷雾(纯呈现层;正主=HUD框架「视野迷雾」节 v0.13,渲染规格=art-bible §6.5 v3.5)----
|
||||
# ---- 视野迷雾(纯呈现层;现行事实源=HUD框架「视野迷雾」节 v0.13,渲染规格=art-bible §6.5 v3.5)----
|
||||
const FOG_RADIUS := 8 # 菱形灯光区基准半径(曼哈顿距离 ≤R——与微光环「周围 8 格」同圈起步;半径基准值改动=非白名单须用户)
|
||||
var _fog_enabled := true # 迷雾开关(呈现态布尔——真实游戏恒 on;探针/夹具可 off=无迷雾基线,两态结算逐位一致断言面)
|
||||
var _fog_lantern := 0 # 视野加成现值(缺省 0=无加成基线零扰动;生产写入面=组合根每战装配链显式重算——main._sync_treasure_glow)
|
||||
@@ -142,7 +142,7 @@ func _init() -> void:
|
||||
add_child(_wrap)
|
||||
_svp_container = SubViewportContainer.new()
|
||||
_svp_container.stretch = true # 容器尺寸 = 视口逻辑分辨率(_update_world_size 同步)——恒 1:1 无缩放
|
||||
_svp_container.mouse_filter = Control.MOUSE_FILTER_IGNORE # 输入归壳层 _gui_input(板级公式换算),不进 SubViewport
|
||||
_svp_container.mouse_filter = Control.MOUSE_FILTER_IGNORE # 输入归壳层 _gui_input(整图公式换算),不进 SubViewport
|
||||
_wrap.add_child(_svp_container)
|
||||
_viewport = SubViewport.new()
|
||||
_viewport.transparent_bg = true # 格间距露出 D 区底色
|
||||
@@ -502,7 +502,7 @@ func click_cell(cell: Vector2i, button: int) -> void:
|
||||
_on_cell_input(cell, ev)
|
||||
|
||||
|
||||
# 板级公式单点:格坐标 = floor(板内局部坐标 / 格步长)
|
||||
# 整图公式单点:格坐标 = floor(板内局部坐标 / 格步长)
|
||||
#(格步长 = 格边长 + 间距;板外/负域返回 (-9,-9);2px 格间隙落入左/上邻格)
|
||||
func _cell_at(shell_pos: Vector2) -> Vector2i:
|
||||
if _board == null or _board.width == 0:
|
||||
@@ -534,7 +534,7 @@ func _update_world_size() -> void:
|
||||
_viewport.size = px
|
||||
|
||||
|
||||
# 真实输入路径(Node2D 迁移批 Decision 3):壳层 _gui_input → 板级公式换算 → 复用既有 hover/点选/chord 出口
|
||||
# 真实输入路径(Node2D 迁移批 Decision 3):壳层 _gui_input → 整图公式换算 → 复用既有 hover/点选/chord 出口
|
||||
func _gui_input(ev: InputEvent) -> void:
|
||||
if _minesweeper == null:
|
||||
return
|
||||
@@ -832,7 +832,7 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
|
||||
u.mutation_mark = ""
|
||||
u.badge_glyph = _update_badge(c)
|
||||
u.glow_group = int(_glow.get(c, UiKit.GLOW_NONE))
|
||||
# 视野迷雾呈态:曼哈顿距离 > 半径 → 区外——未开格全黑(正主照抄)/
|
||||
# 视野迷雾呈态:曼哈顿距离 > 半径 → 区外——未开格全黑(现行事实源照抄)/
|
||||
# 已开格记忆态(灰显可读);以英雄格为心逐格重算,refresh()/notify_hero_move() 既有重绘驱动=移动实时跟随。
|
||||
# 纯呈现零逻辑——格态/数字真值/清图判定零触碰(🔴 契约 1);结算期去饱和叠加互斥由 CellUnit 记忆态终态档承载。
|
||||
if _fog_enabled:
|
||||
|
||||
@@ -107,7 +107,7 @@ func open_pick(header: String, cards: Array) -> void:
|
||||
_confirm_btn.visible = false
|
||||
_continue_btn.visible = false
|
||||
_foot_hint.visible = true # T7 底注=pick 态专属(result 态让位)
|
||||
_refresh_btn.visible = false # 刷新面随 set_refresh_display 投喂后现形(open 先归零防残留;店内门票面不投喂=无刷新)
|
||||
_refresh_btn.visible = false # 刷新面随 set_refresh_display 投喂后现形(open 先归零防残留;店内专长凭证面不投喂=无刷新)
|
||||
_refresh_l.text = ""
|
||||
visible = true
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ func set_feat_holdings(lines: Array) -> void:
|
||||
_feat_section.visible = not lines.is_empty()
|
||||
|
||||
|
||||
# 地形变异常驻角标:lines = 文案行(板级变异 display_name+体感短语)——空数组 = 整节隐藏
|
||||
# 地形变异常驻角标:lines = 文案行(整图变异 display_name+体感短语)——空数组 = 整节隐藏
|
||||
func set_board_variants(lines: Array) -> void:
|
||||
for c3 in _board_variant_list.get_children():
|
||||
_board_variant_list.remove_child(c3)
|
||||
@@ -157,7 +157,7 @@ func _data_line() -> Label:
|
||||
|
||||
# ---- 秘宝库存条(C 区四槽常读+两步交互第一步)----
|
||||
# 投影行 = {handle, glyph, name, used, usable}(组合根组装:字形=道具名首字;数据源 runner 级库存只读面)。
|
||||
# 空槽=虚位;used=暗态「已用」保留占位(Used 不可逆——受理序展示语义);不可用=置灰(板级零信息);
|
||||
# 空槽=虚位;used=暗态「已用」保留占位(Used 不可逆——受理序展示语义);不可用=置灰(整图零信息);
|
||||
# selected=金框高亮(两步交互第一步的可见态)。tooltip=全名+维度语义。
|
||||
func set_treasure_inventory(items: Array, selected_handle: int) -> void:
|
||||
_selected_handle = selected_handle
|
||||
|
||||
@@ -11,7 +11,7 @@ func _init() -> void:
|
||||
|
||||
|
||||
# 结算轮光带:金橙半透明横带自棋盘上缘扫至下缘(一次 0.5s,自动回收)——
|
||||
# "棋盘能量向战斗画面汇聚"的开轮语义(§2.2 色彩转金橙主导;区分于 board_fx 的完美排雷金光带)。
|
||||
# "棋盘能量向战斗画面汇聚"的开轮语义(§2.2 色彩转金橙主导;区分于 board_fx 的完美封印金光带)。
|
||||
# 终稿(样张 v2 冻结批 T3):加 2px 亮金前导缘线——扫带运动方向可读(兑现光带逐行横扫 §2.2)
|
||||
func play_round_sweep(board_rect: Rect2) -> void:
|
||||
if board_rect.size == Vector2.ZERO:
|
||||
@@ -143,7 +143,7 @@ func play_round_banner(ri: int) -> void:
|
||||
tw.tween_callback(banner.queue_free)
|
||||
|
||||
|
||||
# 开战横幅——板级地形变异预告:board_variants 非空时开战
|
||||
# 开战横幅——整图地形变异预告:board_variants 非空时开战
|
||||
# 显示一行(文本=「地形变异 · 贫矿脉」式);减动效=静态驻留后即隐(轮横幅先例——行呈现不跳过)。
|
||||
# 文案/驻留参数 provisional 归本地化批;普通图恒不发射(组合根按快照 board_variants 空判)。
|
||||
func play_board_variant_banner(text: String) -> void:
|
||||
|
||||
@@ -28,7 +28,7 @@ var _cur_settlement = null # 当关 settlement(身份回调读取面——
|
||||
func _ready() -> void:
|
||||
# 运行前提=窗口化真渲染面(shot_probe 同款护栏——headless 下 frame_post_draw 永不触发+视口纹理恒空)
|
||||
if DisplayServer.get_name() == "headless":
|
||||
print("[board_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);正主=tools/render_gate.sh 取证段")
|
||||
print("[board_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);现行事实源=tools/render_gate.sh 取证段")
|
||||
get_tree().quit(1)
|
||||
return
|
||||
var args := OS.get_cmdline_user_args()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 布局几何断言探针(正主=tools/probe_gate.sh 默认段;呈现层三区布局的分辨率维度验收)
|
||||
# 布局几何断言探针(现行事实源=tools/probe_gate.sh 默认段;呈现层三区布局的分辨率维度验收)
|
||||
# 用途:battle.md §验收「1280×800 与 16:9 全屏下三区无遮挡/无重叠/无裁切」的可执行化
|
||||
# GDD 锚:design/gdd/ux/battle.md §Layout Zones(B/C/D 三区几何)
|
||||
# 硬约束:档位表是数据、断言是一份函数据——加档只改表不动断言(禁每档建一个探针)
|
||||
|
||||
@@ -222,7 +222,7 @@ static func _on_adventure_node_entered(node: Dictionary, info: Dictionary, adr,
|
||||
adr.present_node_curio(ncands)
|
||||
var npick: Dictionary = _pick_token(ncands, String(st.get("feat_mode", "off")))
|
||||
if adr.apply_node_curio(String(npick.get("kind", "")), String(npick.get("tier", "")), String(npick.get("feat_id", ""))):
|
||||
# 门票拿到即开——候选已被替换为专长三选一,就地再选一轮(确定性策略同款 316-f);
|
||||
# 专长凭证拿到即开——候选已被替换为专长三选一,就地再选一轮(确定性策略同款 316-f);
|
||||
# 不作此分支则节点停点悬空→选路卡死(MC timeout 形态)
|
||||
if String(npick.get("kind", "")) == "feat_ticket":
|
||||
var fcands: Array = (adr.node_curio_pending_state().get("candidates", []) as Array)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 整屏截图探针(呈现层测试分级 B 档基建:视口截图程序化产出;七屏——
|
||||
# 菜单/设置面/生涯页/营地/关卡画面/战斗/状态面板,正主=tools/render_gate.sh)。
|
||||
# 菜单/设置面/生涯页/营地/关卡画面/战斗/状态面板,现行事实源=tools/render_gate.sh)。
|
||||
# 必须**窗口化**运行(真渲染设备——headless 无渲染面,get_image 得到空纹理):
|
||||
# Godot_console.exe --path . res://smoke/shot_probe.tscn -- <输出目录>
|
||||
# 流程 = 真实按钮信号路径驱动(ui_click_probe 同款;存档/设置/元进度三面换注隔离档——禁碰真实档,
|
||||
@@ -25,7 +25,7 @@ var _meta := {} # 控件实测几何(全局 rect——shot_checker 文字框
|
||||
func _ready() -> void:
|
||||
# 运行前提=窗口化真渲染面:headless 下 frame_post_draw 永不触发+视口纹理恒空——无此守卫时 headless 调用方必挂死
|
||||
if DisplayServer.get_name() == "headless":
|
||||
print("[shot_probe] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);headless 自动闸禁跑本探针(正主=tools/probe_gate.sh)")
|
||||
print("[shot_probe] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);headless 自动闸禁跑本探针(现行事实源=tools/probe_gate.sh)")
|
||||
get_tree().quit(1)
|
||||
return
|
||||
var args := OS.get_cmdline_user_args()
|
||||
|
||||
+17
-17
@@ -1357,15 +1357,15 @@ func _smoke_feats() -> void:
|
||||
if String((t as Dictionary).get("kind", "")) == "relic":
|
||||
node_relic_seen = true
|
||||
check(feat_seen.size() >= 2, "通关渠道只出专长(60 次重抽 ≥2 种不同 relic——身份键 feat_id 同档可多件)")
|
||||
check(not node_relic_seen, "节点渠道零专长(60 次重抽零 relic——专长在非 Boss 渠道只以门票形态出现)")
|
||||
# T5 门票行为断言(A5 拿到即开 / A6 保底计数——契约④四口径;独立 runner 防污染 a_r 牌库)
|
||||
check(not node_relic_seen, "节点渠道零专长(60 次重抽零 relic——专长在非 Boss 渠道只以专长凭证形态出现)")
|
||||
# T5 专长凭证行为断言(A5 拿到即开 / A6 保底计数——契约④四口径;独立 runner 防污染 a_r 牌库)
|
||||
var a_t = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(91))
|
||||
a_t.start_adventure(91, {"first_script": true})
|
||||
var stock_before := {}
|
||||
for kk in ["attack", "gp", "heal"]:
|
||||
stock_before[kk] = a_t.pool_stock(kk)
|
||||
a_t._node_curio_pending = {"candidates": [{"kind": "feat_ticket", "tier": "excellent"}, {"kind": "attack", "tier": "common"}]}
|
||||
check(a_t.apply_node_curio("feat_ticket", "excellent"), "A5 门票兑付受理(节点渠道——拿到即开)")
|
||||
check(a_t.apply_node_curio("feat_ticket", "excellent"), "A5 专长凭证兑付受理(节点渠道——拿到即开)")
|
||||
var tkt_cands: Array = (a_t.node_curio_pending_state().get("candidates", []) as Array)
|
||||
var tkt_all_relic := tkt_cands.size() > 0
|
||||
for t in tkt_cands:
|
||||
@@ -1373,13 +1373,13 @@ func _smoke_feats() -> void:
|
||||
tkt_all_relic = false
|
||||
check(tkt_all_relic, "A5 拿到即开——停点候选已替换为专长三选一(全 relic)")
|
||||
check(a_t.pool_stock("attack") == int(stock_before["attack"]) and a_t.pool_stock("gp") == int(stock_before["gp"]),
|
||||
"A5 零摘牌——门票兑付不动令牌库(不进持有集)")
|
||||
check(not (a_t.feats_held() as Array).has("feat_ticket"), "A5 无门票残留持有集")
|
||||
"A5 零摘牌——专长凭证兑付不动令牌库(不进持有集)")
|
||||
check(not (a_t.feats_held() as Array).has("feat_ticket"), "A5 无专长凭证残留持有集")
|
||||
var feats_n := (a_t.feats_held() as Array).size()
|
||||
a_t.apply_node_curio("relic", String((tkt_cands[0] as Dictionary).get("tier", "rare")), String((tkt_cands[0] as Dictionary).get("feat_id", "")))
|
||||
check((a_t.feats_held() as Array).size() == feats_n + 1, "A5 专长面兑付受理(门票开出候选可正常入持有集)")
|
||||
check((a_t.feats_held() as Array).size() == feats_n + 1, "A5 专长面兑付受理(专长凭证开出候选可正常入持有集)")
|
||||
# A6 保底:pity 直填 5 → 下次展示必出(第 6 次必出口径);限购满 → 恒不触发
|
||||
a_t._feat_ticket_sold = 0 # A5 已兑付一枚门票(sold=1=limit)——A6 段重置计数隔离验证
|
||||
a_t._feat_ticket_sold = 0 # A5 已兑付一枚专长凭证(sold=1=limit)——A6 段重置计数隔离验证
|
||||
a_t._feat_ticket_pity = int(a_t.db.adventure.feat_ticket_pity_step)
|
||||
var rg_t: RandomNumberGenerator = a_t.rng.open_stream("reward_pick")
|
||||
check(a_t._feat_ticket_consider(rg_t), "A6 保底触发(pity=5 → 第 6 次展示必出——概率无关)")
|
||||
@@ -1841,7 +1841,7 @@ func _smoke_type_glow() -> void:
|
||||
check((snap.get("cells", {}) as Dictionary).size() == mapped - 1,
|
||||
"V2 清单外格剔除后作用集 = 派定数 −1(%d→%d)" % [mapped, (snap.get("cells", {}) as Dictionary).size()])
|
||||
# ---- 相 3:封锁格(query 返回 null)⇒ 无微光且零登记 ----
|
||||
_glow_type_overrides.erase(bogus_cell) # 复位清单外(errors 保留=板级登记语义)
|
||||
_glow_type_overrides.erase(bogus_cell) # 复位清单外(errors 保留=整图登记语义)
|
||||
var blocked_cell: Vector2i = hero
|
||||
for i in mini(assign.size(), nbs.size()):
|
||||
var nb4: Vector2i = nbs[i]
|
||||
@@ -2582,7 +2582,7 @@ func _smoke_global_variant() -> void:
|
||||
vt.rows.assign([{"variant_id": "g3", "display_name": "负丙", "unlock_level": 2, "scope": "global",
|
||||
"effect": "resource_face", "effect_value": 30, "trigger": "on_open", "placement": "any",
|
||||
"board_types": [], "counter_items": []}])
|
||||
check(_errs_has_cross_field(vt.validate()), "互锁负样本⑤:scope=global + trigger=on_open 被拒(global ⇒ always 板级恒在)")
|
||||
check(_errs_has_cross_field(vt.validate()), "互锁负样本⑤:scope=global + trigger=on_open 被拒(global ⇒ always 整图恒在)")
|
||||
vt.rows.assign([{"variant_id": "g4", "display_name": "负丁", "unlock_level": 2, "scope": "global",
|
||||
"effect": "resource_face", "effect_value": 30, "trigger": "always", "placement": "closed_only",
|
||||
"board_types": [], "counter_items": []}])
|
||||
@@ -2624,7 +2624,7 @@ func _smoke_global_variant() -> void:
|
||||
var boss1_calls := 0
|
||||
if boss_ok:
|
||||
var bb = boss_settlement.minesweeper.current_board()
|
||||
check(bb.board_variant_ids().is_empty(), "屏蔽后回落:Boss 图无板级全局型(board_variants 空——全局池空合法态)")
|
||||
check(bb.board_variant_ids().is_empty(), "屏蔽后回落:Boss 图无整图全局型(board_variants 空——全局池空合法态)")
|
||||
var boss_vids := {}
|
||||
for vc in bb.variants:
|
||||
for vid in bb.variants[vc]:
|
||||
@@ -3497,7 +3497,7 @@ func _encounter_replay(seed_val: int) -> Array:
|
||||
|
||||
|
||||
# ==================== 清图奖励双份兑付链 / 轮内刷新 provenance 守卫 / 窗口锚行 ====================
|
||||
# 清图 = 全安全格开完。清图测试用"真雷封印(零误标→完美排雷)+ AutoPlayer 逐轮清图"真实流驱动;
|
||||
# 清图 = 全安全格开完。清图测试用"真雷封印(零误标→完美封印)+ AutoPlayer 逐轮清图"真实流驱动;
|
||||
# DifficultyTable 注入 hp_mult=10 把 Boss 血量抬到 1500,保证清图批次发生在战斗结束之前(测试台账,跑完即还原)。
|
||||
|
||||
const CLEAR_SMOKE_DEPTH := 4
|
||||
@@ -3506,11 +3506,11 @@ var _regular_clear_reward_rows := 0 # 常规(非刷新图)清图的 clear_
|
||||
|
||||
|
||||
func _smoke_clear_reward_chain() -> void:
|
||||
print("--- 清图奖励·双份兑付链(完美排雷 / 零兑付 / 第二份被拒 / 高光记实)---")
|
||||
# ① 真实流完美排雷:标中一面真雷封印 + 零误标 + 清全图 → grant_clear 身份(clear_blast)双份真实兑付
|
||||
print("--- 清图奖励·双份兑付链(完美封印 / 零兑付 / 第二份被拒 / 高光记实)---")
|
||||
# ① 真实流完美封印:标中一面真雷封印 + 零误标 + 清全图 → grant_clear 身份(clear_blast)双份真实兑付
|
||||
var rows: Array = []
|
||||
var run := _run_full_clear(20260915, false, rows)
|
||||
check(bool(run.cleared), "① 完美排雷清图达成(%d 轮)" % int(run.rounds))
|
||||
check(bool(run.cleared), "① 完美封印清图达成(%d 轮)" % int(run.rounds))
|
||||
var dmg := []
|
||||
for r in rows:
|
||||
if String(r.get("type", "")) == "damage" and String(r.get("source_class", "")) == "clear_reward":
|
||||
@@ -4070,7 +4070,7 @@ func _drive_clear(settlement) -> Dictionary:
|
||||
if t.hero_cell != ms.hero_pos():
|
||||
ms.settle_batch([{"action": "move", "cell": t.hero_cell}])
|
||||
ms.settle_batch([{"action": "seal_place", "cell": t.seal_cell}])
|
||||
seal_done = true # 一面真雷封印 = 完美排雷前半(零误标),后半靠 AutoPlayer 清图
|
||||
seal_done = true # 一面真雷封印 = 完美封印前半(零误标),后半靠 AutoPlayer 清图
|
||||
var seq_before: int = int(settlement.diagnostic_snapshot().board_seq)
|
||||
var out := {"result": "", "rounds": 0, "terminated": false, "stream": []}
|
||||
_auto_play_round(settlement, out)
|
||||
@@ -5298,7 +5298,7 @@ func _smoke_shop_pool() -> void:
|
||||
# ⑧ 终局池读数(run_adventure pool 面——商店与奖励跨渠道消耗后的终局余量出讫)
|
||||
var st_pool: Dictionary = autoplay.run_adventure(_db, 42, 0, 0, false, null, "normal", "min", {}, {}, {"mode": "pool"})
|
||||
var ps: Dictionary = st_pool.get("pool_stock", {})
|
||||
check(ps.size() == 6, "终局池读数六键出讫(run_adventure pool 面——四池种+T5 门票+T6 heal 行,读数只锚一次载体)")
|
||||
check(ps.size() == 6, "终局池读数六键出讫(run_adventure pool 面——四池种+T5 专长凭证+T6 heal 行,读数只锚一次载体)")
|
||||
var ps_ok := true
|
||||
for k in ps.keys():
|
||||
var quota := 0
|
||||
@@ -6191,7 +6191,7 @@ func _smoke_battle_log_view() -> void:
|
||||
"cast": {"type": "cast", "display_name": "卓尔精灵 施放 毒雾", "source_class": "enemy_action", "round_index": 3},
|
||||
"decay": {"type": "decay", "value": 1, "round_index": 3},
|
||||
"verdict": {"type": "verdict", "display_name": "下一轮次", "value": 0, "round_index": 3},
|
||||
"highlight": {"type": "highlight", "display_name": "完美排雷!清图奖励 ×2", "value": 2, "source_class": "clear_reward", "round_index": 4},
|
||||
"highlight": {"type": "highlight", "display_name": "完美封印!清图奖励 ×2", "value": 2, "source_class": "clear_reward", "round_index": 4},
|
||||
}
|
||||
for row_type in rest:
|
||||
var before: int = view.parsed_text().length()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# 真实信号路径驱动一场战斗到击杀胜利(结算行在排播队列),断言两条:
|
||||
# ①胜利同帧:终局面未开 + 挂起态在案 + 队列非空(旧行为=同帧 flush+开窗,本断言即红——判别性);
|
||||
# ②排播放完:终局面开启(演播完边沿派发——_on_pump_ended)。
|
||||
# 存档/设置/元进度三面隔离(isolate_save 正主,meta 经 autoload 链同源),零真实档触碰。headless 可跑(不抓帧)。
|
||||
# 存档/设置/元进度三面隔离(isolate_save 现行事实源,meta 经 autoload 链同源),零真实档触碰。headless 可跑(不抓帧)。
|
||||
extends Node
|
||||
|
||||
const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd") # 隔离样板单点
|
||||
@@ -17,7 +17,7 @@ func _ready() -> void:
|
||||
main = load("res://presentation/main.tscn").instantiate()
|
||||
add_child(main)
|
||||
await get_tree().process_frame
|
||||
# 存档/设置两面隔离(ProbeUiUtil.isolate_save 正主,先删后建防陈旧档泄入)——
|
||||
# 存档/设置两面隔离(ProbeUiUtil.isolate_save 现行事实源,先删后建防陈旧档泄入)——
|
||||
# 隔离面走 attach_path 原地重置 autoload 单例:组合根 save_manager/meta 是getter-only
|
||||
# 读视图,直接赋值无效,隔离必须落在单例上。
|
||||
ProbeUiUtil.isolate_save(main, "t17_defer_probe", false, true, false)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# push_input 端到端输入探针(场景结构登记项转义务 + Node2D 呈现层 Risks 缓解面)。
|
||||
# 现役探针全走 BoardView.click_cell 直调(合成鼠标事件零命中已实证)——
|
||||
# 本探针是真实输入路径的唯一自动化覆盖:鼠标事件 → 壳层 _gui_input → 板级公式换算(_cell_at)→
|
||||
# 本探针是真实输入路径的唯一自动化覆盖:鼠标事件 → 壳层 _gui_input → 整图公式换算(_cell_at)→
|
||||
# 悬停/点选/chord 既有出口 → 组合根信号。四 case:①悬停可挖域(金框+十字光标)②悬停禁入
|
||||
# (hover_forbidden 信号+灰禁红框)③悬停已开格(路径预览点迹+移动光标)④右键封印(seal_place
|
||||
# 到达组合根+核心封印态)⑤双击 chord(禁入格双左击,核心拒挖零副作用)⑥左键挖(dig 到达组合根+核心揭格)
|
||||
|
||||
@@ -112,7 +112,7 @@ timeout 120s godot --headless --script tests/run_all.gd
|
||||
`tests/static_scan.sh` 实现静态扫描域 S1–S11 的可执行子集;规则全集与动机见
|
||||
`design/engineering/architecture/architecture.md`「测试与质量域」节。新违规案例必须**先补扫描规则再修码**。
|
||||
|
||||
S11 代码注释禁用词:扫描 game/ 全域 .gd/.tres/.md/.json/.sh 的注释面,词表从 `design/gdd/术语表.md`「退役词对照」解析(显式追加「完美排雷」,排除「巢穴」「旗」);三层豁免(闸门自指/显式留档 4 处/非注释面天然不取);两道自检(扫描面文件数非空+词表解析非空)。
|
||||
S11 代码注释禁用词:扫描 game/ 全域 .gd/.tres/.md/.json/.sh 的注释面,词表从 `design/gdd/术语表.md`「退役词对照」解析(显式追加「完美封印」,排除「巢穴」「旗」);三层豁免(闸门自指/显式留档 4 处/非注释面天然不取);两道自检(扫描面文件数非空+词表解析非空)。
|
||||
|
||||
## 本地闸(唯一验收门禁)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
5. 移动:已开格瞬移、**已引爆危险格可通行可读**(工程债呈现半边)
|
||||
6. 停手:RAP 1:1 转存、下轮 AP 硬重置同图继续
|
||||
7. 轮末结算:明细逐行呈现、来源标注可读(P2——"这一行是我哪步扫雷带来的"可答)
|
||||
8. 清图:清图奖励兑付 + 完美排雷高光(零误标时双份)+ 换新图;未刷新的停手轮不换图
|
||||
8. 清图:清图奖励兑付 + 完美封印高光(零误标时双份)+ 换新图;未刷新的停手轮不换图
|
||||
9. 轮内刷新(方案 A):Active 当场换图、AP 保留、RAP 扣减、每轮 ≤2 次、跨图事实结算完整
|
||||
|
||||
## Battle & Level
|
||||
|
||||
+10
-10
@@ -70,7 +70,7 @@ fi
|
||||
|
||||
# S3 — core/ 禁 ConfigDB 外 data 表加载(schema class_name 直引豁免)
|
||||
# 扫描路径必须写 game/core——写裸 `core` 仓根无此目录,恒零命中恒绿(静默空转)。
|
||||
# 豁免:①注释行 ②game/core/config_db.gd 自身(数值单一事实源的正主,它的单点 load 是本规则的例外)。
|
||||
# 豁免:①注释行 ②game/core/config_db.gd 自身(数值单一事实源的现行事实源,它的单点 load 是本规则的例外)。
|
||||
if require_scan_face "S3" "$DIR_CORE"; then
|
||||
hits=$(grep -rnE '\b(load|preload)[[:space:]]*\(|ResourceLoader\.load' "$DIR_CORE" --include='*.gd' 2>/dev/null \
|
||||
| grep -vE '^[^:]+:[0-9]+:[[:space:]]*#' \
|
||||
@@ -97,7 +97,7 @@ fi
|
||||
# 禁「板级」「门票」「正主」「落籍」「完美排雷」等退役词进注释面(完整词表见术语表解析)
|
||||
# 权威出处:design/gdd/术语表.md「退役词对照」节+「对外命名纪律」节
|
||||
# 扫描面:game/ 全域 .gd/.tres/.md/.json/.sh(.txt 不收=第三方许可证非本仓库文本)
|
||||
# 词表来源:解析「退役词对照」第一列(去括号注、斜杠拆分)+显式追加「完美排雷」;显式排除「巢穴」(玩家专名/风味层,术语表自带除外注)、「旗」(单字误报率高,doc_term_audit 判例)
|
||||
# 词表来源:解析「退役词对照」第一列(去括号注、斜杠拆分)+显式追加禁「完美排雷」(受对外命名纪律约束,不在退役词对照表里);显式排除「巢穴」(玩家专名/风味层,术语表自带除外注)、「旗」(单字误报率高,doc_term_audit 判例)
|
||||
# 注释文本提取:.gd/.sh 取 # 后文本;.tres 取 ; 后文本;.md 取整行;.json 无注释语法(保留扩展名但不产生注释段)
|
||||
# 三层豁免依序:①闸门自指(行内含检查/禁令形态即跳过)②显式留档豁免单 4 处 ③非注释面天然不取
|
||||
|
||||
@@ -148,11 +148,11 @@ else
|
||||
for(i=1;i<=nw;i++){
|
||||
if(index(cmt,words[i])>0){
|
||||
if($0~/contains\(|find\(|grep|has_char\(|禁「|禁『|零「|零『/)next
|
||||
if(FILENAME~"enemy.tres"&&NR==653)next
|
||||
if(FILENAME~"level_runner"&&NR==832)next
|
||||
if(FILENAME~"adventure_runner"&&NR==403)next
|
||||
if(FILENAME~"damage_math_test"&&NR==36)next
|
||||
print FILENAME":"NR":"words[i]
|
||||
if(FILENAME~"enemy.tres"&&FNR==653)next
|
||||
if(FILENAME~"level_runner"&&FNR==832)next
|
||||
if(FILENAME~"adventure_runner"&&FNR==403)next
|
||||
if(FILENAME~"damage_math_test"&&FNR==36)next
|
||||
print FILENAME":"FNR":"words[i]
|
||||
next
|
||||
}
|
||||
}
|
||||
@@ -167,8 +167,8 @@ else
|
||||
for(i=1;i<=nw;i++){
|
||||
if(index(cmt,words[i])>0){
|
||||
if($0~/contains\(|find\(|grep|has_char\(|禁「|禁『|零「|零『/)next
|
||||
if(FILENAME~"enemy.tres"&&NR==653)next
|
||||
print FILENAME":"NR":"words[i]
|
||||
if(FILENAME~"enemy.tres"&&FNR==653)next
|
||||
print FILENAME":"FNR":"words[i]
|
||||
next
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ else
|
||||
for(i=1;i<=nw;i++){
|
||||
if(index($0,words[i])>0){
|
||||
if($0~/contains\(|find\(|grep|has_char\(|禁「|禁『|零「|零『/)next
|
||||
print FILENAME":"NR":"words[i]
|
||||
print FILENAME":"FNR":"words[i]
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ func _init() -> void:
|
||||
"判定相减:误标 1 − 豁免 1 = 有效 0 且标中≥1 → 完美成立〔卡② R2 真值表〕")
|
||||
orch._perfect_hit_true = 0
|
||||
Kit.check_quiet(not orch.perfect_sweep_earned(),
|
||||
"判定守卫:标中数 0 时零误标也不成立(板级 ≥1 标中条件零松动)〔卡② R2 真值表〕")
|
||||
"判定守卫:标中数 0 时零误标也不成立(整图 ≥1 标中条件零松动)〔卡② R2 真值表〕")
|
||||
var rig_rng2 = RngScript.new()
|
||||
rig_rng2.set_master_seed(778002)
|
||||
var orch2 = RigScript.new(db, rig_rng2)
|
||||
|
||||
@@ -95,7 +95,7 @@ func check_v7(a, db) -> void:
|
||||
if String(t.get("tier", "")) != "common":
|
||||
ok_fb = false
|
||||
Kit.check_quiet(ok_fb, "子池空回退全池:全普通池候选恒 3 格普通档〔专长批 V7〕")
|
||||
# 构成③:凭证不进子池也不进全池视图(独立计数体系——只经门票注入出现)
|
||||
# 构成③:凭证不进子池也不进全池视图(独立计数体系——只经专长凭证注入出现)
|
||||
a._curio_deck = [_tok("gp", "common"), _tok("attack", "common"), _tok("max_hp", "common"),
|
||||
_tok("feat_ticket", "excellent")]
|
||||
var ticket_seen := false
|
||||
|
||||
@@ -130,7 +130,7 @@ func _rows_contain(pool: Array, row: Dictionary) -> bool:
|
||||
func _test_shop_accessors(db) -> void:
|
||||
var products: Array = db.shop_products()
|
||||
if products.is_empty():
|
||||
Kit.check("ShopTable products 行族非空(表已落籍前提)", false)
|
||||
Kit.check("ShopTable products 行族非空(表已已入库前提)", false)
|
||||
return
|
||||
Kit.check("ShopTable products 行族非空", true)
|
||||
var first: Dictionary = products[0]
|
||||
|
||||
@@ -38,7 +38,7 @@ func _run() -> void:
|
||||
ov.visible and btns == 3 and not ov._confirm_btn.visible and not ov._continue_btn.visible):
|
||||
return
|
||||
# ①b 刷新面投喂(对齐商店 MC-1——投喂前隐藏/免费位点亮/GP 付费档禁用态/真实钮路径外发)
|
||||
if not _req("投喂前刷新钮应隐藏(未投喂上下文如店内门票面无刷新)",
|
||||
if not _req("投喂前刷新钮应隐藏(未投喂上下文如店内专长凭证面无刷新)",
|
||||
not ov._refresh_btn.visible):
|
||||
return
|
||||
var refreshed := []
|
||||
|
||||
Reference in new issue
Block a user