Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/FBZ/FBZMissile.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: FBZMissile Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectFBZMissile *FBZMissile;
11
12
void FBZMissile_Update(void)
13
{
14
RSDK_THIS(FBZMissile);
15
16
StateMachine_Run(self->state);
17
}
18
19
void FBZMissile_LateUpdate(void) {}
20
21
void FBZMissile_StaticUpdate(void) {}
22
23
void FBZMissile_Draw(void)
24
{
25
RSDK_THIS(FBZMissile);
26
27
StateMachine_Run(self->stateDraw);
28
29
RSDK.DrawSprite(&self->animator, NULL, false);
30
}
31
32
void FBZMissile_Create(void *data)
33
{
34
RSDK_THIS(FBZMissile);
35
36
if (self->type != FBZMISSILE_HULL && !self->interval)
37
self->interval = -16;
38
39
self->drawFX = FX_FLIP;
40
if (!SceneInfo->inEditor) {
41
self->active = ACTIVE_BOUNDS;
42
self->visible = true;
43
self->drawGroup = Zone->objectDrawGroup[0];
44
self->updateRange.x = 0x800000;
45
self->updateRange.y = 0x800000;
46
if (data)
47
self->type = VOID_TO_INT(data);
48
49
switch (self->type) {
50
case FBZMISSILE_LAUNCHER_V:
51
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 0, &self->animator, true, 0);
52
self->direction *= FLIP_Y;
53
self->drawGroup = Zone->objectDrawGroup[1];
54
self->state = FBZMissile_StateLauncherV_Delay;
55
break;
56
57
case FBZMISSILE_LAUNCHER_H:
58
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 1, &self->animator, true, 0);
59
self->state = FBZMissile_StateLauncherH_Fire;
60
break;
61
62
case FBZMISSILE_HULL:
63
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 3, &self->animator, true, 0);
64
self->drawGroup = Zone->objectDrawGroup[1];
65
self->timer = self->interval;
66
self->state = FBZMissile_State_Hull;
67
break;
68
69
case FBZMISSILE_VERTICAL:
70
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 2, &self->animator, true, 0);
71
self->state = FBZMissile_StateVertical_Rise;
72
break;
73
74
case FBZMISSILE_HORIZONTAL:
75
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 1, &self->animator, true, 0);
76
self->state = FBZMissile_StateHorizontal_Move;
77
break;
78
79
default: break;
80
}
81
}
82
}
83
84
void FBZMissile_StageLoad(void)
85
{
86
FBZMissile->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Missile.bin", SCOPE_STAGE);
87
88
FBZMissile->hitboxMissileH.left = -16;
89
FBZMissile->hitboxMissileH.top = -3;
90
FBZMissile->hitboxMissileH.right = 16;
91
FBZMissile->hitboxMissileH.bottom = 3;
92
93
FBZMissile->hitboxMissileV.left = -5;
94
FBZMissile->hitboxMissileV.top = -8;
95
FBZMissile->hitboxMissileV.right = 5;
96
FBZMissile->hitboxMissileV.bottom = 8;
97
98
FBZMissile->hitboxHull.left = -32;
99
FBZMissile->hitboxHull.top = -8;
100
FBZMissile->hitboxHull.right = 32;
101
FBZMissile->hitboxHull.bottom = 8;
102
103
FBZMissile->sfxPush = RSDK.GetSfx("Stage/Push.wav");
104
FBZMissile->sfxPush2 = RSDK.GetSfx("Stage/Push.wav");
105
FBZMissile->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");
106
}
107
108
void FBZMissile_StateLauncherV_Delay(void)
109
{
110
RSDK_THIS(FBZMissile);
111
112
if (!((Zone->timer + self->intervalOffset) % self->interval)) {
113
self->timer = 42;
114
self->state = FBZMissile_StateLauncherV_Launch;
115
}
116
117
if (!(Zone->timer & 1)) {
118
if (self->animator.frameID > 0)
119
self->animator.frameID--;
120
}
121
}
122
123
void FBZMissile_StateLauncherV_Launch(void)
124
{
125
RSDK_THIS(FBZMissile);
126
127
if (!(self->timer & 1)) {
128
if (self->animator.frameID < 3)
129
self->animator.frameID++;
130
}
131
132
switch (--self->timer) {
133
case 1: self->state = FBZMissile_StateLauncherV_Delay; break;
134
135
case 9:
136
case 25:
137
case 41: {
138
RSDK.PlaySfx(FBZMissile->sfxPush, false, 255);
139
EntityFBZMissile *missile = CREATE_ENTITY(FBZMissile, INT_TO_VOID(FBZMISSILE_VERTICAL), self->position.x, self->position.y);
140
missile->isPermanent = true;
141
missile->velocity.y = -0x60000;
142
missile->drawGroup = self->drawGroup - 1;
143
missile->velocity.x = FBZMissile->velocities[FBZMissile->velocityID++];
144
FBZMissile->velocityID &= 7;
145
break;
146
}
147
148
default: break;
149
}
150
}
151
152
void FBZMissile_StateLauncherH_Fire(void)
153
{
154
RSDK_THIS(FBZMissile);
155
156
if (!((Zone->timer + self->intervalOffset) % self->interval)) {
157
RSDK.PlaySfx(FBZMissile->sfxPush2, false, 255);
158
159
EntityFBZMissile *missile = CREATE_ENTITY(FBZMissile, INT_TO_VOID(FBZMISSILE_HORIZONTAL), self->position.x, self->position.y);
160
missile->drawGroup = self->drawGroup;
161
missile->direction = self->direction;
162
if (self->direction) {
163
missile->velocity.x = 0x40000;
164
self->position.x -= 500000;
165
}
166
else {
167
missile->velocity.x = -0x40000;
168
self->position.x += 500000;
169
}
170
171
self->timer = 62;
172
self->state = FBZMissile_StateLauncherH_Prepare;
173
}
174
}
175
176
void FBZMissile_StateLauncherH_Prepare(void)
177
{
178
RSDK_THIS(FBZMissile);
179
180
if (--self->timer > 0) {
181
if (self->direction)
182
self->position.x += 0x2000;
183
else
184
self->position.x -= 0x2000;
185
}
186
else {
187
self->state = FBZMissile_StateLauncherH_Fire;
188
}
189
}
190
191
void FBZMissile_StateVertical_Rise(void)
192
{
193
RSDK_THIS(FBZMissile);
194
195
self->position.y += self->velocity.y;
196
self->velocity.y += 0x1800;
197
198
if (self->velocity.y >= 0) {
199
self->drawGroup = Zone->objectDrawGroup[0];
200
self->state = FBZMissile_StateVertical_Fall;
201
}
202
203
if (self->velocity.y > -0x1D000)
204
self->position.x += self->velocity.x;
205
206
if (!RSDK.CheckOnScreen(self, NULL))
207
destroyEntity(self);
208
}
209
210
void FBZMissile_StateVertical_Fall(void)
211
{
212
RSDK_THIS(FBZMissile);
213
214
self->position.y += self->velocity.y;
215
self->velocity.y += 0x1000;
216
217
if (!self->timer) {
218
if (self->animator.frameID < 5)
219
self->animator.frameID++;
220
}
221
222
self->timer = (self->timer - 1) & 1;
223
if (self->velocity.y < 0x1D000)
224
self->position.x += self->velocity.x;
225
226
if (RSDK.CheckOnScreen(self, NULL)) {
227
foreach_active(Player, player)
228
{
229
if (Player_CheckCollisionTouch(player, self, &FBZMissile->hitboxMissileV)) {
230
#if MANIA_USE_PLUS
231
if (!Player_CheckMightyUnspin(player, 0x300, 2, &player->uncurlTimer))
232
#endif
233
Player_Hurt(player, self);
234
235
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSSPUFF), self->position.x, self->position.y + 0x30000)->drawGroup =
236
Zone->objectDrawGroup[1];
237
RSDK.PlaySfx(FBZMissile->sfxExplosion, false, 255);
238
destroyEntity(self);
239
240
foreach_break;
241
}
242
}
243
244
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, false)) {
245
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSSPUFF), self->position.x, self->position.y + 0x30000)->drawGroup =
246
Zone->objectDrawGroup[1];
247
RSDK.PlaySfx(FBZMissile->sfxExplosion, false, 255);
248
destroyEntity(self);
249
}
250
else {
251
foreach_active(FBZMissile, missile)
252
{
253
if (missile->type == FBZMISSILE_HULL
254
&& RSDK.CheckObjectCollisionTouchBox(missile, &FBZMissile->hitboxHull, self, &FBZMissile->hitboxMissileV)) {
255
if (--missile->timer <= 0) {
256
destroyEntity(missile);
257
RSDK.PlaySfx(Player->sfxRelease, false, 255);
258
}
259
260
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSSPUFF), self->position.x, self->position.y + 0x30000)->drawGroup =
261
Zone->objectDrawGroup[1];
262
RSDK.PlaySfx(FBZMissile->sfxExplosion, false, 255);
263
destroyEntity(self);
264
}
265
}
266
}
267
}
268
else {
269
destroyEntity(self);
270
}
271
}
272
273
void FBZMissile_StateHorizontal_Move(void)
274
{
275
RSDK_THIS(FBZMissile);
276
277
self->position.x += self->velocity.x;
278
279
if (RSDK.CheckOnScreen(self, NULL)) {
280
RSDK.ProcessAnimation(&self->animator);
281
282
foreach_active(Player, player)
283
{
284
if (Player_CheckCollisionTouch(player, self, &FBZMissile->hitboxMissileH)) {
285
#if MANIA_USE_PLUS
286
if (!Player_CheckMightyUnspin(player, 0x300, 2, &player->uncurlTimer))
287
#endif
288
Player_Hurt(player, self);
289
}
290
}
291
}
292
else {
293
destroyEntity(self);
294
}
295
}
296
297
void FBZMissile_State_Hull(void)
298
{
299
RSDK_THIS(FBZMissile);
300
301
self->position.x += self->velocity.x;
302
RSDK.ProcessAnimation(&self->animator);
303
304
#if MANIA_USE_PLUS
305
foreach_active(Player, player)
306
{
307
int32 velY = player->velocity.y;
308
if (Player_CheckCollisionBox(player, self, &FBZMissile->hitboxHull) && player->state == Player_State_MightyHammerDrop && !player->sidekick) {
309
RSDK.PlaySfx(FBZMissile->sfxExplosion, false, 255);
310
RSDK.PlaySfx(Player->sfxRelease, false, 255);
311
312
player->velocity.y = velY - 0x10000;
313
player->onGround = false;
314
315
destroyEntity(self);
316
foreach_break;
317
}
318
}
319
#endif
320
}
321
322
#if GAME_INCLUDE_EDITOR
323
void FBZMissile_EditorDraw(void)
324
{
325
RSDK_THIS(FBZMissile);
326
327
int32 dir = self->direction;
328
switch (self->type) {
329
case FBZMISSILE_LAUNCHER_V:
330
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 0, &self->animator, true, 0);
331
self->direction *= FLIP_Y;
332
self->drawGroup = Zone->objectDrawGroup[1];
333
break;
334
335
case FBZMISSILE_LAUNCHER_H: RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 1, &self->animator, true, 0); break;
336
337
case FBZMISSILE_HULL:
338
RSDK.SetSpriteAnimation(FBZMissile->aniFrames, 3, &self->animator, true, 0);
339
self->drawGroup = Zone->objectDrawGroup[1];
340
break;
341
342
default: break;
343
}
344
345
FBZMissile_Draw();
346
347
self->direction = dir;
348
}
349
350
void FBZMissile_EditorLoad(void)
351
{
352
FBZMissile->aniFrames = RSDK.LoadSpriteAnimation("FBZ/Missile.bin", SCOPE_STAGE);
353
354
RSDK_ACTIVE_VAR(FBZMissile, type);
355
RSDK_ENUM_VAR("Launcher (Vertical)", FBZMISSILE_LAUNCHER_V);
356
RSDK_ENUM_VAR("Launcher (Horizontal)", FBZMISSILE_LAUNCHER_H);
357
RSDK_ENUM_VAR("Hull", FBZMISSILE_HULL);
358
359
RSDK_ACTIVE_VAR(FBZMissile, direction);
360
RSDK_ENUM_VAR("Up/Left", FLIP_NONE);
361
RSDK_ENUM_VAR("Down/Right", FLIP_X);
362
}
363
#endif
364
365
void FBZMissile_Serialize(void)
366
{
367
RSDK_EDITABLE_VAR(FBZMissile, VAR_ENUM, type);
368
RSDK_EDITABLE_VAR(FBZMissile, VAR_UINT8, interval);
369
RSDK_EDITABLE_VAR(FBZMissile, VAR_UINT8, intervalOffset);
370
RSDK_EDITABLE_VAR(FBZMissile, VAR_UINT8, direction);
371
}
372
373