Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/MMZ/Gachapandora.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Gachapandora Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectGachapandora *Gachapandora;
11
12
void Gachapandora_Update(void)
13
{
14
RSDK_THIS(Gachapandora);
15
16
StateMachine_Run(self->state);
17
}
18
19
void Gachapandora_LateUpdate(void) {}
20
21
void Gachapandora_StaticUpdate(void)
22
{
23
// Bug Details:
24
// there's no NULL check here for Gachapandora->eggman so this will be called even on MMZ1 and its NULL.
25
// Gachapandora->eggman also isn't cleared on StageLoad so this can point to a random entity
26
RSDK.AddDrawListRef(Zone->objectDrawGroup[0] + 1, RSDK.GetEntitySlot(Gachapandora->eggman));
27
}
28
29
void Gachapandora_Draw(void)
30
{
31
RSDK_THIS(Gachapandora);
32
33
StateMachine_Run(self->stateDraw);
34
}
35
36
void Gachapandora_Create(void *data)
37
{
38
RSDK_THIS(Gachapandora);
39
40
self->drawFX = FX_FLIP;
41
if (!SceneInfo->inEditor) {
42
if (globals->gameMode < MODE_TIMEATTACK) {
43
self->active = ACTIVE_BOUNDS;
44
if (data)
45
self->type = VOID_TO_INT(data);
46
47
int32 capsuleOffset = 0;
48
switch (self->type) {
49
case GACHAPANDORA_MAIN:
50
self->visible = false;
51
self->drawGroup = Zone->objectDrawGroup[0];
52
53
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 0, &self->mainAnimator, true, 0);
54
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, true, 0);
55
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, true, 7);
56
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &self->capsuleAnimator, true, 7);
57
58
self->hitbox.left = -33;
59
self->hitbox.top = -37;
60
self->hitbox.right = 33;
61
self->hitbox.bottom = 6;
62
63
self->startY = self->position.y;
64
self->updateRange.x = 0x800000;
65
self->updateRange.y = 0x800000;
66
Gachapandora->eggman = self;
67
68
capsuleOffset = 55;
69
for (int32 i = GACHAPANDORA_CAPSULE_COUNT - 1; i >= 0; --i) {
70
int32 id = 0;
71
72
Gachapandora->capsuleTypeL[i] = RSDK.Rand(0, 6);
73
id = Gachapandora->capsuleTypeL[i] % 3;
74
75
while (id == Gachapandora->lastCapsuleType && Gachapandora->capsuleCount[id] == 3) {
76
Gachapandora->capsuleTypeL[i] = RSDK.Rand(0, 6);
77
id = Gachapandora->capsuleTypeL[i] % 3;
78
}
79
80
Gachapandora->lastCapsuleType = Gachapandora->capsuleTypeL[i] % 3;
81
++Gachapandora->capsuleCount[Gachapandora->lastCapsuleType];
82
Gachapandora->capsuleOffsetL[i] = 4 * capsuleOffset;
83
Gachapandora->capsuleMaxL[i] = 4 * capsuleOffset;
84
85
Gachapandora->capsuleTypeR[i] = RSDK.Rand(0, 6);
86
id = Gachapandora->capsuleTypeR[i] % 3;
87
88
while (id == Gachapandora->lastCapsuleType && i && Gachapandora->capsuleCount[id] == 3) {
89
Gachapandora->capsuleTypeR[i] = RSDK.Rand(0, 6);
90
id = Gachapandora->capsuleTypeR[i] % 3;
91
}
92
93
Gachapandora->lastCapsuleType = Gachapandora->capsuleTypeR[i] % 3;
94
++Gachapandora->capsuleCount[Gachapandora->lastCapsuleType];
95
Gachapandora->capsuleOffsetR[i] = 4 * capsuleOffset;
96
Gachapandora->capsuleMaxR[i] = 4 * capsuleOffset;
97
98
capsuleOffset -= 18;
99
}
100
101
Gachapandora->nextPrizeType = 0;
102
Gachapandora->handleSpinTimer = 0x7FFF;
103
Gachapandora->nextCapsuleL = 3;
104
Gachapandora->nextCapsuleR = 3;
105
Gachapandora->capsuleSide = RSDK.Rand(0, 2);
106
107
if (Gachapandora->capsuleSide == 1) {
108
for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {
109
int32 store = Gachapandora->capsuleTypeL[i];
110
Gachapandora->capsuleTypeL[i] = Gachapandora->capsuleTypeR[i];
111
Gachapandora->capsuleTypeR[i] = store;
112
}
113
}
114
115
self->state = Gachapandora_StateBoss_SetupArena;
116
self->stateDraw = Gachapandora_Draw_Boss;
117
break;
118
119
case GACHAPANDORA_EGGMAN:
120
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 4, &self->mainAnimator, true, 0);
121
122
self->state = Gachapandora_StateEggman_Falling;
123
self->stateDraw = Gachapandora_Draw_Simple;
124
125
self->updateRange.x = 0x800000;
126
self->updateRange.y = 0x800000;
127
self->active = ACTIVE_NORMAL;
128
self->visible = true;
129
self->drawGroup = Zone->objectDrawGroup[0];
130
break;
131
132
case GACHAPANDORA_PRIZE:
133
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &self->mainAnimator, true, 0);
134
135
self->state = Gachapandora_StatePrize_CapsuleFall;
136
self->stateDraw = Gachapandora_Draw_Prize;
137
138
self->updateRange.x = 0x800000;
139
self->updateRange.y = 0x800000;
140
self->active = ACTIVE_NORMAL;
141
self->visible = true;
142
self->drawGroup = Zone->objectDrawGroup[0];
143
break;
144
145
case GACHAPANDORA_AMY:
146
case GACHAPANDORA_DRILLER:
147
case GACHAPANDORA_FIREDROPPER: break;
148
149
case GACHAPANDORA_FIREBALL:
150
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 11, &self->mainAnimator, true, 0);
151
152
self->hitbox.left = -2;
153
self->hitbox.top = -2;
154
self->hitbox.right = 2;
155
self->hitbox.bottom = 2;
156
self->state = Gachapandora_StateFireball_Falling;
157
self->stateDraw = Gachapandora_Draw_Simple;
158
self->updateRange.x = 0x800000;
159
self->updateRange.y = 0x800000;
160
self->active = ACTIVE_NORMAL;
161
self->visible = true;
162
self->drawGroup = Zone->objectDrawGroup[0];
163
break;
164
165
case GACHAPANDORA_DEBRIS:
166
self->active = ACTIVE_NORMAL;
167
self->visible = true;
168
self->drawGroup = Zone->objectDrawGroup[0];
169
170
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 0, &self->mainAnimator, true, 0);
171
172
self->state = Gachapandora_StateDebris_Delay;
173
self->stateDraw = Gachapandora_Draw_Simple;
174
175
self->updateRange.x = 0x800000;
176
self->updateRange.y = 0x800000;
177
break;
178
179
case GACHAPANDORA_SPARK:
180
self->active = ACTIVE_NORMAL;
181
self->visible = true;
182
self->drawGroup = Zone->objectDrawGroup[1];
183
184
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 13, &self->mainAnimator, true, 0);
185
186
self->state = Gachapandora_StateSpark_Attached;
187
self->stateDraw = Gachapandora_Draw_Simple;
188
189
self->updateRange.x = 0x800000;
190
self->updateRange.y = 0x800000;
191
break;
192
193
default: break;
194
}
195
}
196
else {
197
destroyEntity(self);
198
}
199
}
200
}
201
202
void Gachapandora_StageLoad(void)
203
{
204
Gachapandora->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Gachapandora.bin", SCOPE_STAGE);
205
Gachapandora->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanMMZ2.bin", SCOPE_STAGE);
206
207
Gachapandora->hitboxHandle.left = -16;
208
Gachapandora->hitboxHandle.top = 22;
209
Gachapandora->hitboxHandle.right = 16;
210
Gachapandora->hitboxHandle.bottom = 30;
211
212
Gachapandora->hitboxAmyRange.left = -128;
213
Gachapandora->hitboxAmyRange.top = -256;
214
Gachapandora->hitboxAmyRange.right = 128;
215
Gachapandora->hitboxAmyRange.bottom = 256;
216
217
Gachapandora->hitboxAmy.left = -32;
218
Gachapandora->hitboxAmy.top = -32;
219
Gachapandora->hitboxAmy.right = 0;
220
Gachapandora->hitboxAmy.bottom = 32;
221
222
Gachapandora->hitboxFireball.left = -5;
223
Gachapandora->hitboxFireball.top = -11;
224
Gachapandora->hitboxFireball.right = 5;
225
Gachapandora->hitboxFireball.bottom = 0;
226
227
Gachapandora->hitboxDrill.left = -28;
228
Gachapandora->hitboxDrill.top = 3;
229
Gachapandora->hitboxDrill.right = -20;
230
Gachapandora->hitboxDrill.bottom = 10;
231
232
Gachapandora->hitboxSpark.left = -2;
233
Gachapandora->hitboxSpark.top = 2;
234
Gachapandora->hitboxSpark.right = -2;
235
Gachapandora->hitboxSpark.bottom = 2;
236
237
Gachapandora->active = ACTIVE_ALWAYS;
238
Gachapandora->activeToys = 0;
239
Gachapandora->awardAchievement = false;
240
Gachapandora->destroyedToys = 0;
241
Gachapandora->lastCapsuleType = -1;
242
Gachapandora->capsuleCount[0] = 0;
243
Gachapandora->capsuleCount[1] = 0;
244
Gachapandora->capsuleCount[2] = 0;
245
246
Gachapandora->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");
247
Gachapandora->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");
248
Gachapandora->sfxUnravel = RSDK.GetSfx("Stage/Unravel.wav");
249
Gachapandora->sfxPon = RSDK.GetSfx("Stage/Pon.wav");
250
Gachapandora->sfxFireball = RSDK.GetSfx("Stage/Fireball.wav");
251
Gachapandora->sfxGiggle = RSDK.GetSfx("MMZ/Giggle.wav");
252
}
253
254
void Gachapandora_CheckPlayerCollisions_Prize(void)
255
{
256
RSDK_THIS(Gachapandora);
257
258
foreach_active(Player, player)
259
{
260
if (player->animator.animationID != ANI_VICTORY) {
261
if (Player_CheckBadnikTouch(player, self, &self->hitbox)) {
262
int32 blink = player->blinkTimer;
263
if (self->type == GACHAPANDORA_AMY)
264
player->blinkTimer = 1;
265
266
bool32 wasHit = false;
267
if (Player_CheckBossHit(player, self)) {
268
if (self->health)
269
self->health--;
270
271
if (self->health) {
272
RSDK.PlaySfx(Gachapandora->sfxHit, false, 255);
273
}
274
else {
275
EntityGachapandora *eggman = Gachapandora->eggman;
276
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 1, &eggman->eggmanAnimator, true, 0);
277
RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);
278
self->state = Gachapandora_StatePrize_Destroyed;
279
}
280
self->invincibilityTimer = 30;
281
wasHit = true;
282
}
283
284
if (self->type == GACHAPANDORA_AMY)
285
player->blinkTimer = blink;
286
287
if (wasHit)
288
foreach_break;
289
}
290
else {
291
if (self->type == GACHAPANDORA_DRILLER) {
292
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxDrill))
293
Player_Hurt(player, self);
294
}
295
}
296
}
297
}
298
}
299
300
void Gachapandora_Explode(int32 xMin, int32 xMax, int32 yMin, int32 yMax)
301
{
302
RSDK_THIS(Gachapandora);
303
304
int32 interval = 4 * (self->state == Gachapandora_StateBoss_Explode) + 3;
305
306
if (!(Zone->timer % interval)) {
307
RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);
308
309
if (Zone->timer & 4) {
310
int32 x = self->position.x + (RSDK.Rand(xMin, xMax) << 16);
311
int32 y = self->position.y + (RSDK.Rand(yMin, yMax) << 16);
312
CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1] + 2;
313
}
314
}
315
}
316
317
void Gachapandora_Player_StateInput_P1Grabbed(void)
318
{
319
RSDK_THIS(Player);
320
321
Player_Input_P1();
322
323
self->up = false;
324
self->down = false;
325
self->jumpPress = false;
326
self->jumpHold = false;
327
328
self->velocity.x = CLAMP(self->velocity.x, -0x20000, 0x20000);
329
self->groundVel = CLAMP(self->groundVel, -0x20000, 0x20000);
330
}
331
332
void Gachapandora_Player_StateInput_P2PlayerGrabbed(void)
333
{
334
RSDK_THIS(Player);
335
336
Player_Input_P2_Player();
337
338
self->up = false;
339
self->down = false;
340
self->jumpPress = false;
341
self->jumpHold = false;
342
343
self->velocity.x = CLAMP(self->velocity.x, -0x40000, 0x40000);
344
self->groundVel = CLAMP(self->groundVel, -0x40000, 0x40000);
345
346
if (self->stateInput == Player_Input_P2_AI)
347
self->stateInput = Gachapandora_Player_StateInput_P2AIGrabbed;
348
}
349
350
void Gachapandora_Player_StateInput_P2AIGrabbed(void)
351
{
352
RSDK_THIS(Player);
353
354
Player_Input_P2_AI();
355
356
self->up = false;
357
self->down = false;
358
self->jumpPress = false;
359
self->jumpHold = false;
360
361
self->velocity.x = CLAMP(self->velocity.x, -0x40000, 0x40000);
362
self->groundVel = CLAMP(self->groundVel, -0x40000, 0x40000);
363
364
if (self->stateInput == Player_Input_P2_Player)
365
self->stateInput = Gachapandora_Player_StateInput_P2PlayerGrabbed;
366
}
367
368
void Gachapandora_HandleSparksAndDebris(void)
369
{
370
RSDK_THIS(Gachapandora);
371
372
// is this line meant to be here??
373
// there's no check if this is 0 so it automatically goes to -1/255 (which is far too long)
374
// which would be fine, but the fact there's a switch case for health implies otherwise
375
--Gachapandora->debrisTimer;
376
377
if (!Gachapandora->debrisTimer) {
378
switch (self->health) {
379
default:
380
case 0: break;
381
382
case 1:
383
case 2: Gachapandora->debrisTimer = RSDK.Rand(8, 16); break;
384
385
case 3: Gachapandora->debrisTimer = RSDK.Rand(15, 31); break;
386
case 4: Gachapandora->debrisTimer = RSDK.Rand(30, 61); break;
387
case 5: Gachapandora->debrisTimer = RSDK.Rand(60, 91); break;
388
389
case 6:
390
case 7: Gachapandora->debrisTimer = RSDK.Rand(90, 121); break;
391
392
case 8:
393
case 9: return;
394
}
395
396
int32 type = RSDK.Rand(0, 3);
397
switch (type) {
398
case 2:
399
case 0: {
400
int32 off = RSDK.Rand(-12, 12);
401
EntityGachapandora *debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS),
402
self->position.x + (off << 16) + self->velocity.x, self->position.y + 0x300000);
403
404
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, RSDK.Rand(0, 4) + 18, &debris->mainAnimator, true, 0);
405
406
if (self->state != Gachapandora_StateBoss_HandleSpun && !self->invincibilityTimer)
407
debris->velocity.x = self->velocity.x >> 1;
408
409
debris->state = Gachapandora_StateDebris_BossDebris;
410
break;
411
}
412
413
case 1: {
414
EntityGachapandora *spark = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_SPARK), self->position.x, self->position.y);
415
spark->parent = self;
416
417
if (RSDK.Rand(0, 2))
418
spark->originPos.x = (RSDK.Rand(-6, 6) - 26) << 16;
419
else
420
spark->originPos.x = (RSDK.Rand(-6, 6) + 26) << 16;
421
spark->originPos.y = (RSDK.Rand(-8, 8) + 20) << 16;
422
423
RSDK.SetSpriteAnimation(Explosion->aniFrames, 3, &spark->mainAnimator, true, 0);
424
break;
425
}
426
}
427
}
428
429
if (self->state == Gachapandora_StateBoss_LastDitchAttack) {
430
for (int32 i = 0; i < 2; ++i) {
431
if (!--Gachapandora->sideSparkTimer[i]) {
432
Gachapandora->sideSparkTimer[i] = RSDK.Rand(16, 30);
433
434
EntityGachapandora *spark = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_SPARK), self->position.x, self->position.y);
435
spark->parent = self;
436
437
if (i) {
438
spark->originPos.x = (RSDK.Rand(-2, 2) - 34) << 16;
439
}
440
else {
441
spark->direction = FLIP_X;
442
spark->originPos.x = (RSDK.Rand(-2, 2) + 34) << 16;
443
}
444
spark->originPos.y = (RSDK.Rand(-8, 8) + 20) << 16;
445
446
if (RSDK.Rand(0, 3) == 2)
447
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 14, &spark->mainAnimator, true, 0);
448
}
449
}
450
}
451
}
452
453
void Gachapandora_HandleAnimations(void)
454
{
455
RSDK_THIS(Gachapandora);
456
457
if (self->eggmanAnimator.animationID) {
458
if (self->eggmanAnimator.animationID == 1) {
459
if (self->eggmanAnimator.frameID >= self->eggmanAnimator.frameCount - 1)
460
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, true, 0);
461
}
462
else {
463
if (self->eggmanAnimator.animationID == 2) {
464
bool32 wasHit = false;
465
foreach_active(Player, player)
466
{
467
if (player->state == Player_State_Hurt || player->state == Player_State_Death)
468
wasHit = true;
469
}
470
471
if (self->eggmanAnimator.frameID >= self->eggmanAnimator.frameCount - 1) {
472
if (wasHit)
473
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 2, &self->eggmanAnimator, true, 6);
474
else
475
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, true, 0);
476
}
477
}
478
}
479
}
480
else {
481
bool32 wasHit = false;
482
foreach_active(Player, player)
483
{
484
if (player->state == Player_State_Hurt || player->state == Player_State_Death)
485
wasHit = true;
486
}
487
488
if (wasHit)
489
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 2, &self->eggmanAnimator, true, 0);
490
}
491
}
492
493
void Gachapandora_StateBoss_SetupArena(void)
494
{
495
RSDK_THIS(Gachapandora);
496
497
if (++self->timer >= 2) {
498
self->timer = 0;
499
500
Zone->playerBoundActiveR[0] = true;
501
Zone->playerBoundActiveB[0] = true;
502
Zone->cameraBoundsR[0] = (self->position.x >> 16) + ScreenInfo->center.x;
503
Zone->cameraBoundsB[0] = (self->position.y >> 16) + 128;
504
505
self->position.y = (ScreenInfo->position.y - 192) << 16;
506
self->active = ACTIVE_NORMAL;
507
self->visible = true;
508
self->state = Gachapandora_StateBoss_AwaitPlayer;
509
}
510
}
511
512
void Gachapandora_StateBoss_AwaitPlayer(void)
513
{
514
RSDK_THIS(Gachapandora);
515
516
Zone->playerBoundActiveL[0] = true;
517
Zone->cameraBoundsL[0] = ScreenInfo->position.x;
518
519
if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x) {
520
Zone->playerBoundActiveL[0] = true;
521
Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;
522
523
Music_TransitionTrack(TRACK_EGGMAN2, 0.0125);
524
self->health = 9;
525
self->state = Gachapandora_StateBoss_EnterEggman;
526
}
527
}
528
529
void Gachapandora_StateBoss_EnterEggman(void)
530
{
531
RSDK_THIS(Gachapandora);
532
533
RSDK.ProcessAnimation(&self->eggmanAnimator);
534
RSDK.ProcessAnimation(&self->handleAnimator);
535
536
self->position.y = self->position.y + 0x10000;
537
538
if (self->position.y < self->startY) {
539
if (self->position.y >= self->startY - 0x400000)
540
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 2, &self->eggmanAnimator, false, 0);
541
}
542
else {
543
self->position.y = self->startY;
544
self->originPos.x = self->position.x;
545
self->originPos.y = self->position.y;
546
self->angle = 0;
547
self->state = Gachapandora_StateBoss_FloatAround;
548
}
549
550
RSDK.AddDrawListRef(Zone->objectDrawGroup[0] + 1, SceneInfo->entitySlot);
551
}
552
553
void Gachapandora_StateBoss_FloatAround(void)
554
{
555
RSDK_THIS(Gachapandora);
556
557
RSDK.ProcessAnimation(&self->eggmanAnimator);
558
RSDK.ProcessAnimation(&self->handleAnimator);
559
560
Gachapandora_HandleAnimations();
561
562
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
563
564
if (self->invincibilityTimer) {
565
if (!--self->invincibilityTimer && !self->velocity.x) {
566
self->velocity.x = self->direction == FLIP_NONE ? -0x8000 : 0x8000;
567
}
568
}
569
else {
570
if (self->position.x < (ScreenInfo->position.x + 64) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 64) << 16)
571
self->velocity.x = -self->velocity.x;
572
573
self->position.x += self->velocity.x;
574
}
575
576
if (RSDK.Rand(0, 64) == 21)
577
Gachapandora->eggmanDir ^= FLIP_X;
578
579
for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {
580
if (Gachapandora->capsuleDelayL[i]) {
581
Gachapandora->capsuleDelayL[i]--;
582
}
583
else if (Gachapandora->capsuleOffsetL[i] != Gachapandora->capsuleMaxL[i]) {
584
++Gachapandora->capsuleSpeedL[i];
585
Gachapandora->capsuleOffsetL[i] += Gachapandora->capsuleSpeedL[i];
586
587
if (Gachapandora->capsuleOffsetL[i] > Gachapandora->capsuleMaxL[i])
588
Gachapandora->capsuleOffsetL[i] = Gachapandora->capsuleMaxL[i];
589
}
590
591
if (Gachapandora->capsuleDelayR[i]) {
592
Gachapandora->capsuleDelayR[i]--;
593
}
594
else if (Gachapandora->capsuleOffsetR[i] != Gachapandora->capsuleMaxR[i]) {
595
++Gachapandora->capsuleSpeedR[i];
596
Gachapandora->capsuleOffsetR[i] += Gachapandora->capsuleSpeedR[i];
597
598
if (Gachapandora->capsuleOffsetR[i] > Gachapandora->capsuleMaxR[i])
599
Gachapandora->capsuleOffsetR[i] = Gachapandora->capsuleMaxR[i];
600
}
601
}
602
603
if (self->timer <= 0) {
604
foreach_active(Player, player)
605
{
606
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxHandle)) {
607
RSDK.PlaySfx(Gachapandora->sfxUnravel, false, 255);
608
609
if (player->position.x >= self->position.x)
610
Gachapandora->handleDir = player->velocity.y < 0;
611
else
612
Gachapandora->handleDir = player->velocity.y > 0;
613
614
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, true, 0);
615
if (Gachapandora->nextCapsuleL + Gachapandora->nextCapsuleR == 0x1FE) {
616
self->invincibilityTimer = 25;
617
self->state = Gachapandora_StateBoss_Defeated;
618
}
619
else {
620
self->timer = 60;
621
int32 id = 0;
622
if (Gachapandora->capsuleSide) {
623
Gachapandora->handleSpinTimer = 148;
624
Gachapandora->nextPrizeType = Gachapandora->capsuleTypeR[Gachapandora->nextCapsuleR];
625
Gachapandora->capsuleOffsetR[Gachapandora->nextCapsuleR] = 0xFF;
626
Gachapandora->capsuleMaxR[Gachapandora->nextCapsuleR--] = 0xFF;
627
628
while (id <= Gachapandora->nextCapsuleR) {
629
Gachapandora->capsuleDelayR[id] = 8 * (Gachapandora->nextCapsuleR - id + 2);
630
Gachapandora->capsuleMaxR[id] += 72;
631
Gachapandora->capsuleSpeedR[id++] = 0;
632
}
633
}
634
else {
635
Gachapandora->handleSpinTimer = -148;
636
Gachapandora->nextPrizeType = Gachapandora->capsuleTypeL[Gachapandora->nextCapsuleL];
637
Gachapandora->capsuleOffsetL[Gachapandora->nextCapsuleL] = 0xFF;
638
Gachapandora->capsuleMaxL[Gachapandora->nextCapsuleL--] = 0xFF;
639
640
while (id <= Gachapandora->nextCapsuleL) {
641
Gachapandora->capsuleDelayL[id] = 8 * (Gachapandora->nextCapsuleL - id + 2);
642
Gachapandora->capsuleMaxL[id] += 72;
643
Gachapandora->capsuleSpeedL[id++] = 0;
644
}
645
}
646
647
Gachapandora->capsuleSide ^= 1;
648
self->velocity.x += self->velocity.x >= 0 ? 0x4000 : -0x4000;
649
self->state = Gachapandora_StateBoss_HandleSpun;
650
}
651
foreach_break;
652
}
653
}
654
}
655
else {
656
self->timer--;
657
}
658
}
659
660
void Gachapandora_StateBoss_HandleSpun(void)
661
{
662
RSDK_THIS(Gachapandora);
663
664
RSDK.ProcessAnimation(&self->eggmanAnimator);
665
RSDK.ProcessAnimation(&self->handleAnimator);
666
667
Gachapandora_HandleAnimations();
668
669
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
670
671
if (RSDK.Rand(0, 64) == 21)
672
Gachapandora->eggmanDir ^= FLIP_X;
673
674
for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {
675
if (Gachapandora->capsuleDelayL[i]) {
676
Gachapandora->capsuleDelayL[i]--;
677
}
678
else if (Gachapandora->capsuleOffsetL[i] != Gachapandora->capsuleMaxL[i]) {
679
++Gachapandora->capsuleSpeedL[i];
680
Gachapandora->capsuleOffsetL[i] += Gachapandora->capsuleSpeedL[i];
681
682
if (Gachapandora->capsuleOffsetL[i] > Gachapandora->capsuleMaxL[i])
683
Gachapandora->capsuleOffsetL[i] = Gachapandora->capsuleMaxL[i];
684
}
685
686
if (Gachapandora->capsuleDelayR[i]) {
687
Gachapandora->capsuleDelayR[i]--;
688
}
689
else if (Gachapandora->capsuleOffsetR[i] != Gachapandora->capsuleMaxR[i]) {
690
++Gachapandora->capsuleSpeedR[i];
691
Gachapandora->capsuleOffsetR[i] += Gachapandora->capsuleSpeedR[i];
692
693
if (Gachapandora->capsuleOffsetR[i] > Gachapandora->capsuleMaxR[i])
694
Gachapandora->capsuleOffsetR[i] = Gachapandora->capsuleMaxR[i];
695
}
696
}
697
698
if (Gachapandora->handleSpinTimer) {
699
if (Gachapandora->handleSpinTimer >= 0) {
700
Gachapandora->handleSpinTimer -= 3;
701
702
if (Gachapandora->handleSpinTimer < 0)
703
Gachapandora->handleSpinTimer = 0;
704
}
705
else {
706
Gachapandora->handleSpinTimer += 3;
707
if (Gachapandora->handleSpinTimer > 0)
708
Gachapandora->handleSpinTimer = 0;
709
}
710
}
711
else {
712
EntityGachapandora *prize = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_PRIZE), self->position.x, self->position.y + 0x1A0000);
713
prize->type = Gachapandora->nextPrizeType;
714
715
switch (prize->type) {
716
default: break;
717
case 0:
718
case 1: prize->mainAnimator.frameID = 0; break;
719
720
case 2: prize->mainAnimator.frameID = 1; break;
721
722
case 3:
723
case 4: prize->mainAnimator.frameID = 2; break;
724
725
case 5: prize->mainAnimator.frameID = 3; break;
726
}
727
728
Gachapandora->handleSpinTimer = 0x7FFF;
729
730
if (--self->health == 1) {
731
EntityGachapandora *debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);
732
debris->mainAnimator.frameID = 4;
733
debris->timer = 30;
734
debris->velocity.x = 0x20000;
735
debris->velocity.y = -0x20000;
736
737
debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);
738
debris->mainAnimator.frameID = 5;
739
debris->timer = 30;
740
debris->velocity.x = -0x20000;
741
debris->velocity.y = -0x20000;
742
743
debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);
744
++debris->drawGroup;
745
debris->mainAnimator.frameID = 2;
746
debris->timer = 90;
747
debris->velocity.x = -0x20000;
748
debris->velocity.y = -0x20000;
749
750
debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);
751
++debris->drawGroup;
752
debris->mainAnimator.frameID = 3;
753
debris->timer = 90;
754
debris->velocity.x = 0x20000;
755
debris->velocity.y = -0x20000;
756
757
self->invincibilityTimer = 120;
758
759
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 1, &self->eggmanAnimator, true, 0);
760
RSDK.SetSpriteAnimation(-1, 0, &self->capsuleAnimator, true, 0);
761
762
self->state = Gachapandora_StateBoss_Explode;
763
self->stateDraw = Gachapandora_Draw_BossDestroyed;
764
}
765
else {
766
self->invincibilityTimer = 30;
767
self->state = Gachapandora_StateBoss_FloatAround;
768
}
769
}
770
}
771
772
void Gachapandora_StateBoss_Explode(void)
773
{
774
RSDK_THIS(Gachapandora);
775
776
RSDK.ProcessAnimation(&self->eggmanAnimator);
777
778
Gachapandora_Explode(-24, 24, -48, 48);
779
Gachapandora_HandleSparksAndDebris();
780
781
if (--self->invincibilityTimer <= 0)
782
self->state = Gachapandora_StateBoss_PanicFlee;
783
}
784
785
void Gachapandora_StateBoss_PanicFlee(void)
786
{
787
RSDK_THIS(Gachapandora);
788
789
RSDK.ProcessAnimation(&self->eggmanAnimator);
790
791
Gachapandora_HandleSparksAndDebris();
792
793
self->position.y += self->velocity.y;
794
self->velocity.y -= 0x1800;
795
796
if (self->position.y < (ScreenInfo->position.y - 192) << 16) {
797
self->position.y = (ScreenInfo->position.y - 192) << 16;
798
self->position.x = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;
799
self->state = Gachapandora_StateBoss_EnsureAllCapsulesDestroyed;
800
}
801
}
802
803
void Gachapandora_StateBoss_EnsureAllCapsulesDestroyed(void)
804
{
805
RSDK_THIS(Gachapandora);
806
807
if (Gachapandora->destroyedToys >= 8) {
808
self->originPos.y = self->position.y;
809
self->angle = 0;
810
811
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 17, &self->capsuleAnimator, true, 0);
812
813
self->timer = 60;
814
self->velocity.x >>= 1;
815
self->state = Gachapandora_StateBoss_LastDitchAttack;
816
}
817
}
818
819
void Gachapandora_StateBoss_LastDitchAttack(void)
820
{
821
RSDK_THIS(Gachapandora);
822
823
RSDK.ProcessAnimation(&self->eggmanAnimator);
824
RSDK.ProcessAnimation(&self->handleAnimator);
825
RSDK.ProcessAnimation(&self->capsuleAnimator);
826
827
Gachapandora_HandleAnimations();
828
829
if (self->originPos.y >= self->startY) {
830
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
831
}
832
else {
833
self->originPos.y += 0x10000;
834
self->position.y = self->originPos.y;
835
}
836
837
Gachapandora_HandleSparksAndDebris();
838
839
if (self->position.x < (ScreenInfo->position.x + 32) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 32) << 16)
840
self->velocity.x = -self->velocity.x;
841
842
self->position.x = self->position.x + self->velocity.x;
843
844
if (RSDK.Rand(0, 64) == 21)
845
Gachapandora->eggmanDir ^= FLIP_X;
846
847
if (--self->timer <= 0) {
848
self->timer = 60;
849
for (int32 i = 0; i < 2; ++i) {
850
EntityGachapandora *spark = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_SPARK), self->position.x, self->position.y);
851
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 15, &spark->mainAnimator, true, 0);
852
853
if (i) {
854
spark->position.x += (RSDK.Rand(-2, 2) - 34) << 16;
855
spark->velocity.x = self->velocity.x - 0x10000;
856
}
857
else {
858
spark->direction = FLIP_X;
859
spark->position.x += (RSDK.Rand(-2, 2) + 34) << 16;
860
spark->velocity.x = self->velocity.x + 0x10000;
861
}
862
863
spark->state = Gachapandora_StateSpark_Detached;
864
spark->position.y += (RSDK.Rand(-8, 8) + 20) << 16;
865
}
866
}
867
868
foreach_active(Player, player)
869
{
870
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxHandle)) {
871
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 4, &self->eggmanAnimator, true, 0);
872
RSDK.PlaySfx(Gachapandora->sfxUnravel, false, 255);
873
874
if (player->position.x >= self->position.x)
875
Gachapandora->handleDir = player->velocity.y < 0;
876
else
877
Gachapandora->handleDir = player->velocity.y > 0;
878
879
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, true, 0);
880
self->invincibilityTimer = 25;
881
self->velocity.y = 0;
882
self->state = Gachapandora_StateBoss_Defeated;
883
foreach_break;
884
}
885
}
886
}
887
888
void Gachapandora_StateBoss_Defeated(void)
889
{
890
RSDK_THIS(Gachapandora);
891
892
Gachapandora_HandleSparksAndDebris();
893
894
self->position.y += self->velocity.y;
895
self->velocity.y -= 0x800;
896
897
RSDK.ProcessAnimation(&self->eggmanAnimator);
898
RSDK.ProcessAnimation(&self->handleAnimator);
899
RSDK.ProcessAnimation(&self->capsuleAnimator);
900
901
Gachapandora_HandleSparksAndDebris();
902
903
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
904
if (!--self->invincibilityTimer) {
905
CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_EGGMAN), self->position.x, self->position.y - 0x100000)->parent = self;
906
RSDK.SetSpriteAnimation(-1, 0, &self->eggmanAnimator, true, 0);
907
self->invincibilityTimer = 60;
908
self->state = Gachapandora_StateBoss_EggmanFallOut;
909
}
910
}
911
912
void Gachapandora_StateBoss_EggmanFallOut(void)
913
{
914
RSDK_THIS(Gachapandora);
915
916
RSDK.ProcessAnimation(&self->eggmanAnimator);
917
RSDK.ProcessAnimation(&self->handleAnimator);
918
RSDK.ProcessAnimation(&self->capsuleAnimator);
919
920
Gachapandora_HandleSparksAndDebris();
921
922
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);
923
self->position.y += self->velocity.y;
924
self->velocity.y -= 0x800;
925
926
if (!--self->invincibilityTimer) {
927
SceneInfo->timeEnabled = false;
928
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);
929
self->invincibilityTimer = 120;
930
self->state = Gachapandora_StateBoss_Finish;
931
}
932
}
933
934
void Gachapandora_StateBoss_Finish(void)
935
{
936
RSDK_THIS(Gachapandora);
937
938
RSDK.ProcessAnimation(&self->eggmanAnimator);
939
RSDK.ProcessAnimation(&self->handleAnimator);
940
RSDK.ProcessAnimation(&self->capsuleAnimator);
941
942
Gachapandora_HandleSparksAndDebris();
943
Gachapandora_Explode(-24, 24, -48, 48);
944
945
if (self->invincibilityTimer) {
946
if (!--self->invincibilityTimer || self->invincibilityTimer == 96)
947
self->velocity.y = -0x40000;
948
}
949
else {
950
self->position.y += self->velocity.y;
951
self->velocity.y += 0x1800;
952
953
if (self->position.y > (ScreenInfo->position.y + ScreenInfo->size.y + 128) << 16) {
954
Zone->cameraBoundsR[0] += WIDE_SCR_XSIZE;
955
self->state = StateMachine_None;
956
Music_TransitionTrack(TRACK_STAGE, 0.0125);
957
}
958
}
959
}
960
961
void Gachapandora_Draw_Boss(void)
962
{
963
RSDK_THIS(Gachapandora);
964
965
Vector2 drawPos = self->position;
966
if (SceneInfo->currentDrawGroup == Zone->objectDrawGroup[0]) {
967
self->mainAnimator.frameID = 4;
968
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
969
970
self->mainAnimator.frameID = 5;
971
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
972
973
for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {
974
if (Gachapandora->capsuleOffsetL[i] != 0xFF) {
975
self->capsuleAnimator.frameID = ((Gachapandora->capsuleTypeL[i] % 3) >> 1) + 2 * (Gachapandora->capsuleTypeL[i] / 3);
976
drawPos.x = self->position.x - (Gachapandora->capsuleOffsets[56 - (Gachapandora->capsuleOffsetL[i] >> 2)] << 16);
977
drawPos.y = self->position.y + (((Gachapandora->capsuleOffsetL[i] & 0xFC) - 152) << 14);
978
RSDK.DrawSprite(&self->capsuleAnimator, &drawPos, false);
979
}
980
981
if (Gachapandora->capsuleOffsetR[i] != 0xFF) {
982
self->capsuleAnimator.frameID = ((Gachapandora->capsuleTypeR[i] % 3) >> 1) + 2 * (Gachapandora->capsuleTypeR[i] / 3);
983
drawPos.x = self->position.x + (Gachapandora->capsuleOffsets[56 - (Gachapandora->capsuleOffsetR[i] >> 2)] << 16);
984
drawPos.y = self->position.y + (((Gachapandora->capsuleOffsetR[i] & 0xFC) - 152) << 14);
985
RSDK.DrawSprite(&self->capsuleAnimator, &drawPos, false);
986
}
987
}
988
989
if (Gachapandora->handleSpinTimer != 0x7FFF) {
990
self->capsuleAnimator.frameID = ((Gachapandora->nextPrizeType % 3) >> 1) + 2 * (Gachapandora->nextPrizeType / 3);
991
drawPos.x = self->position.x + (Gachapandora->handleSpinTimer << 14);
992
drawPos.y = self->position.y + 0x120000;
993
RSDK.DrawSprite(&self->capsuleAnimator, &drawPos, false);
994
}
995
996
self->mainAnimator.frameID = 2;
997
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
998
999
self->mainAnimator.frameID = 3;
1000
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1001
1002
self->mainAnimator.frameID = 0;
1003
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1004
1005
int32 storeDir = self->direction;
1006
self->direction = Gachapandora->eggmanDir;
1007
drawPos.x = self->position.x;
1008
drawPos.y = self->position.y - 0x100000;
1009
RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);
1010
1011
self->direction = storeDir;
1012
}
1013
else {
1014
self->mainAnimator.frameID = 1;
1015
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1016
1017
int32 storeDir = self->direction;
1018
self->direction = Gachapandora->handleDir;
1019
drawPos.y += 0x1A0000;
1020
RSDK.DrawSprite(&self->handleAnimator, &drawPos, false);
1021
1022
self->direction = storeDir;
1023
}
1024
}
1025
1026
void Gachapandora_Draw_BossDestroyed(void)
1027
{
1028
RSDK_THIS(Gachapandora);
1029
1030
int32 storeDir = self->direction;
1031
Vector2 drawPos = self->position;
1032
if (SceneInfo->currentDrawGroup == Zone->objectDrawGroup[0]) {
1033
self->mainAnimator.frameID = 0;
1034
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1035
1036
self->direction = Gachapandora->eggmanDir;
1037
drawPos.x = self->position.x;
1038
drawPos.y = self->position.y - 0x100000;
1039
RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);
1040
}
1041
else {
1042
self->mainAnimator.frameID = 1;
1043
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1044
1045
storeDir = self->direction;
1046
self->direction = Gachapandora->handleDir;
1047
drawPos.y += 0x1A0000;
1048
RSDK.DrawSprite(&self->handleAnimator, &drawPos, false);
1049
1050
self->direction = FLIP_NONE;
1051
RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);
1052
1053
self->direction = FLIP_X;
1054
RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);
1055
}
1056
1057
self->direction = storeDir;
1058
}
1059
1060
void Gachapandora_StatePrize_CapsuleFall(void)
1061
{
1062
RSDK_THIS(Gachapandora);
1063
1064
self->position.y += self->velocity.y;
1065
self->velocity.y += 0x2000;
1066
1067
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {
1068
EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);
1069
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &debris->animator, true, 4);
1070
1071
debris->velocity.x = RSDK.Rand(-1, 2) << 16;
1072
debris->velocity.y = -0x48000;
1073
debris->gravityStrength = 0x3800;
1074
debris->drawGroup = Zone->objectDrawGroup[1];
1075
debris->updateRange.x = 0x400000;
1076
debris->updateRange.y = 0x400000;
1077
1078
debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);
1079
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &debris->animator, true, 5);
1080
1081
if (self->type > GACHAPANDORA_PRIZE)
1082
++debris->animator.frameID;
1083
debris->velocity.x = RSDK.Rand(-1, 2) << 15;
1084
debris->velocity.y = -0x30000;
1085
debris->gravityStrength = 0x3800;
1086
debris->drawGroup = Zone->objectDrawGroup[1];
1087
debris->updateRange.x = 0x400000;
1088
debris->updateRange.y = 0x400000;
1089
1090
RSDK.PlaySfx(Gachapandora->sfxPon, false, 255);
1091
self->velocity.y = -0x38000;
1092
switch (self->type) {
1093
case 0:
1094
case 3:
1095
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 3, &self->mainAnimator, true, 0);
1096
self->type = GACHAPANDORA_DRILLER;
1097
if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x)
1098
self->direction = FLIP_X;
1099
break;
1100
1101
case 1:
1102
case 4:
1103
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 4, &self->mainAnimator, true, 0);
1104
self->type = GACHAPANDORA_FIREDROPPER;
1105
break;
1106
1107
case 2:
1108
case 5:
1109
if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x)
1110
self->velocity.x = -0x8000;
1111
else
1112
self->velocity.x = 0x8000;
1113
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 5, &self->mainAnimator, true, 0);
1114
self->type = GACHAPANDORA_AMY;
1115
break;
1116
1117
default: break;
1118
}
1119
1120
self->drawFX |= FX_SCALE;
1121
self->scale.x = 0x20;
1122
self->scale.y = 0x20;
1123
self->drawGroup = Zone->objectDrawGroup[1] + 1;
1124
if (++Gachapandora->activeToys >= 8 && !Gachapandora->destroyedToys)
1125
Gachapandora->awardAchievement = true;
1126
1127
self->state = Gachapandora_StatePrize_ExitCapsule;
1128
}
1129
}
1130
1131
void Gachapandora_StatePrize_ExitCapsule(void)
1132
{
1133
RSDK_THIS(Gachapandora);
1134
1135
self->position.y += self->velocity.y;
1136
self->velocity.y += 0x2000;
1137
1138
if (self->scale.x < 0x200) {
1139
self->scale.y += 16;
1140
self->scale.x += 16;
1141
}
1142
1143
switch (self->type) {
1144
default: break;
1145
case GACHAPANDORA_AMY:
1146
RSDK.ProcessAnimation(&self->mainAnimator);
1147
1148
self->position.x += self->velocity.x;
1149
1150
if (self->velocity.y >= 0) {
1151
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {
1152
self->velocity.y = 0;
1153
1154
self->hitbox.left = -5;
1155
self->hitbox.top = -11;
1156
self->hitbox.right = 5;
1157
self->hitbox.bottom = 11;
1158
1159
self->health = 1;
1160
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);
1161
self->state = Gachapandora_StatePrize_AmyWalk;
1162
}
1163
}
1164
break;
1165
1166
case GACHAPANDORA_DRILLER:
1167
if (self->velocity.y >= 0) {
1168
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x110000, true)) {
1169
self->velocity.x = self->direction == FLIP_NONE ? -0x20000 : 0x20000;
1170
self->velocity.y = -0x18000;
1171
1172
self->hitbox.left = -16;
1173
self->hitbox.top = -10;
1174
self->hitbox.right = 25;
1175
self->hitbox.bottom = 17;
1176
1177
self->health = 3;
1178
self->state = Gachapandora_StatePrize_DrillerCapsuleExitBounce;
1179
}
1180
}
1181
break;
1182
1183
case GACHAPANDORA_FIREDROPPER:
1184
if (self->velocity.y >= 0) {
1185
self->originPos.y = self->position.y;
1186
self->velocity.x = self->direction == FLIP_NONE ? -0x18000 : 0x18000;
1187
self->velocity.y = 0;
1188
1189
self->hitbox.left = -13;
1190
self->hitbox.top = -10;
1191
self->hitbox.right = 13;
1192
self->hitbox.bottom = 10;
1193
1194
self->health = 3;
1195
self->timer = 120;
1196
self->state = Gachapandora_StatePrize_FireDropperMove;
1197
}
1198
break;
1199
}
1200
}
1201
1202
void Gachapandora_StatePrize_Destroyed(void)
1203
{
1204
RSDK_THIS(Gachapandora);
1205
1206
Gachapandora_Explode(-8, 8, -8, 8);
1207
1208
if (self->invincibilityTimer) {
1209
self->invincibilityTimer--;
1210
}
1211
else {
1212
if (++Gachapandora->destroyedToys >= 8 && Gachapandora->awardAchievement)
1213
API_UnlockAchievement(&achievementList[ACH_MMZ]);
1214
1215
destroyEntity(self);
1216
}
1217
}
1218
1219
void Gachapandora_StatePrize_DrillerCapsuleExitBounce(void)
1220
{
1221
RSDK_THIS(Gachapandora);
1222
1223
Gachapandora_StatePrize_DrillerMove();
1224
1225
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x110000, true)) {
1226
self->velocity.y = 0;
1227
self->state = Gachapandora_StatePrize_DrillerMove;
1228
}
1229
else {
1230
self->velocity.y += 0x3800;
1231
}
1232
}
1233
1234
void Gachapandora_StatePrize_DrillerMove(void)
1235
{
1236
RSDK_THIS(Gachapandora);
1237
1238
RSDK.ProcessAnimation(&self->mainAnimator);
1239
1240
self->position.y += self->velocity.y;
1241
self->position.x += self->velocity.x;
1242
1243
if (self->position.x < (ScreenInfo->position.x - 64) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x + 64) << 16) {
1244
self->direction ^= FLIP_X;
1245
self->velocity.x = -self->velocity.x;
1246
}
1247
1248
if (self->invincibilityTimer)
1249
self->invincibilityTimer--;
1250
else
1251
Gachapandora_CheckPlayerCollisions_Prize();
1252
}
1253
1254
void Gachapandora_StatePrize_FireDropperMove(void)
1255
{
1256
RSDK_THIS(Gachapandora);
1257
1258
RSDK.ProcessAnimation(&self->mainAnimator);
1259
RSDK.ProcessAnimation(&self->eggmanAnimator);
1260
1261
self->position.x += self->velocity.x;
1262
if (self->startY) {
1263
self->position.y += self->velocity.y;
1264
self->velocity.y -= 0x800;
1265
1266
if (self->position.y <= self->originPos.y) {
1267
self->position.y = self->originPos.y;
1268
self->velocity.y = 0;
1269
self->angle = 0;
1270
self->startY = 0;
1271
}
1272
}
1273
else {
1274
self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 9);
1275
}
1276
1277
if (self->position.x < (ScreenInfo->position.x + 16) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 16) << 16) {
1278
self->startY = 1;
1279
self->direction ^= FLIP_X;
1280
self->velocity.y = 0x18000;
1281
self->velocity.x = -self->velocity.x;
1282
}
1283
1284
if (!--self->timer) {
1285
self->timer = 120;
1286
RSDK.PlaySfx(Gachapandora->sfxFireball, false, 255);
1287
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 10, &self->eggmanAnimator, true, 0);
1288
1289
EntityGachapandora *fireball = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_FIREBALL), self->position.x, self->position.y);
1290
fireball->parent = self;
1291
fireball->timer = 12;
1292
}
1293
1294
if (self->invincibilityTimer)
1295
self->invincibilityTimer--;
1296
else
1297
Gachapandora_CheckPlayerCollisions_Prize();
1298
}
1299
1300
void Gachapandora_StatePrize_AmyWalk(void)
1301
{
1302
RSDK_THIS(Gachapandora);
1303
1304
RSDK.ProcessAnimation(&self->mainAnimator);
1305
1306
self->position.x += self->velocity.x;
1307
self->position.y += self->velocity.y;
1308
1309
if (self->invincibilityTimer)
1310
self->invincibilityTimer--;
1311
else
1312
Gachapandora_CheckPlayerCollisions_Prize();
1313
1314
EntityPlayer *player = Player_GetNearestPlayer();
1315
1316
if (self->position.x < (ScreenInfo->position.x + 8) << 16 || self->position.x > (ScreenInfo->size.x + ScreenInfo->position.x - 8) << 16
1317
|| Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {
1318
if (abs(player->position.x - self->position.x) > 0x80000)
1319
self->direction = player->position.x > self->position.x;
1320
1321
bool32 canJump = false;
1322
if (self->direction) {
1323
if (self->velocity.x < 0x20000)
1324
self->velocity.x += 0xC00;
1325
1326
canJump = self->velocity.x >= 0x10000;
1327
}
1328
else {
1329
if (self->velocity.x > -0x20000)
1330
self->velocity.x -= 0xC00;
1331
1332
canJump = self->velocity.x <= -0x10000;
1333
}
1334
1335
if (canJump && Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmy)) {
1336
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 5, &self->mainAnimator, true, 0);
1337
self->state = Gachapandora_StatePrize_AmyJump;
1338
self->onGround = false;
1339
self->velocity.y = -0x24000;
1340
}
1341
}
1342
else {
1343
if (self->velocity.x > 0) {
1344
self->velocity.x -= 0xC00;
1345
1346
if (self->velocity.x < 0) {
1347
self->velocity.x = 0;
1348
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);
1349
self->state = Gachapandora_StatePrize_AmyIdle;
1350
}
1351
}
1352
else {
1353
self->velocity.x += 0xC00;
1354
if (self->velocity.x >= 0) {
1355
self->velocity.x = 0;
1356
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);
1357
self->state = Gachapandora_StatePrize_AmyIdle;
1358
}
1359
}
1360
}
1361
}
1362
1363
void Gachapandora_StatePrize_AmyIdle(void)
1364
{
1365
RSDK_THIS(Gachapandora);
1366
1367
EntityPlayer *player = Player_GetNearestPlayer();
1368
1369
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {
1370
self->velocity.x = 0;
1371
self->direction = player->position.x > self->position.x;
1372
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);
1373
1374
self->state = Gachapandora_StatePrize_AmyWalk;
1375
Gachapandora_StatePrize_AmyWalk();
1376
}
1377
1378
if (self->state == Gachapandora_StatePrize_AmyIdle) {
1379
RSDK.ProcessAnimation(&self->mainAnimator);
1380
1381
if (self->invincibilityTimer)
1382
self->invincibilityTimer--;
1383
else
1384
Gachapandora_CheckPlayerCollisions_Prize();
1385
}
1386
}
1387
1388
void Gachapandora_StatePrize_AmyJump(void)
1389
{
1390
RSDK_THIS(Gachapandora);
1391
1392
RSDK.ProcessAnimation(&self->mainAnimator);
1393
1394
self->position.x += self->velocity.x;
1395
self->position.y += self->velocity.y;
1396
self->velocity.y += 0x2800;
1397
1398
if (!self->invincibilityTimer) {
1399
foreach_active(Player, player)
1400
{
1401
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxFireball)) {
1402
#if MANIA_USE_PLUS
1403
if (player->state == Player_State_MightyHammerDrop) {
1404
if (Player_CheckBossHit(player, self)) {
1405
if (self->health)
1406
self->health--;
1407
1408
if (self->health) {
1409
RSDK.PlaySfx(Gachapandora->sfxHit, false, 255);
1410
}
1411
else {
1412
EntityGachapandora *eggman = Gachapandora->eggman;
1413
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 1, &eggman->eggmanAnimator, true, 0);
1414
RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);
1415
self->state = Gachapandora_StatePrize_Destroyed;
1416
}
1417
1418
self->invincibilityTimer = 30;
1419
}
1420
foreach_break;
1421
}
1422
else {
1423
#endif
1424
if (Player_CheckAttacking(player, self) && player->stateInput != Gachapandora_Player_StateInput_P1Grabbed
1425
&& player->stateInput != Gachapandora_Player_StateInput_P2PlayerGrabbed
1426
&& player->stateInput != Gachapandora_Player_StateInput_P2AIGrabbed) {
1427
bool32 shouldRebound = self->velocity.x >= 0;
1428
if (player->position.x > self->position.x) {
1429
if (self->velocity.x > 0) {
1430
self->velocity.x = -self->velocity.x;
1431
shouldRebound = true;
1432
}
1433
}
1434
1435
if (player->position.x >= self->position.x || shouldRebound) {
1436
self->velocity.y = -0x20000;
1437
if (self->position.x >= player->position.x) {
1438
self->direction = FLIP_NONE;
1439
player->velocity.x = -0x18000;
1440
}
1441
else {
1442
self->direction = FLIP_X;
1443
player->velocity.x = 0x18000;
1444
}
1445
player->groundVel = player->velocity.x;
1446
player->velocity.y = -player->velocity.y;
1447
player->state = Player_State_Air;
1448
if (player->animator.animationID == ANI_SPINDASH)
1449
player->animator.animationID = ANI_WALK;
1450
self->state = Gachapandora_StatePrize_AmyRebound;
1451
foreach_break;
1452
}
1453
}
1454
else {
1455
RSDK.PlaySfx(Gachapandora->sfxGiggle, false, 0xFF);
1456
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 6, &self->mainAnimator, true, 0);
1457
1458
if (player->stateInput == Player_Input_P1)
1459
player->stateInput = Gachapandora_Player_StateInput_P1Grabbed;
1460
else if (player->stateInput == Player_Input_P2_Player)
1461
player->stateInput = Gachapandora_Player_StateInput_P2PlayerGrabbed;
1462
else if (player->stateInput == Player_Input_P2_AI)
1463
player->stateInput = Gachapandora_Player_StateInput_P2AIGrabbed;
1464
1465
self->timer = 90;
1466
self->parent = (EntityGachapandora *)player;
1467
self->state = Gachapandora_StatePrize_AmyGrabbed;
1468
foreach_break;
1469
}
1470
#if MANIA_USE_PLUS
1471
}
1472
#endif
1473
}
1474
}
1475
}
1476
else {
1477
self->invincibilityTimer--;
1478
}
1479
1480
if (self->state == Gachapandora_StatePrize_AmyJump) {
1481
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {
1482
self->velocity.y = 0;
1483
EntityPlayer *player = Player_GetNearestPlayer();
1484
if (self->position.x < (ScreenInfo->position.x + 8) << 16 || self->position.x > (ScreenInfo->size.x + ScreenInfo->position.x - 8) << 16
1485
|| Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {
1486
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);
1487
self->state = Gachapandora_StatePrize_AmyWalk;
1488
}
1489
else {
1490
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);
1491
self->state = Gachapandora_StatePrize_AmyIdle;
1492
}
1493
}
1494
}
1495
}
1496
1497
void Gachapandora_StatePrize_AmyRebound(void)
1498
{
1499
RSDK_THIS(Gachapandora);
1500
1501
RSDK.ProcessAnimation(&self->mainAnimator);
1502
1503
self->position.x += self->velocity.x;
1504
self->position.y += self->velocity.y;
1505
self->velocity.y += 0x2800;
1506
1507
if (self->invincibilityTimer)
1508
self->invincibilityTimer--;
1509
1510
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {
1511
self->velocity.y = 0;
1512
EntityPlayer *player = Player_GetNearestPlayer();
1513
1514
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {
1515
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);
1516
self->state = Gachapandora_StatePrize_AmyWalk;
1517
}
1518
else {
1519
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);
1520
self->state = Gachapandora_StatePrize_AmyIdle;
1521
}
1522
}
1523
1524
if (self->mainAnimator.animationID == 7) {
1525
if (!--self->timer) {
1526
RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);
1527
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1] + 2;
1528
1529
self->invincibilityTimer = 30;
1530
self->state = Gachapandora_StatePrize_Destroyed;
1531
}
1532
}
1533
}
1534
1535
void Gachapandora_StatePrize_AmyGrabbed(void)
1536
{
1537
RSDK_THIS(Gachapandora);
1538
1539
EntityPlayer *parent = (EntityPlayer *)self->parent;
1540
1541
RSDK.ProcessAnimation(&self->mainAnimator);
1542
self->position.x = parent->position.x;
1543
self->position.y = parent->position.y;
1544
1545
self->direction = parent->direction ^ FLIP_X;
1546
self->position.x += self->direction ? -0x60000 : 0x60000;
1547
1548
if (self->prevShakeFlags) {
1549
if (self->shakeTimer) {
1550
self->shakeTimer--;
1551
1552
uint8 shakeFlags = 0;
1553
if (parent->left)
1554
shakeFlags = 1;
1555
if (parent->right)
1556
shakeFlags |= 2;
1557
1558
if (shakeFlags) {
1559
if (shakeFlags != 3 && shakeFlags != self->prevShakeFlags) {
1560
self->prevShakeFlags = shakeFlags;
1561
if (++self->shakeCount >= 6) {
1562
self->shakeCount = 0;
1563
self->parent = NULL;
1564
1565
if (parent->stateInput == Gachapandora_Player_StateInput_P1Grabbed)
1566
parent->stateInput = Player_Input_P1;
1567
else if (parent->stateInput == Gachapandora_Player_StateInput_P2PlayerGrabbed)
1568
parent->stateInput = Player_Input_P2_Player;
1569
else if (parent->stateInput == Gachapandora_Player_StateInput_P2AIGrabbed)
1570
parent->stateInput = Player_Input_P2_AI;
1571
1572
self->velocity.x = self->direction == FLIP_NONE ? 0x20000 : -0x20000;
1573
self->velocity.y = -0x20000;
1574
self->state = Gachapandora_StatePrize_AmyRebound;
1575
}
1576
}
1577
}
1578
}
1579
else {
1580
self->shakeCount = 0;
1581
self->prevShakeFlags = 0;
1582
}
1583
}
1584
else {
1585
if (parent->left)
1586
self->prevShakeFlags = 1;
1587
else if (parent->right)
1588
self->prevShakeFlags = 2;
1589
1590
self->shakeTimer = 64;
1591
}
1592
1593
if (self->state == Gachapandora_StatePrize_AmyGrabbed) {
1594
if (!--self->timer) {
1595
if (parent->stateInput == Gachapandora_Player_StateInput_P1Grabbed)
1596
parent->stateInput = Player_Input_P1;
1597
else if (parent->stateInput == Gachapandora_Player_StateInput_P2PlayerGrabbed)
1598
parent->stateInput = Player_Input_P2_Player;
1599
else if (parent->stateInput == Gachapandora_Player_StateInput_P2AIGrabbed)
1600
parent->stateInput = Player_Input_P2_AI;
1601
1602
Player_Hurt(parent, self);
1603
1604
RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);
1605
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1] + 2;
1606
1607
self->invincibilityTimer = 30;
1608
self->state = Gachapandora_StatePrize_Destroyed;
1609
}
1610
else if (self->timer == 30) {
1611
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 7, &self->mainAnimator, true, 0);
1612
}
1613
}
1614
}
1615
1616
void Gachapandora_Draw_Prize(void)
1617
{
1618
RSDK_THIS(Gachapandora);
1619
1620
if (self->invincibilityTimer & 1)
1621
RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);
1622
1623
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1624
RSDK.DrawSprite(&self->eggmanAnimator, NULL, false);
1625
1626
RSDK.SetPaletteEntry(0, 128, 0x000000);
1627
}
1628
1629
void Gachapandora_StateFireball_Falling(void)
1630
{
1631
RSDK_THIS(Gachapandora);
1632
1633
RSDK.ProcessAnimation(&self->mainAnimator);
1634
1635
if (self->timer) {
1636
EntityGachapandora *parent = self->parent;
1637
if (parent->direction)
1638
self->position.x = parent->position.x + 0x20000;
1639
else
1640
self->position.x = parent->position.x - 0x20000;
1641
self->position.y += parent->velocity.y;
1642
self->timer--;
1643
}
1644
1645
foreach_active(Player, player)
1646
{
1647
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxFireball)) {
1648
Player_ElementHurt(player, self, SHIELD_FIRE);
1649
}
1650
}
1651
1652
self->position.y += 0x18000;
1653
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x20000, true)) {
1654
self->timer = 6;
1655
self->health = 4;
1656
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 12, &self->mainAnimator, true, 0);
1657
self->state = Gachapandora_StateFireball_BurnGround;
1658
}
1659
}
1660
1661
void Gachapandora_StateFireball_BurnGround(void)
1662
{
1663
RSDK_THIS(Gachapandora);
1664
1665
RSDK.ProcessAnimation(&self->mainAnimator);
1666
1667
if (self->timer) {
1668
if (!--self->timer) {
1669
EntityGachapandora *fireball =
1670
CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_FIREBALL), self->position.x + 0x40000, self->position.y);
1671
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 12, &fireball->mainAnimator, true, 0);
1672
fireball->state = Gachapandora_StateFireball_BurnGround;
1673
if (self->health) {
1674
fireball->timer = 6;
1675
fireball->health = self->health - 1;
1676
}
1677
1678
fireball = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_FIREBALL), self->position.x - 0x40000, self->position.y);
1679
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 12, &fireball->mainAnimator, true, 0);
1680
fireball->state = Gachapandora_StateFireball_BurnGround;
1681
if (self->health) {
1682
fireball->timer = 6;
1683
fireball->health = self->health - 1;
1684
}
1685
}
1686
}
1687
if (self->mainAnimator.frameID < 5) {
1688
foreach_active(Player, player)
1689
{
1690
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxFireball)) {
1691
Player_ElementHurt(player, self, SHIELD_FIRE);
1692
}
1693
}
1694
}
1695
1696
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)
1697
destroyEntity(self);
1698
}
1699
1700
void Gachapandora_Draw_Simple(void)
1701
{
1702
RSDK_THIS(Gachapandora);
1703
1704
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1705
}
1706
1707
void Gachapandora_StateDebris_Delay(void)
1708
{
1709
RSDK_THIS(Gachapandora);
1710
1711
if (!--self->timer) {
1712
self->state = Gachapandora_StateDebris_Falling;
1713
self->stateDraw = Gachapandora_Draw_BossDebris;
1714
}
1715
}
1716
1717
void Gachapandora_StateDebris_Falling(void)
1718
{
1719
RSDK_THIS(Gachapandora);
1720
1721
RSDK.ProcessAnimation(&self->mainAnimator);
1722
1723
self->position.x += self->velocity.x;
1724
self->position.y += self->velocity.y;
1725
self->velocity.y += 0x2800;
1726
1727
if (!RSDK.CheckOnScreen(self, NULL))
1728
destroyEntity(self);
1729
}
1730
1731
void Gachapandora_StateDebris_BossDebris(void)
1732
{
1733
RSDK_THIS(Gachapandora);
1734
1735
RSDK.ProcessAnimation(&self->mainAnimator);
1736
1737
self->position.x += self->velocity.x;
1738
self->position.y += self->velocity.y;
1739
self->velocity.y += 0x2800;
1740
1741
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, true)) {
1742
self->velocity.y = -0x20000;
1743
self->velocity.x = RSDK.Rand(-2, 3) << 16;
1744
self->state = Gachapandora_StateDebris_Falling;
1745
self->stateDraw = Gachapandora_Draw_BossDebris;
1746
}
1747
}
1748
1749
void Gachapandora_Draw_BossDebris(void)
1750
{
1751
RSDK_THIS(Gachapandora);
1752
1753
if (Zone->timer & 1)
1754
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1755
}
1756
1757
void Gachapandora_StateSpark_Attached(void)
1758
{
1759
RSDK_THIS(Gachapandora);
1760
1761
RSDK.ProcessAnimation(&self->mainAnimator);
1762
1763
EntityGachapandora *parent = self->parent;
1764
if (parent) {
1765
self->position.x = parent->position.x + self->originPos.x;
1766
self->position.y = parent->position.y + self->originPos.y;
1767
}
1768
1769
if (self->mainAnimator.animationID >= 14 && (self->mainAnimator.animationID != 16 || self->mainAnimator.frameID < 2)) {
1770
foreach_active(Player, player)
1771
{
1772
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxSpark)) {
1773
Player_ElementHurt(player, self, SHIELD_LIGHTNING);
1774
}
1775
}
1776
}
1777
1778
if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)
1779
destroyEntity(self);
1780
}
1781
1782
void Gachapandora_StateSpark_Detached(void)
1783
{
1784
RSDK_THIS(Gachapandora);
1785
1786
RSDK.ProcessAnimation(&self->mainAnimator);
1787
1788
self->position.x += self->velocity.x;
1789
self->position.y += self->velocity.y;
1790
1791
if (self->velocity.y < 0x20000)
1792
self->velocity.y += 0x1800;
1793
1794
foreach_active(Player, player)
1795
{
1796
if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxSpark)) {
1797
Player_ElementHurt(player, self, SHIELD_LIGHTNING);
1798
}
1799
}
1800
1801
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, true)) {
1802
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 16, &self->mainAnimator, true, 0);
1803
self->velocity.x = 0;
1804
self->velocity.y = 0;
1805
self->state = Gachapandora_StateSpark_Attached;
1806
}
1807
}
1808
1809
void Gachapandora_StateEggman_Falling(void)
1810
{
1811
RSDK_THIS(Gachapandora);
1812
1813
RSDK.ProcessAnimation(&self->mainAnimator);
1814
1815
self->position.y += self->velocity.y;
1816
self->velocity.y += 0x1800;
1817
1818
if (self->position.y >= self->parent->position.y + 0xE0000) {
1819
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 5, &self->mainAnimator, true, 0);
1820
self->state = Gachapandora_StateEggman_Escape;
1821
}
1822
}
1823
1824
void Gachapandora_StateEggman_Escape(void)
1825
{
1826
RSDK_THIS(Gachapandora);
1827
1828
self->position.y += self->velocity.y;
1829
self->velocity.y += 0x1800;
1830
1831
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x180000, true)) {
1832
self->velocity.x = 0;
1833
self->velocity.y = 0;
1834
self->state = Gachapandora_StateEggman_RunAway;
1835
}
1836
}
1837
1838
void Gachapandora_StateEggman_RunAway(void)
1839
{
1840
RSDK_THIS(Gachapandora);
1841
1842
RSDK.ProcessAnimation(&self->mainAnimator);
1843
1844
if (self->mainAnimator.frameID >= 4) {
1845
if (self->velocity.x < 0x60000)
1846
self->velocity.x += 0xC00;
1847
1848
self->position.x += self->velocity.x;
1849
}
1850
1851
if (!RSDK.CheckOnScreen(self, NULL))
1852
destroyEntity(self);
1853
}
1854
1855
#if GAME_INCLUDE_EDITOR
1856
void Gachapandora_EditorDraw(void)
1857
{
1858
RSDK_THIS(Gachapandora);
1859
1860
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 0, &self->mainAnimator, false, 0);
1861
RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, false, 0);
1862
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, false, 7);
1863
RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &self->capsuleAnimator, false, 7);
1864
1865
Vector2 drawPos = self->position;
1866
self->mainAnimator.frameID = 4;
1867
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1868
1869
self->mainAnimator.frameID = 5;
1870
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1871
1872
self->mainAnimator.frameID = 2;
1873
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1874
1875
self->mainAnimator.frameID = 3;
1876
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1877
1878
self->mainAnimator.frameID = 0;
1879
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1880
1881
int32 storeDir = self->direction;
1882
self->direction = Gachapandora->eggmanDir;
1883
drawPos.x = self->position.x;
1884
drawPos.y = self->position.y - 0x100000;
1885
RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);
1886
1887
self->direction = storeDir;
1888
1889
self->mainAnimator.frameID = 1;
1890
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
1891
1892
self->direction = Gachapandora->handleDir;
1893
drawPos.y += 0x1A0000;
1894
RSDK.DrawSprite(&self->handleAnimator, &drawPos, false);
1895
1896
self->direction = storeDir;
1897
1898
if (showGizmos()) {
1899
RSDK_DRAWING_OVERLAY(true);
1900
1901
DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE, WIDE_SCR_XCENTER, 128, 1 | 0 | 4 | 8, 0x00C0F0);
1902
1903
RSDK_DRAWING_OVERLAY(false);
1904
}
1905
}
1906
1907
void Gachapandora_EditorLoad(void)
1908
{
1909
Gachapandora->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Gachapandora.bin", SCOPE_STAGE);
1910
Gachapandora->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanMMZ2.bin", SCOPE_STAGE);
1911
}
1912
#endif
1913
1914
void Gachapandora_Serialize(void) {}
1915
1916