sm64

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

yoshi.inc.c (5761B)


      1 // yoshi.inc.c
      2 
      3 // X/Z coordinates of Yoshi's homes that he switches between.
      4 // Note that this doesn't contain the Y coordinate since the castle roof is flat,
      5 // so o->oHomeY is never updated.
      6 static s16 sYoshiHomeLocations[] = { 0, -5625, -1364, -5912, -1403, -4609, -1004, -5308 };
      7 
      8 void bhv_yoshi_init(void) {
      9     o->oGravity = 2.0f;
     10     o->oFriction = 0.9f;
     11     o->oBuoyancy = 1.3f;
     12     o->oInteractionSubtype = INT_SUBTYPE_NPC;
     13 
     14     if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) < 120
     15         || sYoshiDead == TRUE) {
     16         o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
     17     }
     18 }
     19 
     20 void yoshi_walk_loop(void) {
     21     UNUSED s16 collisionFlags;
     22     s16 animFrame = o->header.gfx.animInfo.animFrame;
     23 
     24     o->oForwardVel = 10.0f;
     25     collisionFlags = object_step();
     26     o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500);
     27 
     28     if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200)) {
     29         o->oAction = YOSHI_ACT_IDLE;
     30     }
     31 
     32     cur_obj_init_animation(1);
     33 
     34     if (animFrame == 0 || animFrame == 15) {
     35         cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK);
     36     }
     37 
     38     if (o->oInteractStatus == INT_STATUS_INTERACTED) {
     39         o->oAction = YOSHI_ACT_TALK;
     40     }
     41 
     42     if (o->oPosY < 2100.0f) {
     43         create_respawner(MODEL_YOSHI, bhvYoshi, 3000);
     44         o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
     45     }
     46 }
     47 
     48 void yoshi_idle_loop(void) {
     49     s16 chosenHome;
     50     UNUSED s16 animFrame = o->header.gfx.animInfo.animFrame;
     51 
     52     if (o->oTimer > 90) {
     53         chosenHome = random_float() * 3.99;
     54 
     55         if (o->oYoshiChosenHome == chosenHome) {
     56             return;
     57         } else {
     58             o->oYoshiChosenHome = chosenHome;
     59         }
     60 
     61         o->oHomeX = sYoshiHomeLocations[o->oYoshiChosenHome * 2];
     62         o->oHomeZ = sYoshiHomeLocations[o->oYoshiChosenHome * 2 + 1];
     63         o->oYoshiTargetYaw = atan2s(o->oHomeZ - o->oPosZ, o->oHomeX - o->oPosX);
     64         o->oAction = YOSHI_ACT_WALK;
     65     }
     66 
     67     cur_obj_init_animation(0);
     68 
     69     if (o->oInteractStatus == INT_STATUS_INTERACTED) {
     70         o->oAction = YOSHI_ACT_TALK;
     71     }
     72 
     73     // Credits; Yoshi appears at this position overlooking the castle near the end of the credits
     74     if (gPlayerCameraState->cameraEvent == CAM_EVENT_START_ENDING ||
     75         gPlayerCameraState->cameraEvent == CAM_EVENT_START_END_WAVING) {
     76         o->oAction = YOSHI_ACT_CREDITS;
     77         o->oPosX = -1798.0f;
     78         o->oPosY = 3174.0f;
     79         o->oPosZ = -3644.0f;
     80     }
     81 }
     82 
     83 void yoshi_talk_loop(void) {
     84     if ((s16) o->oMoveAngleYaw == (s16) o->oAngleToMario) {
     85         cur_obj_init_animation(0);
     86         if (set_mario_npc_dialog(MARIO_DIALOG_LOOK_FRONT) == MARIO_DIALOG_STATUS_SPEAK) {
     87             o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
     88             if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_161) != 0) {
     89                 o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
     90                 o->oInteractStatus = 0;
     91                 o->oHomeX = sYoshiHomeLocations[2];
     92                 o->oHomeZ = sYoshiHomeLocations[3];
     93                 o->oYoshiTargetYaw = atan2s(o->oHomeZ - o->oPosZ, o->oHomeX - o->oPosX);
     94                 o->oAction = YOSHI_ACT_GIVE_PRESENT;
     95             }
     96         }
     97     } else {
     98         cur_obj_init_animation(1);
     99         play_puzzle_jingle();
    100         o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oAngleToMario, 0x500);
    101     }
    102 }
    103 
    104 void yoshi_walk_and_jump_off_roof_loop(void) {
    105     s16 animFrame = o->header.gfx.animInfo.animFrame;
    106 
    107     o->oForwardVel = 10.0f;
    108     object_step();
    109     cur_obj_init_animation(1);
    110 
    111     if (o->oTimer == 0) {
    112         cutscene_object(CUTSCENE_STAR_SPAWN, o);
    113     }
    114 
    115     o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500);
    116 
    117     if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200)) {
    118         cur_obj_init_animation(2);
    119         cur_obj_play_sound_2(SOUND_GENERAL_ENEMY_ALERT1);
    120         o->oForwardVel = 50.0f;
    121         o->oVelY = 40.0f;
    122         o->oMoveAngleYaw = -0x3FFF;
    123         o->oAction = YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN;
    124     }
    125 
    126     if (animFrame == 0 || animFrame == 15) {
    127         cur_obj_play_sound_2(SOUND_GENERAL_YOSHI_WALK);
    128     }
    129 }
    130 
    131 void yoshi_finish_jumping_and_despawn_loop(void) {
    132     cur_obj_extend_animation_if_at_end();
    133     obj_move_xyz_using_fvel_and_yaw(o);
    134 
    135     o->oVelY -= 2.0;
    136 
    137     if (o->oPosY < 2100.0f) {
    138         set_mario_npc_dialog(MARIO_DIALOG_STOP);
    139         gObjCutsceneDone = TRUE;
    140         sYoshiDead = TRUE;
    141         o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
    142     }
    143 }
    144 
    145 void yoshi_give_present_loop(void) {
    146     s32 globalTimer = gGlobalTimer;
    147 
    148     if (gHudDisplay.lives == 100) {
    149         play_sound(SOUND_GENERAL_COLLECT_1UP, gGlobalSoundSource);
    150         gSpecialTripleJump = TRUE;
    151         o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF;
    152         return;
    153     }
    154 
    155     if (!(globalTimer & 3)) {
    156         play_sound(SOUND_MENU_YOSHI_GAIN_LIVES, gGlobalSoundSource);
    157         gMarioState->numLives++;
    158     }
    159 }
    160 
    161 void bhv_yoshi_loop(void) {
    162     switch (o->oAction) {
    163         case YOSHI_ACT_IDLE:
    164             yoshi_idle_loop();
    165             break;
    166 
    167         case YOSHI_ACT_WALK:
    168             yoshi_walk_loop();
    169             break;
    170 
    171         case YOSHI_ACT_TALK:
    172             yoshi_talk_loop();
    173             break;
    174 
    175         case YOSHI_ACT_WALK_JUMP_OFF_ROOF:
    176             yoshi_walk_and_jump_off_roof_loop();
    177             break;
    178 
    179         case YOSHI_ACT_FINISH_JUMPING_AND_DESPAWN:
    180             yoshi_finish_jumping_and_despawn_loop();
    181             break;
    182 
    183         case YOSHI_ACT_GIVE_PRESENT:
    184             yoshi_give_present_loop();
    185             break;
    186 
    187         case YOSHI_ACT_CREDITS:
    188             cur_obj_init_animation(0);
    189             break;
    190     }
    191 
    192     curr_obj_random_blink(&o->oYoshiBlinkTimer);
    193 }