Path: blob/main/Scripts/R7/Eggman.txt
1319 views
//-------------------Sonic CD Eggman Script-------------------//1//--------Scripted by Christian Whitehead 'The Taxman'--------//2//-------Unpacked By Rubberduckycooly's Script Unpacker-------//34// Note: We're using R7Eggman as a prefix here because there's like 5 "Eggman" objects in the game, it's less confusing this way56// Aliases7#alias Object.Value0 : Object.Timer8#alias Object.Value1 : Object.XVelocity9#alias Object.Value2 : Object.LaserActive10#alias Object.Value3 : Object.DebrisTimer11#alias Object.Value4 : Object.LastExplosion12#alias Object.Value5 : Object.LaserOffset13#alias Object.Value6 : Object.Acceleration1415// HUD Alias16#alias Object[24].PropertyValue : HUD.CurrentTimePeriod1718// Initial few States19#alias 0 : R7EGGMAN_AWAITPLAYER20#alias 1 : R7EGGMAN_WAIT2122// Flying across the Screen, Right -> Left, then Left -> Right23#alias 2 : R7EGGMAN_FLYIN_RL24#alias 3 : R7EGGMAN_FLYIN_LR2526// Some States for taking care of Metal27#alias 4 : R7EGGMAN_GOTOMETAL28#alias 5 : R7EGGMAN_STARTUPMETAL2930// A bunch of small States for when he's flashing the laser on and off31#alias 6 : R7EGGMAN_INTROLASERON132#alias 7 : R7EGGMAN_INTROLASEROFF133#alias 8 : R7EGGMAN_INTROLASERON234#alias 9 : R7EGGMAN_INTROLASEROFF235#alias 10 : R7EGGMAN_INTROLASERON336#alias 11 : R7EGGMAN_INTROLASEROFF33738// Chasing the pair of Blues during the race39#alias 12 : R7EGGMAN_CHASESTART40#alias 13 : R7EGGMAN_CHASEMAIN4142// After the race, a series of states for him repeatedly lasering Metal Sonic's scrapped remains (?)43#alias 14 : R7EGGMAN_ENDLASERON144#alias 15 : R7EGGMAN_ENDLASEROFF145#alias 16 : R7EGGMAN_ENDLASERON246#alias 17 : R7EGGMAN_ENDLASEROFF247#alias 18 : R7EGGMAN_ENDLASERON348#alias 19 : R7EGGMAN_ENDLASEROFF34950// After that fit, now he descends and flies off to the right51#alias 20 : R7EGGMAN_DESCEND52#alias 21 : R7EGGMAN_PAUSE53#alias 22 : R7EGGMAN_FLYAWAY5455// Thruster Animations56#alias 0 : R7EGGMANANI_THRUSTEROFF57#alias 1 : R7EGGMANANI_THRUSTERON5859// Metal Sonic (Object[+1]) Aliases60#alias 1 : METALSONIC_TURNRIGHT6162#alias 2 : ANI_TURNING6364// Vertical Door (Object [-2] and [-1]) Aliases65#alias Object.Value0 : Object.DrawPosY6667#alias 1 : VERTICALDOOR_START_OPENING68#alias 3 : VERTICALDOOR_END_OPENED6970// Object[-2] is the door at the start of the race, [-1] is the final door7172// Debris Aliases73// (XVel is coincidentally the same value as the main Eggman object so it doesn't need to be redeclared here)74#alias Object.Value2 : Object.YVelocity7576// Fade Music Aliases77#alias 0 : FADEMUSIC_FADE_TO_BOSS78#alias 1 : FADEMUSIC_FADE_TO_LEVEL79#alias 2 : FADEMUSIC_SSZEGGMAN8081// Soundtrack82#alias 0 : OST_JP8384// Collision Sides85#alias 0 : CSIDE_FLOOR8687// Priority88#alias 0 : PRIORITY_BOUNDS89#alias 1 : PRIORITY_ACTIVE9091// Time Periods92#alias 2 : TIME_GOOD_FUTURE939495// Function declarations96#function R7Eggman_FollowGround979899function R7Eggman_FollowGround100// The track has all sorts of curves and ramps and stairs and such, this function is called to make Robotnik trace them101102// First move Robotnik 32 pixels up and attempt to find ground103Object.YPos -= 0x200000104ObjectTileGrip(CSIDE_FLOOR, 6, 176, 0)105if CheckResult == false106107// No ground was found, so move Robotnik 16 pixels down and try again108Object.YPos += 0x100000109ObjectTileGrip(CSIDE_FLOOR, 6, 176, 0)110if CheckResult == false111112// Still no collision, try once more113Object.YPos += 0x100000114ObjectTileGrip(CSIDE_FLOOR, 6, 176, 0)115if CheckResult == false116117// Give up - move Robotnik but don't try to follow the ground anymore118// At this point, Robotnik will be at the same point he started at before calling this function119Object.YPos += 0x100000120end if121end if122end if123124end function125126127sub ObjectMain128switch Object.State129case R7EGGMAN_AWAITPLAYER130// Setup some things for the Boss Fight131132// Set screen bounds133Stage.XBoundary2 = Object.iXPos134Stage.XBoundary2 -= 64135136TempValue0 = Stage.XBoundary2137TempValue0 -= Screen.XSize138Stage.NewXBoundary1 = TempValue0139140// Player Object collision checking in ObjectMain, that's certainly risky!141// (This only checks against the last player on the list! Not a big issue with CD's single Player setup, but still worthy of concern...)142PlayerObjectCollision(C_TOUCH, -256, -256, 0, 256)143144if CheckResult == true145// If the player's within range, start the startup sequence146147CreateTempObject(TypeName[Fade Music], FADEMUSIC_FADE_TO_BOSS, Object.XPos, Object.YPos)148149Object.Direction = FACING_LEFT150151// From this point on, make Robotnik always active, as the Player very well may outrun him during the race152Object.Priority = PRIORITY_ACTIVE153154Object.State++155end if156break157158case R7EGGMAN_WAIT159// Before making his grand enterance, hide off screen for a couple of seconds...160if Object.Timer < 120161Object.Timer++162else163// He's prepared, turn the thruster on and start moving!164Object.Timer = 0165Object.Animation = R7EGGMANANI_THRUSTERON166Object.State++167end if168break169170// The following set of two states is for Robotnik flying across the screen, he's got a movement speed of 6 pixels per second and that's about all that's interesting about them171172case R7EGGMAN_FLYIN_RL173if Object.Timer < 140174Object.XPos -= 0x60000175Object.Timer++176else177Object.Timer = 0178Object.Direction = FACING_RIGHT179Object.State++180end if181break182183case R7EGGMAN_FLYIN_LR184if Object.Timer < 160185Object.XPos += 0x60000186Object.Timer++187else188Object.Timer = 0189Object.Direction = FACING_LEFT190Object.State++191end if192break193194case R7EGGMAN_GOTOMETAL195if Object.Timer < 47196Object.XPos -= 0x60000197Object.Timer++198else199// Arrived at Metal, stop for a moment while powering him on200Object.Timer = 0201Object.Animation = R7EGGMANANI_THRUSTEROFF202Object.State++203end if204break205206case R7EGGMAN_STARTUPMETAL207if Object.Timer < 94208Object.Timer++209if Object.Timer == 30210// Object[+1] is Metal Sonic211Object[+1].State = METALSONIC_TURNRIGHT212Object[+1].Animation = ANI_TURNING213Object[+1].Timer = 0214end if215216if Object.Timer == 90217// Metal's now ready, but is Sonic?218Object.LaserActive = true219end if220else221Object.Timer = 0222Object.Animation = R7EGGMANANI_THRUSTERON223224// This laser around, the explosions should be 6 pixels left of Robotnik225Object.LaserOffset = -0x60000226Object.State++227end if228break229230// Following are a bunch of small states to manage Robotnik turning his laser on and off a bunch, with a movement speed of 2 pixels per second231232case R7EGGMAN_INTROLASERON1233Object.XPos -= 0x20000234if Object.Timer < 6235Object.Timer++236else237Object.Timer = 0238Object.LaserActive = false239Object.State++240end if241break242243case R7EGGMAN_INTROLASEROFF1244Object.XPos -= 0x20000245if Object.Timer < 30246Object.Timer++247else248Object.Timer = 0249Object.LaserActive = true250Object.State++251end if252break253254case R7EGGMAN_INTROLASERON2255Object.XPos -= 0x20000256if Object.Timer < 10257Object.Timer++258else259Object.Timer = 0260Object.LaserActive = false261Object.State++262end if263break264265case R7EGGMAN_INTROLASEROFF2266Object.XPos -= 0x20000267if Object.Timer < 30268Object.Timer++269else270Object.Timer = 0271Object.LaserActive = true272Object.State++273end if274break275276case R7EGGMAN_INTROLASERON3277Object.XPos -= 0x20000278if Object.Timer < 10279Object.Timer++280else281Object.Timer = 0282Object.LaserActive = false283Object.State++284end if285286CallFunction(R7Eggman_FollowGround)287break288289case R7EGGMAN_INTROLASEROFF3290Object.XPos -= 0x20000291if Object.Timer < 120292Object.Timer++293else294if HUD.CurrentTimePeriod == TIME_GOOD_FUTURE295// In the Bad Future nothing needs to happen, but if in the Good Future then start playing the Bad Future music296if Options.Soundtrack == OST_JP297SetMusicTrack("JP/R7D.ogg", 0, true)298else299SetMusicTrack("US/R7D.ogg", 0, 92324)300end if301end if302303CreateTempObject(TypeName[Fade Music], FADEMUSIC_SSZEGGMAN, Object.XPos, Object.YPos)304305// Open the starting door306Object[-2].State = VERTICALDOOR_START_OPENING307308// And open the ending door as well309Object[-1].State = VERTICALDOOR_END_OPENED310Object[-1].DrawPosY = 0x400000311Object[-1].YPos -= 0x400000312313Object.Timer = 0314Object.Direction = FACING_RIGHT315Object.LaserActive = true316Object.LaserOffset = 0x60000317Object.XVelocity = 0x20000318Object.State++319end if320321CallFunction(R7Eggman_FollowGround)322break323324case R7EGGMAN_CHASESTART325// This state is essentially an easier version of CHASEMAIN, just toned down a bit since the race just started and the player (& screen bounds) need to adjust326327Object.XPos += Object.XVelocity328TempValue0 = Object.iXPos329TempValue0 -= 16330if Stage.XBoundary2 < 16352331TempValue1 = Player.XVelocity332TempValue1 >>= 16333Stage.XBoundary2 += 6334Stage.XBoundary2 += TempValue1335end if336337if Stage.XBoundary1 < TempValue0338Stage.XBoundary1 = TempValue0339end if340341if Object.Timer < 360342Object.Timer++343else344Object.Timer = 0345Stage.XBoundary2 = Object[-1].iXPos346Stage.XBoundary2 += 112347Object.State++348end if349350CallFunction(R7Eggman_FollowGround)351break352353case R7EGGMAN_CHASEMAIN354TempValue0 = Object.XVelocity355356// As the race progresses, Robotnik speeds up...357Object.Acceleration++358Object.Acceleration &= 0x3FFF359360TempValue1 = Object.Acceleration361TempValue1 >>= 4362Object.XVelocity += TempValue1363if Object.XVelocity > 0x50000364// Maximum speed of 5 pixels per frame365366Object.XVelocity = 0x50000367end if368369TempValue1 = Screen.XOffset370TempValue1 <<= 16371TempValue1 -= Object.XPos372if TempValue1 > 0373TempValue1 >>= 7374if TempValue1 > 0x40000375TempValue1 = 0x40000376end if377TempValue0 += TempValue1378end if379380if TempValue0 > 0x50000381TempValue0 = 0x50000382end if383384if TempValue0 > 0x30000385TempValue0 -= 0x30000386Object.XPos += 0x30000387CallFunction(R7Eggman_FollowGround)388Object.XPos += TempValue0389CallFunction(R7Eggman_FollowGround)390else391Object.XPos += TempValue0392CallFunction(R7Eggman_FollowGround)393end if394395// Move the left side of the screen along with Robotnik396TempValue0 = Object.iXPos397TempValue0 -= 16398if Stage.XBoundary1 < TempValue0399Stage.XBoundary1 = TempValue0400401// More hardcoded stage bounds...402if Stage.XBoundary1 > 15840403Stage.XBoundary1 = 15840404end if405end if406407// Is Robotnik further than 34 pixels before the last door?408// (Strange way to put it, I hope you don't mind...)409TempValue0 = Object[-1].XPos410TempValue0 -= 0x220000411if Object.XPos > TempValue0412Object.XPos = TempValue0413Object.Animation = R7EGGMANANI_THRUSTEROFF414Object.XVelocity = 0415Object.State++416end if417break418419// The following 6 states are for when Robotnik turns the laser on and off a bunch of times after the race420// Is his button broken or something? I never understood why he'd need to do it so many times like that...421422case R7EGGMAN_ENDLASERON1423if Player.Animation != ANI_DYING424if Object.Timer < 50425Object.Timer++426else427Object.Timer = 0428Object.LaserActive = false429Object.State++430end if431end if432break433434case R7EGGMAN_ENDLASEROFF1435if Object.Timer < 20436Object.Timer++437else438Object.Timer = 0439Object.LaserActive = true440Object.State++441end if442break443444case R7EGGMAN_ENDLASERON2445if Object.Timer < 20446Object.Timer++447else448Object.Timer = 0449Object.LaserActive = false450Object.State++451end if452break453454case R7EGGMAN_ENDLASEROFF2455if Object.Timer < 20456Object.Timer++457else458Object.Timer = 0459Object.LaserActive = true460Object.State++461end if462break463464case R7EGGMAN_ENDLASERON3465if Object.Timer < 20466Object.Timer++467else468Object.Timer = 0469Object.LaserActive = false470Object.State++471end if472break473474case R7EGGMAN_ENDLASEROFF3475if Object.Timer < 60476Object.Timer++477else478Object.Timer = 0479Object.State++480end if481break482483case R7EGGMAN_DESCEND484// Going down for a moment before retreating...485Object.YPos += 0x20000486487if Object.Timer < 42488Object.Timer++489else490Object.Timer = 0491Object.LaserActive = false492Object.State++493end if494break495496case R7EGGMAN_PAUSE497// Hold for a second...498if Object.Timer < 60499Object.Timer++500else501Player.Score += 1000502Object.Timer = 0503Object.Animation = R7EGGMANANI_THRUSTERON504Object.State++505end if506break507508case R7EGGMAN_FLYAWAY509Object.XPos += 0x60000510if Object.OutOfBounds == true511Object.Type = TypeName[Blank Object]512Object.Priority = PRIORITY_BOUNDS513514if HUD.CurrentTimePeriod == TIME_GOOD_FUTURE515// In the Bad Future nothing needs to change, but in the Good Future start playing the normal Good Future music again516if Options.Soundtrack == OST_JP517SetMusicTrack("JP/R7C.ogg", 0, 103060)518else519SetMusicTrack("US/R7C.ogg", 0, 136670)520end if521522CreateTempObject(TypeName[Fade Music], FADEMUSIC_FADE_TO_LEVEL, Object.XPos, Object.YPos)523end if524525Stage.NewXBoundary2 = 16352526end if527break528529end switch530531if Object.LaserActive == true532if Object.DebrisTimer == 0533CreateTempObject(TypeName[Explosion], 0, Object.XPos, Object.YPos)534535// Offset the new object accordingly as needed536// Horizontal offset is +/- 6 pixels depending on Robotnik's current direction, and the laser touches the ground 176 pixels down537Object[TempObjectPos].XPos += Object.LaserOffset538Object[TempObjectPos].YPos += 0xB00000539540ArrayPos0 = Object.LastExplosion541Object.LastExplosion = Object[TempObjectPos].EntityNo542Object.DebrisTimer = 8543if Object[ArrayPos0].DrawOrder == 3544Object[TempObjectPos].DrawOrder = 4545546// Create some Debris with a randomised sprite547548Rand(TempValue0, 4)549CreateTempObject(TypeName[Debris], TempValue0, Object.XPos, Object.YPos)550551Object[TempObjectPos].XPos += Object.LaserOffset552Object[TempObjectPos].YPos += 0xB00000553554Rand(Object[TempObjectPos].XVelocity, 6)555Object[TempObjectPos].XVelocity <<= 16556Object[TempObjectPos].XVelocity -= 0x28000557Object[TempObjectPos].XVelocity += Object.XVelocity558559Rand(Object[TempObjectPos].YVelocity, 3)560Object[TempObjectPos].YVelocity += 2561Object[TempObjectPos].YVelocity <<= 16562FlipSign(Object[TempObjectPos].YVelocity)563end if564else565// Move the last explosion along with the laser for a little bit566567ArrayPos0 = Object.LastExplosion568Object[ArrayPos0].XPos = Object.XPos569Object[ArrayPos0].XPos += Object.LaserOffset570571Object[ArrayPos0].YPos = Object.YPos572Object[ArrayPos0].YPos += 0xB00000573574Object.DebrisTimer--575end if576else577if Object.DebrisTimer > 0578// Move the last explosion along with the laser for a little bit579580ArrayPos0 = Object.LastExplosion581Object[ArrayPos0].XPos = Object.XPos582Object[ArrayPos0].XPos += Object.LaserOffset583584Object[ArrayPos0].YPos = Object.YPos585Object[ArrayPos0].YPos += 0xB00000586587Object.DebrisTimer--588end if589end if590591end sub592593594sub ObjectPlayerInteraction595if Object.LaserActive == true596if Object.State < R7EGGMAN_CHASESTART597// Use the intro version of the laser hitbox598599PlayerObjectCollision(C_TOUCH, -12, 48, 12, 176)600601if CheckResult == true602CallFunction(Player_Hit)603end if604else605if Player.XPos < Object.XPos606Player.XPos = Object.XPos607608// Player.RCollisionFlag is a global flag set by Solid Blocks upon having the Player collide to the block's left (the player's right)609if Player.RCollisionFlag == true610CallFunction(Player_Kill)611end if612end if613614// Reset the flag, regardless if it was previously true or not615Player.RCollisionFlag = false616617if Object.State < R7EGGMAN_ENDLASERON1618PlayerObjectCollision(C_TOUCH, -12, 48, 12, 176)619else620PlayerObjectCollision(C_TOUCH, -64, -256, 16, 176)621end if622623if CheckResult == true624CallFunction(Player_Kill)625end if626end if627end if628629// Limit Tails's flight when needed630631if Player.YPos < Object.YPos // Is the Player Object higher up than the Robotnik object?632if Player.XPos < 0xE000000 // And has the Player Object not yet passed X Position 3584?633if Player.State == Player_State_Fly634if Player.Timer < 470635Player.Timer = 470636end if637end if638end if639640if Player.XPos > 0x38900000 // Alternatively, has the Player Object passed X Position 14480?641if Player.State == Player_State_Fly642if Player.Timer < 470643Player.Timer = 470644end if645end if646end if647end if648649end sub650651652sub ObjectDraw653switch Object.Animation654case R7EGGMANANI_THRUSTEROFF655DrawSpriteFX(0, FX_FLIP, Object.XPos, Object.YPos)656657TempValue0 = Object.AnimationTimer658TempValue0 /= 6659if TempValue0 == 1660// Draw the flashing sprites661DrawSpriteFX(1, FX_FLIP, Object.XPos, Object.YPos)662DrawSpriteFX(2, FX_FLIP, Object.XPos, Object.YPos)663DrawSpriteFX(3, FX_FLIP, Object.XPos, Object.YPos)664end if665666if Object.LaserActive == true667// Draw the laser, as a series of smaller, chained together sprites668TempValue0 = Object.AnimationTimer669TempValue0 &= 3670TempValue0 >>= 1671TempValue0 += 12672673TempValue1 = Object.XPos674675// Start 48 pixels below Robotnik676TempValue2 = Object.YPos677TempValue2 += 0x300000678DrawSpriteXY(TempValue0, TempValue1, TempValue2)679680// For the rest of the pieces, space them away 32 pixels vertically and 2 pixels horizontally, with the horizontal offset depending on Robotnik's direction681if Object.Direction == FACING_RIGHT682TempValue2 += 0x200000683TempValue1 += 0x20000684DrawSpriteXY(TempValue0, TempValue1, TempValue2)685686TempValue2 += 0x200000687TempValue1 += 0x20000688DrawSpriteXY(TempValue0, TempValue1, TempValue2)689690TempValue2 += 0x200000691TempValue1 += 0x20000692DrawSpriteXY(TempValue0, TempValue1, TempValue2)693else694TempValue2 += 0x200000695TempValue1 -= 0x20000696DrawSpriteXY(TempValue0, TempValue1, TempValue2)697698TempValue2 += 0x200000699TempValue1 -= 0x20000700DrawSpriteXY(TempValue0, TempValue1, TempValue2)701702TempValue2 += 0x200000703TempValue1 -= 0x20000704DrawSpriteXY(TempValue0, TempValue1, TempValue2)705end if706end if707Object.AnimationTimer++708Object.AnimationTimer %= 12709break710711case R7EGGMANANI_THRUSTERON712TempValue0 = Object.AnimationTimer713TempValue0 &= 1714if TempValue0 == 1715Object.Frame++716Object.Frame &= 3717end if718TempValue0 = Object.Frame719TempValue0 += 4720DrawSpriteFX(TempValue0, FX_FLIP, Object.XPos, Object.YPos)721TempValue0 += 4722DrawSpriteFX(TempValue0, FX_FLIP, Object.XPos, Object.YPos)723TempValue0 = Object.AnimationTimer724TempValue0 /= 6725726DrawSpriteFX(0, FX_FLIP, Object.XPos, Object.YPos)727728if TempValue0 == 1729// Draw the flashing sprites730DrawSpriteFX(1, FX_FLIP, Object.XPos, Object.YPos)731DrawSpriteFX(2, FX_FLIP, Object.XPos, Object.YPos)732DrawSpriteFX(3, FX_FLIP, Object.XPos, Object.YPos)733end if734735if Object.LaserActive == true736// Draw the Laser737TempValue0 = Object.AnimationTimer738TempValue0 &= 3739TempValue0 >>= 1740TempValue0 += 12741742TempValue1 = Object.XPos743TempValue2 = Object.YPos744TempValue2 += 0x300000745746DrawSpriteXY(TempValue0, TempValue1, TempValue2)747if Object.Direction == FACING_RIGHT748TempValue2 += 0x200000749TempValue1 += 0x20000750DrawSpriteXY(TempValue0, TempValue1, TempValue2)751752TempValue2 += 0x200000753TempValue1 += 0x20000754DrawSpriteXY(TempValue0, TempValue1, TempValue2)755756TempValue2 += 0x200000757TempValue1 += 0x20000758DrawSpriteXY(TempValue0, TempValue1, TempValue2)759else760TempValue2 += 0x200000761TempValue1 -= 0x20000762DrawSpriteXY(TempValue0, TempValue1, TempValue2)763764TempValue2 += 0x200000765TempValue1 -= 0x20000766DrawSpriteXY(TempValue0, TempValue1, TempValue2)767768TempValue2 += 0x200000769TempValue1 -= 0x20000770DrawSpriteXY(TempValue0, TempValue1, TempValue2)771end if772end if773774Object.AnimationTimer++775Object.AnimationTimer %= 12776break777778end switch779780end sub781782783sub ObjectStartup784LoadSpriteSheet("R7/Objects2.gif")785786// Main Robotnik + Ship Frame787SpriteFrame(-40, -24, 72, 72, 91, 1)788789// Motor Animation Frame790SpriteFrame(-24, -9, 24, 16, 164, 1)791792// Lit Light Frame793SpriteFrame(22, 27, 8, 8, 75, 99)794795// Backside Animation Frame796SpriteFrame(-32, 8, 16, 24, 176, 142)797798// Thruster Flames799SpriteFrame(-68, -10, 40, 16, 66, 133)800SpriteFrame(-60, -10, 32, 16, 66, 116)801SpriteFrame(-68, -10, 40, 16, 124, 150)802SpriteFrame(-60, -10, 32, 16, 66, 150)803SpriteFrame(-63, 30, 32, 16, 66, 150)804SpriteFrame(-55, 30, 24, 16, 99, 150)805SpriteFrame(-63, 30, 32, 16, 66, 116)806SpriteFrame(-55, 30, 24, 16, 99, 116)807808// Laser809SpriteFrame(-8, 0, 16, 32, 91, 74)810SpriteFrame(-8, 0, 16, 32, 108, 74)811812end sub813814815// ========================816// Editor Subs817// ========================818819sub RSDKDraw820DrawSprite(0)821end sub822823824sub RSDKLoad825LoadSpriteSheet("R7/Objects2.gif")826SpriteFrame(-40, -24, 72, 72, 91, 1)827828SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")829end sub830831832