hy-farm/godot/FarmGodot/scripts/ui/panels/gold_exchange_panel.gd
2026-05-29 19:54:56 +08:00

161 lines
8.9 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)))