Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/AIZ/EncoreIntro.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: EncoreIntro Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectEncoreIntro *EncoreIntro;
12
13
void EncoreIntro_Update(void)
14
{
15
RSDK_THIS(EncoreIntro);
16
17
if (!self->activated) {
18
foreach_active(Player, player)
19
{
20
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
21
EncoreIntro_SetupCutscene();
22
CutsceneSeq_SetSkipType(SKIPTYPE_RELOADSCN);
23
self->activated = true;
24
}
25
}
26
}
27
28
if (self->skipPart2) {
29
EncoreIntro_SetupCutscenePart2();
30
CutsceneSeq_StartSequence(self, EncoreIntro_Cutscene_AIZEncore, EncoreIntro_Cutscene_CapsuleFound, EncoreIntro_Cutscene_BuddySelect,
31
EncoreIntro_Cutscene_ViewEncoreTutorial, EncoreIntro_Cutscene_MysticGetRuby, EncoreIntro_Cutscene_MysticStealRuby,
32
EncoreIntro_Cutscene_MysticEscape, EncoreIntro_Cutscene_AIZEncoreTutorial, EncoreIntro_Cutscene_CameraPanToHBHPile,
33
EncoreIntro_Cutscene_MysticPassRuby, EncoreIntro_Cutscene_KingActivate, EncoreIntro_Cutscene_RubyActivated,
34
EncoreIntro_Cutscene_RubyWarp, EncoreIntro_Cutscene_LoadGHZ, EncoreIntro_Cutscene_AwaitSaveFinish,
35
EncoreIntro_Cutscene_FadeOutAndReset, EncoreIntro_Cutscene_FadeInAndStart, EncoreIntro_Cutscene_SkipAndFadeOut,
36
EncoreIntro_Cutscene_AwaitSaveFinish, StateMachine_None);
37
self->skipPart2 = false;
38
39
#if MANIA_USE_PLUS
40
CutsceneSeq_SetSkipType(SKIPTYPE_DISABLED);
41
#endif
42
}
43
}
44
45
void EncoreIntro_LateUpdate(void) {}
46
47
void EncoreIntro_StaticUpdate(void) {}
48
49
void EncoreIntro_Draw(void) {}
50
51
void EncoreIntro_Create(void *data)
52
{
53
RSDK_THIS(EncoreIntro);
54
55
if (!SceneInfo->inEditor) {
56
INIT_ENTITY(self);
57
CutsceneRules_SetupEntity(self, &self->size, &self->hitbox);
58
EncoreIntro_SetupEntities();
59
self->active = ACTIVE_NORMAL;
60
61
if (globals->enableIntro) {
62
foreach_all(HUD, hud)
63
{
64
HUD_MoveIn(hud);
65
hud->state = StateMachine_None;
66
}
67
68
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
69
ruby->alpha = 0;
70
ruby->inkEffect = INK_ALPHA;
71
ruby->state = EncoreIntro_PhantomRuby_OscillateFX;
72
RSDK.SetSpriteAnimation(-1, -1, &ruby->flashAnimator, true, 0);
73
ruby->flashAnimator.animationID = -1;
74
}
75
else {
76
int32 id = RSDK.GetEntitySlot(self);
77
78
foreach_all(Animals, animal)
79
{
80
if (RSDK.GetEntitySlot(animal) < id) {
81
destroyEntity(animal);
82
}
83
else {
84
foreach_break;
85
}
86
}
87
RSDK.ResetEntitySlot(id - 3, TYPE_BLANK, NULL);
88
RSDK.ResetEntitySlot(id - 2, TYPE_BLANK, NULL);
89
self->activated = true;
90
self->skipPart2 = true;
91
}
92
}
93
}
94
95
void EncoreIntro_StageLoad(void)
96
{
97
EncoreIntro->aniFrames = RSDK.LoadSpriteAnimation("AIZ/Cutscene.bin", SCOPE_STAGE);
98
99
EncoreIntro->sfxHighFive = RSDK.GetSfx("Stage/HighFive.wav");
100
EncoreIntro->sfxMysticPoof = RSDK.GetSfx("MSZ/MysticPoof.wav");
101
EncoreIntro->sfxKingCharge = RSDK.GetSfx("LRZ/KingCharge.wav");
102
EncoreIntro->sfxMysticHat = RSDK.GetSfx("MSZ/MysticHat.wav");
103
EncoreIntro->sfxMysticTransform = RSDK.GetSfx("MSZ/MysticTransform.wav");
104
EncoreIntro->sfxPon = RSDK.GetSfx("Stage/Pon.wav");
105
106
Music_SetMusicTrack("BuddyBeat.ogg", TRACK_BUDDYBEAT, 85232);
107
}
108
109
void EncoreIntro_SetupEntities(void)
110
{
111
foreach_all(PhantomRuby, ruby)
112
{
113
EncoreIntro->phantomRuby = ruby;
114
foreach_break;
115
}
116
117
foreach_all(FXRuby, fxRuby)
118
{
119
EncoreIntro->fxRuby = fxRuby;
120
fxRuby->state = FXRuby_State_Shrinking;
121
fxRuby->outerRadius = 0;
122
foreach_break;
123
}
124
125
foreach_all(RubyPortal, portal)
126
{
127
EncoreIntro->rubyPortal = portal;
128
foreach_break;
129
}
130
}
131
132
void EncoreIntro_SetupCutscene(void)
133
{
134
RSDK_THIS(EncoreIntro);
135
136
CutsceneSeq_StartSequence(self, EncoreIntro_Cutscene_SetupAIZEncore, EncoreIntro_Cutscene_PlayerAppear, EncoreIntro_Cutscene_RubyAppear,
137
EncoreIntro_Cutscene_PortalClose, EncoreIntro_Cutscene_Empty, EncoreIntro_Cutscene_BeginAIZEncore,
138
EncoreIntro_Cutscene_AIZEncore, EncoreIntro_Cutscene_CapsuleFound, EncoreIntro_Cutscene_BuddySelect,
139
EncoreIntro_Cutscene_ViewEncoreTutorial, EncoreIntro_Cutscene_MysticGetRuby, EncoreIntro_Cutscene_MysticStealRuby,
140
EncoreIntro_Cutscene_MysticEscape, EncoreIntro_Cutscene_AIZEncoreTutorial, EncoreIntro_Cutscene_CameraPanToHBHPile,
141
EncoreIntro_Cutscene_MysticPassRuby, EncoreIntro_Cutscene_KingActivate, EncoreIntro_Cutscene_RubyActivated,
142
EncoreIntro_Cutscene_RubyWarp, EncoreIntro_Cutscene_LoadGHZ, EncoreIntro_Cutscene_AwaitSaveFinish,
143
EncoreIntro_Cutscene_FadeOutAndReset, EncoreIntro_Cutscene_FadeInAndStart, EncoreIntro_Cutscene_SkipAndFadeOut,
144
EncoreIntro_Cutscene_AwaitSaveFinish, StateMachine_None);
145
146
#if MANIA_USE_PLUS
147
CutsceneSeq_SetSkipType(SKIPTYPE_DISABLED);
148
#endif
149
}
150
151
void EncoreIntro_SetupCutscenePart2(void)
152
{
153
RSDK_THIS(EncoreIntro);
154
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
155
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
156
157
player1->camera = camera;
158
player1->stateInput = Player_Input_P1;
159
player1->tileCollisions = TILECOLLISION_DOWN;
160
player1->onGround = true;
161
player1->state = Player_State_Ground;
162
camera->target = (Entity *)player1;
163
camera->state = Camera_State_FollowXY;
164
camera->position.x = player1->position.x;
165
166
Vector2 size;
167
RSDK.GetLayerSize(Zone->fgLayer[0], &size, true);
168
Zone->cameraBoundsR[0] = size.x;
169
Zone->playerBoundsR[0] = size.x << 16;
170
Zone->playerBoundActiveR[0] = true;
171
Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;
172
Zone->playerBoundsL[0] = Zone->cameraBoundsL[0] << 16;
173
Zone->playerBoundActiveL[0] = true;
174
175
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
176
foreach_all(SchrodingersCapsule, capsule)
177
{
178
ruby->position.x = capsule->position.x;
179
ruby->state = EncoreIntro_PhantomRuby_OscillateFX;
180
ruby->startPos.y = capsule->position.y - 0x800000;
181
ruby->position.y = capsule->position.y - 0x800000;
182
}
183
}
184
185
bool32 EncoreIntro_Cutscene_SetupAIZEncore(EntityCutsceneSeq *host)
186
{
187
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
188
189
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
190
EntityFXRuby *fxRuby = EncoreIntro->fxRuby;
191
192
// NOTE:
193
// ok idk HOW this is meant to be triggered
194
// I assume its via dying and hitting a StarPost
195
// big problem there: there aren't any!
196
// so there doesn't seem to be any way to get this to run normally
197
if (SceneInfo->minutes || SceneInfo->seconds) {
198
host->stateID = 21; // EncoreIntro_Cutscene_FadeOutAndReset
199
host->skipType = SKIPTYPE_DISABLED;
200
}
201
else {
202
if (!host->timer) {
203
globals->stock = ID_NONE;
204
globals->characterFlags = ID_SONIC;
205
Player_ChangeCharacter(player1, ID_SONIC);
206
destroyEntity(RSDK_GET_ENTITY(SLOT_PLAYER2, Player));
207
player1->alpha = 0;
208
player1->inkEffect = INK_ALPHA;
209
ruby->alpha = 0;
210
ruby->inkEffect = INK_ALPHA;
211
player1->position.y = ruby->position.y;
212
player1->state = Player_State_Static;
213
player1->stateInput = StateMachine_None;
214
CutsceneSeq_LockAllPlayerControl();
215
player1->groundVel = 0;
216
player1->velocity.x = 0;
217
player1->direction = FLIP_NONE;
218
foreach_all(CutsceneHBH, cutsceneHBH) { cutsceneHBH->drawGroup = Zone->objectDrawGroup[0]; }
219
Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;
220
Zone->playerBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;
221
}
222
else if (host->timer == 240) {
223
fxRuby->delay = 32;
224
fxRuby->state = FXRuby_State_IncreaseStageDeform;
225
PhantomRuby_PlaySfx(RUBYSFX_ATTACK4);
226
Camera_ShakeScreen(0, 4, 4);
227
Music_TransitionTrack(TRACK_EGGMAN1, 0.01);
228
foreach_active(Animals, animal)
229
{
230
animal->behaviour = ANIMAL_BEHAVE_FREE;
231
animal->active = ACTIVE_NORMAL;
232
}
233
}
234
235
if (host->timer < 360) {
236
RSDK.SetSpriteAnimation(player1->aniFrames, ANI_FAN, &player1->animator, false, 0);
237
player1->position.x += (player1->position.x - player1->position.x) >> 3;
238
player1->position.y += (0xA00 * RSDK.Sin256(2 * (host->timer - host->storedTimer)) + ruby->position.y - player1->position.y) >> 3;
239
player1->state = Player_State_Static;
240
}
241
else {
242
ruby->alpha = 0;
243
ruby->inkEffect = INK_ALPHA;
244
return true;
245
}
246
}
247
248
return false;
249
}
250
251
bool32 EncoreIntro_Cutscene_PlayerAppear(EntityCutsceneSeq *host)
252
{
253
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
254
255
if (host->timer >= 60) {
256
player->alpha += 2;
257
if (player->alpha >= 0x100) {
258
player->inkEffect = INK_NONE;
259
RSDK.Sin256(2 * (host->timer - host->storedTimer));
260
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
261
player->state = Player_State_Air;
262
player->up = true;
263
host->values[0] = 1;
264
return true;
265
}
266
}
267
268
return false;
269
}
270
271
bool32 EncoreIntro_Cutscene_RubyAppear(EntityCutsceneSeq *host)
272
{
273
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
274
275
if (host->timer >= 60) {
276
ruby->alpha += 2;
277
if (ruby->alpha >= 0x100) {
278
ruby->inkEffect = INK_NONE;
279
return true;
280
}
281
}
282
283
return false;
284
}
285
286
bool32 EncoreIntro_Cutscene_PortalClose(EntityCutsceneSeq *host)
287
{
288
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
289
EntityRubyPortal *portal = EncoreIntro->rubyPortal;
290
291
if (host->timer >= 60) {
292
portal->alpha -= 4;
293
if (portal->alpha <= 0) {
294
destroyEntity(portal);
295
ruby->state = EncoreIntro_PhantomRuby_EscapeRight;
296
Music_FadeOut(0.012);
297
host->skipType = SKIPTYPE_DISABLED;
298
return true;
299
}
300
}
301
302
return false;
303
}
304
305
bool32 EncoreIntro_Cutscene_Empty(EntityCutsceneSeq *host)
306
{
307
return true; // what the
308
}
309
310
bool32 EncoreIntro_Cutscene_BeginAIZEncore(EntityCutsceneSeq *host)
311
{
312
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
313
314
if (host->timer == 60)
315
player->up = false;
316
317
if (host->timer >= 120) {
318
foreach_all(TitleCard, titleCard)
319
{
320
titleCard->active = ACTIVE_NORMAL;
321
titleCard->state = TitleCard_State_SetupBGElements;
322
titleCard->stateDraw = TitleCard_Draw_SlideIn;
323
foreach_break;
324
}
325
foreach_all(HUD, hud)
326
{
327
hud->vsStates[0] = HUD_State_MoveIn;
328
hud->state = hud->vsStates[0];
329
}
330
Music_PlayTrack(TRACK_STAGE);
331
EncoreIntro_SetupCutscenePart2();
332
return true;
333
}
334
335
return false;
336
}
337
338
bool32 EncoreIntro_Cutscene_AIZEncore(EntityCutsceneSeq *host)
339
{
340
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
341
342
RSDK_THIS(EncoreIntro);
343
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
344
345
if (player->position.x <= self->position.x + 0x2000000) {
346
Zone->cameraBoundsL[0] = ScreenInfo->position.x;
347
Zone->playerBoundsL[0] = Zone->cameraBoundsL[0] << 16;
348
Zone->playerBoundActiveL[0] = true;
349
}
350
else {
351
Zone->cameraBoundsT[0] = 0;
352
Zone->playerBoundsT[0] = 0;
353
}
354
355
if (ruby->onScreen) {
356
Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;
357
Zone->playerBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;
358
Music_TransitionTrack(TRACK_EGGMAN1, 0.05);
359
return true;
360
}
361
362
return false;
363
}
364
365
bool32 EncoreIntro_Cutscene_CapsuleFound(EntityCutsceneSeq *host)
366
{
367
RSDK_THIS(EncoreIntro);
368
369
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
370
EntityActClear *actClear = RSDK_GET_ENTITY(SLOT_ACTCLEAR, ActClear);
371
372
if (!self->seenActClear) {
373
if (actClear->classID == ActClear->classID)
374
self->seenActClear = true;
375
}
376
else {
377
player->velocity.x = 0;
378
player->groundVel = 0;
379
if (actClear->classID != ActClear->classID) {
380
self->seenActClear = false;
381
Music_TransitionTrack(TRACK_EGGMAN2, 0.05);
382
383
StarPost->playerPositions[0] = player->position;
384
StarPost->playerPositions[1] = player->position;
385
player->state = EncoreIntro_PlayerState_BuddySel;
386
player->stateInput = EncoreIntro_PlayerInput_BuddySel;
387
RSDK.SetSpriteAnimation(player->aniFrames, ANI_IDLE, &player->animator, true, 0);
388
389
EntityPlayer *buddy1 = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);
390
buddy1->state = Player_State_Ground;
391
RSDK.SetSpriteAnimation(buddy1->aniFrames, ANI_IDLE, &buddy1->animator, true, 0);
392
393
EntityPlayer *buddy2 = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);
394
buddy2->state = Player_State_Ground;
395
RSDK.SetSpriteAnimation(buddy2->aniFrames, ANI_IDLE, &buddy2->animator, true, 0);
396
return true;
397
}
398
}
399
400
return false;
401
}
402
403
bool32 EncoreIntro_Cutscene_BuddySelect(EntityCutsceneSeq *host)
404
{
405
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
406
407
player->drawGroup = Zone->playerDrawGroup[1];
408
EntityPlayer *selBuddy = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);
409
if (player->position.x > selBuddy->position.x - 0x380000) {
410
globals->characterFlags = ID_SONIC | ID_MIGHTY;
411
}
412
else {
413
selBuddy = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);
414
if (player->position.x < selBuddy->position.x + 0x380000)
415
globals->characterFlags = ID_SONIC | ID_RAY;
416
else
417
return false;
418
}
419
player->state = EncoreIntro_PlayerState_HandleAir;
420
player->nextAirState = StateMachine_None;
421
player->nextGroundState = Player_State_Static;
422
player->onGround = false;
423
globals->stock = ID_NONE;
424
if (globals->characterFlags == (ID_SONIC | ID_RAY)) {
425
RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 0, &player->animator, true, 0);
426
player->velocity.x = -0xC000;
427
}
428
else {
429
RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 1, &player->animator, true, 0);
430
player->velocity.x = 0x8000;
431
}
432
player->velocity.y = -0x30000;
433
CutsceneSeq_LockPlayerControl(player);
434
player->stateInput = StateMachine_None;
435
436
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
437
RSDK.CopyEntity(buddy, selBuddy, true);
438
buddy->drawGroup = Zone->playerDrawGroup[1];
439
buddy->state = EncoreIntro_PlayerState_HandleAir;
440
buddy->nextAirState = StateMachine_None;
441
buddy->nextGroundState = Player_State_Static;
442
buddy->onGround = false;
443
444
if (globals->characterFlags == (ID_SONIC | ID_RAY)) {
445
RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 2, &buddy->animator, true, 0);
446
buddy->velocity.x = 0xC000;
447
}
448
else {
449
RSDK.SetSpriteAnimation(EncoreIntro->aniFrames, 3, &buddy->animator, true, 0);
450
buddy->velocity.x = -0x8000;
451
}
452
buddy->velocity.y = -0x30000;
453
globals->playerID = (buddy->characterID << 8) + ID_SONIC;
454
Music_FadeOut(0.025);
455
RSDK.PlaySfx(EncoreIntro->sfxHighFive, false, 0xFF);
456
457
if (globals->characterFlags == (ID_SONIC | ID_RAY))
458
CREATE_ENTITY(AIZEncoreTutorial, INT_TO_VOID(5), (buddy->position.x >> 1) + (player->position.x >> 1), player->position.y - 0x480000);
459
else
460
CREATE_ENTITY(AIZEncoreTutorial, INT_TO_VOID(6), (buddy->position.x >> 1) + (player->position.x >> 1), player->position.y - 0x480000);
461
462
return true;
463
}
464
465
bool32 EncoreIntro_Cutscene_ViewEncoreTutorial(EntityCutsceneSeq *host)
466
{
467
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
468
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
469
470
RSDK_THIS(EncoreIntro);
471
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
472
473
HeavyMystic_HandleParticleFX();
474
if (player->onGround) {
475
RSDK.SetSpriteAnimation(player->aniFrames, ANI_IDLE, &player->animator, true, 0);
476
player->velocity.x = 0;
477
player->groundVel = 0;
478
}
479
480
if (host->timer > 300)
481
player->direction = ruby->position.x < player->position.x;
482
483
if (buddy->onGround) {
484
RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_IDLE, &buddy->animator, true, 0);
485
buddy->velocity.x = 0;
486
buddy->groundVel = 0;
487
}
488
489
if (host->timer > 300)
490
buddy->direction = ruby->position.x < buddy->position.x;
491
492
if (host->timer == 18) {
493
if (globals->characterFlags == (ID_SONIC | ID_RAY)) {
494
player->velocity.x = 0;
495
buddy->velocity.x = 0;
496
}
497
}
498
else if (host->timer == 300) {
499
EntityPlayer *otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);
500
if (!otherBuddy->classID)
501
otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);
502
self->position.x = otherBuddy->position.x;
503
self->position.y = otherBuddy->position.y;
504
}
505
else {
506
if (host->timer != 420) {
507
if (host->timer == 480) {
508
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
509
RSDK.SetSpriteAnimation(mystic->aniFrames, 1, &mystic->mainAnimator, true, 0);
510
}
511
else {
512
if (host->timer == 496) {
513
RSDK.PlaySfx(EncoreIntro->sfxMysticHat, false, 0xFF);
514
}
515
else if (host->timer < 570) {
516
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
517
if (mystic->mainAnimator.frameID == mystic->mainAnimator.frameCount - 1)
518
RSDK.SetSpriteAnimation(mystic->aniFrames, 0, &mystic->mainAnimator, true, 0);
519
}
520
else {
521
return true;
522
}
523
}
524
}
525
else {
526
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
527
EntityPlayer *otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER3, Player);
528
if (!otherBuddy->classID)
529
otherBuddy = RSDK_GET_ENTITY(SLOT_PLAYER4, Player);
530
mystic->position.x = otherBuddy->position.x;
531
mystic->position.y = otherBuddy->position.y;
532
mystic->direction = otherBuddy->direction ^ 1;
533
mystic->drawGroup = Zone->playerDrawGroup[1] - 1;
534
destroyEntity(otherBuddy);
535
536
RSDK.PlaySfx(EncoreIntro->sfxMysticPoof, false, 0xFF);
537
CREATE_ENTITY(Explosion, INT_TO_VOID(2), mystic->position.x, mystic->position.y)->drawGroup = Zone->playerDrawGroup[1] - 1;
538
Music_PlayTrack(TRACK_HBHMISCHIEF);
539
540
for (int32 i = 0; i < 2; ++i) {
541
EntityPlayer *playerPtr = RSDK_GET_ENTITY(i, Player);
542
playerPtr->state = Player_State_Air;
543
playerPtr->onGround = false;
544
playerPtr->velocity.y = -0x38000;
545
RSDK.SetSpriteAnimation(playerPtr->aniFrames, ANI_HURT, &playerPtr->animator, false, 0);
546
}
547
}
548
}
549
return false;
550
}
551
552
bool32 EncoreIntro_Cutscene_MysticGetRuby(EntityCutsceneSeq *host)
553
{
554
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
555
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
556
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
557
UNUSED(camera);
558
559
RSDK_THIS(EncoreIntro);
560
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
561
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
562
563
player->direction = ruby->position.x < player->position.x;
564
buddy->direction = ruby->position.x < buddy->position.x;
565
566
int32 offset = -0x320000;
567
if (buddy->direction)
568
offset = 0x320000;
569
int32 pos = offset + ruby->position.x;
570
571
if (mystic->position.x != pos) {
572
if (mystic->position.x >= pos) {
573
mystic->position.x -= 0x20000;
574
if (mystic->position.x < offset + ruby->position.x)
575
mystic->position.x = offset + ruby->position.x;
576
}
577
else {
578
mystic->position.x += 0x20000;
579
if (mystic->position.x > offset + ruby->position.x)
580
mystic->position.x = offset + ruby->position.x;
581
}
582
583
mystic->position.y -= 0x18000;
584
mystic->velocity.y = -0x18000;
585
if (host->timer > 24) {
586
RSDK.SetSpriteAnimation(player->aniFrames, ANI_LOOK_UP, &player->animator, false, 1);
587
if (player->animator.frameID == 5)
588
player->animator.speed = 0;
589
590
RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_LOOK_UP, &buddy->animator, false, 1);
591
if (buddy->animator.frameID == 5)
592
buddy->animator.speed = 0;
593
}
594
self->position.x = mystic->position.x;
595
self->position.y = mystic->position.y;
596
HeavyMystic_HandleParticleFX();
597
}
598
else {
599
RSDK.SetSpriteAnimation(player->aniFrames, ANI_LOOK_UP, &player->animator, false, 1);
600
if (player->animator.frameID == 5)
601
player->animator.speed = 0;
602
603
RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_LOOK_UP, &buddy->animator, false, 1);
604
if (buddy->animator.frameID == 5)
605
buddy->animator.speed = 0;
606
607
if (mystic->position.y > ruby->startPos.y + 0x140000) {
608
mystic->position.y += mystic->velocity.y;
609
self->position.x = mystic->position.x;
610
self->position.y = mystic->position.y;
611
HeavyMystic_HandleParticleFX();
612
}
613
else {
614
RSDK.SetSpriteAnimation(mystic->aniFrames, 2, &mystic->mainAnimator, true, 0);
615
return true;
616
}
617
}
618
619
return false;
620
}
621
622
bool32 EncoreIntro_Cutscene_MysticStealRuby(EntityCutsceneSeq *host)
623
{
624
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
625
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
626
627
RSDK_THIS(EncoreIntro);
628
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
629
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
630
631
player->direction = ruby->position.x < player->position.x;
632
buddy->direction = ruby->position.x < buddy->position.x;
633
634
if (host->timer == 33) {
635
RSDK.PlaySfx(EncoreIntro->sfxMysticTransform, false, 255);
636
ruby->state = StateMachine_None;
637
}
638
else if (host->timer >= 34) {
639
if (ruby->position.y < mystic->position.y) {
640
ruby->startPos.y += 0x18000;
641
ruby->position.y += 0x18000;
642
}
643
else if (ruby->visible) {
644
ruby->visible = false;
645
}
646
else if (host->timer == 75) {
647
RSDK.SetSpriteAnimation(mystic->aniFrames, 0, &mystic->mainAnimator, true, 0);
648
Zone->cameraBoundsR[0] = 16 * RSDK.GetTileLayer(Zone->fgLayer[0])->width;
649
Zone->playerBoundsR[0] = 16 * RSDK.GetTileLayer(Zone->fgLayer[0])->width;
650
Zone->cameraBoundsT[0] = 784;
651
Zone->playerBoundsT[0] = 784;
652
mystic->direction = FLIP_NONE;
653
return true;
654
}
655
}
656
657
self->position.x = mystic->position.x;
658
self->position.y = mystic->position.y;
659
HeavyMystic_HandleParticleFX();
660
return false;
661
}
662
663
bool32 EncoreIntro_Cutscene_MysticEscape(EntityCutsceneSeq *host)
664
{
665
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
666
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
667
668
RSDK_THIS(EncoreIntro);
669
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
670
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
671
672
player->direction = mystic->position.x < player->position.x;
673
buddy->direction = mystic->position.x < buddy->position.x;
674
if (host->timer >= 60) {
675
mystic->position.y -= 0x800000;
676
mystic->position.x = CutsceneHBH_GetEntity(HBH_KINGDAMAGED)->position.x - 0x580000;
677
ruby->position.y -= 0x800000;
678
SceneInfo->timeEnabled = true;
679
680
player->state = Player_State_Ground;
681
player->stateInput = Player_Input_P1;
682
RSDK.SetSpriteAnimation(player->aniFrames, ANI_IDLE, &player->animator, true, 0);
683
684
buddy->state = Player_State_Ground;
685
buddy->stateInput = Player_Input_P2_AI;
686
RSDK.SetSpriteAnimation(buddy->aniFrames, ANI_IDLE, &buddy->animator, true, 0);
687
return true;
688
}
689
else {
690
mystic->velocity.x += 0x1800;
691
if (mystic->velocity.x > 0x30000)
692
mystic->velocity.x = 0x30000;
693
if (mystic->onScreen == 1)
694
--host->timer;
695
mystic->position.x += mystic->velocity.x;
696
self->position.x = mystic->position.x;
697
self->position.y = mystic->position.y;
698
HeavyMystic_HandleParticleFX();
699
}
700
return false;
701
}
702
703
bool32 EncoreIntro_Cutscene_AIZEncoreTutorial(EntityCutsceneSeq *host)
704
{
705
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
706
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
707
708
RSDK_THIS(AIZEncoreTutorial);
709
EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);
710
711
if (player->position.x >= king->position.x - 0x2600000) {
712
self->position.x = player->position.x;
713
self->position.y = player->position.y;
714
player->stateInput = StateMachine_None;
715
if (player->onGround)
716
player->state = Player_State_Ground;
717
CutsceneSeq_LockAllPlayerControl();
718
719
player->right = true;
720
if (player->velocity.x >= 0x20000)
721
player->velocity.x = 0x20000;
722
self->velocity.x = player->velocity.x;
723
camera->target = (Entity *)self;
724
CutsceneSeq_SetSkipTypeCallback(AIZEncoreTutorial_State_ReturnToCutscene);
725
HUD_MoveOut();
726
return true;
727
}
728
return false;
729
}
730
731
bool32 EncoreIntro_Cutscene_CameraPanToHBHPile(EntityCutsceneSeq *host)
732
{
733
RSDK_THIS(EncoreIntro);
734
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
735
EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);
736
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
737
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
738
739
if (self->position.x >= king->position.x - 0x880000) {
740
if (self->velocity.x == 0x60000) {
741
player->groundVel = 0x30000;
742
player->velocity.x = 0x30000;
743
player->position.x = (ScreenInfo->position.x - 32) << 16;
744
buddy->groundVel = 0x30000;
745
buddy->position.x = (ScreenInfo->position.x - 96) << 16;
746
buddy->velocity.x = 0x30000;
747
buddy->drawFX &= ~FX_SCALE;
748
buddy->position.y = player->position.y;
749
buddy->state = Player_State_Ground;
750
buddy->tileCollisions = TILECOLLISION_DOWN;
751
buddy->stateInput = StateMachine_None;
752
buddy->scale.x = 0;
753
buddy->scale.y = 0;
754
buddy->drawGroup = player->drawGroup - 1;
755
}
756
757
self->velocity.x -= 0x1800;
758
if (self->velocity.x < 0x4C000) {
759
player->right = false;
760
buddy->right = false;
761
player->up = true;
762
buddy->up = true;
763
}
764
if (buddy->state == Player_State_Ground && buddy->position.x >= player->position.x - 0x200000)
765
buddy->velocity.x = player->velocity.x;
766
if (self->velocity.x <= -0x2D000) {
767
RSDK.SetSpriteAnimation(mystic->aniFrames, 2, &mystic->mainAnimator, true, 0);
768
self->velocity.x = 0;
769
return true;
770
}
771
}
772
else {
773
self->velocity.x += 0x6000;
774
if (self->velocity.x > 0x60000)
775
self->velocity.x = 0x60000;
776
777
player->state = Player_State_Ground;
778
player->right = true;
779
if (player->groundVel > 0x20000)
780
player->groundVel = 0x20000;
781
if (buddy->groundVel > ((buddy->position.x <= player->position.x) + 1) << 16)
782
buddy->groundVel = 0x20000;
783
}
784
785
if (self->velocity.x > 0)
786
self->position.x += self->velocity.x;
787
788
self->position.y = mystic->position.y;
789
if (self->position.x <= mystic->position.x) {
790
int32 storeX = self->position.x;
791
int32 storeY = self->position.y;
792
self->position.x = mystic->position.x;
793
self->position.y = mystic->position.y;
794
HeavyMystic_HandleParticleFX();
795
self->position.x = storeX;
796
self->position.y = storeY;
797
}
798
else {
799
self->position.x = mystic->position.x;
800
self->position.y = mystic->position.y;
801
HeavyMystic_HandleParticleFX();
802
}
803
804
return false;
805
}
806
807
bool32 EncoreIntro_Cutscene_MysticPassRuby(EntityCutsceneSeq *host)
808
{
809
EntityCutsceneHBH *mystic = CutsceneHBH_GetEntity(HBH_MYSTIC);
810
EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);
811
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
812
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
813
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
814
815
player->timer = 0;
816
buddy->timer = 0;
817
if (buddy->state == Player_State_Ground && buddy->position.x >= player->position.x - 0x200000)
818
buddy->velocity.x = player->velocity.x;
819
820
switch (host->timer) {
821
case 33:
822
RSDK.PlaySfx(EncoreIntro->sfxPon, false, 0xFF);
823
ruby->visible = true;
824
ruby->position.x = mystic->position.x + 0x320000;
825
ruby->position.y = mystic->position.y;
826
ruby->velocity.x = 0;
827
ruby->velocity.y = -0x40000;
828
ruby->state = EncoreIntro_PhantomRuby_Fall;
829
Music_TransitionTrack(TRACK_EGGMAN1, 0.025);
830
break;
831
case 40: mystic->drawGroup = Zone->playerDrawGroup[0]; break;
832
case 75:
833
RSDK.SetSpriteAnimation(mystic->aniFrames, 0, &mystic->mainAnimator, true, 0);
834
player->up = false;
835
buddy->up = false;
836
break;
837
default:
838
if (ruby->position.y >= king->position.y + 0x60000) {
839
ruby->position.y = king->position.y + 0x60000;
840
ruby->state = StateMachine_None;
841
RSDK.PlaySfx(Player->sfxGrab, false, 0xFF);
842
RSDK.SetSpriteAnimation(king->aniFrames, 3, &king->fxAnimator, true, 0);
843
return true;
844
}
845
break;
846
}
847
HeavyMystic_HandleParticleFX();
848
return false;
849
}
850
851
bool32 EncoreIntro_Cutscene_KingActivate(EntityCutsceneSeq *host)
852
{
853
EntityCutsceneHBH *king = CutsceneHBH_GetEntity(HBH_KINGDAMAGED);
854
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
855
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
856
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
857
858
player->timer = 0;
859
buddy->timer = 0;
860
if (buddy->state == Player_State_Ground && buddy->position.x >= player->position.x - 0x200000)
861
buddy->velocity.x = player->velocity.x;
862
863
switch (host->timer) {
864
case 9: ruby->drawGroup = Zone->objectDrawGroup[0]; break;
865
866
case 42: RSDK.SetSpriteAnimation(king->aniFrames, 2, &king->mainAnimator, true, 0); break;
867
868
case 58:
869
case 66:
870
case 74: RSDK.PlaySfx(EncoreIntro->sfxKingCharge, false, 0xFF); break;
871
872
case 102: return true;
873
874
default: break;
875
}
876
HeavyMystic_HandleParticleFX();
877
return false;
878
}
879
880
bool32 EncoreIntro_Cutscene_RubyActivated(EntityCutsceneSeq *host)
881
{
882
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
883
if (!host->timer)
884
PhantomRuby_SetupFlash(ruby);
885
if (ruby->flashFinished)
886
return true;
887
HeavyMystic_HandleParticleFX();
888
return false;
889
}
890
891
bool32 EncoreIntro_Cutscene_RubyWarp(EntityCutsceneSeq *host)
892
{
893
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
894
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
895
EntityPlayer *buddy = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);
896
897
EntityFXRuby *fxRuby = NULL;
898
if (!host->timer) {
899
fxRuby = CREATE_ENTITY(FXRuby, NULL, ruby->position.x, ruby->position.y);
900
fxRuby->drawGroup = Zone->playerDrawGroup[1] + 1;
901
EncoreIntro->fxRuby = fxRuby;
902
PhantomRuby_PlaySfx(RUBYSFX_REDCUBE);
903
Camera_ShakeScreen(0, 4, 4);
904
player->drawGroup = Zone->playerDrawGroup[1] + 1;
905
if (buddy->classID == Player->classID)
906
buddy->drawGroup = Zone->playerDrawGroup[1] + 1;
907
}
908
else {
909
fxRuby = EncoreIntro->fxRuby;
910
}
911
912
if (!host->values[0]) {
913
if (fxRuby->fullyExpanded) {
914
if (host->storedTimer) {
915
if (host->timer == host->storedTimer + 30) {
916
fxRuby->delay = 64;
917
fxRuby->state = FXRuby_State_IncreaseStageDeform;
918
PhantomRuby_PlaySfx(4);
919
Camera_ShakeScreen(0, 4, 4);
920
}
921
else if (host->timer == host->storedTimer + 210) {
922
fxRuby->delay = 32;
923
fxRuby->state = FXRuby_State_IncreaseStageDeform;
924
PhantomRuby_PlaySfx(RUBYSFX_ATTACK1);
925
Camera_ShakeScreen(0, 4, 4);
926
Music_FadeOut(0.025);
927
host->storedTimer = host->timer;
928
host->values[0] = 1;
929
}
930
}
931
else {
932
host->storedTimer = host->timer;
933
}
934
935
if (host->timer >= host->storedTimer + 32) {
936
EntityPlayer *players[2];
937
players[0] = player;
938
players[1] = buddy;
939
940
for (int32 i = 0, angle = 0; angle < 0x80; ++i, angle += 0x40) {
941
if (!players[i])
942
break;
943
EntityPlayer *playerPtr = players[i];
944
RSDK.SetSpriteAnimation(playerPtr->aniFrames, ANI_FAN, &playerPtr->animator, false, 0);
945
946
playerPtr->position.x += (playerPtr->position.x - playerPtr->position.x) >> 3;
947
playerPtr->position.y +=
948
(0xA00 * RSDK.Sin256(2 * (host->timer + angle - host->storedTimer)) + ruby->position.y - playerPtr->position.y) >> 3;
949
playerPtr->tileCollisions = TILECOLLISION_NONE;
950
playerPtr->velocity.x = 0;
951
playerPtr->velocity.y = 0;
952
playerPtr->state = Player_State_Static;
953
}
954
}
955
}
956
}
957
else {
958
if (fxRuby->fadeWhite >= 512) {
959
if (fxRuby->fadeBlack >= 512) {
960
if (host->timer >= host->storedTimer + 150) {
961
return true;
962
}
963
}
964
else {
965
fxRuby->fadeBlack += 16;
966
}
967
}
968
else {
969
fxRuby->fadeWhite += 16;
970
}
971
}
972
HeavyMystic_HandleParticleFX();
973
974
return false;
975
}
976
977
bool32 EncoreIntro_Cutscene_LoadGHZ(EntityCutsceneSeq *host)
978
{
979
RSDK_THIS(EncoreIntro);
980
Player->playerCount = 2;
981
SaveGame_SavePlayerState();
982
SaveGame_GetSaveRAM()->saveState = SAVEGAME_INPROGRESS; // save file is active
983
RSDK.SetScene("Cutscenes", "Green Hill Zone");
984
EncoreIntro->awaitingSaveFinish = true;
985
SaveGame_SaveFile(EncoreIntro_SaveGameCB);
986
if (EncoreIntro->awaitingSaveFinish) {
987
UIWaitSpinner_StartWait();
988
if (EncoreIntro->awaitingSaveFinish)
989
return true;
990
}
991
RSDK.LoadScene();
992
destroyEntity(self);
993
994
return false;
995
}
996
997
bool32 EncoreIntro_Cutscene_AwaitSaveFinish(EntityCutsceneSeq *host)
998
{
999
RSDK_THIS(EncoreIntro);
1000
if (!EncoreIntro->awaitingSaveFinish) {
1001
RSDK.LoadScene();
1002
destroyEntity(self);
1003
}
1004
return false;
1005
}
1006
1007
bool32 EncoreIntro_Cutscene_FadeOutAndReset(EntityCutsceneSeq *host)
1008
{
1009
EntityFXRuby *fxRuby = EncoreIntro->fxRuby;
1010
1011
if (fxRuby->fadeBlack >= 512) {
1012
EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
1013
EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);
1014
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
1015
destroyEntity(EncoreIntro->rubyPortal);
1016
1017
ruby->state = EncoreIntro_PhantomRuby_EscapeRight;
1018
ruby->inkEffect = INK_NONE;
1019
1020
player->inkEffect = INK_NONE;
1021
RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
1022
player->state = Player_State_Air;
1023
player->up = true;
1024
player->camera = NULL;
1025
host->values[0] = true;
1026
player->stateInput = Player_Input_P1;
1027
player->tileCollisions = TILECOLLISION_DOWN;
1028
player->onGround = true;
1029
player->state = Player_State_Ground;
1030
player->camera = camera;
1031
1032
Camera_SetupLerp(CAMERA_LERP_NORMAL, 0, camera->position.x, camera->position.y, 0);
1033
camera->target = (Entity *)player;
1034
camera->state = Camera_State_FollowXY;
1035
1036
Hitbox *playerHitbox = Player_GetHitbox(player);
1037
while (
1038
!RSDK.ObjectTileGrip(player, player->collisionLayers, player->collisionMode, player->collisionPlane, 0, playerHitbox->bottom << 16, 8)) {
1039
player->position.y += 0x80000;
1040
}
1041
1042
if (!SceneInfo->minutes && !SceneInfo->seconds) {
1043
EntityTitleCard *titleCard = (EntityTitleCard *)CutsceneSeq_GetEntity(TitleCard->classID);
1044
titleCard->active = ACTIVE_NORMAL;
1045
titleCard->state = TitleCard_State_SetupBGElements;
1046
titleCard->stateDraw = TitleCard_Draw_SlideIn;
1047
}
1048
1049
Vector2 size;
1050
RSDK.GetLayerSize(Zone->fgLayer[0], &size, true);
1051
Zone->playerBoundsR[0] = size.x;
1052
Zone->cameraBoundsR[0] = size.x;
1053
Zone->playerBoundActiveR[0] = true;
1054
1055
foreach_all(HUD, hud)
1056
{
1057
hud->vsStates[0] = HUD_State_MoveIn;
1058
hud->state = hud->vsStates[0];
1059
}
1060
1061
foreach_all(SchrodingersCapsule, capsule)
1062
{
1063
ruby->position.x = capsule->position.x;
1064
ruby->startPos.y = capsule->position.y - 0x800000;
1065
ruby->state = EncoreIntro_PhantomRuby_OscillateFX;
1066
}
1067
1068
foreach_active(Animals, animal) { destroyEntity(animal); }
1069
return true;
1070
}
1071
else {
1072
fxRuby->fadeBlack += 16;
1073
}
1074
1075
return false;
1076
}
1077
1078
bool32 EncoreIntro_Cutscene_FadeInAndStart(EntityCutsceneSeq *host)
1079
{
1080
EntityFXRuby *fxRuby = EncoreIntro->fxRuby;
1081
1082
if (fxRuby->fadeBlack <= 0) {
1083
host->stateID = 6; // EncoreIntro_Cutscene_AIZEncore
1084
host->timer = 0;
1085
}
1086
else {
1087
fxRuby->fadeBlack -= 16;
1088
}
1089
1090
return false;
1091
}
1092
1093
// Called as skipCB when mystic shows up with the pile
1094
bool32 EncoreIntro_Cutscene_SkipAndFadeOut(EntityCutsceneSeq *host)
1095
{
1096
EntityFXRuby *fxRuby = EncoreIntro->fxRuby;
1097
1098
if (fxRuby->fadeWhite < 512) {
1099
fxRuby->fadeWhite += 16;
1100
}
1101
else if (fxRuby->fadeBlack < 512) {
1102
fxRuby->fadeBlack += 16;
1103
}
1104
else if (host->timer >= 150) {
1105
// Same as EncoreIntro_Cutscene_LoadGHZ but setting GHZ+1 to skip the intro cutscene
1106
RSDK_THIS(EncoreIntro);
1107
Player->playerCount = 2;
1108
SaveGame_SavePlayerState();
1109
SaveGame_GetSaveRAM()->saveState = SAVEGAME_INPROGRESS; // save file is active
1110
RSDK.SetScene("Encore Mode", "Green Hill Zone+ 1");
1111
EncoreIntro->awaitingSaveFinish = true;
1112
SaveGame_SaveFile(EncoreIntro_SaveGameCB);
1113
if (EncoreIntro->awaitingSaveFinish) {
1114
UIWaitSpinner_StartWait();
1115
if (EncoreIntro->awaitingSaveFinish)
1116
return true;
1117
}
1118
RSDK.LoadScene();
1119
destroyEntity(self);
1120
}
1121
1122
return false;
1123
}
1124
1125
void EncoreIntro_SaveGameCB(bool32 success)
1126
{
1127
UIWaitSpinner_FinishWait();
1128
EncoreIntro->awaitingSaveFinish = false;
1129
}
1130
1131
void EncoreIntro_PhantomRuby_OscillateFX(void)
1132
{
1133
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
1134
EntityFXRuby *fxRuby = EncoreIntro->fxRuby;
1135
1136
ruby->position.y = BadnikHelpers_Oscillate(ruby->startPos.y, 2, 10);
1137
fxRuby->position.x = ruby->position.x;
1138
fxRuby->position.y = ruby->position.y;
1139
}
1140
void EncoreIntro_PhantomRuby_EscapeRight(void)
1141
{
1142
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
1143
1144
if (ruby->velocity.x < 0x40000)
1145
ruby->velocity.x += 0x1800;
1146
ruby->angle += 2;
1147
ruby->position.x += ruby->velocity.x;
1148
ruby->position.y = (RSDK.Sin256(ruby->angle) << 10) + ruby->startPos.y;
1149
}
1150
void EncoreIntro_PhantomRuby_Fall(void)
1151
{
1152
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
1153
1154
ruby->position.x += ruby->velocity.x;
1155
ruby->position.y += ruby->velocity.y;
1156
ruby->velocity.y += 0x3800;
1157
}
1158
void EncoreIntro_PhantomRuby_CapsuleRiseUp(void)
1159
{
1160
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
1161
1162
ruby->active = ACTIVE_NORMAL;
1163
if (ruby->velocity.y <= -0x60000) {
1164
ruby->velocity.y = -ruby->velocity.y;
1165
ruby->velocity.x = 0;
1166
ruby->state = EncoreIntro_PhantomRuby_CapsuleFallDown;
1167
}
1168
else {
1169
ruby->position.y += ruby->velocity.y;
1170
ruby->velocity.y -= 0x3800;
1171
}
1172
RSDK.SetChannelAttributes(Music->channelID, 1.0 - (((ruby->startPos.y - ruby->position.y) >> 16) / 120.0), 0.0, 1.0);
1173
}
1174
void EncoreIntro_PhantomRuby_CapsuleFallDown(void)
1175
{
1176
EntityPhantomRuby *ruby = EncoreIntro->phantomRuby;
1177
1178
if (ruby->velocity.x >= 60) {
1179
if (ruby->velocity.y <= 0) {
1180
ruby->velocity.y = 0;
1181
ruby->active = ACTIVE_BOUNDS;
1182
ruby->state = EncoreIntro_PhantomRuby_OscillateFX;
1183
}
1184
else {
1185
ruby->velocity.y -= 0x3800;
1186
ruby->position.y += ruby->velocity.y;
1187
}
1188
RSDK.SetChannelAttributes(Music->channelID, 1.0 - (((ruby->startPos.y - ruby->position.y) >> 16) / 120.0), 0.0, 1.0);
1189
}
1190
else {
1191
ruby->velocity.x++;
1192
}
1193
}
1194
1195
void EncoreIntro_PlayerState_BuddySel(void)
1196
{
1197
RSDK_THIS(Player);
1198
self->groundVel = CLAMP(self->groundVel, -0x20000, 0x20000);
1199
Player_State_Ground();
1200
}
1201
1202
void EncoreIntro_PlayerState_HandleAir(void)
1203
{
1204
Player_HandleAirFriction();
1205
Player_HandleAirMovement();
1206
}
1207
1208
void EncoreIntro_PlayerInput_BuddySel(void)
1209
{
1210
RSDK_THIS(Player);
1211
1212
ControllerInfo[CONT_P1].keyX.down = false;
1213
ControllerInfo[CONT_P1].keyX.press = false;
1214
ControllerInfo[CONT_P1].keyY.down = false;
1215
ControllerInfo[CONT_P1].keyY.press = false;
1216
ControllerInfo[CONT_P1].keyZ.down = false;
1217
ControllerInfo[CONT_P1].keyZ.press = false;
1218
ControllerInfo[CONT_P1].keyStart.down = false;
1219
ControllerInfo[CONT_P1].keyStart.press = false;
1220
ControllerInfo[CONT_P1].keySelect.down = false;
1221
ControllerInfo[CONT_P1].keySelect.press = false;
1222
1223
Player_Input_P1();
1224
1225
self->up = false;
1226
self->down = false;
1227
self->jumpPress = false;
1228
self->jumpHold = false;
1229
}
1230
1231
#if GAME_INCLUDE_EDITOR
1232
void EncoreIntro_EditorDraw(void)
1233
{
1234
RSDK_THIS(EncoreIntro);
1235
CutsceneRules_DrawCutsceneBounds(self, &self->size);
1236
}
1237
1238
void EncoreIntro_EditorLoad(void) {}
1239
#endif
1240
1241
void EncoreIntro_Serialize(void) { RSDK_EDITABLE_VAR(EncoreIntro, VAR_VECTOR2, size); }
1242
#endif
1243
1244