sm64

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

tweester.inc.c (4741B)


      1 
      2 /**
      3  * Behavior file for bhvTweester and bhvTweesterSandParticle
      4  * Tweester swaps between twhree action- an idle action, a chasing
      5  * Mario action, and an action that hides it. At certain times the
      6  * Tweester spawns the sand particles also in this file.
      7  */
      8 
      9 struct ObjectHitbox sTweesterHitbox = {
     10     /* interactType:      */ INTERACT_TORNADO,
     11     /* downOffset:        */ 0,
     12     /* damageOrCoinValue: */ 0,
     13     /* health:            */ 0,
     14     /* numLootCoins:      */ 0,
     15     /* radius:            */ 1500,
     16     /* height:            */ 4000,
     17     /* hurtboxRadius:     */ 0,
     18     /* hurtboxHeight:     */ 0,
     19 };
     20 
     21 /**
     22  * Controls the scaling of the tweester as well as
     23  * its forward velocity.
     24  */
     25 void tweester_scale_and_move(f32 preScale) {
     26     s16 dYaw  = 0x2C00;
     27     f32 scale = preScale * 0.4;
     28 
     29     o->header.gfx.scale[0]
     30         = (( coss(o->oTweesterScaleTimer) + 1.0) * 0.5 * 0.3 + 1.0) * scale;
     31     o->header.gfx.scale[1]
     32         = ((-coss(o->oTweesterScaleTimer) + 1.0) * 0.5 * 0.5 + 0.5) * scale;
     33     o->header.gfx.scale[2]
     34         = (( coss(o->oTweesterScaleTimer) + 1.0) * 0.5 * 0.3 + 1.0) * scale;
     35 
     36     o->oTweesterScaleTimer += 0x200;
     37     o->oForwardVel = 14.0f;
     38     o->oFaceAngleYaw += dYaw;
     39 }
     40 
     41 /**
     42  * Tweester's idle action. Basically stays in active until Mario enters a 1500
     43  * radius, at which point it appears and grows for 60 frames at which point it
     44  * it enters the chasing action.
     45  */
     46 void tweester_act_idle(void) {
     47     if (o->oSubAction == TWEESTER_SUB_ACT_WAIT) {
     48         cur_obj_become_tangible();
     49         cur_obj_set_pos_to_home();
     50         cur_obj_scale(0.0f);
     51 
     52         // Hard to have any idea of this purpose, only set here.
     53         o->oTweesterUnused = 0;
     54 
     55         // If Mario is within range, change to the growth sub-action.
     56         if (o->oDistanceToMario < 1500.0f) {
     57             o->oSubAction++;
     58         }
     59 
     60         o->oTimer = 0;
     61     } else {
     62         cur_obj_play_sound_1(SOUND_ENV_WIND1);
     63         tweester_scale_and_move(o->oTimer / 60.0f);
     64         if (o->oTimer >= 60) {
     65             o->oAction = TWEESTER_ACT_CHASE;
     66         }
     67     }
     68 }
     69 
     70 /**
     71  * Action where the tweester "chases" Mario.
     72  * After Mario is twirling, then return home.
     73  */
     74 void tweester_act_chase(void) {
     75     f32 activationRadius = o->oBhvParams2ndByte * 100;
     76 
     77     o->oAngleToHome = cur_obj_angle_to_home();
     78     cur_obj_play_sound_1(SOUND_ENV_WIND1);
     79 
     80     if (cur_obj_lateral_dist_from_mario_to_home() < activationRadius
     81         && o->oSubAction == TWEESTER_SUB_ACT_CHASE) {
     82 
     83         o->oForwardVel = 20.0f;
     84         cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x200);
     85         print_debug_top_down_objectinfo("off ", 0);
     86 
     87         if (gMarioStates[0].action == ACT_TWIRLING) {
     88             o->oSubAction++;
     89         }
     90     } else {
     91         o->oForwardVel = 20.0f;
     92         cur_obj_rotate_yaw_toward(o->oAngleToHome, 0x200);
     93 
     94         if (cur_obj_lateral_dist_to_home() < 200.0f) {
     95             o->oAction = TWEESTER_ACT_HIDE;
     96         }
     97     }
     98 
     99     if (o->oDistanceToMario > 3000.0f) {
    100         o->oAction = TWEESTER_ACT_HIDE;
    101     }
    102 
    103     cur_obj_update_floor_and_walls();
    104     if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
    105         o->oMoveAngleYaw = o->oWallAngle;
    106     }
    107 
    108     cur_obj_move_standard(60);
    109     tweester_scale_and_move(1.0f);
    110     spawn_object(o, MODEL_SAND_DUST, bhvTweesterSandParticle);
    111 }
    112 
    113 /**
    114  * Shrinks the tweester until it is invisible, then returns to the idle
    115  * action if Mario is 2500 units away or 12 seconds passed.
    116  */
    117 void tweester_act_hide(void) {
    118     f32 shrinkTimer = 60.0f - o->oTimer;
    119 
    120     if (shrinkTimer >= 0.0f) {
    121         tweester_scale_and_move(shrinkTimer / 60.0f);
    122     } else {
    123         cur_obj_become_intangible();
    124         if (cur_obj_lateral_dist_from_mario_to_home() > 2500.0f) {
    125             o->oAction = TWEESTER_ACT_IDLE;
    126         }
    127         if (o->oTimer > 360) {
    128             o->oAction = TWEESTER_ACT_IDLE;
    129         }
    130     }
    131 }
    132 
    133 // Array of Tweester action functions.
    134 void (*sTweesterActions[])(void) = {
    135     tweester_act_idle,
    136     tweester_act_chase,
    137     tweester_act_hide,
    138 };
    139 
    140 /**
    141  * Loop behavior for Tweester.
    142  * Loads the hitbox and calls its relevant action.
    143  */
    144 void bhv_tweester_loop(void) {
    145     obj_set_hitbox(o, &sTweesterHitbox);
    146     cur_obj_call_action_function(sTweesterActions);
    147     o->oInteractStatus = 0;
    148 }
    149 
    150 /**
    151  * Loop behavior for the particles Tweesters create.
    152  * Floats upwards semi-randomly.
    153  */
    154 void bhv_tweester_sand_particle_loop(void) {
    155     o->oMoveAngleYaw += 0x3700;
    156     o->oForwardVel += 15.0f;
    157     o->oPosY += 22.0f;
    158 
    159     cur_obj_scale(random_float() + 1.0);
    160 
    161     if (o->oTimer == 0) {
    162         obj_translate_xz_random(o, 100.0f);
    163         o->oFaceAnglePitch = random_u16();
    164         o->oFaceAngleYaw = random_u16();
    165     }
    166 
    167     if (o->oTimer > 15) {
    168         obj_mark_for_deletion(o);
    169     }
    170 }