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

125 lines
6.9 KiB
GDScript

class_name LotteryPanel
extends PanelModule
# 幸运转盘面板:
# - 负责转盘奖励格、抽奖接口、旋转动画和结果落账。
# - 动画完成前不允许重复点击,避免同一轮抽奖产生多次本地奖励。
# - 奖励展示和发放都走统一 reward/cost 格式,方便对齐原 H5 配置。
const NumberFormatterScript := preload("res://scripts/core/number_formatter.gd")
var _pay_bg_path := ""
var _light: TextureRect
var _button: Control
var _panel: Control
func setup(options: Dictionary) -> void:
super.setup(options)
_pay_bg_path = str(options.get("pay_bg_path", _pay_bg_path))
func open() -> void:
_close_modal(false)
_panel = _ui.create_legacy_panel_shell("LotteryPanel", Vector2(20.0, 191.0), Vector2(600.0, 578.0), _texture_provider.frame(_texture_provider.atlas_path("lottery"), "panel_icon_lottery_png"), _texture_provider.frame(_texture_provider.atlas_path("lottery"), "panel_title_lottery_png"), Vector2(75.0, 160.0), Vector2(210.0, 160.0), Vector2(220.0, 709.0))
_ui.add_scale9_patch(_panel, "PayBg", _texture_provider.standalone(_pay_bg_path), Vector2(45.0, 261.0), Vector2(550.0, 458.0), Rect2(65.0, 200.0, 392.0, 11.0))
_ui.add_texture(_panel, "DecorLeft", _texture_provider.standalone("res://assets/egret/assets/game/pay/pay_zhuangshi.png"), Vector2(7.0, 246.0), Vector2(167.0, 269.0))
var decor_right: TextureRect = _ui.add_texture(_panel, "DecorRight", _texture_provider.standalone("res://assets/egret/assets/game/pay/pay_zhuangshi.png"), Vector2(467.0, 246.0), Vector2(167.0, 269.0))
decor_right.flip_h = true
_light = _ui.add_texture(_panel, "LotteryLight", _texture_provider.frame(_texture_provider.atlas_path("lottery"), "lottery_light_png"), Vector2(68.0, 304.0), Vector2(120.0, 120.0))
_light.visible = false
_add_lottery_dots()
_ui.add_texture(_panel, "CirLight", _texture_provider.frame(_texture_provider.atlas_path("lottery"), "lottery_l2_png"), Vector2(186.0, 417.0), Vector2(275.0, 180.0), TextureRect.STRETCH_KEEP_ASPECT_CENTERED)
var card_positions := [
Vector2(83.0, 319.0), Vector2(180.0, 319.0), Vector2(276.0, 319.0), Vector2(373.0, 319.0), Vector2(469.0, 319.0),
Vector2(469.0, 414.0), Vector2(469.0, 510.0), Vector2(469.0, 605.0), Vector2(373.0, 605.0), Vector2(276.0, 605.0),
Vector2(180.0, 605.0), Vector2(83.0, 605.0), Vector2(83.0, 510.0), Vector2(83.0, 414.0)
]
var lottery_rows: Array[Dictionary] = _game_config.get_lottery_config()
for index in range(mini(lottery_rows.size(), 14)):
var card := Control.new()
card.name = "LotteryCard%s" % index
card.position = card_positions[index]
card.size = Vector2(90.0, 90.0)
_panel.add_child(card)
_ui.add_texture(card, "Bg", _texture_provider.common("item_bg"), Vector2.ZERO, Vector2(90.0, 90.0))
var item_id := int(lottery_rows[index].get("item_id", lottery_rows[index].get("value", 0)))
var count := int(lottery_rows[index].get("count", lottery_rows[index].get("value", 0)))
_ui.add_texture(card, "Icon", _get_item_icon_texture(_game_config.get_item_icon_id(item_id)), Vector2(8.0, 5.0), Vector2(74.0, 68.0), TextureRect.STRETCH_KEEP_ASPECT_CENTERED)
_ui.add_panel_label(card, "Count", "x%s" % NumberFormatterScript.compact(count), Vector2(8.0, 64.0), Vector2(74.0, 22.0), 22, Color.html("#b36011"), 1, Color.html("#ffe59d"), HORIZONTAL_ALIGNMENT_RIGHT)
_button = _ui.add_texture_button(_panel, "LotteryGo", _texture_provider.frame(_texture_provider.atlas_path("lottery"), "lottery_btn_go_png"), Vector2(254.0, 484.0), Vector2(133.0, 52.0), "", Callable(self, "_go"), 20)
_ui.add_panel_label(_panel, "LotteryPrice", _price_text(), Vector2(285.0, 552.0), Vector2(155.0, 24.0), 20, Color.html("#7bff6d"), 0, Color.TRANSPARENT, HORIZONTAL_ALIGNMENT_LEFT)
_ui.add_texture(_panel, "GoldIcon", _get_item_icon_texture(3002), Vector2(257.0, 541.0), Vector2(35.0, 35.0), TextureRect.STRETCH_KEEP_ASPECT_CENTERED)
var close := _panel.get_node_or_null("PanelClose")
if close != null:
_panel.move_child(close, _panel.get_child_count() - 1)
_open_modal(_panel)
func _add_lottery_dots() -> void:
var dot_positions := [
["lottery_dot1_png", Vector2(213.0, 446.0)], ["lottery_dot1_png", Vector2(207.0, 552.0)],
["lottery_dot1_png", Vector2(307.0, 450.0)], ["lottery_dot1_png", Vector2(373.0, 552.0)],
["lottery_dot2_png", Vector2(405.0, 458.0)], ["lottery_dot2_png", Vector2(354.0, 437.0)],
["lottery_dot2_png", Vector2(406.0, 550.0)], ["lottery_dot2_png", Vector2(220.0, 507.0)],
["lottery_dot2_png", Vector2(268.0, 540.0)], ["lottery_dot2_png", Vector2(419.0, 516.0)]
]
for index in range(dot_positions.size()):
var entry: Array = dot_positions[index]
_ui.add_texture(_panel, "LotteryDot%s" % index, _texture_provider.frame(_texture_provider.atlas_path("lottery"), str(entry[0])), entry[1], Vector2(12.0, 12.0), TextureRect.STRETCH_KEEP_ASPECT_CENTERED)
func _price_text() -> String:
return "(本次免费)" if int(_player_data().get("lottery_count", 0)) == 0 else "x%s" % int(_game_config.get_common_config(15).get("min", 0))
func _go() -> void:
if _is_busy():
return
var player := _player_data()
var cost := 0 if int(player.get("lottery_count", 0)) == 0 else int(_game_config.get_common_config(15).get("min", 0))
if cost > int(player.get("gold", 0)):
_show_toast("金豆不足")
return
_set_busy(true)
_set_texture_button_enabled(_button, false)
var result: Dictionary = await _activity_api.lottery(_token())
_set_busy(false)
if not result.get("ok", false):
_set_texture_button_enabled(_button, true)
_show_toast(_response_status_text(result, "抽奖失败"))
return
var data = _response_data(result, {})
var reward_id := int(data.get("id", 1)) if data is Dictionary else 1
if data is Dictionary:
player["lottery_count"] = int(data.get("count", int(player.get("lottery_count", 0)) + 1))
player["gold"] = maxi(int(player.get("gold", 0)) - cost, 0)
_render_player()
await _play_effect(reward_id - 1)
var reward_config := _find_config_by_id(_game_config.get_lottery_config(), reward_id)
if not reward_config.is_empty():
var reward_text := "%s:%s" % [int(reward_config.get("item_id", reward_config.get("value", 0))), int(reward_config.get("count", 1))]
_add_reward_items(reward_text)
_show_toast("抽中 %s" % _format_reward_text(reward_text))
_set_texture_button_enabled(_button, true)
func _play_effect(target_index: int) -> void:
if _panel == null:
return
var cards: Array[Control] = []
for index in range(14):
var card := _panel.get_node_or_null("LotteryCard%s" % index) as Control
if card != null:
cards.append(card)
if cards.is_empty():
return
for round_index in range(34 + target_index):
var selected := round_index % cards.size()
for index in range(cards.size()):
cards[index].modulate = Color(1.25, 1.25, 1.25, 1.0) if index == selected else Color.WHITE
if _light != null:
_light.visible = true
_light.position = cards[selected].position - Vector2(18.0, 18.0)
if _owner != null:
await _owner.get_tree().create_timer(0.035 + minf(float(round_index) * 0.002, 0.06)).timeout