extends CharacterBody3D @export var speed = 100.0 @export var fall_acceleration = 75.0 @export var vertical_sensivity = 0.005 @export var horizontal_sensivity = 0.005 var queue: CommandQueue = CommandQueue.new() @onready var camera: Camera3D = $"Camera" @onready var weapon_player: AnimationPlayer = $"HUD/Weapon/AnimationPlayer" @onready var weapons: WeaponContainer = $"WeaponContainer" # Placeholder UI @onready var ammo_label: Label = $"HUD/Ammo" var current_weapon: Weapon func _ready() -> void: queue.command_pushed.connect(on_queue_command_pushed) queue.command_popped.connect(on_queue_command_popped) weapons.slot_selected.connect(on_weapon_slot_selected) get_tree().create_timer(0.02).timeout.connect(on_weapon_slot_selected) Input.mouse_mode = Input.MOUSE_MODE_CAPTURED func _process(_delta: float) -> void: if current_weapon == null: return var weapon_sides = current_weapon.uses_hands var weapon_sides_are_free = not queue.sides_are_busy(weapon_sides) if weapon_sides_are_free: # Fire logic var fire_action = Input.is_action_just_pressed('shoot') if \ current_weapon.fire_mode is SingleFireMode else \ Input.is_action_pressed('shoot') if fire_action: push_copied_command(CommandQueue.Command.FIRE, weapon_sides) # Reload logic var reload_action = Input.is_action_just_pressed('reload') if reload_action: if not queue.has_command(CommandQueue.Command.RELOAD): push_copied_command(CommandQueue.Command.RELOAD, weapon_sides) for side in CommandQueue.Side.values(): var command = queue.current_command(side) match side: CommandQueue.Side.LEFT: handle_current_left_command(command) CommandQueue.Side.RIGHT: handle_current_right_command(command) func _physics_process(delta: float) -> void: var direction = Vector3.ZERO direction.z = Input.get_axis("move_forward", "move_backward") direction.x = Input.get_axis("move_left", "move_right") var target_velocity = (transform.basis * direction).normalized() * speed * delta if not is_on_floor(): target_velocity.y -= fall_acceleration * delta velocity = target_velocity move_and_slide() func _input(event): if event is InputEventMouseMotion: var new_rotation = clamp( camera.rotation.x - event.relative.y * vertical_sensivity, -PI/2, PI/2 ) camera.rotation.x = new_rotation rotation.y -= event.relative.x * horizontal_sensivity func on_weapon_slot_selected(): if current_weapon != null: current_weapon.fired.disconnect(on_weapon_fired) current_weapon.fire_failed.disconnect(finish_task) weapon_player.remove_animation_library("current") current_weapon = weapons.current_weapon print('im here') current_weapon.fired.connect(on_weapon_fired) current_weapon.fire_failed.connect(finish_task) weapon_player.add_animation_library("current", current_weapon.animation_library) weapon_player.play("current/static") update_ammo_label() func on_queue_command_pushed(commands: Dictionary): for side in commands: match side: CommandQueue.Side.LEFT: handle_new_left_command(commands[side]) CommandQueue.Side.RIGHT: handle_new_right_command(commands[side]) func push_copied_command(command: CommandQueue.Command, sides: Array[CommandQueue.Side]): var commands = {} for side in sides: commands[side] = command queue.push(commands) func finish_task(): queue.pop() func reset_animation_and_finish_task(): weapon_player.play("current/static") queue.pop() func on_queue_command_popped(commands): for i in CommandQueue.Side.size(): match CommandQueue.Side.values()[i]: CommandQueue.Side.LEFT: handle_ended_left_command(commands[i]) CommandQueue.Side.RIGHT: handle_ended_right_command(commands[i]) func update_ammo_label(): ammo_label.text = "{ammo}/{max}".format({ ammo = current_weapon.ammo, max = current_weapon.max_ammo }) func on_weapon_fired(): weapon_player.play("current/fire") update_ammo_label() func on_weapon_reload(): weapon_player.play("current/reload") func reset_animation(): weapon_player.play("current/static") func handle_new_left_command(command: CommandQueue.Command): match command: pass func handle_new_right_command(command: CommandQueue.Command): match command: CommandQueue.Command.RELOAD: weapon_player.play('current/reload') func handle_ended_left_command(command: CommandQueue.Command): match command: pass func handle_ended_right_command(command: CommandQueue.Command): match command: CommandQueue.Command.FIRE: current_weapon.end_fire() CommandQueue.Command.RELOAD: weapon_player.play('current/static') current_weapon.reload() update_ammo_label() func handle_current_left_command(command: CommandQueue.Command): match command: pass func handle_current_right_command(command: CommandQueue.Command): match command: CommandQueue.Command.FIRE: current_weapon.request_fire()