extends Node # CameraContextManager # Handles camera position based on player's row on the board. # var screen_shake_manager: Node # Removed var camera: Camera3D var player: Node3D # Configuration Map: Row Threshold -> Target Position # We use a list of dictionaries to define ranges. # Setup A: Rows 0-5 # Setup B: Rows 6-9 # Setup C: Rows 10+ var camera_setups = [ { "max_row": 5, "position": Vector3(7.0, 19.636, 15.0) }, { "max_row": 9, "position": Vector3(7.0, 19.636, 19.0) }, { "max_row": 999, "position": Vector3(7.0, 19.22636, 22.5) } # Default/Bottom ] var unique_id: int var current_row_setup: int = -1 var current_col_setup: int = -1 func initialize(p_camera: Camera3D, _p_shake_manager: Node): camera = p_camera # screen_shake_manager = p_shake_manager print("[CameraContextManager] Initialized with camera") func set_player(p_player: Node3D): player = p_player unique_id = p_player.name.to_int() # Try to get movement manager (might be initializing child) var movement_mgr = player.get("movement_manager") if not movement_mgr and "movement_manager" in player: movement_mgr = player.movement_manager var has_snap_signal = player.has_signal("position_changed") if movement_mgr and has_snap_signal: # 1. Follow during movement finished if not movement_mgr.movement_finished.is_connected(_on_player_moved): movement_mgr.movement_finished.connect(_on_player_moved) # 2. Snap on spawn/teleport (Resets setups for immediate catch-up) if not player.position_changed.is_connected(_on_player_snapped): player.position_changed.connect(_on_player_snapped) print("[CameraContextManager] Successfully connected to all player signals") else: print("[CameraContextManager] Warning: movement_manager or signal missing. Retrying in 0.5s...") await get_tree().create_timer(0.5).timeout if player == p_player: set_player(p_player) return # Exit current (failed) initialization _update_camera_target() func _on_player_moved(): # Normal movement finish (keeps hysteresis) _update_camera_target() func _on_player_snapped(): # Sharp snap (spawn/teleport) - Reset setup indices to force immediate re-eval current_row_setup = -1 current_col_setup = -1 # print("[CameraContextManager] Player snapped, resetting setups") _update_camera_target() func _update_camera_target(): if not player or not camera: return var current_row = player.current_position.y var current_col = player.current_position.x var mode = LobbyManager.get_game_mode() if mode == GameMode.Mode.STOP_N_GO: _update_stop_n_go_camera(current_row, current_col) elif mode == GameMode.Mode.TEKTON_DOORS: _update_tekton_doors_camera() else: _update_freemode_camera(current_row, current_col) func _update_stop_n_go_camera(current_row: int, current_col: int): # --- STOP N GO: 4 Columns (X), 2 Rows (Y/Z) --- # Columns: 0-5, 6-10, 11-15, 16-21 # Rows: 0-4, 5-9 # 1. Column Logic (4 Zones) if current_col_setup == -1: if current_col <= 5: current_col_setup = 0 elif current_col <= 10: current_col_setup = 1 elif current_col <= 15: current_col_setup = 2 else: current_col_setup = 3 match current_col_setup: 0: # Leftmost if current_col >= 7: current_col_setup = 1 1: # Mid-Left if current_col <= 4: current_col_setup = 0 elif current_col >= 12: current_col_setup = 2 2: # Mid-Right if current_col <= 9: current_col_setup = 1 elif current_col >= 17: current_col_setup = 3 3: # Rightmost if current_col <= 14: current_col_setup = 2 # 2. Row Logic (2 Zones) if current_row_setup == -1: if current_row <= 4: current_row_setup = 0 else: current_row_setup = 1 match current_row_setup: 0: # Top if current_row >= 6: current_row_setup = 1 1: # Bottom if current_row <= 3: current_row_setup = 0 # 3. Target Calculation var target_x = 3.0 + (current_col_setup * 5.0) # approx centers for 4 zones in 22 cols var target_y = 19.636 var target_z = 15.0 if current_row_setup == 0 else 17.5 # Adjust specific X centers for the 22-col field match current_col_setup: 0: target_x = 3.0 1: target_x = 8.5 2: target_x = 13.5 3: target_x = 18.5 _apply_camera_tween(Vector3(target_x, target_y, target_z)) func _update_tekton_doors_camera(): # --- TEKTON DOORS: Static Overlook --- # Grid is 14x14, center is approx (7, 7) # User requested position: Vector3(7.0, 31.0, 25.5) _apply_camera_tween(Vector3(7.0, 32.3, 25.8)) func _update_freemode_camera(current_row: int, current_col: int): # --- FREEMODE: 3x3 Grid --- # Zone thresholds 4, 9 # Row Hysteresis if current_row_setup == -1: if current_row <= 4: current_row_setup = 0 elif current_row <= 9: current_row_setup = 1 else: current_row_setup = 2 match current_row_setup: 0: # Top if current_row >= 6: current_row_setup = 1 1: # Mid if current_row <= 3: current_row_setup = 0 elif current_row >= 11: current_row_setup = 2 2: # Bot if current_row <= 8: current_row_setup = 1 # Col Hysteresis if current_col_setup == -1: if current_col <= 4: current_col_setup = 0 elif current_col <= 9: current_col_setup = 1 else: current_col_setup = 2 match current_col_setup: 0: # Left if current_col >= 6: current_col_setup = 1 1: # Center if current_col <= 3: current_col_setup = 0 elif current_col >= 11: current_col_setup = 2 2: # Right if current_col <= 8: current_col_setup = 1 var target_z = 15.0 var target_y = 19.636 var target_x = 7.0 match current_row_setup: 0: target_z = 15.0 1: target_z = 19.0 2: target_z = 22.5; target_y = 19.22636 match current_col_setup: 0: target_x = 3.0 # Left zone center 1: target_x = 7.0 # Main center 2: target_x = 11.0 # Right zone center _apply_camera_tween(Vector3(target_x, target_y, target_z)) func _apply_camera_tween(target_pos: Vector3): if camera.position != target_pos: var tween = create_tween() tween.tween_property(camera, "position", target_pos, 0.4).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)