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

271 lines
7.1 KiB
C

// hoot.c.inc
void bhv_hoot_init(void) {
cur_obj_init_animation(0);
o->oHomeX = o->oPosX + 800.0f;
o->oHomeY = o->oPosY - 150.0f;
o->oHomeZ = o->oPosZ + 300.0f;
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
cur_obj_become_intangible();
}
// sp28 = arg0
// sp2c = arg1
f32 hoot_find_next_floor(struct FloorGeometry **arg0, f32 arg1) {
f32 sp24 = arg1 * sins(o->oMoveAngleYaw) + o->oPosX;
UNUSED f32 sp20 = o->oPosY;
f32 sp1c = arg1 * coss(o->oMoveAngleYaw) + o->oPosZ;
f32 floorY = find_floor_height_and_data(sp24, 10000.0f, sp1c, arg0);
return floorY;
}
void hoot_floor_bounce(void) {
struct FloorGeometry *sp1c;
f32 floorY;
floorY = hoot_find_next_floor(&sp1c, 375.0f);
if (floorY + 75.0f > o->oPosY)
o->oMoveAnglePitch -= 3640.8888;
floorY = hoot_find_next_floor(&sp1c, 200.0f);
if (floorY + 125.0f > o->oPosY)
o->oMoveAnglePitch -= 7281.7776;
floorY = hoot_find_next_floor(&sp1c, 0);
if (floorY + 125.0f > o->oPosY)
o->oPosY = floorY + 125.0f;
if (o->oMoveAnglePitch < -21845.3328)
o->oMoveAnglePitch = -21845;
}
// sp30 = fastOscY
// sp34 = speed
void hoot_free_step(s16 fastOscY, s32 speed) {
struct FloorGeometry *sp2c;
s16 yaw = o->oMoveAngleYaw;
s16 pitch = o->oMoveAnglePitch;
s16 sp26 = o->header.gfx.unk38.animFrame;
f32 xPrev = o->oPosX;
f32 zPrev = o->oPosZ;
f32 hSpeed;
o->oVelY = sins(pitch) * speed;
hSpeed = coss(pitch) * speed;
o->oVelX = sins(yaw) * hSpeed;
o->oVelZ = coss(yaw) * hSpeed;
o->oPosX += o->oVelX;
if (fastOscY == 0)
o->oPosY -= o->oVelY + coss((s32)(sp26 * 3276.8)) * 50.0f / 4;
else
o->oPosY -= o->oVelY + coss((s32)(sp26 * 6553.6)) * 50.0f / 4;
o->oPosZ += o->oVelZ;
find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &sp2c);
if (sp2c == NULL) {
o->oPosX = xPrev;
o->oPosZ = zPrev;
}
if (sp26 == 0)
cur_obj_play_sound_2(SOUND_GENERAL_SWISH_WATER);
}
void hoot_player_set_yaw(void) {
s16 stickX = gPlayer3Controller->rawStickX;
s16 stickY = gPlayer3Controller->rawStickY;
UNUSED s16 pitch = o->oMoveAnglePitch;
if (stickX < 10 && stickX >= -9)
stickX = 0;
if (stickY < 10 && stickY >= -9)
stickY = 0;
o->oMoveAngleYaw -= 5 * stickX;
}
// sp28 = speed
// sp2c = xPrev
// sp30 = zPrev
void hoot_carry_step(s32 speed, UNUSED f32 xPrev, UNUSED f32 zPrev) {
s16 yaw = o->oMoveAngleYaw;
s16 pitch = o->oMoveAnglePitch;
s16 sp22 = o->header.gfx.unk38.animFrame;
f32 hSpeed;
o->oVelY = sins(pitch) * speed;
hSpeed = coss(pitch) * speed;
o->oVelX = sins(yaw) * hSpeed;
o->oVelZ = coss(yaw) * hSpeed;
o->oPosX += o->oVelX;
o->oPosY -= o->oVelY + coss((s32)(sp22 * 6553.6)) * 50.0f / 4;
o->oPosZ += o->oVelZ;
if (sp22 == 0)
cur_obj_play_sound_2(SOUND_GENERAL_SWISH_WATER);
}
// sp48 = xPrev
// sp4c = yPrev
// sp50 = zPrev
void hoot_surface_collision(f32 xPrev, UNUSED f32 yPrev, f32 zPrev) {
struct FloorGeometry *sp44;
struct WallCollisionData hitbox;
f32 floorY;
hitbox.x = o->oPosX;
hitbox.y = o->oPosY;
hitbox.z = o->oPosZ;
hitbox.offsetY = 10.0;
hitbox.radius = 50.0;
if (find_wall_collisions(&hitbox) != 0) {
o->oPosX = hitbox.x;
o->oPosY = hitbox.y;
o->oPosZ = hitbox.z;
gMarioObject->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */
}
floorY = find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &sp44);
if (sp44 == NULL) {
o->oPosX = xPrev;
o->oPosZ = zPrev;
return;
}
if (absf_2(o->oPosX) > 8000.0f)
o->oPosX = xPrev;
if (absf_2(o->oPosZ) > 8000.0f)
o->oPosZ = zPrev;
if (floorY + 125.0f > o->oPosY)
o->oPosY = floorY + 125.0f;
}
// sp28 = xPrev
// sp2c = zPrev
void hoot_act_ascent(f32 xPrev, f32 zPrev) {
f32 negX = 0 - o->oPosX;
f32 negZ = 0 - o->oPosZ;
s16 angleToOrigin = atan2s(negZ, negX);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, angleToOrigin, 0x500);
o->oMoveAnglePitch = 0xCE38;
if (o->oTimer >= 29) {
cur_obj_play_sound_1(SOUND_ENV_WIND2);
o->header.gfx.unk38.animFrame = 1;
}
if (o->oPosY > 6500.0f)
o->oAction = HOOT_ACT_CARRY;
hoot_carry_step(60, xPrev, zPrev);
}
void hoot_action_loop(void) {
f32 xPrev = o->oPosX;
f32 yPrev = o->oPosY;
f32 zPrev = o->oPosZ;
switch (o->oAction) {
case HOOT_ACT_ASCENT:
hoot_act_ascent(xPrev, zPrev);
break;
case HOOT_ACT_CARRY:
hoot_player_set_yaw();
o->oMoveAnglePitch = 0x71C;
if (o->oPosY < 2700.0f) {
set_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_045)) {
clear_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
o->oAction = HOOT_ACT_TIRED;
}
}
hoot_carry_step(20, xPrev, zPrev);
break;
case HOOT_ACT_TIRED:
hoot_player_set_yaw();
o->oMoveAnglePitch = 0;
hoot_carry_step(20, xPrev, zPrev);
if (o->oTimer >= 61)
gMarioObject->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */
break;
}
hoot_surface_collision(xPrev, yPrev, zPrev);
}
void hoot_turn_to_home(void) {
f32 homeDistX = o->oHomeX - o->oPosX;
f32 homeDistY = o->oHomeY - o->oPosY;
f32 homeDistZ = o->oHomeZ - o->oPosZ;
s16 hAngleToHome = atan2s(homeDistZ, homeDistX);
s16 vAngleToHome = atan2s(sqrtf(homeDistX * homeDistX + homeDistZ * homeDistZ), -homeDistY);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, hAngleToHome, 0x140);
o->oMoveAnglePitch = approach_s16_symmetric(o->oMoveAnglePitch, vAngleToHome, 0x140);
}
void hoot_awake_loop(void) {
if (o->oInteractStatus == INT_STATUS_HOOT_GRABBED_BY_MARIO) {
hoot_action_loop();
cur_obj_init_animation(1);
} else {
cur_obj_init_animation(0);
hoot_turn_to_home();
hoot_floor_bounce();
hoot_free_step(0, 10);
o->oAction = 0;
o->oTimer = 0;
}
set_object_visibility(o, 2000);
}
void bhv_hoot_loop(void) {
switch (o->oHootAvailability) {
case HOOT_AVAIL_ASLEEP_IN_TREE:
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 50)) {
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
o->oHootAvailability = HOOT_AVAIL_WANTS_TO_TALK;
}
break;
case HOOT_AVAIL_WANTS_TO_TALK:
hoot_awake_loop();
if (set_mario_npc_dialog(2) == 2 && cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_044)) {
set_mario_npc_dialog(0);
cur_obj_become_tangible();
o->oHootAvailability = HOOT_AVAIL_READY_TO_FLY;
}
break;
case HOOT_AVAIL_READY_TO_FLY:
hoot_awake_loop();
break;
}
}