161 lines
8.9 KiB
GDScript
161 lines
8.9 KiB
GDScript
class_name GoldExchangePanel
|
||
extends PanelModule
|
||
|
||
# 兑换金豆面板:
|
||
# - 负责钻石/道具兑换金豆的配置展示和兑换请求。
|
||
# - 消耗判断走 PanelModule,兑换成功后只增加金豆并刷新顶部资源。
|
||
# - 该入口来自左侧“兑换金豆”按钮,UI 尺寸需保持原版面板比例。
|
||
const NumberFormatterScript := preload("res://scripts/core/number_formatter.gd")
|
||
|
||
var _mode := "gemToGold"
|
||
var _amount := 1
|
||
var _history_list: VBoxContainer
|
||
var _status_label: Label
|
||
var _amount_label: Label
|
||
var _result_label: Label
|
||
|
||
|
||
func open() -> void:
|
||
_close_modal(false)
|
||
_mode = "gemToGold"
|
||
_amount = _step()
|
||
var panel: Control = _ui.create_modal_root("GoldExchangePanel")
|
||
var player := _player_data()
|
||
_ui.add_scale9_patch(panel, "PanelBg", _texture_provider.common("c_panel"), Vector2(20.0, 76.0), Vector2(600.0, 820.0), Rect2(122.0, 174.0, 21.0, 10.0))
|
||
_ui.add_texture(panel, "TitleBg", _texture_provider.frame(_texture_provider.atlas_path("common2"), "common2_diban_png"), Vector2(168.0, 70.0), Vector2(304.0, 70.0))
|
||
_ui.add_panel_label(panel, "TitleText", "兑换金豆", Vector2(170.0, 84.0), Vector2(300.0, 48.0), 34, Color.html("#fffbf2"), 2, Color.html("#724f2e"))
|
||
_status_label = _ui.add_panel_label(panel, "Status", "", Vector2(60.0, 142.0), Vector2(520.0, 34.0), 20, Color.html("#5b3616"), 0, Color.TRANSPARENT)
|
||
_ui.add_panel_label(panel, "GoldBalance", "金豆:%s" % NumberFormatterScript.compact(int(player.get("gold", 0))), Vector2(92.0, 184.0), Vector2(210.0, 30.0), 22, Color.html("#5b3616"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_LEFT)
|
||
_ui.add_panel_label(panel, "GemBalance", "钻石:%s" % NumberFormatterScript.compact(int(player.get("gem", player.get("diamond", 0)))), Vector2(332.0, 184.0), Vector2(210.0, 30.0), 22, Color.html("#5b3616"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_LEFT)
|
||
_ui.add_texture_button(panel, "GemToGold", _texture_provider.common("c_btn3"), Vector2(80.0, 228.0), Vector2(220.0, 54.0), "钻石兑金豆", Callable(self, "_set_mode").bind("gemToGold"), 24)
|
||
_ui.add_texture_button(panel, "GoldToGem", _texture_provider.common("c_btn3"), Vector2(340.0, 228.0), Vector2(220.0, 54.0), "金豆兑钻石", Callable(self, "_set_mode").bind("goldToGem"), 24)
|
||
_ui.add_panel_label(panel, "ModeTitle", "", Vector2(80.0, 306.0), Vector2(480.0, 40.0), 28, Color.html("#fffbf2"), 2, Color.html("#724f2e"))
|
||
_ui.add_panel_label(panel, "Rate", "", Vector2(80.0, 348.0), Vector2(480.0, 30.0), 20, Color.html("#7d1c1c"), 0, Color.TRANSPARENT)
|
||
_ui.add_texture_button(panel, "Minus", _texture_provider.common("btn_sub"), Vector2(112.0, 394.0), Vector2(54.0, 44.0), "", Callable(self, "_change_amount").bind(-1), 20)
|
||
_ui.add_scale9_patch(panel, "InputBg", _texture_provider.frame(_texture_provider.atlas_path("common2"), "common2_inputbg_png"), Vector2(184.0, 396.0), Vector2(270.0, 42.0), Rect2(13.0, 4.0, 84.0, 30.0))
|
||
_amount_label = _ui.add_panel_label(panel, "Amount", "", Vector2(196.0, 400.0), Vector2(246.0, 34.0), 24, Color.html("#5b3616"), 0, Color.TRANSPARENT)
|
||
_ui.add_texture_button(panel, "Plus", _texture_provider.common("btn_add"), Vector2(474.0, 394.0), Vector2(54.0, 44.0), "", Callable(self, "_change_amount").bind(1), 20)
|
||
_result_label = _ui.add_panel_label(panel, "Result", "", Vector2(80.0, 448.0), Vector2(480.0, 30.0), 20, Color.html("#5b3616"), 0, Color.TRANSPARENT)
|
||
_ui.add_texture_button(panel, "Exchange", _texture_provider.common("c_btn3"), Vector2(245.0, 486.0), Vector2(150.0, 58.0), "兑换", Callable(self, "_exchange"), 28)
|
||
_ui.add_panel_label(panel, "HistoryTitle", "兑换记录", Vector2(70.0, 566.0), Vector2(500.0, 32.0), 24, Color.html("#fffbf2"), 2, Color.html("#724f2e"))
|
||
_ui.add_scale9_patch(panel, "HistoryBg", _texture_provider.common("inner_page"), Vector2(70.0, 602.0), Vector2(500.0, 214.0), Rect2(31.0, 31.0, 8.0, 9.0))
|
||
var scroll := ScrollContainer.new()
|
||
scroll.position = Vector2(70.0, 607.0)
|
||
scroll.size = Vector2(500.0, 204.0)
|
||
scroll.clip_contents = true
|
||
_ui.configure_vertical_scroll(scroll)
|
||
panel.add_child(scroll)
|
||
_history_list = VBoxContainer.new()
|
||
_history_list.custom_minimum_size = Vector2(490.0, 0.0)
|
||
scroll.add_child(_history_list)
|
||
_ui.add_texture_button(panel, "PanelClose", _texture_provider.common("c_btn3"), Vector2(240.0, 820.0), Vector2(160.0, 58.0), "离开", Callable(self, "_close_modal").bind(true), 30)
|
||
_open_modal(panel)
|
||
await render()
|
||
|
||
|
||
func _set_mode(mode: String) -> void:
|
||
_mode = mode
|
||
_amount = _step()
|
||
await render()
|
||
|
||
|
||
func _change_amount(direction: int) -> void:
|
||
_amount = maxi(_step(), _amount + direction * _step())
|
||
_update_labels()
|
||
|
||
|
||
func render() -> void:
|
||
_update_labels()
|
||
var history_list := _history_list
|
||
if not _clear_children_if_live(history_list):
|
||
return
|
||
_ui.add_panel_label(history_list, "Loading", "正在读取兑换记录...", Vector2.ZERO, Vector2(490.0, 40.0), 18, Color.html("#5b3616"), 0, Color.TRANSPARENT)
|
||
var result: Dictionary = await _activity_api.fetch_exchange_history(_token(), 0 if _mode == "gemToGold" else 1)
|
||
if not _is_current_node(history_list, _history_list):
|
||
return
|
||
_clear_children(history_list)
|
||
if not result.get("ok", false):
|
||
_ui.add_panel_label(history_list, "Error", _response_status_text(result, "兑换记录读取失败"), Vector2.ZERO, Vector2(490.0, 40.0), 18, Color.html("#ce5f5f"), 0, Color.TRANSPARENT)
|
||
return
|
||
var data = _response_data(result, {})
|
||
var rows: Array = data.get("list", []) if data is Dictionary else []
|
||
if _is_live_node(_status_label):
|
||
_status_label.text = I18nScript.t("兑换记录已加载" if not rows.is_empty() else "暂无兑换记录")
|
||
for index in range(mini(rows.size(), 12)):
|
||
if rows[index] is Dictionary:
|
||
_add_history_row(history_list, rows[index])
|
||
|
||
|
||
func _update_labels() -> void:
|
||
var panel := _history_list.get_parent().get_parent() as Control if _is_live_node(_history_list) and _history_list.get_parent() != null else null
|
||
var mode_title := panel.get_node_or_null("ModeTitle") as Label if panel != null else null
|
||
var rate_label := panel.get_node_or_null("Rate") as Label if panel != null else null
|
||
var is_gem := _mode == "gemToGold"
|
||
var rate := _rate()
|
||
if mode_title != null:
|
||
mode_title.text = I18nScript.t("钻石兑换金豆" if is_gem else "金豆兑换钻石")
|
||
if rate_label != null:
|
||
rate_label.text = I18nScript.t("兑换比例 1 钻石 = %s 金豆" % rate if is_gem else "兑换比例 %s 金豆 = 1 钻石" % rate)
|
||
if _is_live_node(_amount_label):
|
||
_amount_label.text = str(_amount)
|
||
if _is_live_node(_result_label):
|
||
_result_label.text = I18nScript.t("预计获得 %s 金豆" % _result() if is_gem else "预计获得 %s 钻石" % _result())
|
||
|
||
|
||
func _exchange() -> void:
|
||
if _is_busy():
|
||
return
|
||
var player := _player_data()
|
||
var owned := int(player.get("gem", player.get("diamond", 0))) if _mode == "gemToGold" else int(player.get("gold", 0))
|
||
if _amount <= 0 or _amount > owned:
|
||
_show_toast("钻石不足" if _mode == "gemToGold" else "金豆不足")
|
||
return
|
||
_set_busy(true)
|
||
var result: Dictionary
|
||
if _mode == "gemToGold":
|
||
result = await _activity_api.exchange_gem_to_gold(_token(), _amount)
|
||
else:
|
||
result = await _activity_api.exchange_gold_to_gem(_token(), _amount)
|
||
_set_busy(false)
|
||
if not result.get("ok", false):
|
||
_show_toast(_response_status_text(result, "兑换失败"))
|
||
return
|
||
var data = _response_data(result, {})
|
||
if data is Dictionary:
|
||
for key in data.keys():
|
||
player[key] = data[key]
|
||
else:
|
||
if _mode == "gemToGold":
|
||
player["gem"] = maxi(int(player.get("gem", player.get("diamond", 0))) - _amount, 0)
|
||
player["gold"] = int(player.get("gold", 0)) + _result()
|
||
else:
|
||
player["gold"] = maxi(int(player.get("gold", 0)) - _amount, 0)
|
||
player["gem"] = int(player.get("gem", player.get("diamond", 0))) + _result()
|
||
_render_player()
|
||
_show_toast("兑换成功")
|
||
await render()
|
||
|
||
|
||
func _add_history_row(parent: Control, row: Dictionary) -> void:
|
||
var holder := Control.new()
|
||
holder.custom_minimum_size = Vector2(490.0, 62.0)
|
||
holder.size = Vector2(490.0, 62.0)
|
||
parent.add_child(holder)
|
||
_ui.add_panel_label(holder, "Time", _format_timestamp(int(row.get("created_at", 0))), Vector2(12.0, 8.0), Vector2(190.0, 24.0), 18, Color.html("#f4991d"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_LEFT)
|
||
_ui.add_panel_label(holder, "Desc", "兑换获得金豆" if _mode == "gemToGold" else "兑换获得钻石", Vector2(12.0, 34.0), Vector2(370.0, 24.0), 18, Color.html("#7d1c1c"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_LEFT)
|
||
_ui.add_panel_label(holder, "Num", "+%s" % int(row.get("num", row.get("count", 0))), Vector2(390.0, 34.0), Vector2(92.0, 24.0), 18, Color.html("#2f9c11"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_RIGHT)
|
||
_ui.add_nine_patch(holder, "Line", _texture_provider.common("line"), Vector2(8.0, 60.0), Vector2(482.0, 2.0), Vector4.ZERO)
|
||
|
||
|
||
func _rate() -> int:
|
||
return maxi(int(_game_config.get_common_config(24 if _mode == "gemToGold" else 17).get("min", 10)), 1)
|
||
|
||
|
||
func _step() -> int:
|
||
return 1 if _mode == "gemToGold" else _rate()
|
||
|
||
|
||
func _result() -> int:
|
||
var rate := _rate()
|
||
return _amount * rate if _mode == "gemToGold" else int(floor(float(_amount) / float(rate)))
|