sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

sl_walking_penguin.inc.c (4747B)


      1 // sl_walking_penguin.inc.c
      2 
      3 struct SLWalkingPenguinStep {
      4     s32 stepLength;
      5     s32 anim;
      6     f32 speed;
      7     f32 animSpeed;
      8 };
      9 
     10 // The penguin follows a preset list of movements while walking forward.
     11 struct SLWalkingPenguinStep sSLWalkingPenguinErraticSteps[] = {
     12     { 60, PENGUIN_ANIM_WALK, 6.0f,  1.0f }, // Walk forwards for 2 seconds
     13     { 30, PENGUIN_ANIM_IDLE, 0.0f,  1.0f }, // Stop for 1 second
     14     { 30, PENGUIN_ANIM_WALK, 12.0f, 2.0f }, // Walk forwards quickly for 1 second
     15     { 30, PENGUIN_ANIM_IDLE, 0.0f,  1.0f }, // Stop for 1 second
     16     { 30, PENGUIN_ANIM_WALK, -6.0f, 1.0f }, // Walk backwards for 1 second
     17     { 30, PENGUIN_ANIM_IDLE, 0.0f,  1.0f }, // Stop for 1 second
     18     { -1, 0, 0.0f,  0.0f }, // Repeat
     19 };
     20 
     21 static s32 sl_walking_penguin_turn(void) {
     22     // Stay still and use walking animation for the turn.
     23     o->oForwardVel = 0.0f;
     24     cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 1.0f);
     25 
     26     // Turn around.
     27     o->oAngleVelYaw = 0x400;
     28     o->oMoveAngleYaw += o->oAngleVelYaw;
     29 
     30     if (o->oTimer == 31) {
     31         return TRUE; // Finished turning
     32     } else {
     33         return FALSE;
     34     }
     35 }
     36 
     37 void bhv_sl_walking_penguin_loop(void) {
     38     f32 adjustedXPos, adjustedZPos;
     39     f32 perpendicularOffset = 100.0f;
     40 
     41     o->oAngleVelYaw = 0;
     42     cur_obj_update_floor_and_walls();
     43 
     44     switch (o->oAction) {
     45         // Walk erratically across the ice bridge using preset steps.
     46         case SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS:
     47             if (o->oTimer == 0) {
     48                 // Initiate variables
     49                 o->oSLWalkingPenguinCurStep = 0;
     50                 o->oSLWalkingPenguinCurStepTimer = 0;
     51             }
     52 
     53             if (o->oSLWalkingPenguinCurStepTimer <
     54                 sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength) {
     55                 o->oSLWalkingPenguinCurStepTimer++;
     56             } else {
     57                 // Move to next step
     58                 o->oSLWalkingPenguinCurStepTimer = 0;
     59                 o->oSLWalkingPenguinCurStep++;
     60                 if (sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength < 0) {
     61                     // Reached the end of the list, go back to the start
     62                     o->oSLWalkingPenguinCurStep = 0;
     63                 }
     64             }
     65 
     66             if (o->oPosX < 300.0f) {
     67                 o->oAction++; // If reached the end of the bridge, turn around and head back.
     68             } else {
     69                 // Move and animate the penguin
     70                 o->oForwardVel = sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].speed;
     71 
     72                 cur_obj_init_animation_with_accel_and_sound(
     73                     sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].anim,
     74                     sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].animSpeed
     75                 );
     76             }
     77             break;
     78 
     79         // At the end, turn around and prepare to head back across the bridge.
     80         case SL_WALKING_PENGUIN_ACT_TURNING_BACK:
     81             if (sl_walking_penguin_turn()) {
     82                 o->oAction++; // Finished turning
     83             }
     84             break;
     85 
     86         // Walk back across the bridge at a constant speed.
     87         case SL_WALKING_PENGUIN_ACT_RETURNING:
     88             // Move and animate the penguin
     89             o->oForwardVel = 12.0f;
     90             cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 2.0f);
     91 
     92             if (o->oPosX > 1700.0f) {
     93                 o->oAction++; // If reached the start of the bridge, turn around.
     94             }
     95             break;
     96 
     97         // At the start, turn around and prepare to walk erratically across the bridge.
     98         case SL_WALKING_PENGUIN_ACT_TURNING_FORWARDS:
     99             if (sl_walking_penguin_turn()) {
    100                 o->oAction = SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS; // Finished turning
    101             }
    102             break;
    103     }
    104 
    105     cur_obj_move_standard(-78);
    106     if (!cur_obj_hide_if_mario_far_away_y(1000.0f)) {
    107         play_penguin_walking_sound(PENGUIN_WALK_BIG);
    108     }
    109 
    110     // Adjust the position to get a point better lined up with the visual model, for stopping the wind.
    111     // The new point is 60 units behind the penguin and 100 units perpedicularly, away from the snowman.
    112 
    113     adjustedXPos = o->oPosX + sins(0xDBB0) * 60.0f; // 0xDBB0 = -51 degrees, the angle the penguin is facing
    114     adjustedZPos = o->oPosZ + coss(0xDBB0) * 60.0f;
    115     adjustedXPos += perpendicularOffset * sins(0x1BB0); // 0x1BB0 = 39 degrees, perpendicular to the penguin
    116     adjustedZPos += perpendicularOffset * coss(0x1BB0);
    117     o->oSLWalkingPenguinWindCollisionXPos = adjustedXPos;
    118     o->oSLWalkingPenguinWindCollisionZPos = adjustedZPos;
    119 
    120     print_debug_bottom_up("x %d", o->oPosX);
    121     print_debug_bottom_up("z %d", o->oPosZ);
    122 }