extends BaseNetInput class_name PlayerInputFPS @export var mouse_sensitivity: float = 1.0 @export var big_gun: MeshInstance3D @export var hud: CanvasGroup @onready var camera: Camera3D = $"../Head/Camera3D" # Config variables var is_setup: bool = false var override_mouse: bool = false # Input latches (set in _input, consumed in _gather) var _fire_pressed_latch := false var _reload_pressed_latch := false var _next_weapon_latch := false var _prev_weapon_latch := false var _slot_1_latch := false var _slot_2_latch := false var _slot_3_latch := false var _slot_4_latch := false # Direct keyboard state (bypasses Input.get_axis() for reliability) var _key_w := false var _key_s := false var _key_a := false var _key_d := false # Input variables (frame-rate mouse accumulator) var mouse_rotation: Vector2 = Vector2.ZERO # Rollback input properties (set in _gather) var look_angle: Vector2 = Vector2.ZERO var movement: Vector3 = Vector3.ZERO var jump: bool = false var fire_held: bool = false var fire_pressed: bool = false var reload_pressed: bool = false var next_weapon: bool = false var prev_weapon: bool = false var slot_1: bool = false var slot_2: bool = false var slot_3: bool = false var slot_4: bool = false var use_held: bool = false func _notification(what): if what == NOTIFICATION_WM_WINDOW_FOCUS_IN: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) override_mouse = false print("[INPUT] Window focus gained — recaptured mouse") func _input(event: InputEvent) -> void: if !is_multiplayer_authority(): return if event is InputEventMouseMotion: mouse_rotation.y += event.relative.x * mouse_sensitivity mouse_rotation.x += event.relative.y * mouse_sensitivity if event.is_action_pressed("escape"): Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) override_mouse = true # Latched inputs — captured on press, consumed once in _gather if event.is_action_pressed("mouse_weapon_fire"): _fire_pressed_latch = true if event.is_action_pressed("weapon_reload"): _reload_pressed_latch = true if event.is_action_pressed("weapon_next"): _next_weapon_latch = true if event.is_action_pressed("weapon_prev"): _prev_weapon_latch = true if event.is_action_pressed("weapon_slot_1"): _slot_1_latch = true if event.is_action_pressed("weapon_slot_2"): _slot_2_latch = true if event.is_action_pressed("weapon_slot_3"): _slot_3_latch = true if event.is_action_pressed("weapon_slot_4"): _slot_4_latch = true # Track WASD directly from key events (backup for Input.get_axis()) if event is InputEventKey and event.keycode != 0: match event.keycode: KEY_W: _key_w = event.pressed KEY_S: _key_s = event.pressed KEY_A: _key_a = event.pressed KEY_D: _key_d = event.pressed # Also check physical keycode as fallback match event.physical_keycode: KEY_W: _key_w = event.pressed KEY_S: _key_s = event.pressed KEY_A: _key_a = event.pressed KEY_D: _key_d = event.pressed func _gather(): if !is_setup: print("[INPUT DEBUG] _gather first call - setting up") setup() # Movement: try Input.get_axis() first, fall back to direct key tracking var mx = Input.get_axis("move_west", "move_east") var mz = Input.get_axis("move_north", "move_south") # If Input.get_axis() returns 0 but keys are pressed via event tracking, use event tracking if mx == 0.0 and mz == 0.0: if _key_d: mx = 1.0 elif _key_a: mx = -1.0 if _key_s: mz = 1.0 elif _key_w: mz = -1.0 var old_mv = movement movement = Vector3(mx, 0, mz) if movement != old_mv and (mx != 0 or mz != 0): print("[INPUT DEBUG] _gather movement=%s (mx=%.2f mz=%.2f)" % [movement, mx, mz]) jump = Input.is_action_pressed("move_jump") # Fire: held state + one-shot pressed latch fire_held = Input.is_action_pressed("mouse_weapon_fire") fire_pressed = _fire_pressed_latch _fire_pressed_latch = false # Weapon inputs (latched) reload_pressed = _reload_pressed_latch _reload_pressed_latch = false next_weapon = _next_weapon_latch _next_weapon_latch = false prev_weapon = _prev_weapon_latch _prev_weapon_latch = false slot_1 = _slot_1_latch _slot_1_latch = false slot_2 = _slot_2_latch _slot_2_latch = false slot_3 = _slot_3_latch _slot_3_latch = false slot_4 = _slot_4_latch _slot_4_latch = false use_held = Input.is_action_pressed("use_action") # Mouse look if override_mouse: look_angle = Vector2.ZERO mouse_rotation = Vector2.ZERO else: look_angle = Vector2(-mouse_rotation.y, -mouse_rotation.x) mouse_rotation = Vector2.ZERO func setup(): is_setup = true camera.current = true big_gun.hide() hud.show() Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) # Ensure window has keyboard focus for WASD get_window().call_deferred("grab_focus") DisplayServer.call_deferred("window_move_to_foreground") print("[INPUT] Setup complete — camera active, mouse captured, focus grabbed")