Path: blob/master/Sonic 2/Scripts/Global/BrokenMonitor.txt
1480 views
// ----------------------------------1// RSDK Project: Sonic 22// Script Description: Broken Monitor Object3// Script Author: Christian Whitehead/Simon Thomley4// Unpacked by Rubberduckycooly's script unpacker5// ----------------------------------67// ========================8// Aliases9// ========================1011private alias object.value0 : object.contentsPos.y12private alias object.value1 : object.timer13private alias object.value3 : object.rewardPlayer14private alias object.value4 : object.drawIndex1516// Monitor type aliases17private alias 0 : MONITOR_BLANK18private alias 1 : MONITOR_RINGS19private alias 2 : MONITOR_SHIELD_BLUE20private alias 3 : MONITOR_INVINCIBILITY21private alias 4 : MONITOR_SPEEDSHOES22private alias 5 : MONITOR_1UP_SONIC // In Origins with game.coinMode set to true, these give coins instead23private alias 6 : MONITOR_1UP_TAILS24private alias 7 : MONITOR_1UP_KNUX25private alias 8 : MONITOR_SUPER26private alias 9 : MONITOR_SHIELD_BUBBLE27private alias 10 : MONITOR_SHIELD_FIRE28private alias 11 : MONITOR_SHIELD_LIGHTNING29private alias 12 : MONITOR_EGGMAN30private alias 13 : MONITOR_TELEPORT31private alias 14 : MONITOR_RANDOM32private alias 14 : MONITOR_DEBUG_SPIKES // This is strange... spikes shouldn't be here... yet is is.33private alias 15 : MONITOR_DEBUG_SHIELD34private alias 16 : MONITOR_DEBUG_EMERALDS35private alias 17 : MONITOR_1UP_AMY // Origins exclusive3637// Monitor states38private alias 0 : MONITOR_STATE_RISE39private alias 1 : MONITOR_STATE_FADE40private alias 2 : MONITOR_STATE_IDLE4142// VSGame States43private alias 1 : VSGAME_TELEPORT4445// Player aliases46private alias object.type : player.type47private alias object.xpos : player.xpos48private alias object.ypos : player.ypos49private alias object.speed : player.speed50private alias object.value0 : player.rings51private alias object.value3 : player.drownTimer52private alias object.value4 : player.drownLevel53private alias object.value6 : player.speedShoesTimer54private alias object.value7 : player.invincibleTimer55private alias object.value16 : player.isSidekick56private alias object.value37 : player.shield5758// Shields59private alias 0 : SHIELD_NONE60private alias 1 : SHIELD_NORMAL61private alias 2 : SHIELD_BUBBLE62private alias 3 : SHIELD_FIRE63private alias 4 : SHIELD_LIGHTNING6465// Super States66private alias 1 : SUPERSTATE_SUPER6768// Shield Type Aliases69private alias 3 : SHIELDTYPE_RAND_S37071// Game Modes72private alias 2 : MODE_TIMEATTACK7374// Music Events75private alias 25 : SLOT_MUSICEVENT_CHANGE7677private alias 2 : MUSICEVENT_TRANSITION7879// Tracks80private alias 2 : TRACK_INVINCIBLE8182// Global Variable ID Aliases83private alias 25 : GLOBAL_PLAYERLIVES848586// ========================87// Function Declarations88// ========================8990reserve function BrokenMonitor_Blank919293// ========================94// Static Values95// ========================9697public value BrokenMonitor_ResetDrownMusic = 09899100// ========================101// Function Definitions102// ========================103104private function BrokenMonitor_Blank105// Do nothing!106end function107108109// ========================110// Events111// ========================112113event ObjectUpdate114switch object.state115case MONITOR_STATE_RISE116if object.timer < 0117object.contentsPos.y += object.timer118object.timer += 0x1800119else120object.timer = 0121end if122123if object.timer == 0124object.state = MONITOR_STATE_FADE125object.inkEffect = INK_ALPHA126currentPlayer = object.rewardPlayer127switch object.propertyValue128case MONITOR_BLANK129break130131case MONITOR_RINGS132player[currentPlayer].rings += 10133if ringPan == 0134PlaySfx(SfxName[Ring L], false)135SetSfxAttributes(SfxName[Ring L], -1, -100)136ringPan = 1137else138PlaySfx(SfxName[Ring R], false)139SetSfxAttributes(SfxName[Ring R], -1, 100)140ringPan = 0141end if142143if player[currentPlayer].rings > 999144player[currentPlayer].rings = 999145end if146147if player[0].rings >= ringExtraLife148if options.gameMode != MODE_TIMEATTACK149// this one doesn't have 2P global array code, it's just like this150#platform: USE_ORIGINS151if game.coinMode == false152player.lives++153else154CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)155end if156#endplatform157#platform: USE_STANDALONE158player.lives++159#endplatform160PlaySfx(SfxName[Life], false)161PauseMusic()162ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)163object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE164end if165166ringExtraLife += 100167if ringExtraLife > 300168ringExtraLife = 1000169end if170end if171break172173case MONITOR_SHIELD_BLUE174PlaySfx(SfxName[Blue Shield], false)175arrayPos0 = playerCount176arrayPos0 += currentPlayer177player[currentPlayer].shield = SHIELD_NORMAL178179if Player_superState != SUPERSTATE_SUPER180if object[arrayPos0].type != invincibilityType181CallFunction(Player_ApplyShield)182end if183end if184break185186case MONITOR_INVINCIBILITY187if Player_superState != SUPERSTATE_SUPER188arrayPos0 = playerCount189arrayPos0 += currentPlayer190ResetObjectEntity(arrayPos0, invincibilityType, 0, player[currentPlayer].xpos, player[currentPlayer].ypos)191object[arrayPos0].priority = PRIORITY_ACTIVE192player[currentPlayer].invincibleTimer = 1260193PlayMusic(TRACK_INVINCIBLE)194end if195break196197case MONITOR_SPEEDSHOES198if SpeedUpMusic != 0199if player[currentPlayer].speedShoesTimer == 0200CallFunction(SpeedUpMusic)201end if202end if203204player[currentPlayer].speedShoesTimer = 1320205CallFunction(Player_UpdatePhysicsState)206break207208case MONITOR_1UP_SONIC209case MONITOR_1UP_TAILS210case MONITOR_1UP_KNUX211#platform: USE_ORIGINS212case MONITOR_1UP_AMY213if game.coinMode == false214#endplatform215// global variable "array" (yes, this is actually how its done)216arrayPos0 = GLOBAL_PLAYERLIVES217#platform: USE_DECOMP218arrayPos0 = VarName[player.lives]219#endplatform220if player[currentPlayer].isSidekick == false221arrayPos0 += currentPlayer222end if223224global[arrayPos0]++225#platform: USE_ORIGINS226else227CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)228end if229#endplatform230231PlaySfx(SfxName[Life], false)232PauseMusic()233ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)234object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE235break236237case MONITOR_SUPER238currentPlayer = 0239player[0].rings += 50240if Player_superState != SUPERSTATE_SUPER241object.type = player[0].type242CallFunction(Player_TryTransform)243object.type = TypeName[Broken Monitor]244else245if ringPan == 0246PlaySfx(SfxName[Ring L], false)247SetSfxAttributes(SfxName[Ring L], -1, -100)248ringPan = 1249else250PlaySfx(SfxName[Ring R], false)251SetSfxAttributes(SfxName[Ring R], -1, 100)252ringPan = 0253end if254end if255256if player[0].rings > 999257player[0].rings = 999258end if259260if player[0].rings >= ringExtraLife261if options.gameMode != MODE_TIMEATTACK262// this one doesn't have 2P code, it's just like this since the code only gives rings to P1 anyway263#platform: USE_ORIGINS264if game.coinMode == false265player.lives++266else267CallNativeFunction2(NotifyCallback, NOTIFY_ADD_COIN, 1)268end if269#endplatform270#platform: USE_STANDALONE271player.lives++272#endplatform273274PlaySfx(SfxName[Life], false)275PauseMusic()276ResetObjectEntity(SLOT_MUSICEVENT_CHANGE, TypeName[Music Event], MUSICEVENT_TRANSITION, 0, 0)277object[SLOT_MUSICEVENT_CHANGE].priority = PRIORITY_ACTIVE278end if279280ringExtraLife += 100281if ringExtraLife > 300282ringExtraLife = 1000283end if284end if285break286287case MONITOR_SHIELD_BUBBLE288PlaySfx(SfxName[Bubble Shield], false)289arrayPos0 = playerCount290arrayPos0 += currentPlayer291player[currentPlayer].shield = SHIELD_BUBBLE292293if Player_superState != SUPERSTATE_SUPER294if object[arrayPos0].type != invincibilityType295CallFunction(Player_ApplyShield)296end if297end if298299if player[currentPlayer].drownLevel >= 3300player[currentPlayer].drownTimer = 0301player[currentPlayer].drownLevel = 0302CallFunction(BrokenMonitor_ResetDrownMusic)303end if304break305306case MONITOR_SHIELD_FIRE307PlaySfx(SfxName[Fire Shield], false)308arrayPos0 = playerCount309arrayPos0 += currentPlayer310player[currentPlayer].shield = SHIELD_FIRE311312if Player_superState != SUPERSTATE_SUPER313if object[arrayPos0].type != invincibilityType314CallFunction(Player_ApplyShield)315end if316end if317break318319case MONITOR_SHIELD_LIGHTNING320PlaySfx(SfxName[Lightning Shield], false)321arrayPos0 = playerCount322arrayPos0 += currentPlayer323player[currentPlayer].shield = SHIELD_LIGHTNING324325if Player_superState != SUPERSTATE_SUPER326if object[arrayPos0].type != invincibilityType327CallFunction(Player_ApplyShield)328end if329end if330break331332case MONITOR_EGGMAN333CallFunction(Player_Hit)334break335336case MONITOR_TELEPORT337CreateTempObject(TypeName[VS Game], 0, object.xpos, object.ypos)338object[tempObjectPos].state = VSGAME_TELEPORT339PlaySfx(SfxName[Teleport], false)340break341342case MONITOR_DEBUG_SPIKES343// Leftover from S1, this code should never hit at all since MONITOR_DEBUG_SPIKES is the same ID as MONITOR_RANDOM and344// random monitors get replaced on startup345346PlaySfx(SfxName[Spike], false)347options.spikeBehavior ^= true348break349350case MONITOR_DEBUG_SHIELD351PlaySfx(SfxName[Blue Shield], false)352options.shieldType++353options.shieldType &= SHIELDTYPE_RAND_S3354arrayPos0 = playerCount355currentPlayer = 0356CallFunction(Player_ApplyShield)357break358359case MONITOR_DEBUG_EMERALDS360// Toggle emerald state - give the player all emeralds if they don't have them already but give them none if they have all361if specialStage.emeralds == 0x7F362specialStage.emeralds = 0363else364specialStage.emeralds = 0x7F365end if366PlaySfx(SfxName[Transform], false)367break368end switch369end if370break371372case MONITOR_STATE_FADE373object.timer++374if object.timer == 30375object.timer = 0376object.state = MONITOR_STATE_IDLE377object.propertyValue = MONITOR_BLANK378if object.priority != PRIORITY_XBOUNDS_DESTROY379object.priority = PRIORITY_BOUNDS380end if381else382if object.timer > 14383object.alpha -= 16384end if385end if386break387388case MONITOR_STATE_IDLE389break390end switch391#platform: USE_ORIGINS392object.drawIndex = 0 // Added in Origins, prevents flickering issues in 2PVS Splitscreen.393#endplatform394end event395396397event ObjectDraw398if object.drawIndex == 0399// Draw the monitor box on the normal layer400DrawSprite(0)401AddDrawListEntityRef(5, object.entityPos)402else403// Draw the effect icon on the higher draw layer404if object.propertyValue > 0405DrawSpriteFX(object.propertyValue, FX_INK, object.xpos, object.contentsPos.y)406end if407end if408409object.drawIndex ^= 1410end event411412413event ObjectStartup414LoadSpriteSheet("Global/Items.gif")415SpriteFrame(-16, 0, 32, 16, 18, 34) // 0 - Broken Monitor Frame416417SpriteFrame(-8, -9, 16, 14, 18, 66) // 1 - MONITOR_RINGS418SpriteFrame(-8, -9, 16, 14, 35, 66) // 2 - MONITOR_SHIELD_BLUE419SpriteFrame(-8, -9, 16, 14, 18, 81) // 3 - MONITOR_INVINCIBILITY420SpriteFrame(-8, -9, 16, 14, 35, 81) // 4 - MONITOR_SPEEDSHOES421422// Amy's monitor icon is at the end of the list423#platform: USE_ORIGINS424if game.coinMode == false425#endplatform426// Player lives icons427SpriteFrame(-8, -9, 16, 14, 18, 96) // 5 - MONITOR_1UP_SONIC428SpriteFrame(-8, -9, 16, 14, 35, 96) // 6 - MONITOR_1UP_TAILS429SpriteFrame(-8, -9, 16, 14, 18, 111) // 7 - MONITOR_1UP_KNUX430#platform: USE_ORIGINS431else432SpriteFrame(-8, -9, 16, 14, 35, 186) // 5 - MONITOR_1UP_SONIC (Coin)433SpriteFrame(-8, -9, 16, 14, 35, 186) // 6 - MONITOR_1UP_TAILS (Coin but again)434SpriteFrame(-8, -9, 16, 14, 35, 186) // 7 - MONITOR_1UP_KNUX (Coin but yet again)435end if436#endplatform437438SpriteFrame(-8, -9, 16, 14, 35, 111) // 8 - MONITOR_SUPER439SpriteFrame(-8, -9, 16, 14, 18, 141) // 9 - MONITOR_SHIELD_BUBBLE440SpriteFrame(-8, -9, 16, 14, 35, 126) // 10 - MONITOR_SHIELD_FIRE441SpriteFrame(-8, -9, 16, 14, 18, 126) // 11 - MONITOR_SHIELD_LIGHTNING442SpriteFrame(-8, -9, 16, 14, 35, 141) // 12 - MONITOR_EGGMAN443SpriteFrame(-8, -9, 16, 14, 18, 156) // 13 - MONITOR_TELEPORT444SpriteFrame(-8, -9, 16, 14, 35, 156) // 14 - MONITOR_RANDOM445SpriteFrame(-8, -9, 16, 14, 18, 171) // 15 - MONITOR_DEBUG_SHIELD446SpriteFrame(-8, -9, 16, 14, 35, 171) // 16 - MONITOR_DEBUG_EMERALDS447#platform: USE_ORIGINS448if game.coinMode == false449SpriteFrame(-8, -9, 16, 14, 18, 201) // 17 - MONITOR_1UP_AMY450else451SpriteFrame(-8, -9, 16, 14, 35, 186) // 17 - MONITOR_1UP_AMY (The long awaited return of Coin)452end if453#endplatform454455// (The Spring Icon is unused, and so is the Mania monitor added in Origins)456457// By default, assume there isn't any water in the stage and assign a dummy function for resetting drown music458// (In stages with water, that stage's [Water] object will set the function itself instead)459BrokenMonitor_ResetDrownMusic = BrokenMonitor_Blank460end event461462463// ========================464// Editor Events465// ========================466467event RSDKDraw468DrawSprite(0)469end event470471472event RSDKLoad473LoadSpriteSheet("Global/Items.gif")474SpriteFrame(-16, 0, 32, 16, 18, 34)475476SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")477end event478479480