# FPS Character Controller — Tactical Shooter First-person character controller for the tactical shooter GDExtension simulation core. ## Architecture The character controller is a **GDScript bridge** between Godot's input/physics system and the C++ `SimulationServer` (built in task `t_aca0f251`). ``` Godot Input │ ├─► FPSCharacterController._physics_process() │ ├─ capture input (WASD, mouse, jump, sprint, crouch, shoot) │ ├─ build EntityInput Dictionary │ ├─ SimulationServer.apply_input(entity_id, input_dict) │ ├─ SimulationServer.fire_weapon(entity_id) [if shoot] │ ├─ read entity position from server → apply to CharacterBody3D │ └─ apply mouse look (yaw on body, pitch on camera) │ ├─► FpsCamera._process() │ ├─ view bobbing (head bob from movement) │ ├─ weapon sway │ └─ sprint FOV kick │ └─► SimulationServer (C++ GDExtension) ├─ process_tick() @ 128Hz ├─ MovementComponent.update() ├─ HitDetection.process_shot() └─→ returns serialized snapshot ``` ## Files | File | Purpose | |------|---------| | `character/fps_character_controller.gd` | Main controller (CharacterBody3D). Input capture, simulation bridge, walk toggle, crouch, jump. | | `character/fps_camera.gd` | First-person camera (Camera3D). Mouse look pitch, view bobbing, weapon sway, FOV kick. | | `input/input_handler.gd` | Documentation of expected input map bindings. | ## Scene Setup 1. **Create a CharacterBody3D scene:** ``` FPSCharacterController (CharacterBody3D) — script: fps_character_controller.gd ├── FpsCamera (Camera3D) — script: fps_camera.gd ├── CollisionShape3D (CapsuleShape3D) — radius: 0.4, height: 1.8 └── Weapon (Node3D, optional) — child of camera, rest transform tracked ``` 2. **Configure exports** on the root node: - `mouse_sensitivity`: 0.1–0.2 for typical tactical feel - `walk_toggle`: `true` = tap Shift to toggle sprint (CS-style) - `crouch_toggle`: `false` = hold Ctrl to crouch (tactical-style) - `eye_height_stand` / `eye_height_crouch`: match your capsule height 3. **Set up Input Map** in Project Settings: - `move_forward` → W - `move_backward` → S - `move_left` → A - `move_right` → D - `jump` → Space - `sprint` → Shift - `crouch` → Ctrl - `shoot` → Mouse LMB - `aim` → Mouse RMB - `ui_cancel` → Esc (built-in, releases mouse capture) 4. **Integration with SimulationServer:** ```gdscript # In your game manager (autoload or scene root): var server = SimulationServer.new() server.set_tick_rate(128) server.start() var player_id = server.spawn_entity(Vector3(0, 0, 0)) # When player scene is ready: $Player/FPSCharacterController.set_entity_id(player_id) # In _process(delta): while server.can_tick(delta): var snapshot = server.tick() # send snapshot to network layer ``` ## Walk Toggle Behavior - **`walk_toggle = true`** (default): Press Shift to toggle between walk and sprint. Press again to toggle off. Same feel as Counter-Strike's walk/run toggle. - **`walk_toggle = false`**: Hold Shift for temporary sprint. Release to decelerate to walk speed. ## Crouch Behavior - **`crouch_toggle = false`** (default): Hold Ctrl to crouch. Release to stand up. - **`crouch_toggle = true`**: Press Ctrl once to crouch, press again to stand. Crouch transitions are smooth lerps over `crouch_transition_time` seconds. The collision capsule height and camera eye height both lerp simultaneously. ## Standalone Mode When no `SimulationServer` singleton is available, the controller falls back to built-in `CharacterBody3D` movement (`_move_local()`). This is useful for: - Testing the character controller in isolation - Prototyping without the GDExtension compiled - Single-player scenarios without the full simulation stack Configure `local_walk_speed`, `local_sprint_speed`, `local_crouch_speed`, etc. for standalone tuning. ## Dependencies - **Godot 4.2+** (for `Input.get_vector`, `move_toward`, `StringName` literals) - **SimulationServer GDExtension** (from task `t_aca0f251`) for server-authoritative mode - Input map actions listed above ## See Also - Scaffold: `t_aca0f251` — `src/movement_component.h` (C++ Quake/CS movement physics) - Greybox map: `t_p1_greybox` — test environment for this controller - Hitscan weapon: `t_p1_hitscan` — weapon firing + lag compensation - Client prediction: `t_p1_pred` — client-side prediction + server reconciliation - Round system: `t_p1_round` — win/loss/sudden death on top of character controller