merge: 代拍板八项确认+工坊解锁渠道可替换轴落籍(台账 121)

This commit is contained in:
DKChan committed 2026-09-21 18:10:34 +08:00
commit d8023037d5
5 files changed
+44 -19

No files matched your search

+1 -1
View File
@@ -622,7 +622,7 @@ entities:
row_families: forge_products {attr ∈ {max_hp, atk, armor_class} 恰三, display_name, flat_value, base_price, price_ratio_pct ∈ [100,400]} · boss_keystone {level_index 连续从 1, first_kill ≥ repeat_kill} · workshop_items {item_id ∈ registry aux_items 六件词表恰全, display_name, clear_threshold ∈ [1,99]} · conversion {attr 与 forge 词表一致恰三, per_level_shift_pct ∈ [0,100]}
provisional: 数值全 provisional 归元进度设计批配读数(骨架先行先例 = GP+商店房批)——现行落表值:flat 血+3/攻+1/甲+1、base 10 ratio 150 三行同;Boss 两档 L1 5/1 · L2 8/2 · L3 12/3;工坊阈值 1/1/2/2/3/3(按总通关次数);换算率全 0 占位
impl: core/meta_progression.gd(MetaProgression 账本服务——余额/几何定价〔tier 级价格 = 迭代 floor(p × ratio/100)〕/购买/工坊解锁〔总通关次数渠道〕/settle_adventure Boss 两档入账/hero_override 注入计算;Core 层零 UI 零信号)
workshop_unlock_rule: 首版只挂总通关次数渠道(Σ level_clear_counts 达阈值——2026-09-21 实现批代拍板 2,GDD 未细分);钥石直购价随定价批后补
workshop_unlock_rule: 首版只挂总通关次数渠道(Σ level_clear_counts 达阈值——2026-09-21 实现批代拍板 2 并经用户确认,GDD 未细分);**channel 可替换轴**(同日用户拍板:解锁条件须抽象、可替换、可扩展——渠道由 workshop_items.channel 字段声明〔缺省 total_clears,词表 MetaTable.WORKSHOP_CHANNELS 封闭〕,判定量换算单点 = MetaProgression._workshop_progress,换/加渠道 = 词表加值 + 一 match 分支,阈值比较与解锁写档零改动;未知渠道恒 0 = 永不解锁 fail-safe;候选 adventure_depth 最高通关深度 / keystone 直购双渠道已预留语义未实现);钥石直购价随定价批后补
referenced_by: [元进度, 存档序列化, 数据配置]
# 2026-09-09 奖励道具经济 full 评审修订批(owner=奖励道具经济 代用户修订,NEEDS REVISION 14 blocking 同日核销):
@@ -4,8 +4,9 @@
# Date: 2026-09-21(元进度实现批——设计权威 design/gdd/systems/冒险循环/元进度.md 定稿 v1.2)
# 元进度账本服务(Core 层零 UI、纯被动服务——同 StatusContainer 先例:零信号零外发,读存档算账)。
# 职责三件:① 属性锻造定价与购买(几何递增——tier 级价格 = 迭代 floor(p × ratio/100),tier 0 =
# base_price,floor 单一取整对齐 round_direction 纪律);② 道具工坊解锁(首版只挂总通关次数渠道——
# Σ level_clear_counts 达标,代拍板 2;六件局内效果归 Alpha 魔法道具重设计批,本类只有解锁状态);
# base_price,floor 单一取整对齐 round_direction 纪律);② 道具工坊解锁(渠道由 meta.tres channel
# 字段声明、判定量换算单点 _workshop_progress——2026-09-21 用户拍板可替换轴;首版 = 总通关次数,
# 钥石直购价随定价批后补最终双渠道;六件局内效果归 Alpha 魔法道具重设计批,本类只有解锁状态);
# ③ 冒险收束入账(Boss 两档 = 表值 first_kill/repeat_kill,首杀标记读存档判first;调 SaveManager
# apply_adventure_summary 入账并附 boss_drops 副本——复盘可归因,验收 5)。
# 注入面:hero_override() = 三档 forge flat(全零 = 白板合法态;override 不写表——表运行期只读,
@@ -64,17 +65,24 @@ func buy_forge(attr: String) -> bool:
# ---- 道具工坊(首版全走通关次数渠道——钥石直购价随定价批后补,最终双渠道并存)----
# 总通关次数 = Σ level_clear_counts(工坊解锁判定量——代拍板 2)
func _total_clears() -> int:
var total := 0
for i in db.level.rows.size():
total += save.clear_count(i + 1)
return total
# 解锁判定量单点(可替换轴——2026-09-21 用户拍板:解锁条件须抽象、可替换、可扩展,禁与渠道实现耦合)。
# 契约:渠道由 meta.tres workshop_items.channel 声明(缺省 total_clears,词表 MetaTable.WORKSHOP_CHANNELS
# 封闭);本方法是渠道 → 判定数值的唯一换算点——换/加渠道 = 词表加值 + 此处增一 match 分支,
# 阈值比较(refresh/workshop_status)与解锁写档零改动。候选渠道(语义已预留未实现):
# adventure_depth 最高通关深度 / keystone 钥石直购双渠道。
func _workshop_progress(channel: String) -> int:
match channel:
"total_clears":
var total := 0
for i in db.level.rows.size():
total += save.clear_count(i + 1)
return total
_:
return 0 # 未知渠道恒 0 = 永不解锁(fail-safe 非致命——渠道词表校验兜底,不静默误解锁)
# 工坊六行只读投影(呈现层数据源):{item_id, display_name, threshold, unlocked, progress}
func workshop_status() -> Array:
var total := _total_clears()
var out: Array = []
for row in db.meta_workshop_items():
var iid := String(row.get("item_id", ""))
@@ -83,7 +91,7 @@ func workshop_status() -> Array:
"display_name": String(row.get("display_name", "")),
"threshold": int(row.get("clear_threshold", 0)),
"unlocked": save.item_unlocked(iid),
"progress": total,
"progress": _workshop_progress(String(row.get("channel", "total_clears"))),
})
return out
@@ -91,12 +99,12 @@ func workshop_status() -> Array:
# 达标未解锁 → unlock_item + 写盘;返回新解锁 item_id 列(冒险收束后与营地打开时各调一次)
func refresh_workshop_unlocks() -> Array:
var new_unlocks: Array = []
var total := _total_clears()
for row in db.meta_workshop_items():
var iid := String(row.get("item_id", ""))
if save.item_unlocked(iid):
continue
if total >= int(row.get("clear_threshold", 99)):
var progress := _workshop_progress(String(row.get("channel", "total_clears")))
if progress >= int(row.get("clear_threshold", 99)):
save.unlock_item(iid)
new_unlocks.append(iid)
if not new_unlocks.is_empty():
@@ -23,6 +23,10 @@ extends Resource
const FORGE_ATTRS := ["max_hp", "atk", "armor_class"]
const WORKSHOP_ITEM_IDS := ["probe_dust", "sapper_order", "loot_compass", "nest_pendulum", "catacomb_scroll", "blast_kit"]
# 工坊解锁渠道词表(可替换轴——2026-09-21 用户拍板:解锁条件须抽象、可替换、可扩展。
# 现行唯一合法值 total_clears = 总通关次数;扩新渠道 = 词表加值 + MetaProgression._workshop_progress
# 增一分支,阈值比较与解锁写档零改动。缺省(行无 channel 字段)= total_clears)
const WORKSHOP_CHANNELS := ["total_clears"]
func validate() -> Array:
@@ -87,6 +91,10 @@ func validate() -> Array:
var th: int = int(row.get("clear_threshold", -1))
if th < 1 or th > 99:
errs.append({"category": "domain", "message": "workshop_items %s clear_threshold 越域 [1,99]: %d" % [iid, th]})
# channel:可替换解锁渠道(缺省 total_clears——词表封闭,扩渠道 = 词表加值 + 判定量分支)
var channel: String = row.get("channel", "total_clears")
if not WORKSHOP_CHANNELS.has(channel):
errs.append({"category": "enum", "message": "workshop_items %s channel 出域 %s: %s" % [iid, str(WORKSHOP_CHANNELS), channel]})
if not workshop_items.is_empty():
for iid_key in WORKSHOP_ITEM_IDS:
if not seen_item.has(iid_key):
@@ -39,27 +39,33 @@ boss_keystone = [{
workshop_items = [{
"item_id": "probe_dust",
"display_name": "显影尘",
"clear_threshold": 1
"clear_threshold": 1,
"channel": "total_clears"
}, {
"item_id": "sapper_order",
"display_name": "工兵令",
"clear_threshold": 1
"clear_threshold": 1,
"channel": "total_clears"
}, {
"item_id": "loot_compass",
"display_name": "探宝罗盘",
"clear_threshold": 2
"clear_threshold": 2,
"channel": "total_clears"
}, {
"item_id": "nest_pendulum",
"display_name": "探巢摆钟",
"clear_threshold": 2
"clear_threshold": 2,
"channel": "total_clears"
}, {
"item_id": "catacomb_scroll",
"display_name": "地穴全图卷",
"clear_threshold": 3
"clear_threshold": 3,
"channel": "total_clears"
}, {
"item_id": "blast_kit",
"display_name": "爆破工兵包",
"clear_threshold": 3
"clear_threshold": 3,
"channel": "total_clears"
}]
conversion = [{
"attr": "max_hp",
@@ -3231,6 +3231,9 @@ func _meta_settle_and_workshop() -> void:
got_n += 1 if bool(st_row.get("unlocked", false)) else 0
check(got_n == expect_n and mp.refresh_workshop_unlocks().is_empty(),
"工坊解锁数 = 总通关 %d 次达阈值件数(%d 件)且重复 refresh 幂等" % [total_clears, expect_n])
# 渠道可替换轴(2026-09-21 用户拍板):判定量单点正控 + 未知渠道 fail-safe(恒 0 = 永不解锁,非致命)
check(mp._workshop_progress("total_clears") == total_clears and mp._workshop_progress("adventure_depth") == 0,
"解锁判定量单点:total_clears 正控 + 未知渠道恒 0(channel 可替换轴 fail-safe)")
var sv_r = _meta_new_save(_META_SMOKE_PATHS[2])
var r_n := 0
for st_row in load("res://core/meta_progression.gd").new(_db, sv_r).workshop_status():