Path: blob/master/Sonic 1/Scripts/Players/PlayerObject.txt
1480 views
// ----------------------------------1// RSDK Project: Sonic 12// Script Description: Player Object Object3// Script Author: Christian Whitehead/Simon Thomley4// Unpacked by Rubberduckycooly's script unpacker5// ----------------------------------67// ========================8// Aliases9// ========================1011public alias 0x100 : GROUP_PLAYERS12public alias arrayPos6 : currentPlayer13public alias arrayPos7 : playerCount1415// Gravity16public alias 0 : GRAVITY_GROUND17public alias 1 : GRAVITY_AIR1819// Priority20public alias 0 : PRIORITY_BOUNDS21public alias 1 : PRIORITY_ACTIVE22public alias 2 : PRIORITY_ALWAYS23public alias 3 : PRIORITY_XBOUNDS24public alias 4 : PRIORITY_XBOUNDS_DESTROY25public alias 5 : PRIORITY_INACTIVE26public alias 6 : PRIORITY_BOUNDS_SMALL27public alias 7 : PRIORITY_ACTIVE_SMALL2829// Control Modes30public alias -1 : CONTROLMODE_NONE31public alias 0 : CONTROLMODE_P132public alias 1 : CONTROLMODE_P233public alias 2 : CONTROLMODE_P3 // Although unused by the game normally, RSDKv5U does have support for up to 4 players34public alias 3 : CONTROLMODE_P43536// Camera Styles37public alias 0 : CAMERASTYLE_FOLLOW38public alias 1 : CAMERASTYLE_EXTENDED39public alias 2 : CAMERASTYLE_EXTENDED_OFFSET_L40public alias 3 : CAMERASTYLE_EXTENDED_OFFSET_R41public alias 4 : CAMERASTYLE_HLOCKED4243// Ink Effects44public alias 0 : INK_NONE45public alias 1 : INK_BLEND46public alias 2 : INK_ALPHA47public alias 3 : INK_ADD48public alias 4 : INK_SUB4950// Flip Directions51public alias 0 : FLIP_NONE52public alias 1 : FLIP_X53public alias 2 : FLIP_Y54public alias 3 : FLIP_XY5556// Collision Sides57public alias 0 : CSIDE_FLOOR58public alias 1 : CSIDE_LWALL59public alias 2 : CSIDE_RWALL60public alias 3 : CSIDE_ROOF61public alias 4 : CSIDE_LENTITY // Origins only62public alias 5 : CSIDE_RENTITY // Origins only6364// Collision Modes65public alias 0 : CMODE_FLOOR66public alias 1 : CMODE_LWALL67public alias 2 : CMODE_ROOF68public alias 3 : CMODE_RWALL6970// Collision Directions71public alias 0 : COL_NONE72public alias 1 : COL_TOP73public alias 2 : COL_LEFT74public alias 3 : COL_RIGHT75public alias 4 : COL_BOTTOM7677// Reserved Object Slot Aliases78private alias 0 : SLOT_PLAYER179private alias 1 : SLOT_PLAYER280private alias 11 : SLOT_TITLECARD81private alias 30 : SLOT_ACTFINISH8283// Mode Aliases84private alias 2 : MODE_TIMEATTACK8586// Mission Number Aliases87private alias 8 : MISSIONNO_MERCY8889// Draw Order Aliases90private alias -1 : DRAWORDER_PLAYER9192// Tile Info ID Aliases93private alias 8 : TILEINFO_ANGLEB9495// Player List Pos Aliases96// The A at the end of each of these stands for Alias, Origins Plus introduced global variables for player slots but we need to support Standalone too97// Also switch cases don't support variables so we have to do this either way98public alias 0 : PLAYER_SONIC_A99public alias 1 : PLAYER_TAILS_A100public alias 2 : PLAYER_KNUCKLES_A101public alias 3 : PLAYER_SONIC_TAILS_A102public alias 4 : PLAYER_KNUCKLES_TAILS_A103public alias 5 : PLAYER_AMY_A104public alias 6 : PLAYER_AMY_TAILS_A105106// Shield Aliases107private alias 0 : SHIELD_NONE108private alias 1 : SHIELD_NORMAL109private alias 2 : SHIELD_BUBBLE110private alias 3 : SHIELD_FIRE111private alias 4 : SHIELD_LIGHTNING112private alias 5 : SHIELD_GOGGLES // LZ goggles, debug mode only113114private alias 0 : BUBBLESHIELD_IDLE_SETUP115private alias 2 : BUBBLESHIELD_BOUNCE_SETUP116private alias 4 : BUBBLESHIELD_RECOIL_SETUP117118private alias 0 : FIRESHIELD_IDLE_SETUP119private alias 2 : FIRESHIELD_DASH_SETUP120121// Shield Types Aliases122private alias 1 : SHIELDTYPE_S2123124// Super States125private alias 0 : SUPERSTATE_NONE126private alias 1 : SUPERSTATE_SUPER127private alias 2 : SUPERSTATE_UNTRANSFORM128private alias 3 : SUPERSTATE_END129130// Tracks131private alias 0 : TRACK_STAGE132private alias 1 : TRACK_ACTFINISH133private alias 2 : TRACK_INVINCIBLE134private alias 3 : TRACK_CONTINUE135private alias 4 : TRACK_BOSS136private alias 5 : TRACK_GAMEOVER137private alias 6 : TRACK_DROWNING138139// This isn't a global variable, so let's fake it here - it's an unused (and broken) animation, left over from Sonic Nexus140private alias 34 : ANI_CORKSCREW_V141142// Origins Stats Aliases143private alias StageStatsUsabilityParam1 : stageStat.badnikDestroyCount144private alias StageStatsUsabilityParam2 : stageStat.spindashDestroyCount145private alias StageStatsUsabilityParam3 : stageStat.motobugDestroyCount146147// We can't use TypeName aliases for stage objects in global objects, so a regular alias will have to do148private alias 58 : TYPE_MOTOBUG149150// Variables151private alias object.type : player.type152private alias object.groupID : player.groupID // Normally GROUP_PLAYERS, unless in Debug Mode153private alias object.entityPos : player.entityPos // Where the player is on the object list - P1 should be 0, P2 should be 1154private alias object.state : player.state155private alias object.visible : player.visible156private alias object.propertyValue : player.character // Individual character type of the object. See the "alone" Player List Pos aliases157private alias object.priority : player.priority158private alias object.xpos : player.xpos // In total world-space position (0x10000 == 1.0)159private alias object.ypos : player.ypos160private alias object.ixpos : player.ixpos // In screen space position (1 == 1)161private alias object.iypos : player.iypos162private alias object.lookPosX : player.lookPosX // Camera offset based on the player's position (X isn't used in this script, but kept here for refence)163private alias object.lookPosY : player.lookPosY164private alias object.xvel : player.xvel // Based on world-space165private alias object.yvel : player.yvel166private alias object.speed : player.speed // Also based on world-space167private alias object.rotation : player.rotation168private alias object.angle : player.angle169private alias object.direction : player.direction // Note: Because this is stored as a byte, it goes from 0-255, not 0-360!170private alias object.gravity : player.gravity // GRAVITY_GROUND or GRAVITY_AIR. Not to be confused with player.gravityStrength, see there for more info171private alias object.frame : player.frame172private alias object.animation : player.animation173private alias object.prevAnimation : player.prevAnimation174private alias object.animationSpeed : player.animationSpeed175private alias object.animationTimer : player.animationTimer176private alias object.drawOrder : player.drawOrder177private alias object.pushing : player.pushing178private alias object.controlLock : player.controlLock // Timer for how long control lock is active. Not to be confused with roll jump lock, see the Player_Action_Jump function for that179private alias object.controlMode : player.controlMode // See CONTROLMODE_* aliases180private alias object.interaction : player.interaction // Will the object interact with other objects?181private alias object.scrollTracking : player.scrollTracking // Determines if the camera will track the player's position or just follow it182private alias object.collisionMode : player.collisionMode183private alias object.collisionLeft : player.collisionLeft184private alias object.collisionTop : player.collisionTop185private alias object.collisionRight : player.collisionRight186private alias object.collisionBottom : player.collisionBottom187private alias object.collisionPlane : player.collisionPlane188private alias object.floorSensorC : player.floorSensorC189private alias object.floorSensorL : player.floorSensorL190private alias object.floorSensorR : player.floorSensorR191private alias object.floorSensorLC : player.floorSensorLC192private alias object.floorSensorRC : player.floorSensorRC193private alias object.tileCollisions : player.tileCollisions194195// *Object-wise* input, not to be confused with keyPress and keyDown196private alias object.jumpPress : player.jumpPress197private alias object.jumpHold : player.jumpHold198private alias object.up : player.up199private alias object.down : player.down200private alias object.left : player.left201private alias object.right : player.right202203// Object values204private alias object.value0 : player.rings205private alias object.value1 : player.timer206private alias object.value2 : player.abilityTimer207private alias object.value3 : player.drownTimer // Drowning values are progressed in the Water script, rather than here208private alias object.value4 : player.drownLevel209private alias object.value5 : player.rollAnimationSpeed210private alias object.value6 : player.speedShoesTimer211private alias object.value7 : player.invincibleTimer212private alias object.value8 : player.blinkTimer213private alias object.value9 : player.skidSpeed214private alias object.value10 : player.animationReserve // Used by springs to store what animation will play after the bounce animation215private alias object.value11 : player.scrollDelay // A timer of how long the camera will stay locked for, after a spindash216private alias object.value12 : player.tailFrame // One of Tails' tail values, not used by the player itself217private alias object.value13 : player.tailAnim // Also one of Tails' tail values218private alias object.value14 : player.skidding219// value15 is unused220private alias object.value16 : player.isSidekick // false if player 1, true if player 2221private alias object.value17 : debugMode.currentSelection222private alias object.value18 : player.sortedDrawOrder223private alias object.value19 : player.badnikBonus // How many enemies the player has bounced on in a row224private alias object.value20 : player.topSpeed225private alias object.value21 : player.acceleration226private alias object.value22 : player.deceleration227private alias object.value23 : player.airAcceleration228private alias object.value24 : player.airDeceleration229private alias object.value25 : player.gravityStrength // Also used in underwater checks, 0x1000 if underwater, otherwise 0x3800. Not to be confused with player.gravity230private alias object.value26 : player.flightVelocity // Used by Tails only231private alias object.value27 : player.jumpStrength232private alias object.value28 : player.jumpCap233private alias object.value29 : player.rollingFriction // Active rolling deceleration - With the player holding the opposite direction234private alias object.value30 : player.jumpOffset // Added to the player's position when jumping/rolling. Normally -5 for S&K, and -1 for Tails235private alias object.value31 : player.rollingDeceleration // Passive rolling deceleration - Without the player holding the opposite direction236private alias object.value32 : player.jumpAbility // Used to store whatever function this player has for its jump ability237private alias object.value33 : player.actionSpindash // Used to store whatever function this player has for its spindash ability238private alias object.value34 : player.collisionDisabled239private alias object.value35 : player.jumpAbilityState240private alias object.value36 : player.flyCarryTimer // Tails assist lockout timer241private alias object.value37 : player.shield // Current shield the player has, see above constants for what is what242private alias object.value40 : player.hitboxLeft243private alias object.value38 : player.hitboxTop244private alias object.value41 : player.hitboxRight245private alias object.value39 : player.hitboxBottom246private alias object.value42 : player.prevGravity247248// Values used in Origins249private alias object.value16 : player.releasingDropDash250private alias object.value44 : player.missionBlockID251private alias object.value47 : player.disableGravity // Added in Origins 2.0.1, used after clearing/failing a mission252253// P2 values254private alias object.value43 : player.jumpInTimer255private alias object.value44 : player.stateInputP2256private alias object.value45 : player.autoJumpTimer257private alias object.value46 : player.targetLeaderPos.x258private alias object.value47 : player.targetLeaderPos.y259260// Death Event Aliases261private alias object.state : deathEvent.state262private alias object.value1 : deathEvent.leftTextPos263private alias object.value2 : deathEvent.rightTextPos264private alias object.value3 : deathEvent.timer265private alias object.drawOrder : deathEvent.drawOrder266267private alias 0 : DEATHEVENT_GAMEOVER268private alias 1 : DEATHEVENT_TIMEOVER269private alias 2 : DEATHEVENT_DEATH270private alias 3 : DEATHEVENT_DEATH_TA271272// Shield related values273private alias object.value0 : goggles.targetPlayer274275// Mission Values276private alias object.value0 : object.ledgePullFlag277278// Title Card aliases279private alias 8 : TITLECARD_FADETOTITLE280281282// ========================283// Function Declarations284// ========================285286reserve function Player_ProcessUpdate287reserve function Player_State_Static288reserve function Player_HandleGroundMovement289reserve function Player_HandleAirFriction290reserve function Player_HandleAirMovement291reserve function Player_HandleOnGround292reserve function Player_Action_Jump293reserve function Player_Action_Spindash294reserve function Player_Action_DblJumpTails295reserve function Player_Action_DblJumpKnux296reserve function Player_State_Ground297reserve function Player_State_Air_NoDropDash298reserve function Player_State_Air299reserve function Player_State_TubeAirRoll300reserve function Player_State_Roll301reserve function Player_State_RollJump302reserve function Player_State_LookUp303reserve function Player_State_Crouch304reserve function Player_State_Spindash305reserve function Player_State_Fly306reserve function Player_State_GlideLeft307reserve function Player_State_GlideRight308reserve function Player_State_GlideDrop309reserve function Player_State_GlideSlide310reserve function Player_State_Climb311reserve function Player_State_LedgePullUp312reserve function Player_State_GotHit // got hit, applies damange313reserve function Player_State_Hurt // damage recoil, ouch!!314reserve function Player_State_Death315reserve function Player_State_Drown316reserve function Player_State_HangBar // Unused - Leftover from Sonic CD317reserve function Player_State_CorkscrewRun // Unused - Leftover from Sonic Nexus318reserve function Player_State_CorkscrewRoll // Unused - Leftover from Sonic Nexus319reserve function Player_State_TubeRoll320reserve function Player_State_Clinging321reserve function Player_HandleDropDash322reserve function Player_State_Climb_Mission323reserve function Player_State_LPullUp_Mission324reserve function Player_SetDropDashCharge325reserve function Player_GetDropDashCharge326reserve function Player_State_WaterSlide327reserve function Player_State_Carried328reserve function Player_State_ContinueRun329reserve function Player_CheckIfOnScreen330reserve function Player_Action_DblJumpAmy331reserve function Player_Action_HammerDash332reserve function Player_State_HammerDash333reserve function Player_SetHammerDashSpeed334reserve function Player_HandleAmyHitbox335reserve function Player_SetupAttractDemo336reserve function Player_ApplyShield337reserve function Player_HandleSuperPalette_Sonic338reserve function Player_HandleSuperPalette_Tails339reserve function Player_HandleSuperPalette_Knux340reserve function Player_HandleSuperPalette_Amy341reserve function Player_UpdatePhysicsState342reserve function Player_HandleSuperForm343reserve function Player_CheckHit344reserve function Player_BadnikBreak345reserve function Player_Hit346reserve function Player_FireHit347reserve function Player_LightningHit348reserve function Player_ProjectileHit349reserve function Player_SpikeHit350reserve function Player_Kill351reserve function Player_HandleRollAnimSpeed352reserve function Player_HandleWalkAnimSpeed353reserve function Player_HandleRunAnimSpeed354reserve function Player_HandleRollDeceleration355reserve function Player_State_Transform356reserve function Player_TryTransform357reserve function Player_State_BubbleBounce358reserve function Player_Action_DblJumpSonic359reserve function Player_HandleFlyCarry360361362// ========================363// Static Values364// ========================365366public value Player_flyCarryLeaderXPos = 0367public value Player_flyCarryLeaderYPos = 0368public value Player_flyCarryBuddyXPos = 0369public value Player_flyCarryBuddyYPos = 0370371public value Player_superState = 0372public value Player_superRingLossTimer = 0373public value Player_superBlendClr = 0374public value Player_superBlendTimer = 0375376public value Player_attractTable = 0377public value Player_attractTablePos = 0378public value Player_attractTableSize = 0379public value Player_attractFrameCount = 0380public value Player_attractDuration = 0381382public value Player_ScreenPosDiff = 0 // New to Origins Plus383384// All these below are declared but unused385private value Player_unusedValue1 = 0386private value Player_unusedValue2 = 0387private value Player_unusedValue3 = 0388private value Player_unusedValue4 = 0389private value Player_unusedValue5 = 0390private value Player_unusedValue6 = 0391private value Player_unusedValue7 = 0392393394// ========================395// Tables396// ========================397398public table Player_SonicSuperPal3990x202080, 0x4040A0, 0x6060C0, 0x8080E04000x404060, 0x6060A0, 0x8080E0, 0xA0A0E04010x606040, 0x8080A0, 0xA0A0E0, 0xC0C0E04020x808040, 0xA0A0A0, 0xC0C0E0, 0xE0E0E04030xA0A040, 0xC0C0A0, 0xE0E0E0, 0xE0E0E04040xC0C040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E04050xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E04060xE0E060, 0xE0E0E0, 0xE0E0E0, 0xE0E0E04070xE0E080, 0xE0E0E0, 0xE0E0E0, 0xE0E0E04080xE0E060, 0xE0E0C0, 0xE0E0E0, 0xE0E0E04090xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E04100xE0E020, 0xE0E080, 0xE0E0C0, 0xE0E0E04110xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E04120xE0E000, 0xE0E040, 0xE0E080, 0xE0E0C04130xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E04140xE0E000, 0xE0E080, 0xE0E0C0, 0xE0E0E0415end table416417// Alt underwater palette418// Normally only used by LZ in S1, the actual UW colors are set in LZSetup419public table Player_SonicSuperAltPal4200x202080, 0x4040A0, 0x6060C0, 0x8080E04210x404060, 0x6060A0, 0x8080E0, 0xA0A0E04220x606040, 0x8080A0, 0xA0A0E0, 0xC0C0E04230x808040, 0xA0A0A0, 0xC0C0E0, 0xE0E0E04240xA0A040, 0xC0C0A0, 0xE0E0E0, 0xE0E0E04250xC0C040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E04260xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E04270xE0E060, 0xE0E0E0, 0xE0E0E0, 0xE0E0E04280xE0E080, 0xE0E0E0, 0xE0E0E0, 0xE0E0E04290xE0E060, 0xE0E0C0, 0xE0E0E0, 0xE0E0E04300xE0E040, 0xE0E0A0, 0xE0E0E0, 0xE0E0E04310xE0E020, 0xE0E080, 0xE0E0C0, 0xE0E0E04320xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E04330xE0E000, 0xE0E040, 0xE0E080, 0xE0E0C04340xE0E000, 0xE0E060, 0xE0E0A0, 0xE0E0E04350xE0E000, 0xE0E080, 0xE0E0C0, 0xE0E0E0436end table437438public table Player_TailsSuperPal4390x800000, 0xE08000, 0xE0A000, 0xA060404400x800000, 0xE0A020, 0xE0C040, 0xA060404410xA06040, 0xE0C040, 0xE0C080, 0xC060404420xC06040, 0xE0C080, 0xE0E0A0, 0xE080404430xA06040, 0xE0C040, 0xE0C080, 0xC060404440x800000, 0xE0A020, 0xE0C040, 0xA06040445end table446447// Alt underwater palette448// Normally only used by LZ in S1, the actual UW colors are set in LZSetup449public table Player_TailsSuperAltPal4500x800000, 0xE08000, 0xE0A000, 0xA060404510x800000, 0xE0A020, 0xE0C040, 0xA060404520xA06040, 0xE0C040, 0xE0C080, 0xC060404530xC06040, 0xE0C080, 0xE0E0A0, 0xE080404540xA06040, 0xE0C040, 0xE0C080, 0xC060404550x800000, 0xE0A020, 0xE0C040, 0xA06040456end table457458public table Player_KnuxSuperPal4590x600020, 0xC00020, 0xE040604600x802040, 0xE04060, 0xE060A04610xA04060, 0xE06080, 0xE080C04620xC06080, 0xE080A0, 0xE0A0E04630xE080A0, 0xE0A0C0, 0xE0C0E04640xE0A0C0, 0xE0C0E0, 0xE0E0E04650xE080A0, 0xE0A0C0, 0xE0C0E04660xC06080, 0xE080A0, 0xE0A0E04670xA04060, 0xE06080, 0xE080C04680x802040, 0xE04060, 0xE060A0469end table470471// Alt underwater palette472// Normally only used by LZ in S1, the actual UW colors are set in LZSetup473public table Player_KnuxSuperAltPal4740x600020, 0xC00040, 0xE040804750x802040, 0xE04060, 0xE060A04760xA04060, 0xE06080, 0xE080C04770xC06080, 0xE080A0, 0xE0A0E04780xE080A0, 0xE0A0C0, 0xE0C0E04790xE0A0C0, 0xE0C0E0, 0xE0E0E04800xE080A0, 0xE0A0C0, 0xE0C0E04810xC06080, 0xE080A0, 0xE0A0E04820xA04060, 0xE06080, 0xE080C04830x802040, 0xE04060, 0xE060A0484end table485486// Bug Details (yeah we haven't gotten to any actual code yet and there's already an issue):487// Amy's base palette is completely missing in both of these tables, causing the game to apply the first super palette when the scene loads instead488// This is what causes Amy's fur to be slightly brighter in-game compared to the spritesheets and global palette489// Note that if you're looking to fix this, you'll also have to edit the Player_HandleSuperPalette_Amy function to account for the new line490491public table Player_AmySuperPal4920xD468B0, 0xFC8CFC, 0xFCD4FC, 0x8C2068, 0xB0448C4930xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC4940xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC4950xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC4960xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC4970xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECC0E8, 0xF0E4EC4980xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC4990xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC5000xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC5010xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC502end table503504public table Player_AmySuperAltPal5050xD468B0, 0xFC8CFC, 0xFCD4FC, 0x8C2068, 0xB0448C5060xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC5070xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC5080xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC5090xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC5100xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECC0E8, 0xF0E4EC5110xF4E8F0, 0xFCECFC, 0xFCE4FC, 0xECA0E8, 0xF0C4EC5120xF4C8F0, 0xFCECFC, 0xFCE4FC, 0xEC80C8, 0xF0A4EC5130xF4A8F0, 0xFCCCFC, 0xFCE4FC, 0xCC60A8, 0xF084CC5140xF488D0, 0xFCACFC, 0xFCE4FC, 0xAC4088, 0xD064AC515end table516517// Each line of these physics tables store the values in this order:518// Top Speed, Ground Acceleration, Air Acceleration, Air Deleceration, Skid Speed, Rolling Friction, Jump Strength, Jump Cap519// Note that Ground Deceleration is not defined here, rather it's calculated based on Ground Acceleration520521private table Player_SonicPhysicsTable5220x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x68000, -0x40000 // Normal5230x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x38000, -0x20000 // Underwater5240xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x80000, -0x40000 // Super5250x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x38000, -0x20000 // Super + Underwater5260xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x68000, -0x40000 // Speed Shoes5270x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Underwater5280xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x80000, -0x40000 // Speed Shoes + Super5290x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Super + Underwater530end table531532private table Player_TailsPhysicsTable5330x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x68000, -0x40000 // Normal5340x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x38000, -0x20000 // Underwater5350xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x80000, -0x40000 // Super5360x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x38000, -0x20000 // Super + Underwater5370xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x68000, -0x40000 // Speed Shoes5380x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Underwater5390xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x80000, -0x40000 // Speed Shoes + Super5400x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Super + Underwater541end table542543private table Player_KnuxPhysicsTable5440x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x60000, -0x40000 // Normal5450x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x30000, -0x20000 // Underwater5460xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x60000, -0x40000 // Super5470x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x30000, -0x20000 // Super + Underwater5480xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x60000, -0x40000 // Speed Shoes5490x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x30000, -0x20000 // Speed Shoes + Underwater5500xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x60000, -0x40000 // Speed Shoes + Super5510x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0300, 0x30000, -0x20000 // Speed Shoes + Super + Underwater552end table553554private table Player_AmyPhysicsTable5550x60000, 0x0C00, 0x1800, 0x0600, 0x08000, 0x0600, 0x68000, -0x40000 // Normal5560x30000, 0x0600, 0x0C00, 0x0300, 0x04000, 0x0300, 0x38000, -0x20000 // Underwater5570xA0000, 0x3000, 0x6000, 0x1800, 0x10000, 0x0600, 0x80000, -0x40000 // Super5580x50000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0300, 0x38000, -0x20000 // Super + Underwater5590xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x68000, -0x40000 // Speed Shoes5600x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Underwater5610xC0000, 0x1800, 0x3000, 0x0C00, 0x08000, 0x0600, 0x80000, -0x40000 // Speed Shoes + Super5620x60000, 0x0C00, 0x1800, 0x0600, 0x04000, 0x0300, 0x38000, -0x20000 // Speed Shoes + Super + Underwater563end table564565566// ========================567// Function Definitions568// ========================569570public function Player_HandleAmyHitbox571#platform: USE_ORIGINS572if stage.playerListPos == PLAYER_AMY573temp0 = false574575if player[currentPlayer].animation == ANI_HAMMER_JUMP576temp0 = true577578player[currentPlayer].hitboxTop = -25579player[currentPlayer].hitboxBottom = 25580player[currentPlayer].hitboxLeft = -25581player[currentPlayer].hitboxRight = 25582end if583584if player[currentPlayer].animation == ANI_HAMMER_DASH585temp0 = true586587player[currentPlayer].hitboxBottom = 17588player[currentPlayer].hitboxTop = -24589player[currentPlayer].hitboxLeft = -18590player[currentPlayer].hitboxRight = 10591592switch player[currentPlayer].frame593case 0594case 4595player[currentPlayer].hitboxTop = -17596player[currentPlayer].hitboxLeft = -10597player[currentPlayer].hitboxRight = 23598break599600case 1601case 5602player[currentPlayer].hitboxTop = -17603player[currentPlayer].hitboxLeft = -23604player[currentPlayer].hitboxRight = 10605break606607case 2608case 6609player[currentPlayer].hitboxTop = -24610player[currentPlayer].hitboxLeft = -18611player[currentPlayer].hitboxRight = 10612break613614case 3615case 7616player[currentPlayer].hitboxTop = -26617player[currentPlayer].hitboxLeft = -10618player[currentPlayer].hitboxRight = 25619break620end switch621622if player[currentPlayer].direction == FACING_LEFT623// Swap the left and right values624temp1 = player[currentPlayer].hitboxLeft625player[currentPlayer].hitboxLeft = player[currentPlayer].hitboxRight626player[currentPlayer].hitboxRight = temp1627player[currentPlayer].hitboxLeft *= -1628player[currentPlayer].hitboxRight *= -1629end if630end if631632if temp0 == false633// Default to regular hitbox634player[currentPlayer].hitboxTop = C_BOX635player[currentPlayer].hitboxBottom = C_BOX636player[currentPlayer].hitboxLeft = C_BOX637player[currentPlayer].hitboxRight = C_BOX638end if639end if640#endplatform641end function642643// Initialize the character object for replay playback644public function Player_SetupAttractDemo645// Input entries start 2 indexes in, since the first two values are starting position646Player_attractTablePos = 2647Player_attractFrameCount = 1648649// Reset each player's controls650currentPlayer = 0651while currentPlayer < playerCount652GetTableValue(player[currentPlayer].xpos, 0, Player_attractTable)653GetTableValue(player[currentPlayer].ypos, 1, Player_attractTable)654player[currentPlayer].controlMode = CONTROLMODE_NONE655player[currentPlayer].up = false656player[currentPlayer].down = false657player[currentPlayer].left = false658player[currentPlayer].right = false659player[currentPlayer].jumpPress = false660player[currentPlayer].jumpHold = false661player[currentPlayer].timer = false662currentPlayer++663loop664665camera[0].xpos = player[SLOT_PLAYER1].ixpos666camera[0].ypos = player[SLOT_PLAYER1].iypos667end function668669670// Give the player back their shield after invincibility671public function Player_ApplyShield672switch player[currentPlayer].shield673case SHIELD_NONE // No shield - that means to just set the shield slot to blank674ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)675break676677case SHIELD_NORMAL // Blue shield, restore it and also set its alpha properties678ResetObjectEntity(arrayPos0, blueShieldType, 0, 0, 0)679object[arrayPos0].priority = PRIORITY_ACTIVE680object[arrayPos0].inkEffect = INK_ALPHA681object[arrayPos0].alpha = 160682break683684case SHIELD_BUBBLE685ResetObjectEntity(arrayPos0, TypeName[Bubble Shield], 0, 0, 0)686object[arrayPos0].priority = PRIORITY_ACTIVE687break688689case SHIELD_FIRE690ResetObjectEntity(arrayPos0, TypeName[Fire Shield], 0, 0, 0)691object[arrayPos0].priority = PRIORITY_ACTIVE692break693694case SHIELD_LIGHTNING695ResetObjectEntity(arrayPos0, TypeName[LightningShield], 0, 0, 0)696object[arrayPos0].priority = PRIORITY_ACTIVE697break698699case SHIELD_GOGGLES // LZ Googles, restore them and set them to draw right infront of the player700ResetObjectEntity(arrayPos0, goggleType, 0, 0, 0)701object[arrayPos0].priority = PRIORITY_ACTIVE702goggles[arrayPos0].targetPlayer = currentPlayer703object[arrayPos0].drawOrder = DRAWORDER_PLAYER704break705706end switch707end function708709710public function Player_HandleSuperPalette_Sonic711if Player_superState == SUPERSTATE_SUPER712// Main Super state713Player_superBlendTimer++714if Player_superBlendTimer >= 4715Player_superBlendTimer = 0716Player_superBlendClr += 4717718if Player_superBlendClr >= 64719Player_superBlendClr = 24720end if721end if722else723// Detransforming724Player_superBlendTimer++725if Player_superBlendTimer >= 8726Player_superBlendTimer = 0727Player_superBlendClr -= 4728729if Player_superBlendClr <= 0730Player_superBlendClr = 0731Player_superState = SUPERSTATE_NONE732end if733734if Player_superBlendClr >= 24735Player_superBlendClr = 24736end if737end if738end if739740// Make Sonic's Super palette all flashy741// Palette table 0 is normal palette, palette table 1 is underwater palette742temp1 = Player_superBlendClr743GetTableValue(temp0, temp1, Player_SonicSuperPal)744SetPaletteEntry(0, 2, temp0)745GetTableValue(temp0, temp1, Player_SonicSuperAltPal)746SetPaletteEntry(1, 2, temp0)747temp1++748749GetTableValue(temp0, temp1, Player_SonicSuperPal)750SetPaletteEntry(0, 3, temp0)751GetTableValue(temp0, temp1, Player_SonicSuperAltPal)752SetPaletteEntry(1, 3, temp0)753temp1++754755GetTableValue(temp0, temp1, Player_SonicSuperPal)756SetPaletteEntry(0, 4, temp0)757GetTableValue(temp0, temp1, Player_SonicSuperAltPal)758SetPaletteEntry(1, 4, temp0)759temp1++760761GetTableValue(temp0, temp1, Player_SonicSuperPal)762SetPaletteEntry(0, 5, temp0)763GetTableValue(temp0, temp1, Player_SonicSuperAltPal)764SetPaletteEntry(1, 5, temp0)765end function766767768public function Player_HandleSuperPalette_Tails769if Player_superState == SUPERSTATE_SUPER770// Main Super state771Player_superBlendTimer++772if Player_superBlendTimer >= 12773Player_superBlendTimer = 0774Player_superBlendClr += 4775776if Player_superBlendClr >= 24777Player_superBlendClr = 0778end if779end if780else781// Detransforming782if Player_superBlendClr > 12783FlipSign(Player_superBlendClr)784Player_superBlendClr += 24785end if786787Player_superBlendTimer++788if Player_superBlendTimer >= 12789Player_superBlendTimer = 0790Player_superBlendClr -= 4791792if Player_superBlendClr <= 0793Player_superBlendClr = 0794Player_superState = SUPERSTATE_NONE795end if796end if797end if798799temp1 = Player_superBlendClr800GetTableValue(temp0, temp1, Player_TailsSuperPal)801SetPaletteEntry(0, 13, temp0)802GetTableValue(temp0, temp1, Player_TailsSuperAltPal)803SetPaletteEntry(1, 13, temp0)804temp1++805806GetTableValue(temp0, temp1, Player_TailsSuperPal)807SetPaletteEntry(0, 17, temp0)808GetTableValue(temp0, temp1, Player_TailsSuperAltPal)809SetPaletteEntry(1, 17, temp0)810temp1++811812GetTableValue(temp0, temp1, Player_TailsSuperPal)813SetPaletteEntry(0, 18, temp0)814GetTableValue(temp0, temp1, Player_TailsSuperAltPal)815SetPaletteEntry(1, 18, temp0)816temp1++817818GetTableValue(temp0, temp1, Player_TailsSuperPal)819SetPaletteEntry(0, 16, temp0)820GetTableValue(temp0, temp1, Player_TailsSuperAltPal)821SetPaletteEntry(1, 16, temp0)822end function823824825public function Player_HandleSuperPalette_Knux826if Player_superState == SUPERSTATE_SUPER827// Main Super state828Player_superBlendTimer++829if Player_superBlendTimer >= 12830Player_superBlendTimer = 9831Player_superBlendClr += 3832833if Player_superBlendClr >= 30834Player_superBlendTimer = 0835Player_superBlendClr = 0836end if837end if838else839// Detransforming840if Player_superBlendClr > 15841FlipSign(Player_superBlendClr)842Player_superBlendClr += 30843end if844845Player_superBlendTimer++846if Player_superBlendTimer >= 12847Player_superBlendTimer = 0848Player_superBlendClr -= 3849850if Player_superBlendClr <= 0851Player_superBlendClr = 0852Player_superState = SUPERSTATE_NONE853end if854end if855end if856857temp1 = Player_superBlendClr858GetTableValue(temp0, temp1, Player_KnuxSuperPal)859SetPaletteEntry(0, 26, temp0)860GetTableValue(temp0, temp1, Player_KnuxSuperAltPal)861SetPaletteEntry(1, 26, temp0)862temp1++863864GetTableValue(temp0, temp1, Player_KnuxSuperPal)865SetPaletteEntry(0, 27, temp0)866GetTableValue(temp0, temp1, Player_KnuxSuperAltPal)867SetPaletteEntry(1, 27, temp0)868temp1++869870GetTableValue(temp0, temp1, Player_KnuxSuperPal)871SetPaletteEntry(0, 28, temp0)872GetTableValue(temp0, temp1, Player_KnuxSuperAltPal)873SetPaletteEntry(1, 28, temp0)874end function875876public function Player_HandleSuperPalette_Amy877#platform: USE_ORIGINS878if Player_superState == SUPERSTATE_SUPER879Player_superBlendTimer++880if Player_superBlendTimer >= 12881Player_superBlendTimer = 5882Player_superBlendClr += 5883if Player_superBlendClr >= 50884Player_superBlendClr = 0885end if886end if887else888if Player_superBlendClr > 15889FlipSign(Player_superBlendClr)890Player_superBlendClr += 50891end if892893Player_superBlendTimer++894if Player_superBlendTimer >= 12895Player_superBlendTimer = 0896Player_superBlendClr -= 5897if Player_superBlendClr <= 0898Player_superBlendClr = 0899Player_superState = SUPERSTATE_NONE900end if901end if902end if903904temp1 = Player_superBlendClr905906GetTableValue(temp0, temp1, Player_AmySuperPal)907SetPaletteEntry(0, 66, temp0)908GetTableValue(temp0, temp1, Player_AmySuperAltPal)909SetPaletteEntry(1, 66, temp0)910temp1++911912GetTableValue(temp0, temp1, Player_AmySuperPal)913SetPaletteEntry(0, 67, temp0)914GetTableValue(temp0, temp1, Player_AmySuperAltPal)915SetPaletteEntry(1, 67, temp0)916temp1++917918GetTableValue(temp0, temp1, Player_AmySuperPal)919SetPaletteEntry(0, 68, temp0)920GetTableValue(temp0, temp1, Player_AmySuperAltPal)921SetPaletteEntry(1, 68, temp0)922temp1++923924GetTableValue(temp0, temp1, Player_AmySuperPal)925SetPaletteEntry(0, 64, temp0)926GetTableValue(temp0, temp1, Player_AmySuperAltPal)927SetPaletteEntry(1, 64, temp0)928temp1++929930GetTableValue(temp0, temp1, Player_AmySuperPal)931SetPaletteEntry(0, 65, temp0)932GetTableValue(temp0, temp1, Player_AmySuperAltPal)933SetPaletteEntry(1, 65, temp0)934#endplatform935end function936937938public function Player_UpdatePhysicsState939switch stage.playerListPos940case PLAYER_SONIC_A941case PLAYER_SONIC_TAILS_A942temp0 = Player_SonicPhysicsTable943break944945case PLAYER_TAILS_A946temp0 = Player_TailsPhysicsTable947break948949case PLAYER_KNUCKLES_A950temp0 = Player_KnuxPhysicsTable951break952953#platform: USE_ORIGINS954case PLAYER_AMY_A955temp0 = Player_AmyPhysicsTable956break957#endplatform958end switch959960temp1 = 0961temp2 = 0962963if stage.state != STAGE_FROZEN964// Is the player underwater?965temp3 = player[currentPlayer].ypos966temp3 >>= 16967968// Pairing the water & Debug Mode checks together969CheckGreater(temp3, stage.waterLevel)970temp4 = checkResult971CheckNotEqual(player[currentPlayer].type, TypeName[Debug Mode])972temp4 &= checkResult973974if temp4 == true975SetBit(temp1, 0, true)976player[currentPlayer].gravityStrength = 0x1000977else978player[currentPlayer].gravityStrength = 0x3800979end if980981if Player_superState == SUPERSTATE_SUPER982#platform: USE_ORIGINS983// Tails can no longer be silly :(984if player[currentPlayer].isSidekick == false985#endplatform986SetBit(temp1, 1, true)987temp2 = 2988#platform: USE_ORIGINS989end if990#endplatform991end if992993if player[currentPlayer].speedShoesTimer > 0994SetBit(temp1, 2, true)995temp2 = 1996end if997998temp1 <<= 3999end if10001001// Set the physics values1002GetTableValue(player[currentPlayer].topSpeed, temp1, temp0)1003temp1++1004GetTableValue(player[currentPlayer].acceleration, temp1, temp0)10051006player[currentPlayer].deceleration = player[currentPlayer].acceleration1007player[currentPlayer].deceleration >>= temp210081009temp1++1010GetTableValue(player[currentPlayer].airAcceleration, temp1, temp0)1011temp1++1012GetTableValue(player[currentPlayer].airDeceleration, temp1, temp0)1013temp1++1014GetTableValue(player[currentPlayer].skidSpeed, temp1, temp0)1015temp1++1016GetTableValue(player[currentPlayer].rollingFriction, temp1, temp0)1017temp1++1018GetTableValue(player[currentPlayer].jumpStrength, temp1, temp0)1019temp1++1020GetTableValue(player[currentPlayer].jumpCap, temp1, temp0)1021end function102210231024public function Player_HandleSuperForm1025// Do the fancy palette stuff if Super or while untransforming back to normal1026if Player_superState != SUPERSTATE_NONE1027switch stage.playerListPos1028case PLAYER_SONIC_A1029case PLAYER_SONIC_TAILS_A // This case check should never pass since playing as S&T will set your character to Sonic alone1030CallFunction(Player_HandleSuperPalette_Sonic)1031break10321033case PLAYER_TAILS_A1034CallFunction(Player_HandleSuperPalette_Tails)1035break10361037case PLAYER_KNUCKLES_A1038CallFunction(Player_HandleSuperPalette_Knux)1039break10401041#platform: USE_ORIGINS1042case PLAYER_AMY_A1043CallFunction(Player_HandleSuperPalette_Amy)1044break1045#endplatform1046end switch1047end if10481049if Player_superState == SUPERSTATE_SUPER1050player.invincibleTimer = 6010511052Player_superRingLossTimer++10531054// If a second has passed since the last ring loss...1055if Player_superRingLossTimer == 601056// ...then take another ring from the player1057Player_superRingLossTimer = 01058player.rings--10591060// If the player has no more rings, make them untransform1061if player.rings == 01062Player_superState = SUPERSTATE_UNTRANSFORM1063end if1064end if1065end if10661067if Player_superState == SUPERSTATE_UNTRANSFORM1068if stage.playerListPos == PLAYER_SONIC_A1069LoadAnimation("Sonic.ani")1070end if10711072if music.currentTrack == TRACK_INVINCIBLE1073PlayMusic(0)1074end if10751076player.invincibleTimer = 010771078// If the player isn't already dead, give them back their shield1079if player.state != Player_State_Death1080if player.state != Player_State_Drown1081currentPlayer = player.entityPos1082arrayPos0 = currentPlayer1083arrayPos0 += playerCount10841085CallFunction(Player_ApplyShield)1086end if1087end if10881089Player_superState = SUPERSTATE_END1090CallFunction(Player_UpdatePhysicsState)1091end if1092end function109310941095// Used by badniks to check for if the player should get hit1096// -> Not to be confused with Player_BadnikBreak, which is for breaking badniks as a whole1097public function Player_CheckHit1098CheckEqual(player[currentPlayer].animation, ANI_JUMPING)1099temp0 = checkResult1100CheckEqual(player[currentPlayer].animation, ANI_SPINDASH)1101temp0 |= checkResult1102CheckEqual(player[currentPlayer].animation, ANI_GLIDING)1103temp0 |= checkResult1104CheckEqual(player[currentPlayer].animation, ANI_GLIDING_STOP)1105temp0 |= checkResult1106CheckNotEqual(player[currentPlayer].invincibleTimer, 0)1107temp0 |= checkResult11081109#platform: USE_ORIGINS1110// Amy's trusty Pico Pico Hammer can bash through anything!1111if stage.playerListPos == PLAYER_AMY1112if player[currentPlayer].isSidekick == false1113CheckEqual(player[currentPlayer].animation, ANI_HAMMER_JUMP)1114temp0 |= checkResult1115CheckEqual(player[currentPlayer].animation, ANI_HAMMER_DASH)1116temp0 |= checkResult1117end if1118end if1119#endplatform11201121CheckEqual(player[currentPlayer].animation, ANI_FLYING)1122temp1 = checkResult1123CheckEqual(player[currentPlayer].animation, ANI_FLYINGTIRED)1124temp1 |= checkResult1125CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_UP)1126temp1 |= checkResult1127CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_DOWN)1128temp1 |= checkResult1129CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_TIRED)1130temp1 |= checkResult1131if temp1 == true1132CheckGreater(player[currentPlayer].ypos, object.ypos)1133temp0 |= checkResult1134end if11351136if temp0 == true1137FlipSign(player[currentPlayer].xvel)1138player[currentPlayer].xvel >>= 11139player[currentPlayer].speed = player[currentPlayer].xvel1140FlipSign(player[currentPlayer].yvel)1141player[currentPlayer].yvel >>= 111421143if player[currentPlayer].animation == ANI_GLIDING1144player[currentPlayer].animation = ANI_GLIDING_DROP1145player[currentPlayer].state = Player_State_GlideDrop1146end if11471148checkResult = true1149else1150if player[currentPlayer].state != Player_State_Death1151if player[currentPlayer].invincibleTimer == 01152if player[currentPlayer].blinkTimer == 01153player[currentPlayer].state = Player_State_GotHit11541155if player[currentPlayer].xpos > object.xpos1156player[currentPlayer].speed = 0x200001157else1158player[currentPlayer].speed = -0x200001159end if1160end if1161end if1162end if11631164checkResult = false1165end if1166end function116711681169// Used by badniks to check if the badnik should be destroyed1170// -> Not to be confused with Player_CheckHit1171public function Player_BadnikBreak1172CheckEqual(player[currentPlayer].animation, ANI_JUMPING)1173temp0 = checkResult1174CheckEqual(player[currentPlayer].animation, ANI_SPINDASH)1175temp0 |= checkResult1176CheckEqual(player[currentPlayer].animation, ANI_GLIDING)1177temp0 |= checkResult1178CheckEqual(player[currentPlayer].animation, ANI_GLIDING_STOP)1179temp0 |= checkResult1180CheckNotEqual(player[currentPlayer].invincibleTimer, 0)1181temp0 |= checkResult11821183#platform: USE_ORIGINS1184// Amy's trusty Pico Pico Hammer can bash through anything!1185if stage.playerListPos == PLAYER_AMY1186if player[currentPlayer].isSidekick == false1187CheckEqual(player[currentPlayer].animation, ANI_HAMMER_JUMP)1188temp0 |= checkResult1189CheckEqual(player[currentPlayer].animation, ANI_HAMMER_DASH)1190temp0 |= checkResult1191end if1192end if1193#endplatform11941195CheckEqual(player[currentPlayer].animation, ANI_FLYING)1196temp1 = checkResult1197CheckEqual(player[currentPlayer].animation, ANI_FLYINGTIRED)1198temp1 |= checkResult1199CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_UP)1200temp1 |= checkResult1201CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_DOWN)1202temp1 |= checkResult1203CheckEqual(player[currentPlayer].animation, ANI_FLY_LIFT_TIRED)1204temp1 |= checkResult1205if temp1 == true1206CheckGreater(player[currentPlayer].ypos, object.ypos)1207temp0 |= checkResult1208end if12091210#platform: USE_ORIGINS1211if game.playMode == BOOT_PLAYMODE_MISSION1212if stage.timeEnabled == false1213temp0 = false1214end if12151216if game.missionFunctionNo == MISSIONNO_MERCY1217temp0 = false1218end if1219end if1220#endplatform12211222if temp0 == true1223#platform: USE_ORIGINS1224CheckCurrentStageFolder("Zone01") // Green Hill Zone1225if checkResult == true1226if object.type == TYPE_MOTOBUG1227stageStat.motobugDestroyCount++1228end if1229end if1230#endplatform12311232ResetObjectEntity(object.entityPos, TypeName[Blank Object], 0, object.xpos, object.ypos)1233Rand(checkResult, 32)1234if checkResult >= 161235CreateTempObject(animalType1, 0, object.xpos, object.ypos)1236else1237CreateTempObject(animalType2, 0, object.xpos, object.ypos)1238end if1239object[tempObjectPos].priority = PRIORITY_ACTIVE_SMALL12401241CreateTempObject(TypeName[Smoke Puff], 0, object.xpos, object.ypos)1242object[tempObjectPos].drawOrder = 412431244CreateTempObject(TypeName[Object Score], player[currentPlayer].badnikBonus, object.xpos, object.ypos)1245object[tempObjectPos].drawOrder = 412461247#platform: USE_STANDALONE1248PlaySfx(SfxName[Destroy], false)1249#endplatform12501251#platform: USE_ORIGINS1252temp2 = false12531254if stage.playerListPos == PLAYER_AMY1255if player[currentPlayer].isSidekick == false1256if player[currentPlayer].animation == ANI_HAMMER_JUMP1257temp2 = true1258end if12591260if player[currentPlayer].animation == ANI_HAMMER_DASH1261temp2 = true1262end if1263end if1264end if12651266if temp2 == true1267PlaySfx(SfxName[HammerHit], false)1268else1269PlaySfx(SfxName[Destroy], false)1270end if1271#endplatform12721273if player[currentPlayer].yvel > 01274if player[currentPlayer].ypos >= object.ypos1275player[currentPlayer].yvel -= 0x100001276else1277player[currentPlayer].yvel += player[currentPlayer].gravityStrength1278player[currentPlayer].yvel += player[currentPlayer].gravityStrength1279FlipSign(player[currentPlayer].yvel)1280end if1281else1282player[currentPlayer].yvel += 0x100001283end if12841285if options.competition == false // Will always pass because guess what doesn't exist in S1?1286temp0 = currentPlayer1287currentPlayer = 01288end if12891290switch player[currentPlayer].badnikBonus1291case 01292player.score += 1001293break12941295case 11296player.score += 2001297break12981299case 21300player.score += 5001301break13021303case 31304case 41305case 51306case 61307case 71308case 81309case 91310case 101311case 111312case 121313case 131314case 141315player.score += 10001316break13171318case 151319player.score += 100001320break13211322end switch13231324if player[currentPlayer].badnikBonus < 151325player[currentPlayer].badnikBonus++1326end if13271328if options.competition == false // Again, will always pass1329currentPlayer = temp01330end if13311332#platform: USE_ORIGINS1333// Handle achievement callback stuff13341335temp0 = 013361337CheckEqual(player[currentPlayer].state, Player_State_Roll)1338temp1 = checkResult1339CheckEqual(player[currentPlayer].state, Player_State_RollJump)1340temp1 |= checkResult1341if temp1 == true1342if object.propertyValue == 0 // sure ig? (all Motobugs in the mission have a prop val of 0, there aren't any with non-zero prop vals)1343temp0 = KILL_ENEMY_ATTR_SPINDASH1344stageStat.spindashDestroyCount++1345end if1346end if13471348CheckEqual(player[currentPlayer].state, Player_State_GlideLeft)1349temp1 = checkResult1350CheckEqual(player[currentPlayer].state, Player_State_GlideRight)1351temp1 |= checkResult1352if temp1 == true1353temp0 = KILL_ENEMY_ATTR_GLIDING1354end if13551356stageStat.badnikDestroyCount++13571358CallNativeFunction2(NotifyCallback, NOTIFY_KILL_ENEMY, temp0)1359if game.playMode == BOOT_PLAYMODE_MISSION1360if game.missionFunctionNo == MISSIONNO_MERCY1361game.forceKillPlayer = true1362end if1363end if1364#endplatform1365else1366// If the player doesn't have any hitboxes active, then damage (or kill) them1367if player[currentPlayer].state != Player_State_Death1368if player[currentPlayer].invincibleTimer == 01369if player[currentPlayer].blinkTimer == 01370player[currentPlayer].state = Player_State_GotHit1371#platform: USE_ORIGINS1372if game.playMode == BOOT_PLAYMODE_MISSION1373if game.missionFunctionNo == MISSIONNO_MERCY1374game.missionValue = 11375end if1376end if1377#endplatform13781379if player[currentPlayer].xpos > object.xpos1380player[currentPlayer].speed = 0x200001381else1382player[currentPlayer].speed = -0x200001383end if1384end if1385end if1386end if1387end if1388end function138913901391// This function is called in order to hurt currentPlayer, not to be confused with the actual Player State functions1392public function Player_Hit1393if player[currentPlayer].state != Player_State_Death1394arrayPos0 = player[currentPlayer].entityPos // So there are these lines to find the player's shield slot... but nothing's done with it1395arrayPos0 += playerCount13961397if player[currentPlayer].invincibleTimer == 01398if player[currentPlayer].blinkTimer == 01399player[currentPlayer].state = Player_State_GotHit1400if player[currentPlayer].xpos > object.xpos1401player[currentPlayer].speed = 0x200001402else1403player[currentPlayer].speed = -0x200001404end if1405end if1406end if1407end if1408end function140914101411// Used by things like MZ lava and other fire-based obstacles1412public function Player_FireHit1413if player[currentPlayer].shield != SHIELD_FIRE1414if player[currentPlayer].state != Player_State_Death1415arrayPos0 = player[currentPlayer].entityPos // Just like above, this focuses on the player's shield slot, but it's not further referenced at all...1416arrayPos0 += playerCount14171418if player[currentPlayer].invincibleTimer == 01419if player[currentPlayer].blinkTimer == 01420player[currentPlayer].state = Player_State_GotHit1421if player[currentPlayer].xpos > object.xpos1422player[currentPlayer].speed = 0x200001423else1424player[currentPlayer].speed = -0x200001425end if1426end if1427end if1428end if1429end if1430end function143114321433// Used by things like SBZ lightning and other lightning-based obstacles1434public function Player_LightningHit1435if player[currentPlayer].shield != SHIELD_LIGHTNING1436if player[currentPlayer].state != Player_State_Death1437// (Player shouldn't have a lighting shield underwater so no other check is needed here)1438arrayPos0 = player[currentPlayer].entityPos1439arrayPos0 += playerCount14401441if player[currentPlayer].invincibleTimer == 01442if player[currentPlayer].blinkTimer == 01443player[currentPlayer].state = Player_State_GotHit14441445if player[currentPlayer].xpos > object.xpos1446player[currentPlayer].speed = 0x200001447else1448player[currentPlayer].speed = -0x200001449end if1450end if1451end if1452end if1453end if1454end function145514561457// Used by badnik projectiles when on player collision1458public function Player_ProjectileHit1459if player[currentPlayer].shield > SHIELD_NORMAL // Reflect it if the player has an elemental shield1460temp0 = player[currentPlayer].xpos1461temp0 -= object.xpos14621463temp1 = player[currentPlayer].ypos1464temp1 -= object.ypos14651466ATan2(temp2, temp0, temp1)1467Sin256(temp0, temp2)1468Cos256(temp1, temp2)14691470object.xvel = temp11471object.xvel *= -0x80014721473object.yvel = temp01474object.yvel *= -0x8001475else14761477if player[currentPlayer].state != Player_State_Death1478arrayPos0 = player[currentPlayer].entityPos1479arrayPos0 += playerCount14801481if player[currentPlayer].invincibleTimer == 01482if player[currentPlayer].blinkTimer == 01483player[currentPlayer].state = Player_State_GotHit14841485if player[currentPlayer].xpos > object.xpos1486player[currentPlayer].speed = 0x200001487else1488player[currentPlayer].speed = -0x200001489end if1490end if1491end if1492end if1493end if1494end function149514961497// Used by spikes upon player collision1498public function Player_SpikeHit1499if player[currentPlayer].state != Player_State_Death1500arrayPos0 = player[currentPlayer].entityPos1501arrayPos0 += playerCount15021503if player[currentPlayer].invincibleTimer == 01504if player[currentPlayer].state != Player_State_GotHit1505if player[currentPlayer].state != Player_State_Hurt1506// Check for spike bug if player is invulnerable1507temp0 = options.spikeBehavior1508CheckEqual(player[currentPlayer].blinkTimer, 0)1509temp0 |= checkResult15101511if temp0 == true1512if player[currentPlayer].blinkTimer == 01513player[currentPlayer].blinkTimer = 21514end if15151516player[currentPlayer].state = Player_State_GotHit1517if player[currentPlayer].xpos > object.xpos1518player[currentPlayer].speed = 0x200001519else1520player[currentPlayer].speed = -0x200001521end if1522end if1523end if1524end if1525end if1526end if1527end function152815291530// Used by other objects to kill currentPlayer, not to be confused with Player_State_Death1531public function Player_Kill1532#platform: USE_ORIGINS1533// Bug Details:1534// This code was added in 2.0.1 to prevent the player from dying after clearing/failing a mission1535// However, they used temp0 here, which causes objects that use that variable when updating its position to disappear1536// (This bug was fixed in 2.0.0, but now it's back, hooray!)15371538temp0 = false1539if game.playMode == BOOT_PLAYMODE_MISSION1540if stage.timeEnabled == false1541temp0 = true1542end if1543end if15441545if temp0 == false1546CallFunction(Player_CheckIfOnScreen)1547if checkResult != false1548PlaySfx(SfxName[Hurt], false)1549end if1550#endplatform15511552#platform: USE_STANDALONE1553PlaySfx(SfxName[Hurt], false)1554#endplatform15551556// Reset player stuff1557player[currentPlayer].speed = 01558player[currentPlayer].xvel = 01559player[currentPlayer].yvel = -0x680001560player[currentPlayer].state = Player_State_Death1561player[currentPlayer].animation = ANI_DYING1562player[currentPlayer].tileCollisions = false1563player[currentPlayer].interaction = false1564player[currentPlayer].blinkTimer = 01565player[currentPlayer].visible = true1566#platform: USE_STANDALONE1567player[currentPlayer].sortedDrawOrder = 61568#endplatform1569#platform: USE_ORIGINS1570player[currentPlayer].sortedDrawOrder = 71571#endplatform15721573// Is this the main character?1574if currentPlayer == 01575player[currentPlayer].priority = PRIORITY_ALWAYS1576if player[1].type == TypeName[Player 2 Object]1577player[1].priority = PRIORITY_ALWAYS1578end if15791580// Stop the game flow1581camera[0].enabled = false1582stage.state = STAGE_FROZEN1583end if15841585arrayPos0 = currentPlayer1586arrayPos0 += playerCount15871588if object[arrayPos0].type == invincibilityType1589// Used for when exiting Debug Mode, in order to preserve invincibility1590object[arrayPos0].propertyValue = 31591end if15921593// Remove the player's shield1594object[arrayPos0].type = TypeName[Blank Object]1595player[currentPlayer].shield = SHIELD_NONE1596#platform: USE_ORIGINS1597else1598player[currentPlayer].disableGravity = true1599end if1600#endplatform1601end function160216031604// Handles important stuff called regardless of state1605public function Player_ProcessUpdate1606if options.attractMode == false1607if player.controlMode == CONTROLMODE_P11608#platform: USE_STANDALONE1609CheckTouchRect(0, 96, screen.xcenter, screen.ysize)16101611if checkResult > -11612arrayPos0 = checkResult16131614temp0 = touchscreen[arrayPos0].xpos1615temp0 -= saveRAM[39]16161617temp1 = touchscreen[arrayPos0].ypos1618temp1 -= saveRAM[40]16191620ATan2(temp2, temp0, temp1)16211622temp2 += 321623temp2 &= 2551624temp2 >>= 616251626switch temp21627case 01628keyDown[1].right = true1629break16301631case 11632keyDown[1].down = true1633break16341635case 21636keyDown[1].left = true1637break16381639case 31640keyDown[1].up = true1641break16421643end switch1644end if16451646CheckTouchRect(screen.xcenter, 96, screen.xsize, 240)1647if checkResult > -11648keyDown[1].buttonA = true1649end if16501651if touchJump == false1652keyPress[1].buttonA |= keyDown[1].buttonA1653end if16541655touchJump = keyDown[1].buttonA16561657if stage.debugMode == true1658CheckTouchRect(0, 0, 112, 56)1659if checkResult > -11660keyDown[1].buttonB = true1661end if16621663if touchDebug == false1664keyPress[1].buttonB |= keyDown[1].buttonB1665end if16661667touchDebug = keyDown[1].buttonB1668end if16691670CheckTouchRect(240, 0, screen.xsize, 40)1671if checkResult > -11672// Pause the game if the pause icon was tapped1673PlaySfx(SfxName[Menu Back], false)1674StopSfx(SfxName[Flying])1675StopSfx(SfxName[Jump])1676engine.state = 51677end if16781679if keyPress[1].start == true1680// Pause the game if the start button was pressed1681PlaySfx(SfxName[Menu Back], false)1682StopSfx(SfxName[Flying])1683StopSfx(SfxName[Jump])1684engine.state = 51685end if1686#endplatform16871688#platform: USE_ORIGINS1689if keyPress[1].start == true1690engine.state = 51691end if1692#endplatform1693end if16941695ProcessObjectControl()1696else1697// In attract mode16981699if credits.screen == false1700#platform: USE_STANDALONE1701CheckTouchRect(0, 0, screen.xsize, screen.ysize)17021703if keyPress[0].start == true1704checkResult = false1705end if17061707if checkResult > -11708if Player_attractDuration > 11709Player_attractDuration = 11710end if1711end if17121713if keyPress[0].start == true1714if Player_attractDuration > 11715Player_attractDuration = 11716end if1717end if1718#endplatform17191720#platform: USE_ORIGINS1721if keyPress[1].start == true1722if Player_attractDuration > 11723Player_attractDuration = 11724end if1725end if1726#endplatform1727end if17281729if player.controlMode == CONTROLMODE_P11730Player_attractFrameCount--17311732if Player_attractFrameCount < 11733if Player_attractTablePos < Player_attractTableSize1734// Get and set the player inputs for this frame based on the replay table1735GetTableValue(temp0, Player_attractTablePos, Player_attractTable)1736GetBit(player.up, temp0, 0)1737GetBit(player.down, temp0, 1)1738GetBit(player.left, temp0, 2)1739GetBit(player.right, temp0, 3)1740GetBit(player.jumpPress, temp0, 4)1741GetBit(player.jumpHold, temp0, 5)1742Player_attractTablePos++1743GetTableValue(Player_attractFrameCount, Player_attractTablePos, Player_attractTable)1744Player_attractTablePos++1745end if1746else1747if player.jumpPress == true1748player.jumpPress = false1749end if1750end if17511752// Update replay timer1753if Player_attractDuration > 01754Player_attractDuration--17551756if Player_attractDuration < 1 // Replay over?1757// Start fading out17581759ResetObjectEntity(SLOT_TITLECARD, TypeName[Title Card], 0, 0, 0)1760object[SLOT_TITLECARD].state = TITLECARD_FADETOTITLE1761object[SLOT_TITLECARD].priority = PRIORITY_ACTIVE1762#platform: USE_STANDALONE1763object[SLOT_TITLECARD].drawOrder = 61764#endplatform1765#platform: USE_ORIGINS1766object[SLOT_TITLECARD].drawOrder = 71767#endplatform17681769player.invincibleTimer = 801770camera[0].enabled = false1771end if1772end if1773end if1774end if17751776// Update speed shoes1777if player.speedShoesTimer > 01778player.speedShoesTimer--17791780// Ran out of speed shoes?1781if player.speedShoesTimer < 11782// Reset player speed1783currentPlayer = player.entityPos1784CallFunction(Player_UpdatePhysicsState)17851786// SlowDownMusic is normally a function ID set by the stage's setup script, but if it's not set then don't call it1787if SlowDownMusic != 01788CallFunction(SlowDownMusic)1789end if17901791player.speedShoesTimer = 0 // Reset the speed shoes counter, shouldn't be needed but it doesn't hurt1792end if1793end if17941795// Update invulnerability1796if player.state != Player_State_Hurt // Don't update during knockback1797if player.blinkTimer > 0 // Only update if invulnerable, of course1798player.blinkTimer--17991800GetBit(temp0, player.blinkTimer, 2) // Get the 3rd bit in the variable1801if temp0 == true // Determine whether or not to show the player based on that bit1802player.visible = false1803else1804player.visible = true1805end if1806end if1807end if18081809// Update invincibility1810if player.invincibleTimer > 01811player.invincibleTimer--18121813if player.invincibleTimer == 01814if music.currentTrack == TRACK_INVINCIBLE1815PlayMusic(TRACK_STAGE)1816end if18171818// If the next object in an invincibility effect object, remove it and restore the shield the player had1819if object[+playerCount].type == invincibilityType1820currentPlayer = player.entityPos1821arrayPos0 = currentPlayer1822arrayPos0 += playerCount1823CallFunction(Player_ApplyShield)1824end if1825end if1826end if18271828// If not looking up or down, restore the camera back to normal1829if player.state != Player_State_LookUp1830if player.state != Player_State_Crouch1831if player.lookPosY > 01832player.lookPosY -= 21833end if18341835if player.lookPosY < 01836player.lookPosY += 21837end if1838end if1839end if18401841// Update camera lock (from Spindash or similar)1842if player.scrollDelay > 01843player.scrollDelay--18441845if player.scrollDelay == 01846camera[0].style = CAMERASTYLE_FOLLOW // "Free" the camera1847end if1848end if18491850if player.state != Player_State_Fly1851if player.flightVelocity != 01852StopSfx(SfxName[Flying])1853StopSfx(SfxName[Tired])1854player.flightVelocity = 01855end if1856end if1857end function185818591860// Do nothing!!1861public function Player_State_Static1862checkResult = false1863end function186418651866// Handles animation speed when rolling1867public function Player_HandleRollAnimSpeed1868if player.character == PLAYER_TAILS_A1869// Tails gets a constant anim speed of 1201870player.rollAnimationSpeed = 1201871else1872// S&K's animation speeds are dependant on their speed1873player.rollAnimationSpeed = player.speed18741875// Get the absolute value of their speed1876if player.rollAnimationSpeed < 01877FlipSign(player.rollAnimationSpeed)1878end if18791880// Do some maths to get the final speed1881player.rollAnimationSpeed *= 2401882player.rollAnimationSpeed /= 0x600001883player.rollAnimationSpeed += 481884end if1885end function188618871888// Handles walking animation speed1889// All characters share the same routine1890public function Player_HandleWalkAnimSpeed1891player.animationSpeed = player.speed18921893// Get the absolute value1894if player.animationSpeed < 01895FlipSign(player.animationSpeed)1896end if18971898// Do some maths1899player.animationSpeed *= 601900player.animationSpeed /= 0x600001901player.animationSpeed += 201902end function190319041905// Handles running animation speed1906// Also shared between characters1907public function Player_HandleRunAnimSpeed1908player.animationSpeed = player.speed19091910// Absolute value1911if player.animationSpeed < 01912FlipSign(player.animationSpeed)1913end if19141915// Do some (admittedly less complex) maths to get the final speed1916player.animationSpeed *= 801917player.animationSpeed /= 0x600001918end function191919201921// Handles movement based on things like angles and etc.1922public function Player_HandleGroundMovement1923if player.controlLock > 01924player.controlLock--1925Sin256(temp0, player.angle)1926temp0 *= 0x20001927temp0 >>= 81928player.speed += temp01929else1930if player.left == true1931temp0 = player.topSpeed1932FlipSign(temp0)1933if player.speed > temp01934if player.speed > 01935if player.collisionMode == CMODE_FLOOR1936if player.speed > 0x400001937player.skidding = 161938end if1939end if19401941if player.speed < player.skidSpeed1942player.speed = player.skidSpeed1943FlipSign(player.speed)1944player.skidding = 01945else1946player.speed -= player.skidSpeed1947end if1948else1949player.speed -= player.acceleration1950player.skidding = 01951end if1952end if19531954if player.speed <= 01955player.direction = FACING_LEFT1956end if1957end if19581959if player.right == true1960if player.speed < player.topSpeed1961if player.speed < 01962if player.collisionMode == CMODE_FLOOR1963if player.speed < -0x400001964player.skidding = 161965end if1966end if19671968temp0 = player.skidSpeed1969FlipSign(temp0)1970if player.speed > temp01971player.speed = player.skidSpeed1972player.skidding = 01973else1974player.speed += player.skidSpeed1975end if1976else1977player.speed += player.acceleration1978player.skidding = 01979end if1980end if1981if player.speed >= 01982player.direction = FACING_RIGHT1983end if1984end if19851986temp0 = player.left1987temp0 |= player.right1988if temp0 == false1989if player.speed > 01990player.speed -= player.deceleration1991if player.speed < 01992player.speed = 01993end if1994else1995player.speed += player.deceleration1996if player.speed > 01997player.speed = 01998end if1999end if20002001if player.speed > 0x20002002Sin256(temp0, player.angle)2003temp0 *= 0x20002004temp0 >>= 82005player.speed += temp02006end if20072008if player.speed < -0x20002009Sin256(temp0, player.angle)2010temp0 *= 0x20002011temp0 >>= 82012player.speed += temp02013end if20142015if player.angle > 1922016if player.angle < 2282017if player.speed > -0x100002018if player.speed < 0x100002019player.controlLock = 302020end if2021end if2022end if2023end if20242025if player.angle > 282026if player.angle < 642027if player.speed > -0x100002028if player.speed < 0x100002029player.controlLock = 302030end if2031end if2032end if2033end if2034else2035Sin256(temp0, player.angle)2036temp0 *= 0x20002037temp0 >>= 82038player.speed += temp02039if player.right == true2040if player.left == false2041if player.angle > 1922042if player.angle < 2282043if player.speed < 0x280002044if player.speed > -0x200002045player.controlLock = 302046end if2047end if2048end if2049end if2050end if2051else2052if player.left == true2053if player.angle > 282054if player.angle < 642055if player.speed > -0x280002056if player.speed < 0x200002057player.controlLock = 302058end if2059end if2060end if2061end if2062end if2063end if2064end if20652066if options.speedCap == true2067if player.left == true2068temp0 = player.topSpeed2069FlipSign(temp0)2070if player.speed < temp02071player.speed = temp02072end if2073end if20742075if player.right == true2076if player.speed > player.topSpeed2077player.speed = player.topSpeed2078end if2079end if2080end if2081end if20822083switch player.collisionMode2084case CMODE_LWALL2085if player.angle <= 1922086if player.speed > -0x200002087if player.speed < 0x200002088player.gravity = GRAVITY_AIR2089player.angle = 02090player.collisionMode = CMODE_FLOOR2091player.speed = player.xvel2092end if2093end if2094end if2095break20962097case CMODE_ROOF2098if player.speed > -0x200002099if player.speed < 0x200002100player.gravity = GRAVITY_AIR2101player.angle = 02102player.collisionMode = CMODE_FLOOR2103player.speed = player.xvel2104end if2105end if2106break21072108case CMODE_RWALL2109if player.angle >= 642110if player.speed > -0x200002111if player.speed < 0x200002112player.gravity = GRAVITY_AIR2113player.angle = 02114player.collisionMode = CMODE_FLOOR2115player.speed = player.xvel2116end if2117end if2118end if2119break21202121end switch2122end function212321242125// Handles player movement through the air2126public function Player_HandleAirFriction2127// This little bit of code manages jumping deceleration2128if player.yvel > -0x400002129if player.yvel < 02130// Limit max velocity2131temp0 = player.speed2132temp0 >>= 52133player.speed -= temp02134end if2135end if21362137// Update air control21382139// Moving left?2140temp0 = player.topSpeed2141FlipSign(temp0)2142if player.speed > temp02143if player.left == true2144// Player hasn't reached the speed cap yet, allow them to continue accelerating2145player.speed -= player.airAcceleration2146player.direction = FACING_LEFT2147end if2148else2149// Player has hit speed cap, don't allow them to accelerate further2150if player.left == true2151player.direction = FACING_LEFT2152end if2153end if21542155// Same as above but for moving right2156if player.speed < player.topSpeed2157// Player hasn't hit speed cap yet, allow them to get faster2158if player.right == true2159player.speed += player.airAcceleration2160player.direction = FACING_RIGHT2161end if2162else2163// Player has reached speed cap, stop speeding them up2164if player.right == true2165player.direction = FACING_RIGHT2166end if2167end if21682169// Limit player speed if air speed cap is turned on2170if options.airSpeedCap == true2171// Player is trying to left, use negative version of speed cap2172if player.left == true2173temp0 = player.topSpeed2174FlipSign(temp0)2175if player.speed < temp02176player.speed = temp02177end if2178end if21792180// Player is trying to go right, use normal version of speed cap2181if player.right == true2182if player.speed > player.topSpeed2183player.speed = player.topSpeed2184end if2185end if2186end if21872188#platform: USE_ORIGINS2189if game.playMode == BOOT_PLAYMODE_MISSION2190if stage.timeEnabled == false2191temp1 = screen.yoffset2192temp1 += screen.ysize2193temp1 += 402194if player.iypos > temp12195player.iypos = temp12196end if2197end if2198end if2199#endplatform2200end function220122022203// Handles player rolling on ground. Not to be confused for Player_State_Roll2204public function Player_HandleRollDeceleration2205if player.right == true2206if player.speed < 02207player.speed += player.rollingDeceleration2208end if2209end if22102211if player.left == true2212if player.speed > 02213player.speed -= player.rollingDeceleration2214end if2215end if22162217temp1 = player.speed22182219if player.speed > 02220// Player is moving right22212222player.speed -= player.rollingFriction2223Sin256(temp0, player.angle)22242225if temp0 > 02226Sin256(temp0, player.angle)2227temp0 *= 0x50002228else2229Sin256(temp0, player.angle)2230temp0 *= 0x14002231end if22322233temp0 >>= 82234player.speed += temp02235if player.speed > 0x1200002236player.speed = 0x1200002237end if2238else2239// Player is moving left22402241player.speed += player.rollingFriction2242Sin256(temp0, player.angle)22432244if temp0 < 02245Sin256(temp0, player.angle)2246temp0 *= 0x50002247else2248Sin256(temp0, player.angle)2249temp0 *= 0x14002250end if22512252temp0 >>= 82253player.speed += temp02254if player.speed < -0x1200002255player.speed = -0x1200002256end if2257end if22582259switch player.collisionMode2260case CMODE_FLOOR2261case CMODE_ROOF2262if temp1 > 02263if player.speed < 022642265player.speed = 02266player.state = Player_State_Ground22672268end if2269else2270if player.speed > 022712272player.speed = 02273player.state = Player_State_Ground22742275end if2276end if2277break22782279case CMODE_LWALL2280if player.angle < 1932281if temp1 > 02282if player.speed < 0x200002283player.gravity = GRAVITY_AIR2284player.xvel = 02285player.speed = 02286end if2287end if2288end if2289break22902291case CMODE_RWALL2292if player.angle > 632293if temp1 < 02294if player.speed > -0x200002295player.gravity = GRAVITY_AIR2296player.xvel = 02297player.speed = 02298end if2299end if2300end if2301break2302end switch2303end function23042305// Handles air movement for things like the player jumping and running off an incline2306public function Player_HandleAirMovement2307player.scrollTracking = true23082309#platform: USE_STANDALONE2310player.yvel += player.gravityStrength2311#endplatform23122313#platform: USE_ORIGINS2314// Bug Details:2315// Sonic Team wrapped this in a check, where if you init "Player_Kill" while the stage is finished,2316// -> it disables the gravity of the player (in Mission Mode)2317// However, this check uses the "currentPlayer" array, and while this is no issue for the other characters,2318// -> it used to become one for Tails (as either Tails Object or Player 2 Object)2319// This results in various issues in Origins 2.0.1, such as crashes, Tails losing gravity, etc.2320// This was fixed (kinda) in Origins 2.0.2, see Tails Object.23212322if player[currentPlayer].disableGravity == false2323player.yvel += player.gravityStrength2324end if2325#endplatform23262327if player.yvel < player.jumpCap2328if player.jumpHold == false2329if player.timer > 02330// Limit maximum velocity2331player.yvel = player.jumpCap2332temp0 = player.speed2333temp0 >>= 52334player.speed -= temp02335end if2336end if2337end if23382339player.xvel = player.speed23402341if player.rotation < 2562342if player.rotation > 02343player.rotation -= 42344else2345player.rotation = 02346end if2347else2348if player.rotation < 5122349player.rotation += 42350else2351player.rotation = 02352end if2353end if23542355player.collisionMode = CMODE_FLOOR23562357if player.animation == ANI_JUMPING2358player.animationSpeed = player.rollAnimationSpeed2359end if2360end function236123622363// Set various player values2364public function Player_HandleOnGround2365player.scrollTracking = false23662367Cos256(temp0, player.angle)23682369temp0 *= player.speed2370temp0 >>= 823712372player.xvel = temp023732374Sin256(temp0, player.angle)23752376temp0 *= player.speed2377temp0 >>= 823782379player.yvel = temp02380end function238123822383// This is also set as the player's spindash function if the move is disabled2384public function Player_Action_Jump2385temp1 = false23862387if player.collisionMode == CMODE_FLOOR2388// Check if there's a roof right above the player2389temp6 = player.xpos2390temp7 = player.ypos2391temp0 = player.collisionTop2392temp0 -= 22393ObjectTileCollision(CSIDE_ROOF, 0, temp0, player.collisionPlane)23942395temp1 = checkResult2396player.xpos = temp62397player.ypos = temp72398temp0 = player.collisionBottom2399if player.animation != ANI_JUMPING2400player.iypos -= player.jumpOffset2401temp0 += player.jumpOffset2402end if2403ObjectTileCollision(CSIDE_FLOOR, 0, temp0, player.collisionPlane)2404end if24052406if temp1 == false2407// No roof - start jumping2408player.controlLock = 02409player.gravity = GRAVITY_AIR24102411temp1 = player.jumpStrength2412temp1 += player.gravityStrength24132414Sin256(player.xvel, player.angle)2415player.xvel *= temp124162417Cos256(temp0, player.angle)2418temp0 *= player.speed24192420player.xvel += temp02421player.xvel >>= 824222423Sin256(player.yvel, player.angle)2424player.yvel *= player.speed24252426Cos256(temp0, player.angle)24272428temp0 *= temp124292430player.yvel -= temp02431player.yvel >>= 824322433player.speed = player.xvel24342435player.scrollTracking = true2436player.animation = ANI_JUMPING24372438player.angle = 024392440player.collisionMode = CMODE_FLOOR2441player.timer = 124422443// Set initial animation speed2444CallFunction(Player_HandleRollAnimSpeed)24452446// Set the player's state to one depending if they were previously rolling or not2447if player.state == Player_State_Roll2448player.state = Player_State_RollJump2449else2450player.state = Player_State_Air2451end if24522453#platform: USE_ORIGINS2454currentPlayer = player.entityPos2455CallFunction(Player_CheckIfOnScreen)2456if checkResult != false2457PlaySfx(SfxName[Jump], false)2458end if2459#endplatform24602461#platform: USE_STANDALONE2462PlaySfx(SfxName[Jump], false)2463#endplatform24642465player.collisionDisabled = true24662467// Allow the player to use midair abilities2468player.jumpAbilityState = 12469end if24702471#platform: USE_ORIGINS2472if game.playMode == BOOT_PLAYMODE_CLASSIC2473temp7 = -12474else2475if options.spindash == false // It's neat they tied the Drop Dash to the Spindash setting, they didn't have much of a reason to do that but they did it anyway2476temp7 = -12477else2478temp7 = 02479end if2480end if24812482CallFunction(Player_SetDropDashCharge)2483#endplatform2484end function248524862487// Only starts the spindash, the actual spindash state is Player_State_Spindash2488public function Player_Action_Spindash2489player.state = Player_State_Spindash2490player.animation = ANI_SPINDASH2491player.abilityTimer = 024922493#platform: USE_STANDALONE2494PlaySfx(SfxName[Charge], false)2495#endplatform24962497#platform: USE_ORIGINS2498// Don't play the Charge sound effect if using the Drop Dash2499CheckEqual(player.releasingDropDash, true)2500temp0 = checkResult2501CallFunction(Player_GetDropDashCharge)2502CheckGreater(20, temp7)2503temp0 |= checkResult2504if temp0 == true2505PlaySfx(SfxName[Charge], false)2506end if2507#endplatform25082509// Create dust puff object2510CreateTempObject(TypeName[Dust Puff], player.entityPos, player.xpos, player.ypos)2511object[tempObjectPos].iypos = player.collisionBottom2512object[tempObjectPos].ypos += player.ypos2513object[tempObjectPos].frame = 42514object[tempObjectPos].drawOrder = 42515object[tempObjectPos].direction = player.direction2516end function251725182519// Temporary state for when the player is in their transform animation2520public function Player_State_Transform2521player.collisionDisabled = true25222523// Delay is normally 24 frames, set in the transform script rather than here2524player.timer--2525if player.timer == 02526#platform: USE_STANDALONE2527player.state = Player_State_Air2528#endplatform2529#platform: USE_ORIGINS2530player.state = Player_State_Air_NoDropDash2531#endplatform2532player.animation = ANI_WALKING2533end if2534end function253525362537// Function that transforms the player2538public function Player_TryTransform2539// Only allow the player to transform during the actual level, not when results are showing or other blocking elements2540if stage.timeEnabled == true2541// Spawn the sparkly super trail object2542arrayPos0 = currentPlayer2543arrayPos0 += playerCount2544ResetObjectEntity(arrayPos0, TypeName[Super Spark], 0, player[SLOT_PLAYER1].xpos, player[SLOT_PLAYER1].ypos)2545object[arrayPos0].priority = PRIORITY_ACTIVE25462547PlaySfx(SfxName[Transform], false)2548PlayMusic(2) // Invincibility music2549Player_superState = SUPERSTATE_SUPER2550player[currentPlayer].invincibleTimer = 602551player[currentPlayer].blinkTimer = 02552player[currentPlayer].visible = true25532554CallFunction(Player_UpdatePhysicsState)25552556// Load Super Sonic sprites if Sonic2557if stage.playerListPos == PLAYER_SONIC_A2558LoadAnimation("SuperSonic.ani")2559end if25602561player[currentPlayer].state = Player_State_Transform2562player[currentPlayer].collisionDisabled = true2563player[currentPlayer].animation = ANI_SUPER_TRANSFORM2564player[currentPlayer].timer = 242565end if2566end function256725682569// When the player is falling from a bubble bounce2570public function Player_State_BubbleBounce2571CallFunction(Player_HandleAirFriction)25722573// Check if the player should stop bubble-bouncing25742575// Does the player no longer have the bubble shield?2576CheckNotEqual(player.shield, SHIELD_BUBBLE)2577temp0 = checkResult25782579// Is the player invincible?2580CheckNotEqual(player.invincibleTimer, 0)2581temp0 |= checkResult25822583// Is the player Super?2584CheckEqual(Player_superState, SUPERSTATE_SUPER)2585temp0 |= checkResult25862587if temp0 == true2588// At least one of the checks came back true, go back to normal air falling2589#platform: USE_STANDALONE2590player.state = Player_State_Air2591#endplatform2592#platform: USE_ORIGINS2593player.state = Player_State_Air_NoDropDash2594#endplatform2595else2596if player.gravity == GRAVITY_AIR2597CallFunction(Player_HandleAirMovement)2598else2599// Allow the player to bounce again after rebound2600player.jumpAbilityState = 126012602player.gravity = GRAVITY_AIR26032604// Underwater?2605if player.jumpStrength == 0x380002606temp1 = -0x400002607else2608temp1 = -0x780002609end if26102611temp1 += player.gravityStrength26122613Sin256(player.xvel, player.angle)2614player.xvel *= temp126152616Cos256(temp0, player.angle)2617temp0 *= player.speed26182619player.xvel += temp02620player.xvel >>= 826212622Sin256(player.yvel, player.angle)2623player.yvel *= player.speed26242625Cos256(temp0, player.angle)2626temp0 *= temp126272628player.yvel = temp02629player.yvel >>= 826302631player.speed = player.xvel26322633player.scrollTracking = true2634player.animation = ANI_JUMPING26352636player.angle = 02637player.collisionMode = CMODE_FLOOR2638player.timer = 126392640CallFunction(Player_HandleRollAnimSpeed)26412642#platform: USE_STANDALONE2643player.state = Player_State_Air2644#endplatform2645#platform: USE_ORIGINS2646player.state = Player_State_Air_NoDropDash2647#endplatform26482649PlaySfx(SfxName[Bubble Bounce], false)26502651// Set the bubble shield state to 42652object[+playerCount].state = BUBBLESHIELD_RECOIL_SETUP2653end if2654end if2655end function265626572658// Sonic's ability2659public function Player_Action_DblJumpSonic2660#platform: USE_ORIGINS2661// Handle the super activation2662if keyPress[1].buttonY != false2663// Following checks are to see if Sonic should transform instead of doing arial abilities26642665// Each bit represents an emerald's collected state - 0x7F is 7 1's, AKA 7 emeralds2666CheckEqual(specialStage.emeralds, 0x7F)2667temp0 = checkResult26682669// Player needs to have at least 50 rings2670CheckGreater(player.rings, 49)2671temp0 &= checkResult26722673// Player can't already be Super, of course2674CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2675temp0 &= checkResult26762677// Don't let the player transform if the level is over, either2678CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])2679temp0 &= checkResult26802681if temp0 == true2682// All checks passed, transform!2683currentPlayer = player.entityPos2684CallFunction(Player_TryTransform)2685CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION, 1, 0, 0)2686end if2687end if2688#endplatform26892690// Only act if the jump button is pressed2691if player.jumpPress == true2692#platform: USE_STANDALONE2693// Same code as earlier, so the comments won't be repeated2694CheckEqual(specialStage.emeralds, 0x7F)2695temp0 = checkResult2696CheckGreater(player.rings, 49)2697temp0 &= checkResult2698CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2699temp0 &= checkResult2700CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])2701temp0 &= checkResult2702if temp0 == true2703currentPlayer = player.entityPos2704CallFunction(Player_TryTransform)2705else2706#endplatform2707// Check if the player should do arial abilities27082709// Can't do anything if invincible2710CheckEqual(player.invincibleTimer, 0)2711temp0 = checkResult27122713// Can't do anything if Super, either2714CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2715temp0 &= checkResult27162717if temp0 == true // All checks passed?2718// Determine ability with the player's current shield2719switch player.shield2720case SHIELD_NONE2721if options.shieldType > SHIELDTYPE_S2 // Are S3 shields enabled?2722PlaySfx(SfxName[Insta Shield], false)27232724// Set the shield object slot to hold the insta shield2725if object[+playerCount].type == TypeName[Blank Object]2726currentPlayer = player.entityPos2727arrayPos0 = currentPlayer2728arrayPos0 += playerCount2729ResetObjectEntity(arrayPos0, TypeName[Insta Shield], 0, 0, 0)2730object[arrayPos0].priority = PRIORITY_ACTIVE2731end if27322733player.jumpAbilityState = 227342735// Set insta shield state to active?2736// Side note: this isn't ever used LOL2737object[+playerCount].state = 127382739// Remove roll jump lock2740if player.state == Player_State_RollJump2741player.state = Player_State_Air2742end if2743end if2744break27452746case SHIELD_NORMAL2747// Normal blue shield - no reaction2748break27492750case SHIELD_BUBBLE2751// Start the bubble bounce2752PlaySfx(SfxName[Bubble Bounce], false)27532754player.yvel = 0x800002755player.xvel = 02756player.speed = player.xvel2757player.jumpAbilityState = 22758player.state = Player_State_BubbleBounce27592760// Set the bubble shield state to falling2761object[+playerCount].state = BUBBLESHIELD_BOUNCE_SETUP2762break27632764case SHIELD_FIRE2765PlaySfx(SfxName[Fire Dash], false)27662767// Determine launch direction based on where the player's currently facing2768GetBit(temp0, player.direction, 0)27692770if temp0 == false2771player.xvel = 0x800002772else2773player.xvel = -0x800002774end if27752776player.speed = player.xvel2777player.yvel = 02778player.jumpAbilityState = 227792780// Lock the camera momentarily2781player.scrollDelay = 152782camera[0].style = CAMERASTYLE_HLOCKED27832784// Remove roll jump lock2785if player.state == Player_State_RollJump2786player.state = Player_State_Air2787end if27882789// Set the flame shield to active and make it match the player's direction2790object[+playerCount].state = FIRESHIELD_DASH_SETUP2791object[+playerCount].direction = player.direction2792break27932794case SHIELD_LIGHTNING2795PlaySfx(SfxName[Lightning Jump], false)27962797// Double jump2798player.yvel = -0x580002799player.jumpAbilityState = 228002801// Create the spark objects2802CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)2803object[tempObjectPos].xvel = -0x200002804object[tempObjectPos].yvel = -0x2000028052806CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)2807object[tempObjectPos].xvel = 0x200002808object[tempObjectPos].yvel = -0x2000028092810CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)2811object[tempObjectPos].xvel = -0x200002812object[tempObjectPos].yvel = 0x2000028132814CreateTempObject(TypeName[Lightning Spark], 0, player.xpos, player.ypos)2815object[tempObjectPos].xvel = 0x200002816object[tempObjectPos].yvel = 0x2000028172818// Remove roll jump lock2819if player.state == Player_State_RollJump2820player.state = Player_State_Air2821end if2822break2823end switch2824end if2825#platform: USE_STANDALONE2826end if2827#endplatform2828end if2829end function283028312832// Tails's ability2833public function Player_Action_DblJumpTails2834#platform: USE_ORIGINS2835// Handle the super activation2836if keyPress[1].buttonY != false2837// Following checks are to see if Tails should transform instead of doing arial abilities28382839// Each bit represents an emerald's collected state - 0x7F is 7 1's, AKA 7 emeralds2840CheckEqual(specialStage.emeralds, 0x7F)2841temp0 = checkResult28422843// Player needs to have at least 50 rings2844CheckGreater(player.rings, 49)2845temp0 &= checkResult28462847// Player can't already be Super, of course2848CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2849temp0 &= checkResult28502851// Don't let the player transform if the level is over, either2852CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])2853temp0 &= checkResult28542855if temp0 == true2856// All checks passed, transform!2857currentPlayer = player.entityPos2858CallFunction(Player_TryTransform)2859end if2860end if2861#endplatform28622863// Only act if the jump button is pressed2864if player.jumpPress == true2865#platform: USE_STANDALONE2866// Same code as earlier, so the comments won't be repeated2867CheckEqual(specialStage.emeralds, 0x7F)2868temp0 = checkResult2869CheckGreater(player.rings, 49)2870temp0 &= checkResult2871CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2872temp0 &= checkResult2873CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])2874temp0 &= checkResult2875if temp0 == true2876currentPlayer = player.entityPos2877CallFunction(Player_TryTransform)2878else2879#endplatform2880// Make Tails start flying2881#platform: USE_ORIGINS2882CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION, 0, 1, 0)2883#endplatform2884player.timer = 02885player.state = Player_State_Fly2886player.flightVelocity = 0x8002887if player.gravityStrength == 0x38002888PlaySfx(SfxName[Flying], true)2889player.animation = ANI_FLYING2890else2891player.animation = ANI_SWIMMING2892end if2893#platform: USE_STANDALONE2894end if2895#endplatform2896end if28972898end function289929002901// Knuckles's ability2902public function Player_Action_DblJumpKnux2903#platform: USE_ORIGINS2904// Handle the super activation2905if keyPress[1].buttonY != false2906// Following checks are to see if Knuckles should transform instead of doing arial abilities29072908// Each bit represents an emerald's collected state - 0x7F is 7 1's, AKA 7 emeralds2909CheckEqual(specialStage.emeralds, 0x7F)2910temp0 = checkResult29112912// Player needs to have at least 50 rings2913CheckGreater(player.rings, 49)2914temp0 &= checkResult29152916// Player can't already be Super, of course2917CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2918temp0 &= checkResult29192920// Don't let the player transform if the level is over, either2921CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])2922temp0 &= checkResult29232924if temp0 == true2925// All checks passed, transform!2926currentPlayer = player.entityPos2927CallFunction(Player_TryTransform)2928end if2929end if2930#endplatform29312932// Only act if the jump button is pressed2933if player.jumpPress == true2934#platform: USE_STANDALONE2935// Same code as earlier, so the comments won't be repeated2936CheckEqual(specialStage.emeralds, 0x7F)2937temp0 = checkResult2938CheckGreater(player.rings, 49)2939temp0 &= checkResult2940CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2941temp0 &= checkResult2942CheckNotEqual(object[SLOT_ACTFINISH].type, TypeName[Act Finish])2943temp0 &= checkResult2944if temp0 == true2945currentPlayer = player.entityPos2946CallFunction(Player_TryTransform)2947else2948#endplatform2949// Start gliding2950#platform: USE_ORIGINS2951CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION2, 1, 0, 0)2952#endplatform2953player.speed = 0x400002954if player.yvel < 02955player.yvel = 02956end if29572958if player.direction == FACING_RIGHT2959player.state = Player_State_GlideRight2960player.xvel = 0x400002961player.timer = 02962else2963player.state = Player_State_GlideLeft2964player.xvel = -0x400002965player.timer = 2562966end if29672968player.animation = ANI_GLIDING2969player.frame = 22970#platform: USE_STANDALONE2971end if2972#endplatform2973end if2974end function29752976public function Player_Action_DblJumpAmy2977#platform: USE_ORIGINS2978if keyPress[1].buttonY != false2979CheckEqual(specialStage.emeralds, 0x7F)2980temp0 = checkResult2981CheckGreater(player.rings, 49)2982temp0 &= checkResult2983CheckNotEqual(Player_superState, SUPERSTATE_SUPER)2984temp0 &= checkResult29852986if temp0 == true2987currentPlayer = player.entityPos2988CallFunction(Player_TryTransform)2989end if2990end if29912992if player.jumpPress == true2993PlaySfx(SfxName[HammerJump], false)2994CallNativeFunction4(NotifyCallback, NOTIFY_STATS_CHARA_ACTION2, 0, 1, 0)29952996// Change the animation without resetting the frame or animation speed2997temp0 = player.animationSpeed2998temp1 = player.frame2999player.animation = ANI_HAMMER_JUMP3000ProcessAnimation()3001player.animationSpeed = temp03002player.frame = temp130033004// No states are set here or anything, instead Amy shares Sonic's Drop Dash code seen in Player_HandleDropDash3005end if3006#endplatform3007end function30083009public function Player_Action_HammerDash3010#platform: USE_ORIGINS3011PlaySfx(SfxName[HammerDash], false)30123013player.state = Player_State_HammerDash3014player.animation = ANI_HAMMER_DASH3015player.timer = 030163017temp7 = -13018CallFunction(Player_SetDropDashCharge)3019CallFunction(Player_SetHammerDashSpeed)3020#endplatform3021end function30223023public function Player_State_HammerDash3024#platform: USE_ORIGINS3025if player.right == true3026player.direction = FACING_RIGHT3027else3028if player.left == true3029player.direction = FACING_LEFT3030end if3031end if30323033temp0 = true30343035if player.speed != 03036player.timer++3037if player.jumpHold == true3038if player.timer < 603039CallFunction(Player_SetHammerDashSpeed)3040if player.gravity == GRAVITY_AIR3041CallFunction(Player_HandleAirMovement)3042else3043CallFunction(Player_HandleOnGround)3044end if3045temp0 = false3046end if3047end if3048end if30493050// If Amy is on a steep enough slope, cancel the move3051// (Despite the patch notes for version 2.0.1 claiming this was removed, it's very much still here)3052Cos256(temp1, player.angle)3053if temp1 <= 03054temp0 = true3055end if30563057if temp0 == true3058object.state = Player_State_Ground3059end if3060#endplatform3061end function306230633064public function Player_SetHammerDashSpeed3065#platform: USE_ORIGINS3066if player.direction == FACING_RIGHT3067player.speed = 0x600003068else3069// Could they not have just set it to -0x60000?3070player.speed = 03071player.speed -= 0x600003072end if3073#endplatform3074end function307530763077// Handles activating the Drop Dash (Check Player_State_Air or Player_State_RollJump for releasing it)3078public function Player_HandleDropDash3079#platform: USE_ORIGINS3080if player.releasingDropDash == false3081CallFunction(Player_GetDropDashCharge)3082if temp7 >= 03083if temp7 == 03084if player.jumpPress == true3085switch player.character3086case PLAYER_SONIC_A3087CheckEqual(player.character, PLAYER_SONIC_A) // A bit redundant here, but whatever3088temp0 = checkResult3089// You can't use the Drop Dash with elemental shields3090CheckNotEqual(player.shield, SHIELD_BUBBLE)3091temp0 &= checkResult3092CheckNotEqual(player.shield, SHIELD_FIRE)3093temp0 &= checkResult3094CheckNotEqual(player.shield, SHIELD_LIGHTNING)3095temp0 &= checkResult30963097if temp0 == true3098temp7 = 13099else3100temp7 = -13101end if3102break31033104case PLAYER_AMY_A3105// Amy defies all the odds and is able to Drop Dash with any shield3106temp7 = 13107break3108end switch3109end if3110else3111if player.jumpHold == false3112if temp7 >= 203113temp7 = -13114end if3115else3116temp7++3117if temp7 == 203118PlaySfx(SfxName[DropDash], false)3119end if31203121if temp7 >= 203122// Set Sonic to always use the full ball sprite3123// This code, when placed here, doesn't work properly. Check ObjectUpdate for the same code in a more proper location3124if player.animation == ANI_JUMPING3125if Player_superState == SUPERSTATE_SUPER3126player.frame = 03127else3128player.frame = 43129end if3130player.animationTimer = 03131player.animationSpeed = 13132end if3133end if3134end if3135end if31363137CallFunction(Player_SetDropDashCharge)3138end if3139end if3140#endplatform3141end function31423143// Yes, this is actually how Sonic Team programmed this3144// Note about these next two functions, player.dropdashCount0 and player.dropdashCount1 are global variables, NOT object values3145// Also, the "player.dropdashCount2" and "player.dropdashCount3" values introduced in Origins Plus are unused, this function stayed the same between 1.0.4 and later versions31463147// Preconditions:3148// - temp7 is the value to set the current player's Drop Dash Charge to3149public function Player_SetDropDashCharge3150#platform: USE_ORIGINS3151// Note - P2 should never even be able to Drop Dash in S1, but regardless the two players use separate global vars3152if player.entityPos == SLOT_PLAYER13153player.dropdashCount0 = temp73154else3155player.dropdashCount1 = temp73156end if3157#endplatform3158end function315931603161// Return value:3162// - temp7 will be the value of the current player's Drop Dash Charge3163public function Player_GetDropDashCharge3164#platform: USE_ORIGINS3165if player.entityPos == SLOT_PLAYER13166temp7 = player.dropdashCount03167else3168temp7 = player.dropdashCount13169end if3170#endplatform3171end function317231733174public function Player_CheckIfOnScreen3175#platform: USE_ORIGINS3176// Introduced in Origins 1.0.4. There's a whole CheckCameraProximity function that was introduced in RSDKv5U already, but I guess that wasn't good enough3177// Originally, this used temp0 instead of Player_ScreenPosDiff, but Origins 2.0.0 changed it to fix a bug where this function would overwrite object positions when the player gets crushed3178// (..except they later unfixed it in 2.0.1, see Player_Kill)31793180checkResult = false31813182Player_ScreenPosDiff = screen.xoffset3183Player_ScreenPosDiff -= 203184if player[currentPlayer].ixpos > Player_ScreenPosDiff3185Player_ScreenPosDiff = screen.xoffset3186Player_ScreenPosDiff += screen.xsize3187Player_ScreenPosDiff += 203188if player[currentPlayer].ixpos < Player_ScreenPosDiff3189Player_ScreenPosDiff = screen.yoffset3190Player_ScreenPosDiff -= 403191if player[currentPlayer].iypos > Player_ScreenPosDiff3192Player_ScreenPosDiff = screen.yoffset3193Player_ScreenPosDiff += screen.ysize3194Player_ScreenPosDiff += 403195if player[currentPlayer].iypos < Player_ScreenPosDiff3196checkResult = true3197end if3198end if3199end if3200end if3201#endplatform3202end function320332043205public function Player_State_Ground3206if player.animation != ANI_SKIDDING3207temp7 = true3208else3209temp7 = false3210end if32113212CallFunction(Player_HandleGroundMovement)32133214if player.gravity == GRAVITY_AIR3215#platform: USE_STANDALONE3216player.state = Player_State_Air3217#endplatform3218#platform: USE_ORIGINS3219player.state = Player_State_Air_NoDropDash3220#endplatform3221CallFunction(Player_HandleAirMovement)3222else3223CallFunction(Player_HandleOnGround)32243225if player.speed == 03226if player.collisionMode == CMODE_FLOOR3227#platform: USE_STANDALONE3228if player.timer < 2403229player.animation = ANI_STOPPED3230player.timer++3231else3232player.animation = ANI_WAITING32333234if stage.playerListPos == PLAYER_KNUCKLES_A3235player.timer++32363237if player.timer == 8343238player.timer = 03239player.animation = ANI_STOPPED3240end if3241end if3242end if3243#endplatform32443245// Update balancing animation3246switch player.character3247case PLAYER_SONIC_A3248case PLAYER_TAILS_A3249#platform: USE_ORIGINS3250if player.timer < 2403251player.animation = ANI_STOPPED3252player.timer++3253else3254player.animation = ANI_WAITING3255end if3256#endplatform32573258if player.floorSensorC == false3259if player.floorSensorR == false3260player.timer = 03261player.animation = ANI_FLAILING13262player.direction = FACING_RIGHT3263end if32643265if player.floorSensorL == false3266player.timer = 03267player.animation = ANI_FLAILING13268player.direction = FACING_LEFT3269end if3270end if3271break32723273case PLAYER_KNUCKLES_A3274#platform: USE_ORIGINS3275if player.timer < 2403276player.animation = ANI_STOPPED3277player.timer++3278else3279if player.timer < 5703280player.animation = ANI_WAITING3281player.timer++3282else3283player.animation = ANI_BORED3284player.timer++3285if player.timer == 8423286player.timer = 03287player.animation = ANI_STOPPED3288end if3289end if3290end if3291#endplatform32923293if player.floorSensorC == false3294if player.floorSensorR == false3295player.timer = 03296player.animation = ANI_FLAILING13297if player.direction == FACING_LEFT3298player.prevAnimation = ANI_FLAILING13299player.frame = 43300player.animationTimer = 03301player.animationSpeed = 03302end if33033304player.direction = FACING_RIGHT3305end if33063307if player.floorSensorL == false3308player.timer = 03309player.animation = ANI_FLAILING13310if player.direction == FACING_RIGHT3311player.prevAnimation = ANI_FLAILING13312player.frame = 43313player.animationTimer = 03314player.animationSpeed = 03315end if33163317player.direction = FACING_LEFT3318end if3319end if3320break33213322#platform: USE_ORIGINS3323case PLAYER_AMY_A3324if player.timer < 2403325player.animation = ANI_STOPPED3326player.timer++3327else3328if player.timer < 11073329player.animation = ANI_WAITING3330player.timer++3331else3332player.animation = ANI_BORED3333player.timer++3334if player.timer >= 11523335player.timer = 11073336end if3337end if3338end if33393340if player.floorSensorC == false3341if player.floorSensorR == false3342player.timer = 03343player.animation = ANI_FLAILING13344player.direction = FACING_RIGHT3345end if33463347if player.floorSensorL == false3348player.timer = 03349player.animation = ANI_FLAILING13350player.direction = FACING_LEFT3351end if3352end if3353break3354#endplatform3355end switch3356end if3357else3358player.timer = 03359if player.speed > 03360if player.speed < 0x5F5C23361player.animation = ANI_WALKING3362CallFunction(Player_HandleWalkAnimSpeed)3363else3364if player.speed > 0x9FFFF3365player.animation = ANI_PEELOUT3366else3367player.animation = ANI_RUNNING3368end if33693370CallFunction(Player_HandleRunAnimSpeed)3371end if3372else3373if player.speed > -0x5F5C23374player.animation = ANI_WALKING3375CallFunction(Player_HandleWalkAnimSpeed)3376else3377if player.speed < -0x9FFFF3378player.animation = ANI_PEELOUT3379else3380player.animation = ANI_RUNNING3381end if33823383CallFunction(Player_HandleRunAnimSpeed)3384end if3385end if3386end if33873388if player.skidding > 03389if temp7 == true3390PlaySfx(SfxName[Skidding], false)3391end if33923393player.animation = ANI_SKIDDING3394player.animationSpeed = 03395player.skidding--33963397if ringTimer == 03398CreateTempObject(TypeName[Dust Puff], 0, player.xpos, player.ypos)3399object[tempObjectPos].iypos += player.collisionBottom3400object[tempObjectPos].drawOrder = player.sortedDrawOrder3401end if34023403if player.speed > 03404player.direction = FACING_RIGHT3405else3406player.direction = FACING_LEFT3407end if34083409end if34103411if player.collisionMode == CMODE_FLOOR3412if player.pushing == 23413player.animation = ANI_PUSHING3414player.animationSpeed = 03415end if3416end if34173418if player.jumpPress == true3419CallFunction(Player_Action_Jump)3420else3421if player.up == true3422if player.speed == 03423if player.animation != ANI_FLAILING13424if player.animation != ANI_FLAILING23425player.state = Player_State_LookUp3426player.timer = 03427else3428player.up = false3429player.down = false3430end if3431else3432player.up = false3433player.down = false3434end if3435end if3436end if34373438if player.down == true3439if player.speed == 03440if player.animation != ANI_FLAILING13441if player.animation != ANI_FLAILING23442player.state = Player_State_Crouch3443player.timer = 03444else3445player.up = false3446player.down = false3447end if3448else3449player.up = false3450player.down = false3451end if3452else3453if player.left == false3454if player.right == false34553456if player.speed > 03457if player.speed > 0x88003458// Start rolling3459player.state = Player_State_Roll3460player.animation = ANI_JUMPING3461if player.prevAnimation != ANI_JUMPING3462player.iypos -= player.jumpOffset3463end if3464player.abilityTimer = 0x4003465PlaySfx(SfxName[Rolling], false)3466end if3467else3468if player.speed < -0x88003469// Start rolling3470player.state = Player_State_Roll3471player.animation = ANI_JUMPING3472if player.prevAnimation != ANI_JUMPING3473player.iypos -= player.jumpOffset3474end if3475player.abilityTimer = 0x4003476PlaySfx(SfxName[Rolling], false)3477end if3478end if3479end if3480end if3481end if3482end if3483end if3484end if3485end function348634873488// Prevents the player from using the Drop Dash if they went midair without jumping3489public function Player_State_Air_NoDropDash3490#platform: USE_ORIGINS3491temp7 = -13492CallFunction(Player_SetDropDashCharge)3493player.state = Player_State_Air3494CallFunction(Player_State_Air)3495#endplatform3496end function349734983499public function Player_State_Air3500CallFunction(Player_HandleAirFriction)35013502// Only do this if actually in the air3503if player.gravity == GRAVITY_AIR3504CallFunction(Player_HandleAirMovement)35053506if player.yvel > 0x200003507if player.animation == ANI_FLAILING13508player.animation = ANI_WALKING3509end if35103511if player.animation == ANI_FLAILING23512player.animation = ANI_WALKING3513end if3514end if35153516// After hitting a spring3517if player.animation == ANI_BOUNCING3518if player.yvel >= 03519if player.animationReserve == ANI_STOPPED3520player.animationReserve = ANI_WALKING3521end if3522player.animation = player.animationReserve3523end if3524end if35253526if player.animation == ANI_HURT3527if player.yvel >= 03528if player.animationReserve == ANI_STOPPED3529player.animationReserve = ANI_WALKING3530end if3531player.animation = player.animationReserve3532end if3533end if3534#platform: USE_STANDALONE3535// Allow the player to use their jump ability if these conditions are met3536if player.animation == ANI_JUMPING3537if player.jumpAbilityState == 13538if player.yvel >= player.jumpCap // Did the player actually jump? Rolling off of a ledge shouldn't count!3539CallFunction(player.jumpAbility)3540end if3541end if3542end if3543#endplatform35443545#platform: USE_ORIGINS3546// Allow the player to use their jump ability if these conditions are met3547if player.yvel >= player.jumpCap // Did the player actually jump? Rolling off of a ledge shouldn't count!3548CallFunction(Player_HandleDropDash)3549if player.animation == ANI_JUMPING3550if player.jumpAbilityState == 13551CallFunction(player.jumpAbility)3552end if3553end if3554end if3555#endplatform35563557if player.animation == ANI_SKIDDING3558if player.skidding > 03559player.skidding--3560else3561player.animation = ANI_WALKING3562player.prevAnimation = ANI_WALKING3563player.frame = 03564player.animationSpeed = 403565end if3566end if3567else3568#platform: USE_STANDALONE3569player.state = Player_State_Ground3570CallFunction(Player_HandleOnGround)3571player.skidding = 03572#endplatform35733574#platform: USE_ORIGINS3575CheckEqual(player.releasingDropDash, false)3576temp0 = checkResult3577temp1 = 203578temp1 -= 1 // yep3579CallFunction(Player_GetDropDashCharge)3580CheckGreater(temp7, temp1)3581temp0 &= checkResult35823583if temp0 == true3584switch player.character3585case PLAYER_SONIC_A3586CallFunction(Player_Action_Spindash) // Good ol' Sonic Team programming3587break3588case PLAYER_AMY_A3589CallFunction(Player_Action_HammerDash)3590break3591end switch3592if Player_superState == SUPERSTATE_SUPER3593screen.shakeY = 63594end if3595else3596player.state = Player_State_Ground3597CallFunction(Player_HandleOnGround)3598player.skidding = 03599end if3600#endplatform3601end if3602end function360336043605public function Player_State_TubeAirRoll3606CallFunction(Player_HandleAirFriction)36073608if player.gravity == GRAVITY_AIR3609CallFunction(Player_HandleAirMovement)3610else3611player.state = Player_State_TubeRoll3612CallFunction(Player_HandleOnGround)36133614player.skidding = 03615end if36163617player.animation = ANI_JUMPING3618end function361936203621public function Player_State_Roll3622CallFunction(Player_HandleRollDeceleration)36233624if player.gravity == GRAVITY_AIR3625#platform: USE_STANDALONE3626player.state = Player_State_Air3627#endplatform3628#platform: USE_ORIGINS3629player.state = Player_State_Air_NoDropDash3630#endplatform3631player.timer = 03632CallFunction(Player_HandleAirMovement)3633else3634CallFunction(Player_HandleRollAnimSpeed)36353636player.animationSpeed = player.rollAnimationSpeed3637CallFunction(Player_HandleOnGround)36383639if player.jumpPress == true3640CallFunction(Player_Action_Jump)3641end if3642end if3643end function364436453646// Jumping while rolling leads you to here instead of the normal air function3647public function Player_State_RollJump3648#platform: USE_ORIGINS3649// Origins Plus removed Roll Jump Lock! We should still apply it to attract demos so they don't break, though3650if options.attractMode == true3651#endplatform3652player.left = false3653player.right = false3654#platform: USE_ORIGINS3655end if3656#endplatform36573658CallFunction(Player_HandleAirFriction)36593660if player.gravity == GRAVITY_AIR3661#platform: USE_STANDALONE3662if player.animation == ANI_JUMPING3663if player.jumpAbilityState == 13664if player.yvel >= player.jumpCap3665CallFunction(player.jumpAbility)3666end if3667end if3668end if3669#endplatform36703671#platform: USE_ORIGINS3672if player.yvel >= player.jumpCap3673CallFunction(Player_HandleDropDash)3674if player.animation == ANI_JUMPING3675if player.jumpAbilityState == 13676CallFunction(player.jumpAbility)3677end if3678end if3679end if3680#endplatform36813682CallFunction(Player_HandleAirMovement)3683else3684#platform: USE_STANDALONE3685player.state = Player_State_Ground3686CallFunction(Player_HandleOnGround)3687player.skidding = 03688#endplatform36893690#platform: USE_ORIGINS3691CheckEqual(player.releasingDropDash, false)3692temp0 = checkResult3693temp1 = 203694temp1 -= 1 // yep3695CallFunction(Player_GetDropDashCharge)3696CheckGreater(temp7, temp1)3697temp0 &= checkResult36983699if temp0 == true3700switch player.character3701case PLAYER_SONIC_A3702CallFunction(Player_Action_Spindash) // Good ol' Sonic Team programming3703break37043705case PLAYER_AMY_A3706CallFunction(Player_Action_HammerDash)3707break3708end switch3709if Player_superState == SUPERSTATE_SUPER3710screen.shakeY = 63711end if3712else3713player.state = Player_State_Ground3714CallFunction(Player_HandleOnGround)3715player.skidding = 03716end if3717#endplatform3718end if3719end function372037213722// Also handles moving the camera up3723public function Player_State_LookUp3724if player.up == false3725player.state = Player_State_Ground3726player.timer = 03727else37283729if player.timer < 603730player.timer++3731else3732temp0 = player.ypos3733temp0 >>= 163734temp0 -= camera[0].ypos3735temp0 -= 1123736if player.lookPosY > temp03737player.lookPosY -= 23738end if3739end if37403741player.animation = ANI_LOOKINGUP37423743if player.gravity == GRAVITY_AIR3744#platform: USE_STANDALONE3745player.state = Player_State_Air3746#endplatform3747#platform: USE_ORIGINS3748player.state = Player_State_Air_NoDropDash3749#endplatform3750player.timer = 03751else3752if player.jumpPress == true3753CallFunction(Player_Action_Jump)3754end if3755end if3756end if3757end function375837593760// Also handles moving the camera down3761public function Player_State_Crouch3762if player.down == false3763player.state = Player_State_Ground3764player.timer = 03765else3766if player.timer < 603767player.timer++3768else3769temp0 = player.ypos3770temp0 >>= 163771temp0 -= camera[0].ypos3772temp0 += 963773if player.lookPosY < temp03774player.lookPosY += 23775end if3776end if37773778player.animation = ANI_LOOKINGDOWN37793780if player.gravity == GRAVITY_AIR3781#platform: USE_STANDALONE3782player.state = Player_State_Air3783#endplatform3784#platform: USE_ORIGINS3785player.state = Player_State_Air_NoDropDash3786#endplatform3787player.timer = 03788else3789if player.jumpPress == true3790CallFunction(player[SLOT_PLAYER1].actionSpindash)3791end if3792end if3793end if3794end function379537963797// While the player is charging the spindash3798public function Player_State_Spindash3799if player.gravity == GRAVITY_AIR3800#platform: USE_STANDALONE3801player.state = Player_State_Air3802#endplatform3803#platform: USE_ORIGINS3804player.state = Player_State_Air_NoDropDash3805#endplatform3806player.speed = 03807end if38083809if player.jumpPress == true3810// Rev up the spindash38113812if player.abilityTimer < 0x900003813player.abilityTimer += 0x200003814else3815player.abilityTimer = 0x800003816end if38173818player.frame = 03819PlaySfx(SfxName[Charge], false)3820else3821temp0 = player.abilityTimer3822temp0 >>= 53823player.abilityTimer -= temp03824end if38253826#platform: USE_ORIGINS3827temp1 = player.down3828CheckEqual(player.releasingDropDash, false)3829temp2 = checkResult3830CallFunction(Player_GetDropDashCharge)3831CheckGreater(temp7, 19)3832temp2 &= checkResult38333834if temp2 == true3835temp7 = -13836CallFunction(Player_SetDropDashCharge)3837Sin256(temp0, player.angle)38383839if player.direction == FACING_RIGHT3840if temp0 >= 03841temp0 <<= 123842else3843temp0 <<= 113844end if3845else3846if temp0 >= 03847temp0 <<= 113848else3849temp0 <<= 123850end if3851FlipSign(temp0)3852end if38533854player.abilityTimer = temp03855temp1 = false3856end if38573858if temp1 == false3859#endplatform38603861#platform: USE_STANDALONE3862if player.down == false3863#endplatform3864// Release the spindash!38653866player.timer = 03867player.state = Player_State_Roll3868player.animation = ANI_JUMPING3869player.iypos -= player.jumpOffset38703871if player.entityPos == SLOT_PLAYER13872player.scrollDelay = 153873camera[0].style = CAMERASTYLE_HLOCKED3874end if38753876temp0 = player.abilityTimer3877temp0 >>= 173878temp0 <<= 1638793880if Player_superState == SUPERSTATE_SUPER3881temp0 += 0xB00003882else3883temp0 += 0x800003884end if38853886if player.direction == FACING_RIGHT3887player.speed = temp03888else3889player.speed = temp03890FlipSign(player.speed)3891end if38923893StopSfx(SfxName[Charge])3894PlaySfx(SfxName[Release], false)38953896CallFunction(Player_HandleOnGround)3897end if3898end function389939003901// P2 Tails starts flying for Tails Assist3902public function Player_HandleFlyCarry3903if player.flyCarryTimer != 03904player.flyCarryTimer--3905end if39063907temp0 = player.xpos3908temp1 = player.ypos3909temp1 += 0x1F000039103911if player[SLOT_PLAYER1].animation == ANI_JUMPING3912temp1 += 0x500003913end if39143915temp0 -= player[SLOT_PLAYER1].xpos3916temp1 -= player[SLOT_PLAYER1].ypos39173918if player[SLOT_PLAYER1].state != Player_State_Carried3919CheckEqual(player[SLOT_PLAYER1].gravity, GRAVITY_GROUND)3920temp2 = checkResult3921CheckGreater(player.yvel, 0)3922temp2 &= checkResult3923if temp2 == false3924CheckEqual(player[SLOT_PLAYER1].state, Player_State_Ground)3925temp2 = checkResult3926CheckEqual(player[SLOT_PLAYER1].state, Player_State_Roll)3927temp2 |= checkResult3928CheckEqual(player[SLOT_PLAYER1].state, Player_State_Air)3929temp2 |= checkResult3930CheckEqual(player[SLOT_PLAYER1].state, Player_State_RollJump)3931temp2 |= checkResult3932CheckEqual(player[SLOT_PLAYER1].state, Player_State_LookUp)3933temp2 |= checkResult3934CheckEqual(player[SLOT_PLAYER1].state, Player_State_Crouch)3935temp2 |= checkResult3936if temp2 != false3937temp2 = temp03938Abs(temp2)3939temp3 = temp13940Abs(temp3)3941if temp2 <= 0x800003942if temp3 <= 0x800003943if player.flyCarryTimer == 03944if player[SLOT_PLAYER1].down == false3945player[SLOT_PLAYER1].animation = ANI_HANGING3946player[SLOT_PLAYER1].state = Player_State_Carried3947player[SLOT_PLAYER1].xpos += temp03948player[SLOT_PLAYER1].ypos += temp13949PlaySfx(SfxName[Catch], false)3950end if3951end if3952end if3953end if3954end if3955end if3956end if39573958if player[SLOT_PLAYER1].state == Player_State_Carried3959temp2 = player.xpos3960temp3 = player.ypos3961temp6 = player.xvel3962temp7 = player.yvel39633964ProcessObjectMovement()39653966Player_flyCarryBuddyXPos = player.xpos3967Player_flyCarryBuddyYPos = player.ypos39683969temp4 = player.xpos3970temp4 &= 0xFFFF000039713972temp5 = player.ypos3973temp5 &= 0xFFFF00003974temp5 += 0x1F000039753976player.xpos = temp23977player.ypos = temp33978player.xvel = temp63979player.yvel = temp739803981// "Move" to P1's entity slot3982stage.entityPos = SLOT_PLAYER139833984temp0 = player.xpos3985temp0 &= 0xFFFF00003986temp1 = player.ypos3987temp1 &= 0xFFFF000039883989player.xvel = temp43990player.yvel = temp53991player.xvel -= temp03992player.yvel -= temp139933994ProcessObjectMovement()39953996// "Move" back to P2's entity slot3997stage.entityPos = SLOT_PLAYER239983999player[SLOT_PLAYER1].collisionPlane = player.collisionPlane4000player[SLOT_PLAYER1].speed = player.speed4001player[SLOT_PLAYER1].direction = player.direction40024003Player_flyCarryLeaderXPos = player[SLOT_PLAYER1].xpos4004Player_flyCarryLeaderYPos = player[SLOT_PLAYER1].ypos40054006temp2 = player[SLOT_PLAYER1].xpos4007temp2 &= 0xFFFF00004008temp3 = player[SLOT_PLAYER1].ypos4009temp3 &= 0xFFFF000040104011CheckNotEqual(temp4, temp2)4012temp6 = checkResult4013CheckNotEqual(temp5, temp3)4014temp6 |= checkResult40154016if temp6 == true4017if player[SLOT_PLAYER1].gravity == GRAVITY_GROUND4018player[SLOT_PLAYER1].state = Player_State_Ground4019else4020#platform: USE_STANDALONE4021player[SLOT_PLAYER1].state = Player_State_Air4022#endplatform4023#platform: USE_ORIGINS4024player[SLOT_PLAYER1].state = Player_State_Air_NoDropDash4025#endplatform4026end if40274028player.flyCarryTimer = 30 // 30 frame delay before Sonic can grab Tails again4029end if4030end if4031end function403240334034// Main character gets picked up by P2 Tails4035public function Player_State_Carried4036if player[1].state != Player_State_Fly4037#platform: USE_STANDALONE4038player.state = Player_State_Air4039#endplatform4040#platform: USE_ORIGINS4041player.state = Player_State_Air_NoDropDash4042#endplatform4043end if40444045temp0 = player[1].xpos4046temp0 &= 0xFFFF000040474048temp2 = player.xpos4049temp2 &= 0xFFFF000040504051if player.xpos == Player_flyCarryLeaderXPos4052Player_flyCarryBuddyXPos &= 0xFFFF00004053temp1 = temp04054temp1 -= Player_flyCarryBuddyXPos4055temp2 += temp14056end if40574058if temp0 != temp24059if player.gravity == GRAVITY_GROUND4060player.state = Player_State_Ground4061else4062#platform: USE_STANDALONE4063player.state = Player_State_Air4064#endplatform4065#platform: USE_ORIGINS4066player.state = Player_State_Air_NoDropDash4067#endplatform4068end if4069end if40704071if player.gravity == GRAVITY_GROUND4072if player.yvel >= 04073player.state = Player_State_Ground4074end if4075end if40764077if player.jumpPress != false4078if player.down != false4079if player.gravityStrength == 0x38004080player.yvel = -0x400004081else4082player.yvel = -0x200004083end if4084player.state = Player_State_Air4085player.animation = ANI_JUMPING4086end if4087end if40884089if player.state == Player_State_Carried4090player.xvel = 04091player.yvel = 04092player.speed = 04093else4094player[1].flyCarryTimer = 30 // 30 frame delay before Sonic can grab Tails again4095end if4096end function409740984099// Used by both normal Tails and P2/AI Tails4100public function Player_State_Fly4101CallFunction(Player_HandleAirFriction)41024103if player.gravity == GRAVITY_AIR4104player.xvel = player.speed4105if player.yvel < -0x100004106player.flightVelocity = 0x8004107else4108if player.yvel < 14109if player.abilityTimer < 604110player.abilityTimer++4111else4112player.flightVelocity = 0x8004113end if4114end if4115end if41164117player.yvel += player.flightVelocity41184119if player.ypos < 0x1000004120if player.yvel < 04121player.yvel = 04122end if4123end if41244125CallFunction(Player_HandleFlyCarry)41264127if player.timer < 4804128if player.gravityStrength == 0x38004129if player[SLOT_PLAYER1].state == Player_State_Carried4130if player.yvel < 04131player.animation = ANI_FLY_LIFT_UP4132player.animationSpeed = 2404133else4134player.animation = ANI_FLY_LIFT_DOWN4135player.animationSpeed = 1204136end if4137else4138player.animation = ANI_FLYING4139if player.yvel < 04140player.animationSpeed = 2404141else4142player.animationSpeed = 1204143end if4144end if4145else4146if player[SLOT_PLAYER1].state == Player_State_Carried4147player.animation = ANI_SWIM_LIFT4148else4149player.animation = ANI_SWIMMING4150if player.yvel < 04151player.animationSpeed = 604152else4153player.animationSpeed = 304154end if4155end if4156end if41574158player.timer++41594160if player.timer == 4804161if player.gravityStrength == 0x38004162if player[SLOT_PLAYER1].state == Player_State_Carried4163player.animation = ANI_FLY_LIFT_TIRED4164else4165player.animation = ANI_FLYINGTIRED4166end if4167player.animationSpeed = 1204168StopSfx(SfxName[Flying])4169PlaySfx(SfxName[Tired], true)4170else4171if player[SLOT_PLAYER1].state == Player_State_Carried4172player.animation = ANI_SWIM_LIFT4173else4174player.animation = ANI_SWIMMINGTIRED4175end if4176end if4177else4178if player.jumpPress == true4179CheckNotEqual(player.gravityStrength, 0x3800)4180temp0 = checkResult4181CheckEqual(player[SLOT_PLAYER1].state, Player_State_Carried)4182temp0 &= checkResult4183if temp0 == false4184player.flightVelocity = -0x20004185player.abilityTimer = 04186end if4187end if4188end if4189else4190if player.gravityStrength == 0x38004191if player[SLOT_PLAYER1].state == Player_State_Carried4192player.animation = ANI_FLY_LIFT_TIRED4193else4194player.animation = ANI_FLYINGTIRED4195end if4196else4197if player[SLOT_PLAYER1].state == Player_State_Carried4198player.animation = ANI_SWIM_LIFT4199else4200player.animation = ANI_SWIMMINGTIRED4201end if4202end if4203end if4204else4205player.animation = ANI_WALKING4206player.state = Player_State_Ground4207CallFunction(Player_HandleOnGround)4208end if4209end function421042114212public function Player_State_GlideLeft4213if player.gravity == GRAVITY_AIR4214if player.jumpHold == true4215if player.timer == 2564216if player.speed < 0x1800004217player.speed += 0x4004218end if4219else4220if player.speed < 0x400004221player.speed += 0x10004222end if4223end if42244225if player.yvel > 0x80004226player.yvel -= 0x20004227else4228player.yvel += 0x20004229end if42304231if player.timer < 2564232player.timer += 44233end if42344235if player.timer < 1704236if player.timer > 864237player.frame = 04238else4239if player.timer > 444240player.frame = 14241else4242player.frame = 24243end if4244end if4245else4246if player.timer < 2124247player.frame = 14248else4249player.frame = 24250end if4251end if42524253temp7 = player.xpos4254if player.timer < 1284255player.direction = FACING_RIGHT42564257temp0 = false4258temp1 = false4259else4260player.direction = FACING_LEFT42614262player.xpos = temp74263player.xpos += player.xvel4264player.ypos = player.ypos4265ObjectTileCollision(CSIDE_RWALL, -12, -2, player.collisionPlane)42664267temp0 = checkResult4268temp2 = player.xpos4269player.xpos = temp74270player.xpos += player.xvel4271ObjectTileCollision(CSIDE_RWALL, -12, 11, player.collisionPlane)42724273temp1 = checkResult4274temp3 = player.xpos4275end if42764277Cos(player.xvel, player.timer)4278player.xvel *= player.speed4279player.xvel >>= 94280if player.right == true4281player.state = Player_State_GlideRight4282end if42834284player.xpos = temp74285checkResult = temp04286checkResult &= temp14287if checkResult == true4288if temp2 == temp34289#platform: USE_ORIGINS4290player.animation = ANI_CLIMBING4291player.frame = 04292#endplatform4293player.state = Player_State_Climb4294player.speed = 04295player.xvel = 04296player.yvel = 04297player.timer = 04298PlaySfx(SfxName[Catch], false)4299else4300player.timer = 04301player.xvel >>= 24302player.speed = player.xvel4303player.animation = ANI_GLIDING_DROP4304player.state = Player_State_GlideDrop4305end if4306else4307if temp0 == true4308player.timer = 04309player.xvel >>= 24310player.speed = player.xvel4311player.animation = ANI_GLIDING_DROP4312player.state = Player_State_GlideDrop4313end if4314end if4315else4316player.timer = 04317player.xvel >>= 24318player.speed = player.xvel4319player.animation = ANI_GLIDING_DROP4320player.state = Player_State_GlideDrop4321end if4322else4323if player.collisionMode == CMODE_FLOOR4324player.timer = 04325player.state = Player_State_GlideSlide4326player.animation = ANI_GLIDING_STOP4327player.speed = player.xvel4328else4329player.state = Player_State_Ground4330CallFunction(Player_HandleOnGround)4331player.skidding = 04332end if4333end if43344335temp0 = stage.curYBoundary14336temp0 += 164337temp0 <<= 164338if player.ypos < temp04339player.xvel = 04340player.speed = player.xvel4341end if4342end function434343444345public function Player_State_GlideRight4346if player.gravity == GRAVITY_AIR4347if player.jumpHold == true4348if player.timer == 04349if player.speed < 0x1800004350player.speed += 0x4004351end if4352else4353if player.speed < 0x400004354player.speed += 0x10004355end if4356end if4357if player.yvel > 0x80004358player.yvel -= 0x20004359else4360player.yvel += 0x20004361end if4362if player.timer > 04363player.timer -= 44364end if4365if player.timer < 1704366if player.timer > 864367player.frame = 04368else4369if player.timer > 444370player.frame = 14371else4372player.frame = 24373end if4374end if4375else4376if player.timer < 2124377player.frame = 14378else4379player.frame = 24380end if4381end if4382temp7 = player.xpos4383if player.timer < 1284384player.direction = FACING_RIGHT43854386player.xpos = temp74387player.xpos += player.xvel4388player.ypos = player.ypos4389ObjectTileCollision(CSIDE_LWALL, 12, -2, player.collisionPlane)43904391temp0 = checkResult4392temp2 = player.xpos4393player.xpos = temp74394player.xpos += player.xvel4395ObjectTileCollision(CSIDE_LWALL, 12, 11, player.collisionPlane)43964397temp1 = checkResult4398temp3 = player.xpos4399else4400player.direction = FACING_LEFT4401temp0 = false4402temp1 = false4403end if4404Cos(player.xvel, player.timer)4405player.xvel *= player.speed4406player.xvel >>= 94407if player.left == true4408player.state = Player_State_GlideLeft4409end if4410player.xpos = temp74411checkResult = temp04412checkResult &= temp14413if checkResult == true4414temp2 >>= 14415temp3 >>= 14416if temp2 == temp34417#platform: USE_ORIGINS4418player.animation = ANI_CLIMBING4419player.frame = 04420#endplatform4421player.state = Player_State_Climb4422player.speed = 04423player.xvel = 04424player.yvel = 04425player.timer = 04426PlaySfx(SfxName[Catch], false)4427else4428player.timer = 04429player.xvel >>= 24430player.speed = player.xvel4431player.animation = ANI_GLIDING_DROP4432player.state = Player_State_GlideDrop4433end if4434else4435if temp0 == true4436player.speed = 04437player.timer = 04438player.xvel >>= 24439player.speed = player.xvel4440player.animation = ANI_GLIDING_DROP4441player.state = Player_State_GlideDrop4442end if4443end if4444else4445player.timer = 04446player.xvel >>= 24447player.speed = player.xvel4448player.animation = ANI_GLIDING_DROP4449player.state = Player_State_GlideDrop4450end if4451else4452if player.collisionMode == CMODE_FLOOR4453player.timer = 04454player.state = Player_State_GlideSlide4455player.animation = ANI_GLIDING_STOP4456player.speed = player.xvel4457else4458player.state = Player_State_Ground4459CallFunction(Player_HandleOnGround)4460player.skidding = 04461end if4462end if44634464temp0 = stage.curYBoundary14465temp0 += 164466temp0 <<= 164467if player.ypos < temp04468player.xvel = 04469player.speed = player.xvel4470end if4471end function447244734474public function Player_State_GlideDrop4475if player.gravity == GRAVITY_AIR4476CallFunction(Player_HandleAirFriction)4477CallFunction(Player_HandleAirMovement)4478else4479#platform: USE_ORIGINS4480// Origins Plus added performing actions out of this state like in S3&K, neat!4481if player.jumpPress == true4482player.xvel = 04483player.speed = 04484if player.down == true4485CallFunction(player.actionSpindash)4486else4487CallFunction(Player_Action_Jump)4488end if4489else4490#endplatform4491if player.timer == 04492PlaySfx(SfxName[Landing], false)4493end if44944495player.scrollTracking = false4496player.speed = 04497player.xvel = 04498player.animation = ANI_LOOKINGDOWN4499player.prevAnimation = ANI_LOOKINGDOWN4500player.frame = 245014502if player.timer < 164503player.timer++4504else4505player.state = Player_State_Ground4506CallFunction(Player_HandleOnGround)4507player.skidding = 04508end if4509#platform: USE_ORIGINS4510end if4511#endplatform4512end if4513end function451445154516public function Player_State_GlideSlide4517if player.gravity == GRAVITY_GROUND4518if player.speed == 04519#platform: USE_ORIGINS4520// Origins Plus added performing actions out of this state like in S3&K, neat!4521if player.jumpPress == true4522if player.down == true4523CallFunction(player.actionSpindash)4524else4525CallFunction(Player_Action_Jump)4526end if4527else4528#endplatform4529player.scrollTracking = false4530player.frame = 14531if player.timer < 164532player.timer++4533else4534player.state = Player_State_Ground4535CallFunction(Player_HandleOnGround)4536player.skidding = 04537end if4538#platform: USE_ORIGINS4539end if4540#endplatform4541else4542if ringTimer == 04543CreateTempObject(TypeName[Dust Puff], 0, player.xpos, player.ypos)4544object[tempObjectPos].iypos += player.collisionBottom4545object[tempObjectPos].drawOrder = player.sortedDrawOrder4546if player.timer == 04547PlaySfx(SfxName[Sliding], false)4548player.timer = 14549else4550player.timer = 04551end if4552end if4553player.frame = 04554if player.speed > 04555player.speed -= 0x20004556if player.speed < 04557player.speed = 04558player.timer = 04559end if4560else4561player.speed += 0x20004562if player.speed > 04563player.speed = 04564player.timer = 04565end if4566end if4567if player.jumpHold == false4568player.speed = 04569player.timer = 04570end if4571end if4572player.xvel = player.speed4573else4574player.timer = 04575player.animation = ANI_GLIDING_DROP4576player.state = Player_State_GlideDrop4577end if4578end function457945804581public function Player_State_Climb4582if player.gravity == GRAVITY_AIR4583player.animation = ANI_CLIMBING4584if player.up == true4585if Player_superState == SUPERSTATE_SUPER4586player.yvel = -0x200004587else4588player.yvel = -0x100004589end if45904591temp0 = player.collisionTop4592temp0 *= -0x100004593if player.ypos < temp04594player.ypos = temp04595end if45964597player.timer++4598if player.timer == 44599player.timer = 04600player.frame++4601player.frame %= 64602end if4603else4604if player.down == true4605if Player_superState == SUPERSTATE_SUPER4606player.yvel = 0x200004607else4608player.yvel = 0x100004609end if46104611player.timer++4612if player.timer == 44613player.timer = 04614if player.frame < 14615player.frame += 64616end if4617player.frame--4618end if4619else4620player.yvel = 04621end if4622end if46234624if player.jumpPress == true4625player.animation = ANI_JUMPING4626player.state = Player_State_Air4627player.timer = 046284629PlaySfx(SfxName[Jump], false)4630if player.direction == FACING_LEFT4631player.xvel = 0x400004632player.speed = 0x400004633player.direction = FACING_RIGHT4634else4635player.xvel = -0x400004636player.speed = -0x400004637player.direction = FACING_LEFT4638end if46394640player.yvel = -0x400004641if player.gravityStrength != 0x38004642player.xvel >>= 14643player.speed >>= 14644player.yvel >>= 14645end if4646else4647if player.direction == FACING_RIGHT4648temp2 = player.xpos4649#platform: USE_STANDALONE4650ObjectTileGrip(CSIDE_LWALL, 10, -10, player.collisionPlane)4651#endplatform4652#platform: USE_ORIGINS4653ObjectTileGrip(CSIDE_LENTITY, 10, -10, player.collisionPlane)4654#endplatform465546564657temp0 = checkResult4658temp3 = player.xpos4659player.xpos = temp24660#platform: USE_STANDALONE4661ObjectTileGrip(CSIDE_LWALL, 10, 11, player.collisionPlane)4662#endplatform4663#platform: USE_ORIGINS4664ObjectTileGrip(CSIDE_LENTITY, 10, 11, player.collisionPlane)4665#endplatform46664667temp1 = checkResult4668if player.xpos > temp34669player.xpos = temp34670end if4671else4672temp2 = player.xpos4673#platform: USE_STANDALONE4674ObjectTileGrip(CSIDE_RWALL, -10, -10, player.collisionPlane)4675#endplatform4676#platform: USE_ORIGINS4677ObjectTileGrip(CSIDE_RENTITY, -10, -10, player.collisionPlane)4678#endplatform46794680temp0 = checkResult4681temp3 = player.xpos4682player.xpos = temp24683#platform: USE_STANDALONE4684ObjectTileGrip(CSIDE_RWALL, -10, 11, player.collisionPlane)4685#endplatform4686#platform: USE_ORIGINS4687ObjectTileGrip(CSIDE_RENTITY, -10, 11, player.collisionPlane)4688#endplatform46894690temp1 = checkResult4691if player.xpos < temp34692player.xpos = temp34693end if4694end if46954696if temp0 == false4697#platform: USE_ORIGINS4698if temp1 == 24699player.animation = ANI_GLIDING_DROP4700player.prevAnimation = ANI_GLIDING_DROP4701player.frame = 24702player.timer = 04703player.state = Player_State_GlideDrop4704else4705#endplatform4706player.xpos = temp24707player.animation = ANI_LEDGEPULLUP4708player.yvel = 04709player.timer = 04710player.state = Player_State_LedgePullUp4711player.tileCollisions = false4712if player.direction == FACING_RIGHT4713player.xpos += 0x100004714end if4715#platform: USE_ORIGINS4716end if4717#endplatform4718else4719if temp1 == false4720player.animation = ANI_GLIDING_DROP4721player.prevAnimation = ANI_GLIDING_DROP4722player.frame = 24723player.timer = 04724player.state = Player_State_GlideDrop4725end if4726end if4727end if4728else4729player.animation = ANI_WALKING4730player.state = Player_State_Ground4731CallFunction(Player_HandleOnGround)4732end if4733end function473447354736public function Player_State_Climb_Mission4737#platform: USE_ORIGINS4738// This is a modified version of Player_State_Climb, that allows Knuckles to climb Mission Blocks4739// The Type ID of [Mission Block] should be set in player[0].missionBlockID47404741if player.gravity == GRAVITY_AIR4742player.animation = ANI_CLIMBING4743if player.up == true4744if Player_superState == SUPERSTATE_SUPER4745player.yvel = -0x200004746else4747player.yvel = -0x100004748end if47494750temp0 = player.collisionTop4751temp0 *= -0x100004752if player.ypos < temp04753player.ypos = temp04754end if47554756player.timer++4757if player.timer == 44758player.timer = 04759player.frame++4760player.frame %= 64761end if4762else4763if player.down == true4764if Player_superState == SUPERSTATE_SUPER4765player.yvel = 0x200004766else4767player.yvel = 0x100004768end if47694770player.timer++4771if player.timer == 44772player.timer = 04773if player.frame < 14774player.frame += 64775end if4776player.frame--4777end if4778else4779player.yvel = 04780end if4781end if47824783if player.jumpPress == true4784player.animation = ANI_JUMPING4785player.state = Player_State_Air4786player.timer = 047874788PlaySfx(SfxName[Jump], false)4789if player.direction == FACING_LEFT4790player.xvel = 0x400004791player.speed = 0x400004792player.direction = FACING_RIGHT4793else4794player.xvel = -0x400004795player.speed = -0x400004796player.direction = FACING_LEFT4797end if47984799player.yvel = -0x400004800if player.gravityStrength != 0x38004801player.xvel >>= 14802player.speed >>= 14803player.yvel >>= 14804end if4805else4806if player.direction == FACING_RIGHT4807temp2 = player.xpos4808ObjectTileGrip(CSIDE_LENTITY, 10, -10, player.collisionPlane)4809temp0 = checkResult4810temp3 = player.xpos4811player.xpos = temp24812ObjectTileGrip(CSIDE_LENTITY, 10, 11, player.collisionPlane)4813temp1 = checkResult4814if player.xpos > temp34815player.xpos = temp34816end if4817else4818temp2 = player.xpos4819ObjectTileGrip(CSIDE_RENTITY, -10, -10, player.collisionPlane)4820temp0 = checkResult4821temp3 = player.xpos4822player.xpos = temp24823ObjectTileGrip(CSIDE_RENTITY, -10, 11, player.collisionPlane)4824temp1 = checkResult4825if player.xpos < temp34826player.xpos = temp34827end if4828end if48294830if temp0 == 04831if temp1 == 24832player.animation = ANI_GLIDING_DROP4833player.prevAnimation = ANI_GLIDING_DROP4834player.frame = 24835player.timer = 04836player.state = Player_State_GlideDrop4837else4838player.xpos = temp24839player.animation = ANI_LEDGEPULLUP4840player.yvel = 04841player.timer = 04842player.state = Player_State_LedgePullUp4843player.tileCollisions = false4844if player.direction == FACING_RIGHT4845player.xpos += 0x100004846end if4847end if4848else4849if temp1 == false4850player.animation = ANI_GLIDING_DROP4851player.prevAnimation = ANI_GLIDING_DROP4852player.frame = 24853player.timer = 04854player.state = Player_State_GlideDrop4855end if4856end if4857end if4858else4859player.animation = ANI_WALKING4860player.state = Player_State_Ground4861CallFunction(Player_HandleOnGround)4862end if4863#endplatform4864end function486548664867public function Player_State_LedgePullUp4868switch player.frame4869case 04870if player.timer < 54871ObjectTileGrip(CSIDE_FLOOR, 12, -9, player.collisionPlane)4872player.timer++4873else4874player.timer = 04875player.frame++4876if player.direction == FACING_RIGHT4877player.xpos += 0x900004878else4879player.xpos -= 0x900004880end if4881player.ypos -= 0xA00004882end if4883break48844885case 14886if player.timer < 54887player.timer++4888else4889player.timer = 04890player.frame++4891if player.direction == FACING_RIGHT4892player.xpos += 0x500004893else4894player.xpos -= 0x500004895end if4896player.ypos -= 0x200004897end if4898break48994900case 24901if player.timer < 54902player.timer++4903else4904player.timer = 04905player.animation = ANI_STOPPED4906#platform: USE_STANDALONE4907player.state = Player_State_Air4908#endplatform4909#platform: USE_ORIGINS4910player.state = Player_State_Air_NoDropDash4911#endplatform4912player.ypos -= 0xA00004913player.tileCollisions = true4914end if4915break4916end switch4917end function491849194920public function Player_State_LPullUp_Mission4921#platform: USE_ORIGINS4922// This is a modified version of Player_State_LedgePullUp, to be paired with Player_State_Climb_Mission4923// It's similarly made for pulling Knuckles up on Mission Blocks49244925switch player.frame4926case 04927if player.timer < 54928player.timer++4929else4930player.timer = 04931player.frame++4932if player.direction == FACING_RIGHT4933player.xpos += 0x900004934else4935player.xpos -= 0x900004936end if4937player.ypos -= 0xA00004938end if4939break49404941case 14942if player.timer < 54943player.timer++4944else4945player.timer = 04946player.frame++4947if player.direction == FACING_RIGHT4948player.xpos += 0x500004949else4950player.xpos -= 0x500004951end if4952player.ypos -= 0x200004953end if4954break49554956case 24957if player.timer < 54958player.timer++4959else4960player.timer = 04961player.animation = ANI_STOPPED4962player.state = Player_State_Air_NoDropDash4963player.ypos -= 0xA00004964player.tileCollisions = true4965end if4966break4967end switch4968#endplatform4969end function497049714972// Ouch!4973public function Player_State_GotHit4974#platform: USE_ORIGINS4975temp2 = false4976if game.playMode == BOOT_PLAYMODE_MISSION4977if game.missionFunctionNo == MISSIONNO_MERCY4978if game.missionValue == true4979game.missionValue = false4980temp2 = true4981end if4982end if4983end if4984#endplatform49854986if player.isSidekick == false4987arrayPos0 = player.entityPos4988arrayPos0 += playerCount4989if player.shield != SHIELD_NONE4990temp0 = 14991ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)4992player.shield = SHIELD_NONE4993CheckEqual(options.spikeBehavior, 0)4994temp1 = checkResult4995CheckNotEqual(player.blinkTimer, 0)4996temp1 &= checkResult4997if temp1 == true4998PlaySfx(SfxName[Spike], false)4999else5000PlaySfx(SfxName[Hurt], false)5001end if5002else5003if player[SLOT_PLAYER1].rings == 05004if player.blinkTimer != 05005PlaySfx(SfxName[Spike], false)5006else5007PlaySfx(SfxName[Hurt], false)5008end if5009temp0 = 35010else5011#platform: USE_STANDALONE5012PlaySfx(SfxName[Lose Rings], false)5013temp0 = 25014#endplatform50155016#platform: USE_ORIGINS5017if temp2 == false5018PlaySfx(SfxName[Lose Rings], false)5019temp0 = 25020end if5021#endplatform5022end if5023end if5024else5025temp0 = 15026if player.blinkTimer != 05027PlaySfx(SfxName[Spike], false)5028else5029PlaySfx(SfxName[Hurt], false)5030end if5031end if50325033player.visible = true50345035#platform: USE_ORIGINS5036if temp2 != false5037temp0 = 35038end if5039#endplatform50405041switch temp05042case 1 // Shield recoil, also used by P2 - Ouch!5043player.state = Player_State_Hurt5044player.animation = ANI_HURT5045player.yvel = -0x400005046player.gravity = GRAVITY_AIR5047player.scrollTracking = true5048player.tileCollisions = true5049player.blinkTimer = 1205050if player.gravityStrength == 0x10005051player.speed >>= 15052player.yvel >>= 15053end if5054break50555056case 2 // Lose Rings Recoil - Ouch!5057player.state = Player_State_Hurt5058player.animation = ANI_HURT5059player.yvel = -0x400005060player.gravity = GRAVITY_AIR5061player.scrollTracking = true5062player.tileCollisions = true5063player.blinkTimer = 1205064if player.gravityStrength == 0x10005065player.speed >>= 15066player.yvel >>= 15067end if50685069temp0 = player[SLOT_PLAYER1].rings5070if temp0 > 165071temp1 = temp05072temp1 -= 165073temp0 = 165074else5075temp1 = 05076end if5077if temp1 > 165078temp1 = 165079end if5080temp3 = temp15081temp3 >>= 15082temp3 <<= 55083temp2 = 3845084temp2 -= temp35085temp3 >>= 45086if temp3 == temp15087temp2 += 165088else5089temp2 -= 165090end if50915092temp3 = 05093while temp3 < temp15094CreateTempObject(TypeName[Lose Ring], player.collisionPlane, player.xpos, player.ypos)5095Cos(object[tempObjectPos].xvel, temp2)5096Sin(object[tempObjectPos].yvel, temp2)5097object[tempObjectPos].xvel <<= 85098object[tempObjectPos].yvel <<= 85099object[tempObjectPos].animationSpeed = 2565100object[tempObjectPos].inkEffect = INK_ALPHA5101object[tempObjectPos].alpha = 2565102temp3++5103temp2 += 325104loop5105temp3 = temp05106temp3 >>= 15107temp3 <<= 55108temp2 = 3845109temp2 -= temp35110temp3 >>= 45111if temp3 == temp05112temp2 += 165113else5114temp2 -= 165115end if51165117temp3 = 05118while temp3 < temp05119CreateTempObject(TypeName[Lose Ring], player.collisionPlane, player.xpos, player.ypos)5120Cos(object[tempObjectPos].xvel, temp2)5121Sin(object[tempObjectPos].yvel, temp2)5122object[tempObjectPos].xvel <<= 95123object[tempObjectPos].yvel <<= 95124object[tempObjectPos].animationSpeed = 2565125object[tempObjectPos].inkEffect = INK_ALPHA5126object[tempObjectPos].alpha = 2565127temp3++5128temp2 += 325129loop5130player[SLOT_PLAYER1].rings = 05131ringExtraLife = 1005132break51335134case 3 // Death - Gadzooks!5135#platform: USE_STANDALONE5136player.sortedDrawOrder = 65137#endplatform5138#platform: USE_ORIGINS5139player.sortedDrawOrder = 75140#endplatform5141player.speed = 05142player.yvel = -0x700005143player.xvel = 05144player.state = Player_State_Death5145player.animation = ANI_DYING5146player.tileCollisions = false5147player.interaction = false5148if player.entityPos == SLOT_PLAYER15149player.priority = PRIORITY_ALWAYS5150if object[1].type == TypeName[Player 2 Object]5151object[1].priority = PRIORITY_ALWAYS5152end if5153camera[0].enabled = false5154stage.state = STAGE_FROZEN5155end if51565157if object[+playerCount].type == invincibilityType5158object[+playerCount].propertyValue = 35159end if51605161object[+playerCount].type = TypeName[Blank Object]5162break5163end switch5164end function516551665167// Only knockback, no rings knocked out, no shields lost. Just a little scratch.5168public function Player_State_Hurt5169if player.gravity == GRAVITY_AIR5170player.scrollTracking = true5171if player.gravityStrength == 0x38005172player.yvel += 0x30005173else5174player.yvel += 0xF005175end if5176player.xvel = player.speed5177else5178player.state = Player_State_Ground5179player.speed = 05180player.xvel = 05181CallFunction(Player_HandleOnGround)5182end if5183end function518451855186// Called by the player object itself to die - Gadzooks!5187public function Player_State_Death5188if player.entityPos == SLOT_PLAYER15189if Player_superState == SUPERSTATE_SUPER5190Player_superState = SUPERSTATE_UNTRANSFORM5191end if5192end if51935194// Lock player control5195if player.controlMode != CONTROLMODE_NONE5196player.yvel = -0x700005197player.controlMode = CONTROLMODE_NONE5198end if51995200// Remove player invulnerability and make the player visible5201if player.blinkTimer != 05202player.blinkTimer = 05203player.visible = true5204end if52055206player.yvel += 0x38005207if player.animation != ANI_BORED5208player.animation = ANI_DYING5209end if52105211if player.yvel > 0x1000005212if player.isSidekick == false5213#platform: USE_STANDALONE5214player.lives--5215#endplatform52165217#platform: USE_ORIGINS5218CallNativeFunction2(NotifyCallback, NOTIFY_DEATH_EVENT, 0)5219if game.coinMode == false5220CheckEqual(game.playMode, BOOT_PLAYMODE_BOSSRUSH)5221temp0 = checkResult5222CheckEqual(game.oneStageFlag, false)5223temp0 |= checkResult5224if temp0 != false5225player.lives--5226end if5227end if5228#endplatform52295230stage.timeEnabled = false5231player.type = TypeName[Death Event]5232#platform: USE_STANDALONE5233deathEvent.drawOrder = 65234#endplatform5235#platform: USE_ORIGINS5236deathEvent.drawOrder = 75237#endplatform5238deathEvent.leftTextPos = screen.xcenter5239deathEvent.leftTextPos -= 2645240deathEvent.rightTextPos = screen.xcenter5241deathEvent.rightTextPos += 20052425243if options.gameMode == MODE_TIMEATTACK5244deathEvent.timer = 05245deathEvent.state = DEATHEVENT_DEATH_TA5246else5247if player.lives == 05248deathEvent.timer = -28805249deathEvent.state = DEATHEVENT_GAMEOVER5250PlayMusic(TRACK_GAMEOVER)5251stage.pauseEnabled = false5252#platform: USE_ORIGINS5253if game.oneStageFlag != false5254if game.playMode == BOOT_PLAYMODE_BOSSRUSH5255CallNativeFunction4(NotifyCallback, NOTIFY_STAGE_RETRY, false, stage.listPos, 0)5256end if5257end if5258#endplatform5259else5260deathEvent.timer = 05261deathEvent.state = DEATHEVENT_DEATH52625263#platform: USE_ORIGINS5264if game.coinMode == false5265if game.playMode != BOOT_PLAYMODE_BOSSRUSH5266#endplatform5267// Check for Time Over5268if stage.minutes == 95269if stage.seconds == 595270if stage.milliSeconds == 995271#platform: USE_ORIGINS5272if game.oneStageFlag == false5273#endplatform5274deathEvent.timer = -28805275deathEvent.state = DEATHEVENT_TIMEOVER5276PlayMusic(TRACK_GAMEOVER)5277stage.pauseEnabled = false5278#platform: USE_ORIGINS5279end if5280#endplatform5281end if5282end if5283end if5284#platform: USE_ORIGINS5285end if5286end if5287#endplatform5288end if5289end if5290end if5291end if5292end function529352945295public function Player_State_Drown5296if player.entityPos == SLOT_PLAYER15297if Player_superState == SUPERSTATE_SUPER5298Player_superState = SUPERSTATE_UNTRANSFORM5299end if5300end if53015302player.controlMode = CONTROLMODE_NONE5303player.yvel += player.gravityStrength5304player.animation = ANI_DROWNING5305if player.yvel > 0x800005306if player.isSidekick == false5307#platform: USE_STANDALONE5308if player.lives > 05309player.lives--5310end if5311#endplatform53125313#platform: USE_ORIGINS5314CallNativeFunction2(NotifyCallback, NOTIFY_DEATH_EVENT, 0)5315if game.coinMode == false5316CheckEqual(game.playMode, BOOT_PLAYMODE_BOSSRUSH)5317temp0 = checkResult5318CheckEqual(game.oneStageFlag, false)5319temp0 |= checkResult5320if temp0 != 05321if player.lives > 05322player.lives--5323end if5324end if5325end if5326#endplatform53275328stage.timeEnabled = false5329player.type = TypeName[Death Event]5330#platform: USE_STANDALONE5331deathEvent.drawOrder = 65332#endplatform5333#platform: USE_ORIGINS5334deathEvent.drawOrder = 75335#endplatform5336deathEvent.leftTextPos = screen.xcenter5337deathEvent.leftTextPos -= 2645338deathEvent.rightTextPos = screen.xcenter5339deathEvent.rightTextPos += 20053405341if options.gameMode == MODE_TIMEATTACK5342deathEvent.timer = 05343deathEvent.state = DEATHEVENT_DEATH_TA5344else5345if player.lives == 05346deathEvent.timer = -28805347deathEvent.state = DEATHEVENT_GAMEOVER5348PlayMusic(TRACK_GAMEOVER)5349stage.pauseEnabled = false5350else5351deathEvent.timer = 05352deathEvent.state = DEATHEVENT_DEATH53535354// We don't need the Time Over check here because the player can't drown while already dead5355end if5356end if5357end if5358end if5359end function53605361// Wacky Workbench hanging bar gimmick5362// Unused leftover from CD5363public function Player_State_HangBar5364if player.left == true5365player.direction = FACING_LEFT5366player.speed = -0x200005367player.animationSpeed = 305368else5369if player.right == true5370player.direction = FACING_RIGHT5371player.speed = 0x200005372player.animationSpeed = 305373else5374player.speed = 05375player.animationSpeed = 05376end if5377end if5378temp1 = player.xpos5379temp1 >>= 165380temp2 = player.ypos5381temp2 >>= 165382temp2 += player.collisionTop53835384Get16x16TileInfo(temp0, temp1, temp2, TILEINFO_ANGLEB)5385if temp0 != 3 // this is/was the bar tile flag value5386// and even if this function isn't used in Origins they still updated it there lol5387#platform: USE_STANDALONE5388player.state = Player_State_Air5389#endplatform5390#platform: USE_ORIGINS5391player.state = Player_State_Air_NoDropDash5392#endplatform5393player.speed = 05394player.animationSpeed = 05395player.yvel = 05396end if53975398if player.jumpPress == true5399player.state = Player_State_Air5400player.yvel = 05401player.speed = 05402player.animationSpeed = 05403player.ypos += 0x400005404end if54055406player.xvel = player.speed5407end function54085409// Unused leftover from Sonic Nexus (2008)5410public function Player_State_CorkscrewRun5411player.angle = 05412CallFunction(Player_HandleGroundMovement)5413player.animation = ANI_CORKSCREW_V // Corkscrew animation, it uses Nexus values and as such, it just looks like a jumbled mess in-game54145415if player.speed < 0x600005416if player.speed > -0x600005417player.animation = ANI_WALKING54185419// even if this function is unused, they still updated it for origins lol5420#platform: USE_STANDALONE5421player.state = Player_State_Air5422#endplatform5423#platform: USE_ORIGINS5424player.state = Player_State_Air_NoDropDash5425#endplatform54265427player.rotation = 05428if player.speed < 05429player.direction = FACING_LEFT5430end if5431end if5432end if54335434if player.down == true5435if player.speed > 0x199A5436player.state = Player_State_CorkscrewRoll5437player.animation = ANI_JUMPING5438end if54395440if player.speed < -0x199A5441player.state = Player_State_CorkscrewRoll5442player.animation = ANI_JUMPING5443end if5444end if54455446if player.skidding > 05447if player.skidding == 165448PlaySfx(8, false) // Would be Skidding SFX if using Nexus SFX list, though slot 8 in S1 is SfxName[Destroy]5449end if5450player.animation = ANI_SKIDDING5451player.skidding--5452end if54535454if player.jumpPress == true5455CallFunction(Player_Action_Jump)5456else5457CallFunction(Player_HandleOnGround)5458end if5459end function546054615462// Unused leftover from Sonic Nexus (2008)5463public function Player_State_CorkscrewRoll5464player.angle = 05465CallFunction(Player_HandleRollDeceleration)54665467if player.speed < 0x600005468if player.speed > -0x600005469#platform: USE_STANDALONE5470player.state = Player_State_Air5471#endplatform5472#platform: USE_ORIGINS5473player.state = Player_State_Air_NoDropDash5474#endplatform5475end if5476end if54775478if player.jumpPress == true5479CallFunction(Player_Action_Jump)5480else5481CallFunction(Player_HandleOnGround)5482end if5483end function548454855486public function Player_State_TubeRoll5487#platform: USE_ORIGINS5488temp7 = -15489CallFunction(Player_SetDropDashCharge)5490#endplatform54915492if player.gravity == GRAVITY_AIR5493player.state = Player_State_TubeAirRoll5494player.timer = 05495CallFunction(Player_HandleAirMovement)5496else5497if player.speed > 05498if player.collisionMode == CMODE_FLOOR5499if player.speed < 0x100005500player.speed = 0x400005501end if5502end if5503else5504if player.collisionMode == CMODE_FLOOR5505if player.speed > -0x100005506player.speed = -0x400005507end if5508end if5509end if55105511if player.right == true5512if player.speed < 05513player.speed += player.rollingDeceleration5514end if5515end if55165517if player.left == true5518if player.speed > 05519player.speed -= player.rollingDeceleration5520end if5521end if55225523if player.speed > 05524player.speed -= player.rollingFriction5525Sin256(temp0, player.angle)5526if temp0 > 05527Sin256(temp0, player.angle)5528temp0 *= 0x50005529else5530Sin256(temp0, player.angle)5531temp0 *= 0x1E005532end if5533temp0 >>= 85534player.speed += temp05535else5536player.speed += player.rollingFriction5537Sin256(temp0, player.angle)5538if temp0 < 05539Sin256(temp0, player.angle)5540temp0 *= 0x50005541else5542Sin256(temp0, player.angle)5543temp0 *= 0x1E005544end if5545temp0 >>= 85546player.speed += temp05547end if55485549CallFunction(Player_HandleRollAnimSpeed)5550player.animationSpeed = player.rollAnimationSpeed5551CallFunction(Player_HandleOnGround)5552end if5553end function555455555556// Used when hanging onto the LZ poles against the current5557public function Player_State_Clinging5558player.gravity = GRAVITY_AIR55595560if player.animation != ANI_CLINGING5561player.xvel = 0x800005562player.speed = 0x800005563else5564player.xvel = 05565player.speed = 05566end if55675568if player.up == true5569player.ypos -= 0x100005570else5571if player.down == true5572player.ypos += 0x100005573end if5574end if55755576player.yvel = 05577end function557855795580// Used for LZ's water slides5581public function Player_State_WaterSlide5582if player.gravity == GRAVITY_AIR5583// If the player's in the air, then make them stop sliding5584#platform: USE_STANDALONE5585player.state = Player_State_Air5586#endplatform5587#platform: USE_ORIGINS5588player.state = Player_State_Air_NoDropDash5589#endplatform5590player.angle = 05591player.collisionMode = CMODE_FLOOR5592player.timer = 05593CallFunction(Player_HandleAirMovement)5594player.animation = ANI_WATERSLIDE5595else5596if player.direction == FACING_RIGHT5597player.speed = 0xA00005598else5599player.speed = -0xA00005600end if56015602CallFunction(Player_HandleRollAnimSpeed)56035604player.animation = ANI_WATERSLIDE56055606CallFunction(Player_HandleOnGround)56075608if player.jumpPress == true5609CallFunction(Player_Action_Jump)5610end if5611end if5612end function561356145615public function Player_State_ContinueRun5616if player.speed > 0x100005617player.timer = 056185619if player.speed < 0x5F5C25620player.animation = ANI_WALKING5621CallFunction(Player_HandleWalkAnimSpeed)5622else5623if player.speed > 0x9FFFF5624player.animation = ANI_PEELOUT5625else5626player.animation = ANI_RUNNING5627end if56285629CallFunction(Player_HandleRunAnimSpeed)5630end if5631end if5632end function563356345635// ========================5636// Events5637// ========================56385639event ObjectUpdate5640#platform: USE_ORIGINS5641currentPlayer = player.entityPos5642#endplatform56435644if stage.debugMode == true5645CallFunction(Player_ProcessUpdate)5646CheckEqual(options.attractMode, false)5647temp0 = checkResult5648CheckEqual(keyPress[0].buttonB, true)5649temp0 &= checkResult5650if temp0 == true5651player.type = TypeName[Debug Mode]5652player.yvel = 05653player.state = Player_State_Static5654player.frame = 05655player.rotation = 05656player.interaction = false5657player.drawOrder = 45658player.priority = PRIORITY_ACTIVE5659player.blinkTimer = 05660player.visible = true5661player.abilityTimer = 05662player.drownTimer = 05663player.drownLevel = 05664player.frame = debugMode.currentSelection5665camera[0].enabled = true5666camera[0].style = CAMERASTYLE_FOLLOW5667player.hitboxTop = C_BOX5668player.hitboxBottom = C_BOX5669player.hitboxLeft = C_BOX5670player.hitboxRight = C_BOX56715672if stage.state == STAGE_FROZEN5673stage.state = STAGE_RUNNING5674end if56755676if player[1].type == TypeName[Player 2 Object]5677player[1].priority = PRIORITY_ACTIVE5678end if56795680if object[+playerCount].propertyValue == 35681object[+playerCount].type = invincibilityType5682object[+playerCount].propertyValue = 05683end if5684else5685if player.gravity == GRAVITY_GROUND5686player.jumpAbilityState = 05687end if56885689CallFunction(player.state)56905691// For Origins, they didn't put the Drop Dash "animation" code here...56925693ProcessAnimation()56945695if player.entityPos == camera[0].target5696// Bug Details:5697// This check handles the jump offset so the jump ball sprite isn't higher than it's supposed to be relative to the actual player position5698// In Origins Plus, Amy has a second animation related to being in a jumpball, but this code doesn't take that into account. Whoops!5699if player.animation == ANI_JUMPING5700camera[0].adjustY = player.jumpOffset5701else5702if camera[0].adjustY == player.jumpOffset5703camera[0].adjustY = 05704player.iypos += player.jumpOffset5705end if5706end if5707end if57085709if player.collisionDisabled == false5710temp0 = player.prevGravity5711player.prevGravity = player.gravity5712ProcessObjectMovement()5713player.prevGravity ^= GRAVITY_AIR5714CheckEqual(player.gravity, GRAVITY_GROUND)5715player.prevGravity |= checkResult5716player.prevGravity ^= GRAVITY_AIR57175718if temp0 == GRAVITY_AIR5719if player.prevGravity == GRAVITY_GROUND5720player.badnikBonus = 05721achieveRingCount = 05722if player.animation == ANI_JUMPING5723if player.down == false5724if player.state != Player_State_BubbleBounce5725if player.state != Player_State_Roll5726if player.state != Player_State_TubeRoll5727player.animation = ANI_WALKING5728if player.entityPos == camera[0].target5729camera[0].adjustY = 05730end if5731player.iypos += player.jumpOffset5732end if5733end if5734end if5735end if5736end if5737end if5738end if5739else5740player.collisionDisabled = false5741end if5742end if5743else5744CallFunction(Player_ProcessUpdate)5745if player.gravity == GRAVITY_GROUND5746player.jumpAbilityState = 05747end if57485749CallFunction(player.state)57505751#platform: USE_ORIGINS5752// Set Sonic to always use the full ball sprite while drop dashing5753CallFunction(Player_GetDropDashCharge)5754if temp7 >= 205755if player.animation == ANI_JUMPING5756if Player_superState == SUPERSTATE_SUPER5757player.frame = 05758else5759player.frame = 45760end if5761player.animationTimer = 05762player.animationSpeed = 15763end if5764end if5765#endplatform57665767ProcessAnimation()57685769if player.entityPos == camera[0].target5770// Bug Details: See above5771if player.animation == ANI_JUMPING5772camera[0].adjustY = player.jumpOffset5773else5774if camera[0].adjustY == player.jumpOffset5775camera[0].adjustY = 05776player.iypos += player.jumpOffset5777end if5778end if5779end if57805781if player.collisionDisabled == false5782temp0 = player.prevGravity5783player.prevGravity = player.gravity5784ProcessObjectMovement()5785player.prevGravity ^= GRAVITY_AIR5786CheckEqual(player.gravity, GRAVITY_GROUND)5787player.prevGravity |= checkResult5788player.prevGravity ^= GRAVITY_AIR57895790if temp0 == GRAVITY_AIR5791if player.prevGravity == GRAVITY_GROUND5792player.badnikBonus = 05793achieveRingCount = 05794if player.animation == ANI_JUMPING5795if player.down == false5796if player.state != Player_State_BubbleBounce5797if player.state != Player_State_Roll5798if player.state != Player_State_TubeRoll5799player.animation = ANI_WALKING5800if player.entityPos == camera[0].target5801camera[0].adjustY = 05802end if58035804player.iypos += player.jumpOffset5805end if5806end if5807end if5808end if5809end if5810end if5811end if5812else5813player.collisionDisabled = false5814end if5815end if58165817CallFunction(Player_HandleSuperForm)58185819#platform: USE_ORIGINS5820// Handle preventing the player from moving after defeating a boss in Boss Rush5821if game.playMode == BOOT_PLAYMODE_BOSSRUSH5822if game.missionCondition == MISSION_CONDITION_CLEAR5823player.invincibleTimer = 8058245825// We should do this in every zone *but* Final Zone, since Final Zone handles the following itself5826CheckCurrentStageFolder("BR6Zone06")5827if checkResult == false5828CheckEqual(player[SLOT_PLAYER1].state, Player_State_Ground)5829temp0 = checkResult5830CheckEqual(player[SLOT_PLAYER1].state, Player_State_Static)5831temp0 |= checkResult58325833if temp0 == true5834// Prevent the player from moving anymore5835player[SLOT_PLAYER1].state = Player_State_Static5836player[SLOT_PLAYER1].controlMode = CONTROLMODE_NONE5837player[SLOT_PLAYER1].interaction = false5838player[SLOT_PLAYER1].up = false5839player[SLOT_PLAYER1].down = false5840player[SLOT_PLAYER1].left = false5841player[SLOT_PLAYER1].right = false5842player[SLOT_PLAYER1].jumpHold = false5843player[SLOT_PLAYER1].jumpPress = false5844player[SLOT_PLAYER1].xvel = 05845player[SLOT_PLAYER1].yvel = 05846player[SLOT_PLAYER1].speed = 05847player[SLOT_PLAYER1].animation = ANI_WAITING5848end if5849end if5850end if5851end if5852CallFunction(Player_HandleAmyHitbox)5853#endplatform5854end event585558565857event ObjectDraw5858if player.animation != player.prevAnimation5859player.prevAnimation = player.animation5860player.frame = 05861player.animationTimer = 05862player.animationSpeed = 05863end if58645865DrawObjectAnimation()5866end event586758685869event ObjectStartup5870playerCount = 058715872if options.attractMode == false5873if options.stageSelectFlag == false5874ReadSaveRAM()58755876// Read from the "spindash" option and set things accordingly5877if saveRAM[35] == true5878options.spindash = true5879options.speedCap = false5880options.airSpeedCap = false5881options.spikeBehavior = false5882else5883options.spindash = false5884options.speedCap = true5885options.airSpeedCap = true5886options.spikeBehavior = true5887end if5888end if5889else5890options.spindash = true5891options.speedCap = false5892options.airSpeedCap = false5893options.spikeBehavior = false5894end if58955896foreach (TypeName[Player Object], arrayPos0, ALL_ENTITIES)5897camera[0].enabled = true5898camera[0].style = CAMERASTYLE_FOLLOW5899camera[0].target = 05900currentPlayer = SLOT_PLAYER159015902#platform: USE_STANDALONE5903// Handle S&T5904if stage.playerListPos > PLAYER_KNUCKLES_A // Only true with S&T5905stage.playerListPos = PLAYER_SONIC_A5906stage.player2Enabled = true5907end if5908#endplatform59095910#platform: USE_ORIGINS5911switch stage.playerListPos5912case PLAYER_SONIC_TAILS_A5913stage.playerListPos = PLAYER_SONIC5914stage.player2Enabled = true5915break59165917case PLAYER_AMY_TAILS_A5918stage.playerListPos = PLAYER_AMY5919stage.player2Enabled = true5920break5921end switch5922#endplatform59235924ResetObjectEntity(SLOT_PLAYER1, TypeName[Player Object], 0, object[arrayPos0].xpos, object[arrayPos0].ypos)5925camera[0].xpos = player[SLOT_PLAYER1].ixpos5926camera[0].ypos = player[SLOT_PLAYER1].iypos59275928player[SLOT_PLAYER1].groupID = GROUP_PLAYERS5929#platform: USE_STANDALONE5930player[SLOT_PLAYER1].state = Player_State_Air5931#endplatform5932#platform: USE_ORIGINS5933player[SLOT_PLAYER1].state = Player_State_Air_NoDropDash5934#endplatform5935player[SLOT_PLAYER1].priority = PRIORITY_ACTIVE5936player[SLOT_PLAYER1].drawOrder = DRAWORDER_PLAYER5937player[SLOT_PLAYER1].sortedDrawOrder = 45938player[SLOT_PLAYER1].rollingDeceleration = 0x200059395940if options.spindash == true5941player[SLOT_PLAYER1].actionSpindash = Player_Action_Spindash5942else5943player[SLOT_PLAYER1].actionSpindash = Player_Action_Jump5944end if59455946player[SLOT_PLAYER1].hitboxLeft = C_BOX5947player[SLOT_PLAYER1].hitboxRight = C_BOX5948player[SLOT_PLAYER1].hitboxTop = C_BOX5949player[SLOT_PLAYER1].hitboxBottom = C_BOX59505951Player_superState = SUPERSTATE_NONE5952Player_superRingLossTimer = 05953Player_superBlendClr = 05954Player_superBlendTimer = 059555956// Player specific stuff5957switch stage.playerListPos5958case PLAYER_SONIC_A5959// Even though you never start an act as Super Sonic, loading the animation file on startup will load all the sprites upon startup5960// so that they won't have to load during gameplay instead and cause a notable pause5961LoadAnimation("SuperSonic.ani")5962LoadAnimation("Sonic.ani")59635964CallFunction(Player_HandleSuperPalette_Sonic) // Initialize fur colors59655966#platform: USE_STANDALONE5967player[SLOT_PLAYER1].character = PLAYER_SONIC_A5968#endplatform5969#platform: USE_ORIGINS5970player[SLOT_PLAYER1].character = PLAYER_SONIC5971#endplatform5972player[SLOT_PLAYER1].jumpOffset = -5 // Offset of 5 pixels when rolling5973player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpSonic5974ANI_PEELOUT = ANI_RUNNING // Disable the Peelout animation from showing up5975break59765977case PLAYER_TAILS_A5978// Instead of being a [Player Object], turn the player into a [Tails Object] instead5979player[SLOT_PLAYER1].type = TypeName[Tails Object]5980#platform: USE_STANDALONE5981player[SLOT_PLAYER1].character = PLAYER_TAILS_A5982#endplatform5983#platform: USE_ORIGINS5984player[SLOT_PLAYER1].character = PLAYER_TAILS5985#endplatform59865987CallFunction(Player_HandleSuperPalette_Tails) // Initialize fur colors59885989LoadAnimation("Tails.ani")59905991// As opposed to Sonic & Knuckles' 5 pixel offset,5992// Tails get offset by 1 pixel when rolling since he's shorter5993player[SLOT_PLAYER1].jumpOffset = -159945995player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpTails59965997// Tails can't have Miles following him, unfortunately5998stage.player2Enabled = false59996000// (Tails doesn't disable the "peelout" animation since it's actually his fastest run animation)60016002break60036004case PLAYER_KNUCKLES_A6005LoadAnimation("Knuckles.ani")60066007CallFunction(Player_HandleSuperPalette_Knux) // Initialize fur colors6008#platform: USE_STANDALONE6009player[SLOT_PLAYER1].character = PLAYER_KNUCKLES_A6010#endplatform6011#platform: USE_ORIGINS6012player[SLOT_PLAYER1].character = PLAYER_KNUCKLES6013#endplatform60146015player[SLOT_PLAYER1].jumpOffset = -5 // Offset by 5 pixels when rolling6016player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpKnux6017ANI_PEELOUT = ANI_RUNNING // Disable the Peelout animation from showing up60186019// Force 2P Tails to be off if not on no-save6020// Note this is actually bugged as this only checks for the last three save slots, ignoring the first one6021if options.saveSlot > 06022stage.player2Enabled = false6023end if6024break6025#platform: USE_ORIGINS6026case PLAYER_AMY_A6027LoadAnimation("Amy.ani")6028CallFunction(Player_HandleSuperPalette_Amy)6029player[SLOT_PLAYER1].character = PLAYER_AMY6030player[SLOT_PLAYER1].jumpOffset = -46031player[SLOT_PLAYER1].jumpAbility = Player_Action_DblJumpAmy6032ANI_PEELOUT = ANI_RUNNING6033break6034#endplatform6035end switch60366037if stage.player2Enabled == true6038playerCount = 26039else6040playerCount = 16041end if60426043currentPlayer = SLOT_PLAYER160446045CallFunction(Player_UpdatePhysicsState) // Initialize physics60466047ResetObjectEntity(arrayPos0, TypeName[Blank Object], 0, 0, 0)6048next60496050goggleType = TypeName[Blank Object]6051end event605260536054// ========================6055// Editor Events6056// ========================60576058event RSDKDraw6059DrawSprite(0)6060end event606160626063event RSDKLoad6064LoadSpriteSheet("Players/Sonic1.gif")6065SpriteFrame(-16, -19, 28, 39, 1, 1)60666067// Used in-game, but not to be set from the editor6068SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")6069end event607060716072