From d4cde739763f0588ae0ee860eafe05791fcbd5fe Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Mon, 5 Oct 2026 18:30:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A5=87=E7=89=A9=E6=89=B9T1=EF=BC=9Afeature?= =?UTF-8?q?=5F*=E2=86=92curio=5F*=E8=AF=8D=E6=97=8F=E6=8D=A2=E5=90=8D?= =?UTF-8?q?=EF=BC=88CURIO=5FKINDS/curio=5Fquota/curio=5Fvalue/curio=5Fcand?= =?UTF-8?q?idate=5Fcount+adventure.tres=E9=94=AE=E5=90=8D+entities.yaml?= =?UTF-8?q?=E6=8D=A2=E4=BB=A3=E7=99=BB=E8=AE=B0=E7=BB=AD=E5=86=99=EF=BC=8C?= =?UTF-8?q?=E5=80=BC=E9=9B=B6=E5=8F=98=E6=9B=B4=E5=AE=9E=E6=B5=8B=EF=BC=9B?= =?UTF-8?q?T0=E5=B7=AE=E5=BC=82=E5=9B=9E=E5=86=99=EF=BC=9A93=E5=A4=84/7?= =?UTF-8?q?=E6=96=87=E4=BB=B6+bonus=5Faux=5Fcarry=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E6=BE=84=E6=B8=85=E5=89=94=E9=99=A4=E6=94=B9=E5=90=8D=E9=9D=A2?= =?UTF-8?q?+=E5=9F=BA=E7=BA=BF772/0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/registry/entities.yaml | 10 +- ...务书-奇物词族对齐与渠道分离批-2026-10-05.md | 2 + game/core/adventure_runner.gd | 18 +-- game/core/battle_orchestrator.gd | 2 +- game/core/config_db_cross_validator.gd | 8 +- game/core/level_runner.gd | 2 +- game/data/schemas/adventure_table.gd | 106 +++++++++--------- game/data/tables/adventure.tres | 42 +++---- .../presentation/bonus_interact_controller.gd | 4 +- game/smoke/smoke_all.gd | 26 ++--- 10 files changed, 111 insertions(+), 109 deletions(-) diff --git a/design/registry/entities.yaml b/design/registry/entities.yaml index d31ff5e0..f386a869 100644 --- a/design/registry/entities.yaml +++ b/design/registry/entities.yaml @@ -613,12 +613,12 @@ entities: fields: | 退役两字段(迭代 10 奖励重构批,2026-09-30 用户拍板):level_clear_hp_bonus(「血回满+上限提升」件随大奖励三件套退役——回血改 clear_heal_pct 部分回血、上限提升改三选一件值列)、keystone_per_level(钥石退役出大奖励改 Boss/精英击杀掉落)。 clear_heal_pct: int [0,100](knob 默认 20——非末关通关部分回血回复生效上限的百分比,封顶上限不回满、满血回 0 合法;难度上压方向,带重扫义务归 难度曲线与Boss) - **2026-10-05 命名统一批**:本表的属性值提升奇物字段与常量整体换名(旧 → 新)——BONUS_IDS → FEATURE_KINDS、bonus_token_count() → feature_quota()、bonus_value() → feature_value()、bonus_candidate_count → feature_candidate_count、token_{kind}_{tier} → feature_quota_{kind}_{tier}、bonus_*_flat/_amount(_large) → feature_value_{kind}_{tier};值零变更(句柄改称不改数),断点附随键名沿用历史形态不动(存档兼容)。换名动因见 curio 条目(v2.0 顶层改名为「奇物」)。 - feature_value_attack_common / feature_value_max_hp_common / feature_value_armor_common: int [0,999](三选一属性值提升奇物兑付值——加算区攻击/生命上限/护甲轴累加,经覆盖值通道;值锚与上调约束归 难度曲线与Boss) - feature_value_gp_common: int [0,999](GP 袋件定额入钱包);feature_value_ap_rarest: int [0,10](AP 件每场战斗首轮行动点基线增量);bonus_aux_item_count: int [1,9](魔法道具件授予件数) + **2026-10-05 命名统一批**:本表的属性值提升奇物字段与常量整体换名(旧 → 新)——BONUS_IDS → CURIO_KINDS、bonus_token_count() → curio_quota()(→ curio_quota(),本批)、bonus_value() → curio_value()、bonus_candidate_count → curio_candidate_count、token_{kind}_{tier} → curio_quota_{kind}_{tier}、bonus_*_flat/_amount(_large) → curio_value_{kind}_{tier};值零变更(句柄改称不改数),断点附随键名沿用历史形态不动(存档兼容)。换名动因见 curio 条目(v2.0 顶层改名为「奇物」)。 + curio_value_attack_common / curio_value_max_hp_common / curio_value_armor_common: int [0,999](三选一属性值提升奇物兑付值——加算区攻击/生命上限/护甲轴累加,经覆盖值通道;值锚与上调约束归 难度曲线与Boss) + curio_value_gp_common: int [0,999](GP 袋件定额入钱包);curio_value_ap_rarest: int [0,10](AP 件每场战斗首轮行动点基线增量);bonus_aux_item_count: int [1,9](魔法道具件授予件数) ~~bonus_weight_*(E-S 加权洗牌权重族)~~ / ~~bonus_cap_*(种类次数上限族)~~:**v2.2 令牌池换代退役(迭代 12 TP0——2026-10-03 追认 b 实施批;洗牌改令牌 Fisher-Yates、池消耗即上限)** - feature_quota_{kind}_{tier}: int [0,99](**TP0 令牌配额族**——kind×tier 计数:attack 18/5 · max_hp 17/5 · armor 17/5 · gp 18/5 · heal 0/5 · ap 0/0/3〔common/rare/rarest〕;未列组合=0;档位结构锚 70/25/3=98 张入 schema validate 硬断言〔罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项〕) - feature_value_attack_rare / feature_value_max_hp_rare / feature_value_armor_rare / feature_value_gp_rare: int [0,999](稀有档大数值对——+2/+10/+2/50);feature_value_heal_rare: int [0,999](恢复件 +6 当即回血——新入池种类 rare 档);MC 策略 316-f(autoplay 1 级最稀有/2 级最左)随批落地 + curio_quota_{kind}_{tier}: int [0,99](**TP0 令牌配额族**——kind×tier 计数:attack 18/5 · max_hp 17/5 · armor 17/5 · gp 18/5 · heal 0/5 · ap 0/0/3〔common/rare/rarest〕;未列组合=0;档位结构锚 70/25/3=98 张入 schema validate 硬断言〔罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项〕) + curio_value_attack_rare / curio_value_max_hp_rare / curio_value_armor_rare / curio_value_gp_rare: int [0,999](稀有档大数值对——+2/+10/+2/50);curio_value_heal_rare: int [0,999](恢复件 +6 当即回血——新入池种类 rare 档);MC 策略 316-f(autoplay 1 级最稀有/2 级最左)随批落地 transitional_sync_slots: int [0,9](同调位过渡读数源,默认 1——道具持有上限;正主 = attunement_growth.tres 里程碑谓词表,同调实施批落地后切换读数源) mvp_content: 单行全局默认值即 MVP 行(provisional 归 曲线调参批——迭代 10 扩列批注) extension_reserve: 大奖励形态扩列位已消费(迭代 10 奖励重构批落地三选一/攻击型——本键使命完成退役;冒险结构 OQ2 收口) diff --git a/design/research/任务书-奇物词族对齐与渠道分离批-2026-10-05.md b/design/research/任务书-奇物词族对齐与渠道分离批-2026-10-05.md index 0656330f..7d163423 100644 --- a/design/research/任务书-奇物词族对齐与渠道分离批-2026-10-05.md +++ b/design/research/任务书-奇物词族对齐与渠道分离批-2026-10-05.md @@ -101,6 +101,8 @@ ### T1 词族对齐第一批:`feature_*` → `curio_*`(≈0.7d) +> ✅ **T0 复核差异回写(2026-10-05 实测,master 413c936)**:①`feature_*` 实测 **93 处/7 文件**(§2.1 的 103 系③秘宝批动 smoke/bonus_interact_controller 前口径);②运行层 `bonus_` 族实测远超 160 处(含信号 bonus_choice_presented/bonus_resolved/bonus_overlay 等全部形态);③**`bonus_aux_carry` 语义澄清=秘宝件跨关携带(③批已对齐 treasure 词族,内部变量现名 _bonus_treasure_carry),非奇物概念——本批改名面剔除,存档键引号字面量照③批先例禁改**;④基线=冒烟 772/0+run_all 14/15(reward_overlay 红=M7 bcard 换控件致 `c is Button` 断言失效,成因已考,T2 触碰该测试时适配);⑤res_ 仅 smoke 局部变量 res_box 4 处(语义无关,资源词族 res_* 不撞)。 + - 范围:`FEATURE_KINDS` → `CURIO_KINDS`、`feature_quota()` → `curio_quota()`、`feature_value()` → `curio_value()`、`feature_candidate_count` → `curio_candidate_count`、`feature_quota_{kind}_{tier}` → `curio_quota_*`、`feature_value_{kind}_{tier}` → `curio_value_*` - 涉及:`adventure_table.gd` + `adventure.tres`(键名)+ 6 个引用文件 - **值零变更**(只改键名与常量名) diff --git a/game/core/adventure_runner.gd b/game/core/adventure_runner.gd index 561a5795..3df74700 100644 --- a/game/core/adventure_runner.gd +++ b/game/core/adventure_runner.gd @@ -267,14 +267,14 @@ func _reset_bonus_state() -> void: _node_bonus_pending = {} -# 令牌池构建(TP0 v2.2——按表 kind×tier 配额展开为持久多重集;构建序确定 = FEATURE_KINDS×TIERS 逐层, +# 令牌池构建(TP0 v2.2——按表 kind×tier 配额展开为持久多重集;构建序确定 = CURIO_KINDS×TIERS 逐层, # 随机性只发生在洗牌消费 reward_pick 封闭流的时刻。迭代 12 T1:规则改写型特性带=relic 活行每件 1 张追加 # (rarity common/rare→稀有令牌档、rarest→罕见令牌档——relic 永不入普通档;空表=零追加零扰动)) func _build_bonus_deck() -> Array: var deck: Array = [] - for kind in db.adventure.FEATURE_KINDS: + for kind in db.adventure.CURIO_KINDS: for tier in db.adventure.TIERS: - for i in int(db.adventure.feature_quota(String(kind), String(tier))): + for i in int(db.adventure.curio_quota(String(kind), String(tier))): deck.append({"kind": String(kind), "tier": String(tier)}) for row in db.relic_rows(): var rtier := "rarest" if String(row.get("rarity", "")) == "rarest" else "rare" @@ -361,7 +361,7 @@ func pick_bonus(kind: String, tier: String = "", relic_id: String = "") -> bool: if _find_token(candidates, kind, tier, relic_id).is_empty(): push_error("[冒险结构] pick_bonus 拒绝——令牌不在候选: %s|%s|%s" % [kind, tier, relic_id]) return false - var value: int = int(db.adventure.feature_value(kind, tier)) + var value: int = int(db.adventure.curio_value(kind, tier)) var hp_before := int(ledger.get("hero_hp", 0)) if kind == "treasure_item": return _pick_treasure_item(value) # 道具件分派通关渠道(持有容器 = 跨关携带——与节点渠道分轨;池种退役后不可达) @@ -457,10 +457,10 @@ func pool_stock(kind: String) -> int: # 写加算区+账本+摘牌(与奖励三选一真单点——买一件=奖励面少一件的库存语义由同库成立)。 # 未知 kind 拒绝(货架词表封闭的前置防御)。 func _consume_pool_purchase(kind: String, tier: String) -> bool: - if not db.adventure.FEATURE_KINDS.has(kind): + if not db.adventure.CURIO_KINDS.has(kind): push_error("[冒险结构] 商店购买消费拒绝——件不在池词表: %s" % kind) return false - return _apply_bonus_pick(kind, tier, int(db.adventure.feature_value(kind, tier))) + return _apply_bonus_pick(kind, tier, int(db.adventure.curio_value(kind, tier))) # 终局池快照(_settle 清账前调用——_reset_bonus_state 会重置 _bonus_taken,摘要 additive 键 @@ -552,7 +552,7 @@ func apply_node_bonus(kind: String, tier: String = "", relic_id: String = "") -> if _find_token(candidates, kind, tier, relic_id).is_empty(): push_error("[冒险结构] apply_node_bonus 拒绝——令牌不在候选: %s|%s|%s" % [kind, tier, relic_id]) return false - var value: int = int(db.adventure.feature_value(kind, tier)) + var value: int = int(db.adventure.curio_value(kind, tier)) if kind == "treasure_item": return _apply_node_treasure(value) # 道具件分派节点渠道(持有容器 = 关卡域库存——与通关渠道分轨;池种退役后不可达) if not _apply_bonus_pick(kind, tier, value, relic_id): @@ -573,7 +573,7 @@ func _apply_node_treasure(count: int) -> bool: var records: Array = [] if _runner != null and _runner.treasure_inventory != null: records = _runner.treasure_inventory.holding_records() - # 迭代 11 第①批 T7——守卫随过渡键退役拆除(FEATURE_KINDS 已除名 treasure_item,本分支不可达; + # 迭代 11 第①批 T7——守卫随过渡键退役拆除(CURIO_KINDS 已除名 treasure_item,本分支不可达; # 替换子交互路由随容量闸一并退役——能力件容量闸正主 = 营地装配面满位禁选) if _runner != null: for iid in picked: @@ -739,7 +739,7 @@ func _draw_bonus_candidates() -> Array: if ident.begins_with("relic:"): cand["relic_id"] = String((tok as Dictionary).get("relic_id", "")) out.append(cand) - if out.size() >= int(db.adventure.feature_candidate_count): + if out.size() >= int(db.adventure.curio_candidate_count): break return out diff --git a/game/core/battle_orchestrator.gd b/game/core/battle_orchestrator.gd index 85da5281..11667074 100644 --- a/game/core/battle_orchestrator.gd +++ b/game/core/battle_orchestrator.gd @@ -680,7 +680,7 @@ func set_treasure_unlocked(ids: Dictionary) -> void: func _grant_routed(snap: Dictionary, polarity: String, source_class: String, cell: Vector2i, ri: int, highlight: String = "", label_suffix: String = "") -> bool: # 迭代 11 第①批 T7——aux 授予分支随掉落/停点渠道退役拆除(reward 词表第十型 treasure_item 保留但零投放: - # 无 aux 行入池、FEATURE_KINDS 词表已除名);剩余类型走极性字典路由。 + # 无 aux 行入池、CURIO_KINDS 词表已除名);剩余类型走极性字典路由。 var row: Dictionary = _reward_economy.polarity_row(String(snap.get("cell_type", "")), polarity) if row.is_empty(): _fatal("极性字典缺行: %s %s" % [String(snap.get("cell_type", "")), polarity]) diff --git a/game/core/config_db_cross_validator.gd b/game/core/config_db_cross_validator.gd index 0efe416c..583c3d2f 100644 --- a/game/core/config_db_cross_validator.gd +++ b/game/core/config_db_cross_validator.gd @@ -99,18 +99,18 @@ func cross_validate(loaded: Dictionary, push_diag: Callable) -> void: for e in validate_skill_pool_links(skt, en, loaded.get("status_effects")): push_diag.call("error", e.category, e.message) # ⑥ 商店货架 × 冒险共享池跨表校验(M-4 迭代 11 第②批 T1——次数上限域): - # pool_shelf kind 须命中 adventure.FEATURE_KINDS 且为有限库存种(cap ∈ [1,99]——gp 无上限种/牌库外种 + # pool_shelf kind 须命中 adventure.CURIO_KINDS 且为有限库存种(cap ∈ [1,99]——gp 无上限种/牌库外种 # 入货架 = 库存账本无锚,加载致命;gp 袋负交易切边/规则改写型特性三轴切边由 ShopTable 词表封闭另拦) var adv = loaded.get("adventure") var shp = loaded.get("shop") if adv != null and shp != null: for row in shp.pool_shelf: var kind: String = String(row.get("kind_id", "")) - if not adv.FEATURE_KINDS.has(kind): - push_diag.call("error", "shelf_dangling_kind", "ShopTable.pool_shelf kind %s 不在 AdventureTable.FEATURE_KINDS(共享池牌库外种)" % kind) + if not adv.CURIO_KINDS.has(kind): + push_diag.call("error", "shelf_dangling_kind", "ShopTable.pool_shelf kind %s 不在 AdventureTable.CURIO_KINDS(共享池牌库外种)" % kind) continue # TP0 令牌池——货架件须为有限令牌种(配额 >0;种类次数上限退役后库存=剩余令牌数) - var quota := int(adv.feature_quota(kind, adv.TIER_COMMON)) + int(adv.feature_quota(kind, adv.TIER_RARE)) + int(adv.feature_quota(kind, adv.TIER_RAREST)) + var quota := int(adv.curio_quota(kind, adv.TIER_COMMON)) + int(adv.curio_quota(kind, adv.TIER_RARE)) + int(adv.curio_quota(kind, adv.TIER_RAREST)) if quota < 1: push_diag.call("error", "shelf_zero_quota", "ShopTable.pool_shelf kind %s 令牌配额为 0(牌库空种入货架 = 库存无锚)" % kind) diff --git a/game/core/level_runner.gd b/game/core/level_runner.gd index 0d5f745a..99a12096 100644 --- a/game/core/level_runner.gd +++ b/game/core/level_runner.gd @@ -834,7 +834,7 @@ func shop_shelf() -> Array: var tier := String((tok as Dictionary).get("tier", "")) var row: Dictionary = db.shop_pool_row(kind) var display := String(row.get("display_name", kind)) - var value := int(db.adventure.feature_value(kind, tier)) + var value := int(db.adventure.curio_value(kind, tier)) if row.is_empty() and kind == "relic": var rrow: Dictionary = db.relic_row(String(tok.get("relic_id", ""))) display = String(rrow.get("display_name", "特性")) diff --git a/game/data/schemas/adventure_table.gd b/game/data/schemas/adventure_table.gd index 8b55a98f..e82a3a10 100644 --- a/game/data/schemas/adventure_table.gd +++ b/game/data/schemas/adventure_table.gd @@ -18,13 +18,13 @@ extends Resource ## 它们是它的分类轴上的枚举(专长 / 属性值提升 / 资源),不是三套系统; ## 本表承载属性值提升与资源的种类配额与件值。 ## (2026-10-05 命名统一 + v2.0 改名:旧称「数值件」→ 属性提升;顶层「特性」→「奖励」→「奇物」。 -## 常量与字段随之前缀 feature_*,**尚未**随顶层改名换到 reward_*——见 06-待办清单。 +## 常量与字段随之前缀 curio_*,**尚未**随顶层改名换到 reward_*——见 06-待办清单。 ## 分类轴三个枚举:属性值提升〔生命上限 / AC / 攻击〕;资源〔行动点上限 / ## 刷新次数 / 金币 / 回复,命名待定〕——本表两类混编;刷新次数与专长获取两项尚未入表。 ## 类内异质性:金币与回复是即时兑付,不进持有集、不持续生效。) ## 三选一提升池 kind 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)。 ## treasure_item 池种退役(迭代 11 第①批 T7——同调批出池);heal 恢复件新入池(v2.2 令牌池追认 b)。 -const FEATURE_KINDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal"] +const CURIO_KINDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal"] ## 令牌档位词表(v2.2 三档位——稀有度命名对齐 MC 策略判读序 316-f:1 级最稀有=rarest 优先) const TIERS: Array[String] = ["common", "rare", "rarest"] const TIER_COMMON := "common" @@ -39,65 +39,65 @@ const TIER_QUOTAS := {"common": 70, "rare": 25, "rarest": 3} @export var clear_heal_pct: int = 20 # [0,100] knob——回复生效上限的百分比,封顶上限不回满 # —— 三选一候选数(2026-10-02 修复批 T2 魔法数结构化)—— -@export var feature_candidate_count: int = 3 # [1,6] knob——令牌洗牌不放回抽取张数上界 +@export var curio_candidate_count: int = 3 # [1,6] knob——令牌洗牌不放回抽取张数上界 @export var shop_refresh_free: int = 0 # [0,9] knob(MC-1 provisional——进店免费刷新次数;基础 0=Q2 裁,天赋增益位预留) @export var shop_refresh_cost_base: int = 20 # [1,999] knob(MC-1 provisional——GP 刷新基价) @export var shop_refresh_cost_curve: float = 1.8 # [1.0,4.0] knob(MC-1 provisional——按已付费刷新数幂曲线,A 链同族) # —— 令牌配额(kind × tier 计数;未列组合 = 0——heal 只入稀有/ap 只入罕见,v2.2 档位构成)—— -@export var feature_quota_attack_common: int = 18 # [0,99] -@export var feature_quota_attack_rare: int = 5 # [0,99] -@export var feature_quota_max_hp_common: int = 17 # [0,99] -@export var feature_quota_max_hp_rare: int = 5 # [0,99] -@export var feature_quota_armor_common: int = 17 # [0,99] -@export var feature_quota_armor_rare: int = 5 # [0,99] -@export var feature_quota_gp_common: int = 18 # [0,99] -@export var feature_quota_gp_rare: int = 5 # [0,99] -@export var feature_quota_heal_rare: int = 5 # [0,99]——恢复件(新入池种类,当即回血) -@export var feature_quota_ap_rarest: int = 3 # [0,99]——AP 件(罕见档;道具件 2 席位随池种退役收窄) +@export var curio_quota_attack_common: int = 18 # [0,99] +@export var curio_quota_attack_rare: int = 5 # [0,99] +@export var curio_quota_max_hp_common: int = 17 # [0,99] +@export var curio_quota_max_hp_rare: int = 5 # [0,99] +@export var curio_quota_armor_common: int = 17 # [0,99] +@export var curio_quota_armor_rare: int = 5 # [0,99] +@export var curio_quota_gp_common: int = 18 # [0,99] +@export var curio_quota_gp_rare: int = 5 # [0,99] +@export var curio_quota_heal_rare: int = 5 # [0,99]——恢复件(新入池种类,当即回血) +@export var curio_quota_ap_rarest: int = 3 # [0,99]——AP 件(罕见档;道具件 2 席位随池种退役收窄) # —— 令牌件值(小/大数值对——v2.2 追认 b 定稿:20/50、+1/+2、+1/+2、+5/+10、恢复+6、AP+1)—— -@export var feature_value_attack_common: int = 1 # [0,999] knob——小增伤 -@export var feature_value_attack_rare: int = 2 # [0,999] knob——大增伤 -@export var feature_value_max_hp_common: int = 5 # [0,999] knob——小生命 -@export var feature_value_max_hp_rare: int = 10 # [0,999] knob——大生命 -@export var feature_value_armor_common: int = 1 # [0,999] knob——小护甲 -@export var feature_value_armor_rare: int = 2 # [0,999] knob——大护甲 -@export var feature_value_gp_common: int = 20 # [0,999] knob——小GP -@export var feature_value_gp_rare: int = 50 # [0,999] knob——大GP -@export var feature_value_heal_rare: int = 6 # [0,999] knob——恢复(当即回血,封顶生效上限) -@export var feature_value_ap_rarest: int = 1 # [0,10] knob——AP 件每场战斗首轮行动点基线增量 +@export var curio_value_attack_common: int = 1 # [0,999] knob——小增伤 +@export var curio_value_attack_rare: int = 2 # [0,999] knob——大增伤 +@export var curio_value_max_hp_common: int = 5 # [0,999] knob——小生命 +@export var curio_value_max_hp_rare: int = 10 # [0,999] knob——大生命 +@export var curio_value_armor_common: int = 1 # [0,999] knob——小护甲 +@export var curio_value_armor_rare: int = 2 # [0,999] knob——大护甲 +@export var curio_value_gp_common: int = 20 # [0,999] knob——小GP +@export var curio_value_gp_rare: int = 50 # [0,999] knob——大GP +@export var curio_value_heal_rare: int = 6 # [0,999] knob——恢复(当即回血,封顶生效上限) +@export var curio_value_ap_rarest: int = 1 # [0,10] knob——AP 件每场战斗首轮行动点基线增量 ## 令牌配额读数(未列 kind×tier 组合 = 0——heal 无普通档/ap 无普通稀有档按 v2.2 构成) -func feature_quota(kind: String, tier: String) -> int: +func curio_quota(kind: String, tier: String) -> int: match [kind, tier]: - ["attack", TIER_COMMON]: return feature_quota_attack_common - ["attack", TIER_RARE]: return feature_quota_attack_rare - ["max_hp", TIER_COMMON]: return feature_quota_max_hp_common - ["max_hp", TIER_RARE]: return feature_quota_max_hp_rare - ["armor", TIER_COMMON]: return feature_quota_armor_common - ["armor", TIER_RARE]: return feature_quota_armor_rare - ["gp", TIER_COMMON]: return feature_quota_gp_common - ["gp", TIER_RARE]: return feature_quota_gp_rare - ["heal", TIER_RARE]: return feature_quota_heal_rare - ["ap", TIER_RAREST]: return feature_quota_ap_rarest + ["attack", TIER_COMMON]: return curio_quota_attack_common + ["attack", TIER_RARE]: return curio_quota_attack_rare + ["max_hp", TIER_COMMON]: return curio_quota_max_hp_common + ["max_hp", TIER_RARE]: return curio_quota_max_hp_rare + ["armor", TIER_COMMON]: return curio_quota_armor_common + ["armor", TIER_RARE]: return curio_quota_armor_rare + ["gp", TIER_COMMON]: return curio_quota_gp_common + ["gp", TIER_RARE]: return curio_quota_gp_rare + ["heal", TIER_RARE]: return curio_quota_heal_rare + ["ap", TIER_RAREST]: return curio_quota_ap_rarest return 0 ## 令牌件值(kind × tier;v2.2 数值对——小/大两档) -func feature_value(kind: String, tier: String = TIER_COMMON) -> int: +func curio_value(kind: String, tier: String = TIER_COMMON) -> int: match [kind, tier]: - ["attack", TIER_COMMON]: return feature_value_attack_common - ["attack", TIER_RARE]: return feature_value_attack_rare - ["max_hp", TIER_COMMON]: return feature_value_max_hp_common - ["max_hp", TIER_RARE]: return feature_value_max_hp_rare - ["armor", TIER_COMMON]: return feature_value_armor_common - ["armor", TIER_RARE]: return feature_value_armor_rare - ["gp", TIER_COMMON]: return feature_value_gp_common - ["gp", TIER_RARE]: return feature_value_gp_rare - ["heal", TIER_RARE]: return feature_value_heal_rare - ["ap", TIER_RAREST]: return feature_value_ap_rarest + ["attack", TIER_COMMON]: return curio_value_attack_common + ["attack", TIER_RARE]: return curio_value_attack_rare + ["max_hp", TIER_COMMON]: return curio_value_max_hp_common + ["max_hp", TIER_RARE]: return curio_value_max_hp_rare + ["armor", TIER_COMMON]: return curio_value_armor_common + ["armor", TIER_RARE]: return curio_value_armor_rare + ["gp", TIER_COMMON]: return curio_value_gp_common + ["gp", TIER_RARE]: return curio_value_gp_rare + ["heal", TIER_RARE]: return curio_value_heal_rare + ["ap", TIER_RAREST]: return curio_value_ap_rarest return 0 @@ -113,8 +113,8 @@ func tier_rank(tier: String) -> int: ## 档位令牌总数(货架/校验读面) func tier_total(tier: String) -> int: var total := 0 - for kind in FEATURE_KINDS: - total += feature_quota(kind, tier) + for kind in CURIO_KINDS: + total += curio_quota(kind, tier) return total @@ -127,18 +127,18 @@ func validate() -> Array: var errs: Array[Dictionary] = [] if clear_heal_pct < 0 or clear_heal_pct > 100: errs.append({"category": "domain", "message": "clear_heal_pct 越域 [0,100]: %d" % clear_heal_pct}) - for kind in FEATURE_KINDS: + for kind in CURIO_KINDS: for tier in TIERS: - var c := feature_quota(kind, tier) + var c := curio_quota(kind, tier) if c < 0 or c > 99: errs.append({"category": "domain", "message": "token_count(%s,%s) 越域 [0,99]: %d" % [kind, tier, c]}) - var v := feature_value(kind, tier) + var v := curio_value(kind, tier) if v < 0 or v > 999: - errs.append({"category": "domain", "message": "feature_value(%s,%s) 越域 [0,999]: %d" % [kind, tier, v]}) + errs.append({"category": "domain", "message": "curio_value(%s,%s) 越域 [0,999]: %d" % [kind, tier, v]}) for tier in TIERS: var total := tier_total(tier) if total != int(TIER_QUOTAS.get(tier, -1)): errs.append({"category": "domain", "message": "档位配额结构失锚(v2.2 追认 b——%s 应=%d 实=%d;改总量须重裁)" % [tier, int(TIER_QUOTAS.get(tier, -1)), total]}) - if feature_candidate_count < 1 or feature_candidate_count > 6: - errs.append({"category": "domain", "message": "feature_candidate_count 越域 [1,6]: %d" % feature_candidate_count}) + if curio_candidate_count < 1 or curio_candidate_count > 6: + errs.append({"category": "domain", "message": "curio_candidate_count 越域 [1,6]: %d" % curio_candidate_count}) return errs diff --git a/game/data/tables/adventure.tres b/game/data/tables/adventure.tres index e64cd4d8..aa3390b1 100644 --- a/game/data/tables/adventure.tres +++ b/game/data/tables/adventure.tres @@ -5,27 +5,27 @@ [resource] script = ExtResource("1") clear_heal_pct = 20 -feature_candidate_count = 3 -feature_quota_attack_common = 18 -feature_quota_attack_rare = 5 -feature_quota_max_hp_common = 17 -feature_quota_max_hp_rare = 5 -feature_quota_armor_common = 17 -feature_quota_armor_rare = 5 -feature_quota_gp_common = 18 -feature_quota_gp_rare = 5 -feature_quota_heal_rare = 5 -feature_quota_ap_rarest = 3 -feature_value_attack_common = 1 -feature_value_attack_rare = 2 -feature_value_max_hp_common = 5 -feature_value_max_hp_rare = 10 -feature_value_armor_common = 1 -feature_value_armor_rare = 2 -feature_value_gp_common = 20 -feature_value_gp_rare = 50 -feature_value_heal_rare = 6 -feature_value_ap_rarest = 1 +curio_candidate_count = 3 +curio_quota_attack_common = 18 +curio_quota_attack_rare = 5 +curio_quota_max_hp_common = 17 +curio_quota_max_hp_rare = 5 +curio_quota_armor_common = 17 +curio_quota_armor_rare = 5 +curio_quota_gp_common = 18 +curio_quota_gp_rare = 5 +curio_quota_heal_rare = 5 +curio_quota_ap_rarest = 3 +curio_value_attack_common = 1 +curio_value_attack_rare = 2 +curio_value_max_hp_common = 5 +curio_value_max_hp_rare = 10 +curio_value_armor_common = 1 +curio_value_armor_rare = 2 +curio_value_gp_common = 20 +curio_value_gp_rare = 50 +curio_value_heal_rare = 6 +curio_value_ap_rarest = 1 ; TP0 令牌池换代(2026-10-03,node-reward v2.2 追认 b 落地):三选一池 = 固定配额令牌池—— ; 普通 70/稀有 25/罕见 3 = 98 张(罕见档原列「道具件 2」随 treasure_item 池种退役收窄——台账自决披露项); diff --git a/game/presentation/bonus_interact_controller.gd b/game/presentation/bonus_interact_controller.gd index ac1621b5..87abb5a2 100644 --- a/game/presentation/bonus_interact_controller.gd +++ b/game/presentation/bonus_interact_controller.gd @@ -127,9 +127,9 @@ func _bonus_card_texts(candidates: Array, treasure_detail: Array = []) -> Array: elif kind == "treasure_item": var iid := String(treasure_detail[treasure_i]) if treasure_i < treasure_detail.size() else "" treasure_i += 1 - text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)), _treasure_card_line(iid)) + text = Narrator.bonus_card_text(kind, tier, int(db.adventure.curio_value(kind, tier)), _treasure_card_line(iid)) else: - text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier))) + text = Narrator.bonus_card_text(kind, tier, int(db.adventure.curio_value(kind, tier))) out.append({"id": cid, "text": text}) return out diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index 836d9492..c613f74b 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -220,12 +220,12 @@ func _smoke_adventure_table() -> void: check(int(_db.adventure.tier_total(tier)) == int(_db.adventure.TIER_QUOTAS[tier]), "档位配额结构锚(v2.2 追认 b):%s = %d 张" % [tier, int(_db.adventure.TIER_QUOTAS[tier])]) check(int(_db.adventure.deck_total()) == 98, "令牌池总量 = 98 张(普通 70/稀有 25/罕见 3——罕见档随道具件池种退役收窄)") - check(int(_db.adventure.feature_value("gp", "common")) == 20 and int(_db.adventure.feature_value("gp", "rare")) == 50 - and int(_db.adventure.feature_value("attack", "common")) == 1 and int(_db.adventure.feature_value("attack", "rare")) == 2 - and int(_db.adventure.feature_value("max_hp", "common")) == 5 and int(_db.adventure.feature_value("max_hp", "rare")) == 10 - and int(_db.adventure.feature_value("armor", "common")) == 1 and int(_db.adventure.feature_value("armor", "rare")) == 2, + check(int(_db.adventure.curio_value("gp", "common")) == 20 and int(_db.adventure.curio_value("gp", "rare")) == 50 + and int(_db.adventure.curio_value("attack", "common")) == 1 and int(_db.adventure.curio_value("attack", "rare")) == 2 + and int(_db.adventure.curio_value("max_hp", "common")) == 5 and int(_db.adventure.curio_value("max_hp", "rare")) == 10 + and int(_db.adventure.curio_value("armor", "common")) == 1 and int(_db.adventure.curio_value("armor", "rare")) == 2, "数值对(v2.2):小GP 20/大GP 50 · 小增伤 +1/大 +2 · 小生命 +5/大 +10 · 小护甲 +1/大 +2") - check(int(_db.adventure.feature_value("heal", "rare")) == 6 and int(_db.adventure.feature_value("ap", "rarest")) == 1, + check(int(_db.adventure.curio_value("heal", "rare")) == 6 and int(_db.adventure.curio_value("ap", "rarest")) == 1, "恢复件 +6 当即回血(新入池种类,rare 档)· AP +1(rarest 档)") check(_db.attunement_growth != null and int(_db.attunement_slot_cap()) == 3 and Attunement.slots(_db, null) == 0, @@ -349,7 +349,7 @@ func _smoke_adventure() -> void: var cand_ok := picks.size() == 2 var ks_gain_ok := picks.size() == 2 var resolve_ok := level_resolves.size() == 2 - var max_flat := int(_db.adventure.feature_value_max_hp_common) + var max_flat := int(_db.adventure.curio_value_max_hp_common) var heal_pct := int(_db.adventure.clear_heal_pct) var hp_acc := 0 # max_hp 件累加(回血封顶断言的生效上限推导——TP0 起按兑付令牌实值,大小档分别计) var ks_prefix := 0 @@ -386,7 +386,7 @@ func _smoke_adventure() -> void: var r: Dictionary = level_resolves[i] var rk := String(r.get("picked", "")) var rt := String(r.get("tier", "")) - if _smoke_find_token(p.get("candidates", []) as Array, rk, rt).is_empty() or int(r.get("value", -1)) != int(_db.adventure.feature_value(rk, rt)): + if _smoke_find_token(p.get("candidates", []) as Array, rk, rt).is_empty() or int(r.get("value", -1)) != int(_db.adventure.curio_value(rk, rt)): resolve_ok = false if rk == "max_hp": hp_acc += int(r.get("value", max_flat)) @@ -399,7 +399,7 @@ func _smoke_adventure() -> void: var exp_base := maxi(1, int(round(float(int(_db.hero.max_hp)) * k))) # 模拟档 v3.4 商店贪心购血(数值修复批)合法抬升——上限窗口 = 基础 + 加算区 3 件 + 购血余量; # TP0 数值对后 max_hp 件有大生命 +10(rare 档)——上界按大件最坏构成 3×10+购血 15=+45(TP0 放宽) - var hp_ceiling := maxi(1, int(round(float(int(_db.hero.max_hp) + 3 * int(_db.adventure.feature_value("max_hp", "rare")) + 15) * k))) + var hp_ceiling := maxi(1, int(round(float(int(_db.hero.max_hp) + 3 * int(_db.adventure.curio_value("max_hp", "rare")) + 15) * k))) var seq_ok := seq.size() > 0 and int(seq[0]) == exp_base for v in (seq as Array): if int(v) < exp_base or int(v) > hp_ceiling: @@ -594,8 +594,8 @@ func _smoke_adventure() -> void: a13.present_node_bonus(ncands13, ndraw.get("aux_detail", []) as Array) a13.present_node_bonus([{"kind": "gp", "tier": "common"}]) var gp13 := int(a13.ledger.get("gp", 0)) - check(a13.apply_node_bonus("gp", "common") and int(a13.ledger.get("gp", 0)) == gp13 + int(_db.adventure.feature_value("gp", "common")), - "奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" % int(_db.adventure.feature_value("gp", "common"))) + check(a13.apply_node_bonus("gp", "common") and int(a13.ledger.get("gp", 0)) == gp13 + int(_db.adventure.curio_value("gp", "common")), + "奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" % int(_db.adventure.curio_value("gp", "common"))) check(a13._node_bonus_pending.is_empty(), "节点停点态兑付后清零(恰一次语义同构)") var s10: Dictionary = a10.summary check(String(s10.get("result", "")) == "abandoned" and not bool(s10.get("cleared", true)), @@ -3875,8 +3875,8 @@ func _smoke_shop_pool() -> void: var val0: int = int(a8.bonus.get(String(val_map[kind]), -999)) check(r8.buy_pool_item(kind), "购买受理(pool 口——%s|%s)" % [kind, tier]) check(int(r8.gp) == gp0 - int(buy_c.get("price", 0)), "钱包扣现价(%d → %d)" % [gp0, int(r8.gp)]) - check(int(a8.bonus.get(String(val_map[kind]), -999)) == val0 + int(_db.adventure.feature_value(kind, tier)), - "加算区 +令牌档位件值(池件=奖励件本体——%s|%s %+d)" % [kind, tier, int(_db.adventure.feature_value(kind, tier))]) + check(int(a8.bonus.get(String(val_map[kind]), -999)) == val0 + int(_db.adventure.curio_value(kind, tier)), + "加算区 +令牌档位件值(池件=奖励件本体——%s|%s %+d)" % [kind, tier, int(_db.adventure.curio_value(kind, tier))]) check(int(a8._bonus_taken.get(kind, 0)) == taken0 + 1, "共享池账本 -1(跨渠道单点——taken %d → %d)" % [taken0, int(a8._bonus_taken.get(kind, 0))]) # A 链:同visit 第二购现价 = ceil(base×b^(l2−1)×A^1)(货架已全重抽——新卡新价同公式) var second: Dictionary = {} @@ -3941,7 +3941,7 @@ func _smoke_shop_pool() -> void: for k in ps.keys(): var quota := 0 for tier in _db.adventure.TIERS: - quota += int(_db.adventure.feature_quota(String(k), tier)) + quota += int(_db.adventure.curio_quota(String(k), tier)) if int(ps[k]) < 0 or int(ps[k]) > quota: ps_ok = false check(ps_ok, "终局池余量在域 [0,配额](%s)" % str(ps))