extends Node3D class_name SoulAI @export var follow_speed_curve: Curve @export var follow_dist_max: int = 5 @onready var character: Character = (get_owner() as Character) @onready var status: Status = (%Status as Status) @onready var skill: Skill = (%Skill as Skill) var owner_character: Character func _process(delta) -> void: owner_character = Global.character_mgr.get_character(status.owner_id) if not owner_character: Global.character_mgr.destroy_character(character.id()) return update_skill() update_skill_move() update_move() update_bullet() func update_skill() -> void: if not status.ai_skill_order: return var skill_order: Status.SkillOrder = status.ai_skill_order[0] if not skill_order: return var skill_cfg: SkillCfg = skill_order.skill_cfg if skill_cfg.sub_character and skill_cfg.sub_character.type == Enum.ECharacterType.Bullet: var bullet_order: Status.BulletOrder = Status.BulletOrder.new() bullet_order.bullet_cfg = skill_cfg.sub_character bullet_order.cast_dir = skill_order.cast_dir bullet_order.target = skill_order.target status.ai_bullet_order.append(bullet_order) status.ai_skill_order.remove_at(0) else: var cast_dir: Vector2 = skill_order.cast_dir if skill_order.cast_dir else Vector2.RIGHT status.target = skill_order.target var target: Character = Global.character_mgr.get_character(status.target) if target: cast_dir = character.pos2D().direction_to(target.pos2D()).normalized() #施放技能条件检查 if not skill.cast_skill_check(skill_cfg, status.break_level): return character.move_to(cast_dir) skill.cast_skill(skill_cfg, cast_dir) status.ai_skill_order.remove_at(0) func update_skill_move() -> void: if not status.is_skill_running: return var target: Character = Global.character_mgr.get_character(status.target) if not target: return var dir: Vector2 = target.pos2D() - character.pos2D() var dist: float = dir.length() if int(status.break_level) < Enum.EBreakLevel.Break: if dist < 0.5: character.move_to(-dir) elif dist > 2: character.move_to(dir) func update_bullet() -> void: if not status.ai_bullet_order: return var bullet_order: Status.BulletOrder = status.ai_bullet_order[0] if not bullet_order: return var pos: Vector3 = character.pos() var dir: Vector2 = bullet_order.cast_dir var sub: Character = Global.character_mgr.create_character(bullet_order.bullet_cfg, status.team, pos, dir, status.id) if sub: sub.set_status("target", bullet_order.target) status.ai_bullet_order.remove_at(0) func update_move() -> void: if status.is_skill_running: return var owner_pos: Vector3 = owner_character.pos() var radius_add: float = owner_character.radius() + character.radius() var target_pos: Vector3 = owner_pos + Vector3(-1 if owner_character.is_right() else 1, 0, 0) * radius_add * 1.1 var dir: Vector3 = target_pos - character.pos() var dir_2d: Vector2 = Vector2(dir.x, dir.z) var dist: float = dir_2d.length() if dist > follow_dist_max: character.set_pos(target_pos) return var dist_rate = clamp(dist / follow_dist_max, 0, 1) status.speed_up_rate = follow_speed_curve.sample(dist_rate) character.move_to(dir_2d)