Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/ERZ/ERZStart.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: ERZStart Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectERZStart *ERZStart;
11
12
void ERZStart_Update(void)
13
{
14
RSDK_THIS(ERZStart);
15
16
if (!self->activated) {
17
foreach_active(Player, player)
18
{
19
if (!player->sidekick && Player_CheckCollisionTouch(player, self, &self->hitbox)) {
20
CutsceneSeq_StartSequence(self, ERZStart_Cutscene_FadeIn, ERZStart_Cutscene_ShrinkRubyWarpFX, ERZStart_Cutscene_EnterKing,
21
ERZStart_Cutscene_KingMovingRuby, ERZStart_Cutscene_KingAttachHornRuby,
22
ERZStart_Cutscene_SetupEggmanReveal, ERZStart_Cutscene_EnterEggman, ERZStart_Cutscene_EggmanKingWrestling,
23
ERZStart_Cutscene_PostWrestleFadeIn, ERZStart_Cutscene_ReturnCamToSonic,
24
ERZStart_Cutscene_PreparePlayerTransform, ERZStart_Cutscene_PlayerTransform, ERZStart_Cutscene_StartFight,
25
ERZStart_Cutscene_Fight, StateMachine_None);
26
27
#if MANIA_USE_PLUS
28
CutsceneSeq_SetSkipType(SKIPTYPE_DISABLED);
29
#endif
30
31
self->activated = true;
32
}
33
}
34
}
35
36
// Have the timer go haywire
37
if (--self->timer <= 0) {
38
// update every 15, 30, 45 or 60 frames
39
self->timer = 15 * RSDK.Rand(0, 4);
40
SceneInfo->seconds = RSDK.Rand(0, 100);
41
SceneInfo->milliseconds = RSDK.Rand(0, 100);
42
SceneInfo->minutes = RSDK.Rand(0, 9);
43
}
44
45
#if !MANIA_USE_PLUS
46
if (ERZStart->superDashCooldown > 0) {
47
RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
48
HUD_EnableRingFlash();
49
--ERZStart->superDashCooldown;
50
}
51
#endif
52
}
53
54
void ERZStart_LateUpdate(void) {}
55
56
void ERZStart_StaticUpdate(void) {}
57
58
void ERZStart_Draw(void) {}
59
60
void ERZStart_Create(void *data)
61
{
62
RSDK_THIS(ERZStart);
63
64
if (!SceneInfo->inEditor) {
65
INIT_ENTITY(self);
66
CutsceneRules_SetupEntity(self, &self->size, &self->hitbox);
67
self->active = ACTIVE_NORMAL;
68
69
ERZStart_SetupObjects();
70
ERZStart->timer = 0;
71
}
72
}
73
74
void ERZStart_StageLoad(void)
75
{
76
ERZStart->sfxClack = RSDK.GetSfx("Stage/Clack.wav");
77
ERZStart->sfxFlyIn = RSDK.GetSfx("ERZ/FlyIn.wav");
78
ERZStart->sfxHullClose = RSDK.GetSfx("Stage/HullClose.wav");
79
ERZStart->sfxRumble = RSDK.GetSfx("Stage/Rumble.wav");
80
}
81
82
void ERZStart_SetupObjects(void)
83
{
84
foreach_all(PhantomRuby, ruby)
85
{
86
ERZStart->ruby = ruby;
87
foreach_break;
88
}
89
90
foreach_all(FXRuby, fxRuby)
91
{
92
ERZStart->fxRuby = fxRuby;
93
fxRuby->state = StateMachine_None;
94
fxRuby->fadeBlack = 0x200;
95
fxRuby->fadeWhite = 0x200;
96
fxRuby->outerRadius = ScreenInfo->size.x;
97
fxRuby->timer = 64;
98
foreach_break;
99
}
100
101
foreach_all(PhantomKing, king)
102
{
103
if (!king->type)
104
ERZStart->king = king;
105
}
106
107
foreach_all(ChaosEmerald, emerald) { ERZStart->emeralds[emerald->type] = emerald; }
108
109
foreach_all(KleptoMobile, eggman)
110
{
111
if (!eggman->type)
112
ERZStart->eggman = eggman;
113
}
114
}
115
116
void ERZStart_HandlePlayerHover(EntityPlayer *player, EntityCutsceneSeq *seq, int32 posY)
117
{
118
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
119
player->position.x = 0x300000;
120
player->position.x += (player->position.x - player->position.x) >> 3;
121
player->position.y += (posY + 0xA00 * RSDK.Sin256(2 * (seq->timer - seq->storedTimer + 64)) - player->position.y) >> 3;
122
player->state = Player_State_Static;
123
124
for (int32 e = 0; e < 7; ++e) {
125
EntityChaosEmerald *emerald = ERZStart->emeralds[e];
126
emerald->originPos = player->position;
127
emerald->active = ACTIVE_NORMAL;
128
}
129
}
130
131
bool32 ERZStart_Cutscene_FadeIn(EntityCutsceneSeq *host)
132
{
133
MANIA_GET_PLAYER(player1, player2, camera);
134
UNUSED(player2);
135
UNUSED(camera);
136
137
EntityPhantomRuby *ruby = ERZStart->ruby;
138
EntityFXRuby *fxRuby = ERZStart->fxRuby;
139
140
if (!host->timer) {
141
player1->position.y = ruby->position.y;
142
player1->state = Player_State_Static;
143
player1->stateInput = StateMachine_None;
144
CutsceneSeq_LockAllPlayerControl();
145
camera->position.x = 0;
146
camera->position.y = 0;
147
148
ScreenInfo->position.x = 0;
149
ScreenInfo->position.y = 0;
150
Zone->playerBoundsT[0] = 0;
151
Zone->cameraBoundsT[0] = 0;
152
camera->boundsT = 0;
153
Zone->playerBoundsB[0] = ScreenInfo->size.y;
154
Zone->cameraBoundsB[0] = Zone->playerBoundsB[0];
155
camera->boundsB = Zone->cameraBoundsB[0];
156
ruby->state = ERZStart_RubyHover;
157
158
int32 angle = 0;
159
for (int32 i = 0; i < 7; ++i) {
160
EntityChaosEmerald *emerald = ERZStart->emeralds[i];
161
emerald->originPos.x = player1->position.x;
162
emerald->originPos.y = player1->position.y;
163
emerald->angle = angle;
164
emerald->radius = 0x2000;
165
emerald->groundVel = 512;
166
emerald->state = ChaosEmerald_State_Rotate;
167
168
angle += 0x2492;
169
}
170
171
Zone->playerBoundActiveR[0] = true;
172
Zone->playerBoundsR[0] = 1552;
173
Zone->cameraBoundsR[0] = 1552;
174
}
175
176
if (host->timer >= 60) {
177
if (fxRuby->fadeBlack > 0) {
178
fxRuby->fadeBlack -= 16;
179
}
180
else {
181
if (fxRuby->fadeWhite > 0) {
182
fxRuby->fadeWhite -= 16;
183
}
184
else {
185
PhantomRuby_PlaySfx(RUBYSFX_ATTACK4);
186
return true;
187
}
188
}
189
}
190
191
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
192
return false;
193
}
194
195
bool32 ERZStart_Cutscene_ShrinkRubyWarpFX(EntityCutsceneSeq *host)
196
{
197
MANIA_GET_PLAYER(player1, player2, camera);
198
UNUSED(player2);
199
UNUSED(camera);
200
201
EntityPhantomRuby *ruby = ERZStart->ruby;
202
EntityFXRuby *fxRuby = ERZStart->fxRuby;
203
204
if (!host->timer)
205
fxRuby->state = FXRuby_State_Shrinking;
206
207
EntityPhantomKing *king = ERZStart->king;
208
if (fxRuby->outerRadius <= 0) {
209
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
210
ruby->drawGroup = Zone->objectDrawGroup[0] + 1;
211
king->state = PhantomKing_State_SetupArms;
212
return true;
213
}
214
215
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
216
return false;
217
}
218
219
bool32 ERZStart_Cutscene_EnterKing(EntityCutsceneSeq *host)
220
{
221
MANIA_GET_PLAYER(player1, player2, camera);
222
UNUSED(player2);
223
UNUSED(camera);
224
225
EntityPhantomRuby *ruby = ERZStart->ruby;
226
227
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
228
229
EntityPhantomKing *king = ERZStart->king;
230
if (king->state == PhantomKing_State_TakeRubyAway) {
231
ruby->state = ERZStart_RubyMove;
232
return true;
233
}
234
235
return false;
236
}
237
238
bool32 ERZStart_Cutscene_KingMovingRuby(EntityCutsceneSeq *host)
239
{
240
MANIA_GET_PLAYER(player1, player2, camera);
241
UNUSED(player2);
242
243
EntityPhantomRuby *ruby = ERZStart->ruby;
244
245
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
246
247
EntityPhantomKing *king = ERZStart->king;
248
if (!host->timer) {
249
camera->target = NULL;
250
player1->camera = NULL;
251
Zone->playerBoundActiveL[0] = false;
252
Zone->playerBoundActiveR[0] = false;
253
Zone->playerBoundActiveT[0] = false;
254
host->storedTimer = camera->position.x;
255
}
256
257
int32 pos = host->storedTimer;
258
if (king->position.x - 0x400000 > pos)
259
pos = king->position.x - 0x400000;
260
261
camera->position.x = pos;
262
263
if (king->finishedMovingRuby) {
264
ruby->state = StateMachine_None;
265
return true;
266
}
267
268
return false;
269
}
270
271
bool32 ERZStart_Cutscene_KingAttachHornRuby(EntityCutsceneSeq *host)
272
{
273
MANIA_GET_PLAYER(player1, player2, camera);
274
UNUSED(player2);
275
UNUSED(camera);
276
277
EntityPhantomRuby *ruby = ERZStart->ruby;
278
279
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
280
EntityPhantomKing *king = ERZStart->king;
281
282
if (!host->timer) {
283
host->storedTimer = ruby->position.x;
284
host->storedValue = ruby->position.y;
285
}
286
287
if (host->timer > 0) {
288
if (host->timer == 60) {
289
RSDK.PlaySfx(ERZStart->sfxClack, false, 255);
290
291
king->drawRuby = true;
292
ruby->position.x = -0x400000;
293
ruby->state = StateMachine_None;
294
return true;
295
}
296
297
int32 percent = 0x10000;
298
if (host->timer << 16 < 0x3C0000)
299
percent = (host->timer << 16) / 60;
300
301
Vector2 pos = MathHelpers_GetBezierPoint(percent, host->storedTimer, host->storedValue, host->storedTimer, host->storedValue - 0x400000,
302
king->rubyPos.x, king->rubyPos.y - 0x400000, king->rubyPos.x, king->rubyPos.y);
303
304
ruby->position.x += (pos.x - ruby->position.x) >> 2;
305
ruby->position.y += (pos.y - ruby->position.y) >> 2;
306
}
307
308
return false;
309
}
310
311
bool32 ERZStart_Cutscene_SetupEggmanReveal(EntityCutsceneSeq *host)
312
{
313
MANIA_GET_PLAYER(player1, player2, camera);
314
UNUSED(player2);
315
316
EntityPhantomRuby *ruby = ERZStart->ruby;
317
318
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
319
320
if (host->timer == 30)
321
Camera_SetupLerp(CAMERA_LERP_NORMAL, 0, camera->position.x - (ScreenInfo->size.x << 16), camera->position.y, 3);
322
323
if (host->timer == 45)
324
RSDK.PlaySfx(ERZStart->sfxFlyIn, false, 255);
325
326
return host->timer == 120;
327
}
328
329
bool32 ERZStart_Cutscene_EnterEggman(EntityCutsceneSeq *host)
330
{
331
MANIA_GET_PLAYER(player1, player2, camera);
332
UNUSED(player2);
333
334
EntityPhantomRuby *ruby = ERZStart->ruby;
335
336
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
337
338
EntityKleptoMobile *eggman = ERZStart->eggman;
339
EntityPhantomKing *king = ERZStart->king;
340
341
uint16 eggmanSlot = RSDK.GetEntitySlot(eggman);
342
EntityKleptoMobile *eggmanHand = RSDK_GET_ENTITY(eggmanSlot - 2, KleptoMobile);
343
EntityKleptoMobile *eggmanArmL = RSDK_GET_ENTITY(eggmanSlot - 1, KleptoMobile);
344
EntityKleptoMobile *eggmanArmR = RSDK_GET_ENTITY(eggmanSlot + 1, KleptoMobile);
345
346
uint16 kingSlot = RSDK.GetEntitySlot(king);
347
EntityPhantomKing *kingArmL = RSDK_GET_ENTITY(kingSlot - 1, PhantomKing);
348
EntityPhantomKing *kingArmR = RSDK_GET_ENTITY(kingSlot + 1, PhantomKing);
349
350
if (!host->timer) {
351
host->storedTimer = camera->position.x;
352
host->storedValue = camera->position.y;
353
king->originPos.y = king->position.y;
354
king->originPos.x = king->position.x;
355
king->state = PhantomKing_State_WrestleEggman;
356
king->rotation = -4;
357
king->rubyAnimator.frameID = 0;
358
king->drawGroup = eggman->drawGroup + 1;
359
king->rubyAnimator.speed = 0;
360
361
eggman->state = KleptoMobile_State_CutsceneControlled;
362
RSDK.SetSpriteAnimation(KleptoMobile->aniFrames, 11, &eggmanHand->handAnimator, true, 0);
363
eggman->position.x = camera->position.x - (ScreenInfo->size.x << 16);
364
eggman->originPos.x = camera->position.x - (ScreenInfo->size.x << 16);
365
eggman->position.y = king->originPos.y + 0x100000;
366
eggman->originPos.y = king->originPos.y + 0x100000;
367
eggman->direction = FLIP_X;
368
eggman->velocity.x = 0xD0000;
369
eggman->velocity.y = 0;
370
}
371
372
eggmanHand->state = KleptoMobile_StateHand_Boss;
373
eggmanArmL->state = KleptoMobile_StateArm_Idle;
374
eggmanArmR->state = KleptoMobile_StateArm_Idle;
375
376
eggmanHand->position.x = eggman->originPos.x;
377
eggmanHand->position.y = eggman->originPos.y;
378
eggmanHand->position.x += 0x3C0000;
379
eggmanHand->position.y -= 0x3E0000;
380
eggmanHand->drawGroup = eggmanArmL->drawGroup + 1;
381
382
eggmanArmL->position.x = eggman->originPos.x;
383
eggmanArmL->position.x -= 0x40000;
384
eggmanArmL->position.y = eggman->originPos.y;
385
eggmanArmL->position.y -= 0x360000;
386
eggmanArmL->armBezierPos.x = eggman->originPos.x - 0x600000;
387
eggmanArmL->armBezierPos.y = eggman->originPos.y - 0x280000;
388
eggmanArmL->finger1Animator.speed = 0;
389
eggmanArmL->finger2Animator.frameID = 0;
390
eggmanArmL->finger2Animator.speed = 0;
391
eggmanArmL->finger1Animator.frameID = 0;
392
393
eggmanArmR->position.x = eggman->originPos.x;
394
eggmanArmR->position.x += 0x2E0000;
395
eggmanArmR->position.y = eggman->originPos.y;
396
eggmanArmR->position.y += 0x400000;
397
eggmanArmR->armBezierPos.x = eggman->originPos.x - 0x3A0000;
398
eggmanArmR->armBezierPos.y = eggman->originPos.y + 0x300000;
399
eggmanArmR->finger1Animator.speed = 0;
400
eggmanArmR->finger2Animator.frameID = 0;
401
eggmanArmR->finger2Animator.speed = 0;
402
eggmanArmR->finger1Animator.frameID = 0;
403
404
camera->position.x = MAX(eggman->originPos.x + 0x200000, host->storedTimer);
405
406
kingArmL->state = PhantomKing_StateArm_WrestleEggman;
407
kingArmR->state = PhantomKing_StateArm_WrestleEggman;
408
409
kingArmL->position.x = king->originPos.x - 0x700000;
410
kingArmL->position.y = king->originPos.y - 0x1C0000;
411
kingArmL->armBezierPos.x = king->originPos.x + 0x100000;
412
kingArmL->armBezierPos.y = king->originPos.y - 0x2A0000;
413
kingArmL->handAnimator.frameID = 1;
414
kingArmL->drawGroup = eggmanArmL->drawGroup + 1;
415
kingArmL->handAnimator.speed = 0;
416
417
kingArmR->position.x = king->originPos.x - 0x3E0000;
418
kingArmR->position.y = king->originPos.y + 0x520000;
419
kingArmR->armBezierPos.x = king->originPos.x + 0x380000;
420
kingArmR->armBezierPos.y = king->originPos.y + 0x380000;
421
kingArmR->handAnimator.frameID = 1;
422
kingArmR->drawGroup = eggmanArmR->drawGroup + 1;
423
kingArmR->handAnimator.speed = 0;
424
425
if (eggman->position.x >= king->originPos.x - 0x580000) {
426
eggman->position.x = king->originPos.x - 0x580000;
427
eggman->velocity.x = 0;
428
eggman->velocity.y = 0;
429
430
Camera_ShakeScreen(0, 5, 0);
431
RSDK.PlaySfx(ERZStart->sfxHullClose, false, 255);
432
return true;
433
}
434
435
return false;
436
}
437
438
bool32 ERZStart_Cutscene_EggmanKingWrestling(EntityCutsceneSeq *host)
439
{
440
MANIA_GET_PLAYER(player1, player2, camera);
441
UNUSED(player2);
442
UNUSED(camera);
443
444
EntityPhantomRuby *ruby = ERZStart->ruby;
445
EntityFXRuby *fxRuby = ERZStart->fxRuby;
446
447
EntityKleptoMobile *eggman = ERZStart->eggman;
448
EntityPhantomKing *king = ERZStart->king;
449
450
uint16 eggmanSlot = RSDK.GetEntitySlot(eggman);
451
EntityKleptoMobile *eggmanHand1 = RSDK_GET_ENTITY(eggmanSlot - 1, KleptoMobile);
452
EntityKleptoMobile *eggmanHand2 = RSDK_GET_ENTITY(eggmanSlot + 1, KleptoMobile);
453
454
uint16 kingSlot = RSDK.GetEntitySlot(king);
455
EntityPhantomKing *kingChild1 = RSDK_GET_ENTITY(kingSlot - 1, PhantomKing);
456
EntityPhantomKing *kingChild2 = RSDK_GET_ENTITY(kingSlot + 1, PhantomKing);
457
458
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
459
460
if (host->timer > 6 && !(host->timer % 6))
461
Camera_ShakeScreen(0, 1, 0);
462
463
if (!(host->timer % 37))
464
RSDK.PlaySfx(ERZStart->sfxRumble, false, 255);
465
466
if (host->timer == 120) {
467
RSDK.SetSpriteAnimation(PhantomKing->aniFrames, 8, &king->rubyAnimator, true, 1);
468
king->rubyAnimator.speed = 1;
469
}
470
471
if (host->timer == 172) {
472
PhantomRuby_PlaySfx(RUBYSFX_ATTACK4);
473
fxRuby->position.x = king->position.x;
474
fxRuby->position.y = king->position.y;
475
fxRuby->fadeWhite = 0x300;
476
477
RSDK.StopSfx(ERZStart->sfxRumble);
478
return true;
479
}
480
else {
481
eggmanHand1->position.x -= RSDK.Sin256(16 * host->timer) << 8;
482
kingChild1->position.x -= RSDK.Sin256(16 * host->timer) << 8;
483
eggmanHand2->position.x += RSDK.Sin256(16 * host->timer) << 8;
484
kingChild2->position.x += RSDK.Sin256(16 * host->timer) << 8;
485
}
486
487
return false;
488
}
489
490
bool32 ERZStart_Cutscene_PostWrestleFadeIn(EntityCutsceneSeq *host)
491
{
492
MANIA_GET_PLAYER(player1, player2, camera);
493
UNUSED(player2);
494
UNUSED(camera);
495
496
EntityPhantomRuby *ruby = ERZStart->ruby;
497
EntityFXRuby *fxRuby = ERZStart->fxRuby;
498
499
EntityKleptoMobile *eggman = ERZStart->eggman;
500
EntityPhantomKing *king = ERZStart->king;
501
502
uint16 eggmanSlot = RSDK.GetEntitySlot(eggman);
503
EntityKleptoMobile *eggmanHand = RSDK_GET_ENTITY(eggmanSlot - 2, KleptoMobile);
504
EntityKleptoMobile *eggmanArmL = RSDK_GET_ENTITY(eggmanSlot - 1, KleptoMobile);
505
EntityKleptoMobile *eggmanArmR = RSDK_GET_ENTITY(eggmanSlot + 1, KleptoMobile);
506
507
uint16 kingSlot = RSDK.GetEntitySlot(king);
508
EntityPhantomKing *kingArmL = RSDK_GET_ENTITY(kingSlot - 1, PhantomKing);
509
EntityPhantomKing *kingArmR = RSDK_GET_ENTITY(kingSlot + 1, PhantomKing);
510
511
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
512
513
if (!king->rubyAnimator.frameID)
514
king->rubyAnimator.speed = 0;
515
516
if (!host->timer) {
517
eggman->position.x = 0x31C0000;
518
eggman->position.y = -0x3C0000;
519
eggman->state = StateMachine_None;
520
eggmanHand->state = KleptoMobile_StateHand_Cutscene;
521
eggmanArmL->state = KleptoMobile_StateArm_Cutscene;
522
eggmanArmR->state = KleptoMobile_StateArm_Cutscene;
523
524
eggmanHand->drawGroup = Zone->objectDrawGroup[0];
525
RSDK.SetSpriteAnimation(KleptoMobile->aniFrames, 12, &eggmanHand->handAnimator, true, 5);
526
527
kingArmL->state = PhantomKing_StateArm_Idle;
528
kingArmR->state = PhantomKing_StateArm_Idle;
529
king->drawGroup = Zone->objectDrawGroup[0];
530
kingArmL->drawGroup = Zone->objectDrawGroup[0];
531
kingArmR->drawGroup = Zone->objectDrawGroup[0];
532
}
533
534
if (fxRuby->fadeWhite > 0)
535
fxRuby->fadeWhite -= 8;
536
537
return fxRuby->fadeWhite == 0;
538
}
539
540
bool32 ERZStart_Cutscene_ReturnCamToSonic(EntityCutsceneSeq *host)
541
{
542
MANIA_GET_PLAYER(player1, player2, camera);
543
UNUSED(player2);
544
545
EntityPhantomRuby *ruby = ERZStart->ruby;
546
547
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
548
549
if (host->timer == 30)
550
Camera_SetupLerp(CAMERA_LERP_NORMAL, 0, ScreenInfo->center.x << 16, camera->position.y, 2);
551
552
if (!host->values[0]) {
553
if (camera->position.x == ScreenInfo->center.x << 16) {
554
host->values[0] = 1;
555
host->storedTimer = host->timer;
556
}
557
}
558
else if (host->timer - host->storedTimer == 60) {
559
Music_TransitionTrack(TRACK_ERZBOSS, 0.0215);
560
return true;
561
}
562
563
return false;
564
}
565
566
bool32 ERZStart_Cutscene_PreparePlayerTransform(EntityCutsceneSeq *host)
567
{
568
MANIA_GET_PLAYER(player1, player2, camera);
569
UNUSED(player2);
570
UNUSED(camera);
571
572
EntityPhantomRuby *ruby = ERZStart->ruby;
573
574
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
575
576
if (++ERZStart->timer >= 60) {
577
ERZStart->timer = 0;
578
579
for (int32 i = 0; i < 7; ++i) {
580
EntityChaosEmerald *emerald = ERZStart->emeralds[i];
581
emerald->drawFX |= FX_SCALE;
582
emerald->scale.x = 0x200;
583
emerald->scale.y = 0x200;
584
}
585
586
return true;
587
}
588
589
return false;
590
}
591
592
bool32 ERZStart_Cutscene_PlayerTransform(EntityCutsceneSeq *host)
593
{
594
MANIA_GET_PLAYER(player1, player2, camera);
595
UNUSED(player2);
596
UNUSED(camera);
597
598
EntityPhantomRuby *ruby = ERZStart->ruby;
599
600
if (++ERZStart->timer > 96) {
601
ERZStart->timer = 0;
602
return true;
603
}
604
else {
605
for (int32 i = 0; i < 7; ++i) {
606
EntityChaosEmerald *emerald = ERZStart->emeralds[i];
607
emerald->drawGroup = Zone->objectDrawGroup[0];
608
emerald->radius -= 0x60;
609
610
if (emerald->radius <= 0)
611
emerald->visible = false;
612
613
emerald->groundVel += 32;
614
emerald->scale.x -= 3;
615
emerald->scale.y -= 3;
616
}
617
618
if (ERZStart->timer >= 32) {
619
if (ERZStart->timer == 32) {
620
Player_GiveRings(player1, 50, false);
621
Player_TryTransform(player1, 0x7F);
622
}
623
}
624
else {
625
ERZStart_HandlePlayerHover(player1, host, ruby->startPos.y);
626
}
627
}
628
629
return false;
630
}
631
632
bool32 ERZStart_Cutscene_StartFight(EntityCutsceneSeq *host)
633
{
634
RSDK_THIS(ERZStart);
635
MANIA_GET_PLAYER(player1, player2, camera);
636
UNUSED(player2);
637
638
EntityPhantomKing *king = ERZStart->king;
639
640
if (player1->animator.animationID != ANI_TRANSFORM) {
641
Zone->playerBoundActiveR[0] = true;
642
Zone->playerBoundActiveT[0] = true;
643
Zone->cameraBoundsR[0] = 0x610;
644
Zone->cameraBoundsT[0] = 0;
645
646
player1->state = ERZStart_State_PlayerSuperFly;
647
player1->abilityValues[0] = 60;
648
player1->velocity.x = 0x160000;
649
player1->onGround = false;
650
player1->stateAbility = ERZStart_Player_StartSuperFly;
651
RSDK.PlaySfx(Player->sfxPeelRelease, false, 255);
652
653
EntityFXFade *fxFade = CREATE_ENTITY(FXFade, INT_TO_VOID(0xF0F0F0), self->position.x, self->position.y);
654
fxFade->speedIn = 256;
655
fxFade->speedOut = 64;
656
player1->stateInput = Player_Input_P1;
657
658
if (player1->characterID == ID_KNUCKLES) {
659
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_GLIDE, &player1->animator, false, 6);
660
player1->animator.rotationStyle = ROTSTYLE_FULL;
661
}
662
else {
663
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_RUN, &player1->animator, false, 0);
664
}
665
666
Zone->playerBoundActiveL[0] = true;
667
Zone->playerBoundActiveR[0] = true;
668
Zone->playerBoundActiveT[0] = true;
669
670
PhantomKing_SetupKing(king);
671
672
Camera_SetTargetEntity(0, player1);
673
camera->target = (Entity *)player1;
674
camera->offset.x = 0;
675
camera->offset.y = 0;
676
camera->state = Camera_State_FollowXY;
677
player1->camera = camera;
678
679
foreach_all(RingField, field) { field->running = true; }
680
681
SceneInfo->timeEnabled = true;
682
return true;
683
}
684
685
return false;
686
}
687
688
bool32 ERZStart_Cutscene_Fight(EntityCutsceneSeq *host)
689
{
690
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
691
EntityKleptoMobile *eggman = ERZStart->eggman;
692
EntityPhantomKing *king = ERZStart->king;
693
694
if (player1->superState == SUPERSTATE_SUPER) {
695
if (!king->health && !eggman->health)
696
return true;
697
}
698
else if (player1->deathType != PLAYER_DEATH_DIE_USESFX) {
699
player1->deathType = PLAYER_DEATH_DIE_USESFX;
700
}
701
702
return false;
703
}
704
705
void ERZStart_RubyHover(void)
706
{
707
EntityPhantomRuby *ruby = ERZStart->ruby;
708
EntityFXRuby *fxRuby = ERZStart->fxRuby;
709
710
ruby->angle += 2;
711
ruby->position.y = (RSDK.Sin256(ruby->angle) << 10) + ruby->startPos.y;
712
713
fxRuby->position.x = ruby->position.x;
714
fxRuby->position.y = ruby->position.y;
715
}
716
717
void ERZStart_RubyMove(void)
718
{
719
RSDK_THIS(ERZStart);
720
EntityPhantomRuby *ruby = ERZStart->ruby;
721
722
if (self->velocity.x < 0x40000)
723
self->velocity.x += 0x1800;
724
725
ruby->angle += 2;
726
ruby->position.x += ruby->velocity.x;
727
ruby->position.y = (RSDK.Sin256(ruby->angle) << 10) + ruby->startPos.y;
728
}
729
730
void ERZStart_Player_HandleSuperDash(EntityPlayer *player)
731
{
732
RSDK_THIS(Player);
733
734
uint8 dashDir = 0;
735
if (player->up)
736
dashDir |= 1;
737
738
if (player->down)
739
dashDir |= 2;
740
741
if (player->left)
742
dashDir |= 4;
743
744
if (player->right)
745
dashDir |= 8;
746
747
int32 dashAngle = 0;
748
uint8 dashAngles[] = { 0x00, 0xC0, 0x40, 0x00, 0x80, 0xA0, 0x60, 0x00, 0x00, 0xE0, 0x20 };
749
750
if (dashDir == 0 && player->direction)
751
dashAngle = 0x80;
752
else
753
dashAngle = dashAngles[dashDir];
754
755
player->rings -= 5;
756
if (player->rings < 0)
757
player->rings = 0;
758
759
player->velocity.x = 0x1600 * RSDK.Cos256(dashAngle);
760
player->velocity.y = 0x1600 * RSDK.Sin256(dashAngle);
761
762
RSDK.PlaySfx(ItemBox->sfxHyperRing, false, 0xFF);
763
RSDK.PlaySfx(Player->sfxPeelRelease, false, 0xFF);
764
765
if (player->characterID == ID_KNUCKLES) {
766
RSDK.SetSpriteAnimation(player->aniFrames, ANI_GLIDE, &player->animator, false, 6);
767
player->animator.rotationStyle = ROTSTYLE_FULL;
768
}
769
else {
770
RSDK.SetSpriteAnimation(player->aniFrames, ANI_RUN, &player->animator, false, 0);
771
}
772
773
player->state = ERZStart_State_PlayerSuperFly;
774
player->abilityValues[0] = 60;
775
776
if (FXFade) {
777
EntityFXFade *fxFade = CREATE_ENTITY(FXFade, INT_TO_VOID(0xF0F0F0), self->position.x, self->position.y);
778
fxFade->speedIn = 256;
779
fxFade->speedOut = 64;
780
}
781
782
#if MANIA_USE_PLUS
783
Player->superDashCooldown = 30;
784
#else
785
ERZStart->superDashCooldown = 30;
786
#endif
787
}
788
789
void ERZStart_State_PlayerSuperFly(void)
790
{
791
RSDK_THIS(Player);
792
793
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
794
795
if (player1->onGround) {
796
player1->state = Player_State_Ground;
797
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_IDLE, &player1->animator, false, 0);
798
}
799
else {
800
if (player1->up) {
801
if (self->velocity.y > -player1->topSpeed) {
802
self->velocity.y -= player1->acceleration;
803
804
if (player1->velocity.y > 0)
805
self->velocity.y -= player1->acceleration;
806
}
807
}
808
else if (player1->down) {
809
if (self->velocity.y < player1->topSpeed) {
810
self->velocity.y += player1->acceleration;
811
812
if (player1->velocity.y < 0)
813
self->velocity.y += player1->acceleration;
814
}
815
}
816
else {
817
if (player1->velocity.y) {
818
if (player1->velocity.y < 0) {
819
player1->velocity.y += player1->deceleration;
820
821
if (player1->velocity.y > 0)
822
player1->velocity.y = 0;
823
}
824
else {
825
player1->velocity.y -= player1->deceleration;
826
827
if (player1->velocity.y < 0)
828
player1->velocity.y = 0;
829
}
830
}
831
}
832
833
int32 velY = player1->velocity.y;
834
if (velY >= -player1->topSpeed) {
835
if (velY > player1->topSpeed)
836
player1->velocity.y = velY - (player1->acceleration >> 1) - player1->acceleration;
837
}
838
else {
839
player1->velocity.y = player1->acceleration + velY + (player1->acceleration >> 1);
840
}
841
842
if (player1->left) {
843
if (player1->characterID == ID_KNUCKLES && self->direction == FLIP_NONE)
844
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_GLIDE, &player1->animator, true, 0);
845
846
if (self->velocity.x > -player1->topSpeed) {
847
self->velocity.x -= player1->acceleration;
848
849
if (player1->velocity.x > 0)
850
self->velocity.x -= player1->acceleration;
851
}
852
853
player1->direction = FLIP_X;
854
}
855
else if (player1->right) {
856
if (player1->characterID == ID_KNUCKLES && self->direction == FLIP_X)
857
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_GLIDE, &player1->animator, true, 0);
858
859
if (self->velocity.x < player1->topSpeed) {
860
self->velocity.x += player1->acceleration;
861
862
if (player1->velocity.x < 0)
863
self->velocity.x += player1->acceleration;
864
}
865
866
player1->direction = FLIP_NONE;
867
}
868
else {
869
if (player1->velocity.x) {
870
if (player1->velocity.x < 0) {
871
player1->velocity.x += player1->deceleration;
872
873
if (player1->velocity.x > 0)
874
player1->velocity.x = 0;
875
}
876
else {
877
player1->velocity.x -= player1->deceleration;
878
879
if (player1->velocity.x < 0)
880
player1->velocity.x = 0;
881
}
882
}
883
}
884
885
int32 velX = player1->velocity.x;
886
if (velX >= -player1->topSpeed) {
887
if (velX > player1->topSpeed)
888
player1->velocity.x = velX - (player1->acceleration >> 1) - player1->acceleration;
889
}
890
else {
891
player1->velocity.x = player1->acceleration + velX + (player1->acceleration >> 1);
892
}
893
894
if (player1->abilityValues[0]) {
895
player1->abilityValues[0]--;
896
}
897
else if (player1->jumpPress) {
898
if (player1->rings > 10)
899
ERZStart_Player_HandleSuperDash(player1);
900
}
901
}
902
}
903
904
void ERZStart_Player_StartSuperFly(void)
905
{
906
RSDK_THIS(Player);
907
908
if (self->jumpAbilityState == 1 && self->jumpPress) {
909
if (self->characterID == ID_KNUCKLES) {
910
RSDK.SetSpriteAnimation(self->aniFrames, ANI_GLIDE, &self->animator, false, 6);
911
self->animator.rotationStyle = ROTSTYLE_FULL;
912
}
913
else {
914
RSDK.SetSpriteAnimation(self->aniFrames, ANI_RUN, &self->animator, false, 0);
915
}
916
917
self->state = ERZStart_State_PlayerSuperFly;
918
}
919
}
920
921
void ERZStart_State_PlayerRebound(void)
922
{
923
EntityPlayer *entity = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
924
925
if (entity->characterID == ID_KNUCKLES) {
926
RSDK.SetSpriteAnimation(entity->aniFrames, ANI_GLIDE, &entity->animator, false, 6);
927
entity->animator.rotationStyle = ROTSTYLE_FULL;
928
}
929
else {
930
RSDK.SetSpriteAnimation(entity->aniFrames, ANI_RUN, &entity->animator, false, 0);
931
}
932
933
entity->rotation += 0x20;
934
entity->onGround = false;
935
936
if (entity->rotation == 0x600) {
937
entity->rotation = 0;
938
entity->state = ERZStart_State_PlayerSuperFly;
939
}
940
}
941
942
#if GAME_INCLUDE_EDITOR
943
void ERZStart_EditorDraw(void)
944
{
945
RSDK_THIS(ERZStart);
946
947
CutsceneRules_DrawCutsceneBounds(self, &self->size);
948
}
949
950
void ERZStart_EditorLoad(void) {}
951
#endif
952
953
void ERZStart_Serialize(void) { RSDK_EDITABLE_VAR(ERZOutro, VAR_VECTOR2, size); }
954
955