Alchemy
Loading...
Searching...
No Matches

bilibin.c

Go to the documentation of this file.
1/// @file
2/// Bilibin's village, river crossing and raised warehouse approach.
3/// Town dialogue changes with the tree curse; the river route includes a rescue
4/// and Jill's reward for helping the stranded villager.
5
6#include "game_state.h"
7#include "flags.h"
8#include "scene_ids.h"
9#include "unit/import.h"
10#include "unit/scene/bilibin.h"
11#include "unit/object/object.h"
13#include "unit/field/field.h"
15#include "battle.h"
16#include "debug.h"
17#include "field.h"
18#include "game.h"
19#include "graphics.h"
20#include "menu.h"
21#include "minigame.h"
22#include "sound.h"
23#include "system.h"
24#include "bilibin.h"
25#include "types.h"
26#include "field_event.h"
27#include "field_service.h"
28#include "field_scene.h"
29#include "call.h"
30#include "text/msg_ids.h"
31#include "ability_ids.h"
32#include "objcmd.h"
33#include "facing_object.h"
34#include "field_obj.h"
35#include "songs.h"
36#include "item_ids.h"
37
38static void Bilibin_RestoreVillageActors(void);
39static void Bilibin_UpdateVillageBlockCells(void);
40static void Bilibin_RestoreRiverActors(void);
41static void Bilibin_UpdateRiverBlockCells(void);
42static void Bilibin_RestoreRaisedEntrance(void);
43static void Bilibin_UpdateRiverEffect(void);
44static void Bilibin_SpawnRiverEffect(struct FieldActor *actor);
45static void Bilibin_UpdateRaisedBlockCells(void);
46
47/// Actors of the village (Bilibin1), numbered from its placement rows.
48enum {
49 TREE_MAN = 9, ///< the cursed traveler, a tree at the village entrance
50 VILLAGE_BLOCK = 20, ///< the block moved with Move
51 FORMER_TREE_MAN = 21 ///< the same man once the curse is lifted
52};
53
54/// Actors of the river south of the village (Bilibin3).
55enum {
57 JILL_TREE = 11, ///< Jill as a tree, about to be swept downstream
58 /// Jill's two friends. With her they were the "Gang of Three".
61 JILL = 14
62};
63
64/// Actors of the warehouse approach (Bilibin2).
65enum { RAISED_BLOCK = 8, GUST = 9 };
66
67/// Counts frames between the river effects, one every 30 frames.
70};
71
73
75
77 s16 scene = gGameState.scene;
78
79 if (scene == (s32)&SceneId_Bilibin1) {
80 return gBilibinEntrances1;
81 }
82 if (scene == (s32)&SceneId_Bilibin3) {
83 return gBilibinEntrances3;
84 }
85 if (scene == (s32)&SceneId_Bilibin2) {
86 return gBilibinEntrances2;
87 }
88 return (const struct SceneEntrance *)gBilibinEntrancesOther;
89}
90
91/// Only the raised approach supplies exit-region boxes.
92const struct SceneRegion *Bilibin_GetRegions(void) {
94 return (const struct SceneRegion *)gBilibinRegions2;
95 }
96 return 0;
97}
98
99/// Returns the packed exit destinations shared by the three maps.
100const u32 *Bilibin_GetExits(void) { return gBilibinExits; }
101
102/// Gust, Jupiter Djinni 0, joins the party on the warehouse approach.
104
105/// Selects the village, river or raised-approach actors.
107 s16 scene = gGameState.scene;
108
109 if (scene == (s32)&SceneId_Bilibin1) {
110 return gBilibinPlacements1;
111 }
112 if (scene == (s32)&SceneId_Bilibin3) {
113 return gBilibinPlacements3;
114 }
115 if (scene == (s32)&SceneId_Bilibin2) {
116 return gBilibinPlacements2;
117 }
119}
120
121/// Reads the two-part description of the deep well.
122static void Event_InspectWell(void) {
124 Engine_MessageShowCentered(MsgFieldPeeredWell, 1);
125 Engine_MessageShowCentered(MsgBilibinBottomNotVisibleLooksVery, 1);
127}
128
129const struct SceneEvent *Bilibin_GetEvents(void) {
130 s16 scene = gGameState.scene;
131
132 if (scene == (s32)&SceneId_Bilibin1) {
133 return gBilibinEvents1;
134 }
135 if (scene == (s32)&SceneId_Bilibin3) {
136 return gBilibinEvents3;
137 }
138 if (scene == (s32)&SceneId_Bilibin2) {
139 return gBilibinEvents2;
140 }
141 return gBilibinEventsOther;
142}
143
144/// Reads the sign restricting entry without permission.
147 Engine_MessageShowCentered(MsgBilibinAreaOffLimitsThoseWithout, 1);
149}
150
151/// Reads McCoy's warning on the hidden warehouse.
152static void Event_ReadWarehouseSign(void) {
154 Engine_MessageShowCentered(MsgBilibinMccoysHiddenWarehouseDoNot, 1);
156}
157
158/// Describes the human shape shared by the river's transformed villagers.
161 Engine_MessageShowCentered(MsgBilibinThereTreeLooksLikePerson, 1);
163}
164
165/// The tree at the village entrance almost looks like a man; looked at again,
166/// like a living person. 0x301 remembers the first look while in the village.
167static void Event_ExamineTreeMan(void) {
169 Engine_EventSetMessage(MsgBilibinItsTreeButAlmostLooks);
170 if (GameFlag_IsSet(0x301) != 0) {
172 }
174 GameFlag_Set(0x301);
176}
177
178/// Asks whether the party saw the strange tree at the entrance.
179static void Event_AskAboutEntranceTree(void) {
181 Engine_EventSetMessage(MsgBilibinDidSeeTreeAtEntrance);
184}
185
186/// Asks whether the party tried the route southeast from Bilibin.
189 Engine_EventSetMessage(MsgBilibinHaveTriedHeadingSoutheastFrom);
192}
193
194/// Once the curse is lifted, the man who was the entrance tree asks whether the
195/// party can believe it.
196static void Event_AskAboutBeingATree(void) {
198 Engine_EventSetMessage(MsgBilibinWasTurnedIntoTreeFor);
201}
202
203/// Asks whether the party are the three warriors who broke the curse.
206 Engine_EventSetMessage(MsgBilibinCurseWasBrokenThanksEfforts);
209}
210
211/// Asks whether the party has visited Imil to the north.
212static void Event_AskAboutImil(void) {
214 Engine_EventSetMessage(MsgBilibinHaveEverBeenVillageImil);
217}
218
219/// Walking into a door: everyone stops, the door opens and the leader walks
220/// through it. Doors 3 to 8 lead into the houses and shops, door 9 into the
221/// Sanctum, whose door sounds and is stepped through differently.
222static void Event_OpenDoorAndLeave(void) {
223
224 u32 actorSlot;
225 struct FieldActor *actor;
226 s32 exitIndex;
227 u8 *originBytes;
228 s32 originOffset;
229 s32 rowOffset;
230 s32 column;
231 s32 row;
232 struct EventWork *work;
233
234 work = gEventWork;
236 // Freeze placed actors before the exit cells start animating.
237 for (actorSlot = ACTOR_FIRST_PLACED; actorSlot < 66; actorSlot++) {
238 actor = Object_GetById(actorSlot);
239 if (actor != 0) {
240 actor->motionFlags = 0;
241 }
242 }
243 exitIndex = (((u16)work->touchedTrigger - 3) << 16) >> 16;
244 if (exitIndex == 6) {
246 } else {
248 }
249 // Each door has its cell and the steps that draw it opening.
250 originOffset = exitIndex << 2;
251 originBytes = (u8 *)gBilibin_DoorCells;
252 column = *(s16 *)(originBytes + originOffset);
253 rowOffset = originOffset + 2;
254 row = *(s16 *)(originBytes + rowOffset);
255 Engine_MapAnimateCells(gBilibin_DoorSteps[exitIndex], column, row);
256 Actor_SetSpeed(ACTOR_PARTY_LEADER, 0x8000, 0x4000);
259 if (exitIndex == 6) {
262 } else {
264 }
265 if (exitIndex == 4) {
267 } else {
269 }
271 Engine_EventRequestExit(exitIndex + 3);
273}
274
275/// Move on Jill, a tree caught in the river: from cell column 6, by the bank,
276/// the leader pulls her ashore in three tugs, and she thanks the party for
277/// saving her from being washed downstream.
278static void Event_PullJillFromRiver(void) {
279 struct FieldActor *leader;
280 struct FieldActor *jillTree;
281
283 jillTree = Object_GetById(JILL_TREE);
284 if ((jillTree->x.fixed >> 20) == 6) {
290 Actor_SetSpeed(JILL_TREE, PIXELS(1) / 5, PIXELS(1) / 10);
292 jillTree->motionFlags = 0;
293 // Each tug: the leader faces about, strains and draws her in, then steps
294 // on.
295 leader->scaleX = -0x10000;
299 leader->scaleX = 0x10000;
302 leader->scaleX = -0x10000;
306 leader->scaleX = 0x10000;
309 leader->scaleX = -0x10000;
313 leader->scaleX = 0x10000;
320 Engine_TaskWait(10);
321 Engine_EventSetMessage(MsgBilibinThankSavedMeFromBeing);
324 Engine_TaskWait(10);
327 }
328}
329
330/// Checks the blocked direction before allowing another movement step.
332
333/// Back on the riverbank once the curse is lifted, Jill and her friends
334/// recognize the party, and she gives the leader a Hard Nut in thanks.
335/// "Remember me? I was that tree!"
336static void Event_JillGivesHardNut(void) {
337 struct FieldActor *leader;
338 struct FieldActor *westMember;
339
343 return;
344
346 // The camera moves over to the three; the friend nearer the leader speaks
347 // first.
348 Camera_SetSpeed(PIXELS(12) / 5, PIXELS(3) / 10);
349 Camera_MoveTo(PIXELS(263), -1, PIXELS(173), 1);
351 westMember = Actor_Get(GANG_MEMBER_WEST);
352 if (westMember->x.fixed > leader->x.fixed) {
355 Engine_EventSetMessage(MsgBilibinYoureGuy);
358 } else {
361 Engine_EventSetMessage(MsgBilibinYoureGuy);
364 }
388 Actor_SetSpeed(JILL, PIXELS(3) / 5, PIXELS(3) / 10);
390 Actor_WalkToAndWait(JILL, 266, 172);
396 // Show the named gift before adding it to the party's inventory.
397 Engine_MessageShowCentered(MsgBilibinJillGaveIsaacSpecialGift, 1);
404 Actor_SetSpeed(JILL, PIXELS(1), PIXELS(1) / 2);
406 Actor_WalkToAndWait(JILL, 262, 156);
408 {
409 struct FieldActor *jill = Actor_Get(JILL);
411
413 }
420 // From now on the three turn to face the leader wherever he goes.
432}
433
434/// Restores the current map's actors, collision cells and opening transition.
439 } else if (gGameState.scene == (s32)&SceneId_Bilibin3) {
442 } else if (gGameState.scene == (s32)&SceneId_Bilibin2) {
444 }
445 return 0;
446}
447
448/// Restores the village population and entrance-dependent actor positions.
450
451 struct FieldActor *actor;
452 s16 entrance;
453
458 } else {
459 actor = Actor_Get(TREE_MAN);
462 }
463 // Apply arrival-specific changes after restoring the population.
464 actor = Actor_Get(8);
465 actor->scaleY = 0x18000;
466 entrance = gGameState.entrance;
467 if (entrance == 10) {
468 Actor_SetPosition(8, 0, 0);
469 } else if (entrance == 9) {
471 }
473 entrance = gGameState.entrance;
474 if (entrance == 11) {
476 }
477 }
481 GameFlag_Set(0x304);
482 }
483}
484
485/// Updates collision cells around the movable block and moves an overlapping
486/// leader clear.
488 s32 leaderRow;
489 s32 leaderColumn;
490 struct FieldActor *leader;
491 struct FieldActor *block;
492 s32 blockX;
493 s32 blockRow;
494
497 blockRow = block->z.fixed >> 20;
498 leaderColumn = (leader->x.fixed >> 20);
499 leaderRow = (leader->z.fixed >> 20);
500 blockX = block->x.fixed;
501 // Repaint the block's lane before clearing the cells it currently occupies.
502 Map_CopyCellAttributes(15, 11, 3, 1, 15, 12);
503 Map_CopyCellAttributes(15, 11, 3, 1, 15, 13);
504 Map_CopyCellAttributes(15, 11, 3, 1, 15, 14);
505 Map_CopyCellAttributes(1, 0, 1, 1, (blockX >> 20), blockRow);
506 if ((blockX >> 20) != 16 || blockRow != 13) {
507 Map_CopyCellAttributes(0, 0, 1, 1, 16, 13);
508 }
509 // The block may have moved onto the leader while this event was running.
510 if (leaderColumn == 16) {
511 if (leaderRow == 13) {
516 if (blockRow == 13) {
519 } else {
522 }
524 }
525 }
526}
527
528/// Sets up the river: before the curse is lifted, Jill and her friends are
529/// trees here; afterwards they are people again on the bank.
530static void Bilibin_RestoreRiverActors(void) {
531 struct FieldActor *jillTree;
532 s32 populationState;
533 struct FieldActor *fallenTree;
534 struct FieldActor *actor;
535 s32 crossingState;
536
537 fallenTree = Object_GetById(10);
538 jillTree = Object_GetById(JILL_TREE);
539 actor = Actor_Get(RIVER_BLOCK);
541 populationState = GameFlag_IsSet(FLAG_KOLIMA_CURSE_LIFTED);
542 if (populationState != 0) {
543 // The trees are gone; the bank is mended where one had fallen.
544 Actor_SetPosition(9, 0, 0);
545 Actor_SetPosition(10, 0, 0);
547 Map_CopyCellsTo(56, 15, 40, 15, 1, 2);
548 Map_CopyCellAttributes(26, 15, 1, 3, 10, 15);
554 0);
555 }
556 } else {
559 }
560 } else {
563 Actor_SetPosition(JILL, 0, 0);
564 actor = Actor_Get(9);
566 actor = Actor_Get(10);
568 actor = Actor_Get(JILL_TREE);
570 fallenTree->motionFlags = populationState;
571 // Once 0x881 is set ("They crossed the river after pushing us down"), a
572 // tree lies on its side at the crossing and Jill is in the water, or on the
573 // bank where she was pulled ashore.
575 if (crossingState != 0) {
579 Actor_SetPosition(16, PIXELS(142), PIXELS(156));
580 actor = Actor_Get(16);
582 Actor_SetPosition(10, PIXELS(142), PIXELS(156));
583 fallenTree->sprite->rotation = 0x4000;
584 fallenTree->y.fixed += -0x80000;
587 } else {
590 jillTree->collisionFlags |= 4;
591 }
592 } else {
593 fallenTree->y.fixed = PIXELS(32);
594 jillTree->motionFlags = crossingState;
595 jillTree->y.fixed = PIXELS(48);
596 }
597 }
599}
600
601/// Restores ten river cells, then clears the movable block's current cell.
603 struct FieldActor *actor;
604 s32 blockColumn;
605 s32 blockRow;
606 u32 cellOffset;
607
609 blockColumn = actor->x.fixed >> 20;
610 blockRow = actor->z.fixed >> 20;
611
612 // The packed table stores ten byte-sized column/row pairs.
613 for (cellOffset = 0; cellOffset < 20; cellOffset += 2) {
614 s32 column = ((u8 *)gBilibin_RiverBlockCells)[cellOffset];
615 s32 row = ((u8 *)gBilibin_RiverBlockCells)[cellOffset + 1];
616 Map_CopyCellAttributes(1, 0, 1, 1, column, row);
617 }
618
619 Map_CopyCellAttributes(0, 0, 1, 1, blockColumn, blockRow);
620}
621
622/// Restores the block cells and starts the raised arrivals above floor height.
624 struct FieldActor *leader;
625
628 if (gGameState.entrance == 3 || gGameState.entrance == 4) {
632 leader->y.fixed = PIXELS(16);
633 Engine_CameraMoveTo(leader->x.fixed, leader->y.fixed, leader->z.fixed, 0);
637 }
638 }
639}
640
642
643/// Pushing a block: it slides one cell ahead with the leader behind it, if the
644/// cell is free.
645static void Event_PushBlock(void) {
646 struct FieldActor *leader;
647 struct FieldActor *block;
648 u32 direction;
649 struct FieldPosition destination;
650
652 direction = leader->facing >> 12;
653 block = SceneActor_FindActorAtCell(
654 (leader->x.part.pixel + (gBilibin_FacingCellSteps[direction] >> 16)) >> 4,
655 (leader->z.part.pixel + (s16)gBilibin_FacingCellSteps[direction]) >> 4);
656 if (block != NULL) {
657 block->terrainId = 2;
658 destination.x =
659 block->x.fixed + (gBilibin_FacingCellSteps[direction] & -0x10000);
660 destination.y = block->y.fixed;
661 destination.z =
662 block->z.fixed + (gBilibin_FacingCellSteps[direction] << 16);
663 if (FieldObject_CheckMovementCollision(block, &destination) <= 0) {
664 // The leader leans on the block, then both move together.
665 Object_SetMode(leader, 8);
666 Engine_TaskWait(15);
668 block->speed = PIXELS(1) / 5;
669 block->acceleration = PIXELS(1) / 5;
670 Engine_ObjectSetPosition(block, destination.x, destination.y,
671 destination.z);
672 leader->speed = PIXELS(1) / 5;
673 leader->acceleration = PIXELS(1) / 5;
674 Engine_ObjectSetPosition(leader, destination.x, destination.y,
675 destination.z);
677 block->x.fixed = destination.x;
678 block->z.fixed = destination.z;
679 block->velocityX = 0;
680 block->velocityZ = 0;
681 Object_SetMode(leader, 1);
682 // Each map derives its collision cells from this same moved actor.
685 else if (gGameState.scene == (s32)&SceneId_Bilibin1)
687 else if (gGameState.scene == (s32)&SceneId_Bilibin2)
689 }
690 }
691}
692
693/// Runs every frame in the river: while the controlled actor is west of x 142
694/// and below 8 pixels high, an effect appears at it every thirty frames.
695static void Bilibin_UpdateRiverEffect(void) {
696 struct FieldActor *actor;
697
699 if (actor->x.fixed < PIXELS(142)) {
700 if (actor->y.fixed < PIXELS(8)) {
705 } else {
707 }
708 }
709}
710
711/// Spawns the semi-transparent effect, which frees itself after thirty frames.
712static void Bilibin_SpawnRiverEffect(struct FieldActor *actor) {
713 struct FieldActor *effect;
714 struct AnimationObject *sprite;
715
716 effect =
717 Engine_ObjectCreate(24, actor->x.fixed, actor->y.fixed, actor->z.fixed);
718 if (effect == NULL)
719 return;
720
721 sprite = effect->sprite;
723 effect->motionFlags = 0;
724 effect->terrainId = 1;
725 effect->priorityFlags = 2;
726 if (sprite == NULL)
727 return;
728
730 sprite->flags = 0;
731 sprite->image.objectMode = 1;
732 sprite->image.priority = 3;
733}
734
735/// Updates the two passage cells according to the movable block's current row.
737 struct FieldActor *block;
738
739 block = Actor_Get(RAISED_BLOCK);
740 if (block == NULL)
741 return;
742
743 if (block->z.fixed >> 20 == 6)
744 Map_CopyCellAttributes(2, 0, 1, 1, 14, 6);
745 else
746 Map_CopyCellAttributes(0, 0, 1, 1, 14, 6);
747
748 if (block->z.fixed >> 20 == 9)
749 Map_CopyCellAttributes(2, 0, 1, 1, 14, 9);
750 else
751 Map_CopyCellAttributes(1, 0, 1, 1, 14, 9);
752}
753
755 SC_CALL(Scene_TurnTowardTarget),
757};
758
760 MAP_CELL_STEP(0, 65535, 168, 0, 168),
761 MAP_CELL_STEP(16384, 0, 65535, 65535, 65535),
763};
764
766 {1, CONDITION_ALWAYS, 240, 0, 472, FACING_NORTH, 0, -1, -1, -1, -1, 0},
767 {2, CONDITION_ALWAYS, 224, 0, 88, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
768 {3, CONDITION_ALWAYS, 376, 0, 360, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
769 {4, CONDITION_ALWAYS, 200, 0, 328, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
770 {5, CONDITION_ALWAYS, 104, 0, 344, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
771 {6, CONDITION_ALWAYS, 168, 0, 216, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
772 {7, CONDITION_ALWAYS, 72, 0, 216, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
773 {8, CONDITION_ALWAYS, 296, 0, 184, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
774 {9, CONDITION_ALWAYS, 400, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
775 {10, CONDITION_ALWAYS, 40, 0, 152, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
776 {11, CONDITION_ALWAYS, 264, 0, 200, FACING_NORTH, 0, -1, -1, -1, -1, 0},
778};
779
781 {0, CONDITION_ALWAYS, 168, 0, 168, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
782 {1, CONDITION_ALWAYS, 56, 0, 376, FACING_EAST, 0, 16, 16, 400, 400, 0},
783 {2, CONDITION_ALWAYS, 376, 0, 184, FACING_WEST, 0, 16, 16, 400, 400, 0},
785};
786
788 {0, CONDITION_ALWAYS, 232, 0, 144, FACING_SOUTH, 0, -1, -1, -1, -1, 0},
789 {1, CONDITION_ALWAYS, 120, 0, 408, FACING_NORTH, 0, 0, 288, 240, 448, 0},
790 {2, CONDITION_ALWAYS, 120, 0, 384, FACING_SOUTH, 0, 0, 288, 240, 448, 0},
791 {3, CONDITION_ALWAYS, 72, 4, 128, FACING_NORTH, 0, 32, 32, 384, 304, 0},
792 {4, CONDITION_ALWAYS, 296, 4, 224, FACING_NORTH, 0, 32, 32, 384, 304, 0},
794};
795
796// clang-format off
798 66, 26, 128, 78, 38, 140, -1, 3,
799 290, 26, 224, 302, 38, 236, -1, 4,
800 -1, 0, 0, 0, 0, 0, 0, 0,
801};
802
804 SCENE_EXITS(30),
805 SCENE_EXIT(1, 2, 5),
806 SCENE_EXIT(2, 34, 1),
807 SCENE_EXIT(3, 31, 6),
808 SCENE_EXIT(4, 31, 1),
809 SCENE_EXIT(5, 31, 2),
810 SCENE_EXIT(6, 31, 3),
811 SCENE_EXIT(7, 31, 5),
812 SCENE_EXIT(8, 31, 4),
813 SCENE_EXIT(9, 9, 35),
814 SCENE_EXIT(10, 32, 1),
815 SCENE_EXIT(11, 32, 4),
816 SCENE_EXIT(0, 32, 0),
817 SCENE_EXIT(1, 30, 10),
818 SCENE_EXIT(2, 32, 3),
819 SCENE_EXIT(3, 32, 2),
820 SCENE_EXIT(4, 30, 11),
821 SCENE_EXIT(0, 35, 0),
822 SCENE_EXIT(1, 2, 6),
823 SCENE_EXIT(2, 2, 47),
825};
826
828 { SCENE_TABLE_END },
829};
830
833 PIXELS(40), 0, PIXELS(140), FACING_SOUTH, TALK_KEEP_FACING, 0 },
835 PIXELS(256), 0, PIXELS(440), FACING_SOUTH, TALK_KEEP_FACING, 0 },
837 PIXELS(264), 0, PIXELS(328), FACING_SOUTHWEST, TALK_FACE_PARTY, 0 },
841 PIXELS(176), 0, PIXELS(328), FACING_EAST, TALK_FACE_PARTY, 0 },
843 PIXELS(128), 0, PIXELS(224), FACING_EAST, TALK_FACE_PARTY, 0 },
849 PIXELS(208), 0, PIXELS(200), FACING_SOUTH, TALK_FACE_PARTY, 0 },
851 PIXELS(192), 0, PIXELS(208), FACING_SOUTH, TALK_FACE_PARTY, 0 },
853 PIXELS(232), 0, PIXELS(296), FACING_SOUTHWEST, TALK_FACE_PARTY, 0 },
856 { 0xf3, CONDITION_ALWAYS, 7,
857 PIXELS(264), 0, PIXELS(216), FACING_SOUTH, TALK_KEEP_FACING, 0 },
859 PIXELS(264), 0, PIXELS(432), FACING_SOUTH, TALK_FACE_PARTY, 0 },
860 { SCENE_TABLE_END },
861};
862
864 { 0xf1, CONDITION_ALWAYS, 7,
865 PIXELS(136), 0, PIXELS(300), FACING_SOUTH, TALK_KEEP_FACING, 0 },
873 PIXELS(282), 0, PIXELS(170), FACING_WEST + FACING_STEP, TALK_FACE_PARTY, 0 },
877 PIXELS(262), 0, PIXELS(156), FACING_WEST + FACING_STEP, TALK_FACE_PARTY, 0 },
878 { 0x17, CONDITION_ALWAYS, 7,
879 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
880 { 0x16, CONDITION_ALWAYS, 7,
881 0, 0, 0, FACING_SOUTH, TALK_KEEP_FACING, 0 },
882 { SCENE_TABLE_END },
883};
884
887 PIXELS(232), 0, PIXELS(100), FACING_SOUTH, TALK_KEEP_FACING, 0 },
889 PIXELS(328), 0, PIXELS(152), FACING_SOUTH, TALK_FACE_PARTY, 0 },
890 { SCENE_TABLE_END },
891};
892
895};
896
898 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
899 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
900 { EVENT_EXIT, 10, CONDITION_ALWAYS, 10 },
901 { EVENT_EXIT, 11, CONDITION_ALWAYS, 11 },
911 { EVENT_TALK, 10, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinWelcomeToBilibinPleaseJustIgnore) },
912 { EVENT_TALK, 10, CONDITION_ALWAYS, MSGNO(MsgBilibinWelcomeToBilibinWellForgetThat) },
913 { EVENT_TALK, 11, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinIHearALargeGroupCrossed) },
914 { EVENT_TALK, 11, CONDITION_ALWAYS, MSGNO(MsgBilibinIfYoureTalkingAboutTheTravelers) },
916 { EVENT_TALK, 12, CONDITION_ALWAYS, MSGNO(MsgBilibinYoureWonderingAboutTheTreeNear) },
917 { EVENT_TALK, 13, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinLordMccoyHasBeenQuiteFrightened) },
918 { EVENT_TALK, 13, CONDITION_ALWAYS, MSGNO(MsgBilibinISawLordMccoyTheChief) },
920 { EVENT_TALK, 14, CONDITION_ALWAYS, MSGNO(MsgBilibinIHearTheBarricadeGateThat) },
921 { EVENT_TALK, 15, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinTheRoadToKolimaIsBlocked) },
922 { EVENT_TALK, 15, CONDITION_ALWAYS, MSGNO(MsgBilibinThoseThreeKidsVanishedDuringAll) },
923 { EVENT_TALK, 16, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinEverSinceThatManTurnedInto) },
925 { EVENT_TALK, 17, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinIsItTrueThatAMountain) },
926 { EVENT_TALK, 17, CONDITION_ALWAYS, MSGNO(MsgBilibinLordMccoysMenSaidTheySaw) },
927 { EVENT_TALK, 18, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinTheresATowerAtTheTip) },
929 { EVENT_TALK, 19, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinSomethingChangedInTheEruptionNow) },
930 { EVENT_TALK, 19, CONDITION_ALWAYS, MSGNO(MsgBilibinTheEruptionOnTheOtherSide) },
931 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), TREE_MAN, CONDITION_ALWAYS, MSGNO(MsgBilibinHelpMeSomebody) },
932 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FORMER_TREE_MAN, CONDITION_ALWAYS, MSGNO(MsgBilibinINeverWantToBeTurned) },
933 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinYouGuysAreSoUnluckyArriving) },
934 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgBilibinNotManyLumberjacksAreWillingTo) },
935 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinYouMustBeMadItsAlmost) },
936 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 11, CONDITION_ALWAYS, MSGNO(MsgBilibinOneOfTheTwoPeopleThat) },
937 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinWeEndedUpLikeThisBecause) },
938 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 12, CONDITION_ALWAYS, MSGNO(MsgBilibinThatGuyMightTurnIntoA) },
939 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinEveryoneGetsWorriedWhenTownLeaders) },
940 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 13, CONDITION_ALWAYS, MSGNO(MsgBilibinLordMccoySeemsToBeHaving) },
941 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinWhereDidTheseKidsComeFrom) },
942 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 14, CONDITION_ALWAYS, MSGNO(MsgBilibinApparentlyJustAboutAnyoneCouldJust) },
943 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinNoOneWouldDareGoAfter) },
944 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 15, CONDITION_ALWAYS, MSGNO(MsgBilibinTheGangOfThreeHaTheyre) },
945 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinHeBeggedForHelpAsHe) },
946 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgBilibinImSureLordMccoyWillGive) },
947 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 17, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinIWantToSeeThatPretty) },
948 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 17, CONDITION_ALWAYS, MSGNO(MsgBilibinTheyMustBeReportingYourDeeds) },
949 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 18, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinOnlyGreatAdeptsCanEnterThe) },
950 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 18, CONDITION_ALWAYS, MSGNO(MsgBilibinIWantToShareWithYou) },
951 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 19, FLAG_KOLIMA_CURSE_LIFTED, MSGNO(MsgBilibinThatExplosionMustHaveBeenA) },
952 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 19, CONDITION_ALWAYS, MSGNO(MsgBilibinAsLongAsImOkayI) },
956 { SEARCH(SEARCH_JAR), 100, 0xf50, FIND_ITEM(ITEM_HERB) },
957 { SEARCH(SEARCH_JAR), 101, 0xf51, FIND_COINS(5) },
960};
961
963 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
964 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
969 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, IF_FLAG_SET(FLAG_SATUROS_BEATEN_AT_MERCURY), MSGNO(MsgBilibinTheyCrossedTheRiverAfterPushing) },
970 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 9, CONDITION_ALWAYS, MSGNO(MsgBilibinTheyreSoHeavy) },
971 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinShellBeSweptDownstreamIfShe) },
972 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 16, CONDITION_ALWAYS, MSGNO(MsgBilibinOhItLooksLikeSheIs) },
973 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinShellBeSweptDownstreamIfShe) },
974 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), 10, CONDITION_ALWAYS, MSGNO(MsgBilibinOhItLooksLikeSheIs) },
975 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), JILL_TREE, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinAhhhhPleaseAnyonePleaseHelp) },
976 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), JILL_TREE, CONDITION_ALWAYS, MSGNO(MsgBilibinThankSavedMeFromBeing) },
977 { EVENT_TALK, GANG_MEMBER_WEST, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinIHeardWeWereOnceCalled) },
978 { EVENT_TALK, GANG_MEMBER_WEST, CONDITION_ALWAYS, MSGNO(MsgBilibinItWasAwfulLuckBeingTurned) },
979 { EVENT_TALK, GANG_MEMBER_EAST, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinIfOnlyWeHadntTriedGetting) },
980 { EVENT_TALK, GANG_MEMBER_EAST, CONDITION_ALWAYS, MSGNO(MsgBilibinIReallyLikeThisSpotBy) },
981 { EVENT_TALK, JILL, CONDITION_ALWAYS, MSGNO(MsgBilibinIWillThinkOfYouWhenever) },
982 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GANG_MEMBER_WEST, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinWeWorkedSoHardIfOnly) },
983 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GANG_MEMBER_WEST, CONDITION_ALWAYS, MSGNO(MsgBilibinWhoseIdeaWasItToPick) },
984 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GANG_MEMBER_EAST, FLAG_BILIBIN_JILL_RESCUED, MSGNO(MsgBilibinWhatACruelWorldWeJust) },
985 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GANG_MEMBER_EAST, CONDITION_ALWAYS, MSGNO(MsgBilibinWellItWasntMyIdeaTo) },
986 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), JILL, CONDITION_ALWAYS, MSGNO(MsgBilibinThesePersimmonsAreJustLikeMy) },
988 { SEARCH(SEARCH_UNNAMED), 30, CONDITION_ALWAYS, FIND_MESSAGE(MSGNO(MsgFieldDoorTightlyLocked)) },
997};
998
1000 { EVENT_EXIT, 1, CONDITION_ALWAYS, 1 },
1001 { EVENT_EXIT, 2, CONDITION_ALWAYS, 2 },
1011 { SCENE_EVENTS_END },
1012};
1013
1015 MAP_CELL_STEP(37, 33, 4, 2, 5), MAP_CELL_STEP(33, 33, 4, 2, 5), MAP_CELL_STEPS_END,
1016};
1017
1019 MAP_CELL_STEP(35, 43, 2, 2, 5), MAP_CELL_STEP(33, 43, 2, 2, 5), MAP_CELL_STEPS_END,
1020};
1021
1023 MAP_CELL_STEP(35, 52, 2, 2, 5), MAP_CELL_STEP(33, 52, 2, 2, 5), MAP_CELL_STEPS_END,
1024};
1025
1027 MAP_CELL_STEP(35, 54, 2, 2, 5), MAP_CELL_STEP(33, 54, 2, 2, 5), MAP_CELL_STEPS_END,
1028};
1029
1031 MAP_CELL_STEP(35, 48, 2, 2, 5), MAP_CELL_STEP(33, 48, 2, 2, 5), MAP_CELL_STEPS_END,
1032};
1033
1035 MAP_CELL_STEP(35, 46, 2, 2, 5), MAP_CELL_STEP(33, 46, 2, 2, 5), MAP_CELL_STEPS_END,
1036};
1037
1039 MAP_CELL_STEP(35, 50, 2, 2, 5), MAP_CELL_STEP(33, 50, 2, 2, 5), MAP_CELL_STEPS_END,
1040};
1041
1050};
1051
1053 0x140036, 0x12002b, 0x130025, 0xb0029, 0xb0023, 0x90031, 0x60037,
1054};
1055
1057 0x12091208, 0x1308120a, 0x130a1309, 0x1409130b, 0x140b140a,
1058};
1059// clang-format on
1060
1061/// Pixel step by direction: X in the upper halfword, Z in the lower.
1062#define DIRECTION_STEP(dx, dz) (((dx) << 16) | ((dz) & 0xffff))
1063
1065 DIRECTION_STEP(16, 0), DIRECTION_STEP(16, 0), DIRECTION_STEP(16, 0),
1066 DIRECTION_STEP(0, 16), DIRECTION_STEP(0, 16), DIRECTION_STEP(0, 16),
1067 DIRECTION_STEP(0, 16), DIRECTION_STEP(-16, 0), DIRECTION_STEP(-16, 0),
1068 DIRECTION_STEP(-16, 0), DIRECTION_STEP(-16, 0), DIRECTION_STEP(0, -16),
1069 DIRECTION_STEP(0, -16), DIRECTION_STEP(0, -16), DIRECTION_STEP(0, -16),
1070 DIRECTION_STEP(16, 0),
1071};
1072
1074 SC_WAIT(30),
1075 SC_FREE,
1076};
Ability numbers, named from the English release.
@ ABILITY_MIND_READ
Definition ability_ids.h:16
@ ABILITY_MOVE
Definition ability_ids.h:15
@ ABILITY_WHIRLWIND
Definition ability_ids.h:13
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
#define DIRECTION_STEP(dx, dz)
Pixel step by direction: X in the upper halfword, Z in the lower.
s32 AnimationObjects_SelectAnimation(struct AnimationObject *sprite, s32 animation)
Starts animation flags & 0x7f on every layer of a sprite (bit 7 keeps each layer's place and timer),...
Definition animation.c:317
@ ELEMENT_JUPITER
Definition battle_unit.h:39
static void Event_PushBlock(void)
Pushing a block: it slides one cell ahead with the leader behind it, if the cell is free.
Definition bilibin.c:645
static void Event_CheckAhead(void)
Checks the blocked direction before allowing another movement step.
Definition bilibin.c:331
const struct SceneEvent * Bilibin_GetEvents(void)
Definition bilibin.c:129
@ GANG_MEMBER_EAST
Definition bilibin.c:60
@ JILL_TREE
Jill as a tree, about to be swept downstream.
Definition bilibin.c:57
@ JILL
Definition bilibin.c:61
@ RIVER_BLOCK
Definition bilibin.c:56
@ GANG_MEMBER_WEST
Jill's two friends. With her they were the "Gang of Three".
Definition bilibin.c:59
struct SceneEvent gBilibinEvents3[]
Definition bilibin.c:962
u16 gBilibin_DoorSteps1[]
Definition bilibin.c:1026
static void Bilibin_RestoreRiverActors(void)
Sets up the river: before the curse is lifted, Jill and her friends are trees here; afterwards they a...
Definition bilibin.c:530
u16 gBilibinEntrancesOther[]
Definition bilibin.c:759
static void Bilibin_RestoreVillageActors(void)
Restores the village population and entrance-dependent actor positions.
Definition bilibin.c:449
struct SceneEntrance gBilibinEntrances2[]
Definition bilibin.c:787
static void Event_AskAboutImil(void)
Asks whether the party has visited Imil to the north.
Definition bilibin.c:212
static void Event_AskAboutSoutheastRoute(void)
Asks whether the party tried the route southeast from Bilibin.
Definition bilibin.c:187
u16 gBilibin_DoorSteps5[]
Definition bilibin.c:1022
static void Bilibin_UpdateRaisedBlockCells(void)
Updates the two passage cells according to the movable block's current row.
Definition bilibin.c:736
struct SpawnCounter gBilibin_RiverEffectTimer
Definition bilibin.c:72
@ RAISED_BLOCK
Definition bilibin.c:65
@ GUST
Definition bilibin.c:65
s32 gBilibin_FacingCellSteps[]
Definition bilibin.c:1064
struct ScenePlacement gBilibinPlacements3[]
Definition bilibin.c:863
struct SceneEvent gBilibinEvents2[]
Definition bilibin.c:999
s32 gBilibin_TransientEffectScript[]
Definition bilibin.c:1073
static void Event_AskAboutBeingATree(void)
Once the curse is lifted, the man who was the entrance tree asks whether the party can believe it.
Definition bilibin.c:196
static void Event_PullJillFromRiver(void)
Move on Jill, a tree caught in the river: from cell column 6, by the bank, the leader pulls her ashor...
Definition bilibin.c:278
u32 gBilibin_DoorCells[]
Definition bilibin.c:1052
static void Event_ExamineTreeMan(void)
The tree at the village entrance almost looks like a man; looked at again, like a living person.
Definition bilibin.c:167
const struct SceneRegion * Bilibin_GetRegions(void)
Only the raised approach supplies exit-region boxes.
Definition bilibin.c:92
u16 gBilibin_DoorSteps0[]
Definition bilibin.c:1030
static void Event_GustJoins(void)
Gust, Jupiter Djinni 0, joins the party on the warehouse approach.
Definition bilibin.c:103
static void Event_AskAboutCurseBreakers(void)
Asks whether the party are the three warriors who broke the curse.
Definition bilibin.c:204
s32 Bilibin_Initialize(void)
Restores the current map's actors, collision cells and opening transition.
Definition bilibin.c:435
static void Event_JillGivesHardNut(void)
Back on the riverbank once the curse is lifted, Jill and her friends recognize the party,...
Definition bilibin.c:336
const struct SceneEntrance * Bilibin_GetEntrances(void)
Definition bilibin.c:76
u16 gBilibin_DoorSteps3[]
Definition bilibin.c:1038
struct ScenePlacement gBilibinPlacements1[]
Definition bilibin.c:831
struct SceneEntrance gBilibinEntrances3[]
Definition bilibin.c:780
static void Event_AskAboutEntranceTree(void)
Asks whether the party saw the strange tree at the entrance.
Definition bilibin.c:179
s16 gBilibinRegions2[]
Definition bilibin.c:797
u16 gBilibin_DoorSteps6[]
Definition bilibin.c:1014
static void Event_InspectHumanShapedTree(void)
Describes the human shape shared by the river's transformed villagers.
Definition bilibin.c:159
u16 gBilibin_DoorSteps4[]
Definition bilibin.c:1018
struct SceneEvent gBilibinEventsOther[]
Definition bilibin.c:893
u32 gBilibin_RiverBlockCells[]
Definition bilibin.c:1056
static void Bilibin_UpdateVillageBlockCells(void)
Updates collision cells around the movable block and moves an overlapping leader clear.
Definition bilibin.c:487
static void Event_OpenDoorAndLeave(void)
Walking into a door: everyone stops, the door opens and the leader walks through it.
Definition bilibin.c:222
static void Bilibin_RestoreRaisedEntrance(void)
Restores the block cells and starts the raised arrivals above floor height.
Definition bilibin.c:623
u32 gBilibinExits[]
Definition bilibin.c:803
u16 * gBilibin_DoorSteps[]
Definition bilibin.c:1042
const u32 * Bilibin_GetExits(void)
Returns the packed exit destinations shared by the three maps.
Definition bilibin.c:100
struct SceneEvent gBilibinEvents1[]
Definition bilibin.c:897
static void Event_ReadRestrictedAreaSign(void)
Reads the sign restricting entry without permission.
Definition bilibin.c:145
struct ScenePlacement gBilibinPlacements2[]
Definition bilibin.c:885
static void Bilibin_SpawnRiverEffect(struct FieldActor *actor)
Spawns the semi-transparent effect, which frees itself after thirty frames.
Definition bilibin.c:712
struct SceneEntrance gBilibinEntrances1[]
Definition bilibin.c:765
@ TREE_MAN
the cursed traveler, a tree at the village entrance
Definition bilibin.c:49
@ VILLAGE_BLOCK
the block moved with Move
Definition bilibin.c:50
@ FORMER_TREE_MAN
the same man once the curse is lifted
Definition bilibin.c:51
static void Event_ReadWarehouseSign(void)
Reads McCoy's warning on the hidden warehouse.
Definition bilibin.c:152
u16 gBilibin_DoorSteps2[]
Definition bilibin.c:1034
static void Event_InspectWell(void)
Reads the two-part description of the deep well.
Definition bilibin.c:122
const struct ScenePlacement * Bilibin_GetPlacements(void)
Selects the village, river or raised-approach actors.
Definition bilibin.c:106
struct ScenePlacement gBilibinPlacementsOther[]
Definition bilibin.c:827
s32 gBilibin_FaceLeaderScript[]
Definition bilibin.c:754
static void Bilibin_UpdateRiverBlockCells(void)
Restores ten river cells, then clears the movable block's current cell.
Definition bilibin.c:602
static void Bilibin_UpdateRiverEffect(void)
Runs every frame in the river: while the controlled actor is west of x 142 and below 8 pixels high,...
Definition bilibin.c:695
Calls through a function pointer, by argument count.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
struct FieldActor * Engine_ObjectCreate(s32, s32, s32, s32)
The engine calls the debug menus import, and their palette swatch tiles.
void Djinn_JoinParty(s32 slot, s32 element, s32 djinn)
A Djinni joins the party: djinn (0 to 19) of element goes to the member with the fewest Djinn,...
Definition djinni.c:124
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
static s32 FieldObject_CheckMovementCollision(struct FieldActor *actor, struct FieldPosition *position)
Definition engine_call.h:66
FacingObject, the view of an object that turns to face a target.
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
void Engine_ObjectSetPosition(struct FieldActor *object, s32 fixed_x, s32 fixed_y, s32 fixed_z)
@ ANIM_WALK
Definition field_event.h:44
@ ANIM_STAND
Definition field_event.h:43
@ ANIM_NOD
Definition field_event.h:45
s32 Engine_LeaderCheckAhead(void)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Object_SetMode(struct FieldActor *object, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
static void Event_ShowMessageAndWait(s32 speaker, s32 flags, s32 frames)
void Engine_MessageShowCentered(s32 message, s32 flags)
s32 Engine_PartyGiveItem(s32 item, s32 flags)
#define GameFlag_IsSet
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
static void Camera_SetSpeed(s32 speed, s32 acceleration)
void Engine_CameraMoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
#define EMOTE_IN_FRONT
Definition field_event.h:49
static void Actor_MoveToAndWait(s32 actor, s32 x, s32 z)
#define MAP_CELL_STEP(srcX, srcY, width, height, frames)
Definition field_event.h:59
void Engine_ItemShowFound(s32 item, s32 height)
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
static void Map_CopyCellsTo(s32 srcX, s32 srcY, s32 destX, s32 destY, s32 width, s32 height)
void Engine_PsynergyCancel(void)
#define GameFlag_Clear
#define GameFlag_Set
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
s32 Engine_EventAskYesNo(s32 speaker, s32 flags)
void Engine_ObjectSetScript(struct FieldActor *object, const s32 *script)
void Engine_CameraWaitForMove(void)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
static void Event_ShowMessage(s32 speaker, s32 flags)
static void Event_PlayCue(s32 cue)
#define MAP_CELL_STEPS_END
Definition field_event.h:61
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_MapAnimateCells(const u16 *steps, s32 destX, s32 destY)
static void Actor_CenterAndWalk(s32 actor, s32 priority, s32 dz)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
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_EventWait(s32 frames)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
static struct FieldActor * Actor_Get(s32 actor)
Field objects and actors, and the scene transition styles.
@ ACTOR_LINK_KEEP_MOTION
Definition field_obj.h:148
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ TRANSITION_BACKDROP_FADE
Definition field_obj.h:16
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
@ ACTOR_FACES_MOTION
turns toward its velocity, 1/16 turn a frame
Definition field_obj.h:166
The scene table formats: entrances, exits, placements and events, and the macros that write them.
#define SCENE_EVENTS_END
#define FIND_ITEM(item)
@ EVENT_TOUCH
@ EVENT_EXIT
@ EVENT_TALK
@ FACING_STEP
Definition field_scene.h:36
#define SCENE_EXITS(scene)
Definition field_scene.h:72
#define IF_FLAG_SET(flag)
Definition field_scene.h:48
#define FIND_MESSAGE(message)
#define SCENE_EXIT(exit, scene, entrance)
Definition field_scene.h:73
@ ACTOR_FIRST_PLACED
@ ACTOR_PARTY_LEADER
@ SCENE_TABLE_END
Definition field_scene.h:43
@ CONDITION_ALWAYS
Definition field_scene.h:44
@ TALK_KEEP_FACING
@ TALK_FACE_PARTY
@ TALK_FACE_PARTY_AND_BACK
#define PSYNERGY_ON_ACTOR(ability)
#define EVENT_SCRIPT(script)
@ ACTOR_WANDER
@ ACTOR_STAND
#define SEARCH(target)
#define SCENE_EXITS_END
Definition field_scene.h:77
#define TOUCH_WALKING_INTO(facing)
@ FACING_NORTHEAST
Definition field_scene.h:33
@ FACING_EAST
Definition field_scene.h:26
@ FACING_SOUTHEAST
Definition field_scene.h:27
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_SOUTHWEST
Definition field_scene.h:29
@ FACING_NORTHWEST
Definition field_scene.h:31
@ FACING_SOUTH
Definition field_scene.h:28
@ FACING_WEST
Definition field_scene.h:30
#define TOUCH_WALKING
#define PIXELS(value)
@ SEARCH_JAR
@ SEARCH_UNNAMED
#define FIND_COINS(coins)
The scene service layer: one typed inline for each engine service a scene calls by its own name,...
static void FieldObject_SetTargetAndCallback(s32 object, s32 target, const s32 *actions)
Game flags, named where their meaning is shown.
#define FLAG_SHOW_LOCATION_NAME
Definition flags.h:94
#define FLAG_DJINNI_0
the flag of Djinni 0, set once it is caught
Definition flags.h:15
#define FLAG_MCCOY_PALACE_VISITED
set on every entry to the palace
Definition flags.h:324
#define FLAG_BILIBIN_JILL_GIFT_RECEIVED
her thanks, a Hard Nut
Definition flags.h:216
#define FLAG_MCCOY_PALACE_ADMITTED
The gate guards have let the party into the palace.
Definition flags.h:323
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_KOLIMA_CURSE_LIFTED
Definition flags.h:103
#define FLAG_BILIBIN_JILL_RESCUED
Jill, a tree, pulled from the river.
Definition flags.h:215
#define FLAG_SATUROS_BEATEN_AT_MERCURY
Saturos is beaten at Mercury Lighthouse: the Hermes fountain at its foot flows again.
Definition flags.h:358
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The screen blend's globals and the graphics routines.
The main-image routines scene overlays import.
Item numbers, named from the English release.
@ ITEM_HARD_NUT
Definition item_ids.h:53
@ ITEM_HERB
Definition item_ids.h:40
void RunSceneTransitionEffect(s32 x, s32 y)
Starts the wave effect of caster sourceId on target targetId: fades the palettes toward a hue that sh...
Definition mind_read.c:27
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
#define SC_LOOP(n, to)
Repeat up to n times.
Definition objcmd.h:28
#define SC_FREE
Release.
Definition objcmd.h:43
#define SC_FOREVER
Definition objcmd.h:14
#define SC_WAIT(n)
Wait n frames.
Definition objcmd.h:16
#define SC_TOP
Script start.
Definition objcmd.h:13
#define SC_CALL(fn)
Definition objcmd.h:50
void FieldObject_WaitForMove(void *fieldObject)
Waits a frame at a time until a field object has arrived at its target, at most 600 frames.
Scene numbers, named after their places.
char SceneId_Bilibin3
char SceneId_Bilibin2
char SceneId_Bilibin1
Song and sound effect ids, indices into gSound_SongTable.
#define SE_DOOR_OPEN
Definition songs.h:153
#define SE_185
Definition songs.h:180
#define SE_188
Definition songs.h:183
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
void Engine_TaskWait()
void Engine_EventSetMessage()
#define NULL
Definition bilibin.h:6
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationSpritePart image
Definition animspr.h:109
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
u16 priority
2 when created
Definition animspr.h:100
The running scene's event work: its placement and event tables, its actors, the triggers and exit it ...
Definition event_work.h:20
s32 startTransition
SCENE_TRANSITION(style, variant).
Definition event_work.h:43
s16 touchedTrigger
the step event a touch or exit event answers
Definition event_work.h:26
u16 message
the next message, advanced as each window opens
Definition event_work.h:47
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
u8 steeringFlags
ActorSteeringFlag bits.
Definition field_obj.h:92
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
Definition field_obj.h:83
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
s32 velocityX
16.16 fixed-point pixels per frame
Definition field_obj.h:52
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
Definition field_obj.h:51
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition field_obj.h:39
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition field_obj.h:40
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
s32 velocityZ
16.16 fixed-point pixels per frame
Definition field_obj.h:54
u8 terrainId
The map layer (0 to 3) its ground height is read from, which the scrolling camera updates from the ce...
Definition field_obj.h:47
A position on the field.
s32 z
16.16 fixed-point pixels
s16 entrance
Definition game_state.h:37
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
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...
Counts frames between the river effects, one every 30 frames.
Definition bilibin.c:68
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels