Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/game/behaviors/camera_lakitu.inc.c
7861 views
1
2
/**
3
* Behavior for bhvCameraLakitu. This includes both the intro lakitu and the
4
* lakitu visible in the mirror room.
5
* TODO: Processing order relative to bhvCloud
6
*/
7
8
/**
9
* Init function for camera lakitu.
10
* If this is the intro lakitu, despawn unless this is the start of the game.
11
* Spawn cloud if not the intro lakitu.
12
*/
13
void bhv_camera_lakitu_init(void) {
14
if (o->oBehParams2ndByte != CAMERA_LAKITU_BP_FOLLOW_CAMERA) {
15
// Despawn unless this is the very beginning of the game
16
if (gNeverEnteredCastle != TRUE) {
17
obj_mark_for_deletion(o);
18
}
19
} else {
20
spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);
21
}
22
}
23
24
/**
25
* Wait for mario to stand on the bridge, then interrupt his action and enter
26
* the spawn cloud action.
27
*/
28
static void camera_lakitu_intro_act_trigger_cutscene(void) {
29
//! These bounds are slightly smaller than the actual bridge bounds, allowing
30
// the RTA speedrunning method of lakitu skip
31
if (!configSkipCutscenes
32
&& gMarioObject->oPosX > -544.0f && gMarioObject->oPosX < 545.0f && gMarioObject->oPosY > 800.0f
33
&& gMarioObject->oPosZ > -2000.0f && gMarioObject->oPosZ < -177.0f
34
&& gMarioObject->oPosZ < -177.0f) // always double check your conditions
35
{
36
if (set_mario_npc_dialog(MARIO_DIALOG_LOOK_UP) == MARIO_DIALOG_STATUS_START) {
37
o->oAction = CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD;
38
}
39
}
40
}
41
42
/**
43
* Warp up into the air and spawn cloud, then enter the TODO action.
44
*/
45
static void camera_lakitu_intro_act_spawn_cloud(void) {
46
if (set_mario_npc_dialog(MARIO_DIALOG_LOOK_UP) == MARIO_DIALOG_STATUS_SPEAK) {
47
o->oAction = CAMERA_LAKITU_INTRO_ACT_UNK2;
48
49
o->oPosX = 1800.0f;
50
o->oPosY = 2400.0f;
51
o->oPosZ = -2400.0f;
52
53
o->oMoveAnglePitch = 0x4000;
54
o->oCameraLakituSpeed = 60.0f;
55
o->oCameraLakituCircleRadius = 1000.0f;
56
57
spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);
58
}
59
}
60
61
/**
62
* Circle down to mario, show the dialog, then fly away.
63
*/
64
static void camera_lakitu_intro_act_show_dialog(void) {
65
s16 targetMovePitch;
66
s16 targetMoveYaw;
67
#ifdef AVOID_UB
68
targetMovePitch = 0;
69
targetMoveYaw = 0;
70
#endif
71
72
cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY);
73
74
// Face toward mario
75
o->oFaceAnglePitch = obj_turn_pitch_toward_mario(120.0f, 0);
76
o->oFaceAngleYaw = o->oAngleToMario;
77
78
// After finishing dialog, fly away and despawn
79
if (o->oCameraLakituFinishedDialog) {
80
approach_f32_ptr(&o->oCameraLakituSpeed, 60.0f, 3.0f);
81
if (o->oDistanceToMario > 6000.0f) {
82
obj_mark_for_deletion(o);
83
}
84
85
targetMovePitch = -0x3000;
86
targetMoveYaw = -0x6000;
87
} else {
88
if (o->oCameraLakituSpeed != 0.0f) {
89
if (o->oDistanceToMario > 5000.0f) {
90
targetMovePitch = o->oMoveAnglePitch;
91
targetMoveYaw = o->oAngleToMario;
92
} else {
93
// Stay moving in a circle around mario
94
s16 turnAmount = 0x4000
95
- atan2s(o->oCameraLakituCircleRadius,
96
o->oDistanceToMario - o->oCameraLakituCircleRadius);
97
if ((s16)(o->oMoveAngleYaw - o->oAngleToMario) < 0) {
98
turnAmount = -turnAmount;
99
}
100
101
targetMoveYaw = o->oAngleToMario + turnAmount;
102
targetMovePitch = o->oFaceAnglePitch;
103
104
approach_f32_ptr(&o->oCameraLakituCircleRadius, 200.0f, 50.0f);
105
if (o->oDistanceToMario < 1000.0f) {
106
#ifndef VERSION_JP
107
if (!o->oCameraLakituUnk104) {
108
play_music(SEQ_PLAYER_LEVEL, SEQUENCE_ARGS(15, SEQ_EVENT_CUTSCENE_LAKITU), 0);
109
o->oCameraLakituUnk104 = TRUE;
110
}
111
#endif
112
113
// Once within 1000 units, slow down
114
approach_f32_ptr(&o->oCameraLakituSpeed, 20.0f, 1.0f);
115
if (o->oDistanceToMario < 500.0f
116
&& abs_angle_diff(gMarioObject->oFaceAngleYaw, o->oFaceAngleYaw) > 0x7000) {
117
// Once within 500 units and facing toward mario, come
118
// to a stop
119
approach_f32_ptr(&o->oCameraLakituSpeed, 0.0f, 5.0f);
120
}
121
}
122
}
123
} else if (cur_obj_update_dialog_with_cutscene(MARIO_DIALOG_LOOK_UP,
124
DIALOG_FLAG_TURN_TO_MARIO, CUTSCENE_DIALOG, DIALOG_034)) {
125
o->oCameraLakituFinishedDialog = TRUE;
126
}
127
}
128
129
o->oCameraLakituPitchVel = approach_s16_symmetric(o->oCameraLakituPitchVel, 0x7D0, 0x190);
130
obj_move_pitch_approach(targetMovePitch, o->oCameraLakituPitchVel);
131
132
o->oCameraLakituYawVel = approach_s16_symmetric(o->oCameraLakituYawVel, 0x7D0, 0x64);
133
cur_obj_rotate_yaw_toward(targetMoveYaw, o->oCameraLakituYawVel);
134
135
// vel y is explicitly computed, so gravity doesn't apply
136
obj_compute_vel_from_move_pitch(o->oCameraLakituSpeed);
137
cur_obj_move_using_fvel_and_gravity();
138
}
139
140
/**
141
* Update function for camera lakitu.
142
*/
143
void bhv_camera_lakitu_update(void) {
144
if (configSkipCutscenes) {
145
obj_mark_for_deletion(o);
146
return;
147
}
148
149
if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
150
obj_update_blinking(&o->oCameraLakituBlinkTimer, 20, 40, 4);
151
152
if (o->oBehParams2ndByte != CAMERA_LAKITU_BP_FOLLOW_CAMERA) {
153
switch (o->oAction) {
154
case CAMERA_LAKITU_INTRO_ACT_TRIGGER_CUTSCENE:
155
camera_lakitu_intro_act_trigger_cutscene();
156
break;
157
case CAMERA_LAKITU_INTRO_ACT_SPAWN_CLOUD:
158
camera_lakitu_intro_act_spawn_cloud();
159
break;
160
case CAMERA_LAKITU_INTRO_ACT_UNK2:
161
camera_lakitu_intro_act_show_dialog();
162
break;
163
}
164
} else {
165
f32 val0C = (f32) 0x875C3D / 0x800 - gLakituState.curPos[0];
166
if (gLakituState.curPos[0] < 1700.0f || val0C < 0.0f) {
167
cur_obj_hide();
168
} else {
169
cur_obj_unhide();
170
171
o->oPosX = gLakituState.curPos[0];
172
o->oPosY = gLakituState.curPos[1];
173
o->oPosZ = gLakituState.curPos[2];
174
175
o->oHomeX = gLakituState.curFocus[0];
176
o->oHomeZ = gLakituState.curFocus[2];
177
178
o->oFaceAngleYaw = -cur_obj_angle_to_home();
179
o->oFaceAnglePitch = atan2s(cur_obj_lateral_dist_to_home(),
180
o->oPosY - gLakituState.curFocus[1]);
181
182
o->oPosX = (f32) 0x875C3D / 0x800 + val0C;
183
}
184
}
185
}
186
}
187
188