diff --git a/src/OpenTheBox.Web/WebGameHost.cs b/src/OpenTheBox.Web/WebGameHost.cs index aa1627d..f2b7ce6 100644 --- a/src/OpenTheBox.Web/WebGameHost.cs +++ b/src/OpenTheBox.Web/WebGameHost.cs @@ -1115,28 +1115,44 @@ public sealed class WebGameHost private async Task RenderFullLayout() { + // Top row: Stats (30) | Resources (30) | Completion (60) — total 120 var topRow = new Table().NoBorder().HideHeaders().Expand(); - topRow.AddColumn(new TableColumn("c1").Width(20).NoWrap()); - topRow.AddColumn(new TableColumn("c2").Width(30).NoWrap()); - topRow.AddColumn(new TableColumn("c3").NoWrap()); + topRow.AddColumn(new TableColumn("c1").Width(30)); + topRow.AddColumn(new TableColumn("c2").Width(30)); + topRow.AddColumn(new TableColumn("c3").Width(60)); - topRow.AddRow( - _renderContext.HasPortraitPanel - ? PortraitPanel.Render(_state.Appearance, useColors: _renderContext.HasColors) - : new Panel("[dim]?[/]").Header("Portrait").Expand(), - _renderContext.HasStatsPanel - ? StatsPanel.Render(_state, _loc) - : new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.stats"))}[/]").Header("Stats").Expand(), - _renderContext.HasResourcePanel - ? ResourcePanel.Render(_state, _loc) - : new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.resources"))}[/]") - .Header(Markup.Escape(_loc.Get("resource.title"))).Expand()); + IRenderable statsPanel = _renderContext.HasStatsPanel + ? StatsPanel.Render(_state, _loc) + : new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.stats"))}[/]").Header("Stats").Expand(); + IRenderable resourcePanel = _renderContext.HasResourcePanel + ? ResourcePanel.Render(_state, _loc, barWidth: 8) + : new Panel($"[dim italic]{Markup.Escape(_loc.Get("panel.locked.resources"))}[/]") + .Header(Markup.Escape(_loc.Get("resource.title"))).Expand(); + + var completionItems = new List(); + if (_renderContext.HasCompletionTracker) + { + // Compact: single line with percent + hint joined + string completionLine = _loc.Get("ui.completion", _renderContext.CompletionPercent); + if (_renderContext.NextHints.Count > 0) + completionLine += " — " + _renderContext.NextHints[0]; + completionItems.Add(new Markup($"[bold cyan]{Markup.Escape(completionLine)}[/]")); + // Additional hints on separate lines + for (int i = 1; i < _renderContext.NextHints.Count; i++) + completionItems.Add(new Markup($" [dim]{Markup.Escape(_renderContext.NextHints[i])}[/]")); + } + IRenderable completionPanel = completionItems.Count > 0 + ? new Rows(completionItems) + : new Text(""); + + topRow.AddRow(statsPanel, resourcePanel, completionPanel); await _terminal.WriteRenderableAsync(topRow); + // Bottom row: Inventory (60) | Portrait + Crafting (60) — total 120 var botRow = new Table().NoBorder().HideHeaders().Expand(); - botRow.AddColumn(new TableColumn("c1").Width(60).NoWrap()); - botRow.AddColumn(new TableColumn("c2").NoWrap()); + botRow.AddColumn(new TableColumn("c1").Width(60)); + botRow.AddColumn(new TableColumn("c2").Width(60)); IRenderable leftPanel = _renderContext.HasInventoryPanel ? InventoryPanel.Render(_state, _registry, _loc, compact: true) @@ -1144,20 +1160,14 @@ public sealed class WebGameHost .Header("Inventory").Expand(); var rightItems = new List(); + if (_renderContext.HasPortraitPanel) + rightItems.Add(PortraitPanel.Render(_state.Appearance, useColors: _renderContext.HasColors)); + else + rightItems.Add(new Panel("[dim]?[/]").Header("Portrait").Expand()); if (_renderContext.HasCraftingPanel) rightItems.Add(CraftingPanel.Render(_state, _registry, _loc)); - if (_renderContext.HasCompletionTracker) - { - rightItems.Add(new Markup($"[bold cyan]{Markup.Escape(_loc.Get("ui.completion", _renderContext.CompletionPercent))}[/]")); - foreach (var hint in _renderContext.NextHints) - rightItems.Add(new Markup($" [dim]{Markup.Escape(hint)}[/]")); - } - IRenderable rightPanel = rightItems.Count > 0 - ? new Rows(rightItems) - : new Panel("[dim]???[/]").Header("???").Expand(); - - botRow.AddRow(leftPanel, rightPanel); + botRow.AddRow(leftPanel, new Rows(rightItems)); await _terminal.WriteRenderableAsync(botRow); } diff --git a/src/OpenTheBox.Web/wwwroot/index.html b/src/OpenTheBox.Web/wwwroot/index.html index 4f0110c..6cacee0 100644 --- a/src/OpenTheBox.Web/wwwroot/index.html +++ b/src/OpenTheBox.Web/wwwroot/index.html @@ -4,7 +4,7 @@ Open The Box - + @@ -19,8 +19,8 @@
- - + + diff --git a/src/OpenTheBox/Rendering/Panels/ResourcePanel.cs b/src/OpenTheBox/Rendering/Panels/ResourcePanel.cs index d274ccc..445346a 100644 --- a/src/OpenTheBox/Rendering/Panels/ResourcePanel.cs +++ b/src/OpenTheBox/Rendering/Panels/ResourcePanel.cs @@ -15,7 +15,7 @@ public static class ResourcePanel /// Builds a renderable resource display from the current game state. /// Only resources present in are shown. /// - public static IRenderable Render(GameState state, LocalizationManager? loc = null) + public static IRenderable Render(GameState state, LocalizationManager? loc = null, int barWidth = 20) { var rows = new List(); @@ -29,7 +29,6 @@ public static class ResourcePanel int max = resource.Max; // Build a text-based bar: [####----] 40/100 - int barWidth = 20; int filled = max > 0 ? (int)Math.Round((double)current / max * barWidth) : 0; filled = Math.Clamp(filled, 0, barWidth); int empty = barWidth - filled; @@ -55,7 +54,7 @@ public static class ResourcePanel private static string GetResourceColor(ResourceType type) => type switch { ResourceType.Gold => "gold1", - ResourceType.Blood => "red", + ResourceType.Ink => "red", _ => "silver" }; }