// ----------------------------------
// RSDK Project: Sonic 2
// Script Description: Tails Object Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// ----------------------------------

// ========================
// Aliases
// ========================

private alias object.type			 : player.type
private alias object.entityPos		 : player.entityPos
private alias object.state			 : player.state
private alias object.visible		 : player.visible
private alias object.priority		 : player.priority
private alias object.xpos			 : player.xpos
private alias object.ypos			 : player.ypos
private alias object.iypos			 : player.iypos
private alias object.xvel			 : player.xvel
private alias object.yvel			 : player.yvel
private alias object.rotation		 : player.rotation
private alias object.direction		 : player.direction
private alias object.gravity		 : player.gravity
private alias object.frame			 : player.frame
private alias object.animation		 : player.animation
private alias object.prevAnimation	 : player.prevAnimation
private alias object.animationSpeed	 : player.animationSpeed
private alias object.animationTimer	 : player.animationTimer
private alias object.drawOrder		 : player.drawOrder
private alias object.interaction	 : player.interaction

private alias object.down	 	: player.down

private alias object.value2  : player.abilityTimer			// Note: Also used by death/drowning state
private alias object.value3  : player.drownTimer			// Countdown before player moves to next drown "level"
private alias object.value4  : player.drownLevel
private alias object.value8  : player.blinkTimer
private alias object.value12 : player.tailFrame
private alias object.value13 : player.tailAnim
private alias object.value17 : debugMode.currentSelection
private alias object.value19 : player.badnikBonus
private alias object.value30 : player.jumpOffset
private alias object.value34 : player.collisionDisabled
private alias object.value35 : player.jumpAbilityState
private alias object.value42 : player.prevGravity


// ========================
// Function Declarations
// ========================

reserve function TailsObject_ProcessTailSprite


// ========================
// Function Definitions
// ========================

public function TailsObject_ProcessTailSprite
	switch player.tailAnim
	case 0 // ANI_STOPPED
		if player.frame == 0
			player.tailFrame++
			player.tailFrame %= 40
		end if
		break

	case 1 // ANI_WAITING
	case 3 // ANI_LOOKINGUP
	case 4 // ANI_LOOKINGDOWN
	case 21 // ANI_HANGING
	case 36 // ANI_CONTINUE
	case 37 // ANI_CONTINUE_UP
		player.tailFrame++
		player.tailFrame %= 40
		break

	case 7 // ANI_SKIDDING
	case 9 // ANI_SPINDASH
	case 10 // ANI_JUMPING
	case 43 // Unknown, this was probably "SSRoll" in Sonic 1 before it got moved to its own ani file in that game
		player.tailFrame++
		player.tailFrame %= 12
		break

	case 17 // ANI_PUSHING
		player.tailFrame++
		player.tailFrame %= 30
		break
		
	end switch
end function


// ========================
// Events
// ========================

event ObjectUpdate
	if stage.debugMode == true
		CallFunction(Player_ProcessUpdate)

		CheckEqual(options.attractMode, false)
		temp0 = checkResult
		CheckEqual(keyPress[0].buttonB, true)
		temp0 &= checkResult
		
		if temp0 == true
			player.type = TypeName[Debug Mode]
			player.yvel = 0
			player.state = Player_State_Static
			player.frame = 0
			player.rotation = 0
			player.interaction = false
			player.drawOrder = 4
			player.priority = PRIORITY_ACTIVE
			player.blinkTimer = 0
			player.visible = true
			player.abilityTimer = 0
			player.drownTimer = 0
			player.drownLevel = 0
			player.frame = debugMode.currentSelection
			camera[0].enabled = true
			camera[0].style = CAMERASTYLE_FOLLOW

			StopSfx(SfxName[Flying])
			StopSfx(SfxName[Jump])

			if stage.state == STAGE_FROZEN
				stage.state = STAGE_RUNNING
			end if

			if player[1].type == TypeName[Player 2 Object]
				player[1].priority = PRIORITY_ACTIVE
			end if

			if object[+playerCount].propertyValue == 3
				object[+playerCount].type = TypeName[Invincibility]
				object[+playerCount].propertyValue = 0
			end if
		else
			if player.gravity == GRAVITY_GROUND
				player.jumpAbilityState = 0
			end if

			CallFunction(player.state)
			ProcessAnimation()
			CallFunction(TailsObject_ProcessTailSprite)

			if player.animation == ANI_JUMPING
				camera[0].adjustY = player.jumpOffset
			else
				if camera[0].adjustY == player.jumpOffset
					camera[0].adjustY = 0
					player.iypos += player.jumpOffset
				end if
			end if

			if player.collisionDisabled == false
				temp0 = player.prevGravity
				player.prevGravity = player.gravity
				ProcessObjectMovement()
				player.prevGravity ^= GRAVITY_AIR
				CheckEqual(player.gravity, GRAVITY_GROUND)
				player.prevGravity |= checkResult
				player.prevGravity ^= GRAVITY_AIR
				
				if temp0 == GRAVITY_AIR
					if player.prevGravity == GRAVITY_GROUND
						player.badnikBonus = 0
						if player.animation == ANI_JUMPING
							if player.down == false
								if player.state != Player_State_Roll
									if player.state != Player_State_TubeRoll
										player.animation = ANI_WALKING
										if player.entityPos == camera[0].target
											camera[0].adjustY = 0
										end if

										player.iypos += player.jumpOffset
									end if
								end if
							end if
						end if
					end if
				end if
			else
				player.collisionDisabled = false
			end if
		end if
	else
		CallFunction(Player_ProcessUpdate)

		if player.gravity == GRAVITY_GROUND
			player.jumpAbilityState = 0
		end if

		CallFunction(player.state)
		ProcessAnimation()
		CallFunction(TailsObject_ProcessTailSprite)

		if player.animation == ANI_JUMPING
			camera[0].adjustY = player.jumpOffset
		else
			if camera[0].adjustY == player.jumpOffset
				camera[0].adjustY = 0
				player.iypos += player.jumpOffset
			end if
		end if

		if player.collisionDisabled == false
			temp0 = player.prevGravity
			player.prevGravity = player.gravity
			ProcessObjectMovement()
			player.prevGravity ^= GRAVITY_AIR
			CheckEqual(player.gravity, GRAVITY_GROUND)
			player.prevGravity |= checkResult
			player.prevGravity ^= GRAVITY_AIR

			if temp0 == GRAVITY_AIR
				if player.prevGravity == GRAVITY_GROUND
					player.badnikBonus = 0
					if player.animation == ANI_JUMPING
						if player.down == false
							if player.state != Player_State_Roll
								if player.state != Player_State_TubeRoll
									player.animation = ANI_WALKING
									if player.entityPos == camera[0].target
										camera[0].adjustY = 0
									end if

									player.iypos += player.jumpOffset
								end if
							end if
						end if
					end if
				end if
			end if
		else
			player.collisionDisabled = false
		end if
	end if

	CallFunction(Player_HandleSuperForm)
end event


event ObjectDraw
	if player.animation != player.prevAnimation
		player.prevAnimation = player.animation
		player.frame = 0
		player.animationTimer = 0
		player.animationSpeed = 0
	end if

	if player.tailAnim != player.animation
		if player.animation > 4 // Animation 4 is ANI_LOOKINGDOWN, it's notable they used a direct constant rather than the normal ANI_* variables
			player.tailFrame = 0
		end if

		if player.tailAnim > 4
			player.tailFrame = 0
		end if

		player.tailAnim = player.animation
	end if
	
	// Draw the Tails part of Tails
	switch player.tailAnim
	case 0 // ANI_STOPPED
		if player.frame == 0
			temp0 = player.tailFrame
			temp0 >>= 3
			if player.visible == true
				DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)
			end if
		end if
		break

	case 1 // ANI_WAITING
	case 3 // ANI_LOOKINGUP
	case 4 // ANI_LOOKINGDOWN
	case 21 // ANI_HANGING
	case 36 // ANI_CONTINUE
	case 37 // ANI_CONTINUE_UP
		temp0 = player.tailFrame
		temp0 >>= 3
		if player.visible == true
			DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)
		end if
		break

	case 7 // ANI_SKIDDING
	case 9 // ANI_SPINDASH
		temp0 = player.tailFrame
		temp0 >>= 2
		temp0 += 11
		if player.visible == true
			DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)
		end if
		break

	case 10 // ANI_JUMPING
	case 43 // Unknown, this was probably "SSRoll" in Sonic 1 before it got moved to its own ani file in that game
		temp0 = player.tailFrame
		temp0 >>= 2
		CheckEqual(player.xvel, 0)
		temp1 = checkResult
		CheckEqual(player.yvel, 0)
		temp1 &= checkResult
		temp2 = player.rotation
		if temp1 == false
			ATan2(player.rotation, player.xvel, player.yvel)
			player.rotation += 0x10
			player.rotation &= 0xFF
			player.rotation >>= 5
			switch player.rotation
			case 0
			case 8
				temp0 += 5
				player.rotation = 0x00
				break

			case 1
				temp0 += 8
				if player.direction == FACING_RIGHT
					player.rotation = 0x40
				else
					player.rotation = 0x00
				end if
				break

			case 2
				temp0 += 5
				player.rotation = 0x40
				break

			case 3
				temp0 += 8
				if player.direction == FACING_RIGHT
					player.rotation = 0x80
				else
					player.rotation = 0x40
				end if
				break

			case 4
				temp0 += 5
				player.rotation = 0x80
				break

			case 5
				temp0 += 8
				if player.direction == FACING_RIGHT
					player.rotation = 0xC0
				else
					player.rotation = 0x80
				end if
				break

			case 6
				temp0 += 5
				player.rotation = 0xC0
				break

			case 7
				temp0 += 8
				if player.direction == FACING_RIGHT
					player.rotation = 0x00
				else
					player.rotation = 0xC0
				end if
				break
			end switch

			if player.direction == FACING_LEFT
				player.rotation += 0x80
			end if
		else
			temp0 += 5
			player.rotation = 0x00
		end if

		player.rotation <<= 1
		if player.visible == true
			DrawSpriteFX(temp0, FX_ROTATE, player.xpos, player.ypos)
		end if
		player.rotation = temp2
		break

	case 17 // ANI_PUSHING
		temp0 = player.tailFrame
		temp0 /= 10
		temp0 += 11
		if player.visible == true
			DrawSpriteFX(temp0, FX_FLIP, player.xpos, player.ypos)
		end if
		break
		
	end switch
	
	// Draw Tails himself (Separate tails are drawn in the process above)
	DrawObjectAnimation()
end event


event ObjectStartup
	if stage.playerListPos == PLAYER_TAILS_ALONE
		// Tails's main body uses the ani, the gif and SpriteFrames are for this Tails
		LoadSpriteSheet("Players/Tails1.gif")
		LoadAnimation("Tails.ani")
		
		SpriteFrame(-22, -8, 16, 24, 82, 199)
		SpriteFrame(-26, -8, 20, 24, 99, 199)
		SpriteFrame(-26, -8, 20, 24, 120, 199)
		SpriteFrame(-26, -8, 20, 24, 141, 199)
		SpriteFrame(-26, -8, 20, 24, 162, 199)
		SpriteFrame(-35, -8, 24, 16, 231, 166)
		SpriteFrame(-35, -8, 24, 16, 231, 183)
		SpriteFrame(-35, -8, 24, 16, 231, 200)
		SpriteFrame(-25, 9, 20, 16, 235, 217)
		SpriteFrame(-25, 9, 18, 16, 237, 234)
		SpriteFrame(-25, 9, 20, 16, 216, 234)
		SpriteFrame(-30, -6, 24, 16, 231, 166)
		SpriteFrame(-30, -6, 24, 16, 231, 183)
		SpriteFrame(-30, -6, 24, 16, 231, 200)
	end if
end event


// ========================
// Editor Events
// ========================

event RSDKDraw
	DrawSprite(0)
end event


event RSDKLoad
	LoadSpriteSheet("Players/Tails1.gif")
	SpriteFrame(-16, -12, 24, 32, 1, 1)
	
	SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
end event
