extends Node # CameraContextManager - Smoothly follows player and clamps to arena edges var camera: Camera3D var player: Node3D # Configuration @export var smooth_speed: float = 5.0 @export var z_offset: float = 12.0 @export var default_y: float = 19.636 var bounds_gauntlet = { "min_x": 0.0, "max_x": 20.0, "min_z": 10.0, "max_z": 32.0 } # Bounds Definitions { min_x, max_x, min_z, max_z } var bounds_freemode = { "min_x": 3.0, "max_x": 11.0, "min_z": 13.0, "max_z": 22.5 } var bounds_stop_n_go = { "min_x": 3.0, "max_x": 19.5, "min_z": 13.0, "max_z": 19.5 } var bounds_doors = { "min_x": 7.0, "max_x": 7.0, "min_z": 25.8, "max_z": 25.8 } # Static overlook func initialize(p_camera: Camera3D, _p_shake_manager: Node): camera = p_camera print("[CameraContextManager] Initialized with camera") func set_player(p_player: Node3D): player = p_player print("[CameraContextManager] Player set: ", player.name) func _physics_process(delta): if not player or not camera or not is_instance_valid(player): return var target_pos = _calculate_target_position() # Smoothly interpolate to target camera.position = camera.position.lerp(target_pos, smooth_speed * delta) func _calculate_target_position() -> Vector3: var player_pos = player.global_position var mode = LobbyManager.get_game_mode() # Initial target based on player position + offsets var target_x = player_pos.x var target_y = default_y var target_z = player_pos.z + z_offset # Apply Mode-Specific Clamping var bounds = bounds_freemode # Default if mode == GameMode.Mode.GAUNTLET: bounds = bounds_gauntlet elif mode == GameMode.Mode.STOP_N_GO: bounds = bounds_stop_n_go elif mode == GameMode.Mode.TEKTON_DOORS: bounds = bounds_doors target_y = 32.3 # Doors uses a higher overlook # Clamp X and Z target_x = clamp(target_x, bounds.min_x, bounds.max_x) target_z = clamp(target_z, bounds.min_z, bounds.max_z) # Special case for Setup C in Freemode (Lower Y at bottom edges) if mode == GameMode.Mode.FREEMODE and target_z > 21.0: target_y = 19.22636 return Vector3(target_x, target_y, target_z)