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

116 lines
4.6 KiB
C

// sl_walking_penguin.c.inc
struct SLWalkingPenguinStep {
s32 stepLength;
s32 anim;
f32 speed;
f32 animSpeed;
};
// The penguin follows a preset list of movements while walking forward.
struct SLWalkingPenguinStep sSLWalkingPenguinErraticSteps[] = {
{ 60, PENGUIN_ANIM_WALK, 6.0f, 1.0f }, // Walk forwards for 2 seconds
{ 30, PENGUIN_ANIM_IDLE, 0.0f, 1.0f }, // Stop for 1 second
{ 30, PENGUIN_ANIM_WALK, 12.0f, 2.0f }, // Walk forwards quickly for 1 second
{ 30, PENGUIN_ANIM_IDLE, 0.0f, 1.0f }, // Stop for 1 second
{ 30, PENGUIN_ANIM_WALK, -6.0f, 1.0f }, // Walk backwards for 1 second
{ 30, PENGUIN_ANIM_IDLE, 0.0f, 1.0f }, // Stop for 1 second
{ -1, 0, 0.0f, 0.0f } }; // Repeat
static s32 sl_walking_penguin_turn(void) {
// Stay still and use walking animation for the turn.
o->oForwardVel = 0.0f;
cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 1.0f);
// Turn around.
o->oAngleVelYaw = 0x400;
o->oMoveAngleYaw += o->oAngleVelYaw;
if (o->oTimer == 31)
return TRUE; // Finished turning
else
return FALSE;
}
void bhv_sl_walking_penguin_loop(void) {
f32 adjustedXPos, adjustedZPos;
f32 perpendicularOffset = 100.0f;
o->oAngleVelYaw = 0;
cur_obj_update_floor_and_walls();
switch (o->oAction) {
// Walk erratically across the ice bridge using preset steps.
case SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS:
if (o->oTimer == 0) {
// Initiate variables
o->oSLWalkingPenguinCurStep = 0;
o->oSLWalkingPenguinCurStepTimer = 0;
}
if (o->oSLWalkingPenguinCurStepTimer < sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength)
o->oSLWalkingPenguinCurStepTimer++;
else {
// Move to next step
o->oSLWalkingPenguinCurStepTimer = 0;
o->oSLWalkingPenguinCurStep++;
if (sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength < 0)
// Reached the end of the list, go back to the start
o->oSLWalkingPenguinCurStep = 0;
}
if (o->oPosX < 300.0f)
o->oAction++; // If reached the end of the bridge, turn around and head back.
else {
// Move and animate the penguin
o->oForwardVel = sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].speed;
cur_obj_init_animation_with_accel_and_sound(
sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].anim,
sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].animSpeed
);
}
break;
// At the end, turn around and prepare to head back across the bridge.
case SL_WALKING_PENGUIN_ACT_TURNING_BACK:
if (sl_walking_penguin_turn())
o->oAction++; // Finished turning
break;
// Walk back across the bridge at a constant speed.
case SL_WALKING_PENGUIN_ACT_RETURNING:
// Move and animate the penguin
o->oForwardVel = 12.0f;
cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 2.0f);
if (o->oPosX > 1700.0f)
o->oAction++; // If reached the start of the bridge, turn around.
break;
// At the start, turn around and prepare to walk erratically across the bridge.
case SL_WALKING_PENGUIN_ACT_TURNING_FORWARDS:
if (sl_walking_penguin_turn())
o->oAction = SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS; // Finished turning
break;
}
cur_obj_move_standard(-78);
if (!cur_obj_hide_if_mario_far_away_y(1000.0f))
play_penguin_walking_sound(PENGUIN_WALK_BIG);
// Adjust the position to get a point better lined up with the visual model, for stopping the wind.
// The new point is 60 units behind the penguin and 100 units perpedicularly, away from the snowman.
adjustedXPos = o->oPosX + sins(0xDBB0) * 60.0f; // 0xDBB0 = -51 degrees, the angle the penguin is facing
adjustedZPos = o->oPosZ + coss(0xDBB0) * 60.0f;
adjustedXPos += perpendicularOffset * sins(0x1BB0); // 0x1BB0 = 39 degrees, perpendicular to the penguin
adjustedZPos += perpendicularOffset * coss(0x1BB0);
o->oSLWalkingPenguinWindCollisionXPos = adjustedXPos;
o->oSLWalkingPenguinWindCollisionZPos = adjustedZPos;
print_debug_bottom_up("x %d", o->oPosX);
print_debug_bottom_up("z %d", o->oPosZ);
}