Alchemy
Loading...
Searching...
No Matches

kolima.c

Go to the documentation of this file.
1/// @file
2/// Kolima, whose villagers the forest's curse has turned into trees, in three
3/// maps: the village, an interior and the bridge. On the first visit the party
4/// sees the curse fall and the bridge collapse.
5
6#include "script.h"
7#include "flags.h"
8#include "character_ids.h"
9#include "game_state.h"
10#include "global_cells.h"
11#include "scene_ids.h"
12#include "unit/scene/kolima.h"
14#include "unit/object/object.h"
16#include "unit/field/field.h"
18#include "battle.h"
19#include "debug.h"
20#include "field.h"
21#include "game.h"
22#include "graphics.h"
23#include "menu.h"
24#include "minigame.h"
25#include "sound.h"
26#include "system.h"
27#include "types.h"
28#include "field_event.h"
29#include "field_service.h"
30#include "field_scene.h"
31#include "kolima.h"
32#include "object_runtime.h"
33#include "call.h"
34#include "text/msg_ids.h"
35#include "ability_ids.h"
36#include "objcmd.h"
37#include "facing_object.h"
38#include "fixed_math.h"
39#include "palbuf.h"
40#include "field_runtime.h"
41#include "songs.h"
42#include "item_ids.h"
43
44static void Kolima_WitnessForestCurse(void);
45static void Kolima_ShowMessageAndWait(s32 actorId, s32 waitFrames);
46static void Kolima_FaceActorAndWait(s32 actorId, s32 facing, s32 waitFrames);
47static void Kolima_SpawnCurseSparkle(void);
48static void Kolima_RestoreBridgeState(void);
49
50/// Applies the deferred pose change requested by the falling-effect script.
51static s32 Kolima_ApplyPendingPose(struct ScriptInterpreter *interpreter) {
52 struct FieldActor *actor = (struct FieldActor *)interpreter;
53 if (gKolima_PendingPose != 0) {
54 Object_SetMode(actor, 2);
56 }
57 return 1;
58}
59
60/// Alternates an ambient actor's child appearance with a random timer.
62 struct FieldActor *actor = (struct FieldActor *)interpreter;
63 s32 randomValue = Engine_RandomNext();
64 s32 scaledRandom = randomValue * 100;
65 s32 appearanceTimer = (u16)actor->timer + ((u32)scaledRandom >> 16);
66 actor->timer = appearanceTimer;
67 if ((s16)appearanceTimer > 1000) {
69 } else {
71 }
72 if ((s16)actor->timer > 1200) {
73 actor->timer = 0;
74 }
75 return 1;
76}
77
78/// Replaces the nine villagers' placement sprites with their cursed trees.
79static void
81 struct ScenePlacement *villager = &placements[3];
82 u32 villagerIndex;
83 s32 treeSprite;
84 s32 alternateTreeSprite;
85
86 villagerIndex = 0;
87 treeSprite = 105;
88 alternateTreeSprite = 110;
89 for (; villagerIndex <= 8; villagerIndex++) {
90 villager->sprite = treeSprite;
91 if ((villagerIndex - 6) <= 1) {
92 villager->sprite = alternateTreeSprite;
93 }
94 villager->talkFacing = TALK_KEEP_FACING;
95 villager->behavior = ACTOR_STAND;
96 villager++;
97 }
98}
99
100/// Moves, enlarges and releases one bridge fragment after its lifetime.
102 struct FieldActor *debris = (struct FieldActor *)interpreter;
103 debris->x.fixed += debris->velocityX;
104 debris->z.fixed += debris->velocityZ;
105 debris->velocityZ -= PIXELS(1) / 25;
106 debris->scaleX += 3 * Q16_ONE / 128;
107 debris->scaleY += 3 * Q16_ONE / 128;
108 {
109 s32 framesLeft = (u16)debris->timer - 1;
110 debris->timer = framesLeft;
111 if ((u16)framesLeft == 0) {
113 }
114 }
115 return 1;
116}
117
118#include "common/object_facing.h"
119
120/// Selects the entrance table for the village, interior or bridge.
122 s16 scene = gGameState.scene;
123
124 if (scene == (s32)&SceneId_Kolima3) {
125 return gKolimaEntrances3;
126 }
127 if (scene == (s32)&SceneId_Kolima2) {
128 return gKolimaEntrances2;
129 }
130 return gKolimaEntrances;
131}
132
133/// Returns the interior's regions; the other maps have none.
134const struct SceneRegion *Kolima_GetRegions(void) {
136 return gKolimaRegions2;
137 }
138 return 0;
139}
140
141/// Returns the shared packed exit table.
142const u32 *Kolima_GetExits(void) { return gKolimaExits; }
143
144/// Selects placements and applies tree sprites while the villagers are cursed.
146 s32 scene = gGameState.scene;
147
148 if (scene == (s32)&SceneId_Kolima1) {
151 }
152 return gKolimaPlacements1;
153 }
154 if (scene == (s32)&SceneId_Kolima3) {
155 return gKolimaPlacements3;
156 }
157 return gKolimaPlacements;
158}
159
160/// Offers sanctum services to a north-facing leader, or discusses the trees.
161static void Kolima_TalkToHealer(void) {
162 struct FieldActor *leader = Object_GetById(0);
163 s32 facing = leader->facing;
165 if (FACING_IS_NORTH(facing)) {
167 } else {
168 Engine_EventSetMessage(MsgKolimaToldHolyTrees);
170 }
172}
173
174/// Lets the village's Djinni join the party.
175static void Kolima_RecruitDjinni(void) { Djinn_JoinParty(27, 0, 1); }
176
177/// Selects the village or bridge event table.
178const struct SceneEvent *Kolima_GetEvents(void) {
180 return gKolimaEvents3;
181 }
182 return gKolimaEvents;
183}
184
185/// Walks the leader northward through the selected exit.
186static void Kolima_WalkThroughExit(s32 exitId) {
193}
194
195/// Animates the touched map cells or leaves through the southern exit.
196static void Kolima_AnimateSwitchOrExit(void) {
197 struct EventWork *work = gEventWork;
198 s32 x = 0;
199 s32 y = 0;
200
203 switch (work->touchedTrigger) {
204 case 5:
205 x = 71;
206 y = 9;
207 break;
208 case 6:
209 x = 73;
210 y = 17;
211 break;
212 case 7:
213 x = 80;
214 y = 21;
215 break;
216 case 8:
217 x = 84;
218 y = 12;
219 break;
220 case 9:
227 return;
228 }
232}
233
234/// Shows the villager's crossing and the bridge collapsing into debris.
235static void Kolima_ShowBridgeCollapse(void) {
236 u32 debrisIndex;
237
239 Camera_SetSpeed(PIXELS(2), PIXELS(1) / 4);
240 Camera_MoveTo(PIXELS(168), 0, PIXELS(246), 1);
245 Engine_EventSetMessage(MsgKolimaGoingCrossBridge);
247 Engine_CameraSetSpeed(PIXELS(2) / 5, PIXELS(1) / 20);
248 Camera_MoveTo(PIXELS(168), 0, PIXELS(234), 1);
260 Actor_SetSpeed(8, PIXELS(2), PIXELS(1));
261 Engine_ActorJump(8, 2, 0);
269 // Animate the bridge in progressively shorter collapse steps.
270 Map_CopyCellsTo(91, 0, 72, 9, 5, 4);
272 Map_CopyCellsTo(91, 4, 72, 9, 5, 4);
275 Map_CopyCellsTo(91, 8, 72, 9, 5, 5);
277 Map_CopyCellsTo(91, 13, 72, 9, 5, 6);
280 // Scatter ten fragments with alternating horizontal velocities.
281 for (debrisIndex = 0; debrisIndex < 10; debrisIndex++) {
282 struct FieldActor *debris =
283 Engine_ObjectCreate(222, PIXELS(148 + debrisIndex * 4), 0, PIXELS(258));
284
285 if (debris != 0) {
286 debris->motionFlags = 0;
288 debris->sprite->image.priority = 0;
289 {
290 u16 delay = (((u32)(Engine_RandomNext() * 40)) >> 16) + 40;
291
292 debris->timer = delay;
293 }
294 debris->velocityX = (s32)((PIXELS(debrisIndex & 3) + PIXELS(1))) >> 1;
295 debris->velocityZ = PIXELS(1);
296 if (debrisIndex & 1) {
297 debris->velocityX = -((s32)(((debrisIndex & 3) << 16) + 0x10000) >> 1);
298 }
299 Object_SetMode(debris, 1);
301 }
302 }
303 Map_CopyCellsTo(91, 19, 72, 9, 5, 7);
304 Map_CopyCellAttributes(23, 11, 5, 7, 8, 11);
309 Map_SetShake(-1, -1, 9 * Q16_ONE / 10);
310 // From now on the villager on the far side turns to keep facing the leader.
317}
318
319/// Restores the current map and plays the first visit to cursed Kolima.
321 s16 scene;
322 u32 actor;
323 const s32 *table;
324
325 scene = gGameState.scene;
326
327 if (scene == (s32)&SceneId_Kolima3) {
329 return 0;
330 }
331
332 if (scene == (s32)&SceneId_Kolima2) {
334 return 0;
335 }
336
341
342 table = gKolima_EntryActions;
343 Actor_SetActionScript(23, table);
344 Actor_SetActionScript(24, table);
345 Actor_SetActionScript(25, table);
346 Actor_SetActionScript(26, table);
347
349 for (actor = 8; actor <= 16; actor++) {
351 }
352 Map_CopyCellAttributes(13, 9, 1, 1, 13, 8);
353 Map_CopyCellAttributes(13, 9, 1, 1, 15, 8);
354 Map_CopyCellAttributes(13, 9, 1, 1, 14, 9);
355 }
356
358 if (gGameState.entrance == 1) {
360 }
361 }
362
374 }
375
376 return 0;
377}
378
379/// Shows a protective field on its assigned alternating frame.
380static __inline__ void Kolima_SetProtectiveFieldHeight(s32 actorId,
381 s32 visibleOnOddFrames) {
382 struct FieldActor *field = Object_GetById(actorId);
383 if (field != NULL) {
384 field->motionFlags = 0;
385 if (visibleOnOddFrames ? (gFrameCount & 1) : !(gFrameCount & 1)) {
386 field->y.fixed = 0;
387 } else {
388 field->y.fixed = PIXELS(500);
389 }
390 }
391}
392
393/// Alternates the four protective sprites between visible and hidden heights.
399}
400
401/// Begins Mind Read on one of the villagers transformed into a tree.
402static void Kolima_ReadVillagerThoughts(s32 actorId, s32 targetId) {
404 Engine_PsynergySetTarget(actorId, targetId);
408}
409
410/// Finishes Mind Read and releases its temporary scene objects.
415}
416
417/// Gives the four companions the same nod, waiting on the final actor.
418static __inline__ void Kolima_NodTogether(void) {
423}
424
425/// Shows the forest's curse, the party's protective Psynergy and the trees'
426/// appeal.
427static void Kolima_WitnessForestCurse(void) {
428 struct FieldActor *actor;
429 s32 *partyLayout;
430 s32 motionFacingFlag;
431 // One staging word is reused for facing bytes, jump values and flags.
432 s32 stagingValue;
433 const s32 *squashActions;
434 const s32 *restoreScaleActions;
435 u32 *firstCurtainState;
436 s32 *sceneState;
437 const s32 *growFieldActions;
438 const s32 *shrinkFieldActions;
439 u32 *secondCurtainState;
440
441 // Enter the deserted village and let Ivan inspect one of its trees.
443 partyLayout = &gKolima_MiaInParty;
444 *partyLayout = GameFlag_IsSet(FLAG_IN_PARTY(MIA));
445 actor = Object_GetById(19);
447 actor = Object_GetById(20);
449 actor = Object_GetById(21);
451 actor = Object_GetById(22);
453 Camera_MoveTo(PIXELS(104), -1, PIXELS(256), 0);
461 Actor_SetSpeed(GARET, PIXELS(3) / 5, PIXELS(3) / 10);
462 Actor_SetSpeed(IVAN, PIXELS(3) / 5, PIXELS(3) / 10);
463 actor = Object_GetById(0);
464 if (actor != NULL) {
465 Actor_SetPosition(GARET, actor->x.fixed, actor->z.fixed);
466 }
467 actor = Object_GetById(0);
468 if (actor != NULL) {
469 Actor_SetPosition(IVAN, actor->x.fixed, actor->z.fixed);
470 }
473 if (*partyLayout != 0) {
474 Actor_SetSpeed(MIA, PIXELS(3) / 5, PIXELS(3) / 10);
475 actor = Object_GetById(0);
476 if (actor != NULL) {
477 Actor_SetPosition(MIA, actor->x.fixed, actor->z.fixed);
478 }
480 }
485 partyLayout = &gKolima_MiaInParty;
486 if (*partyLayout != 0) {
488 }
492 if (*partyLayout != 0) {
494 }
498 if (*partyLayout != 0) {
500 }
503 Engine_EventSetMessage(MsgKolimaQuiet);
508 Actor_WalkToAndWait(IVAN, 72, 0x11e);
509 Actor_WalkToAndWait(IVAN, 72, 0x12e);
510 Actor_WalkToAndWait(IVAN, 88, 0x136);
516 if (*partyLayout != 0) {
518 }
521 if (*partyLayout != 0) {
523 }
530 // Mind Read reveals that the trees are the missing villagers.
535 Actor_SetSpeed(IVAN, PIXELS(1), PIXELS(1) / 2);
537 Actor_WalkToAndWait(IVAN, 80, 0x136);
538 motionFacingFlag = ACTOR_FACES_MOTION;
540 Object_GetById(IVAN)->steeringFlags |= motionFacingFlag;
545 if (*partyLayout != 0) {
547 }
549 if (*partyLayout != 0) {
551 }
556 Actor_SetSpeed(IVAN, PIXELS(1) / 2, PIXELS(1) / 4);
558 Actor_WalkToAndWait(IVAN, 72, 0x11e);
560 Object_GetById(IVAN)->steeringFlags |= motionFacingFlag;
562 if (*partyLayout != 0) {
567 } else {
569 }
580 if (Engine_EventChooseYesNo(0, 0) == 0) {
583 } else {
586 }
595 stagingValue = 160;
598 Kolima_FaceActorAndWait(ACTOR_PARTY_LEADER, (stagingValue << 8), 10);
605 Engine_EventSetMessage(MsgKolimaWhatIsIt);
611 Kolima_FaceActorAndWait(ACTOR_PARTY_LEADER, (stagingValue << 8), 40);
624 ColorBuffer_ApplyTarget(0x7fff, 0);
627 // The falling sparkles threaten to turn the party into trees as well.
630 Engine_TaskWait(20);
631 ColorBuffer_ApplyTarget(0x405210, 1);
634 Engine_TaskWait(60);
635 squashActions = gKolima_PartySquashActions;
637 Actor_SetActionScript(GARET, squashActions);
638 Actor_SetActionScript(IVAN, squashActions);
639 Actor_SetActionScript(MIA, squashActions);
640 Engine_EventWait(100);
643 if (gKolima_MiaInParty != 0) {
648 } else {
650 }
652 if (gKolima_MiaInParty != 0) {
653 stagingValue = 128;
654 actor = Object_GetById(3);
655 actor->velocityY = (stagingValue << 10);
657 Actor_SetSpeed(MIA, (stagingValue << 10), (stagingValue << 10));
660 actor = Object_GetById(3);
664 }
665 stagingValue = 128;
666 actor = Object_GetById(0);
667 actor->velocityY = (stagingValue << 10);
669 Actor_SetSpeed(ACTOR_PARTY_LEADER, (stagingValue << 10),
670 (stagingValue << 10));
671 restoreScaleActions = gKolima_PartyRestoreScaleActions;
672 Actor_SetActionScript(ACTOR_PARTY_LEADER, restoreScaleActions);
673 actor = Object_GetById(0);
677 actor = Object_GetById(1);
678 actor->velocityY = (stagingValue << 10);
680 Actor_SetSpeed(GARET, (stagingValue << 10), (stagingValue << 10));
681 Actor_SetActionScript(GARET, restoreScaleActions);
682 actor = Object_GetById(1);
686 actor = Object_GetById(2);
687 actor->velocityY = (stagingValue << 10);
689 Actor_SetActionScript(IVAN, restoreScaleActions);
690 actor = Object_GetById(2);
694 Engine_EventWait(160);
696 Engine_EventWait(120);
697 ColorBuffer_ApplyTarget(0x406218, 1);
699 Engine_TaskWait(60);
700 // Bring the falling curtain over the party and reveal their protective
701 // fields.
703 firstCurtainState = &gFallingEffectState;
705 *firstCurtainState = 1;
707 Engine_EventWait(180);
717 *firstCurtainState = 2;
734 if (gKolima_MiaInParty != 0) {
737 } else {
739 }
740 sceneState = (s32 *)&gFallingEffectState;
741 *sceneState = 3;
742 Object_GetById(0)->priorityFlags &= 254;
743 Object_GetById(1)->priorityFlags &= 254;
744 Object_GetById(2)->priorityFlags &= 254;
745 Object_GetById(3)->priorityFlags &= 254;
749 stagingValue = 0;
751 gKolima_PendingPose = stagingValue;
754 Object_GetById(19)->priorityFlags &= 254;
756 Actor_SetPosition(19, PIXELS(120), PIXELS(248));
757 growFieldActions = gKolima_ProtectiveFieldGrowActions;
758 Actor_SetActionScript(19, growFieldActions);
759 Object_GetById(20)->priorityFlags &= 254;
761 Actor_SetPosition(20, PIXELS(100), PIXELS(274));
762 Actor_SetActionScript(20, growFieldActions);
763 if (gKolima_MiaInParty != 0) {
764 Object_GetById(21)->priorityFlags &= 254;
766 Actor_SetPosition(21, PIXELS(74), PIXELS(254));
767 Actor_SetActionScript(21, growFieldActions);
768 }
769 Object_GetById(22)->priorityFlags &= 254;
771 Actor_SetPosition(22, PIXELS(94), PIXELS(225));
772 Actor_SetActionScript(22, growFieldActions);
773 if (*sceneState != 0) {
774 do {
776 } while (gFallingEffectState != 0);
777 }
778 Engine_EventWait(300);
780 Engine_EventWait(120);
784 Engine_TaskWait(60);
787 if (gKolima_MiaInParty != 0) {
789 }
792 shrinkFieldActions = gKolima_ProtectiveFieldShrinkActions;
793 Actor_SetActionScript(19, shrinkFieldActions);
794 Actor_SetActionScript(20, shrinkFieldActions);
795 if (gKolima_MiaInParty != 0) {
796 Actor_SetActionScript(21, shrinkFieldActions);
797 }
798 Actor_RunActionScriptAndWait(22, shrinkFieldActions);
803 Actor_SetPosition(17, PIXELS(87), PIXELS(139));
804 Actor_SetPosition(18, PIXELS(87), PIXELS(139));
806 if (Engine_EventChooseYesNo(17, 0) == 1) {
808 }
813 if (gKolima_MiaInParty != 0) {
816 Engine_EventSetMessage(MsgKolimaKnowThoseFieldsWere);
818 }
823 // The companions discover that their Psynergy formed the barriers.
824 Engine_EventSetMessage(MsgKolimaWasOurPsynergy);
830 actor = Object_GetById(1);
832 Engine_ActorJump(GARET, 6, 0);
846 Engine_ActorJump(GARET, 2, 0);
848 Engine_ActorJump(GARET, 2, 0);
850 Engine_ActorJump(GARET, 4, 0);
853 if (gKolima_MiaInParty != 0) {
860 actor = Object_GetById(3);
862 Engine_ActorJump(MIA, 4, 0);
869 } else {
871 }
872 Engine_ActorJump(GARET, 2, 0);
883 stagingValue = 1;
885 Object_GetById(2)->priorityFlags |= stagingValue;
886 actor = Object_GetById(2);
888 Engine_ActorJump(IVAN, 4, 0);
894 Object_GetById(0)->priorityFlags |= stagingValue;
895 actor = Object_GetById(0);
921 if (Engine_EventChooseYesNo(0, 0) == 0) {
925 } else {
930 }
937 if (gKolima_MiaInParty != 0) {
943 } else {
945 }
950 stagingValue = 128;
953 Kolima_FaceActorAndWait(GARET, (stagingValue << 7), 10);
963 Actor_FaceDirection(GARET, (stagingValue << 7), 0);
982 if (Engine_EventChooseYesNo(0, 0) == 0) {
984 } else {
989 }
992 ColorBuffer_ApplyTarget(0x406218, 1);
994 Engine_TaskWait(60);
997 secondCurtainState = &gFallingEffectState;
998 *secondCurtainState = 1;
1000 Engine_EventWait(80);
1005 Engine_EventWait(60);
1007 // A second shower tests the barriers before the forest spirits speak.
1008 Engine_EventSetMessage(MsgKolimaWatchOutItsHappeningAgain);
1012 if (gKolima_MiaInParty != 0) {
1014 }
1015 Object_GetById(0)->priorityFlags &= 254;
1016 Object_GetById(1)->priorityFlags &= 254;
1017 Object_GetById(2)->priorityFlags &= 254;
1018 Object_GetById(3)->priorityFlags &= 254;
1023 *secondCurtainState = 2;
1025 Actor_SetPosition(19, PIXELS(120), PIXELS(248));
1026 growFieldActions = gKolima_ProtectiveFieldGrowActions;
1027 Actor_SetActionScript(19, growFieldActions);
1028 Actor_SetPosition(20, PIXELS(100), PIXELS(274));
1029 Actor_SetActionScript(20, growFieldActions);
1030 if (gKolima_MiaInParty != 0) {
1031 Actor_SetPosition(21, PIXELS(74), PIXELS(254));
1032 Actor_SetActionScript(21, growFieldActions);
1033 }
1034 Actor_SetPosition(22, PIXELS(94), PIXELS(225));
1035 Actor_SetActionScript(22, growFieldActions);
1036 Engine_EventWait(120);
1037 *secondCurtainState = 3;
1038 do {
1039 Engine_TaskWait(1);
1040 } while (gFallingEffectState != 0);
1041 // Hear the trees debate the party's immunity to Tret's glamour.
1048 Engine_EventWait(60);
1058 Engine_EventWait(40);
1087 Engine_EventWait(60);
1114 Engine_EventWait(40);
1122 Engine_EventWait(60);
1123 // End the forest's appeal and let the party decide whether to help.
1124 Event_ShowMessage(18, 0);
1125 Event_ShowMessage(17, 0);
1127 Engine_EventWait(80);
1130 Engine_TaskWait(80);
1131 Engine_ActorStop(19);
1132 Engine_ActorStop(20);
1133 sceneState = &gKolima_MiaInParty;
1134 Engine_ActorStop(21);
1135 Engine_ActorStop(22);
1136 Engine_TaskWait(1);
1137 shrinkFieldActions = gKolima_ProtectiveFieldShrinkActions;
1138 Actor_SetActionScript(19, shrinkFieldActions);
1139 Actor_SetActionScript(20, shrinkFieldActions);
1140 if (*sceneState != 0) {
1141 Actor_SetActionScript(21, shrinkFieldActions);
1142 }
1143 Actor_RunActionScriptAndWait(22, shrinkFieldActions);
1144 Engine_EventWait(20);
1148 stagingValue = 1;
1150 Object_GetById(0)->priorityFlags |= stagingValue;
1151 Object_GetById(1)->priorityFlags |= stagingValue;
1152 Object_GetById(2)->priorityFlags |= stagingValue;
1153 Object_GetById(3)->priorityFlags |= stagingValue;
1159 if (Engine_EventChooseYesNo(0, 0) == 0) {
1161 Engine_EventWait(10);
1163 if (Engine_EventChooseYesNo(0, 0) == 0) {
1168 Engine_EventWait(40);
1176 } else {
1182 Engine_EventSetMessage(MsgKolimaHesAsStumpedAsWe);
1186 }
1190 } else {
1191 Engine_EventWait(20);
1193 Engine_EventWait(10);
1194 Engine_EventSetMessage(MsgKolimaYoureIsaacThereIsntMuch);
1200 Engine_EventWait(10);
1203 if (Engine_EventChooseYesNo(0, 0) == 0) {
1204 Engine_EventWait(20);
1206 Engine_EventWait(40);
1209 if (gKolima_MiaInParty != 0) {
1213 } else {
1215 }
1218 Engine_EventWait(40);
1222 Engine_EventWait(120);
1224 if (gKolima_MiaInParty != 0) {
1228 } else {
1230 }
1231 Engine_EventWait(60);
1233 if (gKolima_MiaInParty != 0) {
1236 }
1240 Engine_EventWait(40);
1244 Engine_EventWait(20);
1247 } else {
1249 Engine_EventWait(40);
1251 Engine_EventSetMessage(MsgKolimaThatsReliefIsaacThoughtYoud);
1253 if (gKolima_MiaInParty != 0) {
1257 } else {
1259 }
1262 Engine_EventWait(40);
1266 Engine_EventWait(80);
1268 if (gKolima_MiaInParty != 0) {
1272 } else {
1274 }
1276 Engine_EventWait(20);
1280 Engine_EventWait(40);
1282 }
1283 }
1284 // Reunite the party and remember that the first visit has played.
1286 Actor_SetSpeed(GARET, PIXELS(6) / 5, PIXELS(3) / 5);
1287 Actor_SetSpeed(IVAN, PIXELS(6) / 5, PIXELS(3) / 5);
1288 Actor_SetSpeed(MIA, PIXELS(6) / 5, PIXELS(3) / 5);
1290 actor = Object_GetById(0);
1291 if (actor != NULL) {
1292 Actor_SetDestination(GARET, actor->x.part.pixel, actor->z.part.pixel);
1293 }
1295 Actor_SetPosition(GARET, 0, 0);
1297 actor = Object_GetById(0);
1298 if (actor != NULL) {
1299 Actor_SetDestination(IVAN, actor->x.part.pixel, actor->z.part.pixel);
1300 }
1302 Actor_SetPosition(IVAN, 0, 0);
1303 Actor_SetPosition(17, 0, 0);
1304 Actor_SetPosition(18, 0, 0);
1305 if (gKolima_MiaInParty != 0) {
1307 actor = Object_GetById(0);
1308 if (actor != NULL) {
1309 Actor_SetDestination(MIA, actor->x.part.pixel, actor->z.part.pixel);
1310 }
1312 Actor_SetPosition(MIA, 0, 0);
1313 }
1317}
1318
1319/// Shows the selected dialogue through an actor, then holds for its reaction.
1320static void Kolima_ShowMessageAndWait(s32 actorId, s32 waitFrames) {
1321 Engine_EventShowMessage(actorId, 0);
1322 Engine_EventWait(waitFrames);
1323}
1324
1325/// Turns an actor immediately, then leaves time for the next scene beat.
1326static void Kolima_FaceActorAndWait(s32 actorId, s32 facing, s32 waitFrames) {
1327 Engine_ActorFaceDirection(actorId, facing, 0);
1328 Engine_EventWait(waitFrames);
1329}
1330
1331#include "common/kolima_grow.h"
1332
1333/// Spawns a moving curse sparkle every eighth frame.
1334static void Kolima_SpawnCurseSparkle(void) {
1335 struct FieldActor *sparkle;
1336 struct AnimationObject *sprite;
1337 s32 framePhase;
1338 s32 priorityFlags;
1339 s32 spawnX = PIXELS(98);
1340 s32 spawnZ = PIXELS(105);
1341 s32 targetX = PIXELS(98);
1342 s32 targetZ = PIXELS(269);
1343
1344 framePhase = gFrameCount & 7;
1345 if (framePhase != 0) {
1346 return;
1347 }
1348 if (gKolima_EffectActive != 0) {
1350 }
1351 sparkle = Engine_ObjectCreate(26, spawnX, 0, spawnZ);
1352 if (sparkle == 0) {
1353 return;
1354 }
1355 sprite = sparkle->sprite;
1356 sprite->flags = framePhase;
1357 priorityFlags = 0xff & ~ACTOR_PRIORITY_AUTOMATIC;
1358 priorityFlags &= sparkle->priorityFlags;
1359 sparkle->priorityFlags = priorityFlags;
1360 sprite->image.priority = 1;
1361 sparkle->scaleX = Q16_ONE / 10;
1362 sparkle->speed = PIXELS(8);
1363 sparkle->acceleration = PIXELS(8);
1364 sparkle->motionFlags = framePhase;
1365 Object_SetMode(sparkle, 2);
1366 Engine_ObjectSetPosition(sparkle, targetX, 0, targetZ);
1368}
1369
1370#include "common/kolima_blink.h"
1371
1372/// Triggers a temporary pose when an effect enters the party's occupied area.
1374 struct FieldActor *actor = (struct FieldActor *)interpreter;
1375 if (gKolima_MiaInParty != 0) {
1376 if ((actor->x.fixed > PIXELS(59) && actor->x.fixed < PIXELS(141) &&
1377 actor->z.fixed > PIXELS(211) && actor->z.fixed < PIXELS(257)) ||
1378 (actor->x.fixed > PIXELS(69) && actor->x.fixed < PIXELS(122) &&
1379 actor->z.fixed > PIXELS(194) && actor->z.fixed < PIXELS(277))) {
1383 }
1384 } else {
1385 if ((actor->x.fixed > PIXELS(59) && actor->x.fixed < PIXELS(111) &&
1386 actor->z.fixed > PIXELS(194) && actor->z.fixed < PIXELS(230)) ||
1387 (actor->x.fixed > PIXELS(111) && actor->x.fixed < PIXELS(141) &&
1388 actor->z.fixed > PIXELS(216) && actor->z.fixed < PIXELS(250)) ||
1389 (actor->x.fixed > PIXELS(78) && actor->x.fixed < PIXELS(122) &&
1390 actor->z.fixed > PIXELS(241) && actor->z.fixed < PIXELS(277))) {
1394 }
1395 }
1396 return 0;
1397}
1398
1400s32 gKolima_PendingPose __attribute__((section(".bss")));
1401s32 gKolima_MiaInParty __attribute__((section(".bss")));
1402s32 gKolima_EffectActive __attribute__((section(".bss")));
1403
1404/// Restores the bridge's villagers and collision after its collapse.
1405static void Kolima_RestoreBridgeState(void) {
1407 Engine_ActorSetPosition(8, 0, 0);
1408 {
1409 Map_CopyCellAttributes(9, 17, 5, 1, 9, 18);
1410 }
1412 Engine_TaskWait(1);
1413 } else {
1414 Engine_ActorSetPosition(9, 0, 0);
1415 }
1417 {
1418 Map_CopyCellsTo(91, 19, 72, 9, 5, 7);
1419 }
1420 {
1421 Map_CopyCellAttributes(23, 11, 5, 7, 8, 11);
1422 }
1424 Engine_TaskWait(1);
1425 }
1426}
1427
1429 SC_ARG(2), SC_MOVE(PIXELS(97), 0, PIXELS(221)),
1431 SC_ARG(1), SC_END,
1432};
1433
1435 SC_ARG(2), SC_MOVE(PIXELS(101), 0, PIXELS(268)),
1437 SC_ARG(1), SC_END,
1438};
1439
1441 SC_ARG(2), SC_MOVE(PIXELS(78), 0, PIXELS(247)),
1443 SC_ARG(1), SC_END,
1444};
1445
1447 SC_ADD(SW_SCALE_X, -Q16_ONE / 4),
1449 SC_WAIT(2),
1451 SC_ADD(SW_SCALE_Y, -Q16_ONE / 16),
1452 SC_WAIT(2),
1453 SC_ADD(SW_SCALE_X, Q16_ONE / 16),
1454 SC_ADD(SW_SCALE_Y, -Q16_ONE / 32),
1455 SC_WAIT(2),
1456 SC_ADD(SW_SCALE_X, Q16_ONE / 16),
1457 SC_ADD(SW_SCALE_Y, -Q16_ONE / 32),
1458 SC_WAIT(2),
1460};
1461
1465 SC_WAIT(1),
1466 SC_END,
1467};
1468
1470 SC_SET(SW_SCALE_X, Q16_ONE / 10),
1471 SC_SET(SW_SCALE_Y, Q16_ONE / 10),
1472 SC_WAIT(1),
1473 SC_LABEL(1),
1474 SC_ADD(SW_SCALE_X, Q16_ONE / 50),
1475 SC_ADD(SW_SCALE_Y, Q16_ONE / 50),
1476 SC_WAIT(1),
1477 SC_LOOP(70, SC_TO(1)),
1479 SC_END,
1480};
1481
1483 SC_ARG(1),
1484 SC_ADD(SW_Z, -PIXELS(1) / 10),
1485 SC_ADD(SW_SCALE_X, -3 * Q16_ONE / 200),
1486 SC_ADD(SW_SCALE_Y, -3 * Q16_ONE / 200),
1487 SC_WAIT(1),
1488 SC_LOOP(90, SC_TOP),
1489 SC_POS(0, 0, 0),
1490 SC_WAIT(1),
1491 SC_END,
1492};
1493
1495 SC_SET(SW_SCALE_X, 3 * Q16_ONE / 4),
1496 SC_SET(SW_SCALE_Y, 3 * Q16_ONE / 4),
1497 SC_SET(SW_COLLISION, 0),
1498 SC_SET(0x23, 0),
1499 SC_LABEL(1),
1502};
1503
1507};
1508
1510 SC_CALL(Scene_TurnTowardTarget),
1512};
1513
1515 MAP_CELL_STEP(66, 32, 1, 2, 4),
1516 MAP_CELL_STEP(67, 32, 1, 2, 4),
1518};
1519
1521 {0, CONDITION_ALWAYS, 232, 0, 120, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1522 {1, CONDITION_ALWAYS, 44, 0, 267, FACING_EAST, 0, -1, -1, -1, -1, 0},
1523 {2, CONDITION_ALWAYS, 418, 0, 285, FACING_WEST, 0, -1, -1, -1, -1, 0},
1524 {3, CONDITION_ALWAYS, 119, 0, 182, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1525 {4, CONDITION_ALWAYS, 151, 0, 310, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1526 {5, CONDITION_ALWAYS, 264, 0, 373, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1527 {6, CONDITION_ALWAYS, 329, 0, 230, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1528 {7, CONDITION_ALWAYS, 263, 0, 326, FACING_NORTH, 0, -1, -1, -1, -1, 0},
1529 {8, CONDITION_ALWAYS, 360, 0, 346, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1530 {10, CONDITION_ALWAYS, 44, 0, 267, FACING_EAST, 0, -1, -1, -1, -1, 0},
1531 {12, CONDITION_ALWAYS, 232, 0, 176, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1533};
1534
1536 {1, CONDITION_ALWAYS, 170, 0, 386, FACING_NORTH, 0, 0, 0, 288, 416, 0},
1537 {2, CONDITION_ALWAYS, 168, 0, 50, FACING_SOUTH, 0, 48, 0, 288, 416, 0},
1539};
1540
1542 {1, CONDITION_ALWAYS, 216, 0, 320, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1543 {2, CONDITION_ALWAYS, 312, 0, 312, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
1545};
1546
1547// clang-format off
1549 {207, 31, 311, 225, 49, 329, -1, 1},
1550 {303, 31, 303, 321, 49, 321, -1, 2},
1551 {-1, 0, 0, 0, 0, 0, 0, 0},
1552};
1553
1555 SCENE_EXITS(36),
1556 SCENE_EXIT(1, 2, 7),
1557 SCENE_EXIT(2, 2, 38),
1558 SCENE_EXIT(5, 37, 4),
1559 SCENE_EXIT(6, 37, 3),
1560 SCENE_EXIT(7, 37, 7),
1561 SCENE_EXIT(8, 37, 10),
1562 SCENE_EXIT(9, 37, 8),
1563 SCENE_EXIT(10, 38, 2),
1564 SCENE_EXIT(0, 39, 0),
1565 SCENE_EXIT(1, 2, 11),
1566 SCENE_EXIT(2, 2, 46),
1567 SCENE_EXIT(0, 38, 0),
1568 SCENE_EXIT(1, 37, 9),
1569 SCENE_EXIT(2, 36, 8),
1571};
1572
1574 { SCENE_TABLE_END },
1575};
1576
1579 0, 0, 0, FACING_EAST, TALK_FACE_PARTY, 0 },
1581 0, 0, 0, FACING_EAST, TALK_FACE_PARTY, 0 },
1583 0, 0, 0, FACING_EAST, TALK_FACE_PARTY, 0 },
1585 PIXELS(104), 0, PIXELS(192), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1587 PIXELS(104), 0, PIXELS(312), FACING_WEST, TALK_FACE_PARTY, 0 },
1589 PIXELS(168), 0, PIXELS(360), FACING_WEST, TALK_FACE_PARTY, 0 },
1591 PIXELS(344), 0, PIXELS(280), FACING_EAST, TALK_FACE_PARTY, 0 },
1593 PIXELS(248), 0, PIXELS(392), FACING_SOUTH, 3, 0 },
1595 PIXELS(248), 0, PIXELS(184), FACING_WEST, TALK_FACE_PARTY, 0 },
1603 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
1605 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
1607 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
1615 PIXELS(24), 0, PIXELS(232), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1622 { 0x5a, 0x31, ACTOR_STAND,
1623 PIXELS(328), 0, PIXELS(360), FACING_EAST, TALK_FACE_PARTY, 0 },
1624 { SCENE_TABLE_END },
1625};
1626
1628 { 0x11d, FLAG_KOLIMA_CURSE_LIFTED, 7,
1629 PIXELS(120), 0, PIXELS(424), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1630 { 0x11d, FLAG_KOLIMA_CURSE_LIFTED, 7,
1632 { 0x11d, FLAG_KOLIMA_CURSE_LIFTED, 7,
1634 { 0x11d, FLAG_KOLIMA_CURSE_LIFTED, 7,
1636 { 0x11d, FLAG_KOLIMA_CURSE_LIFTED, 7,
1638 { SCENE_TABLE_END },
1639};
1640
1643 PIXELS(234), 0, PIXELS(200), FACING_SOUTH + FACING_STEP, 3, 0 },
1645 PIXELS(234), 0, PIXELS(200), FACING_SOUTH, TALK_KEEP_FACING, 0 },
1646 { SCENE_TABLE_END },
1647};
1648
1650 { EVENT_EXIT, 99, CONDITION_ALWAYS, 1 },
1651 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
1652 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
1658 { EVENT_EXIT, 10, CONDITION_ALWAYS, 10 },
1659 { EVENT_TALK, 8, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaThisIsKolimaVillageOfLumberjacks) },
1660 { EVENT_TALK, 9, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaWeRelyOnTheForestsSo) },
1661 { EVENT_TALK, 10, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaYouKnowBeingATreeGives) },
1662 { EVENT_TALK, 11, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaITurnedIntoATreeRight) },
1663 { EVENT_TALK, 12, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaDontBlameTheVillagersForBeing) },
1664 { EVENT_TALK, 13, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaWhoWouldTryToUseThe) },
1665 { EVENT_TALK, 14, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaIDidntMindBeingATree) },
1666 { EVENT_TALK, 15, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaYawnTreesAreSoSleepy) },
1669 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaForAWhileIThoughtId) },
1670 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaTheForestTreesAreAliveJust) },
1671 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaIWonderIfIdLiveLonger) },
1672 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaIfThoseSparklesStartFallingAgain) },
1673 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaIveBeenPoorAllMyLife) },
1674 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaItsNotCalledTheHolyTree) },
1675 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaIfWeWereAllTreesThered) },
1676 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaNobodyYellsAtYouWhenYoure) },
1677 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, IF_FLAG_SET(FLAG_KOLIMA_CURSE_LIFTED), MSGNO(MsgKolimaIfTheHolyTreeAloneCaused) },
1678 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, CONDITION_ALWAYS, MSGNO(MsgKolimaIfICouldSpeakIdTell) },
1679 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgKolimaHowCouldAnyoneTurnAGirl) },
1680 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgKolimaThisIsADreamItHas) },
1681 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, CONDITION_ALWAYS, MSGNO(MsgKolimaBeingUnableToMoveIsSo) },
1682 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, CONDITION_ALWAYS, MSGNO(MsgKolimaIAmOldIveLivedA) },
1683 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, CONDITION_ALWAYS, MSGNO(MsgKolimaItsTheSacredTreesCurseWhy) },
1684 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, CONDITION_ALWAYS, MSGNO(MsgKolimaTheWaterAtMyFeetHuh) },
1685 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, CONDITION_ALWAYS, MSGNO(MsgKolimaIfICantMoveThenMom) },
1686 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgKolimaMaybeIfIMeditateHarderIll) },
1687 { SEARCH(SEARCH_JAR), 100, 0xf57, FIND_ITEM(ITEM_APPLE) },
1688 { SEARCH(SEARCH_JAR), 101, 0xf58, FIND_ITEM(ITEM_HERB) },
1689 { SCENE_EVENTS_END },
1690};
1691
1693 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
1694 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
1696 { EVENT_TALK, 8, CONDITION_ALWAYS, MSGNO(MsgKolimaForAWhileIThoughtNo) },
1697 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, CONDITION_ALWAYS, MSGNO(MsgKolimaYouWouldntUnderstandButItsTruly) },
1698 { SCENE_EVENTS_END },
1699};
1700// clang-format on
1701
1705};
1706
1710 SC_WAIT(10),
1711 SC_FREE,
1712};
1713
1715 SC_ADD(SW_Y, -PIXELS(2)),
1717 SC_WAIT(1),
1718 SC_ADD(SW_Y, -PIXELS(2)),
1720 SC_WAIT(1),
1721 SC_LOOP(30, SC_TOP),
1722 SC_LABEL(1),
1723 SC_ADD(SW_Y, -PIXELS(1)),
1725 SC_WAIT(1),
1726 SC_LOOP(40, SC_TO(1)),
1728 SC_FREE,
1729};
Ability numbers, named from the English release.
@ ABILITY_MIND_READ
Definition ability_ids.h:16
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.
Calls through a function pointer, by argument count.
Character numbers, with each character's Japanese name.
#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
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
FacingObject, the view of an object that turns to face a target.
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)
static s32 Event_OpenMessage(s32 speaker, s32 flags)
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_SanctumOpen(s32 priest)
void Object_SetMode(struct FieldActor *object, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
void Engine_PsynergyBegin(s32 ability, s32 flags)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
#define GameFlag_IsSet
void Engine_CameraSetSpeed(s32 speed, s32 acceleration)
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
static void Camera_SetSpeed(s32 speed, s32 acceleration)
void Engine_PsynergyRaiseHands(void)
s32 Engine_TaskRemoveCallback(void(*callback)(void))
void Engine_PsynergyLowerHands(void)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
#define EMOTE_IN_FRONT
Definition field_event.h:49
#define MAP_CELL_STEP(srcX, srcY, width, height, frames)
Definition field_event.h:59
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ObjectDispatchRelease(struct FieldActor *object)
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)
static void Actor_FaceActor(s32 actor, s32 target, s32 frames)
static void ColorBuffer_ApplyTarget(s32 value, s32 mode)
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)
void Engine_GameFlagSet(s32 flag)
void Engine_CameraWaitForMove(void)
static void Actor_SetActionScript(s32 actor, const s32 *script)
The engine encodes either a built-in action or an action-script address.
void Engine_ActorWaitForMove(s32 actor)
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)
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
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_MapAnimateCells(const u16 *steps, s32 destX, s32 destY)
void Engine_PsynergyPlayEffect(s32 effect)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_ObjectMotionSetPositionAndCommit(s32 actor, s32 x, s32 z)
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_ActorSetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorFaceEachOther(s32 actor, s32 other, s32 frames)
void Engine_EventWait(s32 frames)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
void Engine_PsynergySetTarget(s32 caster, s32 target)
@ ACTOR_LINK_KEEP_MOTION
Definition field_obj.h:148
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
Definition field_obj.h:153
#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 IF_FLAG_SET(flag)
Definition field_scene.h:48
#define SCENE_EXIT(exit, scene, entrance)
Definition field_scene.h:73
@ 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)
@ ACTOR_WANDER
@ ACTOR_STAND
#define SEARCH(target)
#define SCENE_EXITS_END
Definition field_scene.h:77
#define TOUCH_WALKING_INTO(facing)
#define FACING_IS_NORTH(facing)
Definition field_scene.h:38
#define PLACEMENT_SHARE_PREVIOUS_SPRITE
@ 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
The scene service layer: one typed inline for each engine service a scene calls by its own name,...
static void FieldObject_SetTargetAndCallback(s32 object, s32 target, const s32 *actions)
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_KOLIMA_BRIDGE_COLLAPSED
Kolima's bridge fell as the party crossed it.
Definition flags.h:262
#define FLAG_IN_PARTY(character)
Flags 0 to 7: the character with that id (character_ids.h) is in the party (Party_AddActiveOwner).
Definition flags.h:9
#define FLAG_KOLIMA_CURSE_WITNESSED
The party has seen the curse fall, in Kolima or on the forest bridge.
Definition flags.h:260
#define FLAG_KOLIMA_CURSE_LIFTED
Definition flags.h:103
volatile u32 gFrameCount
Frames WaitFrames has finished.
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The work slots of gWorkSlot, read through their own names.
The screen blend's globals and the graphics routines.
Item numbers, named from the English release.
@ ITEM_APPLE
Definition item_ids.h:52
@ ITEM_HERB
Definition item_ids.h:40
static void Kolima_WalkThroughExit(s32 exitId)
Walks the leader northward through the selected exit.
Definition kolima.c:186
s32 gFallingEffectScript[]
Definition kolima.c:1714
static s32 Kolima_ApplyPendingPose(struct ScriptInterpreter *interpreter)
Applies the deferred pose change requested by the falling-effect script.
Definition kolima.c:51
s32 gKolima_RegionScript[]
Definition kolima.c:1707
s32 gKolima_EffectActive
Definition kolima.c:1402
const struct SceneEvent * Kolima_GetEvents(void)
Selects the village or bridge event table.
Definition kolima.c:178
static void Kolima_RecruitDjinni(void)
Lets the village's Djinni join the party.
Definition kolima.c:175
static void Kolima_TalkToHealer(void)
Offers sanctum services to a north-facing leader, or discusses the trees.
Definition kolima.c:161
static void Kolima_RestoreBridgeState(void)
Restores the bridge's villagers and collision after its collapse.
Definition kolima.c:1405
struct SceneEvent gKolimaEvents[]
Definition kolima.c:1649
struct ScenePlacement gKolimaPlacements[]
Definition kolima.c:1573
s32 gKolima_PartyRestoreScaleActions[]
Definition kolima.c:1462
s32 gKolima_FaceLeaderScript[]
Definition kolima.c:1509
static void Kolima_ReadVillagerThoughts(s32 actorId, s32 targetId)
Begins Mind Read on one of the villagers transformed into a tree.
Definition kolima.c:402
s32 gKolima_MiaInParty
Definition kolima.c:1401
static s32 Kolima_UpdateFallingDebris(struct ScriptInterpreter *interpreter)
Moves, enlarges and releases one bridge fragment after its lifetime.
Definition kolima.c:101
s32 gKolima_PartySquashActions[]
Definition kolima.c:1446
s32 gKolima_ProtectiveFieldGrowActions[]
Definition kolima.c:1469
const u32 * Kolima_GetExits(void)
Returns the shared packed exit table.
Definition kolima.c:142
static void Kolima_FinishReadingThoughts(void)
Finishes Mind Read and releases its temporary scene objects.
Definition kolima.c:411
static __inline__ void Kolima_SetProtectiveFieldHeight(s32 actorId, s32 visibleOnOddFrames)
Shows a protective field on its assigned alternating frame.
Definition kolima.c:380
struct ScenePlacement gKolimaPlacements3[]
Definition kolima.c:1641
s32 gKolima_Object26Script[]
Definition kolima.c:1702
struct ScenePlacement gKolima_EntryScript[]
Definition kolima.c:1627
s32 gKolima_ActionTable3[]
Definition kolima.c:1440
static void Kolima_AnimateSwitchOrExit(void)
Animates the touched map cells or leaves through the southern exit.
Definition kolima.c:196
const struct ScenePlacement * Kolima_GetPlacements(void)
Selects placements and applies tree sprites while the villagers are cursed.
Definition kolima.c:145
s32 gKolima_ActionTable1[]
Definition kolima.c:1428
static void Kolima_InitializeCursedVillagers(struct ScenePlacement *placements)
Replaces the nine villagers' placement sprites with their cursed trees.
Definition kolima.c:80
struct ScenePlacement gKolimaPlacements1[]
Definition kolima.c:1577
static s32 Kolima_UpdateTimedAppearance(struct ScriptInterpreter *interpreter)
Alternates an ambient actor's child appearance with a random timer.
Definition kolima.c:61
s32 gKolima_EntryActions[]
Definition kolima.c:1494
struct SceneEntrance gKolimaEntrances3[]
Definition kolima.c:1535
static __inline__ void Kolima_NodTogether(void)
Gives the four companions the same nod, waiting on the final actor.
Definition kolima.c:418
s32 gKolima_ProtectiveFieldShrinkActions[]
Definition kolima.c:1482
u32 gKolimaExits[]
Definition kolima.c:1554
struct SceneEvent gKolimaEvents3[]
Definition kolima.c:1692
struct SceneEntrance gKolimaEntrances[]
Definition kolima.c:1520
const struct SceneEntrance * Kolima_GetEntrances(void)
Selects the entrance table for the village, interior or bridge.
Definition kolima.c:121
struct SceneEntrance gKolimaEntrances2[]
Definition kolima.c:1541
static void Kolima_ShowBridgeCollapse(void)
Shows the villager's crossing and the bridge collapsing into debris.
Definition kolima.c:235
s32 gKolima_PendingPose
Definition kolima.c:1400
static s32 Kolima_TriggerRegionScript(struct ScriptInterpreter *interpreter)
Triggers a temporary pose when an effect enters the party's occupied area.
Definition kolima.c:1373
static void Kolima_SpawnCurseSparkle(void)
Spawns a moving curse sparkle every eighth frame.
Definition kolima.c:1334
s32 gKolima_DebrisScript[]
Definition kolima.c:1504
u16 gKolima_SwitchCells[]
Definition kolima.c:1514
static void Kolima_WitnessForestCurse(void)
Shows the forest's curse, the party's protective Psynergy and the trees' appeal.
Definition kolima.c:427
static void Kolima_FaceActorAndWait(s32 actorId, s32 facing, s32 waitFrames)
Turns an actor immediately, then leaves time for the next scene beat.
Definition kolima.c:1326
static void Kolima_ShowMessageAndWait(s32 actorId, s32 waitFrames)
Shows the selected dialogue through an actor, then holds for its reaction.
Definition kolima.c:1320
static void Kolima_AlternateProtectiveFieldHeights(void)
Alternates the four protective sprites between visible and hidden heights.
Definition kolima.c:394
s32 gKolima_ActionTable2[]
Definition kolima.c:1434
const struct SceneRegion * Kolima_GetRegions(void)
Returns the interior's regions; the other maps have none.
Definition kolima.c:134
struct SceneRegion gKolimaRegions2[]
Definition kolima.c:1548
s32 Kolima_Initialize(void)
Restores the current map and plays the first visit to cursed Kolima.
Definition kolima.c:320
The globals Kolima's scenes share: the falling effect and the party's state.
Kolima, its forest bridge and the forest's tree: an effect (object 26) that stretches as it travels.
static s32 SceneEffect_AdvanceAngleUntilIdle(struct ScriptInterpreter *interpreter)
An object script call: widen the object by 0x1eb8 (about 0.12) a frame, and release it once it has re...
Definition kolima_grow.h:11
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
#define SC_LABEL(n)
Branch destination.
Definition objcmd.h:11
#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_SYNC
Wait for arrival.
Definition objcmd.h:17
#define SC_FOREVER
Definition objcmd.h:14
#define SC_TO(n)
Definition objcmd.h:12
#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
@ SW_SCALE_Y
Definition objcmd.h:63
@ SW_COLLISION
Definition objcmd.h:79
@ SW_Z
Definition objcmd.h:60
@ SW_FACING
Definition objcmd.h:57
@ SW_Y
Definition objcmd.h:59
@ SW_SCALE_X
Definition objcmd.h:62
#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 BattleEffect_CleanupSceneObjects(void)
Ends a Psynergy effect: frees the effect slots still in use and, unless another effect is being resol...
Definition setup.c:110
ObjectRuntime, a field object's runtime state, and the object snapshots.
Palette fades, the battle effect palette buffers and the colour channel curves.
@ PALETTE_TRANSFORM_PLAIN
each colour unchanged
Definition palbuf.h:72
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_Kolima1
char SceneId_Kolima2
char SceneId_Kolima3
The field object script interpreter and the operands its commands read.
Song and sound effect ids, indices into gSound_SongTable.
#define SE_220
Definition songs.h:215
#define SE_DOOR_OPEN
Definition songs.h:153
#define SE_106
Definition songs.h:99
#define SE_206
Definition songs.h:201
#define MUS_017
Definition songs.h:27
#define MUS_021
Definition songs.h:31
#define SE_198
Definition songs.h:193
#define SE_188
Definition songs.h:183
#define SE_200
Definition songs.h:195
#define SE_176
Definition songs.h:171
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
void Engine_ActorShowEmote()
void Engine_TaskWait()
void Engine_EventSetMessage()
void Engine_EventShowMessage()
#define NULL
Definition bilibin.h:6
void Kolima_UpdateCurseDust(void)
A scene callback: every eighth frame a speck (object 285, its script gFallingEffectScript) starts 160...
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
u16 priority
2 when created
Definition animspr.h:100
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
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
s32 velocityZ
16.16 fixed-point pixels per frame
Definition field_obj.h:54
s16 entrance
Definition game_state.h:37
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
u8 talkFacing
enum ActorTalkFacing; 3 follows the leader afterwards
Definition field_scene.h:95
s16 sprite
The actor's sprite; 0 to 7 are the party's characters, each in its own actor slot,...
Definition field_scene.h:84
s32 behavior
A built-in action (enum ActorBehavior, 1 to 7) or an action script, for ObjectMotion_SetActionCallbac...
Definition field_scene.h:90
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
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels