Path: blob/main/Scripts/Special/PauseMenu.txt
1319 views
//-----------------Sonic CD Pause Menu Script-----------------//1//--------Scripted by Christian Whitehead 'The Taxman'--------//2//-------Unpacked By Rubberduckycooly's Script Unpacker-------//34// Aliases56// How long the Pause Menu should initially slide out for7#alias Object.PropertyValue : Object.ExtendTime89#alias Object.Value0 : Object.Timer1011// The current highlighted selection, check out the PAUSEMENU_SEL_* aliases right down below12#alias Object.Value1 : Object.CurrentSelection1314// Selection Aliases15#alias -1 : PAUSEMENU_SEL_NULL16#alias 0 : PAUSEMENU_SEL_CONTINUE17#alias 1 : PAUSEMENU_SEL_RESTART18#alias 2 : PAUSEMENU_SEL_EXIT19#alias 3 : PAUSEMENU_SEL_DEVMENU2021// X Position of the underline that's underneat the Options texts22#alias Object.Value2 : Object.UnderlinePos2324// X Position for the Black Bar behind the Pause Text25// This is accompanied by PauseBarYPos, check out below for more about Value4 since it's multi-use in this Object26#alias Object.Value3 : Object.PauseBarXPos2728// Value4 has different uses across this Object's various States2930// In states 0-2:31// Value 4 is used to hold the Y Position of the White Rectangle32#alias Object.Value4 : Object.WhiteRectPos3334// And then, this holds the position of that White Rectangle from the previous frame during those states35// -> See ObjectDraw for more info36#alias Object.Value5 : Object.PrevWhiteRectPos3738// In states 4-5:39// Value 4 is used to hold the Y Position of the Pause text & its bar40// Check out PauseBarXPos too, though that one's just a normal Value and only has one use41#alias Object.Value4 : Object.PauseBarYPos4243// For clarity's sake, the two types of Value 4 uses are aliases differently4445// Just a bool, essentially useless since restarts are always disabled in Special Stages so there's no reason for this to be here46// 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 purpose47#alias Object.Value6 : Object.RestartDisabled4849// Position of the stuff on the right side (options, black bar, etc.)50#alias Object.XPos : Object.SelectionBarPos5152// values for the tiny 'lil sonic :)53#alias Object.Frame : Object.SonicFrame54#alias Object.AnimationTimer : Object.SonicTimer5556// States5758// This Object can't have its value setup via a normal loop in ObjectStartup since it doesn't even exist59// normally - it's spawned in by the Sonic Object instead - so the first state is for initialising its values60#alias 0 : PAUSEMENU_INIT6162// 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 right63#alias 1 : PAUSEMENU_SLIDEIN6465// After that, now the Sprite aspects of it fade in, like the Options and Pause text66#alias 2 : PAUSEMENU_FADEIN6768// Yup, now we're in the main state!69// This is where all the good stuff is done, of course70#alias 3 : PAUSEMENU_MAIN7172// Upon selecting any option, the selected option will flash for a few moments...73#alias 4 : PAUSEMENU_FLASH7475// ... and after that comes a branch of fate - choose a path!7677// If you selected the Continue option, then...78// Close the Pause Menu, and resume the normal game79#alias 5 : PAUSEMENU_CLOSE8081// If you selected any other option, then...82// Make the Pause Menu consume the screen, and exit the level or whatever afterwards83#alias 6 : PAUSEMENU_EXIT8485// One of the updates changed the left bounds for how far the Pause Menu should go86// Originally was -32, but the current version is -6487// That's about a two frames difference, isn't that interesting?88#alias -64 : PAUSEMENU_LEFTMOST8990// Player Aliases91#alias 0 : PLAYER_SONIC_A92#alias 1 : PLAYER_TAILS_A9394// Presentation Stages95#alias 0 : STAGE_P_TITLE96#alias 2 : STAGE_P_TIMEATTACK9798// Languages99#alias 0 : LANG_ENGLISH100#alias 1 : LANG_FRENCH101#alias 2 : LANG_ITALIAN102#alias 3 : LANG_DEUTSCH103#alias 4 : LANG_SPANISH104#alias 5 : LANG_JAPANESE105106// Screen Aliases107// This Object uses a hardcoded constant of 240 rather often, rather than Screen.YSize, so this is here just to clarify stuff a bit108#alias 240 : SCREEN_YSIZE109110// Global SFX111#alias 23 : SFX_G_MENUBUTTON112#alias 27 : SFX_G_SELECT113114// Ink Effect Aliases115#alias 2 : INK_ALPHA116117// Game Mode Aliases118#alias 2 : MODE_TIMEATTACK119120// Engine Messages121// (Strange to describe, but they're essentially system-level stuff that the engine transmits to the scripts)122#alias 2 : MESSAGE_LOSTFOCUS123#alias 3 : MESSAGE_YES_SELECTED124#alias 4 : MESSAGE_NO_SELECTED125126// Engine Callbacks127#alias 6 : CALLBACK_RESTART_SELECTED128#alias 7 : CALLBACK_EXIT_SELECTED129130// Tile Layer Types131#alias 4 : LAYER_3DSKY132133134sub ObjectMain135switch Object.State136case PAUSEMENU_INIT137// Object just got spawned, setup everything here138139// Start the right Bar to be, well, off to the right140Object.SelectionBarPos = Screen.XSize141142// And then make the left Pause bar start all the way to the left143Object.PauseBarXPos = 0144145Object.Timer = 0146147// The Object uses alpha effects to fade-in the test, so get that all set up too148Object.InkEffect = INK_ALPHA149Object.Alpha = 0150151// Some languages have longer text than others152// LANG_FRENCH is the longest, while the standard LANG_ENGLISH version is the shortest153switch Engine.Language154case LANG_ENGLISH155case LANG_JAPANESE156Object.ExtendTime = 12157break158159case LANG_FRENCH160Object.ExtendTime = 15161break162163// A bit of fall-through could probably be used on these last three entries, but it isn't164// Oh well165166case LANG_ITALIAN167Object.ExtendTime = 13168break169170case LANG_DEUTSCH171Object.ExtendTime = 13172break173174case LANG_SPANISH175Object.ExtendTime = 13176break177178end switch179180// Disable Restarting if needed... but it's always gonna be disabled181if Player.Lives < 2182Object.RestartDisabled = true183else184185// This version of the Pause Menu is only used in Special Stages anyway... so why is this check here?186// Likely just a result of copy-pasting the maingame one, if I had to guess, as that one187// 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 stages188#platform: Use_Standalone189if Stage.ActiveList == SPECIAL_STAGE190Object.RestartDisabled = true191else192Object.RestartDisabled = false193end if194#endplatform195196#platform: Use_Origins197// Origins messed up the Active List IDs ("SPECIAL_STAGE" points to the Bonus Stage list now!) so we check via a direct ID instead here198if Stage.ActiveList == 3199Object.RestartDisabled = true200else201Object.RestartDisabled = false202end if203#endplatform204205end if206#platform: Use_Origins207// On Origins, Physical Controls are enforced as the default208Options.PhysicalControls = true209#endplatform210211#platform: Mobile212// On Mobile though, have a default selection (or don't) based on if the Player's using a physical gamepad or not213if Options.TouchControls == true214Object.CurrentSelection = PAUSEMENU_SEL_NULL215Options.PhysicalControls = false216else217// (Implicitly making the starting selection PAUSEMENU_SEL_CONTINUE - ID 0)218Options.PhysicalControls = true219end if220#endplatform221222Object.State++223break224225case PAUSEMENU_SLIDEIN226227// Slide the Pause bar in228Object.PauseBarXPos = Object.Timer229Object.PauseBarXPos *= Screen.XSize230Object.PauseBarXPos /= 12231232// And then move the background white rectangle in233Object.WhiteRectPos = Object.Timer234Object.WhiteRectPos *= SCREEN_YSIZE235Object.WhiteRectPos /= 12236237// And then slide the right bar in too238239TempValue0 = Object.Timer240TempValue0 <<= 7241TempValue0 /= 12242243Object.SelectionBarPos = Screen.XSize244Object.SelectionBarPos -= TempValue0245246if Object.Timer < Object.ExtendTime247// Haven't reached where we should yet, keep moving...248249Object.Timer++250else251// Get ready to go to the next state252253// Setup the Underline initial position254Object.UnderlinePos = Object.SelectionBarPos255Object.UnderlinePos += 48256257Object.Timer = 0258259Object.State++260end if261break262263case PAUSEMENU_FADEIN264if Object.Timer < 256265Object.Timer += 16266267// Because Object.Alpha is a byte and will overflow if over 255,268// we have to do this instead269if Object.Timer < 255270Object.Alpha = Object.Timer271else272Object.Alpha = 255273end if274else275// Next state276277Object.Timer = 0278279// Just to make sure it's at full opacity280Object.Alpha = 255281282Object.State++283end if284break285286case PAUSEMENU_MAIN287288// There's normally a `if Options.PhysicalControls == true` path here, but to keep 2012 Steam datafiles working we gotta do this roundabout way instead289#platform: Standard290// Let's assume the variable doesn't exist, force Physical Controls291CheckResult = true292#endplatform293294#platform: Mobile295CheckEqual(Options.PhysicalControls, true)296#endplatform297298#platform: Use_Origins299CheckEqual(Options.PhysicalControls, true)300#endplatform301302303if CheckResult == true304// Update Physical Controls305306if KeyPress[0].Up == true307308PlaySfx(SFX_G_MENUBUTTON, false)309310// Reset all the stuff311312Object.Timer = 0313314// Sonic should resume his normal stance315Object.SonicTimer = 0316Object.SonicFrame = 0317318// Move the bar all the way over to the right319Object.UnderlinePos = Screen.XSize320321// And of course, bump down the current selection by one322Object.CurrentSelection--323324// Enforce different upwards loop points based on if the 4th Dev Menu option is available or not325if Options.DevMenuFlag == true326if Object.CurrentSelection < PAUSEMENU_SEL_CONTINUE327Object.CurrentSelection = PAUSEMENU_SEL_DEVMENU328end if329else330if Object.CurrentSelection < PAUSEMENU_SEL_CONTINUE331Object.CurrentSelection = PAUSEMENU_SEL_EXIT332end if333end if334335// If restart is disabled (which it always should be here) then don't let the player select it336if Object.RestartDisabled == true337if Object.CurrentSelection == PAUSEMENU_SEL_RESTART338// Move them to the PAUSEMENU_SEL_CONTINUE instead339Object.CurrentSelection--340end if341end if342343end if344345if KeyPress[0].Down == true346347PlaySfx(SFX_G_MENUBUTTON, false)348349// Reset some stuff350351Object.Timer = 0352353Object.SonicTimer = 0354Object.SonicFrame = 0355356// Move the line back offscreen357Object.UnderlinePos = Screen.XSize358359// And of course, move a selection down360Object.CurrentSelection++361362// The Dev Menu adds a 4th entry, so the wrap around value is different too363if Options.DevMenuFlag == true364if Object.CurrentSelection > PAUSEMENU_SEL_DEVMENU365Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE366end if367else368if Object.CurrentSelection > PAUSEMENU_SEL_EXIT369Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE370end if371end if372373// If restarting is disabled (always the case here in Special Stages) then374// move the player's selection to PAUSEMENU_SEL_EXIT instead375if Object.RestartDisabled == true376if Object.CurrentSelection == PAUSEMENU_SEL_RESTART377Object.CurrentSelection++378end if379end if380381end if382383// You can use either Start or A to close a selection, the other two buttons won't do anything though...384if KeyPress[0].Start == true385PlaySfx(SFX_G_SELECT, false)386Object.State = PAUSEMENU_FLASH387Object.Alpha = 248388Object.Timer = 0389end if390391if KeyPress[0].ButtonA == true392PlaySfx(SFX_G_SELECT, false)393Object.State = PAUSEMENU_FLASH394Object.Alpha = 248395Object.Timer = 0396end if397398#platform: Mobile399// If the Player's touched the screen at all, then switch to Touch Controls400CheckTouchRect(0, 0, Screen.XSize, Screen.YSize)401402if CheckResult > -1403Options.PhysicalControls = false404Object.CurrentSelection = PAUSEMENU_SEL_NULL405end if406#endplatform407else408409// If the Player's not even in the game, then reset the current selection410if Engine.Message == MESSAGE_LOSTFOCUS411Object.CurrentSelection = PAUSEMENU_SEL_NULL412end if413414// From here, now we do a whole lotta stuff with touch controls, where we check manually for every option415// For the most part, each chunk of code here is the same, only with one or two minor differences416417// See if the Player's tapped the screen at all, and store the result into TempValue3418// This value is used throughout this entire touch controls section419CheckTouchRect(0, 0, Screen.XSize, Screen.YSize)420TempValue3 = CheckResult421422// And now, check for the Continue button423424// See if the Player's tapped it425CheckTouchRect(TempValue0, 32, Screen.XSize, 64)426427if CheckResult > -1428// If the player has their finger over the Continue button but hasn't relased it yet, then just keep it selected429// but don't actually activate it yet430431Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE432else433if TempValue3 < 0434// The Player doesn't have their finger on the screen *nor* the Continue button435436if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE437// The Player's released their finger while on the button, so let's start Continuing now438439PlaySfx(SFX_G_SELECT, false)440Object.State = PAUSEMENU_FLASH441Object.Alpha = 248442Object.Timer = 0443end if444else445// The Player's finger is on the screen but not on the Continue option, so make them deselect446447if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE448Object.CurrentSelection = PAUSEMENU_SEL_NULL449end if450end if451end if452453// Now, the Restart button454// As said before, RestartDisabled is always gonna be true in a Special Stage so this whole chunk of code is essentially useless...455456// Yeah, I guess they just kept it here anyway because it looked cool or something idk457if Object.RestartDisabled == false458459// See if the Player's got their finger over the Restart button460CheckTouchRect(TempValue0, 80, Screen.XSize, 112)461462if CheckResult > -1463// If they do, then make the current selection Restart464465Object.CurrentSelection = PAUSEMENU_SEL_RESTART466else467if TempValue3 < 0468// The Player isn't touching the screen at all469470if Object.CurrentSelection == PAUSEMENU_SEL_RESTART471// The Player released their finger while hovering over Restart, so let's restart then!472473PlaySfx(SFX_G_SELECT, false)474Object.State = PAUSEMENU_FLASH475Object.Alpha = 248476Object.Timer = 0477end if478else479// The finger has their player on the screen, but not over the Continue button480481if Object.CurrentSelection == PAUSEMENU_SEL_RESTART482Object.CurrentSelection = PAUSEMENU_SEL_NULL483end if484end if485end if486487end if488489// After that comes the wonderful, Exit button!490491// See if there's a finger on it492CheckTouchRect(TempValue0, 128, Screen.XSize, 160)493494if CheckResult > -1495// If there is, then make it the current selection496497Object.CurrentSelection = PAUSEMENU_SEL_EXIT498else499// The Player isn't currently on the Exit button500501if TempValue3 < 0502// And, the Player isn't touching the screen at all!503504if Object.CurrentSelection == PAUSEMENU_SEL_EXIT505// So in that case, if they were on it for at least one frame before, then let's go ahead and Exit506507PlaySfx(SFX_G_SELECT, false)508Object.State = PAUSEMENU_FLASH509Object.Alpha = 248510Object.Timer = 0511end if512else513// The Player's finger is on the screen, but not on the Exit button514515if Object.CurrentSelection == PAUSEMENU_SEL_EXIT516Object.CurrentSelection = PAUSEMENU_SEL_NULL517end if518end if519end if520521// Yup, and now the Dev Menu button!522// It only shows under the most special conditions, they say...523524if Options.DevMenuFlag == true525526// Check to see if the Player's touching it527CheckTouchRect(TempValue0, 176, Screen.XSize, 208)528529if CheckResult > -1530// If they are, then make it selected531532Object.CurrentSelection = PAUSEMENU_SEL_DEVMENU533else534// The Player's not touching the Dev Menu button535536if TempValue3 < 0537// Additionally, they're not touching the screen at all either538539if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU540// If they were touching the Dev Menu button last frame, then assume a button press541542PlaySfx(SFX_G_SELECT, false)543Object.State = PAUSEMENU_FLASH544Object.Alpha = 248545Object.Timer = 0546end if547else548// The Player's holding the screen, but they're not touching the Dev Menu button549550if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU551// So just let the button go552Object.CurrentSelection = PAUSEMENU_SEL_NULL553end if554end if555end if556557end if558559// And now, after all that's done, check for actual, physical inputs560561if KeyPress[0].Up == true562563// If Up was pressed, then go to the bottommost entry564// This'll vary if the Dev Menu is active, of course565566if Options.DevMenuFlag == true567Object.CurrentSelection = PAUSEMENU_SEL_DEVMENU568else569Object.CurrentSelection = PAUSEMENU_SEL_EXIT570end if571572#platform: Mobile573// And set Physical Controls to active, now that the player's actually pressed something574575Options.PhysicalControls = true576#endplatform577end if578579if KeyPress[0].Down == true580581// If Down was pressed, then just go to the topmost entry582// Nothing further needed here583584Object.CurrentSelection = PAUSEMENU_SEL_CONTINUE585586#platform: Mobile587// And similarly, set Physical Controls to be active for the same reason as before588589Options.PhysicalControls = true590#endplatform591end if592end if593594// Progress mini Sonic's animation595596if Object.Timer < 60597// Make him stand all nice and polite for a second...598599Object.Timer++600else601// But once that second's over, gotta get moving!602603// Get the topmost bit of Sonic's Animation Timer604Object.SonicFrame = Object.SonicTimer605Object.SonicFrame >>= 4606607// And then bump it up one more to match with the Sprite Frame IDs608Object.SonicFrame++609610Object.SonicTimer++611Object.SonicTimer &= 31612end if613break614615case PAUSEMENU_FLASH616617// In this state, the Timer is used to control the selected sprite's visibility, or flashing618// So, let's progress that value619Object.Timer++620Object.Timer &= 3621622// Slide the underline text away623Object.UnderlinePos += 4624625// First, fade the texts out626if Object.Alpha > 0627Object.Alpha -= 8628else629if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE630// If on the Continue option, then make the Pause Menu move away rather than cover the screen631632Object.UnderlinePos = Object.SelectionBarPos633Object.UnderlinePos += 48634635// Set the initial Y position for the bottom bar636// -> Normally, during the rest of the Pause Menu states, it's a direct constant 202,637// rather than reading from a variable, which is why the new variable is initially being set here638Object.PauseBarYPos = 202639640Object.Timer = 0641Object.Alpha = 128642643Object.State = PAUSEMENU_CLOSE644645// Resume the stage now, rather than when the Pause Menu is fully out of the way646Stage.State = STAGE_RUNNING647else648649// The following code is dependant on the current platform650// Origins uses the Standard platform code, of course651#platform: Standard652Object.UnderlinePos = Object.SelectionBarPos653Object.UnderlinePos += 48654StopMusic()655Object.State = PAUSEMENU_EXIT656#endplatform657658#platform: Mobile659// On Mobile, we got a whole lot of Engine Message stuff to worry about660661if Engine.Message < MESSAGE_YES_SELECTED662switch Object.CurrentSelection663case PAUSEMENU_SEL_RESTART664EngineCallback(CALLBACK_RESTART_SELECTED)665break666667case PAUSEMENU_SEL_EXIT668EngineCallback(CALLBACK_EXIT_SELECTED)669break670671case PAUSEMENU_SEL_DEVMENU672// For the Dev Menu, don't prompt any extra confirmation and just start sliding away already673674Object.UnderlinePos = Object.SelectionBarPos675Object.UnderlinePos += 48676StopMusic()677678Object.State = PAUSEMENU_EXIT679break680681end switch682else683if Engine.Message == MESSAGE_NO_SELECTED684685// Nevermind, let's go back instead686687// Reset everything and resume back to normal688689Object.Timer = 0690691Object.SonicTimer = 0692Object.SonicFrame = 0693Object.UnderlinePos = Screen.XSize694695if Options.PhysicalControls == false696Object.CurrentSelection = PAUSEMENU_SEL_NULL697end if698699Object.State = PAUSEMENU_MAIN700Object.Alpha = 255701702else703// Yup, the Player truly wants to leave704705Object.UnderlinePos = Object.SelectionBarPos706Object.UnderlinePos += 48707StopMusic()708709Object.State = PAUSEMENU_EXIT710end if711end if712#endplatform713end if714end if715break716717case PAUSEMENU_CLOSE718if Object.Alpha > 0719// Closing the Pause Menu...720721// Fade out the text722Object.Alpha -= 8723724// And move all the other shapes out of the way725Object.SelectionBarPos += 16726Object.UnderlinePos += 16727Object.PauseBarYPos += 16728729else730// The Objects are already moving now, let's continue the music too!731ResumeMusic()732733// Erase this current Pause Menu Object, as it's no longer needed734ResetObjectEntity(Object.EntityNo, TypeName[Blank Object], 0, 0, 0)735736if Engine.FrameSkipSetting > 0737Engine.FrameSkipTimer = 0738end if739740// Make the Floor render in High Quality mode now741// (...shouldn't this be done when the stage state is reset? why is it being done afterwards?)742TileLayer[0].Type = LAYER_3DSKY743744end if745break746747case PAUSEMENU_EXIT748if Object.SelectionBarPos > PAUSEMENU_LEFTMOST749// Not arrived at the destination yet, keep on moving750751Object.SelectionBarPos -= 16752Object.UnderlinePos += 16753else754755// From here, jump to the handling needed756757switch Object.CurrentSelection758case PAUSEMENU_SEL_RESTART759// You should never be able to restart a Special Stage, so this piece of code goes unused...760761LampPost.Check = 0762Player.Lives--763764LoadStage()765break766767case PAUSEMENU_SEL_EXIT768// Before Exiting, reset everything for the next playthrough769770Good_Future_Count = 0771Good_Future_List = 0772773Good_Future = false774Transporter_Destroyed = false775MetalSonic_Destroyed = false776777Stage.ActiveList = PRESENTATION_STAGE778779LampPost.Check = 0780781// Time Attack should return to the TA Menu, but otherwise go back to the Title Screen782if Options.GameMode == MODE_TIMEATTACK783Stage.ListPos = STAGE_P_TIMEATTACK784TimeAttack.Result = 0785else786Stage.ListPos = STAGE_P_TITLE787end if788789LoadStage()790break791792case PAUSEMENU_SEL_DEVMENU793// To get to the Dev Menu, we need to reset the entire game rather than directly opening the menu or anything like that794Engine.State = RESET_GAME795break796797end switch798end if799break800801end switch802803end sub804805806sub ObjectDraw807switch Object.State808case PAUSEMENU_INIT809case PAUSEMENU_SLIDEIN810case PAUSEMENU_FADEIN811812// Draw the White Rectangle Background813814// Don't draw it if it's at the bottom of the screen already815if Object.PrevWhiteRectPos < SCREEN_YSIZE816if Object.WhiteRectPos > Object.PrevWhiteRectPos817818// Note that the Stage State is currently paused, in other words nothing is getting rendered819// -> That means that, if we were to simply draw a white tint rectangle from 0,0 to whereever,820// it would overlap with what was drawn the previous frame, and that would continously stack821// -> Because of that, we have to not draw the entire tint rect at once, but822// draw only the difference from the previous frame every time instead823824// Find how tall the tint rectangle should be825TempValue0 = Object.WhiteRectPos826TempValue0 -= Object.PrevWhiteRectPos827828// Now, draw it at the previous rect position with the height found from earlier829DrawRect(0, Object.PrevWhiteRectPos, 384, TempValue0, 255, 255, 255, 128)830Object.PrevWhiteRectPos = Object.WhiteRectPos831832end if833end if834835// Fall through to the next part836// Note - Originally, there was a whole identical duplicate of the below code here, but Origins actually cleaned it up837// and made it easier for our eyes! How nice of them!838839case PAUSEMENU_MAIN840841// First, draw all the waves on the right842DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)843DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)844DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)845DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)846DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)847DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)848DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)849DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)850851// Draw the black rectangle on top of them too852TempValue0 = Object.SelectionBarPos853TempValue0 += 128854DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)855856// Draw the Pause bar857DrawRect(0, 202, Object.PauseBarXPos, 13, 0, 0, 0, 255)858DrawSpriteScreenFX(4, FX_INK, 0, 202)859860// Update Underline scrolling861862TempValue0 = Object.SelectionBarPos863TempValue0 += 48864865if Object.UnderlinePos > TempValue0866TempValue1 = TempValue0867TempValue1 -= Object.UnderlinePos868TempValue1 >>= 3869870// Move the unedrline to the left871Object.UnderlinePos += TempValue1872end if873874// Draw the Continue text875876TempValue1 = 48877DrawSpriteScreenFX(6, FX_INK, TempValue0, TempValue1)878879if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE880// If it's the current selection, then draw the underline and mini Sonic next to it881882DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)883DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)884end if885886// Move down to the Selection text position887TempValue1 += 48888889// Draw the Continue sprite, based on whether it's enabled or not890// (It's always gonna be disabled anyway though)891if Object.RestartDisabled == false892DrawSpriteScreenFX(7, FX_INK, TempValue0, TempValue1)893else894DrawSpriteScreenFX(10, FX_INK, TempValue0, TempValue1)895end if896897if Object.CurrentSelection == PAUSEMENU_SEL_RESTART898// If it's the current selection, then draw the underline underneath and along with Sonic next to it899// -> As said earlier though, Restart's always disabled in Special Stages so...900901DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)902DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)903end if904905// Now, move to the Exit text position906TempValue1 += 48907908// Draw the Exit text909DrawSpriteScreenFX(8, FX_INK, TempValue0, TempValue1)910911if Object.CurrentSelection == PAUSEMENU_SEL_EXIT912// If Exit is currently selected, then draw the underline and Sonic along with with913914DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)915DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)916end if917918// Last but certainly not least, move to the Dev Menu text pos919TempValue1 += 48920921if Options.DevMenuFlag == true922923// Draw the Dev Menu text924DrawSpriteScreenFX(9, FX_INK, TempValue0, TempValue1)925926if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU927// And if it's the current selection, then do the usual928929DrawSpriteScreenFX(5, FX_INK, Object.UnderlinePos, TempValue1)930DrawSpriteScreenFX(Object.SonicFrame, FX_INK, TempValue0, TempValue1)931end if932end if933break934935case PAUSEMENU_FLASH936937// Draw all the Bars938DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)939DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)940DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)941DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)942DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)943DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)944DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)945DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)946947// And a black rectangle on top of those bars948TempValue0 = Object.SelectionBarPos949TempValue0 += 128950DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)951952// Then, draw the Pause text bar953DrawRect(0, 202, Object.PauseBarXPos, 13, 0, 0, 0, 255)954DrawSpriteScreenXY(4, 0, 202)955956// Get the X Positions for the texts957TempValue0 = Object.SelectionBarPos958TempValue0 += 48959960// And now, the Y position for the Continue text961TempValue1 = 48962963if Object.CurrentSelection == PAUSEMENU_SEL_CONTINUE964965// Draw the Continue text, but only every other second frame966if Object.Timer < 2967DrawSpriteScreenXY(6, TempValue0, TempValue1)968end if969970// And then of course, the underline and Sonic come after971DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)972DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)973974else975// Nothing special to do here, just draw the Continue text with a fade out effect976977DrawSpriteScreenFX(6, FX_INK, TempValue0, TempValue1)978end if979980// Then comes the Restart text981TempValue1 += 48982983if Object.CurrentSelection == PAUSEMENU_SEL_RESTART984// As said many times before, you can't restart in Special Stages, so this all goes unused985986// Flash the Restart text987if Object.Timer < 2988DrawSpriteScreenXY(7, TempValue0, TempValue1)989end if990991// And then draw the underline and Sonic too992DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)993DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)994995else996if Object.RestartDisabled == false997// This part kinda goes unused too998999DrawSpriteScreenFX(7, FX_INK, TempValue0, TempValue1)1000else1001// Draw the greyed out Restart text, fading out10021003DrawSpriteScreenFX(10, FX_INK, TempValue0, TempValue1)1004end if1005end if10061007// After that comes the Exit text1008TempValue1 += 4810091010if Object.CurrentSelection == PAUSEMENU_SEL_EXIT10111012// Flash it as needed1013if Object.Timer < 21014DrawSpriteScreenXY(8, TempValue0, TempValue1)1015end if10161017// And then, as with all the others, draw the underline and Sonic too1018DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)1019DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)10201021else1022// The player didn't choose to exit, so fade out the Exit text1023DrawSpriteScreenFX(8, FX_INK, TempValue0, TempValue1)1024end if10251026// And then, the elusive Dev Menu1027TempValue1 += 4810281029if Options.DevMenuFlag == true10301031if Object.CurrentSelection == PAUSEMENU_SEL_DEVMENU10321033// Flash the Dev Menu text1034if Object.Timer < 21035DrawSpriteScreenXY(9, TempValue0, TempValue1)1036end if10371038// Underneath it, draw the underline1039DrawSpriteScreenXY(5, Object.UnderlinePos, TempValue1)10401041// But to the left, draw Sonic1042DrawSpriteScreenXY(Object.SonicFrame, TempValue0, TempValue1)10431044else1045// Fade out the Dev Menu text10461047DrawSpriteScreenFX(9, FX_INK, TempValue0, TempValue1)1048end if10491050end if1051break10521053case PAUSEMENU_CLOSE1054// This is the state where the Pause Menu is leaving the screen, after the player chose to resume the game10551056if Object.Alpha < 1281057// Draw the white fade-in rectangle, around the entire screen10581059// The stage is resumed now, meaning it's drawing again, which is why1060// we can do the entire screen at once rather than the old `only difference` system needed before10611062DrawRect(0, 0, Screen.XSize, SCREEN_YSIZE, 255, 255, 255, Object.Alpha)1063end if10641065// On top of that fade rectangle, draw the Pause Menu10661067// First, all the waves1068DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)1069DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)1070DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)1071DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)1072DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)1073DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)1074DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)1075DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)10761077// Then, draw the black rectangle on the right1078TempValue0 = Object.SelectionBarPos1079TempValue0 += 1281080DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)10811082// Draw the Pause text's Bar1083DrawRect(0, Object.PauseBarYPos, Screen.XSize, 13, 0, 0, 0, 255)10841085// And then, draw the actual Pause text on top of that1086DrawSpriteScreenXY(4, 0, Object.PauseBarYPos)10871088// From here, the only text drawn is that of the current selection1089// So, jump as needed1090switch Object.CurrentSelection1091case PAUSEMENU_SEL_CONTINUE1092DrawSpriteScreenXY(6, Object.UnderlinePos, 48)1093DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 48)1094break10951096case PAUSEMENU_SEL_RESTART1097// Huh? Why is the Continue sprite being used here?1098// The Restart sprite is frame 7...1099DrawSpriteScreenXY(6, Object.UnderlinePos, 96)1100DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 96)1101break11021103case PAUSEMENU_SEL_EXIT1104DrawSpriteScreenXY(8, Object.UnderlinePos, 144)1105DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 144)1106break11071108case PAUSEMENU_SEL_DEVMENU1109if Options.DevMenuFlag == true1110DrawSpriteScreenXY(9, Object.UnderlinePos, 192)1111DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 192)1112end if1113break11141115end switch1116break11171118case PAUSEMENU_EXIT1119// This is the state where the Pause Menu envelopes the screen, after choosing an option that isn't Continue11201121// Black out the right side of the screen1122TempValue0 = Screen.XSize1123TempValue0 -= 961124DrawRect(TempValue0, 0, 96, SCREEN_YSIZE, 0, 0, 0, 255)11251126// Now, draw all the waves1127DrawSpriteScreenXY(3, Object.SelectionBarPos, 0)1128DrawSpriteScreenXY(3, Object.SelectionBarPos, 32)1129DrawSpriteScreenXY(3, Object.SelectionBarPos, 64)1130DrawSpriteScreenXY(3, Object.SelectionBarPos, 96)1131DrawSpriteScreenXY(3, Object.SelectionBarPos, 128)1132DrawSpriteScreenXY(3, Object.SelectionBarPos, 160)1133DrawSpriteScreenXY(3, Object.SelectionBarPos, 192)1134DrawSpriteScreenXY(3, Object.SelectionBarPos, 224)11351136// And the black rectangle ontop of them, since it's sweeping left1137TempValue0 = Object.SelectionBarPos1138TempValue0 += 1281139DrawRect(TempValue0, 0, 128, Screen.YSize, 0, 0, 0, 255)11401141// Draw the option selected and its underline as well, sliding to the right1142switch Object.CurrentSelection1143case PAUSEMENU_SEL_CONTINUE1144DrawSpriteScreenXY(6, Object.UnderlinePos, 48)1145DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 48)1146break11471148case PAUSEMENU_SEL_RESTART1149// This is still using the continue sprite...1150DrawSpriteScreenXY(6, Object.UnderlinePos, 96)1151DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 96)1152break11531154case PAUSEMENU_SEL_EXIT1155DrawSpriteScreenXY(8, Object.UnderlinePos, 144)1156DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 144)1157break11581159case PAUSEMENU_SEL_DEVMENU1160if Options.DevMenuFlag == true1161DrawSpriteScreenXY(9, Object.UnderlinePos, 192)1162DrawSpriteScreenXY(Object.SonicFrame, Object.UnderlinePos, 192)1163end if1164break11651166end switch1167break11681169end switch11701171end sub117211731174sub ObjectStartup11751176// Load the correct sprites for each language1177switch Engine.Language1178case LANG_ENGLISH1179case LANG_JAPANESE1180LoadSpriteSheet("Special/ScoreScreen.gif")1181break11821183case LANG_FRENCH1184LoadSpriteSheet("Special/ScoreScreen_FR.gif")1185break11861187case LANG_ITALIAN1188LoadSpriteSheet("Special/ScoreScreen_IT.gif")1189break11901191case LANG_DEUTSCH1192LoadSpriteSheet("Special/ScoreScreen_DE.gif")1193break11941195case LANG_SPANISH1196LoadSpriteSheet("Special/ScoreScreen_ES.gif")1197break11981199end switch12001201// The mini character frames should, of course, be different for each character1202if Stage.PlayerListPos == PLAYER_SONIC_A // PLAYER_SONIC in origins1203// 0 - Standing Sonic1204SpriteFrame(-28, -14, 16, 24, 1, 231)1205// 1-2 - Impatient Sonic1206SpriteFrame(-28, -14, 16, 24, 18, 231)1207SpriteFrame(-28, -14, 16, 24, 35, 231)1208end if1209if Stage.PlayerListPos == PLAYER_TAILS_A // PLAYER_TAILS in origins1210// 0 - Normal Tails1211SpriteFrame(-28, -14, 16, 24, 122, 202)1212// 1-2 - Tapping Tails1213SpriteFrame(-28, -14, 16, 24, 139, 202)1214SpriteFrame(-28, -14, 16, 24, 156, 202)1215end if12161217#platform: Use_Origins1218if Stage.PlayerListPos == PLAYER_KNUCKLES1219// 0 - Normal Knuckles1220SpriteFrame(-28, -14, 16, 24, 1, 256)1221// 1-2 - Tapping Knuckles1222SpriteFrame(-28, -14, 16, 24, 18, 256)1223SpriteFrame(-28, -14, 16, 24, 35, 256)1224end if1225if Stage.PlayerListPos == PLAYER_AMY1226// 0 - Normal Amy1227SpriteFrame(-28, -14, 16, 24, 52, 256)1228// 1-2 - Tapping Amy1229SpriteFrame(-28, -14, 16, 24, 70, 256)1230SpriteFrame(-28, -14, 16, 24, 88, 256)1231end if1232#endplatform1233// 3 - Wave1234SpriteFrame(0, 0, 128, 32, 0, 128)12351236// 4 - Pause Header1237SpriteFrame(0, -19, 128, 32, 0, 160)12381239// 5 - Underline1240SpriteFrame(-6, 7, 128, 3, 0, 193)12411242// All the remaining text Frames are different between languages1243switch Engine.Language1244case LANG_ENGLISH1245case LANG_JAPANESE12461247// 6 - Continue1248SpriteFrame(0, -5, 65, 11, 0, 197)12491250// 7 - Restart1251SpriteFrame(0, -5, 55, 11, 66, 197)12521253// 8 - Exit1254SpriteFrame(0, -5, 30, 11, 0, 209)12551256// 9 - Dev Menu1257SpriteFrame(0, -5, 64, 11, 31, 209)12581259// 10 - Greyed out Restart1260SpriteFrame(0, -5, 55, 11, 52, 244)1261break12621263case LANG_FRENCH12641265// 6 - Continuer1266SpriteFrame(0, -5, 73, 11, 0, 197)12671268// 7 - Recommencer1269SpriteFrame(0, -5, 95, 11, 0, 209)12701271// 8 - Quitter1272SpriteFrame(0, -5, 53, 11, 148, 244)12731274// 9 - Dev1275SpriteFrame(0, -5, 23, 11, 96, 209)12761277// 10 - Recommencer (grey)1278SpriteFrame(0, -5, 95, 11, 52, 244)1279break12801281case LANG_ITALIAN12821283// 6 - Continua1284SpriteFrame(0, -5, 65, 11, 0, 197)12851286// 7 - Ricomincia1287SpriteFrame(0, -5, 78, 11, 0, 209)12881289// 8 - Esci1290SpriteFrame(0, -5, 28, 11, 66, 197)12911292// 9 - Dev1293SpriteFrame(0, -5, 23, 11, 79, 209)12941295// 10 - Grey Ricomincia1296SpriteFrame(0, -5, 78, 11, 52, 244)1297break12981299case LANG_DEUTSCH13001301// 6 - Weiter1302SpriteFrame(0, -5, 48, 11, 0, 197)13031304// 7 - Neustart1305SpriteFrame(0, -5, 65, 11, 0, 209)13061307// 8 - Verlassen1308SpriteFrame(0, -5, 71, 11, 49, 197)13091310// 9 - Dev1311SpriteFrame(0, -5, 23, 11, 66, 209)13121313// 10 - Neustart (grey)1314SpriteFrame(0, -5, 65, 11, 52, 244)1315break13161317case LANG_SPANISH13181319// 6 - Continuar1320SpriteFrame(0, -5, 73, 11, 0, 197)13211322// 7 - Reiniciar1323SpriteFrame(0, -5, 67, 11, 0, 209)13241325// 8 - Salir1326SpriteFrame(0, -5, 36, 11, 74, 197)13271328// 9 - Dev1329SpriteFrame(0, -5, 23, 11, 68, 209)13301331// 10 - Grey Reiniciar1332SpriteFrame(0, -5, 67, 11, 52, 244)1333break13341335end switch13361337end sub133813391340// ========================1341// Editor Subs1342// ========================13431344sub RSDKDraw1345DrawSprite(0)1346end sub134713481349sub RSDKLoad1350LoadSpriteSheet("Special/ScoreScreen.gif")1351SpriteFrame(-64, -16, 128, 32, 0, 160)13521353SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")1354end sub135513561357