extends CharacterBody3D enum State { IDLE, FLYING } const AIR_FRICTION := 0.90 const MIN_SPEED := 0.3 const WALL_BOUNCE := 0.7 var kickable_type: String = "leather" var tier: int = 1 var state: State = State.IDLE var fly_vel: Vector3 = Vector3.ZERO var damage_modifier: float = 0.0 @onready var mesh_node: MeshInstance3D = $LeatherMesh func _ready() -> void: add_to_group("kickable") func apply_collision_damage(_dmg: float) -> void: pass func receive_kick(direction: Vector3, force: float) -> void: fly_vel = direction * force fly_vel.y = 0.0 state = State.FLYING func _physics_process(delta: float) -> void: if state == State.IDLE: return _fly(delta) func _fly(delta: float) -> void: var speed_now := Vector2(fly_vel.x, fly_vel.z).length() velocity = fly_vel velocity.y = 0.0 move_and_slide() var handled := false for i in get_slide_collision_count(): var col := get_slide_collision(i) var col3d := col.get_collider() as Node3D if col3d == null: continue if col3d.has_meta("is_wall"): var normal := col.get_normal() normal.y = 0.0 if normal.length() > 0.01: fly_vel = fly_vel.bounce(normal.normalized()) * WALL_BOUNCE else: fly_vel = Vector3.ZERO handled = true break elif col3d.is_in_group("enemies") or col3d.is_in_group("kickable"): if col3d == self: continue KickSystem.resolve(self, col3d, fly_vel) if is_instance_valid(col3d): var kick_dir := col3d.global_position - global_position kick_dir.y = 0.0 if kick_dir.length() > 0.01: col3d.call("receive_kick", kick_dir.normalized(), speed_now * 0.4) fly_vel *= 0.35 handled = true break if not handled: fly_vel = velocity fly_vel.y = 0.0 fly_vel *= pow(AIR_FRICTION, delta * 60.0) if Vector2(fly_vel.x, fly_vel.z).length() < MIN_SPEED: fly_vel = Vector3.ZERO velocity = Vector3.ZERO state = State.IDLE mesh_node.rotation.y += delta * speed_now * 0.2