use crate::{ core::game_state::GameState, data::day_config::DayConfig, systems::hazard_system::HazardSystem, }; use godot::{ classes::{Control, Label}, prelude::*, }; #[derive(GodotClass)] #[class(base=Node)] pub struct GameManager { #[export] days: Array>, #[export] game_state: Option>, #[export] hazard_system: Option>, #[export] minigame_container: Option>, #[export] win_screen: Option>, #[export] lose_screen: Option>, #[export] game_complete_screen: Option>, #[export] day_label: Option>, #[export] main_menu_scene: Option>, current_day_index: i32, current_mini_game: Option>, level_ended: bool, base: Base, } #[godot_api] impl INode for GameManager { fn init(base: Base) -> Self { Self { days: Array::new(), game_state: None, hazard_system: None, minigame_container: None, win_screen: None, lose_screen: None, game_complete_screen: None, day_label: None, main_menu_scene: None, current_day_index: 0, current_mini_game: None, level_ended: false, base, } } fn ready(&mut self) { let idx = self.current_day_index; self.base_mut() .call_deferred("start_day", &[idx.to_variant()]); } fn process(&mut self, _delta: f64) { if self.level_ended { return; } let (won, lost) = if let Some(state) = &self.game_state { let bind = state.bind(); (bind.get_is_lift_complete(), bind.get_is_lift_failed()) } else { (false, false) }; if won { self.handle_win(); self.level_ended = true; } else if lost { self.handle_loss(); self.level_ended = true; } } } #[godot_api] impl GameManager { #[func] fn start_day(&mut self, index: i32) { self.level_ended = false; if let Some(state) = &self.game_state { let bind = state.bind(); if let Ok(mut inner) = bind.inner.write() { inner.is_lift_complete = false; inner.is_lift_failed = false; inner.lift_progress = 0.0; inner.visual_height = 0.0; inner.lift_effort = 0.0; inner.active_hazards.clear(); } } if index >= self.days.len() as i32 { self.cleanup_level(); if let Some(s) = &mut self.game_complete_screen { s.set_visible(true); } return; } self.cleanup_level(); let config = self.days.get(index as usize).expect("Invalid Day Index"); let config_bind = config.bind(); if let Some(prefab) = &config_bind.mini_game_scene { if let Some(instance) = prefab.instantiate() { if let Some(container) = &mut self.minigame_container { container.add_child(&instance.clone()); } if let Some(mut system) = instance.get_node_or_null("System") { system.set("target_value", &config_bind.target_weight.to_variant()); system.set("gravity", &config_bind.gravity.to_variant()); if let Some(state) = &self.game_state { system.set("game_state", &state.to_variant()); } } self.current_mini_game = Some(instance); } } if let Some(hs) = &mut self.hazard_system { hs.bind_mut() .set_available_hazards(config_bind.available_hazards.clone()); } if let Some(l) = &mut self.day_label { l.set_text(&config_bind.day_title); } if let Some(s) = &mut self.win_screen { s.set_visible(false); } if let Some(s) = &mut self.lose_screen { s.set_visible(false); } } fn cleanup_level(&mut self) { if let Some(game) = &mut self.current_mini_game { game.queue_free(); self.current_mini_game = None; } if let Some(hs) = &mut self.hazard_system { hs.bind_mut().clear_hazards(); } } fn handle_win(&mut self) { if let Some(s) = &mut self.win_screen { s.set_visible(true); } } fn handle_loss(&mut self) { if let Some(s) = &mut self.lose_screen { s.set_visible(true); } } #[func] pub fn on_next_day_pressed(&mut self) { self.current_day_index += 1; let idx = self.current_day_index; self.base_mut() .call_deferred("start_day", &[idx.to_variant()]); godot_print!("GameManager: Starting day {}", idx); } #[func] pub fn on_retry_pressed(&mut self) { godot_print!("GameManager: Retrying day {}", self.current_day_index); let idx = self.current_day_index; self.base_mut() .call_deferred("start_day", &[idx.to_variant()]); } #[func] pub fn on_menu_pressed(&mut self) { if let Some(menu) = &self.main_menu_scene { godot_print!("GameManager: Returning to main menu"); let menu_ref = menu.clone(); self.base() .get_tree() .unwrap() .change_scene_to_packed(&menu_ref); } else { godot_error!("GameManager: No main menu scene assigned"); self.base().get_tree().unwrap().quit(); } } }