M6 商店bcard同构化(UI落码第二波)——pool货架横排行卡→bcard三竖卡(类型色带/图标/名/件值/价签金/底注/购买钮footer)+顶栏(标题+刷新占位钮禁用+GP烛光章)+库存余量退役(v1.5-a用户裁,数据层stock_left不动)+爬价行挂MC-1(无成文出口);BCard微扩body/add_footer(串行无撞);legacy面原样。闸=冒烟747/0+probe_gate全绿+layout 0

This commit is contained in:
DKChan committed 2026-10-05 02:18:43 +08:00
1 parent 912dcb20b9
commit b6ae74e288
2 files changed
+61 -26

No files matched your search

+55 -26
View File
@@ -18,19 +18,43 @@ const ATTR_LABELS := {"atk": "攻击", "max_hp": "生命上限", "armor_class":
const KIND_LABELS := {"attack": "攻击", "max_hp": "生命上限", "armor": "护甲", "ap": "行动点"} # 货架件值文案轴(共享池 kind 词表——迭代 11 第②批)
var _gp_label: Label
var _refresh_btn: Button # M6 刷新呈现位(禁用占位——机制由 MC-1 核心批接线)
var _cards_box: VBoxContainer
var _card_rows: Array[Dictionary] = [] # [{product_id, price, bought, btn}]——refresh_state 就地重刷(零重建回流)
var _shelf_rows: Array[Dictionary] = [] # [{kind_id, btn}]——pool 面卡片(买后整架重建=重抽反馈)
func _init() -> void:
# M6(UI 落码批):pool 面卡面 bcard 三竖卡同构化(demo ⑤/2026-10-02 同构裁决呈现侧闭环)——
# 库存余量退役(关卡节点地图 v1.5-a 用户裁);刷新钮呈现位照摆(机制=MC-1 核心批投喂,占位禁用);
# 爬价总览行不摆=已购次数无成文出口(随 MC-1 shop_draw 投影补)。legacy 面(open_shop)原样保留。
var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box
var title := UiKit.label("商店", 26, true, UiKit.WARM)
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(title)
_gp_label = UiKit.label("金币 0", 18, true, UiKit.GOLD)
_gp_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_gp_label)
var top := HBoxContainer.new()
top.add_theme_constant_override("separation", 12)
box.add_child(top)
var title := UiKit.label("商 店", 26, true, UiKit.WARM)
top.add_child(title)
var top_sp := Control.new()
top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
top.add_child(top_sp)
_refresh_btn = UiKit.button("")
_refresh_btn.icon = UiKit.load_tex(UiKit.TEX_ICON_REFRESH)
_refresh_btn.custom_minimum_size = Vector2(44, 44)
_refresh_btn.tooltip_text = "刷新货架(机制接入中——商店刷新核心批 MC-1)"
_refresh_btn.disabled = true
top.add_child(_refresh_btn)
var stock_badge := UiKit.label("0", 12, true, UiKit.INK_ON_GOLD)
stock_badge.mouse_filter = Control.MOUSE_FILTER_IGNORE
stock_badge.set_anchors_preset(Control.PRESET_TOP_RIGHT)
stock_badge.offset_left = -22.0
stock_badge.offset_top = -6.0
_refresh_btn.add_child(stock_badge)
var gp_chip := PanelContainer.new()
gp_chip.add_theme_stylebox_override("panel",
UiKit.panel_flat(UiKit.CANDLE, UiKit.CAMP_HEADER_BAND, 2, 1, Vector4(12, 4, 12, 4)))
top.add_child(gp_chip)
_gp_label = UiKit.label("金币 0", 16, true, UiKit.INK_ON_GOLD)
gp_chip.add_child(_gp_label)
_cards_box = VBoxContainer.new()
_cards_box.add_theme_constant_override("separation", 8)
box.add_child(_cards_box)
@@ -110,12 +134,16 @@ func open_shelf(cards: Array, gp: int) -> void:
for child in _cards_box.get_children():
child.queue_free()
_shelf_rows.clear()
var row := HBoxContainer.new()
row.alignment = BoxContainer.ALIGNMENT_CENTER
row.add_theme_constant_override("separation", 20)
_cards_box.add_child(row)
for c in cards:
_shelf_rows.append(_build_shelf_card(c))
_shelf_rows.append(_build_shelf_card(row, c))
if cards.is_empty():
var empty := UiKit.label("货架售罄——共享池已买空(属性件全冒险共 3+3+3 份 / AP 件 2 份)", 14, false, UiKit.WARM_FAINT)
empty.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_cards_box.add_child(empty)
row.add_child(empty)
refresh_shelf_state(gp)
visible = true
@@ -125,29 +153,30 @@ func refresh_shelf_state(gp: int) -> void:
_gp_label.text = "金币 %d" % gp
for card in _shelf_rows:
card.btn.disabled = gp < int(card.price)
card.card.modulate = Color(1, 1, 1, 1) if gp >= int(card.price) else Color(1, 1, 1, 0.55)
# 货架卡(显示名+件值文案 | 现价 | 库存余量 | 购买钮)——三选一同构语言:买 1 = 一次真实购买
func _build_shelf_card(c: Dictionary) -> Dictionary:
# 货架卡(bcard 竖卡:类型色带+图标+名+件值描述+价签+购买钮——M6 同构卡;demo ⑤)
# 库存余量退役=关卡节点地图 v1.5-a 用户裁(2026-10-04)——数据层 stock_left 仍投喂断点,仅呈现不摆
func _build_shelf_card(holder: Control, c: Dictionary) -> Dictionary:
var kind := String(c.get("kind_id", ""))
var card := PanelContainer.new()
card.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.BG_OVERLAY, UiKit.GOLD_DIM, 4, 1, Vector4(12, 6, 12, 6)))
var row := HBoxContainer.new()
row.add_theme_constant_override("separation", 14)
card.add_child(row)
var name_l := UiKit.label("%s(%s %+d)" % [String(c.get("display_name", kind)), String(KIND_LABELS.get(kind, kind)), int(c.get("value", 0))], 15, true)
name_l.custom_minimum_size = Vector2(190, 0)
row.add_child(name_l)
var price_l := UiKit.label("现价 %d 金币" % int(c.get("price", 0)), 14, false, UiKit.WARM_SOFT)
price_l.custom_minimum_size = Vector2(110, 0)
row.add_child(price_l)
var stock_l := UiKit.label("库存余 %s" % str(int(c.get("stock_left", 0))) if int(c.get("stock_left", 0)) < (1 << 20) else "库存余 ∞", 14, false, UiKit.WARM_FAINT)
row.add_child(stock_l)
var icon_key := UiKit.TEX_ICON_SWORD
var kl := kind.to_lower()
if kl.contains("hp") or kl.contains("heal"):
icon_key = UiKit.TEX_ICON_HEART
elif kl.contains("armor") or kl.contains("shield"):
icon_key = UiKit.TEX_ICON_SHIELD
elif kl.contains("ap") or kl.contains("action") or kl.contains("pouch"):
icon_key = UiKit.TEX_ICON_POUCH
var card := UiKit.bcard(String(c.get("display_name", kind)),
"%s %+d(本冒险)" % [String(KIND_LABELS.get(kind, kind)), int(c.get("value", 0))],
Color8(194, 178, 100), icon_key,
"%d ◈" % int(c.get("price", 0)), String(KIND_LABELS.get(kind, kind)))
var btn := UiKit.button("购买")
btn.pressed.connect(_emit_shelf_buy.bind(kind))
row.add_child(btn)
_cards_box.add_child(card)
return {"kind_id": kind, "price": int(c.get("price", 0)), "btn": btn}
card.add_footer(btn)
holder.add_child(card)
return {"kind_id": kind, "price": int(c.get("price", 0)), "btn": btn, "card": card}
func _emit_shelf_buy(kind: String) -> void:
+6
View File
@@ -386,6 +386,7 @@ class BCard:
var desc_l: Label
var price_l: Label
var foot_l: Label
var body: VBoxContainer # 内容列(消费方经 add_footer 插件到底注前——M6 购买钮挂位)
var _sb_normal: StyleBox
var _sb_sel: StyleBox
@@ -398,6 +399,7 @@ class BCard:
var box := VBoxContainer.new()
box.add_theme_constant_override("separation", 8)
add_child(box)
body = box
var band_r := ColorRect.new()
band_r.color = band
band_r.custom_minimum_size = Vector2(0, 6)
@@ -439,6 +441,10 @@ class BCard:
add_theme_stylebox_override("panel", _sb_sel if v else _sb_normal)
mark.visible = v
func add_footer(c: Control) -> void:
body.add_child(c)
body.move_child(c, body.get_child_index(foot_l))
static func bcard(title: String, desc: String, band: Color, icon_path: String, price := "", footnote := "") -> BCard:
return BCard.new(title, desc, band, icon_path, price, footnote)