Alchemy
Loading...
Searching...
No Matches

vault_cave.c

Go to the documentation of this file.
1/// @file
2/// Vault's cave puzzles: movable switches, Frost targets, falling objects
3/// and the rumbling mechanism restored when the party returns.
4
5#include "game_state.h"
6#include "unit/field/field.h"
7#include "engine_call.h"
8#include "scene_ids.h"
9#include "unit/import.h"
11#include "unit/object/object.h"
14#include "battle.h"
15#include "debug.h"
16#include "field.h"
17#include "game.h"
18#include "graphics.h"
19#include "menu.h"
20#include "minigame.h"
21#include "sound.h"
22#include "system.h"
23#include "global_cells.h"
24#include "types.h"
25#include "text/msg_ids.h"
26#include "field_event.h"
27#include "field_scene.h"
28#include "callback_scheduler.h"
29#include "call.h"
30#include "object_runtime.h"
31#include "ability_ids.h"
32#include "flags.h"
33#include "songs.h"
34#include "objcmd.h"
35#include "map_scroll.h"
36#include "field_runtime.h"
37#include "macros.h"
38#include "item_ids.h"
39
40// Forward declarations.
44static void VaultCave_SpawnPuffs(struct FieldActor *source);
45
46#include "io_write_queue.h"
47
48#define TILE(position) ((position) / 0x100000)
49
50/// Scene flags. The six Frost targets of the second map keep their frozen
51/// state in six flags in a row, read by index as well.
52enum {
59 /// A falling object struck the northern block before it reached its switch.
62};
63
64const struct SceneEntrance *Scene_GetEntrances(void) {
65 s16 scene = gGameState.scene;
66
67 if (scene == (s32)&SceneId_VaultCave1) {
69 }
70 if (scene == (s32)&SceneId_VaultCave2) {
72 }
73 if (scene == (s32)&SceneId_VaultCave3) {
75 }
77}
78
79/// Returns the region boxes used by the cave exits.
80const struct SceneRegion *Scene_GetRegions(void) { return gVaultCaveRegions; }
81
82const u32 *Scene_GetExits(void) {
83 s16 scene = gGameState.scene;
84
85 if (scene == (s32)&SceneId_VaultCave1) {
86 return gVaultCaveExits1;
87 }
88 if (scene == (s32)&SceneId_VaultCave2) {
89 return gVaultCaveExits2;
90 }
91 if (scene == (s32)&SceneId_VaultCave3) {
92 return gVaultCaveExits3;
93 }
95}
96
97/// Selects the movable blocks, falling objects and Frost targets.
99 s16 scene = gGameState.scene;
100
101 if (scene == (s32)&SceneId_VaultCave1) {
103 }
104 if (scene == (s32)&SceneId_VaultCave2) {
106 }
107 if (scene == (s32)&SceneId_VaultCave3) {
109 }
111}
112
113/// Finds a placed actor with collision enabled at the requested map cell.
115 s32 row) {
116 // UB: scene creation leaves unused actor slots NULL. The plain safe lookup
117 // adds four native bytes in EN; retain the original reads for matching.
118#ifdef UBFIX
119 struct FieldWork *work = (struct FieldWork *)gEventWork;
120 u32 actorSlot;
121
122 for (actorSlot = ACTOR_FIRST_PLACED; actorSlot <= 65; actorSlot++) {
123 struct FieldActor *actor = work->actors[actorSlot];
124
125 if (actor != NULL && column == (actor->x.fixed >> 20) &&
126 row == (actor->z.fixed >> 20) && actor->collisionFlags != 0) {
127 return actor;
128 }
129 }
130#else
131 s32 **slots = (s32 **)((u8 *)gEventWork + 0x14);
132 u32 actorSlot;
133
134 for (actorSlot = 8; actorSlot <= 65; actorSlot++) {
135 s32 *actorWords = slots[actorSlot];
136
137 if (column == (actorWords[2] >> 20) && row == (actorWords[4] >> 20) &&
138 *((u8 *)actorWords + 0x59) != 0) {
139 return (struct FieldActor *)actorWords;
140 }
141 }
142#endif
143 return NULL;
144}
145
146#ifdef UBFIX
147/// The table stores Z then X as halfwords. Build its packed word without
148/// reading a halfword array through an incompatible, more-aligned struct.
149#define DIRECTION_STEP(heading) \
150 ((s32)(((u32)(u16)gVaultCave_DirectionSteps[(heading) * 2 + 1] << 16) | \
151 (u16)gVaultCave_DirectionSteps[(heading) * 2]))
152#else
153/// The step table read as one word per heading: the x step in pixels in the
154/// high halfword, the z step in the low.
156 s32 xz[16];
157};
158
159#define DIRECTION_STEP(heading) \
160 (((struct DirectionSteps *)gVaultCave_DirectionSteps)->xz[heading])
161#endif
162
163/// Pushes the faced block one cell unless another actor or terrain blocks it.
164static void VaultCave_PushBlockAhead(void) {
165 /* FAKEMATCH: DIRECTION_STEP reads the s16-pair table (x high, z low) as one
166 * word per heading through an array reference; as const s32 words indexed
167 * directly, 79 of 146 instructions differ in tbs-en. */
169 s32 direction = leader->facing >> 12;
170 struct FieldActor *block;
171 struct FieldActor *beyond;
172 struct FieldPosition destination;
173 s32 fallingIndex;
174 s32 column;
175 s32 row;
176
177 column = (leader->x.part.pixel + (DIRECTION_STEP(direction) >> 16)) >> 4;
178 row = (leader->z.part.pixel + (s16)DIRECTION_STEP(direction)) >> 4;
179 block = VaultCave_FindCollidableActorAtCell(column, row);
180 // UB: the lookup may return NULL. The plain safe guard moves the null
181 // branch ahead of the byte load in EN, so matching keeps its original order.
182#ifdef UBFIX
183 if (block == NULL || block->collisionFlags == 0) {
184#else
185 if (block->collisionFlags == 0 || block == NULL) {
186#endif
187 return;
188 }
189 for (fallingIndex = 0; fallingIndex <= 3; fallingIndex++) {
190 if (block == Object_GetById(fallingIndex + 11)) {
191 return;
192 }
193 }
194 column = (block->x.part.pixel + (DIRECTION_STEP(direction) >> 16)) >> 4;
195 row = (block->z.part.pixel + (s16)DIRECTION_STEP(direction)) >> 4;
196 beyond = VaultCave_FindCollidableActorAtCell(column, row);
197 if (beyond != 0 && (beyond->collisionFlags & 1)) {
198 return;
199 }
200 block->terrainId = 2;
201 destination.x = block->x.fixed + (DIRECTION_STEP(direction) & 0xffff0000);
202 destination.y = block->y.fixed;
203 destination.z = block->z.fixed + (s32)((u32)DIRECTION_STEP(direction) << 16);
204 if (FieldObject_CheckMovementCollision(block, &destination) > 0) {
205 return;
206 }
207 Object_SetMode(leader, 8);
208 Engine_TaskWait(15);
210 block->speed = 0x3333;
211 block->acceleration = 0x3333;
212 Engine_ObjectSetPosition(block, destination.x, destination.y, destination.z);
213 leader->speed = 0x3333;
214 leader->acceleration = 0x3333;
215 Engine_ObjectSetPosition(leader, destination.x, destination.y, destination.z);
218 block->x.fixed = destination.x;
219 block->z.fixed = destination.z;
220 block->velocityX = 0;
221 block->velocityZ = 0;
222 leader->velocityX = 0;
223 leader->velocityZ = 0;
224 leader->targetX = ACTOR_NO_TARGET;
225 leader->targetZ = ACTOR_NO_TARGET;
226 Object_SetMode(leader, 1);
227}
228
229/// Whirlwind on the target in the second map blows it away for good.
230static void Event_UseWhirlwind(void) {
232}
233
234/// Searching the locked door. "The door is tightly locked."
235static void Event_ShowLockedDoor(void) {
236 Engine_MessageShowCentered(MSGNO(MsgFieldDoorTightlyLocked), 1);
237}
238
239/// Selects the cave map's searches, movement checks and Psynergy callbacks.
240const struct SceneEvent *Scene_GetEvents(void) {
241 s16 scene = gGameState.scene;
242
243 if (scene == (s32)&SceneId_VaultCave1) {
244 return gVaultCaveEvents1;
245 }
246 if (scene == (s32)&SceneId_VaultCave2) {
247 return gVaultCaveEvents2;
248 }
249 if (scene == (s32)&SceneId_VaultCave3) {
250 return gVaultCaveEvents3;
251 }
253}
254
255/// Tests the southern block's cell, rounding fixed coordinates toward zero.
257 struct FieldActor *block = Object_GetById(9);
258 s32 fixedZ = block->z.fixed;
259 s32 fixedX;
260 s32 row;
261 s32 column;
262
263 if (fixedZ < 0) {
264 fixedZ += 0x000FFFFF;
265 }
266 fixedX = block->x.fixed;
267 row = fixedZ >> 20;
268 if (fixedX < 0) {
269 fixedX += 0x000FFFFF;
270 }
271 column = fixedX >> 20;
272 if (column == 15 && row == 54) {
273 return 1;
274 }
275 return 0;
276}
277
278/// Finishes the southern switch only after the block reaches its target cell.
279static inline void VaultCave_CompleteSouthernSwitch(void) {
284 }
285}
286
287/// Pushing the southern block; once it rests on its switch, the puzzle chime
288/// plays and the switch opens the way.
289static void Event_PushSouthernBlock(void) {
293 }
294}
295
296/// Restores the map cells and attributes of the completed southern switch.
298 Map_CopyCells(87, 50, 2, 4, 80, 50);
299 Map_CopyCells(23, 52, 1, 2, 16, 52);
300 Map_CopyCellAttributes(16, 52, 1, 1, 16, 53);
301}
302
303/// Move on the southern block, with the same switch check.
304static void Event_MoveSouthernBlock(void) {
307 }
308}
309
310static void UNUSED VaultCave_UnusedNoOp(void) {}
311
312/// Restores the map cells and attributes of the completed northern switch.
314 Map_CopyCells(90, 9, 2, 3, 80, 9);
315 Map_CopyCells(27, 10, 1, 2, 17, 10);
316 Map_CopyCellAttributes(17, 10, 1, 1, 17, 11);
317}
318
319/// Tests the northern block's cell with the same signed-coordinate rounding.
321 struct FieldActor *block = Object_GetById(10);
322 s32 fixedZ = block->z.fixed;
323 s32 fixedX;
324 s32 row;
325 s32 column;
326
327 if (fixedZ < 0) {
328 fixedZ += 0x000FFFFF;
329 }
330 fixedX = block->x.fixed;
331 row = fixedZ >> 20;
332 if (fixedX < 0) {
333 fixedX += 0x000FFFFF;
334 }
335 column = fixedX >> 20;
336 if (column == 16 && row == 12) {
337 return 1;
338 }
339 return 0;
340}
341
342/// The northern switch also waits until the falling-object guard is clear.
343static inline void VaultCave_CompleteNorthernSwitch(void) {
350 }
351 }
352 }
353}
354
355/// Pushing the northern block; it opens its switch only if no falling object
356/// has struck it.
357static void Event_PushNorthernBlock(void) {
360}
361
362/// Move on the southern block in the third map does nothing.
363static void Event_IgnoreMove(void) {}
364
365/// Move on the northern block, with the same switch check.
366static void Event_MoveNorthernBlock(void) {
368}
369
370/// Frost on the upper western target freezes it and changes its map cell;
371/// arriving again re-freezes every target whose flag is set.
373 // An ordinary shared Frost helper keeps the extents but saves r5-r7 instead
374 // of r5 alone and changes the map-copy argument registers in native English.
375 struct FieldActor *target = Object_GetById(16);
376
377 Map_CopyCellAttributes(26, 30, 1, 1, 23, 32);
378
379 if (target != 0) {
380
383 }
384
386}
387
389 struct FieldActor *target = Object_GetById(17);
390
391 Map_CopyCellAttributes(26, 30, 1, 1, 23, 34);
392
393 if (target != 0) {
394
397 }
398
400}
401
403 struct FieldActor *target = Object_GetById(18);
404
405 Map_CopyCellAttributes(26, 30, 1, 1, 24, 34);
406
407 if (target != 0) {
408
411 }
412
414}
415
417 struct FieldActor *target = Object_GetById(19);
418
419 Map_CopyCellAttributes(26, 30, 1, 1, 26, 32);
420
421 if (target != 0) {
423
426 }
427
429}
430
432 struct FieldActor *target = Object_GetById(20);
433
434 Map_CopyCellAttributes(26, 30, 1, 1, 26, 34);
435
436 if (target != 0) {
438
441 }
442
444}
445
446static void Event_FreezeFarEastTarget(void) {
447 struct FieldActor *target = Object_GetById(21);
448
449 Map_CopyCellAttributes(26, 30, 1, 1, 28, 33);
450
451 if (target != 0) {
453
456 }
457
459}
460
461/// Changes the Frost targets' draw priorities when the leader is above them.
464
465 if (leader->y.fixed >= PIXELS(16)) {
467 } else {
469 }
470}
471
472/// Keeps all six Frost targets beneath the leader's feet.
474 s32 targetIndex;
475 s32 actorSlot;
476
477 actorSlot = 16;
478 for (targetIndex = 0; targetIndex < 6; targetIndex++) {
480 actorSlot++;
481 }
482}
483
484/// Restores automatic draw priority for the same six targets.
486 s32 actorSlot = 16;
487 s32 priority = ACTOR_PRIORITY_AUTOMATIC;
488 s32 remaining = 5;
489
490 do {
491 struct FieldActor *target = Object_GetById(actorSlot);
492
493 remaining--;
494 target->priorityFlags = priority;
495 actorSlot++;
496 } while (remaining >= 0);
497}
498
499/// Moves the third map layer through its phases, then fades the mechanism's
500/// final map state.
501static void VaultCave_RunRumble(void) {
502 struct MapLayerScroll *layer =
503 &((struct MapScrollWork *)gMapWork[0])->layers[2];
504 s32 frame;
505 s32 fadeLevel;
506 s32 lowFadeLevel;
507 s32 upperFadeBits;
508
510 if (gFrameCount & 1) {
511 layer->speedX = 1;
512 layer->speedY = 1;
513 } else {
514 layer->speedX = -1;
515 layer->speedY = -1;
516 }
517 Map_SetShake(0x30000, 0x30000, 0x10000);
518 Map_SetShake(-1, -1, 0xe666);
520 // Scroll and shake for 480 frames before the final fade.
521 for (frame = 479; frame >= 0; frame--) {
522 u32 scrollDrift = (u32)(Random_Next() << 11) >> 16;
523
524 layer->phaseY = (double)layer->phaseY - (4718.592 - (double)scrollDrift);
526 }
527 // Keep the packed native value written to BLDALPHA.
528 fadeLevel = 6;
529 lowFadeLevel = 6;
530 frame = 0;
531 upperFadeBits = fadeLevel << 10;
532 do {
533 IoWriteQueue_Store16(0x4000052,
534 upperFadeBits | (fadeLevel << 5) | lowFadeLevel);
536 if (frame % 20 == 0) {
537 lowFadeLevel--;
538 fadeLevel--;
539 }
540 frame++;
541 } while (frame <= 69);
542 // Replace the mechanism's map cells after the fade completes.
543 Map_CopyCells(19, 83, 15, 8, 19, 91);
548}
549
550/// Flips the switch. "Isaac flipped the switch." The first time, the switch
551/// turns, the cave rumbles and shakes for eight seconds and the map changes as
552/// it fades.
553static void Event_FlipSwitch(void) {
554 s32 destinationRow;
555 s32 destinationColumn;
556
558 Engine_MessageShowCentered(MSGNO(MsgFieldFlippedSwitch), 1);
560 // Animate the switch face before the adjacent mechanism starts.
561 destinationRow = 27;
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);
575 }
576}
577
578/// Resets a low falling object sharing the subject's cell and reports a hit.
580 struct FieldActor *subject = Object_GetById(subjectActorId);
581 s32 fallingIndex = 0;
582
583 do {
584 struct FieldActor *fallingActor = Object_GetById(fallingIndex + 11);
585
586 if ((u32)(fallingActor->y.fixed - 1) <= 0x000ffffe) {
587 s32 fallingRow = TILE(fallingActor->z.fixed);
588 s32 fallingColumn = TILE(fallingActor->x.fixed);
589 s32 subjectRow = TILE(subject->z.fixed);
590 s32 subjectColumn = TILE(subject->x.fixed);
591 s32 zDelta = subjectRow - fallingRow;
592 s32 xDelta = subjectColumn - fallingColumn;
593
594 if (xDelta == 0 && zDelta == 0) {
595 fallingActor->y.fixed = PIXELS(255);
596 fallingActor->gravity = 0;
597 fallingActor->velocityY = 0;
598 return 1;
599 }
600 }
601
602 fallingIndex++;
603 } while (fallingIndex <= 3);
604
605 return 0;
606}
607
608/// Drops four objects on a repeating schedule and handles their landings.
610 s32 fallingIndex;
611 struct FieldActor *fallingActor;
612 s32 paused;
613 s32 scheduleIndex;
614
616 if (paused == 0) {
617 if (++gVaultCave_ScheduleTimer > 190) {
619 }
620 scheduleIndex = gVaultCave_ScheduleIndex;
622 fallingActor = Actor_Get((scheduleIndex + 11));
623 fallingActor->gravity = 0xa3d;
624 if (++gVaultCave_ScheduleIndex > 3) {
626 }
627 }
628 // Reset objects that have reached the floor and spawn their landing puffs.
629 for (fallingIndex = 0; fallingIndex <= 3; fallingIndex++) {
630 fallingActor = Actor_Get((fallingIndex + 11));
631 if (fallingActor->velocityY >= 0) {
632 if (fallingActor->y.fixed <= 0xffff) {
633 VaultCave_SpawnPuffs(fallingActor);
634 fallingActor->y.fixed = PIXELS(255);
635 fallingActor->gravity = 0;
636 fallingActor->velocityY = 0;
637 fallingActor->paused = 0;
639 }
640 }
641 }
642 // A falling object landing on either movable block restarts at the top.
648 } else {
650 }
651 }
654 }
655 }
656}
657
658/// Drops a random object every 64 frames, with reset height set by its Frost
659/// target.
661
662 s32 fallingIndex;
663 struct FieldActor *fallingActor;
664 s32 stateValue;
665 s32 *selectedIndex;
666
667 fallingActor = Object_GetById(10);
668 if (fallingActor->paused == 0) {
669 // Preserve one random selection per 64 frames.
670 if ((++gVaultCave_TickCounter & 63) == 0) {
671 selectedIndex = &gVaultCave_TickValue;
672 stateValue = Engine_RandomNext();
673 stateValue = Math_RemainderUnsigned(stateValue, 6);
674 *selectedIndex = stateValue;
675 fallingActor = Object_GetById((stateValue + 10));
676 fallingActor->gravity = 0xa3d;
677 }
678 // Each object's paired Frost flag selects its reset height.
679 for (fallingIndex = 0; fallingIndex <= 5; fallingIndex++) {
680 fallingActor = Object_GetById((fallingIndex + 10));
681 stateValue =
683 if (stateValue != 0) {
684 if (fallingActor->velocityY <= 0) {
685 if (fallingActor->y.fixed > 0x20ffff) {
686 continue;
687 }
688 }
689 fallingActor->y.fixed = PIXELS(255);
690 fallingActor->gravity = 0;
691 fallingActor->velocityY = 0;
693 } else {
694 if (fallingActor->velocityY <= 0) {
695 if (fallingActor->y.fixed > 0xffff) {
696 continue;
697 }
698 }
699 fallingActor->gravity = stateValue;
700 fallingActor->velocityY = stateValue;
701 fallingActor->y.fixed = PIXELS(255);
703 }
704 }
705 }
706}
707
708/// Offsets an actor's current position by a polar displacement.
710 s32 angle) {
711 s32 destination[3];
712
713 if (actor == NULL) {
714 return;
715 }
716 SET_VECTOR(destination, actor->x.fixed, actor->y.fixed, actor->z.fixed);
717 Vector_AddPolarOffset(radius, angle, destination);
718 Engine_ObjectSetPosition(actor, destination[0], destination[1],
719 destination[2]);
720}
721
722/// Spawns up to four short-lived puffs around a landing object.
723static void VaultCave_SpawnPuffs(struct FieldActor *source) {
724 struct FieldActor *puff;
725 s32 puffIndex;
726
727 for (puffIndex = 0; puffIndex < 4; puffIndex++) {
728 puff = Engine_ObjectCreate(240, source->x.fixed, source->y.fixed,
729 source->z.fixed);
730 if (puff == 0)
731 break;
732 puff->scaleY = 0x8ccc;
733 puff->scaleX = 0x8ccc;
734 puff->motionFlags = ACTOR_FALLS;
735 puff->velocityY = -0x10000;
736 puff->speed = Engine_RandomNext() + 0xcccc;
737 puff->collisionFlags = 1;
739 {
740 u16 *timer = &puff->wait;
741 s32 frames = 8;
742
743 *timer = frames;
744 }
746 }
747}
748
749/// Initializes six falling objects and starts their Frost-controlled updater.
751 s32 actorSlot = 10;
752 s32 remaining = 5;
753
754 do {
755 struct FieldActor *fallingActor;
756
758 fallingActor = Object_GetById(actorSlot);
759 fallingActor->bounce = 0x1999;
760 fallingActor->gravity = 0;
761 remaining--;
762 fallingActor->y.fixed = PIXELS(255);
763 actorSlot++;
764 } while (remaining >= 0);
765
768}
769
770/// Initializes four falling objects and starts their timed updater.
771static void VaultCave_StartTimedFalls(void) {
772 s32 actorSlot = 11;
773 s32 fallingIndex = 0;
774
775 do {
776 struct FieldActor *fallingActor;
777
779 fallingActor = Object_GetById(actorSlot);
780 fallingActor->bounce = 0x1999;
781 fallingActor->gravity = 0;
782 fallingActor->y.fixed = PIXELS(255);
783 Engine_ActorSetSpritePriority(fallingIndex + 11, 1);
784 fallingIndex++;
785 actorSlot++;
786 } while (fallingIndex <= 3);
787
790}
791
792/// Restores each room's puzzles and actors, then sets the Retreat destination.
794 ((struct FieldWork *)gEventWork)->transition =
797 switch (gGameState.entrance) {
798 case 5:
799 case 6:
800 case 7:
801 case 8:
802 case 13:
804 Map_CopyCellAttributes(22, 29, 1, 1, 21, 29);
805 } else {
806 Map_CopyCells(108, 27, 1, 1, 92, 27);
808 Map_CopyCells(19, 83, 15, 8, 19, 91);
810 Map_CopyCells(2, 24, 1, 2, 25, 27);
811 }
814 break;
815 case 10:
817 break;
818 }
819 }
822 Object_GetById(22)->scaleY = 0x18000;
823 }
824 switch (gGameState.entrance) {
825 case 1:
826 case 2:
827 case 3:
828 case 4:
830 Map_CopyCells(5, 81, 11, 7, 5, 73);
831 } else {
832 Map_CopyCellAttributes(5, 12, 1, 1, 6, 12);
833 Map_CopyCellAttributes(12, 10, 1, 1, 12, 11);
834 }
835 break;
836 case 8:
837 case 9:
838 case 14:
843 }
847 }
851 }
855 }
859 }
863 }
866 break;
867 case 10:
868 case 11:
871 Actor_SetPosition(9, PIXELS(248), PIXELS(876));
872 }
874 break;
875 }
881 }
886 }
890 Object_GetById(10)->collisionFlags |= 0x80;
891 Object_GetById(9)->collisionFlags |= 0x80;
892 switch (gGameState.entrance) {
893 case 5:
894 case 6:
905 Actor_SetPosition(10, PIXELS(264), PIXELS(204));
906 }
907 break;
908 }
909 }
910 // Retreat always returns to the first cave map's outer entrance.
913 return 0;
914}
915
916// clang-format off
918 0, 16,
919 0, 16,
920 0, 16,
921 16, 0,
922 16, 0,
923 16, 0,
924 16, 0,
925 0, -16,
926 0, -16,
927 0, -16,
928 0, -16,
929 -16, 0,
930 -16, 0,
931 -16, 0,
932 -16, 0,
933 0, 16,
934};
935
937 SC_FREE,
938};
939
941 { 0, CONDITION_ALWAYS, 120, 0, 152, FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
942 { SCENE_TABLE_END },
943};
944
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 },
960 { SCENE_TABLE_END },
961};
962
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 },
978 { SCENE_TABLE_END },
979};
980
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 },
989 { SCENE_TABLE_END },
990};
991
993 { 447, 47, 783, 463, 63, 799, -1, 10 },
994 { -1, 0, 0, 0, 0, 0, 0, 0 },
995};
996
998 SCENE_EXITS(511),
999};
1000
1002 SCENE_EXITS(96),
1003 SCENE_EXIT(1, 98, 2),
1004 SCENE_EXIT(2, 97, 1),
1005 SCENE_EXIT(3, 96, 5),
1006 SCENE_EXIT(4, 96, 13),
1007 SCENE_EXIT(5, 96, 3),
1008 SCENE_EXIT(6, 97, 6),
1009 SCENE_EXIT(7, 97, 10),
1010 SCENE_EXIT(8, 96, 9),
1011 SCENE_EXIT(9, 96, 8),
1012 SCENE_EXIT(10, 23, 13),
1013 SCENE_EXIT(10, 96, 11),
1014 SCENE_EXIT(11, 96, 12),
1015 SCENE_EXIT(12, 96, 11),
1016 SCENE_EXIT(13, 96, 4),
1018};
1019
1021 SCENE_EXITS(97),
1022 SCENE_EXIT(1, 96, 2),
1023 SCENE_EXIT(2, 98, 6),
1024 SCENE_EXIT(3, 97, 8),
1025 SCENE_EXIT(4, 97, 5),
1026 SCENE_EXIT(5, 97, 4),
1027 SCENE_EXIT(6, 96, 6),
1028 SCENE_EXIT(7, 98, 3),
1029 SCENE_EXIT(8, 97, 3),
1030 SCENE_EXIT(9, 97, 11),
1031 SCENE_EXIT(10, 96, 7),
1032 SCENE_EXIT(11, 97, 9),
1033 SCENE_EXIT(13, 97, 13),
1034 SCENE_EXIT(14, 97, 14),
1036};
1037
1039 SCENE_EXITS(98),
1040 SCENE_EXIT(1, 23, 14),
1041 SCENE_EXIT(2, 96, 1),
1042 SCENE_EXIT(3, 97, 7),
1043 SCENE_EXIT(4, 98, 5),
1044 SCENE_EXIT(5, 98, 4),
1045 SCENE_EXIT(6, 97, 2),
1047};
1048
1050 { SCENE_TABLE_END },
1051};
1052
1054 { SCENE_TABLE_END },
1055};
1056
1058 { 0x12b, CONDITION_ALWAYS, ACTOR_STAND,
1059 PIXELS(280), 0, PIXELS(876), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1060 { 0x12b, CONDITION_ALWAYS, ACTOR_STAND,
1061 PIXELS(184), 0, PIXELS(892), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1063 PIXELS(372), 0, PIXELS(512), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1065 PIXELS(372), 0, PIXELS(544), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1067 PIXELS(388), 0, PIXELS(544), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1069 PIXELS(420), 0, PIXELS(512), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1071 PIXELS(420), 0, PIXELS(544), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1073 PIXELS(452), 0, PIXELS(528), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1075 PIXELS(376), 0, PIXELS(520), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1077 PIXELS(376), 0, PIXELS(552), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1079 PIXELS(392), 0, PIXELS(552), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1081 PIXELS(424), 0, PIXELS(520), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1083 PIXELS(424), 0, PIXELS(552), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1085 PIXELS(456), 0, PIXELS(536), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1087 PIXELS(456), 0, PIXELS(456), FACING_SOUTH, TALK_KEEP_FACING, 0 },
1088 { SCENE_TABLE_END },
1089};
1090
1092 { 0x12b, CONDITION_ALWAYS, ACTOR_STAND,
1093 PIXELS(296), 0, PIXELS(204), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1094 { 0x12b, CONDITION_ALWAYS, ACTOR_STAND,
1095 PIXELS(264), 0, PIXELS(236), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1096 { 0x12b, CONDITION_ALWAYS, ACTOR_STAND,
1097 PIXELS(264), 0, PIXELS(300), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1099 PIXELS(248), 0, PIXELS(232), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1101 PIXELS(264), 0, PIXELS(248), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1103 PIXELS(264), 0, PIXELS(264), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1105 PIXELS(280), 0, PIXELS(280), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1106 { SCENE_TABLE_END },
1107};
1108
1110 { SCENE_EVENTS_END },
1111};
1112
1114 { 0x21, 1, CONDITION_ALWAYS, 1 },
1115 { 0x31, 2, CONDITION_ALWAYS, 2 },
1116 { EVENT_EXIT, 3, CONDITION_ALWAYS, 3 },
1117 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
1118 { EVENT_EXIT, 5, CONDITION_ALWAYS, 5 },
1119 { 0x31, 6, CONDITION_ALWAYS, 6 },
1120 { 0x31, 7, CONDITION_ALWAYS, 7 },
1121 { EVENT_EXIT, 8, CONDITION_ALWAYS, 8 },
1122 { EVENT_EXIT, 9, CONDITION_ALWAYS, 9 },
1123 { EVENT_EXIT, 10, CONDITION_ALWAYS, 10 },
1124 { EVENT_EXIT, 11, CONDITION_ALWAYS, 11 },
1125 { EVENT_EXIT, 12, CONDITION_ALWAYS, 12 },
1126 { EVENT_EXIT, 13, CONDITION_ALWAYS, 13 },
1129 { SEARCH(SEARCH_CHEST), 100, FLAG_VAULT_CAVE_1_CHEST, 0x500003 },
1130 { SCENE_EVENTS_END },
1131};
1132
1134 { 0x21, 1, CONDITION_ALWAYS, 1 },
1135 { 0x31, 2, CONDITION_ALWAYS, 2 },
1136 { EVENT_EXIT, 3, CONDITION_ALWAYS, 3 },
1137 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
1138 { EVENT_EXIT, 5, CONDITION_ALWAYS, 5 },
1139 { 0x21, 6, CONDITION_ALWAYS, 6 },
1140 { 0x31, 7, CONDITION_ALWAYS, 7 },
1141 { EVENT_EXIT, 8, CONDITION_ALWAYS, 8 },
1142 { EVENT_EXIT, 9, CONDITION_ALWAYS, 9 },
1143 { 0x21, 10, CONDITION_ALWAYS, 10 },
1144 { EVENT_EXIT, 11, CONDITION_ALWAYS, 11 },
1145 { EVENT_EXIT, 13, CONDITION_ALWAYS, 13 },
1146 { EVENT_EXIT, 14, CONDITION_ALWAYS, 14 },
1158 { SCENE_EVENTS_END },
1159};
1160
1162 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
1163 { 0x31, 2, CONDITION_ALWAYS, 2 },
1164 { 0x21, 3, CONDITION_ALWAYS, 3 },
1165 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
1166 { EVENT_EXIT, 5, CONDITION_ALWAYS, 5 },
1167 { 0x21, 6, CONDITION_ALWAYS, 6 },
1172 { SCENE_EVENTS_END },
1173};
1174
1176 20, 80, 115, 170,
1177};
1178// clang-format on
1179
1181
1183
1185
Ability numbers, named from the English release.
@ ABILITY_MOVE
Definition ability_ids.h:15
@ ABILITY_WHIRLWIND
Definition ability_ids.h:13
@ ABILITY_FROST
Definition ability_ids.h:11
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.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
struct FieldActor * Engine_ObjectCreate(s32, s32, s32, s32)
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.
Definition engine_call.h:36
static s32 FieldObject_CheckMovementCollision(struct FieldActor *actor, struct FieldPosition *position)
Definition engine_call.h:66
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)
#define GameFlag_IsSet
#define GameFlag_Set
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)
s32 Engine_RandomNext()
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)
@ TASK_PRIORITY_SCENE
Definition field_event.h:40
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)
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ ACTOR_PRIORITY_UNDERFOOT
The depth sort treats it as 320 pixels higher on the screen.
Definition field_obj.h:155
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
Definition field_obj.h:153
@ ACTOR_FALLS
falls by its gravity and bounces
Definition field_obj.h:161
#define ACTOR_NO_TARGET
A target coordinate that is not set: the object has no target.
Definition field_obj.h:145
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
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_EVENTS_END
#define FIND_ITEM(item)
@ EVENT_TOUCH
@ EVENT_EXIT
#define SCENE_EXITS(scene)
Definition field_scene.h:72
#define SCENE_EXIT(exit, scene, entrance)
Definition field_scene.h:73
@ ACTOR_FIRST_PLACED
@ ACTOR_PARTY_LEADER
@ SCENE_TABLE_END
Definition field_scene.h:43
@ CONDITION_ALWAYS
Definition field_scene.h:44
@ TALK_KEEP_FACING
@ TALK_FACE_PARTY
#define PSYNERGY_ON_ACTOR(ability)
#define EVENT_SCRIPT(script)
#define EVENT_TOUCH_WALKING
@ ACTOR_STAND
#define SEARCH(target)
#define SCENE_EXITS_END
Definition field_scene.h:77
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_SOUTH
Definition field_scene.h:28
#define PIXELS(value)
@ SEARCH_UNNAMED
@ SEARCH_CHEST
Game flags, named where their meaning is shown.
#define FLAG_SCENE_TEMP_05
Definition flags.h:718
#define FLAG_SCENE_TEMP_03
Definition flags.h:716
#define FLAG_SCENE_TEMP_00
Definition flags.h:713
#define FLAG_VAULT_CAVE_SWITCH_FLIPPED
Definition flags.h:572
#define FLAG_VAULT_CAVE_2_CHEST
Definition flags.h:576
#define FLAG_SCENE_TEMP_02
Definition flags.h:715
#define FLAG_VAULT_CAVE_NORTH_BLOCK_ON_SWITCH
Definition flags.h:574
#define FLAG_VAULT_CAVE_SOUTH_BLOCK_ON_SWITCH
Definition flags.h:573
#define FLAG_VAULT_CAVE_1_CHEST
Definition flags.h:575
#define FLAG_SCENE_TEMP_01
Definition flags.h:714
#define FLAG_SCENE_TEMP_04
Definition flags.h:717
#define FLAG_SCENE_TEMP_07
Definition flags.h:720
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.
void * gMapWork[]
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.
Definition io_queue.c:21
The register write queue that VBlank carries out after each finished frame.
Item numbers, named from the English release.
@ ITEM_VAMBRACE
Definition item_ids.h:32
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,...
Definition macros.h:12
The map layers' scroll work and the background scroll values.
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,...
Definition math.c:23
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
#define SC_FREE
Release.
Definition objcmd.h:43
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.
char SceneId_VaultCave3
char SceneId_VaultCave2
char SceneId_VaultCave1
Song and sound effect ids, indices into gSound_SongTable.
#define SE_156
Definition songs.h:151
#define SE_163
Definition songs.h:158
#define SE_204
Definition songs.h:199
#define SE_155
Definition songs.h:150
#define MUS_PUZZLE_SOLVED
Definition songs.h:79
#define SE_288
Definition songs.h:281
#define SE_106
Definition songs.h:99
#define SE_238
Definition songs.h:233
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
void Engine_TaskWait()
#define NULL
Definition bilibin.h:6
The step table read as one word per heading: the x step in pixels in the high halfword,...
Definition vault_cave.c:155
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s16 timer
The parameter its action script reads (a follow distance or an angle to face), the player's frames to...
Definition field_obj.h:109
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
s32 targetX
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:59
u16 radius
Collision radius in pixels: 16, or half the sprite metadata's boxY, when created; the overlap checks ...
Definition field_obj.h:43
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
Definition field_obj.h:83
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
s32 targetZ
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:61
s32 velocityX
16.16 fixed-point pixels per frame
Definition field_obj.h:52
u8 paused
nonzero skips its script and motion, not its update
Definition field_obj.h:93
s32 bounce
The share of its falling speed kept as it bounces on landing, 16.16 fixed point (0x4000 when created)...
Definition field_obj.h:64
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
Definition field_obj.h:51
s32 velocityY
16.16 fixed-point pixels per frame
Definition field_obj.h:53
s32 gravity
Taken off the vertical velocity each frame while it is above the ground, in 16.16 fixed-point pixels ...
Definition field_obj.h:68
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition field_obj.h:39
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition field_obj.h:40
u16 wait
the object script's wait, in frames (ScriptMotionObject)
Definition field_obj.h:98
u16 work
The side of the player's next footprint (2 after a stop), or scene scratch.
Definition field_obj.h:112
u8 collisionFlags
bits: 7 refuses to move into a solid object | 4 nearer for Psynergy targets | 3 never a talk or Psyne...
Definition field_obj.h:91
s32 velocityZ
16.16 fixed-point pixels per frame
Definition field_obj.h:54
u8 terrainId
The map layer (0 to 3) its ground height is read from, which the scrolling camera updates from the ce...
Definition field_obj.h:47
A position on the field.
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
Definition game_state.h:109
s16 retreatScene
where Retreat goes; the group's first entrance
Definition game_state.h:108
s16 entrance
Definition game_state.h:37
One background layer of the field map: its scroll position, origin, parallax against the view,...
Definition map_scroll.h:14
s32 speedY
16.16 fixed-point pixels per frame
Definition map_scroll.h:18
s32 phaseY
16.16 fixed-point pixels
Definition map_scroll.h:19
The field map's work: the followed position, screen shake, tile animations, blend script,...
Definition map_scroll.h:27
struct MapLayerScroll layers[3]
BG3, BG2 and BG1, in that order.
Definition map_scroll.h:49
A scene entrance: where and facing which way the party arrives, and the camera's bounds there (-1 for...
Definition field_scene.h:54
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,...
Definition field_scene.h:81
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.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
struct ScenePlacement gVaultCavePlacements3[]
struct SceneRegion gVaultCaveRegions[]
Definition vault_cave.c:992
u32 gVaultCaveExits2[]
static void VaultCave_StartTimedFalls(void)
Initializes four falling objects and starts their timed updater.
Definition vault_cave.c:771
struct ScenePlacement gVaultCavePlacements1[]
static void VaultCave_UseUnderfootFrostPriorities(void)
Keeps all six Frost targets beneath the leader's feet.
Definition vault_cave.c:473
static void VaultCave_StartFrostControlledFalls(void)
Initializes six falling objects and starts their Frost-controlled updater.
Definition vault_cave.c:750
s32 gVaultCave_ScheduleIndex
static s32 VaultCave_ResetFallingObjectAtActorCell(s32 subjectActorId)
Resets a low falling object sharing the subject's cell and reports a hit.
Definition vault_cave.c:579
static void VaultCave_SpawnPuffs(struct FieldActor *source)
Spawns up to four short-lived puffs around a landing object.
Definition vault_cave.c:723
static void Event_MoveSouthernBlock(void)
Move on the southern block, with the same switch check.
Definition vault_cave.c:304
static void VaultCave_CompleteNorthernSwitch(void)
The northern switch also waits until the falling-object guard is clear.
Definition vault_cave.c:343
const s16 gVaultCave_DirectionSteps[]
Definition vault_cave.c:917
static void VaultCave_RunRumble(void)
Moves the third map layer through its phases, then fades the mechanism's final map state.
Definition vault_cave.c:501
static void VaultCave_CompleteSouthernSwitch(void)
Finishes the southern switch only after the block reaches its target cell.
Definition vault_cave.c:279
u32 gVaultCaveExitsOther[]
Definition vault_cave.c:997
static void Event_FlipSwitch(void)
Flips the switch.
Definition vault_cave.c:553
s32 gVaultCave_TickCounter
static void Event_FreezeInnerWestLowerTarget(void)
Definition vault_cave.c:402
u32 gVaultCaveExits3[]
@ FLAG_WEST_UPPER_FROZEN
Definition vault_cave.c:53
@ FLAG_WEST_LOWER_FROZEN
Definition vault_cave.c:54
@ FLAG_NORTH_BLOCK_STRUCK
A falling object struck the northern block before it reached its switch.
Definition vault_cave.c:60
@ FLAG_WHIRLWIND_USED
Definition vault_cave.c:61
@ FLAG_EAST_UPPER_FROZEN
Definition vault_cave.c:56
@ FLAG_INNER_WEST_LOWER_FROZEN
Definition vault_cave.c:55
@ FLAG_FAR_EAST_FROZEN
Definition vault_cave.c:58
@ FLAG_EAST_LOWER_FROZEN
Definition vault_cave.c:57
static void Event_FreezeEastLowerTarget(void)
Definition vault_cave.c:431
struct SceneEvent gVaultCaveEvents2[]
static struct FieldActor * VaultCave_FindCollidableActorAtCell(s32 column, s32 row)
Finds a placed actor with collision enabled at the requested map cell.
Definition vault_cave.c:114
const s32 gVaultCave_PuffScript[]
Definition vault_cave.c:936
static void UNUSED VaultCave_UnusedNoOp(void)
Definition vault_cave.c:310
static void VaultCave_UpdateFrostControlledFallingObjects(void)
Drops a random object every 64 frames, with reset height set by its Frost target.
Definition vault_cave.c:660
struct SceneEntrance gVaultCaveEntrances1[]
Definition vault_cave.c:945
struct SceneEvent gVaultCaveEvents1[]
static void Event_FreezeFarEastTarget(void)
Definition vault_cave.c:446
static void Event_MoveNorthernBlock(void)
Move on the northern block, with the same switch check.
Definition vault_cave.c:366
struct SceneEntrance gVaultCaveEntrancesOther[]
Definition vault_cave.c:940
static s32 VaultCave_IsNorthernBlockOnSwitch(void)
Tests the northern block's cell with the same signed-coordinate rounding.
Definition vault_cave.c:320
u32 gVaultCaveExits1[]
static void Event_UseWhirlwind(void)
Whirlwind on the target in the second map blows it away for good.
Definition vault_cave.c:230
static void VaultCave_PushBlockAhead(void)
Pushes the faced block one cell unless another actor or terrain blocks it.
Definition vault_cave.c:164
struct SceneEvent gVaultCaveEventsOther[]
static void VaultCave_OffsetActorRadially(struct FieldActor *actor, s32 radius, s32 angle)
Offsets an actor's current position by a polar displacement.
Definition vault_cave.c:709
static void VaultCave_UseAutomaticFrostPriorities(void)
Restores automatic draw priority for the same six targets.
Definition vault_cave.c:485
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 ...
Definition vault_cave.c:289
static void VaultCave_ApplySouthernSwitchCells(void)
Restores the map cells and attributes of the completed southern switch.
Definition vault_cave.c:297
struct ScenePlacement gVaultCavePlacementsOther[]
s32 gVaultCave_TickValue
u32 gVaultCave_ScheduleFrames[]
#define TILE(position)
Definition vault_cave.c:48
static void Event_ShowLockedDoor(void)
Searching the locked door. "The door is tightly locked.".
Definition vault_cave.c:235
struct SceneEntrance gVaultCaveEntrances3[]
Definition vault_cave.c:981
static void Event_FreezeWestLowerTarget(void)
Definition vault_cave.c:388
struct SceneEvent gVaultCaveEvents3[]
static void VaultCave_ApplyNorthernSwitchCells(void)
Restores the map cells and attributes of the completed northern switch.
Definition vault_cave.c:313
static void Event_PushNorthernBlock(void)
Pushing the northern block; it opens its switch only if no falling object has struck it.
Definition vault_cave.c:357
static void Event_FreezeEastUpperTarget(void)
Definition vault_cave.c:416
static s32 VaultCave_IsSouthernBlockOnSwitch(void)
Tests the southern block's cell, rounding fixed coordinates toward zero.
Definition vault_cave.c:256
static void VaultCave_UpdateFrostTargetPriorities(void)
Changes the Frost targets' draw priorities when the leader is above them.
Definition vault_cave.c:462
struct SceneEntrance gVaultCaveEntrances2[]
Definition vault_cave.c:963
static void Event_FreezeWestUpperTarget(void)
Frost on the upper western target freezes it and changes its map cell; arriving again re-freezes ever...
Definition vault_cave.c:372
static void VaultCave_UpdateTimedFallingObjects(void)
Drops four objects on a repeating schedule and handles their landings.
Definition vault_cave.c:609
s32 gVaultCave_ScheduleTimer