Skip to content

Commit 7ad22e5

Browse files
authored
Test for OpenEnroth#2116 & some cleanup in EngineController (OpenEnroth#2264)
* Activate characters in tests with key presses * Added a test for OpenEnroth#2116
1 parent eba4309 commit 7ad22e5

File tree

5 files changed

+107
-32
lines changed

5 files changed

+107
-32
lines changed

src/Engine/Components/Control/EngineController.cpp

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include "Library/FileSystem/Memory/MemoryFileSystem.h"
2828
#include "Library/Platform/Application/PlatformApplication.h"
29+
#include "Library/Platform/Interface/PlatformEnumFunctions.h"
2930
#include "Library/Platform/Interface/PlatformEvents.h"
3031

3132
#include "Utility/Exception.h"
@@ -149,38 +150,23 @@ void EngineController::pressGuiButton(std::string_view buttonId) {
149150
}
150151

151152
void EngineController::goToGame() {
152-
ThrowingTicker ticker(this, "Couldn't return to game");
153-
154-
// Skip movies.
155-
while (current_screen_type == SCREEN_VIDEO) {
156-
pressAndReleaseKey(PlatformKey::KEY_ESCAPE);
157-
ticker.tick();
158-
}
159-
160-
// Can't always leave key settings menu by pressing ESC, so need custom handling.
161-
if (current_screen_type == SCREEN_KEYBOARD_OPTIONS) {
162-
pressGuiButton("KeyBinding_Default");
163-
ticker.tick();
164-
}
165-
166-
// Leave to game screen if we're in the game, or to main menu if we're in menus.
167-
while (current_screen_type != SCREEN_GAME && GetCurrentMenuID() != MENU_MAIN) {
168-
pressAndReleaseKey(PlatformKey::KEY_ESCAPE);
169-
ticker.tick(2); // Somehow tick(1) is not enough when we're trying to leave the game loading menu.
170-
}
171-
172-
// If game is starting up - wait for main menu to appear.
173-
while (GetCurrentMenuID() == MENU_MAIN && lWindowList.empty())
174-
ticker.tick();
153+
goToGameOrMainMenu();
154+
if (GetCurrentMenuID() == MENU_MAIN)
155+
throw Exception("Can't go to game from the main menu");
175156
}
176157

177158
void EngineController::goToInventory(int characterIndex) {
159+
assert(characterIndex >= 1 && characterIndex <= 4);
160+
178161
goToGame();
179162

180-
if (GetCurrentMenuID() != MENU_NONE)
181-
throw Exception("Can't go to inventory from the main menu");
163+
if (pParty->activeCharacterIndex() != characterIndex) {
164+
pressAndReleaseKey(platformKeyForDigit(characterIndex));
165+
tick(1);
166+
if (pParty->activeCharacterIndex() != characterIndex)
167+
throw Exception("Couldn't activate character #{}", characterIndex);
168+
}
182169

183-
pParty->setActiveCharacterIndex(characterIndex);
184170
pressAndReleaseKey(PlatformKey::KEY_I);
185171
tick(2); // Need two ticks for inventory to be shown.
186172

@@ -189,14 +175,13 @@ void EngineController::goToInventory(int characterIndex) {
189175
}
190176

191177
void EngineController::goToMainMenu() {
192-
ThrowingTicker ticker(this, "Couldn't return to main menu");
193-
194-
goToGame();
195-
178+
goToGameOrMainMenu();
196179
if (GetCurrentMenuID() == MENU_MAIN)
197180
return;
198181
assert(GetCurrentMenuID() == MENU_NONE);
199182

183+
ThrowingTicker ticker(this, "Couldn't return to main menu");
184+
200185
// Go to in-game menu.
201186
while (current_screen_type != SCREEN_MENU) {
202187
pressAndReleaseKey(PlatformKey::KEY_ESCAPE);
@@ -343,15 +328,22 @@ void EngineController::teleportTo(MapId map, Vec3f position, int viewYaw) {
343328
}
344329

345330
void EngineController::castSpell(int characterIndex, SpellId spell) {
346-
goToGame();
331+
assert(characterIndex >= 1 && characterIndex <= 4);
347332

333+
goToGame();
348334
if (GetCurrentMenuID() != MENU_NONE)
349335
throw Exception("Can't cast a spell from the main menu");
350336

337+
if (pParty->activeCharacterIndex() != characterIndex) {
338+
pressAndReleaseKey(platformKeyForDigit(characterIndex));
339+
tick(1);
340+
if (pParty->activeCharacterIndex() != characterIndex)
341+
throw Exception("Couldn't activate character #{}", characterIndex);
342+
}
343+
351344
MagicSchool school = magicSchoolForSpell(spell);
352345
int index = spellIndexInMagicSchool(spell);
353346

354-
pParty->setActiveCharacterIndex(characterIndex);
355347
pressGuiButton("Game_CastSpell");
356348
tick(1);
357349
pressGuiButton(fmt::format("SpellBook_School{}", std::to_underlying(school)));
@@ -362,6 +354,32 @@ void EngineController::castSpell(int characterIndex, SpellId spell) {
362354
tick(1);
363355
}
364356

357+
void EngineController::goToGameOrMainMenu() {
358+
ThrowingTicker ticker(this, "Couldn't return to game");
359+
360+
// Skip movies.
361+
while (current_screen_type == SCREEN_VIDEO) {
362+
pressAndReleaseKey(PlatformKey::KEY_ESCAPE);
363+
ticker.tick();
364+
}
365+
366+
// Can't always leave key settings menu by pressing ESC, so need custom handling.
367+
if (current_screen_type == SCREEN_KEYBOARD_OPTIONS) {
368+
pressGuiButton("KeyBinding_Default");
369+
ticker.tick();
370+
}
371+
372+
// Leave to game screen if we're in the game, or to main menu if we're in menus.
373+
while (current_screen_type != SCREEN_GAME && GetCurrentMenuID() != MENU_MAIN) {
374+
pressAndReleaseKey(PlatformKey::KEY_ESCAPE);
375+
ticker.tick(2); // Somehow tick(1) is not enough when we're trying to leave the game loading menu.
376+
}
377+
378+
// If game is starting up - wait for main menu to appear.
379+
while (GetCurrentMenuID() == MENU_MAIN && lWindowList.empty())
380+
ticker.tick();
381+
}
382+
365383
GUIButton *EngineController::existingButton(std::string_view buttonId) {
366384
auto findButton = [](std::string_view buttonId) -> GUIButton * {
367385
for (GUIWindow *window : lWindowList)

src/Engine/Components/Control/EngineController.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class EngineController {
5858
*/
5959
void pressGuiButton(std::string_view buttonId);
6060

61+
/**
62+
* Closes all menus and goes to the game screen. Will fail if main menu is currently open.
63+
*/
6164
void goToGame();
6265

6366
void goToInventory(int characterIndex);
@@ -120,6 +123,8 @@ class EngineController {
120123
void castSpell(int characterIndex, SpellId spell);
121124

122125
private:
126+
void goToGameOrMainMenu();
127+
123128
GUIButton *existingButton(std::string_view buttonId);
124129

125130
private:

src/Library/Platform/Interface/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(LIBRARY_PLATFORM_INTERFACE_SOURCES
55

66
set(LIBRARY_PLATFORM_INTERFACE_HEADERS
77
Platform.h
8+
PlatformEnumFunctions.h
89
PlatformEnums.h
910
PlatformEventHandler.h
1011
PlatformEventLoop.h
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <cassert>
4+
#include <utility>
5+
6+
#include "PlatformEnums.h"
7+
8+
inline PlatformKey platformKeyForDigit(int digit) {
9+
assert(digit >= 0 && digit <= 9);
10+
11+
return static_cast<PlatformKey>(std::to_underlying(PlatformKey::KEY_DIGIT_0) + digit);
12+
}

test/Bin/GameTest/GameTests_2000.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,45 @@ GAME_TEST(Issues, Issue2109) {
318318
EXPECT_LE(damageRange[1], 5);
319319
}
320320

321+
GAME_TEST(Issues, Issue2116) {
322+
// Resuscitating a character in turn based mode does not give them a turn.
323+
auto activeCharacterTape = tapes.activeCharacterIndex();
324+
325+
game.startNewGame();
326+
test.startTaping();
327+
328+
game.pressAndReleaseKey(PlatformKey::KEY_RETURN);
329+
game.tick();
330+
EXPECT_TRUE(pParty->bTurnBasedModeOn);
331+
332+
pParty->pCharacters[3].SetCondDeadWithBlockCheck(false);
333+
game.tick();
334+
335+
for (int i = 0; i < 10; i++) {
336+
game.pressAndReleaseKey(PlatformKey::KEY_B); // Pass.
337+
do {
338+
game.tick(2);
339+
} while (!pParty->hasActiveCharacter());
340+
}
341+
EXPECT_CONTAINS(activeCharacterTape, 1);
342+
EXPECT_CONTAINS(activeCharacterTape, 2);
343+
EXPECT_CONTAINS(activeCharacterTape, 3);
344+
EXPECT_MISSES(activeCharacterTape, 4);
345+
346+
pParty->pCharacters[3].conditions.reset(CONDITION_DEAD);
347+
pParty->pCharacters[3].conditions.reset(CONDITION_UNCONSCIOUS);
348+
pParty->pCharacters[3].health = 1;
349+
game.tick();
350+
351+
for (int i = 0; i < 10; i++) {
352+
game.pressAndReleaseKey(PlatformKey::KEY_B); // Pass.
353+
do {
354+
game.tick(2);
355+
} while (!pParty->hasActiveCharacter());
356+
}
357+
EXPECT_CONTAINS(activeCharacterTape, 4);
358+
}
359+
321360
GAME_TEST(Issues, Issue2117) {
322361
// Jumping down from Celeste crashes the game
323362
auto mapTape = tapes.map();

0 commit comments

Comments
 (0)