Alchemy
Loading...
Searching...
No Matches

colosso_log.c

Go to the documentation of this file.
1/// @file
2/// Colosso's third finals course: Isaac races another warrior through the
3/// Scales of Justice, the Stepping-Stone Stage, the Wall Wedge, the Free-Climb
4/// Area, the Moving Sidewalk Stage and a log-rolling area to the arena.
5
6#include "script.h"
7#include "version.h"
8#include "game_state.h"
9#include "io_write_queue.h"
10#include "resource_ids.h"
11#include "scene_ids.h"
12#include "vram_tab.h"
13#include "unit/import.h"
19#include "unit/object/object.h"
21#include "unit/field/field.h"
22#include "unit/game/game.h"
23#include "unit/window/window.h"
25#include "unit/menu/menu.h"
26#include "unit/sound/sound.h"
29#include "types.h"
30#include "field_event.h"
31#include "field_scene.h"
33#include "io_reg.h"
34#include "keystate.h"
35#include "battle.h"
36#include "debug.h"
37#include "field.h"
38#include "game.h"
39#include "graphics.h"
40#include "menu.h"
41#include "minigame.h"
42#include "sound.h"
43#include "system.h"
44#include "mem.h"
45#include "field_service.h"
46#include "flags.h"
47#include "text/msg_ids.h"
48#include "battle_unit.h"
49#include "resource.h"
50#include "ability_ids.h"
51#include "edition.h"
52#include "item_ids.h"
53#include "objcmd.h"
54#include "field_obj.h"
55#include "heap_state.h"
56#include "field_runtime.h"
57#include "fixed_math.h"
58#include "palbuf.h"
59#include "colosso_gauge.h"
60#include "macros.h"
61#include "songs.h"
62
63// Keep native call forms while UBFIX uses the declared void contracts.
64#ifdef UBFIX
65#define COLOSSO_LOG_FACE_DIRECTION Engine_ActorFaceDirection
66#define COLOSSO_LOG_INITIALIZE_MODE_TASK \
67 ColossoLogRollingStage_InitializeModeTask
68#define COLOSSO_LOG_APPLY_MATCHING_SLOT_VALUES Scene_GiveAndEquipItem
69#else
70#define COLOSSO_LOG_FACE_DIRECTION ((s32 (*)())Engine_ActorFaceDirection)
71#define COLOSSO_LOG_INITIALIZE_MODE_TASK \
72 ((s32 (*)())ColossoLogRollingStage_InitializeModeTask)
73#define COLOSSO_LOG_APPLY_MATCHING_SLOT_VALUES \
74 ((s32 (*)())Scene_GiveAndEquipItem)
75#endif
76
77static void ColossoLog_PlayPostBattleReunion(s32 battleResult);
78static void ColossoLog_IntroduceFinalCourse(s32 guideId);
81static void ColossoLog_WaitForRivalToFinish(void);
82static s32 ColossoLog_CollectFinishEquipment(s32 firstItem, s32 secondItem);
83static void ColossoLog_PushActorAhead(void);
84
85typedef void (*SceneTaskEntry)(void);
86
87/// The third course's actors, by the guide's and attendants' explanations: the
88/// Scales of Justice, the Stepping-Stone Stage, the Wall Wedge, the Free-Climb
89/// Area, the Moving Sidewalk Stage and another log-rolling area lead to the
90/// arena. The Wall Wedge's moving wall is actors 18 to 27; actors 15 to 17 are
91/// rocks that settle where they fall (FLAG_SCENE_TEMP_14 to _16).
92enum {
93 OPPONENT = 8, ///< the warrior racing Isaac to the arena
94 FROST_TARGET = 9, ///< on the eastern pan
95 SCALE_PAN_WEST = 10, ///< the Scales of Justice
97 SCALE_WEIGHT = 12, ///< pushed onto the western pan
98 STONE = 13,
102 LONG_LOG = 31, ///< the log-rolling area's long log
103 GUIDE = 32, ///< explains the third course
110 PRIZE_A = 39, ///< the arena's Claymore and Hunter's Sword
112};
113
114/// Sets the leader speed for the shared solo-party placement routine.
115static inline void InitializeActorZero(void) {
117}
118
119/// Sets a companion speed for the shared solo-party placement routine.
120static inline void InitializeSelectedActor(s32 actorId) {
121 Engine_ActorSetSpeed(actorId, PIXELS(1), PIXELS(1) / 2);
122}
123
125
128}
129
130const struct SceneRegion *ColossoLog_GetRegions(void) { return 0; }
131
133
136}
137
138/// Cycles the moving wall and raises the opening event beneath the rider.
140 struct EventWork *work = gEventWork;
142 s32 row = actor->z.fixed >> 20;
143 s32 i;
144 s32 kind;
145
146 if (gColossoSceneTaskState == 0) {
148 for (i = 18; i <= 22; i++) {
151 Engine_ActorSetAnimation(i + 5, kind + 8);
152 Engine_MapCopyCellAttributes(32, 11, 1, 2, (i - 18) * 2 + 33, 11);
153 if (kind != 7) {
154 Engine_MapCopyCellAttributes(74, 12, 1, 1, (i - 18) * 2 + 33, 11);
155 }
156 }
159 } else {
160 for (i = 18; i <= 22; i++) {
162 if ((u32)(actor->x.fixed - (i << 21) + 0x31ffff) <= 0x13fffe) {
163 if (row == 11 && kind == 4)
164 work->raisedTrigger = kind;
165 if (row == 12 && kind == 5)
166 work->raisedTrigger = kind;
167 }
168 }
169 }
170 if ((u32)++gColossoSceneTaskState > 17) {
172 }
173}
174
175// Function from another file; its callers use no declaration (implicit int).
176
177/// Resets the moving wall to its first displayed pattern.
179 SceneTaskEntry entry;
180
185 entry();
186}
187
188/// Resumes cycling the moving wall.
191}
192
193/// Waits for the wall pattern used by the tutorial, with a bounded timeout.
195 s32 polls;
196
197 Engine_TaskWait(10);
198
199 polls = 0;
202 polls++;
203 if (polls > 119) {
204 return;
205 }
206 }
207}
208
209/// On the Moving Sidewalk, until 0x363 is set, the belt carries the controlled
210/// actor and the camera west.
211static void Event_RideMovingSidewalk(void) {
212 struct EventWork *work = gEventWork;
213 struct GameState *state = &gGameState;
214 s32 id = state->selectedActor;
215 struct FieldActor *subject = work->viewCenter;
216 struct FieldActor *actor = Object_GetById(id);
217 s32 z = actor->z.part.pixel;
218
219 if ((u32)(z - 183) <= 3) {
220 subject->x.fixed += -(PIXELS(4) / 5);
221 actor->x.fixed += -(PIXELS(4) / 5);
222 }
223}
224
225/// Growth on the plant: it grows and opens a shortcut (0x360).
226static void Event_GrowPlant(void) {
227 Engine_GameFlagSet(0x360);
228 {
229
230 Map_CopyCellAttributes(47, 61, 1, 4, 49, 61);
231 }
232}
233
234/// Moves a scale pan vertically at the shared speed and acceleration.
235static inline void ColossoLog_MoveOnScales(struct FieldActor *pan, s32 height) {
236 pan->acceleration = PIXELS(2) / 5;
237 pan->speed = PIXELS(4) / 5;
238 Engine_ObjectSetPosition(pan, pan->x.fixed, height, pan->z.fixed);
239}
240
241/// Frost on the target on the eastern pan: it freezes and the Scales of Justice
242/// tip, the western pan down and the eastern pan up (0x362).
243static void Event_FreezeOnScales(void) {
244 struct FieldActor *object;
245
247 object->scaleX = Q16_ONE;
248 object->scaleY = Q16_ONE;
249
251 ColossoLog_MoveOnScales(object, PIXELS(32));
252
255
256 Engine_GameFlagSet(0x362);
257 Map_CopyCellAttributes(15, 12, 1, 1, 13, 12);
258 Map_CopyCellAttributes(14, 12, 1, 1, 9, 12);
259}
260
261/// Stepping onto the western pan, unless the scales are frozen: it sinks with
262/// the rider as the eastern pan rises (0x367).
263static void Event_StepOnScales(void) {
264 s32 actor;
265 s32 lowered;
266 struct FieldActor *log;
267 struct FieldActor *rider;
268 u8 *flags;
269
271 lowered = GameFlag_IsSet(0x362);
272 if (lowered == 0) {
274 if (log != NULL) {
275 Actor_SetDestination(actor, log->x.part.pixel, log->z.part.pixel);
276 }
279 log->motionFlags = lowered;
282 log->motionFlags = lowered;
284 rider = Object_GetById(actor);
285 flags = &rider->motionFlags;
286 *flags = lowered;
290 Map_CopyCellAttributes(0, 24, 1, 1, 9, 12);
294 rider->terrainHeight = rider->y.fixed;
295 Engine_GameFlagSet(0x367);
296 }
297}
298
299/// Stepping off the western pan: the scales swing back.
300static void Event_StepOffScales(void) {
301 struct FieldActor *object;
302
304
306 object->motionFlags = 0;
308
310 object->motionFlags = 0;
311 ColossoLog_MoveOnScales(object, PIXELS(32));
312
314 {
315 Map_CopyCellAttributes(0, 25, 1, 1, 9, 12);
316 }
319}
320
321/// When the weight reaches the western pan, it sinks the pan and the eastern
322/// pan rises (0x368).
323static void Event_SetWeightOnScales(void) {
324 struct FieldActor *probe;
325 struct FieldActor *log;
326 struct FieldActor *upper;
327 struct FieldActor *lower;
328 s32 x;
329 s32 z;
330
332 x = probe->x.fixed >> 20;
333 if (x == 9) {
334 z = probe->z.fixed >> 20;
335 if (z == 12) {
339 log->motionFlags = 0;
346 Engine_GameFlagSet(0x368);
347 Map_CopyCellAttributes(15, 12, 1, 1, 13, z);
348 Map_CopyCellAttributes(1, 25, 1, 1, x, z);
349 }
350 }
351}
352
353/// Walking into the weight pushes it, perhaps onto the scales.
354static void Event_PushWeight(void) {
357}
358
359/// After Move on the stone: its column is kept (byte flag 0x370) and its cell
360/// rebuilt.
361static void Event_MoveStone(void) {
362 struct FieldActor *actor;
363 s32 x;
364
365 actor = Object_GetById(STONE);
366 x = actor->x.fixed >> 20;
368 Map_CopyCellAttributes(18, 10, 3, 1, 18, 11);
369 Map_CopyCellAttributes(17, 11, 1, 1, x, 11);
370}
371
372/// Move on this rock needs nothing more.
373static void Event_IgnoreMove(void) {}
374
375/// Walking into a rock pushes it.
377
378/// A rock resting on the floor becomes a step (FLAG_SCENE_TEMP_14 to _16).
379static void Event_SettleRocks(void) {
380 struct FieldActor *actor;
381 s32 slot;
382 s32 x;
383 s32 z;
384 s32 x2;
385 s32 z2;
386
387 for (slot = 15; slot <= 17; slot++) {
388 actor = Object_GetById(slot);
389 if (Map_GetTerrainHeight(0, actor->x.fixed, actor->z.fixed) == 0) {
390 actor->priorityFlags = 2;
391 actor->motionFlags = 0;
392 x = actor->x.fixed >> 20;
393 z = actor->z.fixed >> 20;
394 Map_CopyCellAttributes(83, 13, 1, 1, x, z);
395 x2 = actor->x.fixed >> 20;
396 z2 = actor->z.fixed >> 20;
397 Map_CopyCellAttributes(83, 13, 1, 1, x2, z2 + 52);
399 }
400 }
401}
402
403/// Changes the eastern end collision according to the rider facing.
405 struct FieldActor *actor;
406 s32 x;
407 s32 z;
408 s32 collisionKind;
409
411 x = actor->x.fixed >> 20;
412 collisionKind = 23;
413 z = actor->z.fixed >> 20;
414 if (x == 81 && z == 12) {
415 if ((actor->facing & 0xE000) == 0x4000) {
416 collisionKind = 253;
417 }
418 SetMapCellCollision(0, x << 20, z << 20, collisionKind);
419 }
420}
421
422/// Rejects blocked cells and cells occupied by one of the three obstacles.
424 struct FieldActor *actor;
425
426 if (GetMapCellCollision(0, x, z) == 255) {
427 return -2;
428 }
429 actor = Object_GetById(15);
430 x >>= 20;
431 z >>= 20;
432 if (actor->x.fixed >> 20 == x && actor->z.fixed >> 20 == z) {
433 return -1;
434 }
435 actor = Object_GetById(16);
436 if (actor->x.fixed >> 20 == x && actor->z.fixed >> 20 == z) {
437 return -1;
438 }
439 actor = Object_GetById(17);
440 if (actor->x.fixed >> 20 == x && actor->z.fixed >> 20 == z) {
441 return -1;
442 }
443 return 0;
444}
445
446/// Checks all four cells covered by the long rolling log.
452 return -1;
453 }
454 return 0;
455}
456
457/// Walking into the long log rolls it, with the leader, the way the pad is held
458/// until something stops it; at the east end it drops into place and the path
459/// is made (0x369). Away from the log, a rock ahead is pushed instead.
460static void Event_RollLongLog(void) {
461 struct FieldActor *rider;
462 struct FieldActor *log;
463 struct EventWork *work;
464 s32 angle;
465 s32 actor;
466 s32 x;
467 s32 z;
468 s32 steps;
469 s32 nextX;
470 s32 column;
471 s32 acceleration;
472 s32 mode;
473 s32 step;
474 s32 ahead[3];
475
478 steps = 0;
479 angle = gColossoEarlySequenceData[rider->facing >> 13];
481 SET_VECTOR(ahead, (rider->x.fixed & -0x100000) + PIXELS(8), rider->y.fixed,
482 (rider->z.fixed & -0x100000) + PIXELS(8));
483 Vector_AddPolarOffset(PIXELS(16), angle, ahead);
484 x = log->x.fixed;
485 z = log->z.fixed;
486 // Only a nearby rider rolls the log; other interactions push the actor ahead.
487 if ((ahead[0] - x >= 0 ? ahead[0] - x : x - ahead[0]) > PIXELS(8) ||
488 (ahead[2] - z >= 0 ? ahead[2] - z : z - ahead[2]) > PIXELS(32)) {
489 goto far;
490 }
491 if (gKeysHeld & KEY_LEFT) {
492 mode = 2;
493 step = -8;
494 for (;;) {
495 nextX = x - PIXELS(16);
497 steps++;
498 x = nextX;
499 } else {
500 break;
501 }
502 }
503 } else {
504 if (!(gKeysHeld & KEY_RIGHT)) {
505 return;
506 }
507 mode = 3;
508 step = 8;
509 for (;;) {
510 nextX = x + PIXELS(16);
512 steps++;
513 x = nextX;
514 } else {
515 break;
516 }
517 }
518 }
519 if (steps == 0) {
520 return;
521 }
522 // Clear the old footprint, then move the log and rider together.
523 Map_CopyCellAttributes(74, 8, 1, 4, log->x.fixed >> 20, 9);
524 Map_CopyCellAttributes(120, 60, 8, 5, 74, 60);
526 Engine_ActorSetAnimation(actor, 8);
528 log->speed = PIXELS(1) / 2;
529 acceleration = PIXELS(1) / 5;
530 log->acceleration = acceleration;
531 Object_SetMode(log, mode);
532 Engine_ObjectSetPosition(log, x, 0, z);
534 Engine_ActorSetAnimation(actor, 2);
535 work = Runtime_AllocateBlock(HEAP_SLOT_EVENT, sizeof(struct FieldWork));
537 (s32)log);
538 Actor_SetSpeed(actor, PIXELS(1) / 2, acceleration);
540 Object_SetMode(rider, 2);
541 Engine_ObjectSetPosition(rider, (steps * step * PIXELS(1)) + rider->x.fixed,
542 0, rider->z.fixed);
544 Object_SetMode(rider, 1);
546 // At the eastern end the log settles into the course exit.
547 if (x >= PIXELS(1328)) {
548 GameFlag_Set(0x369);
552 Object_SetMode(log, 8);
555 column = 84;
556 Map_CopyCellAttributes(86, 10, 1, 2, column, 10);
557 Map_CopyCellAttributes(86, 9, 1, 1, column, 12);
560 } else {
561 Object_SetMode(log, 1);
564 column = x >> 20;
565 Map_CopyCellAttributes(85, 9, 1, 4, column, 9);
566 Map_CopyCellAttributes(85, 9, 1, 4, column, 61);
567 }
570 return;
571far:
574}
575
576/// Displays the activated moving sidewalk and plays its arrival sounds.
577static s32
583 return 0;
584}
585
586/// Force on the Moving Sidewalk's block: it slides away and the belt carries
587/// no one any more (0x363).
588static void Event_ForceSidewalkBlock(void) {
589 struct FieldActor *effect;
590 s32 moveRate;
591
593 effect->motionFlags = 0;
594 moveRate = PIXELS(8) / 5;
595 effect->acceleration = moveRate;
596 effect->speed = moveRate;
597 Object_SetMode(effect, 2);
599 Engine_GameFlagSet(0x363);
600}
601
602/// Halt on the wall operator: the Wall Wedge stops at its next open pattern
603/// (0x361).
604static void Event_HaltWall(void) {
606 Engine_GameFlagSet(0x361);
607 Engine_TaskWait(10);
612}
613
614/// The rider passes through the moving wall's northern opening.
615static void Event_PassNorthWallOpening(void) {
616 struct FieldActor *actor;
617#ifndef UBFIX
618 s16 *gameWords;
619#endif
620 s32 *actorId;
621 s32 z;
622
623#ifdef UBFIX
624 actorId = &gGameState.selectedActor;
625#else
626 // The original word-indexed address takes three more instructions here.
627 gameWords = (s16 *)&gGameState;
628 actorId = (s32 *)&gameWords[offsetof(struct GameState, selectedActor) /
629 sizeof(s16)];
630#endif
631 actor = Object_GetById(*actorId);
632 actor->acceleration = PIXELS(1);
633 actor->speed = PIXELS(2);
634 Engine_ActorSetAttachedEffect(*actorId, 258);
635 Object_SetMode(actor, 5);
636 z = actor->z.fixed & 0xFFF00000;
637 Engine_ObjectSetPosition(actor, actor->x.fixed, actor->y.fixed,
638 z + PIXELS(24));
640}
641
642/// The rider passes through the moving wall's southern opening.
643static void Event_PassSouthWallOpening(void) {
644 struct FieldActor *actor;
645#ifndef UBFIX
646 s16 *gameWords;
647#endif
648 s32 *actorId;
649 s32 z;
650
651#ifdef UBFIX
652 actorId = &gGameState.selectedActor;
653#else
654 // The original word-indexed address takes three more instructions here.
655 gameWords = (s16 *)&gGameState;
656 actorId = (s32 *)&gameWords[offsetof(struct GameState, selectedActor) /
657 sizeof(s16)];
658#endif
659 actor = Object_GetById(*actorId);
660 if (actor->x.fixed > PIXELS(664)) {
661 actor->x.fixed = PIXELS(664);
662 }
663 actor->acceleration = PIXELS(1);
664 actor->speed = PIXELS(2);
665 Object_SetMode(actor, 5);
666 z = actor->z.fixed & 0xFFF00000;
667 Engine_ObjectSetPosition(actor, actor->x.fixed, actor->y.fixed,
668 z + PIXELS(12));
670 Engine_ActorSetAttachedEffect(*actorId, 258);
672}
673
675
676/// Offers to practise the course with a selected solo competitor.
677UNUSED static void ColossoLog_RunCompetitorTalk(s32 competitorId) {
678 struct EventWork *work;
679 s32 actorId;
680 s32 messageOffset;
681 s32 entrance;
682
683 work = gEventWork;
684 actorId = gGameState.selectedActor;
685 entrance = gGameState.entrance;
686 if (entrance == 2) {
688 messageOffset = competitorId * 3;
689 Engine_EventSetMessage(messageOffset + MsgColossoDidntThinkBattles);
690 Engine_EventOpenMessage(competitorId, 0);
691 if (Engine_EventChooseYesNo(actorId, 0) == 0) {
692 Engine_EventSetMessage(messageOffset + MsgColossoDidntThinkBattles + 1);
693 Engine_EventShowMessage(competitorId, 0);
695 work->transitionFrames = 15;
698 Colosso_ControlCharacterAlone(competitorId);
701 } else {
702 Engine_EventSetMessage(messageOffset + MsgColossoDidntThinkBattles + 2);
703 Engine_EventShowMessage(competitorId, 0);
704 }
706 }
707}
708
709/// Reaching the arena: the leader takes a prize (the Claymore if first, the
710/// Hunter's Sword if second), and he and his opponent face off and fight.
711/// FLAG_SCENE_TEMP_11 says the arena was already reached; the arena's touch
712/// works while FLAG_SCENE_TEMP_10 is clear.
713static void Event_ReachArena(void) {
714 s32 place;
715 s32 i;
716 s32 last;
717
718 /* FAKEMATCH: the last place is set at the top as a forced temporary, so the
719 * weight stays 4 - place + 1 instead of folding to 5 - place. */
720 last = 4;
725 for (i = 0; i < 10; i++) {
727 }
729 Actor_WalkTo(OPPONENT, 1528, 192);
741 Actor_WalkToAndWait(OPPONENT, 1520, 192);
745 Field_RequestBattleFromEncounterTable(72, last - place + 1);
750}
751
752/// Walking into something: unless it is an actor, it is checked.
753static void Event_CheckAhead(void) {
754 if (Colosso_FindActorAhead() == 0) {
756 }
757}
758
759/// Walking into something: the weight is pushed, anything else is checked.
761 if (Colosso_FindActorAhead() == 0) {
763 } else {
765 }
766}
767
768const struct SceneEvent *ColossoLog_GetEvents(void) {
769 return gColossoLogEvents;
770}
771
772/// Restores obstacle progress, then enters practice, introduction or battle
773/// aftermath.
775 struct FieldActor *actor;
776 s32 i;
777 s32 height;
778 s32 column;
779
782 // Restore the scale pans, movable weight and supporting collision cells.
784 Map_CopyCellAttributes(74, 60, 8, 6, 120, 60);
785
787
790 actor->motionFlags = 0;
791 actor->y.fixed = PIXELS(32);
792
795 actor->motionFlags = 0;
796 actor->y.fixed = PIXELS(4);
797
798 if (Engine_GameFlagIsSet(866) != 0) {
801 actor->y.fixed = PIXELS(4);
803 actor->y.fixed = PIXELS(32);
804 Map_CopyCellAttributes(15, 12, 1, 1, 13, 12);
805 } else {
807 actor->scaleX = 3 * Q16_ONE / 2;
808 actor->scaleY = 3 * Q16_ONE / 2;
809 if (Engine_GameFlagIsSet(871) != 0) {
810 Map_CopyCellAttributes(0, 24, 1, 1, 9, 12);
811 } else {
812 Map_CopyCellAttributes(0, 25, 1, 1, 9, 12);
813 }
814 }
815
816 if (Engine_GameFlagIsSet(872) != 0) {
817 Map_CopyCellAttributes(15, 12, 1, 1, 13, 12);
818 Map_CopyCellAttributes(1, 25, 1, 1, 9, 12);
821 actor->motionFlags = 0;
822 actor->y.fixed = PIXELS(2);
825 actor->y.fixed = PIXELS(4);
828 actor->y.fixed = PIXELS(32);
829 }
830
831 column = FieldGameFlag_GetByte(880);
832 if (column == 0) {
833 column = 19;
834 }
835 actor = Object_GetById(STONE);
836 actor->x.fixed = (column << 20) + (PIXELS(8));
837 actor->motionFlags = 0;
839 Map_CopyCellAttributes(18, 10, 3, 1, 18, 11);
840 Map_CopyCellAttributes(17, 11, 1, 1, column, 11);
841
842 for (i = 15; i <= 17; i++) {
843 actor = Object_GetById(i);
844 height = Map_GetTerrainHeight(0, actor->x.fixed, actor->z.fixed);
845 if (actor->y.fixed == 0 && height == 0) {
847 actor->motionFlags = height;
848 Map_CopyCellAttributes(83, 13, 1, 1, actor->x.fixed >> 20,
849 actor->z.fixed >> 20);
850 Map_CopyCellAttributes(83, 13, 1, 1, actor->x.fixed >> 20,
851 (actor->z.fixed >> 20) + 52);
852 }
853 }
854
855 // Halt preserves a stationary wall; otherwise restart its pattern cycle.
856 if (Engine_GameFlagIsSet(865) != 0) {
857 for (i = 18; i <= 22; i++) {
858 actor = Object_GetById(i);
860 Object_SetMode(actor, 2);
861 actor = Object_GetById(i + 5);
863 actor->motionFlags = 0;
864 actor->y.fixed = PIXELS(32);
865 Object_SetMode(actor, 10);
866 Map_CopyCellAttributes(74, 12, 1, 1, i * 2 - 3, 11);
867 }
870 } else {
871 for (i = 18; i <= 22; i++) {
872 actor = Object_GetById(i);
874 actor = Object_GetById(i + 5);
876 actor->motionFlags = 0;
877 actor->y.fixed = PIXELS(32);
878 }
880 }
881
882 if (Engine_GameFlagIsSet(864) != 0) {
884 Map_CopyCellAttributes(47, 61, 1, 4, 49, 61);
885 }
886
887 if (Engine_GameFlagIsSet(867) != 0) {
890 actor->motionFlags = 0;
891 actor->x.fixed = PIXELS(1130);
892 actor->z.fixed = PIXELS(184);
894 Object_SetMode(actor, 3);
896 } else {
898 }
899
900 if (Engine_GameFlagIsSet(873) != 0) {
901 actor = Object_GetById(LONG_LOG);
902 Object_SetMode(actor, 8);
904 Map_CopyCellAttributes(86, 10, 1, 2, 84, 10);
905 Map_CopyCellAttributes(86, 9, 1, 1, 84, 12);
906 } else {
907 actor = Object_GetById(LONG_LOG);
908 Map_CopyCellAttributes(85, 9, 1, 4, actor->x.fixed >> 20, 9);
909 Map_CopyCellAttributes(85, 9, 1, 4, actor->x.fixed >> 20, 61);
910 }
911
913 actor->motionFlags = 0;
916 actor->motionFlags = 0;
919 actor->motionFlags = 0;
926
927 // Enter the race, solo practice, course tour or post-battle reunion.
928 switch (gGameState.entrance) {
929 case 1:
930 Colosso_StartRaceGauge(0, 8, 6, PIXELS(1512), PIXELS(192), 39, 40);
931 Map_CopyCellsLayered(127, 0, 1, 2, 5, 2);
945 }
950 break;
951
952 case 2:
957 break;
958 }
962 break;
963
964 case 3:
966 break;
967 }
970 break;
971
972 case 4:
977 break;
978
979 case 5:
983 break;
984 }
985 return 0;
986}
987
988/// Advances a reunion particle; timer and work hold signed 1/256-pixel steps.
990 struct ScriptInterpreter *interpreter) {
991 struct FieldActor *particle = (struct FieldActor *)interpreter;
992 particle->x.fixed += particle->timer * 256;
993 particle->y.fixed += (s16)particle->work * 256;
994 particle->scaleX += Q16_ONE / 40;
995 particle->scaleY += Q16_ONE / 40;
996 particle->timer += 5;
997 particle->work = (s16)particle->work - 1;
998 return 0;
999}
1000
1001/// Shows one of three reunion particles at its scheduled point in the cycle.
1003 struct FieldActor *particle;
1004 struct FieldActor *source;
1005 s32 x;
1006 s32 y;
1007 s32 kind;
1008 s32 count;
1009
1010 particle = Object_GetById(0);
1011 count = gColossoParticleCount + 1;
1012 kind = 41;
1013 x = particle->x.fixed;
1014 y = particle->y.fixed;
1015 gColossoParticleCount = count;
1016 switch (count % 180) {
1017 case 10:
1018 break;
1019 case 20:
1020 kind = 42;
1021 break;
1022 case 30:
1023 kind = 43;
1024 break;
1025 default:
1026 return;
1027 }
1028 particle = Object_GetById(kind);
1029 if (particle == 0) {
1030 return;
1031 }
1032 source = Object_GetById(0);
1033 if (source != 0) {
1034 Engine_ActorSetPosition(kind, source->x.fixed, source->z.fixed);
1035 }
1037 particle->motionFlags = 0;
1038 particle->scaleX = 2 * Q16_ONE / 5;
1039 particle->scaleY = 2 * Q16_ONE / 5;
1040 {
1041 s32 height = PIXELS(4);
1042 particle->x.fixed = x + height;
1043 height += y;
1044 particle->y.fixed = height;
1045 particle->targetY = height;
1046 }
1047 particle->timer = 25;
1048 particle->work = 128;
1050}
1051
1052/// Reunites the party after the battle and plays the resting conversation.
1053static void ColossoLog_PlayPostBattleReunion(s32 battleResult) {
1054 struct FieldActor *actor;
1055 const s32 *leaderScaleScript;
1056 SchedulerCallback particleCallback;
1057
1058 // Place the rival and companions around the resting leader.
1065 if (battleResult < 0) {
1067 } else {
1069 }
1073 {
1074 u16 shown = 0;
1075
1076 actor->facing = shown;
1077 }
1080 Actor_SetSpeed(1, PIXELS(1), PIXELS(1) / 2);
1081 Actor_SetSpeed(IVAN, PIXELS(1), PIXELS(1) / 2);
1082 Actor_SetSpeed(MIA, PIXELS(1), PIXELS(1) / 2);
1083 Actor_SetPosition(GARET, PIXELS(1464), PIXELS(184));
1084 Actor_SetPosition(IVAN, PIXELS(1464), PIXELS(200));
1085 Actor_SetPosition(MIA, PIXELS(1448), PIXELS(192));
1086 actor = Object_GetById(1);
1087 {
1088 u16 shown = 0;
1089
1090 actor->facing = shown;
1091 }
1092 actor = Object_GetById(2);
1093 {
1094 u16 shown = 0;
1095
1096 actor->facing = shown;
1097 }
1098 actor = Object_GetById(3);
1099 {
1100 u16 shown = 0;
1101
1102 actor->facing = shown;
1103 }
1104 Engine_TaskWait(1);
1110 Engine_EventSetMessage(MsgColossoIsaac);
1111 Engine_EventWait(60);
1112 leaderScaleScript = gColossoMultiPhaseData;
1113 Actor_SetActionScript(ACTOR_PARTY_LEADER, leaderScaleScript);
1115 actor->scaleX = Q16_ONE;
1117 actor->scaleY = Q16_ONE;
1120 actor->x.fixed += PIXELS(3);
1121 Engine_EventWait(10);
1124 Engine_EventWait(20);
1126 // Let each companion react before the leader settles back to sleep.
1128 Engine_EventWait(20);
1129 Actor_WalkToAndWait(1, 1504, 176);
1131 Engine_ActorShowEmote(1, 0x100, 20);
1134 Engine_EventWait(30);
1135 Actor_WalkToAndWait(IVAN, 1488, 176);
1136 Actor_WalkTo(GARET, 1520, 184);
1137 Actor_WalkToAndWait(IVAN, 1504, 176);
1142 Engine_EventWait(10);
1144 Engine_EventWait(30);
1146 Engine_EventWait(30);
1150 Actor_WalkToAndWait(MIA, 1488, 184);
1153 Actor_ShowEmote(GARET, 0x102, 60);
1156 Engine_EventWait(40);
1158 Engine_EventWait(10);
1161 Engine_EventWait(20);
1166 Engine_EventWait(20);
1170 Engine_EventWait(20);
1174 Engine_EventWait(20);
1176 Actor_SetActionScript(ACTOR_PARTY_LEADER, leaderScaleScript);
1177 Engine_EventWait(60);
1179 // Time the small reunion effects to the companions' reactions.
1181 Task_AddCallback(particleCallback, 0xc80);
1183 Engine_TaskRemoveCallback(particleCallback);
1184 Engine_EventWait(55);
1185 Actor_ShowEmote(GARET, 0x101, 60);
1186 Task_AddCallback(particleCallback, 0xc80);
1187 Engine_EventWait(20);
1188 Engine_TaskRemoveCallback(particleCallback);
1189 Engine_EventWait(40);
1190 Actor_ShowEmote(IVAN, 0x101, 60);
1192 Task_AddCallback(particleCallback, 0xc80);
1193 Engine_EventWait(35);
1194 Engine_TaskRemoveCallback(particleCallback);
1195 Engine_EventWait(25);
1196 Actor_ShowEmote(MIA, 0x102, 60);
1198 Task_AddCallback(particleCallback, 0xc80);
1199 Engine_EventWait(35);
1200 Engine_TaskRemoveCallback(particleCallback);
1201 Engine_EventWait(25);
1202 Actor_ShowEmote(2, 0x102, 60);
1205 Engine_EventWait(60);
1209 Task_AddCallback(particleCallback, 0xc80);
1210 Engine_EventWait(35);
1211 Engine_TaskRemoveCallback(particleCallback);
1212 Engine_EventWait(25);
1213 Actor_ShowEmote(MIA, 0x108, 60);
1220 Task_AddCallback(particleCallback, 0xc80);
1224 Engine_EventWait(60);
1225 // The companions begin to leave, then discuss the sleeping leader off-screen.
1226 Actor_WalkTo(MIA, 1464, 200);
1228 Actor_WalkTo(IVAN, 1368, 184);
1230 Actor_WalkToAndWait(GARET, 1512, 184);
1231 Actor_WalkTo(GARET, 1368, 184);
1235 Engine_EventWait(60);
1236 Actor_WalkToAndWait(MIA, 1432, 200);
1237 Actor_WalkTo(MIA, 1368, 184);
1240 Engine_EventWait(30);
1241 Actor_SetPosition(GARET, PIXELS(1512), PIXELS(176));
1242 Actor_SetPosition(IVAN, PIXELS(1464), PIXELS(192));
1243 Actor_SetPosition(MIA, PIXELS(1560), PIXELS(200));
1247 Engine_EventSetMessage(MsgColossoIsaacFellAsleep);
1251 Engine_EventWait(60);
1253}
1254
1255/// Stages the party behind the guide for the introduction to the third finals.
1257 s32 guideZ;
1258 s32 guideX;
1259 struct FieldActor *actor;
1260
1261 actor = Object_GetById(guideId);
1262 guideX = actor->x.part.pixel;
1263 guideZ = actor->z.part.pixel;
1265 Actor_SetSpeed(guideId, PIXELS(1), PIXELS(1) / 2);
1266 Actor_SetSpeed(0, PIXELS(1), PIXELS(1) / 2);
1267 Actor_SetSpeed(1, PIXELS(1), PIXELS(1) / 2);
1268 Actor_SetSpeed(2, PIXELS(1), PIXELS(1) / 2);
1269 Actor_SetSpeed(3, PIXELS(1), PIXELS(1) / 2);
1271 (PIXELS(guideZ) - PIXELS(48)));
1272 Engine_ActorSetPosition(1, PIXELS(guideX) - PIXELS(16),
1273 PIXELS(guideZ) - PIXELS(40));
1274 Engine_ActorSetPosition(2, PIXELS(guideX) + PIXELS(16),
1275 PIXELS(guideZ) - PIXELS(40));
1276 Engine_ActorSetPosition(3, PIXELS(guideX), (PIXELS(guideZ) - PIXELS(32)));
1277 Engine_ActorSetPosition(guideId, PIXELS(guideX),
1278 (PIXELS(guideZ) - PIXELS(80)));
1280 actor->facing = FACING_NORTH;
1284 Engine_EventSetMessage(MsgColossoSiteThirdFinals);
1286 Engine_EventShowMessage(guideId, 0);
1288 Engine_EventShowMessage(guideId, 0);
1290 Engine_EventShowMessage(guideId, 0);
1292 Engine_EventShowMessage(guideId, 0);
1300 if (actor != 0) {
1301 Engine_ActorSetDestination(1, actor->x.part.pixel, actor->z.part.pixel);
1302 }
1305 if (actor != 0) {
1306 Engine_ActorSetDestination(2, actor->x.part.pixel, actor->z.part.pixel);
1307 }
1310 if (actor != 0) {
1311 Engine_ActorSetDestination(3, actor->x.part.pixel, actor->z.part.pixel);
1312 }
1313 Engine_ActorWalkToAndWait(guideId, (guideX - 16), (guideZ - 64));
1314 Engine_ActorSetPosition(1, 0, 0);
1315 Engine_ActorSetPosition(2, 0, 0);
1316 Engine_ActorSetPosition(3, 0, 0);
1317 Engine_ActorWalkToAndWait(guideId, (guideX - 16), (guideZ - 16));
1318 Engine_ActorWalkToAndWait(guideId, guideX, guideZ);
1321}
1322
1323/// The Scales of Justice's attendant: the first time, the pans are shown; then
1324/// the objective.
1325static void Event_TalkToScalesAttendant(s32 guideId) {
1326 struct FieldActor *pan1;
1327 struct FieldActor *pan2;
1328 struct FieldActor *back1;
1329 struct FieldActor *back2;
1330 s32 promptResult;
1331
1332 if (gGameState.entrance == 2) {
1333 Colosso_AskDoneCheering(guideId);
1334 return;
1335 }
1337 promptResult = Colosso_GreetAtStage(guideId, 1);
1338 if (promptResult == 0) {
1339 // Point out the pans, demonstrate both heights, then restore the course.
1340 Engine_EventSetMessage(MsgColossoStageCalledScales);
1342 Engine_CameraMoveTo(PIXELS(152), -1, PIXELS(200), 1);
1344 Engine_EventWait(30);
1345 Engine_EventShowMessage(guideId, 0);
1346 Colosso_ShowPointer(104, 68, 0);
1347 Engine_EventWait(60);
1348 Colosso_MovePointer(168, 96, 10);
1349 Engine_EventWait(70);
1350 Engine_EventShowMessage(guideId, 0);
1352 Engine_TaskWait(2);
1354 pan1->motionFlags = 0;
1357 pan2->motionFlags = 0;
1360 Engine_EventWait(45);
1362 back1->motionFlags = 0;
1363 ColossoLog_MoveOnScales(back1, PIXELS(32));
1365 back2->motionFlags = 0;
1368 Engine_EventWait(15);
1369 Engine_EventShowMessage(guideId, 0);
1370 Colosso_ShowPointer(104, 68, 0);
1371 Engine_EventWait(30);
1372 Colosso_MovePointer(168, 96, 10);
1373 Engine_EventWait(40);
1374 Colosso_MovePointer(104, 68, 10);
1375 Engine_EventWait(70);
1376 Engine_EventShowMessage(guideId, 0);
1378 Engine_TaskWait(2);
1380 Colosso_RepeatStageNumber(guideId, 1);
1381 } else if (promptResult == 1) {
1382 Engine_EventSetMessage(MsgColossoObjectiveGetAcross);
1383 Engine_EventShowMessage(guideId, 0);
1384 }
1385 Colosso_OfferCheeringSpot(promptResult, guideId, 1);
1387}
1388
1389/// The Stepping-Stone Stage's attendant: the first time, a warrior finds the
1390/// way; then the objective.
1392 s32 promptResult;
1393 s32 x;
1394
1395 if (gGameState.entrance == 2) {
1396 Colosso_AskDoneCheering(guideId);
1397 return;
1398 }
1400 promptResult = Colosso_GreetAtStage(guideId, 2);
1401 if (promptResult == 0) {
1402 Engine_EventSetMessage(MsgColossoSteppingStoneStage);
1403 Camera_SetSpeed(PIXELS(3), PIXELS(3) / 8);
1404 Camera_MoveTo(PIXELS(376), -1, PIXELS(152), 1);
1405 x = 280;
1407 Engine_EventWait(30);
1408 Event_ShowMessage(guideId, 0);
1409 Colosso_FadeInCompetitor(0, x, 200);
1412 Colosso_WalkActorToAndStand(0, 296, 152);
1413 Engine_EventWait(10);
1415 Camera_MoveTo(-1, -1, -1, 0);
1418 Camera_MoveTo(-1, -1, -1, 0);
1421 Camera_MoveTo(-1, -1, -1, 0);
1423 Event_ShowMessage(guideId, 0);
1424 Colosso_ShowPointer(96, 40, 0);
1425 Colosso_MovePointer(128, 40, 10);
1426 Engine_EventWait(30);
1427 Colosso_MovePointer(160, 40, 10);
1428 Engine_EventWait(30);
1429 Colosso_MovePointer(160, 72, 10);
1430 Engine_EventWait(30);
1431 Event_ShowMessage(guideId, 0);
1435 Colosso_RepeatStageNumber(guideId, 2);
1436 } else if (promptResult == 1) {
1437 Engine_EventSetMessage(MsgColossoYourGoalInStageSimple);
1438 Event_ShowMessage(guideId, 0);
1439 }
1440 Colosso_OfferCheeringSpot(promptResult, guideId, 2);
1442}
1443
1444/// The Wall Wedge's attendant: the first time, a warrior times his way through
1445/// the moving wall; then that its operator will cheer for Isaac.
1447 struct EventWork *work;
1448 s32 promptResult;
1449
1450 if (gGameState.entrance == 2) {
1451 Colosso_AskDoneCheering(guideId);
1452 } else {
1454 promptResult = Colosso_GreetAtStage(guideId, 3);
1455 if (promptResult == 0) {
1456 // Show the pattern cycle before demonstrating a timed passage.
1457 work = gEventWork;
1458 Engine_EventSetMessage(MsgColossoPlaceCalledWall);
1461 Engine_CameraMoveTo(PIXELS(616), -1, PIXELS(184), 1);
1463 Engine_EventWait(30);
1464 Event_ShowMessage(guideId, 0);
1466 Engine_EventWait(60);
1467 Engine_EventShowMessage(guideId, 0);
1468 Colosso_FadeInCompetitor(0, 504, 200);
1469 // UB: the void target is called through an incompatible return type.
1470 /* FAKEMATCH: called through a cast to the s32 call type the bytes show,
1471 * its result discarded, so r0 loads last; as a direct call, 3
1472 * instructions differ in tbs-en. */
1475 Actor_SetSpeed(0, PIXELS(3) / 2, PIXELS(3) / 4);
1476 Colosso_WalkActorTo(0, 680, 200);
1477 if (work->raisedTrigger != 5) {
1478 do {
1479 Engine_TaskWait(1);
1480 if (++promptResult > 239) {
1481 break;
1482 }
1483 } while (work->raisedTrigger != 5);
1484 }
1487 Actor_ShowEmote(0, 0x103, 60);
1488 Engine_EventShowMessage(guideId, 0);
1491 Colosso_RepeatStageNumber(guideId, 3);
1492 work->raisedTrigger = 0;
1493 } else if (promptResult == 1) {
1494 Engine_EventSetMessage(MsgColossoOperatorWallsCheer);
1495 Engine_EventShowMessage(guideId, 0);
1496 }
1497 Colosso_OfferCheeringSpot(promptResult, guideId, 3);
1499 }
1500}
1501
1502/// The Free-Climb Area's attendant: the first time, a warrior climbs across;
1503/// then the objective.
1505 s32 result;
1506 struct FieldActor *actor;
1507 s32 x;
1508 s32 y;
1509 s32 raisedHeight;
1510 s32 shiftedX;
1511
1512 if (gGameState.entrance == 2) {
1513 Colosso_AskDoneCheering(guideId);
1514 } else {
1516 result = Colosso_GreetAtStage(guideId, 4);
1517 if (result == 0) {
1518 Engine_EventSetMessage(MsgColossoPlaceNormallyCalledFreeClimb);
1519 Camera_SetSpeed(PIXELS(3), PIXELS(3) / 8);
1520 Camera_MoveTo(PIXELS(856), -1, PIXELS(168), 1);
1522 Engine_EventWait(30);
1523 Event_ShowMessage(guideId, 0);
1524 Event_ShowMessage(guideId, 0);
1525 Colosso_FadeInCompetitor(0, 816, 200);
1529 Field_ClimbUp();
1530 Camera_MoveTo(-1, -1, -1, 0);
1533 y = actor->y.fixed;
1534 x = actor->x.fixed;
1537 raisedHeight = PIXELS(6) + y;
1538 Engine_ObjectSetPosition(actor, x, raisedHeight, actor->z.fixed);
1541 shiftedX = PIXELS(64) + x;
1542 Engine_ObjectSetPosition(actor, shiftedX, raisedHeight, actor->z.fixed);
1545 Engine_ObjectSetPosition(actor, shiftedX, y + PIXELS(54), actor->z.fixed);
1548 Engine_ObjectSetPosition(actor, x + PIXELS(48), y + PIXELS(54),
1549 actor->z.fixed);
1552 Event_ShowMessage(guideId, 0);
1555 Colosso_RepeatStageNumber(guideId, 4);
1556 } else if (result == 1) {
1557 Engine_EventSetMessage(MsgColossoClearStageMustAbleChange);
1558 Event_ShowMessage(guideId, 0);
1559 }
1560 Colosso_OfferCheeringSpot(result, guideId, 4);
1562 }
1563}
1564
1565// DispatchObject is the engine's script-control view of these same actors.
1566
1567/// Starts a scripted pixel destination while preserving the actor height.
1569 struct FieldActor *actor;
1570
1571 actor = Engine_ActorLookup(selector);
1572 if (actor != 0) {
1574 Object_SetMode(actor, 5);
1575 Engine_ObjectSetPosition(actor, x << 16, actor->y.fixed, z << 16);
1576 }
1577}
1578
1579/// Moves to a scripted pixel destination, waits, then restores the idle mode.
1581 s32 z) {
1582 struct FieldActor *actor;
1583
1584 actor = Engine_ActorLookup(selector);
1585 if (actor != 0) {
1587 Object_SetMode(actor, 5);
1588 Engine_ObjectSetPosition(actor, x << 16, actor->y.fixed, z << 16);
1590 Object_SetMode(actor, 1);
1591 }
1592}
1593
1594/// The Moving Sidewalk Stage's attendant: the first time, a warrior walks
1595/// against the belt; then the objective.
1597 s32 i;
1598 s32 result;
1599 struct FieldActor *actor;
1600
1601 if (gGameState.entrance == 2) {
1602 Colosso_AskDoneCheering(guideId);
1603 } else {
1605 result = Colosso_GreetAtStage(guideId, 5);
1606 if (result == 0) {
1607 // Walk against the sidewalk, then show how its current pushes the rider.
1608 Engine_EventSetMessage(MsgColossoCalledMovingSidewalkStage);
1609 Camera_SetSpeed(PIXELS(3), PIXELS(3) / 8);
1610 Camera_MoveTo(PIXELS(1080), -1, PIXELS(168), 1);
1612 Engine_EventWait(30);
1613 Event_ShowMessage(guideId, 0);
1614 Event_ShowMessage(guideId, 0);
1615 Colosso_FadeInCompetitor(0, 984, 184);
1620 Engine_EventWait(120);
1622 Engine_EventWait(120);
1625#if !TBS_PATCH_3
1627#endif
1630 for (i = 119; i >= 0; i--) {
1631 if (actor->x.fixed > PIXELS(992)) {
1632 actor->x.fixed -= PIXELS(6) / 5;
1633 }
1634 Engine_TaskWait(1);
1635 }
1638 Event_ShowMessage(guideId, 0);
1643 Colosso_RepeatStageNumber(guideId, 5);
1644 } else if (result == 1) {
1645 Engine_EventSetMessage(MsgColossoInStageMustTryOutpace);
1646 Event_ShowMessage(guideId, 0);
1647 }
1648 Colosso_OfferCheeringSpot(result, guideId, 5);
1650 }
1651}
1652
1653/// The log-rolling area's attendant: the first time, a marker traces the log's
1654/// route; then the objective.
1656 s32 state;
1657
1658 if (gGameState.entrance == 2) {
1660 return;
1661 }
1662
1664 state = Colosso_GreetAtStage(actor, 6);
1665
1666 if (state == 0) {
1667 Engine_EventSetMessage(MsgColossoAnotherLogRollingArea);
1669 Engine_CameraMoveTo(PIXELS(1288), -1, PIXELS(152), 1);
1671 Engine_EventWait(30);
1672 Engine_EventShowMessage(actor, 0);
1673 Colosso_ShowPointer(180, 88, 0);
1674 Engine_EventWait(60);
1675 Engine_EventShowMessage(actor, 0);
1676 Colosso_MovePointer(32, 84, 10);
1677 Engine_EventWait(30);
1678 Engine_EventShowMessage(actor, 0);
1679 Colosso_MovePointer(96, 84, 30);
1680 Engine_EventWait(60);
1681 Engine_EventShowMessage(actor, 0);
1685 Colosso_RepeatStageNumber(actor, 6);
1686 } else if (state == 1) {
1687 Engine_EventSetMessage(MsgColossoHereMustFigureOutHow);
1688 Engine_EventShowMessage(actor, 0);
1689 }
1690
1691 Colosso_OfferCheeringSpot(state, actor, 6);
1693}
1694
1695#include "common/colosso_solo.h"
1696#include "common/item_equip.h"
1697#include "common/colosso_task.h"
1698
1699/// Selects the portrait task script and clears its movement state.
1701 s32 handler;
1702
1704 gColosso_LetteringParam = (parameter << 4);
1705
1706 {
1707 s32 budget = 0xc80;
1708 SchedulerCallback task = Colosso_UpdateLettering;
1709 FieldScheduler_AddCallback(task, budget);
1710 }
1711
1712 handler = (s32)gColossoModeScriptDefault;
1713 if (mode == 2) {
1714 handler = (s32)gColossoModeScript2;
1715 }
1716 if (mode == 4) {
1717 handler = (s32)gColossoModeScript4;
1718 }
1719 if (mode == 3) {
1720 if (parameter != 0) {
1721 handler = (s32)gColossoModeScript3B;
1722 } else {
1723 handler = (s32)gColossoModeScript3A;
1724 }
1725 }
1726
1728 gColosso_LetteringScript = (s16 *)handler;
1732}
1733
1734/// Plays the countdown portraits and the start-of-race transition.
1736 if (mode == 0) {
1740 Engine_EventWait(30);
1742 Colosso_LoadLettering(0);
1744 Engine_EventWait(120);
1746 return;
1747 }
1748
1753 {
1755 *(s16 *)((u8 *)base + 30) = (mode * 60);
1756 }
1757 Engine_EventWait(30);
1758 Engine_AudioPlayCue(mode + 0x5a);
1759 Colosso_LoadLettering(mode);
1761 Engine_EventWait(120);
1762
1763 while (AudioCommand_GetStateByte() != 0) {
1764 Engine_TaskWait(1);
1765 }
1766
1768 Colosso_LoadLettering(5);
1771 Engine_EventWait(60);
1774 Engine_EventWait(60);
1775 Colosso_LoadLettering(6);
1778 Engine_EventWait(60);
1779 Colosso_LoadLettering(7);
1784 Engine_GameFlagSet(0x123);
1785}
1786
1787/// Unused portrait countdown for a signed number of seconds.
1789 s32 actorId;
1790
1794 gColossoModeScript3A[13] = countdown * 60;
1796 (countdown < 0 ? -countdown : countdown) * 60;
1797 if (countdown < 0) {
1798 Engine_EventWait(30);
1800 Colosso_LoadLettering(8);
1801 // UB: the void target is called through an incompatible return type.
1802 /* FAKEMATCH: called through a cast to the s32 call type the bytes show, its
1803 * result discarded, so r1 loads before r0; as a direct call, 2
1804 * instructions differ in tbs-en. */
1806 Engine_EventWait(-countdown * 60 + 60);
1807 actorId = 0;
1808 } else {
1809 Engine_EventWait(30);
1810 Engine_AudioPlayCue(countdown + 90);
1811 Colosso_LoadLettering(4);
1812 // UB: the void target is called through an incompatible return type.
1813 /* FAKEMATCH: called through the s32 cast, its result discarded, as in the
1814 * first arm; as a direct call, 2 instructions differ in tbs-en. */
1816 Engine_EventWait(countdown * 60 + 60);
1817 actorId = 8;
1818 }
1819 Engine_ActorShowEmote(actorId, 0x105, 0);
1820 while (AudioCommand_GetStateByte() != 0) {
1821 Engine_TaskWait(1);
1822 }
1824 Engine_EventWait(30);
1828}
1829
1830#include "common/colosso_marker.h"
1832
1833/// Writes eight hexadecimal digits followed by a terminator.
1834UNUSED static void WriteU32AsHex(u8 *hexText, u32 value) {
1835 s32 digitIndex;
1836
1837 hexText += 8;
1838 *hexText = 0;
1839 hexText--;
1840 for (digitIndex = 7; digitIndex >= 0; digitIndex--) {
1841 *hexText = gColossoHexChars[value & 15];
1842 value >>= 4;
1843 hexText--;
1844 }
1845}
1846
1848
1849/// Marks the rival path recorder as finished.
1851 struct PathRecorder *recorder = (struct PathRecorder *)gSceneState;
1852
1853 recorder->mode = 9;
1854}
1855
1856/// Waits until the rival path recorder reaches its finished mode.
1858 struct PathRecorder *recorder = (struct PathRecorder *)gSceneState;
1859
1860 while (recorder->mode != 9) {
1861 Engine_TaskWait(1);
1862 }
1863}
1864
1865/// Occasionally scatters an effect around a moving source actor.
1866static void
1868 struct FieldActor *source = (struct FieldActor *)fieldObject;
1869
1870 s32 position[3];
1871 u32 randomValue;
1872
1873 if (source->velocityY >= -255 && source->velocityY <= 255) {
1874 source->motionFlags = 0;
1875 }
1876 randomValue = Engine_RandomNext();
1877 if (randomValue * 100 >> 16 <= 9) {
1878 struct FieldActor *effect;
1879 s32 angle;
1880 s32 radius;
1881
1882 SET_VECTOR(position, source->x.fixed, source->y.fixed, source->z.fixed);
1883 angle = Engine_RandomNext();
1885 Vector_AddPolarOffset(angle << 4, radius, position);
1886 {
1887 s32 x = position[0];
1888 s32 y = position[1];
1889 s32 z = position[2];
1890
1891 effect = Engine_ObjectCreate(285, x, y, z);
1892 }
1893 if (effect != 0) {
1894 effect->motionFlags = 0;
1895 Engine_ActorSetSpriteFlags(effect, 0);
1897 Object_SetMode(effect, 1);
1898 Object_SetMode(effect, 0);
1899 }
1900 }
1901}
1902
1903/// Raises the linked item actor and clears the source link.
1905 struct ScriptInterpreter *interpreter) {
1906 struct FieldActor *source = (struct FieldActor *)interpreter;
1907
1908 struct FieldActor *effect = Object_GetById(source->timer);
1909
1910 Engine_ObjectSetPosition(effect, source->x.fixed,
1911 source->y.fixed + PIXELS(36), source->z.fixed);
1912 effect->motionFlags = 0;
1915 source->timer = 0;
1916 return 0;
1917}
1918
1919/// Moves to the available finish item, equips it and announces it.
1920static s32 ColossoLog_CollectFinishEquipment(s32 firstItem, s32 secondItem) {
1921 struct ColossoGaugeWork *work = (struct ColossoGaugeWork *)gColossoWork;
1922 struct FieldActor *actor;
1923 s32 rivalFinishedFirst;
1924 s32 x;
1925 s32 z;
1926 u16 *itemActorId;
1927 s16 *linkedItemActor;
1928
1929 rivalFinishedFirst = Engine_GameFlagIsSet(FLAG_SCENE_TEMP_11);
1931 if (work->finishX < actor->x.fixed) {
1932 x = work->finishX + PIXELS(12);
1933 } else {
1934 x = work->finishX - PIXELS(12);
1935 }
1936 if (rivalFinishedFirst != 0) {
1937 z = work->finishZ + PIXELS(16);
1938 itemActorId = &work->finishItemActorB;
1939 } else {
1940 z = work->finishZ - PIXELS(16);
1941 itemActorId = &work->finishItemActorA;
1942 }
1943 linkedItemActor = &actor->timer;
1944 *linkedItemActor = *itemActorId;
1945 actor->acceleration = PIXELS(1) / 4;
1946 actor->speed = PIXELS(1);
1947 Engine_ObjectSetPosition(actor, x, 0, z);
1950 while (*linkedItemActor != 0) {
1951 Engine_TaskWait(1);
1952 }
1953 if (rivalFinishedFirst == 0) {
1954 // UB: the void target is called through an incompatible return type.
1955 /* FAKEMATCH: the void function is called as returning s32, which loads r1
1956 * before r0; by its prototype, 2 instructions differ in tbs-en. */
1958 UiWork_PushValueSlot(firstItem, 2);
1959 } else {
1960 // UB: the void target is called through an incompatible return type.
1961 /* FAKEMATCH: called as returning s32, as in the first arm; by its
1962 * prototype, 2 instructions differ in tbs-en. */
1964 UiWork_PushValueSlot(secondItem, 2);
1965 }
1967 Engine_MessageShowCentered(MsgColossoIsaacGotItem, 3);
1969 return rivalFinishedFirst;
1970}
1971
1973#include "common/colosso_setup.h"
1975#include "common/object_findslot.h"
1976
1977/// Pushes a neighboring actor one cell when its destination and overhead are
1978/// clear.
1979static void ColossoLog_PushActorAhead(void) {
1980 struct FieldActor *subject;
1981 struct FieldActor *target;
1982 struct FieldActor *blocker;
1983 u32 step;
1984 u32 direction;
1985 struct FieldPosition position;
1986 s32 zero;
1987 s32 subjectHandle;
1988
1989 subjectHandle = gGameState.selectedActor;
1990 subject = Object_GetById(subjectHandle);
1991
1992 direction = subject->facing >> 12;
1993
1994 step = gStagedActor_DirectionSteps[direction];
1995 position.x = subject->x.fixed + (step & 0xffff0000);
1996 position.y = subject->y.fixed;
1997 step <<= 16;
1998 position.z = subject->z.fixed + step;
1999
2000 target = SceneData_FindSlotAtPosition(&position, subject);
2001 if (target == 0) {
2002 return;
2003 }
2004
2005 step = gStagedActor_DirectionSteps[direction];
2006 position.x = target->x.fixed + (step & 0xffff0000);
2007 position.y = target->y.fixed;
2008 step <<= 16;
2009 position.z = target->z.fixed + step;
2010
2011 blocker = SceneData_FindSlotAtPosition(&position, target);
2012 if (blocker != 0 && (blocker->collisionFlags & 1) != 0) {
2013 return;
2014 }
2015
2016 position.x = target->x.fixed;
2017 position.y = target->y.fixed + PIXELS(16);
2018 position.z = target->z.fixed;
2019
2020 blocker = SceneData_FindSlotAtPosition(&position, target);
2021 if (blocker != 0 && (blocker->collisionFlags & 1) != 0) {
2022 return;
2023 }
2024
2025 target->terrainId = 2;
2026 zero = 0;
2027
2028 step = gStagedActor_DirectionSteps[direction];
2029 position.x = target->x.fixed + (step & 0xffff0000);
2030 position.y = target->y.fixed;
2031 step <<= 16;
2032 position.z = target->z.fixed + step;
2033
2034 if (FieldObject_CheckMovementCollision(target, &position) > 0) {
2035 return;
2036 }
2037
2038 Object_SetMode(subject, 8);
2039 Engine_TaskWait(15);
2040
2041 target->speed = PIXELS(1) / 5;
2042 target->acceleration = PIXELS(1) / 5;
2043 Engine_ObjectSetPosition(target, position.x, position.y, position.z);
2044
2045 subject->speed = PIXELS(1) / 5;
2046 subject->acceleration = PIXELS(1) / 5;
2047 Engine_ObjectSetPosition(subject, position.x, position.y, position.z);
2048
2052
2053 target->x.fixed = position.x;
2054 target->z.fixed = position.z;
2055 target->velocityX = zero;
2056 target->velocityZ = zero;
2057
2058 Object_SetMode(subject, 1);
2059}
2060
2062
2064 SC_SET(SW_Y, PIXELS(1)), SC_WAIT(10), SC_SET(SW_Y, 0), SC_WAIT(10),
2066};
2067
2069 {7, 5, 7, 5, 7, 11},
2070 {4, 6, 4, 6, 4, 10},
2071 {5, 7, 5, 7, 5, 12},
2072 {6, 4, 6, 4, 6, 10},
2073};
2074
2075// clang-format off
2077 0, 0, 0x4000, 0x8000, 0x8000, 0x8000, 0xc000, 0,
2078};
2079
2081 SC_MOVE(PIXELS(1088), 0, PIXELS(184)),
2082 SC_SYNC,
2083 SC_MOVE(PIXELS(1130), 0, PIXELS(184)),
2084 SC_SYNC,
2086 SC_LABEL(1),
2087 SC_SET(SW_Y, PIXELS(1)),
2088 SC_WAIT(10),
2089 SC_SET(SW_Y, 0),
2090 SC_WAIT(10),
2092};
2093
2095#if LANGUAGE == LANGUAGE_JAPANESE || LANGUAGE == LANGUAGE_ENGLISH
2096 0, 32, 32, 32, 96, 64, 64, 64, 128, 0,
2097#else
2098 0, 32, 32, 32, 96, 64, 64, 160, 128, 0,
2099#endif
2100};
2101
2103 0x1000, 512, 1, 0x2000, 0, 1, 0x1000, 256,
2104 6, 0x2000, 16, 6, 0x7fff, 30, 0x2000, 0,
2105 30, 0x7fff, 30, -1,
2106};
2107
2109 0x1000, 128, 1, 0x2000, 0, 1, 0x1000, 256,
2110 6, 0x2000, 16, 6, 0x7fff, 60, 0x1000, 384,
2111 6, 0x7fff, 6, 0x1000, 240, 6, 0x7fff, 6,
2112 0x1000, 368, 6, 0x7fff, 6, 0x1000, 224, 6,
2113 0x7fff, 6, 0x2000, 0, 30, 0x1000, 352, 6,
2114 0x7fff, 6, 0x1000, 208, 6, 0x7fff, 6, 0x1000,
2115 336, 6, 0x7fff, 6, 0x1000, 192, 6, 0x7fff,
2116 6, 0x1000, 320, 6, 0x7fff, 6, -1,
2117};
2118
2119char gColossoHexChars[20] = "0123456789ABCDEF";
2120
2122 SC_ADD(SW_Y, -(PIXELS(1) / 4)),
2123 SC_WAIT(1),
2124 SC_LOOP(60, SC_TOP),
2125 SC_FREE,
2126};
2127
2130 SC_LABEL(1),
2131 SC_WAIT(10),
2132 SC_SET(SW_SCALE_X, 11 * Q16_ONE / 8),
2133 SC_SET(SW_SCALE_Y, 11 * Q16_ONE / 8),
2134 SC_WAIT(2),
2135 SC_SET(SW_SCALE_X, 3 * Q16_ONE / 2),
2136 SC_SET(SW_SCALE_Y, 3 * Q16_ONE / 2),
2137 SC_WAIT(2),
2138 SC_SET(SW_SCALE_X, 9 * Q16_ONE / 8),
2139 SC_SET(SW_SCALE_Y, 9 * Q16_ONE / 8),
2140 SC_WAIT(2),
2143 SC_WAIT(2),
2144 SC_SET(SW_SCALE_X, 11 * Q16_ONE / 8),
2145 SC_SET(SW_SCALE_Y, 11 * Q16_ONE / 8),
2146 SC_WAIT(2),
2147 SC_SET(SW_SCALE_X, 3 * Q16_ONE / 2),
2148 SC_SET(SW_SCALE_Y, 3 * Q16_ONE / 2),
2149 SC_WAIT(2),
2150 SC_SET(SW_SCALE_X, 9 * Q16_ONE / 8),
2151 SC_SET(SW_SCALE_Y, 9 * Q16_ONE / 8),
2152 SC_WAIT(2),
2155 SC_WAIT(2),
2156 SC_WAIT(50),
2157 SC_LOOP(2, SC_TO(1)),
2158 SC_POS(0, 0, 0),
2159 SC_SET(SW_HOOK, 0),
2160 SC_END,
2161};
2162
2163/// Pixel step by direction: X in the upper halfword, Z in the lower.
2164#define DIRECTION_STEP(x, z) ((u32)(x) << 16 | (u16)(z))
2165
2167 DIRECTION_STEP(16, 0),
2168 DIRECTION_STEP(16, 0),
2169 DIRECTION_STEP(16, 0),
2170 DIRECTION_STEP(0, 16),
2171 DIRECTION_STEP(0, 16),
2172 DIRECTION_STEP(0, 16),
2173 DIRECTION_STEP(0, 16),
2174 DIRECTION_STEP(-16, 0),
2175 DIRECTION_STEP(-16, 0),
2176 DIRECTION_STEP(-16, 0),
2177 DIRECTION_STEP(-16, 0),
2178 DIRECTION_STEP(0, -16),
2179 DIRECTION_STEP(0, -16),
2180 DIRECTION_STEP(0, -16),
2181 DIRECTION_STEP(0, -16),
2182 DIRECTION_STEP(16, 0),
2183};
2184
2186 { 0, CONDITION_ALWAYS, 88, 0, 104, FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
2187 { 1, CONDITION_ALWAYS, 88, 0, 104, FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
2188 { 2, CONDITION_ALWAYS, 136, 0, 392, FACING_NORTH, 0, -1, -1, -1, -1, 0 },
2189 { 4, CONDITION_ALWAYS, 88, 0, 104, FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
2190 { 5, CONDITION_ALWAYS, 88, 0, 104, FACING_SOUTH, 0, -1, -1, -1, -1, 0 },
2191 { SCENE_TABLE_END },
2192};
2193
2195 SCENE_EXITS(145),
2196 SCENE_EXIT(10, 145, 1),
2197 SCENE_EXIT(11, 140, 66),
2198 SCENE_EXIT(4, 138, 99),
2199 SCENE_EXIT(5, 138, 99),
2201};
2202
2205 PIXELS(88), 0, PIXELS(104), FACING_SOUTH, TALK_FACE_PARTY, 0 },
2207 0, 0, 0, FACING_NORTH, TALK_FACE_PARTY, 0 },
2209 0, 0, 0, FACING_NORTH, TALK_FACE_PARTY, 0 },
2211 0, 0, 0, FACING_NORTH, TALK_FACE_PARTY, 0 },
2213 0, 0, 0, FACING_WEST, TALK_FACE_PARTY, 0 },
2215 PIXELS(216), 0, PIXELS(200), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2216 { 0x122, CONDITION_ALWAYS, 7,
2217 PIXELS(152), 0, PIXELS(200), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2218 { 0x122, CONDITION_ALWAYS, 7,
2221 PIXELS(88), 0, PIXELS(168), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2223 PIXELS(312), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2225 PIXELS(712), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2227 PIXELS(1240), 0, PIXELS(136), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2229 PIXELS(1272), 0, PIXELS(168), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2231 PIXELS(1304), 0, PIXELS(200), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2232 { 0x123, CONDITION_ALWAYS, 7,
2233 PIXELS(536), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2234 { 0x123, CONDITION_ALWAYS, 7,
2235 PIXELS(568), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2236 { 0x123, CONDITION_ALWAYS, 7,
2237 PIXELS(600), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2238 { 0x123, CONDITION_ALWAYS, 7,
2239 PIXELS(632), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2240 { 0x123, CONDITION_ALWAYS, 7,
2241 PIXELS(664), 0, PIXELS(184), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2242 { 0x123, CONDITION_ALWAYS, 7,
2243 PIXELS(536), 0, PIXELS(216), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2244 { 0x123, CONDITION_ALWAYS, 7,
2245 PIXELS(568), 0, PIXELS(216), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2246 { 0x123, CONDITION_ALWAYS, 7,
2247 PIXELS(600), 0, PIXELS(216), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2248 { 0x123, CONDITION_ALWAYS, 7,
2249 PIXELS(632), 0, PIXELS(216), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2250 { 0x123, CONDITION_ALWAYS, 7,
2251 PIXELS(664), 0, PIXELS(216), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2253 PIXELS(720), 0, PIXELS(216), FACING_WEST, TALK_KEEP_FACING, 0 },
2255 PIXELS(792), 0, PIXELS(194), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2256 { 0x126, CONDITION_ALWAYS, 7,
2257 PIXELS(1080), 0, PIXELS(200), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2258 { 0xcd, CONDITION_ALWAYS, 7,
2259 PIXELS(1208), 0, PIXELS(176), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2271 PIXELS(1080), 0, PIXELS(312), FACING_SOUTH, TALK_FACE_PARTY_AND_BACK, 0 },
2273 PIXELS(1304), 0, PIXELS(312), FACING_SOUTH, TALK_FACE_PARTY_AND_BACK, 0 },
2275 PIXELS(1512), 0, PIXELS(176), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2277 PIXELS(1512), 0, PIXELS(208), FACING_SOUTH, TALK_KEEP_FACING, 0 },
2278 { 0x118, CONDITION_ALWAYS, ACTOR_STAND,
2279 0, 0, 0, FACING_EAST, TALK_FACE_PARTY, 0 },
2280 { 0x118, CONDITION_ALWAYS, ACTOR_STAND,
2282 { 0x118, CONDITION_ALWAYS, ACTOR_STAND,
2284 { SCENE_TABLE_END },
2285};
2286
2288
2290
2307 { SEARCH(SEARCH_CHEST), 101, 0x36a, FIND_ITEM(ITEM_SMOKE_BOMB) },
2308 { SEARCH(SEARCH_CHEST), 102, 0x36b, FIND_ITEM(ITEM_NUT) },
2309 { 0x8413, 103, 0x36c, FIND_ITEM(ITEM_SLEEP_BOMB) },
2323 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), GUIDE, CONDITION_ALWAYS, MSGNO(MsgColossoRiverThisYearsFinalsAreIncredibleThis) },
2324 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), SCALES_ATTENDANT, CONDITION_ALWAYS, MSGNO(MsgColossoLogTheStreetVendorsCornOnThe) },
2325 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), STEPPING_STONE_ATTENDANT, CONDITION_ALWAYS, MSGNO(MsgColossoLogICantSeeAnythingWhenIm) },
2326 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), WALL_WEDGE_ATTENDANT, CONDITION_ALWAYS, MSGNO(MsgColossoLogItsNotVeryExcitingWorkBut) },
2327 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), FREE_CLIMB_ATTENDANT, CONDITION_ALWAYS, MSGNO(MsgColossoLogStandingForLongPeriodsOfTime) },
2328 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), MOVING_SIDEWALK_ATTENDANT, CONDITION_ALWAYS, MSGNO(MsgColossoLogIWasUpAllNightTrying) },
2329 { PSYNERGY_ON_ACTOR(ABILITY_MIND_READ), LOG_ROLLING_ATTENDANT, CONDITION_ALWAYS, MSGNO(MsgColossoLogSomeTouristToldMeILook) },
2331 { SCENE_EVENTS_END },
2332};
2333
2335 SC_ADD(SW_SCALE_Y, 512),
2336 SC_ADD(SW_SCALE_X, -256),
2337 SC_WAIT(2),
2338 SC_ADD(SW_SCALE_Y, 512),
2339 SC_ADD(SW_SCALE_X, -256),
2340 SC_WAIT(2),
2341 SC_ADD(SW_SCALE_Y, 512),
2342 SC_ADD(SW_SCALE_X, -256),
2343 SC_WAIT(4),
2344 SC_ADD(SW_SCALE_Y, -512),
2345 SC_ADD(SW_SCALE_X, 256),
2346 SC_WAIT(4),
2347 SC_ADD(SW_SCALE_Y, -512),
2348 SC_ADD(SW_SCALE_X, 256),
2349 SC_WAIT(4),
2350 SC_ADD(SW_SCALE_Y, -512),
2351 SC_ADD(SW_SCALE_X, 256),
2352 SC_WAIT(10),
2354 SC_END,
2355};
2356
2358 SC_ADD(SW_SCALE_Y, 512),
2359 SC_ADD(SW_SCALE_X, -256),
2360 SC_WAIT(2),
2361 SC_ADD(SW_SCALE_Y, 512),
2362 SC_ADD(SW_SCALE_X, -256),
2363 SC_WAIT(2),
2364 SC_ADD(SW_SCALE_Y, 512),
2365 SC_ADD(SW_SCALE_X, -256),
2366 SC_WAIT(6),
2367 SC_ADD(SW_SCALE_Y, -512),
2368 SC_ADD(SW_SCALE_X, 256),
2369 SC_WAIT(4),
2370 SC_ADD(SW_SCALE_Y, -512),
2371 SC_ADD(SW_SCALE_X, 256),
2372 SC_WAIT(4),
2373 SC_ADD(SW_SCALE_Y, -512),
2374 SC_ADD(SW_SCALE_X, 256),
2375 SC_WAIT(12),
2377 SC_END,
2378};
2379
2383 SC_LABEL(1),
2384 SC_ADD(SW_SCALE_Y, 3 * Q16_ONE / 64),
2385 SC_WAIT(2),
2386 SC_ADD(SW_SCALE_Y, 3 * Q16_ONE / 64),
2387 SC_WAIT(2),
2388 SC_ADD(SW_SCALE_Y, 3 * Q16_ONE / 64),
2389 SC_WAIT(16),
2390 SC_ADD(SW_SCALE_Y, -(3 * Q16_ONE / 64)),
2391 SC_WAIT(4),
2392 SC_ADD(SW_SCALE_Y, -(3 * Q16_ONE / 64)),
2393 SC_WAIT(4),
2394 SC_ADD(SW_SCALE_Y, -(3 * Q16_ONE / 64)),
2395 SC_WAIT(32),
2397 SC_END,
2398};
2399
2403 SC_LABEL(1),
2404 SC_ADD(SW_SCALE_Y, 3 * Q16_ONE / 64),
2405 SC_WAIT(2),
2406 SC_ADD(SW_SCALE_Y, 3 * Q16_ONE / 64),
2407 SC_WAIT(2),
2408 SC_ADD(SW_SCALE_Y, 3 * Q16_ONE / 64),
2409 SC_WAIT(26),
2410 SC_ADD(SW_SCALE_Y, -(3 * Q16_ONE / 64)),
2411 SC_WAIT(4),
2412 SC_ADD(SW_SCALE_Y, -(3 * Q16_ONE / 64)),
2413 SC_WAIT(4),
2414 SC_ADD(SW_SCALE_Y, -(3 * Q16_ONE / 64)),
2415 SC_WAIT(52),
2417 SC_END,
2418};
2419
2423 SC_END,
2424};
2425
2428 SC_WAIT(1),
2429 SC_LOOP(60, SC_TOP),
2430 SC_POS(0, 0, 0),
2431 SC_WAIT(1),
2432 SC_END,
2433};
2434
2436
2438#if LANGUAGE == LANGUAGE_JAPANESE
2439 0x4000, -188, 2048, 0x1000, 256, 1, 0x2000, 16,
2440#else
2441 0x4000, -188, 2048, 0x1000, 384, 1, 0x2000, 16,
2442#endif
2443 1, 0x7fff, 14, 0x3000, 0, 20, 0x7fff, 60,
2444 0x3000, 2048, 20, 0x7fff, 60, -1,
2445};
2446
2448#if LANGUAGE == LANGUAGE_FRENCH
2449 0x1000, 512, 1, 0x2000, 0, 1, 0x1000, 384,
2450 6, 0x2000, 16, 6, 0x7fff, 6, 0x1000, 512,
2451 6, 0x7fff, 6, 0x1000, 384, 6, 0x7fff, 6,
2452 0x1000, 512, 6, 0x7fff, 6, 0x1000, 384, 6,
2453 0x7fff, 6, 0x2000, 0, 30, 0x1000, 512, 6,
2454 0x7fff, 6, 0x1000, 384, 6, 0x7fff, 6, 0x1000,
2455 512, 6, 0x7fff, 6, 0x1000, 384, 6, 0x7fff,
2456 6, 0x1000, 512, 6, 0x7fff, 6, -1,
2457#elif LANGUAGE == LANGUAGE_SPANISH || LANGUAGE == LANGUAGE_ITALIAN
2458 0x1000, 384, 1, 0x2000, 0, 1, 0x1000, 256,
2459 6, 0x2000, 16, 6, 0x7fff, 6, 0x1000, 384,
2460 6, 0x7fff, 6, 0x1000, 256, 6, 0x7fff, 6,
2461 0x1000, 384, 6, 0x7fff, 6, 0x1000, 256, 6,
2462 0x7fff, 6, 0x2000, 0, 30, 0x1000, 384, 6,
2463 0x7fff, 6, 0x1000, 256, 6, 0x7fff, 6, 0x1000,
2464 384, 6, 0x7fff, 6, 0x1000, 256, 6, 0x7fff,
2465 6, 0x1000, 384, 6, 0x7fff, 6, -1,
2466#else
2467 0x1000, 512, 1, 0x2000, 0, 1, 0x1000, 256,
2468 6, 0x2000, 16, 6, 0x7fff, 6, 0x1000, 384,
2469 6, 0x7fff, 6, 0x1000, 256, 6, 0x7fff, 6,
2470 0x1000, 384, 6, 0x7fff, 6, 0x1000, 256, 6,
2471 0x7fff, 6, 0x2000, 0, 30, 0x1000, 384, 6,
2472 0x7fff, 6, 0x1000, 256, 6, 0x7fff, 6, 0x1000,
2473 384, 6, 0x7fff, 6, 0x1000, 256, 6, 0x7fff,
2474 6, 0x1000, 384, 6, 0x7fff, 6, -1,
2475#endif
2476};
2477
2479 0x1000, 128, 1, 0x2000, 0, 1, 0x1000, 256,
2480 6, 0x2000, 16, 6, 0x7fff, 60, 0x1000, 384,
2481 6, 0x7fff, 6, 0x1000, 272, 6, 0x7fff, 6,
2482 0x1000, 400, 6, 0x7fff, 6, 0x1000, 288, 6,
2483 0x7fff, 6, 0x2000, 0, 30, 0x1000, 416, 6,
2484 0x7fff, 6, 0x1000, 304, 6, 0x7fff, 6, 0x1000,
2485 432, 6, 0x7fff, 6, 0x1000, 320, 6, 0x7fff,
2486 6, 0x1000, 448, 6, 0x7fff, 6, -1,
2487};
2488// clang-format on
2489
2491
2493 SC_ARG(2),
2494 SC_SYNC,
2495 SC_ARG(1),
2496 SC_WAIT(6),
2498 SC_WAIT(3),
2499 SC_ARG(10),
2500 SC_WAIT(150),
2502 SC_ARG(1),
2503 SC_END,
2504};
2505
2507 SC_ARG(2),
2508 SC_SYNC,
2509 SC_ARG(1),
2510 SC_WAIT(6),
2512 SC_WAIT(3),
2513 SC_ARG(28),
2514 SC_WAIT(150),
2516 SC_ARG(1),
2517 SC_END,
2518};
Ability numbers, named from the English release.
@ ABILITY_FORCE
Definition ability_ids.h:17
@ ABILITY_MIND_READ
Definition ability_ids.h:16
@ ABILITY_HALT
Definition ability_ids.h:20
@ ABILITY_MOVE
Definition ability_ids.h:15
@ ABILITY_FROST
Definition ability_ids.h:11
@ ABILITY_GROWTH
Definition ability_ids.h:10
void Object_RefreshSelectorById(u32 objectId)
Waits, at most 300 frames, for an actor's script to reach its end (command 0x10).
void Object_LinkObjectAndSetCallback(u32 objectId, u32 linkedObjectId)
Makes an actor follow another (the linked action script): writes its linkedObject.
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.
#define DIRECTION_STEP(dx, dz)
Pixel step by direction: X in the upper halfword, Z in the lower.
BattleUnit, a party member's or enemy's battle state, with the elements, abilities and actions it use...
static void Event_CheckAhead(void)
Checks the blocked direction before allowing another movement step.
Definition bilibin.c:331
static void Event_GrowPlant(void)
Growth on the entrance section's target: the plant grows and its cell's collision changes; 0x305 keep...
void(*) SchedulerCallback(void)
#define GARET
Jerald.
#define MIA
Mary.
#define IVAN
Ivan.
s32 Field_ClimbUp(void)
Climbing up (the player presses up at a climbable wall).
Definition climbing.c:196
The Colosso race gauge's sprites and work.
static void Event_TalkToWallWedgeAttendant(s32 guideId)
The Wall Wedge's attendant: the first time, a warrior times his way through the moving wall; then tha...
static UNUSED void ColossoLog_RunCompetitorTalk(s32 competitorId)
Offers to practise the course with a selected solo competitor.
s16 gColossoModeScript3A[]
s32 gColossoRandomEffect[]
void(*) SceneTaskEntry(void)
Definition colosso_log.c:85
static UNUSED void ColossoLog_MarkRivalFinished(void)
Marks the rival path recorder as finished.
static void ColossoLogRollingStage_WaitForSceneTask(void)
Waits for the wall pattern used by the tutorial, with a bounded timeout.
struct ScenePlacement gColossoLogPlacements[]
struct SceneEvent gColossoLogEvents[]
s32 gColossoLog_PlaceScript[]
static void Event_MoveStone(void)
After Move on the stone: its column is kept (byte flag 0x370) and its cell rebuilt.
static void Event_PassNorthWallOpening(void)
The rider passes through the moving wall's northern opening.
s32 gColossoLinkedEffect[]
static void ColossoLog_WaitForRivalToFinish(void)
Waits until the rival path recorder reaches its finished mode.
s32 gColossoSceneTaskStatus
static void ColossoLogRollingStage_InitializeModeTask(u32 mode, u32 parameter)
Selects the portrait task script and clears its movement state.
static void Event_PassSouthWallOpening(void)
The rider passes through the moving wall's southern opening.
const s8 gColossoLog_LogPattern[][6]
static s32 ColossoLogRollingStage_AdvanceParticleMotion(struct ScriptInterpreter *interpreter)
Advances a reunion particle; timer and work hold signed 1/256-pixel steps.
s16 gColosso_MarkerSlot
const u8 gColosso_LetteringPaletteOffsets[]
const struct SceneRegion * ColossoLog_GetRegions(void)
s32 gColossoParticleCount
u32 gColossoLogExits[]
static void ColossoLog_IntroduceFinalCourse(s32 guideId)
Stages the party behind the guide for the introduction to the third finals.
static void Event_IgnoreMove(void)
Move on this rock needs nothing more.
s32 gColossoSceneTaskState
static void Event_ReachArena(void)
Reaching the arena: the leader takes a prize (the Claymore if first, the Hunter's Sword if second),...
static s32 ColossoLogRollingStage_CheckObstacleDestination(s32 x, s32 z)
Rejects blocked cells and cells occupied by one of the three obstacles.
static void InitializeSelectedActor(s32 actorId)
Sets a companion speed for the shared solo-party placement routine.
s32 gColossoParticleKinds[]
static void InitializeActorZero(void)
Sets the leader speed for the shared solo-party placement routine.
const struct ScenePlacement * ColossoLog_GetPlacements(void)
static void Event_RideMovingSidewalk(void)
On the Moving Sidewalk, until 0x363 is set, the belt carries the controlled actor and the camera west...
static void Event_RollLongLog(void)
Walking into the long log rolls it, with the leader, the way the pad is held until something stops it...
const u16 gColossoEarlySequenceData[]
s16 gColosso_LetteringSlot
@ STONE
Definition colosso_log.c:98
@ PRIZE_A
the arena's Claymore and Hunter's Sword
@ SCALE_PAN_EAST
Definition colosso_log.c:96
@ LOG_ROLLING_ATTENDANT
@ OPPONENT
the warrior racing Isaac to the arena
Definition colosso_log.c:93
@ SIDEWALK_BLOCK
@ STEPPING_STONE_ATTENDANT
@ LONG_LOG
the log-rolling area's long log
@ FROST_TARGET
on the eastern pan
Definition colosso_log.c:94
@ SCALE_PAN_WEST
the Scales of Justice
Definition colosso_log.c:95
@ SCALE_WEIGHT
pushed onto the western pan
Definition colosso_log.c:97
@ WALL_OPERATOR
Definition colosso_log.c:99
@ GUIDE
explains the third course
@ SCALES_ATTENDANT
@ WALL_WEDGE_ATTENDANT
@ GROWTH_PLANT
@ MOVING_SIDEWALK_ATTENDANT
@ FREE_CLIMB_ATTENDANT
@ PRIZE_B
static void Event_TalkToLogRollingAttendant(s32 actor)
The log-rolling area's attendant: the first time, a marker traces the log's route; then the objective...
s32 gColossoLog_LeaderActionB[]
static void Event_ForceSidewalkBlock(void)
Force on the Moving Sidewalk's block: it slides away and the belt carries no one any more (0x363).
static void Event_TalkToSteppingStoneAttendant(s32 guideId)
The Stepping-Stone Stage's attendant: the first time, a warrior finds the way; then the objective.
s32 ColossoLog_Initialize(void)
Restores obstacle progress, then enters practice, introduction or battle aftermath.
static void Event_TalkToScalesAttendant(s32 guideId)
The Scales of Justice's attendant: the first time, the pans are shown; then the objective.
static void Event_HaltWall(void)
Halt on the wall operator: the Wall Wedge stops at its next open pattern (0x361).
static void ColossoLogRollingStage_SpawnPeriodicParticle(void)
Shows one of three reunion particles at its scheduled point in the cycle.
static void ColossoLog_MoveOnScales(struct FieldActor *pan, s32 height)
Moves a scale pan vertically at the shared speed and acceleration.
static void Event_StepOffScales(void)
Stepping off the western pan: the scales swing back.
static void Event_TalkToMovingSidewalkAttendant(s32 guideId)
The Moving Sidewalk Stage's attendant: the first time, a warrior walks against the belt; then the obj...
static void ColossoLogRollingStage_PositionActor(s32 selector, s32 x, s32 z)
Starts a scripted pixel destination while preserving the actor height.
s16 gColossoModeScript4[]
s32 gColosso_RivalFinishScript[]
static void ColossoLogRollingStage_SpawnRandomSceneEffect(union FieldObject *fieldObject)
Occasionally scatters an effect around a moving source actor.
const struct SceneEvent * ColossoLog_GetEvents(void)
static void Event_PushWeightOrCheckAhead(void)
Walking into something: the weight is pushed, anything else is checked.
static UNUSED void ColossoLogRollingStage_NoopSceneEventHook(void)
static s32 ColossoLog_ShowActivatedSidewalkLayer(struct ScriptInterpreter *interpreter)
Displays the activated moving sidewalk and plays its arrival sounds.
s32 gColossoLog_LeaderActionA[]
const s32 gColossoLog_Record30Script[]
const s16 gColossoModeScript2[]
#define COLOSSO_LOG_FACE_DIRECTION
Definition colosso_log.c:70
const struct SceneEntrance * ColossoLog_GetEntrances(void)
static void Event_FreezeOnScales(void)
Frost on the target on the eastern pan: it freezes and the Scales of Justice tip, the western pan dow...
static void ColossoLog_PushActorAhead(void)
Pushes a neighboring actor one cell when its destination and overhead are clear.
static UNUSED void FieldScene_RunScene3bcSequenceA(s32 countdown)
Unused portrait countdown for a signed number of seconds.
s16 gColossoModeScriptDefault[]
#define COLOSSO_LOG_APPLY_MATCHING_SLOT_VALUES
Definition colosso_log.c:73
static void Event_SettleRocks(void)
A rock resting on the floor becomes a step (FLAG_SCENE_TEMP_14 to _16).
static s32 ColossoLog_CollectFinishEquipment(s32 firstItem, s32 secondItem)
Moves to the available finish item, equips it and announces it.
const s16 gColossoModeScript3B[]
static void ColossoLogRollingStage_RunScriptedTransition(s32 mode)
Plays the countdown portraits and the start-of-race transition.
static void ColossoLogRollingStage_ResetAndRunSceneTask(void)
Resets the moving wall to its first displayed pattern.
s32 gColossoLog_LeaderActionC[]
const u32 * ColossoLog_GetExits(void)
static void Event_TalkToFreeClimbAttendant(s32 guideId)
The Free-Climb Area's attendant: the first time, a warrior climbs across; then the objective.
static void Event_StepOnScales(void)
Stepping onto the western pan, unless the scales are frozen: it sinks with the rider as the eastern p...
static s32 ColossoLogRollingStage_RaiseLinkedSceneEffect(struct ScriptInterpreter *interpreter)
Raises the linked item actor and clears the source link.
static void ColossoLogRollingStage_NoopSceneHook(void)
static void ColossoLog_UpdateEastEndCollision(void)
Changes the eastern end collision according to the rider facing.
static void Event_PushWeight(void)
Walking into the weight pushes it, perhaps onto the scales.
static void ColossoLogRollingStage_PositionAndActivateActor(s32 selector, s32 x, s32 z)
Moves to a scripted pixel destination, waits, then restores the idle mode.
static UNUSED void WriteU32AsHex(u8 *hexText, u32 value)
Writes eight hexadecimal digits followed by a terminator.
char gColossoHexChars[20]
static s32 ColossoLogRollingStage_CheckPathClearance(s32 x, s32 z)
Checks all four cells covered by the long rolling log.
static void ColossoLogRollingStage_SceneTask(void)
Cycles the moving wall and raises the opening event beneath the rider.
static void ColossoLogRollingStage_StartSceneTask(void)
Resumes cycling the moving wall.
static void Event_SetWeightOnScales(void)
When the weight reaches the western pan, it sinks the pan and the eastern pan rises (0x368).
static void Event_PushRock(void)
Walking into a rock pushes it.
static void ColossoLog_PlayPostBattleReunion(s32 battleResult)
Reunites the party after the battle and plays the resting conversation.
struct SceneEntrance gColossoLogEntrances[]
#define COLOSSO_LOG_INITIALIZE_MODE_TASK
Definition colosso_log.c:71
s32 gColossoMultiPhaseData[]
s32 gColossoLog_Actor8Action[]
const s32 gColossoSceneEventEffect[]
Declares nothing of its own: it only includes types.h.
The Colosso finals' three courses (Colosso Log, River and Wall): a helper for the race gauge that no ...
s16 gColosso_ModeMoveTarget
s16 * gColosso_LetteringScript
s16 gColosso_LetteringTimer
s32 gColosso_LetteringPosition
s16 gColosso_ModeMoveDuration
s16 gColosso_LetteringParam
s16 gColosso_LetteringMode
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 edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
static s32 FieldScheduler_AddCallback(SchedulerCallback callback, s32 priority)
Registers a main-image scheduler callback.
Definition engine_call.h:36
static s32 FieldObject_CheckMovementCollision(struct FieldActor *actor, struct FieldPosition *position)
Definition engine_call.h:66
static s32 FieldGameFlag_GetByte(s32 flag)
Definition engine_call.h:71
static void FieldBattleFx_RunRisingObjectSequence(s32 actor, s32 mode, s32 action)
Definition engine_call.h:60
static void FieldGameFlag_SetByte(s32 flag, s32 value)
Definition engine_call.h:75
void ObjectDispatch_StartCamera(struct DispatchObject *object, s32 linkedObjectHandle)
Starts an object on the camera script (SC_CAMERA).
Definition objects.c:480
void ObjectDispatch_StartIdle(struct DispatchObject *object)
Starts an object on the idle script (a lone SC_END).
Definition objects.c:471
void ObjectDispatch_WaitForValue16(void *rawObject)
Waits until the object's script reaches SC_END (0x10), at most 300 frames.
Definition objects.c:495
void ObjectSystem_SuspendProjectionAndShowSprites(void)
Suspends the object camera updates, starts the palette back to normal and, a frame later,...
Definition objects.c:552
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)
s32 Engine_LeaderCheckAhead(void)
static void Actor_SetDestination(s32 actor, s32 x, s32 z)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_MapCopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
void Object_SetMode(struct FieldActor *object, s32 animation)
struct FieldActor * Engine_ActorLookup(s32 actor)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
void Engine_MessageShowCentered(s32 message, s32 flags)
#define GameFlag_IsSet
void Engine_CameraSetSpeed(s32 speed, s32 acceleration)
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
static void Camera_SetSpeed(s32 speed, s32 acceleration)
void Engine_CameraMoveTo(s32 fixed_x, s32 fixed_y, s32 fixed_z, s32 pan)
s32 Engine_TaskRemoveCallback(void(*callback)(void))
static void Actor_SetDestinationOffset(s32 actor, s32 dx, s32 dz)
void Engine_ActorSetSpeed(s32 actor, s32 speed, s32 acceleration)
void Engine_ActorFaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_EventCloseScreen(void)
void Engine_ActorSetDestination(s32 actor, s32 x, s32 z)
void Engine_ActorWalkToAndWait(s32 actor, s32 x, s32 z)
static void ColorBuffer_ApplyTarget(s32 value, s32 mode)
static void Actor_WalkTo(s32 actor, s32 x, s32 z)
void Engine_EventWaitForScreen(void)
#define GameFlag_Set
void Engine_ActorDestroy(s32 actor)
static void Actor_ShowEmote(s32 actor, s32 emote, s32 frames)
void Engine_ObjectSetScript(struct FieldActor *object, const s32 *script)
void Engine_EventOpenScreen(void)
s32 Engine_EventOpenMessage(s32 speaker, s32 flags)
void Engine_GameFlagSet(s32 flag)
void Engine_GameFlagClear(s32 flag)
void Engine_CameraWaitForMove(void)
static void Actor_SetActionScript(s32 actor, const s32 *script)
The engine encodes either a built-in action or an action-script address.
void Engine_ActorWaitForMove(s32 actor)
void Engine_CameraFollowActor(s32 actor, s32 keep_position)
static void Map_CopyCellAttributes(s32 srcX, s32 srcY, s32 width, s32 height, s32 destX, s32 destY)
void Engine_ActorRunRepeatedMotion(s32 actor, s32 repeats)
static void Event_ShowMessage(s32 speaker, s32 flags)
void Engine_ActorSetAttachedEffect(s32 actor, s32 effect)
s32 Engine_RandomNext()
static void Event_PlayCue(s32 cue)
void Engine_ActorSetChildValue(s32 actor, s32 value)
#define STORE_CONST(place)
Definition field_event.h:29
s32 Engine_GameFlagIsSet(s32 flag)
u8 gSceneState[]
void Engine_ActorStartRepeatedMotion(s32 actor, s32 repeats)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
u8 * gColossoWork
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)
static void Map_CopyCellsLayered(s32 srcX, s32 srcY, s32 destX, s32 destY, s32 width, s32 height)
void Engine_ActorFaceEachOther(s32 actor, s32 other, s32 frames)
void Engine_EventWait(s32 frames)
static void Actor_SetAttachedEffect(s32 actor, s32 effect)
Field objects and actors, and the scene transition styles.
@ TRANSITION_WINDOW
Definition field_obj.h:17
@ TRANSITION_BACKDROP_FADE
Definition field_obj.h:16
@ ACTOR_PRIORITY_UNDERFOOT
The depth sort treats it as 320 pixels higher on the screen.
Definition field_obj.h:155
@ ACTOR_FOLLOWS_TERRAIN
moves with the ground height under it
Definition field_obj.h:160
@ ACTOR_FALLS
falls by its gravity and bounces
Definition field_obj.h:161
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
The field's runtime work: map cells, scene records and regions, map markers and FieldWork.
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_TALK
@ EVENT_RAISED
#define SCENE_EXITS(scene)
Definition field_scene.h:72
#define IF_FLAG_SET(flag)
Definition field_scene.h:48
#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_STAND
#define SEARCH(target)
#define SCENE_EXITS_END
Definition field_scene.h:77
#define PLACEMENT_SHARE_PREVIOUS_SPRITE
@ FACING_EAST
Definition field_scene.h:26
@ FACING_NORTH
Definition field_scene.h:32
@ FACING_SOUTHWEST
Definition field_scene.h:29
@ FACING_SOUTH
Definition field_scene.h:28
@ FACING_WEST
Definition field_scene.h:30
#define TOUCH_WALKING
#define PIXELS(value)
@ SEARCH_CHEST
The scene service layer: one typed inline for each engine service a scene calls by its own name,...
static s32 Task_AddCallback(void(*callback)(void), s32 priority)
Calls the main-image scheduler through engine_call.h.
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_COLOSSO_OVER
the Colosso finals have been fought
Definition flags.h:191
#define FLAG_SCENE_TEMP_15
Definition flags.h:734
#define FLAG_KEEP_MUSIC
The next scene keeps the music that is playing; scene.c clears FLAG_KEEP_MUSIC as it does,...
Definition flags.h:35
#define FLAG_SCENE_TEMP_16
Definition flags.h:735
#define FLAG_RETREAT_BLOCKED
Retreat is blocked, from Psynergy or an item.
Definition flags.h:55
#define FLAG_SCENE_TEMP_11
Definition flags.h:730
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_SCENE_TEMP_10
Definition flags.h:729
#define FLAG_SCENE_TEMP_14
Definition flags.h:733
#define FLAG_WON_COLOSSO
the party won the finals
Definition flags.h:192
GameState, the game's state: play time, coins, the scene and the leader's position,...
#define Battle_SetStart(mode)
Sets the battle start type.
Definition game_state.h:164
struct GameState gGameState
The screen blend's globals and the graphics routines.
void BattleEffect_PauseObject(s32 actorId)
Pauses object id, keeping its per-frame update and, if it is animated, its first animation's param in...
Definition halt.c:173
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
Definition heap.c:80
The heap's work slots and HeapState.
@ HEAP_SLOT_EVENT
Definition heap_state.h:40
The main-image routines scene overlays import.
The hardware's I/O registers and their bits, as pret names them.
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_RIGHT
Definition io_reg.h:247
The register write queue that VBlank carries out after each finished frame.
Colosso Log, River and Wall, and Goma Cave's entrance: giving a character an item and putting it on.
Item numbers, named from the English release.
@ ITEM_NUT
Definition item_ids.h:41
@ ITEM_SMOKE_BOMB
Definition item_ids.h:67
@ ITEM_SLEEP_BOMB
Definition item_ids.h:68
The keypad state the VBlank interrupt keeps.
volatile u32 gKeysHeld
Keys down now.
Small statement macros both games use for positions, velocities and bounds.
#define SET_VECTOR(v, x, y, z)
Sets the x, y and z of a three-part vector: a position about to be projected, a per-frame step,...
Definition macros.h:12
void Map_SetLayerEntryFlag(u32 channelIndex)
Pauses tile animation channel channelIndex by setting its paused byte.
void Map_ClearLayerEntryFlag(u32 channelIndex)
Resumes tile animation channel channelIndex by clearing its paused byte.
void Vector_AddPolarOffset(s32 radius, s32 angle, void *position)
Moves the point position by radius in direction angle on the ground plane: x by the cosine,...
Definition math.c:23
The heaps: allocating and freeing blocks.
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_FACING
Definition objcmd.h:57
@ SW_Y
Definition objcmd.h:59
@ SW_SCALE_X
Definition objcmd.h:62
@ SW_HOOK
Definition objcmd.h:84
#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.
Palette fades, the battle effect palette buffers and the colour channel curves.
@ PALETTE_TRANSFORM_GREY
grey of brightness (2R + 4G + B) / 7
Definition palbuf.h:73
@ PALETTE_TRANSFORM_PLAIN
each colour unchanged
Definition palbuf.h:72
void Field_RequestBattleFromEncounterTable(s32 zoneNo, s32 slotNo)
Sets up a battle with enemy group slot of encounter table zone.
Definition requests.c:14
void Event_SetDefeatDestination(s32 scene, s32 entrance)
Sets where the party wakes up after losing a battle (gGameState.defeatScene and defeatEntrance).
Definition requests.c:70
void Event_SetNextDestination(s32 scene, s32 entrance)
Sets the scene and entrance that the field goes to next (gGameState.nextScene and nextEntrance).
Definition requests.c:61
Resource numbers, named where their contents are known.
char ResourceId_RivalPathC
void Audio_PlayCueFromEventWork(void)
Starts the current scene's field music, chosen by Scene_ResolveInteractionResult.
Definition scene.c:355
Scene numbers, named after their places.
char SceneId_ColossoLog
The field object script interpreter and the operands its commands read.
Song and sound effect ids, indices into gSound_SongTable.
#define SE_213
Definition songs.h:208
#define SE_240
Definition songs.h:235
#define SE_239
Definition songs.h:234
#define SE_247
Definition songs.h:242
#define MUS_086
Definition songs.h:85
#define MUS_089
Definition songs.h:88
#define MUS_TREASURE_FOUND
Definition songs.h:82
#define SE_288
Definition songs.h:281
#define MUS_017
Definition songs.h:27
#define SE_217
Definition songs.h:212
#define MUS_019
Definition songs.h:29
#define SE_237
Definition songs.h:232
#define SE_238
Definition songs.h:233
#define SE_236
Definition songs.h:231
#define SE_289
Definition songs.h:282
s32 AudioCommand_GetStateByte(void)
Returns the remaining delay before BGM can be restored after a fanfare.
Definition sound.c:261
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_EventEnd(void)
void Engine_AudioPlayCue()
void Engine_EventBegin(void)
void Engine_ActorShowEmote()
void Engine_TaskWait()
void Engine_EventSetMessage()
void Engine_EventShowMessage()
#define NULL
Definition bilibin.h:6
Colosso Log, River and Wall, and Crossbone Isle's platform rooms: an actor drawn as an item's menu ic...
void Colosso_ShowItemIcon(s32 id, s32 item)
Replaces the picture of actor id, when it has a sprite of its own, with the icon of item: the icon's ...
void Colosso_ShowPointer(u32 x, u32 y, u32 style)
Shows the pointer at screen pixel (x, y), drawn at priority style & 3.
void Colosso_MovePointer(u32 x, u32 y, u32 duration)
Glides the pointer to screen pixel (x, y) over duration frames.
void OverlayObject_ResetMotionFields(s32 actor)
Stops the actor where it is: no velocity and no destination.
void Colosso_WalkActorTo(s32 actorId, s32 x, s32 z)
Walks the actor at 2 pixels a frame towards pixel (x, z) and returns at once.
void Colosso_FadeInCompetitor(s32 id, s32 x, s32 z)
Isaac (id) appears at pixel (x, z) on the stage, facing south: he fades in through the backgrounds wh...
void Colosso_HidePointer(void)
Hides the pointer and frees its VRAM block.
void Colosso_WalkActorToAndStand(s32 actorId, s32 x, s32 z)
Walks the actor at 1.25 pixels a frame to pixel (x, z), waits until it arrives and stands it there.
void Colosso_RestoreCompetitor(s32 id)
Puts Isaac (id) back where Colosso_FadeInCompetitor found him: he stands (or turns south,...
void * Colosso_FindActorAhead(void)
Returns the placed actor standing one cell, or else two cells, ahead of the actor the player moves (s...
Colosso Log and Colosso River: setting up a race against the rival, with the race gauge at the top of...
void Colosso_StartRaceGauge(s32 playerActor, s32 rivalActor, s32 segments, s32 finishX, s32 finishZ, s32 finishItemActorA, s32 finishItemActorB)
Starts the race gauge (struct ColossoGaugeWork, in work slot 59): Isaac and the rival as playerActor ...
void Colosso_StartRival(s32 resource)
Decodes the rival's recorded path (resource) after the gauge's work and, unless the party returns to ...
void Colosso_OfferCheeringSpot(s32 mode, s32 guide, s32 stage)
The guide at a stage, with the mode Colosso_GreetAtStage returned: offer a friend's cheering at the s...
void Colosso_RepeatStageNumber(s32 speaker, s32 competitor)
A stage's guide, after describing the stage, names it again: the copy of that line after it in the te...
void Colosso_AskDoneCheering(s32 id)
A stage's guide, talking to a friend who looks around alone, asks whether they are done cheering.
static void Colosso_TakePlaceForMatch(void)
Raised event 99: the nearest actor with animation 165 level with or below the friend on the map calls...
void Colosso_PlaceFriendsAtCheeringSpots(void)
Puts Garet, Ivan and Mia back at the cells where they chose to cheer, at the centre of each cell.
void Colosso_ClearCheeringSpots(void)
Forgets where Garet, Ivan and Mia cheer from.
s32 Colosso_GreetAtStage(s32 speaker, s32 competitor)
A stage's guide names the stage and decides what to do next.
void Colosso_ControlCharacterAlone(s32 id)
Makes the character the party's only member, the one the player moves and the camera follows,...
void Colosso_RaiseTakePlaceOnPsynergy(void)
A scene callback while a friend looks around the course alone (entrance 2): when the Psynergy request...
static void Colosso_AskReadyToRace(s32 actorId)
The guide at the course's start.
#define offsetof(type, member)
Definition stddef.h:19
The Colosso race gauge's work at the start of work slot 59: its sprites, how far it has slid down,...
A field object as the object dispatcher's far calls take it.
The running scene's event work: its placement and event tables, its actors, the triggers and exit it ...
Definition event_work.h:20
struct FieldActor * viewCenter
the object the map view follows
Definition event_work.h:49
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 mode
MODE_WORLD_MAP (3) on the world map.
Definition event_work.h:38
s32 transitionFrames
frames
Definition event_work.h:45
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s16 timer
The parameter its action script reads (a follow distance or an angle to face), the player's frames to...
Definition field_obj.h:109
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
u16 radius
Collision radius in pixels: 16, or half the sprite metadata's boxY, when created; the overlap checks ...
Definition field_obj.h:43
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
s32 terrainHeight
16.16 fixed-point pixels
Definition field_obj.h:38
s32 velocityY
16.16 fixed-point pixels per frame
Definition field_obj.h:53
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
s32 targetY
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:60
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
u16 work
The side of the player's next footprint (2 after a stop), or scene scratch.
Definition field_obj.h:112
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
Full event work allocated by Field_RunScene (heap slot 27).
The game's state: play time, coins, the scene and the leader's position, the active party and the opt...
Definition game_state.h:14
s16 entrance
Definition game_state.h:37
u8 movementMode
1 while the leader is climbing, 0 otherwise
Definition game_state.h:57
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
The Colosso rival's path player in the scene state: its mode (1 playing, 2 recording,...
Definition field.h:75
s16 mode
Definition field.h:76
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
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
s32 GetMapCellCollision(s32 layer, s32 x, s32 y)
Returns the collision code of a layer's cell at (x, y) in 16.16 pixels.
Definition terrain.c:401
void SetMapCellCollision(u32 layer, s32 x, s32 y, u32 collisionCode)
Sets the collision code of a layer's cell at (x, y) in 16.16 pixels.
Definition terrain.c:422
s32 Map_GetTerrainHeight(s32 layer, s32 x, s32 y)
Returns the ground height of a layer at (x, y) in 16.16 pixels: the height function of the cell's ter...
Definition terrain.c:343
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 char s8
Definition types.h:10
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
An object on the field, read as an actor or as an effect.
void Party_RestoreHpPp(s32 cureConditions)
Restores every party member's HP and PP; with cureConditions 1 it also cures poison and haunting.
Definition units.c:662
The patch levels: our groups of the measured changes from the Japanese release.
The sprite VRAM block cache and its owners.
void UiWork_PushValueSlot(u32 value, u32 kind)
Adds a message argument of kind (MSG_ARG_) with value to the first free place of the argument table; ...
Definition messages.c:216