Alchemy
Loading...
Searching...
No Matches

kalay.c

Go to the documentation of this file.
1/// @file
2/// Kalay, in six maps: the town, the palace gate, the cave by the palace's
3/// secret passage, two more maps and the tunnel with the two blocks. Leaving
4/// town after hearing of the Colosso tour, the party watches the tour group
5/// stop and set off without its missing man.
6
7#include "game_state.h"
8#include "unit/field/field.h"
9#include "engine_call.h"
10#include "scene_ids.h"
11#include "unit/import.h"
12#include "unit/scene/kalay.h"
14#include "unit/object/object.h"
16#include "unit/window/window.h"
19#include "battle.h"
20#include "debug.h"
21#include "field.h"
22#include "game.h"
23#include "graphics.h"
24#include "menu.h"
25#include "minigame.h"
26#include "sound.h"
27#include "system.h"
28#include "types.h"
29#include "edition.h"
30#include "callback_scheduler.h"
31#include "field_event.h"
32#include "field_scene.h"
33#include "resource_3a8_effect.h"
34#include "call.h"
35#include "text/msg_ids.h"
36#include "ability_ids.h"
37#include "item_ids.h"
38#include "objcmd.h"
39#include "script.h"
40#include "macros.h"
41
42#include "field_obj.h"
43#include "object_effect.h"
44#include "orbit.h"
45#include "fixed_math.h"
46#include "field_runtime.h"
47#include "heap_state.h"
48
49#include "flags.h"
50#include "songs.h"
51
53
54/// Kalay's maps share actor numbers; each is named on the map it is proved.
56 // Town
57 ACTOR_LATE_TOURIST = 14, ///< the one the tour guides are missing
59 ACTOR_HEAD_GUIDE = 20, ///< the Colosso tour's guides
65 /// Hammet's palace gate
68 /// The cave by the palace's secret passage
74 // The tunnel
75 ACTOR_FIRST_BLOCK = 8, ///< the blocks that open the two passages
79};
80
81/// The tunnel's own flags, kept while the party is there.
85 /// Each block's particles have started their sound.
90};
91
92static void Kalay_PrepareTown(void);
93static void Kalay_PreparePalaceGate(void);
94static void Kalay_PrepareCave(void);
95static void Kalay_StartWindowTransition(void);
96static void Kalay_PrepareTunnel(void);
97static void Kalay_StartTouristsFidgeting(void);
98static void Kalay_StartTouristFidgeting(s32 actorId);
99static void Kalay_StartGuidesPacing(void);
100static void Kalay_AlternateGuidesPacing(void);
101static void Kalay_IvanMeetsPalaceGuards(void);
102static void Kalay_HammetReturnsToPalace(void);
103static void Kalay_UpdateTunnelPassages(void);
104static void Kalay_UpdateTunnelEmitters(void);
105static void Kalay_SpawnTunnelParticle(s32 x, s32 height, s32 z);
106static void Kalay_UpdateNutOrbit(void);
107
108/// Clears the flag a guide's script sets when it is done.
109static __inline__ void Kalay_ClearScriptDone(struct FieldActor *actor) {
110 s32 completed = 0;
111
112 actor->timer = completed;
113}
114
115/// Talking to the Mars Djinni in the tunnel adds it to the party.
116static void Kalay_RecruitDjinn(void) {
118}
119
120/// While the tour waits, a tourist now and then nods, shakes his head or turns.
122 struct FieldActor *actor = (struct FieldActor *)interpreter;
123 u32 action;
124 u32 nextTimer;
125
126 if ((s16)actor->work == 0) {
127 action = (u32)(Engine_RandomNext() * 8) >> 0x10;
128 switch (action) {
129 case 0:
130 Object_SetMode(actor, 3);
131 break;
132 case 1:
133 Object_SetMode(actor, 4);
134 break;
135 case 3:
136 case 4:
137 actor->facing += (u32)(Engine_RandomNext() << 0xF) >> 0x10;
138 break;
139 }
140 nextTimer = (u32)(Engine_RandomNext() * 0x50) >> 0x10;
141 actor->work = nextTimer;
142 }
143 if ((s16)actor->work != 0) {
144 actor->work = (s16)actor->work - 1;
145 }
146 return 1;
147}
148
149// Shared source, included in link order.
151
153 s16 scene = gGameState.scene;
154
155 if (scene == (s32)&SceneId_Kalay1) {
157 }
158 if (scene == (s32)&SceneId_Kalay2) {
160 }
161 if (scene == (s32)&SceneId_Kalay3) {
163 }
164 if (scene == (s32)&SceneId_Kalay4) {
165 return gKalay_Entrances4;
166 }
167 if (scene == (s32)&SceneId_Kalay5) {
168 return gKalay_Entrances5;
169 }
170 if (scene == (s32)&SceneId_Kalay6) {
172 }
173 return gKalay_NoEntrances;
174}
175
176const struct SceneRegion *Kalay_GetRegions(void) { return NULL; }
177
178/// The numbered exits of all six maps.
179const u32 *Kalay_GetExits(void) { return gKalay_Exits; }
180
181/// The people of the town, palace gate, cave and tunnel.
183 s16 scene = gGameState.scene;
184
185 if (scene == (s32)&SceneId_Kalay1) {
187 }
188 if (scene == (s32)&SceneId_Kalay2) {
190 }
191 if (scene == (s32)&SceneId_Kalay3) {
193 }
194 if (scene == (s32)&SceneId_Kalay6) {
196 }
197 return gKalay_NoPlacements;
198}
199
200/// Searching the town well: the party peers in, and it is very clean.
201static void Kalay_SearchWell(void) {
203 Engine_MessageShowCentered(MsgFieldPeeredWell, 1);
204 Engine_MessageShowCentered(MsgKalayVeryCleanMaintained, 1);
206}
207
208/// Catch pulls in the Nut floating in the cave.
209static void Kalay_CatchCaveNut(void) {
212 Engine_GameFlagSet(0xfd6);
216}
217
218/// The conversations, exits and Psynergy targets of each map.
219const struct SceneEvent *Kalay_GetEvents(void) {
220 s16 scene = gGameState.scene;
221
222 if (scene == (s32)&SceneId_Kalay1) {
223 return gKalay_TownEvents;
224 }
225 if (scene == (s32)&SceneId_Kalay2) {
227 }
228 if (scene == (s32)&SceneId_Kalay3) {
229 return gKalay_CaveEvents;
230 }
231 if (scene == (s32)&SceneId_Kalay4) {
232 return gKalay_Events4;
233 }
234 if (scene == (s32)&SceneId_Kalay5) {
235 return gKalay_Events5;
236 }
237 if (scene == (s32)&SceneId_Kalay6) {
238 return gKalay_TunnelEvents;
239 }
240 return gKalay_NoEvents;
241}
242
243/// A man tells why he moved to Kalay: he left Tolbi, afraid of Babi.
244static void Kalay_TalkAboutLeavingHome(void) {
246 Engine_EventSetMessage(MsgKalayCameKalayBecauseDidntLike);
249}
250
251/// Spoken to from any side but the north, the cave guard asks whether the
252/// party wants to go into the cave, and turns it away either way.
253static void Kalay_AskAboutCaveAccess(void) {
254 struct FieldActor *leader;
255 u32 relativeFacing;
256 u16 *message;
257
259 relativeFacing = (leader->facing + 0xfffff000) << 16;
260 if (relativeFacing > 0x60000000) {
264 Engine_EventSetMessage(MsgKalayDoWantGoCaveUp);
266 if (Engine_EventChooseYesNo(0, 0) == 0) {
269 } else {
270 message = &gEventWork->message;
271 *message = *message + 1;
274 }
276 }
277}
278
279/// In the tunnel, a man asks whether Layana was too hard on the party.
280static void Kalay_TalkAboutLayana(void) {
282 Engine_EventSetMessage(MsgKalayLayanaWasVeryHardOn);
285}
286
287/// Across the counter, the leader facing north, the weapon shop opens; from
288/// elsewhere the merchant grumbles that Hammet sells his best weapons away.
289static void Kalay_TalkToWeaponMerchant(void) {
290 struct FieldActor *leader;
291 u32 relativeFacing;
292
294 relativeFacing = (leader->facing - 0x2000) << 16;
295 if (relativeFacing > 0x80000000) {
297 } else {
299 Engine_EventSetMessage(MsgKalayLordHammetSellsHisBest);
302 }
303}
304
305/// Across the counter, the leader facing west to north, the armor shop opens;
306/// from elsewhere the merchant asks whether the party found its weapons.
307static void Kalay_TalkToArmorMerchant(void) {
308 struct FieldActor *leader;
309 u32 relativeFacing;
310
312 relativeFacing = (leader->facing - 0x6001) << 16;
313 if (relativeFacing <= 0x7ffe0000) {
315 } else {
317 Engine_EventSetMessage(MsgKalayDidFindNeededInWeapon);
320 }
321}
322
323/// Across the counter, the leader facing east, the item shop opens; from
324/// elsewhere the merchant praises Lady Layana.
325static void Kalay_TalkToItemMerchant(void) {
326 struct FieldActor *leader;
327 u32 relativeFacing;
328
330 relativeFacing = (leader->facing - 0x2000) << 16;
331 if (relativeFacing > 0xC0000000) {
333 } else {
335 Engine_EventSetMessage(MsgKalayLadyLayanaSharedInLord);
338 }
339}
340
341/// Walking north into a house door, everyone stops, the door opens and the
342/// leader walks in.
343static void Kalay_OpenDoorAndExit(void) {
344 struct EventWork *event;
345 struct FieldActor *actor;
346 s16 *trigger;
347 u32 i;
348 s32 door;
349
350 event = gEventWork;
352 for (i = ACTOR_FIRST_PLACED; i <= 65; i++) {
353 actor = Object_GetById(i);
354 if (actor != NULL) {
355 actor->motionFlags = 0;
356 }
357 }
358 trigger = &event->touchedTrigger;
359 door = *trigger - 1;
361 {
362 s32 x = gKalay_DoorCells[door].x;
363 s32 y = gKalay_DoorCells[door].y;
364
366 }
372 Engine_EventRequestExit(*trigger);
376}
377
378/// The palace door opens in two frames.
379static __inline__ void Kalay_AnimatePalaceDoor(void) {
381 Map_CopyCellsTo(36, 23, 43, 12, 2, 2);
383 Map_CopyCellsTo(39, 23, 43, 12, 2, 2);
385}
386
387/// Walking north into the palace door, it opens and the leader walks in.
388static void Kalay_EnterPalace(void) {
400}
401
402/// Leaving town (triggers 9 and 10) after hearing of the Colosso tour, the
403/// party watches the tour group stop: the guides count everyone, pace back and
404/// forth while the tourists grumble, give up on the missing man and lead the
405/// group off. The late tourist then runs after it. Otherwise the party leaves.
407 s32 message;
408 struct FieldActor *headWait;
409 struct FieldActor *lastWait;
410 struct FieldActor *closing;
411 struct FieldActor *late;
412 struct FieldActor *headEnd;
413 struct FieldActor *lastEnd;
414 struct FieldActor *leader;
415 struct FieldActor *last;
416 struct FieldActor *head;
417 struct FieldActor *headBack;
418 struct FieldActor *headAgain;
419 struct FieldActor *headHome;
420 struct EventWork *work;
421
422 work = gEventWork;
428 Actor_SetPosition(27, PIXELS(284), PIXELS(264));
429 Actor_SetPosition(28, PIXELS(284), PIXELS(280));
430 Actor_SetPosition(29, PIXELS(300), PIXELS(264));
431 Actor_SetPosition(30, PIXELS(300), PIXELS(280));
432 Actor_SetPosition(32, PIXELS(316), PIXELS(264));
433 Actor_SetPosition(31, PIXELS(316), PIXELS(280));
434 Actor_SetPosition(33, PIXELS(332), PIXELS(264));
435 Actor_SetPosition(34, PIXELS(332), PIXELS(280));
439 UiText_ShowCenteredMessage(MsgKalayOkListeningLets, 1, 0);
443 if (work->touchedTrigger == 9) {
444 Camera_SetSpeed(PIXELS(12) / 5, PIXELS(3) / 10);
446 } else {
447 Camera_SetSpeed(PIXELS(6) / 5, PIXELS(3) / 20);
449 }
450 // Stagger the speeds so the group arrives in rows.
451 Actor_SetSpeed(ACTOR_HEAD_GUIDE, PIXELS(11) / 10, PIXELS(11) / 20);
452 Actor_SetSpeed(27, PIXELS(1), PIXELS(1) / 2);
453 Actor_SetSpeed(28, PIXELS(1), PIXELS(1) / 2);
454 Actor_SetSpeed(29, PIXELS(9) / 10, PIXELS(9) / 20);
455 Actor_SetSpeed(30, PIXELS(9) / 10, PIXELS(9) / 20);
456 Actor_SetSpeed(32, PIXELS(4) / 5, PIXELS(2) / 5);
457 Actor_SetSpeed(31, PIXELS(4) / 5, PIXELS(2) / 5);
458 Actor_SetSpeed(33, PIXELS(7) / 10, PIXELS(7) / 20);
459 Actor_SetSpeed(34, PIXELS(7) / 10, PIXELS(7) / 20);
471 last->timer = 0;
473 Camera_MoveTo(PIXELS(186), -1, PIXELS(272), 1);
476 do {
478 } while (last->timer == 0);
482 Engine_EventSetMessage(MsgKalayWhyWeStoppingAtPlace);
483 Event_ShowMessageAndWait(27, 0, 10);
487 Event_ShowMessageAndWait(28, 0, 10);
490 Event_ShowMessageAndWait(32, 0, 10);
493 Event_ShowMessageAndWait(31, 0, 10);
497 Event_ShowMessageAndWait(31, 0, 10);
511 headBack = Actor_Get(ACTOR_HEAD_GUIDE);
519 headAgain = Actor_Get(ACTOR_HEAD_GUIDE);
523 headHome = Actor_Get(ACTOR_HEAD_GUIDE);
531 Event_ShowMessageAndWait(34, 0, 10);
533 Event_ShowMessageAndWait(33, 0, 10);
535 Event_ShowMessageAndWait(33, 0, 10);
548 // The tourists fidget while the guides count them.
589 message = MsgKalayShortOnePerson;
592 // The guides pace while the tourists complain one by one.
596 Engine_EventWait(240);
600 Actor_ShowEmote(27, EMOTE_IN_FRONT | 1, 60);
601 Event_ShowMessageAndWait(27, 0, 10);
608 Event_ShowMessageAndWait(28, 0, 10);
610 Engine_EventWait(160);
614 Actor_ShowEmote(32, EMOTE_IN_FRONT | 1, 60);
615 Event_ShowMessageAndWait(32, 0, 10);
623 Event_ShowMessageAndWait(30, 0, 10);
628 headWait = Actor_Get(ACTOR_HEAD_GUIDE);
629 headWait->timer = 0;
630 lastWait = Actor_Get(ACTOR_SECOND_GUIDE);
631 lastWait->timer = 0;
639 message += 5;
642 Event_ShowMessageAndWait(29, 0, 20);
645 do {
647 } while (Actor_Get(ACTOR_HEAD_GUIDE)->timer == 0 ||
648 Actor_Get(ACTOR_SECOND_GUIDE)->timer != 1);
656 message = MsgKalayDecideEnteringColosso;
658 Event_ShowMessageAndWait(31, 0, 10);
663 Actor_ShowEmote(34, EMOTE_IN_FRONT | 5, 40);
664 Actor_ShowEmote(33, EMOTE_IN_FRONT | 5, 60);
667 message += 3;
670 Event_ShowMessageAndWait(34, 0, 10);
673 Event_ShowMessageAndWait(33, 0, 10);
674 Actor_ShowEmote(34, EMOTE_IN_FRONT | 2, 60);
677 Engine_EventSetMessage(MsgKalayThatsWeCantWaitAny);
690 Engine_ActorJump(27, 2, 0);
691 Engine_ActorJump(28, 2, 0);
692 Engine_ActorJump(29, 2, 0);
693 Engine_ActorJump(30, 2, 0);
694 Engine_ActorJump(32, 2, 0);
695 Engine_ActorJump(31, 2, 0);
696 Engine_ActorJump(33, 2, 0);
697 Engine_ActorJump(34, 2, 0);
715 Actor_ShowEmote(27, EMOTE_IN_FRONT | 2, 40);
717 Event_ShowMessageAndWait(27, 0, 10);
718 Actor_ShowEmote(28, EMOTE_IN_FRONT | 2, 40);
719 Event_ShowMessageAndWait(28, 0, 10);
752 Actor_SetSpeed(ACTOR_HEAD_GUIDE, PIXELS(11) / 10, PIXELS(11) / 20);
753 Actor_SetSpeed(27, PIXELS(21) / 20, PIXELS(21) / 40);
754 Actor_SetSpeed(28, PIXELS(21) / 20, PIXELS(21) / 40);
755 Actor_SetSpeed(29, PIXELS(1), PIXELS(1) / 2);
756 Actor_SetSpeed(30, PIXELS(1), PIXELS(1) / 2);
757 Actor_SetSpeed(32, PIXELS(19) / 20, PIXELS(19) / 40);
758 Actor_SetSpeed(31, PIXELS(19) / 20, PIXELS(19) / 40);
759 Actor_SetSpeed(33, PIXELS(9) / 10, PIXELS(9) / 20);
760 Actor_SetSpeed(34, PIXELS(9) / 10, PIXELS(9) / 20);
761 Actor_SetSpeed(ACTOR_SECOND_GUIDE, PIXELS(17) / 20, PIXELS(17) / 40);
783 // Send the group onward, then bring in the missing tourist.
793 closing = Actor_Get(ACTOR_SECOND_GUIDE);
794 closing->timer = 0;
796 do {
798 } while (Actor_Get(ACTOR_SECOND_GUIDE)->timer != 1);
800 // The late tourist finds that the rest of the group has already left.
821 closing = Actor_Get(ACTOR_LATE_TOURIST);
822 closing->timer = 0;
824 do {
826 } while (Actor_Get(ACTOR_LATE_TOURIST)->timer != 1);
831 headEnd = Actor_Get(ACTOR_HEAD_GUIDE);
832 headEnd->facing = FACING_NORTH + FACING_STEP;
834 lastEnd = Actor_Get(ACTOR_SECOND_GUIDE);
835 lastEnd->facing = FACING_SOUTH + FACING_STEP;
845 if (work->touchedTrigger == 9) {
848 leader->facing = FACING_NORTH;
849 } else {
852 leader->facing = FACING_SOUTH;
853 }
856 } else {
861 }
863}
864
865/// Touching trigger 10 in the tunnel stops the fade overlay following the
866/// leader.
867static void Kalay_StopTrackingLeader(void) {
871 }
872}
873
874/// Touching trigger 11 in the tunnel makes the fade overlay follow the leader.
875static void Kalay_StartTrackingLeader(void) {
876 struct FadeOverlayWork *work;
877
879 work = gActorEffectWork;
882 }
883}
884
885/// Trigger 19 in the tunnel: the leader's depth priority follows his position.
887 u8 *priorityFlags;
888 s32 flags;
889
892 flags |= *priorityFlags;
893 *priorityFlags = flags;
894}
895
896/// Trigger 18 in the tunnel: the leader's depth priority stays fixed.
898 u8 *priorityFlags;
899 s32 flags;
900
903 flags &= *priorityFlags;
904 *priorityFlags = flags;
905}
906
907/// Catch pulls in the Nut circling in the town.
908static void Kalay_CatchTownNut(void) {
915}
916
917/// Every map of Kalay sets flag 0x87a, then prepares its own people and cells.
919 s32 scene;
920
922 scene = gGameState.scene;
923 if (scene == (s32)&SceneId_Kalay1) {
925 } else if (scene == (s32)&SceneId_Kalay2) {
927 } else if (scene == (s32)&SceneId_Kalay3) {
929 } else if (scene == (s32)&SceneId_Kalay5) {
931 } else if (scene == (s32)&SceneId_Kalay6) {
933 }
934 return 0;
935}
936
937/// Once Lunpa's trade has reopened, Hammet's palace flags (0x321 and 0x912 to
938/// 0x915) are set. Until it is caught, the Nut circles above the town.
939static void Kalay_PrepareTown(void) {
941 s32 found;
942 u8 *heap;
944
946 Engine_GameFlagSet(0x321);
949 Engine_GameFlagSet(0x915);
950 }
952 Engine_GameFlagSet(0x321);
953 }
954 if (gGameState.entrance == 14) {
955 Actor_SetPosition(25, PIXELS(424), PIXELS(88));
956 }
959 if (found != 0) {
961 } else {
963 sprite = nut->sprite;
964 sprite->flags09Mode = 1;
965 sprite->flags05Bit5 = 0;
966 sprite->flags09High = 0;
967 sprite->state = found;
968 nut->active = 1;
969 nut->mode = found;
970 nut->y = PIXELS(10);
971 nut->visible = 1;
972 heap = Engine_HeapAllocate(17, 0x608);
974 Engine_VramLoad(sprite->palette, 128, heap + 0x400);
976 nut->orbitAngle = found;
977 nut->orbitCenterX = nut->x;
978 nut->orbitCenterY = nut->y;
979 nut->orbitCenterZ = nut->z;
981 }
982}
983
984/// The palace flags as in the town; walking up to the gate the first time,
985/// Ivan introduces himself to the guards.
986static void Kalay_PreparePalaceGate(void) {
988 Engine_GameFlagSet(0x321);
991 Engine_GameFlagSet(0x915);
992 }
994 Engine_GameFlagSet(0x321);
995 }
996 if (gGameState.entrance != 0) {
999 }
1000 }
1001}
1002
1003/// The cave's Nut floats until caught, the guard turns after flag 0x915,
1004/// and arriving through entrance 10 brings Hammet back by wagon.
1005static void Kalay_PrepareCave(void) {
1006 struct FieldActor *guard;
1007
1008 if (Engine_GameFlagIsSet(0xfd6) == 0) {
1010 }
1011 if (Engine_GameFlagIsSet(0x915) != 0) {
1013 guard->facing = 0;
1014 }
1015 if (gGameState.entrance == 10) {
1017 }
1018}
1019
1020/// The fifth map opens with a window transition. After flag 0x915 its passage
1021/// cells are open; entrances 1 to 3 start sound 170.
1024 if (Engine_GameFlagIsSet(0x915) != 0) {
1025 Map_CopyCellsTo(58, 5, 58, 8, 2, 3);
1026 {
1027 Map_CopyCellAttributes(8, 11, 2, 1, 8, 10);
1028 }
1029 Map_CopyCellsTo(8, 12, 8, 11, 2, 1);
1031 Engine_TaskWait(1);
1032 }
1033 if (gGameState.entrance <= 3) {
1035 }
1036}
1037
1038/// The tunnel: the fade overlay follows the leader unless he came in by
1039/// entrance 4; pushed blocks, frozen target and opened passages are restored.
1040static void Kalay_PrepareTunnel(void) {
1041#if TBS_PATCH_1
1042 s32 resumedScene;
1043#endif
1044 struct FieldActor *actor;
1045 s32 trackingValue;
1046 s32 column;
1047 struct FadeOverlayWork *effectWork;
1048 // Slot 36 is nine slots after the event work; index the actual slot array,
1049 // not adjacent storage reached past the scalar gEventWork declaration.
1050 void **workSlots = gWorkSlot + HEAP_SLOT_EVENT;
1051
1052 ((struct EventWork *)workSlots[0])->startTransition =
1055#if TBS_PATCH_1
1057 if (resumedScene != 0) {
1058 effectWork = workSlots[9];
1060#ifdef UBFIX
1061 if (trackingValue != 0) {
1063 } else {
1064 actor = NULL;
1065 }
1066 effectWork->actor = actor;
1067#else
1068 // The original integer temporary carries an actor pointer too. The typed
1069 // branch adds a jump and a zero load in the native English trial.
1070 if (trackingValue != 0) {
1071 trackingValue = Object_GetById(ACTOR_PARTY_LEADER);
1072 }
1073 effectWork->actor = (struct FieldActor *)trackingValue;
1074#endif
1075 } else {
1077 if (gGameState.entrance == 4) {
1078 ((struct FadeOverlayWork *)workSlots[9])->actor = NULL;
1080 }
1081 }
1082#else
1085 effectWork = workSlots[9];
1087#ifdef UBFIX
1088 if (trackingValue != 0) {
1090 } else {
1091 actor = NULL;
1092 }
1093 effectWork->actor = actor;
1094#else
1095 // As in the earlier-edition branch, the integer also carries a pointer.
1096 if (trackingValue != 0) {
1097 trackingValue = Object_GetById(ACTOR_PARTY_LEADER);
1098 }
1099 effectWork->actor = (struct FieldActor *)trackingValue;
1100#endif
1101 } else if (gGameState.entrance == 4) {
1102 ((struct FadeOverlayWork *)workSlots[9])->actor = NULL;
1104 }
1105#endif
1110 column = 9;
1112 Map_CopyCellAttributes(0, 0, 1, 1, column, 14);
1113 Map_CopyCellAttributes(0, 0, 1, 1, column, 45);
1114 {
1117
1118 v |= *p;
1119 *p = v;
1120 }
1121 }
1122 }
1129 if (GameFlag_IsSet(0x915) != 0) {
1130 Actor_SetPosition(10, PIXELS(426), PIXELS(730));
1131 actor = Actor_Get(10);
1132 {
1133 u16 shown = 0x5000;
1134
1135 actor->facing = shown;
1136 }
1137 Map_CopyCellsTo(88, 48, 88, 45, 2, 3);
1138 Map_CopyCellsTo(24, 49, 24, 48, 2, 1);
1139 Map_CopyCellsTo(25, 42, 25, 47, 1, 1);
1140 Map_CopyCellAttributes(22, 50, 2, 1, 24, 49);
1141 }
1144 Map_CopyCellAttributes(7, 44, 1, 1, 0, 1);
1145 Map_CopyCellsTo(74, 58, 78, 41, 1, 5);
1146 Map_CopyCellsTo(16, 109, 13, 109, 3, 2);
1147 Map_CopyCellsTo(67, 64, 71, 44, 1, 2);
1148 Map_CopyCellsTo(67, 64, 72, 44, 1, 2);
1149 Map_CopyCellsTo(67, 68, 73, 43, 1, 2);
1150 Map_CopyCellsTo(67, 68, 74, 43, 1, 2);
1151 Map_CopyCellsTo(67, 64, 75, 44, 1, 2);
1152 Map_CopyCellsTo(67, 66, 76, 44, 1, 2);
1153 Map_CopyCellsTo(67, 64, 77, 44, 1, 2);
1154 Map_CopyCellsTo(67, 64, 78, 44, 1, 2);
1155 Map_CopyCellsTo(67, 64, 79, 44, 1, 2);
1156 Map_CopyCellsTo(67, 66, 80, 44, 1, 2);
1157 Map_CopyCellsTo(2, 0, 9, 42, 2, 2);
1158 Map_CopyCellsTo(68, 64, 71, 44, 1, 2);
1159 Map_CopyCellsTo(68, 64, 72, 44, 1, 2);
1160 Map_CopyCellsTo(68, 68, 73, 43, 1, 2);
1161 Map_CopyCellsTo(68, 68, 74, 43, 1, 2);
1162 Map_CopyCellsTo(68, 64, 75, 44, 1, 2);
1163 Map_CopyCellsTo(68, 66, 76, 44, 1, 2);
1164 Map_CopyCellsTo(68, 64, 77, 44, 1, 2);
1165 Map_CopyCellsTo(68, 64, 78, 44, 1, 2);
1166 Map_CopyCellsTo(68, 64, 79, 44, 1, 2);
1167 Map_CopyCellsTo(68, 66, 80, 44, 1, 2);
1168 Map_CopyCellsTo(4, 0, 9, 42, 2, 2);
1169 Map_CopyCellsTo(7, 11, 7, 42, 10, 8);
1170 Map_CopyCellsTo(71, 12, 71, 43, 10, 13);
1171 Map_CopyCellAttributes(6, 13, 12, 12, 6, 44);
1172 Map_CopyCellAttributes(0, 1, 1, 1, 7, 44);
1173 } else {
1174 switch (gGameState.entrance) {
1175 case 1:
1176 case 2:
1178 break;
1179 }
1180 }
1183 Map_CopyCellsTo(74, 58, 107, 41, 1, 5);
1184 Map_CopyCellsTo(45, 109, 42, 109, 3, 2);
1185 Map_CopyCellsTo(67, 64, 102, 44, 1, 2);
1186 Map_CopyCellsTo(67, 64, 103, 44, 1, 2);
1187 Map_CopyCellsTo(67, 64, 104, 44, 1, 2);
1188 Map_CopyCellsTo(67, 66, 105, 44, 1, 2);
1189 Map_CopyCellsTo(67, 64, 106, 44, 1, 2);
1190 Map_CopyCellsTo(67, 64, 107, 44, 1, 2);
1191 Map_CopyCellsTo(67, 64, 108, 44, 1, 2);
1192 Map_CopyCellsTo(67, 66, 109, 44, 1, 2);
1193 Map_CopyCellsTo(68, 64, 102, 44, 1, 2);
1194 Map_CopyCellsTo(68, 64, 103, 44, 1, 2);
1195 Map_CopyCellsTo(68, 64, 104, 44, 1, 2);
1196 Map_CopyCellsTo(68, 66, 105, 44, 1, 2);
1197 Map_CopyCellsTo(68, 64, 106, 44, 1, 2);
1198 Map_CopyCellsTo(68, 64, 107, 44, 1, 2);
1199 Map_CopyCellsTo(68, 64, 108, 44, 1, 2);
1200 Map_CopyCellsTo(68, 66, 109, 44, 1, 2);
1201 Map_CopyCellsTo(38, 14, 38, 44, 8, 4);
1202 Map_CopyCellsTo(102, 14, 102, 44, 8, 12);
1203 Map_CopyCellAttributes(37, 13, 10, 12, 37, 43);
1204 } else {
1205 switch (gGameState.entrance) {
1206 case 3:
1207 case 4:
1209 break;
1210 }
1211 }
1212}
1213
1214/// All eight tourists start fidgeting.
1224}
1225
1226/// A tourist starts fidgeting after a random pause.
1227static void Kalay_StartTouristFidgeting(s32 actorId) {
1228 struct FieldActor *actor;
1229 u32 random;
1230
1231 actor = Object_GetById(actorId);
1232 actor->timer = actorId;
1233 random = Engine_RandomNext();
1234 actor->work = (random * 5) >> 12;
1236}
1237
1238/// The guides speed up and start pacing in turn.
1239static void Kalay_StartGuidesPacing(void) {
1240 gKalay_DanceStep = 0;
1245}
1246
1247/// Each guide paces in turn, starting when the other finishes.
1249 switch (gKalay_DanceStep) {
1250 case 0:
1254 break;
1255 case 1:
1260 }
1261 break;
1262 case 2:
1267 }
1268 break;
1269 case 3:
1274 }
1275 break;
1276 case 4:
1278 gKalay_DanceStep = 0;
1279 }
1280 break;
1281 }
1282}
1283
1284/// At the palace gate the guards turn the party away until they recognize
1285/// Ivan, tanned and grown, and learn that he does not know Hammet is a
1286/// prisoner. Ivan insists his friends hear everything, and the guards open the
1287/// door for the party.
1289 struct FieldActor *actor;
1290
1292 Camera_MoveTo(-1, -1, -1, 0);
1293 Engine_TaskWait(1);
1295 Engine_TaskWait(1);
1296 Camera_SetSpeed(PIXELS(1) / 5, PIXELS(1) / 40);
1297 Camera_MoveTo(PIXELS(192), -1, PIXELS(252), 1);
1307 actor->facing = FACING_SOUTH + FACING_STEP;
1308 Engine_TaskWait(1);
1314 Engine_EventWait(20);
1317 Engine_EventWait(20);
1319 Engine_EventSetMessage(MsgKalayLordHammetsPalaceLordAway);
1322 10);
1326 Engine_EventWait(60);
1328 if (actor != NULL) {
1329 Actor_SetPosition(IVAN, actor->x.fixed, actor->z.fixed);
1330 }
1331 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
1332 Actor_WalkToAndWait(IVAN, 212, 268);
1337 Actor_WalkToAndWait(IVAN, 202, 254);
1338 Engine_EventWait(20);
1340 Engine_EventWait(10);
1348 20);
1360 Engine_EventWait(10);
1363 Engine_EventWait(10);
1380 10);
1384 if (Engine_EventChooseYesNo(0, 0) == 0) {
1388 } else {
1392 }
1399 Engine_EventWait(60);
1406 Engine_EventWait(60);
1417 10);
1421 Engine_EventWait(10);
1431 actor->facing = 0;
1433 actor->facing = FACING_WEST;
1439 Engine_EventWait(20);
1442 Actor_WalkToAndWait(IVAN, 192, 232);
1445 Actor_WalkToAndWait(IVAN, 192, 222);
1446 // Lead the party and guards through the opened palace door.
1447 Actor_SetPosition(IVAN, 0, 0);
1465}
1466
1467/// Arriving through the cave's entrance 10, Hammet comes home by Bunza's wagon
1468/// with the party. Hammet explains the secret passage to the palace and asks
1469/// Bunza to take the party round through the town, so the passage stays
1470/// secret; the cave guard opens it, Hammet goes in and the party rides off.
1472 u8 *leaderPhase;
1473 u32 random;
1474 u32 motionPhase;
1475 struct FieldActor *object;
1476 struct EventWork *work;
1477 const s32 *motionActions;
1478 s32 southFacing;
1479 const s32 *exitActions;
1480
1482 Camera_MoveTo(-1, -1, -1, 0);
1483 Engine_TaskWait(1);
1486 object = Actor_Get(ACTOR_WAGON);
1487 Engine_ActorSetSpriteFlags(object, 0);
1488 Camera_MoveTo(PIXELS(440), -1, PIXELS(522), 0);
1490 Engine_TaskWait(1);
1492 Camera_SetSpeed(PIXELS(8) / 5, PIXELS(1) / 5);
1493 Camera_MoveTo(PIXELS(440), -1, PIXELS(400), 1);
1495 Actor_SetSpeed(ACTOR_WAGON, PIXELS(8) / 5, PIXELS(4) / 5);
1497 Camera_SetSpeed(PIXELS(3) / 4, PIXELS(3) / 32);
1498 Camera_MoveTo(PIXELS(440), -1, PIXELS(300), 1);
1499 Actor_SetSpeed(ACTOR_WAGON, PIXELS(4) / 5, PIXELS(2) / 5);
1503 Engine_EventWait(40);
1504 Actor_SetSpeed(ACTOR_BUNZA, PIXELS(4) / 5, PIXELS(2) / 5);
1511 Camera_MoveTo(PIXELS(410), -1, PIXELS(280), 1);
1512 Actor_SetSpeed(ACTOR_HAMMET, PIXELS(3) / 5, PIXELS(3) / 10);
1527 // Seed the party idle phases for the arrival conversation.
1528 leaderPhase = (u8 *)Actor_Get(ACTOR_PARTY_LEADER);
1529 random = Random_Next();
1530 motionPhase = random * 5;
1531 motionActions = gKalay_PartyFidgetScript;
1532 leaderPhase += offsetof(struct FieldActor, work);
1533 *(u16 *)leaderPhase = motionPhase >> 12;
1537 Engine_EventSetMessage(MsgKalayWeveArrivedHammet);
1540 object = Actor_Get(ACTOR_PARTY_LEADER);
1541 if (object != 0) {
1542 Actor_SetPosition(GARET, object->x.fixed, object->z.fixed);
1543 }
1544 object = Actor_Get(ACTOR_PARTY_LEADER);
1545 if (object != 0) {
1546 Actor_SetPosition(IVAN, object->x.fixed, object->z.fixed);
1547 }
1548 object = Actor_Get(ACTOR_PARTY_LEADER);
1549 if (object != 0) {
1550 Actor_SetPosition(MIA, object->x.fixed, object->z.fixed);
1551 }
1552 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
1553 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
1554 Actor_SetSpeed(MIA, PIXELS(4) / 5, PIXELS(2) / 5);
1555 Actor_WalkTo(GARET, 378, 310);
1556 Actor_WalkTo(IVAN, 400, 288);
1557 Actor_WalkToAndWait(MIA, 410, 308);
1563 leaderPhase = (u8 *)Actor_Get(GARET);
1564 random = Random_Next();
1565 leaderPhase += offsetof(struct FieldActor, work);
1566 *(u16 *)leaderPhase = (random * 5) >> 12;
1567 leaderPhase = (u8 *)Actor_Get(IVAN);
1568 random = Random_Next();
1569 leaderPhase += offsetof(struct FieldActor, work);
1570 *(u16 *)leaderPhase = (random * 5) >> 12;
1571 leaderPhase = (u8 *)Actor_Get(MIA);
1572 random = Random_Next();
1573 leaderPhase += offsetof(struct FieldActor, work);
1574 *(u16 *)leaderPhase = (random * 5) >> 12;
1575 Actor_SetActionScript(GARET, motionActions);
1576 Actor_SetActionScript(IVAN, motionActions);
1577 Actor_SetActionScript(MIA, motionActions);
1587 Engine_TaskWait(1);
1612 Engine_EventWait(10);
1622 Engine_EventWait(40);
1657 if (Engine_EventChooseYesNo(0, 0) == 0) {
1658 Engine_EventWait(20);
1659 gEventWork->message += 3;
1660 } else {
1661 Engine_EventWait(20);
1668 }
1675 Engine_EventWait(20);
1678 Camera_SetSpeed(PIXELS(1), PIXELS(1) / 8);
1679 Camera_MoveTo(PIXELS(280), -1, PIXELS(200), 1);
1690 // The guard opens the passage and Hammet goes in.
1692 Map_CopyCellsTo(71, 60, 76, 11, 2, 1);
1693 Map_CopyCellAttributes(71, 60, 2, 1, 16, 11);
1694 Engine_EventWait(20);
1698 Camera_SetSpeed(PIXELS(3) / 5, PIXELS(3) / 40);
1699 Camera_MoveTo(PIXELS(248), -1, PIXELS(170), 1);
1711 object = Actor_Get(ACTOR_WAGON);
1712 southFacing = FACING_SOUTH;
1713 object->facing = southFacing;
1714 Camera_MoveTo(PIXELS(380), -1, PIXELS(280), 0);
1716 Engine_TaskWait(10);
1719 Engine_EventWait(40);
1721 Engine_EventWait(20);
1731 // The party climbs back into the wagon.
1732 exitActions = gKalay_PartyGatherScript;
1733 Actor_SetActionScript(GARET, exitActions);
1734 Actor_SetActionScript(IVAN, exitActions);
1735 Actor_RunActionScriptAndWait(MIA, exitActions);
1736 Camera_MoveTo(PIXELS(410), -1, PIXELS(300), 1);
1742 Actor_SetSpeed(ACTOR_WAGON, PIXELS(4) / 5, PIXELS(2) / 5);
1743 Camera_SetSpeed(PIXELS(1), PIXELS(1) / 8);
1744 Camera_MoveTo(PIXELS(440), -1, PIXELS(420), 1);
1746 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
1747 Camera_MoveTo(PIXELS(440), -1, PIXELS(600), 1);
1748 Actor_SetSpeed(ACTOR_WAGON, PIXELS(8) / 5, PIXELS(4) / 5);
1750 Actor_WalkTo(ACTOR_WAGON, 440, 600);
1752 work = gEventWork;
1753 work->transitionFrames = 24;
1759}
1760
1761// Shared source, included in link order.
1762#include "common/object_findcell.h"
1763
1764/// In the tunnel, walking into a block pushes it one tile when there is room.
1765static void Kalay_PushTunnelBlock(void) {
1766 struct FieldPosition destination;
1767 struct FieldActor *leader;
1768 struct FieldActor *block;
1769 s32 direction;
1770 s32 probeStep;
1771 s32 moveStep;
1772 s32 leaderX;
1773 struct FieldPosition *target;
1774 s32 stoppedVelocity;
1775 s32 pushSpeed;
1776
1778 direction = (leader->facing >> 12);
1779 leaderX = leader->x.part.pixel;
1780 probeStep = gKalay_TileStepByFacing[direction];
1781 block =
1782 SceneActor_FindActorAtCell((leaderX + (probeStep >> 16)) >> 4,
1783 (leader->z.part.pixel + (s16)probeStep) >> 4);
1784 if (block != NULL) {
1785 stoppedVelocity = 0;
1786 block->terrainId = 2;
1787 target = &destination;
1788 moveStep = gKalay_TileStepByFacing[direction];
1789 SET_POSITION(target, block->x.fixed + (moveStep & -0x10000), block->y.fixed,
1790 block->z.fixed + (moveStep << 16));
1791 if (FieldObject_CheckMovementCollision(block, target) <= 0) {
1792 Object_SetMode(leader, 8);
1793 pushSpeed = PIXELS(1) / 5;
1794 Engine_TaskWait(15);
1796 block->speed = pushSpeed;
1797 block->acceleration = pushSpeed;
1798 Engine_ObjectSetPosition(block, target->x, target->y, target->z);
1799 leader->speed = pushSpeed;
1800 leader->acceleration = pushSpeed;
1801 Engine_ObjectSetPosition(leader, target->x, target->y, target->z);
1804 block->x.fixed = target->x;
1805 block->z.fixed = target->z;
1806 block->velocityX = stoppedVelocity;
1807 block->velocityZ = stoppedVelocity;
1808 Object_SetMode(leader, 1);
1810 }
1811 }
1812}
1813
1814/// Once a block is pushed far enough west, its passage opens step by step and
1815/// the frost target appears for the first.
1817 struct FieldActor *firstBlock;
1818 struct FieldActor *secondBlock;
1819 s32 firstPassageOpen;
1820 struct FieldActor *frostEffect;
1821 u32 i;
1822 s32 span;
1823 s32 height;
1824 s32 width;
1825
1826 // Open each passage only after its corresponding block reaches the trigger.
1827 firstBlock = Object_GetById(ACTOR_FIRST_BLOCK);
1828 secondBlock = Object_GetById(ACTOR_SECOND_BLOCK);
1830 if (firstPassageOpen != 0) {
1831 } else if ((firstBlock->x.fixed >> 19) > 29) {
1832 } else {
1833 frostEffect = Object_GetById(ACTOR_FROST_TARGET);
1835 Map_CopyCellAttributes(7, 44, 1, 1, firstPassageOpen, 1);
1836 i = 67;
1837 width = 1;
1838 height = 5;
1839 do {
1840 Map_CopyCellsTo(i, 58, 78, 41, width, height);
1842 if (i == 70) {
1844 }
1845 i++;
1846 } while (i <= 74);
1847 span = 2;
1848 Map_CopyCellsTo(16, 109, 13, 109, 3, span);
1849 Engine_EventWait(40);
1850 frostEffect->scaleX = Q16_ONE / 10;
1851 frostEffect->scaleY = Q16_ONE / 10;
1854 height = 1;
1855 Map_CopyCellsTo(67, 64, 71, 44, height, span);
1856 Map_CopyCellsTo(67, 64, 72, 44, height, span);
1857 Map_CopyCellsTo(67, 68, 73, 43, height, span);
1858 Map_CopyCellsTo(67, 68, 74, 43, height, span);
1859 Map_CopyCellsTo(67, 64, 75, 44, height, span);
1860 Map_CopyCellsTo(67, 66, 76, 44, height, span);
1861 Map_CopyCellsTo(67, 64, 77, 44, height, span);
1862 Map_CopyCellsTo(67, 64, 78, 44, height, span);
1863 Map_CopyCellsTo(67, 64, 79, 44, height, span);
1864 Map_CopyCellsTo(67, 66, 80, 44, height, span);
1865 Map_CopyCellsTo(2, 0, 9, 42, span, span);
1866 Engine_EventWait(40);
1867 Map_CopyCellsTo(68, 64, 71, 44, height, span);
1868 Map_CopyCellsTo(68, 64, 72, 44, height, span);
1869 Map_CopyCellsTo(68, 68, 73, 43, height, span);
1870 Map_CopyCellsTo(68, 68, 74, 43, height, span);
1871 Map_CopyCellsTo(68, 64, 75, 44, height, span);
1872 Map_CopyCellsTo(68, 66, 76, 44, height, span);
1873 Map_CopyCellsTo(68, 64, 77, 44, height, span);
1874 Map_CopyCellsTo(68, 64, 78, 44, height, span);
1875 Map_CopyCellsTo(68, 64, 79, 44, height, span);
1876 Map_CopyCellsTo(68, 66, 80, 44, height, span);
1877 Map_CopyCellsTo(4, 0, 9, 42, span, span);
1878 Engine_EventWait(40);
1879 span = 10;
1880 Map_CopyCellsTo(7, 11, 7, 42, span, 8);
1881 Map_CopyCellsTo(71, 12, 71, 43, span, 13);
1882 span = 44;
1883 Map_CopyCellAttributes(6, 13, 12, 12, 6, span);
1884 Engine_EventWait(40);
1886 Map_CopyCellAttributes(0, 1, 1, 1, 7, span);
1888 }
1890 } else if ((secondBlock->x.fixed >> 19) > 87) {
1891 } else {
1893 i = 67;
1894 width = 1;
1895 height = 5;
1896 do {
1897 Map_CopyCellsTo(i, 58, 107, 41, width, height);
1899 if (i == 70) {
1901 }
1902 i++;
1903 } while (i <= 74);
1904 height = 2;
1905 Map_CopyCellsTo(45, 109, 42, 109, 3, height);
1906 Engine_EventWait(40);
1907 span = 1;
1908 Map_CopyCellsTo(67, 64, 102, 44, span, height);
1909 Map_CopyCellsTo(67, 64, 103, 44, span, height);
1910 Map_CopyCellsTo(67, 64, 104, 44, span, height);
1911 Map_CopyCellsTo(67, 66, 105, 44, span, height);
1912 Map_CopyCellsTo(67, 64, 106, 44, span, height);
1913 Map_CopyCellsTo(67, 64, 107, 44, span, height);
1914 Map_CopyCellsTo(67, 64, 108, 44, span, height);
1915 Map_CopyCellsTo(67, 66, 109, 44, span, height);
1916 Engine_EventWait(40);
1917 Map_CopyCellsTo(68, 64, 102, 44, span, height);
1918 Map_CopyCellsTo(68, 64, 103, 44, span, height);
1919 Map_CopyCellsTo(68, 64, 104, 44, span, height);
1920 Map_CopyCellsTo(68, 66, 105, 44, span, height);
1921 Map_CopyCellsTo(68, 64, 106, 44, span, height);
1922 Map_CopyCellsTo(68, 64, 107, 44, span, height);
1923 Map_CopyCellsTo(68, 64, 108, 44, span, height);
1924 Map_CopyCellsTo(68, 66, 109, 44, span, height);
1925 Engine_EventWait(40);
1926 span = 8;
1927 Map_CopyCellsTo(38, 14, 38, 44, span, 4);
1928 Map_CopyCellsTo(102, 14, 102, 44, span, 12);
1929 Map_CopyCellAttributes(37, 13, 10, 12, 37, 43);
1930 Engine_EventWait(40);
1933 }
1934}
1935
1936// UB: the native void epilogue returns through r0, leaving the nonzero return
1937// address as SC_CALL's status. Repeat once per frame until the object is
1938// destroyed, with an explicit status in the modern build.
1939// Advance a particle, damp its velocity, and expire its lifetime.
1940#ifdef UBFIX
1941static s32 Kalay_UpdateTunnelParticle(struct ScriptInterpreter *interpreter) {
1942#else
1943static void Kalay_UpdateTunnelParticle(struct ScriptInterpreter *interpreter) {
1944#endif
1945 struct FieldActor *particle = (struct FieldActor *)interpreter;
1946 s16 *lifetime;
1947 s32 remainingFrames;
1948 s32 velocityX;
1949 s32 velocityY;
1950
1951 lifetime = &particle->timer;
1952 remainingFrames = *lifetime;
1953 if (remainingFrames == 0) {
1954 Object_Destroy((struct DispatchObject *)particle);
1955 } else if (remainingFrames == 1) {
1956 particle->velocityX = 0;
1957 particle->velocityY = 0;
1958 particle->x.fixed = 0;
1959 particle->y.fixed = 0;
1960 } else {
1961 particle->scaleX += Q16_ONE / 32;
1962 particle->scaleY += Q16_ONE / 32;
1963 }
1964 particle->x.fixed += particle->velocityX;
1965 particle->y.fixed += particle->velocityY;
1966 velocityX = particle->velocityX;
1967 velocityY = particle->velocityY;
1968 particle->velocityX = velocityX - velocityX / 256;
1969 particle->velocityY = velocityY - velocityY / 16;
1970 {
1971 s32 nextLifetime = *(u16 *)lifetime;
1972 nextLifetime -= 1;
1973 *(u16 *)lifetime = nextLifetime;
1974 }
1975#ifdef UBFIX
1976 return 1;
1977#endif
1978}
1979
1980/// Particles stream from each block while its passage is closed.
1982 struct FieldActor *firstEmitter;
1983 struct FieldActor *secondEmitter;
1984
1985 firstEmitter = Actor_Get(ACTOR_FIRST_BLOCK);
1986 secondEmitter = Actor_Get(ACTOR_SECOND_BLOCK);
1987 if ((u32)(firstEmitter->x.part.pixel - 381) <= 12 &&
1988 firstEmitter->z.part.pixel > 777) {
1989 firstEmitter->sprite->image.priority =
1990 Actor_Get(ACTOR_PARTY_LEADER)->sprite->image.priority;
1992 firstEmitter->x.part.pixel <= 245 && (gFrameCount & 1) == 0) {
1997 }
1998 Kalay_SpawnTunnelParticle(firstEmitter->x.fixed, firstEmitter->y.fixed,
1999 firstEmitter->z.fixed);
2000 }
2002 secondEmitter->x.part.pixel <= 709 && (gFrameCount & 1) == 0) {
2007 }
2008 Kalay_SpawnTunnelParticle(secondEmitter->x.fixed, secondEmitter->y.fixed,
2009 secondEmitter->z.fixed);
2010 }
2011}
2012
2013/// Creates a short-lived particle with random position and velocity offsets.
2014static void Kalay_SpawnTunnelParticle(s32 x, s32 height, s32 z) {
2015 s32 depth;
2016 struct FieldActor *particle;
2017 s32 random;
2018 s32 attributeMask;
2019 u8 *spriteBytes;
2020
2021 depth = z;
2022 random = Engine_RandomNext();
2023 particle = Engine_ObjectCreate(
2024 222, (x - PIXELS(8)),
2025 (((((u32)(random << 3) >> 16) << 16) + height) + PIXELS(16)), depth);
2026 if (particle != 0) {
2027 ((u8 *)particle)[offsetof(struct FieldActor, motionFlags)] =
2028 (attributeMask = 0);
2029 spriteBytes = (u8 *)particle->sprite;
2030 attributeMask -= 13;
2031 spriteBytes[9] = ((spriteBytes[9] & attributeMask) | 8);
2032 ObjectGroup_SetChildValue(particle, 9);
2033 Engine_ActorSetSpriteFlags(particle, 0);
2034 random = Random_Next();
2035 particle->velocityX = ((((u32)(random << 1) >> 16) - 1) << 16);
2036 random = Random_Next();
2037 particle->velocityY =
2038 ((((u32)(((random << 1) + random) << 1) >> 16) - 3) << 16);
2039 {
2040 u16 *target = (u16 *)&particle->timer;
2041 u16 shown = 20;
2042
2043 *target = shown;
2044 particle->frozen = 1;
2045 }
2046 Object_SetMode(particle, 1);
2048 }
2049}
2050
2051/// The town Nut circles its spot and rocks as it goes.
2052static void Kalay_UpdateNutOrbit(void) {
2053 OrbitingSceneObject *effect =
2055 struct AnimationObject *sprite = (struct AnimationObject *)effect->sprite;
2056 s32 offset = Engine_MathSin(effect->orbitAngle) * 2;
2057 s32 first;
2058
2059 if (offset > 0) {
2060 offset = -offset;
2061 }
2062 effect->x = effect->orbitCenterX + Engine_MathCos(effect->orbitAngle) * 2;
2063 effect->y = effect->orbitCenterY + offset;
2064 sprite->rotation = Engine_MathCos(effect->orbitAngle + 0x8000) >> 3;
2065 first = Engine_RandomNext();
2066 effect->orbitAngle += ((u32)(first << 9) >> 16) +
2067 ((u32)(Engine_RandomNext() << 9) >> 16) + 0x400;
2068}
2069
2070/// Frost on the target sinks it into the floor, clearing its cells.
2071static void Kalay_FreezeFrostTarget(void) {
2073
2074 Map_CopyCellAttributes(0, 0, 1, 1, 9, 14);
2075 Map_CopyCellAttributes(0, 0, 1, 1, 9, 45);
2076 if (effect != 0) {
2077 Engine_ActorSetSpriteFlags(effect, 0);
2078 effect->y.fixed -= PIXELS(32);
2079 effect->priorityFlags = 2;
2080 }
2082}
2083
2084// Shared source, included in link order.
2085#include "common/object_orbit.h"
2086
2087// One tile in each facing direction: x in the high 16 bits, z in the low 16.
2088// UB: negative x coordinates cannot be left-shifted as signed integers.
2089#ifdef UBFIX
2090#define TILE_STEP(dx, dz) (((u32)(dx) << 16) | ((dz) & 0xffff))
2091#else
2092#define TILE_STEP(dx, dz) (((dx) << 16) | ((dz) & 0xffff))
2093#endif
2094
2096 TILE_STEP(16, 0), TILE_STEP(16, 0), TILE_STEP(16, 0), TILE_STEP(0, 16),
2097 TILE_STEP(0, 16), TILE_STEP(0, 16), TILE_STEP(0, 16), TILE_STEP(-16, 0),
2098 TILE_STEP(-16, 0), TILE_STEP(-16, 0), TILE_STEP(-16, 0), TILE_STEP(0, -16),
2099 TILE_STEP(0, -16), TILE_STEP(0, -16), TILE_STEP(0, -16), TILE_STEP(16, 0),
2100};
2101
2103 SC_ARG(2), SC_MOVE_BY(-PIXELS(80), 0, 0),
2104 SC_SYNC, SC_ARG(1),
2105 SC_SET(0x23, 1), SC_WAIT(1),
2106 SC_END,
2107};
2108
2110 SC_ARG(2), SC_MOVE_BY(-PIXELS(72), 0, 0),
2111 SC_SYNC, SC_MOVE_BY(-PIXELS(100), 0, 0),
2112 SC_SYNC, SC_MOVE_BY(-PIXELS(100), 0, 0),
2113 SC_SYNC, SC_ARG(1),
2114 SC_SET(0x23, 1), SC_POS(0, 0, 0),
2115 SC_WAIT(1), SC_END,
2116 SC_ARG(2), SC_MOVE(PIXELS(192), 0, PIXELS(222)),
2117 SC_SYNC, SC_POS(0, 0, 0),
2118 SC_WAIT(1), SC_END,
2119};
2120
2124};
2125
2127 SC_ARG(2),
2128 SC_MOVE(PIXELS(228), 0, PIXELS(296)),
2129 SC_SYNC,
2130 SC_ARG(1),
2132 SC_WAIT(40),
2133 SC_ARG(2),
2134 SC_MOVE(PIXELS(212), 0, PIXELS(296)),
2135 SC_SYNC,
2136 SC_ARG(1),
2138 SC_WAIT(40),
2139 SC_ARG(2),
2140 SC_MOVE(PIXELS(192), 0, PIXELS(296)),
2141 SC_SYNC,
2142 SC_ARG(1),
2144 SC_WAIT(40),
2145 SC_SET(0x23, 1),
2146 SC_ARG(2),
2147 SC_MOVE(PIXELS(178), 0, PIXELS(272)),
2148 SC_SYNC,
2149 SC_ARG(1),
2151 SC_WAIT(1),
2152 SC_END,
2153};
2154
2156 SC_ARG(2),
2157 SC_MOVE(PIXELS(164), 0, PIXELS(278)),
2158 SC_SYNC,
2159 SC_MOVE(PIXELS(182), 0, PIXELS(304)),
2160 SC_SYNC,
2161 SC_MOVE(PIXELS(238), 0, PIXELS(304)),
2162 SC_SYNC,
2163 SC_MOVE(PIXELS(246), 0, PIXELS(296)),
2164 SC_SYNC,
2165 SC_ARG(1),
2166 SC_SET(SW_FACING, 0xd000),
2167 SC_WAIT(40),
2168 SC_SET(0x23, 1),
2169 SC_END,
2170};
2171
2179 SC_WAIT(1),
2180 SC_ARG(2),
2181 SC_MOVE(PIXELS(184), 0, PIXELS(294)),
2182 SC_SYNC,
2183 SC_ARG(1),
2185 SC_SET(0x23, 1),
2186 SC_WAIT(1),
2187 SC_END,
2188};
2189
2197 SC_WAIT(1),
2198 SC_ARG(2),
2199 SC_MOVE(PIXELS(198), 0, PIXELS(300)),
2200 SC_SYNC,
2201 SC_ARG(1),
2203 SC_SET(0x23, 1),
2204 SC_WAIT(1),
2205 SC_END,
2206};
2207
2209 SC_ARG(2),
2210 SC_MOVE(PIXELS(178), 0, PIXELS(272)),
2211 SC_SYNC,
2212 SC_ARG(1),
2214 SC_SET(0x23, 0),
2215 SC_WAIT(1),
2216 SC_END,
2217};
2218
2220 SC_ARG(2),
2221 SC_MOVE(PIXELS(255), 0, PIXELS(289)),
2222 SC_SYNC,
2223 SC_MOVE(PIXELS(265), 0, PIXELS(280)),
2224 SC_SYNC,
2225 SC_MOVE(PIXELS(284), 0, PIXELS(272)),
2226 SC_SYNC,
2227 SC_ARG(1),
2229 SC_SET(0x23, 0),
2230 SC_WAIT(1),
2231 SC_END,
2232};
2233
2237};
2238
2240 SC_ARG(2), SC_MOVE(PIXELS(388), 0, PIXELS(300)),
2241 SC_SYNC, SC_ARG(1),
2242 SC_POS(0, 0, 0), SC_END,
2243};
2244
2246 SC_ADD(SW_SCALE_X, 546),
2247 SC_ADD(SW_SCALE_Y, 546),
2248 SC_WAIT(1),
2249 SC_LOOP(108, SC_TOP),
2250 SC_END,
2251};
2252
2254 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2256};
2257
2259 {0, CONDITION_ALWAYS, 224, 0, 280, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2260 {1, CONDITION_ALWAYS, 72, 0, 200, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2261 {2, CONDITION_ALWAYS, 408, 0, 184, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2262 {3, CONDITION_ALWAYS, 408, 0, 216, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2263 {4, CONDITION_ALWAYS, 408, 0, 408, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2264 {5, CONDITION_ALWAYS, 328, 0, 440, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2265 {6, CONDITION_ALWAYS, 120, 0, 264, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2266 {7, CONDITION_ALWAYS, 312, 0, 264, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2267 {8, CONDITION_ALWAYS, 152, 0, 440, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2268 {9, CONDITION_ALWAYS, 224, 0, 464, FACING_NORTH, 0, -1, -1, -1, -1, 0},
2269 {10, CONDITION_ALWAYS, 56, 0, 272, FACING_EAST, 0, -1, -1, -1, -1, 0},
2270 {11, CONDITION_ALWAYS, 224, 0, 88, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2271 {12, CONDITION_ALWAYS, 296, 0, 408, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2272 {13, CONDITION_ALWAYS, 152, 0, 232, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2273 {14, CONDITION_ALWAYS, 440, 0, 88, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2275};
2276
2278 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2279 {1, CONDITION_ALWAYS, 192, 0, 280, FACING_NORTH, 0, 0, 0, 400, 352, 0},
2280 {2, CONDITION_ALWAYS, 192, 0, 232, FACING_SOUTH, 0, 0, 0, 400, 352, 0},
2282};
2283
2285 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2286 {1, CONDITION_ALWAYS, 248, 0, 152, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2287 {2, CONDITION_ALWAYS, 424, 0, 520, FACING_NORTH, 0, -1, -1, -1, -1, 0},
2288 {10, CONDITION_ALWAYS, 440, 0, 540, FACING_NORTH, 0, -1, -1, -1, -1, 0},
2290};
2291
2293 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2294 {1, CONDITION_ALWAYS, 296, 0, 104, FACING_SOUTH, 0, 100, 50, 440, 445, 0},
2295 {2, CONDITION_ALWAYS, 280, 0, 392, FACING_NORTH, 0, 100, 50, 440, 445, 0},
2297};
2298
2300 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2301 {1, CONDITION_ALWAYS, 296, 0, 456, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2302 {2, CONDITION_ALWAYS, 632, 0, 456, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2303 {3, CONDITION_ALWAYS, 152, 0, 72, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2304 {4, CONDITION_ALWAYS, 568, 0, 152, FACING_SOUTH, 0, 390, 0, 630, 220, 0},
2305 {5, CONDITION_ALWAYS, 472, 0, 72, FACING_SOUTH, 0, 390, 0, 630, 220, 0},
2307};
2308
2310 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2311 {1, CONDITION_ALWAYS, 408, 0, 632, FACING_SOUTH, 0, 85, 400, 465, 880, 0},
2312 {2, CONDITION_ALWAYS, 296, 0, 488, FACING_SOUTH, 0, 85, 400, 465, 880, 0},
2313 {3, CONDITION_ALWAYS, 744, 0, 488, FACING_SOUTH, 0, 595, 400, 930, 880, 0},
2314 {4, CONDITION_ALWAYS, 856, 0, 856, FACING_NORTH, 0, 595, 400, 930, 880, 0},
2316};
2317
2319 SCENE_EXITS(99), SCENE_EXIT(1, 100, 1), SCENE_EXIT(2, 100, 2),
2320 SCENE_EXIT(3, 100, 3), SCENE_EXIT(4, 100, 4), SCENE_EXIT(5, 100, 6),
2321 SCENE_EXIT(6, 100, 7), SCENE_EXIT(7, 100, 10), SCENE_EXIT(8, 101, 1),
2322 SCENE_EXIT(9, 2, 20), SCENE_EXIT(10, 2, 19), SCENE_EXIT(11, 102, 1),
2323 SCENE_EXIT(12, 100, 5), SCENE_EXIT(13, 100, 8), SCENE_EXIT(14, 156, 4),
2324 SCENE_EXIT(0, 102, 0), SCENE_EXIT(1, 99, 11), SCENE_EXIT(2, 103, 1),
2325 SCENE_EXIT(5, 103, 20), SCENE_EXIT(0, 153, 0), SCENE_EXIT(1, 154, 2),
2326 SCENE_EXIT(2, 2, 60), SCENE_EXIT(10, 2, 71), SCENE_EXIT(0, 154, 0),
2327 SCENE_EXIT(1, 155, 5), SCENE_EXIT(2, 153, 1), SCENE_EXIT(0, 155, 0),
2328 SCENE_EXIT(1, 156, 2), SCENE_EXIT(2, 156, 3), SCENE_EXIT(3, 155, 4),
2329 SCENE_EXIT(4, 155, 3), SCENE_EXIT(5, 154, 1), SCENE_EXIT(0, 156, 0),
2330 SCENE_EXIT(1, 103, 11), SCENE_EXIT(2, 155, 1), SCENE_EXIT(3, 155, 2),
2331 SCENE_EXIT(4, 99, 14), SCENE_EXITS_END,
2332};
2333
2336};
2337
2338// clang-format off
2345 PIXELS(222), 0, PIXELS(382), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2347 PIXELS(328), 0, PIXELS(134), FACING_EAST, TALK_FACE_PARTY, 0 },
2349 PIXELS(115), 0, PIXELS(453), FACING_EAST, TALK_FACE_PARTY, 0 },
2351 PIXELS(484), 0, PIXELS(258), FACING_SOUTH + FACING_STEP, TALK_FACE_PARTY, 0 },
2355 PIXELS(404), 0, PIXELS(268), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2357 PIXELS(154), 0, PIXELS(119), FACING_EAST, TALK_FACE_PARTY, 0 },
2359 PIXELS(198), 0, PIXELS(84), FACING_WEST, TALK_FACE_PARTY, 0 },
2375 PIXELS(440), 0, PIXELS(88), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2376 { 0x16, CONDITION_ALWAYS, 7,
2377 PIXELS(56), 0, PIXELS(332), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2378 { SCENE_TABLE_END },
2379};
2380
2383 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2385 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2387 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2389 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2391 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2393 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2395 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2397 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2398 { SCENE_TABLE_END },
2399};
2400
2403 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
2408 { SCENE_TABLE_END },
2409};
2410
2413 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
2415 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
2417 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
2420 { 0x111, CONDITION_ALWAYS, ACTOR_STAND,
2421 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
2423 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
2425 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
2426 { 0x16, 0xfd6, 7,
2427 PIXELS(136), 0, PIXELS(120), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2428 { SCENE_TABLE_END },
2429};
2430
2433 PIXELS(376), 0, PIXELS(826), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2435 PIXELS(808), 0, PIXELS(732), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2437 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2439 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
2440 { 0x5c, 0x5b, ACTOR_STAND,
2441 PIXELS(632), 0, PIXELS(712), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2442 { SCENE_TABLE_END },
2443};
2444
2446 { SCENE_EVENTS_END },
2447};
2448
2458 { EVENT_EXIT, 11, CONDITION_ALWAYS, 11 },
2459 { EVENT_EXIT, 12, CONDITION_ALWAYS, 12 },
2460 { EVENT_EXIT, 13, CONDITION_ALWAYS, 13 },
2461 { EVENT_EXIT, 14, CONDITION_ALWAYS, 14 },
2464 { EVENT_TALK, 8, CONDITION_ALWAYS, MSGNO(MsgKalayWelcomeInPeace) },
2465 { EVENT_TALK, 9, CONDITION_ALWAYS, MSGNO(MsgKalaySoldiersProtectPeace) },
2466 { EVENT_TALK, 10, CONDITION_ALWAYS, MSGNO(MsgKalayHammetGenerousMerchant) },
2467 { EVENT_TALK, 11, CONDITION_ALWAYS, MSGNO(MsgKalayHammetOnJourney) },
2468 { EVENT_TALK, 12, CONDITION_ALWAYS, MSGNO(MsgKalayNorthernBridgeRebuilt) },
2469 { EVENT_TALK, 13, CONDITION_ALWAYS, MSGNO(MsgKalayLamakanTrouble) },
2470 { EVENT_TALK, 14, CONDITION_ALWAYS, MSGNO(MsgKalayElderTownNews) },
2471 { EVENT_TALK, 15, FLAG_KALAY_COLOSSO_TOUR_LEFT, MSGNO(MsgKalayInnFestivalTourists) },
2472 { EVENT_TALK, 15, CONDITION_ALWAYS, MSGNO(MsgKalayFormerInnFestivalTourists) },
2473 { EVENT_TALK, 16, CONDITION_ALWAYS, MSGNO(MsgKalayChildWantsFestival) },
2474 { EVENT_TALK, 17, CONDITION_ALWAYS, MSGNO(MsgKalayTraderTownNews) },
2475 { EVENT_TALK, 18, CONDITION_ALWAYS, MSGNO(MsgKalayHammetBusinessSkill) },
2477 { EVENT_TALK, 20, CONDITION_ALWAYS, MSGNO(MsgKalayHammetCapturedRumor) },
2478 { EVENT_TALK, 21, CONDITION_ALWAYS, MSGNO(MsgKalayHammetWentNorth) },
2482 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, CONDITION_ALWAYS, MSGNO(MsgKalayWarriorHonestEyes) },
2483 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgKalayGuardsJudgeVisitors) },
2484 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgKalayHammetPeaceAndLiberty) },
2485 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, CONDITION_ALWAYS, MSGNO(MsgKalayHammetCanBeRash) },
2486 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, CONDITION_ALWAYS, MSGNO(MsgKalaySoldiersWentToVault) },
2487 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, CONDITION_ALWAYS, MSGNO(MsgKalayStrangeEvents) },
2488 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, CONDITION_ALWAYS, MSGNO(MsgKalayElderThoughts) },
2489 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, CONDITION_ALWAYS, MSGNO(MsgKalayWishSavedForFestival) },
2490 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgKalayChildFestivalDream) },
2491 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 17, CONDITION_ALWAYS, MSGNO(MsgKalayTraderThoughts) },
2492 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 18, CONDITION_ALWAYS, MSGNO(MsgKalayHammetValuesTrust) },
2493 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 19, CONDITION_ALWAYS, MSGNO(MsgKalayTrustAgainstForce) },
2494 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 20, CONDITION_ALWAYS, MSGNO(MsgKalayLunpaNorthOfVault) },
2495 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 21, CONDITION_ALWAYS, MSGNO(MsgKalayRumorsHideTruth) },
2496 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 22, CONDITION_ALWAYS, MSGNO(MsgKalayWishBetterWeapons) },
2497 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 23, CONDITION_ALWAYS, MSGNO(MsgKalayWeaponsHaveSoul) },
2498 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 24, CONDITION_ALWAYS, MSGNO(MsgKalayPalaceWaterSupply) },
2501 { SEARCH(SEARCH_JAR), 100, 0xf81, FIND_ITEM(ITEM_SLEEP_BOMB) },
2502 { SEARCH(SEARCH_JAR), 101, 0xf82, FIND_ITEM(ITEM_VIAL) },
2504 { SCENE_EVENTS_END },
2505};
2506
2508 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
2510 { EVENT_TALK, 8, CONDITION_ALWAYS, MSGNO(MsgKalaySoldiersHandleAffairs) },
2511 { EVENT_TALK, 9, CONDITION_ALWAYS, MSGNO(MsgKalaySoldiersRescueHammet) },
2512 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, CONDITION_ALWAYS, MSGNO(MsgKalayPrayForHammetSafety) },
2513 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgKalayWarriorsWillSaveHammet) },
2514 { SCENE_EVENTS_END },
2515};
2516
2518 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
2519 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
2521 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, CONDITION_ALWAYS, MSGNO(MsgKalayPassageClosedByOrders) },
2523 { SCENE_EVENTS_END },
2524};
2525
2527 { 0x31, 1, CONDITION_ALWAYS, 1 },
2528 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
2529 { SEARCH(SEARCH_CHEST), 100, 0xf22, FIND_ITEM(ITEM_APPLE) },
2530 { SCENE_EVENTS_END },
2531};
2532
2534 { 0x31, 1, CONDITION_ALWAYS, 1 },
2535 { 0x31, 2, CONDITION_ALWAYS, 2 },
2536 { 0x21, 3, CONDITION_ALWAYS, 3 },
2537 { 0x31, 4, CONDITION_ALWAYS, 4 },
2538 { 0x21, 5, CONDITION_ALWAYS, 5 },
2539 { SCENE_EVENTS_END },
2540};
2541
2543 { 0x21, 1, CONDITION_ALWAYS, 1 },
2544 { 0x21, 2, CONDITION_ALWAYS, 2 },
2545 { 0x21, 3, CONDITION_ALWAYS, 3 },
2546 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
2548 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgKalayTreasureBeyondDoors) },
2563 { SEARCH(SEARCH_CHEST), 102, 0xf1e, FIND_ITEM(ITEM_SLEEP_BOMB) },
2564 { SEARCH(SEARCH_CHEST), 103, 0xf1f, FIND_ITEM(ITEM_LUCKY_MEDAL) },
2565 { SEARCH(SEARCH_CHEST), 104, 0xf20, FIND_COINS(200) },
2566 { SEARCH(SEARCH_CHEST), 105, 0xf21, FIND_ITEM(ITEM_POTION) },
2567 { SCENE_EVENTS_END },
2568};
2569// clang-format on
2570
2572 MAP_CELL_STEP(35, 33, 1, 2, 5),
2573 MAP_CELL_STEP(37, 33, 1, 2, 5),
2575};
2576
2578 {gKalay_DoorCellSteps, 36, 10}, {gKalay_DoorCellSteps, 57, 7},
2579 {gKalay_DoorCellSteps, 57, 11}, {gKalay_DoorCellSteps, 57, 23},
2580 {gKalay_DoorCellSteps, 52, 25}, {gKalay_DoorCellSteps, 39, 14},
2581 {gKalay_DoorCellSteps, 51, 14}, {gKalay_DoorCellSteps, 41, 25},
2582};
2583
2587};
Ability numbers, named from the English release.
@ ABILITY_MIND_READ
Definition ability_ids.h:16
@ ABILITY_CATCH
Definition ability_ids.h:23
@ ABILITY_MOVE
Definition ability_ids.h:15
@ ABILITY_FROST
Definition ability_ids.h:11
void ObjectGroup_SetChildValue(struct FieldActor *actor, s32 param)
Sets the param byte of every animated part of an actor's sprite.
void Object_RefreshSelectorById(u32 objectId)
Waits, at most 300 frames, for an actor's script to reach its end (command 0x10).
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
@ ELEMENT_MARS
Definition battle_unit.h:38
Calls through a function pointer, by argument count.
The task scheduler: tasks, their order and the scheduler's state.
struct FieldActor * Camera_GetEventObject(void)
The event command "get view centre": returns the camera object.
Definition camera.c:133
#define GARET
Jerald.
#define MIA
Mary.
#define IVAN
Ivan.
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.
void Djinn_JoinParty(s32 slot, s32 element, s32 djinn)
A Djinni joins the party: djinn (0 to 19) of element goes to the member with the fewest Djinn,...
Definition djinni.c:124
The edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
The engine call layer: one typed inline for each of the thirteen main-image routines below that the s...
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
static s32 FieldObject_CheckMovementCollision(struct FieldActor *actor, struct FieldPosition *position)
Definition engine_call.h:66
void BattleFx_StartFadeOverlay(void *object)
Starts the fade overlay on object (the party leader when NULL): loads its solid tiles,...
void Object_Destroy(struct DispatchObject *work)
s32 gKalay_DanceStep
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
void Engine_ObjectSetPosition(struct FieldActor *object, s32 fixed_x, s32 fixed_y, s32 fixed_z)
@ 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
static s32 Event_OpenMessage(s32 speaker, s32 flags)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Object_SetMode(struct FieldActor *object, s32 animation)
#define SPEAKER_WINDOW_ABOVE
Definition field_event.h:56
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
static void Event_ShowMessageAndWait(s32 speaker, s32 flags, s32 frames)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
s32 Engine_PartyGiveItem(s32 item, s32 flags)
#define GameFlag_IsSet
#define SPEAKER_PORTRAIT_RIGHT
Definition field_event.h:55
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
static void Camera_SetSpeed(s32 speed, s32 acceleration)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
void Engine_ItemLoadIcon(s32 item)
#define EMOTE_IN_FRONT
Definition field_event.h:49
s32 Engine_MathSin(s32 angle)
#define MAP_CELL_STEP(srcX, srcY, width, height, frames)
Definition field_event.h:59
void Engine_ItemShowFound(s32 item, s32 height)
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorSetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_EventCloseScreen(void)
static void Actor_RunActionScriptAndWait(s32 actor, const s32 *script)
Runs a script, waiting at most 300 frames for its final command.
static void Map_CopyCellsTo(s32 srcX, s32 srcY, s32 destX, s32 destY, s32 width, s32 height)
void Engine_HeapRelease(s32 slot)
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
void Engine_ActorDestroy(s32 actor)
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
s32 Engine_EventAskYesNo(s32 speaker, s32 flags)
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)
static void Actor_SetActionScript(s32 actor, const s32 *script)
The engine encodes either a built-in action or an action-script address.
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)
s32 Engine_RandomNext()
static void Event_PlayCue(s32 cue)
void Engine_ActorSetChildValue(s32 actor, s32 value)
#define MAP_CELL_STEPS_END
Definition field_event.h:61
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_MapAnimateCells(const u16 *steps, s32 destX, s32 destY)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
s32 Engine_MathCos(s32 angle)
static s32 Event_AskYesNo(s32 speaker, s32 flags)
static void Actor_CenterAndWalk(s32 actor, s32 priority, s32 dz)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_MapRedraw(void)
void Engine_ShopOpen(s32 shop, s32 keeper)
static s32 Random_Next(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 void Actor_SetAttachedEffect(s32 actor, s32 effect)
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_UNDERFOOT
The depth sort treats it as 320 pixels higher on the screen.
Definition field_obj.h:155
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
Definition field_obj.h:153
#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 field's runtime work: map cells, scene records and regions, map markers and FieldWork.
The scene table formats: entrances, exits, placements and events, and the macros that write them.
#define SCENE_EVENTS_END
#define FIND_ITEM(item)
@ EVENT_TOUCH
@ EVENT_EXIT
@ 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_KEEP_FACING
@ TALK_FACE_PARTY
@ TALK_FACE_PARTY_AND_BACK
#define PSYNERGY_ON_ACTOR(ability)
#define EVENT_SCRIPT(script)
#define EVENT_TOUCH_WALKING
@ ACTOR_WANDER
@ 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_JAR
@ SEARCH_UNNAMED
@ SEARCH_CHEST
#define FIND_COINS(coins)
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_KALAY_TOWN_NUT_CAUGHT
the Nut circling in the town
Definition flags.h:230
#define FLAG_SCENE_TEMP_03
Definition flags.h:716
#define FLAG_REACHED_KALAY
Set whenever Kalay is entered; Vale's villagers then talk of the party's journey.
Definition flags.h:441
#define FLAG_LUNPA_TRADE_REOPENED
Definition flags.h:123
#define FLAG_LUNPA_HEARD_OF_PRISONER
Definition flags.h:122
#define FLAG_SCENE_TEMP_00
Definition flags.h:713
#define FLAG_SCENE_TEMP_02
Definition flags.h:715
#define FLAG_IVAN_REPORTED_TO_LAYANA
that Hammet is still in Lunpa
Definition flags.h:604
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_SCENE_TEMP_01
Definition flags.h:714
#define FLAG_KALAY_HEARD_OF_COLOSSO_TOUR
The inn's guests told the party about the Colosso tour to Tolbi.
Definition flags.h:228
#define FLAG_KALAY_COLOSSO_TOUR_LEFT
the tour group has left town
Definition flags.h:229
#define FLAG_LAYANA_SCOLDED_LUNPA_VISIT
Definition flags.h:605
volatile u32 gFrameCount
Frames WaitFrames has finished.
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The screen blend's globals and the graphics routines.
The heap's work slots and HeapState.
@ HEAP_SLOT_EVENT
Definition heap_state.h:40
@ ACTOR_ITEM_MERCHANT
Definition imil.c:62
@ ACTOR_ARMOR_MERCHANT
Definition imil.c:60
@ ACTOR_WEAPON_MERCHANT
Definition imil.c:59
The main-image routines scene overlays import.
Item numbers, named from the English release.
@ ITEM_APPLE
Definition item_ids.h:52
@ ITEM_NUT
Definition item_ids.h:41
@ ITEM_SPIRIT_GLOVES
Definition item_ids.h:33
@ ITEM_SLEEP_BOMB
Definition item_ids.h:68
@ ITEM_VIAL
Definition item_ids.h:42
@ ITEM_POTION
Definition item_ids.h:43
@ ITEM_LUCKY_MEDAL
Definition item_ids.h:70
const u32 * Kalay_GetExits(void)
The numbered exits of all six maps.
Definition kalay.c:179
struct ScenePlacement gKalay_NoPlacements[]
Definition kalay.c:2334
static void Kalay_PushTunnelBlock(void)
In the tunnel, walking into a block pushes it one tile when there is room.
Definition kalay.c:1765
struct SceneEntrance gKalay_PalaceGateEntrances[]
Definition kalay.c:2277
static void Kalay_RecruitDjinn(void)
Talking to the Mars Djinni in the tunnel adds it to the party.
Definition kalay.c:116
s32 gKalay_TunnelParticleScript[]
Definition kalay.c:2584
s32 gKalay_TourGroupLeaveScript[]
Definition kalay.c:2109
static void Kalay_HammetReturnsToPalace(void)
Arriving through the cave's entrance 10, Hammet comes home by Bunza's wagon with the party.
Definition kalay.c:1471
s32 gKalay_TileStepByFacing[]
Definition kalay.c:2095
struct MapCellAnim gKalay_DoorCells[]
Definition kalay.c:2577
s32 gKalay_GuidePaceScript[]
Definition kalay.c:2155
s32 gKalay_SecondGuideStopScript[]
Definition kalay.c:2190
static void Kalay_StartTrackingLeader(void)
Touching trigger 11 in the tunnel makes the fade overlay follow the leader.
Definition kalay.c:875
static void Kalay_WatchTourGroupDeparture(void)
Leaving town (triggers 9 and 10) after hearing of the Colosso tour, the party watches the tour group ...
Definition kalay.c:406
static s32 Kalay_UpdateTouristFidget(struct ScriptInterpreter *interpreter)
While the tour waits, a tourist now and then nods, shakes his head or turns.
Definition kalay.c:121
static void Kalay_CatchCaveNut(void)
Catch pulls in the Nut floating in the cave.
Definition kalay.c:209
static void Kalay_FreezeFrostTarget(void)
Frost on the target sinks it into the floor, clearing its cells.
Definition kalay.c:2071
static void Kalay_UpdateNutOrbit(void)
The town Nut circles its spot and rocks as it goes.
Definition kalay.c:2052
struct SceneEntrance gKalay_CaveEntrances[]
Definition kalay.c:2284
static void Kalay_UpdateTunnelEmitters(void)
Particles stream from each block while its passage is closed.
Definition kalay.c:1981
struct SceneEvent gKalay_TownEvents[]
Definition kalay.c:2449
static void Kalay_TalkAboutLeavingHome(void)
A man tells why he moved to Kalay: he left Tolbi, afraid of Babi.
Definition kalay.c:244
struct SceneEvent gKalay_NoEvents[]
Definition kalay.c:2445
static void Kalay_UpdateTunnelPassages(void)
Once a block is pushed far enough west, its passage opens step by step and the frost target appears f...
Definition kalay.c:1816
struct SceneEntrance gKalay_TownEntrances[]
Definition kalay.c:2258
#define TILE_STEP(dx, dz)
Definition kalay.c:2092
u32 gKalay_Exits[]
Definition kalay.c:2318
struct SceneEntrance gKalay_Entrances5[]
Definition kalay.c:2299
static void Kalay_TalkToItemMerchant(void)
Across the counter, the leader facing east, the item shop opens; from elsewhere the merchant praises ...
Definition kalay.c:325
static void Kalay_StartTouristFidgeting(s32 actorId)
A tourist starts fidgeting after a random pause.
Definition kalay.c:1227
static void Kalay_CatchTownNut(void)
Catch pulls in the Nut circling in the town.
Definition kalay.c:908
static void Kalay_StartGuidesPacing(void)
The guides speed up and start pacing in turn.
Definition kalay.c:1239
static void Kalay_StopTrackingLeader(void)
Touching trigger 10 in the tunnel stops the fade overlay following the leader.
Definition kalay.c:867
static void Kalay_TalkToArmorMerchant(void)
Across the counter, the leader facing west to north, the armor shop opens; from elsewhere the merchan...
Definition kalay.c:307
static __inline__ void Kalay_ClearScriptDone(struct FieldActor *actor)
Clears the flag a guide's script sets when it is done.
Definition kalay.c:109
static void Kalay_DisableLeaderAutomaticPriority(void)
Trigger 18 in the tunnel: the leader's depth priority stays fixed.
Definition kalay.c:897
static void Kalay_SpawnTunnelParticle(s32 x, s32 height, s32 z)
Creates a short-lived particle with random position and velocity offsets.
Definition kalay.c:2014
const struct SceneRegion * Kalay_GetRegions(void)
Definition kalay.c:176
struct SceneEvent gKalay_CaveEvents[]
Definition kalay.c:2517
static void Kalay_StartWindowTransition(void)
The fifth map opens with a window transition.
Definition kalay.c:1022
struct SceneEntrance gKalay_NoEntrances[]
Definition kalay.c:2253
KalayActor
Kalay's maps share actor numbers; each is named on the map it is proved.
Definition kalay.c:55
@ ACTOR_TOLBI_EMIGRANT
Definition kalay.c:58
@ ACTOR_SECOND_BLOCK
Definition kalay.c:76
@ ACTOR_SECOND_GUIDE
Definition kalay.c:60
@ ACTOR_TOWN_NUT
Definition kalay.c:64
@ ACTOR_BUNZA
Definition kalay.c:72
@ ACTOR_CAVE_NUT
Definition kalay.c:73
@ ACTOR_PALACE_GUARD
Hammet's palace gate.
Definition kalay.c:66
@ ACTOR_WAGON
Definition kalay.c:70
@ ACTOR_SECOND_PALACE_GUARD
Definition kalay.c:67
@ ACTOR_CAVE_GUARD
The cave by the palace's secret passage.
Definition kalay.c:69
@ ACTOR_FIRST_BLOCK
the blocks that open the two passages
Definition kalay.c:75
@ ACTOR_LATE_TOURIST
the one the tour guides are missing
Definition kalay.c:57
@ ACTOR_FROST_TARGET
Definition kalay.c:77
@ ACTOR_HAMMET
Definition kalay.c:71
@ ACTOR_TUNNEL_DJINNI
Definition kalay.c:78
@ ACTOR_HEAD_GUIDE
the Colosso tour's guides
Definition kalay.c:59
s32 Kalay_Initialize(void)
Every map of Kalay sets flag 0x87a, then prepares its own people and cells.
Definition kalay.c:918
static void Kalay_StartTouristsFidgeting(void)
All eight tourists start fidgeting.
Definition kalay.c:1215
static void Kalay_PreparePalaceGate(void)
The palace flags as in the town; walking up to the gate the first time, Ivan introduces himself to th...
Definition kalay.c:986
struct SceneEvent gKalay_TunnelEvents[]
Definition kalay.c:2542
struct SceneEntrance gKalay_TunnelEntrances[]
Definition kalay.c:2309
const struct SceneEvent * Kalay_GetEvents(void)
The conversations, exits and Psynergy targets of each map.
Definition kalay.c:219
static void Kalay_TalkToWeaponMerchant(void)
Across the counter, the leader facing north, the weapon shop opens; from elsewhere the merchant grumb...
Definition kalay.c:289
struct SceneEvent gKalay_Events5[]
Definition kalay.c:2533
u16 gKalay_DoorCellSteps[]
Definition kalay.c:2571
static void Kalay_PrepareTunnel(void)
The tunnel: the fade overlay follows the leader unless he came in by entrance 4; pushed blocks,...
Definition kalay.c:1040
static __inline__ void Kalay_AnimatePalaceDoor(void)
The palace door opens in two frames.
Definition kalay.c:379
s32 gKalay_HeadGuideStopScript[]
Definition kalay.c:2172
s32 gKalay_TouristFidgetScript[]
Definition kalay.c:2121
@ KALAY_CALLBACK_PRIORITY
Definition kalay.c:52
static void Kalay_AlternateGuidesPacing(void)
Each guide paces in turn, starting when the other finishes.
Definition kalay.c:1248
static void Kalay_AskAboutCaveAccess(void)
Spoken to from any side but the north, the cave guard asks whether the party wants to go into the cav...
Definition kalay.c:253
static void Kalay_PrepareTown(void)
Once Lunpa's trade has reopened, Hammet's palace flags (0x321 and 0x912 to 0x915) are set.
Definition kalay.c:939
s32 gKalay_PartyGatherScript[]
Definition kalay.c:2239
struct SceneEvent gKalay_Events4[]
Definition kalay.c:2526
static void Kalay_UpdateTunnelParticle(struct ScriptInterpreter *interpreter)
Definition kalay.c:1943
const struct ScenePlacement * Kalay_GetPlacements(void)
The people of the town, palace gate, cave and tunnel.
Definition kalay.c:182
s32 gKalay_SecondGuideReturnScript[]
Definition kalay.c:2219
static void Kalay_PrepareCave(void)
The cave's Nut floats until caught, the guard turns after flag 0x915, and arriving through entrance 1...
Definition kalay.c:1005
s32 gKalay_HeadGuideReturnScript[]
Definition kalay.c:2208
static void Kalay_OpenDoorAndExit(void)
Walking north into a house door, everyone stops, the door opens and the leader walks in.
Definition kalay.c:343
struct ScenePlacement gKalay_TunnelPlacements[]
Definition kalay.c:2431
s32 gKalay_TourGroupWalkScript[]
Definition kalay.c:2102
const struct SceneEntrance * Kalay_GetEntrances(void)
Definition kalay.c:152
static void Kalay_EnableLeaderAutomaticPriority(void)
Trigger 19 in the tunnel: the leader's depth priority follows his position.
Definition kalay.c:886
struct SceneEntrance gKalay_Entrances4[]
Definition kalay.c:2292
struct ScenePlacement gKalay_TourGroupPlacements[]
Definition kalay.c:2381
struct SceneEvent gKalay_PalaceGateEvents[]
Definition kalay.c:2507
struct ScenePlacement gKalay_PalaceGatePlacements[]
Definition kalay.c:2401
static void Kalay_EnterPalace(void)
Walking north into the palace door, it opens and the leader walks in.
Definition kalay.c:388
static void Kalay_TalkAboutLayana(void)
In the tunnel, a man asks whether Layana was too hard on the party.
Definition kalay.c:280
s32 gKalay_PartyFidgetScript[]
Definition kalay.c:2234
s32 gKalay_FrostGrowScript[]
Definition kalay.c:2245
static void Kalay_SearchWell(void)
Searching the town well: the party peers in, and it is very clean.
Definition kalay.c:201
KalayTunnelFlag
The tunnel's own flags, kept while the party is there.
Definition kalay.c:82
@ FLAG_TUNNEL_OVERLAY_FOLLOWS_LEADER
the fade overlay
Definition kalay.c:83
@ FLAG_TUNNEL_SECOND_PARTICLES_SOUNDED
Definition kalay.c:87
@ FLAG_TUNNEL_FROST_TARGET_FROZEN
Definition kalay.c:84
@ FLAG_TUNNEL_FIRST_PARTICLES_SOUNDED
Each block's particles have started their sound.
Definition kalay.c:86
@ FLAG_TUNNEL_SECOND_PASSAGE_OPEN
Definition kalay.c:89
@ FLAG_TUNNEL_FIRST_PASSAGE_OPEN
Definition kalay.c:88
struct ScenePlacement gKalay_CavePlacements[]
Definition kalay.c:2411
s32 gKalay_GuideCountScript[]
Definition kalay.c:2126
static void Kalay_IvanMeetsPalaceGuards(void)
At the palace gate the guards turn the party away until they recognize Ivan, tanned and grown,...
Definition kalay.c:1288
struct ScenePlacement gKalay_TownPlacements[]
Definition kalay.c:2339
Small statement macros both games use for positions, velocities and bounds.
#define SET_POSITION(p, px, py, pz)
Sets the position or the velocity of a particle, a piece of debris or an object in one statement.
Definition macros.h:16
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_SYNC
Wait for arrival.
Definition objcmd.h:17
#define SC_FOREVER
Definition objcmd.h:14
#define SC_ADD(w, v)
Definition objcmd.h:38
#define SC_ARG(v)
Definition objcmd.h:44
#define SC_MOVE(x, y, z)
Move toward the target.
Definition objcmd.h:19
#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
#define SC_MOVE_BY(x, y, z)
Move by a relative offset.
Definition objcmd.h:20
@ SW_VELOCITY_X
Definition objcmd.h:64
@ SW_TARGET_Y
Definition objcmd.h:70
@ SW_TARGET_Z
Definition objcmd.h:71
@ SW_VELOCITY_Z
Definition objcmd.h:66
@ SW_TARGET_X
Definition objcmd.h:69
@ SW_SCALE_Y
Definition objcmd.h:63
@ SW_FACING
Definition objcmd.h:57
@ SW_SCALE_X
Definition objcmd.h:62
@ SW_VELOCITY_Y
Definition objcmd.h:65
#define SC_CALL(fn)
Definition objcmd.h:50
void Event_CallWithLastActiveObjectId(struct ScenePlacement *table)
Spawns the actors of a placement table after the last actor in use.
Definition events.c:148
void Ui_SetMessageVoiceFromActor(s32 actor)
Sets the voice of the messages that follow to that of actor's sprite, at the rate the message speed o...
Definition messages.c:483
The fade overlay, the weather particles and the actor effect work.
struct FadeOverlayWork * gActorEffectWork
static s32 Scene_LookAboutRandomly(struct ScriptInterpreter *interpreter)
An object script call, each frame: when the actor's countdown (work) runs out, it turns by a random a...
void FieldObject_WaitForMove(void *fieldObject)
Waits a frame at a time until a field object has arrived at its target, at most 600 frames.
The views of an orbiting scene object's sprite.
void BattleFx_PlayQueuedSound(void)
Plays the sound BattleFx_SetQueuedSoundAndPlay remembered, if any.
Definition requests.c:102
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
The view a scene overlay takes of an effect; most fields are still unnamed.
void Audio_PlayCueFromEventWork(void)
Starts the current scene's field music, chosen by Scene_ResolveInteractionResult.
Definition scene.c:355
Scene numbers, named after their places.
char SceneId_Kalay6
char SceneId_Kalay5
char SceneId_Kalay4
char SceneId_Kalay1
char SceneId_Kalay3
char SceneId_Kalay2
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
The field object script interpreter and the operands its commands read.
Song and sound effect ids, indices into gSound_SongTable.
#define SE_170
Definition songs.h:165
#define SE_DOOR_OPEN
Definition songs.h:153
#define SE_185
Definition songs.h:180
#define SE_MAP_EXIT
Definition songs.h:116
#define SE_125
Definition songs.h:118
#define MUS_017
Definition songs.h:27
#define SE_188
Definition songs.h:183
#define SE_141
Definition songs.h:134
#define SE_230
Definition songs.h:225
#define SE_289
Definition songs.h:282
#define MUS_009
Definition songs.h:19
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 Scene_FloatNut(s32 id)
Draws actor id as the Nut's icon and starts it floating, 32 pixels up unless the party returns to whe...
void * gWorkSlot[]
#define offsetof(type, member)
Definition stddef.h:19
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
u16 rotation
1/65536 turns
Definition animspr.h:118
A field object as the object dispatcher's far calls take it.
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
s16 touchedTrigger
the step event a touch or exit event answers
Definition event_work.h:26
s32 transitionFrames
frames
Definition event_work.h:45
u16 message
the next message, advanced as each window opens
Definition event_work.h:47
The fade overlay draws one mark on each side of its tracked actor.
struct FieldActor * actor
the actor tracked; null draws nothing
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s16 timer
The parameter its action script reads (a follow distance or an angle to face), the player's frames to...
Definition field_obj.h:109
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
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 velocityX
16.16 fixed-point pixels per frame
Definition field_obj.h:52
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
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition field_obj.h:39
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition field_obj.h:40
u16 work
The side of the player's next footprint (2 after a stop), or scene scratch.
Definition field_obj.h:112
s32 velocityZ
16.16 fixed-point pixels per frame
Definition field_obj.h:54
u8 terrainId
The map layer (0 to 3) its ground height is read from, which the scrolling camera updates from the ce...
Definition field_obj.h:47
u8 frozen
Nonzero skips steering, terrain, gravity and floating; its velocity still moves it (ScriptMotionObjec...
Definition field_obj.h:104
A position on the field.
s32 z
16.16 fixed-point pixels
s16 entrance
Definition game_state.h:37
Cell replacement: procedure and destination cells.
Definition field_event.h:64
u16 y
destination cell row
Definition field_event.h:69
u16 x
destination cell column
Definition field_event.h:68
A floating Nut's sprite, seen as the attribute bits, palette and state its scenes set.
Definition orbit.h:11
u8 state
AnimationObject's count of layers; the Nut's scenes zero it.
Definition orbit.h:34
u8 palette
AnimationObject's slot: the VRAM cache entry the Nut's icon is loaded into.
Definition orbit.h:32
u8 flags09Mode
priority; the Nut's scenes set 1
Definition orbit.h:26
u8 flags05Bit5
full colour; the Nut's scenes clear it
Definition orbit.h:18
u8 flags09High
palette; the Nut's scenes set 0
Definition orbit.h:27
A floating Nut's actor: its position, the spot it sways around and how far through the sway it is,...
Definition orbit.h:39
s32 orbitCenterY
16.16 fixed-point pixels
Definition orbit.h:53
s32 y
16.16 fixed-point pixels
Definition orbit.h:42
OrbitingSceneObjectSprite * sprite
Definition orbit.h:56
s32 orbitCenterZ
16.16 fixed-point pixels
Definition orbit.h:54
u8 visible
FieldActor's frozen, which skips steering, terrain, gravity and floating; the Nut's scenes set it.
Definition orbit.h:67
u8 mode
FieldActor's motionFlags; the Nut's scenes zero it.
Definition orbit.h:58
s32 x
16.16 fixed-point pixels
Definition orbit.h:41
s32 orbitAngle
1/65536 turns; advanced by 0x400 plus two random steps each frame.
Definition orbit.h:50
u8 active
FieldActor.retainSpriteCache: the Nut's scenes keep its sprite's VRAM cache entry.
Definition orbit.h:63
s32 z
16.16 fixed-point pixels
Definition orbit.h:43
s32 orbitCenterX
16.16 fixed-point pixels
Definition orbit.h:52
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 prefix that command handlers read from a field object's 0x70-byte slot.
Definition script.h:16
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
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