This commit is contained in:
2026-01-24 05:59:34 +01:00
commit 0a6a2317bf
100 changed files with 3464 additions and 0 deletions

View File

@@ -0,0 +1,207 @@
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<Gd<DayConfig>>,
#[export]
game_state: Option<Gd<GameState>>,
#[export]
hazard_system: Option<Gd<HazardSystem>>,
#[export]
minigame_container: Option<Gd<Node>>,
#[export]
win_screen: Option<Gd<Control>>,
#[export]
lose_screen: Option<Gd<Control>>,
#[export]
game_complete_screen: Option<Gd<Control>>,
#[export]
day_label: Option<Gd<Label>>,
#[export]
main_menu_scene: Option<Gd<PackedScene>>,
current_day_index: i32,
current_mini_game: Option<Gd<Node>>,
level_ended: bool,
base: Base<Node>,
}
#[godot_api]
impl INode for GameManager {
fn init(base: Base<Node>) -> 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()]);
}
#[func]
pub fn on_retry_pressed(&mut self) {
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 {
let menu_ref = menu.clone();
self.base()
.get_tree()
.unwrap()
.change_scene_to_packed(&menu_ref);
} else {
self.base().get_tree().unwrap().quit();
}
}
}