0% found this document useful (0 votes)
3 views

Player Object

The document is a script for a Sonic CD Player object, detailing various player attributes, actions, and game mechanics. It includes aliases for player values, functions for player interactions, and collision handling. The script is structured to support different game modes and player states, including actions like jumping, climbing, and handling damage.

Uploaded by

leinnyshidalgo81
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Player Object

The document is a script for a Sonic CD Player object, detailing various player attributes, actions, and game mechanics. It includes aliases for player values, functions for player interactions, and collision handling. The script is structured to support different game modes and player states, including actions like jumping, climbing, and handling damage.

Uploaded by

leinnyshidalgo81
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 86

//----------------Sonic CD Player Object Script---------------//

//--------Scripted by Christian Whitehead 'The Taxman'--------//


//-------Unpacked By Rubberduckycooly's Script Unpacker-------//

// Aliases
#alias Player.Value0 : Player.Rings
#alias Player.Value1 : Player.AbilityTimer
#alias Player.Value2 : Player.RollAnimationSpeed
#alias Player.Value3 : Player.SpeedShoesTimer
#alias Player.Value4 : Player.InvincibleTimer
#alias Player.Value5 : Player.BlinkTimer
#alias Player.Value6 : Player.MinRollSpeed
#alias Player.Value7 : Player.AnimationReserve
#alias Player.Value8 : Player.ScrollDelay
#alias Player.Value9 : Player.JumpOffset
#alias Player.Value10 : Player.JumpAbility
#alias Player.Value11 : Player.ActionPeelout
#alias Player.Value12 : Player.ActionSpindash

// Originally unused in the 2011 release, but Origins gave them a purpose
#alias Player.Value13 : Player.ForceGrounded
#alias Player.Value14 : Player.DropDashCharge

#alias Player.Value15 : Player.FlightVelocity

// Flailing states, v4 names explains this much better


#alias Player.Flailing[0] : Player.FloorSensorL
#alias Player.Flailing[1] : Player.FloorSensorC
#alias Player.Flailing[2] : Player.FloorSensorR

// LoseRing Aliases
#alias Object.Value0 : Object.XVelocity
#alias Object.Value1 : Object.YVelocity

// Warp Star Aliases


#alias Object[3].Value0 : WarpStar.Timer
#alias Object[3].DrawOrder : WarpStar.DrawOrder

// Object Score Alias


#alias Object[26].Value0 : ObjectScore.BadnikBonus

// Pause Menu Aliases


#alias Object[9].DrawOrder : PauseMenu.DrawOrder
#alias Object[9].Priority : PauseMenu.Priority

// Debug Mode Alias


#alias Object[25].Value7 : DebugMode.ButtonA

// Death Event Aliases


#alias Object.Value1 : DeathEvent.Text1XPos // Game or Time
#alias Object.Value2 : DeathEvent.Text2XPos // Over
#alias Object.Value3 : DeathEvent.Timer // Also used for fading
#alias Object.DrawOrder : DeathEvent.DrawOrder
#alias Object.State : DeathEvent.State

// Death Event States


#alias 0 : DEATHEVENT_GAMEOVER
#alias 1 : DEATHEVENT_TIMEOVER
#alias 2 : DEATHEVENT_FADEOUT
#alias 3 : DEATHEVENT_TIMEATTACK

// Priority
#alias 1 : PRIORITY_ACTIVE
#alias 2 : PRIORITY_ALWAYS

// Gravity
#alias 0 : GRAVITY_GROUND
#alias 1 : GRAVITY_AIR

// Player List Pos Aliases


#alias 0 : PLAYER_SONIC_A
#alias 1 : PLAYER_TAILS_A
#alias 2 : PLAYER_KNUCKLES_A
#alias 5 : PLAYER_AMY_A

// Ink
#alias 2 : INK_ALPHA

// Callbacks & Messages


#alias 2 : MESSAGE_LOSTFOCUS

// Cameras
#alias 0 : CAMERASTYLE_FOLLOW
#alias 1 : CAMERASTYLE_EXTENDED
#alias 2 : CAMERASTYLE_EXTENDED_OFFSET_L
#alias 3 : CAMERASTYLE_EXTENDED_OFFSET_R
#alias 4 : CAMERASTYLE_HLOCKED

// Damage Type
#alias 1 : DAMAGE_SHIELDED
#alias 2 : DAMAGE_HURT
#alias 3 : DAMAGE_DEATH

// Collision Modes
#alias 0 : CMODE_FLOOR
#alias 1 : CMODE_LWALL
#alias 2 : CMODE_ROOF
#alias 3 : CMODE_RWALL

// Collision Planes
#alias 0 : COLLISION_PLANE_A

// Collision Sides
#alias 0 : CSIDE_FLOOR
#alias 1 : CSIDE_LWALL
#alias 2 : CSIDE_RWALL
#alias 3 : CSIDE_ROOF
#alias 4 : CSIDE_ENTITY

// Entity Collision Effects


#alias 0 : ECEFFECT_NONE
#alias 1 : ECEFFECT_RESETSTORAGE
#alias 2 : ECEFFECT_BOXCOL3

// Control Modes
#alias -1 : CONTROLMODE_NONE
#alias 0 : CONTROLMODE_NORMAL
// Shield status
#alias 0 : NO_SHIELD
#alias 1 : ACTIVE_SHIELD

// Global SFX
#alias 0 : SFX_G_JUMP
#alias 3 : SFX_G_SKIDDING
#alias 4 : SFX_G_LOSERINGS
#alias 5 : SFX_G_HURT
#alias 6 : SFX_G_CHARGE
#alias 7 : SFX_G_RELEASE
#alias 8 : SFX_G_DESTROY
#alias 24 : SFX_G_FLYING
#alias 25 : SFX_G_TIRED
#alias 26 : SFX_G_OUTTAHERE
#alias 27 : SFX_G_SELECT
#alias 28 : SFX_G_DROPDASH // Origins-exclusive SFX start here
#alias 29 : SFX_G_HAMMERJUMP
#alias 30 : SFX_G_HAMMERDASH
#alias 31 : SFX_G_HAMMERHIT
#alias 32 : SFX_G_SLIDE
#alias 33 : SFX_G_GLIDEDROPLAND
#alias 34 : SFX_G_GRAB

// Game Mode Aliases


#alias 2 : MODE_TIMEATTACK

// Warp Destination
#alias 0 : WARPDEST_NONE

// Mission Functions
#alias 8 : RULE_MERCY_BADNIKS

// Engine Callbacks
#alias 13 : CALLBACK_PAUSE_REQUESTED

// Tile Info
#alias 8 : TILEINFO_ANGLEB

// Function declarations

// Main functions
#function Player_BadnikBreak
#function Player_Hit
#function Player_Kill
#function Player_ProcessUpdate
#function Player_State_Static

// "Physics" functions
#function Player_HandleRollAnimSpeed
#function Player_HandleWalkAnimSpeed
#function Player_HandleRunAnimSpeed
#function Player_HandleGroundMovement
#function Player_HandleAirFriction
#function Player_HandleRollDeceleration
#function Player_HandleAirMovement
#function Player_HandleOnGround
// Move Starters functions
#function Player_Action_Jump
#function Player_Action_Spindash_S2
#function Player_Action_Spindash_CD
#function Player_Action_Peelout_S2
#function Player_Action_Peelout_CD
#function Player_Action_DblJumpTails

// Player Movements
#function Player_State_Ground
#function Player_State_Air_NoDropDash // Origins function
#function Player_State_Air
#function Player_State_Roll
#function Player_State_RollJump // Unused - Leftover from Sonic Nexus
#function Player_State_LookUp
#function Player_State_Crouch
#function Player_State_Spindash_S2
#function Player_State_Spindash_CD
#function Player_State_Peelout_S2
#function Player_State_Peelout_CD
#function Player_State_Fly

// Damage and death


#function Player_State_GotHit
#function Player_State_Hurt
#function Player_State_OuttaHere
#function Player_State_Death
#function Player_State_Drown

// Level Gimmicks
#function Player_State_HangBar
#function Player_State_CorkscrewRun // Unused - Leftover from Sonic Nexus
#function Player_State_CorkscrewRoll // Unused - Leftover from Sonic Nexus
#function Player_State_TubeRoll
#function Player_State_TubeAirRoll
#function Player_State_SpinningTop
#function Player_State_Hugged
#function Player_State_Ramp3D
#function Player_State_WaterCurrent
#function Player_SetJumpOffset
#function Player_State_SizeChange

// Origins Functions
#function Player_HandleDropDash
#function Player_Action_DblJumpKnux
#function Player_State_GlideLeft
#function Player_State_GlideRight
#function Player_State_GlideDrop
#function Player_State_GlideSlide
#function Player_State_Climb
#function Player_State_LedgePullUp
#function Player_State_GlideLeftNoGrip
#function Player_State_GlideRightNoGrip
#function Player_CheckRoofGlide
#function Player_Action_GlideDrop
#function Player_Action_DblJumpAmy
#function Player_Action_HammerDash
#function Player_State_HammerDash
#function Player_SetHammerDashSpeed
#function Player_Setup_Startup

#function Player_ClimbBlock
#function Player_Unstick
#function Player_CancelClimb
#function Player_ForceNoGrip
#function Player_ForceGrip

// Used by badniks, if the conditions are met, they get destroyed, otherwise you
get hurt
function Player_BadnikBreak
CheckEqual(Player.Animation, ANI_JUMPING)
TempValue0 = CheckResult
#platform: Use_Origins
CheckEqual(Player.Animation, ANI_HAMMER_JUMP)
TempValue0 |= CheckResult
CheckEqual(Player.Animation, ANI_HAMMER_DASH)
TempValue0 |= CheckResult
#endplatform
CheckEqual(Player.Animation, ANI_SPINDASH)
TempValue0 |= CheckResult
#platform: Use_Origins
CheckEqual(Player.Animation, ANI_GLIDING)
TempValue0 |= CheckResult
CheckEqual(Player.Animation, ANI_GLIDING_STOP)
TempValue0 |= CheckResult
#endplatform

ArrayPos0 = Player.EntityNo
ArrayPos0 += 2
CheckEqual(Object[ArrayPos0].Type, TypeName[Invincibility])
TempValue0 |= CheckResult

// you're invincible to badniks during the warping run


if Warp.Timer > 0
TempValue0 |= true
end if

if Player.Animation == ANI_FLYING
CheckGreater(Player.YPos, Object.YPos)
TempValue0 |= CheckResult
end if

#platform: Use_Origins
if game.playMode == BOOT_PLAYMODE_MISSION
if Stage.TimeEnabled == false
TempValue0 = false
end if
end if
#endplatform

if TempValue0 == true
ResetObjectEntity(Object.EntityNo, Flower_TypeNo, 0, Object.XPos,
Object.YPos)
Object.DrawOrder = 4

CreateTempObject(TypeName[Smoke Puff], 0, Object.XPos, Object.YPos)


Object[TempObjectPos].DrawOrder = 4
CreateTempObject(TypeName[Object Score], ObjectScore.BadnikBonus,
Object.XPos, Object.YPos)
Object[TempObjectPos].DrawOrder = 4
TempValue0 = false
#platform: Use_Origins
if Player.Animation == ANI_HAMMER_JUMP
TempValue0 = true
end if

if Player.Animation == ANI_HAMMER_DASH
TempValue0 = true
end if
#endplatform
if TempValue0 == true
PlaySfx(SFX_G_HAMMERHIT, false)
else
PlaySfx(SFX_G_DESTROY, false)
end if

if Player.YVelocity > 0
FlipSign(Player.YVelocity)
else
Player.YVelocity += 0xC000
end if

switch ObjectScore.BadnikBonus
case 0
Player.Score += 100
break
case 1
Player.Score += 200
break
case 2
Player.Score += 500
break
case 3
Player.Score += 1000
break
end switch

// (Normally the Badnik Bonus would be updated here, but 2011 does that
in the Object Score script instead? That makes things kinda weird though, check out
that script for more info)

#platform: Use_Haptics
HapticEffect(10, 0, 0, 0)
#endplatform

#platform: Use_Origins
TempValue0 = 0
game.callbackParam0 = 0
CheckEqual(Player.State, Player_State_Roll)
TempValue0 = CheckResult
CheckEqual(Player.State, Player_State_RollJump)
TempValue0 |= CheckResult
if TempValue0 == true
if Stage.PlayerListPos == PLAYER_SONIC
game.callbackParam0 = KILL_ENEMY_ATTR_SPINDASH
StageStatsUsabilityParam2 += 1
end if
end if

StageStatsUsabilityParam1 += 1
EngineCallback(NOTIFY_KILL_ENEMY)
if game.playMode == BOOT_PLAYMODE_MISSION
// Set during "M097 - Mercy"
if game.missionFunctionNo == RULE_MERCY_BADNIKS
game.forceKillPlayer = true
end if
end if
#endplatform
else
if Player.InvincibleTimer == 0
Player.State = Player_State_GotHit

#platform: Use_Origins
if game.playMode == BOOT_PLAYMODE_MISSION
if game.missionFunctionNo == RULE_MERCY_BADNIKS
game.missionValue = 1
end if
end if
#endplatform

if Player.XPos > Object.XPos


Player.Speed = 0x20000
else
Player.Speed = -0x20000
end if
end if
end if
end function

// Do you really need an explanation?


function Player_Hit
ArrayPos0 = Player.EntityNo
ArrayPos0 += 2
if Object[ArrayPos0].Type != TypeName[Invincibility]
if Player.InvincibleTimer == 0
Player.State = Player_State_GotHit
if Player.XPos > Object.XPos
Player.Speed = 0x20000
else
Player.Speed = -0x20000
end if
end if
end if
end function

// Called by block objects to see if Knuckles should climb them


// (Note that the block object needs to have called C_BOX3 before calling this
function)
function Player_ClimbBlock
#platform: Use_Origins
if Player.State != Player_State_Climb
TempValue0 = false
ArrayPos0 = 32
if Player.State == Player_State_GlideRightNoGrip // Nothing for a left
glide?
TempValue0 = true
else
while ArrayPos0 < 1056
if Object[ArrayPos0].Type == TypeName[Blank Object] // huh?
maybe this is supposed to be [NoGripArea], but you can't use stage object TypeNames
in global objects...
if Object[ArrayPos0].Value0 == true
TempValue0 = true
end if
end if
ArrayPos0++
loop
end if

if TempValue0 == false
if Player.Direction == FACING_LEFT
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, false,
ECEFFECT_BOXCOL3)
else
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, false,
ECEFFECT_BOXCOL3)
end if
PlaySfx(SFX_G_GRAB, false)
Player.State = Player_State_Climb
Player.Speed = 0
Player.XVelocity = 0
Player.YVelocity = 0
Player.Timer = 0
Player.Gravity = GRAVITY_AIR
game.callbackParam0 = 2
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
end if
end if
#endplatform
end function

// These two functions are pretty similar, the former makes Knuckles cancel a climb
into a glide drop, while the latter cancels a climb into normal air movement,
instead

// See above, this one's p much only called by NoGripArea's


function Player_Unstick
#platform: Use_Origins
CallFunction(Player_Action_GlideDrop)
Player.PrevAnimation = ANI_GLIDING_DROP
Player.Frame = 2
#endplatform
end function
// See above, this one's p much only called by Bumpers
function Player_CancelClimb
#platform: Use_Origins
Player.Animation = ANI_WALKING
Player.Timer = 0
Player.State = Player_State_Air_NoDropDash
#endplatform
end function

// Called by No Grip Area objects to, well, force No Grip gliding


function Player_ForceNoGrip
#platform: Use_Origins
if Player.State == Player_State_GlideLeft
Player.State = Player_State_GlideLeftNoGrip
end if

if Player.State == Player_State_GlideRight
Player.State = Player_State_GlideRightNoGrip
end if
#endplatform
end function

// Called by No Grip Area objects to restore normal gliding


function Player_ForceGrip
#platform: Use_Origins
if Player.State == Player_State_GlideLeftNoGrip
Player.State = Player_State_GlideLeft
end if

if Player.State == Player_State_GlideRightNoGrip
Player.State = Player_State_GlideRight
end if
#endplatform
end function

// YOU DIED
function Player_Kill
PlaySfx(SFX_G_HURT, false)

Player.DrawOrder = 5

Player.Speed = 0
Player.XVelocity = 0
Player.YVelocity = -0x68000

Player.State = Player_State_Death
Player.Animation = ANI_DYING

Player.TileCollisions = false
Player.ObjectInteraction = false
Screen.CameraEnabled = false

#platform: Use_Haptics
HapticEffect(28, 0, 0, 0)
#endplatform
end function

function Player_ProcessUpdate
#platform: Standard
if Options.AttractMode == false
if Player.ControlMode == CONTROLMODE_NORMAL
if Object[9].Type == TypeName[Blank Object]
if KeyPress[1].Start == true
KeyPress[1].Start = false
if Options.DevMenuFlag == true
Stage.State = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
PauseMenu.DrawOrder = 7
PauseMenu.Priority = PRIORITY_ALWAYS
else
EngineCallback(CALLBACK_PAUSE_REQUESTED) // ask
the engine to open the "native" pause menu
end if
end if
end if
end if

ProcessPlayerControl()
end if
#endplatform

#platform: Use_Decomp
if Options.AttractMode == false
if Player.ControlMode == CONTROLMODE_NORMAL
if Object[9].Type == TypeName[Blank Object]
if Engine.Message == MESSAGE_LOSTFOCUS
Stage.State = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
PauseMenu.DrawOrder = 7
PauseMenu.Priority = PRIORITY_ALWAYS
if Engine.FrameSkipTimer > -1
Engine.FrameSkipTimer = -1
end if
end if
end if
end if
end if
#endplatform

#platform: Mobile
if Options.AttractMode == false
if Options.TouchControls == true
if Player.ControlMode == CONTROLMODE_NORMAL
CheckTouchRect(0, 96, Screen.CenterX, Screen.YSize)
if CheckResult > -1
ArrayPos0 = CheckResult
// D-Pad XPos
TempValue0 = TouchScreen[ArrayPos0].XPos
TempValue0 -= Options.DPadX
// D-Pad YPos
TempValue1 = TouchScreen[ArrayPos0].YPos
TempValue1 -= 192

// tldr; check what did you touch in the d-pad


ATan2(TempValue2, TempValue0, TempValue1)
TempValue2 += 32
TempValue2 &= 255
TempValue2 >>= 6
switch TempValue2
case 0
KeyDown[1].Right = true
break
case 1
KeyDown[1].Down = true
break
case 2
KeyDown[1].Left = true
break
case 3
KeyDown[1].Up = true
break
end switch
end if

CheckTouchRect(Screen.CenterX, 96, Screen.XSize, 240)


if CheckResult > -1
KeyDown[1].ButtonA = true
end if

if DebugMode.ButtonA == false
KeyPress[1].ButtonA |= KeyDown[1].ButtonA
end if

DebugMode.ButtonA = KeyDown[1].ButtonA
if Object[9].Type == TypeName[Blank Object]

CheckTouchRect(240, 0, Screen.XSize, 40)


if CheckResult > -1
Stage.State = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
PauseMenu.DrawOrder = 7
PauseMenu.Priority = PRIORITY_ALWAYS
if Engine.FrameSkipTimer > -1
Engine.FrameSkipTimer = -1
end if

end if

if Engine.Message == MESSAGE_LOSTFOCUS
Stage.State = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
PauseMenu.DrawOrder = 7
PauseMenu.Priority = PRIORITY_ALWAYS
if Engine.FrameSkipTimer > -1
Engine.FrameSkipTimer = -1
end if
end if
end if
end if
else
if Player.ControlMode == CONTROLMODE_NORMAL
if Object[9].Type == TypeName[Blank Object]
if KeyPress[1].Start == true

KeyPress[1].Start = false
Stage.State = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
PauseMenu.DrawOrder = 7
PauseMenu.Priority = PRIORITY_ALWAYS
if Engine.FrameSkipTimer > -1
Engine.FrameSkipTimer = -1
end if
end if

if Engine.Message == MESSAGE_LOSTFOCUS
Stage.State = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
PauseMenu.DrawOrder = 7
PauseMenu.Priority = PRIORITY_ALWAYS
if Engine.FrameSkipTimer > -1
Engine.FrameSkipTimer = -1
end if
end if
end if
end if
end if

ProcessPlayerControl()
end if
#endplatform

// Speed Shoes control


if Player.SpeedShoesTimer > 0
Player.SpeedShoesTimer--
if Player.SpeedShoesTimer == 0
Player.Acceleration = 0xC00
Player.AirAcceleration = 0x1800
Player.TopSpeed = 0x60000
if Music.CurrentTrack == 3 // Speed Shoes
PlayMusic(0)
end if
end if
end if

// Invincibility Control
if Player.InvincibleTimer > 0
if Player.State != Player_State_Hurt
if Player.InvincibleTimer > 2000
Player.InvincibleTimer = 120
Player.BlinkTimer = 3
end if
end if

if Player.BlinkTimer > 0
Player.BlinkTimer++
if Player.BlinkTimer > 8
Player.BlinkTimer = 1
end if
if Player.BlinkTimer > 4
Player.Visible = false
else
Player.Visible = true
end if
end if

Player.InvincibleTimer--
if Player.InvincibleTimer == 0
Player.BlinkTimer = 0
Player.Visible = true
if Music.CurrentTrack == 2 // Invincibility
PlayMusic(0)
end if
if Object[+2].Type == TypeName[Invincibility]
switch Object[+2].PropertyValue
case NO_SHIELD
TempValue0 = Player.EntityNo
TempValue0 += 2
ResetObjectEntity(TempValue0, TypeName[Blank Object],
0, 0, 0)
break

case ACTIVE_SHIELD
TempValue0 = Player.EntityNo
TempValue0 += 2
ResetObjectEntity(TempValue0, TypeName[Blank Object],
0, 0, 0)
Object[+2].Type = TypeName[Blue Shield]
Object[+2].PropertyValue = ACTIVE_SHIELD
Object[+2].Priority = PRIORITY_ACTIVE
Object[+2].DrawOrder = 4
Object[+2].InkEffect = INK_ALPHA
Object[+2].Alpha = 160
Object[+2].XPos = Player.XPos
Object[+2].YPos = Player.YPos
break

end switch
end if
end if
end if
// Restore camera position after looking up / crounching
if Player.State != Player_State_LookUp
if Player.State != Player_State_Crouch
if Player.LookPos > 0
Player.LookPos -= 2
end if

if Player.LookPos < 0
Player.LookPos += 2
end if
end if
end if

if Warp.Timer > 0
Warp.Timer++

if Warp.Timer == 204
Screen.CameraEnabled = false
CreateTempObject(TypeName[Time Warp], 0, 0, 0)
#platform: Use_Standalone
Object[TempObjectPos].DrawOrder = 6
#endplatform
#platform: Use_Origins
Object[TempObjectPos].DrawOrder = 7
#endplatform
end if
end if

// Keeps the camera in place for a bit after releasing S2 Spin Dash
if Player.ScrollDelay > 0
Player.ScrollDelay--
if Player.ScrollDelay == 0
Screen.CameraStyle = CAMERASTYLE_FOLLOW
end if
end if

// Resets FlightVelocity
if Player.State != Player_State_Fly
if Player.FlightVelocity != 0
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Player.FlightVelocity = 0
end if
end if

end function

// Do nothing!!
function Player_State_Static
CheckResult = false
end function

// Updates animation speed while rolling


function Player_HandleRollAnimSpeed
if Stage.PlayerListPos == PLAYER_TAILS_A
Player.RollAnimationSpeed = 120
else
Player.RollAnimationSpeed = Player.Speed
if Player.RollAnimationSpeed < 0
FlipSign(Player.RollAnimationSpeed)
end if
Player.RollAnimationSpeed *= 240
Player.RollAnimationSpeed /= 0x60000
Player.RollAnimationSpeed += 48
end if
end function

// Animation speed while walking


function Player_HandleWalkAnimSpeed
Player.AnimationSpeed = Player.Speed
if Player.AnimationSpeed < 0
FlipSign(Player.AnimationSpeed)
end if
Player.AnimationSpeed *= 60
Player.AnimationSpeed /= 0x60000
Player.AnimationSpeed += 20
end function

// Animation speed while running


function Player_HandleRunAnimSpeed
Player.AnimationSpeed = Player.Speed
if Player.AnimationSpeed < 0
FlipSign(Player.AnimationSpeed)
end if
Player.AnimationSpeed *= 80
Player.AnimationSpeed /= 0x60000
end function

// This makes you move


function Player_HandleGroundMovement
if Player.ControlLock > 0
Player.ControlLock--
Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x2000
TempValue0 >>= 8
Player.Speed += TempValue0
else
if Player.Left == true
TempValue0 = Player.TopSpeed
FlipSign(TempValue0)
if Player.Speed > TempValue0
if Player.Speed > 0
if Player.CollisionMode == CMODE_FLOOR
// Skid
if Player.Speed > 0x40000
Player.Skidding = 16
end if
end if

if Player.Speed < 0x8000


Player.Speed = -0x8000
Player.Skidding = 0
else
Player.Speed -= 0x8000
end if
else
Player.Speed -= Player.Acceleration
Player.Skidding = 0
end if
end if

if Player.Speed <= 0
Player.Direction = FACING_LEFT
end if
end if

if Player.Right == true
if Player.Speed < Player.TopSpeed
if Player.Speed < 0
if Player.CollisionMode == CMODE_FLOOR
// Skid
if Player.Speed < -0x40000
Player.Skidding = 16
end if
end if

if Player.Speed > -0x8000


Player.Speed = 0x8000
Player.Skidding = 0
else
Player.Speed += 0x8000
end if
else
Player.Speed += Player.Acceleration
Player.Skidding = 0
end if
end if

if Player.Speed >= 0
Player.Direction = FACING_RIGHT
end if
end if

TempValue0 = Player.Left
TempValue0 |= Player.Right
if TempValue0 == false
//tldr, reduce speed with desaceleration, or based on angle
if Player.Speed > 0
Player.Speed -= Player.Deceleration
if Player.Speed < 0
Player.Speed = 0
end if
else
Player.Speed += Player.Deceleration
if Player.Speed > 0
Player.Speed = 0
end if
end if

if Player.Speed > 0x2000


Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x2000
TempValue0 >>= 8
Player.Speed += TempValue0
end if

if Player.Speed < -0x2000


Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x2000
TempValue0 >>= 8
Player.Speed += TempValue0
end if

if Player.Angle > 192


if Player.Angle < 228
if Player.Speed > -0x10000
if Player.Speed < 0x10000
Player.ControlLock = 30 // Lock the
player to move out of the angle
end if
end if
end if
end if

if Player.Angle > 28
if Player.Angle < 64
if Player.Speed > -0x10000
if Player.Speed < 0x10000
Player.ControlLock = 30 // Lock the
player to move out of the angle
end if
end if
end if
end if
else
Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x2000
TempValue0 >>= 8
Player.Speed += TempValue0

if Player.Right == true
if Player.Left == false
if Player.Angle > 192
if Player.Angle < 228
if Player.Speed < 0x28000
if Player.Speed > -0x20000
Player.ControlLock = 30 //
Lock the player to move out of the angle
end if
end if
end if
end if
end if
else
if Player.Left == true
if Player.Angle > 28
if Player.Angle < 64
if Player.Speed > -0x28000
if Player.Speed < 0x20000
Player.ControlLock = 30 //
Lock the player to move out of the angle
end if
end if
end if
end if
end if
end if
end if
end if
end function

// Handle movement in the air


function Player_HandleAirFriction
if Player.YVelocity > -0x40000
if Player.YVelocity < 0
TempValue0 = Player.Speed
TempValue0 >>= 5
Player.Speed -= TempValue0
end if
end if
TempValue0 = Player.TopSpeed
FlipSign(TempValue0)

if Player.Speed > TempValue0


if Player.Left == true
Player.Speed -= Player.AirAcceleration
Player.Direction = FACING_LEFT
end if
else
if Player.Left == true
Player.Direction = FACING_LEFT
end if
end if

if Player.Speed < Player.TopSpeed


if Player.Right == true
Player.Speed += Player.AirAcceleration
Player.Direction = FACING_RIGHT
end if
else
if Player.Right == true
Player.Direction = FACING_RIGHT
end if
end if

if Options.OriginalControls == true
if Player.Left == true
TempValue0 = Player.TopSpeed
FlipSign(TempValue0)
if Player.Speed < TempValue0
Player.Speed = TempValue0
end if
end if

if Player.Right == true
if Player.Speed > Player.TopSpeed
Player.Speed = Player.TopSpeed
end if
end if
end if
end function
// Handles desaceleration while rolling
function Player_HandleRollDeceleration

if Player.Right == true
if Player.Speed < 0
Player.Speed += Player.RollingDeceleration
end if
end if

if Player.Left == true
if Player.Speed > 0
Player.Speed -= Player.RollingDeceleration
end if
end if

if Player.Speed > 0
Player.Speed -= Player.AirDeceleration
if Player.Speed < 0
Player.Speed = 0
end if

if Player.Speed == 0
if Player.Angle > 224
Player.State = Player_State_Ground
end if
if Player.Angle < 32
Player.State = Player_State_Ground
end if
end if

Sin256(TempValue0, Player.Angle)
if TempValue0 > 0
Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x5000
else
Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x1E00
end if

TempValue0 >>= 8
Player.Speed += TempValue0
else
Player.Speed += Player.AirDeceleration
if Player.Speed > 0
Player.Speed = 0
end if

if Player.Speed == 0
if Player.Angle > 224
Player.State = Player_State_Ground
end if
if Player.Angle < 32
Player.State = Player_State_Ground
end if
end if

Sin256(TempValue0, Player.Angle)
if TempValue0 < 0
Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x5000
else
Sin256(TempValue0, Player.Angle)
TempValue0 *= 0x1E00
end if

TempValue0 >>= 8
Player.Speed += TempValue0
end if

if Player.Speed > 0x180000


Player.Speed = 0x180000
end if

if Player.Speed < -0x180000


Player.Speed = -0x180000
end if
end function

// Movement when you fall from a cliff


function Player_HandleAirMovement
Player.TrackScroll = true

Player.YVelocity += Player.GravityStrength
if Player.YVelocity < Player.JumpCap
if Player.JumpHold == false
if Player.Timer > 0
Player.YVelocity = Player.JumpCap
TempValue0 = Player.Speed
TempValue0 >>= 5
Player.Speed -= TempValue0
end if
end if
end if
Player.XVelocity = Player.Speed

if Player.Rotation < 256


if Player.Rotation > 0
Player.Rotation -= 4
else
Player.Rotation = 0
end if
else
if Player.Rotation < 512
Player.Rotation += 4
else
Player.Rotation = 0
end if
end if

Player.CollisionMode = CMODE_FLOOR
if Player.Animation == ANI_JUMPING
Player.AnimationSpeed = Player.RollAnimationSpeed
end if
end function

// Gets X and Y Velocity based on angles


function Player_HandleOnGround
Player.TrackScroll = false
Cos256(TempValue0, Player.Angle)
TempValue0 *= Player.Speed
TempValue0 >>= 8
Player.XVelocity = TempValue0

Sin256(TempValue0, Player.Angle)
TempValue0 *= Player.Speed
TempValue0 >>= 8
Player.YVelocity = TempValue0
end function

// A classic move
function Player_Action_Jump
CheckResult = false
if Player.CollisionMode == CMODE_FLOOR
TempValue6 = Object.XPos
TempValue7 = Object.YPos

Object.XPos = Player.XPos
Object.YPos = Player.YPos
TempValue0 = Player.CollisionTop
TempValue0 -= 2
ObjectTileCollision(CSIDE_RWALL, 0, TempValue0, 0)

Object.XPos = TempValue6
Object.YPos = TempValue7
end if

if CheckResult == false
Player.ControlLock = 0
Player.Gravity = GRAVITY_AIR
Player.AbilityTimer = 8

Sin256(Player.XVelocity, Player.Angle)
Player.XVelocity *= Player.JumpStrength
Cos256(TempValue0, Player.Angle)
TempValue0 *= Player.Speed
Player.XVelocity += TempValue0
Player.XVelocity >>= 8

Sin256(Player.YVelocity, Player.Angle)
Player.YVelocity *= Player.Speed
Cos256(TempValue0, Player.Angle)
TempValue0 *= Player.JumpStrength
Player.YVelocity -= TempValue0
Player.YVelocity >>= 8

Player.Speed = Player.XVelocity
Player.TrackScroll = true
Player.Animation = ANI_JUMPING
Player.Angle = 0
Player.CollisionMode = CMODE_FLOOR
Player.Timer = 1
CallFunction(Player_HandleRollAnimSpeed)

Player.State = Player_State_Air

PlaySfx(SFX_G_JUMP, false)
end if

#platform: Use_Origins
if game.playMode == BOOT_PLAYMODE_CLASSIC
Player.DropDashCharge = -1
else
Player.DropDashCharge = 0
end if
#endplatform
end function

// A true Classic, but the actual spindash is set here, this only starts it
function Player_Action_Spindash_S2
Player.State = Player_State_Spindash_S2
Player.Animation = ANI_SPINDASH
Player.AbilityTimer = 0

PlaySfx(SFX_G_CHARGE, false)
// Dust Puff Code
CreateTempObject(TypeName[Dust Puff], Object.EntityNo, Player.XPos,
Player.YPos)
Object[TempObjectPos].iYPos = Player.CollisionBottom
Object[TempObjectPos].YPos += Player.YPos
Object[TempObjectPos].Frame = 4
Object[TempObjectPos].DrawOrder = 4
Object[TempObjectPos].Direction = Player.Direction

#platform: Use_Haptics
HapticEffect(112, 0, 0, 0)
#endplatform
end function

// Not so classic, but the actual spindash is set here, this only starts it
function Player_Action_Spindash_CD
Player.State = Player_State_Spindash_CD
Player.Animation = ANI_JUMPING
Player.YPos += 0x50000
Player.AbilityTimer = 0

PlaySfx(SFX_G_CHARGE, false)

#platform: Use_Haptics
HapticEffect(112, 0, 0, 0)
#endplatform
end function

// um yesh, Sonic 2 Peel Out, this just starts it


function Player_Action_Peelout_S2
Player.State = Player_State_Peelout_S2
Player.AbilityTimer = 0
PlaySfx(SFX_G_CHARGE, false)

#platform: Use_Haptics
HapticEffect(115, 0, 0, 0)
#endplatform
end function

// A true classic, this just starts it tho


function Player_Action_Peelout_CD
Player.State = Player_State_Peelout_CD
Player.AbilityTimer = 0
PlaySfx(SFX_G_CHARGE, false)

#platform: Use_Haptics
HapticEffect(115, 0, 0, 0)
#endplatform
end function

// Starts flying state


function Player_Action_DblJumpTails
if Player.AbilityTimer > 0
Player.AbilityTimer--
else
if Player.JumpPress == true
Player.Timer = 0
Player.State = Player_State_Fly
Player.FlightVelocity = 0x800

#platform: Use_Origins
game.callbackParam0 = 0 // Turned into Super Sonic (not in this
game LOL)
game.callbackParam1 = 1 // Used Tails' Flight
game.callbackParam2 = 0 // Used Knux's Glide
EngineCallback(NOTIFY_STATS_CHARA_ACTION)
#endplatform

// check that you're not in water


if Player.GravityStrength == 0x3800
PlaySfx(SFX_G_FLYING, true)
Player.Animation = ANI_FLYING
else
Player.Animation = ANI_SWIMMING
end if
end if
end if
end function

function Player_State_Ground
if Player.Animation != ANI_SKIDDING // This handles that the skid only plays
sfx once
TempValue7 = true
else
TempValue7 = false
end if

CallFunction(Player_HandleGroundMovement)

if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleOnGround)
if Player.Speed == 0
// Consumes the warp if you stop too late during warping run
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 220
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if

if Player.CollisionMode == CMODE_FLOOR
#platform: Use_Origins
switch Stage.PlayerListPos
case PLAYER_SONIC_A
case PLAYER_TAILS_A
// Original behaviour - Outta Here (Sonic, Classic
Mode only)
if Player.Timer < 240
Player.Animation = ANI_STOPPED
Player.Timer++
else // Waiting animation
Player.Animation = ANI_WAITING
if Stage.PlayerListPos == PLAYER_SONIC
Player.Timer++
if game.playMode == BOOT_PLAYMODE_CLASSIC
if Player.Timer == 10620 // 177
seconds (2 minutes, 57 seconds)
Player.Timer = 0

// This SFX is muted in


Origins
PlaySfx(SFX_G_OUTTAHERE,
false)

Player.State =
Player_State_OuttaHere
Player.Animation = ANI_BORED
end if
end if
end if
end if
break
case PLAYER_KNUCKLES_A
// Knuckles sparring with the air
if Player.Timer < 240
Player.Animation = ANI_STOPPED
Player.Timer++
else
if Player.Timer < 570
Player.Animation = ANI_WAITING
Player.Timer++
else
if Mini_PlayerFlag == false
Player.Animation = ANI_BORED
Player.Timer++
if Player.Timer == 842
Player.Timer = 0
Player.Animation =
ANI_STOPPED
end if
else
Player.Timer = 0
Player.Animation = ANI_STOPPED
end if
end if
end if
break
case PLAYER_AMY_A
// Amy daydreaming
if Player.Timer < 240
Player.Animation = ANI_STOPPED
Player.Timer++
else
if Player.Timer < 1107
Player.Animation = ANI_WAITING
Player.Timer++
else
if Mini_PlayerFlag == false
Player.Animation = ANI_BORED
Player.Timer++
if Player.Timer >= 1152
Player.Timer = 1107
end if
end if
end if
end if
break
end switch
#endplatform

#platform: Use_Standalone
if Player.Timer < 240
Player.Animation = ANI_STOPPED
Player.Timer++
else // Waiting animation
Player.Animation = ANI_WAITING
if Stage.PlayerListPos == PLAYER_SONIC_A
Player.Timer++
if Player.Timer == 10620 // I'm Outta Here!
Player.Timer = 0

PlaySfx(SFX_G_OUTTAHERE, false)

Player.State =
Player_State_OuttaHere
Player.Animation = ANI_BORED
end if
end if
end if
#endplatform

if Player.FloorSensorC == false
if Player.FloorSensorR == false
Player.Timer = 0
if Player.Direction == FACING_LEFT
Player.Animation = ANI_FLAILINGLEFT
else
Player.Animation = ANI_FLAILINGRIGHT
end if
end if

if Player.FloorSensorL == false
Player.Timer = 0

if Player.Direction == FACING_RIGHT
Player.Animation = ANI_FLAILINGLEFT
else
Player.Animation = ANI_FLAILINGRIGHT
end if
end if

end if

end if
else
Player.Timer = 0
if Player.Speed > 0
if Player.Speed < 0x5F5C2
Player.Animation = ANI_WALKING
CallFunction(Player_HandleWalkAnimSpeed)
// Consumes the warp if you stop too late during
warping run, plus deletes the warp star
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
Object[3].Type = TypeName[Blank Object]
end if
else
// Spawns the Warp Stars
if Warp.Destination > WARPDEST_NONE
if Warp.Timer == 0
Warp.Timer = 1
ResetObjectEntity(3, TypeName[Warp Star],
0, Player.XPos, Player.YPos)
WarpStar.Timer = 7
WarpStar.DrawOrder = 4
end if
end if

if Player.Speed > 0x9FFFF


Player.Animation = ANI_PEELOUT
else
Player.Animation = ANI_RUNNING
end if
CallFunction(Player_HandleRunAnimSpeed)
end if
else
if Player.Speed > -0x5F5C2
Player.Animation = ANI_WALKING
CallFunction(Player_HandleWalkAnimSpeed)
// Consumes the warp if you stop too late during
warping run, plus deletes the warp star
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
Object[3].Type = TypeName[Blank Object]
end if
else
// Spawns the Warp Stars
if Warp.Destination > WARPDEST_NONE
if Warp.Timer == 0
Warp.Timer = 1
ResetObjectEntity(3, TypeName[Warp Star],
0, Player.XPos, Player.YPos)
WarpStar.Timer = 7
WarpStar.DrawOrder = 4
end if
end if

if Player.Speed < -0x9FFFF


Player.Animation = ANI_PEELOUT
else
Player.Animation = ANI_RUNNING
end if
CallFunction(Player_HandleRunAnimSpeed)
end if

end if

end if

// Skidding
if Player.Skidding > 0
if TempValue7 == true
PlaySfx(SFX_G_SKIDDING, false)
end if
Player.Animation = ANI_SKIDDING
Player.AnimationSpeed = 0
Player.Skidding--

if Ring.AniCount == 0
CreateTempObject(TypeName[Dust Puff], 0, Player.XPos,
Player.YPos)
Object[TempObjectPos].iYPos +=
Player.CollisionBottom
Object[TempObjectPos].DrawOrder = Player.DrawOrder
end if

if Player.Speed > 0
Player.Direction = FACING_RIGHT
else
Player.Direction = FACING_LEFT
end if
end if
// Push, there's a small delay so 2 is our "true"
if Player.CollisionMode == CMODE_FLOOR
if Player.Pushing == 2
Player.Animation = ANI_PUSHING
Player.AnimationSpeed = 0
end if
end if

// Jump
if Player.JumpPress == true
CallFunction(Player_Action_Jump)
else
// Look Up
if Player.Up == true
if Player.Speed == 0
if Player.Animation != ANI_FLAILINGLEFT
if Player.Animation != ANI_FLAILINGRIGHT
Player.State =
Player_State_LookUp
Player.Animation = ANI_LOOKINGUP
Player.Timer = 0
end if
end if
end if
end if

// Crouch
if Player.Down == true
if Player.Speed == 0
if Player.Animation != ANI_FLAILINGLEFT
if Player.Animation != ANI_FLAILINGRIGHT
Player.State =
Player_State_Crouch
Player.Animation = ANI_LOOKINGDOWN
Player.Timer = 0
end if
end if
else
// Roll
if Player.Left == false
if Player.Right == false
if Player.Speed > 0
if Player.Speed > 0x8800
Player.State =
Player_State_Roll
Player.Animation =
ANI_JUMPING
Player.iYPos -=
Player.JumpOffset
Player.AbilityTimer =
1024
end if
else
if Player.Speed < -0x8800
Player.State =
Player_State_Roll
Player.Animation =
ANI_JUMPING
Player.iYPos -=
Player.JumpOffset
Player.AbilityTimer =
1024
end if
end if
end if
end if
end if
end if
end if
end if
end function

function Player_State_Air_NoDropDash // Origins function, prevents Sonic from


drop dashing without jumping

Player.DropDashCharge = -1
Player.State = Player_State_Air
CallFunction(Player_State_Air)
end function

function Player_State_Air
CallFunction(Player_HandleAirFriction)
#platform: Use_Origins
if Stage.PlayerListPos == PLAYER_TAILS
CallFunction(Player_HandleDropDash)
end if
#endplatform
if Player.Gravity == GRAVITY_AIR // Check that you're truly in the air
CallFunction(Player_HandleAirMovement)

// More warp stuff


if Warp.Destination > WARPDEST_NONE
TempValue0 = Player.YVelocity
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 < 0x60000


TempValue0 = Player.XVelocity
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 < 0x60000


TempValue0 = Player.XVelocity
TempValue0 -= Warp.SpeedCompare
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 > 0x40000


if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
end if
end if
Warp.SpeedCompare = Player.XVelocity
end if

// changes the flailing with the walking, not sure when this is used
if Player.YVelocity > 0x20000
if Player.Animation == ANI_FLAILINGLEFT
Player.Animation = ANI_WALKING
end if
if Player.Animation == ANI_FLAILINGRIGHT
Player.Animation = ANI_WALKING
end if
end if

// Post-Hitting a spring
if Player.Animation == ANI_BOUNCING
if Player.YVelocity >= 0
if Player.AnimationReserve == ANI_STOPPED
Player.AnimationReserve = ANI_WALKING
end if
Player.Animation = Player.AnimationReserve
end if
end if

// Post Getting hurt


if Player.Animation == ANI_HURT
if Player.YVelocity >= 0
if Player.AnimationReserve == ANI_STOPPED
Player.AnimationReserve = ANI_WALKING
end if
Player.Animation = Player.AnimationReserve
end if
end if

// Calls the player flight function


#platform: Use_Origins
// Bug Details:
// This segment of code was backported from Sonic 1 to (presumably)
prevent the ledge roll-off ability bug that's from 2011.
// -> However, this code is missing the Player.JumpAbilityState check
before the second ANI_JUMPING check.
// -> This basically makes it still behave like 2011 does, just more
advanced (?).
// -> The other checks from S1 that also do things with
Player.JumpAbilityState are missing too...
// -> Not really sure why it turned out this way.
if Stage.PlayerListPos == PLAYER_TAILS
if Player.Animation == ANI_JUMPING
CallFunction(Player.JumpAbility)
end if
else
if Player.YVelocity >= Player.JumpCap
CallFunction(Player_HandleDropDash)
if Player.Animation == ANI_JUMPING
CallFunction(Player.JumpAbility)
end if
end if
end if
#endplatform

#platform: Use_Standalone
if Player.Animation == ANI_JUMPING
CallFunction(Player.JumpAbility)
end if
#endplatform
else
// go back to the ground silly
#platform: Use_Origins
if Player.DropDashCharge >= 20
if Stage.PlayerListPos == PLAYER_AMY
CallFunction(Player_Action_HammerDash)
else
CallFunction(Player_Action_Spindash_S2)
end if
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
#endplatform
end if
end function

function Player_State_Roll
CallFunction(Player_HandleRollDeceleration)
#platform: Use_Origins
if Player.ForceGrounded > 0
Player.Gravity = GRAVITY_GROUND
Player.ForceGrounded -= 1 // ig a normal "--" wasn't good enough, huh?
end if
#endplatform

if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Timer = 0
CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleRollAnimSpeed)
Player.AnimationSpeed = Player.RollAnimationSpeed

TempValue0 = Player.Speed
if TempValue0 < 0
FlipSign(TempValue0)
end if

// Warp-Consuming
if TempValue0 < 0x5F5C2
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
else
// Spawn Warp Stars
if Warp.Destination > WARPDEST_NONE
if Warp.Timer == 0
Warp.Timer = 1
ResetObjectEntity(3, TypeName[Warp Star], 0,
Player.XPos, Player.YPos)
WarpStar.Timer = 7
WarpStar.DrawOrder = 4
end if
end if
end if

CallFunction(Player_HandleOnGround)

if Player.JumpPress == true
CallFunction(Player_Action_Jump)
end if
end if
end function

// Cancels input movement (Unused leftover from Sonic Nexus (2008))


function Player_State_RollJump
#platform: Use_Origins
// they removed roll jump lock in Plus lol
if Options.AttractMode == true
Player.Left = false
Player.Right = false
end if

CallFunction(Player_HandleAirFriction)
if Stage.PlayerListPos == PLAYER_TAILS
CallFunction(Player_HandleDropDash)
else
if Player.YVelocity >= Player.JumpCap
CallFunction(Player_HandleDropDash)
end if
end if
#endplatform

#platform: Use_Standalone
Player.Left = false
Player.Right = false
CallFunction(Player_HandleAirFriction)
#endplatform
if Player.Gravity == GRAVITY_AIR
CallFunction(Player_HandleAirMovement)
else

#platform: Use_Origins
if Player.DropDashCharge >= 20
if Stage.PlayerListPos == PLAYER_AMY
CallFunction(Player_Action_HammerDash)
else
CallFunction(Player_Action_Spindash_S2)
end if
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
#endplatform

end if
end function

// Hey look up
function Player_State_LookUp
if Player.Up == false
Player.State = Player_State_Ground
Player.Timer = 0
else
if Player.Timer < 60
Player.Timer++
else
if Player.LookPos > -112
Player.LookPos -= 2
end if
end if

if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Timer = 0
else
if Player.JumpPress == true
CallFunction(Player.ActionPeelout)
end if
end if
end if
end function

// Hey look down


function Player_State_Crouch
if Player.Down == false
Player.State = Player_State_Ground
Player.Timer = 0
else
if Player.Timer < 60
Player.Timer++
else
if Player.LookPos < 96
Player.LookPos += 2
end if
end if

if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Timer = 0
else
if Player.JumpPress == true
CallFunction(Player.ActionSpindash)
end if
end if
end if
end function

// S2 Spin Dash code


function Player_State_Spindash_S2
// Keep the camera lock, cancel the spin dash
if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Speed = 0
end if

// Mashing
if Player.JumpPress == true
if Player.AbilityTimer < 512
Player.AbilityTimer += 64
end if
Player.Frame = 0

PlaySfx(SFX_G_CHARGE, false)
else
if Player.AbilityTimer > 0
Player.AbilityTimer--
end if
end if

#platform: Use_Origins
TempValue1 = Player.Down
if Player.DropDashCharge >= 20
Player.DropDashCharge = -1
Sin256(TempValue0, Player.Angle)
if Player.Direction == FACING_RIGHT
if TempValue0 >= 0
TempValue0 <<= 2
else
TempValue0 <<= 1
end if
else
if TempValue0 >= 0
TempValue0 <<= 1
else
TempValue0 <<= 2
end if
FlipSign(TempValue0)
end if

if TempValue0 > 512


TempValue0 = 512
end if

Player.AbilityTimer = TempValue0
TempValue1 = false
end if

CheckEqual(TempValue1, false)
#endplatform

#platform: Use_Standalone
CheckEqual(Player.Down, false)
#endplatform
// Work around to adapt it to origins
// Spin Dash release
if CheckResult == true
Player.Timer = 0
Player.State = Player_State_Roll
Player.Animation = ANI_JUMPING
Player.iYPos -= Player.JumpOffset

Player.ScrollDelay = 15
Screen.CameraStyle = CAMERASTYLE_HLOCKED

TempValue0 = Player.AbilityTimer
TempValue0 <<= 9
TempValue0 += 0x80000

if Player.Direction == FACING_RIGHT
Player.Speed = TempValue0
else
Player.Speed = TempValue0
FlipSign(Player.Speed)
end if

PlaySfx(SFX_G_RELEASE, false)

CallFunction(Player_HandleOnGround)

#platform: Use_Origins
Player.ForceGrounded = 6
#endplatform

#platform: Use_Haptics
HapticEffect(42, 0, 0, 0)
#endplatform

end if
end function

function Player_State_Spindash_CD
if Player.Direction == FACING_RIGHT
Screen.CameraStyle = CAMERASTYLE_EXTENDED_OFFSET_L
else
Screen.CameraStyle = CAMERASTYLE_EXTENDED_OFFSET_R
end if

// Keep the camera lock, cancel the spin dash


if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Speed = 0
Screen.CameraStyle = CAMERASTYLE_EXTENDED
end if

// Charge
if Player.GravityStrength == 0x1000
if Player.AbilityTimer < 0x80000
Player.AbilityTimer += 0x6000
end if
else
if Player.AbilityTimer < 0xC0000
Player.AbilityTimer += 0x6000
end if
end if

// Release
if Player.Down == false
Screen.CameraStyle = CAMERASTYLE_EXTENDED
Player.Timer = 0

if Player.AbilityTimer < 0x2FAE1


Player.Speed = 0
Player.State = Player_State_Ground
else
Player.State = Player_State_Roll
Player.Animation = ANI_JUMPING
Player.Speed = Player.AbilityTimer

if Player.Direction == FACING_LEFT
FlipSign(Player.Speed)
end if

PlaySfx(SFX_G_RELEASE, false)
end if
CallFunction(Player_HandleOnGround)

#platform: Use_Haptics
HapticEffect(42, 0, 0, 0)
#endplatform

end if
end function

function Player_State_Peelout_S2
// Cancels the Peel Out, keeps the camera
if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Speed = 0
end if
// Charge
if Player.GravityStrength == 0x1000
if Player.AbilityTimer < 0x60000
Player.AbilityTimer += 0x6000
end if
else
if Player.AbilityTimer < 0xC0000
Player.AbilityTimer += 0x6000
end if
end if
// Speed building, from walking to running then peelout
if Player.AbilityTimer < 0x5F5C2
Player.Animation = ANI_WALKING
TempValue0 = Player.AbilityTimer
TempValue0 >>= 16
TempValue0 *= 80
TempValue0 /= 6
TempValue0 += 20
else
TempValue0 = Player.AbilityTimer
TempValue0 >>= 16
TempValue0 *= 80
TempValue0 /= 6
if Player.AbilityTimer > 0x9FFFF
Player.Animation = ANI_PEELOUT
else
Player.Animation = ANI_RUNNING
end if
end if

// Release
if Player.Up == false
Player.ScrollDelay = 15
Screen.CameraStyle = CAMERASTYLE_HLOCKED

Player.State = Player_State_Ground
// Cancels the peel out if you didn't charged it enough
if Player.AbilityTimer < 0x5F5C2
Player.Speed = 0
else
Player.Speed = Player.AbilityTimer
if Player.Direction == FACING_LEFT
FlipSign(Player.Speed)
end if
PlaySfx(SFX_G_RELEASE, false)
end if
CallFunction(Player_HandleOnGround)

#platform: Use_Haptics
HapticEffect(42, 0, 0, 0)
#endplatform

end if
Player.AnimationSpeed = TempValue0
end function

function Player_State_Peelout_CD
// Moves the camera
if Player.Direction == FACING_RIGHT
Screen.CameraStyle = CAMERASTYLE_EXTENDED_OFFSET_L
else
Screen.CameraStyle = CAMERASTYLE_EXTENDED_OFFSET_R
end if
// Cancels the Peel Out, keeps the camera
if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Speed = 0
Screen.CameraStyle = CAMERASTYLE_EXTENDED
end if

// Charge
if Player.GravityStrength == 0x1000
if Player.AbilityTimer < 0x60000
Player.AbilityTimer += 0x6000
end if
else
if Player.AbilityTimer < 0xC0000
Player.AbilityTimer += 0x6000
end if
end if

// Speed building, from walking to running then peelout


if Player.AbilityTimer < 0x5F5C2
Player.Animation = ANI_WALKING
TempValue0 = Player.AbilityTimer
TempValue0 >>= 16
TempValue0 *= 80
TempValue0 /= 6
TempValue0 += 20
else
TempValue0 = Player.AbilityTimer
TempValue0 >>= 16
TempValue0 *= 80
TempValue0 /= 6
if Player.AbilityTimer > 0x9FFFF
Player.Animation = ANI_PEELOUT
else
Player.Animation = ANI_RUNNING
end if
end if

// Release
if Player.Up == false
Screen.CameraStyle = CAMERASTYLE_EXTENDED

Player.State = Player_State_Ground
// Cancels the peel out if you didn't charged it enough
if Player.AbilityTimer < 0x5F5C2
Player.Speed = 0
else
Player.Speed = Player.AbilityTimer
if Player.Direction == FACING_LEFT
FlipSign(Player.Speed)
end if

PlaySfx(SFX_G_RELEASE, false)
end if
CallFunction(Player_HandleOnGround)

#platform: Use_Haptics
HapticEffect(42, 0, 0, 0)
#endplatform

end if
Player.AnimationSpeed = TempValue0
end function

// Tails flight
function Player_State_Fly
CallFunction(Player_HandleAirFriction)
if Player.Gravity == GRAVITY_AIR
Player.XVelocity = Player.Speed
// Check if you have enough speed while flying to keep the warp
if Warp.Destination > WARPDEST_NONE
TempValue0 = Player.XVelocity
if TempValue0 < 0
FlipSign(TempValue0)
end if

TempValue1 = Player.YVelocity
if TempValue1 < 0
FlipSign(TempValue1)
end if

TempValue0 += TempValue1
if TempValue0 < 0x40000
if Warp.Timer > 99
if Warp.Timer < 220
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
end if

if Player.YVelocity < -0x10000


Player.FlightVelocity = 0x800
else
if Player.YVelocity < 1
if Player.AbilityTimer < 60
Player.AbilityTimer++
else
Player.FlightVelocity = 0x800
end if
end if
end if

Player.YVelocity += Player.FlightVelocity
if Player.Timer < 480
if Player.GravityStrength == 0x3800
Player.Animation = ANI_FLYING
else
Player.Animation = ANI_SWIMMING
end if

Player.Timer++
if Player.Timer == 480
if Player.GravityStrength == 0x3800
Player.Animation = ANI_FLYINGTIRED
StopSfx(SFX_G_FLYING)
PlaySfx(SFX_G_TIRED, true)
else
Player.Animation = ANI_SWIMMINGTIRED
end if
else
if Player.JumpPress == true
Player.FlightVelocity = -0x2000
Player.AbilityTimer = 0
end if
end if
else
if Player.GravityStrength == 0x3800
Player.Animation = ANI_FLYINGTIRED
else
Player.Animation = ANI_SWIMMINGTIRED
end if
end if
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
end if

// If the level has a roof barrier, you're not getting too far
if Player.RoofBarrier == true
TempValue0 = Player.YPos
TempValue0 >>= 16
if TempValue0 < Player.CollisionBottom
Player.YPos = Player.CollisionBottom
Player.YPos <<= 16
end if
end if
end function

// Player Damage
function Player_State_GotHit
#platform: Use_Origins
TempValue1 = false
if game.playMode == BOOT_PLAYMODE_MISSION
if game.missionFunctionNo == RULE_MERCY_BADNIKS
if game.missionValue == 1
game.missionValue = 0
TempValue1 = true
end if
end if
end if
#endplatform

ArrayPos0 = Player.EntityNo
ArrayPos0 += 2
// if you had a shield, remove it
if Object[ArrayPos0].PropertyValue > 0
TempValue0 = DAMAGE_SHIELDED
ResetObjectEntity(ArrayPos0, TypeName[Blank Object], 0, 0, 0)
PlaySfx(SFX_G_HURT, false)
else
if Player.Rings == 0
PlaySfx(SFX_G_HURT, false)
TempValue0 = DAMAGE_DEATH
else
#platform: Use_Origins
if TempValue1 == false
PlaySfx(SFX_G_LOSERINGS, false)
TempValue0 = DAMAGE_HURT
end if
#endplatform

#platform: Use_Standalone
PlaySfx(SFX_G_LOSERINGS, false)
TempValue0 = DAMAGE_HURT
#endplatform
end if
end if

#platform: Use_Origins
if TempValue1 != false
TempValue0 = DAMAGE_DEATH
end if
#endplatform

switch TempValue0
case DAMAGE_SHIELDED
#platform: Use_Haptics
HapticEffect(16, 0, 0, 0)
#endplatform

Player.State = Player_State_Hurt
Player.Animation = ANI_HURT
Player.YVelocity = -0x40000
Player.Gravity = GRAVITY_AIR
Player.TrackScroll = true
Player.InvincibleTimer = 8000

if Player.GravityStrength == 0x1000
Player.Speed >>= 1
Player.YVelocity >>= 1
end if
break

case DAMAGE_HURT
#platform: Use_Haptics
HapticEffect(16, 0, 0, 0)
#endplatform

if Player.CollisionPlane == COLLISION_PLANE_A
TempValue4 = 3
else
TempValue4 = 1
end if

Player.State = Player_State_Hurt
Player.Animation = ANI_HURT
Player.YVelocity = -0x40000
Player.Gravity = GRAVITY_AIR
Player.TrackScroll = true
Player.InvincibleTimer = 8000

if Player.GravityStrength == 0x1000
Player.Speed >>= 1
Player.YVelocity >>= 1
end if
// Lose ring code
TempValue0 = Player.Rings
if TempValue0 > 16
TempValue1 = TempValue0
TempValue1 -= 16
TempValue0 = 16
else
TempValue1 = 0
end if
if TempValue1 > 16
TempValue1 = 16
end if

TempValue3 = TempValue1
TempValue3 >>= 1
TempValue3 <<= 5

TempValue2 = 384
TempValue2 -= TempValue3

TempValue3 >>= 4
if TempValue3 == TempValue1
TempValue2 += 16
else
TempValue2 -= 16
end if

TempValue3 = 0
while TempValue3 < TempValue1
CreateTempObject(TypeName[Lose Ring], Player.CollisionPlane,
Player.XPos, Player.YPos)
Cos(Object[TempObjectPos].XVelocity, TempValue2)
Sin(Object[TempObjectPos].YVelocity, TempValue2)
Object[TempObjectPos].XVelocity <<= 8
Object[TempObjectPos].YVelocity <<= 8
Object[TempObjectPos].DrawOrder = TempValue4
Object[TempObjectPos].AnimationSpeed = 256
TempValue3++
TempValue2 += 32
loop
TempValue3 = TempValue0
TempValue3 >>= 1
TempValue3 <<= 5

TempValue2 = 384
TempValue2 -= TempValue3

TempValue3 >>= 4
if TempValue3 == TempValue0
TempValue2 += 16
else
TempValue2 -= 16
end if
TempValue3 = 0

while TempValue3 < TempValue0


CreateTempObject(TypeName[Lose Ring], Player.CollisionPlane,
Player.XPos, Player.YPos)
Cos(Object[TempObjectPos].XVelocity, TempValue2)
Sin(Object[TempObjectPos].YVelocity, TempValue2)
Object[TempObjectPos].XVelocity <<= 9
Object[TempObjectPos].YVelocity <<= 9
Object[TempObjectPos].DrawOrder = TempValue4
Object[TempObjectPos].AnimationSpeed = 256
TempValue3++
TempValue2 += 32
loop
Player.Rings = 0
Ring.ExtraLife = 100
break

case DAMAGE_DEATH
#platform: Use_Haptics
HapticEffect(28, 0, 0, 0)
#endplatform

Object.DrawOrder = 5
Player.Speed = 0
Player.YVelocity = -0x70000
Player.XVelocity = 0
Player.State = Player_State_Death
Player.Animation = ANI_DYING

Player.TileCollisions = false
Player.ObjectInteraction = false
if Player.EntityNo == 0 // Check if it's was player 1 who
died......what?
Screen.CameraEnabled = false
end if
break
end switch
// lose your warp-run if you receive damage
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
end function

function Player_State_Hurt
#platform: Use_Origins
Player.TileCollisions = true
#endplatform
if Player.Gravity == GRAVITY_AIR
Player.TrackScroll = true
if Player.GravityStrength == 0x3800
Player.YVelocity += 0x3000
else
Player.YVelocity += 0xF00
end if
Player.XVelocity = Player.Speed
else
Player.State = Player_State_Ground
Player.InvincibleTimer = 120
Player.BlinkTimer = 3
Player.Speed = 0
Player.XVelocity = 0
CallFunction(Player_HandleOnGround)
end if
end function

function Player_State_OuttaHere
// preparing to jump
if Player.Timer < 140
Player.Timer++
else
// The Jump.
Player.Timer = 0
Player.DrawOrder = 5

if Player.Direction == FACING_RIGHT
Player.Speed = 0x10000
Player.XVelocity = 0x10000
else
Player.Speed = -0x10000
Player.XVelocity = -0x10000
end if
Player.YVelocity = -0x58000
Player.State = Player_State_Death

Player.TileCollisions = false
Player.ObjectInteraction = false

Screen.CameraEnabled = false
end if
end function

// YOU DIED.
function Player_State_Death
Player.ControlMode = CONTROLMODE_NONE
Player.YVelocity += 0x3800
// Don't override the bored animation
if Player.Animation != ANI_BORED
Player.Animation = ANI_DYING
end if

if Player.YVelocity > 0x100000


#platform: Use_Origins
EngineCallback(NOTIFY_DEATH_EVENT)
#endplatform

if Player.Lives > 0
if Player.Animation == ANI_BORED // Outta Here makes an
automatic game over, no lifes will save you
Player.Lives = 0
else

#platform: Use_Origins
// Check that we are actually in a mode where we use lives
if game.coinMode == false
if game.playMode != BOOT_PLAYMODE_MISSION
CheckEqual(game.playMode,
BOOT_PLAYMODE_BOSSRUSH)
TempValue0 = CheckResult
CheckEqual(game.oneStageFlag, false)
TempValue0 |= CheckResult
if TempValue0 != 0
Player.Lives--
end if
end if
end if
#endplatform

#platform: Use_Standalone
// In Standalone, we don't have any extra things to worry
about
Player.Lives--
#endplatform
end if
end if

Stage.TimeEnabled = false

#platform: Use_Origins
CheckEqual(game.playMode, BOOT_PLAYMODE_BOSSRUSH)
TempValue0 = CheckResult
CheckNotEqual(Player.Lives, 0)
TempValue0 |= CheckResult
// Check if the player is replaying the stage from My Data & Rankings
CheckEqual(game.oneStageFlag, false)
CheckResult |= TempValue0
#endplatform

#platform: Use_Standalone
// Slight workaround to make this cleaner - the check below this comes
from Origins, but we need it to always be true on standalone

CheckResult = true
#endplatform

// Again, this check is new to Origins and doesn't exist in Standalone


if CheckResult != false
Object.Type = TypeName[Death Event]
DeathEvent.DrawOrder = 7
DeathEvent.Text1XPos = Screen.CenterX
DeathEvent.Text1XPos -= 232
DeathEvent.Text2XPos = Screen.CenterX
DeathEvent.Text2XPos += 232
end if

if Options.GameMode == MODE_TIMEATTACK
DeathEvent.Timer = 0
DeathEvent.State = DEATHEVENT_TIMEATTACK
else
if Player.Lives == 0
DeathEvent.Timer = -2880
DeathEvent.State = DEATHEVENT_GAMEOVER
// *Technically it goes to the traditional game over in the
same state
PlayMusic(5)
Stage.PauseEnabled = false

#platform: Use_Origins
if game.oneStageFlag != false
game.callbackResult = -1 //
Reset any callback result
game.callbackParam0 = 0 // 0 -
Normal Retry, anything else - Show current and best time
game.callbackParam1 = Stage.ListPos // Get
current stage
game.callbackParam2 = 0 //
Unknown
EngineCallback(NOTIFY_STAGE_RETRY)
end if
#endplatform

else
DeathEvent.Timer = 0
DeathEvent.State = DEATHEVENT_FADEOUT

#platform: Use_Origins
// Lots of checks here, before we do anything else

if game.coinMode == false
if game.playMode != BOOT_PLAYMODE_BOSSRUSH
if Stage.Minutes == 9
if Stage.Seconds == 59
// Check if the player is replaying
the stage from My Data & Rankings
if game.oneStageFlag == false
DeathEvent.Timer = -2880
DeathEvent.State =
DEATHEVENT_TIMEOVER

PlayMusic(5)
Stage.PauseEnabled = false
end if
end if
end if
end if
end if
#endplatform

#platform: Use_Standalone
if Stage.Minutes == 9
if Stage.Seconds == 59
DeathEvent.Timer = -2880
DeathEvent.State = DEATHEVENT_TIMEOVER

PlayMusic(5)
Stage.PauseEnabled = false
end if
end if
#endplatform
end if
end if
end if
end function

// Same as death, just slower and without the bored or time over stuff
function Player_State_Drown
Player.ControlMode = CONTROLMODE_NONE
Player.YVelocity += Player.GravityStrength
Player.Animation = ANI_DROWNING

if Player.YVelocity > 0x80000


#platform: Use_Origins
EngineCallback(NOTIFY_DEATH_EVENT)
// We only subtract lives sometimes in Origins
if game.coinMode == false
if game.playMode != BOOT_PLAYMODE_MISSION
CheckEqual(game.playMode, BOOT_PLAYMODE_BOSSRUSH)
TempValue0 = CheckResult
CheckEqual(game.oneStageFlag, false)
TempValue0 |= CheckResult
if TempValue0 != false
if Player.Lives > 0
Player.Lives--
end if
end if
end if
end if
#endplatform

#platform: Use_Standalone
if Player.Lives > 0
Player.Lives--
end if
#endplatform

Stage.TimeEnabled = false

Object.Type = TypeName[DeathEvent]
DeathEvent.DrawOrder = 7
DeathEvent.Text1XPos = Screen.CenterX
DeathEvent.Text1XPos -= 232
DeathEvent.Text2XPos = Screen.CenterX
DeathEvent.Text2XPos += 232

if Options.GameMode == MODE_TIMEATTACK
DeathEvent.Timer = 0
DeathEvent.State = DEATHEVENT_TIMEATTACK
else
if Player.Lives == 0
DeathEvent.Timer = -2880
DeathEvent.State = DEATHEVENT_GAMEOVER

PlayMusic(5)
Stage.PauseEnabled = false
else
DeathEvent.Timer = 0
DeathEvent.State = DEATHEVENT_FADEOUT
end if
end if
end if
end function

// Wacky Workbench hanging bar gimmick


function Player_State_HangBar
if Player.Left == true
Player.Direction = FACING_LEFT
Player.Speed = -0x20000
Player.AnimationSpeed = 30
else
if Player.Right == true
Player.Direction = FACING_RIGHT
Player.Speed = 0x20000
Player.AnimationSpeed = 30
else
Player.Speed = 0
Player.AnimationSpeed = 0
end if
end if

TempValue1 = Player.XPos
TempValue1 >>= 16

TempValue2 = Player.YPos
TempValue2 >>= 16
TempValue2 += Player.CollisionTop
// Check that you are in the hanging bar
Get16x16TileInfo(TempValue0, TempValue1, TempValue2, TILEINFO_ANGLEB)
if TempValue0 != 3 // seems like you're not

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Speed = 0
Player.AnimationSpeed = 0
Player.YVelocity = 0
end if

// Manual Drop
if Player.JumpPress == true

Player.State = Player_State_Air
Player.YVelocity = 0
Player.Speed = 0
Player.AnimationSpeed = 0
Player.YPos += 0x40000
end if
Player.XVelocity = Player.Speed
// Cancel warp
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if

Warp.Timer = 0
end if
end function

// Unused leftover from Sonic Nexus (2008)


function Player_State_CorkscrewRun
Player.Angle = 0
CallFunction(Player_HandleGroundMovement)
Player.Animation = 34 // Corkscrew animation, it uses Nexus values and as
such, it just looks like a jumbled mess in-game
if Player.Speed < 0x60000
if Player.Speed > -0x60000
Player.Animation = ANI_WALKING

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Rotation = 0

if Player.Speed < 0
Player.Direction = FACING_LEFT
end if
end if
end if

if Player.Down == true
if Player.Speed > 0x199A
Player.State = Player_State_CorkscrewRoll
Player.Animation = ANI_JUMPING
end if

if Player.Speed < -0x199A


Player.State = Player_State_CorkscrewRoll
Player.Animation = ANI_JUMPING
end if
end if

if Player.Skidding > 0
if Player.Skidding == 16
PlaySfx(SFX_G_DESTROY, false) // Would be Skidding SFX if using
Nexus SFX list
end if
Player.Animation = ANI_SKIDDING
Player.Skidding--
end if

if Player.JumpPress == true
CallFunction(Player_Action_Jump)
else
CallFunction(Player_HandleOnGround)
end if
end function

// Unused leftover from Sonic Nexus (2008)


function Player_State_CorkscrewRoll
Player.Angle = 0
CallFunction(Player_HandleRollDeceleration)

if Player.Speed < 0x60000


if Player.Speed > -0x60000

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform
#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

end if
end if

if Player.JumpPress == true
CallFunction(Player_Action_Jump)
else
CallFunction(Player_HandleOnGround)
end if
end function

// Tube Switch function


function Player_State_TubeRoll
#platform: Use_Origins
Player.DropDashCharge = -1
#endplatform
if Player.Gravity == GRAVITY_AIR // end the function if you are in the air

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Timer = 0
CallFunction(Player_HandleAirMovement)
else
if Player.Speed > 0
if Player.Speed < Player.MinRollSpeed
Player.Speed = Player.MinRollSpeed
end if

if Player.Speed > 0x100000


Player.Speed = 0x100000
end if
else
TempValue0 = Player.MinRollSpeed
FlipSign(TempValue0)
if Player.Speed > TempValue0
Player.Speed = TempValue0
CallFunction(Player_HandleOnGround)
end if

if Player.Speed < -0x100000


Player.Speed = -0x100000
end if
end if

TempValue0 = Player.Speed
if TempValue0 < 0
FlipSign(TempValue0)
end if
if TempValue0 < 0x5F5C2
// Warp Star delete checks
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
else
// Warp Star spawnning
if Warp.Destination > WARPDEST_NONE
if Warp.Timer == 0
Warp.Timer = 1
CreateTempObject(TypeName[Warp Star], 0, Player.XPos,
Player.YPos)
WarpStar.Timer = 7
WarpStar.DrawOrder = 4
end if
end if
end if

CallFunction(Player_HandleRollDeceleration)
CallFunction(Player_HandleRollAnimSpeed)
Player.AnimationSpeed = Player.RollAnimationSpeed
CallFunction(Player_HandleOnGround)
end if
end function

function Player_State_TubeAirRoll
#platform: Use_Origins
Player.DropDashCharge = -1
#endplatform
Player.Right = false
Player.Left = false
if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Timer = 0
CallFunction(Player_HandleAirMovement)
else
if Player.Speed > 0
Player.Speed = Player.MinRollSpeed
else
TempValue0 = Player.MinRollSpeed
FlipSign(TempValue0)
Player.Speed = TempValue0
end if

TempValue0 = Player.Speed
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 < 0x5F5C2


if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
else
if Warp.Destination > WARPDEST_NONE
if Warp.Timer == 0
Warp.Timer = 1
CreateTempObject(TypeName[Warp Star], 0, Player.XPos,
Player.YPos)
WarpStar.Timer = 7
WarpStar.DrawOrder = 4
end if
end if
end if
CallFunction(Player_HandleRollDeceleration)
CallFunction(Player_HandleRollAnimSpeed)
Player.AnimationSpeed = Player.RollAnimationSpeed
CallFunction(Player_HandleOnGround)
end if
end function

// Palmtree Panic and Wacky Workbench spinning tops


function Player_State_SpinningTop
Player.Timer += Player.MinRollSpeed
if Player.Gravity == GRAVITY_AIR // Drop from them if you get out of range

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Animation = ANI_WALKING
Player.Timer = 0
CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleOnGround)
end if
end function

// Amy Rose's favorite function


function Player_State_Hugged
if Player.Gravity == GRAVITY_AIR // No hugs if you're in the air

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform
#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Animation = ANI_WALKING
Player.Timer = 0
CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleOnGround)
// Yes, the only thing the function does is make you wait
if Player.Timer < 240
Player.Animation = ANI_STOPPED
Player.Timer++
else
Player.Animation = ANI_WAITING
end if

// Warp cancel check


if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if

// Get free from Amy


if Player.JumpPress == true
CallFunction(Player_Action_Jump)
end if
end if
end function

// Palmtree Panic Ramp


function Player_State_Ramp3D
CallFunction(Player_HandleGroundMovement)
if Player.Gravity == GRAVITY_AIR

#platform: Use_Origins
Player.State = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
Player.State = Player_State_Air
#endplatform

Player.Timer = 0
CallFunction(Player_HandleAirMovement)
// Set the equivalent animation for looking to the left
if Player.Direction == FACING_LEFT

if Player.Animation == ANI_RAMP_RUNNING3
Player.Animation = ANI_RAMP_RUNNING5
end if

if Player.Animation == ANI_RAMP_RUNNING2
Player.Animation = ANI_RAMP_RUNNING6
end if
end if
else
#platform: Use_Origins
if Player.Animation == ANI_GLIDING
Player.XVelocity = 0
Player.YVelocity = 0
Player.Speed = 0
Player.Animation = ANI_GLIDING_STOP
end if
#endplatform
CallFunction(Player_HandleOnGround)
if Player.Speed == 0
// Warp Star erase check
if Warp.Destination > WARPDEST_NONE
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = WARPDEST_NONE
end if
end if
Warp.Timer = 0
end if
// Waiting timer while in the ramp
if Player.Timer < 240
Player.Animation = ANI_STOPPED
Player.Timer++
else
Player.Animation = ANI_WAITING
end if
else
// Set animation based on angle
if Player.Angle == 0
Player.Animation = ANI_RAMP_RUNNING1
end if

if Player.Angle > 200


if Player.Direction == FACING_RIGHT
Player.Animation = ANI_RAMP_RUNNING3
else
Player.Animation = ANI_RAMP_RUNNING5
end if
end if

if Player.Angle > 216


if Player.Direction == FACING_RIGHT
Player.Animation = ANI_RAMP_RUNNING2
else
Player.Animation = ANI_RAMP_RUNNING6
end if
end if

if Player.Angle > 232


Player.Animation = ANI_RAMP_RUNNING1
end if

if Player.Angle == 192
Player.Animation = ANI_RAMP_RUNNING4
end if
end if
if Player.JumpPress == true
CallFunction(Player_Action_Jump)
else
if Player.Up == true
if Player.Speed == 0
Player.State = Player_State_LookUp
Player.Animation = ANI_LOOKINGUP
Player.Timer = 0
end if
end if
if Player.Down == true
if Player.Speed == 0
Player.State = Player_State_Crouch
Player.Animation = ANI_LOOKINGDOWN
Player.Timer = 0
else
if Player.Speed > 0x199A
Player.ControlLock = 0
Player.State = Player_State_Roll
Player.Animation = ANI_JUMPING
end if

if Player.Speed < -0x199A


Player.ControlLock = 0
Player.State = Player_State_Roll
Player.Animation = ANI_JUMPING
end if
end if
end if
end if
end if

if Player.Animation != ANI_STOPPED
Player.AnimationSpeed = Player.Speed
if Player.AnimationSpeed < 0
FlipSign(Player.AnimationSpeed)
end if
Player.AnimationSpeed *= 60
Player.AnimationSpeed /= 0x60000
Player.AnimationSpeed += 20
else
Player.AnimationSpeed = 0
end if
end function

function Player_State_WaterCurrent
Player.Gravity = GRAVITY_AIR

if Player.Up == true
Player.YPos -= 0x20000
end if

if Player.Down == true
Player.YPos += 0x20000
end if

if Player.Left == true
Player.XPos -= 0x20000
end if

if Player.Right == true
Player.XPos += 0x20000
end if
end function

function Player_SetJumpOffset
#platform: Use_Origins
if Mini_PlayerFlag == true
Player.JumpOffset = -1
else
if Stage.PlayerListPos == PLAYER_SONIC
Player.JumpOffset = -5
end if

if Stage.PlayerListPos == PLAYER_TAILS
Player.JumpOffset = -1
end if

if Stage.PlayerListPos == PLAYER_KNUCKLES
Player.JumpOffset = -5
end if

if Stage.PlayerListPos == PLAYER_AMY
Player.JumpOffset = -4
end if
end if
#endplatform
end function

function Player_State_SizeChange
Player.TileCollisions = true
if Player.Gravity == GRAVITY_AIR // Knockback after touching the laser
Player.TrackScroll = true
Player.YVelocity += 0x3000
Player.XVelocity = Player.Speed
else
Player.State = Player_State_Ground

Player.InvincibleTimer = 120
Player.BlinkTimer = 3

Player.Speed = 0
Player.XVelocity = 0

CallFunction(Player_HandleOnGround)
if Mini_PlayerFlag == false
Mini_PlayerFlag = true

#platform: Use_Standalone
Player.JumpOffset = -1
switch Stage.PlayerListPos
case PLAYER_SONIC_A
LoadAnimation("MiniSonic.Ani")
break

case PLAYER_TAILS_A
LoadAnimation("MiniTails.Ani")
Object[1].Type = TypeName[Blank Object] // Mini Tails's
tails are built-in with his sprites
break
end switch
#endplatform

#platform: Use_Origins
switch Stage.PlayerListPos
case PLAYER_SONIC_A
LoadAnimation("MiniSonic.Ani")
break

case PLAYER_TAILS_A
LoadAnimation("MiniTails.Ani")
Object[1].Type = TypeName[Blank Object] // Mini Tails's
tails are built-in with his sprites
break

case PLAYER_KNUCKLES_A
LoadAnimation("MiniKnuckles.Ani")
Object[1].Type = TypeName[Blank Object] // Mini Knuckles...
doesn't have tails, but set the object to blank anyway, I guess
break

case PLAYER_AMY_A
LoadAnimation("MiniAmy.Ani")
Object[1].Type = TypeName[Blank Object] // Mini Amy...
doesn't have tails, but set the object to blank anyway, I guess
break
end switch
#endplatform
else
Mini_PlayerFlag = false

#platform: Use_Standalone
switch Stage.PlayerListPos
case PLAYER_SONIC_A
LoadAnimation("Sonic.Ani")
Player.JumpOffset = -5
break

case PLAYER_TAILS_A
LoadAnimation("Tails.Ani")
Player.JumpOffset = -1
Object[1].Type = TypeName[Tails Object] // Restore Tails's
tails
break
end switch
#endplatform

#platform: Use_Origins
if Stage.PlayerListPos == PLAYER_SONIC
LoadAnimation("Sonic.Ani")
end if

if Stage.PlayerListPos == PLAYER_TAILS
LoadAnimation("Tails.Ani")
Object[1].Type = TypeName[Tails Object] // Restore Tails's
tails
end if

if Stage.PlayerListPos == PLAYER_KNUCKLES
LoadAnimation("Knuckles.Ani")
end if

if Stage.PlayerListPos == PLAYER_AMY
LoadAnimation("Amy.Ani")
end if
#endplatform
end if

#platform: Use_Origins
CallFunction(Player_SetJumpOffset)
#endplatform

BindPlayerToObject(0, 0)
end if
end function

function Player_HandleDropDash
#platform: Use_Origins
if Player.DropDashCharge >= 0
if Player.DropDashCharge == 0
if Player.JumpPress == true
if Stage.PlayerListPos == PLAYER_SONIC
Player.DropDashCharge = 1
else
if Stage.PlayerListPos == PLAYER_AMY
Player.DropDashCharge = 1
else
Player.DropDashCharge = -1
end if
end if
end if
else
if Player.JumpHold == false
if Stage.PlayerListPos == PLAYER_TAILS
Player.DropDashCharge = -1
else
if Player.DropDashCharge >= 20
Player.DropDashCharge = -1
end if
end if
else
Player.DropDashCharge++
if Player.DropDashCharge == 20
PlaySfx(SFX_G_DROPDASH, false)
end if

if Player.DropDashCharge >= 20
if Player.Animation == ANI_JUMPING
Player.Frame = 0
Player.AnimationTimer = 0
Player.AnimationSpeed = 1
end if
end if
end if
end if
end if
#endplatform
end function

function Player_Action_DblJumpKnux
#platform: Use_Origins
if Player.YVelocity >= Player.JumpCap
if Player.JumpPress == true
game.callbackParam0 = 1
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
Player.Speed = 0x40000
if Player.YVelocity < 0
Player.YVelocity = 0
end if
if Player.Direction == FACING_RIGHT
Player.State = Player_State_GlideRight
Player.XVelocity = 0x40000
Player.Timer = 0
else
Player.State = Player_State_GlideLeft
Player.XVelocity = -0x40000
Player.Timer = 256
end if
Player.Animation = ANI_GLIDING
Player.Frame = 2
Object.Frame = 2
end if
end if
#endplatform
end function

function Player_State_GlideLeft
#platform: Use_Origins
if Player.Speed == 0
if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
end if

if Player.Gravity == GRAVITY_AIR
if Player.JumpHold == true
if Player.Timer == 256
if Player.Speed < 0x180000
Player.Speed += 0x400
end if
else
if Player.Speed < 0x40000
Player.Speed += 0x1000
end if
end if

if Player.YVelocity > 0x8000


Player.YVelocity -= 0x2000
else
Player.YVelocity += 0x2000
end if

if Player.Timer < 256


Player.Timer += 4
end if

if Player.Timer < 170


if Player.Timer > 86
Player.Frame = 0
else
if Player.Timer > 44
Player.Frame = 1
else
Player.Frame = 2
end if
end if
else
if Player.Timer < 212
Player.Frame = 1
else
Player.Frame = 2
end if
end if

TempValue7 = Player.XPos
if Player.Timer < 128
Player.Direction = FACING_RIGHT
TempValue0 = false
TempValue1 = false
else
Player.Direction = FACING_LEFT
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Player.YPos = Player.YPos
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_RWALL, -12, -2,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue0 = CheckResult
TempValue2 = Player.XPos
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_RWALL, -12, 11,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue1 = CheckResult
TempValue3 = Player.XPos
end if

Cos(Player.XVelocity, Player.Timer)
Player.XVelocity *= Player.Speed
Player.XVelocity >>= 9
if Player.Right == true
Player.State = Player_State_GlideRight

if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
end if

Player.XPos = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
if TempValue2 == TempValue3
if Player.XVelocity > 0
Player.Direction = FACING_RIGHT
end if
Player.State = Player_State_Climb
Player.Speed = 0
Player.XVelocity = 0
Player.YVelocity = 0
Player.Timer = 0
PlaySfx(SFX_G_GRAB, false)
game.callbackParam0 = 2
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
else
if TempValue0 == true
if TempValue1 == false
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT,
false, ECEFFECT_NONE)
end if

if CheckResult == false
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
else
if Player.CollisionMode == CMODE_FLOOR
Player.Timer = 0
Player.State = Player_State_GlideSlide
Player.Animation = ANI_GLIDING_STOP
Player.Speed = Player.XVelocity
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
end if

CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_State_GlideRight
#platform: Use_Origins
if Player.Speed == 0
if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
end if

if Player.Gravity == GRAVITY_AIR
if Player.JumpHold == true
if Player.Timer == 0
if Player.Speed < 0x180000
Player.Speed += 0x400
end if
else
if Player.Speed < 0x40000
Player.Speed += 0x1000
end if
end if

if Player.YVelocity > 0x8000


Player.YVelocity -= 0x2000
else
Player.YVelocity += 0x2000
end if

if Player.Timer > 0
Player.Timer -= 4
end if
if Player.Timer < 170
if Player.Timer > 86
Player.Frame = 0
else
if Player.Timer > 44
Player.Frame = 1
else
Player.Frame = 2
end if
end if
else
if Player.Timer < 212
Player.Frame = 1
else
Player.Frame = 2
end if
end if

TempValue7 = Player.XPos
if Player.Timer < 128
Player.Direction = FACING_RIGHT
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Player.YPos = Player.YPos
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_LWALL, 12, -2,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue0 = CheckResult
TempValue2 = Player.XPos
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_LWALL, 12, 11,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue1 = CheckResult
TempValue3 = Player.XPos
else
Player.Direction = FACING_LEFT
TempValue0 = false
TempValue1 = false
end if

Cos(Player.XVelocity, Player.Timer)
Player.XVelocity *= Player.Speed
Player.XVelocity >>= 9
if Player.Left == true
Player.State = Player_State_GlideLeft

if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
end if

Player.XPos = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
TempValue2 >>= 1
TempValue3 >>= 1
if TempValue2 == TempValue3
if Player.XVelocity < 0
Player.Direction = FACING_LEFT
end if
Player.State = Player_State_Climb
Player.Speed = 0
Player.XVelocity = 0
Player.YVelocity = 0
Player.Timer = 0
PlaySfx(SFX_G_GRAB, false)
game.callbackParam0 = 2
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
else
if TempValue0 == true
if TempValue1 == false
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT,
false, ECEFFECT_NONE)
end if

if CheckResult == false
Player.Speed = 0
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
else
if Player.CollisionMode == CMODE_FLOOR
Player.Timer = 0
Player.State = Player_State_GlideSlide
Player.Animation = ANI_GLIDING_STOP
Player.Speed = Player.XVelocity
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
end if

CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_State_GlideDrop
#platform: Use_Origins
if Player.Gravity == GRAVITY_AIR
CallFunction(Player_HandleAirFriction)
CallFunction(Player_HandleAirMovement)
else
if Player.JumpPress == true
Player.XVelocity = 0
Player.Speed = 0
if Player.Down == true
CallFunction(Player.ActionSpindash)
else
CallFunction(Player_Action_Jump)
end if
else
if Player.AbilityTimer == 0
PlaySfx(SFX_G_GLIDEDROPLAND, false)
end if

Player.TrackScroll = false
Player.Speed = 0
Player.XVelocity = 0
Player.Animation = ANI_LOOKINGDOWN
Player.PrevAnimation = ANI_LOOKINGDOWN
Player.Frame = 2

if Player.AbilityTimer < 16
Player.AbilityTimer++
else
Player.AbilityTimer = 0
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
if Warp.Destination > 0
if Warp.Timer > 99
if Warp.Timer < 204
Warp.Destination = 0
end if
end if
Warp.Timer = 0
end if
end if
end if
end if
#endplatform
end function

function Player_State_GlideSlide
#platform: Use_Origins
if Player.Gravity == GRAVITY_GROUND
if Player.Speed == 0
if Player.JumpPress == true
if Player.Down == true
CallFunction(Player.ActionSpindash)
else
CallFunction(Player_Action_Jump)
end if
else
Player.TrackScroll = false
Player.Frame = 1
if Player.Timer < 16
Player.Timer++
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
end if
else
Player.Timer++
TempValue0 = Player.Timer
TempValue0 %= 4
if TempValue0 == 0
CreateTempObject(TypeName[Dust Puff], 0, Player.XPos,
Player.YPos)
Object[TempObjectPos].iYPos += Player.CollisionBottom
Object[TempObjectPos].DrawOrder = Player.DrawOrder
end if

Player.Timer %= 8
if Player.Timer == 0
PlaySfx(SFX_G_SLIDE, false)
end if

Player.Frame = 0
if Player.Speed > 0
Player.Speed -= 0x2000
if Player.Speed < 0
Player.Speed = 0
Player.Timer = 0
end if
else
Player.Speed += 0x2000
if Player.Speed > 0
Player.Speed = 0
Player.Timer = 0
end if
end if
if Player.JumpHold == 0
Player.Speed = 0
Player.Timer = 0
end if
end if

Player.XVelocity = Player.Speed
else
CallFunction(Player_Action_GlideDrop)
end if
#endplatform
end function

function Player_State_Climb
#platform: Use_Origins
if Player.Gravity == GRAVITY_AIR
Player.Animation = ANI_CLIMBING
if Player.Up == true
Player.YVelocity = -0x10000
TempValue0 = Player.CollisionTop
TempValue0 *= -0x10000
if Player.YPos < TempValue0
Player.YPos = TempValue0
end if

Player.Timer++
if Player.Timer == 4
Player.Timer = 0
Player.Frame++
if Mini_PlayerFlag == true
Player.Frame %= 2
else
Player.Frame %= 6
end if
end if
else
if Player.Down == true
Player.YVelocity = 0x10000
Player.Timer++
if Player.Timer == 4
Player.Timer = 0
if Player.Frame < 1
if Mini_PlayerFlag == true
Player.Frame += 2
else
Player.Frame += 6
end if
end if
Player.Frame--
end if
else
Player.YVelocity = 0
end if
end if

if Player.JumpPress == true
Player.Animation = ANI_JUMPING
Player.State = Player_State_Air_NoDropDash
Player.Timer = 0
if Player.Direction == FACING_LEFT
Player.XVelocity = 0x40000
Player.Speed = 0x40000
Player.Direction = FACING_RIGHT
else
Player.XVelocity = -0x40000
Player.Speed = -0x40000
Player.Direction = FACING_LEFT
end if

Player.YVelocity = -0x40000
if Player.GravityStrength != 0x3800 // (see if Knuckles is
underwater)
Player.XVelocity >>= 1
Player.Speed >>= 1
Player.YVelocity >>= 1
end if
else
if Mini_PlayerFlag == true
TempValue4 = 7
TempValue5 = -6
else
TempValue4 = 10
TempValue5 = -10
end if

if Player.Direction == FACING_RIGHT
TempValue2 = Player.XPos
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileGrip(CSIDE_LWALL, TempValue4, TempValue5,
Player.CollisionPlane)
TempValue0 = CheckResult
if TempValue0 == 0
Player.XPos = TempValue2
Object.XPos = Player.XPos
ObjectTileGrip(CSIDE_LWALL, TempValue4, 11,
Player.CollisionPlane)
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, true,
ECEFFECT_NONE)
TempValue0 = CheckResult
end if
Player.XPos = Object.XPos
TempValue3 = Player.XPos
Player.XPos = TempValue2
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileGrip(CSIDE_LWALL, TempValue4, 11,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue1 = CheckResult
if TempValue1 == 0
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, false,
ECEFFECT_NONE)
TempValue1 = CheckResult
end if
if Player.XPos > TempValue3
Player.XPos = TempValue3
end if
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, false,
ECEFFECT_RESETSTORAGE)
else
if Mini_PlayerFlag == true
TempValue4 = -7
else
TempValue4 = -10
end if

TempValue2 = Player.XPos
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileGrip(CSIDE_RWALL, TempValue4, TempValue5,
Player.CollisionPlane)
TempValue0 = CheckResult
if TempValue0 == 0
Player.XPos = TempValue2
Object.XPos = Player.XPos
ObjectTileGrip(CSIDE_RWALL, TempValue4, 11,
Player.CollisionPlane)
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, true,
ECEFFECT_NONE)
TempValue0 = CheckResult
end if
Player.XPos = Object.XPos
TempValue3 = Player.XPos
Player.XPos = TempValue2
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileGrip(CSIDE_RWALL, TempValue4, 11,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue1 = CheckResult
if TempValue1 == 0
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, false,
ECEFFECT_NONE)
TempValue1 = CheckResult
end if
if Player.XPos < TempValue3
Player.XPos = TempValue3
end if
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, false,
ECEFFECT_RESETSTORAGE)
end if
if TempValue0 == 0
if Player.YVelocity < 0
Player.XPos = TempValue2
Player.Animation = ANI_LEDGEPULLUP
Player.YVelocity = 0
Player.Timer = 0
Player.State = Player_State_LedgePullUp
Player.TileCollisions = false
if Player.Direction == FACING_RIGHT
Player.XPos += 0x10000
end if
end if
else
if TempValue1 == 0
Player.PrevAnimation = ANI_GLIDING_DROP
Player.Frame = 2
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
Player.Animation = ANI_WALKING
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
end if
#endplatform
end function

function Player_State_LedgePullUp
#platform: Use_Origins
switch Player.Frame
case 0
if Player.Timer < 5
ObjectTileGrip(CSIDE_FLOOR, 12, -9, Player.CollisionPlane)
Player.Timer++
else
Player.Timer = 0
Player.Frame++
if Player.Direction == FACING_RIGHT
Player.XPos += 0x90000
else
Player.XPos -= 0x90000
end if
Player.YPos -= 0xA0000
end if
break

case 1
if Player.Timer < 5
Player.Timer++
else
Player.Timer = 0
Player.Frame++
if Player.Direction == FACING_RIGHT
Player.XPos += 0x50000
else
Player.XPos -= 0x50000
end if
end if
break

case 2
if Player.Timer < 5
Player.Timer++
else
Player.Timer = 0
Player.Animation = ANI_STOPPED
Player.State = Player_State_Air_NoDropDash
Player.YPos -= 0x80000
Player.TileCollisions = true
end if
break

end switch
#endplatform
end function
function Player_State_GlideLeftNoGrip
#platform: Use_Origins
if Player.Gravity == GRAVITY_AIR
if Player.JumpHold == true
if Player.Timer == 256
if Player.Speed < 0x180000
Player.Speed += 0x400
end if
else
if Player.Speed < 0x40000
Player.Speed += 0x1000
end if
end if

if Player.YVelocity > 0x8000


Player.YVelocity -= 0x2000
else
Player.YVelocity += 0x2000
end if

if Player.Timer < 256


Player.Timer += 4
end if

if Player.Timer < 170


if Player.Timer > 86
Player.Frame = 0
else
if Player.Timer > 44
Player.Frame = 1
else
Player.Frame = 2
end if
end if
else
if Player.Timer < 212
Player.Frame = 1
else
Player.Frame = 2
end if
end if

TempValue7 = Player.XPos
if Player.Timer < 128
Player.Direction = FACING_RIGHT
TempValue0 = false
TempValue1 = false
else
Player.Direction = FACING_LEFT
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Player.YPos = Player.YPos
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_RWALL, -12, -2,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue0 = CheckResult
TempValue2 = Player.XPos
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_RWALL, -12, 11,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue1 = CheckResult
TempValue3 = Player.XPos
end if

Cos(Player.XVelocity, Player.Timer)
Player.XVelocity *= Player.Speed
Player.XVelocity >>= 9
if Player.Right == true
Player.State = Player_State_GlideRightNoGrip
end if

Player.XPos = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
TempValue0 = false
ArrayPos0 = 32
while ArrayPos0 < 1056
CheckEqual(Object[ArrayPos0].Type, TypeName[Blank
Object]) // huh? maybe this is supposed to be [NoGripArea], but you can't use stage
object TypeNames in global objects...
if CheckResult == true
if Object[ArrayPos0].Value0 == true
TempValue0 = true
end if
end if
ArrayPos0++
loop

if TempValue0 == false
if TempValue2 == TempValue3
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
else
if Player.CollisionMode == CMODE_FLOOR
Player.Timer = 0
Player.State = Player_State_GlideSlide
Player.Animation = ANI_GLIDING_STOP
Player.Speed = Player.XVelocity
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
end if

CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_State_GlideRightNoGrip
#platform: Use_Origins
if Player.Gravity == GRAVITY_AIR
if Player.JumpHold == true
if Player.Timer == 0
if Player.Speed < 0x180000
Player.Speed += 0x400
end if
else
if Player.Speed < 0x40000
Player.Speed += 0x1000
end if
end if

if Player.YVelocity > 0x8000


Player.YVelocity -= 0x2000
else
Player.YVelocity += 0x2000
end if

if Player.Timer > 0
Player.Timer -= 4
end if

if Player.Timer < 170


if Player.Timer > 86
Player.Frame = 0
else
if Player.Timer > 44
Player.Frame = 1
else
Player.Frame = 2
end if
end if
else
if Player.Timer < 212
Player.Frame = 1
else
Player.Frame = 2
end if
end if

TempValue7 = Player.XPos
if Player.Timer < 128
Player.Direction = FACING_RIGHT
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Player.YPos = Player.YPos
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_LWALL, 12, -2,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue0 = CheckResult
TempValue2 = Player.XPos
Player.XPos = TempValue7
Player.XPos += Player.XVelocity
Object.XPos = Player.XPos
Object.YPos = Player.YPos
ObjectTileCollision(CSIDE_LWALL, 12, 11,
Player.CollisionPlane)
Player.XPos = Object.XPos
TempValue1 = CheckResult
TempValue3 = Player.XPos
else
Player.Direction = FACING_LEFT
TempValue0 = false
TempValue1 = false
end if

Cos(Player.XVelocity, Player.Timer)
Player.XVelocity *= Player.Speed
Player.XVelocity >>= 9
if Player.Left == true
Player.State = Player_State_GlideLeftNoGrip
end if

Player.XPos = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
TempValue2 >>= 1
TempValue3 >>= 1
if TempValue2 == TempValue3
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
end if
else
Player.XVelocity >>= 2
Player.Speed = Player.XVelocity
CallFunction(Player_Action_GlideDrop)
end if
else
if Player.CollisionMode == CMODE_FLOOR
Player.Timer = 0
Player.State = Player_State_GlideSlide
Player.Animation = ANI_GLIDING_STOP
Player.Speed = Player.XVelocity
else
Player.State = Player_State_Ground
CallFunction(Player_HandleOnGround)
Player.Skidding = 0
end if
end if
CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_CheckRoofGlide
#platform: Use_Origins
// This function's just here to make sure that Knuckles doesn't go above the
stage in MMZ3 (not a good thing)
if Stage.ActiveList == REGULAR_STAGE
CheckEqual(Stage.ListPos, 68) // MMZ3C
TempValue0 = CheckResult
CheckEqual(Stage.ListPos, 69) // MMZ3D
TempValue0 |= CheckResult
if TempValue0 != false
if Stage.PlayerListPos == PLAYER_KNUCKLES // a bit redundant,
this func is only called in glide functions anyways..
if Player.RoofBarrier == true
TempValue0 = Player.YPos
TempValue0 >>= 16
if TempValue0 < Player.CollisionBottom
Player.YPos = Player.CollisionBottom
Player.YPos <<= 16
end if
end if
end if
end if
end if
#endplatform
end function

function Player_Action_GlideDrop
#platform: Use_Origins
// Bug Details:
// Player.Timer should probably be cleared here, but it isn't
// Because of this, doing things like landing from a drop after a left-facing
glide will make Knuckles skip to the middle of his idle animation immediately

Player.Animation = ANI_GLIDING_DROP
Player.AbilityTimer = 0
Player.State = Player_State_GlideDrop
#endplatform
end function

function Player_Action_DblJumpAmy
#platform: Use_Origins
if Player.JumpPress == true
PlaySfx(SFX_G_HAMMERJUMP, false)
game.callbackParam0 = 0
game.callbackParam1 = 1
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
TempValue0 = Player.AnimationSpeed
TempValue1 = Player.Frame
Player.Animation = ANI_HAMMER_JUMP
ProcessAnimation()
Player.AnimationSpeed = TempValue0
Player.Frame = TempValue1
end if
#endplatform
end function

function Player_Action_HammerDash
#platform: Use_Origins
PlaySfx(SFX_G_HAMMERDASH, false)
Player.State = Player_State_HammerDash
Player.Animation = ANI_HAMMER_DASH
Player.Timer = 0
Player.DropDashCharge = -1
CallFunction(Player_SetHammerDashSpeed)
#endplatform
end function

function Player_State_HammerDash
#platform: Use_Origins
if Player.Right == true
Player.Direction = FACING_RIGHT
else
if Player.Left == true
Player.Direction = FACING_LEFT
end if
end if

TempValue0 = true

if Player.Speed != 0
Player.Timer++
if Player.JumpHold == true
if Player.Timer < 60
CallFunction(Player_SetHammerDashSpeed)
if Player.Gravity == GRAVITY_AIR
CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleOnGround)
end if
TempValue0 = false
end if
end if
end if

// If Amy is on a steep enough slope, cancel the move


// (Despite the patch notes for version 2.01 claiming this was removed, it's
very much still here)
Cos256(TempValue1, Player.Angle)
if TempValue1 <= 0
TempValue0 = true
end if

if TempValue0 == true
Player.State = Player_State_Ground
end if
#endplatform
end function
function Player_SetHammerDashSpeed
#platform: Use_Origins
if Player.Direction == FACING_RIGHT
Player.Speed = 0x60000
else
// Could they not have just set it to -0x60000?
Player.Speed = 0
Player.Speed -= 0x60000
end if
#endplatform
end function

function Player_Setup_Startup
#platform: Use_Origins
ResetObjectEntity(0, TypeName[Player Object], 0, Object[ArrayPos0].XPos,
Object[ArrayPos0].YPos)

Player.XPos = Object[ArrayPos0].XPos
Player.YPos = Object[ArrayPos0].YPos

if Mini_PlayerFlag == false
if Stage.PlayerListPos == PLAYER_SONIC
LoadAnimation("Sonic.Ani")
end if

if Stage.PlayerListPos == PLAYER_TAILS
LoadAnimation("Tails.Ani")
end if

if Stage.PlayerListPos == PLAYER_KNUCKLES
LoadAnimation("Knuckles.Ani")
end if

if Stage.PlayerListPos == PLAYER_AMY
LoadAnimation("Amy.Ani")
end if
else
if Stage.PlayerListPos == PLAYER_SONIC
LoadAnimation("MiniSonic.Ani")
end if

if Stage.PlayerListPos == PLAYER_TAILS
LoadAnimation("MiniTails.Ani")
Object[1].Type = TypeName[Blank Object]
end if

// it's not like Knuckles or Amy have any tails to worry about...
if Stage.PlayerListPos == PLAYER_KNUCKLES
LoadAnimation("MiniKnuckles.Ani")
Object[1].Type = TypeName[Blank Object]
end if

if Stage.PlayerListPos == PLAYER_AMY
LoadAnimation("MiniAmy.Ani")
Object[1].Type = TypeName[Blank Object]
end if
end if

BindPlayerToObject(0, 0)

Player.State = Player_State_Air_NoDropDash
Player.Priority = PRIORITY_ACTIVE
Player.DrawOrder = 4

Player.TopSpeed = 0x60000
Player.Acceleration = 0xC00
Player.Deceleration = 0xC00
Player.AirAcceleration = 0x1800
Player.AirDeceleration = 0x600
Player.GravityStrength = 0x3800
Player.JumpStrength = 0x68000
Player.JumpCap = -0x40000
Player.RollingDeceleration = 0x2000

if Stage.PlayerListPos == PLAYER_SONIC
Player.JumpAbility = Player_State_Static
if Options.OriginalControls == false
Player.ActionPeelout = Player_Action_Peelout_S2
Player.ActionSpindash = Player_Action_Spindash_S2
else
Player.ActionPeelout = Player_Action_Peelout_CD
Player.ActionSpindash = Player_Action_Spindash_CD
end if
end if

if Stage.PlayerListPos == PLAYER_TAILS
Player.JumpAbility = Player_Action_DblJumpTails
Player.ActionPeelout = Player_Action_Jump
if Options.OriginalControls == false
Player.ActionSpindash = Player_Action_Spindash_S2
else
Player.ActionSpindash = Player_Action_Spindash_CD
end if
end if

if Stage.PlayerListPos == PLAYER_KNUCKLES
Player.JumpStrength = 0x60000
Player.JumpAbility = Player_Action_DblJumpKnux
Player.ActionPeelout = Player_Action_Jump
if Options.OriginalControls == false
Player.ActionSpindash = Player_Action_Spindash_S2
else
Player.ActionSpindash = Player_Action_Spindash_CD
end if
end if

if Stage.PlayerListPos == PLAYER_AMY
Player.JumpAbility = Player_Action_DblJumpAmy
Player.ActionPeelout = Player_Action_Jump
if Options.OriginalControls == false
Player.ActionSpindash = Player_Action_Spindash_S2
else
Player.ActionSpindash = Player_Action_Spindash_CD
end if
end if
CallFunction(Player_SetJumpOffset)

GetAnimationByName(ANI_SPINNING_TOP, "Spinning Top")


GetAnimationByName(ANI_RAMP_RUNNING1, "3D Ramp 1")
GetAnimationByName(ANI_RAMP_RUNNING2, "3D Ramp 2")
GetAnimationByName(ANI_RAMP_RUNNING3, "3D Ramp 3")
GetAnimationByName(ANI_RAMP_RUNNING4, "3D Ramp 4")
GetAnimationByName(ANI_RAMP_RUNNING5, "3D Ramp 5")
GetAnimationByName(ANI_RAMP_RUNNING6, "3D Ramp 6")
GetAnimationByName(ANI_ROLL3D, "3D Ramp 7")
GetAnimationByName(ANI_SIZE_CHANGE, "Size Change")
ResetObjectEntity(ArrayPos0, TypeName[Blank Object], 0, 0, 0)
#endplatform
end function

sub ObjectMain
// Only PC had access to debug mode, so here's a hack to prevent it on mobile
TempValue0 = false
#platform: Standard
TempValue0 = Stage.DebugMode
#endplatform

if TempValue0 == true
if KeyPress[1].ButtonB == true // Turn Debug Mode
Object.Type = TypeName[Debug Mode]

if Stage.PlayerListPos != PLAYER_SONIC_A // PLAYER_SONIC in


origins
Object[+1].Type = TypeName[Blank Object]
end if

Player.YVelocity = 0
Player.State = Player_State_Static
Player.Frame = 0
Player.Rotation = 0

Player.ObjectInteraction = false
Player.TileCollisions = true
Player.DrawOrder = 4

Player.AbilityTimer = 0
Player.MinRollSpeed = 0

Screen.CameraEnabled = true
Screen.CameraStyle = Options.OriginalControls
else
// Handle Player
CallFunction(Player_ProcessUpdate)
CallFunction(Player.State)
ProcessAnimation()

if Player.Animation == ANI_JUMPING
Screen.AdjustCameraY = Player.JumpOffset
else
if Screen.AdjustCameraY == Player.JumpOffset
Screen.AdjustCameraY = 0
Player.iYPos += Player.JumpOffset
end if
end if

if Player.YVelocity > 0x100000


Player.YVelocity = 0x100000
end if

PlayerTileCollision()

if CheckResult == true
if Player.Animation == ANI_JUMPING
if Player.Down == false
Player.Animation = ANI_WALKING
Screen.AdjustCameraY = 0
Player.iYPos += Player.JumpOffset
end if
end if
end if
end if
else
// Mobile version ObjectMain starts here, since there wasn't a debug
mode
// Handle Player
CallFunction(Player_ProcessUpdate)
CallFunction(Player.State)

#platform: Use_Origins
if Player.DropDashCharge >= 20
if Player.Animation == ANI_JUMPING
Player.Frame = 0
Player.AnimationTimer = 0
Player.AnimationSpeed = 1
end if
end if
#endplatform

ProcessAnimation()

if Player.Animation == ANI_JUMPING
Screen.AdjustCameraY = Player.JumpOffset
else
if Screen.AdjustCameraY == Player.JumpOffset
Screen.AdjustCameraY = 0
Player.iYPos += Player.JumpOffset
end if
end if

if Player.YVelocity > 0x100000


Player.YVelocity = 0x100000
end if

PlayerTileCollision()
if CheckResult == true
if Player.Animation == ANI_JUMPING
if Player.Down == false
Player.Animation = ANI_WALKING
Screen.AdjustCameraY = 0
Player.iYPos += Player.JumpOffset
end if
end if
end if
end if
end sub

sub ObjectDraw
if Player.Animation != Player.PrevAnimation
Player.PrevAnimation = Player.Animation
Player.Frame = 0
Player.AnimationTimer = 0
Player.AnimationSpeed = 0
end if

DrawPlayerAnimation()
end sub

sub ObjectStartup
#platform: Use_Origins
// I feel like I got spoiled on a Knuckles route...
TempValue0 = false
CheckGreater(Warp.Timer, 204)
TempValue0 |= CheckResult
TempValue0 &= Mini_PlayerFlag
Mini_PlayerFlag = TempValue0
Warp.Timer = 0

if Options.AttractMode == false
if Options.StageSelectFlag == false
ReadSaveRAM()
end if
end if

// Origins Plus includes new start positions for Knuckles in some levels
ArrayPos1 = 32
TempValue5 = 0
TempValue6 = 0
while ArrayPos1 < 1056
// So now we have to check how many player objects the game found
if Object[ArrayPos1].Type == TypeName[Player Object]
TempValue5++
end if
ArrayPos1++
loop

// We found multiple spawn points, now check which one to use


if TempValue5 > 1
ArrayPos1 = 32
TempValue7 = 0
while ArrayPos1 < 1056
if Object[ArrayPos1].Type == TypeName[Player Object]
// The standard spawnpoint
if Object[ArrayPos1].PropertyValue == 0
TempValue7 = ArrayPos1
end if

// Character specific spawnpoint


if Object[ArrayPos1].PropertyValue == Stage.PlayerListPos
TempValue6 = ArrayPos1
ArrayPos1 = 1056
end if
end if
ArrayPos1++
loop

// If we didn't find a special spawnpoint, just use the regular one


if TempValue6 == 0
TempValue6 = TempValue7
end if
end if

// Get rid of all spawnpoints except the one we're going to use
TempValue7 = 0
ArrayPos0 = 32
while ArrayPos0 < 1056
if Object[ArrayPos0].Type == TypeName[Player Object]
if TempValue5 > 1
if ArrayPos0 == TempValue6
CallFunction(Player_Setup_Startup)
else
ResetObjectEntity(ArrayPos0, TypeName[Blank Object],
0, 0, 0)
end if
else
TempValue7 = ArrayPos0
end if
end if
ArrayPos0++
loop

if TempValue7 > 0
ArrayPos0 = TempValue7
CallFunction(Player_Setup_Startup)
end if
#endplatform

#platform: Use_Standalone
ArrayPos0 = 32
while ArrayPos0 < 1056
if Object[ArrayPos0].Type == TypeName[Player Object]
switch Stage.PlayerListPos
case PLAYER_SONIC_A
ResetObjectEntity(0, TypeName[Player Object], 0,
Object[ArrayPos0].XPos, Object[ArrayPos0].YPos)
Player.XPos = Object[ArrayPos0].XPos
Player.YPos = Object[ArrayPos0].YPos

LoadAnimation("Sonic.Ani")
BindPlayerToObject(0, 0)

Player.State = Player_State_Air

Player.Priority = PRIORITY_ACTIVE

Player.DrawOrder = 4

Player.TopSpeed = 0x60000
Player.Acceleration = 0xC00
Player.Deceleration = 0xC00
Player.AirAcceleration = 0x1800
Player.AirDeceleration = 0x600
Player.GravityStrength = 0x3800
Player.JumpStrength = 0x68000
Player.JumpCap = -0x40000
Player.RollingDeceleration = 0x2000

Player.JumpOffset = -5

Player.JumpAbility = Player_State_Static
if Options.OriginalControls == false
Player.ActionPeelout = Player_Action_Peelout_S2
Player.ActionSpindash = Player_Action_Spindash_S2
else
Player.ActionPeelout = Player_Action_Peelout_CD
Player.ActionSpindash = Player_Action_Spindash_CD
end if
break

case PLAYER_TAILS_A
ResetObjectEntity(0, TypeName[Player Object], 0,
Object[ArrayPos0].XPos, Object[ArrayPos0].YPos)
Player.XPos = Object[ArrayPos0].XPos
Player.YPos = Object[ArrayPos0].YPos

LoadAnimation("Tails.Ani")
BindPlayerToObject(0, 0)

Player.State = Player_State_Air
Player.Priority = PRIORITY_ACTIVE
Player.DrawOrder = 4

Player.TopSpeed = 0x60000
Player.Acceleration = 0xC00
Player.Deceleration = 0xC00
Player.AirAcceleration = 0x1800
Player.AirDeceleration = 0x600
Player.GravityStrength = 0x3800
Player.JumpStrength = 0x68000
Player.JumpCap = -0x40000
Player.RollingDeceleration = 0x2000

Player.JumpOffset = -1

Player.JumpAbility =
Player_Action_DblJumpTails
Player.ActionPeelout = Player_Action_Jump
if Options.OriginalControls == false
Player.ActionSpindash = Player_Action_Spindash_S2
else
Player.ActionSpindash = Player_Action_Spindash_CD
end if
break

end switch

GetAnimationByName(ANI_SPINNING_TOP, "Spinning Top")


GetAnimationByName(ANI_RAMP_RUNNING1, "3D Ramp 1")
GetAnimationByName(ANI_RAMP_RUNNING2, "3D Ramp 2")
GetAnimationByName(ANI_RAMP_RUNNING3, "3D Ramp 3")
GetAnimationByName(ANI_RAMP_RUNNING4, "3D Ramp 4")
GetAnimationByName(ANI_RAMP_RUNNING5, "3D Ramp 5")
GetAnimationByName(ANI_RAMP_RUNNING6, "3D Ramp 6")
GetAnimationByName(ANI_ROLL3D, "3D Ramp 7")
GetAnimationByName(ANI_SIZE_CHANGE, "Size Change")

ResetObjectEntity(ArrayPos0, TypeName[Blank Object], 0, 0, 0)


end if

ArrayPos0++
loop
#endplatform
end sub

// ========================
// Editor Subs
// ========================

// All of the Character ID stuff is specific to Origins Plus, other versions of the
game don't check or use the PropertyValue

sub RSDKEdit
if Editor.ReturnVariable == true
switch Editor.VariableID
case EDIT_VAR_PROPVAL // Property Value
CheckResult = Object.PropertyValue
break
case 0 // Character ID
CheckResult = Object.PropertyValue
break
end switch
else
switch Editor.VariableID
case EDIT_VAR_PROPVAL // Property Value
Object.PropertyValue = Editor.VariableValue
break
case 0 // Character ID
Object.PropertyValue = Editor.VariableValue
break
end switch
end if
end sub

sub RSDKDraw
switch Object.PropertyValue
default
LoadSpriteSheet("Players/Sonic1.gif")
DrawSprite(0)
break

case 1
LoadSpriteSheet("Players/Tails1.gif")
DrawSprite(1)
break
case 2
LoadSpriteSheet("Players/KTE1.gif")
DrawSprite(2)
break

case 5
LoadSpriteSheet("Players/Amy1.gif")
DrawSprite(3)
break
end switch
end sub

sub RSDKLoad
LoadSpriteSheet("Players/Sonic1.gif")
SpriteFrame(-16, -19, 28, 39, 1, 1) // Sonic Standing Frame

LoadSpriteSheet("Players/Tails1.gif")
SpriteFrame(-12, -12, 24, 32, 1, 1) // Tails Standing Frame

LoadSpriteSheet("Players/KTE1.gif")
SpriteFrame(-14, -20, 26, 40, 1, 1) // Knuckles Standing Frame

LoadSpriteSheet("Players/Amy1.gif")
SpriteFrame(-12, -15, 21, 35, 45, 1) // Amy Standing Frame

AddEditorVariable("Character ID (Origins Plus)")


SetActiveVariable("Character ID (Origins Plus)")
AddEnumVariable("Sonic", PLAYER_SONIC_A)
AddEnumVariable("Tails", PLAYER_TAILS_A)
AddEnumVariable("Knuckles", PLAYER_KNUCKLES_A)
AddEnumVariable("Amy", PLAYER_AMY_A)
end sub

You might also like