|
|
|
|
extends Node3D
|
|
|
|
|
class_name Move
|
|
|
|
|
|
|
|
|
|
@export var after_image_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 Global.is_level_loading: return
|
|
|
|
|
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(delta)
|
|
|
|
|
update_move(delta)
|
|
|
|
|
update_speed_y(delta)
|
|
|
|
|
var is_against_wall: bool = update_move_check(delta)
|
|
|
|
|
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())
|
|
|
|
|
update_deformation(delta)
|
|
|
|
|
update_move_effect(delta)
|
|
|
|
|
return is_against_wall
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func update_on_floor(delta) -> bool:
|
|
|
|
|
var is_on_floor: bool = character.is_on_floor()
|
|
|
|
|
var is_hit: bool = not status.is_on_floor and is_on_floor
|
|
|
|
|
status.is_on_floor = is_on_floor
|
|
|
|
|
if status.is_on_floor and not status.is_jumping:
|
|
|
|
|
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.speed_y = character.velocity.y
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func update_move(delta):
|
|
|
|
|
var move_velocity: Vector2 = status.move_dir.normalized() * (status.cfg.move.speed * (1 + status.speed_up_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.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.speed_xz = Vector2(character.velocity.x, character.velocity.z).length()
|
|
|
|
|
if status.is_free_turn and status.move_dir.x != 0:
|
|
|
|
|
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.deformation_dir=Vector2(dir_x, dir_y)
|
|
|
|
|
character.add_buff("deformation", 0.2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func update_move_effect(delta):
|
|
|
|
|
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)
|
|
|
|
|
pass
|
|
|
|
|
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
|
|
|
|
|
status.trigger_jump = true
|
|
|
|
|
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
|