Remove per-item cutscene authoring macros

Every CUTSCENE_XXX(...) shorthand (CUTSCENE_WAIT, CUTSCENE_TEXT,
CUTSCENE_ENTITY_WALK_TO, etc.) existed to build a cutsceneitem_t literal
in C; real cutscenes are now authored exclusively as .jsonc files, and
the only other users were test fixtures. Deletes all ~55 of these
macros (and the shared CUTSCENE_ITEM(...) helper they built on) along
with their doc comments, leaving each item's struct/enum/Start/Update/
Load declarations untouched.

test_battle.c, test_cutscenecontrol.c, test_cutscenemaparea.c,
test_cutscenesystem.c and test_entityinteract.c now build their
cutsceneitem_t fixtures as plain struct literals instead.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-09-14 11:20:58 -05:00
co-authored by Claude Sonnet 5
parent 1646e964b5
commit 68cebce04a
48 changed files with 117 additions and 812 deletions
@@ -18,50 +18,6 @@ typedef struct {
easingtype_t easing;
} cutsceneaudiofade_t;
/**
* Longhand - starts CHANNEL fading from FROM to TO over DURATION seconds,
* eased by EASING. Doesn't wait for it - pair with
* CUTSCENE_AUDIO_FADE_WAIT(CHANNEL) to block until it finishes. See
* CUTSCENE_AUDIO_FADE_OUT/CUTSCENE_AUDIO_FADE_IN below for the
* shorthands; use this directly for a custom range, e.g.
* CUTSCENE_AUDIO_FADE(CHANNEL, 1.0f, 0.3f, 5.0f, EASING_LINEAR) to fade
* down to "playing quietly" rather than silent.
*
* @param CHANNEL audiomixerchannel_t to fade.
* @param FROM Starting volume (0.0-1.0).
* @param TO Ending volume (0.0-1.0).
* @param DURATION Duration in seconds.
* @param EASING easingtype_t to apply.
*/
#define CUTSCENE_AUDIO_FADE(CHANNEL, FROM, TO, DURATION, EASING) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_FADE, audioFade, { \
.channel = CHANNEL, \
.from = FROM, \
.to = TO, \
.duration = DURATION, \
.easing = EASING \
})
/**
* Shorthand: fade CHANNEL from full volume to silent over DURATION
* seconds.
*
* @param CHANNEL audiomixerchannel_t to fade.
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_AUDIO_FADE_OUT(CHANNEL, DURATION) \
CUTSCENE_AUDIO_FADE(CHANNEL, 1.0f, 0.0f, DURATION, EASING_LINEAR)
/**
* Shorthand: fade CHANNEL from silent to full volume over DURATION
* seconds.
*
* @param CHANNEL audiomixerchannel_t to fade.
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_AUDIO_FADE_IN(CHANNEL, DURATION) \
CUTSCENE_AUDIO_FADE(CHANNEL, 0.0f, 1.0f, DURATION, EASING_LINEAR)
/**
* Starts an audio fade step (starts the fade via audioMixerFadeTo() -
* doesn't wait for it; pair with CUTSCENE_AUDIO_FADE_WAIT to block on it).
@@ -9,15 +9,6 @@
#include "audio/mixer/audiomixerchannel.h"
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Waits until CHANNEL's fade (started elsewhere by CUTSCENE_AUDIO_FADE)
* has finished - a no-op wait if CHANNEL isn't fading.
*
* @param CHANNEL audiomixerchannel_t to wait on.
*/
#define CUTSCENE_AUDIO_FADE_WAIT(CHANNEL) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_FADE_WAIT, audioFadeWaitChannel, CHANNEL)
/**
* Updates an audio fade-wait step, completing once the watched channel's
* fade (started by a CUTSCENE_AUDIO_FADE elsewhere) finishes. Has no Start
@@ -9,14 +9,6 @@
#include "audio/mixer/audiomixerchannel.h"
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Pauses CHANNEL immediately.
*
* @param CHANNEL audiomixerchannel_t to pause.
*/
#define CUTSCENE_AUDIO_PAUSE(CHANNEL) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_PAUSE, audioPauseChannel, CHANNEL)
/**
* Starts an audio pause step (pauses the channel immediately).
*
@@ -20,55 +20,6 @@ typedef struct {
float_t loopTo;
} cutsceneaudioplay_t;
/**
* Longhand - queues a sound via audioMixerQueuePlay() (see its own
* comment on when it actually starts). See CUTSCENE_AUDIO_PLAY_SIMPLE/
* CUTSCENE_AUDIO_PLAY_LOOPED below for the shorthands.
*
* @param FILE Audio file path.
* @param CHANNEL audiomixerchannel_t to play on.
* @param VOLUME Playback volume (0.0-1.0).
* @param PAN Stereo pan (-1.0 left to 1.0 right, 0.0 centered).
* @param LOOPING Whether the clip loops.
* @param LOOP_COUNT Number of loop repeats (0 = infinite, if LOOPING).
* @param LOOP_START Loop region start in seconds, or -1.0f for the clip
* start.
* @param LOOP_TO Loop region end/return point in seconds.
*/
#define CUTSCENE_AUDIO_PLAY( \
FILE, CHANNEL, VOLUME, PAN, LOOPING, LOOP_COUNT, LOOP_START, LOOP_TO \
) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_PLAY, audioPlay, { \
.file = FILE, \
.channel = CHANNEL, \
.volume = VOLUME, \
.pan = PAN, \
.looping = LOOPING, \
.loopCount = LOOP_COUNT, \
.loopStart = LOOP_START, \
.loopTo = LOOP_TO \
})
/**
* Shorthand: play FILE on CHANNEL once, full volume, centered (0.0f, same
* as AUDIO_STREAM_CENTER), no loop.
*
* @param FILE Audio file path.
* @param CHANNEL audiomixerchannel_t to play on.
*/
#define CUTSCENE_AUDIO_PLAY_SIMPLE(FILE, CHANNEL) \
CUTSCENE_AUDIO_PLAY(FILE, CHANNEL, 1.0f, 0.0f, false, 0, -1.0f, 0.0f)
/**
* Shorthand: play FILE on CHANNEL looping the whole clip forever, full
* volume, centered (0.0f, same as AUDIO_STREAM_CENTER).
*
* @param FILE Audio file path.
* @param CHANNEL audiomixerchannel_t to play on.
*/
#define CUTSCENE_AUDIO_PLAY_LOOPED(FILE, CHANNEL) \
CUTSCENE_AUDIO_PLAY(FILE, CHANNEL, 1.0f, 0.0f, true, 0, -1.0f, 0.0f)
/**
* Starts an audio play step (queues the sound via audioMixerQueuePlay() -
* see its own comment on when it actually starts).
@@ -9,14 +9,6 @@
#include "audio/mixer/audiomixerchannel.h"
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Resumes CHANNEL immediately.
*
* @param CHANNEL audiomixerchannel_t to resume.
*/
#define CUTSCENE_AUDIO_RESUME(CHANNEL) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_RESUME, audioResumeChannel, CHANNEL)
/**
* Starts an audio resume step (resumes the channel immediately).
*
@@ -18,30 +18,6 @@ typedef struct {
float_t loopTo;
} cutsceneaudioset_t;
/**
* Combined form of CUTSCENE_AUDIO_SET_PAN + CUTSCENE_AUDIO_SET_LOOP, for
* setting both at once rather than as two separate items.
*
* @param CHANNEL audiomixerchannel_t to adjust.
* @param PAN Stereo pan (-1.0 left to 1.0 right, 0.0 centered).
* @param LOOPING Whether the clip loops.
* @param LOOP_COUNT Number of loop repeats (0 = infinite, if LOOPING).
* @param LOOP_START Loop region start in seconds, or -1.0f for the clip
* start.
* @param LOOP_TO Loop region end/return point in seconds.
*/
#define CUTSCENE_AUDIO_SET( \
CHANNEL, PAN, LOOPING, LOOP_COUNT, LOOP_START, LOOP_TO \
) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_SET, audioSet, { \
.channel = CHANNEL, \
.pan = PAN, \
.looping = LOOPING, \
.loopCount = LOOP_COUNT, \
.loopStart = LOOP_START, \
.loopTo = LOOP_TO \
})
/**
* Starts an audio set step - applies pan and looping behaviour together in
* one item (via audioMixerSetPan()/audioMixerSetLoop()), for when you want
@@ -17,27 +17,6 @@ typedef struct {
float_t loopTo;
} cutsceneaudiosetloop_t;
/**
* Applies new looping behaviour immediately, via audioMixerSetLoop().
*
* @param CHANNEL audiomixerchannel_t to adjust.
* @param LOOPING Whether the clip loops.
* @param LOOP_COUNT Number of loop repeats (0 = infinite, if LOOPING).
* @param LOOP_START Loop region start in seconds, or -1.0f for the clip
* start.
* @param LOOP_TO Loop region end/return point in seconds.
*/
#define CUTSCENE_AUDIO_SET_LOOP( \
CHANNEL, LOOPING, LOOP_COUNT, LOOP_START, LOOP_TO \
) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_SET_LOOP, audioSetLoop, { \
.channel = CHANNEL, \
.looping = LOOPING, \
.loopCount = LOOP_COUNT, \
.loopStart = LOOP_START, \
.loopTo = LOOP_TO \
})
/**
* Starts an audio set-loop step (applies the new looping behaviour
* immediately, via audioMixerSetLoop()).
@@ -14,17 +14,6 @@ typedef struct {
float_t pan;
} cutsceneaudiosetpan_t;
/**
* Applies a new pan immediately, via audioMixerSetPan().
*
* @param CHANNEL audiomixerchannel_t to adjust.
* @param PAN Stereo pan (-1.0 left to 1.0 right, 0.0 centered).
*/
#define CUTSCENE_AUDIO_SET_PAN(CHANNEL, PAN) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_SET_PAN, audioSetPan, { \
.channel = CHANNEL, .pan = PAN \
})
/**
* Starts an audio set-pan step (applies the new pan immediately, via
* audioMixerSetPan()).
@@ -9,14 +9,6 @@
#include "audio/mixer/audiomixerchannel.h"
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Stops CHANNEL immediately.
*
* @param CHANNEL audiomixerchannel_t to stop.
*/
#define CUTSCENE_AUDIO_STOP(CHANNEL) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_AUDIO_STOP, audioStopChannel, CHANNEL)
/**
* Starts an audio stop step (stops the channel immediately).
*
@@ -14,18 +14,6 @@ typedef struct {
uint8_t targetIndex;
} cutscenebattleforceaction_t;
/**
* Immediately queues an attack for FIGHTER_INDEX against TARGET_INDEX,
* bypassing normal player/AI selection for that fighter this round.
*
* @param FIGHTER_INDEX Attacking fighter's battle index.
* @param TARGET_INDEX Target fighter's battle index.
*/
#define CUTSCENE_BATTLE_FORCE_ACTION(FIGHTER_INDEX, TARGET_INDEX) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_BATTLE_FORCE_ACTION, battleForceAction, { \
.fighterIndex = FIGHTER_INDEX, .targetIndex = TARGET_INDEX \
})
/**
* Starts a battle force-action step: immediately queues an attack for the
* given fighter against the given target, bypassing normal player/AI
@@ -13,21 +13,6 @@ typedef struct {
battlestate_t state;
} cutscenebattlewaitstate_t;
/**
* Waits until BATTLE.state reaches STATE. Put this BEFORE
* CUTSCENE_SET_PAUSE(CUTSCENE_PAUSE_BATTLE), not after -- pausing first
* freezes BATTLE.state wherever it already is, so it would never reach
* STATE on its own to satisfy the wait. Waiting unpaused, then pausing
* the moment it's satisfied, catches the battle right at STATE before it
* can advance further.
*
* @param STATE battlestate_t to wait for.
*/
#define CUTSCENE_BATTLE_WAIT_STATE(STATE) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_BATTLE_WAIT_STATE, battleWaitState, { \
.state = STATE \
})
/**
* Updates a battle wait-state step, completing once BATTLE.state reaches
* the watched state. Has no Start callback -- there's nothing to do until
@@ -13,22 +13,6 @@
/** Maximum number of items that may run inside a CUTSCENE_CONCURRENT. */
#define CUTSCENE_CONCURRENT_MAX 8
/**
* Runs all listed items simultaneously and waits until all are done.
* Concurrent items cannot be nested inside another CUTSCENE_CONCURRENT.
*
* @param ... Child cutsceneitem_t entries (e.g. CUTSCENE_WAIT(...),
* CUTSCENE_ENTITY_WALK_TO(...)) to run at the same time.
*/
#define CUTSCENE_CONCURRENT(...) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_CONCURRENT, concurrent, { \
.items = (const cutsceneitem_t[]){ __VA_ARGS__ }, \
.count = (uint8_t)( \
sizeof((cutsceneitem_t[]){ __VA_ARGS__ }) / \
sizeof(cutsceneitem_t) \
) \
})
/**
* Static (const) data for a concurrent cutscene item.
*/
@@ -8,14 +8,6 @@
#pragma once
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Blocks the cutscene here indefinitely - it never completes on its own,
* only cutsceneGoTo (called externally, e.g. from a UI callback) can move
* execution past it.
*/
#define CUTSCENE_IDLE() \
{ .type = CUTSCENE_ITEM_TYPE_IDLE }
/**
* Updates an idle item. Never completes on its own - the cutscene blocks
* here indefinitely until something external (e.g. a UI callback) calls
@@ -12,17 +12,6 @@ typedef struct {
const char_t *name;
} cutscenemarker_t;
/**
* A named, otherwise no-op position in the item list that cutsceneGoTo
* can jump execution straight to.
*
* @param NAME Marker name, matched with stringEquals (not pointer
* identity) - safe to use separate string literals with the same
* contents at the marker and at each call site.
*/
#define CUTSCENE_MARKER(NAME) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MARKER, marker, { .name = NAME })
/**
* Starts a marker item. A marker does nothing on its own - it exists
* purely as a named position for cutsceneGoTo to jump to.
@@ -8,13 +8,6 @@
#pragma once
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Restarts the currently running cutscene from its first item,
* preserving whatever interact/interacted entities triggered it.
*/
#define CUTSCENE_RESTART() \
{ .type = CUTSCENE_ITEM_TYPE_RESTART }
/**
* Starts a restart item (restarts the currently running cutscene from
* its first item via cutsceneRestart).
@@ -13,17 +13,6 @@ typedef struct {
scenetype_t type;
} cutscenescene_t;
/**
* Requests a switch to a different SCENE_TYPE via sceneSet, then
* immediately continues on to whatever follows this item - the switch
* itself doesn't happen until the next sceneUpdate() tick, so it does
* not take effect this frame.
*
* @param TYPE Target scenetype_t to switch to.
*/
#define CUTSCENE_SCENE(TYPE) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_SCENE, sceneChange, { .type = TYPE })
/**
* Starts a scene item (requests a switch to the given scene via
* sceneSet). The switch itself doesn't happen until the next
@@ -9,14 +9,6 @@
#include "rpg/cutscene/cutscenepause.h"
#include "rpg/cutscene/item/cutsceneitembase.h"
/**
* Applies the given pause flags immediately.
*
* @param FLAGS CUTSCENE_PAUSE_* flags, OR'd together.
*/
#define CUTSCENE_SET_PAUSE(FLAGS) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_SET_PAUSE, setPause, (FLAGS))
/**
* Starts a set-pause item (applies the new pause flags immediately).
*
@@ -11,14 +11,6 @@
typedef float_t cutscenewait_t;
typedef float_t cutscenewaitdata_t;
/**
* Waits WAIT seconds before continuing.
*
* @param WAIT Duration in seconds.
*/
#define CUTSCENE_WAIT(WAIT) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_WAIT, wait, WAIT)
/**
* Starts a wait item (stores the duration in data).
*
@@ -10,15 +10,6 @@
typedef void (*cutscenecallback_t)(void *userData);
/**
* Invokes CALLBACK immediately, then continues on to whatever follows
* this item.
*
* @param CALLBACK A cutscenecallback_t function pointer.
*/
#define CUTSCENE_CALLBACK(CALLBACK) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_CALLBACK, callback, CALLBACK)
/**
* Starts a callback item (invokes the callback immediately).
*
@@ -68,21 +68,6 @@ typedef enum {
CUTSCENE_ITEM_TYPE_COUNT
} cutsceneitemtype_t;
/**
* Shorthand for a cutsceneitem_t literal - used by each item type's own
* authoring macro (e.g. CUTSCENE_WAIT in cutscenewait.h) to fill in .type
* and its union member together.
*
* @param TYPE The item's CUTSCENE_ITEM_TYPE_* enum value.
* @param UNION_NAME Name of the cutsceneitem_t union member to fill.
* @param ... The union member's value. Passed through __VA_ARGS__ (rather
* than a single named parameter) so it may itself be a brace initializer
* with top-level commas, e.g.
* CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_FADE, fade, { .from = A, .to = B }).
*/
#define CUTSCENE_ITEM(TYPE, UNION_NAME, ...) \
{ .type = TYPE, .UNION_NAME = __VA_ARGS__ }
/**
* Shared no-op Load for item types with no JSON fields of their own to
* parse (IDLE, RESTART, MODAL_CLOSE) - always succeeds without touching
@@ -14,14 +14,6 @@ typedef struct {
char_t text[CUTSCENE_PRINT_MAX_CHARS];
} cutsceneprint_t;
/**
* Prints TEXT to the console.
*
* @param TEXT Text to print.
*/
#define CUTSCENE_PRINT(TEXT) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_PRINT, print, { .text = TEXT })
/**
* Starts a print item (prints the item's text to the console).
*
@@ -15,19 +15,6 @@ typedef struct {
worldpos_t position;
} cutsceneentityadd_t;
/**
* Spawns a new entity into the world immediately.
*
* @param TYPE Entity type to spawn.
* @param X Spawn world X.
* @param Y Spawn world Y.
* @param Z Spawn world Z.
*/
#define CUTSCENE_ENTITY_ADD(TYPE, X, Y, Z) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ENTITY_ADD, entityAdd, { \
.entityType = TYPE, .position = { X, Y, Z } \
})
/**
* Starts an entity add step (spawns the entity into the world immediately).
*
@@ -12,16 +12,6 @@ typedef struct {
uint8_t entityIndex;
} cutsceneentityremove_t;
/**
* Removes an entity from the world immediately.
*
* @param ENTITY_INDEX Entity index to remove.
*/
#define CUTSCENE_ENTITY_REMOVE(ENTITY_INDEX) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ENTITY_REMOVE, entityRemove, { \
.entityIndex = ENTITY_INDEX \
})
/**
* Starts an entity remove step (removes the entity from the world immediately).
*
@@ -14,19 +14,6 @@ typedef struct {
worldpos_t target;
} cutsceneentityteleport_t;
/**
* Teleports an entity to a world position immediately.
*
* @param ENTITY_INDEX Entity index to teleport.
* @param X Target world X.
* @param Y Target world Y.
* @param Z Target world Z.
*/
#define CUTSCENE_ENTITY_TELEPORT(ENTITY_INDEX, X, Y, Z) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ENTITY_TELEPORT, entityTeleport, { \
.entityIndex = ENTITY_INDEX, .target = { X, Y, Z } \
})
/**
* Starts an entity teleport item (teleports the entity immediately).
*
@@ -14,17 +14,6 @@ typedef struct {
entitydir_t direction;
} cutsceneentityturn_t;
/**
* Turns an entity to face a direction.
*
* @param ENTITY_INDEX Entity index to turn.
* @param DIRECTION Target entitydir_t to face.
*/
#define CUTSCENE_ENTITY_TURN(ENTITY_INDEX, DIRECTION) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ENTITY_TURN, entityTurn, { \
.entityIndex = ENTITY_INDEX, .direction = DIRECTION \
})
/**
* Starts an entity turn step. The turn itself is driven from Update, since
* the entity may still be finishing a previous action.
@@ -25,45 +25,6 @@ typedef struct {
uint8_t currentIndex;
} cutsceneentitywalktodata_t;
/**
* Walks an entity to a single world position, navigating around
* obstacles.
*
* @param ENTITY_INDEX Entity index to move.
* @param X Target world X.
* @param Y Target world Y.
* @param Z Target world Z.
*/
#define CUTSCENE_ENTITY_WALK_TO(ENTITY_INDEX, X, Y, Z) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO, entityWalkTo, { \
.entityIndex = ENTITY_INDEX, \
.positions = { { X, Y, Z } }, \
.count = 1, \
.walkAround = true \
})
/**
* Declares a standalone, named cutsceneitem_t (not a list entry) that
* walks an entity through a fixed sequence of waypoints. ... must not
* exceed CUTSCENE_ENTITY_WALK_TO_MAX entries - the compiler rejects the
* initializer with "excess elements in array initializer" if it does.
*
* @param NAME Suffix for the generated CUTSCENE_##NAME static.
* @param ENTITY_INDEX Entity index to move.
* @param ... One or more worldpos_t-shaped waypoint initializers, e.g.
* { X, Y, Z }, { X2, Y2, Z2 } - at most CUTSCENE_ENTITY_WALK_TO_MAX.
*/
#define CUTSCENE_ENTITY_WALK_PATH(NAME, ENTITY_INDEX, ...) \
static const cutsceneitem_t CUTSCENE_##NAME = { \
.type = CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO, \
.entityWalkTo = { \
.entityIndex = ENTITY_INDEX, \
.positions = { __VA_ARGS__ }, \
.count = sizeof((const worldpos_t[]){ __VA_ARGS__ }) / sizeof(worldpos_t), \
.walkAround = true \
} \
};
/**
* Starts an entity walk-to item (resets the waypoint index).
*
@@ -16,27 +16,6 @@ typedef struct {
worldunit_t offsetY;
} cutsceneentitywalktoentity_t;
/**
* Walks ENTITY_INDEX to stand beside TARGET_ENTITY_INDEX, offset by
* (OFFSET_X, OFFSET_Y) on the 2D plane. The destination Z is resolved
* from nearby terrain each frame, so ramps between the two entities are
* accounted for automatically.
*
* @param ENTITY_INDEX Entity index to move.
* @param TARGET_ENTITY_INDEX Entity index to walk toward.
* @param OFFSET_X X offset from the target entity's position.
* @param OFFSET_Y Y offset from the target entity's position.
*/
#define CUTSCENE_ENTITY_WALK_TO_ENTITY( \
ENTITY_INDEX, TARGET_ENTITY_INDEX, OFFSET_X, OFFSET_Y \
) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ENTITY_WALK_TO_ENTITY, entityWalkToEntity, { \
.entityIndex = ENTITY_INDEX, \
.targetEntityIndex = TARGET_ENTITY_INDEX, \
.offsetX = OFFSET_X, \
.offsetY = OFFSET_Y \
})
/**
* Starts an entity walk-to-entity item. No setup is needed, the destination
* is recomputed from the target's live position every Update.
@@ -14,17 +14,6 @@ typedef struct {
uint8_t quantity;
} cutsceneitemgive_t;
/**
* Adds an item to the player's backpack immediately.
*
* @param ITEM_ID Item ID to give.
* @param QUANTITY Quantity to give.
*/
#define CUTSCENE_ITEM_GIVE(ITEM_ID, QUANTITY) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_ITEM_GIVE, itemGive, { \
.item = ITEM_ID, .quantity = QUANTITY \
})
/**
* Starts a give-item step (adds the item to the player's backpack immediately).
*
@@ -19,55 +19,6 @@ typedef struct {
uint8_t trigger;
} cutscenemapareaadd_t;
/**
* Adds a map area immediately, storing its ID in
* CUTSCENE_SYSTEM.areaLastCreated.
*
* @param MIN_X Area bounding box minimum world X.
* @param MIN_Y Area bounding box minimum world Y.
* @param MIN_Z Area bounding box minimum world Z.
* @param MAX_X Area bounding box maximum world X.
* @param MAX_Y Area bounding box maximum world Y.
* @param MAX_Z Area bounding box maximum world Z.
* @param CALLBACK mapareacallback_t to invoke when the area is triggered.
* @param NOTIFY Notify count/threshold passed to the area.
* @param TRIGGER Trigger count/threshold passed to the area.
*/
#define CUTSCENE_MAP_AREA_ADD( \
MIN_X, MIN_Y, MIN_Z, MAX_X, MAX_Y, MAX_Z, CALLBACK, NOTIFY, TRIGGER \
) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MAP_AREA_ADD, mapAreaAdd, { \
.min = { MIN_X, MIN_Y, MIN_Z }, \
.max = { MAX_X, MAX_Y, MAX_Z }, \
.callback = CALLBACK, \
.notify = NOTIFY, \
.trigger = TRIGGER \
})
/**
* Adds a map area, waits for it to be triggered once, then removes it
* before the cutscene continues. Uses a no-op callback since the wait is
* driven by the area's trigger count rather than callback logic.
*
* @param MIN_X Area bounding box minimum world X.
* @param MIN_Y Area bounding box minimum world Y.
* @param MIN_Z Area bounding box minimum world Z.
* @param MAX_X Area bounding box maximum world X.
* @param MAX_Y Area bounding box maximum world Y.
* @param MAX_Z Area bounding box maximum world Z.
* @param NOTIFY Notify count/threshold passed to the area.
* @param TRIGGER Trigger count/threshold passed to the area.
*/
#define CUTSCENE_MAP_AREA_TRIGGER_ONCE( \
MIN_X, MIN_Y, MIN_Z, MAX_X, MAX_Y, MAX_Z, NOTIFY, TRIGGER \
) \
CUTSCENE_MAP_AREA_ADD( \
MIN_X, MIN_Y, MIN_Z, MAX_X, MAX_Y, MAX_Z, \
mapAreaNoopCallback, NOTIFY, TRIGGER \
), \
CUTSCENE_MAP_AREA_WAIT(CUTSCENE_AREA_LAST_CREATED), \
CUTSCENE_MAP_AREA_REMOVE(CUTSCENE_AREA_LAST_CREATED)
/**
* Starts a map area add step (adds the area immediately, storing its ID
* in CUTSCENE_SYSTEM.areaLastCreated).
@@ -12,17 +12,6 @@ typedef struct {
uint8_t areaId;
} cutscenemaparearemove_t;
/**
* Removes a map area immediately.
*
* @param AREA_ID Area ID to remove, or CUTSCENE_AREA_LAST_CREATED in
* place of a literal area ID.
*/
#define CUTSCENE_MAP_AREA_REMOVE(AREA_ID) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MAP_AREA_REMOVE, mapAreaRemove, { \
.areaId = AREA_ID \
})
/**
* Starts a map area remove step (removes the area immediately). Accepts
* CUTSCENE_AREA_LAST_CREATED in place of a literal area ID.
@@ -20,20 +20,6 @@ typedef struct {
uint32_t baseline[CUTSCENE_MAP_AREA_WAIT_MAX];
} cutscenemapareawaitdata_t;
/**
* Waits until any one of the given map area IDs has its callback invoked.
*
* @param ... One or more area IDs to watch. Accepts
* CUTSCENE_AREA_LAST_CREATED in place of a literal area ID.
*/
#define CUTSCENE_MAP_AREA_WAIT(...) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT, mapAreaWait, { \
.areaIds = { __VA_ARGS__ }, \
.count = (uint8_t)( \
sizeof((const uint8_t[]){ __VA_ARGS__ }) / sizeof(uint8_t) \
) \
})
/**
* Starts a map area wait step, snapshotting each watched area's current
* trigger count.
@@ -13,22 +13,6 @@ typedef struct {
const char_t *failureMarker;
} cutscenesavedevicecheck_t;
/**
* (Re)requests an available save device and jumps straight to
* SUCCESS_MARKER or FAILURE_MARKER once it resolves, same as a
* CUTSCENE_MODAL_OPTIONS callback - it does not fall through to
* whatever follows this item, so both markers must be scripted
* elsewhere in the same cutscene.
*
* @param SUCCESS_MARKER Marker to jump to if a device is available.
* @param FAILURE_MARKER Marker to jump to if no device is available.
*/
#define CUTSCENE_SAVE_DEVICE_CHECK(SUCCESS_MARKER, FAILURE_MARKER) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_SAVE_DEVICE_CHECK, saveDeviceCheck, { \
.successMarker = SUCCESS_MARKER, \
.failureMarker = FAILURE_MARKER \
})
/**
* Starts a save-device-check item: (re)requests an available save
* device via saveFindAvailableDevice. Never completes on its own - see
@@ -13,22 +13,6 @@ typedef struct {
const char_t *failureMarker;
} cutscenesaveloadallslots_t;
/**
* (Re)loads every save slot via saveLoadAllSlots() and jumps straight to
* SUCCESS_MARKER or FAILURE_MARKER once it resolves, same shape as
* CUTSCENE_SAVE_DEVICE_CHECK - it does not fall through to whatever
* follows this item, so both markers must be scripted elsewhere in the
* same cutscene.
*
* @param SUCCESS_MARKER Marker to jump to on success.
* @param FAILURE_MARKER Marker to jump to on failure.
*/
#define CUTSCENE_SAVE_LOAD_ALL_SLOTS(SUCCESS_MARKER, FAILURE_MARKER) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_SAVE_LOAD_ALL_SLOTS, saveLoadAllSlots, { \
.successMarker = SUCCESS_MARKER, \
.failureMarker = FAILURE_MARKER \
})
/**
* Starts a save-load-all-slots item: calls saveLoadAllSlots() and jumps
* straight to the item's successMarker or failureMarker via
@@ -15,21 +15,6 @@ typedef struct {
uiemojitype_t emojiType;
} cutsceneemoji_t;
/**
* Shows an emoji above an entity for a duration, then completes
* immediately.
*
* @param ENTITY_INDEX Entity index to show the emoji above.
* @param EMOJI_TYPE uiemojitype_t to show.
* @param DURATION Duration in seconds to show it.
*/
#define CUTSCENE_EMOJI(ENTITY_INDEX, EMOJI_TYPE, DURATION) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_EMOJI, emoji, { \
.entityIndex = ENTITY_INDEX, \
.emojiType = EMOJI_TYPE, \
.duration = DURATION \
})
/**
* Starts an emoji step (shows an emoji above the entity for the given
* duration, then completes immediately).
@@ -17,52 +17,6 @@ typedef struct {
easingtype_t easing;
} cutscenefade_t;
/**
* Longhand - begins a full-screen overlay transition between two colors.
* See the CUTSCENE_FADE_(TO|FROM)_(BLACK|WHITE) shorthands below.
*
* @param FROM Starting color_t.
* @param TO Ending color_t.
* @param DURATION Duration in seconds.
* @param EASING easingtype_t to apply.
*/
#define CUTSCENE_FADE(FROM, TO, DURATION, EASING) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_FADE, fade, { \
.from = FROM, .to = TO, .duration = DURATION, .easing = EASING \
})
/**
* Shorthand: fades from transparent to black over DURATION seconds.
*
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_FADE_TO_BLACK(DURATION) \
CUTSCENE_FADE(COLOR_TRANSPARENT_BLACK, COLOR_BLACK, DURATION, EASING_LINEAR)
/**
* Shorthand: fades from black to transparent over DURATION seconds.
*
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_FADE_FROM_BLACK(DURATION) \
CUTSCENE_FADE(COLOR_BLACK, COLOR_TRANSPARENT_BLACK, DURATION, EASING_LINEAR)
/**
* Shorthand: fades from transparent to white over DURATION seconds.
*
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_FADE_TO_WHITE(DURATION) \
CUTSCENE_FADE(COLOR_TRANSPARENT_WHITE, COLOR_WHITE, DURATION, EASING_LINEAR)
/**
* Shorthand: fades from white to transparent over DURATION seconds.
*
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_FADE_FROM_WHITE(DURATION) \
CUTSCENE_FADE(COLOR_WHITE, COLOR_TRANSPARENT_WHITE, DURATION, EASING_LINEAR)
/**
* Starts a fade item (begins the overlay transition).
*
@@ -14,19 +14,6 @@ typedef struct {
uikeyboardopen_t open;
} cutscenekeyboard_t;
/**
* Opens the on-screen keyboard and blocks the cutscene until it closes,
* then caches whatever was typed - see cutsceneSystemGetTextCache to
* read it back afterwards.
*
* @param ... uikeyboardopen_t designated initializers, e.g.
* CUTSCENE_KEYBOARD(.cancel = true, .maxLength = 8).
*/
#define CUTSCENE_KEYBOARD(...) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_KEYBOARD, keyboard, { \
.open = { __VA_ARGS__ } \
})
/**
* Starts a keyboard item (opens the on-screen keyboard with the item's
* open parameters, unmodified - see uiKeyboardOpen).
@@ -41,59 +41,6 @@ typedef struct {
cutscenemodaloptioncallback_t callback;
} cutscenemodal_t;
/**
* Shows a message-only modal (no option buttons) and immediately
* continues on to whatever follows this item - it does not wait for
* the dialog to be dismissed. Script the rest of the interaction (e.g.
* CUTSCENE_CALLBACK to kick off work, CUTSCENE_WAIT, then
* CUTSCENE_MODAL_CLOSE) as later items in the same cutscene.
*
* @param TITLE Modal title - displayed as-is unless it matches a locale
* message ID, in which case the translated string is shown - see
* uiModalLocalize.
* @param MESSAGE Modal message, same locale-matching rule as TITLE.
*/
#define CUTSCENE_MODAL(TITLE, MESSAGE) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MODAL, modal, { \
.title = TITLE, .message = MESSAGE \
})
/**
* Shows a modal with option buttons and immediately continues on, same
* as CUTSCENE_MODAL - it does not block waiting for a selection.
* Back/cancel input is disabled while it's open (see
* uiMenuSetDisableBack), so it must be dismissed by picking one; CALLBACK
* then fires with the selected option index once the dialog closes.
*
* @param TITLE Modal title (locale-matched, see CUTSCENE_MODAL).
* @param MESSAGE Modal message (locale-matched, see CUTSCENE_MODAL).
* @param CALLBACK cutscenemodaloptioncallback_t fired with the selected
* option index once the dialog closes.
* @param ... Option label strings, e.g.
* CUTSCENE_MODAL_OPTIONS(title, message, callback, "Retry", "Cancel") -
* not copied by this item, so they must stay valid until the modal opens
* (string literals are fine). Each is translated if it matches a locale
* message ID, same as TITLE/MESSAGE.
*/
#define CUTSCENE_MODAL_OPTIONS(TITLE, MESSAGE, CALLBACK, ...) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MODAL, modal, { \
.title = TITLE, .message = MESSAGE, \
.options = (const char_t *[]){ __VA_ARGS__ }, \
.optionCount = (uint8_t)( \
sizeof((const char_t *[]){ __VA_ARGS__ }) / sizeof(const char_t *) \
), \
.callback = CALLBACK \
})
/**
* Closes the currently open modal (if any). Useful when a modal was
* opened outside of a blocking CUTSCENE_MODAL item (e.g. directly via
* uiModalOpen) and this cutscene just needs to dismiss it and continue
* on to whatever follows this item in the sequence.
*/
#define CUTSCENE_MODAL_CLOSE() \
{ .type = CUTSCENE_ITEM_TYPE_MODAL_CLOSE }
/**
* Starts a modal item (shows the modal dialog with the item's title,
* message, and options, wiring callback to fire with the selected
@@ -26,49 +26,6 @@ typedef struct {
uint8_t optionCount;
} cutscenemodaloptionsmarkers_t;
/**
* Same as CUTSCENE_MODAL_OPTIONS, but fixed to exactly one option and
* MARKER1 to jump straight to via cutsceneGoTo once it's selected - no
* callback function to write. Does not fall through to whatever follows
* this item, so MARKER1 must be scripted elsewhere in the same cutscene.
*
* @param TITLE Modal title (locale-matched, see CUTSCENE_MODAL).
* @param MESSAGE Modal message (locale-matched, see CUTSCENE_MODAL).
* @param OPTION1 The single option's label.
* @param MARKER1 Marker to jump to when OPTION1 is selected.
*/
#define CUTSCENE_MODAL_OPTIONS_ONE(TITLE, MESSAGE, OPTION1, MARKER1) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MODAL_OPTIONS_MARKERS, modalOptionsMarkers, { \
.title = TITLE, .message = MESSAGE, \
.options = { OPTION1 }, \
.markers = { MARKER1 }, \
.optionCount = 1 \
})
/**
* Same as CUTSCENE_MODAL_OPTIONS, but fixed to exactly two options,
* jumping straight to OPTION1_MARKER or OPTION2_MARKER via cutsceneGoTo
* once the corresponding option is selected - no callback function to
* write. Does not fall through to whatever follows this item, so both
* markers must be scripted elsewhere in the same cutscene.
*
* @param TITLE Modal title (locale-matched, see CUTSCENE_MODAL).
* @param MESSAGE Modal message (locale-matched, see CUTSCENE_MODAL).
* @param OPTION1 First option's label.
* @param OPTION1_MARKER Marker to jump to when OPTION1 is selected.
* @param OPTION2 Second option's label.
* @param OPTION2_MARKER Marker to jump to when OPTION2 is selected.
*/
#define CUTSCENE_MODAL_OPTIONS_TWO( \
TITLE, MESSAGE, OPTION1, OPTION1_MARKER, OPTION2, OPTION2_MARKER \
) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_MODAL_OPTIONS_MARKERS, modalOptionsMarkers, { \
.title = TITLE, .message = MESSAGE, \
.options = { OPTION1, OPTION2 }, \
.markers = { OPTION1_MARKER, OPTION2_MARKER }, \
.optionCount = 2 \
})
/**
* Starts a modal-options-markers item (shows the modal dialog with the
* item's title, message, and options).
@@ -13,18 +13,6 @@ typedef struct {
float_t duration;
} cutsceneshake_t;
/**
* Kicks off a camera shake immediately.
*
* @param AMOUNT Shake amount, 0 (no shake) to 4 (three tiles): 1 is half
* a tile, 2 is a full tile, 3 is two tiles, and 4 is three tiles.
* @param DURATION Duration in seconds.
*/
#define CUTSCENE_SHAKE(AMOUNT, DURATION) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_SHAKE, shake, { \
.amount = AMOUNT, .duration = DURATION \
})
/**
* Starts a camera shake item (kicks off the shake on the RPG camera).
*
@@ -14,14 +14,6 @@ typedef struct {
char_t text[CUTSCENE_TEXT_MAX_CHARS];
} cutscenetext_t;
/**
* Shows the textbox with TEXT, blocking until it's dismissed.
*
* @param TEXT Text to display.
*/
#define CUTSCENE_TEXT(TEXT) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_TEXT, text, { .text = TEXT })
/**
* Starts a text item (shows the textbox with the item's text).
*
@@ -16,23 +16,6 @@ typedef struct {
float_t duration;
} cutscenetextmini_t;
/**
* Shows a mini textbox at a world position for a duration, then
* completes immediately.
*
* @param TEXT Text to display.
* @param X World X of the mini textbox.
* @param Y World Y of the mini textbox.
* @param Z World Z of the mini textbox.
* @param DURATION Duration in seconds to show it.
*/
#define CUTSCENE_TEXT_MINI(TEXT, X, Y, Z, DURATION) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_TEXT_MINI, textMini, { \
.text = TEXT, \
.position = { X, Y, Z }, \
.duration = DURATION \
})
/**
* Starts a mini text item (shows a mini textbox at the given world
* position for the given duration, then completes immediately).
@@ -12,16 +12,6 @@ typedef struct {
uint8_t index;
} cutscenetextminihide_t;
/**
* Closes a mini textbox immediately.
*
* @param INDEX Mini textbox index to close.
*/
#define CUTSCENE_TEXT_MINI_HIDE(INDEX) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_TEXT_MINI_HIDE, textMiniHide, { \
.index = INDEX \
})
/**
* Starts a mini text hide step (closes the mini textbox immediately).
*
@@ -21,15 +21,6 @@ typedef struct {
uiscreentype_t screen;
} cutsceneuishow_t;
/**
* Opens a full-screen UI panel (e.g. the main menu) declaratively, then
* immediately continues on to whatever follows this item.
*
* @param SCREEN uiscreentype_t to open.
*/
#define CUTSCENE_UI_SHOW(SCREEN) \
CUTSCENE_ITEM(CUTSCENE_ITEM_TYPE_UI_SHOW, uiShow, { .screen = SCREEN })
/**
* Starts a UI_SHOW item, opening the requested full-screen UI panel.
*
+10 -4
View File
@@ -15,11 +15,17 @@ static const cutsceneitem_t CUTSCENE_TEST_SCRATCH_ITEMS[] = {
// Waiting BEFORE pausing is the correct order: pausing first would
// freeze BATTLE.state wherever it happened to be and it would never
// reach PRE_ROUND on its own to satisfy the wait.
CUTSCENE_BATTLE_WAIT_STATE(BATTLE_STATE_PRE_ROUND),
CUTSCENE_SET_PAUSE(CUTSCENE_PAUSE_BATTLE),
{
.type = CUTSCENE_ITEM_TYPE_BATTLE_WAIT_STATE,
.battleWaitState = { .state = BATTLE_STATE_PRE_ROUND }
},
{ .type = CUTSCENE_ITEM_TYPE_SET_PAUSE, .setPause = CUTSCENE_PAUSE_BATTLE },
// enemy (slot 2) forced onto allyA (slot 0)
CUTSCENE_BATTLE_FORCE_ACTION(2, 0),
CUTSCENE_SET_PAUSE(CUTSCENE_PAUSE_NONE)
{
.type = CUTSCENE_ITEM_TYPE_BATTLE_FORCE_ACTION,
.battleForceAction = { .fighterIndex = 2, .targetIndex = 0 }
},
{ .type = CUTSCENE_ITEM_TYPE_SET_PAUSE, .setPause = CUTSCENE_PAUSE_NONE }
};
static const cutscene_t CUTSCENE_TEST_SCRATCH = {
.items = CUTSCENE_TEST_SCRATCH_ITEMS,
+44 -14
View File
@@ -12,7 +12,7 @@
static void test_cutsceneWaitCompletesAfterItsDuration(void **state) {
cutsceneitem_t item = CUTSCENE_WAIT(1.0f);
cutsceneitem_t item = { .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 1.0f };
cutsceneitemdata_t data;
memoryZero(&data, sizeof(data));
@@ -38,7 +38,8 @@ static void test_cutsceneCallbackFiresOnStartWithUserData(void **state) {
callbackCallCount = 0;
lastUserData = NULL;
cutsceneitem_t item = CUTSCENE_CALLBACK(recordCallback);
cutsceneitem_t item =
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordCallback };
cutsceneitemdata_t data;
cutsceneCallbackStart(&item, &data);
@@ -65,8 +66,10 @@ static void test_cutsceneCallbackNullIsNoop(void **state) {
static void test_cutsceneSetPauseAppliesImmediately(void **state) {
CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE;
cutsceneitem_t item =
CUTSCENE_SET_PAUSE(CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_BATTLE);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_SET_PAUSE,
.setPause = CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_BATTLE
};
cutsceneitemdata_t data;
cutsceneSetPauseStart(&item, &data);
@@ -78,10 +81,16 @@ static void test_cutsceneSetPauseAppliesImmediately(void **state) {
static void test_cutsceneConcurrentCompletesOnceAllChildrenDo(void **state) {
cutsceneitem_t item = CUTSCENE_CONCURRENT(
CUTSCENE_WAIT(0.2f),
CUTSCENE_WAIT(0.5f)
);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_CONCURRENT,
.concurrent = {
.items = (const cutsceneitem_t[]){
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 0.2f },
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 0.5f }
},
.count = 2
}
};
cutsceneitemdata_t data;
memoryZero(&data, sizeof(data));
@@ -100,10 +109,16 @@ static void test_cutsceneConcurrentDoesNotReUpdateFinishedChildren(
void **state
) {
cutsceneitem_t item = CUTSCENE_CONCURRENT(
CUTSCENE_WAIT(0.1f),
CUTSCENE_WAIT(10.0f)
);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_CONCURRENT,
.concurrent = {
.items = (const cutsceneitem_t[]){
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 0.1f },
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 10.0f }
},
.count = 2
}
};
cutsceneitemdata_t data;
memoryZero(&data, sizeof(data));
@@ -121,8 +136,23 @@ static void test_cutsceneConcurrentDoesNotReUpdateFinishedChildren(
static void test_cutsceneConcurrentCannotNest(void **state) {
cutsceneitem_t outer =
CUTSCENE_CONCURRENT(CUTSCENE_CONCURRENT(CUTSCENE_WAIT(1.0f)));
cutsceneitem_t outer = {
.type = CUTSCENE_ITEM_TYPE_CONCURRENT,
.concurrent = {
.items = (const cutsceneitem_t[]){
{
.type = CUTSCENE_ITEM_TYPE_CONCURRENT,
.concurrent = {
.items = (const cutsceneitem_t[]){
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 1.0f }
},
.count = 1
}
}
},
.count = 1
}
};
cutsceneitemdata_t data;
expect_assert_failure(cutsceneConcurrentStart(&outer, &data));
+44 -15
View File
@@ -19,9 +19,14 @@ static void test_cutsceneMapAreaAddCreatesAreaAndStoresLastCreated(
) {
resetMapAreas();
cutsceneitem_t item = CUTSCENE_MAP_AREA_ADD(
0, 0, 0, 5, 5, 0, mapAreaNoopCallback, MAP_AREA_NOTIFY_ALL, MAP_TRIGGER_ALL
);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_ADD,
.mapAreaAdd = {
.min = { 0, 0, 0 }, .max = { 5, 5, 0 },
.callback = mapAreaNoopCallback,
.notify = MAP_AREA_NOTIFY_ALL, .trigger = MAP_TRIGGER_ALL
}
};
cutsceneitemdata_t data;
cutsceneMapAreaAddStart(&item, &data);
@@ -40,7 +45,10 @@ static void test_cutsceneMapAreaRemoveClearsSlot(void **state) {
mapAreaNoopCallback, MAP_AREA_NOTIFY_ALL, MAP_TRIGGER_ALL
);
cutsceneitem_t item = CUTSCENE_MAP_AREA_REMOVE(id);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_REMOVE,
.mapAreaRemove = { .areaId = id }
};
cutsceneitemdata_t data;
cutsceneMapAreaRemoveStart(&item, &data);
@@ -53,15 +61,22 @@ static void test_cutsceneMapAreaRemoveResolvesLastCreatedSentinel(
) {
resetMapAreas();
cutsceneitem_t addItem = CUTSCENE_MAP_AREA_ADD(
0, 0, 0, 5, 5, 0, mapAreaNoopCallback, MAP_AREA_NOTIFY_ALL, MAP_TRIGGER_ALL
);
cutsceneitem_t addItem = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_ADD,
.mapAreaAdd = {
.min = { 0, 0, 0 }, .max = { 5, 5, 0 },
.callback = mapAreaNoopCallback,
.notify = MAP_AREA_NOTIFY_ALL, .trigger = MAP_TRIGGER_ALL
}
};
cutsceneitemdata_t data;
cutsceneMapAreaAddStart(&addItem, &data);
uint8_t id = CUTSCENE_SYSTEM.areaLastCreated;
cutsceneitem_t removeItem =
CUTSCENE_MAP_AREA_REMOVE(CUTSCENE_AREA_LAST_CREATED);
cutsceneitem_t removeItem = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_REMOVE,
.mapAreaRemove = { .areaId = CUTSCENE_AREA_LAST_CREATED }
};
cutsceneMapAreaRemoveStart(&removeItem, &data);
assert_null(MAP_AREAS[id].callback);
}
@@ -76,7 +91,10 @@ static void test_cutsceneMapAreaWaitCompletesWhenTriggerCountChanges(
mapAreaNoopCallback, MAP_AREA_NOTIFY_ALL, MAP_TRIGGER_ALL
);
cutsceneitem_t item = CUTSCENE_MAP_AREA_WAIT(id);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT,
.mapAreaWait = { .areaIds = { id }, .count = 1 }
};
cutsceneitemdata_t data;
cutsceneMapAreaWaitStart(&item, &data);
@@ -100,7 +118,10 @@ static void test_cutsceneMapAreaWaitCompletesWhenAnyWatchedAreaChanges(
mapAreaNoopCallback, MAP_AREA_NOTIFY_ALL, MAP_TRIGGER_ALL
);
cutsceneitem_t item = CUTSCENE_MAP_AREA_WAIT(idA, idB);
cutsceneitem_t item = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT,
.mapAreaWait = { .areaIds = { idA, idB }, .count = 2 }
};
cutsceneitemdata_t data;
cutsceneMapAreaWaitStart(&item, &data);
@@ -115,14 +136,22 @@ static void test_cutsceneMapAreaWaitResolvesLastCreatedSentinel(
) {
resetMapAreas();
cutsceneitem_t addItem = CUTSCENE_MAP_AREA_ADD(
0, 0, 0, 5, 5, 0, mapAreaNoopCallback, MAP_AREA_NOTIFY_ALL, MAP_TRIGGER_ALL
);
cutsceneitem_t addItem = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_ADD,
.mapAreaAdd = {
.min = { 0, 0, 0 }, .max = { 5, 5, 0 },
.callback = mapAreaNoopCallback,
.notify = MAP_AREA_NOTIFY_ALL, .trigger = MAP_TRIGGER_ALL
}
};
cutsceneitemdata_t data;
cutsceneMapAreaAddStart(&addItem, &data);
uint8_t id = CUTSCENE_SYSTEM.areaLastCreated;
cutsceneitem_t waitItem = CUTSCENE_MAP_AREA_WAIT(CUTSCENE_AREA_LAST_CREATED);
cutsceneitem_t waitItem = {
.type = CUTSCENE_ITEM_TYPE_MAP_AREA_WAIT,
.mapAreaWait = { .areaIds = { CUTSCENE_AREA_LAST_CREATED }, .count = 1 }
};
cutsceneMapAreaWaitStart(&waitItem, &data);
assert_false(cutsceneMapAreaWaitUpdate(&waitItem, &data));
+18 -18
View File
@@ -21,7 +21,7 @@ static void recordCallback(void *userData) {
// replaces CUTSCENE_SYSTEM.scene outright, and the callback item's effect
// fires in Start, not Update, so it fires the same frame the jump happens.
static const cutsceneitem_t CUTSCENE_TEST_INNER_ITEMS[] = {
CUTSCENE_CALLBACK(recordCallback)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordCallback }
};
static const cutscene_t CUTSCENE_TEST_INNER = {
.items = CUTSCENE_TEST_INNER_ITEMS,
@@ -30,7 +30,7 @@ static const cutscene_t CUTSCENE_TEST_INNER = {
};
static const cutsceneitem_t CUTSCENE_TEST_OUTER_ITEMS[] = {
CUTSCENE_WAIT(0.5f),
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 0.5f },
{
.type = CUTSCENE_ITEM_TYPE_CUTSCENE,
.cutsceneRef = { .cutscene = &CUTSCENE_TEST_INNER, .name = NULL }
@@ -89,7 +89,7 @@ static void test_cutsceneSystemUpdateIsNoopWithNoActiveCutscene(void **state) {
}
static const cutsceneitem_t CUTSCENE_TEST_SINGLE_WAIT_ITEMS[] = {
CUTSCENE_WAIT(1.0f)
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 1.0f }
};
static const cutscene_t CUTSCENE_TEST_SINGLE_WAIT = {
.items = CUTSCENE_TEST_SINGLE_WAIT_ITEMS,
@@ -207,9 +207,9 @@ static void recordOrderA(void *userData) { insertOrderLog[insertOrderLogCount++]
static void recordOrderB(void *userData) { insertOrderLog[insertOrderLogCount++] = 4; }
static const cutsceneitem_t CUTSCENE_TEST_INSERT_SNIPPET_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrderA),
CUTSCENE_WAIT(2.0f),
CUTSCENE_CALLBACK(recordOrderB)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrderA },
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 2.0f },
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrderB }
};
static const cutscene_t CUTSCENE_TEST_INSERT_SNIPPET = {
.items = CUTSCENE_TEST_INSERT_SNIPPET_ITEMS,
@@ -219,14 +219,14 @@ static const cutscene_t CUTSCENE_TEST_INSERT_SNIPPET = {
};
static const cutsceneitem_t CUTSCENE_TEST_INSERT_OUTER_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrder0),
CUTSCENE_WAIT(1.0f),
CUTSCENE_CALLBACK(recordOrder1),
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrder0 },
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 1.0f },
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrder1 },
{
.type = CUTSCENE_ITEM_TYPE_INSERT,
.insert = { .cutscene = &CUTSCENE_TEST_INSERT_SNIPPET, .name = NULL }
},
CUTSCENE_CALLBACK(recordOrder2)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrder2 }
};
static const cutscene_t CUTSCENE_TEST_INSERT_OUTER = {
.items = CUTSCENE_TEST_INSERT_OUTER_ITEMS,
@@ -264,7 +264,7 @@ static void test_cutsceneInsertSplicesItemsInPlaceThenResumes(void **state) {
}
static const cutsceneitem_t CUTSCENE_TEST_INSERT_AS_LAST_ITEM_SNIPPET_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrderA)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrderA }
};
static const cutscene_t CUTSCENE_TEST_INSERT_AS_LAST_ITEM_SNIPPET = {
.items = CUTSCENE_TEST_INSERT_AS_LAST_ITEM_SNIPPET_ITEMS,
@@ -274,7 +274,7 @@ static const cutscene_t CUTSCENE_TEST_INSERT_AS_LAST_ITEM_SNIPPET = {
};
static const cutsceneitem_t CUTSCENE_TEST_INSERT_AS_LAST_ITEM_OUTER_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrder0),
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrder0 },
{
.type = CUTSCENE_ITEM_TYPE_INSERT,
.insert = {
@@ -314,7 +314,7 @@ static void test_cutsceneInsertAsLastItemEndsCutsceneNaturally(
}
static const cutsceneitem_t CUTSCENE_TEST_INSERT_NESTED_INNER_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrderA)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrderA }
};
static const cutscene_t CUTSCENE_TEST_INSERT_NESTED_INNER = {
.items = CUTSCENE_TEST_INSERT_NESTED_INNER_ITEMS,
@@ -331,7 +331,7 @@ static const cutsceneitem_t CUTSCENE_TEST_INSERT_NESTED_MID_ITEMS[] = {
.type = CUTSCENE_ITEM_TYPE_INSERT,
.insert = { .cutscene = &CUTSCENE_TEST_INSERT_NESTED_INNER, .name = NULL }
},
CUTSCENE_CALLBACK(recordOrderB)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrderB }
};
static const cutscene_t CUTSCENE_TEST_INSERT_NESTED_MID = {
.items = CUTSCENE_TEST_INSERT_NESTED_MID_ITEMS,
@@ -341,12 +341,12 @@ static const cutscene_t CUTSCENE_TEST_INSERT_NESTED_MID = {
};
static const cutsceneitem_t CUTSCENE_TEST_INSERT_NESTED_OUTER_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrder0),
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrder0 },
{
.type = CUTSCENE_ITEM_TYPE_INSERT,
.insert = { .cutscene = &CUTSCENE_TEST_INSERT_NESTED_MID, .name = NULL }
},
CUTSCENE_CALLBACK(recordOrder2)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrder2 }
};
static const cutscene_t CUTSCENE_TEST_INSERT_NESTED_OUTER = {
.items = CUTSCENE_TEST_INSERT_NESTED_OUTER_ITEMS,
@@ -381,7 +381,7 @@ static void test_cutsceneInsertNestsThroughMultipleLevels(void **state) {
}
static const cutsceneitem_t CUTSCENE_TEST_INSERT_OVERFLOW_LEVEL5_ITEMS[] = {
CUTSCENE_CALLBACK(recordOrderA)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = recordOrderA }
};
static const cutscene_t CUTSCENE_TEST_INSERT_OVERFLOW_LEVEL5 = {
.items = CUTSCENE_TEST_INSERT_OVERFLOW_LEVEL5_ITEMS,
@@ -467,7 +467,7 @@ static void test_cutsceneInsertAssertsWhenNestingExceedsStackMax(
static void noopInsertCallback(void *userData) {}
static const cutsceneitem_t CUTSCENE_TEST_INSERT_PERSIST_SNIPPET_ITEMS[] = {
CUTSCENE_CALLBACK(noopInsertCallback)
{ .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = noopInsertCallback }
};
static const cutscene_t CUTSCENE_TEST_INSERT_PERSIST_SNIPPET = {
.items = CUTSCENE_TEST_INSERT_PERSIST_SNIPPET_ITEMS,
+1 -1
View File
@@ -12,7 +12,7 @@
#include "rpg/cutscene/cutscenesystem.h"
static const cutsceneitem_t CUTSCENE_TEST_INTERACT_ITEMS[] = {
CUTSCENE_WAIT(1.0f)
{ .type = CUTSCENE_ITEM_TYPE_WAIT, .wait = 1.0f }
};
static const cutscene_t CUTSCENE_TEST_INTERACT = {
.items = CUTSCENE_TEST_INTERACT_ITEMS,