feat: 2.3.2
This commit is contained in:
+106
-22
@@ -8,6 +8,9 @@ signal closed
|
||||
@onready var item_grid: GridContainer = %ItemGrid
|
||||
@onready var back_btn: Button = %BackBtn
|
||||
@onready var status_label: Label = %StatusLabel
|
||||
@onready var banner1: Button = %Banner1
|
||||
@onready var banner2: Button = %Banner2
|
||||
@onready var banner3: Button = %Banner3
|
||||
|
||||
# Tabs
|
||||
@onready var tab_head: Button = %TabHead
|
||||
@@ -17,6 +20,9 @@ signal closed
|
||||
@onready var tab_gold: Button = %TabGold
|
||||
@onready var tab_star: Button = %TabStar
|
||||
|
||||
# Maps category -> tab button (populated in _ready)
|
||||
var _tab_map: Dictionary = {}
|
||||
|
||||
# 3D Preview
|
||||
@onready var character_root: Node3D = %CharacterRoot
|
||||
@onready var anim_player: AnimationPlayer = %AnimationPlayer
|
||||
@@ -72,6 +78,14 @@ const STAR_PACKS: Array = [
|
||||
# _ready
|
||||
# -----------------------------------------------------------------------
|
||||
func _ready() -> void:
|
||||
_tab_map = {
|
||||
"head": tab_head,
|
||||
"costume": tab_costume,
|
||||
"glove": tab_glove,
|
||||
"accessory": tab_acc,
|
||||
"gold_packs": tab_gold,
|
||||
"star_packs": tab_star,
|
||||
}
|
||||
back_btn.pressed.connect(_on_close)
|
||||
tab_head.pressed.connect(_on_tab_selected.bind("head"))
|
||||
tab_costume.pressed.connect(_on_tab_selected.bind("costume"))
|
||||
@@ -85,6 +99,7 @@ func _ready() -> void:
|
||||
if UserProfileManager.profile_updated.connect(_refresh_wallet) != OK:
|
||||
pass
|
||||
|
||||
_set_active_tab(current_category)
|
||||
_setup_3d_preview()
|
||||
|
||||
if UserProfileManager.shop_catalog.is_empty():
|
||||
@@ -175,12 +190,78 @@ func _fetch_and_build() -> void:
|
||||
|
||||
func _build_shop() -> void:
|
||||
_refresh_wallet()
|
||||
_populate_banners()
|
||||
_populate_current_tab()
|
||||
|
||||
func _on_tab_selected(category: String) -> void:
|
||||
current_category = category
|
||||
_set_active_tab(category)
|
||||
_populate_current_tab()
|
||||
|
||||
func _set_active_tab(active_category: String) -> void:
|
||||
var style_active := StyleBoxFlat.new()
|
||||
style_active.bg_color = Color(1, 1, 1, 1)
|
||||
style_active.content_margin_left = 16.0
|
||||
style_active.content_margin_top = 10.0
|
||||
style_active.content_margin_right = 16.0
|
||||
style_active.content_margin_bottom = 10.0
|
||||
style_active.corner_radius_top_left = 6
|
||||
style_active.corner_radius_top_right = 6
|
||||
style_active.corner_radius_bottom_right = 6
|
||||
style_active.corner_radius_bottom_left = 6
|
||||
|
||||
var style_inactive := StyleBoxFlat.new()
|
||||
style_inactive.bg_color = Color(0.15, 0.18, 0.22, 1)
|
||||
style_inactive.content_margin_left = 16.0
|
||||
style_inactive.content_margin_top = 10.0
|
||||
style_inactive.content_margin_right = 16.0
|
||||
style_inactive.content_margin_bottom = 10.0
|
||||
style_inactive.corner_radius_top_left = 6
|
||||
style_inactive.corner_radius_top_right = 6
|
||||
style_inactive.corner_radius_bottom_right = 6
|
||||
style_inactive.corner_radius_bottom_left = 6
|
||||
|
||||
var style_hover := StyleBoxFlat.new()
|
||||
style_hover.bg_color = Color(0.22, 0.26, 0.30, 1)
|
||||
style_hover.content_margin_left = 16.0
|
||||
style_hover.content_margin_top = 10.0
|
||||
style_hover.content_margin_right = 16.0
|
||||
style_hover.content_margin_bottom = 10.0
|
||||
style_hover.corner_radius_top_left = 6
|
||||
style_hover.corner_radius_top_right = 6
|
||||
style_hover.corner_radius_bottom_right = 6
|
||||
style_hover.corner_radius_bottom_left = 6
|
||||
|
||||
for cat in _tab_map:
|
||||
var btn: Button = _tab_map[cat]
|
||||
if cat == active_category:
|
||||
btn.add_theme_stylebox_override("normal", style_active)
|
||||
btn.add_theme_stylebox_override("hover", style_active)
|
||||
btn.add_theme_stylebox_override("pressed", style_active)
|
||||
btn.add_theme_color_override("font_color", Color(0.08, 0.09, 0.12))
|
||||
btn.add_theme_color_override("font_hover_color", Color(0.08, 0.09, 0.12))
|
||||
else:
|
||||
btn.add_theme_stylebox_override("normal", style_inactive)
|
||||
btn.add_theme_stylebox_override("hover", style_hover)
|
||||
btn.add_theme_stylebox_override("pressed", style_inactive)
|
||||
btn.add_theme_color_override("font_color", Color(0.7, 0.7, 0.7))
|
||||
btn.add_theme_color_override("font_hover_color", Color(1, 1, 1))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Banner population — promotional / featured items
|
||||
# -----------------------------------------------------------------------
|
||||
func _populate_banners() -> void:
|
||||
var banners: Array[Button] = [banner1, banner2, banner3]
|
||||
var promos: Array = UserProfileManager.shop_catalog.get("banners", [])
|
||||
for i in banners.size():
|
||||
var btn: Button = banners[i]
|
||||
if i < promos.size():
|
||||
btn.text = promos[i].get("label", "")
|
||||
btn.tooltip_text = promos[i].get("id", "")
|
||||
btn.show()
|
||||
else:
|
||||
btn.hide()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Grid population — builds cards dynamically from localized templates
|
||||
# -----------------------------------------------------------------------
|
||||
@@ -214,8 +295,8 @@ func _make_gold_card(pack: Dictionary) -> Control:
|
||||
var card: Control = template_gold_card.duplicate()
|
||||
card.visible = true
|
||||
|
||||
var amount_lbl: Label = card.find_child("AmountLabel", true, false) as Label
|
||||
if amount_lbl: amount_lbl.text = "⭐ %d" % pack.amount
|
||||
var amount_lbl: RichTextLabel = card.find_child("AmountLabel", true, false) as RichTextLabel
|
||||
if amount_lbl: amount_lbl.text = "[right][img=24x24]res://assets/graphics/gui/lobby/gold.png[/img] %d[/right]" % pack.amount
|
||||
|
||||
var bonus_lbl: Label = card.find_child("BonusLabel", true, false) as Label
|
||||
if bonus_lbl:
|
||||
@@ -237,11 +318,11 @@ func _make_star_card(pack: Dictionary) -> Control:
|
||||
var card: Control = template_star_card.duplicate()
|
||||
card.visible = true
|
||||
|
||||
var amount_lbl: Label = card.find_child("AmountLabel", true, false) as Label
|
||||
if amount_lbl: amount_lbl.text = "✦ %d" % pack.amount
|
||||
var amount_lbl: RichTextLabel = card.find_child("AmountLabel", true, false) as RichTextLabel
|
||||
if amount_lbl: amount_lbl.text = "[right][img=24x24]res://assets/graphics/gui/lobby/star.png[/img] %d[/right]" % pack.amount
|
||||
|
||||
var cost_lbl: Label = card.find_child("CostLabel", true, false) as Label
|
||||
if cost_lbl: cost_lbl.text = "Cost: ⭐ %d Gold" % pack.gold_cost
|
||||
var cost_lbl: RichTextLabel = card.find_child("CostLabel", true, false) as RichTextLabel
|
||||
if cost_lbl: cost_lbl.text = "[center]Cost: [img=20x20]res://assets/graphics/gui/lobby/gold.png[/img] %d[/center]" % pack.gold_cost
|
||||
|
||||
var buy_btn: Button = card.find_child("BuyBtn", true, false) as Button
|
||||
if buy_btn: buy_btn.pressed.connect(_on_buy_star_pressed.bind(pack))
|
||||
@@ -270,13 +351,16 @@ func _make_cosmetic_card(item: Dictionary) -> Control:
|
||||
}.get(rarity, Color(0.50, 0.50, 0.50))
|
||||
rarity_lbl.add_theme_color_override("font_color", rarity_col)
|
||||
|
||||
var price_lbl: Label = card.find_child("PriceLabel", true, false) as Label
|
||||
var price_lbl: RichTextLabel = card.find_child("PriceLabel", true, false) as RichTextLabel
|
||||
if price_lbl:
|
||||
var g: int = int(item.get("gold", 0))
|
||||
var s: int = int(item.get("star", 0))
|
||||
if g > 0 and s > 0: price_lbl.text = "⭐ %d ✦ %d" % [g, s]
|
||||
elif g > 0: price_lbl.text = "⭐ %d" % g
|
||||
else: price_lbl.text = "✦ %d" % s
|
||||
if g > 0 and s > 0:
|
||||
price_lbl.text = "[center][img=20x20]res://assets/graphics/gui/lobby/gold.png[/img] %d [img=20x20]res://assets/graphics/gui/lobby/star.png[/img] %d[/center]" % [g, s]
|
||||
elif g > 0:
|
||||
price_lbl.text = "[center][img=20x20]res://assets/graphics/gui/lobby/gold.png[/img] %d[/center]" % g
|
||||
else:
|
||||
price_lbl.text = "[center][img=20x20]res://assets/graphics/gui/lobby/star.png[/img] %d[/center]" % s
|
||||
|
||||
var try_btn: Button = card.find_child("TryBtn", true, false) as Button
|
||||
if try_btn: try_btn.pressed.connect(_on_try_pressed.bind(item))
|
||||
@@ -300,8 +384,8 @@ func _make_cosmetic_card(item: Dictionary) -> Control:
|
||||
func _refresh_wallet() -> void:
|
||||
var g: int = UserProfileManager.wallet.get("gold", 0)
|
||||
var s: int = UserProfileManager.wallet.get("star", 0)
|
||||
gold_label.text = "⭐ %d" % g
|
||||
star_label.text = "✦ %d" % s
|
||||
gold_label.text = str(g)
|
||||
star_label.text = str(s)
|
||||
status_label.text = ""
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
@@ -351,23 +435,23 @@ func _on_buy_cosmetic_pressed(item: Dictionary) -> void:
|
||||
if UserProfileManager.inventory.has(item.id):
|
||||
status_label.text = "Already owned: " + item.get("name", item.id)
|
||||
return
|
||||
var price_gold: int = item.get("gold", 0)
|
||||
var price_star: int = item.get("star", 0)
|
||||
if UserProfileManager.wallet.get("gold", 0) < price_gold \
|
||||
or UserProfileManager.wallet.get("star", 0) < price_star:
|
||||
status_label.text = "Not enough currency."
|
||||
return
|
||||
|
||||
status_label.text = "Purchasing..."
|
||||
var success: bool = await UserProfileManager.purchase_item(
|
||||
item.id, price_gold, price_star, current_category)
|
||||
status_label.text = ("Purchased: " + item.get("name", item.id)) if success else "Purchase failed."
|
||||
if success:
|
||||
var err: String = await UserProfileManager.purchase_item(item.id)
|
||||
|
||||
if err == "":
|
||||
status_label.text = "Purchased: " + item.get("name", item.id)
|
||||
_refresh_wallet()
|
||||
# Refresh preview to show newly purchased skin's materials
|
||||
if _preview_revert.is_valid():
|
||||
_preview_revert.call()
|
||||
_preview_revert = Callable()
|
||||
SkinManager.apply_loadout(character_root, UserProfileManager.loadout)
|
||||
else:
|
||||
if "NotEnoughFunds" in err or "funds" in err.to_lower() or "wallet" in err.to_lower():
|
||||
status_label.text = "Not enough currency."
|
||||
else:
|
||||
status_label.text = "Purchase failed."
|
||||
|
||||
func _on_close() -> void:
|
||||
# Clean up any open preview when closing the shop
|
||||
|
||||
Reference in New Issue
Block a user