- battleStateSelectionAiDecide: AI-controlled fighters now actually queue a basic attack against the first living enemy instead of doing nothing every round. - battleStateEndingInit: disposes the battle and switches back to SCENE_TYPE_OVERWORLD instead of leaving the game stuck in the battle scene forever. - cutsceneSystemNext now pops each finished item off the front of the running cutscene (cutsceneRemoveFront) instead of leaving it in place forever, so a long-running cutscene (many battle rounds splicing items in repeatedly) no longer grows scene->items unboundedly. - cutsceneGoTo reworked to match: since consumed items are evicted, a marker behind the current position can't be found in the live queue anymore, so it now re-parses the cutscene fresh from its source file (cutsceneLoadParse, into a persistent scratch buffer, not the stack) and replaces the live queue with marker-onward from that fresh parse. Only supported when the running cutscene is the one cutsceneSystemLoad/cutsceneCutsceneResolve populated. - Fixed a real bug this surfaced: cutsceneSystemPrepare unconditionally cleared loadedFile, which ran *after* cutsceneCutsceneResolve had just stamped it but *before* the cutscene started - wiping it out immediately and breaking cutsceneGoTo for any cutscene entered via a CUTSCENE item or cutsceneCutsceneResolve (e.g. the main menu's NEW_GAME/OPTIONS/QUIT navigation). Now only cleared when switching away from loadedScene entirely. - Added cutsceneLoadParse, the shared "lock asset, require loaded, parse items, unlock" sequence, replacing four near-identical copies across cutsceneSystemLoad/cutsceneCutsceneResolve/ cutsceneInsertResolveAndSplice/battleStateExecutingInit. Each call site handles its own fatal-error display; cutsceneLoadParse itself just propagates. - Added test_cutscene.c (cutsceneRemoveFront) and a regression test for the loadedFile bug. Writing the zero-count RemoveFront test caught a real self-move bug (count == 0 passed dest == src into memoryMove). Co-Authored-By: Claude Sonnet 5 <[email protected]>
85 lines
2.5 KiB
C
85 lines
2.5 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "dusktest.h"
|
|
#include "rpg/cutscene/cutscene.h"
|
|
#include "util/memory.h"
|
|
#include "util/string.h"
|
|
|
|
// ============================================================
|
|
// cutsceneRemoveFront
|
|
// ============================================================
|
|
|
|
static cutsceneitem_t MARKER_ITEM(const char_t *name) {
|
|
cutsceneitem_t item;
|
|
memoryZero(&item, sizeof(item));
|
|
item.type = CUTSCENE_ITEM_TYPE_MARKER;
|
|
stringCopy(item.marker.name, name, CUTSCENE_MARKER_NAME_MAX - 1);
|
|
return item;
|
|
}
|
|
|
|
static void test_cutsceneRemoveFrontShiftsRemainderToIndexZero(
|
|
void **state
|
|
) {
|
|
|
|
cutsceneitem_t items[4] = {
|
|
MARKER_ITEM("a"), MARKER_ITEM("b"), MARKER_ITEM("c"), MARKER_ITEM("d")
|
|
};
|
|
cutscene_t scene = { .items = items, .itemCount = 4, .itemsMax = 4 };
|
|
|
|
cutsceneRemoveFront(&scene, 2);
|
|
|
|
assert_int_equal(scene.itemCount, 2);
|
|
assert_string_equal(scene.items[0].marker.name, "c");
|
|
assert_string_equal(scene.items[1].marker.name, "d");
|
|
}
|
|
|
|
static void test_cutsceneRemoveFrontAllItemsLeavesEmptyScene(void **state) {
|
|
|
|
cutsceneitem_t items[3] = {
|
|
MARKER_ITEM("a"), MARKER_ITEM("b"), MARKER_ITEM("c")
|
|
};
|
|
cutscene_t scene = { .items = items, .itemCount = 3, .itemsMax = 3 };
|
|
|
|
cutsceneRemoveFront(&scene, 3);
|
|
|
|
assert_int_equal(scene.itemCount, 0);
|
|
}
|
|
|
|
static void test_cutsceneRemoveFrontZeroIsNoop(void **state) {
|
|
|
|
cutsceneitem_t items[2] = { MARKER_ITEM("a"), MARKER_ITEM("b") };
|
|
cutscene_t scene = { .items = items, .itemCount = 2, .itemsMax = 2 };
|
|
|
|
cutsceneRemoveFront(&scene, 0);
|
|
|
|
assert_int_equal(scene.itemCount, 2);
|
|
assert_string_equal(scene.items[0].marker.name, "a");
|
|
assert_string_equal(scene.items[1].marker.name, "b");
|
|
}
|
|
|
|
static void test_cutsceneRemoveFrontAssertsWhenCountExceedsItemCount(
|
|
void **state
|
|
) {
|
|
|
|
cutsceneitem_t items[2] = { MARKER_ITEM("a"), MARKER_ITEM("b") };
|
|
cutscene_t scene = { .items = items, .itemCount = 2, .itemsMax = 2 };
|
|
|
|
expect_assert_failure(cutsceneRemoveFront(&scene, 3));
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
const struct CMUnitTest tests[] = {
|
|
cmocka_unit_test(test_cutsceneRemoveFrontShiftsRemainderToIndexZero),
|
|
cmocka_unit_test(test_cutsceneRemoveFrontAllItemsLeavesEmptyScene),
|
|
cmocka_unit_test(test_cutsceneRemoveFrontZeroIsNoop),
|
|
cmocka_unit_test(test_cutsceneRemoveFrontAssertsWhenCountExceedsItemCount),
|
|
};
|
|
|
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
}
|