mario.c (60332B)
1 #include <PR/ultratypes.h> 2 3 #include "sm64.h" 4 #include "area.h" 5 #include "audio/external.h" 6 #include "behavior_actions.h" 7 #include "behavior_data.h" 8 #include "camera.h" 9 #include "engine/graph_node.h" 10 #include "engine/math_util.h" 11 #include "engine/surface_collision.h" 12 #include "game_init.h" 13 #include "interaction.h" 14 #include "level_table.h" 15 #include "level_update.h" 16 #include "main.h" 17 #include "mario.h" 18 #include "mario_actions_airborne.h" 19 #include "mario_actions_automatic.h" 20 #include "mario_actions_cutscene.h" 21 #include "mario_actions_moving.h" 22 #include "mario_actions_object.h" 23 #include "mario_actions_stationary.h" 24 #include "mario_actions_submerged.h" 25 #include "mario_misc.h" 26 #include "mario_step.h" 27 #include "memory.h" 28 #include "object_fields.h" 29 #include "object_helpers.h" 30 #include "object_list_processor.h" 31 #include "print.h" 32 #include "save_file.h" 33 #include "sound_init.h" 34 #include "rumble_init.h" 35 36 u32 unused80339F10; 37 u8 unused80339F1C[20]; 38 39 /************************************************** 40 * ANIMATIONS * 41 **************************************************/ 42 43 /** 44 * Checks if Mario's animation has reached its end point. 45 */ 46 s32 is_anim_at_end(struct MarioState *m) { 47 struct Object *o = m->marioObj; 48 49 return (o->header.gfx.animInfo.animFrame + 1) == o->header.gfx.animInfo.curAnim->loopEnd; 50 } 51 52 /** 53 * Checks if Mario's animation has surpassed 2 frames before its end point. 54 */ 55 s32 is_anim_past_end(struct MarioState *m) { 56 struct Object *o = m->marioObj; 57 58 return o->header.gfx.animInfo.animFrame >= (o->header.gfx.animInfo.curAnim->loopEnd - 2); 59 } 60 61 /** 62 * Sets Mario's animation without any acceleration, running at its default rate. 63 */ 64 s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) { 65 struct Object *o = m->marioObj; 66 struct Animation *targetAnim = m->animList->bufTarget; 67 68 if (load_patchable_table(m->animList, targetAnimID)) { 69 targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); 70 targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); 71 } 72 73 if (o->header.gfx.animInfo.animID != targetAnimID) { 74 o->header.gfx.animInfo.animID = targetAnimID; 75 o->header.gfx.animInfo.curAnim = targetAnim; 76 o->header.gfx.animInfo.animAccel = 0; 77 o->header.gfx.animInfo.animYTrans = m->unkB0; 78 79 if (targetAnim->flags & ANIM_FLAG_2) { 80 o->header.gfx.animInfo.animFrame = targetAnim->startFrame; 81 } else { 82 if (targetAnim->flags & ANIM_FLAG_BACKWARD) { 83 o->header.gfx.animInfo.animFrame = targetAnim->startFrame + 1; 84 } else { 85 o->header.gfx.animInfo.animFrame = targetAnim->startFrame - 1; 86 } 87 } 88 } 89 90 return o->header.gfx.animInfo.animFrame; 91 } 92 93 /** 94 * Sets Mario's animation where the animation is sped up or 95 * slowed down via acceleration. 96 */ 97 s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) { 98 struct Object *o = m->marioObj; 99 struct Animation *targetAnim = m->animList->bufTarget; 100 101 if (load_patchable_table(m->animList, targetAnimID)) { 102 targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); 103 targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); 104 } 105 106 if (o->header.gfx.animInfo.animID != targetAnimID) { 107 o->header.gfx.animInfo.animID = targetAnimID; 108 o->header.gfx.animInfo.curAnim = targetAnim; 109 o->header.gfx.animInfo.animYTrans = m->unkB0; 110 111 if (targetAnim->flags & ANIM_FLAG_2) { 112 o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10); 113 } else { 114 if (targetAnim->flags & ANIM_FLAG_BACKWARD) { 115 o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) + accel; 116 } else { 117 o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) - accel; 118 } 119 } 120 121 o->header.gfx.animInfo.animFrame = (o->header.gfx.animInfo.animFrameAccelAssist >> 0x10); 122 } 123 124 o->header.gfx.animInfo.animAccel = accel; 125 126 return o->header.gfx.animInfo.animFrame; 127 } 128 129 /** 130 * Sets the animation to a specific "next" frame from the frame given. 131 */ 132 void set_anim_to_frame(struct MarioState *m, s16 animFrame) { 133 struct AnimInfo *animInfo = &m->marioObj->header.gfx.animInfo; 134 struct Animation *curAnim = animInfo->curAnim; 135 136 if (animInfo->animAccel != 0) { 137 if (curAnim->flags & ANIM_FLAG_BACKWARD) { 138 animInfo->animFrameAccelAssist = (animFrame << 0x10) + animInfo->animAccel; 139 } else { 140 animInfo->animFrameAccelAssist = (animFrame << 0x10) - animInfo->animAccel; 141 } 142 } else { 143 if (curAnim->flags & ANIM_FLAG_BACKWARD) { 144 animInfo->animFrame = animFrame + 1; 145 } else { 146 animInfo->animFrame = animFrame - 1; 147 } 148 } 149 } 150 151 s32 is_anim_past_frame(struct MarioState *m, s16 animFrame) { 152 s32 isPastFrame; 153 s32 acceleratedFrame = animFrame << 0x10; 154 struct AnimInfo *animInfo = &m->marioObj->header.gfx.animInfo; 155 struct Animation *curAnim = animInfo->curAnim; 156 157 if (animInfo->animAccel != 0) { 158 if (curAnim->flags & ANIM_FLAG_BACKWARD) { 159 isPastFrame = 160 (animInfo->animFrameAccelAssist > acceleratedFrame) 161 && (acceleratedFrame >= (animInfo->animFrameAccelAssist - animInfo->animAccel)); 162 } else { 163 isPastFrame = 164 (animInfo->animFrameAccelAssist < acceleratedFrame) 165 && (acceleratedFrame <= (animInfo->animFrameAccelAssist + animInfo->animAccel)); 166 } 167 } else { 168 if (curAnim->flags & ANIM_FLAG_BACKWARD) { 169 isPastFrame = (animInfo->animFrame == (animFrame + 1)); 170 } else { 171 isPastFrame = ((animInfo->animFrame + 1) == animFrame); 172 } 173 } 174 175 return isPastFrame; 176 } 177 178 /** 179 * Rotates the animation's translation into the global coordinate system 180 * and returns the animation's flags. 181 */ 182 s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s translation) { 183 f32 dx; 184 f32 dz; 185 186 struct Animation *curAnim = (void *) obj->header.gfx.animInfo.curAnim; 187 s16 animFrame = geo_update_animation_frame(&obj->header.gfx.animInfo, NULL); 188 u16 *animIndex = segmented_to_virtual((void *) curAnim->index); 189 s16 *animValues = segmented_to_virtual((void *) curAnim->values); 190 191 f32 s = (f32) sins(yaw); 192 f32 c = (f32) coss(yaw); 193 194 dx = *(animValues + (retrieve_animation_index(animFrame, &animIndex))) / 4.0f; 195 translation[1] = *(animValues + (retrieve_animation_index(animFrame, &animIndex))) / 4.0f; 196 dz = *(animValues + (retrieve_animation_index(animFrame, &animIndex))) / 4.0f; 197 198 translation[0] = (dx * c) + (dz * s); 199 translation[2] = (-dx * s) + (dz * c); 200 201 return curAnim->flags; 202 } 203 204 /** 205 * Updates Mario's position from his animation's translation. 206 */ 207 void update_mario_pos_for_anim(struct MarioState *m) { 208 Vec3s translation; 209 s16 flags; 210 211 flags = find_mario_anim_flags_and_translation(m->marioObj, m->faceAngle[1], translation); 212 213 if (flags & (ANIM_FLAG_HOR_TRANS | ANIM_FLAG_6)) { 214 m->pos[0] += (f32) translation[0]; 215 m->pos[2] += (f32) translation[2]; 216 } 217 218 if (flags & (ANIM_FLAG_VERT_TRANS | ANIM_FLAG_6)) { 219 m->pos[1] += (f32) translation[1]; 220 } 221 } 222 223 /** 224 * Finds the vertical translation from Mario's animation. 225 */ 226 s16 return_mario_anim_y_translation(struct MarioState *m) { 227 Vec3s translation; 228 find_mario_anim_flags_and_translation(m->marioObj, 0, translation); 229 230 return translation[1]; 231 } 232 233 /************************************************** 234 * AUDIO * 235 **************************************************/ 236 237 /** 238 * Plays a sound if if Mario doesn't have the flag being checked. 239 */ 240 void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) { 241 if (!(m->flags & flags)) { 242 play_sound(soundBits, m->marioObj->header.gfx.cameraToObject); 243 m->flags |= flags; 244 } 245 } 246 247 /** 248 * Plays a jump sound if one has not been played since the last action change. 249 */ 250 void play_mario_jump_sound(struct MarioState *m) { 251 if (!(m->flags & MARIO_MARIO_SOUND_PLAYED)) { 252 #ifndef VERSION_JP 253 if (m->action == ACT_TRIPLE_JUMP) { 254 play_sound(SOUND_MARIO_YAHOO_WAHA_YIPPEE + ((gAudioRandom % 5) << 16), 255 m->marioObj->header.gfx.cameraToObject); 256 } else { 257 #endif 258 play_sound(SOUND_MARIO_YAH_WAH_HOO + ((gAudioRandom % 3) << 16), 259 m->marioObj->header.gfx.cameraToObject); 260 #ifndef VERSION_JP 261 } 262 #endif 263 m->flags |= MARIO_MARIO_SOUND_PLAYED; 264 } 265 } 266 267 /** 268 * Adjusts the volume/pitch of sounds from Mario's speed. 269 */ 270 void adjust_sound_for_speed(struct MarioState *m) { 271 s32 absForwardVel = (m->forwardVel > 0.0f) ? m->forwardVel : -m->forwardVel; 272 set_sound_moving_speed(SOUND_BANK_MOVING, (absForwardVel > 100) ? 100 : absForwardVel); 273 } 274 275 /** 276 * Spawns particles if the step sound says to, then either plays a step sound or relevant other sound. 277 */ 278 void play_sound_and_spawn_particles(struct MarioState *m, u32 soundBits, u32 waveParticleType) { 279 if (m->terrainSoundAddend == (SOUND_TERRAIN_WATER << 16)) { 280 if (waveParticleType != 0) { 281 m->particleFlags |= PARTICLE_SHALLOW_WATER_SPLASH; 282 } else { 283 m->particleFlags |= PARTICLE_SHALLOW_WATER_WAVE; 284 } 285 } else { 286 if (m->terrainSoundAddend == (SOUND_TERRAIN_SAND << 16)) { 287 m->particleFlags |= PARTICLE_DIRT; 288 } else if (m->terrainSoundAddend == (SOUND_TERRAIN_SNOW << 16)) { 289 m->particleFlags |= PARTICLE_SNOW; 290 } 291 } 292 293 if ((m->flags & MARIO_METAL_CAP) || soundBits == SOUND_ACTION_UNSTUCK_FROM_GROUND 294 || soundBits == SOUND_MARIO_PUNCH_HOO) { 295 play_sound(soundBits, m->marioObj->header.gfx.cameraToObject); 296 } else { 297 play_sound(m->terrainSoundAddend + soundBits, m->marioObj->header.gfx.cameraToObject); 298 } 299 } 300 301 /** 302 * Plays an environmental sound if one has not been played since the last action change. 303 */ 304 void play_mario_action_sound(struct MarioState *m, u32 soundBits, u32 waveParticleType) { 305 if (!(m->flags & MARIO_ACTION_SOUND_PLAYED)) { 306 play_sound_and_spawn_particles(m, soundBits, waveParticleType); 307 m->flags |= MARIO_ACTION_SOUND_PLAYED; 308 } 309 } 310 311 /** 312 * Plays a landing sound, accounting for metal cap. 313 */ 314 void play_mario_landing_sound(struct MarioState *m, u32 soundBits) { 315 play_sound_and_spawn_particles( 316 m, (m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_LANDING : soundBits, 1); 317 } 318 319 /** 320 * Plays a landing sound, accounting for metal cap. Unlike play_mario_landing_sound, 321 * this function uses play_mario_action_sound, making sure the sound is only 322 * played once per action. 323 */ 324 void play_mario_landing_sound_once(struct MarioState *m, u32 soundBits) { 325 play_mario_action_sound( 326 m, (m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_LANDING : soundBits, 1); 327 } 328 329 /** 330 * Plays a heavy landing (ground pound, etc.) sound, accounting for metal cap. 331 */ 332 void play_mario_heavy_landing_sound(struct MarioState *m, u32 soundBits) { 333 play_sound_and_spawn_particles( 334 m, (m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_HEAVY_LANDING : soundBits, 1); 335 } 336 337 /** 338 * Plays a heavy landing (ground pound, etc.) sound, accounting for metal cap. 339 * Unlike play_mario_heavy_landing_sound, this function uses play_mario_action_sound, 340 * making sure the sound is only played once per action. 341 */ 342 void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits) { 343 play_mario_action_sound( 344 m, (m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_HEAVY_LANDING : soundBits, 1); 345 } 346 347 /** 348 * Plays action and Mario sounds relevant to what was passed into the function. 349 */ 350 void play_mario_sound(struct MarioState *m, s32 actionSound, s32 marioSound) { 351 if (actionSound == SOUND_ACTION_TERRAIN_JUMP) { 352 play_mario_action_sound(m, (m->flags & MARIO_METAL_CAP) ? (s32) SOUND_ACTION_METAL_JUMP 353 : (s32) SOUND_ACTION_TERRAIN_JUMP, 1); 354 } else { 355 play_sound_if_no_flag(m, actionSound, MARIO_ACTION_SOUND_PLAYED); 356 } 357 358 if (marioSound == 0) { 359 play_mario_jump_sound(m); 360 } 361 362 if (marioSound != -1) { 363 play_sound_if_no_flag(m, marioSound, MARIO_MARIO_SOUND_PLAYED); 364 } 365 } 366 367 /************************************************** 368 * ACTIONS * 369 **************************************************/ 370 371 /** 372 * Sets Mario's other velocities from his forward speed. 373 */ 374 void mario_set_forward_vel(struct MarioState *m, f32 forwardVel) { 375 m->forwardVel = forwardVel; 376 377 m->slideVelX = sins(m->faceAngle[1]) * m->forwardVel; 378 m->slideVelZ = coss(m->faceAngle[1]) * m->forwardVel; 379 380 m->vel[0] = (f32) m->slideVelX; 381 m->vel[2] = (f32) m->slideVelZ; 382 } 383 384 /** 385 * Returns the slipperiness class of Mario's floor. 386 */ 387 s32 mario_get_floor_class(struct MarioState *m) { 388 s32 floorClass; 389 390 // The slide terrain type defaults to slide slipperiness. 391 // This doesn't matter too much since normally the slide terrain 392 // is checked for anyways. 393 if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE) { 394 floorClass = SURFACE_CLASS_VERY_SLIPPERY; 395 } else { 396 floorClass = SURFACE_CLASS_DEFAULT; 397 } 398 399 if (m->floor != NULL) { 400 switch (m->floor->type) { 401 case SURFACE_NOT_SLIPPERY: 402 case SURFACE_HARD_NOT_SLIPPERY: 403 case SURFACE_SWITCH: 404 floorClass = SURFACE_CLASS_NOT_SLIPPERY; 405 break; 406 407 case SURFACE_SLIPPERY: 408 case SURFACE_NOISE_SLIPPERY: 409 case SURFACE_HARD_SLIPPERY: 410 case SURFACE_NO_CAM_COL_SLIPPERY: 411 floorClass = SURFACE_CLASS_SLIPPERY; 412 break; 413 414 case SURFACE_VERY_SLIPPERY: 415 case SURFACE_ICE: 416 case SURFACE_HARD_VERY_SLIPPERY: 417 case SURFACE_NOISE_VERY_SLIPPERY_73: 418 case SURFACE_NOISE_VERY_SLIPPERY_74: 419 case SURFACE_NOISE_VERY_SLIPPERY: 420 case SURFACE_NO_CAM_COL_VERY_SLIPPERY: 421 floorClass = SURFACE_CLASS_VERY_SLIPPERY; 422 break; 423 } 424 } 425 426 // Crawling allows Mario to not slide on certain steeper surfaces. 427 if (m->action == ACT_CRAWLING && m->floor->normal.y > 0.5f && floorClass == SURFACE_CLASS_DEFAULT) { 428 floorClass = SURFACE_CLASS_NOT_SLIPPERY; 429 } 430 431 return floorClass; 432 } 433 434 // clang-format off 435 s8 sTerrainSounds[7][6] = { 436 // default, hard, slippery, 437 // very slippery, noisy default, noisy slippery 438 { SOUND_TERRAIN_DEFAULT, SOUND_TERRAIN_STONE, SOUND_TERRAIN_GRASS, 439 SOUND_TERRAIN_GRASS, SOUND_TERRAIN_GRASS, SOUND_TERRAIN_DEFAULT }, // TERRAIN_GRASS 440 { SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE, 441 SOUND_TERRAIN_STONE, SOUND_TERRAIN_GRASS, SOUND_TERRAIN_GRASS }, // TERRAIN_STONE 442 { SOUND_TERRAIN_SNOW, SOUND_TERRAIN_ICE, SOUND_TERRAIN_SNOW, 443 SOUND_TERRAIN_ICE, SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE }, // TERRAIN_SNOW 444 { SOUND_TERRAIN_SAND, SOUND_TERRAIN_STONE, SOUND_TERRAIN_SAND, 445 SOUND_TERRAIN_SAND, SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE }, // TERRAIN_SAND 446 { SOUND_TERRAIN_SPOOKY, SOUND_TERRAIN_SPOOKY, SOUND_TERRAIN_SPOOKY, 447 SOUND_TERRAIN_SPOOKY, SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE }, // TERRAIN_SPOOKY 448 { SOUND_TERRAIN_DEFAULT, SOUND_TERRAIN_STONE, SOUND_TERRAIN_GRASS, 449 SOUND_TERRAIN_ICE, SOUND_TERRAIN_STONE, SOUND_TERRAIN_ICE }, // TERRAIN_WATER 450 { SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE, SOUND_TERRAIN_STONE, 451 SOUND_TERRAIN_STONE, SOUND_TERRAIN_ICE, SOUND_TERRAIN_ICE }, // TERRAIN_SLIDE 452 }; 453 // clang-format on 454 455 /** 456 * Computes a value that should be added to terrain sounds before playing them. 457 * This depends on surfaces and terrain. 458 */ 459 u32 mario_get_terrain_sound_addend(struct MarioState *m) { 460 s16 floorSoundType; 461 s16 terrainType = m->area->terrainType & TERRAIN_MASK; 462 s32 ret = SOUND_TERRAIN_DEFAULT << 16; 463 s32 floorType; 464 465 if (m->floor != NULL) { 466 floorType = m->floor->type; 467 468 if ((gCurrLevelNum != LEVEL_LLL) && (m->floorHeight < (m->waterLevel - 10))) { 469 // Water terrain sound, excluding LLL since it uses water in the volcano. 470 ret = SOUND_TERRAIN_WATER << 16; 471 } else if (SURFACE_IS_QUICKSAND(floorType)) { 472 ret = SOUND_TERRAIN_SAND << 16; 473 } else { 474 switch (floorType) { 475 default: 476 floorSoundType = 0; 477 break; 478 479 case SURFACE_NOT_SLIPPERY: 480 case SURFACE_HARD: 481 case SURFACE_HARD_NOT_SLIPPERY: 482 case SURFACE_SWITCH: 483 floorSoundType = 1; 484 break; 485 486 case SURFACE_SLIPPERY: 487 case SURFACE_HARD_SLIPPERY: 488 case SURFACE_NO_CAM_COL_SLIPPERY: 489 floorSoundType = 2; 490 break; 491 492 case SURFACE_VERY_SLIPPERY: 493 case SURFACE_ICE: 494 case SURFACE_HARD_VERY_SLIPPERY: 495 case SURFACE_NOISE_VERY_SLIPPERY_73: 496 case SURFACE_NOISE_VERY_SLIPPERY_74: 497 case SURFACE_NOISE_VERY_SLIPPERY: 498 case SURFACE_NO_CAM_COL_VERY_SLIPPERY: 499 floorSoundType = 3; 500 break; 501 502 case SURFACE_NOISE_DEFAULT: 503 floorSoundType = 4; 504 break; 505 506 case SURFACE_NOISE_SLIPPERY: 507 floorSoundType = 5; 508 break; 509 } 510 511 ret = sTerrainSounds[terrainType][floorSoundType] << 16; 512 } 513 } 514 515 return ret; 516 } 517 518 /** 519 * Collides with walls and returns the most recent wall. 520 */ 521 struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius) { 522 struct WallCollisionData collisionData; 523 struct Surface *wall = NULL; 524 525 collisionData.x = pos[0]; 526 collisionData.y = pos[1]; 527 collisionData.z = pos[2]; 528 collisionData.radius = radius; 529 collisionData.offsetY = offset; 530 531 if (find_wall_collisions(&collisionData)) { 532 wall = collisionData.walls[collisionData.numWalls - 1]; 533 } 534 535 pos[0] = collisionData.x; 536 pos[1] = collisionData.y; 537 pos[2] = collisionData.z; 538 539 // This only returns the most recent wall and can also return NULL 540 // there are no wall collisions. 541 return wall; 542 } 543 544 /** 545 * Finds the ceiling from a vec3f horizontally and a height (with 80 vertical buffer). 546 */ 547 f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) { 548 UNUSED u8 filler[4]; 549 550 return find_ceil(pos[0], height + 80.0f, pos[2], ceil); 551 } 552 553 /** 554 * Determines if Mario is facing "downhill." 555 */ 556 s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) { 557 s16 faceAngleYaw = m->faceAngle[1]; 558 559 // This is never used in practice, as turnYaw is 560 // always passed as zero. 561 if (turnYaw && m->forwardVel < 0.0f) { 562 faceAngleYaw += 0x8000; 563 } 564 565 faceAngleYaw = m->floorAngle - faceAngleYaw; 566 567 return (-0x4000 < faceAngleYaw) && (faceAngleYaw < 0x4000); 568 } 569 570 /** 571 * Determines if a surface is slippery based on the surface class. 572 */ 573 u32 mario_floor_is_slippery(struct MarioState *m) { 574 f32 normY; 575 576 if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE 577 && m->floor->normal.y < 0.9998477f //~cos(1 deg) 578 ) { 579 return TRUE; 580 } 581 582 switch (mario_get_floor_class(m)) { 583 case SURFACE_VERY_SLIPPERY: 584 normY = 0.9848077f; //~cos(10 deg) 585 break; 586 587 case SURFACE_SLIPPERY: 588 normY = 0.9396926f; //~cos(20 deg) 589 break; 590 591 default: 592 normY = 0.7880108f; //~cos(38 deg) 593 break; 594 595 case SURFACE_NOT_SLIPPERY: 596 normY = 0.0f; 597 break; 598 } 599 600 return m->floor->normal.y <= normY; 601 } 602 603 /** 604 * Determines if a surface is a slope based on the surface class. 605 */ 606 s32 mario_floor_is_slope(struct MarioState *m) { 607 f32 normY; 608 609 if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE 610 && m->floor->normal.y < 0.9998477f) { // ~cos(1 deg) 611 return TRUE; 612 } 613 614 switch (mario_get_floor_class(m)) { 615 case SURFACE_VERY_SLIPPERY: 616 normY = 0.9961947f; // ~cos(5 deg) 617 break; 618 619 case SURFACE_SLIPPERY: 620 normY = 0.9848077f; // ~cos(10 deg) 621 break; 622 623 default: 624 normY = 0.9659258f; // ~cos(15 deg) 625 break; 626 627 case SURFACE_NOT_SLIPPERY: 628 normY = 0.9396926f; // ~cos(20 deg) 629 break; 630 } 631 632 return m->floor->normal.y <= normY; 633 } 634 635 /** 636 * Determines if a surface is steep based on the surface class. 637 */ 638 s32 mario_floor_is_steep(struct MarioState *m) { 639 f32 normY; 640 s32 result = FALSE; 641 642 // Interestingly, this function does not check for the 643 // slide terrain type. This means that steep behavior persists for 644 // non-slippery and slippery surfaces. 645 // This does not matter in vanilla game practice. 646 if (!mario_facing_downhill(m, FALSE)) { 647 switch (mario_get_floor_class(m)) { 648 case SURFACE_VERY_SLIPPERY: 649 normY = 0.9659258f; // ~cos(15 deg) 650 break; 651 652 case SURFACE_SLIPPERY: 653 normY = 0.9396926f; // ~cos(20 deg) 654 break; 655 656 default: 657 normY = 0.8660254f; // ~cos(30 deg) 658 break; 659 660 case SURFACE_NOT_SLIPPERY: 661 normY = 0.8660254f; // ~cos(30 deg) 662 break; 663 } 664 665 result = m->floor->normal.y <= normY; 666 } 667 668 return result; 669 } 670 671 /** 672 * Finds the floor height relative from Mario given polar displacement. 673 */ 674 f32 find_floor_height_relative_polar(struct MarioState *m, s16 angleFromMario, f32 distFromMario) { 675 struct Surface *floor; 676 f32 floorY; 677 678 f32 y = sins(m->faceAngle[1] + angleFromMario) * distFromMario; 679 f32 x = coss(m->faceAngle[1] + angleFromMario) * distFromMario; 680 681 floorY = find_floor(m->pos[0] + y, m->pos[1] + 100.0f, m->pos[2] + x, &floor); 682 683 return floorY; 684 } 685 686 /** 687 * Returns the slope of the floor based off points around Mario. 688 */ 689 s16 find_floor_slope(struct MarioState *m, s16 yawOffset) { 690 struct Surface *floor; 691 f32 forwardFloorY, backwardFloorY; 692 f32 forwardYDelta, backwardYDelta; 693 s16 result; 694 695 f32 x = sins(m->faceAngle[1] + yawOffset) * 5.0f; 696 f32 z = coss(m->faceAngle[1] + yawOffset) * 5.0f; 697 698 forwardFloorY = find_floor(m->pos[0] + x, m->pos[1] + 100.0f, m->pos[2] + z, &floor); 699 backwardFloorY = find_floor(m->pos[0] - x, m->pos[1] + 100.0f, m->pos[2] - z, &floor); 700 701 //! If Mario is near OOB, these floorY's can sometimes be -11000. 702 // This will cause these to be off and give improper slopes. 703 forwardYDelta = forwardFloorY - m->pos[1]; 704 backwardYDelta = m->pos[1] - backwardFloorY; 705 706 if (forwardYDelta * forwardYDelta < backwardYDelta * backwardYDelta) { 707 result = atan2s(5.0f, forwardYDelta); 708 } else { 709 result = atan2s(5.0f, backwardYDelta); 710 } 711 712 return result; 713 } 714 715 /** 716 * Adjusts Mario's camera and sound based on his action status. 717 */ 718 void update_mario_sound_and_camera(struct MarioState *m) { 719 u32 action = m->action; 720 s32 camPreset = m->area->camera->mode; 721 722 if (action == ACT_FIRST_PERSON) { 723 raise_background_noise(2); 724 gCameraMovementFlags &= ~CAM_MOVE_C_UP_MODE; 725 // Go back to the last camera mode 726 set_camera_mode(m->area->camera, -1, 1); 727 } else if (action == ACT_SLEEPING) { 728 raise_background_noise(2); 729 } 730 731 if (!(action & (ACT_FLAG_SWIMMING | ACT_FLAG_METAL_WATER))) { 732 if (camPreset == CAMERA_MODE_BEHIND_MARIO || camPreset == CAMERA_MODE_WATER_SURFACE) { 733 set_camera_mode(m->area->camera, m->area->camera->defMode, 1); 734 } 735 } 736 } 737 738 /** 739 * Transitions Mario to a steep jump action. 740 */ 741 void set_steep_jump_action(struct MarioState *m) { 742 m->marioObj->oMarioSteepJumpYaw = m->faceAngle[1]; 743 744 if (m->forwardVel > 0.0f) { 745 //! ((s16)0x8000) has undefined behavior. Therefore, this downcast has 746 // undefined behavior if m->floorAngle >= 0. 747 s16 angleTemp = m->floorAngle + 0x8000; 748 s16 faceAngleTemp = m->faceAngle[1] - angleTemp; 749 750 f32 y = sins(faceAngleTemp) * m->forwardVel; 751 f32 x = coss(faceAngleTemp) * m->forwardVel * 0.75f; 752 753 m->forwardVel = sqrtf(y * y + x * x); 754 m->faceAngle[1] = atan2s(x, y) + angleTemp; 755 } 756 757 drop_and_set_mario_action(m, ACT_STEEP_JUMP, 0); 758 } 759 760 /** 761 * Sets Mario's vertical speed from his forward speed. 762 */ 763 static void set_mario_y_vel_based_on_fspeed(struct MarioState *m, f32 initialVelY, f32 multiplier) { 764 // get_additive_y_vel_for_jumps is always 0 and a stubbed function. 765 // It was likely trampoline related based on code location. 766 m->vel[1] = initialVelY + get_additive_y_vel_for_jumps() + m->forwardVel * multiplier; 767 768 if (m->squishTimer != 0 || m->quicksandDepth > 1.0f) { 769 m->vel[1] *= 0.5f; 770 } 771 } 772 773 /** 774 * Transitions for a variety of airborne actions. 775 */ 776 static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actionArg) { 777 f32 forwardVel; 778 779 if ((m->squishTimer != 0 || m->quicksandDepth >= 1.0f) 780 && (action == ACT_DOUBLE_JUMP || action == ACT_TWIRLING)) { 781 action = ACT_JUMP; 782 } 783 784 switch (action) { 785 case ACT_DOUBLE_JUMP: 786 set_mario_y_vel_based_on_fspeed(m, 52.0f, 0.25f); 787 m->forwardVel *= 0.8f; 788 break; 789 790 case ACT_BACKFLIP: 791 m->marioObj->header.gfx.animInfo.animID = -1; 792 m->forwardVel = -16.0f; 793 set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f); 794 break; 795 796 case ACT_TRIPLE_JUMP: 797 set_mario_y_vel_based_on_fspeed(m, 69.0f, 0.0f); 798 m->forwardVel *= 0.8f; 799 break; 800 801 case ACT_FLYING_TRIPLE_JUMP: 802 set_mario_y_vel_based_on_fspeed(m, 82.0f, 0.0f); 803 break; 804 805 case ACT_WATER_JUMP: 806 case ACT_HOLD_WATER_JUMP: 807 if (actionArg == 0) { 808 set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.0f); 809 } 810 break; 811 812 case ACT_BURNING_JUMP: 813 m->vel[1] = 31.5f; 814 m->forwardVel = 8.0f; 815 break; 816 817 case ACT_RIDING_SHELL_JUMP: 818 set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.25f); 819 break; 820 821 case ACT_JUMP: 822 case ACT_HOLD_JUMP: 823 m->marioObj->header.gfx.animInfo.animID = -1; 824 set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.25f); 825 m->forwardVel *= 0.8f; 826 break; 827 828 case ACT_WALL_KICK_AIR: 829 case ACT_TOP_OF_POLE_JUMP: 830 set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f); 831 if (m->forwardVel < 24.0f) { 832 m->forwardVel = 24.0f; 833 } 834 m->wallKickTimer = 0; 835 break; 836 837 case ACT_SIDE_FLIP: 838 set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f); 839 m->forwardVel = 8.0f; 840 m->faceAngle[1] = m->intendedYaw; 841 break; 842 843 case ACT_STEEP_JUMP: 844 m->marioObj->header.gfx.animInfo.animID = -1; 845 set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.25f); 846 m->faceAngle[0] = -0x2000; 847 break; 848 849 case ACT_LAVA_BOOST: 850 m->vel[1] = 84.0f; 851 if (actionArg == 0) { 852 m->forwardVel = 0.0f; 853 } 854 break; 855 856 case ACT_DIVE: 857 if ((forwardVel = m->forwardVel + 15.0f) > 48.0f) { 858 forwardVel = 48.0f; 859 } 860 mario_set_forward_vel(m, forwardVel); 861 break; 862 863 case ACT_LONG_JUMP: 864 m->marioObj->header.gfx.animInfo.animID = -1; 865 set_mario_y_vel_based_on_fspeed(m, 30.0f, 0.0f); 866 m->marioObj->oMarioLongJumpIsSlow = m->forwardVel > 16.0f ? FALSE : TRUE; 867 868 //! (BLJ's) This properly handles long jumps from getting forward speed with 869 // too much velocity, but misses backwards longs allowing high negative speeds. 870 if ((m->forwardVel *= 1.5f) > 48.0f) { 871 m->forwardVel = 48.0f; 872 } 873 break; 874 875 case ACT_SLIDE_KICK: 876 m->vel[1] = 12.0f; 877 if (m->forwardVel < 32.0f) { 878 m->forwardVel = 32.0f; 879 } 880 break; 881 882 case ACT_JUMP_KICK: 883 m->vel[1] = 20.0f; 884 break; 885 } 886 887 m->peakHeight = m->pos[1]; 888 m->flags |= MARIO_UNKNOWN_08; 889 890 return action; 891 } 892 893 /** 894 * Transitions for a variety of moving actions. 895 */ 896 static u32 set_mario_action_moving(struct MarioState *m, u32 action, UNUSED u32 actionArg) { 897 s16 floorClass = mario_get_floor_class(m); 898 f32 forwardVel = m->forwardVel; 899 f32 mag = min(m->intendedMag, 8.0f); 900 901 switch (action) { 902 case ACT_WALKING: 903 if (floorClass != SURFACE_CLASS_VERY_SLIPPERY) { 904 if (0.0f <= forwardVel && forwardVel < mag) { 905 m->forwardVel = mag; 906 } 907 } 908 909 m->marioObj->oMarioWalkingPitch = 0; 910 break; 911 912 case ACT_HOLD_WALKING: 913 if (0.0f <= forwardVel && forwardVel < mag / 2.0f) { 914 m->forwardVel = mag / 2.0f; 915 } 916 break; 917 918 case ACT_BEGIN_SLIDING: 919 if (mario_facing_downhill(m, FALSE)) { 920 action = ACT_BUTT_SLIDE; 921 } else { 922 action = ACT_STOMACH_SLIDE; 923 } 924 break; 925 926 case ACT_HOLD_BEGIN_SLIDING: 927 if (mario_facing_downhill(m, FALSE)) { 928 action = ACT_HOLD_BUTT_SLIDE; 929 } else { 930 action = ACT_HOLD_STOMACH_SLIDE; 931 } 932 break; 933 } 934 935 return action; 936 } 937 938 /** 939 * Transition for certain submerged actions, which is actually just the metal jump actions. 940 */ 941 static u32 set_mario_action_submerged(struct MarioState *m, u32 action, UNUSED u32 actionArg) { 942 if (action == ACT_METAL_WATER_JUMP || action == ACT_HOLD_METAL_WATER_JUMP) { 943 m->vel[1] = 32.0f; 944 } 945 946 return action; 947 } 948 949 /** 950 * Transitions for a variety of cutscene actions. 951 */ 952 static u32 set_mario_action_cutscene(struct MarioState *m, u32 action, UNUSED u32 actionArg) { 953 switch (action) { 954 case ACT_EMERGE_FROM_PIPE: 955 m->vel[1] = 52.0f; 956 break; 957 958 case ACT_FALL_AFTER_STAR_GRAB: 959 mario_set_forward_vel(m, 0.0f); 960 break; 961 962 case ACT_SPAWN_SPIN_AIRBORNE: 963 mario_set_forward_vel(m, 2.0f); 964 break; 965 966 case ACT_SPECIAL_EXIT_AIRBORNE: 967 case ACT_SPECIAL_DEATH_EXIT: 968 m->vel[1] = 64.0f; 969 break; 970 } 971 972 return action; 973 } 974 975 /** 976 * Puts Mario into a given action, putting Mario through the appropriate 977 * specific function if needed. 978 */ 979 u32 set_mario_action(struct MarioState *m, u32 action, u32 actionArg) { 980 switch (action & ACT_GROUP_MASK) { 981 case ACT_GROUP_MOVING: 982 action = set_mario_action_moving(m, action, actionArg); 983 break; 984 985 case ACT_GROUP_AIRBORNE: 986 action = set_mario_action_airborne(m, action, actionArg); 987 break; 988 989 case ACT_GROUP_SUBMERGED: 990 action = set_mario_action_submerged(m, action, actionArg); 991 break; 992 993 case ACT_GROUP_CUTSCENE: 994 action = set_mario_action_cutscene(m, action, actionArg); 995 break; 996 } 997 998 // Resets the sound played flags, meaning Mario can play those sound types again. 999 m->flags &= ~(MARIO_ACTION_SOUND_PLAYED | MARIO_MARIO_SOUND_PLAYED); 1000 1001 if (!(m->action & ACT_FLAG_AIR)) { 1002 m->flags &= ~MARIO_UNKNOWN_18; 1003 } 1004 1005 // Initialize the action information. 1006 m->prevAction = m->action; 1007 m->action = action; 1008 m->actionArg = actionArg; 1009 m->actionState = 0; 1010 m->actionTimer = 0; 1011 1012 return TRUE; 1013 } 1014 1015 /** 1016 * Puts Mario into a specific jumping action from a landing action. 1017 */ 1018 s32 set_jump_from_landing(struct MarioState *m) { 1019 if (m->quicksandDepth >= 11.0f) { 1020 if (m->heldObj == NULL) { 1021 return set_mario_action(m, ACT_QUICKSAND_JUMP_LAND, 0); 1022 } else { 1023 return set_mario_action(m, ACT_HOLD_QUICKSAND_JUMP_LAND, 0); 1024 } 1025 } 1026 1027 if (mario_floor_is_steep(m)) { 1028 set_steep_jump_action(m); 1029 } else { 1030 if ((m->doubleJumpTimer == 0) || (m->squishTimer != 0)) { 1031 set_mario_action(m, ACT_JUMP, 0); 1032 } else { 1033 switch (m->prevAction) { 1034 case ACT_JUMP_LAND: 1035 set_mario_action(m, ACT_DOUBLE_JUMP, 0); 1036 break; 1037 1038 case ACT_FREEFALL_LAND: 1039 set_mario_action(m, ACT_DOUBLE_JUMP, 0); 1040 break; 1041 1042 case ACT_SIDE_FLIP_LAND_STOP: 1043 set_mario_action(m, ACT_DOUBLE_JUMP, 0); 1044 break; 1045 1046 case ACT_DOUBLE_JUMP_LAND: 1047 // If Mario has a wing cap, he ignores the typical speed 1048 // requirement for a triple jump. 1049 if (m->flags & MARIO_WING_CAP) { 1050 set_mario_action(m, ACT_FLYING_TRIPLE_JUMP, 0); 1051 } else if (m->forwardVel > 20.0f) { 1052 set_mario_action(m, ACT_TRIPLE_JUMP, 0); 1053 } else { 1054 set_mario_action(m, ACT_JUMP, 0); 1055 } 1056 break; 1057 1058 default: 1059 set_mario_action(m, ACT_JUMP, 0); 1060 break; 1061 } 1062 } 1063 } 1064 1065 m->doubleJumpTimer = 0; 1066 1067 return TRUE; 1068 } 1069 1070 /** 1071 * Puts Mario in a given action, as long as it is not overruled by 1072 * either a quicksand or steep jump. 1073 */ 1074 s32 set_jumping_action(struct MarioState *m, u32 action, u32 actionArg) { 1075 UNUSED u32 currAction = m->action; 1076 1077 if (m->quicksandDepth >= 11.0f) { 1078 // Checks whether Mario is holding an object or not. 1079 if (m->heldObj == NULL) { 1080 return set_mario_action(m, ACT_QUICKSAND_JUMP_LAND, 0); 1081 } else { 1082 return set_mario_action(m, ACT_HOLD_QUICKSAND_JUMP_LAND, 0); 1083 } 1084 } 1085 1086 if (mario_floor_is_steep(m)) { 1087 set_steep_jump_action(m); 1088 } else { 1089 set_mario_action(m, action, actionArg); 1090 } 1091 1092 return TRUE; 1093 } 1094 1095 /** 1096 * Drop anything Mario is holding and set a new action. 1097 */ 1098 s32 drop_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg) { 1099 mario_stop_riding_and_holding(m); 1100 1101 return set_mario_action(m, action, actionArg); 1102 } 1103 1104 /** 1105 * Increment Mario's hurt counter and set a new action. 1106 */ 1107 s32 hurt_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg, s16 hurtCounter) { 1108 m->hurtCounter = hurtCounter; 1109 1110 return set_mario_action(m, action, actionArg); 1111 } 1112 1113 /** 1114 * Checks a variety of inputs for common transitions between many different 1115 * actions. A common variant of the below function. 1116 */ 1117 s32 check_common_action_exits(struct MarioState *m) { 1118 if (m->input & INPUT_A_PRESSED) { 1119 return set_mario_action(m, ACT_JUMP, 0); 1120 } 1121 if (m->input & INPUT_OFF_FLOOR) { 1122 return set_mario_action(m, ACT_FREEFALL, 0); 1123 } 1124 if (m->input & INPUT_NONZERO_ANALOG) { 1125 return set_mario_action(m, ACT_WALKING, 0); 1126 } 1127 if (m->input & INPUT_ABOVE_SLIDE) { 1128 return set_mario_action(m, ACT_BEGIN_SLIDING, 0); 1129 } 1130 1131 return FALSE; 1132 } 1133 1134 /** 1135 * Checks a variety of inputs for common transitions between many different 1136 * object holding actions. A holding variant of the above function. 1137 */ 1138 s32 check_common_hold_action_exits(struct MarioState *m) { 1139 if (m->input & INPUT_A_PRESSED) { 1140 return set_mario_action(m, ACT_HOLD_JUMP, 0); 1141 } 1142 if (m->input & INPUT_OFF_FLOOR) { 1143 return set_mario_action(m, ACT_HOLD_FREEFALL, 0); 1144 } 1145 if (m->input & INPUT_NONZERO_ANALOG) { 1146 return set_mario_action(m, ACT_HOLD_WALKING, 0); 1147 } 1148 if (m->input & INPUT_ABOVE_SLIDE) { 1149 return set_mario_action(m, ACT_HOLD_BEGIN_SLIDING, 0); 1150 } 1151 1152 return FALSE; 1153 } 1154 1155 /** 1156 * Transitions Mario from a submerged action to a walking action. 1157 */ 1158 s32 transition_submerged_to_walking(struct MarioState *m) { 1159 set_camera_mode(m->area->camera, m->area->camera->defMode, 1); 1160 1161 vec3s_set(m->angleVel, 0, 0, 0); 1162 1163 if (m->heldObj == NULL) { 1164 return set_mario_action(m, ACT_WALKING, 0); 1165 } else { 1166 return set_mario_action(m, ACT_HOLD_WALKING, 0); 1167 } 1168 } 1169 1170 /** 1171 * This is the transition function typically for entering a submerged action for a 1172 * non-submerged action. This also applies the water surface camera preset. 1173 */ 1174 s32 set_water_plunge_action(struct MarioState *m) { 1175 m->forwardVel = m->forwardVel / 4.0f; 1176 m->vel[1] = m->vel[1] / 2.0f; 1177 1178 m->pos[1] = m->waterLevel - 100; 1179 1180 m->faceAngle[2] = 0; 1181 1182 vec3s_set(m->angleVel, 0, 0, 0); 1183 1184 if (!(m->action & ACT_FLAG_DIVING)) { 1185 m->faceAngle[0] = 0; 1186 } 1187 1188 if (m->area->camera->mode != CAMERA_MODE_WATER_SURFACE) { 1189 set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1); 1190 } 1191 1192 return set_mario_action(m, ACT_WATER_PLUNGE, 0); 1193 } 1194 1195 /** 1196 * These are the scaling values for the x and z axis for Mario 1197 * when he is close to unsquishing. 1198 */ 1199 u8 sSquishScaleOverTime[16] = { 0x46, 0x32, 0x32, 0x3C, 0x46, 0x50, 0x50, 0x3C, 1200 0x28, 0x14, 0x14, 0x1E, 0x32, 0x3C, 0x3C, 0x28 }; 1201 1202 /** 1203 * Applies the squish to Mario's model via scaling. 1204 */ 1205 void squish_mario_model(struct MarioState *m) { 1206 if (m->squishTimer != 0xFF) { 1207 // If no longer squished, scale back to default. 1208 if (m->squishTimer == 0) { 1209 vec3f_set(m->marioObj->header.gfx.scale, 1.0f, 1.0f, 1.0f); 1210 } 1211 // If timer is less than 16, rubber-band Mario's size scale up and down. 1212 else if (m->squishTimer <= 16) { 1213 m->squishTimer -= 1; 1214 1215 m->marioObj->header.gfx.scale[1] = 1216 1.0f - ((sSquishScaleOverTime[15 - m->squishTimer] * 0.6f) / 100.0f); 1217 m->marioObj->header.gfx.scale[0] = 1218 ((sSquishScaleOverTime[15 - m->squishTimer] * 0.4f) / 100.0f) + 1.0f; 1219 1220 m->marioObj->header.gfx.scale[2] = m->marioObj->header.gfx.scale[0]; 1221 } else { 1222 m->squishTimer -= 1; 1223 1224 vec3f_set(m->marioObj->header.gfx.scale, 1.4f, 0.4f, 1.4f); 1225 } 1226 } 1227 } 1228 1229 /** 1230 * Debug function that prints floor normal, velocity, and action information. 1231 */ 1232 void debug_print_speed_action_normal(struct MarioState *m) { 1233 f32 steepness; 1234 f32 floor_nY; 1235 1236 if (gShowDebugText) { 1237 steepness = sqrtf( 1238 ((m->floor->normal.x * m->floor->normal.x) + (m->floor->normal.z * m->floor->normal.z))); 1239 floor_nY = m->floor->normal.y; 1240 1241 print_text_fmt_int(210, 88, "ANG %d", (atan2s(floor_nY, steepness) * 180.0f) / 32768.0f); 1242 1243 print_text_fmt_int(210, 72, "SPD %d", m->forwardVel); 1244 1245 // STA short for "status," the official action name via SMS map. 1246 print_text_fmt_int(210, 56, "STA %x", (m->action & ACT_ID_MASK)); 1247 } 1248 } 1249 1250 /** 1251 * Update the button inputs for Mario. 1252 */ 1253 void update_mario_button_inputs(struct MarioState *m) { 1254 if (m->controller->buttonPressed & A_BUTTON) { 1255 m->input |= INPUT_A_PRESSED; 1256 } 1257 1258 if (m->controller->buttonDown & A_BUTTON) { 1259 m->input |= INPUT_A_DOWN; 1260 } 1261 1262 // Don't update for these buttons if squished. 1263 if (m->squishTimer == 0) { 1264 if (m->controller->buttonPressed & B_BUTTON) { 1265 m->input |= INPUT_B_PRESSED; 1266 } 1267 1268 if (m->controller->buttonDown & Z_TRIG) { 1269 m->input |= INPUT_Z_DOWN; 1270 } 1271 1272 if (m->controller->buttonPressed & Z_TRIG) { 1273 m->input |= INPUT_Z_PRESSED; 1274 } 1275 } 1276 1277 if (m->input & INPUT_A_PRESSED) { 1278 m->framesSinceA = 0; 1279 } else if (m->framesSinceA < 0xFF) { 1280 m->framesSinceA++; 1281 } 1282 1283 if (m->input & INPUT_B_PRESSED) { 1284 m->framesSinceB = 0; 1285 } else if (m->framesSinceB < 0xFF) { 1286 m->framesSinceB++; 1287 } 1288 } 1289 1290 /** 1291 * Updates the joystick intended magnitude. 1292 */ 1293 void update_mario_joystick_inputs(struct MarioState *m) { 1294 struct Controller *controller = m->controller; 1295 f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f; 1296 1297 if (m->squishTimer == 0) { 1298 m->intendedMag = mag / 2.0f; 1299 } else { 1300 m->intendedMag = mag / 8.0f; 1301 } 1302 1303 if (m->intendedMag > 0.0f) { 1304 m->intendedYaw = atan2s(-controller->stickY, controller->stickX) + m->area->camera->yaw; 1305 m->input |= INPUT_NONZERO_ANALOG; 1306 } else { 1307 m->intendedYaw = m->faceAngle[1]; 1308 } 1309 } 1310 1311 /** 1312 * Resolves wall collisions, and updates a variety of inputs. 1313 */ 1314 void update_mario_geometry_inputs(struct MarioState *m) { 1315 f32 gasLevel; 1316 f32 ceilToFloorDist; 1317 1318 f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 60.0f, 50.0f); 1319 f32_find_wall_collision(&m->pos[0], &m->pos[1], &m->pos[2], 30.0f, 24.0f); 1320 1321 m->floorHeight = find_floor(m->pos[0], m->pos[1], m->pos[2], &m->floor); 1322 1323 // If Mario is OOB, move his position to his graphical position (which was not updated) 1324 // and check for the floor there. 1325 // This can cause errant behavior when combined with astral projection, 1326 // since the graphical position was not Mario's previous location. 1327 if (m->floor == NULL) { 1328 vec3f_copy(m->pos, m->marioObj->header.gfx.pos); 1329 m->floorHeight = find_floor(m->pos[0], m->pos[1], m->pos[2], &m->floor); 1330 } 1331 1332 m->ceilHeight = vec3f_find_ceil(m->pos, m->floorHeight, &m->ceil); 1333 gasLevel = find_poison_gas_level(m->pos[0], m->pos[2]); 1334 m->waterLevel = find_water_level(m->pos[0], m->pos[2]); 1335 1336 if (m->floor != NULL) { 1337 m->floorAngle = atan2s(m->floor->normal.z, m->floor->normal.x); 1338 m->terrainSoundAddend = mario_get_terrain_sound_addend(m); 1339 1340 if ((m->pos[1] > m->waterLevel - 40) && mario_floor_is_slippery(m)) { 1341 m->input |= INPUT_ABOVE_SLIDE; 1342 } 1343 1344 if ((m->floor->flags & SURFACE_FLAG_DYNAMIC) 1345 || (m->ceil && m->ceil->flags & SURFACE_FLAG_DYNAMIC)) { 1346 ceilToFloorDist = m->ceilHeight - m->floorHeight; 1347 1348 if ((0.0f <= ceilToFloorDist) && (ceilToFloorDist <= 150.0f)) { 1349 m->input |= INPUT_SQUISHED; 1350 } 1351 } 1352 1353 if (m->pos[1] > m->floorHeight + 100.0f) { 1354 m->input |= INPUT_OFF_FLOOR; 1355 } 1356 1357 if (m->pos[1] < (m->waterLevel - 10)) { 1358 m->input |= INPUT_IN_WATER; 1359 } 1360 1361 if (m->pos[1] < (gasLevel - 100.0f)) { 1362 m->input |= INPUT_IN_POISON_GAS; 1363 } 1364 1365 } else { 1366 level_trigger_warp(m, WARP_OP_DEATH); 1367 } 1368 } 1369 1370 /** 1371 * Handles Mario's input flags as well as a couple timers. 1372 */ 1373 void update_mario_inputs(struct MarioState *m) { 1374 m->particleFlags = 0; 1375 m->input = 0; 1376 m->collidedObjInteractTypes = m->marioObj->collidedObjInteractTypes; 1377 m->flags &= 0xFFFFFF; 1378 1379 update_mario_button_inputs(m); 1380 update_mario_joystick_inputs(m); 1381 update_mario_geometry_inputs(m); 1382 1383 debug_print_speed_action_normal(m); 1384 1385 if (gCameraMovementFlags & CAM_MOVE_C_UP_MODE) { 1386 if (m->action & ACT_FLAG_ALLOW_FIRST_PERSON) { 1387 m->input |= INPUT_FIRST_PERSON; 1388 } else { 1389 gCameraMovementFlags &= ~CAM_MOVE_C_UP_MODE; 1390 } 1391 } 1392 1393 if (!(m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED))) { 1394 m->input |= INPUT_UNKNOWN_5; 1395 } 1396 1397 // These 3 flags are defined by Bowser stomping attacks 1398 if (m->marioObj->oInteractStatus 1399 & (INT_STATUS_MARIO_STUNNED | INT_STATUS_MARIO_KNOCKBACK_DMG | INT_STATUS_MARIO_SHOCKWAVE)) { 1400 m->input |= INPUT_STOMPED; 1401 } 1402 1403 // This function is located near other unused trampoline functions, 1404 // perhaps logically grouped here with the timers. 1405 stub_mario_step_1(m); 1406 1407 if (m->wallKickTimer > 0) { 1408 m->wallKickTimer--; 1409 } 1410 1411 if (m->doubleJumpTimer > 0) { 1412 m->doubleJumpTimer--; 1413 } 1414 } 1415 1416 /** 1417 * Set's the camera preset for submerged action behaviors. 1418 */ 1419 void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) { 1420 f32 heightBelowWater; 1421 s16 camPreset; 1422 1423 if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_SUBMERGED) { 1424 heightBelowWater = (f32)(m->waterLevel - 80) - m->pos[1]; 1425 camPreset = m->area->camera->mode; 1426 1427 if (m->action & ACT_FLAG_METAL_WATER) { 1428 if (camPreset != CAMERA_MODE_CLOSE) { 1429 set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); 1430 } 1431 } else { 1432 if ((heightBelowWater > 800.0f) && (camPreset != CAMERA_MODE_BEHIND_MARIO)) { 1433 set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); 1434 } 1435 1436 if ((heightBelowWater < 400.0f) && (camPreset != CAMERA_MODE_WATER_SURFACE)) { 1437 set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1); 1438 } 1439 1440 // As long as Mario isn't drowning or at the top 1441 // of the water with his head out, spawn bubbles. 1442 if (!(m->action & ACT_FLAG_INTANGIBLE)) { 1443 if ((m->pos[1] < (f32)(m->waterLevel - 160)) || (m->faceAngle[0] < -0x800)) { 1444 m->particleFlags |= PARTICLE_BUBBLE; 1445 } 1446 } 1447 } 1448 } 1449 } 1450 1451 /** 1452 * Both increments and decrements Mario's HP. 1453 */ 1454 void update_mario_health(struct MarioState *m) { 1455 s32 terrainIsSnow; 1456 1457 if (m->health >= 0x100) { 1458 // When already healing or hurting Mario, Mario's HP is not changed any more here. 1459 if (((u32) m->healCounter | (u32) m->hurtCounter) == 0) { 1460 if ((m->input & INPUT_IN_POISON_GAS) && !(m->action & ACT_FLAG_INTANGIBLE)) { 1461 if (!(m->flags & MARIO_METAL_CAP) && !gDebugLevelSelect) { 1462 m->health -= 4; 1463 } 1464 } else { 1465 if ((m->action & ACT_FLAG_SWIMMING) && !(m->action & ACT_FLAG_INTANGIBLE)) { 1466 terrainIsSnow = (m->area->terrainType & TERRAIN_MASK) == TERRAIN_SNOW; 1467 1468 // When Mario is near the water surface, recover health (unless in snow), 1469 // when in snow terrains lose 3 health. 1470 // If using the debug level select, do not lose any HP to water. 1471 if ((m->pos[1] >= (m->waterLevel - 140)) && !terrainIsSnow) { 1472 m->health += 0x1A; 1473 } else if (!gDebugLevelSelect) { 1474 m->health -= (terrainIsSnow ? 3 : 1); 1475 } 1476 } 1477 } 1478 } 1479 1480 if (m->healCounter > 0) { 1481 m->health += 0x40; 1482 m->healCounter--; 1483 } 1484 if (m->hurtCounter > 0) { 1485 m->health -= 0x40; 1486 m->hurtCounter--; 1487 } 1488 1489 if (m->health > 0x880) { 1490 m->health = 0x880; 1491 } 1492 if (m->health < 0x100) { 1493 m->health = 0xFF; 1494 } 1495 1496 // Play a noise to alert the player when Mario is close to drowning. 1497 if (((m->action & ACT_GROUP_MASK) == ACT_GROUP_SUBMERGED) && (m->health < 0x300)) { 1498 play_sound(SOUND_MOVING_ALMOST_DROWNING, gGlobalSoundSource); 1499 #if ENABLE_RUMBLE 1500 if (gRumblePakTimer == 0) { 1501 gRumblePakTimer = 36; 1502 if (is_rumble_finished_and_queue_empty()) { 1503 queue_rumble_data(3, 30); 1504 } 1505 } 1506 } else { 1507 gRumblePakTimer = 0; 1508 #endif 1509 } 1510 } 1511 } 1512 1513 /** 1514 * Updates some basic info for camera usage. 1515 */ 1516 void update_mario_info_for_cam(struct MarioState *m) { 1517 m->marioBodyState->action = m->action; 1518 m->statusForCamera->action = m->action; 1519 1520 vec3s_copy(m->statusForCamera->faceAngle, m->faceAngle); 1521 1522 if (!(m->flags & MARIO_UNKNOWN_25)) { 1523 vec3f_copy(m->statusForCamera->pos, m->pos); 1524 } 1525 } 1526 1527 /** 1528 * Resets Mario's model, done every time an action is executed. 1529 */ 1530 void mario_reset_bodystate(struct MarioState *m) { 1531 struct MarioBodyState *bodyState = m->marioBodyState; 1532 1533 bodyState->capState = MARIO_HAS_DEFAULT_CAP_OFF; 1534 bodyState->eyeState = MARIO_EYES_BLINK; 1535 bodyState->handState = MARIO_HAND_FISTS; 1536 bodyState->modelState = 0; 1537 bodyState->wingFlutter = FALSE; 1538 1539 m->flags &= ~MARIO_METAL_SHOCK; 1540 } 1541 1542 /** 1543 * Adjusts Mario's graphical height for quicksand. 1544 */ 1545 void sink_mario_in_quicksand(struct MarioState *m) { 1546 struct Object *o = m->marioObj; 1547 1548 if (o->header.gfx.throwMatrix) { 1549 (*o->header.gfx.throwMatrix)[3][1] -= m->quicksandDepth; 1550 } 1551 1552 o->header.gfx.pos[1] -= m->quicksandDepth; 1553 } 1554 1555 /** 1556 * Is a binary representation of the frames to flicker Mario's cap when the timer 1557 * is running out. 1558 * 1559 * Equals [1000]^5 . [100]^8 . [10]^9 . [1] in binary, which is 1560 * 100010001000100010001001001001001001001001001010101010101010101. 1561 */ 1562 u64 sCapFlickerFrames = 0x4444449249255555; 1563 1564 /** 1565 * Updates the cap flags mainly based on the cap timer. 1566 */ 1567 u32 update_and_return_cap_flags(struct MarioState *m) { 1568 u32 flags = m->flags; 1569 u32 action; 1570 1571 if (m->capTimer > 0) { 1572 action = m->action; 1573 1574 if ((m->capTimer <= 60) 1575 || ((action != ACT_READING_AUTOMATIC_DIALOG) && (action != ACT_READING_NPC_DIALOG) 1576 && (action != ACT_READING_SIGN) && (action != ACT_IN_CANNON))) { 1577 m->capTimer -= 1; 1578 } 1579 1580 if (m->capTimer == 0) { 1581 stop_cap_music(); 1582 1583 m->flags &= ~MARIO_SPECIAL_CAPS; 1584 if (!(m->flags & MARIO_CAPS)) { 1585 m->flags &= ~MARIO_CAP_ON_HEAD; 1586 } 1587 } 1588 1589 if (m->capTimer == 60) { 1590 fadeout_cap_music(); 1591 } 1592 1593 // This code flickers the cap through a long binary string, increasing in how 1594 // common it flickers near the end. 1595 if ((m->capTimer < 64) && ((1ULL << m->capTimer) & sCapFlickerFrames)) { 1596 flags &= ~MARIO_SPECIAL_CAPS; 1597 if (!(flags & MARIO_CAPS)) { 1598 flags &= ~MARIO_CAP_ON_HEAD; 1599 } 1600 } 1601 } 1602 1603 return flags; 1604 } 1605 1606 /** 1607 * Updates the Mario's cap, rendering, and hitbox. 1608 */ 1609 void mario_update_hitbox_and_cap_model(struct MarioState *m) { 1610 struct MarioBodyState *bodyState = m->marioBodyState; 1611 s32 flags = update_and_return_cap_flags(m); 1612 1613 if (flags & MARIO_VANISH_CAP) { 1614 bodyState->modelState = MODEL_STATE_NOISE_ALPHA; 1615 } 1616 1617 if (flags & MARIO_METAL_CAP) { 1618 bodyState->modelState |= MODEL_STATE_METAL; 1619 } 1620 1621 if (flags & MARIO_METAL_SHOCK) { 1622 bodyState->modelState |= MODEL_STATE_METAL; 1623 } 1624 1625 //! (Pause buffered hitstun) Since the global timer increments while paused, 1626 // this can be paused through to give continual invisibility. This leads to 1627 // no interaction with objects. 1628 if ((m->invincTimer >= 3) && (gGlobalTimer & 1)) { 1629 gMarioState->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; 1630 } 1631 1632 if (flags & MARIO_CAP_IN_HAND) { 1633 if (flags & MARIO_WING_CAP) { 1634 bodyState->handState = MARIO_HAND_HOLDING_WING_CAP; 1635 } else { 1636 bodyState->handState = MARIO_HAND_HOLDING_CAP; 1637 } 1638 } 1639 1640 if (flags & MARIO_CAP_ON_HEAD) { 1641 if (flags & MARIO_WING_CAP) { 1642 bodyState->capState = MARIO_HAS_WING_CAP_ON; 1643 } else { 1644 bodyState->capState = MARIO_HAS_DEFAULT_CAP_ON; 1645 } 1646 } 1647 1648 // Short hitbox for crouching/crawling/etc. 1649 if (m->action & ACT_FLAG_SHORT_HITBOX) { 1650 m->marioObj->hitboxHeight = 100.0f; 1651 } else { 1652 m->marioObj->hitboxHeight = 160.0f; 1653 } 1654 1655 if ((m->flags & MARIO_TELEPORTING) && (m->fadeWarpOpacity != 0xFF)) { 1656 bodyState->modelState &= ~0xFF; 1657 bodyState->modelState |= (0x100 | m->fadeWarpOpacity); 1658 } 1659 } 1660 1661 /** 1662 * An unused and possibly a debug function. Z + another button input 1663 * sets Mario with a different cap. 1664 */ 1665 UNUSED static void debug_update_mario_cap(u16 button, s32 flags, u16 capTimer, u16 capMusic) { 1666 // This checks for Z_TRIG instead of Z_DOWN flag 1667 // (which is also what other debug functions do), 1668 // so likely debug behavior rather than unused behavior. 1669 if ((gPlayer1Controller->buttonDown & Z_TRIG) && (gPlayer1Controller->buttonPressed & button) 1670 && !(gMarioState->flags & flags)) { 1671 gMarioState->flags |= (flags + MARIO_CAP_ON_HEAD); 1672 1673 if (capTimer > gMarioState->capTimer) { 1674 gMarioState->capTimer = capTimer; 1675 } 1676 1677 play_cap_music(capMusic); 1678 } 1679 } 1680 1681 #if ENABLE_RUMBLE 1682 void func_sh_8025574C(void) { 1683 if (gMarioState->particleFlags & PARTICLE_HORIZONTAL_STAR) { 1684 queue_rumble_data(5, 80); 1685 } else if (gMarioState->particleFlags & PARTICLE_VERTICAL_STAR) { 1686 queue_rumble_data(5, 80); 1687 } else if (gMarioState->particleFlags & PARTICLE_TRIANGLE) { 1688 queue_rumble_data(5, 80); 1689 } 1690 if (gMarioState->heldObj && gMarioState->heldObj->behavior == segmented_to_virtual(bhvBobomb)) { 1691 reset_rumble_timers(); 1692 } 1693 } 1694 #endif 1695 1696 /** 1697 * Main function for executing Mario's behavior. 1698 */ 1699 s32 execute_mario_action(UNUSED struct Object *o) { 1700 s32 inLoop = TRUE; 1701 1702 if (gMarioState->action) { 1703 gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; 1704 mario_reset_bodystate(gMarioState); 1705 update_mario_inputs(gMarioState); 1706 mario_handle_special_floors(gMarioState); 1707 mario_process_interactions(gMarioState); 1708 1709 // If Mario is OOB, stop executing actions. 1710 if (gMarioState->floor == NULL) { 1711 return 0; 1712 } 1713 1714 // The function can loop through many action shifts in one frame, 1715 // which can lead to unexpected sub-frame behavior. Could potentially hang 1716 // if a loop of actions were found, but there has not been a situation found. 1717 while (inLoop) { 1718 switch (gMarioState->action & ACT_GROUP_MASK) { 1719 case ACT_GROUP_STATIONARY: 1720 inLoop = mario_execute_stationary_action(gMarioState); 1721 break; 1722 1723 case ACT_GROUP_MOVING: 1724 inLoop = mario_execute_moving_action(gMarioState); 1725 break; 1726 1727 case ACT_GROUP_AIRBORNE: 1728 inLoop = mario_execute_airborne_action(gMarioState); 1729 break; 1730 1731 case ACT_GROUP_SUBMERGED: 1732 inLoop = mario_execute_submerged_action(gMarioState); 1733 break; 1734 1735 case ACT_GROUP_CUTSCENE: 1736 inLoop = mario_execute_cutscene_action(gMarioState); 1737 break; 1738 1739 case ACT_GROUP_AUTOMATIC: 1740 inLoop = mario_execute_automatic_action(gMarioState); 1741 break; 1742 1743 case ACT_GROUP_OBJECT: 1744 inLoop = mario_execute_object_action(gMarioState); 1745 break; 1746 } 1747 } 1748 1749 sink_mario_in_quicksand(gMarioState); 1750 squish_mario_model(gMarioState); 1751 set_submerged_cam_preset_and_spawn_bubbles(gMarioState); 1752 update_mario_health(gMarioState); 1753 update_mario_info_for_cam(gMarioState); 1754 mario_update_hitbox_and_cap_model(gMarioState); 1755 1756 // Both of the wind handling portions play wind audio only in 1757 // non-Japanese releases. 1758 if (gMarioState->floor->type == SURFACE_HORIZONTAL_WIND) { 1759 spawn_wind_particles(0, (gMarioState->floor->force << 8)); 1760 #ifndef VERSION_JP 1761 play_sound(SOUND_ENV_WIND2, gMarioState->marioObj->header.gfx.cameraToObject); 1762 #endif 1763 } 1764 1765 if (gMarioState->floor->type == SURFACE_VERTICAL_WIND) { 1766 spawn_wind_particles(1, 0); 1767 #ifndef VERSION_JP 1768 play_sound(SOUND_ENV_WIND2, gMarioState->marioObj->header.gfx.cameraToObject); 1769 #endif 1770 } 1771 1772 play_infinite_stairs_music(); 1773 gMarioState->marioObj->oInteractStatus = 0; 1774 #if ENABLE_RUMBLE 1775 func_sh_8025574C(); 1776 #endif 1777 1778 return gMarioState->particleFlags; 1779 } 1780 1781 return 0; 1782 } 1783 1784 /************************************************** 1785 * INITIALIZATION * 1786 **************************************************/ 1787 1788 void init_mario(void) { 1789 Vec3s capPos; 1790 struct Object *capObject; 1791 1792 unused80339F10 = 0; 1793 1794 gMarioState->actionTimer = 0; 1795 gMarioState->framesSinceA = 0xFF; 1796 gMarioState->framesSinceB = 0xFF; 1797 1798 gMarioState->invincTimer = 0; 1799 1800 if (save_file_get_flags() 1801 & (SAVE_FLAG_CAP_ON_GROUND | SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_UKIKI 1802 | SAVE_FLAG_CAP_ON_MR_BLIZZARD)) { 1803 gMarioState->flags = 0; 1804 } else { 1805 gMarioState->flags = (MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); 1806 } 1807 1808 gMarioState->forwardVel = 0.0f; 1809 gMarioState->squishTimer = 0; 1810 1811 gMarioState->hurtCounter = 0; 1812 gMarioState->healCounter = 0; 1813 1814 gMarioState->capTimer = 0; 1815 gMarioState->quicksandDepth = 0.0f; 1816 1817 gMarioState->heldObj = NULL; 1818 gMarioState->riddenObj = NULL; 1819 gMarioState->usedObj = NULL; 1820 1821 gMarioState->waterLevel = 1822 find_water_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]); 1823 1824 gMarioState->area = gCurrentArea; 1825 gMarioState->marioObj = gMarioObject; 1826 gMarioState->marioObj->header.gfx.animInfo.animID = -1; 1827 vec3s_copy(gMarioState->faceAngle, gMarioSpawnInfo->startAngle); 1828 vec3s_set(gMarioState->angleVel, 0, 0, 0); 1829 vec3s_to_vec3f(gMarioState->pos, gMarioSpawnInfo->startPos); 1830 vec3f_set(gMarioState->vel, 0, 0, 0); 1831 gMarioState->floorHeight = 1832 find_floor(gMarioState->pos[0], gMarioState->pos[1], gMarioState->pos[2], &gMarioState->floor); 1833 1834 if (gMarioState->pos[1] < gMarioState->floorHeight) { 1835 gMarioState->pos[1] = gMarioState->floorHeight; 1836 } 1837 1838 gMarioState->marioObj->header.gfx.pos[1] = gMarioState->pos[1]; 1839 1840 gMarioState->action = 1841 (gMarioState->pos[1] <= (gMarioState->waterLevel - 100)) ? ACT_WATER_IDLE : ACT_IDLE; 1842 1843 mario_reset_bodystate(gMarioState); 1844 update_mario_info_for_cam(gMarioState); 1845 gMarioState->marioBodyState->punchState = 0; 1846 1847 gMarioState->marioObj->oPosX = gMarioState->pos[0]; 1848 gMarioState->marioObj->oPosY = gMarioState->pos[1]; 1849 gMarioState->marioObj->oPosZ = gMarioState->pos[2]; 1850 1851 gMarioState->marioObj->oMoveAnglePitch = gMarioState->faceAngle[0]; 1852 gMarioState->marioObj->oMoveAngleYaw = gMarioState->faceAngle[1]; 1853 gMarioState->marioObj->oMoveAngleRoll = gMarioState->faceAngle[2]; 1854 1855 vec3f_copy(gMarioState->marioObj->header.gfx.pos, gMarioState->pos); 1856 vec3s_set(gMarioState->marioObj->header.gfx.angle, 0, gMarioState->faceAngle[1], 0); 1857 1858 if (save_file_get_cap_pos(capPos)) { 1859 capObject = spawn_object(gMarioState->marioObj, MODEL_MARIOS_CAP, bhvNormalCap); 1860 1861 capObject->oPosX = capPos[0]; 1862 capObject->oPosY = capPos[1]; 1863 capObject->oPosZ = capPos[2]; 1864 1865 capObject->oForwardVelS32 = 0; 1866 1867 capObject->oMoveAngleYaw = 0; 1868 } 1869 } 1870 1871 void init_mario_from_save_file(void) { 1872 gMarioState->unk00 = 0; 1873 gMarioState->flags = 0; 1874 gMarioState->action = 0; 1875 gMarioState->spawnInfo = &gPlayerSpawnInfos[0]; 1876 gMarioState->statusForCamera = &gPlayerCameraState[0]; 1877 gMarioState->marioBodyState = &gBodyStates[0]; 1878 gMarioState->controller = &gControllers[0]; 1879 gMarioState->animList = &gMarioAnimsBuf; 1880 1881 gMarioState->numCoins = 0; 1882 gMarioState->numStars = 1883 save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); 1884 gMarioState->numKeys = 0; 1885 1886 gMarioState->numLives = 4; 1887 gMarioState->health = 0x880; 1888 1889 gMarioState->prevNumStarsForDialog = gMarioState->numStars; 1890 gMarioState->unkB0 = 0xBD; 1891 1892 gHudDisplay.coins = 0; 1893 gHudDisplay.wedges = 8; 1894 }