Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HCZ/ScrewMobile.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: ScrewMobile Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectScrewMobile *ScrewMobile;
11
12
void ScrewMobile_Update(void)
13
{
14
RSDK_THIS(ScrewMobile);
15
16
StateMachine_Run(self->state);
17
}
18
19
void ScrewMobile_LateUpdate(void) {}
20
21
void ScrewMobile_StaticUpdate(void)
22
{
23
foreach_active(ScrewMobile, screwMobile)
24
{
25
if (screwMobile->state != ScrewMobile_StateDepthCharge_Active) {
26
RSDK.AddDrawListRef(Zone->playerDrawGroup[0] - 1, RSDK.GetEntitySlot(screwMobile));
27
}
28
}
29
30
if (ScrewMobile->fanSfxTimer) {
31
if (!ScrewMobile->playingFanSfx) {
32
RSDK.PlaySfx(ScrewMobile->sfxBigFan, 47208, 0xFF);
33
ScrewMobile->playingFanSfx = true;
34
}
35
}
36
else if (ScrewMobile->playingFanSfx) {
37
RSDK.StopSfx(ScrewMobile->sfxBigFan);
38
ScrewMobile->playingFanSfx = false;
39
}
40
41
ScrewMobile->fanSfxTimer = 0;
42
}
43
44
void ScrewMobile_Draw(void)
45
{
46
RSDK_THIS(ScrewMobile);
47
48
StateMachine_Run(self->stateDraw);
49
}
50
51
void ScrewMobile_Create(void *data)
52
{
53
RSDK_THIS(ScrewMobile);
54
55
if (globals->gameMode == MODE_TIMEATTACK) {
56
destroyEntity(self);
57
}
58
else {
59
self->drawFX = FX_FLIP;
60
if (!SceneInfo->inEditor) {
61
self->visible = true;
62
63
if (data) {
64
switch (VOID_TO_INT(data)) {
65
default: break;
66
67
case 1:
68
self->active = ACTIVE_NORMAL;
69
self->drawGroup = Zone->hudDrawGroup - 2;
70
self->updateRange.x = 0x800000;
71
self->updateRange.y = 0x800000;
72
self->whirlpoolHeight = 0x3800;
73
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 6, &self->mobileAnimator, true, 0);
74
self->state = ScrewMobile_StateDepthCharge_Active;
75
self->stateDraw = ScrewMobile_Draw_DepthCharge;
76
break;
77
}
78
}
79
else {
80
self->active = ACTIVE_BOUNDS;
81
self->drawGroup = Zone->hudDrawGroup - 1;
82
self->updateRange.x = 0x800000;
83
self->updateRange.y = 0x800000;
84
self->startPos = self->position;
85
86
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 0, &self->mobileAnimator, true, 0);
87
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 1, &self->propellerAnimator, true, 0);
88
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 7, &self->rackAnimator, true, 6);
89
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 2, &self->whirlpoolAnimator, true, 0);
90
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 3, &self->whirlpoolTopAnimator, true, 0);
91
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 5, &self->whirlpoolBottomAnimator, true, 0);
92
93
// ???
94
// The HCZ1 boss health is managed by DiveEggman... so what was this for??
95
self->health = 8;
96
self->propellerAnimator.speed = 0;
97
self->state = ScrewMobile_State_CheckPlayerEnter;
98
self->stateDraw = ScrewMobile_Draw_ScrewMobile;
99
}
100
}
101
}
102
}
103
104
void ScrewMobile_StageLoad(void)
105
{
106
if (RSDK.CheckSceneFolder("HCZ"))
107
ScrewMobile->aniFrames = RSDK.LoadSpriteAnimation("HCZ/ScrewMobile.bin", SCOPE_STAGE);
108
109
ScrewMobile->hitboxCockpit.left = -32;
110
ScrewMobile->hitboxCockpit.top = -20;
111
ScrewMobile->hitboxCockpit.right = 32;
112
ScrewMobile->hitboxCockpit.bottom = 20;
113
114
ScrewMobile->hitboxDepthCharge.left = -8;
115
ScrewMobile->hitboxDepthCharge.top = -4;
116
ScrewMobile->hitboxDepthCharge.right = 8;
117
ScrewMobile->hitboxDepthCharge.bottom = 4;
118
119
ScrewMobile->playingFanSfx = false;
120
ScrewMobile->fanSfxTimer = 0;
121
ScrewMobile->active = ACTIVE_ALWAYS;
122
123
ScrewMobile->sfxButton = RSDK.GetSfx("Stage/Button2.wav");
124
ScrewMobile->sfxEggMobile = RSDK.GetSfx("HCZ/EggMobile.wav");
125
ScrewMobile->sfxBigFan = RSDK.GetSfx("HCZ/BigFan.wav");
126
ScrewMobile->sfxImpact = RSDK.GetSfx("Stage/Impact5.wav");
127
}
128
129
void ScrewMobile_State_CheckPlayerEnter(void)
130
{
131
RSDK_THIS(ScrewMobile);
132
133
Zone->cameraBoundsR[0] = (self->position.x >> 16) + 32;
134
Zone->playerBoundsR[0] = Zone->cameraBoundsR[0] << 16;
135
Zone->playerBoundActiveR[0] = true;
136
137
if (Player->playerCount > 1) {
138
EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
139
140
if (Player_CheckCollisionTouch(player2, self, &ScrewMobile->hitboxCockpit)) {
141
player2->direction = FLIP_X;
142
player2->state = Player_State_Static;
143
player2->velocity.x = 0;
144
player2->velocity.y = 0;
145
player2->groundVel = 0;
146
player2->position.x = self->position.x;
147
player2->position.y = self->position.y - 0x100000;
148
player2->tileCollisions = TILECOLLISION_DOWN;
149
RSDK.SetSpriteAnimation(player2->aniFrames, ANI_IDLE, &player2->animator, true, 0);
150
}
151
}
152
153
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
154
if (Player_CheckCollisionTouch(player1, self, &ScrewMobile->hitboxCockpit)) {
155
Zone->cameraBoundsT[0] = (self->position.y >> 16) - 40;
156
Zone->playerBoundsR[0] = 0x7FFF;
157
Zone->cameraBoundsR[0] = 0x7FFF;
158
Zone->playerBoundActiveR[0] = false;
159
160
player1->state = Player_State_Static;
161
player1->velocity.x = 0;
162
player1->velocity.y = 0;
163
player1->groundVel = 0;
164
player1->direction = FLIP_X;
165
player1->position.x = self->position.x;
166
player1->position.y = self->position.y - 0x100000;
167
player1->tileCollisions = TILECOLLISION_DOWN;
168
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_IDLE, &player1->animator, true, 0);
169
170
Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);
171
RSDK.PlaySfx(ScrewMobile->sfxEggMobile, false, 255);
172
DCEvent->canExplodeBombs = true;
173
self->state = ScrewMobile_State_PlayerRiding;
174
}
175
}
176
177
void ScrewMobile_State_PlayerRiding(void)
178
{
179
RSDK_THIS(ScrewMobile);
180
181
RSDK.ProcessAnimation(&self->propellerAnimator);
182
RSDK.ProcessAnimation(&self->rackAnimator);
183
RSDK.ProcessAnimation(&self->whirlpoolAnimator);
184
RSDK.ProcessAnimation(&self->whirlpoolTopAnimator);
185
RSDK.ProcessAnimation(&self->whirlpoolBottomAnimator);
186
187
self->position.y = BadnikHelpers_Oscillate(self->startPos.y, 2, 10);
188
self->position.x += self->velocity.x;
189
190
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
191
if (Player_CheckValidState(player1)) {
192
player1->position.x = self->position.x;
193
player1->position.y = self->position.y - 0x100000;
194
player1->velocity.x = 0;
195
player1->velocity.y = 0;
196
player1->outtaHereTimer = 0;
197
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_IDLE, &player1->animator, true, 0);
198
199
if ((player1->left || player1->right) && !player1->jumpHold) {
200
if (player1->left) {
201
self->velocity.x -= 0xC00;
202
203
if (self->velocity.x > 0)
204
self->velocity.x -= 0x1200;
205
else if (self->velocity.x < -0x20000)
206
self->velocity.x = -0x20000;
207
}
208
else if (player1->right) {
209
self->velocity.x += 0xC00;
210
211
if (self->velocity.x < 0)
212
self->velocity.x += 0x1200;
213
else if (self->velocity.x > 0x20000)
214
self->velocity.x = 0x20000;
215
}
216
}
217
else {
218
if (self->velocity.x) {
219
if (self->velocity.x >= 0) {
220
self->velocity.x -= 0xC00;
221
222
if (self->velocity.x < 0)
223
self->velocity.x = 0;
224
}
225
else {
226
self->velocity.x += 0xC00;
227
228
if (self->velocity.x > 0)
229
self->velocity.x = 0;
230
}
231
}
232
}
233
234
if (self->velocity.x) {
235
if (self->velocity.x <= 0) {
236
self->direction = FLIP_NONE;
237
238
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -0x200000, 0, true)) {
239
if (self->velocity.x <= -0x20000)
240
RSDK.PlaySfx(ScrewMobile->sfxImpact, false, 0xFF);
241
242
self->velocity.x = 0;
243
}
244
}
245
else {
246
self->direction = FLIP_X;
247
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x200000, 0, true)) {
248
if (self->velocity.x >= 0x20000)
249
RSDK.PlaySfx(ScrewMobile->sfxImpact, false, 0xFF);
250
251
self->velocity.x = 0;
252
}
253
}
254
}
255
256
player1->direction = self->direction ^ FLIP_X;
257
}
258
259
if (Player->playerCount >= 2) {
260
EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
261
262
if (Player_CheckValidState(player2)) {
263
if (player2->state == Player_State_Static) {
264
player2->position.x = self->position.x;
265
player2->position.y = self->position.y - 0x100000;
266
player2->velocity.x = 0;
267
player2->velocity.y = 0;
268
player2->outtaHereTimer = 0;
269
player2->direction = self->direction ^ FLIP_X;
270
RSDK.SetSpriteAnimation(player2->aniFrames, ANI_IDLE, &player2->animator, true, 0);
271
}
272
else if (Player_CheckCollisionTouch(player2, self, &ScrewMobile->hitboxCockpit)) {
273
player2->state = Player_State_Static;
274
player2->velocity.x = 0;
275
player2->velocity.y = 0;
276
player2->groundVel = 0;
277
player2->direction = FLIP_X;
278
player2->position.x = self->position.x;
279
player2->position.y = self->position.y - 0x100000;
280
player2->drawGroup = Zone->playerDrawGroup[0];
281
player2->tileCollisions = TILECOLLISION_DOWN;
282
player2->direction = self->direction ^ FLIP_X;
283
RSDK.SetSpriteAnimation(player2->aniFrames, ANI_IDLE, &player2->animator, true, 0);
284
}
285
}
286
}
287
288
if (Player_CheckValidState(player1)) {
289
if (player1->jumpPress) {
290
if (!Zone->cameraBoundsT[0]) {
291
Player_Action_Jump(player1);
292
self->state = ScrewMobile_State_Idle;
293
return;
294
}
295
296
if (!self->whirlPoolTimer && ScrewMobile->playingFanSfx == false) {
297
self->propellerAnimator.speed = 64;
298
RSDK.PlaySfx(ScrewMobile->sfxButton, false, 255);
299
}
300
}
301
if (!player1->jumpHold || self->whirlPoolTimer) {
302
EntityWhirlpool *whirlpool = self->whirlpool;
303
if (whirlpool) {
304
if (whirlpool->classID == Whirlpool->classID)
305
whirlpool->activePlayers = -3;
306
307
self->whirlpool = NULL;
308
}
309
310
if (self->propellerAnimator.speed)
311
self->propellerAnimator.speed -= 2;
312
313
if (self->propellerAnimator.speed > 0xC0)
314
++ScrewMobile->fanSfxTimer;
315
}
316
else {
317
if (self->whirlpoolHeight > 0) {
318
EntityWhirlpool *whirlpool = self->whirlpool;
319
320
if (whirlpool) {
321
if (whirlpool->classID == Whirlpool->classID)
322
whirlpool->position.x = self->position.x;
323
else
324
self->whirlpool = NULL;
325
}
326
else {
327
Vector2 pos;
328
pos.x = 0x1000000;
329
pos.y = 0x1000000;
330
whirlpool = CREATE_ENTITY(Whirlpool, &pos, self->position.x, self->startPos.y + 0xF00000);
331
whirlpool->activePlayers = -1;
332
whirlpool->angVel = 10;
333
whirlpool->alpha = 0;
334
whirlpool->isPermanent = true;
335
self->whirlpool = whirlpool;
336
}
337
}
338
339
if (self->propellerAnimator.speed < 0x100)
340
self->propellerAnimator.speed += 2;
341
342
if (self->propellerAnimator.speed > 0x40)
343
++ScrewMobile->fanSfxTimer;
344
}
345
}
346
347
if (self->propellerAnimator.speed < 0xF0) {
348
if (self->whirlpoolHeight > 0)
349
self->whirlpoolHeight--;
350
}
351
else {
352
if (self->whirlpoolHeight < 86)
353
self->whirlpoolHeight++;
354
}
355
356
if (player1->down) {
357
if (!self->bombPress && !self->timer && self->rackAnimator.frameID == 6) {
358
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 7, &self->rackAnimator, true, 0);
359
self->bombPress = true;
360
}
361
}
362
else {
363
self->bombPress = false;
364
}
365
366
if (self->rackAnimator.frameID == 2 && !self->timer) {
367
self->timer = 60;
368
369
EntityScrewMobile *bomb = CREATE_ENTITY(ScrewMobile, INT_TO_VOID(SCREWMOBILE_BOMB), self->position.x, self->position.y + 0x130000);
370
if (self->direction)
371
bomb->position.x -= 0x350000;
372
else
373
bomb->position.x += 0x350000;
374
bomb->direction = self->direction;
375
bomb->velocity.y = -0x7000;
376
}
377
378
if (self->whirlPoolTimer > (player1->jumpHold == true))
379
self->whirlPoolTimer--;
380
381
if (self->timer)
382
self->timer--;
383
384
if (self->invincibilityTimer > 0)
385
self->invincibilityTimer--;
386
}
387
388
void ScrewMobile_State_BossFinished(void)
389
{
390
RSDK_THIS(ScrewMobile);
391
392
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
393
player1->up = false;
394
player1->down = false;
395
player1->left = false;
396
player1->right = true;
397
player1->jumpPress = false;
398
player1->jumpHold = false;
399
400
ScrewMobile_State_PlayerRiding();
401
402
Zone->cameraBoundsL[0] = ScreenInfo->position.x;
403
Zone->playerBoundsL[0] = Zone->cameraBoundsL[0] << 16;
404
405
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, 0x200000, 0, true)) {
406
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
407
Zone->cameraBoundsL[0] += 2;
408
ScreenInfo->position.x = Zone->cameraBoundsL[0];
409
Zone->playerBoundsL[0] = Zone->cameraBoundsL[0] << 16;
410
camera->position.x = Zone->cameraBoundsL[0] << 16;
411
412
if (Zone->cameraBoundsL[0] >= (self->position.x >> 16) - 32)
413
self->state = ScrewMobile_State_Idle;
414
}
415
}
416
417
void ScrewMobile_State_Idle(void)
418
{
419
RSDK_THIS(ScrewMobile);
420
421
self->position.y = BadnikHelpers_Oscillate(self->startPos.y, 2, 10);
422
423
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
424
if (player1->state == Player_State_Static) {
425
if (player1->jumpPress) {
426
Player_Action_Jump(player1);
427
}
428
else {
429
player1->position.x = self->position.x;
430
player1->position.y = self->position.y;
431
player1->position.y -= 0x100000;
432
player1->velocity.x = 0;
433
player1->velocity.y = 0;
434
player1->outtaHereTimer = 0;
435
player1->direction = self->direction ^ FLIP_X;
436
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_IDLE, &player1->animator, true, 0);
437
}
438
}
439
else if (player1->velocity.y >= 0 && Player_CheckCollisionTouch(player1, self, &ScrewMobile->hitboxCockpit)) {
440
player1->state = Player_State_Static;
441
player1->velocity.x = 0;
442
player1->velocity.y = 0;
443
player1->groundVel = 0;
444
player1->direction = FLIP_X;
445
player1->position.x = self->position.x;
446
player1->position.y = self->position.y;
447
player1->position.y -= 0x100000;
448
player1->drawGroup = Zone->playerDrawGroup[0];
449
player1->tileCollisions = TILECOLLISION_DOWN;
450
player1->direction = self->direction ^ FLIP_X;
451
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_IDLE, &player1->animator, true, 0);
452
}
453
454
if (Player->playerCount >= 2) {
455
EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
456
457
if (player2->state == Player_State_Static) {
458
if (player2->jumpPress) {
459
Player_Action_Jump(player2);
460
}
461
else {
462
player2->position.x = self->position.x;
463
player2->position.y = self->position.y;
464
player2->position.y -= 0x100000;
465
player2->velocity.x = 0;
466
player2->velocity.y = 0;
467
player2->outtaHereTimer = 0;
468
player2->direction = self->direction ^ FLIP_X;
469
RSDK.SetSpriteAnimation(player2->aniFrames, ANI_IDLE, &player2->animator, true, 0);
470
}
471
}
472
else if (player2->velocity.y >= 0) {
473
if (Player_CheckCollisionTouch(player2, self, &ScrewMobile->hitboxCockpit)) {
474
player2->state = Player_State_Static;
475
player2->velocity.x = 0;
476
player2->velocity.y = 0;
477
player2->groundVel = 0;
478
player2->direction = FLIP_X;
479
player2->position.x = self->position.x;
480
player2->position.y = self->position.y;
481
player2->position.y -= 0x100000;
482
player2->drawGroup = Zone->playerDrawGroup[0];
483
player2->tileCollisions = TILECOLLISION_DOWN;
484
player2->direction = self->direction ^ FLIP_X;
485
RSDK.SetSpriteAnimation(player2->aniFrames, ANI_IDLE, &player2->animator, true, 0);
486
}
487
}
488
}
489
}
490
491
void ScrewMobile_Draw_ScrewMobile(void)
492
{
493
RSDK_THIS(ScrewMobile);
494
495
if (SceneInfo->currentDrawGroup == Zone->playerDrawGroup[0] - 1) {
496
self->mobileAnimator.frameID = 1;
497
RSDK.DrawSprite(&self->mobileAnimator, NULL, false);
498
}
499
else {
500
if (self->invincibilityTimer & 1)
501
RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);
502
503
self->mobileAnimator.frameID = 0;
504
RSDK.DrawSprite(&self->mobileAnimator, NULL, false);
505
RSDK.SetPaletteEntry(0, 128, 0x0000);
506
RSDK.DrawSprite(&self->rackAnimator, NULL, false);
507
508
int32 storeDir = self->direction;
509
510
self->direction = FLIP_NONE;
511
RSDK.DrawSprite(&self->propellerAnimator, NULL, false);
512
513
if (self->propellerAnimator.speed >= 0x40) {
514
Vector2 drawPos = self->position;
515
516
self->inkEffect = INK_ALPHA;
517
if (self->whirlpoolHeight <= 0) {
518
self->alpha = self->propellerAnimator.speed;
519
}
520
else {
521
self->alpha = 0xD0;
522
drawPos.y = Water->waterLevel - 0x100000;
523
524
SpriteFrame *frame = RSDK.GetFrame(ScrewMobile->aniFrames, 2, self->whirlpoolAnimator.frameID);
525
526
frame->height = 32;
527
frame->sprY = 33 * self->whirlpoolAnimator.frameID + 181;
528
frame->pivotY = -16;
529
530
int32 count = self->whirlpoolHeight >> 5;
531
for (int32 i = 0; i < count; ++i) {
532
RSDK.DrawSprite(&self->whirlpoolAnimator, &drawPos, false);
533
drawPos.y -= 0x200000;
534
}
535
536
frame->height = self->whirlpoolHeight % 32;
537
frame->sprY += 31 - frame->height;
538
frame->pivotY = 16 - frame->height;
539
RSDK.DrawSprite(&self->whirlpoolAnimator, &drawPos, false);
540
drawPos.y = Water->waterLevel;
541
RSDK.DrawSprite(&self->whirlpoolBottomAnimator, &drawPos, false);
542
self->alpha = 0x100;
543
}
544
545
drawPos.y = Water->waterLevel - (self->whirlpoolHeight << 16);
546
RSDK.DrawSprite(&self->whirlpoolTopAnimator, &drawPos, false);
547
self->inkEffect = INK_NONE;
548
}
549
550
self->direction = storeDir;
551
}
552
}
553
554
void ScrewMobile_StateDepthCharge_Active(void)
555
{
556
RSDK_THIS(ScrewMobile);
557
558
if (RSDK.CheckOnScreen(self, NULL)) {
559
self->position.y += self->velocity.y;
560
561
if (self->whirlpoolHeight == 0x3800 && self->position.y >= Water->waterLevel) {
562
self->velocity.y = self->velocity.y >> 2;
563
self->whirlpoolHeight = 0;
564
CREATE_ENTITY(Water, INT_TO_VOID(WATER_SPLASH), self->position.x, Water->waterLevel);
565
RSDK.PlaySfx(Water->sfxSplash, false, 255);
566
}
567
568
self->velocity.y += self->whirlpoolHeight; // this is "gravityStrength" here
569
570
foreach_active(DiveEggman, eggman)
571
{
572
if (eggman->state == DiveEggman_StateBomb_Idle || eggman->state == DiveEggman_StateBomb_InWhirlpool
573
|| eggman->state == DiveEggman_StateBomb_WhirlpoolRise || eggman->state == DiveEggman_StateBomb_Falling) {
574
if (RSDK.CheckObjectCollisionTouchBox(self, &ScrewMobile->hitboxDepthCharge, eggman, &DiveEggman->hitboxBomb)) {
575
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), eggman->position.x, eggman->position.y)->drawGroup =
576
Zone->objectDrawGroup[1];
577
RSDK.PlaySfx(DiveEggman->sfxExplosion, false, 255);
578
579
EntityWater *water = CREATE_ENTITY(Water, INT_TO_VOID(WATER_BUBBLE), eggman->position.x, eggman->position.y);
580
water->velocity.y = -0x8800;
581
water->angle = 2 * RSDK.Rand(0, 256);
582
water->bubbleX = water->position.x;
583
water->childPtr = NULL;
584
RSDK.SetSpriteAnimation(Water->aniFrames, 3, &water->animator, true, 0);
585
586
destroyEntity(eggman);
587
destroyEntity(self);
588
foreach_break;
589
}
590
}
591
else if (RSDK.CheckObjectCollisionTouchBox(self, &ScrewMobile->hitboxDepthCharge, eggman, &DiveEggman->hitboxEggman)) {
592
RSDK.PlaySfx(DiveEggman->sfxRockemSockem, false, 255);
593
594
self->velocity.x = RSDK.Rand(-4, 5) << 15;
595
self->velocity.y = -0x20000;
596
self->state = ScrewMobile_StateDepthCharge_Debris;
597
foreach_break;
598
}
599
}
600
}
601
else {
602
destroyEntity(self);
603
}
604
}
605
606
void ScrewMobile_StateDepthCharge_Debris(void)
607
{
608
RSDK_THIS(ScrewMobile);
609
610
self->position.x += self->velocity.x;
611
self->position.y += self->velocity.y;
612
self->velocity.y += 0x2800;
613
self->visible ^= true;
614
615
if (!RSDK.CheckOnScreen(self, NULL))
616
destroyEntity(self);
617
}
618
619
void ScrewMobile_Draw_DepthCharge(void)
620
{
621
RSDK_THIS(ScrewMobile);
622
623
RSDK.DrawSprite(&self->mobileAnimator, NULL, false);
624
}
625
626
#if GAME_INCLUDE_EDITOR
627
void ScrewMobile_EditorDraw(void)
628
{
629
RSDK_THIS(ScrewMobile);
630
631
self->startPos = self->position;
632
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 0, &self->mobileAnimator, true, 0);
633
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 1, &self->propellerAnimator, true, 0);
634
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 7, &self->rackAnimator, true, 6);
635
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 2, &self->whirlpoolAnimator, true, 0);
636
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 3, &self->whirlpoolTopAnimator, true, 0);
637
RSDK.SetSpriteAnimation(ScrewMobile->aniFrames, 5, &self->whirlpoolBottomAnimator, true, 0);
638
self->propellerAnimator.speed = 0;
639
640
ScrewMobile_Draw_ScrewMobile();
641
}
642
643
void ScrewMobile_EditorLoad(void) { ScrewMobile->aniFrames = RSDK.LoadSpriteAnimation("HCZ/ScrewMobile.bin", SCOPE_STAGE); }
644
#endif
645
646
void ScrewMobile_Serialize(void) {}
647
648