sm64

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

tuxie.inc.c (11362B)


      1 // tuxie.inc.c
      2 
      3 void play_penguin_walking_sound(s32 walk) {
      4     s32 sound;
      5 
      6     if (o->oSoundStateID == 0) {
      7         if (walk == PENGUIN_WALK_BABY) {
      8             sound = SOUND_OBJ_BABY_PENGUIN_WALK;
      9         } else { // PENGUIN_WALK_BIG
     10             sound = SOUND_OBJ_BIG_PENGUIN_WALK;
     11         }
     12         set_obj_anim_with_accel_and_sound(1, 11, sound);
     13     }
     14 }
     15 
     16 void tuxies_mother_act_2(void) {
     17     f32 sp24;
     18     UNUSED u8 filler[4];
     19     struct Object *sp1C = cur_obj_find_nearest_object_with_behavior(bhvSmallPenguin, &sp24);
     20 
     21     if (cur_obj_find_nearby_held_actor(bhvUnused20E0, 1000.0f) != NULL) {
     22         if (o->oSubAction == 0) {
     23             cur_obj_init_animation_with_sound(0);
     24             o->oForwardVel = 10.0f;
     25             if (cur_obj_lateral_dist_from_mario_to_home() > 800.0f) {
     26                 o->oSubAction = 1;
     27             }
     28             cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x400);
     29         } else {
     30             o->oForwardVel = 0.0f;
     31             cur_obj_init_animation_with_sound(3);
     32             if (cur_obj_lateral_dist_from_mario_to_home() < 700.0f) {
     33                 o->oSubAction = 0;
     34             }
     35         }
     36     } else {
     37         o->oForwardVel = 0.0f;
     38         cur_obj_init_animation_with_sound(3);
     39     }
     40 
     41     if (sp1C != NULL && sp24 < 300.0f && sp1C->oHeldState != HELD_FREE) {
     42         o->oAction = 1;
     43         sp1C->oSmallPenguinUnk88 = TRUE;
     44         o->prevObj = sp1C;
     45     }
     46 }
     47 
     48 void tuxies_mother_act_1(void) {
     49     switch (o->oSubAction) {
     50         case 0:
     51             cur_obj_init_animation_with_sound(3);
     52             if (!cur_obj_is_mario_on_platform()) {
     53                 s32 sp2C = (o->oBhvParams >> 16) & 0xFF;
     54                 s32 sp28 = (o->prevObj->oBhvParams >> 16) & 0xFF;
     55                 s32 dialogID;
     56 
     57                 if (sp2C == sp28) {
     58                     dialogID = DIALOG_058;
     59                 } else {
     60                     dialogID = DIALOG_059;
     61                 }
     62                 if (cur_obj_update_dialog_with_cutscene(MARIO_DIALOG_LOOK_UP,
     63                         DIALOG_FLAG_TURN_TO_MARIO, CUTSCENE_DIALOG, dialogID)) {
     64                     if (dialogID == DIALOG_058) {
     65                         o->oSubAction = 1;
     66                     } else {
     67                         o->oSubAction = 2;
     68                     }
     69                     o->prevObj->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY;
     70                 }
     71             } else {
     72                 cur_obj_init_animation_with_sound(0);
     73             }
     74             break;
     75 
     76         case 1:
     77             if (o->prevObj->oHeldState == HELD_FREE) {
     78                 //! This line is was almost certainly supposed to be something
     79                 // like o->prevObj->oInteractionSubtype &= ~INT_SUBTYPE_DROP_IMMEDIATELY;
     80                 // however, this code uses the value of o->oInteractionSubtype
     81                 // rather than its offset to rawData. For this object,
     82                 // o->oInteractionSubtype is always 0, so the result is this:
     83                 // o->prevObj->oUnknownUnk88 &= ~INT_SUBTYPE_DROP_IMMEDIATELY
     84                 // which has no effect as o->prevObj->oUnknownUnk88 is always 0
     85                 // or 1, which is not affected by the bitwise AND.
     86                 o->prevObj->OBJECT_FIELD_S32(o->oInteractionSubtype) &= ~INT_SUBTYPE_DROP_IMMEDIATELY;
     87                 obj_set_behavior(o->prevObj, bhvUnused20E0);
     88 #ifndef VERSION_JP
     89                 cur_obj_spawn_star_at_y_offset(3167.0f, -4300.0f, 5108.0f, 200.0f);
     90 #else
     91                 spawn_default_star(3500.0f, -4300.0f, 4650.0f);
     92 #endif
     93                 o->oAction = 2;
     94             }
     95             break;
     96 
     97         case 2:
     98             if (o->prevObj->oHeldState == HELD_FREE) {
     99                 //! Same bug as above
    100                 o->prevObj->OBJECT_FIELD_S32(o->oInteractionSubtype) &= ~INT_SUBTYPE_DROP_IMMEDIATELY;
    101                 obj_set_behavior(o->prevObj, bhvPenguinBaby);
    102                 o->oAction = 2;
    103             }
    104             break;
    105     }
    106 }
    107 
    108 void tuxies_mother_act_0(void) {
    109     s32 sp2C = FALSE;
    110     f32 sp28;
    111     struct Object *sp24 = cur_obj_find_nearest_object_with_behavior(bhvSmallPenguin, &sp28);
    112 
    113     cur_obj_scale(4.0f);
    114     cur_obj_init_animation_with_sound(3);
    115 
    116     if (sp28 < 500.0f) {
    117         sp2C = TRUE;
    118     }
    119 
    120     if (sp24 != NULL && sp28 < 300.0f && sp24->oHeldState != HELD_FREE) {
    121         o->oAction = 1;
    122         sp24->oSmallPenguinUnk88 = TRUE;
    123         o->prevObj = sp24;
    124     } else {
    125         switch (o->oSubAction) {
    126             case 0:
    127                 if (cur_obj_can_mario_activate_textbox_2(300.0f, 100.0f) && !sp2C) {
    128                     o->oSubAction++;
    129                 }
    130                 break;
    131             case 1:
    132                 if (cur_obj_update_dialog_with_cutscene(MARIO_DIALOG_LOOK_UP,
    133                     DIALOG_FLAG_TURN_TO_MARIO, CUTSCENE_DIALOG, DIALOG_057)) {
    134                     o->oSubAction++;
    135                 }
    136                 break;
    137             case 2:
    138                 if (o->oDistanceToMario > 450.0f) {
    139                     o->oSubAction = 0;
    140                 }
    141                 break;
    142         }
    143     }
    144 
    145     if (cur_obj_check_anim_frame(1)) {
    146         cur_obj_play_sound_2(SOUND_OBJ_BIG_PENGUIN_YELL);
    147     }
    148 }
    149 
    150 void (*sTuxiesMotherActions[])(void) = {
    151     tuxies_mother_act_0,
    152     tuxies_mother_act_1,
    153     tuxies_mother_act_2,
    154 };
    155 
    156 void bhv_tuxies_mother_loop(void) {
    157     o->activeFlags |= ACTIVE_FLAG_UNK10;
    158     cur_obj_update_floor_and_walls();
    159     cur_obj_call_action_function(sTuxiesMotherActions);
    160     cur_obj_move_standard(-78);
    161     play_penguin_walking_sound(PENGUIN_WALK_BIG);
    162     o->oInteractStatus = 0;
    163 }
    164 
    165 void small_penguin_dive_with_mario(void) {
    166     if (mario_is_dive_sliding()) {
    167         o->oSmallPenguinUnk100 = o->oAction;
    168         o->oAction = 3;
    169     }
    170 }
    171 
    172 void small_penguin_act_2(void) {
    173     s32 sp1C = FALSE;
    174 
    175     if (o->oTimer == 0
    176         && cur_obj_dist_to_nearest_object_with_behavior(bhvTuxiesMother) < 1000.0f) {
    177         sp1C = TRUE;
    178     }
    179     cur_obj_init_animation_with_sound(0);
    180     o->oForwardVel = o->oSmallPenguinUnk104 + 3.0f;
    181     cur_obj_rotate_yaw_toward(o->oAngleToMario + 0x8000, o->oSmallPenguinUnk110 + 0x600);
    182     if (o->oDistanceToMario > o->oSmallPenguinUnk108 + 500.0f) {
    183         o->oAction = 0;
    184     }
    185     small_penguin_dive_with_mario();
    186     if (sp1C) {
    187         o->oAction = 5;
    188     }
    189 }
    190 
    191 void small_penguin_act_1(void) {
    192     cur_obj_init_animation_with_sound(0);
    193     o->oForwardVel = o->oSmallPenguinUnk104 + 3.0f;
    194     cur_obj_rotate_yaw_toward(o->oAngleToMario, o->oSmallPenguinUnk110 + 0x600);
    195     if (o->oDistanceToMario < o->oSmallPenguinUnk108 + 300.0f) {
    196         o->oAction = 0;
    197     }
    198     if (o->oDistanceToMario > 1100.0f) {
    199         o->oAction = 0;
    200     }
    201     small_penguin_dive_with_mario();
    202 }
    203 
    204 void small_penguin_act_3(void) {
    205     if (o->oTimer > 5) {
    206         if (o->oTimer == 6) {
    207             cur_obj_play_sound_2(SOUND_OBJ_BABY_PENGUIN_DIVE);
    208         }
    209         cur_obj_init_animation_with_sound(1);
    210         if (o->oTimer > 25 && !mario_is_dive_sliding()) {
    211             o->oAction = 4;
    212         }
    213     }
    214 }
    215 
    216 void small_penguin_act_4(void) {
    217     if (o->oTimer > 20) {
    218         o->oForwardVel = 0.0f;
    219         cur_obj_init_animation_with_sound(2);
    220         if (o->oTimer > 40) {
    221             o->oAction = o->oSmallPenguinUnk100;
    222         }
    223     }
    224 }
    225 
    226 void small_penguin_act_0(void) {
    227     s32 sp1C = FALSE;
    228 
    229     cur_obj_init_animation_with_sound(3);
    230     if (o->oTimer == 0) {
    231         o->oSmallPenguinUnk110 = (s32)(random_float() * 0x400);
    232         o->oSmallPenguinUnk108 = random_float() * 100.0f;
    233         o->oSmallPenguinUnk104 = random_float();
    234         o->oForwardVel = 0.0f;
    235         if (cur_obj_dist_to_nearest_object_with_behavior(bhvTuxiesMother) < 1000.0f) {
    236             sp1C = TRUE;
    237         }
    238     }
    239     if (o->oDistanceToMario < 1000.0f && o->oDistanceToMario > o->oSmallPenguinUnk108 + 600.0f) {
    240         o->oAction = 1;
    241     } else if (o->oDistanceToMario < o->oSmallPenguinUnk108 + 300.0f) {
    242         o->oAction = 2;
    243     }
    244     if (sp1C) {
    245         o->oAction = 5;
    246     }
    247     if (cur_obj_mario_far_away()) {
    248         cur_obj_set_pos_to_home();
    249     }
    250 }
    251 
    252 void small_penguin_act_5(void) {
    253     f32 sp24;
    254     s16 sp22;
    255     struct Object *sp1C = cur_obj_nearest_object_with_behavior(bhvTuxiesMother);
    256 
    257     if (sp1C != NULL) {
    258         if (o->oDistanceToMario < 1000.0f) {
    259             o->oForwardVel = 2.0f;
    260         } else {
    261             o->oForwardVel = 0.0f;
    262         }
    263 
    264         sp24 = dist_between_objects(o, sp1C);
    265         sp22 = obj_angle_to_object(o, sp1C);
    266 
    267         if (sp24 > 200.0f) {
    268             cur_obj_rotate_yaw_toward(sp22, 0x400);
    269         } else {
    270             cur_obj_rotate_yaw_toward(sp22 + 0x8000, 0x400);
    271         }
    272 
    273         cur_obj_init_animation_with_sound(0);
    274     }
    275 
    276     small_penguin_dive_with_mario();
    277 }
    278 
    279 void (*sSmallPenguinActions[])(void) = {
    280     small_penguin_act_0,
    281     small_penguin_act_1,
    282     small_penguin_act_2,
    283     small_penguin_act_3,
    284     small_penguin_act_4,
    285     small_penguin_act_5,
    286 };
    287 
    288 void small_penguin_free_actions(void) {
    289     if (o->oSmallPenguinUnk88) {
    290         o->oAction = 5;
    291         o->oSmallPenguinUnk88 = FALSE;
    292     }
    293     cur_obj_update_floor_and_walls();
    294     cur_obj_call_action_function(sSmallPenguinActions);
    295     cur_obj_move_standard(-78);
    296     play_penguin_walking_sound(PENGUIN_WALK_BABY);
    297 }
    298 
    299 void bhv_small_penguin_loop(void) {
    300     switch (o->oHeldState) {
    301         case HELD_FREE:
    302             small_penguin_free_actions();
    303             break;
    304         case HELD_HELD:
    305             cur_obj_unrender_set_action_and_anim(0, 0);
    306             if (cur_obj_has_behavior(bhvPenguinBaby)) {
    307                 obj_set_behavior(o, bhvSmallPenguin);
    308             }
    309             obj_copy_pos(o, gMarioObject);
    310             if (gGlobalTimer % 30 == 0) {
    311 #ifndef VERSION_JP
    312                 play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, gMarioObject->header.gfx.cameraToObject);
    313 #else
    314                 play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject);
    315 #endif
    316             }
    317             break;
    318         case HELD_THROWN:
    319             cur_obj_get_thrown_or_placed(0, 0, 0);
    320             break;
    321         case HELD_DROPPED:
    322             cur_obj_get_dropped();
    323             break;
    324     }
    325 }
    326 
    327 /** Geo switch logic for Tuxie's mother's eyes. Cases 0-4. Interestingly, case
    328  * 4 is unused, and is the eye state seen in Shoshinkai 1995 footage.
    329  */
    330 Gfx *geo_switch_tuxie_mother_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx) {
    331     if (run == TRUE) {
    332         struct Object *obj = (struct Object *) gCurGraphNodeObject;
    333         struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node;
    334         s32 timer;
    335 
    336         switchCase->selectedCase = 0;
    337 
    338         // timer logic for blinking. uses cases 0-2.
    339         timer = gGlobalTimer % 50;
    340         if (timer < 43) {
    341             switchCase->selectedCase = 0;
    342         } else if (timer < 45) {
    343             switchCase->selectedCase = 1;
    344         } else if (timer < 47) {
    345             switchCase->selectedCase = 2;
    346         } else {
    347             switchCase->selectedCase = 1;
    348         }
    349 
    350         /** make Tuxie's Mother have angry eyes if Mario takes the correct baby
    351          * after giving it back. The easiest way to check this is to see if she's
    352          * moving, since she only does when she's chasing Mario.
    353          */
    354         if (obj->behavior == segmented_to_virtual(bhvTuxiesMother)) {
    355             if (obj->oForwardVel > 5.0f) {
    356                 switchCase->selectedCase = 3;
    357             }
    358         }
    359     }
    360 
    361     return NULL;
    362 }