Path: blob/master/src/game/behaviors/camera_lakitu.inc.c
7861 views
1/**2* Behavior for bhvCameraLakitu. This includes both the intro lakitu and the3* lakitu visible in the mirror room.4* TODO: Processing order relative to bhvCloud5*/67/**8* Init function for camera lakitu.9* If this is the intro lakitu, despawn unless this is the start of the game.10* Spawn cloud if not the intro lakitu.11*/12void bhv_camera_lakitu_init(void) {13if (o->oBehParams2ndByte != CAMERA_LAKITU_BP_FOLLOW_CAMERA) {14// Despawn unless this is the very beginning of the game15if (gNeverEnteredCastle != TRUE) {16obj_mark_for_deletion(o);17}18} else {19spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);20}21}2223/**24* Wait for mario to stand on the bridge, then interrupt his action and enter25* the spawn cloud action.26*/27static void camera_lakitu_intro_act_trigger_cutscene(void) {28//! These bounds are slightly smaller than the actual bridge bounds, allowing29// the RTA speedrunning method of lakitu skip30if (!configSkipCutscenes31&& gMarioObject->oPosX > -544.0f && gMarioObject->oPosX < 545.0f && gMarioObject->oPosY > 800.0f32&& gMarioObject->oPosZ > -2000.0f && gMarioObject->oPosZ < -177.0f33&& gMarioObject->oPosZ < -177.0f) // always double check your conditions34{35if (set_mario_npc_dialog(MARIO_DIALOG_LOOK_UP) == MARIO_DIALOG_STATUS_START) {36o->oAction = CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD;37}38}39}4041/**42* Warp up into the air and spawn cloud, then enter the TODO action.43*/44static void camera_lakitu_intro_act_spawn_cloud(void) {45if (set_mario_npc_dialog(MARIO_DIALOG_LOOK_UP) == MARIO_DIALOG_STATUS_SPEAK) {46o->oAction = CAMERA_LAKITU_INTRO_ACT_UNK2;4748o->oPosX = 1800.0f;49o->oPosY = 2400.0f;50o->oPosZ = -2400.0f;5152o->oMoveAnglePitch = 0x4000;53o->oCameraLakituSpeed = 60.0f;54o->oCameraLakituCircleRadius = 1000.0f;5556spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);57}58}5960/**61* Circle down to mario, show the dialog, then fly away.62*/63static void camera_lakitu_intro_act_show_dialog(void) {64s16 targetMovePitch;65s16 targetMoveYaw;66#ifdef AVOID_UB67targetMovePitch = 0;68targetMoveYaw = 0;69#endif7071cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY);7273// Face toward mario74o->oFaceAnglePitch = obj_turn_pitch_toward_mario(120.0f, 0);75o->oFaceAngleYaw = o->oAngleToMario;7677// After finishing dialog, fly away and despawn78if (o->oCameraLakituFinishedDialog) {79approach_f32_ptr(&o->oCameraLakituSpeed, 60.0f, 3.0f);80if (o->oDistanceToMario > 6000.0f) {81obj_mark_for_deletion(o);82}8384targetMovePitch = -0x3000;85targetMoveYaw = -0x6000;86} else {87if (o->oCameraLakituSpeed != 0.0f) {88if (o->oDistanceToMario > 5000.0f) {89targetMovePitch = o->oMoveAnglePitch;90targetMoveYaw = o->oAngleToMario;91} else {92// Stay moving in a circle around mario93s16 turnAmount = 0x400094- atan2s(o->oCameraLakituCircleRadius,95o->oDistanceToMario - o->oCameraLakituCircleRadius);96if ((s16)(o->oMoveAngleYaw - o->oAngleToMario) < 0) {97turnAmount = -turnAmount;98}99100targetMoveYaw = o->oAngleToMario + turnAmount;101targetMovePitch = o->oFaceAnglePitch;102103approach_f32_ptr(&o->oCameraLakituCircleRadius, 200.0f, 50.0f);104if (o->oDistanceToMario < 1000.0f) {105#ifndef VERSION_JP106if (!o->oCameraLakituUnk104) {107play_music(SEQ_PLAYER_LEVEL, SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_LAKITU), 0);108o->oCameraLakituUnk104 = TRUE;109}110#endif111112// Once within 1000 units, slow down113approach_f32_ptr(&o->oCameraLakituSpeed, 20.0f, 1.0f);114if (o->oDistanceToMario < 500.0f115&& abs_angle_diff(gMarioObject->oFaceAngleYaw, o->oFaceAngleYaw) > 0x7000) {116// Once within 500 units and facing toward mario, come117// to a stop118approach_f32_ptr(&o->oCameraLakituSpeed, 0.0f, 5.0f);119}120}121}122} else if (cur_obj_update_dialog_with_cutscene(MARIO_DIALOG_LOOK_UP,123DIALOG_FLAG_TURN_TO_MARIO, CUTSCENE_DIALOG, DIALOG_034)) {124o->oCameraLakituFinishedDialog = TRUE;125}126}127128o->oCameraLakituPitchVel = approach_s16_symmetric(o->oCameraLakituPitchVel, 0x7D0, 0x190);129obj_move_pitch_approach(targetMovePitch, o->oCameraLakituPitchVel);130131o->oCameraLakituYawVel = approach_s16_symmetric(o->oCameraLakituYawVel, 0x7D0, 0x64);132cur_obj_rotate_yaw_toward(targetMoveYaw, o->oCameraLakituYawVel);133134// vel y is explicitly computed, so gravity doesn't apply135obj_compute_vel_from_move_pitch(o->oCameraLakituSpeed);136cur_obj_move_using_fvel_and_gravity();137}138139/**140* Update function for camera lakitu.141*/142void bhv_camera_lakitu_update(void) {143if (configSkipCutscenes) {144obj_mark_for_deletion(o);145return;146}147148if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {149obj_update_blinking(&o->oCameraLakituBlinkTimer, 20, 40, 4);150151if (o->oBehParams2ndByte != CAMERA_LAKITU_BP_FOLLOW_CAMERA) {152switch (o->oAction) {153case CAMERA_LAKITU_INTRO_ACT_TRIGGER_CUTSCENE:154camera_lakitu_intro_act_trigger_cutscene();155break;156case CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD:157camera_lakitu_intro_act_spawn_cloud();158break;159case CAMERA_LAKITU_INTRO_ACT_UNK2:160camera_lakitu_intro_act_show_dialog();161break;162}163} else {164f32 val0C = (f32) 0x875C3D / 0x800 - gLakituState.curPos[0];165if (gLakituState.curPos[0] < 1700.0f || val0C < 0.0f) {166cur_obj_hide();167} else {168cur_obj_unhide();169170o->oPosX = gLakituState.curPos[0];171o->oPosY = gLakituState.curPos[1];172o->oPosZ = gLakituState.curPos[2];173174o->oHomeX = gLakituState.curFocus[0];175o->oHomeZ = gLakituState.curFocus[2];176177o->oFaceAngleYaw = -cur_obj_angle_to_home();178o->oFaceAnglePitch = atan2s(cur_obj_lateral_dist_to_home(),179o->oPosY - gLakituState.curFocus[1]);180181o->oPosX = (f32) 0x875C3D / 0x800 + val0C;182}183}184}185}186187188