0% found this document useful (0 votes)
30 views86 pages

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
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views86 pages

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
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

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

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


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

// Aliases
#alias Player.Value0 : [Link]
#alias Player.Value1 : [Link]
#alias Player.Value2 : [Link]
#alias Player.Value3 : [Link]
#alias Player.Value4 : [Link]
#alias Player.Value5 : [Link]
#alias Player.Value6 : [Link]
#alias Player.Value7 : [Link]
#alias Player.Value8 : [Link]
#alias Player.Value9 : [Link]
#alias Player.Value10 : [Link]
#alias Player.Value11 : [Link]
#alias Player.Value12 : [Link]

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

#alias Player.Value15 : [Link]

// Flailing states, v4 names explains this much better


#alias [Link][0] : [Link]
#alias [Link][1] : [Link]
#alias [Link][2] : [Link]

// LoseRing Aliases
#alias Object.Value0 : [Link]
#alias Object.Value1 : [Link]

// Warp Star Aliases


#alias Object[3].Value0 : [Link]
#alias Object[3].DrawOrder : [Link]

// Object Score Alias


#alias Object[26].Value0 : [Link]

// Pause Menu Aliases


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

// Debug Mode Alias


#alias Object[25].Value7 : [Link]

// Death Event Aliases


#alias Object.Value1 : DeathEvent.Text1XPos // Game or Time
#alias Object.Value2 : DeathEvent.Text2XPos // Over
#alias Object.Value3 : [Link] // Also used for fading
#alias [Link] : [Link]
#alias [Link] : [Link]

// 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([Link], ANI_JUMPING)
TempValue0 = CheckResult
#platform: Use_Origins
CheckEqual([Link], ANI_HAMMER_JUMP)
TempValue0 |= CheckResult
CheckEqual([Link], ANI_HAMMER_DASH)
TempValue0 |= CheckResult
#endplatform
CheckEqual([Link], ANI_SPINDASH)
TempValue0 |= CheckResult
#platform: Use_Origins
CheckEqual([Link], ANI_GLIDING)
TempValue0 |= CheckResult
CheckEqual([Link], ANI_GLIDING_STOP)
TempValue0 |= CheckResult
#endplatform

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

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


if [Link] > 0
TempValue0 |= true
end if

if [Link] == ANI_FLYING
CheckGreater([Link], [Link])
TempValue0 |= CheckResult
end if

#platform: Use_Origins
if [Link] == BOOT_PLAYMODE_MISSION
if [Link] == false
TempValue0 = false
end if
end if
#endplatform

if TempValue0 == true
ResetObjectEntity([Link], Flower_TypeNo, 0, [Link],
[Link])
[Link] = 4

CreateTempObject(TypeName[Smoke Puff], 0, [Link], [Link])


Object[TempObjectPos].DrawOrder = 4
CreateTempObject(TypeName[Object Score], [Link],
[Link], [Link])
Object[TempObjectPos].DrawOrder = 4
TempValue0 = false
#platform: Use_Origins
if [Link] == ANI_HAMMER_JUMP
TempValue0 = true
end if

if [Link] == 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 [Link] > 0
FlipSign([Link])
else
[Link] += 0xC000
end if

switch [Link]
case 0
[Link] += 100
break
case 1
[Link] += 200
break
case 2
[Link] += 500
break
case 3
[Link] += 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([Link], Player_State_Roll)
TempValue0 = CheckResult
CheckEqual([Link], Player_State_RollJump)
TempValue0 |= CheckResult
if TempValue0 == true
if [Link] == PLAYER_SONIC
game.callbackParam0 = KILL_ENEMY_ATTR_SPINDASH
StageStatsUsabilityParam2 += 1
end if
end if

StageStatsUsabilityParam1 += 1
EngineCallback(NOTIFY_KILL_ENEMY)
if [Link] == BOOT_PLAYMODE_MISSION
// Set during "M097 - Mercy"
if [Link] == RULE_MERCY_BADNIKS
[Link] = true
end if
end if
#endplatform
else
if [Link] == 0
[Link] = Player_State_GotHit

#platform: Use_Origins
if [Link] == BOOT_PLAYMODE_MISSION
if [Link] == RULE_MERCY_BADNIKS
[Link] = 1
end if
end if
#endplatform

if [Link] > [Link]


[Link] = 0x20000
else
[Link] = -0x20000
end if
end if
end if
end function

// Do you really need an explanation?


function Player_Hit
ArrayPos0 = [Link]
ArrayPos0 += 2
if Object[ArrayPos0].Type != TypeName[Invincibility]
if [Link] == 0
[Link] = Player_State_GotHit
if [Link] > [Link]
[Link] = 0x20000
else
[Link] = -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 [Link] != Player_State_Climb
TempValue0 = false
ArrayPos0 = 32
if [Link] == 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 [Link] == 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)
[Link] = Player_State_Climb
[Link] = 0
[Link] = 0
[Link] = 0
[Link] = 0
[Link] = GRAVITY_AIR
game.callbackParam0 = 2
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 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)
[Link] = ANI_GLIDING_DROP
[Link] = 2
#endplatform
end function
// See above, this one's p much only called by Bumpers
function Player_CancelClimb
#platform: Use_Origins
[Link] = ANI_WALKING
[Link] = 0
[Link] = 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 [Link] == Player_State_GlideLeft
[Link] = Player_State_GlideLeftNoGrip
end if

if [Link] == Player_State_GlideRight
[Link] = 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 [Link] == Player_State_GlideLeftNoGrip
[Link] = Player_State_GlideLeft
end if

if [Link] == Player_State_GlideRightNoGrip
[Link] = Player_State_GlideRight
end if
#endplatform
end function

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

[Link] = 5

[Link] = 0
[Link] = 0
[Link] = -0x68000

[Link] = Player_State_Death
[Link] = ANI_DYING

[Link] = false
[Link] = false
[Link] = false

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

function Player_ProcessUpdate
#platform: Standard
if [Link] == false
if [Link] == CONTROLMODE_NORMAL
if Object[9].Type == TypeName[Blank Object]
if KeyPress[1].Start == true
KeyPress[1].Start = false
if [Link] == true
[Link] = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
[Link] = 7
[Link] = 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 [Link] == false
if [Link] == CONTROLMODE_NORMAL
if Object[9].Type == TypeName[Blank Object]
if [Link] == MESSAGE_LOSTFOCUS
[Link] = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
[Link] = 7
[Link] = PRIORITY_ALWAYS
if [Link] > -1
[Link] = -1
end if
end if
end if
end if
end if
#endplatform

#platform: Mobile
if [Link] == false
if [Link] == true
if [Link] == CONTROLMODE_NORMAL
CheckTouchRect(0, 96, [Link], [Link])
if CheckResult > -1
ArrayPos0 = CheckResult
// D-Pad XPos
TempValue0 = TouchScreen[ArrayPos0].XPos
TempValue0 -= [Link]
// 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([Link], 96, [Link], 240)


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

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

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

CheckTouchRect(240, 0, [Link], 40)


if CheckResult > -1
[Link] = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
[Link] = 7
[Link] = PRIORITY_ALWAYS
if [Link] > -1
[Link] = -1
end if

end if

if [Link] == MESSAGE_LOSTFOCUS
[Link] = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
[Link] = 7
[Link] = PRIORITY_ALWAYS
if [Link] > -1
[Link] = -1
end if
end if
end if
end if
else
if [Link] == CONTROLMODE_NORMAL
if Object[9].Type == TypeName[Blank Object]
if KeyPress[1].Start == true

KeyPress[1].Start = false
[Link] = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
[Link] = 7
[Link] = PRIORITY_ALWAYS
if [Link] > -1
[Link] = -1
end if
end if

if [Link] == MESSAGE_LOSTFOCUS
[Link] = STAGE_PAUSED
PauseMusic()
PlaySfx(SFX_G_SELECT, false)
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
Object[9].Type = TypeName[Pause Menu]
[Link] = 7
[Link] = PRIORITY_ALWAYS
if [Link] > -1
[Link] = -1
end if
end if
end if
end if
end if

ProcessPlayerControl()
end if
#endplatform

// Speed Shoes control


if [Link] > 0
[Link]--
if [Link] == 0
[Link] = 0xC00
[Link] = 0x1800
[Link] = 0x60000
if [Link] == 3 // Speed Shoes
PlayMusic(0)
end if
end if
end if

// Invincibility Control
if [Link] > 0
if [Link] != Player_State_Hurt
if [Link] > 2000
[Link] = 120
[Link] = 3
end if
end if

if [Link] > 0
[Link]++
if [Link] > 8
[Link] = 1
end if
if [Link] > 4
[Link] = false
else
[Link] = true
end if
end if

[Link]--
if [Link] == 0
[Link] = 0
[Link] = true
if [Link] == 2 // Invincibility
PlayMusic(0)
end if
if Object[+2].Type == TypeName[Invincibility]
switch Object[+2].PropertyValue
case NO_SHIELD
TempValue0 = [Link]
TempValue0 += 2
ResetObjectEntity(TempValue0, TypeName[Blank Object],
0, 0, 0)
break

case ACTIVE_SHIELD
TempValue0 = [Link]
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 = [Link]
Object[+2].YPos = [Link]
break

end switch
end if
end if
end if
// Restore camera position after looking up / crounching
if [Link] != Player_State_LookUp
if [Link] != Player_State_Crouch
if [Link] > 0
[Link] -= 2
end if

if [Link] < 0
[Link] += 2
end if
end if
end if

if [Link] > 0
[Link]++

if [Link] == 204
[Link] = 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 [Link] > 0
[Link]--
if [Link] == 0
[Link] = CAMERASTYLE_FOLLOW
end if
end if

// Resets FlightVelocity
if [Link] != Player_State_Fly
if [Link] != 0
StopSFX(SFX_G_FLYING)
StopSFX(SFX_G_TIRED)
[Link] = 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 [Link] == PLAYER_TAILS_A
[Link] = 120
else
[Link] = [Link]
if [Link] < 0
FlipSign([Link])
end if
[Link] *= 240
[Link] /= 0x60000
[Link] += 48
end if
end function

// Animation speed while walking


function Player_HandleWalkAnimSpeed
[Link] = [Link]
if [Link] < 0
FlipSign([Link])
end if
[Link] *= 60
[Link] /= 0x60000
[Link] += 20
end function

// Animation speed while running


function Player_HandleRunAnimSpeed
[Link] = [Link]
if [Link] < 0
FlipSign([Link])
end if
[Link] *= 80
[Link] /= 0x60000
end function

// This makes you move


function Player_HandleGroundMovement
if [Link] > 0
[Link]--
Sin256(TempValue0, [Link])
TempValue0 *= 0x2000
TempValue0 >>= 8
[Link] += TempValue0
else
if [Link] == true
TempValue0 = [Link]
FlipSign(TempValue0)
if [Link] > TempValue0
if [Link] > 0
if [Link] == CMODE_FLOOR
// Skid
if [Link] > 0x40000
[Link] = 16
end if
end if

if [Link] < 0x8000


[Link] = -0x8000
[Link] = 0
else
[Link] -= 0x8000
end if
else
[Link] -= [Link]
[Link] = 0
end if
end if

if [Link] <= 0
[Link] = FACING_LEFT
end if
end if

if [Link] == true
if [Link] < [Link]
if [Link] < 0
if [Link] == CMODE_FLOOR
// Skid
if [Link] < -0x40000
[Link] = 16
end if
end if

if [Link] > -0x8000


[Link] = 0x8000
[Link] = 0
else
[Link] += 0x8000
end if
else
[Link] += [Link]
[Link] = 0
end if
end if

if [Link] >= 0
[Link] = FACING_RIGHT
end if
end if

TempValue0 = [Link]
TempValue0 |= [Link]
if TempValue0 == false
//tldr, reduce speed with desaceleration, or based on angle
if [Link] > 0
[Link] -= [Link]
if [Link] < 0
[Link] = 0
end if
else
[Link] += [Link]
if [Link] > 0
[Link] = 0
end if
end if

if [Link] > 0x2000


Sin256(TempValue0, [Link])
TempValue0 *= 0x2000
TempValue0 >>= 8
[Link] += TempValue0
end if

if [Link] < -0x2000


Sin256(TempValue0, [Link])
TempValue0 *= 0x2000
TempValue0 >>= 8
[Link] += TempValue0
end if

if [Link] > 192


if [Link] < 228
if [Link] > -0x10000
if [Link] < 0x10000
[Link] = 30 // Lock the
player to move out of the angle
end if
end if
end if
end if

if [Link] > 28
if [Link] < 64
if [Link] > -0x10000
if [Link] < 0x10000
[Link] = 30 // Lock the
player to move out of the angle
end if
end if
end if
end if
else
Sin256(TempValue0, [Link])
TempValue0 *= 0x2000
TempValue0 >>= 8
[Link] += TempValue0

if [Link] == true
if [Link] == false
if [Link] > 192
if [Link] < 228
if [Link] < 0x28000
if [Link] > -0x20000
[Link] = 30 //
Lock the player to move out of the angle
end if
end if
end if
end if
end if
else
if [Link] == true
if [Link] > 28
if [Link] < 64
if [Link] > -0x28000
if [Link] < 0x20000
[Link] = 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 [Link] > -0x40000
if [Link] < 0
TempValue0 = [Link]
TempValue0 >>= 5
[Link] -= TempValue0
end if
end if
TempValue0 = [Link]
FlipSign(TempValue0)

if [Link] > TempValue0


if [Link] == true
[Link] -= [Link]
[Link] = FACING_LEFT
end if
else
if [Link] == true
[Link] = FACING_LEFT
end if
end if

if [Link] < [Link]


if [Link] == true
[Link] += [Link]
[Link] = FACING_RIGHT
end if
else
if [Link] == true
[Link] = FACING_RIGHT
end if
end if

if [Link] == true
if [Link] == true
TempValue0 = [Link]
FlipSign(TempValue0)
if [Link] < TempValue0
[Link] = TempValue0
end if
end if

if [Link] == true
if [Link] > [Link]
[Link] = [Link]
end if
end if
end if
end function
// Handles desaceleration while rolling
function Player_HandleRollDeceleration

if [Link] == true
if [Link] < 0
[Link] += [Link]
end if
end if

if [Link] == true
if [Link] > 0
[Link] -= [Link]
end if
end if

if [Link] > 0
[Link] -= [Link]
if [Link] < 0
[Link] = 0
end if

if [Link] == 0
if [Link] > 224
[Link] = Player_State_Ground
end if
if [Link] < 32
[Link] = Player_State_Ground
end if
end if

Sin256(TempValue0, [Link])
if TempValue0 > 0
Sin256(TempValue0, [Link])
TempValue0 *= 0x5000
else
Sin256(TempValue0, [Link])
TempValue0 *= 0x1E00
end if

TempValue0 >>= 8
[Link] += TempValue0
else
[Link] += [Link]
if [Link] > 0
[Link] = 0
end if

if [Link] == 0
if [Link] > 224
[Link] = Player_State_Ground
end if
if [Link] < 32
[Link] = Player_State_Ground
end if
end if

Sin256(TempValue0, [Link])
if TempValue0 < 0
Sin256(TempValue0, [Link])
TempValue0 *= 0x5000
else
Sin256(TempValue0, [Link])
TempValue0 *= 0x1E00
end if

TempValue0 >>= 8
[Link] += TempValue0
end if

if [Link] > 0x180000


[Link] = 0x180000
end if

if [Link] < -0x180000


[Link] = -0x180000
end if
end function

// Movement when you fall from a cliff


function Player_HandleAirMovement
[Link] = true

[Link] += [Link]
if [Link] < [Link]
if [Link] == false
if [Link] > 0
[Link] = [Link]
TempValue0 = [Link]
TempValue0 >>= 5
[Link] -= TempValue0
end if
end if
end if
[Link] = [Link]

if [Link] < 256


if [Link] > 0
[Link] -= 4
else
[Link] = 0
end if
else
if [Link] < 512
[Link] += 4
else
[Link] = 0
end if
end if

[Link] = CMODE_FLOOR
if [Link] == ANI_JUMPING
[Link] = [Link]
end if
end function

// Gets X and Y Velocity based on angles


function Player_HandleOnGround
[Link] = false
Cos256(TempValue0, [Link])
TempValue0 *= [Link]
TempValue0 >>= 8
[Link] = TempValue0

Sin256(TempValue0, [Link])
TempValue0 *= [Link]
TempValue0 >>= 8
[Link] = TempValue0
end function

// A classic move
function Player_Action_Jump
CheckResult = false
if [Link] == CMODE_FLOOR
TempValue6 = [Link]
TempValue7 = [Link]

[Link] = [Link]
[Link] = [Link]
TempValue0 = [Link]
TempValue0 -= 2
ObjectTileCollision(CSIDE_RWALL, 0, TempValue0, 0)

[Link] = TempValue6
[Link] = TempValue7
end if

if CheckResult == false
[Link] = 0
[Link] = GRAVITY_AIR
[Link] = 8

Sin256([Link], [Link])
[Link] *= [Link]
Cos256(TempValue0, [Link])
TempValue0 *= [Link]
[Link] += TempValue0
[Link] >>= 8

Sin256([Link], [Link])
[Link] *= [Link]
Cos256(TempValue0, [Link])
TempValue0 *= [Link]
[Link] -= TempValue0
[Link] >>= 8

[Link] = [Link]
[Link] = true
[Link] = ANI_JUMPING
[Link] = 0
[Link] = CMODE_FLOOR
[Link] = 1
CallFunction(Player_HandleRollAnimSpeed)

[Link] = Player_State_Air

PlaySfx(SFX_G_JUMP, false)
end if

#platform: Use_Origins
if [Link] == BOOT_PLAYMODE_CLASSIC
[Link] = -1
else
[Link] = 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
[Link] = Player_State_Spindash_S2
[Link] = ANI_SPINDASH
[Link] = 0

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

#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
[Link] = Player_State_Spindash_CD
[Link] = ANI_JUMPING
[Link] += 0x50000
[Link] = 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
[Link] = Player_State_Peelout_S2
[Link] = 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
[Link] = Player_State_Peelout_CD
[Link] = 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 [Link] > 0
[Link]--
else
if [Link] == true
[Link] = 0
[Link] = Player_State_Fly
[Link] = 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 [Link] == 0x3800
PlaySfx(SFX_G_FLYING, true)
[Link] = ANI_FLYING
else
[Link] = ANI_SWIMMING
end if
end if
end if
end function

function Player_State_Ground
if [Link] != ANI_SKIDDING // This handles that the skid only plays
sfx once
TempValue7 = true
else
TempValue7 = false
end if

CallFunction(Player_HandleGroundMovement)

if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleOnGround)
if [Link] == 0
// Consumes the warp if you stop too late during warping run
if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 220
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if

if [Link] == CMODE_FLOOR
#platform: Use_Origins
switch [Link]
case PLAYER_SONIC_A
case PLAYER_TAILS_A
// Original behaviour - Outta Here (Sonic, Classic
Mode only)
if [Link] < 240
[Link] = ANI_STOPPED
[Link]++
else // Waiting animation
[Link] = ANI_WAITING
if [Link] == PLAYER_SONIC
[Link]++
if [Link] == BOOT_PLAYMODE_CLASSIC
if [Link] == 10620 // 177
seconds (2 minutes, 57 seconds)
[Link] = 0

// This SFX is muted in


Origins
PlaySfx(SFX_G_OUTTAHERE,
false)

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

#platform: Use_Standalone
if [Link] < 240
[Link] = ANI_STOPPED
[Link]++
else // Waiting animation
[Link] = ANI_WAITING
if [Link] == PLAYER_SONIC_A
[Link]++
if [Link] == 10620 // I'm Outta Here!
[Link] = 0

PlaySfx(SFX_G_OUTTAHERE, false)

[Link] =
Player_State_OuttaHere
[Link] = ANI_BORED
end if
end if
end if
#endplatform

if [Link] == false
if [Link] == false
[Link] = 0
if [Link] == FACING_LEFT
[Link] = ANI_FLAILINGLEFT
else
[Link] = ANI_FLAILINGRIGHT
end if
end if

if [Link] == false
[Link] = 0

if [Link] == FACING_RIGHT
[Link] = ANI_FLAILINGLEFT
else
[Link] = ANI_FLAILINGRIGHT
end if
end if

end if

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

if [Link] > 0x9FFFF


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

if [Link] < -0x9FFFF


[Link] = ANI_PEELOUT
else
[Link] = ANI_RUNNING
end if
CallFunction(Player_HandleRunAnimSpeed)
end if

end if

end if

// Skidding
if [Link] > 0
if TempValue7 == true
PlaySfx(SFX_G_SKIDDING, false)
end if
[Link] = ANI_SKIDDING
[Link] = 0
[Link]--

if [Link] == 0
CreateTempObject(TypeName[Dust Puff], 0, [Link],
[Link])
Object[TempObjectPos].iYPos +=
[Link]
Object[TempObjectPos].DrawOrder = [Link]
end if

if [Link] > 0
[Link] = FACING_RIGHT
else
[Link] = FACING_LEFT
end if
end if
// Push, there's a small delay so 2 is our "true"
if [Link] == CMODE_FLOOR
if [Link] == 2
[Link] = ANI_PUSHING
[Link] = 0
end if
end if

// Jump
if [Link] == true
CallFunction(Player_Action_Jump)
else
// Look Up
if [Link] == true
if [Link] == 0
if [Link] != ANI_FLAILINGLEFT
if [Link] != ANI_FLAILINGRIGHT
[Link] =
Player_State_LookUp
[Link] = ANI_LOOKINGUP
[Link] = 0
end if
end if
end if
end if

// Crouch
if [Link] == true
if [Link] == 0
if [Link] != ANI_FLAILINGLEFT
if [Link] != ANI_FLAILINGRIGHT
[Link] =
Player_State_Crouch
[Link] = ANI_LOOKINGDOWN
[Link] = 0
end if
end if
else
// Roll
if [Link] == false
if [Link] == false
if [Link] > 0
if [Link] > 0x8800
[Link] =
Player_State_Roll
[Link] =
ANI_JUMPING
[Link] -=
[Link]
[Link] =
1024
end if
else
if [Link] < -0x8800
[Link] =
Player_State_Roll
[Link] =
ANI_JUMPING
[Link] -=
[Link]
[Link] =
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

[Link] = -1
[Link] = Player_State_Air
CallFunction(Player_State_Air)
end function

function Player_State_Air
CallFunction(Player_HandleAirFriction)
#platform: Use_Origins
if [Link] == PLAYER_TAILS
CallFunction(Player_HandleDropDash)
end if
#endplatform
if [Link] == GRAVITY_AIR // Check that you're truly in the air
CallFunction(Player_HandleAirMovement)

// More warp stuff


if [Link] > WARPDEST_NONE
TempValue0 = [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 < 0x60000


TempValue0 = [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 < 0x60000


TempValue0 = [Link]
TempValue0 -= [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 > 0x40000


if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
end if
end if
[Link] = [Link]
end if

// changes the flailing with the walking, not sure when this is used
if [Link] > 0x20000
if [Link] == ANI_FLAILINGLEFT
[Link] = ANI_WALKING
end if
if [Link] == ANI_FLAILINGRIGHT
[Link] = ANI_WALKING
end if
end if

// Post-Hitting a spring
if [Link] == ANI_BOUNCING
if [Link] >= 0
if [Link] == ANI_STOPPED
[Link] = ANI_WALKING
end if
[Link] = [Link]
end if
end if

// Post Getting hurt


if [Link] == ANI_HURT
if [Link] >= 0
if [Link] == ANI_STOPPED
[Link] = ANI_WALKING
end if
[Link] = [Link]
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 [Link] 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
[Link] are missing too...
// -> Not really sure why it turned out this way.
if [Link] == PLAYER_TAILS
if [Link] == ANI_JUMPING
CallFunction([Link])
end if
else
if [Link] >= [Link]
CallFunction(Player_HandleDropDash)
if [Link] == ANI_JUMPING
CallFunction([Link])
end if
end if
end if
#endplatform

#platform: Use_Standalone
if [Link] == ANI_JUMPING
CallFunction([Link])
end if
#endplatform
else
// go back to the ground silly
#platform: Use_Origins
if [Link] >= 20
if [Link] == PLAYER_AMY
CallFunction(Player_Action_HammerDash)
else
CallFunction(Player_Action_Spindash_S2)
end if
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
end if
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
#endplatform
end if
end function

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

if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleRollAnimSpeed)
[Link] = [Link]

TempValue0 = [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if

// Warp-Consuming
if TempValue0 < 0x5F5C2
if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
else
// Spawn Warp Stars
if [Link] > WARPDEST_NONE
if [Link] == 0
[Link] = 1
ResetObjectEntity(3, TypeName[Warp Star], 0,
[Link], [Link])
[Link] = 7
[Link] = 4
end if
end if
end if

CallFunction(Player_HandleOnGround)

if [Link] == 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 [Link] == true
[Link] = false
[Link] = false
end if

CallFunction(Player_HandleAirFriction)
if [Link] == PLAYER_TAILS
CallFunction(Player_HandleDropDash)
else
if [Link] >= [Link]
CallFunction(Player_HandleDropDash)
end if
end if
#endplatform

#platform: Use_Standalone
[Link] = false
[Link] = false
CallFunction(Player_HandleAirFriction)
#endplatform
if [Link] == GRAVITY_AIR
CallFunction(Player_HandleAirMovement)
else

#platform: Use_Origins
if [Link] >= 20
if [Link] == PLAYER_AMY
CallFunction(Player_Action_HammerDash)
else
CallFunction(Player_Action_Spindash_S2)
end if
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
end if
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
#endplatform

end if
end function

// Hey look up
function Player_State_LookUp
if [Link] == false
[Link] = Player_State_Ground
[Link] = 0
else
if [Link] < 60
[Link]++
else
if [Link] > -112
[Link] -= 2
end if
end if

if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
else
if [Link] == true
CallFunction([Link])
end if
end if
end if
end function

// Hey look down


function Player_State_Crouch
if [Link] == false
[Link] = Player_State_Ground
[Link] = 0
else
if [Link] < 60
[Link]++
else
if [Link] < 96
[Link] += 2
end if
end if

if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
else
if [Link] == true
CallFunction([Link])
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 [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
end if

// Mashing
if [Link] == true
if [Link] < 512
[Link] += 64
end if
[Link] = 0

PlaySfx(SFX_G_CHARGE, false)
else
if [Link] > 0
[Link]--
end if
end if

#platform: Use_Origins
TempValue1 = [Link]
if [Link] >= 20
[Link] = -1
Sin256(TempValue0, [Link])
if [Link] == 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

[Link] = TempValue0
TempValue1 = false
end if

CheckEqual(TempValue1, false)
#endplatform

#platform: Use_Standalone
CheckEqual([Link], false)
#endplatform
// Work around to adapt it to origins
// Spin Dash release
if CheckResult == true
[Link] = 0
[Link] = Player_State_Roll
[Link] = ANI_JUMPING
[Link] -= [Link]

[Link] = 15
[Link] = CAMERASTYLE_HLOCKED

TempValue0 = [Link]
TempValue0 <<= 9
TempValue0 += 0x80000

if [Link] == FACING_RIGHT
[Link] = TempValue0
else
[Link] = TempValue0
FlipSign([Link])
end if

PlaySfx(SFX_G_RELEASE, false)

CallFunction(Player_HandleOnGround)

#platform: Use_Origins
[Link] = 6
#endplatform

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

end if
end function

function Player_State_Spindash_CD
if [Link] == FACING_RIGHT
[Link] = CAMERASTYLE_EXTENDED_OFFSET_L
else
[Link] = CAMERASTYLE_EXTENDED_OFFSET_R
end if

// Keep the camera lock, cancel the spin dash


if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
[Link] = CAMERASTYLE_EXTENDED
end if

// Charge
if [Link] == 0x1000
if [Link] < 0x80000
[Link] += 0x6000
end if
else
if [Link] < 0xC0000
[Link] += 0x6000
end if
end if

// Release
if [Link] == false
[Link] = CAMERASTYLE_EXTENDED
[Link] = 0

if [Link] < 0x2FAE1


[Link] = 0
[Link] = Player_State_Ground
else
[Link] = Player_State_Roll
[Link] = ANI_JUMPING
[Link] = [Link]

if [Link] == FACING_LEFT
FlipSign([Link])
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 [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

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

// Release
if [Link] == false
[Link] = 15
[Link] = CAMERASTYLE_HLOCKED

[Link] = Player_State_Ground
// Cancels the peel out if you didn't charged it enough
if [Link] < 0x5F5C2
[Link] = 0
else
[Link] = [Link]
if [Link] == FACING_LEFT
FlipSign([Link])
end if
PlaySfx(SFX_G_RELEASE, false)
end if
CallFunction(Player_HandleOnGround)

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

end if
[Link] = TempValue0
end function

function Player_State_Peelout_CD
// Moves the camera
if [Link] == FACING_RIGHT
[Link] = CAMERASTYLE_EXTENDED_OFFSET_L
else
[Link] = CAMERASTYLE_EXTENDED_OFFSET_R
end if
// Cancels the Peel Out, keeps the camera
if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
[Link] = CAMERASTYLE_EXTENDED
end if

// Charge
if [Link] == 0x1000
if [Link] < 0x60000
[Link] += 0x6000
end if
else
if [Link] < 0xC0000
[Link] += 0x6000
end if
end if

// Speed building, from walking to running then peelout


if [Link] < 0x5F5C2
[Link] = ANI_WALKING
TempValue0 = [Link]
TempValue0 >>= 16
TempValue0 *= 80
TempValue0 /= 6
TempValue0 += 20
else
TempValue0 = [Link]
TempValue0 >>= 16
TempValue0 *= 80
TempValue0 /= 6
if [Link] > 0x9FFFF
[Link] = ANI_PEELOUT
else
[Link] = ANI_RUNNING
end if
end if

// Release
if [Link] == false
[Link] = CAMERASTYLE_EXTENDED

[Link] = Player_State_Ground
// Cancels the peel out if you didn't charged it enough
if [Link] < 0x5F5C2
[Link] = 0
else
[Link] = [Link]
if [Link] == FACING_LEFT
FlipSign([Link])
end if

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

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

end if
[Link] = TempValue0
end function

// Tails flight
function Player_State_Fly
CallFunction(Player_HandleAirFriction)
if [Link] == GRAVITY_AIR
[Link] = [Link]
// Check if you have enough speed while flying to keep the warp
if [Link] > WARPDEST_NONE
TempValue0 = [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if

TempValue1 = [Link]
if TempValue1 < 0
FlipSign(TempValue1)
end if

TempValue0 += TempValue1
if TempValue0 < 0x40000
if [Link] > 99
if [Link] < 220
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
end if

if [Link] < -0x10000


[Link] = 0x800
else
if [Link] < 1
if [Link] < 60
[Link]++
else
[Link] = 0x800
end if
end if
end if

[Link] += [Link]
if [Link] < 480
if [Link] == 0x3800
[Link] = ANI_FLYING
else
[Link] = ANI_SWIMMING
end if

[Link]++
if [Link] == 480
if [Link] == 0x3800
[Link] = ANI_FLYINGTIRED
StopSfx(SFX_G_FLYING)
PlaySfx(SFX_G_TIRED, true)
else
[Link] = ANI_SWIMMINGTIRED
end if
else
if [Link] == true
[Link] = -0x2000
[Link] = 0
end if
end if
else
if [Link] == 0x3800
[Link] = ANI_FLYINGTIRED
else
[Link] = ANI_SWIMMINGTIRED
end if
end if
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
end if

// If the level has a roof barrier, you're not getting too far
if [Link] == true
TempValue0 = [Link]
TempValue0 >>= 16
if TempValue0 < [Link]
[Link] = [Link]
[Link] <<= 16
end if
end if
end function

// Player Damage
function Player_State_GotHit
#platform: Use_Origins
TempValue1 = false
if [Link] == BOOT_PLAYMODE_MISSION
if [Link] == RULE_MERCY_BADNIKS
if [Link] == 1
[Link] = 0
TempValue1 = true
end if
end if
end if
#endplatform

ArrayPos0 = [Link]
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 [Link] == 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

[Link] = Player_State_Hurt
[Link] = ANI_HURT
[Link] = -0x40000
[Link] = GRAVITY_AIR
[Link] = true
[Link] = 8000

if [Link] == 0x1000
[Link] >>= 1
[Link] >>= 1
end if
break

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

if [Link] == COLLISION_PLANE_A
TempValue4 = 3
else
TempValue4 = 1
end if

[Link] = Player_State_Hurt
[Link] = ANI_HURT
[Link] = -0x40000
[Link] = GRAVITY_AIR
[Link] = true
[Link] = 8000

if [Link] == 0x1000
[Link] >>= 1
[Link] >>= 1
end if
// Lose ring code
TempValue0 = [Link]
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], [Link],
[Link], [Link])
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], [Link],
[Link], [Link])
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
[Link] = 0
[Link] = 100
break

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

[Link] = 5
[Link] = 0
[Link] = -0x70000
[Link] = 0
[Link] = Player_State_Death
[Link] = ANI_DYING

[Link] = false
[Link] = false
if [Link] == 0 // Check if it's was player 1 who
died......what?
[Link] = false
end if
break
end switch
// lose your warp-run if you receive damage
if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
end function

function Player_State_Hurt
#platform: Use_Origins
[Link] = true
#endplatform
if [Link] == GRAVITY_AIR
[Link] = true
if [Link] == 0x3800
[Link] += 0x3000
else
[Link] += 0xF00
end if
[Link] = [Link]
else
[Link] = Player_State_Ground
[Link] = 120
[Link] = 3
[Link] = 0
[Link] = 0
CallFunction(Player_HandleOnGround)
end if
end function

function Player_State_OuttaHere
// preparing to jump
if [Link] < 140
[Link]++
else
// The Jump.
[Link] = 0
[Link] = 5

if [Link] == FACING_RIGHT
[Link] = 0x10000
[Link] = 0x10000
else
[Link] = -0x10000
[Link] = -0x10000
end if
[Link] = -0x58000
[Link] = Player_State_Death

[Link] = false
[Link] = false

[Link] = false
end if
end function

// YOU DIED.
function Player_State_Death
[Link] = CONTROLMODE_NONE
[Link] += 0x3800
// Don't override the bored animation
if [Link] != ANI_BORED
[Link] = ANI_DYING
end if

if [Link] > 0x100000


#platform: Use_Origins
EngineCallback(NOTIFY_DEATH_EVENT)
#endplatform

if [Link] > 0
if [Link] == ANI_BORED // Outta Here makes an
automatic game over, no lifes will save you
[Link] = 0
else

#platform: Use_Origins
// Check that we are actually in a mode where we use lives
if [Link] == false
if [Link] != BOOT_PLAYMODE_MISSION
CheckEqual([Link],
BOOT_PLAYMODE_BOSSRUSH)
TempValue0 = CheckResult
CheckEqual([Link], false)
TempValue0 |= CheckResult
if TempValue0 != 0
[Link]--
end if
end if
end if
#endplatform

#platform: Use_Standalone
// In Standalone, we don't have any extra things to worry
about
[Link]--
#endplatform
end if
end if

[Link] = false

#platform: Use_Origins
CheckEqual([Link], BOOT_PLAYMODE_BOSSRUSH)
TempValue0 = CheckResult
CheckNotEqual([Link], 0)
TempValue0 |= CheckResult
// Check if the player is replaying the stage from My Data & Rankings
CheckEqual([Link], 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
[Link] = TypeName[Death Event]
[Link] = 7
DeathEvent.Text1XPos = [Link]
DeathEvent.Text1XPos -= 232
DeathEvent.Text2XPos = [Link]
DeathEvent.Text2XPos += 232
end if

if [Link] == MODE_TIMEATTACK
[Link] = 0
[Link] = DEATHEVENT_TIMEATTACK
else
if [Link] == 0
[Link] = -2880
[Link] = DEATHEVENT_GAMEOVER
// *Technically it goes to the traditional game over in the
same state
PlayMusic(5)
[Link] = false

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

else
[Link] = 0
[Link] = DEATHEVENT_FADEOUT

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

if [Link] == false
if [Link] != BOOT_PLAYMODE_BOSSRUSH
if [Link] == 9
if [Link] == 59
// Check if the player is replaying
the stage from My Data & Rankings
if [Link] == false
[Link] = -2880
[Link] =
DEATHEVENT_TIMEOVER

PlayMusic(5)
[Link] = false
end if
end if
end if
end if
end if
#endplatform

#platform: Use_Standalone
if [Link] == 9
if [Link] == 59
[Link] = -2880
[Link] = DEATHEVENT_TIMEOVER

PlayMusic(5)
[Link] = 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
[Link] = CONTROLMODE_NONE
[Link] += [Link]
[Link] = ANI_DROWNING

if [Link] > 0x80000


#platform: Use_Origins
EngineCallback(NOTIFY_DEATH_EVENT)
// We only subtract lives sometimes in Origins
if [Link] == false
if [Link] != BOOT_PLAYMODE_MISSION
CheckEqual([Link], BOOT_PLAYMODE_BOSSRUSH)
TempValue0 = CheckResult
CheckEqual([Link], false)
TempValue0 |= CheckResult
if TempValue0 != false
if [Link] > 0
[Link]--
end if
end if
end if
end if
#endplatform

#platform: Use_Standalone
if [Link] > 0
[Link]--
end if
#endplatform

[Link] = false

[Link] = TypeName[DeathEvent]
[Link] = 7
DeathEvent.Text1XPos = [Link]
DeathEvent.Text1XPos -= 232
DeathEvent.Text2XPos = [Link]
DeathEvent.Text2XPos += 232

if [Link] == MODE_TIMEATTACK
[Link] = 0
[Link] = DEATHEVENT_TIMEATTACK
else
if [Link] == 0
[Link] = -2880
[Link] = DEATHEVENT_GAMEOVER

PlayMusic(5)
[Link] = false
else
[Link] = 0
[Link] = DEATHEVENT_FADEOUT
end if
end if
end if
end function

// Wacky Workbench hanging bar gimmick


function Player_State_HangBar
if [Link] == true
[Link] = FACING_LEFT
[Link] = -0x20000
[Link] = 30
else
if [Link] == true
[Link] = FACING_RIGHT
[Link] = 0x20000
[Link] = 30
else
[Link] = 0
[Link] = 0
end if
end if

TempValue1 = [Link]
TempValue1 >>= 16

TempValue2 = [Link]
TempValue2 >>= 16
TempValue2 += [Link]
// 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
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
[Link] = 0
[Link] = 0
end if

// Manual Drop
if [Link] == true

[Link] = Player_State_Air
[Link] = 0
[Link] = 0
[Link] = 0
[Link] += 0x40000
end if
[Link] = [Link]
// Cancel warp
if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if

[Link] = 0
end if
end function

// Unused leftover from Sonic Nexus (2008)


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

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0

if [Link] < 0
[Link] = FACING_LEFT
end if
end if
end if

if [Link] == true
if [Link] > 0x199A
[Link] = Player_State_CorkscrewRoll
[Link] = ANI_JUMPING
end if

if [Link] < -0x199A


[Link] = Player_State_CorkscrewRoll
[Link] = ANI_JUMPING
end if
end if

if [Link] > 0
if [Link] == 16
PlaySfx(SFX_G_DESTROY, false) // Would be Skidding SFX if using
Nexus SFX list
end if
[Link] = ANI_SKIDDING
[Link]--
end if

if [Link] == true
CallFunction(Player_Action_Jump)
else
CallFunction(Player_HandleOnGround)
end if
end function

// Unused leftover from Sonic Nexus (2008)


function Player_State_CorkscrewRoll
[Link] = 0
CallFunction(Player_HandleRollDeceleration)

if [Link] < 0x60000


if [Link] > -0x60000

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform
#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

end if
end if

if [Link] == true
CallFunction(Player_Action_Jump)
else
CallFunction(Player_HandleOnGround)
end if
end function

// Tube Switch function


function Player_State_TubeRoll
#platform: Use_Origins
[Link] = -1
#endplatform
if [Link] == GRAVITY_AIR // end the function if you are in the air

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
CallFunction(Player_HandleAirMovement)
else
if [Link] > 0
if [Link] < [Link]
[Link] = [Link]
end if

if [Link] > 0x100000


[Link] = 0x100000
end if
else
TempValue0 = [Link]
FlipSign(TempValue0)
if [Link] > TempValue0
[Link] = TempValue0
CallFunction(Player_HandleOnGround)
end if

if [Link] < -0x100000


[Link] = -0x100000
end if
end if

TempValue0 = [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if
if TempValue0 < 0x5F5C2
// Warp Star delete checks
if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
else
// Warp Star spawnning
if [Link] > WARPDEST_NONE
if [Link] == 0
[Link] = 1
CreateTempObject(TypeName[Warp Star], 0, [Link],
[Link])
[Link] = 7
[Link] = 4
end if
end if
end if

CallFunction(Player_HandleRollDeceleration)
CallFunction(Player_HandleRollAnimSpeed)
[Link] = [Link]
CallFunction(Player_HandleOnGround)
end if
end function

function Player_State_TubeAirRoll
#platform: Use_Origins
[Link] = -1
#endplatform
[Link] = false
[Link] = false
if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
CallFunction(Player_HandleAirMovement)
else
if [Link] > 0
[Link] = [Link]
else
TempValue0 = [Link]
FlipSign(TempValue0)
[Link] = TempValue0
end if

TempValue0 = [Link]
if TempValue0 < 0
FlipSign(TempValue0)
end if

if TempValue0 < 0x5F5C2


if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
else
if [Link] > WARPDEST_NONE
if [Link] == 0
[Link] = 1
CreateTempObject(TypeName[Warp Star], 0, [Link],
[Link])
[Link] = 7
[Link] = 4
end if
end if
end if
CallFunction(Player_HandleRollDeceleration)
CallFunction(Player_HandleRollAnimSpeed)
[Link] = [Link]
CallFunction(Player_HandleOnGround)
end if
end function

// Palmtree Panic and Wacky Workbench spinning tops


function Player_State_SpinningTop
[Link] += [Link]
if [Link] == GRAVITY_AIR // Drop from them if you get out of range

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = ANI_WALKING
[Link] = 0
CallFunction(Player_HandleAirMovement)
else
CallFunction(Player_HandleOnGround)
end if
end function

// Amy Rose's favorite function


function Player_State_Hugged
if [Link] == GRAVITY_AIR // No hugs if you're in the air

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform
#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

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

// Warp cancel check


if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if

// Get free from Amy


if [Link] == true
CallFunction(Player_Action_Jump)
end if
end if
end function

// Palmtree Panic Ramp


function Player_State_Ramp3D
CallFunction(Player_HandleGroundMovement)
if [Link] == GRAVITY_AIR

#platform: Use_Origins
[Link] = Player_State_Air_NoDropDash
#endplatform

#platform: Use_Standalone
[Link] = Player_State_Air
#endplatform

[Link] = 0
CallFunction(Player_HandleAirMovement)
// Set the equivalent animation for looking to the left
if [Link] == FACING_LEFT

if [Link] == ANI_RAMP_RUNNING3
[Link] = ANI_RAMP_RUNNING5
end if

if [Link] == ANI_RAMP_RUNNING2
[Link] = ANI_RAMP_RUNNING6
end if
end if
else
#platform: Use_Origins
if [Link] == ANI_GLIDING
[Link] = 0
[Link] = 0
[Link] = 0
[Link] = ANI_GLIDING_STOP
end if
#endplatform
CallFunction(Player_HandleOnGround)
if [Link] == 0
// Warp Star erase check
if [Link] > WARPDEST_NONE
if [Link] > 99
if [Link] < 204
[Link] = WARPDEST_NONE
end if
end if
[Link] = 0
end if
// Waiting timer while in the ramp
if [Link] < 240
[Link] = ANI_STOPPED
[Link]++
else
[Link] = ANI_WAITING
end if
else
// Set animation based on angle
if [Link] == 0
[Link] = ANI_RAMP_RUNNING1
end if

if [Link] > 200


if [Link] == FACING_RIGHT
[Link] = ANI_RAMP_RUNNING3
else
[Link] = ANI_RAMP_RUNNING5
end if
end if

if [Link] > 216


if [Link] == FACING_RIGHT
[Link] = ANI_RAMP_RUNNING2
else
[Link] = ANI_RAMP_RUNNING6
end if
end if

if [Link] > 232


[Link] = ANI_RAMP_RUNNING1
end if

if [Link] == 192
[Link] = ANI_RAMP_RUNNING4
end if
end if
if [Link] == true
CallFunction(Player_Action_Jump)
else
if [Link] == true
if [Link] == 0
[Link] = Player_State_LookUp
[Link] = ANI_LOOKINGUP
[Link] = 0
end if
end if
if [Link] == true
if [Link] == 0
[Link] = Player_State_Crouch
[Link] = ANI_LOOKINGDOWN
[Link] = 0
else
if [Link] > 0x199A
[Link] = 0
[Link] = Player_State_Roll
[Link] = ANI_JUMPING
end if

if [Link] < -0x199A


[Link] = 0
[Link] = Player_State_Roll
[Link] = ANI_JUMPING
end if
end if
end if
end if
end if

if [Link] != ANI_STOPPED
[Link] = [Link]
if [Link] < 0
FlipSign([Link])
end if
[Link] *= 60
[Link] /= 0x60000
[Link] += 20
else
[Link] = 0
end if
end function

function Player_State_WaterCurrent
[Link] = GRAVITY_AIR

if [Link] == true
[Link] -= 0x20000
end if

if [Link] == true
[Link] += 0x20000
end if

if [Link] == true
[Link] -= 0x20000
end if

if [Link] == true
[Link] += 0x20000
end if
end function

function Player_SetJumpOffset
#platform: Use_Origins
if Mini_PlayerFlag == true
[Link] = -1
else
if [Link] == PLAYER_SONIC
[Link] = -5
end if

if [Link] == PLAYER_TAILS
[Link] = -1
end if

if [Link] == PLAYER_KNUCKLES
[Link] = -5
end if

if [Link] == PLAYER_AMY
[Link] = -4
end if
end if
#endplatform
end function

function Player_State_SizeChange
[Link] = true
if [Link] == GRAVITY_AIR // Knockback after touching the laser
[Link] = true
[Link] += 0x3000
[Link] = [Link]
else
[Link] = Player_State_Ground

[Link] = 120
[Link] = 3

[Link] = 0
[Link] = 0

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

#platform: Use_Standalone
[Link] = -1
switch [Link]
case PLAYER_SONIC_A
LoadAnimation("[Link]")
break

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

#platform: Use_Origins
switch [Link]
case PLAYER_SONIC_A
LoadAnimation("[Link]")
break

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

case PLAYER_KNUCKLES_A
LoadAnimation("[Link]")
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("[Link]")
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 [Link]
case PLAYER_SONIC_A
LoadAnimation("[Link]")
[Link] = -5
break

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

#platform: Use_Origins
if [Link] == PLAYER_SONIC
LoadAnimation("[Link]")
end if

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

if [Link] == PLAYER_KNUCKLES
LoadAnimation("[Link]")
end if

if [Link] == PLAYER_AMY
LoadAnimation("[Link]")
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 [Link] >= 0
if [Link] == 0
if [Link] == true
if [Link] == PLAYER_SONIC
[Link] = 1
else
if [Link] == PLAYER_AMY
[Link] = 1
else
[Link] = -1
end if
end if
end if
else
if [Link] == false
if [Link] == PLAYER_TAILS
[Link] = -1
else
if [Link] >= 20
[Link] = -1
end if
end if
else
[Link]++
if [Link] == 20
PlaySfx(SFX_G_DROPDASH, false)
end if

if [Link] >= 20
if [Link] == ANI_JUMPING
[Link] = 0
[Link] = 0
[Link] = 1
end if
end if
end if
end if
end if
#endplatform
end function

function Player_Action_DblJumpKnux
#platform: Use_Origins
if [Link] >= [Link]
if [Link] == true
game.callbackParam0 = 1
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
[Link] = 0x40000
if [Link] < 0
[Link] = 0
end if
if [Link] == FACING_RIGHT
[Link] = Player_State_GlideRight
[Link] = 0x40000
[Link] = 0
else
[Link] = Player_State_GlideLeft
[Link] = -0x40000
[Link] = 256
end if
[Link] = ANI_GLIDING
[Link] = 2
[Link] = 2
end if
end if
#endplatform
end function

function Player_State_GlideLeft
#platform: Use_Origins
if [Link] == 0
if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
end if

if [Link] == GRAVITY_AIR
if [Link] == true
if [Link] == 256
if [Link] < 0x180000
[Link] += 0x400
end if
else
if [Link] < 0x40000
[Link] += 0x1000
end if
end if

if [Link] > 0x8000


[Link] -= 0x2000
else
[Link] += 0x2000
end if

if [Link] < 256


[Link] += 4
end if

if [Link] < 170


if [Link] > 86
[Link] = 0
else
if [Link] > 44
[Link] = 1
else
[Link] = 2
end if
end if
else
if [Link] < 212
[Link] = 1
else
[Link] = 2
end if
end if

TempValue7 = [Link]
if [Link] < 128
[Link] = FACING_RIGHT
TempValue0 = false
TempValue1 = false
else
[Link] = FACING_LEFT
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_RWALL, -12, -2,
[Link])
[Link] = [Link]
TempValue0 = CheckResult
TempValue2 = [Link]
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_RWALL, -12, 11,
[Link])
[Link] = [Link]
TempValue1 = CheckResult
TempValue3 = [Link]
end if

Cos([Link], [Link])
[Link] *= [Link]
[Link] >>= 9
if [Link] == true
[Link] = Player_State_GlideRight

if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
end if

[Link] = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
if TempValue2 == TempValue3
if [Link] > 0
[Link] = FACING_RIGHT
end if
[Link] = Player_State_Climb
[Link] = 0
[Link] = 0
[Link] = 0
[Link] = 0
PlaySfx(SFX_G_GRAB, false)
game.callbackParam0 = 2
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
else
[Link] >>= 2
[Link] = [Link]
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
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
else
if [Link] == CMODE_FLOOR
[Link] = 0
[Link] = Player_State_GlideSlide
[Link] = ANI_GLIDING_STOP
[Link] = [Link]
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
end if
end if

CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_State_GlideRight
#platform: Use_Origins
if [Link] == 0
if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
end if

if [Link] == GRAVITY_AIR
if [Link] == true
if [Link] == 0
if [Link] < 0x180000
[Link] += 0x400
end if
else
if [Link] < 0x40000
[Link] += 0x1000
end if
end if

if [Link] > 0x8000


[Link] -= 0x2000
else
[Link] += 0x2000
end if

if [Link] > 0
[Link] -= 4
end if
if [Link] < 170
if [Link] > 86
[Link] = 0
else
if [Link] > 44
[Link] = 1
else
[Link] = 2
end if
end if
else
if [Link] < 212
[Link] = 1
else
[Link] = 2
end if
end if

TempValue7 = [Link]
if [Link] < 128
[Link] = FACING_RIGHT
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_LWALL, 12, -2,
[Link])
[Link] = [Link]
TempValue0 = CheckResult
TempValue2 = [Link]
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_LWALL, 12, 11,
[Link])
[Link] = [Link]
TempValue1 = CheckResult
TempValue3 = [Link]
else
[Link] = FACING_LEFT
TempValue0 = false
TempValue1 = false
end if

Cos([Link], [Link])
[Link] *= [Link]
[Link] >>= 9
if [Link] == true
[Link] = Player_State_GlideLeft

if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
end if

[Link] = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
TempValue2 >>= 1
TempValue3 >>= 1
if TempValue2 == TempValue3
if [Link] < 0
[Link] = FACING_LEFT
end if
[Link] = Player_State_Climb
[Link] = 0
[Link] = 0
[Link] = 0
[Link] = 0
PlaySfx(SFX_G_GRAB, false)
game.callbackParam0 = 2
game.callbackParam1 = 0
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
else
[Link] >>= 2
[Link] = [Link]
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
[Link] = 0
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
else
if [Link] == CMODE_FLOOR
[Link] = 0
[Link] = Player_State_GlideSlide
[Link] = ANI_GLIDING_STOP
[Link] = [Link]
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
end if
end if

CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_State_GlideDrop
#platform: Use_Origins
if [Link] == GRAVITY_AIR
CallFunction(Player_HandleAirFriction)
CallFunction(Player_HandleAirMovement)
else
if [Link] == true
[Link] = 0
[Link] = 0
if [Link] == true
CallFunction([Link])
else
CallFunction(Player_Action_Jump)
end if
else
if [Link] == 0
PlaySfx(SFX_G_GLIDEDROPLAND, false)
end if

[Link] = false
[Link] = 0
[Link] = 0
[Link] = ANI_LOOKINGDOWN
[Link] = ANI_LOOKINGDOWN
[Link] = 2

if [Link] < 16
[Link]++
else
[Link] = 0
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
if [Link] > 0
if [Link] > 99
if [Link] < 204
[Link] = 0
end if
end if
[Link] = 0
end if
end if
end if
end if
#endplatform
end function

function Player_State_GlideSlide
#platform: Use_Origins
if [Link] == GRAVITY_GROUND
if [Link] == 0
if [Link] == true
if [Link] == true
CallFunction([Link])
else
CallFunction(Player_Action_Jump)
end if
else
[Link] = false
[Link] = 1
if [Link] < 16
[Link]++
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
end if
end if
else
[Link]++
TempValue0 = [Link]
TempValue0 %= 4
if TempValue0 == 0
CreateTempObject(TypeName[Dust Puff], 0, [Link],
[Link])
Object[TempObjectPos].iYPos += [Link]
Object[TempObjectPos].DrawOrder = [Link]
end if

[Link] %= 8
if [Link] == 0
PlaySfx(SFX_G_SLIDE, false)
end if

[Link] = 0
if [Link] > 0
[Link] -= 0x2000
if [Link] < 0
[Link] = 0
[Link] = 0
end if
else
[Link] += 0x2000
if [Link] > 0
[Link] = 0
[Link] = 0
end if
end if
if [Link] == 0
[Link] = 0
[Link] = 0
end if
end if

[Link] = [Link]
else
CallFunction(Player_Action_GlideDrop)
end if
#endplatform
end function

function Player_State_Climb
#platform: Use_Origins
if [Link] == GRAVITY_AIR
[Link] = ANI_CLIMBING
if [Link] == true
[Link] = -0x10000
TempValue0 = [Link]
TempValue0 *= -0x10000
if [Link] < TempValue0
[Link] = TempValue0
end if

[Link]++
if [Link] == 4
[Link] = 0
[Link]++
if Mini_PlayerFlag == true
[Link] %= 2
else
[Link] %= 6
end if
end if
else
if [Link] == true
[Link] = 0x10000
[Link]++
if [Link] == 4
[Link] = 0
if [Link] < 1
if Mini_PlayerFlag == true
[Link] += 2
else
[Link] += 6
end if
end if
[Link]--
end if
else
[Link] = 0
end if
end if

if [Link] == true
[Link] = ANI_JUMPING
[Link] = Player_State_Air_NoDropDash
[Link] = 0
if [Link] == FACING_LEFT
[Link] = 0x40000
[Link] = 0x40000
[Link] = FACING_RIGHT
else
[Link] = -0x40000
[Link] = -0x40000
[Link] = FACING_LEFT
end if

[Link] = -0x40000
if [Link] != 0x3800 // (see if Knuckles is
underwater)
[Link] >>= 1
[Link] >>= 1
[Link] >>= 1
end if
else
if Mini_PlayerFlag == true
TempValue4 = 7
TempValue5 = -6
else
TempValue4 = 10
TempValue5 = -10
end if

if [Link] == FACING_RIGHT
TempValue2 = [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileGrip(CSIDE_LWALL, TempValue4, TempValue5,
[Link])
TempValue0 = CheckResult
if TempValue0 == 0
[Link] = TempValue2
[Link] = [Link]
ObjectTileGrip(CSIDE_LWALL, TempValue4, 11,
[Link])
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, true,
ECEFFECT_NONE)
TempValue0 = CheckResult
end if
[Link] = [Link]
TempValue3 = [Link]
[Link] = TempValue2
[Link] = [Link]
[Link] = [Link]
ObjectTileGrip(CSIDE_LWALL, TempValue4, 11,
[Link])
[Link] = [Link]
TempValue1 = CheckResult
if TempValue1 == 0
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, false,
ECEFFECT_NONE)
TempValue1 = CheckResult
end if
if [Link] > TempValue3
[Link] = TempValue3
end if
ObjectTileGrip(CSIDE_ENTITY, FACING_RIGHT, false,
ECEFFECT_RESETSTORAGE)
else
if Mini_PlayerFlag == true
TempValue4 = -7
else
TempValue4 = -10
end if

TempValue2 = [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileGrip(CSIDE_RWALL, TempValue4, TempValue5,
[Link])
TempValue0 = CheckResult
if TempValue0 == 0
[Link] = TempValue2
[Link] = [Link]
ObjectTileGrip(CSIDE_RWALL, TempValue4, 11,
[Link])
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, true,
ECEFFECT_NONE)
TempValue0 = CheckResult
end if
[Link] = [Link]
TempValue3 = [Link]
[Link] = TempValue2
[Link] = [Link]
[Link] = [Link]
ObjectTileGrip(CSIDE_RWALL, TempValue4, 11,
[Link])
[Link] = [Link]
TempValue1 = CheckResult
if TempValue1 == 0
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, false,
ECEFFECT_NONE)
TempValue1 = CheckResult
end if
if [Link] < TempValue3
[Link] = TempValue3
end if
ObjectTileGrip(CSIDE_ENTITY, FACING_LEFT, false,
ECEFFECT_RESETSTORAGE)
end if
if TempValue0 == 0
if [Link] < 0
[Link] = TempValue2
[Link] = ANI_LEDGEPULLUP
[Link] = 0
[Link] = 0
[Link] = Player_State_LedgePullUp
[Link] = false
if [Link] == FACING_RIGHT
[Link] += 0x10000
end if
end if
else
if TempValue1 == 0
[Link] = ANI_GLIDING_DROP
[Link] = 2
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
[Link] = ANI_WALKING
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
end if
#endplatform
end function

function Player_State_LedgePullUp
#platform: Use_Origins
switch [Link]
case 0
if [Link] < 5
ObjectTileGrip(CSIDE_FLOOR, 12, -9, [Link])
[Link]++
else
[Link] = 0
[Link]++
if [Link] == FACING_RIGHT
[Link] += 0x90000
else
[Link] -= 0x90000
end if
[Link] -= 0xA0000
end if
break

case 1
if [Link] < 5
[Link]++
else
[Link] = 0
[Link]++
if [Link] == FACING_RIGHT
[Link] += 0x50000
else
[Link] -= 0x50000
end if
end if
break

case 2
if [Link] < 5
[Link]++
else
[Link] = 0
[Link] = ANI_STOPPED
[Link] = Player_State_Air_NoDropDash
[Link] -= 0x80000
[Link] = true
end if
break

end switch
#endplatform
end function
function Player_State_GlideLeftNoGrip
#platform: Use_Origins
if [Link] == GRAVITY_AIR
if [Link] == true
if [Link] == 256
if [Link] < 0x180000
[Link] += 0x400
end if
else
if [Link] < 0x40000
[Link] += 0x1000
end if
end if

if [Link] > 0x8000


[Link] -= 0x2000
else
[Link] += 0x2000
end if

if [Link] < 256


[Link] += 4
end if

if [Link] < 170


if [Link] > 86
[Link] = 0
else
if [Link] > 44
[Link] = 1
else
[Link] = 2
end if
end if
else
if [Link] < 212
[Link] = 1
else
[Link] = 2
end if
end if

TempValue7 = [Link]
if [Link] < 128
[Link] = FACING_RIGHT
TempValue0 = false
TempValue1 = false
else
[Link] = FACING_LEFT
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_RWALL, -12, -2,
[Link])
[Link] = [Link]
TempValue0 = CheckResult
TempValue2 = [Link]
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_RWALL, -12, 11,
[Link])
[Link] = [Link]
TempValue1 = CheckResult
TempValue3 = [Link]
end if

Cos([Link], [Link])
[Link] *= [Link]
[Link] >>= 9
if [Link] == true
[Link] = Player_State_GlideRightNoGrip
end if

[Link] = 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
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
end if
end if
else
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
else
if [Link] == CMODE_FLOOR
[Link] = 0
[Link] = Player_State_GlideSlide
[Link] = ANI_GLIDING_STOP
[Link] = [Link]
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 0
end if
end if

CallFunction(Player_CheckRoofGlide)
#endplatform
end function

function Player_State_GlideRightNoGrip
#platform: Use_Origins
if [Link] == GRAVITY_AIR
if [Link] == true
if [Link] == 0
if [Link] < 0x180000
[Link] += 0x400
end if
else
if [Link] < 0x40000
[Link] += 0x1000
end if
end if

if [Link] > 0x8000


[Link] -= 0x2000
else
[Link] += 0x2000
end if

if [Link] > 0
[Link] -= 4
end if

if [Link] < 170


if [Link] > 86
[Link] = 0
else
if [Link] > 44
[Link] = 1
else
[Link] = 2
end if
end if
else
if [Link] < 212
[Link] = 1
else
[Link] = 2
end if
end if

TempValue7 = [Link]
if [Link] < 128
[Link] = FACING_RIGHT
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_LWALL, 12, -2,
[Link])
[Link] = [Link]
TempValue0 = CheckResult
TempValue2 = [Link]
[Link] = TempValue7
[Link] += [Link]
[Link] = [Link]
[Link] = [Link]
ObjectTileCollision(CSIDE_LWALL, 12, 11,
[Link])
[Link] = [Link]
TempValue1 = CheckResult
TempValue3 = [Link]
else
[Link] = FACING_LEFT
TempValue0 = false
TempValue1 = false
end if

Cos([Link], [Link])
[Link] *= [Link]
[Link] >>= 9
if [Link] == true
[Link] = Player_State_GlideLeftNoGrip
end if

[Link] = TempValue7
CheckResult = TempValue0
CheckResult &= TempValue1
if CheckResult == true
TempValue2 >>= 1
TempValue3 >>= 1
if TempValue2 == TempValue3
else
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
end if
else
[Link] >>= 2
[Link] = [Link]
CallFunction(Player_Action_GlideDrop)
end if
else
if [Link] == CMODE_FLOOR
[Link] = 0
[Link] = Player_State_GlideSlide
[Link] = ANI_GLIDING_STOP
[Link] = [Link]
else
[Link] = Player_State_Ground
CallFunction(Player_HandleOnGround)
[Link] = 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 [Link] == REGULAR_STAGE
CheckEqual([Link], 68) // MMZ3C
TempValue0 = CheckResult
CheckEqual([Link], 69) // MMZ3D
TempValue0 |= CheckResult
if TempValue0 != false
if [Link] == PLAYER_KNUCKLES // a bit redundant,
this func is only called in glide functions anyways..
if [Link] == true
TempValue0 = [Link]
TempValue0 >>= 16
if TempValue0 < [Link]
[Link] = [Link]
[Link] <<= 16
end if
end if
end if
end if
end if
#endplatform
end function

function Player_Action_GlideDrop
#platform: Use_Origins
// Bug Details:
// [Link] 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

[Link] = ANI_GLIDING_DROP
[Link] = 0
[Link] = Player_State_GlideDrop
#endplatform
end function

function Player_Action_DblJumpAmy
#platform: Use_Origins
if [Link] == true
PlaySfx(SFX_G_HAMMERJUMP, false)
game.callbackParam0 = 0
game.callbackParam1 = 1
game.callbackParam2 = 0
EngineCallback(NOTIFY_STATS_CHARA_ACTION2)
TempValue0 = [Link]
TempValue1 = [Link]
[Link] = ANI_HAMMER_JUMP
ProcessAnimation()
[Link] = TempValue0
[Link] = TempValue1
end if
#endplatform
end function

function Player_Action_HammerDash
#platform: Use_Origins
PlaySfx(SFX_G_HAMMERDASH, false)
[Link] = Player_State_HammerDash
[Link] = ANI_HAMMER_DASH
[Link] = 0
[Link] = -1
CallFunction(Player_SetHammerDashSpeed)
#endplatform
end function

function Player_State_HammerDash
#platform: Use_Origins
if [Link] == true
[Link] = FACING_RIGHT
else
if [Link] == true
[Link] = FACING_LEFT
end if
end if

TempValue0 = true

if [Link] != 0
[Link]++
if [Link] == true
if [Link] < 60
CallFunction(Player_SetHammerDashSpeed)
if [Link] == 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, [Link])
if TempValue1 <= 0
TempValue0 = true
end if

if TempValue0 == true
[Link] = Player_State_Ground
end if
#endplatform
end function
function Player_SetHammerDashSpeed
#platform: Use_Origins
if [Link] == FACING_RIGHT
[Link] = 0x60000
else
// Could they not have just set it to -0x60000?
[Link] = 0
[Link] -= 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)

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

if Mini_PlayerFlag == false
if [Link] == PLAYER_SONIC
LoadAnimation("[Link]")
end if

if [Link] == PLAYER_TAILS
LoadAnimation("[Link]")
end if

if [Link] == PLAYER_KNUCKLES
LoadAnimation("[Link]")
end if

if [Link] == PLAYER_AMY
LoadAnimation("[Link]")
end if
else
if [Link] == PLAYER_SONIC
LoadAnimation("[Link]")
end if

if [Link] == PLAYER_TAILS
LoadAnimation("[Link]")
Object[1].Type = TypeName[Blank Object]
end if

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

if [Link] == PLAYER_AMY
LoadAnimation("[Link]")
Object[1].Type = TypeName[Blank Object]
end if
end if

BindPlayerToObject(0, 0)

[Link] = Player_State_Air_NoDropDash
[Link] = PRIORITY_ACTIVE
[Link] = 4

[Link] = 0x60000
[Link] = 0xC00
[Link] = 0xC00
[Link] = 0x1800
[Link] = 0x600
[Link] = 0x3800
[Link] = 0x68000
[Link] = -0x40000
[Link] = 0x2000

if [Link] == PLAYER_SONIC
[Link] = Player_State_Static
if [Link] == false
[Link] = Player_Action_Peelout_S2
[Link] = Player_Action_Spindash_S2
else
[Link] = Player_Action_Peelout_CD
[Link] = Player_Action_Spindash_CD
end if
end if

if [Link] == PLAYER_TAILS
[Link] = Player_Action_DblJumpTails
[Link] = Player_Action_Jump
if [Link] == false
[Link] = Player_Action_Spindash_S2
else
[Link] = Player_Action_Spindash_CD
end if
end if

if [Link] == PLAYER_KNUCKLES
[Link] = 0x60000
[Link] = Player_Action_DblJumpKnux
[Link] = Player_Action_Jump
if [Link] == false
[Link] = Player_Action_Spindash_S2
else
[Link] = Player_Action_Spindash_CD
end if
end if

if [Link] == PLAYER_AMY
[Link] = Player_Action_DblJumpAmy
[Link] = Player_Action_Jump
if [Link] == false
[Link] = Player_Action_Spindash_S2
else
[Link] = 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 = [Link]
#endplatform

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

if [Link] != PLAYER_SONIC_A // PLAYER_SONIC in


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

[Link] = 0
[Link] = Player_State_Static
[Link] = 0
[Link] = 0

[Link] = false
[Link] = true
[Link] = 4

[Link] = 0
[Link] = 0

[Link] = true
[Link] = [Link]
else
// Handle Player
CallFunction(Player_ProcessUpdate)
CallFunction([Link])
ProcessAnimation()

if [Link] == ANI_JUMPING
[Link] = [Link]
else
if [Link] == [Link]
[Link] = 0
[Link] += [Link]
end if
end if

if [Link] > 0x100000


[Link] = 0x100000
end if

PlayerTileCollision()

if CheckResult == true
if [Link] == ANI_JUMPING
if [Link] == false
[Link] = ANI_WALKING
[Link] = 0
[Link] += [Link]
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([Link])

#platform: Use_Origins
if [Link] >= 20
if [Link] == ANI_JUMPING
[Link] = 0
[Link] = 0
[Link] = 1
end if
end if
#endplatform

ProcessAnimation()

if [Link] == ANI_JUMPING
[Link] = [Link]
else
if [Link] == [Link]
[Link] = 0
[Link] += [Link]
end if
end if

if [Link] > 0x100000


[Link] = 0x100000
end if

PlayerTileCollision()
if CheckResult == true
if [Link] == ANI_JUMPING
if [Link] == false
[Link] = ANI_WALKING
[Link] = 0
[Link] += [Link]
end if
end if
end if
end if
end sub

sub ObjectDraw
if [Link] != [Link]
[Link] = [Link]
[Link] = 0
[Link] = 0
[Link] = 0
end if

DrawPlayerAnimation()
end sub

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

if [Link] == false
if [Link] == 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 == [Link]
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 [Link]
case PLAYER_SONIC_A
ResetObjectEntity(0, TypeName[Player Object], 0,
Object[ArrayPos0].XPos, Object[ArrayPos0].YPos)
[Link] = Object[ArrayPos0].XPos
[Link] = Object[ArrayPos0].YPos

LoadAnimation("[Link]")
BindPlayerToObject(0, 0)

[Link] = Player_State_Air

[Link] = PRIORITY_ACTIVE

[Link] = 4

[Link] = 0x60000
[Link] = 0xC00
[Link] = 0xC00
[Link] = 0x1800
[Link] = 0x600
[Link] = 0x3800
[Link] = 0x68000
[Link] = -0x40000
[Link] = 0x2000

[Link] = -5

[Link] = Player_State_Static
if [Link] == false
[Link] = Player_Action_Peelout_S2
[Link] = Player_Action_Spindash_S2
else
[Link] = Player_Action_Peelout_CD
[Link] = Player_Action_Spindash_CD
end if
break

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

LoadAnimation("[Link]")
BindPlayerToObject(0, 0)

[Link] = Player_State_Air
[Link] = PRIORITY_ACTIVE
[Link] = 4

[Link] = 0x60000
[Link] = 0xC00
[Link] = 0xC00
[Link] = 0x1800
[Link] = 0x600
[Link] = 0x3800
[Link] = 0x68000
[Link] = -0x40000
[Link] = 0x2000

[Link] = -1

[Link] =
Player_Action_DblJumpTails
[Link] = Player_Action_Jump
if [Link] == false
[Link] = Player_Action_Spindash_S2
else
[Link] = 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 [Link] == true
switch [Link]
case EDIT_VAR_PROPVAL // Property Value
CheckResult = [Link]
break
case 0 // Character ID
CheckResult = [Link]
break
end switch
else
switch [Link]
case EDIT_VAR_PROPVAL // Property Value
[Link] = [Link]
break
case 0 // Character ID
[Link] = [Link]
break
end switch
end if
end sub

sub RSDKDraw
switch [Link]
default
LoadSpriteSheet("Players/[Link]")
DrawSprite(0)
break

case 1
LoadSpriteSheet("Players/[Link]")
DrawSprite(1)
break
case 2
LoadSpriteSheet("Players/[Link]")
DrawSprite(2)
break

case 5
LoadSpriteSheet("Players/[Link]")
DrawSprite(3)
break
end switch
end sub

sub RSDKLoad
LoadSpriteSheet("Players/[Link]")
SpriteFrame(-16, -19, 28, 39, 1, 1) // Sonic Standing Frame

LoadSpriteSheet("Players/[Link]")
SpriteFrame(-12, -12, 24, 32, 1, 1) // Tails Standing Frame

LoadSpriteSheet("Players/[Link]")
SpriteFrame(-14, -20, 26, 40, 1, 1) // Knuckles Standing Frame

LoadSpriteSheet("Players/[Link]")
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