1279 lines
41 KiB
GDScript
1279 lines
41 KiB
GDScript
extends Area2D
|
||
class_name NewPetBase
|
||
|
||
#============================信号管理==============================
|
||
signal pet_died(pet: NewPetBase)
|
||
signal pet_attacked(attacker: NewPetBase, target: NewPetBase, damage: float)
|
||
signal pet_skill_used(pet: NewPetBase, skill_name: String)
|
||
#============================信号管理==============================
|
||
|
||
|
||
#============================节点引用===============================
|
||
# 节点引用
|
||
@onready var pet_image: AnimatedSprite2D = $PetImage
|
||
@onready var left_tool_image: Sprite2D = $PetImage/LeftToolImage
|
||
@onready var right_tool_image: Sprite2D = $PetImage/RightToolImage
|
||
@onready var volume_collision: CollisionShape2D = $VolumeCollision
|
||
|
||
# UI节点引用
|
||
@onready var pet_inform_vbox: VBoxContainer = $PetInformVBox
|
||
@onready var pet_name_rich_text: RichTextLabel = $PetInformVBox/PetNameRichText
|
||
@onready var armor_bar: ProgressBar = $PetInformVBox/ArmorBar
|
||
@onready var armor_label: Label = $PetInformVBox/ArmorBar/ArmorLabel
|
||
@onready var shield_bar: ProgressBar = $PetInformVBox/ShieldBar
|
||
@onready var shield_label: Label = $PetInformVBox/ShieldBar/ShieldLabel
|
||
@onready var health_bar: ProgressBar = $PetInformVBox/HealthBar
|
||
@onready var health_label: Label = $PetInformVBox/HealthBar/HealthLabel
|
||
#============================节点引用===============================
|
||
|
||
|
||
#============================枚举===============================
|
||
# 攻击类型枚举
|
||
enum AttackType {
|
||
MELEE # 近战攻击
|
||
}
|
||
|
||
enum ElementType {
|
||
NONE, METAL, WOOD, WATER, FIRE, EARTH, THUNDER
|
||
}
|
||
|
||
enum PetState {
|
||
IDLE, # 待机
|
||
MOVING, # 移动
|
||
ATTACKING, # 攻击中
|
||
SKILL_CASTING, # 释放技能
|
||
PATROLLING, # 巡逻
|
||
DEAD # 死亡
|
||
}
|
||
#============================枚举===============================
|
||
|
||
|
||
#============================宠物所有属性===============================
|
||
# 基本属性
|
||
var pet_name: String = "萌芽小绿" # 宠物名称
|
||
var pet_team: String = "attacker" # 所属队伍(attacker进攻方 或 defender防守方)
|
||
var pet_id: String = "0001" # 宠物唯一编号
|
||
var pet_type: String = "小绿" # 宠物种类
|
||
var pet_level: int = 50 # 宠物等级
|
||
var pet_image_path: String = "" # 宠物图片路径
|
||
|
||
# 生命与防御
|
||
var max_health: float = 200.0 # 最大生命值
|
||
var current_health: float = 200.0 # 当前生命值
|
||
var enable_health_regen: bool = true # 是否开启生命恢复
|
||
var health_regen: float = 1.0 # 每秒生命恢复大小
|
||
var enable_shield_regen: bool = true # 是否开启护盾恢复
|
||
var max_shield: float = 100.0 # 最大护盾值
|
||
var current_shield: float = 100.0 # 当前护盾值
|
||
var shield_regen: float = 1.0 # 每秒护盾恢复大小
|
||
var max_armor: float = 100.0 # 最大护甲值
|
||
var current_armor: float = 100.0 # 当前护甲值
|
||
|
||
# 攻击属性
|
||
var attack_type: AttackType = AttackType.MELEE # 攻击类型(仅近战)
|
||
var base_attack_damage: float = 25.0 # 基础攻击力
|
||
var attack_range: float = 100.0 # 攻击范围(近战或远程都适用)
|
||
var attack_speed: float = 1.0 # 每秒攻击次数(攻速)
|
||
var crit_rate: float = 0.1 # 暴击几率(0~1)
|
||
var crit_damage: float = 1.5 # 暴击伤害倍率(1.5 = 150%伤害)
|
||
var armor_penetration: float = 0.0 # 护甲穿透值(无视对方部分护甲)
|
||
|
||
# 技能-多发射击
|
||
var enable_multi_projectile_skill: bool = false
|
||
var projectile_speed: float = 300.0 # 投射物飞行速度
|
||
var multi_projectile_count: int = 0 # 多发射击触发标记(0=未触发,1=已触发)
|
||
var multi_projectile_delay: float = 2 # 多发射击延迟时间(秒)
|
||
var multi_projectile_spread: float = 10.0 # 多发射击角度范围(度)
|
||
var spawn_time: float = 0.0 # 宠物生成时间
|
||
|
||
# 技能-狂暴模式
|
||
var enable_berserker_skill: bool = false
|
||
var berserker_threshold: float = 0.3 # 狂暴触发阈值(生命值百分比)
|
||
var berserker_bonus: float = 1.5 # 狂暴伤害加成
|
||
var berserker_duration: float = 5.0 # 狂暴持续时间(秒)
|
||
var berserker_triggered: bool = false # 是否已触发过狂暴(防止重复触发)
|
||
var is_berserker: bool = false # 是否处于狂暴状态
|
||
var berserker_end_time: float = 0.0 # 狂暴结束时间
|
||
|
||
#技能-死亡自爆
|
||
var enable_self_destruct_skill: bool = false
|
||
var self_destruct_damage: float = 50.0 # 自爆伤害值
|
||
|
||
#技能-召唤小弟
|
||
var enable_summon_pet_skill: bool = false
|
||
var summon_health_threshold: float = 0.5 # 召唤触发阈值(生命值百分比)
|
||
var summon_count: int = 1 # 召唤小弟数量
|
||
var summon_triggered: bool = false # 是否已触发过召唤(防止重复触发)
|
||
var summon_scale: float = 0.1 # 召唤小弟属性缩放比例(10%)
|
||
|
||
#技能-死亡重生
|
||
var enable_death_respawn_skill: bool = false
|
||
var respawn_health_percentage: float = 0.3 # 重生时恢复的血量百分比(30%)
|
||
var max_respawn_count: int = 1 # 最大重生次数
|
||
var current_respawn_count: int = 0 # 当前已重生次数
|
||
|
||
#技能-反弹伤害
|
||
var enable_damage_reflection_skill: bool = false
|
||
var damage_reflection_cooldown: float = 10.0 # 反弹伤害冷却时间(秒)
|
||
var damage_reflection_cooldown_end_time: float = 0.0 # 反弹伤害冷却结束时间
|
||
var damage_reflection_percentage: float = 0.5 # 反弹伤害百分比(50%)
|
||
|
||
#击退效果
|
||
var enable_knockback: bool = true # 是否启用击退效果
|
||
var knockback_force: float = 300.0 # 击退力度(像素/秒)
|
||
var knockback_duration: float = 0.8 # 击退持续时间(秒)
|
||
var knockback_velocity: Vector2 = Vector2.ZERO # 当前击退速度
|
||
var knockback_end_time: float = 0.0 # 击退结束时间
|
||
var is_being_knocked_back: bool = false # 是否正在被击退
|
||
|
||
# 边界限制
|
||
var boundary_min: Vector2 = Vector2(0, 0) # 边界最小坐标
|
||
var boundary_max: Vector2 = Vector2(1400, 720) # 边界最大坐标
|
||
var boundary_damage: float = 10.0 # 碰撞边界时受到的伤害
|
||
var boundary_bounce_force: float = 200.0 # 边界反弹力度
|
||
|
||
|
||
# 移动属性
|
||
var move_speed: float = 150.0 # 移动速度(像素/秒)
|
||
var dodge_rate: float = 0.05 # 闪避概率(0~1)
|
||
|
||
# 元素属性
|
||
var element_type: ElementType = ElementType.NONE # 元素类型(例如火、水、雷等)
|
||
var element_damage_bonus: float = 50.0 # 元素伤害加成(额外元素伤害)
|
||
|
||
|
||
# 武器系统
|
||
var left_weapon: String = "" # 左手武器名称
|
||
var right_weapon: String = "" # 右手武器名称
|
||
var weapon_system: WeaponBase # 武器系统引用
|
||
|
||
# 巡逻状态
|
||
var is_patrolling: bool = false # 是否正在巡逻
|
||
var patrol_path: PackedVector2Array = [] # 巡逻路径点
|
||
var patrol_speed: float = 80.0 # 巡逻移动速度
|
||
var current_patrol_index: int = 0 # 当前巡逻目标点索引
|
||
var patrol_wait_time: float = 0.0 # 在巡逻点的等待时间
|
||
var patrol_max_wait_time: float = 1.0 # 在巡逻点的最大等待时间
|
||
|
||
# 巡逻随机走动
|
||
var patrol_center_position: Vector2 = Vector2.ZERO # 巡逻中心点位置
|
||
var patrol_radius: float = 150.0 # 巡逻半径
|
||
var patrol_target_position: Vector2 = Vector2.ZERO # 当前巡逻目标位置
|
||
var patrol_move_timer: float = 0.0 # 巡逻移动计时器
|
||
var patrol_move_interval: float = 2.0 # 巡逻移动间隔(秒)
|
||
|
||
# 战斗控制
|
||
var combat_enabled: bool = true # 是否启用战斗行为
|
||
|
||
#============================宠物所有属性===============================
|
||
|
||
|
||
|
||
#============================杂项未处理===============================
|
||
# 状态变量
|
||
var current_state: PetState = PetState.IDLE # 当前状态(待机、移动、攻击等)
|
||
var current_target: NewPetBase = null # 当前目标(敌方宠物对象)
|
||
var last_attack_time: float = 0.0 # 上次攻击时间(用于计算攻速冷却)
|
||
var velocity: Vector2 = Vector2.ZERO # 当前移动速度(方向与速度)
|
||
var is_alive: bool = true # 是否存活
|
||
|
||
# 子弹场景
|
||
var bullet_scene: PackedScene = preload("res://Scene/NewPet/BulletBase.tscn")
|
||
|
||
# 性能优化变量
|
||
var update_ui_timer: float = 0.0
|
||
var ui_update_interval: float = 0.2 # UI更新间隔,减少频繁更新
|
||
var ai_update_timer: float = 0.0
|
||
var ai_update_interval: float = 0.05 # AI更新间隔,平衡性能和反应速度
|
||
|
||
var last_direction_x = -1 # 假设初始向右
|
||
#============================杂项未处理===============================
|
||
|
||
|
||
#====================基础方法=========================
|
||
func _ready():
|
||
# 记录生成时间
|
||
spawn_time = Time.get_ticks_msec() / 1000.0
|
||
#默认佩戴武器测试武器系统
|
||
equip_weapon("钻石剑", "left")
|
||
equip_weapon("铁镐", "right")
|
||
|
||
# 初始化武器系统
|
||
init_weapon_system()
|
||
|
||
# 初始化UI
|
||
update_ui()
|
||
# 设置碰撞层和掩码
|
||
setup_collision_layers()
|
||
# 延迟一帧后开始AI,确保所有宠物都已生成
|
||
await get_tree().process_frame
|
||
_start_ai()
|
||
|
||
func _physics_process(delta):
|
||
if not is_alive:
|
||
return
|
||
|
||
# 更新计时器
|
||
update_ui_timer += delta
|
||
ai_update_timer += delta
|
||
|
||
# 生命恢复
|
||
if enable_health_regen and current_health < max_health:
|
||
current_health = min(max_health, current_health + health_regen * delta)
|
||
|
||
# 护盾恢复
|
||
if enable_shield_regen and max_shield > 0 and current_shield < max_shield:
|
||
current_shield = min(max_shield, current_shield + shield_regen * delta)
|
||
|
||
# 巡逻逻辑已简化为静态生成,无需移动处理
|
||
|
||
# AI更新
|
||
if ai_update_timer >= ai_update_interval:
|
||
update_ai()
|
||
ai_update_timer = 0.0
|
||
|
||
# 检查技能-多发射击触发
|
||
if enable_multi_projectile_skill:
|
||
check_multi_projectile_skill()
|
||
|
||
# 检查技能-狂暴模式触发
|
||
if enable_berserker_skill:
|
||
check_berserker_skill()
|
||
|
||
# 检查技能-召唤小弟触发
|
||
if enable_summon_pet_skill:
|
||
check_summon_pet_skill()
|
||
|
||
# 击退效果处理
|
||
if is_being_knocked_back:
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
if current_time >= knockback_end_time:
|
||
# 击退结束
|
||
is_being_knocked_back = false
|
||
knockback_velocity = Vector2.ZERO
|
||
else:
|
||
# 应用击退速度,逐渐衰减
|
||
var remaining_time = knockback_end_time - current_time
|
||
var decay_factor = remaining_time / knockback_duration
|
||
position += knockback_velocity * decay_factor * delta
|
||
|
||
# 移动处理(击退时不应用普通移动)
|
||
if not is_being_knocked_back and velocity.length() > 0:
|
||
position += velocity * delta
|
||
velocity = velocity.move_toward(Vector2.ZERO, 500 * delta) # 摩擦力
|
||
|
||
# 边界检测和反弹处理
|
||
check_boundary_collision()
|
||
|
||
# UI更新
|
||
if update_ui_timer >= ui_update_interval:
|
||
update_ui()
|
||
update_ui_timer = 0.0
|
||
#====================基础方法=========================
|
||
|
||
|
||
|
||
#=========================宠物系统通用函数==================================
|
||
#设置碰撞体积(对远程攻击还是有用的)
|
||
func setup_collision_layers():
|
||
collision_layer = 1
|
||
collision_mask = 1
|
||
|
||
#开启宠物ai系统
|
||
func _start_ai():
|
||
"""启动AI,立即寻找目标"""
|
||
if not is_alive:
|
||
return
|
||
|
||
# 立即寻找最近的敌人
|
||
current_target = find_nearest_enemy()
|
||
|
||
# 如果找到目标,开始移动或攻击
|
||
if current_target != null:
|
||
current_state = PetState.MOVING
|
||
# 找到攻击目标
|
||
|
||
#AI逻辑更新
|
||
func update_ai():
|
||
"""AI逻辑更新"""
|
||
if current_state == PetState.DEAD or is_being_knocked_back:
|
||
return
|
||
|
||
# 如果正在巡逻,执行巡逻AI逻辑
|
||
if is_patrolling:
|
||
update_patrol_ai()
|
||
return
|
||
|
||
# 如果启用了战斗且不在巡逻状态,执行战斗AI
|
||
if combat_enabled and not is_patrolling:
|
||
# 寻找目标(即使在攻击状态也要检查目标有效性)
|
||
if current_target == null or not current_target.is_alive:
|
||
current_target = find_nearest_enemy()
|
||
|
||
if current_target == null:
|
||
# 没有目标时,继续搜索而不是待机
|
||
current_state = PetState.MOVING
|
||
pet_image.animation = "walk"
|
||
# 随机移动寻找敌人
|
||
var random_direction = Vector2(randf_range(-1, 1), randf_range(-1, 1)).normalized()
|
||
velocity = random_direction * move_speed * 0.5
|
||
return
|
||
|
||
# 如果正在攻击,等待攻击完成
|
||
if current_state == PetState.ATTACKING:
|
||
return
|
||
|
||
var distance_to_target = global_position.distance_to(current_target.global_position)
|
||
|
||
# 优先近战攻击(包含武器攻击范围加成)
|
||
var total_attack_range = attack_range
|
||
if distance_to_target <= total_attack_range:
|
||
if can_attack():
|
||
perform_melee_attack()
|
||
else:
|
||
current_state = PetState.IDLE
|
||
pet_image.animation = "idle"
|
||
else:
|
||
# 移动到目标
|
||
move_towards_target()
|
||
|
||
#寻找最近的敌人
|
||
func find_nearest_enemy() -> NewPetBase:
|
||
"""寻找最近的敌人"""
|
||
var enemies = get_tree().get_nodes_in_group("pets")
|
||
var nearest_enemy: NewPetBase = null
|
||
var min_distance = INF
|
||
|
||
for enemy in enemies:
|
||
if enemy == self or not enemy.is_alive or enemy.pet_team == pet_team:
|
||
continue
|
||
|
||
var distance = global_position.distance_to(enemy.global_position)
|
||
if distance < min_distance:
|
||
min_distance = distance
|
||
nearest_enemy = enemy
|
||
|
||
return nearest_enemy
|
||
|
||
#移动到目标
|
||
func move_towards_target():
|
||
"""移动到目标"""
|
||
if current_target == null:
|
||
return
|
||
|
||
current_state = PetState.MOVING
|
||
pet_image.animation = "walk"
|
||
|
||
var direction = (current_target.global_position - global_position).normalized()
|
||
velocity = direction * move_speed
|
||
|
||
#==================只有当方向发生变化时才执行翻转逻辑=======================
|
||
if direction.x != last_direction_x:
|
||
if direction.x < 0:
|
||
# 向左转
|
||
pet_image.flip_h = false
|
||
left_tool_image.flip_h = true
|
||
right_tool_image.flip_h = true
|
||
|
||
# 只翻转一次位置(使用初始位置的相反数)
|
||
left_tool_image.position.x = -abs(left_tool_image.position.x)
|
||
right_tool_image.position.x = -abs(right_tool_image.position.x)
|
||
else:
|
||
# 向右转
|
||
pet_image.flip_h = true
|
||
left_tool_image.flip_h = false
|
||
right_tool_image.flip_h = false
|
||
|
||
# 只翻转一次位置(使用初始位置的绝对值)
|
||
left_tool_image.position.x = abs(left_tool_image.position.x)
|
||
right_tool_image.position.x = abs(right_tool_image.position.x)
|
||
|
||
# 更新上一次的方向记录
|
||
last_direction_x = direction.x
|
||
#==================只有当方向发生变化时才执行翻转逻辑=======================
|
||
|
||
|
||
#检查边界碰撞并处理反弹和伤害
|
||
func check_boundary_collision():
|
||
"""检查边界碰撞并处理反弹和伤害"""
|
||
if not is_alive:
|
||
return
|
||
|
||
# 巡逻宠物不受边界限制
|
||
if is_patrolling:
|
||
return
|
||
|
||
var collision_occurred = false
|
||
var bounce_direction = Vector2.ZERO
|
||
|
||
# 检查X轴边界
|
||
if position.x < boundary_min.x:
|
||
position.x = boundary_min.x
|
||
bounce_direction.x = 1.0 # 向右反弹
|
||
collision_occurred = true
|
||
elif position.x > boundary_max.x:
|
||
position.x = boundary_max.x
|
||
bounce_direction.x = -1.0 # 向左反弹
|
||
collision_occurred = true
|
||
|
||
# 检查Y轴边界
|
||
if position.y < boundary_min.y:
|
||
position.y = boundary_min.y
|
||
bounce_direction.y = 1.0 # 向下反弹
|
||
collision_occurred = true
|
||
elif position.y > boundary_max.y:
|
||
position.y = boundary_max.y
|
||
bounce_direction.y = -1.0 # 向上反弹
|
||
collision_occurred = true
|
||
|
||
# 如果发生碰撞,应用反弹和伤害
|
||
if collision_occurred:
|
||
# 应用反弹效果
|
||
if bounce_direction.length() > 0:
|
||
bounce_direction = bounce_direction.normalized()
|
||
velocity = bounce_direction * boundary_bounce_force
|
||
# 如果正在被击退,也要修改击退方向
|
||
if is_being_knocked_back:
|
||
knockback_velocity = bounce_direction * knockback_force
|
||
|
||
# 造成边界伤害
|
||
take_damage(boundary_damage, null)
|
||
# 边界碰撞处理
|
||
|
||
#检查是否可以攻击
|
||
func can_attack() -> bool:
|
||
"""检查是否可以攻击"""
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
var time_since_last_attack = current_time - last_attack_time
|
||
# 计算总攻击速度(包含武器加成)
|
||
var total_attack_speed = attack_speed
|
||
var attack_cooldown = 1.0 / max(0.1, total_attack_speed) # 防止除零错误
|
||
return time_since_last_attack >= attack_cooldown
|
||
|
||
#执行近战攻击
|
||
func perform_melee_attack():
|
||
"""执行近战攻击"""
|
||
current_state = PetState.ATTACKING
|
||
pet_image.animation = "idle" # 可以添加攻击动画
|
||
last_attack_time = Time.get_ticks_msec() / 1000.0
|
||
|
||
# 显示武器
|
||
left_tool_image.visible = true
|
||
right_tool_image.visible = true
|
||
|
||
# 直接攻击当前目标(如果在攻击范围内)
|
||
if current_target != null and current_target.is_alive:
|
||
var distance_to_target = global_position.distance_to(current_target.global_position)
|
||
var total_attack_range = attack_range
|
||
if distance_to_target <= total_attack_range and current_target.pet_team != pet_team:
|
||
deal_damage_to(current_target)
|
||
# 执行近战攻击
|
||
|
||
# 隐藏武器并重置状态(延迟)
|
||
get_tree().create_timer(0.2).timeout.connect(func():
|
||
#left_tool_image.visible = false
|
||
#right_tool_image.visible = false
|
||
current_state = PetState.IDLE
|
||
)
|
||
|
||
#应用宠物外观图片
|
||
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
|
||
|
||
# 外观应用成功
|
||
else:
|
||
pass # 静默处理错误
|
||
|
||
# 清理临时实例
|
||
temp_instance.queue_free()
|
||
|
||
# 重新更新武器图标(因为外观应用可能覆盖了武器图标)
|
||
if pet.weapon_system != null:
|
||
pet.update_weapon_icons()
|
||
|
||
#对目标造成伤害
|
||
func deal_damage_to(target: NewPetBase):
|
||
"""对目标造成伤害"""
|
||
var damage = calculate_damage(target)
|
||
target.take_damage(damage, self)
|
||
|
||
# 应用击退效果
|
||
if enable_knockback and target.enable_knockback and target.is_alive:
|
||
apply_knockback_to(target)
|
||
|
||
# 发射信号
|
||
pet_attacked.emit(self, target, damage)
|
||
|
||
#对目标应用击退效果
|
||
func apply_knockback_to(target: NewPetBase):
|
||
"""对目标应用击退效果"""
|
||
if not target.is_alive or target.is_being_knocked_back:
|
||
return
|
||
|
||
# 计算击退方向(从攻击者指向目标)
|
||
var knockback_direction = (target.global_position - global_position).normalized()
|
||
|
||
# 如果距离太近,使用随机方向避免除零错误
|
||
if knockback_direction.length() < 0.1:
|
||
knockback_direction = Vector2(randf_range(-1, 1), randf_range(-1, 1)).normalized()
|
||
|
||
# 设置击退参数(包含武器击退力加成)
|
||
var total_knockback_force = target.knockback_force
|
||
target.knockback_velocity = knockback_direction * total_knockback_force
|
||
target.is_being_knocked_back = true
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
target.knockback_end_time = current_time + target.knockback_duration
|
||
|
||
# 击退时暂停AI行为
|
||
if target.current_state != PetState.DEAD:
|
||
target.current_state = PetState.IDLE
|
||
|
||
# 击退效果生效
|
||
|
||
#计算伤害
|
||
func calculate_damage(target: NewPetBase) -> float:
|
||
"""计算伤害"""
|
||
var damage = base_attack_damage
|
||
|
||
# 添加元素伤害加成(固定额外伤害)
|
||
damage += element_damage_bonus
|
||
|
||
# 狂暴模式伤害加成
|
||
if is_berserker:
|
||
damage *= berserker_bonus
|
||
|
||
# 暴击计算(包含武器暴击率加成)
|
||
var total_crit_rate = crit_rate
|
||
if randf() < total_crit_rate:
|
||
damage *= crit_damage
|
||
|
||
# 元素克制倍数(相克关系的倍数加成)
|
||
var element_multiplier = get_element_multiplier(element_type, target.element_type)
|
||
damage *= element_multiplier
|
||
|
||
# 护甲减伤计算(新系统:护甲值直接减免伤害,但最少保留1点伤害)
|
||
# 包含武器护甲穿透加成
|
||
var total_armor_penetration = armor_penetration
|
||
var effective_armor = max(0, target.current_armor - total_armor_penetration)
|
||
# 护甲值直接减免伤害
|
||
damage = max(1.0, damage - effective_armor) # 最少保留1点伤害
|
||
|
||
return damage
|
||
|
||
#获取元素克制倍数
|
||
func get_element_multiplier(attacker_element: ElementType, defender_element: ElementType) -> float:
|
||
"""获取元素克制倍数"""
|
||
# 简化的元素克制系统
|
||
if attacker_element == ElementType.FIRE and defender_element == ElementType.WOOD:
|
||
return 1.5
|
||
elif attacker_element == ElementType.WATER and defender_element == ElementType.FIRE:
|
||
return 1.5
|
||
elif attacker_element == ElementType.WOOD and defender_element == ElementType.EARTH:
|
||
return 1.5
|
||
else:
|
||
return 1.0
|
||
|
||
#受到伤害
|
||
func take_damage(damage: float, attacker: NewPetBase):
|
||
"""受到伤害"""
|
||
if not is_alive:
|
||
return
|
||
|
||
# 检查攻击者是否有效(防止已释放对象错误)
|
||
var attacker_name = "未知攻击者"
|
||
if attacker != null and is_instance_valid(attacker):
|
||
attacker_name = attacker.pet_name
|
||
|
||
# 闪避检查
|
||
if randf() < dodge_rate:
|
||
# 闪避成功
|
||
return # 闪避成功
|
||
|
||
# 反弹伤害技能检查
|
||
if enable_damage_reflection_skill and attacker != null and is_instance_valid(attacker) and attacker != self:
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
# 检查冷却时间
|
||
if current_time >= damage_reflection_cooldown_end_time:
|
||
# 计算反弹伤害
|
||
var reflection_damage = damage * damage_reflection_percentage
|
||
# 对攻击者造成反弹伤害(不会再次触发反弹,避免无限循环)
|
||
attacker.take_reflection_damage(reflection_damage, self)
|
||
# 设置冷却时间
|
||
damage_reflection_cooldown_end_time = current_time + damage_reflection_cooldown
|
||
# 发射技能信号
|
||
pet_skill_used.emit(self, "反弹伤害")
|
||
|
||
# 护盾优先吸收伤害
|
||
if current_shield > 0:
|
||
var shield_damage = min(current_shield, damage)
|
||
current_shield -= shield_damage
|
||
damage -= shield_damage
|
||
# 护盾吸收伤害
|
||
|
||
# 护盾消耗完后,剩余伤害扣除生命值
|
||
if damage > 0:
|
||
current_health -= damage
|
||
# 受到伤害
|
||
|
||
# 受伤视觉效果(短暂变红)
|
||
if not is_berserker: # 狂暴状态下不覆盖红色效果
|
||
pet_image.modulate = Color(1.3, 0.7, 0.7, 1.0)
|
||
get_tree().create_timer(0.15).timeout.connect(func():
|
||
if not is_berserker and is_alive:
|
||
pet_image.modulate = Color(1.0, 1.0, 1.0, 1.0)
|
||
)
|
||
|
||
# 检查死亡
|
||
if current_health <= 0:
|
||
die()
|
||
|
||
#受到反弹伤害(不会再次触发反弹效果)
|
||
func take_reflection_damage(damage: float, reflector: NewPetBase):
|
||
"""受到反弹伤害(不会再次触发反弹效果)"""
|
||
if not is_alive:
|
||
return
|
||
|
||
# 闪避检查
|
||
if randf() < dodge_rate:
|
||
# 闪避成功
|
||
return
|
||
|
||
# 护盾优先吸收伤害
|
||
if current_shield > 0:
|
||
var shield_damage = min(current_shield, damage)
|
||
current_shield -= shield_damage
|
||
damage -= shield_damage
|
||
|
||
# 护盾消耗完后,剩余伤害扣除生命值
|
||
if damage > 0:
|
||
current_health -= damage
|
||
|
||
# 受伤视觉效果(短暂变红)
|
||
if not is_berserker:
|
||
pet_image.modulate = Color(1.3, 0.7, 0.7, 1.0)
|
||
get_tree().create_timer(0.15).timeout.connect(func():
|
||
if not is_berserker and is_alive:
|
||
pet_image.modulate = Color(1.0, 1.0, 1.0, 1.0)
|
||
)
|
||
|
||
# 检查死亡
|
||
if current_health <= 0:
|
||
die()
|
||
|
||
#治疗
|
||
func heal(amount: float):
|
||
"""治疗"""
|
||
current_health = min(max_health, current_health + amount)
|
||
|
||
#死亡处理
|
||
func die():
|
||
"""死亡处理"""
|
||
# 防止重复死亡处理
|
||
if current_state == PetState.DEAD:
|
||
return
|
||
|
||
# 检查死亡重生技能
|
||
if enable_death_respawn_skill and current_respawn_count < max_respawn_count:
|
||
trigger_death_respawn_skill()
|
||
return # 重生成功,不执行死亡逻辑
|
||
|
||
# 确认死亡状态
|
||
is_alive = false
|
||
current_state = PetState.DEAD
|
||
current_health = 0 # 确保生命值为0
|
||
velocity = Vector2.ZERO # 停止移动
|
||
current_target = null # 清除目标
|
||
|
||
# 死亡视觉效果
|
||
modulate = Color(0.5, 0.5, 0.5, 0.7) # 变灰
|
||
|
||
# 触发自爆技能
|
||
if enable_self_destruct_skill:
|
||
trigger_self_destruct_skill()
|
||
|
||
# 发射死亡信号
|
||
pet_died.emit(self)
|
||
|
||
# 从宠物组中移除
|
||
remove_from_group("pets")
|
||
|
||
#更新UI显示
|
||
func update_ui():
|
||
"""更新UI显示"""
|
||
if pet_name_rich_text:
|
||
pet_name_rich_text.text = pet_name
|
||
|
||
update_health_bar()
|
||
update_shield_bar()
|
||
update_armor_bar()
|
||
|
||
#更新生命值条
|
||
func update_health_bar():
|
||
"""更新生命值条"""
|
||
if health_bar and health_label:
|
||
health_bar.value = (current_health / max_health) * 100
|
||
health_label.text = "生命值:%d/%d" % [current_health, max_health]
|
||
|
||
#更新护盾条
|
||
func update_shield_bar():
|
||
"""更新护盾条"""
|
||
if shield_bar and shield_label:
|
||
if max_shield > 0:
|
||
shield_bar.visible = true
|
||
shield_label.visible = true
|
||
shield_bar.value = (current_shield / max_shield) * 100
|
||
shield_label.text = "护盾值:%d/%d" % [current_shield, max_shield]
|
||
else:
|
||
shield_bar.visible = false
|
||
shield_label.visible = false
|
||
|
||
#更新护甲条
|
||
func update_armor_bar():
|
||
"""更新护甲条"""
|
||
if armor_bar and armor_label:
|
||
if max_armor > 0:
|
||
armor_bar.visible = true
|
||
armor_label.visible = true
|
||
armor_bar.value = (current_armor / max_armor) * 100
|
||
armor_label.text = "护甲值:%d/%d" % [current_armor, max_armor]
|
||
else:
|
||
armor_bar.visible = false
|
||
armor_label.visible = false
|
||
#=========================宠物系统通用函数==================================
|
||
|
||
|
||
|
||
|
||
#=======================宠物技能系统===================================
|
||
|
||
|
||
#==================特殊技能-多发射击=====================
|
||
func check_multi_projectile_skill():
|
||
"""检查多发射击技能触发条件"""
|
||
if multi_projectile_count > 0 or not is_alive:
|
||
return
|
||
|
||
# 宠物生成后按配置的延迟时间触发多发射击(只触发一次)
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
if current_time - spawn_time >= multi_projectile_delay: # 使用配置的延迟时间
|
||
trigger_multi_projectile_skill()
|
||
multi_projectile_count = 1 # 标记已触发,防止重复触发
|
||
|
||
func trigger_multi_projectile_skill():
|
||
"""触发多发射击技能:发射3枚不同类型的平行子弹"""
|
||
# 触发多发射击技能
|
||
|
||
# 获取宠物朝向(基于精灵翻转状态)
|
||
var forward_direction = Vector2.RIGHT if pet_image.flip_h else Vector2.LEFT
|
||
|
||
# 定义三种不同的子弹类型
|
||
var bullet_types = ["小蓝弹", "小红弹", "长紫弹"]
|
||
|
||
# 发射3枚不同类型的平行子弹
|
||
for i in range(3):
|
||
var bullet = bullet_scene.instantiate()
|
||
self.get_parent().add_child(bullet)
|
||
|
||
# 计算子弹位置偏移(平行排列)
|
||
var offset_y = (i - 1) * 30 # 上中下三枚子弹,间距30像素
|
||
var bullet_position = global_position + Vector2(0, offset_y)
|
||
bullet.global_position = bullet_position
|
||
|
||
# 设置子弹属性,使用不同类型的子弹
|
||
bullet.setup(forward_direction, projectile_speed, base_attack_damage * 0.6, self, bullet_types[i])
|
||
|
||
# 稍微延迟发射,创造连发效果
|
||
await get_tree().create_timer(0.05).timeout
|
||
#==================特殊技能-多发射击=====================
|
||
|
||
|
||
#==================特殊技能-狂暴模式=====================
|
||
func check_berserker_skill():
|
||
"""检查狂暴技能触发条件"""
|
||
if berserker_triggered or not is_alive:
|
||
return
|
||
|
||
# 检查生命值是否低于阈值
|
||
var health_percentage = current_health / max_health
|
||
if health_percentage <= berserker_threshold:
|
||
trigger_berserker_skill()
|
||
berserker_triggered = true
|
||
|
||
# 检查狂暴是否结束
|
||
if is_berserker:
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
if current_time >= berserker_end_time:
|
||
end_berserker_skill()
|
||
|
||
func trigger_berserker_skill():
|
||
"""触发狂暴技能:提升攻击力和攻击速度"""
|
||
# 触发狂暴技能
|
||
|
||
is_berserker = true
|
||
var current_time = Time.get_ticks_msec() / 1000.0
|
||
berserker_end_time = current_time + berserker_duration
|
||
|
||
# 视觉效果:宠物变红
|
||
pet_image.modulate = Color(1.5, 0.8, 0.8, 1.0)
|
||
|
||
# 提升攻击速度
|
||
attack_speed *= 1.3
|
||
|
||
# 发射技能信号
|
||
pet_skill_used.emit(self, "狂暴模式")
|
||
|
||
func end_berserker_skill():
|
||
"""结束狂暴技能"""
|
||
# 狂暴模式结束
|
||
|
||
is_berserker = false
|
||
|
||
# 恢复正常颜色
|
||
pet_image.modulate = Color(1.0, 1.0, 1.0, 1.0)
|
||
|
||
# 恢复攻击速度
|
||
attack_speed /= 1.3
|
||
#==================特殊技能-狂暴模式=====================
|
||
|
||
|
||
#==================特殊技能-自爆=====================
|
||
func trigger_self_destruct_skill():
|
||
"""触发自爆技能:死亡时向周围360度发射12枚闪电子弹"""
|
||
# 触发自爆技能
|
||
|
||
# 计算12枚子弹的角度间隔(360度 / 12 = 30度)
|
||
var bullet_count = 12
|
||
var angle_step = 360.0 / bullet_count
|
||
|
||
# 定义四种闪电子弹类型,循环使用
|
||
var lightning_types = ["黄色闪电", "绿色闪电", "红色闪电", "紫色闪电"]
|
||
|
||
# 发射12枚闪电子弹
|
||
for i in range(bullet_count):
|
||
var bullet = bullet_scene.instantiate()
|
||
get_tree().current_scene.add_child(bullet)
|
||
|
||
# 计算子弹发射角度(度转弧度)
|
||
var angle_degrees = i * angle_step
|
||
var angle_radians = deg_to_rad(angle_degrees)
|
||
|
||
# 计算子弹发射方向
|
||
var direction = Vector2(cos(angle_radians), sin(angle_radians))
|
||
|
||
# 设置子弹位置(从宠物中心发射)
|
||
bullet.global_position = global_position
|
||
|
||
# 设置子弹属性(自爆伤害),使用循环的闪电类型
|
||
var bullet_type = lightning_types[i % lightning_types.size()]
|
||
bullet.setup(direction, projectile_speed, self_destruct_damage, self, bullet_type)
|
||
|
||
# 稍微延迟发射,创造爆炸效果
|
||
await get_tree().create_timer(0.02).timeout
|
||
|
||
# 发射技能信号
|
||
pet_skill_used.emit(self, "自爆")
|
||
#==================特殊技能-自爆=====================
|
||
|
||
|
||
#==================特殊技能-召唤小弟=====================
|
||
func check_summon_pet_skill():
|
||
"""检查召唤小弟技能触发条件"""
|
||
if summon_triggered or not is_alive:
|
||
return
|
||
|
||
# 检查生命值是否低于阈值
|
||
var health_percentage = current_health / max_health
|
||
if health_percentage <= summon_health_threshold:
|
||
trigger_summon_pet_skill()
|
||
summon_triggered = true
|
||
|
||
func trigger_summon_pet_skill():
|
||
"""触发召唤小弟技能:召唤迷你版自己"""
|
||
# 触发召唤技能
|
||
|
||
# 获取NewPetBase场景
|
||
var pet_scene = preload("res://Scene/NewPet/NewPetBase.tscn")
|
||
|
||
# 召唤指定数量的小弟
|
||
for i in range(summon_count):
|
||
var minion = pet_scene.instantiate()
|
||
self.get_parent().add_child(minion)
|
||
|
||
# 设置小弟位置(在召唤者周围随机位置)
|
||
var offset_angle = randf() * 2 * PI
|
||
var offset_distance = 80 + i * 30 # 避免重叠
|
||
var offset = Vector2(cos(offset_angle), sin(offset_angle)) * offset_distance
|
||
minion.global_position = global_position + offset
|
||
|
||
# 设置小弟属性(原版的10%)
|
||
minion.pet_name = pet_name + "的小弟" + str(i + 1)
|
||
minion.pet_team = pet_team # 同队伍
|
||
minion.pet_id = pet_id + "_minion_" + str(i + 1)
|
||
minion.pet_type = pet_type + "(迷你)"
|
||
minion.pet_level = max(1, int(pet_level * summon_scale))
|
||
|
||
# 复制宠物图片路径
|
||
minion.pet_image_path = pet_image_path
|
||
|
||
# 复制武器配置
|
||
if left_weapon != "":
|
||
minion.equip_weapon(left_weapon, "left")
|
||
if right_weapon != "":
|
||
minion.equip_weapon(right_weapon, "right")
|
||
|
||
# 生命与防御属性缩放
|
||
minion.max_health = max_health * summon_scale
|
||
minion.current_health = minion.max_health
|
||
minion.health_regen = health_regen * summon_scale
|
||
minion.max_shield = max_shield * summon_scale
|
||
minion.current_shield = minion.max_shield
|
||
minion.shield_regen = shield_regen * summon_scale
|
||
minion.max_armor = max_armor * summon_scale
|
||
minion.current_armor = minion.max_armor
|
||
|
||
# 攻击属性缩放
|
||
minion.base_attack_damage = base_attack_damage * summon_scale
|
||
minion.attack_range = attack_range * summon_scale
|
||
minion.attack_speed = attack_speed * summon_scale
|
||
minion.crit_rate = crit_rate * summon_scale
|
||
minion.crit_damage = crit_damage
|
||
minion.armor_penetration = armor_penetration * summon_scale
|
||
|
||
# 移动属性缩放
|
||
minion.move_speed = move_speed * summon_scale
|
||
minion.dodge_rate = dodge_rate * summon_scale
|
||
|
||
# 元素属性缩放
|
||
minion.element_type = element_type
|
||
minion.element_damage_bonus = element_damage_bonus * summon_scale
|
||
|
||
# 技能属性缩放
|
||
minion.self_destruct_damage = self_destruct_damage * summon_scale
|
||
minion.berserker_bonus = berserker_bonus
|
||
minion.berserker_duration = berserker_duration * summon_scale
|
||
|
||
# 禁用小弟的所有技能
|
||
minion.enable_multi_projectile_skill = false # 禁用多发射击技能
|
||
minion.enable_berserker_skill = false # 禁用狂暴技能
|
||
minion.enable_self_destruct_skill = false # 禁用自爆技能
|
||
minion.enable_summon_pet_skill = false # 禁用召唤技能
|
||
minion.enable_death_respawn_skill = false # 禁用死亡重生技能
|
||
|
||
# 应用宠物图片(如果有的话)
|
||
if pet_image_path != "":
|
||
apply_pet_image(minion, pet_image_path)
|
||
|
||
# 设置小弟的缩放(视觉上更小,原宠物的二分之一)
|
||
minion.scale = Vector2(0.5, 0.5)
|
||
|
||
# 将小弟加入宠物组
|
||
minion.add_to_group("pets")
|
||
|
||
# 小弟召唤成功
|
||
|
||
# 发射技能信号
|
||
pet_skill_used.emit(self, "召唤小弟")
|
||
#==================特殊技能-召唤小弟=====================
|
||
|
||
|
||
#==================特殊技能-死亡重生=====================
|
||
func trigger_death_respawn_skill():
|
||
"""触发死亡重生技能:重生并恢复30%血量"""
|
||
# 增加重生次数
|
||
current_respawn_count += 1
|
||
|
||
# 恢复生命值到指定百分比
|
||
current_health = max_health * respawn_health_percentage
|
||
|
||
# 确保宠物处于存活状态
|
||
is_alive = true
|
||
current_state = PetState.IDLE
|
||
velocity = Vector2.ZERO # 重置速度
|
||
|
||
# 恢复正常外观
|
||
modulate = Color(1.0, 1.0, 1.0, 1.0)
|
||
|
||
# 重生视觉效果:短暂发光
|
||
pet_image.modulate = Color(1.5, 1.5, 1.0, 1.0) # 金色光芒
|
||
get_tree().create_timer(1.0).timeout.connect(func():
|
||
if is_alive and is_instance_valid(self):
|
||
pet_image.modulate = Color(1.0, 1.0, 1.0, 1.0) # 恢复正常颜色
|
||
)
|
||
|
||
# 重生时清除所有负面状态
|
||
is_being_knocked_back = false
|
||
knockback_velocity = Vector2.ZERO
|
||
|
||
# 重新加入宠物组(如果被移除了)
|
||
if not is_in_group("pets"):
|
||
add_to_group("pets")
|
||
|
||
# 更新UI显示
|
||
update_ui()
|
||
|
||
# 发射技能信号
|
||
pet_skill_used.emit(self, "死亡重生")
|
||
#==================特殊技能-死亡重生=====================
|
||
|
||
|
||
#=======================宠物技能系统===================================
|
||
|
||
|
||
|
||
|
||
|
||
#==========================巡逻系统函数=================================
|
||
# 巡逻AI逻辑更新
|
||
func update_patrol_ai():
|
||
"""巡逻AI逻辑:在巡逻点周围随机走动"""
|
||
current_target = null # 清除攻击目标
|
||
|
||
# 如果还没有设置巡逻中心点,使用当前位置作为中心点
|
||
if patrol_center_position == Vector2.ZERO:
|
||
patrol_center_position = global_position
|
||
patrol_target_position = global_position
|
||
|
||
# 更新巡逻移动计时器
|
||
patrol_move_timer += get_physics_process_delta_time()
|
||
|
||
# 检查是否到达目标位置或需要更换目标
|
||
var distance_to_target = global_position.distance_to(patrol_target_position)
|
||
if distance_to_target < 10.0 or patrol_move_timer >= patrol_move_interval:
|
||
# 生成新的随机目标位置(在巡逻半径内)
|
||
var random_angle = randf() * 5 * PI
|
||
var random_distance = randf() * patrol_radius
|
||
patrol_target_position = patrol_center_position + Vector2(
|
||
cos(random_angle) * random_distance,
|
||
sin(random_angle) * random_distance
|
||
)
|
||
patrol_move_timer = 0.0
|
||
|
||
# 移动到目标位置
|
||
var direction = (patrol_target_position - global_position).normalized()
|
||
if direction.length() > 0.1: # 避免抖动
|
||
current_state = PetState.MOVING
|
||
pet_image.animation = "walk"
|
||
velocity = direction * patrol_speed
|
||
|
||
#==================只有当方向发生变化时才执行翻转逻辑=======================
|
||
if direction.x != last_direction_x:
|
||
if direction.x < 0:
|
||
# 向左转
|
||
pet_image.flip_h = false
|
||
left_tool_image.flip_h = true
|
||
right_tool_image.flip_h = true
|
||
|
||
# 只翻转一次位置(使用初始位置的相反数)
|
||
left_tool_image.position.x = -abs(left_tool_image.position.x)
|
||
right_tool_image.position.x = -abs(right_tool_image.position.x)
|
||
else:
|
||
# 向右转
|
||
pet_image.flip_h = true
|
||
left_tool_image.flip_h = false
|
||
right_tool_image.flip_h = false
|
||
|
||
# 只翻转一次位置(使用初始位置的绝对值)
|
||
left_tool_image.position.x = abs(left_tool_image.position.x)
|
||
right_tool_image.position.x = abs(right_tool_image.position.x)
|
||
|
||
# 更新上一次的方向记录
|
||
last_direction_x = direction.x
|
||
#==================只有当方向发生变化时才执行翻转逻辑=======================
|
||
|
||
else:
|
||
# 到达目标位置,待机
|
||
current_state = PetState.IDLE
|
||
pet_image.animation = "idle"
|
||
velocity = Vector2.ZERO
|
||
|
||
# 设置巡逻中心点
|
||
func set_patrol_center(center_pos: Vector2):
|
||
"""设置巡逻中心点位置"""
|
||
patrol_center_position = center_pos
|
||
patrol_target_position = center_pos
|
||
|
||
# 设置战斗启用状态
|
||
func set_combat_enabled(enabled: bool):
|
||
combat_enabled = enabled
|
||
if not enabled:
|
||
# 禁用战斗时,清除当前目标
|
||
current_target = null
|
||
current_state = PetState.IDLE
|
||
#==========================巡逻系统函数=================================
|
||
|
||
|
||
|
||
#==========================武器系统函数=================================
|
||
|
||
func init_weapon_system():
|
||
"""初始化武器系统"""
|
||
weapon_system = WeaponBase.new()
|
||
|
||
func equip_weapon(weapon_name: String, slot: String) -> bool:
|
||
"""装备武器到指定槽位"""
|
||
if weapon_system == null:
|
||
init_weapon_system()
|
||
|
||
# 检查武器是否存在
|
||
if not weapon_system.weapon_data.has(weapon_name):
|
||
return false
|
||
|
||
# 检查槽位是否有效
|
||
if slot != "left" and slot != "right":
|
||
return false
|
||
|
||
# 卸下当前武器(如果有)
|
||
if slot == "left" and left_weapon != "":
|
||
unequip_weapon("left")
|
||
elif slot == "right" and right_weapon != "":
|
||
unequip_weapon("right")
|
||
|
||
# 装备新武器
|
||
if slot == "left":
|
||
left_weapon = weapon_name
|
||
elif slot == "right":
|
||
right_weapon = weapon_name
|
||
|
||
# 应用武器效果
|
||
weapon_system.apply_weapon_effect(self, weapon_name)
|
||
|
||
# 更新武器图标
|
||
update_weapon_icons()
|
||
|
||
# 武器装备完成
|
||
return true
|
||
|
||
func unequip_weapon(slot: String) -> bool:
|
||
"""卸下指定槽位的武器"""
|
||
if weapon_system == null:
|
||
return false
|
||
|
||
var weapon_name = ""
|
||
if slot == "left":
|
||
weapon_name = left_weapon
|
||
left_weapon = ""
|
||
elif slot == "right":
|
||
weapon_name = right_weapon
|
||
right_weapon = ""
|
||
else:
|
||
return false
|
||
|
||
if weapon_name == "":
|
||
return false
|
||
|
||
# 移除武器效果
|
||
weapon_system.remove_weapon_effect(self, weapon_name)
|
||
|
||
# 更新武器图标
|
||
update_weapon_icons()
|
||
|
||
# 武器卸载完成
|
||
return true
|
||
|
||
func update_weapon_icons():
|
||
"""更新武器图标显示"""
|
||
if weapon_system == null:
|
||
return
|
||
|
||
# 更新左手武器图标
|
||
if left_tool_image != null:
|
||
if left_weapon != "":
|
||
var icon_path = weapon_system.get_weapon_icon(left_weapon)
|
||
if icon_path != "":
|
||
left_tool_image.texture = load(icon_path)
|
||
left_tool_image.visible = true
|
||
else:
|
||
left_tool_image.visible = false
|
||
else:
|
||
left_tool_image.visible = false
|
||
|
||
# 更新右手武器图标
|
||
if right_tool_image != null:
|
||
if right_weapon != "":
|
||
var icon_path = weapon_system.get_weapon_icon(right_weapon)
|
||
if icon_path != "":
|
||
right_tool_image.texture = load(icon_path)
|
||
right_tool_image.visible = true
|
||
else:
|
||
right_tool_image.visible = false
|
||
else:
|
||
right_tool_image.visible = false
|
||
|
||
# 武器图标更新完成
|
||
|
||
func get_equipped_weapons() -> Array:
|
||
"""获取当前装备的武器列表"""
|
||
var weapons = []
|
||
if left_weapon != "":
|
||
weapons.append({"slot": "left", "weapon": left_weapon})
|
||
if right_weapon != "":
|
||
weapons.append({"slot": "right", "weapon": right_weapon})
|
||
return weapons
|
||
|
||
func has_weapon_type(weapon_type: String) -> bool:
|
||
"""检查是否装备了指定类型的武器"""
|
||
if weapon_system == null:
|
||
return false
|
||
|
||
# 根据武器名称判断类型
|
||
var weapons_to_check = [left_weapon, right_weapon]
|
||
for weapon_name in weapons_to_check:
|
||
if weapon_name == "":
|
||
continue
|
||
|
||
# 根据武器名称判断类型
|
||
if weapon_type == "sword" and (weapon_name.contains("剑")):
|
||
return true
|
||
elif weapon_type == "axe" and (weapon_name.contains("斧")):
|
||
return true
|
||
elif weapon_type == "pickaxe" and (weapon_name.contains("镐")):
|
||
return true
|
||
|
||
return false
|
||
|
||
func test_weapon_system():
|
||
"""测试武器系统功能"""
|
||
# 装备武器测试
|
||
equip_weapon("钻石剑", "left")
|
||
equip_weapon("铁镐", "right")
|
||
|
||
#==========================武器系统函数=================================
|