|  |  |  | 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: | 
					
						
							|  |  |  | 		for i in range(skill_cfg.sub_character_count): | 
					
						
							|  |  |  | 			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 character.has_buff("bullet_cd"): | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	character.add_buff("bullet_cd", Setting.bullet_cd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) |