extends Node3D class_name Move @export var after_image_speed_curve: Curve @export var speed_curve: Curve var after_image_speed_max: float = 10 @onready var character: Character = (get_owner() as Character) @onready var status: Status = (%Status as Status) @onready var buff: Buff = (%Buff as Buff) @onready var effect: Effect = (%Effect as Effect) @onready var battle: Battle = (%Battle as Battle) var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") var velocity_cache: Vector3 func _process(delta) -> void: if status.is_pause: return if status.is_be_throw: return move_tick(delta) return func move_tick(delta) -> bool: var is_hit_floor: bool = update_on_floor() update_move(delta) update_speed_y(delta) var is_against_wall: bool = update_move_check(delta) status.set_status("velocity_change", character.velocity.abs() - velocity_cache) velocity_cache = character.velocity.abs() if character.velocity: SignalManager.character_pos_changed.emit(character.id(), character.pos()) SignalManager.character_ui_pos_changed.emit(character.id(), character.ui_pos()) SignalManager.character_status_changed.emit(status.id, "pos2d", character.pos2D()) if is_hit_floor: SignalManager.character_hit_floor.emit(character.id(), character.pos()) battle.on_hit_floor() update_deformation(delta) update_move_effect(delta) return is_against_wall func update_on_floor() -> bool: var is_on_floor: bool = character.is_on_floor() var is_hit: bool = not status.is_on_floor and is_on_floor status.set_status("is_on_floor", is_on_floor) if status.is_on_floor and not status.is_jumping: status.set_status("is_jumped", false) var is_skill_running: bool = status.is_skill_running and status.break_level != Enum.EBreakLevel.Walk if is_hit and not status.is_stagger and not is_skill_running: Global.effect_mgr.cast_particle(ResourceManager.particle_move_hit_ground, character.pos()) return is_hit func update_speed_y(delta) -> void: if status.is_speed_y_freeze: character.velocity.y = 0 return var has_y_speed: bool = (status.skill_float_speed != 0) or (status.hit_up_speed != 0) if has_y_speed: character.velocity.y = status.skill_float_speed + status.hit_up_speed else: if not status.is_on_floor: character.velocity.y -= gravity * delta * status.cfg.move.gravity_scale status.set_status("speed_y", character.velocity.y) func update_move(delta): var speed_rate = speed_curve.sample(status.speed_up_rate) var move_velocity: Vector2 = status.move_dir.normalized() * (status.cfg.move.speed * speed_rate) var skill_velocity: Vector2 = status.skill_move_dir * status.skill_move_speed if not status.skill_move_stop else Vector2.ZERO var hit_back_velocity: Vector2 = status.hit_back_dir * status.hit_back_speed move_velocity += skill_velocity + hit_back_velocity status.set_status("speed_dir", Vector2(move_velocity.x, move_velocity.y)) if skill_velocity.length() > 0: move_velocity *= (1 - status.speed_down_push_rate) if move_velocity.length() == 0: move_velocity = Vector2(character.velocity.x, character.velocity.z); if status.is_on_floor: move_velocity = Util.vector_reduce(move_velocity, Setting.drag_ground * delta) else: move_velocity = Util.vector_reduce(move_velocity, Setting.drag_air * delta) character.velocity.x = move_velocity.x character.velocity.z = move_velocity.y status.set_status("speed_xz", Vector2(character.velocity.x, character.velocity.z).length()) if status.is_free_turn and status.move_dir.x != 0: status.set_status("is_right", status.move_dir.x > 0) func update_deformation(_delta): var velocity_change_sum: float = status.velocity_change.x + status.velocity_change.y + status.velocity_change.z if velocity_change_sum > 6: var velocity_change_x: float = status.velocity_change.x var velocity_change_y: float = status.velocity_change.y + status.velocity_change.z var dir_x: int = 1 if (velocity_change_x > 1) or (velocity_change_y < -1) else 0 var dir_y: int = 1 if (velocity_change_y > 1) or (velocity_change_x < -1) else 0 if dir_x or dir_y: status.set_status("deformation_dir", Vector2(dir_x, dir_y)) character.add_buff("deformation", 0.4) func update_move_effect(_delta): var character_type: Enum.ECharacterType = character.cfg().type; match character_type: Enum.ECharacterType.Player: pass Enum.ECharacterType.Monster: pass _: return var speed: float = character.velocity.length() var speed_rate: float = clamp(speed / after_image_speed_max, 0, 1) var after_image_alpha: float = clamp(after_image_speed_curve.sample(speed_rate), 0, 1) if after_image_alpha > 0: effect.cast_after_image(after_image_alpha) if speed > 6: Global.effect_mgr.cast_particle(ResourceManager.particle_move_speed, character.view_pos(), character.velocity.normalized()) var velocity_change_sum: float = status.velocity_change.x + status.velocity_change.y + status.velocity_change.z if velocity_change_sum > 6: Global.effect_mgr.cast_particle(ResourceManager.particle_move_dash, character.view_pos(), character.velocity.normalized()) func update_move_check(_delta) -> bool: var velocity: Vector3 = character.velocity character.move_and_slide() var collision_count: int = character.get_slide_collision_count() if collision_count > 0: var normal: Vector3 = Vector3.ZERO for i in collision_count: var collision: KinematicCollision3D = character.get_slide_collision(i) normal += collision.get_normal() normal = normal.normalized() var normal_speed: float = velocity.dot(normal) if status.is_stagger: if normal_speed < -6 and normal.y >= 0 and not buff.has_buff("hit_ground_cd"): #墙体互动 Global.effect_mgr.cast_particle(ResourceManager.particle_hit_ground_heavy, character.pos(), normal) var velocity_new: Vector3 = velocity - normal * normal_speed * 2 var attack_dir: Vector2 = Vector2(velocity_new.x, velocity_new.z).normalized() character.velocity = Vector3.ZERO var attack_info: Struct.AttackInfo = Struct.AttackInfo.new() attack_info.attack = ResourceManager.cfg_attack_rebound attack_info.attack_box = ResourceManager.cfg_attack_box_rebound attack_info.attack_dir = attack_dir battle.add_attack(attack_info) buff.add_buff("hit_ground_cd", 0.1) elif normal_speed < -3: #反弹 Global.effect_mgr.cast_particle(ResourceManager.particle_hit_ground_normal, character.pos(), normal) character.velocity = velocity - normal * normal_speed * 1.5 character.add_buff("floating", -1) Global.camera_mgr.effect_shake(0.1) if normal.y == 0: if not status.is_stagger: status.is_hit_wall = true return true return false func jump(): character.velocity.y = status.cfg.move.jump_velocity # status.is_jumped = true character.set_view_trigger("jump") buff.add_buff("jumping", 0.1) if status.is_on_floor: Global.effect_mgr.cast_particle(ResourceManager.particle_move_jump_ground, character.pos(), character.velocity.normalized()) else: Global.effect_mgr.cast_particle(ResourceManager.particle_move_jump_air, character.pos(), character.velocity.normalized()) func stop(): character.velocity = Vector3.ZERO