Alchemy
Loading...
Searching...
No Matches

vault_interiors.c

Go to the documentation of this file.
1/// @file
2/// The houses, shops and inn of Vault while Hammet's rod is missing.
3
4#include "game_state.h"
5#include "flags.h"
6#include "animspr.h"
7#include "version.h"
8#include "scene_ids.h"
9#include "unit/import.h"
12#include "unit/object/object.h"
14#include "unit/battle/battle.h"
15#include "unit/game/game.h"
17#include "battle.h"
18#include "debug.h"
19#include "field.h"
20#include "game.h"
21#include "graphics.h"
22#include "menu.h"
23#include "minigame.h"
24#include "sound.h"
25#include "system.h"
26#include "mem.h"
27#include "edition.h"
28#include "types.h"
29#include "callback_scheduler.h"
30#include "item_ids.h"
31#include "field_event.h"
32#include "field_scene.h"
33#include "tbs_edition.h"
34#include "battle_party.h"
35#include "text/msg_ids.h"
36#include "field_service.h"
37#include "ability_ids.h"
38#include "objcmd.h"
39#include "fixed_math.h"
40#include "macros.h"
41#include "songs.h"
42
43#if TBS_PATCH_3
44#define VAULT_INTERIORS_ENTRY_ACTOR_Z PIXELS(451)
45#else
46#define VAULT_INTERIORS_ENTRY_ACTOR_Z PIXELS(464)
47#endif
48
49/// A cornering lasts half a second before the chase raises an event.
50#define VAULT_INTERIORS_CORNERED_FRAMES 30
51
52/// The chase adds the blocked-suspect mask (1 the leader, 2 the thief) to 200.
58};
59
60/// The townspeople, named by what they say.
61enum {
62 ACTOR_GEM_OWNER = 8, ///< a sparkling rock was blown here from the volcano
64 /// Distrusts the man next door. "My neighbor creeps me out."
66 /// Asks about travel. "Hey, mister! Is it fun to see strange new places?"
68 /// Wonders what was stolen. "Is it just me, or am I missing something?"
70 /// Says Grandpa keeps wondering if anything was stolen.
72 /// "I could help Ivan if I were just a little older."
74 /// Tells the party Ivan's secret once it helps him.
76 ACTOR_MAYOR = 16, ///< Ivan's host; his wife calls him the mayor
82 /// Works at the inn. "The guests upstairs weren't in their room during the
83 /// eruption."
86 /// The two guests at the inn the town suspects: the thieves' leader and one
87 /// of his men.
90 ACTOR_CRATE = 26 ///< pushed aside to open a passage
91};
92
93/// Place flags of Vault's group (0x300 to 0x3ff, kept while the party stays in
94/// Vault and its buildings).
95enum {
96 /// Set while the two suspects run from the party, until the party steps
97 /// aside to talk it over.
99};
100
101// Scene flags here:
102// - FLAG_SCENE_TEMP_50: in the house with the Bone, the leader stands beside
103// it (Vault_UpdateBoneProximityFlag); in the inn, set while the party
104// corners the suspects, when talking to Ivan or the suspects does nothing.
105
106/// The inn's loft (entrances 15 to 17), where the thieves hid the stolen goods.
107enum {
108 ACTOR_ATTIC_ROOFER = 8, ///< tied up while fixing the roof
113 /// Comes up with the mayor and helps tie the thieves up. "What should we do
114 /// with them?"
116 /// Comes up with the mayor and opens the crates. "Mayor... Isn't that your
117 /// family's urn?"
122 ACTOR_FOUND_URN = 18, ///< rises from the first crate: the mayor's urn
123 ACTOR_FOUND_STATUE = 19 ///< rises from the second: the Sanctum's gold statue
124};
125
126static void VaultInteriors_IvanJoinsRodSearch(void);
127static void VaultInteriors_DiscussMindReading(void);
128static void VaultInteriors_AdvanceSuspectRoute(s32 actor, s32 expected,
129 s32 next, const s32 *actions);
131static void VaultInteriors_LoseToThieves(void);
133static void VaultInteriors_DefeatThieves(void);
134static void VaultInteriors_ReturnStolenGoods(void);
136static void VaultInteriors_ShowMessageAndWait(s32 actorId, s32 waitFrames);
137static void VaultInteriors_FaceActorAndWait(s32 actorId, s32 targetId,
138 s32 waitFrames);
139static void VaultInteriors_FaceEachOtherAndWait(s32 firstId, s32 secondId,
140 s32 waitFrames);
141static void VaultInteriors_PlayAnimationAndWait(s32 actorId, s32 animation,
142 s32 waitFrames);
143static void VaultInteriors_BeginMindRead(s32 casterId, s32 targetId);
144static void VaultInteriors_EndMindRead(void);
145static void VaultInteriors_UpdateActorStops(void);
146static void VaultInteriors_StartActorStops(void);
147
150}
151
152/// Returns the one exit region: the box around (648, 416) in the room with the
153/// crate, which takes exit 13 back out to Vault.
154const struct SceneRegion *Scene_GetRegions(void) {
156}
157
159
160/// Places the townspeople, or, for the inn's loft (entrances 15 to 17), the
161/// roofer, the mayor, the thieves, their crates and the found treasures.
163 struct ScenePlacement *table;
164
165 switch (gGameState.entrance) {
166 case 15:
167 case 16:
168 case 17:
170 break;
171 default:
173 break;
174 }
176 return table;
177}
178
179#if !TBS_PATCH_1
180/// Jumps the leader to the requested destination when nothing blocks it there;
181/// returns 1 when it jumped. Only the editions before the first patch have it;
182/// the patched ones look ahead instead (Engine_LeaderCheckAhead).
183static s32 VaultInteriors_TryJumpTo(struct FieldPosition *pos) {
184 struct FieldActor *leader;
185 u8 *flags;
186 u8 savedMotionFlags;
187
189 flags = &leader->motionFlags;
190 savedMotionFlags = *flags;
191 if (FieldObject_CheckMovementCollision(leader, pos) == 0) {
193 Object_SetMode(leader, 6);
196 Object_SetMode(leader, 7);
197 leader->speed = PIXELS(3);
198 leader->acceleration = PIXELS(2);
199 leader->velocityY = PIXELS(4);
200 *flags &= 0x7e;
203 ((union FieldCoordinate *)&pos->x)->part.pixel,
204 ((union FieldCoordinate *)&pos->z)->part.pixel);
205 Object_SetMode(leader, 6);
208 *flags = savedMotionFlags;
210 return 1;
211 }
212 return 0;
213}
214#endif
215
216/// Facing north or south across the gap in the roof, the leader jumps it.
217///
218/// Reached by walking onto cell code 40. Then copies the cell (41, 85) or
219/// (43, 85) over the gap's cell (42, 85), whichever side the leader faced.
220static void Event_JumpAcrossRoofGap(void) {
221 s32 x;
222 s32 z;
223#if !TBS_PATCH_1
224 struct FieldPosition target;
225 struct FieldPosition *pos;
226 struct FieldActor *leader;
227#endif
228
229 if (Object_GetById(ACTOR_PARTY_LEADER)->facing >= 0xa000 &&
231#if TBS_PATCH_1
233#else
235 pos = &target;
236 SET_POSITION(pos, leader->x.fixed,
239 VaultInteriors_TryJumpTo(pos);
240#endif
241 x = 42;
242 z = 85;
243 Map_CopyCellAttributes(41, 85, 1, 1, x, z);
244 } else if (Object_GetById(ACTOR_PARTY_LEADER)->facing >= 0x2000 &&
246#if TBS_PATCH_1
248#else
250 pos = &target;
251 SET_POSITION(pos, leader->x.fixed,
254 VaultInteriors_TryJumpTo(pos);
255#endif
256 x = 42;
257 z = 85;
258 Map_CopyCellAttributes(43, 85, 1, 1, x, z);
259 }
260}
261
262/// Once the crate has been moved aside to column 42, the passage behind it
263/// opens.
264///
265/// Reached by Move on the crate (actor 26) until FLAG_VAULT_CRATE_MOVED is
266/// set; sets it when the crate has reached column 42.
267static void Event_CheckCrateMoved(void) {
268 struct FieldActor *crate;
269
272 if ((crate->x.fixed >> 20) == 42) {
273 Map_CopyCellAttributes(101, 24, 3, 4, 41, 24);
275 }
277}
278
279/// Across the counter the weapon shop opens; otherwise the merchant lost
280/// expensive goods too, or found the stolen weapons rusted in the cemetery.
281///
282/// Reached by talking to the weapon merchant (actor 19), before and after the
283/// thieves are jailed (FLAG_VAULT_THIEVES_JAILED picks the line). The armor
284/// merchant, the inn and the item shop below work the same way: the counter is
285/// between them when the leader faces north (0xa001 to 0xdfff).
286static void Event_TalkToWeaponMerchant(void) {
288
290 if (leaderFacing >= 0xa001 && leaderFacing <= 0xdfff) {
292 } else {
294 Engine_EventSetMessage(MsgVaultMasterHammetIsntOnlyOne);
295 } else {
296 Engine_EventSetMessage(MsgVaultWeFoundOurStolenWeapons);
297 }
299 }
301}
302
303/// Across the counter the armor shop opens; otherwise the merchant wants the
304/// thieves to pay, or advises preparing for the cave in the Goma Range.
305///
306/// Reached by talking to the armor merchant (actor 20).
307static void Event_TalkToArmorMerchant(void) {
309
311 if (leaderFacing >= 0xa001 && leaderFacing <= 0xdfff) {
313 } else {
315 Engine_EventSetMessage(MsgVaultThievesDidntHitOurHouse);
316 } else {
317 Engine_EventSetMessage(MsgVaultIfYoureGonnaHeadInto);
318 }
320 }
322}
323
324/// Across the counter the inn opens; otherwise the innkeeper defends the
325/// guests everyone suspects, or learns the goods were hidden in his loft.
326///
327/// Reached by talking to the innkeeper (actor 23).
328static void Event_TalkToInnkeeper(void) {
330
332 if (leaderFacing >= 0xa001 && leaderFacing <= 0xdfff) {
334 } else {
336 Engine_EventSetMessage(MsgVaultEveryoneThinksOurGuestsThieves);
337 } else {
338 Engine_EventSetMessage(MsgVaultTheyHidThoseStolenGoods);
339 }
341 }
343}
344
345#include "common/vault_bone.h"
346
347/// Garet refuses to leave. "We don't have time for that, Isaac!"
348///
349/// Reached through raised event 250, which the engine raises in place of a
350/// menu or a shortcut while FLAG_MENUS_RAISE_EVENT is set, as the party
351/// corners the suspects.
352static void Event_GaretRefusesToLeave(void) {
353#if TBS_PATCH_1
355#endif
356 Engine_EventSetMessage(MsgVaultWeDontHaveTimeFor);
358}
359
360/// Isaac checks the barrel but doesn't find anything.
361///
362/// Reached by searching cell code 41 before the thieves are jailed; after, the
363/// same spot holds the Bone (Vault_FindBone).
364static void Event_SearchEmptyBarrel(void) {
366 Engine_MessageShowCentered(MsgVaultIsaacCheckedBarrel, 1);
367 Engine_MessageShowCentered(MsgVaultButDidntFindAnything, 1);
369}
370
371/// Isaac checks the chest, but it is empty.
372///
373/// Reached by talking to one of the loft's three crates (actors 15 to 17).
374static void Event_SearchEmptyChest(void) {
376 Engine_MessageShowCentered(MsgVaultIsaacCheckedChest, 1);
377 Engine_MessageShowCentered(MsgVaultButChestWasEmpty, 1);
379}
380
381/// Returns the loft's events for entrances 15 to 17, else the houses' events,
382/// which change once FLAG_VAULT_THIEVES_JAILED is set.
383const struct SceneEvent *Scene_GetEvents(void) {
384 switch (gGameState.entrance) {
385 case 15:
386 case 16:
387 case 17:
389 }
392 }
394}
395
396/// Stands the speaker, faces the leader, and shows the selected message.
401}
402
403#include "common/vault_talk.h"
404
405/// Faces the leader and selects the next reply when the answer is no.
409 if (Engine_EventChooseYesNo(0, 0) != 0) {
411 }
413}
414
415/// The child asks about travel.
416/// "Hey, mister! Is it fun to see strange new places?"
417///
418/// Reached by talking to the child (actor 11) before the thieves are jailed.
419static void Event_ChildAsksAboutTravel(void) {
421 Engine_EventSetMessage(MsgVaultMisterFunSeeStrangeNew);
425}
426
427/// Offers Ivan's secret.
428/// "Ivan has great powers. Wouldn't you like to know what they are?"
429///
430/// Reached by talking to actor 15 until FLAG_VAULT_IVAN_JOINED_ROD_SEARCH is
431/// set; then the row after it tells the secret: Ivan can talk with animals.
432static void Event_OfferIvansSecret(void) {
434 Engine_EventSetMessage(MsgVaultIvanHasGreatPowersWouldnt);
438}
439
440/// Across the counter the item shop opens; otherwise a greeting, or, after the
441/// thieves are jailed, the bridge is out. "Did you just arrive in town today?"
442///
443/// Reached by talking to the item merchant (actor 21).
444static void Event_TalkToItemMerchant(void) {
446
448 if (leaderFacing >= 0xa001 && leaderFacing <= 0xdfff) {
451 Engine_EventSetMessage(MsgVaultDidJustArriveInTown);
453 } else {
454 Engine_EventSetMessage(MsgVaultWithBridgeOutWillQuite);
456 }
458}
459
460/// The gem owner's wife wishes their rocks were gems, or, after the thieves
461/// are jailed, is glad they were caught before stealing the gem.
462///
463/// Reached by talking to the gem owner's wife (actor 9).
464static void Event_TalkAboutRocks(void) {
467 Engine_EventSetMessage(MsgVaultIfOnlyTheseRocksWere);
468 } else {
469 Engine_EventSetMessage(MsgVaultThankGoodnessThoseThievesWere);
470 }
473}
474
475/// Talks about missing things, or, after the thieves are jailed, says they hid
476/// the treasure in the loft and more in the cemetery.
477/// "Is it just me, or am I missing something?"
478///
479/// Reached by talking to Grandpa (actor 12).
483 Engine_EventSetMessage(MsgVaultThievesHidStolenTreasureIn);
484 } else {
485 Engine_EventSetMessage(MsgVaultJustMeOrAmMissing);
486 }
489}
490
491/// The mayor asks for someone to help Ivan; once the party has agreed, he
492/// thanks them the first time and asks them to look after Ivan after that.
493///
494/// Reached by talking to the mayor (actor 16) before the thieves are jailed.
495/// Sets FLAG_VAULT_MAYOR_THANKED_PARTY with the thanks.
496static void Event_MayorAsksHelpForIvan(void) {
497 s32 thankedForHelpingFlag;
498 thankedForHelpingFlag = FLAG_VAULT_MAYOR_THANKED_PARTY;
501 if (Engine_GameFlagIsSet(thankedForHelpingFlag) == 0) {
502 Engine_EventSetMessage(MsgVaultYoureGoingHelpIvan);
506 Engine_GameFlagSet(thankedForHelpingFlag);
507 } else {
508 Engine_EventSetMessage(MsgVaultPleaseLookAfterIvan);
509 }
510 } else {
511 Engine_EventSetMessage(MsgVaultCouldSomeonePleaseHelpIvan);
512 }
515}
516
517/// The three strangers have fooled the innkeeper and his wife.
518///
519/// Reached by talking to the bone giver (actor 18) before the thieves are
520/// jailed.
523 Engine_EventSetMessage(MsgVaultThoseThreeStrangersSureHave);
526}
527
528/// The suspected leader cries out and runs to his next spot, chosen by the way
529/// he faces and where he is on his route. "Ow! Stop it!"
530///
531/// Reached by Mind Read on him (actor 24), and by talking to him once
532/// FLAG_VAULT_SUSPECTS_MIND_READ is set (before, he only says Ivan creeps him
533/// out); neither while the party corners him. His timer holds his place on the
534/// six-step route, wrapping from 5 to 0.
536 struct FieldActor *suspect;
537 s16 *routeState;
538 s32 routeIndex;
539 s32 nextRoute;
540
544 Engine_EventSetMessage(MsgVaultOwStop);
547 if ((u32)((suspect->facing & 0xf000) - 0x5000) <= 0x6000) {
548 routeState = (s16 *)&suspect->timer;
549 routeIndex = *routeState;
550 if (routeIndex <= 2) {
552 gVaultInteriors_StepActions[routeIndex]);
553 *(u16 *)routeState = *(u16 *)routeState + 1;
554 } else {
556 gVaultInteriors_IdleActions[routeIndex]);
557 nextRoute = *(u16 *)routeState - 1;
558 *(u16 *)routeState = nextRoute;
559 }
560 } else {
561 routeState = (s16 *)&suspect->timer;
562 routeIndex = *routeState;
563 if (routeIndex > 2) {
565 gVaultInteriors_StepActions[routeIndex]);
566 *(u16 *)routeState = *(u16 *)routeState + 1;
567 } else {
569 gVaultInteriors_IdleActions[routeIndex]);
570 nextRoute = *(u16 *)routeState - 1;
571 *(u16 *)routeState = nextRoute;
572 }
573 }
574 if (*routeState > 5) {
575 nextRoute = 0;
576 *(u16 *)routeState = nextRoute;
577 }
578 if (*routeState < 0) {
579 nextRoute = 5;
580 *(u16 *)routeState = nextRoute;
581 }
584}
585
586/// Selects a response script and advances the second suspect's route state.
587static inline void
589 s32 routePair, u16 routeDelta) {
592 gVaultInteriors_ResponseScripts[scriptRow * 4 + actor->timer]);
593 actor->timer = actor->timer - routePair * 2 + routeDelta;
594}
595
596/// The suspected thief cries out and runs to his next spot.
597/// "No! Leave me alone!"
598///
599/// Reached as Event_SuspectedLeaderDodges is, on actor 25. His timer holds his
600/// place on his route (4 at its start).
601static void Event_SuspectedThiefDodges(void) {
602 struct FieldActor *actor;
603 u32 facing;
604 s32 routePair;
605
607 facing = actor->facing & 0xf000;
608 routePair = actor->timer >> 1;
611 Engine_EventSetMessage(MsgVaultNoLeaveAlone);
614 switch (actor->timer) {
615 case 4:
616 if (facing > 0x2000 && facing < 0xa000) {
618 actor->timer = 2;
619 } else {
621 actor->timer = 3;
622 }
623 break;
624 case 0:
625 case 2:
626 if (facing > 0x2000 && facing < 0xa000) {
627 VaultInteriors_ApplySecondSuspectRoute(actor, routePair, routePair, 1);
628 } else {
629 VaultInteriors_ApplySecondSuspectRoute(actor, routePair ^ 1, routePair,
630 -1);
631 }
632 break;
633 case 1:
634 case 3:
635 if (facing > 0x6000 && facing < 0xe000) {
636 VaultInteriors_ApplySecondSuspectRoute(actor, routePair, routePair, 1);
637 } else {
638 VaultInteriors_ApplySecondSuspectRoute(actor, routePair ^ 1, routePair,
639 -1);
640 }
641 break;
642 }
643 actor->timer &= 3;
646}
647
648/// Asks whether the thieves came from Lunpa.
649/// "Did those thieves come from Lunpa?"
650///
651/// Reached by talking to the wary neighbor (actor 10) after the thieves are
652/// jailed; the child and actor 14 below are reached the same way.
655 Engine_EventSetMessage(MsgVaultDidThoseThievesComeFrom);
658}
659
660/// The child's father worries about the prisoners from Lunpa.
663 Engine_EventSetMessage(MsgVaultMyFatherWorriedAboutThose);
666}
667
668/// Asks about defeating the thieves. "I heard you defeated those thieves!"
671 Engine_EventSetMessage(MsgVaultHeardDefeatedThoseThieves);
674}
675
676/// After the thieves are jailed, the mayor thanks Isaac and gives the promised
677/// Water of Life, if there is room; then asks whether the party is heading
678/// beyond the Goma Range, and points them to the cave on the way to Bilibin.
679///
680/// Reached by talking to the mayor (actor 16) after the thieves are jailed.
681/// Gives the Water of Life and sets FLAG_VAULT_WATER_OF_LIFE_RECEIVED, once;
682/// with a full bag he says to come back for it.
686 Engine_EventSetMessage(MsgVaultYouWereSuchGreatHelp);
697 if (PartyInventory_HasSpace() == 0) {
698 Engine_EventSetMessage(MsgVaultYouWereSuchGreatHelp + 3);
701 return;
702 }
705 }
706 Engine_EventSetMessage(MsgVaultHeadingOutBeyondGomaRange);
709 if (Engine_EventChooseYesNo(0, 0) != 0) {
711 }
714}
715
716/// The bone giver offers leftover bones from dinner; a yes gets a Bone if
717/// there is room, a no a nod.
718///
719/// Reached by talking to the bone giver (actor 18) after the thieves are
720/// jailed, while the leader is not beside the Bone on the floor
721/// (FLAG_SCENE_TEMP_50 clear). Gives a Bone and sets FLAG_VAULT_BONE_RECEIVED.
722static void Event_OfferBones(void) {
726 Engine_EventSetMessage(MsgVaultHaveLotLeftoverBonesFrom);
728 } else {
729 Engine_EventSetMessage(MsgVaultWantMoreBones);
731 }
732 if (Engine_EventChooseYesNo(0, 0) == 0) {
738 if (PartyInventory_HasSpace() == 0) {
741 Engine_EventSetMessage(MsgVaultWowHaveManyThingsArent);
743 } else {
747 }
748 } else {
754 }
757}
758
759/// Mind Read on the wife: let me see that rock, or maybe it is worthless.
760///
761/// Reached by Mind Read on the gem owner's wife (actor 9); the Mind Read
762/// events below are reached the same way on the actor each names, before and
763/// after the thieves are jailed (FLAG_VAULT_THIEVES_JAILED picks the thought).
764static void Event_ReadMindOnRock(void) {
767 Engine_EventSetMessage(MsgVaultOkMisterLetMeSee);
768 } else {
769 Engine_EventSetMessage(MsgVaultIfRockWorthlessMaybeThats);
770 }
773}
774
775/// Mind Read on the child: what is the outside world like, or Father looks
776/// sad.
777static void Event_ReadChildMind(void) {
780 Engine_EventSetMessage(MsgVaultWonderOutsideWorldLike);
781 } else {
782 Engine_EventSetMessage(MsgVaultFatherLooksSadWorryingLike);
783 }
786}
787
788/// Mind Read on Grandpa: could they be thieves? Who can be trusted? Or nothing
789/// in the house was worth stealing.
790static void Event_ReadMindOnThieves(void) {
793 Engine_EventSetMessage(MsgVaultCouldTheyThievesGoodDont);
794 } else {
795 Engine_EventSetMessage(MsgVaultGuessNothingInOurHouse);
796 }
799}
800
801/// Mind Read on the mayor: a laugh, or the cave in the Goma Range is
802/// dangerous, but the party will be okay. "That tickles..."
803static void Event_ReadMayorMind(void) {
806 Engine_EventSetMessage(MsgVaultTicklesBeingTickledByBoy);
807 } else {
808 Engine_EventSetMessage(MsgVaultCaveInGomaRangeDangerous);
809 }
812}
813
814/// Mind Read on the bone giver: the master and his wife are blinded by money;
815/// after the thieves are jailed, hungry while cooking, or, once a Bone was
816/// given, wondering about calcium.
817static void Event_ReadBoneGiverMind(void) {
820 Engine_EventSetMessage(MsgVaultMasterHisWifeBlindedBy);
822 Engine_EventSetMessage(MsgVaultGeeAlwaysGetHungryWhen);
823 } else {
824 Engine_EventSetMessage(MsgVaultHeReallyLikesBonesWonder);
825 }
828}
829
830/// Talking to Ivan at the mayor's: the first time, he reads the two's minds,
831/// admits his strange powers and learns they are called Psynergy; then he asks
832/// for help finding the rod. A yes has him join the party.
833///
834/// Reached by talking to Ivan (actor 2), except while the party corners the
835/// suspects. Sets FLAG_VAULT_MET_IVAN the first time, and on a yes plays
836/// VaultInteriors_IvanJoinsRodSearch, sets FLAG_VAULT_IVAN_JOINED_ROD_SEARCH
837/// and has Ivan walk into the leader.
838static void Event_MeetIvan(void) {
839
840 struct FieldActor *actor;
841
844 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
845 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
846 // Isaac steps up in front of Ivan and Garet comes out beside him.
851 Actor_WalkToAndWait(GARET, 368, 408);
853 // Introduce Ivan's ability only on the first meeting.
856 // Ivan reads Isaac's mind and admits his strange powers.
860 Engine_EventSetMessage(MsgVaultDoPossessStrangePowers);
865 // The two start; he reads again: "You have them, too, don't you?"
877 // A third reading: his power is called Psynergy; then they have so much
878 // in common he can trust them.
888 // He walks off a step, turns back and tells of Hammet's stolen rod.
893 Actor_WalkToAndWait(IVAN, 376, 376);
904 // "Would you please help me get my master's rod back?"
906 } else {
907 // Asked again: "Would you really? Would you help me find the rod?"
909 Engine_EventSetMessage(MsgVaultWouldReallyWouldHelpMe);
911 }
912 // Accepting the search lets Ivan merge into the leader's position; a no gets
913 // his apology for asking.
914 if (Engine_EventChooseYesNo(0, 0) == 0) {
919 if (actor != 0) {
920 Actor_SetDestination(IVAN, actor->x.part.pixel, actor->z.part.pixel);
921 }
923 Actor_SetPosition(IVAN, 0, 0);
924 } else {
926 }
927 // Garet walks back into the leader and the earlier music returns.
930 if (actor != 0) {
931 Actor_SetDestination(GARET, actor->x.part.pixel, actor->z.part.pixel);
932 }
937}
938
939/// Ivan thanks them, they exchange names, and he shows Isaac and Garet Mind
940/// Read; he joins the party.
941///
942/// Called by Event_MeetIvan when the party agrees to help. Adds Ivan to the
943/// party ("Ivan joined your party!").
945 s32 message;
946
947 // Ivan jumps for joy: "Thank you. With your help, I believe we can recover
948 // the rod." Then he asks their names.
951 Engine_ActorJump(IVAN, 4, 0);
953 message = MsgVaultThankHelpBelieve;
954 Engine_EventSetMessage(message);
957 Actor_ShowEmote(IVAN, 0x101, 0);
960 // He reads their names from Isaac's mind; Isaac backs away from him.
961 Actor_WalkToAndWait(IVAN, 376, 392);
972 // Demonstrate Mind Read and let Garet and Isaac react to Ivan's explanation.
978 Actor_ShowEmote(IVAN, 0x101, 0);
991 Actor_ShowEmote(GARET, 0x102, 0);
993 // "Is my Mind Read so frightening?": either answer goes on the same way.
994 Actor_ShowEmote(IVAN, 0x102, 0);
1000 Engine_EventWait(30);
1001 // Ivan and Isaac clasp hands, and Garet cries out that his mind is read.
1003 Actor_WalkToAndWait(IVAN, 384, 408);
1004 Engine_EventWait(10);
1005 Engine_MessageShowCentered(message + 5, 1);
1006 Engine_EventSetMessage(message + 6);
1009 Actor_ShowEmote(GARET, 0x102, 0);
1010 Engine_EventWait(60);
1013 Actor_WalkToAndWait(GARET, 352, 408);
1016 Engine_EventWait(10);
1017 // Garet backs off; Ivan asks whether Isaac could read Garet's mind, and the
1018 // two read it together. "Just as I thought."
1019 Actor_WalkTo(IVAN, 368, 408);
1020 Engine_EventWait(20);
1031 Engine_EventWait(30);
1043 Actor_ShowEmote(GARET, 0x101, 0);
1044 Engine_EventWait(60);
1045 // Sharing their Psynergy let Isaac read minds too; Garet protests that it
1046 // isn't fair, and Ivan agrees it is one-way.
1049 Engine_ActorShowEmote(GARET, 0x103, 0);
1050 Engine_EventWait(60);
1053 Engine_ActorShowEmote(IVAN, 0x100, 0);
1054 Engine_EventWait(60);
1056 Actor_ShowEmote(GARET, 0x102, 0);
1057 Engine_EventWait(60);
1058 // Ivan and Garet clasp hands, and Garet reads Isaac's mind.
1059 Engine_MessageShowCentered(message + 13, 1);
1060 Engine_EventSetMessage(message + 14);
1064 Engine_EventWait(60);
1075 Engine_EventWait(20);
1076 // "Let's use Mind Read to find the thieves!" Garet worries people will
1077 // notice.
1081 Actor_ShowEmote(IVAN, 0x101, 0);
1082 Engine_EventWait(30);
1089 // Only Adepts can tell when Ivan uses Psynergy; ordinary people see
1090 // nothing, and he promises not to read their minds again.
1091 Engine_ActorShowEmote(IVAN, 0x106, 0);
1092 Engine_EventWait(60);
1099 Engine_ActorShowEmote(GARET, 0x101, 0);
1100 Engine_EventWait(60);
1104 Engine_EventWait(60);
1110 // "Ivan joined your party!", then he will read the townspeople's minds.
1112 Engine_EventSetMessage(message + 22);
1115}
1116
1117/// In the loft, Isaac cuts the roofer free; the three thieves arrive, boast of
1118/// Lunpa and Dodonpa, ask to be let go, and attack.
1119///
1120/// Reached by talking to the tied-up roofer (actor 8) in the loft; the loft's
1121/// setup replays the thieves' part through VaultInteriors_ConfrontThievesAgain
1122/// once FLAG_VAULT_THIEVES_CONFRONTED is set. Sets that flag and starts the
1123/// battle (encounter 12, 5): a win returns to entrance 17, a loss to 16.
1125 s32 base;
1126
1129 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
1130 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
1131 // Isaac cuts the roofer free from the ropes; he gets up and nods.
1133 Engine_EventWait(20);
1134 base = MsgVaultVaultCutFree;
1136 base++;
1138 Engine_EventWait(30);
1140 Engine_EventWait(60);
1142 // Garet and Ivan come out of the leader around the roofer.
1145 Actor_SetPosition(GARET, PIXELS(792), PIXELS(440));
1146 Actor_SetPosition(IVAN, PIXELS(792), PIXELS(440));
1147 Actor_WalkTo(GARET, 808, 432);
1148 Actor_WalkTo(IVAN, 792, 456);
1153 // The roofer tells how he came up to fix the roof, was whacked from behind
1154 // and woke up tied.
1156 Engine_EventWait(60);
1161 Engine_EventWait(20);
1163 Actor_ShowEmote(IVAN, 258, 0);
1164 Actor_ShowEmote(GARET, 258, 0);
1165 Engine_EventWait(60);
1167 Engine_EventWait(10);
1169 // He looks around at crates he doesn't remember; Ivan guesses the stolen
1170 // goods are in them.
1172 Engine_EventWait(30);
1174 Engine_EventWait(60);
1176 Engine_EventWait(40);
1178 Engine_EventWait(40);
1184 // The thieves' leader appears at the ladder to MUS_061: "Looks like we've
1185 // been found out!" Everyone turns.
1193 Engine_EventWait(30);
1198 // He walks up and his two men run in behind him.
1206 Engine_EventWait(70);
1213 Engine_EventWait(40);
1219 Engine_EventWait(40);
1220 // The three taunt Hammet's whelp and say Hammet was caught by worse thieves
1221 // after fleeing to Lunpa.
1225 Engine_EventWait(10);
1228 Engine_EventWait(10);
1230 Actor_ShowEmote(IVAN, 257, 0);
1231 Engine_EventWait(60);
1235 Actor_ShowEmote(GARET, 257, 0);
1236 Engine_EventWait(60);
1237 // The roofer is alarmed at the name Lunpa; Garet asks what kind of place it
1238 // is, and the roofer and the thieves tell of Lunpa, Donpa and Dodonpa.
1240 Engine_EventWait(40);
1242 Engine_EventWait(20);
1250 Engine_EventWait(20);
1255 Engine_EventWait(60);
1258 Engine_EventWait(10);
1268 Actor_ShowEmote(GARET, 258, 0);
1269 Actor_ShowEmote(IVAN, 258, 0);
1270 Engine_EventWait(60);
1271 // "See, we're not so bad. How about it? Will you let us go?" Yes: if they
1272 // return the goods and repent? No: even returning everything is a crime?
1275 Engine_EventWait(50);
1278 if (Engine_EventChooseYesNo(0, 0) == 0) {
1279 Engine_EventWait(40);
1283 Engine_EventWait(20);
1285 } else {
1286 Engine_EventWait(40);
1289 base = MsgVaultVaultThievesCaught;
1292 Engine_EventWait(20);
1294 // Both answers go on with the same refusal.
1295 base -= 3;
1297 }
1298 // "We stole this stuff fair and square!" They agree to keep the party quiet,
1299 // and the leader cries "Get 'em!!!"
1301 Engine_EventWait(60);
1306 30);
1310 30);
1316 Engine_EventWait(20);
1319 // Preserve the return destinations before requesting the thieves' encounter.
1322 base = (s32)&SceneId_VaultInteriors;
1323 Event_SetNextDestination(base, 17);
1325 Battle_SetStart(3);
1328}
1329
1330/// The party walks through to entrance 11.
1331///
1332/// Reached by stepping on cell code 7 before the thieves are jailed (after,
1333/// the same cell is a plain exit); takes exit 11.
1334static void Event_GoToEntrance11(void) {
1337}
1338
1339/// The party climbs up into the inn's loft.
1340///
1341/// Reached by stepping on cell code 26; takes exit 15 to the loft's entrance.
1342static void Event_ClimbToAttic(void) {
1348}
1349
1350/// Leaving the loft before the thieves are confronted, the party hears the
1351/// roofer groan. "Uhnn... Uhnn..."
1352///
1353/// Reached by stepping on cell code 27 in the loft; takes exit 14 back down.
1354static void Event_LeaveAttic(void) {
1359 Engine_EventSetMessage(MsgVaultUhnnUhnn);
1362 }
1366}
1367
1368/// The suspects at the inn spot that weird kid with the party and run from him.
1369/// "What do you want?"
1370///
1371/// Reached by stepping on cell code 10 at the suspects' room while
1372/// FLAG_VAULT_IVAN_JOINED_ROD_SEARCH is set. Sets
1373/// FLAG_VAULT_SUSPECTS_APPROACHED and FLAG_SUSPECTS_FLEEING, starts their
1374/// routes and the callback that keeps them facing the leader.
1375/// XXX: the row has no condition that stops it after the first time; whether
1376/// it plays again depends on the leader's path to cell code 10.
1377static void Event_ApproachSuspects(void) {
1378
1379 struct FieldActor *actor24;
1380 struct FieldActor *actor25;
1381
1386 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
1387 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
1388 // Isaac walks in; the two start and spot Ivan with him: "It looks like that
1389 // weird kid is with them!"
1392 Engine_EventWait(10);
1395 Engine_EventWait(60);
1397 10);
1399 Engine_EventWait(20);
1400 Engine_EventSetMessage(MsgVaultWant);
1403 Engine_EventWait(60);
1407 // "Don't let him near me!" They run off to their routes' first spots.
1413 Map_CopyCellAttributes(14, 45, 3, 1, 14, 44);
1418 actor24->timer = 1;
1419 actor25->timer = 3;
1421}
1422
1423/// Stepping out, the party talks it over: Ivan can't read their minds while
1424/// they run; Garet tells Isaac to take the lead and corner them.
1425///
1426/// Reached by stepping on cell code 20, at the room's door, while
1427/// FLAG_SUSPECTS_FLEEING is set. Clears it and stops the facing callback; the
1428/// suspects go back to their places.
1430 struct FieldActor *actor24;
1431 struct FieldActor *actor25;
1432 s32 base;
1433
1439 if (actor24->timer <= 3) {
1441 } else {
1443 }
1444 if (actor25->timer <= 2) {
1446 } else {
1448 }
1450 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
1451 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
1452 // Outside the room, Garet and Ivan step out of the leader.
1454 Actor_SetPosition(IVAN, PIXELS(248), PIXELS(728));
1455 Actor_SetPosition(GARET, PIXELS(248), PIXELS(728));
1456 Actor_WalkTo(IVAN, 264, 744);
1457 Actor_WalkToAndWait(GARET, 232, 744);
1462 // Ivan: they're acting suspicious.
1464 base = MsgVaultTheyreActingSuspiciousSomethingsNot;
1472 // Garet: "But you can't use Mind Read if they keep running away, can you?"
1473 // Yes: Ivan asks how he can catch them; no: there must be a way.
1475 if (Engine_EventChooseYesNo(0, 0) != 0) {
1477 }
1479 // Garet's plan: the three of them surround one of the two.
1480 Engine_EventSetMessage((base + 4));
1483 Actor_ShowEmote(IVAN, 0x100, 0);
1484 Engine_EventWait(60);
1491 Actor_ShowEmote(GARET, 0x102, 0);
1492 Engine_EventWait(60);
1495 // "Isaac, you take the lead." The two walk back into him, and the suspects
1496 // are put back at their table.
1497 Engine_EventSetMessage(MsgVaultIsaacTakeLead);
1500 Engine_EventWait(40);
1504 Actor_WalkTo(IVAN, 248, 728);
1505 Actor_WalkToAndWait(GARET, 248, 728);
1506 Actor_SetPosition(GARET, 0, 0);
1507 Actor_SetPosition(IVAN, 0, 0);
1512 Map_CopyCellAttributes(14, 50, 3, 1, 14, 44);
1514}
1515
1516/// The party sets out to corner the two suspects.
1517///
1518/// Reached by stepping on cell code 21 while FLAG_VAULT_SUSPECTS_APPROACHED is
1519/// set. Sets FLAG_MENUS_RAISE_EVENT, so the menus answer with Garet's refusal,
1520/// and FLAG_SCENE_TEMP_50, so talking to Ivan or the suspects does nothing;
1521/// then starts the chase (VaultInteriors_StartActorStops).
1526}
1527
1528/// Has the suspects react to the party's return and resets their route states.
1529/// "Hey, they're back!"
1530///
1531/// Called by VaultInteriors_StartActorStops.
1533 Engine_EventWait(30);
1535 Engine_EventWait(20);
1536 Engine_EventSetMessage(MsgVaultTheyreBack);
1543 Engine_EventWait(20);
1550 {
1552 u16 routeIndex = 1;
1553
1554 suspect->timer = routeIndex;
1555 }
1556 {
1558 u16 routeIndex = 3;
1559
1560 suspect->timer = routeIndex;
1561 }
1562 Map_CopyCellAttributes(14, 48, 4, 1, 14, 44);
1563}
1564
1565/// Sets the three party images to the priority used during the mind-reading
1566/// scene.
1568 {
1569 struct AnimationObject *sprite = Object_GetById(ACTOR_PARTY_LEADER)->sprite;
1570 sprite->image.priority = 1;
1571 }
1572 {
1573 struct AnimationObject *sprite = Object_GetById(GARET)->sprite;
1574 sprite->image.priority = 1;
1575 }
1576 {
1577 struct AnimationObject *sprite = Object_GetById(IVAN)->sprite;
1578 sprite->image.priority = 1;
1579 }
1580}
1581
1582/// Once a suspect is cornered, Garet calls Ivan and Ivan reads their minds.
1583/// "Uh-oh! I'm surrounded!" "Now, Ivan!"
1584///
1585/// Reached through raised events 201 to 203, which
1586/// VaultInteriors_UpdateActorStops raises after thirty frames with at least
1587/// one suspect blocked: 201 the leader, 202 the thief, 203 both. Stops the
1588/// chase, clears FLAG_MENUS_RAISE_EVENT and FLAG_SCENE_TEMP_50, plays the
1589/// party's talk (VaultInteriors_DiscussMindReading) and sets
1590/// FLAG_VAULT_SUSPECTS_MIND_READ.
1592 s32 actor;
1593 struct EventWork *work;
1594
1595 work = gEventWork;
1609 Engine_EventWait(10);
1610 actor = ACTOR_SUSPECTED_LEADER;
1611 // The event identifies the suspects blocked on the last frame of the wait.
1612 switch (work->raisedTrigger) {
1615 Engine_EventSetMessage(MsgVaultImSurrounded);
1620 actor = ACTOR_SUSPECTED_THIEF;
1621 break;
1622 }
1623 // When both are cornered, the leader's reaction follows the thief's.
1624 // fall through
1626 Engine_EventSetMessage(MsgVaultTheresNowhereRun);
1629 actor = ACTOR_SUSPECTED_LEADER;
1631 break;
1632 }
1634 Actor_FaceActor(IVAN, actor, 0);
1637 Engine_EventWait(20);
1638 // "Now, Ivan!" "A-All right!" Ivan reads the cornered one's mind while the
1639 // two wonder what he is doing.
1640 Engine_EventSetMessage(MsgVaultNowIvan);
1643 Engine_EventWait(20);
1647 Engine_EventWait(60);
1652 // "Are you done, Ivan?" He nods, and the window closes.
1653 Actor_ShowEmote(IVAN, 0x100, 60);
1657 Engine_EventWait(20);
1660 Engine_EventWait(20);
1662 Engine_EventWait(40);
1668 // Move the discussion away from the suspects while the screen is closed.
1670 // The suspects stay at their table, turned toward the leader from now on.
1671 Map_CopyCellAttributes(14, 45, 3, 1, 14, 44);
1673 {
1675 s32 routeIndex = 5;
1676
1677 suspect->timer = routeIndex;
1678 }
1679 {
1681 s32 routeIndex = 4;
1682
1683 suspect->timer = routeIndex;
1684 }
1689}
1690
1691/// Shows the party's branching conversation about what Ivan learned: the
1692/// stolen goods are hidden in the inn, which they must search.
1693///
1694/// Called by Event_ReadCorneredSuspectsMinds while the screen is closed; sets
1695/// the party outside the room and opens the screen on them.
1697 s32 persistedWithQuestions;
1698
1699 // Move the party outside the room and the suspects back to their table.
1702 {
1704
1706 }
1707 FieldMap_SetViewBounds(PIXELS(32), PIXELS(576), PIXELS(400), PIXELS(936));
1709 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
1710 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
1712 Actor_SetPosition(IVAN, PIXELS(264), PIXELS(744));
1723 Engine_EventWait(30);
1724 {
1725 struct EventWork *work = gEventWork;
1726
1727 work->transitionFrames = 24;
1729 }
1732 Engine_EventWait(40);
1733 // "What did you learn, Ivan?" It is them: they hid the stolen goods
1734 // somewhere in this inn, but won't let him near again.
1736 Engine_EventWait(10);
1737 Engine_EventSetMessage(MsgVaultLearn);
1747 Actor_ShowEmote(GARET, 0x102, 0);
1748 Engine_EventWait(60);
1752 Engine_EventWait(20);
1754 // Garet: they have to search the inn. Each no leads to another plea, from
1755 // Garet and then Ivan; three noes and Garet vouches for Isaac's sense of
1756 // duty, while any yes gets "Leave it to us!"
1758 persistedWithQuestions = 0;
1759 if (Engine_EventChooseYesNo(0, 0) != 0) {
1760 Engine_EventWait(20);
1764 persistedWithQuestions = 0;
1765 if (Engine_EventChooseYesNo(0, 0) != 0) {
1766 Engine_EventWait(20);
1767 Engine_ActorShowEmote(IVAN, 0x102, 0);
1768 Engine_EventWait(60);
1772 persistedWithQuestions = 0;
1773 if (Engine_EventChooseYesNo(2, 0) != 0) {
1774 Engine_EventWait(20);
1775 Engine_ActorShowEmote(IVAN, 0x105, 0);
1776 Engine_EventWait(60);
1780 Engine_EventWait(10);
1783 Engine_ActorShowEmote(IVAN, 0x101, 0);
1784 Engine_EventWait(60);
1789 persistedWithQuestions = 1;
1791 }
1792 }
1793 }
1794 if (persistedWithQuestions == 0) {
1795 Engine_EventSetMessage(MsgVaultLeave);
1799 }
1800 // "Let's go, Ivan." Garet and Ivan walk back into the leader.
1802 Engine_EventWait(60);
1810 Actor_WalkTo(IVAN, 248, 728);
1811 Actor_WalkToAndWait(GARET, 248, 728);
1814}
1815
1816/// The leader stepping on one of the route triggers 11 to 18 moves the
1817/// fleeing suspects on to their next spots.
1818///
1819/// Reached by stepping on cell codes 11 to 18 while FLAG_SUSPECTS_FLEEING is
1820/// set.
1822 switch (gEventWork->touchedTrigger) {
1823 case 11:
1828 break;
1829 case 12:
1836 break;
1837 case 13:
1844 break;
1845 case 14:
1850 break;
1851 case 15:
1856 break;
1857 case 16:
1864 break;
1865 case 17:
1872 break;
1873 case 18:
1878 break;
1879 }
1880}
1881
1882/// Installs a route script only when the suspect is in its expected state.
1883static void VaultInteriors_AdvanceSuspectRoute(s32 actor, s32 expected,
1884 s32 next, const s32 *actions) {
1885 struct FieldActor *suspect = Object_GetById(actor);
1886
1887 if (suspect->timer == expected) {
1888 Actor_SetActionScript(actor, actions);
1889 suspect->timer = next;
1890 }
1891}
1892
1893#include "common/vault_spotflag.h"
1894
1895/// On arrival: restores each room for the story so far, and plays the loft's
1896/// scenes: the tied-up roofer, the rematch, and the defeat or victory.
1897///
1898/// Called by the engine once the actors are placed, by entrance. In the house
1899/// with the Bone, after the thieves are jailed, places the Bone and starts
1900/// Vault_UpdateBoneProximityFlag. After a lost battle (entrance 16) takes exit
1901/// 16; after a won one (17) sets FLAG_VAULT_THIEVES_JAILED through
1902/// VaultInteriors_ReturnStolenGoods, which also removes Ivan from the party.
1905 switch (gGameState.entrance) {
1906 case 5: {
1907 s32 zero = 0;
1908
1909 // The gem owner's house: he stands on the floor.
1913 } break;
1914 case 10:
1915 // The mayor's house: Ivan waits a step back once met and is gone once he
1916 // has joined; after the thieves are jailed, the mayor stands by the door.
1918 Actor_SetPosition(IVAN, PIXELS(376), PIXELS(376));
1920 }
1923 }
1929 }
1930 break;
1931 case 7:
1932 case 11:
1933 // The bone giver's house: once the thieves are jailed, the Bone lies on
1934 // the floor beside her; after the mind reading and before that, she is
1935 // out.
1944 }
1945 break;
1946 case 12:
1947 // The inn: back from a battle mid-chase, the suspects keep running.
1952 Map_CopyCellAttributes(14, 45, 3, 1, 14, 44);
1955 break;
1956 }
1960 }
1961 // Once approached, the room's doorway collision changes; after the mind
1962 // reading the suspects sit turned toward the leader.
1964 Map_CopyCellAttributes(14, 45, 3, 1, 14, 44);
1966 Map_CopyCellAttributes(14, 50, 3, 1, 14, 44);
1967 break;
1968 }
1973 }
1974 break;
1975 case 13:
1976 case 14:
1977 // The room with the crate: the crate keeps its place once moved, and the
1978 // passage behind it stays open.
1980 Map_CopyCellsTo(54, 2, 35, 20, 2, 10);
1981 Map_CopyCellsTo(54, 2, 95, 20, 2, 10);
1982 Map_CopyCellsTo(54, 2, 35, 80, 2, 10);
1983 Map_CopyCellsTo(54, 2, 46, 21, 4, 8);
1984 Map_CopyCellsTo(54, 2, 46, 81, 4, 8);
1989 Map_CopyCellAttributes(101, 24, 3, 4, 41, 24);
1990 }
1991 break;
1992 case 15:
1994 Map_CopyCellsTo(54, 2, 44, 21, 2, 8);
1995 Map_CopyCellsTo(54, 2, 44, 81, 2, 8);
1997 // The loft: emptied crates after the thieves are jailed; else the roofer
1998 // lies tied, groaning to MUS_017, or the thieves wait for a rematch.
2004 break;
2005 }
2010 break;
2011 }
2015 Engine_EventSetMessage(MsgVaultUhnnUhnn);
2018 break;
2019 case 16:
2020 // Lost to the thieves: they gloat, and the party wakes up elsewhere.
2021 Map_CopyCells(54, 2, 2, 8, 44, 21);
2022 Map_CopyCells(54, 2, 2, 8, 44, 81);
2026 break;
2027 case 17:
2028 // Won: the thieves are caught and the stolen goods handed back.
2029 Map_CopyCells(54, 2, 2, 8, 44, 21);
2030 Map_CopyCells(54, 2, 2, 8, 44, 81);
2035 break;
2036 }
2041 break;
2042 }
2043 return 0;
2044}
2045
2046/// Keeps both suspects facing the leader while they evade the party.
2047///
2048/// Run each frame as a scene callback, from Event_ApproachSuspects until
2049/// Event_DiscussSuspiciousGuests, and again once their minds are read.
2054
2055 first->facing = ArcTan2(origin->z.fixed - first->z.fixed,
2056 origin->x.fixed - first->x.fixed);
2057 second->facing = ArcTan2(origin->z.fixed - second->z.fixed,
2058 origin->x.fixed - second->x.fixed);
2059}
2060
2061/// Shows the thieves' reaction after the party loses their battle: the party
2062/// lies beaten and the thieves keep the roofer as their hostage.
2063///
2064/// Called by Scene_Initialize at entrance 16, the battle's defeat
2065/// destination; the scene then takes exit 16 to Vault's Sanctum.
2067 struct FieldActor *actor;
2069
2070 // The party lies on the floor (animation 19) before the three thieves.
2081 Actor_SetPosition(GARET, PIXELS(808), PIXELS(432));
2082 Actor_SetPosition(IVAN, PIXELS(776), PIXELS(432));
2092 actor = Object_GetById(IVAN);
2094 actor = Object_GetById(GARET);
2102 Engine_EventWait(60);
2103 // "These kids are nothing to worry about." The roofer groans.
2105 Engine_EventSetMessage(MsgVaultTheseKidsNothingWorryAbout);
2108 // The two men step to the roofer: he stays as their hostage.
2115 Engine_EventWait(30);
2121}
2122
2123/// Arranges the attic confrontation and restarts the thieves' battle. "They
2124/// won't go away, will they? They're back!"
2125///
2126/// Called by Scene_Initialize at the loft's entrance 15 once
2127/// FLAG_VAULT_THIEVES_CONFRONTED is set. Starts the same battle as
2128/// Event_FreeRooferAndConfrontThieves.
2130
2131 // The thieves stand over the roofer as the party comes up.
2139 Actor_SetPosition(GARET, PIXELS(808), PIXELS(432));
2140 Actor_SetPosition(IVAN, PIXELS(792), PIXELS(456));
2149 Engine_TaskWait(1);
2152 Engine_EventWait(60);
2153 Engine_EventSetMessage(MsgVaultWontGoAway);
2155 Engine_EventWait(20);
2158 Engine_EventWait(20);
2161 30);
2165 30);
2171 Engine_EventWait(20);
2172 // "We'll make you sorry you were ever born! Get 'em!!" and the battle.
2178 Battle_SetStart(3);
2180}
2181
2182/// Counts the Venus Djinn Ivan holds, which he gives back before he leaves the
2183/// party.
2186}
2187
2188#include "common/vault_djinn.h"
2189
2190/// Stages the defeated thieves and gathers the townspeople in the attic.
2191///
2192/// Called by Scene_Initialize at entrance 17, the battle's victory
2193/// destination, unless the party is only coming back to where it was; then
2194/// VaultInteriors_ReturnStolenGoods follows.
2196 struct FieldActor *actor;
2197 struct EventWork *work;
2198 const s32 *actions;
2199 struct AnimationObject *thirdThiefSprite;
2200
2202 thirdThiefSprite = actor->sprite;
2203 // The beaten thieves lie heaving (animation 9 and the action table's
2204 // squash) before the party.
2219 thirdThiefSprite->image.priority = 3;
2223 Actor_SetPosition(GARET, PIXELS(808), PIXELS(432));
2224 Actor_SetPosition(IVAN, PIXELS(776), PIXELS(440));
2236 Engine_EventWait(30);
2238 Engine_EventWait(30);
2239 // "They... They got us..." The roofer thought they were goners; he slips
2240 // past Garet, cheers the win and runs for the mayor.
2241 Engine_EventSetMessage(MsgVaultTheyTheyGotUs);
2244 Engine_EventWait(60);
2247 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
2248 Actor_WalkToAndWait(GARET, 792, 432);
2252 Actor_WalkToAndWait(GARET, 808, 432);
2254 Engine_EventWait(20);
2258 Engine_EventWait(20);
2268 Engine_EventWait(50);
2269 // The thieves grumble; Garet: stealing is wrong, evil never prevails.
2274 Engine_EventWait(20);
2282 Actor_ShowEmote(GARET, 0x103, 0);
2283 Engine_EventWait(60);
2285 // Ivan will take the rod to Hammet in Lunpa, and asks what the two will do:
2286 // go after Saturos and the others.
2294 Actor_ShowEmote(GARET, 0x100, 0);
2295 Engine_EventWait(60);
2297 Actor_ShowEmote(IVAN, 0x101, 0);
2298 Engine_EventWait(60);
2302 // Ivan reads Isaac's mind. Garet: "Shouldn't we stop him?" Yes: too late,
2303 // he's done. No: "If you say so."
2310 Engine_EventWait(20);
2312 Engine_EventWait(60);
2315 if (Engine_EventChooseYesNo(0, 0) == 0) {
2316 Engine_EventWait(20);
2322 Engine_EventWait(20);
2324 } else {
2326 Actor_ShowEmote(GARET, 0x102, 0);
2327 Engine_EventWait(60);
2334 Engine_EventWait(20);
2335 }
2336 // "I see... So that's what happened..." The roofer comes back with the
2337 // mayor and two townsmen.
2338 Actor_ShowEmote(IVAN, 0x102, 0);
2339 Engine_EventWait(60);
2341 Engine_EventSetMessage(MsgVaultSeeThatsHappened);
2347 Engine_EventWait(30);
2352 Engine_EventWait(20);
2371 // The mayor scolds them for stealing in a disaster; the thieves talk back.
2376 // "What should we do with them?" Locked up for a long, long time; the two
2377 // townsmen rouse the thieves to tie them up.
2379 20);
2381 Engine_EventWait(20);
2385 20);
2392 20);
2401 Engine_EventWait(20);
2404 20);
2407 20);
2412 // The window closes while the thieves are tied up.
2413 work = gEventWork;
2414 work->transitionFrames = 30;
2418 Engine_EventWait(60);
2420}
2421
2422/// Returns the stolen goods and rod, thanks the party, and clears the attic.
2423///
2424/// Called by Scene_Initialize after VaultInteriors_DefeatThieves. Sets
2425/// FLAG_VAULT_THIEVES_JAILED; the thieves are led away, the mayor's urn and
2426/// the Sanctum's gold statue come out of the crates, Ivan takes the Shaman's
2427/// Rod, gives back any Venus Djinn and leaves the party, and every actor of
2428/// the loft is cleared away.
2430 struct FieldActor *temporaryActor;
2431 struct FieldActor *actor;
2432 s32 aftermath;
2433 s32 rod;
2434 struct EventWork *event;
2435
2436 event = gEventWork;
2438 // With the screen still closed, the crates go back along the wall and the
2439 // thieves stand tied before the mayor.
2441 {
2443
2445 }
2473 Actor_SetPosition(GARET, PIXELS(808), PIXELS(440));
2474 Actor_SetPosition(IVAN, PIXELS(776), PIXELS(440));
2482 Engine_EventWait(40);
2483 // "Isaac, right? I won't forget this!" "Take them away!"
2485 aftermath = MsgVaultYouIsaacRightWontForget;
2486 Engine_EventSetMessage(aftermath);
2489 Engine_EventWait(20);
2496 Engine_EventWait(60);
2497 // The escort leads the three thieves down the ladder, the roofer after them.
2503 Engine_EventWait(20);
2505 Engine_EventWait(15);
2507 Engine_EventWait(35);
2509 Engine_EventWait(20);
2512 Engine_EventWait(40);
2513 // The mayor and the searcher thank the party.
2533 // "Let's take a look at what they stole." The two go round to the crates.
2538 Engine_EventWait(50);
2540 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
2541 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
2542 Actor_WalkToAndWait(GARET, 792, 456);
2544 Engine_EventWait(30);
2545 Actor_WalkToAndWait(IVAN, 792, 408);
2547 Actor_WalkToAndWait(GARET, 808, 456);
2549 Engine_EventWait(100);
2554 Engine_EventWait(20);
2555 // The mayor opens the first crate and his urn rises out of it.
2565 Engine_EventWait(60);
2566 Engine_MessageShowCentered((aftermath + 5), 1);
2579 Engine_EventWait(40);
2580 // The searcher opens the second: the gold statue stolen from the Sanctum.
2591 Engine_EventWait(60);
2592 Engine_MessageShowCentered((aftermath + 8), 1);
2597 Engine_EventWait(60);
2602 Engine_EventWait(20);
2606 // The searcher finds another chest; the mayor asks whether it is what Ivan
2607 // was looking for, and he can return to Master Hammet.
2609 Engine_EventWait(30);
2611 Engine_EventWait(60);
2613 Engine_EventWait(20);
2617 Actor_ShowEmote(IVAN, 0x100, 0);
2618 Engine_EventWait(60);
2624 Engine_EventWait(30);
2633 // Hammet was seen heading toward Lunpa: Dodonpa must have kidnapped him.
2635 Engine_EventWait(20);
2643 Actor_ShowEmote(IVAN, 0x102, 0);
2644 Engine_EventWait(60);
2650 Engine_EventWait(30);
2654 // Ivan rushes forward: what will happen to Hammet? The mayor calms him:
2655 // Dodonpa wants a ransom, so Hammet is safe for now.
2658 Actor_SetSpeed(IVAN, PIXELS(3) / 2, PIXELS(3) / 4);
2659 Actor_WalkToAndWait(IVAN, 800, 408);
2669 Engine_EventWait(60);
2672 Engine_EventWait(20);
2675 Actor_ShowEmote(GARET, 0x101, 0);
2676 Actor_ShowEmote(IVAN, 0x101, 0);
2677 Engine_EventWait(60);
2683 Engine_EventWait(20);
2686 // The mayor asks the two their names, thanks them, and asks them to come
2687 // see him before they leave town.
2688 Actor_ShowEmote(IVAN, 0x105, 0);
2689 Engine_EventWait(60);
2692 20);
2696 Engine_EventWait(20);
2699 Engine_EventWait(20);
2704 20);
2706 // The mayor and the searcher leave down the ladder.
2710 Actor_WalkTo(GARET, 792, 456);
2711 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
2712 Actor_WalkTo(IVAN, 776, 432);
2719 temporaryActor = Object_GetById(ACTOR_ATTIC_SEARCHER);
2720 {
2721 u8 *pauseFlag = &temporaryActor->paused;
2722 u8 paused = 1;
2723
2724 *pauseFlag = paused;
2725 }
2726 temporaryActor->targetX = ACTOR_NO_TARGET;
2727 temporaryActor->targetY = ACTOR_NO_TARGET;
2728 temporaryActor->targetZ = ACTOR_NO_TARGET;
2731 Engine_EventWait(50);
2733 Actor_WalkToAndWait(GARET, 808, 440);
2735 Engine_EventWait(20);
2745 Engine_EventWait(30);
2746 // Alone, Garet tries to cheer Ivan up; Ivan only wants to rescue Hammet,
2747 // but has seen the two's mission in their minds and won't ask their help.
2750 Actor_ShowEmote(IVAN, 0x105, 0);
2751 Engine_EventWait(50);
2755 Engine_EventWait(20);
2764 Engine_EventWait(20);
2767 Engine_EventWait(20);
2774 Actor_ShowEmote(GARET, 0x101, 0);
2775 Engine_EventWait(60);
2779 Actor_ShowEmote(GARET, 0x100, 0);
2780 Engine_EventWait(60);
2784 Actor_ShowEmote(GARET, 0x102, 0);
2785 Engine_EventWait(60);
2790 // "Then, I suppose this is good-bye." A no has Garet say Isaac would help,
2791 // and Ivan decline.
2793 if (Engine_EventChooseYesNo(0, 0) != 0) {
2794 Engine_EventWait(20);
2796 Engine_EventWait(20);
2800 }
2801 // Ivan walks round to the third crate and takes the Shaman's Rod from it.
2803 Actor_WalkToAndWait(IVAN, 800, 456);
2806 Actor_WalkToAndWait(IVAN, 856, 456);
2809 Actor_WalkToAndWait(IVAN, 856, 376);
2813 Engine_EventWait(20);
2815 temporaryActor =
2817 Engine_EventWait(60);
2818 rod = MsgVaultIvanGotShamansRod;
2820 Engine_ObjectDispatchRelease(temporaryActor);
2822 Engine_EventWait(20);
2824 Actor_WalkToAndWait(IVAN, 856, 456);
2827 Actor_WalkToAndWait(IVAN, 800, 456);
2830 Actor_WalkToAndWait(IVAN, 776, 424);
2833 // He thanks the town, hands back any Venus Djinni and leaves the party.
2835 Engine_EventSetMessage((rod + 1));
2838 {
2839 u16 *slot = &event->message;
2840 s32 saved = (s16)*slot;
2841
2843 Engine_EventSetMessage(MsgVaultWaitDontWantTakeYour);
2846 }
2848 *slot = saved;
2849 }
2851 Actor_WalkToAndWait(IVAN, 776, 408);
2854 // Ivan goes down the ladder; Garet: they'd better get moving too.
2855 Actor_WalkToAndWait(IVAN, 744, 408);
2856 Engine_EventWait(40);
2859 Engine_EventWait(20);
2864 if (actor != NULL) {
2865 Actor_SetDestination(GARET, actor->x.part.pixel, actor->z.part.pixel);
2866 }
2868 Actor_SetPosition(GARET, 0, 0);
2869 Engine_EventWait(30);
2870 // Clear the loft of everyone the cutscene used.
2878 Actor_SetPosition(IVAN, 0, 0);
2881}
2882
2883/// Opens the window transition and waits one frame after it finishes.
2885 struct EventWork *state;
2886
2887 state = gEventWork;
2892}
2893
2894static void VaultInteriors_ShowMessageAndWait(s32 actorId, s32 waitFrames) {
2895 Engine_EventShowMessage(actorId, 0);
2896 Engine_EventWait(waitFrames);
2897}
2898
2899static void VaultInteriors_FaceActorAndWait(s32 actorId, s32 targetId,
2900 s32 waitFrames) {
2901 Engine_ActorFaceActor(actorId, targetId, 0);
2902 Engine_EventWait(waitFrames);
2903}
2904
2905static void VaultInteriors_FaceEachOtherAndWait(s32 firstId, s32 secondId,
2906 s32 waitFrames) {
2907 Engine_ActorFaceEachOther(firstId, secondId, 0);
2908 Engine_EventWait(waitFrames);
2909}
2910
2911/// Waits for the animation to change before the following pause.
2912static void VaultInteriors_PlayAnimationAndWait(s32 actorId, s32 animation,
2913 s32 waitFrames) {
2914 Engine_ActorSetAnimation(actorId, animation, waitFrames);
2916 Engine_EventWait(waitFrames);
2917}
2918
2919/// Begins Mind Read, chooses its target, and shows its opening effect.
2920static void VaultInteriors_BeginMindRead(s32 casterId, s32 targetId) {
2922 Engine_PsynergySetTarget(casterId, targetId);
2925 Engine_TaskWait(1);
2926}
2927
2928/// Finishes Mind Read and releases its scene effect objects.
2933}
2934
2935#include "common/vault_itemobj.h"
2936
2937/// Finds the route node containing the actor's position on the eight-pixel
2938/// grid.
2939static struct VaultInteriorsStop *
2941 s32 gridX = (position[0] - PIXELS(64)) >> 19;
2942 s32 gridZ = (position[2] - PIXELS(624)) >> 19;
2944 struct VaultInteriorsStop *result = NULL;
2945 u32 i;
2946
2947 for (i = 0; i <= 36; i++, stop++) {
2948 s32 stopX = stop->gridX;
2949
2950 if (stopX == gridX || stopX + 1 == gridX) {
2951 s32 stopZ = stop->gridZ;
2952
2953 if (stopZ == gridZ || stopZ + 1 == gridZ) {
2954 result = stop;
2955 break;
2956 }
2957 }
2958 }
2959 return result;
2960}
2961
2962/// Chooses the outgoing connection nearest the requested facing.
2963static struct VaultInteriorsStop *
2965 s16 *requestedFacing) {
2966 struct VaultInteriorsStopConnection *connection;
2967 s32 stopIndex;
2968 s32 nearestDifference;
2969 s32 chosenFacing;
2970 s32 angleDifference;
2971 u32 connectionIndex;
2972 u16 connectionFacing;
2973
2974 stopIndex = -1;
2975 chosenFacing = *requestedFacing;
2976 connection = node->connections;
2977 nearestDifference = 0x8000;
2978 for (connectionIndex = 0; connectionIndex <= 2;
2979 connectionIndex++, connection++) {
2980 connectionFacing = connection->facing << 8;
2981 angleDifference = (s16)(connectionFacing - *requestedFacing);
2982 if (angleDifference < 0)
2983 angleDifference = -angleDifference;
2984 /* FAKEMATCH: the used-stop test reads the stopIndex through a volatile
2985 * lvalue, so it is loaded again for the result; as a plain test, 9
2986 * instructions differ in tbs-en. */
2987 if (*(volatile u8 *)&connection->stopIndex != 0xff &&
2988 angleDifference < nearestDifference) {
2989 nearestDifference = angleDifference;
2990 stopIndex = connection->stopIndex;
2991 chosenFacing = (s16)connectionFacing;
2992 }
2993 }
2994 if (stopIndex == -1)
2995 return 0;
2996 *requestedFacing = chosenFacing;
2998}
2999
3000/// Checks whether an actor's destination or current position lies within eight
3001/// pixels.
3003 struct FieldActor *actor = Engine_ActorLookup(id);
3004 s32 targetX = actor->targetX;
3005 s32 targetZ;
3006
3007 if (targetX == ACTOR_NO_TARGET) {
3008 targetX = actor->x.fixed;
3009 }
3010 targetZ = actor->targetZ;
3011 if (targetZ == ACTOR_NO_TARGET) {
3012 targetZ = actor->z.fixed;
3013 }
3014
3015 targetX = (targetX - x) >> 16;
3016 targetZ = (targetZ - z) >> 16;
3017 if (targetX * targetX + targetZ * targetZ <= 64)
3018 return 1;
3019 return 0;
3020}
3021
3022/// Checks whether an actor's destination or current position lies within
3023/// sixteen pixels.
3025 struct FieldActor *actor = Engine_ActorLookup(id);
3026 s32 ax;
3027 s32 az;
3028
3029 ax = actor->targetX;
3030 if (ax == ACTOR_NO_TARGET)
3031 ax = actor->x.fixed;
3032 az = actor->targetZ;
3033 if (az == ACTOR_NO_TARGET)
3034 az = actor->z.fixed;
3035 ax = (ax - x) >> 16;
3036 az = (az - z) >> 16;
3037 if (ax * ax + az * az <= 0x100)
3038 return 1;
3039 return 0;
3040}
3041
3042/// Reserves a full cell around the leader and half a cell around each actor
3043/// following a route. Testing destinations as well as current positions
3044/// prevents two actors choosing the same stop while still walking.
3046 s32 x;
3047 s32 z;
3048
3049 if (stop == NULL) {
3050 return 1;
3051 }
3052 x = (stop->gridX << 19) + PIXELS(72);
3053 z = (stop->gridZ << 19) + PIXELS(632);
3055 0 ||
3058 0 ||
3060 0) {
3061 return -1;
3062 }
3063 return 0;
3064}
3065
3066/// Sets the actor's destination to the route stop's cell center.
3068 struct VaultInteriorsStop *stop) {
3069 Engine_ObjectSetPosition(actor, (stop->gridX << 19) + PIXELS(72), 0,
3070 (stop->gridZ << 19) + PIXELS(632));
3071}
3072
3073/// Steers Ivan and both suspects through the graph and detects a sustained
3074/// cornering.
3075///
3076/// Run each frame as a scene callback from VaultInteriors_StartActorStops
3077/// until Event_ReadCorneredSuspectsMinds removes it. Raises event 200 plus the
3078/// blocked suspects (1 the leader, 2 the thief) after thirty frames with at
3079/// least one suspect blocked; a frame when both can move restarts the wait.
3081 struct FieldActor *leader;
3082 struct FieldActor *actor;
3083 struct EventWork *work;
3084 struct VaultInteriorsStop *entry;
3085 struct VaultInteriorsStop *destination;
3086 s32 dx;
3087 s32 dz;
3088 s32 blocked;
3089 u16 angle;
3090 s16 facing;
3091 s16 facingDifference;
3092
3094 blocked = 0;
3095 work = gEventWork;
3096 actor = Engine_ActorLookup(IVAN);
3097 entry = VaultInteriors_FindStopAtPosition(&actor->x.fixed);
3098 if (entry != NULL && actor->targetX == ACTOR_NO_TARGET) {
3099 dx = actor->x.fixed - leader->x.fixed;
3100 dz = actor->z.fixed - leader->z.fixed;
3101 facing = leader->facing;
3102 angle = ArcTan2(dz, dx);
3103 dx >>= 16;
3104 dz >>= 16;
3105 if (work->blockedSteps > 0 && dx * dx + dz * dz <= 400 &&
3106 (facingDifference = (u16)facing - angle) > -0x1000 &&
3107 facingDifference < 0x1000) {
3108 /* FAKEMATCH: a dead store keeps this empty branch through the first jump
3109 * optimization (bge to the else, then b past it); as an empty branch, 4
3110 * instructions differ in tbs-en. */
3111 facingDifference = 0;
3112#if TBS_PATCH_1
3113 } else if (dx * dx + dz * dz > 64) {
3114#else
3115 } else {
3116#endif
3117 facing = actor->facing;
3118 }
3119 destination = VaultInteriors_SnapToNearestStop(entry, &facing);
3120 if (VaultInteriors_CheckStopOccupancy(destination) == 0) {
3121 VaultInteriors_MoveActorToStop(actor, destination);
3122 Object_SetMode(actor, 2);
3123 } else {
3124 Object_SetMode(actor, 1);
3125 }
3126 }
3127
3128 // Each suspect tries a random turn, then reverses when that route is
3129 // occupied.
3131 entry = VaultInteriors_FindStopAtPosition(&actor->x.fixed);
3132 if (entry != NULL && actor->targetX == ACTOR_NO_TARGET) {
3133 u32 turn = (u32)Engine_RandomNext() * 2 >> 16;
3134 s32 currentFacing;
3135
3136 turn *= 0x60000000;
3137 currentFacing = actor->facing;
3138 facing = ((turn - 0x30000000) >> 16) + currentFacing;
3139 destination = VaultInteriors_SnapToNearestStop(entry, &facing);
3140 if (VaultInteriors_CheckStopOccupancy(destination) != 0) {
3141 facing = actor->facing + 0x8000;
3142 destination = VaultInteriors_SnapToNearestStop(entry, &facing);
3143 if (VaultInteriors_CheckStopOccupancy(destination) == 0) {
3145 goto move_first;
3146 }
3147 Object_SetMode(actor, 4);
3148 blocked = 1;
3149 } else {
3150 move_first:
3151 VaultInteriors_MoveActorToStop(actor, destination);
3152 Object_SetMode(actor, 2);
3153 }
3154 }
3155
3157 entry = VaultInteriors_FindStopAtPosition(&actor->x.fixed);
3158 if (entry != NULL && actor->targetX == ACTOR_NO_TARGET) {
3159 u32 turn = (u32)Engine_RandomNext() * 3 >> 16;
3160 s32 currentFacing;
3161
3162 turn *= 0x30000000;
3163 currentFacing = actor->facing;
3164 facing = ((turn - 0x30000000) >> 16) + currentFacing;
3165 destination = VaultInteriors_SnapToNearestStop(entry, &facing);
3166 if (VaultInteriors_CheckStopOccupancy(destination) != 0) {
3167 facing = actor->facing + 0x8000;
3168 destination = VaultInteriors_SnapToNearestStop(entry, &facing);
3169 if (VaultInteriors_CheckStopOccupancy(destination) == 0) {
3171 goto move_second;
3172 }
3173 Object_SetMode(actor, 4);
3174 blocked += 2;
3175 } else {
3176 move_second:
3177 VaultInteriors_MoveActorToStop(actor, destination);
3178 Object_SetMode(actor, 2);
3179 }
3180 }
3181 // A failed route choice alone is not enough to end the chase.
3182 if (blocked != 0) {
3185 } else {
3186 gVaultInteriors_StopTimer = blocked;
3187 }
3188}
3189
3190/// Arranges the chase, constrains its camera, and starts the route callback.
3191///
3192/// Called by Event_BeginCorneringSuspects. Starts
3193/// VaultInteriors_UpdateActorStops and the chase music, MUS_009.
3196 Camera_MoveTo(PIXELS(168), -1, PIXELS(656), 1);
3198 Actor_SetSpeed(GARET, PIXELS(4) / 5, PIXELS(2) / 5);
3199 Actor_SetSpeed(IVAN, PIXELS(4) / 5, PIXELS(2) / 5);
3201 Actor_SetPosition(GARET, PIXELS(248), PIXELS(696));
3202 Actor_SetPosition(IVAN, PIXELS(248), PIXELS(696));
3204 Actor_WalkTo(GARET, 248, 712);
3205 Actor_WalkToAndWait(IVAN, 232, 696);
3212 FieldMap_SetViewBounds(PIXELS(48), PIXELS(576), PIXELS(288), PIXELS(736));
3213 Actor_SetSpeed(GARET, PIXELS(1), PIXELS(1) / 2);
3214 Actor_SetSpeed(IVAN, PIXELS(3) / 4, PIXELS(3) / 8);
3219 // XXX: flag 0x1ff is cleared here and named nowhere else; a reader of it in
3220 // the engine or another scene would say what it holds.
3221 GameFlag_Clear(0x1ff);
3224}
3225
3226// clang-format off
3227// A missing edge keeps both sentinel bytes; valid facings use the angle's high
3228// byte.
3229#define NO_CONNECTION {255, 0xff, {0, 0}}
3230#define CONNECTION(stop, direction) {stop, (direction) >> 8, {0, 0}}
3232 {4, 0, {0},
3234 {6, 0, {0},
3236 {8, 0, {0},
3238 {10, 0, {0},
3240 {12, 0, {0},
3242 {14, 0, {0},
3244 {16, 0, {0},
3246 {18, 0, {0},
3248 {20, 0, {0},
3250 {22, 0, {0},
3252 {24, 0, {0},
3254 {24, 2, {0},
3256 {24, 4, {0},
3258 {24, 6, {0},
3260 {24, 8, {0},
3262 {22, 8, {0},
3264 {20, 8, {0},
3266 {18, 8, {0},
3268 {16, 8, {0},
3270 {14, 8, {0},
3272 {12, 8, {0},
3274 {10, 8, {0},
3276 {8, 8, {0},
3278 {6, 8, {0},
3280 {4, 8, {0},
3282 {2, 8, {0},
3284 {0, 8, {0},
3286 {0, 6, {0},
3288 {0, 4, {0},
3290 {0, 2, {0},
3292 {2, 1, {0},
3294 {8, 2, {0},
3296 {8, 4, {0},
3298 {8, 6, {0},
3300 {16, 2, {0},
3302 {16, 4, {0},
3304 {16, 6, {0},
3306};
3307
3308#undef CONNECTION
3309#undef NO_CONNECTION
3310
3312 SC_ADD(SW_SCALE_Y, (-Q16_ONE / 16)),
3313 SC_ADD(SW_SCALE_X, (-Q16_ONE / 256)),
3314 SC_WAIT(2),
3315 SC_ADD(SW_SCALE_Y, (-Q16_ONE / 16)),
3316 SC_ADD(SW_SCALE_X, (Q16_ONE / 256)),
3317 SC_WAIT(2),
3320 SC_WAIT(4),
3321 SC_ADD(SW_SCALE_Y, (-Q16_ONE / 16)),
3322 SC_ADD(SW_SCALE_X, (-Q16_ONE / 256)),
3323 SC_WAIT(2),
3324 SC_ADD(SW_SCALE_Y, (-Q16_ONE / 16)),
3325 SC_ADD(SW_SCALE_X, (Q16_ONE / 256)),
3326 SC_WAIT(2),
3329 SC_WAIT(180),
3331};
3332
3334 SC_ARG(2),
3335 SC_MOVE(PIXELS(776), 0, PIXELS(408)),
3336 SC_SYNC,
3337 SC_MOVE(PIXELS(776), 0, PIXELS(400)),
3338 SC_SYNC,
3339 SC_MOVE(PIXELS(800), 0, PIXELS(400)),
3340 SC_SYNC,
3341 SC_ARG(1),
3342 SC_SET(SW_FACING, 0x3000),
3343 SC_WAIT(20),
3344 SC_END,
3345};
3346
3348 SC_ARG(2),
3349 SC_MOVE(PIXELS(776), 0, PIXELS(408)),
3350 SC_SYNC,
3351 SC_MOVE(PIXELS(776), 0, PIXELS(416)),
3352 SC_SYNC,
3353 SC_ARG(1),
3354 SC_SET(SW_FACING, 0x3000),
3355 SC_WAIT(20),
3356 SC_END,
3357};
3358
3360 SC_SET(SW_SPEED, PIXELS(4) / 5),
3361 SC_ARG(2),
3362 SC_MOVE(PIXELS(776), 0, PIXELS(408)),
3363 SC_SYNC,
3364 SC_MOVE(PIXELS(744), 0, PIXELS(408)),
3365 SC_SYNC,
3366 SC_ARG(1),
3367 SC_POS(0, 0, 0),
3368 SC_END,
3369};
3370
3372 SC_SET(SW_SPEED, PIXELS(4) / 5),
3373 SC_ARG(6),
3374 SC_MOVE(PIXELS(776), 0, PIXELS(408)),
3375 SC_SYNC,
3376 SC_MOVE(PIXELS(744), 0, PIXELS(408)),
3377 SC_SYNC,
3378 SC_ARG(1),
3379 SC_POS(0, 0, 0),
3380 SC_END,
3381};
3382
3384 SC_SET(SW_SPEED, PIXELS(4) / 5),
3385 SC_ARG(2),
3386 SC_MOVE(PIXELS(792), 0, PIXELS(408)),
3387 SC_SYNC,
3388 SC_MOVE(PIXELS(808), 0, PIXELS(440)),
3389 SC_SYNC,
3390 SC_MOVE(PIXELS(808), 0, PIXELS(456)),
3391 SC_SYNC,
3392 SC_MOVE(PIXELS(840), 0, PIXELS(456)),
3393 SC_SYNC,
3394 SC_MOVE(PIXELS(856), 0, PIXELS(408)),
3395 SC_SYNC,
3396 SC_ARG(1),
3398 SC_WAIT(10),
3399 SC_END,
3400};
3401
3403 SC_SET(SW_SPEED, PIXELS(4) / 5),
3404 SC_ARG(2),
3405 SC_MOVE(PIXELS(808), 0, PIXELS(408)),
3406 SC_SYNC,
3407 SC_MOVE(PIXELS(808), 0, PIXELS(456)),
3408 SC_SYNC,
3409 SC_MOVE(PIXELS(840), 0, PIXELS(456)),
3410 SC_SYNC,
3411 SC_MOVE(PIXELS(856), 0, PIXELS(424)),
3412 SC_SYNC,
3413 SC_ARG(1),
3415 SC_WAIT(10),
3416 SC_END,
3417};
3418
3420 SC_SET(SW_SPEED, PIXELS(4) / 5),
3421 SC_ARG(2),
3422 SC_MOVE(PIXELS(840), 0, PIXELS(456)),
3423 SC_SYNC,
3424 SC_MOVE(PIXELS(808), 0, PIXELS(456)),
3425 SC_SYNC,
3426 SC_MOVE(PIXELS(808), 0, PIXELS(408)),
3427 SC_SYNC,
3428 SC_MOVE(PIXELS(776), 0, PIXELS(408)),
3429 SC_SYNC,
3430 SC_ARG(1),
3431 SC_END,
3432};
3433
3435 SC_ARG(2),
3436 SC_MOVE(PIXELS(104), 0, PIXELS(632)),
3437 SC_SYNC,
3438 SC_ARG(1),
3439 SC_END,
3440};
3441
3443 SC_ARG(2),
3444 SC_MOVE(PIXELS(72), 0, PIXELS(696)),
3445 SC_SYNC,
3446 SC_MOVE(PIXELS(80), 0, PIXELS(640)),
3447 SC_SYNC,
3448 SC_MOVE(PIXELS(104), 0, PIXELS(632)),
3449 SC_SYNC,
3450 SC_ARG(1),
3451 SC_END,
3452};
3453
3455 SC_ARG(2),
3456 SC_MOVE(PIXELS(168), 0, PIXELS(632)),
3457 SC_SYNC,
3458 SC_ARG(1),
3459 SC_END,
3460};
3461
3463 SC_ARG(2),
3464 SC_MOVE(PIXELS(232), 0, PIXELS(632)),
3465 SC_SYNC,
3466 SC_ARG(1),
3467 SC_END,
3468};
3469
3471 SC_ARG(2),
3472 SC_MOVE(PIXELS(264), 0, PIXELS(696)),
3473 SC_SYNC,
3474 SC_MOVE(PIXELS(264), 0, PIXELS(632)),
3475 SC_SYNC,
3476 SC_MOVE(PIXELS(232), 0, PIXELS(632)),
3477 SC_SYNC,
3478 SC_ARG(1),
3479 SC_END,
3480};
3481
3483 SC_ARG(2),
3484 SC_MOVE(PIXELS(104), 0, PIXELS(696)),
3485 SC_SYNC,
3486 SC_ARG(1),
3487 SC_END,
3488};
3489
3491 SC_ARG(2),
3492 SC_MOVE(PIXELS(80), 0, PIXELS(640)),
3493 SC_SYNC,
3494 SC_MOVE(PIXELS(72), 0, PIXELS(696)),
3495 SC_SYNC,
3496 SC_MOVE(PIXELS(104), 0, PIXELS(696)),
3497 SC_SYNC,
3498 SC_ARG(1),
3499 SC_END,
3500};
3501
3503 SC_ARG(2),
3504 SC_MOVE(PIXELS(168), 0, PIXELS(696)),
3505 SC_SYNC,
3506 SC_ARG(1),
3507 SC_END,
3508};
3509
3511 SC_ARG(2),
3512 SC_MOVE(PIXELS(232), 0, PIXELS(696)),
3513 SC_SYNC,
3514 SC_ARG(1),
3515 SC_END,
3516};
3517
3519 SC_ARG(2),
3520 SC_MOVE(PIXELS(264), 0, PIXELS(632)),
3521 SC_SYNC,
3522 SC_MOVE(PIXELS(264), 0, PIXELS(696)),
3523 SC_SYNC,
3524 SC_MOVE(PIXELS(232), 0, PIXELS(696)),
3525 SC_SYNC,
3526 SC_ARG(1),
3527 SC_END,
3528};
3529
3531 SC_ARG(2),
3532 SC_MOVE(PIXELS(168), 0, PIXELS(648)),
3533 SC_SYNC,
3534 SC_MOVE(PIXELS(72), 0, PIXELS(648)),
3535 SC_SYNC,
3536 SC_ARG(1),
3537 SC_END,
3538};
3539
3541 SC_ARG(2),
3542 SC_MOVE(PIXELS(72), 0, PIXELS(648)),
3543 SC_SYNC,
3544 SC_ARG(1),
3545 SC_END,
3546};
3547
3549 SC_ARG(2),
3550 SC_MOVE(PIXELS(168), 0, PIXELS(648)),
3551 SC_SYNC,
3552 SC_MOVE(PIXELS(264), 0, PIXELS(648)),
3553 SC_SYNC,
3554 SC_ARG(1),
3555 SC_END,
3556};
3557
3559 SC_ARG(2),
3560 SC_MOVE(PIXELS(264), 0, PIXELS(648)),
3561 SC_SYNC,
3562 SC_ARG(1),
3563 SC_END,
3564};
3565
3567 SC_ARG(2),
3568 SC_MOVE(PIXELS(72), 0, PIXELS(696)),
3569 SC_SYNC,
3570 SC_ARG(1),
3571 SC_END,
3572};
3573
3575 SC_ARG(2),
3576 SC_MOVE(PIXELS(120), 0, PIXELS(696)),
3577 SC_SYNC,
3578 SC_MOVE(PIXELS(72), 0, PIXELS(696)),
3579 SC_SYNC,
3580 SC_ARG(1),
3581 SC_END,
3582};
3583
3585 SC_ARG(2),
3586 SC_MOVE(PIXELS(264), 0, PIXELS(696)),
3587 SC_SYNC,
3588 SC_ARG(1),
3589 SC_END,
3590};
3591
3593 SC_ARG(2),
3594 SC_MOVE(PIXELS(168), 0, PIXELS(696)),
3595 SC_SYNC,
3596 SC_MOVE(PIXELS(264), 0, PIXELS(696)),
3597 SC_SYNC,
3598 SC_ARG(1),
3599 SC_END,
3600};
3601
3603 { 0, CONDITION_ALWAYS, 172, 0, 149, FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
3604 { 5, CONDITION_ALWAYS, 192, 0, 220, FACING_NORTH, 0, 32, 0, 272, 240, 0 },
3605 { 6, CONDITION_ALWAYS, 432, 0, 254, FACING_NORTH, 0, 288, 0, 528, 272, 0 },
3606 { 7, CONDITION_ALWAYS, 720, 0, 782, FACING_NORTH, 0, 432, 576, 800, 800, 0 },
3607 { 8, CONDITION_ALWAYS, 624, 0, 236, FACING_NORTH, 0, 560, 32, 848, 256, 0 },
3608 { 9, CONDITION_ALWAYS, 144, 0, 492, FACING_NORTH, 0, 16, 288, 256, 512, 0 },
3609 { 10, CONDITION_ALWAYS, 416, 0, 526, FACING_NORTH, 0, 320, 288, 592, 544, 0 },
3610 { 11, CONDITION_ALWAYS, 744, 0, 640, FACING_SOUTH, 0, 432, 576, 800, 800, 0 },
3611 { 12, CONDITION_ALWAYS, 358, 0, 632, FACING_SOUTH, 0, 32, 576, 400, 776, 0 },
3612 { 13, CONDITION_ALWAYS, 648, 0, 424, FACING_SOUTH, 0, 560, 320, 800, 480, 0 },
3613 { 14, CONDITION_ALWAYS, 704, 0, 408, FACING_WEST, 0, 560, 320, 800, 480, 0 },
3614 { 15, CONDITION_ALWAYS, 768, 0, 408, FACING_EAST, 0, 712, 288, 952, 496, 0 },
3615 { 16, CONDITION_ALWAYS, 792, 0, 432, FACING_NORTH, 0, 712, 288, 952, 496, 0 },
3616 { 17, CONDITION_ALWAYS, 792, 0, 432, FACING_NORTH, 0, 712, 288, 952, 496, 0 },
3617 { SCENE_TABLE_END },
3618};
3619
3621 {639, 33, 407, 657, 51, 425, CONDITION_ALWAYS, 13},
3623};
3624
3626 SCENE_EXITS(21),
3627 SCENE_EXIT(5, 20, 5),
3628 SCENE_EXIT(6, 20, 6),
3629 SCENE_EXIT(7, 20, 7),
3630 SCENE_EXIT(8, 20, 8),
3631 SCENE_EXIT(9, 20, 9),
3632 SCENE_EXIT(10, 20, 10),
3633 SCENE_EXIT(11, 21, 11),
3634 SCENE_EXIT(12, 21, 12),
3635 SCENE_EXIT(13, 20, 13),
3636 SCENE_EXIT(14, 21, 14),
3637 SCENE_EXIT(15, 21, 15),
3638 SCENE_EXIT(16, 9, 12),
3640};
3641
3644 PIXELS(8), 0, PIXELS(8), FACING_NORTH, TALK_FACE_PARTY, 0 },
3646 PIXELS(376), 0, PIXELS(392), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3647 { 0x6c, 0x0, ACTOR_STAND,
3649 { 0x6a, 0x0, 3,
3650 PIXELS(152), 0, PIXELS(72), FACING_WEST, TALK_FACE_PARTY, 0 },
3651 { 0x65, 0x0, ACTOR_STAND,
3652 PIXELS(456), 0, PIXELS(184), FACING_EAST, TALK_FACE_PARTY, 0 },
3653 { 0x6b, 0x0, ACTOR_WANDER,
3654 PIXELS(368), 0, PIXELS(120), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3655 { 0x67, 0x0, ACTOR_WANDER,
3656 PIXELS(744), 0, PIXELS(200), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3657 { 0x6f, 0x0, ACTOR_STAND,
3658 PIXELS(752), 0, PIXELS(128), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3659 { 0x6b, 0x0, ACTOR_STAND,
3661 { 0x66, 0x0, ACTOR_STAND,
3663 { 0x75, 0x0, ACTOR_STAND,
3664 PIXELS(536), 0, PIXELS(451), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3665 { 0x73, 0x0, ACTOR_STAND,
3666 PIXELS(416), 0, PIXELS(464), FACING_NORTH, TALK_FACE_PARTY, 0 },
3667 { 0x6a, 0x0, ACTOR_WANDER,
3668 PIXELS(536), 0, PIXELS(672), FACING_NORTH, TALK_FACE_PARTY, 0 },
3669 { 0x7c, 0x0, ACTOR_STAND,
3671 { 0x7d, 0x0, ACTOR_STAND,
3673 { 0x76, 0x0, ACTOR_STAND,
3674 PIXELS(632), 0, PIXELS(136), FACING_SOUTH, 3, 0 },
3675 { 0x65, 0x0, ACTOR_STAND,
3677 { 0x80, 0x0, ACTOR_STAND,
3680 PIXELS(104), 0, PIXELS(696), FACING_EAST, 3, 0 },
3682 PIXELS(200), 0, PIXELS(680), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3683 { 0xdf, 0x0, ACTOR_STAND,
3684 PIXELS(692), 0, PIXELS(411), FACING_SOUTH, TALK_KEEP_FACING, 0 },
3685 { SCENE_TABLE_END },
3686};
3687
3690 PIXELS(8), 0, PIXELS(8), FACING_NORTH, TALK_FACE_PARTY, 0 },
3692 PIXELS(376), 0, PIXELS(392), FACING_SOUTH + FACING_STEP, TALK_FACE_PARTY, 0 },
3696 PIXELS(504), 0, PIXELS(456), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3698 PIXELS(104), 0, PIXELS(696), FACING_EAST, 3, 0 },
3700 PIXELS(200), 0, PIXELS(680), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3702 PIXELS(8), 0, PIXELS(8), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3704 PIXELS(8), 0, PIXELS(8), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3706 PIXELS(8), 0, PIXELS(8), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3707 { 0x14, 0x0, ACTOR_STAND,
3708 PIXELS(872), 0, PIXELS(424), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3709 { 0x14, 0x0, ACTOR_STAND,
3710 PIXELS(872), 0, PIXELS(408), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3711 { 0x14, 0x0, ACTOR_STAND,
3712 PIXELS(872), 0, PIXELS(376), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3713 { 0xfb, CONDITION_ALWAYS, 7,
3714 PIXELS(8), 0, PIXELS(8), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3715 { 0xdd, CONDITION_ALWAYS, 7,
3716 PIXELS(8), 0, PIXELS(8), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3717 { SCENE_TABLE_END },
3718};
3719
3721 { EVENT_EXIT, 1, CONDITION_ALWAYS, 5 },
3722 { EVENT_EXIT, 2, CONDITION_ALWAYS, 6 },
3723 { EVENT_EXIT, 3, CONDITION_ALWAYS, 7 },
3724 { EVENT_EXIT, 4, CONDITION_ALWAYS, 8 },
3725 { EVENT_EXIT, 5, CONDITION_ALWAYS, 9 },
3726 { EVENT_EXIT, 6, CONDITION_ALWAYS, 10 },
3728 { EVENT_EXIT, 8, CONDITION_ALWAYS, 12 },
3748 { EVENT_TALK, ACTOR_GEM_OWNER, CONDITION_ALWAYS, MSGNO(MsgVaultThisRockWasBlownHereAll) },
3750 { EVENT_TALK, ACTOR_WARY_NEIGHBOR, CONDITION_ALWAYS, MSGNO(MsgVaultMyNeighborCreepsMeOutHe) },
3753 { EVENT_TALK, ACTOR_GRANDPAS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultEverSinceTheEruptionGrandpaKeeps) },
3754 { EVENT_TALK, ACTOR_WOULD_BE_HELPER, FLAG_VAULT_IVAN_JOINED_ROD_SEARCH, MSGNO(MsgVaultICouldHelpIvanIfI) },
3755 { EVENT_TALK, ACTOR_WOULD_BE_HELPER, CONDITION_ALWAYS, MSGNO(MsgVaultYoureHelpingIvanYouDontLook) },
3757 { EVENT_TALK, ACTOR_SECRET_KEEPER, CONDITION_ALWAYS, MSGNO(MsgVaultSinceYoureHelpingIvanIllTell) },
3759 { EVENT_TALK, ACTOR_MAYORS_WIFE, FLAG_VAULT_IVAN_JOINED_ROD_SEARCH, MSGNO(MsgVaultMyHusbandTheMayorCantBelieve) },
3760 { EVENT_TALK, ACTOR_MAYORS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultReallyYoureGoingToHelpIvan) },
3765 { EVENT_TALK, ACTOR_INN_STAFF, CONDITION_ALWAYS, MSGNO(MsgVaultTheGuestsUpstairsWerentInTheir) },
3771 { EVENT_TALK, ACTOR_SUSPECTED_LEADER, FLAG_VAULT_SUSPECTS_MIND_READ, MSGNO(MsgVaultThatKidIvanHeCreepsMe) },
3772 { EVENT_TALK, ACTOR_SUSPECTED_THIEF, FLAG_VAULT_SUSPECTS_MIND_READ, MSGNO(MsgVaultWeHaventDoneAnythingYoureA) },
3775 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_GEM_OWNER, CONDITION_ALWAYS, MSGNO(MsgVaultTheOtherSparklingRocksAllCrumbled) },
3777 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_WARY_NEIGHBOR, CONDITION_ALWAYS, MSGNO(MsgVaultHeyMaybeMyNeighborIsThe) },
3780 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_GRANDPAS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultYouNeverBoughtMeAnythingWorth) },
3781 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_WOULD_BE_HELPER, CONDITION_ALWAYS, MSGNO(MsgVaultTheseGuysLookReliableIGuess) },
3782 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_SECRET_KEEPER, CONDITION_ALWAYS, MSGNO(MsgVaultIWonderWhatSortOfThing) },
3784 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_MAYORS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultMaybeTheyllFindOurStolenFamily) },
3786 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_WEAPON_MERCHANT, CONDITION_ALWAYS, MSGNO(MsgVaultAllOurBestWeaponsWereStolen) },
3787 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_ARMOR_MERCHANT, CONDITION_ALWAYS, MSGNO(MsgVaultIWonderIfTheyLeftUs) },
3788 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_ITEM_MERCHANT, CONDITION_ALWAYS, MSGNO(MsgVaultHahhWereSureToSeeA) },
3789 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_INN_STAFF, CONDITION_ALWAYS, MSGNO(MsgVaultItWouldBeAwfulIfOur) },
3790 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_INNKEEPER, CONDITION_ALWAYS, MSGNO(MsgVaultThatVolcanoCostUsALot) },
3799 { 0xc4f3, 200, CONDITION_ALWAYS, FIND_MESSAGE(MSGNO(MsgVaultTheresABookEntitledHistoryOf)) },
3800 { SEARCH(SEARCH_BOOKCASE), 201, CONDITION_ALWAYS, FIND_MESSAGE(MSGNO(MsgVaultTheresABookEntitledGemsOf)) },
3801 { SCENE_EVENTS_END },
3802};
3803
3811 { SCENE_EVENTS_END },
3812};
3813
3816 { EVENT_EXIT, 1, CONDITION_ALWAYS, 5 },
3817 { EVENT_EXIT, 2, CONDITION_ALWAYS, 6 },
3818 { EVENT_EXIT, 3, CONDITION_ALWAYS, 7 },
3819 { EVENT_EXIT, 4, CONDITION_ALWAYS, 8 },
3820 { EVENT_EXIT, 5, CONDITION_ALWAYS, 9 },
3821 { EVENT_EXIT, 6, CONDITION_ALWAYS, 10 },
3822 { EVENT_EXIT, 7, CONDITION_ALWAYS, 11 },
3823 { EVENT_EXIT, 8, CONDITION_ALWAYS, 12 },
3826 { EVENT_TALK, ACTOR_GEM_OWNER, CONDITION_ALWAYS, MSGNO(MsgVaultICanSleepWellNowThat) },
3831 { EVENT_TALK, ACTOR_GRANDPAS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultJustAsIThoughtNothingWas) },
3833 { EVENT_TALK, ACTOR_SECRET_KEEPER, CONDITION_ALWAYS, MSGNO(MsgVaultIvanLearnedALotByTalking) },
3835 { EVENT_TALK, ACTOR_MAYORS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultYoureThePersonWhoGotOur) },
3840 { EVENT_TALK, ACTOR_INN_STAFF, CONDITION_ALWAYS, MSGNO(MsgVaultImShockedThoseGuestsOfOurs) },
3842 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_GEM_OWNER, CONDITION_ALWAYS, MSGNO(MsgVaultEverybodysAfterMyRockTheyWant) },
3844 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_WARY_NEIGHBOR, CONDITION_ALWAYS, MSGNO(MsgVaultTheReasonLunpaTurnedBadIs) },
3847 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_GRANDPAS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultIWishIHadSomethingWorth) },
3848 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_WOULD_BE_HELPER, CONDITION_ALWAYS, MSGNO(MsgVaultWhenIGrowUpIWant) },
3849 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_SECRET_KEEPER, CONDITION_ALWAYS, MSGNO(MsgVaultIWishIHadWingsLike) },
3851 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_MAYORS_WIFE, CONDITION_ALWAYS, MSGNO(MsgVaultImSoRelievedNowThatWe) },
3853 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_WEAPON_MERCHANT, CONDITION_ALWAYS, MSGNO(MsgVaultMyWeaponsWereFoundInThe) },
3854 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_ARMOR_MERCHANT, CONDITION_ALWAYS, MSGNO(MsgVaultItMustBeSnowingUpIn) },
3855 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_ITEM_MERCHANT, CONDITION_ALWAYS, MSGNO(MsgVaultWhyAreThesePeopleSoAnxious) },
3856 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_INN_STAFF, CONDITION_ALWAYS, MSGNO(MsgVaultWhoCouldHaveKnownTheyWere) },
3857 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), ACTOR_INNKEEPER, CONDITION_ALWAYS, MSGNO(MsgVaultOfCourseIAlwaysSuspectedThey) },
3862 { 0xc4f3, 200, CONDITION_ALWAYS, FIND_MESSAGE(MSGNO(MsgVaultTheresABookEntitledHistoryOf)) },
3863 { SEARCH(SEARCH_BOOKCASE), 201, CONDITION_ALWAYS, FIND_MESSAGE(MSGNO(MsgVaultTheresABookEntitledGemsOf)) },
3864 { SCENE_EVENTS_END },
3865};
3866// clang-format on
3867
3872};
3873
3878};
3879
3885};
3886
Ability numbers, named from the English release.
@ ABILITY_MIND_READ
Definition ability_ids.h:16
@ ABILITY_MOVE
Definition ability_ids.h:15
void Object_RefreshSelectorById(u32 objectId)
Waits, at most 300 frames, for an actor's script to reach its end (command 0x10).
void ObjectMotion_WaitForAnimationChange(u32 objectId)
Waits, at most 90 frames, for an actor's animation to change.
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.
@ ACTOR_INNKEEPER
Definition altin.c:82
Animated sprites: their layers, frames and colour modes, and the resource slots they draw from.
Which units are in a battle, and the Djinn recovery list.
@ ELEMENT_VENUS
Definition battle_unit.h:36
static void Event_TalkToInnkeeper(void)
Opens the inn across the counter, or discusses the curse in Kolima.
The task scheduler: tasks, their order and the scheduler's state.
#define GARET
Jerald.
#define IVAN
Ivan.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
The engine calls the debug menus import, and their palette swatch tiles.
The edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
static s32 FieldObject_CheckMovementCollision(struct FieldActor *actor, struct FieldPosition *position)
Definition engine_call.h:66
static void FieldMap_SetViewBounds(s32 minX, s32 minY, s32 maxX, s32 maxY)
Definition engine_call.h:55
void FieldScene_PrepareActors(struct ScenePlacement *entry)
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
void Engine_ObjectSetPosition(struct FieldActor *object, s32 fixed_x, s32 fixed_y, s32 fixed_z)
@ ANIM_WALK
Definition field_event.h:44
@ ANIM_STAND
Definition field_event.h:43
@ ANIM_NOD
Definition field_event.h:45
@ ANIM_SHAKE_HEAD
Definition field_event.h:46
static s32 Event_OpenMessage(s32 speaker, s32 flags)
void Engine_ActorFaceActor(s32 actor, s32 target, s32 frames)
s32 Engine_LeaderCheckAhead(void)
static void Actor_SetDestination(s32 actor, s32 x, s32 z)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Object_SetMode(struct FieldActor *object, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
void Engine_PsynergyBegin(s32 ability, s32 flags)
struct FieldActor * Engine_ActorLookup(s32 actor)
static void Actor_SetBuiltinAction(s32 actor, s32 action)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
s32 Engine_PartyGiveItem(s32 item, s32 flags)
#define GameFlag_IsSet
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
void Engine_PsynergyRaiseHands(void)
void Engine_PsynergyLowerHands(void)
void Engine_ActorMoveToAndWait(s32 actor, s32 x, s32 z)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
static void Actor_MoveToAndWait(s32 actor, s32 x, s32 z)
void Engine_ItemShowFound(s32 item, s32 height)
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorSetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_InnOpen(s32 inn, s32 keeper)
void Engine_EventCloseScreen(void)
void Engine_ObjectDispatchRelease(struct FieldActor *object)
static void Map_CopyCellsTo(s32 srcX, s32 srcY, s32 destX, s32 destY, s32 width, s32 height)
static void Actor_FaceActor(s32 actor, s32 target, s32 frames)
static void Actor_WalkTo(s32 actor, s32 x, s32 z)
#define GameFlag_Clear
void Engine_EventWaitForScreen(void)
#define GameFlag_Set
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
void Engine_EventOpenScreen(void)
s32 Engine_EventOpenMessage(s32 speaker, s32 flags)
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)
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)
void Engine_ActorSetAttachedEffect(s32 actor, s32 effect)
s32 Engine_RandomNext()
static void Event_PlayCue(s32 cue)
static void Map_CopyCells(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_PsynergyPlayEffect(s32 effect)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
@ TASK_PRIORITY_SCENE
Definition field_event.h:40
void Engine_MapRedraw(void)
void Engine_ShopOpen(s32 shop, s32 keeper)
static void Camera_MoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
static void Actor_SetPosition(s32 actor, s32 fixed_x, s32 fixed_z)
void Engine_ActorFaceEachOther(s32 actor, s32 other, s32 frames)
void Engine_EventWait(s32 frames)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
void Engine_PsynergySetTarget(s32 caster, s32 target)
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ ACTOR_PRIORITY_UNDERFOOT
The depth sort treats it as 320 pixels higher on the screen.
Definition field_obj.h:155
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
Definition field_obj.h:153
#define ACTOR_NO_TARGET
A target coordinate that is not set: the object has no target.
Definition field_obj.h:145
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
@ ACTOR_FACES_MOTION
turns toward its velocity, 1/16 turn a frame
Definition field_obj.h:166
The 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
@ EVENT_RAISED
@ 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_MESSAGE(message)
#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
@ FACING_EAST
Definition field_scene.h:26
@ FACING_SOUTHEAST
Definition field_scene.h:27
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_NORTHWEST
Definition field_scene.h:31
@ FACING_SOUTH
Definition field_scene.h:28
@ FACING_WEST
Definition field_scene.h:30
#define TOUCH_WALKING
#define PIXELS(value)
@ SEARCH_BOOKCASE
@ SEARCH_WOODEN_BOX
@ SEARCH_JAR
@ SEARCH_UNNAMED
@ SEARCH_BARREL
#define FIND_COINS(coins)
The scene service layer: one typed inline for each engine service a scene calls by its own name,...
static s32 Task_AddCallback(void(*callback)(void), s32 priority)
Calls the main-image scheduler through engine_call.h.
static s32 FieldScheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 priority)
Calls the main-image scheduler through engine_call.h.
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_VAULT_IVAN_JOINED_ROD_SEARCH
Set when the party agrees to help Ivan find the rod; while it is set and the thieves are free,...
Definition flags.h:554
#define FLAG_VAULT_BONE_RECEIVED
Definition flags.h:108
#define FLAG_MENUS_RAISE_EVENT
While set, opening the field menu or the pause menu, or pressing a shortcut, raises event 250 instead...
Definition flags.h:27
#define FLAG_VAULT_MET_IVAN
Set when Ivan first shows the party his strange powers at the mayor's.
Definition flags.h:543
#define FLAG_VAULT_INTERIORS_BOX_MINT
Definition flags.h:569
#define FLAG_VAULT_SUSPECTS_MIND_READ
Set once Ivan has read the minds of the two cornered suspects.
Definition flags.h:556
#define FLAG_VAULT_THIEVES_JAILED
Definition flags.h:106
#define FLAG_VAULT_WATER_OF_LIFE_RECEIVED
Set once the mayor has given the party the Water of Life.
Definition flags.h:549
#define FLAG_VAULT_SUSPECTS_APPROACHED
Set when the party first approaches the two suspects at the inn.
Definition flags.h:547
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_VAULT_CRATE_MOVED
Set once the crate is pushed aside, opening the passage behind it.
Definition flags.h:551
#define FLAG_VAULT_INTERIORS_BARREL_COINS
Definition flags.h:567
#define FLAG_VAULT_INTERIORS_JAR_COINS
Definition flags.h:566
#define FLAG_VAULT_MAYOR_THANKED_PARTY
Set once the mayor has thanked the party for helping Ivan.
Definition flags.h:545
#define FLAG_VAULT_THIEVES_CONFRONTED
Set as the three thieves are confronted in the attic, before the battle.
Definition flags.h:558
#define FLAG_VAULT_INTERIORS_BARREL_SLEEP_BOMB
Definition flags.h:568
#define FLAG_SCENE_TEMP_50
Definition flags.h:793
GameState, the game's state: play time, coins, the scene and the leader's position,...
#define Battle_SetStart(mode)
Sets the battle start type.
Definition game_state.h:164
struct GameState gGameState
The screen blend's globals and the graphics routines.
@ ACTOR_ITEM_MERCHANT
Definition imil.c:62
@ ACTOR_ARMOR_MERCHANT
Definition imil.c:60
@ ACTOR_WEAPON_MERCHANT
Definition imil.c:59
The main-image routines scene overlays import.
s32 PartyInventory_HasSpace(void)
Returns 1 when the selected character or any party member has a free inventory slot.
Definition inventory.c:99
Item numbers, named from the English release.
@ ITEM_MINT
Definition item_ids.h:54
@ ITEM_BONE
Definition item_ids.h:72
@ ITEM_WATER_OF_LIFE
Definition item_ids.h:49
@ ITEM_SLEEP_BOMB
Definition item_ids.h:68
static void Event_TalkToArmorMerchant(void)
After Lunpa reopens, across the counter, the armor shop; otherwise small talk.
static void Event_TalkToItemMerchant(void)
Across the counter, the item shop; otherwise small talk.
static void Event_TalkToWeaponMerchant(void)
After Lunpa reopens, across the counter, the weapon shop; otherwise small talk.
Small statement macros both games use for positions, velocities and bounds.
#define SET_POSITION(p, px, py, pz)
Sets the position or the velocity of a particle, a piece of debris or an object in one statement.
Definition macros.h:16
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 heaps: allocating and freeing blocks.
void Ui_SetBank15PaletteAndClearRenderMode(void)
Stops the BG0 scanline scroll and restores BG palette 15.
Definition mind_read.c:279
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
#define SC_SET(w, v)
Write a work value.
Definition objcmd.h:37
#define SC_LOOP(n, to)
Repeat up to n times.
Definition objcmd.h:28
#define SC_POS(x, y, z)
Set position.
Definition objcmd.h:18
#define SC_SYNC
Wait for arrival.
Definition objcmd.h:17
#define SC_FOREVER
Definition objcmd.h:14
#define SC_ADD(w, v)
Definition objcmd.h:38
#define SC_ARG(v)
Definition objcmd.h:44
#define SC_MOVE(x, y, z)
Move toward the target.
Definition objcmd.h:19
#define SC_WAIT(n)
Wait n frames.
Definition objcmd.h:16
#define SC_TOP
Script start.
Definition objcmd.h:13
#define SC_END
Return to the main script.
Definition objcmd.h:32
@ SW_SCALE_Y
Definition objcmd.h:63
@ SW_SPEED
Definition objcmd.h:67
@ SW_FACING
Definition objcmd.h:57
@ SW_SCALE_X
Definition objcmd.h:62
s32 BattleFx_PlayCueAndStartEmitterOnTarget(s32 actor, s32 target, s32 itemId)
If actor target exists, plays SE_124, gives it animation 4 and, 12 frames later, shows itemId in fron...
Definition targets.c:207
void Leader_StopMoving(void)
Stops the leader where it stands: no horizontal velocity, the normal walking speed (1....
Definition events.c:67
void Party_RemoveOwnerRestored(s32 unit)
Takes unit out of the party, fully restoring its HP and PP and curing its poison.
Definition events.c:214
void Event_PrepareObjectAndApplyValue(s32 unit, s32 announce)
Adds unit to the party.
Definition events.c:165
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
#define ACTOR_ACTION_IDLE
void Field_RequestBattleFromEncounterTable(s32 zoneNo, s32 slotNo)
Sets up a battle with enemy group slot of encounter table zone.
Definition requests.c:14
void Event_SetDefeatDestination(s32 scene, s32 entrance)
Sets where the party wakes up after losing a battle (gGameState.defeatScene and defeatEntrance).
Definition requests.c:70
void Event_SetNextDestination(s32 scene, s32 entrance)
Sets the scene and entrance that the field goes to next (gGameState.nextScene and nextEntrance).
Definition requests.c:61
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_VaultInteriors
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
Song and sound effect ids, indices into gSound_SongTable.
#define SE_MAP_EXIT
Definition songs.h:116
#define MUS_061
Definition songs.h:65
#define MUS_017
Definition songs.h:27
#define MUS_019
Definition songs.h:29
#define SE_124
Definition songs.h:117
#define SE_JUMP
An actor jumps: ObjectMotion_Launch plays the high jump above 5 pixels a frame.
Definition songs.h:147
#define MUS_060
Definition songs.h:64
#define MUS_009
Definition songs.h:19
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
void Engine_ActorShowEmote()
void Engine_TaskWait()
void Engine_EventSetMessage()
void Engine_EventShowMessage()
#define NULL
Definition bilibin.h:6
Vault's interiors, before and after the thieves are caught: an item lying on the floor,...
void Vault_PlaceItemIcon(s32 item, s32 fixed_x, s32 fixed_y, s32 fixed_z)
Creates object 22 at the 16.16 position and draws it as the item's icon: the sprite's own animation i...
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
u16 priority
2 when created
Definition animspr.h:100
u8 djinnOwnedCounts[4]
the Djinn held in each element, at most 10
The running scene's event work: its placement and event tables, its actors, the triggers and exit it ...
Definition event_work.h:20
s16 raisedTrigger
a raised event for Scene_RunRaisedEvent
Definition event_work.h:35
s32 startTransition
SCENE_TRANSITION(style, variant).
Definition event_work.h:43
s16 blockedSteps
frames the leader has pushed against something
Definition event_work.h:37
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
s32 targetX
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:59
u8 steeringFlags
ActorSteeringFlag bits.
Definition field_obj.h:92
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
Definition field_obj.h:83
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
s32 targetZ
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:61
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
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
Definition field_obj.h:51
s32 terrainHeight
16.16 fixed-point pixels
Definition field_obj.h:38
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 targetY
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:60
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
A position on the field.
s32 z
16.16 fixed-point pixels
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
A scene's exit region: the box that, while its condition holds, takes the party leader out through it...
Each stop links to up to three others, with a heading for each connection.
u8 stopIndex
the stop it leads to; 0xff for no connection
u8 facing
the heading toward it, a facing's high byte
A stop on the route network, two cells square, with its links to others.
struct VaultInteriorsStopConnection connections[3]
u8 gridX
8-pixel cells from x 64
u8 gridZ
8-pixel cells from z 624
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
Values that differ by patch level or language, chosen once for their code.
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
A field coordinate, read whole or as its fraction and its whole pixels.
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
struct BattleUnit * UnitGet(u32 owner)
Returns the unit record of owner: 0 to 7 are the playable characters in the game state,...
Definition units.c:73
Vault's interiors, before and after the thieves are caught: the Bone left on the floor of the house w...
static void Vault_FindBone(void)
Searching cell code 41 beside the bone giver takes a Bone after the thieves are jailed.
Definition vault_bone.h:13
Vault and its interiors: Ivan hands back Isaac's Djinni before he leaves the party.
static s32 Vault_ReturnIsaacsDjinni(void)
Brings every Djinni back from recovery (twenty rounds of it), then, if Ivan holds the first Venus Dji...
Definition vault_djinn.h:18
s32 gVaultInteriors_PairScriptG[]
static void VaultInteriors_OpenWindowTransition(void)
Opens the window transition and waits one frame after it finishes.
struct SceneEntrance gVaultInteriors_Entrances[]
static void VaultInteriors_ApplySecondSuspectRoute(struct FieldActor *actor, s32 scriptRow, s32 routePair, u16 routeDelta)
Selects a response script and advances the second suspect's route state.
s32 gVaultInteriors_PairScriptM[]
VaultInteriorsRaisedEvent
The chase adds the blocked-suspect mask (1 the leader, 2 the thief) to 200.
@ VAULT_INTERIORS_LEADER_CORNERED
@ VAULT_INTERIORS_BOTH_CORNERED
@ VAULT_INTERIORS_CORNERED_EVENT_BASE
@ VAULT_INTERIORS_THIEF_CORNERED
s32 gVaultInteriors_PairScriptR[]
s32 * gVaultInteriors_IdleActions[]
static void Event_MeetIvan(void)
Talking to Ivan at the mayor's: the first time, he reads the two's minds, admits his strange powers a...
s32 gVaultInteriors_PairScriptK[]
static void VaultInteriors_StandAndShowMessage(s32 x)
Stands the speaker, faces the leader, and shows the selected message.
static void VaultInteriors_BeginMindRead(s32 casterId, s32 targetId)
Begins Mind Read, chooses its target, and shows its opening effect.
s32 gVaultInteriors_PairScriptJ[]
static void VaultInteriors_SetPartyImagePriority(void)
Sets the three party images to the priority used during the mind-reading scene.
s32 gVaultInteriors_PairScriptC[]
struct SceneEvent gVaultInteriors_Events[]
static void Event_ReadMindOnThieves(void)
Mind Read on Grandpa: could they be thieves?
static void Event_SearchEmptyBarrel(void)
Isaac checks the barrel but doesn't find anything.
s32 gVaultInteriors_FirstThiefEntryScript[]
static void VaultInteriors_MoveActorToStop(struct FieldActor *actor, struct VaultInteriorsStop *stop)
Sets the actor's destination to the route stop's cell center.
s32 gVaultInteriors_VaultScriptD[]
s32 gVaultInteriors_ActionTable[]
static void VaultInteriors_ReturnStolenGoods(void)
Returns the stolen goods and rod, thanks the party, and clears the attic.
s32 gVaultInteriors_VaultScriptA[]
#define CONNECTION(stop, direction)
s32 gVaultInteriors_PairScriptH[]
static void VaultInteriors_FaceActorAndWait(s32 actorId, s32 targetId, s32 waitFrames)
static void VaultInteriors_ShowMessageAndWait(s32 actorId, s32 waitFrames)
s32 gVaultInteriors_PairScriptO[]
static void Event_OfferBones(void)
The bone giver offers leftover bones from dinner; a yes gets a Bone if there is room,...
static void Event_FreeRooferAndConfrontThieves(void)
In the loft, Isaac cuts the roofer free; the three thieves arrive, boast of Lunpa and Dodonpa,...
static void Event_DiscussSuspiciousGuests(void)
Stepping out, the party talks it over: Ivan can't read their minds while they run; Garet tells Isaac ...
static void Event_ReadMindOnRock(void)
Mind Read on the wife: let me see that rock, or maybe it is worthless.
static void Event_ReadBoneGiverMind(void)
Mind Read on the bone giver: the master and his wife are blinded by money; after the thieves are jail...
static void Event_TalkAboutMissingThings(void)
Talks about missing things, or, after the thieves are jailed, says they hid the treasure in the loft ...
u16 gVaultInteriors_StopTimer
s32 gVaultInteriors_VaultScriptC[]
static void VaultInteriors_FaceSuspectsTowardLeader(void)
Keeps both suspects facing the leader while they evade the party.
static void Event_AdvanceSuspectRoutes(void)
The leader stepping on one of the route triggers 11 to 18 moves the fleeing suspects on to their next...
static void VaultInteriors_AdvanceSuspectRoute(s32 actor, s32 expected, s32 next, const s32 *actions)
Installs a route script only when the suspect is in its expected state.
static void VaultInteriors_FaceEachOtherAndWait(s32 firstId, s32 secondId, s32 waitFrames)
s32 gVaultInteriors_PairScriptE[]
struct SceneEvent gVaultInteriors_AtticEvents[]
static s32 VaultInteriors_CheckStopOccupancy(struct VaultInteriorsStop *stop)
Reserves a full cell around the leader and half a cell around each actor following a route.
static void VaultInteriors_ConfrontThievesAgain(void)
Arranges the attic confrontation and restarts the thieves' battle.
static s32 VaultInteriors_IsActorWithinSixteenPixels(s32 x, s32 z, s32 id)
Checks whether an actor's destination or current position lies within sixteen pixels.
s32 * gVaultInteriors_ResponseScripts[]
static void VaultInteriors_UpdateActorStops(void)
Steers Ivan and both suspects through the graph and detects a sustained cornering.
static void Event_CheckCrateMoved(void)
Once the crate has been moved aside to column 42, the passage behind it opens.
s32 gVaultInteriors_PairScriptI[]
s32 gVaultInteriors_PairScriptD[]
static void VaultInteriors_LoseToThieves(void)
Shows the thieves' reaction after the party loses their battle: the party lies beaten and the thieves...
static void Event_SuspectedThiefDodges(void)
The suspected thief cries out and runs to his next spot.
static void Event_OfferIvansSecret(void)
Offers Ivan's secret.
static void Event_TalkAboutRocks(void)
The gem owner's wife wishes their rocks were gems, or, after the thieves are jailed,...
static void Event_JumpAcrossRoofGap(void)
Facing north or south across the gap in the roof, the leader jumps it.
static void VaultInteriors_EndMindRead(void)
Finishes Mind Read and releases its scene effect objects.
s32 gVaultInteriors_PairScriptQ[]
struct ScenePlacement gVaultInteriors_AtticPlacements[]
s32 gVaultInteriors_VaultScriptE[]
static void Event_MayorGivesWaterOfLife(void)
After the thieves are jailed, the mayor thanks Isaac and gives the promised Water of Life,...
struct SceneRegion gVaultInteriors_Regions[]
static void Event_SearchEmptyChest(void)
Isaac checks the chest, but it is empty.
static void VaultInteriors_AskYesNoAndShowReply(s32 x)
Faces the leader and selects the next reply when the answer is no.
s32 gVaultInteriors_VaultScriptB[]
s32 gVaultInteriors_SecondThiefEntryScript[]
static void Event_AskAboutDefeatingThieves(void)
Asks about defeating the thieves. "I heard you defeated those thieves!".
static void VaultInteriors_DiscussMindReading(void)
Shows the party's branching conversation about what Ivan learned: the stolen goods are hidden in the ...
s32 gVaultInteriors_PairScriptP[]
static void Event_ChildAsksAboutTravel(void)
The child asks about travel.
#define VAULT_INTERIORS_CORNERED_FRAMES
A cornering lasts half a second before the chase raises an event.
s32 gVaultInteriors_PairScriptL[]
struct SceneEvent gVaultInteriors_EventsAfterThieves[]
u32 gVaultInteriors_Exits[]
static s32 VaultInteriors_IsActorWithinEightPixels(s32 x, s32 z, s32 id)
Checks whether an actor's destination or current position lies within eight pixels.
static void Event_GoToEntrance11(void)
The party walks through to entrance 11.
static void Event_LeaveAttic(void)
Leaving the loft before the thieves are confronted, the party hears the roofer groan.
static void VaultInteriors_IvanJoinsRodSearch(void)
Ivan thanks them, they exchange names, and he shows Isaac and Garet Mind Read; he joins the party.
static void Event_ClimbToAttic(void)
The party climbs up into the inn's loft.
struct VaultInteriorsStop gVaultInteriors_Stops[]
static void Event_ChildWorriesAboutFather(void)
The child's father worries about the prisoners from Lunpa.
s32 gVaultInteriors_PairScriptA[]
static void Event_GaretRefusesToLeave(void)
Garet refuses to leave.
static void VaultInteriors_StartActorStops(void)
Arranges the chase, constrains its camera, and starts the route callback.
static void Event_SuspectedLeaderDodges(void)
The suspected leader cries out and runs to his next spot, chosen by the way he faces and where he is ...
static struct VaultInteriorsStop * VaultInteriors_FindStopAtPosition(s32 *position)
Finds the route node containing the actor's position on the eight-pixel grid.
s32 gVaultInteriors_PairScriptN[]
@ ACTOR_MAYORS_WIFE
@ ACTOR_BONE_GIVER
@ ACTOR_WOULD_BE_HELPER
"I could help Ivan if I were just a little older."
@ ACTOR_INN_STAFF
Works at the inn.
@ ACTOR_CRATE
pushed aside to open a passage
@ ACTOR_SUSPECTED_THIEF
@ ACTOR_GRANDPAS_WIFE
Says Grandpa keeps wondering if anything was stolen.
@ ACTOR_GEM_OWNER
a sparkling rock was blown here from the volcano
@ ACTOR_MAYOR
Ivan's host; his wife calls him the mayor.
@ ACTOR_GRANDPA
Wonders what was stolen. "Is it just me, or am I missing something?".
@ ACTOR_WARY_NEIGHBOR
Distrusts the man next door. "My neighbor creeps me out.".
@ ACTOR_GEM_OWNERS_WIFE
@ ACTOR_SUSPECTED_LEADER
The two guests at the inn the town suspects: the thieves' leader and one of his men.
@ ACTOR_CHILD
Asks about travel. "Hey, mister! Is it fun to see strange new places?".
@ ACTOR_SECRET_KEEPER
Tells the party Ivan's secret once it helps him.
#define VAULT_INTERIORS_ENTRY_ACTOR_Z
static void VaultInteriors_ResetSuspectRoutes(void)
Has the suspects react to the party's return and resets their route states.
static void Event_MayorAsksHelpForIvan(void)
The mayor asks for someone to help Ivan; once the party has agreed, he thanks them the first time and...
#define NO_CONNECTION
@ ACTOR_FOUND_URN
rises from the first crate: the mayor's urn
@ ACTOR_FOUND_STATUE
rises from the second: the Sanctum's gold statue
@ ACTOR_THIRD_CHEST
@ ACTOR_ATTIC_MAYOR
@ ACTOR_THIEF_LEADER
@ ACTOR_ATTIC_ESCORT
Comes up with the mayor and helps tie the thieves up.
@ ACTOR_ATTIC_SEARCHER
Comes up with the mayor and opens the crates.
@ ACTOR_SECOND_THIEF
@ ACTOR_FIRST_THIEF
@ ACTOR_FIRST_CHEST
@ ACTOR_ATTIC_ROOFER
tied up while fixing the roof
@ ACTOR_SECOND_CHEST
static void Event_WarnAboutThreeStrangers(void)
The three strangers have fooled the innkeeper and his wife.
static void Event_BeginCorneringSuspects(void)
The party sets out to corner the two suspects.
s32 gVaultInteriors_PairScriptF[]
struct ScenePlacement gVaultInteriors_Placements[]
@ FLAG_SUSPECTS_FLEEING
Set while the two suspects run from the party, until the party steps aside to talk it over.
s32 gVaultInteriors_PairScriptB[]
static void VaultInteriors_DefeatThieves(void)
Stages the defeated thieves and gathers the townspeople in the attic.
static void Event_ApproachSuspects(void)
The suspects at the inn spot that weird kid with the party and run from him.
static struct VaultInteriorsStop * VaultInteriors_SnapToNearestStop(struct VaultInteriorsStop *node, s16 *requestedFacing)
Chooses the outgoing connection nearest the requested facing.
static s32 VaultInteriors_GetIvanVenusDjinnCount(void)
Counts the Venus Djinn Ivan holds, which he gives back before he leaves the party.
static void Event_ReadMayorMind(void)
Mind Read on the mayor: a laugh, or the cave in the Goma Range is dangerous, but the party will be ok...
static void Event_ReadChildMind(void)
Mind Read on the child: what is the outside world like, or Father looks sad.
static void Event_ReadCorneredSuspectsMinds(void)
Once a suspect is cornered, Garet calls Ivan and Ivan reads their minds.
static void Event_AskWhetherThievesCameFromLunpa(void)
Asks whether the thieves came from Lunpa.
static void VaultInteriors_PlayAnimationAndWait(s32 actorId, s32 animation, s32 waitFrames)
Waits for the animation to change before the following pause.
s32 * gVaultInteriors_StepActions[]
Vault's interiors, before and after the thieves are caught: whether the leader stands beside the Bone...
static void Vault_UpdateBoneProximityFlag(void)
Prevents the bone giver offering another Bone while the leader stands beside the one on the floor.
Vault and its interiors: a villager's thought read with Mind Read.
static void Vault_ShowThought(s32 actorId)
Shows the message already set as the actor's thought: the actor stops and stands while the thought is...
Definition vault_talk.h:9
The patch levels: our groups of the measured changes from the Japanese release.