Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/game/mario_actions_object.c
7858 views
1
#include <PR/ultratypes.h>
2
3
#include "sm64.h"
4
#include "mario_actions_object.h"
5
#include "types.h"
6
#include "mario_step.h"
7
#include "mario.h"
8
#include "audio/external.h"
9
#include "interaction.h"
10
#include "engine/math_util.h"
11
#include "rumble_init.h"
12
13
#include "settings.h"
14
15
/**
16
* Used by act_punching() to determine Mario's forward velocity during each
17
* animation frame.
18
*/
19
s8 sPunchingForwardVelocities[8] = { 0, 1, 1, 2, 3, 5, 7, 10 };
20
21
void animated_stationary_ground_step(struct MarioState *m, s32 animation, u32 endAction) {
22
stationary_ground_step(m);
23
set_mario_animation(m, animation);
24
if (is_anim_at_end(m)) {
25
set_mario_action(m, endAction, 0);
26
}
27
}
28
29
s32 mario_update_punch_sequence(struct MarioState *m) {
30
u32 endAction, crouchEndAction;
31
s32 animFrame;
32
33
if (m->action & ACT_FLAG_MOVING) {
34
endAction = ACT_WALKING, crouchEndAction = ACT_CROUCH_SLIDE;
35
} else {
36
endAction = ACT_IDLE, crouchEndAction = ACT_CROUCHING;
37
}
38
39
switch (m->actionArg) {
40
case 0:
41
play_sound(SOUND_MARIO_PUNCH_YAH, m->marioObj->header.gfx.cameraToObject);
42
// Fall-through:
43
case 1:
44
set_mario_animation(m, MARIO_ANIM_FIRST_PUNCH);
45
if (is_anim_past_end(m)) {
46
m->actionArg = 2;
47
} else {
48
m->actionArg = 1;
49
}
50
51
if (m->marioObj->header.gfx.animInfo.animFrame >= 2) {
52
if (mario_check_object_grab(m)) {
53
return TRUE;
54
}
55
56
m->flags |= MARIO_PUNCHING;
57
}
58
59
if (m->actionArg == 2) {
60
m->marioBodyState->punchState = (0 << 6) | 4;
61
}
62
break;
63
64
case 2:
65
set_mario_animation(m, MARIO_ANIM_FIRST_PUNCH_FAST);
66
67
if (m->marioObj->header.gfx.animInfo.animFrame <= 0) {
68
m->flags |= MARIO_PUNCHING;
69
}
70
71
if (m->input & INPUT_B_PRESSED) {
72
m->actionArg = 3;
73
}
74
75
if (is_anim_at_end(m)) {
76
set_mario_action(m, endAction, 0);
77
}
78
break;
79
80
case 3:
81
play_sound(SOUND_MARIO_PUNCH_WAH, m->marioObj->header.gfx.cameraToObject);
82
// Fall-through:
83
case 4:
84
set_mario_animation(m, MARIO_ANIM_SECOND_PUNCH);
85
if (is_anim_past_end(m)) {
86
m->actionArg = 5;
87
} else {
88
m->actionArg = 4;
89
}
90
91
if (m->marioObj->header.gfx.animInfo.animFrame > 0) {
92
m->flags |= MARIO_PUNCHING;
93
}
94
95
if (m->actionArg == 5) {
96
m->marioBodyState->punchState = (1 << 6) | 4;
97
}
98
break;
99
100
case 5:
101
set_mario_animation(m, MARIO_ANIM_SECOND_PUNCH_FAST);
102
if (m->marioObj->header.gfx.animInfo.animFrame <= 0) {
103
m->flags |= MARIO_PUNCHING;
104
}
105
106
if (m->input & INPUT_B_PRESSED) {
107
m->actionArg = 6;
108
}
109
110
if (is_anim_at_end(m)) {
111
set_mario_action(m, endAction, 0);
112
}
113
break;
114
115
case 6:
116
play_mario_action_sound(m, SOUND_MARIO_PUNCH_HOO, 1);
117
animFrame = set_mario_animation(m, MARIO_ANIM_GROUND_KICK);
118
if (animFrame == 0) {
119
m->marioBodyState->punchState = (2 << 6) | 6;
120
}
121
122
if (animFrame >= 0 && animFrame < 8) {
123
m->flags |= MARIO_KICKING;
124
}
125
126
if (is_anim_at_end(m)) {
127
set_mario_action(m, endAction, 0);
128
}
129
break;
130
131
case 9:
132
play_mario_action_sound(m, SOUND_MARIO_PUNCH_HOO, 1);
133
set_mario_animation(m, MARIO_ANIM_BREAKDANCE);
134
animFrame = m->marioObj->header.gfx.animInfo.animFrame;
135
136
if (animFrame >= 2 && animFrame < 8) {
137
m->flags |= MARIO_TRIPPING;
138
}
139
140
if (is_anim_at_end(m)) {
141
set_mario_action(m, crouchEndAction, 0);
142
}
143
break;
144
}
145
146
return FALSE;
147
}
148
149
s32 act_punching(struct MarioState *m) {
150
if (m->input & INPUT_STOMPED) {
151
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
152
}
153
154
if (m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE)) {
155
return check_common_action_exits(m);
156
}
157
158
if (m->actionState == 0 && (m->input & INPUT_A_DOWN)) {
159
return set_mario_action(m, ACT_JUMP_KICK, 0);
160
}
161
162
m->actionState = 1;
163
if (m->actionArg == 0) {
164
m->actionTimer = 7;
165
}
166
167
mario_set_forward_vel(m, sPunchingForwardVelocities[m->actionTimer]);
168
if (m->actionTimer > 0) {
169
m->actionTimer--;
170
}
171
172
mario_update_punch_sequence(m);
173
perform_ground_step(m);
174
return FALSE;
175
}
176
177
s32 act_picking_up(struct MarioState *m) {
178
if (m->input & INPUT_STOMPED) {
179
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
180
}
181
182
if (m->input & INPUT_OFF_FLOOR) {
183
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
184
}
185
186
if (m->actionState == 0 && is_anim_at_end(m)) {
187
//! While the animation is playing, it is possible for the used object
188
// to unload. This allows you to pick up a vacant or newly loaded object
189
// slot (cloning via fake object).
190
mario_grab_used_object(m);
191
play_sound_if_no_flag(m, SOUND_MARIO_HRMM, MARIO_MARIO_SOUND_PLAYED);
192
m->actionState = 1;
193
}
194
195
if (m->actionState == 1) {
196
if (m->heldObj->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO) {
197
m->marioBodyState->grabPos = GRAB_POS_HEAVY_OBJ;
198
set_mario_animation(m, MARIO_ANIM_GRAB_HEAVY_OBJECT);
199
if (is_anim_at_end(m)) {
200
set_mario_action(m, ACT_HOLD_HEAVY_IDLE, 0);
201
}
202
} else {
203
m->marioBodyState->grabPos = GRAB_POS_LIGHT_OBJ;
204
set_mario_animation(m, MARIO_ANIM_PICK_UP_LIGHT_OBJ);
205
if (is_anim_at_end(m)) {
206
set_mario_action(m, ACT_HOLD_IDLE, 0);
207
}
208
}
209
}
210
211
stationary_ground_step(m);
212
return FALSE;
213
}
214
215
s32 act_dive_picking_up(struct MarioState *m) {
216
if (m->input & INPUT_STOMPED) {
217
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
218
}
219
220
//! Hands-free holding. Landing on a slope or being pushed off a ledge while
221
// landing from a dive grab sets Mario's action to a non-holding action
222
// without dropping the object, causing the hands-free holding glitch.
223
if (m->input & INPUT_OFF_FLOOR) {
224
if (configApplyBugFixes > 2)
225
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
226
return set_mario_action(m, ACT_FREEFALL, 0);
227
}
228
229
if (m->input & INPUT_ABOVE_SLIDE) {
230
if (configApplyBugFixes > 2)
231
return drop_and_set_mario_action(m, ACT_BEGIN_SLIDING, 0);
232
return set_mario_action(m, ACT_BEGIN_SLIDING, 0);
233
}
234
235
animated_stationary_ground_step(m, MARIO_ANIM_STOP_SLIDE_LIGHT_OBJ, ACT_HOLD_IDLE);
236
return FALSE;
237
}
238
239
s32 act_placing_down(struct MarioState *m) {
240
if (m->input & INPUT_STOMPED) {
241
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
242
}
243
244
if (m->input & INPUT_OFF_FLOOR) {
245
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
246
}
247
248
if (++m->actionTimer == 8) {
249
mario_drop_held_object(m);
250
}
251
252
animated_stationary_ground_step(m, MARIO_ANIM_PLACE_LIGHT_OBJ, ACT_IDLE);
253
return FALSE;
254
}
255
256
s32 act_throwing(struct MarioState *m) {
257
if (m->heldObj && (m->heldObj->oInteractionSubtype & INT_SUBTYPE_HOLDABLE_NPC)) {
258
return set_mario_action(m, ACT_PLACING_DOWN, 0);
259
}
260
261
if (m->input & INPUT_STOMPED) {
262
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
263
}
264
265
if (m->input & INPUT_OFF_FLOOR) {
266
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
267
}
268
269
if (++m->actionTimer == 7) {
270
mario_throw_held_object(m);
271
play_sound_if_no_flag(m, SOUND_MARIO_WAH2, MARIO_MARIO_SOUND_PLAYED);
272
play_sound_if_no_flag(m, SOUND_ACTION_THROW, MARIO_ACTION_SOUND_PLAYED);
273
#if ENABLE_RUMBLE
274
queue_rumble_data(3, 50);
275
#endif
276
}
277
278
animated_stationary_ground_step(m, MARIO_ANIM_GROUND_THROW, ACT_IDLE);
279
return FALSE;
280
}
281
282
s32 act_heavy_throw(struct MarioState *m) {
283
if (m->input & INPUT_STOMPED) {
284
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
285
}
286
287
if (m->input & INPUT_OFF_FLOOR) {
288
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
289
}
290
291
if (++m->actionTimer == 13) {
292
mario_drop_held_object(m);
293
play_sound_if_no_flag(m, SOUND_MARIO_WAH2, MARIO_MARIO_SOUND_PLAYED);
294
play_sound_if_no_flag(m, SOUND_ACTION_THROW, MARIO_ACTION_SOUND_PLAYED);
295
#if ENABLE_RUMBLE
296
queue_rumble_data(3, 50);
297
#endif
298
}
299
300
animated_stationary_ground_step(m, MARIO_ANIM_HEAVY_THROW, ACT_IDLE);
301
return FALSE;
302
}
303
304
s32 act_stomach_slide_stop(struct MarioState *m) {
305
if (m->input & INPUT_STOMPED) {
306
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
307
}
308
309
if (m->input & INPUT_OFF_FLOOR) {
310
return set_mario_action(m, ACT_FREEFALL, 0);
311
}
312
313
if (m->input & INPUT_ABOVE_SLIDE) {
314
return set_mario_action(m, ACT_BEGIN_SLIDING, 0);
315
}
316
317
animated_stationary_ground_step(m, MARIO_ANIM_SLOW_LAND_FROM_DIVE, ACT_IDLE);
318
return FALSE;
319
}
320
321
s32 act_picking_up_bowser(struct MarioState *m) {
322
if (m->actionState == 0) {
323
m->actionState = 1;
324
m->angleVel[1] = 0;
325
m->marioBodyState->grabPos = GRAB_POS_BOWSER;
326
mario_grab_used_object(m);
327
#if ENABLE_RUMBLE
328
queue_rumble_data(5, 80);
329
#endif
330
play_sound(SOUND_MARIO_HRMM, m->marioObj->header.gfx.cameraToObject);
331
}
332
333
set_mario_animation(m, MARIO_ANIM_GRAB_BOWSER);
334
if (is_anim_at_end(m)) {
335
set_mario_action(m, ACT_HOLDING_BOWSER, 0);
336
}
337
338
stationary_ground_step(m);
339
return FALSE;
340
}
341
342
s32 act_holding_bowser(struct MarioState *m) {
343
s16 spin;
344
345
if (m->input & INPUT_B_PRESSED) {
346
#ifndef VERSION_JP
347
if (m->angleVel[1] <= -0xE00 || m->angleVel[1] >= 0xE00) {
348
play_sound(SOUND_MARIO_SO_LONGA_BOWSER, m->marioObj->header.gfx.cameraToObject);
349
} else {
350
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
351
}
352
#else
353
play_sound(SOUND_MARIO_HERE_WE_GO, m->marioObj->header.gfx.cameraToObject);
354
#endif
355
return set_mario_action(m, ACT_RELEASING_BOWSER, 0);
356
}
357
358
if (m->angleVel[1] == 0) {
359
if (m->actionTimer++ > 120) {
360
return set_mario_action(m, ACT_RELEASING_BOWSER, 1);
361
}
362
363
set_mario_animation(m, MARIO_ANIM_HOLDING_BOWSER);
364
} else {
365
m->actionTimer = 0;
366
set_mario_animation(m, MARIO_ANIM_SWINGING_BOWSER);
367
}
368
369
if (m->intendedMag > 20.0f) {
370
if (m->actionArg == 0) {
371
m->actionArg = 1;
372
m->twirlYaw = m->intendedYaw;
373
} else {
374
// spin = acceleration
375
spin = (s16)(m->intendedYaw - m->twirlYaw) / 0x80;
376
377
if (spin < -0x80) {
378
spin = -0x80;
379
}
380
if (spin > 0x80) {
381
spin = 0x80;
382
}
383
384
m->twirlYaw = m->intendedYaw;
385
m->angleVel[1] += spin;
386
387
if (configEasyBowserThrows)
388
{
389
if (m->angleVel[1] > 0x900) {
390
m->angleVel[1] = 0x900;
391
}
392
if (m->angleVel[1] < -0x900) {
393
m->angleVel[1] = -0x900;
394
}
395
}
396
else
397
{
398
if (m->angleVel[1] > 0x1000) {
399
m->angleVel[1] = 0x1000;
400
}
401
if (m->angleVel[1] < -0x1000) {
402
m->angleVel[1] = -0x1000;
403
}
404
}
405
}
406
} else {
407
m->actionArg = 0;
408
m->angleVel[1] = approach_s32(m->angleVel[1], 0, 64, 64);
409
}
410
411
// spin = starting yaw
412
spin = m->faceAngle[1];
413
m->faceAngle[1] += m->angleVel[1];
414
415
// play sound on overflow
416
if (m->angleVel[1] <= -0x100 && spin < m->faceAngle[1]) {
417
#if ENABLE_RUMBLE
418
queue_rumble_data(4, 20);
419
#endif
420
play_sound(SOUND_OBJ_BOWSER_SPINNING, m->marioObj->header.gfx.cameraToObject);
421
}
422
if (m->angleVel[1] >= 0x100 && spin > m->faceAngle[1]) {
423
#if ENABLE_RUMBLE
424
queue_rumble_data(4, 20);
425
#endif
426
play_sound(SOUND_OBJ_BOWSER_SPINNING, m->marioObj->header.gfx.cameraToObject);
427
}
428
429
stationary_ground_step(m);
430
if (m->angleVel[1] >= 0) {
431
m->marioObj->header.gfx.angle[0] = -m->angleVel[1];
432
} else {
433
m->marioObj->header.gfx.angle[0] = m->angleVel[1];
434
}
435
436
return FALSE;
437
}
438
439
s32 act_releasing_bowser(struct MarioState *m) {
440
if (++m->actionTimer == 1) {
441
if (m->actionArg == 0) {
442
#if ENABLE_RUMBLE
443
queue_rumble_data(5, 50);
444
#endif
445
mario_throw_held_object(m);
446
} else {
447
#if ENABLE_RUMBLE
448
queue_rumble_data(4, 50);
449
#endif
450
mario_drop_held_object(m);
451
}
452
}
453
454
m->angleVel[1] = 0;
455
animated_stationary_ground_step(m, MARIO_ANIM_RELEASE_BOWSER, ACT_IDLE);
456
return FALSE;
457
}
458
459
s32 check_common_object_cancels(struct MarioState *m) {
460
f32 waterSurface = m->waterLevel - 100;
461
if (m->pos[1] < waterSurface) {
462
return set_water_plunge_action(m);
463
}
464
465
if (m->input & INPUT_SQUISHED) {
466
return drop_and_set_mario_action(m, ACT_SQUISHED, 0);
467
}
468
469
if (m->health < 0x100) {
470
return drop_and_set_mario_action(m, ACT_STANDING_DEATH, 0);
471
}
472
473
return FALSE;
474
}
475
476
s32 mario_execute_object_action(struct MarioState *m) {
477
s32 cancel;
478
479
if (check_common_object_cancels(m)) {
480
return TRUE;
481
}
482
483
if (mario_update_quicksand(m, 0.5f)) {
484
return TRUE;
485
}
486
487
/* clang-format off */
488
switch (m->action) {
489
case ACT_PUNCHING: cancel = act_punching(m); break;
490
case ACT_PICKING_UP: cancel = act_picking_up(m); break;
491
case ACT_DIVE_PICKING_UP: cancel = act_dive_picking_up(m); break;
492
case ACT_STOMACH_SLIDE_STOP: cancel = act_stomach_slide_stop(m); break;
493
case ACT_PLACING_DOWN: cancel = act_placing_down(m); break;
494
case ACT_THROWING: cancel = act_throwing(m); break;
495
case ACT_HEAVY_THROW: cancel = act_heavy_throw(m); break;
496
case ACT_PICKING_UP_BOWSER: cancel = act_picking_up_bowser(m); break;
497
case ACT_HOLDING_BOWSER: cancel = act_holding_bowser(m); break;
498
case ACT_RELEASING_BOWSER: cancel = act_releasing_bowser(m); break;
499
}
500
/* clang-format on */
501
502
if (!cancel && (m->input & INPUT_IN_WATER)) {
503
m->particleFlags |= PARTICLE_IDLE_WATER_WAVE;
504
}
505
506
return cancel;
507
}
508
509