sm64

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

racing_penguin.inc.c (6907B)


      1 // racing_penguin.inc.c
      2 
      3 struct RacingPenguinData {
      4     s16 dialogID;
      5     f32 radius;
      6     f32 height;
      7 };
      8 
      9 static struct RacingPenguinData sRacingPenguinData[] = {
     10     /* RACING_PENGUIN_BP_THIN */ { DIALOG_055, 200.0f, 200.0f },
     11     /* RACING_PENGUIN_BP_FAT  */ { DIALOG_164, 350.0f, 250.0f },
     12 };
     13 
     14 void bhv_racing_penguin_init(void) {
     15     if (gMarioState->numStars == 120) {
     16         cur_obj_scale(8.0f);
     17         o->header.gfx.scale[1] = 5.0f;
     18         o->oBhvParams2ndByte = RACING_PENGUIN_BP_FAT;
     19     }
     20 }
     21 
     22 static void racing_penguin_act_wait_for_mario(void) {
     23     if (o->oTimer > o->oRacingPenguinInitTextCooldown && o->oPosY - gMarioObject->oPosY <= 0.0f
     24         && cur_obj_can_mario_activate_textbox_2(400.0f, 400.0f)) {
     25         o->oAction = RACING_PENGUIN_ACT_SHOW_INIT_TEXT;
     26     }
     27 }
     28 
     29 static void racing_penguin_act_show_init_text(void) {
     30     s32 response = obj_update_race_proposition_dialog(sRacingPenguinData[o->oBhvParams2ndByte].dialogID);
     31 
     32     if (response == DIALOG_RESPONSE_YES) {
     33         struct Object *child;
     34 
     35         child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine);
     36         child->parentObj = o;
     37 
     38         child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceShortcutCheck);
     39         child->parentObj = o;
     40 
     41         o->oPathedStartWaypoint = o->oPathedPrevWaypoint =
     42             segmented_to_virtual(ccm_seg7_trajectory_penguin_race);
     43         o->oPathedPrevWaypointFlags = 0;
     44 
     45         o->oAction = RACING_PENGUIN_ACT_PREPARE_FOR_RACE;
     46         o->oVelY = 60.0f;
     47     } else if (response == DIALOG_RESPONSE_NO) {
     48         o->oAction = RACING_PENGUIN_ACT_WAIT_FOR_MARIO;
     49         o->oRacingPenguinInitTextCooldown = 60;
     50     }
     51 }
     52 
     53 static void racing_penguin_act_prepare_for_race(void) {
     54     if (obj_begin_race(TRUE)) {
     55         o->oAction = RACING_PENGUIN_ACT_RACE;
     56         o->oForwardVel = 20.0f;
     57     }
     58 
     59     cur_obj_rotate_yaw_toward(0x4000, 2500);
     60 }
     61 
     62 static void racing_penguin_act_race(void) {
     63     if (cur_obj_follow_path(0) == PATH_REACHED_END) {
     64         o->oRacingPenguinReachedBottom = TRUE;
     65         o->oAction = RACING_PENGUIN_ACT_FINISH_RACE;
     66     } else {
     67         f32 targetSpeed = o->oPosY - gMarioObject->oPosY;
     68         f32 minSpeed = 70.0f;
     69 
     70         cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE);
     71 
     72         if (targetSpeed < 100.0f || (o->oPathedPrevWaypointFlags & WAYPOINT_MASK_00FF) >= 35) {
     73             if ((o->oPathedPrevWaypointFlags & WAYPOINT_MASK_00FF) >= 35) {
     74                 minSpeed = 60.0f;
     75             }
     76 
     77             approach_f32_ptr(&o->oRacingPenguinWeightedNewTargetSpeed, -500.0f, 100.0f);
     78         } else {
     79             approach_f32_ptr(&o->oRacingPenguinWeightedNewTargetSpeed, 1000.0f, 30.0f);
     80         }
     81 
     82         targetSpeed = 0.1f * (o->oRacingPenguinWeightedNewTargetSpeed + targetSpeed);
     83         clamp_f32(&targetSpeed, minSpeed, 150.0f);
     84         obj_forward_vel_approach(targetSpeed, 0.4f);
     85 
     86         cur_obj_init_animation_with_sound(1);
     87         cur_obj_rotate_yaw_toward(o->oPathedTargetYaw, (s32)(15.0f * o->oForwardVel));
     88 
     89         if (cur_obj_check_if_at_animation_end() && (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND)) {
     90             spawn_object_relative_with_scale(0, 0, -100, 0, 4.0f, o, MODEL_SMOKE, bhvWhitePuffSmoke2);
     91         }
     92     }
     93 
     94     if (mario_is_in_air_action()) {
     95         if (o->oTimer > 60) {
     96             o->oRacingPenguinMarioCheated = TRUE;
     97         }
     98     } else {
     99         o->oTimer = 0;
    100     }
    101 }
    102 
    103 static void racing_penguin_act_finish_race(void) {
    104     if (o->oForwardVel != 0.0f) {
    105         if (o->oTimer > 5 && (o->oMoveFlags & OBJ_MOVE_HIT_WALL)) {
    106             cur_obj_play_sound_2(SOUND_OBJ_POUNDING_LOUD);
    107             set_camera_shake_from_point(SHAKE_POS_SMALL, o->oPosX, o->oPosY, o->oPosZ);
    108             o->oForwardVel = 0.0f;
    109         }
    110     } else if (cur_obj_init_anim_and_check_if_end(2)) {
    111         o->oAction = RACING_PENGUIN_ACT_SHOW_FINAL_TEXT;
    112     }
    113 }
    114 
    115 static void racing_penguin_act_show_final_text(void) {
    116     if (o->oRacingPenguinFinalTextbox == 0) {
    117         if (cur_obj_rotate_yaw_toward(0, 200)) {
    118             cur_obj_init_animation_with_sound(3);
    119             o->oForwardVel = 0.0f;
    120 
    121             if (cur_obj_can_mario_activate_textbox_2(400.0f, 400.0f)) {
    122                 if (o->oRacingPenguinMarioWon) {
    123                     if (o->oRacingPenguinMarioCheated) {
    124                         o->oRacingPenguinFinalTextbox = DIALOG_132;
    125                         o->oRacingPenguinMarioWon = FALSE;
    126                     } else {
    127                         o->oRacingPenguinFinalTextbox = DIALOG_056;
    128                     }
    129                 } else {
    130                     o->oRacingPenguinFinalTextbox = DIALOG_037;
    131                 }
    132             }
    133         } else {
    134             cur_obj_init_animation_with_sound(0);
    135 
    136 #ifndef VERSION_JP
    137             play_penguin_walking_sound(1);
    138 #endif
    139 
    140             o->oForwardVel = 4.0f;
    141         }
    142     } else if (o->oRacingPenguinFinalTextbox > 0) {
    143         s32 textResult;
    144         if ((textResult = cur_obj_update_dialog_with_cutscene(MARIO_DIALOG_LOOK_UP,
    145             DIALOG_FLAG_TURN_TO_MARIO, CUTSCENE_DIALOG, o->oRacingPenguinFinalTextbox))) {
    146             o->oRacingPenguinFinalTextbox = -1;
    147             o->oTimer = 0;
    148         }
    149     } else if (o->oRacingPenguinMarioWon) {
    150 #ifdef VERSION_JP
    151         spawn_default_star(-7339.0f, -5700.0f, -6774.0f);
    152 #else
    153         cur_obj_spawn_star_at_y_offset(-7339.0f, -5700.0f, -6774.0f, 200.0f);
    154 #endif
    155         o->oRacingPenguinMarioWon = FALSE;
    156     }
    157 }
    158 
    159 void bhv_racing_penguin_update(void) {
    160     cur_obj_update_floor_and_walls();
    161 
    162     switch (o->oAction) {
    163         case RACING_PENGUIN_ACT_WAIT_FOR_MARIO:
    164             racing_penguin_act_wait_for_mario();
    165             break;
    166         case RACING_PENGUIN_ACT_SHOW_INIT_TEXT:
    167             racing_penguin_act_show_init_text();
    168             break;
    169         case RACING_PENGUIN_ACT_PREPARE_FOR_RACE:
    170             racing_penguin_act_prepare_for_race();
    171             break;
    172         case RACING_PENGUIN_ACT_RACE:
    173             racing_penguin_act_race();
    174             break;
    175         case RACING_PENGUIN_ACT_FINISH_RACE:
    176             racing_penguin_act_finish_race();
    177             break;
    178         case RACING_PENGUIN_ACT_SHOW_FINAL_TEXT:
    179             racing_penguin_act_show_final_text();
    180             break;
    181     }
    182 
    183     cur_obj_move_standard(78);
    184     cur_obj_align_gfx_with_floor();
    185     cur_obj_push_mario_away_from_cylinder(sRacingPenguinData[o->oBhvParams2ndByte].radius,
    186                                           sRacingPenguinData[o->oBhvParams2ndByte].height);
    187 }
    188 
    189 void bhv_penguin_race_finish_line_update(void) {
    190     if ((o->parentObj->oRacingPenguinReachedBottom
    191          || (o->oDistanceToMario < 1000.0f && gMarioObject->oPosZ - o->oPosZ < 0.0f))
    192         && !o->parentObj->oRacingPenguinReachedBottom) {
    193         o->parentObj->oRacingPenguinMarioWon = TRUE;
    194     }
    195 }
    196 
    197 void bhv_penguin_race_shortcut_check_update(void) {
    198     if (o->oDistanceToMario < 500.0f) {
    199         o->parentObj->oRacingPenguinMarioCheated = TRUE;
    200     }
    201 }