Path: blob/master/Sonic 2/Scripts/Players/Player2Object.txt
1479 views
// ----------------------------------1// RSDK Project: Sonic 22// Script Description: Player 2 Object Object3// Script Author: Christian Whitehead/Simon Thomley4// Unpacked by Rubberduckycooly's script unpacker5// ----------------------------------67// ========================8// Aliases9// ========================1011private alias object.type : player.type12private alias object.groupID : player.groupID13private alias object.entityPos : player.entityPos14private alias object.state : player.state15private alias object.visible : player.visible16private alias object.propertyValue : player.character17private alias object.priority : player.priority18private alias object.xpos : player.xpos19private alias object.ypos : player.ypos20private alias object.ixpos : player.ixpos21private alias object.iypos : player.iypos22private alias object.lookPosY : player.lookPosY23private alias object.xvel : player.xvel24private alias object.yvel : player.yvel25private alias object.speed : player.speed26private alias object.rotation : player.rotation27private alias object.angle : player.angle28private alias object.direction : player.direction29private alias object.gravity : player.gravity30private alias object.frame : player.frame31private alias object.animation : player.animation32private alias object.prevAnimation : player.prevAnimation33private alias object.animationSpeed : player.animationSpeed34private alias object.animationTimer : player.animationTimer35private alias object.drawOrder : player.drawOrder36private alias object.controlLock : player.controlLock37private alias object.controlMode : player.controlMode38private alias object.interaction : player.interaction39private alias object.collisionPlane : player.collisionPlane40private alias object.tileCollisions : player.tileCollisions41private alias object.outOfBounds : player.outOfBounds4243private alias object.jumpPress : player.jumpPress44private alias object.jumpHold : player.jumpHold45private alias object.up : player.up46private alias object.down : player.down47private alias object.left : player.left48private alias object.right : player.right4950private alias object.value1 : player.timer51private alias object.value3 : player.drownTimer // Countdown before player moves to next drown "level"52private alias object.value4 : player.drownLevel53private alias object.value6 : player.speedShoesTimer54private alias object.value7 : player.invincibleTimer55private alias object.value8 : player.blinkTimer56private alias object.value11 : player.scrollDelay // A timer of how long the camera will stay locked for57private alias object.value12 : player.tailFrame58private alias object.value13 : player.tailAnim59private alias object.value16 : player.isSidekick // 0/false is player 1, 1/true if player 260private alias object.value18 : player.sortedDrawOrder61private alias object.value19 : player.badnikBonus62private alias object.value25 : player.gravityStrength // Also used in underwater checks , 0x1000 if underwater, otherwise 0x3800. Not to be confused with player.gravity63private alias object.value26 : player.flightVelocity64private alias object.value30 : player.jumpOffset65private alias object.value31 : player.rollingDeceleration // Passive rolling deceleration - Without the player holding the opposite direction66private alias object.value32 : player.jumpAbility // Used to store whatever function this player has for its jump ability67private alias object.value33 : player.spindashFunction // Used to store whatever function this player has for its spindash ability68private alias object.value34 : player.collisionDisabled69private alias object.value40 : player.hitboxLeft70private alias object.value38 : player.hitboxTop71private alias object.value41 : player.hitboxRight72private alias object.value39 : player.hitboxBottom73private alias object.value42 : player.prevGravity74private alias object.value43 : player.jumpInTimer75private alias object.value44 : player.p2InputFunction76private alias object.value45 : player.autoJumpTimer77private alias object.value46 : player.targetLeaderPos.x78private alias object.value47 : player.targetLeaderPos.y7980// Draw Order Aliases81private alias -1 : DRAWORDER_PLAYER8283// Tracks84private alias 0 : TRACK_STAGE85private alias 2 : TRACK_INVINCIBLE86private alias 5 : TRACK_GAMEOVER87private alias 7 : TRACK_SUPER8889// Reserved Object Slots90private alias 0 : SLOT_PLAYER191private alias 1 : SLOT_PLAYER2929394// ========================95// Function Declarations96// ========================9798reserve function Player2_GetDelayedInput99reserve function Player2_Input_GamepadAssist100reserve function Player2_Input_AI_Follow101reserve function Player2_Input_AI_SpindashPt1102reserve function Player2_Input_AI_SpindashPt2103reserve function Player2_State_FlyToPlayer104reserve function Player2_HandleSidekickRespawn105reserve function Player_ProcessUpdateP2106reserve function Player2_Input_None107reserve function Player2_Action_DblJumpTailsAI108reserve function Player_ProcessUpdateP2_VS109110111// ========================112// Static Values113// ========================114115public value Player2Object_stateUp = 0;116public value Player2Object_stateDown = 0;117public value Player2Object_stateLeft = 0;118public value Player2Object_stateRight = 0;119public value Player2Object_stateJumpPress = 0;120public value Player2Object_stateJumpHold = 0;121public value Player2Object_nextLeaderPosID = 0;122public value Player2Object_lastLeaderPosID = 0;123124125// ========================126// Tables127// ========================128129public table Player2Object_leaderPosBufferX[16]130public table Player2Object_leaderPosBufferY[16]131132133// ========================134// Function Definitions135// ========================136137public function Player2_Input_None138temp0 = 0139end function140141142public function Player2_Action_DblJumpTailsAI143CheckNotEqual(player.p2InputFunction, Player2_Input_None)144temp0 = checkResult145#platform: USE_ORIGINS146CheckNotEqual(player.p2InputFunction, Player2_Input_GamepadAssist)147temp0 &= checkResult148#endplatform149CheckNotEqual(player.up, true)150temp0 &= checkResult151if temp0 == false152CallFunction(Player_Action_DblJumpTails)153end if154end function155156157public function Player2_GetDelayedInput158if player.controlMode > CONTROLMODE_NONE159Player2Object_stateUp <<= 1160Player2Object_stateUp |= player[SLOT_PLAYER1].up161Player2Object_stateUp &= 0xFFFF162163Player2Object_stateDown <<= 1164Player2Object_stateDown |= player[SLOT_PLAYER1].down165Player2Object_stateDown &= 0xFFFF166167Player2Object_stateLeft <<= 1168Player2Object_stateLeft |= player[SLOT_PLAYER1].left169Player2Object_stateLeft &= 0xFFFF170171Player2Object_stateRight <<= 1172Player2Object_stateRight |= player[SLOT_PLAYER1].right173Player2Object_stateRight &= 0xFFFF174175Player2Object_stateJumpPress <<= 1176Player2Object_stateJumpPress |= player[SLOT_PLAYER1].jumpPress177Player2Object_stateJumpPress &= 0xFFFF178179Player2Object_stateJumpHold <<= 1180Player2Object_stateJumpHold |= player[SLOT_PLAYER1].jumpHold181Player2Object_stateJumpHold &= 0xFFFF182183if player[SLOT_PLAYER1].state == Player_State_Carried184Player2Object_stateDown <<= 15185Player2Object_stateLeft <<= 15186Player2Object_stateRight <<= 15187Player2Object_stateJumpPress <<= 15188Player2Object_stateJumpHold <<= 15189end if190191temp0 = Player2Object_stateUp192temp0 >>= 15193player.up = temp0194195temp0 = Player2Object_stateDown196temp0 >>= 15197player.down = temp0198199temp0 = Player2Object_stateLeft200temp0 >>= 15201player.left = temp0202203temp0 = Player2Object_stateRight204temp0 >>= 15205player.right = temp0206207temp0 = Player2Object_stateJumpPress208temp0 >>= 15209player.jumpPress = temp0210211temp0 = Player2Object_stateJumpHold212temp0 >>= 15213player.jumpHold = temp0214else215Player2Object_stateUp = 0216Player2Object_stateDown = 0217Player2Object_stateLeft = 0218Player2Object_stateRight = 0219Player2Object_stateJumpPress = 0220Player2Object_stateJumpHold = 0221end if222223if player[SLOT_PLAYER1].state != Player_State_Death224if player[SLOT_PLAYER1].type != TypeName[Death Event]225SetTableValue(player[SLOT_PLAYER1].xpos, Player2Object_lastLeaderPosID, Player2Object_leaderPosBufferX)226SetTableValue(player[SLOT_PLAYER1].ypos, Player2Object_lastLeaderPosID, Player2Object_leaderPosBufferY)227228Player2Object_lastLeaderPosID++229Player2Object_lastLeaderPosID &= 15230Player2Object_nextLeaderPosID++231Player2Object_nextLeaderPosID &= 15232CheckEqual(player[SLOT_PLAYER1].gravity, GRAVITY_AIR)233temp0 = checkResult234CheckEqual(player[SLOT_PLAYER1].prevGravity, GRAVITY_GROUND)235temp0 &= checkResult236237if temp0 == false238GetTableValue(player.targetLeaderPos.x, Player2Object_nextLeaderPosID, Player2Object_leaderPosBufferX)239GetTableValue(player.targetLeaderPos.y, Player2Object_nextLeaderPosID, Player2Object_leaderPosBufferY)240else241player.targetLeaderPos.x = player[SLOT_PLAYER1].xpos242player.targetLeaderPos.y = player[SLOT_PLAYER1].ypos243end if244else245temp0 = Player2Object_lastLeaderPosID246temp0--247if temp0 < 0248temp0 += 16249end if250251GetTableValue(player.targetLeaderPos.x, temp0, Player2Object_leaderPosBufferX)252GetTableValue(player.targetLeaderPos.y, temp0, Player2Object_leaderPosBufferY)253end if254else255temp0 = Player2Object_lastLeaderPosID256temp0--257if temp0 < 0258temp0 += 16259end if260261GetTableValue(player.targetLeaderPos.x, temp0, Player2Object_leaderPosBufferX)262GetTableValue(player.targetLeaderPos.y, temp0, Player2Object_leaderPosBufferY)263end if264end function265266267public function Player2_Input_GamepadAssist268#platform: USE_ORIGINS269IsInputSlotAssigned(2)270if checkResult == false271player.p2InputFunction = Player2_Input_AI_Follow272AssignInputSlotToDevice(2, -1)273return274end if275276ProcessObjectControl()277278temp0 = player.up279temp0 |= player.down280temp0 |= player.left281temp0 |= player.right282temp0 |= player.jumpHold283if temp0 == false284player.autoJumpTimer++285if player.autoJumpTimer >= 600286player.p2InputFunction = Player2_Input_AI_Follow287AssignInputSlotToDevice(2, -1)288end if289else290player.autoJumpTimer = 0291end if292#endplatform293end function294295296public function Player2_Input_AI_Follow297CallFunction(Player2_GetDelayedInput)298if player[SLOT_PLAYER1].type == TypeName[Player Object]299temp0 = player.angle300temp0 += 0x10301temp0 &= 0xE0302if temp0 == 0303if player.left == true304temp0 = player[SLOT_PLAYER1].xpos305temp0 -= 0x80000306if player.xpos < temp0307if player.xvel <= 0308player.left = false309end if310end if311end if312313if player.right == true314temp0 = player[SLOT_PLAYER1].xpos315temp0 += 0x80000316if player.xpos > temp0317if player.yvel <= 0318player.right = false319end if320end if321end if322end if323324if player[SLOT_PLAYER1].state != Player_State_Carried325temp0 = player.targetLeaderPos.x326temp1 = player[SLOT_PLAYER1].gravity327temp1 |= player[SLOT_PLAYER1].prevGravity328329if temp1 == GRAVITY_GROUND330if player[SLOT_PLAYER1].speed < 0x20000331if player[SLOT_PLAYER1].speed > -0x20000332if player[SLOT_PLAYER1].direction == 0333temp0 -= 0x200000334else335temp0 += 0x200000336end if337end if338end if339end if340temp0 -= player.xpos341342if temp0 != 0343if temp0 < 0344if temp0 <= -0x300000345player.right = false346player.left = true347end if348349if player.speed != 0350if player.direction == FACING_LEFT351Cos256(temp1, player.angle)352temp1 *= 0xC0353player.xpos -= temp1354end if355end if356else357if temp0 >= 0x300000358player.left = false359player.right = true360end if361362if player.speed != 0363if player.direction == FACING_RIGHT364Cos256(temp1, player.angle)365temp1 *= 0xC0366player.xpos += temp1367end if368end if369end if370end if371372if player.animation == ANI_PUSHING373player.autoJumpTimer++374if player[SLOT_PLAYER1].direction == player.direction375if player[SLOT_PLAYER1].animation == ANI_PUSHING376player.autoJumpTimer = 0377end if378end if379380if player.autoJumpTimer >= 30381if player.gravity == GRAVITY_GROUND382CallFunction(Player_Action_Jump)383end if384player.timer = 0385player.autoJumpTimer = 0386end if387else388temp0 = player.ypos389temp0 -= player.targetLeaderPos.y390if temp0 > 0x200000391player.autoJumpTimer++392if player.autoJumpTimer >= 64393if player.gravity == GRAVITY_GROUND394CallFunction(Player_Action_Jump)395end if396player.timer = 0397player.autoJumpTimer = 0398end if399else400player.autoJumpTimer = 0401end if402end if403404if player.controlLock > 0405if player.speed < 0x8000406if player.speed > -0x8000407player.p2InputFunction = Player2_Input_AI_SpindashPt1408end if409end if410end if411end if412end if413414#platform: USE_ORIGINS415if game.playMode != BOOT_PLAYMODE_MISSION416temp0 = keyDown[2].up417temp0 |= keyDown[2].down418temp0 |= keyDown[2].left419temp0 |= keyDown[2].right420temp0 |= keyDown[2].buttonA421temp0 |= keyDown[2].buttonB422temp0 |= keyDown[2].buttonC423if temp0 == true424player.autoJumpTimer = 0425player.p2InputFunction = Player2_Input_GamepadAssist426end if427end if428#endplatform429end function430431432public function Player2_Input_AI_SpindashPt1433player.up = false434player.down = false435player.left = false436player.right = false437player.jumpPress = false438player.jumpHold = false439440if player.controlLock == 0441if player.gravity == GRAVITY_GROUND442if player.speed < 0x4000443if player.speed > -0x4000444player.p2InputFunction = Player2_Input_AI_SpindashPt2445player.autoJumpTimer = 1446447if player.animation != ANI_SPINDASH448if player.xpos < player.targetLeaderPos.x449player.direction = FACING_RIGHT450else451player.direction = FACING_LEFT452end if453player.down = true454end if455end if456end if457end if458end if459end function460461462public function Player2_Input_AI_SpindashPt2463if player.autoJumpTimer < 64464player.down = true465temp0 = player.autoJumpTimer466temp0 &= 15467if temp0 == 0468player.jumpPress = true469else470player.jumpPress = false471end if472473player.autoJumpTimer++474else475player.autoJumpTimer = 0476player.down = false477player.jumpPress = false478player.p2InputFunction = Player2_Input_AI_Follow479end if480end function481482483public function Player2_State_FlyToPlayer484CallFunction(Player2_GetDelayedInput)485486if player.gravityStrength == 0x3800487player.animation = ANI_FLYING488else489player.animation = ANI_SWIMMING490end if491492temp0 = player.targetLeaderPos.x493temp0 -= player.xpos494temp1 = temp0495temp0 >>= 4496497if player.xpos < player.targetLeaderPos.x498player.direction = FACING_RIGHT499if temp0 > 0xC0000500temp0 = 0xC0000501end if502503if player[SLOT_PLAYER1].xvel > 0504temp0 += player[SLOT_PLAYER1].xvel505end if506507temp0 += 0x10000508if temp0 > temp1509temp0 = temp1510temp1 = 0511end if512else513player.direction = FACING_LEFT514if temp0 < -0xC0000515temp0 = -0xC0000516end if517518if player[SLOT_PLAYER1].xvel < 0519temp0 += player[SLOT_PLAYER1].xvel520end if521522temp0 -= 0x10000523if temp0 < temp1524temp0 = temp1525temp1 = 0526end if527end if528529player.xpos += temp0530if player.ypos < player.targetLeaderPos.y531player.ypos += 0x10000532end if533534if player.ypos > player.targetLeaderPos.y535player.ypos -= 0x10000536end if537538if player[SLOT_PLAYER1].type != TypeName[Death Event]539if player[SLOT_PLAYER1].state != Player_State_Death540if player[SLOT_PLAYER1].state != Player_State_Drown541if player[SLOT_PLAYER1].state != Player_State_TubeRoll542if temp1 == 0543temp0 = player.targetLeaderPos.y544temp0 -= player.ypos545if temp0 < 0546FlipSign(temp0)547end if548549if temp0 < 0x20000550#platform: USE_STANDALONE551player.state = Player_State_Air552#endplatform553#platform: USE_ORIGINS554player.state = Player_State_Air_NoDropDash555#endplatform556player.animation = ANI_JUMPING557player.gravity = GRAVITY_AIR558player.tileCollisions = true559player.interaction = true560player.controlMode = CONTROLMODE_P2561player.controlLock = 0562player.angle = 0563player.p2InputFunction = Player2_Input_AI_Follow564player.collisionPlane = player[SLOT_PLAYER1].collisionPlane565#platform: USE_ORIGINS566player.sortedDrawOrder = player[SLOT_PLAYER1].sortedDrawOrder567#endplatform568569Player2Object_stateUp = 0570Player2Object_stateDown = 0571Player2Object_stateLeft = 0572Player2Object_stateRight = 0573Player2Object_stateJumpPress = 0574Player2Object_stateJumpHold = 0575end if576end if577end if578end if579end if580end if581end function582583584public function Player2_HandleSidekickRespawn585if player[SLOT_PLAYER1].type == TypeName[Player Object]586if player.outOfBounds == true587player.jumpInTimer++588else589player.jumpInTimer = 0590end if591592if player.jumpInTimer >= 240593player.jumpInTimer = 0594player.state = Player2_State_FlyToPlayer595player.xpos = player[SLOT_PLAYER1].xpos596player.ypos = screen.yoffset597player.ypos -= 128598player.ypos <<= 16599player.xvel = 0600player.yvel = 0601player.speed = 0602player.tileCollisions = false603player.interaction = false604player.controlMode = CONTROLMODE_P2605#platform: USE_STANDALONE606player.sortedDrawOrder = 4607#endplatform608#platform: USE_ORIGINS609player.sortedDrawOrder = player[SLOT_PLAYER1].sortedDrawOrder610#endplatform611player.drownTimer = 0612player.drownLevel = 0613end if614615CheckEqual(player[SLOT_PLAYER1].state, Player_State_Death)616temp0 = checkResult617CheckEqual(player[SLOT_PLAYER1].type, TypeName[Death Event])618temp0 |= checkResult619CheckNotEqual(player.state, Player_State_Hurt)620temp0 &= checkResult621CheckNotEqual(player.state, Player_State_Death)622temp0 &= checkResult623if temp0 == true624player.jumpInTimer = 0625player.state = Player2_State_FlyToPlayer626player.xvel = 0627player.yvel = 0628player.speed = 0629player.tileCollisions = false630player.interaction = false631end if632end if633end function634635636public function Player_ProcessUpdateP2637if player.state == Player_State_Death638player.p2InputFunction = Player2_Input_None639end if640641if player.state == Player_State_Drown642player.p2InputFunction = Player2_Input_None643end if644645CallFunction(player.p2InputFunction)646647if player.state != Player_State_Hurt648if player.blinkTimer > 0649player.blinkTimer--650651GetBit(temp0, player.blinkTimer, 2)652if temp0 == true653player.visible = false654else655player.visible = true656end if657end if658end if659660if player.invincibleTimer > 0661if player.state != Player_State_Hurt662if player.invincibleTimer > 2000663player.invincibleTimer = 120664player.blinkTimer = 3665end if666end if667668player.invincibleTimer--669if player.invincibleTimer == 0670player.blinkTimer = 0671player.visible = true672end if673end if674675if player.state != Player_State_LookUp676if player.state != Player_State_Crouch677if player.lookPosY > 0678player.lookPosY -= 2679end if680681if player.lookPosY < 0682player.lookPosY += 2683end if684end if685end if686687if player.state != Player_State_Fly688if player.flightVelocity != 0689StopSfx(SfxName[Flying])690StopSfx(SfxName[Tired])691player.flightVelocity = 0692end if693end if694end function695696697public function Player_ProcessUpdateP2_VS698#platform: USE_STANDALONE699CallNativeFunction2(ReceiveEntity, player.entityPos, true)700player.type = TypeName[Player 2 Object]701#endplatform702703#platform: USE_ORIGINS704ProcessObjectControl()705#endplatform706707if player.speedShoesTimer > 0708player.speedShoesTimer--709if player.speedShoesTimer < 1710currentPlayer = player.entityPos711CallFunction(Player_UpdatePhysicsState)712713temp0 = false714foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)715temp0 += player[currentPlayer].speedShoesTimer716next717718if temp0 == false719if SlowDownMusic != 0720CallFunction(SlowDownMusic)721end if722end if723724player.speedShoesTimer = 0725end if726end if727728if player.state != Player_State_Hurt729if player.blinkTimer > 0730player.blinkTimer--731GetBit(temp0, player.blinkTimer, 2)732if temp0 == true733player.visible = false734else735player.visible = true736end if737end if738end if739740if player.invincibleTimer > 0741player.invincibleTimer--742if player.invincibleTimer == 0743temp0 = false744foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)745temp0 += player[currentPlayer].invincibleTimer746next747748if temp0 == false749if music.currentTrack == TRACK_INVINCIBLE750PlayMusic(TRACK_STAGE)751end if752end if753754if object[+playerCount].type == invincibilityType755currentPlayer = player.entityPos756arrayPos0 = currentPlayer757arrayPos0 += playerCount758CallFunction(Player_ApplyShield)759end if760end if761end if762763if player.state != Player_State_LookUp764if player.state != Player_State_Crouch765if player.lookPosY > 0766player.lookPosY -= 2767end if768769if player.lookPosY < 0770player.lookPosY += 2771end if772end if773end if774775if player.scrollDelay > 0776player.scrollDelay--777if player.scrollDelay == 0778if player.entityPos == camera[1].target779camera[1].style = CAMERASTYLE_FOLLOW780end if781end if782end if783784if player.state != Player_State_Fly785if player.flightVelocity != 0786StopSfx(SfxName[Flying])787StopSfx(SfxName[Tired])788player.flightVelocity = 0789end if790end if791end function792793794// ========================795// Events796// ========================797798event ObjectUpdate799if options.vsMode == false800CallFunction(Player_ProcessUpdateP2)801CallFunction(player.state)802ProcessAnimation()803804CallFunction(TailsObject_ProcessTailSprite)805else806CallFunction(Player_ProcessUpdateP2_VS)807CallFunction(player.state)808809// Bug Details:810// -> In the main Player Object script, the Drop Dash "animation" code in Origins would normally be here811// However, they had forgot to copy it over here too812// -> Because of that, using the Drop Dash as P2 Sonic in 2PVS means he doesn't always look quite right...813814ProcessAnimation()815816if player.character == PLAYER_TAILS_A817CallFunction(TailsObject_ProcessTailSprite)818end if819end if820821// Bug Details:822// The code to set the jump ability state to 0 when you're on the ground isn't here823// This means when P2 jumps and lands without using their ability, their ability state is stored,824// allowing them to roll off of a ledge and use their ability out of it, which isn't intended825826if player.entityPos == camera[1].target827if player.animation == ANI_JUMPING828camera[1].adjustY = player.jumpOffset829else830if camera[1].adjustY == player.jumpOffset831camera[1].adjustY = 0832player.iypos += player.jumpOffset833end if834end if835end if836837if player.collisionDisabled == false838temp0 = player.prevGravity839player.prevGravity = player.gravity840ProcessObjectMovement()841player.prevGravity ^= GRAVITY_AIR842CheckEqual(player.gravity, GRAVITY_GROUND)843player.prevGravity |= checkResult844player.prevGravity ^= GRAVITY_AIR845846if temp0 == GRAVITY_AIR847if player.prevGravity == GRAVITY_GROUND848player.badnikBonus = 0849if player.animation == ANI_JUMPING850if player.down == false851if player.state != Player_State_Roll852if player.state != Player_State_TubeRoll853player.animation = ANI_WALKING854if player.entityPos == camera[1].target855camera[1].adjustY = 0856end if857858player.iypos += player.jumpOffset859end if860end if861end if862end if863end if864end if865else866player.collisionDisabled = false867end if868869if options.vsMode == false870CallFunction(Player2_HandleSidekickRespawn)871end if872873// Bug Details:874// Amy's hitbox handling function doesn't get called here, so P2 Amy never gets the extended hammer hitbox...875end event876877878event ObjectDraw879if player.animation != player.prevAnimation880player.prevAnimation = player.animation881player.frame = 0882player.animationTimer = 0883player.animationSpeed = 0884end if885886if player.character == PLAYER_TAILS_A887if player.tailAnim != player.animation888if player.animation > ANI_LOOKINGDOWN889player.tailFrame = 0890end if891892if player.tailAnim > ANI_LOOKINGDOWN893player.tailFrame = 0894end if895896player.tailAnim = player.animation897end if898899// Draw the Tails part of Tails900switch player.tailAnim901case 0 // ANI_STOPPED902if player.frame == 0903temp0 = player.tailFrame904temp0 >>= 3905if player.visible == true906DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)907end if908end if909break910911case 1 // ANI_WAITING912case 3 // ANI_LOOKINGUP913case 4 // ANI_LOOKINGDOWN914case 21 // ANI_HANGING915case 36 // ANI_CONTINUE916case 37 // ANI_CONTINUE_UP917temp0 = player.tailFrame918temp0 >>= 3919if player.visible == true920DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)921end if922break923924case 7 // ANI_SKIDDING925case 9 // ANI_SPINDASH926temp0 = player.tailFrame927temp0 >>= 2928temp0 += 11929if player.visible == true930DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)931end if932break933934case 10 // ANI_JUMPING935case 43 // Unknown, this was probably "SSRoll" in Sonic 1 before it got moved to its own ani file in that game936temp0 = player.tailFrame937temp0 >>= 2938CheckEqual(player.xvel, 0)939temp1 = checkResult940CheckEqual(player.yvel, 0)941temp1 &= checkResult942temp2 = player.rotation943if temp1 == false944ATan2(player.rotation, player.xvel, player.yvel)945player.rotation += 0x10946player.rotation &= 0xFF947player.rotation >>= 5948switch player.rotation949case 0950case 8951temp0 += 5952player.rotation = 0x00953break954955case 1956temp0 += 8957if player.direction == FACING_RIGHT958player.rotation = 0x40959else960player.rotation = 0x00961end if962break963964case 2965temp0 += 5966player.rotation = 0x40967break968969case 3970temp0 += 8971if player.direction == FACING_RIGHT972player.rotation = 0x80973else974player.rotation = 0x40975end if976break977978case 4979temp0 += 5980player.rotation = 0x80981break982983case 5984temp0 += 8985if player.direction == FACING_RIGHT986player.rotation = 0xC0987else988player.rotation = 0x80989end if990break991992case 6993temp0 += 5994player.rotation = 0xC0995break996997case 7998temp0 += 8999if player.direction == FACING_RIGHT1000player.rotation = 0x001001else1002player.rotation = 0xC01003end if1004break10051006end switch10071008if player.direction == FACING_LEFT1009player.rotation += 0x801010end if1011else1012temp0 += 51013player.rotation = 0x001014end if10151016player.rotation <<= 11017if player.visible == true1018DrawSpriteFX(temp0, FX_ROTATE, player.xpos, player.ypos)1019end if1020player.rotation = temp21021break10221023case 17 // ANI_PUSHING1024temp0 = player.tailFrame1025temp0 /= 101026temp0 += 111027if player.visible == true1028DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)1029end if1030break10311032end switch1033end if10341035DrawObjectAnimation()1036end event103710381039event ObjectStartup1040Player2Object_nextLeaderPosID = 11041Player2Object_lastLeaderPosID = 01042Player2Object_stateUp = 01043Player2Object_stateDown = 01044Player2Object_stateLeft = 01045Player2Object_stateRight = 01046Player2Object_stateJumpPress = 01047Player2Object_stateJumpHold = 010481049temp7 = false10501051if options.vsMode == true1052ResetObjectEntity(SLOT_PLAYER2, TypeName[Player 2 Object], 1, player[SLOT_PLAYER1].xpos, player[SLOT_PLAYER1].ypos)1053vs.restartX1 = player[SLOT_PLAYER1].xpos1054vs.restartY1 = player[SLOT_PLAYER1].ypos1055vs.restartX2 = player[SLOT_PLAYER1].xpos1056vs.restartY2 = player[SLOT_PLAYER1].ypos10571058player[SLOT_PLAYER2].groupID = GROUP_PLAYERS1059#platform: USE_STANDALONE1060player[SLOT_PLAYER2].state = Player_State_Air1061#endplatform1062#platform: USE_ORIGINS1063player[SLOT_PLAYER2].state = Player_State_Air_NoDropDash1064#endplatform1065player[SLOT_PLAYER2].priority = PRIORITY_ACTIVE1066#platform: USE_ORIGINS1067player[SLOT_PLAYER2].controlMode = CONTROLMODE_P21068#endplatform1069player[SLOT_PLAYER2].drawOrder = DRAWORDER_PLAYER1070player[SLOT_PLAYER2].sortedDrawOrder = 41071player[SLOT_PLAYER2].rollingDeceleration = 0x20001072player[SLOT_PLAYER2].spindashFunction = Player_Action_Spindash10731074currentPlayer = SLOT_PLAYER21075CallFunction(Player_UpdatePhysicsState)10761077player[SLOT_PLAYER2].hitboxTop = C_BOX1078player[SLOT_PLAYER2].hitboxBottom = C_BOX1079player[SLOT_PLAYER2].hitboxLeft = C_BOX1080player[SLOT_PLAYER2].hitboxRight = C_BOX10811082#platform: USE_ORIGINS1083camera[1].enabled = true1084camera[1].style = CAMERASTYLE_FOLLOW1085camera[1].target = SLOT_PLAYER21086camera[1].xpos = player[SLOT_PLAYER2].ixpos1087camera[1].ypos = player[SLOT_PLAYER2].iypos1088#endplatform10891090switch vs.player2Type1091case PLAYER_SONIC_A1092LoadAnimation("Sonic.ani")1093player[SLOT_PLAYER2].character = PLAYER_SONIC_A1094player[SLOT_PLAYER2].jumpOffset = -51095player[SLOT_PLAYER2].jumpAbility = Player_Action_DblJumpSonic1096ANI_PEELOUT = ANI_RUNNING1097break10981099case PLAYER_TAILS_A1100LoadAnimation("Tails.ani")1101player[SLOT_PLAYER2].character = PLAYER_TAILS_A1102player[SLOT_PLAYER2].jumpOffset = -11103player[SLOT_PLAYER2].jumpAbility = Player_Action_DblJumpTails1104stage.player2Enabled = false1105break11061107case PLAYER_KNUCKLES_A1108LoadAnimation("Knuckles.ani")1109player[SLOT_PLAYER2].character = PLAYER_KNUCKLES_A1110player[SLOT_PLAYER2].jumpOffset = -51111player[SLOT_PLAYER2].jumpAbility = Player_Action_DblJumpKnux1112ANI_PEELOUT = ANI_RUNNING1113break11141115#platform: USE_ORIGINS1116case PLAYER_AMY_A1117LoadAnimation("Amy.ani")1118player[SLOT_PLAYER2].character = PLAYER_AMY1119player[SLOT_PLAYER2].jumpOffset = -41120player[SLOT_PLAYER2].jumpAbility = Player_Action_DblJumpAmy1121ANI_PEELOUT = ANI_RUNNING1122break1123#endplatform1124end switch11251126stage.player2Enabled = false1127playerCount = 21128temp7 = true1129end if11301131if stage.player2Enabled == true1132ResetObjectEntity(SLOT_PLAYER2, TypeName[Player 2 Object], PLAYER_TAILS_A, player[SLOT_PLAYER1].xpos, player[SLOT_PLAYER1].ypos)1133if starPostID == 01134// If at a level's start, then make Tails be 16 pixels left of Sonic1135player[SLOT_PLAYER2].xpos -= 0x1000001136end if11371138LoadAnimation("Tails.ani")1139player[SLOT_PLAYER2].groupID = GROUP_PLAYERS1140player[SLOT_PLAYER2].character = PLAYER_TAILS_A // Small note - this is redundant to the ResetObjectEntity line as that already sets Tails's character, it doesn't matter too much though1141#platform: USE_STANDALONE1142player[SLOT_PLAYER2].state = Player_State_Air1143#endplatform1144#platform: USE_ORIGINS1145player[SLOT_PLAYER2].state = Player_State_Air_NoDropDash1146#endplatform1147player[SLOT_PLAYER2].priority = PRIORITY_ACTIVE1148#platform: USE_STANDALONE1149player[SLOT_PLAYER2].controlMode = CONTROLMODE_P11150#endplatform1151#platform: USE_ORIGINS1152player[SLOT_PLAYER2].controlMode = CONTROLMODE_P21153#endplatform1154player[SLOT_PLAYER2].drawOrder = DRAWORDER_PLAYER1155player[SLOT_PLAYER2].sortedDrawOrder = 411561157currentPlayer = SLOT_PLAYER21158CallFunction(Player_UpdatePhysicsState)11591160player[SLOT_PLAYER2].rollingDeceleration = 0x20001161player[SLOT_PLAYER2].jumpOffset = -11162player[SLOT_PLAYER2].isSidekick = true1163player[SLOT_PLAYER2].jumpAbility = Player2_Action_DblJumpTailsAI1164player[SLOT_PLAYER2].spindashFunction = Player_Action_Spindash11651166CheckCurrentStageFolder("Continue")1167if checkResult == true1168player[SLOT_PLAYER2].p2InputFunction = Player2_Input_None1169else1170player[SLOT_PLAYER2].p2InputFunction = Player2_Input_AI_Follow1171end if11721173temp0 = 01174while temp0 < 161175SetTableValue(player[SLOT_PLAYER1].xpos, temp0, Player2Object_leaderPosBufferX)1176SetTableValue(player[SLOT_PLAYER1].ypos, temp0, Player2Object_leaderPosBufferY)1177temp0++1178loop11791180player[SLOT_PLAYER2].hitboxTop = C_BOX1181player[SLOT_PLAYER2].hitboxBottom = C_BOX1182player[SLOT_PLAYER2].hitboxLeft = C_BOX1183player[SLOT_PLAYER2].hitboxRight = C_BOX11841185temp7 = true11861187#platform: USE_ORIGINS1188AssignInputSlotToDevice(2, -1)1189#endplatform1190end if11911192if temp7 == true1193LoadSpriteSheet("Players/Tails1.gif")1194SpriteFrame(-22, -8, 16, 24, 82, 199)1195SpriteFrame(-26, -8, 20, 24, 99, 199)1196SpriteFrame(-26, -8, 20, 24, 120, 199)1197SpriteFrame(-26, -8, 20, 24, 141, 199)1198SpriteFrame(-26, -8, 20, 24, 162, 199)1199SpriteFrame(-35, -8, 24, 16, 231, 166)1200SpriteFrame(-35, -8, 24, 16, 231, 183)1201SpriteFrame(-35, -8, 24, 16, 231, 200)1202SpriteFrame(-25, 9, 20, 16, 235, 217)1203SpriteFrame(-25, 9, 18, 16, 237, 234)1204SpriteFrame(-25, 9, 20, 16, 216, 234)1205SpriteFrame(-30, -6, 24, 16, 231, 166)1206SpriteFrame(-30, -6, 24, 16, 231, 183)1207SpriteFrame(-30, -6, 24, 16, 231, 200)1208end if1209end event121012111212// ========================1213// Editor Events1214// ========================12151216event RSDKDraw1217DrawSprite(0)1218end event121912201221event RSDKLoad1222LoadSpriteSheet("Players/Tails1.gif")1223SpriteFrame(-16, -12, 24, 32, 1, 1)12241225// used in-game, but shouldn't be set from the editor1226SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")1227end event122812291230