Alchemy
Loading...
Searching...
No Matches

colosso_solo.h

Go to the documentation of this file.
1#include "types.h"
2#include "field_event.h"
3#include "engine_call.h"
4#include "battle.h"
5#include "debug.h"
6#include "field.h"
7#include "game.h"
8#include "graphics.h"
9#include "menu.h"
10#include "minigame.h"
11#include "sound.h"
12#include "system.h"
13#include "game_state.h"
14#include "battle_unit.h"
15#include "field_obj.h"
16#include "animspr.h"
17#include "text/msg_ids.h"
18
19// The Colosso finals' three courses (Colosso Log, River and Wall): before
20// Isaac runs, Garet, Ivan and Mia each look around the course on their own and
21// choose where to cheer from, and the guide at each stage describes it and
22// offers a friend's cheering there.
23
24// Byte flags (eight flags each) holding where a friend cheers from: the cell
25// column at COLOSSO_CHEER_COLUMN + 16 * character and the cell row at
26// COLOSSO_CHEER_ROW + 16 * character, for Garet, Ivan and Mia.
27#define COLOSSO_CHEER_COLUMN 0x370
28#define COLOSSO_CHEER_ROW 0x378
29#define COLOSSO_CHEER_SLOT(character) ((character) << 4)
30
31/// Scene flags, by stage number: a friend cheers at the stage, and its
32/// description was heard. When a friend cheers there, the guide says
33/// "Unfortunately, we have a full house."
34#define COLOSSO_STAGE_CHEERED 0x200
35#define COLOSSO_STAGE_DESCRIBED 0x208
36
37/// Puts Garet, Ivan and Mia back at the cells where they chose to cheer, at the
38/// centre of each cell.
40 {
41 s32 x =
43 s32 y =
45
46 x <<= 20;
47 x += 0x80000;
48 y <<= 20;
49 y += 0x80000;
51 }
52 {
53 s32 x =
56
57 x <<= 20;
58 x += 0x80000;
59 y <<= 20;
60 y += 0x80000;
62 }
63 {
64 s32 x =
67
68 x <<= 20;
69 x += 0x80000;
70 y <<= 20;
71 y += 0x80000;
73 }
74}
75
76/// Makes the character the party's only member, the one the player moves and
77/// the camera follows, with full HP and PP and no poison. The gauges are the
78/// battle's (0x4000 full; a character with any HP or PP left shows at least 1).
80 struct BattleUnit *unit;
81 s32 v;
82 s32 t;
83
92 unit = UnitGet(id);
93 unit->hp = unit->maxHp;
94 unit->pp = unit->maxPp;
95 unit->poison = 0;
96 v = (unit->hp << 14) / unit->maxHp;
97 t = 0x4000;
98 if (v <= 0x4000) {
99 t = 0;
100 if (v >= 0)
101 t = v;
102 }
103 unit->hpGauge = t;
104 if ((u16)t == 0 && unit->hp != 0) {
105 unit->hpGauge = 1;
106 }
107 v = (unit->pp << 14) / unit->maxPp;
108 t = 0x4000;
109 if (v <= 0x4000) {
110 t = 0;
111 if (v >= 0)
112 t = v;
113 }
114 unit->ppGauge = t;
115 if ((u16)t == 0 && unit->pp != 0) {
116 unit->ppGauge = 1;
117 }
119}
120
121/// A scene callback while a friend looks around the course alone (entrance 2):
122/// when the Psynergy request names that friend and flag 0x141 is set, raise
123/// event 99, Colosso_TakePlaceForMatch.
125 struct EventWork *work = gEventWork;
126 s32 selection = gGameState.selectedActor;
127
128 if (selection != 0 && (work->psynergyRequest >> 10) == selection &&
129 Engine_GameFlagIsSet(0x141) != 0) {
130 u16 *raised = (u16 *)&work->raisedTrigger;
131 s32 trigger = 99;
132
133 *raised = trigger;
134 }
135}
136
137/// Raised event 99: the nearest actor with animation 165 level with or below
138/// the friend on the map calls the competitors to their places, and the
139/// friend's cell becomes their place to cheer from. "The match is about to
140/// begin. Please take your places." The next friend then looks around, or,
141/// after Mia, the party leaves by exit 10.
142static void Colosso_TakePlaceForMatch(void) {
143 struct EventWork *work = gEventWork;
144 s32 speakerId = 8;
145 s32 nearestDistance = 0x100000;
146 s32 supporterId = gGameState.selectedActor;
147 struct FieldActor *supporter = Object_GetById(supporterId);
148 s32 actorId;
149 s32 *transition;
150 s32 flagBase;
151
153 // Choose the nearest matching speaker whose Z is at least the supporter's.
154 for (actorId = 8; actorId <= 66; actorId++) {
155 struct FieldActor *actor = Object_GetById(actorId);
156
157 if (actor != 0 && actor->spriteStorageKind == 1 &&
158 actor->sprite->entries[0]->animId == 165) {
159 s32 distanceX = (supporter->x.fixed - actor->x.fixed) / PIXELS(1);
160 s32 distanceZ = (supporter->z.fixed - actor->z.fixed) / PIXELS(1);
161
162 if (distanceZ <= 0) {
163 s32 horizontalDistance = distanceX;
164 s32 distance;
165
166 if (horizontalDistance < 0)
167 horizontalDistance = -horizontalDistance;
168 if (distanceZ < 0)
169 distanceZ = -distanceZ;
170 distance = horizontalDistance + distanceZ;
171 if (distance < nearestDistance) {
172 speakerId = actorId;
173 nearestDistance = distance;
174 }
175 }
176 }
177 }
178 Engine_EventSetMessage(MsgColossoMatchAboutBeginPleaseTake);
179 Engine_EventShowMessage(speakerId, 0);
180 transition = &work->startTransition;
181 *transition = SCENE_TRANSITION(TRANSITION_WINDOW, 0);
182 work->transitionFrames = 15;
186 // Each supporter has one saved map cell in the group's byte flags.
187 flagBase = COLOSSO_CHEER_SLOT(supporterId);
189 supporter->x.fixed >> 20);
190 {
191 s32 cellRow = supporter->z.fixed >> 20;
192
193 FieldGameFlag_SetByte(flagBase + COLOSSO_CHEER_ROW, cellRow);
194 }
195 supporterId++;
196 if (supporterId > MIA) {
199 } else {
203 *transition = 0;
204 }
206}
207
208/// A stage's guide, talking to a friend who looks around alone, asks whether
209/// they are done cheering. "Huh? Are you done cheering?" On "Yeah", "Then
210/// please wait here until the match begins.": the friend's cell becomes their
211/// place, and the next friend looks around, or, after Mia, the party leaves by
212/// exit 10. On "Nope", "Then cheer as best you can!"
214 struct EventWork *work;
215 s32 slot;
216 struct FieldActor *obj;
217 s32 msg;
218 s32 res;
219
221 // Look up the speaker twice and discard both results (two original calls).
222 Object_GetById(id);
223 Object_GetById(id);
225 obj = Object_GetById(slot);
227 msg = MsgColossoCheering;
230 gEventWork->choiceMessage = MsgColossoCheeringChoices;
231 gEventWork->unkcc4 = 4;
232 res = Engine_EventChooseYesNo(slot, 0);
233 if (res == 0) {
234 Engine_EventSetMessage(msg + 1);
236 work->startTransition = SCENE_TRANSITION(TRANSITION_WINDOW, 0);
237 work->transitionFrames = 15;
241 obj->x.fixed >> 20);
243 obj->z.fixed >> 20);
244 slot++;
245 if (slot > MIA) {
248 } else {
252 work->startTransition = 0;
253 }
254 } else {
255 Engine_EventSetMessage(msg + 2);
257 }
259}
260
261/// The guide at the course's start. Once the friends have all gone to cheer
262/// (Isaac is the party), "Isaac, did you get a good look around?": on yes the
263/// guide steps aside, Isaac walks past and the party leaves by exit 11.
264/// Otherwise "Wait, shouldn't you decide where the best place to cheer for
265/// Isaac is?"
266static void Colosso_AskReadyToRace(s32 actorId) {
267 struct FieldActor *actor;
268 s32 x;
269 s32 z;
270
271 actor = Object_GetById(actorId);
272 x = actor->x.part.pixel;
273 z = actor->z.part.pixel;
275
276 if (GetPartyMemberCount() <= 1) {
277 Engine_EventSetMessage(MsgColossoIsaacDidGetGoodLook);
278 if (Engine_EventAskYesNo(actorId, 0) == 0) {
279 InitializeActorZero();
280 InitializeSelectedActor(actorId);
281 Engine_ActorWalkTo(actorId, x, z + 64);
288 }
289 } else {
290 Engine_EventSetMessage(MsgColossoWaitShouldntDecideWhereBest);
291 Engine_EventShowMessage(actorId, 0);
292 }
293
295}
296
297/// Forgets where Garet, Ivan and Mia cheer from.
305}
306
307/// A stage's guide names the stage and decides what to do next. "This is stage
308/// N of the first finals match." (Colosso River; the second is Colosso Wall
309/// and the third Colosso Log). Returns what the guide does next:
310/// 0: describe the stage (yes to "Would you like to hear a description of this
311/// stage?", asked the first time, or "Descriptions" afterwards);
312/// 1: no description, then offer a friend's cheering;
313/// 2: "Cheer" chosen, or a friend already cheers here;
314/// 3: "Nothing", or the choice cancelled.
315s32 Colosso_GreetAtStage(s32 speaker, s32 competitor) {
316 s32 scene;
317 s32 message;
318 s32 choice;
319
322 scene = gGameState.scene;
323 if (scene == (s32)&SceneId_ColossoRiver) {
324 message = MsgColossoStageFirstFinalsMatch;
325 } else if (scene == (s32)&SceneId_ColossoWall) {
326 message = MsgColossoStageSecondFinalsMatch;
327 } else {
328 message = MsgColossoStageThirdFinalsMatch;
329 }
330 Engine_EventSetMessage(message);
331 Engine_EventShowMessage(speaker, 0);
332 if (Engine_GameFlagIsSet(competitor + COLOSSO_STAGE_CHEERED) != 0) {
333 return 2;
334 }
335 if (Engine_GameFlagIsSet(competitor + COLOSSO_STAGE_DESCRIBED) != 0) {
336 choice = PartyTalkMenu_Choose(0);
337 if (choice == 1) {
338 return 2;
339 }
340 if (choice == 2 || choice == -1) {
341 return 3;
342 }
343 return choice;
344 }
346 Engine_EventSetMessage(MsgColossoWouldYouLikeHearDescription);
347 Engine_EventOpenMessage(speaker, 0);
348 return Engine_EventChooseYesNo(0, 0);
349}
350
351/// A stage's guide, after describing the stage, names it again: the copy of
352/// that line after it in the text. "This is stage N of the first finals
353/// match." (or the second or third)
354void Colosso_RepeatStageNumber(s32 speaker, s32 competitor) {
355 s32 scene;
356 s32 message;
357
359 scene = gGameState.scene;
360 if (scene == (s32)&SceneId_ColossoRiver) {
361 message = MsgColossoStageFirstFinalsMatch;
362 } else if (scene == (s32)&SceneId_ColossoWall) {
363 message = MsgColossoStageSecondFinalsMatch;
364 } else {
365 message = MsgColossoStageThirdFinalsMatch;
366 }
367 Engine_EventSetMessage(message + 1);
368 Engine_EventShowMessage(speaker, 0);
369}
370
371/// The guide at a stage, with the mode
372/// Colosso_GreetAtStage returned: offer a friend's
373/// cheering at the stage. With Isaac alone, "All right, do your best!"; with
374/// the stage taken, "Unfortunately, we have a full house."; otherwise "Would
375/// you like a friend to cheer for you here?" (taken as yes in mode 2) and the
376/// party's character menu. The friend chosen is led to the stage and leaves the
377/// party, and their cell is kept. Mode 3, no or no choice: "If you know who you
378/// want to cheer you on, please let me know!"
379void Colosso_OfferCheeringSpot(s32 mode, s32 guide, s32 stage) {
380 struct FieldActor *actor;
381 struct FieldActor *leader;
382 s32 guideX;
383 s32 guideZ;
384 s32 memberCount;
385 s32 answer;
386 s32 friendId;
387 s32 frontZ;
388 s32 besideX;
389 s32 behindZ;
390 s32 column;
391 s32 row;
392 s32 i;
393 u8 members[8];
394
395 actor = Object_GetById(guide);
396 guideX = actor->x.part.pixel;
397 guideZ = actor->z.part.pixel;
398 if (mode != 3) {
399 memberCount = GetPartyMemberCount();
400 for (i = 0; i < memberCount; i++) {
401 members[i] = gGameState.activeOwners[i];
402 }
403 if (memberCount <= 1) {
404 Engine_EventSetMessage(MsgColossoDoYourBest);
405 Event_ShowMessage(guide, 0);
406 return;
407 }
408 if (GameFlag_IsSet(stage + COLOSSO_STAGE_CHEERED) != 0) {
409 Engine_EventSetMessage(MsgColossoUnfortunatelyWeHaveFullHouse);
410 Event_ShowMessage(guide, 0);
411 return;
412 }
413 if (mode == 2) {
414 answer = 0;
416 } else {
417 Engine_EventSetMessage(MsgColossoWouldLikeFriendCheerFor);
418 Event_OpenMessage(guide, 0);
419 answer = Engine_EventChooseYesNo(0, 0);
420 }
421 if (answer == 0) {
422 if (answer < memberCount) {
423 for (i = 0; i < memberCount; i++) {
424 Party_RemoveActiveOwner((s8)members[i]);
425 }
426 }
427 for (i = 0; i < memberCount; i++) {
428 if ((s8)members[i] != 0) {
429 Party_AddActiveOwner((s8)members[i]);
430 }
431 }
432 friendId = Menu_OpenCharacterSelector();
433 for (i = 0; i < memberCount; i++) {
434 Party_RemoveActiveOwner((s8)members[i]);
435 }
436 for (i = 0; i < memberCount; i++) {
437 Party_AddActiveOwner((s8)members[i]);
438 }
439 if (friendId != -1) {
440 goto L_main;
441 }
442 }
443 }
444 Engine_EventSetMessage(MsgColossoIfKnowWhoWantCheer);
445 Event_ShowMessage(guide, 0);
446 return;
447L_main:
449 Engine_EventSetMessage(MsgColossoIsaacWillCheerForWay);
450 Event_ShowMessage(guide, 0);
452 Actor_SetSpeed(friendId, PIXELS(1), PIXELS(1) / 2);
453 Actor_SetSpeed(guide, PIXELS(1), PIXELS(1) / 2);
454 leader = Object_GetById(0);
455 if (leader != 0) {
456 Actor_SetPosition(friendId, leader->x.fixed, leader->z.fixed);
457 }
458 frontZ = guideZ + 16;
459 Actor_WalkToAndWait(friendId, guideX, frontZ);
460 besideX = guideX + 16;
461 Engine_ActorWalkToAndWait(0, besideX, frontZ);
463 Engine_ActorSetAnimation(friendId, 3);
464 behindZ = frontZ - 32;
466 Actor_WalkToAndWait(guide, guideX, behindZ);
467 Engine_ActorWalkTo(guide, besideX, behindZ);
469 Actor_WalkToAndWait(friendId, guideX, behindZ);
470 Engine_ActorSetAnimation(guide, 1);
472 Actor_WalkToAndWait(friendId, guideX, guideZ - 48);
473 Actor_WalkToAndWait(guide, guideX, behindZ);
474 Actor_WalkToAndWait(guide, guideX, guideZ);
475 Party_RemoveActiveOwner(friendId);
477 actor = Object_GetById(friendId);
478 column = actor->x.fixed >> 20;
480 column);
481 row = actor->z.fixed >> 20;
483}
484
485#undef COLOSSO_CHEER_COLUMN
486#undef COLOSSO_CHEER_ROW
487#undef COLOSSO_CHEER_SLOT
488#undef COLOSSO_STAGE_CHEERED
489#undef COLOSSO_STAGE_DESCRIBED
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.
Animated sprites: their layers, frames and colour modes, and the resource slots they draw from.
BattleUnit, a party member's or enemy's battle state, with the elements, abilities and actions it use...
#define GARET
Jerald.
#define MIA
Mary.
#define IVAN
Ivan.
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 FieldGameFlag_GetByte(s32 flag)
Definition engine_call.h:71
static void FieldGameFlag_SetByte(s32 flag, s32 value)
Definition engine_call.h:75
void Engine_EventClearInvalidPackedValues(void)
The scene script layer: the engine services a scene's events call, declared once (Engine_EventBegin,...
static s32 Event_OpenMessage(s32 speaker, s32 flags)
static void Actor_FaceDirection(s32 actor, s32 facing, s32 frames)
void Engine_ActorSetAnimationAndWait(s32 actor, s32 animation)
s32 Engine_EventChooseYesNo(s32 actor, s32 flags)
#define GameFlag_IsSet
static void Actor_WalkToAndWait(s32 actor, s32 x, s32 z)
void Engine_EventCloseScreen(void)
void Engine_ActorWalkToAndWait(s32 actor, s32 x, s32 z)
void Engine_EventWaitForScreen(void)
#define GameFlag_Set
s32 Engine_EventAskYesNo(s32 speaker, s32 flags)
void Engine_EventOpenScreen(void)
s32 Engine_EventOpenMessage(s32 speaker, s32 flags)
void Engine_GameFlagSet(s32 flag)
void Engine_CameraFollowActor(s32 actor, s32 keep_position)
void Engine_ActorWalkTo(s32 actor, s32 x, s32 z)
static void Event_ShowMessage(s32 speaker, s32 flags)
s32 Engine_GameFlagIsSet(s32 flag)
static void Actor_SetSpeed(s32 actor, s32 speed, s32 acceleration)
static void Actor_SetPosition(s32 actor, s32 fixed_x, s32 fixed_z)
void Engine_ActorFaceEachOther(s32 actor, s32 other, s32 frames)
void Engine_EventWait(s32 frames)
Field objects and actors, and the scene transition styles.
@ TRANSITION_WINDOW
Definition field_obj.h:17
#define SCENE_TRANSITION(style, variant)
Definition field_obj.h:20
@ ACTOR_PARTY_LEADER
@ FACING_WEST
Definition field_scene.h:30
#define PIXELS(value)
#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
GameState, the game's state: play time, coins, the scene and the leader's position,...
struct GameState gGameState
The screen blend's globals and the graphics routines.
s32 GetPartyMemberCount(void)
s32 PartyTalkMenu_Choose(s32 unused)
The Colosso choice of what to do: "Descriptions", "Cheer" or "Nothing", chosen with a pointing hand.
Definition joined.c:33
s32 Menu_OpenCharacterSelector(void)
Lets the player choose one party member, over the field (the Colosso scenes use it).
Definition status.c:95
The reel game's title lettering.
void Battle_ResetEffectCounter(void)
Clears the field's busy flag and, while Reveal is active, ends it: Reveal used with ACT_PACKED runs i...
Definition targets.c:261
s32 Party_RemoveActiveOwner(s32 owner)
Takes character owner out of the party: clears its game flag and closes the gap it leaves in gGameSta...
Definition party.c:154
s32 Party_AddActiveOwner(s32 owner)
Adds character owner to the end of the party: sets its game flag and appends it to gGameState....
Definition party.c:135
char SceneId_ColossoWall
char SceneId_ColossoRiver
void Engine_ActorSetAnimation()
struct EventWork * gEventWork
void Engine_EventRequestExit()
void Engine_ActorSetPosition(u32 actor, s32 x, s32 z)
void Engine_EventEnd(void)
void Engine_EventBegin(void)
void Engine_TaskWait()
void Engine_EventSetMessage()
void Engine_EventShowMessage()
#define COLOSSO_CHEER_COLUMN
#define COLOSSO_CHEER_ROW
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...
#define COLOSSO_STAGE_DESCRIBED
#define COLOSSO_CHEER_SLOT(character)
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...
#define COLOSSO_STAGE_CHEERED
Scene flags, by stage number: a friend cheers at the stage, and its description was heard.
static void Colosso_AskReadyToRace(s32 actorId)
The guide at the course's start.
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
s16 maxPp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
s16 hpGauge
hp / maxHp in 0..0x4000; 1 while any HP remains
s8 poison
1 poisoned, 2 deadly poison
s16 hp
current HP, 0 when downed
s16 ppGauge
pp / maxPp in 0..0x4000; 1 while any PP remains
s16 pp
current PP
s16 maxHp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
The running scene's event work: its placement and event tables, its actors, the triggers and exit it ...
Definition event_work.h:20
s16 raisedTrigger
a raised event for Scene_RunRaisedEvent
Definition event_work.h:35
u16 unkcc4
FieldWork's nameWidth; Colosso sets it to 4.
Definition event_work.h:52
u16 choiceMessage
Message containing the choices.
Definition event_work.h:51
s16 psynergyRequest
a field Psynergy to use, as owner << 10 | Psynergy
Definition event_work.h:33
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
u8 spriteStorageKind
Zero hides sprites; one draws a single sprite, two draws a group.
Definition field_obj.h:78
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 work
The side of the player's next footprint (2 after a stop), or scene scratch.
Definition field_obj.h:112
u8 activeOwners[8]
the party in order
Definition game_state.h:60
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
signed char s8
Definition types.h:10
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
struct FieldCoordinate::@024321007066302143002254325121164243234242211074 part
s32 fixed
16.16 fixed-point pixels
@ MSG_ARG_ACTOR
Definition window.h:139
@ MSG_ARG_NUMBER
Definition window.h:143
struct BattleUnit * UnitGet(u32 owner)
Returns the unit record of owner: 0 to 7 are the playable characters in the game state,...
Definition units.c:73
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