Track the loaded cutscene filename and re-load it on restart

Adds CUTSCENE_SYSTEM.loadedFile, set by cutsceneSystemLoad and cleared
by cutsceneSystemPrepare. cutsceneRestart now re-reads and re-parses
that file via cutsceneSystemLoad instead of just rerunning whatever's
still resident in loadedScene/loadedItems, so restarting a file-loaded
cutscene always reflects its current on-disk contents - restart of a
C-authored cutscene is unchanged.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-09-18 09:28:15 -05:00
co-authored by Claude Sonnet 5
parent abf6863044
commit 70ae41bd29
2 changed files with 51 additions and 9 deletions
+29 -4
View File
@@ -36,6 +36,7 @@ void cutsceneSystemDispose() {
CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
CUTSCENE_SYSTEM.textCache[0] = '\0';
CUTSCENE_SYSTEM.onComplete = NULL;
CUTSCENE_SYSTEM.loadedFile[0] = '\0';
cutsceneLoadedSetDoc(NULL);
}
@@ -58,6 +59,7 @@ void cutsceneSystemPrepare(
CUTSCENE_SYSTEM.textCache[0] = '\0';
CUTSCENE_SYSTEM.currentItem = 0xFF;// Set to 0xFF so Next wraps to 0.
CUTSCENE_SYSTEM.onComplete = NULL;
CUTSCENE_SYSTEM.loadedFile[0] = '\0';
}
void cutsceneSystemStartCutscene(cutscene_t *cutscene) {
@@ -69,6 +71,12 @@ void cutsceneSystemStartCutsceneWith(
entity_t *interact,
entity_t *interacted
) {
assertNotNull(cutscene, "Cutscene cannot be NULL");
assertTrue(
cutscene->itemCount <= cutscene->itemsMax,
"Cutscene itemCount exceeds itemsMax"
);
cutsceneSystemPrepare(cutscene, interact, interacted);
cutsceneSystemNext();
}
@@ -139,6 +147,7 @@ void cutsceneSystemLoad(const char_t *file) {
cutsceneLoadedSetDoc(doc);
cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene);
stringCopy(CUTSCENE_SYSTEM.loadedFile, file, ASSET_FILE_NAME_MAX - 1);
}
void cutsceneLoadedSetDoc(yyjson_doc *doc) {
@@ -153,14 +162,30 @@ void cutsceneRestart(void) {
// A restart is the same logical run trying again (e.g. retrying a failed
// save-device check), not a fresh unrelated start, so it should not
// silently drop a completion callback the caller already armed.
// silently drop a completion callback the caller already armed, or the
// entities that triggered it - both cutsceneSystemStartCutsceneWith and
// cutsceneSystemLoad (via cutsceneSystemPrepare) forget them.
cutscenecallback_t onComplete = CUTSCENE_SYSTEM.onComplete;
entity_t *entityInteract = CUTSCENE_SYSTEM.entityInteract;
entity_t *entityInteracted = CUTSCENE_SYSTEM.entityInteracted;
if(CUTSCENE_SYSTEM.loadedFile[0] != '\0') {
// Came from a cutscene asset - re-read+re-parse it from scratch
// rather than just rerunning whatever's still resident in
// loadedScene/loadedItems, so a restart always reflects the file's
// current contents.
char_t file[ASSET_FILE_NAME_MAX];
stringCopy(file, CUTSCENE_SYSTEM.loadedFile, ASSET_FILE_NAME_MAX - 1);
cutsceneSystemLoad(file);
} else {
cutsceneSystemStartCutsceneWith(
CUTSCENE_SYSTEM.scene,
CUTSCENE_SYSTEM.entityInteract,
CUTSCENE_SYSTEM.entityInteracted
CUTSCENE_SYSTEM.scene, entityInteract, entityInteracted
);
}
CUTSCENE_SYSTEM.onComplete = onComplete;
CUTSCENE_SYSTEM.entityInteract = entityInteract;
CUTSCENE_SYSTEM.entityInteracted = entityInteracted;
}
void cutsceneSystemSetOnComplete(cutscenecallback_t onComplete) {
+20 -3
View File
@@ -52,6 +52,16 @@ typedef struct {
cutsceneitem_t loadedItems[CUTSCENE_LOADED_ITEMS_MAX];
cutscene_t loadedScene;
// Filename last passed to cutsceneSystemLoad, e.g. "main_menu.jsonc" -
// set right after it starts loadedScene running. Empty ("") for a
// cutscene started directly via cutsceneSystemStartCutscene* instead
// (a C-authored one, or loadedScene reused without going through
// cutsceneSystemLoad again), and cleared by cutsceneSystemPrepare on
// every fresh start so it never lingers from a previous file load. See
// cutsceneRestart, which re-loads (rather than just rerunning) whatever
// this names.
char_t loadedFile[ASSET_FILE_NAME_MAX];
} cutscenesystem_t;
extern cutscenesystem_t CUTSCENE_SYSTEM;
@@ -153,7 +163,8 @@ void cutsceneSystemInsertCutscene(const cutscene_t *cutscene);
* CUTSCENE_LOADED_ITEMS_MAX's doc comment for why), so it's always
* re-read+re-parsed fresh, never assumed still resident from a previous
* call. Opens the fatal error overlay (see uiFatalErrorOpen) instead of
* starting anything if the asset fails to load.
* starting anything if the asset fails to load. Records file into
* CUTSCENE_SYSTEM.loadedFile once it starts running.
*
* @param file Cutscene file name (with .jsonc extension), relative to
* assets/cutscenes/.
@@ -174,8 +185,14 @@ void cutsceneLoadedSetDoc(yyjson_doc *doc);
/**
* Restarts the currently running cutscene from its first item,
* preserving whatever interact/interacted entities triggered it.
* Asserts if no cutscene is running.
* preserving whatever interact/interacted entities triggered it and
* whatever completion callback was armed. If CUTSCENE_SYSTEM.loadedFile
* is set (i.e. the running cutscene came from cutsceneSystemLoad), this
* re-reads and re-parses that file via cutsceneSystemLoad rather than
* just rerunning whatever's still resident in loadedScene/loadedItems, so
* a restart always reflects the file's current contents - otherwise it's
* just cutsceneSystemStartCutsceneWith on the same cutscene_t. Asserts if
* no cutscene is running.
*/
void cutsceneRestart(void);