Alchemy
Loading...
Searching...
No Matches

lunpa_fortress.c

Go to the documentation of this file.
1/// @file
2/// Dodonpa's fortress above Lunpa, on four maps. The outer rooms (map 1) and
3/// the guard rooms with Donpa's chamber (map 2) are watched by guards who throw
4/// an uncloaked party out; the column room (map 3) hides its passages behind
5/// Whirlwind, Reveal and a column to Move; in the rescue room (map 4) the party
6/// finds Hammet, Dodonpa springs his trap and Donpa judges his son.
7///
8/// Scene flags: FLAG_SCENE_TEMP_14, a guard has spotted the party and
9/// FLAG_SCENE_TEMP_15 with it; FLAG_SCENE_TEMP_17 and _18, the first and second
10/// switch are still hidden; FLAG_SCENE_TEMP_24, the entrance guard has thrown
11/// the party out; FLAG_SCENE_TEMP_25, the sentries have; FLAG_SCENE_TEMP_26,
12/// the startled resident promised to keep quiet; FLAG_SCENE_TEMP_27, the
13/// resident was already startled; FLAG_SCENE_TEMP_70, Hammet's rescue has
14/// begun.
15///
16/// The flags from 0x300 are reused from place to place: 0x301, Hammet is
17/// rescued; 0x313, the attendant has told Donpa's story; 0x314, Donpa has shown
18/// his reward; 0x350 to 0x35c, the cell doors the Cell Key opened.
19
20#include "game_state.h"
21#include "field_event.h"
22#include "unit/import.h"
24#include "unit/object/object.h"
26#include "unit/field/field.h"
27#include "battle.h"
28#include "debug.h"
29#include "field.h"
30#include "game.h"
31#include "graphics.h"
32#include "menu.h"
33#include "minigame.h"
34#include "sound.h"
35#include "system.h"
36#include "global_cells.h"
37#include "edition.h"
39#include "event.h"
40#include "scene_ids.h"
41#include "tbs_edition.h"
42#include "map_scroll.h"
43#include "text/msg_ids.h"
44#include "types.h"
45#include "ability_ids.h"
46#include "field_scene.h"
47#include "item_ids.h"
48#include "objcmd.h"
49#include "flags.h"
50#include "songs.h"
51
52/// The outer rooms (map 1).
53enum {
60};
61
62/// The guard rooms and Donpa's chamber (map 2).
63enum {
68 /// The three guards who fight together.
78};
79
80/// The column room (map 3).
81enum {
86};
87
88/// The rescue room (map 4).
89enum {
95};
96
97/// Triggers: the cell doors count from DOOR_TRIGGER_FIRST in each map, and a
98/// watching guard raises one of the TRIGGER_*_SPOTTED triggers.
99enum {
109};
110
111/// Reveal's phases: the hidden things show, and hide again.
112enum { REVEAL_SHOWN = 5, REVEAL_FADED = 4 };
113
114/// Where a party caught by a guard is sent: the gate below the fortress.
115enum { EXIT_THROWN_OUT = 60 };
116
117/// Where the party comes back after the three guards' battle and after the
118/// monster's.
119enum {
122};
123
124/// What a guard close to the cloaked leader requests of Cloak.
125enum { CLOAK_NEAR_GUARD = 0x2000 | ABILITY_CLOAK };
126
127/// The first of the flags that remember which cell doors the Cell Key opened,
128/// per map: one for each door trigger from DOOR_TRIGGER_FIRST.
129enum {
134};
135
136/// The paired patrol's layer origin across: 136 pixels, in 16.16 fixed point.
137// The native paired patrol computes this layer offset in floating point.
138#define PAIRED_PATROL_LAYER_ORIGIN_X (136.0 * 65536)
139
140static s32 LunpaFortress_TryCollectDisplayedItem(s32 actorId, s32 itemId);
145static void LunpaFortress_GuardThrowsPartyOut(s32 actorId);
146static void LunpaFortress_ActOutIntruderDialogue(s32 actorId);
147static void LunpaFortress_ActOutWhosThereDialogue(s32 actorId);
149static void LunpaFortress_ActOutScoundrelDialogue(s32 actorId);
150static void LunpaFortress_InitializeOuterRooms(void);
151static void LunpaFortress_InitializeGuardRooms(void);
152static void LunpaFortress_InitializeColumnRoom(void);
153static void LunpaFortress_RestoreOuterDoors(void);
157
159
161 s16 sceneId = gGameState.scene;
162
163 if (sceneId == (s32)&SceneId_LunpaFortress1) {
165 }
166 if (sceneId == (s32)&SceneId_LunpaFortress2) {
168 }
169 if (sceneId == (s32)&SceneId_LunpaFortress3) {
171 }
173}
174
175const struct SceneRegion *Scene_GetRegions(void) { return NULL; }
176
177const u32 *Scene_GetExits(void) {
178 s16 sceneId = gGameState.scene;
179
180 if (sceneId == (s32)&SceneId_LunpaFortress2) {
182 }
183 if (sceneId == (s32)&SceneId_LunpaFortress3 ||
184 sceneId == (s32)&SceneId_LunpaFortress4) {
186 }
188}
189
190/// The guards, residents and objects of each map.
192 s16 sceneId = gGameState.scene;
193
194 if (sceneId == (s32)&SceneId_WestLunpaCave) {
196 }
197 if (sceneId == (s32)&SceneId_LunpaFortress3) {
199 }
200 if (sceneId == (s32)&SceneId_LunpaFortress2) {
202 }
203 if (sceneId == (s32)&SceneId_LunpaFortress1) {
205 }
206 if (sceneId == (s32)&SceneId_LunpaFortress4) {
208 }
210}
211
212/// What the party can talk to, search and use Psynergy on, by map.
213const struct SceneEvent *Scene_GetEvents(void) {
214 s16 sceneId = gGameState.scene;
215
216 if (sceneId == (s32)&SceneId_LunpaFortress1) {
218 }
219 if (sceneId == (s32)&SceneId_LunpaFortress2) {
221 }
222 if (sceneId == (s32)&SceneId_LunpaFortress3) {
224 }
226}
227
228/// The column sinks into the floor: the party can walk over it.
229static void LunpaFortress_LowerColumn(void) {
230 struct FieldActor *columnActor;
231
232 Map_CopyCellAttributes(15, 20, 1, 1, 15, 22);
233 Map_CopyCellAttributes(17, 23, 1, 3, 15, 23);
234 columnActor = Object_GetById(COLUMN_ROOM_COLUMN);
235 if (columnActor != 0) {
236 Engine_ActorSetSpriteFlags(columnActor, 0);
237 columnActor->motionFlags = 0;
239 }
240}
241
242/// Pushing the column: it slides one cell along.
243static void Event_PushColumn(void) { StagedActor_AdvancePair(); }
244
245/// The column, pushed onto its hole, slides in and sinks.
246static void Event_ColumnSinks(void) {
247 OBJ_SPEED(COLUMN_ROOM_COLUMN, 0x10000, 0x8000);
250 SE(SE_215);
251 WAIT(60);
254}
255
256/// Move on the column: once it is past row 22, over its hole, the room shakes
257/// and it sinks.
258static void Event_MoveColumn(void) {
259 struct FieldActor *columnActor;
260
261 columnActor = Actor_Get(COLUMN_ROOM_COLUMN);
262 if ((columnActor->z.fixed >> 20) > 22) {
263 Map_SetShake(0x40000, 0x40000, 0x10000);
264 Map_SetShake(-1, -1, 0xe666);
265 SE(SE_144);
266 Map_CopyCellAttributes(15, 20, 1, 1, 15, 22);
267 Map_CopyCellAttributes(17, 23, 1, 3, 15, 23);
268 columnActor = Actor_Get(COLUMN_ROOM_COLUMN);
269 if (columnActor != NULL) {
270 Engine_ActorSetSpriteFlags(columnActor, 0);
272 }
274 }
275}
276
277/// The column stays sunk in its hole.
281}
282
283/// Draws a rescue room cell door open.
284static void LunpaFortress_OpenRescueRoomDoor(s32 doorIndex) {
285 s32 doorCellX = gRescueRoomDoorCells[doorIndex * 2];
286 s32 doorCellY = gRescueRoomDoorCells[doorIndex * 2 + 1];
287
288 Map_CopyCells(0, 0x4d, 1, 3, doorCellX, doorCellY);
289 Map_CopyCells(1, 0x4d, 1, 1, doorCellX + 1, doorCellY);
290 Map_CopyCells(doorCellX, doorCellY - 0x30, 1, 1, doorCellX, doorCellY - 0x2e);
291}
292
293/// Facing a rescue room cell door with the Cell Key: it opens with a rumble.
294/// After Hammet's rescue the fifth, Dodonpa's cell, stays shut.
295static void Event_UnlockRescueRoomDoor(void) {
296 struct EventWork *fieldWork;
297 s32 doorTrigger;
298 s32 doorIndex;
299
300 fieldWork = gEventWork;
302 doorTrigger = fieldWork->touchedTrigger;
303 doorIndex = doorTrigger - DOOR_TRIGGER_FIRST;
304 if (FLAG_CHECK(FLAG_LUNPA_TRADE_REOPENED) == 0 || doorIndex != 4) {
307 Map_SetShake(0x30000, 0x30000, 0x10000);
308 Map_SetShake(-1, -1, 0xe666);
310 }
311 }
312}
313
314/// Draws a column room cell door open and lets the party through; the middle
315/// door opens two cells.
316static void LunpaFortress_OpenColumnRoomDoor(s32 doorIndex) {
317 s32 doorCellX;
318 s32 doorCellY;
319 s32 collisionCellY;
320
321 doorCellX = gColumnRoomDoorCells[doorIndex * 2];
322 doorCellY = gColumnRoomDoorCells[doorIndex * 2 + 1];
323 Map_CopyCells(0, 77, 1, 3, doorCellX, doorCellY);
324 Map_CopyCells(1, 77, 1, 1, doorCellX + 1, doorCellY);
325 collisionCellY = doorCellY - 44;
326 Map_CopyCellAttributes(doorCellX, doorCellY - 45, 1, 1, doorCellX,
327 collisionCellY);
328 if (doorIndex == 1)
329 Map_CopyCellAttributes(doorCellX, collisionCellY, 1, 1, doorCellX,
330 doorCellY - 43);
331}
332
333/// Facing a column room cell door with the Cell Key: it opens with a rumble.
334static void Event_UnlockColumnRoomDoor(void) {
335 struct EventWork *fieldWork;
336 s32 doorTrigger;
337
338 fieldWork = gEventWork;
340 doorTrigger = fieldWork->touchedTrigger;
343 Map_SetShake(0x30000, 0x30000, 0x10000);
344 Map_SetShake(-1, -1, 0xe666);
346 }
347}
348
349/// Draws a guard room cell door open.
350static void LunpaFortress_OpenGuardRoomDoor(s32 doorIndex) {
351 s32 doorCellX = gGuardRoomDoorCells[doorIndex * 2];
352 s32 doorCellY = gGuardRoomDoorCells[doorIndex * 2 + 1];
353
354 Map_CopyCells(0x37, 0x79, 1, 3, doorCellX, doorCellY);
355 Map_CopyCells(0x38, 0x79, 1, 1, doorCellX + 1, doorCellY);
356 Map_CopyCells(doorCellX, doorCellY - 0x3f, 1, 1, doorCellX, doorCellY - 0x3e);
357}
358
359/// Facing a guard room cell door with the Cell Key: it opens with a rumble.
360static void Event_UnlockGuardRoomDoor(void) {
361 struct EventWork *fieldWork;
362 s32 doorTrigger;
363
364 fieldWork = gEventWork;
366 doorTrigger = fieldWork->touchedTrigger;
369 Map_SetShake(0x30000, 0x30000, 0x10000);
370 Map_SetShake(-1, -1, 0xe666);
372 }
373}
374
375/// Draws an outer room cell door open and lets the party through.
376static void LunpaFortress_OpenOuterDoor(s32 doorIndex) {
377 // BUG: the third door's trigger and flag (OUTER_DOOR_FLAG + 2) ask for
378 // index 2, past the two doors gOuterDoorCells holds.
379 s32 doorCellX = gOuterDoorCells[doorIndex * 2];
380 s32 doorCellY = gOuterDoorCells[doorIndex * 2 + 1];
381
382 Map_CopyCells(1, 0x50, 1, 3, doorCellX, doorCellY);
383 Map_CopyCells(2, 0x50, 1, 1, doorCellX + 1, doorCellY);
384 Engine_MapCopyCellAttributes(doorCellX, doorCellY - 0x3f, 1, 1, doorCellX,
385 doorCellY - 0x3e);
386}
387
388/// Facing an outer room cell door with the Cell Key: it opens with a rumble.
389static void Event_UnlockOuterDoor(void) {
390 struct EventWork *fieldWork;
391 s32 doorTrigger;
392
393 fieldWork = gEventWork;
395 doorTrigger = fieldWork->touchedTrigger;
398 Map_SetShake(0x30000, 0x30000, 0x10000);
399 Map_SetShake(-1, -1, 0xe666);
401 }
402}
403
404/// Searching a cell door without the Cell Key: it stays shut.
405/// "The door is tightly locked."
406static void Event_SearchLockedDoor(void) {
408 Engine_MessageShowCentered(MsgFieldDoorTightlyLocked, 1);
409 }
410}
411
412/// Searching the door no key opens.
413static void Event_SearchSealedDoor(void) {
414 Engine_MessageShowCentered(MsgFieldDoorTightlyLocked, 1);
415}
416
417/// Unused: four items set out on actors 8 to 11, each
418/// taken once, with flags 0xf2a to 0xf2d.
421 Engine_GameFlagSet(0xf2a);
422 }
423}
424
427 Engine_GameFlagSet(0xf2b);
428 }
429}
430
433 Engine_GameFlagSet(0xf2c);
434 }
435}
436
439 Engine_GameFlagSet(0xf2d);
440 }
441}
442
443/// Gives the item an actor shows, with its effect; with no room for it, the
444/// actor shows the item is left behind. Returns whether it was given.
446 s32 itemGiven = 0;
447 s32 itemEffect;
448
449 EV_BEGIN();
450 itemEffect =
452 if (Engine_PartyGiveItem(itemId, 0) != -1) {
453 OBJ_MODE(actorId, 2);
454 itemGiven = 1;
455 } else {
456 SE(SE_125);
457 OBJ_MODE(actorId, 5);
458 }
459 Engine_ObjectDispatchRelease((struct FieldActor *)itemEffect);
460 EV_END();
461 return itemGiven;
462}
463
465
467
469
471
472/// Catch on the Cell Key hanging in the guard rooms, or talking to it: the
473/// leader steps up and takes it.
474static void Event_TakeCellKey(void) {
478 WAIT(10);
485}
486/// Where the patrolling pair cannot see the leader: the west end of their
487/// corridor and the cells below its gap.
490 s32 leaderFixedZ = leader->z.fixed;
491 s32 leaderFixedX;
492 s32 leaderTileZ, leaderTileX;
493
494 if (leaderFixedZ < 0) {
495 leaderFixedZ += 0xfffff;
496 }
497 leaderFixedX = leader->x.fixed;
498 leaderTileZ = leaderFixedZ >> 20;
499 if (leaderFixedX < 0) {
500 leaderFixedX += 0xfffff;
501 }
502 leaderTileX = leaderFixedX >> 20;
503 if ((u32)(leaderTileZ - 5) <= 2 && leaderTileX <= 10) {
504 return 1;
505 }
506 if ((u32)(leaderTileX - 8) <= 1 && leaderTileZ > 22) {
507 return 1;
508 }
509 return 0;
510}
511
512// UB: these patrols formerly reached gEventWork through gMapWork[19] and
513// treated its request members as a halfword array. Named owner access adds
514// eight bytes to each of the three patrol callbacks in the EN trial.
515#ifdef UBFIX
516#define PATROL_PSYNERGY_REQUEST(work) ((work)->command)
517#define PATROL_ITEM_REQUEST(work) ((work)->item)
518#define PATROL_RAISED_TRIGGER(work) ((work)->event)
519#else
520#define PATROL_PSYNERGY_REQUEST(work) ((work)[191])
521#define PATROL_ITEM_REQUEST(work) ((work)[192])
522#define PATROL_RAISED_TRIGGER(work) ((work)[193])
523#endif
524
525/// Every frame in the guard rooms: the pair patrolling the west corridor. They
526/// stand still while flag 0x106 is set or Psynergy or an item is in use;
527/// otherwise they walk, with map layer 2 shaking and following the first.
528/// Close to a cloaked leader they request CLOAK_NEAR_GUARD; seeing an
529/// uncloaked leader, they raise TRIGGER_PATROL_PAIR_SPOTTED.
531 struct FieldActor *firstGuard = Actor_Get(GUARD_ROOM_FIRST_PATROL);
532 struct FieldActor *secondGuard = Actor_Get(GUARD_ROOM_SECOND_PATROL);
533 struct MapLayerScroll *patrolLayer =
534 &((struct MapScrollWork *)gMapWork[0])->layers[2];
535#ifdef UBFIX
536 struct FieldWork *fieldWork = (struct FieldWork *)gEventWork;
537#else
538 s16 *fieldWork = *(s16 **)&gMapWork[19];
539#endif
540
541 if (gFrameCount & 1) {
542 patrolLayer->speedX = 1;
543 patrolLayer->speedY = 1;
544 } else {
545 patrolLayer->speedX = -1;
546 patrolLayer->speedY = -1;
547 }
548 if (FLAG_CHECK(FLAG_MENU_OPEN) || PATROL_PSYNERGY_REQUEST(fieldWork) != 0 ||
549 PATROL_ITEM_REQUEST(fieldWork) != 0) {
550 firstGuard->paused = 1;
551 secondGuard->paused = 1;
552 } else if (!FLAG_CHECK(FLAG_SCENE_TEMP_14)) {
553 firstGuard->paused = 0;
554 secondGuard->paused = 0;
555 if (!FLAG_CHECK(FLAG_SCENE_TEMP_14) && firstGuard->paused == 0) {
556 patrolLayer->phaseX = PAIRED_PATROL_LAYER_ORIGIN_X - firstGuard->x.fixed;
557 }
559 if (gGameState.cloaked != 0) {
561 gGameState.cloaked != 0) {
562 SetSceneValue(&PATROL_PSYNERGY_REQUEST(fieldWork), CLOAK_NEAR_GUARD);
563 return;
564 }
566 gGameState.cloaked != 0) {
567 SetSceneValue(&PATROL_PSYNERGY_REQUEST(fieldWork), CLOAK_NEAR_GUARD);
568 return;
569 }
570 }
571 if (gGameState.cloaked == 0) {
575 }
579 }
580 }
582 SetSceneValue(&PATROL_RAISED_TRIGGER(fieldWork),
584 }
585 }
586 }
587}
588
589/// Raised when the patrolling pair spots the leader: the first stops and
590/// stares, and the second throws the party out.
592 EV_BEGIN();
599 EV_END();
600}
601
602/// Whether the leader and the hall patrol are in the two parallel corridors,
603/// where the guard passes without seeing the leader.
605 struct FieldActor *leader = Object_GetById(0);
607 s32 leaderFixedX = leader->x.fixed;
608 s32 guardFixedZ;
609 s32 guardFixedX;
610 s32 leaderTileX, guardTileZ, guardTileX;
611
612 if (leaderFixedX < 0) {
613 leaderFixedX += 0xfffff;
614 }
615 leaderTileX = leaderFixedX >> 20;
616 guardFixedZ = guard->z.fixed;
617 if (guardFixedZ < 0) {
618 guardFixedZ += 0xfffff;
619 }
620 guardFixedX = guard->x.fixed;
621 guardTileZ = guardFixedZ >> 20;
622 if (guardFixedX < 0) {
623 guardFixedX += 0xfffff;
624 }
625 guardTileX = guardFixedX >> 20;
626 if (leaderTileX == 52 && guardTileX == 57 && guardTileZ > 34 &&
627 guardTileZ <= 40) {
628 return 1;
629 }
630 if (leaderTileX == 57 && guardTileX == 52 && guardTileZ > 34 &&
631 guardTileZ <= 40) {
632 return 1;
633 }
634 return 0;
635}
636
637/// Every frame in the guard rooms: the patrol in the east hall, as
638/// LunpaFortress_UpdatePairedGuardDetection; seeing the leader, it raises
639/// TRIGGER_HALL_PATROL_SPOTTED.
641
643 struct MapLayerScroll *patrolLayer =
644 &((struct MapScrollWork *)gMapWork[0])->layers[2];
645#ifdef UBFIX
646 struct FieldWork *fieldWork = (struct FieldWork *)gEventWork;
647#else
648 s16 *fieldWork = *(s16 **)&gMapWork[19];
649#endif
650
652 if (gFrameCount & 1) {
653 patrolLayer->speedX = 1;
654 patrolLayer->speedY = 1;
655 } else {
656 patrolLayer->speedX = -1;
657 patrolLayer->speedY = -1;
658 }
659 if (FLAG_CHECK(FLAG_MENU_OPEN) || PATROL_PSYNERGY_REQUEST(fieldWork) != 0 ||
660 PATROL_ITEM_REQUEST(fieldWork) != 0) {
661 guard->paused = 1;
662 } else if (!FLAG_CHECK(FLAG_SCENE_TEMP_14)) {
663 guard->paused = 0;
664 if (!FLAG_CHECK(FLAG_SCENE_TEMP_14) && guard->paused == 0) {
665 patrolLayer->phaseX = 0x3400000 - guard->x.fixed;
666 patrolLayer->phaseY = 0x2400000 - guard->z.fixed;
667 }
671 gGameState.cloaked != 0) {
672 SetSceneValue(&PATROL_PSYNERGY_REQUEST(fieldWork), 0x2092);
673 return;
674 }
675 if (gGameState.cloaked == 0) {
679 }
680 }
682 SetSceneValue(&PATROL_RAISED_TRIGGER(fieldWork),
684 }
685 }
686 }
687}
688
689/// Raised when the hall patrol spots the leader: it throws the party out.
692 EV_END();
693}
694
695/// Where the outer rooms' patrol cannot see the leader: three stretches of
696/// its rounds.
698 struct FieldActor *leader = Object_GetById(0);
699 s32 leaderTileZ = leader->z.fixed / 0x100000;
700 s32 leaderTileX = leader->x.fixed / 0x100000;
701
702 if ((u32)(leaderTileX - 41) <= 3 && leaderTileZ > 25 && leaderTileZ <= 28) {
703 return 1;
704 }
705 if (leaderTileX == 41 && leaderTileZ > 37 && leaderTileZ <= 41) {
706 return 1;
707 }
708 if ((u32)(leaderTileX - 54) <= 2 && leaderTileZ > 30 && leaderTileZ <= 40) {
709 return 1;
710 }
711 return 0;
712}
713
714/// Every frame in the outer rooms: the patrolling guard, as
715/// LunpaFortress_UpdatePairedGuardDetection; seeing the leader, it raises
716/// TRIGGER_OUTER_PATROL_SPOTTED.
718
719 struct FieldActor *guard = Actor_Get(OUTER_PATROL_GUARD);
720 struct MapLayerScroll *patrolLayer =
721 &((struct MapScrollWork *)gMapWork[0])->layers[2];
722#ifdef UBFIX
723 struct FieldWork *fieldWork = (struct FieldWork *)gEventWork;
724#else
725 s16 *fieldWork = *(s16 **)&gMapWork[19];
726#endif
727
728 if (gFrameCount & 1) {
729 patrolLayer->speedX = 1;
730 patrolLayer->speedY = 1;
731 } else {
732 patrolLayer->speedX = -1;
733 patrolLayer->speedY = -1;
734 }
735 if (FLAG_CHECK(FLAG_MENU_OPEN) || PATROL_PSYNERGY_REQUEST(fieldWork) != 0 ||
736 PATROL_ITEM_REQUEST(fieldWork) != 0) {
737 guard->paused = 1;
738 } else if (!FLAG_CHECK(FLAG_SCENE_TEMP_14)) {
739 guard->paused = 0;
740 if (!FLAG_CHECK(FLAG_SCENE_TEMP_14) && guard->paused == 0) {
741 patrolLayer->phaseX = 0x2f00000 - guard->x.fixed;
742 patrolLayer->phaseY = 0x1f00000 - guard->z.fixed;
743 }
746 gGameState.cloaked != 0) {
747 SetSceneValue(&PATROL_PSYNERGY_REQUEST(fieldWork), 0x2092);
748 return;
749 }
750 if (gGameState.cloaked == 0) {
754 }
755 }
757 SetSceneValue(&PATROL_RAISED_TRIGGER(fieldWork),
759 }
760 }
761 }
762}
763
764/// Raised when the outer rooms' patrol spots the leader: it throws the party
765/// out.
768 EV_END();
769}
770
771/// Whether the leader is outside the upper hall the guard there watches.
773 struct FieldActor *leader = Object_GetById(0);
774 s32 leaderTileZ = leader->z.fixed / 0x100000;
775 s32 leaderTileX = leader->x.fixed / 0x100000;
776
777 if (leaderTileX > 45 && leaderTileZ > 14 && leaderTileX <= 64 &&
778 leaderTileZ <= 16) {
779 return 0;
780 }
781 return 1;
782}
783
784/// Every frame in the upper hall: the guard who sees the uncloaked leader
785/// raises TRIGGER_UPPER_HALL_SPOTTED.
787
788 struct EventWork *fieldWork;
789
790 fieldWork = gEventWork;
791 if (FLAG_CHECK(FLAG_SCENE_TEMP_14) == 0) {
793 if (gGameState.cloaked == 0) {
797 }
798 }
799 if (FLAG_CHECK(FLAG_SCENE_TEMP_14) != 0) {
801 }
802 }
803 }
804}
805
806/// Raised when the upper hall's guard spots the leader: he throws the party
807/// out.
810 EV_END();
811}
812
813/// Every frame past the entrance: the guard who sees the uncloaked leader
814/// raises TRIGGER_ENTRANCE_GUARD_SPOTTED, once.
816
817 struct EventWork *fieldWork = gEventWork;
818
820 gGameState.cloaked == 0) {
822 s32 caughtTrigger;
823
825 raisedTrigger = &fieldWork->raisedTrigger;
826 caughtTrigger = TRIGGER_ENTRANCE_GUARD_SPOTTED;
827 *raisedTrigger = caughtTrigger;
828 }
829}
830
831/// Every frame past the entrance: either sentry who sees the uncloaked
832/// leader raises TRIGGER_SENTRIES_SPOTTED, once for both.
834
835 struct EventWork *fieldWork;
836
837 fieldWork = gEventWork;
838 if (FLAG_CHECK(FLAG_SCENE_TEMP_25) == 0) {
840 if (gGameState.cloaked == 0) {
845 }
846 }
847 }
848}
849
850/// The second sentry, as the first.
852
853 struct EventWork *fieldWork;
854
855 fieldWork = gEventWork;
856 if (FLAG_CHECK(FLAG_SCENE_TEMP_25) == 0) {
858 if (gGameState.cloaked == 0) {
863 }
864 }
865 }
866}
867
868/// Whether the leader is in the guard's column, up to six cells away.
870 struct FieldActor *guard = Object_GetById(actorId);
871 struct FieldActor *leader = Object_GetById(0);
872 s32 guardTileZ = guard->z.fixed / 0x100000;
873 s32 guardTileX = guard->x.fixed / 0x100000;
874 s32 leaderTileZ = leader->z.fixed / 0x100000;
875 s32 leaderTileX = leader->x.fixed / 0x100000;
876 s32 zDistance = guardTileZ - leaderTileZ;
877
878 if (zDistance >= -6 && zDistance <= 6 && guardTileX - 1 < leaderTileX &&
879 guardTileX + 1 > leaderTileX) {
880 return 1;
881 }
882 return 0;
883}
884
885/// Whether the leader is within a row of the guard, up to six cells away.
887 struct FieldActor *guard = Object_GetById(actorId);
888 struct FieldActor *leader = Object_GetById(0);
889 s32 guardTileZ = guard->z.fixed / 0x100000;
890 s32 guardTileX = guard->x.fixed / 0x100000;
891 s32 leaderTileZ = leader->z.fixed / 0x100000;
892 s32 leaderTileX = leader->x.fixed / 0x100000;
893 s32 xDistance = guardTileX - leaderTileX;
894
895 if (xDistance < -6 || xDistance > 6) {
896 return 0;
897 }
898 if (guardTileZ - 2 < leaderTileZ && guardTileZ + 2 > leaderTileZ) {
899 return 1;
900 }
901 return 0;
902}
903
904/// Whether a guard on screen sees the leader along his row or column.
906 if (LunpaFortress_IsGuardNearViewCenter(actorId) == 0) {
907 return 0;
908 }
910 return 1;
911 }
912 {
913 s32 inHorizontalSight =
915
916 return (u32)(inHorizontalSight | -inHorizontalSight) >> 31;
917 }
918}
919
920/// Whether the leader is within four cells, walking, of the cell below the
921/// guard.
923 struct FieldActor *guard = Object_GetById(actorId);
924 struct FieldActor *leader = Object_GetById(0);
925 s32 guardTileZ = guard->z.fixed / 0x100000;
926 s32 guardTileX = guard->x.fixed / 0x100000;
927 s32 leaderTileZ = leader->z.fixed / 0x100000;
928 s32 leaderTileX = leader->x.fixed / 0x100000;
929 s32 xDistance = guardTileX - leaderTileX;
930 s32 zDistance;
931
932 guardTileZ += 1;
933 if (xDistance < 0) {
934 xDistance = -xDistance;
935 }
936 zDistance = guardTileZ - leaderTileZ;
937 if (zDistance < 0) {
938 zDistance = -zDistance;
939 }
940 if (xDistance + zDistance <= 4) {
941 return 1;
942 }
943 return 0;
944}
945
946/// Whether the guard is on screen: within seven columns and five rows of the
947/// view's center.
949 struct FieldActor *guard = Object_GetById(actorId);
950 struct FieldActor *viewCenter = Engine_EventGetViewCenter();
951 s32 guardTileX = guard->x.fixed / 0x100000;
952 s32 guardTileZ = guard->z.fixed / 0x100000;
953 s32 viewTileX = viewCenter->x.fixed / 0x100000;
954 s32 viewTileZ = viewCenter->z.fixed / 0x100000;
955 s32 xDistance = guardTileX - viewTileX;
956 s32 zDistance;
957
958 if (xDistance < 0) {
959 xDistance = -xDistance;
960 }
961 zDistance = guardTileZ - viewTileZ;
962 if (zDistance < 0) {
963 zDistance = -zDistance;
964 }
965 if (xDistance > 7 || zDistance > 5) {
966 return 0;
967 }
968 return 1;
969}
970
971/// Every frame in the outer rooms: walking into the second cell door's
972/// column with the Cell Key unlocks it.
974
975 struct FieldActor *leader = Object_GetById(0);
976
978 s32 playerX = leader->x.fixed / 0x100000;
979 s32 playerZ = leader->z.fixed / 0x100000;
980
981 if (playerX == 43 && playerZ > 28 && playerZ <= 31) {
982 s16 *touchedTrigger = &gEventWork->touchedTrigger;
983 s32 doorTrigger = DOOR_TRIGGER_FIRST + 1;
984
985 *touchedTrigger = doorTrigger;
987 }
988 }
989}
990
991/// Every frame in the guard rooms: walking east or west into the first cell
992/// door's column with the Cell Key unlocks it.
994
995 struct FieldActor *leader = Object_GetById(0);
996
998 s32 playerX = leader->x.fixed / 0x100000;
999 s32 playerZ = leader->z.fixed / 0x100000;
1000
1001 if (playerX == 16 && playerZ > 55 && playerZ <= 58 &&
1002 (leader->facing == 0xc000 || leader->facing == 0x4000)) {
1003 s16 *touchedTrigger = &gEventWork->touchedTrigger;
1004 s32 doorTrigger = DOOR_TRIGGER_FIRST;
1005
1006 *touchedTrigger = doorTrigger;
1008 }
1009 }
1010}
1011
1012/// Unused: the first patrol asks who the party is and sends them out.
1014 EV_BEGIN();
1020 {
1021 s32 challengeMessage = MsgLunpaWho2;
1022
1023 MESSAGE_SET(challengeMessage);
1026 MESSAGE_SET(challengeMessage + 1);
1027 }
1031 EV_END();
1032}
1033
1034/// A guard who caught the party sends it back to the gate below the fortress.
1035/// "Who are you? How did you get in here?"
1037 EV_BEGIN();
1038 EV_BEGIN();
1040 Engine_ActorSetDestinationOffset(actorId, 0, 0);
1042 OBJ_MODE(actorId, 0);
1043 OBJ_FACE(actorId, ACTOR_PARTY_LEADER, 0);
1045 Engine_ActorSetDestinationOffset(actorId, 0, 0);
1047 Engine_ActorStop(actorId);
1048 OBJ_MODE(actorId, 0);
1050 {
1051 s32 challengeMessage = MsgLunpaWho2;
1052
1053 MESSAGE_SET(challengeMessage);
1054 MESSAGE_PUT(actorId, 0);
1055 OBJ_FACE(ACTOR_PARTY_LEADER, actorId, 0);
1057 MESSAGE_SET(challengeMessage + 1);
1058 }
1059 MESSAGE_PUT(actorId, 0);
1061 WAIT(60);
1063 EV_END();
1064}
1065
1066/// A guard faces the leader with one of four challenges, chosen at random
1067/// when the map was entered.
1069
1070 OBJ_FACE(actorId, ACTOR_PARTY_LEADER, 0);
1071 OBJ_FACE(ACTOR_PARTY_LEADER, actorId, 0);
1072 switch (gLunpaFortressRandomPick & 3) {
1073 case 0:
1075 break;
1076 case 1:
1078 break;
1079 case 2:
1081 break;
1082 case 3:
1084 break;
1085 default:
1087 break;
1088 }
1089}
1090
1091/// A guard spots an intruder. "Hey! Intruder!"
1093 s32 messageBase;
1094
1096 messageBase = MsgLunpaIntruder;
1097 MESSAGE_SET(messageBase);
1098 MESSAGE_PUT(actorId, 0);
1099 OBJ_EMOTE(actorId, EMOTE_IN_FRONT | 2, 60);
1100 MESSAGE_SET(messageBase + 1);
1101 MESSAGE_PUT(actorId, 0);
1102 messageBase += 2;
1104 MESSAGE_SET(messageBase);
1105 MESSAGE_PUT(actorId, 0);
1106}
1107
1108/// A guard asks who is there. "Huh? Who's that?"
1110 s32 messageBase = MsgLunpaGuardWhosThat;
1111
1112 MESSAGE_SET(messageBase);
1113 MESSAGE_PUT(actorId, 0);
1115 MESSAGE_SET(messageBase + 1);
1116 MESSAGE_PUT(actorId, 0);
1118 MESSAGE_SET(messageBase + 2);
1119 MESSAGE_PUT(actorId, 0);
1120}
1121
1122/// A guard expects his relief, then sees who it is. "Is my shift up already?"
1124 s32 messageBase;
1125
1126 messageBase = MsgLunpaShiftAlready;
1127 MESSAGE_SET(messageBase);
1128 MESSAGE_PUT(actorId, 0);
1129 WAIT(120);
1130 OBJ_EMOTE(actorId, EMOTE_IN_FRONT | 1, 60);
1131 MESSAGE_SET((messageBase + 1));
1132 MESSAGE_PUT(actorId, 0);
1134 MESSAGE_SET((messageBase + 2));
1135 MESSAGE_PUT(actorId, 0);
1137 MESSAGE_SET((messageBase + 3));
1138 MESSAGE_PUT(actorId, 0);
1139}
1140
1141/// A guard calls the party a scoundrel. "You scoundrel!"
1143 s32 messageBase = MsgLunpaScoundrel;
1144
1145 MESSAGE_SET(messageBase);
1146 MESSAGE_PUT(actorId, 0);
1148 MESSAGE_SET(messageBase + 1);
1149 MESSAGE_PUT(actorId, 0);
1151 MESSAGE_SET(messageBase + 2);
1152 MESSAGE_PUT(actorId, 0);
1154 MESSAGE_SET(messageBase + 3);
1155 MESSAGE_PUT(actorId, 0);
1156}
1157
1158/// Walking up to the west guard: he challenges the party to a battle, and is
1159/// gone after it.
1160static void Event_FightWestGuard(void) {
1161
1167 Battle_SetStart(3);
1170 EV_END();
1172}
1173
1174/// Walking up to the hall guard: he challenges the party to a battle, and is
1175/// gone after it.
1176static void Event_FightHallGuard(void) {
1177
1183 Battle_SetStart(3);
1186 EV_END();
1188}
1189
1190/// Walking up to the three guards: they argue, then fight the party together.
1191/// "Who are you!?" After the battle the party comes back to this room.
1192static void Event_FightThreeGuards(void) {
1193 s32 messageBase;
1194
1201 WAIT(30);
1203 messageBase = MsgLunpaWho3;
1204 MESSAGE_SET(messageBase);
1211 WAIT(65);
1214 MESSAGE_SET((messageBase + 1));
1217 MESSAGE_SET((messageBase + 2));
1219 MESSAGE_SET((messageBase + 3));
1222 MESSAGE_SET((messageBase + 4));
1225 MESSAGE_SET((messageBase + 5));
1228 WAIT(60);
1231 WAIT(70);
1232 OBJ_WALK(GUARD_ROOM_GUARD_A, 672, 88);
1234#if TBS_PATCH_1
1236#endif
1238 WAIT(30);
1239 MESSAGE_SET((messageBase + 6));
1244 Battle_SetStart(3);
1249 EV_END();
1251}
1252
1253/// The three guards lie beaten where they fought.
1255 EV_BEGIN();
1263 EV_END();
1265}
1266
1267/// Walking up to the east guard: he challenges the party to a battle, and is
1268/// gone after it.
1269static void Event_FightEastGuard(void) {
1270
1276 Battle_SetStart(3);
1279 EV_END();
1281}
1282
1283/// Walking past the entrance guard, or seen by him: the party is sent back to
1284/// the gate below the fortress. "Who are you?"
1286 EV_BEGIN();
1293 {
1294 s32 challengeMessage = MsgLunpaWho2;
1295
1296 MESSAGE_SET(challengeMessage);
1299 MESSAGE_SET(challengeMessage + 1);
1300 }
1303 WAIT(60);
1305 EV_END();
1307}
1308
1309/// Walking between the sentries, or seen by them: the party is sent back to the
1310/// gate below the fortress. "Who are you?"
1312 s32 challengeMessage;
1313
1314 EV_BEGIN();
1323 challengeMessage = MsgLunpaWho2;
1324 MESSAGE_SET(challengeMessage);
1327 MESSAGE_SET(challengeMessage + 1);
1330 WAIT(60);
1332 EV_END();
1334}
1335
1336/// The first switch's passage opens.
1338 Map_CopyCells(2, 82, 1, 2, 21, 81);
1339 Map_CopyCellAttributes(21, 32, 1, 1, 21, 34);
1340}
1341
1342/// The second switch's passage opens.
1344 Map_CopyCells(2, 84, 1, 2, 6, 55);
1345 Map_CopyCellAttributes(5, 9, 1, 1, 6, 10);
1346}
1347
1348/// The passage behind the second Whirlwind cover opens.
1350 Map_CopyCells(2, 86, 1, 2, 27, 62);
1351 Map_CopyCellAttributes(26, 16, 1, 1, 27, 17);
1352}
1353
1354/// A switch flips in two frames, then its passage opens.
1355static __inline__ void
1357 void (*openPassage)(void)) {
1358 Map_CopyCells(6, 77, 1, 2, cellX, cellY);
1359 WAIT(5);
1360 Map_CopyCells(7, 77, 1, 2, cellX, cellY);
1361 WAIT(1);
1362 openPassage();
1363}
1364
1365/// Searching the first switch while Reveal shows it flips it, and its passage
1366/// opens. "You flipped the switch."
1367static void Event_FlipFirstSwitch(void) {
1368 if (((struct FieldWork *)gEventWork)->revealActive != 0) {
1370 Engine_MessageShowCentered(MsgFieldFlippedSwitch, 1);
1371 SE(SE_188);
1372 WAIT(1);
1376 }
1377 }
1378}
1379
1380/// Searching the second switch while Reveal shows it flips it, and its passage
1381/// opens. "You flipped the switch."
1382static void Event_FlipSecondSwitch(void) {
1383 if (((struct FieldWork *)gEventWork)->revealActive != 0) {
1385 Engine_MessageShowCentered(MsgFieldFlippedSwitch, 1);
1386 SE(SE_188);
1387 WAIT(1);
1391 }
1392 }
1393}
1394
1395/// Reveal: both switches show and can be searched.
1396static void Event_RevealSwitches(void) {
1397 Map_CopyCells(5, 77, 1, 2, 17, 82);
1398 Map_CopyCells(5, 77, 1, 2, 3, 55);
1399 Map_CopyCellAttributes(15, 33, 1, 1, 17, 35);
1400 Map_CopyCellAttributes(3, 8, 1, 1, 3, 10);
1401}
1402
1403/// Reveal's end: both switches hide again.
1404static void Event_HideSwitches(void) {
1405 Map_CopyCells(8, 77, 1, 2, 17, 82);
1406 Map_CopyCells(8, 77, 1, 2, 3, 55);
1407 Map_CopyCellAttributes(18, 35, 1, 1, 17, 35);
1408 Map_CopyCellAttributes(2, 10, 1, 1, 3, 10);
1409}
1410
1411/// Whirlwind on what hides the first switch: it blows away.
1416}
1417
1418/// Whirlwind on what hides the passage: it blows away and the passage opens.
1423}
1424
1425/// Whirlwind on what hides the second switch: it blows away.
1430}
1431
1433
1434/// Garet, Ivan and Mia step out of the leader and gather around Hammet.
1436 struct FieldActor *leader;
1437
1438 leader = Actor_Get(ACTOR_PARTY_LEADER);
1439 if (leader != NULL) {
1440 Actor_SetPosition(IVAN, leader->x.fixed, leader->z.fixed);
1441 }
1442 leader = Actor_Get(ACTOR_PARTY_LEADER);
1443 if (leader != NULL) {
1444 Actor_SetPosition(MIA, leader->x.fixed, leader->z.fixed);
1445 }
1446 leader = Actor_Get(ACTOR_PARTY_LEADER);
1447 if (leader != NULL) {
1448 Actor_SetPosition(GARET, leader->x.fixed, leader->z.fixed);
1449 }
1451 OBJ_SPEED(IVAN, 0xb333, 0x5999);
1452 OBJ_WALK(IVAN, 456, 192);
1453 OBJ_SPEED(MIA, 0xb333, 0x5999);
1454 OBJ_WALK(MIA, 440, 184);
1455 OBJ_SPEED(GARET, 0xb333, 0x5999);
1456 OBJ_WALK(GARET, 448, 240);
1463 WAIT(15);
1464}
1465
1466/// Dodonpa's lever: the room shakes, the floor opens and everyone startles.
1468 Map_SetShake(0x40000, 0x40000, 0x10000);
1469 SE(SE_141);
1470 WAIT(80);
1471 SE(SE_288);
1472 WAIT(5);
1473 SE(SE_145);
1474 Map_CopyCells(16, 75, 7, 4, 26, 55);
1475 Map_SetShake(-1, -1, 0xe666);
1481 WAIT(60);
1482}
1483
1484/// The camera finds the monster Dodonpa has freed; it lumbers forward.
1488 WAIT(60);
1489 MESSAGE_SET(MsgLunpaPrepareBecomeMonster);
1491 OBJ_SPEED(RESCUE_MONSTER, 0x10000, 0x8000);
1492 OBJ_SPEED(RESCUE_MONSTER_PART, 0x10000, 0x8000);
1493 OBJ_WALK(RESCUE_MONSTER, 472, 180);
1494 OBJ_WALK(RESCUE_MONSTER_PART, 472, 180);
1498 WAIT(30);
1499}
1500
1501/// The party spreads out and faces the monster.
1503 OBJ_SPEED(IVAN, 0x10000, 0x8000);
1504 OBJ_WALK(IVAN, 504, 216);
1505 OBJ_SPEED(MIA, 0x10000, 0x8000);
1506 OBJ_WALK(MIA, 440, 232);
1507 OBJ_SPEED(GARET, 0x10000, 0x8000);
1508 OBJ_WALK(GARET, 480, 224);
1516}
1517
1518/// Walking into Hammet's cell. The first time, Hammet hears the party out
1519/// and recognizes Ivan, then Dodonpa arrives, gloats, pulls a lever and
1520/// frees a monster on them; after a lost battle, the scene goes straight to
1521/// the trap. Either way, the battle follows.
1522static void Event_FindHammet(void) {
1523 s32 messageBase;
1524
1525 if (FLAG_CHECK(0x301) != 0)
1526 return;
1528 EV_BEGIN();
1529 // A retry skips the introduction but repeats Dodonpa's trap and battle.
1531 OBJ_SPEED(ACTOR_PARTY_LEADER, 32768, 16384);
1539 WAIT(30);
1540 OBJ_SPEED(IVAN, 45875, 22937);
1541 OBJ_WALK(IVAN, 464, 192);
1543 WAIT(30);
1548 // Dodonpa approaches from the south, then springs the lever trap.
1549 OBJ_POS_SET(RESCUE_DODONPA, 456, 320);
1550 Camera_SetSpeed(131072, 16384);
1551 messageBase = MsgLunpaBackMoreGuess;
1552 MESSAGE_SET(messageBase);
1554 OBJ_WALK(RESCUE_DODONPA, 458, 272);
1557 WAIT(40);
1560 WAIT(60);
1561 SE(SE_155);
1562 Engine_MessageShowCentered(messageBase + 1, 1);
1565 WAIT(120);
1570 WAIT(20);
1571 messageBase += 2;
1574 MESSAGE_SET(messageBase);
1578 WAIT(1);
1579 Battle_SetStart(3);
1583 } else {
1585 SE(MUS_017);
1586 WAIT(30);
1587 // Ivan recognizes Hammet before Dodonpa interrupts the reunion.
1588 messageBase = MsgLunpaTimeEat;
1589 MESSAGE_SET(messageBase);
1592 WAIT(140);
1596 MESSAGE_SET(messageBase + 1);
1598 OBJ_SPEED(ACTOR_PARTY_LEADER, 32768, 16384);
1602 OBJ_SPEED(IVAN, 45875, 22937);
1603 OBJ_WALK(IVAN, 464, 192);
1605 WAIT(30);
1606 MESSAGE_SET(messageBase + 2);
1607 MESSAGE_PUT(IVAN, 0);
1609 WAIT(110);
1610 SE(MUS_060);
1611 MESSAGE_SET(messageBase + 3);
1613 WAIT(30);
1615 WAIT(20);
1618 WAIT(20);
1619 OBJ_SPEED(RESCUE_HAMMET, 26214, 13107);
1620 OBJ_WALK(RESCUE_HAMMET, 520, 208);
1623 WAIT(20);
1625 WAIT(30);
1627 WAIT(30);
1629 WAIT(20);
1630 MESSAGE_SET(messageBase + 4);
1632 WAIT(40);
1634 WAIT(20);
1636 WAIT(120);
1637 MESSAGE_SET(messageBase + 5);
1639 WAIT(25);
1641 WAIT(30);
1643 WAIT(40);
1644 OBJ_WALK(IVAN, 480, 200);
1647 WAIT(60);
1648 MESSAGE_SET(messageBase + 6);
1649 MESSAGE_PUT(IVAN, 0);
1650 WAIT(20);
1652 WAIT(80);
1653 MESSAGE_SET(messageBase + 7);
1655 // Dodonpa approaches from the south, then springs the lever trap.
1656 OBJ_POS_SET(RESCUE_DODONPA, 456, 320);
1657 SE(MUS_019);
1658 MESSAGE_SET(messageBase + 8);
1663 WAIT(5);
1666 WAIT(30);
1667 SE(MUS_061);
1668 Camera_SetSpeed(131072, 16384);
1671 OBJ_SPEED(RESCUE_DODONPA, 52428, 26214);
1672 OBJ_WALK(RESCUE_DODONPA, 456, 304);
1677 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 2, 0);
1679 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 2, 0);
1681 WAIT(60);
1684 WAIT(60);
1685 MESSAGE_SET(messageBase + 9);
1688 MESSAGE_SET(messageBase + 10);
1690 WAIT(60);
1692 WAIT(30);
1693 MESSAGE_SET(messageBase + 11);
1697 WAIT(60);
1703 WAIT(60);
1704 MESSAGE_SET(messageBase + 12);
1707 WAIT(60);
1709 MESSAGE_SET(messageBase + 13);
1711 OBJ_WALK(GARET, 456, 248);
1714 MESSAGE_SET(messageBase + 14);
1715 MESSAGE_PUT(GARET, 0);
1716 OBJ_WALK(IVAN, 472, 216);
1719 WAIT(10);
1720 MESSAGE_SET(messageBase + 15);
1721 MESSAGE_PUT(IVAN, 0);
1723 WAIT(60);
1724 MESSAGE_SET(messageBase + 16);
1726 OBJ_WALK(MIA, 440, 216);
1730 WAIT(10);
1731 MESSAGE_SET(messageBase + 17);
1732 MESSAGE_PUT(MIA, 0);
1734 MESSAGE_SET(messageBase + 18);
1738 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 2, 0);
1739 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 2, 0);
1741 WAIT(60);
1742 MESSAGE_SET(messageBase + 19);
1744 WAIT(20);
1746 WAIT(60);
1747 MESSAGE_SET(messageBase + 20);
1748 MESSAGE_PUT(GARET, 0);
1750 WAIT(60);
1751 MESSAGE_SET(messageBase + 21);
1753 OBJ_WALK(RESCUE_DODONPA, 456, 280);
1756 WAIT(80);
1759 WAIT(60);
1760 SE(SE_155);
1761 Engine_MessageShowCentered(MsgLunpaDodonpaPulledLever, 1);
1765 SE(MUS_052);
1766 MESSAGE_SET(messageBase + 23);
1768 WAIT(60);
1778 WAIT(1);
1779 Battle_SetStart(3);
1783 }
1784 EV_END();
1785}
1786
1787/// After the battle: the monster has fallen on Dodonpa. The party may pull it
1788/// off him; they argue over his punishment until his father Donpa arrives,
1789/// who orders him locked up, thanks the party, and lets them leave with
1790/// Hammet.
1791static void Event_DonpaJudgesDodonpa(void) {
1792 struct FieldActor *leader;
1793 s32 aftermathMessage;
1794 s32 punishmentMessage;
1795 s32 donpaMessage;
1796
1797 FLAG_SET(0x301);
1799 Map_CopyCells(16, 75, 7, 4, 26, 55);
1801 EV_BEGIN();
1802 leader = Actor_Get(RESCUE_HAMMET);
1803 Engine_ActorSetSpriteFlags(leader, 1);
1806 OBJ_POS_SET(GARET, 440, 192);
1808 OBJ_POS_SET(MIA, 488, 184);
1810 OBJ_POS_SET(IVAN, 472, 184);
1812 OBJ_POS_SET(RESCUE_HAMMET, 520, 224);
1814 OBJ_POS_SET(RESCUE_MONSTER, 448, 237);
1819 OBJ_POS_SET(RESCUE_DODONPA, 458, 243);
1823 WAIT(120);
1824
1825 // The fallen monster has pinned Dodonpa; decide whether to help him.
1826 aftermathMessage = MsgLunpaUhnnGetOff;
1827 MESSAGE_SET(aftermathMessage);
1829 OBJ_EMOTE(GARET, EMOTE_IN_FRONT | 1, 60);
1830 MESSAGE_SET((aftermathMessage + 1));
1831 MESSAGE_PUT(GARET, 0);
1833 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 1, 1);
1834 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 1, 1);
1835 WAIT(60);
1837 WAIT(60);
1838 MESSAGE_SET((aftermathMessage + 2));
1844 WAIT(60);
1845 OBJ_WALK(RESCUE_HAMMET, 512, 232);
1847 WAIT(60);
1848 MESSAGE_SET((aftermathMessage + 3));
1850 WAIT(15);
1852 MESSAGE_SET((aftermathMessage + 4));
1859 MESSAGE_SET((aftermathMessage + 5));
1860 MESSAGE_PUT(IVAN, 0);
1861 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 5, 0);
1863 WAIT(80);
1865 MESSAGE_SET((aftermathMessage + 6));
1866 MESSAGE_PUT(MIA, 0);
1869 WAIT(100);
1870 MESSAGE_SET((aftermathMessage + 7));
1873 WAIT(10);
1874 MESSAGE_SET((aftermathMessage + 8));
1875 MESSAGE_PUT(GARET, 0);
1877 WAIT(30);
1878 MESSAGE_SET((aftermathMessage + 9));
1879 MESSAGE_PUT(IVAN, 0);
1881 MESSAGE_SET((aftermathMessage + 10));
1882 MESSAGE_OPEN(MIA, 0);
1883 if (Engine_EventChooseYesNo(0, 0) == 0) {
1888 WAIT(60);
1889 } else {
1890 MESSAGE_SET((aftermathMessage + 11));
1891 MESSAGE_PUT(MIA, 0);
1896 WAIT(20);
1898 WAIT(60);
1900 WAIT(80);
1902 WAIT(30);
1904 MESSAGE_SET((aftermathMessage + 12));
1906 WAIT(60);
1915 WAIT(80);
1921 }
1922 OBJ_SPEED(ACTOR_PARTY_LEADER, 0x8000, 0x4000);
1923 OBJ_SPEED(GARET, 0x8000, 0x4000);
1924 OBJ_SPEED(MIA, 0x8000, 0x4000);
1925 OBJ_SPEED(IVAN, 0x8000, 0x4000);
1926 OBJ_WALK(GARET, 416, 216);
1928 OBJ_WALK(GARET, 416, 248);
1930 OBJ_WALK(GARET, 440, 248);
1933 OBJ_WALK(ACTOR_PARTY_LEADER, 440, 216);
1936 OBJ_WALK(MIA, 488, 248);
1938 OBJ_WALK(MIA, 456, 248);
1941 OBJ_WALK(IVAN, 456, 216);
1946 WAIT(60);
1951 WAIT(100);
1952 SE(SE_226);
1954 // Move the party and both monster parts together to free Dodonpa.
1955 OBJ_SPEED(ACTOR_PARTY_LEADER, 0x1999, 0xccc);
1957 OBJ_SPEED(GARET, 0x1999, 0xccc);
1959 OBJ_SPEED(MIA, 0x1999, 0xccc);
1961 OBJ_SPEED(IVAN, 0x1999, 0xccc);
1963 OBJ_SPEED(RESCUE_MONSTER, 0x1999, 0xccc);
1964 OBJ_SPEED(RESCUE_MONSTER_PART, 0x1999, 0xccc);
1968 SE(SE_288);
1969 WAIT(60);
1974 WAIT(60);
1979 WAIT(100);
1980 OBJ_SPEED(ACTOR_PARTY_LEADER, 0xb333, 0x5999);
1981 OBJ_SPEED(GARET, 0xb333, 0x5999);
1982 OBJ_SPEED(IVAN, 0xb333, 0x5999);
1983 OBJ_SPEED(MIA, 0xb333, 0x5999);
1984 OBJ_WALK(ACTOR_PARTY_LEADER, 456, 184);
1988 OBJ_WALK(GARET, 464, 256);
1990 OBJ_WALK(GARET, 480, 248);
1992 OBJ_WALK(GARET, 440, 192);
1996 OBJ_WALK(MIA, 488, 248);
1998 OBJ_WALK(MIA, 488, 184);
1999 OBJ_WALK(IVAN, 472, 184);
2006 WAIT(30);
2007 WAIT(60);
2008 // Debate Dodonpa's punishment before his father arrives.
2009 punishmentMessage = MsgLunpaAbleGet;
2010 MESSAGE_SET(punishmentMessage);
2011 MESSAGE_PUT(GARET, 0);
2013 WAIT(120);
2015 WAIT(60);
2017 MESSAGE_SET((punishmentMessage + 1));
2019 WAIT(20);
2021 WAIT(10);
2022 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 1, 80);
2025 MESSAGE_SET((punishmentMessage + 2));
2026 MESSAGE_PUT(MIA, 0);
2029 WAIT(60);
2031 WAIT(70);
2032 MESSAGE_SET((punishmentMessage + 3));
2035 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 8, 40);
2036 MESSAGE_SET((punishmentMessage + 4));
2037 MESSAGE_PUT(IVAN, 0);
2039 OBJ_EMOTE(GARET, EMOTE_IN_FRONT | 3, 60);
2040 OBJ_WALK(GARET, 440, 208);
2043 MESSAGE_SET((punishmentMessage + 5));
2044 MESSAGE_PUT(GARET, 0);
2045 WAIT(20);
2047 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 1, 0);
2048 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 1, 0);
2050 WAIT(70);
2051 OBJ_FACE(GARET, IVAN, 0);
2052 OBJ_EMOTE(GARET, EMOTE_IN_FRONT | 2, 75);
2055 MESSAGE_SET((punishmentMessage + 6));
2056 MESSAGE_PUT(GARET, 0);
2058 WAIT(60);
2059 MESSAGE_SET((punishmentMessage + 7));
2061 OBJ_WALK(GARET, 448, 208);
2065 MESSAGE_SET((punishmentMessage + 8));
2066 MESSAGE_PUT(GARET, 0);
2068 WAIT(60);
2070 WAIT(60);
2071 MESSAGE_SET((punishmentMessage + 9));
2074 WAIT(60);
2075 MESSAGE_SET((punishmentMessage + 10));
2076 MESSAGE_PUT(GARET, 0);
2078 WAIT(30);
2079 MESSAGE_SET((punishmentMessage + 11));
2080 MESSAGE_PUT(IVAN, 0);
2081 OBJ_FACE(GARET, MIA, 0);
2082 WAIT(20);
2083 MESSAGE_SET((punishmentMessage + 12));
2084 MESSAGE_PUT(GARET, 0);
2085 WAIT(30);
2087 OBJ_FACE(MIA, GARET, 0);
2088 MESSAGE_SET((punishmentMessage + 13));
2089 MESSAGE_PUT(MIA, 0);
2091 MESSAGE_SET((punishmentMessage + 14));
2092 MESSAGE_PUT(MIA, 0);
2097 WAIT(120);
2100 WAIT(120);
2102 WAIT(60);
2103 MESSAGE_SET((punishmentMessage + 15));
2105 OBJ_EMOTE(GARET, EMOTE_IN_FRONT | 7, 110);
2106 OBJ_WALK(GARET, 456, 212);
2109 MESSAGE_SET((punishmentMessage + 16));
2110 MESSAGE_PUT(GARET, 0);
2111 OBJ_FACE(IVAN, GARET, 0);
2112 WAIT(60);
2114 MESSAGE_SET((punishmentMessage + 17));
2115 MESSAGE_PUT(IVAN, 0);
2117 WAIT(80);
2118 OBJ_FACE(GARET, IVAN, 0);
2119 WAIT(60);
2121 WAIT(30);
2126 WAIT(80);
2128 WAIT(30);
2129 MESSAGE_SET((punishmentMessage + 18));
2130 MESSAGE_PUT(GARET, 0);
2132 WAIT(70);
2133 MESSAGE_SET((punishmentMessage + 19));
2136 MESSAGE_SET((punishmentMessage + 20));
2137 MESSAGE_PUT(MIA, 0);
2139 WAIT(80);
2140 MESSAGE_SET((punishmentMessage + 21));
2141 MESSAGE_OPEN(IVAN, 0);
2146 OBJ_POS_SET(RESCUE_DONPA, 456, 304);
2147 OBJ_SPEED(RESCUE_DONPA, 0x8000, 0x4000);
2148 if (Engine_EventChooseYesNo(0, 0) == 0) {
2149 SE(MUS_019);
2150 MESSAGE_SET((punishmentMessage + 22));
2152 } else {
2153 SE(MUS_019);
2154 MESSAGE_SET((punishmentMessage + 23));
2156 }
2163 Camera_MoveTo(0x1c80000, -1, 0xf00000, 1);
2165 WAIT(60);
2166 SE(MUS_008);
2167 // Donpa takes charge and orders his son to remain imprisoned.
2168 donpaMessage = MsgLunpaDad;
2169 MESSAGE_SET(donpaMessage);
2171 OBJ_WALK(RESCUE_DONPA, 456, 280);
2173 OBJ_WALK(RESCUE_DONPA, 440, 256);
2174 Camera_MoveTo(0x1c80000, -1, 0xe00000, 1);
2175 MESSAGE_SET((donpaMessage + 1));
2181 WAIT(89);
2182 MESSAGE_SET((donpaMessage + 2));
2186 MESSAGE_SET((donpaMessage + 3));
2190 WAIT(80);
2192 WAIT(20);
2193 MESSAGE_SET((donpaMessage + 4));
2196 MESSAGE_SET((donpaMessage + 5));
2198 WAIT(30);
2201 WAIT(20);
2202 MESSAGE_SET((donpaMessage + 6));
2206 MESSAGE_SET((donpaMessage + 7));
2209 MESSAGE_SET((donpaMessage + 8));
2212 MESSAGE_SET((donpaMessage + 9));
2214 WAIT(20);
2216 WAIT(80);
2218 OBJ_WALK(RESCUE_DONPA, 496, 240);
2221 WAIT(20);
2223 MESSAGE_SET((donpaMessage + 10));
2226 MESSAGE_SET((donpaMessage + 11));
2228 WAIT(40);
2230 WAIT(20);
2231 MESSAGE_SET((donpaMessage + 12));
2235 MESSAGE_SET((donpaMessage + 13));
2238 MESSAGE_SET((donpaMessage + 14));
2241 WAIT(140);
2243 WAIT(120);
2249 WAIT(120);
2251 MESSAGE_SET((donpaMessage + 15));
2254 MESSAGE_SET((donpaMessage + 16));
2258 WAIT(80);
2260 WAIT(60);
2265 WAIT(60);
2266 MESSAGE_SET((donpaMessage + 17));
2270 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 1, 0);
2271 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 1, 0);
2272 WAIT(100);
2273 MESSAGE_SET((donpaMessage + 18));
2274 MESSAGE_PUT(GARET, 0);
2276 WAIT(60);
2277 MESSAGE_SET((donpaMessage + 19));
2278 MESSAGE_PUT(IVAN, 0);
2280 WAIT(20);
2281 MESSAGE_SET((donpaMessage + 20));
2285 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 1, 0);
2286 OBJ_EMOTE(MIA, EMOTE_IN_FRONT | 1, 0);
2287 WAIT(120);
2289 WAIT(120);
2290 MESSAGE_SET((donpaMessage + 21));
2293 MESSAGE_SET((donpaMessage + 22));
2300 WAIT(80);
2302 WAIT(120);
2303 MESSAGE_SET((donpaMessage + 23));
2306 MESSAGE_SET((donpaMessage + 24));
2309 WAIT(20);
2311 WAIT(50);
2312 MESSAGE_SET((donpaMessage + 25));
2315 WAIT(70);
2316 MESSAGE_SET((donpaMessage + 26));
2317 MESSAGE_PUT(GARET, 0);
2319 MESSAGE_SET((donpaMessage + 27));
2320 MESSAGE_PUT(MIA, 0);
2323 WAIT(20);
2324 MESSAGE_SET((donpaMessage + 28));
2326 OBJ_EMOTE(IVAN, EMOTE_IN_FRONT | 1, 90);
2327 MESSAGE_SET((donpaMessage + 29));
2328 MESSAGE_PUT(IVAN, 0);
2330 WAIT(20);
2331 MESSAGE_SET((donpaMessage + 30));
2334 WAIT(60);
2335 MESSAGE_SET((donpaMessage + 31));
2338 WAIT(20);
2340 WAIT(20);
2341 MESSAGE_SET((donpaMessage + 32));
2344 MESSAGE_SET((donpaMessage + 33));
2345 MESSAGE_PUT(GARET, 0);
2347 WAIT(30);
2348 MESSAGE_SET((donpaMessage + 34));
2351 MESSAGE_SET((donpaMessage + 35));
2352 MESSAGE_PUT(MIA, 0);
2354 MESSAGE_SET((donpaMessage + 36));
2357 WAIT(30);
2359 WAIT(100);
2360 MESSAGE_SET((donpaMessage + 37));
2361 MESSAGE_OPEN(IVAN, 0);
2362 if (Engine_EventChooseYesNo(0, 0) != 0) {
2363 MESSAGE_SET((donpaMessage + 38));
2365 }
2366 WAIT(30);
2370 WAIT(100);
2374 WAIT(100);
2375 // Rejoin the companions, then escort Hammet out of the fortress.
2377 leader = Actor_Get(ACTOR_PARTY_LEADER);
2378 if (leader != 0) {
2379 Actor_SetDestination(GARET, leader->x.part.pixel, leader->z.part.pixel);
2380 }
2382 OBJ_POS_SET(GARET, 0, 0);
2384 leader = Actor_Get(ACTOR_PARTY_LEADER);
2385 if (leader != 0) {
2386 Actor_SetDestination(IVAN, leader->x.part.pixel, leader->z.part.pixel);
2387 }
2389 OBJ_POS_SET(IVAN, 0, 0);
2391 leader = Actor_Get(ACTOR_PARTY_LEADER);
2392 if (leader != 0) {
2393 Actor_SetDestination(MIA, leader->x.part.pixel, leader->z.part.pixel);
2394 }
2396 OBJ_POS_SET(MIA, 0, 0);
2397 WAIT(30);
2398 OBJ_SPEED(RESCUE_HAMMET, 0x6666, 0x3333);
2399 OBJ_WALK(RESCUE_HAMMET, 472, 184);
2405 WAIT(20);
2407 WAIT(20);
2408 MESSAGE_SET((donpaMessage + 39));
2411 MESSAGE_SET((donpaMessage + 40));
2414 WAIT(30);
2415 OBJ_SPEED(ACTOR_PARTY_LEADER, 0x10000, 0x8000);
2416 OBJ_SPEED(RESCUE_HAMMET, 0x10000, 0x8000);
2418 OBJ_WALK(ACTOR_PARTY_LEADER, 480, 248);
2419 WAIT(40);
2422 OBJ_WALK(RESCUE_HAMMET, 480, 216);
2429 WAIT(5);
2431 WAIT(100);
2433 WAIT(100);
2434 OBJ_WALK(RESCUE_HAMMET, 480, 248);
2435 OBJ_WALK(ACTOR_PARTY_LEADER, 456, 248);
2437 OBJ_WALK(RESCUE_HAMMET, 456, 248);
2439 OBJ_WALK(ACTOR_PARTY_LEADER, 456, 360);
2441 OBJ_WALK(RESCUE_HAMMET, 456, 360);
2443 OBJ_WALK(ACTOR_PARTY_LEADER, 352, 360);
2445 OBJ_WALK(RESCUE_HAMMET, 352, 360);
2446 WAIT(20);
2447 SE(MUS_017);
2450 WAIT(1);
2451 WAIT(210);
2453 EV_END();
2454}
2455
2456/// Mind Read on the second sentry: one of eight thoughts, chosen at random
2457/// when the map was entered; in one he looks around first.
2458static void Event_ReadSentrysThoughts(void) {
2459
2460 switch (gLunpaFortressRandomPick) {
2461 case 0:
2462 MESSAGE_SET(MsgLunpaHammetGreatMerchant);
2464 break;
2465 case 1:
2466 MESSAGE_SET(MsgLunpaZZZ);
2468 break;
2469 case 2:
2470 MESSAGE_SET(MsgLunpaDodonpasOrdersAbsolute);
2472 break;
2473 case 3:
2474 MESSAGE_SET(MsgLunpaSighBadCouldnt);
2476 break;
2477 case 4:
2478 MESSAGE_SET(MsgLunpaStrangeSwearSomeone);
2480 break;
2481 case 6:
2482 MESSAGE_SET(MsgLunpaToldStandGuard);
2484 break;
2485 case 7:
2486 MESSAGE_SET(MsgLunpaWhoDisruptingSleep);
2488 break;
2489 case 5:
2491 0);
2492 WAIT(50);
2495 WAIT(50);
2497 0);
2498 WAIT(50);
2499 MESSAGE_SET(MsgLunpaTakeCareAnybody);
2501 break;
2502 }
2503}
2504
2505/// The second sentry looks around, hearing someone he cannot see.
2506static void Event_TalkToSentry(void) {
2507
2508 s32 messageBase;
2509
2512 WAIT(50);
2514 WAIT(50);
2516 WAIT(50);
2517 messageBase = MsgLunpaLeftGuardHearsSomeone;
2518 MESSAGE_SET(messageBase);
2521 WAIT(60);
2523 WAIT(40);
2524 MESSAGE_SET(messageBase + 1);
2526}
2527
2528/// Donpa's attendant. Before the rescue the attendant hushes the party,
2529/// glances at the sleeping Donpa, asks a question and tells of Donpa and his
2530/// spoiled son; once told, only a line. After the rescue, Donpa is grateful.
2531static void Event_TalkToAttendant(void) {
2532 s32 whisperMessage;
2533 s32 familyMessage;
2534
2535 EV_BEGIN();
2537 MESSAGE_SET(MsgLunpaDonpaGrateful);
2538 MESSAGE_PUT(18, 0);
2539 EV_END();
2540 } else {
2541 if (FLAG_CHECK(0x313) != 0) {
2542 MESSAGE_SET(MsgLunpaMaybeDodonpasEyes);
2544 EV_END();
2545 } else {
2548 whisperMessage = MsgLunpaShhhPleaseDont;
2549 MESSAGE_SET(whisperMessage);
2554 WAIT(60);
2556 WAIT(20);
2558 MESSAGE_SET(whisperMessage + 1);
2561 MESSAGE_SET(whisperMessage + 2);
2563 WAIT(70);
2566 MESSAGE_SET(whisperMessage + 3);
2568 if (Engine_EventChooseYesNo(0, 0) == 0) {
2569 MESSAGE_SET(whisperMessage + 4);
2571 } else {
2572 MESSAGE_SET(whisperMessage + 5);
2574 }
2575 WAIT(60);
2577 familyMessage = MsgLunpaDonpaKnowsCoddled;
2578 MESSAGE_SET(familyMessage);
2581 MESSAGE_SET(familyMessage + 1);
2584 MESSAGE_SET(familyMessage + 2);
2586 FLAG_SET(0x313);
2587 EV_END();
2588 }
2589 }
2590}
2591
2592/// Mind Read on Donpa's attendant.
2595 MESSAGE_SET(MsgLunpaDifficultDonpaRight);
2597 } else {
2598 MESSAGE_SET(MsgLunpaSomeonePunishDodonpa);
2600 }
2601}
2602
2603/// Mind Read on Donpa.
2604static void Event_ReadDonpasThoughts(void) {
2606 MESSAGE_SET(MsgLunpaFatherStayAngry);
2608 } else {
2609 MESSAGE_SET(MsgLunpaFatherSorryDodonpa);
2611 }
2612}
2613
2614/// Donpa: asleep before the rescue. "ZZZZ..." After it, the first time, he
2615/// thanks the party and has his attendant show them his reward.
2616static void Event_TalkToDonpa(void) {
2617 s32 rewardMessage;
2618
2621 FLAG_CHECK(0x314) == 0) {
2622 rewardMessage = MsgLunpaThankHelpDodonpa;
2623 MESSAGE_SET(rewardMessage);
2626 WAIT(30);
2627 OBJ_SPEED(GUARD_ROOM_DONPA, 6553, 3276);
2631 WAIT(60);
2632 OBJ_SPEED(GUARD_ROOM_DONPA, 13107, 6553);
2636 MESSAGE_SET(rewardMessage + 1);
2640 MESSAGE_SET(rewardMessage + 2);
2642 WAIT(70);
2644 WAIT(60);
2645 OBJ_SPEED(GUARD_ROOM_ATTENDANT, 26214, 13107);
2646 OBJ_WALK(GUARD_ROOM_ATTENDANT, 880, 112);
2649 MESSAGE_SET(rewardMessage + 3);
2652 WAIT(70);
2656 MESSAGE_SET(rewardMessage + 4);
2658 OBJ_WALK(ACTOR_PARTY_LEADER, 896, 120);
2661 WAIT(60);
2663 WAIT(30);
2664 FLAG_SET(0x314);
2665 } else {
2666 MESSAGE_SET(MsgLunpaWellWorriedDodonpa);
2668 }
2669 } else {
2670 MESSAGE_SET(MsgLunpaZZZZ);
2672 }
2673}
2674
2675/// Talking to the Djinni in Donpa's room: it joins the party.
2676static void Event_DjinniJoins(void) {
2679}
2680
2681/// The third of the beaten guards begs. "Owww! Hey! Don't hurt me again..."
2682static void Event_TalkToBeatenGuardC(void) {
2684 MESSAGE_SET(MsgLunpaOwwwDontHurt);
2686}
2687
2688/// The second of the beaten guards gives up, and Hammet is in the cave.
2689/// "We give up!"
2690static void Event_TalkToBeatenGuardB(void) {
2692 MESSAGE_SET(MsgLunpaRightRightGive);
2694}
2695
2696/// The first of the beaten guards marvels at the party.
2697/// "Who'd have thought they'd be so tough?"
2698static void Event_TalkToBeatenGuardA(void) {
2700 MESSAGE_SET(MsgLunpaGuysTougherThought);
2702}
2703
2704/// Asks where Dodonpa is. "Do you know where Dodonpa is?"
2705static void Event_AskWhereDodonpaIs(void) {
2706 MESSAGE_SET(MsgLunpaKnowWhereDodonpa);
2707 Engine_EventAskYesNo(18, 0);
2708}
2709
2710/// A resident of the outer rooms, startled the first time, asks whether the
2711/// party sneaked in in search of something; on yes, promises to keep quiet.
2712/// "Wh-Wh-Who goes there!"
2714 s32 frightMessage;
2715 s32 purposeMessage;
2716
2717 if (FLAG_CHECK(FLAG_SCENE_TEMP_26) != 0) {
2718 MESSAGE_SET(MsgLunpaWontTellAnyone);
2720 } else {
2721 EV_BEGIN();
2723 if (FLAG_CHECK(FLAG_SCENE_TEMP_27) == 0) {
2727 WAIT(20);
2728 frightMessage = MsgLunpaWhWhWho;
2729 MESSAGE_SET(frightMessage);
2732 MESSAGE_SET(frightMessage + 1);
2734 WAIT(30);
2736 WAIT(30);
2737 }
2738 purposeMessage = MsgLunpaDontLookNearly;
2739 MESSAGE_SET(purposeMessage);
2742 MESSAGE_SET(purposeMessage + 1);
2744 if (Engine_EventChooseYesNo(0, 0) == 0) {
2745 MESSAGE_SET(purposeMessage + 2);
2748 } else {
2749 MESSAGE_SET(purposeMessage + 3);
2751 }
2753 EV_END();
2754 }
2755}
2756
2757/// Mind Read on the startled resident: once they have promised, a thought
2758/// about Hammet; before, Mind Read stops and they talk instead.
2760
2762 MESSAGE_SET(MsgLunpaMaybeMerchantReason);
2764 } else {
2765 s16 *psynergyRequest = &gEventWork->psynergyRequest;
2766
2767 *psynergyRequest = 0;
2770 }
2771}
2772
2774
2775/// Dodonpa behind bars begs his father's forgiveness; with the Cell Key, a
2776/// further line shows.
2777static void Event_TalkToJailedDodonpa(void) {
2778 s32 pleaMessage = MsgLunpaWrongTurnOver;
2779
2780 MESSAGE_SET(pleaMessage);
2781 MESSAGE_PUT(0x800d, 0);
2783 Engine_MessageShowCentered(pleaMessage + 2, 1);
2784 }
2785}
2786
2787/// Mind Read on the jailed Dodonpa.
2789 MESSAGE_SET(MsgLunpaCantBelieveWhen);
2791}
2792
2793/// Sets each map up: a random pick for the guards' lines, the doors already
2794/// opened, the watching guards and, in the rescue room, the scene after
2795/// the monster battle or Dodonpa jailed.
2797 struct FieldActor *sceneActor;
2798
2803 }
2814 sceneActor = Actor_Get(8);
2815 if (sceneActor != 0)
2816 Engine_ActorSetSpriteFlags(sceneActor, 0);
2818 sceneActor = Actor_Get(9);
2819 if (sceneActor != 0)
2820 Engine_ActorSetSpriteFlags(sceneActor, 0);
2822 sceneActor = Actor_Get(10);
2823 if (sceneActor != 0)
2824 Engine_ActorSetSpriteFlags(sceneActor, 0);
2830 }
2831 if (gGameState.entrance == 3) {
2835 OBJ_POS_SET(16, 432, 344);
2837 OBJ_POS_SET(RESCUE_DODONPA, 456, 288);
2839 OBJ_POS_SET(17, 456, 320);
2841 }
2842 }
2843 sceneActor = Actor_Get(RESCUE_MONSTER_PART);
2844 if (sceneActor != 0)
2845 Engine_ActorSetSpriteFlags(sceneActor, 0);
2847 sceneActor->scaleX = 0xcccc;
2848 }
2849 return 0;
2850}
2851
2852/// Sets the outer rooms up by entrance: the guards that watch each part, and
2853/// the cell doors already opened.
2856 switch (gGameState.entrance) {
2857 case 2:
2858 case 3:
2859 case 4:
2860 case 5:
2861 case 6:
2862 case 7:
2870 break;
2871 case 12:
2872 case 19:
2875 break;
2876 case 16:
2877 case 17:
2878 case 18:
2883 Engine_TaskWait(1);
2885 Engine_TaskWait(1);
2886 Map_CopyCells(101, 9, 10, 8, 110, 9);
2888 break;
2889 case 13:
2890 case 14:
2891 case 15:
2894 break;
2895 default:
2898 break;
2899 }
2905 Engine_TaskWait(1);
2906}
2907
2908/// Sets the guard rooms up: beaten guards gone or lying where they fell, the
2909/// Cell Key gone once taken, the patrols by entrance and Donpa's attendant
2910/// by his reward's place.
2912 struct FieldActor *keyActor;
2913
2920 }
2923 }
2926 }
2929 }
2930 switch (gGameState.entrance) {
2931 case 1:
2932 case 2:
2933 case 3:
2938 Engine_TaskWait(1);
2940 Engine_TaskWait(1);
2941 break;
2942 case 10:
2943 case 13:
2944 case 20:
2945 case 23:
2946 case 24:
2950 if (FLAG_CHECK(0x314)) {
2952 }
2953 break;
2954 case 21:
2955 case 22:
2960 Engine_TaskWait(1);
2962 Engine_TaskWait(1);
2963 break;
2964 case 11:
2965 case 12:
2969 }
2970 break;
2975 break;
2976 case 14:
2977 case 15:
2978 case 16:
2980 break;
2981 default:
2984 break;
2985 }
2986 keyActor = Actor_Get(GUARD_ROOM_CELL_KEY);
2989 keyActor->scaleX = 0xc000;
2990 keyActor->scaleY = 0xc000;
2991}
2992
2993/// Sets the column room up: the doors, the column, the Whirlwind covers and
2994/// the switches as the party left them.
2996 struct FieldActor *sceneActor;
2997
3002 }
3008 }
3012 }
3016 }
3019 }
3022 }
3023 EV_BEGIN();
3025 if (sceneActor != 0) {
3027 }
3029 if (sceneActor != 0) {
3031 }
3033 if (sceneActor != 0) {
3035 }
3036 sceneActor = Actor_Get(11);
3037 if (sceneActor != 0) {
3038 Engine_ActorSetSpriteFlags(sceneActor, 0);
3039 }
3041 sceneActor = Actor_Get(COLUMN_ROOM_COLUMN);
3042 if (sceneActor != 0) {
3043 sceneActor->collisionFlags |= 0x10;
3044 }
3046 EV_END();
3048}
3049
3050/// The outer rooms' cell doors stay open.
3054 }
3057 }
3060 }
3061}
3062
3063/// The guard rooms' cell doors stay open.
3067 }
3070 }
3071}
3072
3073/// The column room's cell doors stay open.
3077 }
3080 }
3083 }
3084}
3085
3086/// The rescue room's cell doors stay open.
3090 }
3093 }
3096 }
3099 }
3102 }
3103}
3104
3105/// The shared source and field.h declarations lack const, but these three
3106/// tables occupy .rodata. Pixel steps pack X above Z in two halfwords.
3107/// Unsigned packing also defines the entries with negative X steps.
3108#define DIRECTION_STEP(dx, dz) (((u32)(dx) << 16) | ((u32)(dz) & 0xffff))
3109
3110/* FAKEMATCH: the three section attributes below place non-const tables in
3111 * .rodata, where the ROM has them; without them, tbs-en differs, and const
3112 * conflicts with field.h */
3113s32 gStagedActor_DirectionSteps[] __attribute__((section(".rodata"))) = {
3114 DIRECTION_STEP(16, 0), DIRECTION_STEP(16, 0), DIRECTION_STEP(16, 0),
3115 DIRECTION_STEP(0, 16), DIRECTION_STEP(0, 16), DIRECTION_STEP(0, 16),
3116 DIRECTION_STEP(0, 16), DIRECTION_STEP(-16, 0), DIRECTION_STEP(-16, 0),
3117 DIRECTION_STEP(-16, 0), DIRECTION_STEP(-16, 0), DIRECTION_STEP(0, -16),
3118 DIRECTION_STEP(0, -16), DIRECTION_STEP(0, -16), DIRECTION_STEP(0, -16),
3119 DIRECTION_STEP(16, 0),
3120};
3121
3122// clang-format off
3123u32 gStagedActor_FootprintKinds[] __attribute__((section(".rodata"))) = {
3124 207, 205, 228, 229, 298, 297,
3125};
3126
3127s32 gStagedActor_FootprintBounds[] __attribute__((section(".rodata"))) = {
3128 -32, -8, 32, 8,
3129 -8, -32, 8, 32,
3130 -32, -16, 32, 0,
3131 -8, -32, 8, 32,
3132 -32, -8, 32, 8,
3133 -8, -32, 8, 32,
3134};
3135
3137
3139 SC_SET(SW_ACCEL, 0x11999),
3140 SC_SET(SW_SPEED, 0x11999),
3141 SC_ARG(2),
3142 SC_MOVE(PIXELS(192), 0, PIXELS(288)),
3143 SC_SYNC,
3144 SC_ARG(1),
3145 SC_ARG(2),
3146 SC_MOVE(PIXELS(88), 0, PIXELS(288)),
3147 SC_SYNC,
3149};
3150
3152 SC_SET(SW_ACCEL, 0x11999),
3153 SC_SET(SW_SPEED, 0x11999),
3154 SC_ARG(2),
3155 SC_MOVE(PIXELS(192), 0, PIXELS(192)),
3156 SC_SYNC,
3157 SC_ARG(1),
3158 SC_ARG(2),
3159 SC_MOVE(PIXELS(88), 0, PIXELS(192)),
3160 SC_SYNC,
3162};
3163
3165 SC_ARG(5),
3166 SC_END,
3167};
3168
3170 SC_SET(SW_ACCEL, 0x3333),
3171 SC_SET(SW_SPEED, 0x9999),
3172 SC_ARG(2),
3173 SC_MOVE(PIXELS(808), 0, PIXELS(648)),
3174 SC_SYNC,
3175 SC_ARG(1),
3176 SC_WAIT(25),
3177 SC_ARG(2),
3178 SC_MOVE(PIXELS(808), 0, PIXELS(520)),
3179 SC_SYNC,
3180 SC_ARG(1),
3181 SC_WAIT(20),
3182 SC_ARG(2),
3183 SC_MOVE(PIXELS(712), 0, PIXELS(520)),
3184 SC_SYNC,
3185 SC_ARG(1),
3186 SC_WAIT(25),
3187 SC_ARG(2),
3188 SC_MOVE(PIXELS(808), 0, PIXELS(520)),
3189 SC_SYNC,
3190 SC_ARG(1),
3191 SC_WAIT(40),
3192 SC_ARG(2),
3193 SC_MOVE(PIXELS(808), 0, PIXELS(648)),
3194 SC_SYNC,
3195 SC_ARG(1),
3196 SC_WAIT(20),
3197 SC_ARG(2),
3198 SC_MOVE(PIXELS(744), 0, PIXELS(648)),
3199 SC_SYNC,
3200 SC_ARG(1),
3201 SC_WAIT(30),
3203};
3204
3206 SC_SET(SW_ACCEL, 0x3333),
3207 SC_SET(SW_SPEED, 0x9999),
3208 SC_ARG(2),
3209 SC_MOVE(PIXELS(920), 0, PIXELS(648)),
3210 SC_SYNC,
3211 SC_ARG(1),
3212 SC_ARG(2),
3213 SC_MOVE(PIXELS(840), 0, PIXELS(648)),
3214 SC_SYNC,
3215 SC_ARG(1),
3216 SC_ARG(2),
3217 SC_MOVE(PIXELS(840), 0, PIXELS(592)),
3218 SC_SYNC,
3219 SC_ARG(1),
3220 SC_ARG(2),
3221 SC_MOVE(PIXELS(840), 0, PIXELS(648)),
3222 SC_SYNC,
3223 SC_ARG(1),
3224 SC_ARG(2),
3225 SC_MOVE(PIXELS(920), 0, PIXELS(648)),
3226 SC_SYNC,
3227 SC_ARG(1),
3228 SC_ARG(2),
3229 SC_MOVE(PIXELS(920), 0, PIXELS(592)),
3230 SC_SYNC,
3231 SC_ARG(1),
3233};
3234
3236 { 0, CONDITION_ALWAYS, 168, 0, 632, FACING_NORTH, 0, -1, -1, -1, -1, 0 },
3237 { 1, CONDITION_ALWAYS, 160, 0, 168, FACING_NORTH, 0, 40, 24, 296, 280, 0 },
3238 { 2, CONDITION_ALWAYS, 160, 0, 104, FACING_SOUTH, 0, 40, 24, 296, 280, 0 },
3239 { 3, CONDITION_ALWAYS, 272, 0, 896, FACING_NORTH, 0, 24, 616, 536, 936, 0 },
3240 { 4, CONDITION_ALWAYS, 376, 0, 896, FACING_NORTH, 0, 24, 616, 536, 936, 0 },
3241 { 5, CONDITION_ALWAYS, 248, 0, 856, FACING_SOUTH, 0, 24, 616, 536, 936, 0 },
3242 { 6, CONDITION_ALWAYS, 488, 0, 680, FACING_SOUTH, 0, 24, 616, 536, 936, 0 },
3243 { 7, CONDITION_ALWAYS, 72, 0, 696, FACING_SOUTH, 0, 24, 616, 536, 936, 0 },
3244 { 8, CONDITION_ALWAYS, 96, 0, 856, FACING_SOUTH, 0, 24, 616, 536, 936, 0 },
3245 { 9, CONDITION_ALWAYS, 376, 0, 184, FACING_SOUTH, 0, 328, 8, 568, 232, 0 },
3246 { 10, CONDITION_ALWAYS, 504, 0, 88, FACING_SOUTH, 0, 328, 8, 568, 232, 0 },
3247 { 11, CONDITION_ALWAYS, 440, 0, 104, FACING_SOUTH, 0, 328, 8, 568, 232, 0 },
3248 { 12, CONDITION_ALWAYS, 136, 0, 512, FACING_NORTH, 0, 40, 328, 280, 552, 0 },
3249 { 13, CONDITION_ALWAYS, 888, 0, 280, FACING_NORTH, 0, 632, 40, 952, 328, 0 },
3250 { 14, CONDITION_ALWAYS, 696, 0, 264, FACING_SOUTH, 0, 632, 40, 952, 328, 0 },
3251 { 15, CONDITION_ALWAYS, 824, 0, 120, FACING_SOUTH, 0, 632, 40, 952, 328, 0 },
3252 { 16, CONDITION_ALWAYS, 664, 0, 632, FACING_NORTH, 0, 616, 344, 936, 696, 0 },
3253 { 17, CONDITION_ALWAYS, 888, 0, 520, FACING_NORTH, 0, 616, 344, 936, 696, 0 },
3254 { 18, CONDITION_ALWAYS, 696, 0, 432, FACING_SOUTH, 0, 616, 344, 936, 696, 0 },
3255 { 19, CONDITION_ALWAYS, 440, 0, 448, FACING_NORTH, 0, 320, 312, 560, 504, 0 },
3256 { 20, CONDITION_ALWAYS, 696, 0, 824, FACING_NORTH, 0, 616, 744, 856, 952, 0 },
3257 { SCENE_TABLE_END },
3258};
3259
3261 { 0, CONDITION_ALWAYS, 168, 0, 632, FACING_NORTH, 0, -1, -1, -1, -1, 0 },
3262 { 1, CONDITION_ALWAYS, 136, 0, 392, FACING_SOUTH, 0, 40, 8, 308, 448, 0 },
3263 { 2, CONDITION_ALWAYS, 136, 0, 80, FACING_SOUTH, 0, 40, 8, 308, 448, 0 },
3264 { 3, CONDITION_ALWAYS, 264, 0, 416, FACING_SOUTH, 0, 40, 8, 308, 448, 0 },
3265 { 4, CONDITION_ALWAYS, 376, 0, 232, FACING_NORTH, 0, 328, 8, 568, 272, 0 },
3266 { 5, CONDITION_ALWAYS, 504, 0, 104, FACING_NORTH, 0, 328, 8, 568, 272, 0 },
3267 { 6, CONDITION_ALWAYS, 376, 0, 176, FACING_SOUTH, 0, 328, 8, 568, 272, 0 },
3268 { 7, CONDITION_ALWAYS, 408, 0, 456, FACING_NORTH, 0, 328, 272, 584, 512, 0 },
3269 { 8, CONDITION_ALWAYS, 456, 0, 352, FACING_SOUTH, 0, 328, 272, 584, 512, 0 },
3270 { 9, CONDITION_ALWAYS, 504, 0, 456, FACING_NORTH, 0, 328, 272, 584, 512, 0 },
3271 { 10, CONDITION_ALWAYS, 136, 0, 640, FACING_NORTH, 0, 16, 472, 256, 688, 0 },
3272 { 11, CONDITION_ALWAYS, 648, 0, 72, FACING_SOUTH, 0, 568, 16, 808, 176, 0 },
3273 { 12, CONDITION_ALWAYS, 744, 0, 80, FACING_SOUTH, 0, 568, 16, 808, 176, 0 },
3274 { 13, CONDITION_ALWAYS, 696, 0, 376, FACING_NORTH, 0, 576, 264, 816, 432, 0 },
3275 { 14, CONDITION_ALWAYS, 200, 0, 848, FACING_SOUTH, 0, 152, 680, 424, 992, 0 },
3276 { 15, CONDITION_ALWAYS, 264, 0, 776, FACING_SOUTH, 0, 152, 680, 424, 992, 0 },
3277 { 16, CONDITION_ALWAYS, 376, 0, 824, FACING_SOUTH, 0, 152, 680, 424, 992, 0 },
3278 { 17, CONDITION_ALWAYS, 536, 0, 696, FACING_NORTH, 0, 488, 584, 760, 896, 0 },
3279 { 18, CONDITION_ALWAYS, 680, 0, 832, FACING_SOUTH, 0, 488, 584, 760, 896, 0 },
3280 { 19, CONDITION_ALWAYS, 712, 0, 856, FACING_NORTH, 0, 488, 584, 760, 896, 0 },
3281 { 20, CONDITION_ALWAYS, 912, 0, 192, FACING_NORTH, 0, 784, 24, 1024, 240, 0 },
3282 { 21, CONDITION_ALWAYS, 840, 0, 664, FACING_NORTH, 0, 768, 440, 1008, 704, 0 },
3283 { 22, CONDITION_ALWAYS, 952, 0, 528, FACING_SOUTH, 0, 768, 440, 1008, 704, 0 },
3284 { 23, CONDITION_ALWAYS, 872, 0, 376, FACING_NORTH, 0, 768, 264, 1016, 432, 0 },
3285 { 24, CONDITION_ALWAYS, 904, 0, 112, FACING_SOUTH, 0, 784, 24, 1024, 240, 0 },
3286 { 30, CONDITION_ALWAYS, 408, 0, 456, FACING_NORTH, 0, 328, 272, 584, 512, 0 },
3287 { 31, CONDITION_ALWAYS, 648, 0, 88, FACING_NORTH, 0, 568, 16, 808, 176, 0 },
3288 { SCENE_TABLE_END },
3289};
3290
3292 { 0, CONDITION_ALWAYS, 168, 0, 632, FACING_NORTH, 0, -1, -1, -1, -1, 0 },
3293 { 1, CONDITION_ALWAYS, 424, 0, 584, FACING_SOUTH, 0, 200, 488, 480, 648, 0 },
3294 { 2, CONDITION_ALWAYS, 344, 0, 568, FACING_SOUTH, 0, 200, 488, 480, 648, 0 },
3295 { 3, CONDITION_ALWAYS, 312, 0, 448, FACING_NORTH, 0, 8, 8, 568, 480, 0 },
3296 { 4, CONDITION_ALWAYS, 440, 0, 296, FACING_SOUTH, 0, 8, 8, 568, 480, 0 },
3297 { 5, CONDITION_ALWAYS, 312, 0, 248, FACING_SOUTH, 0, 8, 8, 568, 480, 0 },
3298 { 6, CONDITION_ALWAYS, 104, 0, 184, FACING_SOUTH, 0, 8, 8, 568, 480, 0 },
3299 { SCENE_TABLE_END },
3300};
3301
3303 { 0, CONDITION_ALWAYS, 168, 0, 632, FACING_NORTH, 0, -1, -1, -1, -1, 0 },
3304 { 1, CONDITION_ALWAYS, 56, 0, 328, FACING_NORTH, 0, 8, 8, 264, 424, 0 },
3305 { 2, CONDITION_ALWAYS, 184, 0, 368, FACING_NORTH, 0, 8, 8, 264, 424, 0 },
3306 { 3, CONDITION_ALWAYS, 328, 0, 344, FACING_SOUTH, 0, 288, 32, 576, 432, 0 },
3307 { 4, CONDITION_ALWAYS, 440, 0, 224, FACING_NORTH, 0, 288, 32, 576, 432, 0 },
3308 { SCENE_TABLE_END },
3309};
3310
3311/// Scenes 161 to 163 are the fortress's maps 2 to 4; field_scene.h has no names
3312/// for them yet, nor for scene 99.
3316 SCENE_EXIT(2, SCENE_LUNPA, 3),
3317 SCENE_EXIT(3, 99, 11),
3327 SCENE_EXIT(8, 161, 1),
3329 SCENE_EXIT(10, 161, 16),
3330 SCENE_EXIT(11, 162, 1),
3341};
3342
3344 SCENE_EXITS(161),
3347 SCENE_EXIT(2, 161, 4),
3348 SCENE_EXIT(3, 161, 7),
3349 SCENE_EXIT(4, 161, 2),
3350 SCENE_EXIT(5, 161, 11),
3351 SCENE_EXIT(6, 161, 13),
3352 SCENE_EXIT(7, 161, 3),
3353 SCENE_EXIT(8, 161, 10),
3354 SCENE_EXIT(9, 161, 14),
3355 SCENE_EXIT(10, 161, 8),
3356 SCENE_EXIT(11, 161, 5),
3357 SCENE_EXIT(12, 161, 17),
3358 SCENE_EXIT(13, 161, 6),
3359 SCENE_EXIT(14, 161, 9),
3360 SCENE_EXIT(15, 161, 21),
3362 SCENE_EXIT(17, 161, 12),
3363 SCENE_EXIT(18, 161, 20),
3364 SCENE_EXIT(19, 161, 22),
3365 SCENE_EXIT(20, 161, 18),
3366 SCENE_EXIT(21, 161, 15),
3367 SCENE_EXIT(22, 161, 19),
3368 SCENE_EXIT(23, 161, 24),
3369 SCENE_EXIT(24, 161, 23),
3371};
3372
3374 SCENE_EXITS(162),
3376 SCENE_EXIT(2, 162, 3),
3377 SCENE_EXIT(3, 162, 2),
3378 SCENE_EXIT(4, 163, 2),
3379 SCENE_EXIT(5, 163, 1),
3380 SCENE_EXIT(6, 163, 3),
3382 SCENE_EXIT(0, 163, 0),
3383 SCENE_EXIT(1, 162, 5),
3384 SCENE_EXIT(2, 162, 4),
3385 SCENE_EXIT(5, 162, 6),
3389};
3390
3392 { SCENE_TABLE_END },
3393};
3394
3397 PIXELS(184), 0, PIXELS(328), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3399 PIXELS(232), 0, PIXELS(296), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3401 PIXELS(344), 0, PIXELS(252), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3403 PIXELS(552), 0, PIXELS(184), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3405 PIXELS(8), 0, PIXELS(8), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3407 0, 0, 0, FACING_WEST, TALK_KEEP_FACING, 0 },
3409 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3411 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3413 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3414 { SCENE_TABLE_END },
3415};
3416
3419 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
3421 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
3423 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
3425 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
3427 PIXELS(136), 0, PIXELS(760), FACING_SOUTH + FACING_STEP, TALK_FACE_PARTY, 0 },
3435 PIXELS(192), 0, PIXELS(432), FACING_SOUTH + FACING_STEP, TALK_KEEP_FACING, 0 },
3441 PIXELS(192), 0, PIXELS(464), FACING_SOUTH + FACING_STEP, TALK_FACE_PARTY, 0 },
3446 { SCENE_TABLE_END },
3447};
3448
3451 PIXELS(264), 0, PIXELS(856), FACING_SOUTH, TALK_KEEP_FACING, 0 },
3453 PIXELS(88), 0, PIXELS(192), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3455 PIXELS(88), 0, PIXELS(288), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3457 PIXELS(456), 0, PIXELS(392), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3467 PIXELS(680), 0, PIXELS(824), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3469 PIXELS(920), 0, PIXELS(600), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3473 PIXELS(168), 0, PIXELS(560), FACING_WEST, TALK_FACE_PARTY, 0 },
3475 PIXELS(148), 0, PIXELS(616), FACING_SOUTH + FACING_STEP, TALK_FACE_PARTY, 0 },
3483 PIXELS(944), 0, PIXELS(122), FACING_SOUTH, TALK_KEEP_FACING, 0 },
3486 { 0x5b, 0x49, ACTOR_STAND,
3487 PIXELS(872), 0, PIXELS(336), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3488 { SCENE_TABLE_END },
3489};
3490
3493 PIXELS(280), 0, PIXELS(576), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3495 PIXELS(440), 0, PIXELS(282), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3497 PIXELS(56), 0, PIXELS(176), FACING_SOUTH, TALK_FACE_PARTY, 0 },
3499 PIXELS(504), 0, PIXELS(168), FACING_NORTH, TALK_KEEP_FACING, 0 },
3501 PIXELS(248), 0, PIXELS(136), FACING_NORTH, TALK_KEEP_FACING, 0 },
3502 { SCENE_TABLE_END },
3503};
3504
3507 PIXELS(56), 0, PIXELS(72), FACING_NORTH, TALK_KEEP_FACING, 0 },
3509 PIXELS(136), 0, PIXELS(72), FACING_NORTH, TALK_KEEP_FACING, 0 },
3511 PIXELS(216), 0, PIXELS(72), FACING_NORTH, TALK_KEEP_FACING, 0 },
3512 { 0xbb, CONDITION_ALWAYS, 7,
3513 PIXELS(472), 0, PIXELS(88), FACING_SOUTH, TALK_KEEP_FACING, 0 },
3515 PIXELS(528), 0, PIXELS(216), FACING_WEST, TALK_KEEP_FACING, 0 },
3517 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3519 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3521 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3523 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3525 0, 0, 0, FACING_NORTH, TALK_KEEP_FACING, 0 },
3526 { 0x120, CONDITION_ALWAYS, 7,
3527 PIXELS(464), 0, PIXELS(88), FACING_SOUTH, TALK_KEEP_FACING, 0 },
3529 0, 0, 0, FACING_SOUTH, TALK_FACE_PARTY, 0 },
3531 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
3532 { SCENE_TABLE_END },
3533};
3534
3536 { SCENE_EVENTS_END },
3537};
3538
3540 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
3541 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
3542 { EVENT_EXIT, 3, CONDITION_ALWAYS, 3 },
3543 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
3544 { EVENT_EXIT, 5, CONDITION_ALWAYS, 5 },
3545 { EVENT_EXIT, 6, CONDITION_ALWAYS, 6 },
3546 { EVENT_EXIT, 7, CONDITION_ALWAYS, 7 },
3547 { 0x21, 8, CONDITION_ALWAYS, 8 },
3548 { EVENT_EXIT, 9, CONDITION_ALWAYS, 9 },
3549 { 0x21, 10, CONDITION_ALWAYS, 10 },
3550 { 0x31, 11, CONDITION_ALWAYS, 11 },
3551 { EVENT_EXIT, 12, CONDITION_ALWAYS, 12 },
3552 { EVENT_EXIT, 13, CONDITION_ALWAYS, 13 },
3553 { EVENT_EXIT, 14, CONDITION_ALWAYS, 14 },
3554 { EVENT_EXIT, 15, CONDITION_ALWAYS, 15 },
3555 { EVENT_EXIT, 16, CONDITION_ALWAYS, 16 },
3556 { EVENT_EXIT, 17, CONDITION_ALWAYS, 17 },
3557 { EVENT_EXIT, 18, CONDITION_ALWAYS, 18 },
3558 { EVENT_EXIT, 19, CONDITION_ALWAYS, 19 },
3559 { EVENT_EXIT, 20, CONDITION_ALWAYS, 20 },
3569 { EVENT_TALK, 19, CONDITION_ALWAYS, MSGNO(MsgLunpaDonpaResting) },
3570 { EVENT_TALK, 14, CONDITION_ALWAYS, MSGNO(MsgLunpaWhereIsDodonpa) },
3571 { EVENT_TALK, 15, CONDITION_ALWAYS, MSGNO(MsgLunpaHammetBuysDrink) },
3572 { EVENT_TALK, 16, CONDITION_ALWAYS, MSGNO(MsgLunpaHammetMoneyTree) },
3575 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 19, CONDITION_ALWAYS, MSGNO(MsgLunpaWhoFoughtDonpa) },
3576 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, CONDITION_ALWAYS, MSGNO(MsgLunpaWifeSeeksDodonpa) },
3577 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, CONDITION_ALWAYS, MSGNO(MsgLunpaKalayBuysDrink) },
3578 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgLunpaHammetKeepsEarnings) },
3590 { SCENE_EVENTS_END },
3591};
3592
3594 { 0x31, 1, CONDITION_ALWAYS, 1 },
3595 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
3596 { EVENT_EXIT, 3, CONDITION_ALWAYS, 3 },
3597 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
3598 { EVENT_EXIT, 5, CONDITION_ALWAYS, 5 },
3599 { EVENT_EXIT, 6, CONDITION_ALWAYS, 6 },
3600 { EVENT_EXIT, 7, CONDITION_ALWAYS, 7 },
3601 { EVENT_EXIT, 8, CONDITION_ALWAYS, 8 },
3602 { EVENT_EXIT, 9, CONDITION_ALWAYS, 9 },
3603 { EVENT_EXIT, 10, CONDITION_ALWAYS, 10 },
3604 { EVENT_EXIT, 11, CONDITION_ALWAYS, 11 },
3605 { EVENT_EXIT, 12, CONDITION_ALWAYS, 12 },
3606 { EVENT_EXIT, 13, CONDITION_ALWAYS, 13 },
3607 { EVENT_EXIT, 14, CONDITION_ALWAYS, 14 },
3608 { EVENT_EXIT, 15, CONDITION_ALWAYS, 15 },
3609 { 0x31, 16, CONDITION_ALWAYS, 16 },
3610 { EVENT_EXIT, 17, CONDITION_ALWAYS, 17 },
3611 { EVENT_EXIT, 18, CONDITION_ALWAYS, 18 },
3612 { EVENT_EXIT, 19, CONDITION_ALWAYS, 19 },
3613 { EVENT_EXIT, 20, CONDITION_ALWAYS, 20 },
3614 { EVENT_EXIT, 21, CONDITION_ALWAYS, 21 },
3615 { EVENT_EXIT, 22, CONDITION_ALWAYS, 22 },
3616 { EVENT_EXIT, 23, CONDITION_ALWAYS, 23 },
3617 { EVENT_EXIT, 24, CONDITION_ALWAYS, 24 },
3629 { EVENT_TALK, 19, CONDITION_ALWAYS, MSGNO(MsgLunpaChildMustGrowUp) },
3630 { EVENT_TALK, 20, CONDITION_ALWAYS, MSGNO(MsgLunpaPapaWatchesLadies) },
3631 { EVENT_TALK, 21, CONDITION_ALWAYS, MSGNO(MsgLunpaChildTooResponsible) },
3632 { EVENT_TALK, 22, CONDITION_ALWAYS, MSGNO(MsgLunpaDonpaExhausted) },
3633 { EVENT_TALK, 23, CONDITION_ALWAYS, MSGNO(MsgLunpaWomenWantHome) },
3640 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 18, CONDITION_ALWAYS, MSGNO(MsgLunpaDonpappaSuccessor) },
3641 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 19, CONDITION_ALWAYS, MSGNO(MsgLunpaDonpappaProtectsFortress) },
3642 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 20, CONDITION_ALWAYS, MSGNO(MsgLunpaDaughterWillNotMarryPapa) },
3643 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 21, CONDITION_ALWAYS, MSGNO(MsgLunpaDonpappaJudges) },
3644 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 22, CONDITION_ALWAYS, MSGNO(MsgLunpaFearWithoutDonpa) },
3645 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 23, CONDITION_ALWAYS, MSGNO(MsgLunpaHopeDonpaRecovers) },
3646 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GUARD_ROOM_GUARD_A, CONDITION_ALWAYS, MSGNO(MsgLunpaShouldNotHaveFought) },
3647 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GUARD_ROOM_GUARD_B, CONDITION_ALWAYS, MSGNO(MsgLunpaHammetInCave) },
3648 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GUARD_ROOM_GUARD_C, CONDITION_ALWAYS, MSGNO(MsgLunpaHiddenDoorSwitch) },
3653 { SCENE_EVENTS_END },
3654};
3655
3657 { 0x21, 1, CONDITION_ALWAYS, 1 },
3658 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
3659 { EVENT_EXIT, 3, CONDITION_ALWAYS, 3 },
3660 { EVENT_EXIT, 4, CONDITION_ALWAYS, 4 },
3661 { EVENT_EXIT, 5, CONDITION_ALWAYS, 5 },
3662 { 0x31, 6, CONDITION_ALWAYS, 6 },
3679 { SCENE_EVENTS_END },
3680};
3681
3683 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
3684 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
3685 { 0x21, 5, CONDITION_ALWAYS, 5 },
3693 { EVENT_TALK, 16, CONDITION_ALWAYS, MSGNO(MsgLunpaHammetStillInside) },
3694 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgLunpaDodonpaSecretlyInside) },
3695 { EVENT_TALK, 12, CONDITION_ALWAYS, MSGNO(MsgLunpaWrongTurnOver) },
3696 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, CONDITION_ALWAYS, MSGNO(MsgLunpaCantBelieveWhen) },
3700 { SCENE_EVENTS_END },
3701};
3702
3704 13, 56, 8, 56, 3, 56, 28, 85,
3705 28, 65,
3706};
3707
3709 31, 61, 15, 57, 6, 61,
3710};
3711
3713 16, 119, 16, 113,
3714};
3715
3717 28, 72, 43, 92,
3718};
3719// clang-format on
Ability numbers, named from the English release.
@ ABILITY_CLOAK
Definition ability_ids.h:21
@ ABILITY_MIND_READ
Definition ability_ids.h:16
@ ABILITY_CATCH
Definition ability_ids.h:23
@ ABILITY_REVEAL
Definition ability_ids.h:19
@ ABILITY_MOVE
Definition ability_ids.h:15
@ ABILITY_WHIRLWIND
Definition ability_ids.h:13
void Object_RefreshSelectorById(u32 objectId)
Waits, at most 300 frames, for an actor's script to reach its end (command 0x10).
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
const struct ScenePlacement * Scene_GetPlacements(void)
const struct SceneEntrance * Scene_GetEntrances(void)
const struct SceneEvent * Scene_GetEvents(void)
const u32 * Scene_GetExits(void)
Both scenes share one exit table.
const struct SceneRegion * Scene_GetRegions(void)
s32 Scene_Initialize(void)
Sets up whichever scene is being entered and runs its arrival events.
s32 gStagedActor_DirectionSteps[]
Pixel step by direction: X in the upper halfword, Z in the lower.
s32 gStagedActor_FootprintBounds[]
#define DIRECTION_STEP(dx, dz)
Pixel step by direction: X in the upper halfword, Z in the lower.
u32 gStagedActor_FootprintKinds[]
#define GARET
Jerald.
#define MIA
Mary.
#define IVAN
Ivan.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
The engine calls the debug menus import, and their palette swatch tiles.
The edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
Scene commands: the all-caps macros the scene scripts are written in.
#define EV_BEGIN()
Definition event.h:30
#define OBJ_DIR(no, d, t)
Definition event.h:16
#define OBJ_POS_SET(no, x, z)
Definition event.h:13
#define EV_END()
Definition event.h:31
#define MESSAGE_OPEN(no, f)
Definition event.h:11
#define WAIT(n)
Definition event.h:7
#define OBJ_MODE(no, m)
Definition event.h:18
#define OBJ_WALK(no, x, z)
Definition event.h:14
#define MESSAGE_PUT(no, f)
Definition event.h:10
#define MESSAGE_SET(m)
Definition event.h:9
#define SE(n)
Definition event.h:28
#define FLAG_SET(f)
Definition event.h:26
#define FLAG_CHECK(f)
Definition event.h:25
#define OBJ_FACE(no, to, t)
Definition event.h:17
#define OBJ_EMOTE(no, e, t)
Definition event.h:19
#define OBJ_SPEED(no, s, a)
Definition event.h:15
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
@ ANIM_WALK
Definition field_event.h:44
@ ANIM_STAND
Definition field_event.h:43
@ ANIM_NOD
Definition field_event.h:45
@ ANIM_SHAKE_HEAD
Definition field_event.h:46
static void Actor_SetDestination(s32 actor, s32 x, s32 z)
void Engine_MapCopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
static void Actor_SetBuiltinAction(s32 actor, s32 action)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
s32 Engine_PartyGiveItem(s32 item, s32 flags)
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
static void Camera_SetSpeed(s32 speed, s32 acceleration)
s32 Engine_TaskRemoveCallback(void(*callback)(void))
void Engine_CameraMoveToActor(s32 actor, s32 pan)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
#define EMOTE_IN_FRONT
Definition field_event.h:49
void Engine_ItemShowFound(s32 item, s32 height)
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_EventCloseScreen(void)
void Engine_ObjectDispatchRelease(struct FieldActor *object)
void Engine_PsynergyCancel(void)
s32 Engine_EventAskYesNo(s32 speaker, s32 flags)
void Engine_EventOpenScreen(void)
void Engine_GameFlagSet(s32 flag)
void Engine_GameFlagClear(s32 flag)
void Engine_CameraWaitForMove(void)
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_ActorStop(s32 actor)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
void Engine_ActorWalkTo(s32 actor, s32 x, s32 z)
s32 Engine_RandomNext()
static void Map_CopyCells(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorSetChildValue(s32 actor, s32 value)
static void Map_SetShake(s32 horizontal, s32 vertical, s32 decay)
Sets shake amplitudes in fixed-point pixels and the per-frame decay factor.
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
struct FieldActor * Engine_EventGetViewCenter(void)
@ TASK_PRIORITY_SCENE
Definition field_event.h:40
void Engine_MapRedraw(void)
static void Camera_MoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
static void Actor_SetPosition(s32 actor, s32 fixed_x, s32 fixed_z)
void Engine_ActorSetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorFaceEachOther(s32 actor, s32 other, s32 frames)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
static struct FieldActor * Actor_Get(s32 actor)
@ 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
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
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 PSYNERGY_IN_AREA(ability, phase)
@ SCENE_LUNPA_FORTRESS
Definition field_scene.h:21
@ SCENE_WEST_LUNPA_CAVE
Definition field_scene.h:19
@ SCENE_LUNPA
Definition field_scene.h:17
@ SCENE_WORLD_MAP
Definition field_scene.h:13
@ SCENE_LUNPA_FORTRESS_GATE
Definition field_scene.h:20
#define SCENE_EXIT(exit, scene, entrance)
Definition field_scene.h:73
@ ACTOR_PARTY_LEADER
@ SCENE_TABLE_END
Definition field_scene.h:43
@ CONDITION_ALWAYS
Definition field_scene.h:44
@ TALK_KEEP_FACING
@ TALK_FACE_PARTY
@ TALK_FACE_PARTY_AND_BACK
#define PSYNERGY_ON_ACTOR(ability)
#define EVENT_SCRIPT(script)
@ ACTOR_WANDER
@ ACTOR_STAND
#define SEARCH(target)
#define SCENE_EXITS_END
Definition field_scene.h:77
#define TOUCH_WALKING_INTO(facing)
#define TOUCH_FACING(facing)
@ 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_UNNAMED
@ SEARCH_CHEST
@ SEARCH_BARREL
#define FIND_COINS(coins)
static s32 Task_AddCallback(void(*callback)(void), s32 priority)
Calls the main-image scheduler through engine_call.h.
Game flags, named where their meaning is shown.
#define FLAG_SCENE_TEMP_70
Definition flags.h:825
#define FLAG_SCENE_TEMP_15
Definition flags.h:734
#define FLAG_LUNPA_FORTRESS_THREE_GUARDS_BEATEN
Definition flags.h:308
#define FLAG_SCENE_TEMP_27
Definition flags.h:752
#define FLAG_LUNPA_FORTRESS_HALL_GUARD_BEATEN
Definition flags.h:307
#define FLAG_LUNPA_TRADE_REOPENED
Definition flags.h:123
#define FLAG_LUNPA_FORTRESS_COLUMN_LOWERED
Definition flags.h:299
#define FLAG_LUNPA_FORTRESS_REWARD_TAKEN
Donpa's reward, the Djinni in his room, has joined the party.
Definition flags.h:312
#define FLAG_LUNPA_FORTRESS_FIRST_SWITCH_UNCOVERED
Whirlwind has blown away what hid the first switch, the passage and the second switch.
Definition flags.h:302
#define FLAG_SCENE_TEMP_25
Definition flags.h:750
#define FLAG_LUNPA_FORTRESS_CHEST_POWER_BREAD
Definition flags.h:318
#define FLAG_LUNPA_FORTRESS_CHEST_COINS
Definition flags.h:316
#define FLAG_SCENE_TEMP_17
Definition flags.h:736
#define FLAG_LUNPA_FORTRESS_SECOND_SWITCH_FLIPPED
Definition flags.h:306
#define FLAG_LUNPA_FORTRESS_CELL_KEY
caught or taken from its hook
Definition flags.h:319
#define FLAG_LUNPA_FORTRESS_WEST_GUARD_BEATEN
Definition flags.h:310
#define FLAG_LUNPA_FORTRESS_THIRD_CHEST
item 0xaa
Definition flags.h:315
#define FLAG_LUNPA_FORTRESS_FIRST_SWITCH_FLIPPED
Definition flags.h:305
#define FLAG_SCENE_TEMP_18
Definition flags.h:737
#define FLAG_LUNPA_FORTRESS_TRAP_SEEN
The party has seen Hammet's rescue up to Dodonpa's trap; a retry after losing the battle skips to the...
Definition flags.h:298
#define FLAG_SCENE_TEMP_26
Definition flags.h:751
#define FLAG_SCENE_TEMP_24
Definition flags.h:749
#define FLAG_LUNPA_FORTRESS_PASSAGE_UNCOVERED
Definition flags.h:303
#define FLAG_MENU_OPEN
Set while the field menu is open; scenes hold their moving actors still.
Definition flags.h:23
#define FLAG_LUNPA_FORTRESS_CHEST_ELIXIR
Definition flags.h:313
#define FLAG_LUNPA_FORTRESS_SECOND_SWITCH_UNCOVERED
Definition flags.h:304
#define FLAG_SCENE_TEMP_14
Definition flags.h:733
#define FLAG_LUNPA_FORTRESS_CHEST_LUCKY_MEDAL
Definition flags.h:314
#define FLAG_LUNPA_FORTRESS_BARREL_VIAL
Definition flags.h:317
#define FLAG_LUNPA_FORTRESS_EAST_GUARD_BEATEN
Definition flags.h:309
volatile u32 gFrameCount
Frames WaitFrames has finished.
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 work slots of gWorkSlot, read through their own names.
void * gMapWork[]
The screen blend's globals and the graphics routines.
The main-image routines scene overlays import.
void Engine_EventSetNextDestination(s32 first, s32 second)
void Engine_BattleFxSetWeightedResult(s32 zone_no, s32 slot_no)
void Engine_MapSetWorkFlagBits9To11(u32 v)
void Engine_BattleFxRunPageEffectForSlot(s32 slot, s32 element, s32 djinn)
s32 Engine_BattleFxPlayCueAndStartEmitterOnTarget(s32 effect, s32 target, s32 mode)
s32 Engine_PartyInventoryFindOwner(s32 item_id)
Item numbers, named from the English release.
@ ITEM_CELL_KEY
Definition item_ids.h:75
@ ITEM_ELIXIR
Definition item_ids.h:48
@ ITEM_POWER_BREAD
Definition item_ids.h:50
@ ITEM_MYTHRIL_CIRCLET
Definition item_ids.h:39
@ ITEM_VIAL
Definition item_ids.h:42
@ ITEM_LUCKY_MEDAL
Definition item_ids.h:70
static void LunpaFortress_RestoreGuardRoomDoors(void)
The guard rooms' cell doors stay open.
static void Event_UnlockColumnRoomDoor(void)
Facing a column room cell door with the Cell Key: it opens with a rumble.
static void LunpaFortress_CheckUpperHallGuard(void)
Every frame in the upper hall: the guard who sees the uncloaked leader raises TRIGGER_UPPER_HALL_SPOT...
s32 gLunpaFortressRandomPick
s32 gDonpaSleeps[]
struct SceneEvent gLunpaFortressNoEvents[]
s32 gOuterPatrolRoute[]
static void Event_FlipFirstSwitch(void)
Searching the first switch while Reveal shows it flips it, and its passage opens.
static void LunpaFortress_OpenFirstSwitchPassage(void)
The first switch's passage opens.
#define PATROL_RAISED_TRIGGER(work)
struct ScenePlacement gLunpaFortressPlacements1[]
static void LunpaFortress_InitializeOuterRooms(void)
Sets the outer rooms up by entrance: the guards that watch each part, and the cell doors already open...
static void Event_PushColumn(void)
Pushing the column: it slides one cell along.
static void Event_FightWestGuard(void)
Walking up to the west guard: he challenges the party to a battle, and is gone after it.
static void LunpaFortress_CheckEntranceGuard(void)
Every frame past the entrance: the guard who sees the uncloaked leader raises TRIGGER_ENTRANCE_GUARD_...
static void LunpaFortress_ActOutGuardShiftDialogue(s32 actorId)
A guard expects his relief, then sees who it is. "Is my shift up already?".
u32 gLunpaFortressExits2[]
s32 gFirstPatrolRoute[]
static void UNUSED LunpaFortress_DoNothingA(void)
static s32 LunpaFortress_TryCollectDisplayedItem(s32 actorId, s32 itemId)
Gives the item an actor shows, with its effect; with no room for it, the actor shows the item is left...
static void Event_TalkToBeatenGuardB(void)
The second of the beaten guards gives up, and Hammet is in the cave.
@ TRIGGER_LOCKED_DOOR
@ TRIGGER_UPPER_HALL_SPOTTED
@ TRIGGER_SEALED_DOOR
@ TRIGGER_ENTRANCE_GUARD_SPOTTED
@ TRIGGER_SENTRIES_SPOTTED
@ DOOR_TRIGGER_FIRST
@ TRIGGER_OUTER_PATROL_SPOTTED
@ TRIGGER_HALL_PATROL_SPOTTED
@ TRIGGER_PATROL_PAIR_SPOTTED
u32 gColumnRoomDoorCells[]
static void Event_TalkToBeatenGuardA(void)
The first of the beaten guards marvels at the party.
static s32 LunpaFortress_IsLeaderPassingPatrollingGuard(void)
Whether the leader and the hall patrol are in the two parallel corridors, where the guard passes with...
struct ScenePlacement gLunpaFortressPlacements3[]
static void UNUSED LunpaFortress_DoNothingF(void)
static void LunpaFortress_ActOutIntruderDialogue(s32 actorId)
A guard spots an intruder. "Hey! Intruder!".
static void Event_ReadAttendantsThoughts(void)
Mind Read on Donpa's attendant.
static __inline__ void LunpaFortress_FlipHiddenSwitch(s32 cellX, s32 cellY, void(*openPassage)(void))
A switch flips in two frames, then its passage opens.
@ GUARD_ROOM_FIRST_PATROL
@ GUARD_ROOM_ATTENDANT
@ GUARD_ROOM_HALL_GUARD
@ GUARD_ROOM_GUARD_A
The three guards who fight together.
@ GUARD_ROOM_GUARD_C
@ GUARD_ROOM_DONPA
@ GUARD_ROOM_EAST_GUARD
@ GUARD_ROOM_HALL_PATROL
@ GUARD_ROOM_SECOND_PATROL
@ GUARD_ROOM_GUARD_B
@ GUARD_ROOM_CELL_KEY
@ GUARD_ROOM_WEST_GUARD
@ GUARD_ROOM_DJINNI
struct SceneEvent gLunpaFortressEvents1[]
static void Event_UnlockGuardRoomDoor(void)
Facing a guard room cell door with the Cell Key: it opens with a rumble.
static void LunpaFortress_LowerColumn(void)
The column sinks into the floor: the party can walk over it.
static void Event_RevealSwitches(void)
Reveal: both switches show and can be searched.
u32 gGuardRoomDoorCells[]
static void LunpaFortress_OpenCoveredPassage(void)
The passage behind the second Whirlwind cover opens.
static s32 LunpaFortress_IsLeaderInOuterPatrolSafeZone(void)
Where the outer rooms' patrol cannot see the leader: three stretches of its rounds.
static void Event_FlipSecondSwitch(void)
Searching the second switch while Reveal shows it flips it, and its passage opens.
u32 gLunpaFortressExitsOther[]
Scenes 161 to 163 are the fortress's maps 2 to 4; field_scene.h has no names for them yet,...
struct SceneEntrance gLunpaFortressEntrances2[]
static void LunpaFortress_RestoreRescueRoomDoors(void)
The rescue room's cell doors stay open.
static void UNUSED LunpaFortress_DoNothingB(void)
u32 gRescueRoomDoorCells[]
s32 gSecondPatrolRoute[]
static void Event_UpperHallGuardThrowsPartyOut(void)
Raised when the upper hall's guard spots the leader: he throws the party out.
static void LunpaFortress_UpdateOuterGuardDetection(void)
Every frame in the outer rooms: the patrolling guard, as LunpaFortress_UpdatePairedGuardDetection; se...
static void Event_FightThreeGuards(void)
Walking up to the three guards: they argue, then fight the party together.
static void Event_FightEastGuard(void)
Walking up to the east guard: he challenges the party to a battle, and is gone after it.
struct SceneEvent gLunpaFortressEvents3[]
#define PATROL_PSYNERGY_REQUEST(work)
static void LunpaFortress_RestoreColumnRoomDoors(void)
The column room's cell doors stay open.
static void Event_HallPatrolThrowsPartyOut(void)
Raised when the hall patrol spots the leader: it throws the party out.
struct SceneEntrance gLunpaFortressEntrances3[]
static void LunpaFortress_InitializeGuardRooms(void)
Sets the guard rooms up: beaten guards gone or lying where they fell, the Cell Key gone once taken,...
static void LunpaFortress_RestoreLoweredColumn(void)
The column stays sunk in its hole.
struct SceneEntrance gLunpaFortressEntrancesOther[]
s32 gHallPatrolRoute[]
static s32 LunpaFortress_CanGuardSeeLeader(s32 actorId)
Whether a guard on screen sees the leader along his row or column.
struct SceneEntrance gLunpaFortressEntrances1[]
static void UNUSED LunpaFortress_TryCollectActorNineItem(void)
static s32 LunpaFortress_IsLeaderInGuardVerticalSight(s32 actorId)
Whether the leader is in the guard's column, up to six cells away.
static void Event_UnlockRescueRoomDoor(void)
Facing a rescue room cell door with the Cell Key: it opens with a rumble.
static void Event_ReadStartledResidentsThoughts(void)
Mind Read on the startled resident: once they have promised, a thought about Hammet; before,...
@ GUARD_ROOM_DOOR_FLAG
@ OUTER_DOOR_FLAG
@ RESCUE_DOOR_FLAG
@ COLUMN_ROOM_DOOR_FLAG
static void Event_TalkToJailedDodonpa(void)
Dodonpa behind bars begs his father's forgiveness; with the Cell Key, a further line shows.
static void Event_HideSwitches(void)
Reveal's end: both switches hide again.
static void LunpaFortress_RestoreOuterDoors(void)
The outer rooms' cell doors stay open.
static void Event_BlowAwaySecondSwitchCover(void)
Whirlwind on what hides the second switch: it blows away.
static void LunpaFortress_OpenColumnRoomDoor(s32 doorIndex)
Draws a column room cell door open and lets the party through; the middle door opens two cells.
static void LunpaFortress_CheckGuardDoorApproach(void)
Every frame in the guard rooms: walking east or west into the first cell door's column with the Cell ...
static void LunpaFortress_ActOutScoundrelDialogue(s32 actorId)
A guard calls the party a scoundrel. "You scoundrel!".
static void Event_ReadDonpasThoughts(void)
Mind Read on Donpa.
static void LunpaFortress_UpdateHallGuardDetection(void)
Every frame in the guard rooms: the patrol in the east hall, as LunpaFortress_UpdatePairedGuardDetect...
@ OUTER_SECOND_SENTRY
@ OUTER_ENTRANCE_GUARD
@ OUTER_FIRST_SENTRY
@ OUTER_PATROL_GUARD
@ OUTER_UPPER_HALL_GUARD
@ OUTER_STARTLED_RESIDENT
static s32 LunpaFortress_IsLeaderOutsideUpperHall(void)
Whether the leader is outside the upper hall the guard there watches.
static void LunpaFortress_GuardChallengesParty(s32 actorId)
A guard faces the leader with one of four challenges, chosen at random when the map was entered.
static void UNUSED LunpaFortress_DoNothingE(void)
static void LunpaFortress_PositionPartyForMonster(void)
The party spreads out and faces the monster.
static void LunpaFortress_InitializeColumnRoom(void)
Sets the column room up: the doors, the column, the Whirlwind covers and the switches as the party le...
static void LunpaFortress_GatherPartyAroundHammet(void)
Garet, Ivan and Mia step out of the leader and gather around Hammet.
struct SceneEvent gLunpaFortressEventsOther[]
static void Event_OuterPatrolThrowsPartyOut(void)
Raised when the outer rooms' patrol spots the leader: it throws the party out.
static void LunpaFortress_CheckFirstEntranceSentry(void)
Every frame past the entrance: either sentry who sees the uncloaked leader raises TRIGGER_SENTRIES_SP...
static s32 LunpaFortress_IsLeaderInGuardHorizontalSight(s32 actorId)
Whether the leader is within a row of the guard, up to six cells away.
@ RESCUE_MONSTER
@ RESCUE_MONSTER_PART
@ RESCUE_DONPA
@ RESCUE_HAMMET
@ RESCUE_DODONPA
struct ScenePlacement gLunpaFortressPlacements4[]
static void UNUSED LunpaFortress_TryCollectActorElevenItem(void)
static void Event_BlowAwayPassageCover(void)
Whirlwind on what hides the passage: it blows away and the passage opens.
static void UNUSED LunpaFortress_TryCollectActorTenItem(void)
#define PAIRED_PATROL_LAYER_ORIGIN_X
The paired patrol's layer origin across: 136 pixels, in 16.16 fixed point.
static void UNUSED LunpaFortress_TryCollectActorEightItem(void)
Unused: four items set out on actors 8 to 11, each taken once, with flags 0xf2a to 0xf2d.
static s32 LunpaFortress_IsGuardNearViewCenter(s32 actorId)
Whether the guard is on screen: within seven columns and five rows of the view's center.
static void Event_TalkToDonpa(void)
Donpa: asleep before the rescue.
static void Event_FightHallGuard(void)
Walking up to the hall guard: he challenges the party to a battle, and is gone after it.
@ RESCUE_ENTRANCE_AFTER_BATTLE
@ GUARD_ROOM_ENTRANCE_AFTER_BATTLE
u32 gLunpaFortressExits3And4[]
static void Event_FindHammet(void)
Walking into Hammet's cell.
@ EXIT_THROWN_OUT
static void Event_SentriesThrowPartyOut(void)
Walking between the sentries, or seen by them: the party is sent back to the gate below the fortress.
static void Event_TalkToStartledResident(void)
A resident of the outer rooms, startled the first time, asks whether the party sneaked in in search o...
static void LunpaFortress_CheckOuterDoorApproach(void)
Every frame in the outer rooms: walking into the second cell door's column with the Cell Key unlocks ...
static void LunpaFortress_OpenSecondSwitchPassage(void)
The second switch's passage opens.
static void Event_BlowAwayFirstSwitchCover(void)
Whirlwind on what hides the first switch: it blows away.
static void LunpaFortress_ActivateLeverTrap(void)
Dodonpa's lever: the room shakes, the floor opens and everyone startles.
static void Event_UnlockOuterDoor(void)
Facing an outer room cell door with the Cell Key: it opens with a rumble.
static void LunpaFortress_PlaceThreeBeatenGuards(void)
The three guards lie beaten where they fought.
static void LunpaFortress_ActOutWhosThereDialogue(s32 actorId)
A guard asks who is there. "Huh? Who's that?".
static void LunpaFortress_GuardThrowsPartyOut(s32 actorId)
A guard who caught the party sends it back to the gate below the fortress.
static void Event_TalkToSentry(void)
The second sentry looks around, hearing someone he cannot see.
static void Event_PatrolPairThrowsPartyOut(void)
Raised when the patrolling pair spots the leader: the first stops and stares, and the second throws t...
static void Event_DjinniJoins(void)
Talking to the Djinni in Donpa's room: it joins the party.
static void LunpaFortress_RevealMonster(void)
The camera finds the monster Dodonpa has freed; it lumbers forward.
static void Event_TalkToAttendant(void)
Donpa's attendant.
#define PATROL_ITEM_REQUEST(work)
@ CLOAK_NEAR_GUARD
static void LunpaFortress_OpenRescueRoomDoor(s32 doorIndex)
Draws a rescue room cell door open.
struct ScenePlacement gLunpaFortressPlacements2[]
static void Event_TalkToBeatenGuardC(void)
The third of the beaten guards begs. "Owww! Hey! Don't hurt me again...".
struct ScenePlacement gLunpaFortressPlacementsOther[]
static void LunpaFortress_OpenOuterDoor(s32 doorIndex)
Draws an outer room cell door open and lets the party through.
@ COLUMN_ROOM_SECOND_SWITCH_COVER
@ COLUMN_ROOM_COLUMN
@ COLUMN_ROOM_FIRST_SWITCH_COVER
@ COLUMN_ROOM_PASSAGE_COVER
u32 gOuterDoorCells[]
struct SceneEvent gLunpaFortressEvents2[]
static void Event_AskWhereDodonpaIs(void)
Asks where Dodonpa is. "Do you know where Dodonpa is?".
static void UNUSED LunpaFortress_DoNothingC(void)
static void LunpaFortress_OpenGuardRoomDoor(s32 doorIndex)
Draws a guard room cell door open.
static void Event_ReadSentrysThoughts(void)
Mind Read on the second sentry: one of eight thoughts, chosen at random when the map was entered; in ...
static void Event_TakeCellKey(void)
Catch on the Cell Key hanging in the guard rooms, or talking to it: the leader steps up and takes it.
static void Event_SearchSealedDoor(void)
Searching the door no key opens.
static void UNUSED LunpaFortress_FirstPatrolThrowsPartyOut(void)
Unused: the first patrol asks who the party is and sends them out.
static void Event_SearchLockedDoor(void)
Searching a cell door without the Cell Key: it stays shut.
static void Event_ReadJailedDodonpasThoughts(void)
Mind Read on the jailed Dodonpa.
static void LunpaFortress_CheckSecondEntranceSentry(void)
The second sentry, as the first.
static void Event_EntranceGuardThrowsPartyOut(void)
Walking past the entrance guard, or seen by him: the party is sent back to the gate below the fortres...
struct ScenePlacement gLunpaFortressPlacementsWestLunpaCave[]
static void UNUSED LunpaFortress_DoNothingD(void)
static void LunpaFortress_UpdatePairedGuardDetection(void)
Every frame in the guard rooms: the pair patrolling the west corridor.
static void Event_DonpaJudgesDodonpa(void)
After the battle: the monster has fallen on Dodonpa.
static void Event_MoveColumn(void)
Move on the column: once it is past row 22, over its hole, the room shakes and it sinks.
static s32 LunpaFortress_IsLeaderInPatrolSafeZone(void)
Where the patrolling pair cannot see the leader: the west end of their corridor and the cells below i...
static void Event_ColumnSinks(void)
The column, pushed onto its hole, slides in and sinks.
static s32 LunpaFortress_IsLeaderNearGuard(s32 actorId)
Whether the leader is within four cells, walking, of the cell below the guard.
The map layers' scroll work and the background scroll values.
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_SYNC
Wait for arrival.
Definition objcmd.h:17
#define SC_FOREVER
Definition objcmd.h:14
#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_ACCEL
Definition objcmd.h:68
@ SW_SPEED
Definition objcmd.h:67
#define ACTOR_ACTION_IDLE
Scene numbers, named after their places.
char SceneId_WestLunpaCave
char SceneId_LunpaFortress3
char SceneId_LunpaFortress2
char SceneId_LunpaFortress1
char SceneId_LunpaFortress4
Song and sound effect ids, indices into gSound_SongTable.
#define SE_215
Definition songs.h:210
#define SE_144
Definition songs.h:137
#define SE_GATE_MOVE
Definition songs.h:152
#define SE_MENU_CANCEL
Definition songs.h:106
#define MUS_008
Definition songs.h:18
#define SE_155
Definition songs.h:150
#define SE_288
Definition songs.h:281
#define MUS_052
Definition songs.h:56
#define SE_125
Definition songs.h:118
#define MUS_061
Definition songs.h:65
#define SE_226
Definition songs.h:221
#define MUS_017
Definition songs.h:27
#define SE_188
Definition songs.h:183
#define SE_141
Definition songs.h:134
#define MUS_019
Definition songs.h:29
#define SE_145
Definition songs.h:138
#define MUS_060
Definition songs.h:64
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_ActorShowEmote()
void Engine_TaskWait()
#define NULL
Definition bilibin.h:6
@ REVEAL_SHOWN
Definition lunpa.h:143
@ REVEAL_FADED
Definition lunpa.h:143
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 touchedTrigger
the step event a touch or exit event answers
Definition event_work.h:26
s16 psynergyRequest
a field Psynergy to use, as owner << 10 | Psynergy
Definition event_work.h:33
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
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
u8 paused
nonzero skips its script and motion, not its update
Definition field_obj.h:93
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
Definition field_obj.h:51
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition field_obj.h:39
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition field_obj.h:40
u8 collisionFlags
bits: 7 refuses to move into a solid object | 4 nearer for Psynergy targets | 3 never a talk or Psyne...
Definition field_obj.h:91
Full event work allocated by Field_RunScene (heap slot 27).
s16 cloaked
1 under Cloak, which prevents battles
Definition game_state.h:114
s16 entrance
Definition game_state.h:37
One background layer of the field map: its scroll position, origin, parallax against the view,...
Definition map_scroll.h:14
s32 speedY
16.16 fixed-point pixels per frame
Definition map_scroll.h:18
s32 phaseY
16.16 fixed-point pixels
Definition map_scroll.h:19
The field map's work: the followed position, screen shake, tile animations, blend script,...
Definition map_scroll.h:27
struct MapLayerScroll layers[3]
BG3, BG2 and BG1, in that order.
Definition map_scroll.h:49
A scene entrance: where and facing which way the party arrives, and the camera's bounds there (-1 for...
Definition field_scene.h:54
A scene event: its kind and detail, the trigger it answers, its condition and its value (a message or...
An actor a scene places: its sprite, the condition for placing it, how it behaves,...
Definition field_scene.h:81
A scene's exit region: the box that, while its condition holds, takes the party leader out through it...
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
Values that differ by patch level or language, chosen once for their code.
#define LUNPA_RETURN_TRANSITION_VARIANT
Definition tbs_edition.h:12
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
#define UNUSED
Definition types.h:22
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels