extends Panel class_name PetBattlePanel # 宠物对战系统管理器 # 支持PVP、PVE,最多20个宠物同时对战 # 高性能设计,适合移动端 signal battle_started signal battle_ended(winner_team: String, battle_data: Dictionary) signal pet_spawned(pet: NewPetBase) # UI节点引用 @onready var map_background: TextureRect = $MapBackGround @onready var title_label: Label = $Title @onready var team_a_node: Node2D = $TeamA @onready var team_b_node: Node2D = $TeamB @onready var battle_end_panel: Panel = $BattleEndPanel @onready var battle_details_panel: Panel = $PetBattleDetailsPanel @onready var battle_details_text: RichTextLabel = $PetBattleDetailsPanel/BattleDetails @onready var return_farm_button: Button = $BattleEndPanel/ReturnFarmButton @onready var time: Label = $Time #剩余对战时间 @onready var confirm_dialog: ConfirmationDialog = $ConfirmDialog #确认弹窗,每当操作需要确认时出现 # 辅助功能按钮引用 @onready var team_a_heal_button: Button = $PlayerSkillPanel/TeamASkills/TeamAHeal @onready var team_a_rage_button: Button = $PlayerSkillPanel/TeamASkills/TeamARage @onready var team_a_shield_button: Button = $PlayerSkillPanel/TeamASkills/TeamAShield @onready var tcp_network_manager_panel: Panel = $'../TCPNetworkManagerPanel'#客户端通信函数 # 队伍名称 var team_a_name: String = "" var team_b_name: String = "" # 战斗状态 enum BattleState { PREPARING, # 准备阶段 BATTLING, # 战斗中 ENDED # 战斗结束 } var current_battle_state: BattleState = BattleState.PREPARING var battle_time: float = 0.0 var max_battle_time: float = 300.0 # 5分钟最大战斗时间 # 队伍管理 var team_a_pets: Array[NewPetBase] = [] var team_b_pets: Array[NewPetBase] = [] var all_pets: Array[NewPetBase] = [] # 战斗统计 var battle_log: Array[String] = [] var damage_dealt: Dictionary = {} # 记录每个宠物造成的伤害 var damage_taken: Dictionary = {} # 记录每个宠物受到的伤害 var kills: Dictionary = {} # 记录每个宠物的击杀数 # 性能优化 var update_timer: float = 0.0 var update_interval: float = 0.2 # 战斗状态更新间隔(降低频率) var cleanup_timer: float = 0.0 var cleanup_interval: float = 2.0 # 清理死亡宠物和子弹的间隔(降低频率) # 宠物配置系统 var pet_config: PetConfig # 辅助功能冷却系统 var assist_cooldown_time: float = 5.0 # 冷却时间5秒 var heal_cooldown_timer: float = 0.0 var rage_cooldown_timer: float = 0.0 var shield_cooldown_timer: float = 0.0 var current_assist_operation: String = "" # 当前待执行的辅助操作 #========================基础函数====================== func _ready(): # 初始化UI battle_end_panel.visible = false return_farm_button.pressed.connect(_on_return_farm_pressed) # 连接可见性改变信号 visibility_changed.connect(_on_visibility_changed) # 连接确认弹窗信号 confirm_dialog.confirmed.connect(_on_assist_confirmed) confirm_dialog.canceled.connect(_on_assist_canceled) # 初始化宠物配置系统 pet_config = PetConfig.new() # 等待一帧确保PetConfig的_ready函数执行完毕 await get_tree().process_frame # 初始化战斗日志 battle_details_text.text = "[color=green]战斗准备中...[/color]\n" # 美化确认弹窗 setup_confirm_dialog() # 延迟一帧后设置演示数据,确保所有节点都已准备好 await get_tree().process_frame # 可以调用测试函数进行本地测试 #setup_test_battle() func _process(delta): # 更新时间显示(无论什么状态都显示) update_time_display() # # 更新辅助功能冷却计时器 update_assist_cooldowns(delta) if current_battle_state != BattleState.BATTLING: return # 更新战斗时间 battle_time += delta # 检查时间是否到达 var remaining_time = max_battle_time - battle_time if remaining_time <= 0: # 时间到,立即清理所有宠物并结束为平局 clear_all_pets_immediately() end_battle("平局") return # 更新计时器 update_timer += delta cleanup_timer += delta # 定期更新战斗状态 if update_timer >= update_interval: update_battle_state() update_timer = 0.0 # 定期清理 if cleanup_timer >= cleanup_interval: cleanup_dead_objects() cleanup_timer = 0.0 #========================基础函数====================== #=====================本地测试函数=========================== # 本地测试对战函数 - 方便调试各种宠物属性 func setup_test_battle(): # 清理现有战斗 clear_all_pets() # 设置队伍名称 team_a_name = "测试队伍A" team_b_name = "测试队伍B" # 创建测试队伍A的宠物数据(进攻方) var team_a_data = [ {"config_key": "烈焰鸟"}, # 使用配置文件中的烈焰鸟 ] # 创建测试队伍B的宠物数据(防守方) var team_b_data = [ {"config_key": "小蓝虫"}, # 使用配置文件中的小蓝虫 ] # 开始战斗 start_battle(team_a_data, team_b_data) # 等待宠物生成完成 await get_tree().process_frame # 获取生成的宠物进行属性调试 var redman_pet = null # 烈焰鸟 var bluebug_pet = null # 大蓝虫 var smallbug_pet = null # 小蓝虫 var smallblue_pet = null # 小蓝 # 查找特定宠物 for pet in team_a_pets: if pet.pet_type == "烈焰鸟": redman_pet = pet elif pet.pet_type == "大蓝虫": bluebug_pet = pet for pet in team_b_pets: if pet.pet_type == "小蓝虫": smallbug_pet = pet elif pet.pet_type == "小蓝": smallblue_pet = pet # =================== 在这里可以一行代码调试宠物属性 =================== # 示例:开启烈焰鸟的反弹伤害技能 if redman_pet: redman_pet.enable_damage_reflection_skill = true redman_pet.damage_reflection_percentage = 0.8 # 反弹80%伤害 redman_pet.damage_reflection_cooldown = 5.0 # 5秒冷却 print("[测试] 本地测试对战设置完成,可以观察宠物战斗效果") # 添加测试日志 add_battle_log("[color=cyan]本地测试对战开始![/color]") add_battle_log("[color=yellow]队伍A: 烈焰鸟(反弹伤害) + 大蓝虫(召唤增强)[/color]") add_battle_log("[color=yellow]队伍B: 小蓝虫(狂暴模式) + 小蓝(自爆技能)[/color]") #=====================UI显示=========================== #更新时间显示 func update_time_display(): var remaining_time: float if current_battle_state == BattleState.BATTLING: remaining_time = max_battle_time - battle_time else: remaining_time = max_battle_time # 确保时间不为负数 remaining_time = max(0, remaining_time) # 更新时间显示(格式:分:秒) var minutes = int(remaining_time) / 60 var seconds = int(remaining_time) % 60 time.text = "剩余时间: %02d:%02d" % [minutes, seconds] # 根据剩余时间设置颜色 if current_battle_state == BattleState.BATTLING: if remaining_time <= 30: time.modulate = Color.RED elif remaining_time <= 60: time.modulate = Color.ORANGE else: time.modulate = Color.WHITE else: time.modulate = Color.WHITE #显示战斗结果 func show_battle_result(winner: String): battle_end_panel.visible = true var title_label = battle_end_panel.get_node("Title") var contents_label = battle_end_panel.get_node("Contents") # 设置标题 match winner: "attacker": title_label.text = "进攻方获胜!" "defender": title_label.text = "防守方获胜!" _: title_label.text = "平局!" # 生成战斗统计 var stats_text = generate_battle_stats() contents_label.text = stats_text #生成战斗统计信息 func generate_battle_stats() -> String: var stats = "战斗时间: %.1f秒\n\n" % battle_time # MVP统计 var max_damage = 0.0 var mvp_pet = "" for pet_id in damage_dealt: if damage_dealt[pet_id] > max_damage: max_damage = damage_dealt[pet_id] mvp_pet = pet_id if mvp_pet != "": stats += "MVP: %s (造成伤害: %.0f)\n" % [mvp_pet, max_damage] stats += "\n战斗详情:\n" for log_entry in battle_log.slice(-10): # 显示最后10条记录 stats += log_entry + "\n" return stats #添加战斗日志 func add_battle_log(message: String): """添加战斗日志""" battle_log.append(message) # 限制日志数量以优化内存 if battle_log.size() > 50: battle_log = battle_log.slice(-30) # 保留最后30条 # 减少UI更新频率 if battle_log.size() % 5 == 0: # 每5条日志更新一次UI var display_logs = battle_log.slice(-15) # 只显示最后15条 battle_details_text.text = "\n".join(display_logs) #返回农场按钮 func _on_return_farm_pressed(): # 清理战斗场景 clear_all_pets() # 清理子弹 var bullets = get_tree().get_nodes_in_group("bullets") for bullet in bullets: bullet.queue_free() # 隐藏面板 visible = false #获取战斗总结数据 func get_battle_summary() -> Dictionary: return { "battle_time": battle_time, "damage_dealt": damage_dealt, "damage_taken": damage_taken, "kills": kills, "battle_log": battle_log } #直接认输逃跑 func _on_stop_battle_button_pressed() -> void: # 检查战斗是否已经结束 if current_battle_state == BattleState.ENDED: return # 添加逃跑日志 add_battle_log("[color=yellow]玩家选择认输逃跑![/color]") # 立即结束战斗,设置防守方获胜(玩家认输) end_battle("defender") # 清理所有宠物的AI状态并移除宠物 for pet in all_pets: if is_instance_valid(pet): pet.current_state = NewPetBase.PetState.DEAD # 设置为死亡状态 pet.current_target = null # 清除目标 pet.is_alive = false # 设置为死亡 pet.queue_free() # 删除宠物 # 清理所有召唤的仆从小弟 clear_all_minions() # 清空宠物数组 team_a_pets.clear() team_b_pets.clear() all_pets.clear() # 清理子弹 var bullets = get_tree().get_nodes_in_group("bullets") for bullet in bullets: bullet.queue_free() # 面板显示时的处理 func _on_visibility_changed(): if visible: GlobalVariables.isZoomDisabled = true pass else: GlobalVariables.isZoomDisabled = false pass #=====================UI显示=========================== #开始战斗 func start_battle(team_a_data: Array, team_b_data: Array): current_battle_state = BattleState.PREPARING battle_time = 0.0 battle_log.clear() damage_dealt.clear() damage_taken.clear() kills.clear() # 清理现有宠物 clear_all_pets() # 生成队伍A的宠物(进攻方) spawn_team(team_a_data, "attacker", team_a_node) # 生成队伍B的宠物(防守方) spawn_team(team_b_data, "defender", team_b_node) # 开始战斗 current_battle_state = BattleState.BATTLING battle_started.emit() add_battle_log("[color=yellow]战斗开始![/color]") #生成队伍宠物 func spawn_team(team_data: Array, team_name: String, team_node: Node2D): var positions = get_team_positions(team_node) for i in range(min(team_data.size(), positions.size())): var pet_info = team_data[i] var pet = spawn_pet(pet_info, team_name, positions[i]) if pet: if team_name == "attacker": team_a_pets.append(pet) else: team_b_pets.append(pet) all_pets.append(pet) #获取队伍位置点 func get_team_positions(team_node: Node2D) -> Array[Vector2]: var positions: Array[Vector2] = [] for child in team_node.get_children(): if child is Marker2D: positions.append(team_node.global_position + child.position) return positions #生成单个宠物 func spawn_pet(pet_info: Dictionary, team: String, pos: Vector2) -> NewPetBase: var pet_scene = preload("res://Scene/NewPet/NewPetBase.tscn") var pet = pet_scene.instantiate() # 添加到场景 add_child(pet) pet.global_position = pos pet.pet_team = team # 处理服务器返回的完整宠物数据或配置键值 var config_key = pet_info.get("config_key", "") var pet_type = pet_info.get("pet_type", "") var config_data: Dictionary if config_key != "" and pet_config: # 使用指定的配置键值 config_data = pet_config.get_pet_config(config_key) apply_pet_config(pet, config_data) apply_level_scaling(pet) elif pet_type != "" and pet_config and pet_config.has_pet_config(pet_type): # 使用宠物类型作为配置键值 config_data = pet_config.get_pet_config(pet_type) apply_pet_config(pet, config_data) # 覆盖配置中的数据为服务器返回的实际数据 apply_server_pet_data(pet, pet_info) apply_level_scaling(pet) else: # 直接使用服务器返回的宠物数据 apply_server_pet_data(pet, pet_info) apply_level_scaling(pet) # 连接信号 pet.pet_died.connect(_on_pet_died) pet.pet_attacked.connect(_on_pet_attacked) pet.pet_skill_used.connect(_on_pet_skill_used) # 添加到宠物组 pet.add_to_group("pets") # 初始化统计数据 damage_dealt[pet.pet_id] = 0.0 damage_taken[pet.pet_id] = 0.0 kills[pet.pet_id] = 0 pet_spawned.emit(pet) return pet #应用服务器返回的宠物数据 func apply_server_pet_data(pet: NewPetBase, pet_data: Dictionary): if pet_data.is_empty(): return # 基本属性 if pet_data.has("pet_name"): pet.pet_name = pet_data["pet_name"] if pet_data.has("pet_id"): pet.pet_id = pet_data["pet_id"] if pet_data.has("pet_type"): pet.pet_type = pet_data["pet_type"] if pet_data.has("pet_level"): pet.pet_level = pet_data["pet_level"] # 生命与防御 if pet_data.has("max_health"): pet.max_health = pet_data["max_health"] # 优先使用服务器返回的当前生命值,否则使用最大生命值 if pet_data.has("pet_current_health"): pet.current_health = pet_data["pet_current_health"] else: pet.current_health = pet.max_health if pet_data.has("enable_health_regen"): pet.enable_health_regen = pet_data["enable_health_regen"] if pet_data.has("health_regen"): pet.health_regen = pet_data["health_regen"] if pet_data.has("enable_shield_regen"): pet.enable_shield_regen = pet_data["enable_shield_regen"] if pet_data.has("max_shield"): pet.max_shield = pet_data["max_shield"] pet.current_shield = pet.max_shield if pet_data.has("shield_regen"): pet.shield_regen = pet_data["shield_regen"] if pet_data.has("max_armor"): pet.max_armor = pet_data["max_armor"] pet.current_armor = pet.max_armor # 攻击属性 if pet_data.has("base_attack_damage"): pet.base_attack_damage = pet_data["base_attack_damage"] if pet_data.has("crit_rate"): pet.crit_rate = pet_data["crit_rate"] if pet_data.has("crit_damage"): pet.crit_damage = pet_data["crit_damage"] if pet_data.has("armor_penetration"): pet.armor_penetration = pet_data["armor_penetration"] # 技能配置 if pet_data.has("enable_multi_projectile_skill"): pet.enable_multi_projectile_skill = pet_data["enable_multi_projectile_skill"] if pet_data.has("multi_projectile_delay"): pet.multi_projectile_delay = pet_data["multi_projectile_delay"] if pet_data.has("enable_berserker_skill"): pet.enable_berserker_skill = pet_data["enable_berserker_skill"] if pet_data.has("berserker_bonus"): pet.berserker_bonus = pet_data["berserker_bonus"] if pet_data.has("berserker_duration"): pet.berserker_duration = pet_data["berserker_duration"] if pet_data.has("enable_self_destruct_skill"): pet.enable_self_destruct_skill = pet_data["enable_self_destruct_skill"] if pet_data.has("self_destruct_damage"): pet.self_destruct_damage = pet_data["self_destruct_damage"] if pet_data.has("enable_summon_pet_skill"): pet.enable_summon_pet_skill = pet_data["enable_summon_pet_skill"] if pet_data.has("summon_count"): pet.summon_count = pet_data["summon_count"] if pet_data.has("summon_scale"): pet.summon_scale = pet_data["summon_scale"] if pet_data.has("enable_death_respawn_skill"): pet.enable_death_respawn_skill = pet_data["enable_death_respawn_skill"] if pet_data.has("respawn_health_percentage"): pet.respawn_health_percentage = pet_data["respawn_health_percentage"] # 移动属性 if pet_data.has("move_speed"): pet.move_speed = pet_data["move_speed"] if pet_data.has("dodge_rate"): pet.dodge_rate = pet_data["dodge_rate"] # 元素属性 if pet_data.has("element_type"): if typeof(pet_data["element_type"]) == TYPE_STRING: pet.element_type = string_to_element_type(pet_data["element_type"]) else: pet.element_type = pet_data["element_type"] if pet_data.has("element_damage_bonus"): pet.element_damage_bonus = pet_data["element_damage_bonus"] # 武器系统 if pet_data.has("left_weapon") and pet_data["left_weapon"] != "": pet.equip_weapon(pet_data["left_weapon"], "left") if pet_data.has("right_weapon") and pet_data["right_weapon"] != "": pet.equip_weapon(pet_data["right_weapon"], "right") # 宠物外观配置 if pet_data.has("pet_image"): pet.pet_image_path = pet_data["pet_image"] apply_pet_image(pet, pet_data["pet_image"]) # 打印调试信息 print("[PetBattlePanel] 应用服务器宠物数据: %s (等级%d)" % [pet.pet_name, pet.pet_level]) #字符串转元素类型枚举 func string_to_element_type(element_string: String) -> NewPetBase.ElementType: match element_string.to_upper(): "FIRE": return NewPetBase.ElementType.FIRE "WATER": return NewPetBase.ElementType.WATER "EARTH": return NewPetBase.ElementType.EARTH "METAL": return NewPetBase.ElementType.METAL "WOOD": return NewPetBase.ElementType.WOOD "THUNDER": return NewPetBase.ElementType.THUNDER _: return NewPetBase.ElementType.NONE #将配置应用到宠物上 func apply_pet_config(pet: NewPetBase, config: Dictionary): if not config.is_empty(): # 基本属性 if config.has("pet_name"): pet.pet_name = config["pet_name"] if config.has("pet_id"): pet.pet_id = config["pet_id"] if config.has("pet_type"): pet.pet_type = config["pet_type"] if config.has("pet_level"): pet.pet_level = config["pet_level"] # 生命与防御 if config.has("max_health"): pet.max_health = config["max_health"] pet.current_health = pet.max_health if config.has("enable_health_regen"): pet.enable_health_regen = config["enable_health_regen"] if config.has("health_regen"): pet.health_regen = config["health_regen"] if config.has("enable_shield_regen"): pet.enable_shield_regen = config["enable_shield_regen"] if config.has("max_shield"): pet.max_shield = config["max_shield"] pet.current_shield = pet.max_shield if config.has("shield_regen"): pet.shield_regen = config["shield_regen"] if config.has("max_armor"): pet.max_armor = config["max_armor"] pet.current_armor = pet.max_armor # 攻击属性 if config.has("base_attack_damage"): pet.base_attack_damage = config["base_attack_damage"] if config.has("crit_rate"): pet.crit_rate = config["crit_rate"] if config.has("crit_damage"): pet.crit_damage = config["crit_damage"] if config.has("armor_penetration"): pet.armor_penetration = config["armor_penetration"] # 技能配置 if config.has("enable_multi_projectile_skill"): pet.enable_multi_projectile_skill = config["enable_multi_projectile_skill"] if config.has("multi_projectile_delay"): pet.multi_projectile_delay = config["multi_projectile_delay"] if config.has("enable_berserker_skill"): pet.enable_berserker_skill = config["enable_berserker_skill"] if config.has("berserker_bonus"): pet.berserker_bonus = config["berserker_bonus"] if config.has("berserker_duration"): pet.berserker_duration = config["berserker_duration"] if config.has("enable_self_destruct_skill"): pet.enable_self_destruct_skill = config["enable_self_destruct_skill"] if config.has("self_destruct_damage"): pet.self_destruct_damage = config["self_destruct_damage"] if config.has("enable_summon_pet_skill"): pet.enable_summon_pet_skill = config["enable_summon_pet_skill"] if config.has("summon_count"): pet.summon_count = config["summon_count"] if config.has("summon_scale"): pet.summon_scale = config["summon_scale"] if config.has("enable_death_respawn_skill"): pet.enable_death_respawn_skill = config["enable_death_respawn_skill"] if config.has("respawn_health_percentage"): pet.respawn_health_percentage = config["respawn_health_percentage"] # 移动属性 if config.has("move_speed"): pet.move_speed = config["move_speed"] if config.has("dodge_rate"): pet.dodge_rate = config["dodge_rate"] # 元素属性 if config.has("element_type"): pet.element_type = config["element_type"] if config.has("element_damage_bonus"): pet.element_damage_bonus = config["element_damage_bonus"] # 武器系统 if config.has("left_weapon") and config["left_weapon"] != "": pet.equip_weapon(config["left_weapon"], "left") if config.has("right_weapon") and config["right_weapon"] != "": pet.equip_weapon(config["right_weapon"], "right") # 宠物外观配置 if config.has("pet_image"): pet.pet_image_path = config["pet_image"] # 保存图片路径 apply_pet_image(pet, config["pet_image"]) #应用宠物外观图片 func apply_pet_image(pet: NewPetBase, image_path: String): if image_path == "" or not ResourceLoader.exists(image_path): return # 加载新的宠物场景 var new_pet_scene = load(image_path) if not new_pet_scene: return # 实例化新场景以获取图片组件 var temp_instance = new_pet_scene.instantiate() # 根节点本身就是PetImage var new_pet_image = temp_instance var new_left_tool = temp_instance.get_node_or_null("LeftToolImage") var new_right_tool = temp_instance.get_node_or_null("RightToolImage") if new_pet_image and new_pet_image is AnimatedSprite2D: # 复制动画帧到现有宠物 if new_pet_image.sprite_frames: pet.pet_image.sprite_frames = new_pet_image.sprite_frames pet.pet_image.animation = new_pet_image.animation pet.pet_image.scale = new_pet_image.scale # 确保动画播放 pet.pet_image.play() # 复制工具图片 if new_left_tool and pet.left_tool_image: pet.left_tool_image.texture = new_left_tool.texture pet.left_tool_image.position = new_left_tool.position pet.left_tool_image.flip_h = new_left_tool.flip_h pet.left_tool_image.z_index = new_left_tool.z_index pet.left_tool_image.visible = true if new_right_tool and pet.right_tool_image: pet.right_tool_image.texture = new_right_tool.texture pet.right_tool_image.position = new_right_tool.position pet.right_tool_image.flip_h = new_right_tool.flip_h pet.right_tool_image.show_behind_parent = new_right_tool.show_behind_parent pet.right_tool_image.visible = true # 清理临时实例 temp_instance.queue_free() # 重新更新武器图标(因为外观应用可能覆盖了武器图标) if pet.weapon_system != null: pet.update_weapon_icons() # 每5级特殊效果配置字典 var level_bonus_config = { 5: {"crit_rate": 0.05, "armor_penetration": 10.0, "dodge_rate": 0.05}, 10: {"crit_rate": 0.05, "armor_penetration": 10.0, "dodge_rate": 0.05, "move_speed": 20.0}, 15: {"crit_rate": 0.05, "armor_penetration": 15.0, "dodge_rate": 0.05, "crit_damage": 0.2}, 20: {"crit_rate": 0.05, "armor_penetration": 15.0, "dodge_rate": 0.05, "health_regen": 2.0, "shield_regen": 2.0}, 25: {"crit_rate": 0.05, "armor_penetration": 20.0, "dodge_rate": 0.05, "element_damage_bonus": 30.0}, 30: {"crit_rate": 0.05, "armor_penetration": 20.0, "dodge_rate": 0.05, "knockback_force": 100.0}, 35: {"crit_rate": 0.05, "armor_penetration": 25.0, "dodge_rate": 0.05, "attack_range": 20.0}, 40: {"crit_rate": 0.05, "armor_penetration": 25.0, "dodge_rate": 0.05, "crit_damage": 0.3}, 45: {"crit_rate": 0.05, "armor_penetration": 30.0, "dodge_rate": 0.05, "move_speed": 30.0}, 50: {"crit_rate": 0.05, "armor_penetration": 30.0 , "dodge_rate": 0.05, "element_damage_bonus": 50.0, "health_regen": 3.0} } #应用等级缩放 func apply_level_scaling(pet: NewPetBase): # 每级+2基本属性 var level_bonus = (pet.pet_level - 1) * 2.0 # 基本属性增长 pet.max_health += level_bonus # 最大生命值 pet.current_health = pet.max_health pet.base_attack_damage += level_bonus # 基础攻击伤害 pet.max_armor += level_bonus # 最大护甲值 pet.current_armor = pet.max_armor pet.max_shield += level_bonus # 最大护盾值 pet.current_shield = pet.max_shield # 应用每5级的特殊效果 for level_threshold in level_bonus_config.keys(): if pet.pet_level >= level_threshold: var bonuses = level_bonus_config[level_threshold] for attribute in bonuses.keys(): var bonus_value = bonuses[attribute] match attribute: "crit_rate": pet.crit_rate = min(0.8, pet.crit_rate + bonus_value) # 最大80%暴击率 "armor_penetration": pet.armor_penetration += bonus_value "attack_speed": pet.attack_speed += bonus_value "dodge_rate": pet.dodge_rate = min(0.5, pet.dodge_rate + bonus_value) # 最大50%闪避率 "move_speed": pet.move_speed += bonus_value "crit_damage": pet.crit_damage += bonus_value "health_regen": pet.health_regen += bonus_value "shield_regen": pet.shield_regen += bonus_value "element_damage_bonus": pet.element_damage_bonus += bonus_value "knockback_force": pet.knockback_force += bonus_value "attack_range": pet.attack_range += bonus_value #更新战斗状态 func update_battle_state(): # 先清理无效的宠物引用 cleanup_invalid_pet_references() # 检查是否有队伍全灭 var team_a_alive = team_a_pets.filter(func(pet): return is_instance_valid(pet) and pet.is_alive).size() var team_b_alive = team_b_pets.filter(func(pet): return is_instance_valid(pet) and pet.is_alive).size() if team_a_alive == 0 and team_b_alive == 0: end_battle("平局") elif team_a_alive == 0: end_battle("defender") elif team_b_alive == 0: end_battle("attacker") #=================即时清理防止游戏卡死===================== #清理无效的宠物引用 func cleanup_invalid_pet_references(): # 清理all_pets数组中的无效引用 var valid_all_pets: Array[NewPetBase] = [] for pet in all_pets: if is_instance_valid(pet): valid_all_pets.append(pet) all_pets = valid_all_pets # 清理team_a_pets数组中的无效引用 var valid_team_a_pets: Array[NewPetBase] = [] for pet in team_a_pets: if is_instance_valid(pet): valid_team_a_pets.append(pet) team_a_pets = valid_team_a_pets # 清理team_b_pets数组中的无效引用 var valid_team_b_pets: Array[NewPetBase] = [] for pet in team_b_pets: if is_instance_valid(pet): valid_team_b_pets.append(pet) team_b_pets = valid_team_b_pets #清理死亡对象以优化性能 func cleanup_dead_objects(): # 更严格的死亡宠物清理逻辑 var dead_pets = [] for pet in all_pets: # 检查宠物是否真正死亡(防止重生技能导致的状态不一致) if not is_instance_valid(pet): # 无效的宠物对象,直接标记清理 dead_pets.append(pet) elif not pet.is_alive and pet.current_health <= 0: # 确保宠物真正死亡:生命值为0且is_alive为false # 额外检查:如果有重生技能但重生次数已用完 if pet.enable_death_respawn_skill and pet.current_respawn_count < pet.max_respawn_count: # 还有重生机会,不清理 continue else: # 确认死亡,标记清理 pet.current_state = NewPetBase.PetState.DEAD dead_pets.append(pet) # 清理确认死亡的宠物 for pet in dead_pets: if is_instance_valid(pet): # 确保从所有数组中移除 all_pets.erase(pet) team_a_pets.erase(pet) team_b_pets.erase(pet) # 从场景中移除 if pet.get_parent(): pet.get_parent().remove_child(pet) pet.queue_free() else: # 无效对象,直接从数组中移除 all_pets.erase(pet) team_a_pets.erase(pet) team_b_pets.erase(pet) # 清理无效子弹 var bullets = get_tree().get_nodes_in_group("bullets") for bullet in bullets: if not is_instance_valid(bullet) or (bullet.has_method("is_active") and not bullet.is_active): bullet.queue_free() #结束战斗 func end_battle(winner: String): if current_battle_state == BattleState.ENDED: return current_battle_state = BattleState.ENDED # 清理所有宠物的AI状态并移除宠物 for pet in all_pets: if is_instance_valid(pet): pet.current_state = NewPetBase.PetState.DEAD # 设置为死亡状态 pet.current_target = null # 清除目标 pet.is_alive = false # 设置为死亡 pet.queue_free() # 删除宠物 # 清理所有召唤的仆从小弟 clear_all_minions() # 清空宠物数组 team_a_pets.clear() team_b_pets.clear() all_pets.clear() # 清理子弹 var bullets = get_tree().get_nodes_in_group("bullets") for bullet in bullets: bullet.queue_free() # 显示战斗结果 show_battle_result(winner) # 生成战斗数据 var battle_data = { "attacker_pets": [], "defender_pets": [], "battle_duration": battle_time, "damage_dealt": damage_dealt, "damage_taken": damage_taken, "kills": kills, "battle_log": battle_log } # 发射战斗结束信号 battle_ended.emit(winner, battle_data) add_battle_log("[color=red]战斗结束!获胜方: %s[/color]" % winner) for child in get_children(): if child is Area2D: remove_child(child) child.queue_free() #清理所有宠物 func clear_all_pets(): for pet in all_pets: if is_instance_valid(pet): pet.queue_free() # 清理所有召唤的仆从小弟 clear_all_minions() team_a_pets.clear() team_b_pets.clear() all_pets.clear() #清理所有召唤的仆从小弟 func clear_all_minions(): # 获取所有pets组中的节点 var all_pets_in_group = get_tree().get_nodes_in_group("pets") var minions_cleared = 0 for pet in all_pets_in_group: if is_instance_valid(pet) and pet is NewPetBase: # 立即设置为死亡状态 pet.is_alive = false pet.current_state = NewPetBase.PetState.DEAD pet.current_target = null # 从场景中移除 if pet.get_parent(): pet.get_parent().remove_child(pet) pet.queue_free() minions_cleared += 1 if minions_cleared > 0: add_battle_log("[color=purple]清理了 %d 个召唤仆从[/color]" % minions_cleared) #立即清理所有宠物 func clear_all_pets_immediately(): for pet in all_pets: if is_instance_valid(pet): # 立即设置为死亡状态 pet.is_alive = false pet.current_state = NewPetBase.PetState.DEAD pet.current_target = null # 立即从场景中移除 pet.get_parent().remove_child(pet) pet.queue_free() # 清理所有召唤的仆从小弟 clear_all_minions() # 清理所有子弹 var bullets = get_tree().get_nodes_in_group("bullets") for bullet in bullets: if is_instance_valid(bullet): bullet.queue_free() # 清空宠物数组 team_a_pets.clear() team_b_pets.clear() all_pets.clear() add_battle_log("[color=red]时间到!所有宠物已被清理,战斗结束![/color]") #=================即时清理防止游戏卡死===================== #宠物死亡事件 func _on_pet_died(pet: NewPetBase): # 简化死亡处理,减少不必要的计算 if battle_log.size() < 30: # 限制死亡日志数量 add_battle_log("[color=red]%s 死亡[/color]" % pet.pet_name) #宠物攻击事件 func _on_pet_attacked(attacker: NewPetBase, target: NewPetBase, damage: float): # 简化统计更新 damage_dealt[attacker.pet_id] = damage_dealt.get(attacker.pet_id, 0.0) + damage damage_taken[target.pet_id] = damage_taken.get(target.pet_id, 0.0) + damage # 大幅减少攻击日志,只记录关键事件 if damage >= 100: # 只记录高伤害攻击 add_battle_log("[color=orange]%s->%s %.0f[/color]" % [attacker.pet_name, target.pet_name, damage]) #宠物技能使用事件 func _on_pet_skill_used(pet: NewPetBase, skill_name: String): # 减少技能日志,只记录重要技能 if skill_name in ["狂暴模式", "自爆", "召唤小弟", "死亡重生"]: add_battle_log("[color=cyan]%s:%s[/color]" % [pet.pet_name, skill_name]) #================偷菜对战设置=========================== # 设置偷菜对战 func setup_steal_battle(attacker_pets: Array, defender_pets: Array, attacker_name: String, defender_name: String): print("[PetBattlePanel] 设置偷菜对战: 攻击者=%s, 防守者=%s" % [attacker_name, defender_name]) print("[PetBattlePanel] 攻击方宠物数量: %d, 防守方宠物数量: %d" % [attacker_pets.size(), defender_pets.size()]) # 检查双方是否都有宠物 if attacker_pets.is_empty() or defender_pets.is_empty(): print("[PetBattlePanel] 错误: 双方必须至少有一个宠物才能参战") return false # 重置战斗状态和UI current_battle_state = BattleState.PREPARING battle_time = 0.0 battle_log.clear() damage_dealt.clear() damage_taken.clear() kills.clear() # 隐藏战斗结束面板,显示战斗细节面板 battle_end_panel.visible = false battle_details_panel.visible = true # 重置战斗日志显示 battle_details_text.text = "[color=green]战斗准备中...[/color]\n" # 限制出战宠物数量最多4个 var limited_attacker_pets = attacker_pets.slice(0, min(4, attacker_pets.size())) var limited_defender_pets = defender_pets.slice(0, min(4, defender_pets.size())) # 显示对战面板 show() # 清理现有宠物 clear_all_pets() # 设置队伍信息 team_a_name = attacker_name + "(攻击方)" team_b_name = defender_name + "(防守方)" # 获取队伍位置点 var team_a_positions = get_team_positions(team_a_node) var team_b_positions = get_team_positions(team_b_node) # 生成攻击方宠物(teamA) for i in range(limited_attacker_pets.size()): var pet_data = limited_attacker_pets[i] var position = team_a_positions[i] if i < team_a_positions.size() else team_a_positions[0] var pet = spawn_pet(pet_data, "attacker", position) if pet: team_a_pets.append(pet) all_pets.append(pet) # 生成防守方宠物(teamB) for i in range(limited_defender_pets.size()): var pet_data = limited_defender_pets[i] var position = team_b_positions[i] if i < team_b_positions.size() else team_b_positions[0] var pet = spawn_pet(pet_data, "defender", position) if pet: team_b_pets.append(pet) all_pets.append(pet) # 添加战斗日志 add_battle_log("[color=yellow]偷菜对战开始![/color]") add_battle_log("[color=cyan]%s VS %s[/color]" % [team_a_name, team_b_name]) # 开始战斗 start_battle(limited_attacker_pets, limited_defender_pets) return true #================偷菜对战设置=========================== #================场外辅助=========================== #美化确认弹窗 func setup_confirm_dialog(): confirm_dialog.title = "辅助功能确认" confirm_dialog.ok_button_text = "确认使用" confirm_dialog.cancel_button_text = "取消" confirm_dialog.unresizable = false confirm_dialog.size = Vector2i(450, 200) # 创建并应用主题样式 var theme = Theme.new() var style_box = StyleBoxFlat.new() style_box.bg_color = Color(0.2, 0.3, 0.4, 0.95) style_box.border_width_left = 3 style_box.border_width_right = 3 style_box.border_width_top = 3 style_box.border_width_bottom = 3 style_box.border_color = Color(0.4, 0.6, 0.8, 1.0) style_box.corner_radius_top_left = 10 style_box.corner_radius_top_right = 10 style_box.corner_radius_bottom_left = 10 style_box.corner_radius_bottom_right = 10 theme.set_stylebox("panel", "AcceptDialog", style_box) confirm_dialog.theme = theme #更新辅助功能冷却计时器 func update_assist_cooldowns(delta: float): # 更新冷却计时器 if heal_cooldown_timer > 0: heal_cooldown_timer -= delta if heal_cooldown_timer <= 0: team_a_heal_button.disabled = false team_a_heal_button.text = "团队治疗" else: team_a_heal_button.text = "治疗冷却 %.1fs" % heal_cooldown_timer if rage_cooldown_timer > 0: rage_cooldown_timer -= delta if rage_cooldown_timer <= 0: team_a_rage_button.disabled = false team_a_rage_button.text = "团队狂暴" else: team_a_rage_button.text = "狂暴冷却 %.1fs" % rage_cooldown_timer if shield_cooldown_timer > 0: shield_cooldown_timer -= delta if shield_cooldown_timer <= 0: team_a_shield_button.disabled = false team_a_shield_button.text = "团队护盾" else: team_a_shield_button.text = "护盾冷却 %.1fs" % shield_cooldown_timer #显示辅助功能确认弹窗 func show_assist_confirm(operation_type: String, description: String, effect: String): current_assist_operation = operation_type # 设置弹窗内容(纯文本格式) var dialog_text = "%s\n\n" % description dialog_text += "效果:%s\n\n" % effect dialog_text += "注意:使用后该技能将进入5秒冷却时间\n\n" dialog_text += "确定要使用这个辅助功能吗?" confirm_dialog.dialog_text = dialog_text confirm_dialog.popup_centered() #确认使用辅助功能 func _on_assist_confirmed(): match current_assist_operation: "heal": # 团队治疗 execute_team_heal() "rage": # 团队狂暴 execute_team_rage() "shield": # 团队护盾 execute_team_shield() current_assist_operation = "" #取消使用辅助功能 func _on_assist_canceled(): current_assist_operation = "" #执行团队治疗 func execute_team_heal(): var healed_count = 0 # 只对teamA(attacker队伍)的宠物生效 for pet in all_pets: if pet.is_alive and pet.pet_team == "attacker": var heal_amount = pet.max_health * 0.3 # 恢复30%最大生命值 pet.current_health = min(pet.max_health, pet.current_health + heal_amount) pet.update_health_bar() healed_count += 1 # 添加治疗特效(绿色光芒)- 使用弱引用避免访问已销毁的对象 if pet.pet_image: var pet_ref = weakref(pet) var tween = create_tween() tween.tween_method(func(color): var pet_obj = pet_ref.get_ref() if pet_obj != null and is_instance_valid(pet_obj) and pet_obj.pet_image: pet_obj.pet_image.modulate = color, Color.WHITE, Color.GREEN, 0.3) tween.tween_method(func(color): var pet_obj = pet_ref.get_ref() if pet_obj != null and is_instance_valid(pet_obj) and pet_obj.pet_image: pet_obj.pet_image.modulate = color, Color.GREEN, Color.WHITE, 0.3) # 启动冷却 heal_cooldown_timer = assist_cooldown_time team_a_heal_button.disabled = true add_battle_log("[color=green]🌿 使用团队治疗!为 %d 只teamA宠物恢复了30%%生命值[/color]" % healed_count) #执行团队狂暴 func execute_team_rage(): var raged_count = 0 # 只对teamA(attacker队伍)的宠物生效 for pet in all_pets: if pet.is_alive and pet.pet_team == "attacker": # 激活狂暴模式5秒 pet.is_berserker = true raged_count += 1 # 添加狂暴特效(红色光芒) if pet.pet_image: pet.pet_image.modulate = Color.RED # 5秒后自动取消狂暴(使用弱引用避免访问已销毁的对象) var pet_ref = weakref(pet) get_tree().create_timer(5.0).timeout.connect(func(): var pet_obj = pet_ref.get_ref() if pet_obj != null and is_instance_valid(pet_obj) and pet_obj.is_alive: pet_obj.is_berserker = false if pet_obj.pet_image: pet_obj.pet_image.modulate = Color.WHITE ) # 启动冷却 rage_cooldown_timer = assist_cooldown_time team_a_rage_button.disabled = true add_battle_log("[color=red]🔥 使用团队狂暴!%d 只teamA宠物进入狂暴状态5秒[/color]" % raged_count) #执行团队护盾 func execute_team_shield(): var shielded_count = 0 # 只对teamA(attacker队伍)的宠物生效 for pet in all_pets: if pet.is_alive and pet.pet_team == "attacker": # 增加100点护盾(允许超过最大值) pet.current_shield += 10000 # 临时提高最大护盾值以显示正确的进度条 if pet.current_shield > pet.max_shield: pet.max_shield = pet.current_shield pet.update_shield_bar() shielded_count += 1 # 添加护盾特效(蓝色光芒)- 使用弱引用避免访问已销毁的对象 if pet.pet_image: var pet_ref = weakref(pet) var tween = create_tween() tween.tween_method(func(color): var pet_obj = pet_ref.get_ref() if pet_obj != null and is_instance_valid(pet_obj) and pet_obj.pet_image: pet_obj.pet_image.modulate = color, Color.WHITE, Color.BLUE, 0.3) tween.tween_method(func(color): var pet_obj = pet_ref.get_ref() if pet_obj != null and is_instance_valid(pet_obj) and pet_obj.pet_image: pet_obj.pet_image.modulate = color, Color.BLUE, Color.WHITE, 0.3) # 启动冷却 shield_cooldown_timer = assist_cooldown_time team_a_shield_button.disabled = true add_battle_log("[color=blue]🛡️ 使用团队护盾!为 %d 只teamA宠物增加了100点护甲[/color]" % shielded_count) #团队治疗按钮(直接恢复30%血量) func _on_team_a_heal_pressed() -> void: if heal_cooldown_timer > 0: return show_assist_confirm("heal", "团队治疗", "为所有存活的己方宠物恢复30%最大生命值") #团队狂暴按钮(直接进入五秒狂暴模式,与狂暴技能不冲突) func _on_team_a_rage_pressed() -> void: if rage_cooldown_timer > 0: return show_assist_confirm("rage", "团队狂暴", "让所有存活的己方宠物进入狂暴状态5秒,攻击力翻倍") #团队护盾按钮(直接加100护盾) func _on_team_a_shield_pressed() -> void: if shield_cooldown_timer > 0: return show_assist_confirm("shield", "团队护盾", "为所有存活的己方宠物增加100点护甲值") #================场外辅助===========================