迭代11第①批:魔法道具同调实施批 T0-T10 全落(重闸 645/0 + MC off 逐位 PASS)
- T1 表与schema:attunement_growth.tres 谓词表(m1/m2/m3+Σgrant≤slot_cap 校验+slots() 求值口径)+道具表扩列(form/charges/slot_cost/unlock_requires/effective_rounds/charge_n+effect_kinds 九kind+KEY_WHITELIST 零裸flat护栏)+七同调行 - T2 save v4(boss_kill_count 收束入账+attunement_equipped+attune_refresh_level+断点 attunement_charges+迁移链 v3→v4) - T3 Attunement 求值服务(纯函数零 await 零 RNG) - T4 营地装配覆盖层(工坊扩容程序占位+Y 升级行 attune_refresh_upgrade 行族) - T5 被动六件接线+装配注入链+刷新 X/Y 双源(BonusPickOverlay 刷新钮,autoplay 默认不刷) - T6 掘进蓄能全链+摆钟能力面(骑库存面差额注入+断点充能键);炸格 P5 甲影响评估破面大→用户裁拆后批,blast_kit deferred 留位 - T7 退役面五件(BONUS_IDS 除名 aux_item+transitional_sync_slots 过渡键退役=迭代10欠账③清偿+授予路/四容量闸拆除+nest_pendulum 换装 active_charged) - T8 冒烟六新断言(645/0)+MC attune 开关+贪心画像分层 off/on 各 N=60 双策略(on 画像功率显著带平移归调参批;off 新锚=对拍正主留盘主区 sim-data,81000 降批入口基准) - T9 连带修订九件(魔法道具定位重写/元进度v1.6/地图战斗资源v0.16/行动经济v0.7/05不做v1.3/关卡节点地图v1.4/node-reward v2.2/registry 三处/06 收口+炸格拆后批新条) - T10 重闸全绿:冒烟 645/0+熵增 PASS+doc 三闸零新增+MC off 复跑同种子逐位一致 PASS;出口人闸后移迭代 12(用户 2026-10-03 令)
This commit is contained in:
1 parent
02cb92a972
commit
a6a2bf885e
37 files changed
+1075
-173
No files matched your search
@@ -10,9 +10,10 @@
|
||||
class_name AdventureTable
|
||||
extends Resource
|
||||
|
||||
## 三选一提升池件 id 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)
|
||||
const BONUS_IDS: Array[String] = ["attack", "max_hp", "armor", "gp", "aux_item", "ap"]
|
||||
## 无次数上限件的 cap 哨兵值(gp/aux_item——牌库恒非空的结构保证)
|
||||
## 三选一提升池件 id 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)。
|
||||
## aux_item 池种退役(迭代 11 第①批 T7——同调批出池:魔法道具件改走营地同调装配面,不入三选一牌库)
|
||||
const BONUS_IDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap"]
|
||||
## 无次数上限件的 cap 哨兵值(gp——牌库恒非空的结构保证)
|
||||
const BONUS_CAP_UNLIMITED := -1
|
||||
|
||||
# —— 通关部分回血(固定型,非末关通关兑付)——
|
||||
@@ -28,14 +29,12 @@ const BONUS_CAP_UNLIMITED := -1
|
||||
@export var bonus_armor_flat: int = 1 # [0,999] knob——护甲轴累加
|
||||
@export var bonus_gp_amount: int = 20 # [0,999] knob——GP 袋定额入钱包
|
||||
@export var bonus_ap_flat: int = 1 # [0,10] knob——AP 件每场战斗首轮行动点基线增量
|
||||
@export var bonus_aux_item_count: int = 1 # [1,9] knob——魔法道具件授予件数(受同调位约束)
|
||||
|
||||
# —— 三选一权重(加权洗牌不放回,E-S weight-key)——
|
||||
@export var bonus_weight_attack: int = 3 # [1,99] knob
|
||||
@export var bonus_weight_max_hp: int = 3 # [1,99] knob
|
||||
@export var bonus_weight_armor: int = 3 # [1,99] knob
|
||||
@export var bonus_weight_gp: int = 3 # [1,99] knob
|
||||
@export var bonus_weight_aux: int = 1 # [1,99] knob——魔法道具件(受同调位约束)
|
||||
@export var bonus_weight_ap: int = 1 # [1,99] knob——AP 件(全冒险最紧上限)
|
||||
|
||||
# —— 全冒险获取次数上限(达上限件先剔出牌库;gp/aux_item 无上限)——
|
||||
@@ -44,9 +43,6 @@ const BONUS_CAP_UNLIMITED := -1
|
||||
@export var bonus_cap_armor: int = 3 # [0,99] knob
|
||||
@export var bonus_cap_ap: int = 2 # [0,99] knob——全冒险最紧
|
||||
|
||||
# —— 同调位过渡读数源(正主 = attunement_growth.tres 谓词表,同调实施批落地后切换)——
|
||||
@export var transitional_sync_slots: int = 1 # [0,9] knob——道具持有上限
|
||||
|
||||
|
||||
func bonus_value(id: String) -> int:
|
||||
match id:
|
||||
@@ -55,7 +51,6 @@ func bonus_value(id: String) -> int:
|
||||
"armor": return bonus_armor_flat
|
||||
"gp": return bonus_gp_amount
|
||||
"ap": return bonus_ap_flat
|
||||
"aux_item": return bonus_aux_item_count
|
||||
return 0
|
||||
|
||||
|
||||
@@ -65,12 +60,11 @@ func bonus_weight(id: String) -> int:
|
||||
"max_hp": return bonus_weight_max_hp
|
||||
"armor": return bonus_weight_armor
|
||||
"gp": return bonus_weight_gp
|
||||
"aux_item": return bonus_weight_aux
|
||||
"ap": return bonus_weight_ap
|
||||
return 0
|
||||
|
||||
|
||||
## 次数上限(gp/aux_item 返回 BONUS_CAP_UNLIMITED = 无上限,牌库恒非空的结构保证)
|
||||
## 次数上限(gp 返回 BONUS_CAP_UNLIMITED = 无上限,牌库恒非空的结构保证)
|
||||
func bonus_cap(id: String) -> int:
|
||||
match id:
|
||||
"attack": return bonus_cap_attack
|
||||
@@ -95,10 +89,6 @@ func validate() -> Array:
|
||||
var c := bonus_cap(id)
|
||||
if c < 0 or c > 99:
|
||||
errs.append({"category": "domain", "message": "bonus_cap(%s) 越域 [0,99]: %d" % [id, c]})
|
||||
if bonus_aux_item_count < 1 or bonus_aux_item_count > 9:
|
||||
errs.append({"category": "domain", "message": "bonus_aux_item_count 越域 [1,9]: %d" % bonus_aux_item_count})
|
||||
if bonus_candidate_count < 1 or bonus_candidate_count > BONUS_IDS.size():
|
||||
errs.append({"category": "domain", "message": "bonus_candidate_count 越域 [1,%d]: %d" % [BONUS_IDS.size(), bonus_candidate_count]})
|
||||
if transitional_sync_slots < 0 or transitional_sync_slots > 9:
|
||||
errs.append({"category": "domain", "message": "transitional_sync_slots 越域 [0,9]: %d" % transitional_sync_slots})
|
||||
return errs
|
||||
@@ -0,0 +1,81 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Validation Question: 同调位增长是否由「通关次数 + Boss 击杀数」经数据驱动的里程碑谓词表实时求值,
|
||||
# 试玩后调增长曲线 = 改表不动码(proposal-magic-item-attunement-2026-09-22 §2.1 用户点名要求)
|
||||
# Date: 2026-10-03(迭代 11 第①批 魔法道具同调实施批 T1——任务书 v1.1 §六 T1;设计权威底稿 proposal §2)
|
||||
# 数据配置 AttunementGrowthTable schema(魔法道具 回填 owner)。
|
||||
# 单行全局常量表(slot_cap + milestones 行族——AdventureTable 单行全局先例,Rule 4 豁免)。
|
||||
# 行 = Dictionary:{id: String 唯一, grant: int, requires: [{key: String, threshold: int}]}——
|
||||
# requires 为 (计数键, 阈值) 对的 AND 列表,全部满足即授予 grant 槽;
|
||||
# 同调位读数唯一口径 = Σ已达成 grant clamp slot_cap(slots())。
|
||||
# 承重契约(任务书 §三 7 + 底稿 §2.1):
|
||||
# 计数键封闭枚举(COUNTER_KEYS——预留可插拔位 COUNTER_KEYS_RESERVED 本期不实现、加行即扩展不破坏
|
||||
# schema);阈值 [1,999];Σgrant ≤ slot_cap(超出部分永不可达,禁);数值全 provisional 归
|
||||
# 难度曲线与Boss——本表只锁形态,试玩调平衡的全部动作落在表上(改阈值/换计数键/slot_cap 加行)。
|
||||
# OR/复合需求出现时升级谓词形态走任务书修订(底稿 §2.1 同款约束)。
|
||||
class_name AttunementGrowthTable
|
||||
extends Resource
|
||||
|
||||
@export var slot_cap: int = 3
|
||||
@export var milestones: Array = [] # Array[Dictionary] 键 id/grant/requires
|
||||
|
||||
# 计数键封闭枚举(底稿 §2.1——save_file 逐域记账的键词表;T2 落 boss_kill_count 记账)
|
||||
const COUNTER_KEYS := ["clear_count", "boss_kill_count"]
|
||||
# 预留可插拔位(本期不实现,schema 枚举不收——底稿 §2.1 明列四件)
|
||||
const COUNTER_KEYS_RESERVED := ["boss_firstkill_count", "adventure_count", "no_damage_clear_count", "run_depth_best"]
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array = []
|
||||
if slot_cap < 0 or slot_cap > 9:
|
||||
errs.append({"category": "domain", "message": "slot_cap 越域 [0,9]: %d" % slot_cap})
|
||||
var seen := {}
|
||||
var grant_sum := 0
|
||||
for row in milestones:
|
||||
var mid: String = String(row.get("id", ""))
|
||||
if mid == "":
|
||||
errs.append({"category": "domain", "message": "milestone id 空"})
|
||||
continue
|
||||
if seen.has(mid):
|
||||
errs.append({"category": "dup_key", "message": "milestone id 重复: %s" % mid})
|
||||
continue
|
||||
seen[mid] = true
|
||||
var grant: int = int(row.get("grant", 0))
|
||||
if grant < 1 or grant > maxi(1, slot_cap):
|
||||
errs.append({"category": "domain", "message": "%s grant 越域 [1,slot_cap=%d]: %d" % [mid, slot_cap, grant]})
|
||||
grant_sum += maxi(0, grant)
|
||||
var reqs: Array = row.get("requires", [])
|
||||
if reqs.is_empty():
|
||||
errs.append({"category": "domain", "message": "%s requires 空(无条件授予非法——里程碑必有谓词)" % mid})
|
||||
var key_seen := {}
|
||||
for req in reqs:
|
||||
var key: String = String(req.get("key", ""))
|
||||
if not COUNTER_KEYS.has(key):
|
||||
errs.append({"category": "enum", "message": "%s 计数键出域 %s: %s" % [mid, str(COUNTER_KEYS), key]})
|
||||
if key_seen.has(key):
|
||||
errs.append({"category": "dup_key", "message": "%s 计数键重复: %s" % [mid, key]})
|
||||
key_seen[key] = true
|
||||
var th: int = int(req.get("threshold", 0))
|
||||
if th < 1 or th > 999:
|
||||
errs.append({"category": "domain", "message": "%s 阈值越域 [1,999]: %d" % [mid, th]})
|
||||
if grant_sum > slot_cap:
|
||||
errs.append({"category": "cross_field", "message": "Σgrant(%d) > slot_cap(%d)——超出部分永不可达,schema 禁" % [grant_sum, slot_cap]})
|
||||
return errs
|
||||
|
||||
|
||||
# 实时求值:Σ已达成 grant(谓词 = requires 全键达标;counters = {计数键: int},缺键按 0 计)
|
||||
func granted_slots(counters: Dictionary) -> int:
|
||||
var total := 0
|
||||
for row in milestones:
|
||||
var ok := true
|
||||
for req in row.get("requires", []):
|
||||
if int(counters.get(String(req.get("key", "")), 0)) < int(req.get("threshold", 0)):
|
||||
ok = false
|
||||
break
|
||||
if ok:
|
||||
total += maxi(0, int(row.get("grant", 0)))
|
||||
return total
|
||||
|
||||
|
||||
# 同调位读数唯一口径:Σ达成 grant clamp slot_cap(求值服务/装配覆盖层/运行期上限共读此口径)
|
||||
func slots(counters: Dictionary) -> int:
|
||||
return mini(granted_slots(counters), slot_cap)
|
||||
@@ -0,0 +1 @@
|
||||
uid://tfgsbs87xakg
|
||||
@@ -18,15 +18,39 @@
|
||||
# 真视窄域——effect_kinds 含 mine_reveal 的活行 target 必须 area_3x3(真视一次最多 3×3,禁全图看雷);
|
||||
# board_wide 仅恢复推理原料类——target=board_wide 的活行 effect_kinds 不得含 mine_reveal(现行无此类活行,
|
||||
# 显影载体待 Alpha 重定后落位)。
|
||||
# 同调实施批扩列(迭代 11 第①批 T1,2026-10-03——任务书 v1.1;设计权威 proposal-magic-item-attunement-2026-09-22):
|
||||
# form ∈ {"", "passive", "active_charged"}(空 = 切片期过渡形态行——掉落/停点渠道现行承载,T7 退役;
|
||||
# passive = 装配整局生效;active_charged = 每冒险充能、挖掘期发起);
|
||||
# charges_per_adventure(active_charged ≥1 / passive 恒 0);slot_cost(同调行恒 1——底稿裁决 5,schema 强制);
|
||||
# unlock_requires 谓词行 [{key ∈ AttunementGrowthTable.COUNTER_KEYS, threshold ∈ [1,999]}](空 = 已解锁——
|
||||
# 首批全解锁合法态,底稿 §2.2 用户裁;正式解锁渠道归 元进度 道具工坊柜台);
|
||||
# effective_rounds(前 N 轮限时件轮数——P4 甲表值化;仅 ap_rounds_front 行消费);
|
||||
# charge_n(充能进度阈值 N——仅 ap_charge_safe 行消费)。
|
||||
# 🔴 零裸 flat 结构护栏(任务书 §三 1——机制轴禁无条件属性加项):行键白名单封闭(KEY_WHITELIST 外键 =
|
||||
# 加载致命)+ effect_kinds 封闭枚举只收条件触发/机制修正类 kind——任何「无条件属性加项」类效果不得以
|
||||
# 新 kind 或新键入表(返工红线)。
|
||||
class_name AuxItemTable
|
||||
extends Resource
|
||||
|
||||
@export var rows: Array = [] # Array[Dictionary] 键 item_id
|
||||
|
||||
const DIMENSIONS := ["info", "risk", "action", "plan", "counter"]
|
||||
const EFFECT_KINDS := ["mine_reveal", "reward_preview", "ap_grant"]
|
||||
# 同调批扩 enum(迭代 11 第①批 T1)——新增九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。
|
||||
# cell_removal = 爆破工兵包中立移除格(T7 原位换装时启用——T6 影响评估前置);mine_hit_halve 系固定
|
||||
# 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。
|
||||
const EFFECT_KINDS := ["mine_reveal", "reward_preview", "ap_grant", "venom_rider", "flag_burst",
|
||||
"mine_hit_halve", "reflect_damage", "ap_rounds_front", "ap_charge_safe", "cell_removal",
|
||||
"reward_weight_bias", "bonus_refresh"]
|
||||
const TARGETS := ["none", "area_3x3", "board_wide"]
|
||||
const USE_PHASES := ["active_dig"]
|
||||
const FORMS := ["", "passive", "active_charged"]
|
||||
# magnitude 消费面(≥1 校验):ap_grant 与同调 N 值 kind;其余 kind 活行 magnitude 恒 0
|
||||
const MAGNITUDE_KINDS := ["ap_grant", "venom_rider", "flag_burst", "reflect_damage", "ap_rounds_front",
|
||||
"ap_charge_safe", "reward_weight_bias", "bonus_refresh"]
|
||||
# 🔴 零裸 flat 结构护栏:行键白名单封闭(键出域=加载致命)——机制轴禁无条件属性加项的表结构承载
|
||||
const KEY_WHITELIST := ["item_id", "display_name", "dimension_tags", "effect_kinds", "target",
|
||||
"magnitude", "use_phase", "retired", "deferred", "form", "charges_per_adventure", "slot_cost",
|
||||
"unlock_requires", "effective_rounds", "charge_n"]
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
@@ -62,6 +86,13 @@ func validate() -> Array:
|
||||
var phase: String = String(row.get("use_phase", "active_dig"))
|
||||
if not USE_PHASES.has(phase):
|
||||
errs.append({"category": "enum", "message": "%s use_phase 出域 %s: %s" % [iid, str(USE_PHASES), phase]})
|
||||
# 🔴 零裸 flat 结构护栏:键白名单封闭(同调批 T1——机制轴禁无条件属性加项)
|
||||
for k in row.keys():
|
||||
if not KEY_WHITELIST.has(String(k)):
|
||||
errs.append({"category": "zero_flat", "message": "%s 行键出白名单: %s(KEY_WHITELIST 外键禁入)" % [iid, String(k)]})
|
||||
var form: String = String(row.get("form", ""))
|
||||
if not FORMS.has(form):
|
||||
errs.append({"category": "enum", "message": "%s form 出域 %s: %s" % [iid, str(FORMS), form]})
|
||||
if retired or deferred:
|
||||
# 退役/失义行:免 effect_kinds 非空与承重护栏校验(登记面保留,不入投放与 F2)
|
||||
continue
|
||||
@@ -82,17 +113,76 @@ func validate() -> Array:
|
||||
# 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果
|
||||
if target == "board_wide" and kind_seen.has("mine_reveal"):
|
||||
errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 mine_reveal(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid})
|
||||
# magnitude:仅 ap_grant 行消费(≥1);非 ap_grant 活行恒 0
|
||||
# magnitude:MAGNITUDE_KINDS 行消费(≥1);其余活行恒 0(同调批 T1——消费面自 ap_grant 扩至 N 值 kind)
|
||||
var mag: int = int(row.get("magnitude", 0))
|
||||
if mag < 0 or mag > 999:
|
||||
errs.append({"category": "domain", "message": "%s magnitude 越域 [0,999]: %d" % [iid, mag]})
|
||||
if kind_seen.has("ap_grant") and mag < 1:
|
||||
errs.append({"category": "cross_field", "message": "%s ap_grant 行 magnitude 应 ≥1,实得 %d" % [iid, mag]})
|
||||
if not kind_seen.has("ap_grant") and mag != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s 非 ap_grant 活行 magnitude 应 0,实得 %d" % [iid, mag]})
|
||||
var mag_consuming := false
|
||||
for k in kind_seen.keys():
|
||||
if MAGNITUDE_KINDS.has(String(k)):
|
||||
mag_consuming = true
|
||||
if mag_consuming and mag < 1:
|
||||
errs.append({"category": "cross_field", "message": "%s N 值 kind 行 magnitude 应 ≥1,实得 %d" % [iid, mag]})
|
||||
if not mag_consuming and mag != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s 非 N 值 kind 活行 magnitude 应 0,实得 %d" % [iid, mag]})
|
||||
# ---- 同调行约束(form 非空——装配面;过渡行 form="" 不校验)----
|
||||
if form != "":
|
||||
if int(row.get("slot_cost", 1)) != 1:
|
||||
errs.append({"category": "load_bearing", "message": "%s 同调占位统一 1 槽(slot_cost 恒 1——底稿裁决 5,schema 强制)" % iid})
|
||||
var charges: int = int(row.get("charges_per_adventure", 0))
|
||||
if form == "passive" and charges != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s passive 行 charges_per_adventure 应 0,实得 %d" % [iid, charges]})
|
||||
if form == "active_charged" and charges < 1:
|
||||
errs.append({"category": "cross_field", "message": "%s active_charged 行 charges_per_adventure 应 ≥1,实得 %d" % [iid, charges]})
|
||||
var eff_rounds: int = int(row.get("effective_rounds", 0))
|
||||
if eff_rounds < 0 or eff_rounds > 999:
|
||||
errs.append({"category": "domain", "message": "%s effective_rounds 越域 [0,999]: %d" % [iid, eff_rounds]})
|
||||
if kind_seen.has("ap_rounds_front") and eff_rounds < 1:
|
||||
errs.append({"category": "cross_field", "message": "%s ap_rounds_front 行 effective_rounds 应 ≥1(P4 甲表值化),实得 %d" % [iid, eff_rounds]})
|
||||
if not kind_seen.has("ap_rounds_front") and eff_rounds != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s 非 ap_rounds_front 行 effective_rounds 应 0,实得 %d" % [iid, eff_rounds]})
|
||||
var charge_n: int = int(row.get("charge_n", 0))
|
||||
if charge_n < 0 or charge_n > 999:
|
||||
errs.append({"category": "domain", "message": "%s charge_n 越域 [0,999]: %d" % [iid, charge_n]})
|
||||
if kind_seen.has("ap_charge_safe") and charge_n < 1:
|
||||
errs.append({"category": "cross_field", "message": "%s ap_charge_safe 行 charge_n 应 ≥1(每次充能需 N 安全格),实得 %d" % [iid, charge_n]})
|
||||
if not kind_seen.has("ap_charge_safe") and charge_n != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s 非 ap_charge_safe 行 charge_n 应 0,实得 %d" % [iid, charge_n]})
|
||||
# unlock_requires 谓词行:空 = 已解锁(首批全解锁合法态,底稿 §2.2);非空键 ∈ 计数键封闭枚举
|
||||
var ureqs: Array = row.get("unlock_requires", [])
|
||||
var ukeys := {}
|
||||
for req in ureqs:
|
||||
var ukey: String = String(req.get("key", ""))
|
||||
if not AttunementGrowthTable.COUNTER_KEYS.has(ukey):
|
||||
errs.append({"category": "enum", "message": "%s unlock_requires 计数键出域 %s: %s" % [iid, str(AttunementGrowthTable.COUNTER_KEYS), ukey]})
|
||||
if ukeys.has(ukey):
|
||||
errs.append({"category": "dup_key", "message": "%s unlock_requires 计数键重复: %s" % [iid, ukey]})
|
||||
ukeys[ukey] = true
|
||||
var uth: int = int(req.get("threshold", 0))
|
||||
if uth < 1 or uth > 999:
|
||||
errs.append({"category": "domain", "message": "%s unlock_requires 阈值越域 [1,999]: %d" % [iid, uth]})
|
||||
return errs
|
||||
|
||||
|
||||
# 同调行词表(form 非空)——装配覆盖层/效果接线/同调位上限的唯一取数口径(迭代 11 第①批 T1)
|
||||
func attunement_rows() -> Array:
|
||||
var out: Array = []
|
||||
for row in rows:
|
||||
if String(row.get("form", "")) != "" and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)):
|
||||
out.append(row)
|
||||
return out
|
||||
|
||||
|
||||
# 过渡行词表(form 空 = 切片期过渡形态活行)——掉落投放/停点池/过渡覆盖面的取数口径;
|
||||
# 同调行永不入过渡渠道。T7 退役面切换后本口径随渠道消亡。
|
||||
func transitional_rows() -> Array:
|
||||
var out: Array = []
|
||||
for row in rows:
|
||||
if String(row.get("form", "")) == "" and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)):
|
||||
out.append(row)
|
||||
return out
|
||||
|
||||
|
||||
# 活行词表(非 retired 非 deferred)——投放校验/奖励节点池/F2 覆盖面的唯一取数口径
|
||||
func active_rows() -> Array:
|
||||
var out: Array = []
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
# 达标 clear_threshold——2026-09-20 排期裁决;局内效果整体归 Alpha 魔法道具重设计批,本表只有解锁状态面)。
|
||||
# conversion = 区间平移换算率行(attr 与 forge 词表一致恰三;per_level_shift_pct ∈ [0,100]——
|
||||
# registry 键 meta_progression_conversion_table;护甲行强条目:验收读数必须按解锁后参数重测)。
|
||||
# attune_refresh_upgrade = Y 刷新升级行族(迭代 11 第①批 T4——P1 甲:每冒险开局给 Y 次、冒险周期池、
|
||||
# 用完即无;level 连续从 1,等级 L → refresh_charges=Y 表值,钥石直购 keystone_cost;数值全 provisional)。
|
||||
# 行值全部 provisional 归 元进度设计批配读数(用户拍板骨架先行,先例 = GP+商店房批)。
|
||||
class_name MetaTable
|
||||
extends Resource
|
||||
@@ -20,6 +22,7 @@ extends Resource
|
||||
@export var boss_keystone: Array[Dictionary] = [] # Array[Dictionary] 键 level_index
|
||||
@export var workshop_items: Array[Dictionary] = [] # Array[Dictionary] 键 item_id
|
||||
@export var conversion: Array[Dictionary] = [] # Array[Dictionary] 键 attr
|
||||
@export var attune_refresh_upgrade: Array[Dictionary] = [] # Array[Dictionary] 键 level——Y 刷新升级行族(迭代 11 第①批 T4)
|
||||
|
||||
const FORGE_ATTRS := ["max_hp", "atk", "armor_class"]
|
||||
const WORKSHOP_ITEM_IDS := ["probe_dust", "sapper_order", "loot_compass", "nest_pendulum", "catacomb_scroll", "blast_kit"]
|
||||
@@ -31,8 +34,8 @@ const WORKSHOP_CHANNELS := ["total_clears"]
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array[Dictionary] = []
|
||||
# 行族空护栏(四族皆为 ConfigDB 消费面——缺族即致命)
|
||||
for family in ["forge_products", "boss_keystone", "workshop_items", "conversion"]:
|
||||
# 行族空护栏(五族皆为 ConfigDB 消费面——缺族即致命)
|
||||
for family in ["forge_products", "boss_keystone", "workshop_items", "conversion", "attune_refresh_upgrade"]:
|
||||
if get(family).is_empty():
|
||||
errs.append({"category": "empty_table", "message": "MetaTable 行族为空: %s" % family})
|
||||
# forge_products:attr 词表封闭 + 唯一 + 覆盖恰三(注入契约三字段必齐)+ flat/价格域 + 公比域 [100,400]
|
||||
@@ -115,4 +118,22 @@ func validate() -> Array:
|
||||
for conv_key in FORGE_ATTRS:
|
||||
if not seen_conv.has(conv_key):
|
||||
errs.append({"category": "coverage", "message": "conversion 缺属性行: %s(三行与 forge 词表一致)" % conv_key})
|
||||
# attune_refresh_upgrade:level 唯一 + 连续从 1 + charges/cost 域(迭代 11 第①批 T4)
|
||||
var seen_al := {}
|
||||
for row in attune_refresh_upgrade:
|
||||
var al: int = int(row.get("level", -1))
|
||||
if seen_al.has(al):
|
||||
errs.append({"category": "dup_key", "message": "attune_refresh_upgrade level 重复: %d" % al})
|
||||
seen_al[al] = true
|
||||
var ach: int = int(row.get("refresh_charges", -1))
|
||||
if ach < 1 or ach > 9:
|
||||
errs.append({"category": "domain", "message": "attune_refresh_upgrade L%d refresh_charges 越域 [1,9]: %d" % [al, ach]})
|
||||
var acost: int = int(row.get("keystone_cost", -1))
|
||||
if acost < 1 or acost > 999:
|
||||
errs.append({"category": "domain", "message": "attune_refresh_upgrade L%d keystone_cost 越域 [1,999]: %d" % [al, acost]})
|
||||
for i in attune_refresh_upgrade.size():
|
||||
var al_at: int = int(attune_refresh_upgrade[i].get("level", 0))
|
||||
if al_at != i + 1:
|
||||
errs.append({"category": "structural", "message": "attune_refresh_upgrade level 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, al_at]})
|
||||
break
|
||||
return errs
|
||||
@@ -10,24 +10,24 @@ bonus_max_hp_flat = 5
|
||||
bonus_armor_flat = 1
|
||||
bonus_gp_amount = 20
|
||||
bonus_ap_flat = 1
|
||||
bonus_aux_item_count = 1
|
||||
bonus_weight_attack = 3
|
||||
bonus_weight_max_hp = 3
|
||||
bonus_weight_armor = 3
|
||||
bonus_weight_gp = 3
|
||||
bonus_weight_aux = 1
|
||||
bonus_weight_ap = 1
|
||||
bonus_cap_attack = 3
|
||||
bonus_cap_max_hp = 3
|
||||
bonus_cap_armor = 3
|
||||
bonus_cap_ap = 2
|
||||
transitional_sync_slots = 1
|
||||
|
||||
; 迭代 10 奖励重构批(2026-10-01 扩列——registry adventure_table 条目同批改写):
|
||||
; 大奖励 = 非末关通关恰一次:部分回血(clear_heal_pct,封顶上限不回满、满血回 0 合法)
|
||||
; + 提升三选一(池六种加权洗牌不放回 E-S weight-key 掷 3,玩家点选兑付恰一件;消费 reward_pick 封闭流)。
|
||||
; 权重:属性/GP 各 3、道具/AP 各 1;次数上限:属性件各 3、AP 件 2(达上限件先剔牌库)——gp/道具无次数上限。
|
||||
; 同调位过渡键 transitional_sync_slots=1(道具持有上限;正主 = attunement_growth.tres 谓词表,同调实施批切换)。
|
||||
; 权重:属性/GP 各 3、AP 1;次数上限:属性件各 3、AP 件 2(达上限件先剔牌库)——gp 无次数上限。
|
||||
; 迭代 11 第①批 同调实施批 T7(2026-10-03):aux_item 池种退役出三选一牌库(bonus_weight_aux/
|
||||
; bonus_aux_item_count 两字段随批退役);transitional_sync_slots 过渡键退役(正主 = attunement_growth.tres
|
||||
; 谓词表求值,Attunement.slots——迭代 10 欠账③清偿)。
|
||||
; 末关通关不发三选一与回血(奖励只朝下一战生效)。
|
||||
; 退役字段:level_clear_hp_bonus(血回满+上限提升件)、keystone_per_level(钥石改 Boss/精英击杀掉落,行值归 meta.tres boss_keystone)。
|
||||
; 退役字段:level_clear_hp_bonus(血回满+上限提升件)、keystone_per_level(钥石改 Boss/精英击杀掉落,行值归 meta.tres boss_keystone)、
|
||||
; transitional_sync_slots / bonus_weight_aux / bonus_aux_item_count(本批 T7 退役三件)。
|
||||
; 全部 provisional-pending-曲线调参批(值锚与上调约束归 难度曲线与Boss;回血 20% 系难度上压方向,带重扫随批呈报)。
|
||||
@@ -0,0 +1,34 @@
|
||||
[gd_resource type="Resource" script_class="AttunementGrowthTable" load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://data/schemas/attunement_growth_table.gd" id="1"]
|
||||
|
||||
; 迭代 11 第①批 同调实施批 T1(2026-10-03)——同调位里程碑谓词表。
|
||||
; 数值全 provisional 归 难度曲线与Boss(任务书 §三 7);行形态 = 底稿 §2.1 示意形态。
|
||||
[resource]
|
||||
script = ExtResource("1")
|
||||
slot_cap = 3
|
||||
milestones = [{
|
||||
"id": "m1",
|
||||
"grant": 1,
|
||||
"requires": [{
|
||||
"key": "clear_count",
|
||||
"threshold": 1
|
||||
}]
|
||||
}, {
|
||||
"id": "m2",
|
||||
"grant": 1,
|
||||
"requires": [{
|
||||
"key": "boss_kill_count",
|
||||
"threshold": 3
|
||||
}]
|
||||
}, {
|
||||
"id": "m3",
|
||||
"grant": 1,
|
||||
"requires": [{
|
||||
"key": "clear_count",
|
||||
"threshold": 3
|
||||
}, {
|
||||
"key": "boss_kill_count",
|
||||
"threshold": 6
|
||||
}]
|
||||
}]
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1")
|
||||
; 迭代 11 第①批 T1(2026-10-03):追加七件同调行(form 非空——永不入过渡渠道);值全 provisional 归 难度曲线与Boss。
|
||||
; nest_pendulum/blast_kit 维持过渡行,T7 渠道退役时原位换装 form=active_charged;sapper_order/显影尘/地穴全图卷/罗盘 T7 逐件销账。
|
||||
rows = [{
|
||||
"item_id": "probe_dust",
|
||||
"display_name": "显影尘",
|
||||
@@ -20,7 +22,8 @@ rows = [{
|
||||
"effect_kinds": ["ap_grant"],
|
||||
"target": "none",
|
||||
"magnitude": 2,
|
||||
"use_phase": "active_dig"
|
||||
"use_phase": "active_dig",
|
||||
"retired": true
|
||||
}, {
|
||||
"item_id": "loot_compass",
|
||||
"display_name": "探宝罗盘",
|
||||
@@ -37,7 +40,10 @@ rows = [{
|
||||
"effect_kinds": ["mine_reveal"],
|
||||
"target": "area_3x3",
|
||||
"magnitude": 0,
|
||||
"use_phase": "active_dig"
|
||||
"use_phase": "active_dig",
|
||||
"form": "active_charged",
|
||||
"slot_cost": 1,
|
||||
"charges_per_adventure": 2
|
||||
}, {
|
||||
"item_id": "catacomb_scroll",
|
||||
"display_name": "地穴全图卷",
|
||||
@@ -54,5 +60,79 @@ rows = [{
|
||||
"effect_kinds": ["ap_grant", "mine_reveal"],
|
||||
"target": "area_3x3",
|
||||
"magnitude": 4,
|
||||
"use_phase": "active_dig"
|
||||
"use_phase": "active_dig",
|
||||
"deferred": true
|
||||
}, {
|
||||
"item_id": "venom_edge",
|
||||
"display_name": "淬毒刃纹",
|
||||
"dimension_tags": ["counter"],
|
||||
"effect_kinds": ["venom_rider"],
|
||||
"target": "none",
|
||||
"magnitude": 2,
|
||||
"use_phase": "active_dig",
|
||||
"form": "passive",
|
||||
"slot_cost": 1
|
||||
}, {
|
||||
"item_id": "flag_burst",
|
||||
"display_name": "标中殉爆",
|
||||
"dimension_tags": ["action"],
|
||||
"effect_kinds": ["flag_burst"],
|
||||
"target": "none",
|
||||
"magnitude": 2,
|
||||
"use_phase": "active_dig",
|
||||
"form": "passive",
|
||||
"slot_cost": 1
|
||||
}, {
|
||||
"item_id": "nest_counter",
|
||||
"display_name": "惊巢反制",
|
||||
"dimension_tags": ["risk"],
|
||||
"effect_kinds": ["mine_hit_halve", "reflect_damage"],
|
||||
"target": "none",
|
||||
"magnitude": 2,
|
||||
"use_phase": "active_dig",
|
||||
"form": "passive",
|
||||
"slot_cost": 1
|
||||
}, {
|
||||
"item_id": "dawn_order",
|
||||
"display_name": "工兵晨令",
|
||||
"dimension_tags": ["action"],
|
||||
"effect_kinds": ["ap_rounds_front"],
|
||||
"target": "none",
|
||||
"magnitude": 1,
|
||||
"use_phase": "active_dig",
|
||||
"form": "passive",
|
||||
"slot_cost": 1,
|
||||
"effective_rounds": 3
|
||||
}, {
|
||||
"item_id": "dig_charge",
|
||||
"display_name": "掘进蓄能",
|
||||
"dimension_tags": ["action"],
|
||||
"effect_kinds": ["ap_charge_safe"],
|
||||
"target": "none",
|
||||
"magnitude": 1,
|
||||
"use_phase": "active_dig",
|
||||
"form": "active_charged",
|
||||
"slot_cost": 1,
|
||||
"charges_per_adventure": 2,
|
||||
"charge_n": 3
|
||||
}, {
|
||||
"item_id": "luck_coin",
|
||||
"display_name": "偏运硬币",
|
||||
"dimension_tags": ["risk"],
|
||||
"effect_kinds": ["reward_weight_bias"],
|
||||
"target": "none",
|
||||
"magnitude": 2,
|
||||
"use_phase": "active_dig",
|
||||
"form": "passive",
|
||||
"slot_cost": 1
|
||||
}, {
|
||||
"item_id": "pick_refresh",
|
||||
"display_name": "三选一刷新件",
|
||||
"dimension_tags": ["info"],
|
||||
"effect_kinds": ["bonus_refresh"],
|
||||
"target": "none",
|
||||
"magnitude": 1,
|
||||
"use_phase": "active_dig",
|
||||
"form": "passive",
|
||||
"slot_cost": 1
|
||||
}]
|
||||
@@ -77,6 +77,15 @@ conversion = [{
|
||||
"attr": "armor_class",
|
||||
"per_level_shift_pct": 1
|
||||
}]
|
||||
attune_refresh_upgrade = [{
|
||||
"level": 1,
|
||||
"refresh_charges": 1,
|
||||
"keystone_cost": 30
|
||||
}, {
|
||||
"level": 2,
|
||||
"refresh_charges": 2,
|
||||
"keystone_cost": 60
|
||||
}]
|
||||
|
||||
; 元进度实现批(2026-09-21,设计权威 design/gdd/systems/冒险循环/元进度.md 定稿 v1.2):
|
||||
; 数值全 provisional 归元进度设计批配读数(骨架先行——元进度实现批 2026-09-21,先例 = GP+商店房批)。
|
||||
@@ -107,3 +116,7 @@ conversion = [{
|
||||
; 钥石渠道自本批起 =
|
||||
; Boss/精英击杀逐杀掉落(大奖励 keystone_per_level 渠道退役;精英掉 1 预留行随怪物批实装落)。
|
||||
; 产出结构变化 → 元进度标定义务重开(06-待办清单 2026-10-01 登记条)。provisional 归曲线调参批。
|
||||
;
|
||||
; 迭代 11 第①批 同调实施批 T4(2026-10-03):attune_refresh_upgrade 行族 = Y 刷新升级行(任务书 P1 甲——
|
||||
; 每冒险开局给 Y 次、冒险周期池、用完即无;等级 L → Y=L 次刷新,钥石直购)。数值全 provisional 归
|
||||
; 难度曲线与Boss(任务书 §三 7)。
|
||||
Reference in new issue
Block a user