From 04ee449f74c599a87dc3ff22090b14dae4ec7adb Mon Sep 17 00:00:00 2001 From: Samuel Bouchet Date: Fri, 13 Mar 2026 23:42:51 +0100 Subject: [PATCH] Localize loot rarity, material forms, compact footer, rapid consume, meta descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Localize rarity labels in loot reveal and event log (Commun, Rare, Épique…) - Add localized material form names (Lingot, Planche, Poudre, Gemme…) - Show category summary footer in compact inventory (📦3 🧪5 📜2 👗12 🔩8) - Remove WaitForKeyPress after consuming items for rapid multi-use - Add description keys for all 14 meta items explaining their unlocked feature --- content/data/items.json | 28 +++---- content/strings/en.json | 27 ++++++- content/strings/fr.json | 27 ++++++- src/OpenTheBox/Program.cs | 4 +- .../Rendering/Panels/InventoryPanel.cs | 15 +++- src/OpenTheBox/Rendering/SpectreRenderer.cs | 9 ++- suggestions_3.md | 78 +++++++++++++++++++ 7 files changed, 166 insertions(+), 22 deletions(-) create mode 100644 suggestions_3.md diff --git a/content/data/items.json b/content/data/items.json index 115760b..6a18a9d 100644 --- a/content/data/items.json +++ b/content/data/items.json @@ -1,17 +1,17 @@ [ - {"id": "meta_colors", "nameKey": "meta.colors", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "TextColors"}, - {"id": "meta_extended_colors", "nameKey": "meta.extended_colors", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "ExtendedColors"}, - {"id": "meta_arrows", "nameKey": "meta.arrows", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "ArrowKeySelection"}, - {"id": "meta_inventory", "nameKey": "meta.inventory", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "InventoryPanel"}, - {"id": "meta_resources", "nameKey": "meta.resources", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "ResourcePanel"}, - {"id": "meta_stats", "nameKey": "meta.stats", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "StatsPanel"}, - {"id": "meta_portrait", "nameKey": "meta.portrait", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "PortraitPanel"}, - {"id": "meta_chat", "nameKey": "meta.chat", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "ChatPanel"}, - {"id": "meta_layout", "nameKey": "meta.layout", "category": "Meta", "rarity": "Legendary", "tags": ["Meta"], "metaUnlock": "FullLayout"}, - {"id": "meta_shortcuts", "nameKey": "meta.shortcuts", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "KeyboardShortcuts"}, - {"id": "meta_animation", "nameKey": "meta.animation", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta"], "metaUnlock": "BoxAnimation"}, - {"id": "meta_crafting", "nameKey": "meta.crafting", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "CraftingPanel"}, - {"id": "meta_autosave", "nameKey": "meta.autosave", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta"], "metaUnlock": "AutoSave"}, + {"id": "meta_colors", "nameKey": "meta.colors", "descriptionKey": "meta.colors.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "TextColors"}, + {"id": "meta_extended_colors", "nameKey": "meta.extended_colors", "descriptionKey": "meta.extended_colors.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "ExtendedColors"}, + {"id": "meta_arrows", "nameKey": "meta.arrows", "descriptionKey": "meta.arrows.desc", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "ArrowKeySelection"}, + {"id": "meta_inventory", "nameKey": "meta.inventory", "descriptionKey": "meta.inventory.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "InventoryPanel"}, + {"id": "meta_resources", "nameKey": "meta.resources", "descriptionKey": "meta.resources.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "ResourcePanel"}, + {"id": "meta_stats", "nameKey": "meta.stats", "descriptionKey": "meta.stats.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "StatsPanel"}, + {"id": "meta_portrait", "nameKey": "meta.portrait", "descriptionKey": "meta.portrait.desc", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "PortraitPanel"}, + {"id": "meta_chat", "nameKey": "meta.chat", "descriptionKey": "meta.chat.desc", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "ChatPanel"}, + {"id": "meta_layout", "nameKey": "meta.layout", "descriptionKey": "meta.layout.desc", "category": "Meta", "rarity": "Legendary", "tags": ["Meta"], "metaUnlock": "FullLayout"}, + {"id": "meta_shortcuts", "nameKey": "meta.shortcuts", "descriptionKey": "meta.shortcuts.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "KeyboardShortcuts"}, + {"id": "meta_animation", "nameKey": "meta.animation", "descriptionKey": "meta.animation.desc", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta"], "metaUnlock": "BoxAnimation"}, + {"id": "meta_crafting", "nameKey": "meta.crafting", "descriptionKey": "meta.crafting.desc", "category": "Meta", "rarity": "Epic", "tags": ["Meta"], "metaUnlock": "CraftingPanel"}, + {"id": "meta_autosave", "nameKey": "meta.autosave", "descriptionKey": "meta.autosave.desc", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta"], "metaUnlock": "AutoSave"}, {"id": "meta_resource_health", "nameKey": "resource.health", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta", "ResourceVisibility"], "resourceType": "Health"}, {"id": "meta_resource_mana", "nameKey": "resource.mana", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta", "ResourceVisibility"], "resourceType": "Mana"}, {"id": "meta_resource_food", "nameKey": "resource.food", "category": "Meta", "rarity": "Uncommon", "tags": ["Meta", "ResourceVisibility"], "resourceType": "Food"}, @@ -160,7 +160,7 @@ {"id": "music_melody", "nameKey": "item.music_melody", "category": "Consumable", "rarity": "Rare", "tags": ["Music", "Fun"], "description": "A melody plays from the box. Console.Beep never sounded so good."}, {"id": "cookie_fortune", "nameKey": "item.cookie_fortune", "category": "Consumable", "rarity": "Common", "tags": ["Cookie", "Fun"], "description": "A fortune cookie with wisdom of questionable origin."}, - {"id": "meta_completion", "nameKey": "meta.completion", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "CompletionTracker"}, + {"id": "meta_completion", "nameKey": "meta.completion", "descriptionKey": "meta.completion.desc", "category": "Meta", "rarity": "Rare", "tags": ["Meta"], "metaUnlock": "CompletionTracker"}, {"id": "endgame_crown", "nameKey": "item.endgame_crown", "category": "Cosmetic", "rarity": "Mythic", "tags": ["Cosmetic", "Endgame"], "cosmeticSlot": "Hair", "cosmeticValue": "crown"}, {"id": "destiny_token", "nameKey": "item.destiny_token", "category": "AdventureToken", "rarity": "Mythic", "tags": ["Adventure", "Endgame"], "adventureTheme": "Destiny"}, diff --git a/content/strings/en.json b/content/strings/en.json index 3414900..4632fb2 100644 --- a/content/strings/en.json +++ b/content/strings/en.json @@ -486,5 +486,30 @@ "rarity.rare": "Rare", "rarity.epic": "Epic", "rarity.legendary": "Legendary", - "rarity.mythic": "Mythic" + "rarity.mythic": "Mythic", + + "meta.colors.desc": "Unlocks colored text in the terminal.", + "meta.extended_colors.desc": "More colors! More variety!", + "meta.arrows.desc": "Navigate menus with arrow keys instead of typing numbers.", + "meta.inventory.desc": "Shows a panel listing all your items.", + "meta.resources.desc": "Displays your resources (health, mana, etc.).", + "meta.stats.desc": "Shows your character statistics.", + "meta.portrait.desc": "Displays your character's visual appearance.", + "meta.chat.desc": "Shows an event log of recent actions.", + "meta.layout.desc": "Arranges all panels into a full dashboard layout.", + "meta.shortcuts.desc": "Enables keyboard shortcuts for quick actions.", + "meta.animation.desc": "Adds opening animations when unboxing.", + "meta.crafting.desc": "Shows the crafting panel and active jobs.", + "meta.autosave.desc": "Your game saves automatically. No more lost progress!", + "meta.completion.desc": "Tracks your overall game completion percentage.", + + "material.form.raw": "Raw", + "material.form.refined": "Refined", + "material.form.nail": "Nail", + "material.form.plank": "Plank", + "material.form.ingot": "Ingot", + "material.form.sheet": "Sheet", + "material.form.thread": "Thread", + "material.form.dust": "Dust", + "material.form.gem": "Gem" } diff --git a/content/strings/fr.json b/content/strings/fr.json index 56901b8..f5ca25b 100644 --- a/content/strings/fr.json +++ b/content/strings/fr.json @@ -486,5 +486,30 @@ "rarity.rare": "Rare", "rarity.epic": "Épique", "rarity.legendary": "Légendaire", - "rarity.mythic": "Mythique" + "rarity.mythic": "Mythique", + + "meta.colors.desc": "Débloque les couleurs de texte dans le terminal.", + "meta.extended_colors.desc": "Plus de couleurs ! Plus de variété !", + "meta.arrows.desc": "Navigue dans les menus avec les flèches au lieu de taper des chiffres.", + "meta.inventory.desc": "Affiche un panneau listant tous tes objets.", + "meta.resources.desc": "Affiche tes ressources (santé, mana, etc.).", + "meta.stats.desc": "Affiche les statistiques de ton personnage.", + "meta.portrait.desc": "Affiche l'apparence visuelle de ton personnage.", + "meta.chat.desc": "Affiche un journal des événements récents.", + "meta.layout.desc": "Organise tous les panneaux en tableau de bord complet.", + "meta.shortcuts.desc": "Active les raccourcis clavier pour des actions rapides.", + "meta.animation.desc": "Ajoute des animations d'ouverture de boîtes.", + "meta.crafting.desc": "Affiche le panneau d'artisanat et les travaux en cours.", + "meta.autosave.desc": "Ta partie se sauvegarde automatiquement. Plus de progression perdue !", + "meta.completion.desc": "Suit ton pourcentage de complétion du jeu.", + + "material.form.raw": "Brut", + "material.form.refined": "Raffiné", + "material.form.nail": "Clou", + "material.form.plank": "Planche", + "material.form.ingot": "Lingot", + "material.form.sheet": "Feuille", + "material.form.thread": "Fil", + "material.form.dust": "Poudre", + "material.form.gem": "Gemme" } diff --git a/src/OpenTheBox/Program.cs b/src/OpenTheBox/Program.cs index 7a88d70..5d891aa 100644 --- a/src/OpenTheBox/Program.cs +++ b/src/OpenTheBox/Program.cs @@ -573,7 +573,7 @@ public static class Program // Proposal 6A: Feed loot to the event log foreach (var (name, rarity, _) in allLoot) - AddEventLog($"+ {name} [{rarity}]"); + AddEventLog($"+ {name} [{_loc.Get($"rarity.{rarity.ToLower()}")}]"); // Proposal 4: Show inline resource summary when ResourcePanel is not unlocked if (!_renderContext.HasResourcePanel && _state.Resources.Count > 0) @@ -703,7 +703,7 @@ public static class Program break; } } - _renderer.WaitForKeyPress(_loc.Get("prompt.press_key")); + // No WaitForKeyPress — return to inventory immediately for rapid consumption break; case ItemCategory.LoreFragment: diff --git a/src/OpenTheBox/Rendering/Panels/InventoryPanel.cs b/src/OpenTheBox/Rendering/Panels/InventoryPanel.cs index e6faf31..ad19c42 100644 --- a/src/OpenTheBox/Rendering/Panels/InventoryPanel.cs +++ b/src/OpenTheBox/Rendering/Panels/InventoryPanel.cs @@ -209,6 +209,17 @@ public static class InventoryPanel table.AddRow($"[dim]{Markup.Escape(emptyText)}[/]", "", "", ""); } + // In compact mode, add a summary footer showing count per category + if (compact && totalItems > maxRows) + { + var summary = grouped + .GroupBy(g => g.Category) + .OrderBy(g => CategorySortOrder(g.Key)) + .Select(g => $"{CategoryIcon(g.Key)}{g.Count()}") + .ToArray(); + table.AddRow($"[dim]{string.Join(" ", summary)}[/]", "", "", $"[dim]{totalItems}[/]"); + } + // Build header with scroll indicator string headerText = loc?.Get("ui.inventory") ?? "Inventory"; string header; @@ -307,7 +318,9 @@ public static class InventoryPanel break; case ItemCategory.Material when item.Def?.MaterialType is not null: - rows.Add(new Markup($"[dim]{Markup.Escape(item.Def.MaterialType.Value.ToString())} ({Markup.Escape(item.Def.MaterialForm?.ToString() ?? "Raw")})[/]")); + string matType = loc?.Get($"material.{item.Def.MaterialType.Value.ToString().ToLower()}") ?? item.Def.MaterialType.Value.ToString(); + string matForm = loc?.Get($"material.form.{(item.Def.MaterialForm ?? MaterialForm.Raw).ToString().ToLower()}") ?? item.Def.MaterialForm?.ToString() ?? "Raw"; + rows.Add(new Markup($"[dim]{Markup.Escape(matType)} ({Markup.Escape(matForm)})[/]")); break; } diff --git a/src/OpenTheBox/Rendering/SpectreRenderer.cs b/src/OpenTheBox/Rendering/SpectreRenderer.cs index 1bc87a4..8cc1e4a 100644 --- a/src/OpenTheBox/Rendering/SpectreRenderer.cs +++ b/src/OpenTheBox/Rendering/SpectreRenderer.cs @@ -89,9 +89,10 @@ public sealed class SpectreRenderer : IRenderer foreach (var (name, rarity, category) in items) { string color = RarityColor(rarity); + string localizedRarity = _loc.Get($"rarity.{rarity.ToLower()}"); table.AddRow( $"[{color}]{Markup.Escape(name)}[/]", - $"[{color}]{Markup.Escape(rarity)}[/]"); + $"[{color}]{Markup.Escape(localizedRarity)}[/]"); } AnsiConsole.Write(table); @@ -102,7 +103,8 @@ public sealed class SpectreRenderer : IRenderer foreach (var (name, rarity, category) in items) { string color = RarityColor(rarity); - AnsiConsole.MarkupLine($" - [{color}]{Markup.Escape(name)}[/] [{color}][[{Markup.Escape(rarity)}]][/]"); + string localizedRarity = _loc.Get($"rarity.{rarity.ToLower()}"); + AnsiConsole.MarkupLine($" - [{color}]{Markup.Escape(name)}[/] [{color}][[{Markup.Escape(localizedRarity)}]][/]"); } } else @@ -110,7 +112,8 @@ public sealed class SpectreRenderer : IRenderer Console.WriteLine(_loc.Get("loot.received")); foreach (var (name, rarity, category) in items) { - Console.WriteLine($" - {name} [{rarity}]"); + string localizedRarity = _loc.Get($"rarity.{rarity.ToLower()}"); + Console.WriteLine($" - {name} [{localizedRarity}]"); } } } diff --git a/suggestions_3.md b/suggestions_3.md new file mode 100644 index 0000000..d3bdb92 --- /dev/null +++ b/suggestions_3.md @@ -0,0 +1,78 @@ +# Suggestions d'amélioration #3 + +Basées sur l'analyse des rendus PlaythroughCapture et InventoryRenderCapture après suggestions_2. + +| # | Suggestion | Priorité | Statut | +|---|-----------|----------|--------| +| 1 | Loot reveal : afficher la rareté localisée | ★★★★★ | ✅ DONE | +| 2 | Matériaux : afficher le nom de forme localisé | ★★★★★ | ✅ DONE | +| 3 | Inventaire compact avec résumé catégories en footer | ★★★★☆ | ✅ DONE | +| 4 | Multi-use consommables : consommer en lot sans quitter l'inventaire | ★★★★☆ | ✅ DONE | +| 5 | Panneau de détail Meta : expliquer le feature débloqué | ★★★★☆ | ✅ DONE | +| 6 | Panneau "???" localisé dans le FullLayout | ★★★☆☆ | | +| 7 | Compteur de boîtes dans l'en-tête du loot reveal | ★★★☆☆ | | +| 8 | Tronquer le nom "Potion de Santé Moyenne" qui casse le tableau | ★★★☆☆ | | +| 9 | Indicateur visuel des ressources modifiées lors du loot | ★★☆☆☆ | | +| 10 | Feedback sonore optionnel pour les items rares+ | ★★☆☆☆ | | + +--- + +## 1. Loot reveal : afficher la rareté localisée — ★★★★★ + +**Constat** : Dans `ShowLootReveal`, la rareté affichée est le nom enum brut anglais (`Common`, `Uncommon`, `Rare`), pas la version localisée. Incohérent avec l'inventaire qui est maintenant localisé. + +**Solution** : Localiser la rareté dans `RenderEvents` avant de l'envoyer au loot reveal, ou dans `ShowLootReveal` directement. + +## 2. Matériaux : afficher le nom de forme localisé — ★★★★★ + +**Constat** : Dans le panneau de détails des matériaux, on voit "Bronze (Ingot)" avec le nom de forme en anglais. Il devrait être localisé ("Lingot"). + +**Solution** : Ajouter des clés de localisation `material.form.raw`, `material.form.ingot`, `material.form.sheet`, etc. + +## 3. Inventaire compact avec résumé catégories en footer — ★★★★☆ + +**Constat** : En mode compact (FullLayout), seuls 6 items sont visibles et on ne sait pas combien d'items de chaque catégorie on possède. + +**Solution** : Ajouter une ligne de pied résumant les catégories : "📦3 🧪5 📜2 👗12 🔩8". + +## 4. Multi-use consommables — ★★★★☆ + +**Constat** : Pour utiliser 5 potions de santé, il faut faire Entrée → message → touche → Entrée → message → touche × 5. C'est fastidieux. + +**Solution** : Après avoir utilisé un consommable, si il en reste, revenir automatiquement à l'inventaire sans quitter. Le joueur peut continuer à appuyer sur Entrée ou naviguer ailleurs. + +## 5. Panneau de détail Meta : expliquer le feature débloqué — ★★★★☆ + +**Constat** : Les items Meta ("Couleurs de texte", "Panneau de statistiques") n'ont aucune description dans le panneau de détails. + +**Solution** : Ajouter des `descriptionKey` dans items.json pour tous les meta items et les localiser. + +## 6. Panneau "???" localisé dans le FullLayout — ★★★☆☆ + +**Constat** : Les panneaux non encore débloqués dans le FullLayout affichent "[dim]???[/]" avec des headers anglais "Stats", "Resources", "Inventory". + +**Solution** : Utiliser les clés de localisation existantes pour ces headers. + +## 7. Compteur de boîtes dans l'en-tête du loot reveal — ★★★☆☆ + +**Constat** : La table de loot n'indique pas combien de boîtes le joueur a ouvertes au total. + +**Solution** : Ajouter le compteur dans le titre du loot reveal. + +## 8. Tronquer le nom "Potion de Santé Moyenne" — ★★★☆☆ + +**Constat** : Le nom "Potion de Santé Moyenne" déborde sur 2 lignes dans la table d'inventaire, ce qui casse l'alignement. + +**Solution** : La troncature à MaxNameWidth existe déjà (24 chars) mais le nom fait exactement 24 chars et n'est pas tronqué. Vérifier/ajuster le padding avec l'indicateur "►" et le préfixe " ". + +## 9. Indicateur visuel des ressources lors du loot — ★★☆☆☆ + +**Constat** : Quand un loot contient des consommables qui pourraient être utiles, le joueur ne voit pas l'état de ses ressources. + +**Solution** : Optionnellement afficher un mini-résumé des ressources après le loot. + +## 10. Feedback sonore pour items rares+ — ★★☆☆☆ + +**Constat** : Tous les items apparaissent de la même façon dans le loot, pas de feedback distinct pour les items rares. + +**Solution** : Console.Beep optionnel pour les Rare+ sur Windows.