Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-CD-2011-Script-Decompilation
Path: blob/main/Scripts/Special/PauseMenu.txt
1319 views
1
//-----------------Sonic CD Pause Menu Script-----------------//
2
//--------Scripted by Christian Whitehead 'The Taxman'--------//
3
//-------Unpacked By Rubberduckycooly's Script Unpacker-------//
4
5
// Aliases
6
7
// How long the Pause Menu should initially slide out for
8
#alias Object.PropertyValue : Object.ExtendTime
9
10
#alias Object.Value0 : Object.Timer
11
12
// The current highlighted selection, check out the PAUSEMENU_SEL_* aliases right down below
13
#alias Object.Value1 : Object.CurrentSelection
14
15
// Selection Aliases
16
#alias -1 : PAUSEMENU_SEL_NULL
17
#alias 0 : PAUSEMENU_SEL_CONTINUE
18
#alias 1 : PAUSEMENU_SEL_RESTART
19
#alias 2 : PAUSEMENU_SEL_EXIT
20
#alias 3 : PAUSEMENU_SEL_DEVMENU
21
22
// X Position of the underline that's underneat the Options texts
23
#alias Object.Value2 : Object.UnderlinePos
24
25
// X Position for the Black Bar behind the Pause Text
26
// This is accompanied by PauseBarYPos, check out below for more about Value4 since it's multi-use in this Object
27
#alias Object.Value3 : Object.PauseBarXPos
28
29
// Value4 has different uses across this Object's various States
30
31
// In states 0-2:
32
// Value 4 is used to hold the Y Position of the White Rectangle
33
#alias Object.Value4 : Object.WhiteRectPos
34
35
// And then, this holds the position of that White Rectangle from the previous frame during those states
36
// -> See ObjectDraw for more info
37
#alias Object.Value5 : Object.PrevWhiteRectPos
38
39
// In states 4-5:
40
// Value 4 is used to hold the Y Position of the Pause text & its bar
41
// Check out PauseBarXPos too, though that one's just a normal Value and only has one use
42
#alias Object.Value4 : Object.PauseBarYPos
43
44
// For clarity's sake, the two types of Value 4 uses are aliases differently
45
46
// Just a bool, essentially useless since restarts are always disabled in Special Stages so there's no reason for this to be here
47
// Check out its initial use for more info, but this Object's pretty much a copy of the Global version, where the variable *is* used for actual purpose
48
#alias Object.Value6 : Object.RestartDisabled
49
50
// Position of the stuff on the right side (options, black bar, etc.)
51
#alias Object.XPos : Object.SelectionBarPos
52
53
// values for the tiny 'lil sonic :)
54
#alias Object.Frame : Object.SonicFrame
55
#alias Object.AnimationTimer : Object.SonicTimer
56
57
// States
58
59
// This Object can't have its value setup via a normal loop in ObjectStartup since it doesn't even exist
60
// normally - it's spawned in by the Sonic Object instead - so the first state is for initialising its values
61
#alias 0 : PAUSEMENU_INIT
62
63
// Once the Object is setup, all the shape parts of it slide in, including the white background, pause bar, and other black bar to the right
64
#alias 1 : PAUSEMENU_SLIDEIN
65
66
// After that, now the Sprite aspects of it fade in, like the Options and Pause text
67
#alias 2 : PAUSEMENU_FADEIN
68
69
// Yup, now we're in the main state!
70
// This is where all the good stuff is done, of course
71
#alias 3 : PAUSEMENU_MAIN
72
73
// Upon selecting any option, the selected option will flash for a few moments...
74
#alias 4 : PAUSEMENU_FLASH
75
76
// ... and after that comes a branch of fate - choose a path!
77
78
// If you selected the Continue option, then...
79
// Close the Pause Menu, and resume the normal game
80
#alias 5 : PAUSEMENU_CLOSE
81
82
// If you selected any other option, then...
83
// Make the Pause Menu consume the screen, and exit the level or whatever afterwards
84
#alias 6 : PAUSEMENU_EXIT
85
86
// One of the updates changed the left bounds for how far the Pause Menu should go
87
// Originally was -32, but the current version is -64
88
// That's about a two frames difference, isn't that interesting?
89
#alias -64 : PAUSEMENU_LEFTMOST
90
91
// Player Aliases
92
#alias 0 : PLAYER_SONIC_A
93
#alias 1 : PLAYER_TAILS_A
94
95
// Presentation Stages
96
#alias 0 : STAGE_P_TITLE
97
#alias 2 : STAGE_P_TIMEATTACK
98
99
// Languages
100
#alias 0 : LANG_ENGLISH
101
#alias 1 : LANG_FRENCH
102
#alias 2 : LANG_ITALIAN
103
#alias 3 : LANG_DEUTSCH
104
#alias 4 : LANG_SPANISH
105
#alias 5 : LANG_JAPANESE
106
107
// Screen Aliases
108
// This Object uses a hardcoded constant of 240 rather often, rather than Screen.YSize, so this is here just to clarify stuff a bit
109
#alias 240 : SCREEN_YSIZE
110
111
// Global SFX
112
#alias 23 : SFX_G_MENUBUTTON
113
#alias 27 : SFX_G_SELECT
114
115
// Ink Effect Aliases
116
#alias 2 : INK_ALPHA
117
118
// Game Mode Aliases
119
#alias 2 : MODE_TIMEATTACK
120
121
// Engine Messages
122
// (Strange to describe, but they're essentially system-level stuff that the engine transmits to the scripts)
123
#alias 2 : MESSAGE_LOSTFOCUS
124
#alias 3 : MESSAGE_YES_SELECTED
125
#alias 4 : MESSAGE_NO_SELECTED
126
127
// Engine Callbacks
128
#alias 6 : CALLBACK_RESTART_SELECTED
129
#alias 7 : CALLBACK_EXIT_SELECTED
130
131
// Tile Layer Types
132
#alias 4 : LAYER_3DSKY
133
134
135
sub ObjectMain
136
switch Object.State
137
case PAUSEMENU_INIT
138
// Object just got spawned, setup everything here
139
140
// Start the right Bar to be, well, off to the right
141
Object.SelectionBarPos = Screen.XSize
142
143
// And then make the left Pause bar start all the way to the left
144
Object.PauseBarXPos = 0
145
146
Object.Timer = 0
147
148
// The Object uses alpha effects to fade-in the test, so get that all set up too
149
Object.InkEffect = INK_ALPHA
150
Object.Alpha = 0
151
152
// Some languages have longer text than others
153
// LANG_FRENCH is the longest, while the standard LANG_ENGLISH version is the shortest
154
switch Engine.Language
155
case LANG_ENGLISH
156
case LANG_JAPANESE
157
Object.ExtendTime = 12
158
break
159
160
case LANG_FRENCH
161
Object.ExtendTime = 15
162
break
163
164
// A bit of fall-through could probably be used on these last three entries, but it isn't
165
// Oh well
166
167
case LANG_ITALIAN
168
Object.ExtendTime = 13
169
break
170
171
case LANG_DEUTSCH
172
Object.ExtendTime = 13
173
break
174
175
case LANG_SPANISH
176
Object.ExtendTime = 13
177
break
178
179
end switch
180
181
// Disable Restarting if needed... but it's always gonna be disabled
182
if Player.Lives < 2
183
Object.RestartDisabled = true
184
else
185
186
// This version of the Pause Menu is only used in Special Stages anyway... so why is this check here?
187
// Likely just a result of copy-pasting the maingame one, if I had to guess, as that one
188
// has the same check there despite it being the opposite situation, where it'll never be true since it's only used in regular/bonus stages
189
#platform: Use_Standalone
190
if Stage.ActiveList == SPECIAL_STAGE
191
Object.RestartDisabled = true
192
else
193
Object.RestartDisabled = false
194
end if
195
#endplatform
196
197
#platform: Use_Origins
198
// Origins messed up the Active List IDs ("SPECIAL_STAGE" points to the Bonus Stage list now!) so we check via a direct ID instead here
199
if Stage.ActiveList == 3
200
Object.RestartDisabled = true
201
else
202
Object.RestartDisabled = false
203
end if
204
#endplatform
205
206
end if
207
#platform: Use_Origins
208
// On Origins, Physical Controls are enforced as the default
209
Options.PhysicalControls = true
210
#endplatform
211
212
#platform: Mobile
213
// On Mobile though, have a default selection (or don't) based on if the Player's using a physical gamepad or not
214
if Options.TouchControls == true
215
Object.CurrentSelection = PAUSEMENU_SEL_NULL
216
Options.PhysicalControls = false
217
else
218
// (Implicitly making the starting selection PAUSEMENU_SEL_CONTINUE - ID 0)
219
Options.PhysicalControls = true
220
end if
221
#endplatform
222
223
Object.State++
224
break
225
226
case PAUSEMENU_SLIDEIN
227
228
// Slide the Pause bar in
229
Object.PauseBarXPos = Object.Timer
230
Object.PauseBarXPos *= Screen.XSize
231
Object.PauseBarXPos /= 12
232
233
// And then move the background white rectangle in
234
Object.WhiteRectPos = Object.Timer
235
Object.WhiteRectPos *= SCREEN_YSIZE
236
Object.WhiteRectPos /= 12
237
238
// And then slide the right bar in too
239
240
TempValue0 = Object.Timer
241
TempValue0 <<= 7
242
TempValue0 /= 12
243
244
Object.SelectionBarPos = Screen.XSize
245
Object.SelectionBarPos -= TempValue0
246
247
if Object.Timer < Object.ExtendTime
248
// Haven't reached where we should yet, keep moving...
249
250
Object.Timer++
251
else
252
// Get ready to go to the next state
253
254
// Setup the Underline initial position
255
Object.UnderlinePos = Object.SelectionBarPos
256
Object.UnderlinePos += 48
257
258
Object.Timer = 0
259
260
Object.State++
261
end if
262
break
263
264
case PAUSEMENU_FADEIN
265
if Object.Timer < 256
266
Object.Timer += 16
267
268
// Because Object.Alpha is a byte and will overflow if over 255,
269
// we have to do this instead
270
if Object.Timer < 255
271
Object.Alpha = Object.Timer
272
else
273
Object.Alpha = 255
274
end if
275
else
276
// Next state
277
278
Object.Timer = 0
279
280
// Just to make sure it's at full opacity
281
Object.Alpha = 255
282
283
Object.State++
284
end if
285
break
286
287
case PAUSEMENU_MAIN
288
289
// There's normally a `if Options.PhysicalControls == true` path here, but to keep 2012 Steam datafiles working we gotta do this roundabout way instead
290
#platform: Standard
291
// Let's assume the variable doesn't exist, force Physical Controls
292
CheckResult = true
293
#endplatform
294
295
#platform: Mobile
296
CheckEqual(Options.PhysicalControls, true)
297
#endplatform
298
299
#platform: Use_Origins
300
CheckEqual(Options.PhysicalControls, true)
301
#endplatform
302
303
304
if CheckResult == true
305
// Update Physical Controls
306
307
if KeyPress[0].Up == true
308
309
PlaySfx(SFX_G_MENUBUTTON, false)
310
311
// Reset all the stuff
312
313
Object.Timer = 0
314
315
// Sonic should resume his normal stance
316
Object.SonicTimer = 0
317
Object.SonicFrame = 0
318
319
// Move the bar all the way over to the right
320
Object.UnderlinePos = Screen.XSize
321
322
// And of course, bump down the current selection by one
323
Object.CurrentSelection--
324
325
// Enforce different upwards loop points based on if the 4th Dev Menu option is available or not
326
if Options.DevMenuFlag == true
327
if Object.CurrentSelection < PAUSEMENU_SEL_CONTINUE
328
Object.CurrentSelection = PAUSEMENU_SEL_DEVMENU
329
end if
330
else
331
if Object.CurrentSelection < PAUSEMENU_SEL_CONTINUE
332
Object.CurrentSelection = PAUSEMENU_SEL_EXIT
333
end if
334
end if
335
336
// If restart is disabled (which it always should be here) then don't let the player select it
337
if Object.RestartDisabled == true
338
if Object.CurrentSelection == PAUSEMENU_SEL_RESTART
339
// Move them to the PAUSEMENU_SEL_CONTINUE instead
340
Object.CurrentSelection--
341
end if
342
end if
343
344
end if
345
346
if KeyPress[0].Down == true
347
348
PlaySfx(SFX_G_MENUBUTTON, false)
349
350
// Reset some stuff
351
352
Object.Timer = 0
353
354
Object.SonicTimer = 0
355
Object.SonicFrame = 0
356
357
// Move the line back offscreen
358
Object.UnderlinePos = Screen.XSize
359
360
// And of course, move a selection down
361
Object.CurrentSelection++
362
363
// The Dev Menu adds a 4th entry, so the wrap around value is different too
364
if Options.DevMenuFlag == true
365
if Object.CurrentSelection > PAUSEMENU_SEL_DEVMENU
366
Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE
367
end if
368
else
369
if Object.CurrentSelection > PAUSEMENU_SEL_EXIT
370
Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE
371
end if
372
end if
373
374
// If restarting is disabled (always the case here in Special Stages) then
375
// move the player's selection to PAUSEMENU_SEL_EXIT instead
376
if Object.RestartDisabled == true
377
if Object.CurrentSelection == PAUSEMENU_SEL_RESTART
378
Object.CurrentSelection++
379
end if
380
end if
381
382
end if
383
384
// You can use either Start or A to close a selection, the other two buttons won't do anything though...
385
if KeyPress[0].Start == true
386
PlaySfx(SFX_G_SELECT, false)
387
Object.State = PAUSEMENU_FLASH
388
Object.Alpha = 248
389
Object.Timer = 0
390
end if
391
392
if KeyPress[0].ButtonA == true
393
PlaySfx(SFX_G_SELECT, false)
394
Object.State = PAUSEMENU_FLASH
395
Object.Alpha = 248
396
Object.Timer = 0
397
end if
398
399
#platform: Mobile
400
// If the Player's touched the screen at all, then switch to Touch Controls
401
CheckTouchRect(0, 0, Screen.XSize, Screen.YSize)
402
403
if CheckResult > -1
404
Options.PhysicalControls = false
405
Object.CurrentSelection = PAUSEMENU_SEL_NULL
406
end if
407
#endplatform
408
else
409
410
// If the Player's not even in the game, then reset the current selection
411
if Engine.Message == MESSAGE_LOSTFOCUS
412
Object.CurrentSelection = PAUSEMENU_SEL_NULL
413
end if
414
415
// From here, now we do a whole lotta stuff with touch controls, where we check manually for every option
416
// For the most part, each chunk of code here is the same, only with one or two minor differences
417
418
// See if the Player's tapped the screen at all, and store the result into TempValue3
419
// This value is used throughout this entire touch controls section
420
CheckTouchRect(0, 0, Screen.XSize, Screen.YSize)
421
TempValue3 = CheckResult
422
423
// And now, check for the Continue button
424
425
// See if the Player's tapped it
426
CheckTouchRect(TempValue0, 32, Screen.XSize, 64)
427
428
if CheckResult > -1
429
// If the player has their finger over the Continue button but hasn't relased it yet, then just keep it selected
430
// but don't actually activate it yet
431
432
Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE
433
else
434
if TempValue3 < 0
435
// The Player doesn't have their finger on the screen *nor* the Continue button
436
437
if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE
438
// The Player's released their finger while on the button, so let's start Continuing now
439
440
PlaySfx(SFX_G_SELECT, false)
441
Object.State = PAUSEMENU_FLASH
442
Object.Alpha = 248
443
Object.Timer = 0
444
end if
445
else
446
// The Player's finger is on the screen but not on the Continue option, so make them deselect
447
448
if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE
449
Object.CurrentSelection = PAUSEMENU_SEL_NULL
450
end if
451
end if
452
end if
453
454
// Now, the Restart button
455
// As said before, RestartDisabled is always gonna be true in a Special Stage so this whole chunk of code is essentially useless...
456
457
// Yeah, I guess they just kept it here anyway because it looked cool or something idk
458
if Object.RestartDisabled == false
459
460
// See if the Player's got their finger over the Restart button
461
CheckTouchRect(TempValue0, 80, Screen.XSize, 112)
462
463
if CheckResult > -1
464
// If they do, then make the current selection Restart
465
466
Object.CurrentSelection = PAUSEMENU_SEL_RESTART
467
else
468
if TempValue3 < 0
469
// The Player isn't touching the screen at all
470
471
if Object.CurrentSelection == PAUSEMENU_SEL_RESTART
472
// The Player released their finger while hovering over Restart, so let's restart then!
473
474
PlaySfx(SFX_G_SELECT, false)
475
Object.State = PAUSEMENU_FLASH
476
Object.Alpha = 248
477
Object.Timer = 0
478
end if
479
else
480
// The finger has their player on the screen, but not over the Continue button
481
482
if Object.CurrentSelection == PAUSEMENU_SEL_RESTART
483
Object.CurrentSelection = PAUSEMENU_SEL_NULL
484
end if
485
end if
486
end if
487
488
end if
489
490
// After that comes the wonderful, Exit button!
491
492
// See if there's a finger on it
493
CheckTouchRect(TempValue0, 128, Screen.XSize, 160)
494
495
if CheckResult > -1
496
// If there is, then make it the current selection
497
498
Object.CurrentSelection = PAUSEMENU_SEL_EXIT
499
else
500
// The Player isn't currently on the Exit button
501
502
if TempValue3 < 0
503
// And, the Player isn't touching the screen at all!
504
505
if Object.CurrentSelection == PAUSEMENU_SEL_EXIT
506
// So in that case, if they were on it for at least one frame before, then let's go ahead and Exit
507
508
PlaySfx(SFX_G_SELECT, false)
509
Object.State = PAUSEMENU_FLASH
510
Object.Alpha = 248
511
Object.Timer = 0
512
end if
513
else
514
// The Player's finger is on the screen, but not on the Exit button
515
516
if Object.CurrentSelection == PAUSEMENU_SEL_EXIT
517
Object.CurrentSelection = PAUSEMENU_SEL_NULL
518
end if
519
end if
520
end if
521
522
// Yup, and now the Dev Menu button!
523
// It only shows under the most special conditions, they say...
524
525
if Options.DevMenuFlag == true
526
527
// Check to see if the Player's touching it
528
CheckTouchRect(TempValue0, 176, Screen.XSize, 208)
529
530
if CheckResult > -1
531
// If they are, then make it selected
532
533
Object.CurrentSelection = PAUSEMENU_SEL_DEVMENU
534
else
535
// The Player's not touching the Dev Menu button
536
537
if TempValue3 < 0
538
// Additionally, they're not touching the screen at all either
539
540
if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU
541
// If they were touching the Dev Menu button last frame, then assume a button press
542
543
PlaySfx(SFX_G_SELECT, false)
544
Object.State = PAUSEMENU_FLASH
545
Object.Alpha = 248
546
Object.Timer = 0
547
end if
548
else
549
// The Player's holding the screen, but they're not touching the Dev Menu button
550
551
if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU
552
// So just let the button go
553
Object.CurrentSelection = PAUSEMENU_SEL_NULL
554
end if
555
end if
556
end if
557
558
end if
559
560
// And now, after all that's done, check for actual, physical inputs
561
562
if KeyPress[0].Up == true
563
564
// If Up was pressed, then go to the bottommost entry
565
// This'll vary if the Dev Menu is active, of course
566
567
if Options.DevMenuFlag == true
568
Object.CurrentSelection = PAUSEMENU_SEL_DEVMENU
569
else
570
Object.CurrentSelection = PAUSEMENU_SEL_EXIT
571
end if
572
573
#platform: Mobile
574
// And set Physical Controls to active, now that the player's actually pressed something
575
576
Options.PhysicalControls = true
577
#endplatform
578
end if
579
580
if KeyPress[0].Down == true
581
582
// If Down was pressed, then just go to the topmost entry
583
// Nothing further needed here
584
585
Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE
586
587
#platform: Mobile
588
// And similarly, set Physical Controls to be active for the same reason as before
589
590
Options.PhysicalControls = true
591
#endplatform
592
end if
593
end if
594
595
// Progress mini Sonic's animation
596
597
if Object.Timer < 60
598
// Make him stand all nice and polite for a second...
599
600
Object.Timer++
601
else
602
// But once that second's over, gotta get moving!
603
604
// Get the topmost bit of Sonic's Animation Timer
605
Object.SonicFrame = Object.SonicTimer
606
Object.SonicFrame >>= 4
607
608
// And then bump it up one more to match with the Sprite Frame IDs
609
Object.SonicFrame++
610
611
Object.SonicTimer++
612
Object.SonicTimer &= 31
613
end if
614
break
615
616
case PAUSEMENU_FLASH
617
618
// In this state, the Timer is used to control the selected sprite's visibility, or flashing
619
// So, let's progress that value
620
Object.Timer++
621
Object.Timer &= 3
622
623
// Slide the underline text away
624
Object.UnderlinePos += 4
625
626
// First, fade the texts out
627
if Object.Alpha > 0
628
Object.Alpha -= 8
629
else
630
if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE
631
// If on the Continue option, then make the Pause Menu move away rather than cover the screen
632
633
Object.UnderlinePos = Object.SelectionBarPos
634
Object.UnderlinePos += 48
635
636
// Set the initial Y position for the bottom bar
637
// -> Normally, during the rest of the Pause Menu states, it's a direct constant 202,
638
// rather than reading from a variable, which is why the new variable is initially being set here
639
Object.PauseBarYPos = 202
640
641
Object.Timer = 0
642
Object.Alpha = 128
643
644
Object.State = PAUSEMENU_CLOSE
645
646
// Resume the stage now, rather than when the Pause Menu is fully out of the way
647
Stage.State = STAGE_RUNNING
648
else
649
650
// The following code is dependant on the current platform
651
// Origins uses the Standard platform code, of course
652
#platform: Standard
653
Object.UnderlinePos = Object.SelectionBarPos
654
Object.UnderlinePos += 48
655
StopMusic()
656
Object.State = PAUSEMENU_EXIT
657
#endplatform
658
659
#platform: Mobile
660
// On Mobile, we got a whole lot of Engine Message stuff to worry about
661
662
if Engine.Message < MESSAGE_YES_SELECTED
663
switch Object.CurrentSelection
664
case PAUSEMENU_SEL_RESTART
665
EngineCallback(CALLBACK_RESTART_SELECTED)
666
break
667
668
case PAUSEMENU_SEL_EXIT
669
EngineCallback(CALLBACK_EXIT_SELECTED)
670
break
671
672
case PAUSEMENU_SEL_DEVMENU
673
// For the Dev Menu, don't prompt any extra confirmation and just start sliding away already
674
675
Object.UnderlinePos = Object.SelectionBarPos
676
Object.UnderlinePos += 48
677
StopMusic()
678
679
Object.State = PAUSEMENU_EXIT
680
break
681
682
end switch
683
else
684
if Engine.Message == MESSAGE_NO_SELECTED
685
686
// Nevermind, let's go back instead
687
688
// Reset everything and resume back to normal
689
690
Object.Timer = 0
691
692
Object.SonicTimer = 0
693
Object.SonicFrame = 0
694
Object.UnderlinePos = Screen.XSize
695
696
if Options.PhysicalControls == false
697
Object.CurrentSelection = PAUSEMENU_SEL_NULL
698
end if
699
700
Object.State = PAUSEMENU_MAIN
701
Object.Alpha = 255
702
703
else
704
// Yup, the Player truly wants to leave
705
706
Object.UnderlinePos = Object.SelectionBarPos
707
Object.UnderlinePos += 48
708
StopMusic()
709
710
Object.State = PAUSEMENU_EXIT
711
end if
712
end if
713
#endplatform
714
end if
715
end if
716
break
717
718
case PAUSEMENU_CLOSE
719
if Object.Alpha > 0
720
// Closing the Pause Menu...
721
722
// Fade out the text
723
Object.Alpha -= 8
724
725
// And move all the other shapes out of the way
726
Object.SelectionBarPos += 16
727
Object.UnderlinePos += 16
728
Object.PauseBarYPos += 16
729
730
else
731
// The Objects are already moving now, let's continue the music too!
732
ResumeMusic()
733
734
// Erase this current Pause Menu Object, as it's no longer needed
735
ResetObjectEntity(Object.EntityNo, TypeName[Blank Object], 0, 0, 0)
736
737
if Engine.FrameSkipSetting > 0
738
Engine.FrameSkipTimer = 0
739
end if
740
741
// Make the Floor render in High Quality mode now
742
// (...shouldn't this be done when the stage state is reset? why is it being done afterwards?)
743
TileLayer[0].Type = LAYER_3DSKY
744
745
end if
746
break
747
748
case PAUSEMENU_EXIT
749
if Object.SelectionBarPos > PAUSEMENU_LEFTMOST
750
// Not arrived at the destination yet, keep on moving
751
752
Object.SelectionBarPos -= 16
753
Object.UnderlinePos += 16
754
else
755
756
// From here, jump to the handling needed
757
758
switch Object.CurrentSelection
759
case PAUSEMENU_SEL_RESTART
760
// You should never be able to restart a Special Stage, so this piece of code goes unused...
761
762
LampPost.Check = 0
763
Player.Lives--
764
765
LoadStage()
766
break
767
768
case PAUSEMENU_SEL_EXIT
769
// Before Exiting, reset everything for the next playthrough
770
771
Good_Future_Count = 0
772
Good_Future_List = 0
773
774
Good_Future = false
775
Transporter_Destroyed = false
776
MetalSonic_Destroyed = false
777
778
Stage.ActiveList = PRESENTATION_STAGE
779
780
LampPost.Check = 0
781
782
// Time Attack should return to the TA Menu, but otherwise go back to the Title Screen
783
if Options.GameMode == MODE_TIMEATTACK
784
Stage.ListPos = STAGE_P_TIMEATTACK
785
TimeAttack.Result = 0
786
else
787
Stage.ListPos = STAGE_P_TITLE
788
end if
789
790
LoadStage()
791
break
792
793
case PAUSEMENU_SEL_DEVMENU
794
// To get to the Dev Menu, we need to reset the entire game rather than directly opening the menu or anything like that
795
Engine.State = RESET_GAME
796
break
797
798
end switch
799
end if
800
break
801
802
end switch
803
804
end sub
805
806
807
sub ObjectDraw
808
switch Object.State
809
case PAUSEMENU_INIT
810
case PAUSEMENU_SLIDEIN
811
case PAUSEMENU_FADEIN
812
813
// Draw the White Rectangle Background
814
815
// Don't draw it if it's at the bottom of the screen already
816
if Object.PrevWhiteRectPos < SCREEN_YSIZE
817
if Object.WhiteRectPos > Object.PrevWhiteRectPos
818
819
// Note that the Stage State is currently paused, in other words nothing is getting rendered
820
// -> That means that, if we were to simply draw a white tint rectangle from 0,0 to whereever,
821
// it would overlap with what was drawn the previous frame, and that would continously stack
822
// -> Because of that, we have to not draw the entire tint rect at once, but
823
// draw only the difference from the previous frame every time instead
824
825
// Find how tall the tint rectangle should be
826
TempValue0 = Object.WhiteRectPos
827
TempValue0 -= Object.PrevWhiteRectPos
828
829
// Now, draw it at the previous rect position with the height found from earlier
830
DrawRect(0, Object.PrevWhiteRectPos, 384, TempValue0, 255, 255, 255, 128)
831
Object.PrevWhiteRectPos = Object.WhiteRectPos
832
833
end if
834
end if
835
836
// Fall through to the next part
837
// Note - Originally, there was a whole identical duplicate of the below code here, but Origins actually cleaned it up
838
// and made it easier for our eyes! How nice of them!
839
840
case PAUSEMENU_MAIN
841
842
// First, draw all the waves on the right
843
DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)
844
DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)
845
DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)
846
DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)
847
DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)
848
DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)
849
DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)
850
DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)
851
852
// Draw the black rectangle on top of them too
853
TempValue0 = Object.SelectionBarPos
854
TempValue0 += 128
855
DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)
856
857
// Draw the Pause bar
858
DrawRect(0, 202, Object.PauseBarXPos, 13, 0, 0, 0, 255)
859
DrawSpriteScreenFX(4, FX_INK, 0, 202)
860
861
// Update Underline scrolling
862
863
TempValue0 = Object.SelectionBarPos
864
TempValue0 += 48
865
866
if Object.UnderlinePos > TempValue0
867
TempValue1 = TempValue0
868
TempValue1 -= Object.UnderlinePos
869
TempValue1 >>= 3
870
871
// Move the unedrline to the left
872
Object.UnderlinePos += TempValue1
873
end if
874
875
// Draw the Continue text
876
877
TempValue1 = 48
878
DrawSpriteScreenFX(6, FX_INK, TempValue0, TempValue1)
879
880
if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE
881
// If it's the current selection, then draw the underline and mini Sonic next to it
882
883
DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)
884
DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)
885
end if
886
887
// Move down to the Selection text position
888
TempValue1 += 48
889
890
// Draw the Continue sprite, based on whether it's enabled or not
891
// (It's always gonna be disabled anyway though)
892
if Object.RestartDisabled == false
893
DrawSpriteScreenFX(7, FX_INK, TempValue0, TempValue1)
894
else
895
DrawSpriteScreenFX(10, FX_INK, TempValue0, TempValue1)
896
end if
897
898
if Object.CurrentSelection == PAUSEMENU_SEL_RESTART
899
// If it's the current selection, then draw the underline underneath and along with Sonic next to it
900
// -> As said earlier though, Restart's always disabled in Special Stages so...
901
902
DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)
903
DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)
904
end if
905
906
// Now, move to the Exit text position
907
TempValue1 += 48
908
909
// Draw the Exit text
910
DrawSpriteScreenFX(8, FX_INK, TempValue0, TempValue1)
911
912
if Object.CurrentSelection == PAUSEMENU_SEL_EXIT
913
// If Exit is currently selected, then draw the underline and Sonic along with with
914
915
DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)
916
DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)
917
end if
918
919
// Last but certainly not least, move to the Dev Menu text pos
920
TempValue1 += 48
921
922
if Options.DevMenuFlag == true
923
924
// Draw the Dev Menu text
925
DrawSpriteScreenFX(9, FX_INK, TempValue0, TempValue1)
926
927
if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU
928
// And if it's the current selection, then do the usual
929
930
DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)
931
DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)
932
end if
933
end if
934
break
935
936
case PAUSEMENU_FLASH
937
938
// Draw all the Bars
939
DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)
940
DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)
941
DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)
942
DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)
943
DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)
944
DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)
945
DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)
946
DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)
947
948
// And a black rectangle on top of those bars
949
TempValue0 = Object.SelectionBarPos
950
TempValue0 += 128
951
DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)
952
953
// Then, draw the Pause text bar
954
DrawRect(0, 202, Object.PauseBarXPos, 13, 0, 0, 0, 255)
955
DrawSpriteScreenXY(4, 0, 202)
956
957
// Get the X Positions for the texts
958
TempValue0 = Object.SelectionBarPos
959
TempValue0 += 48
960
961
// And now, the Y position for the Continue text
962
TempValue1 = 48
963
964
if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE
965
966
// Draw the Continue text, but only every other second frame
967
if Object.Timer < 2
968
DrawSpriteScreenXY(6, TempValue0, TempValue1)
969
end if
970
971
// And then of course, the underline and Sonic come after
972
DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)
973
DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)
974
975
else
976
// Nothing special to do here, just draw the Continue text with a fade out effect
977
978
DrawSpriteScreenFX(6, FX_INK, TempValue0, TempValue1)
979
end if
980
981
// Then comes the Restart text
982
TempValue1 += 48
983
984
if Object.CurrentSelection == PAUSEMENU_SEL_RESTART
985
// As said many times before, you can't restart in Special Stages, so this all goes unused
986
987
// Flash the Restart text
988
if Object.Timer < 2
989
DrawSpriteScreenXY(7, TempValue0, TempValue1)
990
end if
991
992
// And then draw the underline and Sonic too
993
DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)
994
DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)
995
996
else
997
if Object.RestartDisabled == false
998
// This part kinda goes unused too
999
1000
DrawSpriteScreenFX(7, FX_INK, TempValue0, TempValue1)
1001
else
1002
// Draw the greyed out Restart text, fading out
1003
1004
DrawSpriteScreenFX(10, FX_INK, TempValue0, TempValue1)
1005
end if
1006
end if
1007
1008
// After that comes the Exit text
1009
TempValue1 += 48
1010
1011
if Object.CurrentSelection == PAUSEMENU_SEL_EXIT
1012
1013
// Flash it as needed
1014
if Object.Timer < 2
1015
DrawSpriteScreenXY(8, TempValue0, TempValue1)
1016
end if
1017
1018
// And then, as with all the others, draw the underline and Sonic too
1019
DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)
1020
DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)
1021
1022
else
1023
// The player didn't choose to exit, so fade out the Exit text
1024
DrawSpriteScreenFX(8, FX_INK, TempValue0, TempValue1)
1025
end if
1026
1027
// And then, the elusive Dev Menu
1028
TempValue1 += 48
1029
1030
if Options.DevMenuFlag == true
1031
1032
if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU
1033
1034
// Flash the Dev Menu text
1035
if Object.Timer < 2
1036
DrawSpriteScreenXY(9, TempValue0, TempValue1)
1037
end if
1038
1039
// Underneath it, draw the underline
1040
DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)
1041
1042
// But to the left, draw Sonic
1043
DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)
1044
1045
else
1046
// Fade out the Dev Menu text
1047
1048
DrawSpriteScreenFX(9, FX_INK, TempValue0, TempValue1)
1049
end if
1050
1051
end if
1052
break
1053
1054
case PAUSEMENU_CLOSE
1055
// This is the state where the Pause Menu is leaving the screen, after the player chose to resume the game
1056
1057
if Object.Alpha < 128
1058
// Draw the white fade-in rectangle, around the entire screen
1059
1060
// The stage is resumed now, meaning it's drawing again, which is why
1061
// we can do the entire screen at once rather than the old `only difference` system needed before
1062
1063
DrawRect(0, 0, Screen.XSize, SCREEN_YSIZE, 255, 255, 255, Object.Alpha)
1064
end if
1065
1066
// On top of that fade rectangle, draw the Pause Menu
1067
1068
// First, all the waves
1069
DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)
1070
DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)
1071
DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)
1072
DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)
1073
DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)
1074
DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)
1075
DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)
1076
DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)
1077
1078
// Then, draw the black rectangle on the right
1079
TempValue0 = Object.SelectionBarPos
1080
TempValue0 += 128
1081
DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)
1082
1083
// Draw the Pause text's Bar
1084
DrawRect(0, Object.PauseBarYPos, Screen.XSize, 13, 0, 0, 0, 255)
1085
1086
// And then, draw the actual Pause text on top of that
1087
DrawSpriteScreenXY(4, 0, Object.PauseBarYPos)
1088
1089
// From here, the only text drawn is that of the current selection
1090
// So, jump as needed
1091
switch Object.CurrentSelection
1092
case PAUSEMENU_SEL_CONTINUE
1093
DrawSpriteScreenXY(6, Object.UnderlinePos, 48)
1094
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 48)
1095
break
1096
1097
case PAUSEMENU_SEL_RESTART
1098
// Huh? Why is the Continue sprite being used here?
1099
// The Restart sprite is frame 7...
1100
DrawSpriteScreenXY(6, Object.UnderlinePos, 96)
1101
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 96)
1102
break
1103
1104
case PAUSEMENU_SEL_EXIT
1105
DrawSpriteScreenXY(8, Object.UnderlinePos, 144)
1106
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 144)
1107
break
1108
1109
case PAUSEMENU_SEL_DEVMENU
1110
if Options.DevMenuFlag == true
1111
DrawSpriteScreenXY(9, Object.UnderlinePos, 192)
1112
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 192)
1113
end if
1114
break
1115
1116
end switch
1117
break
1118
1119
case PAUSEMENU_EXIT
1120
// This is the state where the Pause Menu envelopes the screen, after choosing an option that isn't Continue
1121
1122
// Black out the right side of the screen
1123
TempValue0 = Screen.XSize
1124
TempValue0 -= 96
1125
DrawRect(TempValue0, 0, 96, SCREEN_YSIZE, 0, 0, 0, 255)
1126
1127
// Now, draw all the waves
1128
DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)
1129
DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)
1130
DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)
1131
DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)
1132
DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)
1133
DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)
1134
DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)
1135
DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)
1136
1137
// And the black rectangle ontop of them, since it's sweeping left
1138
TempValue0 = Object.SelectionBarPos
1139
TempValue0 += 128
1140
DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)
1141
1142
// Draw the option selected and its underline as well, sliding to the right
1143
switch Object.CurrentSelection
1144
case PAUSEMENU_SEL_CONTINUE
1145
DrawSpriteScreenXY(6, Object.UnderlinePos, 48)
1146
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 48)
1147
break
1148
1149
case PAUSEMENU_SEL_RESTART
1150
// This is still using the continue sprite...
1151
DrawSpriteScreenXY(6, Object.UnderlinePos, 96)
1152
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 96)
1153
break
1154
1155
case PAUSEMENU_SEL_EXIT
1156
DrawSpriteScreenXY(8, Object.UnderlinePos, 144)
1157
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 144)
1158
break
1159
1160
case PAUSEMENU_SEL_DEVMENU
1161
if Options.DevMenuFlag == true
1162
DrawSpriteScreenXY(9, Object.UnderlinePos, 192)
1163
DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 192)
1164
end if
1165
break
1166
1167
end switch
1168
break
1169
1170
end switch
1171
1172
end sub
1173
1174
1175
sub ObjectStartup
1176
1177
// Load the correct sprites for each language
1178
switch Engine.Language
1179
case LANG_ENGLISH
1180
case LANG_JAPANESE
1181
LoadSpriteSheet("Special/ScoreScreen.gif")
1182
break
1183
1184
case LANG_FRENCH
1185
LoadSpriteSheet("Special/ScoreScreen_FR.gif")
1186
break
1187
1188
case LANG_ITALIAN
1189
LoadSpriteSheet("Special/ScoreScreen_IT.gif")
1190
break
1191
1192
case LANG_DEUTSCH
1193
LoadSpriteSheet("Special/ScoreScreen_DE.gif")
1194
break
1195
1196
case LANG_SPANISH
1197
LoadSpriteSheet("Special/ScoreScreen_ES.gif")
1198
break
1199
1200
end switch
1201
1202
// The mini character frames should, of course, be different for each character
1203
if Stage.PlayerListPos == PLAYER_SONIC_A // PLAYER_SONIC in origins
1204
// 0 - Standing Sonic
1205
SpriteFrame(-28, -14, 16, 24, 1, 231)
1206
// 1-2 - Impatient Sonic
1207
SpriteFrame(-28, -14, 16, 24, 18, 231)
1208
SpriteFrame(-28, -14, 16, 24, 35, 231)
1209
end if
1210
if Stage.PlayerListPos == PLAYER_TAILS_A // PLAYER_TAILS in origins
1211
// 0 - Normal Tails
1212
SpriteFrame(-28, -14, 16, 24, 122, 202)
1213
// 1-2 - Tapping Tails
1214
SpriteFrame(-28, -14, 16, 24, 139, 202)
1215
SpriteFrame(-28, -14, 16, 24, 156, 202)
1216
end if
1217
1218
#platform: Use_Origins
1219
if Stage.PlayerListPos == PLAYER_KNUCKLES
1220
// 0 - Normal Knuckles
1221
SpriteFrame(-28, -14, 16, 24, 1, 256)
1222
// 1-2 - Tapping Knuckles
1223
SpriteFrame(-28, -14, 16, 24, 18, 256)
1224
SpriteFrame(-28, -14, 16, 24, 35, 256)
1225
end if
1226
if Stage.PlayerListPos == PLAYER_AMY
1227
// 0 - Normal Amy
1228
SpriteFrame(-28, -14, 16, 24, 52, 256)
1229
// 1-2 - Tapping Amy
1230
SpriteFrame(-28, -14, 16, 24, 70, 256)
1231
SpriteFrame(-28, -14, 16, 24, 88, 256)
1232
end if
1233
#endplatform
1234
// 3 - Wave
1235
SpriteFrame(0, 0, 128, 32, 0, 128)
1236
1237
// 4 - Pause Header
1238
SpriteFrame(0, -19, 128, 32, 0, 160)
1239
1240
// 5 - Underline
1241
SpriteFrame(-6, 7, 128, 3, 0, 193)
1242
1243
// All the remaining text Frames are different between languages
1244
switch Engine.Language
1245
case LANG_ENGLISH
1246
case LANG_JAPANESE
1247
1248
// 6 - Continue
1249
SpriteFrame(0, -5, 65, 11, 0, 197)
1250
1251
// 7 - Restart
1252
SpriteFrame(0, -5, 55, 11, 66, 197)
1253
1254
// 8 - Exit
1255
SpriteFrame(0, -5, 30, 11, 0, 209)
1256
1257
// 9 - Dev Menu
1258
SpriteFrame(0, -5, 64, 11, 31, 209)
1259
1260
// 10 - Greyed out Restart
1261
SpriteFrame(0, -5, 55, 11, 52, 244)
1262
break
1263
1264
case LANG_FRENCH
1265
1266
// 6 - Continuer
1267
SpriteFrame(0, -5, 73, 11, 0, 197)
1268
1269
// 7 - Recommencer
1270
SpriteFrame(0, -5, 95, 11, 0, 209)
1271
1272
// 8 - Quitter
1273
SpriteFrame(0, -5, 53, 11, 148, 244)
1274
1275
// 9 - Dev
1276
SpriteFrame(0, -5, 23, 11, 96, 209)
1277
1278
// 10 - Recommencer (grey)
1279
SpriteFrame(0, -5, 95, 11, 52, 244)
1280
break
1281
1282
case LANG_ITALIAN
1283
1284
// 6 - Continua
1285
SpriteFrame(0, -5, 65, 11, 0, 197)
1286
1287
// 7 - Ricomincia
1288
SpriteFrame(0, -5, 78, 11, 0, 209)
1289
1290
// 8 - Esci
1291
SpriteFrame(0, -5, 28, 11, 66, 197)
1292
1293
// 9 - Dev
1294
SpriteFrame(0, -5, 23, 11, 79, 209)
1295
1296
// 10 - Grey Ricomincia
1297
SpriteFrame(0, -5, 78, 11, 52, 244)
1298
break
1299
1300
case LANG_DEUTSCH
1301
1302
// 6 - Weiter
1303
SpriteFrame(0, -5, 48, 11, 0, 197)
1304
1305
// 7 - Neustart
1306
SpriteFrame(0, -5, 65, 11, 0, 209)
1307
1308
// 8 - Verlassen
1309
SpriteFrame(0, -5, 71, 11, 49, 197)
1310
1311
// 9 - Dev
1312
SpriteFrame(0, -5, 23, 11, 66, 209)
1313
1314
// 10 - Neustart (grey)
1315
SpriteFrame(0, -5, 65, 11, 52, 244)
1316
break
1317
1318
case LANG_SPANISH
1319
1320
// 6 - Continuar
1321
SpriteFrame(0, -5, 73, 11, 0, 197)
1322
1323
// 7 - Reiniciar
1324
SpriteFrame(0, -5, 67, 11, 0, 209)
1325
1326
// 8 - Salir
1327
SpriteFrame(0, -5, 36, 11, 74, 197)
1328
1329
// 9 - Dev
1330
SpriteFrame(0, -5, 23, 11, 68, 209)
1331
1332
// 10 - Grey Reiniciar
1333
SpriteFrame(0, -5, 67, 11, 52, 244)
1334
break
1335
1336
end switch
1337
1338
end sub
1339
1340
1341
// ========================
1342
// Editor Subs
1343
// ========================
1344
1345
sub RSDKDraw
1346
DrawSprite(0)
1347
end sub
1348
1349
1350
sub RSDKLoad
1351
LoadSpriteSheet("Special/ScoreScreen.gif")
1352
SpriteFrame(-64, -16, 128, 32, 0, 160)
1353
1354
SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
1355
end sub
1356
1357