Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/MMZ/EggPistonsMKII.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: EggPistonsMKII Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectEggPistonsMKII *EggPistonsMKII;
11
12
void EggPistonsMKII_Update(void)
13
{
14
RSDK_THIS(EggPistonsMKII);
15
16
StateMachine_Run(self->state);
17
}
18
19
void EggPistonsMKII_LateUpdate(void) {}
20
21
void EggPistonsMKII_StaticUpdate(void) {}
22
23
void EggPistonsMKII_Draw(void)
24
{
25
RSDK_THIS(EggPistonsMKII);
26
27
if (self->type == EGGPISTON_ALARM) {
28
RSDK.FillScreen(0x880000, EggPistonsMKII->alarmTimer, EggPistonsMKII->alarmTimer, EggPistonsMKII->alarmTimer);
29
}
30
else {
31
RSDK.DrawSprite(&self->altAnimator, NULL, false);
32
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
33
}
34
}
35
36
void EggPistonsMKII_Create(void *data)
37
{
38
RSDK_THIS(EggPistonsMKII);
39
40
self->drawFX = FX_FLIP;
41
if (!SceneInfo->inEditor) {
42
if (globals->gameMode < MODE_TIMEATTACK) {
43
self->active = ACTIVE_BOUNDS;
44
45
if (data)
46
self->type = VOID_TO_INT(data);
47
48
switch (self->type) {
49
case EGGPISTON_PISTON:
50
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 0, &self->mainAnimator, true, 0);
51
52
self->updateRange.x = 0xA00000;
53
self->updateRange.y = 0xEC0000;
54
55
self->hitbox.left = -32;
56
self->hitbox.top = -96;
57
self->hitbox.right = 32;
58
self->hitbox.bottom = 60;
59
60
self->state = EggPistonsMKII_StatePiston_Idle;
61
self->visible = true;
62
self->drawGroup = Zone->fgDrawGroup[1] - 1;
63
self->pistonID = self->position.y;
64
65
EggPistonsMKII->pistons[EggPistonsMKII->pistonCount++] = self;
66
break;
67
68
case EGGPISTON_CONTROL:
69
RSDK.SetSpriteAnimation(EggPistonsMKII->eggmanFrames, 0, &self->mainAnimator, true, 0);
70
71
self->updateRange.x = 0x800000;
72
self->updateRange.y = 0x800000;
73
74
self->hitbox.left = -33;
75
self->hitbox.top = -37;
76
self->hitbox.right = 33;
77
self->hitbox.bottom = 6;
78
79
self->state = EggPistonsMKII_State_SetupArena;
80
self->visible = false;
81
self->drawGroup = Zone->objectDrawGroup[0];
82
83
EggPistonsMKII->controller = self;
84
break;
85
86
case EGGPISTON_EMITTER:
87
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 1, &self->mainAnimator, true, 0);
88
89
self->updateRange.x = 0x800000;
90
self->updateRange.y = 0x800000;
91
92
self->hitbox.left = -8;
93
self->hitbox.top = -8;
94
self->hitbox.right = 8;
95
self->hitbox.bottom = 8;
96
97
self->state = EggPistonsMKII_StatePiston_Idle;
98
self->visible = true;
99
self->drawGroup = Zone->objectDrawGroup[0] + 1;
100
break;
101
102
case EGGPISTON_BARRIER:
103
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 5, &self->mainAnimator, true, 0);
104
105
self->hitbox.left = -32;
106
self->hitbox.top = -32;
107
self->hitbox.right = 32;
108
self->hitbox.bottom = 32;
109
110
self->state = EggPistonsMKII_StateOrbGenerator_Idle;
111
self->updateRange.x = 0x800000;
112
self->updateRange.y = 0x800000;
113
self->visible = true;
114
self->drawGroup = Zone->objectDrawGroup[0];
115
break;
116
117
case EGGPISTON_PLASMABALL:
118
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 2, &self->mainAnimator, true, 0);
119
120
self->hitbox.left = -12;
121
self->hitbox.top = -12;
122
self->hitbox.right = 12;
123
self->hitbox.bottom = 12;
124
125
self->state = EggPistonsMKII_StateOrb_MoveToTargetPos;
126
self->updateRange.x = 0x800000;
127
self->updateRange.y = 0x800000;
128
self->visible = true;
129
self->drawGroup = Zone->objectDrawGroup[0];
130
break;
131
132
case EGGPISTON_ALARM:
133
self->updateRange.x = 0x800000;
134
self->updateRange.y = 0x800000;
135
136
self->state = EggPistonsMKII_StateAlarm_Active;
137
self->visible = true;
138
self->drawGroup = Zone->objectDrawGroup[1];
139
break;
140
141
default: break;
142
}
143
}
144
else {
145
destroyEntity(self);
146
}
147
}
148
}
149
150
void EggPistonsMKII_StageLoad(void)
151
{
152
EggPistonsMKII->aniFrames = RSDK.LoadSpriteAnimation("MMZ/EggPistonsMKII.bin", SCOPE_STAGE);
153
EggPistonsMKII->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanMMZ1.bin", SCOPE_STAGE);
154
155
EggPistonsMKII->pistonCount = 0;
156
EggPistonsMKII->invincibilityTimer = 0;
157
EggPistonsMKII->isPhase2 = false;
158
159
EggPistonsMKII->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");
160
EggPistonsMKII->sfxWall = RSDK.GetSfx("Stage/Wall.wav");
161
EggPistonsMKII->sfxElectrify = RSDK.GetSfx("Stage/Electrify.wav");
162
EggPistonsMKII->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");
163
EggPistonsMKII->sfxAlarm = RSDK.GetSfx("MMZ/Alarm.wav");
164
165
RSDK.StopSfx(EggPistonsMKII->sfxAlarm);
166
}
167
168
void EggPistonsMKII_CheckPlayerCollisions_Piston(void)
169
{
170
RSDK_THIS(EggPistonsMKII);
171
172
EntityEggPistonsMKII *parent = self->parent;
173
174
foreach_active(Player, player)
175
{
176
int32 side = Player_CheckCollisionBox(player, self, &self->hitbox);
177
if (side == C_TOP) {
178
player->position.y += self->velocity.y;
179
player->position.y &= 0xFFFF0000;
180
}
181
else if (side == C_BOTTOM && player->onGround)
182
player->deathType = PLAYER_DEATH_DIE_USESFX;
183
}
184
185
self->position.y += self->velocity.y;
186
if (parent) {
187
parent->position.x = self->position.x;
188
parent->position.y = self->position.y;
189
parent->position.y += self->direction ? 0xE0000 : -0xA0000;
190
}
191
}
192
193
void EggPistonsMKII_CheckPlayerCollisions_EggPiston(void)
194
{
195
RSDK_THIS(EggPistonsMKII);
196
197
foreach_active(Player, player)
198
{
199
if (!EggPistonsMKII->invincibilityTimer && Player_CheckBadnikTouch(player, self, &self->hitbox)
200
&& EggPistonsMKII_CheckPlayerAttacking(player)) {
201
EggPistonsMKII_Hit();
202
}
203
}
204
}
205
206
void EggPistonsMKII_CheckPlayerCollisions_Ball(void)
207
{
208
RSDK_THIS(EggPistonsMKII);
209
210
foreach_active(Player, player)
211
{
212
if (Player_CheckCollisionTouch(player, self, &self->hitbox))
213
Player_ElementHurt(player, self, SHIELD_LIGHTNING);
214
}
215
}
216
217
void EggPistonsMKII_CheckPlayerCollisions_Solid(void)
218
{
219
RSDK_THIS(EggPistonsMKII);
220
221
foreach_active(Player, player)
222
{
223
if (Player_CheckCollisionBox(player, self, &self->hitbox) == C_BOTTOM) {
224
if (player->onGround)
225
player->deathType = PLAYER_DEATH_DIE_USESFX;
226
}
227
}
228
}
229
230
void EggPistonsMKII_Hit(void)
231
{
232
RSDK_THIS(EggPistonsMKII);
233
234
EggPistonsMKII->invincibilityTimer = 120;
235
if (EggPistonsMKII->health > 0)
236
EggPistonsMKII->health--;
237
238
if (EggPistonsMKII->health) {
239
RSDK.SetSpriteAnimation(EggPistonsMKII->eggmanFrames, 1, &self->mainAnimator, true, 0);
240
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 4, &self->altAnimator, true, 0);
241
RSDK.PlaySfx(EggPistonsMKII->sfxHit, false, 255);
242
}
243
else {
244
RSDK.SetSpriteAnimation(EggPistonsMKII->eggmanFrames, 2, &self->mainAnimator, true, 0);
245
SceneInfo->timeEnabled = false;
246
Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);
247
self->mainAnimator.frameID = 1;
248
RSDK.PlaySfx(EggPistonsMKII->sfxExplosion, false, 255);
249
self->state = EggPistonsMKII_State_Finish;
250
}
251
}
252
253
void EggPistonsMKII_Explode(void)
254
{
255
RSDK_THIS(EggPistonsMKII);
256
257
int32 interval = 4 * (EggPistonsMKII->health != 0) + 3;
258
259
if (!(Zone->timer % interval)) {
260
RSDK.PlaySfx(EggPistonsMKII->sfxExplosion, false, 255);
261
262
if (Zone->timer & 4) {
263
int32 x = self->position.x + (RSDK.Rand(-24, 24) << 16);
264
int32 y = self->position.y + (RSDK.Rand(-48, 48) << 16);
265
CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1];
266
}
267
}
268
}
269
270
EntityEggPistonsMKII *EggPistonsMKII_GetNextPiston(void)
271
{
272
RSDK_THIS(EggPistonsMKII);
273
274
int32 pistonID = RSDK.Rand(0, 5);
275
EntityEggPistonsMKII *piston = EggPistonsMKII->pistons[pistonID];
276
277
if (piston->state != EggPistonsMKII_StatePiston_Idle)
278
pistonID = EggPistonsMKII->pistonID - 1; // force another try
279
280
while (pistonID == EggPistonsMKII->pistonID - 1 || pistonID == EggPistonsMKII->pistonID + 1) {
281
pistonID = RSDK.Rand(0, 5);
282
piston = EggPistonsMKII->pistons[pistonID];
283
284
if (piston->state != EggPistonsMKII_StatePiston_Idle)
285
pistonID = EggPistonsMKII->pistonID - 1; // force another try
286
}
287
288
EggPistonsMKII->pistonID = pistonID;
289
290
self->visible = true;
291
piston->timer = 15;
292
piston->state = EggPistonsMKII_StatePiston_Shaking;
293
return piston;
294
}
295
296
void EggPistonsMKII_SpawnElecBall(void)
297
{
298
EntityEggPistonsMKII *spawner = RSDK_GET_ENTITY(SceneInfo->entitySlot + 6, EggPistonsMKII);
299
spawner->state = EggPistonsMKII_StateOrbGenerator_Warning;
300
spawner->timer = 330;
301
int32 offset = 0;
302
303
for (int32 i = 0; i < 4; ++i) {
304
EntityEggPistonsMKII *child = CREATE_ENTITY(EggPistonsMKII, INT_TO_VOID(EGGPISTON_PLASMABALL), spawner->position.x, spawner->position.y);
305
child->pistonID = offset + spawner->position.x + ((RSDK.Rand(0, 48) - 48) << 16);
306
child->inkEffect = INK_ADD;
307
child->velocity.x = (child->pistonID - child->position.x) >> 4;
308
child->alpha = 0;
309
offset -= 0x570000;
310
}
311
}
312
313
bool32 EggPistonsMKII_CheckPlayerAttacking(EntityPlayer *player)
314
{
315
RSDK_THIS(EggPistonsMKII);
316
317
if (Player_CheckAttacking(player, NULL)) {
318
if (player->position.x >= self->position.x) {
319
player->velocity.x = 0x30000;
320
player->groundVel = 0x30000;
321
}
322
else {
323
player->velocity.x = -0x30000;
324
player->groundVel = -0x30000;
325
}
326
327
if (player->characterID == ID_KNUCKLES && player->animator.animationID == ANI_GLIDE) {
328
RSDK.SetSpriteAnimation(Player->knuxFrames, ANI_GLIDE_DROP, &player->animator, true, 0);
329
player->state = Player_State_KnuxGlideDrop;
330
}
331
332
return true;
333
}
334
335
return false;
336
}
337
338
void EggPistonsMKII_State_SetupArena(void)
339
{
340
RSDK_THIS(EggPistonsMKII);
341
342
for (int32 i = 0; i < 6; ++i) {
343
EntityCollapsingPlatform *platform = RSDK_GET_ENTITY(SceneInfo->entitySlot + 8 + i, CollapsingPlatform);
344
if (platform->classID == CollapsingPlatform->classID)
345
platform->active = ACTIVE_NEVER;
346
}
347
348
if (++self->timer >= 2) {
349
self->timer = 0;
350
351
Zone->playerBoundActiveR[0] = true;
352
Zone->playerBoundActiveB[0] = true;
353
Zone->cameraBoundsR[0] = (self->position.x >> 16) + ScreenInfo->center.x;
354
Zone->cameraBoundsB[0] = (self->position.y >> 16) + 71;
355
Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - ScreenInfo->size.y;
356
357
self->active = ACTIVE_NORMAL;
358
self->state = EggPistonsMKII_State_EnterBoss;
359
}
360
}
361
362
void EggPistonsMKII_State_EnterBoss(void)
363
{
364
RSDK_THIS(EggPistonsMKII);
365
366
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
367
368
Zone->playerBoundActiveL[0] = true;
369
Zone->cameraBoundsL[0] = ScreenInfo->position.x;
370
371
int32 pos = MANIA_USE_PLUS ? (self->position.x - 0xC00000) : self->position.x;
372
if (player1->position.x > pos) {
373
#if MANIA_USE_PLUS
374
if (player1->onGround)
375
player1->state = Player_State_Ground;
376
player1->stateInput = StateMachine_None;
377
player1->jumpPress = false;
378
player1->jumpHold = false;
379
player1->left = false;
380
player1->right = true;
381
player1->up = false;
382
player1->down = false;
383
384
if (player1->groundVel > 0x30000)
385
player1->groundVel = 0x30000;
386
387
if (player1->position.x > (self->position.x - 0x80000)) {
388
#endif
389
Zone->playerBoundActiveL[0] = true;
390
Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;
391
Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);
392
EggPistonsMKII->health = 8;
393
394
self->timer = 142;
395
for (int32 i = 0; i < 2; ++i) {
396
EntityEggPistonsMKII *barrier = RSDK_GET_ENTITY(SceneInfo->entitySlot + 14 + i, EggPistonsMKII);
397
barrier->velocity.y = -0x20000;
398
barrier->timer = 64;
399
barrier->state = EggPistonsMKII_StateBarrier_Solid;
400
}
401
402
player1->right = false;
403
player1->left = true;
404
self->state = EggPistonsMKII_State_PistonReveal;
405
#if MANIA_USE_PLUS
406
}
407
#endif
408
}
409
}
410
411
void EggPistonsMKII_State_PistonReveal(void)
412
{
413
RSDK_THIS(EggPistonsMKII);
414
415
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
416
417
if (!player1->stateInput && player1->groundVel <= 0) {
418
player1->groundVel = 0;
419
player1->velocity.x = 0;
420
player1->left = false;
421
player1->direction = FLIP_NONE;
422
}
423
424
if (--self->timer <= 0) {
425
player1->stateInput = Player_Input_P1;
426
427
for (int32 i = 0; i < 6; ++i) {
428
EntityCollapsingPlatform *platform = RSDK_GET_ENTITY(SceneInfo->entitySlot + 8 + i, CollapsingPlatform);
429
if (platform->classID == CollapsingPlatform->classID) {
430
platform->active = ACTIVE_NORMAL;
431
platform->collapseDelay = 8;
432
platform->stoodPos.x = self->position.x;
433
}
434
}
435
436
for (int32 i = 0; i < 2; ++i) {
437
EntityEggPistonsMKII *piston = RSDK_GET_ENTITY(SceneInfo->entitySlot + 14 + i, EggPistonsMKII);
438
piston->velocity.y = 0x80000;
439
piston->timer = 8;
440
piston->state = EggPistonsMKII_StateBarrier_Solid;
441
}
442
443
self->position.y -= 0x800000;
444
self->timer = 120;
445
self->state = EggPistonsMKII_State_ClassicMode;
446
}
447
}
448
449
void EggPistonsMKII_State_ClassicMode(void)
450
{
451
RSDK_THIS(EggPistonsMKII);
452
453
if (--self->timer <= 0) {
454
if (self->pistonID) {
455
if (EggPistonsMKII->health > 4) {
456
EggPistonsMKII_SpawnElecBall();
457
RSDK.PlaySfx(EggPistonsMKII->sfxElectrify, false, 255);
458
self->timer = 345;
459
}
460
else {
461
self->timer = 120;
462
self->state = EggPistonsMKII_State_StartPinchMode;
463
}
464
}
465
else {
466
EggPistonsMKII_GetNextPiston();
467
EggPistonsMKII_GetNextPiston()->parent = self;
468
469
RSDK.SetSpriteAnimation(EggPistonsMKII->eggmanFrames, 0, &self->mainAnimator, true, 0);
470
RSDK.SetSpriteAnimation(-1, 0, &self->altAnimator, true, 0);
471
472
self->timer = 165;
473
RSDK.PlaySfx(EggPistonsMKII->sfxWall, false, 255);
474
}
475
self->pistonID ^= 1;
476
}
477
478
if (EggPistonsMKII->invincibilityTimer)
479
EggPistonsMKII->invincibilityTimer--;
480
481
self->direction = RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x <= self->position.x;
482
483
RSDK.ProcessAnimation(&self->mainAnimator);
484
RSDK.ProcessAnimation(&self->altAnimator);
485
486
if (self->visible)
487
EggPistonsMKII_CheckPlayerCollisions_EggPiston();
488
}
489
490
void EggPistonsMKII_State_StartPinchMode(void)
491
{
492
RSDK_THIS(EggPistonsMKII);
493
494
if (--self->timer <= 0) {
495
CREATE_ENTITY(EggPistonsMKII, INT_TO_VOID(EGGPISTON_ALARM), self->position.x, self->position.y);
496
497
EntityEggPistonsMKII *orbSpawner = RSDK_GET_ENTITY(SceneInfo->entitySlot + 6, EggPistonsMKII);
498
RSDK.PlaySfx(EggPistonsMKII->sfxExplosion, false, 255);
499
CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_ENEMY), orbSpawner->position.x, orbSpawner->position.y)->drawGroup = Zone->objectDrawGroup[1];
500
501
EggPistonsMKII->isPhase2 = true;
502
destroyEntity(orbSpawner);
503
504
self->timer = 120;
505
self->pistonID = 1;
506
RSDK.PlaySfx(EggPistonsMKII->sfxAlarm, true, 255);
507
self->state = EggPistonsMKII_State_PinchMode;
508
}
509
}
510
511
void EggPistonsMKII_State_PinchMode(void)
512
{
513
RSDK_THIS(EggPistonsMKII);
514
515
if (--self->timer <= 0) {
516
EntityEggPistonsMKII *piston = EggPistonsMKII_GetNextPiston();
517
if (!self->pistonID) {
518
piston->parent = self;
519
RSDK.SetSpriteAnimation(EggPistonsMKII->eggmanFrames, 0, &self->mainAnimator, true, 0);
520
RSDK.SetSpriteAnimation(-1, 0, &self->altAnimator, true, 0);
521
}
522
523
self->pistonID = (self->pistonID + 1) & 3;
524
525
RSDK.PlaySfx(EggPistonsMKII->sfxWall, false, 255);
526
self->timer = 64;
527
}
528
529
if (EggPistonsMKII->invincibilityTimer)
530
EggPistonsMKII->invincibilityTimer--;
531
532
self->direction = RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x <= self->position.x;
533
RSDK.ProcessAnimation(&self->mainAnimator);
534
RSDK.ProcessAnimation(&self->altAnimator);
535
536
if (self->visible)
537
EggPistonsMKII_CheckPlayerCollisions_EggPiston();
538
539
if (!EggPistonsMKII->health)
540
self->state = EggPistonsMKII_State_Destroyed;
541
}
542
543
void EggPistonsMKII_State_Destroyed(void)
544
{
545
RSDK_THIS(EggPistonsMKII);
546
547
int32 id = 0;
548
for (int32 i = 0; i < 5; ++i) {
549
EntityEggPistonsMKII *piston = EggPistonsMKII->pistons[i];
550
551
if (piston->state == EggPistonsMKII_StatePiston_Idle)
552
++id;
553
}
554
555
if (++id >= 5) {
556
EggPistonsMKII->isPhase2 = false;
557
Music_TransitionTrack(TRACK_STAGE, 0.0125);
558
RSDK.StopSfx(EggPistonsMKII->sfxAlarm);
559
self->state = EggPistonsMKII_State_Finish;
560
}
561
}
562
563
void EggPistonsMKII_State_Finish(void) {}
564
565
void EggPistonsMKII_StatePiston_Idle(void) { EggPistonsMKII_CheckPlayerCollisions_Piston(); }
566
567
void EggPistonsMKII_StatePiston_Shaking(void)
568
{
569
RSDK_THIS(EggPistonsMKII);
570
571
self->position.y = (RSDK.Rand(-2, 3) << 16) + self->pistonID;
572
EggPistonsMKII_CheckPlayerCollisions_Piston();
573
574
if (!--self->timer) {
575
self->position.y = self->pistonID;
576
self->velocity.y = self->direction == FLIP_NONE ? -0x8000 : 0x8000;
577
578
self->timer = 32;
579
self->state = EggPistonsMKII_StatePiston_BeginCrushing;
580
}
581
582
if (!EggPistonsMKII->health) {
583
self->position.y = self->pistonID;
584
self->state = EggPistonsMKII_StatePiston_Explode;
585
586
EggPistonsMKII_Explode();
587
}
588
}
589
590
void EggPistonsMKII_StatePiston_BeginCrushing(void)
591
{
592
RSDK_THIS(EggPistonsMKII);
593
594
EggPistonsMKII_CheckPlayerCollisions_Piston();
595
if (!--self->timer) {
596
self->timer = 48;
597
self->velocity.y = self->direction == FLIP_NONE ? -0x30000 : 0x30000;
598
self->state = EggPistonsMKII_StatePiston_CrushExtend;
599
}
600
601
if (!EggPistonsMKII->health) {
602
self->velocity.y = self->direction == FLIP_NONE ? 0x10000 : -0x10000;
603
self->timer >>= 1;
604
self->state = EggPistonsMKII_StatePiston_Explode;
605
606
EggPistonsMKII_Explode();
607
}
608
}
609
610
void EggPistonsMKII_StatePiston_CrushExtend(void)
611
{
612
RSDK_THIS(EggPistonsMKII);
613
614
EggPistonsMKII_CheckPlayerCollisions_Piston();
615
616
if (!--self->timer) {
617
self->timer = 80;
618
self->velocity.y = self->direction == FLIP_NONE ? 0x20000 : -0x20000;
619
self->state = EggPistonsMKII_StatePiston_Retract;
620
}
621
622
if (!EggPistonsMKII->health) {
623
self->state = EggPistonsMKII_StatePiston_Explode;
624
self->velocity.y = self->direction == FLIP_NONE ? 0x10000 : -0x10000;
625
self->timer >>= 1;
626
627
EggPistonsMKII_Explode();
628
}
629
}
630
631
void EggPistonsMKII_StatePiston_Retract(void)
632
{
633
RSDK_THIS(EggPistonsMKII);
634
635
EggPistonsMKII_CheckPlayerCollisions_Piston();
636
637
if (!--self->timer) {
638
self->velocity.y = 0;
639
self->parent = NULL;
640
self->state = EggPistonsMKII_StatePiston_Idle;
641
}
642
643
if (!EggPistonsMKII->health || (!EggPistonsMKII->isPhase2 && EggPistonsMKII->health == 4)) {
644
self->state = EggPistonsMKII_StatePiston_Explode;
645
self->velocity.y = self->direction == FLIP_NONE ? 0x10000 : -0x10000;
646
647
EggPistonsMKII_Explode();
648
}
649
}
650
651
void EggPistonsMKII_StatePiston_Explode(void)
652
{
653
RSDK_THIS(EggPistonsMKII);
654
655
if ((self->direction || self->position.y < self->pistonID) && (self->direction != FLIP_Y || self->position.y > self->pistonID)) {
656
EggPistonsMKII_CheckPlayerCollisions_Piston();
657
658
if (!EggPistonsMKII->health || (!EggPistonsMKII->isPhase2 && EggPistonsMKII->health == 4)) {
659
EggPistonsMKII_Explode();
660
}
661
}
662
else {
663
self->position.y = self->pistonID;
664
self->velocity.y = 0;
665
self->parent = NULL;
666
self->state = EggPistonsMKII_StatePiston_Idle;
667
}
668
}
669
670
void EggPistonsMKII_StateOrbGenerator_Idle(void) {}
671
672
void EggPistonsMKII_StateOrbGenerator_Warning(void)
673
{
674
RSDK_THIS(EggPistonsMKII);
675
676
RSDK.ProcessAnimation(&self->mainAnimator);
677
678
if ((self->timer & 7) == 4)
679
RSDK.PlaySfx(EggPistonsMKII->sfxElectrify, false, 255);
680
681
if (!--self->timer) {
682
self->mainAnimator.frameID = 0;
683
self->state = EggPistonsMKII_StateOrbGenerator_Idle;
684
}
685
}
686
687
void EggPistonsMKII_StateOrb_MoveToTargetPos(void)
688
{
689
RSDK_THIS(EggPistonsMKII);
690
691
if (self->alpha < 0xC0)
692
self->alpha += 0x10;
693
694
self->position.x += self->velocity.x;
695
696
if (self->position.x <= self->pistonID) {
697
self->timer = 180;
698
self->state = EggPistonsMKII_StateOrb_Charging;
699
}
700
701
RSDK.ProcessAnimation(&self->mainAnimator);
702
}
703
704
void EggPistonsMKII_StateOrb_Charging(void)
705
{
706
RSDK_THIS(EggPistonsMKII);
707
708
if (!--self->timer) {
709
self->alpha = 0x80;
710
self->velocity.x = (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x - self->position.x) >> 7;
711
self->velocity.y = 0x14000;
712
self->timer = 133;
713
714
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 3, &self->altAnimator, true, 0);
715
self->state = EggPistonsMKII_StateOrb_Attacking;
716
self->mainAnimator.speed *= 2;
717
}
718
719
RSDK.ProcessAnimation(&self->mainAnimator);
720
}
721
722
void EggPistonsMKII_StateOrb_Attacking(void)
723
{
724
RSDK_THIS(EggPistonsMKII);
725
726
self->velocity.x = (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x - self->position.x) >> 7;
727
self->position.x += self->velocity.x;
728
self->position.y += self->velocity.y;
729
730
if (!--self->timer)
731
destroyEntity(self);
732
733
RSDK.ProcessAnimation(&self->mainAnimator);
734
735
EggPistonsMKII_CheckPlayerCollisions_Ball();
736
}
737
738
void EggPistonsMKII_StateAlarm_Active(void)
739
{
740
RSDK_THIS(EggPistonsMKII);
741
742
EggPistonsMKII->alarmTimer = (abs(RSDK.Sin256(2 * EggPistonsMKII->alarmAngle)) >> 1) + 32;
743
++EggPistonsMKII->alarmAngle;
744
745
if (!EggPistonsMKII->health && !EggPistonsMKII->isPhase2 && EggPistonsMKII->alarmTimer == 32)
746
self->state = EggPistonsMKII_StateAlarm_Destroyed;
747
}
748
749
void EggPistonsMKII_StateAlarm_Destroyed(void)
750
{
751
RSDK_THIS(EggPistonsMKII);
752
753
if (!--EggPistonsMKII->alarmTimer) {
754
for (int32 i = 0; i < 2; ++i) {
755
int32 slot = RSDK.GetEntitySlot(EggPistonsMKII->controller);
756
EntityEggPistonsMKII *barrier = RSDK_GET_ENTITY(slot + 14 + i, EggPistonsMKII);
757
758
for (int32 d = 0; d < 4; ++d) {
759
EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, barrier->position.x, barrier->position.y);
760
RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 5, &debris->animator, true, i + 1);
761
debris->gravityStrength = 0x3800;
762
debris->velocity.x = ((i & 1) << 17 >> (i >> 1)) - 0x10000;
763
debris->velocity.y = 0x18000 * ((i >> 1) - 2);
764
debris->drawGroup = Zone->objectDrawGroup[1];
765
debris->updateRange.x = 0x400000;
766
debris->updateRange.y = 0x400000;
767
}
768
769
destroyEntity(barrier);
770
}
771
772
Zone->cameraBoundsR[0] += WIDE_SCR_XSIZE;
773
Zone->playerBoundActiveR[0] = false;
774
775
destroyEntity(self);
776
}
777
}
778
779
void EggPistonsMKII_StateBarrier_Solid(void)
780
{
781
RSDK_THIS(EggPistonsMKII);
782
783
self->position.y += self->velocity.y;
784
if (--self->timer <= 0) {
785
self->state = EggPistonsMKII_StateBarrier_Explode;
786
787
if (self->velocity.y == 0x80000) {
788
RSDK_GET_ENTITY(SLOT_CAMERA1, Camera)->shakePos.y = 4;
789
self->velocity.y = 0;
790
}
791
else if (self->velocity.y == 0x20000) {
792
self->velocity.y = -0x20000;
793
self->timer = 32;
794
self->state = EggPistonsMKII_StateBarrier_Solid;
795
}
796
}
797
798
EggPistonsMKII_CheckPlayerCollisions_Solid();
799
}
800
801
void EggPistonsMKII_StateBarrier_Explode(void)
802
{
803
EggPistonsMKII_CheckPlayerCollisions_Solid();
804
805
if (!EggPistonsMKII->health)
806
EggPistonsMKII_Explode();
807
}
808
809
#if GAME_INCLUDE_EDITOR
810
void EggPistonsMKII_EditorDraw(void)
811
{
812
RSDK_THIS(EggPistonsMKII);
813
814
self->updateRange.x = 0x800000;
815
self->updateRange.y = 0x800000;
816
817
switch (self->type) {
818
case EGGPISTON_PISTON: RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 0, &self->mainAnimator, true, 0); break;
819
case EGGPISTON_CONTROL: RSDK.SetSpriteAnimation(EggPistonsMKII->eggmanFrames, 0, &self->mainAnimator, true, 0); break;
820
case EGGPISTON_EMITTER: RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 1, &self->mainAnimator, true, 0); break;
821
case EGGPISTON_BARRIER: RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 5, &self->mainAnimator, true, 0); break;
822
case EGGPISTON_PLASMABALL: RSDK.SetSpriteAnimation(EggPistonsMKII->aniFrames, 2, &self->mainAnimator, true, 0); break;
823
case EGGPISTON_ALARM: RSDK.SetSpriteAnimation(-1, 0, &self->mainAnimator, true, 0); break;
824
default: break;
825
}
826
827
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
828
829
if (self->type == EGGPISTON_CONTROL && showGizmos()) {
830
RSDK_DRAWING_OVERLAY(true);
831
832
DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE, WIDE_SCR_XCENTER, 71, 1 | 2 | 4 | 8, 0x00C0F0);
833
834
RSDK_DRAWING_OVERLAY(false);
835
}
836
}
837
838
void EggPistonsMKII_EditorLoad(void)
839
{
840
EggPistonsMKII->aniFrames = RSDK.LoadSpriteAnimation("MMZ/EggPistonsMKII.bin", SCOPE_STAGE);
841
EggPistonsMKII->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanMMZ1.bin", SCOPE_STAGE);
842
843
RSDK_ACTIVE_VAR(EggPistonsMKII, type);
844
RSDK_ENUM_VAR("Piston", EGGPISTON_PISTON);
845
RSDK_ENUM_VAR("Control", EGGPISTON_CONTROL);
846
RSDK_ENUM_VAR("Emitter", EGGPISTON_EMITTER);
847
RSDK_ENUM_VAR("Barrier", EGGPISTON_BARRIER);
848
}
849
#endif
850
851
void EggPistonsMKII_Serialize(void)
852
{
853
RSDK_EDITABLE_VAR(EggPistonsMKII, VAR_UINT8, direction);
854
RSDK_EDITABLE_VAR(EggPistonsMKII, VAR_UINT8, type);
855
}
856
857