迭代11第②批:GP商店房重构——三选一同构化(P1共享池账本+抽3买1全重抽+A/b乘法定价ceil+断点扩键+货架同构呈现+MC off/on分层;冒烟671/0+off对拍off_n60逐位PASS+探针三件绿)
This commit is contained in:
1 parent
bc17b66c00
commit
d79afd2241
18 files changed
+557
-45
No files matched your search
+122
-1
@@ -67,6 +67,12 @@ var _aux_unlocked := {} # aux 解锁门控集(迭代 7
|
||||
var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——adventure params.attunement 下传,begin_battle enc 携带进战斗结算;空集=off 零扰动)
|
||||
var _attune_charges: Dictionary = {} # 同调主动件充能账本(迭代 11 第①批 T6——adventure 共享 dict 引用;settlement use_aux 扣减直改同引用)
|
||||
# 关卡末清空+快照计数入 level_finished 载荷)
|
||||
# ---- 商店共享池模式态(迭代 11 第②批 T3——缺省 legacy=固定三件加定价 off 对照承载,零 RNG 零池消费)----
|
||||
var _shop_pool_mode := false # pool 模式旗(set_shop_pool 注入时置位——AdventureRunner 按 params.shop_mode 下传)
|
||||
var _pool_taken: Dictionary = {} # 共享池库存账本共享引用(AdventureRunner._bonus_taken——stock=cap−taken 单点)
|
||||
var _pool_consume := Callable() # 池消费 handler(AdventureRunner._consume_pool_purchase——_apply_bonus_pick 同口写加算区+账本)
|
||||
var _shop_shelf: Array[String] = [] # 当前货架(进店抽 3/买后全重抽——kind_id 序)
|
||||
var _shop_visit_buys := 0 # 本次进店已购次数(A 链定价输入——离开清零)
|
||||
|
||||
var hero_atk_pct := 0 # 测试面板覆盖值(切片专用)
|
||||
var hero_hp_pct := 0
|
||||
@@ -441,7 +447,11 @@ func _enter_node(node: Dictionary) -> bool:
|
||||
"shop":
|
||||
# 商店房兑付(GP+商店房实施批 2026-09-21):到达即开店(覆盖层归呈现层),购买出账/
|
||||
# 离开归玩家意图——零自动推进;离开确认经 continue_after_node 回选路口
|
||||
node_entered.emit(node, {"gp": gp})
|
||||
if _shop_pool_mode:
|
||||
_shop_open_pool() # 迭代 11 第②批 T3——进店抽 3(恰一 shop_draw scope;买后全重抽同签)
|
||||
node_entered.emit(node, {"gp": gp, "shelf": true})
|
||||
return true
|
||||
node_entered.emit(node, {"gp": gp}) # legacy 固定三件(off 对照承载——零 RNG 零池消费)
|
||||
return true
|
||||
push_error("[关卡节点地图] 未知节点类型: %s" % str(node))
|
||||
return false
|
||||
@@ -615,6 +625,9 @@ func continue_after_node() -> bool:
|
||||
var t := String(current_node().get("type", ""))
|
||||
if t != "reward" and t != "rest" and t != "shop":
|
||||
return false
|
||||
if t == "shop":
|
||||
_shop_shelf = [] # 离开店面货架态清零(断点快照 shop_shelf 键随离开落空架合法态——迭代 11 第②批 T2)
|
||||
_shop_visit_buys = 0
|
||||
return _present_choices()
|
||||
|
||||
|
||||
@@ -689,3 +702,111 @@ func player_request_refresh() -> bool:
|
||||
if _settlement == null:
|
||||
return false
|
||||
return _settlement.player_request_refresh()
|
||||
|
||||
|
||||
# ---- 商店共享池模式(迭代 11 第②批 T3——P1 共享池/P4 ceil;legacy 固定三件路径上方原样保留为 off 对照承载)----
|
||||
|
||||
# 注入(AdventureRunner._start_current_level 唯一调用方——pool 模式专用):库存账本共享引用 +
|
||||
# 池消费 handler。legacy 模式不注入(_shop_pool_mode 恒 false——off 态零 RNG 零池消费零扰动)。
|
||||
func set_shop_pool(taken_ref: Dictionary, consume_handler: Callable) -> void:
|
||||
_pool_taken = taken_ref
|
||||
_pool_consume = consume_handler
|
||||
_shop_pool_mode = true
|
||||
|
||||
|
||||
# 进店开店(_enter_node shop 分支 pool 模式):进店购买次计数清零 + 抽 3 落架(恰一 shop_draw scope)
|
||||
func _shop_open_pool() -> void:
|
||||
_shop_visit_buys = 0
|
||||
_shop_draw_shelf()
|
||||
|
||||
|
||||
# 货架抽签(进店 + 每次买后全重抽共用):牌库 = 货架词表四种中库存 >0 者(库存=上限即库存——
|
||||
# 与奖励三选一达上限剔牌同一账本承载);E-S weight-key 加权洗牌不放回取 3(数学同奖励洗牌族,
|
||||
# 自包含实现防奖励侧 RNG 序漂移);消费 shop_draw 封闭流恰一 scope(每次抽 3 恰一取号)。牌库空
|
||||
# = 空货架合法态(池空硬闸——买光即枯竭既定后果)。
|
||||
func _shop_draw_shelf() -> void:
|
||||
_shop_shelf = []
|
||||
var deck: Array = []
|
||||
for row in db.shop_pool_rows():
|
||||
var kind := String(row.get("kind_id", ""))
|
||||
if pool_stock(kind) > 0:
|
||||
deck.append(kind)
|
||||
if deck.is_empty():
|
||||
return
|
||||
var stream: RandomNumberGenerator = rng.open_stream("shop_draw")
|
||||
var keyed: Array = []
|
||||
for kind in deck:
|
||||
var w := float(maxi(1, int(db.adventure.bonus_weight(kind))))
|
||||
keyed.append({"id": kind, "key": pow(stream.randf(), 1.0 / w)})
|
||||
keyed.sort_custom(func(a, b): return float(a["key"]) > float(b["key"]))
|
||||
for i in mini(3, keyed.size()):
|
||||
_shop_shelf.append(String(keyed[i]["id"]))
|
||||
|
||||
|
||||
# 库存余量(账本单点读——gp 无上限种不入货架,防御读返回大数)
|
||||
func pool_stock(kind: String) -> int:
|
||||
var cap := int(db.adventure.bonus_cap(kind))
|
||||
if cap == db.adventure.BONUS_CAP_UNLIMITED:
|
||||
return 1 << 30
|
||||
return cap - int(_pool_taken.get(kind, 0))
|
||||
|
||||
|
||||
# 现价 = ceil(基价 × b^(关序−1) × A^(本次进店已购次数))(P4 甲 ceil 向上单一取整——玩家不利向;
|
||||
# A/b 表 knob provisional;核心现算,呈现层禁复算——契约 5)
|
||||
func pool_price(kind: String) -> int:
|
||||
var row: Dictionary = db.shop_pool_row(kind)
|
||||
var base := float(maxi(1, int(row.get("base_price", 1))))
|
||||
var price_f: float = base * pow(db.shop_price_b(), float(maxi(0, int(level_row.level_index) - 1))) \
|
||||
* pow(db.shop_price_a(), float(_shop_visit_buys))
|
||||
return int(ceil(price_f))
|
||||
|
||||
|
||||
# 货架只读投影(呈现层数据源——kind/显示名/件值/现价/库存余量齐备,UI 零复算)。
|
||||
# 件值=奖励件本体值(db.adventure.bonus_value——池件与三选一件同一本体,买一件=奖励面少一件)。
|
||||
func shop_shelf() -> Array:
|
||||
var out: Array[Dictionary] = []
|
||||
for kind in _shop_shelf:
|
||||
var row: Dictionary = db.shop_pool_row(kind)
|
||||
out.append({
|
||||
"kind_id": kind,
|
||||
"display_name": String(row.get("display_name", kind)),
|
||||
"value": int(db.adventure.bonus_value(kind)),
|
||||
"price": pool_price(kind),
|
||||
"stock_left": pool_stock(kind),
|
||||
})
|
||||
return out
|
||||
|
||||
|
||||
# 购买(pool 模式唯一购买口):在架/余额前置校验零副作用 → handler 消费池库存(_apply_bonus_pick
|
||||
# 同口写加算区+账本——跨渠道共账)→ 出账 → 进店购买次计数 → wallet 事件 → 三件全重抽(未买
|
||||
# 不保留——重抽绑购买,无独立刷新动作)
|
||||
func buy_pool_item(kind: String) -> bool:
|
||||
if not _shop_pool_mode or not _shop_shelf.has(kind):
|
||||
push_error("[关卡节点地图] 商店购买拒绝——非池模式或件不在架: %s" % kind)
|
||||
return false
|
||||
var price := pool_price(kind)
|
||||
if gp < price:
|
||||
push_warning("[关卡节点地图] 购买拒绝——余额不足: %s(需 %d,钱包 %d)" % [kind, price, gp])
|
||||
return false
|
||||
if _pool_consume.is_null() or not bool(_pool_consume.call(kind)):
|
||||
push_error("[关卡节点地图] 购买拒绝——池库存消费失败: %s" % kind)
|
||||
return false
|
||||
gp -= price
|
||||
_shop_visit_buys += 1
|
||||
wallet_changed.emit("buy", gp, {"product": kind, "price": price})
|
||||
_shop_draw_shelf() # 买 1 → 三件全重抽(恰一 shop_draw scope——同进店取号签)
|
||||
return true
|
||||
|
||||
|
||||
# 池模式谓词(呈现层组合根分发用——货架面 vs legacy 商品面)
|
||||
func is_shop_pool() -> bool:
|
||||
return _shop_pool_mode
|
||||
|
||||
|
||||
# 断点快照读面(P2 甲货架+账本入断点——AdventureRunner._snapshot_breakpoint 消费;离开店即空架)
|
||||
func shop_bp_shelf() -> Array:
|
||||
return _shop_shelf.duplicate()
|
||||
|
||||
|
||||
func shop_bp_visit_buys() -> int:
|
||||
return _shop_visit_buys
|
||||
Reference in new issue
Block a user