sm64

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

coin.inc.c (8538B)


      1 // coin.inc.c
      2 
      3 struct ObjectHitbox sYellowCoinHitbox = {
      4     /* interactType:      */ INTERACT_COIN,
      5     /* downOffset:        */ 0,
      6     /* damageOrCoinValue: */ 1,
      7     /* health:            */ 0,
      8     /* numLootCoins:      */ 0,
      9     /* radius:            */ 100,
     10     /* height:            */ 64,
     11     /* hurtboxRadius:     */ 0,
     12     /* hurtboxHeight:     */ 0,
     13 };
     14 
     15 s32 bhv_coin_sparkles_init(void) {
     16     if (o->oInteractStatus & INT_STATUS_INTERACTED
     17         && !(o->oInteractStatus & INT_STATUS_TOUCHED_BOB_OMB)) {
     18         spawn_object(o, MODEL_SPARKLES, bhvGoldenCoinSparkles);
     19         obj_mark_for_deletion(o);
     20         return TRUE;
     21     }
     22 
     23     o->oInteractStatus = 0;
     24 
     25     return FALSE;
     26 }
     27 
     28 void bhv_yellow_coin_init(void) {
     29     cur_obj_set_behavior(bhvYellowCoin);
     30     obj_set_hitbox(o, &sYellowCoinHitbox);
     31     bhv_init_room();
     32     cur_obj_update_floor_height();
     33 
     34     if (500.0f < absf(o->oPosY - o->oFloorHeight)) {
     35         cur_obj_set_model(MODEL_YELLOW_COIN_NO_SHADOW);
     36     }
     37 
     38     if (o->oFloorHeight < FLOOR_LOWER_LIMIT_MISC) {
     39         obj_mark_for_deletion(o);
     40     }
     41 }
     42 
     43 void bhv_yellow_coin_loop(void) {
     44     bhv_coin_sparkles_init();
     45     o->oAnimState++;
     46 }
     47 
     48 void bhv_temp_coin_loop(void) {
     49     o->oAnimState++;
     50 
     51     if (cur_obj_wait_then_blink(200, 20)) {
     52         obj_mark_for_deletion(o);
     53     }
     54 
     55     bhv_coin_sparkles_init();
     56 }
     57 
     58 void bhv_spawned_coin_init(void) {
     59     o->oVelY = random_float() * 10.0f + 30.0f + o->oCoinBaseVelY;
     60     o->oForwardVel = random_float() * 10.0f;
     61     o->oMoveAngleYaw = random_u16();
     62 
     63     cur_obj_set_behavior(bhvYellowCoin);
     64     obj_set_hitbox(o, &sYellowCoinHitbox);
     65     cur_obj_become_intangible();
     66 }
     67 
     68 void bhv_spawned_coin_loop(void) {
     69     struct Surface *floor;
     70 
     71     cur_obj_update_floor_and_walls();
     72     cur_obj_if_hit_wall_bounce_away();
     73     cur_obj_move_standard(-62);
     74 
     75     if ((floor = o->oFloor) != NULL) {
     76         if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) {
     77             o->oSubAction = 1;
     78         }
     79         if (o->oSubAction == 1) {
     80             o->oBounciness = 0;
     81             if (floor->normal.y < 0.9) {
     82                 s16 sp1A = atan2s(floor->normal.z, floor->normal.x);
     83                 cur_obj_rotate_yaw_toward(sp1A, 0x400);
     84             }
     85         }
     86     }
     87 
     88     if (o->oTimer == 0) {
     89         cur_obj_play_sound_2(SOUND_GENERAL_COIN_SPURT);
     90     }
     91 
     92     if (o->oVelY < 0.0f) {
     93         cur_obj_become_tangible();
     94     }
     95 
     96     if (o->oMoveFlags & OBJ_MOVE_LANDED) {
     97 #ifndef VERSION_JP
     98         if (o->oMoveFlags & (OBJ_MOVE_ABOVE_DEATH_BARRIER | OBJ_MOVE_ABOVE_LAVA))
     99 #else
    100         if (o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA)
    101 #endif
    102         {
    103             obj_mark_for_deletion(o);
    104         }
    105     }
    106 
    107     if (o->oMoveFlags & OBJ_MOVE_BOUNCE) {
    108 #ifndef VERSION_JP
    109         if (o->oCoinNumBounceSoundPlayed < 5) {
    110 #endif
    111             cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP);
    112 #ifndef VERSION_JP
    113         }
    114         o->oCoinNumBounceSoundPlayed++;
    115 #endif
    116     }
    117 
    118     if (cur_obj_wait_then_blink(400, 20)) {
    119         obj_mark_for_deletion(o);
    120     }
    121 
    122     bhv_coin_sparkles_init();
    123 }
    124 
    125 void bhv_coin_formation_spawn_loop(void) {
    126     if (o->oTimer == 0) {
    127         cur_obj_set_behavior(bhvYellowCoin);
    128         obj_set_hitbox(o, &sYellowCoinHitbox);
    129         bhv_init_room();
    130 
    131         if (o->oCoinOnGround) {
    132             o->oPosY += 300.0f;
    133             cur_obj_update_floor_height();
    134 
    135             if (o->oPosY < o->oFloorHeight || o->oFloorHeight < FLOOR_LOWER_LIMIT_MISC) {
    136                 obj_mark_for_deletion(o);
    137             } else {
    138                 o->oPosY = o->oFloorHeight;
    139             }
    140         } else {
    141             cur_obj_update_floor_height();
    142 
    143             if (absf(o->oPosY - o->oFloorHeight) > 250.0f) {
    144                 cur_obj_set_model(MODEL_YELLOW_COIN_NO_SHADOW);
    145             }
    146         }
    147     } else {
    148         if (bhv_coin_sparkles_init()) {
    149             o->parentObj->oCoinCollectedFlags |= bit_shift_left(o->oBhvParams2ndByte);
    150         }
    151         o->oAnimState++;
    152     }
    153 
    154     if (o->parentObj->oAction == COIN_FORMATION_ACT_RESPAWN_COINS) {
    155         obj_mark_for_deletion(o);
    156     }
    157 }
    158 
    159 s16 sCoinArrowPositions[][2] = {
    160     { 0, -150 },
    161     { 0, -50 },
    162     { 0, 50 },
    163     { 0, 150 },
    164     { -50, 100 },
    165     { -100, 50 },
    166     { 50, 100 },
    167     { 100, 50 },
    168 };
    169 
    170 void spawn_coin_in_formation(s32 coinIndex, s32 coinFormationFlags) {
    171     struct Object *coinSpawner;
    172     Vec3i pos;
    173     s32 setSpawner = TRUE;
    174     s32 onGround = TRUE;
    175 
    176     pos[0] = pos[1] = pos[2] = 0;
    177 
    178     switch (coinFormationFlags & COIN_FORMATION_BP_FLAG_MASK) {
    179         case COIN_FORMATION_BP_LINE_HORIZONTAL:
    180             pos[2] = 160 * (coinIndex - 2);
    181             if (coinIndex > 4) {
    182                 setSpawner = FALSE;
    183             }
    184             break;
    185 
    186         case COIN_FORMATION_BP_LINE_VERTICAL:
    187             onGround = FALSE;
    188             pos[1] = 160 * coinIndex * 0.8; // 128 * coinIndex
    189             if (coinIndex > 4) {
    190                 setSpawner = FALSE;
    191             }
    192             break;
    193 
    194         case COIN_FORMATION_BP_RING_HORIZONTAL:
    195             pos[0] = sins(coinIndex << 13) * 300.0f;
    196             pos[2] = coss(coinIndex << 13) * 300.0f;
    197             break;
    198 
    199         case COIN_FORMATION_BP_RING_VERTICAL:
    200             onGround = FALSE;
    201             pos[0] = coss(coinIndex << 13) * 200.0f;
    202             pos[1] = sins(coinIndex << 13) * 200.0f + 200.0f;
    203             break;
    204 
    205         case COIN_FORMATION_BP_ARROW:
    206             pos[0] = sCoinArrowPositions[coinIndex][0];
    207             pos[2] = sCoinArrowPositions[coinIndex][1];
    208             break;
    209     }
    210 
    211     if (coinFormationFlags & COIN_FORMATION_BP_FLAG_FLYING) {
    212         onGround = FALSE;
    213     }
    214 
    215     if (setSpawner) {
    216         coinSpawner = spawn_object_relative(coinIndex, pos[0], pos[1], pos[2], o,
    217                                             MODEL_YELLOW_COIN, bhvCoinFormationSpawn);
    218         coinSpawner->oCoinOnGround = onGround;
    219     }
    220 }
    221 
    222 void bhv_coin_formation_init(void) {
    223     o->oCoinCollectedFlags = (o->oBhvParams >> 8) & 0xFF;
    224 }
    225 
    226 void bhv_coin_formation_loop(void) {
    227     s32 coinIndex;
    228 
    229     switch (o->oAction) {
    230         case COIN_FORMATION_ACT_SPAWN_COINS:
    231             if (o->oDistanceToMario < 2000.0f) {
    232                 for (coinIndex = 0; coinIndex <= 7; coinIndex++) {
    233                     if (!(o->oCoinCollectedFlags & (1 << coinIndex))) {
    234                         spawn_coin_in_formation(coinIndex, o->oBhvParams2ndByte);
    235                     }
    236                 }
    237                 o->oAction++;
    238             }
    239             break;
    240 
    241         case COIN_FORMATION_ACT_IDLE:
    242             if (o->oDistanceToMario > 2100.0f) {
    243                 o->oAction++;
    244             }
    245             break;
    246 
    247         case COIN_FORMATION_ACT_RESPAWN_COINS:
    248             o->oAction = COIN_FORMATION_ACT_SPAWN_COINS;
    249             break;
    250     }
    251 
    252     set_object_respawn_info_bits(o, o->oCoinCollectedFlags & 0xFF);
    253 }
    254 
    255 void coin_inside_boo_act_1(void) {
    256     cur_obj_update_floor_and_walls();
    257     cur_obj_if_hit_wall_bounce_away();
    258 
    259     if (o->oMoveFlags & OBJ_MOVE_BOUNCE) {
    260         cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP);
    261     }
    262 
    263     if (o->oTimer > 90 || (o->oMoveFlags & OBJ_MOVE_LANDED)) {
    264         obj_set_hitbox(o, &sYellowCoinHitbox);
    265         cur_obj_become_tangible();
    266         cur_obj_set_behavior(bhvYellowCoin);
    267     }
    268 
    269     cur_obj_move_standard(-30);
    270     bhv_coin_sparkles_init();
    271 
    272     if (cur_obj_has_model(MODEL_BLUE_COIN)) {
    273         o->oDamageOrCoinValue = 5;
    274     }
    275 
    276     if (cur_obj_wait_then_blink(400, 20)) {
    277         obj_mark_for_deletion(o);
    278     }
    279 }
    280 
    281 void coin_inside_boo_act_0(void) {
    282     s16 sp26;
    283     f32 sp20;
    284     struct Object *parent = o->parentObj;
    285 
    286     cur_obj_become_intangible();
    287 
    288     if (o->oTimer == 0 && gCurrLevelNum == LEVEL_BBH) {
    289         cur_obj_set_model(MODEL_BLUE_COIN);
    290         cur_obj_scale(0.7f);
    291     }
    292 
    293     obj_copy_pos(o, parent);
    294 
    295     if (parent->oBooDeathStatus == BOO_DEATH_STATUS_DYING) {
    296         o->oAction = 1;
    297         sp26 = gMarioObject->oMoveAngleYaw;
    298         sp20 = 3.0f;
    299         o->oVelX = sins(sp26) * sp20;
    300         o->oVelZ = coss(sp26) * sp20;
    301         o->oVelY = 35.0f;
    302     }
    303 }
    304 
    305 void (*sCoinInsideBooActions[])(void) = {
    306     coin_inside_boo_act_0,
    307     coin_inside_boo_act_1,
    308 };
    309 
    310 void bhv_coin_inside_boo_loop(void) {
    311     cur_obj_call_action_function(sCoinInsideBooActions);
    312 }
    313 
    314 void bhv_coin_sparkles_loop(void) {
    315     cur_obj_scale(0.6f);
    316 }
    317 
    318 void bhv_golden_coin_sparkles_loop(void) {
    319     struct Object *sparkles;
    320     UNUSED u8 filler[4];
    321     f32 sp24 = 30.0f;
    322 
    323     sparkles = spawn_object(o, MODEL_SPARKLES, bhvCoinSparkles);
    324     sparkles->oPosX += random_float() * sp24 - sp24 / 2;
    325     sparkles->oPosZ += random_float() * sp24 - sp24 / 2;
    326 }