First pass cleaning cutscene system.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
cutscene.c
|
cutscene.c
|
||||||
|
cutscenerefs.c
|
||||||
cutscenesystem.c
|
cutscenesystem.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -148,26 +148,6 @@ void cutsceneAppendNext(
|
|||||||
cutsceneAppendAt(scene, (uint8_t)(currentIndex + 1), items, count);
|
cutsceneAppendAt(scene, (uint8_t)(currentIndex + 1), items, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneRemoveFront(
|
|
||||||
cutscene_t *scene,
|
|
||||||
const uint8_t count
|
|
||||||
) {
|
|
||||||
assertNotNull(scene, "Scene cannot be NULL");
|
|
||||||
assertTrue(count <= scene->itemCount, "count exceeds itemCount");
|
|
||||||
|
|
||||||
const size_t tailCount = (size_t)scene->itemCount - count;
|
|
||||||
// count == 0 has nothing to shift (and would pass dest == src into
|
|
||||||
// memoryMove, which asserts against that as a no-op call).
|
|
||||||
if(count > 0 && tailCount > 0) {
|
|
||||||
memoryMove(
|
|
||||||
&scene->items[0],
|
|
||||||
&scene->items[count],
|
|
||||||
tailCount * sizeof(cutsceneitem_t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
scene->itemCount -= count;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t cutsceneLoadParse(
|
errorret_t cutsceneLoadParse(
|
||||||
const char_t *path,
|
const char_t *path,
|
||||||
cutscene_t *scene,
|
cutscene_t *scene,
|
||||||
@@ -189,7 +169,9 @@ errorret_t cutsceneLoadParse(
|
|||||||
// cutsceneitem_t field that could reference it owns its string data by
|
// cutsceneitem_t field that could reference it owns its string data by
|
||||||
// value, so nothing needs to survive past this call and the entry can
|
// value, so nothing needs to survive past this call and the entry can
|
||||||
// just be unlocked like any other asset once parsing finishes.
|
// just be unlocked like any other asset once parsing finishes.
|
||||||
errorret_t parseResult = cutsceneParseDoc(entry->data.json, scene, items, itemsMax);
|
errorret_t parseResult = cutsceneParseDoc(
|
||||||
|
entry->data.json, scene, items, itemsMax
|
||||||
|
);
|
||||||
assetUnlockEntry(entry);
|
assetUnlockEntry(entry);
|
||||||
errorChain(parseResult);
|
errorChain(parseResult);
|
||||||
|
|
||||||
|
|||||||
@@ -128,30 +128,13 @@ void cutsceneAppendNext(
|
|||||||
const uint8_t count
|
const uint8_t count
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes count items from the front of scene->items, shifting the
|
|
||||||
* remainder down to index 0 and shrinking scene->itemCount to match. Used
|
|
||||||
* by cutsceneSystemNext/cutsceneGoTo to reclaim already-run items' slots
|
|
||||||
* instead of leaving them as dead weight forever - see
|
|
||||||
* CUTSCENE_SYSTEM.currentItem's doc comment, since the currently-running
|
|
||||||
* item is always scene->items[0] once a cutscene has started.
|
|
||||||
*
|
|
||||||
* @param scene Cutscene to remove from.
|
|
||||||
* @param count Number of items to remove from the front - must be
|
|
||||||
* <= scene->itemCount.
|
|
||||||
*/
|
|
||||||
void cutsceneRemoveFront(
|
|
||||||
cutscene_t *scene,
|
|
||||||
const uint8_t count
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a cutscene JSON asset by path and parses it into scene/items (see
|
* Loads a cutscene JSON asset by path and parses it into scene/items (see
|
||||||
* cutsceneParseDoc) - the common "lock the asset, require it loaded,
|
* cutsceneParseDoc) - the common "lock the asset, require it loaded,
|
||||||
* parse its 'items' array, unlock it again" sequence shared by every
|
* parse its 'items' array, unlock it again" sequence shared by every
|
||||||
* place that resolves a cutscene by file path (cutsceneSystemLoad,
|
* place that resolves a cutscene by file path (cutsceneSystemLoad,
|
||||||
* cutsceneCutsceneResolve, cutsceneInsertResolveAndSplice,
|
* cutsceneCutsceneResolve, cutsceneInsertResolveAndSplice,
|
||||||
* battleStateExecutingInit, cutsceneGoTo's reload). Purely propagates the
|
* battleStateExecutingInit, cutsceneSystemGoTo's reload). Purely propagates the
|
||||||
* error on failure (like cutsceneParseDoc) - this is core cutscene logic,
|
* error on failure (like cutsceneParseDoc) - this is core cutscene logic,
|
||||||
* not UI, so it doesn't reach for uiFatalErrorOpen itself; each caller
|
* not UI, so it doesn't reach for uiFatalErrorOpen itself; each caller
|
||||||
* decides how to surface the failure (typically errorCatch(errorPrint())
|
* decides how to surface the failure (typically errorCatch(errorPrint())
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cutscenerefs.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void cutsceneRefsReset(
|
||||||
|
cutscenesystemrefs_t *refs,
|
||||||
|
entity_t *interact,
|
||||||
|
entity_t *interacted
|
||||||
|
) {
|
||||||
|
assertNotNull(refs, "Refs cannot be null");
|
||||||
|
|
||||||
|
refs->entityInteract = interact;
|
||||||
|
refs->entityInteracted = interacted;
|
||||||
|
refs->entityLastCreated = NULL;
|
||||||
|
refs->entityLastRef = NULL;
|
||||||
|
refs->areaLastCreated = CUTSCENE_AREA_LAST_CREATED;
|
||||||
|
refs->textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
typedef struct entity_s entity_t;
|
||||||
|
|
||||||
|
#define CUTSCENE_AREA_LAST_CREATED ((uint8_t)0xFF)
|
||||||
|
#define CUTSCENE_TEXT_MINI_LAST_CREATED ((uint8_t)0xFA)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common cutscene references that should survive a cutsceneRestart -
|
||||||
|
* grouped into one struct (rather than loose fields on cutscenesystem_t)
|
||||||
|
* so cutsceneRestart can snapshot/restore all of them in one copy instead
|
||||||
|
* of field-by-field, and so anything added here later comes along for the
|
||||||
|
* ride automatically.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
entity_t *entityInteract;
|
||||||
|
entity_t *entityInteracted;
|
||||||
|
entity_t *entityLastCreated;
|
||||||
|
entity_t *entityLastRef;
|
||||||
|
uint8_t areaLastCreated;
|
||||||
|
uint8_t textMiniLastCreated;
|
||||||
|
} cutscenesystemrefs_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets refs to a fresh state: interact/interacted set to the given
|
||||||
|
* entities, everything else (last-created entity, last-referenced entity,
|
||||||
|
* last-created map area, last-created mini textbox) cleared back to its
|
||||||
|
* "nothing yet" sentinel.
|
||||||
|
*
|
||||||
|
* @param refs Refs to reset.
|
||||||
|
* @param interact The entity that initiated the interaction, or NULL.
|
||||||
|
* @param interacted The entity being interacted with, or NULL.
|
||||||
|
*/
|
||||||
|
void cutsceneRefsReset(
|
||||||
|
cutscenesystemrefs_t *refs,
|
||||||
|
entity_t *interact,
|
||||||
|
entity_t *interacted
|
||||||
|
);
|
||||||
@@ -21,16 +21,18 @@ void cutsceneSystemInit() {
|
|||||||
CUTSCENE_SYSTEM.loadedScene.itemsMax = CUTSCENE_LOADED_ITEMS_MAX;
|
CUTSCENE_SYSTEM.loadedScene.itemsMax = CUTSCENE_LOADED_ITEMS_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cutsceneSystemUpdate() {
|
||||||
|
if(CUTSCENE_SYSTEM.scene == NULL) return;
|
||||||
|
|
||||||
|
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
||||||
|
if(cutsceneItemUpdate(item, &CUTSCENE_SYSTEM.data)) cutsceneSystemNext();
|
||||||
|
}
|
||||||
|
|
||||||
void cutsceneSystemDispose() {
|
void cutsceneSystemDispose() {
|
||||||
CUTSCENE_SYSTEM.scene = NULL;
|
CUTSCENE_SYSTEM.scene = NULL;
|
||||||
CUTSCENE_SYSTEM.currentItem = 0xFF;
|
CUTSCENE_SYSTEM.currentItem = CUTSCENE_CURRENT_ITEM_NONE;
|
||||||
CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE;
|
CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE;
|
||||||
CUTSCENE_SYSTEM.entityInteract = NULL;
|
cutsceneRefsReset(&CUTSCENE_SYSTEM.refs, NULL, NULL);
|
||||||
CUTSCENE_SYSTEM.entityInteracted = NULL;
|
|
||||||
CUTSCENE_SYSTEM.entityLastCreated = NULL;
|
|
||||||
CUTSCENE_SYSTEM.entityLastRef = NULL;
|
|
||||||
CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED;
|
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
|
|
||||||
CUTSCENE_SYSTEM.textCache[0] = '\0';
|
CUTSCENE_SYSTEM.textCache[0] = '\0';
|
||||||
CUTSCENE_SYSTEM.onComplete = NULL;
|
CUTSCENE_SYSTEM.onComplete = NULL;
|
||||||
CUTSCENE_SYSTEM.loadedFile[0] = '\0';
|
CUTSCENE_SYSTEM.loadedFile[0] = '\0';
|
||||||
@@ -45,25 +47,14 @@ void cutsceneSystemPrepare(
|
|||||||
|
|
||||||
CUTSCENE_SYSTEM.scene = cutscene;
|
CUTSCENE_SYSTEM.scene = cutscene;
|
||||||
CUTSCENE_SYSTEM.pause = cutscene->pause;
|
CUTSCENE_SYSTEM.pause = cutscene->pause;
|
||||||
CUTSCENE_SYSTEM.entityInteract = interact;
|
cutsceneRefsReset(&CUTSCENE_SYSTEM.refs, interact, interacted);
|
||||||
CUTSCENE_SYSTEM.entityInteracted = interacted;
|
|
||||||
CUTSCENE_SYSTEM.entityLastCreated = NULL;
|
|
||||||
CUTSCENE_SYSTEM.entityLastRef = NULL;
|
|
||||||
CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED;
|
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
|
|
||||||
CUTSCENE_SYSTEM.textCache[0] = '\0';
|
CUTSCENE_SYSTEM.textCache[0] = '\0';
|
||||||
CUTSCENE_SYSTEM.currentItem = 0xFF;// Set to 0xFF so Next wraps to 0.
|
|
||||||
CUTSCENE_SYSTEM.onComplete = NULL;
|
CUTSCENE_SYSTEM.onComplete = NULL;
|
||||||
|
|
||||||
// Only invalidate the known source file when switching away from
|
// cutsceneNext will cause overflow to index 0 (intentional).
|
||||||
// loadedScene entirely. Starting loadedScene itself means
|
CUTSCENE_SYSTEM.currentItem = CUTSCENE_CURRENT_ITEM_NONE;
|
||||||
// cutsceneSystemLoad/cutsceneCutsceneResolve just populated it - for
|
|
||||||
// cutsceneCutsceneResolve (see cutsceneCutsceneStart), that already
|
// Clear loaded file if cutscene not running from file.
|
||||||
// happened before this call, so clearing loadedFile here would
|
|
||||||
// immediately undo it. cutsceneGoTo needs loadedFile intact to reload
|
|
||||||
// a marker behind the current position; cutsceneSystemLoad re-stamps
|
|
||||||
// it itself right after this call anyway, so it's unaffected either
|
|
||||||
// way.
|
|
||||||
if(cutscene != &CUTSCENE_SYSTEM.loadedScene) {
|
if(cutscene != &CUTSCENE_SYSTEM.loadedScene) {
|
||||||
CUTSCENE_SYSTEM.loadedFile[0] = '\0';
|
CUTSCENE_SYSTEM.loadedFile[0] = '\0';
|
||||||
}
|
}
|
||||||
@@ -84,9 +75,9 @@ void cutsceneSystemStartCutsceneWith(
|
|||||||
"Cutscene itemCount exceeds itemsMax"
|
"Cutscene itemCount exceeds itemsMax"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Prep cutscene, save it to the save slot, and advance, aka overflow to 0.
|
||||||
cutsceneSystemPrepare(cutscene, interact, interacted);
|
cutsceneSystemPrepare(cutscene, interact, interacted);
|
||||||
saveSlotSetCurrentCutscene(CUTSCENE_SYSTEM.loadedFile);
|
saveSlotSetCurrentCutscene(CUTSCENE_SYSTEM.loadedFile);
|
||||||
|
|
||||||
cutsceneSystemNext();
|
cutsceneSystemNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +87,9 @@ void cutsceneSystemStartCutsceneAndGoToMarker(
|
|||||||
) {
|
) {
|
||||||
assertNotNull(marker, "Marker cannot be NULL");
|
assertNotNull(marker, "Marker cannot be NULL");
|
||||||
|
|
||||||
|
// Restarts the cutscene
|
||||||
cutsceneSystemPrepare(cutscene, NULL, NULL);
|
cutsceneSystemPrepare(cutscene, NULL, NULL);
|
||||||
cutsceneGoTo(marker);
|
cutsceneSystemGoTo(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneSystemInsertItemsNext(
|
void cutsceneSystemInsertItemsNext(
|
||||||
@@ -109,7 +101,6 @@ void cutsceneSystemInsertItemsNext(
|
|||||||
CUTSCENE_SYSTEM.scene,
|
CUTSCENE_SYSTEM.scene,
|
||||||
"cutsceneSystemInsertItemsNext called with no cutscene running"
|
"cutsceneSystemInsertItemsNext called with no cutscene running"
|
||||||
);
|
);
|
||||||
|
|
||||||
cutsceneAppendNext(
|
cutsceneAppendNext(
|
||||||
CUTSCENE_SYSTEM.scene, CUTSCENE_SYSTEM.currentItem, items, itemCount
|
CUTSCENE_SYSTEM.scene, CUTSCENE_SYSTEM.currentItem, items, itemCount
|
||||||
);
|
);
|
||||||
@@ -128,31 +119,27 @@ void cutsceneSystemInsertCutscene(const cutscene_t *cutscene) {
|
|||||||
cutsceneSystemInsertItems(cutscene->items, cutscene->itemCount);
|
cutsceneSystemInsertItems(cutscene->items, cutscene->itemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneSystemDiscardQueued(void) {
|
void cutsceneSystemClearAfter(const uint8_t index) {
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.scene,
|
CUTSCENE_SYSTEM.scene,
|
||||||
"cutsceneSystemDiscardQueued called with no cutscene running"
|
"cutsceneSystemClearAfter called with no cutscene running"
|
||||||
|
);
|
||||||
|
assertTrue(
|
||||||
|
index < CUTSCENE_SYSTEM.scene->itemCount,
|
||||||
|
"cutsceneSystemClearAfter index out of range"
|
||||||
);
|
);
|
||||||
|
|
||||||
// currentItem is always 0 once a cutscene has started (see its doc
|
CUTSCENE_SYSTEM.scene->itemCount = index + 1;
|
||||||
// comment) - keep just that one item, drop everything queued after it.
|
|
||||||
CUTSCENE_SYSTEM.scene->itemCount = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneSystemLoad(const char_t *file) {
|
void cutsceneSystemLoad(const char_t *file) {
|
||||||
assertNotNull(file, "File cannot be NULL");
|
assertNotNull(file, "File cannot be NULL");
|
||||||
|
|
||||||
// Copy file out before it can be invalidated - every caller today
|
// Take a copy of file, as it may be a part of the cutscene itself.
|
||||||
// passes a string literal, but file could in principle point into
|
|
||||||
// CUTSCENE_SYSTEM.loadedItems (a running item's own name field, if the
|
|
||||||
// running cutscene is loadedScene), which both cutsceneLoadParse and
|
|
||||||
// cutsceneSystemStartCutscene below overwrite/re-enter (see
|
|
||||||
// cutsceneCutsceneResolve's matching comment for the exact bug this
|
|
||||||
// guards against - initial.jsonc's closing CUTSCENE item into
|
|
||||||
// main_menu.jsonc hit it there).
|
|
||||||
char_t fileCopy[ASSET_FILE_NAME_MAX];
|
char_t fileCopy[ASSET_FILE_NAME_MAX];
|
||||||
stringCopy(fileCopy, file, ASSET_FILE_NAME_MAX - 1);
|
stringCopy(fileCopy, file, ASSET_FILE_NAME_MAX - 1);
|
||||||
|
|
||||||
|
// Load the cutscene asset, parse it, and start it.
|
||||||
errorret_t result = cutsceneLoadParse(
|
errorret_t result = cutsceneLoadParse(
|
||||||
fileCopy, &CUTSCENE_SYSTEM.loadedScene, CUTSCENE_SYSTEM.loadedItems,
|
fileCopy, &CUTSCENE_SYSTEM.loadedScene, CUTSCENE_SYSTEM.loadedItems,
|
||||||
CUTSCENE_LOADED_ITEMS_MAX
|
CUTSCENE_LOADED_ITEMS_MAX
|
||||||
@@ -162,13 +149,8 @@ void cutsceneSystemLoad(const char_t *file) {
|
|||||||
uiFatalErrorOpen(NULL);
|
uiFatalErrorOpen(NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stamped before starting (not after) - cutsceneSystemStartCutsceneWith
|
// Store the loaded file so we can restart if needed.
|
||||||
// reads loadedFile to persist the in-progress cutscene to the save (see
|
|
||||||
// saveSlotSetCurrentCutscene), so it must already be correct by then.
|
|
||||||
// Safe: cutsceneSystemPrepare (called from within Start) only clears
|
|
||||||
// loadedFile when switching away from loadedScene entirely, which this
|
|
||||||
// isn't.
|
|
||||||
stringCopy(CUTSCENE_SYSTEM.loadedFile, fileCopy, ASSET_FILE_NAME_MAX - 1);
|
stringCopy(CUTSCENE_SYSTEM.loadedFile, fileCopy, ASSET_FILE_NAME_MAX - 1);
|
||||||
cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene);
|
cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene);
|
||||||
}
|
}
|
||||||
@@ -177,10 +159,14 @@ void cutsceneRestart(void) {
|
|||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.scene, "cutsceneRestart called with no cutscene running"
|
CUTSCENE_SYSTEM.scene, "cutsceneRestart called with no cutscene running"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Snapshotted as one struct (rather than field-by-field) so anything
|
||||||
|
// added to cutscenesystemrefs_t later - entities, map areas, mini
|
||||||
|
// textboxes, etc - survives a restart automatically instead of needing
|
||||||
|
// its own line here. cutsceneSystemPrepare (called from within both
|
||||||
|
// branches below) resets refs to a fresh state, so it's restored after.
|
||||||
cutscenecallback_t onComplete = CUTSCENE_SYSTEM.onComplete;
|
cutscenecallback_t onComplete = CUTSCENE_SYSTEM.onComplete;
|
||||||
entity_t *entityInteract = CUTSCENE_SYSTEM.entityInteract;
|
cutscenesystemrefs_t refs = CUTSCENE_SYSTEM.refs;
|
||||||
entity_t *entityInteracted = CUTSCENE_SYSTEM.entityInteracted;
|
|
||||||
|
|
||||||
if(CUTSCENE_SYSTEM.loadedFile[0] != '\0') {
|
if(CUTSCENE_SYSTEM.loadedFile[0] != '\0') {
|
||||||
char_t file[ASSET_FILE_NAME_MAX];
|
char_t file[ASSET_FILE_NAME_MAX];
|
||||||
@@ -188,13 +174,12 @@ void cutsceneRestart(void) {
|
|||||||
cutsceneSystemLoad(file);
|
cutsceneSystemLoad(file);
|
||||||
} else {
|
} else {
|
||||||
cutsceneSystemStartCutsceneWith(
|
cutsceneSystemStartCutsceneWith(
|
||||||
CUTSCENE_SYSTEM.scene, entityInteract, entityInteracted
|
CUTSCENE_SYSTEM.scene, refs.entityInteract, refs.entityInteracted
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUTSCENE_SYSTEM.onComplete = onComplete;
|
CUTSCENE_SYSTEM.onComplete = onComplete;
|
||||||
CUTSCENE_SYSTEM.entityInteract = entityInteract;
|
CUTSCENE_SYSTEM.refs = refs;
|
||||||
CUTSCENE_SYSTEM.entityInteracted = entityInteracted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneSystemSetOnComplete(cutscenecallback_t onComplete) {
|
void cutsceneSystemSetOnComplete(cutscenecallback_t onComplete) {
|
||||||
@@ -210,28 +195,28 @@ entity_t * cutsceneSystemGetEntity(const uint8_t entityIndex) {
|
|||||||
|
|
||||||
if(entityIndex == CUTSCENE_ENTITY_INTERACT) {
|
if(entityIndex == CUTSCENE_ENTITY_INTERACT) {
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.entityInteract,
|
CUTSCENE_SYSTEM.refs.entityInteract,
|
||||||
"CUTSCENE_ENTITY_INTERACT used but no interact entity is set"
|
"CUTSCENE_ENTITY_INTERACT used but no interact entity is set"
|
||||||
);
|
);
|
||||||
entity = CUTSCENE_SYSTEM.entityInteract;
|
entity = CUTSCENE_SYSTEM.refs.entityInteract;
|
||||||
} else if(entityIndex == CUTSCENE_ENTITY_INTERACTED) {
|
} else if(entityIndex == CUTSCENE_ENTITY_INTERACTED) {
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.entityInteracted,
|
CUTSCENE_SYSTEM.refs.entityInteracted,
|
||||||
"CUTSCENE_ENTITY_INTERACTED used but no interacted entity is set"
|
"CUTSCENE_ENTITY_INTERACTED used but no interacted entity is set"
|
||||||
);
|
);
|
||||||
entity = CUTSCENE_SYSTEM.entityInteracted;
|
entity = CUTSCENE_SYSTEM.refs.entityInteracted;
|
||||||
} else if(entityIndex == CUTSCENE_ENTITY_LAST_CREATED) {
|
} else if(entityIndex == CUTSCENE_ENTITY_LAST_CREATED) {
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.entityLastCreated,
|
CUTSCENE_SYSTEM.refs.entityLastCreated,
|
||||||
"CUTSCENE_ENTITY_LAST_CREATED used but no entity has been created"
|
"CUTSCENE_ENTITY_LAST_CREATED used but no entity has been created"
|
||||||
);
|
);
|
||||||
entity = CUTSCENE_SYSTEM.entityLastCreated;
|
entity = CUTSCENE_SYSTEM.refs.entityLastCreated;
|
||||||
} else if(entityIndex == CUTSCENE_ENTITY_LAST_REF) {
|
} else if(entityIndex == CUTSCENE_ENTITY_LAST_REF) {
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.entityLastRef,
|
CUTSCENE_SYSTEM.refs.entityLastRef,
|
||||||
"CUTSCENE_ENTITY_LAST_REF used but no entity has been referenced"
|
"CUTSCENE_ENTITY_LAST_REF used but no entity has been referenced"
|
||||||
);
|
);
|
||||||
entity = CUTSCENE_SYSTEM.entityLastRef;
|
entity = CUTSCENE_SYSTEM.refs.entityLastRef;
|
||||||
} else {
|
} else {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
entityIndex < ENTITY_COUNT,
|
entityIndex < ENTITY_COUNT,
|
||||||
@@ -240,17 +225,17 @@ entity_t * cutsceneSystemGetEntity(const uint8_t entityIndex) {
|
|||||||
entity = &ENTITIES[entityIndex];
|
entity = &ENTITIES[entityIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
CUTSCENE_SYSTEM.entityLastRef = entity;
|
CUTSCENE_SYSTEM.refs.entityLastRef = entity;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t cutsceneSystemGetAreaId(const uint8_t areaId) {
|
uint8_t cutsceneSystemGetAreaId(const uint8_t areaId) {
|
||||||
if(areaId == CUTSCENE_AREA_LAST_CREATED) {
|
if(areaId == CUTSCENE_AREA_LAST_CREATED) {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
CUTSCENE_SYSTEM.areaLastCreated != CUTSCENE_AREA_LAST_CREATED,
|
CUTSCENE_SYSTEM.refs.areaLastCreated != CUTSCENE_AREA_LAST_CREATED,
|
||||||
"CUTSCENE_AREA_LAST_CREATED used but no map area has been created"
|
"CUTSCENE_AREA_LAST_CREATED used but no map area has been created"
|
||||||
);
|
);
|
||||||
return CUTSCENE_SYSTEM.areaLastCreated;
|
return CUTSCENE_SYSTEM.refs.areaLastCreated;
|
||||||
}
|
}
|
||||||
return areaId;
|
return areaId;
|
||||||
}
|
}
|
||||||
@@ -258,11 +243,12 @@ uint8_t cutsceneSystemGetAreaId(const uint8_t areaId) {
|
|||||||
uint8_t cutsceneSystemGetTextMiniId(const uint8_t index) {
|
uint8_t cutsceneSystemGetTextMiniId(const uint8_t index) {
|
||||||
if(index == CUTSCENE_TEXT_MINI_LAST_CREATED) {
|
if(index == CUTSCENE_TEXT_MINI_LAST_CREATED) {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated != CUTSCENE_TEXT_MINI_LAST_CREATED,
|
CUTSCENE_SYSTEM.refs.textMiniLastCreated !=
|
||||||
|
CUTSCENE_TEXT_MINI_LAST_CREATED,
|
||||||
"CUTSCENE_TEXT_MINI_LAST_CREATED used but no mini textbox has been "
|
"CUTSCENE_TEXT_MINI_LAST_CREATED used but no mini textbox has been "
|
||||||
"shown"
|
"shown"
|
||||||
);
|
);
|
||||||
return CUTSCENE_SYSTEM.textMiniLastCreated;
|
return CUTSCENE_SYSTEM.refs.textMiniLastCreated;
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@@ -282,68 +268,49 @@ void cutsceneSystemSetTextCache(const char_t *text) {
|
|||||||
void cutsceneSystemNext() {
|
void cutsceneSystemNext() {
|
||||||
if(CUTSCENE_SYSTEM.scene == NULL) return;
|
if(CUTSCENE_SYSTEM.scene == NULL) return;
|
||||||
|
|
||||||
// Pop the just-finished item off the front rather than advancing an
|
// Pop the just-finished item off the front.
|
||||||
// index further into the array - see CUTSCENE_SYSTEM.currentItem's doc
|
if(CUTSCENE_SYSTEM.currentItem == CUTSCENE_CURRENT_ITEM_NONE) {
|
||||||
// comment. The very first call (currentItem still 0xFF) has nothing to
|
|
||||||
// pop yet; it just marks the cutscene as started.
|
|
||||||
if(CUTSCENE_SYSTEM.currentItem == 0xFF) {
|
|
||||||
CUTSCENE_SYSTEM.currentItem = 0;
|
CUTSCENE_SYSTEM.currentItem = 0;
|
||||||
} else {
|
} else {
|
||||||
cutsceneRemoveFront(CUTSCENE_SYSTEM.scene, 1);
|
cutscene_t *scene = CUTSCENE_SYSTEM.scene;
|
||||||
|
const size_t tailCount = (size_t)scene->itemCount - 1;
|
||||||
|
if(tailCount > 0) {
|
||||||
|
memoryMove(
|
||||||
|
&scene->items[0], &scene->items[1], tailCount * sizeof(cutsceneitem_t)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
scene->itemCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of the cutscene? Note that a CUTSCENE_ITEM_TYPE_INSERT item's
|
// End of the cutscene?
|
||||||
// spliced-in items are physically part of this same array (see
|
|
||||||
// cutsceneSystemInsertCutscene), so there's no separate "parent scene"
|
|
||||||
// to fall back into here - itemCount already accounts for them.
|
|
||||||
if(CUTSCENE_SYSTEM.scene->itemCount == 0) {
|
if(CUTSCENE_SYSTEM.scene->itemCount == 0) {
|
||||||
// Saved and cleared before firing so a callback that immediately
|
|
||||||
// starts another cutscene (or sets its own onComplete) isn't clobbered
|
|
||||||
// by this function's own cleanup running after it - same reentrancy
|
|
||||||
// hazard as uiFocusPop, see src/dusk/ui/focus/uifocus.c.
|
|
||||||
cutscenecallback_t onComplete = CUTSCENE_SYSTEM.onComplete;
|
cutscenecallback_t onComplete = CUTSCENE_SYSTEM.onComplete;
|
||||||
|
|
||||||
CUTSCENE_SYSTEM.scene = NULL;
|
CUTSCENE_SYSTEM.scene = NULL;
|
||||||
CUTSCENE_SYSTEM.currentItem = 0xFF;
|
|
||||||
CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE;
|
CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE;
|
||||||
CUTSCENE_SYSTEM.entityInteract = NULL;
|
|
||||||
CUTSCENE_SYSTEM.entityInteracted = NULL;
|
|
||||||
CUTSCENE_SYSTEM.entityLastCreated = NULL;
|
|
||||||
CUTSCENE_SYSTEM.entityLastRef = NULL;
|
|
||||||
CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED;
|
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
|
|
||||||
CUTSCENE_SYSTEM.textCache[0] = '\0';
|
|
||||||
CUTSCENE_SYSTEM.onComplete = NULL;
|
|
||||||
|
|
||||||
if(onComplete != NULL) onComplete(NULL);
|
if(onComplete != NULL) onComplete(NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start item.
|
// Start next (now current) item
|
||||||
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
||||||
memset(&CUTSCENE_SYSTEM.data, 0, sizeof(CUTSCENE_SYSTEM.data));
|
memset(&CUTSCENE_SYSTEM.data, 0, sizeof(CUTSCENE_SYSTEM.data));
|
||||||
cutsceneItemStart(item, &CUTSCENE_SYSTEM.data);
|
cutsceneItemStart(item, &CUTSCENE_SYSTEM.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneGoTo(const char_t *name) {
|
void cutsceneSystemGoTo(const char_t *name) {
|
||||||
assertNotNull(name, "Name cannot be NULL");
|
assertNotNull(name, "Name cannot be NULL");
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.scene, "cutsceneGoTo called with no cutscene running"
|
CUTSCENE_SYSTEM.scene, "cutsceneSystemGoTo called with no cutscene running"
|
||||||
);
|
);
|
||||||
// A marker behind the current position can't be found in the live
|
|
||||||
// queue - already-run items are evicted from its front as the
|
|
||||||
// cutscene advances (see cutsceneSystemNext/cutsceneRemoveFront), so
|
|
||||||
// the untouched original has to be re-parsed from source instead. Only
|
|
||||||
// supported when the running cutscene is the one cutsceneSystemLoad/
|
|
||||||
// cutsceneCutsceneResolve populated - a C-authored cutscene_t, or
|
|
||||||
// content spliced in via INSERT/battleStateExecutingInit, has no
|
|
||||||
// source to reload from, so a backward jump into those isn't supported
|
|
||||||
// yet.
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
CUTSCENE_SYSTEM.scene == &CUTSCENE_SYSTEM.loadedScene &&
|
CUTSCENE_SYSTEM.scene == &CUTSCENE_SYSTEM.loadedScene,
|
||||||
CUTSCENE_SYSTEM.loadedFile[0] != '\0',
|
"cutsceneSystemGoTo requires the running cutscene file reference (1)"
|
||||||
"cutsceneGoTo requires the running cutscene to have come from "
|
);
|
||||||
"cutsceneSystemLoad/cutsceneCutsceneResolve"
|
assertTrue(
|
||||||
|
CUTSCENE_SYSTEM.loadedFile[0] != '\0',
|
||||||
|
"cutsceneSystemGoTo requires the running cutscene file reference (2)"
|
||||||
);
|
);
|
||||||
|
|
||||||
cutscene_t freshScene = { .items = CUTSCENE_SYSTEM.gotoScratchItems };
|
cutscene_t freshScene = { .items = CUTSCENE_SYSTEM.gotoScratchItems };
|
||||||
@@ -357,6 +324,7 @@ void cutsceneGoTo(const char_t *name) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search for the marker with the given name...
|
||||||
for(uint8_t i = 0; i < freshScene.itemCount; i++) {
|
for(uint8_t i = 0; i < freshScene.itemCount; i++) {
|
||||||
const cutsceneitem_t *item = &freshScene.items[i];
|
const cutsceneitem_t *item = &freshScene.items[i];
|
||||||
if(
|
if(
|
||||||
@@ -364,10 +332,8 @@ void cutsceneGoTo(const char_t *name) {
|
|||||||
!stringEquals(item->marker.name, name)
|
!stringEquals(item->marker.name, name)
|
||||||
) continue;
|
) continue;
|
||||||
|
|
||||||
// Commit: replace the live queue outright with marker-onward from
|
// Found, so splice the cutscene at that point and start it, the remaining
|
||||||
// the fresh parse. Nothing before the marker (including whatever was
|
// items being the rest of the cutscene after the marker.
|
||||||
// running) gets Started - only the marker item itself does, same as
|
|
||||||
// the old in-place jump's semantics.
|
|
||||||
const uint8_t remaining = freshScene.itemCount - i;
|
const uint8_t remaining = freshScene.itemCount - i;
|
||||||
memoryCopy(
|
memoryCopy(
|
||||||
CUTSCENE_SYSTEM.loadedItems, &freshScene.items[i],
|
CUTSCENE_SYSTEM.loadedItems, &freshScene.items[i],
|
||||||
@@ -383,19 +349,10 @@ void cutsceneGoTo(const char_t *name) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(false, "cutsceneGoTo: no marker found with that name");
|
assertTrue(false, "cutsceneSystemGoTo: no marker found with that name");
|
||||||
}
|
|
||||||
|
|
||||||
void cutsceneSystemUpdate() {
|
|
||||||
if(CUTSCENE_SYSTEM.scene == NULL) return;
|
|
||||||
|
|
||||||
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
|
||||||
if(cutsceneItemUpdate(item, &CUTSCENE_SYSTEM.data)) cutsceneSystemNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cutsceneitem_t * cutsceneSystemGetCurrentItem() {
|
const cutsceneitem_t * cutsceneSystemGetCurrentItem() {
|
||||||
if(CUTSCENE_SYSTEM.scene == NULL) return NULL;
|
if(CUTSCENE_SYSTEM.scene == NULL) return NULL;
|
||||||
|
|
||||||
// Always index 0 - see CUTSCENE_SYSTEM.currentItem's doc comment.
|
|
||||||
return &CUTSCENE_SYSTEM.scene->items[0];
|
return &CUTSCENE_SYSTEM.scene->items[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "cutscene.h"
|
#include "cutscene.h"
|
||||||
|
#include "cutscenerefs.h"
|
||||||
typedef struct entity_s entity_t;
|
|
||||||
|
|
||||||
#define CUTSCENE_ENTITY_INTERACT ((uint8_t)0xFE)
|
#define CUTSCENE_ENTITY_INTERACT ((uint8_t)0xFE)
|
||||||
#define CUTSCENE_ENTITY_INTERACTED ((uint8_t)0xFD)
|
#define CUTSCENE_ENTITY_INTERACTED ((uint8_t)0xFD)
|
||||||
#define CUTSCENE_ENTITY_LAST_CREATED ((uint8_t)0xFC)
|
#define CUTSCENE_ENTITY_LAST_CREATED ((uint8_t)0xFC)
|
||||||
#define CUTSCENE_ENTITY_LAST_REF ((uint8_t)0xFB)
|
#define CUTSCENE_ENTITY_LAST_REF ((uint8_t)0xFB)
|
||||||
#define CUTSCENE_AREA_LAST_CREATED ((uint8_t)0xFF)
|
#define CUTSCENE_CURRENT_ITEM_NONE ((uint8_t)0xFF)
|
||||||
#define CUTSCENE_TEXT_MINI_LAST_CREATED ((uint8_t)0xFA)
|
|
||||||
|
|
||||||
#define CUTSCENE_TEXT_CACHE_MAX 64
|
#define CUTSCENE_TEXT_CACHE_MAX 64
|
||||||
#define CUTSCENE_LOADED_ITEMS_MAX 128
|
#define CUTSCENE_LOADED_ITEMS_MAX 128
|
||||||
@@ -23,21 +21,10 @@ typedef struct entity_s entity_t;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
cutscene_t *scene;
|
cutscene_t *scene;
|
||||||
|
|
||||||
// 0xFF if nothing has started running yet, otherwise always 0 - the
|
|
||||||
// currently-running item is always scene->items[0]; cutsceneSystemNext
|
|
||||||
// removes it from the front (see cutsceneRemoveFront) rather than
|
|
||||||
// advancing an index further into the array, so an item's slot is
|
|
||||||
// reclaimed the moment it finishes instead of sitting there as dead
|
|
||||||
// weight for the rest of the cutscene's run.
|
|
||||||
uint8_t currentItem;
|
uint8_t currentItem;
|
||||||
cutscenepause_t pause;
|
cutscenepause_t pause;
|
||||||
entity_t *entityInteract;
|
|
||||||
entity_t *entityInteracted;
|
cutscenesystemrefs_t refs;
|
||||||
entity_t *entityLastCreated;
|
|
||||||
entity_t *entityLastRef;
|
|
||||||
uint8_t areaLastCreated;
|
|
||||||
uint8_t textMiniLastCreated;
|
|
||||||
|
|
||||||
// Free-form text cache for the running cutscene - see
|
// Free-form text cache for the running cutscene - see
|
||||||
// cutsceneSystemGetTextCache/cutsceneSystemSetTextCache.
|
// cutsceneSystemGetTextCache/cutsceneSystemSetTextCache.
|
||||||
@@ -49,17 +36,12 @@ typedef struct {
|
|||||||
// See cutsceneSystemSetOnComplete.
|
// See cutsceneSystemSetOnComplete.
|
||||||
cutscenecallback_t onComplete;
|
cutscenecallback_t onComplete;
|
||||||
|
|
||||||
|
// Cache and storage used for the dynamically loaded cutscenes.
|
||||||
cutsceneitem_t loadedItems[CUTSCENE_LOADED_ITEMS_MAX];
|
cutsceneitem_t loadedItems[CUTSCENE_LOADED_ITEMS_MAX];
|
||||||
cutscene_t loadedScene;
|
cutscene_t loadedScene;
|
||||||
|
|
||||||
// Filename last passed to cutsceneSystemLoad - see cutsceneRestart.
|
|
||||||
char_t loadedFile[ASSET_FILE_NAME_MAX];
|
char_t loadedFile[ASSET_FILE_NAME_MAX];
|
||||||
|
|
||||||
// Scratch space for cutsceneGoTo's re-parse of loadedFile - a fixed,
|
// Cutscene items scratch, mostly used for CUTSCENE_INSERT items.
|
||||||
// persistent buffer rather than a local one since cutsceneitem_t is
|
|
||||||
// large (e.g. cutscenemodal_t alone carries a 256-byte message buffer),
|
|
||||||
// making a CUTSCENE_LOADED_ITEMS_MAX-sized array too big to put on the
|
|
||||||
// stack on constrained platforms (PSP/GameCube/Wii).
|
|
||||||
cutsceneitem_t gotoScratchItems[CUTSCENE_LOADED_ITEMS_MAX];
|
cutsceneitem_t gotoScratchItems[CUTSCENE_LOADED_ITEMS_MAX];
|
||||||
} cutscenesystem_t;
|
} cutscenesystem_t;
|
||||||
|
|
||||||
@@ -157,15 +139,19 @@ void cutsceneSystemInsertItems(
|
|||||||
void cutsceneSystemInsertCutscene(const cutscene_t *cutscene);
|
void cutsceneSystemInsertCutscene(const cutscene_t *cutscene);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discards every item still queued behind the currently-running one,
|
* Discards every item queued after index (e.g. index 0 keeps only the
|
||||||
* without disturbing that item's own progress - e.g. so a callback that
|
* currently-running item and drops everything spliced in behind it),
|
||||||
|
* without disturbing index's own progress - e.g. so a callback that
|
||||||
* decides the rest of a batch-spliced sequence is now moot (a battle
|
* decides the rest of a batch-spliced sequence is now moot (a battle
|
||||||
* ending mid-round, with other fighters' still-queued move cutscenes and
|
* ending mid-round, with other fighters' still-queued move cutscenes and
|
||||||
* the round's trailing state transition left behind) can drop it before
|
* the round's trailing state transition left behind) can drop it before
|
||||||
* splicing in its own follow-up items, instead of leaving it to run
|
* splicing in its own follow-up items, instead of leaving it to run
|
||||||
* afterward against torn-down state.
|
* afterward against torn-down state.
|
||||||
|
*
|
||||||
|
* @param index Index to keep - everything after it is discarded. Must be
|
||||||
|
* < the running cutscene's current item count.
|
||||||
*/
|
*/
|
||||||
void cutsceneSystemDiscardQueued(void);
|
void cutsceneSystemClearAfter(const uint8_t index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads and immediately starts a cutscene asset by file name.
|
* Loads and immediately starts a cutscene asset by file name.
|
||||||
@@ -235,25 +221,12 @@ void cutsceneSystemSetTextCache(const char_t *text);
|
|||||||
void cutsceneSystemNext();
|
void cutsceneSystemNext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jumps the running cutscene directly to the marker with the given name
|
* Jumps to a cutscene marker directly. If the cutscene is a loaded cutscene,
|
||||||
* and starts it immediately. Re-parses the cutscene fresh from its
|
* this will result in it being reloaded (due to unshift nature of cutscenes).
|
||||||
* source file (see cutsceneLoadParse) and replaces the live queue with
|
|
||||||
* marker-onward from that fresh parse - items already run may have been
|
|
||||||
* evicted from the front of the live queue (see
|
|
||||||
* cutsceneSystemNext/cutsceneRemoveFront), so a marker behind the
|
|
||||||
* current position can only be found in the untouched original. Nothing
|
|
||||||
* before the marker gets Started, only the marker item itself.
|
|
||||||
*
|
|
||||||
* Requires the running cutscene to be the one cutsceneSystemLoad/
|
|
||||||
* cutsceneCutsceneResolve populated (i.e. CUTSCENE_SYSTEM.scene ==
|
|
||||||
* &CUTSCENE_SYSTEM.loadedScene) - asserts otherwise. A C-authored
|
|
||||||
* cutscene_t, or content spliced in via INSERT/battleStateExecutingInit,
|
|
||||||
* has no source file to reload from, so backward jumps into those
|
|
||||||
* aren't supported yet.
|
|
||||||
*
|
*
|
||||||
* @param name Marker name to search for.
|
* @param name Marker name to search for.
|
||||||
*/
|
*/
|
||||||
void cutsceneGoTo(const char_t *name);
|
void cutsceneSystemGoTo(const char_t *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the cutscene system for one frame.
|
* Update the cutscene system for one frame.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ void cutsceneBattlePostMoveStart(
|
|||||||
// still-pending move cutscenes, the trailing BATTLE_SET_STATE(PRE_ROUND) -
|
// still-pending move cutscenes, the trailing BATTLE_SET_STATE(PRE_ROUND) -
|
||||||
// see battleStateExecutingInit) - the battle is over, so none of that
|
// see battleStateExecutingInit) - the battle is over, so none of that
|
||||||
// should run against the WON/LOST/ENDING transition about to replace it.
|
// should run against the WON/LOST/ENDING transition about to replace it.
|
||||||
cutsceneSystemDiscardQueued();
|
cutsceneSystemClearAfter(CUTSCENE_SYSTEM.currentItem);
|
||||||
|
|
||||||
const cutsceneitem_t items[] = {
|
const cutsceneitem_t items[] = {
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
/**
|
/**
|
||||||
* Updates an idle item. Never completes on its own - the cutscene blocks
|
* Updates an idle item. Never completes on its own - the cutscene blocks
|
||||||
* here indefinitely until something external (e.g. a UI callback) calls
|
* here indefinitely until something external (e.g. a UI callback) calls
|
||||||
* cutsceneGoTo to jump elsewhere.
|
* cutsceneSystemGoTo to jump elsewhere.
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ typedef struct {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a marker item. A marker does nothing on its own - it exists
|
* Starts a marker item. A marker does nothing on its own - it exists
|
||||||
* purely as a named position for cutsceneGoTo to jump to.
|
* purely as a named position for cutsceneSystemGoTo to jump to.
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -481,9 +481,9 @@ cutscene_t * cutsceneCutsceneResolve(const char_t *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shares loadedScene/loadedItems with cutsceneSystemLoad, so track the
|
// Shares loadedScene/loadedItems with cutsceneSystemLoad, so track the
|
||||||
// source the same way it does - cutsceneGoTo needs this to reload the
|
// source the same way it does - cutsceneSystemGoTo needs this to reload the
|
||||||
// untouched original when jumping to a marker behind the current
|
// untouched original when jumping to a marker behind the current
|
||||||
// position (see cutsceneGoTo's doc comment).
|
// position (see cutsceneSystemGoTo's doc comment).
|
||||||
stringCopy(CUTSCENE_SYSTEM.loadedFile, nameCopy, ASSET_FILE_NAME_MAX - 1);
|
stringCopy(CUTSCENE_SYSTEM.loadedFile, nameCopy, ASSET_FILE_NAME_MAX - 1);
|
||||||
|
|
||||||
return &CUTSCENE_SYSTEM.loadedScene;
|
return &CUTSCENE_SYSTEM.loadedScene;
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ void cutsceneEntityAddStart(
|
|||||||
entityInit(entity, item->entityAdd.entityType);
|
entityInit(entity, item->entityAdd.entityType);
|
||||||
entityPositionSet(entity, item->entityAdd.position);// Also assigns chunk.
|
entityPositionSet(entity, item->entityAdd.position);// Also assigns chunk.
|
||||||
|
|
||||||
CUTSCENE_SYSTEM.entityLastCreated = entity;
|
CUTSCENE_SYSTEM.refs.entityLastCreated = entity;
|
||||||
CUTSCENE_SYSTEM.entityLastRef = entity;
|
CUTSCENE_SYSTEM.refs.entityLastRef = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t cutsceneEntityAddUpdate(
|
bool_t cutsceneEntityAddUpdate(
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ void cutsceneMapAreaAddStart(
|
|||||||
const cutsceneitem_t *item,
|
const cutsceneitem_t *item,
|
||||||
cutsceneitemdata_t *data
|
cutsceneitemdata_t *data
|
||||||
) {
|
) {
|
||||||
CUTSCENE_SYSTEM.areaLastCreated = mapAreaAdd(
|
CUTSCENE_SYSTEM.refs.areaLastCreated = mapAreaAdd(
|
||||||
item->mapAreaAdd.min,
|
item->mapAreaAdd.min,
|
||||||
item->mapAreaAdd.max,
|
item->mapAreaAdd.max,
|
||||||
item->mapAreaAdd.callback,
|
item->mapAreaAdd.callback,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ typedef struct {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a map area add step (adds the area immediately, storing its ID
|
* Starts a map area add step (adds the area immediately, storing its ID
|
||||||
* in CUTSCENE_SYSTEM.areaLastCreated).
|
* in CUTSCENE_SYSTEM.refs.areaLastCreated).
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
void cutsceneSaveDeviceCheckCallback(savedevice_t *device, void *user) {
|
void cutsceneSaveDeviceCheckCallback(savedevice_t *device, void *user) {
|
||||||
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
||||||
cutsceneGoTo(
|
cutsceneSystemGoTo(
|
||||||
device != NULL ?
|
device != NULL ?
|
||||||
item->saveDeviceCheck.successMarker :
|
item->saveDeviceCheck.successMarker :
|
||||||
item->saveDeviceCheck.failureMarker
|
item->saveDeviceCheck.failureMarker
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ void cutsceneSaveDeviceCheckStart(
|
|||||||
* Updates a save-device-check item. Like a CUTSCENE_MODAL_OPTIONS item,
|
* Updates a save-device-check item. Like a CUTSCENE_MODAL_OPTIONS item,
|
||||||
* this never completes on its own - once saveFindAvailableDevice's
|
* this never completes on its own - once saveFindAvailableDevice's
|
||||||
* callback fires, it jumps straight to the item's successMarker or
|
* callback fires, it jumps straight to the item's successMarker or
|
||||||
* failureMarker via cutsceneGoTo.
|
* failureMarker via cutsceneSystemGoTo.
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ void cutsceneSaveLoadAllSlotsStart(
|
|||||||
errorret_t result = saveLoadAllSlots();
|
errorret_t result = saveLoadAllSlots();
|
||||||
if(errorIsNotOk(result)) {
|
if(errorIsNotOk(result)) {
|
||||||
errorCatch(errorPrint(result));
|
errorCatch(errorPrint(result));
|
||||||
cutsceneGoTo(item->saveLoadAllSlots.failureMarker);
|
cutsceneSystemGoTo(item->saveLoadAllSlots.failureMarker);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cutsceneGoTo(item->saveLoadAllSlots.successMarker);
|
cutsceneSystemGoTo(item->saveLoadAllSlots.successMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t cutsceneSaveLoadAllSlotsUpdate(
|
bool_t cutsceneSaveLoadAllSlotsUpdate(
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* Starts a save-load-all-slots item: calls saveLoadAllSlots() and jumps
|
* Starts a save-load-all-slots item: calls saveLoadAllSlots() and jumps
|
||||||
* straight to the item's successMarker or failureMarker via
|
* straight to the item's successMarker or failureMarker via
|
||||||
* cutsceneGoTo, depending on the result.
|
* cutsceneSystemGoTo, depending on the result.
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ void cutsceneModalStart(
|
|||||||
* CUTSCENE_MODAL_OPTIONS) always blocks regardless of the blocking
|
* CUTSCENE_MODAL_OPTIONS) always blocks regardless of the blocking
|
||||||
* field - it's dismissed by the player picking one of them, and the
|
* field - it's dismissed by the player picking one of them, and the
|
||||||
* option callback is responsible for moving the cutscene on from there
|
* option callback is responsible for moving the cutscene on from there
|
||||||
* (typically via cutsceneGoTo or cutsceneRestart).
|
* (typically via cutsceneSystemGoTo or cutsceneRestart).
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ void cutsceneModalOptionsMarkersCallback(
|
|||||||
// the modal directly (uiModalClose) before an option is picked.
|
// the modal directly (uiModalClose) before an option is picked.
|
||||||
const uint8_t index =
|
const uint8_t index =
|
||||||
optionIndex < options->optionCount ? optionIndex : options->optionCount - 1;
|
optionIndex < options->optionCount ? optionIndex : options->optionCount - 1;
|
||||||
cutsceneGoTo(options->markers[index]);
|
cutsceneSystemGoTo(options->markers[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cutsceneModalOptionsMarkersStart(
|
void cutsceneModalOptionsMarkersStart(
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ typedef struct {
|
|||||||
char_t message[CUTSCENE_MODAL_MESSAGE_MAX_CHARS];
|
char_t message[CUTSCENE_MODAL_MESSAGE_MAX_CHARS];
|
||||||
|
|
||||||
// Each option's display text/locale message ID, and the marker to
|
// Each option's display text/locale message ID, and the marker to
|
||||||
// cutsceneGoTo when that option is selected. Copied by value at parse
|
// cutsceneSystemGoTo when that option is selected. Copied by value at parse
|
||||||
// time (see cutsceneModalOptionsMarkersLoad), so they stay valid
|
// time (see cutsceneModalOptionsMarkersLoad), so they stay valid
|
||||||
// regardless of the backing JSON doc's lifetime.
|
// regardless of the backing JSON doc's lifetime.
|
||||||
char_t options[CUTSCENE_MODAL_OPTIONS_MARKERS_MAX][UI_MODAL_OPTION_TEXT_MAX];
|
char_t options[CUTSCENE_MODAL_OPTIONS_MARKERS_MAX][UI_MODAL_OPTION_TEXT_MAX];
|
||||||
@@ -47,7 +47,7 @@ void cutsceneModalOptionsMarkersStart(
|
|||||||
* the cutscene blocks here indefinitely. Back/cancel input is disabled
|
* the cutscene blocks here indefinitely. Back/cancel input is disabled
|
||||||
* while it's open (see uiMenuSetDisableBack), so it must be dismissed
|
* while it's open (see uiMenuSetDisableBack), so it must be dismissed
|
||||||
* by picking an option, which jumps straight to that option's marker
|
* by picking an option, which jumps straight to that option's marker
|
||||||
* via cutsceneGoTo.
|
* via cutsceneSystemGoTo.
|
||||||
*
|
*
|
||||||
* @param item The cutscene item.
|
* @param item The cutscene item.
|
||||||
* @param data Runtime data storage.
|
* @param data Runtime data storage.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ void cutsceneTextMiniStart(
|
|||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated = index;
|
CUTSCENE_SYSTEM.refs.textMiniLastCreated = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t cutsceneTextMiniUpdate(
|
bool_t cutsceneTextMiniUpdate(
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ void uiMainMenuStartGame(void) {
|
|||||||
if(cutscene == NULL) return;
|
if(cutscene == NULL) return;
|
||||||
cutsceneSystemStartCutsceneAndGoToMarker(cutscene, "NEW_GAME");
|
cutsceneSystemStartCutsceneAndGoToMarker(cutscene, "NEW_GAME");
|
||||||
} else {
|
} else {
|
||||||
cutsceneGoTo("NEW_GAME");
|
cutsceneSystemGoTo("NEW_GAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
cutsceneSystemSetOnComplete(uiMainMenuOpenSelectSave);
|
cutsceneSystemSetOnComplete(uiMainMenuOpenSelectSave);
|
||||||
@@ -93,7 +93,7 @@ void uiMainMenuOptions(void) {
|
|||||||
if(cutscene == NULL) return;
|
if(cutscene == NULL) return;
|
||||||
cutsceneSystemStartCutsceneAndGoToMarker(cutscene, "OPTIONS");
|
cutsceneSystemStartCutsceneAndGoToMarker(cutscene, "OPTIONS");
|
||||||
} else {
|
} else {
|
||||||
cutsceneGoTo("OPTIONS");
|
cutsceneSystemGoTo("OPTIONS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ void uiMainMenuQuit(void) {
|
|||||||
if(cutscene == NULL) return;
|
if(cutscene == NULL) return;
|
||||||
cutsceneSystemStartCutsceneAndGoToMarker(cutscene, "QUIT");
|
cutsceneSystemStartCutsceneAndGoToMarker(cutscene, "QUIT");
|
||||||
} else {
|
} else {
|
||||||
cutsceneGoTo("QUIT");
|
cutsceneSystemGoTo("QUIT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ static void test_cutsceneSystemStartWithSetsInteractEntities(void **state) {
|
|||||||
&CUTSCENE_TEST_SINGLE_WAIT, &ENTITIES[0], &ENTITIES[1]
|
&CUTSCENE_TEST_SINGLE_WAIT, &ENTITIES[0], &ENTITIES[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ptr_equal(CUTSCENE_SYSTEM.entityInteract, &ENTITIES[0]);
|
assert_ptr_equal(CUTSCENE_SYSTEM.refs.entityInteract, &ENTITIES[0]);
|
||||||
assert_ptr_equal(CUTSCENE_SYSTEM.entityInteracted, &ENTITIES[1]);
|
assert_ptr_equal(CUTSCENE_SYSTEM.refs.entityInteracted, &ENTITIES[1]);
|
||||||
assert_ptr_equal(
|
assert_ptr_equal(
|
||||||
cutsceneSystemGetEntity(CUTSCENE_ENTITY_INTERACT), &ENTITIES[0]
|
cutsceneSystemGetEntity(CUTSCENE_ENTITY_INTERACT), &ENTITIES[0]
|
||||||
);
|
);
|
||||||
@@ -122,8 +122,8 @@ static void test_cutsceneSystemStartWithSetsInteractEntities(void **state) {
|
|||||||
|
|
||||||
TIME.delta = 2.0f;
|
TIME.delta = 2.0f;
|
||||||
cutsceneSystemUpdate();// ends the cutscene
|
cutsceneSystemUpdate();// ends the cutscene
|
||||||
assert_null(CUTSCENE_SYSTEM.entityInteract);// reset on end
|
assert_null(CUTSCENE_SYSTEM.refs.entityInteract);// reset on end
|
||||||
assert_null(CUTSCENE_SYSTEM.entityInteracted);
|
assert_null(CUTSCENE_SYSTEM.refs.entityInteracted);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_cutsceneSystemGetEntitySentinelsRequireBeingSet(
|
static void test_cutsceneSystemGetEntitySentinelsRequireBeingSet(
|
||||||
@@ -158,26 +158,26 @@ static void test_cutsceneSystemGetAreaId(void **state) {
|
|||||||
cutsceneSystemInit();
|
cutsceneSystemInit();
|
||||||
// cutsceneSystemInit() zero-inits the field -- only actually starting a
|
// cutsceneSystemInit() zero-inits the field -- only actually starting a
|
||||||
// cutscene sets it to the "nothing created yet" sentinel.
|
// cutscene sets it to the "nothing created yet" sentinel.
|
||||||
CUTSCENE_SYSTEM.areaLastCreated = CUTSCENE_AREA_LAST_CREATED;
|
CUTSCENE_SYSTEM.refs.areaLastCreated = CUTSCENE_AREA_LAST_CREATED;
|
||||||
|
|
||||||
expect_assert_failure(cutsceneSystemGetAreaId(CUTSCENE_AREA_LAST_CREATED));
|
expect_assert_failure(cutsceneSystemGetAreaId(CUTSCENE_AREA_LAST_CREATED));
|
||||||
assert_int_equal(cutsceneSystemGetAreaId(5), 5);// direct IDs pass through
|
assert_int_equal(cutsceneSystemGetAreaId(5), 5);// direct IDs pass through
|
||||||
|
|
||||||
CUTSCENE_SYSTEM.areaLastCreated = 3;
|
CUTSCENE_SYSTEM.refs.areaLastCreated = 3;
|
||||||
assert_int_equal(cutsceneSystemGetAreaId(CUTSCENE_AREA_LAST_CREATED), 3);
|
assert_int_equal(cutsceneSystemGetAreaId(CUTSCENE_AREA_LAST_CREATED), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_cutsceneSystemGetTextMiniId(void **state) {
|
static void test_cutsceneSystemGetTextMiniId(void **state) {
|
||||||
|
|
||||||
cutsceneSystemInit();
|
cutsceneSystemInit();
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
|
CUTSCENE_SYSTEM.refs.textMiniLastCreated = CUTSCENE_TEXT_MINI_LAST_CREATED;
|
||||||
|
|
||||||
expect_assert_failure(
|
expect_assert_failure(
|
||||||
cutsceneSystemGetTextMiniId(CUTSCENE_TEXT_MINI_LAST_CREATED)
|
cutsceneSystemGetTextMiniId(CUTSCENE_TEXT_MINI_LAST_CREATED)
|
||||||
);
|
);
|
||||||
assert_int_equal(cutsceneSystemGetTextMiniId(4), 4);
|
assert_int_equal(cutsceneSystemGetTextMiniId(4), 4);
|
||||||
|
|
||||||
CUTSCENE_SYSTEM.textMiniLastCreated = 1;
|
CUTSCENE_SYSTEM.refs.textMiniLastCreated = 1;
|
||||||
assert_int_equal(
|
assert_int_equal(
|
||||||
cutsceneSystemGetTextMiniId(CUTSCENE_TEXT_MINI_LAST_CREATED), 1
|
cutsceneSystemGetTextMiniId(CUTSCENE_TEXT_MINI_LAST_CREATED), 1
|
||||||
);
|
);
|
||||||
@@ -195,15 +195,15 @@ static void test_cutsceneSystemDisposeResetsState(void **state) {
|
|||||||
assert_null(CUTSCENE_SYSTEM.scene);
|
assert_null(CUTSCENE_SYSTEM.scene);
|
||||||
assert_int_equal(CUTSCENE_SYSTEM.currentItem, 0xFF);
|
assert_int_equal(CUTSCENE_SYSTEM.currentItem, 0xFF);
|
||||||
assert_int_equal(CUTSCENE_SYSTEM.pause, CUTSCENE_PAUSE_NONE);
|
assert_int_equal(CUTSCENE_SYSTEM.pause, CUTSCENE_PAUSE_NONE);
|
||||||
assert_null(CUTSCENE_SYSTEM.entityInteract);
|
assert_null(CUTSCENE_SYSTEM.refs.entityInteract);
|
||||||
assert_null(CUTSCENE_SYSTEM.entityInteracted);
|
assert_null(CUTSCENE_SYSTEM.refs.entityInteracted);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- loadedFile survival across cutsceneSystemPrepare -------------------
|
// --- loadedFile survival across cutsceneSystemPrepare -------------------
|
||||||
//
|
//
|
||||||
// cutsceneCutsceneResolve (and cutsceneSystemLoad) stamp
|
// cutsceneCutsceneResolve (and cutsceneSystemLoad) stamp
|
||||||
// CUTSCENE_SYSTEM.loadedFile with what they just parsed loadedScene from
|
// CUTSCENE_SYSTEM.loadedFile with what they just parsed loadedScene from
|
||||||
// - cutsceneGoTo needs that to survive so it can reload the same source
|
// - cutsceneSystemGoTo needs that to survive so it can reload the same source
|
||||||
// later. cutsceneCutsceneResolve's caller stamps it BEFORE calling
|
// later. cutsceneCutsceneResolve's caller stamps it BEFORE calling
|
||||||
// cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene), so
|
// cutsceneSystemStartCutscene(&CUTSCENE_SYSTEM.loadedScene), so
|
||||||
// cutsceneSystemPrepare must not blindly clear loadedFile on every
|
// cutsceneSystemPrepare must not blindly clear loadedFile on every
|
||||||
@@ -212,7 +212,7 @@ static void test_cutsceneSystemDisposeResetsState(void **state) {
|
|||||||
// regression-tests the exact bug hit via initial.jsonc's CUTSCENE item
|
// regression-tests the exact bug hit via initial.jsonc's CUTSCENE item
|
||||||
// into main_menu.jsonc: cutsceneCutsceneResolve stamped loadedFile, then
|
// into main_menu.jsonc: cutsceneCutsceneResolve stamped loadedFile, then
|
||||||
// the immediately following cutsceneSystemStartCutscene call wiped it
|
// the immediately following cutsceneSystemStartCutscene call wiped it
|
||||||
// straight back out, so a later cutsceneGoTo on the still-running
|
// straight back out, so a later cutsceneSystemGoTo on the still-running
|
||||||
// cutscene had nothing to reload from.
|
// cutscene had nothing to reload from.
|
||||||
static void test_cutsceneSystemPrepareKeepsLoadedFileWhenReenteringLoadedScene(
|
static void test_cutsceneSystemPrepareKeepsLoadedFileWhenReenteringLoadedScene(
|
||||||
void **state
|
void **state
|
||||||
@@ -551,8 +551,8 @@ static void test_cutsceneInsertDoesNotResetPauseOrInteractEntities(
|
|||||||
// been popped off the front, only the snippet's one item is left.
|
// been popped off the front, only the snippet's one item is left.
|
||||||
assert_ptr_equal(CUTSCENE_SYSTEM.scene, &CUTSCENE_TEST_INSERT_PERSIST_OUTER);
|
assert_ptr_equal(CUTSCENE_SYSTEM.scene, &CUTSCENE_TEST_INSERT_PERSIST_OUTER);
|
||||||
assert_int_equal(CUTSCENE_SYSTEM.scene->itemCount, 1);
|
assert_int_equal(CUTSCENE_SYSTEM.scene->itemCount, 1);
|
||||||
assert_ptr_equal(CUTSCENE_SYSTEM.entityInteract, &ENTITIES[3]);
|
assert_ptr_equal(CUTSCENE_SYSTEM.refs.entityInteract, &ENTITIES[3]);
|
||||||
assert_ptr_equal(CUTSCENE_SYSTEM.entityInteracted, &ENTITIES[4]);
|
assert_ptr_equal(CUTSCENE_SYSTEM.refs.entityInteracted, &ENTITIES[4]);
|
||||||
// The snippet declares ALL, but INSERT doesn't apply it -- the outer
|
// The snippet declares ALL, but INSERT doesn't apply it -- the outer
|
||||||
// cutscene's NPC pause, already in effect, stands.
|
// cutscene's NPC pause, already in effect, stands.
|
||||||
assert_int_equal(CUTSCENE_SYSTEM.pause, CUTSCENE_PAUSE_NPC);
|
assert_int_equal(CUTSCENE_SYSTEM.pause, CUTSCENE_PAUSE_NPC);
|
||||||
|
|||||||
Reference in New Issue
Block a user