Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/game/mario_actions_cutscene.c
7858 views
1
#include <PR/ultratypes.h>
2
3
#include <stdlib.h>
4
5
#include "prevent_bss_reordering.h"
6
#include "sm64.h"
7
#include "area.h"
8
#include "audio/external.h"
9
#include "behavior_data.h"
10
#include "camera.h"
11
#include "dialog_ids.h"
12
#include "engine/behavior_script.h"
13
#include "engine/graph_node.h"
14
#include "engine/math_util.h"
15
#include "engine/surface_collision.h"
16
#include "game_init.h"
17
#include "gfx_dimensions.h"
18
#include "ingame_menu.h"
19
#include "interaction.h"
20
#include "level_table.h"
21
#include "level_update.h"
22
#include "mario.h"
23
#include "mario_actions_cutscene.h"
24
#include "mario_actions_moving.h"
25
#include "mario_step.h"
26
#include "moving_texture.h"
27
#include "object_helpers.h"
28
#include "object_list_processor.h"
29
#include "save_file.h"
30
#include "seq_ids.h"
31
#include "sound_init.h"
32
#include "rumble_init.h"
33
34
#include "settings.h"
35
36
static struct Object *sIntroWarpPipeObj;
37
static struct Object *sEndPeachObj;
38
static struct Object *sEndRightToadObj;
39
static struct Object *sEndLeftToadObj;
40
static struct Object *sEndJumboStarObj;
41
static UNUSED s32 sUnused;
42
static s16 sEndPeachAnimation;
43
static s16 sEndToadAnims[2];
44
45
static Vp sEndCutsceneVp = { { { 640, 480, 511, 0 }, { 640, 480, 511, 0 } } };
46
static struct CreditsEntry *sDispCreditsEntry = NULL;
47
48
// related to peach gfx?
49
static s8 D_8032CBE4 = 0;
50
static s8 D_8032CBE8 = 0;
51
static s8 D_8032CBEC[7] = { 2, 3, 2, 1, 2, 3, 2 };
52
53
static u8 sStarsNeededForDialog[] = { 1, 3, 8, 30, 50, 70 };
54
55
/**
56
* Data for the jumbo star cutscene. It specifies the flight path after triple
57
* jumping. Each entry is one keyframe.
58
* The first number is playback speed, 1000 is the maximum and means it lasts
59
* 1 frame. 20 means that it lasts 1000/20 = 50 frames.
60
* Speed 0 marks the last keyframe. Since the cubic spline looks 3 keyframes
61
* ahead, there should be at least 2 more entries afterwards.
62
* The last three numbers of each entry are x, y and z coordinates of points
63
* that define the curve.
64
*/
65
static Vec4s sJumboStarKeyframes[27] = {
66
{ 20, 0, 678, -2916 }, { 30, 0, 680, -3500 }, { 40, 1000, 700, -4000 },
67
{ 50, 2500, 750, -3500 }, { 50, 3500, 800, -2000 }, { 50, 4000, 850, 0 },
68
{ 50, 3500, 900, 2000 }, { 50, 2000, 950, 3500 }, { 50, 0, 1000, 4000 },
69
{ 50, -2000, 1050, 3500 }, { 50, -3500, 1100, 2000 }, { 50, -4000, 1150, 0 },
70
{ 50, -3500, 1200, -2000 }, { 50, -2000, 1250, -3500 }, { 50, 0, 1300, -4000 },
71
{ 50, 2000, 1350, -3500 }, { 50, 3500, 1400, -2000 }, { 50, 4000, 1450, 0 },
72
{ 50, 3500, 1500, 2000 }, { 50, 2000, 1600, 3500 }, { 50, 0, 1700, 4000 },
73
{ 50, -2000, 1800, 3500 }, { 50, -3500, 1900, 2000 }, { 30, -4000, 2000, 0 },
74
{ 0, -3500, 2100, -2000 }, { 0, -2000, 2200, -3500 }, { 0, 0, 2300, -4000 },
75
};
76
77
/**
78
* get_credits_str_width: Calculate width of a Credits String
79
* Loop over each character in a credits string and increment the length. If the
80
* character is a space, increment by 4; otherwise increment by 7. Once the next
81
* character is a null character (equal to 0), stop counting the length since
82
* that's the end of the string.
83
*/
84
s32 get_credits_str_width(char *str) {
85
u32 c;
86
s32 length = 0;
87
88
while ((c = *str++) != 0) {
89
length += (c == ' ' ? 4 : 7);
90
}
91
92
return length;
93
}
94
95
#define CREDIT_TEXT_MARGIN_X ((s32)(GFX_DIMENSIONS_ASPECT_RATIO * 21))
96
#define CREDIT_TEXT_X_LEFT GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(CREDIT_TEXT_MARGIN_X)
97
#define CREDIT_TEXT_X_RIGHT GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(CREDIT_TEXT_MARGIN_X)
98
99
/**
100
* print_displaying_credits_entry: Print the current displaying Credits Entry
101
* Called in render_game. This function checks if sDispCreditsEntry points to a
102
* credits entry (see act_credits_cutscene), and if so, display it. The reason
103
* this is called every frame in render_game is because the credits need to
104
* display on top of everything else.
105
* To print a credits entry, we take the first character of the first string,
106
* subtract the value of the 0 character, and use that as the number of lines to
107
* print, excluding the title. Then, we print the title (after advancing the
108
* pointer by 1) at X 28, Y either 28 or 172, depending on the print at bottom
109
* flag. Finally, we print each line using the number of lines previously stored
110
* as a counter, and increase the Y value by either the constant 16 (JP only) or
111
* by the value of lineHeight.
112
*/
113
void print_displaying_credits_entry(void) {
114
char **currStrPtr;
115
char *titleStr;
116
s16 numLines;
117
s16 strY;
118
#ifndef VERSION_JP
119
s16 lineHeight;
120
#endif
121
122
if (sDispCreditsEntry != NULL) {
123
currStrPtr = (char **) sDispCreditsEntry->unk0C;
124
titleStr = *currStrPtr++;
125
numLines = *titleStr++ - '0';
126
127
strY = (sDispCreditsEntry->unk02 & 0x20 ? 28 : 172) + (numLines == 1) * 16;
128
#ifndef VERSION_JP
129
lineHeight = 16;
130
#endif
131
132
dl_rgba16_begin_cutscene_msg_fade();
133
print_credits_str_ascii(CREDIT_TEXT_X_LEFT, strY, titleStr);
134
135
#ifndef VERSION_JP
136
switch (numLines) {
137
case 4:
138
print_credits_str_ascii(CREDIT_TEXT_X_LEFT, strY + 24, *currStrPtr++);
139
numLines = 2;
140
lineHeight = 24;
141
break;
142
case 5:
143
print_credits_str_ascii(CREDIT_TEXT_X_LEFT, strY + 16, *currStrPtr++);
144
numLines = 3;
145
break;
146
#ifdef VERSION_EU
147
case 6:
148
print_credits_str_ascii(CREDIT_TEXT_X_LEFT, strY + 32, *currStrPtr++);
149
numLines = 3;
150
break;
151
case 7:
152
print_credits_str_ascii(CREDIT_TEXT_X_LEFT, strY + 16, *currStrPtr++);
153
print_credits_str_ascii(CREDIT_TEXT_X_LEFT, strY + 32, *currStrPtr++);
154
numLines = 3;
155
break;
156
#endif
157
}
158
#endif
159
160
while (numLines-- > 0) {
161
print_credits_str_ascii(CREDIT_TEXT_X_RIGHT - get_credits_str_width(*currStrPtr), strY, *currStrPtr);
162
163
#ifdef VERSION_JP
164
strY += 16;
165
#else
166
strY += lineHeight;
167
#endif
168
169
currStrPtr++;
170
}
171
172
dl_rgba16_stop_cutscene_msg_fade();
173
sDispCreditsEntry = NULL;
174
}
175
}
176
177
void bhv_end_peach_loop(void) {
178
cur_obj_init_animation_with_sound(sEndPeachAnimation);
179
if (cur_obj_check_if_near_animation_end()) {
180
// anims: 0-3, 4, 5, 6-8, 9, 10, 11
181
if (sEndPeachAnimation < 3 || sEndPeachAnimation == 6 || sEndPeachAnimation == 7) {
182
sEndPeachAnimation++;
183
}
184
}
185
}
186
187
void bhv_end_toad_loop(void) {
188
s32 toadAnimIndex = (gCurrentObject->oPosX >= 0.0f);
189
190
cur_obj_init_animation_with_sound(sEndToadAnims[toadAnimIndex]);
191
if (cur_obj_check_if_near_animation_end()) {
192
// 0-1, 2-3, 4, 5, 6, 7
193
if (sEndToadAnims[toadAnimIndex] == 0 || sEndToadAnims[toadAnimIndex] == 2) {
194
sEndToadAnims[toadAnimIndex]++;
195
}
196
}
197
}
198
199
// Geo switch case function for controlling Peach's eye state.
200
s32 geo_switch_peach_eyes(s32 run, struct GraphNode *node, UNUSED s32 a2) {
201
struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
202
s16 timer;
203
204
if (run == TRUE) {
205
if (D_8032CBE4 == 0) {
206
timer = (gAreaUpdateCounter + 0x20) >> 1 & 0x1F;
207
if (timer < 7) {
208
switchCase->selectedCase = D_8032CBE8 * 4 + D_8032CBEC[timer];
209
} else {
210
switchCase->selectedCase = D_8032CBE8 * 4 + 1;
211
}
212
} else {
213
switchCase->selectedCase = D_8032CBE8 * 4 + D_8032CBE4 - 1;
214
}
215
}
216
217
return 0;
218
}
219
220
// unused
221
UNUSED static void stub_is_textbox_active(u16 *arg) {
222
if (get_dialog_id() == DIALOG_NONE) {
223
*arg = 0;
224
}
225
}
226
227
/**
228
* get_star_collection_dialog: Determine what dialog should show when Mario
229
* collects a star.
230
* Determines if Mario has collected enough stars to get a dialog for it, and
231
* if so, return the dialog ID. Otherwise, return 0. A dialog is returned if
232
* numStars has reached a milestone and prevNumStarsForDialog has not reached it.
233
*/
234
s32 get_star_collection_dialog(struct MarioState *m) {
235
s32 i;
236
s32 dialogID = 0;
237
s32 numStarsRequired;
238
239
if (configSkipCutscenes)
240
return 0;
241
242
for (i = 0; i < ARRAY_COUNT(sStarsNeededForDialog); i++) {
243
numStarsRequired = sStarsNeededForDialog[i];
244
if (m->prevNumStarsForDialog < numStarsRequired && m->numStars >= numStarsRequired) {
245
dialogID = i + DIALOG_141;
246
break;
247
}
248
}
249
250
m->prevNumStarsForDialog = m->numStars;
251
return dialogID;
252
}
253
254
// save menu handler
255
void handle_save_menu(struct MarioState *m) {
256
s32 dialogID;
257
// wait for the menu to show up
258
if (is_anim_past_end(m) && gSaveOptSelectIndex != MENU_OPT_NONE) {
259
// save and continue / save and quit
260
if (gSaveOptSelectIndex == MENU_OPT_SAVE_AND_CONTINUE || gSaveOptSelectIndex == MENU_OPT_SAVE_AND_QUIT) {
261
save_file_do_save(gCurrSaveFileNum - 1);
262
263
if (gSaveOptSelectIndex == MENU_OPT_SAVE_AND_QUIT) {
264
if (configQuitOption)
265
exit(0);
266
else
267
fade_into_special_warp(-2, 0); // reset game
268
}
269
}
270
271
// not quitting
272
if (gSaveOptSelectIndex != MENU_OPT_SAVE_AND_QUIT) {
273
disable_time_stop();
274
m->faceAngle[1] += 0x8000;
275
// figure out what dialog to show, if we should
276
dialogID = get_star_collection_dialog(m);
277
if (dialogID) {
278
play_peachs_jingle();
279
// look up for dialog
280
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, dialogID);
281
} else {
282
set_mario_action(m, ACT_IDLE, 0);
283
}
284
}
285
}
286
}
287
288
/**
289
* spawn_obj_at_mario_rel_yaw: Spawns object at Mario with relative yaw.
290
* Spawns object with given behavior and model and copies over Mario's position
291
* and yaw plus relative yaw.
292
*/
293
struct Object *spawn_obj_at_mario_rel_yaw(struct MarioState *m, s32 model, const BehaviorScript *behavior, s16 relYaw) {
294
struct Object *o = spawn_object(m->marioObj, model, behavior);
295
296
o->oFaceAngleYaw = m->faceAngle[1] + relYaw;
297
o->oPosX = m->pos[0];
298
o->oPosY = m->pos[1];
299
o->oPosZ = m->pos[2];
300
301
return o;
302
}
303
304
/**
305
* cutscene_take_cap_off: Put Mario's cap on.
306
* Clears "cap on head" flag, sets "cap in hand" flag, plays sound
307
* SOUND_ACTION_UNKNOWN43D.
308
*/
309
void cutscene_take_cap_off(struct MarioState *m) {
310
m->flags &= ~MARIO_CAP_ON_HEAD;
311
m->flags |= MARIO_CAP_IN_HAND;
312
play_sound(SOUND_ACTION_UNKNOWN43D, m->marioObj->header.gfx.cameraToObject);
313
}
314
315
/**
316
* cutscene_put_cap_on: Put Mario's cap on.
317
* Clears "cap in hand" flag, sets "cap on head" flag, plays sound
318
* SOUND_ACTION_UNKNOWN43E.
319
*/
320
void cutscene_put_cap_on(struct MarioState *m) {
321
m->flags &= ~MARIO_CAP_IN_HAND;
322
m->flags |= MARIO_CAP_ON_HEAD;
323
play_sound(SOUND_ACTION_UNKNOWN43E, m->marioObj->header.gfx.cameraToObject);
324
}
325
326
/**
327
* mario_ready_to_speak: Determine if Mario is able to speak to a NPC
328
* The following conditions must be met in order for Mario to be considered
329
* ready to speak.
330
* 1: Mario's action must be in the stationary or moving action groups, or if
331
* not, he must be in the "waiting for dialog" state.
332
* 2: Mario mat not be riding a shell or be invulnerable.
333
* 3: Mario must not be in first person mode.
334
*/
335
s32 mario_ready_to_speak(void) {
336
u32 actionGroup = gMarioState->action & ACT_GROUP_MASK;
337
s32 isReadyToSpeak = FALSE;
338
339
if ((gMarioState->action == ACT_WAITING_FOR_DIALOG || actionGroup == ACT_GROUP_STATIONARY
340
|| actionGroup == ACT_GROUP_MOVING)
341
&& (!(gMarioState->action & (ACT_FLAG_RIDING_SHELL | ACT_FLAG_INVULNERABLE))
342
&& gMarioState->action != ACT_FIRST_PERSON)) {
343
isReadyToSpeak = TRUE;
344
}
345
346
return isReadyToSpeak;
347
}
348
349
// (can) place Mario in dialog?
350
// initiate dialog?
351
// return values:
352
// 0 = not in dialog
353
// 1 = starting dialog
354
// 2 = speaking
355
s32 set_mario_npc_dialog(s32 actionArg) {
356
s32 dialogState = MARIO_DIALOG_STATUS_NONE;
357
358
// in dialog
359
if (gMarioState->action == ACT_READING_NPC_DIALOG) {
360
if (gMarioState->actionState < 8) {
361
dialogState = MARIO_DIALOG_STATUS_START; // starting dialog
362
}
363
if (gMarioState->actionState == 8) {
364
if (actionArg == MARIO_DIALOG_STOP) {
365
gMarioState->actionState++; // exit dialog
366
} else {
367
dialogState = MARIO_DIALOG_STATUS_SPEAK;
368
}
369
}
370
} else if (actionArg != 0 && mario_ready_to_speak()) {
371
gMarioState->usedObj = gCurrentObject;
372
set_mario_action(gMarioState, ACT_READING_NPC_DIALOG, actionArg);
373
dialogState = MARIO_DIALOG_STATUS_START; // starting dialog
374
}
375
376
return dialogState;
377
}
378
379
// actionargs:
380
// 1 : no head turn
381
// 2 : look up
382
// 3 : look down
383
// actionstate values:
384
// 0 - 7: looking toward npc
385
// 8: in dialog
386
// 9 - 22: looking away from npc
387
// 23: end
388
s32 act_reading_npc_dialog(struct MarioState *m) {
389
s32 headTurnAmount = 0;
390
s16 angleToNPC;
391
392
if (m->actionArg == MARIO_DIALOG_LOOK_UP) {
393
headTurnAmount = -1024;
394
}
395
if (m->actionArg == MARIO_DIALOG_LOOK_DOWN) {
396
headTurnAmount = 384;
397
}
398
399
if (m->actionState < 8) {
400
// turn to NPC
401
angleToNPC = mario_obj_angle_to_object(m, m->usedObj);
402
m->faceAngle[1] =
403
angleToNPC - approach_s32((angleToNPC - m->faceAngle[1]) << 16 >> 16, 0, 2048, 2048);
404
// turn head to npc
405
m->actionTimer += headTurnAmount;
406
// set animation
407
set_mario_animation(m, m->heldObj == NULL ? MARIO_ANIM_FIRST_PERSON
408
: MARIO_ANIM_IDLE_WITH_LIGHT_OBJ);
409
} else if (m->actionState >= 9 && m->actionState < 17) {
410
// look back from facing NPC
411
m->actionTimer -= headTurnAmount;
412
} else if (m->actionState == 23) {
413
if (m->flags & MARIO_CAP_IN_HAND) {
414
set_mario_action(m, ACT_PUTTING_ON_CAP, 0);
415
} else {
416
set_mario_action(m, m->heldObj == NULL ? ACT_IDLE : ACT_HOLD_IDLE, 0);
417
}
418
}
419
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
420
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
421
vec3s_set(m->marioBodyState->headAngle, m->actionTimer, 0, 0);
422
423
if (m->actionState != 8) {
424
m->actionState++;
425
}
426
427
return FALSE;
428
}
429
430
// puts Mario in a state where he's waiting for (npc) dialog; doesn't do much
431
s32 act_waiting_for_dialog(struct MarioState *m) {
432
set_mario_animation(m, m->heldObj == NULL ? MARIO_ANIM_FIRST_PERSON
433
: MARIO_ANIM_IDLE_WITH_LIGHT_OBJ);
434
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
435
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
436
return FALSE;
437
}
438
439
// makes Mario disappear and triggers warp
440
s32 act_disappeared(struct MarioState *m) {
441
set_mario_animation(m, MARIO_ANIM_A_POSE);
442
stop_and_set_height_to_floor(m);
443
m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
444
if (m->actionArg) {
445
m->actionArg--;
446
if ((m->actionArg & 0xFFFF) == 0) {
447
level_trigger_warp(m, m->actionArg >> 16);
448
}
449
}
450
return FALSE;
451
}
452
453
s32 act_reading_automatic_dialog(struct MarioState *m) {
454
u32 actionArg;
455
456
m->actionState++;
457
if (m->actionState == 2) {
458
enable_time_stop();
459
}
460
if (m->actionState < 9) {
461
set_mario_animation(m, m->prevAction == ACT_STAR_DANCE_WATER ? MARIO_ANIM_WATER_IDLE
462
: MARIO_ANIM_FIRST_PERSON);
463
// always look up for automatic dialogs
464
m->actionTimer -= 1024;
465
} else {
466
// set Mario dialog
467
if (m->actionState == 9) {
468
actionArg = m->actionArg;
469
if (GET_HIGH_U16_OF_32(actionArg) == 0) {
470
create_dialog_box(GET_LOW_U16_OF_32(actionArg));
471
} else {
472
create_dialog_box_with_var(GET_HIGH_U16_OF_32(actionArg), GET_LOW_U16_OF_32(actionArg));
473
}
474
}
475
// wait until dialog is done
476
else if (m->actionState == 10) {
477
if (get_dialog_id() >= 0) {
478
m->actionState--;
479
}
480
}
481
// look back down
482
else if (m->actionState < 19) {
483
m->actionTimer += 1024;
484
}
485
// finished action
486
else if (m->actionState == 25) {
487
disable_time_stop();
488
if (gNeverEnteredCastle && !stay_in_level()) {
489
gNeverEnteredCastle = FALSE;
490
play_cutscene_music(SEQUENCE_ARGS(0, SEQ_LEVEL_INSIDE_CASTLE));
491
}
492
if (m->prevAction == ACT_STAR_DANCE_WATER) {
493
set_mario_action(m, ACT_WATER_IDLE, 0); // 100c star?
494
} else {
495
// make Mario walk into door after star dialog
496
set_mario_action(m, m->prevAction == ACT_UNLOCKING_STAR_DOOR ? ACT_WALKING : ACT_IDLE,
497
0);
498
}
499
}
500
}
501
// apply head turn
502
vec3s_set(m->marioBodyState->headAngle, m->actionTimer, 0, 0);
503
return FALSE;
504
}
505
506
s32 act_reading_sign(struct MarioState *m) {
507
struct Object *marioObj = m->marioObj;
508
509
play_sound_if_no_flag(m, SOUND_ACTION_READ_SIGN, MARIO_ACTION_SOUND_PLAYED);
510
511
switch (m->actionState) {
512
// start dialog
513
case 0:
514
trigger_cutscene_dialog(1);
515
enable_time_stop();
516
// reading sign
517
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
518
m->actionState = 1;
519
// intentional fall through
520
// turn toward sign
521
case 1:
522
m->faceAngle[1] += marioObj->oMarioPoleUnk108 / 11;
523
m->pos[0] += marioObj->oMarioReadingSignDPosX / 11.0f;
524
m->pos[2] += marioObj->oMarioReadingSignDPosZ / 11.0f;
525
// create the text box
526
if (m->actionTimer++ == 10) {
527
create_dialog_inverted_box(m->usedObj->oBehParams2ndByte);
528
m->actionState = 2;
529
}
530
break;
531
// in dialog
532
case 2:
533
// dialog finished
534
if (gCamera->cutscene == 0) {
535
disable_time_stop();
536
set_mario_action(m, ACT_IDLE, 0);
537
}
538
break;
539
}
540
541
vec3f_copy(marioObj->header.gfx.pos, m->pos);
542
vec3s_set(marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
543
return FALSE;
544
}
545
546
s32 act_debug_free_move(struct MarioState *m) {
547
struct Surface *surf;
548
f32 floorHeight;
549
Vec3f pos;
550
f32 speed;
551
u32 action;
552
553
// integer immediates, generates convert instructions for some reason
554
speed = gPlayer1Controller->buttonDown & B_BUTTON ? 4 : 1;
555
if (gPlayer1Controller->buttonDown & L_TRIG) {
556
speed = 0.01f;
557
}
558
559
set_mario_animation(m, MARIO_ANIM_A_POSE);
560
vec3f_copy(pos, m->pos);
561
562
if (gPlayer1Controller->buttonDown & U_JPAD) {
563
pos[1] += 16.0f * speed;
564
}
565
if (gPlayer1Controller->buttonDown & D_JPAD) {
566
pos[1] -= 16.0f * speed;
567
}
568
569
if (m->intendedMag > 0) {
570
pos[0] += 32.0f * speed * sins(m->intendedYaw);
571
pos[2] += 32.0f * speed * coss(m->intendedYaw);
572
}
573
574
resolve_and_return_wall_collisions(pos, 60.0f, 50.0f);
575
576
floorHeight = find_floor(pos[0], pos[1], pos[2], &surf);
577
if (surf != NULL) {
578
if (pos[1] < floorHeight) {
579
pos[1] = floorHeight;
580
}
581
vec3f_copy(m->pos, pos);
582
}
583
584
m->faceAngle[1] = m->intendedYaw;
585
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
586
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
587
588
if (gPlayer1Controller->buttonPressed == A_BUTTON) {
589
if (m->pos[1] <= m->waterLevel - 100) {
590
action = ACT_WATER_IDLE;
591
} else {
592
action = ACT_IDLE;
593
}
594
set_mario_action(m, action, 0);
595
}
596
597
return FALSE;
598
}
599
600
void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
601
s32 dialogID;
602
if (m->actionState == 0) {
603
switch (++m->actionTimer) {
604
case 1:
605
spawn_object(m->marioObj, MODEL_STAR, bhvCelebrationStar);
606
disable_background_sound();
607
if (m->actionArg & 1) {
608
play_course_clear();
609
} else {
610
if (gCurrLevelNum == LEVEL_BOWSER_1 || gCurrLevelNum == LEVEL_BOWSER_2) {
611
play_music(SEQ_PLAYER_ENV, SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_COLLECT_KEY), 0);
612
} else {
613
play_music(SEQ_PLAYER_ENV, SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_COLLECT_STAR), 0);
614
}
615
}
616
// We will be extending the cap timer artificially for this star.
617
if (configStayInCourse && gCollectedStar == 5 && gCurrLevelNum == LEVEL_DDD) {
618
619
if (m->flags & MARIO_CAP_ON_HEAD) {
620
m->flags |= MARIO_VANISH_CAP;
621
}
622
if (m->capTimer < 300) {
623
m->capTimer = 300;
624
}
625
}
626
break;
627
628
case 42:
629
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
630
if (configStayInCourse) {
631
gHudDisplay.starGet = 1;
632
if (!sTimerRunning)
633
level_control_timer(TIMER_CONTROL_HIDE);
634
}
635
break;
636
637
case 80:
638
if ((m->actionArg & 1) == 0) {
639
level_trigger_warp(m, restart_level_after_star() ? WARP_OP_CUSTOM_RESET : WARP_OP_STAR_EXIT);
640
} else {
641
642
// Ugly code ahead!
643
// This is the most readable I could make the code without overcomplicating it
644
645
// First let's get if we have all the stars
646
s32 i;
647
u8 starCount = 0;
648
u8 flag = 1;
649
u8 starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1);
650
for (i = 0; i < 7; i++, flag <<= 1) {
651
if (!(starFlags & flag)) {
652
starCount++;
653
}
654
}
655
656
// If we set it to ask
657
if (configStayInCourse > 0 &&
658
(gCurrLevelNum == LEVEL_CASTLE_GROUNDS || gCurrLevelNum == LEVEL_CASTLE || gCurrLevelNum == LEVEL_CASTLE_COURTYARD))
659
{
660
enable_time_stop();
661
create_dialog_box_with_response(DIALOG_014);
662
m->actionState = 1;
663
}
664
else if (configStayInCourse == 1) {
665
enable_time_stop();
666
create_dialog_box_with_response(gLastCompletedStarNum == 7 ? DIALOG_171 : DIALOG_170);
667
m->actionState = 1;
668
}
669
else if (configStayInCourse == 2 && starCount >= 7) {
670
enable_time_stop();
671
create_dialog_box_with_response(gLastCompletedStarNum == 7 ? DIALOG_171 : DIALOG_175);
672
m->actionState = 1;
673
}
674
// If it's automatic
675
else if (configStayInCourse == 3) {
676
if ((gLastCompletedStarNum == 7) ||
677
(gCurrAreaIndex > 1 && (gCurrLevelNum == LEVEL_SSL || gCurrLevelNum == LEVEL_LLL || gCurrLevelNum == LEVEL_WDW))) {
678
enable_time_stop();
679
create_dialog_box_with_response(gLastCompletedStarNum == 7 ? DIALOG_171 : DIALOG_170);
680
m->actionState = 1;
681
}
682
else {
683
save_file_do_save(gCurrSaveFileNum - 1);
684
m->actionState = 2;
685
}
686
}
687
// If it's set to always
688
else if (configStayInCourse == 2) {
689
save_file_do_save(gCurrSaveFileNum - 1);
690
m->actionState = 2;
691
}
692
// By default
693
else {
694
enable_time_stop();
695
create_dialog_box_with_response((gLastCompletedStarNum == 7) ? DIALOG_013 : DIALOG_014);
696
m->actionState = 1;
697
}
698
}
699
break;
700
}
701
} else if (m->actionState == 1 && gDialogResponse != DIALOG_RESPONSE_NONE) {
702
if (gDialogResponse == DIALOG_RESPONSE_YES) {
703
save_file_do_save(gCurrSaveFileNum - 1);
704
}
705
else if (configStayInCourse > 0) {
706
level_trigger_warp(m, WARP_OP_STAR_EXIT);
707
}
708
m->actionState = 2;
709
} else if (m->actionState == 2 && is_anim_at_end(m)) {
710
disable_time_stop();
711
enable_background_sound();
712
dialogID = get_star_collection_dialog(m);
713
if (dialogID) {
714
// look up for dialog
715
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, dialogID);
716
} else {
717
set_mario_action(m, isInWater ? ACT_WATER_IDLE : ACT_IDLE, 0);
718
}
719
}
720
}
721
722
s8 get_random_hand_sign(struct MarioState *m) {
723
s8 handSign = m->faceAngle[1] % 3;
724
if (handSign == 0) {
725
return MARIO_HAND_PEACE_SIGN;
726
} else if (handSign == 1) {
727
return MARIO_HAND_RIGHT_OPEN;
728
} else {
729
return MARIO_HAND_FISTS;
730
}
731
}
732
733
s32 act_star_dance(struct MarioState *m) {
734
m->faceAngle[1] = m->area->camera->yaw;
735
set_mario_animation(m, m->actionState == 2 ? MARIO_ANIM_RETURN_FROM_STAR_DANCE
736
: MARIO_ANIM_STAR_DANCE);
737
general_star_dance_handler(m, 0);
738
if (m->actionState != 2 && m->actionTimer >= 40) {
739
m->marioBodyState->handState = configRockPaperScissors ? get_random_hand_sign(m) : MARIO_HAND_PEACE_SIGN;
740
}
741
stop_and_set_height_to_floor(m);
742
return FALSE;
743
}
744
745
s32 act_star_dance_water(struct MarioState *m) {
746
m->faceAngle[1] = m->area->camera->yaw;
747
set_mario_animation(m, m->actionState == 2 ? MARIO_ANIM_RETURN_FROM_WATER_STAR_DANCE
748
: MARIO_ANIM_WATER_STAR_DANCE);
749
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
750
vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
751
general_star_dance_handler(m, 1);
752
if (m->actionState != 2 && m->actionTimer >= 62) {
753
m->marioBodyState->handState = configRockPaperScissors ? get_random_hand_sign(m) : MARIO_HAND_PEACE_SIGN;
754
}
755
return FALSE;
756
}
757
758
s32 act_fall_after_star_grab(struct MarioState *m) {
759
if (m->pos[1] < m->waterLevel - 130) {
760
play_sound(SOUND_ACTION_UNKNOWN430, m->marioObj->header.gfx.cameraToObject);
761
m->particleFlags |= PARTICLE_WATER_SPLASH;
762
return set_mario_action(m, ACT_STAR_DANCE_WATER, m->actionArg);
763
}
764
if (perform_air_step(m, 1) == AIR_STEP_LANDED) {
765
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
766
set_mario_action(m, m->actionArg & 1 ? ACT_STAR_DANCE_NO_EXIT : ACT_STAR_DANCE_EXIT,
767
m->actionArg);
768
}
769
set_mario_animation(m, MARIO_ANIM_GENERAL_FALL);
770
return FALSE;
771
}
772
773
s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWarp) {
774
s32 animFrame = set_mario_animation(m, animation);
775
if (animFrame == frameToDeathWarp) {
776
level_trigger_warp(m, WARP_OP_DEATH);
777
}
778
m->marioBodyState->eyeState = MARIO_EYES_DEAD;
779
stop_and_set_height_to_floor(m);
780
return animFrame;
781
}
782
783
s32 act_standing_death(struct MarioState *m) {
784
if (m->input & INPUT_IN_POISON_GAS) {
785
return set_mario_action(m, ACT_SUFFOCATION, 0);
786
}
787
788
play_sound_if_no_flag(m, SOUND_MARIO_DYING, MARIO_ACTION_SOUND_PLAYED);
789
common_death_handler(m, MARIO_ANIM_DYING_FALL_OVER, 80);
790
if (m->marioObj->header.gfx.animInfo.animFrame == 77) {
791
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND);
792
}
793
return FALSE;
794
}
795
796
s32 act_electrocution(struct MarioState *m) {
797
play_sound_if_no_flag(m, SOUND_MARIO_DYING, MARIO_ACTION_SOUND_PLAYED);
798
common_death_handler(m, MARIO_ANIM_ELECTROCUTION, 43);
799
return FALSE;
800
}
801
802
s32 act_suffocation(struct MarioState *m) {
803
play_sound_if_no_flag(m, SOUND_MARIO_DYING, MARIO_ACTION_SOUND_PLAYED);
804
common_death_handler(m, MARIO_ANIM_SUFFOCATING, 86);
805
return FALSE;
806
}
807
808
s32 act_death_on_back(struct MarioState *m) {
809
play_sound_if_no_flag(m, SOUND_MARIO_DYING, MARIO_ACTION_SOUND_PLAYED);
810
if (common_death_handler(m, MARIO_ANIM_DYING_ON_BACK, 54) == 40) {
811
play_mario_heavy_landing_sound(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND);
812
}
813
return FALSE;
814
}
815
816
s32 act_death_on_stomach(struct MarioState *m) {
817
play_sound_if_no_flag(m, SOUND_MARIO_DYING, MARIO_ACTION_SOUND_PLAYED);
818
if (common_death_handler(m, MARIO_ANIM_DYING_ON_STOMACH, 37) == 37) {
819
play_mario_heavy_landing_sound(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND);
820
}
821
return FALSE;
822
}
823
824
s32 act_quicksand_death(struct MarioState *m) {
825
if (m->actionState == 0) {
826
set_mario_animation(m, MARIO_ANIM_DYING_IN_QUICKSAND);
827
set_anim_to_frame(m, 60);
828
m->actionState = 1;
829
}
830
if (m->actionState == 1) {
831
if (m->quicksandDepth >= 100.0f) {
832
play_sound_if_no_flag(m, SOUND_MARIO_WAAAOOOW, MARIO_ACTION_SOUND_PLAYED);
833
}
834
if ((m->quicksandDepth += 5.0f) >= 180.0f) {
835
level_trigger_warp(m, WARP_OP_DEATH);
836
m->actionState = 2;
837
}
838
}
839
stationary_ground_step(m);
840
play_sound(SOUND_MOVING_QUICKSAND_DEATH, m->marioObj->header.gfx.cameraToObject);
841
return FALSE;
842
}
843
844
s32 act_eaten_by_bubba(struct MarioState *m) {
845
play_sound_if_no_flag(m, SOUND_MARIO_DYING, MARIO_ACTION_SOUND_PLAYED);
846
set_mario_animation(m, MARIO_ANIM_A_POSE);
847
m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
848
m->health = 0xFF;
849
if (m->actionTimer++ == 60) {
850
level_trigger_warp(m, WARP_OP_DEATH);
851
}
852
return FALSE;
853
}
854
855
// set animation and forwardVel; when perform_air_step returns AIR_STEP_LANDED,
856
// set the new action
857
s32 launch_mario_until_land(struct MarioState *m, s32 endAction, s32 animation, f32 forwardVel) {
858
s32 airStepLanded;
859
mario_set_forward_vel(m, forwardVel);
860
set_mario_animation(m, animation);
861
airStepLanded = (perform_air_step(m, 0) == AIR_STEP_LANDED);
862
if (airStepLanded) {
863
set_mario_action(m, endAction, 0);
864
}
865
return airStepLanded;
866
}
867
868
s32 act_unlocking_key_door(struct MarioState *m) {
869
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
870
871
m->pos[0] = m->usedObj->oPosX + coss(m->faceAngle[1]) * 75.0f;
872
m->pos[2] = m->usedObj->oPosZ + sins(m->faceAngle[1]) * 75.0f;
873
874
if (m->actionArg & 2) {
875
m->faceAngle[1] += 0x8000;
876
}
877
878
if (m->actionTimer == 0) {
879
spawn_obj_at_mario_rel_yaw(m, MODEL_BOWSER_KEY_CUTSCENE, bhvBowserKeyUnlockDoor, 0);
880
set_mario_animation(m, MARIO_ANIM_UNLOCK_DOOR);
881
}
882
883
switch (m->marioObj->header.gfx.animInfo.animFrame) {
884
case 79:
885
play_sound(SOUND_GENERAL_DOOR_INSERT_KEY, m->marioObj->header.gfx.cameraToObject);
886
break;
887
case 111:
888
play_sound(SOUND_GENERAL_DOOR_TURN_KEY, m->marioObj->header.gfx.cameraToObject);
889
break;
890
}
891
892
update_mario_pos_for_anim(m);
893
stop_and_set_height_to_floor(m);
894
895
if (is_anim_at_end(m)) {
896
if (m->usedObj->oBehParams >> 24 == 1) {
897
save_file_set_flags(SAVE_FLAG_UNLOCKED_UPSTAIRS_DOOR);
898
save_file_clear_flags(SAVE_FLAG_HAVE_KEY_2);
899
} else {
900
save_file_set_flags(SAVE_FLAG_UNLOCKED_BASEMENT_DOOR);
901
save_file_clear_flags(SAVE_FLAG_HAVE_KEY_1);
902
}
903
set_mario_action(m, ACT_WALKING, 0);
904
}
905
906
m->actionTimer++;
907
return FALSE;
908
}
909
910
s32 act_unlocking_star_door(struct MarioState *m) {
911
switch (m->actionState) {
912
case 0:
913
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
914
if (m->actionArg & 2) {
915
m->faceAngle[1] += 0x8000;
916
}
917
m->marioObj->oMarioReadingSignDPosX = m->pos[0];
918
m->marioObj->oMarioReadingSignDPosZ = m->pos[2];
919
set_mario_animation(m, MARIO_ANIM_SUMMON_STAR);
920
m->actionState++;
921
break;
922
case 1:
923
if (is_anim_at_end(m)) {
924
spawn_object(m->marioObj, MODEL_STAR, bhvUnlockDoorStar);
925
m->actionState++;
926
}
927
break;
928
case 2:
929
if (m->actionTimer++ == 70) {
930
set_mario_animation(m, MARIO_ANIM_RETURN_STAR_APPROACH_DOOR);
931
m->actionState++;
932
}
933
break;
934
case 3:
935
if (is_anim_at_end(m)) {
936
save_file_set_flags(get_door_save_file_flag(m->usedObj));
937
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, DIALOG_038);
938
}
939
break;
940
}
941
942
m->pos[0] = m->marioObj->oMarioReadingSignDPosX;
943
m->pos[2] = m->marioObj->oMarioReadingSignDPosZ;
944
945
update_mario_pos_for_anim(m);
946
stop_and_set_height_to_floor(m);
947
948
return FALSE;
949
}
950
951
s32 act_entering_star_door(struct MarioState *m) {
952
f32 targetDX;
953
f32 targetDZ;
954
s16 targetAngle;
955
956
if (m->actionTimer++ == 0) {
957
m->interactObj->oInteractStatus = 0x00010000;
958
959
// ~30 degrees / 1/12 rot
960
targetAngle = m->usedObj->oMoveAngleYaw + 0x1555;
961
if (m->actionArg & 2) {
962
targetAngle += 0x5556; // ~120 degrees / 1/3 rot (total 150d / 5/12)
963
}
964
965
// targetDX and targetDZ are the offsets to add to Mario's position to
966
// have Mario stand 150 units in front of the door
967
968
targetDX = m->usedObj->oPosX + 150.0f * sins(targetAngle) - m->pos[0];
969
targetDZ = m->usedObj->oPosZ + 150.0f * coss(targetAngle) - m->pos[2];
970
971
m->marioObj->oMarioReadingSignDPosX = targetDX / 20.0f;
972
m->marioObj->oMarioReadingSignDPosZ = targetDZ / 20.0f;
973
974
m->faceAngle[1] = atan2s(targetDZ, targetDX);
975
}
976
977
// set Mario's animation
978
if (m->actionTimer < 15) {
979
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
980
}
981
982
// go through door? for 20 frames
983
else if (m->actionTimer < 35) {
984
m->pos[0] += m->marioObj->oMarioReadingSignDPosX;
985
m->pos[2] += m->marioObj->oMarioReadingSignDPosZ;
986
987
set_mario_anim_with_accel(m, MARIO_ANIM_WALKING, 0x00028000);
988
}
989
990
else {
991
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
992
993
if (m->actionArg & 2) {
994
m->faceAngle[1] += 0x8000;
995
}
996
997
m->pos[0] += 12.0f * sins(m->faceAngle[1]);
998
m->pos[2] += 12.0f * coss(m->faceAngle[1]);
999
1000
set_mario_anim_with_accel(m, MARIO_ANIM_WALKING, 0x00028000);
1001
}
1002
1003
stop_and_set_height_to_floor(m);
1004
1005
if (m->actionTimer == 48) {
1006
set_mario_action(m, ACT_IDLE, 0);
1007
}
1008
1009
return FALSE;
1010
}
1011
1012
s32 act_going_through_door(struct MarioState *m) {
1013
if (m->actionTimer == 0) {
1014
if (m->actionArg & 1) {
1015
m->interactObj->oInteractStatus = 0x00010000;
1016
set_mario_animation(m, MARIO_ANIM_PULL_DOOR_WALK_IN);
1017
} else {
1018
m->interactObj->oInteractStatus = 0x00020000;
1019
set_mario_animation(m, MARIO_ANIM_PUSH_DOOR_WALK_IN);
1020
}
1021
}
1022
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
1023
m->pos[0] = m->usedObj->oPosX;
1024
m->pos[2] = m->usedObj->oPosZ;
1025
1026
update_mario_pos_for_anim(m);
1027
stop_and_set_height_to_floor(m);
1028
1029
if (m->actionArg & 4) {
1030
if (m->actionTimer == 16) {
1031
level_trigger_warp(m, WARP_OP_WARP_DOOR);
1032
}
1033
} else if (is_anim_at_end(m)) {
1034
if (m->actionArg & 2) {
1035
m->faceAngle[1] += 0x8000;
1036
}
1037
set_mario_action(m, ACT_IDLE, 0);
1038
}
1039
1040
m->actionTimer++;
1041
return FALSE;
1042
}
1043
1044
s32 act_warp_door_spawn(struct MarioState *m) {
1045
if (m->actionState == 0) {
1046
m->actionState = 1;
1047
if (m->actionArg & 1) {
1048
m->usedObj->oInteractStatus = 0x00040000;
1049
} else {
1050
m->usedObj->oInteractStatus = 0x00080000;
1051
}
1052
} else if (m->usedObj->oAction == 0) {
1053
if (gNeverEnteredCastle == TRUE && gCurrLevelNum == LEVEL_CASTLE) {
1054
if (configSkipCutscenes) {
1055
set_mario_action(m, ACT_IDLE, 0);
1056
play_cutscene_music(SEQUENCE_ARGS(0, SEQ_LEVEL_INSIDE_CASTLE));
1057
gNeverEnteredCastle = FALSE;
1058
}
1059
else {
1060
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, DIALOG_021);
1061
}
1062
} else {
1063
set_mario_action(m, ACT_IDLE, 0);
1064
}
1065
}
1066
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
1067
stop_and_set_height_to_floor(m);
1068
return FALSE;
1069
}
1070
1071
s32 act_emerge_from_pipe(struct MarioState *m) {
1072
struct Object *marioObj = m->marioObj;
1073
1074
if (m->actionTimer++ < 11) {
1075
marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
1076
return FALSE;
1077
}
1078
1079
marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
1080
1081
play_sound_if_no_flag(m, SOUND_MARIO_YAHOO, MARIO_MARIO_SOUND_PLAYED);
1082
1083
if (gCurrLevelNum == LEVEL_THI) {
1084
if (gCurrAreaIndex == 2) {
1085
play_sound_if_no_flag(m, SOUND_MENU_EXIT_PIPE, MARIO_ACTION_SOUND_PLAYED);
1086
} else {
1087
play_sound_if_no_flag(m, SOUND_MENU_ENTER_PIPE, MARIO_ACTION_SOUND_PLAYED);
1088
}
1089
}
1090
1091
if (launch_mario_until_land(m, ACT_JUMP_LAND_STOP, MARIO_ANIM_SINGLE_JUMP, 8.0f)) {
1092
mario_set_forward_vel(m, 0.0f);
1093
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1094
}
1095
return FALSE;
1096
}
1097
1098
s32 act_spawn_spin_airborne(struct MarioState *m) {
1099
s32 tempActionState;
1100
1101
// entered water, exit action
1102
if (m->pos[1] < m->waterLevel - 100) {
1103
load_level_init_text(0);
1104
return set_water_plunge_action(m);
1105
}
1106
1107
// updates all velocity variables based on m->forwardVel
1108
mario_set_forward_vel(m, m->forwardVel);
1109
1110
// landed on floor, play spawn land animation
1111
if (perform_air_step(m, 0.0) == AIR_STEP_LANDED) {
1112
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1113
if (configSpawnSparkles)
1114
tempActionState = m->actionState;
1115
set_mario_action(m, ACT_SPAWN_SPIN_LANDING, 0);
1116
if (configSpawnSparkles)
1117
m->actionState = tempActionState;
1118
}
1119
1120
// is 300 units above floor, spin and play woosh sounds
1121
if (m->actionState == 0 && m->pos[1] - m->floorHeight > 300.0f) {
1122
if (set_mario_animation(m, MARIO_ANIM_FORWARD_SPINNING) == 0) { // first anim frame
1123
play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject);
1124
}
1125
}
1126
1127
// under 300 units above floor, enter freefall animation
1128
else if (!configSpawnSparkles || m->actionState == 1) {
1129
m->actionState = 1;
1130
set_mario_animation(m, MARIO_ANIM_GENERAL_FALL);
1131
}
1132
1133
if (configSpawnSparkles)
1134
m->particleFlags |= PARTICLE_SPARKLES;
1135
1136
return FALSE;
1137
}
1138
1139
s32 act_spawn_spin_landing(struct MarioState *m) {
1140
1141
if (!configSpawnSparkles || m->actionState == 1) {
1142
stop_and_set_height_to_floor(m);
1143
set_mario_animation(m, MARIO_ANIM_GENERAL_LAND);
1144
if (is_anim_at_end(m)) {
1145
load_level_init_text(0);
1146
set_mario_action(m, ACT_IDLE, 0);
1147
}
1148
}
1149
else if (configSpawnSparkles) {
1150
m->vel[1] = 32.0f;
1151
set_mario_action(m, ACT_SPAWN_SPIN_AIRBORNE, 1);
1152
m->actionState = 1;
1153
m->particleFlags |= PARTICLE_SPARKLES;
1154
}
1155
return FALSE;
1156
}
1157
1158
/**
1159
* act_exit_airborne: Jump out of a level after collecting a Power Star (no
1160
** sparkles)
1161
* Mario always faces a level entrance when he launches out of it, whether he
1162
* died or he collected a star/key. Because of that, we need him to move away
1163
* from the painting by setting his speed to -32.0f and have him face away from
1164
* the painting by adding 0x8000 (180 deg) to his graphics angle. We also set
1165
* his heal counter to 31 to restore 7.75 units of his health, and enable the
1166
* particle flag that generates sparkles.
1167
*/
1168
s32 act_exit_airborne(struct MarioState *m) {
1169
if (15 < m->actionTimer++
1170
&& launch_mario_until_land(m, ACT_EXIT_LAND_SAVE_DIALOG, MARIO_ANIM_GENERAL_FALL, -32.0f)) {
1171
// heal Mario
1172
m->healCounter = 31;
1173
}
1174
// rotate him to face away from the entrance
1175
m->marioObj->header.gfx.angle[1] += 0x8000;
1176
m->particleFlags |= PARTICLE_SPARKLES;
1177
return FALSE;
1178
}
1179
1180
s32 act_falling_exit_airborne(struct MarioState *m) {
1181
if (launch_mario_until_land(m, ACT_EXIT_LAND_SAVE_DIALOG, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
1182
// heal Mario
1183
m->healCounter = 31;
1184
}
1185
// rotate Mario to face away from the entrance
1186
m->marioObj->header.gfx.angle[1] += 0x8000;
1187
m->particleFlags |= PARTICLE_SPARKLES;
1188
return FALSE;
1189
}
1190
1191
s32 act_exit_land_save_dialog(struct MarioState *m) {
1192
s32 animFrame;
1193
stationary_ground_step(m);
1194
play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING);
1195
switch (m->actionState) {
1196
// determine type of exit
1197
case 0:
1198
set_mario_animation(m, m->actionArg == 0 ? MARIO_ANIM_GENERAL_LAND
1199
: MARIO_ANIM_LAND_FROM_SINGLE_JUMP);
1200
if (is_anim_past_end(m)) {
1201
if (gLastCompletedCourseNum != COURSE_BITDW
1202
&& gLastCompletedCourseNum != COURSE_BITFS) {
1203
enable_time_stop();
1204
}
1205
1206
set_menu_mode(MENU_MODE_RENDER_COURSE_COMPLETE_SCREEN);
1207
gSaveOptSelectIndex = MENU_OPT_NONE;
1208
1209
m->actionState = 3; // star exit with cap
1210
if (!(m->flags & MARIO_CAP_ON_HEAD)) {
1211
m->actionState = 2; // star exit without cap
1212
}
1213
if (gLastCompletedCourseNum == COURSE_BITDW
1214
|| gLastCompletedCourseNum == COURSE_BITFS) {
1215
m->actionState = 1; // key exit
1216
}
1217
}
1218
break;
1219
// key exit
1220
case 1:
1221
animFrame = set_mario_animation(m, MARIO_ANIM_THROW_CATCH_KEY);
1222
switch (animFrame) {
1223
case -1:
1224
spawn_obj_at_mario_rel_yaw(m, MODEL_BOWSER_KEY_CUTSCENE, bhvBowserKeyCourseExit, -32768);
1225
//! fall through
1226
if (configRestoreUnusedSounds)
1227
break;
1228
case 67:
1229
play_sound(SOUND_ACTION_KEY_SWISH, m->marioObj->header.gfx.cameraToObject);
1230
//! fall through
1231
if (configRestoreUnusedSounds)
1232
break;
1233
case 83:
1234
play_sound(SOUND_ACTION_PAT_BACK, m->marioObj->header.gfx.cameraToObject);
1235
//! fall through
1236
if (configRestoreUnusedSounds)
1237
break;
1238
case 111:
1239
play_sound(SOUND_ACTION_UNKNOWN45C, m->marioObj->header.gfx.cameraToObject);
1240
// no break
1241
if (configRestoreUnusedSounds)
1242
break;
1243
}
1244
handle_save_menu(m);
1245
break;
1246
// exit without cap
1247
case 2:
1248
animFrame = set_mario_animation(m, MARIO_ANIM_MISSING_CAP);
1249
if ((animFrame >= 18 && animFrame < 55) || (animFrame >= 112 && animFrame < 134)) {
1250
m->marioBodyState->handState = MARIO_HAND_OPEN;
1251
}
1252
if (!(animFrame < 109) && animFrame < 154) {
1253
m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED;
1254
}
1255
1256
handle_save_menu(m);
1257
break;
1258
// exit with cap
1259
case 3:
1260
animFrame = set_mario_animation(m, MARIO_ANIM_TAKE_CAP_OFF_THEN_ON);
1261
switch (animFrame) {
1262
case 12:
1263
cutscene_take_cap_off(m);
1264
break;
1265
case 37:
1266
// fall through
1267
case 53:
1268
play_sound(SOUND_ACTION_BRUSH_HAIR, m->marioObj->header.gfx.cameraToObject);
1269
break;
1270
case 82:
1271
cutscene_put_cap_on(m);
1272
break;
1273
}
1274
handle_save_menu(m);
1275
break;
1276
}
1277
1278
m->marioObj->header.gfx.angle[1] += 0x8000;
1279
return FALSE;
1280
}
1281
1282
s32 act_death_exit(struct MarioState *m) {
1283
if (15 < m->actionTimer++
1284
&& launch_mario_until_land(m, ACT_DEATH_EXIT_LAND, MARIO_ANIM_GENERAL_FALL, -32.0f)) {
1285
#ifdef VERSION_JP
1286
play_sound(SOUND_MARIO_OOOF, m->marioObj->header.gfx.cameraToObject);
1287
#else
1288
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
1289
#endif
1290
#if ENABLE_RUMBLE
1291
queue_rumble_data(5, 80);
1292
#endif
1293
if (configLifeMode) {
1294
m->numLives++;
1295
}
1296
else if (m->numLives > 0) {
1297
m->numLives--;
1298
save_file_set_num_lives(m->numLives);
1299
}
1300
// restore 7.75 units of health
1301
m->healCounter = 31;
1302
}
1303
// one unit of health
1304
m->health = 0x0100;
1305
return FALSE;
1306
}
1307
1308
s32 act_unused_death_exit(struct MarioState *m) {
1309
if (launch_mario_until_land(m, ACT_FREEFALL_LAND_STOP, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
1310
#ifdef VERSION_JP
1311
play_sound(SOUND_MARIO_OOOF, m->marioObj->header.gfx.cameraToObject);
1312
#else
1313
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
1314
#endif
1315
if (configLifeMode) {
1316
m->numLives++;
1317
}
1318
else if (m->numLives > 0) {
1319
m->numLives--;
1320
save_file_set_num_lives(m->numLives);
1321
}
1322
// restore 7.75 units of health
1323
m->healCounter = 31;
1324
}
1325
// one unit of health
1326
m->health = 0x0100;
1327
return FALSE;
1328
}
1329
1330
s32 act_falling_death_exit(struct MarioState *m) {
1331
if (launch_mario_until_land(m, ACT_DEATH_EXIT_LAND, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
1332
#ifdef VERSION_JP
1333
play_sound(SOUND_MARIO_OOOF, m->marioObj->header.gfx.cameraToObject);
1334
#else
1335
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
1336
#endif
1337
#if ENABLE_RUMBLE
1338
queue_rumble_data(5, 80);
1339
#endif
1340
if (configLifeMode) {
1341
m->numLives++;
1342
}
1343
else if (m->numLives > 0) {
1344
m->numLives--;
1345
save_file_set_num_lives(m->numLives);
1346
}
1347
// restore 7.75 units of health
1348
m->healCounter = 31;
1349
}
1350
// one unit of health
1351
m->health = 0x0100;
1352
return FALSE;
1353
}
1354
1355
// waits 11 frames before actually executing, also has reduced fvel
1356
s32 act_special_exit_airborne(struct MarioState *m) {
1357
struct Object *marioObj = m->marioObj;
1358
1359
play_sound_if_no_flag(m, SOUND_MARIO_YAHOO, MARIO_MARIO_SOUND_PLAYED);
1360
1361
if (m->actionTimer++ < 11) {
1362
marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
1363
return FALSE;
1364
}
1365
1366
if (launch_mario_until_land(m, ACT_EXIT_LAND_SAVE_DIALOG, MARIO_ANIM_SINGLE_JUMP, -24.0f)) {
1367
// heal Mario
1368
m->healCounter = 31;
1369
m->actionArg = 1;
1370
}
1371
1372
m->particleFlags |= PARTICLE_SPARKLES;
1373
// rotate Mario to face away from the entrance
1374
marioObj->header.gfx.angle[1] += 0x8000;
1375
// show Mario
1376
marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
1377
1378
return FALSE;
1379
}
1380
1381
s32 act_special_death_exit(struct MarioState *m) {
1382
struct Object *marioObj = m->marioObj;
1383
1384
if (m->actionTimer++ < 11) {
1385
marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
1386
return FALSE;
1387
}
1388
1389
if (launch_mario_until_land(m, ACT_HARD_BACKWARD_GROUND_KB, MARIO_ANIM_BACKWARD_AIR_KB, -24.0f)) {
1390
#if ENABLE_RUMBLE
1391
queue_rumble_data(5, 80);
1392
#endif
1393
if (configLifeMode) {
1394
m->numLives++;
1395
}
1396
else if (m->numLives > 0) {
1397
m->numLives--;
1398
save_file_set_num_lives(m->numLives);
1399
}
1400
m->healCounter = 31;
1401
}
1402
// show Mario
1403
marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
1404
// one unit of health
1405
m->health = 0x0100;
1406
1407
return FALSE;
1408
}
1409
1410
s32 act_spawn_no_spin_airborne(struct MarioState *m) {
1411
launch_mario_until_land(m, ACT_SPAWN_NO_SPIN_LANDING, MARIO_ANIM_GENERAL_FALL, 0.0f);
1412
if (m->pos[1] < m->waterLevel - 100) {
1413
set_water_plunge_action(m);
1414
}
1415
return FALSE;
1416
}
1417
1418
s32 act_spawn_no_spin_landing(struct MarioState *m) {
1419
play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING);
1420
set_mario_animation(m, MARIO_ANIM_GENERAL_LAND);
1421
stop_and_set_height_to_floor(m);
1422
if (is_anim_at_end(m)) {
1423
load_level_init_text(0);
1424
set_mario_action(m, ACT_IDLE, 0);
1425
}
1426
return FALSE;
1427
}
1428
1429
s32 act_bbh_enter_spin(struct MarioState *m) {
1430
f32 floorDist;
1431
f32 scale;
1432
f32 cageDX;
1433
f32 cageDZ;
1434
f32 cageDist;
1435
f32 forwardVel;
1436
1437
cageDX = m->usedObj->oPosX - m->pos[0];
1438
cageDZ = m->usedObj->oPosZ - m->pos[2];
1439
cageDist = sqrtf(cageDX * cageDX + cageDZ * cageDZ);
1440
1441
if (cageDist > 20.0f) {
1442
forwardVel = 10.0f;
1443
} else {
1444
forwardVel = cageDist / 2.0f;
1445
}
1446
if (forwardVel < 0.5f) {
1447
forwardVel = 0.0f;
1448
}
1449
1450
switch (m->actionState) {
1451
case 0:
1452
floorDist = 512.0f - (m->pos[1] - m->floorHeight);
1453
m->vel[1] = floorDist > 0 ? sqrtf(4.0f * floorDist + 1.0f) - 1.0f : 2.0f;
1454
1455
m->actionState = 1;
1456
m->actionTimer = 100;
1457
// fall through
1458
1459
case 1:
1460
m->faceAngle[1] = atan2s(cageDZ, cageDX);
1461
mario_set_forward_vel(m, forwardVel);
1462
1463
if (set_mario_animation(m, MARIO_ANIM_FORWARD_SPINNING) == 0) {
1464
play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject);
1465
}
1466
1467
m->flags &= ~MARIO_UNKNOWN_08;
1468
perform_air_step(m, 0);
1469
if (m->vel[1] <= 0) {
1470
m->actionState = 2;
1471
}
1472
break;
1473
1474
case 2:
1475
// fall through
1476
case 3:
1477
m->faceAngle[1] = atan2s(cageDZ, cageDX);
1478
mario_set_forward_vel(m, forwardVel);
1479
m->flags &= ~MARIO_UNKNOWN_08;
1480
if (perform_air_step(m, 0) == AIR_STEP_LANDED) {
1481
level_trigger_warp(m, WARP_OP_UNKNOWN_02);
1482
#if ENABLE_RUMBLE
1483
queue_rumble_data(15, 80);
1484
#endif
1485
m->actionState = 4;
1486
}
1487
if (m->actionState == 2) {
1488
if (m->marioObj->header.gfx.animInfo.animFrame == 0) {
1489
m->actionState = 3;
1490
}
1491
} else {
1492
play_sound_if_no_flag(m, SOUND_ACTION_SHRINK_INTO_BBH, MARIO_ACTION_SOUND_PLAYED);
1493
set_mario_animation(m, MARIO_ANIM_DIVE);
1494
m->marioObj->header.gfx.angle[0] = atan2s(m->forwardVel, -m->vel[1]);
1495
}
1496
m->squishTimer = 0xFF;
1497
if (m->actionTimer >= 11) {
1498
m->actionTimer -= 6;
1499
scale = m->actionTimer / 100.0f;
1500
vec3f_set(m->marioObj->header.gfx.scale, scale, scale, scale);
1501
}
1502
break;
1503
1504
case 4:
1505
stop_and_set_height_to_floor(m);
1506
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
1507
break;
1508
}
1509
1510
return FALSE;
1511
}
1512
1513
s32 act_bbh_enter_jump(struct MarioState *m) {
1514
f32 cageDX;
1515
f32 cageDZ;
1516
f32 cageDist;
1517
1518
play_mario_action_sound(
1519
m, m->flags & MARIO_METAL_CAP ? SOUND_ACTION_METAL_JUMP : SOUND_ACTION_TERRAIN_JUMP, 1);
1520
play_mario_jump_sound(m);
1521
1522
if (m->actionState == 0) {
1523
cageDX = m->usedObj->oPosX - m->pos[0];
1524
cageDZ = m->usedObj->oPosZ - m->pos[2];
1525
cageDist = sqrtf(cageDX * cageDX + cageDZ * cageDZ);
1526
1527
m->vel[1] = 60.0f;
1528
m->faceAngle[1] = atan2s(cageDZ, cageDX);
1529
mario_set_forward_vel(m, cageDist / 20.0f);
1530
1531
m->flags &= ~MARIO_UNKNOWN_08;
1532
m->actionState = 1;
1533
}
1534
1535
set_mario_animation(m, MARIO_ANIM_DOUBLE_JUMP_RISE);
1536
perform_air_step(m, 0);
1537
1538
if (m->vel[1] <= 0.0f) {
1539
set_mario_action(m, ACT_BBH_ENTER_SPIN, 0);
1540
}
1541
1542
return FALSE;
1543
}
1544
1545
s32 act_teleport_fade_out(struct MarioState *m) {
1546
play_sound_if_no_flag(m, SOUND_ACTION_TELEPORT, MARIO_ACTION_SOUND_PLAYED);
1547
set_mario_animation(m, m->prevAction == ACT_CROUCHING ? MARIO_ANIM_CROUCHING
1548
: MARIO_ANIM_FIRST_PERSON);
1549
1550
#if ENABLE_RUMBLE
1551
if (m->actionTimer == 0) {
1552
queue_rumble_data(30, 70);
1553
func_sh_8024C89C(2);
1554
}
1555
#endif
1556
1557
m->flags |= MARIO_TELEPORTING;
1558
1559
if (m->actionTimer < 32) {
1560
m->fadeWarpOpacity = (-m->actionTimer << 3) + 0xF8;
1561
}
1562
1563
if (m->actionTimer++ == 20) {
1564
level_trigger_warp(m, WARP_OP_TELEPORT);
1565
}
1566
1567
stop_and_set_height_to_floor(m);
1568
1569
return FALSE;
1570
}
1571
1572
s32 act_teleport_fade_in(struct MarioState *m) {
1573
play_sound_if_no_flag(m, SOUND_ACTION_TELEPORT, MARIO_ACTION_SOUND_PLAYED);
1574
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
1575
1576
#if ENABLE_RUMBLE
1577
if (m->actionTimer == 0) {
1578
queue_rumble_data(30, 70);
1579
func_sh_8024C89C(2);
1580
}
1581
#endif
1582
1583
if (m->actionTimer < 32) {
1584
m->flags |= MARIO_TELEPORTING;
1585
m->fadeWarpOpacity = m->actionTimer << 3;
1586
} else {
1587
m->flags &= ~MARIO_TELEPORTING;
1588
}
1589
1590
if (m->actionTimer++ == 32) {
1591
if (m->pos[1] < m->waterLevel - 100) {
1592
// Check if the camera is not underwater.
1593
if (m->area->camera->mode != CAMERA_MODE_WATER_SURFACE) {
1594
set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1);
1595
}
1596
set_mario_action(m, ACT_WATER_IDLE, 0);
1597
} else {
1598
set_mario_action(m, ACT_IDLE, 0);
1599
}
1600
}
1601
1602
stop_and_set_height_to_floor(m);
1603
1604
return FALSE;
1605
}
1606
1607
s32 act_shocked(struct MarioState *m) {
1608
play_sound_if_no_flag(m, SOUND_MARIO_WAAAOOOW, MARIO_ACTION_SOUND_PLAYED);
1609
play_sound(SOUND_MOVING_SHOCKED, m->marioObj->header.gfx.cameraToObject);
1610
set_camera_shake_from_hit(SHAKE_SHOCK);
1611
1612
if (set_mario_animation(m, MARIO_ANIM_SHOCKED) == 0) {
1613
m->actionTimer++;
1614
m->flags |= MARIO_METAL_SHOCK;
1615
}
1616
1617
if (m->actionArg == 0) {
1618
mario_set_forward_vel(m, 0.0f);
1619
if (perform_air_step(m, 1) == AIR_STEP_LANDED) {
1620
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1621
m->actionArg = 1;
1622
}
1623
} else {
1624
if (m->actionTimer >= 6) {
1625
m->invincTimer = 30;
1626
set_mario_action(m, m->health < 0x0100 ? ACT_ELECTROCUTION : ACT_IDLE, 0);
1627
}
1628
stop_and_set_height_to_floor(m);
1629
}
1630
1631
return FALSE;
1632
}
1633
1634
s32 act_squished(struct MarioState *m) {
1635
UNUSED s32 pad;
1636
f32 squishAmount;
1637
f32 spaceUnderCeil;
1638
s16 surfAngle;
1639
s32 underSteepSurf = FALSE; // seems to be responsible for setting velocity?
1640
1641
if ((spaceUnderCeil = m->ceilHeight - m->floorHeight) < 0) {
1642
spaceUnderCeil = 0;
1643
}
1644
1645
switch (m->actionState) {
1646
case 0:
1647
if (spaceUnderCeil > 160.0f) {
1648
m->squishTimer = 0;
1649
return set_mario_action(m, ACT_IDLE, 0);
1650
}
1651
1652
m->squishTimer = 0xFF;
1653
1654
if (spaceUnderCeil >= 10.1f) {
1655
// Mario becomes a pancake
1656
squishAmount = spaceUnderCeil / 160.0f;
1657
vec3f_set(m->marioObj->header.gfx.scale, 2.0f - squishAmount, squishAmount,
1658
2.0f - squishAmount);
1659
} else {
1660
if (!(m->flags & MARIO_METAL_CAP) && m->invincTimer == 0) {
1661
// cap on: 3 units; cap off: 4.5 units
1662
m->hurtCounter += m->flags & MARIO_CAP_ON_HEAD ? 12 : 18;
1663
play_sound_if_no_flag(m, SOUND_MARIO_ATTACKED, MARIO_MARIO_SOUND_PLAYED);
1664
}
1665
1666
// Both of the 1.8's are really floats, but one of them has to
1667
// be written as a double for this to match on -O2.
1668
vec3f_set(m->marioObj->header.gfx.scale, 1.8, 0.05f, 1.8f);
1669
#if ENABLE_RUMBLE
1670
queue_rumble_data(10, 80);
1671
#endif
1672
m->actionState = 1;
1673
}
1674
break;
1675
case 1:
1676
if (spaceUnderCeil >= 30.0f) {
1677
m->actionState = 2;
1678
}
1679
break;
1680
case 2:
1681
m->actionTimer++;
1682
if (m->actionTimer >= 15) {
1683
// 1 unit of health
1684
if (m->health < 0x0100) {
1685
level_trigger_warp(m, WARP_OP_DEATH);
1686
// woosh, he's gone!
1687
set_mario_action(m, ACT_DISAPPEARED, 0);
1688
} else if (m->hurtCounter == 0) {
1689
// un-squish animation
1690
m->squishTimer = 30;
1691
set_mario_action(m, ACT_IDLE, 0);
1692
}
1693
}
1694
break;
1695
}
1696
1697
// steep floor
1698
if (m->floor != NULL && m->floor->normal.y < 0.5f) {
1699
surfAngle = atan2s(m->floor->normal.z, m->floor->normal.x);
1700
underSteepSurf = TRUE;
1701
}
1702
// steep ceiling
1703
if (m->ceil != NULL && -0.5f < m->ceil->normal.y) {
1704
surfAngle = atan2s(m->ceil->normal.z, m->ceil->normal.x);
1705
underSteepSurf = TRUE;
1706
}
1707
1708
if (underSteepSurf) {
1709
m->vel[0] = sins(surfAngle) * 10.0f;
1710
m->vel[2] = coss(surfAngle) * 10.0f;
1711
m->vel[1] = 0;
1712
1713
// check if there's no floor 10 units away from the surface
1714
if (perform_ground_step(m) == GROUND_STEP_LEFT_GROUND) {
1715
// instant un-squish
1716
m->squishTimer = 0;
1717
set_mario_action(m, ACT_IDLE, 0);
1718
return FALSE;
1719
}
1720
}
1721
1722
// squished for more than 10 seconds, so kill Mario
1723
if (m->actionArg++ > 300) {
1724
// 0 units of health
1725
m->health = 0x00FF;
1726
m->hurtCounter = 0;
1727
level_trigger_warp(m, WARP_OP_DEATH);
1728
// woosh, he's gone!
1729
set_mario_action(m, ACT_DISAPPEARED, 0);
1730
}
1731
stop_and_set_height_to_floor(m);
1732
set_mario_animation(m, MARIO_ANIM_A_POSE);
1733
return FALSE;
1734
}
1735
1736
s32 act_putting_on_cap(struct MarioState *m) {
1737
s32 animFrame = set_mario_animation(m, MARIO_ANIM_PUT_CAP_ON);
1738
1739
if (animFrame == 0) {
1740
enable_time_stop();
1741
}
1742
1743
if (animFrame == 28) {
1744
cutscene_put_cap_on(m);
1745
}
1746
1747
if (is_anim_at_end(m)) {
1748
set_mario_action(m, ACT_IDLE, 0);
1749
disable_time_stop();
1750
}
1751
1752
stationary_ground_step(m);
1753
return FALSE;
1754
}
1755
1756
void stuck_in_ground_handler(struct MarioState *m, s32 animation, s32 unstuckFrame, s32 target2,
1757
s32 target3, s32 endAction) {
1758
s32 animFrame = set_mario_animation(m, animation);
1759
1760
if (m->input & INPUT_A_PRESSED) {
1761
m->actionTimer++;
1762
if (m->actionTimer >= 5 && animFrame < unstuckFrame - 1) {
1763
animFrame = unstuckFrame - 1;
1764
set_anim_to_frame(m, animFrame);
1765
}
1766
}
1767
1768
stop_and_set_height_to_floor(m);
1769
1770
if (animFrame == -1) {
1771
play_sound_and_spawn_particles(m, SOUND_ACTION_TERRAIN_STUCK_IN_GROUND, 1);
1772
} else if (animFrame == unstuckFrame) {
1773
#if ENABLE_RUMBLE
1774
queue_rumble_data(5, 80);
1775
#endif
1776
play_sound_and_spawn_particles(m, SOUND_ACTION_UNSTUCK_FROM_GROUND, 1);
1777
} else if (animFrame == target2 || animFrame == target3) {
1778
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1779
}
1780
1781
if (is_anim_at_end(m)) {
1782
set_mario_action(m, endAction, 0);
1783
}
1784
}
1785
1786
s32 act_head_stuck_in_ground(struct MarioState *m) {
1787
stuck_in_ground_handler(m, MARIO_ANIM_HEAD_STUCK_IN_GROUND, 96, 105, 135, ACT_IDLE);
1788
return FALSE;
1789
}
1790
1791
s32 act_butt_stuck_in_ground(struct MarioState *m) {
1792
stuck_in_ground_handler(m, MARIO_ANIM_BOTTOM_STUCK_IN_GROUND, 127, 136, -2, ACT_GROUND_POUND_LAND);
1793
return FALSE;
1794
}
1795
1796
s32 act_feet_stuck_in_ground(struct MarioState *m) {
1797
stuck_in_ground_handler(m, MARIO_ANIM_LEGS_STUCK_IN_GROUND, 116, 129, -2, ACT_IDLE);
1798
return FALSE;
1799
}
1800
1801
/**
1802
* advance_cutscene_step: Advances the current step in the current cutscene.
1803
* Resets action state and action timer, adds 1 to the action arg (responsible
1804
* for keeping track of what step of the cutscene Mario is in.)
1805
*/
1806
static void advance_cutscene_step(struct MarioState *m) {
1807
m->actionState = 0;
1808
m->actionTimer = 0;
1809
m->actionArg++;
1810
}
1811
1812
static void intro_cutscene_hide_hud_and_mario(struct MarioState *m) {
1813
gHudDisplay.flags = HUD_DISPLAY_NONE;
1814
m->statusForCamera->cameraEvent = CAM_EVENT_START_INTRO;
1815
m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
1816
advance_cutscene_step(m);
1817
}
1818
1819
#ifdef VERSION_EU
1820
#define TIMER_SPAWN_PIPE 47
1821
#else
1822
#define TIMER_SPAWN_PIPE 37
1823
#endif
1824
1825
static void intro_cutscene_peach_lakitu_scene(struct MarioState *m) {
1826
if ((s16) m->statusForCamera->cameraEvent != CAM_EVENT_START_INTRO) {
1827
if (m->actionTimer++ == TIMER_SPAWN_PIPE) {
1828
sIntroWarpPipeObj =
1829
spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_CASTLE_GROUNDS_WARP_PIPE,
1830
bhvStaticObject, -1328, 60, 4664, 0, 180, 0);
1831
advance_cutscene_step(m);
1832
}
1833
}
1834
}
1835
#undef TIMER_SPAWN_PIPE
1836
1837
#ifdef VERSION_EU
1838
#define TIMER_RAISE_PIPE 28
1839
#else
1840
#define TIMER_RAISE_PIPE 38
1841
#endif
1842
1843
static void intro_cutscene_raise_pipe(struct MarioState *m) {
1844
sIntroWarpPipeObj->oPosY = camera_approach_f32_symmetric(sIntroWarpPipeObj->oPosY, 260.0f, 10.0f);
1845
1846
if (m->actionTimer == 0) {
1847
play_sound(SOUND_MENU_EXIT_PIPE, sIntroWarpPipeObj->header.gfx.cameraToObject);
1848
}
1849
1850
if (m->actionTimer++ == TIMER_RAISE_PIPE) {
1851
m->vel[1] = 60.0f;
1852
advance_cutscene_step(m);
1853
}
1854
}
1855
#undef TIMER_RAISE_PIPE
1856
1857
static void intro_cutscene_jump_out_of_pipe(struct MarioState *m) {
1858
if (m->actionTimer == 25) {
1859
gHudDisplay.flags = HUD_DISPLAY_DEFAULT;
1860
}
1861
1862
if (m->actionTimer++ >= 118) {
1863
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
1864
1865
#ifdef VERSION_EU
1866
// For some reason these calls were swapped.
1867
play_sound_if_no_flag(m, SOUND_ACTION_HIT_3, MARIO_ACTION_SOUND_PLAYED);
1868
play_sound_if_no_flag(m, SOUND_MARIO_YAHOO, MARIO_MARIO_SOUND_PLAYED);
1869
#else
1870
play_sound_if_no_flag(m, SOUND_MARIO_YAHOO, MARIO_MARIO_SOUND_PLAYED);
1871
#ifndef VERSION_JP
1872
play_sound_if_no_flag(m, SOUND_ACTION_HIT_3, MARIO_ACTION_SOUND_PLAYED);
1873
#endif
1874
#endif
1875
1876
set_mario_animation(m, MARIO_ANIM_SINGLE_JUMP);
1877
mario_set_forward_vel(m, 10.0f);
1878
if (perform_air_step(m, 0) == AIR_STEP_LANDED) {
1879
sound_banks_enable(SEQ_PLAYER_SFX, SOUND_BANKS_DISABLED_DURING_INTRO_CUTSCENE);
1880
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1881
#ifndef VERSION_JP
1882
play_sound(SOUND_MARIO_HAHA, m->marioObj->header.gfx.cameraToObject);
1883
#endif
1884
advance_cutscene_step(m);
1885
}
1886
}
1887
}
1888
1889
static void intro_cutscene_land_outside_pipe(struct MarioState *m) {
1890
set_mario_animation(m, MARIO_ANIM_LAND_FROM_SINGLE_JUMP);
1891
1892
if (is_anim_at_end(m)) {
1893
advance_cutscene_step(m);
1894
}
1895
1896
stop_and_set_height_to_floor(m);
1897
}
1898
1899
static void intro_cutscene_lower_pipe(struct MarioState *m) {
1900
if (m->actionTimer++ == 0) {
1901
play_sound(SOUND_MENU_ENTER_PIPE, sIntroWarpPipeObj->header.gfx.cameraToObject);
1902
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
1903
}
1904
1905
sIntroWarpPipeObj->oPosY -= 5.0f;
1906
if (sIntroWarpPipeObj->oPosY <= 50.0f) {
1907
obj_mark_for_deletion(sIntroWarpPipeObj);
1908
advance_cutscene_step(m);
1909
}
1910
1911
stop_and_set_height_to_floor(m);
1912
}
1913
1914
static void intro_cutscene_set_mario_to_idle(struct MarioState *m) {
1915
if (gCamera->cutscene == 0) {
1916
gCameraMovementFlags &= ~CAM_MOVE_C_UP_MODE;
1917
set_mario_action(m, ACT_IDLE, 0);
1918
}
1919
1920
stop_and_set_height_to_floor(m);
1921
}
1922
1923
enum {
1924
INTRO_CUTSCENE_HIDE_HUD_AND_MARIO,
1925
INTRO_CUTSCENE_PEACH_LAKITU_SCENE,
1926
INTRO_CUTSCENE_RAISE_PIPE,
1927
INTRO_CUTSCENE_JUMP_OUT_OF_PIPE,
1928
INTRO_CUTSCENE_LAND_OUTSIDE_PIPE,
1929
INTRO_CUTSCENE_LOWER_PIPE,
1930
INTRO_CUTSCENE_SET_MARIO_TO_IDLE
1931
};
1932
1933
static s32 act_intro_cutscene(struct MarioState *m) {
1934
switch (m->actionArg) {
1935
case INTRO_CUTSCENE_HIDE_HUD_AND_MARIO:
1936
intro_cutscene_hide_hud_and_mario(m);
1937
break;
1938
case INTRO_CUTSCENE_PEACH_LAKITU_SCENE:
1939
intro_cutscene_peach_lakitu_scene(m);
1940
break;
1941
case INTRO_CUTSCENE_RAISE_PIPE:
1942
intro_cutscene_raise_pipe(m);
1943
break;
1944
case INTRO_CUTSCENE_JUMP_OUT_OF_PIPE:
1945
intro_cutscene_jump_out_of_pipe(m);
1946
break;
1947
case INTRO_CUTSCENE_LAND_OUTSIDE_PIPE:
1948
intro_cutscene_land_outside_pipe(m);
1949
break;
1950
case INTRO_CUTSCENE_LOWER_PIPE:
1951
intro_cutscene_lower_pipe(m);
1952
break;
1953
case INTRO_CUTSCENE_SET_MARIO_TO_IDLE:
1954
intro_cutscene_set_mario_to_idle(m);
1955
break;
1956
}
1957
return FALSE;
1958
}
1959
1960
// jumbo star cutscene: Mario lands after grabbing the jumbo star
1961
static void jumbo_star_cutscene_falling(struct MarioState *m) {
1962
if (m->actionState == 0) {
1963
m->input |= INPUT_A_DOWN;
1964
m->flags |= (MARIO_WING_CAP | MARIO_CAP_ON_HEAD);
1965
1966
m->faceAngle[1] = -0x8000;
1967
m->pos[0] = 0.0f;
1968
m->pos[2] = 0.0f;
1969
1970
mario_set_forward_vel(m, 0.0f);
1971
set_mario_animation(m, MARIO_ANIM_GENERAL_FALL);
1972
1973
if (perform_air_step(m, 1) == AIR_STEP_LANDED) {
1974
play_cutscene_music(SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_VICTORY));
1975
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1976
m->actionState++;
1977
}
1978
} else {
1979
set_mario_animation(m, MARIO_ANIM_GENERAL_LAND);
1980
if (is_anim_at_end(m)) {
1981
m->statusForCamera->cameraEvent = CAM_EVENT_START_GRAND_STAR;
1982
advance_cutscene_step(m);
1983
}
1984
}
1985
}
1986
1987
// jumbo star cutscene: Mario takes off
1988
static s32 jumbo_star_cutscene_taking_off(struct MarioState *m) {
1989
struct Object *marioObj = m->marioObj;
1990
s32 animFrame;
1991
1992
if (m->actionState == 0) {
1993
set_mario_animation(m, MARIO_ANIM_FINAL_BOWSER_RAISE_HAND_SPIN);
1994
marioObj->rawData.asF32[0x22] = 0.0f;
1995
1996
if (is_anim_past_end(m)) {
1997
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
1998
m->actionState++;
1999
}
2000
} else {
2001
animFrame = set_mario_animation(m, MARIO_ANIM_FINAL_BOWSER_WING_CAP_TAKE_OFF);
2002
if (animFrame == 3 || animFrame == 28 || animFrame == 60) {
2003
play_sound_and_spawn_particles(m, SOUND_ACTION_TERRAIN_JUMP, 1);
2004
}
2005
if (animFrame >= 3) {
2006
marioObj->rawData.asF32[0x22] -= 32.0f;
2007
}
2008
2009
switch (animFrame) {
2010
case 3:
2011
play_sound(SOUND_MARIO_YAH_WAH_HOO + (gAudioRandom % 3 << 16),
2012
m->marioObj->header.gfx.cameraToObject);
2013
break;
2014
2015
case 28:
2016
play_sound(SOUND_MARIO_HOOHOO, m->marioObj->header.gfx.cameraToObject);
2017
break;
2018
2019
case 60:
2020
play_sound(SOUND_MARIO_YAHOO, m->marioObj->header.gfx.cameraToObject);
2021
break;
2022
}
2023
m->particleFlags |= PARTICLE_SPARKLES;
2024
2025
if (is_anim_past_end(m)) {
2026
advance_cutscene_step(m);
2027
}
2028
}
2029
2030
vec3f_set(m->pos, 0.0f, 307.0, marioObj->rawData.asF32[0x22]);
2031
update_mario_pos_for_anim(m);
2032
vec3f_copy(marioObj->header.gfx.pos, m->pos);
2033
vec3s_set(marioObj->header.gfx.angle, 0, m->faceAngle[1], 0);
2034
2035
// not sure why they did this, probably was from being used to action
2036
// functions
2037
return FALSE;
2038
}
2039
2040
// jumbo star cutscene: Mario flying
2041
static s32 jumbo_star_cutscene_flying(struct MarioState *m) {
2042
Vec3f targetPos;
2043
UNUSED struct Object *marioObj = m->marioObj;
2044
f32 targetDX;
2045
f32 targetDY;
2046
f32 targetDZ;
2047
f32 targetHyp;
2048
s16 targetAngle;
2049
2050
switch (m->actionState) {
2051
case 0:
2052
set_mario_animation(m, MARIO_ANIM_WING_CAP_FLY);
2053
anim_spline_init(sJumboStarKeyframes);
2054
m->actionState++;
2055
// fall through
2056
case 1:
2057
if (anim_spline_poll(targetPos)) {
2058
// does this twice
2059
set_mario_action(m, ACT_FREEFALL, 0);
2060
m->actionState++;
2061
} else {
2062
targetDX = targetPos[0] - m->pos[0];
2063
targetDY = targetPos[1] - m->pos[1];
2064
targetDZ = targetPos[2] - m->pos[2];
2065
targetHyp = sqrtf(targetDX * targetDX + targetDZ * targetDZ);
2066
targetAngle = atan2s(targetDZ, targetDX);
2067
2068
vec3f_copy(m->pos, targetPos);
2069
m->marioObj->header.gfx.angle[0] = -atan2s(targetHyp, targetDY);
2070
m->marioObj->header.gfx.angle[1] = targetAngle;
2071
m->marioObj->header.gfx.angle[2] = ((m->faceAngle[1] - targetAngle) << 16 >> 16) * 20;
2072
m->faceAngle[1] = targetAngle;
2073
}
2074
break;
2075
case 2:
2076
set_mario_action(m, ACT_FREEFALL, 0);
2077
break;
2078
}
2079
2080
m->marioBodyState->handState = MARIO_HAND_RIGHT_OPEN;
2081
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
2082
m->particleFlags |= PARTICLE_SPARKLES;
2083
2084
if (m->actionTimer++ == 500) {
2085
level_trigger_warp(m, WARP_OP_CREDITS_START);
2086
}
2087
2088
return FALSE;
2089
}
2090
2091
enum { JUMBO_STAR_CUTSCENE_FALLING, JUMBO_STAR_CUTSCENE_TAKING_OFF, JUMBO_STAR_CUTSCENE_FLYING };
2092
2093
static s32 act_jumbo_star_cutscene(struct MarioState *m) {
2094
switch (m->actionArg) {
2095
case JUMBO_STAR_CUTSCENE_FALLING:
2096
jumbo_star_cutscene_falling(m);
2097
break;
2098
case JUMBO_STAR_CUTSCENE_TAKING_OFF:
2099
jumbo_star_cutscene_taking_off(m);
2100
break;
2101
case JUMBO_STAR_CUTSCENE_FLYING:
2102
jumbo_star_cutscene_flying(m);
2103
break;
2104
}
2105
return FALSE;
2106
}
2107
2108
void generate_yellow_sparkles(s16 x, s16 y, s16 z, f32 radius) {
2109
static s32 sSparkleGenTheta = 0;
2110
static s32 sSparkleGenPhi = 0;
2111
2112
s16 offsetX = radius * coss(sSparkleGenTheta) * sins(sSparkleGenPhi);
2113
s16 offsetY = radius * sins(sSparkleGenTheta);
2114
s16 offsetZ = radius * coss(sSparkleGenTheta) * coss(sSparkleGenPhi);
2115
2116
spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_NONE, bhvSparkleSpawn, x + offsetX, y + offsetY,
2117
z + offsetZ, 0, 0, 0);
2118
2119
//! copy paste error
2120
offsetX = offsetX * 4 / 3;
2121
offsetX = offsetY * 4 / 3;
2122
offsetX = offsetZ * 4 / 3;
2123
2124
spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_NONE, bhvSparkleSpawn, x - offsetX, y - offsetY,
2125
z - offsetZ, 0, 0, 0);
2126
2127
sSparkleGenTheta += 0x3800;
2128
sSparkleGenPhi += 0x6000;
2129
}
2130
2131
// not sure what this does, returns the height of the floor.
2132
// (animation related?)
2133
static f32 end_obj_set_visual_pos(struct Object *o) {
2134
struct Surface *surf;
2135
Vec3s sp24;
2136
f32 sp20;
2137
f32 sp1C;
2138
f32 sp18;
2139
2140
find_mario_anim_flags_and_translation(o, o->header.gfx.angle[1], sp24);
2141
2142
sp20 = o->header.gfx.pos[0] + sp24[0];
2143
sp1C = o->header.gfx.pos[1] + 10.0f;
2144
sp18 = o->header.gfx.pos[2] + sp24[2];
2145
2146
return find_floor(sp20, sp1C, sp18, &surf);
2147
}
2148
2149
// make Mario fall and soften wing cap gravity
2150
static void end_peach_cutscene_mario_falling(struct MarioState *m) {
2151
if (m->actionTimer == 1) {
2152
m->statusForCamera->cameraEvent = CAM_EVENT_START_ENDING;
2153
}
2154
2155
m->input |= INPUT_A_DOWN;
2156
m->flags |= (MARIO_WING_CAP | MARIO_CAP_ON_HEAD);
2157
2158
set_mario_animation(m, MARIO_ANIM_GENERAL_FALL);
2159
mario_set_forward_vel(m, 0.0f);
2160
2161
if (perform_air_step(m, 0) == AIR_STEP_LANDED) {
2162
play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING);
2163
advance_cutscene_step(m);
2164
}
2165
}
2166
2167
// set Mario on the ground, wait and spawn the jumbo star outside the castle.
2168
static void end_peach_cutscene_mario_landing(struct MarioState *m) {
2169
set_mario_animation(m, MARIO_ANIM_GENERAL_LAND);
2170
stop_and_set_height_to_floor(m);
2171
2172
if (is_anim_at_end(m)) {
2173
// make wing cap run out
2174
m->capTimer = 60;
2175
2176
sEndJumboStarObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_STAR, bhvStaticObject, 0,
2177
2528, -1800, 0, 0, 0);
2178
obj_scale(sEndJumboStarObj, 3.0);
2179
advance_cutscene_step(m);
2180
}
2181
}
2182
2183
// raise hand animation, lower hand animation, do some special effects
2184
static void end_peach_cutscene_summon_jumbo_star(struct MarioState *m) {
2185
set_mario_animation(m, m->actionState == 0 ? MARIO_ANIM_CREDITS_RAISE_HAND
2186
: MARIO_ANIM_CREDITS_LOWER_HAND);
2187
2188
if (m->actionState == 0 && is_anim_past_end(m)) {
2189
m->actionState++;
2190
}
2191
if (m->actionTimer == 90) {
2192
play_cutscene_music(SEQUENCE_ARGS(0, SEQ_EVENT_CUTSCENE_ENDING));
2193
}
2194
if (m->actionTimer == 255) {
2195
advance_cutscene_step(m);
2196
}
2197
2198
sEndJumboStarObj->oFaceAngleYaw += 0x0400;
2199
generate_yellow_sparkles(0, 2528, -1800, 250.0f);
2200
play_sound(SOUND_AIR_PEACH_TWINKLE, sEndJumboStarObj->header.gfx.cameraToObject);
2201
}
2202
2203
#if defined(VERSION_EU)
2204
#define TIMER_FADE_IN_PEACH 201
2205
#define TIMER_DESCEND_PEACH 280
2206
#elif defined(VERSION_SH)
2207
#define TIMER_FADE_IN_PEACH 276
2208
#define TIMER_DESCEND_PEACH 400
2209
#else
2210
#define TIMER_FADE_IN_PEACH 276
2211
#define TIMER_DESCEND_PEACH 355
2212
#endif
2213
2214
// free peach from the stained glass window
2215
static void end_peach_cutscene_spawn_peach(struct MarioState *m) {
2216
if (m->actionTimer == 1) {
2217
play_transition(WARP_TRANSITION_FADE_INTO_COLOR, 14, 255, 255, 255);
2218
}
2219
if (m->actionTimer == 2) {
2220
play_sound(SOUND_MENU_STAR_SOUND, gGlobalSoundSource);
2221
}
2222
if (m->actionTimer == 44) {
2223
play_transition(WARP_TRANSITION_FADE_FROM_COLOR, 192, 255, 255, 255);
2224
}
2225
if (m->actionTimer == 40) {
2226
obj_mark_for_deletion(sEndJumboStarObj);
2227
2228
sEndPeachObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_PEACH, bhvEndPeach, 0, 2428,
2229
-1300, 0, 0, 0);
2230
gCutsceneFocus = sEndPeachObj;
2231
2232
sEndRightToadObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_TOAD, bhvEndToad, 200,
2233
906, -1290, 0, 0, 0);
2234
2235
sEndLeftToadObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_TOAD, bhvEndToad, -200,
2236
906, -1290, 0, 0, 0);
2237
2238
sEndPeachObj->oOpacity = 127;
2239
sEndRightToadObj->oOpacity = 255;
2240
sEndLeftToadObj->oOpacity = 255;
2241
2242
D_8032CBE4 = 4;
2243
sEndPeachAnimation = 4;
2244
2245
sEndToadAnims[0] = 4;
2246
sEndToadAnims[1] = 5;
2247
}
2248
2249
if (m->actionTimer >= TIMER_FADE_IN_PEACH) {
2250
sEndPeachObj->oOpacity = camera_approach_f32_symmetric(sEndPeachObj->oOpacity, 255.0f, 2.0f);
2251
}
2252
if (m->actionTimer >= 40) {
2253
generate_yellow_sparkles(0, 2628, -1300, 150.0f);
2254
}
2255
2256
if (m->actionTimer == TIMER_DESCEND_PEACH) {
2257
advance_cutscene_step(m);
2258
}
2259
// probably added sounds later and missed the previous >= 40 check
2260
if (m->actionTimer >= 40) {
2261
play_sound(SOUND_AIR_PEACH_TWINKLE, sEndPeachObj->header.gfx.cameraToObject);
2262
}
2263
}
2264
2265
#ifdef VERSION_EU
2266
#define TIMER_RUN_TO_PEACH 531
2267
#else
2268
#define TIMER_RUN_TO_PEACH 584
2269
#endif
2270
2271
// descend peach
2272
static void end_peach_cutscene_descend_peach(struct MarioState *m) {
2273
generate_yellow_sparkles(0, sEndPeachObj->oPosY, -1300, 150.0f);
2274
2275
if (sEndPeachObj->oPosY >= 1300.0f) {
2276
if (m->actionState < 60) {
2277
m->actionState += 5;
2278
}
2279
} else {
2280
if (m->actionState >= 27) {
2281
m->actionState -= 2;
2282
}
2283
set_mario_animation(m, MARIO_ANIM_CREDITS_RETURN_FROM_LOOK_UP);
2284
}
2285
2286
if ((sEndPeachObj->oPosY -= m->actionState / 10) <= 907.0f) {
2287
sEndPeachObj->oPosY = 906.0f;
2288
}
2289
2290
play_sound(SOUND_AIR_PEACH_TWINKLE, sEndPeachObj->header.gfx.cameraToObject);
2291
2292
if (m->actionTimer >= TIMER_RUN_TO_PEACH) {
2293
advance_cutscene_step(m);
2294
}
2295
}
2296
2297
#undef TIMER_RUN_TO_PEACH
2298
2299
// Mario runs to peach
2300
static void end_peach_cutscene_run_to_peach(struct MarioState *m) {
2301
struct Surface *surf;
2302
2303
if (m->actionTimer == 22) {
2304
sEndPeachAnimation = 5;
2305
}
2306
2307
if ((m->pos[2] -= 20.0f) <= -1181.0f) {
2308
m->pos[2] = -1180.0f;
2309
advance_cutscene_step(m);
2310
}
2311
2312
m->pos[1] = find_floor(m->pos[0], m->pos[1], m->pos[2], &surf);
2313
2314
set_mario_anim_with_accel(m, MARIO_ANIM_RUNNING, 0x00080000);
2315
play_step_sound(m, 9, 45);
2316
2317
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
2318
m->particleFlags |= PARTICLE_DUST;
2319
}
2320
2321
// dialog 1
2322
// "Mario!"
2323
// "The power of the Stars is restored to the castle..."
2324
static void end_peach_cutscene_dialog_1(struct MarioState *m) {
2325
s32 animFrame = set_mario_animation(m, m->actionState == 0 ? MARIO_ANIM_CREDITS_TAKE_OFF_CAP
2326
: MARIO_ANIM_CREDITS_LOOK_UP);
2327
2328
if (m->actionState == 0) {
2329
if (animFrame == 8) {
2330
cutscene_take_cap_off(m);
2331
}
2332
2333
if (is_anim_at_end(m)) {
2334
m->actionState++;
2335
}
2336
}
2337
2338
switch (m->actionTimer) {
2339
#ifdef VERSION_SH
2340
case 110:
2341
#else
2342
case 80:
2343
#endif
2344
sEndPeachAnimation = 6;
2345
break;
2346
2347
#ifdef VERSION_SH
2348
case 111:
2349
#else
2350
case 81:
2351
#endif
2352
D_8032CBE4 = 3;
2353
break;
2354
2355
#ifdef VERSION_SH
2356
case 175:
2357
#else
2358
case 145:
2359
#endif
2360
D_8032CBE4 = 2;
2361
break;
2362
2363
#ifdef VERSION_SH
2364
case 258:
2365
#else
2366
case 228:
2367
#endif
2368
D_8032CBE4 = 1;
2369
D_8032CBE8 = 1;
2370
break;
2371
2372
#ifdef VERSION_SH
2373
case 260:
2374
#else
2375
case 230:
2376
#endif
2377
set_cutscene_message(160, 227, 0, 30);
2378
#ifndef VERSION_JP
2379
seq_player_lower_volume(SEQ_PLAYER_LEVEL, 60, 40);
2380
play_sound(SOUND_PEACH_MARIO, sEndPeachObj->header.gfx.cameraToObject);
2381
#endif
2382
break;
2383
2384
#ifdef VERSION_SH
2385
case 305:
2386
#else
2387
case 275:
2388
#endif
2389
D_8032CBE4 = 0;
2390
D_8032CBE8 = 0;
2391
break;
2392
2393
#ifdef VERSION_SH
2394
case 320:
2395
#else
2396
case 290:
2397
#endif
2398
set_cutscene_message(160, 227, 1, 60);
2399
#ifndef VERSION_JP
2400
play_sound(SOUND_PEACH_POWER_OF_THE_STARS, sEndPeachObj->header.gfx.cameraToObject);
2401
#endif
2402
break;
2403
2404
#ifdef VERSION_SH
2405
case 510:
2406
#else
2407
case 480:
2408
#endif
2409
advance_cutscene_step(m);
2410
break;
2411
}
2412
}
2413
2414
#if defined(VERSION_EU)
2415
#define TIMER_SOMETHING_SPECIAL 150
2416
#define TIMER_PEACH_KISS 260
2417
#elif defined(VERSION_SH)
2418
#define TIMER_SOMETHING_SPECIAL 170
2419
#define TIMER_PEACH_KISS 250
2420
#else
2421
#define TIMER_SOMETHING_SPECIAL 130
2422
#define TIMER_PEACH_KISS 200
2423
#endif
2424
2425
// dialog 2
2426
// "...and it's all thanks to you!"
2427
// "Thank you Mario!"
2428
// "We have to do something special for you..."
2429
static void end_peach_cutscene_dialog_2(struct MarioState *m) {
2430
sEndPeachAnimation = 9;
2431
2432
switch (m->actionTimer) {
2433
#ifdef VERSION_SH
2434
case 39:
2435
#else
2436
case 29:
2437
#endif
2438
set_cutscene_message(160, 227, 2, 30);
2439
#ifndef VERSION_JP
2440
play_sound(SOUND_PEACH_THANKS_TO_YOU, sEndPeachObj->header.gfx.cameraToObject);
2441
#endif
2442
break;
2443
2444
#ifdef VERSION_SH
2445
case 65:
2446
#else
2447
case 45:
2448
#endif
2449
D_8032CBE8 = 1;
2450
break;
2451
2452
#ifdef VERSION_SH
2453
case 105:
2454
#else
2455
case 75:
2456
#endif
2457
set_cutscene_message(160, 227, 3, 30);
2458
#ifndef VERSION_JP
2459
play_sound(SOUND_PEACH_THANK_YOU_MARIO, sEndPeachObj->header.gfx.cameraToObject);
2460
#endif
2461
break;
2462
2463
case TIMER_SOMETHING_SPECIAL:
2464
set_cutscene_message(160, 227, 4, 40);
2465
#ifndef VERSION_JP
2466
play_sound(SOUND_PEACH_SOMETHING_SPECIAL, sEndPeachObj->header.gfx.cameraToObject);
2467
#endif
2468
break;
2469
2470
case TIMER_PEACH_KISS:
2471
advance_cutscene_step(m);
2472
break;
2473
}
2474
}
2475
2476
#undef TIMER_SOMETHING_SPECIAL
2477
#undef TIMER_PEACH_KISS
2478
2479
// blink twice then have half-shut eyes (see end_peach_cutscene_kiss_from_peach)
2480
static u8 sMarioBlinkOverride[20] = {
2481
MARIO_EYES_HALF_CLOSED, MARIO_EYES_HALF_CLOSED, MARIO_EYES_CLOSED, MARIO_EYES_CLOSED,
2482
MARIO_EYES_HALF_CLOSED, MARIO_EYES_HALF_CLOSED, MARIO_EYES_OPEN, MARIO_EYES_OPEN,
2483
MARIO_EYES_HALF_CLOSED, MARIO_EYES_HALF_CLOSED, MARIO_EYES_CLOSED, MARIO_EYES_CLOSED,
2484
MARIO_EYES_HALF_CLOSED, MARIO_EYES_HALF_CLOSED, MARIO_EYES_OPEN, MARIO_EYES_OPEN,
2485
MARIO_EYES_HALF_CLOSED, MARIO_EYES_HALF_CLOSED, MARIO_EYES_CLOSED, MARIO_EYES_CLOSED,
2486
};
2487
2488
static void end_peach_cutscene_kiss_from_peach(struct MarioState *m) {
2489
sEndPeachAnimation = 10;
2490
2491
if (m->actionTimer >= 90) {
2492
m->marioBodyState->eyeState =
2493
m->actionTimer < 110 ? sMarioBlinkOverride[m->actionTimer - 90] : MARIO_EYES_HALF_CLOSED;
2494
}
2495
2496
switch (m->actionTimer) {
2497
case 8:
2498
D_8032CBE8 = 0;
2499
break;
2500
2501
case 10:
2502
D_8032CBE4 = 3;
2503
break;
2504
2505
case 50:
2506
D_8032CBE4 = 4;
2507
break;
2508
2509
case 75:
2510
m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED;
2511
break;
2512
2513
case 76:
2514
m->marioBodyState->eyeState = MARIO_EYES_CLOSED;
2515
break;
2516
2517
case 100:
2518
D_8032CBE4 = 3;
2519
break;
2520
2521
case 136:
2522
D_8032CBE4 = 0;
2523
break;
2524
2525
case 140:
2526
advance_cutscene_step(m);
2527
break;
2528
}
2529
}
2530
2531
static void end_peach_cutscene_star_dance(struct MarioState *m) {
2532
s32 animFrame = set_mario_animation(m, MARIO_ANIM_CREDITS_PEACE_SIGN);
2533
2534
if (animFrame == 77) {
2535
cutscene_put_cap_on(m);
2536
}
2537
if (animFrame == 88) {
2538
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
2539
}
2540
if (animFrame >= 98) {
2541
m->marioBodyState->handState = MARIO_HAND_PEACE_SIGN;
2542
}
2543
2544
if (m->actionTimer < 52) {
2545
m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED;
2546
}
2547
2548
switch (m->actionTimer) {
2549
case 70:
2550
D_8032CBE4 = 1;
2551
break;
2552
2553
case 86:
2554
D_8032CBE4 = 2;
2555
break;
2556
2557
case 90:
2558
D_8032CBE4 = 3;
2559
break;
2560
2561
case 120:
2562
D_8032CBE4 = 0;
2563
break;
2564
2565
case 140:
2566
#ifndef VERSION_JP
2567
seq_player_unlower_volume(SEQ_PLAYER_LEVEL, 60);
2568
#endif
2569
play_cutscene_music(SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_CREDITS));
2570
break;
2571
2572
case 142:
2573
advance_cutscene_step(m);
2574
break;
2575
}
2576
}
2577
2578
// dialog 3
2579
// "Listen everybody"
2580
// "let's bake a delicious cake..."
2581
// "...for Mario..."
2582
static void end_peach_cutscene_dialog_3(struct MarioState *m) {
2583
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
2584
2585
sEndPeachObj->oPosY = end_obj_set_visual_pos(sEndPeachObj);
2586
sEndRightToadObj->oPosY = end_obj_set_visual_pos(sEndRightToadObj);
2587
sEndLeftToadObj->oPosY = end_obj_set_visual_pos(sEndLeftToadObj);
2588
2589
switch (m->actionTimer) {
2590
case 1:
2591
sEndPeachAnimation = 0;
2592
sEndToadAnims[0] = 0;
2593
sEndToadAnims[1] = 2;
2594
D_8032CBE8 = 1;
2595
set_cutscene_message(160, 227, 5, 30);
2596
#ifndef VERSION_JP
2597
play_sound(SOUND_PEACH_BAKE_A_CAKE, sEndPeachObj->header.gfx.cameraToObject);
2598
#endif
2599
break;
2600
2601
case 55:
2602
set_cutscene_message(160, 227, 6, 40);
2603
break;
2604
2605
case 130:
2606
set_cutscene_message(160, 227, 7, 50);
2607
#ifndef VERSION_JP
2608
play_sound(SOUND_PEACH_FOR_MARIO, sEndPeachObj->header.gfx.cameraToObject);
2609
#endif
2610
break;
2611
}
2612
2613
if (m->actionTimer == 350) {
2614
advance_cutscene_step(m);
2615
}
2616
}
2617
2618
// "Mario!"
2619
static void end_peach_cutscene_run_to_castle(struct MarioState *m) {
2620
set_mario_animation(m, m->actionState == 0 ? MARIO_ANIM_CREDITS_START_WALK_LOOK_UP
2621
: MARIO_ANIM_CREDITS_LOOK_BACK_THEN_RUN);
2622
2623
m->marioObj->header.gfx.pos[1] = end_obj_set_visual_pos(m->marioObj);
2624
2625
if (m->actionState == 0 && is_anim_past_end(m)) {
2626
m->actionState = 1;
2627
}
2628
2629
if (m->actionTimer == 95) {
2630
set_cutscene_message(160, 227, 0, 40);
2631
#ifndef VERSION_JP
2632
play_sound(SOUND_PEACH_MARIO2, sEndPeachObj->header.gfx.cameraToObject);
2633
#endif
2634
}
2635
if (m->actionTimer == 389) {
2636
advance_cutscene_step(m);
2637
}
2638
}
2639
2640
static void end_peach_cutscene_fade_out(struct MarioState *m) {
2641
if (m->actionState == 0) {
2642
level_trigger_warp(m, WARP_OP_CREDITS_NEXT);
2643
gPaintingMarioYEntry = 1500.0f; // ensure medium water level in WDW credits cutscene
2644
m->actionState = 1;
2645
}
2646
}
2647
2648
enum {
2649
END_PEACH_CUTSCENE_MARIO_FALLING,
2650
END_PEACH_CUTSCENE_MARIO_LANDING,
2651
END_PEACH_CUTSCENE_SUMMON_JUMBO_STAR,
2652
END_PEACH_CUTSCENE_SPAWN_PEACH,
2653
END_PEACH_CUTSCENE_DESCEND_PEACH,
2654
END_PEACH_CUTSCENE_RUN_TO_PEACH,
2655
END_PEACH_CUTSCENE_DIALOG_1,
2656
END_PEACH_CUTSCENE_DIALOG_2,
2657
END_PEACH_CUTSCENE_KISS_FROM_PEACH,
2658
END_PEACH_CUTSCENE_STAR_DANCE,
2659
END_PEACH_CUTSCENE_DIALOG_3,
2660
END_PEACH_CUTSCENE_RUN_TO_CASTLE,
2661
END_PEACH_CUTSCENE_FADE_OUT
2662
};
2663
2664
static s32 act_end_peach_cutscene(struct MarioState *m) {
2665
switch (m->actionArg) {
2666
case END_PEACH_CUTSCENE_MARIO_FALLING:
2667
end_peach_cutscene_mario_falling(m);
2668
break;
2669
case END_PEACH_CUTSCENE_MARIO_LANDING:
2670
end_peach_cutscene_mario_landing(m);
2671
break;
2672
case END_PEACH_CUTSCENE_SUMMON_JUMBO_STAR:
2673
end_peach_cutscene_summon_jumbo_star(m);
2674
break;
2675
case END_PEACH_CUTSCENE_SPAWN_PEACH:
2676
end_peach_cutscene_spawn_peach(m);
2677
break;
2678
case END_PEACH_CUTSCENE_DESCEND_PEACH:
2679
end_peach_cutscene_descend_peach(m);
2680
break;
2681
case END_PEACH_CUTSCENE_RUN_TO_PEACH:
2682
end_peach_cutscene_run_to_peach(m);
2683
break;
2684
case END_PEACH_CUTSCENE_DIALOG_1:
2685
end_peach_cutscene_dialog_1(m);
2686
break;
2687
case END_PEACH_CUTSCENE_DIALOG_2:
2688
end_peach_cutscene_dialog_2(m);
2689
break;
2690
case END_PEACH_CUTSCENE_KISS_FROM_PEACH:
2691
end_peach_cutscene_kiss_from_peach(m);
2692
break;
2693
case END_PEACH_CUTSCENE_STAR_DANCE:
2694
end_peach_cutscene_star_dance(m);
2695
break;
2696
case END_PEACH_CUTSCENE_DIALOG_3:
2697
end_peach_cutscene_dialog_3(m);
2698
break;
2699
case END_PEACH_CUTSCENE_RUN_TO_CASTLE:
2700
end_peach_cutscene_run_to_castle(m);
2701
break;
2702
case END_PEACH_CUTSCENE_FADE_OUT:
2703
end_peach_cutscene_fade_out(m);
2704
break;
2705
}
2706
2707
m->actionTimer++;
2708
2709
sEndCutsceneVp.vp.vscale[0] = 640;
2710
sEndCutsceneVp.vp.vscale[1] = 360;
2711
sEndCutsceneVp.vp.vtrans[0] = 640;
2712
sEndCutsceneVp.vp.vtrans[1] = 480;
2713
override_viewport_and_clip(NULL, &sEndCutsceneVp, 0, 0, 0);
2714
2715
return FALSE;
2716
}
2717
2718
/*#ifdef VERSION_EU
2719
#define TIMER_CREDITS_SHOW 51
2720
#define TIMER_CREDITS_PROGRESS 80
2721
#define TIMER_CREDITS_WARP 160
2722
#elif defined(VERSION_SH)
2723
#define TIMER_CREDITS_SHOW 61
2724
#define TIMER_CREDITS_PROGRESS 90
2725
#define TIMER_CREDITS_WARP 204
2726
#else
2727
#define TIMER_CREDITS_SHOW 61
2728
#define TIMER_CREDITS_PROGRESS 90
2729
#define TIMER_CREDITS_WARP 200
2730
#endif*/
2731
2732
#ifdef VERSION_EU
2733
#define TIMER_CREDITS_SHOW 64
2734
#define TIMER_CREDITS_PROGRESS 93
2735
#define TIMER_CREDITS_WARP 173
2736
#else
2737
#define TIMER_CREDITS_SHOW 74
2738
#define TIMER_CREDITS_PROGRESS 103
2739
#define TIMER_CREDITS_WARP 213
2740
#endif
2741
2742
static s32 act_credits_cutscene(struct MarioState *m) {
2743
s32 width;
2744
s32 height;
2745
2746
m->statusForCamera->cameraEvent = CAM_EVENT_START_CREDITS;
2747
// checks if Mario is underwater (JRB, DDD, SA, etc.)
2748
if (m->pos[1] < m->waterLevel - 100) {
2749
if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) {
2750
set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1);
2751
}
2752
set_mario_animation(m, MARIO_ANIM_WATER_IDLE);
2753
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
2754
// will copy over roll and pitch, if set
2755
vec3s_copy(m->marioObj->header.gfx.angle, m->faceAngle);
2756
m->particleFlags |= PARTICLE_BUBBLE;
2757
} else {
2758
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
2759
if (m->actionTimer > 0) {
2760
stop_and_set_height_to_floor(m);
2761
}
2762
}
2763
2764
if (m->actionTimer >= TIMER_CREDITS_SHOW) {
2765
if (m->actionState < 40) {
2766
m->actionState += 2;
2767
}
2768
2769
width = m->actionState * 640 / 100;
2770
height = m->actionState * 480 / 100;
2771
2772
sEndCutsceneVp.vp.vscale[0] = 640 - width;
2773
sEndCutsceneVp.vp.vscale[1] = 480 - height;
2774
sEndCutsceneVp.vp.vtrans[0] =
2775
(gCurrCreditsEntry->unk02 & 0x10 ? width : -width) * 56 / 100 + 640;
2776
sEndCutsceneVp.vp.vtrans[1] =
2777
(gCurrCreditsEntry->unk02 & 0x20 ? height : -height) * 66 / 100 + 480;
2778
2779
override_viewport_and_clip(&sEndCutsceneVp, 0, 0, 0, 0);
2780
}
2781
2782
if (m->actionTimer == TIMER_CREDITS_PROGRESS) {
2783
reset_cutscene_msg_fade();
2784
}
2785
2786
if (m->actionTimer >= TIMER_CREDITS_PROGRESS) {
2787
sDispCreditsEntry = gCurrCreditsEntry;
2788
}
2789
2790
if (m->actionTimer++ == TIMER_CREDITS_WARP) {
2791
level_trigger_warp(m, WARP_OP_CREDITS_NEXT);
2792
}
2793
2794
m->marioObj->header.gfx.angle[1] += (gCurrCreditsEntry->unk02 & 0xC0) << 8;
2795
2796
return FALSE;
2797
}
2798
2799
static s32 act_end_waving_cutscene(struct MarioState *m) {
2800
if (m->actionState == 0) {
2801
m->statusForCamera->cameraEvent = CAM_EVENT_START_END_WAVING;
2802
2803
sEndPeachObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_PEACH, bhvEndPeach, 60, 906,
2804
-1180, 0, 0, 0);
2805
2806
sEndRightToadObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_TOAD, bhvEndToad, 180,
2807
906, -1170, 0, 0, 0);
2808
2809
sEndLeftToadObj = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_TOAD, bhvEndToad, -180,
2810
906, -1170, 0, 0, 0);
2811
2812
sEndPeachObj->oOpacity = 255;
2813
sEndRightToadObj->oOpacity = 255;
2814
sEndLeftToadObj->oOpacity = 255;
2815
2816
sEndPeachAnimation = 11;
2817
sEndToadAnims[0] = 6;
2818
sEndToadAnims[1] = 7;
2819
2820
m->actionState = 1;
2821
}
2822
2823
set_mario_animation(m, MARIO_ANIM_CREDITS_WAVING);
2824
stop_and_set_height_to_floor(m);
2825
2826
m->marioObj->header.gfx.angle[1] += 0x8000;
2827
m->marioObj->header.gfx.pos[0] -= 60.0f;
2828
m->marioBodyState->handState = MARIO_HAND_RIGHT_OPEN;
2829
2830
if (m->actionTimer++ == 300) {
2831
level_trigger_warp(m, WARP_OP_CREDITS_END);
2832
}
2833
2834
return FALSE;
2835
}
2836
2837
static s32 check_for_instant_quicksand(struct MarioState *m) {
2838
if (m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE
2839
&& m->action != ACT_QUICKSAND_DEATH) {
2840
update_mario_sound_and_camera(m);
2841
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
2842
}
2843
return FALSE;
2844
}
2845
2846
s32 mario_execute_cutscene_action(struct MarioState *m) {
2847
s32 cancel;
2848
2849
if (check_for_instant_quicksand(m)) {
2850
return TRUE;
2851
}
2852
2853
/* clang-format off */
2854
switch (m->action) {
2855
case ACT_DISAPPEARED: cancel = act_disappeared(m); break;
2856
case ACT_INTRO_CUTSCENE: cancel = act_intro_cutscene(m); break;
2857
case ACT_STAR_DANCE_EXIT: cancel = act_star_dance(m); break;
2858
case ACT_STAR_DANCE_NO_EXIT: cancel = act_star_dance(m); break;
2859
case ACT_STAR_DANCE_WATER: cancel = act_star_dance_water(m); break;
2860
case ACT_FALL_AFTER_STAR_GRAB: cancel = act_fall_after_star_grab(m); break;
2861
case ACT_READING_AUTOMATIC_DIALOG: cancel = act_reading_automatic_dialog(m); break;
2862
case ACT_READING_NPC_DIALOG: cancel = act_reading_npc_dialog(m); break;
2863
case ACT_DEBUG_FREE_MOVE: cancel = act_debug_free_move(m); break;
2864
case ACT_READING_SIGN: cancel = act_reading_sign(m); break;
2865
case ACT_JUMBO_STAR_CUTSCENE: cancel = act_jumbo_star_cutscene(m); break;
2866
case ACT_WAITING_FOR_DIALOG: cancel = act_waiting_for_dialog(m); break;
2867
case ACT_STANDING_DEATH: cancel = act_standing_death(m); break;
2868
case ACT_QUICKSAND_DEATH: cancel = act_quicksand_death(m); break;
2869
case ACT_ELECTROCUTION: cancel = act_electrocution(m); break;
2870
case ACT_SUFFOCATION: cancel = act_suffocation(m); break;
2871
case ACT_DEATH_ON_STOMACH: cancel = act_death_on_stomach(m); break;
2872
case ACT_DEATH_ON_BACK: cancel = act_death_on_back(m); break;
2873
case ACT_EATEN_BY_BUBBA: cancel = act_eaten_by_bubba(m); break;
2874
case ACT_END_PEACH_CUTSCENE: cancel = act_end_peach_cutscene(m); break;
2875
case ACT_CREDITS_CUTSCENE: cancel = act_credits_cutscene(m); break;
2876
case ACT_END_WAVING_CUTSCENE: cancel = act_end_waving_cutscene(m); break;
2877
case ACT_PULLING_DOOR:
2878
case ACT_PUSHING_DOOR: cancel = act_going_through_door(m); break;
2879
case ACT_WARP_DOOR_SPAWN: cancel = act_warp_door_spawn(m); break;
2880
case ACT_EMERGE_FROM_PIPE: cancel = act_emerge_from_pipe(m); break;
2881
case ACT_SPAWN_SPIN_AIRBORNE: cancel = act_spawn_spin_airborne(m); break;
2882
case ACT_SPAWN_SPIN_LANDING: cancel = act_spawn_spin_landing(m); break;
2883
case ACT_EXIT_AIRBORNE: cancel = act_exit_airborne(m); break;
2884
case ACT_EXIT_LAND_SAVE_DIALOG: cancel = act_exit_land_save_dialog(m); break;
2885
case ACT_DEATH_EXIT: cancel = act_death_exit(m); break;
2886
case ACT_UNUSED_DEATH_EXIT: cancel = act_unused_death_exit(m); break;
2887
case ACT_FALLING_DEATH_EXIT: cancel = act_falling_death_exit(m); break;
2888
case ACT_SPECIAL_EXIT_AIRBORNE: cancel = act_special_exit_airborne(m); break;
2889
case ACT_SPECIAL_DEATH_EXIT: cancel = act_special_death_exit(m); break;
2890
case ACT_FALLING_EXIT_AIRBORNE: cancel = act_falling_exit_airborne(m); break;
2891
case ACT_UNLOCKING_KEY_DOOR: cancel = act_unlocking_key_door(m); break;
2892
case ACT_UNLOCKING_STAR_DOOR: cancel = act_unlocking_star_door(m); break;
2893
case ACT_ENTERING_STAR_DOOR: cancel = act_entering_star_door(m); break;
2894
case ACT_SPAWN_NO_SPIN_AIRBORNE: cancel = act_spawn_no_spin_airborne(m); break;
2895
case ACT_SPAWN_NO_SPIN_LANDING: cancel = act_spawn_no_spin_landing(m); break;
2896
case ACT_BBH_ENTER_JUMP: cancel = act_bbh_enter_jump(m); break;
2897
case ACT_BBH_ENTER_SPIN: cancel = act_bbh_enter_spin(m); break;
2898
case ACT_TELEPORT_FADE_OUT: cancel = act_teleport_fade_out(m); break;
2899
case ACT_TELEPORT_FADE_IN: cancel = act_teleport_fade_in(m); break;
2900
case ACT_SHOCKED: cancel = act_shocked(m); break;
2901
case ACT_SQUISHED: cancel = act_squished(m); break;
2902
case ACT_HEAD_STUCK_IN_GROUND: cancel = act_head_stuck_in_ground(m); break;
2903
case ACT_BUTT_STUCK_IN_GROUND: cancel = act_butt_stuck_in_ground(m); break;
2904
case ACT_FEET_STUCK_IN_GROUND: cancel = act_feet_stuck_in_ground(m); break;
2905
case ACT_PUTTING_ON_CAP: cancel = act_putting_on_cap(m); break;
2906
}
2907
/* clang-format on */
2908
2909
if (!cancel && (m->input & INPUT_IN_WATER)) {
2910
m->particleFlags |= PARTICLE_IDLE_WATER_WAVE;
2911
}
2912
2913
return cancel;
2914
}
2915