Path: blob/main/Scripts/Global/StageSetup.txt
1319 views
//---------------Sonic CD Stage Setup Script------------------//1//--------Scripted by Christian Whitehead 'The Taxman'--------//2//-------Unpacked By Rubberduckycooly's Script Unpacker-------//34// Aliases5#alias Object[23].Priority : StageSetup.Priority6#alias Object[24].Priority : HUD.Priority7#alias Object[24].DrawOrder : HUD.DrawOrder8#alias Object[24].PropertyValue : HUD.CurrentTimePeriod910// Badnik Alias11#alias Object.PropertyValue : Badnik.Quality1213// Player Aliases14#alias Player.Value0 : Player.Rings15#alias Player.Value6 : Player.MinRollSpeed1617// Flower States18#alias 1 : FLOWER_SEED_FALL1920// Future post State21#alias 2 : FUTUREPOST_USED2223// Past Post State24#alias 2 : PASTPOST_USED2526// Monitor States27#alias 2 : BROKENMONITOR_BLANK2829// Priority30#alias 1 : PRIORITY_ACTIVE3132// Warp Destination33#alias 0 : WARP_NONE3435// Game Mode Aliases36#alias 2 : MODE_TIMEATTACK3738// Player39#alias 0 : PLAYER_SONIC_A4041// Control Mode42#alias -1 : CONTROLMODE_NONE4344// Soundtrack45#alias 0 : OST_JP4647// Global SFX48#alias 20 : SFX_G_1UP49#alias 21 : SFX_G_ACHIEVEMENT5051// Track List52#alias 0 : TRACK_STAGE53#alias 1 : TRACK_ACTFINISH54#alias 2 : TRACK_INVINCIBILITY55#alias 3 : TRACK_SPEEDSHOES56#alias 4 : TRACK_BOSS57#alias 5 : TRACK_GAMEOVER585960// Time Period Aliases61#alias 0 : TIME_PRESENT62#alias 1 : TIME_PAST63#alias 2 : TIME_GOOD_FUTURE64#alias 3 : TIME_BAD_FUTURE6566// Function declarations67#function StageSetup_CheckGoodFuture68#function StageSetup_SaveStageState69#function StageSetup_LoadStageState707172function StageSetup_CheckGoodFuture73if Good_Future == true74// Destroying the transporters in the past will get rid of any badnik with bad condition in the present75if Badnik.Quality > 076ResetObjectEntity(Object.EntityNo, Flower_TypeNo, 0, Object.XPos, Object.YPos)77Object.DrawOrder = 478Object.State = FLOWER_SEED_FALL79else80// And get rid entirely of them in the past and good future81if HUD.CurrentTimePeriod > 082ResetObjectEntity(Object.EntityNo, Flower_TypeNo, 0, Object.XPos, Object.YPos)83Object.DrawOrder = 484Object.State = FLOWER_SEED_FALL85end if86end if87end if88end function899091function StageSetup_SaveStageState92ArrayPos0 = 3293ArrayPos1 = 71689495TempValue1 = HUD.CurrentTimePeriod96TempValue1 += 497// Checks and saves:98// Anything that doesn't exist anymore99// Broken Monitors100// Used Warp Signs101// Anything that transformed into a flower102while ArrayPos0 < 1056103if Object[ArrayPos0].Type == TypeName[Blank Object]104SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, true)105else106if Object[ArrayPos0].Type == TypeName[Broken Monitor]107SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, true)108else109if Object[ArrayPos0].Type == TypeName[Future Post]110if Object[ArrayPos0].State == FUTUREPOST_USED111SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, true)112else113SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, false)114end if115else116if Object[ArrayPos0].Type == TypeName[Past Post]117if Object[ArrayPos0].State == PASTPOST_USED118SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, true)119else120SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, false)121end if122else123SetBit(SaveRAM[ArrayPos1], HUD.CurrentTimePeriod, false)124if Object[ArrayPos0].Type == Flower_TypeNo125SetBit(SaveRAM[ArrayPos1], TempValue1, true)126else127SetBit(SaveRAM[ArrayPos1], TempValue1, false)128end if129end if130end if131end if132end if133ArrayPos0++134ArrayPos1++135loop136end function137138139function StageSetup_LoadStageState140ArrayPos0 = 32141ArrayPos1 = 7168142143TempValue1 = HUD.CurrentTimePeriod144TempValue1 += 4145// Checks and loads:146// Anything that doesn't exist anymore147// Broken Monitors148// Used Warp Signs149// Anything that transformed into a flower150while ArrayPos0 < 1056151if Object[ArrayPos0].Type == TypeName[Ring]152GetBit(TempValue0, SaveRAM[ArrayPos1], HUD.CurrentTimePeriod)153if TempValue0 == true154Object[ArrayPos0].Type = TypeName[Blank Object]155end if156else157if Object[ArrayPos0].Type == TypeName[Monitor]158GetBit(TempValue0, SaveRAM[ArrayPos1], HUD.CurrentTimePeriod)159if TempValue0 == true160Object[ArrayPos0].Type = TypeName[Broken Monitor]161Object[ArrayPos0].State = BROKENMONITOR_BLANK162end if163else164if Object[ArrayPos0].Type == TypeName[Future Post]165GetBit(TempValue0, SaveRAM[ArrayPos1], HUD.CurrentTimePeriod)166if TempValue0 == true167Object[ArrayPos0].State = FUTUREPOST_USED168end if169else170if Object[ArrayPos0].Type == TypeName[Past Post]171GetBit(TempValue0, SaveRAM[ArrayPos1], HUD.CurrentTimePeriod)172if TempValue0 == true173Object[ArrayPos0].State = PASTPOST_USED174end if175else176GetBit(TempValue0, SaveRAM[ArrayPos1], TempValue1)177if TempValue0 == true178Object[ArrayPos0].Type = TypeName[Blank Object]179end if180end if181end if182end if183end if184ArrayPos0++185ArrayPos1++186loop187end function188189190sub ObjectMain191Ring.AniCount++192if Ring.AniCount == 4193Ring.AniCount = 0194Ring.Frame++195Ring.Frame &= 7196end if197198if Options.GameMode != MODE_TIMEATTACK199if Player.Score >= Player.ScoreBonus200201#platform: Use_Origins202if game.coinMode == false203Player.Lives++204else205game.callbackParam0 = 1 // Set the amount of coins to add206EngineCallback(NOTIFY_ADD_COIN)207end if208#endplatform209210#platform: Use_Standalone211Player.Lives++212#endplatform213214Player.ScoreBonus += 50000215if Stage.PlayerListPos == PLAYER_SONIC_A // PLAYER_SONIC in origins216PlaySfx(SFX_G_1UP, false)217else218PlaySfx(SFX_G_ACHIEVEMENT, false)219end if220end if221end if222223Oscillation++224Oscillation &= 511225226#platform: Use_Origins227if Stage.TimeEnabled == true228if game.coinMode == false229CheckEqual(game.timeOver, false)230TempValue0 = CheckResult231CheckEqual(Stage.Minutes, 10)232TempValue0 &= CheckResult233if TempValue0 != false234if game.playMode == BOOT_PLAYMODE_CLASSIC235Stage.Minutes = 9236Stage.Seconds = 59237Stage.MilliSeconds = 99238Stage.TimeEnabled = false239end if240241if game.playMode != BOOT_PLAYMODE_BOSSRUSH242Object[0].Type = TypeName[Player Object]243CallFunction(Player_Kill)244end if245end if246end if247end if248249if game.forceKillPlayer == true250game.forceKillPlayer = false251CheckEqual(Player.State, Player_State_Death)252TempValue0 = CheckResult253CheckEqual(Player.State, Player_State_Drown)254CheckResult |= TempValue0255if CheckResult == false256Object[0].Type = TypeName[Player Object]257CallFunction(Player_Kill)258end if259end if260#endplatform261262#platform: Use_Standalone263if Stage.TimeEnabled == true264if Stage.Minutes == 10265Stage.Minutes = 9266Stage.Seconds = 59267Stage.MilliSeconds = 99268Stage.TimeEnabled = false269Object[0].Type = TypeName[Player Object]270CallFunction(Player_Kill)271end if272end if273#endplatform274end sub275276277sub ObjectPlayerInteraction278TempValue0 = Player.CollisionLeft279TempValue0 <<= 16280TempValue0 += Player.XPos281282TempValue1 = Stage.XBoundary1283TempValue1 <<= 16284if TempValue0 < TempValue1285if Player.Right == true286Player.XVelocity = 0x10000287Player.Speed = 0x10000288else289Player.XVelocity = 0290Player.Speed = 0291end if292Player.XPos = TempValue1293TempValue0 = Player.CollisionLeft294TempValue0 <<= 16295Player.XPos -= TempValue0296end if297// Death Boundary298TempValue0 = Player.CollisionBottom299TempValue0 <<= 16300TempValue0 += Player.YPos301if TempValue0 > Stage.DeathBoundary302CallFunction(Player_Kill)303end if304end sub305306307sub ObjectStartup308if Options.Soundtrack == OST_JP309SetMusicTrack("JP/ZoneComplete.ogg", TRACK_ACTFINISH, 0)310SetMusicTrack("JP/Invincibility.ogg", TRACK_INVINCIBILITY, 0)311SetMusicTrack("JP/SpeedShoes.ogg", TRACK_SPEEDSHOES, 0)312SetMusicTrack("JP/Boss.ogg", TRACK_BOSS, 1)313SetMusicTrack("JP/GameOver.ogg", TRACK_GAMEOVER, 0)314else315SetMusicTrack("US/ZoneComplete.ogg", TRACK_ACTFINISH, 0)316SetMusicTrack("US/Invincibility.ogg", TRACK_INVINCIBILITY, 0)317SetMusicTrack("US/SpeedShoes.ogg", TRACK_SPEEDSHOES, 0)318SetMusicTrack("US/Boss.ogg", TRACK_BOSS, 196526)319SetMusicTrack("US/GameOver.ogg", TRACK_GAMEOVER, 0)320end if321322Stage.PauseEnabled = false323Screen.CameraStyle = Options.OriginalControls324Screen.CameraTarget = 0325326Stage.DeathBoundary = Stage.YBoundary2327Stage.DeathBoundary <<= 16328Object[23].Type = TypeName[Stage Setup]329StageSetup.Priority = PRIORITY_ACTIVE330331ArrayPos0 = 32332while ArrayPos0 < 1056333if Object[ArrayPos0].Type == TypeName[Stage Setup]334ResetObjectEntity(ArrayPos0, TypeName[Blank Object], 0, 0, 0)335end if336ArrayPos0++337loop338339ArrayPos0 = 32340while ArrayPos0 < 1056341if Object[ArrayPos0].Type == TypeName[HUD] // Delete extra HUD objects and set the correct one342Object[ArrayPos0].Type = TypeName[Blank Object]343Object[24].Type = TypeName[HUD]344HUD.Priority = PRIORITY_ACTIVE345HUD.DrawOrder = 6346HUD.CurrentTimePeriod = Object[ArrayPos0].PropertyValue347end if348ArrayPos0++349loop350351// In origins this is reset by player object so, goodbye!352#platform: Use_Standalone353Warp.Timer = 0354#endplatform355if Warp.XPos > 0 // if the player comes from a time travel, load the warp values356// Reload the previous player stats357Player.XPos = Warp.XPos358Player.YPos = Warp.YPos359Player.XVelocity = Warp.XVelocity360Player.YVelocity = Warp.YVelocity361Player.Speed = Warp.Speed362Player.CollisionMode = Warp.CollisionMode363Player.Gravity = Warp.Gravity364Player.State = Warp.State365Player.Animation = Warp.Animation366Player.Frame = Warp.PlayerFrame367Player.Angle = Warp.Angle368Player.Rings = Warp.Rings369Player.MinRollSpeed = Warp.MinRollSpeed370371// Reload the previous stage time372Stage.MilliSeconds = Rec_Milliseconds373Stage.Seconds = Rec_Seconds374Stage.Minutes = Rec_Minutes375376CallFunction(StageSetup_LoadStageState)377else378ArrayPos0 = 7168379while ArrayPos0 < 8192380SaveRAM[ArrayPos0] = 0381ArrayPos0++382loop383Player.Direction = FACING_RIGHT384Player.Left = false385Player.Right = true386Player.ControlMode = CONTROLMODE_NONE387Player.Speed = 0388Player.Animation = ANI_STOPPED389end if390391if HUD.CurrentTimePeriod == TIME_GOOD_FUTURE392Good_Future = true393Transporter_Destroyed = true394end if395396if SpecialStage.TimeStones == 127 // 0b1111111, each '1' bit represents an obtained time stone397Good_Future = true398Transporter_Destroyed = true399end if400401Warp.Destination = WARP_NONE402Ring.ExtraLife = 100403Player.RoofBarrier = false404end sub405406407// ========================408// Editor Subs409// ========================410411sub RSDKDraw412DrawSprite(0)413end sub414415416sub RSDKLoad417LoadSpriteSheet("Global/Display.gif")418SpriteFrame(-16, -16, 32, 32, 1, 143) // #0 - "Script" Icon419420SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")421end sub422423424// ========================425// Editor Helpers426// ========================427428// All the following are only to be used from Editor subs, using these in the actual game itself won't do much429// None of these exist in the original game, they're all custom to the decomp430431#function EditorHelpers_DrawHitbox432#function EditorHelpers_DrawX433#function EditorHelpers_FindTimePeriod434435436function EditorHelpers_DrawHitbox437438#platform: Editor439440// This function is called in order to draw an object's hitbox, as a white441// Editor.DrawingOverlay isn't set here442443// Preconditions:444// - Object.XPos and Object.YPos are the position for the hitbox to be centered around445// - TempValue0 is the left hitbox size446// - TempValue1 is the top hitbox size447// - TempValue2 is the right hitbox size448// - TempValue3 is the bottom hitbox size449// - All these values are to be positive450451// Get the base 1:1 position of the object452TempValue4 = Object.iXPos453TempValue5 = Object.iYPos454455// Move to its top left corner456TempValue4 -= TempValue0457TempValue5 -= TempValue1458459// Get the hitbox's total width and height460TempValue2 += TempValue0461TempValue3 += TempValue1462463// Turning iPos into normal Pos464TempValue4 <<= 16465TempValue5 <<= 16466467DrawRectOutline(TempValue4, TempValue5, TempValue2, TempValue3, 255, 255, 0, 255)468469#endplatform470471end function472473474function EditorHelpers_DrawX475476#platform: Editor477478// This function is called to draw a red X, just for when you wanna show something's *really* wrong479// Editor.DrawingOverlay isn't set here, it's expected to be set (or ignored) by the Object calling this function480481// Preconditions:482// - TempValue0 and TempValue1 are the position for the X to be centered around, in world-space483484// Left485TempValue2 = TempValue0486TempValue2 -= 0x100000487488// Right489TempValue3 = TempValue0490TempValue3 += 0x100000491492// Top493TempValue4 = TempValue1494TempValue4 -= 0x100000495496// Bottom497TempValue5 = TempValue1498TempValue5 += 0x100000499500// TL-BR501DrawLine(TempValue2, TempValue4, TempValue3, TempValue5, 255, 0, 0)502503// TR-BL504DrawLine(TempValue3, TempValue4, TempValue2, TempValue5, 255, 0, 0)505506#endplatform507508end function509510511function EditorHelpers_FindTimePeriod512513#platform: Editor514515// This function is called in order to get the current Time Period516// Do note that this is inaccurate to how the game actually handles it, but since517// we can't look at the HUD's property value instead we have to estimate based on the current stage's folder518519// Postconditions:520// - CheckResult holds the current time period521// - If the current folder's name doesn't end in ABCD then Present time period will be assumed522523TempValue0 = TIME_PRESENT524525CheckCurrentStageFolder("B")526SetBit(TempValue0, 0, CheckResult)527528CheckCurrentStageFolder("C")529SetBit(TempValue0, 1, CheckResult)530531CheckCurrentStageFolder("D")532CheckResult *= TIME_BAD_FUTURE533TempValue0 += CheckResult534535CheckResult = TempValue0536537#endplatform538539end function540541542