Alchemy
Loading...
Searching...
No Matches

sol_sanctum_elemental_star_room.c

Go to the documentation of this file.
1/// @file
2/// Sol Sanctum's Elemental Star room: the party bags the four stars from their
3/// pedestals, Saturos and Menardi take Jenna and Kraden hostage, and Alex takes
4/// the stars.
5
6#include "game_state.h"
7#include "unit/import.h"
11#include "unit/object/object.h"
13#include "unit/field/field.h"
14#include "unit/game/game.h"
15#include "unit/window/window.h"
17#include "unit/shop/shop.h"
19#include "field_obj.h"
20#include "types.h"
21#include "field_event.h"
22#include "field_scene.h"
24#include "overlay_object.h"
25#include "battle.h"
26#include "debug.h"
27#include "field.h"
28#include "game.h"
29#include "graphics.h"
30#include "menu.h"
31#include "minigame.h"
32#include "sound.h"
33#include "system.h"
34#include "battle_unit.h"
35#include "call.h"
36#include "field_service.h"
37#include "text/msg_ids.h"
38#include "glyph.h"
39#include "ability_ids.h"
40#include "objcmd.h"
41#include "facing_object.h"
42#include "fixed_math.h"
43#include "palbuf.h"
44#include "flags.h"
45#include "songs.h"
46#include "item_ids.h"
47
56 s32 frames);
58 s32 z);
61
70};
71
72#define NULL ((void *)0)
73
74struct ObjectRuntime;
75
77#include "common/effect_spawn.h"
78
79/// Advances through the current dialogue's consecutive messages.
80static __inline__ void SolSanctumElementalStarRoom_SkipMessages(s32 amount) {
81 gEventWork->message += amount;
82}
83
85
88}
89
91 return NULL;
92}
93
96}
97
100}
101
102/// Returns the star, dialogue, and boundary interactions.
105}
106
107/// Searching the Venus Star's pedestal: the room flashes, new crossings open
108/// between the pedestals, and the star goes into a Mythril Bag.
109static void Event_BagVenusStar(void) {
110 u32 i;
111 s32 itemOwner;
112 s32 message;
113
115 // Flash the room before revealing the crossings for this star.
117 for (i = 0; i != 6; i++) {
124 if (i == 1) {
126 }
127 }
130 Engine_CameraSetSpeed(PIXELS(12) / 5, PIXELS(3) / 10);
131 Camera_MoveTo(PIXELS(664), -1, PIXELS(497), 1);
137 Map_CopyCellAttributes(0, 0, 1, 1, 41, 29);
138 Map_CopyCellsTo(87, 42, 41, 31, 1, 2);
141 Engine_CameraSetSpeed(PIXELS(32) / 5, PIXELS(4) / 5);
142 Camera_MoveTo(PIXELS(311), -1, PIXELS(497), 1);
148 Map_CopyCellAttributes(0, 0, 1, 1, 19, 29);
149 Map_CopyCellsTo(87, 42, 19, 31, 1, 2);
152 Camera_MoveTo(PIXELS(663), -1, PIXELS(192), 1);
158 Map_CopyCellAttributes(0, 0, 1, 1, 41, 10);
159 Map_CopyCellsTo(87, 42, 41, 12, 1, 2);
164 Camera_MoveTo(PIXELS(710), -1, PIXELS(474), 0);
172 Map_SetShake(-1, -1, 9 * Q16_ONE / 10);
175 Map_CopyCellsTo(0, 40, 43, 66, 3, 3);
177 // Present the collected star, then return to Kraden's explanation.
179 PIXELS(16), PIXELS(464));
181 UiWork_PushValueSlot(itemOwner, 1);
182 message = MsgSolSanctumVenusStarBagged;
183 Engine_MessageShowCentered(message, 1);
188 Camera_MoveTo(PIXELS(462), -1, PIXELS(350), 0);
195 Engine_EventSetMessage(message - 1);
199 Engine_CameraMoveTo(PIXELS(710), -1, PIXELS(474), 0);
206}
207
208/// Searching the Mercury Star's pedestal: as the Venus Star.
209static void Event_BagMercuryStar(void) {
210 u32 i;
211 s32 itemOwner;
212 s32 message;
213
216 for (i = 0; i != 6; i++) {
217 ColorBuffer_ApplyTarget(0x404a4e, 1);
223 if (i == 1) {
225 }
226 }
229 Map_SetShake(0, 0, 0);
230 Camera_SetSpeed(PIXELS(28) / 5, PIXELS(7) / 10);
231 Camera_MoveTo(PIXELS(472), -1, PIXELS(98), 1);
237 Map_CopyCellAttributes(0, 0, 1, 1, 29, 4);
238 Map_CopyCellsTo(87, 42, 29, 6, 1, 2);
240 Map_SetShake(0, 0, 0);
241 Camera_MoveTo(PIXELS(343), -1, PIXELS(369), 1);
247 Map_CopyCellAttributes(0, 0, 1, 1, 21, 21);
248 Map_CopyCellsTo(87, 42, 21, 23, 1, 2);
250 Map_SetShake(0, 0, 0);
251 Camera_SetSpeed(PIXELS(16) / 5, PIXELS(2) / 5);
252 Camera_MoveTo(PIXELS(343), -1, PIXELS(497), 1);
258 Map_CopyCellAttributes(0, 0, 1, 1, 21, 29);
259 Map_CopyCellsTo(87, 42, 21, 31, 1, 2);
264 Camera_MoveTo(PIXELS(712), -1, PIXELS(152), 0);
272 Map_SetShake(-1, -1, 9 * Q16_ONE / 10);
275 Map_CopyCellsTo(0, 40, 43, 46, 3, 3);
277 // Present the collected star, then return to Kraden's explanation.
279 PIXELS(16), PIXELS(144));
281 UiWork_PushValueSlot(itemOwner, 1);
282 message = MsgSolSanctumPutMercuryStar;
283 Engine_MessageShowCentered(message, 1);
288 Camera_MoveTo(PIXELS(462), -1, PIXELS(350), 0);
295 Engine_EventSetMessage(message - 2);
299 Camera_MoveTo(PIXELS(712), -1, PIXELS(152), 0);
306}
307
308/// Searching the Jupiter Star's pedestal: the star is bagged, then Saturos and
309/// Menardi appear, take Jenna and Kraden hostage, and Alex takes the stars.
321}
322
323/// Reveals the Jupiter crossings and places the star in a mythril bag.
325 u32 i;
326 s32 itemOwner;
327
329 for (i = 0; i != 6; i++) {
330 ColorBuffer_ApplyTarget(0x4049d2, 1);
336 if (i == 1) {
338 }
339 }
342 Camera_SetSpeed(PIXELS(12) / 5, PIXELS(3) / 10);
343 Camera_MoveTo(PIXELS(167), -1, PIXELS(529), 1);
349 Map_CopyCellAttributes(0, 0, 1, 1, 10, 31);
350 Map_CopyCellsTo(87, 42, 10, 33, 1, 2);
352 Map_SetShake(0, 0, 0);
353 Camera_SetSpeed(PIXELS(32) / 5, PIXELS(4) / 5);
354 Camera_MoveTo(PIXELS(391), -1, PIXELS(177), 1);
360 Map_CopyCellAttributes(0, 0, 1, 1, 24, 9);
361 Map_CopyCellsTo(87, 42, 24, 11, 1, 2);
363 Map_SetShake(0, 0, 0);
364 Camera_SetSpeed(PIXELS(12) / 5, PIXELS(3) / 10);
365 Camera_MoveTo(PIXELS(583), -1, PIXELS(193), 1);
371 Map_CopyCellAttributes(0, 0, 1, 1, 36, 10);
372 Map_CopyCellsTo(87, 42, 36, 12, 1, 2);
377 Camera_MoveTo(PIXELS(232), -1, PIXELS(477), 0);
385 Map_SetShake(-1, -1, 9 * Q16_ONE / 10);
388 Map_CopyCellsTo(0, 40, 13, 66, 3, 3);
391 PIXELS(16), PIXELS(464));
393 UiWork_PushValueSlot(itemOwner, 1);
394 Engine_MessageShowCentered(MsgSolSanctumJupiterStarBagged, 1);
395}
396
397/// Brings Isaac and Garet back to discover Jenna and Kraden's captors.
399 struct FieldActor *leader;
400
406 Engine_EventWait(180);
414 if (leader != 0) {
415 Actor_SetPosition(GARET, leader->x.fixed, leader->z.fixed);
416 }
417 Actor_SetSpeed(GARET, PIXELS(1), PIXELS(1) / 2);
418 Actor_WalkToAndWait(GARET, 257, 491);
429 Actor_SetSpeed(GARET, PIXELS(6) / 5, PIXELS(3) / 5);
431 Actor_WalkToAndWait(GARET, 282, 469);
438 Engine_ActorJump(GARET, 6, 60);
443 Camera_SetSpeed(PIXELS(36) / 5, PIXELS(9) / 10);
444 Camera_MoveTo(PIXELS(485), -1, PIXELS(345), 1);
451}
452
453/// Reveals the masked intruder while the captors demand the stars.
456 u8 *spriteFlags;
457 struct FieldActor *felix;
458 struct FieldActor *glow;
459 s32 i;
460 u8 zero;
461
464 Engine_EventSetMessage(MsgSolSanctumLooksLikeTheyveSpottedUs);
488 spriteFlags = &felix->sprite->flags;
489 zero = 0;
490 *spriteFlags = zero;
491 felix->scaleX = Q16_ONE / 10;
492 felix->scaleY = Q16_ONE / 10;
493 glow->scaleX = Q16_ONE / 10;
494 glow->scaleY = Q16_ONE / 10;
497 motionFlags = &felix->motionFlags;
498 *motionFlags = zero;
499 felix->y.fixed = PIXELS(40);
508 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
509 Camera_MoveTo(PIXELS(471), -1, PIXELS(309), 1);
514 for (i = 0; i != 90; i++) {
515 felix->y.fixed -= PIXELS(1) / 10;
516 felix->scaleX += Q16_ONE / 100;
517 felix->scaleY += Q16_ONE / 100;
518 glow->scaleX += Q16_ONE / 100;
519 glow->scaleY += Q16_ONE / 100;
521 }
522 *motionFlags = 5;
524 for (i = 0; i != 60; i++) {
525 felix->y.fixed -= PIXELS(1) / 2;
527 }
530 *spriteFlags = 1;
533 {
535
536 /* FAKEMATCH: the bit held in the loop counter itemSlot keeps the 1 in r5
537 * ahead of the actor 8 call's arguments; as a plain |=, 31 instructions
538 * differ in tbs-en. */
540 i |= *flags;
541 *flags = i;
542 }
580 Camera_MoveTo(PIXELS(264), -1, PIXELS(460), 0);
591 if (Engine_EventChooseYesNo(0, 0) != 0) {
593 }
597 Engine_CameraMoveTo(PIXELS(477), -1, PIXELS(334), 0);
605 Engine_EventSetMessage(MsgSolSanctumWhyDenyDont);
616}
617
618/// Has the captors offer a guarantee for their hostages' safety.
664 Camera_MoveTo(PIXELS(261), -1, PIXELS(466), 0);
679 Engine_EventSetMessage(MsgSolSanctumMenardiDontYouWantThem);
689 Camera_MoveTo(PIXELS(477), -1, PIXELS(334), 0);
714}
715
716/// Reveals Felix's identity and lets Isaac decide how to hand over the stars.
718 struct FieldActor *actor;
719 struct FieldActor *other;
720 u16 *inventoryEntry;
721 s32 remainingSlots;
722 s32 starCount;
723 s32 messageA;
724 s32 messageB;
725
730 if (other != 0) {
731 Actor_SetPosition(ACTOR_FELIX, other->x.fixed, other->z.fixed);
732 }
795 Camera_MoveTo(PIXELS(261), -1, PIXELS(466), 0);
806 Actor_SetSpeed(GARET, PIXELS(1) / 2, PIXELS(1) / 4);
808 Actor_WalkToAndWait(GARET, 260, 490);
816 starCount = 0;
817 inventoryEntry = UnitGet(1)->inventory;
818 remainingSlots = 14;
819 do {
820 u32 item = *inventoryEntry & 0x1ff;
821 inventoryEntry++;
822 if (item == 220 || item == 221 || item == 223)
823 starCount++;
824 remainingSlots--;
825 } while (remainingSlots >= 0);
827 if (Engine_EventChooseYesNo(0, 0) == 0) {
828 messageA = MsgSolSanctumGuessTakeElemental;
829 Engine_EventSetMessage(messageA);
832 if (starCount <= 2) {
834 Actor_WalkToAndWait(GARET, 252, 486);
837 UiText_ShowCenteredMessage((messageA + 1), 1, 0);
838 } else {
839 Engine_EventSetMessage(MsgSolSanctumRightTake);
841 }
842 } else {
843 if (starCount <= 2) {
844 messageB = MsgSolSanctumDontHandOver;
845 Engine_EventSetMessage(messageB);
854 Actor_WalkToAndWait(GARET, 244, 478);
859 UiText_ShowCenteredMessage((messageB + 1), 1, 0);
863 } else {
864 Engine_EventSetMessage(MsgSolSanctumWontLetGo);
870 }
871 }
872 Camera_SetSpeed(PIXELS(1) / 2, PIXELS(1) / 16);
877 Actor_SetSpeed(GARET, PIXELS(1) / 2, PIXELS(1) / 4);
878 actor = Object_GetById(GARET);
880 Actor_WalkToAndWait(GARET, 264, 482);
882 Actor_WalkToAndWait(GARET, 278, 480);
883 actor->speed = PIXELS(3);
884 actor->acceleration = PIXELS(2);
886 actor->velocityY = PIXELS(6);
888 Actor_MoveToAndWait(GARET, 312, 470);
892 actor->velocityY = PIXELS(6);
894 Actor_MoveToAndWait(GARET, 342, 470);
898 actor->velocityY = PIXELS(6);
900 Actor_MoveToAndWait(GARET, 376, 470);
902}
903
904/// Has Alex collect the stars and returns the party to the final pedestal.
906 u32 i;
907 struct FieldActor *actor;
908 struct FieldActor *alex;
909 u8 none;
910
914 alex = Actor_Get(ACTOR_ALEX);
925 Engine_EventSetMessage(MsgSolSanctumPermitRelieveElemental);
938 Actor_SetSpeed(GARET, PIXELS(1) / 2, PIXELS(1) / 4);
939 Actor_WalkToAndWait(GARET, 389, 468);
942 UiText_ShowCenteredMessage(MsgSolSanctumPermitRelieveElemental + 4, 1, 10);
943 Actor_SetSpeed(GARET, PIXELS(1) / 2, PIXELS(1) / 4);
944 actor = Object_GetById(GARET);
946 none = 0;
947 Actor_WalkToAndWait(GARET, 376, 470);
952 Engine_EventSetMessage(MsgSolSanctumPermitRelieveElemental + 5);
962 alex = Actor_Get(ACTOR_ALEX);
964 actor = Object_GetById(ACTOR_ALEX);
965 actor->motionFlags = none;
967 for (i = 0; i != 30; i++) {
968 actor->y.fixed += PIXELS(1);
970 }
971 actor->motionFlags = 5;
986 Camera_MoveTo(PIXELS(477), -1, PIXELS(334), 0);
995 Camera_SetSpeed(PIXELS(32) / 5, PIXELS(4) / 5);
996 Camera_MoveTo(PIXELS(374), -1, PIXELS(470), 1);
1001 if (Engine_EventChooseYesNo(1, 0) != 0) {
1002 Engine_EventWait(10);
1004 Engine_EventSetMessage(MsgSolSanctumDontWantAnything);
1006 if (Engine_EventChooseYesNo(1, 0) == 0) {
1007 do {
1008 Engine_EventWait(20);
1010 Engine_EventWait(10);
1011 Engine_EventSetMessage(MsgSolSanctumDoubtHowFeel);
1013 } while (Engine_EventChooseYesNo(1, 0) == 0);
1014 }
1015 }
1016 Engine_EventWait(30);
1018 Engine_EventWait(20);
1019 Engine_EventSetMessage(MsgSolSanctumThankCooperation);
1022 Engine_EventWait(10);
1024 actor->motionFlags = 0;
1025 Actor_SetSpeed(ACTOR_ALEX, PIXELS(12) / 5, PIXELS(6) / 5);
1026 FieldObject_SetPosition(actor, PIXELS(460), 0, PIXELS(360));
1029 alex = Actor_Get(ACTOR_ALEX);
1031 Engine_EventWait(30);
1034 Engine_EventWait(40);
1037 Engine_EventWait(20);
1038 actor = Object_GetById(GARET);
1040 actor->speed = PIXELS(3);
1041 actor->acceleration = PIXELS(2);
1043 actor->velocityY = PIXELS(6);
1045 Actor_MoveToAndWait(GARET, 342, 470);
1047 Engine_EventWait(30);
1049 actor->velocityY = PIXELS(6);
1051 Actor_MoveToAndWait(GARET, 312, 470);
1053 Engine_EventWait(30);
1055 actor->velocityY = PIXELS(6);
1057 Actor_MoveToAndWait(GARET, 278, 480);
1059 Engine_EventWait(30);
1060 Camera_SetSpeed(PIXELS(1) / 2, PIXELS(1) / 16);
1062 Actor_SetSpeed(GARET, PIXELS(8) / 5, PIXELS(4) / 5);
1064 Engine_EventWait(30);
1069 Engine_EventWait(20);
1071 {
1073
1074 if (leader != NULL) {
1075 Actor_SetDestination(GARET, leader->x.part.pixel, leader->z.part.pixel);
1076 }
1077 }
1079 Actor_SetPosition(GARET, 0, 0);
1083}
1084
1085/// Arranges the captors and hostages after the exchange.
1087 struct FieldActor *leader;
1088 struct FieldActor *actor;
1089 struct FieldActor *alex;
1090
1099 Actor_SetPosition(JENNA, PIXELS(475), PIXELS(332));
1105 actor = Object_GetById(JENNA);
1106 actor->linkedObject = leader;
1107 actor->steeringFlags |= 1;
1110 actor->linkedObject = leader;
1111 actor->steeringFlags |= 1;
1114 actor->linkedObject = leader;
1115 actor->steeringFlags |= 1;
1118 actor->linkedObject = leader;
1119 actor->steeringFlags |= 1;
1121 alex = Object_GetById(ACTOR_ALEX);
1122 alex->linkedObject = leader;
1123 alex->steeringFlags |= 1;
1124 alex->scaleX = Q16_ONE;
1125 alex->scaleY = Q16_ONE;
1127 alex->y.fixed = 0;
1129 actor = Object_GetById(ACTOR_FELIX);
1130 actor->linkedObject = leader;
1131 actor->steeringFlags |= 1;
1134}
1135
1136/// Searching the Mars Star's pedestal: Isaac takes the last star and the room
1137/// begins to shake.
1138static void Event_TakeMarsStar(void) {
1139 u8 pass;
1140 s32 itemOwner;
1141 struct FieldActor *leader;
1142
1145 for (pass = 0; pass != 6; pass++) {
1146 ColorBuffer_ApplyTarget(0x4039d2, 1);
1152 if (pass == 1) {
1154 }
1155 }
1157 Map_SetShake(-1, -1, 9 * Q16_ONE / 10);
1158 Map_CopyCellsTo(0, 40, 13, 46, 3, 3);
1159 Engine_EventWait(20);
1160 itemOwner = SolSanctumElementalStarRoom_PresentStar(222, PIXELS(232),
1161 PIXELS(16), PIXELS(144));
1162 Engine_EventWait(40);
1163 UiWork_PushValueSlot(itemOwner, 1);
1164 Engine_MessageShowCentered(MsgSolSanctumMarsStarBagged, 1);
1165 Actor_SetPosition(JENNA, PIXELS(307), PIXELS(277));
1172 Engine_EventWait(10);
1174 if (leader != NULL) {
1175 Actor_SetPosition(GARET, leader->x.fixed, leader->z.fixed);
1176 }
1177 Actor_SetSpeed(GARET, PIXELS(6) / 5, PIXELS(3) / 5);
1178 Actor_WalkToAndWait(GARET, 218, 172);
1180 Engine_EventWait(20);
1183 Engine_EventWait(20);
1185 Engine_EventWait(40);
1199 Engine_EventWait(30);
1201 Engine_ActorJump(GARET, 2, 20);
1203 Engine_ActorJump(GARET, 6, 40);
1208}
1209
1210/// Talking to Kraden: about the stars still to bag, or the hostages.
1211static void Event_TalkToKraden(void) {
1214 Engine_EventSetMessage(MsgSolSanctumKradenIAmResponsible);
1216 } else {
1218 Engine_EventSetMessage(MsgSolSanctumKradenBringTheStarsHere);
1219 else
1220 Engine_EventSetMessage(MsgSolSanctumKradenFetchTheOthers);
1222 Engine_EventWait(10);
1224 }
1226}
1227
1228/// Talking to Jenna, or reading her mind: about the stars, or Felix alive.
1229static void Event_TalkToJenna(void) {
1232 Engine_EventSetMessage(MsgSolSanctumJennaMyBrotherIsAlive);
1234 } else {
1236 Engine_EventSetMessage(MsgSolSanctumJennaBeCareful);
1237 else
1238 Engine_EventSetMessage(MsgSolSanctumJennaKradenIsGiddy);
1240 Engine_EventWait(10);
1242 }
1244}
1245
1246/// Talking to Saturos: he demands the last star.
1247static void Event_TalkToSaturos(void) {
1249 Engine_EventSetMessage(MsgSolSanctumSaturosBringTheFinalStar);
1252}
1253
1254/// Talking to Menardi, or reading her mind: she demands the last one.
1255static void Event_TalkToMenardi(void) {
1257 Engine_EventSetMessage(MsgSolSanctumMenardiBringTheFinalGem);
1260}
1261
1262/// Talking to Felix: he says nothing. "..."
1263static void Event_TalkToFelix(void) {
1265 Engine_EventSetMessage(MsgSolSanctumFelixSilence);
1268}
1269
1270/// Talking to Alex: only one star is left.
1271static void Event_TalkToAlex(void) {
1273 Engine_EventSetMessage(MsgSolSanctumAlexOnlyOneLeft);
1276}
1277
1278/// Heading out before the stars are bagged: the party is called back.
1279/// "There aren't any Elemental Stars out there!"
1282 Engine_EventSetMessage(MsgSolSanctumNoStarsOutThere);
1285}
1286
1287/// Walking into trigger 10 or 11: the way ahead is checked as on any field.
1289
1290/// Shows a pedestal while Kraden describes it, then returns to the party.
1291static inline void
1293 s32 actorZ, s32 speaker) {
1294 Camera_MoveTo(cameraX, -1, cameraZ, 1);
1296 Actor_SetPosition(ACTOR_KRADEN, actorX << 16, actorZ << 16);
1297 Engine_EventWait(40);
1298 Event_ShowMessage(speaker, 0);
1300 Engine_EventWait(80);
1301 Camera_MoveTo(PIXELS(471), -1, PIXELS(370), 1);
1303}
1304
1305/// Introduces the room, explains the Elemental Stars, and gives out mythril
1306/// bags.
1308 u16 i;
1309 u8 *leaderMotion;
1310 u8 *kradenMotion;
1311 u8 *leaderSprite;
1312 u8 *kradenSprite;
1313 struct FieldActor *rising;
1314 struct FieldActor *glow;
1315 struct FieldActor *leader;
1316 u8 *kradenSteeringFlags;
1317 s32 kradenSpeaker;
1318 s32 height;
1319 s32 kradenMessageSpeaker;
1320 s32 zero;
1321
1323 Map_CopyCellAttributes(27, 16, 5, 1, 27, 17);
1324 Camera_MoveTo(PIXELS(471), -1, PIXELS(261), 0);
1327 // Materialize Isaac above the arrival platform with the expanding glow.
1329 glow->scaleX = Q16_ONE / 10;
1330 glow->scaleY = Q16_ONE / 10;
1331 rising = Actor_Get(ACTOR_PARTY_LEADER);
1332 leaderSprite = &rising->sprite->flags;
1333 *leaderSprite = 0;
1334 rising->scaleX = Q16_ONE / 10;
1335 rising->scaleY = Q16_ONE / 10;
1338 leaderMotion = &rising->motionFlags;
1339 *leaderMotion = 0;
1340 rising->y.fixed = PIXELS(40);
1345 Engine_EventWait(20);
1349 for (i = 0; i != 90; i++) {
1350 rising->y.fixed += -PIXELS(1) / 10;
1351 rising->scaleX += Q16_ONE / 100;
1352 rising->scaleY += Q16_ONE / 100;
1353 glow->scaleX += Q16_ONE / 100;
1354 glow->scaleY += Q16_ONE / 100;
1356 }
1357 *leaderMotion = 5;
1358 Engine_EventWait(80);
1359 Camera_SetSpeed(PIXELS(3) / 10, PIXELS(3) / 80);
1360 Camera_MoveTo(PIXELS(471), -1, PIXELS(290), 1);
1361 for (i = 0; i != 60; i++) {
1362 rising->y.fixed += -PIXELS(1) / 2;
1364 }
1365 *leaderMotion = 3;
1366 Engine_EventWait(20);
1368 {
1369 struct FieldActor *actor = Actor_Get(ACTOR_PARTY_LEADER);
1370 s32 flags = 1 | actor->priorityFlags;
1371 actor->priorityFlags = flags;
1372 }
1373 // Finish Isaac's arrival and let the companions inspect the room.
1375 {
1376 s32 shown = 1;
1377
1378 *leaderSprite = shown;
1379 }
1382 Engine_EventWait(20);
1386 Engine_EventWait(20);
1388 Engine_EventWait(20);
1389 zero = 0;
1390 leader = Actor_Get(ACTOR_PARTY_LEADER);
1391 if (leader != NULL) {
1392 Actor_SetPosition(JENNA, leader->x.fixed, leader->z.fixed);
1393 }
1394 leader = Actor_Get(ACTOR_PARTY_LEADER);
1395 if (leader != NULL) {
1396 Actor_SetPosition(GARET, leader->x.fixed, leader->z.fixed);
1397 }
1398 Actor_SetSpeed(GARET, PIXELS(1) / 2, PIXELS(1) / 4);
1399 Actor_SetSpeed(JENNA, PIXELS(1) / 2, PIXELS(1) / 4);
1400 Actor_WalkTo(JENNA, 453, 302);
1401 Actor_WalkToAndWait(GARET, 489, 302);
1409 Engine_ActorJump(JENNA, 2, 0);
1410 Engine_ActorJump(GARET, 2, 40);
1414 Engine_EventWait(40);
1418 Engine_EventWait(60);
1420 Actor_SetSpeed(JENNA, PIXELS(6) / 5, PIXELS(3) / 5);
1421 Actor_SetSpeed(GARET, PIXELS(6) / 5, PIXELS(3) / 5);
1423 Actor_WalkTo(JENNA, 431, 338);
1424 Actor_WalkTo(GARET, 511, 338);
1432 Actor_SetSpeed(JENNA, PIXELS(3) / 10, PIXELS(3) / 20);
1433 Actor_SetSpeed(GARET, PIXELS(3) / 10, PIXELS(3) / 20);
1445 Engine_EventWait(20);
1447 Engine_EventWait(20);
1451 Engine_EventWait(20);
1456 // Materialize Kraden after the companions have explored the chamber.
1457 rising = Actor_Get(ACTOR_KRADEN);
1458 kradenSprite = &rising->sprite->flags;
1459 *kradenSprite = zero;
1460 rising->scaleX = Q16_ONE / 10;
1461 rising->scaleY = Q16_ONE / 10;
1462 glow->scaleX = Q16_ONE / 10;
1463 glow->scaleY = Q16_ONE / 10;
1466 kradenMotion = &rising->motionFlags;
1467 *kradenMotion = zero;
1468 rising->y.fixed = PIXELS(40);
1470 Engine_EventSetMessage(MsgSolSanctumKradenWhereAreWe);
1473 Engine_ActorJump(JENNA, 4, 0);
1474 Engine_ActorJump(GARET, 4, 40);
1478 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
1479 Camera_MoveTo(PIXELS(471), -1, PIXELS(309), 1);
1484 for (i = 0; i != 90; i++) {
1485 rising->y.fixed += -PIXELS(1) / 10;
1486 rising->scaleX += Q16_ONE / 100;
1487 rising->scaleY += Q16_ONE / 100;
1488 glow->scaleX += Q16_ONE / 100;
1489 glow->scaleY += Q16_ONE / 100;
1491 }
1492 *kradenMotion = 5;
1493 Engine_EventWait(80);
1494 for (i = 0; i != 60; i++) {
1495 rising->y.fixed += -PIXELS(1) / 2;
1497 }
1498 *kradenMotion = 3;
1499 Engine_EventWait(30);
1501 {
1502 struct FieldActor *actor = Actor_Get(ACTOR_KRADEN);
1503 s32 flags = 1 | actor->priorityFlags;
1504 actor->priorityFlags = flags;
1505 }
1507 {
1508 s32 shown = 1;
1509
1510 *kradenSprite = shown;
1511 }
1513 Engine_EventWait(30);
1514 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(6) / 5, PIXELS(3) / 5);
1516 Engine_EventWait(20);
1520 Engine_EventWait(30);
1523 Engine_EventWait(20);
1526 Engine_EventWait(20);
1529 Engine_EventWait(30);
1531 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(12) / 5, PIXELS(6) / 5);
1538 Engine_EventWait(30);
1540 Engine_EventWait(40);
1547 Engine_EventWait(30);
1548 kradenSpeaker = 0x4009;
1550 Engine_EventWait(40);
1553 Engine_EventWait(40);
1569 Engine_EventWait(20);
1571 Engine_EventWait(40);
1572 Camera_SetSpeed(PIXELS(1) / 2, PIXELS(1) / 16);
1573 Camera_MoveTo(PIXELS(533), -1, PIXELS(339), 1);
1574 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(1) / 2, PIXELS(1) / 4);
1584 Engine_EventWait(30);
1586 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(8) / 5, PIXELS(4) / 5);
1587 Actor_WalkTo(ACTOR_KRADEN, 455, 360);
1588 Engine_EventWait(20);
1593 Engine_EventWait(20);
1596 Engine_EventWait(30);
1598 Engine_EventWait(20);
1602 Engine_EventWait(30);
1605 Engine_EventWait(20);
1607 Actor_SetSpeed(JENNA, PIXELS(4) / 5, PIXELS(2) / 5);
1608 Actor_WalkToAndWait(JENNA, 440, 346);
1609 Engine_EventWait(10);
1612 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
1613 Actor_WalkToAndWait(GARET, 495, 346);
1615 Engine_EventWait(10);
1620 if (Engine_EventChooseYesNo(0, 0) == 1) {
1622 }
1625 // Kraden explains the elements and the stars at the room's four corners.
1626 Engine_EventSetMessage(MsgSolSanctumKradenTheElementsAreThe);
1636 Engine_EventWait(40);
1642 Engine_EventWait(10);
1651 // Tour the four pedestals, returning the view to the party after each.
1653 0x1009);
1654 Engine_EventWait(10);
1656 Engine_EventWait(10);
1662 0x1009);
1663 Engine_EventWait(10);
1665 Engine_EventWait(10);
1675 0x2009);
1676 Engine_EventWait(10);
1678 Engine_EventWait(10);
1688 0x2009);
1689 Engine_EventWait(30);
1711 if (Engine_EventChooseYesNo(0, 0) == 1) {
1713 }
1714 Engine_EventWait(20);
1717 // Discuss the Wisdom Stone and the power stored in the Elemental Stars.
1718 Engine_EventSetMessage(MsgSolSanctumKradenTheWisdomStone);
1727 Engine_EventWait(40);
1736 if (Engine_EventChooseYesNo(0, 0) == 1) {
1738 }
1740 Engine_EventWait(20);
1745 Engine_EventSetMessage(MsgSolSanctumTheStarsHaveEnormousPower);
1756 Engine_EventWait(40);
1765 Engine_ActorJump(GARET, 4, 40);
1768 Engine_EventWait(40);
1776 Engine_EventWait(20);
1781 Engine_EventWait(20);
1788 Engine_EventWait(80);
1790 Engine_EventWait(20);
1793 rising = Actor_Get(ACTOR_KRADEN);
1794 // Kraden demonstrates reaching the platforms, then asks the party to help.
1795 height = 192;
1796 Engine_TaskWait(6);
1797 rising->speed = PIXELS(3);
1798 rising->acceleration = PIXELS(2);
1800 rising->velocityY = (height << 11);
1802 Engine_TaskWait(6);
1803 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(3) / 10, PIXELS(3) / 20);
1804 kradenSteeringFlags = &rising->steeringFlags;
1805 *kradenSteeringFlags &= ~ACTOR_FACES_MOTION;
1815 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(4) / 5, PIXELS(2) / 5);
1817 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(3) / 10, PIXELS(3) / 20);
1818 *kradenSteeringFlags &= ~ACTOR_FACES_MOTION;
1830 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(1) / 5, PIXELS(1) / 10);
1833 Engine_EventWait(30);
1834 {
1835 s32 flags = 1 | *kradenSteeringFlags;
1836 *kradenSteeringFlags = flags;
1837 }
1839 Engine_TaskWait(6);
1840 rising->speed = PIXELS(3);
1841 rising->acceleration = PIXELS(2);
1843 rising->velocityY = (height << 11);
1845 Engine_TaskWait(6);
1846 Engine_EventWait(40);
1863 Engine_ActorJump(GARET, 4, 0);
1868 Engine_EventWait(40);
1872 Engine_EventWait(30);
1875 Engine_EventWait(20);
1882 Engine_EventWait(20);
1884 Engine_EventWait(20);
1888 // Jenna keeps asking until Isaac agrees to collect the stars.
1889 while (Engine_EventChooseYesNo(0, 0) != 0) {
1890 Engine_EventSetMessage(MsgSolSanctumJennaWontYouPlease);
1892 Engine_ActorJump(JENNA, 4, 60);
1894 }
1895 Engine_EventSetMessage(MsgSolSanctumJennaThankYou);
1896 Engine_EventWait(20);
1898 Engine_EventWait(20);
1904 Engine_EventWait(20);
1906 Actor_SetSpeed(ACTOR_KRADEN, PIXELS(1) / 5, PIXELS(1) / 10);
1908 Engine_EventWait(20);
1909 kradenMessageSpeaker = 0x8009;
1911 Engine_EventWait(20);
1912 SolSanctumElementalStarRoom_ShowMessageAndWait(kradenMessageSpeaker, 60);
1913 *kradenSteeringFlags &= ~ACTOR_FACES_MOTION;
1915 Engine_EventWait(20);
1917 Engine_EventWait(20);
1918 Engine_EventSetMessage(MsgSolSanctumTheBagsAreFromKradens);
1922 Engine_EventWait(20);
1927 SolSanctumElementalStarRoom_ShowMessageAndWait(kradenMessageSpeaker, 20);
1933 SolSanctumElementalStarRoom_ShowMessageAndWait(kradenMessageSpeaker, 10);
1937 Engine_EventWait(10);
1938 SolSanctumElementalStarRoom_ShowMessageAndWait(kradenMessageSpeaker, 30);
1941 Engine_EventWait(20);
1945 Engine_EventWait(30);
1947 Engine_EventWait(10);
1948 Actor_SetSpeed(GARET, PIXELS(1), PIXELS(1) / 2);
1951 if (leader != NULL) {
1952 Actor_SetDestination(GARET, leader->x.part.pixel, leader->z.part.pixel);
1953 }
1955 Actor_SetPosition(GARET, 0, 0);
1958 // Give out the bags and make the pedestal crossings available.
1960 Map_CopyCellAttributes(8, 0, 5, 1, 27, 17);
1964}
1965
1966/// Restores pedestal state and runs the first-arrival scene when needed.
1968 s32 ringActor;
1969
1971 // Retreat does not work here (flag 0x144).
1973 ringActor = 15;
1974 do {
1975 Object_GetById(ringActor)->collisionFlags = 0;
1976 Engine_ActorSetSpritePriority(ringActor++, 1);
1977 } while ((u32)ringActor <= 24);
1981 Actor_SetPosition(JENNA, PIXELS(440), PIXELS(346));
1982 }
1984 Map_CopyCellsTo(0, 40, 43, 66, 3, 3);
1985 Map_CopyCellsTo(83, 40, 96, 29, 3, 4);
1986 Map_CopyCellAttributes(0, 0, 1, 1, 41, 29);
1987 Map_CopyCellsTo(87, 42, 41, 31, 1, 2);
1988 Map_CopyCellsTo(83, 40, 74, 29, 3, 4);
1989 Map_CopyCellAttributes(0, 0, 1, 1, 19, 29);
1990 Map_CopyCellsTo(87, 42, 19, 31, 1, 2);
1991 Map_CopyCellsTo(83, 40, 96, 10, 3, 4);
1992 Map_CopyCellAttributes(0, 0, 1, 1, 41, 10);
1993 Map_CopyCellsTo(87, 42, 41, 12, 1, 2);
1994 }
1996 Map_CopyCellsTo(0, 40, 43, 46, 3, 3);
1997 Map_CopyCellsTo(83, 40, 84, 4, 3, 4);
1998 Map_CopyCellAttributes(0, 0, 1, 1, 29, 4);
1999 Map_CopyCellsTo(87, 42, 29, 6, 1, 2);
2000 Map_CopyCellsTo(83, 40, 76, 21, 3, 4);
2001 Map_CopyCellAttributes(0, 0, 1, 1, 21, 21);
2002 Map_CopyCellsTo(87, 42, 21, 23, 1, 2);
2003 Map_CopyCellsTo(83, 40, 76, 29, 3, 4);
2004 Map_CopyCellAttributes(0, 0, 1, 1, 21, 29);
2005 Map_CopyCellsTo(87, 42, 21, 31, 1, 2);
2006 }
2008 Map_CopyCellsTo(0, 40, 13, 66, 3, 3);
2009 Map_CopyCellsTo(83, 40, 65, 31, 3, 4);
2010 Map_CopyCellAttributes(0, 0, 1, 1, 10, 31);
2011 Map_CopyCellsTo(87, 42, 10, 33, 1, 2);
2012 Map_CopyCellsTo(83, 40, 79, 9, 3, 4);
2013 Map_CopyCellAttributes(0, 0, 1, 1, 24, 9);
2014 Map_CopyCellsTo(87, 42, 24, 11, 1, 2);
2015 Map_CopyCellsTo(83, 40, 91, 10, 3, 4);
2016 Map_CopyCellAttributes(0, 0, 1, 1, 36, 10);
2017 Map_CopyCellsTo(87, 42, 36, 12, 1, 2);
2019 }
2021 if (gGameState.entrance == 10) {
2023 }
2024 }
2025 return 0;
2026}
2027
2029 s32 frames) {
2030 Engine_EventShowMessage(speaker, 0);
2031 Engine_EventWait(frames);
2032}
2033
2034/// Animates a star's icon and replaces its owner's mythril bag with the star.
2036 s32 z) {
2037 GlyphTransfer *glyph;
2038 struct FieldActor *actor;
2039 struct AnimationObject *sprite;
2040 s32 owner;
2041 s32 slot;
2042
2043 glyph = NULL;
2044 actor = Engine_ObjectCreate(22, x, y, z);
2047 if (actor == NULL)
2048 return owner;
2050 sprite = actor->sprite;
2051 sprite->flags = 0;
2052 sprite->count = 0;
2053 sprite->image.fullColor = 0;
2054 sprite->image.palette = 0;
2055 actor->velocityY = PIXELS(5) / 2;
2056 actor->gravity = PIXELS(1) / 4;
2057 glyph = Engine_HeapAllocate(17, sizeof(*glyph));
2058 Engine_ItemLoadIcon(item);
2059 Engine_VramLoad(sprite->slot, 128, glyph->tiles);
2063 Inventory_Discard(owner, slot);
2064 Inventory_AddItem(owner, item);
2067 return owner;
2068}
2069
2070/// Makes inventory room and gives the party four bags, preserving the dialogue.
2072 struct EventWork *work = gEventWork;
2073 s16 savedMessage = work->message;
2074 s32 itemSlot;
2075 s32 itemOwner;
2076 s32 freeSlots;
2077
2080 Engine_MessageShowCentered(MsgSolSanctumGotFourMythrilBags, 1);
2081 do {
2082 freeSlots = 30 - Inventory_Count(0);
2083 freeSlots -= Inventory_Count(1);
2084
2085 if (freeSlots <= 3) {
2086 Engine_MessageShowCentered(MsgSolSanctumTooManyItems, 1);
2087 if (Shop_PickUnitItem(&itemOwner, &itemSlot) != -1)
2088 Inventory_Discard(itemOwner, itemSlot);
2089 }
2090 } while (freeSlots <= 3);
2095 work->message = savedMessage;
2096}
2097
2098/// Emits sparks while Alex disappears and reappears.
2100 struct EffectOptions options;
2101 struct EffectOptions *effectOptions;
2102 struct FieldActor *alex;
2103 u32 frame;
2104 s32 x;
2105 s32 xOffset;
2106
2107 alex = Object_GetById(ACTOR_ALEX);
2110 effectOptions = &options;
2111 effectOptions->priority = 1;
2112 effectOptions->palette = 5;
2113 effectOptions->type = 0x11c;
2114 effectOptions->startScaleX = 2 * Q16_ONE / 5;
2115 effectOptions->startScaleY = 3 * Q16_ONE;
2116 for (frame = 0; frame <= 31; frame++) {
2118 if (!(frame & 1)) {
2119 xOffset = (((u32)Engine_RandomNext() * 24) >> 16) << 16;
2120 x = alex->x.fixed;
2121 x += xOffset;
2122 x += -PIXELS(12);
2123 Effect_Spawn(x,
2124 alex->y.fixed +
2125 ((((u32)Engine_RandomNext() << 5) >> 16) << 16) +
2126 PIXELS(32),
2127 alex->z.fixed, 0, -PIXELS(4), 0,
2130 effectOptions);
2131 }
2132 if (frame == 20)
2134 }
2137}
2138
2140
2142 SC_WAIT(1), SC_LOOP(22, SC_TOP), SC_WAIT(1),
2143 SC_POS(0, 0, 0), SC_WAIT(1), SC_FREE,
2144};
2145
2147 SC_WAIT(1), SC_LOOP(44, SC_TOP), SC_WAIT(1),
2148 SC_POS(0, 0, 0), SC_WAIT(1), SC_FREE,
2149};
2150
2152 SC_WAIT(1), SC_LOOP(126, SC_TOP), SC_WAIT(1),
2153 SC_POS(0, 0, 0), SC_WAIT(1), SC_FREE,
2154};
2155
2160};
2161
2163 SC_CALL(Scene_TurnTowardTarget),
2165};
2166
2170 SC_WAIT(2),
2171 SC_SET(SW_SCALE_X, 3 * Q16_ONE / 4),
2172 SC_SET(SW_SCALE_Y, 3 * Q16_ONE / 4),
2173 SC_WAIT(2),
2174 SC_SET(SW_SCALE_X, 7 * Q16_ONE / 8),
2175 SC_SET(SW_SCALE_Y, 7 * Q16_ONE / 8),
2176 SC_WAIT(2),
2177 SC_SET(SW_SCALE_X, 15 * Q16_ONE / 16),
2178 SC_SET(SW_SCALE_Y, 15 * Q16_ONE / 16),
2179 SC_WAIT(2),
2182 SC_WAIT(16),
2183 SC_SET(SW_SCALE_X, 11 * Q16_ONE / 8),
2184 SC_SET(SW_SCALE_Y, 11 * Q16_ONE / 8),
2185 SC_WAIT(2),
2186 SC_SET(SW_SCALE_X, 3 * Q16_ONE / 2),
2187 SC_SET(SW_SCALE_Y, 3 * Q16_ONE / 2),
2188 SC_WAIT(2),
2189 SC_SET(SW_SCALE_X, 9 * Q16_ONE / 8),
2190 SC_SET(SW_SCALE_Y, 9 * Q16_ONE / 8),
2191 SC_WAIT(2),
2194 SC_WAIT(2),
2195 SC_SET(SW_SCALE_X, 11 * Q16_ONE / 8),
2196 SC_SET(SW_SCALE_Y, 11 * Q16_ONE / 8),
2197 SC_WAIT(2),
2198 SC_SET(SW_SCALE_X, 3 * Q16_ONE / 2),
2199 SC_SET(SW_SCALE_Y, 3 * Q16_ONE / 2),
2200 SC_WAIT(2),
2201 SC_SET(SW_SCALE_X, 9 * Q16_ONE / 8),
2202 SC_SET(SW_SCALE_Y, 9 * Q16_ONE / 8),
2203 SC_WAIT(2),
2206 SC_WAIT(2),
2207 SC_END,
2208};
2209
2211 {0, CONDITION_ALWAYS, 472, 0, 322, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2213};
2214
2216 SCENE_EXITS(17),
2217 SCENE_EXIT(2, 18, 10),
2219};
2220
2221// clang-format off
2224 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2226 0, 0, 0, FACING_SOUTH, 3, 0 },
2228 0, 0, 0, FACING_EAST, TALK_FACE_PARTY, 0 },
2230 0, 0, 0, FACING_SOUTH, 3, 0 },
2232 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2234 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2236 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2238 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2240 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2241 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2242 PIXELS(617), 0, PIXELS(408), FACING_EAST, TALK_FACE_PARTY, 0 },
2243 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2244 PIXELS(429), 0, PIXELS(221), FACING_EAST, TALK_FACE_PARTY, 0 },
2245 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2246 PIXELS(696), 0, PIXELS(113), FACING_EAST, TALK_FACE_PARTY, 0 },
2247 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2248 PIXELS(170), 0, PIXELS(168), FACING_EAST, TALK_FACE_PARTY, 0 },
2249 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2250 PIXELS(308), 0, PIXELS(511), FACING_EAST, TALK_FACE_PARTY, 0 },
2251 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2252 PIXELS(397), 0, PIXELS(418), FACING_EAST, TALK_FACE_PARTY, 0 },
2253 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2254 PIXELS(542), 0, PIXELS(269), FACING_EAST, TALK_FACE_PARTY, 0 },
2255 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2256 PIXELS(421), 0, PIXELS(117), FACING_EAST, TALK_FACE_PARTY, 0 },
2257 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2258 PIXELS(295), 0, PIXELS(210), FACING_EAST, TALK_FACE_PARTY, 0 },
2259 { 0x11f, CONDITION_ALWAYS, ACTOR_STAND,
2260 PIXELS(742), 0, PIXELS(310), FACING_EAST, TALK_FACE_PARTY, 0 },
2261 { SCENE_TABLE_END },
2262};
2263
2271 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgSolSanctumKradenIAmResponsible) },
2273 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgSolSanctumSaturosBringTheFinalStar) },
2275 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, CONDITION_ALWAYS, MSGNO(MsgSolSanctumAlexOnlyOneLeft) },
2283 { SCENE_EVENTS_END },
2284};
2285
2287 MAP_CELL_STEP(59, 40, 3, 4, 6), MAP_CELL_STEP(62, 40, 3, 4, 6), MAP_CELL_STEP(65, 40, 3, 4, 6), MAP_CELL_STEP(68, 40, 3, 4, 6), MAP_CELL_STEP(71, 40, 3, 4, 6), MAP_CELL_STEP(74, 40, 3, 4, 6), MAP_CELL_STEP(77, 40, 3, 4, 6), MAP_CELL_STEP(80, 40, 3, 4, 6), MAP_CELL_STEP(83, 40, 3, 4, 0), MAP_CELL_STEPS_END,
2288};
2289
2291 { 4, 4, 4 },
2292 { 4, 0, 3 },
2293 { 4, 0, 4 },
2294 { 4, 0, 4 },
2295 { 3, 0, 4 },
2296 { 4, 6, 4 },
2297 { 6, 0, 4 },
2298 { 4, 0, 3 },
2299 { 2, 0, 1 },
2300 { 2, 0, 2 },
2301};
2302
2304 { 1, 1, 2 },
2305 { 1, 0, 2 },
2306 { 1, 0, 2 },
2307 { 1, 0, 1 },
2308 { 1, 0, 2 },
2309 { 1, 1, 2 },
2310 { 1, 0, 2 },
2311 { 1, 0, 2 },
2312 { 1, 0, 2 },
2313 { 1, 0, 2 },
2314};
2315
2317 { 1, 1, 1 },
2318 { 1, 0, 1 },
2319 { 1, 0, 1 },
2320 { -1, 0, 1 },
2321 { -1, 0, -1 },
2322 { 1, 1, 1 },
2323 { -1, 0, -1 },
2324 { -1, 0, -1 },
2325 { -1, 0, -1 },
2326 { -1, 0, -1 },
2327};
2328
2330 0x9999, 0xcccc, 0xb333, 0x9999, 0xcccc, 0x9999, 0xb333, 0x9999,
2331 0x9999, 0xb333,
2332};
2333
2335 655, 458, 655, 458, 655, 458, 655, 655,
2336 524, 655,
2337};
2338// clang-format on
Ability numbers, named from the English release.
@ ABILITY_MIND_READ
Definition ability_ids.h:16
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
s32 gEffectScript0[]
const s32 * gEffectScripts[]
s32 gEffectScript1[]
s32 gEffectScript2[]
BattleUnit, a party member's or enemy's battle state, with the elements, abilities and actions it use...
static void Event_CheckAhead(void)
Checks the blocked direction before allowing another movement step.
Definition bilibin.c:331
Calls through a function pointer, by argument count.
#define GARET
Jerald.
#define JENNA
Jasmine.
The engine calls a scene uses to create an overlay object and set its sprite flags.
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.
FacingObject, the view of an object that turns to face a target.
@ EFFECT_USE_PALETTE
options.palette, as its group child value
@ EFFECT_USE_START_SCALE
options.startScaleX and startScaleY
@ EFFECT_USE_TYPE
options.type, else object type 222
@ EFFECT_USE_PRIORITY
options.priority, as the sprite's priority
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
#define SPEAKER_PORTRAIT_LEFT
Definition field_event.h:54
static s32 Event_OpenMessage(s32 speaker, s32 flags)
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_WorkSetValuesIfNonNegative(s32 first, s32 second, s32 third)
#define SPEAKER_WINDOW_ABOVE
Definition field_event.h:56
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
static void Actor_SetBuiltinAction(s32 actor, s32 action)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
#define GameFlag_IsSet
#define SPEAKER_PORTRAIT_RIGHT
Definition field_event.h:55
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)
void Engine_ItemLoadIcon(s32 item)
#define EMOTE_IN_FRONT
Definition field_event.h:49
static void Actor_MoveToAndWait(s32 actor, s32 x, s32 z)
#define MAP_CELL_STEP(srcX, srcY, width, height, frames)
Definition field_event.h:59
void Engine_ItemShowFound(s32 item, s32 height)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_EventCloseScreen(void)
void Engine_ObjectDispatchRelease(struct FieldActor *object)
static void Map_CopyCellsTo(s32 srcX, s32 srcY, s32 destX, s32 destY, s32 width, s32 height)
static void Actor_FaceActor(s32 actor, s32 target, s32 frames)
#define SPEAKER_WINDOW_BELOW
Definition field_event.h:57
void Engine_HeapRelease(s32 slot)
static void ColorBuffer_ApplyTarget(s32 value, s32 mode)
s32 Engine_VramLoad(s32 block, s32 size, const void *data)
static void Actor_WalkTo(s32 actor, s32 x, s32 z)
#define GameFlag_Clear
void Engine_EventWaitForScreen(void)
#define GameFlag_Set
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
void Engine_ObjectSetScript(struct FieldActor *object, const s32 *script)
void Engine_EventOpenScreen(void)
s32 Engine_EventOpenMessage(s32 speaker, s32 flags)
void Engine_GameFlagSet(s32 flag)
void Engine_MapRenderWaitForValues(void)
void Engine_CameraWaitForMove(void)
void Engine_ActorWaitForMove(s32 actor)
void Engine_CameraFollowActor(s32 actor, s32 keep_position)
void * Engine_HeapAllocate(s32 slot, s32 size)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorStop(s32 actor)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
static void Event_ShowMessage(s32 speaker, s32 flags)
void Engine_ActorSetAttachedEffect(s32 actor, s32 effect)
s32 Engine_RandomNext()
static void Event_PlayCue(s32 cue)
void Engine_ActorSetChildValue(s32 actor, s32 value)
static void Map_SetShake(s32 horizontal, s32 vertical, s32 decay)
Sets shake amplitudes in fixed-point pixels and the per-frame decay factor.
#define MAP_CELL_STEPS_END
Definition field_event.h:61
static void Actor_SetChildValue(s32 actor, s32 value)
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_MapAnimateCells(const u16 *steps, s32 destX, s32 destY)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
void Engine_RunRisingObjectSequence(struct FieldActor *object, s32 mode)
static s32 Event_AskYesNo(s32 speaker, s32 flags)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_MapRedraw(void)
void Engine_ColorBufferInterpolate(s32 frames)
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 void Actor_SetAttachedEffect(s32 actor, s32 effect)
void Engine_ColorBufferApplyTarget(s32 value, s32 mode)
void Engine_ColorBufferApplySource(s32 value, s32 mode)
static struct FieldActor * Actor_Get(s32 actor)
Field objects and actors, and the scene transition styles.
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ TRANSITION_BACKDROP_FADE
Definition field_obj.h:16
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
Definition field_obj.h:153
@ ACTOR_FOLLOWS_TERRAIN
moves with the ground height under it
Definition field_obj.h:160
@ ACTOR_FALLS
falls by its gravity and bounces
Definition field_obj.h:161
#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_TALK
@ FACING_STEP
Definition field_scene.h:36
#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 SEARCH(target)
#define SCENE_EXITS_END
Definition field_scene.h:77
#define TOUCH_WALKING_INTO(facing)
@ FACING_NORTHEAST
Definition field_scene.h:33
@ FACING_EAST
Definition field_scene.h:26
@ FACING_SOUTHEAST
Definition field_scene.h:27
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_SOUTHWEST
Definition field_scene.h:29
@ FACING_NORTHWEST
Definition field_scene.h:31
@ FACING_SOUTH
Definition field_scene.h:28
@ FACING_WEST
Definition field_scene.h:30
#define PIXELS(value)
@ SEARCH_UNNAMED
The scene service layer: one typed inline for each engine service a scene calls by its own name,...
static void FieldObject_SetPosition(struct FieldActor *object, s32 fixed_x, s32 fixed_y, s32 fixed_z)
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_SHOW_LOCATION_NAME
Definition flags.h:94
#define FLAG_SOL_SANCTUM_MERCURY_STAR_BAGGED
Definition flags.h:679
#define FLAG_RETREAT_BLOCKED
Retreat is blocked, from Psynergy or an item.
Definition flags.h:55
#define FLAG_SOL_SANCTUM_STAR_ROOM_COLLAPSED
Definition flags.h:682
#define FLAG_SOL_SANCTUM_VENUS_STAR_BAGGED
Definition flags.h:678
#define FLAG_SOL_SANCTUM_STARS_GIVEN_TO_ALEX
The Jupiter Star is bagged and Alex holds the four Elemental Stars.
Definition flags.h:681
#define FLAG_SOL_SANCTUM_STAR_ROOM_EXPLAINED
Definition flags.h:677
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
Font glyphs and their palettes.
The screen blend's globals and the graphics routines.
The main-image routines scene overlays import.
s32 PartyInventory_Discard(s32 itemId)
Discards one itemId from whoever carries it first, as Inventory_Discard does; always returns 0.
Definition inventory.c:422
s32 Inventory_AddItem(s32 owner, s32 itemId)
Gives a unit one item, joining its first matching stack (up to 30) or taking the first free slot.
Definition inventory.c:144
s32 Inventory_Count(s32 owner)
Counts filled inventory slots up to the first empty slot; the inventory is kept closed up,...
Definition inventory.c:82
s32 Inventory_Discard(s32 owner, s32 slot)
Removes one item as Inventory_Remove does, and puts a rare item back into circulation (its counter go...
Definition inventory.c:375
s32 Inventory_Find(s32 owner, s32 itemId)
Returns the first slot holding itemId (any quantity, equipped or not), or -1.
Definition inventory.c:212
s32 PartyInventory_FindOwner(s32 itemId)
Returns who carries itemId, asking the selected character first, or -1.
Definition inventory.c:229
s32 PartyInventory_Add(s32 itemId)
Gives the item to the first party member with room.
Definition inventory.c:189
Item numbers, named from the English release.
@ ITEM_MYTHRIL_BAG
Definition item_ids.h:65
s32 Shop_PickUnitItem(s32 *selectedUnit, s32 *selectedSlot)
Lets the player choose a party member, then one of its items that may be dropped.
Definition item_picker.c:14
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
#define SC_SET(w, v)
Write a work value.
Definition objcmd.h:37
#define SC_LOOP(n, to)
Repeat up to n times.
Definition objcmd.h:28
#define SC_POS(x, y, z)
Set position.
Definition objcmd.h:18
#define SC_FREE
Release.
Definition objcmd.h:43
#define SC_FOREVER
Definition objcmd.h:14
#define SC_WAIT(n)
Wait n frames.
Definition objcmd.h:16
#define SC_TOP
Script start.
Definition objcmd.h:13
#define SC_END
Return to the main script.
Definition objcmd.h:32
@ SW_SCALE_Y
Definition objcmd.h:63
@ SW_SCALE_X
Definition objcmd.h:62
#define SC_CALL(fn)
Definition objcmd.h:50
void Party_RemoveOwnerRestored(s32 unit)
Takes unit out of the party, fully restoring its HP and PP and curing its poison.
Definition events.c:214
void BattlePres_RunActionThenWaitIfModeZero(s32 actor, s32 flags, s32 wait)
The event command "show message and wait": shows the message, then waits wait frames.
Definition messages.c:283
Overlay objects and their records.
Palette fades, the battle effect palette buffers and the colour channel curves.
@ PALETTE_TRANSFORM_PLAIN
each colour unchanged
Definition palbuf.h:72
#define ACTOR_ACTION_IDLE
s8 gSolSanctum_RingDirection[][3]
static void SolSanctumElementalStarRoom_OfferHostageGuarantee(void)
Has the captors offer a guarantee for their hostages' safety.
static void Event_TalkToJenna(void)
Talking to Jenna, or reading her mind: about the stars, or Felix alive.
static void Event_TakeMarsStar(void)
Searching the Mars Star's pedestal: Isaac takes the last star and the room begins to shake.
static void Event_BagJupiterStarAndMeetSaturos(void)
Searching the Jupiter Star's pedestal: the star is bagged, then Saturos and Menardi appear,...
static void SolSanctumElementalStarRoom_DemandElementalStars(void)
Reveals the masked intruder while the captors demand the stars.
static void SolSanctumElementalStarRoom_AlexTakesStars(void)
Has Alex collect the stars and returns the party to the final pedestal.
static void SolSanctumElementalStarRoom_UnmaskFelix(void)
Reveals Felix's identity and lets Isaac decide how to hand over the stars.
static s32 SolSanctumElementalStarRoom_PresentStar(s32 item, s32 x, s32 y, s32 z)
Animates a star's icon and replaces its owner's mythril bag with the star.
s32 SolSanctumElementalStarRoom_Initialize(void)
Restores pedestal state and runs the first-arrival scene when needed.
struct SceneEntrance gSolSanctumElementalStarRoom_Entrances[]
struct SceneEvent gSolSanctumElementalStarRoom_Events[]
u32 gSolSanctumElementalStarRoom_Exits[]
static void Event_BagMercuryStar(void)
Searching the Mercury Star's pedestal: as the Venus Star.
const struct SceneEntrance * SolSanctumElementalStarRoom_GetEntrances(void)
const u32 * SolSanctumElementalStarRoom_GetExits(void)
s32 gSolSanctumElementalStarRoom_PresentItemScript[]
static void Event_TalkToFelix(void)
Talking to Felix: he says nothing. "...".
static void Event_KradenStopsPartyLeaving(void)
Heading out before the stars are bagged: the party is called back.
static void Event_TalkToAlex(void)
Talking to Alex: only one star is left.
static void Event_TalkToKraden(void)
Talking to Kraden: about the stars still to bag, or the hostages.
const struct SceneRegion * SolSanctumElementalStarRoom_GetRegions(void)
u16 gSolSanctumElementalStarRoom_StarCells[]
static void SolSanctumElementalStarRoom_BagJupiterStar(void)
Reveals the Jupiter crossings and places the star in a mythril bag.
s32 gSolSanctumRing_ScaleSteps[]
const struct ScenePlacement * SolSanctumElementalStarRoom_GetPlacements(void)
s32 gSolSanctumRing_MaxScales[]
static void SolSanctumElementalStarRoom_ShowMessageAndWait(s32 speaker, s32 frames)
s32 gSolSanctumElementalStarRoom_AngleScript[]
static void SolSanctumElementalStarRoom_GiveMythrilBags(void)
Makes inventory room and gives the party four bags, preserving the dialogue.
static __inline__ void SolSanctumElementalStarRoom_SkipMessages(s32 amount)
Advances through the current dialogue's consecutive messages.
static void SolSanctumElementalStarRoom_RevealSaturosAndMenardi(void)
Brings Isaac and Garet back to discover Jenna and Kraden's captors.
static void Event_TalkToSaturos(void)
Talking to Saturos: he demands the last star.
static void Event_BagVenusStar(void)
Searching the Venus Star's pedestal: the room flashes, new crossings open between the pedestals,...
u8 gSolSanctum_RingSwing[][3]
const struct SceneEvent * SolSanctumElementalStarRoom_GetEvents(void)
Returns the star, dialogue, and boundary interactions.
static void SolSanctumElementalStarRoom_EnterStarRoom(void)
Introduces the room, explains the Elemental Stars, and gives out mythril bags.
static void SolSanctumElementalStarRoom_AnimateAlexTeleport(void)
Emits sparks while Alex disappears and reappears.
static void Event_TalkToMenardi(void)
Talking to Menardi, or reading her mind: she demands the last one.
u8 gSolSanctum_RingDrift[][3]
static void SolSanctumElementalStarRoom_LineUpFollowers(void)
Arranges the captors and hostages after the exchange.
struct ScenePlacement gSolSanctumElementalStarRoom_Placements[]
static void SolSanctumElementalStarRoom_ShowPedestal(s32 cameraX, s32 cameraZ, s32 actorX, s32 actorZ, s32 speaker)
Shows a pedestal while Kraden describes it, then returns to the party.
Song and sound effect ids, indices into gSound_SongTable.
#define SE_144
Definition songs.h:137
#define SE_220
Definition songs.h:215
#define MUS_TREASURE_FOUND
Definition songs.h:82
#define MUS_061
Definition songs.h:65
#define MUS_017
Definition songs.h:27
#define SE_190
Definition songs.h:185
#define SE_141
Definition songs.h:134
#define SE_145
Definition songs.h:138
#define SE_161
Definition songs.h:156
#define SE_289
Definition songs.h:282
#define SE_HIGH_JUMP
Definition songs.h:148
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_TaskWait()
void Engine_EventSetMessage()
void Engine_EventShowMessage()
#define NULL
Definition bilibin.h:6
void SolSanctum_StartFloatingLights(s32 first, u32 count)
Starts the floating lights: count actors (at most 10) from first, each drawn translucent and starting...
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationSpritePart image
Definition animspr.h:109
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
u8 slot
VRAM cache entry holding its tiles.
Definition animspr.h:112
u8 count
layers in use, up to the last one present
Definition animspr.h:129
u16 fullColor
256 colours; set for both parts when created
Definition animspr.h:94
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
The options of a spawned field effect, each used when its EFFECT_USE_ flag (or EFFECT_SCALE_TO_TARGET...
s16 type
the object type to create; 222 without the flag
s32 palette
passed to ObjectGroup_SetChildValue
s32 startScaleY
16.16 fixed point, 0x10000 full size
s32 priority
the sprite's priority
s32 startScaleX
16.16 fixed point, 0x10000 full size
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
u16 message
the next message, advanced as each window opens
Definition event_work.h:47
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
struct FieldActor * linkedObject
The object its action script follows or faces.
Definition field_obj.h:114
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
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
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
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
u8 tiles[0x200]
Definition glyph.h:40
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
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 char s8
Definition types.h:10
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
struct BattleUnit * UnitGet(u32 owner)
Returns the unit record of owner: 0 to 7 are the playable characters in the game state,...
Definition units.c:73
void UiWork_PushValueSlot(u32 value, u32 kind)
Adds a message argument of kind (MSG_ARG_) with value to the first free place of the argument table; ...
Definition messages.c:216
void UiText_ShowCenteredMessage(s32 message, s32 mode, s32 yOffset)
Shows a message centred on the screen (yOffset tiles lower) and waits until it is typed out,...
Definition messages.c:325