Path: blob/master/Sonic 2/Scripts/ARZ/Water.txt
1480 views
// ----------------------------------1// RSDK Project: Sonic 22// Script Description: Water Object3// Script Author: Christian Whitehead/Simon Thomley4// Unpacked by Rubberduckycooly's script unpacker5// ----------------------------------67// Any water objects in the scene should be followed by THREE blank objects, these manage player stuff89// ========================10// Aliases11// ========================1213private alias object.value1 : object.constBubbleTimer14private alias object.value2 : object.randBubbleTimer15private alias object.value3 : object.proccessActEffects16private alias object.value8 : object.nextTrackID // stores the track that should play after the drowning one stops1718// AirBubble Aliases19private alias object.value1 : airBubble.originPos.x20private alias object.value2 : airBubble.targetPlayer2122// CountdownBubble Aliases23private alias object.value1 : countdownBubble.drawPos.x24private alias object.value2 : countdownBubble.drawPos.y25private alias object.value3 : countdownBubble.drawScreenID // new to Origins.2627// Player Aliases28private alias object.type : player.type29private alias object.state : player.state30private alias object.xpos : player.xpos31private alias object.ypos : player.ypos32private alias object.xvel : player.xvel33private alias object.yvel : player.yvel34private alias object.speed : player.speed35private alias object.direction : player.direction36private alias object.gravity : player.gravity37private alias object.animation : player.animation38private alias object.interaction : player.interaction39private alias object.tileCollisions : player.tileCollisions4041private alias object.value1 : player.timer42private alias object.value3 : player.drownTimer43private alias object.value4 : player.drownLevel44private alias object.value7 : player.invincibleTimer45private alias object.value16 : player.isSidekick46private alias object.value18 : player.sortedDrawOrder47private alias object.value20 : player.topSpeed48private alias object.value21 : player.acceleration49private alias object.value22 : player.deceleration50private alias object.value23 : player.airAcceleration51private alias object.value24 : player.airDeceleration52private alias object.value25 : player.gravityStrength53private alias object.value27 : player.jumpStrength54private alias object.value28 : player.jumpCap55private alias object.value37 : player.shield5657private alias 1 : SUPERSTATE_SUPER5859private alias 30 : SLOT_VSGAME60private alias object.value7 : object.waterSlotID6162// Death Event Aliases63private alias object.value4 : object.timeOver6465// Shields66private alias 0 : SHIELD_NONE67private alias 2 : SHIELD_BUBBLE68private alias 3 : SHIELD_FIRE69private alias 4 : SHIELD_LIGHTNING7071// Tracks72private alias 0 : TRACK_STAGE73private alias 2 : TRACK_INVINCIBLE74private alias 6 : TRACK_DROWNING757677// ========================78// Function Declarations79// ========================8081reserve function Water_ProcessARZAct182reserve function Water_ProcessARZAct283reserve function Water_SpawnSmallAirBubble84reserve function Water_SpawnCountDownBubble85reserve function Water_ResetDrownMusic868788// ========================89// Static Values90// ========================9192private value Water_waterSlotID = 093private value Water_activateFlag = 0949596// ========================97// Tables98// ========================99100private table Water_processActTable[3]101102103// ========================104// Function Definitions105// ========================106107private function Water_ProcessARZAct1108stage.newWaterLevel = 0x4100000109end function110111112private function Water_ProcessARZAct2113stage.newWaterLevel = 0x5100000114end function115116117private function Water_SpawnSmallAirBubble118if object[+currentPlayer].constBubbleTimer > 0119object[+currentPlayer].constBubbleTimer--120121if object[+currentPlayer].randBubbleTimer > 0122object[+currentPlayer].randBubbleTimer--123else124CreateTempObject(TypeName[Air Bubble], 2, player[currentPlayer].xpos, player[currentPlayer].ypos)125object[tempObjectPos].drawOrder = 4126object[tempObjectPos].yvel = -0x8800127airBubble[tempObjectPos].targetPlayer = currentPlayer128if player[currentPlayer].direction == FACING_RIGHT129object[tempObjectPos].xpos += 0x60000130else131object[tempObjectPos].xpos -= 0x60000132object[tempObjectPos].angle = 256133end if134airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos135object[+currentPlayer].randBubbleTimer = 512136end if137else138Rand(temp0, 3)139if temp0 == 1140Rand(object[+currentPlayer].randBubbleTimer, 16)141object[+currentPlayer].randBubbleTimer += 8142else143object[+currentPlayer].randBubbleTimer = 512144end if145146object[+currentPlayer].constBubbleTimer = 60147CreateTempObject(TypeName[Air Bubble], 2, player[currentPlayer].xpos, player[currentPlayer].ypos)148object[tempObjectPos].drawOrder = 4149object[tempObjectPos].yvel = -0x8800150airBubble[tempObjectPos].targetPlayer = currentPlayer151if player[currentPlayer].direction == FACING_RIGHT152object[tempObjectPos].xpos += 0x60000153else154object[tempObjectPos].xpos -= 0x60000155object[tempObjectPos].angle = 256156end if157158airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos159end if160end function161162163private function Water_SpawnCountDownBubble164CreateTempObject(TypeName[Countdown Bubble], temp0, player[currentPlayer].xpos, player[currentPlayer].ypos)165object[tempObjectPos].drawOrder = 5166object[tempObjectPos].yvel = -0x8800167#platform: USE_STANDALONE168countdownBubble[tempObjectPos].drawPos.y = currentPlayer // this is odd... this is drawPos.y, not "targetPlayer", likely a leftover from AirBubble spawning169#endplatform170#platform: USE_ORIGINS171countdownBubble[tempObjectPos].drawScreenID = currentPlayer172#endplatform173if player[currentPlayer].direction == FACING_RIGHT174object[tempObjectPos].xpos += 0x60000175else176object[tempObjectPos].xpos -= 0x60000177object[tempObjectPos].angle = 256178end if179180countdownBubble[tempObjectPos].drawPos.x = object[tempObjectPos].xpos181end function182183184private function Water_ResetDrownMusic185#platform: USE_STANDALONE186if currentPlayer == false187#endplatform188#platform: USE_ORIGINS189if player[currentPlayer].isSidekick == false190#endplatform191192arrayPos0 = Water_waterSlotID193arrayPos0 += currentPlayer194if player[currentPlayer].type != TypeName[Death Event]195if music.currentTrack == TRACK_DROWNING196if object[arrayPos0].nextTrackID == TRACK_INVINCIBLE197arrayPos1 = currentPlayer198arrayPos1 += playerCount199if object[arrayPos1].type != TypeName[Invincibility]200if Player_superState != SUPERSTATE_SUPER201object[arrayPos0].nextTrackID = TRACK_STAGE202end if203end if204end if205206PlayMusic(object[arrayPos0].nextTrackID)207end if208end if209end if210end function211212213// ========================214// Events215// ========================216217event ObjectUpdate218temp0 = player[0].xpos219temp0 >>= 16220temp1 = player[0].ypos221temp1 >>= 16222223arrayPos0 = object.entityPos224CallFunction(object.proccessActEffects)225226// ARZ water doesn't really move, but the functionality for it is here anyway just in case ig227if object.ypos < stage.newWaterLevel228object.ypos += 0x10000229end if230if object.ypos > stage.newWaterLevel231object.ypos -= 0x10000232end if233234stage.waterLevel = object.ypos235temp7 = stage.waterLevel236stage.waterLevel >>= 16237238currentPlayer = 0239while currentPlayer < playerCount240#platform: USE_ORIGINS241if game.playMode == BOOT_PLAYMODE_MISSION242if stage.timeEnabled == false243if object[currentPlayer].type == TypeName[Death Event]244object[currentPlayer].timeOver = 11 // 11??? normally the value is just true/false, did they accidentally put two 1's or something?245end if246end if247end if248#endplatform249250if player[currentPlayer].gravityStrength == 0x3800251CheckNotEqual(player[currentPlayer].type, TypeName[Debug Mode])252temp0 = checkResult253CheckNotEqual(player[currentPlayer].state, Player_State_Death)254temp0 &= checkResult255CheckNotEqual(player[currentPlayer].state, Player_State_Static)256temp0 &= checkResult257CheckGreater(player[currentPlayer].ypos, temp7)258temp0 &= checkResult259if temp0 == true260if player[currentPlayer].yvel > 0261player[currentPlayer].yvel >>= 2262end if263264if object.ypos < stage.newWaterLevel265player[currentPlayer].yvel += 0x10000266end if267268if player[currentPlayer].state == Player_State_Fly269StopSfx(SfxName[Flying])270StopSfx(SfxName[Jump])271end if272273player[currentPlayer].xvel >>= 1274player[currentPlayer].speed >>= 1275276CallFunction(Player_UpdatePhysicsState)277278if player[currentPlayer].yvel != 0279CreateTempObject(TypeName[Water Splash], 0, player[currentPlayer].xpos, temp7)280object[tempObjectPos].drawOrder = 4281PlaySfx(SfxName[Water Splash], false)282end if283284object[+currentPlayer].constBubbleTimer = 52285player[currentPlayer].drownTimer = 0286end if287else288if player[currentPlayer].invincibleTimer == 0289if player[currentPlayer].shield == SHIELD_FIRE290temp2 = 0291while temp2 < 8292Rand(temp0, 32)293Rand(temp1, 32)294temp0 -= 16295temp0 <<= 16296temp0 += player[currentPlayer].xpos297temp1 -= 16298temp1 <<= 16299temp1 += player[currentPlayer].ypos300CreateTempObject(TypeName[Dust Puff], 0, temp0, temp1)301object[tempObjectPos].drawOrder = player[currentPlayer].sortedDrawOrder302object[tempObjectPos].drawOrder++303object[tempObjectPos].xvel = player[currentPlayer].xvel304object[tempObjectPos].yvel = player[currentPlayer].yvel305temp2++306loop307308player[currentPlayer].shield = SHIELD_NONE309arrayPos0 = currentPlayer310arrayPos0 += playerCount311CallFunction(Player_ApplyShield)312end if313314// Player hit the water with a lightning shield - take their shield and electrocute the water315if player[currentPlayer].shield == SHIELD_LIGHTNING316player[currentPlayer].shield = SHIELD_NONE317arrayPos0 = currentPlayer318arrayPos0 += playerCount319CallFunction(Player_ApplyShield)320Water_flashTimer = 4321end if322end if323324if player[currentPlayer].shield != SHIELD_BUBBLE325if player[currentPlayer].drownTimer == 0326player[currentPlayer].drownLevel = 0327CallFunction(Water_ResetDrownMusic)328end if329330switch player[currentPlayer].drownLevel331case 0332CallFunction(Water_SpawnSmallAirBubble)333player[currentPlayer].drownTimer++334if player[currentPlayer].drownTimer == 360335#platform: USE_STANDALONE336if currentPlayer == false337#endplatform338#platform: USE_ORIGINS339if player[currentPlayer].isSidekick == false340#endplatform341PlaySfx(SfxName[Drown Alert], false)342end if343player[currentPlayer].drownLevel++344end if345break346347case 1348CallFunction(Water_SpawnSmallAirBubble)349player[currentPlayer].drownTimer++350if player[currentPlayer].drownTimer == 660351#platform: USE_STANDALONE352if currentPlayer == false353#endplatform354#platform: USE_ORIGINS355if player[currentPlayer].isSidekick == false356#endplatform357PlaySfx(SfxName[Drown Alert], false)358end if359player[currentPlayer].drownLevel++360end if361break362363case 2364CallFunction(Water_SpawnSmallAirBubble)365player[currentPlayer].drownTimer++366if player[currentPlayer].drownTimer == 960367#platform: USE_STANDALONE368if currentPlayer == false369#endplatform370#platform: USE_ORIGINS371if player[currentPlayer].isSidekick == false372#endplatform373PlaySfx(SfxName[Drown Alert], false)374end if375player[currentPlayer].drownLevel++376end if377break378379case 3380CallFunction(Water_SpawnSmallAirBubble)381player[currentPlayer].drownTimer++382if player[currentPlayer].drownTimer == 1080383#platform: USE_STANDALONE384if currentPlayer == false385#endplatform386#platform: USE_ORIGINS387if player[currentPlayer].isSidekick == false388#endplatform389object.nextTrackID = music.currentTrack390PlayMusic(TRACK_DROWNING)391end if392393temp0 = 0394CallFunction(Water_SpawnCountDownBubble)395player[currentPlayer].drownLevel++396end if397break398399case 4400CallFunction(Water_SpawnSmallAirBubble)401player[currentPlayer].drownTimer++402if player[currentPlayer].drownTimer == 1200403temp0 = 1404CallFunction(Water_SpawnCountDownBubble)405player[currentPlayer].drownLevel++406end if407break408409case 5410CallFunction(Water_SpawnSmallAirBubble)411player[currentPlayer].drownTimer++412if player[currentPlayer].drownTimer == 1320413temp0 = 2414CallFunction(Water_SpawnCountDownBubble)415player[currentPlayer].drownLevel++416end if417break418419case 6420CallFunction(Water_SpawnSmallAirBubble)421player[currentPlayer].drownTimer++422if player[currentPlayer].drownTimer == 1440423temp0 = 3424CallFunction(Water_SpawnCountDownBubble)425player[currentPlayer].drownLevel++426end if427break428429case 7430CallFunction(Water_SpawnSmallAirBubble)431player[currentPlayer].drownTimer++432if player[currentPlayer].drownTimer == 1560433temp0 = 4434CallFunction(Water_SpawnCountDownBubble)435player[currentPlayer].drownLevel++436end if437break438439case 8440CallFunction(Water_SpawnSmallAirBubble)441player[currentPlayer].drownTimer++442if player[currentPlayer].drownTimer == 1680443temp0 = 5444CallFunction(Water_SpawnCountDownBubble)445player[currentPlayer].drownLevel++446end if447break448449case 9450CallFunction(Water_SpawnSmallAirBubble)451player[currentPlayer].drownTimer++452if player[currentPlayer].drownTimer == 1800453if player[currentPlayer].state != Player_State_Death454#platform: USE_ORIGINS455if options.vsMode == false456#endplatform457if currentPlayer == 0458stage.timeEnabled = false459camera[0].enabled = false460end if461#platform: USE_ORIGINS462else463camera[currentPlayer].style = CAMERASTYLE_STATIC464end if465#endplatform466player[currentPlayer].state = Player_State_Drown467player[currentPlayer].animation = ANI_DROWNING468player[currentPlayer].speed = 0469player[currentPlayer].xvel = 0470player[currentPlayer].yvel = 0471player[currentPlayer].tileCollisions = false472player[currentPlayer].interaction = false473player[currentPlayer].sortedDrawOrder = 5474object[+currentPlayer].constBubbleTimer = 2475PlaySfx(SfxName[Drowning], false)476player[currentPlayer].drownLevel++477end if478end if479break480481case 10482player[currentPlayer].drownTimer++483if player[currentPlayer].drownTimer == 1860484player[currentPlayer].drownLevel++485end if486487if object[+currentPlayer].constBubbleTimer > 0488object[+currentPlayer].constBubbleTimer--489if object[+currentPlayer].randBubbleTimer > 0490object[+currentPlayer].randBubbleTimer--491else492Rand(temp1, 2)493temp1 += 2494CreateTempObject(TypeName[Air Bubble], temp1, player[currentPlayer].xpos, player[currentPlayer].ypos)495object[tempObjectPos].drawOrder = 5496object[tempObjectPos].yvel = -0x8800497object[tempObjectPos].ypos -= 0x60000498airBubble[tempObjectPos].targetPlayer = currentPlayer499Rand(object[tempObjectPos].angle, 256)500airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos501object[+currentPlayer].randBubbleTimer = 512502end if503else504Rand(temp0, 5)505if temp0 == 1506object[+currentPlayer].randBubbleTimer = 2507else508object[+currentPlayer].randBubbleTimer = 512509end if510object[+currentPlayer].constBubbleTimer = 6511512Rand(temp1, 2)513temp1 += 2514CreateTempObject(TypeName[Air Bubble], temp1, player[currentPlayer].xpos, player[currentPlayer].ypos)515object[tempObjectPos].drawOrder = 5516object[tempObjectPos].yvel = -0x8800517object[tempObjectPos].ypos -= 0x60000518airBubble[tempObjectPos].targetPlayer = currentPlayer519Rand(object[tempObjectPos].angle, 0x100)520airBubble[tempObjectPos].originPos.x = object[tempObjectPos].xpos521end if522break523end switch524end if525526CheckEqual(player[currentPlayer].type, TypeName[Debug Mode])527temp0 = checkResult528CheckLower(player[currentPlayer].ypos, temp7)529temp0 |= checkResult530if temp0 == true531if player[currentPlayer].state != Player_State_Death532player[currentPlayer].yvel <<= 1533if player[currentPlayer].yvel < -0x100000534player[currentPlayer].yvel = -0x100000535end if536537#platform: USE_STANDALONE538// Fixes a bug where jumping at the surface of the water will set your velocity too high539// Also yep this fix isn't in Origins, this is taken from the Sega Forever version of the game540if player[currentPlayer].animation == ANI_JUMPING541if player[currentPlayer].timer > 0542if player[currentPlayer].yvel < -0x68000543player[currentPlayer].yvel = -0x68000544end if545end if546end if547#endplatform548549if player[currentPlayer].state == Player_State_Fly550if player[currentPlayer].timer < 480551PlaySfx(SfxName[Flying], true)552else553PlaySfx(SfxName[Jump], true)554end if555end if556557558CallFunction(Player_UpdatePhysicsState)559if player[currentPlayer].yvel != 0560temp0 = object.ypos561temp0 -= player[currentPlayer].ypos562if temp0 < 0xF00000563CreateTempObject(TypeName[Water Splash], 0, player[currentPlayer].xpos, temp7)564object[tempObjectPos].drawOrder = 4565PlaySfx(SfxName[Water Splash], false)566end if567end if568569player[currentPlayer].drownTimer = 0570CallFunction(Water_ResetDrownMusic)571end if572end if573end if574575currentPlayer++576loop577578object.animationTimer++579object.animationTimer &= 31580object.frame = object.animationTimer581object.frame >>= 3582end event583584585event ObjectDraw586temp0 = screen.xoffset587Sin(temp1, oscillation)588temp1 >>= 5589temp0 += temp1590temp0 &= 63591FlipSign(temp0)592temp1 = stage.waterLevel593temp1 -= screen.yoffset594DrawSpriteScreenFX(object.frame, FX_INK, temp0, temp1)595temp0 += 256596DrawSpriteScreenFX(object.frame, FX_INK, temp0, temp1)597end event598599600event ObjectStartup601SetTableValue(Water_ProcessARZAct1, 1, Water_processActTable)602SetTableValue(Water_ProcessARZAct2, 2, Water_processActTable)603604foreach (TypeName[Water], arrayPos0, ALL_ENTITIES)605object[arrayPos0].priority = PRIORITY_ACTIVE606object[arrayPos0].drawOrder = 5607object[arrayPos0].inkEffect = INK_ALPHA608object[arrayPos0].alpha = 0xA0609if credits.screen == 0 // This check will always pass, see below610stage.newWaterLevel = object[arrayPos0].ypos611else612// Leftover from S1 LZ Water, there aren't any in-game credits in this game so this doesn't really matter...613stage.waterState = 1614stage.newWaterLevel = 0x4C80000615temp0 = player[0].xpos616temp0 >>= 16617temp1 = player[0].ypos618temp1 >>= 16619end if620Water_waterSlotID = arrayPos0621GetTableValue(object[arrayPos0].proccessActEffects, stage.actNum, Water_processActTable)622CallFunction(object[arrayPos0].proccessActEffects)623stage.waterLevel = stage.newWaterLevel624stage.waterLevel >>= 16625object[arrayPos0].ypos = stage.newWaterLevel626627if starPostID >= 32628stage.waterState = recWaterState629stage.waterLevel = recWaterLevel630stage.newWaterLevel = recWaterLevel631stage.newWaterLevel <<= 16632arrayPos0 = Water_waterSlotID633object[arrayPos0].ypos = stage.newWaterLevel634else635if credits.screen == 0 // This check will always pass, see above636stage.waterState = 0637end if638end if639next640641Water_activateFlag = false642643foreach (GROUP_PLAYERS, currentPlayer, ALL_ENTITIES)644player[currentPlayer].drownTimer = 0645if player[currentPlayer].ypos > stage.newWaterLevel646player[currentPlayer].yvel >>= 2647player[currentPlayer].xvel >>= 1648player[currentPlayer].speed >>= 1649player[currentPlayer].topSpeed >>= 1650player[currentPlayer].acceleration >>= 1651player[currentPlayer].deceleration >>= 1652player[currentPlayer].airAcceleration >>= 1653player[currentPlayer].airDeceleration >>= 1654player[currentPlayer].gravityStrength = 0x1000655if stage.playerListPos == PLAYER_KNUCKLES_A656player[currentPlayer].jumpStrength = 0x30000657else658player[currentPlayer].jumpStrength = 0x38000659end if660player[currentPlayer].jumpCap = -0x20000661arrayPos0 = Water_waterSlotID662arrayPos0 += currentPlayer663object[arrayPos0].constBubbleTimer = 52664end if665next666667#platform: USE_ORIGINS668if options.vsMode == true669object[SLOT_VSGAME].waterSlotID = Water_waterSlotID670end if671#endplatform672673// The only ARZ object to actually use this sheet...674// All the other water-related objects in this zone (besides Water Splash) use "CPZ/Objects2.gif" instead...675LoadSpriteSheet("ARZ/Objects2.gif")676SpriteFrame(0, -7, 256, 16, 0, 0)677SpriteFrame(0, -7, 256, 16, 0, 16)678SpriteFrame(0, -7, 256, 16, 0, 32)679SpriteFrame(0, -7, 256, 16, 0, 48)680681BrokenMonitor_ResetDrownMusic = Water_ResetDrownMusic682end event683684685// ========================686// Editor Events687// ========================688689event RSDKDraw690DrawSprite(0)691end event692693694event RSDKLoad695LoadSpriteSheet("ARZ/Objects2.gif")696SpriteFrame(0, -7, 256, 16, 0, 0)697698SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")699end event700701702