rpg_walk: save, main menu, load; action card texts are translated
Covers the empty dialog box after loading a save and the untranslated action cards in battle. Docs: the world is built from engine mods, not a novel engine.
This commit is contained in:
1 parent
5c399b150d
commit
002cd09495
4 files changed
+43
-3
No files matched your search
+1
-1
@@ -3,7 +3,7 @@
|
||||
"name": "RPG World",
|
||||
"version": "1.0.0",
|
||||
"author": "ct",
|
||||
"description": "Top-down tile world in the spirit of RPG Maker on top of the novel engine: maps of square tiles in three layers (back, main, front) with a collision layer, walking on the grid with WASD or the arrows, events that talk, teleport or start battles with the action key E/F or on touch, random encounters. A map is a logical scene, so entry scenarios, ambience, saving and the dialog box work on maps unchanged; battles run on the turn-based platform with the game's battle core and return to the same cell. Scenario actions: rpg.battle, rpg.teleport.",
|
||||
"description": "Top-down tile world in the spirit of RPG Maker on top of the 2D engine mods: maps of square tiles in three layers (back, main, front) with a collision layer, walking on the grid with WASD or the arrows, events that talk, teleport or start battles with the action key E/F or on touch, random encounters. A map is a logical scene, so entry scenarios, ambience, saving and the dialog box work on maps unchanged; battles run on the turn-based platform with the game's battle core and return to the same cell. Scenario actions: rpg.battle, rpg.teleport.",
|
||||
"category": "gameplay",
|
||||
"sources": [
|
||||
"src/**/*.cs"
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ namespace Cthangover.Mods.Rpg
|
||||
/// scene that shows it: entering scene <c>X</c> (any <c>switch_scene X</c>, a
|
||||
/// teleport, the return from a battle, loading a save) mounts map <c>X</c>
|
||||
/// over the shell. Because the scene stays an ordinary scene, everything the
|
||||
/// novel engine attaches to scenes works on a map unchanged — entry
|
||||
/// engine attaches to scenes works on a map unchanged — entry
|
||||
/// scenarios, ambience and music from <c>scenes/X.json</c>, the default
|
||||
/// background (which also becomes the backdrop of battles started here),
|
||||
/// saving rules.
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Cthangover.Mods.Rpg
|
||||
/// It follows the scene lifecycle: entering a scene whose name is a map id
|
||||
/// mounts that map (<see cref="RpgWorldView"/>) and shows the dark backdrop;
|
||||
/// any other scene leaves the host empty and invisible, so a game can mix
|
||||
/// novel scenes and map scenes freely. The shell is rebuilt after battles,
|
||||
/// picture-and-dialogue scenes and map scenes freely. The shell is rebuilt after battles,
|
||||
/// so the host is too; the position survives in <see cref="RpgState"/>.
|
||||
/// <para/>
|
||||
/// <see cref="Current"/> is the host of the live shell, used by teleports
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Cthangover.Core.Battle;
|
||||
using Cthangover.Core.Bootstrap;
|
||||
using Cthangover.Core.Characters;
|
||||
using Cthangover.Core.Factories.Impls;
|
||||
using Cthangover.Core.Games;
|
||||
using Cthangover.Core.Scenes;
|
||||
using Cthangover.Core.Settings;
|
||||
using Cthangover.Core.Utils;
|
||||
@@ -26,6 +29,7 @@ namespace Cthangover.Mods.Rpg.Tests
|
||||
private const string Village = "rpg_village";
|
||||
private const string House = "rpg_elder_house";
|
||||
private const string WinFlag = "rpg_test_win";
|
||||
private const string SaveSlot = "slot_9901";
|
||||
|
||||
private readonly string shotsDir;
|
||||
private readonly List<string> failures = new();
|
||||
@@ -83,6 +87,7 @@ namespace Cthangover.Mods.Rpg.Tests
|
||||
return;
|
||||
Check(GameData.Instance.Runtime.CharacterData.Characters.ContainsKey("rpg_hero"), "party.add put the hero into the party");
|
||||
Check(View.Player.Cell == new Vector2I(15, 14), $"player at the spawn (15,14), got {View.Player.Cell}");
|
||||
CheckActionTexts();
|
||||
Shot("village");
|
||||
Press(Key.W, true);
|
||||
Next();
|
||||
@@ -188,11 +193,46 @@ namespace Cthangover.Mods.Rpg.Tests
|
||||
Godot.Engine.TimeScale = 1;
|
||||
Check(View.Player.Cell == new Vector2I(6, 8), $"the battle returns to the same cell, got {View.Player.Cell}");
|
||||
Check(GameData.Instance.Runtime.Flags.TryGetValue(WinFlag, out var won) && won == "1", "the win flag is set after the victory");
|
||||
// The menu's path: save in the game, go to the main menu, load.
|
||||
SaveService.Save(SaveSlot);
|
||||
GameSession.OpenMainMenu(GetTree());
|
||||
Next();
|
||||
return;
|
||||
case 16:
|
||||
if (RpgWorldHost.Current != null || ++waitTicks < 5)
|
||||
return;
|
||||
Check(GameSession.LoadAndEnter(this, SaveSlot), "the save loads");
|
||||
Next();
|
||||
return;
|
||||
case 17:
|
||||
if (View?.Map?.ID != House || GodotSceneService.IsTransitioning || ++waitTicks < 5)
|
||||
return;
|
||||
Shot("loaded");
|
||||
var dialog = RpgInput.FindDialogBox();
|
||||
Check(dialog != null && !dialog.IsRunning && !dialog.IsVisibleInTree(), $"no dialog box after loading (running={dialog?.IsRunning}, visible={dialog?.IsVisibleInTree()})");
|
||||
Check(View.Player.Cell == new Vector2I(6, 8), $"the loaded game puts the player on the saved cell, got {View.Player.Cell}");
|
||||
SaveService.DeleteSave(SaveSlot);
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The battle shows the names and descriptions of the hero's action cards:
|
||||
/// their keys must be translated by a mod of this game, not only by
|
||||
/// another game's content mod.
|
||||
/// </summary>
|
||||
private void CheckActionTexts()
|
||||
{
|
||||
var hero = CharacterFactory.Instance.Get("rpg_hero");
|
||||
Check(hero?.Actions?.Count > 0, "the hero has action cards");
|
||||
foreach (var action in hero?.Actions ?? new List<ActionCharacter>())
|
||||
{
|
||||
foreach (var key in new[] { action.Name, action.Description })
|
||||
Check(!string.IsNullOrEmpty(key) && TranslationServer.Translate(key) != key, $"action text '{key}' is translated");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Advances a running dialog with the action key; true while it is still running.</summary>
|
||||
private bool AdvanceDialog()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user