完善宠物系统
This commit is contained in:
@@ -293,7 +293,7 @@ func _show_item_info(item_name: String, item_count: int):
|
||||
info_text += "描述: " + description
|
||||
|
||||
if not _is_item_usable(item_name):
|
||||
info_text += "\n注意: 此道具功能暂未实现"
|
||||
pass
|
||||
else:
|
||||
info_text = item_name + " (数量: " + str(item_count) + ")\n描述: 暂无信息"
|
||||
|
||||
@@ -363,7 +363,7 @@ func _send_farm_item_use_request(item_name: String):
|
||||
# 发送请求
|
||||
tcp_network_manager_panel.send_message(message)
|
||||
|
||||
Toast.show("正在使用道具...", Color.BLUE, 2.0, 1.0)
|
||||
#Toast.show("正在使用道具...", Color.BLUE, 2.0, 1.0)
|
||||
|
||||
# 显示宠物使用道具确认对话框
|
||||
func _show_pet_item_confirmation_dialog(item_name: String, item_count: int):
|
||||
@@ -431,13 +431,12 @@ func _send_pet_item_use_request(item_name: String, pet_id: String):
|
||||
# 退出宠物使用道具模式
|
||||
_exit_pet_item_mode()
|
||||
|
||||
Toast.show("正在使用道具...", Color.BLUE, 2.0, 1.0)
|
||||
#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()
|
||||
|
||||
@@ -496,13 +495,12 @@ func _on_quit_button_pressed() -> void:
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 刷新道具背包UI
|
||||
update_item_bag_ui()
|
||||
Toast.show("道具背包已刷新", Color.GREEN, 2.0, 1.0)
|
||||
#Toast.show("道具背包已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
#面板显示与隐藏切换处理
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
update_item_bag_ui()
|
||||
pass
|
||||
else:
|
||||
|
||||
@@ -433,6 +433,7 @@ func _handle_login_success(user_data: Dictionary):
|
||||
main_game.item_bag = user_data.get("道具背包", [])
|
||||
main_game.pet_bag = user_data.get("宠物背包", [])
|
||||
main_game.patrol_pets = user_data.get("巡逻宠物", [])
|
||||
main_game.battle_pets = user_data.get("出战宠物", [])
|
||||
|
||||
# 启动游戏并隐藏登录面板
|
||||
main_game.start_game = true
|
||||
|
||||
@@ -61,9 +61,9 @@ func update_pet_bag_ui():
|
||||
|
||||
# 为背包中的每个宠物创建按钮
|
||||
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 pet_name = pet_data.get("pet_type", "未知宠物")
|
||||
var pet_level = pet_data.get("pet_level", 1)
|
||||
var pet_owner_name = pet_data.get("pet_name", pet_name)
|
||||
|
||||
# 创建宠物按钮
|
||||
var button = _create_pet_button(pet_name, pet_level, pet_owner_name)
|
||||
@@ -118,31 +118,45 @@ func _update_button_pet_image(button: Button, pet_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var pet_image = button.get_node_or_null("CropImage")
|
||||
if not pet_image:
|
||||
print("宠物背包按钮没有找到CropImage节点:", button.name)
|
||||
return
|
||||
|
||||
# 从宠物配置获取场景路径
|
||||
# 从服务器的宠物配置获取场景路径
|
||||
var texture = null
|
||||
var pet_config = _load_pet_config()
|
||||
var pet_config = main_game.pet_config # 使用服务器返回的宠物配置
|
||||
|
||||
if pet_config.has(pet_name):
|
||||
var pet_info = pet_config[pet_name]
|
||||
var scene_path = pet_info.get("场景路径", "")
|
||||
var scene_path = pet_info.get("pet_image", "") # 使用服务器数据的pet_image字段
|
||||
print("宠物背包 ", pet_name, " 的图片路径:", scene_path)
|
||||
|
||||
if scene_path != "" and ResourceLoader.exists(scene_path):
|
||||
print("宠物背包开始加载宠物场景:", 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:
|
||||
# 直接使用实例化的场景根节点,因为根节点就是PetImage
|
||||
if pet_instance and pet_instance.sprite_frames:
|
||||
# 获取默认动画的第一帧
|
||||
var animation_names = pet_image_node.sprite_frames.get_animation_names()
|
||||
var animation_names = pet_instance.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)
|
||||
var frame_count = pet_instance.sprite_frames.get_frame_count(default_animation)
|
||||
if frame_count > 0:
|
||||
texture = pet_image_node.sprite_frames.get_frame_texture(default_animation, 0)
|
||||
texture = pet_instance.sprite_frames.get_frame_texture(default_animation, 0)
|
||||
print("宠物背包成功获取宠物纹理:", pet_name)
|
||||
else:
|
||||
print("宠物背包场景没有动画:", pet_name)
|
||||
else:
|
||||
print("宠物背包场景没有PetImage节点或sprite_frames:", pet_name)
|
||||
pet_instance.queue_free()
|
||||
else:
|
||||
print("宠物背包无法加载宠物场景:", scene_path)
|
||||
else:
|
||||
print("宠物背包图片路径无效或文件不存在:", scene_path)
|
||||
else:
|
||||
print("宠物背包配置中没有找到:", pet_name)
|
||||
|
||||
# 设置图片
|
||||
if texture:
|
||||
@@ -151,8 +165,10 @@ func _update_button_pet_image(button: Button, pet_name: String):
|
||||
pet_image.scale = Vector2(10, 10)
|
||||
# 确保图片居中显示
|
||||
pet_image.centered = true
|
||||
print("宠物背包成功设置宠物图片:", pet_name)
|
||||
else:
|
||||
pet_image.visible = false
|
||||
print("宠物背包无法获取宠物图片:", pet_name)
|
||||
|
||||
# 加载宠物配置数据
|
||||
func _load_pet_config() -> Dictionary:
|
||||
|
||||
@@ -24,6 +24,8 @@ extends Panel
|
||||
|
||||
# 宠物配置数据
|
||||
var pet_config: Dictionary = {}
|
||||
# 请求状态标志,防止重复请求
|
||||
var is_requesting_config: bool = false
|
||||
|
||||
# 准备函数
|
||||
func _ready():
|
||||
@@ -57,20 +59,23 @@ func update_pet_store_ui():
|
||||
child.queue_free()
|
||||
|
||||
print("更新宠物商店UI,宠物种类:", pet_config.size())
|
||||
print("宠物配置数据:", pet_config)
|
||||
|
||||
# 为每个宠物配置创建按钮
|
||||
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)
|
||||
print("处理宠物:", pet_name, ",数据:", pet_info)
|
||||
|
||||
# 适配扁平化数据格式
|
||||
var can_buy = pet_info.get("can_purchase", false)
|
||||
|
||||
# 只显示可购买的宠物
|
||||
if not can_buy:
|
||||
print("宠物 ", pet_name, " 不可购买,跳过")
|
||||
continue
|
||||
|
||||
var pet_cost = purchase_info.get("购买价格", 0)
|
||||
var basic_info = pet_info.get("基本信息", {})
|
||||
var pet_desc = basic_info.get("简介", "可爱的宠物伙伴")
|
||||
var pet_cost = pet_info.get("cost", 0)
|
||||
var pet_desc = pet_info.get("description", "可爱的宠物伙伴")
|
||||
|
||||
# 检查玩家是否已购买该宠物
|
||||
var is_owned = _check_pet_owned(pet_name)
|
||||
@@ -88,6 +93,7 @@ func update_pet_store_ui():
|
||||
button.pressed.connect(func(): _on_store_pet_selected(pet_name, pet_cost, pet_desc))
|
||||
|
||||
store_grid.add_child(button)
|
||||
print("已添加宠物按钮:", pet_name)
|
||||
|
||||
# 检查玩家是否已拥有某种宠物
|
||||
func _check_pet_owned(pet_name: String) -> bool:
|
||||
@@ -95,8 +101,7 @@ func _check_pet_owned(pet_name: String) -> bool:
|
||||
return false
|
||||
|
||||
for pet_data in main_game.pet_bag:
|
||||
var basic_info = pet_data.get("基本信息", {})
|
||||
var pet_type = basic_info.get("宠物类型", "")
|
||||
var pet_type = pet_data.get("pet_type", "")
|
||||
if pet_type == pet_name:
|
||||
return true
|
||||
return false
|
||||
@@ -144,28 +149,44 @@ func _update_button_pet_image(button: Button, pet_name: String):
|
||||
# 检查按钮是否有CropImage节点
|
||||
var pet_image = button.get_node_or_null("CropImage")
|
||||
if not pet_image:
|
||||
print("按钮没有CropImage节点,跳过图片设置")
|
||||
return
|
||||
|
||||
# 从宠物配置获取场景路径
|
||||
var texture = null
|
||||
if pet_config.has(pet_name):
|
||||
var pet_info = pet_config[pet_name]
|
||||
var scene_path = pet_info.get("场景路径", "")
|
||||
var scene_path = pet_info.get("pet_image", "")
|
||||
print("宠物 ", pet_name, " 的图片路径:", scene_path)
|
||||
|
||||
if scene_path != "" and ResourceLoader.exists(scene_path):
|
||||
print("开始加载宠物场景:", 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")
|
||||
# 场景的根节点就是PetImage,直接使用
|
||||
var pet_image_node = pet_instance
|
||||
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)
|
||||
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)
|
||||
print("成功获取宠物纹理:", pet_name)
|
||||
else:
|
||||
print("宠物场景没有动画:", pet_name)
|
||||
else:
|
||||
print("宠物场景没有PetImage节点或sprite_frames:", pet_name)
|
||||
pet_instance.queue_free()
|
||||
|
||||
else:
|
||||
print("无法加载宠物场景:", scene_path)
|
||||
else:
|
||||
print("宠物图片路径无效或文件不存在:", scene_path)
|
||||
else:
|
||||
print("宠物配置中没有找到:", pet_name)
|
||||
|
||||
# 设置图片
|
||||
if texture:
|
||||
@@ -174,31 +195,52 @@ func _update_button_pet_image(button: Button, pet_name: String):
|
||||
pet_image.scale = Vector2(10, 10)
|
||||
# 确保图片居中显示
|
||||
pet_image.centered = true
|
||||
|
||||
print("成功设置宠物图片:", pet_name)
|
||||
else:
|
||||
# 如果无法获取图片,隐藏图片节点但保留按钮
|
||||
pet_image.visible = false
|
||||
print("无法获取宠物图片,隐藏图片节点:", pet_name)
|
||||
|
||||
# 从主游戏脚本获取宠物配置数据
|
||||
# 从服务器获取MongoDB中的宠物配置数据
|
||||
func _load_pet_config_from_main():
|
||||
# 从宠物数据文件加载配置
|
||||
var file = FileAccess.open("res://Data/pet_data.json", FileAccess.READ)
|
||||
if file == null:
|
||||
print("宠物商店:无法打开宠物配置文件")
|
||||
pet_config = {}
|
||||
# 如果正在请求中,避免重复发送
|
||||
if is_requesting_config:
|
||||
print("宠物商店:正在请求配置数据中,跳过重复请求")
|
||||
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("宠物商店:解析宠物配置文件失败")
|
||||
# 发送请求到服务器获取宠物配置
|
||||
if tcp_network_manager_panel and tcp_network_manager_panel.has_method("sendGetPetConfig"):
|
||||
is_requesting_config = true
|
||||
if tcp_network_manager_panel.sendGetPetConfig():
|
||||
print("宠物商店:已发送获取宠物配置请求")
|
||||
# 等待服务器响应,配置数据将通过网络回调更新
|
||||
else:
|
||||
print("宠物商店:发送获取宠物配置请求失败")
|
||||
pet_config = {}
|
||||
is_requesting_config = false
|
||||
else:
|
||||
print("宠物商店:网络管理器不可用,无法获取宠物配置")
|
||||
pet_config = {}
|
||||
return
|
||||
is_requesting_config = false
|
||||
|
||||
# 处理服务器返回的宠物配置数据
|
||||
func _on_pet_config_received(response_data: Dictionary):
|
||||
"""处理从服务器接收到的宠物配置数据"""
|
||||
# 重置请求状态
|
||||
is_requesting_config = false
|
||||
|
||||
pet_config = json.data
|
||||
print("宠物商店:成功加载宠物配置数据,宠物种类:", pet_config.size())
|
||||
var success = response_data.get("success", false)
|
||||
if success:
|
||||
pet_config = response_data.get("pet_config", {})
|
||||
print("宠物商店:成功接收宠物配置数据,宠物种类:", pet_config.size())
|
||||
# 只更新UI,不重新发送请求
|
||||
update_pet_store_ui()
|
||||
else:
|
||||
var error_message = response_data.get("message", "获取宠物配置失败")
|
||||
print("宠物商店:获取宠物配置失败:", error_message)
|
||||
pet_config = {}
|
||||
# 显示错误提示
|
||||
Toast.show(error_message, Color.RED, 3.0, 1.0)
|
||||
|
||||
# 商店宠物点击处理 - 购买宠物
|
||||
func _on_store_pet_selected(pet_name: String, pet_cost: int, pet_desc: String):
|
||||
@@ -269,9 +311,12 @@ func _send_buy_pet_request(pet_name: String, pet_cost: int):
|
||||
#=========================面板通用处理=========================
|
||||
# 手动刷新宠物商店面板
|
||||
func _on_refresh_button_pressed() -> void:
|
||||
# 清空现有配置和请求状态,强制重新获取
|
||||
pet_config = {}
|
||||
is_requesting_config = false
|
||||
# 重新初始化宠物商店
|
||||
init_pet_store()
|
||||
Toast.show("宠物商店已刷新", Color.GREEN, 2.0, 1.0)
|
||||
#Toast.show("宠物商店已刷新", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
# 关闭宠物商店面板
|
||||
func _on_quit_button_pressed() -> void:
|
||||
@@ -283,8 +328,12 @@ func _on_quit_button_pressed() -> void:
|
||||
func _on_visibility_changed():
|
||||
if visible:
|
||||
GlobalVariables.isZoomDisabled = true
|
||||
# 面板显示时自动刷新数据
|
||||
update_pet_store_ui()
|
||||
# 面板显示时只在没有配置数据时才请求
|
||||
if pet_config.is_empty():
|
||||
init_pet_store()
|
||||
else:
|
||||
# 如果已有配置数据,直接更新UI
|
||||
update_pet_store_ui()
|
||||
pass
|
||||
else:
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
|
||||
@@ -53,15 +53,10 @@ extends CharacterBody2D
|
||||
#- 亲密度(额外加属性)
|
||||
#- 品质(白/绿/蓝/橙/红/紫)
|
||||
|
||||
#基本攻击方式:
|
||||
#近战
|
||||
#近战攻击伤害
|
||||
#近战攻击速度
|
||||
|
||||
#远程
|
||||
#远程攻击伤害
|
||||
#远程攻击速度
|
||||
|
||||
#附录
|
||||
#- 护甲公式示例:实际伤害 = 基础伤害 × (1 - 护甲值/(护甲值 + 100)),搭配"护甲穿透"可直接减少目标护甲值
|
||||
#- 元素克制:火属性攻击对冰属性敌人造成150%伤害,同时被水属性克制(仅造成80%伤害)
|
||||
@@ -111,7 +106,7 @@ var current_armor: float = 100.0 # 当前护甲值
|
||||
# 攻击属性
|
||||
var attack_type: AttackType = AttackType.RANGED # 攻击类型
|
||||
var attack_damage: float = 20.0 # 基础攻击伤害
|
||||
var attack_range: float = 300.0 # 攻击距离
|
||||
var attack_range: float = 400.0 # 攻击距离
|
||||
var crit_rate: float = 0.1 # 暴击率(0.0-1.0)
|
||||
var crit_damage: float = 1.5 # 暴击伤害倍数
|
||||
var life_steal: float = 0.1 # 生命汲取(0.0-1.0)
|
||||
@@ -152,7 +147,7 @@ enum RangedAttackMode {
|
||||
PIERCING # 穿透攻击
|
||||
}
|
||||
|
||||
# 内部状态变量(不需要导出)
|
||||
|
||||
var attack_speed: float = 1.0 # 当前攻击速度(根据攻击类型动态设置)
|
||||
var gatling_firing: bool = false # 是否正在加特林射击
|
||||
var gatling_current_bullet: int = 0 # 当前加特林子弹计数
|
||||
@@ -219,13 +214,57 @@ var is_attacking: bool = false # 是否正在攻击
|
||||
var is_berserker: bool = false # 是否处于狂暴状态
|
||||
var is_stunned: bool = false # 是否被眩晕
|
||||
var is_invulnerable: bool = false # 是否无敌
|
||||
var is_being_knocked_back: bool = false # 是否正在被击退
|
||||
var current_target: CharacterBody2D = null # 当前目标
|
||||
var last_attacker: CharacterBody2D = null # 最后攻击者(用于击杀奖励)
|
||||
var last_attack_time: float = 0.0 # 上次攻击时间
|
||||
var last_regen_time: float = 0.0 # 上次恢复时间
|
||||
var last_target_check_time: float = 0.0 # 上次目标检查时间
|
||||
var knockback_velocity: Vector2 = Vector2.ZERO # 击退速度
|
||||
|
||||
# 受伤动画相关
|
||||
var hurt_tween: Tween = null # 受伤动画缓动
|
||||
var original_modulate: Color = Color.WHITE # 原始颜色
|
||||
var last_hurt_time: float = 0.0 # 上次受伤时间(防止受伤动画过于频繁)
|
||||
var hurt_animation_cooldown: float = 0.3 # 受伤动画冷却时间
|
||||
|
||||
# 攻击频率控制
|
||||
var min_attack_interval: float = 0.5 # 最小攻击间隔(防止攻击过于频繁)
|
||||
|
||||
# 伤害反弹保护
|
||||
var damage_reflect_depth: int = 0 # 伤害反弹递归深度
|
||||
var max_reflect_depth: int = 3 # 最大反弹深度(防止无限递归)
|
||||
|
||||
# 性能保护
|
||||
var performance_mode: bool = false # 性能模式(减少特效和计算)
|
||||
var frame_skip_counter: int = 0 # 帧跳跃计数器
|
||||
|
||||
# 升级系统 - 基础属性列表(每次升级随机选择加点)
|
||||
var base_upgrade_attributes: Array[String] = [
|
||||
"max_health", # 最大生命值
|
||||
"attack_damage", # 攻击伤害
|
||||
"move_speed", # 移动速度
|
||||
"max_shield", # 最大护盾值
|
||||
"max_armor", # 最大护甲值
|
||||
"crit_rate", # 暴击率
|
||||
"health_regen", # 生命恢复
|
||||
"attack_range" # 攻击距离
|
||||
]
|
||||
|
||||
# 每次升级随机选择的属性数量
|
||||
var attributes_per_level: int = 3
|
||||
|
||||
# 每5级额外属性奖励表
|
||||
var level_milestone_bonuses: Dictionary = {
|
||||
5: {"max_health": 20, "attack_damage": 5, "crit_rate": 0.02},
|
||||
10: {"max_shield": 30, "armor_penetration": 5, "life_steal": 0.05},
|
||||
15: {"max_armor": 25, "knockback_resist": 0.1, "dodge_rate": 0.03},
|
||||
20: {"health_regen": 2, "move_speed": 15, "attack_range": 30},
|
||||
25: {"max_health": 40, "attack_damage": 10, "enable_berserker_mode": true},
|
||||
30: {"max_shield": 50, "shield_regen": 1, "enable_damage_reflect": true},
|
||||
35: {"crit_damage": 0.3, "berserker_bonus": 0.2, "damage_reflect": 0.05},
|
||||
40: {"max_armor": 40, "control_resist": 0.15, "enable_aid_system": true},
|
||||
45: {"projectile_speed": 50, "pierce_count": 1, "enable_death_immunity": true},
|
||||
50: {"max_health": 100, "attack_damage": 25, "enable_resurrection": true}
|
||||
}
|
||||
|
||||
# 巡逻状态
|
||||
var is_patrolling: bool = false # 是否正在巡逻
|
||||
@@ -642,6 +681,10 @@ func _ready():
|
||||
# 初始化生日
|
||||
initialize_birthday()
|
||||
|
||||
# 保存原始颜色
|
||||
if pet_image:
|
||||
original_modulate = pet_image.modulate
|
||||
|
||||
# 延迟初始化UI显示,确保所有节点都已准备好
|
||||
call_deferred("update_ui")
|
||||
|
||||
@@ -702,35 +745,50 @@ func clamp_to_battle_area():
|
||||
global_position.x = clamp(global_position.x, battle_area_min.x, battle_area_max.x)
|
||||
global_position.y = clamp(global_position.y, battle_area_min.y, battle_area_max.y)
|
||||
|
||||
#宠物物理更新
|
||||
#宠物物理更新(带性能保护)
|
||||
func _physics_process(delta):
|
||||
if not is_alive or is_dying:
|
||||
return
|
||||
|
||||
# 性能保护:每3帧执行一次非关键逻辑
|
||||
frame_skip_counter += 1
|
||||
var should_skip_frame = performance_mode and (frame_skip_counter % 3 != 0)
|
||||
|
||||
# 检测性能问题(如果帧时间过长,自动启用性能模式)
|
||||
if delta > 0.025: # 帧时间超过25ms(低于40FPS)
|
||||
if not performance_mode:
|
||||
performance_mode = true
|
||||
print("⚡ " + pet_name + " 启用性能模式(帧时间: " + str("%.3f" % delta) + "s)")
|
||||
|
||||
# 巡逻宠物特殊处理
|
||||
if is_patrolling:
|
||||
handle_patrol(delta)
|
||||
return
|
||||
|
||||
# 处理生命和护盾恢复
|
||||
handle_regeneration(delta)
|
||||
if not should_skip_frame:
|
||||
handle_regeneration(delta)
|
||||
|
||||
# 更新年龄和亲密度
|
||||
update_age_and_intimacy(delta)
|
||||
# 更新年龄和亲密度(低优先级,可跳帧)
|
||||
if not should_skip_frame:
|
||||
update_age_and_intimacy(delta)
|
||||
|
||||
# 检查狂暴状态
|
||||
check_berserker_mode()
|
||||
if not should_skip_frame:
|
||||
check_berserker_mode()
|
||||
|
||||
# 检查援助系统
|
||||
check_aid_system()
|
||||
# 检查援助系统(低优先级,可跳帧)
|
||||
if not should_skip_frame:
|
||||
check_aid_system()
|
||||
|
||||
# 如果被眩晕则不能行动
|
||||
if is_stunned:
|
||||
return
|
||||
|
||||
# 定期检查目标状态(每0.5秒检查一次)
|
||||
# 定期检查目标状态(性能模式下降低检查频率)
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
if current_time - last_target_check_time >= 0.5:
|
||||
var check_interval = 0.5 if not performance_mode else 1.0
|
||||
if current_time - last_target_check_time >= check_interval:
|
||||
check_target_validity()
|
||||
last_target_check_time = current_time
|
||||
|
||||
@@ -791,15 +849,7 @@ func update_ai_state(delta):
|
||||
|
||||
#宠物移动
|
||||
func handle_movement(delta):
|
||||
# 处理击退效果
|
||||
if is_being_knocked_back:
|
||||
velocity = knockback_velocity
|
||||
# 击退衰减
|
||||
knockback_velocity = knockback_velocity.lerp(Vector2.ZERO, 5.0 * delta)
|
||||
if knockback_velocity.length() < 10.0:
|
||||
is_being_knocked_back = false
|
||||
knockback_velocity = Vector2.ZERO
|
||||
elif current_state == PetState.MOVING_TO_TARGET and current_target:
|
||||
if current_state == PetState.MOVING_TO_TARGET and current_target:
|
||||
var distance_to_target = global_position.distance_to(current_target.global_position)
|
||||
var direction = (current_target.global_position - global_position).normalized()
|
||||
|
||||
@@ -832,7 +882,7 @@ func handle_movement(delta):
|
||||
else:
|
||||
velocity = Vector2.ZERO
|
||||
|
||||
#宠物攻击
|
||||
#宠物攻击(带频率保护)
|
||||
func handle_attack(delta):
|
||||
if current_state == PetState.ATTACKING and current_target:
|
||||
var current_time = Time.get_ticks_msec() / 1000.0 # 转换为秒
|
||||
@@ -841,8 +891,9 @@ func handle_attack(delta):
|
||||
if ranged_mode == RangedAttackMode.GATLING:
|
||||
handle_gatling_attack(current_time, delta)
|
||||
else:
|
||||
# 普通攻击频率控制
|
||||
if current_time - last_attack_time >= 1.0 / attack_speed:
|
||||
# 普通攻击频率控制(确保最小攻击间隔)
|
||||
var attack_interval = max(1.0 / attack_speed, min_attack_interval)
|
||||
if current_time - last_attack_time >= attack_interval:
|
||||
perform_attack(current_target)
|
||||
last_attack_time = current_time
|
||||
|
||||
@@ -959,9 +1010,9 @@ func perform_melee_attack(target: CharacterBody2D):
|
||||
var heal_amount = damage * life_steal
|
||||
heal(heal_amount)
|
||||
|
||||
# 击退效果
|
||||
if knockback_force > 0:
|
||||
apply_knockback_to_target(target)
|
||||
# 击退效果已禁用
|
||||
# if knockback_force > 0:
|
||||
# apply_knockback_to_target(target)
|
||||
|
||||
# 根据攻击模式发射子弹
|
||||
func fire_projectile_by_mode(target: CharacterBody2D):
|
||||
@@ -1090,15 +1141,29 @@ func create_and_fire_projectile(start_pos: Vector2, target_pos: Vector2, damage:
|
||||
RangedAttackMode.PIERCING:
|
||||
projectile.get_node("ProjectileSprite").modulate = Color.PURPLE
|
||||
|
||||
#宠物受到伤害
|
||||
#宠物受到伤害(带死循环保护)
|
||||
func take_damage(damage: float, armor_pen: float = 0.0, attacker_element: ElementType = ElementType.NONE, attacker: CharacterBody2D = null):
|
||||
if not is_alive or is_invulnerable:
|
||||
return
|
||||
|
||||
# 防止过于频繁的伤害处理(性能保护)
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
if current_time - last_attack_time < 0.05: # 50ms最小伤害间隔
|
||||
return
|
||||
|
||||
# 增加伤害反弹递归深度
|
||||
damage_reflect_depth += 1
|
||||
|
||||
# 递归深度保护(防止无限反弹)
|
||||
if damage_reflect_depth > max_reflect_depth:
|
||||
damage_reflect_depth = max(0, damage_reflect_depth - 1)
|
||||
return
|
||||
|
||||
# 闪避检测
|
||||
if randf() < dodge_rate:
|
||||
if attacker and is_instance_valid(attacker):
|
||||
add_battle_detail_to_panel("✨ " + pet_name + " 闪避了 " + attacker.pet_name + " 的攻击!", Color.CYAN)
|
||||
damage_reflect_depth = max(0, damage_reflect_depth - 1)
|
||||
return
|
||||
|
||||
var actual_damage = damage
|
||||
@@ -1123,8 +1188,11 @@ func take_damage(damage: float, armor_pen: float = 0.0, attacker_element: Elemen
|
||||
if actual_damage > 0:
|
||||
current_health -= actual_damage
|
||||
|
||||
# 添加受伤细节
|
||||
if attacker and is_instance_valid(attacker):
|
||||
# 播放受伤动画(带冷却保护)
|
||||
play_hurt_animation()
|
||||
|
||||
# 添加受伤细节(性能模式下减少文本输出)
|
||||
if not performance_mode and attacker and is_instance_valid(attacker):
|
||||
var damage_text = "💔 " + pet_name + " 受到 " + str(int(actual_damage)) + " 点伤害"
|
||||
if element_extra_damage > 0:
|
||||
damage_text += " (元素克制 +" + str(int(element_extra_damage)) + ")"
|
||||
@@ -1135,15 +1203,19 @@ func take_damage(damage: float, armor_pen: float = 0.0, attacker_element: Elemen
|
||||
last_attacker = attacker
|
||||
|
||||
# 反击机制:立即将攻击者设为目标(只有启用战斗时才反击)
|
||||
# 添加反击冷却,防止过于频繁的目标切换
|
||||
if combat_enabled and attacker and is_instance_valid(attacker) and attacker.is_alive:
|
||||
if attacker.get_team() != pet_team: # 确保不攻击队友
|
||||
current_target = attacker
|
||||
current_state = PetState.MOVING_TO_TARGET
|
||||
# 只有当前没有目标或当前目标已死亡时才切换目标
|
||||
if not current_target or not is_instance_valid(current_target) or not current_target.is_alive:
|
||||
current_target = attacker
|
||||
current_state = PetState.MOVING_TO_TARGET
|
||||
|
||||
# 伤害反弹
|
||||
if enable_damage_reflect and damage_reflect > 0.0 and attacker and is_instance_valid(attacker):
|
||||
var reflect_damage = damage * damage_reflect
|
||||
attacker.take_damage(reflect_damage, 0.0, element_type, self) # 反弹伤害也会触发反击
|
||||
# 伤害反弹(带递归深度保护)
|
||||
if enable_damage_reflect and damage_reflect > 0.0 and attacker and is_instance_valid(attacker) and damage_reflect_depth <= max_reflect_depth:
|
||||
var reflect_damage = damage * damage_reflect * 0.5 # 反弹伤害减半,防止无限递归
|
||||
# 延迟反弹,避免同帧内的递归调用
|
||||
call_deferred("apply_reflect_damage", attacker, reflect_damage)
|
||||
|
||||
# 检查死亡
|
||||
if current_health <= 0:
|
||||
@@ -1159,9 +1231,17 @@ func take_damage(damage: float, armor_pen: float = 0.0, attacker_element: Elemen
|
||||
if not is_dying: # 防止重复调用die()
|
||||
call_deferred("die")
|
||||
|
||||
# 减少伤害反弹递归深度
|
||||
damage_reflect_depth = max(0, damage_reflect_depth - 1)
|
||||
|
||||
# 更新UI
|
||||
call_deferred("update_ui")
|
||||
|
||||
# 延迟应用反弹伤害(防止递归调用)
|
||||
func apply_reflect_damage(target: CharacterBody2D, reflect_damage: float):
|
||||
if target and is_instance_valid(target) and target.is_alive:
|
||||
target.take_damage(reflect_damage, 0.0, element_type, self)
|
||||
|
||||
#宠物死亡
|
||||
func die():
|
||||
if is_dying: # 如果已经在死亡过程中,直接返回
|
||||
@@ -1416,6 +1496,10 @@ func apply_quality_bonuses():
|
||||
func get_team() -> String:
|
||||
return pet_team
|
||||
|
||||
# 获取攻击类型(调试用)
|
||||
func get_attack_type() -> AttackType:
|
||||
return attack_type
|
||||
|
||||
# 处理生命和护盾恢复
|
||||
func handle_regeneration(delta: float):
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
@@ -1516,7 +1600,7 @@ func gain_experience(amount: float):
|
||||
while pet_experience >= max_experience and pet_level < 50:
|
||||
level_up()
|
||||
|
||||
# 升级
|
||||
# 升级(新的随机属性系统)
|
||||
func level_up():
|
||||
pet_experience -= max_experience
|
||||
pet_level += 1
|
||||
@@ -1524,25 +1608,197 @@ func level_up():
|
||||
# 计算新的升级经验需求(指数增长)
|
||||
max_experience = 100.0 * pow(1.2, pet_level - 1)
|
||||
|
||||
# 升级属性加成
|
||||
var level_bonus = 1.1 # 每级10%属性加成
|
||||
# 随机选择属性进行升级
|
||||
var upgraded_attributes = apply_random_attribute_upgrade()
|
||||
|
||||
max_health *= level_bonus
|
||||
current_health = max_health # 升级回满血
|
||||
attack_damage *= level_bonus
|
||||
max_shield *= level_bonus
|
||||
current_shield = max_shield # 升级回满护盾
|
||||
max_armor *= level_bonus
|
||||
current_armor = max_armor # 升级回满护甲
|
||||
# 检查是否有里程碑奖励(每5级)
|
||||
var milestone_rewards = apply_milestone_bonus()
|
||||
|
||||
# 升级回血和护盾护甲
|
||||
current_health = max_health
|
||||
current_shield = max_shield
|
||||
current_armor = max_armor
|
||||
|
||||
# 升级特效
|
||||
show_level_up_effect()
|
||||
|
||||
# 添加升级细节
|
||||
add_battle_detail_to_panel("🎉 " + pet_name + " 升级到 " + str(pet_level) + " 级!", Color.GOLD)
|
||||
var upgrade_text = "🎉 " + pet_name + " 升级到 " + str(pet_level) + " 级!"
|
||||
upgrade_text += "\n📈 随机提升:" + ", ".join(upgraded_attributes)
|
||||
if milestone_rewards.size() > 0:
|
||||
upgrade_text += "\n🏆 里程碑奖励:" + ", ".join(milestone_rewards)
|
||||
|
||||
add_battle_detail_to_panel(upgrade_text, Color.GOLD)
|
||||
|
||||
call_deferred("update_ui")
|
||||
|
||||
# 应用随机属性升级
|
||||
func apply_random_attribute_upgrade() -> Array[String]:
|
||||
var upgraded_attributes: Array[String] = []
|
||||
var available_attributes = base_upgrade_attributes.duplicate()
|
||||
|
||||
# 随机选择几个属性进行升级
|
||||
for i in range(min(attributes_per_level, available_attributes.size())):
|
||||
var random_index = randi() % available_attributes.size()
|
||||
var selected_attribute = available_attributes[random_index]
|
||||
available_attributes.remove_at(random_index)
|
||||
|
||||
# 应用属性升级
|
||||
var upgrade_applied = apply_single_attribute_upgrade(selected_attribute)
|
||||
if upgrade_applied:
|
||||
upgraded_attributes.append(upgrade_applied)
|
||||
|
||||
return upgraded_attributes
|
||||
|
||||
# 应用单个属性升级
|
||||
func apply_single_attribute_upgrade(attribute_name: String) -> String:
|
||||
match attribute_name:
|
||||
"max_health":
|
||||
var bonus = randf_range(8.0, 15.0) # 随机8-15点生命值
|
||||
max_health += bonus
|
||||
return "生命值 +" + str(int(bonus))
|
||||
"attack_damage":
|
||||
var bonus = randf_range(2.0, 5.0) # 随机2-5点攻击力
|
||||
attack_damage += bonus
|
||||
return "攻击力 +" + str(int(bonus))
|
||||
"move_speed":
|
||||
var bonus = randf_range(3.0, 8.0) # 随机3-8点移动速度
|
||||
move_speed += bonus
|
||||
return "移动速度 +" + str(int(bonus))
|
||||
"max_shield":
|
||||
var bonus = randf_range(5.0, 12.0) # 随机5-12点护盾值
|
||||
max_shield += bonus
|
||||
return "护盾值 +" + str(int(bonus))
|
||||
"max_armor":
|
||||
var bonus = randf_range(4.0, 10.0) # 随机4-10点护甲值
|
||||
max_armor += bonus
|
||||
return "护甲值 +" + str(int(bonus))
|
||||
"crit_rate":
|
||||
var bonus = randf_range(0.01, 0.03) # 随机1-3%暴击率
|
||||
crit_rate = min(1.0, crit_rate + bonus) # 暴击率上限100%
|
||||
return "暴击率 +" + str(int(bonus * 100)) + "%"
|
||||
"health_regen":
|
||||
var bonus = randf_range(0.3, 0.8) # 随机0.3-0.8点生命恢复
|
||||
health_regen += bonus
|
||||
return "生命恢复 +" + str("%.1f" % bonus)
|
||||
"attack_range":
|
||||
var bonus = randf_range(8.0, 20.0) # 随机8-20点攻击距离
|
||||
attack_range += bonus
|
||||
return "攻击距离 +" + str(int(bonus))
|
||||
_:
|
||||
return ""
|
||||
|
||||
# 应用里程碑奖励
|
||||
func apply_milestone_bonus() -> Array[String]:
|
||||
var milestone_rewards: Array[String] = []
|
||||
|
||||
if not level_milestone_bonuses.has(pet_level):
|
||||
return milestone_rewards
|
||||
|
||||
var bonuses = level_milestone_bonuses[pet_level]
|
||||
|
||||
for bonus_key in bonuses.keys():
|
||||
var bonus_value = bonuses[bonus_key]
|
||||
var reward_text = apply_milestone_bonus_single(bonus_key, bonus_value)
|
||||
if reward_text != "":
|
||||
milestone_rewards.append(reward_text)
|
||||
|
||||
return milestone_rewards
|
||||
|
||||
# 应用单个里程碑奖励
|
||||
func apply_milestone_bonus_single(bonus_key: String, bonus_value) -> String:
|
||||
match bonus_key:
|
||||
"max_health":
|
||||
max_health += bonus_value
|
||||
return "生命值 +" + str(bonus_value)
|
||||
"attack_damage":
|
||||
attack_damage += bonus_value
|
||||
return "攻击力 +" + str(bonus_value)
|
||||
"max_shield":
|
||||
max_shield += bonus_value
|
||||
return "护盾值 +" + str(bonus_value)
|
||||
"max_armor":
|
||||
max_armor += bonus_value
|
||||
return "护甲值 +" + str(bonus_value)
|
||||
"crit_rate":
|
||||
crit_rate = min(1.0, crit_rate + bonus_value)
|
||||
return "暴击率 +" + str(int(bonus_value * 100)) + "%"
|
||||
"armor_penetration":
|
||||
armor_penetration += bonus_value
|
||||
return "护甲穿透 +" + str(bonus_value)
|
||||
"life_steal":
|
||||
life_steal = min(1.0, life_steal + bonus_value)
|
||||
return "生命汲取 +" + str(int(bonus_value * 100)) + "%"
|
||||
"knockback_resist":
|
||||
knockback_resist = min(1.0, knockback_resist + bonus_value)
|
||||
return "击退抗性 +" + str(int(bonus_value * 100)) + "%"
|
||||
"dodge_rate":
|
||||
dodge_rate = min(1.0, dodge_rate + bonus_value)
|
||||
return "闪避率 +" + str(int(bonus_value * 100)) + "%"
|
||||
"health_regen":
|
||||
health_regen += bonus_value
|
||||
return "生命恢复 +" + str(bonus_value)
|
||||
"move_speed":
|
||||
move_speed += bonus_value
|
||||
return "移动速度 +" + str(bonus_value)
|
||||
"attack_range":
|
||||
attack_range += bonus_value
|
||||
return "攻击距离 +" + str(bonus_value)
|
||||
"shield_regen":
|
||||
shield_regen += bonus_value
|
||||
return "护盾恢复 +" + str(bonus_value)
|
||||
"crit_damage":
|
||||
crit_damage += bonus_value
|
||||
return "暴击伤害 +" + str(int(bonus_value * 100)) + "%"
|
||||
"berserker_bonus":
|
||||
berserker_bonus += bonus_value
|
||||
return "狂暴加成 +" + str(int(bonus_value * 100)) + "%"
|
||||
"damage_reflect":
|
||||
damage_reflect = min(1.0, damage_reflect + bonus_value)
|
||||
return "伤害反弹 +" + str(int(bonus_value * 100)) + "%"
|
||||
"control_resist":
|
||||
control_resist = min(1.0, control_resist + bonus_value)
|
||||
return "控制抗性 +" + str(int(bonus_value * 100)) + "%"
|
||||
"projectile_speed":
|
||||
projectile_speed += bonus_value
|
||||
return "子弹速度 +" + str(bonus_value)
|
||||
"pierce_count":
|
||||
pierce_count += bonus_value
|
||||
return "穿透数量 +" + str(bonus_value)
|
||||
"enable_berserker_mode":
|
||||
if bonus_value:
|
||||
enable_berserker_mode = true
|
||||
return "解锁狂暴模式"
|
||||
else:
|
||||
return ""
|
||||
"enable_damage_reflect":
|
||||
if bonus_value:
|
||||
enable_damage_reflect = true
|
||||
return "解锁伤害反弹"
|
||||
else:
|
||||
return ""
|
||||
"enable_aid_system":
|
||||
if bonus_value:
|
||||
enable_aid_system = true
|
||||
return "解锁援助召唤"
|
||||
else:
|
||||
return ""
|
||||
"enable_death_immunity":
|
||||
if bonus_value:
|
||||
enable_death_immunity = true
|
||||
death_immunity = true
|
||||
return "解锁死亡免疫"
|
||||
else:
|
||||
return ""
|
||||
"enable_resurrection":
|
||||
if bonus_value:
|
||||
enable_resurrection = true
|
||||
return "解锁死亡重生"
|
||||
else:
|
||||
return ""
|
||||
_:
|
||||
return ""
|
||||
|
||||
# 显示升级特效
|
||||
func show_level_up_effect():
|
||||
if not pet_image:
|
||||
@@ -1677,34 +1933,24 @@ func heal(amount: float):
|
||||
current_health = min(max_health, current_health + amount)
|
||||
call_deferred("update_ui")
|
||||
|
||||
# 对目标应用击退效果
|
||||
# 击退效果已禁用
|
||||
func apply_knockback_to_target(target: CharacterBody2D):
|
||||
if not target or not is_instance_valid(target):
|
||||
return
|
||||
|
||||
# 计算击退方向
|
||||
var direction = (target.global_position - global_position).normalized()
|
||||
|
||||
# 计算击退力度(考虑目标的击退抗性)
|
||||
var effective_knockback = knockback_force * (1.0 - target.knockback_resist)
|
||||
|
||||
if effective_knockback > 0:
|
||||
target.apply_knockback(direction, effective_knockback)
|
||||
add_battle_detail_to_panel(pet_name + " 击退了 " + target.pet_name)
|
||||
# 击退功能暂时禁用
|
||||
pass
|
||||
|
||||
# 被击退时调用
|
||||
# 击退效果已禁用
|
||||
func apply_knockback(direction: Vector2, force: float):
|
||||
if not is_alive:
|
||||
return
|
||||
# 击退功能暂时禁用
|
||||
pass
|
||||
|
||||
# 将位置限制在战斗区域内
|
||||
func clamp_position_to_battle_area(pos: Vector2) -> Vector2:
|
||||
var battle_area_min = Vector2(50, 50)
|
||||
var battle_area_max = Vector2(1350, 670)
|
||||
|
||||
# 设置击退状态
|
||||
is_being_knocked_back = true
|
||||
knockback_velocity = direction * force
|
||||
|
||||
# 击退时短暂失去目标(可选)
|
||||
if current_target and randf() < 0.3: # 30%概率失去目标
|
||||
current_target = null
|
||||
current_state = PetState.IDLE
|
||||
pos.x = clamp(pos.x, battle_area_min.x, battle_area_max.x)
|
||||
pos.y = clamp(pos.y, battle_area_min.y, battle_area_max.y)
|
||||
return pos
|
||||
|
||||
# 元素克制计算
|
||||
func get_element_multiplier(attacker_element: ElementType, defender_element: ElementType) -> float:
|
||||
@@ -1827,3 +2073,82 @@ func clamp_to_patrol_area():
|
||||
# 限制位置
|
||||
position.x = clamp(position.x, min_x, max_x)
|
||||
position.y = clamp(position.y, min_y, max_y)
|
||||
|
||||
# 播放受伤动画(带冷却保护)
|
||||
func play_hurt_animation():
|
||||
if not pet_image:
|
||||
return
|
||||
|
||||
# 检查受伤动画冷却时间
|
||||
var current_time = Time.get_ticks_msec() / 1000.0
|
||||
if current_time - last_hurt_time < hurt_animation_cooldown:
|
||||
return # 冷却中,不播放动画
|
||||
|
||||
last_hurt_time = current_time
|
||||
|
||||
# 如果已经有受伤动画在播放,停止之前的
|
||||
if hurt_tween:
|
||||
hurt_tween.kill()
|
||||
hurt_tween = null
|
||||
|
||||
# 性能模式下简化动画
|
||||
if performance_mode:
|
||||
# 简单的颜色变化,无需Tween
|
||||
pet_image.modulate = Color.RED
|
||||
# 使用计时器恢复颜色(更轻量)
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
if pet_image: # 确保宠物还存在
|
||||
pet_image.modulate = original_modulate
|
||||
return
|
||||
|
||||
# 创建受伤动画(闪红效果)
|
||||
hurt_tween = create_tween()
|
||||
|
||||
# 立即变红
|
||||
pet_image.modulate = Color.RED
|
||||
|
||||
# 0.2秒后恢复原色
|
||||
hurt_tween.tween_property(pet_image, "modulate", original_modulate, 0.2)
|
||||
|
||||
# 动画结束后清理
|
||||
hurt_tween.tween_callback(func():
|
||||
hurt_tween = null
|
||||
)
|
||||
|
||||
# 切换性能模式
|
||||
func toggle_performance_mode():
|
||||
performance_mode = !performance_mode
|
||||
var mode_text = "性能模式" if performance_mode else "正常模式"
|
||||
add_battle_detail_to_panel("⚡ " + pet_name + " 切换到 " + mode_text, Color.YELLOW)
|
||||
print("⚡ " + pet_name + " 切换到 " + mode_text)
|
||||
|
||||
# 输出宠物性能状态
|
||||
func debug_performance_status():
|
||||
print("=== " + pet_name + " 性能状态调试 ===")
|
||||
print("性能模式: " + str(performance_mode))
|
||||
print("伤害反弹深度: " + str(damage_reflect_depth))
|
||||
print("帧跳跃计数: " + str(frame_skip_counter))
|
||||
print("上次受伤时间: " + str(last_hurt_time))
|
||||
print("上次攻击时间: " + str(last_attack_time))
|
||||
print("当前状态: " + str(current_state))
|
||||
print("是否存活: " + str(is_alive))
|
||||
print("是否正在死亡: " + str(is_dying))
|
||||
print("============================")
|
||||
|
||||
# 重置性能状态(紧急恢复)
|
||||
func reset_performance_state():
|
||||
performance_mode = false
|
||||
damage_reflect_depth = 0
|
||||
frame_skip_counter = 0
|
||||
|
||||
# 清理可能卡住的动画
|
||||
if hurt_tween:
|
||||
hurt_tween.kill()
|
||||
hurt_tween = null
|
||||
|
||||
# 恢复正常颜色
|
||||
if pet_image:
|
||||
pet_image.modulate = original_modulate
|
||||
|
||||
print("🔄 " + pet_name + " 性能状态已重置")
|
||||
add_battle_detail_to_panel("🔄 " + pet_name + " 性能状态已重置", Color.GREEN)
|
||||
|
||||
@@ -57,7 +57,7 @@ var current_attacker_name: String = "" # 当前进攻者用户名
|
||||
|
||||
|
||||
func _ready():
|
||||
# 加载宠物配置
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
load_pet_configs()
|
||||
|
||||
# 连接返回农场按钮
|
||||
@@ -69,7 +69,6 @@ func _ready():
|
||||
battle_end_panel.visible = false
|
||||
if pet_battle_details_panel:
|
||||
pet_battle_details_panel.visible = false
|
||||
|
||||
|
||||
# 加载宠物配置
|
||||
func load_pet_configs():
|
||||
@@ -115,10 +114,17 @@ func clear_battle_details():
|
||||
if battle_details:
|
||||
battle_details.text = ""
|
||||
|
||||
# 战斗结束检查计时器
|
||||
var battle_check_timer: float = 0.0
|
||||
var battle_check_interval: float = 0.5 # 每0.5秒检查一次,减少性能开销
|
||||
|
||||
func _process(delta):
|
||||
# 只有启用自动对战时才检查战斗结束
|
||||
# 只有启用自动对战时才检查战斗结束,并使用计时器减少检查频率
|
||||
if auto_battle_enabled and battle_started and not battle_ended:
|
||||
check_battle_end()
|
||||
battle_check_timer += delta
|
||||
if battle_check_timer >= battle_check_interval:
|
||||
battle_check_timer = 0.0
|
||||
check_battle_end()
|
||||
|
||||
|
||||
# 获取队伍节点 - 供宠物调用
|
||||
@@ -224,12 +230,6 @@ func end_battle(winner: String):
|
||||
# 显示战斗结算面板
|
||||
func show_battle_end_panel(winner: String):
|
||||
var result_text = ""
|
||||
var team1_survivors = 0
|
||||
var team2_survivors = 0
|
||||
var team1_total_damage = 0.0
|
||||
var team2_total_damage = 0.0
|
||||
var team1_pets_info: Array[String] = []
|
||||
var team2_pets_info: Array[String] = []
|
||||
|
||||
# 统计存活宠物和详细信息 - 从宠物组中获取
|
||||
var all_pets = get_tree().get_nodes_in_group("pets")
|
||||
@@ -237,22 +237,6 @@ func show_battle_end_panel(winner: String):
|
||||
if not is_instance_valid(pet):
|
||||
continue
|
||||
|
||||
var status = "💀死亡"
|
||||
if pet.is_alive:
|
||||
status = "❤️存活(" + str(int(pet.current_health)) + ")"
|
||||
if pet.pet_team == "team1":
|
||||
team1_survivors += 1
|
||||
elif pet.pet_team == "team2":
|
||||
team2_survivors += 1
|
||||
|
||||
# 统计战力
|
||||
if pet.pet_team == "team1":
|
||||
team1_total_damage += pet.attack_damage
|
||||
team1_pets_info.append(pet.pet_name + " " + status)
|
||||
elif pet.pet_team == "team2":
|
||||
team2_total_damage += pet.attack_damage
|
||||
team2_pets_info.append(pet.pet_name + " " + status)
|
||||
|
||||
# 构建结算文本
|
||||
result_text += "=== 战斗结算 ===\n\n"
|
||||
|
||||
@@ -416,39 +400,46 @@ func clear_all_pets():
|
||||
# 清空对战细节
|
||||
clear_battle_details()
|
||||
|
||||
# 先移除宠物组标签
|
||||
var all_pets = get_tree().get_nodes_in_group("pets")
|
||||
for pet in all_pets:
|
||||
if is_instance_valid(pet):
|
||||
# 检查是否是当前面板下的宠物
|
||||
if pet.get_parent() == team1_node or pet.get_parent() == team2_node or pet.get_parent() == neutral_node:
|
||||
pet.remove_from_group("pets")
|
||||
pet.remove_from_group("team1")
|
||||
pet.remove_from_group("team2")
|
||||
pet.remove_from_group("neutral")
|
||||
# 批量处理宠物清理,提高性能
|
||||
var nodes_to_clear = [team1_node, team2_node, neutral_node]
|
||||
|
||||
# 清理现有宠物
|
||||
for child in team1_node.get_children():
|
||||
if is_instance_valid(child):
|
||||
child.queue_free()
|
||||
|
||||
for child in team2_node.get_children():
|
||||
if is_instance_valid(child):
|
||||
child.queue_free()
|
||||
|
||||
for child in neutral_node.get_children():
|
||||
if is_instance_valid(child):
|
||||
child.queue_free()
|
||||
for node in nodes_to_clear:
|
||||
if not is_instance_valid(node):
|
||||
continue
|
||||
|
||||
# 先移除组标签,再清理节点
|
||||
for child in node.get_children():
|
||||
if is_instance_valid(child):
|
||||
# 停止宠物的所有行为,防止在清理过程中继续执行逻辑
|
||||
if child.has_method("set_combat_enabled"):
|
||||
child.set_combat_enabled(false)
|
||||
|
||||
# 移除所有组标签
|
||||
child.remove_from_group("pets")
|
||||
child.remove_from_group("team1")
|
||||
child.remove_from_group("team2")
|
||||
child.remove_from_group("neutral")
|
||||
child.remove_from_group("aid_minions")
|
||||
|
||||
# 立即销毁,避免延迟
|
||||
node.remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
# 清空队伍数组
|
||||
team1_pets.clear()
|
||||
team2_pets.clear()
|
||||
|
||||
# 清理所有子弹
|
||||
var all_projectiles = get_tree().get_nodes_in_group("projectiles")
|
||||
for projectile in all_projectiles:
|
||||
if is_instance_valid(projectile):
|
||||
projectile.queue_free()
|
||||
# 清理所有子弹和援助宠物
|
||||
var groups_to_clear = ["projectiles", "aid_minions"]
|
||||
for group_name in groups_to_clear:
|
||||
var group_nodes = get_tree().get_nodes_in_group(group_name)
|
||||
for node in group_nodes:
|
||||
if is_instance_valid(node):
|
||||
node.remove_from_group(group_name)
|
||||
node.queue_free()
|
||||
|
||||
# 等待一帧确保清理完成
|
||||
await get_tree().process_frame
|
||||
|
||||
# 处理偷菜对战结果
|
||||
func handle_steal_battle_result(winner: String):
|
||||
@@ -556,7 +547,9 @@ func update_battle_pet_data(pet_id: String, attacker_name: String, exp_gained: f
|
||||
"new_max_experience": max_exp,
|
||||
"new_intimacy": current_intimacy,
|
||||
"level_ups": level_ups,
|
||||
"level_bonus_multiplier": level_bonus_multiplier
|
||||
"level_bonus_multiplier": level_bonus_multiplier,
|
||||
"is_steal_battle": is_steal_battle,
|
||||
"battle_winner": winner_team
|
||||
}
|
||||
|
||||
# 发送数据到服务器
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
uid://b4p4xk0pdf7yg
|
||||
@@ -95,8 +95,9 @@ func _add_message_to_history(data: Dictionary):
|
||||
# 如果有玩家昵称,优先显示昵称
|
||||
var display_name = player_name if player_name != "" else username
|
||||
|
||||
# 格式化时间
|
||||
var datetime = Time.get_datetime_dict_from_unix_time(timestamp)
|
||||
# 格式化时间 - 确保timestamp是整数类型
|
||||
var timestamp_int = int(timestamp) if typeof(timestamp) == TYPE_STRING else timestamp
|
||||
var datetime = Time.get_datetime_dict_from_unix_time(timestamp_int)
|
||||
var time_str = "%04d年%02d月%02d日 %02d:%02d:%02d" % [datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second]
|
||||
|
||||
# 创建消息记录
|
||||
|
||||
@@ -427,7 +427,7 @@ func _on_harvest_button_pressed():
|
||||
|
||||
|
||||
|
||||
#=================面板通用函数==========================
|
||||
#===================面板通用函数==========================
|
||||
#退出
|
||||
func _on_quit_button_pressed():
|
||||
self.hide()
|
||||
@@ -447,7 +447,7 @@ func _on_visibility_changed():
|
||||
GlobalVariables.isZoomDisabled = false
|
||||
pass
|
||||
|
||||
#=================面板通用函数==========================
|
||||
#===================面板通用函数==========================
|
||||
|
||||
# 更新面板信息显示
|
||||
func _update_panel_information():
|
||||
|
||||
@@ -60,9 +60,8 @@ func show_pet_info(pet_name: String, pet_data: Dictionary):
|
||||
# 设置宠物图片
|
||||
_set_pet_image(pet_name)
|
||||
|
||||
# 设置宠物名称
|
||||
var basic_info = pet_data.get("基本信息", {})
|
||||
var pet_owner_name = basic_info.get("宠物名称", pet_name)
|
||||
# 设置宠物名称(新格式:直接从pet_name字段获取)
|
||||
var pet_owner_name = pet_data.get("pet_name", pet_name)
|
||||
pet_name_edit.text = pet_owner_name
|
||||
|
||||
# 设置宠物详细信息
|
||||
@@ -85,26 +84,40 @@ func _set_pet_image(pet_name: String):
|
||||
|
||||
# 获取宠物纹理
|
||||
func _get_pet_texture(pet_name: String) -> Texture2D:
|
||||
var pet_config = _load_pet_config()
|
||||
# 从服务器的宠物配置获取场景路径
|
||||
var pet_config = main_game.pet_config # 使用服务器返回的宠物配置
|
||||
if pet_config.has(pet_name):
|
||||
var pet_info = pet_config[pet_name]
|
||||
var scene_path = pet_info.get("场景路径", "")
|
||||
var scene_path = pet_info.get("pet_image", "") # 使用服务器数据的pet_image字段
|
||||
print("宠物信息面板 ", pet_name, " 的图片路径:", scene_path)
|
||||
|
||||
if scene_path != "" and ResourceLoader.exists(scene_path):
|
||||
print("宠物信息面板开始加载宠物场景:", scene_path)
|
||||
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()
|
||||
# 直接使用实例化的场景根节点,因为根节点就是PetImage
|
||||
if pet_instance and pet_instance.sprite_frames:
|
||||
var animation_names = pet_instance.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)
|
||||
var frame_count = pet_instance.sprite_frames.get_frame_count(default_animation)
|
||||
if frame_count > 0:
|
||||
var texture = pet_image_node.sprite_frames.get_frame_texture(default_animation, 0)
|
||||
var texture = pet_instance.sprite_frames.get_frame_texture(default_animation, 0)
|
||||
print("宠物信息面板成功获取宠物纹理:", pet_name)
|
||||
pet_instance.queue_free()
|
||||
return texture
|
||||
else:
|
||||
print("宠物信息面板场景没有动画:", pet_name)
|
||||
else:
|
||||
print("宠物信息面板场景没有PetImage节点或sprite_frames:", pet_name)
|
||||
pet_instance.queue_free()
|
||||
else:
|
||||
print("宠物信息面板无法加载宠物场景:", scene_path)
|
||||
else:
|
||||
print("宠物信息面板图片路径无效或文件不存在:", scene_path)
|
||||
else:
|
||||
print("宠物信息面板配置中没有找到:", pet_name)
|
||||
return null
|
||||
|
||||
# 加载宠物配置数据
|
||||
@@ -123,19 +136,10 @@ func _load_pet_config() -> Dictionary:
|
||||
|
||||
return json.data
|
||||
|
||||
# 设置宠物详细信息(使用bbcode美化)
|
||||
# 设置宠物详细信息(使用bbcode美化)- 新格式
|
||||
func _set_pet_detailed_info(pet_name: String, pet_data: Dictionary):
|
||||
var basic_info = pet_data.get("基本信息", {})
|
||||
var level_exp = pet_data.get("等级经验", {})
|
||||
var purchase_info = pet_data.get("购买信息", {})
|
||||
var health_defense = pet_data.get("生命与防御", {})
|
||||
var attack_info = pet_data.get("基础攻击属性", {})
|
||||
var movement = pet_data.get("移动与闪避", {})
|
||||
var element = pet_data.get("元素属性", {})
|
||||
var quality = pet_data.get("品质系统", {})
|
||||
|
||||
# 计算宠物年龄
|
||||
var pet_birthday = basic_info.get("生日", "")
|
||||
var pet_birthday = pet_data.get("pet_birthday", "")
|
||||
var pet_age = 0
|
||||
if pet_birthday != "":
|
||||
pet_age = _calculate_pet_age(pet_birthday)
|
||||
@@ -145,76 +149,64 @@ func _set_pet_detailed_info(pet_name: String, pet_data: Dictionary):
|
||||
|
||||
# 基本信息
|
||||
info_text += "[color=pink][b]🐾 基本信息[/b][/color]\n"
|
||||
info_text += "宠物类型:[color=yellow]" + str(basic_info.get("宠物类型", "未知")) + "[/color]\n"
|
||||
info_text += "宠物编号:[color=gray]" + str(basic_info.get("宠物ID", "无")) + "[/color]\n"
|
||||
info_text += "性格特点:[color=cyan]" + str(basic_info.get("性格", "活泼")) + "[/color]\n"
|
||||
info_text += "宠物类型:[color=yellow]" + str(pet_data.get("pet_type", "未知")) + "[/color]\n"
|
||||
info_text += "宠物编号:[color=gray]" + str(pet_data.get("pet_id", "无")) + "[/color]\n"
|
||||
info_text += "性格特点:[color=cyan]" + str(pet_data.get("pet_temperament", "活泼")) + "[/color]\n"
|
||||
info_text += "出生日期:[color=green]" + str(pet_birthday) + "[/color]\n"
|
||||
info_text += "年龄天数:[color=orange]" + str(pet_age) + " 天[/color]\n"
|
||||
info_text += "爱好:[color=magenta]" + str(pet_data.get("pet_hobby", "无")) + "[/color]\n"
|
||||
info_text += "介绍:[color=lime]" + str(pet_data.get("pet_introduction", "无")) + "[/color]\n\n"
|
||||
|
||||
# 等级经验
|
||||
info_text += "[color=gold][b]⭐ 等级经验[/b][/color]\n"
|
||||
info_text += "当前等级:[color=yellow]" + str(level_exp.get("宠物等级", 1)) + " 级[/color]\n"
|
||||
info_text += "经验值:[color=cyan]" + str(level_exp.get("当前经验", 0)) + "/" + str(level_exp.get("最大经验", 100)) + "[/color]\n"
|
||||
info_text += "亲密度:[color=pink]" + str(level_exp.get("亲密度", 0)) + "/" + str(level_exp.get("最大亲密度", 1000)) + "[/color]\n\n"
|
||||
info_text += "当前等级:[color=yellow]" + str(pet_data.get("pet_level", 1)) + " 级[/color]\n"
|
||||
info_text += "经验值:[color=cyan]" + str(pet_data.get("pet_experience", 0)) + "/" + str(pet_data.get("pet_max_experience", 1000)) + "[/color]\n"
|
||||
info_text += "亲密度:[color=pink]" + str(pet_data.get("pet_intimacy", 0)) + "/" + str(pet_data.get("pet_max_intimacy", 1000)) + "[/color]\n\n"
|
||||
|
||||
# 生命与防御
|
||||
info_text += "[color=red][b]❤️ 生命与防御[/b][/color]\n"
|
||||
info_text += "生命值:[color=red]" + str(health_defense.get("当前生命值", 0)) + "/" + str(health_defense.get("最大生命值", 0)) + "[/color]\n"
|
||||
info_text += "护甲值:[color=blue]" + str(health_defense.get("当前护甲值", 0)) + "/" + str(health_defense.get("最大护甲值", 0)) + "[/color]\n"
|
||||
info_text += "护盾值:[color=cyan]" + str(health_defense.get("当前护盾值", 0)) + "/" + str(health_defense.get("最大护盾值", 0)) + "[/color]\n"
|
||||
info_text += "生命恢复:[color=lime]" + str(health_defense.get("生命恢复速度", 0)) + "/秒[/color]\n\n"
|
||||
info_text += "生命值:[color=red]" + str(pet_data.get("pet_current_health", pet_data.get("max_health", 100))) + "/" + str(pet_data.get("max_health", 100)) + "[/color]\n"
|
||||
info_text += "护甲值:[color=blue]" + str(pet_data.get("pet_current_armor", pet_data.get("max_armor", 0))) + "/" + str(pet_data.get("max_armor", 0)) + "[/color]\n"
|
||||
info_text += "护盾值:[color=cyan]" + str(pet_data.get("pet_current_shield", pet_data.get("max_shield", 0))) + "/" + str(pet_data.get("max_shield", 0)) + "[/color]\n"
|
||||
info_text += "生命恢复:[color=lime]" + str(pet_data.get("health_regen", 0)) + "/秒[/color]\n"
|
||||
info_text += "护盾恢复:[color=cyan]" + str(pet_data.get("shield_regen", 0)) + "/秒[/color]\n\n"
|
||||
|
||||
# 攻击属性
|
||||
info_text += "[color=orange][b]⚔️ 攻击属性[/b][/color]\n"
|
||||
info_text += "攻击类型:[color=yellow]" + _get_attack_type_name(str(attack_info.get("攻击类型", "MELEE"))) + "[/color]\n"
|
||||
info_text += "攻击伤害:[color=red]" + str(attack_info.get("基础攻击伤害", 0)) + " 点[/color]\n"
|
||||
info_text += "攻击距离:[color=green]" + str(attack_info.get("攻击距离", 0)) + " 像素[/color]\n"
|
||||
info_text += "暴击几率:[color=purple]" + str(attack_info.get("暴击率", 0) * 100) + "%[/color]\n"
|
||||
info_text += "暴击倍数:[color=purple]" + str(attack_info.get("暴击伤害倍数", 1.0)) + " 倍[/color]\n"
|
||||
info_text += "生命汲取:[color=magenta]" + str(attack_info.get("生命汲取", 0) * 100) + "%[/color]\n\n"
|
||||
info_text += "攻击伤害:[color=red]" + str(pet_data.get("base_attack_damage", 0)) + " 点[/color]\n"
|
||||
info_text += "暴击几率:[color=purple]" + str(pet_data.get("crit_rate", 0) * 100) + "%[/color]\n"
|
||||
info_text += "暴击倍数:[color=purple]" + str(pet_data.get("crit_damage", 1.0)) + " 倍[/color]\n"
|
||||
info_text += "护甲穿透:[color=orange]" + str(pet_data.get("armor_penetration", 0)) + " 点[/color]\n"
|
||||
info_text += "左手武器:[color=yellow]" + str(pet_data.get("left_weapon", "无")) + "[/color]\n"
|
||||
info_text += "右手武器:[color=yellow]" + str(pet_data.get("right_weapon", "无")) + "[/color]\n\n"
|
||||
|
||||
# 移动与闪避
|
||||
info_text += "[color=green][b]🏃 移动与闪避[/b][/color]\n"
|
||||
info_text += "移动速度:[color=cyan]" + str(movement.get("移动速度", 0)) + " 像素/秒[/color]\n"
|
||||
info_text += "闪避几率:[color=yellow]" + str(movement.get("闪避率", 0) * 100) + "%[/color]\n"
|
||||
info_text += "击退力度:[color=red]" + str(movement.get("击退力度", 0)) + " 点[/color]\n"
|
||||
info_text += "击退抗性:[color=blue]" + str(movement.get("击退抗性", 0) * 100) + "%[/color]\n\n"
|
||||
info_text += "移动速度:[color=cyan]" + str(pet_data.get("move_speed", 0)) + " 像素/秒[/color]\n"
|
||||
info_text += "闪避几率:[color=yellow]" + str(pet_data.get("dodge_rate", 0) * 100) + "%[/color]\n\n"
|
||||
|
||||
# 元素属性
|
||||
info_text += "[color=purple][b]🔥 元素属性[/b][/color]\n"
|
||||
info_text += "元素类型:[color=yellow]" + _get_element_name(str(element.get("元素类型", "NONE"))) + "[/color]\n"
|
||||
info_text += "元素伤害:[color=orange]" + str(element.get("元素克制额外伤害", 0)) + " 点[/color]\n\n"
|
||||
info_text += "元素类型:[color=yellow]" + _get_element_name(str(pet_data.get("element_type", "NONE"))) + "[/color]\n"
|
||||
info_text += "元素伤害:[color=orange]" + str(pet_data.get("element_damage_bonus", 0)) + " 点[/color]\n\n"
|
||||
|
||||
# 品质系统
|
||||
var quality_text = str(quality.get("宠物品质", "COMMON"))
|
||||
var quality_color = "white"
|
||||
var quality_name = ""
|
||||
if quality_text == "COMMON":
|
||||
quality_color = "gray"
|
||||
quality_name = "普通"
|
||||
elif quality_text == "RARE":
|
||||
quality_color = "blue"
|
||||
quality_name = "稀有"
|
||||
elif quality_text == "EPIC":
|
||||
quality_color = "purple"
|
||||
quality_name = "史诗"
|
||||
elif quality_text == "LEGENDARY":
|
||||
quality_color = "orange"
|
||||
quality_name = "传说"
|
||||
else:
|
||||
quality_name = quality_text
|
||||
|
||||
info_text += "[color=gold][b]✨ 品质系统[/b][/color]\n"
|
||||
info_text += "宠物品质:[color=" + quality_color + "]" + quality_name + "[/color]\n\n"
|
||||
|
||||
# 购买信息
|
||||
info_text += "[color=gold][b]💰 购买信息[/b][/color]\n"
|
||||
info_text += "购买价格:[color=yellow]" + str(purchase_info.get("购买价格", 0)) + " 金币[/color]\n"
|
||||
# 技能系统
|
||||
info_text += "[color=gold][b]✨ 技能系统[/b][/color]\n"
|
||||
if pet_data.get("enable_multi_projectile_skill", false):
|
||||
info_text += "多重弹射:[color=green]已激活[/color] (延迟: " + str(pet_data.get("multi_projectile_delay", 0)) + "秒)\n"
|
||||
if pet_data.get("enable_berserker_skill", false):
|
||||
info_text += "狂暴技能:[color=red]已激活[/color] (倍数: " + str(pet_data.get("berserker_bonus", 1.0)) + ", 持续: " + str(pet_data.get("berserker_duration", 0)) + "秒)\n"
|
||||
if pet_data.get("enable_self_destruct_skill", false):
|
||||
info_text += "自爆技能:[color=orange]已激活[/color]\n"
|
||||
if pet_data.get("enable_summon_pet_skill", false):
|
||||
info_text += "召唤技能:[color=cyan]已激活[/color] (数量: " + str(pet_data.get("summon_count", 0)) + ", 缩放: " + str(pet_data.get("summon_scale", 1.0)) + ")\n"
|
||||
if pet_data.get("enable_death_respawn_skill", false):
|
||||
info_text += "死亡重生:[color=purple]已激活[/color] (生命: " + str(pet_data.get("respawn_health_percentage", 0) * 100) + "%)\n"
|
||||
info_text += "\n"
|
||||
|
||||
# 设置文本
|
||||
pet_inform.text = info_text
|
||||
|
||||
|
||||
# 获取攻击类型名称
|
||||
func _get_attack_type_name(attack_type: String) -> String:
|
||||
match attack_type:
|
||||
@@ -340,9 +332,8 @@ func on_edit_inform_button_pressed():
|
||||
Toast.show("宠物名字太长,最多20个字符", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 获取当前宠物名字
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var current_name = basic_info.get("宠物名称", "")
|
||||
# 获取当前宠物名字(新格式)
|
||||
var current_name = current_pet_data.get("pet_name", "")
|
||||
|
||||
# 检查名字是否有变化
|
||||
if new_pet_name == current_name:
|
||||
@@ -383,9 +374,8 @@ func _on_confirm_rename_pet(new_name: String, dialog: AcceptDialog):
|
||||
|
||||
# 取消重命名宠物
|
||||
func _on_cancel_rename_pet(dialog: AcceptDialog):
|
||||
# 恢复原名字
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var original_name = basic_info.get("宠物名称", "")
|
||||
# 恢复原名字(新格式)
|
||||
var original_name = current_pet_data.get("pet_name", "")
|
||||
pet_name_edit.text = original_name
|
||||
dialog.queue_free()
|
||||
|
||||
@@ -395,9 +385,8 @@ func _send_rename_pet_request(new_name: String):
|
||||
Toast.show("网络功能不可用", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 获取宠物ID
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var pet_id = basic_info.get("宠物ID", "")
|
||||
# 获取宠物ID(新格式)
|
||||
var pet_id = current_pet_data.get("pet_id", "")
|
||||
|
||||
if pet_id == "":
|
||||
Toast.show("宠物ID无效", Color.RED, 2.0, 1.0)
|
||||
@@ -411,9 +400,9 @@ func _send_rename_pet_request(new_name: String):
|
||||
|
||||
# 处理重命名成功的响应(从宠物背包或其他地方调用)
|
||||
func on_rename_pet_success(pet_id: String, new_name: String):
|
||||
# 更新当前宠物数据
|
||||
if current_pet_data.get("基本信息", {}).get("宠物ID", "") == pet_id:
|
||||
current_pet_data["基本信息"]["宠物名称"] = new_name
|
||||
# 更新当前宠物数据(新格式)
|
||||
if current_pet_data.get("pet_id", "") == pet_id:
|
||||
current_pet_data["pet_name"] = new_name
|
||||
pet_name_edit.text = new_name
|
||||
Toast.show("宠物名字修改成功!", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
@@ -469,11 +458,6 @@ func on_use_item_button_pressed():
|
||||
|
||||
# 巡逻按钮点击事件
|
||||
func _on_patrol_button_pressed():
|
||||
#直接在客户端
|
||||
patro_button.text = "取消巡逻"
|
||||
patro_button.modulate = Color.ORANGE
|
||||
|
||||
|
||||
if current_pet_data.is_empty():
|
||||
Toast.show("没有选择宠物", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
@@ -484,65 +468,61 @@ func _on_patrol_button_pressed():
|
||||
return
|
||||
|
||||
# 获取宠物ID
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var pet_id = basic_info.get("宠物ID", "")
|
||||
|
||||
var pet_id = current_pet_data.get("pet_id", "")
|
||||
if pet_id == "":
|
||||
Toast.show("宠物ID无效", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 检查当前宠物是否已在巡逻
|
||||
var is_currently_patrolling = _is_pet_patrolling(pet_id)
|
||||
# 检查是否已经在巡逻
|
||||
var is_patrolling = _is_pet_patrolling(pet_id)
|
||||
|
||||
if is_currently_patrolling:
|
||||
# 取消巡逻
|
||||
_remove_from_patrol(pet_id)
|
||||
if is_patrolling:
|
||||
# 取消巡逻 - 发送到服务器
|
||||
_send_patrol_request(pet_id, false)
|
||||
var pet_name = current_pet_data.get("pet_name", "宠物")
|
||||
Toast.show("正在取消 " + pet_name + " 的巡逻...", Color.YELLOW, 2.0, 1.0)
|
||||
else:
|
||||
# 添加到巡逻
|
||||
_add_to_patrol(pet_id)
|
||||
# 检查巡逻宠物数量限制
|
||||
if main_game.patrol_pet_instances.size() >= 4:
|
||||
Toast.show("最多只能设置4个巡逻宠物", Color.RED, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 开始巡逻 - 发送到服务器
|
||||
_send_patrol_request(pet_id, true)
|
||||
var pet_name = current_pet_data.get("pet_name", "宠物")
|
||||
#Toast.show("正在设置 " + pet_name + " 为巡逻宠物...", Color.GREEN, 2.0, 1.0)
|
||||
|
||||
# 检查宠物是否正在巡逻(基于服务器数据)
|
||||
# 发送巡逻请求到服务器
|
||||
func _send_patrol_request(pet_id: String, is_patrolling: bool):
|
||||
var message = {
|
||||
"type": "set_patrol_pet",
|
||||
"pet_id": pet_id,
|
||||
"is_patrolling": is_patrolling
|
||||
}
|
||||
tcp_network_manager_panel.client.send_data(message)
|
||||
|
||||
# 检查宠物是否在巡逻
|
||||
func _is_pet_patrolling(pet_id: String) -> bool:
|
||||
# 检查服务器的巡逻宠物数据
|
||||
if main_game.patrol_pets == null or main_game.patrol_pets.size() == 0:
|
||||
return false
|
||||
|
||||
# 遍历巡逻宠物列表,查找匹配的ID
|
||||
for patrol_pet in main_game.patrol_pets:
|
||||
var patrol_pet_id = patrol_pet.get("基本信息", {}).get("宠物ID", "")
|
||||
if patrol_pet_id == pet_id:
|
||||
return true
|
||||
|
||||
# 检查本地 patrol_pet_instances 数组
|
||||
for pet_instance in main_game.patrol_pet_instances:
|
||||
if pet_instance and is_instance_valid(pet_instance):
|
||||
if pet_instance.pet_id == pet_id:
|
||||
return true
|
||||
return false
|
||||
|
||||
# 添加到巡逻(新的基于ID的逻辑)
|
||||
func _add_to_patrol(pet_id: String):
|
||||
# 检查巡逻宠物数量限制(目前服务器设置最多3个)
|
||||
if main_game.patrol_pets != null and main_game.patrol_pets.size() >= 3:
|
||||
Toast.show("最多只能设置3个巡逻宠物", Color.ORANGE, 3.0, 1.0)
|
||||
return
|
||||
# 移除巡逻宠物
|
||||
func _remove_patrol_pet(pet_id: String):
|
||||
# 查找并移除对应的巡逻宠物实例
|
||||
for pet_instance in main_game.patrol_pet_instances:
|
||||
if pet_instance and is_instance_valid(pet_instance):
|
||||
# 检查是否是对应的巡逻宠物
|
||||
if pet_instance.pet_id == pet_id:
|
||||
pet_instance.queue_free()
|
||||
main_game.patrol_pet_instances.erase(pet_instance)
|
||||
print("移除巡逻宠物实例: " + pet_instance.pet_name)
|
||||
return
|
||||
|
||||
# 目前简化为只允许一个巡逻宠物
|
||||
if main_game.patrol_pets != null and main_game.patrol_pets.size() >= 1:
|
||||
Toast.show("已有宠物在巡逻,请先取消当前巡逻", Color.ORANGE, 3.0, 1.0)
|
||||
return
|
||||
|
||||
# 如果不是访问模式,则发送到服务器保存
|
||||
if not main_game.is_visiting_mode:
|
||||
# 发送到服务器保存
|
||||
tcp_network_manager_panel.sendSetPatrolPet(pet_id, true)
|
||||
var pet_name = current_pet_data.get("基本信息", {}).get("宠物名称", "未知")
|
||||
else:
|
||||
Toast.show("访问模式下无法设置巡逻宠物", Color.ORANGE, 2.0, 1.0)
|
||||
|
||||
# 从巡逻中移除(新的基于ID的逻辑)
|
||||
func _remove_from_patrol(pet_id: String):
|
||||
# 如果不是访问模式,则发送到服务器保存
|
||||
if not main_game.is_visiting_mode:
|
||||
# 发送到服务器移除
|
||||
tcp_network_manager_panel.sendSetPatrolPet(pet_id, false)
|
||||
else:
|
||||
Toast.show("访问模式下无法取消巡逻宠物", Color.ORANGE, 2.0, 1.0)
|
||||
print("未找到对应的巡逻宠物实例: " + pet_id)
|
||||
|
||||
# 更新巡逻按钮文本
|
||||
func _update_patrol_button_text(is_patrolling: bool):
|
||||
@@ -558,8 +538,7 @@ func _refresh_patrol_button():
|
||||
if current_pet_data.is_empty():
|
||||
return
|
||||
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var pet_id = basic_info.get("宠物ID", "")
|
||||
var pet_id = current_pet_data.get("pet_id", "")
|
||||
|
||||
if pet_id == "":
|
||||
return
|
||||
@@ -578,9 +557,8 @@ func _on_battle_button_pressed():
|
||||
Toast.show("访问模式下无法设置出战宠物", Color.ORANGE, 2.0, 1.0)
|
||||
return
|
||||
|
||||
# 获取宠物ID
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var pet_id = basic_info.get("宠物ID", "")
|
||||
# 获取宠物ID(新格式)
|
||||
var pet_id = current_pet_data.get("pet_id", "")
|
||||
|
||||
if pet_id == "":
|
||||
Toast.show("宠物ID无效", Color.RED, 2.0, 1.0)
|
||||
@@ -602,9 +580,9 @@ func _is_pet_battling(pet_id: String) -> bool:
|
||||
if main_game.battle_pets == null or main_game.battle_pets.size() == 0:
|
||||
return false
|
||||
|
||||
# 遍历出战宠物列表,查找匹配的ID
|
||||
# 遍历出战宠物列表,查找匹配的ID(新格式)
|
||||
for battle_pet in main_game.battle_pets:
|
||||
var battle_pet_id = battle_pet.get("基本信息", {}).get("宠物ID", "")
|
||||
var battle_pet_id = battle_pet.get("pet_id", "")
|
||||
if battle_pet_id == pet_id:
|
||||
return true
|
||||
|
||||
@@ -612,9 +590,9 @@ func _is_pet_battling(pet_id: String) -> bool:
|
||||
|
||||
# 添加到出战(新的基于ID的逻辑)
|
||||
func _add_to_battle(pet_id: String):
|
||||
# 检查出战宠物数量限制(目前服务器设置最多1个)
|
||||
if main_game.battle_pets != null and main_game.battle_pets.size() >= 1:
|
||||
Toast.show("最多只能设置1个出战宠物", Color.ORANGE, 3.0, 1.0)
|
||||
# 检查出战宠物数量限制(目前服务器设置最多4个)
|
||||
if main_game.battle_pets != null and main_game.battle_pets.size() >= 4:
|
||||
Toast.show("最多只能设置4个出战宠物", Color.ORANGE, 3.0, 1.0)
|
||||
return
|
||||
|
||||
# 检查是否在巡逻中(出战宠物不能是巡逻宠物)
|
||||
@@ -626,7 +604,7 @@ func _add_to_battle(pet_id: String):
|
||||
if not main_game.is_visiting_mode:
|
||||
# 发送到服务器保存
|
||||
tcp_network_manager_panel.sendSetBattlePet(pet_id, true)
|
||||
var pet_name = current_pet_data.get("基本信息", {}).get("宠物名称", "未知")
|
||||
var pet_name = current_pet_data.get("pet_name", "未知")
|
||||
Toast.show("正在设置 " + pet_name + " 为出战宠物...", Color.YELLOW, 2.0, 1.0)
|
||||
else:
|
||||
Toast.show("访问模式下无法设置出战宠物", Color.ORANGE, 2.0, 1.0)
|
||||
@@ -655,8 +633,7 @@ func _refresh_battle_button():
|
||||
if current_pet_data.is_empty():
|
||||
return
|
||||
|
||||
var basic_info = current_pet_data.get("基本信息", {})
|
||||
var pet_id = basic_info.get("宠物ID", "")
|
||||
var pet_id = current_pet_data.get("pet_id", "")
|
||||
|
||||
if pet_id == "":
|
||||
return
|
||||
|
||||
@@ -247,15 +247,20 @@ func handle_wisdom_tree_operation_response(success: bool, message: String, opera
|
||||
# 根据操作类型显示不同的提示
|
||||
match operation_type:
|
||||
"water":
|
||||
Toast.show("浇水成功!" + message, Color.CYAN)
|
||||
#Toast.show("浇水成功!" + message, Color.CYAN)
|
||||
pass
|
||||
"fertilize":
|
||||
Toast.show("施肥成功!" + message, Color.PURPLE)
|
||||
#Toast.show("施肥成功!" + message, Color.PURPLE)
|
||||
pass
|
||||
"kill_grass":
|
||||
Toast.show("除草成功!" + message, Color.GREEN)
|
||||
#Toast.show("除草成功!" + message, Color.GREEN)
|
||||
pass
|
||||
"kill_bug":
|
||||
Toast.show("杀虫成功!" + message, Color.GREEN)
|
||||
#Toast.show("杀虫成功!" + message, Color.GREEN)
|
||||
pass
|
||||
"play_music":
|
||||
Toast.show("放音乐成功!" + message, Color.MAGENTA)
|
||||
#Toast.show("放音乐成功!" + message, Color.MAGENTA)
|
||||
pass
|
||||
# 放音乐时可能获得随机消息,需要特殊处理
|
||||
if updated_data.has("random_message"):
|
||||
var random_message = updated_data["random_message"]
|
||||
@@ -293,7 +298,7 @@ func handle_wisdom_tree_message_response(success: bool, message: String, updated
|
||||
main_game.money = updated_data["钱币"]
|
||||
main_game._update_ui()
|
||||
|
||||
Toast.show("消息发送成功!", Color.GREEN)
|
||||
#Toast.show("消息发送成功!", Color.GREEN)
|
||||
else:
|
||||
Toast.show(message, Color.RED)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user