Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/game/behaviors/bowser_flame.inc.c
7861 views
1
struct ObjectHitbox sGrowingBowserFlameHitbox = {
2
/* interactType: */ INTERACT_FLAME,
3
/* downOffset: */ 20,
4
/* damageOrCoinValue: */ 1,
5
/* health: */ 0,
6
/* numLootCoins: */ 0,
7
/* radius: */ 10,
8
/* height: */ 40,
9
/* hurtboxRadius: */ 0,
10
/* hurtboxHeight: */ 0,
11
};
12
13
struct ObjectHitbox sBowserFlameHitbox = {
14
/* interactType: */ INTERACT_FLAME,
15
/* downOffset: */ 0,
16
/* damageOrCoinValue: */ 1,
17
/* health: */ 0,
18
/* numLootCoins: */ 0,
19
/* radius: */ 10,
20
/* height: */ 40,
21
/* hurtboxRadius: */ 0,
22
/* hurtboxHeight: */ 0,
23
};
24
25
void bowser_flame_despawn(void) {
26
obj_mark_for_deletion(o);
27
spawn_object_with_scale(o, MODEL_NONE, bhvBlackSmokeUpward, 1.0f);
28
if (random_float() < 0.1) {
29
spawn_object(o, MODEL_YELLOW_COIN, bhvTemporaryYellowCoin);
30
}
31
}
32
33
s32 bowser_flame_should_despawn(s32 maxTime) {
34
if (maxTime < o->oTimer) {
35
return TRUE;
36
}
37
38
// Flames should despawn if they fall off the arena.
39
if (o->oFloorType == SURFACE_BURNING) {
40
return TRUE;
41
}
42
if (o->oFloorType == SURFACE_DEATH_PLANE) {
43
return TRUE;
44
}
45
46
return FALSE;
47
}
48
49
void bhv_flame_bowser_init(void) {
50
o->oAnimState = (s32)(random_float() * 10.0f);
51
o->oMoveAngleYaw = random_u16();
52
if (random_float() < 0.2) {
53
o->oVelY = 80.0f;
54
} else {
55
o->oVelY = 20.0f;
56
}
57
o->oForwardVel = 10.0f;
58
o->oGravity = -1.0f;
59
o->oFlameScale = random_float() + 1.0f;
60
}
61
62
void bhv_flame_large_burning_out_init(void) {
63
o->oAnimState = (s32)(random_float() * 10.0f);
64
o->oMoveAngleYaw = random_u16();
65
o->oVelY = 10.0f;
66
o->oForwardVel = 0.0f;
67
o->oFlameScale = 7.0f;
68
}
69
70
void bowser_flame_move(void) {
71
s32 timer;
72
timer = ((o->oFlameSpeedTimerOffset + gGlobalTimer) & 0x3F) << 10;
73
o->oPosX += sins(o->oMoveAngleYaw) * sins(timer) * 4.0f;
74
o->oPosZ += coss(o->oMoveAngleYaw) * sins(timer) * 4.0f;
75
}
76
77
void bhv_flame_bowser_loop(void) {
78
cur_obj_update_floor_and_walls();
79
cur_obj_move_standard(78);
80
if (o->oVelY < -4.0f) {
81
o->oVelY = -4.0f;
82
}
83
if (o->oAction == 0) {
84
cur_obj_become_intangible();
85
bowser_flame_move();
86
if (o->oMoveFlags & OBJ_MOVE_LANDED) {
87
o->oAction++;
88
if (cur_obj_has_behavior(bhvFlameLargeBurningOut)) {
89
o->oFlameScale = 8.0f;
90
} else {
91
o->oFlameScale = random_float() * 2 + 6.0f;
92
}
93
o->oForwardVel = 0;
94
o->oVelY = 0;
95
o->oGravity = 0;
96
}
97
} else {
98
cur_obj_become_tangible();
99
if (o->oTimer > o->oFlameScale * 10 + 5.0f) {
100
o->oFlameScale -= 0.15;
101
if (o->oFlameScale <= 0) {
102
bowser_flame_despawn();
103
}
104
}
105
}
106
cur_obj_scale(o->oFlameScale);
107
o->oGraphYOffset = o->header.gfx.scale[1] * 14.0f;
108
obj_set_hitbox(o, &sBowserFlameHitbox);
109
}
110
111
void bhv_flame_moving_forward_growing_init(void) {
112
o->oForwardVel = 30.0f;
113
obj_translate_xz_random(o, 80.0f);
114
o->oAnimState = (s32)(random_float() * 10.0f);
115
o->oFlameScale = 3.0f;
116
}
117
118
void bhv_flame_moving_forward_growing_loop(void) {
119
UNUSED s32 unused;
120
UNUSED struct Object *flame;
121
obj_set_hitbox(o, &sGrowingBowserFlameHitbox);
122
o->oFlameScale = o->oFlameScale + 0.5;
123
cur_obj_scale(o->oFlameScale);
124
if (o->oMoveAnglePitch > 0x800) {
125
o->oMoveAnglePitch -= 0x200;
126
}
127
cur_obj_set_pos_via_transform();
128
cur_obj_update_floor_height();
129
if (o->oFlameScale > 30.0f) {
130
obj_mark_for_deletion(o);
131
}
132
if (o->oPosY < o->oFloorHeight) {
133
o->oPosY = o->oFloorHeight;
134
flame = spawn_object(o, MODEL_RED_FLAME, bhvFlameBowser);
135
obj_mark_for_deletion(o);
136
}
137
}
138
139
void bhv_flame_floating_landing_init(void) {
140
o->oAnimState = (s32)(random_float() * 10.0f);
141
o->oMoveAngleYaw = random_u16();
142
if (o->oBehParams2ndByte != 0) {
143
o->oForwardVel = random_float() * 5.0f;
144
} else {
145
o->oForwardVel = random_float() * 70.0f;
146
}
147
o->oVelY = random_float() * 20.0f;
148
o->oGravity = -1.0f;
149
o->oFlameSpeedTimerOffset = random_float() * 64.0f;
150
}
151
152
f32 sFlameFloatingYLimit[] = { -8.0f, -6.0f, -3.0f };
153
154
void bhv_flame_floating_landing_loop(void) {
155
UNUSED s32 unused;
156
cur_obj_update_floor_and_walls();
157
cur_obj_move_standard(78);
158
bowser_flame_move();
159
if (bowser_flame_should_despawn(900)) {
160
obj_mark_for_deletion(o);
161
}
162
if (o->oVelY < sFlameFloatingYLimit[o->oBehParams2ndByte]) {
163
o->oVelY = sFlameFloatingYLimit[o->oBehParams2ndByte];
164
}
165
if (o->oMoveFlags & OBJ_MOVE_LANDED) {
166
if (o->oBehParams2ndByte == 0) {
167
spawn_object(o, MODEL_RED_FLAME, bhvFlameLargeBurningOut);
168
} else {
169
spawn_object(o, MODEL_NONE, bhvBlueFlamesGroup); //? wonder if they meant MODEL_BLUE_FLAME?
170
}
171
obj_mark_for_deletion(o);
172
}
173
o->oGraphYOffset = o->header.gfx.scale[1] * 14.0f;
174
}
175
176
void bhv_blue_bowser_flame_init(void) {
177
obj_translate_xz_random(o, 80.0f);
178
o->oAnimState = (s32)(random_float() * 10.0f);
179
o->oVelY = 7.0f;
180
o->oForwardVel = 35.0f;
181
o->oFlameScale = 3.0f;
182
o->oFlameUnusedRand = random_float() * 0.5;
183
o->oGravity = 1.0f;
184
o->oFlameSpeedTimerOffset = (s32)(random_float() * 64.0f);
185
}
186
187
void bhv_blue_bowser_flame_loop(void) {
188
s32 i;
189
obj_set_hitbox(o, &sGrowingBowserFlameHitbox);
190
if (o->oFlameScale < 16.0f) {
191
o->oFlameScale = o->oFlameScale + 0.5;
192
}
193
cur_obj_scale(o->oFlameScale);
194
cur_obj_update_floor_and_walls();
195
cur_obj_move_standard(78);
196
if (o->oTimer > 0x14) {
197
if (o->oBehParams2ndByte == 0) {
198
for (i = 0; i < 3; i++) {
199
spawn_object_relative_with_scale(0, 0, 0, 0, 5.0f, o, MODEL_RED_FLAME,
200
bhvFlameFloatingLanding);
201
}
202
} else {
203
spawn_object_relative_with_scale(1, 0, 0, 0, 8.0f, o, MODEL_BLUE_FLAME,
204
bhvFlameFloatingLanding);
205
spawn_object_relative_with_scale(2, 0, 0, 0, 8.0f, o, MODEL_BLUE_FLAME,
206
bhvFlameFloatingLanding);
207
}
208
obj_mark_for_deletion(o);
209
}
210
}
211
212
void bhv_flame_bouncing_init(void) {
213
o->oAnimState = (s32)(random_float() * 10.0f);
214
o->oVelY = 30.0f;
215
o->oForwardVel = 20.0f;
216
o->oFlameScale = o->header.gfx.scale[0];
217
o->oFlameSpeedTimerOffset = (s32)(random_float() * 64.0f);
218
}
219
220
void bhv_flame_bouncing_loop(void) {
221
struct Object *bowser;
222
if (o->oTimer == 0) {
223
o->oFlameBowser = cur_obj_nearest_object_with_behavior(bhvBowser);
224
}
225
bowser = o->oFlameBowser;
226
o->oForwardVel = 15.0f;
227
o->oBounciness = -1.0f;
228
cur_obj_scale(o->oFlameScale);
229
obj_set_hitbox(o, &sGrowingBowserFlameHitbox);
230
cur_obj_update_floor_and_walls();
231
cur_obj_move_standard(78);
232
if (bowser_flame_should_despawn(300)) {
233
obj_mark_for_deletion(o);
234
}
235
if (bowser != NULL) {
236
if (bowser->oHeldState == HELD_FREE) {
237
if (lateral_dist_between_objects(o, bowser) < 300.0f) {
238
obj_mark_for_deletion(o);
239
}
240
}
241
}
242
}
243
244
void bhv_blue_flames_group_loop(void) {
245
struct Object *flame;
246
s32 i;
247
if (o->oTimer == 0) {
248
o->oMoveAngleYaw = obj_angle_to_object(o, gMarioObject);
249
o->oBlueFlameNextScale = 5.0f;
250
}
251
if (o->oTimer < 16) {
252
if ((o->oTimer & 1) == 0) {
253
for (i = 0; i < 3; i++) {
254
flame = spawn_object(o, MODEL_BLUE_FLAME, bhvFlameBouncing);
255
flame->oMoveAngleYaw += i * 0x5555;
256
flame->header.gfx.scale[0] = o->oBlueFlameNextScale;
257
}
258
o->oBlueFlameNextScale -= 0.5;
259
}
260
} else {
261
obj_mark_for_deletion(o);
262
}
263
}
264
265