用户 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:// 存档移开态)。
234 lines
15 KiB
GDScript
234 lines
15 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||
## 冒险大奖励表(奇物三选一令牌池)schema:档位配额/件值/已拿上限的类型化读取(单行全局;垂直切片验证:三关连探一条命走完)。
|
||
## kind/tier 词表封闭——断点附随件与牌库剔除态依赖,扩件走本表+registry 修订,禁调用侧私扩。
|
||
## 档位配额总量是结构锚(validate 硬断言):改投放总量=重裁非调参;全部 knob provisional,上调须重扫通关率带。
|
||
class_name AdventureTable
|
||
extends Resource
|
||
|
||
## 概念指路:本表的属性值提升与资源,与 feats.tres 的专长,同属一个对象——
|
||
## 「奇物」(一次冒险内各渠道给予玩家的增益总称)。定义见 design/gdd/systems/冒险循环/奇物.md。
|
||
## 它们是它的分类轴上的枚举(专长 / 属性值提升 / 资源),不是三套系统;
|
||
## 本表承载属性值提升与资源的种类配额与件值。
|
||
## (2026-10-05 命名统一 + v2.0 改名:旧称「数值件」→ 属性提升;顶层「特性」→「奖励」→「奇物」。
|
||
## 常量与字段随之前缀 curio_*,**尚未**随顶层改名换到 reward_*——见 06-待办清单。
|
||
## 分类轴三个枚举:属性值提升〔生命上限 / AC / 攻击〕;资源〔行动点上限 /
|
||
## 刷新次数 / GP / 回复,命名待定〕——本表两类混编;刷新次数与专长获取两项尚未入表。
|
||
## 类内异质性:GP与回复是即时兑付,不进持有集、不持续生效。)
|
||
## 三选一提升池 kind 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)。
|
||
## treasure_item 池种退役(迭代 11 第①批 T7——同调批出池);heal 恢复件新入池(v2.2 令牌池追认 b)。
|
||
## 迭代 20 T4 资源凭证入池五件;迭代 31 卡② 凭证件裁削批(用户 2026-10-18 逐裁)两件出池:
|
||
## 同调电池整件删除(呈现层零接线、玩家无分配途径——有 API 有账本唯独没有入口);
|
||
## 完美保险整件迁出资源类归专长(它给的是规则豁免而非可调动的余量——判据见奇物.md §1.1,
|
||
## 落表 feats.tres 第 30 行,效果类型 forgive_seal_miss)。留任 rap 储备金袋/time_sand 时沙。
|
||
const CURIO_KINDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal", "refresh",
|
||
"rap", "time_sand"] # T6 扩第七类(refresh=资源类成员——作为奇物授予的三选一重抽次数,作用对象=三选一界面非角色;见 registry refresh_boundary)
|
||
## 令牌档位词表(迭代 20 T2 换代——跨层四级稀有度框架〔01-核心循环 v1.5 档名映射:普通→普通、
|
||
## 稀有→优秀、罕见→稀有、传说=新增头奖位〕;1 级最稀有=legendary 优先)
|
||
const TIERS: Array[String] = ["common", "excellent", "rare", "legendary"]
|
||
const TIER_COMMON := "common"
|
||
const TIER_EXCELLENT := "excellent"
|
||
const TIER_RARE := "rare"
|
||
const TIER_LEGENDARY := "legendary"
|
||
## 档位配额结构锚(迭代 20 换代——T2 四级直映射 70/25/3/0;T4 凭证四件入稀有档投放 +6
|
||
## (rap 2/battery 1/时沙 2/保险 1)→ 稀有 9、总量 104;迭代 31 卡② 净删两件投放(battery 1/保险 1)
|
||
## → 稀有 7、总量 102(用户裁「净删」,禁把令牌转给别件保住总量)。已裁换代授权内的 provisional 投放
|
||
## (卡文 T2「四级配额表重构」+Q3 单迭代全量),偏离 GDD 占位记录随代拍板追认单呈报;
|
||
## validate() 硬断言;此后改总量=重裁非调参)。
|
||
const TIER_QUOTAS := {"common": 70, "excellent": 25, "rare": 7, "legendary": 0}
|
||
|
||
# —— 通关部分回血(固定型,非末关通关兑付)——
|
||
@export var clear_heal_pct: int = 20 # [0,100] knob——回复生效上限的百分比,封顶上限不回满
|
||
|
||
# —— 三选一候选数(2026-10-02 修复批 T2 魔法数结构化)——
|
||
@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。迭代 20 T2 四级换代:旧 rare→excellent、
|
||
# 旧 rarest→rare 物理承袭〔70/25/3 零偏离〕+凭证四 kind 占位 rare 档配额 0〔T4 落路由同批投放〕)——
|
||
@export var curio_quota_attack_common: int = 18 # [0,99]
|
||
@export var curio_quota_attack_excellent: int = 5 # [0,99]
|
||
@export var curio_quota_max_hp_common: int = 17 # [0,99]
|
||
@export var curio_quota_max_hp_excellent: int = 5 # [0,99]
|
||
@export var curio_quota_armor_common: int = 17 # [0,99]
|
||
@export var curio_quota_armor_excellent: int = 5 # [0,99]
|
||
@export var curio_quota_gp_common: int = 18 # [0,99]
|
||
@export var curio_quota_gp_excellent: int = 5 # [0,99]
|
||
@export var curio_quota_heal_excellent: int = 3 # [0,99]——恢复件(原 5;T6 挤占 2 席位予 refresh——用户 2026-10-05 裁方案B,总量 98 锚不变)
|
||
@export var curio_quota_refresh_excellent: int = 2 # [0,99]——刷新次数件(T6 新入池资源类成员;provisional 归曲线调参批)
|
||
@export var curio_quota_ap_rare: int = 3 # [0,99]——AP 件(稀有档;旧罕见档物理承袭)
|
||
@export var curio_quota_rap_rare: int = 2 # [0,99]——储备金袋(T4 投放 provisional 归调参批)
|
||
@export var curio_quota_time_sand_rare: int = 2 # [0,99]——时沙(T4 投放 provisional 归调参批)
|
||
|
||
# —— 令牌件值(小/大数值对——v2.2 追认 b 定稿:20/50、+1/+2、+1/+2、+5/+10、恢复+6、AP+1)——
|
||
@export var curio_value_attack_common: int = 1 # [0,999] knob——小增伤
|
||
@export var curio_value_attack_excellent: int = 2 # [0,999] knob——大增伤
|
||
@export var curio_value_max_hp_common: int = 5 # [0,999] knob——小生命
|
||
@export var curio_value_max_hp_excellent: int = 10 # [0,999] knob——大生命
|
||
@export var curio_value_armor_common: int = 1 # [0,999] knob——小护甲
|
||
@export var curio_value_armor_excellent: int = 2 # [0,999] knob——大护甲
|
||
@export var curio_value_gp_common: int = 20 # [0,999] knob——小GP
|
||
@export var curio_value_gp_excellent: int = 50 # [0,999] knob——大GP
|
||
@export var curio_value_heal_excellent: int = 6 # [0,999] knob——恢复(当即回血,封顶生效上限)
|
||
@export var curio_value_refresh_excellent: int = 1 # [0,9] knob(provisional)——刷新次数件兑付值(三选一重抽次数 +N——_attune_refresh_x 增量,不进加算区)
|
||
@export var curio_value_ap_rare: int = 1 # [0,10] knob——AP 件每场战斗首轮行动点基线增量
|
||
@export var curio_value_rap_rare: int = 3 # [0,99] knob(provisional)——储备金袋 RAP +N
|
||
@export var curio_value_time_sand_rare: int = 2 # [0,99] knob(provisional)——时沙 下轮 AP +N
|
||
|
||
# —— 已拿上限 cap(迭代 20 T2 概率与上限解耦〔奇物.md 池结构案D〕——案②令牌池+提前退役:
|
||
# 概率位=档+令牌数〔牌库物理张数〕、上限=本字段〔拿了才计、刷出不计〕;cap 满后该 kind 从候选
|
||
# 视图剔除〔提前退役〕。99=实质无上限占位,实数归调参批;专长 cap 在 feats.tres 行字段〕)——
|
||
@export var curio_cap_attack: int = 99 # [1,99]
|
||
@export var curio_cap_max_hp: int = 99 # [1,99]
|
||
@export var curio_cap_armor: int = 99 # [1,99]
|
||
@export var curio_cap_gp: int = 99 # [1,99]
|
||
@export var curio_cap_ap: int = 99 # [1,99]
|
||
@export var curio_cap_heal: int = 99 # [1,99]
|
||
@export var curio_cap_refresh: int = 99 # [1,99]
|
||
@export var curio_cap_rap: int = 99 # [1,99]
|
||
@export var curio_cap_time_sand: int = 99 # [1,99]
|
||
|
||
# —— 专长获取门票(迭代 15 卡② T5——非 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_limit: int = 1 # [1,9] knob(口径定死=1)——一局限购(选中/买下)次数
|
||
@export var feat_ticket_pity_step: int = 5 # [1,99] knob(口径定死=5)——保底步数(连续未出展示次数)
|
||
|
||
|
||
## 令牌兑付路由表(内容数据驱动扩展批 T5——_apply_curio_pick match 收敛进效果类型:
|
||
## 属性值提升四类 = 「加算落点键」声明路由,加新加算类令牌 = 表行+配额/件值键,零代码;
|
||
## 通道面三类(gp 钱包/heal 台账/refresh 界面余量)+relic 持有集 = 副作用通道显式分支不进本表
|
||
## ——路由表只承载「纯加算落点」形态,与效果引擎组合规则加法族同构)
|
||
const CURIO_APPLY_ROUTES := {
|
||
"attack": "atk",
|
||
"max_hp": "max_hp",
|
||
"armor": "armor_class",
|
||
"ap": "ap",
|
||
}
|
||
|
||
|
||
## 令牌加算路由读数(空 = 非加算形态——调用方走通道面分支)
|
||
func curio_apply_route(kind: String) -> String:
|
||
return String(CURIO_APPLY_ROUTES.get(kind, ""))
|
||
|
||
|
||
## 令牌配额读数(未列 kind×tier 组合 = 0——迭代 20 T2 四级构成:属性四类 common/excellent、
|
||
## heal/refresh excellent、ap rare、凭证四 kind rare 占位 0)
|
||
func curio_quota(kind: String, tier: String) -> int:
|
||
match [kind, tier]:
|
||
["attack", TIER_COMMON]: return curio_quota_attack_common
|
||
["attack", TIER_EXCELLENT]: return curio_quota_attack_excellent
|
||
["max_hp", TIER_COMMON]: return curio_quota_max_hp_common
|
||
["max_hp", TIER_EXCELLENT]: return curio_quota_max_hp_excellent
|
||
["armor", TIER_COMMON]: return curio_quota_armor_common
|
||
["armor", TIER_EXCELLENT]: return curio_quota_armor_excellent
|
||
["gp", TIER_COMMON]: return curio_quota_gp_common
|
||
["gp", TIER_EXCELLENT]: return curio_quota_gp_excellent
|
||
["heal", TIER_EXCELLENT]: return curio_quota_heal_excellent
|
||
["refresh", TIER_EXCELLENT]: return curio_quota_refresh_excellent
|
||
["ap", TIER_RARE]: return curio_quota_ap_rare
|
||
["rap", TIER_RARE]: return curio_quota_rap_rare
|
||
["time_sand", TIER_RARE]: return curio_quota_time_sand_rare
|
||
return 0
|
||
|
||
|
||
## 令牌件值(kind × tier;四级构成随配额表)
|
||
func curio_value(kind: String, tier: String = TIER_COMMON) -> int:
|
||
match [kind, tier]:
|
||
["attack", TIER_COMMON]: return curio_value_attack_common
|
||
["attack", TIER_EXCELLENT]: return curio_value_attack_excellent
|
||
["max_hp", TIER_COMMON]: return curio_value_max_hp_common
|
||
["max_hp", TIER_EXCELLENT]: return curio_value_max_hp_excellent
|
||
["armor", TIER_COMMON]: return curio_value_armor_common
|
||
["armor", TIER_EXCELLENT]: return curio_value_armor_excellent
|
||
["gp", TIER_COMMON]: return curio_value_gp_common
|
||
["gp", TIER_EXCELLENT]: return curio_value_gp_excellent
|
||
["heal", TIER_EXCELLENT]: return curio_value_heal_excellent
|
||
["refresh", TIER_EXCELLENT]: return curio_value_refresh_excellent
|
||
["ap", TIER_RARE]: return curio_value_ap_rare
|
||
["rap", TIER_RARE]: return curio_value_rap_rare
|
||
["time_sand", TIER_RARE]: return curio_value_time_sand_rare
|
||
return 0
|
||
|
||
|
||
## 已拿上限读数(迭代 20 T2 案②——kind 维度;专长 cap 走 feats.tres 行字段不走本面)
|
||
func curio_cap(kind: String) -> int:
|
||
match kind:
|
||
"attack": return curio_cap_attack
|
||
"max_hp": return curio_cap_max_hp
|
||
"armor": return curio_cap_armor
|
||
"gp": return curio_cap_gp
|
||
"ap": return curio_cap_ap
|
||
"heal": return curio_cap_heal
|
||
"refresh": return curio_cap_refresh
|
||
"rap": return curio_cap_rap
|
||
"time_sand": return curio_cap_time_sand
|
||
return 99
|
||
|
||
|
||
## Boss 专长三选一按档配比加权(迭代 20 T5——奇物.md v3.1 rarity 语义约束「候选按档配比或
|
||
## 加权抽取」兑付面;权重 provisional 归调参批——普通打底/优秀期待/稀有稀缺/传说头奖形态)
|
||
func boss_feat_weight(tier: String) -> int:
|
||
match tier:
|
||
TIER_COMMON: return 100
|
||
TIER_EXCELLENT: return 45
|
||
TIER_RARE: return 15
|
||
TIER_LEGENDARY: return 5
|
||
return 1
|
||
|
||
|
||
## 档位判读序(MC 策略 316-f——1 级最稀有:legendary > rare > excellent > common;并列同档取最左由调用方稳定序保证)
|
||
func tier_rank(tier: String) -> int:
|
||
match tier:
|
||
TIER_LEGENDARY: return 4
|
||
TIER_RARE: return 3
|
||
TIER_EXCELLENT: return 2
|
||
TIER_COMMON: return 1
|
||
return 0
|
||
|
||
|
||
## 档位令牌总数(货架/校验读面)
|
||
func tier_total(tier: String) -> int:
|
||
var total := 0
|
||
for kind in CURIO_KINDS:
|
||
total += curio_quota(kind, tier)
|
||
return total
|
||
|
||
|
||
## 牌库总量(结构锚——T2 四级 98 + T4 凭证投放 6 = 104:70+25+9+0)
|
||
func deck_total() -> int:
|
||
var total := 0
|
||
for tier in TIERS:
|
||
total += tier_total(tier)
|
||
return total
|
||
|
||
|
||
func validate() -> Array:
|
||
var errs: Array[Dictionary] = []
|
||
for kv in [["feat_ticket_chance", feat_ticket_chance, 0, 100], ["feat_ticket_quota", feat_ticket_quota, 0, 9], ["feat_ticket_limit", feat_ticket_limit, 1, 9], ["feat_ticket_pity_step", feat_ticket_pity_step, 1, 99]]:
|
||
if int(kv[1]) < int(kv[2]) or int(kv[1]) > int(kv[3]):
|
||
errs.append({"category": "domain", "message": "%s 出域 [%d,%d]: %d" % [kv[0], kv[2], kv[3], kv[1]]})
|
||
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 CURIO_KINDS:
|
||
for tier in TIERS:
|
||
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 := curio_value(kind, tier)
|
||
if v < 0 or v > 999:
|
||
errs.append({"category": "domain", "message": "curio_value(%s,%s) 越域 [0,999]: %d" % [kind, tier, v]})
|
||
if curio_cap(kind) < 1 or curio_cap(kind) > 99:
|
||
errs.append({"category": "domain", "message": "curio_cap(%s) 越域 [1,99]: %d" % [kind, curio_cap(kind)]})
|
||
for tier in TIERS:
|
||
var total := tier_total(tier)
|
||
if total != int(TIER_QUOTAS.get(tier, -1)):
|
||
errs.append({"category": "domain", "message": "档位配额结构失锚(四级锚 70/25/7/0——%s 应=%d 实=%d;改总量须重裁)" % [tier, int(TIER_QUOTAS.get(tier, -1)), total]})
|
||
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
|