Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/OOZ/MeterDroid.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: MeterDroid Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectMeterDroid *MeterDroid;
11
12
void MeterDroid_Update(void)
13
{
14
RSDK_THIS(MeterDroid);
15
16
if (self->invincibilityTimer > 0)
17
self->invincibilityTimer--;
18
19
StateMachine_Run(self->state);
20
}
21
22
void MeterDroid_LateUpdate(void) {}
23
24
void MeterDroid_StaticUpdate(void) {}
25
26
void MeterDroid_Draw(void)
27
{
28
RSDK_THIS(MeterDroid);
29
30
if (self->bgFadeAmount > 0)
31
RSDK.SetLimitedFade(0, 1, 3, self->bgFadeAmount, 32, 47);
32
else if (self->invincibilityTimer & 1)
33
RSDK.CopyPalette(2, 32, 0, 32, 16);
34
35
if (self->stateDraw) {
36
StateMachine_Run(self->stateDraw);
37
}
38
else {
39
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
40
}
41
42
if (self->bgFadeAmount > 0 || (self->invincibilityTimer & 1))
43
RSDK.CopyPalette(1, 32, 0, 32, 16);
44
}
45
46
void MeterDroid_Create(void *data)
47
{
48
RSDK_THIS(MeterDroid);
49
50
if (!SceneInfo->inEditor) {
51
if (globals->gameMode == MODE_TIMEATTACK) {
52
destroyEntity(self);
53
}
54
else {
55
self->origin = self->position;
56
self->active = ACTIVE_BOUNDS;
57
self->updateRange.x = 0x800000;
58
self->updateRange.y = 0x800000;
59
self->health = 6;
60
self->drawGroup = Zone->objectDrawGroup[0];
61
self->state = MeterDroid_State_Init;
62
63
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 1, &self->mainAnimator, true, 0);
64
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 8, &self->propellorAnimator, true, 0);
65
}
66
}
67
}
68
69
void MeterDroid_StageLoad(void)
70
{
71
MeterDroid->aniFrames = RSDK.LoadSpriteAnimation("OOZ/MeterDroid.bin", SCOPE_STAGE);
72
73
MeterDroid->hitboxBoss.left = -14;
74
MeterDroid->hitboxBoss.top = -14;
75
MeterDroid->hitboxBoss.right = 14;
76
MeterDroid->hitboxBoss.bottom = 14;
77
78
MeterDroid->hitboxPropellor.left = 14;
79
MeterDroid->hitboxPropellor.top = -12;
80
MeterDroid->hitboxPropellor.right = 32;
81
MeterDroid->hitboxPropellor.bottom = 12;
82
83
MeterDroid->hitboxWrench.left = -14;
84
MeterDroid->hitboxWrench.top = -14;
85
MeterDroid->hitboxWrench.right = 14;
86
MeterDroid->hitboxWrench.bottom = 14;
87
88
MeterDroid->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");
89
MeterDroid->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");
90
MeterDroid->sfxDestroy = RSDK.GetSfx("Global/Destroy.wav");
91
MeterDroid->sfxToss = RSDK.GetSfx("OOZ/Toss.wav");
92
MeterDroid->sfxGrab = RSDK.GetSfx("Global/Grab.wav");
93
MeterDroid->sfxValve = RSDK.GetSfx("OOZ/Valve.wav");
94
MeterDroid->sfxWrench = RSDK.GetSfx("OOZ/Wrench.wav");
95
}
96
97
void MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip(void)
98
{
99
RSDK_THIS(MeterDroid);
100
101
foreach_active(Player, player)
102
{
103
if (!self->invincibilityTimer) {
104
if (Player_CheckBadnikTouch(player, self, &MeterDroid->hitboxBoss) && Player_CheckBossHit(player, self)) {
105
MeterDroid_Hit();
106
}
107
108
if (!self->invincibilityTimer) {
109
if (Player_CheckCollisionTouch(player, self, &MeterDroid->hitboxPropellor)) {
110
#if MANIA_USE_PLUS
111
if (!Player_CheckMightyUnspin(player, 0x400, false, &player->uncurlTimer))
112
#endif
113
Player_Hurt(player, self);
114
}
115
}
116
}
117
}
118
119
self->direction = RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x >= self->position.x;
120
}
121
122
void MeterDroid_CheckPlayerCollisions_Wrench_NoFlip(void)
123
{
124
RSDK_THIS(MeterDroid);
125
126
foreach_active(Player, player)
127
{
128
int32 storeX = self->position.x;
129
int32 storeY = self->position.y;
130
131
if (!self->invincibilityTimer) {
132
if (Player_CheckBadnikTouch(player, self, &MeterDroid->hitboxBoss) && Player_CheckBossHit(player, self)) {
133
MeterDroid_Hit();
134
}
135
136
if (!self->invincibilityTimer) {
137
if (Player_CheckCollisionTouch(player, self, &MeterDroid->hitboxPropellor)) {
138
#if MANIA_USE_PLUS
139
if (!Player_CheckMightyUnspin(player, 0x400, false, &player->uncurlTimer))
140
#endif
141
Player_Hurt(player, self);
142
}
143
}
144
}
145
146
self->position.x = self->wrenchPos.x;
147
self->position.y = self->wrenchPos.y;
148
149
if (Player_CheckCollisionTouch(player, self, &MeterDroid->hitboxWrench)) {
150
#if MANIA_USE_PLUS
151
if (!Player_CheckMightyUnspin(player, 0x600, false, &player->uncurlTimer))
152
#endif
153
Player_Hurt(player, self);
154
}
155
156
self->position.x = storeX;
157
self->position.y = storeY;
158
}
159
}
160
161
void MeterDroid_CheckPlayerCollisions_NoWrench_NoFlip(void)
162
{
163
RSDK_THIS(MeterDroid);
164
165
foreach_active(Player, player)
166
{
167
if (!self->invincibilityTimer) {
168
if (Player_CheckBadnikTouch(player, self, &MeterDroid->hitboxBoss) && Player_CheckBossHit(player, self)) {
169
MeterDroid_Hit();
170
}
171
172
if (!self->invincibilityTimer) {
173
if (Player_CheckCollisionTouch(player, self, &MeterDroid->hitboxPropellor)) {
174
#if MANIA_USE_PLUS
175
if (!Player_CheckMightyUnspin(player, 0x400, false, &player->uncurlTimer))
176
#endif
177
Player_Hurt(player, self);
178
}
179
}
180
}
181
}
182
}
183
184
void MeterDroid_Hit(void)
185
{
186
RSDK_THIS(MeterDroid);
187
188
if (--self->health <= 0) {
189
self->state = MeterDroid_State_Destroyed;
190
self->timer = 0;
191
192
if (self->stateDraw == MeterDroid_Draw_ThrownWrench) {
193
int32 x = RSDK.Rand(MeterDroid->hitboxBoss.left, MeterDroid->hitboxBoss.right) << 16;
194
int32 y = RSDK.Rand(MeterDroid->hitboxBoss.top, MeterDroid->hitboxBoss.bottom) << 16;
195
196
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), x + self->wrenchPos.x, y + self->wrenchPos.y)->drawGroup = Zone->objectDrawGroup[1];
197
self->stateDraw = MeterDroid_Draw_Normal;
198
}
199
200
SceneInfo->timeEnabled = false;
201
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);
202
}
203
else {
204
self->invincibilityTimer = 48;
205
RSDK.PlaySfx(MeterDroid->sfxHit, false, 0xFF);
206
}
207
}
208
209
void MeterDroid_Explode(void)
210
{
211
RSDK_THIS(MeterDroid);
212
213
if (!(Zone->timer % 3)) {
214
if (self->state == MeterDroid_State_FinishAct) {
215
if (self->timer < 180) {
216
if (self->timer <= 60)
217
RSDK.PlaySfx(MeterDroid->sfxExplosion, Zone->timer % 3, 255);
218
else
219
RSDK.PlaySfx(MeterDroid->sfxDestroy, Zone->timer % 3, 255);
220
}
221
}
222
else {
223
RSDK.PlaySfx(MeterDroid->sfxExplosion, false, 255);
224
}
225
226
if (Zone->timer & 4) {
227
int32 x = (RSDK.Rand(-208, 208) + ScreenInfo->center.x + ScreenInfo->position.x) << 16;
228
int32 y = (RSDK.Rand(-112, 112) + ScreenInfo->center.y + ScreenInfo->position.y) << 16;
229
EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID(2 * (RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y);
230
explosion->drawGroup = Zone->objectDrawGroup[1];
231
}
232
}
233
}
234
235
void MeterDroid_FindTargetValve(void)
236
{
237
RSDK_THIS(MeterDroid);
238
239
EntityValve *valves[5];
240
for (int32 i = 0; i < 5; ++i) valves[i] = NULL;
241
242
int32 id = 1;
243
foreach_active(Valve, valve) { valves[id++] = valve; }
244
245
valves[0] = valves[RSDK.Rand(1, id)];
246
self->targetValve = valves[0];
247
self->direction = valves[0]->direction ^ FLIP_X;
248
self->targetPos.x = valves[0]->position.x;
249
self->targetPos.y = valves[0]->position.y;
250
251
self->targetPos.x += valves[0]->direction == FLIP_NONE ? 0x2E0000 : -0x2E0000;
252
self->targetPos.y -= 0xC0000;
253
254
self->moveVel.x = (self->targetPos.x - self->position.x) >> 11;
255
self->moveVel.y = (self->targetPos.y - self->position.y) >> 11;
256
257
self->velocity.x = 0;
258
self->velocity.y = 0;
259
}
260
261
void MeterDroid_PopPlatforms(void)
262
{
263
int32 delay = 30;
264
265
foreach_active(GasPlatform, platform)
266
{
267
platform->type = GASPLATFORM_BOSS;
268
platform->timer = delay;
269
platform->state = GasPlatform_State_Shaking;
270
delay += 16;
271
}
272
}
273
274
void MeterDroid_Draw_Normal(void)
275
{
276
RSDK_THIS(MeterDroid);
277
278
self->drawFX = FX_FLIP;
279
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
280
281
self->drawFX = FX_NONE;
282
RSDK.DrawSprite(&self->propellorAnimator, NULL, false);
283
}
284
285
void MeterDroid_Draw_SpinningValve(void)
286
{
287
RSDK_THIS(MeterDroid);
288
289
self->drawFX = FX_FLIP;
290
RSDK.DrawSprite(&self->armAnimator, NULL, false);
291
292
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
293
294
self->drawFX = FX_NONE;
295
RSDK.DrawSprite(&self->propellorAnimator, NULL, false);
296
}
297
298
void MeterDroid_Draw_ThrownWrench(void)
299
{
300
RSDK_THIS(MeterDroid);
301
302
self->drawFX = FX_FLIP;
303
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
304
305
self->drawFX = FX_NONE;
306
RSDK.DrawSprite(&self->propellorAnimator, NULL, false);
307
308
self->drawFX = FX_FLIP;
309
RSDK.DrawSprite(&self->wrenchAnimator, &self->wrenchPos, false);
310
}
311
312
void MeterDroid_State_Init(void)
313
{
314
RSDK_THIS(MeterDroid);
315
316
if (++self->timer >= 8) {
317
self->timer = 0;
318
319
Zone->playerBoundActiveL[0] = true;
320
Zone->playerBoundActiveR[0] = true;
321
Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;
322
Zone->cameraBoundsR[0] = (self->position.x >> 16) + ScreenInfo->center.x;
323
Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - ScreenInfo->size.y - 64;
324
325
MeterDroid->boundsL = (Zone->cameraBoundsL[0] + 64) << 16;
326
MeterDroid->boundsR = (Zone->cameraBoundsR[0] - 64) << 16;
327
MeterDroid->boundsM = self->position.x;
328
MeterDroid->boundsT = (Zone->cameraBoundsT[0] + 48) << 16;
329
MeterDroid->boundsB = (Zone->cameraBoundsB[0] - 8) << 16;
330
331
self->position.x += 0x800000;
332
self->visible = true;
333
self->stateDraw = MeterDroid_Draw_Normal;
334
self->state = MeterDroid_State_StartFight;
335
}
336
}
337
338
void MeterDroid_State_StartFight(void)
339
{
340
RSDK_THIS(MeterDroid);
341
342
self->position.y = BadnikHelpers_Oscillate(self->origin.y, 4, 10);
343
344
RSDK.ProcessAnimation(&self->mainAnimator);
345
RSDK.ProcessAnimation(&self->propellorAnimator);
346
347
if (self->timer) {
348
if (++self->timer == 120) {
349
self->timer = 0;
350
self->state = MeterDroid_State_Idle;
351
}
352
}
353
else {
354
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
355
356
if (player1->position.x > self->position.x - 0x800000) {
357
Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);
358
++self->timer;
359
}
360
}
361
}
362
363
void MeterDroid_State_Idle(void)
364
{
365
RSDK_THIS(MeterDroid);
366
367
self->position.y = BadnikHelpers_Oscillate(self->origin.y, 4, 10);
368
369
RSDK.ProcessAnimation(&self->mainAnimator);
370
RSDK.ProcessAnimation(&self->propellorAnimator);
371
372
if (++self->timer == 90) {
373
self->timer = 0;
374
self->state = MeterDroid_State_PickMoveDir;
375
}
376
377
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
378
}
379
380
void MeterDroid_State_PickMoveDir(void)
381
{
382
RSDK_THIS(MeterDroid);
383
384
self->position.y = BadnikHelpers_Oscillate(self->origin.y, 4, 10);
385
386
RSDK.ProcessAnimation(&self->mainAnimator);
387
RSDK.ProcessAnimation(&self->propellorAnimator);
388
389
if (++self->timer == 60) {
390
self->timer = 0;
391
self->moveRadius = 0;
392
self->angle = 64;
393
394
if (self->position.x < MeterDroid->boundsM) {
395
self->direction = FLIP_X;
396
self->state = MeterDroid_State_MoveLeft;
397
}
398
else {
399
self->direction = FLIP_NONE;
400
self->state = MeterDroid_State_MoveRight;
401
}
402
}
403
404
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
405
}
406
407
void MeterDroid_State_MoveRight(void)
408
{
409
RSDK_THIS(MeterDroid);
410
411
RSDK.ProcessAnimation(&self->mainAnimator);
412
RSDK.ProcessAnimation(&self->propellorAnimator);
413
414
self->position.x += (self->moveRadius * RSDK.Cos256(self->angle)) >> 8;
415
self->position.y += (self->moveRadius * RSDK.Sin256(self->angle)) >> 8;
416
417
if (self->angle > 0x80) {
418
self->moveRadius -= 0x1400;
419
if (self->position.y < self->origin.y)
420
self->position.y = self->origin.y;
421
}
422
else {
423
self->moveRadius += 0x1400;
424
}
425
426
if (++self->angle == 0xC0) {
427
self->origin.x = self->position.x;
428
self->origin.y = self->position.y;
429
self->angle = 0;
430
self->state = MeterDroid_State_ThrowWrench;
431
}
432
433
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
434
}
435
436
void MeterDroid_State_MoveLeft(void)
437
{
438
RSDK_THIS(MeterDroid);
439
440
RSDK.ProcessAnimation(&self->mainAnimator);
441
RSDK.ProcessAnimation(&self->propellorAnimator);
442
443
self->position.x += (self->moveRadius * RSDK.Cos256(self->angle)) >> 8;
444
self->position.y += (self->moveRadius * RSDK.Sin256(self->angle)) >> 8;
445
446
if (self->angle < 0) {
447
self->moveRadius -= 0x1400;
448
449
if (self->position.y < self->origin.y)
450
self->position.y = self->origin.y;
451
}
452
else {
453
self->moveRadius += 0x1400;
454
}
455
456
if (--self->angle == -0x40) {
457
self->origin.x = self->position.x;
458
self->origin.y = self->position.y;
459
self->angle = 0;
460
self->state = MeterDroid_State_ThrowWrench;
461
}
462
463
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
464
}
465
466
void MeterDroid_State_ThrowWrench(void)
467
{
468
RSDK_THIS(MeterDroid);
469
470
self->position.y = BadnikHelpers_Oscillate(self->origin.y, 4, 10);
471
472
RSDK.ProcessAnimation(&self->mainAnimator);
473
RSDK.ProcessAnimation(&self->propellorAnimator);
474
RSDK.ProcessAnimation(&self->wrenchAnimator);
475
476
if (++self->timer >= 18) {
477
if (self->mainAnimator.animationID == 2 && self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)
478
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 0, &self->mainAnimator, true, 0);
479
}
480
else if (self->timer == 16) {
481
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 2, &self->mainAnimator, true, 0);
482
}
483
484
if (self->timer == 36) {
485
self->wrenchPos.x = self->position.x + (self->direction == FLIP_NONE ? -0x300000 : 0x300000);
486
self->wrenchPos.y = self->position.y - 0x100000;
487
488
self->targetPos.x = self->wrenchPos.x;
489
self->targetPos.y = self->wrenchPos.y;
490
491
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
492
self->wrenchMoveVel.x = (player1->position.x + 16 * player1->velocity.x - self->wrenchPos.x) >> 5;
493
self->wrenchMoveVel.y = (player1->position.y + 16 * player1->velocity.y - self->wrenchPos.y) >> 5;
494
self->wrenchMoveInc.x = -(self->wrenchMoveVel.x >> 6);
495
self->wrenchMoveInc.y = -(self->wrenchMoveVel.y >> 6);
496
497
RSDK.PlaySfx(MeterDroid->sfxToss, false, 255);
498
RSDK.PlaySfx(MeterDroid->sfxWrench, false, 255);
499
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 9, &self->wrenchAnimator, true, 0);
500
501
self->stateDraw = MeterDroid_Draw_ThrownWrench;
502
}
503
504
if (self->stateDraw == MeterDroid_Draw_ThrownWrench) {
505
self->wrenchMoveVel.x += self->wrenchMoveInc.x;
506
self->wrenchMoveVel.y += self->wrenchMoveInc.y;
507
self->wrenchPos.x += self->wrenchMoveVel.x;
508
self->wrenchPos.y += self->wrenchMoveVel.y;
509
510
if (self->timer == 60)
511
self->state = MeterDroid_State_ThrownWrench;
512
513
MeterDroid_CheckPlayerCollisions_Wrench_NoFlip();
514
}
515
else {
516
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
517
}
518
}
519
520
void MeterDroid_State_ThrownWrench(void)
521
{
522
RSDK_THIS(MeterDroid);
523
524
self->position.y = BadnikHelpers_Oscillate(self->origin.y, 4, 10);
525
526
RSDK.ProcessAnimation(&self->mainAnimator);
527
RSDK.ProcessAnimation(&self->propellorAnimator);
528
RSDK.ProcessAnimation(&self->wrenchAnimator);
529
530
self->wrenchMoveVel.x += self->wrenchMoveInc.x;
531
self->wrenchMoveVel.y += self->wrenchMoveInc.y;
532
self->wrenchPos.x += self->wrenchMoveVel.x;
533
self->wrenchPos.y += self->wrenchMoveVel.y;
534
535
int32 rx = abs(self->targetPos.x - self->wrenchPos.x) >> 16;
536
int32 ry = abs(self->targetPos.y - self->wrenchPos.y) >> 16;
537
538
if (rx * rx + ry * ry < 0x200) {
539
RSDK.PlaySfx(MeterDroid->sfxGrab, false, 0xFF);
540
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 3, &self->mainAnimator, true, 0);
541
542
self->stateDraw = MeterDroid_Draw_Normal;
543
self->state = MeterDroid_State_CaughtWrench;
544
}
545
546
MeterDroid_CheckPlayerCollisions_Wrench_NoFlip();
547
}
548
549
void MeterDroid_State_CaughtWrench(void)
550
{
551
RSDK_THIS(MeterDroid);
552
553
self->position.y = BadnikHelpers_Oscillate(self->origin.y, 4, 10);
554
555
RSDK.ProcessAnimation(&self->mainAnimator);
556
RSDK.ProcessAnimation(&self->propellorAnimator);
557
558
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
559
560
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1) {
561
self->timer = 0;
562
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 1, &self->mainAnimator, true, 0);
563
MeterDroid_FindTargetValve();
564
self->state = MeterDroid_State_MoveToValve;
565
}
566
567
MeterDroid_CheckPlayerCollisions_NoWrench_UseFlip();
568
}
569
570
void MeterDroid_State_MoveToValve(void)
571
{
572
RSDK_THIS(MeterDroid);
573
574
RSDK.ProcessAnimation(&self->mainAnimator);
575
RSDK.ProcessAnimation(&self->propellorAnimator);
576
577
if (abs(self->velocity.x) < 0x40000) {
578
if (abs(self->velocity.x) < 0x40000)
579
self->velocity.x += self->moveVel.x;
580
}
581
582
self->velocity.y += self->moveVel.y;
583
self->position.x += self->velocity.x;
584
self->position.y += self->velocity.y;
585
586
int32 rx = abs(self->targetPos.x - self->position.x) >> 16;
587
int32 ry = abs(self->targetPos.y - self->position.y) >> 16;
588
589
if (rx * rx + ry * ry < 96) {
590
self->direction = self->targetValve->direction;
591
self->drawGroup = Zone->objectDrawGroup[0] - 1;
592
self->state = MeterDroid_State_MoveIntoBG;
593
}
594
595
MeterDroid_CheckPlayerCollisions_NoWrench_NoFlip();
596
}
597
598
void MeterDroid_State_MoveIntoBG(void)
599
{
600
RSDK_THIS(MeterDroid);
601
602
RSDK.ProcessAnimation(&self->mainAnimator);
603
RSDK.ProcessAnimation(&self->propellorAnimator);
604
605
self->bgFadeAmount += 10;
606
607
self->velocity.x = self->velocity.x - (self->velocity.x >> 3);
608
self->velocity.y = self->velocity.y - (self->velocity.y >> 3);
609
self->position.x += ((self->targetPos.x - self->position.x) >> 3) + self->velocity.x;
610
self->position.y += ((self->targetPos.y - self->position.y) >> 3) + self->velocity.y;
611
612
if (++self->timer == 24) {
613
self->position.x = self->targetPos.x;
614
self->position.y = self->targetPos.y;
615
self->timer = 0;
616
617
EntityValve *valve = self->targetValve;
618
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 4, &self->mainAnimator, true, 0);
619
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 6, &self->armAnimator, true, 0);
620
RSDK.SetSpriteAnimation(Valve->aniFrames, 0, &valve->valveAnimator, true, 0);
621
RSDK.SetSpriteAnimation(Valve->aniFrames, 2, &valve->wheelAnimator, true, 0);
622
RSDK.PlaySfx(MeterDroid->sfxValve, false, 255);
623
624
self->state = MeterDroid_State_TurningValve;
625
self->stateDraw = MeterDroid_Draw_SpinningValve;
626
}
627
MeterDroid_CheckPlayerCollisions_NoWrench_NoFlip();
628
}
629
630
void MeterDroid_State_TurningValve(void)
631
{
632
RSDK_THIS(MeterDroid);
633
634
RSDK.ProcessAnimation(&self->mainAnimator);
635
RSDK.ProcessAnimation(&self->armAnimator);
636
RSDK.ProcessAnimation(&self->propellorAnimator);
637
638
if (++self->timer == 60)
639
MeterDroid_PopPlatforms();
640
641
if (self->timer == 90) {
642
self->timer = 0;
643
644
EntityValve *valve = self->targetValve;
645
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 5, &self->mainAnimator, true, 0);
646
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 7, &self->armAnimator, true, 0);
647
RSDK.SetSpriteAnimation(Valve->aniFrames, 1, &valve->valveAnimator, true, 0);
648
RSDK.SetSpriteAnimation(Valve->aniFrames, 3, &valve->wheelAnimator, true, 0);
649
650
self->state = MeterDroid_State_StopTurningValve;
651
}
652
}
653
654
void MeterDroid_State_StopTurningValve(void)
655
{
656
RSDK_THIS(MeterDroid);
657
658
RSDK.ProcessAnimation(&self->mainAnimator);
659
RSDK.ProcessAnimation(&self->armAnimator);
660
RSDK.ProcessAnimation(&self->propellorAnimator);
661
662
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)
663
self->state = MeterDroid_State_WatchPlatformsPopUp;
664
}
665
666
void MeterDroid_State_WatchPlatformsPopUp(void)
667
{
668
RSDK_THIS(MeterDroid);
669
670
RSDK.ProcessAnimation(&self->propellorAnimator);
671
672
++self->timer;
673
if (self->timer > 30) {
674
if (self->bgFadeAmount > 0)
675
self->bgFadeAmount -= 16;
676
}
677
678
if (self->timer == 60) {
679
self->timer = 0;
680
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 1, &self->mainAnimator, true, 0);
681
682
self->origin.x = self->position.x;
683
self->origin.y = self->position.y;
684
self->drawGroup = Zone->objectDrawGroup[0];
685
self->state = MeterDroid_State_PickMoveDir;
686
self->stateDraw = MeterDroid_Draw_Normal;
687
}
688
}
689
690
void MeterDroid_State_Destroyed(void)
691
{
692
RSDK_THIS(MeterDroid);
693
694
MeterDroid_Explode();
695
696
if (++self->timer == 60) {
697
MeterDroid->debrisSpeeds[2] = self->direction;
698
MeterDroid->debrisSpeeds[6] = self->direction;
699
MeterDroid->debrisSpeeds[10] = self->direction;
700
MeterDroid->debrisSpeeds[14] = self->direction;
701
702
if (self->direction == FLIP_X) {
703
MeterDroid->debrisSpeeds[3] = -MeterDroid->debrisSpeeds[3];
704
MeterDroid->debrisSpeeds[7] = -MeterDroid->debrisSpeeds[7];
705
MeterDroid->debrisSpeeds[11] = -MeterDroid->debrisSpeeds[11];
706
MeterDroid->debrisSpeeds[15] = -MeterDroid->debrisSpeeds[15];
707
}
708
709
Debris_CreateFromEntries(MeterDroid->aniFrames, MeterDroid->debrisSpeeds, 10);
710
self->visible = false;
711
}
712
else if (self->timer == 90) {
713
self->timer = 0;
714
self->visible = false;
715
Music_FadeOut(0.025);
716
CREATE_ENTITY(OOZFlames, NULL, self->position.x, self->position.y);
717
self->state = MeterDroid_State_FinishAct;
718
}
719
}
720
721
void MeterDroid_State_FinishAct(void)
722
{
723
RSDK_THIS(MeterDroid);
724
725
MeterDroid_Explode();
726
727
if (++self->timer == 180) {
728
for (int32 p = 0; p < Player->playerCount; ++p) StarPost->postIDs[p] = 0;
729
730
SaveGame_SavePlayerState();
731
globals->enableIntro = true;
732
++SceneInfo->listPos;
733
if (!RSDK.CheckValidScene())
734
RSDK.SetScene("Presentation", "Title Screen");
735
736
Zone_StartFadeOut(10, 0xF0F0F0);
737
}
738
739
if (self->timer == 240)
740
destroyEntity(self);
741
}
742
743
#if GAME_INCLUDE_EDITOR
744
void MeterDroid_EditorDraw(void)
745
{
746
RSDK_THIS(MeterDroid);
747
748
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 1, &self->mainAnimator, false, 0);
749
RSDK.SetSpriteAnimation(MeterDroid->aniFrames, 8, &self->propellorAnimator, false, 0);
750
751
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
752
753
if (showGizmos()) {
754
RSDK_DRAWING_OVERLAY(true);
755
756
DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE - 64, WIDE_SCR_XCENTER, 0, 1 | 0 | 4 | 0, 0x00C0F0);
757
758
RSDK_DRAWING_OVERLAY(false);
759
}
760
}
761
762
void MeterDroid_EditorLoad(void) { MeterDroid->aniFrames = RSDK.LoadSpriteAnimation("OOZ/MeterDroid.bin", SCOPE_STAGE); }
763
#endif
764
765
void MeterDroid_Serialize(void) {}
766
767