Alchemy
Loading...
Searching...
No Matches

kolima_forest_bridge.c

Go to the documentation of this file.
1/// @file
2/// Kolima Forest's bridge, where the road from the world map enters the forest.
3/// Of its three logs, the one pushed west to the bank tips into the river and
4/// bridges it. Arriving from the world map before the party has seen the curse
5/// in Kolima, they see it fall here: sparkles of Tret's glamour rain down,
6/// domes of their own Psynergy shield them, and Tret and Laurel, unseen, speak
7/// of the dying forest.
8///
9/// FLAG_SCENE_TEMP_00: the log is in the river.
10
11#include "script.h"
12#include "flags.h"
13#include "character_ids.h"
14#include "game_state.h"
15#include "global_cells.h"
16#include "unit/import.h"
19#include "unit/object/object.h"
21#include "battle.h"
22#include "debug.h"
23#include "field.h"
24#include "game.h"
25#include "graphics.h"
26#include "menu.h"
27#include "minigame.h"
28#include "sound.h"
29#include "system.h"
30#include "mapcopy.h"
31#include "types.h"
32#include "tbs_edition.h"
33#include "field_event.h"
34#include "engine_call.h"
35#include "field_scene.h"
36#include "kolima.h"
37#include "staged_actor.h"
38#include "staged_actor_effect.h"
39#include "text/msg_ids.h"
40#include "objcmd.h"
41#include "songs.h"
42#include "fixed_math.h"
43
45
46enum {
47 RIVER_LOG = 10, ///< actors 8 to 10 are the logs
48 TRET = 11, ///< roars. "Hroom!"
49 LAUREL = 12,
50 /// The domes of Psynergy, one over each member; Mia's only with Mia.
55 /// The sparkles of Tret's glamour on the ground, gone once the curse is
56 /// lifted.
59};
60
62static void KolimaForestBridge_ShowMessageAndWait(s32 speaker, s32 frames);
63static void KolimaForestBridge_FaceActorAndWait(s32 actorId, s32 facing,
64 s32 waitFrames);
67
71
73
74/// The end of a dome's growing: if a sparkle has burst on a dome, the dome
75/// takes its next pose.
76static s32
78 struct FieldActor *object = (struct FieldActor *)interpreter;
80 if (*pending) {
81 Object_SetMode(object, 2);
82 *pending = 0;
83 }
84 return 1;
85}
86
87/// Each frame: a ground sparkle's timer runs on at random, and the sparkle
88/// shows its bright frame (7) while the timer is past 1000, its dim one (10)
89/// before; at 1200 the timer starts over.
90static s32
92 struct FieldActor *object = (struct FieldActor *)interpreter;
93 s16 *counter = &object->timer;
94 *counter = (*counter + (((u32)Engine_RandomNext() * 100) >> 16));
95 if (*counter > 1000)
97 else
98 ObjectGroup_SetChildValue(object, 10);
99 if (*counter > 1200) {
100 u16 z = 0;
101 *counter = z;
102 }
103 return 1;
104}
105
106/// Where the party enters from the clearing and the world map.
109}
110
111const struct SceneRegion *KolimaForestBridge_GetRegions(void) { return 0; }
112
113/// The paths to the clearing and the world map.
116}
117
118/// The party's companions, the logs, Tret, Laurel, the domes and the ground
119/// sparkles.
122}
123
124/// Walking into a log: it rolls ahead until something stops it. The river
125/// log, stopped at the bank (cell column 20), tips over with a splash and
126/// floats in the water; its cells become ground the party can cross.
127static void KolimaForestBridge_PushLog(void) {
128 struct StagedActorProbe res;
130
131 if (StagedActor_FindClearPosition(&res)) {
132 SceneActor_MoveAndRedraw(res);
133 if (res.actorSlot == RIVER_LOG && (res.position.x >> 20) == 20) {
134 struct FieldActor *actor;
135
142 Map_CopyCellAttributes(0, 17, 2, 4, 19, 17);
143 StagedActor_FillGridAttributeRectangle(2, 20, 17, 1, 4, 0);
145 actor = Object_GetById(RIVER_LOG);
147 }
148 }
149
151}
152
153#include "common/kolima_jump.h"
154
155/// The logs, the jump east from the bank and the two paths.
158}
159
160/// On entry a log already in the river floats there again and the logs mark
161/// the cells they cover. From the world map, before the curse has been seen,
162/// the party sees it fall; once the curse is lifted the ground sparkles are
163/// gone.
165 FieldScene_RedrawActorFootprint(RIVER_LOG);
168 Map_CopyCellAttributes(0, 17, 2, 4, 19, 17);
169 StagedActor_FillGridAttributeRectangle(2, 20, 17, 1, 4, 0);
171 }
172 FieldScene_RedrawActorFootprint(8);
173 FieldScene_RedrawActorFootprint(9);
177 }
178 }
181 Engine_ActorSetPosition(18, 0, 0);
182 Engine_ActorSetPosition(19, 0, 0);
183 Engine_ActorSetPosition(20, 0, 0);
185 }
186 return 0;
187}
188
189/// The party, on the bridge, sees the curse fall. Ivan notices sparkly stuff
190/// on the ground; sparkles rain from the sky, the party sinks under them, and
191/// domes of Psynergy rise around each member before the sparkles reach them.
192/// They argue over whose Psynergy it was, the sparkles fall again and the
193/// domes rise again, and Tret and Laurel speak: Tret turned Kolima's people
194/// into trees for cutting him, and only his gentle side, deep in the forest,
195/// can save them. Lines and choices for Mia are skipped when she is not in
196/// the party.
198 struct FieldActor *record;
199 s32 *party;
200 const s32 *sparkleAction;
201 const s32 *squashAction;
202 s32 *miaInParty;
203 const s32 *restoreScaleAction;
204 const s32 *growBarrierAction;
205 const s32 *shrinkBarrierAction;
206
208 Camera_MoveTo(-1, -1, -1, 0);
210 Camera_MoveTo(PIXELS(246), -1, PIXELS(604), 0);
211 // Flag 3: Mia is in the party.
214 record = Object_GetById(13);
216 record = Object_GetById(14);
218 record = Object_GetById(15);
220 record = Object_GetById(16);
222 record = Object_GetById(17);
224 record = Object_GetById(18);
226 record = Object_GetById(19);
228 record = Object_GetById(20);
230 record = Object_GetById(21);
233 Actor_SetActionScript(17, sparkleAction);
234 Actor_SetActionScript(18, sparkleAction);
235 Actor_SetActionScript(19, sparkleAction);
236 Actor_SetActionScript(20, sparkleAction);
237 Actor_SetActionScript(21, sparkleAction);
246 Actor_SetSpeed(GARET, PIXELS(3) / 5, PIXELS(3) / 10);
247 Actor_SetSpeed(IVAN, PIXELS(3) / 5, PIXELS(3) / 10);
248 {
250
251 if (leader != 0) {
252 Actor_SetPosition(GARET, leader->x.fixed, leader->z.fixed);
253 }
254 }
255 {
257
258 if (leader != 0) {
259 Actor_SetPosition(IVAN, leader->x.fixed, leader->z.fixed);
260 }
261 }
264 if (*party != 0) {
265 Actor_SetSpeed(MIA, PIXELS(3) / 5, PIXELS(3) / 10);
266 {
268
269 if (leader != 0) {
270 Actor_SetPosition(MIA, leader->x.fixed, leader->z.fixed);
271 }
272 }
274 }
292 Engine_EventSetMessage(MsgKolimaMatterIvan);
294 Engine_EventSetMessage(MsgKolimaSparklyStuffOnGround);
312 ColorBuffer_ApplyTarget(0x7fff, 0);
317 Engine_TaskWait(20);
318 ColorBuffer_ApplyTarget(0x405210, 1);
319 ColorBuffer_ApplyTarget(0x10000, 2);
321 Engine_TaskWait(60);
324 Actor_SetActionScript(GARET, squashAction);
325 Actor_SetActionScript(IVAN, squashAction);
326 Actor_SetActionScript(MIA, squashAction);
327 Engine_EventWait(100);
335 } else {
336 gEventWork->message += 1;
337 }
340 record = Object_GetById(3);
341 record->velocityY = PIXELS(2);
346 record = Object_GetById(3);
350 }
351 record = Object_GetById(0);
352 record->velocityY = PIXELS(2);
355 restoreScaleAction = gKolimaForestBridge_RestoreScaleAction;
356 Actor_SetActionScript(ACTOR_PARTY_LEADER, restoreScaleAction);
357 record = Object_GetById(0);
361 record = Object_GetById(1);
362 record->velocityY = PIXELS(2);
365 Actor_SetActionScript(GARET, restoreScaleAction);
366 record = Object_GetById(1);
370 record = Object_GetById(2);
371 record->velocityY = PIXELS(2);
373 Actor_SetActionScript(IVAN, restoreScaleAction);
374 record = Object_GetById(2);
378 Engine_EventWait(160);
380 Engine_EventWait(120);
381 ColorBuffer_ApplyTarget(0x406218, 1);
383 Engine_TaskWait(60);
385 gFallingEffectOffset = 0x800000;
388 Engine_EventWait(180);
418 } else {
419 gEventWork->message += 1;
420 }
422 Object_GetById(0)->priorityFlags &= 254;
423 Object_GetById(1)->priorityFlags &= 254;
424 Object_GetById(2)->priorityFlags &= 254;
425 Object_GetById(3)->priorityFlags &= 254;
436 growBarrierAction = gKolimaForestBridge_BarrierGrowAction;
437 Actor_SetActionScript(LEADER_BARRIER, growBarrierAction);
441 Actor_SetActionScript(IVAN_BARRIER, growBarrierAction);
446 Actor_SetActionScript(MIA_BARRIER, growBarrierAction);
447 }
451 Actor_SetActionScript(GARET_BARRIER, growBarrierAction);
452 if (gFallingEffectState != 0) {
453 do {
455 } while (gFallingEffectState != 0);
456 }
457 Engine_EventWait(300);
459 Engine_EventWait(120);
461 ColorBuffer_ApplyTarget(0x10000, 1);
463 Engine_TaskWait(60);
468 }
471 shrinkBarrierAction = gKolimaForestBridge_BarrierShrinkAction;
472 Actor_SetActionScript(LEADER_BARRIER, shrinkBarrierAction);
473 Actor_SetActionScript(IVAN_BARRIER, shrinkBarrierAction);
475 Actor_SetActionScript(MIA_BARRIER, shrinkBarrierAction);
476 }
477 Actor_RunActionScriptAndWait(GARET_BARRIER, shrinkBarrierAction);
482 Actor_SetPosition(TRET, PIXELS(220), PIXELS(494));
485 if (Engine_EventChooseYesNo(11, 0) == 1) {
486 gEventWork->message += 1;
487 }
495 Engine_EventSetMessage(MsgKolimaKnowThoseFieldsWere);
497 }
502 Engine_EventSetMessage(MsgKolimaWasOurPsynergy);
508 record = Object_GetById(1);
510 Engine_ActorJump(GARET, 6, 0);
525 Engine_ActorJump(GARET, 2, 0);
527 Engine_ActorJump(GARET, 2, 0);
529 Engine_ActorJump(GARET, 4, 0);
539 record = Object_GetById(3);
541 Engine_ActorJump(MIA, 4, 0);
548 } else {
549 gEventWork->message += 1;
550 }
551 Engine_ActorJump(GARET, 2, 0);
564 record = Object_GetById(2);
566 Engine_ActorJump(IVAN, 4, 0);
573 record = Object_GetById(0);
599 if (Engine_EventChooseYesNo(0, 0) == 0) {
602 gEventWork->message += 1;
603 } else {
608 }
621 } else {
622 gEventWork->message += 1;
623 }
660 if (Engine_EventChooseYesNo(0, 0) == 0) {
662 } else {
666 gEventWork->message += 1;
667 }
670 ColorBuffer_ApplyTarget(0x406218, 1);
672 Engine_TaskWait(60);
674 gFallingEffectOffset = 0x800000;
684 Engine_EventSetMessage(MsgKolimaWatchOutItsHappeningAgain);
690 }
691 Object_GetById(0)->priorityFlags &= 254;
692 Object_GetById(1)->priorityFlags &= 254;
693 Object_GetById(2)->priorityFlags &= 254;
694 Object_GetById(3)->priorityFlags &= 254;
702 growBarrierAction = gKolimaForestBridge_BarrierGrowAction;
703 Actor_SetActionScript(LEADER_BARRIER, growBarrierAction);
705 Actor_SetActionScript(IVAN_BARRIER, growBarrierAction);
708 Actor_SetActionScript(MIA_BARRIER, growBarrierAction);
709 }
711 Actor_SetActionScript(GARET_BARRIER, growBarrierAction);
712 Engine_EventWait(120);
714 do {
716 } while (gFallingEffectState != 0);
814 ColorBuffer_ApplyTarget(0x10000, 1);
816 Engine_TaskWait(80);
819 miaInParty = &gKolimaForestBridge_MiaInParty;
823 shrinkBarrierAction = gKolimaForestBridge_BarrierShrinkAction;
824 Actor_SetActionScript(LEADER_BARRIER, shrinkBarrierAction);
825 Actor_SetActionScript(IVAN_BARRIER, shrinkBarrierAction);
826 if (*miaInParty != 0) {
827 Actor_SetActionScript(MIA_BARRIER, shrinkBarrierAction);
828 }
829 Actor_RunActionScriptAndWait(GARET_BARRIER, shrinkBarrierAction);
844 if (Engine_EventChooseYesNo(0, 0) == 0) {
848 if (Engine_EventChooseYesNo(0, 0) == 0) {
861 } else {
868 Engine_EventSetMessage(MsgKolimaHesAsStumpedAsWe);
872 }
876 } else {
880 Engine_EventSetMessage(MsgKolimaYoureIsaacThereIsntMuch);
889 if (Engine_EventChooseYesNo(0, 0) == 0) {
895 if (*miaInParty != 0) {
899 } else {
900 gEventWork->message += 1;
901 }
908 Engine_EventWait(120);
914 } else {
915 gEventWork->message += 1;
916 }
922 }
933 } else {
937 Engine_EventSetMessage(MsgKolimaThatsReliefIsaacThoughtYoud);
939 if (*miaInParty != 0) {
943 } else {
944 gEventWork->message += 1;
945 }
958 } else {
959 gEventWork->message += 1;
960 }
968 }
969 }
971 Actor_SetSpeed(GARET, PIXELS(6) / 5, PIXELS(3) / 5);
972 Actor_SetSpeed(IVAN, PIXELS(6) / 5, PIXELS(3) / 5);
973 Actor_SetSpeed(MIA, PIXELS(6) / 5, PIXELS(3) / 5);
975 {
977
978 if (leader != 0) {
979 Actor_SetDestination(GARET, leader->x.part.pixel, leader->z.part.pixel);
980 }
981 }
985 {
987
988 if (leader != 0) {
989 Actor_SetDestination(IVAN, leader->x.part.pixel, leader->z.part.pixel);
990 }
991 }
993 Actor_SetPosition(IVAN, 0, 0);
996 {
998
999 if (leader != 0) {
1000 Actor_SetDestination(MIA, leader->x.part.pixel, leader->z.part.pixel);
1001 }
1002 }
1004 Actor_SetPosition(MIA, 0, 0);
1005 }
1007 Actor_SetPosition(TRET, 0, 0);
1011}
1012
1013static void KolimaForestBridge_ShowMessageAndWait(s32 speaker, s32 frames) {
1014 Engine_EventShowMessage(speaker, 0);
1015 Engine_EventWait(frames);
1016}
1017
1018/// Turns an actor at once, then leaves time for the next beat.
1020 s32 waitFrames) {
1021 Engine_ActorFaceDirection(actorId, facing, 0);
1022 Engine_EventWait(waitFrames);
1023}
1024
1025#include "common/kolima_grow.h"
1026
1027/// Every eighth frame a sparkle of Tret's glamour (object 26) falls toward
1028/// the party, with its tinkle while the rain is at its height.
1030 struct FieldActor *sparkle;
1031 struct AnimationObject *sprite;
1032 s32 framePhase;
1033 s32 priorityFlags;
1034 s32 spawnX = PIXELS(231);
1035 s32 spawnZ = PIXELS(460);
1036 s32 targetX = PIXELS(231);
1037 s32 targetZ = PIXELS(624);
1038
1039 framePhase = gFrameCount & 7;
1040 if (framePhase != 0)
1041 return;
1044 sparkle = Engine_ObjectCreate(26, spawnX, 0, spawnZ);
1045 if (sparkle == 0)
1046 return;
1047 sprite = sparkle->sprite;
1048 sprite->flags = framePhase;
1049 priorityFlags = 0xff & ~ACTOR_PRIORITY_AUTOMATIC;
1050 priorityFlags &= sparkle->priorityFlags;
1051 sparkle->priorityFlags = priorityFlags;
1052 sprite->image.priority = 1;
1053 sparkle->scaleX = Q16_ONE / 10;
1054 sparkle->speed = PIXELS(8);
1055 sparkle->acceleration = PIXELS(8);
1056 sparkle->motionFlags = framePhase;
1057 Object_SetMode(sparkle, 2);
1058 Engine_ObjectSetPosition(sparkle, targetX, 0, targetZ);
1060}
1061
1062#include "common/kolima_blink.h"
1063
1064/// The end of a sparkle's fall: one that lands on a dome (the domes' area,
1065/// which differs with Mia) bursts with a sound, and the domes are told.
1066static s32
1068 struct FieldActor *arg0 = (struct FieldActor *)interpreter;
1069 s32 x;
1070
1072 ? (x = arg0->x.fixed,
1073 (x > 0xc00000 && x < 0x1120000 && arg0->z.fixed > 0x2360000 &&
1074 arg0->z.fixed < 0x2640000) ||
1075 (x > 0xca0000 && x < 0xff0000 && arg0->z.fixed > 0x2250000 &&
1076 arg0->z.fixed < 0x2780000))
1077 : (x = arg0->x.fixed,
1078 (x > 0xc00000 && x < 0xf40000 && arg0->z.fixed > 0x2250000 &&
1079 arg0->z.fixed <= 0x248ffff) ||
1080 (x > 0xf40000 && x < 0x1120000 &&
1081 arg0->z.fixed > 0x23b0000 && arg0->z.fixed <= 0x25cffff) ||
1082 (x > 0xd30000 && x < 0xff0000 && arg0->z.fixed > 0x2540000 &&
1083 arg0->z.fixed < 0x2780000)))) {
1084 return 0;
1085 }
1087#ifdef UBFIX
1089#else
1090 /* FAKEMATCH: called through a cast to the call type the bytes show; called by
1091 * its prototype or through Object_SetScript, r0 is set before the script
1092 * literal loads (2 differ) */
1093 ((s32 (*)())Engine_ObjectSetScript)(
1095#endif
1097 return 0;
1098}
1099
1101s32 gKolimaForestBridge_BarrierHit __attribute__((section(".bss")));
1102s32 gKolimaForestBridge_MiaInParty __attribute__((section(".bss")));
1103s32 gKolimaForestBridge_SparkleSoundOn __attribute__((section(".bss")));
1104
1105/// Each frame the domes flicker: two show on even frames and two on odd,
1106/// the hidden ones lifted 500 pixels out of sight.
1108 struct FieldActor *p;
1109
1111 if (p != 0) {
1112 p->motionFlags = 0;
1113 if ((gFrameCount & 1) == 0) {
1114 p->y.fixed = 0;
1115 } else {
1116 p->y.fixed = PIXELS(500);
1117 }
1118 }
1120 if (p != 0) {
1121 p->motionFlags = 0;
1122 if ((gFrameCount & 1) != 0) {
1123 p->y.fixed = 0;
1124 } else {
1125 p->y.fixed = PIXELS(500);
1126 }
1127 }
1129 if (p != 0) {
1130 p->motionFlags = 0;
1131 if ((gFrameCount & 1) == 0) {
1132 p->y.fixed = 0;
1133 } else {
1134 p->y.fixed = PIXELS(500);
1135 }
1136 }
1138 if (p != 0) {
1139 p->motionFlags = 0;
1140 if ((gFrameCount & 1) != 0) {
1141 p->y.fixed = 0;
1142 } else {
1143 p->y.fixed = PIXELS(500);
1144 }
1145 }
1146}
1147
1148/// Pixel step by direction: X in the upper halfword, Z in the lower.
1149#define DIRECTION_STEP(dx, dz) (((dx) << 16) | ((dz) & 0xffff))
1150
1152 DIRECTION_STEP(16, 0), DIRECTION_STEP(16, 0), DIRECTION_STEP(16, 0),
1153 DIRECTION_STEP(0, 16), DIRECTION_STEP(0, 16), DIRECTION_STEP(0, 16),
1154 DIRECTION_STEP(0, 16), DIRECTION_STEP(-16, 0), DIRECTION_STEP(-16, 0),
1155 DIRECTION_STEP(-16, 0), DIRECTION_STEP(-16, 0), DIRECTION_STEP(0, -16),
1156 DIRECTION_STEP(0, -16), DIRECTION_STEP(0, -16), DIRECTION_STEP(0, -16),
1157 DIRECTION_STEP(16, 0),
1158};
1159
1160// clang-format off
1162 207, 205, 228, 229, 298, 297,
1163};
1164
1166 -32, -8, 32, 8,
1167 -8, -32, 8, 32,
1168 -32, -16, 32, 0,
1169 -8, -32, 8, 32,
1170 -32, -8, 32, 8,
1171 -8, -32, 8, 32,
1172};
1173// clang-format on
1174
1175/// Garet, Ivan and Mia walk to their places beside the leader.
1177 SC_ARG(2), SC_MOVE(PIXELS(234), 0, PIXELS(576)),
1179 SC_ARG(1), SC_END,
1180};
1181
1183 SC_ARG(2), SC_MOVE(PIXELS(234), 0, PIXELS(623)),
1185 SC_ARG(1), SC_END,
1186};
1187
1189 SC_ARG(2), SC_MOVE(PIXELS(211), 0, PIXELS(602)),
1191 SC_ARG(1), SC_END,
1192};
1193
1194/// The glamour presses the party down: each squashes and wobbles until
1195/// released.
1197 SC_ADD(SW_SCALE_X, -0x4000), SC_ADD(SW_SCALE_Y, 0x2000), SC_WAIT(2),
1198 SC_ADD(SW_SCALE_X, 0x2000), SC_ADD(SW_SCALE_Y, -0x1000), SC_WAIT(2),
1199 SC_ADD(SW_SCALE_X, 0x1000), SC_ADD(SW_SCALE_Y, -2048), SC_WAIT(2),
1200 SC_ADD(SW_SCALE_X, 0x1000), SC_ADD(SW_SCALE_Y, -2048), SC_WAIT(2),
1202};
1203
1205 SC_SET(SW_SCALE_X, 0x10000),
1206 SC_SET(SW_SCALE_Y, 0x10000),
1207 SC_WAIT(1),
1208 SC_END,
1209};
1210
1211/// A dome grows from a tenth of its size over 70 frames.
1213 SC_SET(SW_SCALE_X, 0x1999),
1214 SC_SET(SW_SCALE_Y, 0x1999),
1215 SC_WAIT(1),
1216 SC_LABEL(1),
1217 SC_ADD(SW_SCALE_X, 1310),
1218 SC_ADD(SW_SCALE_Y, 1310),
1219 SC_WAIT(1),
1220 SC_LOOP(70, SC_TO(1)),
1222 SC_END,
1223};
1224
1225/// A dome sinks and shrinks away over 90 frames.
1227 SC_ARG(1),
1228 SC_ADD(SW_Z, -0x1999),
1229 SC_ADD(SW_SCALE_X, -983),
1230 SC_ADD(SW_SCALE_Y, -983),
1231 SC_WAIT(1),
1232 SC_LOOP(90, SC_TOP),
1233 SC_POS(0, 0, 0),
1234 SC_WAIT(1),
1235 SC_END,
1236};
1237
1239 SC_SET(SW_SCALE_X, 0xc000),
1240 SC_SET(SW_SCALE_Y, 0xc000),
1241 SC_SET(SW_COLLISION, 0),
1242 SC_SET(0x23, 0),
1243 SC_LABEL(1),
1246};
1247
1249 {0, CONDITION_ALWAYS, 384, 0, 312, FACING_NORTH, 0, -1, -1, -1, -1, 0},
1250 {2, CONDITION_ALWAYS, 24, 0, 128, FACING_EAST, 0, -1, -1, -1, -1, 0},
1251 {4, CONDITION_ALWAYS, 172, 0, 602, FACING_EAST, 0, -1, -1, -1, -1, 0},
1253};
1254
1255/// Exit 1 to the clearing (scene 41) and exit 4 to the world map (scene 2).
1256/// Exits 2 and 3, which no event uses, lead into this map (scene 40).
1258 SCENE_EXITS(40), SCENE_EXIT(1, 41, 1), SCENE_EXIT(2, 40, 1),
1259 SCENE_EXIT(3, 40, 1), SCENE_EXIT(4, 2, 8), SCENE_EXITS_END,
1260};
1261
1262/// Garet, Ivan and Mia for the curse; the three logs; Tret and Laurel; the
1263/// four domes; and the five ground sparkles.
1264// clang-format off
1269 { 0xcd, CONDITION_ALWAYS, 7,
1270 PIXELS(232), 0, PIXELS(128), FACING_SOUTH, TALK_KEEP_FACING, 0 },
1271 { 0xcf, CONDITION_ALWAYS, 7,
1272 PIXELS(208), 0, PIXELS(296), FACING_SOUTH, TALK_KEEP_FACING, 0 },
1273 { 0xcd, CONDITION_ALWAYS, 7,
1274 PIXELS(360), 0, PIXELS(304), FACING_SOUTH, TALK_KEEP_FACING, 0 },
1284 { 0x11d, CONDITION_ALWAYS, 7,
1285 PIXELS(232), 0, PIXELS(655), FACING_SOUTH, TALK_FACE_PARTY, 0 },
1286 { 0x11d, CONDITION_ALWAYS, 7,
1287 PIXELS(166), 0, PIXELS(576), FACING_SOUTH, TALK_FACE_PARTY,
1289 { 0x11d, CONDITION_ALWAYS, 7,
1290 PIXELS(189), 0, PIXELS(532), FACING_SOUTH, TALK_FACE_PARTY,
1292 { 0x11d, CONDITION_ALWAYS, 7,
1293 PIXELS(288), 0, PIXELS(570), FACING_SOUTH, TALK_FACE_PARTY,
1295 { 0x11d, CONDITION_ALWAYS, 7,
1296 PIXELS(331), 0, PIXELS(659), FACING_SOUTH, TALK_FACE_PARTY,
1298 { SCENE_TABLE_END },
1299};
1300// clang-format on
1301
1310};
1311
1315};
1316
1317/// A sparkle bursts on a dome: it doubles in size and is gone.
1319 SC_SET(SW_SCALE_X, 0x20000),
1320 SC_SET(SW_SCALE_Y, 0x20000),
1321 SC_WAIT(10),
1322 SC_FREE,
1323};
1324
1326 SC_ADD(SW_Y, PIXELS(-2)),
1328 SC_WAIT(1),
1329 SC_ADD(SW_Y, PIXELS(-2)),
1331 SC_WAIT(1),
1332 SC_LOOP(30, SC_TOP),
1333 SC_LABEL(1),
1334 SC_ADD(SW_Y, PIXELS(-1)),
1336 SC_WAIT(1),
1337 SC_LOOP(40, SC_TO(1)),
1339 SC_FREE,
1340};
void ObjectGroup_SetChildValue(struct FieldActor *actor, s32 param)
Sets the param byte of every animated part of an actor's sprite.
void Object_RefreshSelectorById(u32 objectId)
Waits, at most 300 frames, for an actor's script to reach its end (command 0x10).
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
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[]
Character numbers, with each character's Japanese name.
#define GARET
Jerald.
#define MIA
Mary.
#define IVAN
Ivan.
void Engine_ActorSetSpriteFlags(struct FieldActor *, s32)
struct FieldActor * Engine_ObjectCreate(s32, s32, s32, s32)
The engine calls the debug menus import, and their palette swatch tiles.
The engine call layer: one typed inline for each of the thirteen main-image routines below that the s...
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
void Engine_ObjectSetPosition(struct FieldActor *object, s32 fixed_x, s32 fixed_y, s32 fixed_z)
static s32 Event_OpenMessage(s32 speaker, s32 flags)
static void Actor_SetDestination(s32 actor, s32 x, s32 z)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Object_SetMode(struct FieldActor *object, s32 animation)
void Engine_ActorSetSpritePriority(s32 actor, s32 priority)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
#define GameFlag_IsSet
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
s32 Engine_TaskRemoveCallback(void(*callback)(void))
void Engine_ActorJump(s32 actor, s32 height, s32 frames)
#define EMOTE_IN_FRONT
Definition field_event.h:49
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
static void Actor_RunActionScriptAndWait(s32 actor, const s32 *script)
Runs a script, waiting at most 300 frames for its final command.
static void ColorBuffer_ApplyTarget(s32 value, s32 mode)
void Engine_EventWaitForScreen(void)
#define GameFlag_Set
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
void Engine_ObjectSetScript(struct FieldActor *object, const s32 *script)
void Engine_EventOpenScreen(void)
void Engine_GameFlagSet(s32 flag)
static void Actor_SetActionScript(s32 actor, const s32 *script)
The engine encodes either a built-in action or an action-script address.
void Engine_ActorWaitForMove(s32 actor)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorStop(s32 actor)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
static void Event_ShowMessage(s32 speaker, s32 flags)
s32 Engine_RandomNext()
static void Event_PlayCue(s32 cue)
s32 Engine_GameFlagIsSet(s32 flag)
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_MapRedraw(void)
void Engine_ColorBufferInterpolate(s32 frames)
static void Camera_MoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
static void Actor_SetPosition(s32 actor, s32 fixed_x, s32 fixed_z)
void Engine_EventWait(s32 frames)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
@ ACTOR_PRIORITY_AUTOMATIC
The sprite takes its priority from the map cell under it.
Definition field_obj.h:153
The scene table formats: entrances, exits, placements and events, and the macros that write them.
#define SCENE_EVENTS_END
@ EVENT_TOUCH
@ EVENT_EXIT
#define SCENE_EXITS(scene)
Definition field_scene.h:72
#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
#define EVENT_SCRIPT(script)
#define EVENT_TOUCH_WALKING
@ ACTOR_STAND
#define SCENE_EXITS_END
Definition field_scene.h:77
#define TOUCH_WALKING_INTO(facing)
#define PLACEMENT_SHARE_PREVIOUS_SPRITE
@ FACING_NORTHEAST
Definition field_scene.h:33
@ FACING_EAST
Definition field_scene.h:26
@ FACING_SOUTHEAST
Definition field_scene.h:27
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_SOUTHWEST
Definition field_scene.h:29
@ FACING_NORTHWEST
Definition field_scene.h:31
@ FACING_SOUTH
Definition field_scene.h:28
@ FACING_WEST
Definition field_scene.h:30
#define PIXELS(value)
16.16 fixed-point constants, sine and cosine, and the library division.
#define Q16_ONE
One in the engine's signed 16.16 fixed-point format.
Definition fixed_math.h:10
Game flags, named where their meaning is shown.
#define FLAG_IN_PARTY(character)
Flags 0 to 7: the character with that id (character_ids.h) is in the party (Party_AddActiveOwner).
Definition flags.h:9
#define FLAG_KOLIMA_CURSE_WITNESSED
The party has seen the curse fall, in Kolima or on the forest bridge.
Definition flags.h:260
#define FLAG_SCENE_TEMP_00
Definition flags.h:713
#define FLAG_KOLIMA_CURSE_LIFTED
Definition flags.h:103
volatile u32 gFrameCount
Frames WaitFrames has finished.
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The work slots of gWorkSlot, read through their own names.
The screen blend's globals and the graphics routines.
The main-image routines scene overlays import.
s32 gFallingEffectScript[]
Definition kolima.c:1714
The globals Kolima's scenes share: the falling effect and the party's state.
@ IVAN_BARRIER
@ MIA_BARRIER
@ TRET
roars. "Hroom!"
@ LEADER_BARRIER
The domes of Psynergy, one over each member; Mia's only with Mia.
@ LAST_GROUND_SPARKLE
@ GARET_BARRIER
@ RIVER_LOG
actors 8 to 10 are the logs
@ FIRST_GROUND_SPARKLE
The sparkles of Tret's glamour on the ground, gone once the curse is lifted.
static void KolimaForestBridge_WitnessForestCurse(void)
The party, on the bridge, sees the curse fall.
static void KolimaForestBridge_FlickerBarriers(void)
Each frame the domes flicker: two show on even frames and two on odd, the hidden ones lifted 500 pixe...
s32 gKolimaForestBridge_BarrierGrowAction[]
A dome grows from a tenth of its size over 70 frames.
s32 KolimaForestBridge_Initialize(void)
On entry a log already in the river floats there again and the logs mark the cells they cover.
s32 gKolimaForestBridge_GroundSparkleAction[]
struct ScenePlacement gKolimaForestBridge_Placements[]
Garet, Ivan and Mia for the curse; the three logs; Tret and Laurel; the four domes; and the five grou...
s32 gKolimaForestBridge_BarrierShrinkAction[]
A dome sinks and shrinks away over 90 frames.
struct SceneEntrance gKolimaForestBridge_Entrances[]
@ ENTRANCE_FROM_WORLD_MAP
u32 gKolimaForestBridge_Exits[]
Exit 1 to the clearing (scene 41) and exit 4 to the world map (scene 2).
const struct SceneEntrance * KolimaForestBridge_GetEntrances(void)
Where the party enters from the clearing and the world map.
static void KolimaForestBridge_SpawnCurseSparkle(void)
Every eighth frame a sparkle of Tret's glamour (object 26) falls toward the party,...
struct SceneEvent gKolimaForestBridge_Events[]
static void KolimaForestBridge_ShowMessageAndWait(s32 speaker, s32 frames)
static void KolimaForestBridge_PushLog(void)
Walking into a log: it rolls ahead until something stops it.
s32 gKolimaForestBridge_IvanAction[]
s32 gKolimaForestBridge_BarrierHit
s32 gKolimaForestBridge_SquashAction[]
The glamour presses the party down: each squashes and wobbles until released.
s32 gKolimaForestBridge_SparkleScript[]
s32 gKolimaForestBridge_GaretAction[]
Garet, Ivan and Mia walk to their places beside the leader.
static s32 KolimaForestBridge_FlashHitBarriers(struct ScriptInterpreter *interpreter)
The end of a dome's growing: if a sparkle has burst on a dome, the dome takes its next pose.
static void KolimaForestBridge_FaceActorAndWait(s32 actorId, s32 facing, s32 waitFrames)
Turns an actor at once, then leaves time for the next beat.
s32 gKolimaForestBridge_MiaAction[]
static s32 KolimaForestBridge_BurstOnBarrier(struct ScriptInterpreter *interpreter)
The end of a sparkle's fall: one that lands on a dome (the domes' area, which differs with Mia) burst...
s32 gKolimaForestBridge_SparkleBurstScript[]
A sparkle bursts on a dome: it doubles in size and is gone.
s32 gKolimaForestBridge_RestoreScaleAction[]
s32 gKolimaForestBridge_MiaInParty
const struct ScenePlacement * KolimaForestBridge_GetPlacements(void)
The party's companions, the logs, Tret, Laurel, the domes and the ground sparkles.
s32 gKolimaForestBridge_SparkleSoundOn
static s32 KolimaForestBridge_TwinkleGroundSparkle(struct ScriptInterpreter *interpreter)
Each frame: a ground sparkle's timer runs on at random, and the sparkle shows its bright frame (7) wh...
const struct SceneEvent * KolimaForestBridge_GetEvents(void)
The logs, the jump east from the bank and the two paths.
const struct SceneRegion * KolimaForestBridge_GetRegions(void)
const u32 * KolimaForestBridge_GetExits(void)
The paths to the clearing and the world map.
Kolima, its forest bridge and the forest's tree: an effect (object 26) that stretches as it travels.
static s32 SceneEffect_AdvanceAngleUntilIdle(struct ScriptInterpreter *interpreter)
An object script call: widen the object by 0x1eb8 (about 0.12) a frame, and release it once it has re...
Definition kolima_grow.h:11
Kolima's forest bridge and river: the hop east onto actor 10 (the third placement).
static void KolimaForest_HopEast(void)
Touch trigger 11, walking east: hop 30 pixels east of the leader.
Definition kolima_jump.h:60
Declares nothing of its own: it only includes edition.h and types.h.
The reel game's title lettering.
Field object scripts: one s32 command word, then its operands, as gScriptObject_CommandTable runs the...
#define SC_LABEL(n)
Branch destination.
Definition objcmd.h:11
#define SC_SET(w, v)
Write a work value.
Definition objcmd.h:37
#define SC_LOOP(n, to)
Repeat up to n times.
Definition objcmd.h:28
#define SC_POS(x, y, z)
Set position.
Definition objcmd.h:18
#define SC_FREE
Release.
Definition objcmd.h:43
#define SC_SYNC
Wait for arrival.
Definition objcmd.h:17
#define SC_FOREVER
Definition objcmd.h:14
#define SC_TO(n)
Definition objcmd.h:12
#define SC_ADD(w, v)
Definition objcmd.h:38
#define SC_ARG(v)
Definition objcmd.h:44
#define SC_MOVE(x, y, z)
Move toward the target.
Definition objcmd.h:19
#define SC_WAIT(n)
Wait n frames.
Definition objcmd.h:16
#define SC_TOP
Script start.
Definition objcmd.h:13
#define SC_END
Return to the main script.
Definition objcmd.h:32
@ SW_SCALE_Y
Definition objcmd.h:63
@ SW_COLLISION
Definition objcmd.h:79
@ SW_Z
Definition objcmd.h:60
@ SW_FACING
Definition objcmd.h:57
@ SW_Y
Definition objcmd.h:59
@ SW_SCALE_X
Definition objcmd.h:62
#define SC_CALL(fn)
Definition objcmd.h:50
static s32 StagedActor_FillGridAttributeRectangle(u32 layer, s32 x, s32 z, u32 width, u32 height, s32 value)
Sets the collision code of a width by height rectangle of cells, from cell (x, z),...
void Audio_PlayCueFromEventWork(void)
Starts the current scene's field music, chosen by Scene_ResolveInteractionResult.
Definition scene.c:355
The field object script interpreter and the operands its commands read.
Song and sound effect ids, indices into gSound_SongTable.
#define SE_220
Definition songs.h:215
#define SE_240
Definition songs.h:235
#define SE_106
Definition songs.h:99
#define SE_206
Definition songs.h:201
#define MUS_017
Definition songs.h:27
#define MUS_021
Definition songs.h:31
#define SE_200
Definition songs.h:195
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
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()
void Engine_EventShowMessage()
void Kolima_UpdateCurseDust(void)
A scene callback: every eighth frame a speck (object 285, its script gFallingEffectScript) starts 160...
The pushable actors' movement probes and footprint bounds.
A staged actor's effect and its request.
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
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 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
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
Definition field_obj.h:51
s32 velocityY
16.16 fixed-point pixels per frame
Definition field_obj.h:53
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition field_obj.h:39
s16 entrance
Definition game_state.h:37
A scene entrance: where and facing which way the party arrives, and the camera's bounds there (-1 for...
Definition field_scene.h:54
A scene event: its kind and detail, the trigger it answers, its condition and its value (a message or...
An actor a scene places: its sprite, the condition for placing it, how it behaves,...
Definition field_scene.h:81
A scene's exit region: the box that, while its condition holds, takes the party leader out through it...
The prefix that command handlers read from a field object's 0x70-byte slot.
Definition script.h:16
Where a large thing ahead of the leader would roll to: its footprint, its actor, that position,...
struct FieldPosition position
16.16 pixels while moving; converted to cells by footprint redraws.
s32 actorSlot
the large thing's actor number, 8 to 65
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
Values that differ by patch level or language, chosen once for their code.
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels