sm64pc/src/game/behaviors/tweester.inc.c

157 lines
4.4 KiB
C
Raw Normal View History

2020-02-03 05:51:26 +00:00
/**
* 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.
*/
2019-08-25 04:46:40 +00:00
struct ObjectHitbox sTweesterHitbox = {
2020-02-03 05:51:26 +00:00
/* interactType: */ INTERACT_TORNADO,
/* downOffset: */ 0,
2019-08-25 04:46:40 +00:00
/* damageOrCoinValue: */ 0,
2020-02-03 05:51:26 +00:00
/* health: */ 0,
/* numLootCoins: */ 0,
/* radius: */ 1500,
/* height: */ 4000,
/* hurtboxRadius: */ 0,
/* hurtboxHeight: */ 0,
2019-08-25 04:46:40 +00:00
};
2020-02-03 05:51:26 +00:00
/**
* 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;
2019-08-25 04:46:40 +00:00
o->oForwardVel = 14.0f;
2020-02-03 05:51:26 +00:00
o->oFaceAngleYaw += dYaw;
2019-08-25 04:46:40 +00:00
}
2020-02-03 05:51:26 +00:00
/**
* 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) {
2019-08-25 04:46:40 +00:00
obj_become_tangible();
obj_set_pos_to_home();
obj_scale(0);
2020-02-03 05:51:26 +00:00
// 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.
2019-08-25 04:46:40 +00:00
if (o->oDistanceToMario < 1500.0f)
o->oSubAction++;
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
o->oTimer = 0;
} else {
2019-10-05 19:08:05 +00:00
PlaySound(SOUND_ENV_WIND1);
2020-02-03 05:51:26 +00:00
tweester_scale_and_move(o->oTimer / 60.0f);
2019-08-25 04:46:40 +00:00
if (o->oTimer > 59)
2020-02-03 05:51:26 +00:00
o->oAction = TWEESTER_ACT_CHASE;
2019-08-25 04:46:40 +00:00
}
}
2020-02-03 05:51:26 +00:00
/**
* 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 = obj_angle_to_home();
2019-10-05 19:08:05 +00:00
PlaySound(SOUND_ENV_WIND1);
2020-02-03 05:51:26 +00:00
if (obj_lateral_dist_from_mario_to_home() < activationRadius
&& o->oSubAction == TWEESTER_SUB_ACT_CHASE) {
2019-08-25 04:46:40 +00:00
o->oForwardVel = 20.0f;
obj_rotate_yaw_toward(o->oAngleToMario, 0x200);
print_debug_top_down_objectinfo("off ", 0);
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
if (gMarioStates->action == ACT_TWIRLING)
o->oSubAction++;
} else {
o->oForwardVel = 20.0f;
2020-02-03 05:51:26 +00:00
obj_rotate_yaw_toward(o->oAngleToHome, 0x200);
2019-08-25 04:46:40 +00:00
if (obj_lateral_dist_to_home() < 200.0f)
2020-02-03 05:51:26 +00:00
o->oAction = TWEESTER_ACT_HIDE;
2019-08-25 04:46:40 +00:00
}
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
if (o->oDistanceToMario > 3000.0f)
2020-02-03 05:51:26 +00:00
o->oAction = TWEESTER_ACT_HIDE;
2019-08-25 04:46:40 +00:00
obj_update_floor_and_walls();
2020-02-03 05:51:26 +00:00
if (o->oMoveFlags & OBJ_MOVE_HIT_WALL)
2019-08-25 04:46:40 +00:00
o->oMoveAngleYaw = o->oWallAngle;
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
obj_move_standard(60);
2020-02-03 05:51:26 +00:00
tweester_scale_and_move(1.0f);
spawn_object(o, MODEL_SAND_DUST, bhvTweesterSandParticle);
2019-08-25 04:46:40 +00:00
}
2020-02-03 05:51:26 +00:00
/**
* 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);
2019-08-25 04:46:40 +00:00
else {
obj_become_intangible();
if (obj_lateral_dist_from_mario_to_home() > 2500.0f)
2020-02-03 05:51:26 +00:00
o->oAction = TWEESTER_ACT_IDLE;
2019-08-25 04:46:40 +00:00
if (o->oTimer > 360)
2020-02-03 05:51:26 +00:00
o->oAction = TWEESTER_ACT_IDLE;
2019-08-25 04:46:40 +00:00
}
}
2020-02-03 05:51:26 +00:00
// Array of Tweester action functions.
void (*sTweesterActions[])(void) = { tweester_act_idle, tweester_act_chase, tweester_act_hide };
2019-08-25 04:46:40 +00:00
2020-02-03 05:51:26 +00:00
/**
* Loop behavior for Tweester.
* Loads the hitbox and calls its relevant action.
*/
2019-08-25 04:46:40 +00:00
void bhv_tweester_loop(void) {
set_object_hitbox(o, &sTweesterHitbox);
obj_call_action_function(sTweesterActions);
o->oInteractStatus = 0;
}
2020-02-03 05:51:26 +00:00
/**
* Loop behavior for the particles Tweesters create.
* Floats upwards semi-randomly.
*/
2019-08-25 04:46:40 +00:00
void bhv_tweester_sand_particle_loop(void) {
o->oMoveAngleYaw += 0x3700;
o->oForwardVel += 15.0f;
o->oPosY += 22.0f;
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
obj_scale(RandomFloat() + 1.0);
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
if (o->oTimer == 0) {
translate_object_xz_random(o, 100.0f);
o->oFaceAnglePitch = RandomU16();
o->oFaceAngleYaw = RandomU16();
}
2020-02-03 05:51:26 +00:00
2019-08-25 04:46:40 +00:00
if (o->oTimer > 15)
mark_object_for_deletion(o);
}