25#include "text/msg_ids.h"
48#define TILE(position) ((position) / 0x100000)
125 if (actor !=
NULL && column == (actor->
x.
fixed >> 20) &&
134 for (actorSlot = 8; actorSlot <= 65; actorSlot++) {
135 s32 *actorWords = slots[actorSlot];
137 if (column == (actorWords[2] >> 20) && row == (actorWords[4] >> 20) &&
138 *((
u8 *)actorWords + 0x59) != 0) {
149#define DIRECTION_STEP(heading) \
150 ((s32)(((u32)(u16)gVaultCave_DirectionSteps[(heading) * 2 + 1] << 16) | \
151 (u16)gVaultCave_DirectionSteps[(heading) * 2]))
159#define DIRECTION_STEP(heading) \
160 (((struct DirectionSteps *)gVaultCave_DirectionSteps)->xz[heading])
189 for (fallingIndex = 0; fallingIndex <= 3; fallingIndex++) {
202 destination.
y = block->
y.
fixed;
210 block->
speed = 0x3333;
213 leader->
speed = 0x3333;
218 block->
x.
fixed = destination.
x;
219 block->
z.
fixed = destination.
z;
264 fixedZ += 0x000FFFFF;
269 fixedX += 0x000FFFFF;
271 column = fixedX >> 20;
272 if (column == 15 && row == 54) {
328 fixedZ += 0x000FFFFF;
333 fixedX += 0x000FFFFF;
335 column = fixedX >> 20;
336 if (column == 16 && row == 12) {
478 for (targetIndex = 0; targetIndex < 6; targetIndex++) {
496 }
while (remaining >= 0);
521 for (frame = 479; frame >= 0; frame--) {
524 layer->
phaseY = (double)layer->
phaseY - (4718.592 - (
double)scrollDrift);
531 upperFadeBits = fadeLevel << 10;
534 upperFadeBits | (fadeLevel << 5) | lowFadeLevel);
536 if (frame % 20 == 0) {
541 }
while (frame <= 69);
555 s32 destinationColumn;
562 destinationColumn = 92;
564 Map_CopyCells(107, 27, 1, 1, destinationColumn, destinationRow);
566 Map_CopyCells(108, 27, 1, 1, destinationColumn, destinationRow);
568 destinationColumn = 25;
570 Map_CopyCells(1, 24, 1, 2, destinationColumn, destinationRow);
572 Map_CopyCells(2, 24, 1, 2, destinationColumn, destinationRow);
581 s32 fallingIndex = 0;
586 if ((
u32)(fallingActor->
y.
fixed - 1) <= 0x000ffffe) {
591 s32 zDelta = subjectRow - fallingRow;
592 s32 xDelta = subjectColumn - fallingColumn;
594 if (xDelta == 0 && zDelta == 0) {
603 }
while (fallingIndex <= 3);
622 fallingActor =
Actor_Get((scheduleIndex + 11));
629 for (fallingIndex = 0; fallingIndex <= 3; fallingIndex++) {
630 fallingActor =
Actor_Get((fallingIndex + 11));
632 if (fallingActor->
y.
fixed <= 0xffff) {
668 if (fallingActor->
paused == 0) {
674 *selectedIndex = stateValue;
679 for (fallingIndex = 0; fallingIndex <= 5; fallingIndex++) {
683 if (stateValue != 0) {
685 if (fallingActor->
y.
fixed > 0x20ffff) {
695 if (fallingActor->
y.
fixed > 0xffff) {
699 fallingActor->
gravity = stateValue;
727 for (puffIndex = 0; puffIndex < 4; puffIndex++) {
759 fallingActor->
bounce = 0x1999;
764 }
while (remaining >= 0);
773 s32 fallingIndex = 0;
780 fallingActor->
bounce = 0x1999;
786 }
while (fallingIndex <= 3);
941 { 0,
CONDITION_ALWAYS, 120, 0, 152,
FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
946 { 0,
CONDITION_ALWAYS, 120, 0, 152,
FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
947 { 1,
CONDITION_ALWAYS, 424, 0, 216,
FACING_SOUTH, 0, 72, 8, 480, 320, 0 },
948 { 2,
CONDITION_ALWAYS, 136, 0, 104,
FACING_SOUTH, 0, 72, 8, 480, 320, 0 },
949 { 3,
CONDITION_ALWAYS, 120, 0, 256,
FACING_NORTH, 0, 72, 8, 480, 320, 0 },
950 { 4,
CONDITION_ALWAYS, 184, 0, 264,
FACING_NORTH, 0, 72, 8, 480, 320, 0 },
951 { 5,
CONDITION_ALWAYS, 344, 0, 464,
FACING_SOUTH, 0, 280, 360, 640, 640, 0 },
952 { 6,
CONDITION_ALWAYS, 488, 0, 488,
FACING_SOUTH, 0, 280, 360, 640, 640, 0 },
953 { 7,
CONDITION_ALWAYS, 584, 0, 608,
FACING_SOUTH, 0, 280, 360, 640, 640, 0 },
954 { 8,
CONDITION_ALWAYS, 344, 0, 632,
FACING_NORTH, 0, 280, 360, 640, 640, 0 },
955 { 13,
CONDITION_ALWAYS, 408, 0, 472,
FACING_SOUTH, 0, 280, 360, 640, 640, 0 },
956 { 9,
CONDITION_ALWAYS, 88, 0, 704,
FACING_SOUTH, 0, 40, 632, 352, 912, 0 },
957 { 12,
CONDITION_ALWAYS, 184, 0, 864,
FACING_SOUTH, 0, 40, 632, 352, 912, 0 },
958 { 10,
CONDITION_ALWAYS, 456, 0, 800,
FACING_SOUTH, 0, 336, 696, 576, 856, 0 },
959 { 11,
CONDITION_ALWAYS, 456, 0, 840,
FACING_NORTH, 0, 336, 696, 576, 856, 0 },
964 { 0,
CONDITION_ALWAYS, 120, 0, 152,
FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
965 { 1,
CONDITION_ALWAYS, 136, 0, 104,
FACING_SOUTH, 0, 40, 8, 400, 328, 0 },
966 { 2,
CONDITION_ALWAYS, 344, 0, 152,
FACING_SOUTH, 0, 40, 8, 400, 328, 0 },
967 { 3,
CONDITION_ALWAYS, 344, 0, 184,
FACING_NORTH, 0, 40, 8, 400, 328, 0 },
968 { 4,
CONDITION_ALWAYS, 168, 0, 328,
FACING_NORTH, 0, 40, 8, 400, 328, 0 },
969 { 5,
CONDITION_ALWAYS, 56, 0, 480,
FACING_SOUTH, 0, 8, 408, 248, 656, 0 },
970 { 6,
CONDITION_ALWAYS, 152, 0, 472,
FACING_SOUTH, 0, 8, 408, 248, 656, 0 },
971 { 7,
CONDITION_ALWAYS, 120, 0, 576,
FACING_SOUTH, 0, 8, 408, 248, 656, 0 },
972 { 8,
CONDITION_ALWAYS, 344, 0, 456,
FACING_SOUTH, 0, 280, 344, 544, 672, 0 },
973 { 9,
CONDITION_ALWAYS, 424, 0, 664,
FACING_NORTH, 0, 280, 344, 544, 672, 0 },
974 { 14,
CONDITION_ALWAYS, 456, 0, 472,
FACING_SOUTH, 0, 280, 344, 544, 672, 0 },
975 { 10,
CONDITION_ALWAYS, 200, 0, 776,
FACING_SOUTH, 0, 104, 696, 344, 944, 0 },
976 { 11,
CONDITION_ALWAYS, 264, 0, 808,
FACING_SOUTH, 0, 104, 696, 344, 944, 0 },
977 { 13,
CONDITION_ALWAYS, 536, 0, 168,
FACING_NORTH, 0, 416, 24, 656, 184, 0 },
982 { 0,
CONDITION_ALWAYS, 120, 0, 152,
FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
983 { 1,
CONDITION_ALWAYS, 312, 0, 664,
FACING_NORTH, 0, 200, 520, 440, 680, 0 },
984 { 2,
CONDITION_ALWAYS, 312, 0, 600,
FACING_SOUTH, 0, 200, 520, 440, 680, 0 },
985 { 3,
CONDITION_ALWAYS, 88, 0, 568,
FACING_SOUTH, 0, 8, 472, 248, 632, 0 },
986 { 4,
CONDITION_ALWAYS, 168, 0, 544,
FACING_SOUTH, 0, 8, 472, 248, 632, 0 },
987 { 5,
CONDITION_ALWAYS, 248, 0, 336,
FACING_NORTH, 0, 128, 40, 376, 384, 0 },
988 { 6,
CONDITION_ALWAYS, 280, 0, 104,
FACING_SOUTH, 0, 128, 40, 376, 384, 0 },
993 { 447, 47, 783, 463, 63, 799, -1, 10 },
994 { -1, 0, 0, 0, 0, 0, 0, 0 },
Ability numbers, named from the English release.
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
const struct ScenePlacement * Scene_GetPlacements(void)
const struct SceneEntrance * Scene_GetEntrances(void)
const struct SceneEvent * Scene_GetEvents(void)
const u32 * Scene_GetExits(void)
Both scenes share one exit table.
const struct SceneRegion * Scene_GetRegions(void)
s32 Scene_Initialize(void)
Sets up whichever scene is being entered and runs its arrival events.
#define DIRECTION_STEP(dx, dz)
Pixel step by direction: X in the upper halfword, Z in the lower.
Calls through a function pointer, by argument count.
The task scheduler: tasks, their order and the scheduler's state.
static void Event_IgnoreMove(void)
Move on this rock needs nothing more.
The engine calls the debug menus import, and their palette swatch tiles.
The engine call layer: one typed inline for each of the thirteen main-image routines below that the s...
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
static s32 FieldObject_CheckMovementCollision(struct FieldActor *actor, struct FieldPosition *position)
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
void Engine_ObjectSetPosition(struct FieldActor *object, s32 fixed_x, s32 fixed_y, s32 fixed_z)
u32 Math_RemainderUnsigned(u32 dividend, u32 divisor)
void Object_SetMode(struct FieldActor *object, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
void Engine_MessageShowCentered(s32 message, s32 flags)
void Engine_ObjectSetScript(struct FieldActor *object, const s32 *script)
void Engine_GameFlagSet(s32 flag)
void Engine_MapRenderWaitForValues(void)
void Engine_GameFlagClear(s32 flag)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
static void Event_PlayCue(s32 cue)
static void Map_CopyCells(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
static void Map_SetShake(s32 horizontal, s32 vertical, s32 decay)
Sets shake amplitudes in fixed-point pixels and the per-frame decay factor.
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_MapRedraw(void)
static s32 Random_Next(void)
static void Actor_SetPosition(s32 actor, s32 fixed_x, s32 fixed_z)
void Engine_EventWait(s32 frames)
static struct FieldActor * Actor_Get(s32 actor)
@ ACTOR_PRIORITY_UNDERFOOT
The depth sort treats it as 320 pixels higher on the screen.
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
@ ACTOR_FALLS
falls by its gravity and bounces
#define ACTOR_NO_TARGET
A target coordinate that is not set: the object has no target.
#define SCENE_TRANSITION(style, variant)
The field's runtime work: map cells, scene records and regions, map markers and FieldWork.
The scene table formats: entrances, exits, placements and events, and the macros that write them.
#define SCENE_EXITS(scene)
#define SCENE_EXIT(exit, scene, entrance)
#define PSYNERGY_ON_ACTOR(ability)
#define EVENT_SCRIPT(script)
#define EVENT_TOUCH_WALKING
Game flags, named where their meaning is shown.
#define FLAG_SCENE_TEMP_05
#define FLAG_SCENE_TEMP_03
#define FLAG_SCENE_TEMP_00
#define FLAG_VAULT_CAVE_SWITCH_FLIPPED
#define FLAG_VAULT_CAVE_2_CHEST
#define FLAG_SCENE_TEMP_02
#define FLAG_VAULT_CAVE_NORTH_BLOCK_ON_SWITCH
#define FLAG_VAULT_CAVE_SOUTH_BLOCK_ON_SWITCH
#define FLAG_VAULT_CAVE_1_CHEST
#define FLAG_SCENE_TEMP_01
#define FLAG_SCENE_TEMP_04
#define FLAG_SCENE_TEMP_07
volatile u32 gFrameCount
Frames WaitFrames has finished.
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The work slots of gWorkSlot, read through their own names.
The screen blend's globals and the graphics routines.
The main-image routines scene overlays import.
void IoWriteQueue_Store16(u32 address, u32 value)
Queues a halfword store.
The register write queue that VBlank carries out after each finished frame.
Item numbers, named from the English release.
Small statement macros both games use for positions, velocities and bounds.
#define SET_VECTOR(v, x, y, z)
Sets the x, y and z of a three-part vector: a position about to be projected, a per-frame step,...
void Vector_AddPolarOffset(s32 radius, s32 angle, void *position)
Moves the point position by radius in direction angle on the ground plane: x by the cosine,...
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
void FieldObject_WaitForMove(void *fieldObject)
Waits a frame at a time until a field object has arrived at its target, at most 600 frames.
ObjectRuntime, a field object's runtime state, and the object snapshots.
Scene numbers, named after their places.
Song and sound effect ids, indices into gSound_SongTable.
#define MUS_PUZZLE_SOLVED
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
The step table read as one word per heading: the x step in pixels in the high halfword,...
A field actor: a person or thing on the field with a position, motion toward a target,...
s16 timer
The parameter its action script reads (a follow distance or an angle to face), the player's frames to...
s32 speed
speed limit, 16.16 fixed-point pixels per frame
s32 targetX
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
u16 radius
Collision radius in pixels: 16, or half the sprite metadata's boxY, when created; the overlap checks ...
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
union FieldCoordinate x
16.16 fixed-point pixels
s32 targetZ
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
s32 velocityX
16.16 fixed-point pixels per frame
u8 paused
nonzero skips its script and motion, not its update
s32 bounce
The share of its falling speed kept as it bounces on landing, 16.16 fixed point (0x4000 when created)...
union FieldCoordinate y
16.16 fixed-point pixels
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
s32 velocityY
16.16 fixed-point pixels per frame
s32 gravity
Taken off the vertical velocity each frame while it is above the ground, in 16.16 fixed-point pixels ...
union FieldCoordinate z
16.16 fixed-point pixels
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
s32 scaleX
16.16 fixed point, 0x10000 full size
s32 scaleY
16.16 fixed point, 0x10000 full size
u16 wait
the object script's wait, in frames (ScriptMotionObject)
u16 work
The side of the player's next footprint (2 after a stop), or scene scratch.
u8 collisionFlags
bits: 7 refuses to move into a solid object | 4 nearer for Psynergy targets | 3 never a talk or Psyne...
s32 velocityZ
16.16 fixed-point pixels per frame
u8 terrainId
The map layer (0 to 3) its ground height is read from, which the scrolling camera updates from the ce...
s32 z
16.16 fixed-point pixels
Full event work allocated by Field_RunScene (heap slot 27).
s32 transition
SCENE_TRANSITION(style, variant); 0x100 on entry.
s16 retreatEntrance
where Retreat goes; the group's first entrance
s16 retreatScene
where Retreat goes; the group's first entrance
A scene entrance: where and facing which way the party arrives, and the camera's bounds there (-1 for...
A scene event: its kind and detail, the trigger it answers, its condition and its value (a message or...
An actor a scene places: its sprite, the condition for placing it, how it behaves,...
A scene's exit region: the box that, while its condition holds, takes the party leader out through it...
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
The integer types, TRUE, UNUSED and the fixed-address macros.
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
struct ScenePlacement gVaultCavePlacements3[]
struct SceneRegion gVaultCaveRegions[]
static void VaultCave_StartTimedFalls(void)
Initializes four falling objects and starts their timed updater.
struct ScenePlacement gVaultCavePlacements1[]
static void VaultCave_UseUnderfootFrostPriorities(void)
Keeps all six Frost targets beneath the leader's feet.
static void VaultCave_StartFrostControlledFalls(void)
Initializes six falling objects and starts their Frost-controlled updater.
s32 gVaultCave_ScheduleIndex
static s32 VaultCave_ResetFallingObjectAtActorCell(s32 subjectActorId)
Resets a low falling object sharing the subject's cell and reports a hit.
static void VaultCave_SpawnPuffs(struct FieldActor *source)
Spawns up to four short-lived puffs around a landing object.
static void Event_MoveSouthernBlock(void)
Move on the southern block, with the same switch check.
static void VaultCave_CompleteNorthernSwitch(void)
The northern switch also waits until the falling-object guard is clear.
const s16 gVaultCave_DirectionSteps[]
static void VaultCave_RunRumble(void)
Moves the third map layer through its phases, then fades the mechanism's final map state.
static void VaultCave_CompleteSouthernSwitch(void)
Finishes the southern switch only after the block reaches its target cell.
u32 gVaultCaveExitsOther[]
static void Event_FlipSwitch(void)
Flips the switch.
s32 gVaultCave_TickCounter
static void Event_FreezeInnerWestLowerTarget(void)
@ FLAG_NORTH_BLOCK_STRUCK
A falling object struck the northern block before it reached its switch.
@ FLAG_INNER_WEST_LOWER_FROZEN
static void Event_FreezeEastLowerTarget(void)
struct SceneEvent gVaultCaveEvents2[]
static struct FieldActor * VaultCave_FindCollidableActorAtCell(s32 column, s32 row)
Finds a placed actor with collision enabled at the requested map cell.
const s32 gVaultCave_PuffScript[]
static void UNUSED VaultCave_UnusedNoOp(void)
static void VaultCave_UpdateFrostControlledFallingObjects(void)
Drops a random object every 64 frames, with reset height set by its Frost target.
struct SceneEntrance gVaultCaveEntrances1[]
struct SceneEvent gVaultCaveEvents1[]
static void Event_FreezeFarEastTarget(void)
static void Event_MoveNorthernBlock(void)
Move on the northern block, with the same switch check.
struct SceneEntrance gVaultCaveEntrancesOther[]
static s32 VaultCave_IsNorthernBlockOnSwitch(void)
Tests the northern block's cell with the same signed-coordinate rounding.
static void Event_UseWhirlwind(void)
Whirlwind on the target in the second map blows it away for good.
static void VaultCave_PushBlockAhead(void)
Pushes the faced block one cell unless another actor or terrain blocks it.
struct SceneEvent gVaultCaveEventsOther[]
static void VaultCave_OffsetActorRadially(struct FieldActor *actor, s32 radius, s32 angle)
Offsets an actor's current position by a polar displacement.
static void VaultCave_UseAutomaticFrostPriorities(void)
Restores automatic draw priority for the same six targets.
struct ScenePlacement gVaultCavePlacements2[]
static void Event_PushSouthernBlock(void)
Pushing the southern block; once it rests on its switch, the puzzle chime plays and the switch opens ...
static void VaultCave_ApplySouthernSwitchCells(void)
Restores the map cells and attributes of the completed southern switch.
struct ScenePlacement gVaultCavePlacementsOther[]
u32 gVaultCave_ScheduleFrames[]
static void Event_ShowLockedDoor(void)
Searching the locked door. "The door is tightly locked.".
struct SceneEntrance gVaultCaveEntrances3[]
static void Event_FreezeWestLowerTarget(void)
struct SceneEvent gVaultCaveEvents3[]
static void VaultCave_ApplyNorthernSwitchCells(void)
Restores the map cells and attributes of the completed northern switch.
static void Event_PushNorthernBlock(void)
Pushing the northern block; it opens its switch only if no falling object has struck it.
static void Event_FreezeEastUpperTarget(void)
static s32 VaultCave_IsSouthernBlockOnSwitch(void)
Tests the southern block's cell, rounding fixed coordinates toward zero.
static void VaultCave_UpdateFrostTargetPriorities(void)
Changes the Frost targets' draw priorities when the leader is above them.
struct SceneEntrance gVaultCaveEntrances2[]
static void Event_FreezeWestUpperTarget(void)
Frost on the upper western target freezes it and changes its map cell; arriving again re-freezes ever...
static void VaultCave_UpdateTimedFallingObjects(void)
Drops four objects on a repeating schedule and handles their landings.
s32 gVaultCave_ScheduleTimer