using System; using System.Diagnostics; using Godot; public partial class UIHandler : Control { [Export] CodingWindow codingWindow; [Export] RobotList robotList; [Export] Camera3d mainCam; [Export] Map map; [Export] RichTextLabel FPS; [Export] RichTextLabel RAM; [Export] PanelContainer options; [Export] Control uiContent; [Export] PanelContainer menu; [Export] PanelContainer inventory; [Export] ResearchList researchList; [Export] TextureRect robotAlarm; [Export] RichTextLabel energyLabel; [Export] RichTextLabel waterLabel; [Export] RichTextLabel hungerLabel; [Export] RichTextLabel survivalStatus; [Export] RichTextLabel currentLayer; [Export] RichTextLabel deepestLayer; [Export] Button unlockLayer; [Export] PanelContainer gameOver; private bool receivedRobotJumpSignal = false; private bool receivedRobotFollowSignal = false; public override void _Ready() { UIStyle.Apply(this); robotList.OnRobotJumpTo += OnRobotJumpTo; robotList.OnRobotFollow += OnRobotFollow; } public override void _ExitTree() { robotList.OnRobotJumpTo -= OnRobotJumpTo; robotList.OnRobotFollow -= OnRobotFollow; } public override void _Process(double delta) { DisplayStats(); DisplayRobotAlarm(); Control focused = GetViewport().GuiGetFocusOwner(); if (focused is LineEdit || focused is TextEdit) return; if (Input.IsActionJustPressed("map")) HandleMapButton(); if (Input.IsActionJustPressed("menu")) HandleMenuButton(); if (Input.IsActionJustPressed("robot_list")) HandleRobotListButton(); if (Input.IsActionJustPressed("inventory")) HandleInventoryButton(); if (Input.IsActionJustPressed("research")) HandleResearchButton(); } public void HandleMenuButton() { if(GameData.survival.isDead) return; OpenUIElement(menu); GameData.isPaused = menu.Visible || options.Visible; } public void HandleMenu() { if(GameData.survival.isDead) return; HandleMenuButton(); } public void ShowOptions() { if(GameData.survival.isDead) return; menu.Hide(); OpenUIElement(options); GameData.isPaused = options.Visible; } public void HandleMapButton() { if(GameData.survival.isDead) return; OpenUIElement(map); if (map.Visible) map.ShowMap(); } public void HandleRobotListButton() { if(GameData.survival.isDead) return; receivedRobotFollowSignal = false; receivedRobotJumpSignal = false; OpenUIElement(robotList); } public void HandleInventoryButton() { if(GameData.survival.isDead) return; OpenUIElement(inventory); } public void HandleResearchButton() { if(GameData.survival.isDead) return; OpenUIElement(researchList); if (researchList.Visible) researchList.SetupGraph(); } public void DisplayStats() { FPS.Text = Engine.GetFramesPerSecond().ToString() + " FPS"; double memory = Process.GetCurrentProcess().WorkingSet64 / (1024 * 1024); string memoryDisplay = memory > 1024 ? Math.Round(memory / 1024, 2).ToString() + " GB" : memory.ToString() + " MB"; RAM.Text = memoryDisplay; DisplaySurvivalStats(); DisplayWorldStats(); DisplayLoseCondition(); } public void ExitGame() { GetTree().ChangeSceneToFile("res://Scenes/MainMenu.tscn"); } public void SaveGame() { SaveGameManager.SaveGame(); } public void LoadGame() { if (!SaveGameManager.SaveExists()) return; GameData.loadSaveOnStart = true; GetTree().ChangeSceneToFile("res://Scenes/Game.tscn"); } public void OpenUIElement(Control element) { SoundManager.PlayButton(); if (element.Visible) { element.Hide(); } else { element.Show(); } HideUIElements(element); } private void HideUIElements(Control element) { foreach (PanelContainer child in uiContent.GetChildren()) { if (child == element) continue; child.Visible = false; } if (element != menu && element != options) { GameData.isPaused = false; } } private void DisplayRobotAlarm() { string messages = ""; if (GameData.survival.isDead) { messages += GameData.survival.currentStatus + "\r"; } foreach (Robot robot in GameData.robots) { if (robot.currentMessage.Length > 0) { messages += $"{robot.Name}: {robot.currentMessage}\r"; } } robotAlarm.Visible = messages.Length > 0; robotAlarm.TooltipText = messages; } private void OnRobotJumpTo(Robot robot) { if (receivedRobotJumpSignal) return; receivedRobotJumpSignal = true; mainCam.Position = new Vector3(robot.Position.X, mainCam.Position.Y, robot.Position.Z + 3f); codingWindow.SetRobot(robot); OpenUIElement(codingWindow); } private void OnRobotFollow(Robot robot) { if (receivedRobotFollowSignal) return; receivedRobotFollowSignal = true; mainCam.Follow(robot); } private void DisplaySurvivalStats() { energyLabel.Text = $"Energy: {GameData.survival.energy:0}/{GameData.survival.maxEnergy:0}"; waterLabel.Text = $"Water: {GameData.survival.thirst:0}/{GameData.survival.maxThirst:0}"; hungerLabel.Text = $"Food: {GameData.survival.hunger:0}/{GameData.survival.maxHunger:0}"; survivalStatus.Text = GameData.survival.currentStatus; survivalStatus.Modulate = GameData.survival.currentStatus.Contains("critical") ? UIStyle.GetWarningColor() : Colors.White; if (GameData.survival.isDead) { ShowGameOver(); } } private void DisplayWorldStats() { currentLayer.Text = $"Layer: {GameData.currentLayer + 1}/{GameData.ruinSize}"; deepestLayer.Text = $"Gate depth: {GameData.lowestLayer}"; if (GameData.lowestLayer == GameData.ruinSize) { unlockLayer.Visible = false; return; } unlockLayer.TooltipText = "Gate requirements:\r" + GameData.map[GameData.lowestLayer].DisplayGateIngredients(); unlockLayer.Disabled = !GameData.inventory.CanCraft(GameData.map[GameData.lowestLayer].gateIngredients, 1); } private void DisplayLoseCondition() { if (!GameData.HasNoRobotRecovery()) return; ShowGameOver("No robots remain and no robot can be spawned from inventory."); } public void UnlockLayer() { if (GameData.inventory.CanCraft(GameData.map[GameData.lowestLayer].gateIngredients, 1)) { int openedLayer = GameData.lowestLayer; foreach (Ingredient ingredient in GameData.map[GameData.lowestLayer].gateIngredients) { GameData.inventory.RemoveItem(ingredient.Item, ingredient.Amount); } GameData.lowestLayer++; World world = GetNodeOrNull("/root/Main/World"); if (world != null) { world.OpenGate(openedLayer); } if (GameData.lowestLayer == GameData.ruinSize) { gameOver.Show(); } } } public void ShowGameOver() { ShowGameOver($"You died!\rReason: {GameData.survival.deathReason}\rBetter luck next time."); } public void ShowGameOver(string message) { if (gameOver.Visible) return; gameOver.GetNode("./VBoxContainer/Content").Text = $"[font_size=32]{message}\r"; gameOver.Show(); } public void HideGameOver() { gameOver.Hide(); } }