Alchemy
Loading...
Searching...
No Matches

sol_sanctum_statue.c

Go to the documentation of this file.
1/// @file
2/// Sol Sanctum's statue hall: four statues pushed onto their seals and two that
3/// shine their beams at the centre open a hole in the hall's floor, and Kraden
4/// explains the puzzle.
5
6#include "game_state.h"
7#include "version.h"
12#include "callback_scheduler.h"
13#include "resource.h"
14#include "mem.h"
15#include "global_cells.h"
16#include "types.h"
17#include "field_event.h"
18#include "field_scene.h"
19#include "field_service.h"
20#include "call.h"
21#include "text/msg_ids.h"
22#include "battle.h"
23#include "debug.h"
24#include "field.h"
25#include "game.h"
26#include "graphics.h"
27#include "menu.h"
28#include "minigame.h"
29#include "sound.h"
30#include "system.h"
31#include "animspr.h"
32#include "map_scroll.h"
33#include "fixed_math.h"
34#include "resource_37de_scene.h"
35#include "macros.h"
36#include "flags.h"
37#include "songs.h"
38#include "ability_ids.h"
39
40// Place flags: Scene_ResetFlagsOnEnter clears 0x300 to 0x3ff when the party
41// enters another place group, and other places use the numbers for their own.
42#define FLAG_SOL_SANCTUM_STATUE_HALL_VISITED 0x30a
43#define FLAG_SOL_SANCTUM_STATUE_PUZZLE_EXPLAINED 0x30b
44
45#if TBS_PATCH_3
46#define SOL_SANCTUM_STATUE_BACK_SCROLL_ROW_Y_OFFSET 6
47#else
48#define SOL_SANCTUM_STATUE_BACK_SCROLL_ROW_Y_OFFSET 8
49#endif
50
51#define SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT 9
52#define SOL_SANCTUM_STATUE_SPRITE_WIDTH 32
53
54// Scene flags, cleared on every ordinary entrance:
55// - FLAG_SCENE_TEMP_07: both beams have opened the hole in the hall's floor;
56// until then, Move on the centre statue first walks the leader clear of it.
57
59static void Event_CenterStatueMoved(void);
60static void SolSanctumStatue_PushStatue(s32 statueId, s32 statueColumn,
61 s32 statueRow, s32 leaderColumn,
62 s32 leaderRow);
63static s32 SolSanctumStatue_IsActorAtCell(s32 actorId, s32 column, s32 row);
68static void SolSanctumStatue_OpenSeal(void);
69static void SolSanctumStatue_ShineLeftBeam(void);
70static void SolSanctumStatue_ShineRightBeam(void);
71static void Event_SayThenWait(s32 speaker, s32 frames);
72
73#define NULL ((void *)0)
74
75/// A block of map cells copied from one place in the map to another.
76struct CellCopy {
77 s32 srcX; ///< map cells
78 s32 srcY; ///< map cells
79 s32 destX; ///< map cells
80 s32 destY; ///< map cells
81 s32 width; ///< map cells
82 s32 height; ///< map cells
83};
84
85/// The seal being opened: its cell animations, its flag, where the leader
86/// jumps back to and where its statue returns if the story does not go on.
87struct SealScene {
88 struct CellCopy open;
93 s32 facing; ///< 1/65536 turns
94 s32 destX; ///< pixels
95 s32 destZ; ///< pixels
96 struct CellCopy stairs[3];
98 s32 actorX; ///< pixels
99 s32 actorZ; ///< pixels
100 s32 unused[3]; ///< never read or written; the bss keeps its 12 bytes
101};
102
103STATIC_ASSERT(offsetof(struct SealScene, unused) == 0xc4);
104
105/// The placed actors: Kraden, the eight statues, and the centre statue in its
106/// two places. Of the statues, four are pushed onto seals and two shine beams
107/// at the centre; the other two never move.
118};
119
120/// The scene's bss, in this order; as commons of one object the linker would
121/// sort them itself.
122static struct SealScene sSealScene;
123/// Initialization writes each three-word OAM packet; drawing updates its
124/// fields.
125static union {
129
132}
133
134const struct SceneRegion *SolSanctumStatue_GetRegions(void) { return NULL; }
135
137
138/// Returns Kraden (actor 8), the eight statues (9 to 16), the centre statue
139/// (17) and its moved copy (18), then Jenna and Garet.
142}
143
144/// Returns the statues' Move and push events, each row only until its seal or
145/// beam is done.
148}
149
150/// Chooses the cutscene in the Luna and Sol rooms that a newly opened seal
151/// leads to, and requests its exit: the trap (exit 3) once the centre statue
152/// has moved, until FLAG_SOL_SANCTUM_STATUE_TRAP_SPRUNG is set; the falling
153/// lights (exit 4) before then, until FLAG_SOL_SANCTUM_FALLING_LIGHTS_SEEN is
154/// set. Returns 1 when it requests an exit, otherwise -1.
159 return 1;
160 }
163 return 1;
164 }
165 return -1;
166}
167
168/// Animates the floor opening after both light beams meet, then lets the
169/// centre statue drop in if it stands there. Called by the beams, the second
170/// one shining. Sets FLAG_SCENE_TEMP_07.
172 s32 flash;
173
174 {
175 Map_CopyCellsTo(0, 28, 17, 8, 2, 1);
176 }
178 for (flash = 0; flash != 22; flash++) {
179 Map_CopyCellsTo(10, 61, 17, 40, 2, 1);
181 Map_CopyCellsTo(8, 61, 17, 40, 2, 1);
183 }
184 {
185 Map_CopyCellsTo(0, 59, 15, 38, 4, 3);
186 Map_CopyCellsTo(4, 59, 17, 38, 4, 3);
187 }
188 Map_CopyCellsTo(8, 60, 17, 39, 2, 2);
189 {
190 Map_CopyCellAttributes(0, 0, 2, 1, 17, 8);
191 }
194}
195
196/// Kraden comes back after the trap to find the hole in the floor, has the
197/// party tell how it opened, and decides the statue disarmed the trap. Called
198/// by SolSanctumStatue_Initialize at entrance 3 (back from the trap) until
199/// FLAG_SOL_SANCTUM_STATUE_HALL_VISITED is set, which the caller sets. Clears
200/// FLAG_SHOW_LOCATION_NAME.
202 struct FieldActor *leader;
203
212 // Kraden, from the south: "You found it, Isaac!" Jenna: "Kraden!"
213 Engine_EventSetMessage(MsgSolSanctumKradenYouFoundIt);
216 Camera_SetSpeed(PIXELS(4) / 5, PIXELS(1) / 10);
217 Camera_MoveTo(PIXELS(574), -1, PIXELS(180), 1);
221 Engine_ActorJump(JENNA, 2, 0);
228 // The camera swings west to the hole at the centre and back.
229 Camera_SetSpeed(PIXELS(28) / 5, PIXELS(7) / 10);
230 Camera_MoveTo(PIXELS(287), -1, PIXELS(176), 1);
233 Camera_MoveTo(PIXELS(574), -1, PIXELS(180), 1);
240 // Kraden hops up to the party: "Excellent work, Isaac!"
248 // The screen closes and opens on Kraden by the hole: "Where did that hole
249 // come from?" Then back to the party.
254 Camera_MoveTo(PIXELS(287), -1, PIXELS(176), 0);
266 Camera_MoveTo(PIXELS(574), -1, PIXELS(180), 0);
272 Camera_SetSpeed(PIXELS(6) / 5, PIXELS(3) / 20);
273 Camera_MoveTo(PIXELS(574), -1, PIXELS(157), 1);
276 // Garet: two beams shot out of the statues Isaac moved, and the hole
277 // appeared. Jenna: Isaac dropped the statue into it.
284 // Kraden: "Good work, everyone!" and "So the statue puzzle was the trap..."
298 // Kraden: the other statue was there to disarm the trap, and now they
299 // should be all right.
317 // Kraden: he will observe from the Luna room. He leaves south.
319 Camera_SetSpeed(PIXELS(8) / 5, PIXELS(1) / 5);
320 Camera_MoveTo(PIXELS(576), -1, PIXELS(215), 1);
328 Camera_SetSpeed(PIXELS(18) / 5, PIXELS(9) / 20);
329 Camera_MoveTo(PIXELS(576), -1, PIXELS(136), 1);
332 // Rejoin the companions to the leader and restore normal field control.
333 Actor_SetSpeed(GARET, PIXELS(1), PIXELS(1) / 2);
334 Actor_SetSpeed(JENNA, PIXELS(1), PIXELS(1) / 2);
337 if (leader != NULL) {
338 Actor_SetDestination(GARET, leader->x.part.pixel, leader->z.part.pixel);
339 }
344 if (leader != NULL) {
345 Actor_SetDestination(JENNA, leader->x.part.pixel, leader->z.part.pixel);
346 }
353}
354
355/// Kraden comes back after the falling lights to warn that the statues are a
356/// trap, and leaves the mystery to the party. Called by
357/// SolSanctumStatue_Initialize at entrance 4 (back from the falling lights)
358/// until FLAG_SOL_SANCTUM_STATUE_PUZZLE_EXPLAINED is set, which the caller
359/// sets. Clears FLAG_SHOW_LOCATION_NAME.
361 struct EventWork *work;
362 struct FieldActor *leader;
363
367 work->transitionFrames = 32;
373 // Kraden, from the south: "Wait, Isaac!" Jenna: "What's wrong, Kraden?"
374 Engine_EventSetMessage(MsgSolSanctumWait);
376 Camera_SetSpeed(PIXELS(4) / 5, PIXELS(1) / 10);
377 Camera_MoveTo(PIXELS(574), -1, PIXELS(180), 1);
381 Engine_ActorJump(JENNA, 2, 0);
388 Engine_CameraSetSpeed(PIXELS(28) / 5, PIXELS(7) / 10);
389 Camera_MoveTo(PIXELS(287), -1, PIXELS(176), 1);
392 Camera_MoveTo(PIXELS(574), -1, PIXELS(180), 1);
403 // Kraden: "This is a most interesting mechanism you've found, Isaac."
410 // Kraden: "But this is clearly... some kind of trap." All three start.
414 Engine_ActorJump(GARET, 2, 0);
415 Engine_ActorJump(JENNA, 2, 0);
417 // Garet: "This is...a trap?" Kraden: "Go look in the Luna room".
432 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(6) / 5, PIXELS(3) / 5);
435 Camera_SetSpeed(PIXELS(12) / 5, PIXELS(3) / 10);
436 Camera_MoveTo(PIXELS(288), -1, PIXELS(171), 1);
440 Camera_MoveTo(PIXELS(574), -1, PIXELS(180), 1);
450 Engine_CameraSetSpeed(PIXELS(4) / 5, PIXELS(1) / 10);
451 Engine_CameraMoveTo(PIXELS(574), -1, PIXELS(171), 1);
456 // Kraden: they are looking in the right place, but moving one statue
457 // springs the trap. Jenna: why would anyone put a trap here?
470 // Kraden: they have hidden something very important, perhaps the key to
471 // Alchemy itself.
483 // Kraden: "Should I tell you more?" Either answer, he thinks they would not
484 // understand yet.
489 if (Engine_EventChooseYesNo(0, 0) == 0) {
490 Engine_EventSetMessage(MsgSolSanctumHonestlyDoubtUnderstand);
491 } else {
492 Engine_EventSetMessage(MsgSolSanctumHmphWellTold);
493 }
495 // Kraden: "We must try to find a solution to this mystery." Garet:
496 // "Sheesh... Another mystery?" Kraden will keep checking the Luna room.
497 Engine_EventSetMessage(MsgSolSanctumTryFindSolution);
510 Engine_CameraSetSpeed(PIXELS(4) / 5, PIXELS(1) / 10);
511 Camera_MoveTo(PIXELS(574), -1, PIXELS(191), 1);
517 // Kraden, leaving: his intuition says the light is the key to the secret.
523 Camera_MoveTo(PIXELS(576), -1, PIXELS(215), 1);
526 // Leave Isaac in control after Jenna and Garet rejoin him.
527 Camera_SetSpeed(PIXELS(18) / 5, PIXELS(9) / 20);
528 Engine_CameraMoveTo(PIXELS(576), -1, PIXELS(136), 1);
533 // Jenna: "let's see if we can't figure this out ourselves."
537 Actor_SetSpeed(GARET, PIXELS(1), PIXELS(1) / 2);
538 Actor_SetSpeed(JENNA, PIXELS(1), PIXELS(1) / 2);
541 if (leader != 0) {
542 Engine_ActorSetDestination(JENNA, leader->x.part.pixel,
543 leader->z.part.pixel);
544 }
549 if (leader != 0) {
550 Engine_ActorSetDestination(GARET, leader->x.part.pixel,
551 leader->z.part.pixel);
552 }
558 work->transitionFrames = 16;
560}
561
562/// Pans toward the seals' lights, which flash ever faster until the stairway
563/// in the floor is uncovered, then restores the camera. Called by
564/// SolSanctumStatue_OpenSeal once the seals are open after the centre statue
565/// has moved.
567 struct MapScrollWork *map;
568 struct FieldActor *leader;
569 s32 *savedOrigin;
570 s32 cameraPosition[3];
571 s32 approachSide;
572 s32 frame;
573
574 map = gMapWork[0];
576 // Temporarily follow a local point, panning from the leader toward the seal.
577 if (leader->z.fixed < PIXELS(179)) {
581 savedOrigin = map->origin;
582 SET_VECTOR(cameraPosition, leader->x.fixed, leader->y.fixed,
583 leader->z.fixed);
584 map->origin = cameraPosition;
585 for (frame = 0; frame != 30; frame++) {
586 cameraPosition[2] += PIXELS(1);
588 }
590 approachSide = 1;
591 } else {
595 SET_VECTOR(cameraPosition, leader->x.fixed, leader->y.fixed,
596 leader->z.fixed);
597 savedOrigin = map->origin;
598 map->origin = cameraPosition;
599 for (frame = 0; frame != 30; frame++) {
600 cameraPosition[2] -= PIXELS(1);
602 }
604 approachSide = 2;
605 }
606 // Flash progressively faster before uncovering the stairway.
607 for (frame = 0; frame != 6; frame++) {
608 Map_CopyCellsTo(2, 28, 34, 10, 4, 2);
610 Map_CopyCellsTo(2, 30, 34, 10, 4, 2);
612 }
613 for (frame = 0; frame != 10; frame++) {
614 Map_CopyCellsTo(2, 28, 34, 10, 4, 2);
616 Map_CopyCellsTo(2, 30, 34, 10, 4, 2);
618 }
619 for (frame = 0; frame != 12; frame++) {
620 Map_CopyCellsTo(2, 28, 34, 10, 4, 2);
622 Map_CopyCellsTo(2, 30, 34, 10, 4, 2);
624 }
625 Map_CopyCellsTo(2, 28, 34, 10, 4, 2);
626 Map_CopyCellsTo(8, 55, 32, 40, 8, 4);
628 // Reverse the pan before restoring the caller's camera target.
629 if (approachSide == 1) {
630 for (frame = 0; frame != 30; frame++) {
631 cameraPosition[2] -= PIXELS(1);
633 }
634 } else if (approachSide == 2) {
635 for (frame = 0; frame != 30; frame++) {
636 cameraPosition[2] += PIXELS(1);
638 }
639 }
640 map->origin = savedOrigin;
641}
642
643/// Draws the three parallax rows while they overlap the screen. Run each frame
644/// as a callback that SolSanctumStatue_InitializeScrollingSprites adds.
646 struct MapScrollWork *map = gMapWork[0];
647 struct AnimationSpritePart *sprite = sScrollingSprites.parts;
648#ifdef UBFIX
649 s32 cameraX = map->viewX / PIXELS(1);
650 s32 screenY = 80 - map->viewY / PIXELS(1);
651#else
652 // UB: viewX and viewY are separate scalar members, not an array. Reading
653 // them by name adds four bytes in tbs-en.
654 s32 *view = &map->viewX;
655 s32 cameraX = view[0] / PIXELS(1);
656 s32 screenY = 80 - view[1] / PIXELS(1);
657#endif
658 s32 scrollX;
659 u32 column;
660
661 if ((u32)(screenY + 16) <= 175) {
662 // Keep the first sprite just left of the screen for seamless tiling.
663 scrollX = (gSolSanctumStatue_ScrollPhase >> 10) - cameraX;
665 for (column = 0; column < SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT; column++) {
666 sprite->x = scrollX;
667 sprite->y = screenY;
668 Runtime_PushSlotEntry(sprite, 0);
670 sprite++;
671 }
672 scrollX = (gSolSanctumStatue_ScrollPhase >> 9) - cameraX;
674 for (column = 0; column < SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT; column++) {
675 sprite->x = scrollX;
676 sprite->y = screenY;
677 Runtime_PushSlotEntry(sprite, 0);
679 sprite++;
680 }
681 scrollX = (gSolSanctumStatue_ScrollPhase >> 8) - cameraX;
683 for (column = 0; column < SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT; column++) {
684 sprite->x = scrollX;
686 Runtime_PushSlotEntry(sprite, 0);
688 sprite++;
689 }
690 }
691 // The three shifts turn this into 1/8, 1/4 and 1/2 pixel drift per frame.
693}
694
695/// Walking north over cell code 10: the way ahead is checked as on any field.
698 if (leader->facing == FACING_NORTH) {
700 }
701}
702
703/// Walking south over cell code 11: the way ahead is checked as on any field.
706 if (leader->facing == FACING_SOUTH) {
708 }
709}
710
711/// Unused sequence moving the northwest statue to its seal position.
719 }
720}
721
722/// Restores the hall's statues, beams and seals from their flags and plays
723/// Kraden's arrival cutscenes. Called by Field_RunScene once the actors exist.
724/// Sets FLAG_RETREAT_BLOCKED; starts the parallax rows; at entrance 3 plays
725/// SolSanctumStatue_VisitStatueHall and at entrance 4
726/// SolSanctumStatue_ExplainStatuePuzzle, each once (setting
727/// FLAG_SOL_SANCTUM_STATUE_HALL_VISITED or
728/// FLAG_SOL_SANCTUM_STATUE_PUZZLE_EXPLAINED), and not on a return after a
729/// battle.
731 struct FieldActor *centerEffect;
732
735 // Retreat does not work here (flag 0x144).
738 centerEffect->collisionFlags = 0;
739 {
740 u8 flags = centerEffect->priorityFlags | 2;
741
742 centerEffect->priorityFlags = flags;
743 }
747 // Only arrivals 3 and 4 keep Jenna and Garet staged for their conversations.
748 if ((u16)(gGameState.entrance - 3) > 1) {
751 }
758 Map_CopyCellsTo(0, 59, 15, 38, 4, 3);
760 Map_CopyCellsTo(4, 59, 17, 38, 4, 3);
761 Map_CopyCellsTo(8, 60, 17, 39, 2, 2);
762 Map_CopyCellAttributes(0, 1, 2, 1, 17, 7);
767 Map_CopyCellsTo(0, 28, 17, 8, 2, 1);
769 Map_CopyCellsTo(0, 59, 15, 38, 4, 3);
771 Map_CopyCellsTo(4, 59, 17, 38, 4, 3);
772 Map_CopyCellsTo(8, 60, 17, 39, 2, 2);
773 Map_CopyCellAttributes(0, 0, 2, 1, 17, 8);
774 } else {
777 Map_CopyCellsTo(0, 59, 15, 38, 4, 3);
778 }
781 Map_CopyCellsTo(4, 59, 17, 38, 4, 3);
782 }
783 }
786 Map_CopyCellsTo(2, 28, 34, 10, 2, 1);
787 Map_CopyCellsTo(2, 30, 16, 10, 2, 1);
788 Map_CopyCellsTo(0, 55, 32, 40, 4, 3);
789 }
792 Map_CopyCellsTo(4, 28, 36, 10, 2, 1);
793 Map_CopyCellsTo(4, 30, 18, 10, 2, 1);
794 Map_CopyCellsTo(4, 55, 36, 40, 4, 3);
795 }
798 Map_CopyCellsTo(2, 29, 34, 11, 2, 1);
799 Map_CopyCellsTo(2, 31, 16, 11, 2, 1);
800 Map_CopyCellsTo(0, 58, 32, 43, 4, 1);
801 }
804 Map_CopyCellsTo(4, 29, 36, 11, 2, 1);
805 Map_CopyCellsTo(4, 31, 18, 11, 2, 1);
806 Map_CopyCellsTo(4, 58, 36, 43, 4, 1);
807 }
808 if (gGameState.entrance == 3) {
812 } else if (GameFlag_IsSet(FLAG_KEEP_PARTY_POSITION) == 0) {
815 }
816 }
817 if (gGameState.entrance == 4) {
821 } else if (GameFlag_IsSet(FLAG_KEEP_PARTY_POSITION) == 0) {
824 }
825 }
830 }
831 return 0;
832}
833
834/// Loads three graphic strips and initializes their scrolling sprite rows.
836 u32 column;
837 s32 tile;
838 s32 *spriteWords;
839 u8 *pixels;
840
841 spriteWords = sScrollingSprites.words;
842 pixels = Runtime_AllocateBlock(14, 1024);
844 tile = Engine_VramLoad(Resource_FindFreeEntry(), 128, pixels);
845 for (column = 0; column < SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT; column++) {
846 s32 *attributeWords = spriteWords;
847
848 *attributeWords++ = 0;
849 *attributeWords++ = 0x40004000;
850 spriteWords += 3;
851 *attributeWords = tile | 0xac00;
852 }
853 tile = Engine_VramLoad(Resource_FindFreeEntry(), 128, pixels + 128);
854 for (column = 0; column < SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT; column++) {
855 s32 *attributeWords = spriteWords;
856
857 *attributeWords++ = 0;
858 *attributeWords++ = 0x40004000;
859 spriteWords += 3;
860 *attributeWords = tile | 0xdc00;
861 }
862 tile = Engine_VramLoad(Resource_FindFreeEntry(), 128, pixels + 256);
863 for (column = 0; column < SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT; column++) {
864 s32 *attributeWords = spriteWords;
865
866 *attributeWords++ = 0;
867 *attributeWords++ = 0x40004000;
868 spriteWords += 3;
869 *attributeWords = tile | 0xc00;
870 }
872 {
873 s32 priority = 3200;
874
876 priority);
877 }
878}
879
880/// Moving the northwest statue with Move: on its seal, the seal opens.
881/// Reached by Move on actor 9 until FLAG_SOL_SANCTUM_NORTHWEST_SEAL_OPEN is
882/// set.
883static void Event_NorthwestStatueMoved(void) {
886 }
887}
888
889/// Moving the northeast statue with Move: on its seal, the seal opens.
890/// Reached by Move on actor 11 until FLAG_SOL_SANCTUM_NORTHEAST_SEAL_OPEN is
891/// set.
892static void Event_NortheastStatueMoved(void) {
895 }
896}
897
898/// Moving the southwest statue with Move: on its seal, the seal opens.
899/// Reached by Move on actor 13 until FLAG_SOL_SANCTUM_SOUTHWEST_SEAL_OPEN is
900/// set.
901static void Event_SouthwestStatueMoved(void) {
904 }
905}
906
907/// Moving the southeast statue with Move: on its seal, the seal opens.
908/// Reached by Move on actor 15 until FLAG_SOL_SANCTUM_SOUTHEAST_SEAL_OPEN is
909/// set.
910static void Event_SoutheastStatueMoved(void) {
913 }
914}
915
916/// Moving the left beam statue with Move: its cell is freed, and in front of
917/// the centre it shines its beam. Reached by Move on actor 10 until
918/// FLAG_SOL_SANCTUM_LEFT_BEAM_SHINING is set.
919static void Event_LeftBeamStatueMoved(void) {
920 Field_SetMapCellCollision(2, PIXELS(208), PIXELS(112), 0);
923 }
924}
925
926/// Moving the right beam statue with Move: as the left one. Reached by Move on
927/// actor 12 until FLAG_SOL_SANCTUM_RIGHT_BEAM_SHINING is set.
928static void Event_RightBeamStatueMoved(void) {
929 Field_SetMapCellCollision(2, PIXELS(352), PIXELS(112), 0);
932 }
933}
934
935/// Starting Move beside the centre statue: its cells are blocked while the
936/// leader stands in their row. Reached by the first phase of Move on actor 17
937/// until FLAG_SOL_SANCTUM_CENTER_STATUE_MOVED is set.
939 struct FieldActor *leaderPosition;
940 s32 column;
941 struct FieldActor *leader;
942
943 leaderPosition = Object_GetById(ACTOR_PARTY_LEADER);
944 column = leaderPosition->x.fixed >> 20;
946 if ((leader->z.fixed >> 20) == 8) {
947 if ((u32)(column - 17) <= 1) {
948 Field_SetMapCellCollision(2, PIXELS(272), PIXELS(128), 255);
949 Field_SetMapCellCollision(2, PIXELS(288), PIXELS(128), 255);
950 }
951 }
952}
953
954/// Starting Move beside the left beam statue: its cell is blocked while the
955/// leader stands beside it. Reached by the first phase of Move on actor 10
956/// until FLAG_SOL_SANCTUM_LEFT_BEAM_SHINING is set.
957static void Event_BlockLeftTriggerCell(void) {
960
961 if (row == 7 && (u32)(column - 13) <= 1) {
962 Field_SetMapCellCollision(2, PIXELS(208), PIXELS(112), 255);
963 }
964}
965
966/// Starting Move beside the right beam statue: as the left one, on actor 12.
970
971 if (row == 7 && (u32)(column - 21) <= 1) {
972 Field_SetMapCellCollision(2, PIXELS(352), PIXELS(112), 255);
973 }
974}
975
976/// Moving the centre statue with Move, or a beam completing the pair: with
977/// both beams shining the statue slides into the opened floor and the hall
978/// shakes. "Something clicked!" Reached by Move on actor 17 until
979/// FLAG_SOL_SANCTUM_CENTER_STATUE_MOVED is set, and called by
980/// SolSanctumStatue_OpenCentralHole. Sets FLAG_SOL_SANCTUM_CENTER_STATUE_MOVED,
981/// and FLAG_SOL_SANCTUM_ALL_SEALS_OPEN when the four seals are open; actor 18
982/// takes the statue's place in the hole.
983static void Event_CenterStatueMoved(void) {
984 struct FieldActor *statue;
985 struct FieldActor *leader;
986 s32 statueZ;
987
989 Field_SetMapCellCollision(2, PIXELS(272), PIXELS(128), 0);
990 Field_SetMapCellCollision(2, PIXELS(288), PIXELS(128), 0);
991 if (statue != NULL) {
992 statueZ = statue->z.fixed;
994 if ((statueZ >> 20) == 8) {
997 if ((u32)(leader->z.fixed >> 19) <= 17) {
1000 leader->facing = FACING_NORTH;
1001 }
1002 }
1006 // The statue slides south into the hole; actor 18 stands in for it
1007 // there and the hall shakes hard, then settles.
1008 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
1009 Camera_MoveTo(PIXELS(286), -1, PIXELS(146), 1);
1014 statue->motionFlags = 0;
1020 statue->targetX = ACTOR_NO_TARGET;
1021 statue->targetY = ACTOR_NO_TARGET;
1022 statue->targetZ = ACTOR_NO_TARGET;
1023 statue->x.fixed = 0;
1024 statue->y.fixed = 0;
1025 statue->z.fixed = 0;
1026 SET_VELOCITY(statue, 0, 0, 0);
1029 Engine_EventWait(10);
1032 Engine_EventWait(10);
1034 Engine_EventWait(35);
1036 Engine_EventWait(20);
1038 Engine_EventWait(30);
1040 Engine_EventWait(40);
1043 Engine_EventWait(10);
1044 Map_SetShake(-1, -1, 9 * Q16_ONE / 10);
1045 Engine_EventWait(60);
1052 }
1053 Engine_EventWait(40);
1054 Engine_MessageShowCentered(MsgSolSanctumSomethingClicked, 1);
1055 Map_CopyCellAttributes(0, 1, 2, 1, 17, 8);
1056 Map_CopyCellAttributes(17, 9, 2, 1, 17, 7);
1057 }
1058 }
1060 }
1061}
1062
1063/// Walking into the centre statue from the south: the leader pushes it north.
1064/// Reached by walking north into cell code 32 until
1065/// FLAG_SOL_SANCTUM_CENTER_STATUE_MOVED is set.
1067 struct FieldActor *movingActor;
1068
1069 movingActor = Object_GetById(ACTOR_CENTER_STATUE);
1070 if (movingActor != 0) {
1071 if ((movingActor->z.fixed >> 20) == 8) {
1078 movingActor = Object_GetById(ACTOR_PARTY_LEADER);
1079 Actor_SetDestination(ACTOR_PARTY_LEADER, movingActor->x.part.pixel, 136);
1084 }
1085 }
1086}
1087
1088/// Walking into the northwest statue: the leader pushes it onto its seal.
1089/// Reached by walking east into cell code 5 until
1090/// FLAG_SOL_SANCTUM_NORTHWEST_SEAL_OPEN is set.
1091static void Event_PushNorthwestStatue(void) {
1094}
1095
1096/// Walking into the northeast statue: the leader pushes it onto its seal.
1097/// Reached by walking west into cell code 6 until
1098/// FLAG_SOL_SANCTUM_NORTHEAST_SEAL_OPEN is set.
1099static void Event_PushNortheastStatue(void) {
1102}
1103
1104/// Walking into the southwest statue: the leader pushes it onto its seal.
1105/// Reached by walking east into cell code 7 until
1106/// FLAG_SOL_SANCTUM_SOUTHWEST_SEAL_OPEN is set.
1107static void Event_PushSouthwestStatue(void) {
1110}
1111
1112/// Walking into the southeast statue: the leader pushes it onto its seal.
1113/// Reached by walking west into cell code 8 until
1114/// FLAG_SOL_SANCTUM_SOUTHEAST_SEAL_OPEN is set.
1115static void Event_PushSoutheastStatue(void) {
1118}
1119
1120/// Walking into the left beam statue from the west: it slides east in front
1121/// of the centre and shines its beam. Reached by walking east into cell codes
1122/// 20 and 21 until FLAG_SOL_SANCTUM_LEFT_BEAM_SHINING is set.
1126}
1127
1128/// Walking into the left beam statue from the north: it slides one cell south.
1129/// Reached by walking south into cell code 21 until the beam shines.
1132 s32 row;
1133
1134 if (statue == 0) {
1135 return;
1136 }
1137
1138 row = statue->z.fixed >> 20;
1140}
1141
1142/// Walking into the left beam statue from the south: it slides one cell north.
1143/// Reached by walking north into cell codes 23 and 24 until the beam shines.
1146 if (statue != NULL) {
1147 s32 row = statue->z.fixed >> 20;
1149 }
1150}
1151
1152/// Walking into the right beam statue from the east: as the left one. Reached
1153/// by walking west into cell codes 25 and 26 until
1154/// FLAG_SOL_SANCTUM_RIGHT_BEAM_SHINING is set.
1158}
1159
1160/// Walking into the right beam statue from the north: it slides one cell south.
1161/// Reached by walking south into cell code 26 until the beam shines.
1164 if (statue != NULL) {
1165 s32 row = statue->z.fixed >> 20;
1167 }
1168}
1169
1170/// Walking into the right beam statue from the south: it slides one cell north.
1171/// Reached by walking north into cell codes 28 and 29 until the beam shines.
1174 if (statue != NULL) {
1175 s32 row = statue->z.fixed >> 20;
1177 }
1178}
1179
1180/// Moves the leader and statue together to the centers of their target cells.
1181static void SolSanctumStatue_PushStatue(s32 statueId, s32 statueColumn,
1182 s32 statueRow, s32 leaderColumn,
1183 s32 leaderRow) {
1184 s32 statueX;
1185 s32 statueZ;
1186
1189 Actor_SetSpeed(statueId, PIXELS(1) / 5, PIXELS(1) / 10);
1193 Engine_ActorSetDestination(ACTOR_PARTY_LEADER, (leaderColumn << 4) + 8,
1194 (leaderRow << 4) + 8);
1195 statueX = statueColumn << 4;
1196 statueZ = statueRow << 4;
1197 Engine_ActorSetDestination(statueId, statueX + 8, statueZ + 8);
1198 Engine_ActorWaitForMove(statueId);
1201}
1202
1203/// Returns 1 when the actor stands in the given map cell.
1204static s32 SolSanctumStatue_IsActorAtCell(s32 actorId, s32 column, s32 row) {
1205 struct FieldActor *actor = Object_GetById(actorId);
1206 if (actor == NULL || (actor->x.fixed >> 20) != column) {
1207 return 0;
1208 }
1209 if ((actor->z.fixed >> 20) != row) {
1210 return 0;
1211 }
1212 return 1;
1213}
1214
1215/// Configures the northwest seal animation and statue return position.
1217 struct SealScene *scene = &sSealScene;
1218 scene->open.srcX = 0;
1219 scene->open.srcY = 55;
1220 scene->open.destX = 32;
1221 scene->open.destY = 40;
1222 scene->open.width = 4;
1223 scene->open.height = 3;
1224 scene->pulseA.srcX = 2;
1225 scene->pulseA.srcY = 30;
1226 scene->pulseA.destX = 34;
1227 scene->pulseA.destY = 10;
1228 scene->pulseA.width = 2;
1229 scene->pulseA.height = 1;
1230 scene->pulseB.srcX = 2;
1231 scene->pulseB.srcY = 28;
1232 scene->pulseB.destX = 34;
1233 scene->pulseB.destY = 10;
1234 scene->pulseB.width = 2;
1235 scene->pulseB.height = 1;
1236 scene->opened.srcX = 2;
1237 scene->opened.srcY = 30;
1238 scene->opened.destX = 16;
1239 scene->opened.destY = 10;
1240 scene->opened.width = 2;
1241 scene->opened.height = 1;
1243 scene->facing = FACING_SOUTH;
1244 scene->destX = 500;
1245 scene->destZ = 132;
1246 scene->stairs[0].srcX = 8;
1247 scene->stairs[0].srcY = 55;
1248 scene->stairs[0].destX = 32;
1249 scene->stairs[0].destY = 40;
1250 scene->stairs[0].width = 4;
1251 scene->stairs[0].height = 3;
1252 scene->stairs[1].srcX = 2;
1253 scene->stairs[1].srcY = 30;
1254 scene->stairs[1].destX = 34;
1255 scene->stairs[1].destY = 10;
1256 scene->stairs[1].width = 2;
1257 scene->stairs[1].height = 1;
1258 scene->stairs[2].srcX = 2;
1259 scene->stairs[2].srcY = 28;
1260 scene->stairs[2].destX = 16;
1261 scene->stairs[2].destY = 10;
1262 scene->stairs[2].width = 2;
1263 scene->stairs[2].height = 1;
1265 scene->actorX = 488;
1266 scene->actorZ = 152;
1268}
1269
1270/// Configures the northeast seal animation and statue return position.
1272 struct SealScene *scene = &sSealScene;
1273 scene->open.srcX = 4;
1274 scene->open.srcY = 55;
1275 scene->open.destX = 36;
1276 scene->open.destY = 40;
1277 scene->open.width = 4;
1278 scene->open.height = 3;
1279 scene->pulseA.srcX = 4;
1280 scene->pulseA.srcY = 30;
1281 scene->pulseA.destX = 36;
1282 scene->pulseA.destY = 10;
1283 scene->pulseA.width = 2;
1284 scene->pulseA.height = 1;
1285 scene->pulseB.srcX = 4;
1286 scene->pulseB.srcY = 28;
1287 scene->pulseB.destX = 36;
1288 scene->pulseB.destY = 10;
1289 scene->pulseB.width = 2;
1290 scene->pulseB.height = 1;
1291 scene->opened.srcX = 4;
1292 scene->opened.srcY = 30;
1293 scene->opened.destX = 18;
1294 scene->opened.destY = 10;
1295 scene->opened.width = 2;
1296 scene->opened.height = 1;
1298 scene->facing = FACING_SOUTH;
1299 scene->destX = 654;
1300 scene->destZ = 132;
1301 scene->stairs[0].srcX = 12;
1302 scene->stairs[0].srcY = 55;
1303 scene->stairs[0].destX = 36;
1304 scene->stairs[0].destY = 40;
1305 scene->stairs[0].width = 4;
1306 scene->stairs[0].height = 3;
1307 scene->stairs[1].srcX = 4;
1308 scene->stairs[1].srcY = 30;
1309 scene->stairs[1].destX = 36;
1310 scene->stairs[1].destY = 10;
1311 scene->stairs[1].width = 2;
1312 scene->stairs[1].height = 1;
1313 scene->stairs[2].srcX = 4;
1314 scene->stairs[2].srcY = 28;
1315 scene->stairs[2].destX = 18;
1316 scene->stairs[2].destY = 10;
1317 scene->stairs[2].width = 2;
1318 scene->stairs[2].height = 1;
1320 scene->actorX = 664;
1321 scene->actorZ = 152;
1323}
1324
1325/// Configures the southwest seal animation and statue return position.
1327 struct SealScene *scene = &sSealScene;
1328 scene->open.srcX = 0;
1329 scene->open.srcY = 58;
1330 scene->open.destX = 32;
1331 scene->open.destY = 43;
1332 scene->open.width = 4;
1333 scene->open.height = 1;
1334 scene->pulseA.srcX = 2;
1335 scene->pulseA.srcY = 31;
1336 scene->pulseA.destX = 34;
1337 scene->pulseA.destY = 11;
1338 scene->pulseA.width = 2;
1339 scene->pulseA.height = 1;
1340 scene->pulseB.srcX = 2;
1341 scene->pulseB.srcY = 29;
1342 scene->pulseB.destX = 34;
1343 scene->pulseB.destY = 11;
1344 scene->pulseB.width = 2;
1345 scene->pulseB.height = 1;
1346 scene->opened.srcX = 2;
1347 scene->opened.srcY = 31;
1348 scene->opened.destX = 16;
1349 scene->opened.destY = 11;
1350 scene->opened.width = 2;
1351 scene->opened.height = 1;
1353 scene->facing = FACING_NORTH;
1354 scene->destX = 500;
1355 scene->destZ = 216;
1356 scene->stairs[0].srcX = 8;
1357 scene->stairs[0].srcY = 58;
1358 scene->stairs[0].destX = 32;
1359 scene->stairs[0].destY = 43;
1360 scene->stairs[0].width = 4;
1361 scene->stairs[0].height = 1;
1362 scene->stairs[1].srcX = 2;
1363 scene->stairs[1].srcY = 31;
1364 scene->stairs[1].destX = 34;
1365 scene->stairs[1].destY = 11;
1366 scene->stairs[1].width = 2;
1367 scene->stairs[1].height = 1;
1368 scene->stairs[2].srcX = 2;
1369 scene->stairs[2].srcY = 29;
1370 scene->stairs[2].destX = 16;
1371 scene->stairs[2].destY = 11;
1372 scene->stairs[2].width = 2;
1373 scene->stairs[2].height = 1;
1375 scene->actorX = 488;
1376 scene->actorZ = 200;
1378}
1379
1380/// Configures the southeast seal animation and statue return position.
1382 struct SealScene *scene = &sSealScene;
1383 scene->open.srcX = 4;
1384 scene->open.srcY = 58;
1385 scene->open.destX = 36;
1386 scene->open.destY = 43;
1387 scene->open.width = 4;
1388 scene->open.height = 1;
1389 scene->pulseA.srcX = 4;
1390 scene->pulseA.srcY = 31;
1391 scene->pulseA.destX = 36;
1392 scene->pulseA.destY = 11;
1393 scene->pulseA.width = 2;
1394 scene->pulseA.height = 1;
1395 scene->pulseB.srcX = 4;
1396 scene->pulseB.srcY = 29;
1397 scene->pulseB.destX = 36;
1398 scene->pulseB.destY = 11;
1399 scene->pulseB.width = 2;
1400 scene->pulseB.height = 1;
1401 scene->opened.srcX = 4;
1402 scene->opened.srcY = 31;
1403 scene->opened.destX = 18;
1404 scene->opened.destY = 11;
1405 scene->opened.width = 2;
1406 scene->opened.height = 1;
1408 scene->facing = FACING_NORTH;
1409 scene->destX = 654;
1410 scene->destZ = 216;
1411 scene->stairs[0].srcX = 12;
1412 scene->stairs[0].srcY = 58;
1413 scene->stairs[0].destX = 36;
1414 scene->stairs[0].destY = 43;
1415 scene->stairs[0].width = 4;
1416 scene->stairs[0].height = 1;
1417 scene->stairs[1].srcX = 4;
1418 scene->stairs[1].srcY = 31;
1419 scene->stairs[1].destX = 36;
1420 scene->stairs[1].destY = 11;
1421 scene->stairs[1].width = 2;
1422 scene->stairs[1].height = 1;
1423 scene->stairs[2].srcX = 4;
1424 scene->stairs[2].srcY = 29;
1425 scene->stairs[2].destX = 18;
1426 scene->stairs[2].destY = 11;
1427 scene->stairs[2].width = 2;
1428 scene->stairs[2].height = 1;
1430 scene->actorX = 664;
1431 scene->actorZ = 200;
1433}
1434
1435#define COPY_CELLS(copy) \
1436 Map_CopyCellsTo((copy).srcX, (copy).srcY, (copy).destX, (copy).destY, \
1437 (copy).width, (copy).height)
1438
1439/// Animates the seal and either advances the story or resets its statue.
1440/// Called by the four OpenXSeal functions with sSealScene filled in. Sets the
1441/// seal's flag; when no cutscene follows and the centre statue has not moved,
1442/// the statue slides back, the leader jumps clear and the flag is cleared
1443/// again.
1444static void SolSanctumStatue_OpenSeal(void) {
1445 struct SealScene *scene;
1446 s32 exitResult;
1447 s32 pulse;
1448
1449 exitResult = 0;
1452 // Show the configured seal and flash its two tile states.
1454 Engine_CameraMoveTo(PIXELS(576), -1, PIXELS(172), 1);
1458 for (pulse = 0; pulse != 20; pulse++) {
1465 }
1466 scene = &sSealScene;
1467 COPY_CELLS(scene->opened);
1468 Engine_GameFlagSet(scene->flag);
1469 exitResult = SolSanctumStatue_SelectStoryExit();
1470 // Keep the statue reusable until the central statue has moved.
1471 if (exitResult == -1) {
1480 scene->destZ);
1481 COPY_CELLS(scene->stairs[0]);
1482 COPY_CELLS(scene->stairs[1]);
1483 COPY_CELLS(scene->stairs[2]);
1486 scene->actorZ);
1488 Engine_GameFlagClear(scene->flag);
1489 }
1490 } else if (exitResult == 0 &&
1492 // DEAD: SelectStoryExit returns only 1 or -1, so this branch cannot run.
1499 }
1502 exitResult = 1;
1503 }
1504 }
1505 }
1506 if (exitResult == 1) {
1509 }
1511}
1512
1513/// Draws the left beam and opens the floor when the right beam is also lit.
1514/// Called when the left beam statue reaches its place in front of the centre,
1515/// until the centre statue has moved. Sets FLAG_SOL_SANCTUM_LEFT_BEAM_SHINING.
1520 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
1521 Camera_MoveTo(PIXELS(286), -1, PIXELS(146), 1);
1524 Map_CopyCellsTo(0, 59, 15, 38, 4, 3);
1526 Map_CopyCellsTo(8, 60, 17, 39, 2, 2);
1527 }
1529 Engine_EventWait(30);
1533 }
1534 }
1535 }
1537}
1538
1539/// Draws the right beam and opens the floor when the left beam is also lit.
1540/// As the left one; sets FLAG_SOL_SANCTUM_RIGHT_BEAM_SHINING.
1545 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
1546 Camera_MoveTo(PIXELS(286), -1, PIXELS(146), 1);
1549 Map_CopyCellsTo(4, 59, 17, 38, 4, 3);
1551 Map_CopyCellsTo(8, 60, 17, 39, 2, 2);
1552 }
1554 Engine_EventWait(30);
1558 }
1559 }
1560 }
1562}
1563
1564/// Shows the selected message from one speaker and waits the requested frames.
1565static void Event_SayThenWait(s32 speaker, s32 frames) {
1566 Engine_EventShowMessage(speaker, 0);
1567 Engine_EventWait(frames);
1568}
1569
1571 {0, CONDITION_ALWAYS, 287, 0, 176, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1572 {1, CONDITION_ALWAYS, 646, 0, 329, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1573 {2, CONDITION_ALWAYS, 647, 0, 470, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1574 {3, CONDITION_ALWAYS, 576, 0, 136, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1575 {4, CONDITION_ALWAYS, 576, 0, 136, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1576 {5, CONDITION_ALWAYS, 576, 0, 136, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1577 {6, CONDITION_ALWAYS, 576, 0, 136, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1578 {99, CONDITION_ALWAYS, 576, 0, 136, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1580};
1581
1583 SCENE_EXITS(12), SCENE_EXIT(1, 11, 2), SCENE_EXIT(2, 13, 1),
1584 SCENE_EXIT(3, 11, 4), SCENE_EXIT(4, 11, 5), SCENE_EXIT(5, 11, 6),
1585 SCENE_EXIT(6, 11, 7), SCENE_EXIT(10, 510, 1), SCENE_EXITS_END,
1586};
1587
1588// clang-format off
1591 PIXELS(1608), 0, PIXELS(1608), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1593 PIXELS(488), 0, PIXELS(152), FACING_SOUTH + FACING_STEP, TALK_FACE_PARTY, 0 },
1605 PIXELS(664), 0, PIXELS(200), FACING_NORTH + FACING_STEP, TALK_FACE_PARTY, 0 },
1609 PIXELS(288), 0, PIXELS(120), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1611 PIXELS(1608), 0, PIXELS(1608), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1613 PIXELS(560), 0, PIXELS(136), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1615 PIXELS(592), 0, PIXELS(136), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1616 { SCENE_TABLE_END },
1617};
1618// clang-format on
1619
1621 {0x31, 1, CONDITION_ALWAYS, 1},
1681};
1682
Ability numbers, named from the English release.
@ ABILITY_MOVE
Definition ability_ids.h:15
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
Animated sprites: their layers, frames and colour modes, and the resource slots they draw from.
Calls through a function pointer, by argument count.
The task scheduler: tasks, their order and the scheduler's state.
#define GARET
Jerald.
#define JENNA
Jasmine.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
The engine calls the debug menus import, and their palette swatch tiles.
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
u8 gSolSanctumStatue_SpriteRowsGfx[]
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
@ ANIM_WALK
Definition field_event.h:44
@ ANIM_STAND
Definition field_event.h:43
@ ANIM_NOD
Definition field_event.h:45
@ ANIM_SHAKE_HEAD
Definition field_event.h:46
void Engine_ActorFaceActor(s32 actor, s32 target, s32 frames)
s32 Engine_LeaderCheckAhead(void)
static void Actor_SetDestination(s32 actor, s32 x, s32 z)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
#define GameFlag_IsSet
void Engine_CameraSetSpeed(s32 speed, s32 acceleration)
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
static void Camera_SetSpeed(s32 speed, s32 acceleration)
void Engine_CameraMoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
#define EMOTE_IN_FRONT
Definition field_event.h:49
void Engine_ActorSetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_EventCloseScreen(void)
void Engine_ActorSetDestination(s32 actor, s32 x, s32 z)
static void Map_CopyCellsTo(s32 srcX, s32 srcY, s32 destX, s32 destY, s32 width, s32 height)
void Engine_ActorWalkToAndWait(s32 actor, s32 x, s32 z)
static void Actor_FaceActor(s32 actor, s32 target, s32 frames)
void Engine_HeapRelease(s32 slot)
s32 Engine_VramLoad(s32 block, s32 size, const void *data)
#define GameFlag_Clear
void Engine_EventWaitForScreen(void)
#define GameFlag_Set
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
void Engine_EventOpenScreen(void)
void Engine_GameFlagSet(s32 flag)
void Engine_GameFlagClear(s32 flag)
void Engine_CameraWaitForMove(void)
void Engine_ActorWaitForMove(s32 actor)
void Engine_CameraFollowActor(s32 actor, s32 keep_position)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
void Engine_ActorWalkTo(s32 actor, s32 x, s32 z)
static void Event_PlayCue(s32 cue)
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)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_ObjectMotionSetPositionAndCommit(s32 actor, s32 x, s32 z)
void Engine_MapRedraw(void)
static void Camera_MoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
static void Actor_SetPosition(s32 actor, s32 fixed_x, s32 fixed_z)
void Engine_ActorFaceEachOther(s32 actor, s32 other, s32 frames)
void Engine_EventWait(s32 frames)
static struct FieldActor * Actor_Get(s32 actor)
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ TRANSITION_BACKDROP_FADE
Definition field_obj.h:16
#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
@ ACTOR_FACES_MOTION
turns toward its velocity, 1/16 turn a frame
Definition field_obj.h:166
The scene table formats: entrances, exits, placements and events, and the macros that write them.
#define SCENE_EVENTS_END
@ EVENT_EXIT
@ FACING_STEP
Definition field_scene.h:36
#define PSYNERGY_PHASE_ON_ACTOR(ability, phase)
A Psynergy event on an actor at one phase of the cast, as PSYNERGY_IN_AREA is for an area.
#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_FACE_PARTY
#define PSYNERGY_ON_ACTOR(ability)
#define EVENT_SCRIPT(script)
@ ACTOR_STAND
#define SCENE_EXITS_END
Definition field_scene.h:77
#define TOUCH_WALKING_INTO(facing)
#define PLACEMENT_SHARE_PREVIOUS_SPRITE
@ FACING_EAST
Definition field_scene.h:26
@ FACING_SOUTHEAST
Definition field_scene.h:27
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_NORTHWEST
Definition field_scene.h:31
@ FACING_SOUTH
Definition field_scene.h:28
@ FACING_WEST
Definition field_scene.h:30
#define TOUCH_WALKING
#define PIXELS(value)
The scene service layer: one typed inline for each engine service a scene calls by its own name,...
static void Field_SetMapCellCollision(s32 a0, s32 a1, s32 a2, s32 a3)
16.16 fixed-point constants, sine and cosine, and the library division.
#define Q16_ONE
One in the engine's signed 16.16 fixed-point format.
Definition fixed_math.h:10
Game flags, named where their meaning is shown.
#define FLAG_SOL_SANCTUM_RIGHT_BEAM_SHINING
Definition flags.h:663
#define FLAG_SHOW_LOCATION_NAME
Definition flags.h:94
#define FLAG_SOL_SANCTUM_CENTER_STATUE_MOVED
Definition flags.h:664
#define FLAG_RETREAT_BLOCKED
Retreat is blocked, from Psynergy or an item.
Definition flags.h:55
#define FLAG_SOL_SANCTUM_FALLING_LIGHTS_SEEN
The statues' lights have flashed and fallen through the Luna room.
Definition flags.h:655
#define FLAG_SOL_SANCTUM_ERUPTED
The volcano has erupted and the sanctum's rooms rumble and shake.
Definition flags.h:660
#define FLAG_SOL_SANCTUM_NORTHEAST_SEAL_OPEN
Definition flags.h:646
#define FLAG_SOL_SANCTUM_LEFT_BEAM_SHINING
The statues beside the hall's centre shine their beams.
Definition flags.h:662
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_SOL_SANCTUM_SOUTHEAST_SEAL_OPEN
Definition flags.h:648
#define FLAG_SOL_SANCTUM_STATUE_TRAP_SPRUNG
The statues' lights have flashed as Kraden stood among them.
Definition flags.h:657
#define FLAG_SOL_SANCTUM_SOUTHWEST_SEAL_OPEN
Definition flags.h:647
#define FLAG_SOL_SANCTUM_ALL_SEALS_OPEN
Definition flags.h:649
#define FLAG_SCENE_TEMP_07
Definition flags.h:720
#define FLAG_SOL_SANCTUM_NORTHWEST_SEAL_OPEN
A statue stands on its seal and the seal's light shines.
Definition flags.h:645
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.
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
Definition heap.c:80
Small statement macros both games use for positions, velocities and bounds.
#define SET_VELOCITY(p, vx, vy, vz)
Definition macros.h:18
#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.
The heaps: allocating and freeing blocks.
The reel game's title lettering.
struct UiWindow * UiText_OpenMessageAtObject(s32 actor, s32 unused)
The event command "open message": opens the event's current message in a speech window next to the sp...
Definition messages.c:24
void Runtime_PushSlotEntry(void *slotEntry, s32 slot)
Links a sprite entry into depth slot slot (clamped to 0..255) for this frame.
Definition render.c:79
void BattleFx_SetQueuedSoundAndPlay(s32 soundId)
Plays SE_298, then soundId (SE_289 for -1), and remembers soundId for BattleFx_PlayQueuedSound in the...
Definition requests.c:90
A scene overlay's imports: queueing a scene sound and setting up its record buffer.
s32 Resource_DecodeByteLz(const void *source, void *destination)
Decodes a byte-oriented LZ resource and returns its unpacked byte count.
Definition decompress.c:37
void InitializeSceneRecordBuffer()
static void Event_PushLeftBeamStatueEast(void)
Walking into the left beam statue from the west: it slides east in front of the centre and shines its...
static void Event_PushNorthwestStatue(void)
Walking into the northwest statue: the leader pushes it onto its seal.
struct ScenePlacement gSolSanctumStatue_Placements[]
static void Event_NortheastStatueMoved(void)
Moving the northeast statue with Move: on its seal, the seal opens.
#define COPY_CELLS(copy)
static void Event_BlockRightTriggerCell(void)
Starting Move beside the right beam statue: as the left one, on actor 12.
static void SolSanctumStatue_OpenNorthwestSeal(void)
Configures the northwest seal animation and statue return position.
struct SceneEntrance gSolSanctumStatue_Entrances[]
static void Event_LeftBeamStatueMoved(void)
Moving the left beam statue with Move: its cell is freed, and in front of the centre it shines its be...
static UNUSED void SolSanctumStatue_MoveUnusedNorthwestStatue(void)
Unused sequence moving the northwest statue to its seal position.
static void Event_PushLeftBeamStatueNorth(void)
Walking into the left beam statue from the south: it slides one cell north.
static void SolSanctumStatue_OpenSouthwestSeal(void)
Configures the southwest seal animation and statue return position.
static void Event_PushRightBeamStatueNorth(void)
Walking into the right beam statue from the south: it slides one cell north.
static void Event_PushNortheastStatue(void)
Walking into the northeast statue: the leader pushes it onto its seal.
const struct SceneRegion * SolSanctumStatue_GetRegions(void)
s32 SolSanctumStatue_Initialize(void)
Restores the hall's statues, beams and seals from their flags and plays Kraden's arrival cutscenes.
static void Event_PushSouthwestStatue(void)
Walking into the southwest statue: the leader pushes it onto its seal.
struct SceneEvent gSolSanctumStatue_Events[]
static void SolSanctumStatue_InitializeScrollingSprites(void)
Loads three graphic strips and initializes their scrolling sprite rows.
#define FLAG_SOL_SANCTUM_STATUE_HALL_VISITED
static void Event_PushRightBeamStatueWest(void)
Walking into the right beam statue from the east: as the left one.
static void SolSanctumStatue_OpenNortheastSeal(void)
Configures the northeast seal animation and statue return position.
static s32 SolSanctumStatue_SelectStoryExit(void)
Chooses the cutscene in the Luna and Sol rooms that a newly opened seal leads to, and requests its ex...
StatueHallActor
The placed actors: Kraden, the eight statues, and the centre statue in its two places.
@ ACTOR_SOUTHEAST_STATUE
@ ACTOR_MOVED_CENTER_STATUE
@ ACTOR_SOUTHWEST_STATUE
@ ACTOR_NORTHWEST_STATUE
@ ACTOR_NORTHEAST_STATUE
@ ACTOR_RIGHT_BEAM_STATUE
@ ACTOR_CENTER_STATUE
@ ACTOR_LEFT_BEAM_STATUE
static void SolSanctumStatue_OpenSeal(void)
Animates the seal and either advances the story or resets its statue.
static void Event_RightBeamStatueMoved(void)
Moving the right beam statue with Move: as the left one.
static void Event_PushCenterStatueNorth(void)
Walking into the centre statue from the south: the leader pushes it north.
#define FLAG_SOL_SANCTUM_STATUE_PUZZLE_EXPLAINED
static void SolSanctumStatue_OpenCentralHole(void)
Animates the floor opening after both light beams meet, then lets the centre statue drop in if it sta...
static void SolSanctumStatue_VisitStatueHall(void)
Kraden comes back after the trap to find the hole in the floor, has the party tell how it opened,...
static void Event_PushRightBeamStatueSouth(void)
Walking into the right beam statue from the north: it slides one cell south.
static void SolSanctumStatue_RunSealOpenedSequence(void)
Pans toward the seals' lights, which flash ever faster until the stairway in the floor is uncovered,...
const struct SceneEvent * SolSanctumStatue_GetEvents(void)
Returns the statues' Move and push events, each row only until its seal or beam is done.
static void SolSanctumStatue_ExplainStatuePuzzle(void)
Kraden comes back after the falling lights to warn that the statues are a trap, and leaves the myster...
#define SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT
static void Event_CenterStatueMoved(void)
Moving the centre statue with Move, or a beam completing the pair: with both beams shining the statue...
static void Event_PushSoutheastStatue(void)
Walking into the southeast statue: the leader pushes it onto its seal.
static union @133327075273071043343026314075216362254362256270 sScrollingSprites
#define SOL_SANCTUM_STATUE_SPRITE_WIDTH
s32 gSolSanctumStatue_ScrollPhase
static void SolSanctumStatue_OpenSoutheastSeal(void)
Configures the southeast seal animation and statue return position.
static s32 SolSanctumStatue_IsActorAtCell(s32 actorId, s32 column, s32 row)
Returns 1 when the actor stands in the given map cell.
static void Event_BlockLeftTriggerCell(void)
Starting Move beside the left beam statue: its cell is blocked while the leader stands beside it.
static void SolSanctumStatue_ShineRightBeam(void)
Draws the right beam and opens the floor when the left beam is also lit.
static void Event_SouthwestStatueMoved(void)
Moving the southwest statue with Move: on its seal, the seal opens.
static void Event_SayThenWait(s32 speaker, s32 frames)
Shows the selected message from one speaker and waits the requested frames.
static void SolSanctumStatue_UpdateScrollingSprites(void)
Draws the three parallax rows while they overlap the screen.
static void Event_NorthwestStatueMoved(void)
Moving the northwest statue with Move: on its seal, the seal opens.
const u32 * SolSanctumStatue_GetExits(void)
const struct SceneEntrance * SolSanctumStatue_GetEntrances(void)
static void Event_CheckAheadFacingNorth(void)
Walking north over cell code 10: the way ahead is checked as on any field.
static struct SealScene sSealScene
The scene's bss, in this order; as commons of one object the linker would sort them itself.
static void Event_PushLeftBeamStatueSouth(void)
Walking into the left beam statue from the north: it slides one cell south.
static void Event_CheckAheadFacingSouth(void)
Walking south over cell code 11: the way ahead is checked as on any field.
static void SolSanctumStatue_ShineLeftBeam(void)
Draws the left beam and opens the floor when the right beam is also lit.
static void Event_SoutheastStatueMoved(void)
Moving the southeast statue with Move: on its seal, the seal opens.
const struct ScenePlacement * SolSanctumStatue_GetPlacements(void)
Returns Kraden (actor 8), the eight statues (9 to 16), the centre statue (17) and its moved copy (18)...
#define SOL_SANCTUM_STATUE_BACK_SCROLL_ROW_Y_OFFSET
u32 gSolSanctumStatue_Exits[]
static void Event_BlockCenterTriggerCells(void)
Starting Move beside the centre statue: its cells are blocked while the leader stands in their row.
static void SolSanctumStatue_PushStatue(s32 statueId, s32 statueColumn, s32 statueRow, s32 leaderColumn, s32 leaderRow)
Moves the leader and statue together to the centers of their target cells.
Song and sound effect ids, indices into gSound_SongTable.
#define SE_189
Definition songs.h:184
#define SE_186
Definition songs.h:181
#define SE_185
Definition songs.h:180
#define SE_188
Definition songs.h:183
#define SE_141
Definition songs.h:134
#define SE_200
Definition songs.h:195
#define SE_246
Definition songs.h:241
#define SE_289
Definition songs.h:282
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
void Engine_ActorShowEmote()
void Engine_TaskWait()
void Engine_EventSetMessage()
void Engine_EventShowMessage()
#define NULL
Definition bilibin.h:6
#define STATIC_ASSERT(condition)
C89 permits repeated extern declarations of the same array.
#define offsetof(type, member)
Definition stddef.h:19
The hardware sprite attributes one part of an animated sprite (its image or its shadow) is drawn with...
Definition animspr.h:84
u16 y
The OAM entry's attributes 0 to 2.
Definition animspr.h:90
u16 x
screen pixels
Definition animspr.h:96
A block of map cells copied from one place in the map to another.
s32 destY
map cells
s32 srcX
map cells
s32 srcY
map cells
s32 destX
map cells
s32 width
map cells
s32 height
map cells
The running scene's event work: its placement and event tables, its actors, the triggers and exit it ...
Definition event_work.h:20
s32 startTransition
SCENE_TRANSITION(style, variant).
Definition event_work.h:43
s32 transitionFrames
frames
Definition event_work.h:45
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s32 targetX
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:59
u8 steeringFlags
ActorSteeringFlag bits.
Definition field_obj.h:92
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
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
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 targetY
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:60
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
s16 entrance
Definition game_state.h:37
The field map's work: the followed position, screen shake, tile animations, blend script,...
Definition map_scroll.h:27
s32 viewY
the view's top left, 16.16 fixed-point pixels
Definition map_scroll.h:40
s32 * origin
The followed point, read as x, height and z in 16.16 fixed-point pixels; Camera_FollowActor points it...
Definition map_scroll.h:30
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 seal being opened: its cell animations, its flag, where the leader jumps back to and where its st...
s32 destX
pixels
s32 destZ
pixels
struct CellCopy pulseB
s32 facing
1/65536 turns
struct CellCopy pulseA
s32 actorX
pixels
struct CellCopy opened
struct CellCopy stairs[3]
s32 unused[3]
never read or written; the bss keeps its 12 bytes
struct CellCopy open
s32 actorZ
pixels
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
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
s32 words[3 *SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT *3]
struct AnimationSpritePart parts[3 *SOL_SANCTUM_STATUE_ROW_SPRITE_COUNT]
The patch levels: our groups of the measured changes from the Japanese release.
s32 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
Definition vram_cache.c:211