Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-CD-2011-Script-Decompilation
Path: blob/main/Scripts/Special/StageFinish.txt
1319 views
1
//---------------Sonic CD Stage Finish Script-----------------//
2
//--------Scripted by Christian Whitehead 'The Taxman'--------//
3
//-------Unpacked By Rubberduckycooly's Script Unpacker-------//
4
5
// Aliases
6
#alias Object.Value0 : Object.Timer
7
#alias Object.Value5 : Object.TimeBonus
8
#alias Object.Value6 : Object.RingBonus
9
10
// This can be Coins bonus too, depending on the current mode
11
// For simplicity's sake, we're just going to continue calling it ExtraLives
12
#alias Object.Value7 : Object.ExtraLives
13
14
// All texts have their own X position values
15
#alias Object.XPos : Object.LineXPos0
16
#alias Object.Value1 : Object.LineXPos1
17
#alias Object.Value2 : Object.LineXPos2
18
#alias Object.Value3 : Object.LineXPos3
19
#alias Object.Value4 : Object.LineXPos4
20
21
// HUD Alias
22
#alias Object.Value1 : HUD.TimeSeconds
23
#alias Object.Value3 : HUD.Rings
24
25
// States
26
#alias 0 : STAGEFINISH_INIT
27
#alias 1 : STAGEFINISH_FADEOUT
28
#alias 2 : STAGEFINISH_FADEIN
29
#alias 3 : STAGEFINISH_SCROLLTEXT
30
#alias 4 : STAGEFINISH_DISPLAYTALLY
31
#alias 5 : STAGEFINISH_TALLYDOWN
32
#alias 6 : STAGEFINISH_DISPLAYFINAL
33
#alias 7 : STAGEFINISH_LOADNORMAL
34
#alias 8 : STAGEFINISH_LOADTIMEATTACK
35
#alias 9 : STAGEFINISH_LOADLEVELSELECT
36
#alias 10: STAGEFINISH_CHECKRETRYCOND
37
#alias 11: STAGEFINISH_SAVE
38
39
// Property Value - Results Type
40
// Changed by this object, as well as the things that may spawn it
41
#alias Object.PropertyValue : Object.ResultsType
42
43
// Character limit is rearing its head here, which is why we can only stick in a "T" to distinguish it from states
44
// Not what was planned, but not much we can do...
45
#alias 0 : STAGEFINISH_T_FAILURE
46
#alias 1 : STAGEFINISH_T_STONEOBTAINED
47
#alias 2 : STAGEFINISH_T_ALLSTONESOBTAINED
48
49
// Player Aliases
50
#alias 0 : PLAYER_SONIC_A
51
#alias 1 : PLAYER_TAILS_A
52
53
// Game Mode Aliases
54
#alias 2 : MODE_TIMEATTACK
55
56
// Language Aliases
57
#alias 0 : LANG_ENGLISH
58
#alias 1 : LANG_FRENCH
59
#alias 2 : LANG_ITALIAN
60
#alias 3 : LANG_DEUTSCH
61
#alias 4 : LANG_SPANISH
62
#alias 5 : LANG_JAPANESE
63
64
// Global SFX
65
#alias 16 : SFX_G_SCOREADD
66
#alias 17 : SFX_G_SCORETOTAL
67
#alias 19 : SFX_G_SPECIALWARP
68
#alias 20 : SFX_G_1UP
69
#alias 21 : SFX_G_ACHIEVEMENT
70
71
// Ink Effect Aliases
72
#alias 2 : INK_ALPHA
73
74
// Soundtrack
75
#alias 0 : OST_JP
76
77
// Stage Aliases
78
#alias 0 : STAGE_P_TITLESCREEN
79
#alias 2 : STAGE_P_TIMEATTACK
80
#alias 4 : STAGE_P_SOUNDTEST
81
#alias 7 : STAGE_P_CREDITS
82
83
// Game Mode Aliases
84
#alias 1 : MODE_SAVEGAME
85
86
// Control Mode
87
#alias 0 : CONTROLMODE_NORMAL
88
89
90
sub ObjectMain
91
switch Object.State
92
case STAGEFINISH_INIT
93
// Setup the initial text line positions
94
Object.LineXPos0 = -799
95
Object.LineXPos1 = 1255
96
Object.LineXPos2 = 1319
97
Object.LineXPos3 = 1402
98
Object.LineXPos4 = 1466
99
100
Object.State = STAGEFINISH_FADEOUT
101
Object.Timer = 0
102
103
// Setup alpha, used for fading in the Time Stones
104
Object.Alpha = 0
105
Object.InkEffect = INK_ALPHA
106
107
#platform: Use_Origins
108
// Some stuff for Origins, where we back up some cool values
109
BackupSpecialStageListPos = SpecialStage.ListPos
110
BackupTimeStones = SpecialStage.TimeStones
111
#endplatform
112
113
// Don't wanna reward the Player if they just lost!
114
if Object.ResultsType > STAGEFINISH_T_FAILURE
115
116
// Setup the Time Bonus
117
Object.TimeBonus = HUD[4].TimeSeconds
118
Object.TimeBonus *= 200
119
120
// Set the corresponding Time Stone bit for this stage
121
TempValue0 = Stage.ActNo
122
TempValue0--
123
124
#platform: Use_Origins
125
// Origins changed it up a bit
126
SetBit(BackupTimeStones, TempValue0, true)
127
#endplatform
128
129
#platform: Use_Standalone
130
SetBit(SpecialStage.TimeStones, TempValue0, true)
131
#endplatform
132
else
133
Object.TimeBonus = 0
134
end if
135
136
#platform: Use_Origins
137
// Backup the Player's Rings
138
StageStatsUsabilityParam5 = HUD[4].Rings
139
140
// Setup the Ring Bonus
141
Object.RingBonus = HUD[4].Rings
142
Object.RingBonus *= 200
143
144
if BackupTimeStones < 127
145
TempValue0 = false
146
while TempValue0 == false
147
BackupSpecialStageListPos++
148
if BackupSpecialStageListPos > 6
149
BackupSpecialStageListPos = 0
150
end if
151
152
// Carrying through...
153
GetBit(TempValue1, BackupTimeStones, BackupSpecialStageListPos)
154
155
if TempValue1 == false
156
TempValue0 = true
157
end if
158
loop
159
else
160
TempValue0 = Stage.ListPos
161
TempValue0 %= 10
162
if TempValue0 == 9
163
Stage.ListPos--
164
end if
165
166
Good_Future_Count = 2
167
168
if Stage.PlayerListPos == PLAYER_SONIC
169
// If all Stones are collected, unlock the "Treasure Hunter" achievement
170
SetAchievement(8, 100)
171
end if
172
end if
173
174
// There used to be duplicate saving here, but Origins actually optimised that! How nice of them
175
176
// As a replacement for all that, let's just back up the Score instead
177
recScore = Player.Score
178
179
#endplatform
180
181
#platform: Use_Standalone
182
// Setup the Ring Bonus
183
Object.RingBonus = HUD[4].Rings
184
Object.RingBonus *= 200
185
186
Stage.ListPos = SpecialStage.NextZone
187
Stage.ActiveList = REGULAR_STAGE
188
189
if SpecialStage.TimeStones < 127
190
TempValue0 = false
191
while TempValue0 == false
192
SpecialStage.ListPos++
193
if SpecialStage.ListPos > 6
194
SpecialStage.ListPos = 0
195
end if
196
197
GetBit(TempValue1, SpecialStage.TimeStones, SpecialStage.ListPos)
198
if TempValue1 == false
199
TempValue0 = true
200
end if
201
loop
202
else
203
TempValue0 = Stage.ListPos
204
TempValue0 %= 10
205
if TempValue0 == 9
206
Stage.ListPos--
207
end if
208
209
Good_Future_Count = 2
210
211
if Stage.PlayerListPos == PLAYER_SONIC_A
212
// If all Stones are collected, unlock the "Treasure Hunter" achievement
213
SetAchievement(8, 100)
214
end if
215
end if
216
#endplatform
217
break
218
219
case STAGEFINISH_FADEOUT
220
if Object.Timer == 120
221
222
// More Origins changes
223
#platform: Use_Origins
224
Object.State = STAGEFINISH_CHECKRETRYCOND
225
#endplatform
226
227
#platform: Use_Standalone
228
Object.State = STAGEFINISH_FADEIN
229
Object.Timer = 256
230
231
if SpecialStage.TimeStones > 126 // 0b01111110, each '1' bit represents an obtained time stone
232
// If the player has all Stones, then turn this object into the "Got 'em all!!" variant
233
234
Object.ResultsType = STAGEFINISH_T_ALLSTONESOBTAINED
235
end if
236
237
PlayMusic(1)
238
#endplatform
239
else
240
Object.Timer++
241
Music.Volume--
242
243
if Object.Timer == 24
244
// Clear all game objects (aside from this one)
245
246
// First do all the reserved object slots
247
TempValue0 = 0
248
while TempValue0 < 30
249
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
250
TempValue0++
251
loop
252
253
// Then do all the game object slots
254
TempValue0++
255
while TempValue0 < 1184
256
ResetObjectEntity(TempValue0, TypeName[Blank Object], 0, 0, 0)
257
TempValue0++
258
loop
259
260
// Set all layers to not draw
261
Stage.ActiveLayer[0] = 9
262
Stage.ActiveLayer[1] = 9
263
Stage.ActiveLayer[2] = 9
264
Stage.ActiveLayer[3] = 9
265
266
// Lock the player from doing stuff too
267
Player.ControlMode = CONTROLMODE_NORMAL
268
KeyDown[1].Left = false
269
KeyDown[1].Right = false
270
Player.Direction = FACING_RIGHT
271
272
end if
273
end if
274
275
TempValue0 = Object.Timer
276
TempValue0 <<= 4
277
if TempValue0 > 255
278
TempValue0 = 255
279
end if
280
SetScreenFade(208, 255, 224, TempValue0)
281
break
282
283
case STAGEFINISH_FADEIN
284
Object.Timer -= 16
285
if Object.Timer == 0
286
Object.State = STAGEFINISH_SCROLLTEXT
287
288
#platform: Use_Origins
289
// We can actually set the stage now
290
Stage.ActiveList = REGULAR_STAGE
291
Stage.ListPos = SpecialStage.NextZone
292
#endplatform
293
end if
294
295
SetScreenFade(208, 255, 224, Object.Timer)
296
297
// Move in all the texts
298
299
TempValue0 = Screen.CenterX
300
TempValue0 -= 88
301
if Object.LineXPos0 < TempValue0
302
Object.LineXPos0 += 16
303
if Object.LineXPos0 > TempValue0
304
Object.LineXPos0 = TempValue0
305
end if
306
else
307
Object.LineXPos0 = TempValue0
308
end if
309
310
TempValue0++
311
if Object.LineXPos1 > TempValue0
312
Object.LineXPos1 -= 16
313
if Object.LineXPos1 < TempValue0
314
Object.LineXPos1 = TempValue0
315
end if
316
else
317
Object.LineXPos1 = TempValue0
318
end if
319
320
if Object.LineXPos2 > TempValue0
321
Object.LineXPos2 -= 16
322
if Object.LineXPos2 < TempValue0
323
Object.LineXPos2 = TempValue0
324
end if
325
else
326
Object.LineXPos2 = TempValue0
327
end if
328
329
if Object.LineXPos3 > TempValue0
330
Object.LineXPos3 -= 16
331
if Object.LineXPos3 < TempValue0
332
Object.LineXPos3 = TempValue0
333
end if
334
else
335
Object.LineXPos3 = TempValue0
336
end if
337
338
if Object.LineXPos4 > TempValue0
339
Object.LineXPos4 -= 16
340
if Object.LineXPos4 < TempValue0
341
Object.LineXPos4 = TempValue0
342
end if
343
else
344
Object.LineXPos4 = TempValue0
345
346
// All the texts are in place, proceed
347
// It should never happen, but if this is reached before the screen is fully faded in (see start of this state) then
348
// the screen will stay faded the entire durration of the results screen
349
350
Object.State = STAGEFINISH_DISPLAYTALLY
351
Object.Timer = 0
352
end if
353
break
354
355
case STAGEFINISH_SCROLLTEXT
356
// Moving the text in
357
358
TempValue0 = Screen.CenterX
359
TempValue0 -= 88
360
361
if Object.LineXPos0 < TempValue0
362
Object.LineXPos0 += 16
363
if Object.LineXPos0 > TempValue0
364
Object.LineXPos0 = TempValue0
365
end if
366
else
367
Object.LineXPos0 = TempValue0
368
end if
369
370
TempValue0++
371
if Object.LineXPos1 > TempValue0
372
Object.LineXPos1 -= 16
373
if Object.LineXPos1 < TempValue0
374
Object.LineXPos1 = TempValue0
375
end if
376
else
377
Object.LineXPos1 = TempValue0
378
end if
379
380
if Object.LineXPos2 > TempValue0
381
Object.LineXPos2 -= 16
382
if Object.LineXPos2 < TempValue0
383
Object.LineXPos2 = TempValue0
384
end if
385
else
386
Object.LineXPos2 = TempValue0
387
end if
388
389
if Object.LineXPos3 > TempValue0
390
Object.LineXPos3 -= 16
391
if Object.LineXPos3 < TempValue0
392
Object.LineXPos3 = TempValue0
393
end if
394
else
395
Object.LineXPos3 = TempValue0
396
end if
397
398
if Object.LineXPos4 > TempValue0
399
Object.LineXPos4 -= 16
400
if Object.LineXPos4 < TempValue0
401
Object.LineXPos4 = TempValue0
402
end if
403
else
404
Object.LineXPos4 = TempValue0
405
Object.State = STAGEFINISH_DISPLAYTALLY
406
Object.Timer = 0
407
end if
408
break
409
410
case STAGEFINISH_DISPLAYTALLY
411
// Waiting for a bit, to let the player see what they got
412
413
// Fade in the Stones
414
if Object.Alpha < 255
415
// TempValue0 is used to hold the target value since Object.Alpha is a byte, and therefore prone to overflowing if too much is added
416
417
TempValue0 = Object.Alpha
418
TempValue0 += 8
419
if TempValue0 > 255
420
TempValue0 = 255
421
end if
422
423
Object.Alpha = TempValue0
424
end if
425
426
// The different soundtrack jingles have different lenghts, so account for that
427
if Options.Soundtrack == OST_JP
428
Object.Timer++
429
if Object.Timer > 299
430
Object.Timer = 0
431
Object.State = STAGEFINISH_TALLYDOWN
432
end if
433
else
434
Object.Timer++
435
if Object.Timer > 429
436
Object.Timer = 0
437
Object.State = STAGEFINISH_TALLYDOWN
438
end if
439
end if
440
break
441
442
case STAGEFINISH_TALLYDOWN
443
// Tally up the bonuses, rings first then time
444
445
if Object.RingBonus > 0
446
Object.RingBonus -= 200
447
Player.Score += 200
448
449
if Object.RingBonus < 0
450
Player.Score += Object.RingBonus
451
Object.RingBonus = 0
452
end if
453
else
454
if Object.TimeBonus > 0
455
Object.TimeBonus -= 200
456
Player.Score += 200
457
458
if Object.TimeBonus < 0
459
Player.Score += Object.TimeBonus
460
Object.TimeBonus = 0
461
end if
462
end if
463
end if
464
465
if Player.Score >= Player.ScoreBonus
466
Object.ExtraLives++
467
468
#platform: Use_Origins
469
// In Origins, give either Coins or Lives based on the current mode
470
if game.coinMode == false
471
Player.Lives++
472
else
473
game.callbackParam0 = 1 // Set the amount of coins to add
474
EngineCallback(NOTIFY_ADD_COIN)
475
end if
476
#endplatform
477
478
#platform: Use_Standalone
479
Player.Lives++ // In Standalone, we only have lives
480
#endplatform
481
482
Player.ScoreBonus += 50000
483
484
if Stage.PlayerListPos == PLAYER_SONIC_A // PLAYER_SONIC in origins
485
PlaySfx(SFX_G_1UP, false)
486
else
487
PlaySfx(SFX_G_ACHIEVEMENT, false)
488
end if
489
end if
490
491
CheckGreater(Object.RingBonus, 0)
492
TempValue0 = CheckResult
493
CheckGreater(Object.TimeBonus, 0)
494
TempValue0 |= CheckResult
495
496
if TempValue0 == true
497
Object.Timer++
498
499
if Object.Timer == 2
500
PlaySfx(SFX_G_SCOREADD, false)
501
Object.Timer = 0
502
end if
503
else
504
// The tally's done, proceed
505
506
Object.State = STAGEFINISH_DISPLAYFINAL
507
Object.Timer = 0
508
509
// And of course, the signature ka-ching!
510
PlaySfx(SFX_G_SCORETOTAL, false)
511
end if
512
break
513
514
case STAGEFINISH_DISPLAYFINAL
515
// Wait some more, letting the player see what they *really* got
516
Object.Timer++
517
518
if Object.Timer == 160
519
Object.Timer = 0
520
Object.State = STAGEFINISH_LOADNORMAL
521
if Object[0].Type == TypeName[Blank Object]
522
PlaySfx(SFX_G_SPECIALWARP, false)
523
end if
524
end if
525
break
526
527
case STAGEFINISH_LOADNORMAL
528
if Object[0].Type == TypeName[Blank Object]
529
Object.Timer += 8
530
SetScreenFade(208, 255, 224, Object.Timer)
531
532
if Object.Timer == 1024
533
if Options.GameMode == MODE_SAVEGAME
534
535
// Save the Player's progress
536
// This used to be useless, because the Player's progress was already saved previously in the Object,
537
// but Origins removed that duplicate, and now this whole section actually serves a purpose now
538
539
ArrayPos1 = Options.SaveSlot
540
ArrayPos1 <<= 3
541
542
SaveRAM[ArrayPos1] = Stage.PlayerListPos
543
544
ArrayPos1++
545
SaveRAM[ArrayPos1] = Player.Lives
546
547
ArrayPos1++
548
SaveRAM[ArrayPos1] = Player.Score
549
550
ArrayPos1++
551
SaveRAM[ArrayPos1] = Stage.ListPos
552
SaveRAM[ArrayPos1]++
553
554
ArrayPos1++
555
SaveRAM[ArrayPos1] = SpecialStage.TimeStones
556
557
ArrayPos1++
558
SaveRAM[ArrayPos1] = SpecialStage.ListPos
559
560
ArrayPos1++
561
SaveRAM[ArrayPos1] = Player.ScoreBonus
562
563
// This bump in particular, it doesn't do anything, does it?
564
ArrayPos1++
565
566
WriteSaveRAM()
567
end if
568
569
#platform: Use_Origins
570
// A small Origins tweak - backup the Player's score (again)
571
// So I guess in return for one redundancy loss, we got another one in return...
572
recScore = Player.Score
573
#endplatform
574
575
// Write the correct colors to Fade_Colour so that the maingame fades back in with the same white
576
// (This is setting Fade_Colout to 0xD0FFE0, in hex form)
577
Fade_Colour = 208
578
Fade_Colour <<= 16
579
TempValue0 = 255
580
TempValue0 <<= 8
581
Fade_Colour += TempValue0
582
Fade_Colour += 224
583
584
#platform: Use_Origins
585
// Now, let the game know how many Rings we got
586
game.callbackParam0 = StageStatsUsabilityParam5
587
EngineCallback(NOTIFY_STATS_RING)
588
589
// Reset the variable for future use
590
StageStatsUsabilityParam5 = 0
591
#endplatform
592
593
if Stage.ListPos < Stage.ListSize
594
LoadStage()
595
else
596
// This should never happen, but you're somehow supposed to go to a stage that doesn't exist, so
597
// just go back to the title screen instead
598
Stage.ActiveList = PRESENTATION_STAGE
599
Stage.ListPos = STAGE_P_TITLESCREEN
600
LoadStage()
601
end if
602
end if
603
end if
604
break
605
606
case STAGEFINISH_LOADTIMEATTACK
607
if Object.Timer < 480
608
Object.Timer += 4
609
Music.Volume--
610
else
611
StopMusic()
612
613
// Save the Time Attack results
614
TimeAttack.Result = Stage.Seconds
615
TimeAttack.Result *= 100
616
617
TempValue0 = Stage.Minutes
618
TempValue0 *= 6000
619
620
TimeAttack.Result += TempValue0
621
TimeAttack.Result += Stage.MilliSeconds
622
623
// Load the Time Attack Menu
624
// This is an extremely minor change, but Origins changed this part to be more in line with
625
// other stage setting code, where active list is set first and then list pos comes after
626
// Before that, this part had list pos first and then active list, which was quite odd...
627
Stage.ActiveList = PRESENTATION_STAGE
628
Stage.ListPos = STAGE_P_TIMEATTACK
629
630
LoadStage()
631
end if
632
633
SetScreenFade(0, 0, 0, Object.Timer)
634
break
635
636
case STAGEFINISH_LOADLEVELSELECT
637
// Used when exiting the hidden Robotnik stage
638
#platform: Use_Standalone
639
if Object.Timer < 480
640
#endplatform
641
#platform: Use_Origins
642
if Object.Timer < 240
643
#endplatform
644
// Fade out the screen and the music
645
646
Object.Timer += 4
647
Music.Volume--
648
else
649
// Load the credits scene
650
651
StopMusic()
652
653
// Similarly to the above, this spot used to be out-of-order until Origins came and fixed it
654
// One strange thing through, it changed it from the Credits to be the Sound Test instead?
655
// I have no idea if that was an intentional change or not, but it's strange...
656
657
Stage.ActiveList = PRESENTATION_STAGE
658
659
#platform: Use_Origins
660
Stage.ListPos = STAGE_P_SOUNDTEST
661
#endplatform
662
663
#platform: Use_Standalone
664
Stage.ListPos = STAGE_P_CREDITS
665
#endplatform
666
LoadStage()
667
end if
668
669
SetScreenFade(0, 0, 0, Object.Timer)
670
break
671
672
#platform: Use_Origins
673
// The Origins folks put an extra break in here LOL
674
// This code never hits anyway, so I guess it's fine?
675
break
676
677
case STAGEFINISH_CHECKRETRYCOND
678
679
game.callbackResult = -1 // Reset the Callback result
680
681
if Object.ResultsType == STAGEFINISH_T_FAILURE
682
// We've failed getting the Stone, so we're able to retry the Special Stage
683
684
game.callbackParam0 = false
685
else
686
// We got the Stone, so we don't need to retry
687
688
game.callbackParam0 = true
689
end if
690
691
// Offer to restart the Special Stage, if the Player failed it
692
game.callbackParam1 = BackupSpecialStageListPos
693
game.callbackParam2 = BackupTimeStones
694
EngineCallback(NOTIFY_SPECIAL_RETRY)
695
696
Object.State = STAGEFINISH_SAVE
697
698
SetScreenFade(208, 255, 224, 255)
699
break
700
701
case STAGEFINISH_SAVE
702
if game.callbackResult >= false
703
SpecialStage.ListPos = BackupSpecialStageListPos
704
SpecialStage.TimeStones = BackupTimeStones
705
706
if Options.GameMode == MODE_SAVEGAME
707
ArrayPos1 = Options.SaveSlot
708
ArrayPos1 <<= 3
709
710
SaveRAM[ArrayPos1] = Stage.PlayerListPos
711
712
ArrayPos1++
713
SaveRAM[ArrayPos1] = Player.Lives
714
715
ArrayPos1++
716
SaveRAM[ArrayPos1] = Player.Score
717
718
ArrayPos1++
719
SaveRAM[ArrayPos1] = Stage.ListPos
720
SaveRAM[ArrayPos1]++
721
722
ArrayPos1++
723
SaveRAM[ArrayPos1] = SpecialStage.TimeStones
724
725
ArrayPos1++
726
SaveRAM[ArrayPos1] = SpecialStage.ListPos
727
728
ArrayPos1++
729
SaveRAM[ArrayPos1] = Player.ScoreBonus
730
731
ArrayPos1++
732
733
WriteSaveRAM()
734
end if
735
736
if Options.GameMode == MODE_TIMEATTACK
737
738
// Save up the Time Attack results
739
740
TimeAttack.Result = Stage.Seconds
741
TimeAttack.Result *= 100
742
743
TempValue0 = Stage.Minutes
744
TempValue0 *= 6000
745
746
TimeAttack.Result += TempValue0
747
TimeAttack.Result += Stage.MilliSeconds
748
749
// Load the Time Attack menu
750
Stage.ActiveList = PRESENTATION_STAGE
751
Stage.ListPos = STAGE_P_TIMEATTACK
752
753
LoadStage()
754
else
755
Object.State = STAGEFINISH_FADEIN
756
Object.Timer = 256
757
if SpecialStage.TimeStones > 126 // 0b1111110, each '1' bit represents an obtained time stone
758
// Got 'em all!
759
Object.ResultsType = STAGEFINISH_T_ALLSTONESOBTAINED
760
EngineCallback(NOTIFY_STATS_PARAM_2)
761
end if
762
763
PlayMusic(1)
764
end if
765
end if
766
767
SetScreenFade(208, 255, 224, 255)
768
break
769
#endplatform
770
end switch
771
772
end sub
773
774
775
sub ObjectDraw
776
if Object.State != STAGEFINISH_LOADLEVELSELECT
777
if Object.State > STAGEFINISH_FADEOUT
778
779
// Draw the Background
780
TempValue0 = 0
781
while TempValue0 < 240
782
TempValue1 = 0
783
while TempValue1 < 360
784
DrawSpriteScreenXY(0, TempValue1, TempValue0)
785
TempValue1 += 224
786
loop
787
788
TempValue0 += 48
789
loop
790
791
#platform: Use_Decomp
792
// Only on decomp, extend the bg past 448
793
TempValue0 = 0
794
while TempValue0 < 240
795
TempValue1 = 448
796
while TempValue1 < 720
797
DrawSpriteScreenXY(0, TempValue1, TempValue0)
798
TempValue1 += 224
799
loop
800
801
TempValue0 += 48
802
loop
803
804
#endplatform
805
806
// Draw all the Time Stones the player has so far
807
// - TempValue0 is the current Stone
808
// - TempValue1 is the starting Sprite Frame ID for the Stones
809
// - TempValue2 is the draw position for the Stones
810
// - TempValue3 is either true or false based if the current Time Stone is obtained
811
TempValue0 = 0
812
TempValue1 = 20
813
TempValue2 = Screen.CenterX
814
TempValue2 -= 79
815
816
while TempValue0 < 7
817
818
// See if the Player has the current Time Stone
819
GetBit(TempValue3, SpecialStage.TimeStones, TempValue0)
820
821
// Bump up the index, for next loop around
822
TempValue0++
823
824
// If the Player has the Time Stone, then draw it
825
if TempValue3 == true
826
DrawSpriteScreenFX(TempValue1, FX_INK, TempValue2, 81)
827
end if
828
829
TempValue1++
830
831
// Each Stone is drawn 24 px apart from each other's center
832
TempValue2 += 24
833
loop
834
end if
835
836
// Draw the main text, depending on what the current results type is
837
switch Object.ResultsType
838
case STAGEFINISH_T_FAILURE
839
// "SPECIAL ZONE"
840
DrawSpriteScreenXY(1, Object.XPos, 50)
841
break
842
843
case STAGEFINISH_T_STONEOBTAINED
844
// "TIME STONES"
845
DrawSpriteScreenXY(2, Object.XPos, 50)
846
break
847
848
case STAGEFINISH_T_ALLSTONESOBTAINED
849
// "GOT THEM ALL!!"
850
DrawSpriteScreenXY(3, Object.XPos, 50)
851
break
852
853
end switch
854
855
// Draw the Score text
856
DrawSpriteScreenXY(4, Object.LineXPos1, 105)
857
858
// Draw the Player's Score
859
TempValue0 = Object.LineXPos1
860
TempValue0 += 176
861
DrawNumbers(10, TempValue0, 105, Player.Score, 6, 8, false)
862
863
// Then, the Ring Bonus line
864
865
// First, draw the "RING" sprite
866
DrawSpriteScreenXY(5, Object.LineXPos2, 129)
867
868
TempValue0 = Object.LineXPos2
869
TempValue0 += 40
870
871
// Then, 40 pixels to the right of that, draw the "BONUS" sprite
872
DrawSpriteScreenXY(7, TempValue0, 129)
873
874
// And at the end of the line, draw the Ring Bonus count
875
TempValue0 += 136
876
DrawNumbers(10, TempValue0, 129, Object.RingBonus, 5, 8, false)
877
878
// Line 3, holds the Time Bonus text
879
880
// First, the "TIME" sprite
881
DrawSpriteScreenXY(6, Object.LineXPos3, 153)
882
883
TempValue0 = Object.LineXPos3
884
TempValue0 += 40
885
886
// Then, 40 pixels to the right, the "BONUS" frame
887
DrawSpriteScreenXY(7, TempValue0, 153)
888
889
// And at the end of this line too, draw the Time Bonus numbers
890
TempValue0 += 136
891
DrawNumbers(10, TempValue0, 153, Object.TimeBonus, 5, 8, false)
892
893
// Line 4, holds either Continues or Coins based on the current mode
894
#platform: Use_Origins
895
if game.coinMode == false
896
897
// Draw the "EXTRA LIVES" text
898
899
// First, is "EXTRA"
900
DrawSpriteScreenXY(8, Object.LineXPos4, 177)
901
902
TempValue0 = Object.LineXPos4
903
TempValue0 += 49
904
905
// Then after than of course, comes "LIVES"
906
DrawSpriteScreenXY(9, TempValue0, 177)
907
908
else
909
910
// Draw the "COINS BONUS" text
911
912
// First, comes "COINS"
913
DrawSpriteScreenXY(35, Object.LineXPos4, 177)
914
915
TempValue0 = Object.LineXPos4
916
TempValue0 += 40
917
918
// Then to the right of that, is "BONUS"
919
DrawSpriteScreenXY(7, TempValue0, 177)
920
921
// And then bump up the position for the icons to be drawn at
922
TempValue0 += 9
923
924
end if
925
#endplatform
926
927
#platform: Use_Standalone
928
// Draw the "EXTRA LIVES" text
929
930
// First, is "EXTRA"
931
DrawSpriteScreenXY(8, Object.LineXPos4, 177)
932
933
TempValue0 = Object.LineXPos4
934
TempValue0 += 49
935
936
// Then after than of course, comes "LIVES"
937
DrawSpriteScreenXY(9, TempValue0, 177)
938
#endplatform
939
940
// Move to the end of the line
941
TempValue0 += 86
942
943
// Animate the mini-character
944
Object.Frame++
945
Object.Frame &= 15
946
947
// Get the base frame the mini-character should use
948
TempValue1 = Object.Frame
949
TempValue1 >>= 3
950
951
// Bump it up to match its corresponding Sprite Frame ID
952
TempValue1 += 27
953
954
TempValue2 = Object.ExtraLives
955
956
#platform: Use_Origins
957
// Now, draw either Continues or Coins
958
959
if game.coinMode == false
960
961
// Draw Continues
962
963
while TempValue2 > 0
964
DrawSpriteScreenXY(TempValue1, TempValue0, 177)
965
TempValue2--
966
967
TempValue0 += 24
968
loop
969
970
else
971
972
if TempValue2 > 0
973
TempValue0 += 12
974
975
// This TempValue1, it isn't used anywhere, is it?
976
// It corresponds with the following Sprite Frame ID, perhaps it was used for that before...
977
TempValue1 = 29
978
979
// Draw the Coins icon
980
DrawSpriteScreenXY(29, TempValue0, 177)
981
982
// And then an x1 next to it
983
DrawSpriteScreenXY(30, TempValue0, 177)
984
985
// And then make the Coin sparkle
986
TempValue1 = Object.Frame
987
TempValue1 >>= 2
988
989
// From that sparkle frame, but it up by 31 to match the Sprite Frame IDs
990
TempValue1 += 31
991
992
// And now, draw the sparkle on top of the Coin
993
DrawSpriteScreenXY(TempValue1, TempValue0, 177)
994
end if
995
996
end if
997
#endplatform
998
999
#platform: Use_Standalone
1000
// Just draw Continues, we don't use Coins in Standalone
1001
1002
while TempValue2 > 0
1003
DrawSpriteScreenXY(TempValue1, TempValue0, 177)
1004
TempValue2--
1005
TempValue0 += 24
1006
loop
1007
#endplatform
1008
1009
end if
1010
end sub
1011
1012
1013
sub ObjectStartup
1014
1015
// Load the correct sheet based on the current language
1016
switch Engine.Language
1017
case LANG_ENGLISH
1018
case LANG_JAPANESE
1019
// LANG_ENGLISH and LANG_JAPANESE use the same sheet (the LANG_ENGLISH sheet)
1020
LoadSpriteSheet("Special/ScoreScreen.gif")
1021
break
1022
1023
case LANG_FRENCH
1024
LoadSpriteSheet("Special/ScoreScreen_FR.gif")
1025
break
1026
1027
case LANG_ITALIAN
1028
LoadSpriteSheet("Special/ScoreScreen_IT.gif")
1029
break
1030
1031
case LANG_DEUTSCH
1032
LoadSpriteSheet("Special/ScoreScreen_DE.gif")
1033
break
1034
1035
case LANG_SPANISH
1036
LoadSpriteSheet("Special/ScoreScreen_ES.gif")
1037
break
1038
1039
end switch
1040
1041
// 0 - Background
1042
SpriteFrame(0, 0, 224, 48, 0, 63)
1043
1044
// 1 - "SPECIAL ZONE" Text
1045
SpriteFrame(0, 0, 184, 14, 1, 1)
1046
1047
// 2 - "TIME STONES" Text
1048
SpriteFrame(9, 0, 167, 14, 1, 16)
1049
1050
// 3 - "GOT THEM ALL!!" Text
1051
SpriteFrame(-16, 0, 205, 14, 1, 48)
1052
1053
// 4 - "SCORE" Text
1054
SpriteFrame(0, 0, 39, 11, 1, 112)
1055
1056
// 5 - "RING" Text
1057
SpriteFrame(0, 0, 31, 11, 41, 112)
1058
1059
// 6 - "TIME" Text
1060
SpriteFrame(0, 0, 31, 11, 73, 112)
1061
1062
// 7 - "BONUS" Text
1063
SpriteFrame(0, 0, 41, 11, 105, 112)
1064
1065
// 8 - "EXTRA" Text
1066
SpriteFrame(0, 0, 40, 11, 147, 112)
1067
1068
// 9 - "LIVES" Text
1069
SpriteFrame(0, 0, 36, 11, 188, 112)
1070
1071
// 10-19 - Numbers 0-9
1072
SpriteFrame(0, 0, 8, 11, 220, 1)
1073
SpriteFrame(0, 0, 8, 11, 229, 1)
1074
SpriteFrame(0, 0, 8, 11, 238, 1)
1075
SpriteFrame(0, 0, 8, 11, 247, 1)
1076
SpriteFrame(0, 0, 8, 11, 220, 13)
1077
SpriteFrame(0, 0, 8, 11, 229, 13)
1078
SpriteFrame(0, 0, 8, 11, 238, 13)
1079
SpriteFrame(0, 0, 8, 11, 247, 13)
1080
SpriteFrame(0, 0, 8, 11, 238, 25)
1081
SpriteFrame(0, 0, 8, 11, 247, 25)
1082
1083
// 20-26 - Time Stones
1084
SpriteFrame(0, 0, 16, 16, 1, 31)
1085
SpriteFrame(0, 0, 16, 16, 18, 31)
1086
SpriteFrame(0, 0, 16, 16, 35, 31)
1087
SpriteFrame(0, 0, 16, 16, 52, 31)
1088
SpriteFrame(0, 0, 16, 16, 69, 31)
1089
SpriteFrame(0, 0, 16, 16, 86, 31)
1090
SpriteFrame(0, 0, 16, 16, 103, 31)
1091
1092
// 27-28 - Small Foot-Tapping Player Icons
1093
if Stage.PlayerListPos == PLAYER_SONIC_A // PLAYER_SONIC in origins
1094
// Do note, these are separate from the ones used in the Pause Menu
1095
// These ones are bluer, as well as having a hole in Sonic's head...
1096
SpriteFrame(0, 0, 16, 23, 169, 24)
1097
SpriteFrame(0, 0, 16, 23, 186, 24)
1098
end if
1099
if Stage.PlayerListPos == PLAYER_TAILS_A // PLAYER_TAILS in origins
1100
SpriteFrame(0, 0, 16, 23, 139, 203)
1101
SpriteFrame(0, 0, 16, 23, 156, 203)
1102
end if
1103
#platform: Use_Origins
1104
if Stage.PlayerListPos == PLAYER_KNUCKLES
1105
SpriteFrame(0, 0, 16, 22, 18, 256)
1106
SpriteFrame(0, 0, 16, 22, 35, 256)
1107
end if
1108
if Stage.PlayerListPos == PLAYER_AMY
1109
SpriteFrame(0, 0, 17, 22, 70, 256)
1110
SpriteFrame(0, 0, 17, 22, 88, 256)
1111
end if
1112
1113
// These below ones are new to Origins
1114
1115
// 29 - Coins icon
1116
SpriteFrame(0, -4, 18, 16, 204, 29)
1117
1118
// 30 - "x1"
1119
SpriteFrame(18, -4, 32, 16, 187, 1)
1120
1121
// 31-34 - Sparkle Frames
1122
SpriteFrame(-4, -8, 24, 24, 130, 125)
1123
SpriteFrame(-4, -8, 24, 24, 155, 125)
1124
SpriteFrame(-4, -8, 24, 24, 130, 150)
1125
SpriteFrame(-4, -8, 24, 24, 155, 150)
1126
1127
// 35 - "COIN" text, in the context of "Coin Bonus"
1128
SpriteFrame(0, 0, 31, 11, 130, 175)
1129
#endplatform
1130
1131
end sub
1132
1133
1134
// ========================
1135
// Editor Subs
1136
// ========================
1137
1138
sub RSDKDraw
1139
DrawSprite(0)
1140
end sub
1141
1142
1143
sub RSDKLoad
1144
LoadSpriteSheet("Special/ScoreScreen.gif")
1145
SpriteFrame(0, 0, 184, 14, 1, 1)
1146
1147
// Although used, it's not to be set from editor
1148
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
1149
end sub
1150
1151