hoot.inc.c (7343B)
1 // hoot.inc.c 2 3 void bhv_hoot_init(void) { 4 cur_obj_init_animation(0); 5 6 o->oHomeX = o->oPosX + 800.0f; 7 o->oHomeY = o->oPosY - 150.0f; 8 o->oHomeZ = o->oPosZ + 300.0f; 9 o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; 10 11 cur_obj_become_intangible(); 12 } 13 14 f32 hoot_find_next_floor(struct FloorGeometry **floorGeo, f32 arg1) { 15 f32 sp24 = arg1 * sins(o->oMoveAngleYaw) + o->oPosX; 16 UNUSED f32 sp20 = o->oPosY; 17 f32 sp1c = arg1 * coss(o->oMoveAngleYaw) + o->oPosZ; 18 f32 floorY = find_floor_height_and_data(sp24, 10000.0f, sp1c, floorGeo); 19 20 return floorY; 21 } 22 23 void hoot_floor_bounce(void) { 24 struct FloorGeometry *floorGeo; 25 f32 floorY; 26 27 floorY = hoot_find_next_floor(&floorGeo, 375.0f); 28 if (floorY + 75.0f > o->oPosY) { 29 o->oMoveAnglePitch -= 3640.8888; 30 } 31 32 floorY = hoot_find_next_floor(&floorGeo, 200.0f); 33 if (floorY + 125.0f > o->oPosY) { 34 o->oMoveAnglePitch -= 7281.7776; 35 } 36 37 floorY = hoot_find_next_floor(&floorGeo, 0); 38 if (floorY + 125.0f > o->oPosY) { 39 o->oPosY = floorY + 125.0f; 40 } 41 42 if (o->oMoveAnglePitch < -21845.3328) { 43 o->oMoveAnglePitch = -21845; 44 } 45 } 46 47 void hoot_free_step(s16 fastOscY, s32 speed) { 48 struct FloorGeometry *floorGeo; 49 s16 yaw = o->oMoveAngleYaw; 50 s16 pitch = o->oMoveAnglePitch; 51 s16 animFrame = o->header.gfx.animInfo.animFrame; 52 f32 xPrev = o->oPosX; 53 f32 zPrev = o->oPosZ; 54 f32 hSpeed; 55 56 o->oVelY = sins(pitch) * speed; 57 hSpeed = coss(pitch) * speed; 58 o->oVelX = sins(yaw) * hSpeed; 59 o->oVelZ = coss(yaw) * hSpeed; 60 61 o->oPosX += o->oVelX; 62 if (fastOscY == 0) { 63 o->oPosY -= o->oVelY + coss((s32)(animFrame * 3276.8)) * 50.0f / 4; 64 } else { 65 o->oPosY -= o->oVelY + coss((s32)(animFrame * 6553.6)) * 50.0f / 4; 66 } 67 o->oPosZ += o->oVelZ; 68 69 find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &floorGeo); 70 if (floorGeo == NULL) { 71 o->oPosX = xPrev; 72 o->oPosZ = zPrev; 73 } 74 75 if (animFrame == 0) { 76 cur_obj_play_sound_2(SOUND_GENERAL_SWISH_WATER); 77 } 78 } 79 80 void hoot_player_set_yaw(void) { 81 s16 stickX = gPlayer3Controller->rawStickX; 82 s16 stickY = gPlayer3Controller->rawStickY; 83 UNUSED s16 pitch = o->oMoveAnglePitch; 84 85 if (stickX < 10 && stickX >= -9) { 86 stickX = 0; 87 } 88 89 if (stickY < 10 && stickY >= -9) { 90 stickY = 0; 91 } 92 93 o->oMoveAngleYaw -= 5 * stickX; 94 } 95 96 void hoot_carry_step(s32 speed, UNUSED f32 xPrev, UNUSED f32 zPrev) { 97 s16 yaw = o->oMoveAngleYaw; 98 s16 pitch = o->oMoveAnglePitch; 99 s16 animFrame = o->header.gfx.animInfo.animFrame; 100 f32 hSpeed; 101 102 o->oVelY = sins(pitch) * speed; 103 hSpeed = coss(pitch) * speed; 104 o->oVelX = sins(yaw) * hSpeed; 105 o->oVelZ = coss(yaw) * hSpeed; 106 107 o->oPosX += o->oVelX; 108 o->oPosY -= o->oVelY + coss((s32)(animFrame * 6553.6)) * 50.0f / 4; 109 o->oPosZ += o->oVelZ; 110 111 if (animFrame == 0) { 112 cur_obj_play_sound_2(SOUND_GENERAL_SWISH_WATER); 113 } 114 } 115 116 void hoot_surface_collision(f32 xPrev, UNUSED f32 yPrev, f32 zPrev) { 117 struct FloorGeometry *floorGeo; 118 struct WallCollisionData hitbox; 119 f32 floorY; 120 121 hitbox.x = o->oPosX; 122 hitbox.y = o->oPosY; 123 hitbox.z = o->oPosZ; 124 hitbox.offsetY = 10.0; 125 hitbox.radius = 50.0; 126 127 if (find_wall_collisions(&hitbox) != 0) { 128 o->oPosX = hitbox.x; 129 o->oPosY = hitbox.y; 130 o->oPosZ = hitbox.z; 131 gMarioObject->oInteractStatus |= INT_STATUS_MARIO_UNK7; 132 } 133 134 floorY = find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &floorGeo); 135 if (floorGeo == NULL) { 136 o->oPosX = xPrev; 137 o->oPosZ = zPrev; 138 return; 139 } 140 141 if (absf_2(o->oPosX) > 8000.0f) { 142 o->oPosX = xPrev; 143 } 144 145 if (absf_2(o->oPosZ) > 8000.0f) { 146 o->oPosZ = zPrev; 147 } 148 149 if (floorY + 125.0f > o->oPosY) { 150 o->oPosY = floorY + 125.0f; 151 } 152 } 153 154 void hoot_act_ascent(f32 xPrev, f32 zPrev) { 155 f32 negX = 0 - o->oPosX; 156 f32 negZ = 0 - o->oPosZ; 157 s16 angleToOrigin = atan2s(negZ, negX); 158 159 o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, angleToOrigin, 0x500); 160 o->oMoveAnglePitch = 0xCE38; 161 162 if (o->oTimer >= 29) { 163 cur_obj_play_sound_1(SOUND_ENV_WIND2); 164 o->header.gfx.animInfo.animFrame = 1; 165 } 166 167 if (o->oPosY > 6500.0f) { 168 o->oAction = HOOT_ACT_CARRY; 169 } 170 171 hoot_carry_step(60, xPrev, zPrev); 172 } 173 174 void hoot_action_loop(void) { 175 f32 xPrev = o->oPosX; 176 f32 yPrev = o->oPosY; 177 f32 zPrev = o->oPosZ; 178 179 switch (o->oAction) { 180 case HOOT_ACT_ASCENT: 181 hoot_act_ascent(xPrev, zPrev); 182 break; 183 184 case HOOT_ACT_CARRY: 185 hoot_player_set_yaw(); 186 187 o->oMoveAnglePitch = 0x71C; 188 189 if (o->oPosY < 2700.0f) { 190 set_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS); 191 192 if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_045) != 0) { 193 clear_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS); 194 o->oAction = HOOT_ACT_TIRED; 195 } 196 } 197 198 hoot_carry_step(20, xPrev, zPrev); 199 break; 200 201 case HOOT_ACT_TIRED: 202 hoot_player_set_yaw(); 203 204 o->oMoveAnglePitch = 0; 205 206 hoot_carry_step(20, xPrev, zPrev); 207 208 if (o->oTimer > 60) { 209 gMarioObject->oInteractStatus |= INT_STATUS_MARIO_UNK7; 210 } 211 break; 212 } 213 214 hoot_surface_collision(xPrev, yPrev, zPrev); 215 } 216 217 void hoot_turn_to_home(void) { 218 f32 homeDistX = o->oHomeX - o->oPosX; 219 f32 homeDistY = o->oHomeY - o->oPosY; 220 f32 homeDistZ = o->oHomeZ - o->oPosZ; 221 s16 hAngleToHome = atan2s(homeDistZ, homeDistX); 222 s16 vAngleToHome = atan2s(sqrtf(homeDistX * homeDistX + homeDistZ * homeDistZ), -homeDistY); 223 224 o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, hAngleToHome, 0x140); 225 o->oMoveAnglePitch = approach_s16_symmetric(o->oMoveAnglePitch, vAngleToHome, 0x140); 226 } 227 228 void hoot_awake_loop(void) { 229 if (o->oInteractStatus == TRUE) { //! Note: Not a flag, treated as a TRUE/FALSE statement 230 hoot_action_loop(); 231 cur_obj_init_animation(1); 232 } else { 233 cur_obj_init_animation(0); 234 235 hoot_turn_to_home(); 236 hoot_floor_bounce(); 237 hoot_free_step(0, 10); 238 239 o->oAction = 0; 240 o->oTimer = 0; 241 } 242 243 set_object_visibility(o, 2000); 244 } 245 246 void bhv_hoot_loop(void) { 247 switch (o->oHootAvailability) { 248 case HOOT_AVAIL_ASLEEP_IN_TREE: 249 if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 50)) { 250 o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; 251 o->oHootAvailability = HOOT_AVAIL_WANTS_TO_TALK; 252 } 253 break; 254 255 case HOOT_AVAIL_WANTS_TO_TALK: 256 hoot_awake_loop(); 257 258 if (set_mario_npc_dialog(MARIO_DIALOG_LOOK_UP) == MARIO_DIALOG_STATUS_SPEAK 259 && cutscene_object_with_dialog(CUTSCENE_DIALOG, o, DIALOG_044)) { 260 set_mario_npc_dialog(MARIO_DIALOG_STOP); 261 262 cur_obj_become_tangible(); 263 264 o->oHootAvailability = HOOT_AVAIL_READY_TO_FLY; 265 } 266 break; 267 268 case HOOT_AVAIL_READY_TO_FLY: 269 hoot_awake_loop(); 270 break; 271 } 272 }