Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/AIZ/AIZSetup.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: AIZSetup Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectAIZSetup *AIZSetup;
11
12
void AIZSetup_Update(void) {}
13
14
void AIZSetup_LateUpdate(void) {}
15
16
void AIZSetup_StaticUpdate(void)
17
{
18
#if MANIA_USE_PLUS
19
if (Zone->actID != 3 && !AIZSetup->hasSetupCutscene) {
20
#else
21
if (!AIZSetup->hasSetupCutscene) {
22
#endif
23
AIZSetup_SetupObjects();
24
AIZSetup_GetCutsceneSetupPtr();
25
AIZSetup->hasSetupCutscene = true;
26
}
27
28
#if MANIA_USE_PLUS
29
if (AIZSetup->background4) {
30
#endif
31
if (ScreenInfo->position.x <= 4096)
32
AIZSetup->background2->scrollPos = 0;
33
else
34
AIZSetup->background2->scrollPos = 0x1000000;
35
36
if (ScreenInfo->position.x <= 8704) {
37
AIZSetup->background2->drawGroup[0] = 0;
38
AIZSetup->background3->drawGroup[0] = DRAWGROUP_COUNT;
39
}
40
else {
41
AIZSetup->background2->drawGroup[0] = DRAWGROUP_COUNT;
42
AIZSetup->background3->drawGroup[0] = 0;
43
}
44
#if MANIA_USE_PLUS
45
}
46
else {
47
if (!(Zone->timer & 3)) {
48
++RSDK.GetTileLayer(0)->deformationOffsetW;
49
}
50
51
if (!(Zone->timer & 1)) {
52
for (int32 i = Zone->fgLayer[0]; i <= Zone->fgLayer[1]; ++i) {
53
RSDK.GetTileLayer(i)->deformationOffsetW++;
54
}
55
}
56
}
57
#endif
58
59
if (!(Zone->timer % 5)) {
60
RSDK.RotatePalette(0, 171, 174, true);
61
#if MANIA_USE_PLUS
62
RSDK.RotatePalette(1, 171, 174, true);
63
CutsceneHBH->paletteColors[43] = RSDK.GetPaletteEntry(0, 171);
64
CutsceneHBH->paletteColors[44] = RSDK.GetPaletteEntry(0, 172);
65
CutsceneHBH->paletteColors[45] = RSDK.GetPaletteEntry(0, 173);
66
CutsceneHBH->paletteColors[46] = RSDK.GetPaletteEntry(0, 174);
67
#endif
68
}
69
70
if (!AIZSetup->playDrillSfx || RSDK_GET_ENTITY(SLOT_PAUSEMENU, PauseMenu)->classID == PauseMenu->classID) {
71
if (AIZSetup->playingDrillSfx) {
72
RSDK.StopSfx(AIZSetup->sfxDrill);
73
AIZSetup->playingDrillSfx = false;
74
}
75
}
76
else if (!AIZSetup->playingDrillSfx) {
77
RSDK.PlaySfx(AIZSetup->sfxDrill, 1, 255);
78
AIZSetup->playingDrillSfx = true;
79
}
80
81
#if MANIA_USE_PLUS
82
--AIZSetup->bellPlantAniTimer;
83
if (AIZSetup->bellPlantAniTimer < 0) {
84
++AIZSetup->bellPlantAniFrame;
85
if (AIZSetup->bellPlantAniFramePos[AIZSetup->bellPlantAniFrame] == -1)
86
AIZSetup->bellPlantAniFrame = 0;
87
88
AIZSetup->bellPlantAniTimer = AIZSetup->bellPlantAniDurations[AIZSetup->bellPlantAniFrame];
89
RSDK.DrawAniTiles(AIZSetup->aniTiles, 196, 16 * AIZSetup->bellPlantAniFramePos[AIZSetup->bellPlantAniFrame], 0, 16, 32);
90
}
91
92
--AIZSetup->curlPlant1AniTimer;
93
if (AIZSetup->curlPlant1AniTimer < 0) {
94
++AIZSetup->curlPlant1AniFrame;
95
if (AIZSetup->curlPlant1AniFramePos[AIZSetup->curlPlant1AniFrame] == -1)
96
AIZSetup->curlPlant1AniFrame = 0;
97
98
AIZSetup->curlPlant1AniTimer = AIZSetup->curlPlant1AniDurations[AIZSetup->curlPlant1AniFrame];
99
RSDK.DrawAniTiles(AIZSetup->aniTiles, 198, 16 * AIZSetup->curlPlant1AniFramePos[AIZSetup->curlPlant1AniFrame], 32, 16, 48);
100
}
101
102
--AIZSetup->curlPlant2AniTimer;
103
if (AIZSetup->curlPlant2AniTimer < 0) {
104
++AIZSetup->curlPlant2AniFrame;
105
if (AIZSetup->curlPlant2AniFramePos[AIZSetup->curlPlant2AniFrame] == -1)
106
AIZSetup->curlPlant2AniFrame = 0;
107
108
AIZSetup->curlPlant2AniTimer = AIZSetup->curlPlant2AniDurations[AIZSetup->curlPlant2AniFrame];
109
RSDK.DrawAniTiles(AIZSetup->aniTiles, 201, 16 * AIZSetup->curlPlant2AniFramePos[AIZSetup->curlPlant2AniFrame], 32, 16, 48);
110
}
111
#endif
112
}
113
114
void AIZSetup_Draw(void) {}
115
116
void AIZSetup_Create(void *data) {}
117
118
void AIZSetup_StageLoad(void)
119
{
120
#if MANIA_USE_PLUS
121
if (Zone->actID != 3)
122
#endif
123
Zone->cameraBoundsB[0] = SCREEN_YSIZE;
124
125
AIZSetup->hasSetupCutscene = false;
126
127
AIZSetup->aniTiles = RSDK.LoadSpriteSheet("AIZ/AniTiles.gif", SCOPE_STAGE);
128
AIZSetup->knuxFrames = RSDK.LoadSpriteAnimation("Players/KnuxCutsceneAIZ.bin", SCOPE_STAGE);
129
130
#if MANIA_USE_PLUS
131
if (RSDK.GetTileLayerID("Background 4") >= DRAWGROUP_COUNT) {
132
// Bug Details:
133
// AIZ->background4 doesn't get cleared here, so coming from AIZ Intro to AIZ Encore (same folder so object structs aren't reset)
134
// leaves background4's tileLayer pointer intact, though pointing to the wrong layers
135
// it also enables the behaviour in StaticUpdate that should only play in AIZ Intro
136
// Fix:
137
// AIZSetup->background4 = NULL;
138
// (though you should prolly clear the other 3 as well)
139
140
for (int32 i = Zone->fgLayer[0]; i <= Zone->fgLayer[1]; ++i) {
141
int32 *deformData = RSDK.GetTileLayer(i)->deformationDataW;
142
143
int32 angle = 0;
144
for (int32 d = 0; d < 0x200; ++d) {
145
deformData[d] = (2 * RSDK.Sin1024(angle)) >> 10;
146
angle += 16;
147
}
148
149
memcpy(&deformData[0x200], &deformData[0], (0x200 * sizeof(int32)));
150
}
151
152
int32 *deformData = RSDK.GetTileLayer(0)->deformationDataW;
153
for (int32 d = 0; d < 0x200; d += 16) {
154
int32 id = MAX(d, 0);
155
156
int32 angle = 0;
157
int32 deform = RSDK.Rand(0, 4);
158
for (int32 i = 0; i < 16; ++i) {
159
deformData[id + i] = (deform * RSDK.Sin1024(angle)) >> 10;
160
angle += 64;
161
}
162
}
163
memcpy(&deformData[0x200], &deformData[0], (0x200 * sizeof(int32)));
164
}
165
else {
166
#endif
167
AIZSetup->background1 = RSDK.GetTileLayer(RSDK.GetTileLayerID("Background 1"));
168
AIZSetup->background2 = RSDK.GetTileLayer(RSDK.GetTileLayerID("Background 2"));
169
AIZSetup->background3 = RSDK.GetTileLayer(RSDK.GetTileLayerID("Background 3"));
170
AIZSetup->background4 = RSDK.GetTileLayer(RSDK.GetTileLayerID("Background 4"));
171
172
for (int32 i = 0; i < AIZSetup->background2->scrollInfoCount; ++i) {
173
int32 parallaxFactor = AIZSetup->background2->scrollInfo[i].parallaxFactor;
174
AIZSetup->background2->scrollInfo[i].scrollPos = -TO_FIXED(0x700) - (TO_FIXED(34) * parallaxFactor);
175
}
176
177
for (int32 i = 0; i < AIZSetup->background3->scrollInfoCount; ++i) {
178
int32 parallaxFactor = AIZSetup->background3->scrollInfo[i].parallaxFactor;
179
AIZSetup->background3->scrollInfo[i].scrollPos = -TO_FIXED(0x700) - (TO_FIXED(34) * parallaxFactor);
180
}
181
#if MANIA_USE_PLUS
182
}
183
#endif
184
185
Animals->animalTypes[0] = ANIMAL_FLICKY;
186
Animals->animalTypes[1] = ANIMAL_RICKY;
187
188
Music_SetMusicTrack("RubyPresence.ogg", TRACK_RUBYPRESENCE, 198457);
189
190
AIZSetup->sfxDrill = RSDK.GetSfx("LRZ/Drill.wav");
191
AIZSetup->sfxBreak = RSDK.GetSfx("Stage/LedgeBreak3.wav");
192
AIZSetup->sfxImpact = RSDK.GetSfx("Stage/Impact4.wav");
193
AIZSetup->sfxHeliWoosh = RSDK.GetSfx("SPZ1/HeliWooshIn.wav");
194
195
if (CHECK_CHARACTER_ID(ID_KNUCKLES, 1)) {
196
foreach_all(AIZTornado, tornado) { destroyEntity(tornado); }
197
foreach_all(AIZTornadoPath, node) { destroyEntity(node); }
198
}
199
200
#if MANIA_USE_PLUS
201
BGSwitch->switchCallback[AIZ_BG_JUNGLE] = AIZSetup_BGSwitch_Jungle;
202
BGSwitch->switchCallback[AIZ_BG_SKY] = AIZSetup_BGSwitch_Sky;
203
204
BGSwitch->layerIDs[0] = AIZ_BG_JUNGLE;
205
BGSwitch->layerIDs[1] = AIZ_BG_JUNGLE;
206
BGSwitch->layerIDs[2] = AIZ_BG_JUNGLE;
207
BGSwitch->layerIDs[3] = AIZ_BG_JUNGLE;
208
209
RSDK.SetDrawGroupProperties(0, false, Water_DrawHook_ApplyWaterPalette);
210
RSDK.SetDrawGroupProperties(Zone->hudDrawGroup, false, Water_DrawHook_RemoveWaterPalette);
211
Water->waterPalette = 1;
212
#endif
213
}
214
215
#if MANIA_USE_PLUS
216
void AIZSetup_BGSwitch_Jungle(void)
217
{
218
RSDK.GetTileLayer(0)->drawGroup[BGSwitch->screenID] = 0;
219
RSDK.GetTileLayer(1)->drawGroup[BGSwitch->screenID] = DRAWGROUP_COUNT;
220
}
221
222
void AIZSetup_BGSwitch_Sky(void)
223
{
224
RSDK.GetTileLayer(0)->drawGroup[BGSwitch->screenID] = DRAWGROUP_COUNT;
225
RSDK.GetTileLayer(1)->drawGroup[BGSwitch->screenID] = 0;
226
}
227
#endif
228
229
void AIZSetup_PlayerState_Static(void)
230
{
231
RSDK_THIS(Player);
232
self->active = ACTIVE_NORMAL;
233
self->visible = false;
234
self->position.x = 0;
235
self->position.y = 0;
236
self->stateInput = StateMachine_None;
237
}
238
239
void AIZSetup_PlayerState_P2Enter(void)
240
{
241
RSDK_THIS(Player);
242
self->active = ACTIVE_NORMAL;
243
self->visible = true;
244
self->stateInput = Player_Input_P2_AI;
245
Player->respawnTimer = 240;
246
Player_HandleSidekickRespawn();
247
}
248
249
void AIZSetup_HandleHeavyMovement(void)
250
{
251
EntityAIZKingClaw *claw = AIZSetup->claw;
252
253
int32 x = -0x10000;
254
foreach_all(AIZEggRobo, robo)
255
{
256
if (robo->forKnux && x >= robo->position.x)
257
x = robo->position.x;
258
}
259
260
if (x < (ScreenInfo->position.x + ScreenInfo->size.x + 32) << 16) {
261
foreach_all(AIZEggRobo, eggRobo)
262
{
263
if (eggRobo->forKnux)
264
eggRobo->position.x += 0x40000;
265
}
266
claw->position.x += 0x40000;
267
claw->position.y -= 0x4000;
268
}
269
}
270
271
void AIZSetup_SetupObjects(void)
272
{
273
foreach_all(AIZTornado, tornado)
274
{
275
AIZSetup->tornado = tornado;
276
foreach_break;
277
}
278
279
foreach_all(Platform, platform)
280
{
281
if (!platform->frameID) {
282
platform->drawGroup = Zone->objectDrawGroup[1] - 1;
283
AIZSetup->platform = platform;
284
foreach_break;
285
}
286
}
287
288
foreach_all(AIZKingClaw, claw)
289
{
290
AIZSetup->claw = claw;
291
foreach_break;
292
}
293
294
foreach_all(PhantomRuby, ruby)
295
{
296
AIZSetup->phantomRuby = ruby;
297
foreach_break;
298
}
299
300
int32 id = 0;
301
foreach_all(Decoration, decoration) { AIZSetup->decorations[id++] = decoration; }
302
}
303
304
void AIZSetup_GetCutsceneSetupPtr(void)
305
{
306
switch (GET_CHARACTER_ID(1)) {
307
default:
308
case ID_SONIC:
309
case ID_TAILS:
310
#if MANIA_USE_PLUS
311
case ID_MIGHTY:
312
case ID_RAY:
313
#endif
314
AIZSetup_CutsceneST_Setup();
315
break;
316
317
case ID_KNUCKLES: AIZSetup_CutsceneK_Setup(); break;
318
}
319
}
320
321
#if MANIA_USE_PLUS
322
void AIZSetup_Cutscene_SkipCB(void)
323
{
324
#if MANIA_USE_PLUS
325
if (globals->gameMode == MODE_ENCORE)
326
RSDK.SetScene("Encore Mode", "Green Hill Zone+ 1");
327
else
328
#endif
329
RSDK.SetScene("Mania Mode", "Green Hill Zone 1");
330
}
331
#endif
332
333
void AIZSetup_CutsceneST_Setup(void)
334
{
335
RSDK_THIS(AIZSetup);
336
CutsceneSeq_StartSequence(self, AIZSetup_CutsceneSonic_EnterAIZ, AIZSetup_CutsceneSonic_EnterAIZJungle, AIZSetup_CutsceneSonic_EnterHeavies,
337
AIZSetup_CutsceneSonic_P2FlyIn, AIZSetup_CutsceneSonic_EnterClaw, AIZSetup_CutsceneSonic_WatchClaw,
338
AIZSetup_CutsceneSonic_RubyGrabbed, AIZSetup_CutsceneSonic_RubyAppear, AIZSetup_CutsceneSonic_RubyFX,
339
AIZSetup_Cutscene_LoadGHZ, StateMachine_None);
340
341
#if MANIA_USE_PLUS
342
CutsceneSeq_SetSkipTypeCallback(AIZSetup_Cutscene_SkipCB);
343
#endif
344
}
345
346
bool32 AIZSetup_CutsceneSonic_EnterAIZ(EntityCutsceneSeq *host)
347
{
348
MANIA_GET_PLAYER(player1, player2, camera);
349
EntityAIZTornado *tornado = AIZSetup->tornado;
350
351
if (!host->timer) {
352
CutsceneSeq_LockAllPlayerControl();
353
player1->stateInput = StateMachine_None;
354
}
355
Zone->playerBoundActiveL[0] = false;
356
357
if (player2->classID == Player->classID)
358
player2->state = AIZSetup_PlayerState_Static;
359
360
if (tornado->position.x < ScreenInfo->size.x << 16)
361
camera->position.x = ScreenInfo->size.x << 16;
362
363
return tornado->disableInteractions;
364
}
365
bool32 AIZSetup_CutsceneSonic_EnterAIZJungle(EntityCutsceneSeq *host)
366
{
367
MANIA_GET_PLAYER(player1, player2, camera);
368
UNUSED(player2);
369
UNUSED(camera);
370
371
if (player1->position.x >= 0x27100000) {
372
Music_TransitionTrack(TRACK_HBHMISCHIEF, 0.01);
373
player1->right = false;
374
player1->left = true;
375
host->storedValue = player1->groundVel;
376
return true;
377
}
378
else {
379
player1->right = true;
380
}
381
return false;
382
}
383
bool32 AIZSetup_CutsceneSonic_EnterHeavies(EntityCutsceneSeq *host)
384
{
385
MANIA_GET_PLAYER(player1, player2, camera);
386
UNUSED(camera);
387
388
if (player1->position.x >= 0x2A300000) {
389
if (player1->groundVel <= 0) {
390
if (!host->storedTimer) {
391
player1->right = false;
392
player1->left = false;
393
host->storedTimer = host->timer;
394
}
395
}
396
else {
397
if (player2->classID == Player->classID) {
398
player2->stateInput = StateMachine_None;
399
}
400
Player->targetLeaderPosition.x = player1->position.x - 0x200000;
401
Player->targetLeaderPosition.y = player1->position.y;
402
player1->state = Player_State_Ground;
403
player1->right = false;
404
player1->left = true;
405
}
406
}
407
else {
408
player1->state = Player_State_Static;
409
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_SKID, &player1->animator, false, 0);
410
player1->groundVel = host->storedValue;
411
player1->velocity.x = host->storedValue;
412
player1->right = false;
413
player1->left = false;
414
if (player2 && player2->state == AIZSetup_PlayerState_Static)
415
player2->state = AIZSetup_PlayerState_P2Enter;
416
}
417
418
if (host->storedTimer > 0 && host->timer > host->storedTimer + 15) {
419
player1->direction = FLIP_NONE;
420
return true;
421
}
422
423
return false;
424
}
425
bool32 AIZSetup_CutsceneSonic_P2FlyIn(EntityCutsceneSeq *host)
426
{
427
MANIA_GET_PLAYER(player1, player2, camera);
428
UNUSED(camera);
429
430
if (player2->classID == Player->classID) {
431
if (player2->onGround) {
432
player2->stateInput = StateMachine_None;
433
player2->direction = FLIP_NONE;
434
RSDK.SetSpriteAnimation(player2->aniFrames, 0, &player2->animator, true, 0);
435
player2->state = Player_State_Static;
436
return true;
437
}
438
else {
439
Player->targetLeaderPosition.x = player1->position.x - 0x200000;
440
Player->targetLeaderPosition.y = player1->position.y + 0x80000;
441
player2->position.x = Player->targetLeaderPosition.x;
442
player2->direction = FLIP_NONE;
443
}
444
}
445
else {
446
return host->timer > 10;
447
}
448
449
return false;
450
}
451
bool32 AIZSetup_CutsceneSonic_EnterClaw(EntityCutsceneSeq *host)
452
{
453
MANIA_GET_PLAYER(player1, player2, camera);
454
455
if (!host->timer) {
456
player1->camera = NULL;
457
Camera_SetupLerp(CAMERA_LERP_NORMAL, 0, AIZSetup->platform->position.x - 0x400000, camera->position.y, 3);
458
player1->stateInput = StateMachine_None;
459
player1->state = Player_State_Ground;
460
player1->up = true;
461
}
462
else {
463
if (camera->position.x >= camera->endLerpPos.x) {
464
if (host->storedTimer) {
465
if (host->timer >= host->storedTimer + 60)
466
return true;
467
}
468
else {
469
host->storedTimer = host->timer;
470
}
471
}
472
else {
473
player1->up = true;
474
if (player2->classID == Player->classID) {
475
player2->state = Player_State_Static;
476
}
477
}
478
}
479
return false;
480
}
481
bool32 AIZSetup_CutsceneSonic_WatchClaw(EntityCutsceneSeq *host)
482
{
483
EntityAIZKingClaw *claw = AIZSetup->claw;
484
485
if (claw->position.y < -0x1C0000) {
486
claw->position.y += 0x10000;
487
}
488
else {
489
if (host->storedTimer) {
490
if (host->timer >= host->storedTimer + 60)
491
return true;
492
}
493
else {
494
host->storedTimer = host->timer;
495
claw->state = AIZKingClaw_State_Grab;
496
}
497
}
498
499
return false;
500
}
501
bool32 AIZSetup_CutsceneSonic_RubyGrabbed(EntityCutsceneSeq *host)
502
{
503
MANIA_GET_PLAYER(player1, player2, camera);
504
UNUSED(player1);
505
UNUSED(camera);
506
507
EntityAIZKingClaw *claw = AIZSetup->claw;
508
EntityPlatform *platform = AIZSetup->platform;
509
EntityPhantomRuby *ruby = AIZSetup->phantomRuby;
510
511
if (!host->timer) {
512
claw->grabbedEntities[0] = (Entity *)platform;
513
claw->grabbedEntities[1] = (Entity *)ruby;
514
claw->grabCount = 2;
515
}
516
517
if (claw->position.y > -0x520000) {
518
AIZSetup->playDrillSfx = true;
519
520
if (!(host->timer % 5))
521
Camera_ShakeScreen(0, 0, 2);
522
523
claw->position.y -= 0x4000;
524
525
for (int32 i = 0; i < 3; ++i) {
526
EntityDecoration *decor = AIZSetup->decorations[i];
527
decor->drawFX |= FX_ROTATE;
528
decor->rotation = ((2 * (!(i & 1)) - 1) * RSDK.Sin256(16 * host->timer)) >> 7;
529
}
530
}
531
else {
532
if (host->storedTimer) {
533
if (host->values[0]) {
534
if (!host->values[1] && host->timer >= host->storedTimer && host->timer == host->storedTimer) {
535
return true;
536
}
537
}
538
else if (host->timer < host->storedTimer + 30) {
539
Vector2 result = MathHelpers_GetBezierPoint(((host->timer - host->storedTimer) << 16) / 30, claw->position.x, host->storedValue,
540
claw->position.x, host->storedValue - 0x500000, claw->position.x,
541
host->storedValue - 0x300000, claw->position.x, host->storedValue - 0x300000);
542
claw->position.y = result.y;
543
}
544
else if (host->timer != host->storedTimer + 30) {
545
if (!host->values[1] && host->timer >= host->storedTimer && host->timer == host->storedTimer) {
546
return true;
547
}
548
}
549
else {
550
host->values[0] = 1;
551
host->storedTimer = host->timer + 60;
552
}
553
}
554
else {
555
AIZSetup->playDrillSfx = false;
556
557
host->storedTimer = host->timer;
558
host->storedValue = claw->position.y;
559
560
AIZSetup->decorations[0]->rotSpeed = 0;
561
AIZSetup->decorations[1]->rotSpeed = 0;
562
563
if (CHECK_CHARACTER_ID(ID_TAILS, 2))
564
RSDK.SetSpriteAnimation(player2->aniFrames, ANI_SKID, &player2->animator, true, 0);
565
566
RSDK.PlaySfx(AIZSetup->sfxBreak, false, 0x00);
567
568
Music_TransitionTrack(TRACK_EGGMAN1, 0.05);
569
}
570
}
571
572
return false;
573
}
574
bool32 AIZSetup_CutsceneSonic_RubyAppear(EntityCutsceneSeq *host)
575
{
576
EntityPhantomRuby *ruby = AIZSetup->phantomRuby;
577
578
if (!host->timer)
579
PhantomRuby_SetupFlash(ruby);
580
581
return ruby->flashFinished;
582
}
583
bool32 AIZSetup_CutsceneSonic_RubyFX(EntityCutsceneSeq *host)
584
{
585
MANIA_GET_PLAYER(player1, player2, camera);
586
UNUSED(camera);
587
588
EntityPhantomRuby *ruby = AIZSetup->phantomRuby;
589
590
EntityFXRuby *fxRuby = NULL;
591
if (host->timer) {
592
fxRuby = AIZSetup->fxRuby;
593
}
594
else {
595
fxRuby = CREATE_ENTITY(FXRuby, NULL, ruby->position.x, ruby->position.y);
596
fxRuby->drawGroup = Zone->playerDrawGroup[1];
597
AIZSetup->fxRuby = fxRuby;
598
Camera_ShakeScreen(0, 4, 4);
599
player1->drawGroup = Zone->playerDrawGroup[1] + 1;
600
if (player2->classID == Player->classID)
601
player2->drawGroup = Zone->playerDrawGroup[1] + 1;
602
}
603
604
if (!host->values[0]) {
605
if (fxRuby->fullyExpanded) {
606
if (host->storedTimer) {
607
if (host->timer == host->storedTimer + 30) {
608
fxRuby->delay = 64;
609
fxRuby->state = FXRuby_State_IncreaseStageDeform;
610
PhantomRuby_PlaySfx(RUBYSFX_ATTACK4);
611
Camera_ShakeScreen(0, 4, 4);
612
}
613
else if (host->timer == host->storedTimer + 210) {
614
fxRuby->delay = 32;
615
fxRuby->state = FXRuby_State_IncreaseStageDeform;
616
PhantomRuby_PlaySfx(RUBYSFX_ATTACK1);
617
Camera_ShakeScreen(0, 4, 4);
618
Music_FadeOut(0.025);
619
host->storedTimer = host->timer;
620
host->values[0] = true;
621
}
622
}
623
else {
624
host->storedTimer = host->timer;
625
}
626
627
if (host->timer >= host->storedTimer + 32) {
628
int32 id = 0;
629
for (int32 angle = 0; angle < 0x80; angle += 0x40) {
630
EntityPlayer *player = RSDK_GET_ENTITY(id++, Player);
631
if (!player || player->classID == TYPE_BLANK)
632
break;
633
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
634
635
int32 moveX = (player->position.x - player->position.x) >> 3;
636
int32 moveY = (0xA00 * RSDK.Sin256(2 * (host->timer + angle - host->storedTimer)) + ruby->position.y - player->position.y) >> 3;
637
638
player->position.x += moveX;
639
player->position.y += moveY;
640
player->state = Player_State_Static;
641
player->tileCollisions = TILECOLLISION_NONE;
642
player->onGround = false;
643
}
644
}
645
}
646
}
647
else {
648
if (fxRuby->fadeWhite >= 512) {
649
if (fxRuby->fadeBlack >= 512) {
650
if (host->timer == host->storedTimer + 150)
651
return true;
652
}
653
else {
654
fxRuby->fadeBlack += 16;
655
}
656
}
657
else {
658
fxRuby->fadeWhite += 16;
659
}
660
}
661
return false;
662
}
663
664
void AIZSetup_CutsceneK_Setup(void)
665
{
666
RSDK_THIS(AIZSetup);
667
CutsceneSeq_StartSequence(self, AIZSetup_CutsceneKnux_Chillin, AIZSetup_CutsceneKnux_StartDrillin, AIZSetup_CutsceneKnux_Drillin,
668
AIZSetup_CutsceneKnux_PrepareForTrouble, AIZSetup_CutsceneKnux_EnterThreat, AIZSetup_CutsceneKnux_HeaviesAppear,
669
AIZSetup_CutsceneKnux_RubyImpact, AIZSetup_CutsceneKnux_RubyFX, AIZSetup_Cutscene_LoadGHZ, StateMachine_None);
670
671
#if MANIA_USE_PLUS
672
CutsceneSeq_SetSkipTypeCallback(AIZSetup_Cutscene_SkipCB);
673
#endif
674
}
675
676
bool32 AIZSetup_CutsceneKnux_Chillin(EntityCutsceneSeq *host)
677
{
678
MANIA_GET_PLAYER(player1, player2, camera);
679
UNUSED(player2);
680
UNUSED(camera);
681
682
if (!host->timer) {
683
player1->state = Player_State_Static;
684
player1->stateInput = StateMachine_None;
685
player1->direction = FLIP_X;
686
player1->drawFX = FX_FLIP;
687
RSDK.SetSpriteAnimation(AIZSetup->knuxFrames, 1, &player1->animator, true, 0);
688
}
689
690
return host->timer == 180;
691
}
692
bool32 AIZSetup_CutsceneKnux_StartDrillin(EntityCutsceneSeq *host)
693
{
694
MANIA_GET_PLAYER(player1, player2, camera);
695
UNUSED(player2);
696
UNUSED(camera);
697
698
switch (host->timer) {
699
case 0: RSDK.PlaySfx(AIZKingClaw->sfxClack, false, 0); break;
700
701
case 10:
702
RSDK.PlaySfx(AIZKingClaw->sfxWalkerLegs, false, 0);
703
RSDK.SetSpriteAnimation(AIZSetup->knuxFrames, 2, &player1->animator, true, 0);
704
break;
705
706
case 40: return true;
707
708
default: break;
709
}
710
711
return false;
712
}
713
bool32 AIZSetup_CutsceneKnux_Drillin(EntityCutsceneSeq *host)
714
{
715
if (host->timer < 120) {
716
AIZSetup->playDrillSfx = true;
717
718
if (!(host->timer % 5))
719
Camera_ShakeScreen(0, 0, 2);
720
}
721
else if (host->timer == 120) {
722
AIZSetup->playDrillSfx = false;
723
RSDK.PlaySfx(AIZSetup->sfxBreak, false, 0x00);
724
Music_TransitionTrack(TRACK_HBHMISCHIEF, 0.02);
725
}
726
727
return host->timer == 200;
728
}
729
bool32 AIZSetup_CutsceneKnux_PrepareForTrouble(EntityCutsceneSeq *host)
730
{
731
MANIA_GET_PLAYER(player1, player2, camera);
732
UNUSED(player2);
733
UNUSED(camera);
734
735
if (player1->animator.animationID == 3 && player1->animator.frameID == player1->animator.frameCount - 1) {
736
RSDK.SetSpriteAnimation(AIZSetup->knuxFrames, 0, &player1->animator, true, 0);
737
}
738
739
if (!host->timer) {
740
RSDK.SetSpriteAnimation(AIZSetup->knuxFrames, 3, &player1->animator, true, 0);
741
foreach_active(Animals, animal)
742
{
743
animal->active = ACTIVE_NORMAL;
744
animal->behaviour = ANIMAL_BEHAVE_FREE;
745
}
746
}
747
748
return host->timer == 60;
749
}
750
bool32 AIZSetup_CutsceneKnux_EnterThreat(EntityCutsceneSeq *host)
751
{
752
MANIA_GET_PLAYER(player1, player2, camera);
753
UNUSED(player2);
754
755
if (!host->timer) {
756
player1->camera = NULL;
757
Camera_SetupLerp(CAMERA_LERP_NORMAL, 0, player1->position.x - 0x600000, camera->position.y, 3);
758
}
759
else if (camera->position.x <= camera->endLerpPos.x) {
760
if (host->storedTimer) {
761
if (host->timer >= host->storedTimer + 60)
762
return true;
763
}
764
else {
765
host->storedTimer = host->timer;
766
}
767
}
768
else {
769
player1->state = Player_State_Static;
770
}
771
return false;
772
}
773
bool32 AIZSetup_CutsceneKnux_HeaviesAppear(EntityCutsceneSeq *host)
774
{
775
MANIA_GET_PLAYER(player1, player2, camera);
776
UNUSED(player2);
777
UNUSED(camera);
778
779
EntityAIZKingClaw *claw = AIZSetup->claw;
780
EntityPhantomRuby *ruby = AIZSetup->phantomRuby;
781
782
if (!host->timer) {
783
claw->grabbedEntities[0] = (Entity *)AIZSetup->platform;
784
claw->grabbedEntities[1] = (Entity *)ruby;
785
claw->grabCount = 2;
786
claw->angle = -16;
787
claw->position.y = -0x300000;
788
claw->position.x = 0x2F9C0000;
789
ruby->sfx = 0;
790
PhantomRuby_SetupFlash(ruby);
791
player1->drawGroup = Zone->playerDrawGroup[1] + 2;
792
RSDK.PlaySfx(AIZSetup->sfxHeliWoosh, false, 0);
793
}
794
795
AIZSetup_HandleHeavyMovement();
796
797
return ruby->position.x >= player1->position.x - 0x100000;
798
}
799
bool32 AIZSetup_CutsceneKnux_RubyImpact(EntityCutsceneSeq *host)
800
{
801
MANIA_GET_PLAYER(player1, player2, camera);
802
UNUSED(camera);
803
804
EntityPhantomRuby *ruby = AIZSetup->phantomRuby;
805
806
if (!host->timer) {
807
RSDK.PlaySfx(AIZSetup->sfxImpact, false, 0x00);
808
PhantomRuby_PlaySfx(RUBYSFX_REDCUBE);
809
Music_TransitionTrack(TRACK_EGGMAN1, 1.0);
810
811
EntityFXRuby *fxRuby = CREATE_ENTITY(FXRuby, NULL, ruby->position.x, ruby->position.y);
812
fxRuby->drawGroup = Zone->playerDrawGroup[1];
813
AIZSetup->fxRuby = fxRuby;
814
player1->velocity.x = 0x20000;
815
player1->velocity.y = -0x40000;
816
player1->nextGroundState = StateMachine_None;
817
player1->nextAirState = StateMachine_None;
818
player1->state = Player_State_Static;
819
player1->onGround = false;
820
player1->drawGroup = Zone->playerDrawGroup[1] + 1;
821
822
if (player2->classID == Player->classID)
823
player2->drawGroup = Zone->playerDrawGroup[1] + 1;
824
825
Camera_ShakeScreen(0, 4, 4);
826
}
827
828
AIZSetup_HandleHeavyMovement();
829
830
if (player1->onGround) {
831
if (player1->velocity.x > 0)
832
player1->velocity.x -= 0x2000;
833
if (player1->velocity.x < 0)
834
player1->velocity.x = 0;
835
player1->state = Player_State_Static;
836
RSDK.SetSpriteAnimation(AIZSetup->knuxFrames, 5, &player1->animator, false, 0);
837
return true;
838
}
839
else {
840
player1->velocity.y += 0x3800;
841
842
if (player1->velocity.x > 0)
843
player1->velocity.x -= 0x1000;
844
845
if (player1->velocity.x < 0)
846
player1->velocity.x = 0;
847
848
RSDK.SetSpriteAnimation(AIZSetup->knuxFrames, 4, &player1->animator, true, 0);
849
}
850
return false;
851
}
852
bool32 AIZSetup_CutsceneKnux_RubyFX(EntityCutsceneSeq *host)
853
{
854
MANIA_GET_PLAYER(player1, player2, camera);
855
UNUSED(player2);
856
UNUSED(camera);
857
858
EntityFXRuby *fxRuby = AIZSetup->fxRuby;
859
860
if (player1->velocity.x > 0)
861
player1->velocity.x -= 0x1000;
862
863
if (player1->velocity.x < 0)
864
player1->velocity.x = 0;
865
866
if (host->timer == 180) {
867
fxRuby->delay = 32;
868
fxRuby->state = FXRuby_State_IncreaseStageDeform;
869
870
PhantomRuby_PlaySfx(RUBYSFX_ATTACK1);
871
Camera_ShakeScreen(0, 4, 4);
872
Music_FadeOut(0.025);
873
874
host->storedTimer = host->timer;
875
host->values[0] = true;
876
}
877
878
AIZSetup_HandleHeavyMovement();
879
880
if (host->values[0]) {
881
if (fxRuby->fadeWhite < 0x200) {
882
fxRuby->fadeWhite += 0x10;
883
}
884
else if (fxRuby->fadeBlack >= 0x200) {
885
if (host->timer == host->storedTimer + 150)
886
return true;
887
}
888
else {
889
fxRuby->fadeBlack += 0x200;
890
}
891
}
892
893
return false;
894
}
895
896
bool32 AIZSetup_Cutscene_LoadGHZ(EntityCutsceneSeq *host)
897
{
898
UNUSED(host);
899
900
RSDK.SetScene("Cutscenes", "Green Hill Zone");
901
RSDK.LoadScene();
902
903
return true;
904
}
905
906
#if GAME_INCLUDE_EDITOR
907
void AIZSetup_EditorDraw(void) {}
908
909
void AIZSetup_EditorLoad(void)
910
{
911
RSDK_ACTIVE_VAR(BGSwitch, bgID);
912
RSDK_ENUM_VAR("Jungle BG", AIZ_BG_JUNGLE);
913
RSDK_ENUM_VAR("Sky BG", AIZ_BG_SKY);
914
915
RSDK_ACTIVE_VAR(Decoration, type);
916
RSDK_ENUM_VAR("Leaf 1", AIZ_DECOR_LEAF1);
917
RSDK_ENUM_VAR("Leaf 2", AIZ_DECOR_LEAF2);
918
RSDK_ENUM_VAR("Leaf 3", AIZ_DECOR_LEAF3);
919
RSDK_ENUM_VAR("Leaf 4", AIZ_DECOR_LEAF4);
920
}
921
#endif
922
923
void AIZSetup_Serialize(void) {}
924
925