前几天忘了上传了上传一下
This commit is contained in:
534
Script/BigPanel/CropStorePanel.gd
Normal file
534
Script/BigPanel/CropStorePanel.gd
Normal file
@@ -0,0 +1,534 @@
|
||||
extends Panel
|
||||
|
||||
#种子商店面板
|
||||
#种子商店格子
|
||||
@onready var crop_grid_container : GridContainer = $ScrollContainer/Crop_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
@onready var refresh_button : Button = $RefreshButton
|
||||
|
||||
#各种排序过滤按钮
|
||||
@onready var sort_all_button : Button = $SortContainer/Sort_All#全部
|
||||
@onready var sort_common_button : Button = $SortContainer/Sort_Common#普通
|
||||
@onready var sort_superior_button : Button = $SortContainer/Sort_Superior#优良
|
||||
@onready var sort_rare_button : Button = $SortContainer/Sort_Rare#稀有
|
||||
@onready var sort_epic_button : Button = $SortContainer/Sort_Epic#史诗
|
||||
@onready var sort_legendary_button : Button = $SortContainer/Sort_Legendary#传奇
|
||||
@onready var sort_price_button : Button = $SortContainer/Sort_Price#价格
|
||||
@onready var sort_growtime_button : Button = $SortContainer/Sort_GrowTime#生长时间
|
||||
@onready var sort_profit_button : Button = $SortContainer/Sort_Profit#收益
|
||||
@onready var sort_level_button : Button = $SortContainer/Sort_Level#等级
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
@onready var batch_buy_popup: PanelContainer = $'../../DiaLog/BatchBuyPopup'
|
||||
|
||||
|
||||
|
||||
# 作物图片缓存(复用主游戏的缓存系统)
|
||||
var crop_textures_cache : Dictionary = {}
|
||||
var crop_frame_counts : Dictionary = {}
|
||||
|
||||
# 当前过滤和排序设置
|
||||
var current_filter_quality = ""
|
||||
var current_sort_key = ""
|
||||
var current_sort_ascending = true
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接按钮信号
|
||||
_connect_buttons()
|
||||
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
# 面板显示时的处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
# 面板显示时自动刷新数据
|
||||
init_store()
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
|
||||
# 连接所有按钮信号
|
||||
func _connect_buttons():
|
||||
# 关闭按钮
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
|
||||
# 过滤按钮
|
||||
sort_all_button.pressed.connect(func(): _filter_by_quality(""))
|
||||
sort_common_button.pressed.connect(func(): _filter_by_quality("普通"))
|
||||
sort_superior_button.pressed.connect(func(): _filter_by_quality("优良"))
|
||||
sort_rare_button.pressed.connect(func(): _filter_by_quality("稀有"))
|
||||
sort_epic_button.pressed.connect(func(): _filter_by_quality("史诗"))
|
||||
sort_legendary_button.pressed.connect(func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 排序按钮
|
||||
sort_price_button.pressed.connect(func(): _sort_by("花费"))
|
||||
sort_growtime_button.pressed.connect(func(): _sort_by("生长时间"))
|
||||
sort_profit_button.pressed.connect(func(): _sort_by("收益"))
|
||||
sort_level_button.pressed.connect(func(): _sort_by("等级"))
|
||||
|
||||
# 初始化商店
|
||||
func init_store():
|
||||
|
||||
# 清空已有的作物按钮
|
||||
for child in crop_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 遍历可种植的作物数据并添加到商店
|
||||
for crop_name in main_game.can_planted_crop:
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查是否可以购买
|
||||
if not crop.get("能否购买", true):
|
||||
continue
|
||||
|
||||
# 只显示当前等级可以种植的作物
|
||||
if crop["等级"] <= main_game.level:
|
||||
var store_btn = _create_store_button(crop_name, crop["品质"])
|
||||
crop_grid_container.add_child(store_btn)
|
||||
|
||||
print("商店初始化完成,共添加按钮: " + str(crop_grid_container.get_child_count()) + "个")
|
||||
|
||||
# 更新金钱显示
|
||||
_update_money_display()
|
||||
|
||||
# 创建商店按钮
|
||||
func _create_store_button(crop_name: String, crop_quality: String) -> Button:
|
||||
# 根据品质选择相应的按钮
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 设置按钮文本,显示价格
|
||||
button.text = str(crop_quality + "-" + crop_name + "\n价格: ¥" + str(crop["花费"]))
|
||||
|
||||
# 将成熟时间从秒转换为天时分秒格式
|
||||
var total_seconds = int(crop["生长时间"])
|
||||
|
||||
# 定义时间单位换算
|
||||
var SECONDS_PER_MINUTE = 60
|
||||
var SECONDS_PER_HOUR = 3600
|
||||
var SECONDS_PER_DAY = 86400
|
||||
|
||||
# 计算各时间单位
|
||||
var days = total_seconds / SECONDS_PER_DAY
|
||||
total_seconds %= SECONDS_PER_DAY
|
||||
|
||||
var hours = total_seconds / SECONDS_PER_HOUR
|
||||
total_seconds %= SECONDS_PER_HOUR
|
||||
|
||||
var minutes = total_seconds / SECONDS_PER_MINUTE
|
||||
var seconds = total_seconds % SECONDS_PER_MINUTE
|
||||
|
||||
# 构建时间字符串(只显示有值的单位)
|
||||
var time_str = ""
|
||||
if days > 0:
|
||||
time_str += str(days) + "天"
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
button.tooltip_text = str(
|
||||
"作物: " + crop_name + "\n" +
|
||||
"品质: " + crop_quality + "\n" +
|
||||
"价格: " + str(crop["花费"]) + "元\n" +
|
||||
"成熟时间: " + time_str + "\n" +
|
||||
"收获收益: " + str(crop["收益"]) + "元\n" +
|
||||
"需求等级: " + str(crop["等级"]) + "\n" +
|
||||
"耐候性: " + str(crop["耐候性"]) + "\n" +
|
||||
"经验: " + str(crop["经验"]) + "点\n" +
|
||||
"描述: " + str(crop["描述"])
|
||||
)
|
||||
|
||||
# 添加按钮事件
|
||||
button.pressed.connect(func(): _on_store_buy_pressed(crop_name))
|
||||
|
||||
# 更新按钮的作物图片
|
||||
_update_button_crop_image(button, crop_name)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button.get_node("Title").modulate = Color.HONEYDEW#白色
|
||||
"优良":
|
||||
button.get_node("Title").modulate =Color.DODGER_BLUE#深蓝色
|
||||
"稀有":
|
||||
button.get_node("Title").modulate =Color.HOT_PINK#品红色
|
||||
"史诗":
|
||||
button.get_node("Title").modulate =Color.YELLOW#黄色
|
||||
"传奇":
|
||||
button.get_node("Title").modulate =Color.ORANGE_RED#红色
|
||||
|
||||
return button
|
||||
|
||||
# 购买种子事件处理
|
||||
func _on_store_buy_pressed(crop_name: String):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查等级要求
|
||||
if main_game.level < crop["等级"]:
|
||||
Toast.show("等级不足,无法购买此种子", Color.RED)
|
||||
return
|
||||
|
||||
# 检查金钱是否足够(至少能买1个)
|
||||
if main_game.money < crop["花费"]:
|
||||
Toast.show("金钱不足,无法购买种子", Color.RED)
|
||||
return
|
||||
|
||||
# 显示批量购买弹窗
|
||||
if batch_buy_popup:
|
||||
var crop_desc = crop.get("描述", "暂无描述")
|
||||
batch_buy_popup.show_buy_popup(
|
||||
crop_name,
|
||||
crop["花费"],
|
||||
crop_desc,
|
||||
"seed",
|
||||
_on_confirm_buy_seed,
|
||||
_on_cancel_buy_seed
|
||||
)
|
||||
else:
|
||||
print("批量购买弹窗未找到")
|
||||
|
||||
# 确认购买种子回调
|
||||
func _on_confirm_buy_seed(crop_name: String, unit_cost: int, quantity: int, buy_type: String):
|
||||
var total_cost = unit_cost * quantity
|
||||
|
||||
# 再次检查金钱是否足够
|
||||
if main_game.money < total_cost:
|
||||
Toast.show("金钱不足!需要 " + str(total_cost) + " 元,当前只有 " + str(main_game.money) + " 元", Color.RED, 3.0, 1.0)
|
||||
return
|
||||
|
||||
# 发送批量购买请求到服务器
|
||||
_send_batch_buy_seed_request(crop_name, quantity)
|
||||
|
||||
# 取消购买种子回调
|
||||
func _on_cancel_buy_seed():
|
||||
print("取消购买种子")
|
||||
|
||||
# 发送批量购买种子请求
|
||||
func _send_batch_buy_seed_request(crop_name: String, quantity: int):
|
||||
# 发送批量购买请求到服务器
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.sendBuySeed(crop_name, quantity):
|
||||
# 服务器会处理批量购买逻辑,客户端等待响应
|
||||
print("已发送批量购买种子请求:", crop_name, " 数量:", quantity)
|
||||
else:
|
||||
Toast.show("购买请求发送失败", Color.RED, 2.0, 1.0)
|
||||
|
||||
|
||||
# 按品质过滤作物
|
||||
func _filter_by_quality(quality: String):
|
||||
current_filter_quality = quality
|
||||
_apply_filter_and_sort()
|
||||
|
||||
# 按指定键排序
|
||||
func _sort_by(sort_key: String):
|
||||
# 切换排序方向或设置新排序键
|
||||
if current_sort_key == sort_key:
|
||||
current_sort_ascending = !current_sort_ascending
|
||||
else:
|
||||
current_sort_key = sort_key
|
||||
current_sort_ascending = true
|
||||
|
||||
_apply_filter_and_sort()
|
||||
|
||||
# 应用过滤和排序
|
||||
func _apply_filter_and_sort():
|
||||
# 清空现有按钮
|
||||
for child in crop_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 收集符合条件的作物
|
||||
var filtered_crops = []
|
||||
for crop_name in main_game.can_planted_crop:
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查是否可以购买
|
||||
if not crop.get("能否购买", true):
|
||||
continue
|
||||
|
||||
# 检查等级和品质过滤
|
||||
if crop["等级"] > main_game.level:
|
||||
continue
|
||||
|
||||
if current_filter_quality != "" and crop["品质"] != current_filter_quality:
|
||||
continue
|
||||
|
||||
# 添加到过滤后的列表
|
||||
filtered_crops.append({
|
||||
"name": crop_name,
|
||||
"data": crop
|
||||
})
|
||||
|
||||
# 如果有排序条件,进行排序
|
||||
if current_sort_key != "":
|
||||
filtered_crops.sort_custom(Callable(self, "_sort_crop_items"))
|
||||
|
||||
# 添加所有过滤和排序后的作物
|
||||
for crop in filtered_crops:
|
||||
var store_btn = _create_store_button(crop["name"], crop["data"]["品质"])
|
||||
crop_grid_container.add_child(store_btn)
|
||||
|
||||
# 更新金钱显示
|
||||
_update_money_display()
|
||||
|
||||
# 自定义排序函数
|
||||
func _sort_crop_items(a, b):
|
||||
if current_sort_ascending:
|
||||
return a["data"][current_sort_key] < b["data"][current_sort_key]
|
||||
else:
|
||||
return a["data"][current_sort_key] > b["data"][current_sort_key]
|
||||
|
||||
# 更新金钱显示
|
||||
func _update_money_display():
|
||||
var money_label = get_node_or_null("MoneyLabel")
|
||||
if money_label == null:
|
||||
# 创建金钱显示标签
|
||||
money_label = Label.new()
|
||||
money_label.name = "MoneyLabel"
|
||||
money_label.position = Vector2(10, 10)
|
||||
money_label.size = Vector2(300, 45)
|
||||
|
||||
# 设置标签样式
|
||||
money_label.add_theme_color_override("font_color", Color(1, 0.647, 0, 1)) # 橙色
|
||||
money_label.add_theme_font_size_override("font_size", 24)
|
||||
|
||||
add_child(money_label)
|
||||
|
||||
# 更新金钱显示
|
||||
money_label.text = "当前金钱:" + str(main_game.money) + " 元"
|
||||
|
||||
# 刷新商店内容,可以在金钱变化或等级提升后调用
|
||||
func refresh_store():
|
||||
# 清空并重新创建商店按钮
|
||||
init_store()
|
||||
# 尝试创建过滤按钮(如果商店面板中没有这些按钮)
|
||||
_create_filter_buttons_if_needed()
|
||||
|
||||
# 如果需要,动态创建过滤按钮
|
||||
func _create_filter_buttons_if_needed():
|
||||
# 检查是否已存在过滤器容器
|
||||
var filter_container = get_node_or_null("FilterContainer")
|
||||
if filter_container == null:
|
||||
# 创建过滤器容器
|
||||
filter_container = HBoxContainer.new()
|
||||
filter_container.name = "FilterContainer"
|
||||
|
||||
# 设置容器位置和大小
|
||||
filter_container.position = Vector2(320, 10)
|
||||
filter_container.size = Vector2(770, 45)
|
||||
|
||||
add_child(filter_container)
|
||||
|
||||
# 添加过滤按钮
|
||||
_add_filter_button(filter_container, "全部", func(): _filter_by_quality(""))
|
||||
_add_filter_button(filter_container, "普通", func(): _filter_by_quality("普通"))
|
||||
_add_filter_button(filter_container, "优良", func(): _filter_by_quality("优良"))
|
||||
_add_filter_button(filter_container, "稀有", func(): _filter_by_quality("稀有"))
|
||||
_add_filter_button(filter_container, "史诗", func(): _filter_by_quality("史诗"))
|
||||
_add_filter_button(filter_container, "传奇", func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 检查是否已存在排序容器
|
||||
var sort_container = get_node_or_null("SortContainer")
|
||||
if sort_container == null:
|
||||
# 创建排序容器
|
||||
sort_container = HBoxContainer.new()
|
||||
sort_container.name = "SortContainer"
|
||||
|
||||
# 设置容器位置和大小
|
||||
sort_container.position = Vector2(320, 55)
|
||||
sort_container.size = Vector2(770, 30)
|
||||
|
||||
add_child(sort_container)
|
||||
|
||||
# 添加排序按钮
|
||||
_add_filter_button(sort_container, "按价格", func(): _sort_by("花费"))
|
||||
_add_filter_button(sort_container, "按生长时间", func(): _sort_by("生长时间"))
|
||||
_add_filter_button(sort_container, "按收益", func(): _sort_by("收益"))
|
||||
_add_filter_button(sort_container, "按等级", func(): _sort_by("等级"))
|
||||
|
||||
# 添加过滤按钮
|
||||
func _add_filter_button(container, text, callback):
|
||||
var button = Button.new()
|
||||
button.text = text
|
||||
button.custom_minimum_size = Vector2(100, 0)
|
||||
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
container.add_child(button)
|
||||
button.pressed.connect(callback)
|
||||
|
||||
# 获取作物的成熟图片(用于商店显示)
|
||||
func _get_crop_final_texture(crop_name: String) -> Texture2D:
|
||||
# 优先从主游戏的缓存中获取成熟图片
|
||||
if main_game and main_game.crop_mature_textures_cache.has(crop_name):
|
||||
return main_game.crop_mature_textures_cache[crop_name]
|
||||
|
||||
# 如果缓存中没有,再尝试加载"成熟.webp"图片
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var mature_texture_path = crop_path + "成熟.webp"
|
||||
|
||||
if ResourceLoader.exists(mature_texture_path):
|
||||
var texture = load(mature_texture_path)
|
||||
if texture:
|
||||
print("商店加载作物成熟图片:", crop_name)
|
||||
# 如果主游戏存在,也缓存到主游戏中
|
||||
if main_game:
|
||||
main_game.crop_mature_textures_cache[crop_name] = texture
|
||||
return texture
|
||||
|
||||
# 如果没有找到作物的成熟图片,使用默认的成熟图片
|
||||
if main_game and main_game.crop_mature_textures_cache.has("默认"):
|
||||
var default_texture = main_game.crop_mature_textures_cache["默认"]
|
||||
# 缓存给这个作物
|
||||
main_game.crop_mature_textures_cache[crop_name] = default_texture
|
||||
return default_texture
|
||||
|
||||
# 最后尝试直接加载默认成熟图片
|
||||
var default_mature_path = "res://assets/作物/默认/成熟.webp"
|
||||
if ResourceLoader.exists(default_mature_path):
|
||||
var texture = load(default_mature_path)
|
||||
if texture:
|
||||
print("商店使用默认成熟图片:", crop_name)
|
||||
# 缓存到主游戏
|
||||
if main_game:
|
||||
main_game.crop_mature_textures_cache["默认"] = texture
|
||||
main_game.crop_mature_textures_cache[crop_name] = texture
|
||||
return texture
|
||||
|
||||
return null
|
||||
|
||||
# 加载作物图片序列帧(复用主游戏的逻辑)
|
||||
func _load_crop_textures(crop_name: String) -> Array:
|
||||
if crop_textures_cache.has(crop_name):
|
||||
return crop_textures_cache[crop_name]
|
||||
|
||||
var textures = []
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 检查作物文件夹是否存在
|
||||
if DirAccess.dir_exists_absolute(crop_path):
|
||||
# 尝试加载作物的序列帧(从0开始)
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = crop_path + str(frame_index) + ".webp"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
if textures.size() > 0:
|
||||
pass
|
||||
else:
|
||||
textures = _load_default_textures()
|
||||
else:
|
||||
print("商店:作物 ", crop_name, " 的文件夹不存在,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
|
||||
# 缓存结果
|
||||
crop_textures_cache[crop_name] = textures
|
||||
crop_frame_counts[crop_name] = textures.size()
|
||||
|
||||
return textures
|
||||
|
||||
# 加载默认图片
|
||||
func _load_default_textures() -> Array:
|
||||
if crop_textures_cache.has("默认"):
|
||||
return crop_textures_cache["默认"]
|
||||
|
||||
var textures = []
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 尝试加载默认图片序列帧
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = default_path + str(frame_index) + ".webp"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
# 如果没有找到序列帧,尝试加载单个默认图片
|
||||
if textures.size() == 0:
|
||||
var single_texture_path = default_path + "0.webp"
|
||||
if ResourceLoader.exists(single_texture_path):
|
||||
var texture = load(single_texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
|
||||
# 缓存默认图片
|
||||
crop_textures_cache["默认"] = textures
|
||||
crop_frame_counts["默认"] = textures.size()
|
||||
|
||||
return textures
|
||||
|
||||
# 更新按钮的作物图片
|
||||
func _update_button_crop_image(button: Button, crop_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var crop_image = button.get_node_or_null("CropImage")
|
||||
if not crop_image:
|
||||
print("商店按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 获取作物的最后一帧图片
|
||||
var texture = _get_crop_final_texture(crop_name)
|
||||
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
crop_image.texture = texture
|
||||
crop_image.visible = true
|
||||
print("商店更新作物图片:", crop_name)
|
||||
else:
|
||||
crop_image.visible = false
|
||||
print("商店无法获取作物图片:", crop_name)
|
||||
|
||||
# 兼容MainGame.gd中的调用,转发到_on_store_buy_pressed
|
||||
func _on_crop_selected(crop_name: String):
|
||||
_on_store_buy_pressed(crop_name)
|
||||
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
#手动刷新种子商店面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 重新初始化种子商店
|
||||
init_store()
|
||||
Toast.show("种子商店已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
#关闭种子商店面板
|
||||
func _on_quit_button_pressed():
|
||||
self.hide()
|
||||
#=========================面板通用处理=========================
|
||||
1
Script/BigPanel/CropStorePanel.gd.uid
Normal file
1
Script/BigPanel/CropStorePanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://mtfp0ct42nrx
|
||||
531
Script/BigPanel/CropWarehousePanel.gd
Normal file
531
Script/BigPanel/CropWarehousePanel.gd
Normal file
@@ -0,0 +1,531 @@
|
||||
extends Panel
|
||||
#这是作物仓库面板 用来显示玩家收获的作物的成熟品 比如各种果实和花朵
|
||||
|
||||
# 作物仓库格子容器
|
||||
@onready var crop_warehouse_grid_container : GridContainer = $ScrollContainer/Warehouse_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
@onready var refresh_button : Button = $RefreshButton
|
||||
|
||||
#各种排序过滤按钮
|
||||
@onready var sort_all_button : Button = $SortContainer/Sort_All#全部
|
||||
@onready var sort_common_button : Button = $SortContainer/Sort_Common#普通
|
||||
@onready var sort_superior_button : Button = $SortContainer/Sort_Superior#优良
|
||||
@onready var sort_rare_button : Button = $SortContainer/Sort_Rare#稀有
|
||||
@onready var sort_epic_button : Button = $SortContainer/Sort_Epic#史诗
|
||||
@onready var sort_legendary_button : Button = $SortContainer/Sort_Legendary#传奇
|
||||
@onready var sort_price_button : Button = $SortContainer/Sort_Price#价格
|
||||
@onready var sort_growtime_button : Button = $SortContainer/Sort_GrowTime#生长时间
|
||||
@onready var sort_profit_button : Button = $SortContainer/Sort_Profit#收益
|
||||
@onready var sort_level_button : Button = $SortContainer/Sort_Level#等级
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
|
||||
|
||||
# 作物图片缓存(复用主游戏的缓存系统)
|
||||
var crop_textures_cache : Dictionary = {}
|
||||
var crop_frame_counts : Dictionary = {}
|
||||
|
||||
# 当前过滤和排序设置
|
||||
var current_filter_quality = ""
|
||||
var current_sort_key = ""
|
||||
var current_sort_ascending = true
|
||||
|
||||
# 宠物喂食模式相关变量
|
||||
var is_pet_feeding_mode = false
|
||||
var current_pet_data = {}
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接按钮信号
|
||||
_connect_buttons()
|
||||
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
|
||||
# 连接所有按钮信号
|
||||
func _connect_buttons():
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
refresh_button.pressed.connect(self._on_refresh_button_pressed)
|
||||
|
||||
# 过滤按钮
|
||||
sort_all_button.pressed.connect(func(): _filter_by_quality(""))
|
||||
sort_common_button.pressed.connect(func(): _filter_by_quality("普通"))
|
||||
sort_superior_button.pressed.connect(func(): _filter_by_quality("优良"))
|
||||
sort_rare_button.pressed.connect(func(): _filter_by_quality("稀有"))
|
||||
sort_epic_button.pressed.connect(func(): _filter_by_quality("史诗"))
|
||||
sort_legendary_button.pressed.connect(func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 排序按钮
|
||||
sort_price_button.pressed.connect(func(): _sort_by("花费"))
|
||||
sort_growtime_button.pressed.connect(func(): _sort_by("生长时间"))
|
||||
sort_profit_button.pressed.connect(func(): _sort_by("收益"))
|
||||
sort_level_button.pressed.connect(func(): _sort_by("等级"))
|
||||
|
||||
# 设置宠物喂食模式
|
||||
func set_pet_feeding_mode(feeding_mode: bool, pet_data: Dictionary = {}):
|
||||
is_pet_feeding_mode = feeding_mode
|
||||
current_pet_data = pet_data
|
||||
|
||||
# 更新UI以反映当前模式
|
||||
if is_pet_feeding_mode:
|
||||
# 宠物喂食模式下,只显示有喂养效果的作物
|
||||
var pet_name = pet_data.get("基本信息", {}).get("宠物名称", "未知宠物")
|
||||
Toast.show("宠物喂食模式:选择要喂给 " + pet_name + " 的作物", Color.CYAN, 3.0, 1.0)
|
||||
else:
|
||||
# 普通模式
|
||||
Toast.show("普通模式:查看作物仓库", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
# 刷新UI
|
||||
update_crop_warehouse_ui()
|
||||
|
||||
# 初始化作物仓库
|
||||
func init_crop_warehouse():
|
||||
# 清空作物仓库格子
|
||||
for child in crop_warehouse_grid_container.get_children():
|
||||
child.queue_free()
|
||||
# 显示仓库中的成熟物
|
||||
update_crop_warehouse_ui()
|
||||
|
||||
# 更新作物仓库UI
|
||||
func update_crop_warehouse_ui():
|
||||
# 清空作物仓库格子
|
||||
for child in crop_warehouse_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 应用过滤和排序
|
||||
var filtered_crops = _get_filtered_and_sorted_crops()
|
||||
|
||||
# 为仓库中的每个过滤后的成熟物创建按钮
|
||||
for crop_item in filtered_crops:
|
||||
var crop_name = crop_item["name"]
|
||||
var crop_quality = crop_item.get("quality", "普通")
|
||||
var crop_count = crop_item["count"]
|
||||
# 创建成熟物按钮
|
||||
var button = _create_crop_button(crop_name, crop_quality)
|
||||
|
||||
# 更新按钮文本显示数量
|
||||
if is_pet_feeding_mode:
|
||||
# 宠物喂食模式下显示喂养效果
|
||||
var crop_data = main_game.can_planted_crop.get(crop_name, {})
|
||||
var feed_effects = crop_data.get("喂养效果", {})
|
||||
|
||||
# 构建效果描述
|
||||
var effect_descriptions = []
|
||||
for effect_name in feed_effects:
|
||||
var effect_value = feed_effects[effect_name]
|
||||
if effect_value > 0:
|
||||
effect_descriptions.append(effect_name + "+" + str(effect_value))
|
||||
|
||||
var effect_text = " ".join(effect_descriptions) if effect_descriptions.size() > 0 else "无效果"
|
||||
button.text = str(crop_quality + "-" + crop_name + "\n数量:" + str(crop_count) )
|
||||
button.pressed.connect(func(): _on_crop_feed_selected(crop_name, crop_count))
|
||||
else:
|
||||
button.text = str(crop_quality + "-" + crop_name + "\n数量:" + str(crop_count))
|
||||
button.pressed.connect(func(): _on_crop_selected(crop_name, crop_count))
|
||||
|
||||
crop_warehouse_grid_container.add_child(button)
|
||||
print("作物仓库初始化完成,共添加按钮: " + str(crop_warehouse_grid_container.get_child_count()) + "个")
|
||||
|
||||
# 获取过滤和排序后的成熟物列表
|
||||
func _get_filtered_and_sorted_crops():
|
||||
var filtered_crops = []
|
||||
|
||||
# 收集符合条件的成熟物
|
||||
for crop_item in main_game.crop_warehouse:
|
||||
# 安全获取品质字段(兼容老数据)
|
||||
var item_quality = crop_item.get("quality", "普通")
|
||||
|
||||
# 品质过滤
|
||||
if current_filter_quality != "" and item_quality != current_filter_quality:
|
||||
continue
|
||||
|
||||
# 获取成熟物对应的作物数据
|
||||
var crop_data = null
|
||||
if main_game.can_planted_crop.has(crop_item["name"]):
|
||||
crop_data = main_game.can_planted_crop[crop_item["name"]]
|
||||
|
||||
# 宠物喂食模式过滤:只显示有喂养效果的作物
|
||||
if is_pet_feeding_mode:
|
||||
if crop_data == null or not crop_data.has("喂养效果"):
|
||||
continue
|
||||
|
||||
# 添加到过滤后的列表
|
||||
filtered_crops.append({
|
||||
"name": crop_item["name"],
|
||||
"quality": item_quality,
|
||||
"count": crop_item["count"],
|
||||
"data": crop_data
|
||||
})
|
||||
|
||||
# 如果有排序条件且数据可用,进行排序
|
||||
if current_sort_key != "":
|
||||
filtered_crops.sort_custom(Callable(self, "_sort_crop_items"))
|
||||
|
||||
return filtered_crops
|
||||
|
||||
# 自定义排序函数
|
||||
func _sort_crop_items(a, b):
|
||||
# 检查是否有有效数据用于排序
|
||||
if a["data"] == null or b["data"] == null:
|
||||
# 如果某一项没有数据,将其排在后面
|
||||
if a["data"] == null and b["data"] != null:
|
||||
return false
|
||||
if a["data"] != null and b["data"] == null:
|
||||
return true
|
||||
# 如果都没有数据,按名称排序
|
||||
return a["name"] < b["name"]
|
||||
|
||||
# 确保排序键存在于数据中
|
||||
if !a["data"].has(current_sort_key) or !b["data"].has(current_sort_key):
|
||||
print("警告: 排序键 ", current_sort_key, " 在某些成熟物数据中不存在")
|
||||
return false
|
||||
|
||||
# 执行排序
|
||||
if current_sort_ascending:
|
||||
return a["data"][current_sort_key] < b["data"][current_sort_key]
|
||||
else:
|
||||
return a["data"][current_sort_key] > b["data"][current_sort_key]
|
||||
|
||||
# 按品质过滤成熟物
|
||||
func _filter_by_quality(quality: String):
|
||||
current_filter_quality = quality
|
||||
update_crop_warehouse_ui()
|
||||
|
||||
# 按指定键排序
|
||||
func _sort_by(sort_key: String):
|
||||
# 切换排序方向或设置新排序键
|
||||
if current_sort_key == sort_key:
|
||||
current_sort_ascending = !current_sort_ascending
|
||||
else:
|
||||
current_sort_key = sort_key
|
||||
current_sort_ascending = true
|
||||
|
||||
update_crop_warehouse_ui()
|
||||
|
||||
# 创建作物按钮
|
||||
func _create_crop_button(crop_name: String, crop_quality: String) -> Button:
|
||||
# 根据品质选择相应的进度条
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 设置按钮文本
|
||||
button.text = str(crop_quality + "-" + crop_name)
|
||||
|
||||
# 添加工具提示 (tooltip)
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 将成熟时间从秒转换为天时分秒格式
|
||||
var total_seconds = int(crop["生长时间"])
|
||||
|
||||
# 定义时间单位换算
|
||||
var SECONDS_PER_MINUTE = 60
|
||||
var SECONDS_PER_HOUR = 3600
|
||||
var SECONDS_PER_DAY = 86400
|
||||
|
||||
# 计算各时间单位
|
||||
var days = total_seconds / SECONDS_PER_DAY
|
||||
total_seconds %= SECONDS_PER_DAY
|
||||
|
||||
var hours = total_seconds / SECONDS_PER_HOUR
|
||||
total_seconds %= SECONDS_PER_HOUR
|
||||
|
||||
var minutes = total_seconds / SECONDS_PER_MINUTE
|
||||
var seconds = total_seconds % SECONDS_PER_MINUTE
|
||||
|
||||
# 构建时间字符串(只显示有值的单位)
|
||||
var time_str = ""
|
||||
if days > 0:
|
||||
time_str += str(days) + "天"
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
button.tooltip_text = str(
|
||||
"作物: " + crop_name + "\n" +
|
||||
"品质: " + crop_quality + "\n" +
|
||||
"原价格: " + str(crop["花费"]) + "元\n" +
|
||||
"成熟时间: " + time_str + "\n" +
|
||||
"原收益: " + str(crop["收益"]) + "元\n" +
|
||||
"需求等级: " + str(crop["等级"]) + "\n" +
|
||||
"耐候性: " + str(crop["耐候性"]) + "\n" +
|
||||
"经验: " + str(crop["经验"]) + "点\n" +
|
||||
"描述: " + str(crop["描述"])
|
||||
)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").text = crop_quality
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button.get_node("Title").modulate = Color.HONEYDEW#白色
|
||||
"优良":
|
||||
button.get_node("Title").modulate =Color.DODGER_BLUE#深蓝色
|
||||
"稀有":
|
||||
button.get_node("Title").modulate =Color.HOT_PINK#品红色
|
||||
"史诗":
|
||||
button.get_node("Title").modulate =Color.YELLOW#黄色
|
||||
"传奇":
|
||||
button.get_node("Title").modulate =Color.ORANGE_RED#红色
|
||||
|
||||
# 更新按钮的作物图片(使用收获物.webp)
|
||||
_update_button_crop_image(button, crop_name)
|
||||
|
||||
return button
|
||||
|
||||
# 正常模式下的成熟物点击处理
|
||||
func _on_crop_selected(crop_name, crop_count):
|
||||
# 显示成熟物信息
|
||||
var info_text = ""
|
||||
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
var quality = crop.get("品质", "未知")
|
||||
var price = crop.get("花费", 0)
|
||||
var grow_time = crop.get("生长时间", 0)
|
||||
var profit = crop.get("收益", 0)
|
||||
var level_req = crop.get("等级", 1)
|
||||
|
||||
# 将成熟时间转换为可读格式
|
||||
var time_str = ""
|
||||
var total_seconds = int(grow_time)
|
||||
var hours = total_seconds / 3600
|
||||
var minutes = (total_seconds % 3600) / 60
|
||||
var seconds = total_seconds % 60
|
||||
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
info_text = quality + "-" + crop_name + " (数量: " + str(crop_count) + ")\n"
|
||||
info_text += "原价格: " + str(price) + "元, 原收益: " + str(profit) + "元\n"
|
||||
info_text += "成熟时间: " + time_str + ", 需求等级: " + str(level_req) + "\n"
|
||||
info_text += "这是收获的成熟品,可以用于出售或其他用途"
|
||||
else:
|
||||
info_text = crop_name + " (数量: " + str(crop_count) + ")"
|
||||
|
||||
Toast.show(info_text, Color.GOLD, 3.0, 1.0)
|
||||
|
||||
# 访问模式下的成熟物点击处理
|
||||
func _on_visit_crop_selected(crop_name, crop_count):
|
||||
# 显示成熟物信息
|
||||
var info_text = ""
|
||||
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
var quality = crop.get("品质", "未知")
|
||||
var price = crop.get("花费", 0)
|
||||
var grow_time = crop.get("生长时间", 0)
|
||||
var profit = crop.get("收益", 0)
|
||||
var level_req = crop.get("等级", 1)
|
||||
|
||||
# 将成熟时间转换为可读格式
|
||||
var time_str = ""
|
||||
var total_seconds = int(grow_time)
|
||||
var hours = total_seconds / 3600
|
||||
var minutes = (total_seconds % 3600) / 60
|
||||
var seconds = total_seconds % 60
|
||||
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
info_text = quality + "-" + crop_name + " (数量: " + str(crop_count) + ")\n"
|
||||
info_text += "原价格: " + str(price) + "元, 原收益: " + str(profit) + "元\n"
|
||||
info_text += "成熟时间: " + time_str + ", 需求等级: " + str(level_req)
|
||||
else:
|
||||
info_text = crop_name + " (数量: " + str(crop_count) + ")"
|
||||
|
||||
Toast.show(info_text, Color.CYAN, 3.0, 1.0)
|
||||
|
||||
# 宠物喂食模式下的作物选择处理
|
||||
func _on_crop_feed_selected(crop_name: String, crop_count: int):
|
||||
if not is_pet_feeding_mode or current_pet_data.is_empty():
|
||||
Toast.show("当前不在宠物喂食模式", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 检查作物是否有喂养效果
|
||||
var crop_data = main_game.can_planted_crop.get(crop_name, {})
|
||||
if not crop_data.has("喂养效果"):
|
||||
Toast.show("该作物没有喂养效果", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 获取喂养效果
|
||||
var feed_effects = crop_data.get("喂养效果", {})
|
||||
|
||||
# 获取宠物信息
|
||||
var pet_name = current_pet_data.get("基本信息", {}).get("宠物名称", "未知宠物")
|
||||
var pet_id = current_pet_data.get("基本信息", {}).get("宠物ID", "")
|
||||
|
||||
if pet_id == "":
|
||||
Toast.show("宠物ID无效", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 构建效果描述
|
||||
var effect_descriptions = []
|
||||
for effect_name in feed_effects:
|
||||
var effect_value = feed_effects[effect_name]
|
||||
if effect_value > 0:
|
||||
effect_descriptions.append(effect_name + "+" + str(effect_value))
|
||||
|
||||
var effect_text = ",".join(effect_descriptions) if effect_descriptions.size() > 0 else "无效果"
|
||||
|
||||
# 显示确认对话框
|
||||
var confirm_text = str(
|
||||
"确认喂食 " + pet_name + " 吗?\n\n" +
|
||||
"作物:" + crop_name + "\n" +
|
||||
"效果:" + effect_text + "\n\n" +
|
||||
"确认后将消耗1个" + crop_name
|
||||
)
|
||||
|
||||
_show_feed_confirmation_dialog(confirm_text, crop_name, pet_id, feed_effects)
|
||||
|
||||
# 显示喂食确认对话框
|
||||
func _show_feed_confirmation_dialog(confirm_text: String, crop_name: String, pet_id: String, feed_effects: Dictionary):
|
||||
var confirm_dialog = AcceptDialog.new()
|
||||
confirm_dialog.dialog_text = confirm_text
|
||||
confirm_dialog.title = "宠物喂食确认"
|
||||
confirm_dialog.ok_button_text = "确认喂食"
|
||||
confirm_dialog.add_cancel_button("取消")
|
||||
|
||||
# 添加到场景
|
||||
add_child(confirm_dialog)
|
||||
|
||||
# 连接信号
|
||||
confirm_dialog.confirmed.connect(_on_confirm_feed_pet.bind(crop_name, pet_id, feed_effects, confirm_dialog))
|
||||
confirm_dialog.canceled.connect(_on_cancel_feed_pet.bind(confirm_dialog))
|
||||
|
||||
# 显示对话框
|
||||
confirm_dialog.popup_centered()
|
||||
|
||||
# 确认喂食宠物
|
||||
func _on_confirm_feed_pet(crop_name: String, pet_id: String, feed_effects: Dictionary, dialog: AcceptDialog):
|
||||
# 发送喂食请求到服务器
|
||||
_send_feed_pet_request(crop_name, pet_id, feed_effects)
|
||||
dialog.queue_free()
|
||||
|
||||
# 取消喂食宠物
|
||||
func _on_cancel_feed_pet(dialog: AcceptDialog):
|
||||
dialog.queue_free()
|
||||
|
||||
# 发送喂食宠物请求
|
||||
func _send_feed_pet_request(crop_name: String, pet_id: String, feed_effects: Dictionary):
|
||||
if not tcp_network_manager_panel or not tcp_network_manager_panel.has_method("send_message"):
|
||||
Toast.show("网络功能不可用", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 构建喂食请求消息
|
||||
var message = {
|
||||
"type": "feed_pet",
|
||||
"pet_id": pet_id,
|
||||
"crop_name": crop_name,
|
||||
"feed_effects": feed_effects
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
tcp_network_manager_panel.send_message(message)
|
||||
|
||||
# 退出喂食模式
|
||||
set_pet_feeding_mode(false)
|
||||
self.hide()
|
||||
|
||||
|
||||
|
||||
# 获取作物的收获物图片(用于仓库显示)
|
||||
func _get_crop_harvest_texture(crop_name: String) -> Texture2D:
|
||||
# 尝试加载"收获物.webp"图片
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var harvest_texture_path = crop_path + "收获物.webp"
|
||||
|
||||
if ResourceLoader.exists(harvest_texture_path):
|
||||
var texture = load(harvest_texture_path)
|
||||
if texture:
|
||||
print("仓库加载作物收获物图片:", crop_name)
|
||||
return texture
|
||||
|
||||
|
||||
# 如果都没有找到,使用默认的收获物图片
|
||||
var default_harvest_path = "res://assets/作物/默认/收获物.webp"
|
||||
if ResourceLoader.exists(default_harvest_path):
|
||||
var texture = load(default_harvest_path)
|
||||
if texture:
|
||||
print("仓库使用默认收获物图片:", crop_name)
|
||||
return texture
|
||||
|
||||
return null
|
||||
|
||||
# 更新按钮的作物图片
|
||||
func _update_button_crop_image(button: Button, crop_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var crop_image = button.get_node_or_null("CropImage")
|
||||
if not crop_image:
|
||||
print("仓库按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 获取作物的收获物图片
|
||||
var texture = _get_crop_harvest_texture(crop_name)
|
||||
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
crop_image.texture = texture
|
||||
crop_image.visible = true
|
||||
else:
|
||||
crop_image.visible = false
|
||||
print("仓库无法获取作物收获物图片:", crop_name)
|
||||
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
#手动刷新作物仓库面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 刷新作物仓库UI
|
||||
update_crop_warehouse_ui()
|
||||
Toast.show("作物仓库已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
# 关闭作物仓库面板
|
||||
func _on_quit_button_pressed():
|
||||
|
||||
# 如果是宠物喂食模式,退出该模式
|
||||
if is_pet_feeding_mode:
|
||||
set_pet_feeding_mode(false)
|
||||
|
||||
self.hide()
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
update_crop_warehouse_ui()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
1
Script/BigPanel/CropWarehousePanel.gd.uid
Normal file
1
Script/BigPanel/CropWarehousePanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ptdj0qmobihd
|
||||
440
Script/BigPanel/DailyCheckInPanel.gd
Normal file
440
Script/BigPanel/DailyCheckInPanel.gd
Normal file
@@ -0,0 +1,440 @@
|
||||
extends Panel
|
||||
class_name DailyCheckInPanel
|
||||
|
||||
## 每日签到系统 - 后端对接版本
|
||||
## 功能:与服务器对接的签到系统,支持实时数据同步
|
||||
## 奖励平衡性已根据 crop_data.json 调整
|
||||
|
||||
# =============================================================================
|
||||
# 信号定义 - 用于与后端系统通信
|
||||
# =============================================================================
|
||||
signal check_in_completed(rewards: Dictionary) # 签到完成信号
|
||||
signal reward_claimed(reward_type: String, amount: int) # 奖励领取信号
|
||||
signal check_in_data_loaded(data: Dictionary) # 签到数据加载完成信号
|
||||
signal check_in_failed(error_message: String) # 签到失败信号
|
||||
|
||||
# =============================================================================
|
||||
# 节点引用
|
||||
# =============================================================================
|
||||
@onready var daily_check_in_history: RichTextLabel = $Scroll/DailyCheckInHistory
|
||||
@onready var daily_check_in_reward: RichTextLabel = $DailyCheckInReward
|
||||
@onready var daily_check_in_button: Button = $DailyCheckInButton
|
||||
|
||||
# =============================================================================
|
||||
# 数据存储
|
||||
# =============================================================================
|
||||
var check_in_data: Dictionary = {}
|
||||
var today_date: String
|
||||
var consecutive_days: int = 0
|
||||
var has_checked_in_today: bool = false
|
||||
|
||||
# 网络管理器引用
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'.'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 奖励配置系统 - 根据 crop_data.json 平衡调整
|
||||
# =============================================================================
|
||||
var reward_configs: Dictionary = {
|
||||
"coins": {
|
||||
"min": 200,
|
||||
"max": 500,
|
||||
"name": "钱币",
|
||||
"color": "#FFD700",
|
||||
"icon": "💰"
|
||||
},
|
||||
"exp": {
|
||||
"min": 50,
|
||||
"max": 120,
|
||||
"name": "经验",
|
||||
"color": "#00BFFF",
|
||||
"icon": "⭐"
|
||||
},
|
||||
# 种子配置根据 crop_data.json 的作物等级和价值设定
|
||||
"seeds": {
|
||||
"普通": [
|
||||
{"name": "小麦", "color": "#F4A460", "icon": "🌱", "rarity_color": "#FFFFFF"},
|
||||
{"name": "胡萝卜", "color": "#FFA500", "icon": "🌱", "rarity_color": "#FFFFFF"},
|
||||
{"name": "土豆", "color": "#D2691E", "icon": "🌱", "rarity_color": "#FFFFFF"},
|
||||
{"name": "稻谷", "color": "#DAA520", "icon": "🌱", "rarity_color": "#FFFFFF"}
|
||||
],
|
||||
"优良": [
|
||||
{"name": "玉米", "color": "#FFD700", "icon": "🌱", "rarity_color": "#00FF00"},
|
||||
{"name": "番茄", "color": "#FF6347", "icon": "🌱", "rarity_color": "#00FF00"},
|
||||
{"name": "洋葱", "color": "#DDA0DD", "icon": "🌱", "rarity_color": "#00FF00"},
|
||||
{"name": "大豆", "color": "#8FBC8F", "icon": "🌱", "rarity_color": "#00FF00"},
|
||||
{"name": "豌豆", "color": "#90EE90", "icon": "🌱", "rarity_color": "#00FF00"},
|
||||
{"name": "黄瓜", "color": "#32CD32", "icon": "🌱", "rarity_color": "#00FF00"},
|
||||
{"name": "大白菜", "color": "#F0FFF0", "icon": "🌱", "rarity_color": "#00FF00"}
|
||||
],
|
||||
"稀有": [
|
||||
{"name": "草莓", "color": "#FF69B4", "icon": "🌱", "rarity_color": "#0080FF"},
|
||||
{"name": "花椰菜", "color": "#F5F5DC", "icon": "🌱", "rarity_color": "#0080FF"},
|
||||
{"name": "柿子", "color": "#FF4500", "icon": "🌱", "rarity_color": "#0080FF"},
|
||||
{"name": "蓝莓", "color": "#4169E1", "icon": "🌱", "rarity_color": "#0080FF"},
|
||||
{"name": "树莓", "color": "#DC143C", "icon": "🌱", "rarity_color": "#0080FF"}
|
||||
],
|
||||
"史诗": [
|
||||
{"name": "葡萄", "color": "#9370DB", "icon": "🌱", "rarity_color": "#8A2BE2"},
|
||||
{"name": "南瓜", "color": "#FF8C00", "icon": "🌱", "rarity_color": "#8A2BE2"},
|
||||
{"name": "芦笋", "color": "#9ACD32", "icon": "🌱", "rarity_color": "#8A2BE2"},
|
||||
{"name": "茄子", "color": "#9400D3", "icon": "🌱", "rarity_color": "#8A2BE2"},
|
||||
{"name": "向日葵", "color": "#FFD700", "icon": "🌱", "rarity_color": "#8A2BE2"},
|
||||
{"name": "蕨菜", "color": "#228B22", "icon": "🌱", "rarity_color": "#8A2BE2"}
|
||||
],
|
||||
"传奇": [
|
||||
{"name": "西瓜", "color": "#FF69B4", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "甘蔗", "color": "#DDA0DD", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "香草", "color": "#98FB98", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "甜菜", "color": "#DC143C", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "人参", "color": "#DAA520", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "富贵竹", "color": "#32CD32", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "芦荟", "color": "#9ACD32", "icon": "🌱", "rarity_color": "#FF8C00"},
|
||||
{"name": "哈密瓜", "color": "#FFB6C1", "icon": "🌱", "rarity_color": "#FF8C00"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# 系统初始化
|
||||
# =============================================================================
|
||||
func _ready() -> void:
|
||||
_initialize_system()
|
||||
|
||||
func _initialize_system() -> void:
|
||||
"""初始化签到系统"""
|
||||
daily_check_in_reward.hide()
|
||||
today_date = Time.get_date_string_from_system()
|
||||
|
||||
|
||||
|
||||
_update_display()
|
||||
_check_daily_status()
|
||||
|
||||
# 从服务器加载签到数据
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.is_connected_to_server():
|
||||
tcp_network_manager_panel.sendGetCheckInData()
|
||||
|
||||
# =============================================================================
|
||||
# 网络后端交互方法
|
||||
# =============================================================================
|
||||
|
||||
## 处理服务器签到响应
|
||||
func handle_daily_check_in_response(response: Dictionary) -> void:
|
||||
var success = response.get("success", false)
|
||||
var message = response.get("message", "")
|
||||
|
||||
if success:
|
||||
var rewards = response.get("rewards", {})
|
||||
consecutive_days = response.get("consecutive_days", 0)
|
||||
has_checked_in_today = true
|
||||
|
||||
# 显示奖励
|
||||
_show_reward_animation(rewards)
|
||||
|
||||
# 更新按钮状态
|
||||
_set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1))
|
||||
|
||||
# 发送完成信号
|
||||
check_in_completed.emit(rewards)
|
||||
|
||||
# 发送奖励信号
|
||||
for reward_type in rewards.keys():
|
||||
if reward_type == "seeds":
|
||||
for seed_reward in rewards.seeds:
|
||||
reward_claimed.emit("seed_" + seed_reward.name, seed_reward.quantity)
|
||||
elif reward_type in ["coins", "exp", "bonus_coins", "bonus_exp"]:
|
||||
reward_claimed.emit(reward_type, rewards[reward_type])
|
||||
|
||||
Toast.show(message, Color.GREEN)
|
||||
print("签到成功: ", message)
|
||||
else:
|
||||
has_checked_in_today = response.get("has_checked_in", false)
|
||||
_set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1)) if has_checked_in_today else _set_button_state(true, "签到", Color(1, 1, 0.52549, 1))
|
||||
check_in_failed.emit(message)
|
||||
Toast.show(message, Color.RED)
|
||||
print("签到失败: ", message)
|
||||
|
||||
## 处理服务器签到数据响应
|
||||
func handle_check_in_data_response(response: Dictionary) -> void:
|
||||
var success = response.get("success", false)
|
||||
|
||||
if success:
|
||||
check_in_data = response.get("check_in_data", {})
|
||||
consecutive_days = response.get("consecutive_days", 0)
|
||||
has_checked_in_today = response.get("has_checked_in_today", false)
|
||||
today_date = response.get("current_date", Time.get_date_string_from_system())
|
||||
|
||||
# 更新显示
|
||||
_update_display()
|
||||
_check_daily_status()
|
||||
|
||||
# 发送数据加载完成信号
|
||||
check_in_data_loaded.emit(check_in_data)
|
||||
|
||||
print("签到数据加载成功,连续签到:", consecutive_days, "天")
|
||||
else:
|
||||
print("加载签到数据失败")
|
||||
|
||||
# =============================================================================
|
||||
# 核心业务逻辑
|
||||
# =============================================================================
|
||||
|
||||
## 检查今日签到状态
|
||||
func _check_daily_status() -> void:
|
||||
if has_checked_in_today:
|
||||
_set_button_state(false, "已签到", Color(0.7, 0.7, 0.7, 1))
|
||||
else:
|
||||
_set_button_state(true, "签到", Color(1, 1, 0.52549, 1))
|
||||
|
||||
## 设置按钮状态
|
||||
func _set_button_state(enabled: bool, text: String, color: Color) -> void:
|
||||
daily_check_in_button.disabled = not enabled
|
||||
daily_check_in_button.text = text
|
||||
daily_check_in_button.modulate = color
|
||||
|
||||
## 执行签到
|
||||
func execute_check_in() -> void:
|
||||
if has_checked_in_today:
|
||||
Toast.show("今日已签到,请明日再来", Color.ORANGE)
|
||||
return
|
||||
|
||||
if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server():
|
||||
Toast.show("未连接到服务器,无法签到", Color.RED)
|
||||
return
|
||||
|
||||
# 发送签到请求到服务器
|
||||
tcp_network_manager_panel.sendDailyCheckIn()
|
||||
daily_check_in_button.disabled = true
|
||||
daily_check_in_button.text = "签到中..."
|
||||
|
||||
# 3秒后重新启用按钮(防止网络超时)
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
if daily_check_in_button.disabled and daily_check_in_button.text == "签到中...":
|
||||
daily_check_in_button.disabled = false
|
||||
daily_check_in_button.text = "签到"
|
||||
|
||||
## 显示奖励动画
|
||||
func _show_reward_animation(rewards: Dictionary) -> void:
|
||||
daily_check_in_reward.text = _format_reward_text(rewards)
|
||||
daily_check_in_reward.show()
|
||||
|
||||
# 创建动画效果
|
||||
var tween = create_tween()
|
||||
tween.parallel().tween_method(_animate_reward_display, 0.0, 1.0, 0.5)
|
||||
|
||||
## 奖励显示动画
|
||||
func _animate_reward_display(progress: float) -> void:
|
||||
daily_check_in_reward.modulate.a = progress
|
||||
var scale = 0.8 + (0.2 * progress)
|
||||
daily_check_in_reward.scale = Vector2(scale, scale)
|
||||
|
||||
# =============================================================================
|
||||
# UI显示格式化
|
||||
# =============================================================================
|
||||
|
||||
## 格式化奖励显示文本
|
||||
func _format_reward_text(rewards: Dictionary) -> String:
|
||||
var text = ""
|
||||
|
||||
# 显示连续签到信息
|
||||
text += "[center][color=#FF69B4]🔥 连续签到第%d天 🔥[/color][/center]\n" % consecutive_days
|
||||
if consecutive_days > 1:
|
||||
var multiplier = 1.0 + (consecutive_days - 1) * 0.1
|
||||
multiplier = min(multiplier, 3.0)
|
||||
text += "[center][color=#90EE90]奖励倍数: %.1fx[/color][/center]\n\n" % multiplier
|
||||
else:
|
||||
text += "\n"
|
||||
|
||||
# 基础奖励
|
||||
if rewards.has("coins"):
|
||||
text += "[color=%s]%s +%d %s[/color]\n" % [
|
||||
reward_configs.coins.color,
|
||||
reward_configs.coins.icon,
|
||||
rewards.coins,
|
||||
reward_configs.coins.name
|
||||
]
|
||||
|
||||
if rewards.has("exp"):
|
||||
text += "[color=%s]%s +%d %s[/color]\n" % [
|
||||
reward_configs.exp.color,
|
||||
reward_configs.exp.icon,
|
||||
rewards.exp,
|
||||
reward_configs.exp.name
|
||||
]
|
||||
|
||||
# 种子奖励
|
||||
if rewards.has("seeds") and rewards.seeds.size() > 0:
|
||||
for seed_reward in rewards.seeds:
|
||||
var seed_name = seed_reward.name
|
||||
var quantity = seed_reward.quantity
|
||||
var quality = seed_reward.quality
|
||||
|
||||
# 从配置中找到对应的种子信息
|
||||
var seed_info = _get_seed_info(seed_name, quality)
|
||||
if seed_info:
|
||||
text += "[color=%s]%s[/color] [color=%s]%s[/color] x%d [color=%s](%s)[/color]\n" % [
|
||||
seed_info.color, seed_info.icon, seed_info.color, seed_name, quantity, seed_info.rarity_color, quality
|
||||
]
|
||||
|
||||
# 连续签到额外奖励
|
||||
if rewards.has("bonus_coins"):
|
||||
text += "\n[color=#FFD700]🎁 连续签到奖励:[/color]\n"
|
||||
text += "[color=%s]%s +%d %s[/color] [color=#FFD700]✨[/color]\n" % [
|
||||
reward_configs.coins.color,
|
||||
reward_configs.coins.icon,
|
||||
rewards.bonus_coins,
|
||||
reward_configs.coins.name
|
||||
]
|
||||
|
||||
if rewards.has("bonus_exp"):
|
||||
if not rewards.has("bonus_coins"):
|
||||
text += "\n[color=#FFD700]🎁 连续签到奖励:[/color]\n"
|
||||
text += "[color=%s]%s +%d %s[/color] [color=#FFD700]✨[/color]\n" % [
|
||||
reward_configs.exp.color,
|
||||
reward_configs.exp.icon,
|
||||
rewards.bonus_exp,
|
||||
reward_configs.exp.name
|
||||
]
|
||||
|
||||
# 下一个奖励预告
|
||||
var next_bonus_day = 0
|
||||
if consecutive_days < 3:
|
||||
next_bonus_day = 3
|
||||
elif consecutive_days < 7:
|
||||
next_bonus_day = 7
|
||||
elif consecutive_days < 14:
|
||||
next_bonus_day = 14
|
||||
elif consecutive_days < 21:
|
||||
next_bonus_day = 21
|
||||
|
||||
if next_bonus_day > 0:
|
||||
var days_needed = next_bonus_day - consecutive_days
|
||||
text += "\n[center][color=#87CEEB]再签到%d天可获得特殊奖励![/color][/center]" % days_needed
|
||||
|
||||
return text
|
||||
|
||||
## 获取种子信息
|
||||
func _get_seed_info(seed_name: String, quality: String) -> Dictionary:
|
||||
if quality in reward_configs.seeds:
|
||||
for seed in reward_configs.seeds[quality]:
|
||||
if seed.name == seed_name:
|
||||
return seed
|
||||
return {}
|
||||
|
||||
## 格式化历史记录文本
|
||||
func _format_history_text(date: String, rewards: Dictionary) -> String:
|
||||
var text = "[color=#87CEEB]📅 %s[/color] " % date
|
||||
|
||||
var reward_parts = []
|
||||
if rewards.has("coins"):
|
||||
reward_parts.append("[color=%s]%s %d[/color]" % [
|
||||
reward_configs.coins.color,
|
||||
reward_configs.coins.name,
|
||||
rewards.coins
|
||||
])
|
||||
|
||||
if rewards.has("exp"):
|
||||
reward_parts.append("[color=%s]%s %d[/color]" % [
|
||||
reward_configs.exp.color,
|
||||
reward_configs.exp.name,
|
||||
rewards.exp
|
||||
])
|
||||
|
||||
if rewards.has("seeds") and rewards.seeds.size() > 0:
|
||||
for seed_reward in rewards.seeds:
|
||||
var seed_name = seed_reward.name
|
||||
var quantity = seed_reward.quantity
|
||||
var quality = seed_reward.quality
|
||||
var seed_info = _get_seed_info(seed_name, quality)
|
||||
if seed_info:
|
||||
reward_parts.append("[color=%s]%s x%d[/color]" % [
|
||||
seed_info.color, seed_name, quantity
|
||||
])
|
||||
|
||||
text += " ".join(reward_parts)
|
||||
return text
|
||||
|
||||
## 更新显示内容
|
||||
func _update_display() -> void:
|
||||
var history_text = "[center][color=#FFB6C1]📋 签到历史[/color][/center]\n"
|
||||
|
||||
# 显示连续签到状态
|
||||
if consecutive_days > 0:
|
||||
history_text += "[center][color=#FF69B4]🔥 当前连续签到: %d天[/color][/center]\n" % consecutive_days
|
||||
if consecutive_days >= 30:
|
||||
history_text += "[center][color=#FFD700]⭐ 已达到最高连击等级! ⭐[/color][/center]\n"
|
||||
else:
|
||||
history_text += "[center][color=#DDDDDD]还未开始连续签到[/color][/center]\n"
|
||||
|
||||
history_text += "\n"
|
||||
|
||||
if check_in_data.size() == 0:
|
||||
history_text += "[center][color=#DDDDDD]暂无签到记录[/color][/center]"
|
||||
else:
|
||||
# 按日期排序显示历史记录
|
||||
var sorted_dates = check_in_data.keys()
|
||||
sorted_dates.sort()
|
||||
sorted_dates.reverse() # 最新的在前
|
||||
|
||||
for date in sorted_dates:
|
||||
var day_data = check_in_data[date]
|
||||
var rewards = day_data.get("rewards", {})
|
||||
var day_consecutive = day_data.get("consecutive_days", 1)
|
||||
|
||||
history_text += _format_history_text(date, rewards)
|
||||
history_text += " [color=#90EE90](连续%d天)[/color]\n" % day_consecutive
|
||||
history_text += "-----------------------------------------------------------------------------------------------------------------\n"
|
||||
|
||||
daily_check_in_history.text = history_text
|
||||
|
||||
# =============================================================================
|
||||
# 事件处理
|
||||
# =============================================================================
|
||||
|
||||
## 关闭面板按钮
|
||||
func _on_quit_button_pressed() -> void:
|
||||
self.hide()
|
||||
|
||||
## 签到按钮
|
||||
func _on_daily_check_in_button_pressed() -> void:
|
||||
execute_check_in()
|
||||
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
# =============================================================================
|
||||
# 公共接口方法 - 供主游戏调用
|
||||
# =============================================================================
|
||||
|
||||
## 刷新签到数据
|
||||
func refresh_check_in_data() -> void:
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.is_connected_to_server():
|
||||
tcp_network_manager_panel.sendGetCheckInData()
|
||||
|
||||
## 获取当前签到状态
|
||||
func get_check_in_status() -> Dictionary:
|
||||
return {
|
||||
"has_checked_in_today": has_checked_in_today,
|
||||
"consecutive_days": consecutive_days,
|
||||
"today_date": today_date
|
||||
}
|
||||
|
||||
|
||||
1
Script/BigPanel/DailyCheckInPanel.gd.uid
Normal file
1
Script/BigPanel/DailyCheckInPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c0jfbtkh0mj5b
|
||||
519
Script/BigPanel/ItemBagPanel.gd
Normal file
519
Script/BigPanel/ItemBagPanel.gd
Normal file
@@ -0,0 +1,519 @@
|
||||
extends Panel
|
||||
# 这是道具背包面板,用来显示玩家获得的道具
|
||||
|
||||
# 道具背包格子容器
|
||||
@onready var bag_grid: GridContainer = $ScrollContainer/Bag_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
@onready var refresh_button : Button = $RefreshButton
|
||||
|
||||
# 预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
|
||||
|
||||
# 道具使用状态
|
||||
var selected_item_name: String = ""
|
||||
var selected_item_button: Button = null
|
||||
var is_item_selected: bool = false
|
||||
|
||||
# 宠物使用道具模式
|
||||
var is_pet_item_mode: bool = false
|
||||
var current_pet_data: Dictionary = {}
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
|
||||
# 异步更新道具背包UI
|
||||
func _update_item_bag_ui_async():
|
||||
# 清空道具背包格子
|
||||
for child in bag_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 等待一帧确保子节点被清理
|
||||
await get_tree().process_frame
|
||||
|
||||
# 为背包中的每个道具创建按钮
|
||||
for item_data in main_game.item_bag:
|
||||
var item_name = item_data["name"]
|
||||
var item_count = item_data["count"]
|
||||
|
||||
# 创建道具按钮
|
||||
var button = _create_item_button(item_name)
|
||||
|
||||
# 更新按钮文本显示数量
|
||||
button.text = str(item_name + "\n数量:" + str(item_count))
|
||||
|
||||
# 根据是否处于访问模式连接不同的事件
|
||||
if main_game.is_visiting_mode:
|
||||
# 访问模式下,点击道具只显示信息,不能使用
|
||||
button.pressed.connect(func(): _on_visit_item_selected(item_name, item_count))
|
||||
else:
|
||||
# 正常模式下,连接道具选择事件
|
||||
button.pressed.connect(func(): _on_item_selected(item_name, item_count, button))
|
||||
|
||||
bag_grid.add_child(button)
|
||||
|
||||
# 初始化道具背包
|
||||
func init_item_bag():
|
||||
# 清空道具背包格子
|
||||
for child in bag_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 显示背包中的道具
|
||||
update_item_bag_ui()
|
||||
|
||||
# 更新道具背包UI(同步版本,用于刷新按钮)
|
||||
func update_item_bag_ui():
|
||||
# 清空道具背包格子
|
||||
for child in bag_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 获取过滤后的道具列表
|
||||
var filtered_items = _get_filtered_items()
|
||||
|
||||
# 为背包中的每个道具创建按钮
|
||||
for item_data in filtered_items:
|
||||
var item_name = item_data["name"]
|
||||
var item_count = item_data["count"]
|
||||
|
||||
# 创建道具按钮
|
||||
var button = _create_item_button(item_name)
|
||||
|
||||
# 更新按钮文本显示数量
|
||||
button.text = str(item_name + "\n数量:" + str(item_count))
|
||||
|
||||
# 根据模式连接不同的事件
|
||||
if main_game.is_visiting_mode:
|
||||
# 访问模式下,点击道具只显示信息,不能使用
|
||||
button.pressed.connect(func(): _on_visit_item_selected(item_name, item_count))
|
||||
elif is_pet_item_mode:
|
||||
# 宠物使用道具模式下,连接宠物道具选择事件
|
||||
button.pressed.connect(func(): _on_pet_item_selected(item_name, item_count))
|
||||
else:
|
||||
# 正常模式下,连接道具选择事件
|
||||
button.pressed.connect(func(): _on_item_selected(item_name, item_count, button))
|
||||
|
||||
bag_grid.add_child(button)
|
||||
|
||||
# 创建道具按钮
|
||||
func _create_item_button(item_name: String) -> Button:
|
||||
# 使用绿色按钮作为道具按钮的默认样式
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 设置按钮文本
|
||||
button.text = item_name
|
||||
|
||||
# 添加工具提示,从item_config.json获取道具信息
|
||||
var item_config = _load_item_config()
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
var description = item_info.get("描述", "暂无描述")
|
||||
var cost = item_info.get("花费", 0)
|
||||
|
||||
button.tooltip_text = str(
|
||||
"道具: " + item_name + "\n" +
|
||||
"价格: " + str(cost) + "元\n" +
|
||||
"描述: " + description + "\n" +
|
||||
"点击选择道具,然后对地块使用"
|
||||
)
|
||||
else:
|
||||
button.tooltip_text = str("道具: " + item_name + "\n描述: 暂无信息")
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").text = "道具"
|
||||
button.get_node("Title").modulate = Color.CYAN # 道具标题使用青色
|
||||
|
||||
# 更新按钮的道具图片
|
||||
_update_button_item_image(button, item_name)
|
||||
|
||||
return button
|
||||
|
||||
# 从主游戏脚本获取道具配置数据
|
||||
func _load_item_config() -> Dictionary:
|
||||
# 从主游戏脚本的全局变量获取道具配置数据
|
||||
if main_game.item_config_data.size() > 0:
|
||||
return main_game.item_config_data
|
||||
else:
|
||||
print("道具背包:主游戏脚本中没有道具配置数据")
|
||||
return {}
|
||||
|
||||
# 设置宠物使用道具模式
|
||||
func set_pet_item_mode(enabled: bool, pet_data: Dictionary = {}):
|
||||
is_pet_item_mode = enabled
|
||||
current_pet_data = pet_data
|
||||
|
||||
# 刷新UI以应用新的模式
|
||||
update_item_bag_ui()
|
||||
|
||||
# 获取过滤后的道具列表
|
||||
func _get_filtered_items() -> Array:
|
||||
var filtered_items = []
|
||||
|
||||
for item_data in main_game.item_bag:
|
||||
var item_name = item_data["name"]
|
||||
|
||||
# 如果是宠物使用道具模式,只显示宠物道具
|
||||
if is_pet_item_mode:
|
||||
if _is_pet_item(item_name):
|
||||
filtered_items.append(item_data)
|
||||
else:
|
||||
# 正常模式显示所有道具
|
||||
filtered_items.append(item_data)
|
||||
|
||||
return filtered_items
|
||||
|
||||
# 检查是否为宠物道具
|
||||
func _is_pet_item(item_name: String) -> bool:
|
||||
var item_config = _load_item_config()
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
var item_type = item_info.get("类型", "")
|
||||
return item_type == "宠物道具"
|
||||
return false
|
||||
|
||||
|
||||
# 正常模式下的道具点击处理 - 选择道具
|
||||
func _on_item_selected(item_name: String, item_count: int, button: Button):
|
||||
# 检查道具是否可以使用
|
||||
if not _is_item_usable(item_name):
|
||||
# 显示道具信息
|
||||
_show_item_info(item_name, item_count)
|
||||
return
|
||||
|
||||
# 检查是否为农场道具(直接使用类型)
|
||||
if _is_farm_item(item_name):
|
||||
# 农场道具直接使用,显示确认对话框
|
||||
_show_farm_item_confirmation_dialog(item_name, item_count)
|
||||
return
|
||||
|
||||
# 取消之前选择的道具
|
||||
if selected_item_button and selected_item_button != button:
|
||||
_deselect_item()
|
||||
|
||||
if selected_item_name == item_name:
|
||||
# 如果点击的是已选择的道具,取消选择
|
||||
_deselect_item()
|
||||
Toast.show("已取消选择道具", Color.YELLOW, 2.0, 1.0)
|
||||
else:
|
||||
# 选择新道具
|
||||
_select_item(item_name, button)
|
||||
#点击后关闭玩家道具面板
|
||||
_on_quit_button_pressed()
|
||||
Toast.show("已选择 " + item_name + ",点击地块使用道具", Color.CYAN, 3.0, 1.0)
|
||||
|
||||
# 选择道具
|
||||
func _select_item(item_name: String, button: Button):
|
||||
selected_item_name = item_name
|
||||
selected_item_button = button
|
||||
is_item_selected = true
|
||||
|
||||
# 设置全局选择状态
|
||||
main_game.selected_item_name = item_name
|
||||
main_game.is_item_selected = true
|
||||
|
||||
# 更改按钮样式表示选中
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").modulate = Color.YELLOW # 选中时使用黄色
|
||||
|
||||
# 取消选择道具
|
||||
func _deselect_item():
|
||||
selected_item_name = ""
|
||||
is_item_selected = false
|
||||
|
||||
# 清除全局选择状态
|
||||
main_game.selected_item_name = ""
|
||||
main_game.is_item_selected = false
|
||||
|
||||
# 恢复按钮样式
|
||||
if selected_item_button and selected_item_button.has_node("Title"):
|
||||
selected_item_button.get_node("Title").modulate = Color.CYAN
|
||||
|
||||
selected_item_button = null
|
||||
|
||||
# 检查道具是否可以使用
|
||||
func _is_item_usable(item_name: String) -> bool:
|
||||
# 根据道具类型判断是否可以使用
|
||||
match item_name:
|
||||
"农家肥", "金坷垃", "生长素":
|
||||
return true # 施肥道具
|
||||
"水壶", "水桶":
|
||||
return true # 浇水道具
|
||||
"铲子","除草剂":
|
||||
return true # 铲除道具
|
||||
"精准采集锄", "时运锄":
|
||||
return true # 采集道具
|
||||
"小额经验卡", "小额金币卡":
|
||||
return true # 农场道具(直接使用)
|
||||
"杀虫剂":
|
||||
return false # 其他道具(暂不实现)
|
||||
_:
|
||||
return false
|
||||
|
||||
# 检查道具是否为农场道具(直接使用类型)
|
||||
func _is_farm_item(item_name: String) -> bool:
|
||||
var item_config = _load_item_config()
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
var item_type = item_info.get("类型", "")
|
||||
return item_type == "农场道具"
|
||||
return false
|
||||
|
||||
# 显示道具信息
|
||||
func _show_item_info(item_name: String, item_count: int):
|
||||
var info_text = ""
|
||||
|
||||
var item_config = _load_item_config()
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
var description = item_info.get("描述", "暂无描述")
|
||||
var cost = item_info.get("花费", 0)
|
||||
|
||||
info_text = item_name + " (数量: " + str(item_count) + ")\n"
|
||||
info_text += "价格: " + str(cost) + "元\n"
|
||||
info_text += "描述: " + description
|
||||
|
||||
if not _is_item_usable(item_name):
|
||||
info_text += "\n注意: 此道具功能暂未实现"
|
||||
else:
|
||||
info_text = item_name + " (数量: " + str(item_count) + ")\n描述: 暂无信息"
|
||||
|
||||
Toast.show(info_text, Color.CYAN, 3.0, 1.0)
|
||||
|
||||
# 访问模式下的道具点击处理
|
||||
func _on_visit_item_selected(item_name: String, item_count: int):
|
||||
# 显示道具信息
|
||||
_show_item_info(item_name, item_count)
|
||||
|
||||
# 宠物使用道具模式下的道具选择处理
|
||||
func _on_pet_item_selected(item_name: String, item_count: int):
|
||||
# 显示确认对话框
|
||||
_show_pet_item_confirmation_dialog(item_name, item_count)
|
||||
|
||||
# 显示农场道具确认对话框
|
||||
func _show_farm_item_confirmation_dialog(item_name: String, item_count: int):
|
||||
# 获取道具信息
|
||||
var item_config = _load_item_config()
|
||||
var item_description = "未知效果"
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
item_description = item_info.get("描述", "未知效果")
|
||||
|
||||
var confirmation_text = str(
|
||||
"确定要使用道具 " + item_name + " 吗?\n\n" +
|
||||
"道具效果:" + item_description + "\n\n" +
|
||||
"使用后道具数量将减少1个"
|
||||
)
|
||||
|
||||
# 使用自定义的AcceptDialog
|
||||
var dialog = preload("res://Script/Dialog/AcceptDialog.gd").new()
|
||||
|
||||
# 添加到场景(这会触发_ready函数)
|
||||
add_child(dialog)
|
||||
|
||||
# 在_ready执行后设置内容
|
||||
dialog.set_dialog_title("确认使用道具")
|
||||
dialog.set_dialog_content(confirmation_text)
|
||||
dialog.set_ok_text("确认使用")
|
||||
dialog.set_cancel_text("取消")
|
||||
|
||||
# 连接信号
|
||||
dialog.confirmed.connect(_on_confirm_farm_item_use.bind(item_name, dialog))
|
||||
dialog.canceled.connect(_on_cancel_farm_item_use.bind(dialog))
|
||||
|
||||
# 显示对话框
|
||||
dialog.popup_centered()
|
||||
|
||||
# 确认使用农场道具
|
||||
func _on_confirm_farm_item_use(item_name: String, dialog: AcceptDialog):
|
||||
_send_farm_item_use_request(item_name)
|
||||
dialog.queue_free()
|
||||
self.hide()
|
||||
|
||||
# 取消使用农场道具
|
||||
func _on_cancel_farm_item_use(dialog: AcceptDialog):
|
||||
dialog.queue_free()
|
||||
|
||||
# 发送农场道具使用请求
|
||||
func _send_farm_item_use_request(item_name: String):
|
||||
var message = {
|
||||
"type": "use_farm_item",
|
||||
"item_name": item_name
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
tcp_network_manager_panel.send_message(message)
|
||||
|
||||
Toast.show("正在使用道具...", Color.BLUE, 2.0, 1.0)
|
||||
|
||||
# 显示宠物使用道具确认对话框
|
||||
func _show_pet_item_confirmation_dialog(item_name: String, item_count: int):
|
||||
if current_pet_data.is_empty():
|
||||
Toast.show("宠物数据丢失,请重新选择宠物", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
var pet_name = current_pet_data.get("基本信息", {}).get("宠物名称", "未知宠物")
|
||||
var pet_id = current_pet_data.get("基本信息", {}).get("宠物ID", "")
|
||||
|
||||
# 获取道具信息
|
||||
var item_config = _load_item_config()
|
||||
var item_description = "未知效果"
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
item_description = item_info.get("描述", "未知效果")
|
||||
|
||||
var confirmation_text = str(
|
||||
"确定要对宠物 " + pet_name + " 使用道具 " + item_name + " 吗?\n\n" +
|
||||
"道具效果:" + item_description + "\n\n" +
|
||||
"使用后道具数量将减少1个"
|
||||
)
|
||||
|
||||
# 使用自定义的AcceptDialog
|
||||
var dialog = preload("res://Script/Dialog/AcceptDialog.gd").new()
|
||||
|
||||
# 添加到场景(这会触发_ready函数)
|
||||
add_child(dialog)
|
||||
|
||||
# 在_ready执行后设置内容
|
||||
dialog.set_dialog_title("确认使用道具")
|
||||
dialog.set_dialog_content(confirmation_text)
|
||||
dialog.set_ok_text("确认使用")
|
||||
dialog.set_cancel_text("取消")
|
||||
|
||||
# 连接信号
|
||||
dialog.confirmed.connect(_on_confirm_pet_item_use.bind(item_name, pet_id, dialog))
|
||||
dialog.canceled.connect(_on_cancel_pet_item_use.bind(dialog))
|
||||
|
||||
# 显示对话框
|
||||
dialog.popup_centered()
|
||||
|
||||
# 确认使用宠物道具
|
||||
func _on_confirm_pet_item_use(item_name: String, pet_id: String, dialog: AcceptDialog):
|
||||
_send_pet_item_use_request(item_name, pet_id)
|
||||
dialog.queue_free()
|
||||
self.hide()
|
||||
|
||||
# 取消使用宠物道具
|
||||
func _on_cancel_pet_item_use(dialog: AcceptDialog):
|
||||
dialog.queue_free()
|
||||
self.hide()
|
||||
|
||||
# 发送宠物使用道具请求
|
||||
func _send_pet_item_use_request(item_name: String, pet_id: String):
|
||||
var message = {
|
||||
"type": "use_pet_item",
|
||||
"item_name": item_name,
|
||||
"pet_id": pet_id
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
tcp_network_manager_panel.send_message(message)
|
||||
|
||||
# 退出宠物使用道具模式
|
||||
_exit_pet_item_mode()
|
||||
|
||||
Toast.show("正在使用道具...", Color.BLUE, 2.0, 1.0)
|
||||
|
||||
# 退出宠物使用道具模式
|
||||
func _exit_pet_item_mode():
|
||||
is_pet_item_mode = false
|
||||
current_pet_data = {}
|
||||
|
||||
# 刷新UI
|
||||
update_item_bag_ui()
|
||||
|
||||
# 更新按钮的道具图片
|
||||
func _update_button_item_image(button: Button, item_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var item_image = button.get_node_or_null("CropImage")
|
||||
if not item_image:
|
||||
return
|
||||
|
||||
# 从配置文件获取道具图片路径
|
||||
var item_config = _load_item_config()
|
||||
var texture = null
|
||||
|
||||
if item_config and item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
var image_path = item_info.get("道具图片", "")
|
||||
|
||||
if image_path != "" and ResourceLoader.exists(image_path):
|
||||
# 尝试加载道具图片
|
||||
texture = load(image_path)
|
||||
if texture:
|
||||
pass
|
||||
else:
|
||||
print("加载道具图片失败:", item_name, " -> ", image_path)
|
||||
else:
|
||||
print("道具图片路径无效或不存在:", item_name, " -> ", image_path)
|
||||
|
||||
# 如果没有找到道具图片,尝试使用默认道具图片
|
||||
if not texture:
|
||||
var default_item_path = "res://assets/道具图片/默认道具.webp"
|
||||
if ResourceLoader.exists(default_item_path):
|
||||
texture = load(default_item_path)
|
||||
if texture:
|
||||
print("使用默认道具图片:", item_name)
|
||||
|
||||
# 设置图片
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
item_image.texture = texture
|
||||
item_image.visible = true
|
||||
else:
|
||||
# 如果没有图片,隐藏图片节点
|
||||
item_image.visible = false
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
# 关闭道具背包面板
|
||||
func _on_quit_button_pressed() -> void:
|
||||
# 如果是宠物使用道具模式,退出该模式
|
||||
if is_pet_item_mode:
|
||||
_exit_pet_item_mode()
|
||||
|
||||
self.hide()
|
||||
|
||||
#手动刷新道具背包面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 刷新道具背包UI
|
||||
update_item_bag_ui()
|
||||
Toast.show("道具背包已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
update_item_bag_ui()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
#=========================面板通用处理=========================
|
||||
|
||||
# 获取当前选择的道具名称
|
||||
func get_selected_item_name() -> String:
|
||||
return selected_item_name
|
||||
|
||||
# 检查是否有道具被选择
|
||||
func is_item_currently_selected() -> bool:
|
||||
return is_item_selected
|
||||
1
Script/BigPanel/ItemBagPanel.gd.uid
Normal file
1
Script/BigPanel/ItemBagPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b701r833vse3u
|
||||
275
Script/BigPanel/ItemStorePanel.gd
Normal file
275
Script/BigPanel/ItemStorePanel.gd
Normal file
@@ -0,0 +1,275 @@
|
||||
extends Panel
|
||||
# 这是道具商店面板,用来展示各种道具
|
||||
|
||||
# 道具商店格子容器
|
||||
@onready var store_grid: GridContainer = $ScrollContainer/Store_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
@onready var refresh_button : Button = $RefreshButton
|
||||
|
||||
# 预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
@onready var batch_buy_popup: PanelContainer = $'../../DiaLog/BatchBuyPopup'
|
||||
|
||||
|
||||
# 道具配置数据
|
||||
var item_config : Dictionary = {}
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接关闭按钮信号
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
# 初始化道具商店
|
||||
func init_item_store():
|
||||
# 从主游戏脚本获取道具配置数据
|
||||
_load_item_config_from_main()
|
||||
update_item_store_ui()
|
||||
|
||||
# 更新道具商店UI
|
||||
func update_item_store_ui():
|
||||
# 清空道具商店格子
|
||||
for child in store_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
print("更新道具商店UI,道具种类:", item_config.size())
|
||||
|
||||
# 为每个道具配置创建按钮
|
||||
for item_name in item_config.keys():
|
||||
var item_info = item_config[item_name]
|
||||
var item_cost = item_info.get("花费", 0)
|
||||
var item_desc = item_info.get("描述", "暂无描述")
|
||||
|
||||
# 创建道具按钮
|
||||
var button = _create_item_button(item_name, item_cost, item_desc)
|
||||
|
||||
# 更新按钮文本显示价格
|
||||
button.text = str(item_name + "\n价格:" + str(item_cost) + "元")
|
||||
|
||||
# 连接购买点击事件
|
||||
button.pressed.connect(func(): _on_store_item_selected(item_name, item_cost, item_desc))
|
||||
|
||||
store_grid.add_child(button)
|
||||
|
||||
# 创建道具按钮
|
||||
func _create_item_button(item_name: String, item_cost: int, item_desc: String) -> Button:
|
||||
# 使用橙色按钮作为道具商店按钮的样式
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 设置按钮文本
|
||||
button.text = item_name
|
||||
|
||||
# 添加工具提示
|
||||
button.tooltip_text = str(
|
||||
"道具: " + item_name + "\n" +
|
||||
"价格: " + str(item_cost) + "元\n" +
|
||||
"描述: " + item_desc + "\n" +
|
||||
"点击购买道具"
|
||||
)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").text = "商店"
|
||||
button.get_node("Title").modulate = Color.GOLD # 商店标题使用金色
|
||||
|
||||
# 更新按钮的道具图片
|
||||
_update_button_item_image(button, item_name)
|
||||
|
||||
return button
|
||||
|
||||
# 从主游戏脚本获取道具配置数据
|
||||
func _load_item_config_from_main():
|
||||
# 从主游戏脚本的全局变量获取道具配置数据
|
||||
if main_game.item_config_data.size() > 0:
|
||||
item_config = main_game.item_config_data
|
||||
print("道具商店:从主游戏脚本获取道具配置数据,道具种类:", item_config.size())
|
||||
else:
|
||||
print("道具商店:主游戏脚本中没有道具配置数据,使用空配置")
|
||||
item_config = {}
|
||||
|
||||
|
||||
# 商店道具点击处理 - 购买道具
|
||||
func _on_store_item_selected(item_name: String, item_cost: int, item_desc: String):
|
||||
# 检查玩家金钱是否足够(至少能买1个)
|
||||
if main_game.money < item_cost:
|
||||
Toast.show("金钱不足!需要 " + str(item_cost) + " 元,当前只有 " + str(main_game.money) + " 元", Color.RED, 3.0, 1.0)
|
||||
return
|
||||
|
||||
# 显示批量购买弹窗
|
||||
if batch_buy_popup:
|
||||
batch_buy_popup.show_buy_popup(
|
||||
item_name,
|
||||
item_cost,
|
||||
item_desc,
|
||||
"item",
|
||||
_on_confirm_buy_item,
|
||||
_on_cancel_buy_item
|
||||
)
|
||||
else:
|
||||
print("批量购买弹窗未找到")
|
||||
|
||||
# 显示购买确认对话框
|
||||
func _show_buy_confirmation_dialog(item_name: String, item_cost: int, item_desc: String):
|
||||
# 创建确认对话框
|
||||
var confirm_dialog = AcceptDialog.new()
|
||||
confirm_dialog.dialog_text = str(
|
||||
"确认购买道具?\n\n" +
|
||||
"道具名称: " + item_name + "\n" +
|
||||
"购买价格: " + str(item_cost) + " 元\n" +
|
||||
"道具描述: " + item_desc + "\n\n" +
|
||||
"当前金钱: " + str(main_game.money) + " 元\n" +
|
||||
"购买后余额: " + str(main_game.money - item_cost) + " 元"
|
||||
)
|
||||
confirm_dialog.title = "购买道具确认"
|
||||
confirm_dialog.ok_button_text = "确认购买"
|
||||
confirm_dialog.add_cancel_button("取消")
|
||||
|
||||
# 添加到场景
|
||||
add_child(confirm_dialog)
|
||||
|
||||
# 连接信号
|
||||
confirm_dialog.confirmed.connect(_on_confirm_buy_item.bind(item_name, item_cost, confirm_dialog))
|
||||
confirm_dialog.canceled.connect(_on_cancel_buy_item.bind(confirm_dialog))
|
||||
|
||||
# 显示对话框
|
||||
confirm_dialog.popup_centered()
|
||||
|
||||
# 确认购买道具(批量购买版本)
|
||||
func _on_confirm_buy_item(item_name: String, unit_cost: int, quantity: int, buy_type: String):
|
||||
var total_cost = unit_cost * quantity
|
||||
|
||||
# 再次检查金钱是否足够
|
||||
if main_game.money < total_cost:
|
||||
Toast.show("金钱不足!需要 " + str(total_cost) + " 元,当前只有 " + str(main_game.money) + " 元", Color.RED, 3.0, 1.0)
|
||||
return
|
||||
|
||||
# 发送批量购买请求到服务器
|
||||
_send_batch_buy_item_request(item_name, unit_cost, quantity)
|
||||
|
||||
# 取消购买道具(批量购买版本)
|
||||
func _on_cancel_buy_item():
|
||||
print("取消购买道具")
|
||||
|
||||
# 发送批量购买道具请求
|
||||
func _send_batch_buy_item_request(item_name: String, unit_cost: int, quantity: int):
|
||||
# 发送批量购买请求到服务器
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("sendBuyItem"):
|
||||
if tcp_network_manager_panel.sendBuyItem(item_name, unit_cost, quantity):
|
||||
# 服务器会处理批量购买逻辑,客户端等待响应
|
||||
print("已发送批量购买道具请求:", item_name, " 数量:", quantity)
|
||||
else:
|
||||
Toast.show("购买请求发送失败", Color.RED, 2.0, 1.0)
|
||||
else:
|
||||
Toast.show("网络管理器不可用", Color.RED, 2.0, 1.0)
|
||||
|
||||
# 将道具添加到道具背包(客户端同步)
|
||||
func _add_item_to_bag(item_name: String):
|
||||
# 确保道具背包存在
|
||||
if "道具背包" not in main_game:
|
||||
main_game["道具背包"] = []
|
||||
|
||||
# 查找是否已存在该道具
|
||||
var found = false
|
||||
for item in main_game["道具背包"]:
|
||||
if item.get("name") == item_name:
|
||||
item["count"] += 1
|
||||
found = true
|
||||
break
|
||||
|
||||
# 如果不存在,添加新道具
|
||||
if not found:
|
||||
main_game["道具背包"].append({
|
||||
"name": item_name,
|
||||
"count": 1
|
||||
})
|
||||
|
||||
# 更新按钮的道具图片
|
||||
func _update_button_item_image(button: Button, item_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var item_image = button.get_node_or_null("CropImage")
|
||||
if not item_image:
|
||||
print("道具商店按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 从配置文件获取道具图片路径
|
||||
var texture = null
|
||||
|
||||
if item_config.has(item_name):
|
||||
var item_info = item_config[item_name]
|
||||
var image_path = item_info.get("道具图片", "")
|
||||
|
||||
if image_path != "" and ResourceLoader.exists(image_path):
|
||||
# 尝试加载道具图片
|
||||
texture = load(image_path)
|
||||
if texture:
|
||||
pass
|
||||
else:
|
||||
print("加载道具图片失败:", item_name, " -> ", image_path)
|
||||
else:
|
||||
print("道具图片路径无效或不存在:", item_name, " -> ", image_path)
|
||||
|
||||
# 如果没有找到道具图片,尝试使用默认道具图片
|
||||
if not texture:
|
||||
var default_item_path = "res://assets/道具图片/默认道具.webp"
|
||||
if ResourceLoader.exists(default_item_path):
|
||||
texture = load(default_item_path)
|
||||
if texture:
|
||||
print("使用默认道具图片:", item_name)
|
||||
|
||||
# 设置图片
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
item_image.texture = texture
|
||||
item_image.visible = true
|
||||
print("道具商店更新道具图片:", item_name)
|
||||
else:
|
||||
# 如果没有图片,隐藏图片节点
|
||||
item_image.visible = false
|
||||
print("道具商店无法获取道具图片:", item_name)
|
||||
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
#手动刷新道具商店面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 重新初始化道具商店
|
||||
init_item_store()
|
||||
Toast.show("道具商店已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
|
||||
|
||||
# 关闭道具商店面板
|
||||
func _on_quit_button_pressed() -> void:
|
||||
self.hide()
|
||||
pass
|
||||
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
init_item_store()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
#=========================面板通用处理=========================
|
||||
1
Script/BigPanel/ItemStorePanel.gd.uid
Normal file
1
Script/BigPanel/ItemStorePanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bruqwi63myl1m
|
||||
548
Script/BigPanel/LoginPanel.gd
Normal file
548
Script/BigPanel/LoginPanel.gd
Normal file
@@ -0,0 +1,548 @@
|
||||
#玩家登录注册面板
|
||||
extends PanelContainer
|
||||
|
||||
#玩家登录账号,用QQ号代替
|
||||
@onready var username_input : LineEdit = $VBox/UserName/username_input
|
||||
#用户登录密码
|
||||
@onready var password_input : LineEdit = $VBox/Password1/password_input
|
||||
#登录按钮
|
||||
@onready var login_button : Button = $VBox/LoginRegister/login_button
|
||||
|
||||
#下面是注册相关的
|
||||
#注册按钮
|
||||
@onready var register_button : Button = $VBox/LoginRegister/register_button
|
||||
#注册账号时二次确认密码
|
||||
@onready var password_input_2 : LineEdit = $VBox/Password2/password_input2
|
||||
#农场名称
|
||||
@onready var farmname_input : LineEdit = $VBox/FarmName/farmname_input
|
||||
#玩家昵称
|
||||
@onready var playername_input :LineEdit = $VBox/PlayerName/playername_input
|
||||
#邮箱验证码
|
||||
@onready var verificationcode_input :LineEdit = $VBox/VerificationCode/verificationcode_input
|
||||
#发送验证码按钮
|
||||
@onready var send_button :Button = $VBox/VerificationCode/SendButton
|
||||
#状态提示标签
|
||||
@onready var status_label : Label = $VBox/status_label
|
||||
|
||||
|
||||
@onready var password_2: HBoxContainer = $VBox/Password2
|
||||
@onready var verification_code: HBoxContainer = $VBox/VerificationCode
|
||||
@onready var player_name: HBoxContainer = $VBox/PlayerName
|
||||
@onready var farm_name: HBoxContainer = $VBox/FarmName
|
||||
|
||||
|
||||
|
||||
# 记住密码选项
|
||||
var remember_password : bool = true # 默认记住密码
|
||||
|
||||
# 引用主场景和全局函数
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var pet_bag_panel: Panel = $'../PetBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
self.show()
|
||||
#隐藏注册相关UI
|
||||
password_2.hide()
|
||||
verification_code.hide()
|
||||
player_name.hide()
|
||||
farm_name.hide()
|
||||
|
||||
# 连接按钮信号
|
||||
login_button.pressed.connect(self._on_login_button_pressed)
|
||||
register_button.pressed.connect(self._on_register_button_pressed)
|
||||
send_button.pressed.connect(self._on_send_button_pressed)
|
||||
|
||||
# 加载保存的登录信息
|
||||
_load_login_info()
|
||||
|
||||
# 显示客户端版本号
|
||||
_display_version_info()
|
||||
|
||||
# 处理登录按钮点击
|
||||
func _on_login_button_pressed():
|
||||
password_2.hide()
|
||||
verification_code.hide()
|
||||
player_name.hide()
|
||||
farm_name.hide()
|
||||
|
||||
|
||||
|
||||
var user_name = username_input.text.strip_edges() # 修剪前后的空格
|
||||
var user_password = password_input.text.strip_edges()
|
||||
var farmname = farmname_input.text.strip_edges()
|
||||
|
||||
if user_name == "" or user_password == "":
|
||||
status_label.text = "用户名或密码不能为空!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 检查网络连接状态
|
||||
if !tcp_network_manager_panel.client.is_client_connected():
|
||||
status_label.text = "未连接到服务器,正在尝试连接..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 尝试自动连接到服务器
|
||||
tcp_network_manager_panel.connect_to_current_server()
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
|
||||
# 再次检查连接状态
|
||||
if !tcp_network_manager_panel.client.is_client_connected():
|
||||
status_label.text = "连接服务器失败,正在尝试其他服务器..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 等待自动服务器切换完成
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
|
||||
|
||||
# 禁用按钮,防止重复点击
|
||||
login_button.disabled = true
|
||||
|
||||
status_label.text = "正在登录,请稍候..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
|
||||
# 如果启用了记住密码,保存登录信息
|
||||
if remember_password:
|
||||
_save_login_info(user_name, user_password)
|
||||
|
||||
tcp_network_manager_panel.sendLoginInfo(user_name, user_password)
|
||||
|
||||
# 更新主游戏数据
|
||||
main_game.user_name = user_name
|
||||
main_game.user_password = user_password
|
||||
|
||||
# 5秒后重新启用按钮(如果没有收到响应)
|
||||
await get_tree().create_timer(5.0).timeout
|
||||
if login_button.disabled:
|
||||
login_button.disabled = false
|
||||
status_label.text = "登录超时,请重试!"
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 处理验证码发送按钮点击
|
||||
func _on_send_button_pressed():
|
||||
|
||||
|
||||
var user_name = username_input.text.strip_edges()
|
||||
|
||||
if user_name == "":
|
||||
status_label.text = "请输入QQ号以接收验证码!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if !is_valid_qq_number(user_name):
|
||||
status_label.text = "请输入正确的QQ号码(5-12位数字)!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 检查网络连接状态
|
||||
if !tcp_network_manager_panel.client.is_client_connected():
|
||||
status_label.text = "未连接到服务器,正在尝试连接..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 尝试自动连接到服务器
|
||||
tcp_network_manager_panel.connect_to_current_server()
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
|
||||
# 再次检查连接状态
|
||||
if !tcp_network_manager_panel.client.is_client_connected():
|
||||
status_label.text = "连接服务器失败,正在尝试其他服务器..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 等待自动服务器切换完成
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
|
||||
|
||||
# 禁用按钮,防止重复点击
|
||||
send_button.disabled = true
|
||||
|
||||
status_label.text = "正在发送验证码,请稍候..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
|
||||
# 发送验证码请求
|
||||
tcp_network_manager_panel.sendVerificationCodeRequest(user_name)
|
||||
|
||||
# 60秒后重新启用按钮(或收到响应后提前启用)
|
||||
var timer = 60
|
||||
while timer > 0 and send_button.disabled:
|
||||
send_button.text = "重新发送(%d)" % timer
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
timer -= 1
|
||||
|
||||
if send_button.disabled:
|
||||
send_button.disabled = false
|
||||
send_button.text = "发送验证码"
|
||||
|
||||
if status_label.text == "正在发送验证码,请稍候...":
|
||||
status_label.text = "验证码发送超时,请重试!"
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 处理注册按钮点击
|
||||
func _on_register_button_pressed():
|
||||
password_2.show()
|
||||
verification_code.show()
|
||||
player_name.show()
|
||||
farm_name.show()
|
||||
|
||||
var user_name = username_input.text.strip_edges()
|
||||
var user_password = password_input.text.strip_edges()
|
||||
var user_password_2 = password_input_2.text.strip_edges()
|
||||
var farmname = farmname_input.text.strip_edges()
|
||||
var player_name = playername_input.text.strip_edges()
|
||||
var verification_code = verificationcode_input.text.strip_edges()
|
||||
|
||||
# 检查密码格式(只允许数字和字母)
|
||||
if not is_valid_password(user_password):
|
||||
status_label.text = "密码只能包含数字和字母!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if user_name == "" or user_password == "":
|
||||
status_label.text = "用户名或密码不能为空!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
if farmname == "":
|
||||
status_label.text = "农场名称不能为空!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
if user_password != user_password_2:
|
||||
status_label.text = "两次输入的密码不一致!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if !is_valid_qq_number(user_name):
|
||||
status_label.text = "请输入正确的QQ号码(5-12位数字)!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
if verification_code == "":
|
||||
status_label.text = "请输入验证码!"
|
||||
status_label.modulate = Color.RED
|
||||
return
|
||||
|
||||
# 检查网络连接状态
|
||||
if !tcp_network_manager_panel.client.is_client_connected():
|
||||
status_label.text = "未连接到服务器,正在尝试连接..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 尝试自动连接到服务器
|
||||
tcp_network_manager_panel.connect_to_current_server()
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
|
||||
# 再次检查连接状态
|
||||
if !tcp_network_manager_panel.client.is_client_connected():
|
||||
status_label.text = "连接服务器失败,正在尝试其他服务器..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
# 等待自动服务器切换完成
|
||||
await get_tree().create_timer(3.0).timeout
|
||||
|
||||
|
||||
# 禁用按钮,防止重复点击
|
||||
register_button.disabled = true
|
||||
|
||||
status_label.text = "正在注册,请稍候..."
|
||||
status_label.modulate = Color.YELLOW
|
||||
|
||||
# 发送注册请求
|
||||
tcp_network_manager_panel.sendRegisterInfo(user_name, user_password, farmname, player_name, verification_code)
|
||||
|
||||
# 更新主游戏数据
|
||||
main_game.user_name = user_name
|
||||
main_game.user_password = user_password
|
||||
main_game.farmname = farmname
|
||||
|
||||
# 5秒后重新启用按钮(如果没有收到响应)
|
||||
await get_tree().create_timer(5.0).timeout
|
||||
if register_button.disabled:
|
||||
register_button.disabled = false
|
||||
status_label.text = "注册超时,请重试!"
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 处理验证码发送响应
|
||||
func _on_verification_code_response(success: bool, message: String):
|
||||
if success:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.GREEN
|
||||
else:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.RED
|
||||
send_button.disabled = false
|
||||
send_button.text = "发送验证码"
|
||||
|
||||
# 处理验证码验证响应
|
||||
func _on_verify_code_response(success: bool, message: String):
|
||||
if success:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.GREEN
|
||||
else:
|
||||
status_label.text = message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 验证QQ号是否有效
|
||||
func is_valid_qq_number(qq_number: String) -> bool:
|
||||
# QQ号的标准格式是5到12位的数字
|
||||
var qq_regex = RegEx.new()
|
||||
var pattern = r"^\d{5,12}$"
|
||||
|
||||
var error = qq_regex.compile(pattern)
|
||||
if error != OK:
|
||||
status_label.text = "QQ号验证失败部错误"
|
||||
status_label.modulate = Color.RED
|
||||
return false
|
||||
|
||||
return qq_regex.search(qq_number) != null
|
||||
|
||||
# 添加密码验证函数
|
||||
func is_valid_password(password: String) -> bool:
|
||||
# 使用正则表达式检查是否只包含数字和字母
|
||||
var pattern = r"^[a-zA-Z0-9]+$"
|
||||
return password.match(pattern) != null
|
||||
|
||||
# 处理登录响应
|
||||
func _on_login_response_received(success: bool, message: String, user_data: Dictionary):
|
||||
# 启用按钮
|
||||
login_button.disabled = false
|
||||
|
||||
if success:
|
||||
status_label.text = "登录成功!正在加载游戏..."
|
||||
status_label.modulate = Color.GREEN
|
||||
|
||||
# 保存登录数据到主游戏
|
||||
main_game.login_data = user_data.duplicate()
|
||||
|
||||
# 更新主游戏数据
|
||||
main_game.experience = user_data.get("experience", 0)
|
||||
main_game.farm_lots = user_data.get("farm_lots", [])
|
||||
main_game.level = user_data.get("level", 1)
|
||||
main_game.money = user_data.get("money", 0)
|
||||
main_game.stamina = user_data.get("体力值", 20)
|
||||
main_game.show_farm_name.text = "农场名称:"+user_data.get("farm_name", "")
|
||||
main_game.show_player_name.text = "玩家昵称:"+user_data.get("player_name", "")
|
||||
farmname_input.text = user_data.get("farm_name", "")
|
||||
|
||||
# 加载玩家背包数据
|
||||
if user_data.has("player_bag"):
|
||||
main_game.player_bag = user_data.get("player_bag", [])
|
||||
else:
|
||||
main_game.player_bag = []
|
||||
|
||||
# 加载作物仓库数据
|
||||
if user_data.has("作物仓库"):
|
||||
main_game.crop_warehouse = user_data.get("作物仓库", [])
|
||||
else:
|
||||
main_game.crop_warehouse = []
|
||||
|
||||
# 加载道具背包数据
|
||||
if user_data.has("道具背包"):
|
||||
main_game.item_bag = user_data.get("道具背包", [])
|
||||
else:
|
||||
main_game.item_bag = []
|
||||
|
||||
# 加载宠物背包数据
|
||||
if user_data.has("宠物背包"):
|
||||
main_game.pet_bag = user_data.get("宠物背包", [])
|
||||
else:
|
||||
main_game.pet_bag = []
|
||||
|
||||
# 加载巡逻宠物数据
|
||||
if user_data.has("巡逻宠物"):
|
||||
main_game.patrol_pets = user_data.get("巡逻宠物", [])
|
||||
else:
|
||||
main_game.patrol_pets = []
|
||||
|
||||
main_game.start_game = true
|
||||
self.hide()
|
||||
|
||||
# 确保在更新数据后调用主游戏的 UI 更新函数
|
||||
main_game._update_ui()
|
||||
main_game._refresh_farm_lots()
|
||||
|
||||
player_bag_panel.update_player_bag_ui()
|
||||
# 更新作物仓库和道具背包UI
|
||||
crop_warehouse_panel.update_crop_warehouse_ui()
|
||||
item_bag_panel.update_item_bag_ui()
|
||||
# 更新宠物背包UI
|
||||
if pet_bag_panel and pet_bag_panel.has_method("update_pet_bag_ui"):
|
||||
pet_bag_panel.update_pet_bag_ui()
|
||||
|
||||
# 初始化巡逻宠物
|
||||
if main_game.has_method("init_patrol_pets"):
|
||||
main_game.init_patrol_pets()
|
||||
|
||||
# 调用主游戏的登录成功处理函数
|
||||
main_game.handle_login_success(user_data)
|
||||
else:
|
||||
status_label.text = "登录失败:" + message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 如果登录失败且是密码错误,可以选择清除保存的信息
|
||||
if "密码" in message or "password" in message.to_lower():
|
||||
print("登录失败,可能是密码错误。如需清除保存的登录信息,请调用_clear_login_info()")
|
||||
|
||||
# 处理注册响应
|
||||
func _on_register_response_received(success: bool, message: String):
|
||||
# 启用按钮
|
||||
register_button.disabled = false
|
||||
|
||||
if success:
|
||||
status_label.text = "注册成功!请登录游戏"
|
||||
status_label.modulate = Color.GREEN
|
||||
|
||||
# 注册成功后,如果启用了记住密码,保存登录信息
|
||||
if remember_password:
|
||||
var user_name = username_input.text.strip_edges()
|
||||
var user_password = password_input.text.strip_edges()
|
||||
_save_login_info(user_name, user_password)
|
||||
|
||||
# 清除注册相关的输入框
|
||||
password_input_2.text = ""
|
||||
verificationcode_input.text = ""
|
||||
else:
|
||||
status_label.text = "注册失败:" + message
|
||||
status_label.modulate = Color.RED
|
||||
|
||||
# 保存登录信息到JSON文件
|
||||
func _save_login_info(user_name: String, password: String):
|
||||
var login_data = {
|
||||
"user_name": user_name,
|
||||
"password": password
|
||||
}
|
||||
|
||||
var file = FileAccess.open("user://login.json", FileAccess.WRITE)
|
||||
if file:
|
||||
var json_string = JSON.stringify(login_data, "\t")
|
||||
file.store_string(json_string)
|
||||
file.close()
|
||||
print("登录信息已保存")
|
||||
else:
|
||||
print("无法保存登录信息")
|
||||
|
||||
# 从JSON文件加载登录信息
|
||||
func _load_login_info():
|
||||
var file = FileAccess.open("user://login.json", FileAccess.READ)
|
||||
if file:
|
||||
var json_text = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(json_text)
|
||||
if parse_result == OK:
|
||||
var login_data = json.get_data()
|
||||
if login_data.has("user_name") and login_data.has("password"):
|
||||
var saved_username = login_data.get("user_name", "")
|
||||
var saved_password = login_data.get("password", "")
|
||||
|
||||
if saved_username != "" and saved_password != "":
|
||||
username_input.text = saved_username
|
||||
password_input.text = saved_password
|
||||
status_label.text = "已加载保存的登录信息"
|
||||
status_label.modulate = Color.CYAN
|
||||
print("登录信息已加载:用户名 =", saved_username)
|
||||
else:
|
||||
status_label.text = "欢迎使用萌芽农场"
|
||||
status_label.modulate = Color.WHITE
|
||||
print("没有有效的保存登录信息")
|
||||
else:
|
||||
print("登录信息格式错误")
|
||||
else:
|
||||
print("登录信息JSON解析错误:", json.get_error_message())
|
||||
else:
|
||||
# 创建默认的登录信息文件
|
||||
_save_login_info("", "")
|
||||
status_label.text = "欢迎使用萌芽农场"
|
||||
status_label.modulate = Color.WHITE
|
||||
print("没有找到保存的登录信息,已创建默认文件")
|
||||
|
||||
# 清除保存的登录信息
|
||||
func _clear_login_info():
|
||||
var file = FileAccess.open("user://login.json", FileAccess.WRITE)
|
||||
if file:
|
||||
var empty_data = {
|
||||
"user_name": "",
|
||||
"password": ""
|
||||
}
|
||||
var json_string = JSON.stringify(empty_data, "\t")
|
||||
file.store_string(json_string)
|
||||
file.close()
|
||||
print("登录信息已清除")
|
||||
else:
|
||||
print("无法清除登录信息")
|
||||
|
||||
# 切换记住密码选项
|
||||
func toggle_remember_password():
|
||||
remember_password = !remember_password
|
||||
print("记住密码选项:", "开启" if remember_password else "关闭")
|
||||
|
||||
# 如果关闭了记住密码,清除已保存的信息
|
||||
if not remember_password:
|
||||
_clear_login_info()
|
||||
|
||||
# 检查是否有保存的登录信息
|
||||
func has_saved_login_info() -> bool:
|
||||
var file = FileAccess.open("user://login.json", FileAccess.READ)
|
||||
if file:
|
||||
var json_text = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(json_text)
|
||||
if parse_result == OK:
|
||||
var login_data = json.get_data()
|
||||
var user_name = login_data.get("user_name", "")
|
||||
var password = login_data.get("password", "")
|
||||
return user_name != "" and password != ""
|
||||
|
||||
return false
|
||||
|
||||
# 快捷登录(使用保存的登录信息)
|
||||
func quick_login():
|
||||
if has_saved_login_info():
|
||||
var user_name = username_input.text.strip_edges()
|
||||
var user_password = password_input.text.strip_edges()
|
||||
|
||||
if user_name != "" and user_password != "":
|
||||
print("执行快捷登录...")
|
||||
_on_login_button_pressed()
|
||||
else:
|
||||
status_label.text = "保存的登录信息不完整"
|
||||
status_label.modulate = Color.ORANGE
|
||||
else:
|
||||
status_label.text = "没有保存的登录信息"
|
||||
status_label.modulate = Color.ORANGE
|
||||
|
||||
# 获取保存的用户名(用于调试或显示)
|
||||
func get_saved_username() -> String:
|
||||
var file = FileAccess.open("user://login.json", FileAccess.READ)
|
||||
if file:
|
||||
var json_text = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_result = json.parse(json_text)
|
||||
if parse_result == OK:
|
||||
var login_data = json.get_data()
|
||||
return login_data.get("user_name", "")
|
||||
|
||||
return ""
|
||||
|
||||
# 显示版本信息
|
||||
func _display_version_info():
|
||||
# 在状态标签中显示客户端版本信息
|
||||
if status_label.text == "欢迎使用萌芽农场" or status_label.text == "连接状态":
|
||||
status_label.text = "萌芽农场 v" + main_game.client_version + " - 欢迎使用"
|
||||
status_label.modulate = Color.CYAN
|
||||
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
1
Script/BigPanel/LoginPanel.gd.uid
Normal file
1
Script/BigPanel/LoginPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cka0r4g8tbf0
|
||||
593
Script/BigPanel/LuckyDrawPanel.gd
Normal file
593
Script/BigPanel/LuckyDrawPanel.gd
Normal file
@@ -0,0 +1,593 @@
|
||||
extends Panel
|
||||
class_name LuckyDrawPanel
|
||||
|
||||
## 幸运抽奖系统 - 后端对接版本
|
||||
## 功能:与服务器对接的抽奖系统,支持实时数据同步和平衡调整
|
||||
## 奖励平衡性已根据 crop_data.json 调整
|
||||
|
||||
# =============================================================================
|
||||
# 信号定义 - 用于与后端系统通信
|
||||
# =============================================================================
|
||||
signal draw_completed(rewards: Array, draw_type: String) # 抽奖完成信号
|
||||
signal reward_obtained(reward_type: String, amount: int) # 奖励获得信号
|
||||
signal draw_failed(error_message: String) # 抽奖失败信号
|
||||
|
||||
# =============================================================================
|
||||
# 节点引用
|
||||
# =============================================================================
|
||||
#这个展示抽奖获得的奖励
|
||||
@onready var lucky_draw_reward: RichTextLabel = $LuckyDrawReward
|
||||
#这个是展示有哪些奖励选项,最多15个,奖励就在这里面随机挑选
|
||||
@onready var grid: GridContainer = $Grid
|
||||
#这个是奖励模板
|
||||
@onready var reward_item: RichTextLabel = $Grid/RewardItem
|
||||
|
||||
# =============================================================================
|
||||
# 数据存储
|
||||
# =============================================================================
|
||||
var reward_templates: Array[RichTextLabel] = []
|
||||
var current_rewards: Array = []
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
|
||||
|
||||
# 15种不同的模板颜色
|
||||
var template_colors: Array[Color] = [
|
||||
Color(1.0, 0.8, 0.8, 1.0), # 淡红色
|
||||
Color(0.8, 1.0, 0.8, 1.0), # 淡绿色
|
||||
Color(0.8, 0.8, 1.0, 1.0), # 淡蓝色
|
||||
Color(1.0, 1.0, 0.8, 1.0), # 淡黄色
|
||||
Color(1.0, 0.8, 1.0, 1.0), # 淡紫色
|
||||
Color(0.8, 1.0, 1.0, 1.0), # 淡青色
|
||||
Color(1.0, 0.9, 0.8, 1.0), # 淡橙色
|
||||
Color(0.9, 0.8, 1.0, 1.0), # 淡紫蓝色
|
||||
Color(0.8, 1.0, 0.9, 1.0), # 淡薄荷色
|
||||
Color(1.0, 0.8, 0.9, 1.0), # 淡粉色
|
||||
Color(0.9, 1.0, 0.8, 1.0), # 淡柠檬色
|
||||
Color(0.8, 0.9, 1.0, 1.0), # 淡天蓝色
|
||||
Color(1.0, 0.95, 0.8, 1.0), # 淡香槟色
|
||||
Color(0.85, 0.8, 1.0, 1.0), # 淡薰衣草色
|
||||
Color(0.95, 1.0, 0.85, 1.0) # 淡春绿色
|
||||
]
|
||||
|
||||
var anticipation_tween: Tween = null
|
||||
|
||||
# =============================================================================
|
||||
# 基础奖励配置 - 根据 crop_data.json 调整
|
||||
# =============================================================================
|
||||
var base_rewards: Dictionary = {
|
||||
"coins": {"name": "金币", "icon": "💰", "color": "#FFD700"},
|
||||
"exp": {"name": "经验", "icon": "⭐", "color": "#00BFFF"},
|
||||
"empty": {"name": "谢谢惠顾", "icon": "😅", "color": "#CCCCCC"}
|
||||
}
|
||||
|
||||
var seed_rewards: Dictionary = {}
|
||||
|
||||
# 抽奖费用配置
|
||||
var draw_costs: Dictionary = {
|
||||
"single": 800,
|
||||
"five": 3600, # 800 * 5 * 0.9 = 3600
|
||||
"ten": 6400 # 800 * 10 * 0.8 = 6400
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# 奖励池配置 - 根据后端数据动态更新
|
||||
# =============================================================================
|
||||
var server_reward_pools: Dictionary = {}
|
||||
|
||||
# =============================================================================
|
||||
# 系统初始化
|
||||
# =============================================================================
|
||||
func _ready() -> void:
|
||||
_initialize_system()
|
||||
|
||||
#初始化抽奖系统
|
||||
func _initialize_system() -> void:
|
||||
|
||||
# 连接信号
|
||||
if main_game:
|
||||
draw_completed.connect(main_game._on_lucky_draw_completed)
|
||||
draw_failed.connect(main_game._on_lucky_draw_failed)
|
||||
|
||||
lucky_draw_reward.hide()
|
||||
_load_crop_data_and_build_rewards()
|
||||
_generate_reward_templates()
|
||||
_update_template_display()
|
||||
|
||||
#从主游戏加载作物数据并构建种子奖励
|
||||
func _load_crop_data_and_build_rewards() -> void:
|
||||
if main_game and main_game.has_method("get_crop_data"):
|
||||
var crop_data = main_game.get_crop_data()
|
||||
if crop_data:
|
||||
_build_seed_rewards_from_crop_data(crop_data)
|
||||
|
||||
#根据 crop_data.json 构建种子奖励配置
|
||||
func _build_seed_rewards_from_crop_data(crop_data: Dictionary) -> void:
|
||||
seed_rewards.clear()
|
||||
|
||||
for crop_name in crop_data.keys():
|
||||
var crop_info = crop_data[crop_name]
|
||||
|
||||
# 跳过测试作物和不能购买的作物
|
||||
if crop_name == "测试作物" or not crop_info.get("能否购买", true):
|
||||
continue
|
||||
|
||||
var quality = crop_info.get("品质", "普通")
|
||||
var rarity_color = _get_rarity_color(quality)
|
||||
|
||||
seed_rewards[crop_name] = {
|
||||
"icon": "🌱",
|
||||
"color": rarity_color,
|
||||
"rarity": quality,
|
||||
"level": crop_info.get("等级", 1),
|
||||
"cost": crop_info.get("花费", 50)
|
||||
}
|
||||
|
||||
#根据稀有度获取颜色
|
||||
func _get_rarity_color(rarity: String) -> String:
|
||||
match rarity:
|
||||
"普通":
|
||||
return "#90EE90"
|
||||
"优良":
|
||||
return "#87CEEB"
|
||||
"稀有":
|
||||
return "#DDA0DD"
|
||||
"史诗":
|
||||
return "#9932CC"
|
||||
"传奇":
|
||||
return "#FF8C00"
|
||||
_:
|
||||
return "#FFFFFF"
|
||||
|
||||
# =============================================================================
|
||||
# 核心功能
|
||||
# =============================================================================
|
||||
|
||||
## 生成15个奖励模板
|
||||
func _generate_reward_templates() -> void:
|
||||
# 清空现有模板
|
||||
for child in grid.get_children():
|
||||
if child != reward_item:
|
||||
child.queue_free()
|
||||
|
||||
reward_templates.clear()
|
||||
|
||||
# 生成15个模板(包括原有的一个)
|
||||
for i in range(15):
|
||||
var template: RichTextLabel
|
||||
|
||||
if i == 0:
|
||||
# 使用原有的模板
|
||||
template = reward_item
|
||||
else:
|
||||
# 创建新的模板
|
||||
template = reward_item.duplicate()
|
||||
grid.add_child(template)
|
||||
|
||||
# 设置不同的颜色
|
||||
template.self_modulate = template_colors[i]
|
||||
template.bbcode_enabled = true
|
||||
template.threaded = true
|
||||
|
||||
reward_templates.append(template)
|
||||
|
||||
## 更新模板显示
|
||||
func _update_template_display() -> void:
|
||||
var sample_rewards = _generate_sample_rewards()
|
||||
|
||||
for i in range(reward_templates.size()):
|
||||
var template = reward_templates[i]
|
||||
if i < sample_rewards.size():
|
||||
var reward = sample_rewards[i]
|
||||
template.text = _format_template_text(reward)
|
||||
template.show()
|
||||
else:
|
||||
template.hide()
|
||||
|
||||
## 生成示例奖励显示
|
||||
func _generate_sample_rewards() -> Array:
|
||||
var sample_rewards = []
|
||||
|
||||
# 添加基础奖励示例
|
||||
sample_rewards.append({"type": "coins", "amount_range": [100, 300], "rarity": "普通"})
|
||||
sample_rewards.append({"type": "exp", "amount_range": [50, 150], "rarity": "普通"})
|
||||
sample_rewards.append({"type": "empty", "name": "谢谢惠顾", "rarity": "空奖"})
|
||||
|
||||
# 添加各品质种子示例
|
||||
var quality_examples = ["普通", "优良", "稀有", "史诗", "传奇"]
|
||||
for quality in quality_examples:
|
||||
var example_seeds = []
|
||||
for seed_name in seed_rewards.keys():
|
||||
if seed_rewards[seed_name].rarity == quality:
|
||||
example_seeds.append(seed_name)
|
||||
|
||||
if example_seeds.size() > 0:
|
||||
var seed_name = example_seeds[0] # 取第一个作为示例
|
||||
sample_rewards.append({
|
||||
"type": "seed",
|
||||
"name": seed_name,
|
||||
"rarity": quality,
|
||||
"amount_range": [1, 3] if quality != "传奇" else [1, 1]
|
||||
})
|
||||
|
||||
# 添加礼包示例
|
||||
sample_rewards.append({"type": "package", "name": "成长套餐", "rarity": "优良"})
|
||||
sample_rewards.append({"type": "package", "name": "稀有礼包", "rarity": "稀有"})
|
||||
sample_rewards.append({"type": "package", "name": "传奇大礼包", "rarity": "传奇"})
|
||||
|
||||
# 添加高级奖励示例
|
||||
sample_rewards.append({"type": "coins", "amount_range": [1000, 2000], "rarity": "史诗"})
|
||||
sample_rewards.append({"type": "exp", "amount_range": [500, 1000], "rarity": "传奇"})
|
||||
|
||||
return sample_rewards.slice(0, 15) # 只取前15个
|
||||
|
||||
## 格式化模板文本
|
||||
func _format_template_text(reward: Dictionary) -> String:
|
||||
var text = "[center]"
|
||||
|
||||
match reward.type:
|
||||
"empty":
|
||||
text += "[color=%s]%s[/color]\n" % [base_rewards.empty.color, base_rewards.empty.icon]
|
||||
text += "[color=%s]%s[/color]" % [base_rewards.empty.color, reward.get("name", "谢谢惠顾")]
|
||||
|
||||
"package":
|
||||
var rarity_color = _get_rarity_color(reward.get("rarity", "普通"))
|
||||
text += "[color=%s]🎁[/color]\n" % [rarity_color]
|
||||
text += "[color=%s]%s[/color]\n" % [rarity_color, reward.get("name", "礼包")]
|
||||
text += "[color=#CCCCCC](%s)[/color]" % reward.get("rarity", "普通")
|
||||
|
||||
"coins":
|
||||
var rarity_color = _get_rarity_color(reward.get("rarity", "普通"))
|
||||
text += "[color=%s]%s[/color]\n" % [rarity_color, base_rewards.coins.icon]
|
||||
if reward.has("amount_range"):
|
||||
text += "[color=%s]%d-%d[/color]\n" % [rarity_color, reward.amount_range[0], reward.amount_range[1]]
|
||||
text += "[color=%s]%s[/color]" % [rarity_color, base_rewards.coins.name]
|
||||
|
||||
"exp":
|
||||
var rarity_color = _get_rarity_color(reward.get("rarity", "普通"))
|
||||
text += "[color=%s]%s[/color]\n" % [rarity_color, base_rewards.exp.icon]
|
||||
if reward.has("amount_range"):
|
||||
text += "[color=%s]%d-%d[/color]\n" % [rarity_color, reward.amount_range[0], reward.amount_range[1]]
|
||||
text += "[color=%s]%s[/color]" % [rarity_color, base_rewards.exp.name]
|
||||
|
||||
"seed":
|
||||
if reward.has("name") and reward.name in seed_rewards:
|
||||
var seed_info = seed_rewards[reward.name]
|
||||
text += "[color=%s]%s[/color]\n" % [seed_info.color, seed_info.icon]
|
||||
text += "[color=%s]%s[/color]\n" % [seed_info.color, reward.name]
|
||||
if reward.has("amount_range"):
|
||||
text += "[color=%s]x%d-%d[/color]\n" % [seed_info.color, reward.amount_range[0], reward.amount_range[1]]
|
||||
text += "[color=#CCCCCC](%s)[/color]" % seed_info.rarity
|
||||
else:
|
||||
text += "[color=#90EE90]🌱[/color]\n"
|
||||
text += "[color=#90EE90]种子[/color]"
|
||||
|
||||
text += "[/center]"
|
||||
return text
|
||||
|
||||
## 执行网络抽奖
|
||||
func _perform_network_draw(draw_type: String) -> void:
|
||||
if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server():
|
||||
_show_error_message("网络未连接,无法进行抽奖")
|
||||
return
|
||||
|
||||
# 检查费用
|
||||
var cost = draw_costs.get(draw_type, 800)
|
||||
if main_game and main_game.money < cost:
|
||||
_show_error_message("金币不足,需要 %d 金币" % cost)
|
||||
return
|
||||
|
||||
# 发送抽奖请求
|
||||
var success = tcp_network_manager_panel.sendLuckyDraw(draw_type)
|
||||
if not success:
|
||||
_show_error_message("发送抽奖请求失败")
|
||||
return
|
||||
|
||||
# 显示等待动画
|
||||
_show_waiting_animation(draw_type)
|
||||
|
||||
## 显示等待动画
|
||||
func _show_waiting_animation(draw_type: String) -> void:
|
||||
# 禁用抽奖按钮
|
||||
_set_draw_buttons_enabled(false)
|
||||
|
||||
# 隐藏结果区域
|
||||
lucky_draw_reward.hide()
|
||||
|
||||
# 播放期待动画
|
||||
_play_anticipation_animation()
|
||||
|
||||
## 处理服务器抽奖响应
|
||||
func handle_lucky_draw_response(response: Dictionary) -> void:
|
||||
# 停止期待动画
|
||||
_stop_anticipation_animation()
|
||||
|
||||
# 重新启用按钮
|
||||
_set_draw_buttons_enabled(true)
|
||||
|
||||
if response.get("success", false):
|
||||
var rewards = response.get("rewards", [])
|
||||
var draw_type = response.get("draw_type", "single")
|
||||
var cost = response.get("cost", 0)
|
||||
|
||||
# 显示抽奖结果
|
||||
_show_server_draw_results(rewards, draw_type, cost)
|
||||
|
||||
# 发送信号
|
||||
draw_completed.emit(rewards, draw_type)
|
||||
|
||||
else:
|
||||
var error_message = response.get("message", "抽奖失败")
|
||||
_show_error_message(error_message)
|
||||
draw_failed.emit(error_message)
|
||||
|
||||
## 显示服务器返回的抽奖结果
|
||||
func _show_server_draw_results(rewards: Array, draw_type: String, cost: int) -> void:
|
||||
current_rewards = rewards
|
||||
|
||||
# 显示结果(动画已在handle_lucky_draw_response中停止)
|
||||
var result_text = _format_server_draw_results(rewards, draw_type, cost)
|
||||
lucky_draw_reward.text = result_text
|
||||
lucky_draw_reward.show()
|
||||
|
||||
# 播放结果动画
|
||||
_play_result_animation()
|
||||
|
||||
## 格式化服务器抽奖结果文本
|
||||
func _format_server_draw_results(rewards: Array, draw_type: String, cost: int) -> String:
|
||||
var type_names = {
|
||||
"single": "单抽",
|
||||
"five": "五连抽",
|
||||
"ten": "十连抽"
|
||||
}
|
||||
|
||||
var text = "[center][color=#FFD700]🎊 %s结果 🎊[/color][/center]\n" % type_names.get(draw_type, draw_type)
|
||||
text += "[center][color=#87CEEB]消费 %d 金币[/color][/center]\n" % cost
|
||||
|
||||
# 统计稀有度
|
||||
var stats = _count_server_reward_rarity(rewards)
|
||||
|
||||
# 显示稀有度统计
|
||||
var stat_parts = []
|
||||
if stats.legendary > 0:
|
||||
stat_parts.append("[color=#FF8C00]🏆传奇x%d[/color]" % stats.legendary)
|
||||
if stats.epic > 0:
|
||||
stat_parts.append("[color=#9932CC]💎史诗x%d[/color]" % stats.epic)
|
||||
if stats.rare > 0:
|
||||
stat_parts.append("[color=#DDA0DD]⭐稀有x%d[/color]" % stats.rare)
|
||||
if stats.package > 0:
|
||||
stat_parts.append("[color=#FF69B4]🎁礼包x%d[/color]" % stats.package)
|
||||
|
||||
if stat_parts.size() > 0:
|
||||
text += "[center]%s[/center]\n" % " ".join(stat_parts)
|
||||
|
||||
text += "\n"
|
||||
|
||||
# 显示具体奖励
|
||||
for reward in rewards:
|
||||
text += _format_single_server_reward(reward) + "\n"
|
||||
|
||||
# 鼓励文案
|
||||
if stats.empty_only:
|
||||
text += "[center][color=#87CEEB]💪 别灰心,下次一定能中大奖![/color][/center]"
|
||||
elif stats.legendary > 0:
|
||||
text += "[center][color=#FF8C00]🎉 恭喜获得传奇奖励![/color][/center]"
|
||||
elif stats.epic > 0:
|
||||
text += "[center][color=#9932CC]✨ 史诗奖励,运气不错![/color][/center]"
|
||||
|
||||
return text
|
||||
|
||||
## 统计服务器奖励稀有度
|
||||
func _count_server_reward_rarity(rewards: Array) -> Dictionary:
|
||||
var stats = {
|
||||
"legendary": 0,
|
||||
"epic": 0,
|
||||
"rare": 0,
|
||||
"package": 0,
|
||||
"empty": 0,
|
||||
"empty_only": false
|
||||
}
|
||||
|
||||
for reward in rewards:
|
||||
var rarity = reward.get("rarity", "普通")
|
||||
match rarity:
|
||||
"传奇":
|
||||
stats.legendary += 1
|
||||
"史诗":
|
||||
stats.epic += 1
|
||||
"稀有":
|
||||
stats.rare += 1
|
||||
"空奖":
|
||||
stats.empty += 1
|
||||
|
||||
if reward.get("type") == "package":
|
||||
stats.package += 1
|
||||
|
||||
stats.empty_only = (stats.empty == rewards.size() and rewards.size() == 1)
|
||||
return stats
|
||||
|
||||
## 格式化单个服务器奖励显示
|
||||
func _format_single_server_reward(reward: Dictionary) -> String:
|
||||
var text = ""
|
||||
var reward_type = reward.get("type", "")
|
||||
var rarity = reward.get("rarity", "普通")
|
||||
var rarity_color = _get_rarity_color(rarity)
|
||||
|
||||
match reward_type:
|
||||
"empty":
|
||||
var reward_name = reward.get("name", "空奖励")
|
||||
text = "[color=%s]😅 %s[/color]" % [rarity_color, reward_name]
|
||||
|
||||
"package":
|
||||
var reward_name = reward.get("name", "礼包")
|
||||
text = "[color=%s]🎁 %s[/color]\n" % [rarity_color, reward_name]
|
||||
text += "[color=#DDDDDD]内含:[/color] "
|
||||
|
||||
var content_parts = []
|
||||
if reward.has("contents"):
|
||||
for content in reward.contents:
|
||||
var part = _format_package_content(content)
|
||||
if part != "":
|
||||
content_parts.append(part)
|
||||
|
||||
text += " ".join(content_parts)
|
||||
|
||||
"coins":
|
||||
var amount = reward.get("amount", 0)
|
||||
text = "[color=%s]💰 金币 +%d[/color]" % [rarity_color, amount]
|
||||
|
||||
"exp":
|
||||
var amount = reward.get("amount", 0)
|
||||
text = "[color=%s]⭐ 经验 +%d[/color]" % [rarity_color, amount]
|
||||
|
||||
"seed":
|
||||
var reward_name = reward.get("name", "种子")
|
||||
var amount = reward.get("amount", 0)
|
||||
text = "[color=%s]🌱 %s x%d[/color] [color=#CCCCCC](%s)[/color]" % [
|
||||
rarity_color, reward_name, amount, rarity
|
||||
]
|
||||
|
||||
_:
|
||||
text = "[color=#CCCCCC]未知奖励[/color]"
|
||||
|
||||
return text
|
||||
|
||||
## 格式化礼包内容
|
||||
func _format_package_content(content: Dictionary) -> String:
|
||||
var content_type = content.get("type", "")
|
||||
var amount = content.get("amount", 0)
|
||||
|
||||
match content_type:
|
||||
"coins":
|
||||
return "[color=#FFD700]💰%d[/color]" % amount
|
||||
"exp":
|
||||
return "[color=#00BFFF]⭐%d[/color]" % amount
|
||||
"seed":
|
||||
var seed_name = content.get("name", "种子")
|
||||
return "[color=#90EE90]🌱%sx%d[/color]" % [seed_name, amount]
|
||||
_:
|
||||
return ""
|
||||
|
||||
## 播放期待动画(简化版)
|
||||
func _play_anticipation_animation() -> void:
|
||||
"""播放期待动画"""
|
||||
# 停止之前的动画
|
||||
_stop_anticipation_animation()
|
||||
|
||||
# 创建简单的闪烁动画
|
||||
anticipation_tween = create_tween()
|
||||
anticipation_tween.set_loops()
|
||||
|
||||
for template in reward_templates:
|
||||
if template.visible:
|
||||
anticipation_tween.parallel().tween_method(
|
||||
func(progress: float): _anticipation_flash(template, progress),
|
||||
0.0, 1.0, 0.5
|
||||
)
|
||||
|
||||
|
||||
|
||||
func _anticipation_flash(template: RichTextLabel, progress: float) -> void:
|
||||
"""期待动画闪烁效果"""
|
||||
var flash_intensity = 1.0 + sin(progress * PI * 2) * 0.3
|
||||
template.modulate = Color(flash_intensity, flash_intensity, flash_intensity, 1.0)
|
||||
|
||||
## 停止期待动画
|
||||
func _stop_anticipation_animation() -> void:
|
||||
if anticipation_tween:
|
||||
anticipation_tween.kill()
|
||||
anticipation_tween = null
|
||||
|
||||
# 恢复所有模板的正常颜色
|
||||
for i in range(reward_templates.size()):
|
||||
var template = reward_templates[i]
|
||||
template.modulate = Color.WHITE
|
||||
|
||||
## 播放结果动画
|
||||
func _play_result_animation() -> void:
|
||||
var tween = create_tween()
|
||||
|
||||
# 奖励区域动画
|
||||
lucky_draw_reward.modulate.a = 0.0
|
||||
lucky_draw_reward.scale = Vector2(0.8, 0.8)
|
||||
|
||||
tween.parallel().tween_property(lucky_draw_reward, "modulate:a", 1.0, 0.5)
|
||||
tween.parallel().tween_property(lucky_draw_reward, "scale", Vector2(1.0, 1.0), 0.5)
|
||||
|
||||
## 显示错误信息
|
||||
func _show_error_message(message: String) -> void:
|
||||
lucky_draw_reward.text = "[center][color=#FF6B6B]❌ %s[/color][/center]" % message
|
||||
lucky_draw_reward.show()
|
||||
|
||||
# 2秒后隐藏错误信息
|
||||
await get_tree().create_timer(2.0).timeout
|
||||
lucky_draw_reward.hide()
|
||||
|
||||
# =============================================================================
|
||||
# 事件处理
|
||||
# =============================================================================
|
||||
|
||||
## 关闭面板
|
||||
func _on_quit_button_pressed() -> void:
|
||||
self.hide()
|
||||
|
||||
## 单次抽奖
|
||||
func _on_lucky_draw_button_pressed() -> void:
|
||||
_perform_network_draw("single")
|
||||
|
||||
## 五连抽
|
||||
func _on_five_lucky_draw_button_pressed() -> void:
|
||||
_perform_network_draw("five")
|
||||
|
||||
## 十连抽
|
||||
func _on_ten_lucky_draw_button_pressed() -> void:
|
||||
_perform_network_draw("ten")
|
||||
|
||||
## 设置抽奖按钮可用状态
|
||||
func _set_draw_buttons_enabled(enabled: bool) -> void:
|
||||
var buttons = [
|
||||
$HBox/LuckyDrawButton,
|
||||
$HBox/FiveLuckyDrawButton,
|
||||
$HBox/TenLuckyDrawButton
|
||||
]
|
||||
|
||||
for button in buttons:
|
||||
if button:
|
||||
button.disabled = not enabled
|
||||
|
||||
# =============================================================================
|
||||
# 公共接口方法
|
||||
# =============================================================================
|
||||
|
||||
## 获取当前奖励结果
|
||||
func get_current_rewards() -> Array:
|
||||
return current_rewards
|
||||
|
||||
## 清空抽奖结果
|
||||
func clear_draw_results() -> void:
|
||||
current_rewards.clear()
|
||||
lucky_draw_reward.hide()
|
||||
|
||||
## 刷新奖励显示(当作物数据更新时调用)
|
||||
func refresh_reward_display() -> void:
|
||||
_load_crop_data_and_build_rewards()
|
||||
_update_template_display()
|
||||
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
1
Script/BigPanel/LuckyDrawPanel.gd.uid
Normal file
1
Script/BigPanel/LuckyDrawPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://65e0rl31fx0i
|
||||
276
Script/BigPanel/PetBagPanel.gd
Normal file
276
Script/BigPanel/PetBagPanel.gd
Normal file
@@ -0,0 +1,276 @@
|
||||
extends Panel
|
||||
# 这是宠物背包面板,用来显示玩家获得的宠物
|
||||
|
||||
# 宠物背包格子容器
|
||||
@onready var bag_grid: GridContainer = $ScrollContainer/Bag_Grid
|
||||
@onready var quit_button: Button = $QuitButton
|
||||
@onready var refresh_button: Button = $RefreshButton
|
||||
@onready var scroll_container = $ScrollContainer
|
||||
|
||||
# 预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var pet_store_panel: Panel = $'../PetStorePanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
@onready var pet_inform_panel: Panel = $'../../SmallPanel/PetInformPanel'
|
||||
|
||||
# 宠物配置数据
|
||||
var pet_config: Dictionary = {}
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接关闭按钮信号
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
refresh_button.pressed.connect(self._on_refresh_button_pressed)
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
# 初始化宠物背包
|
||||
func init_pet_bag():
|
||||
|
||||
# 显示背包中的宠物
|
||||
update_pet_bag_ui()
|
||||
|
||||
# 更新宠物背包UI(同步版本,用于刷新按钮)
|
||||
func update_pet_bag_ui():
|
||||
if scroll_container:
|
||||
scroll_container.clip_contents = false
|
||||
|
||||
# 设置GridContainer也不裁剪内容
|
||||
if bag_grid:
|
||||
bag_grid.clip_contents = false
|
||||
|
||||
# 清空宠物背包格子
|
||||
for child in bag_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 确保宠物背包存在
|
||||
if not "pet_bag" in main_game or main_game.pet_bag == null:
|
||||
main_game.pet_bag = []
|
||||
|
||||
# 为背包中的每个宠物创建按钮
|
||||
for pet_data in main_game.pet_bag:
|
||||
var pet_name = pet_data.get("基本信息", {}).get("宠物类型", "未知宠物")
|
||||
var pet_level = pet_data.get("等级经验", {}).get("宠物等级", 1)
|
||||
var pet_owner_name = pet_data.get("基本信息", {}).get("宠物名称", pet_name)
|
||||
|
||||
# 创建宠物按钮
|
||||
var button = _create_pet_button(pet_name, pet_level, pet_owner_name)
|
||||
|
||||
# 更新按钮文本显示宠物信息
|
||||
button.text = str(pet_owner_name + "\n等级:" + str(pet_level))
|
||||
|
||||
# 根据是否处于访问模式连接不同的事件
|
||||
if main_game.is_visiting_mode:
|
||||
# 访问模式下,点击宠物只显示信息
|
||||
button.pressed.connect(func(): _on_visit_pet_selected(pet_name, pet_data))
|
||||
else:
|
||||
# 正常模式下,连接宠物选择事件
|
||||
button.pressed.connect(func(): _on_pet_selected(pet_name, pet_data, button))
|
||||
|
||||
bag_grid.add_child(button)
|
||||
|
||||
# 创建宠物按钮
|
||||
func _create_pet_button(pet_name: String, pet_level: int, pet_owner_name: String) -> Button:
|
||||
# 使用按钮作为宠物背包按钮的样式
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 关闭按钮的内容裁剪,允许图片超出按钮边界
|
||||
button.clip_contents = false
|
||||
|
||||
|
||||
# 添加工具提示
|
||||
button.tooltip_text = str(
|
||||
"宠物: " + pet_name + "\n" +
|
||||
"名称: " + pet_owner_name + "\n" +
|
||||
"等级: " + str(pet_level) + "\n" +
|
||||
"点击查看宠物详情"
|
||||
)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").text = "宠物"
|
||||
button.get_node("Title").modulate = Color.MAGENTA # 宠物标题使用洋红色
|
||||
|
||||
# 更新按钮的宠物图片
|
||||
_update_button_pet_image(button, pet_name)
|
||||
|
||||
return button
|
||||
|
||||
# 更新按钮的宠物图片
|
||||
func _update_button_pet_image(button: Button, pet_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var pet_image = button.get_node_or_null("CropImage")
|
||||
if not pet_image:
|
||||
return
|
||||
|
||||
# 从宠物配置获取场景路径
|
||||
var texture = null
|
||||
var pet_config = _load_pet_config()
|
||||
|
||||
if pet_config.has(pet_name):
|
||||
var pet_info = pet_config[pet_name]
|
||||
var scene_path = pet_info.get("场景路径", "")
|
||||
|
||||
if scene_path != "" and ResourceLoader.exists(scene_path):
|
||||
# 加载宠物场景并获取PetImage的纹理
|
||||
var pet_scene = load(scene_path)
|
||||
if pet_scene:
|
||||
var pet_instance = pet_scene.instantiate()
|
||||
var pet_image_node = pet_instance.get_node_or_null("PetImage")
|
||||
if pet_image_node and pet_image_node.sprite_frames:
|
||||
# 获取默认动画的第一帧
|
||||
var animation_names = pet_image_node.sprite_frames.get_animation_names()
|
||||
if animation_names.size() > 0:
|
||||
var default_animation = animation_names[0]
|
||||
var frame_count = pet_image_node.sprite_frames.get_frame_count(default_animation)
|
||||
if frame_count > 0:
|
||||
texture = pet_image_node.sprite_frames.get_frame_texture(default_animation, 0)
|
||||
pet_instance.queue_free()
|
||||
|
||||
# 设置图片
|
||||
if texture:
|
||||
pet_image.texture = texture
|
||||
pet_image.visible = true
|
||||
pet_image.scale = Vector2(10, 10)
|
||||
# 确保图片居中显示
|
||||
pet_image.centered = true
|
||||
else:
|
||||
pet_image.visible = false
|
||||
|
||||
# 加载宠物配置数据
|
||||
func _load_pet_config() -> Dictionary:
|
||||
var file = FileAccess.open("res://Data/pet_data.json", FileAccess.READ)
|
||||
if file == null:
|
||||
return {}
|
||||
|
||||
var json = JSON.new()
|
||||
var json_string = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var parse_result = json.parse(json_string)
|
||||
if parse_result != OK:
|
||||
return {}
|
||||
|
||||
return json.data
|
||||
|
||||
# 计算宠物年龄(以天为单位)
|
||||
func _calculate_pet_age(birthday: String) -> int:
|
||||
if birthday == "":
|
||||
return 0
|
||||
|
||||
# 解析生日字符串,格式:2025年7月5日10时7分25秒
|
||||
var birthday_parts = birthday.split("年")
|
||||
if birthday_parts.size() < 2:
|
||||
return 0
|
||||
|
||||
var year = int(birthday_parts[0])
|
||||
var rest = birthday_parts[1]
|
||||
|
||||
var month_parts = rest.split("月")
|
||||
if month_parts.size() < 2:
|
||||
return 0
|
||||
|
||||
var month = int(month_parts[0])
|
||||
var rest2 = month_parts[1]
|
||||
|
||||
var day_parts = rest2.split("日")
|
||||
if day_parts.size() < 2:
|
||||
return 0
|
||||
|
||||
var day = int(day_parts[0])
|
||||
var rest3 = day_parts[1]
|
||||
|
||||
var hour_parts = rest3.split("时")
|
||||
if hour_parts.size() < 2:
|
||||
return 0
|
||||
|
||||
var hour = int(hour_parts[0])
|
||||
var rest4 = hour_parts[1]
|
||||
|
||||
var minute_parts = rest4.split("分")
|
||||
if minute_parts.size() < 2:
|
||||
return 0
|
||||
|
||||
var minute = int(minute_parts[0])
|
||||
var rest5 = minute_parts[1]
|
||||
|
||||
var second_parts = rest5.split("秒")
|
||||
if second_parts.size() < 1:
|
||||
return 0
|
||||
|
||||
var second = int(second_parts[0])
|
||||
|
||||
# 将生日转换为Unix时间戳
|
||||
var birthday_dict = {
|
||||
"year": year,
|
||||
"month": month,
|
||||
"day": day,
|
||||
"hour": hour,
|
||||
"minute": minute,
|
||||
"second": second
|
||||
}
|
||||
|
||||
var birthday_timestamp = Time.get_unix_time_from_datetime_dict(birthday_dict)
|
||||
var current_timestamp = Time.get_unix_time_from_system()
|
||||
|
||||
# 计算天数差
|
||||
var age_seconds = current_timestamp - birthday_timestamp
|
||||
var age_days = int(age_seconds / (24 * 3600))
|
||||
|
||||
return max(0, age_days)
|
||||
|
||||
|
||||
# 正常模式下的宠物点击处理 - 查看宠物信息
|
||||
func _on_pet_selected(pet_name: String, pet_data: Dictionary, button: Button):
|
||||
# 显示宠物信息面板
|
||||
if pet_inform_panel:
|
||||
pet_inform_panel.show_pet_info(pet_name, pet_data)
|
||||
pet_inform_panel.show()
|
||||
|
||||
|
||||
# 访问模式下的宠物点击处理
|
||||
func _on_visit_pet_selected(pet_name: String, pet_data: Dictionary):
|
||||
# 显示宠物信息面板
|
||||
if pet_inform_panel:
|
||||
pet_inform_panel.show_pet_info(pet_name, pet_data)
|
||||
pet_inform_panel.show()
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
# 关闭宠物背包面板
|
||||
func _on_quit_button_pressed() -> void:
|
||||
self.hide()
|
||||
|
||||
# 手动刷新宠物背包面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 刷新宠物背包UI
|
||||
update_pet_bag_ui()
|
||||
Toast.show("宠物背包已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
update_pet_bag_ui()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
#=========================面板通用处理=========================
|
||||
1
Script/BigPanel/PetBagPanel.gd.uid
Normal file
1
Script/BigPanel/PetBagPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bdhwvqsmakna2
|
||||
292
Script/BigPanel/PetStorePanel.gd
Normal file
292
Script/BigPanel/PetStorePanel.gd
Normal file
@@ -0,0 +1,292 @@
|
||||
extends Panel
|
||||
# 这是宠物商店面板,用来展示各种宠物
|
||||
|
||||
# 宠物商店格子容器
|
||||
@onready var store_grid: GridContainer = $ScrollContainer/Store_Grid
|
||||
@onready var quit_button: Button = $QuitButton
|
||||
@onready var refresh_button: Button = $RefreshButton
|
||||
@onready var scroll_container = $ScrollContainer
|
||||
|
||||
# 预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var pet_bag_panel: Panel = $'../PetBagPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
@onready var batch_buy_popup: PanelContainer = $'../../DiaLog/BatchBuyPopup'
|
||||
|
||||
# 宠物配置数据
|
||||
var pet_config: Dictionary = {}
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接关闭按钮信号
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
refresh_button.pressed.connect(self._on_refresh_button_pressed)
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
|
||||
# 初始化宠物商店
|
||||
func init_pet_store():
|
||||
# 从主游戏脚本获取宠物配置数据
|
||||
_load_pet_config_from_main()
|
||||
update_pet_store_ui()
|
||||
|
||||
# 更新宠物商店UI
|
||||
func update_pet_store_ui():
|
||||
if scroll_container:
|
||||
scroll_container.clip_contents = false
|
||||
|
||||
# 设置GridContainer也不裁剪内容
|
||||
if store_grid:
|
||||
store_grid.clip_contents = false
|
||||
|
||||
# 清空宠物商店格子
|
||||
for child in store_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
print("更新宠物商店UI,宠物种类:", pet_config.size())
|
||||
|
||||
# 为每个宠物配置创建按钮
|
||||
for pet_name in pet_config.keys():
|
||||
var pet_info = pet_config[pet_name]
|
||||
var purchase_info = pet_info.get("购买信息", {})
|
||||
var can_buy = purchase_info.get("能否购买", false)
|
||||
|
||||
# 只显示可购买的宠物
|
||||
if not can_buy:
|
||||
continue
|
||||
|
||||
var pet_cost = purchase_info.get("购买价格", 0)
|
||||
var basic_info = pet_info.get("基本信息", {})
|
||||
var pet_desc = basic_info.get("简介", "可爱的宠物伙伴")
|
||||
|
||||
# 检查玩家是否已购买该宠物
|
||||
var is_owned = _check_pet_owned(pet_name)
|
||||
|
||||
# 创建宠物按钮
|
||||
var button = _create_pet_button(pet_name, pet_cost, pet_desc, is_owned)
|
||||
|
||||
# 更新按钮文本显示价格和状态
|
||||
if is_owned:
|
||||
button.text = str(pet_name + "\n(已购买)")
|
||||
button.disabled = true
|
||||
else:
|
||||
button.text = str(pet_name + "\n价格:" + str(pet_cost) + "元")
|
||||
# 连接购买点击事件
|
||||
button.pressed.connect(func(): _on_store_pet_selected(pet_name, pet_cost, pet_desc))
|
||||
|
||||
store_grid.add_child(button)
|
||||
|
||||
# 检查玩家是否已拥有某种宠物
|
||||
func _check_pet_owned(pet_name: String) -> bool:
|
||||
if not main_game.pet_bag:
|
||||
return false
|
||||
|
||||
for pet_data in main_game.pet_bag:
|
||||
var basic_info = pet_data.get("基本信息", {})
|
||||
var pet_type = basic_info.get("宠物类型", "")
|
||||
if pet_type == pet_name:
|
||||
return true
|
||||
return false
|
||||
|
||||
# 创建宠物按钮
|
||||
func _create_pet_button(pet_name: String, pet_cost: int, pet_desc: String, is_owned: bool = false) -> Button:
|
||||
# 使用按钮作为宠物商店按钮的样式
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
|
||||
# 关闭按钮的内容裁剪,允许图片超出按钮边界
|
||||
button.clip_contents = false
|
||||
|
||||
# 设置按钮文本
|
||||
button.text = pet_name
|
||||
|
||||
# 添加工具提示
|
||||
button.tooltip_text = str(
|
||||
"宠物: " + pet_name + "\n" +
|
||||
"价格: " + str(pet_cost) + "元\n" +
|
||||
"描述: " + pet_desc + "\n" +
|
||||
"点击购买宠物"
|
||||
)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
if is_owned:
|
||||
button.get_node("Title").text = "已购买"
|
||||
button.get_node("Title").modulate = Color.GRAY # 已购买使用灰色
|
||||
else:
|
||||
button.get_node("Title").text = "宠物商店"
|
||||
button.get_node("Title").modulate = Color.PINK # 宠物商店标题使用粉色
|
||||
|
||||
# 更新按钮的宠物图片
|
||||
_update_button_pet_image(button, pet_name)
|
||||
|
||||
return button
|
||||
|
||||
# 更新按钮的宠物图片
|
||||
func _update_button_pet_image(button: Button, pet_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var pet_image = button.get_node_or_null("CropImage")
|
||||
if not pet_image:
|
||||
return
|
||||
|
||||
# 从宠物配置获取场景路径
|
||||
var texture = null
|
||||
if pet_config.has(pet_name):
|
||||
var pet_info = pet_config[pet_name]
|
||||
var scene_path = pet_info.get("场景路径", "")
|
||||
|
||||
if scene_path != "" and ResourceLoader.exists(scene_path):
|
||||
# 加载宠物场景并获取PetImage的纹理
|
||||
var pet_scene = load(scene_path)
|
||||
if pet_scene:
|
||||
var pet_instance = pet_scene.instantiate()
|
||||
var pet_image_node = pet_instance.get_node_or_null("PetImage")
|
||||
if pet_image_node and pet_image_node.sprite_frames:
|
||||
# 获取默认动画的第一帧
|
||||
var default_animation = pet_image_node.sprite_frames.get_animation_names()[0]
|
||||
var frame_count = pet_image_node.sprite_frames.get_frame_count(default_animation)
|
||||
if frame_count > 0:
|
||||
texture = pet_image_node.sprite_frames.get_frame_texture(default_animation, 0)
|
||||
pet_instance.queue_free()
|
||||
|
||||
|
||||
# 设置图片
|
||||
if texture:
|
||||
pet_image.texture = texture
|
||||
pet_image.visible = true
|
||||
pet_image.scale = Vector2(10, 10)
|
||||
# 确保图片居中显示
|
||||
pet_image.centered = true
|
||||
|
||||
else:
|
||||
pet_image.visible = false
|
||||
|
||||
# 从主游戏脚本获取宠物配置数据
|
||||
func _load_pet_config_from_main():
|
||||
# 从宠物数据文件加载配置
|
||||
var file = FileAccess.open("res://Data/pet_data.json", FileAccess.READ)
|
||||
if file == null:
|
||||
print("宠物商店:无法打开宠物配置文件")
|
||||
pet_config = {}
|
||||
return
|
||||
|
||||
var json = JSON.new()
|
||||
var json_string = file.get_as_text()
|
||||
file.close()
|
||||
|
||||
var parse_result = json.parse(json_string)
|
||||
if parse_result != OK:
|
||||
print("宠物商店:解析宠物配置文件失败")
|
||||
pet_config = {}
|
||||
return
|
||||
|
||||
pet_config = json.data
|
||||
print("宠物商店:成功加载宠物配置数据,宠物种类:", pet_config.size())
|
||||
|
||||
# 商店宠物点击处理 - 购买宠物
|
||||
func _on_store_pet_selected(pet_name: String, pet_cost: int, pet_desc: String):
|
||||
# 检查玩家金钱是否足够
|
||||
if main_game.money < pet_cost:
|
||||
Toast.show("金钱不足!需要 " + str(pet_cost) + " 元,当前只有 " + str(main_game.money) + " 元", Color.RED, 3.0, 1.0)
|
||||
return
|
||||
|
||||
# 显示购买确认对话框(宠物只能购买1只,不需要批量购买)
|
||||
_show_buy_confirmation_dialog(pet_name, pet_cost, pet_desc)
|
||||
|
||||
# 显示购买确认对话框
|
||||
func _show_buy_confirmation_dialog(pet_name: String, pet_cost: int, pet_desc: String):
|
||||
# 创建确认对话框
|
||||
var confirm_dialog = AcceptDialog.new()
|
||||
confirm_dialog.dialog_text = str(
|
||||
"确认购买宠物?\n\n" +
|
||||
"宠物名称: " + pet_name + "\n" +
|
||||
"购买价格: " + str(pet_cost) + " 元\n" +
|
||||
"宠物描述: " + pet_desc + "\n\n" +
|
||||
"当前金钱: " + str(main_game.money) + " 元\n" +
|
||||
"购买后余额: " + str(main_game.money - pet_cost) + " 元\n\n" +
|
||||
"注意:每种宠物只能购买一只!"
|
||||
)
|
||||
confirm_dialog.title = "购买宠物确认"
|
||||
confirm_dialog.ok_button_text = "确认购买"
|
||||
confirm_dialog.add_cancel_button("取消")
|
||||
|
||||
# 添加到场景
|
||||
add_child(confirm_dialog)
|
||||
|
||||
# 连接信号
|
||||
confirm_dialog.confirmed.connect(_on_confirm_buy_pet.bind(pet_name, pet_cost, confirm_dialog))
|
||||
confirm_dialog.canceled.connect(_on_cancel_buy_pet.bind(confirm_dialog))
|
||||
|
||||
# 显示对话框
|
||||
confirm_dialog.popup_centered()
|
||||
|
||||
# 确认购买宠物
|
||||
func _on_confirm_buy_pet(pet_name: String, pet_cost: int, dialog: AcceptDialog):
|
||||
# 再次检查金钱是否足够
|
||||
if main_game.money < pet_cost:
|
||||
Toast.show("金钱不足!需要 " + str(pet_cost) + " 元,当前只有 " + str(main_game.money) + " 元", Color.RED, 3.0, 1.0)
|
||||
dialog.queue_free()
|
||||
return
|
||||
|
||||
# 发送购买请求到服务器
|
||||
_send_buy_pet_request(pet_name, pet_cost)
|
||||
dialog.queue_free()
|
||||
|
||||
# 取消购买宠物
|
||||
func _on_cancel_buy_pet(dialog: AcceptDialog):
|
||||
print("取消购买宠物")
|
||||
dialog.queue_free()
|
||||
|
||||
# 发送购买宠物请求
|
||||
func _send_buy_pet_request(pet_name: String, pet_cost: int):
|
||||
# 发送购买请求到服务器
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("sendBuyPet"):
|
||||
if tcp_network_manager_panel.sendBuyPet(pet_name, pet_cost):
|
||||
# 服务器会处理购买逻辑,客户端等待响应
|
||||
print("已发送购买宠物请求:", pet_name)
|
||||
else:
|
||||
Toast.show("购买请求发送失败", Color.RED, 2.0, 1.0)
|
||||
else:
|
||||
Toast.show("网络管理器不可用", Color.RED, 2.0, 1.0)
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
# 手动刷新宠物商店面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 重新初始化宠物商店
|
||||
init_pet_store()
|
||||
Toast.show("宠物商店已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
# 关闭宠物商店面板
|
||||
func _on_quit_button_pressed() -> void:
|
||||
# 打开面板后暂时禁用相机功能
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
self.hide()
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
update_pet_store_ui()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
#=========================面板通用处理=========================
|
||||
1
Script/BigPanel/PetStorePanel.gd.uid
Normal file
1
Script/BigPanel/PetStorePanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dc1pmi1ubd2cf
|
||||
528
Script/BigPanel/PlayerBagPanel.gd
Normal file
528
Script/BigPanel/PlayerBagPanel.gd
Normal file
@@ -0,0 +1,528 @@
|
||||
extends Panel
|
||||
|
||||
# 背包格子容器
|
||||
@onready var player_bag_grid_container : GridContainer = $ScrollContainer/Bag_Grid
|
||||
@onready var quit_button : Button = $QuitButton
|
||||
@onready var refresh_button : Button = $RefreshButton
|
||||
|
||||
#各种排序过滤按钮
|
||||
@onready var sort_all_button : Button = $SortContainer/Sort_All#全部
|
||||
@onready var sort_common_button : Button = $SortContainer/Sort_Common#普通
|
||||
@onready var sort_superior_button : Button = $SortContainer/Sort_Superior#优良
|
||||
@onready var sort_rare_button : Button = $SortContainer/Sort_Rare#稀有
|
||||
@onready var sort_epic_button : Button = $SortContainer/Sort_Epic#史诗
|
||||
@onready var sort_legendary_button : Button = $SortContainer/Sort_Legendary#传奇
|
||||
@onready var sort_price_button : Button = $SortContainer/Sort_Price#价格
|
||||
@onready var sort_growtime_button : Button = $SortContainer/Sort_GrowTime#生长时间
|
||||
@onready var sort_profit_button : Button = $SortContainer/Sort_Profit#收益
|
||||
@onready var sort_level_button : Button = $SortContainer/Sort_Level#等级
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var player_ranking_panel: Panel = $'../PlayerRankingPanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
|
||||
|
||||
# 作物图片缓存(复用主游戏的缓存系统)
|
||||
var crop_textures_cache : Dictionary = {}
|
||||
var crop_frame_counts : Dictionary = {}
|
||||
|
||||
# 当前选择的地块索引,从MainGame获取
|
||||
var selected_lot_index : int = -1
|
||||
|
||||
# 当前过滤和排序设置
|
||||
var current_filter_quality = ""
|
||||
var current_sort_key = ""
|
||||
var current_sort_ascending = true
|
||||
|
||||
# 一键种植模式相关变量
|
||||
var is_planting_mode = false
|
||||
var planting_type = ""
|
||||
var one_click_plant_panel = null
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
# 连接按钮信号
|
||||
_connect_buttons()
|
||||
|
||||
# 连接可见性改变信号
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 隐藏面板(初始默认隐藏)
|
||||
self.hide()
|
||||
|
||||
|
||||
# 连接所有按钮信号
|
||||
func _connect_buttons():
|
||||
# 关闭按钮
|
||||
quit_button.pressed.connect(self._on_quit_button_pressed)
|
||||
|
||||
# 过滤按钮
|
||||
sort_all_button.pressed.connect(func(): _filter_by_quality(""))
|
||||
sort_common_button.pressed.connect(func(): _filter_by_quality("普通"))
|
||||
sort_superior_button.pressed.connect(func(): _filter_by_quality("优良"))
|
||||
sort_rare_button.pressed.connect(func(): _filter_by_quality("稀有"))
|
||||
sort_epic_button.pressed.connect(func(): _filter_by_quality("史诗"))
|
||||
sort_legendary_button.pressed.connect(func(): _filter_by_quality("传奇"))
|
||||
|
||||
# 排序按钮
|
||||
sort_price_button.pressed.connect(func(): _sort_by("花费"))
|
||||
sort_growtime_button.pressed.connect(func(): _sort_by("生长时间"))
|
||||
sort_profit_button.pressed.connect(func(): _sort_by("收益"))
|
||||
sort_level_button.pressed.connect(func(): _sort_by("等级"))
|
||||
|
||||
# 初始化玩家背包
|
||||
func init_player_bag():
|
||||
# 清空玩家背包格子
|
||||
for child in player_bag_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 显示背包中的种子
|
||||
update_player_bag_ui()
|
||||
|
||||
# 更新玩家背包UI
|
||||
func update_player_bag_ui():
|
||||
# 清空玩家背包格子
|
||||
for child in player_bag_grid_container.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# 应用过滤和排序
|
||||
var filtered_seeds = _get_filtered_and_sorted_seeds()
|
||||
|
||||
# 为背包中的每个过滤后的种子创建按钮
|
||||
for seed_item in filtered_seeds:
|
||||
var crop_name = seed_item["name"]
|
||||
var crop_quality = seed_item.get("quality", "普通")
|
||||
var crop_count = seed_item["count"]
|
||||
#print("背包物品:", crop_name, " 数量:", crop_count)
|
||||
# 创建种子按钮
|
||||
var button = _create_crop_button(crop_name, crop_quality)
|
||||
# 更新按钮文本显示数量
|
||||
button.text = str(crop_quality + "-" + crop_name + "\n数量:" + str(crop_count))
|
||||
|
||||
# 根据是否处于访问模式连接不同的事件
|
||||
if main_game.is_visiting_mode:
|
||||
# 访问模式下,点击种子只显示信息,不能种植
|
||||
button.pressed.connect(func(): _on_visit_seed_selected(crop_name, crop_count))
|
||||
else:
|
||||
# 正常模式下,连接种植事件
|
||||
button.pressed.connect(func(): _on_bag_seed_selected(crop_name))
|
||||
|
||||
player_bag_grid_container.add_child(button)
|
||||
|
||||
# 获取过滤和排序后的种子列表
|
||||
func _get_filtered_and_sorted_seeds():
|
||||
var filtered_seeds = []
|
||||
|
||||
# 收集符合条件的种子
|
||||
for seed_item in main_game.player_bag:
|
||||
# 安全获取品质字段(兼容老数据)
|
||||
var item_quality = seed_item.get("quality", "普通")
|
||||
|
||||
# 品质过滤
|
||||
if current_filter_quality != "" and item_quality != current_filter_quality:
|
||||
continue
|
||||
|
||||
# 获取种子对应的作物数据
|
||||
var crop_data = null
|
||||
if main_game.can_planted_crop.has(seed_item["name"]):
|
||||
crop_data = main_game.can_planted_crop[seed_item["name"]]
|
||||
|
||||
# 添加到过滤后的列表
|
||||
filtered_seeds.append({
|
||||
"name": seed_item["name"],
|
||||
"quality": item_quality,
|
||||
"count": seed_item["count"],
|
||||
"data": crop_data
|
||||
})
|
||||
|
||||
# 如果有排序条件且数据可用,进行排序
|
||||
if current_sort_key != "":
|
||||
filtered_seeds.sort_custom(Callable(self, "_sort_seed_items"))
|
||||
|
||||
return filtered_seeds
|
||||
|
||||
# 自定义排序函数
|
||||
func _sort_seed_items(a, b):
|
||||
# 检查是否有有效数据用于排序
|
||||
if a["data"] == null or b["data"] == null:
|
||||
# 如果某一项没有数据,将其排在后面
|
||||
if a["data"] == null and b["data"] != null:
|
||||
return false
|
||||
if a["data"] != null and b["data"] == null:
|
||||
return true
|
||||
# 如果都没有数据,按名称排序
|
||||
return a["name"] < b["name"]
|
||||
|
||||
# 确保排序键存在于数据中
|
||||
if !a["data"].has(current_sort_key) or !b["data"].has(current_sort_key):
|
||||
print("警告: 排序键 ", current_sort_key, " 在某些种子数据中不存在")
|
||||
return false
|
||||
|
||||
# 执行排序
|
||||
if current_sort_ascending:
|
||||
return a["data"][current_sort_key] < b["data"][current_sort_key]
|
||||
else:
|
||||
return a["data"][current_sort_key] > b["data"][current_sort_key]
|
||||
|
||||
# 按品质过滤种子
|
||||
func _filter_by_quality(quality: String):
|
||||
current_filter_quality = quality
|
||||
update_player_bag_ui()
|
||||
|
||||
# 按指定键排序
|
||||
func _sort_by(sort_key: String):
|
||||
# 切换排序方向或设置新排序键
|
||||
if current_sort_key == sort_key:
|
||||
current_sort_ascending = !current_sort_ascending
|
||||
else:
|
||||
current_sort_key = sort_key
|
||||
current_sort_ascending = true
|
||||
|
||||
update_player_bag_ui()
|
||||
|
||||
# 创建作物按钮
|
||||
func _create_crop_button(crop_name: String, crop_quality: String) -> Button:
|
||||
# 根据品质选择相应的进度条
|
||||
var button = main_game.item_button.duplicate()
|
||||
|
||||
|
||||
# 确保按钮可见并可点击
|
||||
button.visible = true
|
||||
button.disabled = false
|
||||
button.focus_mode = Control.FOCUS_ALL
|
||||
# 设置按钮文本
|
||||
button.text = str(crop_quality + "-" + crop_name)
|
||||
|
||||
# 添加工具提示 (tooltip)
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 将成熟时间从秒转换为天时分秒格式
|
||||
var total_seconds = int(crop["生长时间"])
|
||||
|
||||
# 定义时间单位换算
|
||||
var SECONDS_PER_MINUTE = 60
|
||||
var SECONDS_PER_HOUR = 3600
|
||||
var SECONDS_PER_DAY = 86400
|
||||
|
||||
# 计算各时间单位
|
||||
var days = total_seconds / SECONDS_PER_DAY
|
||||
total_seconds %= SECONDS_PER_DAY
|
||||
|
||||
var hours = total_seconds / SECONDS_PER_HOUR
|
||||
total_seconds %= SECONDS_PER_HOUR
|
||||
|
||||
var minutes = total_seconds / SECONDS_PER_MINUTE
|
||||
var seconds = total_seconds % SECONDS_PER_MINUTE
|
||||
|
||||
# 构建时间字符串(只显示有值的单位)
|
||||
var time_str = ""
|
||||
if days > 0:
|
||||
time_str += str(days) + "天"
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
button.tooltip_text = str(
|
||||
"作物: " + crop_name + "\n" +
|
||||
"品质: " + crop_quality + "\n" +
|
||||
"价格: " + str(crop["花费"]) + "元\n" +
|
||||
"成熟时间: " + time_str + "\n" +
|
||||
"收获收益: " + str(crop["收益"]) + "元\n" +
|
||||
"需求等级: " + str(crop["等级"]) + "\n" +
|
||||
"耐候性: " + str(crop["耐候性"]) + "\n" +
|
||||
"经验: " + str(crop["经验"]) + "点\n" +
|
||||
"描述: " + str(crop["描述"])
|
||||
)
|
||||
|
||||
# 如果按钮有标题标签,设置标题
|
||||
if button.has_node("Title"):
|
||||
button.get_node("Title").text = crop_quality
|
||||
match crop_quality:
|
||||
"普通":
|
||||
button.get_node("Title").modulate = Color.HONEYDEW#白色
|
||||
"优良":
|
||||
button.get_node("Title").modulate =Color.DODGER_BLUE#深蓝色
|
||||
"稀有":
|
||||
button.get_node("Title").modulate =Color.HOT_PINK#品红色
|
||||
"史诗":
|
||||
button.get_node("Title").modulate =Color.YELLOW#黄色
|
||||
"传奇":
|
||||
button.get_node("Title").modulate =Color.ORANGE_RED#红色
|
||||
|
||||
# 更新按钮的作物图片
|
||||
_update_button_crop_image(button, crop_name)
|
||||
|
||||
return button
|
||||
|
||||
# 从背包中选择种子并种植
|
||||
func _on_bag_seed_selected(crop_name):
|
||||
# 检查是否处于访问模式
|
||||
if main_game.is_visiting_mode:
|
||||
Toast.show("访问模式下无法种植", Color.ORANGE, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 检查是否是一键种植模式
|
||||
if is_planting_mode:
|
||||
# 一键种植模式下,回调给一键种植面板
|
||||
if one_click_plant_panel and one_click_plant_panel.has_method("on_crop_selected"):
|
||||
one_click_plant_panel.on_crop_selected(crop_name, planting_type)
|
||||
# 退出种植模式
|
||||
_exit_planting_mode()
|
||||
self.hide()
|
||||
return
|
||||
|
||||
# 从主场景获取当前选择的地块索引
|
||||
selected_lot_index = main_game.selected_lot_index
|
||||
|
||||
if selected_lot_index != -1:
|
||||
# 检查背包中是否有这个种子
|
||||
var seed_index = -1
|
||||
for i in range(len(main_game.player_bag)):
|
||||
if main_game.player_bag[i]["name"] == crop_name:
|
||||
seed_index = i
|
||||
break
|
||||
|
||||
if seed_index != -1 and main_game.player_bag[seed_index]["count"] > 0:
|
||||
# 种植种子并从背包中减少数量
|
||||
_plant_crop_from_bag(selected_lot_index, crop_name, seed_index)
|
||||
main_game.selected_lot_index = -1
|
||||
self.hide()
|
||||
|
||||
# 访问模式下的种子点击处理
|
||||
func _on_visit_seed_selected(crop_name, crop_count):
|
||||
# 显示种子信息
|
||||
var info_text = ""
|
||||
|
||||
if main_game.can_planted_crop.has(crop_name):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
var quality = crop.get("品质", "未知")
|
||||
var price = crop.get("花费", 0)
|
||||
var grow_time = crop.get("生长时间", 0)
|
||||
var profit = crop.get("收益", 0)
|
||||
var level_req = crop.get("等级", 1)
|
||||
|
||||
# 将成熟时间转换为可读格式
|
||||
var time_str = ""
|
||||
var total_seconds = int(grow_time)
|
||||
var hours = total_seconds / 3600
|
||||
var minutes = (total_seconds % 3600) / 60
|
||||
var seconds = total_seconds % 60
|
||||
|
||||
if hours > 0:
|
||||
time_str += str(hours) + "小时"
|
||||
if minutes > 0:
|
||||
time_str += str(minutes) + "分钟"
|
||||
if seconds > 0:
|
||||
time_str += str(seconds) + "秒"
|
||||
|
||||
info_text = quality + "-" + crop_name + " (数量: " + str(crop_count) + ")\n"
|
||||
info_text += "价格: " + str(price) + "元, 收益: " + str(profit) + "元\n"
|
||||
info_text += "成熟时间: " + time_str + ", 需求等级: " + str(level_req)
|
||||
else:
|
||||
info_text = crop_name + " (数量: " + str(crop_count) + ")"
|
||||
|
||||
Toast.show(info_text, Color.CYAN, 3.0, 1.0)
|
||||
print("查看种子信息: ", info_text)
|
||||
|
||||
# 从背包种植作物
|
||||
func _plant_crop_from_bag(index, crop_name, seed_index):
|
||||
var crop = main_game.can_planted_crop[crop_name]
|
||||
|
||||
# 检查是否有效的种子索引,防止越界访问
|
||||
if seed_index < 0 or seed_index >= main_game.player_bag.size():
|
||||
#print("错误:无效的种子索引 ", seed_index)
|
||||
return
|
||||
# 发送种植请求到服务器
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.sendPlantCrop(index, crop_name):
|
||||
# 关闭背包面板
|
||||
hide()
|
||||
|
||||
# 设置种植模式
|
||||
func set_planting_mode(plant_type: String, plant_panel):
|
||||
is_planting_mode = true
|
||||
planting_type = plant_type
|
||||
one_click_plant_panel = plant_panel
|
||||
Toast.show("进入种植模式:"+plant_type,Color.GREEN)
|
||||
|
||||
# 退出种植模式
|
||||
func _exit_planting_mode():
|
||||
is_planting_mode = false
|
||||
planting_type = ""
|
||||
one_click_plant_panel = null
|
||||
Toast.show("退出种植模式",Color.GREEN)
|
||||
|
||||
|
||||
# 获取作物的成熟图片(用于背包显示)
|
||||
func _get_crop_final_texture(crop_name: String) -> Texture2D:
|
||||
# 优先从主游戏的缓存中获取成熟图片
|
||||
if main_game and main_game.crop_mature_textures_cache.has(crop_name):
|
||||
return main_game.crop_mature_textures_cache[crop_name]
|
||||
|
||||
# 如果缓存中没有,再尝试加载"成熟.webp"图片
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var mature_texture_path = crop_path + "成熟.webp"
|
||||
|
||||
if ResourceLoader.exists(mature_texture_path):
|
||||
var texture = load(mature_texture_path)
|
||||
if texture:
|
||||
# 如果主游戏存在,也缓存到主游戏中
|
||||
if main_game:
|
||||
main_game.crop_mature_textures_cache[crop_name] = texture
|
||||
return texture
|
||||
|
||||
# 如果没有找到作物的成熟图片,使用默认的成熟图片
|
||||
if main_game and main_game.crop_mature_textures_cache.has("默认"):
|
||||
var default_texture = main_game.crop_mature_textures_cache["默认"]
|
||||
# 缓存给这个作物
|
||||
main_game.crop_mature_textures_cache[crop_name] = default_texture
|
||||
return default_texture
|
||||
|
||||
# 最后尝试直接加载默认成熟图片
|
||||
var default_mature_path = "res://assets/作物/默认/成熟.webp"
|
||||
if ResourceLoader.exists(default_mature_path):
|
||||
var texture = load(default_mature_path)
|
||||
if texture:
|
||||
print("背包使用默认成熟图片:", crop_name)
|
||||
# 缓存到主游戏
|
||||
if main_game:
|
||||
main_game.crop_mature_textures_cache["默认"] = texture
|
||||
main_game.crop_mature_textures_cache[crop_name] = texture
|
||||
return texture
|
||||
|
||||
return null
|
||||
|
||||
# 加载作物图片序列帧(复用主游戏的逻辑)
|
||||
func _load_crop_textures(crop_name: String) -> Array:
|
||||
if crop_textures_cache.has(crop_name):
|
||||
return crop_textures_cache[crop_name]
|
||||
|
||||
var textures = []
|
||||
var crop_path = "res://assets/作物/" + crop_name + "/"
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 检查作物文件夹是否存在
|
||||
if DirAccess.dir_exists_absolute(crop_path):
|
||||
# 尝试加载作物的序列帧(从0开始)
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = crop_path + str(frame_index) + ".webp"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
if textures.size() > 0:
|
||||
pass
|
||||
else:
|
||||
print("背包:作物 ", crop_name, " 文件夹存在但没有找到有效图片,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
else:
|
||||
print("背包:作物 ", crop_name, " 的文件夹不存在,使用默认图片")
|
||||
textures = _load_default_textures()
|
||||
|
||||
# 缓存结果
|
||||
crop_textures_cache[crop_name] = textures
|
||||
crop_frame_counts[crop_name] = textures.size()
|
||||
|
||||
return textures
|
||||
|
||||
# 加载默认图片
|
||||
func _load_default_textures() -> Array:
|
||||
if crop_textures_cache.has("默认"):
|
||||
return crop_textures_cache["默认"]
|
||||
|
||||
var textures = []
|
||||
var default_path = "res://assets/作物/默认/"
|
||||
|
||||
# 尝试加载默认图片序列帧
|
||||
var frame_index = 0
|
||||
while true:
|
||||
var texture_path = default_path + str(frame_index) + ".webp"
|
||||
if ResourceLoader.exists(texture_path):
|
||||
var texture = load(texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
frame_index += 1
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
# 如果没有找到序列帧,尝试加载单个默认图片
|
||||
if textures.size() == 0:
|
||||
var single_texture_path = default_path + ".webp"
|
||||
if ResourceLoader.exists(single_texture_path):
|
||||
var texture = load(single_texture_path)
|
||||
if texture:
|
||||
textures.append(texture)
|
||||
|
||||
# 缓存默认图片
|
||||
crop_textures_cache["默认"] = textures
|
||||
crop_frame_counts["默认"] = textures.size()
|
||||
|
||||
print("背包加载了 ", textures.size(), " 个默认作物图片")
|
||||
return textures
|
||||
|
||||
# 更新按钮的作物图片
|
||||
func _update_button_crop_image(button: Button, crop_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var crop_image = button.get_node_or_null("CropImage")
|
||||
if not crop_image:
|
||||
print("背包按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 获取作物的最后一帧图片
|
||||
var texture = _get_crop_final_texture(crop_name)
|
||||
|
||||
if texture:
|
||||
# CropImage是Sprite2D,直接设置texture属性
|
||||
crop_image.texture = texture
|
||||
crop_image.visible = true
|
||||
else:
|
||||
crop_image.visible = false
|
||||
print("背包无法获取作物图片:", crop_name)
|
||||
|
||||
#=========================面板通用处理=========================
|
||||
#手动刷新种子仓库面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 刷新种子背包UI
|
||||
update_player_bag_ui()
|
||||
Toast.show("种子仓库已刷新", Color.GREEN)
|
||||
|
||||
# 关闭面板
|
||||
func _on_quit_button_pressed():
|
||||
#打开面板后暂时禁用相机功能
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
# 退出种植模式(如果当前在种植模式下)
|
||||
if is_planting_mode:
|
||||
_exit_planting_mode()
|
||||
self.hide()
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
update_player_bag_ui()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
#=========================面板通用处理=========================
|
||||
1
Script/BigPanel/PlayerBagPanel.gd.uid
Normal file
1
Script/BigPanel/PlayerBagPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cgr332wsx63a8
|
||||
321
Script/BigPanel/PlayerRankingPanel.gd
Normal file
321
Script/BigPanel/PlayerRankingPanel.gd
Normal file
@@ -0,0 +1,321 @@
|
||||
extends Panel
|
||||
|
||||
@onready var player_ranking_list : VBoxContainer = $Scroll/PlayerList
|
||||
@onready var refresh_button : Button = $RefreshButton #刷新玩家排行榜面板按钮
|
||||
@onready var quit_button : Button = $QuitButton #关闭面板按钮
|
||||
@onready var search_button: Button = $SearchButton #搜索玩家按钮
|
||||
@onready var register_player_num: Label = $RegisterPlayerNum #显示注册总人数
|
||||
|
||||
#搜索玩家输入框,通过输入QQ号来查询
|
||||
@onready var search_line_edit: LineEdit = $SearchLineEdit
|
||||
|
||||
#排序筛选玩家面板按钮,默认按从大到小排序
|
||||
#排序元素:种子数,等级,在线时长,最后登录时长,点赞数
|
||||
#筛选元素:是否在线 筛选出在线玩家
|
||||
@onready var seed_sort_btn: Button = $FiterAndSortHBox/SeedSortBtn
|
||||
@onready var level_sort_btn: Button = $FiterAndSortHBox/LevelSortBtn
|
||||
@onready var online_time_sort_btn: Button = $FiterAndSortHBox/OnlineTimeSortBtn
|
||||
@onready var login_time_sort_btn: Button = $FiterAndSortHBox/LoginTimeSortBtn
|
||||
@onready var like_num_sort_btn: Button = $FiterAndSortHBox/LikeNumSortBtn
|
||||
@onready var money_sort_btn: Button = $FiterAndSortHBox/MoneySortBtn
|
||||
@onready var is_online_sort_btn: Button = $FiterAndSortHBox/IsOnlineSortBtn
|
||||
|
||||
|
||||
#预添加常用的面板
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
@onready var lucky_draw_panel: LuckyDrawPanel = $'../LuckyDrawPanel'
|
||||
@onready var daily_check_in_panel: DailyCheckInPanel = $'../DailyCheckInPanel'
|
||||
@onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'
|
||||
@onready var item_store_panel: Panel = $'../ItemStorePanel'
|
||||
@onready var crop_warehouse_panel: Panel = $'../CropWarehousePanel'
|
||||
@onready var login_panel: PanelContainer = $'../LoginPanel'
|
||||
@onready var player_bag_panel: Panel = $'../PlayerBagPanel'
|
||||
@onready var crop_store_panel: Panel = $'../CropStorePanel'
|
||||
@onready var item_bag_panel: Panel = $'../ItemBagPanel'
|
||||
|
||||
|
||||
# 排序状态管理
|
||||
var current_sort_by = "level" # 当前排序字段
|
||||
var current_sort_order = "desc" # 当前排序顺序
|
||||
var filter_online_only = false # 是否只显示在线玩家
|
||||
var current_search_qq = "" # 当前搜索的QQ号
|
||||
|
||||
#下面这是每个玩家要展示的信息,直接获取服务器玩家数据json文件来实现
|
||||
#模板用于复制创建新的玩家条目
|
||||
@onready var player_info_template : VBoxContainer = $Scroll/PlayerList/PlayerRankingItem
|
||||
@onready var player_entry_scene : PackedScene = preload("res://GUI/PlayerRankingItem.tscn")
|
||||
|
||||
func _ready() -> void:
|
||||
# 隐藏模板
|
||||
player_info_template.visible = false
|
||||
|
||||
# 连接按钮信号
|
||||
refresh_button.pressed.connect(_on_refresh_button_pressed)
|
||||
quit_button.pressed.connect(_on_quit_button_pressed)
|
||||
search_button.pressed.connect(_on_search_button_pressed)
|
||||
|
||||
# 连接排序按钮信号
|
||||
seed_sort_btn.pressed.connect(func(): _on_sort_button_pressed("seed_count"))
|
||||
level_sort_btn.pressed.connect(func(): _on_sort_button_pressed("level"))
|
||||
online_time_sort_btn.pressed.connect(func(): _on_sort_button_pressed("online_time"))
|
||||
login_time_sort_btn.pressed.connect(func(): _on_sort_button_pressed("login_time"))
|
||||
like_num_sort_btn.pressed.connect(func(): _on_sort_button_pressed("like_num"))
|
||||
money_sort_btn.pressed.connect(func(): _on_sort_button_pressed("money"))
|
||||
is_online_sort_btn.pressed.connect(_on_online_filter_pressed)
|
||||
|
||||
# 初始化按钮状态
|
||||
_update_button_states()
|
||||
|
||||
# 排序按钮点击处理
|
||||
func _on_sort_button_pressed(sort_field: String):
|
||||
# 如果点击的是当前排序字段,切换排序顺序
|
||||
if current_sort_by == sort_field:
|
||||
current_sort_order = "asc" if current_sort_order == "desc" else "desc"
|
||||
else:
|
||||
# 切换到新的排序字段,默认降序
|
||||
current_sort_by = sort_field
|
||||
current_sort_order = "desc"
|
||||
|
||||
# 更新按钮状态
|
||||
_update_button_states()
|
||||
|
||||
# 重新请求排行榜
|
||||
request_player_rankings()
|
||||
|
||||
# 在线筛选按钮点击处理
|
||||
func _on_online_filter_pressed():
|
||||
filter_online_only = !filter_online_only
|
||||
_update_button_states()
|
||||
request_player_rankings()
|
||||
|
||||
# 更新按钮状态显示
|
||||
func _update_button_states():
|
||||
# 重置所有排序按钮
|
||||
var sort_buttons = [seed_sort_btn, level_sort_btn, online_time_sort_btn, login_time_sort_btn, like_num_sort_btn, money_sort_btn]
|
||||
var sort_fields = ["seed_count", "level", "online_time", "login_time", "like_num", "money"]
|
||||
var sort_names = ["种子数", "等级", "游玩时间", "登录时间", "点赞数", "金币数"]
|
||||
|
||||
for i in range(sort_buttons.size()):
|
||||
var btn = sort_buttons[i]
|
||||
var field = sort_fields[i]
|
||||
var name = sort_names[i]
|
||||
|
||||
if current_sort_by == field:
|
||||
# 当前排序字段,显示排序方向
|
||||
var arrow = "↓" if current_sort_order == "desc" else "↑"
|
||||
btn.text = name + arrow
|
||||
btn.modulate = Color.YELLOW
|
||||
else:
|
||||
# 非当前排序字段
|
||||
btn.text = name
|
||||
btn.modulate = Color.WHITE
|
||||
|
||||
# 更新在线筛选按钮
|
||||
if filter_online_only:
|
||||
is_online_sort_btn.text = "仅在线✓"
|
||||
is_online_sort_btn.modulate = Color.GREEN
|
||||
else:
|
||||
is_online_sort_btn.text = "全部玩家"
|
||||
is_online_sort_btn.modulate = Color.WHITE
|
||||
|
||||
# 请求玩家排行榜数据
|
||||
func request_player_rankings():
|
||||
if not tcp_network_manager_panel:
|
||||
register_player_num.text = "网络管理器不可用"
|
||||
register_player_num.modulate = Color.RED
|
||||
return false
|
||||
|
||||
if not tcp_network_manager_panel.is_connected_to_server():
|
||||
register_player_num.text = "未连接服务器"
|
||||
register_player_num.modulate = Color.RED
|
||||
return false
|
||||
|
||||
var success = tcp_network_manager_panel.sendGetPlayerRankings(current_sort_by, current_sort_order, filter_online_only, current_search_qq)
|
||||
if not success:
|
||||
register_player_num.text = "请求发送失败"
|
||||
register_player_num.modulate = Color.RED
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
# 处理玩家排行榜响应
|
||||
func handle_player_rankings_response(data):
|
||||
# 重新启用刷新按钮
|
||||
refresh_button.disabled = false
|
||||
refresh_button.text = "刷新"
|
||||
|
||||
# 检查响应是否成功
|
||||
if not data.get("success", false):
|
||||
register_player_num.text = "获取注册人数失败"
|
||||
register_player_num.modulate = Color.RED
|
||||
Toast.show("获取排行榜失败:" + data.get("message", "未知错误"), Color.RED)
|
||||
return
|
||||
|
||||
# 显示注册总人数和在线人数
|
||||
var total_registered = data.get("total_registered_players", 0)
|
||||
var players_list = data.get("players", [])
|
||||
var online_count = 0
|
||||
for player in players_list:
|
||||
if player.get("is_online", false):
|
||||
online_count += 1
|
||||
|
||||
# 显示搜索和筛选信息
|
||||
var info_text = "总人数:" + str(int(total_registered)) + "| 在线:" + str(online_count)
|
||||
if current_search_qq != "":
|
||||
info_text += "| 搜索:" + current_search_qq
|
||||
if filter_online_only:
|
||||
info_text += "| 仅在线"
|
||||
|
||||
register_player_num.text = info_text
|
||||
register_player_num.modulate = Color.CYAN
|
||||
|
||||
# 清除现有的玩家条目(除了模板)
|
||||
for child in player_ranking_list.get_children():
|
||||
if child != player_info_template:
|
||||
child.queue_free()
|
||||
|
||||
# 添加玩家条目
|
||||
var players = players_list
|
||||
for player_data in players:
|
||||
add_player_entry(player_data)
|
||||
|
||||
print("排行榜数据已更新,显示", players.size(), "个玩家,注册总人数:", total_registered)
|
||||
|
||||
var result_text = "排行榜已刷新!显示 " + str(players.size()) + " 个玩家"
|
||||
if current_search_qq != "":
|
||||
result_text += "(搜索:" + current_search_qq + ")"
|
||||
if filter_online_only:
|
||||
result_text += "(仅在线)"
|
||||
|
||||
Toast.show(result_text, Color.GREEN)
|
||||
|
||||
# 添加单个玩家条目
|
||||
func add_player_entry(player_data):
|
||||
# 实例化新的玩家条目场景,避免 duplicate 引发的复制错误
|
||||
var player_entry = player_entry_scene.instantiate()
|
||||
player_entry.visible = true
|
||||
player_ranking_list.add_child(player_entry)
|
||||
|
||||
# 设置玩家信息
|
||||
|
||||
var player_name = player_entry.get_node("HBox/PlayerName")
|
||||
var player_level = player_entry.get_node("HBox/PlayerLevel")
|
||||
var player_money = player_entry.get_node("HBox/PlayerMoney")
|
||||
var player_seed_num = player_entry.get_node("HBox/SeedNum")
|
||||
var player_online_time = player_entry.get_node("HBox2/OnlineTime")
|
||||
var player_last_login_time = player_entry.get_node("HBox2/LastLoginTime")
|
||||
var player_avatar = player_entry.get_node("HBox/PlayerAvatar")
|
||||
var visit_button = player_entry.get_node("HBox/VisitButton")
|
||||
var player_is_online_time = player_entry.get_node("HBox2/IsOnlineTime")
|
||||
var player_like_num = player_entry.get_node("HBox2/LikeNum")
|
||||
|
||||
# 填充数据
|
||||
var username = player_data.get("user_name", "未知")
|
||||
var display_name = player_data.get("player_name", username)
|
||||
player_name.text = display_name
|
||||
#都是整数,不要乱用浮点数
|
||||
player_level.text = "等级: " + str(int(player_data.get("level", 0)))
|
||||
player_money.text = "金币: " + str(int(player_data.get("money", 0)))
|
||||
player_seed_num.text = "种子: " + str(int(player_data.get("seed_count", 0)))
|
||||
player_online_time.text = "游玩时间: " + player_data.get("total_login_time", "0时0分0秒")
|
||||
player_last_login_time.text = "最后登录: " + player_data.get("last_login_time", "未知")
|
||||
|
||||
# 设置在线状态显示
|
||||
var is_online = player_data.get("is_online", false)
|
||||
if is_online:
|
||||
player_is_online_time.text = "🟢 在线"
|
||||
player_is_online_time.modulate = Color.GREEN
|
||||
else:
|
||||
player_is_online_time.text = "🔴 离线"
|
||||
player_is_online_time.modulate = Color.GRAY
|
||||
|
||||
# 设置点赞数显示
|
||||
player_like_num.text = "点赞: " + str(int(player_data.get("like_num", 0)))
|
||||
|
||||
# 尝试加载玩家头像(使用用户名/QQ号加载头像,而不是显示名)
|
||||
if username.is_valid_int():
|
||||
player_avatar.load_from_url("http://q1.qlogo.cn/g?b=qq&nk=" + username + "&s=100")
|
||||
|
||||
# 设置访问按钮
|
||||
visit_button.pressed.connect(func(): _on_visit_player_pressed(username))
|
||||
|
||||
# 访问玩家按钮点击
|
||||
func _on_visit_player_pressed(username):
|
||||
#访问玩家后取消禁用相机功能,否则无法恢复
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
|
||||
|
||||
# 检查网络连接
|
||||
if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server():
|
||||
Toast.show("未连接服务器,无法访问玩家", Color.RED)
|
||||
return
|
||||
|
||||
# 检查是否尝试访问自己
|
||||
if main_game and main_game.user_name == username:
|
||||
Toast.show("不能访问自己的农场", Color.ORANGE)
|
||||
return
|
||||
|
||||
# 发送访问玩家请求
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("sendVisitPlayer"):
|
||||
var success = tcp_network_manager_panel.sendVisitPlayer(username)
|
||||
if success:
|
||||
Toast.show("正在访问 " + username + " 的农场...", Color.YELLOW)
|
||||
else:
|
||||
Toast.show("发送访问请求失败", Color.RED)
|
||||
else:
|
||||
Toast.show("网络管理器不可用", Color.RED)
|
||||
|
||||
# 刷新按钮点击
|
||||
func _on_refresh_button_pressed():
|
||||
# 检查网络连接
|
||||
if not tcp_network_manager_panel or not tcp_network_manager_panel.is_connected_to_server():
|
||||
register_player_num.text = "未连接服务器,无法刷新"
|
||||
register_player_num.modulate = Color.RED
|
||||
Toast.show("未连接服务器,无法刷新排行榜", Color.RED)
|
||||
return
|
||||
|
||||
# 显示加载状态
|
||||
register_player_num.text = "正在刷新排行榜..."
|
||||
register_player_num.modulate = Color.YELLOW
|
||||
refresh_button.disabled = true
|
||||
refresh_button.text = "刷新中..."
|
||||
|
||||
# 请求排行榜数据
|
||||
request_player_rankings()
|
||||
|
||||
# 5秒后重新启用按钮(防止卡住)
|
||||
await get_tree().create_timer(5.0).timeout
|
||||
if refresh_button.disabled:
|
||||
refresh_button.disabled = false
|
||||
refresh_button.text = "刷新"
|
||||
if register_player_num.text == "正在刷新排行榜...":
|
||||
register_player_num.text = "刷新超时,请重试"
|
||||
register_player_num.modulate = Color.RED
|
||||
|
||||
# 退出按钮点击
|
||||
func _on_quit_button_pressed():
|
||||
#打开面板后暂时禁用相机功能
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
|
||||
self.hide()
|
||||
|
||||
#搜索按钮点击 - 通过QQ号查询玩家
|
||||
func _on_search_button_pressed():
|
||||
var search_text = search_line_edit.text.strip_edges()
|
||||
|
||||
# 如果搜索框为空,清除搜索条件
|
||||
if search_text == "":
|
||||
current_search_qq = ""
|
||||
Toast.show("已清除搜索条件", Color.YELLOW)
|
||||
else:
|
||||
# 验证输入是否为数字(QQ号)
|
||||
if not search_text.is_valid_int():
|
||||
Toast.show("请输入有效的QQ号(纯数字)", Color.RED)
|
||||
return
|
||||
|
||||
current_search_qq = search_text
|
||||
Toast.show("搜索QQ号:" + search_text, Color.YELLOW)
|
||||
|
||||
# 重新请求排行榜
|
||||
request_player_rankings()
|
||||
1
Script/BigPanel/PlayerRankingPanel.gd.uid
Normal file
1
Script/BigPanel/PlayerRankingPanel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://fk4q3x6uqydd
|
||||
Reference in New Issue
Block a user