Path: blob/master/Sonic 2/Scripts/OOZ/CheckeredBall.txt
1480 views
// ----------------------------------1// RSDK Project: Sonic 22// Script Description: Checkered Ball Object3// Script Author: Christian Whitehead/Simon Thomley4// Unpacked by Rubberduckycooly's script unpacker5// ----------------------------------67// ========================8// Aliases9// ========================1011private alias object.value0 : object.unused // reset a couple of times, never used for anything noteworthy12private alias object.value1 : object.roundedPos.x13private alias object.value2 : object.roundedPos.y14private alias object.value3 : object.ballAngle15private alias object.value4 : object.groundAngle16private alias object.value5 : object.angleVel17private alias object.value6 : object.playerControlled18private alias object.value7 : object.startPos.x19private alias object.value8 : object.startPos.y20// object.value9 is unused21private alias object.value10 : object.activePlayers22private alias object.value11 : object.badnikBonus23private alias object.value12 : object.collisionOffset.x24private alias object.value13 : object.collisionOffset.y25// object.value14 is unused26private alias object.value15 : object.parent // Should be a ballcannon entity2728// States29private alias 0 : CHECKEREDBALL_NORMAL30private alias 1 : CHECKEREDBALL_LAUNCHED3132// Player Aliases33private alias object.xpos : player.xpos34private alias object.ypos : player.ypos35private alias object.xvel : player.xvel36private alias object.speed : player.speed37private alias object.gravity : player.gravity38private alias object.pushing : player.pushing39private alias object.controlLock : player.controlLock40private alias object.collisionLeft : player.collisionLeft41private alias object.collisionRight : player.collisionRight42private alias object.left : player.left43private alias object.right : player.right4445private alias object.value20 : player.topSpeed46private alias object.value21 : player.acceleration4748// Super States49private alias 1 : SUPERSTATE_SUPER50private alias 2 : SUPERSTATE_FADEOUT5152// Monitor Aliases53private alias object.value0 : monitor.contentsPos.y54private alias object.value1 : monitor.timer5556// Spring Aliases57private alias object.value0 : spring.timer58private alias object.value1 : spring.active59private alias object.value2 : spring.extraVelocity6061// Plane Sw V Aliases62private alias object.value0 : planeSwV.extendTop63private alias object.value1 : planeSwV.extendBottom64private alias object.value2 : planeSwV.planeR65private alias object.value3 : planeSwV.planeL66private alias object.value4 : planeSwV.drawOrderR67private alias object.value5 : planeSwV.drawOrderL68private alias object.value6 : planeSwV.onGround6970// Plane Sw H Aliases71private alias object.value0 : planeSwH.extendLeft72private alias object.value1 : planeSwH.extendRight73private alias object.value2 : planeSwH.planeR74private alias object.value3 : planeSwH.planeL75private alias object.value4 : planeSwH.drawOrderR76private alias object.value5 : planeSwH.drawOrderL77private alias object.value6 : planeSwH.onGround7879// AnimalPrison Aliases80private alias object.value2 : animalPrison.buttonPos81private alias object.value3 : animalPrison.lockPos.x82private alias object.value4 : animalPrison.lockPos.y8384// AnimalPrison States85private alias 0 : ANIMALPRISON_AWAITOPEN86private alias 1 : ANIMALPRISON_OPENING8788// CFloor Aliases89private alias 0 : CFLOOR_ACTIVE90private alias 1 : CFLOOR_COLLAPSE91private alias 3 : CFLOOR_NONE9293// SwingPlatform94private alias object.value1 : swingPlatform.drawPos.x95private alias object.value2 : swingPlatform.drawPos.y96private alias object.value3 : swingPlatform.collisionOffset.x97private alias object.value4 : swingPlatform.collisionOffset.y9899// Tile Flag Aliases100private alias 0 : TILE_NORMAL101private alias 1 : TILE_OILPOOL102private alias 3 : TILE_OILSTRIP103private alias 5 : TILE_OILSLIDE104105// Tile Info ID Aliases106private alias 8 : TILEINFO_ANGLEB107108// VPushSpring Aliases109private alias object.value1 : vPushSpring.pushOffset110private alias object.value2 : vPushSpring.collisionOffset.y111private alias object.value3 : vPushSpring.beingPushed112113// VPushSpring States114private alias 2 : VPUSHSPRING_RELEASE115116// HPushSpring Aliases117private alias object.value1 : hPushSpring.pushOffset118private alias object.value2 : hPushSpring.beingPushed119120// HPushSpring States121private alias 1 : HPUSHSPRING_PUSHING122123// Elevator Aliases124private alias object.value4 : elevator.collisionOffset.y125126// BallCannon Aliases127private alias object.value0 : ballCannon.timer128private alias object.value1 : ballCannon.tablePos129private alias object.value5 : ballCannon.activePlayers130private alias object.value6 : ballCannon.lastCannon131132// BallCannon States133private alias 1 : BALLCANNON_ENTERED134private alias 4 : BALLCANNON_EXITED135136// PushButton Aliases137private alias object.value0 : pushButton.pressed138private alias object.value1 : pushButton.stood139140// GasBreakBlock States141private alias 0 : GASBREAKBLOCK_BLOCKS142private alias 1 : GASBREAKBLOCK_LAUNCHER143private alias 2 : GASBREAKBLOCK_DEBRIS144145// GasPlatform Aliases146private alias object.value1 : gasPlatform.centerPos.y147private alias object.value2 : gasPlatform.collisionOffset.y148149// OOZEggman Aliases150private alias object.value0 : oozEggman.timer151private alias object.value3 : oozEggman.health152private alias object.value4 : oozEggman.invincibilityTimer153private alias object.value5 : oozEggman.exploding154private alias object.value9 : oozEggman.spawnHarpoon155156// OOZEggman States157private alias 7 : OOZEGGMAN_EXPLODE158159// OOZEggman Animations160private alias 3 : OOZEGGANI_HIT161private alias 4 : OOZEGGANI_DEFEATED162163164// ========================165// Function Declarations166// ========================167168reserve function CheckeredBall_DebugDraw169reserve function CheckeredBall_DebugSpawn170reserve function CheckeredBall_HandlePlayerMove171reserve function CheckeredBall_PlayerInteraction172reserve function CheckeredBall_BadnikBreak173reserve function CheckeredBall_ReflectProjectile174reserve function CheckeredBall_SpringBounce175reserve function CheckeredBall_CLedgeCollapse176reserve function CheckeredBall_HandlePhysics177178179// ========================180// Tables181// ========================182183private table CheckeredBall_heightArray1840, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 20185end table186187// Seems to be unused, and as such, its purpose is unknown...188// This same table exists in S1's and Mania's unused CheckeredBall objects as well, for whatever reason189private table CheckeredBall_unusedTable190253, 251, 248, 245, 243, 240, 237, 235, 232, 229, 226, 224, 221, 219, 216, 213, 210, 208, 205, 203, 200, 197, 195, 192191end table192193194// ========================195// Function Definitions196// ========================197198private function CheckeredBall_DebugDraw199DrawSprite(1)200end function201202203private function CheckeredBall_DebugSpawn204CreateTempObject(TypeName[Checkered Ball], 0, object.xpos, object.ypos)205object[tempObjectPos].gravity = GRAVITY_AIR206object[tempObjectPos].startPos.x = object.xpos207object[tempObjectPos].startPos.y = object.ypos208object[tempObjectPos].roundedPos.x = object.xpos209object[tempObjectPos].roundedPos.y = object.ypos210end function211212213private function CheckeredBall_HandlePlayerMove214object.activePlayers = 0215216temp2 = 0217foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)218CheckEqual(options.attractMode, true)219temp1 = checkResult220CheckEqual(currentPlayer, 1)221temp1 &= checkResult222temp0 = player[currentPlayer].acceleration223temp0 >>= 1224225if player[currentPlayer].gravity == 0226if player[currentPlayer].xvel < 0227BoxCollisionTest(C_TOUCH, object.entityPos, 0, -14, 15, 14, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)228if checkResult == true229if player[currentPlayer].left == true230if temp1 == false231SetBit(object.activePlayers, temp2, true)232temp1 = player[currentPlayer].topSpeed233FlipSign(temp1)234if object.speed > temp1235object.speed -= temp0236end if237object.playerControlled = true238end if239240player[currentPlayer].xpos = player[currentPlayer].collisionRight241player[currentPlayer].xpos += 14242player[currentPlayer].xpos <<= 16243player[currentPlayer].xpos += object.roundedPos.x244245if object.xvel < 0246if player[currentPlayer].speed < object.speed247player[currentPlayer].xvel = object.xvel248player[currentPlayer].speed = object.speed249end if250end if251252player[currentPlayer].pushing = 2253end if254end if255else256if player[currentPlayer].xvel > 0257BoxCollisionTest(C_TOUCH, object.entityPos, -15, -14, 0, 14, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)258if checkResult == true259if player[currentPlayer].right == true260if temp1 == false261SetBit(object.activePlayers, temp2, true)262if object.speed < player[currentPlayer].topSpeed263object.speed += temp0264end if265object.playerControlled = true266end if267268player[currentPlayer].xpos = player[currentPlayer].collisionLeft269player[currentPlayer].xpos += -14270player[currentPlayer].xpos <<= 16271player[currentPlayer].xpos += object.roundedPos.x272273if object.xvel > 0274if player[currentPlayer].speed > object.speed275player[currentPlayer].xvel = object.xvel276player[currentPlayer].speed = object.speed277end if278end if279280player[currentPlayer].pushing = 2281end if282end if283end if284end if285end if286temp2++287next288end function289290291private function CheckeredBall_PlayerInteraction292temp6 = object.xpos293temp6 &= 0xFFFF0000294temp6 -= object.roundedPos.x295296temp7 = object.ypos297temp7 &= 0xFFFF0000298temp7 -= object.roundedPos.y299300temp4 = object.xpos301temp5 = object.ypos302object.xpos = object.roundedPos.x303object.ypos = object.roundedPos.y304305temp2 = 0306foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)307BoxCollisionTest(C_TOUCH, object.entityPos, -2, -2, 2, 2, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)308if checkResult == false309GetBit(temp0, object.activePlayers, temp2)310if temp0 == true311if player[currentPlayer].xpos < object.xpos312temp1 = player[currentPlayer].collisionRight313FlipSign(temp1)314temp1 -= 14315else316temp1 = player[currentPlayer].collisionLeft317FlipSign(temp1)318temp1 += 14319end if320321temp1 <<= 16322player[currentPlayer].xpos = temp1323player[currentPlayer].xpos += temp4324else325BoxCollisionTest(C_SOLID, object.entityPos, -14, -14, 14, 14, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)326if checkResult == COL_TOP327player[currentPlayer].xpos += temp6328temp0 = temp6329temp0 >>= 1330player[currentPlayer].xpos += temp0331player[currentPlayer].ypos += temp7332333if player[currentPlayer].xvel != 0334temp0 = player[currentPlayer].acceleration335temp0 >>= 2336if player[currentPlayer].xvel > 0337FlipSign(temp0)338end if339else340temp0 = 0341end if342343object.speed += temp0344if temp0 != 0345object.playerControlled = true346end if347348object.xpos = temp4349object.ypos = temp5350BoxCollisionTest(C_SOLID, object.entityPos, -14, -14, 14, 14, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)351object.xpos = object.roundedPos.x352object.ypos = object.roundedPos.y353if checkResult == COL_NONE354temp0 = temp6355temp1 = temp6356temp0 >>= 1357temp1 += temp0358player[currentPlayer].speed += temp0359player[currentPlayer].xvel = player[currentPlayer].speed360player[currentPlayer].gravity = GRAVITY_AIR361player[currentPlayer].controlLock = 15362end if363end if364365if checkResult == COL_BOTTOM366if object.yvel >= 0367if player[currentPlayer].gravity == 0368CallFunction(Player_Kill)369end if370end if371end if372end if373374temp2++375end if376next377378object.xpos = temp4379object.ypos = temp5380end function381382383private function CheckeredBall_BadnikBreak384temp0 = object.xvel385temp0 |= object.yvel386if temp0 != 0387ResetObjectEntity(object[arrayPos0].entityPos, TypeName[Blank Object], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)388Rand(checkResult, 32)389if checkResult >= 16390CreateTempObject(animalType1, 0, object[arrayPos0].xpos, object[arrayPos0].ypos)391else392CreateTempObject(animalType2, 0, object[arrayPos0].xpos, object[arrayPos0].ypos)393end if394object[tempObjectPos].priority = PRIORITY_ACTIVE_SMALL395396CreateTempObject(TypeName[Smoke Puff], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)397object[tempObjectPos].drawOrder = 4398399CreateTempObject(TypeName[Object Score], object.badnikBonus, object[arrayPos0].xpos, object[arrayPos0].ypos)400object[tempObjectPos].drawOrder = 4401402PlaySfx(SfxName[Destroy], false)403404// No 2P trickery here!405switch object.badnikBonus406case 0407player.score += 100408break409410case 1411player.score += 200412break413414case 2415player.score += 500416break417418case 3419case 4420case 5421case 6422case 7423case 8424case 9425case 10426case 11427case 12428case 13429case 14430player.score += 1000431break432433case 15434player.score += 10000435break436437end switch438439if object.badnikBonus < 15440object.badnikBonus++441end if442end if443end function444445446private function CheckeredBall_ReflectProjectile447// Do some maths to find where the projectile should go now448temp0 = object.xpos449temp0 -= object[arrayPos0].xpos450temp1 = object.ypos451temp1 -= object[arrayPos0].ypos452453ATan2(temp2, temp0, temp1)454Sin256(temp0, temp2)455Cos256(temp1, temp2)456457object[arrayPos0].xvel = temp1458object[arrayPos0].xvel *= -0x800459object[arrayPos0].yvel = temp0460object[arrayPos0].yvel *= -0x800461end function462463464private function CheckeredBall_SpringBounce465switch object[arrayPos0].propertyValue466case 0467temp0 = spring[arrayPos0].active468if object.gravity == 1469temp0 = true470end if471472if object.collisionMode > 0473if object.yvel < 0474temp0 = true475end if476end if477478if temp0 == false479BoxCollisionTest(C_SOLID, object[arrayPos0].entityPos, -14, -8, 14, 8, object.entityPos, -14, -14, 14, 14)480BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, -14, -10, 14, -6, object.entityPos, -14, -14, 14, 14)481if checkResult == true482spring[arrayPos0].timer = 1483object.tileCollisions = true484object.gravity = GRAVITY_AIR485object.speed = object.xvel486object.yvel = temp7487FlipSign(object.yvel)488object.yvel += spring[arrayPos0].extraVelocity489PlaySfx(SfxName[Spring], false)490end if491else492if object.yvel >= 0493BoxCollisionTest(C_PLATFORM, object[arrayPos0].entityPos, -14, -8, 14, 8, object.entityPos, -14, -14, 14, 14)494BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, -14, -10, 14, -6, object.entityPos, -14, -14, 14, 14)495if checkResult == true496spring[arrayPos0].timer = 1497object.tileCollisions = true498object.gravity = GRAVITY_AIR499object.speed = object.xvel500object.yvel = temp7501FlipSign(object.yvel)502object.yvel += spring[arrayPos0].extraVelocity503PlaySfx(SfxName[Spring], false)504end if505end if506end if507break508509case 1510BoxCollisionTest(C_SOLID, object[arrayPos0].entityPos, -8, -14, 8, 14, object.entityPos, -14, -14, 14, 14)511if object.gravity == 0512BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, 6, -14, 10, 14, object.entityPos, -14, -14, 14, 14)513if checkResult == true514spring[arrayPos0].timer = 1515object.tileCollisions = true516object.speed = temp7517object.collisionMode = CMODE_FLOOR518object.direction = FLIP_NONE519PlaySfx(SfxName[Spring], false)520end if521end if522break523524case 2525BoxCollisionTest(C_SOLID, object[arrayPos0].entityPos, -8, -14, 8, 14, object.entityPos, -14, -14, 14, 14)526if object.gravity == 0527BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, -10, -14, -6, 14, object.entityPos, -14, -14, 14, 14)528if checkResult == true529spring[arrayPos0].timer = 1530object.tileCollisions = true531object.speed = temp7532FlipSign(object.speed)533object.collisionMode = CMODE_FLOOR534object.direction = FLIP_X535PlaySfx(SfxName[Spring], false)536end if537end if538break539540case 3541BoxCollisionTest(C_SOLID, object[arrayPos0].entityPos, -14, -8, 14, 8, object.entityPos, -14, -14, 14, 14)542BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, -14, 6, 14, 10, object.entityPos, -14, -14, 14, 14)543if checkResult == true544spring[arrayPos0].timer = 1545if object.collisionMode == 2546FlipSign(object.speed)547FlipSign(object.xvel)548end if549object.tileCollisions = true550object.gravity = GRAVITY_AIR551object.speed = object.xvel552object.yvel = temp7553PlaySfx(SfxName[Spring], false)554end if555break556557end switch558end function559560561private function CheckeredBall_CLedgeCollapse562if object[arrayPos0].state < CFLOOR_NONE563564// what? why is this here??565// If I had to guess, I'd say it's just a debugging leftover or something, but it's certainly very strange566player.score++567568if object[arrayPos0].propertyValue < 2569if object.yvel >= 0570BoxCollisionTest(C_PLATFORM, arrayPos0, -64, -24, 64, 0, object.entityPos, -10, -14, 10, 14)571else572checkResult = COL_NONE573end if574else575BoxCollisionTest(C_SOLID, arrayPos0, -64, -16, 64, 16, object.entityPos, -10, -14, 10, 14)576end if577578if checkResult == COL_TOP579if object[arrayPos0].state == CFLOOR_ACTIVE580object[arrayPos0].state = CFLOOR_COLLAPSE581object[arrayPos0].priority = PRIORITY_ACTIVE582end if583end if584end if585end function586587588private function CheckeredBall_HandlePhysics589if object.gravity == 1590object.yvel += 0x3800591object.speed = object.xvel592else593Sin256(temp0, object.groundAngle)594temp0 *= 0x2000595temp0 >>= 8596object.speed += temp0597object.angleVel = object.speed598if temp0 == 0599if object.playerControlled == false600if object.speed > 0601object.speed -= 0x400602if object.speed < 0603object.speed = 0604end if605else606object.speed += 0x400607if object.speed > 0608object.speed = 0609end if610end if611end if612end if613614Cos256(temp0, object.groundAngle)615temp0 *= object.speed616temp0 >>= 8617object.xvel = temp0618619Sin256(temp0, object.groundAngle)620temp0 *= object.speed621temp0 >>= 8622object.yvel = temp0623end if624625object.playerControlled = false626end function627628629// ========================630// Events631// ========================632633event ObjectUpdate634if object.state == CHECKEREDBALL_NORMAL635object.priority = PRIORITY_ACTIVE636CallFunction(CheckeredBall_HandlePlayerMove)637object.ballAngle += object.angleVel638object.collisionLeft = -14639object.collisionTop = -14640object.collisionRight = 14641object.collisionBottom = 14642CallFunction(CheckeredBall_HandlePhysics)643ProcessObjectMovement()644object.groundAngle = object.angle645else646object.collisionLeft = -14647object.collisionTop = -14648object.collisionRight = 14649object.collisionBottom = 14650ProcessObjectMovement()651object.ballAngle += 0x40000652end if653654// Cycle through all objects655foreach (0, arrayPos0, ACTIVE_ENTITIES)656// Jump to the object's type657// If not listed here, it has no interaction658switch object[arrayPos0].type659case TypeName[Octus]660BoxCollisionTest(C_TOUCH, object.entityPos, -14, -14, 14, 14, arrayPos0, -16, -12, 16, 12)661if checkResult == true662CallFunction(CheckeredBall_BadnikBreak)663end if664break665666case TypeName[Aquis]667BoxCollisionTest(C_TOUCH, object.entityPos, -14, -14, 14, 14, arrayPos0, -16, -10, 16, 10)668if checkResult == true669CallFunction(CheckeredBall_BadnikBreak)670end if671break672673case TypeName[Octus Shot]674BoxCollisionTest(C_TOUCH, object.entityPos, -14, -14, 14, 14, arrayPos0, -4, -4, 4, 4)675if checkResult == true676CallFunction(CheckeredBall_ReflectProjectile)677end if678break679680case TypeName[Aquis Shot]681BoxCollisionTest(C_TOUCH, object.entityPos, -14, -14, 14, 14, arrayPos0, -4, -4, 4, 4)682if checkResult == true683CallFunction(CheckeredBall_ReflectProjectile)684end if685break686687case TypeName[Monitor]688BoxCollisionTest(C_TOUCH, object.entityPos, -14, -14, 14, 14, arrayPos0, -16, -14, 16, 16)689if checkResult == true690object[arrayPos0].state = 0691CreateTempObject(TypeName[Smoke Puff], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)692object[tempObjectPos].drawOrder = 4693object[arrayPos0].type = TypeName[Broken Monitor]694695if object[arrayPos0].priority != PRIORITY_XBOUNDS_DESTROY696object[arrayPos0].priority = PRIORITY_ACTIVE697end if698699object[arrayPos0].alpha = 0xFF700monitor[arrayPos0].contentsPos.y = object[arrayPos0].ypos701monitor[arrayPos0].timer = -0x30000702PlaySfx(SfxName[Destroy], false)703end if704break705706case TypeName[Spikes]707switch object[arrayPos0].propertyValue708case 0709BoxCollisionTest(C_SOLID, arrayPos0, -16, -16, 16, 16, object.entityPos, -14, -14, 14, 14)710break711712case 1713BoxCollisionTest(C_SOLID, arrayPos0, -16, -16, 15, 16, object.entityPos, -14, -14, 14, 14)714break715716case 2717BoxCollisionTest(C_SOLID, arrayPos0, -15, -16, 16, 16, object.entityPos, -14, -14, 14, 14)718break719720case 3721BoxCollisionTest(C_SOLID, arrayPos0, -16, -16, 16, 15, object.entityPos, -14, -14, 14, 14)722break723724end switch725726switch checkResult727case COL_TOP728object.gravity = GRAVITY_GROUND729break730731case COL_LEFT732if object.speed > 0733object.speed = 0734end if735break736737case COL_RIGHT738if object.speed < 0739object.speed = 0740end if741break742end switch743break744745case TypeName[Yellow Spring]746temp7 = 0xA0000747CallFunction(CheckeredBall_SpringBounce)748break749750case TypeName[Red Spring]751temp7 = 0x100000752CallFunction(CheckeredBall_SpringBounce)753break754755case TypeName[V Push Spring]756temp0 = vPushSpring[arrayPos0].pushOffset757temp0 -= vPushSpring[arrayPos0].collisionOffset.y758temp0 >>= 16759temp0 -= 20760BoxCollisionTest(C_SOLID, arrayPos0, -16, temp0, 16, 20, object.entityPos, -10, -14, 10, 14)761if checkResult == COL_TOP762vPushSpring[arrayPos0].beingPushed |= true763object.ypos += vPushSpring[arrayPos0].collisionOffset.y764if object[arrayPos0].state == VPUSHSPRING_RELEASE765if vPushSpring[arrayPos0].pushOffset == 0x120000766object.gravity = GRAVITY_AIR767object.yvel = -0x60000768object.unused = 0769PlaySfx(SfxName[Spring], false)770end if771end if772end if773break774775case TypeName[H Push Spring]776if object[arrayPos0].direction == FLIP_NONE777temp0 = -20778temp1 = hPushSpring[arrayPos0].pushOffset779temp1 >>= 16780FlipSign(temp1)781temp1 += 22782else783temp0 = hPushSpring[arrayPos0].pushOffset784temp0 >>= 16785temp0 -= 22786temp1 = 20787end if788789temp2 = object.speed790BoxCollisionTest(C_SOLID, arrayPos0, temp0, -16, temp1, 16, object.entityPos, -10, -14, 10, 14)791object.speed = temp2792switch checkResult793case COL_LEFT794temp0 >>= 8795object.speed -= temp0796if object.speed > 0797hPushSpring[arrayPos0].beingPushed |= true798end if799800if object[arrayPos0].state == HPUSHSPRING_PUSHING801if hPushSpring[arrayPos0].pushOffset > 0x10000802object.speed = -12803object.speed *= hPushSpring[arrayPos0].pushOffset804object.speed /= 18805object.collisionMode = CMODE_FLOOR806PlaySfx(SfxName[Spring], false)807end if808end if809break810811case COL_RIGHT812temp0 >>= 5813object.speed -= temp0814if object.speed < 0815hPushSpring[arrayPos0].beingPushed |= true816end if817818if object[arrayPos0].state == HPUSHSPRING_PUSHING819if hPushSpring[arrayPos0].pushOffset > 0x10000820object.speed = 12821object.speed *= hPushSpring[arrayPos0].pushOffset822object.speed /= 18823PlaySfx(SfxName[Spring], false)824end if825end if826break827end switch828break829830case TypeName[Ball Cannon]831BoxCollisionTest(C_TOUCH, arrayPos0, -4, -4, 4, 4, object.entityPos, -10, -14, 10, 14)832if checkResult == true833temp0 = 1834temp0 <<= 5835temp0 &= object[arrayPos0].activePlayers836if temp0 == false837object.state = CHECKEREDBALL_LAUNCHED838object.xpos = object[arrayPos0].xpos839object.ypos = object[arrayPos0].ypos840object.speed = 0841object.xvel = 0842object.yvel = 0843object.visible = false844object.tileCollisions = false845temp0 = 1846temp0 <<= 5847ballCannon[arrayPos0].activePlayers |= temp0848ballCannon[arrayPos0].timer = 0849ballCannon[arrayPos0].tablePos = 0850object[arrayPos0].state = BALLCANNON_ENTERED851if object[arrayPos0].priority != PRIORITY_XBOUNDS_DESTROY852object[arrayPos0].priority = PRIORITY_ACTIVE853end if854object.parent = arrayPos0855PlaySfx(SfxName[Rolling], false)856end if857end if858break859860case TypeName[Gas Platform]861temp0 = object[arrayPos0].ypos862863object[arrayPos0].ypos = gasPlatform[arrayPos0].centerPos.y864BoxCollisionTest(C_SOLID, arrayPos0, -32, 8, 32, 48, object.entityPos, -10, -14, 10, 14)865BoxCollisionTest(C_SOLID, arrayPos0, -16, 0, 16, 24, object.entityPos, -10, -14, 10, 14)866867object[arrayPos0].ypos = temp0868object[arrayPos0].ypos -= gasPlatform[arrayPos0].collisionOffset.y869BoxCollisionTest(C_PLATFORM, arrayPos0, -24, -8, 24, 12, object.entityPos, -10, -14, 10, 14)870if checkResult == true871object.collisionOffset.y = gasPlatform[arrayPos0].collisionOffset.y872end if873874object[arrayPos0].ypos += gasPlatform[arrayPos0].collisionOffset.y875break876877case TypeName[Elevator]878object[arrayPos0].ypos -= elevator[arrayPos0].collisionOffset.y879880if object[arrayPos0].frame == 0881BoxCollisionTest(C_PLATFORM, arrayPos0, -64, -12, 64, 12, object.entityPos, -10, -14, 10, 14)882else883BoxCollisionTest(C_PLATFORM, arrayPos0, -32, -12, 32, 12, object.entityPos, -10, -14, 10, 14)884end if885886if checkResult == true887object.collisionOffset.y = elevator[arrayPos0].collisionOffset.y888end if889890object[arrayPos0].ypos += elevator[arrayPos0].collisionOffset.y891break892893case TypeName[Swing Platform]894temp0 = object[arrayPos0].xpos895temp1 = object[arrayPos0].ypos896object[arrayPos0].xpos = swingPlatform[arrayPos0].drawPos.x897object[arrayPos0].ypos = swingPlatform[arrayPos0].drawPos.y898object[arrayPos0].xpos -= swingPlatform[arrayPos0].collisionOffset.x899object[arrayPos0].ypos -= swingPlatform[arrayPos0].collisionOffset.y900BoxCollisionTest(C_PLATFORM, object[arrayPos0].entityPos, -32, -8, 32, 8, object.entityPos, -10, -14, 10, 14)901if checkResult == true902object.collisionOffset.x = swingPlatform[arrayPos0].collisionOffset.x903object.collisionOffset.y = swingPlatform[arrayPos0].collisionOffset.y904end if905object[arrayPos0].xpos = temp0906object[arrayPos0].ypos = temp1907break908909case TypeName[C Floor]910CallFunction(CheckeredBall_CLedgeCollapse)911break912913case TypeName[Plane Sw V]914// Why is this here, plane switches don't even exist in OOZ...915// (Likely just leftover from copying S1's CheckeredBall object, since there *are* path swappers in GHZ)916CheckEqual(planeSwV[arrayPos0].onGround, false)917temp0 = checkResult918CheckEqual(object.gravity, 0)919temp0 |= checkResult920if temp0 == true921BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, -12, planeSwV[arrayPos0].extendTop, 12, planeSwV[arrayPos0].extendBottom, object.entityPos, -14, -2, 14, 2)922if checkResult == true923if object.xvel > 0924object.collisionPlane = planeSwV[arrayPos0].planeL925object.drawOrder = planeSwV[arrayPos0].drawOrderL926else927object.collisionPlane = planeSwV[arrayPos0].planeR928object.drawOrder = planeSwV[arrayPos0].drawOrderR929end if930end if931end if932break933934case TypeName[Plane Sw H]935// See above note, likely the same story here936// Although the Origins version of the S1 GHZ Checkered Ball script broke Sw H interactions, this was left alone and still works just fine937CheckEqual(planeSwH[arrayPos0].onGround, false)938temp0 = checkResult939CheckEqual(object.gravity, 0)940temp0 |= checkResult941if temp0 == true942BoxCollisionTest(C_TOUCH, object[arrayPos0].entityPos, planeSwH[arrayPos0].extendLeft, -12, planeSwH[arrayPos0].extendRight, 12, object.entityPos, -14, -2, 14, 2)943if checkResult == true944if object.yvel > 0945object.collisionPlane = planeSwH[arrayPos0].planeL946object.drawOrder = planeSwH[arrayPos0].drawOrderL947else948object.collisionPlane = planeSwH[arrayPos0].planeL949object.drawOrder = planeSwH[arrayPos0].drawOrderR950end if951end if952end if953break954955case TypeName[Eggman]956if oozEggman[arrayPos0].health != 0957if object[arrayPos0].visible == true958if oozEggman[arrayPos0].invincibilityTimer == 0959BoxCollisionTest(C_TOUCH, arrayPos0, -24, -10, 24, 24, object.entityPos, -14, -14, 14, 14)960if checkResult == true961oozEggman[arrayPos0].health--962if oozEggman[arrayPos0].health == 0963player.score += 1000964object[arrayPos0].animationTimer = 0965object[arrayPos0].animation = OOZEGGANI_DEFEATED966oozEggman[arrayPos0].exploding = true967oozEggman[arrayPos0].timer = 0968object[arrayPos0].state = OOZEGGMAN_EXPLODE969SetPaletteEntry(0, 192, 0x000000)970else971object[arrayPos0].animationTimer = 0972object[arrayPos0].animation = OOZEGGANI_HIT973oozEggman[arrayPos0].invincibilityTimer = 64974oozEggman[arrayPos0].spawnHarpoon = true975PlaySfx(SfxName[Boss Hit], false)976end if977end if978end if979end if980end if981break982983case TypeName[Push Button]984if object[arrayPos0].frame == 0985BoxCollisionTest(C_SOLID, arrayPos0, -14, -6, 14, 12, object.entityPos, -14, -14, 14, 14)986if checkResult == COL_TOP987pushButton[arrayPos0].stood = true988pushButton[arrayPos0].pressed = true989object.ypos += 40000990PlaySfx(SfxName[Button Press], false)991end if992else993if object.yvel >= 0994BoxCollisionTest(C_PLATFORM, arrayPos0, -14, -6, 14, 12, object.entityPos, -14, -14, 14, 14)995if checkResult == true996pushButton[arrayPos0].stood = true997object.ypos += 0x20000998else999BoxCollisionTest(C_TOUCH, arrayPos0, -20, -12, 20, 8, object.entityPos, -14, -14, 14, 14)1000if checkResult == true1001object.ypos = object.collisionBottom1002FlipSign(object.ypos)1003object.ypos <<= 161004object.ypos += object[arrayPos0].ypos1005object.ypos -= 0x200001006object.gravity = GRAVITY_AIR1007end if1008end if1009end if1010end if1011break10121013case TypeName[Checkered Ball]1014if arrayPos0 != object.entityPos1015temp0 = object.xpos1016temp0 -= object[arrayPos0].xpos1017Abs(temp0)1018temp0 >>= 171019if temp0 >= 161020temp0 = 151021end if1022GetTableValue(temp6, temp0, CheckeredBall_heightArray)1023temp0 = temp61024temp0 >>= 11025temp6 += temp01026temp6 -= 141027temp7 = temp61028FlipSign(temp7)1029temp0 = object.xvel1030temp1 = object.yvel1031temp2 = object.speed1032BoxCollisionTest(C_SOLID, arrayPos0, -14, temp6, 14, temp7, object.entityPos, -14, -14, 14, 14)1033switch checkResult1034case COL_LEFT1035case COL_RIGHT1036CheckGreater(temp0, 0)1037temp3 = checkResult1038CheckLower(object.xpos, object[arrayPos0].xpos)1039temp3 &= checkResult1040CheckLower(temp0, 0)1041temp4 = checkResult1042CheckGreater(object.xpos, object[arrayPos0].xpos)1043temp4 &= checkResult1044temp3 |= temp41045if temp3 != 01046object.xvel = object[arrayPos0].xvel1047object.speed = object[arrayPos0].speed1048object[arrayPos0].xvel = temp01049object[arrayPos0].speed = temp21050end if1051break10521053case COL_TOP1054if object.xpos < object[arrayPos0].xpos1055object.speed -= 0xC001056object.xvel -= 0xC001057object[arrayPos0].speed += 0xC001058object[arrayPos0].xvel += 0xC001059object[arrayPos0].angleVel += 0xC001060else1061object.speed += 0xC001062object.xvel += 0xC001063object[arrayPos0].speed -= 0xC001064object[arrayPos0].xvel -= 0xC001065object[arrayPos0].angleVel -= 0xC001066end if1067// [Fallthrough]1068case COL_BOTTOM1069CheckGreater(temp1, 0)1070temp3 = checkResult1071CheckLower(object.ypos, object[arrayPos0].ypos)1072temp3 &= checkResult1073CheckLower(temp1, 0)1074temp4 = checkResult1075CheckGreater(object.ypos, object[arrayPos0].ypos)1076temp4 &= checkResult1077temp3 |= temp41078if temp3 != 01079object.yvel = object[arrayPos0].yvel1080object[arrayPos0].yvel = temp11081end if1082break10831084end switch10851086BoxCollisionTest(C_TOUCH, arrayPos0, -14, temp6, 14, temp7, object.entityPos, -14, -14, 14, 14)1087if checkResult == true1088if object.xpos < object[arrayPos0].xpos1089object.xpos -= 0x100001090else1091object.xpos += 0x100001092end if1093if object.ypos < object[arrayPos0].ypos1094object.ypos -= 0x100001095else1096object.ypos += 0x100001097end if1098end if1099end if1100break11011102case TypeName[Gas Break Block]1103switch object[arrayPos0].state1104case GASBREAKBLOCK_BLOCKS1105temp0 = object.yvel1106BoxCollisionTest(C_SOLID, arrayPos0, -16, -16, 16, 16, object.entityPos, -14, -14, 14, 14)1107object.yvel = temp01108if checkResult == COL_TOP1109object.gravity = GRAVITY_AIR1110temp0 = 01111temp1 = 01112while temp0 < 161113CreateTempObject(TypeName[Gas Break Block], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)1114GetTableValue(object[tempObjectPos].frame, temp0, GasBreakBlock_blockFrames)1115GetTableValue(temp2, temp1, GasBreakBlock_blockOffsets)1116GetTableValue(object[tempObjectPos].xvel, temp1, GasBreakBlock_blockVelocities)1117temp1++1118GetTableValue(temp3, temp1, GasBreakBlock_blockOffsets)1119GetTableValue(object[tempObjectPos].yvel, temp1, GasBreakBlock_blockVelocities)1120temp1++1121object[tempObjectPos].xpos += temp21122object[tempObjectPos].ypos += temp31123object[tempObjectPos].state = GASBREAKBLOCK_DEBRIS1124object[tempObjectPos].drawOrder = 51125temp0++1126loop1127object[arrayPos0].state++1128if object[arrayPos0].priority != PRIORITY_XBOUNDS_DESTROY1129object[arrayPos0].priority = PRIORITY_ACTIVE1130end if1131PlaySfx(SfxName[Block Break], false)1132end if1133break11341135case GASBREAKBLOCK_LAUNCHER1136if object.state == CHECKEREDBALL_NORMAL1137BoxCollisionTest(C_TOUCH, arrayPos0, -8, -4, 8, 4, object.entityPos, -10, -14, 10, 14)1138if checkResult == true1139object.state = CHECKEREDBALL_LAUNCHED1140object.xpos = object[arrayPos0].xpos1141object.ypos = object[arrayPos0].ypos1142if object[arrayPos0].propertyValue == 01143object.xvel = 01144object.yvel = -0x800001145else1146object.xvel = 0x800001147object.yvel = 01148end if1149PlaySfx(SfxName[Rolling], false)1150end if1151end if1152break11531154end switch // object[arrayPos0].state1155break11561157case TypeName[Animal Prison]1158animalPrison[arrayPos0].buttonPos = object[arrayPos0].ypos1159animalPrison[arrayPos0].buttonPos -= 0x3000001160temp2 = animalPrison[arrayPos0].buttonPos1161temp2 += 0x800001162BoxCollisionTest(C_SOLID, arrayPos0, -32, -24, 32, 32, object.entityPos, -10, -14, 10, 14)1163BoxCollisionTest(C_SOLID, arrayPos0, -16, -40, 16, -24, object.entityPos, -10, -14, 10, 14)1164if object[arrayPos0].state == ANIMALPRISON_AWAITOPEN1165if checkResult == COL_TOP1166object[arrayPos0].state = ANIMALPRISON_OPENING1167stage.timeEnabled = false1168if Player_superState == SUPERSTATE_SUPER1169Player_superState = SUPERSTATE_FADEOUT1170end if1171object[arrayPos0].xvel = 0x800001172object[arrayPos0].yvel = -0x400001173animalPrison[arrayPos0].lockPos.x = object[arrayPos0].xpos1174animalPrison[arrayPos0].lockPos.y = object[arrayPos0].ypos1175CreateTempObject(TypeName[Smoke Puff], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)1176object[tempObjectPos].ypos -= 0x1800001177PlaySfx(SfxName[Destroy], false)1178end if1179end if11801181BoxCollisionTest(C_TOUCH, arrayPos0, -15, -48, 15, -24, object.entityPos, -10, -14, 10, 14)1182if checkResult == true1183temp0 = object.collisionBottom1184temp0 <<= 161185temp0 += object.ypos1186if temp0 > animalPrison[arrayPos0].buttonPos1187if temp0 <= temp21188animalPrison[arrayPos0].buttonPos = temp01189end if1190end if1191end if1192break11931194end switch1195next11961197if object.parent != 01198arrayPos0 = object.parent1199if object[arrayPos0].state == BALLCANNON_EXITED1200if ballCannon[arrayPos0].lastCannon == true1201object.state = CHECKEREDBALL_NORMAL1202object.gravity = GRAVITY_AIR1203object.tileCollisions = true1204end if1205object.visible = true1206object.unused = 01207object.speed = object[arrayPos0].xvel1208object.xvel = object[arrayPos0].xvel1209object.yvel = object[arrayPos0].yvel1210end if1211end if12121213temp1 = object.xpos1214temp1 >>= 161215temp2 = object.ypos1216temp2 >>= 161217temp2 += 61218Get16x16TileInfo(temp0, temp1, temp2, TILEINFO_ANGLEB)1219switch temp01220default1221case TILE_NORMAL1222break12231224case TILE_OILPOOL1225if object.yvel > -11226object.gravity = GRAVITY_GROUND1227object.yvel = 01228object.ypos += 0x100001229end if1230temp0 = object.speed1231temp0 >>= 51232object.speed -= temp01233break12341235case TILE_OILSTRIP1236break12371238case TILE_OILSLIDE1239break12401241end switch12421243if object.state == CHECKEREDBALL_NORMAL1244CallFunction(CheckeredBall_PlayerInteraction)1245temp0 = object.collisionOffset.x1246temp0 |= object.collisionOffset.y1247if temp0 != 01248foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)1249BoxCollisionTest(C_TOUCH, object.entityPos, -2, -2, 2, 2, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)1250if checkResult == false1251BoxCollisionTest(C_SOLID, object.entityPos, -14, -14, 14, 14, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)1252if checkResult == COL_TOP1253player[currentPlayer].xpos += object.collisionOffset.x1254player[currentPlayer].ypos += object.collisionOffset.y1255end if1256end if1257next12581259object.xpos += object.collisionOffset.x1260object.ypos += object.collisionOffset.y1261object.collisionOffset.x = 01262object.collisionOffset.y = 01263end if1264end if12651266if object.outOfBounds == true1267temp0 = object.xpos1268temp1 = object.ypos1269object.xpos = object.startPos.x1270object.ypos = object.startPos.y1271if object.outOfBounds == true1272object.roundedPos.x = object.xpos1273object.roundedPos.y = object.ypos1274object.xvel = 01275object.yvel = 01276object.speed = 01277object.badnikBonus = 01278object.groundAngle = 01279object.activePlayers = 01280object.ballAngle = 01281object.angleVel = 01282object.playerControlled = false1283object.priority = PRIORITY_BOUNDS1284object.state = 01285else1286object.xpos = temp01287object.ypos = temp11288end if1289end if12901291object.roundedPos.x = object.xpos1292object.roundedPos.x &= 0xFFFF00001293object.roundedPos.y = object.ypos1294object.roundedPos.y &= 0xFFFF00001295end event129612971298event ObjectDraw1299// Draw the ball frame1300object.rotation = object.ballAngle1301object.rotation >>= 141302temp0 = object.rotation1303temp0 += 81304temp0 >>= 41305temp0 &= 71306temp0++1307DrawSprite(temp0)13081309// And draw the shine ontop of it too1310object.inkEffect = 31311object.alpha = 0xA01312DrawSpriteFX(0, FX_INK, object.xpos, object.ypos)1313end event131413151316event ObjectStartup1317LoadSpriteSheet("OOZ/Objects.gif")13181319// Checkered Ball Frames1320SpriteFrame(-16, -16, 32, 32, 396, 190)1321SpriteFrame(-16, -16, 32, 32, 429, 190)1322SpriteFrame(-16, -16, 32, 32, 273, 133)1323SpriteFrame(-16, -16, 32, 32, 322, 100)1324SpriteFrame(-16, -16, 32, 32, 289, 100)1325SpriteFrame(-16, -16, 32, 32, 256, 100)1326SpriteFrame(-16, -16, 32, 32, 256, 67)1327SpriteFrame(-16, -16, 32, 32, 256, 34)1328SpriteFrame(-16, -16, 32, 32, 256, 1)13291330// Load the animation file... but why?1331// Nothing's ever really done with it...1332LoadAnimation("WreckingBallJr.ani")13331334// Setup all Checkered Ball objects in the level1335// Do note though that, at least in the normal game, this never really does anything since there aren't any Checkered Ball objects placed in the level1336foreach (TypeName[Checkered Ball], arrayPos0, ALL_ENTITIES)1337object[arrayPos0].gravity = GRAVITY_AIR1338object[arrayPos0].startPos.x = object.xpos1339object[arrayPos0].startPos.y = object.ypos1340next13411342// Add this object to the debug object list1343SetTableValue(TypeName[Checkered Ball], DebugMode_ObjCount, DebugMode_TypesTable)1344SetTableValue(CheckeredBall_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)1345SetTableValue(CheckeredBall_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)1346DebugMode_ObjCount++1347end event134813491350// ========================1351// Editor Events1352// ========================13531354event RSDKDraw1355DrawSprite(0)13561357object.inkEffect = INK_ADD1358object.alpha = 0xA01359DrawSpriteFX(1, FX_INK, object.xpos, object.ypos)1360end event136113621363event RSDKLoad1364LoadSpriteSheet("OOZ/Objects.gif")1365SpriteFrame(-16, -16, 32, 32, 429, 190)1366SpriteFrame(-16, -16, 32, 32, 396, 190)13671368SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")1369end event137013711372