intro_lakitu.inc.c (8438B)
1 2 /** 3 * @file intro_lakitu.inc.c 4 * This file implements lakitu's behvaior during the intro cutscene. 5 * It's also used during the ending cutscene. 6 */ 7 8 /** 9 * Add the camera's position to `offset`, rotate the point to be relative to the camera's focus, then 10 * set lakitu's location. 11 */ 12 void intro_lakitu_set_offset_from_camera(struct Object *obj, Vec3f offset) { 13 f32 dist; 14 Vec3s focusAngles; 15 s16 offsetPitch, offsetYaw; 16 17 vec3f_add(offset, gCamera->pos); 18 vec3f_get_dist_and_angle(gCamera->pos, gCamera->focus, 19 &dist, &focusAngles[0], &focusAngles[1]); 20 vec3f_get_dist_and_angle(gCamera->pos, offset, &dist, &offsetPitch, &offsetYaw); 21 vec3f_set_dist_and_angle(gCamera->pos, offset, dist, 22 focusAngles[0] + offsetPitch, focusAngles[1] + offsetYaw); 23 vec3f_to_object_pos(obj, offset); 24 } 25 26 void intro_lakitu_set_focus(struct Object *obj, Vec3f newFocus) { 27 UNUSED u8 filler1[12]; 28 Vec3f origin; 29 f32 dist; 30 s16 pitch, yaw; 31 UNUSED u8 filler2[4]; 32 33 // newFocus is an offset from lakitu's origin, not a point in the world. 34 vec3f_set(origin, 0.0f, 0.0f, 0.0f); 35 vec3f_get_dist_and_angle(origin, newFocus, &dist, &pitch, &yaw); 36 37 obj->oFaceAnglePitch = pitch; 38 obj->oFaceAngleYaw = yaw; 39 } 40 41 /** 42 * Move lakitu along the spline `offset`, relative to the camera, and face him towards the corresponding 43 * location along the spline `focus`. 44 */ 45 s32 intro_lakitu_set_pos_and_focus(struct Object *obj, struct CutsceneSplinePoint offset[], 46 struct CutsceneSplinePoint focus[]) { 47 Vec3f newOffset, newFocus; 48 s32 splineFinished = 0; 49 s16 splineSegment = obj->oIntroLakituSplineSegment; 50 51 if ((move_point_along_spline(newFocus, offset, &splineSegment, 52 &obj->oIntroLakituSplineSegmentProgress) == 1) 53 || (move_point_along_spline(newOffset, focus, &splineSegment, 54 &obj->oIntroLakituSplineSegmentProgress) == 1)) { 55 splineFinished++; 56 } 57 58 obj->oIntroLakituSplineSegment = splineSegment; 59 60 intro_lakitu_set_offset_from_camera(obj, newOffset); 61 intro_lakitu_set_focus(obj, newFocus); 62 63 return splineFinished; 64 } 65 66 #ifdef VERSION_EU 67 #define TIMER1 599 68 #define TIMER2 74 69 #else 70 #define TIMER1 720 71 #define TIMER2 98 72 #endif 73 74 void bhv_intro_lakitu_loop(void) { 75 Vec3f sp64, sp58, sp4C; 76 UNUSED u8 filler[16]; 77 78 switch (o->oAction) { 79 case 0: 80 cur_obj_disable_rendering(); 81 82 o->oIntroLakituSplineSegment = 0.0f; 83 o->oIntroLakituSplineSegmentProgress = 0.0f; 84 o->oIntroLakituCloud = 85 spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud); 86 87 if (gCamera->cutscene == CUTSCENE_END_WAVING) { 88 o->oAction = 100; 89 } else { 90 o->oAction++; 91 } 92 break; 93 94 case 1: 95 cur_obj_enable_rendering(); 96 97 if ((gCutsceneTimer > 350) && (gCutsceneTimer < 458)) { 98 o->oPosX = gCamera->pos[0]; 99 o->oPosY = gCamera->pos[1] + 500.0f; 100 o->oPosZ = gCamera->pos[2]; 101 } 102 103 if (gCutsceneTimer > 52) { 104 cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY_HIGHPRIO); 105 } 106 107 if (intro_lakitu_set_pos_and_focus(o, gIntroLakituStartToPipeOffsetFromCamera, 108 gIntroLakituStartToPipeFocus) == 1) { 109 o->oAction++; 110 } 111 112 switch (o->oTimer) { 113 #if defined(VERSION_US) || defined(VERSION_SH) || defined(VERSION_CN) 114 case 534: 115 cur_obj_play_sound_2(SOUND_ACTION_FLYING_FAST); 116 break; 117 case 581: 118 cur_obj_play_sound_2(SOUND_ACTION_INTRO_UNK45E); 119 break; 120 #endif 121 case 73: 122 o->oAnimState++; 123 break; 124 case 74: 125 o->oAnimState--; 126 break; 127 case 82: 128 o->oAnimState++; 129 break; 130 case 84: 131 o->oAnimState--; 132 break; 133 } 134 #ifdef VERSION_EU 135 if (o->oTimer == 446) { 136 cur_obj_play_sound_2(SOUND_ACTION_FLYING_FAST); 137 } 138 if (o->oTimer == 485) { 139 cur_obj_play_sound_2(SOUND_ACTION_INTRO_UNK45E); 140 } 141 #endif 142 break; 143 144 case 2: 145 if (gCutsceneTimer > TIMER1) { 146 o->oAction++; 147 148 o->oIntroLakituUnk100 = 1400.0f; 149 o->oIntroLakituUnk104 = -4096.0f; 150 o->oIntroLakituUnk108 = 2048.0f; 151 o->oIntroLakituUnk10C = -200.0f; 152 153 o->oMoveAngleYaw = 0x8000; 154 o->oFaceAngleYaw = o->oMoveAngleYaw + 0x4000; 155 o->oMoveAnglePitch = 0x800; 156 } 157 158 cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY_HIGHPRIO); 159 break; 160 161 case 3: 162 cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY_HIGHPRIO); 163 164 vec3f_set(sp58, -1128.0f, 560.0f, 4664.0f); 165 o->oMoveAngleYaw += 0x200; 166 o->oIntroLakituUnk100 = approach_f32_asymptotic(o->oIntroLakituUnk100, 100.0f, 0.03f); 167 o->oFaceAnglePitch = atan2s(200.0f, o->oPosY - 400.0f); 168 o->oFaceAngleYaw = approach_s16_asymptotic(o->oFaceAngleYaw, o->oMoveAngleYaw + 0x8000, 4); 169 vec3f_set_dist_and_angle(sp58, sp4C, o->oIntroLakituUnk100, 0, o->oMoveAngleYaw); 170 sp4C[1] += 150.0f * coss((s16) o->oIntroLakituUnk104); 171 o->oIntroLakituUnk104 += o->oIntroLakituUnk108; 172 o->oIntroLakituUnk108 = approach_f32_asymptotic(o->oIntroLakituUnk108, 512.0f, 0.05f); 173 sp4C[0] += o->oIntroLakituUnk10C; 174 o->oIntroLakituUnk10C = approach_f32_asymptotic(o->oIntroLakituUnk10C, 0.0f, 0.05f); 175 vec3f_to_object_pos(o, sp4C); 176 177 if (o->oTimer == 31) { 178 o->oPosY -= 158.0f; 179 // Spawn white ground particles 180 spawn_mist_from_global(); 181 o->oPosY += 158.0f; 182 } 183 184 if (o->oTimer == TIMER2) { 185 obj_mark_for_deletion(o); 186 obj_mark_for_deletion(o->oIntroLakituCloud); 187 } 188 189 #ifndef VERSION_JP 190 if (o->oTimer == 14) { 191 cur_obj_play_sound_2(SOUND_ACTION_INTRO_UNK45F); 192 } 193 #endif 194 break; 195 196 case 100: 197 cur_obj_enable_rendering(); 198 199 vec3f_set(sp64, -100.0f, 100.0f, 300.0f); 200 offset_rotated(sp4C, gCamera->pos, sp64, sMarioCamState->faceAngle); 201 vec3f_to_object_pos(o, sp4C); 202 203 o->oMoveAnglePitch = 0x1000; 204 o->oMoveAngleYaw = 0x9000; 205 o->oFaceAnglePitch = o->oMoveAnglePitch / 2; 206 o->oFaceAngleYaw = o->oMoveAngleYaw; 207 208 o->oAction++; 209 break; 210 211 case 101: 212 object_pos_to_vec3f(sp4C, o); 213 214 if (o->oTimer > 60) { 215 o->oForwardVel = approach_f32_asymptotic(o->oForwardVel, -10.0f, 0.05f); 216 o->oMoveAngleYaw += 0x78; 217 o->oMoveAnglePitch += 0x40; 218 o->oFaceAngleYaw = camera_approach_s16_symmetric( 219 o->oFaceAngleYaw, calculate_yaw(sp4C, gCamera->pos), 0x200); 220 } 221 222 if (o->oTimer > 105) { 223 o->oAction++; 224 o->oMoveAnglePitch = 0xE00; 225 } 226 227 o->oFaceAnglePitch = 0; 228 229 cur_obj_set_pos_via_transform(); 230 break; 231 232 case 102: 233 object_pos_to_vec3f(sp4C, o); 234 235 o->oForwardVel = approach_f32_asymptotic(o->oForwardVel, 60.0f, 0.05f); 236 o->oFaceAngleYaw = camera_approach_s16_symmetric( 237 o->oFaceAngleYaw, calculate_yaw(sp4C, gCamera->pos), 0x200); 238 239 if (o->oTimer < 62) { 240 o->oMoveAngleYaw = approach_s16_asymptotic(o->oMoveAngleYaw, 0x1800, 0x1E); 241 } 242 243 o->oMoveAnglePitch = camera_approach_s16_symmetric(o->oMoveAnglePitch, -0x2000, 0x5A); 244 o->oFaceAnglePitch = 0; 245 246 cur_obj_set_pos_via_transform(); 247 break; 248 } 249 } 250 251 #undef TIMER1 252 #undef TIMER2