Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/UFO/SpecialClear.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: SpecialClear Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectSpecialClear *SpecialClear;
11
12
void SpecialClear_Update(void) {}
13
14
void SpecialClear_LateUpdate(void)
15
{
16
RSDK_THIS(SpecialClear);
17
18
StateMachine_Run(self->state);
19
}
20
21
void SpecialClear_StaticUpdate(void) {}
22
23
void SpecialClear_Draw(void)
24
{
25
RSDK_THIS(SpecialClear);
26
27
Vector2 vertPos[4];
28
Vector2 drawPos;
29
30
int32 centerX = ScreenInfo->center.x << 16;
31
drawPos.x = centerX - 0x600000;
32
33
// Draw Emeralds
34
for (int32 i = 0; i < 7; ++i) {
35
int32 frame = 7;
36
if (SaveGame_GetEmerald(i))
37
frame = i;
38
self->emeraldsAnimator.frameID = frame;
39
drawPos.y = self->emeraldPositions[i];
40
RSDK.DrawSprite(&self->emeraldsAnimator, &drawPos, true);
41
drawPos.x += 0x200000;
42
}
43
44
drawPos.x = self->messagePos2.x;
45
drawPos.y = self->messagePos2.y;
46
drawPos.x = centerX + 2 * drawPos.x;
47
vertPos[0].x = drawPos.x - 0x740000;
48
vertPos[0].y = drawPos.y - 0x140000;
49
vertPos[1].x = 0x680000 + drawPos.x;
50
vertPos[2].x = 0x780000 + drawPos.x;
51
vertPos[3].x = drawPos.x - 0x640000;
52
vertPos[1].y = drawPos.y - 0x140000;
53
vertPos[2].y = drawPos.y - 0x40000;
54
vertPos[3].y = drawPos.y - 0x40000;
55
RSDK.DrawFace(vertPos, 4, 0x00, 0x00, 0x00, 0xFF, INK_NONE);
56
57
if (self->messageType > SC_MSG_SPECIALCLEAR) {
58
drawPos.x = self->messagePos1.x;
59
drawPos.y = self->messagePos1.y;
60
drawPos.x = centerX + 2 * drawPos.x;
61
vertPos[0].x = drawPos.x - 0x740000;
62
vertPos[0].y = drawPos.y + 0x1C0000;
63
vertPos[1].x = 0x680000 + drawPos.x;
64
vertPos[2].x = 0x780000 + drawPos.x;
65
vertPos[3].x = drawPos.x - 0x640000;
66
vertPos[1].y = drawPos.y + 0x1C0000;
67
vertPos[2].y = drawPos.y + 0x2C0000;
68
vertPos[3].y = drawPos.y + 0x2C0000;
69
RSDK.DrawFace(vertPos, 4, 0x00, 0x00, 0x00, 0xFF, INK_NONE);
70
}
71
72
drawPos.x = self->messagePos1.x;
73
drawPos.y = self->messagePos1.y;
74
drawPos.x += centerX;
75
switch (self->messageType) {
76
case SC_MSG_SPECIALCLEAR:
77
self->playerNameAnimator.frameID = 0;
78
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
79
break;
80
81
case SC_MSG_GOTEMERALD:
82
self->playerNameAnimator.frameID = 1;
83
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
84
85
self->playerNameAnimator.frameID = 2;
86
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
87
88
drawPos.x = self->messagePos2.x;
89
drawPos.y = self->messagePos2.y;
90
drawPos.x += centerX;
91
self->playerNameAnimator.frameID = 3;
92
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
93
break;
94
95
case SC_MSG_ALLEMERALDS:
96
self->playerNameAnimator.frameID = 4;
97
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
98
99
self->playerNameAnimator.frameID = 5;
100
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
101
102
drawPos.x = self->messagePos2.x;
103
drawPos.y = self->messagePos2.y;
104
drawPos.x += centerX;
105
self->playerNameAnimator.frameID = 6;
106
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
107
break;
108
109
case SC_MSG_SUPER:
110
self->playerNameAnimator.frameID = 7;
111
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
112
113
self->playerNameAnimator.frameID = 8;
114
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
115
116
self->playerNameAnimator.frameID = 9;
117
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
118
119
drawPos.x = self->messagePos2.x;
120
drawPos.y = self->messagePos2.y;
121
drawPos.x += centerX;
122
self->playerNameAnimator.frameID = 10;
123
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
124
125
self->playerNameAnimator.frameID = 11;
126
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
127
128
self->playerNameAnimator.frameID = 13;
129
RSDK.DrawSprite(&self->playerNameAnimator, &drawPos, true);
130
break;
131
132
default: break;
133
}
134
drawPos.x = self->scoreBonusPos.x;
135
drawPos.y = self->scoreBonusPos.y;
136
drawPos.x += centerX - 0x560000;
137
self->bonusAnimator.frameID = 4;
138
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
139
140
self->bonusAnimator.frameID = 6;
141
drawPos.x += 0x660000;
142
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
143
144
drawPos.x += 0x430000;
145
SpecialClear_DrawNumbers(&drawPos, self->score);
146
147
drawPos.x = self->ringBonusPos.x;
148
drawPos.y = self->ringBonusPos.y;
149
drawPos.x += centerX - 0x560000;
150
self->bonusAnimator.frameID = 0;
151
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
152
153
drawPos.x += 3276800;
154
self->bonusAnimator.frameID = 3;
155
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
156
157
self->bonusAnimator.frameID = 6;
158
drawPos.x += 3407872;
159
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
160
161
drawPos.x += 0x430000;
162
SpecialClear_DrawNumbers(&drawPos, self->ringBonus);
163
164
if (self->isBSS) {
165
drawPos.x = self->perfectBonusPos.x;
166
drawPos.y = self->perfectBonusPos.y;
167
drawPos.x += centerX - 0x560000;
168
self->bonusAnimator.frameID = 1;
169
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
170
171
drawPos.x += 0x320000;
172
self->bonusAnimator.frameID = 3;
173
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
174
175
self->bonusAnimator.frameID = 6;
176
drawPos.x += 0x340000;
177
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
178
179
drawPos.x += 0x430000;
180
SpecialClear_DrawNumbers(&drawPos, self->perfectBonus);
181
}
182
else {
183
drawPos.x = self->machBonusPos.x;
184
drawPos.y = self->machBonusPos.y;
185
drawPos.x += centerX - 0x560000;
186
self->bonusAnimator.frameID = 2;
187
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
188
189
drawPos.x += 0x320000;
190
self->bonusAnimator.frameID = 3;
191
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
192
193
self->bonusAnimator.frameID = 6;
194
drawPos.x += 0x340000;
195
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
196
197
drawPos.x += 0x430000;
198
SpecialClear_DrawNumbers(&drawPos, self->machBonus);
199
}
200
201
if (self->hasContinues) {
202
drawPos.x = self->continuePos.x;
203
drawPos.y = self->continuePos.y;
204
drawPos.x += centerX - 0x560000;
205
self->bonusAnimator.frameID = 5;
206
RSDK.DrawSprite(&self->bonusAnimator, &drawPos, true);
207
208
if (self->continueIconVisible) {
209
drawPos.x += 0xB00000;
210
drawPos.y += 0xA0000;
211
RSDK.DrawSprite(&self->continueAnimator, &drawPos, true);
212
}
213
}
214
215
if (self->showFade)
216
RSDK.FillScreen(self->fillColor, self->timer, self->timer - 128, self->timer - 256);
217
}
218
219
void SpecialClear_Create(void *data)
220
{
221
RSDK_THIS(SpecialClear);
222
223
if (!SceneInfo->inEditor) {
224
self->active = ACTIVE_NORMAL;
225
self->visible = true;
226
self->drawGroup = 14;
227
self->timer = 512;
228
self->fillColor = 0xF0F0F0;
229
self->showFade = true;
230
self->state = SpecialClear_State_SetupDelay;
231
232
if (RSDK.CheckSceneFolder("SpecialBS")) {
233
// Blue Spheres...?
234
// This screen doesn't show up in regular BSS gameplay
235
236
self->isBSS = true;
237
self->ringBonus = 100 * BSS_Setup->rings;
238
if (!BSS_Setup->ringCount)
239
self->perfectBonus = 50000;
240
241
self->messageType = SC_MSG_SPECIALCLEAR;
242
}
243
else {
244
RSDK.CopyPalette(7, 0, 0, 0, 128);
245
246
self->isBSS = false;
247
self->ringBonus = 100 * UFO_Setup->rings;
248
self->machBonus = 1000 * (UFO_Setup->machLevel + 10 * UFO_Setup->scoreBonus);
249
250
if (globals->gameMode < MODE_TIMEATTACK && self->machBonus + self->ringBonus >= 10000)
251
self->hasContinues = true;
252
253
SaveRAM *saveRAM = SaveGame_GetSaveRAM();
254
self->score = saveRAM->score;
255
self->score1UP = saveRAM->score1UP;
256
self->lives = saveRAM->lives;
257
if (SaveGame_AllChaosEmeralds())
258
self->messageType = SC_MSG_ALLEMERALDS;
259
else
260
self->messageType = !UFO_Setup->timedOut ? SC_MSG_GOTEMERALD : SC_MSG_SPECIALCLEAR;
261
}
262
263
// "Player Got A"
264
self->messagePos1.x = 0x1400000;
265
self->messagePos1.y = 0x580000;
266
267
// "Chaos Emerald"
268
self->messagePos2.x = -0x1400000;
269
self->messagePos2.y = 0x700000;
270
271
self->scoreBonusPos.x = 0x1E80000;
272
self->scoreBonusPos.y = 0x8C0000;
273
274
self->ringBonusPos.x = 0x3080000;
275
self->ringBonusPos.y = 0xAC0000;
276
277
self->machBonusPos.x = 0x4280000;
278
self->machBonusPos.y = 0xBC0000;
279
280
// this is still here and fully functional, however this object is never shown after BSS, so its unused
281
self->perfectBonusPos.x = 0x4280000;
282
self->perfectBonusPos.y = 0xBC0000;
283
self->continuePos.x = 0x5480000;
284
self->continuePos.y = 0xCC0000;
285
286
RSDK.CopyPalette(1, 0, 0, 128, 48);
287
288
for (int32 i = 0; i < 7; ++i) {
289
self->emeraldPositions[i] = 0x1100000 + (i * 0x200000);
290
self->emeraldSpeeds[i] = -0xA0000 + (i * -0xA000);
291
}
292
293
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_BONUS, &self->bonusAnimator, true, 0);
294
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_NUMBERS, &self->numbersAnimator, true, 0);
295
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_EMERALDS, &self->emeraldsAnimator, true, 0);
296
switch (GET_CHARACTER_ID(1)) {
297
default:
298
case ID_SONIC: RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_SONIC, &self->playerNameAnimator, true, 0);
299
#if MANIA_USE_PLUS
300
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_CONTINUE, &self->continueAnimator, true, SC_ANI_SONIC);
301
#else
302
RSDK.SetSpriteAnimation(SpecialClear->continueFrames, 0, &self->continueAnimator, true, SC_ANI_TAILS);
303
#endif
304
break;
305
306
case ID_TAILS: RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_TAILS, &self->playerNameAnimator, true, 0);
307
#if MANIA_USE_PLUS
308
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_CONTINUE, &self->continueAnimator, true, SC_ANI_TAILS);
309
#else
310
RSDK.SetSpriteAnimation(SpecialClear->continueFrames, 0, &self->continueAnimator, true, SC_ANI_TAILS);
311
#endif
312
break;
313
314
case ID_KNUCKLES: RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_KNUX, &self->playerNameAnimator, true, 0);
315
#if MANIA_USE_PLUS
316
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_CONTINUE, &self->continueAnimator, true, SC_ANI_KNUX);
317
#else
318
RSDK.SetSpriteAnimation(SpecialClear->continueFrames, 0, &self->continueAnimator, true, SC_ANI_TAILS);
319
#endif
320
break;
321
322
#if MANIA_USE_PLUS
323
case ID_MIGHTY:
324
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_MIGHTY, &self->playerNameAnimator, true, 0);
325
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_CONTINUE, &self->continueAnimator, true, 3);
326
break;
327
328
case ID_RAY:
329
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_RAY, &self->playerNameAnimator, true, 0);
330
RSDK.SetSpriteAnimation(SpecialClear->aniFrames, SC_ANI_CONTINUE, &self->continueAnimator, true, SC_ANI_RAY);
331
break;
332
#endif
333
}
334
}
335
}
336
337
void SpecialClear_StageLoad(void)
338
{
339
SpecialClear->aniFrames = RSDK.LoadSpriteAnimation("Special/Results.bin", SCOPE_STAGE);
340
#if !MANIA_USE_PLUS
341
SpecialClear->continueFrames = RSDK.LoadSpriteAnimation("Players/Continue.bin", SCOPE_STAGE);
342
#endif
343
344
SpecialClear->sfxScoreAdd = RSDK.GetSfx("Global/ScoreAdd.wav");
345
SpecialClear->sfxScoreTotal = RSDK.GetSfx("Global/ScoreTotal.wav");
346
SpecialClear->sfxEvent = RSDK.GetSfx("Special/Event.wav");
347
SpecialClear->sfxSpecialWarp = RSDK.GetSfx("Global/SpecialWarp.wav");
348
SpecialClear->sfxContinue = RSDK.GetSfx("Special/Continue.wav");
349
SpecialClear->sfxEmerald = RSDK.GetSfx("Special/Emerald.wav");
350
}
351
352
void SpecialClear_DrawNumbers(Vector2 *pos, int32 value)
353
{
354
RSDK_THIS(SpecialClear);
355
356
int32 cnt = value;
357
358
int32 digitCount = value ? 0 : 1;
359
while (cnt > 0) {
360
++digitCount;
361
cnt /= 10;
362
}
363
364
int32 digit = 1;
365
while (digitCount) {
366
self->numbersAnimator.frameID = value / digit % 10;
367
RSDK.DrawSprite(&self->numbersAnimator, pos, true);
368
digit *= 10;
369
pos->x -= 0x90000;
370
--digitCount;
371
}
372
}
373
374
void SpecialClear_GiveScoreBonus(int32 score)
375
{
376
RSDK_THIS(SpecialClear);
377
378
self->score += score;
379
if (self->score > 9999999)
380
self->score = 9999999;
381
382
#if MANIA_USE_PLUS
383
if (globals->gameMode == MODE_ENCORE)
384
return;
385
#endif
386
387
if (self->score >= self->score1UP) {
388
if (self->lives < 99)
389
self->lives++;
390
391
Music_PlayJingle(TRACK_1UP);
392
393
Music->nextTrack = TRACK_NONE;
394
while (self->score1UP <= self->score) self->score1UP += 50000;
395
}
396
}
397
398
#if MANIA_USE_PLUS
399
void SpecialClear_SaveCB(bool32 success)
400
{
401
RSDK_THIS(SpecialClear);
402
403
UIWaitSpinner_FinishWait();
404
self->saveInProgress = false;
405
}
406
#else
407
void SpecialClear_SaveCB(void)
408
{
409
RSDK_THIS(SpecialClear);
410
411
UIWaitSpinner_FinishWait();
412
self->saveInProgress = false;
413
}
414
#endif
415
416
void SpecialClear_State_SetupDelay(void)
417
{
418
RSDK_THIS(SpecialClear);
419
420
if (self->timer <= 0) {
421
self->timer = 0;
422
self->showFade = false;
423
self->state = SpecialClear_State_EnterText;
424
425
Music_PlayTrack(TRACK_ACTCLEAR);
426
}
427
else {
428
self->timer -= 16;
429
}
430
}
431
432
void SpecialClear_State_EnterText(void)
433
{
434
RSDK_THIS(SpecialClear);
435
436
if (self->messagePos1.x > 0)
437
self->messagePos1.x -= 0x100000;
438
439
if (self->messagePos2.x < 0) {
440
self->messagePos2.x += 0x100000;
441
}
442
443
if (++self->timer == 48) {
444
self->timer = 0;
445
self->state = SpecialClear_State_AdjustText;
446
}
447
}
448
449
void SpecialClear_State_AdjustText(void)
450
{
451
RSDK_THIS(SpecialClear);
452
453
self->messagePos1.y -= 0x10000;
454
self->messagePos2.y -= 0x10000;
455
456
if (++self->timer == 48) {
457
self->timer = 0;
458
self->state = SpecialClear_State_EnterBonuses;
459
}
460
}
461
462
void SpecialClear_HandleEmeraldAppear(void)
463
{
464
RSDK_THIS(SpecialClear);
465
466
int32 stopPos = self->messageType == SC_MSG_SPECIALCLEAR ? 0x680000 : 0x700000;
467
468
for (int32 i = 0; i < 7; ++i) {
469
self->emeraldSpeeds[i] += 0x4000;
470
self->emeraldPositions[i] += self->emeraldSpeeds[i];
471
472
if (self->emeraldPositions[i] > stopPos && self->emeraldSpeeds[i] >= 0) {
473
self->emeraldPositions[i] = stopPos;
474
self->emeraldSpeeds[i] = -(self->emeraldSpeeds[i] >> 1);
475
}
476
}
477
}
478
479
void SpecialClear_State_EnterBonuses(void)
480
{
481
RSDK_THIS(SpecialClear);
482
483
if (self->scoreBonusPos.x > 0)
484
self->scoreBonusPos.x -= 0x100000;
485
486
if (self->ringBonusPos.x > 0)
487
self->ringBonusPos.x -= 0x100000;
488
489
if (self->perfectBonusPos.x > 0)
490
self->perfectBonusPos.x -= 0x100000;
491
492
if (self->machBonusPos.x > 0)
493
self->machBonusPos.x -= 0x100000;
494
495
if (self->continuePos.x <= 0) {
496
if (self->messageType == SC_MSG_ALLEMERALDS) {
497
API_UnlockAchievement(&achievementList[ACH_EMERALDS]);
498
}
499
500
self->state = SpecialClear_State_ScoreShownDelay;
501
}
502
else {
503
self->continuePos.x -= 0x100000;
504
}
505
506
SpecialClear_HandleEmeraldAppear();
507
}
508
509
void SpecialClear_State_ScoreShownDelay(void)
510
{
511
RSDK_THIS(SpecialClear);
512
513
if (++self->timer == 120) {
514
self->timer = 0;
515
self->state = SpecialClear_State_TallyScore;
516
517
if (self->messageType != SC_MSG_SPECIALCLEAR)
518
RSDK.PlaySfx(SpecialClear->sfxEmerald, false, 0xFF);
519
}
520
521
SpecialClear_HandleEmeraldAppear();
522
}
523
524
void SpecialClear_State_TallyScore(void)
525
{
526
RSDK_THIS(SpecialClear);
527
528
if (self->ringBonus > 0) {
529
self->ringBonus -= 100;
530
SpecialClear_GiveScoreBonus(100);
531
}
532
533
if (self->perfectBonus > 0) {
534
self->perfectBonus -= 100;
535
SpecialClear_GiveScoreBonus(100);
536
}
537
538
if (self->machBonus > 0) {
539
self->machBonus -= 100;
540
SpecialClear_GiveScoreBonus(100);
541
}
542
543
if (ControllerInfo->keyA.press || ControllerInfo->keyStart.press) {
544
SpecialClear_GiveScoreBonus(self->machBonus + self->ringBonus + self->perfectBonus);
545
self->ringBonus = 0;
546
self->perfectBonus = 0;
547
self->machBonus = 0;
548
}
549
550
if (self->machBonus + self->ringBonus + self->perfectBonus <= 0) {
551
self->timer = 0;
552
553
if (self->hasContinues)
554
self->state = SpecialClear_State_ShowTotalScore_Continues;
555
else
556
self->state = SpecialClear_State_ShowTotalScore_NoContinues;
557
558
RSDK.PlaySfx(SpecialClear->sfxScoreTotal, false, 0xFF);
559
}
560
else if (++self->timer == 2) {
561
self->timer = 0;
562
RSDK.PlaySfx(SpecialClear->sfxScoreAdd, false, 0xFF);
563
}
564
}
565
566
void SpecialClear_State_ShowTotalScore_Continues(void)
567
{
568
RSDK_THIS(SpecialClear);
569
570
if (++self->timer == 120) {
571
RSDK.PlaySfx(SpecialClear->sfxContinue, false, 0xFF);
572
573
if (globals->continues < 25)
574
globals->continues++;
575
}
576
else if (self->timer > 120) {
577
self->continueIconVisible = (self->timer >> 3) & 1;
578
}
579
580
if (self->timer == 360) {
581
self->timer = 0;
582
583
SaveRAM *saveRAM = SaveGame_GetSaveRAM();
584
saveRAM->score = self->score;
585
globals->restartScore = self->score;
586
saveRAM->score1UP = self->score1UP;
587
saveRAM->lives = self->lives;
588
#if MANIA_USE_PLUS
589
saveRAM->continues = globals->continues;
590
saveRAM->characterFlags = globals->characterFlags;
591
saveRAM->stock = globals->stock;
592
saveRAM->playerID = globals->playerID;
593
#endif
594
595
if (SaveGame_AllChaosEmeralds()) {
596
self->state = SpecialClear_State_ExitFinishMessage;
597
}
598
else {
599
self->timer = 0;
600
self->showFade = true;
601
self->state = SpecialClear_State_ExitResults;
602
603
RSDK.PlaySfx(SpecialClear->sfxSpecialWarp, false, 0xFF);
604
}
605
}
606
}
607
608
void SpecialClear_State_ShowTotalScore_NoContinues(void)
609
{
610
RSDK_THIS(SpecialClear);
611
612
if (++self->timer == 120) {
613
self->timer = 0;
614
SaveRAM *saveRAM = SaveGame_GetSaveRAM();
615
saveRAM->score = self->score;
616
globals->restartScore = self->score;
617
618
if (SaveGame_AllChaosEmeralds()) {
619
self->state = SpecialClear_State_ExitFinishMessage;
620
}
621
else {
622
self->timer = 0;
623
self->showFade = true;
624
RSDK.PlaySfx(SpecialClear->sfxSpecialWarp, false, 0xFF);
625
self->state = SpecialClear_State_ExitResults;
626
}
627
}
628
}
629
630
void SpecialClear_State_ExitFinishMessage(void)
631
{
632
RSDK_THIS(SpecialClear);
633
634
self->messagePos1.x += 0x180000;
635
self->messagePos2.x -= 0x180000;
636
637
if (++self->timer == 30) {
638
self->timer = 0;
639
self->messageType = SC_MSG_SUPER;
640
self->state = SpecialClear_State_EnterSuperMessage;
641
}
642
}
643
644
void SpecialClear_State_EnterSuperMessage(void)
645
{
646
RSDK_THIS(SpecialClear);
647
648
if (self->messagePos1.x > 0)
649
self->messagePos1.x -= 0x180000;
650
651
if (self->messagePos2.x >= 0) {
652
RSDK.PlaySfx(SpecialClear->sfxEvent, false, 0xFF);
653
self->state = SpecialClear_State_ShowSuperMessage;
654
}
655
else {
656
self->messagePos2.x += 0x180000;
657
}
658
}
659
660
void SpecialClear_State_ShowSuperMessage(void)
661
{
662
RSDK_THIS(SpecialClear);
663
664
if (++self->timer == 160) {
665
self->timer = 0;
666
self->showFade = true;
667
RSDK.PlaySfx(SpecialClear->sfxSpecialWarp, false, 0xFF);
668
self->state = SpecialClear_State_ExitResults;
669
}
670
}
671
672
void SpecialClear_State_ExitFadeOut(void)
673
{
674
RSDK_THIS(SpecialClear);
675
676
if (self->fillColor) {
677
self->fillColor -= 0x080808;
678
}
679
else if (!self->saveInProgress) {
680
EntityMenuParam *param = MenuParam_GetParam();
681
682
if (param->bssSelection == BSS_SELECTION_EXTRAS) {
683
RSDK.SetScene("Presentation", "Menu");
684
RSDK.LoadScene();
685
}
686
else {
687
SaveRAM *saveRAM = SaveGame_GetSaveRAM();
688
#if MANIA_USE_PLUS
689
if (globals->gameMode == MODE_ENCORE)
690
RSDK.SetScene("Encore Mode", "");
691
else
692
#endif
693
RSDK.SetScene("Mania Mode", "");
694
695
SceneInfo->listPos = saveRAM->storedStageID;
696
RSDK.LoadScene();
697
}
698
}
699
}
700
701
void SpecialClear_State_ExitResults(void)
702
{
703
RSDK_THIS(SpecialClear);
704
705
if (self->timer >= 768) {
706
self->state = SpecialClear_State_ExitFadeOut;
707
708
if (globals->gameMode < MODE_TIMEATTACK && globals->saveSlotID != NO_SAVE_SLOT) {
709
self->saveInProgress = true;
710
UIWaitSpinner_StartWait();
711
GameProgress_TrackGameProgress(SpecialClear_SaveCB);
712
}
713
}
714
else {
715
self->timer += 8;
716
}
717
}
718
719
#if GAME_INCLUDE_EDITOR
720
void SpecialClear_EditorDraw(void) {}
721
722
void SpecialClear_EditorLoad(void) {}
723
#endif
724
725
void SpecialClear_Serialize(void) {}
726
727