157 lines
4.5 KiB
C
157 lines
4.5 KiB
C
/**
|
|
* Behavior file for bhvTweester and bhvTweesterSandParticle
|
|
* Tweester swaps between twhree action- an idle action, a chasing
|
|
* Mario action, and an action that hides it. At certain times the
|
|
* Tweester spawns the sand particles also in this file.
|
|
*/
|
|
|
|
struct ObjectHitbox sTweesterHitbox = {
|
|
/* interactType: */ INTERACT_TORNADO,
|
|
/* downOffset: */ 0,
|
|
/* damageOrCoinValue: */ 0,
|
|
/* health: */ 0,
|
|
/* numLootCoins: */ 0,
|
|
/* radius: */ 1500,
|
|
/* height: */ 4000,
|
|
/* hurtboxRadius: */ 0,
|
|
/* hurtboxHeight: */ 0,
|
|
};
|
|
|
|
/**
|
|
* Controls the scaling of the tweester as well as
|
|
* its forward velocity.
|
|
*/
|
|
void tweester_scale_and_move(f32 preScale) {
|
|
s16 dYaw = 0x2C00;
|
|
f32 scale = preScale * 0.4;
|
|
|
|
o->header.gfx.scale[0]
|
|
= (( coss(o->oTweesterScaleTimer) + 1.0) * 0.5 * 0.3 + 1.0) * scale;
|
|
o->header.gfx.scale[1]
|
|
= ((-coss(o->oTweesterScaleTimer) + 1.0) * 0.5 * 0.5 + 0.5) * scale;
|
|
o->header.gfx.scale[2]
|
|
= (( coss(o->oTweesterScaleTimer) + 1.0) * 0.5 * 0.3 + 1.0) * scale;
|
|
|
|
o->oTweesterScaleTimer += 0x200;
|
|
o->oForwardVel = 14.0f;
|
|
o->oFaceAngleYaw += dYaw;
|
|
}
|
|
|
|
/**
|
|
* Tweester's idle action. Basically stays in active until Mario enters a 1500
|
|
* radius, at which point it appears and grows for 60 frames at which point it
|
|
* it enters the chasing action.
|
|
*/
|
|
void tweester_act_idle(void) {
|
|
if (o->oSubAction == TWEESTER_SUB_ACT_WAIT) {
|
|
cur_obj_become_tangible();
|
|
cur_obj_set_pos_to_home();
|
|
cur_obj_scale(0);
|
|
|
|
// Hard to have any idea of this purpose, only set here.
|
|
o->oTweesterUnused = 0;
|
|
|
|
// If Mario is within range, change to the growth sub-action.
|
|
if (o->oDistanceToMario < 1500.0f)
|
|
o->oSubAction++;
|
|
|
|
o->oTimer = 0;
|
|
} else {
|
|
cur_obj_play_sound_1(SOUND_ENV_WIND1);
|
|
tweester_scale_and_move(o->oTimer / 60.0f);
|
|
if (o->oTimer > 59)
|
|
o->oAction = TWEESTER_ACT_CHASE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Action where the tweester "chases" Mario.
|
|
* After Mario is twirling, then return home.
|
|
*/
|
|
void tweester_act_chase(void) {
|
|
f32 activationRadius = o->oBehParams2ndByte * 100;
|
|
|
|
o->oAngleToHome = cur_obj_angle_to_home();
|
|
cur_obj_play_sound_1(SOUND_ENV_WIND1);
|
|
|
|
if (cur_obj_lateral_dist_from_mario_to_home() < activationRadius
|
|
&& o->oSubAction == TWEESTER_SUB_ACT_CHASE) {
|
|
|
|
o->oForwardVel = 20.0f;
|
|
cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x200);
|
|
print_debug_top_down_objectinfo("off ", 0);
|
|
|
|
if (gMarioStates->action == ACT_TWIRLING)
|
|
o->oSubAction++;
|
|
} else {
|
|
o->oForwardVel = 20.0f;
|
|
cur_obj_rotate_yaw_toward(o->oAngleToHome, 0x200);
|
|
|
|
if (cur_obj_lateral_dist_to_home() < 200.0f)
|
|
o->oAction = TWEESTER_ACT_HIDE;
|
|
}
|
|
|
|
if (o->oDistanceToMario > 3000.0f)
|
|
o->oAction = TWEESTER_ACT_HIDE;
|
|
|
|
cur_obj_update_floor_and_walls();
|
|
if (o->oMoveFlags & OBJ_MOVE_HIT_WALL)
|
|
o->oMoveAngleYaw = o->oWallAngle;
|
|
|
|
cur_obj_move_standard(60);
|
|
tweester_scale_and_move(1.0f);
|
|
spawn_object(o, MODEL_SAND_DUST, bhvTweesterSandParticle);
|
|
}
|
|
|
|
/**
|
|
* Shrinks the tweester until it is invisible, then returns to the idle
|
|
* action if Mario is 2500 units away or 12 seconds passed.
|
|
*/
|
|
void tweester_act_hide(void) {
|
|
f32 shrinkTimer = 60.0f - o->oTimer;
|
|
|
|
if (shrinkTimer >= 0.0f)
|
|
tweester_scale_and_move(shrinkTimer / 60.0f);
|
|
else {
|
|
cur_obj_become_intangible();
|
|
if (cur_obj_lateral_dist_from_mario_to_home() > 2500.0f)
|
|
o->oAction = TWEESTER_ACT_IDLE;
|
|
if (o->oTimer > 360)
|
|
o->oAction = TWEESTER_ACT_IDLE;
|
|
}
|
|
}
|
|
|
|
// Array of Tweester action functions.
|
|
void (*sTweesterActions[])(void) = { tweester_act_idle, tweester_act_chase, tweester_act_hide };
|
|
|
|
/**
|
|
* Loop behavior for Tweester.
|
|
* Loads the hitbox and calls its relevant action.
|
|
*/
|
|
void bhv_tweester_loop(void) {
|
|
obj_set_hitbox(o, &sTweesterHitbox);
|
|
cur_obj_call_action_function(sTweesterActions);
|
|
o->oInteractStatus = 0;
|
|
}
|
|
|
|
/**
|
|
* Loop behavior for the particles Tweesters create.
|
|
* Floats upwards semi-randomly.
|
|
*/
|
|
void bhv_tweester_sand_particle_loop(void) {
|
|
o->oMoveAngleYaw += 0x3700;
|
|
o->oForwardVel += 15.0f;
|
|
o->oPosY += 22.0f;
|
|
|
|
cur_obj_scale(random_float() + 1.0);
|
|
|
|
if (o->oTimer == 0) {
|
|
obj_translate_xz_random(o, 100.0f);
|
|
o->oFaceAnglePitch = random_u16();
|
|
o->oFaceAngleYaw = random_u16();
|
|
}
|
|
|
|
if (o->oTimer > 15)
|
|
obj_mark_for_deletion(o);
|
|
}
|