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

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

private alias object.value0 : object.timer
private alias object.value1 : object.bgClr.r
private alias object.value2 : object.bgClr.g
private alias object.value3 : object.bgClr.b
private alias object.value4 : object.bgClr.a

// Player Aliases
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos
private alias object.xvel : player.xvel
private alias object.yvel : player.yvel
private alias object.collisionLeft : player.collisionLeft
private alias object.collisionTop : player.collisionTop
private alias object.collisionRight : player.collisionRight
private alias object.collisionBottom : player.collisionBottom

private alias object.value11 : player.collisionFlags

// Game Modes
public alias 1 : MODE_SAVEGAME
public alias 2 : MODE_TIMEATTACK

// Tracks
private alias 0 : TRACK_STAGE
private alias 1 : TRACK_ACTFINISH

// Reserved object slots
private alias 0  : SLOT_PLAYER1
private alias 9  : SLOT_HUD


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

reserve function SpecialSetup_CopyAniTiles
reserve function SpecialSetup_ProcessHScroll
reserve function SpecialSetup_GetBlockPos
reserve function SpecialSetup_PlayerBlockCol


// ========================
// Static Values
// ========================

public value SpecialSetup_gemBlockTimer = 0
public value SpecialSetup_gemBlockBusy 	= 0
public value SpecialSetup_blockTimer 	= 0


// ========================
// Tables
// ========================

private table SpecialSetup_replay_attract_STK
	0x00F00000, 0x00340000
	0x00, 68
	0x30, 1
	0x20, 2
	0x24, 25
	0x04, 12
	0x00, 8
	0x08, 28
	0x00, 53
	0x30, 1
	0x20, 30
	0x28, 8
	0x08, 2
	0x00, 3
	0x04, 35
	0x00, 85
	0x04, 21
	0x00, 66
	0x04, 19
	0x00, 68
	0x38, 1
	0x28, 24
	0x08, 20
	0x38, 1
	0x28, 12
	0x08, 124
	0x00, 73
	0x08, 12
	0x38, 1
	0x28, 7
	0x08, 6
	0x00, 7
	0x04, 31
	0x00, 31
	0x30, 1
	0x20, 5
	0x00, 30
	0x08, 24
	0x00, 21
	0x38, 1
	0x28, 8
	0x08, 6
	0x00, 17
	0x08, 43
	0x38, 1
	0x28, 12
	0x08, 27
end table


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

public function SpecialSetup_CopyAniTiles
	temp0 = 0
	while temp0 < 16
		Copy16x16Tile(temp1, temp2)
		temp1++
		temp2++
		temp0++
	loop
end function


public function SpecialSetup_ProcessHScroll
	temp0 = oscillation
	temp0 <<= 1
	Sin(hParallax[8].scrollPos, temp0)
	hParallax[8].scrollPos <<= 10

	temp0 = oscillation
	temp0 <<= 2
	Sin(hParallax[9].scrollPos, temp0)
	hParallax[9].scrollPos <<= 9

	temp0 = oscillation
	temp0 <<= 1
	temp0 += 256
	Sin(hParallax[10].scrollPos, temp0)
	hParallax[10].scrollPos <<= 11

	temp0 = oscillation
	temp0 <<= 2
	temp0 += 128
	Sin(hParallax[11].scrollPos, temp0)
	hParallax[11].scrollPos <<= 9
end function


public function SpecialSetup_GetBlockPos
	// This code is kinda hard to read, so here's what it'd look like in a more C-like syntax
	// sx = (object.xpos - player[0].xpos) >> 8
	// sy = (object.ypos - player[0].ypos) >> 8
	// x = ((Sin(Player_stageRotation) * sx + Cos(Player_stageRotation) * sy) >> 1) + player[0].xpos
	// y = ((Cos(Player_stageRotation) * sy - Sin(Player_stageRotation) * sx) >> 1) + player[0].ypos

	temp2 = object.xpos
	temp2 -= player[0].xpos
	temp2 >>= 8
	temp3 = object.ypos
	temp3 -= player[0].ypos
	temp3 >>= 8

	Sin(temp4, Player_stageRotation)
	temp4 *= temp3
	Cos(temp5, Player_stageRotation)
	temp5 *= temp2
	temp0 = temp4
	temp0 += temp5
	temp0 >>= 1
	temp0 += player[0].xpos

	Cos(temp4, Player_stageRotation)
	temp4 *= temp3
	Sin(temp5, Player_stageRotation)
	temp5 *= temp2
	temp1 = temp4
	temp1 -= temp5
	temp1 >>= 1
	temp1 += player[0].ypos
	
	object.rotation = 512
	object.rotation -= Player_stageRotation
end function


public function SpecialSetup_PlayerBlockCol
	BoxCollisionTest(C_SOLID2, object.entityPos, -12, -12, 12, 12, 0, C_BOX, C_BOX, C_BOX, C_BOX)
	if checkResult != COL_NONE
		SetBit(player[0].collisionFlags, checkResult, true)
	else
		BoxCollisionTest(C_TOUCH, object.entityPos, -10, -10, 10, 10, 0, C_BOX, C_BOX, C_BOX, C_BOX)
		if checkResult == true
			temp0 = player[0].xvel
			temp1 = player[0].yvel
			Abs(temp0)
			Abs(temp1)

			if temp0 > temp1
				if player[0].xvel > 0
					SetBit(player[0].collisionFlags, 2, true)
					player[0].xpos = player[0].collisionLeft
					player[0].xpos -= 12
					player[0].xpos <<= 16
				else
					SetBit(player[0].collisionFlags, 3, true)
					player[0].xpos = player[0].collisionRight
					player[0].xpos += 12
					player[0].xpos <<= 16
				end if

				player[0].xpos += object.xpos
			else
				if player[0].yvel > 0
					SetBit(player[0].collisionFlags, 1, true)
					player[0].ypos = player[0].collisionTop
					player[0].ypos -= 12
					player[0].ypos <<= 16
				else
					SetBit(player[0].collisionFlags, 4, true)
					player[0].ypos = player[0].collisionBottom
					player[0].ypos += 12
					player[0].ypos <<= 16
				end if

				player[0].ypos += object.ypos
			end if
		end if
	end if
end function


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

event ObjectUpdate
	if Player_rotateDir == 0
		switch Player_rotateSpeed
		case 0
			temp0 = oscillation
			temp0 &= 1
			Player_stageRotation -= temp0
			if Player_stageRotation < 0
				Player_stageRotation += 512
			end if
			break

		case 1
			Player_stageRotation--
			if Player_stageRotation < 0
				Player_stageRotation += 512
			end if
			break
		end switch
	else
		switch Player_rotateSpeed
		case 0
			temp0 = oscillation
			temp0 &= 1
			Player_stageRotation += temp0
			Player_stageRotation &= 511
			break

		case 1
			Player_stageRotation++
			Player_stageRotation &= 511
			break
		end switch
	end if

	oscillation++
	oscillation &= 511
	SpecialSetup_gemBlockTimer++
	SpecialSetup_gemBlockTimer %= 20
	SpecialSetup_blockTimer++
	SpecialSetup_blockTimer &= 63
	
	// These aren't exactly the type of states that are in-depth and deserving of proper names so I hope you enjoy numbers
	switch object.state
	case 0
		object.timer++
		if object.timer == 8
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0xA0
			object.bgClr.b = 0xA0
			object.bgClr.a = 0xFF
			temp1 = 184
			temp2 = 264
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 1
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x60
			object.bgClr.b = 0x80
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 2
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x40
			object.bgClr.b = 0x60
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 3
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x00
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 4
		object.timer++
		if object.timer == 4
			object.timer = 0
			stage.activeLayer[0] = 1
			object.bgClr.r = 0x00
			object.bgClr.g = 0x00
			object.bgClr.b = 0x40
			object.bgClr.a = 0xE0
			temp1 = 104
			temp2 = 136
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 5
		if object.bgClr.a > 0x00
			object.bgClr.a -= 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0
			temp1 = 104
			temp2 = 152
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 6
		if object.bgClr.a > 0x00
			object.bgClr.a -= 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0
			stage.activeLayer[1] = 4
			hParallax[0].scrollSpeed = -0x10000
			object.state++
		end if
		break

	case 7
		object.timer++
		if object.timer == 1020
			object.timer = 0
			stage.activeLayer[1] = 3
			hParallax[0].scrollSpeed = 0
			object.state++
		end if
		break

	case 8
		if object.bgClr.a < 0x00
			object.bgClr.a += 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0

			temp1 = 104
			temp2 = 136
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 9
		if object.bgClr.a < 0x00
			object.bgClr.a += 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x00
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			temp1 = 104
			temp2 = 120
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 10
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x40
			object.bgClr.b = 0x60
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 11
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x60
			object.bgClr.b = 0x80
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 12
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0xA0
			object.bgClr.b = 0xA0
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 13
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.a = 0x00

			temp1 = 184
			temp2 = 200
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 14
		object.timer++
		if object.timer == 8
			object.timer = 0
			object.bgClr.r = 0x60
			object.bgClr.g = 0xC0
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			temp1 = 104
			temp2 = 264
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 15
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x40
			object.bgClr.g = 0x80
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 16
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x20
			object.bgClr.g = 0x40
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 17
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x00
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 18
		object.timer++
		if object.timer == 4
			object.timer = 0
			stage.activeLayer[0] = 2
			object.bgClr.r = 0x00
			object.bgClr.g = 0x00
			object.bgClr.b = 0x40
			object.bgClr.a = 0xE0

			temp1 = 184
			temp2 = 216
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 19
		CallFunction(SpecialSetup_ProcessHScroll)
		if object.bgClr.a > 0x00
			object.bgClr.a -= 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0

			temp1 = 184
			temp2 = 232
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 20
		CallFunction(SpecialSetup_ProcessHScroll)
		if object.bgClr.a > 0x00
			object.bgClr.a -= 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0
			stage.activeLayer[1] = 5
			hParallax[0].scrollSpeed = 0x10000
			object.state++
		end if
		break

	case 21
		CallFunction(SpecialSetup_ProcessHScroll)
		object.timer++
		if object.timer == 1020
			object.timer = 0
			stage.activeLayer[1] = 3
			hParallax[0].scrollSpeed = 0
			object.state++
		end if
		break

	case 22
		CallFunction(SpecialSetup_ProcessHScroll)
		if object.bgClr.a < 0x00
			object.bgClr.a += 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0

			temp1 = 184
			temp2 = 216
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 23
		CallFunction(SpecialSetup_ProcessHScroll)
		if object.bgClr.a < 0x00
			object.bgClr.a += 0x10
		end if

		object.timer++
		if object.timer == 8
			object.timer = 0
			object.bgClr.r = 0x00
			object.bgClr.g = 0x00
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF

			temp1 = 184
			temp2 = 200
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state++
		end if
		break

	case 24
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x20
			object.bgClr.g = 0x40
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 25
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x40
			object.bgClr.g = 0x80
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 26
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.r = 0x60
			object.bgClr.g = 0xC0
			object.bgClr.b = 0x40
			object.bgClr.a = 0xFF
			object.state++
		end if
		break

	case 27
		object.timer++
		if object.timer == 4
			object.timer = 0
			object.bgClr.a = 0x00
			temp1 = 104
			temp2 = 120
			CallFunction(SpecialSetup_CopyAniTiles)
			object.state = 0
		end if
		break
		
	end switch

	ringTimer++
	if ringTimer == 4
		ringTimer = 0
		ringFrame++
		ringFrame &= 7
	end if
	
#platform: USE_ORIGINS
	if game.coinMode != false
		game.hudEnable = HUDENABLE_ON // There's no HUD in the Special Stage, even with this enabled. What's the point of this?
	end if
#endplatform
end event


event ObjectDraw
	screen.xoffset = player[0].xpos
	screen.xoffset >>= 16
	screen.xoffset -= screen.xcenter

	screen.yoffset = player[0].ypos
	screen.yoffset >>= 16
	screen.yoffset -= 104

	DrawRect(0, 0, screen.xsize, screen.ysize, object.bgClr.r, object.bgClr.g, object.bgClr.b, object.bgClr.a)
end event


event ObjectStartup
	SetMusicTrack("Specialstage.ogg", TRACK_STAGE, true)
	SetMusicTrack("ActComplete.ogg", TRACK_ACTFINISH, false)

	if options.gameMode == MODE_TIMEATTACK
		object[SLOT_HUD].type = TypeName[HUD]
		object[SLOT_HUD].priority = PRIORITY_ACTIVE
		object[SLOT_HUD].drawOrder = 6
		
		// Wait huh, arrayPos0? Where'd that come from?
		// This code might've just been copied from the standard Stage Setup code, where the HUD is set up within a foreach
		object[SLOT_HUD].propertyValue = object[arrayPos0].propertyValue
		
#platform: USE_STANDALONE
		stage.timeEnabled = true
#endplatform
	end if

#platform: USE_ORIGINS
	stage.timeEnabled = true
#endplatform

	object[19].type = TypeName[Special Setup]
	object[19].priority = PRIORITY_ACTIVE
	object[19].drawOrder = 1
	
	object[20].type = TypeName[Fade In]
	object[20].priority = PRIORITY_ACTIVE

	stage.activeLayer[0] = 9
	stage.activeLayer[1] = 3
	stage.activeLayer[2] = 9
	stage.activeLayer[3] = 9
	
	if options.attractMode == false
#platform: USE_ORIGINS
		// This is likely "platform: STANDARD" instead, given how this condition was also in 2013, but technically we can't 100% confirm that...
		stage.pauseEnabled = true
#endplatform
	else
		stage.pauseEnabled = false
		options.touchControls = false
	end if

	ringExtraLife = 100
	SpecialSetup_gemBlockTimer 	= 0
	SpecialSetup_gemBlockBusy 	= false
	SpecialSetup_blockTimer 	= 0
	Player_rotateSpeed 	= 0
	Player_rotateDir 	= 0

	if options.attractMode == true
		Player_attractTable = SpecialSetup_replay_attract_STK
		Player_attractTableSize = 94
		Player_attractDuration = 1200
		CallFunction(Player_SetupAttractDemo)
	end if
end event


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

event RSDKDraw
	DrawSprite(0)
end event


event RSDKLoad
	LoadSpriteSheet("Global/Display.gif")
	SpriteFrame(-16, -16, 32, 32, 1, 143)
	
	SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
end event
