Alchemy
Loading...
Searching...
No Matches

fuchin_temple.c

Go to the documentation of this file.
1/// @file
2/// Fuchin Temple and the rooms that share its overlay: the temple grounds with
3/// the waterfall grotto, Nyunpa's hall, Master Feh's school in Xian and Master
4/// Hama's room in Lama Temple.
5#include "game_state.h"
6#include "scene_ids.h"
12#include "field_obj.h"
13#include "script.h"
14#include "types.h"
15#include "field_event.h"
16#include "engine_call.h"
17#include "field_scene.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 "call.h"
28#include "text/msg_ids.h"
29#include "ability_ids.h"
30#include "flags.h"
31#include "songs.h"
32#include "event.h"
33#include "item_ids.h"
34#include "objcmd.h"
35#include "global_cells.h"
36
37// Place flags: Scene_ResetFlagsOnEnter clears 0x300 to 0x3ff when the party
38// enters another place group, and other places use the numbers for their own.
39
40/// Nyunpa's test was declined; the students saw the training tree fall.
41#define FLAG_NYUNPA_TEST_DECLINED 0x300
42#define FLAG_FEH_SCHOOL_SAW_TREE_FALL 0x301
43
44// The first scene, outside the temple.
45#define FALLS_MONK 9 ///< the monk beneath the falls, at the waterfall grotto
46#define HEALER 13
47
48// The second scene: Nyunpa's hall and Master Feh's school.
49#define NYUNPA 8
50#define JUMPING_STUDENT 12
51#define FEIZHI 17
52#define FEH 18
53#define TRAINING_TREE 19
54#define TRAINING_TREE_TARGET 20 ///< where Force strikes the tree
55
56/// The second scene by entrance 3: Hama's room in Lama Temple.
57#define HAMA 8
58
59static void FuchinTemple_FeizhiLeavesForHsu(void);
60static void FuchinTemple_FehSeesChi(void);
61static UNUSED void FuchinTemple_HopLeaderByOffset(s32 offsetX, s32 offsetZ);
62static void FuchinTemple_BeginMindReadDemonstration(s32 caster, s32 target);
65static void FuchinTemple_AnimateRevealLesson(void);
66
67// Shared source, included in link order.
69#include "common/effect_spawn.h"
70
71/// Clears the scripted actor's sprite flags and completes the script command.
73 struct ScriptInterpreter *interpreter) {
74 Engine_ActorSetSpriteFlags((struct FieldActor *)interpreter, 0);
75 return 0;
76}
77
78// Keep an actor facing the party leader while the conversation is staged.
79// UB: update hooks return void. The native produces an unused zero result;
80// plain void changes five instructions in the English build.
81#ifdef UBFIX
82static void FuchinTemple_FaceLeader(union FieldObject *object) {
83#else
85#endif
86 struct FieldActor *actor = (struct FieldActor *)object;
88 actor->facing = ArcTan2(player->z.fixed - actor->z.fixed,
89 player->x.fixed - actor->x.fixed);
90#ifndef UBFIX
91 return 0;
92#endif
93}
94
95/// Chooses the outside entrance table or the shared interior entrances.
96const struct SceneEntrance *Scene_GetEntrances(void) {
97 s16 scene = gGameState.scene;
98
99 if (scene == (s32)&SceneId_FuchinTemple1) {
101 }
103}
104
105const struct SceneRegion *Scene_GetRegions(void) { return NULL; }
106
107const u32 *Scene_GetExits(void) { return gFuchinTempleExits; }
108
109/// Selects the room's actors and applies the post-lesson placement changes.
113 }
114 if (gGameState.entrance == 3) {
116 }
117 // Once Hsu is known to be trapped, the tree and two students are gone, and
118 // another student stands elsewhere.
122 gFuchinTemplePlacements[8].x = 0x1200000;
123 gFuchinTemplePlacements[8].z = 0xf80000;
126 }
129}
130
131/// Talking to the visitor from Kolima outside the temple: he asks how the
132/// party got here. "How did you get here? Is the bridge open again?" Yes
133/// cheers him ("Then I can go home to Kolima now?") and is remembered; no
134/// means the party came through the forest. Later talks go on to the tale of
135/// the forest.
137 EV_BEGIN();
138 MESSAGE_SET(MsgXianHowDidGetHereBridge);
140 gEventWork->message += 4;
141 }
142 Event_OpenMessage(8, 0);
143 if (Engine_EventChooseYesNo(0, 0) == 0) {
145 } else {
147 }
148 Event_ShowMessage(8, 0);
149 EV_END();
150}
151
152/// Talking to the monk (actor 12) outside the temple: he speaks of the one
153/// seeking enlightenment, with up to two more questions. "Isn't it noble of him
154/// to try to save the world by becoming enlightened?" Once Nyunpa is gone,
155/// "Now, he truly is beyond the world's concerns. Is he watching over us?"
156static void Event_MonkSpeaksOfNyunpa(void) {
157
158 EV_BEGIN();
160 MESSAGE_SET(MsgXianNowHeTrulyBeyondWorlds);
162 EV_END();
163 } else {
164 MESSAGE_SET(MsgXianIsntNobleHimTrySave);
165 MESSAGE_OPEN(12, 0);
166 if (Engine_EventChooseYesNo(0, 0) == 1) {
168 MESSAGE_OPEN(12, 0);
169 if (Engine_EventChooseYesNo(0, 0) == 1) {
171 }
172 }
173 MESSAGE_PUT(12, 0);
174 EV_END();
175 }
176}
177
178/// Talking to the monk beneath the falls once Nyunpa has offered the test: he
179/// lets the party pass. "I have already heard of your test from Master Nyunpa.
180/// You may enter." He leaps aside, and the way into the waterfall grotto opens.
182 struct FieldActor *monk;
183 struct FieldActor *movingMonk;
184 struct EffectOptions options;
185
187 EV_BEGIN();
188 MESSAGE_SET(MsgXianAlreadyHeardTest);
190 // The monk leaps aside and lands in a puff of dust.
194 movingMonk = Object_GetById(FALLS_MONK);
195 movingMonk->velocityY = 0x140000;
196 movingMonk = Object_GetById(FALLS_MONK);
197 movingMonk->gravity = 0x40000;
198 OBJ_SPEED(FALLS_MONK, PIXELS(3), 3 * PIXELS(1) / 2);
201 movingMonk = Object_GetById(FALLS_MONK);
202 movingMonk->gravity = 0x10000;
205 // Only the palette option is enabled for these three particles.
206 options.palette = 7;
207 Effect_Spawn(monk->x.fixed, monk->y.fixed, (monk->z.fixed + 0x40000), 0x8000,
208 0, 0, EFFECT_USE_PALETTE, &options);
209 Effect_Spawn(monk->x.fixed, monk->y.fixed, (monk->z.fixed + 0x40000), 0, 0, 0,
210 EFFECT_USE_PALETTE, &options);
211 Effect_Spawn(monk->x.fixed, monk->y.fixed, (monk->z.fixed + 0x40000), -0x8000,
212 0, 0, EFFECT_USE_PALETTE, &options);
213 WAIT(30);
215 Map_CopyCellAttributes(10, 24, 1, 1, 10, 22);
217 EV_END();
218}
219
220/// Coming back out of the grotto (trigger 5), Isaac is sent on to Nyunpa and
221/// the way back is open again. "Young master, did you complete the test?" Then
222/// "Master Nyunpa is waiting for you... Proceed to the temple."
224 EV_BEGIN();
227 WAIT(10);
228 MESSAGE_SET(MsgXianYoungMasterDidCompleteTest);
230 WAIT(20);
233 WAIT(10);
237 WAIT(20);
241 WAIT(20);
243 Map_CopyCellAttributes(10, 26, 1, 1, 10, 24);
244 EV_END();
245}
246
247/// Talking to Nyunpa, or reading his mind: he reads the party's mind in turn,
248/// guesses that they follow Saturos's group, warns of Mogall Forest and offers
249/// the test of the grotto. "Mmmm... Who is that? Who speaks to my mind?"
250/// Accepting it, he sends Isaac to the monk beneath the falls; refusing is
251/// remembered, and the next talk asks again.
252static void Event_NyunpaOffersTest(void) {
253 s32 alreadyDeclinedTrial;
254 struct FieldActor *nyunpa;
255
256 EV_BEGIN();
257 // Revisit an earlier refusal, or introduce the offer through Mind Read.
258 alreadyDeclinedTrial = FLAG_CHECK(FLAG_NYUNPA_TEST_DECLINED);
259 if (alreadyDeclinedTrial != 0) {
261 WAIT(5);
264 SE(SE_JUMP);
265 nyunpa = Actor_Get(NYUNPA);
266 nyunpa->velocityY = 0x80000;
268 WAIT(30);
269 MESSAGE_SET(MsgXianMustSurviveTestGrottoBefore);
270 } else {
271 MESSAGE_SET(MsgXianMmmmWhoWhoSpeaksMy);
273 WAIT(30);
276 WAIT(20);
278 WAIT(5);
280 SE(SE_JUMP);
281 Object_GetById(NYUNPA)->paused = alreadyDeclinedTrial;
282 nyunpa = Actor_Get(NYUNPA);
283 nyunpa->velocityY = 0x80000;
285 WAIT(30);
287 if (Engine_EventChooseYesNo(0, 0) == 1) {
289 WAIT(20);
291 WAIT(20);
293 WAIT(30);
295 WAIT(50);
297 WAIT(30);
300 } else {
301 gEventWork->message += 2;
303 }
305 WAIT(30);
307 MESSAGE_SET(MsgXianFollowThemDoNot);
309 if (Engine_EventChooseYesNo(0, 0) == 1) {
310 OBJ_EMOTE(NYUNPA, 0x105, 60);
312 WAIT(30);
314 WAIT(50);
316 WAIT(30);
318 gEventWork->message += 1;
319 } else {
320 gEventWork->message += 1;
321 WAIT(20);
323 WAIT(20);
325 }
326 WAIT(20);
328 WAIT(20);
331 WAIT(20);
333 WAIT(20);
335 OBJ_SPEED(NYUNPA, 3 * PIXELS(1) / 10, 3 * PIXELS(1) / 20);
336 Actor_WalkToAndWait(NYUNPA, 168, 464);
337 WAIT(60);
340 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x102, 60);
341 Actor_WalkToAndWait(NYUNPA, 168, 472);
342 }
344 if (Engine_EventChooseYesNo(0, 0) == 1) {
345 MESSAGE_SET(MsgXianThenCannotTellGiveUp);
348 } else {
349 // "Do not worry. You will be permitted to enter the grotto." Nyunpa
350 // glows as he calls to the monk.
351 MESSAGE_SET(MsgXianDoNotWorryWillPermitted);
352 WAIT(30);
354 WAIT(20);
355 Camera_SetSpeed(0x8000, 0x1000);
357 ColorBuffer_ApplySource(0x10000, 0);
358 ColorBuffer_ApplyTarget(0x10003, 1);
363 ColorBuffer_ApplyTarget(0x10000, 0);
367 WAIT(20);
371 WAIT(60);
374 }
375 OBJ_MODE(NYUNPA, 5);
376 EV_END();
377}
378
379/// Reading Nyunpa's mind once the test is accepted: he notices.
380/// "You enjoy reading the minds of others, do you not?"
381static void Event_NyunpaFeelsMindRead(void) {
382 EV_BEGIN();
383 MESSAGE_SET(MsgXianEnjoyReadingMindsOthersDo);
385 EV_END();
386}
387
388/// Talking to the student at the door (actor 9): the student asks whether the
389/// party came to watch. "This is Master Feh's school... You came to watch?"
391 EV_BEGIN();
392 MESSAGE_SET(MsgXianMasterFehsSchoolCameWatch);
394 EV_END();
395}
396
397/// Talking to the student who practises jumping: he lands, talks about jumping
398/// (or Lama Temple, or Hsu), then jumps on.
399static void Event_TalkToJumpingStudent(void) {
400 EV_BEGIN();
401
403
404 while (Object_GetById(JUMPING_STUDENT)->y.fixed > 0) {
406 }
407
409
411
413
415
417
419 MESSAGE_SET(MsgXianHsuDidNotPracticeJumping);
420 } else if (Engine_GameFlagIsSet(FLAG_FEH_SAW_CHI) != 0) {
421 MESSAGE_SET(MsgXianLamaTempleFarWestIn);
422 } else {
423 MESSAGE_SET(MsgXianFlexibilityJumpingVeryImportantIn);
424 }
425
427
429
431
433 EV_END();
434}
435
436/// Talking to the student by the training tree (actor 15): the student asks
437/// whether the party still wishes to see Master Feh. "Master Feh is very busy.
438/// Do you still wish to see him?" Yes: if the tree falls to Chi from the line,
439/// he will take the party to Feh.
440static void Event_StudentAsksAboutFeh(void) {
441 EV_BEGIN();
442 MESSAGE_SET(MsgXianMasterFehVeryBusyDo);
444 EV_END();
445}
446
447/// Rotates the training tree through its westward arc and scatters particles.
450 u32 turnStep;
451 s32 angle;
452
453 for (turnStep = 8; turnStep > 3; turnStep--) {
454 angle = turnStep << 12;
455 tree->sprite->rotation = angle;
456 Engine_TaskWait((turnStep - 4) * 2);
457 tree->x.fixed += Engine_MathCos(angle) * 6;
458 tree->z.fixed += Engine_MathSin(angle) * 6;
459 }
460
461 tree->y.fixed = 0x120000;
462 tree->targetY = 0x120000;
463
465
466 Effect_Spawn(tree->x.fixed - 0xc0000, tree->y.fixed, tree->z.fixed + 0x80000,
467 0xffffcccd, 0x6666, 0, 0, 0);
468 Effect_Spawn(tree->x.fixed, tree->y.fixed, tree->z.fixed + 0x80000,
469 0xffff3334, 0x4ccc, 0, 0, 0);
470 Effect_Spawn(tree->x.fixed + 0xa0000, tree->y.fixed, tree->z.fixed + 0x80000,
471 0xffff0000, 0x3333, 0, 0, 0);
472}
473
474/// Rotates the training tree through the opposite arc and reverses its
475/// horizontal scale.
477 struct FieldActor *tree;
478 u32 turnStep;
479 s32 angle;
480
482 for (turnStep = 8; turnStep <= 12; turnStep++) {
483 angle = turnStep << 12;
484 tree->sprite->rotation = angle;
485 Engine_TaskWait((12 - turnStep) * 2);
486 tree->x.fixed -= Engine_MathCos(angle) * 6;
487 tree->z.fixed -= Engine_MathSin(angle) * 6;
488 }
489 tree->y.fixed = 0x120000;
490 tree->targetY = 0x120000;
491 tree->scaleX = 0xffff3334;
493 Effect_Spawn(tree->x.fixed - 0xc0000, tree->y.fixed, tree->z.fixed + 0x80000,
494 0x10000, 0x3333, 0, 0, 0);
495 Effect_Spawn(tree->x.fixed, tree->y.fixed, tree->z.fixed + 0x80000, 0xcccc,
496 0x4ccc, 0, 0, 0);
497 Effect_Spawn(tree->x.fixed + 0xa0000, tree->y.fixed, tree->z.fixed + 0x80000,
498 0x3333, 0x6666, 0, 0, 0);
499}
500
501/// Slides the training tree north in four steps, then scatters particles.
504 u32 stepIndex = 0;
505 s32 delay = 8;
506 u8 rotation;
507 do {
508 Engine_TaskWait(delay);
509 tree->z.fixed += 0xffff0000;
510 tree->targetZ = ACTOR_NO_TARGET;
511 stepIndex++;
512 delay -= 2;
513 } while (stepIndex < 4);
514 rotation = 0;
515 tree->sprite->rotation = rotation;
517 Effect_Spawn(tree->x.fixed, tree->y.fixed, tree->z.fixed + 0xfff80000,
518 0xffff3334, 0, 0xffffcccd, 0, 0);
519 Effect_Spawn(tree->x.fixed, tree->y.fixed, tree->z.fixed + 0xfff80000,
520 0x0000cccc, 0, 0xffffcccd, 0, 0);
521 Effect_Spawn(tree->x.fixed + 0xfffa0000, tree->y.fixed,
522 tree->z.fixed + (160 << 12), 0x00003333, 0, 0xffff0000, 0, 0);
523 Effect_Spawn(tree->x.fixed + (192 << 11), tree->y.fixed,
524 tree->z.fixed + (160 << 12), 0x00003333, 0, 0xffff0000, 0, 0);
525}
526
527/// Slides the training tree south in four steps before the final displacement.
529 struct FieldActor *tree;
530 u32 stepIndex;
531 s32 particleSpeed;
532 s32 delay;
533
535 stepIndex = 0;
536 delay = 8;
537 do {
538 Engine_TaskWait(delay);
539 tree->z.fixed += 0x10000;
540 tree->targetZ = ACTOR_NO_TARGET;
541 stepIndex++;
542 delay -= 2;
543 } while (stepIndex < 4);
544
545 tree->sprite->rotation = 0;
546 tree->z.fixed += 0x180000;
547 tree->targetZ = ACTOR_NO_TARGET;
549
550 Effect_Spawn(tree->x.fixed, tree->y.fixed, tree->z.fixed + 0xc0000, -0xcccc,
551 0, 0x3333, 0, 0);
552 particleSpeed = 0x3333;
553 Effect_Spawn(tree->x.fixed, tree->y.fixed, tree->z.fixed + 0xc0000, 0xcccc, 0,
554 particleSpeed, 0, 0);
555 Effect_Spawn(tree->x.fixed - 0x60000, tree->y.fixed, tree->z.fixed - 0x80000,
556 particleSpeed, 0, 0x10000, 0, 0);
557 Effect_Spawn(tree->x.fixed + 0x60000, tree->y.fixed, tree->z.fixed - 0x80000,
558 particleSpeed, 0, 0x10000, 0, 0);
559}
560
561/// Routes the student around the tree according to the leader's facing.
563 u32 leaderFacing;
564 u32 quadrantLimit;
565
567 quadrantLimit = 0x3fff;
568 if (((leaderFacing + -0x2000) << 16) <= 0x3fff0000) {
569 Engine_ActorWalkToAndWait(15, 216, 168);
570 Engine_ActorWalkToAndWait(15, 224, 168);
571 OBJ_DIR(15, FACING_SOUTHEAST, 20);
572 } else if ((u16)(leaderFacing - 0x6000) <= quadrantLimit) {
573 Engine_ActorWalkToAndWait(15, 232, 160);
575 } else if ((u16)(leaderFacing + 0x6000) <= quadrantLimit) {
576 Engine_ActorWalkToAndWait(15, 216, 168);
577 Engine_ActorWalkToAndWait(15, 224, 172);
578 OBJ_DIR(15, FACING_NORTHEAST, 20);
579 } else {
580 Engine_ActorWalkToAndWait(15, 232, 160);
581 OBJ_DIR(15, FACING_SOUTHEAST, 20);
582 }
583}
584
585/// The student by the tree explains the rules: mode 0 when Psynergy felled it
586/// but not from the line, 1 when Isaac pushed it by hand, 2 to praise a
587/// warrior Feh has already seen. Then he sets the tree up again.
589 s32 rulesMessage;
590
591 OBJ_SPEED(15, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
592 WAIT(60);
593 rulesMessage = MsgXianCannotPushHands;
594 MESSAGE_SET(rulesMessage);
595 if (mode == 0) {
596 MESSAGE_SET(rulesMessage - 1);
597 OBJ_EMOTE(15, 0x101, 60);
600 MESSAGE_SET(MsgXianWarriorsCannotUse);
603 WAIT(20);
606 WAIT(20);
607 }
608 if (mode == 2) {
609 MESSAGE_SET(MsgXianGreatWarriorTrain);
611 WAIT(20);
612 }
614 // Restore the tree and let the student return to the demonstration spot.
617 OBJ_POS_SET(TRAINING_TREE, 232, 168);
622 Object_GetById(TRAINING_TREE)->sprite->rotation = 0x8000;
624 WAIT(40);
625 Engine_ActorWalkToAndWait(15, 216, 152);
626 OBJ_DIR(15, FACING_SOUTHEAST, 30);
627}
628
629/// The students see the tree fall, Feh doubts it came from the line, and the
630/// student sets the tree up again. "Look! The tree fell."
632 struct FieldActor *tree;
633
634 OBJ_FACE(13, TRAINING_TREE, 0);
635 OBJ_FACE(14, TRAINING_TREE, 0);
636 OBJ_FACE(15, TRAINING_TREE, 0);
637 OBJ_FACE(16, TRAINING_TREE, 0);
639 WAIT(20);
641 WAIT(20);
642 MESSAGE_SET(MsgXianLookTreeFell);
645 OBJ_EMOTE(FEH, 0x105, 60);
646 OBJ_EMOTE(16, 0x101, 60);
649 WAIT(20);
651 OBJ_EMOTE(16, 0x102, 60);
654 WAIT(20);
656 WAIT(20);
658 WAIT(20);
659 // Reset the tree after the group has reacted to the demonstration.
660 OBJ_SPEED(15, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
663 OBJ_POS_SET(TRAINING_TREE, 232, 168);
666 tree->y.fixed = 0xc0000;
668 tree->targetY = ACTOR_NO_TARGET;
670 tree->scaleX = 0xcccc;
672 {
673 struct AnimationObject *sprite = tree->sprite;
674 s32 rotation = 0x8000;
675
676 sprite->rotation = rotation;
677 }
679 WAIT(40);
680 Engine_ActorWalkToAndWait(15, 216, 152);
681 OBJ_DIR(15, FACING_SOUTH, 30);
683}
684
685/// Move on the training tree: it topples, and the students react.
686static void Event_MoveTree(void) {
687 EV_BEGIN();
688
689 if (Object_GetById(ACTOR_PARTY_LEADER)->facing > (128 << 7) &&
690 Object_GetById(ACTOR_PARTY_LEADER)->facing < (192 << 8)) {
692 } else {
694 }
695
698 } else {
700 }
701
702 EV_END();
703}
704
705/// Walking into the training tree: Isaac pushes it over by hand. "You cannot
706/// push it with your hands. Attack it with Chi."
707static void Event_PushTreeByHand(void) {
709 u16 facing;
710
711 EV_BEGIN();
713 WAIT(20);
714
715 facing = leader->facing;
716
717 if ((u16)(facing - 0x2000) <= 0x3fffu) {
719 } else if ((u16)(facing - 0x6000) <= 0x3fffu) {
721 } else if ((u16)(facing + (192 << 7)) <= 0x3fffu) {
723 } else {
725 }
726
729 EV_END();
730}
731
732/// Force on the training tree: it topples. From too close it does not count;
733/// from the line, the students call Feh out the first time, and later Feh
734/// himself sees it.
735static void Event_ForceTree(void) {
737 u16 facing;
738
739 EV_BEGIN();
740
741 facing = leader->facing;
742 if ((u16)(facing - 0x2000) <= 0x3fff) {
744 } else if ((u16)(facing - 0x6000) <= 0x3fff) {
746 } else if ((u16)(facing + 0x6000) <= 0x3fff) {
748 } else {
750 }
751
752 Engine_CameraSetSpeed(0x10000, 0x2000);
755
756 if (leader->z.part.pixel <= 209) {
760 } else {
762 }
763 EV_END();
764 return;
765 }
766
771 } else {
773 }
774 EV_END();
775}
776
777/// The first time the tree falls from the line, a student runs for Master Feh.
778/// "What did you do, warrior?" The door opens on its own and Feizhi storms
779/// out, sure that Hsu is in danger. Feh will not believe her visions, and she
780/// leaves alone to find Hsu. Feh then asks Isaac to show him his Chi.
782 struct FieldActor *actor;
783
785 WAIT(30);
789 WAIT(20);
793 WAIT(60);
794 MESSAGE_SET(MsgXianDidDoWarrior);
795 Event_ShowMessageAndWait(13, 0, 20);
798 WAIT(20);
799 Event_ShowMessageAndWait(15, 0, 20);
802 WAIT(20);
804 Event_AskYesNo(16, 0);
805 WAIT(50);
806 // Bring the observers out through the school door.
808 OBJ_SPEED(16, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
809 Actor_WalkToAndWait(16, 176, 248);
810 Actor_WalkToAndWait(16, 308, 248);
812 OBJ_DIR(16, FACING_NORTH, 20);
816 WAIT(20);
817 OBJ_SPEED(16, 3 * PIXELS(1) / 2, 3 * PIXELS(1) / 4);
818 actor = Object_GetById(16);
820 Actor_WalkToAndWait(16, 308, 272);
821 WAIT(1);
822 actor = Actor_Get(16);
823
825 Event_ShowMessageAndWait(16, 0, 50);
826 OBJ_POS_SET(FEIZHI, 304, 216);
827 Actor_WalkToAndWait(FEIZHI, 304, 248);
828 Actor_FaceActor(9, FEIZHI, 0);
829 Actor_FaceActor(10, FEIZHI, 0);
830 Actor_FaceActor(11, FEIZHI, 0);
832 Actor_FaceActor(13, FEIZHI, 0);
833 Actor_FaceActor(14, FEIZHI, 0);
834 Actor_FaceActor(15, FEIZHI, 0);
835 Actor_FaceActor(16, FEIZHI, 0);
837 WAIT(10);
846 OBJ_EMOTE(FEIZHI, 0x103, 60);
847 OBJ_POS_SET(FEH, 304, 216);
848 OBJ_WALK(FEH, 304, 248);
849 OBJ_WALK(FEIZHI, 280, 264);
853 SE(SE_159);
856 Actor_FaceActor(9, FEIZHI, 0);
857 Actor_FaceActor(10, FEIZHI, 0);
858 Actor_FaceActor(11, FEIZHI, 0);
860 Actor_FaceActor(13, FEIZHI, 0);
861 Actor_FaceActor(14, FEIZHI, 0);
862 Actor_FaceActor(15, FEIZHI, 0);
863 Actor_FaceActor(16, FEIZHI, 0);
865 WAIT(10);
867 WAIT(20);
869 WAIT(20);
872 WAIT(20);
874 WAIT(20);
878 OBJ_EMOTE(FEH, 0x102, 60);
881 WAIT(20);
884 WAIT(20);
887 WAIT(20);
889 WAIT(20);
892 WAIT(20);
895 OBJ_DIR(16, FACING_WEST, 20);
897 WAIT(20);
899 WAIT(20);
902 WAIT(20);
903 Event_ShowMessageAndWait(16, 0, 20);
907 WAIT(20);
908 Event_ShowMessageAndWait(9, 0, 20);
911 WAIT(20);
913 OBJ_EMOTE(FEH, 0x102, 60);
915 OBJ_EMOTE(FEIZHI, 0x101, 60);
918 WAIT(20);
923 WAIT(20);
924 OBJ_EMOTE(FEIZHI, 0x103, 60);
929 WAIT(20);
932 WAIT(20);
935 WAIT(10);
936 Actor_WalkToAndWait(FEIZHI, 256, 280);
938 OBJ_POS_SET(FEIZHI, 0, 0);
940 WAIT(30);
942 WAIT(20);
943 Event_ShowMessageAndWait(9, 0, 20);
945 WAIT(20);
946 Event_ShowMessageAndWait(15, 0, 20);
947 Actor_FaceActor(16, FEH, 0);
948 WAIT(20);
950 WAIT(20);
951 Event_ShowMessageAndWait(16, 0, 20);
952 Actor_FaceActor(FEH, 16, 0);
953 WAIT(20);
956 WAIT(20);
959 WAIT(20);
961 OBJ_SPEED(FEH, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
962 Actor_WalkToAndWait(FEH, 256, 248);
966 Actor_WalkToAndWait(FEH, 240, 184);
968 WAIT(20);
969 OBJ_POS_SET(TRAINING_TREE, 232, 168);
971 // Restore the tree before leaving the group ready for another demonstration.
972 actor = Actor_Get(TRAINING_TREE);
973 actor->y.fixed = 0xc0000;
974 actor = Actor_Get(TRAINING_TREE);
975 actor->targetY = ACTOR_NO_TARGET;
976 actor = Actor_Get(TRAINING_TREE);
977 actor->scaleX = 0xcccc;
978 actor = Actor_Get(TRAINING_TREE);
979 {
980 struct AnimationObject *sprite = actor->sprite;
981 s32 rotation = 0x8000;
982
983 sprite->rotation = rotation;
984 }
985 SE(SE_124);
988 Actor_WalkToAndWait(16, 256, 240);
991 Event_ShowMessageAndWait(16, 0, 20);
1001 WAIT(20);
1003 Actor_WalkToAndWait(FEH, 248, 208);
1006 if (Engine_EventChooseYesNo(0, 0) == 0) {
1008 WAIT(20);
1009 Event_ShowMessageAndWait(16, 0, 20);
1011 } else {
1013 WAIT(20);
1014 OBJ_EMOTE(FEH, 0x105, 60);
1015 OBJ_DIR(FEH, FACING_SOUTH, 20);
1017 WAIT(20);
1018 Event_OpenMessage(16, 0);
1019 if (Engine_EventChooseYesNo(0, 0) == 0) {
1021 WAIT(20);
1025 } else {
1027 WAIT(20);
1029 WAIT(20);
1032 }
1033 }
1034 OBJ_DIR(10, FACING_WEST, 0);
1035 OBJ_DIR(11, FACING_WEST, 20);
1036 OBJ_MODE(10, 5);
1037 OBJ_MODE(11, 5);
1039}
1040
1041/// Talking to Feh after the party declined: he asks again to see Isaac's Chi.
1042/// "Warrior, will you show me your Chi?"
1043static void Event_FehAsksToSeeChi(void) {
1044
1045 EV_BEGIN();
1046 MESSAGE_SET(MsgXianWarriorWillShowMeYour);
1047 MESSAGE_OPEN(FEH, 0);
1048
1049 if (Engine_EventChooseYesNo(0, 0) == 0) {
1050 WAIT(20);
1053 EV_END();
1054 } else {
1055 gEventWork->message += 1;
1057 EV_END();
1058 }
1059}
1060
1061/// The tree falls from the line with Feh watching, but Feh sees that it is not
1062/// Chi. "Ya! The tree fell!" He asks whether the party has been to Fuchin
1063/// Temple, and the school goes back to its training.
1064static void FuchinTemple_FehSeesChi(void) {
1065 struct FieldActor *actor;
1066
1067 // Stop the temporary facing hooks while the group reacts to the tree.
1068 actor = Actor_Get(FEH);
1069 actor->update = 0;
1070 actor = Object_GetById(13);
1071 actor->update = 0;
1072 actor = Object_GetById(14);
1073 actor->update = 0;
1074 actor = Object_GetById(15);
1075 actor->update = 0;
1076 actor = Actor_Get(16);
1077 actor->update = 0;
1078 OBJ_MODE(11, 1);
1079 Camera_SetSpeed(0x8000, 0x1000);
1080 Camera_MoveTo(PIXELS(232), -1, PIXELS(200), 1);
1082 // Continue the Chi discussion with the students gathered around the tree.
1083 MESSAGE_SET(MsgXianYaTreeFell);
1084 OBJ_SPEED(10, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1085 OBJ_SPEED(JUMPING_STUDENT, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1086 OBJ_WALK(10, 152, 200);
1096 OBJ_SPEED(10, 3 * PIXELS(1) / 2, 3 * PIXELS(1) / 4);
1098 OBJ_WALK(10, 152, 200);
1104 WAIT(20);
1106 Actor_FaceActor(9, FEH, 0);
1107 Actor_FaceActor(10, FEH, 0);
1111 Actor_FaceActor(14, FEH, 0);
1112 Actor_FaceActor(15, FEH, 0);
1113 Actor_FaceActor(16, FEH, 0);
1114 WAIT(20);
1115 Event_ShowMessageAndWait(16, 0, 20);
1117 WAIT(20);
1119 WAIT(20);
1120 Event_ShowMessageAndWait(16, 0, 20);
1121 OBJ_EMOTE(FEH, 0x105, 60);
1122 OBJ_EMOTE(16, 0x101, 60);
1123 Event_ShowMessageAndWait(16, 0, 20);
1125 OBJ_EMOTE(16, 0x102, 60);
1126 OBJ_EMOTE(15, 0x101, 60);
1127 OBJ_SPEED(15, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1128 Actor_WalkToAndWait(15, 216, 176);
1130 Event_ShowMessageAndWait(15, 0, 20);
1133 WAIT(20);
1143 WAIT(40);
1145 Event_ShowMessageAndWait(13, 0, 20);
1147 WAIT(20);
1151 Event_AskYesNo(FEH, 0);
1152 OBJ_EMOTE(9, 0x101, 0);
1153 WAIT(5);
1154 OBJ_EMOTE(10, 0x101, 0);
1155 WAIT(5);
1156 OBJ_EMOTE(11, 0x101, 0);
1157 WAIT(5);
1158 OBJ_EMOTE(JUMPING_STUDENT, 0x101, 0);
1159 WAIT(5);
1160 OBJ_EMOTE(13, 0x101, 0);
1161 WAIT(5);
1162 OBJ_EMOTE(14, 0x101, 0);
1163 WAIT(5);
1164 OBJ_EMOTE(15, 0x101, 0);
1165 WAIT(5);
1166 OBJ_EMOTE(16, 0x101, 0);
1167 WAIT(60);
1169 Event_ShowMessageAndWait(16, 0, 20);
1171 WAIT(20);
1173 OBJ_EMOTE(15, 0x101, 60);
1174 Event_ShowMessageAndWait(15, 0, 20);
1175 Actor_FaceActor(FEH, 15, 0);
1176 WAIT(20);
1178 WAIT(20);
1180 Engine_ActorFaceEachOther(11, 10, 0);
1182 Engine_ActorFaceEachOther(13, 15, 0);
1183 WAIT(60);
1184 Actor_FaceActor(10, FEH, 0);
1185 Actor_FaceActor(11, FEH, 0);
1187 Actor_FaceActor(13, FEH, 0);
1188 Actor_FaceActor(14, FEH, 0);
1189 Actor_FaceActor(15, FEH, 0);
1190 WAIT(20);
1193 WAIT(20);
1194 OBJ_MODE(9, 3);
1195 OBJ_MODE(10, 3);
1196 OBJ_MODE(11, 3);
1198 OBJ_MODE(13, 3);
1199 OBJ_MODE(14, 3);
1200 OBJ_MODE(15, 3);
1202 WAIT(20);
1204 Event_AskYesNo(FEH, 0);
1206 WAIT(20);
1209 OBJ_MODE(9, 3);
1210 OBJ_MODE(10, 3);
1211 OBJ_MODE(11, 3);
1213 OBJ_MODE(13, 3);
1214 OBJ_MODE(14, 3);
1215 OBJ_MODE(15, 3);
1217 WAIT(20);
1219 WAIT(20);
1224 WAIT(20);
1225 OBJ_DIR(FEH, FACING_WEST, 20);
1227 WAIT(20);
1229 OBJ_MODE(9, 3);
1230 OBJ_MODE(10, 3);
1231 OBJ_MODE(11, 3);
1233 OBJ_MODE(13, 3);
1234 OBJ_MODE(14, 3);
1235 OBJ_MODE(15, 3);
1237 WAIT(20);
1238 OBJ_WALK(10, 120, 200);
1239 OBJ_WALK(JUMPING_STUDENT, 120, 248);
1241 OBJ_DIR(11, FACING_WEST, 20);
1242 OBJ_MODE(10, 5);
1243 OBJ_MODE(11, 5);
1246 OBJ_SPEED(15, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1247 Actor_WalkToAndWait(15, 216, 168);
1248 Actor_WalkToAndWait(15, 232, 168);
1249 OBJ_DIR(15, FACING_NORTH, 20);
1251 OBJ_POS_SET(TRAINING_TREE, 232, 168);
1252 actor = Actor_Get(TRAINING_TREE);
1253 actor->y.fixed = 0xc0000;
1254 actor = Actor_Get(TRAINING_TREE);
1255 actor->targetY = ACTOR_NO_TARGET;
1256 actor = Actor_Get(TRAINING_TREE);
1257 {
1258 struct AnimationObject *sprite = actor->sprite;
1259 s32 rotation = 0x8000;
1260
1261 sprite->rotation = rotation;
1262 }
1263 SE(SE_124);
1264 WAIT(40);
1265 Actor_WalkToAndWait(15, 216, 152);
1266 OBJ_DIR(15, FACING_SOUTH, 30);
1269}
1270
1271/// Talking to a student (actor 11) once Hsu is known to be trapped: the
1272/// student asks about the flood. "Water monsters flooded Altin. Did you defeat
1273/// them, warrior?"
1275 EV_BEGIN();
1276 MESSAGE_SET(MsgXianWaterMonstersFloodedAltinDid);
1277 Engine_EventAskYesNo(11, 0);
1278 EV_END();
1279}
1280
1281/// Walking north into the door Feh and Feizhi came out of (trigger 3): it is
1282/// locked until Feizhi has left; then it opens and Isaac walks through. "It is
1283/// locked."
1284static void Event_OpenLockedDoor(void) {
1285 EV_BEGIN();
1288 Engine_MessageShowCentered(MsgXianItIsLocked, 1);
1289 EV_END();
1290 } else {
1293 OBJ_SPEED(ACTOR_PARTY_LEADER, PIXELS(1) / 2, PIXELS(1) / 4);
1295 OBJ_WALK(ACTOR_PARTY_LEADER, 304, 216);
1296 WAIT(20);
1298 EV_END();
1299 }
1300}
1301
1302/// Talking to the healer: across the counter from the south, the Sanctum's
1303/// services; from elsewhere, a word on the healer's travels. "I'm traveling
1304/// around the world to spread good will."
1305static void Event_TalkToHealer(void) {
1306 struct FieldActor *leader;
1307 u32 facing;
1308
1310 facing = leader->facing;
1311 EV_BEGIN();
1312
1313 if (FACING_IS_NORTH(facing)) {
1315 } else {
1316 MESSAGE_SET(MsgXianImTravelingAroundWorldSpread);
1317 MESSAGE_PUT(HEALER, 0);
1318 }
1319
1320 EV_END();
1321}
1322
1323/// Reading Nyunpa's mind once he is enlightened: he entrusts the world to
1324/// Isaac. "Isaac... Is that you...? I am... counting on you... to bring
1325/// peace... to the world..."
1326static void Event_ReadNyunpasLastWish(void) {
1327 EV_BEGIN();
1329 MESSAGE_SET(MsgXianIsaacAmCountingOnBring);
1330 MESSAGE_PUT(NYUNPA, 0);
1331 EV_END();
1332}
1333
1334/// Selects the outdoor, school, or lesson event table.
1335const struct SceneEvent *Scene_GetEvents(void) {
1337 return gFuchinTempleEvents1;
1338 }
1339 if (gGameState.entrance == 3) {
1341 }
1342 return gFuchinTempleEvents;
1343}
1344
1345/// Emits a falling particle beside the leader during the grotto entrance fade.
1347 struct EffectOptions options;
1348 struct FieldActor *leader;
1349 s32 paletteDraw;
1350 s32 fallSpeed;
1351
1353
1354 options.palette = 7;
1355 paletteDraw = (u32)(Engine_RandomNext() * 7) >> 16;
1356 if ((paletteDraw & 7) == 0)
1357 options.palette = 5;
1358
1359 options.startScaleX = 0xb333;
1360 options.startScaleY = 0xcccc;
1361
1362 fallSpeed = ((u32)(Engine_RandomNext() * 8) >> 16) * 13107;
1363
1364 Effect_Spawn(leader->x.fixed + ((8 - (gFrameCount & 15)) << 16),
1365 leader->y.fixed + (192 << 13), leader->z.fixed, 0, -fallSpeed, 0,
1366 144 << 12, &options);
1367
1368 if ((gFrameCount & 1) != 0)
1370 else
1372}
1373
1374/// Hops the leader one map cell north.
1377}
1378
1379/// Hops the leader one map cell south.
1382}
1383
1384/// Hops the leader one map cell west.
1387}
1388
1389/// Hops the leader by a pixel offset, waiting for the movement to finish.
1390static UNUSED void FuchinTemple_HopLeaderByOffset(s32 offsetX, s32 offsetZ) {
1391 EV_BEGIN();
1392 OBJ_SPEED(ACTOR_PARTY_LEADER, 5 * PIXELS(1) / 2, 5 * PIXELS(1) / 4);
1398 EV_END();
1399}
1400
1401/// Stepping into the grotto's entrance (trigger 3): spray falls over Isaac as
1402/// the screen fades, and he enters the grotto.
1404 struct FieldActor *leader;
1405 SchedulerCallback particleTask;
1406
1407 EV_BEGIN();
1408 // Keep the entry effect alive until the leader has moved into the fade.
1410 FieldScheduler_AddCallback(particleTask, 0xc80);
1420 Engine_ActorSetSpriteFlags(leader, 0);
1421 Scheduler_RemoveCallback(particleTask);
1424 EV_END();
1425}
1426
1427/// Leaving by the first exit.
1428static void Event_LeaveTemple(void) {
1431}
1432
1433/// Walking north into the temple door (trigger 2): it opens, and Isaac walks
1434/// into Nyunpa's hall.
1435static void Event_EnterNyunpasHall(void) {
1436 EV_BEGIN();
1437 SE(SE_188);
1440 OBJ_SPEED(ACTOR_PARTY_LEADER, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1444 WAIT(16);
1446 EV_END();
1447}
1448
1449/// Back from the grotto, Nyunpa praises Isaac. "Excellent, Isaac! I am glad to
1450/// see you master the secrets of Fuchin Temple!" Nyunpa names the power Ki,
1451/// "force" in the western world, and says it will show the monsters hiding in
1452/// Mogall Forest.
1454 struct FieldActor *nyunpa;
1455
1456 EV_BEGIN();
1457 OBJ_SPEED(ACTOR_PARTY_LEADER, PIXELS(1) / 2, PIXELS(1) / 4);
1458 OBJ_WALK(ACTOR_PARTY_LEADER, 168, 504);
1463 WAIT(20);
1466 WAIT(60);
1468 SE(SE_JUMP);
1469 nyunpa = Actor_Get(NYUNPA);
1470 nyunpa->velocityY = 0x80000;
1472 // Praise the completed test before answering the follow-up questions.
1473 MESSAGE_SET(MsgXianExcellentIsaac);
1477 WAIT(20);
1479 WAIT(20);
1481 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 60);
1483 if (Engine_EventChooseYesNo(0, 0) == 0) {
1484 WAIT(10);
1486 WAIT(20);
1488 gEventWork->message += 2;
1489 } else {
1490 WAIT(10);
1492 WAIT(20);
1496 WAIT(20);
1498 }
1501 WAIT(20);
1503 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 60);
1505 if (Engine_EventChooseYesNo(0, 0) == 1) {
1506 WAIT(10);
1507 OBJ_EMOTE(NYUNPA, 0x102, 60);
1508 MESSAGE_SET(MsgXianCanReadMindsKnowCurious);
1510 do {
1511 if (Engine_EventChooseYesNo(0, 0) != 1) {
1512 break;
1513 }
1514 WAIT(10);
1515 OBJ_EMOTE(NYUNPA, 0x102, 60);
1516 MESSAGE_SET(MsgXianDontTryHard);
1518 } while (1);
1519 }
1520 // Explain why hidden monsters make the new ability useful.
1521 MESSAGE_SET(MsgXianMonstersWaitInHidingWould);
1522 WAIT(10);
1524 WAIT(20);
1526 if (Engine_EventChooseYesNo(0, 0) == 0) {
1527 WAIT(10);
1529 WAIT(20);
1532 } else {
1533 WAIT(10);
1537 }
1539 WAIT(20);
1542 WAIT(20);
1545 WAIT(20);
1547 WAIT(20);
1548 OBJ_MODE(NYUNPA, 5);
1550 EV_END();
1551}
1552
1553/// Entering Hama's room, the party is greeted. "So, Isaac, you and your Adept
1554/// companions have finally come." Hama tells Ivan he is a Jupiter Adept like
1555/// her, teaches him Reveal for crossing Lamakan Desert, and tells of Hsu,
1556/// trapped on Silk Road.
1558 struct FieldActor *leader;
1559
1560 EV_BEGIN();
1561 OBJ_SPEED(ACTOR_PARTY_LEADER, 2 * PIXELS(1) / 5, PIXELS(1) / 5);
1562 OBJ_WALK(ACTOR_PARTY_LEADER, 472, 536);
1566 OBJ_DIR(9, FACING_EAST, 20);
1568 WAIT(20);
1569 MESSAGE_SET(MsgXianMasterHamaMeditatingPleaseExtremely);
1570 Event_ShowMessageAndWait(9, 0, 20);
1573 WAIT(30);
1576 WAIT(20);
1580 WAIT(20);
1582 // Bring the other party members out from the leader for the lesson.
1583 leader = Actor_Get(ACTOR_PARTY_LEADER);
1584 if (leader != 0) {
1585 Actor_SetPosition(GARET, leader->x.fixed, leader->z.fixed);
1586 }
1587 leader = Actor_Get(ACTOR_PARTY_LEADER);
1588 if (leader != 0) {
1589 Actor_SetPosition(IVAN, leader->x.fixed, leader->z.fixed);
1590 }
1591 leader = Actor_Get(ACTOR_PARTY_LEADER);
1592 if (leader != 0) {
1593 Actor_SetPosition(MIA, leader->x.fixed, leader->z.fixed);
1594 }
1595 OBJ_SPEED(ACTOR_PARTY_LEADER, PIXELS(1) / 2, PIXELS(1) / 4);
1596 OBJ_SPEED(GARET, PIXELS(1) / 2, PIXELS(1) / 4);
1597 OBJ_SPEED(IVAN, PIXELS(1) / 2, PIXELS(1) / 4);
1598 OBJ_SPEED(MIA, PIXELS(1) / 2, PIXELS(1) / 4);
1599 OBJ_WALK(ACTOR_PARTY_LEADER, 464, 504);
1600 OBJ_WALK(IVAN, 480, 504);
1601 OBJ_WALK(GARET, 496, 496);
1602 OBJ_WALK(MIA, 448, 496);
1609 WAIT(20);
1610 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 0);
1611 OBJ_EMOTE(GARET, 0x101, 0);
1612 OBJ_EMOTE(IVAN, 0x101, 0);
1613 OBJ_EMOTE(MIA, 0x101, 60);
1616 WAIT(20);
1618 WAIT(20);
1624 WAIT(20);
1636 WAIT(60);
1640 WAIT(20);
1643 WAIT(20);
1646 WAIT(20);
1653 WAIT(20);
1655 OBJ_EMOTE(MIA, 0x101, 60);
1660 WAIT(20);
1662 WAIT(20);
1666 WAIT(30);
1671 WAIT(20);
1673 WAIT(10);
1678 OBJ_EMOTE(IVAN, 0x102, 60);
1681 WAIT(20);
1684 WAIT(20);
1686 WAIT(20);
1690 WAIT(20);
1698 WAIT(20);
1700 WAIT(20);
1703 WAIT(20);
1706 WAIT(20);
1709 WAIT(20);
1713 WAIT(20);
1719 WAIT(20);
1721 WAIT(20);
1724 WAIT(20);
1730 WAIT(20);
1732 OBJ_EMOTE(GARET, 0x103, 0);
1734 WAIT(60);
1737 WAIT(20);
1739 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 0);
1740 OBJ_EMOTE(GARET, 0x101, 60);
1742 OBJ_EMOTE(HAMA, 0x102, 0);
1744 WAIT(60);
1746 WAIT(20);
1753 WAIT(20);
1755 WAIT(20);
1757 OBJ_EMOTE(GARET, 0x101, 60);
1760 WAIT(20);
1762 WAIT(20);
1771 WAIT(20);
1778 WAIT(20);
1780 WAIT(20);
1782 OBJ_EMOTE(IVAN, 0x101, 60);
1785 WAIT(20);
1792 WAIT(60);
1795 WAIT(20);
1797 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 0);
1798 OBJ_EMOTE(GARET, 0x101, 0);
1799 OBJ_EMOTE(IVAN, 0x101, 0);
1800 OBJ_EMOTE(MIA, 0x101, 60);
1802 WAIT(20);
1807 WAIT(20);
1811 WAIT(60);
1815 WAIT(20);
1816 Event_AskYesNo(HAMA, 0);
1817 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x102, 0);
1818 OBJ_EMOTE(GARET, 0x102, 0);
1819 OBJ_EMOTE(IVAN, 0x102, 0);
1820 OBJ_EMOTE(MIA, 0x102, 0);
1821 WAIT(60);
1824 WAIT(20);
1829 OBJ_DIR(HAMA, FACING_EAST, 20);
1830 OBJ_EMOTE(HAMA, 0x105, 60);
1831 OBJ_EMOTE(IVAN, 0x101, 60);
1834 OBJ_EMOTE(HAMA, 0x105, 60);
1836 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 0);
1837 OBJ_EMOTE(GARET, 0x101, 0);
1838 OBJ_EMOTE(IVAN, 0x101, 0);
1839 OBJ_EMOTE(MIA, 0x101, 60);
1841 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 0);
1842 OBJ_EMOTE(GARET, 0x101, 0);
1843 OBJ_EMOTE(IVAN, 0x101, 0);
1844 OBJ_EMOTE(MIA, 0x101, 60);
1850 WAIT(20);
1852 WAIT(20);
1858 WAIT(60);
1863 WAIT(30);
1866 WAIT(20);
1868 // Interrupt the discussion with the arrival from the southern path.
1869 OBJ_POS_SET(10, 472, 608);
1870 Event_ShowMessageAndWait(10, 0, 20);
1877 WAIT(60);
1882 OBJ_DIR(9, FACING_EAST, 0);
1883 WAIT(30);
1884 OBJ_SPEED(10, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1885 Actor_WalkToAndWait(10, 472, 536);
1886 OBJ_EMOTE(HAMA, 0x101, 60);
1889 Actor_WalkToAndWait(IVAN, 488, 512);
1890 WAIT(10);
1894 WAIT(10);
1897 WAIT(20);
1898 Event_ShowMessageAndWait(10, 0, 20);
1899 OBJ_EMOTE(HAMA, 0x101, 60);
1902 Actor_SetAttachedEffect(10, 0x102);
1903 WAIT(60);
1904 Event_ShowMessageAndWait(10, 0, 20);
1905 OBJ_EMOTE(HAMA, 0x101, 60);
1907 OBJ_EMOTE(10, EMOTE_IN_FRONT, 60);
1908 Event_ShowMessageAndWait(10, 0, 20);
1916 WAIT(40);
1918 WAIT(20);
1919 Event_ShowMessageAndWait(10, 0, 20);
1921 WAIT(20);
1923 OBJ_EMOTE(HAMA, 0x101, 60);
1926 WAIT(20);
1927 Event_ShowMessageAndWait(10, 0, 20);
1928 OBJ_EMOTE(HAMA, 0x105, 60);
1933 WAIT(2);
1935 WAIT(1);
1937 WAIT(5);
1940 WAIT(20);
1942 OBJ_SPEED(10, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1943 Actor_WalkToAndWait(10, 472, 504);
1944 WAIT(20);
1946 WAIT(20);
1947 Event_ShowMessageAndWait(10, 0, 20);
1948 Actor_FaceActor(HAMA, 10, 0);
1949 OBJ_SPEED(HAMA, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
1955 WAIT(30);
1957 WAIT(20);
1959 OBJ_WALK(10, 472, 568);
1960 Actor_WalkToAndWait(HAMA, 472, 536);
1965 OBJ_EMOTE(HAMA, 0x102, 60);
1973 Actor_WalkToAndWait(HAMA, 472, 512);
1979 WAIT(20);
1982 WAIT(20);
1985 WAIT(1);
1986 {
1987 struct FieldActor *leaderActor = Actor_Get(ACTOR_PARTY_LEADER);
1988 leaderActor->steeringFlags =
1989 ACTOR_FACES_MOTION | leaderActor->steeringFlags;
1990 }
1991 WAIT(20);
1992 // Finish Ivan's lesson before adding Reveal to his ability list.
1994 WAIT(60);
1996 // Let Hama and her attendant leave, then gather the party into the leader.
1998 WAIT(20);
2004 WAIT(20);
2010 WAIT(20);
2011 Actor_WalkToAndWait(HAMA, 472, 552);
2013 WAIT(20);
2017 WAIT(20);
2019 OBJ_SPEED(HAMA, PIXELS(1) / 2, PIXELS(1) / 4);
2020 Actor_WalkToAndWait(HAMA, 480, 540);
2022 OBJ_SPEED(HAMA, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
2023 OBJ_SPEED(9, 4 * PIXELS(1) / 5, 2 * PIXELS(1) / 5);
2024 OBJ_WALK(HAMA, 472, 608);
2025 OBJ_WALK(9, 472, 544);
2026 Actor_WalkToAndWait(10, 472, 608);
2028 OBJ_WALK(9, 472, 608);
2029 OBJ_POS_SET(10, 0, 0);
2031 OBJ_POS_SET(HAMA, 0, 0);
2033 OBJ_POS_SET(9, 0, 0);
2034 Actor_WalkToAndWait(IVAN, 488, 520);
2035 OBJ_EMOTE(IVAN, 0x101, 60);
2037 WAIT(20);
2043 WAIT(20);
2045 OBJ_EMOTE(MIA, 0x105, 60);
2050 WAIT(20);
2052 WAIT(20);
2056 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x101, 0);
2057 OBJ_EMOTE(GARET, 0x101, 60);
2059 WAIT(20);
2061 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x102, 0);
2062 OBJ_EMOTE(GARET, 0x102, 60);
2064 if (Engine_EventChooseYesNo(0, 0) == 0) {
2065 WAIT(20);
2067 WAIT(20);
2070 } else {
2071 WAIT(20);
2074 WAIT(20);
2076 }
2081 WAIT(20);
2082 OBJ_WALK(GARET, 448, 512);
2083 Actor_WalkToAndWait(MIA, 448, 512);
2084 OBJ_POS_SET(MIA, 0, 0);
2086 OBJ_POS_SET(GARET, 0, 0);
2087 WAIT(20);
2089 WAIT(30);
2092 OBJ_EMOTE(ACTOR_PARTY_LEADER, 0x102, 60);
2095 WAIT(60);
2097 WAIT(20);
2099 Actor_WalkToAndWait(IVAN, 448, 512);
2100 OBJ_POS_SET(IVAN, 0, 0);
2101 EV_END();
2103}
2104
2105/// Inside: Nyunpa meditates, or teaches Ki after the test; the school's tree
2106/// and students stand as the story left them; Hama teaches Reveal on the first
2107/// visit. Outside: the monk beneath the falls stands where the story left him.
2109 struct FieldActor *trainingTree;
2110 s32 heardHsuTrapped;
2111
2114 if (gGameState.entrance == 1) {
2116 OBJ_MODE(8, 6);
2117 } else {
2118 OBJ_MODE(8, 5);
2123 }
2124 }
2125 } else if (gGameState.entrance == 2 || gGameState.entrance == 4) {
2128 if (heardHsuTrapped == 0) {
2129 trainingTree = Object_GetById(19);
2130 trainingTree->motionFlags = heardHsuTrapped;
2131 trainingTree->y.fixed = 0xc0000;
2132 trainingTree->targetY = 0xc0000;
2133 trainingTree->scaleX = 0xcccc;
2134 trainingTree->scaleY = 0x8000;
2135 trainingTree->sprite->rotation = 0x8000;
2137 Engine_ActorSetPosition(18, PIXELS(248), PIXELS(208));
2139 Engine_ActorSetPosition(16, PIXELS(256), PIXELS(240));
2145 }
2146 }
2147 } else {
2148 trainingTree = Object_GetById(19);
2149 trainingTree->motionFlags = 0;
2150 trainingTree->y.fixed = 0xc0000;
2151 trainingTree->targetY = 0xc0000;
2152 trainingTree->scaleX = 0xcccc;
2153 trainingTree->scaleY = 0x8000;
2154 trainingTree->collisionFlags |= 8;
2155 trainingTree->sprite->rotation = 0x8000;
2156 Map_CopyCellAttributes(14, 11, 1, 1, 14, 10);
2157 }
2158 OverlayObject_PrepareObject(0x1300000, 0x180000, 0xe00000, 223);
2159 OBJ_MODE(10, 5);
2160 OBJ_MODE(11, 5);
2161 } else if (gGameState.entrance == 3) {
2166 Engine_ActorSetPosition(8, 0, 0);
2167 Engine_ActorSetPosition(9, 0, 0);
2168 }
2169 }
2170 } else {
2173 if (gGameState.entrance == 3 &&
2176 Map_CopyCellAttributes(10, 84, 1, 1, 10, 24);
2177 }
2179 OBJ_POS_SET(9, 152, 392);
2181 Map_CopyCellAttributes(10, 26, 1, 1, 10, 22);
2182 }
2183 }
2184 return 0;
2185}
2186
2187/// Starts the Mind Read demonstration for the requested caster and target.
2189 u8 *effectWork;
2190
2191 Engine_GameFlagSet(160 << 1);
2193 effectWork = gEffectWork;
2194 Engine_PsynergySetTarget(caster, target);
2195 effectWork[0x23] = 0;
2198 Engine_TaskWait(1);
2199}
2200
2201/// Finishes the demonstration's effect and lowers the caster's hands.
2206}
2207
2208/// Emits eight rising particles from Nyunpa, sounding every other shot.
2210 struct EffectOptions options;
2211 struct FieldActor *nyunpa;
2212 u32 shotIndex;
2213
2214 nyunpa = Object_GetById(NYUNPA);
2215 options.priority = 1;
2216 options.type = 0x0119;
2218 options.targetScaleX = 224 << 10;
2219 options.targetScaleY = 192 << 9;
2220 for (shotIndex = 0; shotIndex < 8; shotIndex++) {
2221 WAIT(10);
2222 if (shotIndex & 1) {
2224 }
2225 Effect_Spawn(nyunpa->x.fixed, nyunpa->y.fixed, nyunpa->z.fixed + 0xffe80000,
2226 0, 0x9999, 0, 0x00360001, &options);
2227 }
2228 WAIT(60);
2229}
2230
2231/// Alternates the lesson's child effect from the frame counter, not player
2232/// input.
2234 if ((*(u32 *)&gFrameCount >> 1) & 1) {
2235 ObjectGroup_SetChildValue((struct FieldActor *)object, 10);
2236 } else {
2237 ObjectGroup_SetChildValue((struct FieldActor *)object, 9);
2238 }
2239}
2240
2241/// Animates Hama and Ivan's lesson effects, fades the palette and clears the
2242/// callbacks.
2244 struct EffectOptions options;
2245 struct FieldActor *hama;
2246 u32 particleIndex;
2247 s32 particleX;
2248 s32 particleY;
2249 s32 riseSpeed;
2250
2253 WAIT(40);
2254 Engine_ColorBufferApplySource(128 << 9, 0);
2255 Engine_ColorBufferApplyTarget(0x205c54, 1);
2257 WAIT(40);
2260 WAIT(120);
2261 hama = Object_GetById(HAMA);
2262 // Emit the lesson particles while both temporary child effects run.
2263 options.priority = 1;
2264 options.palette = 2;
2265 options.type = 0x011d;
2266 for (particleIndex = 0; particleIndex < 64; particleIndex++) {
2267 if ((particleIndex & 3) == 0) {
2269 }
2270 particleX = hama->x.fixed +
2271 ((((u32)(Engine_RandomNext() * 3) << 4) >> 16) << 16) +
2272 0xfff40000;
2273 particleY = hama->y.fixed +
2274 ((((u32)Engine_RandomNext() << 5) >> 16) << 16) + 0xfff00000;
2275 riseSpeed = ((((u32)Engine_RandomNext() << 2) >> 16) << 15) + (128 << 8);
2276 Effect_Spawn(particleX, particleY, hama->z.fixed, 0, riseSpeed, 0,
2277 152 << 13, &options);
2278 Engine_TaskWait(2);
2279 }
2281 WAIT(30);
2282 // Fade back and remove both hooks before the conversation resumes.
2283 Engine_ColorBufferApplyTarget(128 << 9, 1);
2285 WAIT(40);
2290}
2291
2293 SC_WAIT(1), SC_LOOP(22, SC_TOP), SC_WAIT(1),
2294 SC_POS(0, 0, 0), SC_WAIT(1), SC_FREE,
2295};
2296
2298 SC_WAIT(1), SC_LOOP(44, SC_TOP), SC_WAIT(1),
2299 SC_POS(0, 0, 0), SC_WAIT(1), SC_FREE,
2300};
2301
2303 SC_WAIT(1), SC_LOOP(126, SC_TOP), SC_WAIT(1),
2304 SC_POS(0, 0, 0), SC_WAIT(1), SC_FREE,
2305};
2306
2311};
2312
2314 SC_ARG(0),
2315 SC_SET(SW_GRAVITY, 0x9999),
2316 SC_LABEL(1),
2317 SC_SET(SW_VELOCITY_Y, 0x30000),
2318 SC_WAIT(30),
2319 SC_SET(SW_VELOCITY_Y, 0x40000),
2320 SC_WAIT(30),
2321 SC_SET(SW_VELOCITY_Y, 0x50000),
2323 SC_WAIT(2),
2324 SC_SET(SW_FACING, 0x5000),
2325 SC_WAIT(2),
2327 SC_WAIT(2),
2328 SC_SET(SW_FACING, 0xb000),
2329 SC_WAIT(2),
2331 SC_WAIT(2),
2332 SC_SET(SW_FACING, 0xd000),
2333 SC_WAIT(2),
2335 SC_WAIT(2),
2336 SC_SET(SW_FACING, 0x3000),
2337 SC_WAIT(2),
2339 SC_WAIT(2),
2340 SC_WAIT(60),
2342 SC_END,
2343};
2344
2347 SC_WAIT(1),
2348 SC_END,
2349};
2350
2352 MAP_CELL_STEP(66, 46, 3, 2, 5),
2353 MAP_CELL_STEP(63, 46, 3, 2, 5),
2355};
2356
2358 MAP_CELL_STEP(62, 19, 2, 2, 5),
2359 MAP_CELL_STEP(64, 19, 2, 2, 5),
2361};
2362
2364 MAP_CELL_STEP(62, 19, 2, 2, 5),
2365 MAP_CELL_STEP(60, 19, 2, 2, 5),
2367};
2368
2370 {0, CONDITION_ALWAYS, 296, 0, 488, FACING_NORTH, 0, -1, -1, -1, -1, 0},
2371 {1, CONDITION_ALWAYS, 296, 0, 504, FACING_NORTH, 0, -1, -1, -1, -1, 0},
2372 {2, CONDITION_ALWAYS, 296, 0, 304, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2373 {3, CONDITION_ALWAYS, 168, 0, 360, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2374 {5, CONDITION_ALWAYS, 232, 0, 328, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
2376};
2377
2379 {0, CONDITION_ALWAYS, 168, 0, 552, FACING_NORTH, 0, -1, -1, -1, -1, 0},
2380 {1, CONDITION_ALWAYS, 168, 0, 552, FACING_NORTH, 0, 48, 384, 288, 576, 0},
2381 {2, CONDITION_ALWAYS, 256, 0, 264, FACING_NORTH, 0, 48, 80, 368, 288, 0},
2382 {3, CONDITION_ALWAYS, 472, 0, 552, FACING_NORTH, 0, 352, 384, 592, 576, 0},
2383 {4, CONDITION_ALWAYS, 304, 0, 248, FACING_SOUTH, 0, 48, 80, 368, 288, 0},
2385};
2386
2388 SCENE_EXITS(60), SCENE_EXIT(1, 2, 12), SCENE_EXIT(2, 61, 1),
2389 SCENE_EXIT(3, 62, 1), SCENE_EXIT(0, 61, 0), SCENE_EXIT(1, 60, 2),
2390 SCENE_EXIT(2, 72, 10), SCENE_EXIT(3, 88, 2), SCENE_EXIT(4, 73, 8),
2392};
2393
2394// clang-format off
2397 PIXELS(296), 0, PIXELS(440), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2399 PIXELS(168), 0, PIXELS(360), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2401 PIXELS(272), 0, PIXELS(424), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2403 PIXELS(392), 0, PIXELS(392), FACING_WEST, TALK_FACE_PARTY, 0 },
2405 PIXELS(312), 0, PIXELS(328), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2408 { SCENE_TABLE_END },
2409};
2410
2412 // Nyunpa
2413 { 0x33, 0x0, ACTOR_STAND,
2414 PIXELS(168), 0, PIXELS(472), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2415 // Master Feh's students
2416 { 0x6c, 0x0, ACTOR_STAND,
2417 PIXELS(216), 0, PIXELS(264), FACING_NORTH, TALK_FACE_PARTY, 0 },
2418 { 0x82, 0x0, ACTOR_STAND,
2420 { 0x83, 0x0, ACTOR_STAND,
2423 PIXELS(120), 0, PIXELS(248), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2424 { 0x83, 0x0, ACTOR_STAND,
2425 PIXELS(176), 0, PIXELS(168), FACING_EAST, TALK_FACE_PARTY, 0 },
2426 { 0x66, 0x0, ACTOR_STAND,
2428 { 0x82, 0x0, ACTOR_STAND,
2430 { 0x82, 0x0, ACTOR_STAND,
2431 PIXELS(176), 0, PIXELS(216), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2432 // Feizhi and Master Feh, out of sight until they come out
2434 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2436 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
2437 // The training tree, and where Force strikes it
2438 { 0xcd, CONDITION_ALWAYS, 7,
2439 PIXELS(232), 0, PIXELS(168), FACING_WEST, TALK_FACE_PARTY, 0 },
2441 PIXELS(232), 0, PIXELS(168), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2442 { SCENE_TABLE_END },
2443};
2444
2447 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
2449 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
2451 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
2452 // Hama
2456 PIXELS(440), 0, PIXELS(536), FACING_EAST, TALK_FACE_PARTY, 0 },
2458 0, 0, 0, FACING_NORTH, TALK_FACE_PARTY, 0 },
2459 { SCENE_TABLE_END },
2460};
2461
2463 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
2467 { EVENT_TALK, 8, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleTheFuchinTempleIsAPleasant) },
2468 { EVENT_TALK, FALLS_MONK, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleOhIsaacWhatTookYouSo) },
2469 { EVENT_TALK, 10, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleAhhhMasterNyunpaHeHasPassed) },
2470 { EVENT_TALK, 11, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleMasterNyunpaHasWastedAwayAt) },
2474 { EVENT_TALK, FALLS_MONK, FLAG_NYUNPA_TEST_ACCEPTED, MSGNO(MsgFuchinTempleOmOmBlueLightsInThe) },
2476 { EVENT_TALK, FALLS_MONK, FLAG_FUCHIN_FALLS_ORB_OF_FORCE_FOUND, MSGNO(MsgFuchinTempleTheTestOfFuchinFallsIs) },
2477 { EVENT_TALK, FALLS_MONK, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleMasterNyunpaIsWaitingForYou) },
2478 { EVENT_TALK, 10, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleGemsFromTheSkyBlueLights) },
2479 { EVENT_TALK, 11, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleNyunpaHasNotEatenInDays) },
2482 { SEARCH(SEARCH_UNNAMED), 110, 0x350, FIND_PSYNERGY_STONE },
2483 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleGemsFallingFromTheSkyMountains) },
2484 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FALLS_MONK, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleIKnewMasterNyunpaWasFasting) },
2485 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleMasterNyunpaReachedEnlightenmentDuringHis) },
2486 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleMasterNyunpaIsNothingButSkin) },
2487 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTempleHeCantLeaveUsYetHe) },
2488 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, FLAG_FUCHIN_TEMPLE_VISITOR_HEARD_BRIDGE_OPEN, MSGNO(MsgFuchinTempleIBeginningToThinkIllBe) },
2489 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 8, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleIDontFeelSafeGoingHome) },
2490 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FALLS_MONK, FLAG_NYUNPA_TEST_ACCEPTED, MSGNO(MsgFuchinTempleManyStarsFellFromTheSky) },
2491 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FALLS_MONK, FLAG_FUCHIN_FALLS_GROTTO_OPENED, MSGNO(MsgFuchinTempleCanSuchYoungWarriorsEndureThe) },
2492 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FALLS_MONK, FLAG_FUCHIN_FALLS_ORB_OF_FORCE_FOUND, MSGNO(MsgFuchinTempleCanSuchYoungWarriorsEndureThe) },
2493 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FALLS_MONK, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleTheWarriorsHaveMasteredTheSecrets) },
2494 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleThereIsNoPointInTraining) },
2495 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleICantImagineFastingItGets) },
2496 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleIWillTrainToBecomeA) },
2497 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), HEALER, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleSinceImHereIdLikeTo) },
2498 { SCENE_EVENTS_END },
2499};
2500
2503 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
2505 { EVENT_TALK, NYUNPA, IF_FLAG_SET(FLAG_NYUNPA_ENLIGHTENED), MSGNO(MsgFuchinTemple) },
2506 { EVENT_TALK, NYUNPA, IF_FLAG_SET(FLAG_NYUNPA_TAUGHT_FORCE), MSGNO(MsgFuchinTempleUseThisEnergyToFindThe) },
2507 { EVENT_TALK, NYUNPA, IF_FLAG_SET(FLAG_NYUNPA_TEST_ACCEPTED), MSGNO(MsgFuchinTempleSpeakToTheMonkStandingBeneath) },
2509 { EVENT_TALK, NYUNPA, CONDITION_ALWAYS, MSGNO(MsgXianNyunpaMeditates) },
2511 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), NYUNPA, IF_FLAG_SET(FLAG_NYUNPA_TAUGHT_FORCE), MSGNO(MsgFuchinTempleNowThatIHavePassedMy) },
2514 { EVENT_TALK, 9, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleThisIsMasterFehsKungFu) },
2515 { EVENT_TALK, 10, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleBouldersOvercameHsuKungFuShould) },
2518 { EVENT_TALK, 14, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleFeizhiPredictedHsusDangerHerProphecy) },
2519 { EVENT_TALK, 16, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleHsuIsRestingFeizhiIsWatching) },
2520 { EVENT_TALK, FEH, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTemplePracticeEveryoneChiHasItsLimits) },
2521 { EVENT_TALK, 9, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleWarriorYouAreGreatYouHave) },
2522 { EVENT_TALK, 10, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleEveryoneWantsToLearnTheChi) },
2523 { EVENT_TALK, 11, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleConcentrateEnergyIntoTheHandsAnd) },
2525 { EVENT_TALK, 13, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleIDidNotThinkMuchOf) },
2526 { EVENT_TALK, 14, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleWhereDidFeizhiGoIAm) },
2527 { EVENT_TALK, 15, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleMasterHsuIsLateICan) },
2528 { EVENT_TALK, 16, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleIWillLearnChiIWill) },
2529 { EVENT_TALK, FEH, IF_FLAG_SET(FLAG_FEH_SCHOOL_SAW_TREE_FALL), MSGNO(MsgFuchinTempleWarriorUseYourChiFromThe) },
2530 { EVENT_TALK, 16, IF_FLAG_SET(FLAG_FEH_SCHOOL_SAW_TREE_FALL), MSGNO(MsgFuchinTempleWarriorPleaseUseYourChiFrom) },
2531 { EVENT_TALK, FEH, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleWarriorLetMeSeeYourChi) },
2532 { EVENT_TALK, 13, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleFeizhiIsGoneItIsDangerous) },
2533 { EVENT_TALK, 14, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleFeizhiIsStrongerThanSheLooks) },
2534 { EVENT_TALK, 15, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleWarriorShowUsYourChiLike) },
2535 { EVENT_TALK, 16, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleWarriorThatWasGreatButMaster) },
2537 { EVENT_TALK, 13, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleFeizhiIsGoneItIsDangerousOutside) },
2538 { EVENT_TALK, 14, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleFeizhiIsStrongerThanSheLooksShe) },
2539 { EVENT_TALK, 15, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleIKnowWhyYouCanUse) },
2540 { EVENT_TALK, 16, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleWarriorChiIsAGreatPower) },
2542 { EVENT_TALK, 10, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleStrongKicksAreVeryImportantKick) },
2543 { EVENT_TALK, 11, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleIWantToLearnSoI) },
2545 { EVENT_TALK, 13, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleEveryoneInXianCanDoMartial) },
2546 { EVENT_TALK, 14, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleJustListeningDoesNotMakeOne) },
2548 { EVENT_TALK, 16, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleMasterFehIsVeryBusyHe) },
2549 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTemplePeaceHasReturnedToXianBut) },
2550 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleNoMatterHowMuchYouPractice) },
2551 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleTheMonstersAreVeryLargeStriking) },
2552 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), JUMPING_STUDENT, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleWhenABoulderFallsJumpRepeat) },
2553 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleWhereDidFeizhiGainThePower) },
2554 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, IF_FLAG_SET(FLAG_XIAN_HEARD_HSU_TRAPPED), MSGNO(MsgFuchinTempleMasterFehIsVeryWorriedAbout) },
2555 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FEH, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleCanSuchAYoungWarriorReally) },
2556 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleYourChiIsFuchinTemplesHow) },
2557 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleIDontCareWhichChiIt) },
2558 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleMasterHamasChiCanShatterBoulders) },
2559 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), JUMPING_STUDENT, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleFollowSilkRoadStraightPassThrough) },
2560 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleWarriorYouUseWeaponsAndChi) },
2561 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleFeizhiIsNotInTheFeh) },
2562 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleFeizhiWorriesOnlyAboutMasterHsu) },
2563 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, IF_FLAG_SET(FLAG_FEH_SAW_CHI), MSGNO(MsgFuchinTempleLearningChiIsVeryHardMaster) },
2564 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FEH, IF_FLAG_SET(FLAG_FEH_SCHOOL_SAW_TREE_FALL), MSGNO(MsgFuchinTempleWarriorTheRulesRequireYouTo) },
2565 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, IF_FLAG_SET(FLAG_FEH_SCHOOL_SAW_TREE_FALL), MSGNO(MsgFuchinTempleSoCloseWarriorUseChiFrom) },
2566 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FEH, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleWarriorShowMeYourChiI) },
2567 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleFeizhiIKnowIKnowHow) },
2568 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleMyKickAndPunchAreVery) },
2569 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleShowUsYourChiNowDo) },
2570 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, IF_FLAG_SET(FLAG_FEH_WAITS_TO_SEE_CHI), MSGNO(MsgFuchinTempleIAmShockedThatThisWarrior) },
2571 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FEH, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleIWantToSeeTheChi) },
2572 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleFeizhiIKnowHowYouFeel) },
2573 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleMyKickAndPunchAreVeryLoud) },
2574 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleWarriorShowMeYourChiNow) },
2575 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, IF_FLAG_SET(FLAG_FEH_CHI_DEMONSTRATION_DECLINED), MSGNO(MsgFuchinTempleWarriorDoNotHideYourChi) },
2576 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleWarriorsFightWithWeaponsKungFu) },
2577 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgFuchinTemplePracticingKicksHurtsMyFeetVery) },
2578 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleThatPunchWasGoodYouSurprise) },
2579 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), JUMPING_STUDENT, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleIMoveTooQuicklyYouCant) },
2580 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleWarriorsCameToLearnTheFeh) },
2581 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleGreatKickKickFromTheHip) },
2582 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleYouAreTheWarriorsWhoCame) },
2583 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleMasterFehIsTalkingWithFeizhi) },
2590 { SEARCH(SEARCH_BARREL), 100, 0xf69, FIND_ITEM(ITEM_ANTIDOTE) },
2591 { SEARCH(SEARCH_JAR), 101, 0xf68, FIND_ITEM(ITEM_UNICORN_RING) },
2592 { SCENE_EVENTS_END },
2593};
2594
2596 { EVENT_EXIT, 4, CONDITION_ALWAYS, 3 },
2597 { EVENT_TALK, 9, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleMasterHamaIsMeditatingAskingFor) },
2598 { EVENT_TALK, HAMA, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleTheFutureHoldsManyHardshipsBut) },
2599 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleIDoNotThinkMasterHama) },
2600 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), HAMA, CONDITION_ALWAYS, MSGNO(MsgFuchinTempleICannotSeeYourFutureClearly) },
2601 { SEARCH(SEARCH_JAR), 102, 0xf6a, FIND_COINS(6) },
2602 { SCENE_EVENTS_END },
2603};
2604// clang-format on
2605
2608 SC_WAIT(44),
2609 SC_WAIT(1),
2610 SC_POS(0, 0, 0),
2611 SC_WAIT(1),
2612 SC_FREE,
2613};
Ability numbers, named from the English release.
@ ABILITY_FORCE
Definition ability_ids.h:17
@ ABILITY_MIND_READ
Definition ability_ids.h:16
@ ABILITY_REVEAL
Definition ability_ids.h:19
@ ABILITY_MOVE
Definition ability_ids.h:15
void ObjectGroup_SetChildValue(struct FieldActor *actor, s32 param)
Sets the param byte of every animated part of an actor's sprite.
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
const struct ScenePlacement * Scene_GetPlacements(void)
const struct SceneEntrance * Scene_GetEntrances(void)
const struct SceneEvent * Scene_GetEvents(void)
const u32 * Scene_GetExits(void)
Both scenes share one exit table.
const struct SceneRegion * Scene_GetRegions(void)
s32 Scene_Initialize(void)
Sets up whichever scene is being entered and runs its arrival events.
s32 gEffectScript0[]
const s32 * gEffectScripts[]
s32 gEffectScript1[]
s32 gEffectScript2[]
Calls through a function pointer, by argument count.
void(*) SchedulerCallback(void)
#define GARET
Jerald.
#define MIA
Mary.
#define IVAN
Ivan.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
The engine calls the debug menus import, and their palette swatch tiles.
The engine call layer: one typed inline for each of the thirteen main-image routines below that the s...
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
Scene commands: the all-caps macros the scene scripts are written in.
#define EV_BEGIN()
Definition event.h:30
#define OBJ_DIR(no, d, t)
Definition event.h:16
#define OBJ_POS_SET(no, x, z)
Definition event.h:13
#define EV_END()
Definition event.h:31
#define MESSAGE_OPEN(no, f)
Definition event.h:11
#define WAIT(n)
Definition event.h:7
#define OBJ_MODE(no, m)
Definition event.h:18
#define OBJ_WALK(no, x, z)
Definition event.h:14
#define MESSAGE_PUT(no, f)
Definition event.h:10
#define MESSAGE_SET(m)
Definition event.h:9
#define SE(n)
Definition event.h:28
#define FLAG_SET(f)
Definition event.h:26
#define FLAG_CHECK(f)
Definition event.h:25
#define OBJ_FACE(no, to, t)
Definition event.h:17
#define OBJ_EMOTE(no, e, t)
Definition event.h:19
#define OBJ_SPEED(no, s, a)
Definition event.h:15
void FieldScene_PrepareActors(struct ScenePlacement *entry)
@ EFFECT_USE_PALETTE
options.palette, as its group child value
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
@ ANIM_WALK
Definition field_event.h:44
@ ANIM_STAND
Definition field_event.h:43
@ ANIM_NOD
Definition field_event.h:45
@ ANIM_SHAKE_HEAD
Definition field_event.h:46
static s32 Event_OpenMessage(s32 speaker, s32 flags)
static void Actor_SetDestination(s32 actor, s32 x, s32 z)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Engine_SanctumOpen(s32 priest)
static void Map_AnimateCells(const u16 *steps, s32 destX, s32 destY)
void Engine_PsynergyBegin(s32 ability, s32 flags)
static void Event_ShowMessageAndWait(s32 speaker, s32 flags, s32 frames)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
void Engine_EventShowMessageAndWait(s32 speaker, s32 flags, s32 frames)
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)
void Engine_PsynergyLowerHands(void)
void Engine_CameraMoveToActor(s32 actor, s32 pan)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
#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
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorSetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_EventCloseScreen(void)
void Engine_ActorWalkToAndWait(s32 actor, s32 x, s32 z)
static void Event_SkipMessages(s32 count)
static void Actor_FaceActor(s32 actor, s32 target, s32 frames)
static void ColorBuffer_ApplyTarget(s32 value, s32 mode)
#define GameFlag_Clear
void Engine_EventWaitForScreen(void)
void Engine_ActorDestroy(s32 actor)
s32 Engine_EventAskYesNo(s32 speaker, s32 flags)
void Engine_EventOpenScreen(void)
void Engine_GameFlagSet(s32 flag)
void Engine_GameFlagClear(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)
void Engine_CameraFollowActor(s32 actor, s32 keep_position)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
static void Event_ShowMessage(s32 speaker, s32 flags)
s32 Engine_RandomNext()
void Engine_ActorSetChildValue(s32 actor, s32 value)
#define MAP_CELL_STEPS_END
Definition field_event.h:61
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_PsynergyPlayEffect(s32 effect)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
s32 Engine_MathCos(s32 angle)
static s32 Event_AskYesNo(s32 speaker, s32 flags)
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)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
void Engine_PsynergySetTarget(s32 caster, s32 target)
void Engine_ColorBufferApplyTarget(s32 value, s32 mode)
void Engine_ColorBufferApplySource(s32 value, s32 mode)
static struct FieldActor * Actor_Get(s32 actor)
static void ColorBuffer_ApplySource(s32 value, s32 mode)
Field objects and actors, and the scene transition styles.
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ TRANSITION_BACKDROP_FADE
Definition field_obj.h:16
#define ACTOR_NO_TARGET
A target coordinate that is not set: the object has no target.
Definition field_obj.h:145
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
@ ACTOR_FACES_MOTION
turns toward its velocity, 1/16 turn a frame
Definition field_obj.h:166
The scene table formats: entrances, exits, placements and events, and the macros that write them.
#define SCENE_EVENTS_END
#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 FIND_PSYNERGY_STONE
#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 TOUCH_FACING(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_BARREL
#define FIND_COINS(coins)
Game flags, named where their meaning is shown.
#define FLAG_FEH_WAITS_TO_SEE_CHI
Definition flags.h:619
#define FLAG_FEH_CHI_DEMONSTRATION_DECLINED
Definition flags.h:620
#define FLAG_SHOW_LOCATION_NAME
Definition flags.h:94
#define FLAG_FUCHIN_FALLS_GROTTO_OPENED
the monk stepped aside
Definition flags.h:614
#define FLAG_XIAN_HEARD_HSU_TRAPPED
Definition flags.h:112
#define FLAG_FUCHIN_TEMPLE_VISITOR_HEARD_BRIDGE_OPEN
The visitor from Kolima heard that the bridge is open again.
Definition flags.h:612
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_FEH_SAW_CHI
Definition flags.h:621
#define FLAG_NYUNPA_ENLIGHTENED
Nyunpa is enlightened, beyond words: he has passed away.
Definition flags.h:610
#define FLAG_FUCHIN_FALLS_ORB_OF_FORCE_FOUND
The Orb of Force's chest in Fuchin Falls has been opened.
Definition flags.h:618
#define FLAG_NYUNPA_TAUGHT_FORCE
the power the monks call Ki
Definition flags.h:615
#define FLAG_FEIZHI_WENT_TO_HSU
Definition flags.h:113
#define FLAG_FUCHIN_FALLS_MONK_ASKED_ABOUT_TEST
Definition flags.h:616
#define FLAG_NYUNPA_TEST_ACCEPTED
the test of the waterfall grotto
Definition flags.h:613
#define FLAG_HSU_RESCUED
Definition flags.h:114
volatile u32 gFrameCount
Frames WaitFrames has finished.
static void Event_EnterNyunpasHall(void)
Walking north into the temple door (trigger 2): it opens, and Isaac walks into Nyunpa's hall.
static void Event_EnterWaterfallGrotto(void)
Stepping into the grotto's entrance (trigger 3): spray falls over Isaac as the screen fades,...
#define FEIZHI
#define NYUNPA
static void Event_PushTreeByHand(void)
Walking into the training tree: Isaac pushes it over by hand.
static void Event_MonkAsksWhetherTestIsDone(void)
Coming back out of the grotto (trigger 5), Isaac is sent on to Nyunpa and the way back is open again.
static void FuchinTemple_ToppleTreeSouth(void)
Slides the training tree south in four steps before the final displacement.
static void FuchinTemple_StudentWalksAroundTree(void)
Routes the student around the tree according to the leader's facing.
static void Event_NyunpaFeelsMindRead(void)
Reading Nyunpa's mind once the test is accepted: he notices.
static void FuchinTemple_BeginMindReadDemonstration(s32 caster, s32 target)
Starts the Mind Read demonstration for the requested caster and target.
static void FuchinTemple_FeizhiLeavesForHsu(void)
The first time the tree falls from the line, a student runs for Master Feh.
static void Event_ReadNyunpasLastWish(void)
Reading Nyunpa's mind once he is enlightened: he entrusts the world to Isaac.
static void Event_FehAsksToSeeChi(void)
Talking to Feh after the party declined: he asks again to see Isaac's Chi.
static void Event_MonkLetsPartyIntoGrotto(void)
Talking to the monk beneath the falls once Nyunpa has offered the test: he lets the party pass.
static UNUSED void FuchinTemple_HopLeaderWest(void)
Hops the leader one map cell west.
#define FEH
static void Event_StudentAsksAboutFeh(void)
Talking to the student by the training tree (actor 15): the student asks whether the party still wish...
static void Event_MoveTree(void)
Move on the training tree: it topples, and the students react.
static s32 FuchinTemple_FaceLeader(union FieldObject *object)
static void FuchinTemple_AlternateLessonChildEffect(union FieldObject *object)
Alternates the lesson's child effect from the frame counter, not player input.
s32 gFuchinTemple_JumpingStudentScript[]
static UNUSED void FuchinTemple_HopLeaderNorth(void)
Hops the leader one map cell north.
u16 gFuchinTemple_CellStepsA[]
struct SceneEvent gFuchinTempleEvents1[]
s32 gFuchinTemple_HiddenSpriteScript[]
static void FuchinTemple_ToppleTreeWest(void)
Rotates the training tree through its westward arc and scatters particles.
static void Event_MonkSpeaksOfNyunpa(void)
Talking to the monk (actor 12) outside the temple: he speaks of the one seeking enlightenment,...
static void FuchinTemple_ToppleTreeEast(void)
Rotates the training tree through the opposite arc and reverses its horizontal scale.
static void Event_NyunpaOffersTest(void)
Talking to Nyunpa, or reading his mind: he reads the party's mind in turn, guesses that they follow S...
#define TRAINING_TREE
#define HAMA
The second scene by entrance 3: Hama's room in Lama Temple.
static void FuchinTemple_ToppleTreeNorth(void)
Slides the training tree north in four steps, then scatters particles.
struct ScenePlacement gFuchinTemplePlacements1[]
static void Event_StudentAsksAboutAltin(void)
Talking to a student (actor 11) once Hsu is known to be trapped: the student asks about the flood.
u16 gFuchinTemple_CellStepsC[]
struct SceneEvent gFuchinTempleEvents[]
static void FuchinTemple_SpawnGrottoEntryParticle(void)
Emits a falling particle beside the leader during the grotto entrance fade.
static void FuchinTemple_AnimateRevealLesson(void)
Animates Hama and Ivan's lesson effects, fades the palette and clears the callbacks.
struct ScenePlacement gFuchinTemplePlacements[]
static void FuchinTemple_StudentsSeeTreeFall(void)
The students see the tree fall, Feh doubts it came from the line, and the student sets the tree up ag...
static UNUSED void FuchinTemple_HopLeaderByOffset(s32 offsetX, s32 offsetZ)
Hops the leader by a pixel offset, waiting for the movement to finish.
static void FuchinTemple_NyunpaTeachesKi(void)
Back from the grotto, Nyunpa praises Isaac.
static UNUSED void FuchinTemple_HopLeaderSouth(void)
Hops the leader one map cell south.
#define TRAINING_TREE_TARGET
where Force strikes the tree
u32 gFuchinTempleExits[]
static void Event_ForceTree(void)
Force on the training tree: it topples.
static void FuchinTemple_StudentExplainsChiRules(s32 mode)
The student by the tree explains the rules: mode 0 when Psynergy felled it but not from the line,...
static void FuchinTemple_FinishMindReadDemonstration(void)
Finishes the demonstration's effect and lowers the caster's hands.
static void FuchinTemple_SpawnNyunpasParticles(void)
Emits eight rising particles from Nyunpa, sounding every other shot.
#define FLAG_NYUNPA_TEST_DECLINED
Nyunpa's test was declined; the students saw the training tree fall.
#define JUMPING_STUDENT
struct SceneEntrance gFuchinTempleEntrancesOther[]
static void Event_LeaveTemple(void)
Leaving by the first exit.
static s32 FuchinTemple_ClearScriptedActorSpriteFlags(struct ScriptInterpreter *interpreter)
Clears the scripted actor's sprite flags and completes the script command.
u16 gFuchinTemple_CellStepsB[]
static void Event_TalkToJumpingStudent(void)
Talking to the student who practises jumping: he lands, talks about jumping (or Lama Temple,...
static void Event_OpenLockedDoor(void)
Walking north into the door Feh and Feizhi came out of (trigger 3): it is locked until Feizhi has lef...
static void FuchinTemple_FehSeesChi(void)
The tree falls from the line with Feh watching, but Feh sees that it is not Chi.
s32 gFuchinTemple_ShotScript[]
struct ScenePlacement gFuchinTemplePlacementsEntrance3[]
static void Event_StudentWelcomesToSchool(void)
Talking to the student at the door (actor 9): the student asks whether the party came to watch.
struct SceneEntrance gFuchinTempleEntrances1[]
#define HEALER
#define FALLS_MONK
the monk beneath the falls, at the waterfall grotto
struct SceneEvent gFuchinTempleEventsEntrance3[]
#define FLAG_FEH_SCHOOL_SAW_TREE_FALL
static void Event_TalkToHealer(void)
Talking to the healer: across the counter from the south, the Sanctum's services; from elsewhere,...
static void FuchinTemple_RunHamasRevealLesson(void)
Entering Hama's room, the party is greeted.
static void Event_VisitorAsksAboutBridge(void)
Talking to the visitor from Kolima outside the temple: he asks how the party got here.
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The work slots of gWorkSlot, read through their own names.
void * gEffectWork
Slot 56: points to a scene-specific structure.
The screen blend's globals and the graphics routines.
Item numbers, named from the English release.
@ ITEM_ANTIDOTE
Definition item_ids.h:47
@ ITEM_UNICORN_RING
Definition item_ids.h:85
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
Definition math.c:36
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_FOREVER
Definition objcmd.h:14
#define SC_TO(n)
Definition objcmd.h:12
#define SC_ARG(v)
Definition objcmd.h:44
#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_GRAVITY
Definition objcmd.h:73
@ SW_FACING
Definition objcmd.h:57
@ SW_VELOCITY_Y
Definition objcmd.h:65
#define SC_CALL(fn)
Definition objcmd.h:50
void Party_LearnAbility(s32 unit, s32 ability)
Teaches unit the Psynergy ability and says so with its jingle, waiting for the player to read it.
Definition events.c:475
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
Scene numbers, named after their places.
char SceneId_FuchinTemple2
char SceneId_FuchinTemple1
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_220
Definition songs.h:215
#define SE_159
Definition songs.h:154
#define SE_170
Definition songs.h:165
#define SE_DOOR_OPEN
Definition songs.h:153
#define SE_131
Definition songs.h:124
#define SE_MAP_EXIT
Definition songs.h:116
#define SE_CAST
Definition songs.h:149
#define SE_227
Definition songs.h:222
#define SE_132
Definition songs.h:125
#define SE_188
Definition songs.h:183
#define SE_130
Definition songs.h:123
#define SE_124
Definition songs.h:117
#define SE_246
Definition songs.h:241
#define SE_JUMP
An actor jumps: ObjectMotion_Launch plays the high jump above 5 pixels a frame.
Definition songs.h:147
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_AudioPlayCue()
void Engine_TaskWait()
#define NULL
Definition bilibin.h:6
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
The options of a spawned field effect, each used when its EFFECT_USE_ flag (or EFFECT_SCALE_TO_TARGET...
s16 type
the object type to create; 222 without the flag
s32 targetScaleY
16.16 fixed point, 0x10000 full size
s32 targetScaleX
16.16 fixed point, 0x10000 full size
s32 palette
passed to ObjectGroup_SetChildValue
s32 startScaleY
16.16 fixed point, 0x10000 full size
s32 priority
the sprite's priority
const s32 * script
the object script, run in mode 1
s32 startScaleX
16.16 fixed point, 0x10000 full size
s32 startTransition
SCENE_TRANSITION(style, variant).
Definition event_work.h:43
s32 transitionFrames
frames
Definition event_work.h:45
u16 message
the next message, advanced as each window opens
Definition event_work.h:47
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
u8 steeringFlags
ActorSteeringFlag bits.
Definition field_obj.h:92
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
Definition field_obj.h:83
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
s32 targetZ
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:61
u8 paused
nonzero skips its script and motion, not its update
Definition field_obj.h:93
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
s32 velocityY
16.16 fixed-point pixels per frame
Definition field_obj.h:53
s32 gravity
Taken off the vertical velocity each frame while it is above the ground, in 16.16 fixed-point pixels ...
Definition field_obj.h:68
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 targetY
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:60
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
void(*) update(union FieldObject *object)
Called each frame before the object's script, while the object is live.
Definition field_obj.h:116
u8 collisionFlags
bits: 7 refuses to move into a solid object | 4 nearer for Psynergy targets | 3 never a talk or Psyne...
Definition field_obj.h:91
s16 entrance
Definition game_state.h:37
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
s32 x
16.16 fixed-point pixels
Definition field_scene.h:91
s16 condition
-1 always, a flag | 0x1000 set, else the flag clear; off the world map, 48 to 127 also need condition...
Definition field_scene.h:87
s32 z
16.16 fixed-point pixels
Definition field_scene.h:93
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
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
An object on the field, read as an actor or as an effect.